[media] drxd/drxk: Don't export MulDiv32 symbol
[deliverable/linux.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>
32#include <linux/version.h>
33#include <asm/div64.h>
34
35#include "dvb_frontend.h"
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) {
0fe44629 133 printk(KERN_ERR "i2c_write error\n");
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
178#undef CHK_ERROR
179#define CHK_ERROR(s) if ((status = s) < 0) break
180
181static void reset(struct tda_state *state)
182{
183 u32 ulIFLevelAnalog = 0;
184 u32 ulIFLevelDigital = 2;
185 u32 ulIFLevelDVBC = 7;
186 u32 ulIFLevelDVBT = 6;
187 u32 ulXTOut = 0;
0fe44629 188 u32 ulStandbyMode = 0x06; /* Send in stdb, but leave osc on */
e8783950
RM
189 u32 ulSlave = 0;
190 u32 ulFMInput = 0;
191 u32 ulSettlingTime = 100;
192
193 state->m_Frequency = 0;
194 state->m_SettlingTime = 100;
195 state->m_IFLevelAnalog = (ulIFLevelAnalog & 0x07) << 2;
196 state->m_IFLevelDigital = (ulIFLevelDigital & 0x07) << 2;
197 state->m_IFLevelDVBC = (ulIFLevelDVBC & 0x07) << 2;
198 state->m_IFLevelDVBT = (ulIFLevelDVBT & 0x07) << 2;
199
200 state->m_EP4 = 0x20;
0fe44629
OE
201 if (ulXTOut != 0)
202 state->m_EP4 |= 0x40;
e8783950
RM
203
204 state->m_EP3_Standby = ((ulStandbyMode & 0x07) << 5) | 0x0F;
205 state->m_bMaster = (ulSlave == 0);
206
207 state->m_SettlingTime = ulSettlingTime;
208
209 state->m_bFMInput = (ulFMInput == 2);
210}
211
212static bool SearchMap1(struct SMap Map[],
213 u32 Frequency, u8 *pParam)
214{
215 int i = 0;
216
0fe44629 217 while ((Map[i].m_Frequency != 0) && (Frequency > Map[i].m_Frequency))
e8783950
RM
218 i += 1;
219 if (Map[i].m_Frequency == 0)
220 return false;
221 *pParam = Map[i].m_Param;
222 return true;
223}
224
225static bool SearchMap2(struct SMapI Map[],
226 u32 Frequency, s32 *pParam)
227{
228 int i = 0;
229
230 while ((Map[i].m_Frequency != 0) &&
0fe44629 231 (Frequency > Map[i].m_Frequency))
e8783950
RM
232 i += 1;
233 if (Map[i].m_Frequency == 0)
234 return false;
235 *pParam = Map[i].m_Param;
236 return true;
237}
238
0fe44629 239static bool SearchMap3(struct SMap2 Map[], u32 Frequency,
e8783950
RM
240 u8 *pParam1, u8 *pParam2)
241{
242 int i = 0;
243
244 while ((Map[i].m_Frequency != 0) &&
0fe44629 245 (Frequency > Map[i].m_Frequency))
e8783950
RM
246 i += 1;
247 if (Map[i].m_Frequency == 0)
248 return false;
249 *pParam1 = Map[i].m_Param1;
250 *pParam2 = Map[i].m_Param2;
251 return true;
252}
253
254static bool SearchMap4(struct SRFBandMap Map[],
255 u32 Frequency, u8 *pRFBand)
256{
257 int i = 0;
258
259 while (i < 7 && (Frequency > Map[i].m_RF_max))
260 i += 1;
261 if (i == 7)
262 return false;
263 *pRFBand = i;
264 return true;
265}
266
267static int ThermometerRead(struct tda_state *state, u8 *pTM_Value)
268{
269 int status = 0;
270
271 do {
272 u8 Regs[16];
273 state->m_Regs[TM] |= 0x10;
0fe44629
OE
274 CHK_ERROR(UpdateReg(state, TM));
275 CHK_ERROR(Read(state, Regs));
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;
0fe44629 279 CHK_ERROR(UpdateReg(state, TM));
e8783950 280 msleep(10);
0fe44629 281 CHK_ERROR(Read(state, Regs));
e8783950 282 }
0fe44629
OE
283 *pTM_Value = (Regs[TM] & 0x20)
284 ? m_Thermometer_Map_2[Regs[TM] & 0x0F]
285 : m_Thermometer_Map_1[Regs[TM] & 0x0F] ;
286 state->m_Regs[TM] &= ~0x10; /* Thermometer off */
287 CHK_ERROR(UpdateReg(state, TM));
288 state->m_Regs[EP4] &= ~0x03; /* CAL_mode = 0 ????????? */
289 CHK_ERROR(UpdateReg(state, EP4));
290 } while (0);
e8783950
RM
291
292 return status;
293}
294
295static int StandBy(struct tda_state *state)
296{
297 int status = 0;
298 do {
0fe44629
OE
299 state->m_Regs[EB12] &= ~0x20; /* PD_AGC1_Det = 0 */
300 CHK_ERROR(UpdateReg(state, EB12));
301 state->m_Regs[EB18] &= ~0x83; /* AGC1_loop_off = 0, AGC1_Gain = 6 dB */
302 CHK_ERROR(UpdateReg(state, EB18));
303 state->m_Regs[EB21] |= 0x03; /* AGC2_Gain = -6 dB */
e8783950 304 state->m_Regs[EP3] = state->m_EP3_Standby;
0fe44629
OE
305 CHK_ERROR(UpdateReg(state, EP3));
306 state->m_Regs[EB23] &= ~0x06; /* ForceLP_Fc2_En = 0, LP_Fc[2] = 0 */
307 CHK_ERROR(UpdateRegs(state, EB21, EB23));
308 } while (0);
e8783950
RM
309 return status;
310}
311
312static int CalcMainPLL(struct tda_state *state, u32 freq)
313{
314
315 u8 PostDiv;
316 u8 Div;
317 u64 OscFreq;
318 u32 MainDiv;
319
0fe44629 320 if (!SearchMap3(m_Main_PLL_Map, freq, &PostDiv, &Div))
e8783950 321 return -EINVAL;
e8783950
RM
322
323 OscFreq = (u64) freq * (u64) Div;
324 OscFreq *= (u64) 16384;
325 do_div(OscFreq, (u64)16000000);
326 MainDiv = OscFreq;
327
328 state->m_Regs[MPD] = PostDiv & 0x77;
329 state->m_Regs[MD1] = ((MainDiv >> 16) & 0x7F);
330 state->m_Regs[MD2] = ((MainDiv >> 8) & 0xFF);
0fe44629 331 state->m_Regs[MD3] = (MainDiv & 0xFF);
e8783950
RM
332
333 return UpdateRegs(state, MPD, MD3);
334}
335
336static int CalcCalPLL(struct tda_state *state, u32 freq)
337{
e8783950
RM
338 u8 PostDiv;
339 u8 Div;
340 u64 OscFreq;
341 u32 CalDiv;
342
0fe44629 343 if (!SearchMap3(m_Cal_PLL_Map, freq, &PostDiv, &Div))
e8783950 344 return -EINVAL;
e8783950
RM
345
346 OscFreq = (u64)freq * (u64)Div;
0fe44629
OE
347 /* CalDiv = u32( OscFreq * 16384 / 16000000 ); */
348 OscFreq *= (u64)16384;
e8783950 349 do_div(OscFreq, (u64)16000000);
0fe44629 350 CalDiv = OscFreq;
e8783950
RM
351
352 state->m_Regs[CPD] = PostDiv;
353 state->m_Regs[CD1] = ((CalDiv >> 16) & 0xFF);
354 state->m_Regs[CD2] = ((CalDiv >> 8) & 0xFF);
0fe44629 355 state->m_Regs[CD3] = (CalDiv & 0xFF);
e8783950 356
0fe44629 357 return UpdateRegs(state, CPD, CD3);
e8783950
RM
358}
359
360static int CalibrateRF(struct tda_state *state,
0fe44629 361 u8 RFBand, u32 freq, s32 *pCprog)
e8783950 362{
e8783950
RM
363 int status = 0;
364 u8 Regs[NUM_REGS];
365 do {
0fe44629
OE
366 u8 BP_Filter = 0;
367 u8 GainTaper = 0;
368 u8 RFC_K = 0;
369 u8 RFC_M = 0;
370
371 state->m_Regs[EP4] &= ~0x03; /* CAL_mode = 0 */
372 CHK_ERROR(UpdateReg(state, EP4));
373 state->m_Regs[EB18] |= 0x03; /* AGC1_Gain = 3 */
374 CHK_ERROR(UpdateReg(state, EB18));
375
376 /* Switching off LT (as datasheet says) causes calibration on C1 to fail */
377 /* (Readout of Cprog is allways 255) */
378 if (state->m_Regs[ID] != 0x83) /* C1: ID == 83, C2: ID == 84 */
379 state->m_Regs[EP3] |= 0x40; /* SM_LT = 1 */
380
381 if (!(SearchMap1(m_BP_Filter_Map, freq, &BP_Filter) &&
382 SearchMap1(m_GainTaper_Map, freq, &GainTaper) &&
383 SearchMap3(m_KM_Map, freq, &RFC_K, &RFC_M)))
e8783950 384 return -EINVAL;
e8783950
RM
385
386 state->m_Regs[EP1] = (state->m_Regs[EP1] & ~0x07) | BP_Filter;
387 state->m_Regs[EP2] = (RFBand << 5) | GainTaper;
388
389 state->m_Regs[EB13] = (state->m_Regs[EB13] & ~0x7C) | (RFC_K << 4) | (RFC_M << 2);
390
0fe44629
OE
391 CHK_ERROR(UpdateRegs(state, EP1, EP3));
392 CHK_ERROR(UpdateReg(state, EB13));
e8783950 393
0fe44629
OE
394 state->m_Regs[EB4] |= 0x20; /* LO_ForceSrce = 1 */
395 CHK_ERROR(UpdateReg(state, EB4));
e8783950 396
0fe44629
OE
397 state->m_Regs[EB7] |= 0x20; /* CAL_ForceSrce = 1 */
398 CHK_ERROR(UpdateReg(state, EB7));
e8783950 399
0fe44629
OE
400 state->m_Regs[EB14] = 0; /* RFC_Cprog = 0 */
401 CHK_ERROR(UpdateReg(state, EB14));
e8783950 402
0fe44629
OE
403 state->m_Regs[EB20] &= ~0x20; /* ForceLock = 0; */
404 CHK_ERROR(UpdateReg(state, EB20));
e8783950 405
0fe44629
OE
406 state->m_Regs[EP4] |= 0x03; /* CAL_Mode = 3 */
407 CHK_ERROR(UpdateRegs(state, EP4, EP5));
e8783950 408
0fe44629
OE
409 CHK_ERROR(CalcCalPLL(state, freq));
410 CHK_ERROR(CalcMainPLL(state, freq + 1000000));
e8783950
RM
411
412 msleep(5);
0fe44629
OE
413 CHK_ERROR(UpdateReg(state, EP2));
414 CHK_ERROR(UpdateReg(state, EP1));
415 CHK_ERROR(UpdateReg(state, EP2));
416 CHK_ERROR(UpdateReg(state, EP1));
e8783950 417
0fe44629
OE
418 state->m_Regs[EB4] &= ~0x20; /* LO_ForceSrce = 0 */
419 CHK_ERROR(UpdateReg(state, EB4));
e8783950 420
0fe44629
OE
421 state->m_Regs[EB7] &= ~0x20; /* CAL_ForceSrce = 0 */
422 CHK_ERROR(UpdateReg(state, EB7));
e8783950
RM
423 msleep(10);
424
0fe44629
OE
425 state->m_Regs[EB20] |= 0x20; /* ForceLock = 1; */
426 CHK_ERROR(UpdateReg(state, EB20));
e8783950
RM
427 msleep(60);
428
0fe44629
OE
429 state->m_Regs[EP4] &= ~0x03; /* CAL_Mode = 0 */
430 state->m_Regs[EP3] &= ~0x40; /* SM_LT = 0 */
431 state->m_Regs[EB18] &= ~0x03; /* AGC1_Gain = 0 */
432 CHK_ERROR(UpdateReg(state, EB18));
433 CHK_ERROR(UpdateRegs(state, EP3, EP4));
434 CHK_ERROR(UpdateReg(state, EP1));
e8783950 435
0fe44629 436 CHK_ERROR(ReadExtented(state, Regs));
e8783950
RM
437
438 *pCprog = Regs[EB14];
e8783950 439
0fe44629 440 } while (0);
e8783950
RM
441 return status;
442}
443
444static int RFTrackingFiltersInit(struct tda_state *state,
445 u8 RFBand)
446{
e8783950
RM
447 int status = 0;
448
449 u32 RF1 = m_RF_Band_Map[RFBand].m_RF1_Default;
450 u32 RF2 = m_RF_Band_Map[RFBand].m_RF2_Default;
451 u32 RF3 = m_RF_Band_Map[RFBand].m_RF3_Default;
452 bool bcal = false;
453
454 s32 Cprog_cal1 = 0;
455 s32 Cprog_table1 = 0;
456 s32 Cprog_cal2 = 0;
457 s32 Cprog_table2 = 0;
458 s32 Cprog_cal3 = 0;
459 s32 Cprog_table3 = 0;
460
461 state->m_RF_A1[RFBand] = 0;
462 state->m_RF_B1[RFBand] = 0;
463 state->m_RF_A2[RFBand] = 0;
464 state->m_RF_B2[RFBand] = 0;
465
466 do {
0fe44629
OE
467 CHK_ERROR(PowerScan(state, RFBand, RF1, &RF1, &bcal));
468 if (bcal) {
469 CHK_ERROR(CalibrateRF(state, RFBand, RF1, &Cprog_cal1));
e8783950 470 }
0fe44629
OE
471 SearchMap2(m_RF_Cal_Map, RF1, &Cprog_table1);
472 if (!bcal)
e8783950 473 Cprog_cal1 = Cprog_table1;
e8783950 474 state->m_RF_B1[RFBand] = Cprog_cal1 - Cprog_table1;
0fe44629 475 /* state->m_RF_A1[RF_Band] = ???? */
e8783950 476
0fe44629
OE
477 if (RF2 == 0)
478 break;
e8783950 479
0fe44629
OE
480 CHK_ERROR(PowerScan(state, RFBand, RF2, &RF2, &bcal));
481 if (bcal) {
482 CHK_ERROR(CalibrateRF(state, RFBand, RF2, &Cprog_cal2));
e8783950 483 }
0fe44629
OE
484 SearchMap2(m_RF_Cal_Map, RF2, &Cprog_table2);
485 if (!bcal)
e8783950 486 Cprog_cal2 = Cprog_table2;
e8783950
RM
487
488 state->m_RF_A1[RFBand] =
489 (Cprog_cal2 - Cprog_table2 - Cprog_cal1 + Cprog_table1) /
0fe44629 490 ((s32)(RF2) - (s32)(RF1));
e8783950 491
0fe44629
OE
492 if (RF3 == 0)
493 break;
e8783950 494
0fe44629
OE
495 CHK_ERROR(PowerScan(state, RFBand, RF3, &RF3, &bcal));
496 if (bcal) {
497 CHK_ERROR(CalibrateRF(state, RFBand, RF3, &Cprog_cal3));
e8783950 498 }
0fe44629
OE
499 SearchMap2(m_RF_Cal_Map, RF3, &Cprog_table3);
500 if (!bcal)
e8783950 501 Cprog_cal3 = Cprog_table3;
0fe44629 502 state->m_RF_A2[RFBand] = (Cprog_cal3 - Cprog_table3 - Cprog_cal2 + Cprog_table2) / ((s32)(RF3) - (s32)(RF2));
e8783950
RM
503 state->m_RF_B2[RFBand] = Cprog_cal2 - Cprog_table2;
504
0fe44629 505 } while (0);
e8783950
RM
506
507 state->m_RF1[RFBand] = RF1;
508 state->m_RF2[RFBand] = RF2;
509 state->m_RF3[RFBand] = RF3;
510
511#if 0
0fe44629
OE
512 printk(KERN_ERR "%s %d RF1 = %d A1 = %d B1 = %d RF2 = %d A2 = %d B2 = %d RF3 = %d\n", __func__,
513 RFBand, RF1, state->m_RF_A1[RFBand], state->m_RF_B1[RFBand], RF2,
514 state->m_RF_A2[RFBand], state->m_RF_B2[RFBand], RF3);
e8783950
RM
515#endif
516
517 return status;
518}
519
520static int PowerScan(struct tda_state *state,
0fe44629 521 u8 RFBand, u32 RF_in, u32 *pRF_Out, bool *pbcal)
e8783950 522{
0fe44629
OE
523 int status = 0;
524 do {
525 u8 Gain_Taper = 0;
526 s32 RFC_Cprog = 0;
527 u8 CID_Target = 0;
528 u8 CountLimit = 0;
529 u32 freq_MainPLL;
530 u8 Regs[NUM_REGS];
531 u8 CID_Gain;
532 s32 Count = 0;
533 int sign = 1;
534 bool wait = false;
535
536 if (!(SearchMap2(m_RF_Cal_Map, RF_in, &RFC_Cprog) &&
537 SearchMap1(m_GainTaper_Map, RF_in, &Gain_Taper) &&
538 SearchMap3(m_CID_Target_Map, RF_in, &CID_Target, &CountLimit))) {
539
540 printk(KERN_ERR "%s Search map failed\n", __func__);
541 return -EINVAL;
542 }
543
544 state->m_Regs[EP2] = (RFBand << 5) | Gain_Taper;
545 state->m_Regs[EB14] = (RFC_Cprog);
546 CHK_ERROR(UpdateReg(state, EP2));
547 CHK_ERROR(UpdateReg(state, EB14));
548
549 freq_MainPLL = RF_in + 1000000;
550 CHK_ERROR(CalcMainPLL(state, freq_MainPLL));
551 msleep(5);
552 state->m_Regs[EP4] = (state->m_Regs[EP4] & ~0x03) | 1; /* CAL_mode = 1 */
553 CHK_ERROR(UpdateReg(state, EP4));
554 CHK_ERROR(UpdateReg(state, EP2)); /* Launch power measurement */
555 CHK_ERROR(ReadExtented(state, Regs));
556 CID_Gain = Regs[EB10] & 0x3F;
557 state->m_Regs[ID] = Regs[ID]; /* Chip version, (needed for C1 workarround in CalibrateRF) */
558
559 *pRF_Out = RF_in;
560
561 while (CID_Gain < CID_Target) {
562 freq_MainPLL = RF_in + sign * Count + 1000000;
563 CHK_ERROR(CalcMainPLL(state, freq_MainPLL));
564 msleep(wait ? 5 : 1);
565 wait = false;
566 CHK_ERROR(UpdateReg(state, EP2)); /* Launch power measurement */
567 CHK_ERROR(ReadExtented(state, Regs));
568 CID_Gain = Regs[EB10] & 0x3F;
569 Count += 200000;
570
571 if (Count < CountLimit * 100000)
572 continue;
573 if (sign < 0)
574 break;
575
576 sign = -sign;
577 Count = 200000;
578 wait = true;
579 }
580 CHK_ERROR(status);
581 if (CID_Gain >= CID_Target) {
582 *pbcal = true;
583 *pRF_Out = freq_MainPLL - 1000000;
584 } else
585 *pbcal = false;
586 } while (0);
587
588 return status;
e8783950
RM
589}
590
591static int PowerScanInit(struct tda_state *state)
592{
e8783950 593 int status = 0;
0fe44629 594 do {
e8783950 595 state->m_Regs[EP3] = (state->m_Regs[EP3] & ~0x1F) | 0x12;
0fe44629
OE
596 state->m_Regs[EP4] = (state->m_Regs[EP4] & ~0x1F); /* If level = 0, Cal mode = 0 */
597 CHK_ERROR(UpdateRegs(state, EP3, EP4));
598 state->m_Regs[EB18] = (state->m_Regs[EB18] & ~0x03); /* AGC 1 Gain = 0 */
599 CHK_ERROR(UpdateReg(state, EB18));
600 state->m_Regs[EB21] = (state->m_Regs[EB21] & ~0x03); /* AGC 2 Gain = 0 (Datasheet = 3) */
601 state->m_Regs[EB23] = (state->m_Regs[EB23] | 0x06); /* ForceLP_Fc2_En = 1, LPFc[2] = 1 */
602 CHK_ERROR(UpdateRegs(state, EB21, EB23));
603 } while (0);
e8783950
RM
604 return status;
605}
606
607static int CalcRFFilterCurve(struct tda_state *state)
608{
e8783950 609 int status = 0;
0fe44629
OE
610 do {
611 msleep(200); /* Temperature stabilisation */
e8783950 612 CHK_ERROR(PowerScanInit(state));
0fe44629
OE
613 CHK_ERROR(RFTrackingFiltersInit(state, 0));
614 CHK_ERROR(RFTrackingFiltersInit(state, 1));
615 CHK_ERROR(RFTrackingFiltersInit(state, 2));
616 CHK_ERROR(RFTrackingFiltersInit(state, 3));
617 CHK_ERROR(RFTrackingFiltersInit(state, 4));
618 CHK_ERROR(RFTrackingFiltersInit(state, 5));
619 CHK_ERROR(RFTrackingFiltersInit(state, 6));
620 CHK_ERROR(ThermometerRead(state, &state->m_TMValue_RFCal)); /* also switches off Cal mode !!! */
621 } while (0);
e8783950
RM
622
623 return status;
624}
625
626static int FixedContentsI2CUpdate(struct tda_state *state)
627{
628 static u8 InitRegs[] = {
0fe44629
OE
629 0x08, 0x80, 0xC6,
630 0xDF, 0x16, 0x60, 0x80,
631 0x80, 0x00, 0x00, 0x00,
632 0x00, 0x00, 0x00, 0x00,
633 0xFC, 0x01, 0x84, 0x41,
634 0x01, 0x84, 0x40, 0x07,
635 0x00, 0x00, 0x96, 0x3F,
636 0xC1, 0x00, 0x8F, 0x00,
637 0x00, 0x8C, 0x00, 0x20,
638 0xB3, 0x48, 0xB0,
e8783950
RM
639 };
640 int status = 0;
0fe44629 641 memcpy(&state->m_Regs[TM], InitRegs, EB23 - TM + 1);
e8783950 642 do {
0fe44629 643 CHK_ERROR(UpdateRegs(state, TM, EB23));
e8783950 644
0fe44629 645 /* AGC1 gain setup */
e8783950 646 state->m_Regs[EB17] = 0x00;
0fe44629 647 CHK_ERROR(UpdateReg(state, EB17));
e8783950 648 state->m_Regs[EB17] = 0x03;
0fe44629 649 CHK_ERROR(UpdateReg(state, EB17));
e8783950 650 state->m_Regs[EB17] = 0x43;
0fe44629 651 CHK_ERROR(UpdateReg(state, EB17));
e8783950 652 state->m_Regs[EB17] = 0x4C;
0fe44629 653 CHK_ERROR(UpdateReg(state, EB17));
e8783950 654
0fe44629 655 /* IRC Cal Low band */
e8783950
RM
656 state->m_Regs[EP3] = 0x1F;
657 state->m_Regs[EP4] = 0x66;
658 state->m_Regs[EP5] = 0x81;
659 state->m_Regs[CPD] = 0xCC;
660 state->m_Regs[CD1] = 0x6C;
661 state->m_Regs[CD2] = 0x00;
662 state->m_Regs[CD3] = 0x00;
663 state->m_Regs[MPD] = 0xC5;
664 state->m_Regs[MD1] = 0x77;
665 state->m_Regs[MD2] = 0x08;
666 state->m_Regs[MD3] = 0x00;
0fe44629 667 CHK_ERROR(UpdateRegs(state, EP2, MD3)); /* diff between sw and datasheet (ep3-md3) */
e8783950 668
0fe44629
OE
669#if 0
670 state->m_Regs[EB4] = 0x61; /* missing in sw */
671 CHK_ERROR(UpdateReg(state, EB4));
672 msleep(1);
673 state->m_Regs[EB4] = 0x41;
674 CHK_ERROR(UpdateReg(state, EB4));
675#endif
e8783950
RM
676
677 msleep(5);
0fe44629 678 CHK_ERROR(UpdateReg(state, EP1));
e8783950
RM
679 msleep(5);
680
681 state->m_Regs[EP5] = 0x85;
682 state->m_Regs[CPD] = 0xCB;
683 state->m_Regs[CD1] = 0x66;
684 state->m_Regs[CD2] = 0x70;
0fe44629 685 CHK_ERROR(UpdateRegs(state, EP3, CD3));
e8783950 686 msleep(5);
0fe44629 687 CHK_ERROR(UpdateReg(state, EP2));
e8783950
RM
688 msleep(30);
689
0fe44629 690 /* IRC Cal mid band */
e8783950
RM
691 state->m_Regs[EP5] = 0x82;
692 state->m_Regs[CPD] = 0xA8;
693 state->m_Regs[CD2] = 0x00;
0fe44629 694 state->m_Regs[MPD] = 0xA1; /* Datasheet = 0xA9 */
e8783950
RM
695 state->m_Regs[MD1] = 0x73;
696 state->m_Regs[MD2] = 0x1A;
0fe44629 697 CHK_ERROR(UpdateRegs(state, EP3, MD3));
e8783950
RM
698
699 msleep(5);
0fe44629 700 CHK_ERROR(UpdateReg(state, EP1));
e8783950
RM
701 msleep(5);
702
703 state->m_Regs[EP5] = 0x86;
704 state->m_Regs[CPD] = 0xA8;
705 state->m_Regs[CD1] = 0x66;
706 state->m_Regs[CD2] = 0xA0;
0fe44629 707 CHK_ERROR(UpdateRegs(state, EP3, CD3));
e8783950 708 msleep(5);
0fe44629 709 CHK_ERROR(UpdateReg(state, EP2));
e8783950
RM
710 msleep(30);
711
0fe44629 712 /* IRC Cal high band */
e8783950
RM
713 state->m_Regs[EP5] = 0x83;
714 state->m_Regs[CPD] = 0x98;
715 state->m_Regs[CD1] = 0x65;
716 state->m_Regs[CD2] = 0x00;
0fe44629 717 state->m_Regs[MPD] = 0x91; /* Datasheet = 0x91 */
e8783950
RM
718 state->m_Regs[MD1] = 0x71;
719 state->m_Regs[MD2] = 0xCD;
0fe44629 720 CHK_ERROR(UpdateRegs(state, EP3, MD3));
e8783950 721 msleep(5);
0fe44629 722 CHK_ERROR(UpdateReg(state, EP1));
e8783950
RM
723 msleep(5);
724 state->m_Regs[EP5] = 0x87;
725 state->m_Regs[CD1] = 0x65;
726 state->m_Regs[CD2] = 0x50;
0fe44629 727 CHK_ERROR(UpdateRegs(state, EP3, CD3));
e8783950 728 msleep(5);
0fe44629 729 CHK_ERROR(UpdateReg(state, EP2));
e8783950
RM
730 msleep(30);
731
0fe44629 732 /* Back to normal */
e8783950 733 state->m_Regs[EP4] = 0x64;
0fe44629
OE
734 CHK_ERROR(UpdateReg(state, EP4));
735 CHK_ERROR(UpdateReg(state, EP1));
e8783950 736
0fe44629 737 } while (0);
e8783950
RM
738 return status;
739}
740
741static int InitCal(struct tda_state *state)
742{
743 int status = 0;
744
0fe44629 745 do {
e8783950
RM
746 CHK_ERROR(FixedContentsI2CUpdate(state));
747 CHK_ERROR(CalcRFFilterCurve(state));
748 CHK_ERROR(StandBy(state));
0fe44629
OE
749 /* m_bInitDone = true; */
750 } while (0);
e8783950
RM
751 return status;
752};
753
754static int RFTrackingFiltersCorrection(struct tda_state *state,
755 u32 Frequency)
756{
757 int status = 0;
758 s32 Cprog_table;
759 u8 RFBand;
760 u8 dCoverdT;
761
0fe44629
OE
762 if (!SearchMap2(m_RF_Cal_Map, Frequency, &Cprog_table) ||
763 !SearchMap4(m_RF_Band_Map, Frequency, &RFBand) ||
764 !SearchMap1(m_RF_Cal_DC_Over_DT_Map, Frequency, &dCoverdT))
765
e8783950 766 return -EINVAL;
e8783950 767
0fe44629 768 do {
e8783950
RM
769 u8 TMValue_Current;
770 u32 RF1 = state->m_RF1[RFBand];
771 u32 RF2 = state->m_RF1[RFBand];
772 u32 RF3 = state->m_RF1[RFBand];
773 s32 RF_A1 = state->m_RF_A1[RFBand];
774 s32 RF_B1 = state->m_RF_B1[RFBand];
775 s32 RF_A2 = state->m_RF_A2[RFBand];
776 s32 RF_B2 = state->m_RF_B2[RFBand];
777 s32 Capprox = 0;
778 int TComp;
779
0fe44629
OE
780 state->m_Regs[EP3] &= ~0xE0; /* Power up */
781 CHK_ERROR(UpdateReg(state, EP3));
e8783950 782
0fe44629 783 CHK_ERROR(ThermometerRead(state, &TMValue_Current));
e8783950 784
0fe44629 785 if (RF3 == 0 || Frequency < RF2)
e8783950 786 Capprox = RF_A1 * ((s32)(Frequency) - (s32)(RF1)) + RF_B1 + Cprog_table;
e8783950 787 else
e8783950 788 Capprox = RF_A2 * ((s32)(Frequency) - (s32)(RF2)) + RF_B2 + Cprog_table;
e8783950
RM
789
790 TComp = (int)(dCoverdT) * ((int)(TMValue_Current) - (int)(state->m_TMValue_RFCal))/1000;
791
792 Capprox += TComp;
793
0fe44629
OE
794 if (Capprox < 0)
795 Capprox = 0;
796 else if (Capprox > 255)
797 Capprox = 255;
e8783950
RM
798
799
0fe44629
OE
800 /* TODO Temperature compensation. There is defenitely a scale factor */
801 /* missing in the datasheet, so leave it out for now. */
802 state->m_Regs[EB14] = Capprox;
e8783950 803
0fe44629 804 CHK_ERROR(UpdateReg(state, EB14));
e8783950 805
0fe44629 806 } while (0);
e8783950
RM
807 return status;
808}
809
810static int ChannelConfiguration(struct tda_state *state,
811 u32 Frequency, int Standard)
812{
813
814 s32 IntermediateFrequency = m_StandardTable[Standard].m_IFFrequency;
815 int status = 0;
816
817 u8 BP_Filter = 0;
818 u8 RF_Band = 0;
819 u8 GainTaper = 0;
820 u8 IR_Meas;
821
0fe44629
OE
822 state->IF = IntermediateFrequency;
823 /* printk("%s Freq = %d Standard = %d IF = %d\n", __func__, Frequency, Standard, IntermediateFrequency); */
824 /* get values from tables */
e8783950 825
0fe44629
OE
826 if (!(SearchMap1(m_BP_Filter_Map, Frequency, &BP_Filter) &&
827 SearchMap1(m_GainTaper_Map, Frequency, &GainTaper) &&
828 SearchMap1(m_IR_Meas_Map, Frequency, &IR_Meas) &&
829 SearchMap4(m_RF_Band_Map, Frequency, &RF_Band))) {
830
831 printk(KERN_ERR "%s SearchMap failed\n", __func__);
e8783950
RM
832 return -EINVAL;
833 }
834
0fe44629 835 do {
e8783950 836 state->m_Regs[EP3] = (state->m_Regs[EP3] & ~0x1F) | m_StandardTable[Standard].m_EP3_4_0;
0fe44629
OE
837 state->m_Regs[EP3] &= ~0x04; /* switch RFAGC to high speed mode */
838
839 /* m_EP4 default for XToutOn, CAL_Mode (0) */
840 state->m_Regs[EP4] = state->m_EP4 | ((Standard > HF_AnalogMax) ? state->m_IFLevelDigital : state->m_IFLevelAnalog);
841 /* state->m_Regs[EP4] = state->m_EP4 | state->m_IFLevelDigital; */
842 if (Standard <= HF_AnalogMax)
843 state->m_Regs[EP4] = state->m_EP4 | state->m_IFLevelAnalog;
844 else if (Standard <= HF_ATSC)
845 state->m_Regs[EP4] = state->m_EP4 | state->m_IFLevelDVBT;
846 else if (Standard <= HF_DVBC)
847 state->m_Regs[EP4] = state->m_EP4 | state->m_IFLevelDVBC;
848 else
849 state->m_Regs[EP4] = state->m_EP4 | state->m_IFLevelDigital;
e8783950 850
0fe44629
OE
851 if ((Standard == HF_FM_Radio) && state->m_bFMInput)
852 state->m_Regs[EP4] |= 80;
e8783950
RM
853
854 state->m_Regs[MPD] &= ~0x80;
0fe44629
OE
855 if (Standard > HF_AnalogMax)
856 state->m_Regs[MPD] |= 0x80; /* Add IF_notch for digital */
e8783950
RM
857
858 state->m_Regs[EB22] = m_StandardTable[Standard].m_EB22;
859
0fe44629
OE
860 /* Note: This is missing from flowchart in TDA18271 specification ( 1.5 MHz cutoff for FM ) */
861 if (Standard == HF_FM_Radio)
862 state->m_Regs[EB23] |= 0x06; /* ForceLP_Fc2_En = 1, LPFc[2] = 1 */
863 else
864 state->m_Regs[EB23] &= ~0x06; /* ForceLP_Fc2_En = 0, LPFc[2] = 0 */
e8783950 865
0fe44629 866 CHK_ERROR(UpdateRegs(state, EB22, EB23));
e8783950 867
0fe44629 868 state->m_Regs[EP1] = (state->m_Regs[EP1] & ~0x07) | 0x40 | BP_Filter; /* Dis_Power_level = 1, Filter */
e8783950
RM
869 state->m_Regs[EP5] = (state->m_Regs[EP5] & ~0x07) | IR_Meas;
870 state->m_Regs[EP2] = (RF_Band << 5) | GainTaper;
871
872 state->m_Regs[EB1] = (state->m_Regs[EB1] & ~0x07) |
0fe44629
OE
873 (state->m_bMaster ? 0x04 : 0x00); /* CALVCO_FortLOn = MS */
874 /* AGC1_always_master = 0 */
875 /* AGC_firstn = 0 */
876 CHK_ERROR(UpdateReg(state, EB1));
877
878 if (state->m_bMaster) {
879 CHK_ERROR(CalcMainPLL(state, Frequency + IntermediateFrequency));
880 CHK_ERROR(UpdateRegs(state, TM, EP5));
881 state->m_Regs[EB4] |= 0x20; /* LO_forceSrce = 1 */
882 CHK_ERROR(UpdateReg(state, EB4));
e8783950 883 msleep(1);
0fe44629
OE
884 state->m_Regs[EB4] &= ~0x20; /* LO_forceSrce = 0 */
885 CHK_ERROR(UpdateReg(state, EB4));
886 } else {
e8783950
RM
887 u8 PostDiv;
888 u8 Div;
0fe44629 889 CHK_ERROR(CalcCalPLL(state, Frequency + IntermediateFrequency));
e8783950 890
0fe44629 891 SearchMap3(m_Cal_PLL_Map, Frequency + IntermediateFrequency, &PostDiv, &Div);
e8783950 892 state->m_Regs[MPD] = (state->m_Regs[MPD] & ~0x7F) | (PostDiv & 0x77);
0fe44629
OE
893 CHK_ERROR(UpdateReg(state, MPD));
894 CHK_ERROR(UpdateRegs(state, TM, EP5));
e8783950 895
0fe44629
OE
896 state->m_Regs[EB7] |= 0x20; /* CAL_forceSrce = 1 */
897 CHK_ERROR(UpdateReg(state, EB7));
e8783950 898 msleep(1);
0fe44629
OE
899 state->m_Regs[EB7] &= ~0x20; /* CAL_forceSrce = 0 */
900 CHK_ERROR(UpdateReg(state, EB7));
e8783950
RM
901 }
902 msleep(20);
0fe44629
OE
903 if (Standard != HF_FM_Radio)
904 state->m_Regs[EP3] |= 0x04; /* RFAGC to normal mode */
905 CHK_ERROR(UpdateReg(state, EP3));
e8783950 906
0fe44629 907 } while (0);
e8783950
RM
908 return status;
909}
910
0fe44629 911static int sleep(struct dvb_frontend *fe)
e8783950
RM
912{
913 struct tda_state *state = fe->tuner_priv;
914
915 StandBy(state);
916 return 0;
917}
918
0fe44629 919static int init(struct dvb_frontend *fe)
e8783950 920{
e8783950
RM
921 return 0;
922}
923
0fe44629 924static int release(struct dvb_frontend *fe)
e8783950
RM
925{
926 kfree(fe->tuner_priv);
927 fe->tuner_priv = NULL;
928 return 0;
929}
930
931static int set_params(struct dvb_frontend *fe,
932 struct dvb_frontend_parameters *params)
933{
934 struct tda_state *state = fe->tuner_priv;
935 int status = 0;
936 int Standard;
937
938 state->m_Frequency = params->frequency;
939
940 if (fe->ops.info.type == FE_OFDM)
941 switch (params->u.ofdm.bandwidth) {
942 case BANDWIDTH_6_MHZ:
943 Standard = HF_DVBT_6MHZ;
944 break;
945 case BANDWIDTH_7_MHZ:
946 Standard = HF_DVBT_7MHZ;
947 break;
948 default:
949 case BANDWIDTH_8_MHZ:
950 Standard = HF_DVBT_8MHZ;
951 break;
952 }
953 else if (fe->ops.info.type == FE_QAM) {
954 Standard = HF_DVBC_8MHZ;
955 } else
956 return -EINVAL;
957 do {
0fe44629
OE
958 CHK_ERROR(RFTrackingFiltersCorrection(state, params->frequency));
959 CHK_ERROR(ChannelConfiguration(state, params->frequency, Standard));
e8783950 960
0fe44629
OE
961 msleep(state->m_SettlingTime); /* Allow AGC's to settle down */
962 } while (0);
e8783950
RM
963 return status;
964}
965
966#if 0
0fe44629 967static int GetSignalStrength(s32 *pSignalStrength, u32 RFAgc, u32 IFAgc)
e8783950 968{
0fe44629
OE
969 if (IFAgc < 500) {
970 /* Scale this from 0 to 50000 */
e8783950
RM
971 *pSignalStrength = IFAgc * 100;
972 } else {
0fe44629 973 /* Scale range 500-1500 to 50000-80000 */
e8783950
RM
974 *pSignalStrength = 50000 + (IFAgc - 500) * 30;
975 }
976
977 return 0;
978}
979#endif
980
981static int get_frequency(struct dvb_frontend *fe, u32 *frequency)
982{
983 struct tda_state *state = fe->tuner_priv;
984
985 *frequency = state->IF;
986 return 0;
987}
988
989static int get_bandwidth(struct dvb_frontend *fe, u32 *bandwidth)
990{
0fe44629
OE
991 /* struct tda_state *state = fe->tuner_priv; */
992 /* *bandwidth = priv->bandwidth; */
e8783950
RM
993 return 0;
994}
995
996
997static struct dvb_tuner_ops tuner_ops = {
998 .info = {
999 .name = "NXP TDA18271C2D",
1000 .frequency_min = 47125000,
1001 .frequency_max = 865000000,
1002 .frequency_step = 62500
1003 },
1004 .init = init,
1005 .sleep = sleep,
1006 .set_params = set_params,
1007 .release = release,
1008 .get_frequency = get_frequency,
1009 .get_bandwidth = get_bandwidth,
1010};
1011
1012struct dvb_frontend *tda18271c2dd_attach(struct dvb_frontend *fe,
1013 struct i2c_adapter *i2c, u8 adr)
1014{
1015 struct tda_state *state;
1016
1017 state = kzalloc(sizeof(struct tda_state), GFP_KERNEL);
1018 if (!state)
1019 return NULL;
1020
1021 fe->tuner_priv = state;
1022 state->adr = adr;
1023 state->i2c = i2c;
1024 memcpy(&fe->ops.tuner_ops, &tuner_ops, sizeof(struct dvb_tuner_ops));
1025 reset(state);
1026 InitCal(state);
1027
1028 return fe;
1029}
e8783950 1030EXPORT_SYMBOL_GPL(tda18271c2dd_attach);
0fe44629 1031
e8783950
RM
1032MODULE_DESCRIPTION("TDA18271C2 driver");
1033MODULE_AUTHOR("DD");
1034MODULE_LICENSE("GPL");
This page took 0.105183 seconds and 5 git commands to generate.