blob: ad7c72e8f517728539f93adde89f63ddf980d137 [file] [log] [blame]
Ralph Metzlere8783952011-07-03 13:36:17 -03001/*
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>
Ralph Metzlere8783952011-07-03 13:36:17 -030032#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
Oliver Endriss0fe44622011-07-03 13:37:31 -030066enum ERegister {
Ralph Metzlere8783952011-07-03 13:36:17 -030067 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,
Oliver Endriss0fe44622011-07-03 13:37:31 -0300116 u8 RFBand, u32 RF_in,
117 u32 *pRF_Out, bool *pbcal);
Ralph Metzlere8783952011-07-03 13:36:17 -0300118
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,
Oliver Endriss0fe44622011-07-03 13:37:31 -0300122 .buf = data, .len = len} };
Ralph Metzlere8783952011-07-03 13:36:17 -0300123 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) {
Mauro Carvalho Chehabf3d40bd2011-07-04 14:00:25 -0300132 printk(KERN_ERR "tda18271c2dd: i2c write error at addr %i\n", adr);
Ralph Metzlere8783952011-07-03 13:36:17 -0300133 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
Oliver Endriss0fe44622011-07-03 13:37:31 -0300148static int WriteReg(struct tda_state *state, u8 SubAddr, u8 Reg)
Ralph Metzlere8783952011-07-03 13:36:17 -0300149{
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
Oliver Endriss0fe44622011-07-03 13:37:31 -0300165static int UpdateRegs(struct tda_state *state, u8 RegFrom, u8 RegTo)
Ralph Metzlere8783952011-07-03 13:36:17 -0300166{
167 return WriteRegs(state, RegFrom,
168 &state->m_Regs[RegFrom], RegTo-RegFrom+1);
169}
170static int UpdateReg(struct tda_state *state, u8 Reg)
171{
Oliver Endriss0fe44622011-07-03 13:37:31 -0300172 return WriteReg(state, Reg, state->m_Regs[Reg]);
Ralph Metzlere8783952011-07-03 13:36:17 -0300173}
174
175#include "tda18271c2dd_maps.h"
176
Ralph Metzlere8783952011-07-03 13:36:17 -0300177static 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;
Oliver Endriss0fe44622011-07-03 13:37:31 -0300184 u32 ulStandbyMode = 0x06; /* Send in stdb, but leave osc on */
Ralph Metzlere8783952011-07-03 13:36:17 -0300185 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;
Oliver Endriss0fe44622011-07-03 13:37:31 -0300197 if (ulXTOut != 0)
198 state->m_EP4 |= 0x40;
Ralph Metzlere8783952011-07-03 13:36:17 -0300199
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
Oliver Endriss0fe44622011-07-03 13:37:31 -0300213 while ((Map[i].m_Frequency != 0) && (Frequency > Map[i].m_Frequency))
Ralph Metzlere8783952011-07-03 13:36:17 -0300214 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) &&
Oliver Endriss0fe44622011-07-03 13:37:31 -0300227 (Frequency > Map[i].m_Frequency))
Ralph Metzlere8783952011-07-03 13:36:17 -0300228 i += 1;
229 if (Map[i].m_Frequency == 0)
230 return false;
231 *pParam = Map[i].m_Param;
232 return true;
233}
234
Oliver Endriss0fe44622011-07-03 13:37:31 -0300235static bool SearchMap3(struct SMap2 Map[], u32 Frequency,
Ralph Metzlere8783952011-07-03 13:36:17 -0300236 u8 *pParam1, u8 *pParam2)
237{
238 int i = 0;
239
240 while ((Map[i].m_Frequency != 0) &&
Oliver Endriss0fe44622011-07-03 13:37:31 -0300241 (Frequency > Map[i].m_Frequency))
Ralph Metzlere8783952011-07-03 13:36:17 -0300242 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;
Mauro Carvalho Chehab469ffe02011-07-03 18:12:26 -0300270 status = UpdateReg(state, TM);
271 if (status < 0)
272 break;
273 status = Read(state, Regs);
274 if (status < 0)
275 break;
Oliver Endriss0fe44622011-07-03 13:37:31 -0300276 if (((Regs[TM] & 0x0F) == 0 && (Regs[TM] & 0x20) == 0x20) ||
277 ((Regs[TM] & 0x0F) == 8 && (Regs[TM] & 0x20) == 0x00)) {
Ralph Metzlere8783952011-07-03 13:36:17 -0300278 state->m_Regs[TM] ^= 0x20;
Mauro Carvalho Chehab469ffe02011-07-03 18:12:26 -0300279 status = UpdateReg(state, TM);
280 if (status < 0)
281 break;
Ralph Metzlere8783952011-07-03 13:36:17 -0300282 msleep(10);
Mauro Carvalho Chehab469ffe02011-07-03 18:12:26 -0300283 status = Read(state, Regs);
284 if (status < 0)
285 break;
Ralph Metzlere8783952011-07-03 13:36:17 -0300286 }
Oliver Endriss0fe44622011-07-03 13:37:31 -0300287 *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 */
Mauro Carvalho Chehab469ffe02011-07-03 18:12:26 -0300291 status = UpdateReg(state, TM);
292 if (status < 0)
293 break;
Oliver Endriss0fe44622011-07-03 13:37:31 -0300294 state->m_Regs[EP4] &= ~0x03; /* CAL_mode = 0 ????????? */
Mauro Carvalho Chehab469ffe02011-07-03 18:12:26 -0300295 status = UpdateReg(state, EP4);
296 if (status < 0)
297 break;
Oliver Endriss0fe44622011-07-03 13:37:31 -0300298 } while (0);
Ralph Metzlere8783952011-07-03 13:36:17 -0300299
300 return status;
301}
302
303static int StandBy(struct tda_state *state)
304{
305 int status = 0;
306 do {
Oliver Endriss0fe44622011-07-03 13:37:31 -0300307 state->m_Regs[EB12] &= ~0x20; /* PD_AGC1_Det = 0 */
Mauro Carvalho Chehab469ffe02011-07-03 18:12:26 -0300308 status = UpdateReg(state, EB12);
309 if (status < 0)
310 break;
Oliver Endriss0fe44622011-07-03 13:37:31 -0300311 state->m_Regs[EB18] &= ~0x83; /* AGC1_loop_off = 0, AGC1_Gain = 6 dB */
Mauro Carvalho Chehab469ffe02011-07-03 18:12:26 -0300312 status = UpdateReg(state, EB18);
313 if (status < 0)
314 break;
Oliver Endriss0fe44622011-07-03 13:37:31 -0300315 state->m_Regs[EB21] |= 0x03; /* AGC2_Gain = -6 dB */
Ralph Metzlere8783952011-07-03 13:36:17 -0300316 state->m_Regs[EP3] = state->m_EP3_Standby;
Mauro Carvalho Chehab469ffe02011-07-03 18:12:26 -0300317 status = UpdateReg(state, EP3);
318 if (status < 0)
319 break;
Oliver Endriss0fe44622011-07-03 13:37:31 -0300320 state->m_Regs[EB23] &= ~0x06; /* ForceLP_Fc2_En = 0, LP_Fc[2] = 0 */
Mauro Carvalho Chehab469ffe02011-07-03 18:12:26 -0300321 status = UpdateRegs(state, EB21, EB23);
322 if (status < 0)
323 break;
Oliver Endriss0fe44622011-07-03 13:37:31 -0300324 } while (0);
Ralph Metzlere8783952011-07-03 13:36:17 -0300325 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
Oliver Endriss0fe44622011-07-03 13:37:31 -0300336 if (!SearchMap3(m_Main_PLL_Map, freq, &PostDiv, &Div))
Ralph Metzlere8783952011-07-03 13:36:17 -0300337 return -EINVAL;
Ralph Metzlere8783952011-07-03 13:36:17 -0300338
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);
Oliver Endriss0fe44622011-07-03 13:37:31 -0300347 state->m_Regs[MD3] = (MainDiv & 0xFF);
Ralph Metzlere8783952011-07-03 13:36:17 -0300348
349 return UpdateRegs(state, MPD, MD3);
350}
351
352static int CalcCalPLL(struct tda_state *state, u32 freq)
353{
Ralph Metzlere8783952011-07-03 13:36:17 -0300354 u8 PostDiv;
355 u8 Div;
356 u64 OscFreq;
357 u32 CalDiv;
358
Oliver Endriss0fe44622011-07-03 13:37:31 -0300359 if (!SearchMap3(m_Cal_PLL_Map, freq, &PostDiv, &Div))
Ralph Metzlere8783952011-07-03 13:36:17 -0300360 return -EINVAL;
Ralph Metzlere8783952011-07-03 13:36:17 -0300361
362 OscFreq = (u64)freq * (u64)Div;
Oliver Endriss0fe44622011-07-03 13:37:31 -0300363 /* CalDiv = u32( OscFreq * 16384 / 16000000 ); */
364 OscFreq *= (u64)16384;
Ralph Metzlere8783952011-07-03 13:36:17 -0300365 do_div(OscFreq, (u64)16000000);
Oliver Endriss0fe44622011-07-03 13:37:31 -0300366 CalDiv = OscFreq;
Ralph Metzlere8783952011-07-03 13:36:17 -0300367
368 state->m_Regs[CPD] = PostDiv;
369 state->m_Regs[CD1] = ((CalDiv >> 16) & 0xFF);
370 state->m_Regs[CD2] = ((CalDiv >> 8) & 0xFF);
Oliver Endriss0fe44622011-07-03 13:37:31 -0300371 state->m_Regs[CD3] = (CalDiv & 0xFF);
Ralph Metzlere8783952011-07-03 13:36:17 -0300372
Oliver Endriss0fe44622011-07-03 13:37:31 -0300373 return UpdateRegs(state, CPD, CD3);
Ralph Metzlere8783952011-07-03 13:36:17 -0300374}
375
376static int CalibrateRF(struct tda_state *state,
Oliver Endriss0fe44622011-07-03 13:37:31 -0300377 u8 RFBand, u32 freq, s32 *pCprog)
Ralph Metzlere8783952011-07-03 13:36:17 -0300378{
Ralph Metzlere8783952011-07-03 13:36:17 -0300379 int status = 0;
380 u8 Regs[NUM_REGS];
381 do {
Oliver Endriss0fe44622011-07-03 13:37:31 -0300382 u8 BP_Filter = 0;
383 u8 GainTaper = 0;
384 u8 RFC_K = 0;
385 u8 RFC_M = 0;
Ralph Metzlere8783952011-07-03 13:36:17 -0300386
Oliver Endriss0fe44622011-07-03 13:37:31 -0300387 state->m_Regs[EP4] &= ~0x03; /* CAL_mode = 0 */
Mauro Carvalho Chehab469ffe02011-07-03 18:12:26 -0300388 status = UpdateReg(state, EP4);
389 if (status < 0)
390 break;
Oliver Endriss0fe44622011-07-03 13:37:31 -0300391 state->m_Regs[EB18] |= 0x03; /* AGC1_Gain = 3 */
Mauro Carvalho Chehab469ffe02011-07-03 18:12:26 -0300392 status = UpdateReg(state, EB18);
393 if (status < 0)
394 break;
Ralph Metzlere8783952011-07-03 13:36:17 -0300395
Oliver Endriss0fe44622011-07-03 13:37:31 -0300396 /* 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 */
Ralph Metzlere8783952011-07-03 13:36:17 -0300400
Oliver Endriss0fe44622011-07-03 13:37:31 -0300401 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)))
Ralph Metzlere8783952011-07-03 13:36:17 -0300404 return -EINVAL;
Ralph Metzlere8783952011-07-03 13:36:17 -0300405
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
Mauro Carvalho Chehab469ffe02011-07-03 18:12:26 -0300411 status = UpdateRegs(state, EP1, EP3);
412 if (status < 0)
413 break;
414 status = UpdateReg(state, EB13);
415 if (status < 0)
416 break;
Ralph Metzlere8783952011-07-03 13:36:17 -0300417
Oliver Endriss0fe44622011-07-03 13:37:31 -0300418 state->m_Regs[EB4] |= 0x20; /* LO_ForceSrce = 1 */
Mauro Carvalho Chehab469ffe02011-07-03 18:12:26 -0300419 status = UpdateReg(state, EB4);
420 if (status < 0)
421 break;
Ralph Metzlere8783952011-07-03 13:36:17 -0300422
Oliver Endriss0fe44622011-07-03 13:37:31 -0300423 state->m_Regs[EB7] |= 0x20; /* CAL_ForceSrce = 1 */
Mauro Carvalho Chehab469ffe02011-07-03 18:12:26 -0300424 status = UpdateReg(state, EB7);
425 if (status < 0)
426 break;
Ralph Metzlere8783952011-07-03 13:36:17 -0300427
Oliver Endriss0fe44622011-07-03 13:37:31 -0300428 state->m_Regs[EB14] = 0; /* RFC_Cprog = 0 */
Mauro Carvalho Chehab469ffe02011-07-03 18:12:26 -0300429 status = UpdateReg(state, EB14);
430 if (status < 0)
431 break;
Ralph Metzlere8783952011-07-03 13:36:17 -0300432
Oliver Endriss0fe44622011-07-03 13:37:31 -0300433 state->m_Regs[EB20] &= ~0x20; /* ForceLock = 0; */
Mauro Carvalho Chehab469ffe02011-07-03 18:12:26 -0300434 status = UpdateReg(state, EB20);
435 if (status < 0)
436 break;
Ralph Metzlere8783952011-07-03 13:36:17 -0300437
Oliver Endriss0fe44622011-07-03 13:37:31 -0300438 state->m_Regs[EP4] |= 0x03; /* CAL_Mode = 3 */
Mauro Carvalho Chehab469ffe02011-07-03 18:12:26 -0300439 status = UpdateRegs(state, EP4, EP5);
440 if (status < 0)
441 break;
Ralph Metzlere8783952011-07-03 13:36:17 -0300442
Mauro Carvalho Chehab469ffe02011-07-03 18:12:26 -0300443 status = CalcCalPLL(state, freq);
444 if (status < 0)
445 break;
446 status = CalcMainPLL(state, freq + 1000000);
447 if (status < 0)
448 break;
Ralph Metzlere8783952011-07-03 13:36:17 -0300449
450 msleep(5);
Mauro Carvalho Chehab469ffe02011-07-03 18:12:26 -0300451 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;
Ralph Metzlere8783952011-07-03 13:36:17 -0300463
Oliver Endriss0fe44622011-07-03 13:37:31 -0300464 state->m_Regs[EB4] &= ~0x20; /* LO_ForceSrce = 0 */
Mauro Carvalho Chehab469ffe02011-07-03 18:12:26 -0300465 status = UpdateReg(state, EB4);
466 if (status < 0)
467 break;
Ralph Metzlere8783952011-07-03 13:36:17 -0300468
Oliver Endriss0fe44622011-07-03 13:37:31 -0300469 state->m_Regs[EB7] &= ~0x20; /* CAL_ForceSrce = 0 */
Mauro Carvalho Chehab469ffe02011-07-03 18:12:26 -0300470 status = UpdateReg(state, EB7);
471 if (status < 0)
472 break;
Ralph Metzlere8783952011-07-03 13:36:17 -0300473 msleep(10);
474
Oliver Endriss0fe44622011-07-03 13:37:31 -0300475 state->m_Regs[EB20] |= 0x20; /* ForceLock = 1; */
Mauro Carvalho Chehab469ffe02011-07-03 18:12:26 -0300476 status = UpdateReg(state, EB20);
477 if (status < 0)
478 break;
Ralph Metzlere8783952011-07-03 13:36:17 -0300479 msleep(60);
480
Oliver Endriss0fe44622011-07-03 13:37:31 -0300481 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 */
Mauro Carvalho Chehab469ffe02011-07-03 18:12:26 -0300484 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;
Ralph Metzlere8783952011-07-03 13:36:17 -0300493
Mauro Carvalho Chehab469ffe02011-07-03 18:12:26 -0300494 status = ReadExtented(state, Regs);
495 if (status < 0)
496 break;
Ralph Metzlere8783952011-07-03 13:36:17 -0300497
498 *pCprog = Regs[EB14];
Ralph Metzlere8783952011-07-03 13:36:17 -0300499
Oliver Endriss0fe44622011-07-03 13:37:31 -0300500 } while (0);
Ralph Metzlere8783952011-07-03 13:36:17 -0300501 return status;
502}
503
504static int RFTrackingFiltersInit(struct tda_state *state,
505 u8 RFBand)
506{
Ralph Metzlere8783952011-07-03 13:36:17 -0300507 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 {
Mauro Carvalho Chehab469ffe02011-07-03 18:12:26 -0300527 status = PowerScan(state, RFBand, RF1, &RF1, &bcal);
528 if (status < 0)
529 break;
Oliver Endriss0fe44622011-07-03 13:37:31 -0300530 if (bcal) {
Mauro Carvalho Chehab469ffe02011-07-03 18:12:26 -0300531 status = CalibrateRF(state, RFBand, RF1, &Cprog_cal1);
532 if (status < 0)
533 break;
Ralph Metzlere8783952011-07-03 13:36:17 -0300534 }
Oliver Endriss0fe44622011-07-03 13:37:31 -0300535 SearchMap2(m_RF_Cal_Map, RF1, &Cprog_table1);
536 if (!bcal)
Ralph Metzlere8783952011-07-03 13:36:17 -0300537 Cprog_cal1 = Cprog_table1;
Ralph Metzlere8783952011-07-03 13:36:17 -0300538 state->m_RF_B1[RFBand] = Cprog_cal1 - Cprog_table1;
Oliver Endriss0fe44622011-07-03 13:37:31 -0300539 /* state->m_RF_A1[RF_Band] = ???? */
Ralph Metzlere8783952011-07-03 13:36:17 -0300540
Oliver Endriss0fe44622011-07-03 13:37:31 -0300541 if (RF2 == 0)
542 break;
Ralph Metzlere8783952011-07-03 13:36:17 -0300543
Mauro Carvalho Chehab469ffe02011-07-03 18:12:26 -0300544 status = PowerScan(state, RFBand, RF2, &RF2, &bcal);
545 if (status < 0)
546 break;
Oliver Endriss0fe44622011-07-03 13:37:31 -0300547 if (bcal) {
Mauro Carvalho Chehab469ffe02011-07-03 18:12:26 -0300548 status = CalibrateRF(state, RFBand, RF2, &Cprog_cal2);
549 if (status < 0)
550 break;
Ralph Metzlere8783952011-07-03 13:36:17 -0300551 }
Oliver Endriss0fe44622011-07-03 13:37:31 -0300552 SearchMap2(m_RF_Cal_Map, RF2, &Cprog_table2);
553 if (!bcal)
Ralph Metzlere8783952011-07-03 13:36:17 -0300554 Cprog_cal2 = Cprog_table2;
Ralph Metzlere8783952011-07-03 13:36:17 -0300555
556 state->m_RF_A1[RFBand] =
557 (Cprog_cal2 - Cprog_table2 - Cprog_cal1 + Cprog_table1) /
Oliver Endriss0fe44622011-07-03 13:37:31 -0300558 ((s32)(RF2) - (s32)(RF1));
Ralph Metzlere8783952011-07-03 13:36:17 -0300559
Oliver Endriss0fe44622011-07-03 13:37:31 -0300560 if (RF3 == 0)
561 break;
Ralph Metzlere8783952011-07-03 13:36:17 -0300562
Mauro Carvalho Chehab469ffe02011-07-03 18:12:26 -0300563 status = PowerScan(state, RFBand, RF3, &RF3, &bcal);
564 if (status < 0)
565 break;
Oliver Endriss0fe44622011-07-03 13:37:31 -0300566 if (bcal) {
Mauro Carvalho Chehab469ffe02011-07-03 18:12:26 -0300567 status = CalibrateRF(state, RFBand, RF3, &Cprog_cal3);
568 if (status < 0)
569 break;
Ralph Metzlere8783952011-07-03 13:36:17 -0300570 }
Oliver Endriss0fe44622011-07-03 13:37:31 -0300571 SearchMap2(m_RF_Cal_Map, RF3, &Cprog_table3);
572 if (!bcal)
Ralph Metzlere8783952011-07-03 13:36:17 -0300573 Cprog_cal3 = Cprog_table3;
Oliver Endriss0fe44622011-07-03 13:37:31 -0300574 state->m_RF_A2[RFBand] = (Cprog_cal3 - Cprog_table3 - Cprog_cal2 + Cprog_table2) / ((s32)(RF3) - (s32)(RF2));
Ralph Metzlere8783952011-07-03 13:36:17 -0300575 state->m_RF_B2[RFBand] = Cprog_cal2 - Cprog_table2;
576
Oliver Endriss0fe44622011-07-03 13:37:31 -0300577 } while (0);
Ralph Metzlere8783952011-07-03 13:36:17 -0300578
579 state->m_RF1[RFBand] = RF1;
580 state->m_RF2[RFBand] = RF2;
581 state->m_RF3[RFBand] = RF3;
582
583#if 0
Mauro Carvalho Chehabf3d40bd2011-07-04 14:00:25 -0300584 printk(KERN_ERR "tda18271c2dd: %s %d RF1 = %d A1 = %d B1 = %d RF2 = %d A2 = %d B2 = %d RF3 = %d\n", __func__,
Oliver Endriss0fe44622011-07-03 13:37:31 -0300585 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);
Ralph Metzlere8783952011-07-03 13:36:17 -0300587#endif
588
589 return status;
590}
591
592static int PowerScan(struct tda_state *state,
Oliver Endriss0fe44622011-07-03 13:37:31 -0300593 u8 RFBand, u32 RF_in, u32 *pRF_Out, bool *pbcal)
Ralph Metzlere8783952011-07-03 13:36:17 -0300594{
Oliver Endriss0fe44622011-07-03 13:37:31 -0300595 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;
Ralph Metzlere8783952011-07-03 13:36:17 -0300607
Oliver Endriss0fe44622011-07-03 13:37:31 -0300608 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))) {
Ralph Metzlere8783952011-07-03 13:36:17 -0300611
Mauro Carvalho Chehabf3d40bd2011-07-04 14:00:25 -0300612 printk(KERN_ERR "tda18271c2dd: %s Search map failed\n", __func__);
Oliver Endriss0fe44622011-07-03 13:37:31 -0300613 return -EINVAL;
614 }
Ralph Metzlere8783952011-07-03 13:36:17 -0300615
Oliver Endriss0fe44622011-07-03 13:37:31 -0300616 state->m_Regs[EP2] = (RFBand << 5) | Gain_Taper;
617 state->m_Regs[EB14] = (RFC_Cprog);
Mauro Carvalho Chehab469ffe02011-07-03 18:12:26 -0300618 status = UpdateReg(state, EP2);
619 if (status < 0)
620 break;
621 status = UpdateReg(state, EB14);
622 if (status < 0)
623 break;
Ralph Metzlere8783952011-07-03 13:36:17 -0300624
Oliver Endriss0fe44622011-07-03 13:37:31 -0300625 freq_MainPLL = RF_in + 1000000;
Mauro Carvalho Chehab469ffe02011-07-03 18:12:26 -0300626 status = CalcMainPLL(state, freq_MainPLL);
627 if (status < 0)
628 break;
Oliver Endriss0fe44622011-07-03 13:37:31 -0300629 msleep(5);
630 state->m_Regs[EP4] = (state->m_Regs[EP4] & ~0x03) | 1; /* CAL_mode = 1 */
Mauro Carvalho Chehab469ffe02011-07-03 18:12:26 -0300631 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;
Oliver Endriss0fe44622011-07-03 13:37:31 -0300640 CID_Gain = Regs[EB10] & 0x3F;
641 state->m_Regs[ID] = Regs[ID]; /* Chip version, (needed for C1 workarround in CalibrateRF) */
Ralph Metzlere8783952011-07-03 13:36:17 -0300642
Oliver Endriss0fe44622011-07-03 13:37:31 -0300643 *pRF_Out = RF_in;
Ralph Metzlere8783952011-07-03 13:36:17 -0300644
Oliver Endriss0fe44622011-07-03 13:37:31 -0300645 while (CID_Gain < CID_Target) {
646 freq_MainPLL = RF_in + sign * Count + 1000000;
Mauro Carvalho Chehab469ffe02011-07-03 18:12:26 -0300647 status = CalcMainPLL(state, freq_MainPLL);
648 if (status < 0)
649 break;
Oliver Endriss0fe44622011-07-03 13:37:31 -0300650 msleep(wait ? 5 : 1);
651 wait = false;
Mauro Carvalho Chehab469ffe02011-07-03 18:12:26 -0300652 status = UpdateReg(state, EP2); /* Launch power measurement */
653 if (status < 0)
654 break;
655 status = ReadExtented(state, Regs);
656 if (status < 0)
657 break;
Oliver Endriss0fe44622011-07-03 13:37:31 -0300658 CID_Gain = Regs[EB10] & 0x3F;
659 Count += 200000;
Ralph Metzlere8783952011-07-03 13:36:17 -0300660
Oliver Endriss0fe44622011-07-03 13:37:31 -0300661 if (Count < CountLimit * 100000)
662 continue;
663 if (sign < 0)
664 break;
665
666 sign = -sign;
667 Count = 200000;
668 wait = true;
669 }
Mauro Carvalho Chehab469ffe02011-07-03 18:12:26 -0300670 status = status;
671 if (status < 0)
672 break;
Oliver Endriss0fe44622011-07-03 13:37:31 -0300673 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;
Ralph Metzlere8783952011-07-03 13:36:17 -0300681}
682
683static int PowerScanInit(struct tda_state *state)
684{
Ralph Metzlere8783952011-07-03 13:36:17 -0300685 int status = 0;
Oliver Endriss0fe44622011-07-03 13:37:31 -0300686 do {
Ralph Metzlere8783952011-07-03 13:36:17 -0300687 state->m_Regs[EP3] = (state->m_Regs[EP3] & ~0x1F) | 0x12;
Oliver Endriss0fe44622011-07-03 13:37:31 -0300688 state->m_Regs[EP4] = (state->m_Regs[EP4] & ~0x1F); /* If level = 0, Cal mode = 0 */
Mauro Carvalho Chehab469ffe02011-07-03 18:12:26 -0300689 status = UpdateRegs(state, EP3, EP4);
690 if (status < 0)
691 break;
Oliver Endriss0fe44622011-07-03 13:37:31 -0300692 state->m_Regs[EB18] = (state->m_Regs[EB18] & ~0x03); /* AGC 1 Gain = 0 */
Mauro Carvalho Chehab469ffe02011-07-03 18:12:26 -0300693 status = UpdateReg(state, EB18);
694 if (status < 0)
695 break;
Oliver Endriss0fe44622011-07-03 13:37:31 -0300696 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 */
Mauro Carvalho Chehab469ffe02011-07-03 18:12:26 -0300698 status = UpdateRegs(state, EB21, EB23);
699 if (status < 0)
700 break;
Oliver Endriss0fe44622011-07-03 13:37:31 -0300701 } while (0);
Ralph Metzlere8783952011-07-03 13:36:17 -0300702 return status;
703}
704
705static int CalcRFFilterCurve(struct tda_state *state)
706{
Ralph Metzlere8783952011-07-03 13:36:17 -0300707 int status = 0;
Oliver Endriss0fe44622011-07-03 13:37:31 -0300708 do {
709 msleep(200); /* Temperature stabilisation */
Mauro Carvalho Chehab469ffe02011-07-03 18:12:26 -0300710 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;
Oliver Endriss0fe44622011-07-03 13:37:31 -0300737 } while (0);
Ralph Metzlere8783952011-07-03 13:36:17 -0300738
739 return status;
740}
741
742static int FixedContentsI2CUpdate(struct tda_state *state)
743{
744 static u8 InitRegs[] = {
Oliver Endriss0fe44622011-07-03 13:37:31 -0300745 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,
Ralph Metzlere8783952011-07-03 13:36:17 -0300755 };
756 int status = 0;
Oliver Endriss0fe44622011-07-03 13:37:31 -0300757 memcpy(&state->m_Regs[TM], InitRegs, EB23 - TM + 1);
Ralph Metzlere8783952011-07-03 13:36:17 -0300758 do {
Mauro Carvalho Chehab469ffe02011-07-03 18:12:26 -0300759 status = UpdateRegs(state, TM, EB23);
760 if (status < 0)
761 break;
Ralph Metzlere8783952011-07-03 13:36:17 -0300762
Oliver Endriss0fe44622011-07-03 13:37:31 -0300763 /* AGC1 gain setup */
Ralph Metzlere8783952011-07-03 13:36:17 -0300764 state->m_Regs[EB17] = 0x00;
Mauro Carvalho Chehab469ffe02011-07-03 18:12:26 -0300765 status = UpdateReg(state, EB17);
766 if (status < 0)
767 break;
Ralph Metzlere8783952011-07-03 13:36:17 -0300768 state->m_Regs[EB17] = 0x03;
Mauro Carvalho Chehab469ffe02011-07-03 18:12:26 -0300769 status = UpdateReg(state, EB17);
770 if (status < 0)
771 break;
Ralph Metzlere8783952011-07-03 13:36:17 -0300772 state->m_Regs[EB17] = 0x43;
Mauro Carvalho Chehab469ffe02011-07-03 18:12:26 -0300773 status = UpdateReg(state, EB17);
774 if (status < 0)
775 break;
Ralph Metzlere8783952011-07-03 13:36:17 -0300776 state->m_Regs[EB17] = 0x4C;
Mauro Carvalho Chehab469ffe02011-07-03 18:12:26 -0300777 status = UpdateReg(state, EB17);
778 if (status < 0)
779 break;
Ralph Metzlere8783952011-07-03 13:36:17 -0300780
Oliver Endriss0fe44622011-07-03 13:37:31 -0300781 /* IRC Cal Low band */
Ralph Metzlere8783952011-07-03 13:36:17 -0300782 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;
Mauro Carvalho Chehab469ffe02011-07-03 18:12:26 -0300793 status = UpdateRegs(state, EP2, MD3); /* diff between sw and datasheet (ep3-md3) */
794 if (status < 0)
795 break;
Ralph Metzlere8783952011-07-03 13:36:17 -0300796
Oliver Endriss0fe44622011-07-03 13:37:31 -0300797#if 0
798 state->m_Regs[EB4] = 0x61; /* missing in sw */
Mauro Carvalho Chehab469ffe02011-07-03 18:12:26 -0300799 status = UpdateReg(state, EB4);
800 if (status < 0)
801 break;
Oliver Endriss0fe44622011-07-03 13:37:31 -0300802 msleep(1);
803 state->m_Regs[EB4] = 0x41;
Mauro Carvalho Chehab469ffe02011-07-03 18:12:26 -0300804 status = UpdateReg(state, EB4);
805 if (status < 0)
806 break;
Oliver Endriss0fe44622011-07-03 13:37:31 -0300807#endif
Ralph Metzlere8783952011-07-03 13:36:17 -0300808
809 msleep(5);
Mauro Carvalho Chehab469ffe02011-07-03 18:12:26 -0300810 status = UpdateReg(state, EP1);
811 if (status < 0)
812 break;
Ralph Metzlere8783952011-07-03 13:36:17 -0300813 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;
Mauro Carvalho Chehab469ffe02011-07-03 18:12:26 -0300819 status = UpdateRegs(state, EP3, CD3);
820 if (status < 0)
821 break;
Ralph Metzlere8783952011-07-03 13:36:17 -0300822 msleep(5);
Mauro Carvalho Chehab469ffe02011-07-03 18:12:26 -0300823 status = UpdateReg(state, EP2);
824 if (status < 0)
825 break;
Ralph Metzlere8783952011-07-03 13:36:17 -0300826 msleep(30);
827
Oliver Endriss0fe44622011-07-03 13:37:31 -0300828 /* IRC Cal mid band */
Ralph Metzlere8783952011-07-03 13:36:17 -0300829 state->m_Regs[EP5] = 0x82;
830 state->m_Regs[CPD] = 0xA8;
831 state->m_Regs[CD2] = 0x00;
Oliver Endriss0fe44622011-07-03 13:37:31 -0300832 state->m_Regs[MPD] = 0xA1; /* Datasheet = 0xA9 */
Ralph Metzlere8783952011-07-03 13:36:17 -0300833 state->m_Regs[MD1] = 0x73;
834 state->m_Regs[MD2] = 0x1A;
Mauro Carvalho Chehab469ffe02011-07-03 18:12:26 -0300835 status = UpdateRegs(state, EP3, MD3);
836 if (status < 0)
837 break;
Ralph Metzlere8783952011-07-03 13:36:17 -0300838
839 msleep(5);
Mauro Carvalho Chehab469ffe02011-07-03 18:12:26 -0300840 status = UpdateReg(state, EP1);
841 if (status < 0)
842 break;
Ralph Metzlere8783952011-07-03 13:36:17 -0300843 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;
Mauro Carvalho Chehab469ffe02011-07-03 18:12:26 -0300849 status = UpdateRegs(state, EP3, CD3);
850 if (status < 0)
851 break;
Ralph Metzlere8783952011-07-03 13:36:17 -0300852 msleep(5);
Mauro Carvalho Chehab469ffe02011-07-03 18:12:26 -0300853 status = UpdateReg(state, EP2);
854 if (status < 0)
855 break;
Ralph Metzlere8783952011-07-03 13:36:17 -0300856 msleep(30);
857
Oliver Endriss0fe44622011-07-03 13:37:31 -0300858 /* IRC Cal high band */
Ralph Metzlere8783952011-07-03 13:36:17 -0300859 state->m_Regs[EP5] = 0x83;
860 state->m_Regs[CPD] = 0x98;
861 state->m_Regs[CD1] = 0x65;
862 state->m_Regs[CD2] = 0x00;
Oliver Endriss0fe44622011-07-03 13:37:31 -0300863 state->m_Regs[MPD] = 0x91; /* Datasheet = 0x91 */
Ralph Metzlere8783952011-07-03 13:36:17 -0300864 state->m_Regs[MD1] = 0x71;
865 state->m_Regs[MD2] = 0xCD;
Mauro Carvalho Chehab469ffe02011-07-03 18:12:26 -0300866 status = UpdateRegs(state, EP3, MD3);
867 if (status < 0)
868 break;
Ralph Metzlere8783952011-07-03 13:36:17 -0300869 msleep(5);
Mauro Carvalho Chehab469ffe02011-07-03 18:12:26 -0300870 status = UpdateReg(state, EP1);
871 if (status < 0)
872 break;
Ralph Metzlere8783952011-07-03 13:36:17 -0300873 msleep(5);
874 state->m_Regs[EP5] = 0x87;
875 state->m_Regs[CD1] = 0x65;
876 state->m_Regs[CD2] = 0x50;
Mauro Carvalho Chehab469ffe02011-07-03 18:12:26 -0300877 status = UpdateRegs(state, EP3, CD3);
878 if (status < 0)
879 break;
Ralph Metzlere8783952011-07-03 13:36:17 -0300880 msleep(5);
Mauro Carvalho Chehab469ffe02011-07-03 18:12:26 -0300881 status = UpdateReg(state, EP2);
882 if (status < 0)
883 break;
Ralph Metzlere8783952011-07-03 13:36:17 -0300884 msleep(30);
885
Oliver Endriss0fe44622011-07-03 13:37:31 -0300886 /* Back to normal */
Ralph Metzlere8783952011-07-03 13:36:17 -0300887 state->m_Regs[EP4] = 0x64;
Mauro Carvalho Chehab469ffe02011-07-03 18:12:26 -0300888 status = UpdateReg(state, EP4);
889 if (status < 0)
890 break;
891 status = UpdateReg(state, EP1);
892 if (status < 0)
893 break;
Ralph Metzlere8783952011-07-03 13:36:17 -0300894
Oliver Endriss0fe44622011-07-03 13:37:31 -0300895 } while (0);
Ralph Metzlere8783952011-07-03 13:36:17 -0300896 return status;
897}
898
899static int InitCal(struct tda_state *state)
900{
901 int status = 0;
902
Oliver Endriss0fe44622011-07-03 13:37:31 -0300903 do {
Mauro Carvalho Chehab469ffe02011-07-03 18:12:26 -0300904 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;
Oliver Endriss0fe44622011-07-03 13:37:31 -0300913 /* m_bInitDone = true; */
914 } while (0);
Ralph Metzlere8783952011-07-03 13:36:17 -0300915 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
Oliver Endriss0fe44622011-07-03 13:37:31 -0300926 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))
Ralph Metzlere8783952011-07-03 13:36:17 -0300929
Oliver Endriss0fe44622011-07-03 13:37:31 -0300930 return -EINVAL;
931
932 do {
Ralph Metzlere8783952011-07-03 13:36:17 -0300933 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
Oliver Endriss0fe44622011-07-03 13:37:31 -0300944 state->m_Regs[EP3] &= ~0xE0; /* Power up */
Mauro Carvalho Chehab469ffe02011-07-03 18:12:26 -0300945 status = UpdateReg(state, EP3);
946 if (status < 0)
947 break;
Ralph Metzlere8783952011-07-03 13:36:17 -0300948
Mauro Carvalho Chehab469ffe02011-07-03 18:12:26 -0300949 status = ThermometerRead(state, &TMValue_Current);
950 if (status < 0)
951 break;
Ralph Metzlere8783952011-07-03 13:36:17 -0300952
Oliver Endriss0fe44622011-07-03 13:37:31 -0300953 if (RF3 == 0 || Frequency < RF2)
Ralph Metzlere8783952011-07-03 13:36:17 -0300954 Capprox = RF_A1 * ((s32)(Frequency) - (s32)(RF1)) + RF_B1 + Cprog_table;
Ralph Metzlere8783952011-07-03 13:36:17 -0300955 else
Ralph Metzlere8783952011-07-03 13:36:17 -0300956 Capprox = RF_A2 * ((s32)(Frequency) - (s32)(RF2)) + RF_B2 + Cprog_table;
Ralph Metzlere8783952011-07-03 13:36:17 -0300957
958 TComp = (int)(dCoverdT) * ((int)(TMValue_Current) - (int)(state->m_TMValue_RFCal))/1000;
959
960 Capprox += TComp;
961
Oliver Endriss0fe44622011-07-03 13:37:31 -0300962 if (Capprox < 0)
963 Capprox = 0;
964 else if (Capprox > 255)
965 Capprox = 255;
Ralph Metzlere8783952011-07-03 13:36:17 -0300966
967
Oliver Endriss0fe44622011-07-03 13:37:31 -0300968 /* 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;
Ralph Metzlere8783952011-07-03 13:36:17 -0300971
Mauro Carvalho Chehab469ffe02011-07-03 18:12:26 -0300972 status = UpdateReg(state, EB14);
973 if (status < 0)
974 break;
Ralph Metzlere8783952011-07-03 13:36:17 -0300975
Oliver Endriss0fe44622011-07-03 13:37:31 -0300976 } while (0);
Ralph Metzlere8783952011-07-03 13:36:17 -0300977 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;
Mauro Carvalho Chehabea90f012011-07-03 18:06:07 -0300990 u8 IR_Meas = 0;
Ralph Metzlere8783952011-07-03 13:36:17 -0300991
Oliver Endriss0fe44622011-07-03 13:37:31 -0300992 state->IF = IntermediateFrequency;
Mauro Carvalho Chehabf3d40bd2011-07-04 14:00:25 -0300993 /* printk("tda18271c2dd: %s Freq = %d Standard = %d IF = %d\n", __func__, Frequency, Standard, IntermediateFrequency); */
Oliver Endriss0fe44622011-07-03 13:37:31 -0300994 /* get values from tables */
Ralph Metzlere8783952011-07-03 13:36:17 -0300995
Oliver Endriss0fe44622011-07-03 13:37:31 -0300996 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
Mauro Carvalho Chehabf3d40bd2011-07-04 14:00:25 -03001001 printk(KERN_ERR "tda18271c2dd: %s SearchMap failed\n", __func__);
Ralph Metzlere8783952011-07-03 13:36:17 -03001002 return -EINVAL;
1003 }
1004
Oliver Endriss0fe44622011-07-03 13:37:31 -03001005 do {
Ralph Metzlere8783952011-07-03 13:36:17 -03001006 state->m_Regs[EP3] = (state->m_Regs[EP3] & ~0x1F) | m_StandardTable[Standard].m_EP3_4_0;
Oliver Endriss0fe44622011-07-03 13:37:31 -03001007 state->m_Regs[EP3] &= ~0x04; /* switch RFAGC to high speed mode */
Ralph Metzlere8783952011-07-03 13:36:17 -03001008
Oliver Endriss0fe44622011-07-03 13:37:31 -03001009 /* 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;
Ralph Metzlere8783952011-07-03 13:36:17 -03001020
Oliver Endriss0fe44622011-07-03 13:37:31 -03001021 if ((Standard == HF_FM_Radio) && state->m_bFMInput)
1022 state->m_Regs[EP4] |= 80;
Ralph Metzlere8783952011-07-03 13:36:17 -03001023
1024 state->m_Regs[MPD] &= ~0x80;
Oliver Endriss0fe44622011-07-03 13:37:31 -03001025 if (Standard > HF_AnalogMax)
1026 state->m_Regs[MPD] |= 0x80; /* Add IF_notch for digital */
Ralph Metzlere8783952011-07-03 13:36:17 -03001027
1028 state->m_Regs[EB22] = m_StandardTable[Standard].m_EB22;
1029
Oliver Endriss0fe44622011-07-03 13:37:31 -03001030 /* 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 */
Ralph Metzlere8783952011-07-03 13:36:17 -03001035
Mauro Carvalho Chehab469ffe02011-07-03 18:12:26 -03001036 status = UpdateRegs(state, EB22, EB23);
1037 if (status < 0)
1038 break;
Ralph Metzlere8783952011-07-03 13:36:17 -03001039
Oliver Endriss0fe44622011-07-03 13:37:31 -03001040 state->m_Regs[EP1] = (state->m_Regs[EP1] & ~0x07) | 0x40 | BP_Filter; /* Dis_Power_level = 1, Filter */
Ralph Metzlere8783952011-07-03 13:36:17 -03001041 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) |
Oliver Endriss0fe44622011-07-03 13:37:31 -03001045 (state->m_bMaster ? 0x04 : 0x00); /* CALVCO_FortLOn = MS */
1046 /* AGC1_always_master = 0 */
1047 /* AGC_firstn = 0 */
Mauro Carvalho Chehab469ffe02011-07-03 18:12:26 -03001048 status = UpdateReg(state, EB1);
1049 if (status < 0)
1050 break;
Ralph Metzlere8783952011-07-03 13:36:17 -03001051
Oliver Endriss0fe44622011-07-03 13:37:31 -03001052 if (state->m_bMaster) {
Mauro Carvalho Chehab469ffe02011-07-03 18:12:26 -03001053 status = CalcMainPLL(state, Frequency + IntermediateFrequency);
1054 if (status < 0)
1055 break;
1056 status = UpdateRegs(state, TM, EP5);
1057 if (status < 0)
1058 break;
Oliver Endriss0fe44622011-07-03 13:37:31 -03001059 state->m_Regs[EB4] |= 0x20; /* LO_forceSrce = 1 */
Mauro Carvalho Chehab469ffe02011-07-03 18:12:26 -03001060 status = UpdateReg(state, EB4);
1061 if (status < 0)
1062 break;
Ralph Metzlere8783952011-07-03 13:36:17 -03001063 msleep(1);
Oliver Endriss0fe44622011-07-03 13:37:31 -03001064 state->m_Regs[EB4] &= ~0x20; /* LO_forceSrce = 0 */
Mauro Carvalho Chehab469ffe02011-07-03 18:12:26 -03001065 status = UpdateReg(state, EB4);
1066 if (status < 0)
1067 break;
Oliver Endriss0fe44622011-07-03 13:37:31 -03001068 } else {
Mauro Carvalho Chehabea90f012011-07-03 18:06:07 -03001069 u8 PostDiv = 0;
Ralph Metzlere8783952011-07-03 13:36:17 -03001070 u8 Div;
Mauro Carvalho Chehab469ffe02011-07-03 18:12:26 -03001071 status = CalcCalPLL(state, Frequency + IntermediateFrequency);
1072 if (status < 0)
1073 break;
Ralph Metzlere8783952011-07-03 13:36:17 -03001074
Oliver Endriss0fe44622011-07-03 13:37:31 -03001075 SearchMap3(m_Cal_PLL_Map, Frequency + IntermediateFrequency, &PostDiv, &Div);
Ralph Metzlere8783952011-07-03 13:36:17 -03001076 state->m_Regs[MPD] = (state->m_Regs[MPD] & ~0x7F) | (PostDiv & 0x77);
Mauro Carvalho Chehab469ffe02011-07-03 18:12:26 -03001077 status = UpdateReg(state, MPD);
1078 if (status < 0)
1079 break;
1080 status = UpdateRegs(state, TM, EP5);
1081 if (status < 0)
1082 break;
Ralph Metzlere8783952011-07-03 13:36:17 -03001083
Oliver Endriss0fe44622011-07-03 13:37:31 -03001084 state->m_Regs[EB7] |= 0x20; /* CAL_forceSrce = 1 */
Mauro Carvalho Chehab469ffe02011-07-03 18:12:26 -03001085 status = UpdateReg(state, EB7);
1086 if (status < 0)
1087 break;
Ralph Metzlere8783952011-07-03 13:36:17 -03001088 msleep(1);
Oliver Endriss0fe44622011-07-03 13:37:31 -03001089 state->m_Regs[EB7] &= ~0x20; /* CAL_forceSrce = 0 */
Mauro Carvalho Chehab469ffe02011-07-03 18:12:26 -03001090 status = UpdateReg(state, EB7);
1091 if (status < 0)
1092 break;
Ralph Metzlere8783952011-07-03 13:36:17 -03001093 }
1094 msleep(20);
Oliver Endriss0fe44622011-07-03 13:37:31 -03001095 if (Standard != HF_FM_Radio)
1096 state->m_Regs[EP3] |= 0x04; /* RFAGC to normal mode */
Mauro Carvalho Chehab469ffe02011-07-03 18:12:26 -03001097 status = UpdateReg(state, EP3);
1098 if (status < 0)
1099 break;
Ralph Metzlere8783952011-07-03 13:36:17 -03001100
Oliver Endriss0fe44622011-07-03 13:37:31 -03001101 } while (0);
Ralph Metzlere8783952011-07-03 13:36:17 -03001102 return status;
1103}
1104
Oliver Endriss0fe44622011-07-03 13:37:31 -03001105static int sleep(struct dvb_frontend *fe)
Ralph Metzlere8783952011-07-03 13:36:17 -03001106{
1107 struct tda_state *state = fe->tuner_priv;
1108
1109 StandBy(state);
1110 return 0;
1111}
1112
Oliver Endriss0fe44622011-07-03 13:37:31 -03001113static int init(struct dvb_frontend *fe)
Ralph Metzlere8783952011-07-03 13:36:17 -03001114{
Ralph Metzlere8783952011-07-03 13:36:17 -03001115 return 0;
1116}
1117
Oliver Endriss0fe44622011-07-03 13:37:31 -03001118static int release(struct dvb_frontend *fe)
Ralph Metzlere8783952011-07-03 13:36:17 -03001119{
1120 kfree(fe->tuner_priv);
1121 fe->tuner_priv = NULL;
1122 return 0;
1123}
1124
Mauro Carvalho Chehabcf845292011-07-28 15:49:43 -03001125
Mauro Carvalho Chehab14d24d12011-12-24 12:24:33 -03001126static int set_params(struct dvb_frontend *fe)
Ralph Metzlere8783952011-07-03 13:36:17 -03001127{
1128 struct tda_state *state = fe->tuner_priv;
1129 int status = 0;
1130 int Standard;
Mauro Carvalho Chehabfd66c452011-12-17 20:36:57 -03001131 u32 bw = fe->dtv_property_cache.bandwidth_hz;
1132 u32 delsys = fe->dtv_property_cache.delivery_system;
Ralph Metzlere8783952011-07-03 13:36:17 -03001133
Mauro Carvalho Chehabfd66c452011-12-17 20:36:57 -03001134 state->m_Frequency = fe->dtv_property_cache.frequency;
Ralph Metzlere8783952011-07-03 13:36:17 -03001135
Mauro Carvalho Chehabfd66c452011-12-17 20:36:57 -03001136 switch (delsys) {
1137 case SYS_DVBT:
1138 case SYS_DVBT2:
1139 switch (bw) {
1140 case 6000000:
Ralph Metzlere8783952011-07-03 13:36:17 -03001141 Standard = HF_DVBT_6MHZ;
1142 break;
Mauro Carvalho Chehabfd66c452011-12-17 20:36:57 -03001143 case 7000000:
Ralph Metzlere8783952011-07-03 13:36:17 -03001144 Standard = HF_DVBT_7MHZ;
1145 break;
Mauro Carvalho Chehabfd66c452011-12-17 20:36:57 -03001146 case 8000000:
Ralph Metzlere8783952011-07-03 13:36:17 -03001147 Standard = HF_DVBT_8MHZ;
1148 break;
Mauro Carvalho Chehabfd66c452011-12-17 20:36:57 -03001149 default:
1150 return -EINVAL;
Ralph Metzlere8783952011-07-03 13:36:17 -03001151 }
Mauro Carvalho Chehabfd66c452011-12-17 20:36:57 -03001152 case SYS_DVBC_ANNEX_A:
1153 case SYS_DVBC_ANNEX_C:
Mauro Carvalho Chehab2440f7a2011-11-11 20:26:03 -02001154 if (bw <= 6000000)
Mauro Carvalho Chehabcf845292011-07-28 15:49:43 -03001155 Standard = HF_DVBC_6MHZ;
Mauro Carvalho Chehab2440f7a2011-11-11 20:26:03 -02001156 else if (bw <= 7000000)
1157 Standard = HF_DVBC_7MHZ;
Mauro Carvalho Chehabcf845292011-07-28 15:49:43 -03001158 else
1159 Standard = HF_DVBC_8MHZ;
Mauro Carvalho Chehab1ca8dde2011-12-30 15:34:51 -02001160 break;
Mauro Carvalho Chehabfd66c452011-12-17 20:36:57 -03001161 default:
Ralph Metzlere8783952011-07-03 13:36:17 -03001162 return -EINVAL;
Mauro Carvalho Chehabfd66c452011-12-17 20:36:57 -03001163 }
Ralph Metzlere8783952011-07-03 13:36:17 -03001164 do {
Mauro Carvalho Chehabfd66c452011-12-17 20:36:57 -03001165 status = RFTrackingFiltersCorrection(state, state->m_Frequency);
Mauro Carvalho Chehab469ffe02011-07-03 18:12:26 -03001166 if (status < 0)
1167 break;
Mauro Carvalho Chehabfd66c452011-12-17 20:36:57 -03001168 status = ChannelConfiguration(state, state->m_Frequency,
1169 Standard);
Mauro Carvalho Chehab469ffe02011-07-03 18:12:26 -03001170 if (status < 0)
1171 break;
Ralph Metzlere8783952011-07-03 13:36:17 -03001172
Oliver Endriss0fe44622011-07-03 13:37:31 -03001173 msleep(state->m_SettlingTime); /* Allow AGC's to settle down */
1174 } while (0);
Ralph Metzlere8783952011-07-03 13:36:17 -03001175 return status;
1176}
1177
1178#if 0
Oliver Endriss0fe44622011-07-03 13:37:31 -03001179static int GetSignalStrength(s32 *pSignalStrength, u32 RFAgc, u32 IFAgc)
Ralph Metzlere8783952011-07-03 13:36:17 -03001180{
Oliver Endriss0fe44622011-07-03 13:37:31 -03001181 if (IFAgc < 500) {
1182 /* Scale this from 0 to 50000 */
Ralph Metzlere8783952011-07-03 13:36:17 -03001183 *pSignalStrength = IFAgc * 100;
1184 } else {
Oliver Endriss0fe44622011-07-03 13:37:31 -03001185 /* Scale range 500-1500 to 50000-80000 */
Ralph Metzlere8783952011-07-03 13:36:17 -03001186 *pSignalStrength = 50000 + (IFAgc - 500) * 30;
1187 }
1188
1189 return 0;
1190}
1191#endif
1192
Mauro Carvalho Chehab8513e142011-09-03 11:40:02 -03001193static int get_if_frequency(struct dvb_frontend *fe, u32 *frequency)
Ralph Metzlere8783952011-07-03 13:36:17 -03001194{
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{
Oliver Endriss0fe44622011-07-03 13:37:31 -03001203 /* struct tda_state *state = fe->tuner_priv; */
1204 /* *bandwidth = priv->bandwidth; */
Ralph Metzlere8783952011-07-03 13:36:17 -03001205 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,
Mauro Carvalho Chehab8513e142011-09-03 11:40:02 -03001220 .get_if_frequency = get_if_frequency,
Ralph Metzlere8783952011-07-03 13:36:17 -03001221 .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}
Ralph Metzlere8783952011-07-03 13:36:17 -03001242EXPORT_SYMBOL_GPL(tda18271c2dd_attach);
Oliver Endriss0fe44622011-07-03 13:37:31 -03001243
Ralph Metzlere8783952011-07-03 13:36:17 -03001244MODULE_DESCRIPTION("TDA18271C2 driver");
1245MODULE_AUTHOR("DD");
1246MODULE_LICENSE("GPL");