summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--apps/debug_menu.c20
-rw-r--r--apps/recorder/radio.c144
-rw-r--r--apps/recorder/radio.h21
-rw-r--r--firmware/SOURCES11
-rw-r--r--firmware/drivers/power.c4
-rw-r--r--firmware/drivers/tuner/lv24020lp.c (renamed from firmware/tuner_sanyo.c)248
-rw-r--r--firmware/drivers/tuner/s1a0903x01.c (renamed from firmware/tuner_samsung.c)47
-rw-r--r--firmware/drivers/tuner/tea5767.c (renamed from firmware/tuner_philips.c)44
-rw-r--r--firmware/export/config.h5
-rw-r--r--firmware/export/hwcompat.h7
-rw-r--r--firmware/export/lv24020lp.h51
-rw-r--r--firmware/export/power.h4
-rw-r--r--firmware/export/s1a0903x01.h40
-rw-r--r--firmware/export/tea5767.h50
-rw-r--r--firmware/export/tuner.h173
-rw-r--r--firmware/target/arm/archos/av300/power-av300.c4
-rw-r--r--firmware/target/arm/iriver/h10/power-h10.c4
-rw-r--r--firmware/target/arm/pnx0101/iriver-ifp7xx/power-ifp7xx.c4
-rw-r--r--firmware/target/arm/sandisk/sansa-e200/power-e200.c58
-rw-r--r--firmware/target/coldfire/iaudio/x5/power-x5.c4
-rw-r--r--firmware/target/coldfire/iriver/h100/power-h100.c4
-rw-r--r--firmware/target/coldfire/iriver/h300/power-h300.c4
-rw-r--r--uisimulator/common/fmradio.c6
23 files changed, 559 insertions, 398 deletions
diff --git a/apps/debug_menu.c b/apps/debug_menu.c
index 20dbf76b66..9c426c2efc 100644
--- a/apps/debug_menu.c
+++ b/apps/debug_menu.c
@@ -1955,27 +1955,27 @@ static int radio_callback(int btn, struct gui_synclist *lists)
1955 "HW detected: yes"); 1955 "HW detected: yes");
1956#if (CONFIG_TUNER & LV24020LP) 1956#if (CONFIG_TUNER & LV24020LP)
1957 snprintf(debug_list_messages[radio_lines++], DEBUG_MSG_LEN, 1957 snprintf(debug_list_messages[radio_lines++], DEBUG_MSG_LEN,
1958 "CTRL_STAT: %02X", sanyo_get(RADIO_ALL) ); 1958 "CTRL_STAT: %02X", lv24020lp_get(LV24020LP_CTRL_STAT) );
1959 snprintf(debug_list_messages[radio_lines++], DEBUG_MSG_LEN, 1959 snprintf(debug_list_messages[radio_lines++], DEBUG_MSG_LEN,
1960 "RADIO_STAT: %02X", sanyo_get(RADIO_REG_STAT)); 1960 "RADIO_STAT: %02X", lv24020lp_get(LV24020LP_REG_STAT));
1961 snprintf(debug_list_messages[radio_lines++], DEBUG_MSG_LEN, 1961 snprintf(debug_list_messages[radio_lines++], DEBUG_MSG_LEN,
1962 "MSS_FM: %d kHz", sanyo_get(RADIO_MSS_FM) ); 1962 "MSS_FM: %d kHz", lv24020lp_get(LV24020LP_MSS_FM) );
1963 snprintf(debug_list_messages[radio_lines++], DEBUG_MSG_LEN, 1963 snprintf(debug_list_messages[radio_lines++], DEBUG_MSG_LEN,
1964 "MSS_IF: %d Hz", (sanyo_get(RADIO_MSS_IF) ) ); 1964 "MSS_IF: %d Hz", (lv24020lp_get(LV24020LP_MSS_IF) ) );
1965 snprintf(debug_list_messages[radio_lines++], DEBUG_MSG_LEN, 1965 snprintf(debug_list_messages[radio_lines++], DEBUG_MSG_LEN,
1966 "MSS_SD: %d Hz", (sanyo_get(RADIO_MSS_SD) ) ); 1966 "MSS_SD: %d Hz", (lv24020lp_get(LV24020LP_MSS_SD) ) );
1967 snprintf(debug_list_messages[radio_lines++], DEBUG_MSG_LEN, 1967 snprintf(debug_list_messages[radio_lines++], DEBUG_MSG_LEN,
1968 "if_set: %d Hz", (sanyo_get(RADIO_IF_SET) ) ); 1968 "if_set: %d Hz", (lv24020lp_get(LV24020LP_IF_SET) ) );
1969 snprintf(debug_list_messages[radio_lines++], DEBUG_MSG_LEN, 1969 snprintf(debug_list_messages[radio_lines++], DEBUG_MSG_LEN,
1970 "sd_set: %d Hz", (sanyo_get(RADIO_SD_SET) ) ); 1970 "sd_set: %d Hz", (lv24020lp_get(LV24020LP_SD_SET) ) );
1971#endif 1971#endif
1972#if (CONFIG_TUNER & S1A0903X01) 1972#if (CONFIG_TUNER & S1A0903X01)
1973 snprintf(debug_list_messages[radio_lines++], DEBUG_MSG_LEN, 1973 snprintf(debug_list_messages[radio_lines++], DEBUG_MSG_LEN,
1974 "Samsung regs: %08X", samsung_get(RADIO_ALL)); 1974 "Samsung regs: %08X", s1a0903x01_get(RADIO_ALL));
1975#endif 1975#endif
1976#if (CONFIG_TUNER & TEA5767) 1976#if (CONFIG_TUNER & TEA5767)
1977 struct philips_dbg_info info; 1977 struct tea5767_dbg_info info;
1978 philips_dbg_info(&info); 1978 tea5767_dbg_info(&info);
1979 snprintf(debug_list_messages[radio_lines++], DEBUG_MSG_LEN, "Philips regs:"); 1979 snprintf(debug_list_messages[radio_lines++], DEBUG_MSG_LEN, "Philips regs:");
1980 snprintf(debug_list_messages[radio_lines++], DEBUG_MSG_LEN, 1980 snprintf(debug_list_messages[radio_lines++], DEBUG_MSG_LEN,
1981 " Read: %02X %02X %02X %02X %02X", 1981 " Read: %02X %02X %02X %02X %02X",
diff --git a/apps/recorder/radio.c b/apps/recorder/radio.c
index 0633289826..c15f5196ec 100644
--- a/apps/recorder/radio.c
+++ b/apps/recorder/radio.c
@@ -102,18 +102,6 @@
102#define RADIO_SCAN_MODE 0 102#define RADIO_SCAN_MODE 0
103#define RADIO_PRESET_MODE 1 103#define RADIO_PRESET_MODE 1
104 104
105static const struct fm_region_setting fm_region[] = {
106 /* Note: Desriptive strings are just for display atm and are not compiled. */
107 [REGION_EUROPE] =
108 FM_REGION_ENTRY("Europe", 87500000, 108000000, 50000, 0, 0),
109 [REGION_US_CANADA] =
110 FM_REGION_ENTRY("US/Canada", 87900000, 107900000, 200000, 1, 0),
111 [REGION_JAPAN] =
112 FM_REGION_ENTRY("Japan", 76000000, 90000000, 100000, 0, 1),
113 [REGION_KOREA] =
114 FM_REGION_ENTRY("Korea", 87500000, 108000000, 100000, 0, 0),
115 };
116
117static int curr_preset = -1; 105static int curr_preset = -1;
118static int curr_freq; 106static int curr_freq;
119static int radio_mode = RADIO_SCAN_MODE; 107static int radio_mode = RADIO_SCAN_MODE;
@@ -176,66 +164,57 @@ bool in_radio_screen(void)
176#define FMRADIO_START_PAUSED 0x8000 164#define FMRADIO_START_PAUSED 0x8000
177void radio_start(void) 165void radio_start(void)
178{ 166{
179 const struct fm_region_setting *fmr; 167 const struct fm_region_data *fmr;
180 bool start_paused; 168 bool start_paused;
181#if CONFIG_TUNER != LV24020LP
182 int mute_timeout;
183#endif
184 169
185 if(radio_status == FMRADIO_PLAYING) 170 if(radio_status == FMRADIO_PLAYING)
186 return; 171 return;
187 172
188 fmr = &fm_region[global_settings.fm_region]; 173 fmr = &fm_region_data[global_settings.fm_region];
189 174
190 start_paused = radio_status & FMRADIO_START_PAUSED; 175 start_paused = radio_status & FMRADIO_START_PAUSED;
191 /* clear flag before any yielding */ 176 /* clear flag before any yielding */
192 radio_status &= ~FMRADIO_START_PAUSED; 177 radio_status &= ~FMRADIO_START_PAUSED;
193 178
194 if(radio_status == FMRADIO_OFF) 179 if(radio_status == FMRADIO_OFF)
195 radio_power(true); 180 tuner_power(true);
196 181
197 curr_freq = global_status.last_frequency 182 curr_freq = global_status.last_frequency
198 * fmr->freq_step + fmr->freq_min; 183 * fmr->freq_step + fmr->freq_min;
199 184
200 radio_set(RADIO_SLEEP, 0); /* wake up the tuner */ 185 tuner_set(RADIO_SLEEP, 0); /* wake up the tuner */
201#if (CONFIG_TUNER & LV24020LP)
202 radio_set(RADIO_REGION, global_settings.fm_region);
203 radio_set(RADIO_FORCE_MONO, global_settings.fm_force_mono);
204#endif
205 radio_set(RADIO_FREQUENCY, curr_freq);
206
207#if CONFIG_TUNER != LV24020LP
208 186
209 if(radio_status == FMRADIO_OFF) 187 if(radio_status == FMRADIO_OFF)
210 { 188 {
211#if (CONFIG_TUNER & S1A0903X01) 189#ifdef HAVE_RADIO_REGION
212 radio_set(RADIO_IF_MEASUREMENT, 0); 190 tuner_set(RADIO_REGION, global_settings.fm_region);
213 radio_set(RADIO_SENSITIVITY, 0);
214#endif
215 radio_set(RADIO_FORCE_MONO, global_settings.fm_force_mono);
216#if (CONFIG_TUNER & TEA5767)
217 radio_set(RADIO_SET_DEEMPHASIS, fmr->deemphasis);
218 radio_set(RADIO_SET_BAND, fmr->band);
219#endif 191#endif
220 mute_timeout = current_tick + 1*HZ; 192 tuner_set(RADIO_FORCE_MONO, global_settings.fm_force_mono);
221 }
222 else
223 {
224 /* paused */
225 mute_timeout = current_tick + 2*HZ;
226 } 193 }
227 194
228 while(!radio_get(RADIO_STEREO) && !radio_get(RADIO_TUNED)) 195 tuner_set(RADIO_FREQUENCY, curr_freq);
196
197#ifdef HAVE_RADIO_MUTE_TIMEOUT
229 { 198 {
230 if(TIME_AFTER(current_tick, mute_timeout)) 199 unsigned long mute_timeout = current_tick + HZ;
231 break; 200 if (radio_status != FMRADIO_OFF)
232 yield(); 201 {
202 /* paused */
203 mute_timeout += HZ;
204 }
205
206 while(!tuner_get(RADIO_STEREO) && !tuner_get(RADIO_TUNED))
207 {
208 if(TIME_AFTER(current_tick, mute_timeout))
209 break;
210 yield();
211 }
233 } 212 }
234#endif /* CONFIG_TUNER != LV24020LP */ 213#endif
235 214
236 /* keep radio from sounding initially */ 215 /* keep radio from sounding initially */
237 if(!start_paused) 216 if(!start_paused)
238 radio_set(RADIO_MUTE, 0); 217 tuner_set(RADIO_MUTE, 0);
239 218
240 radio_status = FMRADIO_PLAYING; 219 radio_status = FMRADIO_PLAYING;
241} /* radio_start */ 220} /* radio_start */
@@ -251,8 +230,8 @@ void radio_pause(void)
251 radio_start(); 230 radio_start();
252 } 231 }
253 232
254 radio_set(RADIO_MUTE, 1); 233 tuner_set(RADIO_MUTE, 1);
255 radio_set(RADIO_SLEEP, 1); 234 tuner_set(RADIO_SLEEP, 1);
256 235
257 radio_status = FMRADIO_PAUSED; 236 radio_status = FMRADIO_PAUSED;
258} /* radio_pause */ 237} /* radio_pause */
@@ -262,30 +241,22 @@ void radio_stop(void)
262 if(radio_status == FMRADIO_OFF) 241 if(radio_status == FMRADIO_OFF)
263 return; 242 return;
264 243
265 radio_set(RADIO_MUTE, 1); 244 tuner_set(RADIO_MUTE, 1);
266 radio_set(RADIO_SLEEP, 1); /* low power mode, if available */ 245 tuner_set(RADIO_SLEEP, 1); /* low power mode, if available */
267 radio_status = FMRADIO_OFF; 246 radio_status = FMRADIO_OFF;
268 radio_power(false); /* status update, power off if avail. */ 247 tuner_power(false); /* status update, power off if avail. */
269} /* radio_stop */ 248} /* radio_stop */
270 249
271bool radio_hardware_present(void) 250bool radio_hardware_present(void)
272{ 251{
273#ifdef HAVE_TUNER_PWR_CTRL 252 return tuner_get(RADIO_PRESENT);
274 bool ret;
275 bool fmstatus = radio_power(true); /* power it up */
276 ret = radio_get(RADIO_PRESENT);
277 radio_power(fmstatus); /* restore previous state */
278 return ret;
279#else
280 return radio_get(RADIO_PRESENT);
281#endif
282} 253}
283 254
284/* Keep freq on the grid for the current region */ 255/* Keep freq on the grid for the current region */
285static int snap_freq_to_grid(int freq) 256static int snap_freq_to_grid(int freq)
286{ 257{
287 const struct fm_region_setting * const fmr = 258 const struct fm_region_data * const fmr =
288 &fm_region[global_settings.fm_region]; 259 &fm_region_data[global_settings.fm_region];
289 260
290 /* Range clamp if out of range or just round to nearest */ 261 /* Range clamp if out of range or just round to nearest */
291 if (freq < fmr->freq_min) 262 if (freq < fmr->freq_min)
@@ -346,9 +317,8 @@ static int find_closest_preset(int freq, int direction)
346 317
347static void remember_frequency(void) 318static void remember_frequency(void)
348{ 319{
349 const struct fm_region_setting * const fmr = 320 const struct fm_region_data * const fmr =
350 &fm_region[global_settings.fm_region]; 321 &fm_region_data[global_settings.fm_region];
351
352 global_status.last_frequency = (curr_freq - fmr->freq_min) 322 global_status.last_frequency = (curr_freq - fmr->freq_min)
353 / fmr->freq_step; 323 / fmr->freq_step;
354 status_save(); 324 status_save();
@@ -367,15 +337,15 @@ static void next_preset(int direction)
367 /* Must stay on the current grid for the region */ 337 /* Must stay on the current grid for the region */
368 curr_freq = snap_freq_to_grid(presets[curr_preset].frequency); 338 curr_freq = snap_freq_to_grid(presets[curr_preset].frequency);
369 339
370 radio_set(RADIO_FREQUENCY, curr_freq); 340 tuner_set(RADIO_FREQUENCY, curr_freq);
371 remember_frequency(); 341 remember_frequency();
372} 342}
373 343
374/* Step to the next or previous frequency */ 344/* Step to the next or previous frequency */
375static int step_freq(int freq, int direction) 345static int step_freq(int freq, int direction)
376{ 346{
377 const struct fm_region_setting * const fmr = 347 const struct fm_region_data * const fmr =
378 &fm_region[global_settings.fm_region]; 348 &fm_region_data[global_settings.fm_region];
379 349
380 freq += direction*fmr->freq_step; 350 freq += direction*fmr->freq_step;
381 351
@@ -402,12 +372,12 @@ static void next_station(int direction)
402 curr_freq = step_freq(curr_freq, direction); 372 curr_freq = step_freq(curr_freq, direction);
403 373
404 if (radio_status == FMRADIO_PLAYING) 374 if (radio_status == FMRADIO_PLAYING)
405 radio_set(RADIO_MUTE, 1); 375 tuner_set(RADIO_MUTE, 1);
406 376
407 radio_set(RADIO_FREQUENCY, curr_freq); 377 tuner_set(RADIO_FREQUENCY, curr_freq);
408 378
409 if (radio_status == FMRADIO_PLAYING) 379 if (radio_status == FMRADIO_PLAYING)
410 radio_set(RADIO_MUTE, 0); 380 tuner_set(RADIO_MUTE, 0);
411 381
412 curr_preset = find_preset(curr_freq); 382 curr_preset = find_preset(curr_freq);
413 remember_frequency(); 383 remember_frequency();
@@ -417,7 +387,7 @@ static void next_station(int direction)
417static void end_search(void) 387static void end_search(void)
418{ 388{
419 if (search_dir != 0 && radio_status == FMRADIO_PLAYING) 389 if (search_dir != 0 && radio_status == FMRADIO_PLAYING)
420 radio_set(RADIO_MUTE, 0); 390 tuner_set(RADIO_MUTE, 0);
421 search_dir = 0; 391 search_dir = 0;
422} 392}
423 393
@@ -540,7 +510,7 @@ int radio_screen(void)
540 curr_freq = step_freq(curr_freq, search_dir); 510 curr_freq = step_freq(curr_freq, search_dir);
541 update_screen = true; 511 update_screen = true;
542 512
543 if(radio_set(RADIO_SCAN_FREQUENCY, curr_freq)) 513 if(tuner_set(RADIO_SCAN_FREQUENCY, curr_freq))
544 { 514 {
545 curr_preset = find_preset(curr_freq); 515 curr_preset = find_preset(curr_freq);
546 remember_frequency(); 516 remember_frequency();
@@ -671,7 +641,7 @@ int radio_screen(void)
671 else if (dir == 0) 641 else if (dir == 0)
672 { 642 {
673 /* Starting auto scan */ 643 /* Starting auto scan */
674 radio_set(RADIO_MUTE, 1); 644 tuner_set(RADIO_MUTE, 1);
675 update_screen = true; 645 update_screen = true;
676 } 646 }
677 break; 647 break;
@@ -847,7 +817,7 @@ int radio_screen(void)
847 /* keep "mono" from always being displayed when paused */ 817 /* keep "mono" from always being displayed when paused */
848 if (radio_status != FMRADIO_PAUSED) 818 if (radio_status != FMRADIO_PAUSED)
849 { 819 {
850 stereo = radio_get(RADIO_STEREO) && 820 stereo = tuner_get(RADIO_STEREO) &&
851 !global_settings.fm_force_mono; 821 !global_settings.fm_force_mono;
852 822
853 if(stereo != last_stereo) 823 if(stereo != last_stereo)
@@ -1329,21 +1299,12 @@ static int handle_radio_presets(void)
1329 1299
1330void toggle_mono_mode(bool mono) 1300void toggle_mono_mode(bool mono)
1331{ 1301{
1332 radio_set(RADIO_FORCE_MONO, mono); 1302 tuner_set(RADIO_FORCE_MONO, mono);
1333} 1303}
1334 1304
1335void set_radio_region(int region) 1305void set_radio_region(int region)
1336{ 1306{
1337#if (CONFIG_TUNER & LV24020LP) 1307 tuner_set(RADIO_REGION, region);
1338 radio_set(RADIO_REGION, global_settings.fm_region);
1339#endif
1340#if (CONFIG_TUNER & TEA5767)
1341 radio_set(RADIO_SET_DEEMPHASIS,
1342 fm_region[region].deemphasis);
1343 radio_set(RADIO_SET_BAND, fm_region[region].band);
1344#else
1345 (void)region;
1346#endif
1347 next_station(0); 1308 next_station(0);
1348 remember_frequency(); 1309 remember_frequency();
1349} 1310}
@@ -1381,15 +1342,16 @@ static int scan_presets(void)
1381 1342
1382 if(do_scan) 1343 if(do_scan)
1383 { 1344 {
1384 const struct fm_region_setting * const fmr = 1345 const struct fm_region_data * const fmr =
1385 &fm_region[global_settings.fm_region]; 1346 &fm_region_data[global_settings.fm_region];
1347
1386 char buf[MAX_FMPRESET_LEN + 1]; 1348 char buf[MAX_FMPRESET_LEN + 1];
1387 int i; 1349 int i;
1388 1350
1389 curr_freq = fmr->freq_min; 1351 curr_freq = fmr->freq_min;
1390 num_presets = 0; 1352 num_presets = 0;
1391 memset(presets, 0, sizeof(presets)); 1353 memset(presets, 0, sizeof(presets));
1392 radio_set(RADIO_MUTE, 1); 1354 tuner_set(RADIO_MUTE, 1);
1393 1355
1394 while(curr_freq <= fmr->freq_max) 1356 while(curr_freq <= fmr->freq_max)
1395 { 1357 {
@@ -1404,7 +1366,7 @@ static int scan_presets(void)
1404 snprintf(buf, MAX_FMPRESET_LEN, str(LANG_FM_SCANNING), freq, frac); 1366 snprintf(buf, MAX_FMPRESET_LEN, str(LANG_FM_SCANNING), freq, frac);
1405 gui_syncsplash(0, buf); 1367 gui_syncsplash(0, buf);
1406 1368
1407 if(radio_set(RADIO_SCAN_FREQUENCY, curr_freq)) 1369 if(tuner_set(RADIO_SCAN_FREQUENCY, curr_freq))
1408 { 1370 {
1409 /* add preset */ 1371 /* add preset */
1410 snprintf(buf, MAX_FMPRESET_LEN, 1372 snprintf(buf, MAX_FMPRESET_LEN,
@@ -1418,7 +1380,7 @@ static int scan_presets(void)
1418 } 1380 }
1419 1381
1420 if (radio_status == FMRADIO_PLAYING) 1382 if (radio_status == FMRADIO_PLAYING)
1421 radio_set(RADIO_MUTE, 0); 1383 tuner_set(RADIO_MUTE, 0);
1422 1384
1423 presets_changed = true; 1385 presets_changed = true;
1424 1386
diff --git a/apps/recorder/radio.h b/apps/recorder/radio.h
index f04c14d6d3..c456d3a6a3 100644
--- a/apps/recorder/radio.h
+++ b/apps/recorder/radio.h
@@ -44,23 +44,6 @@ struct fmstation
44 char name[MAX_FMPRESET_LEN+1]; 44 char name[MAX_FMPRESET_LEN+1];
45}; 45};
46 46
47struct fm_region_setting 47#endif /* CONFIG_TUNER */
48{
49 int freq_min;
50 int freq_max;
51 int freq_step;
52#if (CONFIG_TUNER & TEA5767)
53 char deemphasis; /* 0: 50us, 1: 75us */
54 char band; /* 0: europe, 1: japan (BL in TEA spec)*/
55 /* Note: "region" parameter is just for display atm and is not compiled. */
56 #define FM_REGION_ENTRY(region, fmin, fmax, fstep, deemph, band) \
57 { fmin, fmax, fstep, deemph, band }
58#else
59 #define FM_REGION_ENTRY(region, fmin, fmax, fstep, deemph, band) \
60 { fmin, fmax, fstep }
61#endif
62};
63 48
64#endif 49#endif /* RADIO_H */
65
66#endif
diff --git a/firmware/SOURCES b/firmware/SOURCES
index 7e26ca0bc4..2db8e9e568 100644
--- a/firmware/SOURCES
+++ b/firmware/SOURCES
@@ -151,17 +151,18 @@ drivers/rtc/rtc_as3514.c
151/* Tuner */ 151/* Tuner */
152#if CONFIG_TUNER 152#if CONFIG_TUNER
153#ifndef SIMULATOR 153#ifndef SIMULATOR
154tuner.c
155#if (CONFIG_TUNER & LV24020LP)
156drivers/tuner/lv24020lp.c
157#endif /* (CONFIG_TUNER & LV24020LP) */
154#if (CONFIG_TUNER & S1A0903X01) 158#if (CONFIG_TUNER & S1A0903X01)
155drivers/fmradio.c 159drivers/fmradio.c
156tuner_samsung.c 160drivers/tuner/s1a0903x01.c
157#endif /* (CONFIG_TUNER & S1A0903X01) */ 161#endif /* (CONFIG_TUNER & S1A0903X01) */
158#if (CONFIG_TUNER & TEA5767) 162#if (CONFIG_TUNER & TEA5767)
159drivers/fmradio_i2c.c 163drivers/fmradio_i2c.c
160tuner_philips.c 164drivers/tuner/tea5767.c
161#endif /* (CONFIG_TUNER & TEA5767) */ 165#endif /* (CONFIG_TUNER & TEA5767) */
162#if (CONFIG_TUNER & LV24020LP)
163tuner_sanyo.c
164#endif /* (CONFIG_TUNER & LV24020LP) */
165#endif /*SIMULATOR */ 166#endif /*SIMULATOR */
166#endif /* CONFIG_TUNER */ 167#endif /* CONFIG_TUNER */
167 168
diff --git a/firmware/drivers/power.c b/firmware/drivers/power.c
index eb69fcec27..50117dd321 100644
--- a/firmware/drivers/power.c
+++ b/firmware/drivers/power.c
@@ -37,12 +37,12 @@ bool charger_enabled;
37 37
38static bool powered = false; 38static bool powered = false;
39 39
40bool radio_powered(void) 40bool tuner_powered(void)
41{ 41{
42 return powered; 42 return powered;
43} 43}
44 44
45bool radio_power(bool status) 45bool tuner_power(bool status)
46{ 46{
47 bool old_status = powered; 47 bool old_status = powered;
48 powered = status; 48 powered = status;
diff --git a/firmware/tuner_sanyo.c b/firmware/drivers/tuner/lv24020lp.c
index 6e732975b6..9ec68f9a27 100644
--- a/firmware/tuner_sanyo.c
+++ b/firmware/drivers/tuner/lv24020lp.c
@@ -25,11 +25,9 @@
25#include "kernel.h" 25#include "kernel.h"
26#include "tuner.h" /* tuner abstraction interface */ 26#include "tuner.h" /* tuner abstraction interface */
27#include "fmradio.h" /* physical interface driver */ 27#include "fmradio.h" /* physical interface driver */
28#include "mpeg.h"
29#include "sound.h" 28#include "sound.h"
30#include "pp5024.h" 29#include "pp5024.h"
31#include "system.h" 30#include "system.h"
32#include "as3514.h"
33 31
34#ifndef BOOTLOADER 32#ifndef BOOTLOADER
35 33
@@ -234,7 +232,7 @@ static int fd_log = -1;
234#define TUNER_PRESENCE_CHECKED (1 << 3) 232#define TUNER_PRESENCE_CHECKED (1 << 3)
235static unsigned tuner_status = 0; 233static unsigned tuner_status = 0;
236 234
237static unsigned char sanyo_regs[0x1c]; 235static unsigned char lv24020lp_regs[0x1c];
238 236
239static const int sw_osc_low = 10; /* 30; */ 237static const int sw_osc_low = 10; /* 30; */
240static const int sw_osc_high = 240; /* 200; */ 238static const int sw_osc_high = 240; /* 200; */
@@ -253,7 +251,7 @@ static inline bool tuner_awake(void)
253} 251}
254 252
255/* send a byte to the tuner - expects write mode to be current */ 253/* send a byte to the tuner - expects write mode to be current */
256static void tuner_sanyo_send_byte(unsigned int byte) 254static void lv24020lp_send_byte(unsigned int byte)
257{ 255{
258 int i; 256 int i;
259 257
@@ -274,7 +272,7 @@ static void tuner_sanyo_send_byte(unsigned int byte)
274} 272}
275 273
276/* end a write cycle on the tuner */ 274/* end a write cycle on the tuner */
277static void tuner_sanyo_end_write(void) 275static void lv24020lp_end_write(void)
278{ 276{
279 /* switch back to read mode */ 277 /* switch back to read mode */
280 GPIOH_OUTPUT_EN &= ~(1 << FM_DATA_PIN); 278 GPIOH_OUTPUT_EN &= ~(1 << FM_DATA_PIN);
@@ -282,7 +280,7 @@ static void tuner_sanyo_end_write(void)
282} 280}
283 281
284/* prepare a write cycle on the tuner */ 282/* prepare a write cycle on the tuner */
285static unsigned int tuner_sanyo_begin_write(unsigned int address) 283static unsigned int lv24020lp_begin_write(unsigned int address)
286{ 284{
287 /* Get register's block, translate address */ 285 /* Get register's block, translate address */
288 unsigned int blk = (address >= BLK2_START) ? 286 unsigned int blk = (address >= BLK2_START) ?
@@ -297,29 +295,29 @@ static unsigned int tuner_sanyo_begin_write(unsigned int address)
297 udelay(FM_CLK_DELAY); 295 udelay(FM_CLK_DELAY);
298 296
299 /* current block == register block? */ 297 /* current block == register block? */
300 if (blk == sanyo_regs[BLK_SEL]) 298 if (blk == lv24020lp_regs[BLK_SEL])
301 return address; 299 return address;
302 300
303 /* switch block */ 301 /* switch block */
304 sanyo_regs[BLK_SEL] = blk; 302 lv24020lp_regs[BLK_SEL] = blk;
305 303
306 /* data first */ 304 /* data first */
307 tuner_sanyo_send_byte(blk); 305 lv24020lp_send_byte(blk);
308 /* then address */ 306 /* then address */
309 tuner_sanyo_send_byte(BLK_SEL); 307 lv24020lp_send_byte(BLK_SEL);
310 308
311 tuner_sanyo_end_write(); 309 lv24020lp_end_write();
312 310
313 udelay(FM_CLK_DELAY); 311 udelay(FM_CLK_DELAY);
314 } 312 }
315} 313}
316 314
317/* write a byte to a tuner register */ 315/* write a byte to a tuner register */
318static void tuner_sanyo_write(unsigned int address, unsigned int data) 316static void lv24020lp_write(unsigned int address, unsigned int data)
319{ 317{
320 /* shadow logical values but do logical=>physical remappings on some 318 /* shadow logical values but do logical=>physical remappings on some
321 registers' data. */ 319 registers' data. */
322 sanyo_regs[address] = data; 320 lv24020lp_regs[address] = data;
323 321
324 switch (address) 322 switch (address)
325 { 323 {
@@ -340,39 +338,39 @@ static void tuner_sanyo_write(unsigned int address, unsigned int data)
340 break; 338 break;
341 } 339 }
342 340
343 address = tuner_sanyo_begin_write(address); 341 address = lv24020lp_begin_write(address);
344 342
345 /* data first */ 343 /* data first */
346 tuner_sanyo_send_byte(data); 344 lv24020lp_send_byte(data);
347 /* then address */ 345 /* then address */
348 tuner_sanyo_send_byte(address); 346 lv24020lp_send_byte(address);
349 347
350 tuner_sanyo_end_write(); 348 lv24020lp_end_write();
351} 349}
352 350
353/* helpers to set/clear register bits */ 351/* helpers to set/clear register bits */
354static void tuner_sanyo_write_or(unsigned int address, unsigned int bits) 352static void lv24020lp_write_or(unsigned int address, unsigned int bits)
355{ 353{
356 tuner_sanyo_write(address, sanyo_regs[address] | bits); 354 lv24020lp_write(address, lv24020lp_regs[address] | bits);
357} 355}
358 356
359static void tuner_sanyo_write_and(unsigned int address, unsigned int bits) 357static void lv24020lp_write_and(unsigned int address, unsigned int bits)
360{ 358{
361 tuner_sanyo_write(address, sanyo_regs[address] & bits); 359 lv24020lp_write(address, lv24020lp_regs[address] & bits);
362} 360}
363 361
364/* read a byte from a tuner register */ 362/* read a byte from a tuner register */
365static unsigned int tuner_sanyo_read(unsigned int address) 363static unsigned int lv24020lp_read(unsigned int address)
366{ 364{
367 int i; 365 int i;
368 unsigned int toread; 366 unsigned int toread;
369 367
370 address = tuner_sanyo_begin_write(address); 368 address = lv24020lp_begin_write(address);
371 369
372 /* address */ 370 /* address */
373 tuner_sanyo_send_byte(address); 371 lv24020lp_send_byte(address);
374 372
375 tuner_sanyo_end_write(); 373 lv24020lp_end_write();
376 374
377 /* data */ 375 /* data */
378 toread = 0; 376 toread = 0;
@@ -392,7 +390,7 @@ static unsigned int tuner_sanyo_read(unsigned int address)
392/* enables auto frequency centering */ 390/* enables auto frequency centering */
393static void enable_afc(bool enabled) 391static void enable_afc(bool enabled)
394{ 392{
395 unsigned int radio_ctrl1 = sanyo_regs[RADIO_CTRL1]; 393 unsigned int radio_ctrl1 = lv24020lp_regs[RADIO_CTRL1];
396 394
397 if (enabled) 395 if (enabled)
398 { 396 {
@@ -405,7 +403,7 @@ static void enable_afc(bool enabled)
405 radio_ctrl1 &= ~EN_AFC; 403 radio_ctrl1 &= ~EN_AFC;
406 } 404 }
407 405
408 tuner_sanyo_write(RADIO_CTRL1, radio_ctrl1); 406 lv24020lp_write(RADIO_CTRL1, radio_ctrl1);
409} 407}
410 408
411static int calculate_coef(unsigned fkhz) 409static int calculate_coef(unsigned fkhz)
@@ -439,25 +437,25 @@ static int tuner_measure(unsigned char type, int scale, int duration)
439 return 0; 437 return 0;
440 438
441 /* enable measuring */ 439 /* enable measuring */
442 tuner_sanyo_write_or(MSRC_SEL, type); 440 lv24020lp_write_or(MSRC_SEL, type);
443 tuner_sanyo_write_and(CNT_CTRL, ~CNT_SEL); 441 lv24020lp_write_and(CNT_CTRL, ~CNT_SEL);
444 tuner_sanyo_write_or(RADIO_CTRL1, EN_MEAS); 442 lv24020lp_write_or(RADIO_CTRL1, EN_MEAS);
445 443
446 /* reset counter */ 444 /* reset counter */
447 tuner_sanyo_write_or(CNT_CTRL, CNT1_CLR); 445 lv24020lp_write_or(CNT_CTRL, CNT1_CLR);
448 tuner_sanyo_write_and(CNT_CTRL, ~CNT1_CLR); 446 lv24020lp_write_and(CNT_CTRL, ~CNT1_CLR);
449 447
450 /* start counter, delay for specified time and stop it */ 448 /* start counter, delay for specified time and stop it */
451 tuner_sanyo_write_or(CNT_CTRL, CNT_EN); 449 lv24020lp_write_or(CNT_CTRL, CNT_EN);
452 udelay(duration*1000 - 16); 450 udelay(duration*1000 - 16);
453 tuner_sanyo_write_and(CNT_CTRL, ~CNT_EN); 451 lv24020lp_write_and(CNT_CTRL, ~CNT_EN);
454 452
455 /* read tick count */ 453 /* read tick count */
456 finval = (tuner_sanyo_read(CNT_H) << 8) | tuner_sanyo_read(CNT_L); 454 finval = (lv24020lp_read(CNT_H) << 8) | lv24020lp_read(CNT_L);
457 455
458 /* restore measure mode */ 456 /* restore measure mode */
459 tuner_sanyo_write_and(RADIO_CTRL1, ~EN_MEAS); 457 lv24020lp_write_and(RADIO_CTRL1, ~EN_MEAS);
460 tuner_sanyo_write_and(MSRC_SEL, ~type); 458 lv24020lp_write_and(MSRC_SEL, ~type);
461 459
462 /* convert value */ 460 /* convert value */
463 if (type == MSS_FM) 461 if (type == MSS_FM)
@@ -469,7 +467,7 @@ static int tuner_measure(unsigned char type, int scale, int duration)
469} 467}
470 468
471/* set the FM oscillator frequency */ 469/* set the FM oscillator frequency */
472static void sanyo_set_frequency(int freq) 470static void set_frequency(int freq)
473{ 471{
474 int coef, cap_value, osc_value; 472 int coef, cap_value, osc_value;
475 int f1, f2, x1, x2; 473 int f1, f2, x1, x2;
@@ -494,7 +492,7 @@ static void sanyo_set_frequency(int freq)
494 coef_00, coef_01); 492 coef_00, coef_01);
495 493
496 osc_value = sw_osc_low; 494 osc_value = sw_osc_low;
497 tuner_sanyo_write(FM_OSC, osc_value); 495 lv24020lp_write(FM_OSC, osc_value);
498 496
499 /* Just in case - don't go into infinite loop */ 497 /* Just in case - don't go into infinite loop */
500 for (count = 0; count < 30; count++) 498 for (count = 0; count < 30; count++)
@@ -505,7 +503,7 @@ static void sanyo_set_frequency(int freq)
505 coef_10, coef_11); 503 coef_10, coef_11);
506 int coef_fcur, cap_new, coef_cor, range; 504 int coef_fcur, cap_new, coef_cor, range;
507 505
508 tuner_sanyo_write(FM_CAP, cap_value); 506 lv24020lp_write(FM_CAP, cap_value);
509 507
510 range = y1 - y0; 508 range = y1 - y0;
511 f1 = tuner_measure(MSS_FM, 1, 16); 509 f1 = tuner_measure(MSS_FM, 1, 16);
@@ -554,7 +552,7 @@ static void sanyo_set_frequency(int freq)
554 { 552 {
555 int x2_new; 553 int x2_new;
556 554
557 tuner_sanyo_write(FM_OSC, x2); 555 lv24020lp_write(FM_OSC, x2);
558 f2 = tuner_measure(MSS_FM, 1, 16); 556 f2 = tuner_measure(MSS_FM, 1, 16);
559 557
560 if (abs(f2 - freq) <= 16) 558 if (abs(f2 - freq) <= 16)
@@ -632,9 +630,9 @@ static void fine_step_tune(int (*setcmp)(int regval), int regval, int step)
632 630
633static int if_setcmp(int regval) 631static int if_setcmp(int regval)
634{ 632{
635 tuner_sanyo_write(IF_OSC, regval); 633 lv24020lp_write(IF_OSC, regval);
636 tuner_sanyo_write(IF_CENTER, regval); 634 lv24020lp_write(IF_CENTER, regval);
637 tuner_sanyo_write(IF_BW, 65*regval/100); 635 lv24020lp_write(IF_BW, 65*regval/100);
638 636
639 if_set = tuner_measure(MSS_IF, 1000, 32); 637 if_set = tuner_measure(MSS_IF, 1000, 32);
640 638
@@ -649,7 +647,7 @@ static int if_setcmp(int regval)
649 647
650static int sd_setcmp(int regval) 648static int sd_setcmp(int regval)
651{ 649{
652 tuner_sanyo_write(SD_OSC, regval); 650 lv24020lp_write(SD_OSC, regval);
653 651
654 sd_set = tuner_measure(MSS_SD, 1000, 32); 652 sd_set = tuner_measure(MSS_SD, 1000, 32);
655 653
@@ -659,7 +657,7 @@ static int sd_setcmp(int regval)
659 return sd_set < 38300 ? -1 : 1; 657 return sd_set < 38300 ? -1 : 1;
660} 658}
661 659
662static void sanyo_sleep(bool sleep) 660static void set_sleep(bool sleep)
663{ 661{
664 if (sleep || tuner_awake()) 662 if (sleep || tuner_awake())
665 return; 663 return;
@@ -673,41 +671,41 @@ static void sanyo_sleep(bool sleep)
673 enable_afc(false); 671 enable_afc(false);
674 672
675 /* 2. Calibrate the IF frequency at 110 kHz: */ 673 /* 2. Calibrate the IF frequency at 110 kHz: */
676 tuner_sanyo_write_and(RADIO_CTRL2, ~IF_PM_L); 674 lv24020lp_write_and(RADIO_CTRL2, ~IF_PM_L);
677 fine_step_tune(if_setcmp, 0x80, 8); 675 fine_step_tune(if_setcmp, 0x80, 8);
678 tuner_sanyo_write_or(RADIO_CTRL2, IF_PM_L); 676 lv24020lp_write_or(RADIO_CTRL2, IF_PM_L);
679 677
680 /* 3. Calibrate the stereo decoder clock at 38.3 kHz: */ 678 /* 3. Calibrate the stereo decoder clock at 38.3 kHz: */
681 tuner_sanyo_write_or(STEREO_CTRL, SD_PM); 679 lv24020lp_write_or(STEREO_CTRL, SD_PM);
682 fine_step_tune(sd_setcmp, 0x80, 8); 680 fine_step_tune(sd_setcmp, 0x80, 8);
683 tuner_sanyo_write_and(STEREO_CTRL, ~SD_PM); 681 lv24020lp_write_and(STEREO_CTRL, ~SD_PM);
684 682
685 /* calculate FM tuning coefficients */ 683 /* calculate FM tuning coefficients */
686 tuner_sanyo_write(FM_CAP, sw_cap_low); 684 lv24020lp_write(FM_CAP, sw_cap_low);
687 tuner_sanyo_write(FM_OSC, sw_osc_low); 685 lv24020lp_write(FM_OSC, sw_osc_low);
688 coef_00 = calculate_coef(tuner_measure(MSS_FM, 1, 64)); 686 coef_00 = calculate_coef(tuner_measure(MSS_FM, 1, 64));
689 687
690 tuner_sanyo_write(FM_CAP, sw_cap_high); 688 lv24020lp_write(FM_CAP, sw_cap_high);
691 coef_01 = calculate_coef(tuner_measure(MSS_FM, 1, 64)); 689 coef_01 = calculate_coef(tuner_measure(MSS_FM, 1, 64));
692 690
693 tuner_sanyo_write(FM_CAP, sw_cap_low); 691 lv24020lp_write(FM_CAP, sw_cap_low);
694 tuner_sanyo_write(FM_OSC, sw_osc_high); 692 lv24020lp_write(FM_OSC, sw_osc_high);
695 coef_10 = calculate_coef(tuner_measure(MSS_FM, 1, 64)); 693 coef_10 = calculate_coef(tuner_measure(MSS_FM, 1, 64));
696 694
697 tuner_sanyo_write(FM_CAP, sw_cap_high); 695 lv24020lp_write(FM_CAP, sw_cap_high);
698 coef_11 = calculate_coef(tuner_measure(MSS_FM, 1, 64)); 696 coef_11 = calculate_coef(tuner_measure(MSS_FM, 1, 64));
699 697
700 /* set various audio level settings */ 698 /* set various audio level settings */
701 tuner_sanyo_write(AUDIO_CTRL1, TONE_LVL_SET(0) | VOL_LVL_SET(0)); 699 lv24020lp_write(AUDIO_CTRL1, TONE_LVL_SET(0) | VOL_LVL_SET(0));
702 tuner_sanyo_write_or(RADIO_CTRL2, AGCSP); 700 lv24020lp_write_or(RADIO_CTRL2, AGCSP);
703 tuner_sanyo_write_or(RADIO_CTRL3, VOLSH); 701 lv24020lp_write_or(RADIO_CTRL3, VOLSH);
704 tuner_sanyo_write(STEREO_CTRL, FMCS_SET(7) | AUTOSSR); 702 lv24020lp_write(STEREO_CTRL, FMCS_SET(7) | AUTOSSR);
705 tuner_sanyo_write(PW_SCTRL, SS_CTRL_SET(3) | SM_CTRL_SET(1) | 703 lv24020lp_write(PW_SCTRL, SS_CTRL_SET(3) | SM_CTRL_SET(1) |
706 PW_RAD); 704 PW_RAD);
707} 705}
708 706
709/** Public interfaces **/ 707/** Public interfaces **/
710bool radio_power(bool status) 708void lv24020lp_power(bool status)
711{ 709{
712 static const unsigned char tuner_defaults[][2] = 710 static const unsigned char tuner_defaults[][2] =
713 { 711 {
@@ -733,38 +731,13 @@ bool radio_power(bool status)
733 }; 731 };
734 732
735 unsigned i; 733 unsigned i;
736 bool powered = tuner_status & TUNER_POWERED;
737
738 if (status == powered)
739 return powered;
740 734
741 if (status) 735 if (status)
742 { 736 {
743 /* init mystery amplification device */ 737 tuner_status |= TUNER_POWERED | TUNER_PRESENCE_CHECKED;
744 outl(inl(0x70000084) | 0x1, 0x70000084);
745 udelay(5);
746
747 /* When power up, host should initialize the 3-wire bus in host read
748 mode: */
749
750 /* 1. Set direction of the DATA-line to input-mode. */
751 GPIOH_OUTPUT_EN &= ~(1 << FM_DATA_PIN);
752 GPIOH_ENABLE |= (1 << FM_DATA_PIN);
753
754 /* 2. Drive NR_W low */
755 GPIOH_OUTPUT_VAL &= ~(1 << FM_NRW_PIN);
756 GPIOH_OUTPUT_EN |= (1 << FM_NRW_PIN);
757 GPIOH_ENABLE |= (1 << FM_NRW_PIN);
758
759 /* 3. Drive CLOCK high */
760 GPIOH_OUTPUT_VAL |= (1 << FM_CLOCK_PIN);
761 GPIOH_OUTPUT_EN |= (1 << FM_CLOCK_PIN);
762 GPIOH_ENABLE |= (1 << FM_CLOCK_PIN);
763
764 tuner_status |= TUNER_POWERED;
765 738
766 /* if tuner is present, CHIP ID is 0x09 */ 739 /* if tuner is present, CHIP ID is 0x09 */
767 if (tuner_sanyo_read(CHIP_ID) == 0x09) 740 if (lv24020lp_read(CHIP_ID) == 0x09)
768 { 741 {
769 tuner_status |= TUNER_PRESENT; 742 tuner_status |= TUNER_PRESENT;
770 743
@@ -772,9 +745,9 @@ bool radio_power(bool status)
772 follows: */ 745 follows: */
773 746
774 /* 1. Write default values to the registers: */ 747 /* 1. Write default values to the registers: */
775 sanyo_regs[BLK_SEL] = 0; /* Force a switch on the first */ 748 lv24020lp_regs[BLK_SEL] = 0; /* Force a switch on the first */
776 for (i = 0; i < ARRAYLEN(tuner_defaults); i++) 749 for (i = 0; i < ARRAYLEN(tuner_defaults); i++)
777 tuner_sanyo_write(tuner_defaults[i][0], tuner_defaults[i][1]); 750 lv24020lp_write(tuner_defaults[i][0], tuner_defaults[i][1]);
778 751
779 /* Complete the startup calibration if the tuner is woken */ 752 /* Complete the startup calibration if the tuner is woken */
780 udelay(100000); 753 udelay(100000);
@@ -782,76 +755,55 @@ bool radio_power(bool status)
782 } 755 }
783 else 756 else
784 { 757 {
785 /* Power off and set all as inputs */ 758 /* Power off */
786 if (tuner_status & TUNER_PRESENT) 759 if (tuner_status & TUNER_PRESENT)
787 tuner_sanyo_write_and(PW_SCTRL, ~PW_RAD); 760 lv24020lp_write_and(PW_SCTRL, ~PW_RAD);
788
789 GPIOH_OUTPUT_EN &= ~((1 << FM_DATA_PIN) | (1 << FM_NRW_PIN) |
790 (1 << FM_CLOCK_PIN));
791 GPIOH_ENABLE &= ~((1 << FM_DATA_PIN) | (1 << FM_NRW_PIN) |
792 (1 << FM_CLOCK_PIN));
793
794 outl(inl(0x70000084) & ~0x1, 0x70000084);
795 761
796 tuner_status &= ~(TUNER_POWERED | TUNER_AWAKE); 762 tuner_status &= ~(TUNER_POWERED | TUNER_AWAKE);
797 } 763 }
798
799 return powered;
800}
801
802bool radio_powered(void)
803{
804 return (tuner_status & TUNER_POWERED) != 0;
805} 764}
806 765
807int sanyo_set(int setting, int value) 766int lv24020lp_set(int setting, int value)
808{ 767{
809 int val = 1; 768 int val = 1;
810 769
811 switch(setting) 770 switch(setting)
812 { 771 {
813 case RADIO_SLEEP: 772 case RADIO_SLEEP:
814 sanyo_sleep(value); 773 set_sleep(value);
815 break; 774 break;
816 775
817 case RADIO_FREQUENCY: 776 case RADIO_FREQUENCY:
818 sanyo_set_frequency(value); 777 set_frequency(value);
819 break; 778 break;
820 779
821 case RADIO_SCAN_FREQUENCY: 780 case RADIO_SCAN_FREQUENCY:
822 /* TODO: really implement this */ 781 /* TODO: really implement this */
823 sanyo_set_frequency(value); 782 set_frequency(value);
824 val = sanyo_get(RADIO_TUNED); 783 val = lv24020lp_get(RADIO_TUNED);
825 break; 784 break;
826 785
827 case RADIO_MUTE: 786 case RADIO_MUTE:
828 if (value) 787 if (value)
829 tuner_sanyo_write_and(RADIO_CTRL3, ~AMUTE_L); 788 lv24020lp_write_and(RADIO_CTRL3, ~AMUTE_L);
830 else 789 else
831 tuner_sanyo_write_or(RADIO_CTRL3, AMUTE_L); 790 lv24020lp_write_or(RADIO_CTRL3, AMUTE_L);
832 break; 791 break;
833 792
834 case RADIO_REGION: 793 case RADIO_REGION:
835 switch (value) 794 {
836 { 795 if (lv24020lp_region_data[value])
837 case REGION_EUROPE: 796 lv24020lp_write_or(AUDIO_CTRL2, DEEMP);
838 case REGION_JAPAN: 797 else
839 case REGION_KOREA: 798 lv24020lp_write_and(AUDIO_CTRL2, ~DEEMP);
840 tuner_sanyo_write_and(AUDIO_CTRL2, ~DEEMP);
841 break;
842 case REGION_US_CANADA:
843 tuner_sanyo_write_or(AUDIO_CTRL2, DEEMP);
844 break;
845 default:
846 val = -1;
847 }
848 break; 799 break;
800 }
849 801
850 case RADIO_FORCE_MONO: 802 case RADIO_FORCE_MONO:
851 if (value) 803 if (value)
852 tuner_sanyo_write_or(STEREO_CTRL, ST_M); 804 lv24020lp_write_or(STEREO_CTRL, ST_M);
853 else 805 else
854 tuner_sanyo_write_and(STEREO_CTRL, ~ST_M); 806 lv24020lp_write_and(STEREO_CTRL, ~ST_M);
855 break; 807 break;
856 808
857 default: 809 default:
@@ -861,45 +813,55 @@ int sanyo_set(int setting, int value)
861 return val; 813 return val;
862} 814}
863 815
864int sanyo_get(int setting) 816int lv24020lp_get(int setting)
865{ 817{
866 int val = -1; 818 int val = -1;
867 819
868 switch(setting) 820 switch(setting)
869 { 821 {
870 case RADIO_ALL:
871 return tuner_sanyo_read(CTRL_STAT);
872
873 case RADIO_TUNED: 822 case RADIO_TUNED:
874 /* TODO: really implement this */ 823 /* TODO: really implement this */
875 val = RSS_FS(tuner_sanyo_read(RADIO_STAT)) < 0x1f; 824 val = RSS_FS(lv24020lp_read(RADIO_STAT)) < 0x1f;
876 break; 825 break;
877 826
878 case RADIO_STEREO: 827 case RADIO_STEREO:
879 val = (tuner_sanyo_read(RADIO_STAT) & RSS_MS) != 0; 828 val = (lv24020lp_read(RADIO_STAT) & RSS_MS) != 0;
880 break; 829 break;
881 830
882 case RADIO_PRESENT: 831 case RADIO_PRESENT:
832 {
833 bool fmstatus = true;
834
835 if (!(tuner_status & TUNER_PRESENCE_CHECKED))
836 fmstatus = tuner_power(true);
837
883 val = (tuner_status & TUNER_PRESENT) != 0; 838 val = (tuner_status & TUNER_PRESENT) != 0;
839
840 if (!fmstatus)
841 tuner_power(false);
884 break; 842 break;
843 }
885 844
886 /* tuner-specific debug info */ 845 /* tuner-specific debug info */
887 case RADIO_REG_STAT: 846 case LV24020LP_CTRL_STAT:
888 return tuner_sanyo_read(RADIO_STAT); 847 return lv24020lp_read(CTRL_STAT);
848
849 case LV24020LP_REG_STAT:
850 return lv24020lp_read(RADIO_STAT);
889 851
890 case RADIO_MSS_FM: 852 case LV24020LP_MSS_FM:
891 return tuner_measure(MSS_FM, 1, 16); 853 return tuner_measure(MSS_FM, 1, 16);
892 854
893 case RADIO_MSS_IF: 855 case LV24020LP_MSS_IF:
894 return tuner_measure(MSS_IF, 1000, 16); 856 return tuner_measure(MSS_IF, 1000, 16);
895 857
896 case RADIO_MSS_SD: 858 case LV24020LP_MSS_SD:
897 return tuner_measure(MSS_SD, 1000, 16); 859 return tuner_measure(MSS_SD, 1000, 16);
898 860
899 case RADIO_IF_SET: 861 case LV24020LP_IF_SET:
900 return if_set; 862 return if_set;
901 863
902 case RADIO_SD_SET: 864 case LV24020LP_SD_SET:
903 return sd_set; 865 return sd_set;
904 } 866 }
905 867
diff --git a/firmware/tuner_samsung.c b/firmware/drivers/tuner/s1a0903x01.c
index 82934d7160..cdeba2b3b4 100644
--- a/firmware/tuner_samsung.c
+++ b/firmware/drivers/tuner/s1a0903x01.c
@@ -33,9 +33,10 @@
33 33
34static int fm_in1; 34static int fm_in1;
35static int fm_in2; 35static int fm_in2;
36static int fm_present = -1; /* unknown */
36 37
37/* tuner abstraction layer: set something to the tuner */ 38/* tuner abstraction layer: set something to the tuner */
38int samsung_set(int setting, int value) 39int s1a0903x01_set(int setting, int value)
39{ 40{
40 int val = 1; 41 int val = 1;
41 42
@@ -95,12 +96,13 @@ int samsung_set(int setting, int value)
95 96
96 case RADIO_SCAN_FREQUENCY: 97 case RADIO_SCAN_FREQUENCY:
97 /* Tune in and delay */ 98 /* Tune in and delay */
98 samsung_set(RADIO_FREQUENCY, value); 99 s1a0903x01_set(RADIO_FREQUENCY, value);
99 sleep(1); 100 sleep(1);
100 /* Start IF measurement */ 101 /* Start IF measurement */
101 samsung_set(RADIO_IF_MEASUREMENT, 1); 102 fm_in1 |= 4;
103 fmradio_set(1, fm_in1);
102 sleep(1); 104 sleep(1);
103 val = samsung_get(RADIO_TUNED); 105 val = s1a0903x01_get(RADIO_TUNED);
104 break; 106 break;
105 107
106 case RADIO_MUTE: 108 case RADIO_MUTE:
@@ -108,20 +110,23 @@ int samsung_set(int setting, int value)
108 fmradio_set(1, fm_in1); 110 fmradio_set(1, fm_in1);
109 break; 111 break;
110 112
111 case RADIO_IF_MEASUREMENT: 113 case RADIO_FORCE_MONO:
114 fm_in2 = (fm_in2 & 0xfffffffb) | (value?0:4);
115 fmradio_set(2, fm_in2);
116 break;
117 /* NOTE: These were only zeroed when starting the tuner from OFF
118 but the default values already set them to 0. */
119#if 0
120 case S1A0903X01_IF_MEASUREMENT:
112 fm_in1 = (fm_in1 & 0xfffffffb) | (value?4:0); 121 fm_in1 = (fm_in1 & 0xfffffffb) | (value?4:0);
113 fmradio_set(1, fm_in1); 122 fmradio_set(1, fm_in1);
114 break; 123 break;
115 124
116 case RADIO_SENSITIVITY: 125 case S1A0903X01_SENSITIVITY:
117 fm_in2 = (fm_in2 & 0xffff9fff) | ((value & 3) << 13); 126 fm_in2 = (fm_in2 & 0xffff9fff) | ((value & 3) << 13);
118 fmradio_set(2, fm_in2); 127 fmradio_set(2, fm_in2);
119 break; 128 break;
120 129#endif
121 case RADIO_FORCE_MONO:
122 fm_in2 = (fm_in2 & 0xfffffffb) | (value?0:4);
123 fmradio_set(2, fm_in2);
124 break;
125 default: 130 default:
126 val = -1; 131 val = -1;
127 } 132 }
@@ -130,14 +135,27 @@ int samsung_set(int setting, int value)
130} 135}
131 136
132/* tuner abstraction layer: read something from the tuner */ 137/* tuner abstraction layer: read something from the tuner */
133int samsung_get(int setting) 138int s1a0903x01_get(int setting)
134{ 139{
135 int val = -1; 140 int val = -1;
136 switch(setting) 141 switch(setting)
137 { 142 {
138 case RADIO_PRESENT: 143 case RADIO_PRESENT:
139 fmradio_set(2, 0x140885); /* 5kHz, 7.2MHz crystal, test mode 1 */ 144 if (fm_present == -1)
140 val = (fmradio_read(0) == 0x140885); 145 {
146#ifdef HAVE_TUNER_PWR_CTRL
147 bool fmstatus = tuner_power(true);
148#endif
149 /* 5kHz, 7.2MHz crystal, test mode 1 */
150 fmradio_set(2, 0x140885);
151 fm_present = (fmradio_read(0) == 0x140885);
152#ifdef HAVE_TUNER_PWR_CTRL
153 if (!fmstatus)
154 tuner_power(false);
155#endif
156 }
157
158 val = fm_present;
141 break; 159 break;
142 160
143 case RADIO_TUNED: 161 case RADIO_TUNED:
@@ -148,6 +166,7 @@ int samsung_get(int setting)
148 case RADIO_STEREO: 166 case RADIO_STEREO:
149 val = fmradio_read(3); 167 val = fmradio_read(3);
150 val = ((val & 0x100000) ? true : false); 168 val = ((val & 0x100000) ? true : false);
169 break;
151 } 170 }
152 return val; 171 return val;
153} 172}
diff --git a/firmware/tuner_philips.c b/firmware/drivers/tuner/tea5767.c
index 8520fdbae9..da7cdfb65a 100644
--- a/firmware/tuner_philips.c
+++ b/firmware/drivers/tuner/tea5767.c
@@ -23,13 +23,21 @@
23#include <stdlib.h> 23#include <stdlib.h>
24#include "kernel.h" 24#include "kernel.h"
25#include "tuner.h" /* tuner abstraction interface */ 25#include "tuner.h" /* tuner abstraction interface */
26#include "fmradio.h"
26#include "fmradio_i2c.h" /* physical interface driver */ 27#include "fmradio_i2c.h" /* physical interface driver */
27 28
28#define I2C_ADR 0xC0 29#define I2C_ADR 0xC0
29static unsigned char write_bytes[5] = { 0x00, 0x00, 0x00, 0x00, 0x00 }; 30static unsigned char write_bytes[5] = { 0x00, 0x00, 0x00, 0x00, 0x00 };
30 31
32static void tea5767_set_clear(int byte, unsigned char bits, int set)
33{
34 write_bytes[byte] &= ~bits;
35 if (set)
36 write_bytes[byte] |= bits;
37}
38
31/* tuner abstraction layer: set something to the tuner */ 39/* tuner abstraction layer: set something to the tuner */
32int philips_set(int setting, int value) 40int tea5767_set(int setting, int value)
33{ 41{
34 switch(setting) 42 switch(setting)
35 { 43 {
@@ -44,7 +52,7 @@ int philips_set(int setting, int value)
44 write_bytes[3] |= (1<<3) | (1<<1); 52 write_bytes[3] |= (1<<3) | (1<<1);
45#endif 53#endif
46 /* sleep / standby mode */ 54 /* sleep / standby mode */
47 write_bytes[3] &= ~(1<<6) | (value ? (1<<6) : 0); 55 tea5767_set_clear(3, (1<<6), value);
48 break; 56 break;
49 57
50 case RADIO_FREQUENCY: 58 case RADIO_FREQUENCY:
@@ -56,38 +64,41 @@ int philips_set(int setting, int value)
56 n = (4 * (value - 225000)) / 50000; 64 n = (4 * (value - 225000)) / 50000;
57#endif 65#endif
58 write_bytes[0] = (write_bytes[0] & 0xC0) | (n >> 8); 66 write_bytes[0] = (write_bytes[0] & 0xC0) | (n >> 8);
59 write_bytes[1] = n & 0xFF; 67 write_bytes[1] = n;
60 } 68 }
61 break; 69 break;
62 70
63 case RADIO_SCAN_FREQUENCY: 71 case RADIO_SCAN_FREQUENCY:
64 philips_set(RADIO_FREQUENCY, value); 72 tea5767_set(RADIO_FREQUENCY, value);
65 sleep(HZ/30); 73 sleep(HZ/30);
66 return philips_get(RADIO_TUNED); 74 return tea5767_get(RADIO_TUNED);
67 75
68 case RADIO_MUTE: 76 case RADIO_MUTE:
69 write_bytes[0] = (write_bytes[0] & 0x7F) | (value ? 0x80 : 0); 77 tea5767_set_clear(0, 0x80, value);
70 break; 78 break;
71 79
72 case RADIO_FORCE_MONO: 80 case RADIO_REGION:
73 write_bytes[2] = (write_bytes[2] & 0xF7) | (value ? 0x08 : 0); 81 {
74 break; 82 const struct tea5767_region_data *rd =
83 &tea5767_region_data[value];
75 84
76 case RADIO_SET_DEEMPHASIS: 85 tea5767_set_clear(4, (1<<6), rd->deemphasis);
77 write_bytes[4] = (write_bytes[4] & ~(1<<6)) | (value ? (1<<6) : 0); 86 tea5767_set_clear(3, (1<<5), rd->band);
87 break;
88 }
89 case RADIO_FORCE_MONO:
90 tea5767_set_clear(2, 0x08, value);
78 break; 91 break;
79
80 case RADIO_SET_BAND:
81 write_bytes[3] = (write_bytes[3] & ~(1<<5)) | (value ? (1<<5) : 0);
82 default: 92 default:
83 return -1; 93 return -1;
84 } 94 }
95
85 fmradio_i2c_write(I2C_ADR, write_bytes, sizeof(write_bytes)); 96 fmradio_i2c_write(I2C_ADR, write_bytes, sizeof(write_bytes));
86 return 1; 97 return 1;
87} 98}
88 99
89/* tuner abstraction layer: read something from the tuner */ 100/* tuner abstraction layer: read something from the tuner */
90int philips_get(int setting) 101int tea5767_get(int setting)
91{ 102{
92 unsigned char read_bytes[5]; 103 unsigned char read_bytes[5];
93 int val = -1; /* default for unsupported query */ 104 int val = -1; /* default for unsupported query */
@@ -113,10 +124,11 @@ int philips_get(int setting)
113 val = read_bytes[2] >> 7; 124 val = read_bytes[2] >> 7;
114 break; 125 break;
115 } 126 }
127
116 return val; 128 return val;
117} 129}
118 130
119void philips_dbg_info(struct philips_dbg_info *info) 131void tea5767_dbg_info(struct tea5767_dbg_info *info)
120{ 132{
121 fmradio_i2c_read(I2C_ADR, info->read_regs, 5); 133 fmradio_i2c_read(I2C_ADR, info->read_regs, 5);
122 memcpy(info->write_regs, write_bytes, 5); 134 memcpy(info->write_regs, write_bytes, 5);
diff --git a/firmware/export/config.h b/firmware/export/config.h
index 86e27d0031..056b9857bc 100644
--- a/firmware/export/config.h
+++ b/firmware/export/config.h
@@ -245,6 +245,11 @@
245#define CONFIG_REMOTE_DEFAULT_ICON_WIDTH 6 245#define CONFIG_REMOTE_DEFAULT_ICON_WIDTH 6
246#endif 246#endif
247 247
248#if (CONFIG_TUNER & (CONFIG_TUNER - 1)) != 0
249/* Multiple possible tuners */
250#define CONFIG_TUNER_MULTI
251#endif
252
248/* Enable the directory cache and tagcache in RAM if we have 253/* Enable the directory cache and tagcache in RAM if we have
249 * plenty of RAM. Both features can be enabled independently. */ 254 * plenty of RAM. Both features can be enabled independently. */
250#if ((defined(MEMORYSIZE) && (MEMORYSIZE > 8)) || MEM > 8) && \ 255#if ((defined(MEMORYSIZE) && (MEMORYSIZE > 8)) || MEM > 8) && \
diff --git a/firmware/export/hwcompat.h b/firmware/export/hwcompat.h
index bffb76e3ef..bebca68a6c 100644
--- a/firmware/export/hwcompat.h
+++ b/firmware/export/hwcompat.h
@@ -46,4 +46,11 @@
46bool is_new_player(void); 46bool is_new_player(void);
47#endif 47#endif
48 48
49#ifdef CONFIG_TUNER_MULTI
50static inline int tuner_detect_type(void)
51{
52 return (HW_MASK & TUNER_MODEL) ? TEA5767 : S1A0903X01;
53}
54#endif
55
49#endif /* HWCOMPAT_H */ 56#endif /* HWCOMPAT_H */
diff --git a/firmware/export/lv24020lp.h b/firmware/export/lv24020lp.h
new file mode 100644
index 0000000000..0fc39b18df
--- /dev/null
+++ b/firmware/export/lv24020lp.h
@@ -0,0 +1,51 @@
1/***************************************************************************
2 * __________ __ ___.
3 * Open \______ \ ____ ____ | | _\_ |__ _______ ___
4 * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
5 * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
6 * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
7 * \/ \/ \/ \/ \/
8 * $Id$
9 * Tuner header for the Sanyo LV24020LP
10 *
11 * Copyright (C) 2007 Michael Sevakis
12 *
13 * All files in this archive are subject to the GNU General Public License.
14 * See the file COPYING in the source tree root for full license agreement.
15 *
16 * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
17 * KIND, either express or implied.
18 *
19 ****************************************************************************/
20
21#ifndef _LV24020LP_H_
22#define _LV24020LP_H_
23
24/* Define additional tuner messages here */
25#define HAVE_RADIO_REGION
26
27#define LV24020LP_CTRL_STAT (RADIO_GET_CHIP_FIRST+0)
28#define LV24020LP_REG_STAT (RADIO_GET_CHIP_FIRST+1)
29#define LV24020LP_MSS_FM (RADIO_GET_CHIP_FIRST+2)
30#define LV24020LP_MSS_IF (RADIO_GET_CHIP_FIRST+3)
31#define LV24020LP_MSS_SD (RADIO_GET_CHIP_FIRST+4)
32#define LV24020LP_IF_SET (RADIO_GET_CHIP_FIRST+5)
33#define LV24020LP_SD_SET (RADIO_GET_CHIP_FIRST+6)
34
35struct lv24020lp_region_data
36{
37 unsigned char deemphasis;
38} __attribute__((packed));
39
40const unsigned char lv24020lp_region_data[TUNER_NUM_REGIONS];
41
42int lv24020lp_set(int setting, int value);
43int lv24020lp_get(int setting);
44void lv24020lp_power(bool status);
45
46#ifndef CONFIG_TUNER_MULTI
47#define tuner_set lv24020lp_set
48#define tuner_get lv24020lp_get
49#endif
50
51#endif /* _LV24020LP_H_ */
diff --git a/firmware/export/power.h b/firmware/export/power.h
index cafd6f87c8..8ecff6c51e 100644
--- a/firmware/export/power.h
+++ b/firmware/export/power.h
@@ -48,8 +48,8 @@ bool spdif_powered(void);
48#endif 48#endif
49 49
50#if CONFIG_TUNER 50#if CONFIG_TUNER
51extern bool radio_power(bool status); 51extern bool tuner_power(bool status);
52extern bool radio_powered(void); 52extern bool tuner_powered(void);
53#endif 53#endif
54 54
55#endif 55#endif
diff --git a/firmware/export/s1a0903x01.h b/firmware/export/s1a0903x01.h
new file mode 100644
index 0000000000..bf497628b7
--- /dev/null
+++ b/firmware/export/s1a0903x01.h
@@ -0,0 +1,40 @@
1/***************************************************************************
2 * __________ __ ___.
3 * Open \______ \ ____ ____ | | _\_ |__ _______ ___
4 * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
5 * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
6 * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
7 * \/ \/ \/ \/ \/
8 * $Id$
9 * Tuner header for the Samsung S1A0903X01
10 *
11 * Copyright (C) 2007 Michael Sevakis
12 *
13 * All files in this archive are subject to the GNU General Public License.
14 * See the file COPYING in the source tree root for full license agreement.
15 *
16 * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
17 * KIND, either express or implied.
18 *
19 ****************************************************************************/
20
21#ifndef _S1A0903X01_H_
22#define _S1A0903X01_H_
23
24/* Define additional tuner messages here */
25#define HAVE_RADIO_MUTE_TIMEOUT
26
27#if 0
28#define S1A0903X01_IF_MEASUREMENT (RADIO_SET_CHIP_FIRST+0)
29#define S1A0903X01_SENSITIVITY (RADIO_SET_CHIP_FIRST+1)
30#endif
31
32int s1a0903x01_set(int setting, int value);
33int s1a0903x01_get(int setting);
34
35#ifndef CONFIG_TUNER_MULTI
36#define tuner_set s1a0903x01_get
37#define tuner_get s1a0903x01_set
38#endif
39
40#endif /* _S1A0903X01_H_ */
diff --git a/firmware/export/tea5767.h b/firmware/export/tea5767.h
new file mode 100644
index 0000000000..dfa6149f20
--- /dev/null
+++ b/firmware/export/tea5767.h
@@ -0,0 +1,50 @@
1/***************************************************************************
2 * __________ __ ___.
3 * Open \______ \ ____ ____ | | _\_ |__ _______ ___
4 * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
5 * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
6 * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
7 * \/ \/ \/ \/ \/
8 * $Id$
9 * Tuner header for the Philips TEA5767
10 *
11 * Copyright (C) 2007 Michael Sevakis
12 *
13 * All files in this archive are subject to the GNU General Public License.
14 * See the file COPYING in the source tree root for full license agreement.
15 *
16 * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
17 * KIND, either express or implied.
18 *
19 ****************************************************************************/
20
21#ifndef _TEA5767_H_
22#define _TEA5767_H_
23
24#define HAVE_RADIO_REGION
25#define HAVE_RADIO_MUTE_TIMEOUT
26
27struct tea5767_region_data
28{
29 unsigned char deemphasis; /* 0: 50us, 1: 75us */
30 unsigned char band; /* 0: europe, 1: japan (BL in TEA spec)*/
31} __attribute__((packed));
32
33const struct tea5767_region_data tea5767_region_data[TUNER_NUM_REGIONS];
34
35struct tea5767_dbg_info
36{
37 unsigned char read_regs[5];
38 unsigned char write_regs[5];
39};
40
41int tea5767_set(int setting, int value);
42int tea5767_get(int setting);
43void tea5767_dbg_info(struct tea5767_dbg_info *info);
44
45#ifndef CONFIG_TUNER_MULTI
46#define tuner_set tea5767_set
47#define tuner_get tea5767_get
48#endif
49
50#endif /* _TEA5767_H_ */
diff --git a/firmware/export/tuner.h b/firmware/export/tuner.h
index 9f6d29f697..cf18102744 100644
--- a/firmware/export/tuner.h
+++ b/firmware/export/tuner.h
@@ -22,101 +22,112 @@
22 22
23#include "hwcompat.h" 23#include "hwcompat.h"
24 24
25/* settings to the tuner layer */ 25/** Settings to the tuner layer **/
26#define RADIO_ALL -1 /* debug */ 26enum
27#define RADIO_SLEEP 0 27{
28#define RADIO_FREQUENCY 1 28 RADIO_ALL = -1, /* debug */
29#define RADIO_MUTE 2 29 RADIO_SLEEP,
30#define RADIO_IF_MEASUREMENT 3 30 RADIO_FREQUENCY,
31#define RADIO_SENSITIVITY 4 31 RADIO_MUTE,
32#define RADIO_FORCE_MONO 5 32 RADIO_FORCE_MONO,
33#define RADIO_SCAN_FREQUENCY 6 33 RADIO_SCAN_FREQUENCY,
34#if (CONFIG_TUNER & TEA5767) 34
35#define RADIO_SET_DEEMPHASIS 7 35 /* Put new general-purpose settings above this line */
36#define RADIO_SET_BAND 8 36 __RADIO_SET_STANDARD_LAST
37#endif 37};
38#if (CONFIG_TUNER & LV24020LP) 38
39#define RADIO_REGION 9 /* to be used for all tuners */ 39/** Readback from the tuner layer **/
40#define RADIO_REG_STAT 100 40enum
41#define RADIO_MSS_FM 101 41{
42#define RADIO_MSS_IF 102 42 RADIO_PRESENT = 0,
43#define RADIO_MSS_SD 103 43 RADIO_TUNED,
44#define RADIO_IF_SET 104 44 RADIO_STEREO,
45#define RADIO_SD_SET 105 45
46#endif 46 /* Put new general-purpose readback values above this line */
47/* readback from the tuner layer */ 47 __RADIO_GET_STANDARD_LAST
48#define RADIO_PRESENT 0 48};
49#define RADIO_TUNED 1 49
50#define RADIO_STEREO 2 50/** Tuner regions **/
51
52/* Basic region information */
53enum
54{
55 REGION_EUROPE = 0,
56 REGION_US_CANADA,
57 REGION_JAPAN,
58 REGION_KOREA,
59
60 /* Add new regions above this line */
61 TUNER_NUM_REGIONS
62};
51 63
52#define REGION_EUROPE 0 64struct fm_region_data
53#define REGION_US_CANADA 1 65{
54#define REGION_JAPAN 2 66 int freq_min;
55#define REGION_KOREA 3 67 int freq_max;
68 int freq_step;
69};
70
71extern const struct fm_region_data fm_region_data[TUNER_NUM_REGIONS];
56 72
57#if CONFIG_TUNER 73#if CONFIG_TUNER
58 74
59#ifdef SIMULATOR 75#ifdef SIMULATOR
60int radio_set(int setting, int value); 76int tuner_set(int setting, int value);
61int radio_get(int setting); 77int tuner_get(int setting);
62#else 78#else
63#if CONFIG_TUNER == S1A0903X01 /* FM recorder */
64#define radio_set samsung_set
65#define radio_get samsung_get
66#elif CONFIG_TUNER == LV24020LP /* Sansa */
67#define radio_set sanyo_set
68#define radio_get sanyo_get
69#elif CONFIG_TUNER == TEA5767 /* iRiver, iAudio */
70#define radio_set philips_set
71#define radio_get philips_get
72#elif CONFIG_TUNER == (S1A0903X01 | TEA5767) /* OndioFM */
73#define radio_set _radio_set
74#define radio_get _radio_get
75int (*_radio_set)(int setting, int value);
76int (*_radio_get)(int setting);
77#endif /* CONFIG_TUNER == */
78#endif /* SIMULATOR */
79 79
80#if (CONFIG_TUNER & S1A0903X01) 80#ifdef CONFIG_TUNER_MULTI
81int samsung_set(int setting, int value); 81extern int (*tuner_set)(int setting, int value);
82int samsung_get(int setting); 82extern int (*tuner_get)(int setting);
83#endif /* CONFIG_TUNER & S1A0903X01 */ 83#endif /* CONFIG_TUNER_MULTI */
84 84
85/** Sanyo LV24020LP **/
85#if (CONFIG_TUNER & LV24020LP) 86#if (CONFIG_TUNER & LV24020LP)
86int sanyo_set(int setting, int value); 87/* Sansa e200 Series */
87int sanyo_get(int setting); 88#include "lv24020lp.h"
88#endif /* CONFIG_TUNER & LV24020LP */ 89#endif
90
91/** Samsung S1A0903X01 **/
92#if (CONFIG_TUNER & S1A0903X01)
93/* Ondio FM, FM Recorder */
94#include "s1a0903x01.h"
95#endif
89 96
97/** Philips TEA5767 **/
90#if (CONFIG_TUNER & TEA5767) 98#if (CONFIG_TUNER & TEA5767)
91struct philips_dbg_info 99/* Ondio FM, FM Recorder, Recorder V2, iRiver h100/h300, iAudio x5 */
100#include "tea5767.h"
101#endif
102
103#endif /* SIMULATOR */
104
105/* Additional messages that get enumerated after tuner driver headers */
106
107/* for tuner_set */
108enum
92{ 109{
93 unsigned char read_regs[5]; 110 __RADIO_SET_ADDITIONAL_START = __RADIO_SET_STANDARD_LAST-1,
94 unsigned char write_regs[5]; 111#ifdef HAVE_RADIO_REGION
112 RADIO_REGION,
113#endif
114
115 RADIO_SET_CHIP_FIRST
95}; 116};
96int philips_set(int setting, int value); 117
97int philips_get(int setting); 118/* for tuner_get */
98void philips_dbg_info(struct philips_dbg_info *info); 119enum
99#endif /* CONFIG_TUNER & TEA5767 */
100
101/* Just inline here since only radio screen needs this atm and
102 there's no tuner.c. */
103static inline void tuner_init(void)
104{ 120{
105#ifndef SIMULATOR 121 __RADIO_GET_ADDITIONAL_START = __RADIO_SET_STANDARD_LAST-1,
106#if CONFIG_TUNER == (S1A0903X01 | TEA5767) 122
107 if (HW_MASK & TUNER_MODEL) 123 RADIO_GET_CHIP_FIRST
108 { 124};
109 _radio_set = philips_set; 125
110 _radio_get = philips_get; 126/** **/
111 } 127
112 else 128void tuner_init(void);
113 { 129bool tuner_power(bool power);
114 _radio_set = samsung_set; 130bool tuner_powered(void);
115 _radio_get = samsung_get;
116 }
117#endif
118#endif
119}
120 131
121#endif /* #if CONFIG_TUNER */ 132#endif /* #if CONFIG_TUNER */
122 133
diff --git a/firmware/target/arm/archos/av300/power-av300.c b/firmware/target/arm/archos/av300/power-av300.c
index cfdce69b13..6cc8b4f7c7 100644
--- a/firmware/target/arm/archos/av300/power-av300.c
+++ b/firmware/target/arm/archos/av300/power-av300.c
@@ -84,12 +84,12 @@ void ide_power_enable(bool on)
84 84
85static bool powered = false; 85static bool powered = false;
86 86
87bool radio_powered() 87bool tuner_powered()
88{ 88{
89 return powered; 89 return powered;
90} 90}
91 91
92bool radio_power(bool status) 92bool tuner_power(bool status)
93{ 93{
94 bool old_status = powered; 94 bool old_status = powered;
95 powered = status; 95 powered = status;
diff --git a/firmware/target/arm/iriver/h10/power-h10.c b/firmware/target/arm/iriver/h10/power-h10.c
index 63eb2dc189..d0d3ce59d1 100644
--- a/firmware/target/arm/iriver/h10/power-h10.c
+++ b/firmware/target/arm/iriver/h10/power-h10.c
@@ -40,12 +40,12 @@ bool charger_enabled;
40 40
41static bool powered = false; 41static bool powered = false;
42 42
43bool radio_powered() 43bool tuner_powered()
44{ 44{
45 return powered; 45 return powered;
46} 46}
47 47
48bool radio_power(bool status) 48bool tuner_power(bool status)
49{ 49{
50 bool old_status = powered; 50 bool old_status = powered;
51 powered = status; 51 powered = status;
diff --git a/firmware/target/arm/pnx0101/iriver-ifp7xx/power-ifp7xx.c b/firmware/target/arm/pnx0101/iriver-ifp7xx/power-ifp7xx.c
index 4e4f585298..dfdcb1d27a 100644
--- a/firmware/target/arm/pnx0101/iriver-ifp7xx/power-ifp7xx.c
+++ b/firmware/target/arm/pnx0101/iriver-ifp7xx/power-ifp7xx.c
@@ -30,12 +30,12 @@
30 30
31static bool powered = false; 31static bool powered = false;
32 32
33bool radio_powered(void) 33bool tuner_powered(void)
34{ 34{
35 return powered; 35 return powered;
36} 36}
37 37
38bool radio_power(bool status) 38bool tuner_power(bool status)
39{ 39{
40 bool old_status = powered; 40 bool old_status = powered;
41 powered = status; 41 powered = status;
diff --git a/firmware/target/arm/sandisk/sansa-e200/power-e200.c b/firmware/target/arm/sandisk/sansa-e200/power-e200.c
index dfa4211a91..002dcb8407 100644
--- a/firmware/target/arm/sandisk/sansa-e200/power-e200.c
+++ b/firmware/target/arm/sandisk/sansa-e200/power-e200.c
@@ -21,6 +21,7 @@
21#include "system.h" 21#include "system.h"
22#include "cpu.h" 22#include "cpu.h"
23#include "i2c-pp.h" 23#include "i2c-pp.h"
24#include "tuner.h"
24 25
25void power_init(void) 26void power_init(void)
26{ 27{
@@ -61,3 +62,60 @@ void ide_power_enable(bool on)
61{ 62{
62 (void)on; 63 (void)on;
63} 64}
65
66/** Tuner **/
67static bool powered = false;
68
69bool tuner_power(bool status)
70{
71 bool old_status = powered;
72
73 if (status != old_status)
74 {
75 if (status)
76 {
77 /* init mystery amplification device */
78 outl(inl(0x70000084) | 0x1, 0x70000084);
79 udelay(5);
80
81 /* When power up, host should initialize the 3-wire bus
82 in host read mode: */
83
84 /* 1. Set direction of the DATA-line to input-mode. */
85 GPIOH_OUTPUT_EN &= ~(1 << 5);
86 GPIOH_ENABLE |= (1 << 5);
87
88 /* 2. Drive NR_W low */
89 GPIOH_OUTPUT_VAL &= ~(1 << 3);
90 GPIOH_OUTPUT_EN |= (1 << 3);
91 GPIOH_ENABLE |= (1 << 3);
92
93 /* 3. Drive CLOCK high */
94 GPIOH_OUTPUT_VAL |= (1 << 4);
95 GPIOH_OUTPUT_EN |= (1 << 4);
96 GPIOH_ENABLE |= (1 << 4);
97
98 lv24020lp_power(true);
99 }
100 else
101 {
102 lv24020lp_power(false);
103
104 /* set all as inputs */
105 GPIOH_OUTPUT_EN &= ~((1 << 5) | (1 << 3) | (1 << 4));
106 GPIOH_ENABLE &= ~((1 << 5) | (1 << 3) | (1 << 4));
107
108 /* turn off mystery amplification device */
109 outl(inl(0x70000084) & ~0x1, 0x70000084);
110 }
111
112 powered = status;
113 }
114
115 return old_status;
116}
117
118bool tuner_powered(void)
119{
120 return powered;
121}
diff --git a/firmware/target/coldfire/iaudio/x5/power-x5.c b/firmware/target/coldfire/iaudio/x5/power-x5.c
index c646570821..5c6c388a71 100644
--- a/firmware/target/coldfire/iaudio/x5/power-x5.c
+++ b/firmware/target/coldfire/iaudio/x5/power-x5.c
@@ -90,12 +90,12 @@ void ide_power_enable(bool on)
90 90
91static bool powered = false; 91static bool powered = false;
92 92
93bool radio_powered() 93bool tuner_powered()
94{ 94{
95 return powered; 95 return powered;
96} 96}
97 97
98bool radio_power(bool status) 98bool tuner_power(bool status)
99{ 99{
100 bool old_status = powered; 100 bool old_status = powered;
101 powered = status; 101 powered = status;
diff --git a/firmware/target/coldfire/iriver/h100/power-h100.c b/firmware/target/coldfire/iriver/h100/power-h100.c
index 943168967f..c1841264a2 100644
--- a/firmware/target/coldfire/iriver/h100/power-h100.c
+++ b/firmware/target/coldfire/iriver/h100/power-h100.c
@@ -29,12 +29,12 @@
29 29
30static bool powered = false; 30static bool powered = false;
31 31
32bool radio_powered(void) 32bool tuner_powered(void)
33{ 33{
34 return powered; 34 return powered;
35} 35}
36 36
37bool radio_power(bool status) 37bool tuner_power(bool status)
38{ 38{
39 bool old_status = powered; 39 bool old_status = powered;
40 powered = status; 40 powered = status;
diff --git a/firmware/target/coldfire/iriver/h300/power-h300.c b/firmware/target/coldfire/iriver/h300/power-h300.c
index 5e57326c36..b687b29cba 100644
--- a/firmware/target/coldfire/iriver/h300/power-h300.c
+++ b/firmware/target/coldfire/iriver/h300/power-h300.c
@@ -29,12 +29,12 @@
29 29
30static bool powered = false; 30static bool powered = false;
31 31
32bool radio_powered(void) 32bool tuner_powered(void)
33{ 33{
34 return powered; 34 return powered;
35} 35}
36 36
37bool radio_power(bool status) 37bool tuner_power(bool status)
38{ 38{
39 bool old_status = powered; 39 bool old_status = powered;
40 powered = status; 40 powered = status;
diff --git a/uisimulator/common/fmradio.c b/uisimulator/common/fmradio.c
index 851c11bcb5..372fd10b38 100644
--- a/uisimulator/common/fmradio.c
+++ b/uisimulator/common/fmradio.c
@@ -30,7 +30,7 @@ static bool mono = false;
30static bool powered = false; 30static bool powered = false;
31#endif 31#endif
32 32
33int radio_set(int setting, int value) 33int tuner_set(int setting, int value)
34{ 34{
35 switch(setting) 35 switch(setting)
36 { 36 {
@@ -59,7 +59,7 @@ int radio_set(int setting, int value)
59 return 1; 59 return 1;
60} 60}
61 61
62int radio_get(int setting) 62int tuner_get(int setting)
63{ 63{
64 int val = 0; 64 int val = 0;
65 65
@@ -86,7 +86,7 @@ int radio_get(int setting)
86} 86}
87 87
88#ifdef HAVE_TUNER_PWR_CTRL 88#ifdef HAVE_TUNER_PWR_CTRL
89bool radio_power(bool status) 89bool tuner_power(bool status)
90{ 90{
91 bool oldstatus = powered; 91 bool oldstatus = powered;
92 powered = status; 92 powered = status;