summaryrefslogtreecommitdiff
path: root/firmware/target/hosted/samsungypr/radio-ypr.c
diff options
context:
space:
mode:
Diffstat (limited to 'firmware/target/hosted/samsungypr/radio-ypr.c')
-rw-r--r--firmware/target/hosted/samsungypr/radio-ypr.c106
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 */
35static int radio_dev = -1; 46static int radio_dev = -1;
36 47
37void radiodev_open(void) { 48/* toggle radio RST pin */
38 radio_dev = open("/dev/si470x", O_RDWR); 49static 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
41void radiodev_close(void) { 58void 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 */
46void 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
51uint16_t si4709_read_reg(int addr) { 97void 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 */
58int fmradio_i2c_write(unsigned char address, unsigned char* buf, int count) 117int 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 */
65int fmradio_i2c_read(unsigned char address, unsigned char* buf, int count) 124int 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) {