diff options
author | tvboxspy <tvboxspy@gmail.com> | 2011-09-21 18:06:58 -0400 |
---|---|---|
committer | Mauro Carvalho Chehab <mchehab@redhat.com> | 2011-09-23 22:08:17 -0400 |
commit | 7c2808e2fd4c30a19268215c2958d4a340f057c5 (patch) | |
tree | 1f2e94c1cbcf0fe1af2a07c5d00c8a971582fb8a | |
parent | 2ba0f94796febc26bbb12095f6ad15c2397de474 (diff) |
[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>
-rw-r--r-- | drivers/media/dvb/frontends/it913x-fe-priv.h | 24 | ||||
-rw-r--r-- | drivers/media/dvb/frontends/it913x-fe.c | 139 |
2 files changed, 113 insertions, 50 deletions
diff --git a/drivers/media/dvb/frontends/it913x-fe-priv.h b/drivers/media/dvb/frontends/it913x-fe-priv.h index b80634abe62c..40e1d9b266e3 100644 --- a/drivers/media/dvb/frontends/it913x-fe-priv.h +++ b/drivers/media/dvb/frontends/it913x-fe-priv.h | |||
@@ -316,27 +316,13 @@ static struct it913xset it9137_set[] = { | |||
316 | {0xff, 0x0000, {0x00}, 0x00}, /* Terminating Entry */ | 316 | {0xff, 0x0000, {0x00}, 0x00}, /* Terminating Entry */ |
317 | }; | 317 | }; |
318 | 318 | ||
319 | static struct it913xset it9137_tuner[] = { | ||
320 | {PRO_DMOD, 0xec57, {0x00}, 0x01}, | ||
321 | {PRO_DMOD, 0xec58, {0x00}, 0x01}, | ||
322 | {PRO_DMOD, 0xec40, {0x00}, 0x01}, | ||
323 | {PRO_DMOD, 0xec02, { 0x00, 0x0c, 0x00, 0x40, 0x00, 0x80, 0x80, | ||
324 | 0x00, 0x00, 0x00, 0x00 }, 0x0b}, | ||
325 | {PRO_DMOD, 0xec0d, { 0x00, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, | ||
326 | 0x00, 0x00, 0x00, 0x00 }, 0x0b}, | ||
327 | {PRO_DMOD, 0xec19, { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, | ||
328 | 0x00, 0x00}, 0x08}, | ||
329 | {PRO_DMOD, 0xec22, { 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, | ||
330 | 0x00, 0x00, 0x00 }, 0x0a}, | ||
331 | {PRO_DMOD, 0xec3f, {0x01}, 0x01}, | ||
332 | /* Clear any existing tune */ | ||
333 | {PRO_DMOD, 0xec4c, {0xa8, 0x00, 0x00, 0x00, 0x00}, 0x05}, | ||
334 | {0xff, 0x0000, {0x00}, 0x00}, /* Terminating Entry */ | ||
335 | }; | ||
336 | |||
337 | static struct it913xset set_it9137_template[] = { | 319 | static struct it913xset set_it9137_template[] = { |
338 | {PRO_DMOD, 0xee06, {0x00}, 0x01}, | 320 | {PRO_DMOD, 0xee06, {0x00}, 0x01}, |
339 | {PRO_DMOD, 0xec56, {0x00}, 0x01}, | 321 | {PRO_DMOD, 0xec56, {0x00}, 0x01}, |
340 | {PRO_DMOD, 0xec4c, {0x00, 0x00, 0x00, 0x00, 0x00}, 0x05}, | 322 | {PRO_DMOD, 0xec4c, {0x00}, 0x01}, |
323 | {PRO_DMOD, 0xec4d, {0x00}, 0x01}, | ||
324 | {PRO_DMOD, 0xec4e, {0x00}, 0x01}, | ||
325 | {PRO_DMOD, 0xec4f, {0x00}, 0x01}, | ||
326 | {PRO_DMOD, 0xec50, {0x00}, 0x01}, | ||
341 | {0xff, 0x0000, {0x00}, 0x00}, /* Terminating Entry */ | 327 | {0xff, 0x0000, {0x00}, 0x00}, /* Terminating Entry */ |
342 | }; | 328 | }; |
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 { | |||
58 | u8 tuner_type; | 58 | u8 tuner_type; |
59 | struct adctable *table; | 59 | struct adctable *table; |
60 | fe_status_t it913x_status; | 60 | fe_status_t it913x_status; |
61 | u16 tun_xtal; | ||
62 | u8 tun_fdiv; | ||
63 | u8 tun_clk_mode; | ||
64 | u32 tun_fn_min; | ||
61 | }; | 65 | }; |
62 | 66 | ||
63 | static int it913x_read_reg(struct it913x_fe_state *state, | 67 | 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, | |||
159 | return 0; | 163 | return 0; |
160 | } | 164 | } |
161 | 165 | ||
166 | static int it913x_init_tuner(struct it913x_fe_state *state) | ||
167 | { | ||
168 | int ret, i, reg; | ||
169 | u8 val, nv_val; | ||
170 | u8 nv[] = {48, 32, 24, 16, 12, 8, 6, 4, 2}; | ||
171 | u8 b[2]; | ||
172 | |||
173 | reg = it913x_read_reg_u8(state, 0xec86); | ||
174 | switch (reg) { | ||
175 | case 0: | ||
176 | state->tun_clk_mode = reg; | ||
177 | state->tun_xtal = 2000; | ||
178 | state->tun_fdiv = 3; | ||
179 | val = 16; | ||
180 | break; | ||
181 | case -ENODEV: | ||
182 | return -ENODEV; | ||
183 | case 1: | ||
184 | default: | ||
185 | state->tun_clk_mode = reg; | ||
186 | state->tun_xtal = 640; | ||
187 | state->tun_fdiv = 1; | ||
188 | val = 6; | ||
189 | break; | ||
190 | } | ||
191 | |||
192 | reg = it913x_read_reg_u8(state, 0xed03); | ||
193 | |||
194 | if (reg < 0) | ||
195 | return -ENODEV; | ||
196 | else if (reg < sizeof(nv)) | ||
197 | nv_val = nv[reg]; | ||
198 | else | ||
199 | nv_val = 2; | ||
200 | |||
201 | for (i = 0; i < 50; i++) { | ||
202 | ret = it913x_read_reg(state, 0xed23, &b[0], sizeof(b)); | ||
203 | reg = (b[1] << 8) + b[0]; | ||
204 | if (reg > 0) | ||
205 | break; | ||
206 | if (ret < 0) | ||
207 | return -ENODEV; | ||
208 | udelay(2000); | ||
209 | } | ||
210 | state->tun_fn_min = state->tun_xtal * reg; | ||
211 | state->tun_fn_min /= (state->tun_fdiv * nv_val); | ||
212 | deb_info("Tuner fn_min %d", state->tun_fn_min); | ||
213 | |||
214 | for (i = 0; i < 50; i++) { | ||
215 | reg = it913x_read_reg_u8(state, 0xec82); | ||
216 | if (reg > 0) | ||
217 | break; | ||
218 | if (reg < 0) | ||
219 | return -ENODEV; | ||
220 | udelay(2000); | ||
221 | } | ||
222 | |||
223 | return it913x_write_reg(state, PRO_DMOD, 0xed81, val); | ||
224 | } | ||
225 | |||
162 | static int it9137_set_tuner(struct it913x_fe_state *state, | 226 | static int it9137_set_tuner(struct it913x_fe_state *state, |
163 | enum fe_bandwidth bandwidth, u32 frequency_m) | 227 | enum fe_bandwidth bandwidth, u32 frequency_m) |
164 | { | 228 | { |
165 | struct it913xset *set_tuner = set_it9137_template; | 229 | struct it913xset *set_tuner = set_it9137_template; |
166 | int ret; | 230 | int ret, reg; |
167 | u32 frequency = frequency_m / 1000; | 231 | u32 frequency = frequency_m / 1000; |
168 | u32 freq; | 232 | u32 freq, temp_f, tmp; |
233 | u16 iqik_m_cal; | ||
169 | u16 n_div; | 234 | u16 n_div; |
170 | u8 n; | 235 | u8 n; |
171 | u8 l_band; | 236 | u8 l_band; |
@@ -218,10 +283,11 @@ static int it9137_set_tuner(struct it913x_fe_state *state, | |||
218 | bw = 6; | 283 | bw = 6; |
219 | else | 284 | else |
220 | bw = 6; | 285 | bw = 6; |
286 | |||
221 | set_tuner[1].reg[0] = bw; | 287 | set_tuner[1].reg[0] = bw; |
222 | set_tuner[2].reg[0] = 0xa0 | (l_band << 3); | 288 | set_tuner[2].reg[0] = 0xa0 | (l_band << 3); |
223 | 289 | ||
224 | if (frequency > 49000 && frequency <= 74000) { | 290 | if (frequency > 53000 && frequency <= 74000) { |
225 | n_div = 48; | 291 | n_div = 48; |
226 | n = 0; | 292 | n = 0; |
227 | } else if (frequency > 74000 && frequency <= 111000) { | 293 | } else if (frequency > 74000 && frequency <= 111000) { |
@@ -239,10 +305,10 @@ static int it9137_set_tuner(struct it913x_fe_state *state, | |||
239 | } else if (frequency > 296000 && frequency <= 445000) { | 305 | } else if (frequency > 296000 && frequency <= 445000) { |
240 | n_div = 8; | 306 | n_div = 8; |
241 | n = 5; | 307 | n = 5; |
242 | } else if (frequency > 445000 && frequency <= 560000) { | 308 | } else if (frequency > 445000 && frequency <= state->tun_fn_min) { |
243 | n_div = 6; | 309 | n_div = 6; |
244 | n = 6; | 310 | n = 6; |
245 | } else if (frequency > 560000 && frequency <= 860000) { | 311 | } else if (frequency > state->tun_fn_min && frequency <= 950000) { |
246 | n_div = 4; | 312 | n_div = 4; |
247 | n = 7; | 313 | n = 7; |
248 | } else if (frequency > 1450000 && frequency <= 1680000) { | 314 | } else if (frequency > 1450000 && frequency <= 1680000) { |
@@ -251,26 +317,47 @@ static int it9137_set_tuner(struct it913x_fe_state *state, | |||
251 | } else | 317 | } else |
252 | return -EINVAL; | 318 | return -EINVAL; |
253 | 319 | ||
320 | reg = it913x_read_reg_u8(state, 0xed81); | ||
321 | iqik_m_cal = (u16)reg * n_div; | ||
254 | 322 | ||
255 | /* Frequency + 3000 TODO not sure this is bandwidth setting */ | 323 | if (reg < 0x20) { |
256 | /* Xtal frequency 21327? but it works */ | 324 | if (state->tun_clk_mode == 0) |
257 | freq = (u32) (n_div * 32 * (frequency + 3000) / 21327); | 325 | iqik_m_cal = (iqik_m_cal * 9) >> 5; |
258 | freq += (u32) n << 13; | 326 | else |
259 | set_tuner[2].reg[1] = freq & 0xff; | 327 | iqik_m_cal >>= 1; |
260 | set_tuner[2].reg[2] = (freq >> 8) & 0xff; | 328 | } else { |
329 | iqik_m_cal = 0x40 - iqik_m_cal; | ||
330 | if (state->tun_clk_mode == 0) | ||
331 | iqik_m_cal = ~((iqik_m_cal * 9) >> 5); | ||
332 | else | ||
333 | iqik_m_cal = ~(iqik_m_cal >> 1); | ||
334 | } | ||
335 | |||
336 | temp_f = frequency * (u32)n_div * (u32)state->tun_fdiv; | ||
337 | freq = temp_f / state->tun_xtal; | ||
338 | tmp = freq * state->tun_xtal; | ||
339 | |||
340 | if ((temp_f - tmp) >= (state->tun_xtal >> 1)) | ||
341 | freq++; | ||
261 | 342 | ||
262 | /* frequency */ | ||
263 | freq = (u32) (n_div * 32 * frequency / 21327); | ||
264 | freq += (u32) n << 13; | 343 | freq += (u32) n << 13; |
265 | set_tuner[2].reg[3] = freq & 0xff; | 344 | /* Frequency OMEGA_IQIK_M_CAL_MID*/ |
266 | set_tuner[2].reg[4] = (freq >> 8) & 0xff; | 345 | temp_f = freq + (u32)iqik_m_cal; |
267 | 346 | ||
268 | deb_info("Frequency = %08x, Bandwidth = %02x, ", freq, bw); | 347 | set_tuner[3].reg[0] = temp_f & 0xff; |
348 | set_tuner[4].reg[0] = (temp_f >> 8) & 0xff; | ||
349 | |||
350 | deb_info("High Frequency = %04x", temp_f); | ||
351 | |||
352 | /* Lower frequency */ | ||
353 | set_tuner[5].reg[0] = freq & 0xff; | ||
354 | set_tuner[6].reg[0] = (freq >> 8) & 0xff; | ||
355 | |||
356 | deb_info("low Frequency = %04x", freq); | ||
269 | 357 | ||
270 | ret = it913x_fe_script_loader(state, set_tuner); | 358 | ret = it913x_fe_script_loader(state, set_tuner); |
271 | 359 | ||
272 | return (ret < 0) ? -ENODEV : 0; | 360 | return (ret < 0) ? -ENODEV : 0; |
273 | |||
274 | } | 361 | } |
275 | 362 | ||
276 | static int it913x_fe_select_bw(struct it913x_fe_state *state, | 363 | 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) | |||
593 | u32 adc, xtal; | 680 | u32 adc, xtal; |
594 | u8 b[4]; | 681 | u8 b[4]; |
595 | 682 | ||
683 | ret = it913x_init_tuner(state); | ||
684 | |||
596 | if (adf < 12) { | 685 | if (adf < 12) { |
597 | state->crystalFrequency = fe_clockTable[adf].xtal ; | 686 | state->crystalFrequency = fe_clockTable[adf].xtal ; |
598 | state->table = fe_clockTable[adf].table; | 687 | state->table = fe_clockTable[adf].table; |
@@ -612,7 +701,6 @@ static int it913x_fe_start(struct it913x_fe_state *state) | |||
612 | ret |= it913x_write_reg(state, PRO_LINK, GPIOH3_ON, 0x1); | 701 | ret |= it913x_write_reg(state, PRO_LINK, GPIOH3_ON, 0x1); |
613 | ret |= it913x_write_reg(state, PRO_LINK, GPIOH3_O, 0x1); | 702 | ret |= it913x_write_reg(state, PRO_LINK, GPIOH3_O, 0x1); |
614 | 703 | ||
615 | ret |= it913x_write_reg(state, PRO_DMOD, 0xed81, 0x10); | ||
616 | ret |= it913x_write_reg(state, PRO_LINK, 0xf641, state->tuner_type); | 704 | ret |= it913x_write_reg(state, PRO_LINK, 0xf641, state->tuner_type); |
617 | ret |= it913x_write_reg(state, PRO_DMOD, 0xf5ca, 0x01); | 705 | ret |= it913x_write_reg(state, PRO_DMOD, 0xf5ca, 0x01); |
618 | ret |= it913x_write_reg(state, PRO_DMOD, 0xf715, 0x01); | 706 | ret |= it913x_write_reg(state, PRO_DMOD, 0xf715, 0x01); |
@@ -635,6 +723,7 @@ static int it913x_fe_start(struct it913x_fe_state *state) | |||
635 | default: | 723 | default: |
636 | return -EINVAL; | 724 | return -EINVAL; |
637 | } | 725 | } |
726 | |||
638 | /* set the demod */ | 727 | /* set the demod */ |
639 | ret = it913x_fe_script_loader(state, set_fe); | 728 | ret = it913x_fe_script_loader(state, set_fe); |
640 | /* Always solo frontend */ | 729 | /* Always solo frontend */ |
@@ -648,20 +737,8 @@ static int it913x_fe_start(struct it913x_fe_state *state) | |||
648 | static int it913x_fe_init(struct dvb_frontend *fe) | 737 | static int it913x_fe_init(struct dvb_frontend *fe) |
649 | { | 738 | { |
650 | struct it913x_fe_state *state = fe->demodulator_priv; | 739 | struct it913x_fe_state *state = fe->demodulator_priv; |
651 | struct it913xset *set_tuner; | ||
652 | int ret = 0; | 740 | int ret = 0; |
653 | 741 | ||
654 | switch (state->tuner_type) { | ||
655 | case IT9137: /* Tuner type 0x38 */ | ||
656 | set_tuner = it9137_tuner; | ||
657 | break; | ||
658 | default: | ||
659 | return -EINVAL; | ||
660 | } | ||
661 | |||
662 | /* set any tuner reg(s) */ | ||
663 | ret = it913x_fe_script_loader(state, set_tuner); | ||
664 | |||
665 | it913x_write_reg(state, PRO_DMOD, AFE_MEM0, 0x0); | 742 | it913x_write_reg(state, PRO_DMOD, AFE_MEM0, 0x0); |
666 | 743 | ||
667 | ret |= it913x_fe_script_loader(state, init_1); | 744 | ret |= it913x_fe_script_loader(state, init_1); |
@@ -743,5 +820,5 @@ static struct dvb_frontend_ops it913x_fe_ofdm_ops = { | |||
743 | 820 | ||
744 | MODULE_DESCRIPTION("it913x Frontend and it9137 tuner"); | 821 | MODULE_DESCRIPTION("it913x Frontend and it9137 tuner"); |
745 | MODULE_AUTHOR("Malcolm Priestley tvboxspy@gmail.com"); | 822 | MODULE_AUTHOR("Malcolm Priestley tvboxspy@gmail.com"); |
746 | MODULE_VERSION("1.05"); | 823 | MODULE_VERSION("1.06"); |
747 | MODULE_LICENSE("GPL"); | 824 | MODULE_LICENSE("GPL"); |