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