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