]> git.proxmox.com Git - mirror_ubuntu-jammy-kernel.git/blame - drivers/media/dvb-frontends/tda18271c2dd.c
Merge remote-tracking branches 'asoc/topic/wm8960', 'asoc/topic/wm8978' and 'asoc...
[mirror_ubuntu-jammy-kernel.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
30#include "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 status = status;
678 if (status < 0)
679 break;
0fe44629
OE
680 if (CID_Gain >= CID_Target) {
681 *pbcal = true;
682 *pRF_Out = freq_MainPLL - 1000000;
683 } else
684 *pbcal = false;
685 } while (0);
686
687 return status;
e8783950
RM
688}
689
690static int PowerScanInit(struct tda_state *state)
691{
e8783950 692 int status = 0;
0fe44629 693 do {
e8783950 694 state->m_Regs[EP3] = (state->m_Regs[EP3] & ~0x1F) | 0x12;
0fe44629 695 state->m_Regs[EP4] = (state->m_Regs[EP4] & ~0x1F); /* If level = 0, Cal mode = 0 */
469ffe08
MCC
696 status = UpdateRegs(state, EP3, EP4);
697 if (status < 0)
698 break;
0fe44629 699 state->m_Regs[EB18] = (state->m_Regs[EB18] & ~0x03); /* AGC 1 Gain = 0 */
469ffe08
MCC
700 status = UpdateReg(state, EB18);
701 if (status < 0)
702 break;
0fe44629
OE
703 state->m_Regs[EB21] = (state->m_Regs[EB21] & ~0x03); /* AGC 2 Gain = 0 (Datasheet = 3) */
704 state->m_Regs[EB23] = (state->m_Regs[EB23] | 0x06); /* ForceLP_Fc2_En = 1, LPFc[2] = 1 */
469ffe08
MCC
705 status = UpdateRegs(state, EB21, EB23);
706 if (status < 0)
707 break;
0fe44629 708 } while (0);
e8783950
RM
709 return status;
710}
711
712static int CalcRFFilterCurve(struct tda_state *state)
713{
e8783950 714 int status = 0;
0fe44629
OE
715 do {
716 msleep(200); /* Temperature stabilisation */
469ffe08
MCC
717 status = PowerScanInit(state);
718 if (status < 0)
719 break;
720 status = RFTrackingFiltersInit(state, 0);
721 if (status < 0)
722 break;
723 status = RFTrackingFiltersInit(state, 1);
724 if (status < 0)
725 break;
726 status = RFTrackingFiltersInit(state, 2);
727 if (status < 0)
728 break;
729 status = RFTrackingFiltersInit(state, 3);
730 if (status < 0)
731 break;
732 status = RFTrackingFiltersInit(state, 4);
733 if (status < 0)
734 break;
735 status = RFTrackingFiltersInit(state, 5);
736 if (status < 0)
737 break;
738 status = RFTrackingFiltersInit(state, 6);
739 if (status < 0)
740 break;
741 status = ThermometerRead(state, &state->m_TMValue_RFCal); /* also switches off Cal mode !!! */
742 if (status < 0)
743 break;
0fe44629 744 } while (0);
e8783950
RM
745
746 return status;
747}
748
749static int FixedContentsI2CUpdate(struct tda_state *state)
750{
751 static u8 InitRegs[] = {
0fe44629
OE
752 0x08, 0x80, 0xC6,
753 0xDF, 0x16, 0x60, 0x80,
754 0x80, 0x00, 0x00, 0x00,
755 0x00, 0x00, 0x00, 0x00,
756 0xFC, 0x01, 0x84, 0x41,
757 0x01, 0x84, 0x40, 0x07,
758 0x00, 0x00, 0x96, 0x3F,
759 0xC1, 0x00, 0x8F, 0x00,
760 0x00, 0x8C, 0x00, 0x20,
761 0xB3, 0x48, 0xB0,
e8783950
RM
762 };
763 int status = 0;
0fe44629 764 memcpy(&state->m_Regs[TM], InitRegs, EB23 - TM + 1);
e8783950 765 do {
469ffe08
MCC
766 status = UpdateRegs(state, TM, EB23);
767 if (status < 0)
768 break;
e8783950 769
0fe44629 770 /* AGC1 gain setup */
e8783950 771 state->m_Regs[EB17] = 0x00;
469ffe08
MCC
772 status = UpdateReg(state, EB17);
773 if (status < 0)
774 break;
e8783950 775 state->m_Regs[EB17] = 0x03;
469ffe08
MCC
776 status = UpdateReg(state, EB17);
777 if (status < 0)
778 break;
e8783950 779 state->m_Regs[EB17] = 0x43;
469ffe08
MCC
780 status = UpdateReg(state, EB17);
781 if (status < 0)
782 break;
e8783950 783 state->m_Regs[EB17] = 0x4C;
469ffe08
MCC
784 status = UpdateReg(state, EB17);
785 if (status < 0)
786 break;
e8783950 787
0fe44629 788 /* IRC Cal Low band */
e8783950
RM
789 state->m_Regs[EP3] = 0x1F;
790 state->m_Regs[EP4] = 0x66;
791 state->m_Regs[EP5] = 0x81;
792 state->m_Regs[CPD] = 0xCC;
793 state->m_Regs[CD1] = 0x6C;
794 state->m_Regs[CD2] = 0x00;
795 state->m_Regs[CD3] = 0x00;
796 state->m_Regs[MPD] = 0xC5;
797 state->m_Regs[MD1] = 0x77;
798 state->m_Regs[MD2] = 0x08;
799 state->m_Regs[MD3] = 0x00;
469ffe08
MCC
800 status = UpdateRegs(state, EP2, MD3); /* diff between sw and datasheet (ep3-md3) */
801 if (status < 0)
802 break;
e8783950 803
0fe44629
OE
804#if 0
805 state->m_Regs[EB4] = 0x61; /* missing in sw */
469ffe08
MCC
806 status = UpdateReg(state, EB4);
807 if (status < 0)
808 break;
0fe44629
OE
809 msleep(1);
810 state->m_Regs[EB4] = 0x41;
469ffe08
MCC
811 status = UpdateReg(state, EB4);
812 if (status < 0)
813 break;
0fe44629 814#endif
e8783950
RM
815
816 msleep(5);
469ffe08
MCC
817 status = UpdateReg(state, EP1);
818 if (status < 0)
819 break;
e8783950
RM
820 msleep(5);
821
822 state->m_Regs[EP5] = 0x85;
823 state->m_Regs[CPD] = 0xCB;
824 state->m_Regs[CD1] = 0x66;
825 state->m_Regs[CD2] = 0x70;
469ffe08
MCC
826 status = UpdateRegs(state, EP3, CD3);
827 if (status < 0)
828 break;
e8783950 829 msleep(5);
469ffe08
MCC
830 status = UpdateReg(state, EP2);
831 if (status < 0)
832 break;
e8783950
RM
833 msleep(30);
834
0fe44629 835 /* IRC Cal mid band */
e8783950
RM
836 state->m_Regs[EP5] = 0x82;
837 state->m_Regs[CPD] = 0xA8;
838 state->m_Regs[CD2] = 0x00;
0fe44629 839 state->m_Regs[MPD] = 0xA1; /* Datasheet = 0xA9 */
e8783950
RM
840 state->m_Regs[MD1] = 0x73;
841 state->m_Regs[MD2] = 0x1A;
469ffe08
MCC
842 status = UpdateRegs(state, EP3, MD3);
843 if (status < 0)
844 break;
e8783950
RM
845
846 msleep(5);
469ffe08
MCC
847 status = UpdateReg(state, EP1);
848 if (status < 0)
849 break;
e8783950
RM
850 msleep(5);
851
852 state->m_Regs[EP5] = 0x86;
853 state->m_Regs[CPD] = 0xA8;
854 state->m_Regs[CD1] = 0x66;
855 state->m_Regs[CD2] = 0xA0;
469ffe08
MCC
856 status = UpdateRegs(state, EP3, CD3);
857 if (status < 0)
858 break;
e8783950 859 msleep(5);
469ffe08
MCC
860 status = UpdateReg(state, EP2);
861 if (status < 0)
862 break;
e8783950
RM
863 msleep(30);
864
0fe44629 865 /* IRC Cal high band */
e8783950
RM
866 state->m_Regs[EP5] = 0x83;
867 state->m_Regs[CPD] = 0x98;
868 state->m_Regs[CD1] = 0x65;
869 state->m_Regs[CD2] = 0x00;
0fe44629 870 state->m_Regs[MPD] = 0x91; /* Datasheet = 0x91 */
e8783950
RM
871 state->m_Regs[MD1] = 0x71;
872 state->m_Regs[MD2] = 0xCD;
469ffe08
MCC
873 status = UpdateRegs(state, EP3, MD3);
874 if (status < 0)
875 break;
e8783950 876 msleep(5);
469ffe08
MCC
877 status = UpdateReg(state, EP1);
878 if (status < 0)
879 break;
e8783950
RM
880 msleep(5);
881 state->m_Regs[EP5] = 0x87;
882 state->m_Regs[CD1] = 0x65;
883 state->m_Regs[CD2] = 0x50;
469ffe08
MCC
884 status = UpdateRegs(state, EP3, CD3);
885 if (status < 0)
886 break;
e8783950 887 msleep(5);
469ffe08
MCC
888 status = UpdateReg(state, EP2);
889 if (status < 0)
890 break;
e8783950
RM
891 msleep(30);
892
0fe44629 893 /* Back to normal */
e8783950 894 state->m_Regs[EP4] = 0x64;
469ffe08
MCC
895 status = UpdateReg(state, EP4);
896 if (status < 0)
897 break;
898 status = UpdateReg(state, EP1);
899 if (status < 0)
900 break;
e8783950 901
0fe44629 902 } while (0);
e8783950
RM
903 return status;
904}
905
906static int InitCal(struct tda_state *state)
907{
908 int status = 0;
909
0fe44629 910 do {
469ffe08
MCC
911 status = FixedContentsI2CUpdate(state);
912 if (status < 0)
913 break;
914 status = CalcRFFilterCurve(state);
915 if (status < 0)
916 break;
917 status = StandBy(state);
918 if (status < 0)
919 break;
0fe44629
OE
920 /* m_bInitDone = true; */
921 } while (0);
e8783950
RM
922 return status;
923};
924
925static int RFTrackingFiltersCorrection(struct tda_state *state,
926 u32 Frequency)
927{
928 int status = 0;
929 s32 Cprog_table;
930 u8 RFBand;
931 u8 dCoverdT;
932
0fe44629
OE
933 if (!SearchMap2(m_RF_Cal_Map, Frequency, &Cprog_table) ||
934 !SearchMap4(m_RF_Band_Map, Frequency, &RFBand) ||
935 !SearchMap1(m_RF_Cal_DC_Over_DT_Map, Frequency, &dCoverdT))
936
e8783950 937 return -EINVAL;
e8783950 938
0fe44629 939 do {
e8783950
RM
940 u8 TMValue_Current;
941 u32 RF1 = state->m_RF1[RFBand];
942 u32 RF2 = state->m_RF1[RFBand];
943 u32 RF3 = state->m_RF1[RFBand];
944 s32 RF_A1 = state->m_RF_A1[RFBand];
945 s32 RF_B1 = state->m_RF_B1[RFBand];
946 s32 RF_A2 = state->m_RF_A2[RFBand];
947 s32 RF_B2 = state->m_RF_B2[RFBand];
948 s32 Capprox = 0;
949 int TComp;
950
0fe44629 951 state->m_Regs[EP3] &= ~0xE0; /* Power up */
469ffe08
MCC
952 status = UpdateReg(state, EP3);
953 if (status < 0)
954 break;
e8783950 955
469ffe08
MCC
956 status = ThermometerRead(state, &TMValue_Current);
957 if (status < 0)
958 break;
e8783950 959
0fe44629 960 if (RF3 == 0 || Frequency < RF2)
e8783950 961 Capprox = RF_A1 * ((s32)(Frequency) - (s32)(RF1)) + RF_B1 + Cprog_table;
e8783950 962 else
e8783950 963 Capprox = RF_A2 * ((s32)(Frequency) - (s32)(RF2)) + RF_B2 + Cprog_table;
e8783950
RM
964
965 TComp = (int)(dCoverdT) * ((int)(TMValue_Current) - (int)(state->m_TMValue_RFCal))/1000;
966
967 Capprox += TComp;
968
0fe44629
OE
969 if (Capprox < 0)
970 Capprox = 0;
971 else if (Capprox > 255)
972 Capprox = 255;
e8783950
RM
973
974
0fe44629
OE
975 /* TODO Temperature compensation. There is defenitely a scale factor */
976 /* missing in the datasheet, so leave it out for now. */
977 state->m_Regs[EB14] = Capprox;
e8783950 978
469ffe08
MCC
979 status = UpdateReg(state, EB14);
980 if (status < 0)
981 break;
e8783950 982
0fe44629 983 } while (0);
e8783950
RM
984 return status;
985}
986
987static int ChannelConfiguration(struct tda_state *state,
988 u32 Frequency, int Standard)
989{
990
991 s32 IntermediateFrequency = m_StandardTable[Standard].m_IFFrequency;
992 int status = 0;
993
994 u8 BP_Filter = 0;
995 u8 RF_Band = 0;
996 u8 GainTaper = 0;
ea90f011 997 u8 IR_Meas = 0;
e8783950 998
0fe44629 999 state->IF = IntermediateFrequency;
f3d40bd0 1000 /* printk("tda18271c2dd: %s Freq = %d Standard = %d IF = %d\n", __func__, Frequency, Standard, IntermediateFrequency); */
0fe44629 1001 /* get values from tables */
e8783950 1002
0fe44629
OE
1003 if (!(SearchMap1(m_BP_Filter_Map, Frequency, &BP_Filter) &&
1004 SearchMap1(m_GainTaper_Map, Frequency, &GainTaper) &&
1005 SearchMap1(m_IR_Meas_Map, Frequency, &IR_Meas) &&
1006 SearchMap4(m_RF_Band_Map, Frequency, &RF_Band))) {
1007
f3d40bd0 1008 printk(KERN_ERR "tda18271c2dd: %s SearchMap failed\n", __func__);
e8783950
RM
1009 return -EINVAL;
1010 }
1011
0fe44629 1012 do {
e8783950 1013 state->m_Regs[EP3] = (state->m_Regs[EP3] & ~0x1F) | m_StandardTable[Standard].m_EP3_4_0;
0fe44629
OE
1014 state->m_Regs[EP3] &= ~0x04; /* switch RFAGC to high speed mode */
1015
1016 /* m_EP4 default for XToutOn, CAL_Mode (0) */
1017 state->m_Regs[EP4] = state->m_EP4 | ((Standard > HF_AnalogMax) ? state->m_IFLevelDigital : state->m_IFLevelAnalog);
1018 /* state->m_Regs[EP4] = state->m_EP4 | state->m_IFLevelDigital; */
1019 if (Standard <= HF_AnalogMax)
1020 state->m_Regs[EP4] = state->m_EP4 | state->m_IFLevelAnalog;
1021 else if (Standard <= HF_ATSC)
1022 state->m_Regs[EP4] = state->m_EP4 | state->m_IFLevelDVBT;
1023 else if (Standard <= HF_DVBC)
1024 state->m_Regs[EP4] = state->m_EP4 | state->m_IFLevelDVBC;
1025 else
1026 state->m_Regs[EP4] = state->m_EP4 | state->m_IFLevelDigital;
e8783950 1027
0fe44629 1028 if ((Standard == HF_FM_Radio) && state->m_bFMInput)
58632818 1029 state->m_Regs[EP4] |= 0x80;
e8783950
RM
1030
1031 state->m_Regs[MPD] &= ~0x80;
0fe44629
OE
1032 if (Standard > HF_AnalogMax)
1033 state->m_Regs[MPD] |= 0x80; /* Add IF_notch for digital */
e8783950
RM
1034
1035 state->m_Regs[EB22] = m_StandardTable[Standard].m_EB22;
1036
0fe44629
OE
1037 /* Note: This is missing from flowchart in TDA18271 specification ( 1.5 MHz cutoff for FM ) */
1038 if (Standard == HF_FM_Radio)
1039 state->m_Regs[EB23] |= 0x06; /* ForceLP_Fc2_En = 1, LPFc[2] = 1 */
1040 else
1041 state->m_Regs[EB23] &= ~0x06; /* ForceLP_Fc2_En = 0, LPFc[2] = 0 */
e8783950 1042
469ffe08
MCC
1043 status = UpdateRegs(state, EB22, EB23);
1044 if (status < 0)
1045 break;
e8783950 1046
0fe44629 1047 state->m_Regs[EP1] = (state->m_Regs[EP1] & ~0x07) | 0x40 | BP_Filter; /* Dis_Power_level = 1, Filter */
e8783950
RM
1048 state->m_Regs[EP5] = (state->m_Regs[EP5] & ~0x07) | IR_Meas;
1049 state->m_Regs[EP2] = (RF_Band << 5) | GainTaper;
1050
1051 state->m_Regs[EB1] = (state->m_Regs[EB1] & ~0x07) |
0fe44629
OE
1052 (state->m_bMaster ? 0x04 : 0x00); /* CALVCO_FortLOn = MS */
1053 /* AGC1_always_master = 0 */
1054 /* AGC_firstn = 0 */
469ffe08
MCC
1055 status = UpdateReg(state, EB1);
1056 if (status < 0)
1057 break;
0fe44629
OE
1058
1059 if (state->m_bMaster) {
469ffe08
MCC
1060 status = CalcMainPLL(state, Frequency + IntermediateFrequency);
1061 if (status < 0)
1062 break;
1063 status = UpdateRegs(state, TM, EP5);
1064 if (status < 0)
1065 break;
0fe44629 1066 state->m_Regs[EB4] |= 0x20; /* LO_forceSrce = 1 */
469ffe08
MCC
1067 status = UpdateReg(state, EB4);
1068 if (status < 0)
1069 break;
e8783950 1070 msleep(1);
0fe44629 1071 state->m_Regs[EB4] &= ~0x20; /* LO_forceSrce = 0 */
469ffe08
MCC
1072 status = UpdateReg(state, EB4);
1073 if (status < 0)
1074 break;
0fe44629 1075 } else {
ea90f011 1076 u8 PostDiv = 0;
e8783950 1077 u8 Div;
469ffe08
MCC
1078 status = CalcCalPLL(state, Frequency + IntermediateFrequency);
1079 if (status < 0)
1080 break;
e8783950 1081
0fe44629 1082 SearchMap3(m_Cal_PLL_Map, Frequency + IntermediateFrequency, &PostDiv, &Div);
e8783950 1083 state->m_Regs[MPD] = (state->m_Regs[MPD] & ~0x7F) | (PostDiv & 0x77);
469ffe08
MCC
1084 status = UpdateReg(state, MPD);
1085 if (status < 0)
1086 break;
1087 status = UpdateRegs(state, TM, EP5);
1088 if (status < 0)
1089 break;
e8783950 1090
0fe44629 1091 state->m_Regs[EB7] |= 0x20; /* CAL_forceSrce = 1 */
469ffe08
MCC
1092 status = UpdateReg(state, EB7);
1093 if (status < 0)
1094 break;
e8783950 1095 msleep(1);
0fe44629 1096 state->m_Regs[EB7] &= ~0x20; /* CAL_forceSrce = 0 */
469ffe08
MCC
1097 status = UpdateReg(state, EB7);
1098 if (status < 0)
1099 break;
e8783950
RM
1100 }
1101 msleep(20);
0fe44629
OE
1102 if (Standard != HF_FM_Radio)
1103 state->m_Regs[EP3] |= 0x04; /* RFAGC to normal mode */
469ffe08
MCC
1104 status = UpdateReg(state, EP3);
1105 if (status < 0)
1106 break;
e8783950 1107
0fe44629 1108 } while (0);
e8783950
RM
1109 return status;
1110}
1111
0fe44629 1112static int sleep(struct dvb_frontend *fe)
e8783950
RM
1113{
1114 struct tda_state *state = fe->tuner_priv;
1115
1116 StandBy(state);
1117 return 0;
1118}
1119
0fe44629 1120static int init(struct dvb_frontend *fe)
e8783950 1121{
e8783950
RM
1122 return 0;
1123}
1124
f2709c20
MCC
1125static void release(struct dvb_frontend *fe)
1126{
1127 kfree(fe->tuner_priv);
1128 fe->tuner_priv = NULL;
1129}
1130
1131
14d24d14 1132static int set_params(struct dvb_frontend *fe)
e8783950
RM
1133{
1134 struct tda_state *state = fe->tuner_priv;
1135 int status = 0;
1136 int Standard;
fd66c45d
MCC
1137 u32 bw = fe->dtv_property_cache.bandwidth_hz;
1138 u32 delsys = fe->dtv_property_cache.delivery_system;
e8783950 1139
fd66c45d 1140 state->m_Frequency = fe->dtv_property_cache.frequency;
e8783950 1141
fd66c45d
MCC
1142 switch (delsys) {
1143 case SYS_DVBT:
1144 case SYS_DVBT2:
1145 switch (bw) {
1146 case 6000000:
e8783950
RM
1147 Standard = HF_DVBT_6MHZ;
1148 break;
fd66c45d 1149 case 7000000:
e8783950
RM
1150 Standard = HF_DVBT_7MHZ;
1151 break;
fd66c45d 1152 case 8000000:
e8783950
RM
1153 Standard = HF_DVBT_8MHZ;
1154 break;
fd66c45d
MCC
1155 default:
1156 return -EINVAL;
e8783950 1157 }
fd66c45d
MCC
1158 case SYS_DVBC_ANNEX_A:
1159 case SYS_DVBC_ANNEX_C:
2440f7af 1160 if (bw <= 6000000)
cf845297 1161 Standard = HF_DVBC_6MHZ;
2440f7af
MCC
1162 else if (bw <= 7000000)
1163 Standard = HF_DVBC_7MHZ;
cf845297
MCC
1164 else
1165 Standard = HF_DVBC_8MHZ;
1ca8dde8 1166 break;
fd66c45d 1167 default:
e8783950 1168 return -EINVAL;
fd66c45d 1169 }
e8783950 1170 do {
fd66c45d 1171 status = RFTrackingFiltersCorrection(state, state->m_Frequency);
469ffe08
MCC
1172 if (status < 0)
1173 break;
fd66c45d
MCC
1174 status = ChannelConfiguration(state, state->m_Frequency,
1175 Standard);
469ffe08
MCC
1176 if (status < 0)
1177 break;
e8783950 1178
0fe44629
OE
1179 msleep(state->m_SettlingTime); /* Allow AGC's to settle down */
1180 } while (0);
e8783950
RM
1181 return status;
1182}
1183
1184#if 0
0fe44629 1185static int GetSignalStrength(s32 *pSignalStrength, u32 RFAgc, u32 IFAgc)
e8783950 1186{
0fe44629
OE
1187 if (IFAgc < 500) {
1188 /* Scale this from 0 to 50000 */
e8783950
RM
1189 *pSignalStrength = IFAgc * 100;
1190 } else {
0fe44629 1191 /* Scale range 500-1500 to 50000-80000 */
e8783950
RM
1192 *pSignalStrength = 50000 + (IFAgc - 500) * 30;
1193 }
1194
1195 return 0;
1196}
1197#endif
1198
8513e144 1199static int get_if_frequency(struct dvb_frontend *fe, u32 *frequency)
e8783950
RM
1200{
1201 struct tda_state *state = fe->tuner_priv;
1202
1203 *frequency = state->IF;
1204 return 0;
1205}
1206
1207static int get_bandwidth(struct dvb_frontend *fe, u32 *bandwidth)
1208{
0fe44629
OE
1209 /* struct tda_state *state = fe->tuner_priv; */
1210 /* *bandwidth = priv->bandwidth; */
e8783950
RM
1211 return 0;
1212}
1213
1214
14c4bf3c 1215static const struct dvb_tuner_ops tuner_ops = {
e8783950
RM
1216 .info = {
1217 .name = "NXP TDA18271C2D",
1218 .frequency_min = 47125000,
1219 .frequency_max = 865000000,
1220 .frequency_step = 62500
1221 },
1222 .init = init,
1223 .sleep = sleep,
1224 .set_params = set_params,
f2709c20 1225 .release = release,
8513e144 1226 .get_if_frequency = get_if_frequency,
e8783950
RM
1227 .get_bandwidth = get_bandwidth,
1228};
1229
1230struct dvb_frontend *tda18271c2dd_attach(struct dvb_frontend *fe,
1231 struct i2c_adapter *i2c, u8 adr)
1232{
1233 struct tda_state *state;
1234
1235 state = kzalloc(sizeof(struct tda_state), GFP_KERNEL);
1236 if (!state)
1237 return NULL;
1238
1239 fe->tuner_priv = state;
1240 state->adr = adr;
1241 state->i2c = i2c;
1242 memcpy(&fe->ops.tuner_ops, &tuner_ops, sizeof(struct dvb_tuner_ops));
1243 reset(state);
1244 InitCal(state);
1245
1246 return fe;
1247}
e8783950 1248EXPORT_SYMBOL_GPL(tda18271c2dd_attach);
0fe44629 1249
e8783950
RM
1250MODULE_DESCRIPTION("TDA18271C2 driver");
1251MODULE_AUTHOR("DD");
1252MODULE_LICENSE("GPL");