static void rda5802_set_frequency(int freq) { int i; uint16_t readchan; /* check BAND and spacings */ int start = CHANNEL_BANDr(cache[CHANNEL]) & 1 ? 76000000 : 87000000; int chan = (freq - start) / 50000; for (i = 0; i < 5; i++) { /* tune and wait a bit */ rda5802_write_masked(CHANNEL, CHANNEL_CHANw(chan) | CHANNEL_TUNE, CHANNEL_CHAN | CHANNEL_TUNE); rda5802_write_cache(); sleep(HZ * 70 / 1000); rda5802_write_clear(CHANNEL, CHANNEL_TUNE); rda5802_write_cache(); /* check if tuning was successful */ readchan = rda5802_read_reg(READCHAN); if (readchan & READCHAN_STC) { if (READCHAN_READCHANr(readchan) == chan) { break; } } } }
static void rda5802_set_frequency(int freq) { int i; uint16_t readchan; static const int spacings[] = {100000, 200000, 50000, 50000}; static const int bandstart[] = {87000000, 76000000, 76000000, 65000000}; /* calculate channel number */ int start = bandstart[CHANNEL_BANDr(cache[CHANNEL])]; int space = spacings[CHANNEL_SPACEr(cache[CHANNEL])]; int chan = (freq - start) / space; for (i = 0; i < 5; i++) { /* tune and wait a bit */ rda5802_write_masked(CHANNEL, CHANNEL_CHANw(chan) | CHANNEL_TUNE, CHANNEL_CHAN | CHANNEL_TUNE); rda5802_write_cache(); sleep(HZ * 70 / 1000); rda5802_write_clear(CHANNEL, CHANNEL_TUNE); rda5802_write_cache(); /* check if tuning was successful */ readchan = rda5802_read_reg(READCHAN); if (readchan & READCHAN_STC) { if (READCHAN_READCHANr(readchan) == chan) { break; } } } }
static void rda5802_sleep(int snooze) { if (snooze) { rda5802_write_clear(POWERCFG, POWERCFG_ENABLE); } else { rda5802_write_set(POWERCFG, POWERCFG_ENABLE); } rda5802_write_cache(); }
static void rda5802_set_region(int region) { const struct fm_region_data *rd = &fm_region_data[region]; int band = (rd->freq_min == 76000000) ? CHANNEL_BAND_760_900 : CHANNEL_BAND_870_1080; int deemphasis = (rd->deemphasis == 50) ? SYSCONFIG1_DE : 0; uint16_t bandspacing = CHANNEL_BANDw(band) | CHANNEL_SPACEw(CHANNEL_SPACE_50KHZ); rda5802_write_masked(SYSCONFIG1, deemphasis, SYSCONFIG1_DE); rda5802_write_masked(CHANNEL, bandspacing, CHANNEL_BAND | CHANNEL_SPACE); rda5802_write_cache(); }
/* tuner abstraction layer: set something to the tuner */ int rda5802_set(int setting, int value) { switch (setting) { case RADIO_SLEEP: rda5802_sleep(value); break; case RADIO_FREQUENCY: rda5802_set_frequency(value); break; case RADIO_SCAN_FREQUENCY: rda5802_set_frequency(value); return rda5802_tuned(); case RADIO_MUTE: rda5802_write_masked(POWERCFG, value ? 0 : POWERCFG_DMUTE, POWERCFG_DMUTE); rda5802_write_cache(); break; case RADIO_REGION: rda5802_set_region(value); break; case RADIO_FORCE_MONO: rda5802_write_masked(POWERCFG, value ? POWERCFG_MONO : 0, POWERCFG_MONO); rda5802_write_cache(); break; default: return -1; } return 1; }
static void rda5802_set_region(int region) { const struct fm_region_data *rd = &fm_region_data[region]; int band = (rd->freq_min == 76000000) ? CHANNEL_BAND_760_900 : CHANNEL_BAND_870_1080; int deemphasis = (rd->deemphasis == 50) ? SYSCONFIG1_DE : 0; int space = (rd->freq_step == 50000) ? CHANNEL_SPACE_50KHZ : CHANNEL_SPACE_100KHZ; rda5802_write_masked(SYSCONFIG1, deemphasis, SYSCONFIG1_DE); rda5802_write_masked(CHANNEL, CHANNEL_BANDw(band), CHANNEL_BAND); rda5802_write_masked(CHANNEL, CHANNEL_SPACEw(space), CHANNEL_SPACE); rda5802_write_cache(); }