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