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