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