1 /***************************************************************************
3 * Open \______ \ ____ ____ | | _\_ |__ _______ ___
4 * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
5 * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
6 * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
10 * Tuner "middleware" for Silicon Labs SI4700 chip
12 * Copyright (C) 2008 Nils Wallménius
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.
19 * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
20 * KIND, either express or implied.
22 ****************************************************************************/
29 #include "tuner.h" /* tuner abstraction interface */
31 #include "fmradio_i2c.h" /* physical interface driver */
33 /* some models use the internal 32 kHz oscillator which needs special attention
34 during initialisation, power-up and power-down.
36 #if defined(SANSA_CLIP) || defined(SANSA_E200V2) || defined(SANSA_FUZE) || defined(SANSA_C200V2)
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);
45 #ifndef SI4700_GPIO_SETUP
46 #define SI4700_GPIO_SETUP 0
49 #define SEEK_THRESHOLD 0x16
53 /* define RSSI range */
57 /** Registers and bits - "x" denotes Si4702/03 only (so they say) **/
62 #define SYSCONFIG1 0x4
63 #define SYSCONFIG2 0x5
64 #define SYSCONFIG3 0x6
67 #define BOOTCONFIG 0x9
68 #define STATUSRSSI 0xA
70 #define RDSA 0xC /* x */
71 #define RDSB 0xD /* x */
72 #define RDSC 0xE /* x */
73 #define RDSD 0xF /* x */
76 #define DEVICEID_PN (0xf << 12)
77 /* 0x01 = Si4700/01 */
78 /* 0x01 = Si4702/03 */
79 #define DEVICEID_MFGID (0xfff << 0)
84 #if 0 /* Informational */
86 #define CHIPID_REV (0x3f << 10)
87 #define CHIPID_DEV (0x1 << 9)
88 /* 0 before powerup */
89 /* 0 after powerup = Si4700 */
90 /* 1 after powerup = Si4701 */
91 #define CHIPID_FIRMWARE (0xff << 0)
94 #define CHIPID_REV (0x3f << 10)
95 #define CHIPID_DEV (0xf << 6)
96 /* 0000 before PU = Si4702 */
97 /* 0001 after PU = Si4702 */
98 /* 1000 before PU = Si4703 */
99 /* 1001 after PU = Si4703 */
100 #define CHIPID_FIRMWARE (0x3f << 0)
104 #define POWERCFG_DSMUTE (0x1 << 15)
105 #define POWERCFG_DMUTE (0x1 << 14)
106 #define POWERCFG_MONO (0x1 << 13)
107 #define POWERCFG_RDSM (0x1 << 11) /* x */
108 #define POWERCFG_SKMODE (0x1 << 10)
109 #define POWERCFG_SEEKUP (0x1 << 9)
110 #define POWERCFG_SEEK (0x1 << 8)
111 #define POWERCFG_DISABLE (0x1 << 6)
112 #define POWERCFG_ENABLE (0x1 << 0)
115 #define CHANNEL_TUNE (0x1 << 15)
116 #define CHANNEL_CHAN (0x3ff << 0)
117 #define CHANNEL_CHANw(x) ((x) & CHANNEL_CHAN)
119 /* SYSCONFIG1 (0x4) */
120 #define SYSCONFIG1_RDSIEN (0x1 << 15) /* x */
121 #define SYSCONFIG1_STCIEN (0x1 << 14)
122 #define SYSCONFIG1_RDS (0x1 << 12) /* x */
123 #define SYSCONFIG1_DE (0x1 << 11)
124 #define SYSCONFIG1_AGCD (0x1 << 10)
125 #define SYSCONFIG1_BLNDADJ (0x3 << 6)
126 #define SYSCONFIG1_BLNDADJ_31_39_RSSI (0x0 << 6)
127 #define SYSCONFIG1_BLNDADJ_37_55_RSSI (0x1 << 6)
128 #define SYSCONFIG1_BLNDADJ_19_37_RSSI (0x2 << 6)
129 #define SYSCONFIG1_BLNDADJ_25_43_RSSI (0x3 << 6)
130 #define SYSCONFIG1_GPIO3 (0x3 << 4)
131 #define SYSCONFIG1_GPIO3_HI_Z (0x0 << 4)
132 #define SYSCONFIG1_GPIO3_MO_ST_I (0x1 << 4)
133 #define SYSCONFIG1_GPIO3_LOW (0x2 << 4)
134 #define SYSCONFIG1_GPIO3_HI (0x3 << 4)
135 #define SYSCONFIG1_GPIO2 (0x3 << 2)
136 #define SYSCONFIG1_GPIO2_HI_Z (0x0 << 2)
137 #define SYSCONFIG1_GPIO2_STC_RDS_I (0x1 << 2)
138 #define SYSCONFIG1_GPIO2_LOW (0x2 << 2)
139 #define SYSCONFIG1_GPIO2_HI (0x3 << 2)
140 #define SYSCONFIG1_GPIO1 (0x3 << 0)
141 #define SYSCONFIG1_GPIO1_HI_Z (0x0 << 0)
142 #define SYSCONFIG1_GPIO1_LOW (0x2 << 0)
143 #define SYSCONFIG1_GPIO1_HI (0x3 << 0)
145 /* SYSCONFIG2 (0x5) */
146 #define SYSCONFIG2_SEEKTH (0xff << 8)
147 #define SYSCONFIG2_SKEETHw(x) (((x) << 8) & SYSCONFIG2_SEEKTH)
148 #define SYSCONFIG2_BAND (0x3 << 6)
149 #define SYSCONFIG2_BANDw(x) (((x) << 6) & SYSCONFIG2_BAND)
150 #define SYSCONFIG2_BANDr(x) (((x) & SYSCONFIG2_BAND) >> 6)
151 #define SYSCONFIG2_BAND_875_1080 (0x0 << 6) /* tenth-megahertz */
152 #define SYSCONFIG2_BAND_760_1080 (0x1 << 6)
153 #define SYSCONFIG2_BAND_760_900 (0x2 << 6)
154 #define SYSCONFIG2_SPACE (0x3 << 4)
155 #define SYSCONFIG2_SPACEw(x) (((x) << 4) & SYSCONFIG2_SPACE)
156 #define SYSCONFIG2_SPACEr(x) (((x) & SYSCONFIG2_SPACE) >> 4)
157 #define SYSCONFIG2_SPACE_200KHZ (0x0 << 4)
158 #define SYSCONFIG2_SPACE_100KHZ (0x1 << 4)
159 #define SYSCONFIG2_SPACE_50KHZ (0x2 << 4)
160 /* 4700/01 0000=mute,0001=-28dBFS..2dB steps..1111= +0dBFS */
161 /* 4702/03: VOLEXT=0: 0000=mute,0001=-28dBFS..2dB steps..1111= +0dBFS */
162 /* VOLEXT=1: 0000=mute,0001=-58dBFS..2dB steps..1111=-30dBFS */
163 #define SYSCONFIG2_VOLUME (0xf << 0)
164 #define SYSCONFIG2_VOLUMEw(x) ((x) & SYSCONFIG2_VOLUME)
166 /* SYSCONFIG3 (0x6) */
167 #define SYSCONFIG3_SMUTER (0x3 << 14)
168 #define SYSCONFIG3_SMUTER_FASTEST (0x0 << 14)
169 #define SYSCONFIG3_SMUTER_FAST (0x1 << 14)
170 #define SYSCONFIG3_SMUTER_SLOW (0x2 << 14)
171 #define SYSCONFIG3_SMUTER_SLOWEST (0x3 << 14)
172 #define SYSCONFIG3_SMUTEA (0x3 << 12)
173 #define SYSCONFIG3_SMUTEA_16DB (0x0 << 12)
174 #define SYSCONFIG3_SMUTEA_14DB (0x1 << 12)
175 #define SYSCONFIG3_SMUTEA_12DB (0x2 << 12)
176 #define SYSCONFIG3_SMUTEA_10DB (0x3 << 12)
177 #define SYSCONFIG3_VOLEXT (0x1 << 8) /* x */
178 #define SYSCONFIG3_SKSNR (0xf << 4)
179 #define SYSCONFIG3_SKSNRw(x) (((x) << 4) & SYSCONFIG3_SKSNR)
180 #define SYSCONFIG3_SKCNT (0xf << 0)
181 #define SYSCONFIG3_SKCNTw(x) (((x) << 0) & SYSCONFIG3_SKCNT)
184 /* 4700/01: 15=always 0, 13:0 = write with preexisting values! */
185 /* 4702/03: 13:0 = write with preexisting values! */
186 #define TEST1_XOSCEN (0x1 << 15) /* x */
187 #define TEST1_AHIZEN (0x1 << 14)
190 /* 15:0 = write with preexisting values! */
192 /* BOOTCONFIG (0x9) */
193 /* 15:0 = write with preexisting values! */
195 /* STATUSRSSI (0xA) */
196 #define STATUSRSSI_RDSR (0x1 << 15) /* x */
197 #define STATUSRSSI_STC (0x1 << 14)
198 #define STATUSRSSI_SFBL (0x1 << 13)
199 #define STATUSRSSI_AFCRL (0x1 << 12)
200 #define STATUSRSSI_RDSS (0x1 << 11) /* x */
201 #define STATUSRSSI_BLERA (0x3 << 9) /* x */
202 #define STATUSRSSI_ST (0x1 << 8)
203 #define STATUSRSSI_RSSI (0xff << 0)
204 #define STATUSRSSI_RSSIr(x) ((x) & 0xff)
207 #define READCHAN_BLERB (0x3 << 14) /* x */
208 #define READCHAN_BLERC (0x3 << 12) /* x */
209 #define READCHAN_BLERD (0x3 << 10) /* x */
210 #define READCHAN_READCHAN (0x3ff << 0)
212 /* RDSA-D (0xC-0xF) */
213 /* 4702/03: RDS Block A-D data */
215 static bool tuner_present
= false;
216 static uint16_t cache
[16];
218 /* reads <len> registers from radio at offset 0x0A into cache */
219 static void si4700_read(int len
)
222 unsigned char buf
[32];
223 unsigned char *ptr
= buf
;
226 fmradio_i2c_read(I2C_ADR
, buf
, len
* 2);
227 for (i
= 0; i
< len
; i
++) {
228 data
= ptr
[0] << 8 | ptr
[1];
229 cache
[(i
+ STATUSRSSI
) & 0xF] = data
;
234 /* writes <len> registers from cache to radio at offset 0x02 */
235 static void si4700_write(int len
)
238 unsigned char buf
[32];
239 unsigned char *ptr
= buf
;
242 for (i
= 0; i
< len
; i
++) {
243 data
= cache
[(i
+ POWERCFG
) & 0xF];
244 *ptr
++ = (data
>> 8) & 0xFF;
245 *ptr
++ = data
& 0xFF;
247 fmradio_i2c_write(I2C_ADR
, buf
, len
* 2);
250 /* Hide silly, wrapped and continuous register reading and make interface
251 * appear sane and normal. This also makes the driver compatible with
252 * using the 3-wire interface. */
253 static uint16_t si4700_read_reg(int reg
)
255 si4700_read(((reg
- STATUSRSSI
) & 0xF) + 1);
259 static void si4700_write_reg(int reg
, uint16_t value
)
262 si4700_write(((reg
- POWERCFG
) & 0xF) + 1);
265 static void si4700_write_masked(int reg
, uint16_t bits
, uint16_t mask
)
267 si4700_write_reg(reg
, (cache
[reg
] & ~mask
) | (bits
& mask
));
270 static void si4700_write_set(int reg
, uint16_t mask
)
272 si4700_write_reg(reg
, cache
[reg
] | mask
);
275 static void si4700_write_clear(int reg
, uint16_t mask
)
277 si4700_write_reg(reg
, cache
[reg
] & ~mask
);
280 #if (SI4700_GPIO_SETUP & SYSCONFIG1_GPIO3) != SYSCONFIG1_GPIO3_MO_ST_I
281 /* Poll i2c for the stereo status */
282 static inline int si4700_st(void)
284 return (si4700_read_reg(STATUSRSSI
) & STATUSRSSI_ST
) >> 8;
288 static void si4700_sleep(int snooze
)
293 /* ENABLE high, DISABLE high */
294 si4700_write_set(POWERCFG
,
295 POWERCFG_DISABLE
| POWERCFG_ENABLE
);
296 /* Bits self-clear once placed in powerdown. */
297 cache
[POWERCFG
] &= ~(POWERCFG_DISABLE
| POWERCFG_ENABLE
);
302 /* ENABLE high, DISABLE low */
303 si4700_write_masked(POWERCFG
, POWERCFG_ENABLE
,
304 POWERCFG_DISABLE
| POWERCFG_ENABLE
);
305 sleep(110 * HZ
/ 1000);
307 /* init register cache */
310 #if SI4700_GPIO_SETUP != 0
311 si4700_write_masked(SYSCONFIG1
, SI4700_GPIO_SETUP
,
312 SYSCONFIG1_GPIO1
| SYSCONFIG1_GPIO2
|
315 /* set mono->stereo switching RSSI range to lowest setting */
316 si4700_write_masked(SYSCONFIG1
, SYSCONFIG1_BLNDADJ_19_37_RSSI
,
319 si4700_write_masked(SYSCONFIG2
,
320 SYSCONFIG2_SKEETHw(SEEK_THRESHOLD
) |
321 SYSCONFIG2_VOLUMEw(0xF),
322 SYSCONFIG2_VOLUME
| SYSCONFIG2_SEEKTH
);
326 bool si4700_detect(void)
331 detected
= (si4700_read_reg(DEVICEID
) == 0x1242);
337 void si4700_init(void)
339 /* check device id */
340 if (si4700_detect()) {
341 tuner_present
= true;
345 /* read all registers */
349 #ifdef USE_INTERNAL_OSCILLATOR
350 /* Enable the internal oscillator
351 (Si4702-16 needs this register to be initialised to 0x100) */
352 si4700_write_set(TEST1
, TEST1_XOSCEN
| 0x100);
361 static void si4700_set_frequency(int freq
)
363 static const unsigned int spacings
[3] =
365 200000, /* SYSCONFIG2_SPACE_200KHZ */
366 100000, /* SYSCONFIG2_SPACE_100KHZ */
367 50000, /* SYSCONFIG2_SPACE_50KHZ */
369 static const unsigned int bands
[3] =
371 87500000, /* SYSCONFIG2_BAND_875_1080 */
372 76000000, /* SYSCONFIG2_BAND_760_1080 */
373 76000000, /* SYSCONFIG2_BAND_760_900 */
376 /* check BAND and spacings */
377 int space
= SYSCONFIG2_SPACEr(cache
[SYSCONFIG2
]);
378 int band
= SYSCONFIG2_BANDr(cache
[SYSCONFIG2
]);
379 int chan
= (freq
- bands
[band
]) / spacings
[space
];
384 /* tuning should be done within 60 ms according to the datasheet */
385 si4700_write_reg(CHANNEL
, CHANNEL_CHANw(chan
) | CHANNEL_TUNE
);
386 sleep(HZ
* 60 / 1000);
388 /* get tune result */
389 readchan
= si4700_read_reg(READCHAN
) & READCHAN_READCHAN
;
391 si4700_write_clear(CHANNEL
, CHANNEL_TUNE
);
392 } while (!((cache
[STATUSRSSI
] & STATUSRSSI_STC
) && (readchan
== chan
)));
395 static int si4700_tuned(void)
397 /* Primitive tuning check: sufficient level and AFC not railed */
398 uint16_t status
= si4700_read_reg(STATUSRSSI
);
399 if (STATUSRSSI_RSSIr(status
) >= SEEK_THRESHOLD
&&
400 (status
& STATUSRSSI_AFCRL
) == 0)
406 static void si4700_set_region(int region
)
408 const struct fm_region_data
*rd
= &fm_region_data
[region
];
410 int band
= (rd
->freq_min
== 76000000) ? 2 : 0;
411 int spacing
= (100000 / rd
->freq_step
);
412 int deemphasis
= (rd
->deemphasis
== 50) ? SYSCONFIG1_DE
: 0;
414 uint16_t bandspacing
= SYSCONFIG2_BANDw(band
) |
415 SYSCONFIG2_SPACEw(spacing
);
416 si4700_write_masked(SYSCONFIG1
, deemphasis
, SYSCONFIG1_DE
);
417 si4700_write_masked(SYSCONFIG2
, bandspacing
,
418 SYSCONFIG2_BAND
| SYSCONFIG2_SPACE
);
421 /* tuner abstraction layer: set something to the tuner */
422 int si4700_set(int setting
, int value
)
429 /* else actually it's 'pause' */
432 case RADIO_FREQUENCY
:
433 si4700_set_frequency(value
);
436 case RADIO_SCAN_FREQUENCY
:
437 si4700_set_frequency(value
);
438 return si4700_tuned();
441 si4700_write_masked(POWERCFG
, value
? 0 : POWERCFG_DMUTE
,
446 si4700_set_region(value
);
449 case RADIO_FORCE_MONO
:
450 si4700_write_masked(POWERCFG
, value
? POWERCFG_MONO
: 0,
461 /* tuner abstraction layer: read something from the tuner */
462 int si4700_get(int setting
)
464 int val
= -1; /* default for unsupported query */
469 val
= tuner_present
? 1 : 0;
473 val
= si4700_tuned();
481 val
= STATUSRSSI_RSSIr(si4700_read_reg(STATUSRSSI
));
496 void si4700_dbg_info(struct si4700_dbg_info
*nfo
)
498 memset(nfo
->regs
, 0, sizeof (nfo
->regs
));
503 memcpy(nfo
->regs
, cache
, sizeof (nfo
->regs
));