diff options
author | tvboxspy <tvboxspy@gmail.com> | 2011-09-22 00:06:58 +0200 |
---|---|---|
committer | Mauro Carvalho Chehab <mchehab@redhat.com> | 2011-09-24 04:08:17 +0200 |
commit | 7c2808e2fd4c30a19268215c2958d4a340f057c5 (patch) | |
tree | 1f2e94c1cbcf0fe1af2a07c5d00c8a971582fb8a /drivers/media/dvb/frontends/it913x-fe.c | |
parent | [media] it913x: add remote control support (diff) | |
download | linux-7c2808e2fd4c30a19268215c2958d4a340f057c5.tar.xz linux-7c2808e2fd4c30a19268215c2958d4a340f057c5.zip |
[media] it913x-fe: correct tuner settings
Correct tuner settings for more accuracy. This now makes the tuner
section more compatible with other versions of the IT913X
series.
TODOs
Version 2 chip
Signed-off-by: Malcolm Priestley <tvboxspy@gmail.com>
Signed-off-by: Mauro Carvalho Chehab <mchehab@redhat.com>
Diffstat (limited to 'drivers/media/dvb/frontends/it913x-fe.c')
-rw-r--r-- | drivers/media/dvb/frontends/it913x-fe.c | 139 |
1 files changed, 108 insertions, 31 deletions
diff --git a/drivers/media/dvb/frontends/it913x-fe.c b/drivers/media/dvb/frontends/it913x-fe.c index c92b3ec3f8a5..02839a8b7b29 100644 --- a/drivers/media/dvb/frontends/it913x-fe.c +++ b/drivers/media/dvb/frontends/it913x-fe.c @@ -58,6 +58,10 @@ struct it913x_fe_state { u8 tuner_type; struct adctable *table; fe_status_t it913x_status; + u16 tun_xtal; + u8 tun_fdiv; + u8 tun_clk_mode; + u32 tun_fn_min; }; static int it913x_read_reg(struct it913x_fe_state *state, @@ -159,13 +163,74 @@ static int it913x_fe_script_loader(struct it913x_fe_state *state, return 0; } +static int it913x_init_tuner(struct it913x_fe_state *state) +{ + int ret, i, reg; + u8 val, nv_val; + u8 nv[] = {48, 32, 24, 16, 12, 8, 6, 4, 2}; + u8 b[2]; + + reg = it913x_read_reg_u8(state, 0xec86); + switch (reg) { + case 0: + state->tun_clk_mode = reg; + state->tun_xtal = 2000; + state->tun_fdiv = 3; + val = 16; + break; + case -ENODEV: + return -ENODEV; + case 1: + default: + state->tun_clk_mode = reg; + state->tun_xtal = 640; + state->tun_fdiv = 1; + val = 6; + break; + } + + reg = it913x_read_reg_u8(state, 0xed03); + + if (reg < 0) + return -ENODEV; + else if (reg < sizeof(nv)) + nv_val = nv[reg]; + else + nv_val = 2; + + for (i = 0; i < 50; i++) { + ret = it913x_read_reg(state, 0xed23, &b[0], sizeof(b)); + reg = (b[1] << 8) + b[0]; + if (reg > 0) + break; + if (ret < 0) + return -ENODEV; + udelay(2000); + } + state->tun_fn_min = state->tun_xtal * reg; + state->tun_fn_min /= (state->tun_fdiv * nv_val); + deb_info("Tuner fn_min %d", state->tun_fn_min); + + for (i = 0; i < 50; i++) { + reg = it913x_read_reg_u8(state, 0xec82); + if (reg > 0) + break; + if (reg < 0) + return -ENODEV; + udelay(2000); + } + + return it913x_write_reg(state, PRO_DMOD, 0xed81, val); +} + static int it9137_set_tuner(struct it913x_fe_state *state, enum fe_bandwidth bandwidth, u32 frequency_m) { struct it913xset *set_tuner = set_it9137_template; - int ret; + int ret, reg; u32 frequency = frequency_m / 1000; - u32 freq; + u32 freq, temp_f, tmp; + u16 iqik_m_cal; u16 n_div; u8 n; u8 l_band; @@ -218,10 +283,11 @@ static int it9137_set_tuner(struct it913x_fe_state *state, bw = 6; else bw = 6; + set_tuner[1].reg[0] = bw; set_tuner[2].reg[0] = 0xa0 | (l_band << 3); - if (frequency > 49000 && frequency <= 74000) { + if (frequency > 53000 && frequency <= 74000) { n_div = 48; n = 0; } else if (frequency > 74000 && frequency <= 111000) { @@ -239,10 +305,10 @@ static int it9137_set_tuner(struct it913x_fe_state *state, } else if (frequency > 296000 && frequency <= 445000) { n_div = 8; n = 5; - } else if (frequency > 445000 && frequency <= 560000) { + } else if (frequency > 445000 && frequency <= state->tun_fn_min) { n_div = 6; n = 6; - } else if (frequency > 560000 && frequency <= 860000) { + } else if (frequency > state->tun_fn_min && frequency <= 950000) { n_div = 4; n = 7; } else if (frequency > 1450000 && frequency <= 1680000) { @@ -251,26 +317,47 @@ static int it9137_set_tuner(struct it913x_fe_state *state, } else return -EINVAL; + reg = it913x_read_reg_u8(state, 0xed81); + iqik_m_cal = (u16)reg * n_div; - /* Frequency + 3000 TODO not sure this is bandwidth setting */ - /* Xtal frequency 21327? but it works */ - freq = (u32) (n_div * 32 * (frequency + 3000) / 21327); - freq += (u32) n << 13; - set_tuner[2].reg[1] = freq & 0xff; - set_tuner[2].reg[2] = (freq >> 8) & 0xff; + if (reg < 0x20) { + if (state->tun_clk_mode == 0) + iqik_m_cal = (iqik_m_cal * 9) >> 5; + else + iqik_m_cal >>= 1; + } else { + iqik_m_cal = 0x40 - iqik_m_cal; + if (state->tun_clk_mode == 0) + iqik_m_cal = ~((iqik_m_cal * 9) >> 5); + else + iqik_m_cal = ~(iqik_m_cal >> 1); + } + + temp_f = frequency * (u32)n_div * (u32)state->tun_fdiv; + freq = temp_f / state->tun_xtal; + tmp = freq * state->tun_xtal; + + if ((temp_f - tmp) >= (state->tun_xtal >> 1)) + freq++; - /* frequency */ - freq = (u32) (n_div * 32 * frequency / 21327); freq += (u32) n << 13; - set_tuner[2].reg[3] = freq & 0xff; - set_tuner[2].reg[4] = (freq >> 8) & 0xff; + /* Frequency OMEGA_IQIK_M_CAL_MID*/ + temp_f = freq + (u32)iqik_m_cal; - deb_info("Frequency = %08x, Bandwidth = %02x, ", freq, bw); + set_tuner[3].reg[0] = temp_f & 0xff; + set_tuner[4].reg[0] = (temp_f >> 8) & 0xff; + + deb_info("High Frequency = %04x", temp_f); + + /* Lower frequency */ + set_tuner[5].reg[0] = freq & 0xff; + set_tuner[6].reg[0] = (freq >> 8) & 0xff; + + deb_info("low Frequency = %04x", freq); ret = it913x_fe_script_loader(state, set_tuner); return (ret < 0) ? -ENODEV : 0; - } static int it913x_fe_select_bw(struct it913x_fe_state *state, @@ -593,6 +680,8 @@ static int it913x_fe_start(struct it913x_fe_state *state) u32 adc, xtal; u8 b[4]; + ret = it913x_init_tuner(state); + if (adf < 12) { state->crystalFrequency = fe_clockTable[adf].xtal ; state->table = fe_clockTable[adf].table; @@ -612,7 +701,6 @@ static int it913x_fe_start(struct it913x_fe_state *state) ret |= it913x_write_reg(state, PRO_LINK, GPIOH3_ON, 0x1); ret |= it913x_write_reg(state, PRO_LINK, GPIOH3_O, 0x1); - ret |= it913x_write_reg(state, PRO_DMOD, 0xed81, 0x10); ret |= it913x_write_reg(state, PRO_LINK, 0xf641, state->tuner_type); ret |= it913x_write_reg(state, PRO_DMOD, 0xf5ca, 0x01); ret |= it913x_write_reg(state, PRO_DMOD, 0xf715, 0x01); @@ -635,6 +723,7 @@ static int it913x_fe_start(struct it913x_fe_state *state) default: return -EINVAL; } + /* set the demod */ ret = it913x_fe_script_loader(state, set_fe); /* Always solo frontend */ @@ -648,20 +737,8 @@ static int it913x_fe_start(struct it913x_fe_state *state) static int it913x_fe_init(struct dvb_frontend *fe) { struct it913x_fe_state *state = fe->demodulator_priv; - struct it913xset *set_tuner; int ret = 0; - switch (state->tuner_type) { - case IT9137: /* Tuner type 0x38 */ - set_tuner = it9137_tuner; - break; - default: - return -EINVAL; - } - - /* set any tuner reg(s) */ - ret = it913x_fe_script_loader(state, set_tuner); - it913x_write_reg(state, PRO_DMOD, AFE_MEM0, 0x0); ret |= it913x_fe_script_loader(state, init_1); @@ -743,5 +820,5 @@ static struct dvb_frontend_ops it913x_fe_ofdm_ops = { MODULE_DESCRIPTION("it913x Frontend and it9137 tuner"); MODULE_AUTHOR("Malcolm Priestley tvboxspy@gmail.com"); -MODULE_VERSION("1.05"); +MODULE_VERSION("1.06"); MODULE_LICENSE("GPL"); |