]> git.ipfire.org Git - thirdparty/kernel/stable.git/blame - drivers/media/dvb-frontends/tda18271c2dd.c
media: move dvb kAPI headers to include/media
[thirdparty/kernel/stable.git] / drivers / media / dvb-frontends / tda18271c2dd.c
CommitLineData
e8783950
RM
1/*
2 * tda18271c2dd: Driver for the TDA18271C2 tuner
3 *
4 * Copyright (C) 2010 Digital Devices GmbH
5 *
6 *
7 * This program is free software; you can redistribute it and/or
8 * modify it under the terms of the GNU General Public License
9 * version 2 only, as published by the Free Software Foundation.
10 *
11 *
12 * This program is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 * GNU General Public License for more details.
16 *
bcb63314
SA
17 * To obtain the license, point your browser to
18 * http://www.gnu.org/copyleft/gpl.html
e8783950
RM
19 */
20
21#include <linux/kernel.h>
22#include <linux/module.h>
23#include <linux/moduleparam.h>
24#include <linux/init.h>
25#include <linux/delay.h>
26#include <linux/firmware.h>
27#include <linux/i2c.h>
e8783950
RM
28#include <asm/div64.h>
29
fada1935 30#include <media/dvb_frontend.h>
4e373217 31#include "tda18271c2dd.h"
e8783950 32
8393796d
MCC
33/* Max transfer size done by I2C transfer functions */
34#define MAX_XFER_SIZE 64
35
e8783950
RM
36struct SStandardParam {
37 s32 m_IFFrequency;
38 u32 m_BandWidth;
39 u8 m_EP3_4_0;
40 u8 m_EB22;
41};
42
43struct SMap {
44 u32 m_Frequency;
45 u8 m_Param;
46};
47
48struct SMapI {
49 u32 m_Frequency;
50 s32 m_Param;
51};
52
53struct SMap2 {
54 u32 m_Frequency;
55 u8 m_Param1;
56 u8 m_Param2;
57};
58
59struct SRFBandMap {
60 u32 m_RF_max;
61 u32 m_RF1_Default;
62 u32 m_RF2_Default;
63 u32 m_RF3_Default;
64};
65
0fe44629 66enum ERegister {
e8783950
RM
67 ID = 0,
68 TM,
69 PL,
70 EP1, EP2, EP3, EP4, EP5,
71 CPD, CD1, CD2, CD3,
72 MPD, MD1, MD2, MD3,
73 EB1, EB2, EB3, EB4, EB5, EB6, EB7, EB8, EB9, EB10,
74 EB11, EB12, EB13, EB14, EB15, EB16, EB17, EB18, EB19, EB20,
75 EB21, EB22, EB23,
76 NUM_REGS
77};
78
79struct tda_state {
80 struct i2c_adapter *i2c;
81 u8 adr;
82
83 u32 m_Frequency;
84 u32 IF;
85
86 u8 m_IFLevelAnalog;
87 u8 m_IFLevelDigital;
88 u8 m_IFLevelDVBC;
89 u8 m_IFLevelDVBT;
90
91 u8 m_EP4;
92 u8 m_EP3_Standby;
93
94 bool m_bMaster;
95
96 s32 m_SettlingTime;
97
98 u8 m_Regs[NUM_REGS];
99
100 /* Tracking filter settings for band 0..6 */
101 u32 m_RF1[7];
102 s32 m_RF_A1[7];
103 s32 m_RF_B1[7];
104 u32 m_RF2[7];
105 s32 m_RF_A2[7];
106 s32 m_RF_B2[7];
107 u32 m_RF3[7];
108
109 u8 m_TMValue_RFCal; /* Calibration temperatur */
110
111 bool m_bFMInput; /* true to use Pin 8 for FM Radio */
112
113};
114
115static int PowerScan(struct tda_state *state,
0fe44629
OE
116 u8 RFBand, u32 RF_in,
117 u32 *pRF_Out, bool *pbcal);
e8783950
RM
118
119static int i2c_readn(struct i2c_adapter *adapter, u8 adr, u8 *data, int len)
120{
121 struct i2c_msg msgs[1] = {{.addr = adr, .flags = I2C_M_RD,
0fe44629 122 .buf = data, .len = len} };
e8783950
RM
123 return (i2c_transfer(adapter, msgs, 1) == 1) ? 0 : -1;
124}
125
126static int i2c_write(struct i2c_adapter *adap, u8 adr, u8 *data, int len)
127{
128 struct i2c_msg msg = {.addr = adr, .flags = 0,
129 .buf = data, .len = len};
130
131 if (i2c_transfer(adap, &msg, 1) != 1) {
f3d40bd0 132 printk(KERN_ERR "tda18271c2dd: i2c write error at addr %i\n", adr);
e8783950
RM
133 return -1;
134 }
135 return 0;
136}
137
138static int WriteRegs(struct tda_state *state,
139 u8 SubAddr, u8 *Regs, u16 nRegs)
140{
8393796d
MCC
141 u8 data[MAX_XFER_SIZE];
142
143 if (1 + nRegs > sizeof(data)) {
144 printk(KERN_WARNING
145 "%s: i2c wr: len=%d is too big!\n",
146 KBUILD_MODNAME, nRegs);
147 return -EINVAL;
148 }
e8783950
RM
149
150 data[0] = SubAddr;
151 memcpy(data + 1, Regs, nRegs);
8393796d 152 return i2c_write(state->i2c, state->adr, data, nRegs + 1);
e8783950
RM
153}
154
0fe44629 155static int WriteReg(struct tda_state *state, u8 SubAddr, u8 Reg)
e8783950
RM
156{
157 u8 msg[2] = {SubAddr, Reg};
158
159 return i2c_write(state->i2c, state->adr, msg, 2);
160}
161
162static int Read(struct tda_state *state, u8 * Regs)
163{
164 return i2c_readn(state->i2c, state->adr, Regs, 16);
165}
166
167static int ReadExtented(struct tda_state *state, u8 * Regs)
168{
169 return i2c_readn(state->i2c, state->adr, Regs, NUM_REGS);
170}
171
0fe44629 172static int UpdateRegs(struct tda_state *state, u8 RegFrom, u8 RegTo)
e8783950
RM
173{
174 return WriteRegs(state, RegFrom,
175 &state->m_Regs[RegFrom], RegTo-RegFrom+1);
176}
177static int UpdateReg(struct tda_state *state, u8 Reg)
178{
0fe44629 179 return WriteReg(state, Reg, state->m_Regs[Reg]);
e8783950
RM
180}
181
182#include "tda18271c2dd_maps.h"
183
e8783950
RM
184static void reset(struct tda_state *state)
185{
186 u32 ulIFLevelAnalog = 0;
187 u32 ulIFLevelDigital = 2;
188 u32 ulIFLevelDVBC = 7;
189 u32 ulIFLevelDVBT = 6;
190 u32 ulXTOut = 0;
0fe44629 191 u32 ulStandbyMode = 0x06; /* Send in stdb, but leave osc on */
e8783950
RM
192 u32 ulSlave = 0;
193 u32 ulFMInput = 0;
194 u32 ulSettlingTime = 100;
195
196 state->m_Frequency = 0;
197 state->m_SettlingTime = 100;
198 state->m_IFLevelAnalog = (ulIFLevelAnalog & 0x07) << 2;
199 state->m_IFLevelDigital = (ulIFLevelDigital & 0x07) << 2;
200 state->m_IFLevelDVBC = (ulIFLevelDVBC & 0x07) << 2;
201 state->m_IFLevelDVBT = (ulIFLevelDVBT & 0x07) << 2;
202
203 state->m_EP4 = 0x20;
0fe44629
OE
204 if (ulXTOut != 0)
205 state->m_EP4 |= 0x40;
e8783950
RM
206
207 state->m_EP3_Standby = ((ulStandbyMode & 0x07) << 5) | 0x0F;
208 state->m_bMaster = (ulSlave == 0);
209
210 state->m_SettlingTime = ulSettlingTime;
211
212 state->m_bFMInput = (ulFMInput == 2);
213}
214
215static bool SearchMap1(struct SMap Map[],
216 u32 Frequency, u8 *pParam)
217{
218 int i = 0;
219
0fe44629 220 while ((Map[i].m_Frequency != 0) && (Frequency > Map[i].m_Frequency))
e8783950
RM
221 i += 1;
222 if (Map[i].m_Frequency == 0)
223 return false;
224 *pParam = Map[i].m_Param;
225 return true;
226}
227
228static bool SearchMap2(struct SMapI Map[],
229 u32 Frequency, s32 *pParam)
230{
231 int i = 0;
232
233 while ((Map[i].m_Frequency != 0) &&
0fe44629 234 (Frequency > Map[i].m_Frequency))
e8783950
RM
235 i += 1;
236 if (Map[i].m_Frequency == 0)
237 return false;
238 *pParam = Map[i].m_Param;
239 return true;
240}
241
0fe44629 242static bool SearchMap3(struct SMap2 Map[], u32 Frequency,
e8783950
RM
243 u8 *pParam1, u8 *pParam2)
244{
245 int i = 0;
246
247 while ((Map[i].m_Frequency != 0) &&
0fe44629 248 (Frequency > Map[i].m_Frequency))
e8783950
RM
249 i += 1;
250 if (Map[i].m_Frequency == 0)
251 return false;
252 *pParam1 = Map[i].m_Param1;
253 *pParam2 = Map[i].m_Param2;
254 return true;
255}
256
257static bool SearchMap4(struct SRFBandMap Map[],
258 u32 Frequency, u8 *pRFBand)
259{
260 int i = 0;
261
262 while (i < 7 && (Frequency > Map[i].m_RF_max))
263 i += 1;
264 if (i == 7)
265 return false;
266 *pRFBand = i;
267 return true;
268}
269
270static int ThermometerRead(struct tda_state *state, u8 *pTM_Value)
271{
272 int status = 0;
273
274 do {
275 u8 Regs[16];
276 state->m_Regs[TM] |= 0x10;
469ffe08
MCC
277 status = UpdateReg(state, TM);
278 if (status < 0)
279 break;
280 status = Read(state, Regs);
281 if (status < 0)
282 break;
0fe44629
OE
283 if (((Regs[TM] & 0x0F) == 0 && (Regs[TM] & 0x20) == 0x20) ||
284 ((Regs[TM] & 0x0F) == 8 && (Regs[TM] & 0x20) == 0x00)) {
e8783950 285 state->m_Regs[TM] ^= 0x20;
469ffe08
MCC
286 status = UpdateReg(state, TM);
287 if (status < 0)
288 break;
e8783950 289 msleep(10);
469ffe08
MCC
290 status = Read(state, Regs);
291 if (status < 0)
292 break;
e8783950 293 }
0fe44629
OE
294 *pTM_Value = (Regs[TM] & 0x20)
295 ? m_Thermometer_Map_2[Regs[TM] & 0x0F]
296 : m_Thermometer_Map_1[Regs[TM] & 0x0F] ;
297 state->m_Regs[TM] &= ~0x10; /* Thermometer off */
469ffe08
MCC
298 status = UpdateReg(state, TM);
299 if (status < 0)
300 break;
0fe44629 301 state->m_Regs[EP4] &= ~0x03; /* CAL_mode = 0 ????????? */
469ffe08
MCC
302 status = UpdateReg(state, EP4);
303 if (status < 0)
304 break;
0fe44629 305 } while (0);
e8783950
RM
306
307 return status;
308}
309
310static int StandBy(struct tda_state *state)
311{
312 int status = 0;
313 do {
0fe44629 314 state->m_Regs[EB12] &= ~0x20; /* PD_AGC1_Det = 0 */
469ffe08
MCC
315 status = UpdateReg(state, EB12);
316 if (status < 0)
317 break;
0fe44629 318 state->m_Regs[EB18] &= ~0x83; /* AGC1_loop_off = 0, AGC1_Gain = 6 dB */
469ffe08
MCC
319 status = UpdateReg(state, EB18);
320 if (status < 0)
321 break;
0fe44629 322 state->m_Regs[EB21] |= 0x03; /* AGC2_Gain = -6 dB */
e8783950 323 state->m_Regs[EP3] = state->m_EP3_Standby;
469ffe08
MCC
324 status = UpdateReg(state, EP3);
325 if (status < 0)
326 break;
0fe44629 327 state->m_Regs[EB23] &= ~0x06; /* ForceLP_Fc2_En = 0, LP_Fc[2] = 0 */
469ffe08
MCC
328 status = UpdateRegs(state, EB21, EB23);
329 if (status < 0)
330 break;
0fe44629 331 } while (0);
e8783950
RM
332 return status;
333}
334
335static int CalcMainPLL(struct tda_state *state, u32 freq)
336{
337
338 u8 PostDiv;
339 u8 Div;
340 u64 OscFreq;
341 u32 MainDiv;
342
0fe44629 343 if (!SearchMap3(m_Main_PLL_Map, freq, &PostDiv, &Div))
e8783950 344 return -EINVAL;
e8783950
RM
345
346 OscFreq = (u64) freq * (u64) Div;
347 OscFreq *= (u64) 16384;
348 do_div(OscFreq, (u64)16000000);
349 MainDiv = OscFreq;
350
351 state->m_Regs[MPD] = PostDiv & 0x77;
352 state->m_Regs[MD1] = ((MainDiv >> 16) & 0x7F);
353 state->m_Regs[MD2] = ((MainDiv >> 8) & 0xFF);
0fe44629 354 state->m_Regs[MD3] = (MainDiv & 0xFF);
e8783950
RM
355
356 return UpdateRegs(state, MPD, MD3);
357}
358
359static int CalcCalPLL(struct tda_state *state, u32 freq)
360{
e8783950
RM
361 u8 PostDiv;
362 u8 Div;
363 u64 OscFreq;
364 u32 CalDiv;
365
0fe44629 366 if (!SearchMap3(m_Cal_PLL_Map, freq, &PostDiv, &Div))
e8783950 367 return -EINVAL;
e8783950
RM
368
369 OscFreq = (u64)freq * (u64)Div;
0fe44629
OE
370 /* CalDiv = u32( OscFreq * 16384 / 16000000 ); */
371 OscFreq *= (u64)16384;
e8783950 372 do_div(OscFreq, (u64)16000000);
0fe44629 373 CalDiv = OscFreq;
e8783950
RM
374
375 state->m_Regs[CPD] = PostDiv;
376 state->m_Regs[CD1] = ((CalDiv >> 16) & 0xFF);
377 state->m_Regs[CD2] = ((CalDiv >> 8) & 0xFF);
0fe44629 378 state->m_Regs[CD3] = (CalDiv & 0xFF);
e8783950 379
0fe44629 380 return UpdateRegs(state, CPD, CD3);
e8783950
RM
381}
382
383static int CalibrateRF(struct tda_state *state,
0fe44629 384 u8 RFBand, u32 freq, s32 *pCprog)
e8783950 385{
e8783950
RM
386 int status = 0;
387 u8 Regs[NUM_REGS];
388 do {
0fe44629
OE
389 u8 BP_Filter = 0;
390 u8 GainTaper = 0;
391 u8 RFC_K = 0;
392 u8 RFC_M = 0;
393
394 state->m_Regs[EP4] &= ~0x03; /* CAL_mode = 0 */
469ffe08
MCC
395 status = UpdateReg(state, EP4);
396 if (status < 0)
397 break;
0fe44629 398 state->m_Regs[EB18] |= 0x03; /* AGC1_Gain = 3 */
469ffe08
MCC
399 status = UpdateReg(state, EB18);
400 if (status < 0)
401 break;
0fe44629
OE
402
403 /* Switching off LT (as datasheet says) causes calibration on C1 to fail */
404 /* (Readout of Cprog is allways 255) */
405 if (state->m_Regs[ID] != 0x83) /* C1: ID == 83, C2: ID == 84 */
406 state->m_Regs[EP3] |= 0x40; /* SM_LT = 1 */
407
408 if (!(SearchMap1(m_BP_Filter_Map, freq, &BP_Filter) &&
409 SearchMap1(m_GainTaper_Map, freq, &GainTaper) &&
410 SearchMap3(m_KM_Map, freq, &RFC_K, &RFC_M)))
e8783950 411 return -EINVAL;
e8783950
RM
412
413 state->m_Regs[EP1] = (state->m_Regs[EP1] & ~0x07) | BP_Filter;
414 state->m_Regs[EP2] = (RFBand << 5) | GainTaper;
415
416 state->m_Regs[EB13] = (state->m_Regs[EB13] & ~0x7C) | (RFC_K << 4) | (RFC_M << 2);
417
469ffe08
MCC
418 status = UpdateRegs(state, EP1, EP3);
419 if (status < 0)
420 break;
421 status = UpdateReg(state, EB13);
422 if (status < 0)
423 break;
e8783950 424
0fe44629 425 state->m_Regs[EB4] |= 0x20; /* LO_ForceSrce = 1 */
469ffe08
MCC
426 status = UpdateReg(state, EB4);
427 if (status < 0)
428 break;
e8783950 429
0fe44629 430 state->m_Regs[EB7] |= 0x20; /* CAL_ForceSrce = 1 */
469ffe08
MCC
431 status = UpdateReg(state, EB7);
432 if (status < 0)
433 break;
e8783950 434
0fe44629 435 state->m_Regs[EB14] = 0; /* RFC_Cprog = 0 */
469ffe08
MCC
436 status = UpdateReg(state, EB14);
437 if (status < 0)
438 break;
e8783950 439
0fe44629 440 state->m_Regs[EB20] &= ~0x20; /* ForceLock = 0; */
469ffe08
MCC
441 status = UpdateReg(state, EB20);
442 if (status < 0)
443 break;
e8783950 444
0fe44629 445 state->m_Regs[EP4] |= 0x03; /* CAL_Mode = 3 */
469ffe08
MCC
446 status = UpdateRegs(state, EP4, EP5);
447 if (status < 0)
448 break;
e8783950 449
469ffe08
MCC
450 status = CalcCalPLL(state, freq);
451 if (status < 0)
452 break;
453 status = CalcMainPLL(state, freq + 1000000);
454 if (status < 0)
455 break;
e8783950
RM
456
457 msleep(5);
469ffe08
MCC
458 status = UpdateReg(state, EP2);
459 if (status < 0)
460 break;
461 status = UpdateReg(state, EP1);
462 if (status < 0)
463 break;
464 status = UpdateReg(state, EP2);
465 if (status < 0)
466 break;
467 status = UpdateReg(state, EP1);
468 if (status < 0)
469 break;
e8783950 470
0fe44629 471 state->m_Regs[EB4] &= ~0x20; /* LO_ForceSrce = 0 */
469ffe08
MCC
472 status = UpdateReg(state, EB4);
473 if (status < 0)
474 break;
e8783950 475
0fe44629 476 state->m_Regs[EB7] &= ~0x20; /* CAL_ForceSrce = 0 */
469ffe08
MCC
477 status = UpdateReg(state, EB7);
478 if (status < 0)
479 break;
e8783950
RM
480 msleep(10);
481
0fe44629 482 state->m_Regs[EB20] |= 0x20; /* ForceLock = 1; */
469ffe08
MCC
483 status = UpdateReg(state, EB20);
484 if (status < 0)
485 break;
e8783950
RM
486 msleep(60);
487
0fe44629
OE
488 state->m_Regs[EP4] &= ~0x03; /* CAL_Mode = 0 */
489 state->m_Regs[EP3] &= ~0x40; /* SM_LT = 0 */
490 state->m_Regs[EB18] &= ~0x03; /* AGC1_Gain = 0 */
469ffe08
MCC
491 status = UpdateReg(state, EB18);
492 if (status < 0)
493 break;
494 status = UpdateRegs(state, EP3, EP4);
495 if (status < 0)
496 break;
497 status = UpdateReg(state, EP1);
498 if (status < 0)
499 break;
e8783950 500
469ffe08
MCC
501 status = ReadExtented(state, Regs);
502 if (status < 0)
503 break;
e8783950
RM
504
505 *pCprog = Regs[EB14];
e8783950 506
0fe44629 507 } while (0);
e8783950
RM
508 return status;
509}
510
511static int RFTrackingFiltersInit(struct tda_state *state,
512 u8 RFBand)
513{
e8783950
RM
514 int status = 0;
515
516 u32 RF1 = m_RF_Band_Map[RFBand].m_RF1_Default;
517 u32 RF2 = m_RF_Band_Map[RFBand].m_RF2_Default;
518 u32 RF3 = m_RF_Band_Map[RFBand].m_RF3_Default;
519 bool bcal = false;
520
521 s32 Cprog_cal1 = 0;
522 s32 Cprog_table1 = 0;
523 s32 Cprog_cal2 = 0;
524 s32 Cprog_table2 = 0;
525 s32 Cprog_cal3 = 0;
526 s32 Cprog_table3 = 0;
527
528 state->m_RF_A1[RFBand] = 0;
529 state->m_RF_B1[RFBand] = 0;
530 state->m_RF_A2[RFBand] = 0;
531 state->m_RF_B2[RFBand] = 0;
532
533 do {
469ffe08
MCC
534 status = PowerScan(state, RFBand, RF1, &RF1, &bcal);
535 if (status < 0)
536 break;
0fe44629 537 if (bcal) {
469ffe08
MCC
538 status = CalibrateRF(state, RFBand, RF1, &Cprog_cal1);
539 if (status < 0)
540 break;
e8783950 541 }
0fe44629
OE
542 SearchMap2(m_RF_Cal_Map, RF1, &Cprog_table1);
543 if (!bcal)
e8783950 544 Cprog_cal1 = Cprog_table1;
e8783950 545 state->m_RF_B1[RFBand] = Cprog_cal1 - Cprog_table1;
0fe44629 546 /* state->m_RF_A1[RF_Band] = ???? */
e8783950 547
0fe44629
OE
548 if (RF2 == 0)
549 break;
e8783950 550
469ffe08
MCC
551 status = PowerScan(state, RFBand, RF2, &RF2, &bcal);
552 if (status < 0)
553 break;
0fe44629 554 if (bcal) {
469ffe08
MCC
555 status = CalibrateRF(state, RFBand, RF2, &Cprog_cal2);
556 if (status < 0)
557 break;
e8783950 558 }
0fe44629
OE
559 SearchMap2(m_RF_Cal_Map, RF2, &Cprog_table2);
560 if (!bcal)
e8783950 561 Cprog_cal2 = Cprog_table2;
e8783950
RM
562
563 state->m_RF_A1[RFBand] =
564 (Cprog_cal2 - Cprog_table2 - Cprog_cal1 + Cprog_table1) /
0fe44629 565 ((s32)(RF2) - (s32)(RF1));
e8783950 566
0fe44629
OE
567 if (RF3 == 0)
568 break;
e8783950 569
469ffe08
MCC
570 status = PowerScan(state, RFBand, RF3, &RF3, &bcal);
571 if (status < 0)
572 break;
0fe44629 573 if (bcal) {
469ffe08
MCC
574 status = CalibrateRF(state, RFBand, RF3, &Cprog_cal3);
575 if (status < 0)
576 break;
e8783950 577 }
0fe44629
OE
578 SearchMap2(m_RF_Cal_Map, RF3, &Cprog_table3);
579 if (!bcal)
e8783950 580 Cprog_cal3 = Cprog_table3;
0fe44629 581 state->m_RF_A2[RFBand] = (Cprog_cal3 - Cprog_table3 - Cprog_cal2 + Cprog_table2) / ((s32)(RF3) - (s32)(RF2));
e8783950
RM
582 state->m_RF_B2[RFBand] = Cprog_cal2 - Cprog_table2;
583
0fe44629 584 } while (0);
e8783950
RM
585
586 state->m_RF1[RFBand] = RF1;
587 state->m_RF2[RFBand] = RF2;
588 state->m_RF3[RFBand] = RF3;
589
590#if 0
f3d40bd0 591 printk(KERN_ERR "tda18271c2dd: %s %d RF1 = %d A1 = %d B1 = %d RF2 = %d A2 = %d B2 = %d RF3 = %d\n", __func__,
0fe44629
OE
592 RFBand, RF1, state->m_RF_A1[RFBand], state->m_RF_B1[RFBand], RF2,
593 state->m_RF_A2[RFBand], state->m_RF_B2[RFBand], RF3);
e8783950
RM
594#endif
595
596 return status;
597}
598
599static int PowerScan(struct tda_state *state,
0fe44629 600 u8 RFBand, u32 RF_in, u32 *pRF_Out, bool *pbcal)
e8783950 601{
0fe44629
OE
602 int status = 0;
603 do {
604 u8 Gain_Taper = 0;
605 s32 RFC_Cprog = 0;
606 u8 CID_Target = 0;
607 u8 CountLimit = 0;
608 u32 freq_MainPLL;
609 u8 Regs[NUM_REGS];
610 u8 CID_Gain;
611 s32 Count = 0;
612 int sign = 1;
613 bool wait = false;
614
615 if (!(SearchMap2(m_RF_Cal_Map, RF_in, &RFC_Cprog) &&
616 SearchMap1(m_GainTaper_Map, RF_in, &Gain_Taper) &&
617 SearchMap3(m_CID_Target_Map, RF_in, &CID_Target, &CountLimit))) {
618
f3d40bd0 619 printk(KERN_ERR "tda18271c2dd: %s Search map failed\n", __func__);
0fe44629
OE
620 return -EINVAL;
621 }
622
623 state->m_Regs[EP2] = (RFBand << 5) | Gain_Taper;
624 state->m_Regs[EB14] = (RFC_Cprog);
469ffe08
MCC
625 status = UpdateReg(state, EP2);
626 if (status < 0)
627 break;
628 status = UpdateReg(state, EB14);
629 if (status < 0)
630 break;
0fe44629
OE
631
632 freq_MainPLL = RF_in + 1000000;
469ffe08
MCC
633 status = CalcMainPLL(state, freq_MainPLL);
634 if (status < 0)
635 break;
0fe44629
OE
636 msleep(5);
637 state->m_Regs[EP4] = (state->m_Regs[EP4] & ~0x03) | 1; /* CAL_mode = 1 */
469ffe08
MCC
638 status = UpdateReg(state, EP4);
639 if (status < 0)
640 break;
641 status = UpdateReg(state, EP2); /* Launch power measurement */
642 if (status < 0)
643 break;
644 status = ReadExtented(state, Regs);
645 if (status < 0)
646 break;
0fe44629
OE
647 CID_Gain = Regs[EB10] & 0x3F;
648 state->m_Regs[ID] = Regs[ID]; /* Chip version, (needed for C1 workarround in CalibrateRF) */
649
650 *pRF_Out = RF_in;
651
652 while (CID_Gain < CID_Target) {
653 freq_MainPLL = RF_in + sign * Count + 1000000;
469ffe08
MCC
654 status = CalcMainPLL(state, freq_MainPLL);
655 if (status < 0)
656 break;
0fe44629
OE
657 msleep(wait ? 5 : 1);
658 wait = false;
469ffe08
MCC
659 status = UpdateReg(state, EP2); /* Launch power measurement */
660 if (status < 0)
661 break;
662 status = ReadExtented(state, Regs);
663 if (status < 0)
664 break;
0fe44629
OE
665 CID_Gain = Regs[EB10] & 0x3F;
666 Count += 200000;
667
668 if (Count < CountLimit * 100000)
669 continue;
670 if (sign < 0)
671 break;
672
673 sign = -sign;
674 Count = 200000;
675 wait = true;
676 }
469ffe08
MCC
677 if (status < 0)
678 break;
0fe44629
OE
679 if (CID_Gain >= CID_Target) {
680 *pbcal = true;
681 *pRF_Out = freq_MainPLL - 1000000;
682 } else
683 *pbcal = false;
684 } while (0);
685
686 return status;
e8783950
RM
687}
688
689static int PowerScanInit(struct tda_state *state)
690{
e8783950 691 int status = 0;
0fe44629 692 do {
e8783950 693 state->m_Regs[EP3] = (state->m_Regs[EP3] & ~0x1F) | 0x12;
0fe44629 694 state->m_Regs[EP4] = (state->m_Regs[EP4] & ~0x1F); /* If level = 0, Cal mode = 0 */
469ffe08
MCC
695 status = UpdateRegs(state, EP3, EP4);
696 if (status < 0)
697 break;
0fe44629 698 state->m_Regs[EB18] = (state->m_Regs[EB18] & ~0x03); /* AGC 1 Gain = 0 */
469ffe08
MCC
699 status = UpdateReg(state, EB18);
700 if (status < 0)
701 break;
0fe44629
OE
702 state->m_Regs[EB21] = (state->m_Regs[EB21] & ~0x03); /* AGC 2 Gain = 0 (Datasheet = 3) */
703 state->m_Regs[EB23] = (state->m_Regs[EB23] | 0x06); /* ForceLP_Fc2_En = 1, LPFc[2] = 1 */
469ffe08
MCC
704 status = UpdateRegs(state, EB21, EB23);
705 if (status < 0)
706 break;
0fe44629 707 } while (0);
e8783950
RM
708 return status;
709}
710
711static int CalcRFFilterCurve(struct tda_state *state)
712{
e8783950 713 int status = 0;
0fe44629
OE
714 do {
715 msleep(200); /* Temperature stabilisation */
469ffe08
MCC
716 status = PowerScanInit(state);
717 if (status < 0)
718 break;
719 status = RFTrackingFiltersInit(state, 0);
720 if (status < 0)
721 break;
722 status = RFTrackingFiltersInit(state, 1);
723 if (status < 0)
724 break;
725 status = RFTrackingFiltersInit(state, 2);
726 if (status < 0)
727 break;
728 status = RFTrackingFiltersInit(state, 3);
729 if (status < 0)
730 break;
731 status = RFTrackingFiltersInit(state, 4);
732 if (status < 0)
733 break;
734 status = RFTrackingFiltersInit(state, 5);
735 if (status < 0)
736 break;
737 status = RFTrackingFiltersInit(state, 6);
738 if (status < 0)
739 break;
740 status = ThermometerRead(state, &state->m_TMValue_RFCal); /* also switches off Cal mode !!! */
741 if (status < 0)
742 break;
0fe44629 743 } while (0);
e8783950
RM
744
745 return status;
746}
747
748static int FixedContentsI2CUpdate(struct tda_state *state)
749{
750 static u8 InitRegs[] = {
0fe44629
OE
751 0x08, 0x80, 0xC6,
752 0xDF, 0x16, 0x60, 0x80,
753 0x80, 0x00, 0x00, 0x00,
754 0x00, 0x00, 0x00, 0x00,
755 0xFC, 0x01, 0x84, 0x41,
756 0x01, 0x84, 0x40, 0x07,
757 0x00, 0x00, 0x96, 0x3F,
758 0xC1, 0x00, 0x8F, 0x00,
759 0x00, 0x8C, 0x00, 0x20,
760 0xB3, 0x48, 0xB0,
e8783950
RM
761 };
762 int status = 0;
0fe44629 763 memcpy(&state->m_Regs[TM], InitRegs, EB23 - TM + 1);
e8783950 764 do {
469ffe08
MCC
765 status = UpdateRegs(state, TM, EB23);
766 if (status < 0)
767 break;
e8783950 768
0fe44629 769 /* AGC1 gain setup */
e8783950 770 state->m_Regs[EB17] = 0x00;
469ffe08
MCC
771 status = UpdateReg(state, EB17);
772 if (status < 0)
773 break;
e8783950 774 state->m_Regs[EB17] = 0x03;
469ffe08
MCC
775 status = UpdateReg(state, EB17);
776 if (status < 0)
777 break;
e8783950 778 state->m_Regs[EB17] = 0x43;
469ffe08
MCC
779 status = UpdateReg(state, EB17);
780 if (status < 0)
781 break;
e8783950 782 state->m_Regs[EB17] = 0x4C;
469ffe08
MCC
783 status = UpdateReg(state, EB17);
784 if (status < 0)
785 break;
e8783950 786
0fe44629 787 /* IRC Cal Low band */
e8783950
RM
788 state->m_Regs[EP3] = 0x1F;
789 state->m_Regs[EP4] = 0x66;
790 state->m_Regs[EP5] = 0x81;
791 state->m_Regs[CPD] = 0xCC;
792 state->m_Regs[CD1] = 0x6C;
793 state->m_Regs[CD2] = 0x00;
794 state->m_Regs[CD3] = 0x00;
795 state->m_Regs[MPD] = 0xC5;
796 state->m_Regs[MD1] = 0x77;
797 state->m_Regs[MD2] = 0x08;
798 state->m_Regs[MD3] = 0x00;
469ffe08
MCC
799 status = UpdateRegs(state, EP2, MD3); /* diff between sw and datasheet (ep3-md3) */
800 if (status < 0)
801 break;
e8783950 802
0fe44629
OE
803#if 0
804 state->m_Regs[EB4] = 0x61; /* missing in sw */
469ffe08
MCC
805 status = UpdateReg(state, EB4);
806 if (status < 0)
807 break;
0fe44629
OE
808 msleep(1);
809 state->m_Regs[EB4] = 0x41;
469ffe08
MCC
810 status = UpdateReg(state, EB4);
811 if (status < 0)
812 break;
0fe44629 813#endif
e8783950
RM
814
815 msleep(5);
469ffe08
MCC
816 status = UpdateReg(state, EP1);
817 if (status < 0)
818 break;
e8783950
RM
819 msleep(5);
820
821 state->m_Regs[EP5] = 0x85;
822 state->m_Regs[CPD] = 0xCB;
823 state->m_Regs[CD1] = 0x66;
824 state->m_Regs[CD2] = 0x70;
469ffe08
MCC
825 status = UpdateRegs(state, EP3, CD3);
826 if (status < 0)
827 break;
e8783950 828 msleep(5);
469ffe08
MCC
829 status = UpdateReg(state, EP2);
830 if (status < 0)
831 break;
e8783950
RM
832 msleep(30);
833
0fe44629 834 /* IRC Cal mid band */
e8783950
RM
835 state->m_Regs[EP5] = 0x82;
836 state->m_Regs[CPD] = 0xA8;
837 state->m_Regs[CD2] = 0x00;
0fe44629 838 state->m_Regs[MPD] = 0xA1; /* Datasheet = 0xA9 */
e8783950
RM
839 state->m_Regs[MD1] = 0x73;
840 state->m_Regs[MD2] = 0x1A;
469ffe08
MCC
841 status = UpdateRegs(state, EP3, MD3);
842 if (status < 0)
843 break;
e8783950
RM
844
845 msleep(5);
469ffe08
MCC
846 status = UpdateReg(state, EP1);
847 if (status < 0)
848 break;
e8783950
RM
849 msleep(5);
850
851 state->m_Regs[EP5] = 0x86;
852 state->m_Regs[CPD] = 0xA8;
853 state->m_Regs[CD1] = 0x66;
854 state->m_Regs[CD2] = 0xA0;
469ffe08
MCC
855 status = UpdateRegs(state, EP3, CD3);
856 if (status < 0)
857 break;
e8783950 858 msleep(5);
469ffe08
MCC
859 status = UpdateReg(state, EP2);
860 if (status < 0)
861 break;
e8783950
RM
862 msleep(30);
863
0fe44629 864 /* IRC Cal high band */
e8783950
RM
865 state->m_Regs[EP5] = 0x83;
866 state->m_Regs[CPD] = 0x98;
867 state->m_Regs[CD1] = 0x65;
868 state->m_Regs[CD2] = 0x00;
0fe44629 869 state->m_Regs[MPD] = 0x91; /* Datasheet = 0x91 */
e8783950
RM
870 state->m_Regs[MD1] = 0x71;
871 state->m_Regs[MD2] = 0xCD;
469ffe08
MCC
872 status = UpdateRegs(state, EP3, MD3);
873 if (status < 0)
874 break;
e8783950 875 msleep(5);
469ffe08
MCC
876 status = UpdateReg(state, EP1);
877 if (status < 0)
878 break;
e8783950
RM
879 msleep(5);
880 state->m_Regs[EP5] = 0x87;
881 state->m_Regs[CD1] = 0x65;
882 state->m_Regs[CD2] = 0x50;
469ffe08
MCC
883 status = UpdateRegs(state, EP3, CD3);
884 if (status < 0)
885 break;
e8783950 886 msleep(5);
469ffe08
MCC
887 status = UpdateReg(state, EP2);
888 if (status < 0)
889 break;
e8783950
RM
890 msleep(30);
891
0fe44629 892 /* Back to normal */
e8783950 893 state->m_Regs[EP4] = 0x64;
469ffe08
MCC
894 status = UpdateReg(state, EP4);
895 if (status < 0)
896 break;
897 status = UpdateReg(state, EP1);
898 if (status < 0)
899 break;
e8783950 900
0fe44629 901 } while (0);
e8783950
RM
902 return status;
903}
904
905static int InitCal(struct tda_state *state)
906{
907 int status = 0;
908
0fe44629 909 do {
469ffe08
MCC
910 status = FixedContentsI2CUpdate(state);
911 if (status < 0)
912 break;
913 status = CalcRFFilterCurve(state);
914 if (status < 0)
915 break;
916 status = StandBy(state);
917 if (status < 0)
918 break;
0fe44629
OE
919 /* m_bInitDone = true; */
920 } while (0);
e8783950
RM
921 return status;
922};
923
924static int RFTrackingFiltersCorrection(struct tda_state *state,
925 u32 Frequency)
926{
927 int status = 0;
928 s32 Cprog_table;
929 u8 RFBand;
930 u8 dCoverdT;
931
0fe44629
OE
932 if (!SearchMap2(m_RF_Cal_Map, Frequency, &Cprog_table) ||
933 !SearchMap4(m_RF_Band_Map, Frequency, &RFBand) ||
934 !SearchMap1(m_RF_Cal_DC_Over_DT_Map, Frequency, &dCoverdT))
935
e8783950 936 return -EINVAL;
e8783950 937
0fe44629 938 do {
e8783950
RM
939 u8 TMValue_Current;
940 u32 RF1 = state->m_RF1[RFBand];
941 u32 RF2 = state->m_RF1[RFBand];
942 u32 RF3 = state->m_RF1[RFBand];
943 s32 RF_A1 = state->m_RF_A1[RFBand];
944 s32 RF_B1 = state->m_RF_B1[RFBand];
945 s32 RF_A2 = state->m_RF_A2[RFBand];
946 s32 RF_B2 = state->m_RF_B2[RFBand];
947 s32 Capprox = 0;
948 int TComp;
949
0fe44629 950 state->m_Regs[EP3] &= ~0xE0; /* Power up */
469ffe08
MCC
951 status = UpdateReg(state, EP3);
952 if (status < 0)
953 break;
e8783950 954
469ffe08
MCC
955 status = ThermometerRead(state, &TMValue_Current);
956 if (status < 0)
957 break;
e8783950 958
0fe44629 959 if (RF3 == 0 || Frequency < RF2)
e8783950 960 Capprox = RF_A1 * ((s32)(Frequency) - (s32)(RF1)) + RF_B1 + Cprog_table;
e8783950 961 else
e8783950 962 Capprox = RF_A2 * ((s32)(Frequency) - (s32)(RF2)) + RF_B2 + Cprog_table;
e8783950
RM
963
964 TComp = (int)(dCoverdT) * ((int)(TMValue_Current) - (int)(state->m_TMValue_RFCal))/1000;
965
966 Capprox += TComp;
967
0fe44629
OE
968 if (Capprox < 0)
969 Capprox = 0;
970 else if (Capprox > 255)
971 Capprox = 255;
e8783950
RM
972
973
0fe44629
OE
974 /* TODO Temperature compensation. There is defenitely a scale factor */
975 /* missing in the datasheet, so leave it out for now. */
976 state->m_Regs[EB14] = Capprox;
e8783950 977
469ffe08
MCC
978 status = UpdateReg(state, EB14);
979 if (status < 0)
980 break;
e8783950 981
0fe44629 982 } while (0);
e8783950
RM
983 return status;
984}
985
986static int ChannelConfiguration(struct tda_state *state,
987 u32 Frequency, int Standard)
988{
989
990 s32 IntermediateFrequency = m_StandardTable[Standard].m_IFFrequency;
991 int status = 0;
992
993 u8 BP_Filter = 0;
994 u8 RF_Band = 0;
995 u8 GainTaper = 0;
ea90f011 996 u8 IR_Meas = 0;
e8783950 997
0fe44629 998 state->IF = IntermediateFrequency;
f3d40bd0 999 /* printk("tda18271c2dd: %s Freq = %d Standard = %d IF = %d\n", __func__, Frequency, Standard, IntermediateFrequency); */
0fe44629 1000 /* get values from tables */
e8783950 1001
0fe44629
OE
1002 if (!(SearchMap1(m_BP_Filter_Map, Frequency, &BP_Filter) &&
1003 SearchMap1(m_GainTaper_Map, Frequency, &GainTaper) &&
1004 SearchMap1(m_IR_Meas_Map, Frequency, &IR_Meas) &&
1005 SearchMap4(m_RF_Band_Map, Frequency, &RF_Band))) {
1006
f3d40bd0 1007 printk(KERN_ERR "tda18271c2dd: %s SearchMap failed\n", __func__);
e8783950
RM
1008 return -EINVAL;
1009 }
1010
0fe44629 1011 do {
e8783950 1012 state->m_Regs[EP3] = (state->m_Regs[EP3] & ~0x1F) | m_StandardTable[Standard].m_EP3_4_0;
0fe44629
OE
1013 state->m_Regs[EP3] &= ~0x04; /* switch RFAGC to high speed mode */
1014
1015 /* m_EP4 default for XToutOn, CAL_Mode (0) */
1016 state->m_Regs[EP4] = state->m_EP4 | ((Standard > HF_AnalogMax) ? state->m_IFLevelDigital : state->m_IFLevelAnalog);
1017 /* state->m_Regs[EP4] = state->m_EP4 | state->m_IFLevelDigital; */
1018 if (Standard <= HF_AnalogMax)
1019 state->m_Regs[EP4] = state->m_EP4 | state->m_IFLevelAnalog;
1020 else if (Standard <= HF_ATSC)
1021 state->m_Regs[EP4] = state->m_EP4 | state->m_IFLevelDVBT;
1022 else if (Standard <= HF_DVBC)
1023 state->m_Regs[EP4] = state->m_EP4 | state->m_IFLevelDVBC;
1024 else
1025 state->m_Regs[EP4] = state->m_EP4 | state->m_IFLevelDigital;
e8783950 1026
0fe44629 1027 if ((Standard == HF_FM_Radio) && state->m_bFMInput)
58632818 1028 state->m_Regs[EP4] |= 0x80;
e8783950
RM
1029
1030 state->m_Regs[MPD] &= ~0x80;
0fe44629
OE
1031 if (Standard > HF_AnalogMax)
1032 state->m_Regs[MPD] |= 0x80; /* Add IF_notch for digital */
e8783950
RM
1033
1034 state->m_Regs[EB22] = m_StandardTable[Standard].m_EB22;
1035
0fe44629
OE
1036 /* Note: This is missing from flowchart in TDA18271 specification ( 1.5 MHz cutoff for FM ) */
1037 if (Standard == HF_FM_Radio)
1038 state->m_Regs[EB23] |= 0x06; /* ForceLP_Fc2_En = 1, LPFc[2] = 1 */
1039 else
1040 state->m_Regs[EB23] &= ~0x06; /* ForceLP_Fc2_En = 0, LPFc[2] = 0 */
e8783950 1041
469ffe08
MCC
1042 status = UpdateRegs(state, EB22, EB23);
1043 if (status < 0)
1044 break;
e8783950 1045
0fe44629 1046 state->m_Regs[EP1] = (state->m_Regs[EP1] & ~0x07) | 0x40 | BP_Filter; /* Dis_Power_level = 1, Filter */
e8783950
RM
1047 state->m_Regs[EP5] = (state->m_Regs[EP5] & ~0x07) | IR_Meas;
1048 state->m_Regs[EP2] = (RF_Band << 5) | GainTaper;
1049
1050 state->m_Regs[EB1] = (state->m_Regs[EB1] & ~0x07) |
0fe44629
OE
1051 (state->m_bMaster ? 0x04 : 0x00); /* CALVCO_FortLOn = MS */
1052 /* AGC1_always_master = 0 */
1053 /* AGC_firstn = 0 */
469ffe08
MCC
1054 status = UpdateReg(state, EB1);
1055 if (status < 0)
1056 break;
0fe44629
OE
1057
1058 if (state->m_bMaster) {
469ffe08
MCC
1059 status = CalcMainPLL(state, Frequency + IntermediateFrequency);
1060 if (status < 0)
1061 break;
1062 status = UpdateRegs(state, TM, EP5);
1063 if (status < 0)
1064 break;
0fe44629 1065 state->m_Regs[EB4] |= 0x20; /* LO_forceSrce = 1 */
469ffe08
MCC
1066 status = UpdateReg(state, EB4);
1067 if (status < 0)
1068 break;
e8783950 1069 msleep(1);
0fe44629 1070 state->m_Regs[EB4] &= ~0x20; /* LO_forceSrce = 0 */
469ffe08
MCC
1071 status = UpdateReg(state, EB4);
1072 if (status < 0)
1073 break;
0fe44629 1074 } else {
ea90f011 1075 u8 PostDiv = 0;
e8783950 1076 u8 Div;
469ffe08
MCC
1077 status = CalcCalPLL(state, Frequency + IntermediateFrequency);
1078 if (status < 0)
1079 break;
e8783950 1080
0fe44629 1081 SearchMap3(m_Cal_PLL_Map, Frequency + IntermediateFrequency, &PostDiv, &Div);
e8783950 1082 state->m_Regs[MPD] = (state->m_Regs[MPD] & ~0x7F) | (PostDiv & 0x77);
469ffe08
MCC
1083 status = UpdateReg(state, MPD);
1084 if (status < 0)
1085 break;
1086 status = UpdateRegs(state, TM, EP5);
1087 if (status < 0)
1088 break;
e8783950 1089
0fe44629 1090 state->m_Regs[EB7] |= 0x20; /* CAL_forceSrce = 1 */
469ffe08
MCC
1091 status = UpdateReg(state, EB7);
1092 if (status < 0)
1093 break;
e8783950 1094 msleep(1);
0fe44629 1095 state->m_Regs[EB7] &= ~0x20; /* CAL_forceSrce = 0 */
469ffe08
MCC
1096 status = UpdateReg(state, EB7);
1097 if (status < 0)
1098 break;
e8783950
RM
1099 }
1100 msleep(20);
0fe44629
OE
1101 if (Standard != HF_FM_Radio)
1102 state->m_Regs[EP3] |= 0x04; /* RFAGC to normal mode */
469ffe08
MCC
1103 status = UpdateReg(state, EP3);
1104 if (status < 0)
1105 break;
e8783950 1106
0fe44629 1107 } while (0);
e8783950
RM
1108 return status;
1109}
1110
0fe44629 1111static int sleep(struct dvb_frontend *fe)
e8783950
RM
1112{
1113 struct tda_state *state = fe->tuner_priv;
1114
1115 StandBy(state);
1116 return 0;
1117}
1118
0fe44629 1119static int init(struct dvb_frontend *fe)
e8783950 1120{
e8783950
RM
1121 return 0;
1122}
1123
f2709c20
MCC
1124static void release(struct dvb_frontend *fe)
1125{
1126 kfree(fe->tuner_priv);
1127 fe->tuner_priv = NULL;
1128}
1129
1130
14d24d14 1131static int set_params(struct dvb_frontend *fe)
e8783950
RM
1132{
1133 struct tda_state *state = fe->tuner_priv;
1134 int status = 0;
1135 int Standard;
fd66c45d
MCC
1136 u32 bw = fe->dtv_property_cache.bandwidth_hz;
1137 u32 delsys = fe->dtv_property_cache.delivery_system;
e8783950 1138
fd66c45d 1139 state->m_Frequency = fe->dtv_property_cache.frequency;
e8783950 1140
fd66c45d
MCC
1141 switch (delsys) {
1142 case SYS_DVBT:
1143 case SYS_DVBT2:
1144 switch (bw) {
1145 case 6000000:
e8783950
RM
1146 Standard = HF_DVBT_6MHZ;
1147 break;
fd66c45d 1148 case 7000000:
e8783950
RM
1149 Standard = HF_DVBT_7MHZ;
1150 break;
fd66c45d 1151 case 8000000:
e8783950
RM
1152 Standard = HF_DVBT_8MHZ;
1153 break;
fd66c45d
MCC
1154 default:
1155 return -EINVAL;
e8783950 1156 }
fd66c45d
MCC
1157 case SYS_DVBC_ANNEX_A:
1158 case SYS_DVBC_ANNEX_C:
2440f7af 1159 if (bw <= 6000000)
cf845297 1160 Standard = HF_DVBC_6MHZ;
2440f7af
MCC
1161 else if (bw <= 7000000)
1162 Standard = HF_DVBC_7MHZ;
cf845297
MCC
1163 else
1164 Standard = HF_DVBC_8MHZ;
1ca8dde8 1165 break;
fd66c45d 1166 default:
e8783950 1167 return -EINVAL;
fd66c45d 1168 }
e8783950 1169 do {
fd66c45d 1170 status = RFTrackingFiltersCorrection(state, state->m_Frequency);
469ffe08
MCC
1171 if (status < 0)
1172 break;
fd66c45d
MCC
1173 status = ChannelConfiguration(state, state->m_Frequency,
1174 Standard);
469ffe08
MCC
1175 if (status < 0)
1176 break;
e8783950 1177
0fe44629
OE
1178 msleep(state->m_SettlingTime); /* Allow AGC's to settle down */
1179 } while (0);
e8783950
RM
1180 return status;
1181}
1182
1183#if 0
0fe44629 1184static int GetSignalStrength(s32 *pSignalStrength, u32 RFAgc, u32 IFAgc)
e8783950 1185{
0fe44629
OE
1186 if (IFAgc < 500) {
1187 /* Scale this from 0 to 50000 */
e8783950
RM
1188 *pSignalStrength = IFAgc * 100;
1189 } else {
0fe44629 1190 /* Scale range 500-1500 to 50000-80000 */
e8783950
RM
1191 *pSignalStrength = 50000 + (IFAgc - 500) * 30;
1192 }
1193
1194 return 0;
1195}
1196#endif
1197
8513e144 1198static int get_if_frequency(struct dvb_frontend *fe, u32 *frequency)
e8783950
RM
1199{
1200 struct tda_state *state = fe->tuner_priv;
1201
1202 *frequency = state->IF;
1203 return 0;
1204}
1205
1206static int get_bandwidth(struct dvb_frontend *fe, u32 *bandwidth)
1207{
0fe44629
OE
1208 /* struct tda_state *state = fe->tuner_priv; */
1209 /* *bandwidth = priv->bandwidth; */
e8783950
RM
1210 return 0;
1211}
1212
1213
14c4bf3c 1214static const struct dvb_tuner_ops tuner_ops = {
e8783950
RM
1215 .info = {
1216 .name = "NXP TDA18271C2D",
1217 .frequency_min = 47125000,
1218 .frequency_max = 865000000,
1219 .frequency_step = 62500
1220 },
1221 .init = init,
1222 .sleep = sleep,
1223 .set_params = set_params,
f2709c20 1224 .release = release,
8513e144 1225 .get_if_frequency = get_if_frequency,
e8783950
RM
1226 .get_bandwidth = get_bandwidth,
1227};
1228
1229struct dvb_frontend *tda18271c2dd_attach(struct dvb_frontend *fe,
1230 struct i2c_adapter *i2c, u8 adr)
1231{
1232 struct tda_state *state;
1233
1234 state = kzalloc(sizeof(struct tda_state), GFP_KERNEL);
1235 if (!state)
1236 return NULL;
1237
1238 fe->tuner_priv = state;
1239 state->adr = adr;
1240 state->i2c = i2c;
1241 memcpy(&fe->ops.tuner_ops, &tuner_ops, sizeof(struct dvb_tuner_ops));
1242 reset(state);
1243 InitCal(state);
1244
1245 return fe;
1246}
e8783950 1247EXPORT_SYMBOL_GPL(tda18271c2dd_attach);
0fe44629 1248
e8783950
RM
1249MODULE_DESCRIPTION("TDA18271C2 driver");
1250MODULE_AUTHOR("DD");
1251MODULE_LICENSE("GPL");