diff options
Diffstat (limited to 'firmware/target/hosted/samsungypr/radio-ypr.c')
-rw-r--r-- | firmware/target/hosted/samsungypr/radio-ypr.c | 106 |
1 files changed, 83 insertions, 23 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) { |