blob: 72e256ebeb0fcbaded2e5ef4ac5f01a600b0daba [file] [log] [blame]
Michael Krufky5bea1cd2007-10-22 09:56:38 -03001/*
Michael Krufky6ca04de2007-11-23 16:52:15 -03002 tda18271-fe.c - driver for the Philips / NXP TDA18271 silicon tuner
Michael Krufky5bea1cd2007-10-22 09:56:38 -03003
4 Copyright (C) 2007 Michael Krufky (mkrufky@linuxtv.org)
5
6 This program is free software; you can redistribute it and/or modify
7 it under the terms of the GNU General Public License as published by
8 the Free Software Foundation; either version 2 of the License, or
9 (at your option) any later version.
10
11 This program is distributed in the hope that it will be useful,
12 but WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 GNU General Public License for more details.
15
16 You should have received a copy of the GNU General Public License
17 along with this program; if not, write to the Free Software
18 Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
19*/
20
Michael Krufky5bea1cd2007-10-22 09:56:38 -030021#include <linux/delay.h>
22#include <linux/videodev2.h>
Michael Krufky6ca04de2007-11-23 16:52:15 -030023#include "tda18271-priv.h"
Michael Krufky5bea1cd2007-10-22 09:56:38 -030024
Michael Krufkyb5f3e1e2007-12-02 16:36:05 -030025int tda18271_debug;
Michael Krufky54465b02007-11-23 18:14:53 -030026module_param_named(debug, tda18271_debug, int, 0644);
Michael Krufky293da0e2007-12-02 02:45:04 -030027MODULE_PARM_DESC(debug, "set debug level (info=1, map=2, reg=4 (or-able))");
Michael Krufky5bea1cd2007-10-22 09:56:38 -030028
Michael Krufky5bea1cd2007-10-22 09:56:38 -030029/*---------------------------------------------------------------------*/
30
Michael Krufky7d11c532007-10-24 09:55:54 -030031static int tda18271_i2c_gate_ctrl(struct dvb_frontend *fe, int enable)
32{
33 struct tda18271_priv *priv = fe->tuner_priv;
Michael Krufkye435f952007-12-09 22:23:30 -030034 enum tda18271_i2c_gate gate;
Michael Krufky7d11c532007-10-24 09:55:54 -030035 int ret = 0;
36
Michael Krufkye435f952007-12-09 22:23:30 -030037 switch (priv->gate) {
38 case TDA18271_GATE_DIGITAL:
39 case TDA18271_GATE_ANALOG:
40 gate = priv->gate;
41 break;
42 case TDA18271_GATE_AUTO:
43 default:
44 switch (priv->mode) {
45 case TDA18271_DIGITAL:
46 gate = TDA18271_GATE_DIGITAL;
47 break;
48 case TDA18271_ANALOG:
49 default:
50 gate = TDA18271_GATE_ANALOG;
51 break;
52 }
53 }
54
55 switch (gate) {
56 case TDA18271_GATE_ANALOG:
Michael Krufkybc3e5c72007-12-21 11:18:32 -030057 if (fe->ops.analog_ops.i2c_gate_ctrl)
58 ret = fe->ops.analog_ops.i2c_gate_ctrl(fe, enable);
Michael Krufky7d11c532007-10-24 09:55:54 -030059 break;
Michael Krufkye435f952007-12-09 22:23:30 -030060 case TDA18271_GATE_DIGITAL:
Michael Krufky7d11c532007-10-24 09:55:54 -030061 if (fe->ops.i2c_gate_ctrl)
62 ret = fe->ops.i2c_gate_ctrl(fe, enable);
63 break;
Michael Krufkye435f952007-12-09 22:23:30 -030064 default:
65 ret = -EINVAL;
66 break;
Michael Krufky7d11c532007-10-24 09:55:54 -030067 }
68
69 return ret;
70};
71
Michael Krufky5bea1cd2007-10-22 09:56:38 -030072/*---------------------------------------------------------------------*/
73
74static void tda18271_dump_regs(struct dvb_frontend *fe)
75{
76 struct tda18271_priv *priv = fe->tuner_priv;
77 unsigned char *regs = priv->tda18271_regs;
78
Michael Krufky293da0e2007-12-02 02:45:04 -030079 dbg_reg("=== TDA18271 REG DUMP ===\n");
Michael Krufky5d2bf932007-12-02 17:37:38 -030080 dbg_reg("ID_BYTE = 0x%02x\n", 0xff & regs[R_ID]);
81 dbg_reg("THERMO_BYTE = 0x%02x\n", 0xff & regs[R_TM]);
82 dbg_reg("POWER_LEVEL_BYTE = 0x%02x\n", 0xff & regs[R_PL]);
83 dbg_reg("EASY_PROG_BYTE_1 = 0x%02x\n", 0xff & regs[R_EP1]);
84 dbg_reg("EASY_PROG_BYTE_2 = 0x%02x\n", 0xff & regs[R_EP2]);
85 dbg_reg("EASY_PROG_BYTE_3 = 0x%02x\n", 0xff & regs[R_EP3]);
86 dbg_reg("EASY_PROG_BYTE_4 = 0x%02x\n", 0xff & regs[R_EP4]);
87 dbg_reg("EASY_PROG_BYTE_5 = 0x%02x\n", 0xff & regs[R_EP5]);
88 dbg_reg("CAL_POST_DIV_BYTE = 0x%02x\n", 0xff & regs[R_CPD]);
89 dbg_reg("CAL_DIV_BYTE_1 = 0x%02x\n", 0xff & regs[R_CD1]);
90 dbg_reg("CAL_DIV_BYTE_2 = 0x%02x\n", 0xff & regs[R_CD2]);
91 dbg_reg("CAL_DIV_BYTE_3 = 0x%02x\n", 0xff & regs[R_CD3]);
92 dbg_reg("MAIN_POST_DIV_BYTE = 0x%02x\n", 0xff & regs[R_MPD]);
93 dbg_reg("MAIN_DIV_BYTE_1 = 0x%02x\n", 0xff & regs[R_MD1]);
94 dbg_reg("MAIN_DIV_BYTE_2 = 0x%02x\n", 0xff & regs[R_MD2]);
95 dbg_reg("MAIN_DIV_BYTE_3 = 0x%02x\n", 0xff & regs[R_MD3]);
Michael Krufky5bea1cd2007-10-22 09:56:38 -030096}
97
98static void tda18271_read_regs(struct dvb_frontend *fe)
99{
100 struct tda18271_priv *priv = fe->tuner_priv;
101 unsigned char *regs = priv->tda18271_regs;
102 unsigned char buf = 0x00;
103 int ret;
104 struct i2c_msg msg[] = {
105 { .addr = priv->i2c_addr, .flags = 0,
106 .buf = &buf, .len = 1 },
107 { .addr = priv->i2c_addr, .flags = I2C_M_RD,
108 .buf = regs, .len = 16 }
109 };
110
Michael Krufky7d11c532007-10-24 09:55:54 -0300111 tda18271_i2c_gate_ctrl(fe, 1);
Michael Krufky5bea1cd2007-10-22 09:56:38 -0300112
113 /* read all registers */
114 ret = i2c_transfer(priv->i2c_adap, msg, 2);
115
Michael Krufky7d11c532007-10-24 09:55:54 -0300116 tda18271_i2c_gate_ctrl(fe, 0);
Michael Krufky5bea1cd2007-10-22 09:56:38 -0300117
118 if (ret != 2)
119 printk("ERROR: %s: i2c_transfer returned: %d\n",
120 __FUNCTION__, ret);
121
Michael Krufky293da0e2007-12-02 02:45:04 -0300122 if (tda18271_debug & DBG_REG)
Michael Krufky5bea1cd2007-10-22 09:56:38 -0300123 tda18271_dump_regs(fe);
124}
125
126static void tda18271_write_regs(struct dvb_frontend *fe, int idx, int len)
127{
128 struct tda18271_priv *priv = fe->tuner_priv;
129 unsigned char *regs = priv->tda18271_regs;
130 unsigned char buf[TDA18271_NUM_REGS+1];
131 struct i2c_msg msg = { .addr = priv->i2c_addr, .flags = 0,
132 .buf = buf, .len = len+1 };
133 int i, ret;
134
135 BUG_ON((len == 0) || (idx+len > sizeof(buf)));
136
137 buf[0] = idx;
138 for (i = 1; i <= len; i++) {
139 buf[i] = regs[idx-1+i];
140 }
141
Michael Krufky7d11c532007-10-24 09:55:54 -0300142 tda18271_i2c_gate_ctrl(fe, 1);
Michael Krufky5bea1cd2007-10-22 09:56:38 -0300143
144 /* write registers */
145 ret = i2c_transfer(priv->i2c_adap, &msg, 1);
146
Michael Krufky7d11c532007-10-24 09:55:54 -0300147 tda18271_i2c_gate_ctrl(fe, 0);
Michael Krufky5bea1cd2007-10-22 09:56:38 -0300148
149 if (ret != 1)
150 printk(KERN_WARNING "ERROR: %s: i2c_transfer returned: %d\n",
151 __FUNCTION__, ret);
152}
153
154/*---------------------------------------------------------------------*/
155
Michael Krufky22ee1252007-11-22 17:13:00 -0300156static int tda18271_init_regs(struct dvb_frontend *fe)
Michael Krufky5bea1cd2007-10-22 09:56:38 -0300157{
158 struct tda18271_priv *priv = fe->tuner_priv;
159 unsigned char *regs = priv->tda18271_regs;
160
Michael Krufky5bea1cd2007-10-22 09:56:38 -0300161 printk(KERN_INFO "tda18271: initializing registers\n");
162
163 /* initialize registers */
164 regs[R_ID] = 0x83;
165 regs[R_TM] = 0x08;
166 regs[R_PL] = 0x80;
167 regs[R_EP1] = 0xc6;
168 regs[R_EP2] = 0xdf;
169 regs[R_EP3] = 0x16;
170 regs[R_EP4] = 0x60;
171 regs[R_EP5] = 0x80;
172 regs[R_CPD] = 0x80;
173 regs[R_CD1] = 0x00;
174 regs[R_CD2] = 0x00;
175 regs[R_CD3] = 0x00;
176 regs[R_MPD] = 0x00;
177 regs[R_MD1] = 0x00;
178 regs[R_MD2] = 0x00;
179 regs[R_MD3] = 0x00;
180 regs[R_EB1] = 0xff;
181 regs[R_EB2] = 0x01;
182 regs[R_EB3] = 0x84;
183 regs[R_EB4] = 0x41;
184 regs[R_EB5] = 0x01;
185 regs[R_EB6] = 0x84;
186 regs[R_EB7] = 0x40;
187 regs[R_EB8] = 0x07;
188 regs[R_EB9] = 0x00;
189 regs[R_EB10] = 0x00;
190 regs[R_EB11] = 0x96;
191 regs[R_EB12] = 0x0f;
192 regs[R_EB13] = 0xc1;
193 regs[R_EB14] = 0x00;
194 regs[R_EB15] = 0x8f;
195 regs[R_EB16] = 0x00;
196 regs[R_EB17] = 0x00;
197 regs[R_EB18] = 0x00;
198 regs[R_EB19] = 0x00;
199 regs[R_EB20] = 0x20;
200 regs[R_EB21] = 0x33;
201 regs[R_EB22] = 0x48;
202 regs[R_EB23] = 0xb0;
203
204 tda18271_write_regs(fe, 0x00, TDA18271_NUM_REGS);
205 /* setup AGC1 & AGC2 */
206 regs[R_EB17] = 0x00;
207 tda18271_write_regs(fe, R_EB17, 1);
208 regs[R_EB17] = 0x03;
209 tda18271_write_regs(fe, R_EB17, 1);
210 regs[R_EB17] = 0x43;
211 tda18271_write_regs(fe, R_EB17, 1);
212 regs[R_EB17] = 0x4c;
213 tda18271_write_regs(fe, R_EB17, 1);
214
215 regs[R_EB20] = 0xa0;
216 tda18271_write_regs(fe, R_EB20, 1);
217 regs[R_EB20] = 0xa7;
218 tda18271_write_regs(fe, R_EB20, 1);
219 regs[R_EB20] = 0xe7;
220 tda18271_write_regs(fe, R_EB20, 1);
221 regs[R_EB20] = 0xec;
222 tda18271_write_regs(fe, R_EB20, 1);
223
224 /* image rejection calibration */
225
226 /* low-band */
227 regs[R_EP3] = 0x1f;
228 regs[R_EP4] = 0x66;
229 regs[R_EP5] = 0x81;
230 regs[R_CPD] = 0xcc;
231 regs[R_CD1] = 0x6c;
232 regs[R_CD2] = 0x00;
233 regs[R_CD3] = 0x00;
234 regs[R_MPD] = 0xcd;
235 regs[R_MD1] = 0x77;
236 regs[R_MD2] = 0x08;
237 regs[R_MD3] = 0x00;
238
239 tda18271_write_regs(fe, R_EP3, 11);
240 msleep(5); /* pll locking */
241
242 regs[R_EP1] = 0xc6;
243 tda18271_write_regs(fe, R_EP1, 1);
244 msleep(5); /* wanted low measurement */
245
246 regs[R_EP3] = 0x1f;
247 regs[R_EP4] = 0x66;
248 regs[R_EP5] = 0x85;
249 regs[R_CPD] = 0xcb;
250 regs[R_CD1] = 0x66;
251 regs[R_CD2] = 0x70;
252 regs[R_CD3] = 0x00;
253
254 tda18271_write_regs(fe, R_EP3, 7);
255 msleep(5); /* pll locking */
256
257 regs[R_EP2] = 0xdf;
258 tda18271_write_regs(fe, R_EP2, 1);
259 msleep(30); /* image low optimization completion */
260
261 /* mid-band */
262 regs[R_EP3] = 0x1f;
263 regs[R_EP4] = 0x66;
264 regs[R_EP5] = 0x82;
265 regs[R_CPD] = 0xa8;
266 regs[R_CD1] = 0x66;
267 regs[R_CD2] = 0x00;
268 regs[R_CD3] = 0x00;
269 regs[R_MPD] = 0xa9;
270 regs[R_MD1] = 0x73;
271 regs[R_MD2] = 0x1a;
272 regs[R_MD3] = 0x00;
273
274 tda18271_write_regs(fe, R_EP3, 11);
275 msleep(5); /* pll locking */
276
277 regs[R_EP1] = 0xc6;
278 tda18271_write_regs(fe, R_EP1, 1);
279 msleep(5); /* wanted mid measurement */
280
281 regs[R_EP3] = 0x1f;
282 regs[R_EP4] = 0x66;
283 regs[R_EP5] = 0x86;
284 regs[R_CPD] = 0xa8;
285 regs[R_CD1] = 0x66;
286 regs[R_CD2] = 0xa0;
287 regs[R_CD3] = 0x00;
288
289 tda18271_write_regs(fe, R_EP3, 7);
290 msleep(5); /* pll locking */
291
292 regs[R_EP2] = 0xdf;
293 tda18271_write_regs(fe, R_EP2, 1);
294 msleep(30); /* image mid optimization completion */
295
296 /* high-band */
297 regs[R_EP3] = 0x1f;
298 regs[R_EP4] = 0x66;
299 regs[R_EP5] = 0x83;
300 regs[R_CPD] = 0x98;
301 regs[R_CD1] = 0x65;
302 regs[R_CD2] = 0x00;
303 regs[R_CD3] = 0x00;
304 regs[R_MPD] = 0x99;
305 regs[R_MD1] = 0x71;
306 regs[R_MD2] = 0xcd;
307 regs[R_MD3] = 0x00;
308
309 tda18271_write_regs(fe, R_EP3, 11);
310 msleep(5); /* pll locking */
311
312 regs[R_EP1] = 0xc6;
313 tda18271_write_regs(fe, R_EP1, 1);
314 msleep(5); /* wanted high measurement */
315
316 regs[R_EP3] = 0x1f;
317 regs[R_EP4] = 0x66;
318 regs[R_EP5] = 0x87;
319 regs[R_CPD] = 0x98;
320 regs[R_CD1] = 0x65;
321 regs[R_CD2] = 0x50;
322 regs[R_CD3] = 0x00;
323
324 tda18271_write_regs(fe, R_EP3, 7);
325 msleep(5); /* pll locking */
326
327 regs[R_EP2] = 0xdf;
328
329 tda18271_write_regs(fe, R_EP2, 1);
330 msleep(30); /* image high optimization completion */
331
332 regs[R_EP4] = 0x64;
333 tda18271_write_regs(fe, R_EP4, 1);
334
335 regs[R_EP1] = 0xc6;
336 tda18271_write_regs(fe, R_EP1, 1);
Michael Krufky22ee1252007-11-22 17:13:00 -0300337
338 return 0;
Michael Krufky5bea1cd2007-10-22 09:56:38 -0300339}
340
Michael Krufkyefce8412007-12-01 17:40:16 -0300341static int tda18271_init(struct dvb_frontend *fe)
342{
343 struct tda18271_priv *priv = fe->tuner_priv;
344 unsigned char *regs = priv->tda18271_regs;
345
346 tda18271_read_regs(fe);
347
348 /* test IR_CAL_OK to see if we need init */
349 if ((regs[R_EP1] & 0x08) == 0)
350 tda18271_init_regs(fe);
351
352 return 0;
353}
354
Michael Krufkyfe0bf6d2007-12-24 05:05:05 -0300355static int tda18271_calc_main_pll(struct dvb_frontend *fe, u32 freq)
356{
357 /* Sets Main Post-Divider & Divider bytes, but does not write them */
358 struct tda18271_priv *priv = fe->tuner_priv;
359 unsigned char *regs = priv->tda18271_regs;
360 u8 d, pd;
361 u32 div;
362
Michael Krufky2f27dfc2007-12-25 00:39:37 -0300363 int ret = tda18271_lookup_pll_map(MAIN_PLL, &freq, &pd, &d);
364 if (ret < 0)
365 goto fail;
Michael Krufkyfe0bf6d2007-12-24 05:05:05 -0300366
367 regs[R_MPD] = (0x77 & pd);
368
369 switch (priv->mode) {
370 case TDA18271_ANALOG:
371 regs[R_MPD] &= ~0x08;
372 break;
373 case TDA18271_DIGITAL:
374 regs[R_MPD] |= 0x08;
375 break;
376 }
377
378 div = ((d * (freq / 1000)) << 7) / 125;
379
380 regs[R_MD1] = 0x7f & (div >> 16);
381 regs[R_MD2] = 0xff & (div >> 8);
382 regs[R_MD3] = 0xff & div;
Michael Krufky2f27dfc2007-12-25 00:39:37 -0300383fail:
384 return ret;
Michael Krufkyfe0bf6d2007-12-24 05:05:05 -0300385}
386
387static int tda18271_calc_cal_pll(struct dvb_frontend *fe, u32 freq)
388{
389 /* Sets Cal Post-Divider & Divider bytes, but does not write them */
390 struct tda18271_priv *priv = fe->tuner_priv;
391 unsigned char *regs = priv->tda18271_regs;
392 u8 d, pd;
393 u32 div;
394
Michael Krufky2f27dfc2007-12-25 00:39:37 -0300395 int ret = tda18271_lookup_pll_map(CAL_PLL, &freq, &pd, &d);
396 if (ret < 0)
397 goto fail;
Michael Krufkyfe0bf6d2007-12-24 05:05:05 -0300398
399 regs[R_CPD] = pd;
400
401 div = ((d * (freq / 1000)) << 7) / 125;
402
403 regs[R_CD1] = 0x7f & (div >> 16);
404 regs[R_CD2] = 0xff & (div >> 8);
405 regs[R_CD3] = 0xff & div;
Michael Krufky2f27dfc2007-12-25 00:39:37 -0300406fail:
407 return ret;
Michael Krufkyfe0bf6d2007-12-24 05:05:05 -0300408}
409
Michael Krufky5bea1cd2007-10-22 09:56:38 -0300410static int tda18271_tune(struct dvb_frontend *fe,
411 u32 ifc, u32 freq, u32 bw, u8 std)
412{
413 struct tda18271_priv *priv = fe->tuner_priv;
414 unsigned char *regs = priv->tda18271_regs;
Michael Krufkyfe0bf6d2007-12-24 05:05:05 -0300415 u32 N = 0;
416 u8 val;
Michael Krufky5bea1cd2007-10-22 09:56:38 -0300417
Michael Krufky14572632007-12-02 02:32:49 -0300418 tda18271_init(fe);
Michael Krufky5bea1cd2007-10-22 09:56:38 -0300419
Michael Krufky293da0e2007-12-02 02:45:04 -0300420 dbg_info("freq = %d, ifc = %d\n", freq, ifc);
Michael Krufky5bea1cd2007-10-22 09:56:38 -0300421
Michael Krufky5bea1cd2007-10-22 09:56:38 -0300422 /* RF tracking filter calibration */
423
424 /* calculate BP_Filter */
Michael Krufky2f27dfc2007-12-25 00:39:37 -0300425 tda18271_lookup_map(BP_FILTER, &freq, &val);
Michael Krufky5bea1cd2007-10-22 09:56:38 -0300426
427 regs[R_EP1] &= ~0x07; /* clear bp filter bits */
Michael Krufkyb5f3e1e2007-12-02 16:36:05 -0300428 regs[R_EP1] |= val;
Michael Krufky5bea1cd2007-10-22 09:56:38 -0300429 tda18271_write_regs(fe, R_EP1, 1);
430
431 regs[R_EB4] &= 0x07;
432 regs[R_EB4] |= 0x60;
433 tda18271_write_regs(fe, R_EB4, 1);
434
435 regs[R_EB7] = 0x60;
436 tda18271_write_regs(fe, R_EB7, 1);
437
438 regs[R_EB14] = 0x00;
439 tda18271_write_regs(fe, R_EB14, 1);
440
441 regs[R_EB20] = 0xcc;
442 tda18271_write_regs(fe, R_EB20, 1);
443
444 /* set CAL mode to RF tracking filter calibration */
Michael Krufky26501a72007-12-21 14:28:46 -0300445 regs[R_EP4] |= 0x03;
Michael Krufky5bea1cd2007-10-22 09:56:38 -0300446
447 /* calculate CAL PLL */
448
449 switch (priv->mode) {
450 case TDA18271_ANALOG:
451 N = freq - 1250000;
452 break;
453 case TDA18271_DIGITAL:
454 N = freq + bw / 2;
455 break;
456 }
457
Michael Krufkyfe0bf6d2007-12-24 05:05:05 -0300458 tda18271_calc_cal_pll(fe, N);
Michael Krufky5bea1cd2007-10-22 09:56:38 -0300459
460 /* calculate MAIN PLL */
461
462 switch (priv->mode) {
463 case TDA18271_ANALOG:
464 N = freq - 250000;
465 break;
466 case TDA18271_DIGITAL:
467 N = freq + bw / 2 + 1000000;
468 break;
469 }
470
Michael Krufkyfe0bf6d2007-12-24 05:05:05 -0300471 tda18271_calc_main_pll(fe, N);
Michael Krufky5bea1cd2007-10-22 09:56:38 -0300472
473 tda18271_write_regs(fe, R_EP3, 11);
474 msleep(5); /* RF tracking filter calibration initialization */
475
476 /* search for K,M,CO for RF Calibration */
Michael Krufky2f27dfc2007-12-25 00:39:37 -0300477 tda18271_lookup_map(RF_CAL_KMCO, &freq, &val);
Michael Krufky5bea1cd2007-10-22 09:56:38 -0300478
479 regs[R_EB13] &= 0x83;
Michael Krufkyb5f3e1e2007-12-02 16:36:05 -0300480 regs[R_EB13] |= val;
Michael Krufky5bea1cd2007-10-22 09:56:38 -0300481 tda18271_write_regs(fe, R_EB13, 1);
482
483 /* search for RF_BAND */
Michael Krufky2f27dfc2007-12-25 00:39:37 -0300484 tda18271_lookup_map(RF_BAND, &freq, &val);
Michael Krufky5bea1cd2007-10-22 09:56:38 -0300485
486 regs[R_EP2] &= ~0xe0; /* clear rf band bits */
Michael Krufkyb5f3e1e2007-12-02 16:36:05 -0300487 regs[R_EP2] |= (val << 5);
Michael Krufky5bea1cd2007-10-22 09:56:38 -0300488
489 /* search for Gain_Taper */
Michael Krufky2f27dfc2007-12-25 00:39:37 -0300490 tda18271_lookup_map(GAIN_TAPER, &freq, &val);
Michael Krufky5bea1cd2007-10-22 09:56:38 -0300491
492 regs[R_EP2] &= ~0x1f; /* clear gain taper bits */
Michael Krufkyb5f3e1e2007-12-02 16:36:05 -0300493 regs[R_EP2] |= val;
Michael Krufky5bea1cd2007-10-22 09:56:38 -0300494
495 tda18271_write_regs(fe, R_EP2, 1);
496 tda18271_write_regs(fe, R_EP1, 1);
497 tda18271_write_regs(fe, R_EP2, 1);
498 tda18271_write_regs(fe, R_EP1, 1);
499
500 regs[R_EB4] &= 0x07;
501 regs[R_EB4] |= 0x40;
502 tda18271_write_regs(fe, R_EB4, 1);
503
504 regs[R_EB7] = 0x40;
505 tda18271_write_regs(fe, R_EB7, 1);
506 msleep(10);
507
508 regs[R_EB20] = 0xec;
509 tda18271_write_regs(fe, R_EB20, 1);
510 msleep(60); /* RF tracking filter calibration completion */
511
512 regs[R_EP4] &= ~0x03; /* set cal mode to normal */
513 tda18271_write_regs(fe, R_EP4, 1);
514
515 tda18271_write_regs(fe, R_EP1, 1);
516
517 /* RF tracking filer correction for VHF_Low band */
Michael Krufky2f27dfc2007-12-25 00:39:37 -0300518 tda18271_lookup_map(RF_CAL, &freq, &val);
Michael Krufky5bea1cd2007-10-22 09:56:38 -0300519
520 /* VHF_Low band only */
Michael Krufkyb5f3e1e2007-12-02 16:36:05 -0300521 if (val != 0) {
522 regs[R_EB14] = val;
Michael Krufky5bea1cd2007-10-22 09:56:38 -0300523 tda18271_write_regs(fe, R_EB14, 1);
524 }
525
526 /* Channel Configuration */
527
528 switch (priv->mode) {
529 case TDA18271_ANALOG:
530 regs[R_EB22] = 0x2c;
531 break;
532 case TDA18271_DIGITAL:
533 regs[R_EB22] = 0x37;
534 break;
535 }
536 tda18271_write_regs(fe, R_EB22, 1);
537
538 regs[R_EP1] |= 0x40; /* set dis power level on */
539
540 /* set standard */
541 regs[R_EP3] &= ~0x1f; /* clear std bits */
542
543 /* see table 22 */
544 regs[R_EP3] |= std;
545
Michael Krufky5bea1cd2007-10-22 09:56:38 -0300546 regs[R_EP4] &= ~0x03; /* set cal mode to normal */
547
548 regs[R_EP4] &= ~0x1c; /* clear if level bits */
549 switch (priv->mode) {
550 case TDA18271_ANALOG:
551 regs[R_MPD] &= ~0x80; /* IF notch = 0 */
552 break;
553 case TDA18271_DIGITAL:
554 regs[R_EP4] |= 0x04;
555 regs[R_MPD] |= 0x80;
556 break;
557 }
558
559 regs[R_EP4] &= ~0x80; /* turn this bit on only for fm */
560
Michael Krufkyaaeccba2007-12-02 11:03:57 -0300561 /* image rejection validity EP5[2:0] */
Michael Krufky2f27dfc2007-12-25 00:39:37 -0300562 tda18271_lookup_map(IR_MEASURE, &freq, &val);
Michael Krufkyb5f3e1e2007-12-02 16:36:05 -0300563
Michael Krufkyaaeccba2007-12-02 11:03:57 -0300564 regs[R_EP5] &= ~0x07;
Michael Krufkyb5f3e1e2007-12-02 16:36:05 -0300565 regs[R_EP5] |= val;
Michael Krufky5bea1cd2007-10-22 09:56:38 -0300566
567 /* calculate MAIN PLL */
568 N = freq + ifc;
569
Michael Krufkyfe0bf6d2007-12-24 05:05:05 -0300570 tda18271_calc_main_pll(fe, N);
Michael Krufky5bea1cd2007-10-22 09:56:38 -0300571
572 tda18271_write_regs(fe, R_TM, 15);
573 msleep(5);
Michael Krufky6ca04de2007-11-23 16:52:15 -0300574
Michael Krufky5bea1cd2007-10-22 09:56:38 -0300575 return 0;
576}
577
578/* ------------------------------------------------------------------ */
579
580static int tda18271_set_params(struct dvb_frontend *fe,
581 struct dvb_frontend_parameters *params)
582{
583 struct tda18271_priv *priv = fe->tuner_priv;
584 u8 std;
585 u32 bw, sgIF = 0;
586
587 u32 freq = params->frequency;
588
589 priv->mode = TDA18271_DIGITAL;
590
591 /* see table 22 */
592 if (fe->ops.info.type == FE_ATSC) {
593 switch (params->u.vsb.modulation) {
594 case VSB_8:
595 case VSB_16:
596 std = 0x1b; /* device-specific (spec says 0x1c) */
597 sgIF = 5380000;
598 break;
599 case QAM_64:
600 case QAM_256:
601 std = 0x18; /* device-specific (spec says 0x1d) */
602 sgIF = 4000000;
603 break;
604 default:
605 printk(KERN_WARNING "%s: modulation not set!\n",
606 __FUNCTION__);
607 return -EINVAL;
608 }
Michael Krufky14e3c152007-12-07 00:33:08 -0300609#if 0
610 /* userspace request is already center adjusted */
Michael Krufky5bea1cd2007-10-22 09:56:38 -0300611 freq += 1750000; /* Adjust to center (+1.75MHZ) */
Michael Krufky14e3c152007-12-07 00:33:08 -0300612#endif
Michael Krufky5bea1cd2007-10-22 09:56:38 -0300613 bw = 6000000;
614 } else if (fe->ops.info.type == FE_OFDM) {
615 switch (params->u.ofdm.bandwidth) {
616 case BANDWIDTH_6_MHZ:
Michael Krufky6ca04de2007-11-23 16:52:15 -0300617 std = 0x1b; /* device-specific (spec says 0x1c) */
Michael Krufky5bea1cd2007-10-22 09:56:38 -0300618 bw = 6000000;
Michael Krufky6ca04de2007-11-23 16:52:15 -0300619 sgIF = 3300000;
Michael Krufky5bea1cd2007-10-22 09:56:38 -0300620 break;
621 case BANDWIDTH_7_MHZ:
Michael Krufky6ca04de2007-11-23 16:52:15 -0300622 std = 0x19; /* device-specific (spec says 0x1d) */
Michael Krufky5bea1cd2007-10-22 09:56:38 -0300623 bw = 7000000;
Michael Krufky6ca04de2007-11-23 16:52:15 -0300624 sgIF = 3800000;
Michael Krufky5bea1cd2007-10-22 09:56:38 -0300625 break;
626 case BANDWIDTH_8_MHZ:
Michael Krufky6ca04de2007-11-23 16:52:15 -0300627 std = 0x1a; /* device-specific (spec says 0x1e) */
Michael Krufky5bea1cd2007-10-22 09:56:38 -0300628 bw = 8000000;
Michael Krufky6ca04de2007-11-23 16:52:15 -0300629 sgIF = 4300000;
Michael Krufky5bea1cd2007-10-22 09:56:38 -0300630 break;
631 default:
632 printk(KERN_WARNING "%s: bandwidth not set!\n",
633 __FUNCTION__);
634 return -EINVAL;
635 }
636 } else {
637 printk(KERN_WARNING "%s: modulation type not supported!\n",
638 __FUNCTION__);
639 return -EINVAL;
640 }
641
642 return tda18271_tune(fe, sgIF, freq, bw, std);
643}
644
645static int tda18271_set_analog_params(struct dvb_frontend *fe,
646 struct analog_parameters *params)
647{
648 struct tda18271_priv *priv = fe->tuner_priv;
649 u8 std;
650 unsigned int sgIF;
651 char *mode;
652
653 priv->mode = TDA18271_ANALOG;
654
655 /* see table 22 */
656 if (params->std & V4L2_STD_MN) {
657 std = 0x0d;
658 sgIF = 92;
659 mode = "MN";
660 } else if (params->std & V4L2_STD_B) {
661 std = 0x0e;
662 sgIF = 108;
663 mode = "B";
664 } else if (params->std & V4L2_STD_GH) {
665 std = 0x0f;
666 sgIF = 124;
667 mode = "GH";
668 } else if (params->std & V4L2_STD_PAL_I) {
669 std = 0x0f;
670 sgIF = 124;
671 mode = "I";
672 } else if (params->std & V4L2_STD_DK) {
673 std = 0x0f;
674 sgIF = 124;
675 mode = "DK";
676 } else if (params->std & V4L2_STD_SECAM_L) {
677 std = 0x0f;
678 sgIF = 124;
679 mode = "L";
680 } else if (params->std & V4L2_STD_SECAM_LC) {
681 std = 0x0f;
682 sgIF = 20;
683 mode = "LC";
684 } else {
685 std = 0x0f;
686 sgIF = 124;
687 mode = "xx";
688 }
689
690 if (params->mode == V4L2_TUNER_RADIO)
691 sgIF = 88; /* if frequency is 5.5 MHz */
692
Michael Krufky293da0e2007-12-02 02:45:04 -0300693 dbg_info("setting tda18271 to system %s\n", mode);
Michael Krufky5bea1cd2007-10-22 09:56:38 -0300694
695 return tda18271_tune(fe, sgIF * 62500, params->frequency * 62500,
696 0, std);
697}
698
699static int tda18271_release(struct dvb_frontend *fe)
700{
701 kfree(fe->tuner_priv);
702 fe->tuner_priv = NULL;
703 return 0;
704}
705
706static int tda18271_get_frequency(struct dvb_frontend *fe, u32 *frequency)
707{
708 struct tda18271_priv *priv = fe->tuner_priv;
709 *frequency = priv->frequency;
710 return 0;
711}
712
713static int tda18271_get_bandwidth(struct dvb_frontend *fe, u32 *bandwidth)
714{
715 struct tda18271_priv *priv = fe->tuner_priv;
716 *bandwidth = priv->bandwidth;
717 return 0;
718}
719
Michael Krufky49e7aaf2007-12-24 04:15:20 -0300720static int tda18271_get_id(struct dvb_frontend *fe)
721{
722 struct tda18271_priv *priv = fe->tuner_priv;
723 unsigned char *regs = priv->tda18271_regs;
724 char *name;
725 int ret = 0;
726
727 tda18271_read_regs(fe);
728
729 switch (regs[R_ID] & 0x7f) {
730 case 3:
731 name = "TDA18271HD/C1";
732 break;
733 case 4:
734 name = "TDA18271HD/C2";
735 ret = -EPROTONOSUPPORT;
736 break;
737 default:
738 name = "Unknown device";
739 ret = -EINVAL;
740 break;
741 }
742
743 dbg_info("%s detected @ %d-%04x%s\n", name,
744 i2c_adapter_id(priv->i2c_adap), priv->i2c_addr,
745 (0 == ret) ? "" : ", device not supported.");
746
747 return ret;
748}
749
Michael Krufky5bea1cd2007-10-22 09:56:38 -0300750static struct dvb_tuner_ops tda18271_tuner_ops = {
751 .info = {
752 .name = "NXP TDA18271HD",
753 .frequency_min = 45000000,
754 .frequency_max = 864000000,
755 .frequency_step = 62500
756 },
Michael Krufkyefce8412007-12-01 17:40:16 -0300757 .init = tda18271_init,
Michael Krufky5bea1cd2007-10-22 09:56:38 -0300758 .set_params = tda18271_set_params,
759 .set_analog_params = tda18271_set_analog_params,
760 .release = tda18271_release,
761 .get_frequency = tda18271_get_frequency,
762 .get_bandwidth = tda18271_get_bandwidth,
763};
764
765struct dvb_frontend *tda18271_attach(struct dvb_frontend *fe, u8 addr,
Michael Krufkye435f952007-12-09 22:23:30 -0300766 struct i2c_adapter *i2c,
767 enum tda18271_i2c_gate gate)
Michael Krufky5bea1cd2007-10-22 09:56:38 -0300768{
769 struct tda18271_priv *priv = NULL;
770
Michael Krufky5bea1cd2007-10-22 09:56:38 -0300771 priv = kzalloc(sizeof(struct tda18271_priv), GFP_KERNEL);
772 if (priv == NULL)
773 return NULL;
774
775 priv->i2c_addr = addr;
776 priv->i2c_adap = i2c;
Michael Krufkye435f952007-12-09 22:23:30 -0300777 priv->gate = gate;
Michael Krufky5bea1cd2007-10-22 09:56:38 -0300778
Michael Krufky49e7aaf2007-12-24 04:15:20 -0300779 fe->tuner_priv = priv;
780
781 if (tda18271_get_id(fe) < 0)
782 goto fail;
783
Michael Krufky5bea1cd2007-10-22 09:56:38 -0300784 memcpy(&fe->ops.tuner_ops, &tda18271_tuner_ops,
785 sizeof(struct dvb_tuner_ops));
786
Michael Krufkyefce8412007-12-01 17:40:16 -0300787 tda18271_init_regs(fe);
788
Michael Krufky5bea1cd2007-10-22 09:56:38 -0300789 return fe;
Michael Krufky49e7aaf2007-12-24 04:15:20 -0300790fail:
791 tda18271_release(fe);
792 return NULL;
Michael Krufky5bea1cd2007-10-22 09:56:38 -0300793}
794EXPORT_SYMBOL_GPL(tda18271_attach);
795MODULE_DESCRIPTION("NXP TDA18271HD analog / digital tuner driver");
796MODULE_AUTHOR("Michael Krufky <mkrufky@linuxtv.org>");
797MODULE_LICENSE("GPL");
798
799/*
800 * Overrides for Emacs so that we follow Linus's tabbing style.
801 * ---------------------------------------------------------------------------
802 * Local variables:
803 * c-basic-offset: 8
804 * End:
805 */