forked from len0rd/rockbox
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
This commit is contained in:
parent
d6bae6c858
commit
1fea6f6b22
9 changed files with 510 additions and 173 deletions
|
@ -2293,12 +2293,12 @@ static int radio_callback(int btn, struct gui_synclist *lists)
|
|||
"if_set: %d Hz", lv24020lp_get(LV24020LP_IF_SET) );
|
||||
simplelist_addline(SIMPLELIST_ADD_LINE,
|
||||
"sd_set: %d Hz", lv24020lp_get(LV24020LP_SD_SET) );
|
||||
#endif
|
||||
#endif /* LV24020LP */
|
||||
#if (CONFIG_TUNER & S1A0903X01)
|
||||
simplelist_addline(SIMPLELIST_ADD_LINE,
|
||||
"Samsung regs: %08X", s1a0903x01_get(RADIO_ALL));
|
||||
/* This one doesn't return dynamic data atm */
|
||||
#endif
|
||||
#endif /* S1A0903X01 */
|
||||
#if (CONFIG_TUNER & TEA5767)
|
||||
struct tea5767_dbg_info nfo;
|
||||
tea5767_dbg_info(&nfo);
|
||||
|
@ -2313,7 +2313,29 @@ static int radio_callback(int btn, struct gui_synclist *lists)
|
|||
(unsigned)nfo.write_regs[0], (unsigned)nfo.write_regs[1],
|
||||
(unsigned)nfo.write_regs[2], (unsigned)nfo.write_regs[3],
|
||||
(unsigned)nfo.write_regs[4]);
|
||||
#endif
|
||||
#endif /* TEA5767 */
|
||||
#if (CONFIG_TUNER & SI4700)
|
||||
struct si4700_dbg_info nfo;
|
||||
si4700_dbg_info(&nfo);
|
||||
simplelist_addline(SIMPLELIST_ADD_LINE, "SI4700 regs:");
|
||||
/* Registers */
|
||||
simplelist_addline(SIMPLELIST_ADD_LINE,
|
||||
" %04X %04X %04X %04X",
|
||||
(unsigned)nfo.regs[0], (unsigned)nfo.regs[1],
|
||||
(unsigned)nfo.regs[2], (unsigned)nfo.regs[3]);
|
||||
simplelist_addline(SIMPLELIST_ADD_LINE,
|
||||
" %04X %04X %04X %04X",
|
||||
(unsigned)nfo.regs[4], (unsigned)nfo.regs[5],
|
||||
(unsigned)nfo.regs[6], (unsigned)nfo.regs[7]);
|
||||
simplelist_addline(SIMPLELIST_ADD_LINE,
|
||||
" %04X %04X %04X %04X",
|
||||
(unsigned)nfo.regs[8], (unsigned)nfo.regs[9],
|
||||
(unsigned)nfo.regs[10], (unsigned)nfo.regs[11]);
|
||||
simplelist_addline(SIMPLELIST_ADD_LINE,
|
||||
" %04X %04X %04X %04X",
|
||||
(unsigned)nfo.regs[12], (unsigned)nfo.regs[13],
|
||||
(unsigned)nfo.regs[14], (unsigned)nfo.regs[15]);
|
||||
#endif /* SI4700 */
|
||||
return ACTION_REDRAW;
|
||||
}
|
||||
static bool dbg_fm_radio(void)
|
||||
|
|
|
@ -25,12 +25,33 @@
|
|||
#include <string.h>
|
||||
#include <stdlib.h>
|
||||
#include "kernel.h"
|
||||
#include "power.h"
|
||||
#include "tuner.h" /* tuner abstraction interface */
|
||||
#include "fmradio.h"
|
||||
#include "fmradio_i2c.h" /* physical interface driver */
|
||||
|
||||
/* some models use the internal 32 kHz oscillator which needs special attention
|
||||
during initialisation, power-up and power-down.
|
||||
*/
|
||||
#if defined(SANSA_CLIP) || defined(SANSA_E200V2) || defined(SANSA_FUZE)
|
||||
#define USE_INTERNAL_OSCILLATOR
|
||||
#elif defined(TOSHIBA_GIGABEAT_S)
|
||||
#define SI4700_GPIO_SETUP (SYSCONFIG1_GPIO1_HI_Z | \
|
||||
SYSCONFIG1_GPIO2_HI_Z | \
|
||||
SYSCONFIG1_GPIO3_MO_ST_I)
|
||||
extern int si4700_st(void);
|
||||
#endif
|
||||
|
||||
#ifndef SI4700_GPIO_SETUP
|
||||
#define SI4700_GPIO_SETUP 0
|
||||
#endif
|
||||
|
||||
#define SEEK_THRESHOLD 0x16
|
||||
#define TUNER_VOLUME 0xC
|
||||
|
||||
#define I2C_ADR 0x20
|
||||
|
||||
/** Registers and bits - "x" denotes Si4702/03 only (so they say) **/
|
||||
#define DEVICEID 0x0
|
||||
#define CHIPID 0x1
|
||||
#define POWERCFG 0x2
|
||||
|
@ -43,20 +64,154 @@
|
|||
#define BOOTCONFIG 0x9
|
||||
#define STATUSRSSI 0xA
|
||||
#define READCHAN 0xB
|
||||
#define RDSA 0xC
|
||||
#define RDSB 0xD
|
||||
#define RDSC 0xE
|
||||
#define RDSD 0xF
|
||||
#define RDSA 0xC /* x */
|
||||
#define RDSB 0xD /* x */
|
||||
#define RDSC 0xE /* x */
|
||||
#define RDSD 0xF /* x */
|
||||
|
||||
/* some models use the internal 32 kHz oscillator which needs special attention
|
||||
during initialisation, power-up and power-down.
|
||||
*/
|
||||
#if defined(SANSA_CLIP) || defined(SANSA_E200V2) || defined(SANSA_FUZE)
|
||||
#define USE_INTERNAL_OSCILLATOR
|
||||
#endif
|
||||
/* DEVICEID (0x0) */
|
||||
#define DEVICEID_PN (0xf << 12)
|
||||
/* 0x01 = Si4700/01 */
|
||||
/* 0x01 = Si4702/03 */
|
||||
#define DEVICEID_MFGID (0xfff << 0)
|
||||
/* always 0x242 */
|
||||
|
||||
/* CHIPID (0x1) */
|
||||
|
||||
#if 0 /* Informational */
|
||||
/* Si4700/01 */
|
||||
#define CHIPID_REV (0x3f << 10)
|
||||
#define CHIPID_DEV (0x1 << 9)
|
||||
/* 0 before powerup */
|
||||
/* 0 after powerup = Si4700 */
|
||||
/* 1 after powerup = Si4701 */
|
||||
#define CHIPID_FIRMWARE (0xff << 0)
|
||||
|
||||
/* Si4702/03 */
|
||||
#define CHIPID_REV (0x3f << 10)
|
||||
#define CHIPID_DEV (0xf << 6)
|
||||
/* 0000 before PU = Si4702 */
|
||||
/* 0001 after PU = Si4702 */
|
||||
/* 1000 before PU = Si4703 */
|
||||
/* 1001 after PU = Si4703 */
|
||||
#define CHIPID_FIRMWARE (0x3f << 0)
|
||||
#endif /* 0 */
|
||||
|
||||
/* POWERCFG (0x2) */
|
||||
#define POWERCFG_DSMUTE (0x1 << 15)
|
||||
#define POWERCFG_DMUTE (0x1 << 14)
|
||||
#define POWERCFG_MONO (0x1 << 13)
|
||||
#define POWERCFG_RDSM (0x1 << 11) /* x */
|
||||
#define POWERCFG_SKMODE (0x1 << 10)
|
||||
#define POWERCFG_SEEKUP (0x1 << 9)
|
||||
#define POWERCFG_SEEK (0x1 << 8)
|
||||
#define POWERCFG_DISABLE (0x1 << 6)
|
||||
#define POWERCFG_ENABLE (0x1 << 0)
|
||||
|
||||
/* CHANNEL (0x3) */
|
||||
#define CHANNEL_TUNE (0x1 << 15)
|
||||
#define CHANNEL_CHAN (0x3ff << 0)
|
||||
#define CHANNEL_CHANw(x) ((x) & CHANNEL_CHAN)
|
||||
|
||||
/* SYSCONFIG1 (0x4) */
|
||||
#define SYSCONFIG1_RDSIEN (0x1 << 15) /* x */
|
||||
#define SYSCONFIG1_STCIEN (0x1 << 14)
|
||||
#define SYSCONFIG1_RDS (0x1 << 12) /* x */
|
||||
#define SYSCONFIG1_DE (0x1 << 11)
|
||||
#define SYSCONFIG1_AGCD (0x1 << 10)
|
||||
#define SYSCONFIG1_BLNDADJ (0x3 << 6)
|
||||
#define SYSCONFIG1_BLNDADJ_31_39_RSSI (0x0 << 6)
|
||||
#define SYSCONFIG1_BLNDADJ_37_55_RSSI (0x1 << 6)
|
||||
#define SYSCONFIG1_BLNDADJ_19_37_RSSI (0x2 << 6)
|
||||
#define SYSCONFIG1_BLNDADJ_25_43_RSSI (0x3 << 6)
|
||||
#define SYSCONFIG1_GPIO3 (0x3 << 4)
|
||||
#define SYSCONFIG1_GPIO3_HI_Z (0x0 << 4)
|
||||
#define SYSCONFIG1_GPIO3_MO_ST_I (0x1 << 4)
|
||||
#define SYSCONFIG1_GPIO3_LOW (0x2 << 4)
|
||||
#define SYSCONFIG1_GPIO3_HI (0x3 << 4)
|
||||
#define SYSCONFIG1_GPIO2 (0x3 << 2)
|
||||
#define SYSCONFIG1_GPIO2_HI_Z (0x0 << 2)
|
||||
#define SYSCONFIG1_GPIO2_STC_RDS_I (0x1 << 2)
|
||||
#define SYSCONFIG1_GPIO2_LOW (0x2 << 2)
|
||||
#define SYSCONFIG1_GPIO2_HI (0x3 << 2)
|
||||
#define SYSCONFIG1_GPIO1 (0x3 << 0)
|
||||
#define SYSCONFIG1_GPIO1_HI_Z (0x0 << 0)
|
||||
#define SYSCONFIG1_GPIO1_LOW (0x2 << 0)
|
||||
#define SYSCONFIG1_GPIO1_HI (0x3 << 0)
|
||||
|
||||
/* SYSCONFIG2 (0x5) */
|
||||
#define SYSCONFIG2_SEEKTH (0xff << 8)
|
||||
#define SYSCONFIG2_SKEETHw(x) (((x) << 8) & SYSCONFIG2_SEEKTH)
|
||||
#define SYSCONFIG2_BAND (0x3 << 6)
|
||||
#define SYSCONFIG2_BANDw(x) (((x) << 6) & SYSCONFIG2_BAND)
|
||||
#define SYSCONFIG2_BANDr(x) (((x) & SYSCONFIG2_BAND) >> 6)
|
||||
#define SYSCONFIG2_BAND_875_1080 (0x0 << 6) /* tenth-megahertz */
|
||||
#define SYSCONFIG2_BAND_760_1080 (0x1 << 6)
|
||||
#define SYSCONFIG2_BAND_760_900 (0x2 << 6)
|
||||
#define SYSCONFIG2_SPACE (0x3 << 4)
|
||||
#define SYSCONFIG2_SPACEw(x) (((x) << 4) & SYSCONFIG2_SPACE)
|
||||
#define SYSCONFIG2_SPACEr(x) (((x) & SYSCONFIG2_SPACE) >> 4)
|
||||
#define SYSCONFIG2_SPACE_200KHZ (0x0 << 4)
|
||||
#define SYSCONFIG2_SPACE_100KHZ (0x1 << 4)
|
||||
#define SYSCONFIG2_SPACE_50KHZ (0x2 << 4)
|
||||
/* 4700/01 0000=mute,0001=-28dBFS..2dB steps..1111= +0dBFS */
|
||||
/* 4702/03: VOLEXT=0: 0000=mute,0001=-28dBFS..2dB steps..1111= +0dBFS */
|
||||
/* VOLEXT=1: 0000=mute,0001=-58dBFS..2dB steps..1111=-30dBFS */
|
||||
#define SYSCONFIG2_VOLUME (0xf << 0)
|
||||
#define SYSCONFIG2_VOLUMEw(x) ((x) & SYSCONFIG2_VOLUME)
|
||||
|
||||
/* SYSCONFIG3 (0x6) */
|
||||
#define SYSCONFIG3_SMUTER (0x3 << 14)
|
||||
#define SYSCONFIG3_SMUTER_FASTEST (0x0 << 14)
|
||||
#define SYSCONFIG3_SMUTER_FAST (0x1 << 14)
|
||||
#define SYSCONFIG3_SMUTER_SLOW (0x2 << 14)
|
||||
#define SYSCONFIG3_SMUTER_SLOWEST (0x3 << 14)
|
||||
#define SYSCONFIG3_SMUTEA (0x3 << 12)
|
||||
#define SYSCONFIG3_SMUTEA_16DB (0x0 << 12)
|
||||
#define SYSCONFIG3_SMUTEA_14DB (0x1 << 12)
|
||||
#define SYSCONFIG3_SMUTEA_12DB (0x2 << 12)
|
||||
#define SYSCONFIG3_SMUTEA_10DB (0x3 << 12)
|
||||
#define SYSCONFIG3_VOLEXT (0x1 << 8) /* x */
|
||||
#define SYSCONFIG3_SKSNR (0xf << 4)
|
||||
#define SYSCONFIG3_SKSNRw(x) (((x) << 4) & SYSCONFIG3_SKSNR)
|
||||
#define SYSCONFIG3_SKCNT (0xf << 0)
|
||||
#define SYSCONFIG3_SKCNTw(x) (((x) << 0) & SYSCONFIG3_SKCNT)
|
||||
|
||||
/* TEST1 (0x7) */
|
||||
/* 4700/01: 15=always 0, 13:0 = write with preexisting values! */
|
||||
/* 4702/03: 13:0 = write with preexisting values! */
|
||||
#define TEST1_XOSCEN (0x1 << 15) /* x */
|
||||
#define TEST1_AHIZEN (0x1 << 14)
|
||||
|
||||
/* TEST2 (0x8) */
|
||||
/* 15:0 = write with preexisting values! */
|
||||
|
||||
/* BOOTCONFIG (0x9) */
|
||||
/* 15:0 = write with preexisting values! */
|
||||
|
||||
/* STATUSRSSI (0xA) */
|
||||
#define STATUSRSSI_RDSR (0x1 << 15) /* x */
|
||||
#define STATUSRSSI_STC (0x1 << 14)
|
||||
#define STATUSRSSI_SFBL (0x1 << 13)
|
||||
#define STATUSRSSI_AFCRL (0x1 << 12)
|
||||
#define STATUSRSSI_RDSS (0x1 << 11) /* x */
|
||||
#define STATUSRSSI_BLERA (0x3 << 9) /* x */
|
||||
#define STATUSRSSI_ST (0x1 << 8)
|
||||
#define STATUSRSSI_RSSI (0xff << 0)
|
||||
#define STATUSRSSI_RSSIr(x) ((x) & 0xff)
|
||||
|
||||
/* READCHAN (0xB) */
|
||||
#define READCHAN_BLERB (0x3 << 14) /* x */
|
||||
#define READCHAN_BLERC (0x3 << 12) /* x */
|
||||
#define READCHAN_BLERD (0x3 << 10) /* x */
|
||||
#define READCHAN_READCHAN (0x3ff << 0)
|
||||
|
||||
/* RDSA-D (0xC-0xF) */
|
||||
/* 4702/03: RDS Block A-D data */
|
||||
|
||||
static bool tuner_present = false;
|
||||
static unsigned short cache[16];
|
||||
static int curr_frequency = 87500000; /* Current station frequency (HZ) */
|
||||
static uint16_t cache[16];
|
||||
|
||||
/* reads <len> registers from radio at offset 0x0A into cache */
|
||||
static void si4700_read(int len)
|
||||
|
@ -64,7 +219,7 @@ static void si4700_read(int len)
|
|||
int i;
|
||||
unsigned char buf[32];
|
||||
unsigned char *ptr = buf;
|
||||
unsigned short data;
|
||||
uint16_t data;
|
||||
|
||||
fmradio_i2c_read(I2C_ADR, buf, len * 2);
|
||||
for (i = 0; i < len; i++) {
|
||||
|
@ -80,7 +235,7 @@ static void si4700_write(int len)
|
|||
int i;
|
||||
unsigned char buf[32];
|
||||
unsigned char *ptr = buf;
|
||||
unsigned short data;
|
||||
uint16_t data;
|
||||
|
||||
for (i = 0; i < len; i++) {
|
||||
data = cache[(i + POWERCFG) & 0xF];
|
||||
|
@ -90,6 +245,43 @@ static void si4700_write(int len)
|
|||
fmradio_i2c_write(I2C_ADR, buf, len * 2);
|
||||
}
|
||||
|
||||
/* Hide silly, wrapped and continuous register reading and make interface
|
||||
* appear sane and normal. This also makes the driver compatible with
|
||||
* using the 3-wire interface. */
|
||||
static uint16_t si4700_read_reg(int reg)
|
||||
{
|
||||
si4700_read(((reg - STATUSRSSI) & 0xF) + 1);
|
||||
return cache[reg];
|
||||
}
|
||||
|
||||
static void si4700_write_reg(int reg, uint16_t value)
|
||||
{
|
||||
cache[reg] = value;
|
||||
si4700_write(((reg - POWERCFG) & 0xF) + 1);
|
||||
}
|
||||
|
||||
static void si4700_write_masked(int reg, uint16_t bits, uint16_t mask)
|
||||
{
|
||||
si4700_write_reg(reg, (cache[reg] & ~mask) | (bits & mask));
|
||||
}
|
||||
|
||||
static void si4700_write_set(int reg, uint16_t mask)
|
||||
{
|
||||
si4700_write_reg(reg, cache[reg] | mask);
|
||||
}
|
||||
|
||||
static void si4700_write_clear(int reg, uint16_t mask)
|
||||
{
|
||||
si4700_write_reg(reg, cache[reg] & ~mask);
|
||||
}
|
||||
|
||||
#if (SI4700_GPIO_SETUP & SYSCONFIG1_GPIO3) != SYSCONFIG1_GPIO3_MO_ST_I
|
||||
/* Poll i2c for the stereo status */
|
||||
static inline int si4700_st(void)
|
||||
{
|
||||
return (si4700_read_reg(STATUSRSSI) & STATUSRSSI_ST) >> 8;
|
||||
}
|
||||
#endif
|
||||
|
||||
void si4700_init(void)
|
||||
{
|
||||
|
@ -105,8 +297,7 @@ void si4700_init(void)
|
|||
|
||||
#ifdef USE_INTERNAL_OSCILLATOR
|
||||
/* enable the internal oscillator */
|
||||
cache[TEST1] |= (1 << 15); /* XOSCEN */
|
||||
si4700_write(6);
|
||||
si4700_write_set(TEST1, TEST1_XOSCEN);
|
||||
sleep(HZ/2);
|
||||
#endif
|
||||
}
|
||||
|
@ -114,21 +305,102 @@ void si4700_init(void)
|
|||
tuner_power(false);
|
||||
}
|
||||
|
||||
static void si4700_tune(void)
|
||||
static void si4700_sleep(int snooze)
|
||||
{
|
||||
cache[CHANNEL] |= (1 << 15); /* Set TUNE high to start tuning */
|
||||
si4700_write(2);
|
||||
if (snooze)
|
||||
{
|
||||
/** power down **/
|
||||
/* ENABLE high, DISABLE high */
|
||||
si4700_write_set(POWERCFG,
|
||||
POWERCFG_DISABLE | POWERCFG_ENABLE);
|
||||
/* Bits self-clear once placed in powerdown. */
|
||||
cache[POWERCFG] &= ~(POWERCFG_DISABLE | POWERCFG_ENABLE);
|
||||
}
|
||||
else
|
||||
{
|
||||
/** power up **/
|
||||
/* ENABLE high, DISABLE low */
|
||||
si4700_write_masked(POWERCFG, POWERCFG_ENABLE,
|
||||
POWERCFG_DISABLE | POWERCFG_ENABLE);
|
||||
sleep(110 * HZ / 1000);
|
||||
|
||||
/* init register cache */
|
||||
si4700_read(16);
|
||||
|
||||
#if SI4700_GPIO_SETUP != 0
|
||||
si4700_write_masked(SYSCONFIG1, SI4700_GPIO_SETUP,
|
||||
SYSCONFIG1_GPIO1 | SYSCONFIG1_GPIO2 |
|
||||
SYSCONFIG1_GPIO3);
|
||||
#endif
|
||||
/* -6dB volume, seek threshold 12 */
|
||||
si4700_write_masked(SYSCONFIG2,
|
||||
SYSCONFIG2_SKEETHw(SEEK_THRESHOLD) |
|
||||
SYSCONFIG2_VOLUMEw(TUNER_VOLUME),
|
||||
SYSCONFIG2_VOLUME | SYSCONFIG2_SEEKTH);
|
||||
}
|
||||
}
|
||||
|
||||
static void si4700_set_frequency(int freq)
|
||||
{
|
||||
static const unsigned int spacings[3] =
|
||||
{
|
||||
200000, /* SYSCONFIG2_SPACE_200KHZ */
|
||||
100000, /* SYSCONFIG2_SPACE_100KHZ */
|
||||
50000, /* SYSCONFIG2_SPACE_50KHZ */
|
||||
};
|
||||
static const unsigned int bands[3] =
|
||||
{
|
||||
87500000, /* SYSCONFIG2_BAND_875_1080 */
|
||||
76000000, /* SYSCONFIG2_BAND_760_1080 */
|
||||
76000000, /* SYSCONFIG2_BAND_760_900 */
|
||||
};
|
||||
|
||||
/* check BAND and spacings */
|
||||
int space = SYSCONFIG2_SPACEr(cache[SYSCONFIG2]);
|
||||
int band = SYSCONFIG2_BANDr(cache[SYSCONFIG2]);
|
||||
int chan = (freq - bands[band]) / spacings[space];
|
||||
|
||||
curr_frequency = freq;
|
||||
|
||||
si4700_write_reg(CHANNEL, CHANNEL_CHANw(chan) | CHANNEL_TUNE);
|
||||
|
||||
do
|
||||
{
|
||||
/* tuning should be done within 60 ms according to the datasheet */
|
||||
sleep(HZ * 60 / 1000);
|
||||
si4700_read(2);
|
||||
}
|
||||
while (!(cache[STATUSRSSI] & (1 << 14))); /* STC high */
|
||||
while ((si4700_read_reg(STATUSRSSI) & STATUSRSSI_STC) == 0); /* STC high? */
|
||||
|
||||
cache[CHANNEL] &= ~(1 << 15); /* Set TUNE low */
|
||||
si4700_write(2);
|
||||
si4700_write_clear(CHANNEL, CHANNEL_TUNE); /* Set TUNE low */
|
||||
}
|
||||
|
||||
static int si4700_tuned(void)
|
||||
{
|
||||
/* Primitive tuning check: sufficient level and AFC not railed */
|
||||
uint16_t status = si4700_read_reg(STATUSRSSI);
|
||||
if (STATUSRSSI_RSSIr(status) >= SEEK_THRESHOLD &&
|
||||
(status & STATUSRSSI_AFCRL) == 0)
|
||||
return 1;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void si4700_set_region(int region)
|
||||
{
|
||||
const struct si4700_region_data *rd = &si4700_region_data[region];
|
||||
uint16_t bandspacing = SYSCONFIG2_BANDw(rd->band) |
|
||||
SYSCONFIG2_SPACEw(rd->spacing);
|
||||
uint16_t oldbs = cache[SYSCONFIG2] & (SYSCONFIG2_BAND | SYSCONFIG2_SPACE);
|
||||
|
||||
si4700_write_masked(SYSCONFIG1,
|
||||
rd->deemphasis ? SYSCONFIG1_DE : 0,
|
||||
SYSCONFIG1_DE);
|
||||
si4700_write_masked(SYSCONFIG2, bandspacing,
|
||||
SYSCONFIG2_BAND | SYSCONFIG2_SPACE);
|
||||
|
||||
/* Retune if this region change would change the channel number. */
|
||||
if (oldbs != bandspacing)
|
||||
si4700_set_frequency(curr_frequency);
|
||||
}
|
||||
|
||||
/* tuner abstraction layer: set something to the tuner */
|
||||
|
@ -137,95 +409,35 @@ int si4700_set(int setting, int value)
|
|||
switch(setting)
|
||||
{
|
||||
case RADIO_SLEEP:
|
||||
if (value)
|
||||
{
|
||||
/* power down */
|
||||
cache[POWERCFG] = (1 | (1 << 6)); /* ENABLE high, DISABLE high */
|
||||
si4700_write(1);
|
||||
}
|
||||
else
|
||||
{
|
||||
/* power up */
|
||||
cache[POWERCFG] = 1; /* ENABLE high, DISABLE low */
|
||||
si4700_write(1);
|
||||
sleep(110 * HZ / 1000);
|
||||
|
||||
/* update register cache */
|
||||
si4700_read(16);
|
||||
|
||||
/* -6dB volume, keep everything else as default */
|
||||
cache[SYSCONFIG2] = (cache[SYSCONFIG2] & ~0xF) | 0xC;
|
||||
si4700_write(5);
|
||||
}
|
||||
return 1;
|
||||
si4700_sleep(value);
|
||||
break;
|
||||
|
||||
case RADIO_FREQUENCY:
|
||||
{
|
||||
static const unsigned int spacings[3] =
|
||||
{
|
||||
200000, 100000, 50000
|
||||
};
|
||||
unsigned int chan;
|
||||
unsigned int spacing = spacings[(cache[5] >> 4) & 3] ;
|
||||
|
||||
if (cache[SYSCONFIG2] & (3 << 6)) /* check BAND */
|
||||
{
|
||||
chan = (value - 76000000) / spacing;
|
||||
}
|
||||
else
|
||||
{
|
||||
chan = (value - 87500000) / spacing;
|
||||
}
|
||||
|
||||
cache[CHANNEL] = (cache[CHANNEL] & ~0x3FF) | chan;
|
||||
si4700_tune();
|
||||
return 1;
|
||||
}
|
||||
si4700_set_frequency(value);
|
||||
break;
|
||||
|
||||
case RADIO_SCAN_FREQUENCY:
|
||||
si4700_set(RADIO_FREQUENCY, value);
|
||||
return 1;
|
||||
si4700_set_frequency(value);
|
||||
return si4700_tuned();
|
||||
|
||||
case RADIO_MUTE:
|
||||
if (value)
|
||||
{
|
||||
/* mute */
|
||||
cache[POWERCFG] &= ~(1 << 14);
|
||||
}
|
||||
else
|
||||
{
|
||||
/* unmute */
|
||||
cache[POWERCFG] |= (1 << 14);
|
||||
}
|
||||
si4700_write_masked(POWERCFG, value ? 0 : POWERCFG_DMUTE,
|
||||
POWERCFG_DMUTE);
|
||||
break;
|
||||
|
||||
case RADIO_REGION:
|
||||
{
|
||||
const struct si4700_region_data *rd =
|
||||
&si4700_region_data[value];
|
||||
|
||||
cache[SYSCONFIG1] = (cache[SYSCONFIG1] & ~(1 << 11)) | (rd->deemphasis << 11);
|
||||
cache[SYSCONFIG2] = (cache[SYSCONFIG2] & ~(3 << 6)) | (rd->band << 6);
|
||||
cache[SYSCONFIG2] = (cache[SYSCONFIG2] & ~(3 << 4)) | (rd->spacing << 4);
|
||||
si4700_set_region(value);
|
||||
break;
|
||||
}
|
||||
|
||||
case RADIO_FORCE_MONO:
|
||||
if (value)
|
||||
{
|
||||
cache[POWERCFG] |= (1 << 13);
|
||||
}
|
||||
else
|
||||
{
|
||||
cache[POWERCFG] &= ~(1 << 13);
|
||||
}
|
||||
si4700_write_masked(POWERCFG, value ? POWERCFG_MONO : 0,
|
||||
POWERCFG_MONO);
|
||||
break;
|
||||
|
||||
default:
|
||||
return -1;
|
||||
}
|
||||
|
||||
si4700_write(5);
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
@ -241,15 +453,25 @@ int si4700_get(int setting)
|
|||
break;
|
||||
|
||||
case RADIO_TUNED:
|
||||
val = 1;
|
||||
val = si4700_tuned();
|
||||
break;
|
||||
|
||||
case RADIO_STEREO:
|
||||
si4700_read(1);
|
||||
val = (cache[STATUSRSSI] & (1 << 8)); /* ST high == Stereo */
|
||||
val = si4700_st();
|
||||
break;
|
||||
}
|
||||
|
||||
return val;
|
||||
}
|
||||
|
||||
void si4700_dbg_info(struct si4700_dbg_info *nfo)
|
||||
{
|
||||
memset(nfo->regs, 0, sizeof (nfo->regs));
|
||||
|
||||
if (tuner_powered())
|
||||
{
|
||||
si4700_read(16);
|
||||
memcpy(nfo->regs, cache, sizeof (nfo->regs));
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -202,26 +202,33 @@
|
|||
#define SW_MUX_CTL_GPIO1_0_GPIO1_1_GPIO1_2_GPIO1_3 IOMUXC_(0x14C)
|
||||
#define SW_MUX_CTL_CAPTURE_COMPARE_WATCHDOG_RST_PWMO IOMUXC_(0x150)
|
||||
|
||||
#define SW_MUX_OUT_EN_GPIO_DR 0x0
|
||||
#define SW_MUX_OUT_FUNCTIONAL 0x1
|
||||
#define SW_MUX_OUT_ALTERNATE_1 0x2
|
||||
#define SW_MUX_OUT_ALTERNATE_2 0x3
|
||||
#define SW_MUX_OUT_ALTERNATE_3 0x4
|
||||
#define SW_MUX_OUT_ALTERNATE_4 0x5
|
||||
#define SW_MUX_OUT_ALTERNATE_5 0x6
|
||||
#define SW_MUX_OUT_ALTERNATE_6 0x7
|
||||
#define SW_MUX_OUT (0x7 << 4)
|
||||
#define SW_MUX_OUT_GPIO_DR (0x0 << 4)
|
||||
#define SW_MUX_OUT_FUNCTIONAL (0x1 << 4)
|
||||
#define SW_MUX_OUT_ALT1 (0x2 << 4)
|
||||
#define SW_MUX_OUT_ALT2 (0x3 << 4)
|
||||
#define SW_MUX_OUT_ALT3 (0x4 << 4)
|
||||
#define SW_MUX_OUT_ALT4 (0x5 << 4)
|
||||
#define SW_MUX_OUT_ALT5 (0x6 << 4)
|
||||
#define SW_MUX_OUT_ALT6 (0x7 << 4)
|
||||
|
||||
#define SW_MUX_IN_NO_INPUTS 0x0
|
||||
#define SW_MUX_IN_GPIO_PSR_ISR 0x1
|
||||
#define SW_MUX_IN_FUNCTIONAL 0x2
|
||||
#define SW_MUX_IN_ALTERNATE_1 0x3
|
||||
#define SW_MUX_IN_ALTERNATE_2 0x4
|
||||
#define SW_MUX_IN (0xf << 0)
|
||||
#define SW_MUX_IN_NO_INPUTS (0x0 << 0)
|
||||
#define SW_MUX_IN_GPIO_PSR_ISR (0x1 << 0)
|
||||
#define SW_MUX_IN_FUNCTIONAL (0x2 << 0)
|
||||
#define SW_MUX_IN_ALT1 (0x4 << 0)
|
||||
#define SW_MUX_IN_ALT2 (0x8 << 0)
|
||||
|
||||
/* Masks for each signal field */
|
||||
#define SW_MUX_CTL_SIG1 (0x7f << 0)
|
||||
#define SW_MUX_CTL_SIG2 (0x7f << 8)
|
||||
#define SW_MUX_CTL_SIG3 (0x7f << 16)
|
||||
#define SW_MUX_CTL_SIG4 (0x7f << 24)
|
||||
/* Shift above flags into one of the four fields in each register */
|
||||
#define SW_MUX_CTL_FLD_0(x) ((x) << 0)
|
||||
#define SW_MUX_CTL_FLD_1(x) ((x) << 8)
|
||||
#define SW_MUX_CTL_FLD_2(x) ((x) << 16)
|
||||
#define SW_MUX_CTL_FLD_3(x) ((x) << 24)
|
||||
#define SW_MUX_CTL_SIG1w(x) (((x) << 0) & SW_MUX_CTL_SIG1)
|
||||
#define SW_MUX_CTL_SIG2w(x) (((x) << 8) & SW_MUX_CTL_SIG2)
|
||||
#define SW_MUX_CTL_SIG3w(x) (((x) << 16) & SW_MUX_CTL_SIG3)
|
||||
#define SW_MUX_CTL_SIG4w(x) (((x) << 24) & SW_MUX_CTL_SIG4)
|
||||
|
||||
/* SW_PAD_CTL */
|
||||
#define SW_PAD_CTL_TTM_PAD__X__X IOMUXC_(0x154)
|
||||
|
@ -336,36 +343,39 @@
|
|||
#define SW_PAD_CTL_CAPTURE_COMPARE_WATCHDOG_RST IOMUXC_(0x308)
|
||||
|
||||
/* SW_PAD_CTL flags */
|
||||
#define SW_PAD_CTL_LOOPBACK (1 << 9)
|
||||
#define SW_PAD_CTL_DISABLE_PULL_UP_DOWN_AND_KEEPER (0 << 7)
|
||||
#if 0 /* Same as 0 */
|
||||
#define SW_PAD_CTL_DISABLE_PULL_UP_DOWN_AND_KEEPER (1 << 7)
|
||||
#endif
|
||||
#define SW_PAD_CTL_ENABLE_KEEPER (2 << 7)
|
||||
#define SW_PAD_CTL_ENABLE_PULL_UP_OR_PULL_DOWN (3 << 7)
|
||||
#define SW_PAD_CTL_100K_PULL_DOWN (0 << 5)
|
||||
#define SW_PAD_CTL_100K_PULL_UP (1 << 5)
|
||||
#define SW_PAD_CTL_LOOPBACK (0x1 << 9) /* Route output to input */
|
||||
/* Pullup, pulldown and keeper enable */
|
||||
#define SW_PAD_CTL_PUE_PKE (0x3 << 7)
|
||||
#define SW_PAD_CTL_PUE_PKE_DISABLE (0x0 << 7)
|
||||
#define SW_PAD_CTL_PUE_PKE_DISABLE_2 (0x1 << 7) /* Same as 0x0 */
|
||||
#define SW_PAD_CTL_PUE_PKE_KEEPER (0x2 << 7)
|
||||
#define SW_PAD_CTL_PUE_PKE_PULLUPDOWN (0x3 << 7) /* Enb. Pull up or down */
|
||||
/* Pullup/down resistance */
|
||||
#define SW_PAD_CTL_PUS (0x3 << 5)
|
||||
#define SW_PAD_CTL_PUS_DOWN_100K (0x0 << 5)
|
||||
#define SW_PAD_CTL_PUS_UP_100K (0x1 << 5)
|
||||
#if 0 /* Completeness */
|
||||
#define SW_PAD_CTL_47K_PULL_UP (2 << 5) /* Not in IMX31/L */
|
||||
#define SW_PAD_CTL_22K_PULL_UP (3 << 5) /* Not in IMX31/L */
|
||||
#define SW_PAD_CTL_PUS_UP_47K (0x2 << 5) /* Not in IMX31/L */
|
||||
#define SW_PAD_CTL_PUS_UP_22K (0x3 << 5) /* Not in IMX31/L */
|
||||
#endif
|
||||
#define SW_PAD_CTL_IPP_HYS_STD (0 << 4)
|
||||
#define SW_PAD_CTL_IPP_HYS_SCHIMDT (1 << 4)
|
||||
#define SW_PAD_CTL_IPP_ODE_CMOS (0 << 3)
|
||||
#define SW_PAD_CTL_IPP_ODE_OPEN (1 << 3)
|
||||
#define SW_PAD_CTL_IPP_DSE_STD (0 << 1)
|
||||
#define SW_PAD_CTL_IPP_DSE_HIGH (1 << 1)
|
||||
#define SW_PAD_CTL_IPP_DSE_MAX (2 << 1)
|
||||
#if 0 /* Same as 2 */
|
||||
#define SW_PAD_CTL_IPP_DSE_MAX (3 << 1)
|
||||
#endif
|
||||
#define SW_PAD_CTL_IPP_SRE_SLOW (0 << 0)
|
||||
#define SW_PAD_CTL_IPP_SRE_FAST (1 << 0)
|
||||
#define SW_PAD_CTL_HYS (0x1 << 4) /* Schmitt trigger input */
|
||||
#define SW_PAD_CTL_ODE (0x1 << 3) /* Open drain output 0=CMOS pushpull*/
|
||||
#define SW_PAD_CTL_DSE (0x3 << 1)
|
||||
#define SW_PAD_CTL_DSE_STD (0x0 << 1) /* Drive strength */
|
||||
#define SW_PAD_CTL_DSE_HIGH (0x1 << 1)
|
||||
#define SW_PAD_CTL_DSE_MAX (0x2 << 1)
|
||||
#define SW_PAD_CTL_DSE_MAX_2 (0x3 << 1) /* Same as 0x2 */
|
||||
#define SW_PAD_CTL_SRE (0x1 << 0) /* Slew rate, 1=fast */
|
||||
|
||||
/* Masks for each IO field */
|
||||
#define SW_PAD_CTL_IO1 (0x3ff << 0)
|
||||
#define SW_PAD_CTL_IO2 (0x3ff << 10)
|
||||
#define SW_PAD_CTL_IO3 (0x3ff << 20)
|
||||
|
||||
/* Shift above flags into one of the three fields in each register */
|
||||
#define SW_PAD_CTL_FLD_0(x) ((x) << 0)
|
||||
#define SW_PAD_CTL_FLD_1(x) ((x) << 10)
|
||||
#define SW_PAD_CTL_FLD_2(x) ((x) << 20)
|
||||
#define SW_PAD_CTL_IO1w(x) (((x) << 0) & SW_PAD_CTL_IO1)
|
||||
#define SW_PAD_CTL_IO2w(x) (((x) << 10) & SW_PAD_CTL_IO2)
|
||||
#define SW_PAD_CTL_IO3w(x) (((x) << 20) & SW_PAD_CTL_IO3)
|
||||
|
||||
/* RNGA */
|
||||
#define RNGA_CONTROL (*(REG32_PTR_T)(RNGA_BASE_ADDR+0x00))
|
||||
|
|
|
@ -95,6 +95,7 @@ bool spdif_powered(void);
|
|||
|
||||
#if CONFIG_TUNER
|
||||
bool tuner_power(bool status);
|
||||
bool tuner_powered(void);
|
||||
#endif
|
||||
|
||||
#endif /* _POWER_H_ */
|
||||
|
|
|
@ -36,9 +36,15 @@ struct si4700_region_data
|
|||
|
||||
extern const struct si4700_region_data si4700_region_data[TUNER_NUM_REGIONS];
|
||||
|
||||
struct si4700_dbg_info
|
||||
{
|
||||
uint16_t regs[16]; /* Read registers */
|
||||
};
|
||||
|
||||
void si4700_init(void);
|
||||
int si4700_set(int setting, int value);
|
||||
int si4700_get(int setting);
|
||||
void si4700_dbg_info(struct si4700_dbg_info *nfo);
|
||||
|
||||
#ifndef CONFIG_TUNER_MULTI
|
||||
#define tuner_set si4700_set
|
||||
|
|
|
@ -54,9 +54,21 @@ void ide_power_enable(bool on)
|
|||
}
|
||||
|
||||
#if CONFIG_TUNER
|
||||
static bool tuner_on = false;
|
||||
|
||||
bool tuner_power(bool status)
|
||||
{
|
||||
(void)status;
|
||||
return false;
|
||||
if (status != tuner_on)
|
||||
{
|
||||
tuner_on = status;
|
||||
status = !status;
|
||||
}
|
||||
|
||||
return status;
|
||||
}
|
||||
|
||||
bool tuner_powered(void)
|
||||
{
|
||||
return tuner_on; /* No debug info */
|
||||
}
|
||||
#endif
|
||||
|
|
|
@ -21,6 +21,7 @@
|
|||
****************************************************************************/
|
||||
#include "config.h"
|
||||
#include "system.h"
|
||||
#include "mc13783.h"
|
||||
#include "i2c-imx31.h"
|
||||
#include "fmradio_i2c.h"
|
||||
|
||||
|
@ -33,9 +34,77 @@ static struct i2c_node si4700_i2c_node =
|
|||
.addr = (0x20),
|
||||
};
|
||||
|
||||
void fmradio_i2c_init(void)
|
||||
{
|
||||
/* RST: LOW */
|
||||
imx31_regclr32(&GPIO1_DR, (1 << 26));
|
||||
/* RST: OUT */
|
||||
imx31_regset32(&GPIO1_GDIR, (1 << 26));
|
||||
|
||||
/* I2C2 SCL: IN, I2C2: SDA IN */
|
||||
imx31_regclr32(&GPIO2_GDIR, (3 << 14));
|
||||
/* I2C2 SCL LO, I2C2 SDA LO */
|
||||
imx31_regclr32(&GPIO2_DR, (3 << 14));
|
||||
|
||||
/* open-drain pins - external pullups on PCB. Pullup default but
|
||||
* disabled */
|
||||
imx31_regmod32(&SW_PAD_CTL_DSR_DTE1_RI_DTE1_DCD_DTE1,
|
||||
/* RI_DTE1 (I2C2_SCLK) */
|
||||
SW_PAD_CTL_IO2w(SW_PAD_CTL_PUE_PKE_DISABLE |
|
||||
SW_PAD_CTL_PUS_UP_100K |
|
||||
SW_PAD_CTL_HYS |
|
||||
SW_PAD_CTL_ODE) |
|
||||
/* DCD_DTE1 (I2C2_SDA) */
|
||||
SW_PAD_CTL_IO1w(SW_PAD_CTL_PUE_PKE_DISABLE |
|
||||
SW_PAD_CTL_PUS_UP_100K |
|
||||
SW_PAD_CTL_HYS |
|
||||
SW_PAD_CTL_ODE),
|
||||
SW_PAD_CTL_IO2 | SW_PAD_CTL_IO1);
|
||||
/* set outputs to I2C2 */
|
||||
imx31_regmod32(&SW_MUX_CTL_RI_DTE1_DCD_DTE1_DTR_DCE2_RXD2,
|
||||
/* RI_DTE1 => I2C2_SCLK */
|
||||
SW_MUX_CTL_SIG4w(SW_MUX_OUT_ALT2 | SW_MUX_IN_ALT2) |
|
||||
/* DCD_DTE1 => I2C2_SDA */
|
||||
SW_MUX_CTL_SIG3w(SW_MUX_OUT_ALT2 | SW_MUX_IN_ALT2),
|
||||
SW_MUX_CTL_SIG4 | SW_MUX_CTL_SIG3);
|
||||
}
|
||||
|
||||
void fmradio_i2c_enable(bool enable)
|
||||
{
|
||||
i2c_enable_node(&si4700_i2c_node, enable);
|
||||
if (enable)
|
||||
{
|
||||
uint32_t io_pin_mux = SW_MUX_CTL_RI_DTE1_DCD_DTE1_DTR_DCE2_RXD2;
|
||||
/* place in GPIO mode to hold SDIO low during RESET release,
|
||||
* SEN1 should be high already (pullup) and GPIO3 left alone */
|
||||
imx31_regset32(&GPIO2_GDIR, (1 << 15)); /* SDIO OUT */
|
||||
/* I2C2_SDA => MCU2_15 */
|
||||
imx31_regmod32(&SW_MUX_CTL_RI_DTE1_DCD_DTE1_DTR_DCE2_RXD2,
|
||||
SW_MUX_CTL_SIG3w(SW_MUX_OUT_GPIO_DR | SW_MUX_IN_GPIO_PSR_ISR),
|
||||
SW_MUX_CTL_SIG3);
|
||||
/* enable CLK32KMCU clock */
|
||||
mc13783_set(MC13783_POWER_CONTROL0, MC13783_CLK32KMCUEN);
|
||||
/* enable the fm chip (release RESET) */
|
||||
imx31_regset32(&GPIO1_DR, (1 << 26));
|
||||
sleep(HZ/100);
|
||||
/* busmode should be selected - OK to release SDIO */
|
||||
imx31_regclr32(&GPIO2_GDIR, (1 << 15)); /* SDIO IN */
|
||||
/* restore pin mux (DCD_DTE1 => I2C2_SDA) */
|
||||
imx31_regmod32(&SW_MUX_CTL_RI_DTE1_DCD_DTE1_DTR_DCE2_RXD2,
|
||||
io_pin_mux, SW_MUX_CTL_SIG3);
|
||||
/* the si4700 is the only thing connected to i2c2 so
|
||||
we can diable the i2c module when not in use */
|
||||
i2c_enable_node(&si4700_i2c_node, true);
|
||||
}
|
||||
else
|
||||
{
|
||||
/* the si4700 is the only thing connected to i2c2 so
|
||||
we can diable the i2c module when not in use */
|
||||
i2c_enable_node(&si4700_i2c_node, false);
|
||||
/* disable the fm chip */
|
||||
imx31_regclr32(&GPIO1_DR, (1 << 26));
|
||||
/* disable CLK32KMCU clock */
|
||||
mc13783_clear(MC13783_POWER_CONTROL0, MC13783_CLK32KMCUEN);
|
||||
}
|
||||
}
|
||||
|
||||
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)
|
|||
return 0;
|
||||
}
|
||||
|
||||
int si4700_st(void)
|
||||
{
|
||||
return (GPIO1_DR & (1 << 28)) >> 28;
|
||||
}
|
||||
|
|
|
@ -98,37 +98,24 @@ bool ide_powered(void)
|
|||
}
|
||||
|
||||
#if CONFIG_TUNER
|
||||
static bool tuner_on = false;
|
||||
|
||||
bool tuner_power(bool status)
|
||||
{
|
||||
static bool tuner_powered = false;
|
||||
if (status != tuner_on)
|
||||
{
|
||||
tuner_on = status;
|
||||
/* Handle power and pin setup */
|
||||
fmradio_i2c_enable(status);
|
||||
status = !status;
|
||||
}
|
||||
|
||||
if (status == tuner_powered)
|
||||
return status;
|
||||
}
|
||||
|
||||
tuner_powered = status;
|
||||
|
||||
if (status)
|
||||
{
|
||||
/* the si4700 is the only thing connected to i2c2 so
|
||||
we can diable the i2c module when not in use */
|
||||
fmradio_i2c_enable(true);
|
||||
/* enable the fm chip */
|
||||
imx31_regset32(&GPIO1_DR, (1 << 26));
|
||||
/* enable CLK32KMCU clock */
|
||||
mc13783_set(MC13783_POWER_CONTROL0, MC13783_CLK32KMCUEN);
|
||||
}
|
||||
else
|
||||
{
|
||||
/* the si4700 is the only thing connected to i2c2 so
|
||||
we can diable the i2c module when not in use */
|
||||
fmradio_i2c_enable(false);
|
||||
/* disable the fm chip */
|
||||
imx31_regclr32(&GPIO1_DR, (1 << 26));
|
||||
/* disable CLK32KMCU clock */
|
||||
mc13783_clear(MC13783_POWER_CONTROL0, MC13783_CLK32KMCUEN);
|
||||
}
|
||||
|
||||
return !status;
|
||||
bool tuner_powered(void)
|
||||
{
|
||||
return tuner_on;
|
||||
}
|
||||
#endif /* #if CONFIG_TUNER */
|
||||
|
||||
|
@ -151,6 +138,10 @@ void power_off(void)
|
|||
|
||||
void power_init(void)
|
||||
{
|
||||
#if CONFIG_TUNER
|
||||
fmradio_i2c_init();
|
||||
#endif
|
||||
|
||||
/* Poll initial state */
|
||||
charger_main_detect_event();
|
||||
|
||||
|
|
|
@ -64,7 +64,7 @@ const struct si4700_region_data si4700_region_data[TUNER_NUM_REGIONS] =
|
|||
{
|
||||
[REGION_EUROPE] = { 1, 0, 2 }, /* 50uS, US/Europe band, 50kHz spacing */
|
||||
[REGION_US_CANADA] = { 0, 0, 0 }, /* 75uS, US/Europe band, 200kHz spacing */
|
||||
[REGION_JAPAN] = { 1, 1, 1 }, /* 50uS, Japanese band, 100kHz spacing */
|
||||
[REGION_JAPAN] = { 1, 2, 1 }, /* 50uS, Japanese band, 100kHz spacing */
|
||||
[REGION_KOREA] = { 1, 0, 1 }, /* 50uS, US/Europe band, 100kHz spacing */
|
||||
};
|
||||
#endif /* (CONFIG_TUNER & SI4700) */
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue