blob: 0f8e9622bc96d21389cf6fb6cd4e716c94b124e4 [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>
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
Oliver Endriss0fe44622011-07-03 13:37:31 -030067enum ERegister {
Ralph Metzlere8783952011-07-03 13:36:17 -030068 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,
Oliver Endriss0fe44622011-07-03 13:37:31 -0300117 u8 RFBand, u32 RF_in,
118 u32 *pRF_Out, bool *pbcal);
Ralph Metzlere8783952011-07-03 13:36:17 -0300119
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,
Oliver Endriss0fe44622011-07-03 13:37:31 -0300123 .buf = data, .len = len} };
Ralph Metzlere8783952011-07-03 13:36:17 -0300124 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) {
Mauro Carvalho Chehabf3d40bd2011-07-04 14:00:25 -0300133 printk(KERN_ERR "tda18271c2dd: i2c write error at addr %i\n", adr);
Ralph Metzlere8783952011-07-03 13:36:17 -0300134 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
Oliver Endriss0fe44622011-07-03 13:37:31 -0300149static int WriteReg(struct tda_state *state, u8 SubAddr, u8 Reg)
Ralph Metzlere8783952011-07-03 13:36:17 -0300150{
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
Oliver Endriss0fe44622011-07-03 13:37:31 -0300166static int UpdateRegs(struct tda_state *state, u8 RegFrom, u8 RegTo)
Ralph Metzlere8783952011-07-03 13:36:17 -0300167{
168 return WriteRegs(state, RegFrom,
169 &state->m_Regs[RegFrom], RegTo-RegFrom+1);
170}
171static int UpdateReg(struct tda_state *state, u8 Reg)
172{
Oliver Endriss0fe44622011-07-03 13:37:31 -0300173 return WriteReg(state, Reg, state->m_Regs[Reg]);
Ralph Metzlere8783952011-07-03 13:36:17 -0300174}
175
176#include "tda18271c2dd_maps.h"
177
Ralph Metzlere8783952011-07-03 13:36:17 -0300178static void reset(struct tda_state *state)
179{
180 u32 ulIFLevelAnalog = 0;
181 u32 ulIFLevelDigital = 2;
182 u32 ulIFLevelDVBC = 7;
183 u32 ulIFLevelDVBT = 6;
184 u32 ulXTOut = 0;
Oliver Endriss0fe44622011-07-03 13:37:31 -0300185 u32 ulStandbyMode = 0x06; /* Send in stdb, but leave osc on */
Ralph Metzlere8783952011-07-03 13:36:17 -0300186 u32 ulSlave = 0;
187 u32 ulFMInput = 0;
188 u32 ulSettlingTime = 100;
189
190 state->m_Frequency = 0;
191 state->m_SettlingTime = 100;
192 state->m_IFLevelAnalog = (ulIFLevelAnalog & 0x07) << 2;
193 state->m_IFLevelDigital = (ulIFLevelDigital & 0x07) << 2;
194 state->m_IFLevelDVBC = (ulIFLevelDVBC & 0x07) << 2;
195 state->m_IFLevelDVBT = (ulIFLevelDVBT & 0x07) << 2;
196
197 state->m_EP4 = 0x20;
Oliver Endriss0fe44622011-07-03 13:37:31 -0300198 if (ulXTOut != 0)
199 state->m_EP4 |= 0x40;
Ralph Metzlere8783952011-07-03 13:36:17 -0300200
201 state->m_EP3_Standby = ((ulStandbyMode & 0x07) << 5) | 0x0F;
202 state->m_bMaster = (ulSlave == 0);
203
204 state->m_SettlingTime = ulSettlingTime;
205
206 state->m_bFMInput = (ulFMInput == 2);
207}
208
209static bool SearchMap1(struct SMap Map[],
210 u32 Frequency, u8 *pParam)
211{
212 int i = 0;
213
Oliver Endriss0fe44622011-07-03 13:37:31 -0300214 while ((Map[i].m_Frequency != 0) && (Frequency > Map[i].m_Frequency))
Ralph Metzlere8783952011-07-03 13:36:17 -0300215 i += 1;
216 if (Map[i].m_Frequency == 0)
217 return false;
218 *pParam = Map[i].m_Param;
219 return true;
220}
221
222static bool SearchMap2(struct SMapI Map[],
223 u32 Frequency, s32 *pParam)
224{
225 int i = 0;
226
227 while ((Map[i].m_Frequency != 0) &&
Oliver Endriss0fe44622011-07-03 13:37:31 -0300228 (Frequency > Map[i].m_Frequency))
Ralph Metzlere8783952011-07-03 13:36:17 -0300229 i += 1;
230 if (Map[i].m_Frequency == 0)
231 return false;
232 *pParam = Map[i].m_Param;
233 return true;
234}
235
Oliver Endriss0fe44622011-07-03 13:37:31 -0300236static bool SearchMap3(struct SMap2 Map[], u32 Frequency,
Ralph Metzlere8783952011-07-03 13:36:17 -0300237 u8 *pParam1, u8 *pParam2)
238{
239 int i = 0;
240
241 while ((Map[i].m_Frequency != 0) &&
Oliver Endriss0fe44622011-07-03 13:37:31 -0300242 (Frequency > Map[i].m_Frequency))
Ralph Metzlere8783952011-07-03 13:36:17 -0300243 i += 1;
244 if (Map[i].m_Frequency == 0)
245 return false;
246 *pParam1 = Map[i].m_Param1;
247 *pParam2 = Map[i].m_Param2;
248 return true;
249}
250
251static bool SearchMap4(struct SRFBandMap Map[],
252 u32 Frequency, u8 *pRFBand)
253{
254 int i = 0;
255
256 while (i < 7 && (Frequency > Map[i].m_RF_max))
257 i += 1;
258 if (i == 7)
259 return false;
260 *pRFBand = i;
261 return true;
262}
263
264static int ThermometerRead(struct tda_state *state, u8 *pTM_Value)
265{
266 int status = 0;
267
268 do {
269 u8 Regs[16];
270 state->m_Regs[TM] |= 0x10;
Mauro Carvalho Chehab469ffe02011-07-03 18:12:26 -0300271 status = UpdateReg(state, TM);
272 if (status < 0)
273 break;
274 status = Read(state, Regs);
275 if (status < 0)
276 break;
Oliver Endriss0fe44622011-07-03 13:37:31 -0300277 if (((Regs[TM] & 0x0F) == 0 && (Regs[TM] & 0x20) == 0x20) ||
278 ((Regs[TM] & 0x0F) == 8 && (Regs[TM] & 0x20) == 0x00)) {
Ralph Metzlere8783952011-07-03 13:36:17 -0300279 state->m_Regs[TM] ^= 0x20;
Mauro Carvalho Chehab469ffe02011-07-03 18:12:26 -0300280 status = UpdateReg(state, TM);
281 if (status < 0)
282 break;
Ralph Metzlere8783952011-07-03 13:36:17 -0300283 msleep(10);
Mauro Carvalho Chehab469ffe02011-07-03 18:12:26 -0300284 status = Read(state, Regs);
285 if (status < 0)
286 break;
Ralph Metzlere8783952011-07-03 13:36:17 -0300287 }
Oliver Endriss0fe44622011-07-03 13:37:31 -0300288 *pTM_Value = (Regs[TM] & 0x20)
289 ? m_Thermometer_Map_2[Regs[TM] & 0x0F]
290 : m_Thermometer_Map_1[Regs[TM] & 0x0F] ;
291 state->m_Regs[TM] &= ~0x10; /* Thermometer off */
Mauro Carvalho Chehab469ffe02011-07-03 18:12:26 -0300292 status = UpdateReg(state, TM);
293 if (status < 0)
294 break;
Oliver Endriss0fe44622011-07-03 13:37:31 -0300295 state->m_Regs[EP4] &= ~0x03; /* CAL_mode = 0 ????????? */
Mauro Carvalho Chehab469ffe02011-07-03 18:12:26 -0300296 status = UpdateReg(state, EP4);
297 if (status < 0)
298 break;
Oliver Endriss0fe44622011-07-03 13:37:31 -0300299 } while (0);
Ralph Metzlere8783952011-07-03 13:36:17 -0300300
301 return status;
302}
303
304static int StandBy(struct tda_state *state)
305{
306 int status = 0;
307 do {
Oliver Endriss0fe44622011-07-03 13:37:31 -0300308 state->m_Regs[EB12] &= ~0x20; /* PD_AGC1_Det = 0 */
Mauro Carvalho Chehab469ffe02011-07-03 18:12:26 -0300309 status = UpdateReg(state, EB12);
310 if (status < 0)
311 break;
Oliver Endriss0fe44622011-07-03 13:37:31 -0300312 state->m_Regs[EB18] &= ~0x83; /* AGC1_loop_off = 0, AGC1_Gain = 6 dB */
Mauro Carvalho Chehab469ffe02011-07-03 18:12:26 -0300313 status = UpdateReg(state, EB18);
314 if (status < 0)
315 break;
Oliver Endriss0fe44622011-07-03 13:37:31 -0300316 state->m_Regs[EB21] |= 0x03; /* AGC2_Gain = -6 dB */
Ralph Metzlere8783952011-07-03 13:36:17 -0300317 state->m_Regs[EP3] = state->m_EP3_Standby;
Mauro Carvalho Chehab469ffe02011-07-03 18:12:26 -0300318 status = UpdateReg(state, EP3);
319 if (status < 0)
320 break;
Oliver Endriss0fe44622011-07-03 13:37:31 -0300321 state->m_Regs[EB23] &= ~0x06; /* ForceLP_Fc2_En = 0, LP_Fc[2] = 0 */
Mauro Carvalho Chehab469ffe02011-07-03 18:12:26 -0300322 status = UpdateRegs(state, EB21, EB23);
323 if (status < 0)
324 break;
Oliver Endriss0fe44622011-07-03 13:37:31 -0300325 } while (0);
Ralph Metzlere8783952011-07-03 13:36:17 -0300326 return status;
327}
328
329static int CalcMainPLL(struct tda_state *state, u32 freq)
330{
331
332 u8 PostDiv;
333 u8 Div;
334 u64 OscFreq;
335 u32 MainDiv;
336
Oliver Endriss0fe44622011-07-03 13:37:31 -0300337 if (!SearchMap3(m_Main_PLL_Map, freq, &PostDiv, &Div))
Ralph Metzlere8783952011-07-03 13:36:17 -0300338 return -EINVAL;
Ralph Metzlere8783952011-07-03 13:36:17 -0300339
340 OscFreq = (u64) freq * (u64) Div;
341 OscFreq *= (u64) 16384;
342 do_div(OscFreq, (u64)16000000);
343 MainDiv = OscFreq;
344
345 state->m_Regs[MPD] = PostDiv & 0x77;
346 state->m_Regs[MD1] = ((MainDiv >> 16) & 0x7F);
347 state->m_Regs[MD2] = ((MainDiv >> 8) & 0xFF);
Oliver Endriss0fe44622011-07-03 13:37:31 -0300348 state->m_Regs[MD3] = (MainDiv & 0xFF);
Ralph Metzlere8783952011-07-03 13:36:17 -0300349
350 return UpdateRegs(state, MPD, MD3);
351}
352
353static int CalcCalPLL(struct tda_state *state, u32 freq)
354{
Ralph Metzlere8783952011-07-03 13:36:17 -0300355 u8 PostDiv;
356 u8 Div;
357 u64 OscFreq;
358 u32 CalDiv;
359
Oliver Endriss0fe44622011-07-03 13:37:31 -0300360 if (!SearchMap3(m_Cal_PLL_Map, freq, &PostDiv, &Div))
Ralph Metzlere8783952011-07-03 13:36:17 -0300361 return -EINVAL;
Ralph Metzlere8783952011-07-03 13:36:17 -0300362
363 OscFreq = (u64)freq * (u64)Div;
Oliver Endriss0fe44622011-07-03 13:37:31 -0300364 /* CalDiv = u32( OscFreq * 16384 / 16000000 ); */
365 OscFreq *= (u64)16384;
Ralph Metzlere8783952011-07-03 13:36:17 -0300366 do_div(OscFreq, (u64)16000000);
Oliver Endriss0fe44622011-07-03 13:37:31 -0300367 CalDiv = OscFreq;
Ralph Metzlere8783952011-07-03 13:36:17 -0300368
369 state->m_Regs[CPD] = PostDiv;
370 state->m_Regs[CD1] = ((CalDiv >> 16) & 0xFF);
371 state->m_Regs[CD2] = ((CalDiv >> 8) & 0xFF);
Oliver Endriss0fe44622011-07-03 13:37:31 -0300372 state->m_Regs[CD3] = (CalDiv & 0xFF);
Ralph Metzlere8783952011-07-03 13:36:17 -0300373
Oliver Endriss0fe44622011-07-03 13:37:31 -0300374 return UpdateRegs(state, CPD, CD3);
Ralph Metzlere8783952011-07-03 13:36:17 -0300375}
376
377static int CalibrateRF(struct tda_state *state,
Oliver Endriss0fe44622011-07-03 13:37:31 -0300378 u8 RFBand, u32 freq, s32 *pCprog)
Ralph Metzlere8783952011-07-03 13:36:17 -0300379{
Ralph Metzlere8783952011-07-03 13:36:17 -0300380 int status = 0;
381 u8 Regs[NUM_REGS];
382 do {
Oliver Endriss0fe44622011-07-03 13:37:31 -0300383 u8 BP_Filter = 0;
384 u8 GainTaper = 0;
385 u8 RFC_K = 0;
386 u8 RFC_M = 0;
Ralph Metzlere8783952011-07-03 13:36:17 -0300387
Oliver Endriss0fe44622011-07-03 13:37:31 -0300388 state->m_Regs[EP4] &= ~0x03; /* CAL_mode = 0 */
Mauro Carvalho Chehab469ffe02011-07-03 18:12:26 -0300389 status = UpdateReg(state, EP4);
390 if (status < 0)
391 break;
Oliver Endriss0fe44622011-07-03 13:37:31 -0300392 state->m_Regs[EB18] |= 0x03; /* AGC1_Gain = 3 */
Mauro Carvalho Chehab469ffe02011-07-03 18:12:26 -0300393 status = UpdateReg(state, EB18);
394 if (status < 0)
395 break;
Ralph Metzlere8783952011-07-03 13:36:17 -0300396
Oliver Endriss0fe44622011-07-03 13:37:31 -0300397 /* Switching off LT (as datasheet says) causes calibration on C1 to fail */
398 /* (Readout of Cprog is allways 255) */
399 if (state->m_Regs[ID] != 0x83) /* C1: ID == 83, C2: ID == 84 */
400 state->m_Regs[EP3] |= 0x40; /* SM_LT = 1 */
Ralph Metzlere8783952011-07-03 13:36:17 -0300401
Oliver Endriss0fe44622011-07-03 13:37:31 -0300402 if (!(SearchMap1(m_BP_Filter_Map, freq, &BP_Filter) &&
403 SearchMap1(m_GainTaper_Map, freq, &GainTaper) &&
404 SearchMap3(m_KM_Map, freq, &RFC_K, &RFC_M)))
Ralph Metzlere8783952011-07-03 13:36:17 -0300405 return -EINVAL;
Ralph Metzlere8783952011-07-03 13:36:17 -0300406
407 state->m_Regs[EP1] = (state->m_Regs[EP1] & ~0x07) | BP_Filter;
408 state->m_Regs[EP2] = (RFBand << 5) | GainTaper;
409
410 state->m_Regs[EB13] = (state->m_Regs[EB13] & ~0x7C) | (RFC_K << 4) | (RFC_M << 2);
411
Mauro Carvalho Chehab469ffe02011-07-03 18:12:26 -0300412 status = UpdateRegs(state, EP1, EP3);
413 if (status < 0)
414 break;
415 status = UpdateReg(state, EB13);
416 if (status < 0)
417 break;
Ralph Metzlere8783952011-07-03 13:36:17 -0300418
Oliver Endriss0fe44622011-07-03 13:37:31 -0300419 state->m_Regs[EB4] |= 0x20; /* LO_ForceSrce = 1 */
Mauro Carvalho Chehab469ffe02011-07-03 18:12:26 -0300420 status = UpdateReg(state, EB4);
421 if (status < 0)
422 break;
Ralph Metzlere8783952011-07-03 13:36:17 -0300423
Oliver Endriss0fe44622011-07-03 13:37:31 -0300424 state->m_Regs[EB7] |= 0x20; /* CAL_ForceSrce = 1 */
Mauro Carvalho Chehab469ffe02011-07-03 18:12:26 -0300425 status = UpdateReg(state, EB7);
426 if (status < 0)
427 break;
Ralph Metzlere8783952011-07-03 13:36:17 -0300428
Oliver Endriss0fe44622011-07-03 13:37:31 -0300429 state->m_Regs[EB14] = 0; /* RFC_Cprog = 0 */
Mauro Carvalho Chehab469ffe02011-07-03 18:12:26 -0300430 status = UpdateReg(state, EB14);
431 if (status < 0)
432 break;
Ralph Metzlere8783952011-07-03 13:36:17 -0300433
Oliver Endriss0fe44622011-07-03 13:37:31 -0300434 state->m_Regs[EB20] &= ~0x20; /* ForceLock = 0; */
Mauro Carvalho Chehab469ffe02011-07-03 18:12:26 -0300435 status = UpdateReg(state, EB20);
436 if (status < 0)
437 break;
Ralph Metzlere8783952011-07-03 13:36:17 -0300438
Oliver Endriss0fe44622011-07-03 13:37:31 -0300439 state->m_Regs[EP4] |= 0x03; /* CAL_Mode = 3 */
Mauro Carvalho Chehab469ffe02011-07-03 18:12:26 -0300440 status = UpdateRegs(state, EP4, EP5);
441 if (status < 0)
442 break;
Ralph Metzlere8783952011-07-03 13:36:17 -0300443
Mauro Carvalho Chehab469ffe02011-07-03 18:12:26 -0300444 status = CalcCalPLL(state, freq);
445 if (status < 0)
446 break;
447 status = CalcMainPLL(state, freq + 1000000);
448 if (status < 0)
449 break;
Ralph Metzlere8783952011-07-03 13:36:17 -0300450
451 msleep(5);
Mauro Carvalho Chehab469ffe02011-07-03 18:12:26 -0300452 status = UpdateReg(state, EP2);
453 if (status < 0)
454 break;
455 status = UpdateReg(state, EP1);
456 if (status < 0)
457 break;
458 status = UpdateReg(state, EP2);
459 if (status < 0)
460 break;
461 status = UpdateReg(state, EP1);
462 if (status < 0)
463 break;
Ralph Metzlere8783952011-07-03 13:36:17 -0300464
Oliver Endriss0fe44622011-07-03 13:37:31 -0300465 state->m_Regs[EB4] &= ~0x20; /* LO_ForceSrce = 0 */
Mauro Carvalho Chehab469ffe02011-07-03 18:12:26 -0300466 status = UpdateReg(state, EB4);
467 if (status < 0)
468 break;
Ralph Metzlere8783952011-07-03 13:36:17 -0300469
Oliver Endriss0fe44622011-07-03 13:37:31 -0300470 state->m_Regs[EB7] &= ~0x20; /* CAL_ForceSrce = 0 */
Mauro Carvalho Chehab469ffe02011-07-03 18:12:26 -0300471 status = UpdateReg(state, EB7);
472 if (status < 0)
473 break;
Ralph Metzlere8783952011-07-03 13:36:17 -0300474 msleep(10);
475
Oliver Endriss0fe44622011-07-03 13:37:31 -0300476 state->m_Regs[EB20] |= 0x20; /* ForceLock = 1; */
Mauro Carvalho Chehab469ffe02011-07-03 18:12:26 -0300477 status = UpdateReg(state, EB20);
478 if (status < 0)
479 break;
Ralph Metzlere8783952011-07-03 13:36:17 -0300480 msleep(60);
481
Oliver Endriss0fe44622011-07-03 13:37:31 -0300482 state->m_Regs[EP4] &= ~0x03; /* CAL_Mode = 0 */
483 state->m_Regs[EP3] &= ~0x40; /* SM_LT = 0 */
484 state->m_Regs[EB18] &= ~0x03; /* AGC1_Gain = 0 */
Mauro Carvalho Chehab469ffe02011-07-03 18:12:26 -0300485 status = UpdateReg(state, EB18);
486 if (status < 0)
487 break;
488 status = UpdateRegs(state, EP3, EP4);
489 if (status < 0)
490 break;
491 status = UpdateReg(state, EP1);
492 if (status < 0)
493 break;
Ralph Metzlere8783952011-07-03 13:36:17 -0300494
Mauro Carvalho Chehab469ffe02011-07-03 18:12:26 -0300495 status = ReadExtented(state, Regs);
496 if (status < 0)
497 break;
Ralph Metzlere8783952011-07-03 13:36:17 -0300498
499 *pCprog = Regs[EB14];
Ralph Metzlere8783952011-07-03 13:36:17 -0300500
Oliver Endriss0fe44622011-07-03 13:37:31 -0300501 } while (0);
Ralph Metzlere8783952011-07-03 13:36:17 -0300502 return status;
503}
504
505static int RFTrackingFiltersInit(struct tda_state *state,
506 u8 RFBand)
507{
Ralph Metzlere8783952011-07-03 13:36:17 -0300508 int status = 0;
509
510 u32 RF1 = m_RF_Band_Map[RFBand].m_RF1_Default;
511 u32 RF2 = m_RF_Band_Map[RFBand].m_RF2_Default;
512 u32 RF3 = m_RF_Band_Map[RFBand].m_RF3_Default;
513 bool bcal = false;
514
515 s32 Cprog_cal1 = 0;
516 s32 Cprog_table1 = 0;
517 s32 Cprog_cal2 = 0;
518 s32 Cprog_table2 = 0;
519 s32 Cprog_cal3 = 0;
520 s32 Cprog_table3 = 0;
521
522 state->m_RF_A1[RFBand] = 0;
523 state->m_RF_B1[RFBand] = 0;
524 state->m_RF_A2[RFBand] = 0;
525 state->m_RF_B2[RFBand] = 0;
526
527 do {
Mauro Carvalho Chehab469ffe02011-07-03 18:12:26 -0300528 status = PowerScan(state, RFBand, RF1, &RF1, &bcal);
529 if (status < 0)
530 break;
Oliver Endriss0fe44622011-07-03 13:37:31 -0300531 if (bcal) {
Mauro Carvalho Chehab469ffe02011-07-03 18:12:26 -0300532 status = CalibrateRF(state, RFBand, RF1, &Cprog_cal1);
533 if (status < 0)
534 break;
Ralph Metzlere8783952011-07-03 13:36:17 -0300535 }
Oliver Endriss0fe44622011-07-03 13:37:31 -0300536 SearchMap2(m_RF_Cal_Map, RF1, &Cprog_table1);
537 if (!bcal)
Ralph Metzlere8783952011-07-03 13:36:17 -0300538 Cprog_cal1 = Cprog_table1;
Ralph Metzlere8783952011-07-03 13:36:17 -0300539 state->m_RF_B1[RFBand] = Cprog_cal1 - Cprog_table1;
Oliver Endriss0fe44622011-07-03 13:37:31 -0300540 /* state->m_RF_A1[RF_Band] = ???? */
Ralph Metzlere8783952011-07-03 13:36:17 -0300541
Oliver Endriss0fe44622011-07-03 13:37:31 -0300542 if (RF2 == 0)
543 break;
Ralph Metzlere8783952011-07-03 13:36:17 -0300544
Mauro Carvalho Chehab469ffe02011-07-03 18:12:26 -0300545 status = PowerScan(state, RFBand, RF2, &RF2, &bcal);
546 if (status < 0)
547 break;
Oliver Endriss0fe44622011-07-03 13:37:31 -0300548 if (bcal) {
Mauro Carvalho Chehab469ffe02011-07-03 18:12:26 -0300549 status = CalibrateRF(state, RFBand, RF2, &Cprog_cal2);
550 if (status < 0)
551 break;
Ralph Metzlere8783952011-07-03 13:36:17 -0300552 }
Oliver Endriss0fe44622011-07-03 13:37:31 -0300553 SearchMap2(m_RF_Cal_Map, RF2, &Cprog_table2);
554 if (!bcal)
Ralph Metzlere8783952011-07-03 13:36:17 -0300555 Cprog_cal2 = Cprog_table2;
Ralph Metzlere8783952011-07-03 13:36:17 -0300556
557 state->m_RF_A1[RFBand] =
558 (Cprog_cal2 - Cprog_table2 - Cprog_cal1 + Cprog_table1) /
Oliver Endriss0fe44622011-07-03 13:37:31 -0300559 ((s32)(RF2) - (s32)(RF1));
Ralph Metzlere8783952011-07-03 13:36:17 -0300560
Oliver Endriss0fe44622011-07-03 13:37:31 -0300561 if (RF3 == 0)
562 break;
Ralph Metzlere8783952011-07-03 13:36:17 -0300563
Mauro Carvalho Chehab469ffe02011-07-03 18:12:26 -0300564 status = PowerScan(state, RFBand, RF3, &RF3, &bcal);
565 if (status < 0)
566 break;
Oliver Endriss0fe44622011-07-03 13:37:31 -0300567 if (bcal) {
Mauro Carvalho Chehab469ffe02011-07-03 18:12:26 -0300568 status = CalibrateRF(state, RFBand, RF3, &Cprog_cal3);
569 if (status < 0)
570 break;
Ralph Metzlere8783952011-07-03 13:36:17 -0300571 }
Oliver Endriss0fe44622011-07-03 13:37:31 -0300572 SearchMap2(m_RF_Cal_Map, RF3, &Cprog_table3);
573 if (!bcal)
Ralph Metzlere8783952011-07-03 13:36:17 -0300574 Cprog_cal3 = Cprog_table3;
Oliver Endriss0fe44622011-07-03 13:37:31 -0300575 state->m_RF_A2[RFBand] = (Cprog_cal3 - Cprog_table3 - Cprog_cal2 + Cprog_table2) / ((s32)(RF3) - (s32)(RF2));
Ralph Metzlere8783952011-07-03 13:36:17 -0300576 state->m_RF_B2[RFBand] = Cprog_cal2 - Cprog_table2;
577
Oliver Endriss0fe44622011-07-03 13:37:31 -0300578 } while (0);
Ralph Metzlere8783952011-07-03 13:36:17 -0300579
580 state->m_RF1[RFBand] = RF1;
581 state->m_RF2[RFBand] = RF2;
582 state->m_RF3[RFBand] = RF3;
583
584#if 0
Mauro Carvalho Chehabf3d40bd2011-07-04 14:00:25 -0300585 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 -0300586 RFBand, RF1, state->m_RF_A1[RFBand], state->m_RF_B1[RFBand], RF2,
587 state->m_RF_A2[RFBand], state->m_RF_B2[RFBand], RF3);
Ralph Metzlere8783952011-07-03 13:36:17 -0300588#endif
589
590 return status;
591}
592
593static int PowerScan(struct tda_state *state,
Oliver Endriss0fe44622011-07-03 13:37:31 -0300594 u8 RFBand, u32 RF_in, u32 *pRF_Out, bool *pbcal)
Ralph Metzlere8783952011-07-03 13:36:17 -0300595{
Oliver Endriss0fe44622011-07-03 13:37:31 -0300596 int status = 0;
597 do {
598 u8 Gain_Taper = 0;
599 s32 RFC_Cprog = 0;
600 u8 CID_Target = 0;
601 u8 CountLimit = 0;
602 u32 freq_MainPLL;
603 u8 Regs[NUM_REGS];
604 u8 CID_Gain;
605 s32 Count = 0;
606 int sign = 1;
607 bool wait = false;
Ralph Metzlere8783952011-07-03 13:36:17 -0300608
Oliver Endriss0fe44622011-07-03 13:37:31 -0300609 if (!(SearchMap2(m_RF_Cal_Map, RF_in, &RFC_Cprog) &&
610 SearchMap1(m_GainTaper_Map, RF_in, &Gain_Taper) &&
611 SearchMap3(m_CID_Target_Map, RF_in, &CID_Target, &CountLimit))) {
Ralph Metzlere8783952011-07-03 13:36:17 -0300612
Mauro Carvalho Chehabf3d40bd2011-07-04 14:00:25 -0300613 printk(KERN_ERR "tda18271c2dd: %s Search map failed\n", __func__);
Oliver Endriss0fe44622011-07-03 13:37:31 -0300614 return -EINVAL;
615 }
Ralph Metzlere8783952011-07-03 13:36:17 -0300616
Oliver Endriss0fe44622011-07-03 13:37:31 -0300617 state->m_Regs[EP2] = (RFBand << 5) | Gain_Taper;
618 state->m_Regs[EB14] = (RFC_Cprog);
Mauro Carvalho Chehab469ffe02011-07-03 18:12:26 -0300619 status = UpdateReg(state, EP2);
620 if (status < 0)
621 break;
622 status = UpdateReg(state, EB14);
623 if (status < 0)
624 break;
Ralph Metzlere8783952011-07-03 13:36:17 -0300625
Oliver Endriss0fe44622011-07-03 13:37:31 -0300626 freq_MainPLL = RF_in + 1000000;
Mauro Carvalho Chehab469ffe02011-07-03 18:12:26 -0300627 status = CalcMainPLL(state, freq_MainPLL);
628 if (status < 0)
629 break;
Oliver Endriss0fe44622011-07-03 13:37:31 -0300630 msleep(5);
631 state->m_Regs[EP4] = (state->m_Regs[EP4] & ~0x03) | 1; /* CAL_mode = 1 */
Mauro Carvalho Chehab469ffe02011-07-03 18:12:26 -0300632 status = UpdateReg(state, EP4);
633 if (status < 0)
634 break;
635 status = UpdateReg(state, EP2); /* Launch power measurement */
636 if (status < 0)
637 break;
638 status = ReadExtented(state, Regs);
639 if (status < 0)
640 break;
Oliver Endriss0fe44622011-07-03 13:37:31 -0300641 CID_Gain = Regs[EB10] & 0x3F;
642 state->m_Regs[ID] = Regs[ID]; /* Chip version, (needed for C1 workarround in CalibrateRF) */
Ralph Metzlere8783952011-07-03 13:36:17 -0300643
Oliver Endriss0fe44622011-07-03 13:37:31 -0300644 *pRF_Out = RF_in;
Ralph Metzlere8783952011-07-03 13:36:17 -0300645
Oliver Endriss0fe44622011-07-03 13:37:31 -0300646 while (CID_Gain < CID_Target) {
647 freq_MainPLL = RF_in + sign * Count + 1000000;
Mauro Carvalho Chehab469ffe02011-07-03 18:12:26 -0300648 status = CalcMainPLL(state, freq_MainPLL);
649 if (status < 0)
650 break;
Oliver Endriss0fe44622011-07-03 13:37:31 -0300651 msleep(wait ? 5 : 1);
652 wait = false;
Mauro Carvalho Chehab469ffe02011-07-03 18:12:26 -0300653 status = UpdateReg(state, EP2); /* Launch power measurement */
654 if (status < 0)
655 break;
656 status = ReadExtented(state, Regs);
657 if (status < 0)
658 break;
Oliver Endriss0fe44622011-07-03 13:37:31 -0300659 CID_Gain = Regs[EB10] & 0x3F;
660 Count += 200000;
Ralph Metzlere8783952011-07-03 13:36:17 -0300661
Oliver Endriss0fe44622011-07-03 13:37:31 -0300662 if (Count < CountLimit * 100000)
663 continue;
664 if (sign < 0)
665 break;
666
667 sign = -sign;
668 Count = 200000;
669 wait = true;
670 }
Mauro Carvalho Chehab469ffe02011-07-03 18:12:26 -0300671 status = status;
672 if (status < 0)
673 break;
Oliver Endriss0fe44622011-07-03 13:37:31 -0300674 if (CID_Gain >= CID_Target) {
675 *pbcal = true;
676 *pRF_Out = freq_MainPLL - 1000000;
677 } else
678 *pbcal = false;
679 } while (0);
680
681 return status;
Ralph Metzlere8783952011-07-03 13:36:17 -0300682}
683
684static int PowerScanInit(struct tda_state *state)
685{
Ralph Metzlere8783952011-07-03 13:36:17 -0300686 int status = 0;
Oliver Endriss0fe44622011-07-03 13:37:31 -0300687 do {
Ralph Metzlere8783952011-07-03 13:36:17 -0300688 state->m_Regs[EP3] = (state->m_Regs[EP3] & ~0x1F) | 0x12;
Oliver Endriss0fe44622011-07-03 13:37:31 -0300689 state->m_Regs[EP4] = (state->m_Regs[EP4] & ~0x1F); /* If level = 0, Cal mode = 0 */
Mauro Carvalho Chehab469ffe02011-07-03 18:12:26 -0300690 status = UpdateRegs(state, EP3, EP4);
691 if (status < 0)
692 break;
Oliver Endriss0fe44622011-07-03 13:37:31 -0300693 state->m_Regs[EB18] = (state->m_Regs[EB18] & ~0x03); /* AGC 1 Gain = 0 */
Mauro Carvalho Chehab469ffe02011-07-03 18:12:26 -0300694 status = UpdateReg(state, EB18);
695 if (status < 0)
696 break;
Oliver Endriss0fe44622011-07-03 13:37:31 -0300697 state->m_Regs[EB21] = (state->m_Regs[EB21] & ~0x03); /* AGC 2 Gain = 0 (Datasheet = 3) */
698 state->m_Regs[EB23] = (state->m_Regs[EB23] | 0x06); /* ForceLP_Fc2_En = 1, LPFc[2] = 1 */
Mauro Carvalho Chehab469ffe02011-07-03 18:12:26 -0300699 status = UpdateRegs(state, EB21, EB23);
700 if (status < 0)
701 break;
Oliver Endriss0fe44622011-07-03 13:37:31 -0300702 } while (0);
Ralph Metzlere8783952011-07-03 13:36:17 -0300703 return status;
704}
705
706static int CalcRFFilterCurve(struct tda_state *state)
707{
Ralph Metzlere8783952011-07-03 13:36:17 -0300708 int status = 0;
Oliver Endriss0fe44622011-07-03 13:37:31 -0300709 do {
710 msleep(200); /* Temperature stabilisation */
Mauro Carvalho Chehab469ffe02011-07-03 18:12:26 -0300711 status = PowerScanInit(state);
712 if (status < 0)
713 break;
714 status = RFTrackingFiltersInit(state, 0);
715 if (status < 0)
716 break;
717 status = RFTrackingFiltersInit(state, 1);
718 if (status < 0)
719 break;
720 status = RFTrackingFiltersInit(state, 2);
721 if (status < 0)
722 break;
723 status = RFTrackingFiltersInit(state, 3);
724 if (status < 0)
725 break;
726 status = RFTrackingFiltersInit(state, 4);
727 if (status < 0)
728 break;
729 status = RFTrackingFiltersInit(state, 5);
730 if (status < 0)
731 break;
732 status = RFTrackingFiltersInit(state, 6);
733 if (status < 0)
734 break;
735 status = ThermometerRead(state, &state->m_TMValue_RFCal); /* also switches off Cal mode !!! */
736 if (status < 0)
737 break;
Oliver Endriss0fe44622011-07-03 13:37:31 -0300738 } while (0);
Ralph Metzlere8783952011-07-03 13:36:17 -0300739
740 return status;
741}
742
743static int FixedContentsI2CUpdate(struct tda_state *state)
744{
745 static u8 InitRegs[] = {
Oliver Endriss0fe44622011-07-03 13:37:31 -0300746 0x08, 0x80, 0xC6,
747 0xDF, 0x16, 0x60, 0x80,
748 0x80, 0x00, 0x00, 0x00,
749 0x00, 0x00, 0x00, 0x00,
750 0xFC, 0x01, 0x84, 0x41,
751 0x01, 0x84, 0x40, 0x07,
752 0x00, 0x00, 0x96, 0x3F,
753 0xC1, 0x00, 0x8F, 0x00,
754 0x00, 0x8C, 0x00, 0x20,
755 0xB3, 0x48, 0xB0,
Ralph Metzlere8783952011-07-03 13:36:17 -0300756 };
757 int status = 0;
Oliver Endriss0fe44622011-07-03 13:37:31 -0300758 memcpy(&state->m_Regs[TM], InitRegs, EB23 - TM + 1);
Ralph Metzlere8783952011-07-03 13:36:17 -0300759 do {
Mauro Carvalho Chehab469ffe02011-07-03 18:12:26 -0300760 status = UpdateRegs(state, TM, EB23);
761 if (status < 0)
762 break;
Ralph Metzlere8783952011-07-03 13:36:17 -0300763
Oliver Endriss0fe44622011-07-03 13:37:31 -0300764 /* AGC1 gain setup */
Ralph Metzlere8783952011-07-03 13:36:17 -0300765 state->m_Regs[EB17] = 0x00;
Mauro Carvalho Chehab469ffe02011-07-03 18:12:26 -0300766 status = UpdateReg(state, EB17);
767 if (status < 0)
768 break;
Ralph Metzlere8783952011-07-03 13:36:17 -0300769 state->m_Regs[EB17] = 0x03;
Mauro Carvalho Chehab469ffe02011-07-03 18:12:26 -0300770 status = UpdateReg(state, EB17);
771 if (status < 0)
772 break;
Ralph Metzlere8783952011-07-03 13:36:17 -0300773 state->m_Regs[EB17] = 0x43;
Mauro Carvalho Chehab469ffe02011-07-03 18:12:26 -0300774 status = UpdateReg(state, EB17);
775 if (status < 0)
776 break;
Ralph Metzlere8783952011-07-03 13:36:17 -0300777 state->m_Regs[EB17] = 0x4C;
Mauro Carvalho Chehab469ffe02011-07-03 18:12:26 -0300778 status = UpdateReg(state, EB17);
779 if (status < 0)
780 break;
Ralph Metzlere8783952011-07-03 13:36:17 -0300781
Oliver Endriss0fe44622011-07-03 13:37:31 -0300782 /* IRC Cal Low band */
Ralph Metzlere8783952011-07-03 13:36:17 -0300783 state->m_Regs[EP3] = 0x1F;
784 state->m_Regs[EP4] = 0x66;
785 state->m_Regs[EP5] = 0x81;
786 state->m_Regs[CPD] = 0xCC;
787 state->m_Regs[CD1] = 0x6C;
788 state->m_Regs[CD2] = 0x00;
789 state->m_Regs[CD3] = 0x00;
790 state->m_Regs[MPD] = 0xC5;
791 state->m_Regs[MD1] = 0x77;
792 state->m_Regs[MD2] = 0x08;
793 state->m_Regs[MD3] = 0x00;
Mauro Carvalho Chehab469ffe02011-07-03 18:12:26 -0300794 status = UpdateRegs(state, EP2, MD3); /* diff between sw and datasheet (ep3-md3) */
795 if (status < 0)
796 break;
Ralph Metzlere8783952011-07-03 13:36:17 -0300797
Oliver Endriss0fe44622011-07-03 13:37:31 -0300798#if 0
799 state->m_Regs[EB4] = 0x61; /* missing in sw */
Mauro Carvalho Chehab469ffe02011-07-03 18:12:26 -0300800 status = UpdateReg(state, EB4);
801 if (status < 0)
802 break;
Oliver Endriss0fe44622011-07-03 13:37:31 -0300803 msleep(1);
804 state->m_Regs[EB4] = 0x41;
Mauro Carvalho Chehab469ffe02011-07-03 18:12:26 -0300805 status = UpdateReg(state, EB4);
806 if (status < 0)
807 break;
Oliver Endriss0fe44622011-07-03 13:37:31 -0300808#endif
Ralph Metzlere8783952011-07-03 13:36:17 -0300809
810 msleep(5);
Mauro Carvalho Chehab469ffe02011-07-03 18:12:26 -0300811 status = UpdateReg(state, EP1);
812 if (status < 0)
813 break;
Ralph Metzlere8783952011-07-03 13:36:17 -0300814 msleep(5);
815
816 state->m_Regs[EP5] = 0x85;
817 state->m_Regs[CPD] = 0xCB;
818 state->m_Regs[CD1] = 0x66;
819 state->m_Regs[CD2] = 0x70;
Mauro Carvalho Chehab469ffe02011-07-03 18:12:26 -0300820 status = UpdateRegs(state, EP3, CD3);
821 if (status < 0)
822 break;
Ralph Metzlere8783952011-07-03 13:36:17 -0300823 msleep(5);
Mauro Carvalho Chehab469ffe02011-07-03 18:12:26 -0300824 status = UpdateReg(state, EP2);
825 if (status < 0)
826 break;
Ralph Metzlere8783952011-07-03 13:36:17 -0300827 msleep(30);
828
Oliver Endriss0fe44622011-07-03 13:37:31 -0300829 /* IRC Cal mid band */
Ralph Metzlere8783952011-07-03 13:36:17 -0300830 state->m_Regs[EP5] = 0x82;
831 state->m_Regs[CPD] = 0xA8;
832 state->m_Regs[CD2] = 0x00;
Oliver Endriss0fe44622011-07-03 13:37:31 -0300833 state->m_Regs[MPD] = 0xA1; /* Datasheet = 0xA9 */
Ralph Metzlere8783952011-07-03 13:36:17 -0300834 state->m_Regs[MD1] = 0x73;
835 state->m_Regs[MD2] = 0x1A;
Mauro Carvalho Chehab469ffe02011-07-03 18:12:26 -0300836 status = UpdateRegs(state, EP3, MD3);
837 if (status < 0)
838 break;
Ralph Metzlere8783952011-07-03 13:36:17 -0300839
840 msleep(5);
Mauro Carvalho Chehab469ffe02011-07-03 18:12:26 -0300841 status = UpdateReg(state, EP1);
842 if (status < 0)
843 break;
Ralph Metzlere8783952011-07-03 13:36:17 -0300844 msleep(5);
845
846 state->m_Regs[EP5] = 0x86;
847 state->m_Regs[CPD] = 0xA8;
848 state->m_Regs[CD1] = 0x66;
849 state->m_Regs[CD2] = 0xA0;
Mauro Carvalho Chehab469ffe02011-07-03 18:12:26 -0300850 status = UpdateRegs(state, EP3, CD3);
851 if (status < 0)
852 break;
Ralph Metzlere8783952011-07-03 13:36:17 -0300853 msleep(5);
Mauro Carvalho Chehab469ffe02011-07-03 18:12:26 -0300854 status = UpdateReg(state, EP2);
855 if (status < 0)
856 break;
Ralph Metzlere8783952011-07-03 13:36:17 -0300857 msleep(30);
858
Oliver Endriss0fe44622011-07-03 13:37:31 -0300859 /* IRC Cal high band */
Ralph Metzlere8783952011-07-03 13:36:17 -0300860 state->m_Regs[EP5] = 0x83;
861 state->m_Regs[CPD] = 0x98;
862 state->m_Regs[CD1] = 0x65;
863 state->m_Regs[CD2] = 0x00;
Oliver Endriss0fe44622011-07-03 13:37:31 -0300864 state->m_Regs[MPD] = 0x91; /* Datasheet = 0x91 */
Ralph Metzlere8783952011-07-03 13:36:17 -0300865 state->m_Regs[MD1] = 0x71;
866 state->m_Regs[MD2] = 0xCD;
Mauro Carvalho Chehab469ffe02011-07-03 18:12:26 -0300867 status = UpdateRegs(state, EP3, MD3);
868 if (status < 0)
869 break;
Ralph Metzlere8783952011-07-03 13:36:17 -0300870 msleep(5);
Mauro Carvalho Chehab469ffe02011-07-03 18:12:26 -0300871 status = UpdateReg(state, EP1);
872 if (status < 0)
873 break;
Ralph Metzlere8783952011-07-03 13:36:17 -0300874 msleep(5);
875 state->m_Regs[EP5] = 0x87;
876 state->m_Regs[CD1] = 0x65;
877 state->m_Regs[CD2] = 0x50;
Mauro Carvalho Chehab469ffe02011-07-03 18:12:26 -0300878 status = UpdateRegs(state, EP3, CD3);
879 if (status < 0)
880 break;
Ralph Metzlere8783952011-07-03 13:36:17 -0300881 msleep(5);
Mauro Carvalho Chehab469ffe02011-07-03 18:12:26 -0300882 status = UpdateReg(state, EP2);
883 if (status < 0)
884 break;
Ralph Metzlere8783952011-07-03 13:36:17 -0300885 msleep(30);
886
Oliver Endriss0fe44622011-07-03 13:37:31 -0300887 /* Back to normal */
Ralph Metzlere8783952011-07-03 13:36:17 -0300888 state->m_Regs[EP4] = 0x64;
Mauro Carvalho Chehab469ffe02011-07-03 18:12:26 -0300889 status = UpdateReg(state, EP4);
890 if (status < 0)
891 break;
892 status = UpdateReg(state, EP1);
893 if (status < 0)
894 break;
Ralph Metzlere8783952011-07-03 13:36:17 -0300895
Oliver Endriss0fe44622011-07-03 13:37:31 -0300896 } while (0);
Ralph Metzlere8783952011-07-03 13:36:17 -0300897 return status;
898}
899
900static int InitCal(struct tda_state *state)
901{
902 int status = 0;
903
Oliver Endriss0fe44622011-07-03 13:37:31 -0300904 do {
Mauro Carvalho Chehab469ffe02011-07-03 18:12:26 -0300905 status = FixedContentsI2CUpdate(state);
906 if (status < 0)
907 break;
908 status = CalcRFFilterCurve(state);
909 if (status < 0)
910 break;
911 status = StandBy(state);
912 if (status < 0)
913 break;
Oliver Endriss0fe44622011-07-03 13:37:31 -0300914 /* m_bInitDone = true; */
915 } while (0);
Ralph Metzlere8783952011-07-03 13:36:17 -0300916 return status;
917};
918
919static int RFTrackingFiltersCorrection(struct tda_state *state,
920 u32 Frequency)
921{
922 int status = 0;
923 s32 Cprog_table;
924 u8 RFBand;
925 u8 dCoverdT;
926
Oliver Endriss0fe44622011-07-03 13:37:31 -0300927 if (!SearchMap2(m_RF_Cal_Map, Frequency, &Cprog_table) ||
928 !SearchMap4(m_RF_Band_Map, Frequency, &RFBand) ||
929 !SearchMap1(m_RF_Cal_DC_Over_DT_Map, Frequency, &dCoverdT))
Ralph Metzlere8783952011-07-03 13:36:17 -0300930
Oliver Endriss0fe44622011-07-03 13:37:31 -0300931 return -EINVAL;
932
933 do {
Ralph Metzlere8783952011-07-03 13:36:17 -0300934 u8 TMValue_Current;
935 u32 RF1 = state->m_RF1[RFBand];
936 u32 RF2 = state->m_RF1[RFBand];
937 u32 RF3 = state->m_RF1[RFBand];
938 s32 RF_A1 = state->m_RF_A1[RFBand];
939 s32 RF_B1 = state->m_RF_B1[RFBand];
940 s32 RF_A2 = state->m_RF_A2[RFBand];
941 s32 RF_B2 = state->m_RF_B2[RFBand];
942 s32 Capprox = 0;
943 int TComp;
944
Oliver Endriss0fe44622011-07-03 13:37:31 -0300945 state->m_Regs[EP3] &= ~0xE0; /* Power up */
Mauro Carvalho Chehab469ffe02011-07-03 18:12:26 -0300946 status = UpdateReg(state, EP3);
947 if (status < 0)
948 break;
Ralph Metzlere8783952011-07-03 13:36:17 -0300949
Mauro Carvalho Chehab469ffe02011-07-03 18:12:26 -0300950 status = ThermometerRead(state, &TMValue_Current);
951 if (status < 0)
952 break;
Ralph Metzlere8783952011-07-03 13:36:17 -0300953
Oliver Endriss0fe44622011-07-03 13:37:31 -0300954 if (RF3 == 0 || Frequency < RF2)
Ralph Metzlere8783952011-07-03 13:36:17 -0300955 Capprox = RF_A1 * ((s32)(Frequency) - (s32)(RF1)) + RF_B1 + Cprog_table;
Ralph Metzlere8783952011-07-03 13:36:17 -0300956 else
Ralph Metzlere8783952011-07-03 13:36:17 -0300957 Capprox = RF_A2 * ((s32)(Frequency) - (s32)(RF2)) + RF_B2 + Cprog_table;
Ralph Metzlere8783952011-07-03 13:36:17 -0300958
959 TComp = (int)(dCoverdT) * ((int)(TMValue_Current) - (int)(state->m_TMValue_RFCal))/1000;
960
961 Capprox += TComp;
962
Oliver Endriss0fe44622011-07-03 13:37:31 -0300963 if (Capprox < 0)
964 Capprox = 0;
965 else if (Capprox > 255)
966 Capprox = 255;
Ralph Metzlere8783952011-07-03 13:36:17 -0300967
968
Oliver Endriss0fe44622011-07-03 13:37:31 -0300969 /* TODO Temperature compensation. There is defenitely a scale factor */
970 /* missing in the datasheet, so leave it out for now. */
971 state->m_Regs[EB14] = Capprox;
Ralph Metzlere8783952011-07-03 13:36:17 -0300972
Mauro Carvalho Chehab469ffe02011-07-03 18:12:26 -0300973 status = UpdateReg(state, EB14);
974 if (status < 0)
975 break;
Ralph Metzlere8783952011-07-03 13:36:17 -0300976
Oliver Endriss0fe44622011-07-03 13:37:31 -0300977 } while (0);
Ralph Metzlere8783952011-07-03 13:36:17 -0300978 return status;
979}
980
981static int ChannelConfiguration(struct tda_state *state,
982 u32 Frequency, int Standard)
983{
984
985 s32 IntermediateFrequency = m_StandardTable[Standard].m_IFFrequency;
986 int status = 0;
987
988 u8 BP_Filter = 0;
989 u8 RF_Band = 0;
990 u8 GainTaper = 0;
Mauro Carvalho Chehabea90f012011-07-03 18:06:07 -0300991 u8 IR_Meas = 0;
Ralph Metzlere8783952011-07-03 13:36:17 -0300992
Oliver Endriss0fe44622011-07-03 13:37:31 -0300993 state->IF = IntermediateFrequency;
Mauro Carvalho Chehabf3d40bd2011-07-04 14:00:25 -0300994 /* printk("tda18271c2dd: %s Freq = %d Standard = %d IF = %d\n", __func__, Frequency, Standard, IntermediateFrequency); */
Oliver Endriss0fe44622011-07-03 13:37:31 -0300995 /* get values from tables */
Ralph Metzlere8783952011-07-03 13:36:17 -0300996
Oliver Endriss0fe44622011-07-03 13:37:31 -0300997 if (!(SearchMap1(m_BP_Filter_Map, Frequency, &BP_Filter) &&
998 SearchMap1(m_GainTaper_Map, Frequency, &GainTaper) &&
999 SearchMap1(m_IR_Meas_Map, Frequency, &IR_Meas) &&
1000 SearchMap4(m_RF_Band_Map, Frequency, &RF_Band))) {
1001
Mauro Carvalho Chehabf3d40bd2011-07-04 14:00:25 -03001002 printk(KERN_ERR "tda18271c2dd: %s SearchMap failed\n", __func__);
Ralph Metzlere8783952011-07-03 13:36:17 -03001003 return -EINVAL;
1004 }
1005
Oliver Endriss0fe44622011-07-03 13:37:31 -03001006 do {
Ralph Metzlere8783952011-07-03 13:36:17 -03001007 state->m_Regs[EP3] = (state->m_Regs[EP3] & ~0x1F) | m_StandardTable[Standard].m_EP3_4_0;
Oliver Endriss0fe44622011-07-03 13:37:31 -03001008 state->m_Regs[EP3] &= ~0x04; /* switch RFAGC to high speed mode */
Ralph Metzlere8783952011-07-03 13:36:17 -03001009
Oliver Endriss0fe44622011-07-03 13:37:31 -03001010 /* m_EP4 default for XToutOn, CAL_Mode (0) */
1011 state->m_Regs[EP4] = state->m_EP4 | ((Standard > HF_AnalogMax) ? state->m_IFLevelDigital : state->m_IFLevelAnalog);
1012 /* state->m_Regs[EP4] = state->m_EP4 | state->m_IFLevelDigital; */
1013 if (Standard <= HF_AnalogMax)
1014 state->m_Regs[EP4] = state->m_EP4 | state->m_IFLevelAnalog;
1015 else if (Standard <= HF_ATSC)
1016 state->m_Regs[EP4] = state->m_EP4 | state->m_IFLevelDVBT;
1017 else if (Standard <= HF_DVBC)
1018 state->m_Regs[EP4] = state->m_EP4 | state->m_IFLevelDVBC;
1019 else
1020 state->m_Regs[EP4] = state->m_EP4 | state->m_IFLevelDigital;
Ralph Metzlere8783952011-07-03 13:36:17 -03001021
Oliver Endriss0fe44622011-07-03 13:37:31 -03001022 if ((Standard == HF_FM_Radio) && state->m_bFMInput)
1023 state->m_Regs[EP4] |= 80;
Ralph Metzlere8783952011-07-03 13:36:17 -03001024
1025 state->m_Regs[MPD] &= ~0x80;
Oliver Endriss0fe44622011-07-03 13:37:31 -03001026 if (Standard > HF_AnalogMax)
1027 state->m_Regs[MPD] |= 0x80; /* Add IF_notch for digital */
Ralph Metzlere8783952011-07-03 13:36:17 -03001028
1029 state->m_Regs[EB22] = m_StandardTable[Standard].m_EB22;
1030
Oliver Endriss0fe44622011-07-03 13:37:31 -03001031 /* Note: This is missing from flowchart in TDA18271 specification ( 1.5 MHz cutoff for FM ) */
1032 if (Standard == HF_FM_Radio)
1033 state->m_Regs[EB23] |= 0x06; /* ForceLP_Fc2_En = 1, LPFc[2] = 1 */
1034 else
1035 state->m_Regs[EB23] &= ~0x06; /* ForceLP_Fc2_En = 0, LPFc[2] = 0 */
Ralph Metzlere8783952011-07-03 13:36:17 -03001036
Mauro Carvalho Chehab469ffe02011-07-03 18:12:26 -03001037 status = UpdateRegs(state, EB22, EB23);
1038 if (status < 0)
1039 break;
Ralph Metzlere8783952011-07-03 13:36:17 -03001040
Oliver Endriss0fe44622011-07-03 13:37:31 -03001041 state->m_Regs[EP1] = (state->m_Regs[EP1] & ~0x07) | 0x40 | BP_Filter; /* Dis_Power_level = 1, Filter */
Ralph Metzlere8783952011-07-03 13:36:17 -03001042 state->m_Regs[EP5] = (state->m_Regs[EP5] & ~0x07) | IR_Meas;
1043 state->m_Regs[EP2] = (RF_Band << 5) | GainTaper;
1044
1045 state->m_Regs[EB1] = (state->m_Regs[EB1] & ~0x07) |
Oliver Endriss0fe44622011-07-03 13:37:31 -03001046 (state->m_bMaster ? 0x04 : 0x00); /* CALVCO_FortLOn = MS */
1047 /* AGC1_always_master = 0 */
1048 /* AGC_firstn = 0 */
Mauro Carvalho Chehab469ffe02011-07-03 18:12:26 -03001049 status = UpdateReg(state, EB1);
1050 if (status < 0)
1051 break;
Ralph Metzlere8783952011-07-03 13:36:17 -03001052
Oliver Endriss0fe44622011-07-03 13:37:31 -03001053 if (state->m_bMaster) {
Mauro Carvalho Chehab469ffe02011-07-03 18:12:26 -03001054 status = CalcMainPLL(state, Frequency + IntermediateFrequency);
1055 if (status < 0)
1056 break;
1057 status = UpdateRegs(state, TM, EP5);
1058 if (status < 0)
1059 break;
Oliver Endriss0fe44622011-07-03 13:37:31 -03001060 state->m_Regs[EB4] |= 0x20; /* LO_forceSrce = 1 */
Mauro Carvalho Chehab469ffe02011-07-03 18:12:26 -03001061 status = UpdateReg(state, EB4);
1062 if (status < 0)
1063 break;
Ralph Metzlere8783952011-07-03 13:36:17 -03001064 msleep(1);
Oliver Endriss0fe44622011-07-03 13:37:31 -03001065 state->m_Regs[EB4] &= ~0x20; /* LO_forceSrce = 0 */
Mauro Carvalho Chehab469ffe02011-07-03 18:12:26 -03001066 status = UpdateReg(state, EB4);
1067 if (status < 0)
1068 break;
Oliver Endriss0fe44622011-07-03 13:37:31 -03001069 } else {
Mauro Carvalho Chehabea90f012011-07-03 18:06:07 -03001070 u8 PostDiv = 0;
Ralph Metzlere8783952011-07-03 13:36:17 -03001071 u8 Div;
Mauro Carvalho Chehab469ffe02011-07-03 18:12:26 -03001072 status = CalcCalPLL(state, Frequency + IntermediateFrequency);
1073 if (status < 0)
1074 break;
Ralph Metzlere8783952011-07-03 13:36:17 -03001075
Oliver Endriss0fe44622011-07-03 13:37:31 -03001076 SearchMap3(m_Cal_PLL_Map, Frequency + IntermediateFrequency, &PostDiv, &Div);
Ralph Metzlere8783952011-07-03 13:36:17 -03001077 state->m_Regs[MPD] = (state->m_Regs[MPD] & ~0x7F) | (PostDiv & 0x77);
Mauro Carvalho Chehab469ffe02011-07-03 18:12:26 -03001078 status = UpdateReg(state, MPD);
1079 if (status < 0)
1080 break;
1081 status = UpdateRegs(state, TM, EP5);
1082 if (status < 0)
1083 break;
Ralph Metzlere8783952011-07-03 13:36:17 -03001084
Oliver Endriss0fe44622011-07-03 13:37:31 -03001085 state->m_Regs[EB7] |= 0x20; /* CAL_forceSrce = 1 */
Mauro Carvalho Chehab469ffe02011-07-03 18:12:26 -03001086 status = UpdateReg(state, EB7);
1087 if (status < 0)
1088 break;
Ralph Metzlere8783952011-07-03 13:36:17 -03001089 msleep(1);
Oliver Endriss0fe44622011-07-03 13:37:31 -03001090 state->m_Regs[EB7] &= ~0x20; /* CAL_forceSrce = 0 */
Mauro Carvalho Chehab469ffe02011-07-03 18:12:26 -03001091 status = UpdateReg(state, EB7);
1092 if (status < 0)
1093 break;
Ralph Metzlere8783952011-07-03 13:36:17 -03001094 }
1095 msleep(20);
Oliver Endriss0fe44622011-07-03 13:37:31 -03001096 if (Standard != HF_FM_Radio)
1097 state->m_Regs[EP3] |= 0x04; /* RFAGC to normal mode */
Mauro Carvalho Chehab469ffe02011-07-03 18:12:26 -03001098 status = UpdateReg(state, EP3);
1099 if (status < 0)
1100 break;
Ralph Metzlere8783952011-07-03 13:36:17 -03001101
Oliver Endriss0fe44622011-07-03 13:37:31 -03001102 } while (0);
Ralph Metzlere8783952011-07-03 13:36:17 -03001103 return status;
1104}
1105
Oliver Endriss0fe44622011-07-03 13:37:31 -03001106static int sleep(struct dvb_frontend *fe)
Ralph Metzlere8783952011-07-03 13:36:17 -03001107{
1108 struct tda_state *state = fe->tuner_priv;
1109
1110 StandBy(state);
1111 return 0;
1112}
1113
Oliver Endriss0fe44622011-07-03 13:37:31 -03001114static int init(struct dvb_frontend *fe)
Ralph Metzlere8783952011-07-03 13:36:17 -03001115{
Ralph Metzlere8783952011-07-03 13:36:17 -03001116 return 0;
1117}
1118
Oliver Endriss0fe44622011-07-03 13:37:31 -03001119static int release(struct dvb_frontend *fe)
Ralph Metzlere8783952011-07-03 13:36:17 -03001120{
1121 kfree(fe->tuner_priv);
1122 fe->tuner_priv = NULL;
1123 return 0;
1124}
1125
Mauro Carvalho Chehabcf845292011-07-28 15:49:43 -03001126
Ralph Metzlere8783952011-07-03 13:36:17 -03001127static int set_params(struct dvb_frontend *fe,
1128 struct dvb_frontend_parameters *params)
1129{
1130 struct tda_state *state = fe->tuner_priv;
1131 int status = 0;
1132 int Standard;
Mauro Carvalho Chehabfd66c452011-12-17 20:36:57 -03001133 u32 bw = fe->dtv_property_cache.bandwidth_hz;
1134 u32 delsys = fe->dtv_property_cache.delivery_system;
Ralph Metzlere8783952011-07-03 13:36:17 -03001135
Mauro Carvalho Chehabfd66c452011-12-17 20:36:57 -03001136 state->m_Frequency = fe->dtv_property_cache.frequency;
Ralph Metzlere8783952011-07-03 13:36:17 -03001137
Mauro Carvalho Chehabfd66c452011-12-17 20:36:57 -03001138 switch (delsys) {
1139 case SYS_DVBT:
1140 case SYS_DVBT2:
1141 switch (bw) {
1142 case 6000000:
Ralph Metzlere8783952011-07-03 13:36:17 -03001143 Standard = HF_DVBT_6MHZ;
1144 break;
Mauro Carvalho Chehabfd66c452011-12-17 20:36:57 -03001145 case 7000000:
Ralph Metzlere8783952011-07-03 13:36:17 -03001146 Standard = HF_DVBT_7MHZ;
1147 break;
Mauro Carvalho Chehabfd66c452011-12-17 20:36:57 -03001148 case 8000000:
Ralph Metzlere8783952011-07-03 13:36:17 -03001149 Standard = HF_DVBT_8MHZ;
1150 break;
Mauro Carvalho Chehabfd66c452011-12-17 20:36:57 -03001151 default:
1152 return -EINVAL;
Ralph Metzlere8783952011-07-03 13:36:17 -03001153 }
Mauro Carvalho Chehabfd66c452011-12-17 20:36:57 -03001154 case SYS_DVBC_ANNEX_A:
1155 case SYS_DVBC_ANNEX_C:
Mauro Carvalho Chehab2440f7a2011-11-11 20:26:03 -02001156 if (bw <= 6000000)
Mauro Carvalho Chehabcf845292011-07-28 15:49:43 -03001157 Standard = HF_DVBC_6MHZ;
Mauro Carvalho Chehab2440f7a2011-11-11 20:26:03 -02001158 else if (bw <= 7000000)
1159 Standard = HF_DVBC_7MHZ;
Mauro Carvalho Chehabcf845292011-07-28 15:49:43 -03001160 else
1161 Standard = HF_DVBC_8MHZ;
Mauro Carvalho Chehabfd66c452011-12-17 20:36:57 -03001162 default:
Ralph Metzlere8783952011-07-03 13:36:17 -03001163 return -EINVAL;
Mauro Carvalho Chehabfd66c452011-12-17 20:36:57 -03001164 }
Ralph Metzlere8783952011-07-03 13:36:17 -03001165 do {
Mauro Carvalho Chehabfd66c452011-12-17 20:36:57 -03001166 status = RFTrackingFiltersCorrection(state, state->m_Frequency);
Mauro Carvalho Chehab469ffe02011-07-03 18:12:26 -03001167 if (status < 0)
1168 break;
Mauro Carvalho Chehabfd66c452011-12-17 20:36:57 -03001169 status = ChannelConfiguration(state, state->m_Frequency,
1170 Standard);
Mauro Carvalho Chehab469ffe02011-07-03 18:12:26 -03001171 if (status < 0)
1172 break;
Ralph Metzlere8783952011-07-03 13:36:17 -03001173
Oliver Endriss0fe44622011-07-03 13:37:31 -03001174 msleep(state->m_SettlingTime); /* Allow AGC's to settle down */
1175 } while (0);
Ralph Metzlere8783952011-07-03 13:36:17 -03001176 return status;
1177}
1178
1179#if 0
Oliver Endriss0fe44622011-07-03 13:37:31 -03001180static int GetSignalStrength(s32 *pSignalStrength, u32 RFAgc, u32 IFAgc)
Ralph Metzlere8783952011-07-03 13:36:17 -03001181{
Oliver Endriss0fe44622011-07-03 13:37:31 -03001182 if (IFAgc < 500) {
1183 /* Scale this from 0 to 50000 */
Ralph Metzlere8783952011-07-03 13:36:17 -03001184 *pSignalStrength = IFAgc * 100;
1185 } else {
Oliver Endriss0fe44622011-07-03 13:37:31 -03001186 /* Scale range 500-1500 to 50000-80000 */
Ralph Metzlere8783952011-07-03 13:36:17 -03001187 *pSignalStrength = 50000 + (IFAgc - 500) * 30;
1188 }
1189
1190 return 0;
1191}
1192#endif
1193
Mauro Carvalho Chehab8513e142011-09-03 11:40:02 -03001194static int get_if_frequency(struct dvb_frontend *fe, u32 *frequency)
Ralph Metzlere8783952011-07-03 13:36:17 -03001195{
1196 struct tda_state *state = fe->tuner_priv;
1197
1198 *frequency = state->IF;
1199 return 0;
1200}
1201
1202static int get_bandwidth(struct dvb_frontend *fe, u32 *bandwidth)
1203{
Oliver Endriss0fe44622011-07-03 13:37:31 -03001204 /* struct tda_state *state = fe->tuner_priv; */
1205 /* *bandwidth = priv->bandwidth; */
Ralph Metzlere8783952011-07-03 13:36:17 -03001206 return 0;
1207}
1208
1209
1210static struct dvb_tuner_ops tuner_ops = {
1211 .info = {
1212 .name = "NXP TDA18271C2D",
1213 .frequency_min = 47125000,
1214 .frequency_max = 865000000,
1215 .frequency_step = 62500
1216 },
1217 .init = init,
1218 .sleep = sleep,
1219 .set_params = set_params,
1220 .release = release,
Mauro Carvalho Chehab8513e142011-09-03 11:40:02 -03001221 .get_if_frequency = get_if_frequency,
Ralph Metzlere8783952011-07-03 13:36:17 -03001222 .get_bandwidth = get_bandwidth,
1223};
1224
1225struct dvb_frontend *tda18271c2dd_attach(struct dvb_frontend *fe,
1226 struct i2c_adapter *i2c, u8 adr)
1227{
1228 struct tda_state *state;
1229
1230 state = kzalloc(sizeof(struct tda_state), GFP_KERNEL);
1231 if (!state)
1232 return NULL;
1233
1234 fe->tuner_priv = state;
1235 state->adr = adr;
1236 state->i2c = i2c;
1237 memcpy(&fe->ops.tuner_ops, &tuner_ops, sizeof(struct dvb_tuner_ops));
1238 reset(state);
1239 InitCal(state);
1240
1241 return fe;
1242}
Ralph Metzlere8783952011-07-03 13:36:17 -03001243EXPORT_SYMBOL_GPL(tda18271c2dd_attach);
Oliver Endriss0fe44622011-07-03 13:37:31 -03001244
Ralph Metzlere8783952011-07-03 13:36:17 -03001245MODULE_DESCRIPTION("TDA18271C2 driver");
1246MODULE_AUTHOR("DD");
1247MODULE_LICENSE("GPL");