diff options
-rw-r--r-- | firmware/target/hosted/samsungypr/radio-ypr.c | 106 | ||||
-rw-r--r-- | firmware/target/hosted/samsungypr/radio-ypr.h | 3 | ||||
-rw-r--r-- | firmware/target/hosted/samsungypr/si4709.h | 82 | ||||
-rw-r--r-- | firmware/target/hosted/samsungypr/ypr0/i2c-target.h | 30 | ||||
-rw-r--r-- | firmware/target/hosted/samsungypr/ypr1/i2c-target.h | 30 |
5 files changed, 144 insertions, 107 deletions
diff --git a/firmware/target/hosted/samsungypr/radio-ypr.c b/firmware/target/hosted/samsungypr/radio-ypr.c index 4fccf2616f..42d485231d 100644 --- a/firmware/target/hosted/samsungypr/radio-ypr.c +++ b/firmware/target/hosted/samsungypr/radio-ypr.c | |||
@@ -21,58 +21,116 @@ | |||
21 | * | 21 | * |
22 | ****************************************************************************/ | 22 | ****************************************************************************/ |
23 | 23 | ||
24 | /* system includes */ | ||
24 | #include <unistd.h> | 25 | #include <unistd.h> |
25 | #include <fcntl.h> | 26 | #include <fcntl.h> |
26 | #include <sys/ioctl.h> | 27 | #include <sys/ioctl.h> |
28 | #include <linux/i2c-dev.h> | ||
27 | #include "stdint.h" | 29 | #include "stdint.h" |
28 | #include "string.h" | 30 | #include "string.h" |
29 | #include "kernel.h" | ||
30 | 31 | ||
32 | /* application includes */ | ||
33 | #include "kernel.h" | ||
31 | #include "radio-ypr.h" | 34 | #include "radio-ypr.h" |
32 | #include "si4700.h" | ||
33 | #include "power.h" | 35 | #include "power.h" |
36 | #include "gpio-target.h" | ||
37 | #include "gpio-ypr.h" | ||
38 | #include "panic.h" | ||
39 | #include "i2c-target.h" | ||
40 | |||
41 | /* 7bits I2C address for Si4709 | ||
42 | * (apparently not selectable by pins or revisions) */ | ||
43 | #define SI4709_I2C_SLAVE_ADDR 0x10 | ||
34 | 44 | ||
45 | /** i2c file handle */ | ||
35 | static int radio_dev = -1; | 46 | static int radio_dev = -1; |
36 | 47 | ||
37 | void radiodev_open(void) { | 48 | /* toggle radio RST pin */ |
38 | radio_dev = open("/dev/si470x", O_RDWR); | 49 | static void power_toggle(bool set) |
50 | { | ||
51 | /* setup the GPIO port, as in OF */ | ||
52 | gpio_set_iomux(GPIO_FM_BUS_EN, CONFIG_ALT3); | ||
53 | gpio_set_pad(GPIO_FM_BUS_EN, PAD_CTL_SRE_FAST | PAD_CTL_DRV_HIGH); | ||
54 | gpio_direction_output(GPIO_FM_BUS_EN); | ||
55 | gpio_set(GPIO_FM_BUS_EN, set); | ||
39 | } | 56 | } |
40 | 57 | ||
41 | void radiodev_close(void) { | 58 | void radiodev_open(void) |
42 | close(radio_dev); | 59 | { |
43 | } | 60 | int retval = -1; /* ioctl return value */ |
61 | |||
62 | /* open the I2C bus where the chip is attached to */ | ||
63 | radio_dev = open(I2C_BUS_FM_RADIO, O_RDWR); | ||
64 | |||
65 | if (radio_dev == -1) | ||
66 | { | ||
67 | panicf("%s: failed to open /dev/i2c-1 device - %d", __FUNCTION__, retval); | ||
68 | } | ||
69 | else | ||
70 | { | ||
71 | /* device is open, go on */ | ||
72 | |||
73 | /* set the slave address for the handle. | ||
74 | * Some other modules might have set the same slave address | ||
75 | * e.g. another module. Let's do a I2C_SLAVE_FORCE which does | ||
76 | * not care about looking for other init'ed i2c slaves */ | ||
77 | retval = ioctl(radio_dev, I2C_SLAVE_FORCE, SI4709_I2C_SLAVE_ADDR); | ||
78 | |||
79 | if (retval == -1) | ||
80 | { | ||
81 | /* the ioctl call should never fail, if radio_dev is valid */ | ||
82 | panicf("%s: failed to set slave address - %d", __FUNCTION__, retval); | ||
83 | } | ||
84 | else | ||
85 | { | ||
86 | /* initialization completed */ | ||
87 | } | ||
88 | } | ||
89 | |||
90 | /* i2c subsystem ready, now toggle power to the chip */ | ||
91 | power_toggle(true); | ||
92 | /* 100ms reset delay */ | ||
93 | sleep(HZ/10); | ||
44 | 94 | ||
45 | /* High-level registers access */ | ||
46 | void si4709_write_reg(int addr, uint16_t value) { | ||
47 | sSi4709_t r = { .addr = addr, .value = value }; | ||
48 | ioctl(radio_dev, IOCTL_SI4709_WRITE_BYTE, &r); | ||
49 | } | 95 | } |
50 | 96 | ||
51 | uint16_t si4709_read_reg(int addr) { | 97 | void radiodev_close(void) |
52 | sSi4709_t r = { .addr = addr, .value = 0 }; | 98 | { |
53 | ioctl(radio_dev, IOCTL_SI4709_READ_BYTE, &r); | 99 | /* power the chip down */ |
54 | return r.value; | 100 | power_toggle(false); |
101 | |||
102 | /* close the i2c subsystem */ | ||
103 | if (radio_dev != -1) | ||
104 | { | ||
105 | (void)close(radio_dev); | ||
106 | } | ||
107 | else | ||
108 | { | ||
109 | /* not opened */ | ||
110 | } | ||
111 | |||
112 | /* set back to safe error value */ | ||
113 | radio_dev = -1; | ||
55 | } | 114 | } |
56 | 115 | ||
57 | /* Low-level i2c channel access */ | 116 | /* Low-level i2c channel access: write */ |
58 | int fmradio_i2c_write(unsigned char address, unsigned char* buf, int count) | 117 | int fmradio_i2c_write(unsigned char address, unsigned char* buf, int count) |
59 | { | 118 | { |
60 | (void)address; | 119 | (void)address; |
61 | sSi4709_i2c_t r = { .size = count, .buf = buf }; | 120 | return write(radio_dev, buf, count); |
62 | return ioctl(radio_dev, IOCTL_SI4709_I2C_WRITE, &r); | ||
63 | } | 121 | } |
64 | 122 | ||
123 | /* Low-level i2c channel access: read */ | ||
65 | int fmradio_i2c_read(unsigned char address, unsigned char* buf, int count) | 124 | int fmradio_i2c_read(unsigned char address, unsigned char* buf, int count) |
66 | { | 125 | { |
67 | (void)address; | 126 | (void)address; |
68 | sSi4709_i2c_t r = { .size = count, .buf = buf }; | 127 | return read(radio_dev, buf, count); |
69 | return ioctl(radio_dev, IOCTL_SI4709_I2C_READ, &r); | ||
70 | } | 128 | } |
71 | 129 | ||
72 | #ifdef HAVE_RDS_CAP | 130 | #ifdef HAVE_RDS_CAP |
73 | 131 | ||
74 | /* Register we are going to poll */ | 132 | /* Register we are going to poll */ |
75 | #define STATUSRSSI 0xA | 133 | #define STATUSRSSI (0xA) |
76 | #define STATUSRSSI_RDSR (0x1 << 15) | 134 | #define STATUSRSSI_RDSR (0x1 << 15) |
77 | 135 | ||
78 | /* Low-level RDS Support */ | 136 | /* Low-level RDS Support */ |
@@ -89,6 +147,7 @@ static void NORETURN_ATTR rds_thread(void) | |||
89 | int timeout = TIMEOUT_BLOCK; | 147 | int timeout = TIMEOUT_BLOCK; |
90 | struct queue_event ev; | 148 | struct queue_event ev; |
91 | bool rds_rdy = false; | 149 | bool rds_rdy = false; |
150 | struct si4700_dbg_info radio_regs; | ||
92 | 151 | ||
93 | while (true) { | 152 | while (true) { |
94 | queue_wait_w_tmo(&rds_queue, &ev, timeout); | 153 | queue_wait_w_tmo(&rds_queue, &ev, timeout); |
@@ -97,9 +156,10 @@ static void NORETURN_ATTR rds_thread(void) | |||
97 | /* power up: timeout after 1 tick, else block indefinitely */ | 156 | /* power up: timeout after 1 tick, else block indefinitely */ |
98 | timeout = ev.data ? 1 : TIMEOUT_BLOCK; | 157 | timeout = ev.data ? 1 : TIMEOUT_BLOCK; |
99 | break; | 158 | break; |
100 | case SYS_TIMEOUT:; | 159 | case SYS_TIMEOUT: |
101 | /* Captures RDS data and processes it */ | 160 | /* Captures RDS data and processes it */ |
102 | bool rdsr = si4709_read_reg(STATUSRSSI) & STATUSRSSI_RDSR; | 161 | si4700_dbg_info(&radio_regs); |
162 | bool rdsr = radio_regs.regs[STATUSRSSI] & STATUSRSSI_RDSR; | ||
103 | if (rdsr != rds_rdy) { | 163 | if (rdsr != rds_rdy) { |
104 | rds_rdy = rdsr; | 164 | rds_rdy = rdsr; |
105 | if (rdsr) { | 165 | if (rdsr) { |
diff --git a/firmware/target/hosted/samsungypr/radio-ypr.h b/firmware/target/hosted/samsungypr/radio-ypr.h index 13bcb6dc72..15aeb526ef 100644 --- a/firmware/target/hosted/samsungypr/radio-ypr.h +++ b/firmware/target/hosted/samsungypr/radio-ypr.h | |||
@@ -23,7 +23,6 @@ | |||
23 | #ifndef __RADIO_YPR0_H__ | 23 | #ifndef __RADIO_YPR0_H__ |
24 | #define __RADIO_YPR0_H__ | 24 | #define __RADIO_YPR0_H__ |
25 | 25 | ||
26 | #include "si4709.h" | ||
27 | #include "stdint.h" | 26 | #include "stdint.h" |
28 | #include "rds.h" | 27 | #include "rds.h" |
29 | #include "si4700.h" | 28 | #include "si4700.h" |
@@ -33,4 +32,4 @@ void radiodev_close(void); | |||
33 | void si4709_write_reg(int addr, uint16_t value); | 32 | void si4709_write_reg(int addr, uint16_t value); |
34 | uint16_t si4709_read_reg(int addr); | 33 | uint16_t si4709_read_reg(int addr); |
35 | 34 | ||
36 | #endif /*__RADIO-YPR0_H__*/ \ No newline at end of file | 35 | #endif /*__RADIO-YPR0_H__*/ |
diff --git a/firmware/target/hosted/samsungypr/si4709.h b/firmware/target/hosted/samsungypr/si4709.h deleted file mode 100644 index c27472e856..0000000000 --- a/firmware/target/hosted/samsungypr/si4709.h +++ /dev/null | |||
@@ -1,82 +0,0 @@ | |||
1 | /*************************************************************************** | ||
2 | * __________ __ ___. | ||
3 | * Open \______ \ ____ ____ | | _\_ |__ _______ ___ | ||
4 | * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ / | ||
5 | * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < < | ||
6 | * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \ | ||
7 | * \/ \/ \/ \/ \/ | ||
8 | * | ||
9 | * Module header for SI4709 FM Radio Chip, using /dev/si470x (si4709.ko) of Samsung YP-R0 | ||
10 | * | ||
11 | * Copyright (c) 2012 Lorenzo Miori | ||
12 | * | ||
13 | * This program is free software; you can redistribute it and/or | ||
14 | * modify it under the terms of the GNU General Public License | ||
15 | * as published by the Free Software Foundation; either version 2 | ||
16 | * of the License, or (at your option) any later version. | ||
17 | * | ||
18 | * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY | ||
19 | * KIND, either express or implied. | ||
20 | * | ||
21 | ****************************************************************************/ | ||
22 | |||
23 | #ifndef __SI4709_H__ | ||
24 | #define __SI4709_H__ | ||
25 | |||
26 | #include "stdint.h" | ||
27 | |||
28 | /* 7bits I2C address */ | ||
29 | #define SI4709_I2C_SLAVE_ADDR 0x10 | ||
30 | |||
31 | #define SI4702_DEVICEID 0x00 | ||
32 | #define SI4702_CHIPID 0x01 | ||
33 | #define SI4702_POWERCFG 0x02 | ||
34 | #define SI4702_CHANNEL 0x03 | ||
35 | #define SI4702_SYSCONFIG1 0x04 | ||
36 | #define SI4702_SYSCONFIG2 0x05 | ||
37 | #define SI4702_SYSCONFIG3 0x06 | ||
38 | #define SI4702_TEST1 0x07 | ||
39 | #define SI4702_TEST2 0x08 | ||
40 | #define SI4702_B00TCONFIG 0x09 | ||
41 | #define SI4702_STATUSRSSI 0x0A | ||
42 | #define SI4702_READCHAN 0x0B | ||
43 | #define SI4709_REG_NUM 0x10 | ||
44 | #define SI4702_REG_BYTE (SI4709_REG_NUM * 2) | ||
45 | #define SI4702_DEVICE_ID 0x1242 | ||
46 | #define SI4702_RW_REG_NUM (SI4702_STATUSRSSI - SI4702_POWERCFG) | ||
47 | #define SI4702_RW_OFFSET \ | ||
48 | (SI4709_REG_NUM - SI4702_STATUSRSSI + SI4702_POWERCFG) | ||
49 | #define BYTE_TO_WORD(hi, lo) (((hi) << 8) & 0xFF00) | ((lo) & 0x00FF) | ||
50 | |||
51 | typedef struct { | ||
52 | int addr; | ||
53 | uint16_t value; | ||
54 | }__attribute__((packed)) sSi4709_t; | ||
55 | |||
56 | typedef struct { | ||
57 | int size; | ||
58 | unsigned char *buf; | ||
59 | }__attribute__((packed)) sSi4709_i2c_t; | ||
60 | |||
61 | typedef enum | ||
62 | { | ||
63 | IOCTL_SI4709_INIT = 0, | ||
64 | IOCTL_SI4709_CLOSE, | ||
65 | IOCTL_SI4709_WRITE_BYTE, | ||
66 | IOCTL_SI4709_READ_BYTE, | ||
67 | IOCTL_SI4709_I2C_WRITE, | ||
68 | IOCTL_SI4709_I2C_READ, | ||
69 | |||
70 | E_IOCTL_SI4709_MAX | ||
71 | } eSi4709_ioctl_t; | ||
72 | |||
73 | #define DRV_IOCTL_SI4709_MAGIC 'S' | ||
74 | |||
75 | #define IOCTL_SI4709_INIT _IO(DRV_IOCTL_SI4709_MAGIC, IOCTL_SI4709_INIT) | ||
76 | #define IOCTL_SI4709_CLOSE _IO(DRV_IOCTL_SI4709_MAGIC, IOCTL_SI4709_CLOSE) | ||
77 | #define IOCTL_SI4709_WRITE_BYTE _IOW(DRV_IOCTL_SI4709_MAGIC, IOCTL_SI4709_WRITE_BYTE, sSi4709_t) | ||
78 | #define IOCTL_SI4709_READ_BYTE _IOR(DRV_IOCTL_SI4709_MAGIC, IOCTL_SI4709_READ_BYTE, sSi4709_t) | ||
79 | #define IOCTL_SI4709_I2C_WRITE _IOW(DRV_IOCTL_SI4709_MAGIC, IOCTL_SI4709_I2C_WRITE, sSi4709_i2c_t) | ||
80 | #define IOCTL_SI4709_I2C_READ _IOR(DRV_IOCTL_SI4709_MAGIC, IOCTL_SI4709_I2C_READ, sSi4709_i2c_t) | ||
81 | |||
82 | #endif /* __SI4709_H__ */ \ No newline at end of file | ||
diff --git a/firmware/target/hosted/samsungypr/ypr0/i2c-target.h b/firmware/target/hosted/samsungypr/ypr0/i2c-target.h new file mode 100644 index 0000000000..351988844e --- /dev/null +++ b/firmware/target/hosted/samsungypr/ypr0/i2c-target.h | |||
@@ -0,0 +1,30 @@ | |||
1 | /*************************************************************************** | ||
2 | * __________ __ ___. | ||
3 | * Open \______ \ ____ ____ | | _\_ |__ _______ ___ | ||
4 | * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ / | ||
5 | * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < < | ||
6 | * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \ | ||
7 | * \/ \/ \/ \/ \/ | ||
8 | * | ||
9 | * Module wrapper for SI4709 FM Radio Chip, using /dev/si470x (si4709.ko) | ||
10 | * Samsung YP-R0 & Samsung YP-R1 | ||
11 | * | ||
12 | * Copyright (c) 2017 Lorenzo Miori | ||
13 | * | ||
14 | * This program is free software; you can redistribute it and/or | ||
15 | * modify it under the terms of the GNU General Public License | ||
16 | * as published by the Free Software Foundation; either version 2 | ||
17 | * of the License, or (at your option) any later version. | ||
18 | * | ||
19 | * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY | ||
20 | * KIND, either express or implied. | ||
21 | * | ||
22 | ****************************************************************************/ | ||
23 | |||
24 | #ifndef I2C_TARGET_H_ | ||
25 | #define I2C_TARGET_H_ | ||
26 | |||
27 | /** Define the FM Radio Chip I2C bus */ | ||
28 | #define I2C_BUS_FM_RADIO ("/dev/i2c-0") | ||
29 | |||
30 | #endif /* I2C_TARGET_H_ */ | ||
diff --git a/firmware/target/hosted/samsungypr/ypr1/i2c-target.h b/firmware/target/hosted/samsungypr/ypr1/i2c-target.h new file mode 100644 index 0000000000..f1fed01cc7 --- /dev/null +++ b/firmware/target/hosted/samsungypr/ypr1/i2c-target.h | |||
@@ -0,0 +1,30 @@ | |||
1 | /*************************************************************************** | ||
2 | * __________ __ ___. | ||
3 | * Open \______ \ ____ ____ | | _\_ |__ _______ ___ | ||
4 | * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ / | ||
5 | * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < < | ||
6 | * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \ | ||
7 | * \/ \/ \/ \/ \/ | ||
8 | * | ||
9 | * Module wrapper for SI4709 FM Radio Chip, using /dev/si470x (si4709.ko) | ||
10 | * Samsung YP-R0 & Samsung YP-R1 | ||
11 | * | ||
12 | * Copyright (c) 2017 Lorenzo Miori | ||
13 | * | ||
14 | * This program is free software; you can redistribute it and/or | ||
15 | * modify it under the terms of the GNU General Public License | ||
16 | * as published by the Free Software Foundation; either version 2 | ||
17 | * of the License, or (at your option) any later version. | ||
18 | * | ||
19 | * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY | ||
20 | * KIND, either express or implied. | ||
21 | * | ||
22 | ****************************************************************************/ | ||
23 | |||
24 | #ifndef I2C_TARGET_H_ | ||
25 | #define I2C_TARGET_H_ | ||
26 | |||
27 | /** Define the FM Radio Chip I2C bus */ | ||
28 | #define I2C_BUS_FM_RADIO ("/dev/i2c-1") | ||
29 | |||
30 | #endif /* I2C_TARGET_H_ */ | ||