diff options
author | Michael Sevakis <jethead71@rockbox.org> | 2008-12-27 19:18:50 +0000 |
---|---|---|
committer | Michael Sevakis <jethead71@rockbox.org> | 2008-12-27 19:18:50 +0000 |
commit | 1fea6f6b22af74e904d918fff4cebec345529f4b (patch) | |
tree | 1cdddb0ab125099b7439fd80984517d4a1880341 | |
parent | d6bae6c858413544ff0671910654f709d195e427 (diff) | |
download | rockbox-1fea6f6b22af74e904d918fff4cebec345529f4b.tar.gz rockbox-1fea6f6b22af74e904d918fff4cebec345529f4b.zip |
Make si4700 tuner driver more sane with bit and field defines and entirely hide strange i2c interface from code with write/set/clear/masked functionality. On Gigabeat S use by-the-book busmode selection and GPIO lines. Implement some primitive station detection, debug registers in screen, and misc. changes to tie things together.
git-svn-id: svn://svn.rockbox.org/rockbox/trunk@19600 a1c6a512-1295-4272-9138-f99709370657
-rw-r--r-- | apps/debug_menu.c | 28 | ||||
-rw-r--r-- | firmware/drivers/tuner/si4700.c | 418 | ||||
-rwxr-xr-x | firmware/export/imx31l.h | 100 | ||||
-rw-r--r-- | firmware/export/power.h | 1 | ||||
-rw-r--r-- | firmware/export/si4700.h | 6 | ||||
-rw-r--r-- | firmware/target/arm/as3525/power-as3525.c | 16 | ||||
-rw-r--r-- | firmware/target/arm/imx31/gigabeat-s/fmradio-i2c-gigabeat-s.c | 75 | ||||
-rw-r--r-- | firmware/target/arm/imx31/gigabeat-s/power-imx31.c | 43 | ||||
-rw-r--r-- | firmware/tuner.c | 2 |
9 files changed, 513 insertions, 176 deletions
diff --git a/apps/debug_menu.c b/apps/debug_menu.c index f390cced85..9be36df046 100644 --- a/apps/debug_menu.c +++ b/apps/debug_menu.c | |||
@@ -2293,12 +2293,12 @@ static int radio_callback(int btn, struct gui_synclist *lists) | |||
2293 | "if_set: %d Hz", lv24020lp_get(LV24020LP_IF_SET) ); | 2293 | "if_set: %d Hz", lv24020lp_get(LV24020LP_IF_SET) ); |
2294 | simplelist_addline(SIMPLELIST_ADD_LINE, | 2294 | simplelist_addline(SIMPLELIST_ADD_LINE, |
2295 | "sd_set: %d Hz", lv24020lp_get(LV24020LP_SD_SET) ); | 2295 | "sd_set: %d Hz", lv24020lp_get(LV24020LP_SD_SET) ); |
2296 | #endif | 2296 | #endif /* LV24020LP */ |
2297 | #if (CONFIG_TUNER & S1A0903X01) | 2297 | #if (CONFIG_TUNER & S1A0903X01) |
2298 | simplelist_addline(SIMPLELIST_ADD_LINE, | 2298 | simplelist_addline(SIMPLELIST_ADD_LINE, |
2299 | "Samsung regs: %08X", s1a0903x01_get(RADIO_ALL)); | 2299 | "Samsung regs: %08X", s1a0903x01_get(RADIO_ALL)); |
2300 | /* This one doesn't return dynamic data atm */ | 2300 | /* This one doesn't return dynamic data atm */ |
2301 | #endif | 2301 | #endif /* S1A0903X01 */ |
2302 | #if (CONFIG_TUNER & TEA5767) | 2302 | #if (CONFIG_TUNER & TEA5767) |
2303 | struct tea5767_dbg_info nfo; | 2303 | struct tea5767_dbg_info nfo; |
2304 | tea5767_dbg_info(&nfo); | 2304 | tea5767_dbg_info(&nfo); |
@@ -2313,7 +2313,29 @@ static int radio_callback(int btn, struct gui_synclist *lists) | |||
2313 | (unsigned)nfo.write_regs[0], (unsigned)nfo.write_regs[1], | 2313 | (unsigned)nfo.write_regs[0], (unsigned)nfo.write_regs[1], |
2314 | (unsigned)nfo.write_regs[2], (unsigned)nfo.write_regs[3], | 2314 | (unsigned)nfo.write_regs[2], (unsigned)nfo.write_regs[3], |
2315 | (unsigned)nfo.write_regs[4]); | 2315 | (unsigned)nfo.write_regs[4]); |
2316 | #endif | 2316 | #endif /* TEA5767 */ |
2317 | #if (CONFIG_TUNER & SI4700) | ||
2318 | struct si4700_dbg_info nfo; | ||
2319 | si4700_dbg_info(&nfo); | ||
2320 | simplelist_addline(SIMPLELIST_ADD_LINE, "SI4700 regs:"); | ||
2321 | /* Registers */ | ||
2322 | simplelist_addline(SIMPLELIST_ADD_LINE, | ||
2323 | " %04X %04X %04X %04X", | ||
2324 | (unsigned)nfo.regs[0], (unsigned)nfo.regs[1], | ||
2325 | (unsigned)nfo.regs[2], (unsigned)nfo.regs[3]); | ||
2326 | simplelist_addline(SIMPLELIST_ADD_LINE, | ||
2327 | " %04X %04X %04X %04X", | ||
2328 | (unsigned)nfo.regs[4], (unsigned)nfo.regs[5], | ||
2329 | (unsigned)nfo.regs[6], (unsigned)nfo.regs[7]); | ||
2330 | simplelist_addline(SIMPLELIST_ADD_LINE, | ||
2331 | " %04X %04X %04X %04X", | ||
2332 | (unsigned)nfo.regs[8], (unsigned)nfo.regs[9], | ||
2333 | (unsigned)nfo.regs[10], (unsigned)nfo.regs[11]); | ||
2334 | simplelist_addline(SIMPLELIST_ADD_LINE, | ||
2335 | " %04X %04X %04X %04X", | ||
2336 | (unsigned)nfo.regs[12], (unsigned)nfo.regs[13], | ||
2337 | (unsigned)nfo.regs[14], (unsigned)nfo.regs[15]); | ||
2338 | #endif /* SI4700 */ | ||
2317 | return ACTION_REDRAW; | 2339 | return ACTION_REDRAW; |
2318 | } | 2340 | } |
2319 | static bool dbg_fm_radio(void) | 2341 | static bool dbg_fm_radio(void) |
diff --git a/firmware/drivers/tuner/si4700.c b/firmware/drivers/tuner/si4700.c index f68ea5a750..fb8fc49749 100644 --- a/firmware/drivers/tuner/si4700.c +++ b/firmware/drivers/tuner/si4700.c | |||
@@ -25,12 +25,33 @@ | |||
25 | #include <string.h> | 25 | #include <string.h> |
26 | #include <stdlib.h> | 26 | #include <stdlib.h> |
27 | #include "kernel.h" | 27 | #include "kernel.h" |
28 | #include "power.h" | ||
28 | #include "tuner.h" /* tuner abstraction interface */ | 29 | #include "tuner.h" /* tuner abstraction interface */ |
29 | #include "fmradio.h" | 30 | #include "fmradio.h" |
30 | #include "fmradio_i2c.h" /* physical interface driver */ | 31 | #include "fmradio_i2c.h" /* physical interface driver */ |
31 | 32 | ||
33 | /* some models use the internal 32 kHz oscillator which needs special attention | ||
34 | during initialisation, power-up and power-down. | ||
35 | */ | ||
36 | #if defined(SANSA_CLIP) || defined(SANSA_E200V2) || defined(SANSA_FUZE) | ||
37 | #define USE_INTERNAL_OSCILLATOR | ||
38 | #elif defined(TOSHIBA_GIGABEAT_S) | ||
39 | #define SI4700_GPIO_SETUP (SYSCONFIG1_GPIO1_HI_Z | \ | ||
40 | SYSCONFIG1_GPIO2_HI_Z | \ | ||
41 | SYSCONFIG1_GPIO3_MO_ST_I) | ||
42 | extern int si4700_st(void); | ||
43 | #endif | ||
44 | |||
45 | #ifndef SI4700_GPIO_SETUP | ||
46 | #define SI4700_GPIO_SETUP 0 | ||
47 | #endif | ||
48 | |||
49 | #define SEEK_THRESHOLD 0x16 | ||
50 | #define TUNER_VOLUME 0xC | ||
51 | |||
32 | #define I2C_ADR 0x20 | 52 | #define I2C_ADR 0x20 |
33 | 53 | ||
54 | /** Registers and bits - "x" denotes Si4702/03 only (so they say) **/ | ||
34 | #define DEVICEID 0x0 | 55 | #define DEVICEID 0x0 |
35 | #define CHIPID 0x1 | 56 | #define CHIPID 0x1 |
36 | #define POWERCFG 0x2 | 57 | #define POWERCFG 0x2 |
@@ -43,20 +64,154 @@ | |||
43 | #define BOOTCONFIG 0x9 | 64 | #define BOOTCONFIG 0x9 |
44 | #define STATUSRSSI 0xA | 65 | #define STATUSRSSI 0xA |
45 | #define READCHAN 0xB | 66 | #define READCHAN 0xB |
46 | #define RDSA 0xC | 67 | #define RDSA 0xC /* x */ |
47 | #define RDSB 0xD | 68 | #define RDSB 0xD /* x */ |
48 | #define RDSC 0xE | 69 | #define RDSC 0xE /* x */ |
49 | #define RDSD 0xF | 70 | #define RDSD 0xF /* x */ |
50 | 71 | ||
51 | /* some models use the internal 32 kHz oscillator which needs special attention | 72 | /* DEVICEID (0x0) */ |
52 | during initialisation, power-up and power-down. | 73 | #define DEVICEID_PN (0xf << 12) |
53 | */ | 74 | /* 0x01 = Si4700/01 */ |
54 | #if defined(SANSA_CLIP) || defined(SANSA_E200V2) || defined(SANSA_FUZE) | 75 | /* 0x01 = Si4702/03 */ |
55 | #define USE_INTERNAL_OSCILLATOR | 76 | #define DEVICEID_MFGID (0xfff << 0) |
56 | #endif | 77 | /* always 0x242 */ |
78 | |||
79 | /* CHIPID (0x1) */ | ||
80 | |||
81 | #if 0 /* Informational */ | ||
82 | /* Si4700/01 */ | ||
83 | #define CHIPID_REV (0x3f << 10) | ||
84 | #define CHIPID_DEV (0x1 << 9) | ||
85 | /* 0 before powerup */ | ||
86 | /* 0 after powerup = Si4700 */ | ||
87 | /* 1 after powerup = Si4701 */ | ||
88 | #define CHIPID_FIRMWARE (0xff << 0) | ||
89 | |||
90 | /* Si4702/03 */ | ||
91 | #define CHIPID_REV (0x3f << 10) | ||
92 | #define CHIPID_DEV (0xf << 6) | ||
93 | /* 0000 before PU = Si4702 */ | ||
94 | /* 0001 after PU = Si4702 */ | ||
95 | /* 1000 before PU = Si4703 */ | ||
96 | /* 1001 after PU = Si4703 */ | ||
97 | #define CHIPID_FIRMWARE (0x3f << 0) | ||
98 | #endif /* 0 */ | ||
99 | |||
100 | /* POWERCFG (0x2) */ | ||
101 | #define POWERCFG_DSMUTE (0x1 << 15) | ||
102 | #define POWERCFG_DMUTE (0x1 << 14) | ||
103 | #define POWERCFG_MONO (0x1 << 13) | ||
104 | #define POWERCFG_RDSM (0x1 << 11) /* x */ | ||
105 | #define POWERCFG_SKMODE (0x1 << 10) | ||
106 | #define POWERCFG_SEEKUP (0x1 << 9) | ||
107 | #define POWERCFG_SEEK (0x1 << 8) | ||
108 | #define POWERCFG_DISABLE (0x1 << 6) | ||
109 | #define POWERCFG_ENABLE (0x1 << 0) | ||
110 | |||
111 | /* CHANNEL (0x3) */ | ||
112 | #define CHANNEL_TUNE (0x1 << 15) | ||
113 | #define CHANNEL_CHAN (0x3ff << 0) | ||
114 | #define CHANNEL_CHANw(x) ((x) & CHANNEL_CHAN) | ||
115 | |||
116 | /* SYSCONFIG1 (0x4) */ | ||
117 | #define SYSCONFIG1_RDSIEN (0x1 << 15) /* x */ | ||
118 | #define SYSCONFIG1_STCIEN (0x1 << 14) | ||
119 | #define SYSCONFIG1_RDS (0x1 << 12) /* x */ | ||
120 | #define SYSCONFIG1_DE (0x1 << 11) | ||
121 | #define SYSCONFIG1_AGCD (0x1 << 10) | ||
122 | #define SYSCONFIG1_BLNDADJ (0x3 << 6) | ||
123 | #define SYSCONFIG1_BLNDADJ_31_39_RSSI (0x0 << 6) | ||
124 | #define SYSCONFIG1_BLNDADJ_37_55_RSSI (0x1 << 6) | ||
125 | #define SYSCONFIG1_BLNDADJ_19_37_RSSI (0x2 << 6) | ||
126 | #define SYSCONFIG1_BLNDADJ_25_43_RSSI (0x3 << 6) | ||
127 | #define SYSCONFIG1_GPIO3 (0x3 << 4) | ||
128 | #define SYSCONFIG1_GPIO3_HI_Z (0x0 << 4) | ||
129 | #define SYSCONFIG1_GPIO3_MO_ST_I (0x1 << 4) | ||
130 | #define SYSCONFIG1_GPIO3_LOW (0x2 << 4) | ||
131 | #define SYSCONFIG1_GPIO3_HI (0x3 << 4) | ||
132 | #define SYSCONFIG1_GPIO2 (0x3 << 2) | ||
133 | #define SYSCONFIG1_GPIO2_HI_Z (0x0 << 2) | ||
134 | #define SYSCONFIG1_GPIO2_STC_RDS_I (0x1 << 2) | ||
135 | #define SYSCONFIG1_GPIO2_LOW (0x2 << 2) | ||
136 | #define SYSCONFIG1_GPIO2_HI (0x3 << 2) | ||
137 | #define SYSCONFIG1_GPIO1 (0x3 << 0) | ||
138 | #define SYSCONFIG1_GPIO1_HI_Z (0x0 << 0) | ||
139 | #define SYSCONFIG1_GPIO1_LOW (0x2 << 0) | ||
140 | #define SYSCONFIG1_GPIO1_HI (0x3 << 0) | ||
141 | |||
142 | /* SYSCONFIG2 (0x5) */ | ||
143 | #define SYSCONFIG2_SEEKTH (0xff << 8) | ||
144 | #define SYSCONFIG2_SKEETHw(x) (((x) << 8) & SYSCONFIG2_SEEKTH) | ||
145 | #define SYSCONFIG2_BAND (0x3 << 6) | ||
146 | #define SYSCONFIG2_BANDw(x) (((x) << 6) & SYSCONFIG2_BAND) | ||
147 | #define SYSCONFIG2_BANDr(x) (((x) & SYSCONFIG2_BAND) >> 6) | ||
148 | #define SYSCONFIG2_BAND_875_1080 (0x0 << 6) /* tenth-megahertz */ | ||
149 | #define SYSCONFIG2_BAND_760_1080 (0x1 << 6) | ||
150 | #define SYSCONFIG2_BAND_760_900 (0x2 << 6) | ||
151 | #define SYSCONFIG2_SPACE (0x3 << 4) | ||
152 | #define SYSCONFIG2_SPACEw(x) (((x) << 4) & SYSCONFIG2_SPACE) | ||
153 | #define SYSCONFIG2_SPACEr(x) (((x) & SYSCONFIG2_SPACE) >> 4) | ||
154 | #define SYSCONFIG2_SPACE_200KHZ (0x0 << 4) | ||
155 | #define SYSCONFIG2_SPACE_100KHZ (0x1 << 4) | ||
156 | #define SYSCONFIG2_SPACE_50KHZ (0x2 << 4) | ||
157 | /* 4700/01 0000=mute,0001=-28dBFS..2dB steps..1111= +0dBFS */ | ||
158 | /* 4702/03: VOLEXT=0: 0000=mute,0001=-28dBFS..2dB steps..1111= +0dBFS */ | ||
159 | /* VOLEXT=1: 0000=mute,0001=-58dBFS..2dB steps..1111=-30dBFS */ | ||
160 | #define SYSCONFIG2_VOLUME (0xf << 0) | ||
161 | #define SYSCONFIG2_VOLUMEw(x) ((x) & SYSCONFIG2_VOLUME) | ||
162 | |||
163 | /* SYSCONFIG3 (0x6) */ | ||
164 | #define SYSCONFIG3_SMUTER (0x3 << 14) | ||
165 | #define SYSCONFIG3_SMUTER_FASTEST (0x0 << 14) | ||
166 | #define SYSCONFIG3_SMUTER_FAST (0x1 << 14) | ||
167 | #define SYSCONFIG3_SMUTER_SLOW (0x2 << 14) | ||
168 | #define SYSCONFIG3_SMUTER_SLOWEST (0x3 << 14) | ||
169 | #define SYSCONFIG3_SMUTEA (0x3 << 12) | ||
170 | #define SYSCONFIG3_SMUTEA_16DB (0x0 << 12) | ||
171 | #define SYSCONFIG3_SMUTEA_14DB (0x1 << 12) | ||
172 | #define SYSCONFIG3_SMUTEA_12DB (0x2 << 12) | ||
173 | #define SYSCONFIG3_SMUTEA_10DB (0x3 << 12) | ||
174 | #define SYSCONFIG3_VOLEXT (0x1 << 8) /* x */ | ||
175 | #define SYSCONFIG3_SKSNR (0xf << 4) | ||
176 | #define SYSCONFIG3_SKSNRw(x) (((x) << 4) & SYSCONFIG3_SKSNR) | ||
177 | #define SYSCONFIG3_SKCNT (0xf << 0) | ||
178 | #define SYSCONFIG3_SKCNTw(x) (((x) << 0) & SYSCONFIG3_SKCNT) | ||
179 | |||
180 | /* TEST1 (0x7) */ | ||
181 | /* 4700/01: 15=always 0, 13:0 = write with preexisting values! */ | ||
182 | /* 4702/03: 13:0 = write with preexisting values! */ | ||
183 | #define TEST1_XOSCEN (0x1 << 15) /* x */ | ||
184 | #define TEST1_AHIZEN (0x1 << 14) | ||
185 | |||
186 | /* TEST2 (0x8) */ | ||
187 | /* 15:0 = write with preexisting values! */ | ||
188 | |||
189 | /* BOOTCONFIG (0x9) */ | ||
190 | /* 15:0 = write with preexisting values! */ | ||
191 | |||
192 | /* STATUSRSSI (0xA) */ | ||
193 | #define STATUSRSSI_RDSR (0x1 << 15) /* x */ | ||
194 | #define STATUSRSSI_STC (0x1 << 14) | ||
195 | #define STATUSRSSI_SFBL (0x1 << 13) | ||
196 | #define STATUSRSSI_AFCRL (0x1 << 12) | ||
197 | #define STATUSRSSI_RDSS (0x1 << 11) /* x */ | ||
198 | #define STATUSRSSI_BLERA (0x3 << 9) /* x */ | ||
199 | #define STATUSRSSI_ST (0x1 << 8) | ||
200 | #define STATUSRSSI_RSSI (0xff << 0) | ||
201 | #define STATUSRSSI_RSSIr(x) ((x) & 0xff) | ||
202 | |||
203 | /* READCHAN (0xB) */ | ||
204 | #define READCHAN_BLERB (0x3 << 14) /* x */ | ||
205 | #define READCHAN_BLERC (0x3 << 12) /* x */ | ||
206 | #define READCHAN_BLERD (0x3 << 10) /* x */ | ||
207 | #define READCHAN_READCHAN (0x3ff << 0) | ||
208 | |||
209 | /* RDSA-D (0xC-0xF) */ | ||
210 | /* 4702/03: RDS Block A-D data */ | ||
57 | 211 | ||
58 | static bool tuner_present = false; | 212 | static bool tuner_present = false; |
59 | static unsigned short cache[16]; | 213 | static int curr_frequency = 87500000; /* Current station frequency (HZ) */ |
214 | static uint16_t cache[16]; | ||
60 | 215 | ||
61 | /* reads <len> registers from radio at offset 0x0A into cache */ | 216 | /* reads <len> registers from radio at offset 0x0A into cache */ |
62 | static void si4700_read(int len) | 217 | static void si4700_read(int len) |
@@ -64,7 +219,7 @@ static void si4700_read(int len) | |||
64 | int i; | 219 | int i; |
65 | unsigned char buf[32]; | 220 | unsigned char buf[32]; |
66 | unsigned char *ptr = buf; | 221 | unsigned char *ptr = buf; |
67 | unsigned short data; | 222 | uint16_t data; |
68 | 223 | ||
69 | fmradio_i2c_read(I2C_ADR, buf, len * 2); | 224 | fmradio_i2c_read(I2C_ADR, buf, len * 2); |
70 | for (i = 0; i < len; i++) { | 225 | for (i = 0; i < len; i++) { |
@@ -80,8 +235,8 @@ static void si4700_write(int len) | |||
80 | int i; | 235 | int i; |
81 | unsigned char buf[32]; | 236 | unsigned char buf[32]; |
82 | unsigned char *ptr = buf; | 237 | unsigned char *ptr = buf; |
83 | unsigned short data; | 238 | uint16_t data; |
84 | 239 | ||
85 | for (i = 0; i < len; i++) { | 240 | for (i = 0; i < len; i++) { |
86 | data = cache[(i + POWERCFG) & 0xF]; | 241 | data = cache[(i + POWERCFG) & 0xF]; |
87 | *ptr++ = (data >> 8) & 0xFF; | 242 | *ptr++ = (data >> 8) & 0xFF; |
@@ -90,6 +245,43 @@ static void si4700_write(int len) | |||
90 | fmradio_i2c_write(I2C_ADR, buf, len * 2); | 245 | fmradio_i2c_write(I2C_ADR, buf, len * 2); |
91 | } | 246 | } |
92 | 247 | ||
248 | /* Hide silly, wrapped and continuous register reading and make interface | ||
249 | * appear sane and normal. This also makes the driver compatible with | ||
250 | * using the 3-wire interface. */ | ||
251 | static uint16_t si4700_read_reg(int reg) | ||
252 | { | ||
253 | si4700_read(((reg - STATUSRSSI) & 0xF) + 1); | ||
254 | return cache[reg]; | ||
255 | } | ||
256 | |||
257 | static void si4700_write_reg(int reg, uint16_t value) | ||
258 | { | ||
259 | cache[reg] = value; | ||
260 | si4700_write(((reg - POWERCFG) & 0xF) + 1); | ||
261 | } | ||
262 | |||
263 | static void si4700_write_masked(int reg, uint16_t bits, uint16_t mask) | ||
264 | { | ||
265 | si4700_write_reg(reg, (cache[reg] & ~mask) | (bits & mask)); | ||
266 | } | ||
267 | |||
268 | static void si4700_write_set(int reg, uint16_t mask) | ||
269 | { | ||
270 | si4700_write_reg(reg, cache[reg] | mask); | ||
271 | } | ||
272 | |||
273 | static void si4700_write_clear(int reg, uint16_t mask) | ||
274 | { | ||
275 | si4700_write_reg(reg, cache[reg] & ~mask); | ||
276 | } | ||
277 | |||
278 | #if (SI4700_GPIO_SETUP & SYSCONFIG1_GPIO3) != SYSCONFIG1_GPIO3_MO_ST_I | ||
279 | /* Poll i2c for the stereo status */ | ||
280 | static inline int si4700_st(void) | ||
281 | { | ||
282 | return (si4700_read_reg(STATUSRSSI) & STATUSRSSI_ST) >> 8; | ||
283 | } | ||
284 | #endif | ||
93 | 285 | ||
94 | void si4700_init(void) | 286 | void si4700_init(void) |
95 | { | 287 | { |
@@ -105,8 +297,7 @@ void si4700_init(void) | |||
105 | 297 | ||
106 | #ifdef USE_INTERNAL_OSCILLATOR | 298 | #ifdef USE_INTERNAL_OSCILLATOR |
107 | /* enable the internal oscillator */ | 299 | /* enable the internal oscillator */ |
108 | cache[TEST1] |= (1 << 15); /* XOSCEN */ | 300 | si4700_write_set(TEST1, TEST1_XOSCEN); |
109 | si4700_write(6); | ||
110 | sleep(HZ/2); | 301 | sleep(HZ/2); |
111 | #endif | 302 | #endif |
112 | } | 303 | } |
@@ -114,21 +305,102 @@ void si4700_init(void) | |||
114 | tuner_power(false); | 305 | tuner_power(false); |
115 | } | 306 | } |
116 | 307 | ||
117 | static void si4700_tune(void) | 308 | static void si4700_sleep(int snooze) |
118 | { | 309 | { |
119 | cache[CHANNEL] |= (1 << 15); /* Set TUNE high to start tuning */ | 310 | if (snooze) |
120 | si4700_write(2); | 311 | { |
312 | /** power down **/ | ||
313 | /* ENABLE high, DISABLE high */ | ||
314 | si4700_write_set(POWERCFG, | ||
315 | POWERCFG_DISABLE | POWERCFG_ENABLE); | ||
316 | /* Bits self-clear once placed in powerdown. */ | ||
317 | cache[POWERCFG] &= ~(POWERCFG_DISABLE | POWERCFG_ENABLE); | ||
318 | } | ||
319 | else | ||
320 | { | ||
321 | /** power up **/ | ||
322 | /* ENABLE high, DISABLE low */ | ||
323 | si4700_write_masked(POWERCFG, POWERCFG_ENABLE, | ||
324 | POWERCFG_DISABLE | POWERCFG_ENABLE); | ||
325 | sleep(110 * HZ / 1000); | ||
326 | |||
327 | /* init register cache */ | ||
328 | si4700_read(16); | ||
329 | |||
330 | #if SI4700_GPIO_SETUP != 0 | ||
331 | si4700_write_masked(SYSCONFIG1, SI4700_GPIO_SETUP, | ||
332 | SYSCONFIG1_GPIO1 | SYSCONFIG1_GPIO2 | | ||
333 | SYSCONFIG1_GPIO3); | ||
334 | #endif | ||
335 | /* -6dB volume, seek threshold 12 */ | ||
336 | si4700_write_masked(SYSCONFIG2, | ||
337 | SYSCONFIG2_SKEETHw(SEEK_THRESHOLD) | | ||
338 | SYSCONFIG2_VOLUMEw(TUNER_VOLUME), | ||
339 | SYSCONFIG2_VOLUME | SYSCONFIG2_SEEKTH); | ||
340 | } | ||
341 | } | ||
342 | |||
343 | static void si4700_set_frequency(int freq) | ||
344 | { | ||
345 | static const unsigned int spacings[3] = | ||
346 | { | ||
347 | 200000, /* SYSCONFIG2_SPACE_200KHZ */ | ||
348 | 100000, /* SYSCONFIG2_SPACE_100KHZ */ | ||
349 | 50000, /* SYSCONFIG2_SPACE_50KHZ */ | ||
350 | }; | ||
351 | static const unsigned int bands[3] = | ||
352 | { | ||
353 | 87500000, /* SYSCONFIG2_BAND_875_1080 */ | ||
354 | 76000000, /* SYSCONFIG2_BAND_760_1080 */ | ||
355 | 76000000, /* SYSCONFIG2_BAND_760_900 */ | ||
356 | }; | ||
357 | |||
358 | /* check BAND and spacings */ | ||
359 | int space = SYSCONFIG2_SPACEr(cache[SYSCONFIG2]); | ||
360 | int band = SYSCONFIG2_BANDr(cache[SYSCONFIG2]); | ||
361 | int chan = (freq - bands[band]) / spacings[space]; | ||
362 | |||
363 | curr_frequency = freq; | ||
364 | |||
365 | si4700_write_reg(CHANNEL, CHANNEL_CHANw(chan) | CHANNEL_TUNE); | ||
121 | 366 | ||
122 | do | 367 | do |
123 | { | 368 | { |
124 | /* tuning should be done within 60 ms according to the datasheet */ | 369 | /* tuning should be done within 60 ms according to the datasheet */ |
125 | sleep(HZ * 60 / 1000); | 370 | sleep(HZ * 60 / 1000); |
126 | si4700_read(2); | ||
127 | } | 371 | } |
128 | while (!(cache[STATUSRSSI] & (1 << 14))); /* STC high */ | 372 | while ((si4700_read_reg(STATUSRSSI) & STATUSRSSI_STC) == 0); /* STC high? */ |
129 | 373 | ||
130 | cache[CHANNEL] &= ~(1 << 15); /* Set TUNE low */ | 374 | si4700_write_clear(CHANNEL, CHANNEL_TUNE); /* Set TUNE low */ |
131 | si4700_write(2); | 375 | } |
376 | |||
377 | static int si4700_tuned(void) | ||
378 | { | ||
379 | /* Primitive tuning check: sufficient level and AFC not railed */ | ||
380 | uint16_t status = si4700_read_reg(STATUSRSSI); | ||
381 | if (STATUSRSSI_RSSIr(status) >= SEEK_THRESHOLD && | ||
382 | (status & STATUSRSSI_AFCRL) == 0) | ||
383 | return 1; | ||
384 | |||
385 | return 0; | ||
386 | } | ||
387 | |||
388 | static void si4700_set_region(int region) | ||
389 | { | ||
390 | const struct si4700_region_data *rd = &si4700_region_data[region]; | ||
391 | uint16_t bandspacing = SYSCONFIG2_BANDw(rd->band) | | ||
392 | SYSCONFIG2_SPACEw(rd->spacing); | ||
393 | uint16_t oldbs = cache[SYSCONFIG2] & (SYSCONFIG2_BAND | SYSCONFIG2_SPACE); | ||
394 | |||
395 | si4700_write_masked(SYSCONFIG1, | ||
396 | rd->deemphasis ? SYSCONFIG1_DE : 0, | ||
397 | SYSCONFIG1_DE); | ||
398 | si4700_write_masked(SYSCONFIG2, bandspacing, | ||
399 | SYSCONFIG2_BAND | SYSCONFIG2_SPACE); | ||
400 | |||
401 | /* Retune if this region change would change the channel number. */ | ||
402 | if (oldbs != bandspacing) | ||
403 | si4700_set_frequency(curr_frequency); | ||
132 | } | 404 | } |
133 | 405 | ||
134 | /* tuner abstraction layer: set something to the tuner */ | 406 | /* tuner abstraction layer: set something to the tuner */ |
@@ -137,95 +409,35 @@ int si4700_set(int setting, int value) | |||
137 | switch(setting) | 409 | switch(setting) |
138 | { | 410 | { |
139 | case RADIO_SLEEP: | 411 | case RADIO_SLEEP: |
140 | if (value) | 412 | si4700_sleep(value); |
141 | { | 413 | break; |
142 | /* power down */ | ||
143 | cache[POWERCFG] = (1 | (1 << 6)); /* ENABLE high, DISABLE high */ | ||
144 | si4700_write(1); | ||
145 | } | ||
146 | else | ||
147 | { | ||
148 | /* power up */ | ||
149 | cache[POWERCFG] = 1; /* ENABLE high, DISABLE low */ | ||
150 | si4700_write(1); | ||
151 | sleep(110 * HZ / 1000); | ||
152 | |||
153 | /* update register cache */ | ||
154 | si4700_read(16); | ||
155 | |||
156 | /* -6dB volume, keep everything else as default */ | ||
157 | cache[SYSCONFIG2] = (cache[SYSCONFIG2] & ~0xF) | 0xC; | ||
158 | si4700_write(5); | ||
159 | } | ||
160 | return 1; | ||
161 | 414 | ||
162 | case RADIO_FREQUENCY: | 415 | case RADIO_FREQUENCY: |
163 | { | 416 | si4700_set_frequency(value); |
164 | static const unsigned int spacings[3] = | 417 | break; |
165 | { | ||
166 | 200000, 100000, 50000 | ||
167 | }; | ||
168 | unsigned int chan; | ||
169 | unsigned int spacing = spacings[(cache[5] >> 4) & 3] ; | ||
170 | |||
171 | if (cache[SYSCONFIG2] & (3 << 6)) /* check BAND */ | ||
172 | { | ||
173 | chan = (value - 76000000) / spacing; | ||
174 | } | ||
175 | else | ||
176 | { | ||
177 | chan = (value - 87500000) / spacing; | ||
178 | } | ||
179 | |||
180 | cache[CHANNEL] = (cache[CHANNEL] & ~0x3FF) | chan; | ||
181 | si4700_tune(); | ||
182 | return 1; | ||
183 | } | ||
184 | 418 | ||
185 | case RADIO_SCAN_FREQUENCY: | 419 | case RADIO_SCAN_FREQUENCY: |
186 | si4700_set(RADIO_FREQUENCY, value); | 420 | si4700_set_frequency(value); |
187 | return 1; | 421 | return si4700_tuned(); |
188 | 422 | ||
189 | case RADIO_MUTE: | 423 | case RADIO_MUTE: |
190 | if (value) | 424 | si4700_write_masked(POWERCFG, value ? 0 : POWERCFG_DMUTE, |
191 | { | 425 | POWERCFG_DMUTE); |
192 | /* mute */ | ||
193 | cache[POWERCFG] &= ~(1 << 14); | ||
194 | } | ||
195 | else | ||
196 | { | ||
197 | /* unmute */ | ||
198 | cache[POWERCFG] |= (1 << 14); | ||
199 | } | ||
200 | break; | 426 | break; |
201 | 427 | ||
202 | case RADIO_REGION: | 428 | case RADIO_REGION: |
203 | { | 429 | si4700_set_region(value); |
204 | const struct si4700_region_data *rd = | ||
205 | &si4700_region_data[value]; | ||
206 | |||
207 | cache[SYSCONFIG1] = (cache[SYSCONFIG1] & ~(1 << 11)) | (rd->deemphasis << 11); | ||
208 | cache[SYSCONFIG2] = (cache[SYSCONFIG2] & ~(3 << 6)) | (rd->band << 6); | ||
209 | cache[SYSCONFIG2] = (cache[SYSCONFIG2] & ~(3 << 4)) | (rd->spacing << 4); | ||
210 | break; | 430 | break; |
211 | } | ||
212 | 431 | ||
213 | case RADIO_FORCE_MONO: | 432 | case RADIO_FORCE_MONO: |
214 | if (value) | 433 | si4700_write_masked(POWERCFG, value ? POWERCFG_MONO : 0, |
215 | { | 434 | POWERCFG_MONO); |
216 | cache[POWERCFG] |= (1 << 13); | ||
217 | } | ||
218 | else | ||
219 | { | ||
220 | cache[POWERCFG] &= ~(1 << 13); | ||
221 | } | ||
222 | break; | 435 | break; |
223 | 436 | ||
224 | default: | 437 | default: |
225 | return -1; | 438 | return -1; |
226 | } | 439 | } |
227 | 440 | ||
228 | si4700_write(5); | ||
229 | return 1; | 441 | return 1; |
230 | } | 442 | } |
231 | 443 | ||
@@ -241,15 +453,25 @@ int si4700_get(int setting) | |||
241 | break; | 453 | break; |
242 | 454 | ||
243 | case RADIO_TUNED: | 455 | case RADIO_TUNED: |
244 | val = 1; | 456 | val = si4700_tuned(); |
245 | break; | 457 | break; |
246 | 458 | ||
247 | case RADIO_STEREO: | 459 | case RADIO_STEREO: |
248 | si4700_read(1); | 460 | val = si4700_st(); |
249 | val = (cache[STATUSRSSI] & (1 << 8)); /* ST high == Stereo */ | ||
250 | break; | 461 | break; |
251 | } | 462 | } |
252 | 463 | ||
253 | return val; | 464 | return val; |
254 | } | 465 | } |
255 | 466 | ||
467 | void si4700_dbg_info(struct si4700_dbg_info *nfo) | ||
468 | { | ||
469 | memset(nfo->regs, 0, sizeof (nfo->regs)); | ||
470 | |||
471 | if (tuner_powered()) | ||
472 | { | ||
473 | si4700_read(16); | ||
474 | memcpy(nfo->regs, cache, sizeof (nfo->regs)); | ||
475 | } | ||
476 | } | ||
477 | |||
diff --git a/firmware/export/imx31l.h b/firmware/export/imx31l.h index 6780a5a43f..5a964b8e2e 100755 --- a/firmware/export/imx31l.h +++ b/firmware/export/imx31l.h | |||
@@ -202,26 +202,33 @@ | |||
202 | #define SW_MUX_CTL_GPIO1_0_GPIO1_1_GPIO1_2_GPIO1_3 IOMUXC_(0x14C) | 202 | #define SW_MUX_CTL_GPIO1_0_GPIO1_1_GPIO1_2_GPIO1_3 IOMUXC_(0x14C) |
203 | #define SW_MUX_CTL_CAPTURE_COMPARE_WATCHDOG_RST_PWMO IOMUXC_(0x150) | 203 | #define SW_MUX_CTL_CAPTURE_COMPARE_WATCHDOG_RST_PWMO IOMUXC_(0x150) |
204 | 204 | ||
205 | #define SW_MUX_OUT_EN_GPIO_DR 0x0 | 205 | #define SW_MUX_OUT (0x7 << 4) |
206 | #define SW_MUX_OUT_FUNCTIONAL 0x1 | 206 | #define SW_MUX_OUT_GPIO_DR (0x0 << 4) |
207 | #define SW_MUX_OUT_ALTERNATE_1 0x2 | 207 | #define SW_MUX_OUT_FUNCTIONAL (0x1 << 4) |
208 | #define SW_MUX_OUT_ALTERNATE_2 0x3 | 208 | #define SW_MUX_OUT_ALT1 (0x2 << 4) |
209 | #define SW_MUX_OUT_ALTERNATE_3 0x4 | 209 | #define SW_MUX_OUT_ALT2 (0x3 << 4) |
210 | #define SW_MUX_OUT_ALTERNATE_4 0x5 | 210 | #define SW_MUX_OUT_ALT3 (0x4 << 4) |
211 | #define SW_MUX_OUT_ALTERNATE_5 0x6 | 211 | #define SW_MUX_OUT_ALT4 (0x5 << 4) |
212 | #define SW_MUX_OUT_ALTERNATE_6 0x7 | 212 | #define SW_MUX_OUT_ALT5 (0x6 << 4) |
213 | 213 | #define SW_MUX_OUT_ALT6 (0x7 << 4) | |
214 | #define SW_MUX_IN_NO_INPUTS 0x0 | 214 | |
215 | #define SW_MUX_IN_GPIO_PSR_ISR 0x1 | 215 | #define SW_MUX_IN (0xf << 0) |
216 | #define SW_MUX_IN_FUNCTIONAL 0x2 | 216 | #define SW_MUX_IN_NO_INPUTS (0x0 << 0) |
217 | #define SW_MUX_IN_ALTERNATE_1 0x3 | 217 | #define SW_MUX_IN_GPIO_PSR_ISR (0x1 << 0) |
218 | #define SW_MUX_IN_ALTERNATE_2 0x4 | 218 | #define SW_MUX_IN_FUNCTIONAL (0x2 << 0) |
219 | 219 | #define SW_MUX_IN_ALT1 (0x4 << 0) | |
220 | #define SW_MUX_IN_ALT2 (0x8 << 0) | ||
221 | |||
222 | /* Masks for each signal field */ | ||
223 | #define SW_MUX_CTL_SIG1 (0x7f << 0) | ||
224 | #define SW_MUX_CTL_SIG2 (0x7f << 8) | ||
225 | #define SW_MUX_CTL_SIG3 (0x7f << 16) | ||
226 | #define SW_MUX_CTL_SIG4 (0x7f << 24) | ||
220 | /* Shift above flags into one of the four fields in each register */ | 227 | /* Shift above flags into one of the four fields in each register */ |
221 | #define SW_MUX_CTL_FLD_0(x) ((x) << 0) | 228 | #define SW_MUX_CTL_SIG1w(x) (((x) << 0) & SW_MUX_CTL_SIG1) |
222 | #define SW_MUX_CTL_FLD_1(x) ((x) << 8) | 229 | #define SW_MUX_CTL_SIG2w(x) (((x) << 8) & SW_MUX_CTL_SIG2) |
223 | #define SW_MUX_CTL_FLD_2(x) ((x) << 16) | 230 | #define SW_MUX_CTL_SIG3w(x) (((x) << 16) & SW_MUX_CTL_SIG3) |
224 | #define SW_MUX_CTL_FLD_3(x) ((x) << 24) | 231 | #define SW_MUX_CTL_SIG4w(x) (((x) << 24) & SW_MUX_CTL_SIG4) |
225 | 232 | ||
226 | /* SW_PAD_CTL */ | 233 | /* SW_PAD_CTL */ |
227 | #define SW_PAD_CTL_TTM_PAD__X__X IOMUXC_(0x154) | 234 | #define SW_PAD_CTL_TTM_PAD__X__X IOMUXC_(0x154) |
@@ -336,36 +343,39 @@ | |||
336 | #define SW_PAD_CTL_CAPTURE_COMPARE_WATCHDOG_RST IOMUXC_(0x308) | 343 | #define SW_PAD_CTL_CAPTURE_COMPARE_WATCHDOG_RST IOMUXC_(0x308) |
337 | 344 | ||
338 | /* SW_PAD_CTL flags */ | 345 | /* SW_PAD_CTL flags */ |
339 | #define SW_PAD_CTL_LOOPBACK (1 << 9) | 346 | #define SW_PAD_CTL_LOOPBACK (0x1 << 9) /* Route output to input */ |
340 | #define SW_PAD_CTL_DISABLE_PULL_UP_DOWN_AND_KEEPER (0 << 7) | 347 | /* Pullup, pulldown and keeper enable */ |
341 | #if 0 /* Same as 0 */ | 348 | #define SW_PAD_CTL_PUE_PKE (0x3 << 7) |
342 | #define SW_PAD_CTL_DISABLE_PULL_UP_DOWN_AND_KEEPER (1 << 7) | 349 | #define SW_PAD_CTL_PUE_PKE_DISABLE (0x0 << 7) |
343 | #endif | 350 | #define SW_PAD_CTL_PUE_PKE_DISABLE_2 (0x1 << 7) /* Same as 0x0 */ |
344 | #define SW_PAD_CTL_ENABLE_KEEPER (2 << 7) | 351 | #define SW_PAD_CTL_PUE_PKE_KEEPER (0x2 << 7) |
345 | #define SW_PAD_CTL_ENABLE_PULL_UP_OR_PULL_DOWN (3 << 7) | 352 | #define SW_PAD_CTL_PUE_PKE_PULLUPDOWN (0x3 << 7) /* Enb. Pull up or down */ |
346 | #define SW_PAD_CTL_100K_PULL_DOWN (0 << 5) | 353 | /* Pullup/down resistance */ |
347 | #define SW_PAD_CTL_100K_PULL_UP (1 << 5) | 354 | #define SW_PAD_CTL_PUS (0x3 << 5) |
355 | #define SW_PAD_CTL_PUS_DOWN_100K (0x0 << 5) | ||
356 | #define SW_PAD_CTL_PUS_UP_100K (0x1 << 5) | ||
348 | #if 0 /* Completeness */ | 357 | #if 0 /* Completeness */ |
349 | #define SW_PAD_CTL_47K_PULL_UP (2 << 5) /* Not in IMX31/L */ | 358 | #define SW_PAD_CTL_PUS_UP_47K (0x2 << 5) /* Not in IMX31/L */ |
350 | #define SW_PAD_CTL_22K_PULL_UP (3 << 5) /* Not in IMX31/L */ | 359 | #define SW_PAD_CTL_PUS_UP_22K (0x3 << 5) /* Not in IMX31/L */ |
351 | #endif | ||
352 | #define SW_PAD_CTL_IPP_HYS_STD (0 << 4) | ||
353 | #define SW_PAD_CTL_IPP_HYS_SCHIMDT (1 << 4) | ||
354 | #define SW_PAD_CTL_IPP_ODE_CMOS (0 << 3) | ||
355 | #define SW_PAD_CTL_IPP_ODE_OPEN (1 << 3) | ||
356 | #define SW_PAD_CTL_IPP_DSE_STD (0 << 1) | ||
357 | #define SW_PAD_CTL_IPP_DSE_HIGH (1 << 1) | ||
358 | #define SW_PAD_CTL_IPP_DSE_MAX (2 << 1) | ||
359 | #if 0 /* Same as 2 */ | ||
360 | #define SW_PAD_CTL_IPP_DSE_MAX (3 << 1) | ||
361 | #endif | 360 | #endif |
362 | #define SW_PAD_CTL_IPP_SRE_SLOW (0 << 0) | 361 | #define SW_PAD_CTL_HYS (0x1 << 4) /* Schmitt trigger input */ |
363 | #define SW_PAD_CTL_IPP_SRE_FAST (1 << 0) | 362 | #define SW_PAD_CTL_ODE (0x1 << 3) /* Open drain output 0=CMOS pushpull*/ |
363 | #define SW_PAD_CTL_DSE (0x3 << 1) | ||
364 | #define SW_PAD_CTL_DSE_STD (0x0 << 1) /* Drive strength */ | ||
365 | #define SW_PAD_CTL_DSE_HIGH (0x1 << 1) | ||
366 | #define SW_PAD_CTL_DSE_MAX (0x2 << 1) | ||
367 | #define SW_PAD_CTL_DSE_MAX_2 (0x3 << 1) /* Same as 0x2 */ | ||
368 | #define SW_PAD_CTL_SRE (0x1 << 0) /* Slew rate, 1=fast */ | ||
369 | |||
370 | /* Masks for each IO field */ | ||
371 | #define SW_PAD_CTL_IO1 (0x3ff << 0) | ||
372 | #define SW_PAD_CTL_IO2 (0x3ff << 10) | ||
373 | #define SW_PAD_CTL_IO3 (0x3ff << 20) | ||
364 | 374 | ||
365 | /* Shift above flags into one of the three fields in each register */ | 375 | /* Shift above flags into one of the three fields in each register */ |
366 | #define SW_PAD_CTL_FLD_0(x) ((x) << 0) | 376 | #define SW_PAD_CTL_IO1w(x) (((x) << 0) & SW_PAD_CTL_IO1) |
367 | #define SW_PAD_CTL_FLD_1(x) ((x) << 10) | 377 | #define SW_PAD_CTL_IO2w(x) (((x) << 10) & SW_PAD_CTL_IO2) |
368 | #define SW_PAD_CTL_FLD_2(x) ((x) << 20) | 378 | #define SW_PAD_CTL_IO3w(x) (((x) << 20) & SW_PAD_CTL_IO3) |
369 | 379 | ||
370 | /* RNGA */ | 380 | /* RNGA */ |
371 | #define RNGA_CONTROL (*(REG32_PTR_T)(RNGA_BASE_ADDR+0x00)) | 381 | #define RNGA_CONTROL (*(REG32_PTR_T)(RNGA_BASE_ADDR+0x00)) |
diff --git a/firmware/export/power.h b/firmware/export/power.h index edf43f8cc8..5cd6996eff 100644 --- a/firmware/export/power.h +++ b/firmware/export/power.h | |||
@@ -95,6 +95,7 @@ bool spdif_powered(void); | |||
95 | 95 | ||
96 | #if CONFIG_TUNER | 96 | #if CONFIG_TUNER |
97 | bool tuner_power(bool status); | 97 | bool tuner_power(bool status); |
98 | bool tuner_powered(void); | ||
98 | #endif | 99 | #endif |
99 | 100 | ||
100 | #endif /* _POWER_H_ */ | 101 | #endif /* _POWER_H_ */ |
diff --git a/firmware/export/si4700.h b/firmware/export/si4700.h index 89905ee155..fcc71cb282 100644 --- a/firmware/export/si4700.h +++ b/firmware/export/si4700.h | |||
@@ -36,9 +36,15 @@ struct si4700_region_data | |||
36 | 36 | ||
37 | extern const struct si4700_region_data si4700_region_data[TUNER_NUM_REGIONS]; | 37 | extern const struct si4700_region_data si4700_region_data[TUNER_NUM_REGIONS]; |
38 | 38 | ||
39 | struct si4700_dbg_info | ||
40 | { | ||
41 | uint16_t regs[16]; /* Read registers */ | ||
42 | }; | ||
43 | |||
39 | void si4700_init(void); | 44 | void si4700_init(void); |
40 | int si4700_set(int setting, int value); | 45 | int si4700_set(int setting, int value); |
41 | int si4700_get(int setting); | 46 | int si4700_get(int setting); |
47 | void si4700_dbg_info(struct si4700_dbg_info *nfo); | ||
42 | 48 | ||
43 | #ifndef CONFIG_TUNER_MULTI | 49 | #ifndef CONFIG_TUNER_MULTI |
44 | #define tuner_set si4700_set | 50 | #define tuner_set si4700_set |
diff --git a/firmware/target/arm/as3525/power-as3525.c b/firmware/target/arm/as3525/power-as3525.c index 07867546c2..2fbeab0bc6 100644 --- a/firmware/target/arm/as3525/power-as3525.c +++ b/firmware/target/arm/as3525/power-as3525.c | |||
@@ -54,9 +54,21 @@ void ide_power_enable(bool on) | |||
54 | } | 54 | } |
55 | 55 | ||
56 | #if CONFIG_TUNER | 56 | #if CONFIG_TUNER |
57 | static bool tuner_on = false; | ||
58 | |||
57 | bool tuner_power(bool status) | 59 | bool tuner_power(bool status) |
58 | { | 60 | { |
59 | (void)status; | 61 | if (status != tuner_on) |
60 | return false; | 62 | { |
63 | tuner_on = status; | ||
64 | status = !status; | ||
65 | } | ||
66 | |||
67 | return status; | ||
68 | } | ||
69 | |||
70 | bool tuner_powered(void) | ||
71 | { | ||
72 | return tuner_on; /* No debug info */ | ||
61 | } | 73 | } |
62 | #endif | 74 | #endif |
diff --git a/firmware/target/arm/imx31/gigabeat-s/fmradio-i2c-gigabeat-s.c b/firmware/target/arm/imx31/gigabeat-s/fmradio-i2c-gigabeat-s.c index 154e13f9a7..7646402435 100644 --- a/firmware/target/arm/imx31/gigabeat-s/fmradio-i2c-gigabeat-s.c +++ b/firmware/target/arm/imx31/gigabeat-s/fmradio-i2c-gigabeat-s.c | |||
@@ -21,6 +21,7 @@ | |||
21 | ****************************************************************************/ | 21 | ****************************************************************************/ |
22 | #include "config.h" | 22 | #include "config.h" |
23 | #include "system.h" | 23 | #include "system.h" |
24 | #include "mc13783.h" | ||
24 | #include "i2c-imx31.h" | 25 | #include "i2c-imx31.h" |
25 | #include "fmradio_i2c.h" | 26 | #include "fmradio_i2c.h" |
26 | 27 | ||
@@ -33,9 +34,77 @@ static struct i2c_node si4700_i2c_node = | |||
33 | .addr = (0x20), | 34 | .addr = (0x20), |
34 | }; | 35 | }; |
35 | 36 | ||
37 | void fmradio_i2c_init(void) | ||
38 | { | ||
39 | /* RST: LOW */ | ||
40 | imx31_regclr32(&GPIO1_DR, (1 << 26)); | ||
41 | /* RST: OUT */ | ||
42 | imx31_regset32(&GPIO1_GDIR, (1 << 26)); | ||
43 | |||
44 | /* I2C2 SCL: IN, I2C2: SDA IN */ | ||
45 | imx31_regclr32(&GPIO2_GDIR, (3 << 14)); | ||
46 | /* I2C2 SCL LO, I2C2 SDA LO */ | ||
47 | imx31_regclr32(&GPIO2_DR, (3 << 14)); | ||
48 | |||
49 | /* open-drain pins - external pullups on PCB. Pullup default but | ||
50 | * disabled */ | ||
51 | imx31_regmod32(&SW_PAD_CTL_DSR_DTE1_RI_DTE1_DCD_DTE1, | ||
52 | /* RI_DTE1 (I2C2_SCLK) */ | ||
53 | SW_PAD_CTL_IO2w(SW_PAD_CTL_PUE_PKE_DISABLE | | ||
54 | SW_PAD_CTL_PUS_UP_100K | | ||
55 | SW_PAD_CTL_HYS | | ||
56 | SW_PAD_CTL_ODE) | | ||
57 | /* DCD_DTE1 (I2C2_SDA) */ | ||
58 | SW_PAD_CTL_IO1w(SW_PAD_CTL_PUE_PKE_DISABLE | | ||
59 | SW_PAD_CTL_PUS_UP_100K | | ||
60 | SW_PAD_CTL_HYS | | ||
61 | SW_PAD_CTL_ODE), | ||
62 | SW_PAD_CTL_IO2 | SW_PAD_CTL_IO1); | ||
63 | /* set outputs to I2C2 */ | ||
64 | imx31_regmod32(&SW_MUX_CTL_RI_DTE1_DCD_DTE1_DTR_DCE2_RXD2, | ||
65 | /* RI_DTE1 => I2C2_SCLK */ | ||
66 | SW_MUX_CTL_SIG4w(SW_MUX_OUT_ALT2 | SW_MUX_IN_ALT2) | | ||
67 | /* DCD_DTE1 => I2C2_SDA */ | ||
68 | SW_MUX_CTL_SIG3w(SW_MUX_OUT_ALT2 | SW_MUX_IN_ALT2), | ||
69 | SW_MUX_CTL_SIG4 | SW_MUX_CTL_SIG3); | ||
70 | } | ||
71 | |||
36 | void fmradio_i2c_enable(bool enable) | 72 | void fmradio_i2c_enable(bool enable) |
37 | { | 73 | { |
38 | i2c_enable_node(&si4700_i2c_node, enable); | 74 | if (enable) |
75 | { | ||
76 | uint32_t io_pin_mux = SW_MUX_CTL_RI_DTE1_DCD_DTE1_DTR_DCE2_RXD2; | ||
77 | /* place in GPIO mode to hold SDIO low during RESET release, | ||
78 | * SEN1 should be high already (pullup) and GPIO3 left alone */ | ||
79 | imx31_regset32(&GPIO2_GDIR, (1 << 15)); /* SDIO OUT */ | ||
80 | /* I2C2_SDA => MCU2_15 */ | ||
81 | imx31_regmod32(&SW_MUX_CTL_RI_DTE1_DCD_DTE1_DTR_DCE2_RXD2, | ||
82 | SW_MUX_CTL_SIG3w(SW_MUX_OUT_GPIO_DR | SW_MUX_IN_GPIO_PSR_ISR), | ||
83 | SW_MUX_CTL_SIG3); | ||
84 | /* enable CLK32KMCU clock */ | ||
85 | mc13783_set(MC13783_POWER_CONTROL0, MC13783_CLK32KMCUEN); | ||
86 | /* enable the fm chip (release RESET) */ | ||
87 | imx31_regset32(&GPIO1_DR, (1 << 26)); | ||
88 | sleep(HZ/100); | ||
89 | /* busmode should be selected - OK to release SDIO */ | ||
90 | imx31_regclr32(&GPIO2_GDIR, (1 << 15)); /* SDIO IN */ | ||
91 | /* restore pin mux (DCD_DTE1 => I2C2_SDA) */ | ||
92 | imx31_regmod32(&SW_MUX_CTL_RI_DTE1_DCD_DTE1_DTR_DCE2_RXD2, | ||
93 | io_pin_mux, SW_MUX_CTL_SIG3); | ||
94 | /* the si4700 is the only thing connected to i2c2 so | ||
95 | we can diable the i2c module when not in use */ | ||
96 | i2c_enable_node(&si4700_i2c_node, true); | ||
97 | } | ||
98 | else | ||
99 | { | ||
100 | /* the si4700 is the only thing connected to i2c2 so | ||
101 | we can diable the i2c module when not in use */ | ||
102 | i2c_enable_node(&si4700_i2c_node, false); | ||
103 | /* disable the fm chip */ | ||
104 | imx31_regclr32(&GPIO1_DR, (1 << 26)); | ||
105 | /* disable CLK32KMCU clock */ | ||
106 | mc13783_clear(MC13783_POWER_CONTROL0, MC13783_CLK32KMCUEN); | ||
107 | } | ||
39 | } | 108 | } |
40 | 109 | ||
41 | int fmradio_i2c_write(unsigned char address, const unsigned char* buf, int count) | 110 | int fmradio_i2c_write(unsigned char address, const unsigned char* buf, int count) |
@@ -52,3 +121,7 @@ int fmradio_i2c_read(unsigned char address, unsigned char* buf, int count) | |||
52 | return 0; | 121 | return 0; |
53 | } | 122 | } |
54 | 123 | ||
124 | int si4700_st(void) | ||
125 | { | ||
126 | return (GPIO1_DR & (1 << 28)) >> 28; | ||
127 | } | ||
diff --git a/firmware/target/arm/imx31/gigabeat-s/power-imx31.c b/firmware/target/arm/imx31/gigabeat-s/power-imx31.c index 727b38bd96..b29d3cd0fb 100644 --- a/firmware/target/arm/imx31/gigabeat-s/power-imx31.c +++ b/firmware/target/arm/imx31/gigabeat-s/power-imx31.c | |||
@@ -98,37 +98,24 @@ bool ide_powered(void) | |||
98 | } | 98 | } |
99 | 99 | ||
100 | #if CONFIG_TUNER | 100 | #if CONFIG_TUNER |
101 | static bool tuner_on = false; | ||
102 | |||
101 | bool tuner_power(bool status) | 103 | bool tuner_power(bool status) |
102 | { | 104 | { |
103 | static bool tuner_powered = false; | 105 | if (status != tuner_on) |
104 | |||
105 | if (status == tuner_powered) | ||
106 | return status; | ||
107 | |||
108 | tuner_powered = status; | ||
109 | |||
110 | if (status) | ||
111 | { | ||
112 | /* the si4700 is the only thing connected to i2c2 so | ||
113 | we can diable the i2c module when not in use */ | ||
114 | fmradio_i2c_enable(true); | ||
115 | /* enable the fm chip */ | ||
116 | imx31_regset32(&GPIO1_DR, (1 << 26)); | ||
117 | /* enable CLK32KMCU clock */ | ||
118 | mc13783_set(MC13783_POWER_CONTROL0, MC13783_CLK32KMCUEN); | ||
119 | } | ||
120 | else | ||
121 | { | 106 | { |
122 | /* the si4700 is the only thing connected to i2c2 so | 107 | tuner_on = status; |
123 | we can diable the i2c module when not in use */ | 108 | /* Handle power and pin setup */ |
124 | fmradio_i2c_enable(false); | 109 | fmradio_i2c_enable(status); |
125 | /* disable the fm chip */ | 110 | status = !status; |
126 | imx31_regclr32(&GPIO1_DR, (1 << 26)); | ||
127 | /* disable CLK32KMCU clock */ | ||
128 | mc13783_clear(MC13783_POWER_CONTROL0, MC13783_CLK32KMCUEN); | ||
129 | } | 111 | } |
130 | 112 | ||
131 | return !status; | 113 | return status; |
114 | } | ||
115 | |||
116 | bool tuner_powered(void) | ||
117 | { | ||
118 | return tuner_on; | ||
132 | } | 119 | } |
133 | #endif /* #if CONFIG_TUNER */ | 120 | #endif /* #if CONFIG_TUNER */ |
134 | 121 | ||
@@ -151,6 +138,10 @@ void power_off(void) | |||
151 | 138 | ||
152 | void power_init(void) | 139 | void power_init(void) |
153 | { | 140 | { |
141 | #if CONFIG_TUNER | ||
142 | fmradio_i2c_init(); | ||
143 | #endif | ||
144 | |||
154 | /* Poll initial state */ | 145 | /* Poll initial state */ |
155 | charger_main_detect_event(); | 146 | charger_main_detect_event(); |
156 | 147 | ||
diff --git a/firmware/tuner.c b/firmware/tuner.c index c694031c45..c5da27079c 100644 --- a/firmware/tuner.c +++ b/firmware/tuner.c | |||
@@ -64,7 +64,7 @@ const struct si4700_region_data si4700_region_data[TUNER_NUM_REGIONS] = | |||
64 | { | 64 | { |
65 | [REGION_EUROPE] = { 1, 0, 2 }, /* 50uS, US/Europe band, 50kHz spacing */ | 65 | [REGION_EUROPE] = { 1, 0, 2 }, /* 50uS, US/Europe band, 50kHz spacing */ |
66 | [REGION_US_CANADA] = { 0, 0, 0 }, /* 75uS, US/Europe band, 200kHz spacing */ | 66 | [REGION_US_CANADA] = { 0, 0, 0 }, /* 75uS, US/Europe band, 200kHz spacing */ |
67 | [REGION_JAPAN] = { 1, 1, 1 }, /* 50uS, Japanese band, 100kHz spacing */ | 67 | [REGION_JAPAN] = { 1, 2, 1 }, /* 50uS, Japanese band, 100kHz spacing */ |
68 | [REGION_KOREA] = { 1, 0, 1 }, /* 50uS, US/Europe band, 100kHz spacing */ | 68 | [REGION_KOREA] = { 1, 0, 1 }, /* 50uS, US/Europe band, 100kHz spacing */ |
69 | }; | 69 | }; |
70 | #endif /* (CONFIG_TUNER & SI4700) */ | 70 | #endif /* (CONFIG_TUNER & SI4700) */ |