blob: de0a1c1109723d794d707e13518e2c971d3a1825 [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"
Mauro Carvalho Chehab4e373212012-10-27 11:28:06 -030035#include "tda18271c2dd.h"
Ralph Metzlere8783952011-07-03 13:36:17 -030036
Mauro Carvalho Chehab83937962013-11-02 05:05:18 -030037/* Max transfer size done by I2C transfer functions */
38#define MAX_XFER_SIZE 64
39
Ralph Metzlere8783952011-07-03 13:36:17 -030040struct SStandardParam {
41 s32 m_IFFrequency;
42 u32 m_BandWidth;
43 u8 m_EP3_4_0;
44 u8 m_EB22;
45};
46
47struct SMap {
48 u32 m_Frequency;
49 u8 m_Param;
50};
51
52struct SMapI {
53 u32 m_Frequency;
54 s32 m_Param;
55};
56
57struct SMap2 {
58 u32 m_Frequency;
59 u8 m_Param1;
60 u8 m_Param2;
61};
62
63struct SRFBandMap {
64 u32 m_RF_max;
65 u32 m_RF1_Default;
66 u32 m_RF2_Default;
67 u32 m_RF3_Default;
68};
69
Oliver Endriss0fe44622011-07-03 13:37:31 -030070enum ERegister {
Ralph Metzlere8783952011-07-03 13:36:17 -030071 ID = 0,
72 TM,
73 PL,
74 EP1, EP2, EP3, EP4, EP5,
75 CPD, CD1, CD2, CD3,
76 MPD, MD1, MD2, MD3,
77 EB1, EB2, EB3, EB4, EB5, EB6, EB7, EB8, EB9, EB10,
78 EB11, EB12, EB13, EB14, EB15, EB16, EB17, EB18, EB19, EB20,
79 EB21, EB22, EB23,
80 NUM_REGS
81};
82
83struct tda_state {
84 struct i2c_adapter *i2c;
85 u8 adr;
86
87 u32 m_Frequency;
88 u32 IF;
89
90 u8 m_IFLevelAnalog;
91 u8 m_IFLevelDigital;
92 u8 m_IFLevelDVBC;
93 u8 m_IFLevelDVBT;
94
95 u8 m_EP4;
96 u8 m_EP3_Standby;
97
98 bool m_bMaster;
99
100 s32 m_SettlingTime;
101
102 u8 m_Regs[NUM_REGS];
103
104 /* Tracking filter settings for band 0..6 */
105 u32 m_RF1[7];
106 s32 m_RF_A1[7];
107 s32 m_RF_B1[7];
108 u32 m_RF2[7];
109 s32 m_RF_A2[7];
110 s32 m_RF_B2[7];
111 u32 m_RF3[7];
112
113 u8 m_TMValue_RFCal; /* Calibration temperatur */
114
115 bool m_bFMInput; /* true to use Pin 8 for FM Radio */
116
117};
118
119static int PowerScan(struct tda_state *state,
Oliver Endriss0fe44622011-07-03 13:37:31 -0300120 u8 RFBand, u32 RF_in,
121 u32 *pRF_Out, bool *pbcal);
Ralph Metzlere8783952011-07-03 13:36:17 -0300122
123static int i2c_readn(struct i2c_adapter *adapter, u8 adr, u8 *data, int len)
124{
125 struct i2c_msg msgs[1] = {{.addr = adr, .flags = I2C_M_RD,
Oliver Endriss0fe44622011-07-03 13:37:31 -0300126 .buf = data, .len = len} };
Ralph Metzlere8783952011-07-03 13:36:17 -0300127 return (i2c_transfer(adapter, msgs, 1) == 1) ? 0 : -1;
128}
129
130static int i2c_write(struct i2c_adapter *adap, u8 adr, u8 *data, int len)
131{
132 struct i2c_msg msg = {.addr = adr, .flags = 0,
133 .buf = data, .len = len};
134
135 if (i2c_transfer(adap, &msg, 1) != 1) {
Mauro Carvalho Chehabf3d40bd2011-07-04 14:00:25 -0300136 printk(KERN_ERR "tda18271c2dd: i2c write error at addr %i\n", adr);
Ralph Metzlere8783952011-07-03 13:36:17 -0300137 return -1;
138 }
139 return 0;
140}
141
142static int WriteRegs(struct tda_state *state,
143 u8 SubAddr, u8 *Regs, u16 nRegs)
144{
Mauro Carvalho Chehab83937962013-11-02 05:05:18 -0300145 u8 data[MAX_XFER_SIZE];
146
147 if (1 + nRegs > sizeof(data)) {
148 printk(KERN_WARNING
149 "%s: i2c wr: len=%d is too big!\n",
150 KBUILD_MODNAME, nRegs);
151 return -EINVAL;
152 }
Ralph Metzlere8783952011-07-03 13:36:17 -0300153
154 data[0] = SubAddr;
155 memcpy(data + 1, Regs, nRegs);
Mauro Carvalho Chehab83937962013-11-02 05:05:18 -0300156 return i2c_write(state->i2c, state->adr, data, nRegs + 1);
Ralph Metzlere8783952011-07-03 13:36:17 -0300157}
158
Oliver Endriss0fe44622011-07-03 13:37:31 -0300159static int WriteReg(struct tda_state *state, u8 SubAddr, u8 Reg)
Ralph Metzlere8783952011-07-03 13:36:17 -0300160{
161 u8 msg[2] = {SubAddr, Reg};
162
163 return i2c_write(state->i2c, state->adr, msg, 2);
164}
165
166static int Read(struct tda_state *state, u8 * Regs)
167{
168 return i2c_readn(state->i2c, state->adr, Regs, 16);
169}
170
171static int ReadExtented(struct tda_state *state, u8 * Regs)
172{
173 return i2c_readn(state->i2c, state->adr, Regs, NUM_REGS);
174}
175
Oliver Endriss0fe44622011-07-03 13:37:31 -0300176static int UpdateRegs(struct tda_state *state, u8 RegFrom, u8 RegTo)
Ralph Metzlere8783952011-07-03 13:36:17 -0300177{
178 return WriteRegs(state, RegFrom,
179 &state->m_Regs[RegFrom], RegTo-RegFrom+1);
180}
181static int UpdateReg(struct tda_state *state, u8 Reg)
182{
Oliver Endriss0fe44622011-07-03 13:37:31 -0300183 return WriteReg(state, Reg, state->m_Regs[Reg]);
Ralph Metzlere8783952011-07-03 13:36:17 -0300184}
185
186#include "tda18271c2dd_maps.h"
187
Ralph Metzlere8783952011-07-03 13:36:17 -0300188static void reset(struct tda_state *state)
189{
190 u32 ulIFLevelAnalog = 0;
191 u32 ulIFLevelDigital = 2;
192 u32 ulIFLevelDVBC = 7;
193 u32 ulIFLevelDVBT = 6;
194 u32 ulXTOut = 0;
Oliver Endriss0fe44622011-07-03 13:37:31 -0300195 u32 ulStandbyMode = 0x06; /* Send in stdb, but leave osc on */
Ralph Metzlere8783952011-07-03 13:36:17 -0300196 u32 ulSlave = 0;
197 u32 ulFMInput = 0;
198 u32 ulSettlingTime = 100;
199
200 state->m_Frequency = 0;
201 state->m_SettlingTime = 100;
202 state->m_IFLevelAnalog = (ulIFLevelAnalog & 0x07) << 2;
203 state->m_IFLevelDigital = (ulIFLevelDigital & 0x07) << 2;
204 state->m_IFLevelDVBC = (ulIFLevelDVBC & 0x07) << 2;
205 state->m_IFLevelDVBT = (ulIFLevelDVBT & 0x07) << 2;
206
207 state->m_EP4 = 0x20;
Oliver Endriss0fe44622011-07-03 13:37:31 -0300208 if (ulXTOut != 0)
209 state->m_EP4 |= 0x40;
Ralph Metzlere8783952011-07-03 13:36:17 -0300210
211 state->m_EP3_Standby = ((ulStandbyMode & 0x07) << 5) | 0x0F;
212 state->m_bMaster = (ulSlave == 0);
213
214 state->m_SettlingTime = ulSettlingTime;
215
216 state->m_bFMInput = (ulFMInput == 2);
217}
218
219static bool SearchMap1(struct SMap Map[],
220 u32 Frequency, u8 *pParam)
221{
222 int i = 0;
223
Oliver Endriss0fe44622011-07-03 13:37:31 -0300224 while ((Map[i].m_Frequency != 0) && (Frequency > Map[i].m_Frequency))
Ralph Metzlere8783952011-07-03 13:36:17 -0300225 i += 1;
226 if (Map[i].m_Frequency == 0)
227 return false;
228 *pParam = Map[i].m_Param;
229 return true;
230}
231
232static bool SearchMap2(struct SMapI Map[],
233 u32 Frequency, s32 *pParam)
234{
235 int i = 0;
236
237 while ((Map[i].m_Frequency != 0) &&
Oliver Endriss0fe44622011-07-03 13:37:31 -0300238 (Frequency > Map[i].m_Frequency))
Ralph Metzlere8783952011-07-03 13:36:17 -0300239 i += 1;
240 if (Map[i].m_Frequency == 0)
241 return false;
242 *pParam = Map[i].m_Param;
243 return true;
244}
245
Oliver Endriss0fe44622011-07-03 13:37:31 -0300246static bool SearchMap3(struct SMap2 Map[], u32 Frequency,
Ralph Metzlere8783952011-07-03 13:36:17 -0300247 u8 *pParam1, u8 *pParam2)
248{
249 int i = 0;
250
251 while ((Map[i].m_Frequency != 0) &&
Oliver Endriss0fe44622011-07-03 13:37:31 -0300252 (Frequency > Map[i].m_Frequency))
Ralph Metzlere8783952011-07-03 13:36:17 -0300253 i += 1;
254 if (Map[i].m_Frequency == 0)
255 return false;
256 *pParam1 = Map[i].m_Param1;
257 *pParam2 = Map[i].m_Param2;
258 return true;
259}
260
261static bool SearchMap4(struct SRFBandMap Map[],
262 u32 Frequency, u8 *pRFBand)
263{
264 int i = 0;
265
266 while (i < 7 && (Frequency > Map[i].m_RF_max))
267 i += 1;
268 if (i == 7)
269 return false;
270 *pRFBand = i;
271 return true;
272}
273
274static int ThermometerRead(struct tda_state *state, u8 *pTM_Value)
275{
276 int status = 0;
277
278 do {
279 u8 Regs[16];
280 state->m_Regs[TM] |= 0x10;
Mauro Carvalho Chehab469ffe02011-07-03 18:12:26 -0300281 status = UpdateReg(state, TM);
282 if (status < 0)
283 break;
284 status = Read(state, Regs);
285 if (status < 0)
286 break;
Oliver Endriss0fe44622011-07-03 13:37:31 -0300287 if (((Regs[TM] & 0x0F) == 0 && (Regs[TM] & 0x20) == 0x20) ||
288 ((Regs[TM] & 0x0F) == 8 && (Regs[TM] & 0x20) == 0x00)) {
Ralph Metzlere8783952011-07-03 13:36:17 -0300289 state->m_Regs[TM] ^= 0x20;
Mauro Carvalho Chehab469ffe02011-07-03 18:12:26 -0300290 status = UpdateReg(state, TM);
291 if (status < 0)
292 break;
Ralph Metzlere8783952011-07-03 13:36:17 -0300293 msleep(10);
Mauro Carvalho Chehab469ffe02011-07-03 18:12:26 -0300294 status = Read(state, Regs);
295 if (status < 0)
296 break;
Ralph Metzlere8783952011-07-03 13:36:17 -0300297 }
Oliver Endriss0fe44622011-07-03 13:37:31 -0300298 *pTM_Value = (Regs[TM] & 0x20)
299 ? m_Thermometer_Map_2[Regs[TM] & 0x0F]
300 : m_Thermometer_Map_1[Regs[TM] & 0x0F] ;
301 state->m_Regs[TM] &= ~0x10; /* Thermometer off */
Mauro Carvalho Chehab469ffe02011-07-03 18:12:26 -0300302 status = UpdateReg(state, TM);
303 if (status < 0)
304 break;
Oliver Endriss0fe44622011-07-03 13:37:31 -0300305 state->m_Regs[EP4] &= ~0x03; /* CAL_mode = 0 ????????? */
Mauro Carvalho Chehab469ffe02011-07-03 18:12:26 -0300306 status = UpdateReg(state, EP4);
307 if (status < 0)
308 break;
Oliver Endriss0fe44622011-07-03 13:37:31 -0300309 } while (0);
Ralph Metzlere8783952011-07-03 13:36:17 -0300310
311 return status;
312}
313
314static int StandBy(struct tda_state *state)
315{
316 int status = 0;
317 do {
Oliver Endriss0fe44622011-07-03 13:37:31 -0300318 state->m_Regs[EB12] &= ~0x20; /* PD_AGC1_Det = 0 */
Mauro Carvalho Chehab469ffe02011-07-03 18:12:26 -0300319 status = UpdateReg(state, EB12);
320 if (status < 0)
321 break;
Oliver Endriss0fe44622011-07-03 13:37:31 -0300322 state->m_Regs[EB18] &= ~0x83; /* AGC1_loop_off = 0, AGC1_Gain = 6 dB */
Mauro Carvalho Chehab469ffe02011-07-03 18:12:26 -0300323 status = UpdateReg(state, EB18);
324 if (status < 0)
325 break;
Oliver Endriss0fe44622011-07-03 13:37:31 -0300326 state->m_Regs[EB21] |= 0x03; /* AGC2_Gain = -6 dB */
Ralph Metzlere8783952011-07-03 13:36:17 -0300327 state->m_Regs[EP3] = state->m_EP3_Standby;
Mauro Carvalho Chehab469ffe02011-07-03 18:12:26 -0300328 status = UpdateReg(state, EP3);
329 if (status < 0)
330 break;
Oliver Endriss0fe44622011-07-03 13:37:31 -0300331 state->m_Regs[EB23] &= ~0x06; /* ForceLP_Fc2_En = 0, LP_Fc[2] = 0 */
Mauro Carvalho Chehab469ffe02011-07-03 18:12:26 -0300332 status = UpdateRegs(state, EB21, EB23);
333 if (status < 0)
334 break;
Oliver Endriss0fe44622011-07-03 13:37:31 -0300335 } while (0);
Ralph Metzlere8783952011-07-03 13:36:17 -0300336 return status;
337}
338
339static int CalcMainPLL(struct tda_state *state, u32 freq)
340{
341
342 u8 PostDiv;
343 u8 Div;
344 u64 OscFreq;
345 u32 MainDiv;
346
Oliver Endriss0fe44622011-07-03 13:37:31 -0300347 if (!SearchMap3(m_Main_PLL_Map, freq, &PostDiv, &Div))
Ralph Metzlere8783952011-07-03 13:36:17 -0300348 return -EINVAL;
Ralph Metzlere8783952011-07-03 13:36:17 -0300349
350 OscFreq = (u64) freq * (u64) Div;
351 OscFreq *= (u64) 16384;
352 do_div(OscFreq, (u64)16000000);
353 MainDiv = OscFreq;
354
355 state->m_Regs[MPD] = PostDiv & 0x77;
356 state->m_Regs[MD1] = ((MainDiv >> 16) & 0x7F);
357 state->m_Regs[MD2] = ((MainDiv >> 8) & 0xFF);
Oliver Endriss0fe44622011-07-03 13:37:31 -0300358 state->m_Regs[MD3] = (MainDiv & 0xFF);
Ralph Metzlere8783952011-07-03 13:36:17 -0300359
360 return UpdateRegs(state, MPD, MD3);
361}
362
363static int CalcCalPLL(struct tda_state *state, u32 freq)
364{
Ralph Metzlere8783952011-07-03 13:36:17 -0300365 u8 PostDiv;
366 u8 Div;
367 u64 OscFreq;
368 u32 CalDiv;
369
Oliver Endriss0fe44622011-07-03 13:37:31 -0300370 if (!SearchMap3(m_Cal_PLL_Map, freq, &PostDiv, &Div))
Ralph Metzlere8783952011-07-03 13:36:17 -0300371 return -EINVAL;
Ralph Metzlere8783952011-07-03 13:36:17 -0300372
373 OscFreq = (u64)freq * (u64)Div;
Oliver Endriss0fe44622011-07-03 13:37:31 -0300374 /* CalDiv = u32( OscFreq * 16384 / 16000000 ); */
375 OscFreq *= (u64)16384;
Ralph Metzlere8783952011-07-03 13:36:17 -0300376 do_div(OscFreq, (u64)16000000);
Oliver Endriss0fe44622011-07-03 13:37:31 -0300377 CalDiv = OscFreq;
Ralph Metzlere8783952011-07-03 13:36:17 -0300378
379 state->m_Regs[CPD] = PostDiv;
380 state->m_Regs[CD1] = ((CalDiv >> 16) & 0xFF);
381 state->m_Regs[CD2] = ((CalDiv >> 8) & 0xFF);
Oliver Endriss0fe44622011-07-03 13:37:31 -0300382 state->m_Regs[CD3] = (CalDiv & 0xFF);
Ralph Metzlere8783952011-07-03 13:36:17 -0300383
Oliver Endriss0fe44622011-07-03 13:37:31 -0300384 return UpdateRegs(state, CPD, CD3);
Ralph Metzlere8783952011-07-03 13:36:17 -0300385}
386
387static int CalibrateRF(struct tda_state *state,
Oliver Endriss0fe44622011-07-03 13:37:31 -0300388 u8 RFBand, u32 freq, s32 *pCprog)
Ralph Metzlere8783952011-07-03 13:36:17 -0300389{
Ralph Metzlere8783952011-07-03 13:36:17 -0300390 int status = 0;
391 u8 Regs[NUM_REGS];
392 do {
Oliver Endriss0fe44622011-07-03 13:37:31 -0300393 u8 BP_Filter = 0;
394 u8 GainTaper = 0;
395 u8 RFC_K = 0;
396 u8 RFC_M = 0;
Ralph Metzlere8783952011-07-03 13:36:17 -0300397
Oliver Endriss0fe44622011-07-03 13:37:31 -0300398 state->m_Regs[EP4] &= ~0x03; /* CAL_mode = 0 */
Mauro Carvalho Chehab469ffe02011-07-03 18:12:26 -0300399 status = UpdateReg(state, EP4);
400 if (status < 0)
401 break;
Oliver Endriss0fe44622011-07-03 13:37:31 -0300402 state->m_Regs[EB18] |= 0x03; /* AGC1_Gain = 3 */
Mauro Carvalho Chehab469ffe02011-07-03 18:12:26 -0300403 status = UpdateReg(state, EB18);
404 if (status < 0)
405 break;
Ralph Metzlere8783952011-07-03 13:36:17 -0300406
Oliver Endriss0fe44622011-07-03 13:37:31 -0300407 /* Switching off LT (as datasheet says) causes calibration on C1 to fail */
408 /* (Readout of Cprog is allways 255) */
409 if (state->m_Regs[ID] != 0x83) /* C1: ID == 83, C2: ID == 84 */
410 state->m_Regs[EP3] |= 0x40; /* SM_LT = 1 */
Ralph Metzlere8783952011-07-03 13:36:17 -0300411
Oliver Endriss0fe44622011-07-03 13:37:31 -0300412 if (!(SearchMap1(m_BP_Filter_Map, freq, &BP_Filter) &&
413 SearchMap1(m_GainTaper_Map, freq, &GainTaper) &&
414 SearchMap3(m_KM_Map, freq, &RFC_K, &RFC_M)))
Ralph Metzlere8783952011-07-03 13:36:17 -0300415 return -EINVAL;
Ralph Metzlere8783952011-07-03 13:36:17 -0300416
417 state->m_Regs[EP1] = (state->m_Regs[EP1] & ~0x07) | BP_Filter;
418 state->m_Regs[EP2] = (RFBand << 5) | GainTaper;
419
420 state->m_Regs[EB13] = (state->m_Regs[EB13] & ~0x7C) | (RFC_K << 4) | (RFC_M << 2);
421
Mauro Carvalho Chehab469ffe02011-07-03 18:12:26 -0300422 status = UpdateRegs(state, EP1, EP3);
423 if (status < 0)
424 break;
425 status = UpdateReg(state, EB13);
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[EB4] |= 0x20; /* LO_ForceSrce = 1 */
Mauro Carvalho Chehab469ffe02011-07-03 18:12:26 -0300430 status = UpdateReg(state, EB4);
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[EB7] |= 0x20; /* CAL_ForceSrce = 1 */
Mauro Carvalho Chehab469ffe02011-07-03 18:12:26 -0300435 status = UpdateReg(state, EB7);
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[EB14] = 0; /* RFC_Cprog = 0 */
Mauro Carvalho Chehab469ffe02011-07-03 18:12:26 -0300440 status = UpdateReg(state, EB14);
441 if (status < 0)
442 break;
Ralph Metzlere8783952011-07-03 13:36:17 -0300443
Oliver Endriss0fe44622011-07-03 13:37:31 -0300444 state->m_Regs[EB20] &= ~0x20; /* ForceLock = 0; */
Mauro Carvalho Chehab469ffe02011-07-03 18:12:26 -0300445 status = UpdateReg(state, EB20);
446 if (status < 0)
447 break;
Ralph Metzlere8783952011-07-03 13:36:17 -0300448
Oliver Endriss0fe44622011-07-03 13:37:31 -0300449 state->m_Regs[EP4] |= 0x03; /* CAL_Mode = 3 */
Mauro Carvalho Chehab469ffe02011-07-03 18:12:26 -0300450 status = UpdateRegs(state, EP4, EP5);
451 if (status < 0)
452 break;
Ralph Metzlere8783952011-07-03 13:36:17 -0300453
Mauro Carvalho Chehab469ffe02011-07-03 18:12:26 -0300454 status = CalcCalPLL(state, freq);
455 if (status < 0)
456 break;
457 status = CalcMainPLL(state, freq + 1000000);
458 if (status < 0)
459 break;
Ralph Metzlere8783952011-07-03 13:36:17 -0300460
461 msleep(5);
Mauro Carvalho Chehab469ffe02011-07-03 18:12:26 -0300462 status = UpdateReg(state, EP2);
463 if (status < 0)
464 break;
465 status = UpdateReg(state, EP1);
466 if (status < 0)
467 break;
468 status = UpdateReg(state, EP2);
469 if (status < 0)
470 break;
471 status = UpdateReg(state, EP1);
472 if (status < 0)
473 break;
Ralph Metzlere8783952011-07-03 13:36:17 -0300474
Oliver Endriss0fe44622011-07-03 13:37:31 -0300475 state->m_Regs[EB4] &= ~0x20; /* LO_ForceSrce = 0 */
Mauro Carvalho Chehab469ffe02011-07-03 18:12:26 -0300476 status = UpdateReg(state, EB4);
477 if (status < 0)
478 break;
Ralph Metzlere8783952011-07-03 13:36:17 -0300479
Oliver Endriss0fe44622011-07-03 13:37:31 -0300480 state->m_Regs[EB7] &= ~0x20; /* CAL_ForceSrce = 0 */
Mauro Carvalho Chehab469ffe02011-07-03 18:12:26 -0300481 status = UpdateReg(state, EB7);
482 if (status < 0)
483 break;
Ralph Metzlere8783952011-07-03 13:36:17 -0300484 msleep(10);
485
Oliver Endriss0fe44622011-07-03 13:37:31 -0300486 state->m_Regs[EB20] |= 0x20; /* ForceLock = 1; */
Mauro Carvalho Chehab469ffe02011-07-03 18:12:26 -0300487 status = UpdateReg(state, EB20);
488 if (status < 0)
489 break;
Ralph Metzlere8783952011-07-03 13:36:17 -0300490 msleep(60);
491
Oliver Endriss0fe44622011-07-03 13:37:31 -0300492 state->m_Regs[EP4] &= ~0x03; /* CAL_Mode = 0 */
493 state->m_Regs[EP3] &= ~0x40; /* SM_LT = 0 */
494 state->m_Regs[EB18] &= ~0x03; /* AGC1_Gain = 0 */
Mauro Carvalho Chehab469ffe02011-07-03 18:12:26 -0300495 status = UpdateReg(state, EB18);
496 if (status < 0)
497 break;
498 status = UpdateRegs(state, EP3, EP4);
499 if (status < 0)
500 break;
501 status = UpdateReg(state, EP1);
502 if (status < 0)
503 break;
Ralph Metzlere8783952011-07-03 13:36:17 -0300504
Mauro Carvalho Chehab469ffe02011-07-03 18:12:26 -0300505 status = ReadExtented(state, Regs);
506 if (status < 0)
507 break;
Ralph Metzlere8783952011-07-03 13:36:17 -0300508
509 *pCprog = Regs[EB14];
Ralph Metzlere8783952011-07-03 13:36:17 -0300510
Oliver Endriss0fe44622011-07-03 13:37:31 -0300511 } while (0);
Ralph Metzlere8783952011-07-03 13:36:17 -0300512 return status;
513}
514
515static int RFTrackingFiltersInit(struct tda_state *state,
516 u8 RFBand)
517{
Ralph Metzlere8783952011-07-03 13:36:17 -0300518 int status = 0;
519
520 u32 RF1 = m_RF_Band_Map[RFBand].m_RF1_Default;
521 u32 RF2 = m_RF_Band_Map[RFBand].m_RF2_Default;
522 u32 RF3 = m_RF_Band_Map[RFBand].m_RF3_Default;
523 bool bcal = false;
524
525 s32 Cprog_cal1 = 0;
526 s32 Cprog_table1 = 0;
527 s32 Cprog_cal2 = 0;
528 s32 Cprog_table2 = 0;
529 s32 Cprog_cal3 = 0;
530 s32 Cprog_table3 = 0;
531
532 state->m_RF_A1[RFBand] = 0;
533 state->m_RF_B1[RFBand] = 0;
534 state->m_RF_A2[RFBand] = 0;
535 state->m_RF_B2[RFBand] = 0;
536
537 do {
Mauro Carvalho Chehab469ffe02011-07-03 18:12:26 -0300538 status = PowerScan(state, RFBand, RF1, &RF1, &bcal);
539 if (status < 0)
540 break;
Oliver Endriss0fe44622011-07-03 13:37:31 -0300541 if (bcal) {
Mauro Carvalho Chehab469ffe02011-07-03 18:12:26 -0300542 status = CalibrateRF(state, RFBand, RF1, &Cprog_cal1);
543 if (status < 0)
544 break;
Ralph Metzlere8783952011-07-03 13:36:17 -0300545 }
Oliver Endriss0fe44622011-07-03 13:37:31 -0300546 SearchMap2(m_RF_Cal_Map, RF1, &Cprog_table1);
547 if (!bcal)
Ralph Metzlere8783952011-07-03 13:36:17 -0300548 Cprog_cal1 = Cprog_table1;
Ralph Metzlere8783952011-07-03 13:36:17 -0300549 state->m_RF_B1[RFBand] = Cprog_cal1 - Cprog_table1;
Oliver Endriss0fe44622011-07-03 13:37:31 -0300550 /* state->m_RF_A1[RF_Band] = ???? */
Ralph Metzlere8783952011-07-03 13:36:17 -0300551
Oliver Endriss0fe44622011-07-03 13:37:31 -0300552 if (RF2 == 0)
553 break;
Ralph Metzlere8783952011-07-03 13:36:17 -0300554
Mauro Carvalho Chehab469ffe02011-07-03 18:12:26 -0300555 status = PowerScan(state, RFBand, RF2, &RF2, &bcal);
556 if (status < 0)
557 break;
Oliver Endriss0fe44622011-07-03 13:37:31 -0300558 if (bcal) {
Mauro Carvalho Chehab469ffe02011-07-03 18:12:26 -0300559 status = CalibrateRF(state, RFBand, RF2, &Cprog_cal2);
560 if (status < 0)
561 break;
Ralph Metzlere8783952011-07-03 13:36:17 -0300562 }
Oliver Endriss0fe44622011-07-03 13:37:31 -0300563 SearchMap2(m_RF_Cal_Map, RF2, &Cprog_table2);
564 if (!bcal)
Ralph Metzlere8783952011-07-03 13:36:17 -0300565 Cprog_cal2 = Cprog_table2;
Ralph Metzlere8783952011-07-03 13:36:17 -0300566
567 state->m_RF_A1[RFBand] =
568 (Cprog_cal2 - Cprog_table2 - Cprog_cal1 + Cprog_table1) /
Oliver Endriss0fe44622011-07-03 13:37:31 -0300569 ((s32)(RF2) - (s32)(RF1));
Ralph Metzlere8783952011-07-03 13:36:17 -0300570
Oliver Endriss0fe44622011-07-03 13:37:31 -0300571 if (RF3 == 0)
572 break;
Ralph Metzlere8783952011-07-03 13:36:17 -0300573
Mauro Carvalho Chehab469ffe02011-07-03 18:12:26 -0300574 status = PowerScan(state, RFBand, RF3, &RF3, &bcal);
575 if (status < 0)
576 break;
Oliver Endriss0fe44622011-07-03 13:37:31 -0300577 if (bcal) {
Mauro Carvalho Chehab469ffe02011-07-03 18:12:26 -0300578 status = CalibrateRF(state, RFBand, RF3, &Cprog_cal3);
579 if (status < 0)
580 break;
Ralph Metzlere8783952011-07-03 13:36:17 -0300581 }
Oliver Endriss0fe44622011-07-03 13:37:31 -0300582 SearchMap2(m_RF_Cal_Map, RF3, &Cprog_table3);
583 if (!bcal)
Ralph Metzlere8783952011-07-03 13:36:17 -0300584 Cprog_cal3 = Cprog_table3;
Oliver Endriss0fe44622011-07-03 13:37:31 -0300585 state->m_RF_A2[RFBand] = (Cprog_cal3 - Cprog_table3 - Cprog_cal2 + Cprog_table2) / ((s32)(RF3) - (s32)(RF2));
Ralph Metzlere8783952011-07-03 13:36:17 -0300586 state->m_RF_B2[RFBand] = Cprog_cal2 - Cprog_table2;
587
Oliver Endriss0fe44622011-07-03 13:37:31 -0300588 } while (0);
Ralph Metzlere8783952011-07-03 13:36:17 -0300589
590 state->m_RF1[RFBand] = RF1;
591 state->m_RF2[RFBand] = RF2;
592 state->m_RF3[RFBand] = RF3;
593
594#if 0
Mauro Carvalho Chehabf3d40bd2011-07-04 14:00:25 -0300595 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 -0300596 RFBand, RF1, state->m_RF_A1[RFBand], state->m_RF_B1[RFBand], RF2,
597 state->m_RF_A2[RFBand], state->m_RF_B2[RFBand], RF3);
Ralph Metzlere8783952011-07-03 13:36:17 -0300598#endif
599
600 return status;
601}
602
603static int PowerScan(struct tda_state *state,
Oliver Endriss0fe44622011-07-03 13:37:31 -0300604 u8 RFBand, u32 RF_in, u32 *pRF_Out, bool *pbcal)
Ralph Metzlere8783952011-07-03 13:36:17 -0300605{
Oliver Endriss0fe44622011-07-03 13:37:31 -0300606 int status = 0;
607 do {
608 u8 Gain_Taper = 0;
609 s32 RFC_Cprog = 0;
610 u8 CID_Target = 0;
611 u8 CountLimit = 0;
612 u32 freq_MainPLL;
613 u8 Regs[NUM_REGS];
614 u8 CID_Gain;
615 s32 Count = 0;
616 int sign = 1;
617 bool wait = false;
Ralph Metzlere8783952011-07-03 13:36:17 -0300618
Oliver Endriss0fe44622011-07-03 13:37:31 -0300619 if (!(SearchMap2(m_RF_Cal_Map, RF_in, &RFC_Cprog) &&
620 SearchMap1(m_GainTaper_Map, RF_in, &Gain_Taper) &&
621 SearchMap3(m_CID_Target_Map, RF_in, &CID_Target, &CountLimit))) {
Ralph Metzlere8783952011-07-03 13:36:17 -0300622
Mauro Carvalho Chehabf3d40bd2011-07-04 14:00:25 -0300623 printk(KERN_ERR "tda18271c2dd: %s Search map failed\n", __func__);
Oliver Endriss0fe44622011-07-03 13:37:31 -0300624 return -EINVAL;
625 }
Ralph Metzlere8783952011-07-03 13:36:17 -0300626
Oliver Endriss0fe44622011-07-03 13:37:31 -0300627 state->m_Regs[EP2] = (RFBand << 5) | Gain_Taper;
628 state->m_Regs[EB14] = (RFC_Cprog);
Mauro Carvalho Chehab469ffe02011-07-03 18:12:26 -0300629 status = UpdateReg(state, EP2);
630 if (status < 0)
631 break;
632 status = UpdateReg(state, EB14);
633 if (status < 0)
634 break;
Ralph Metzlere8783952011-07-03 13:36:17 -0300635
Oliver Endriss0fe44622011-07-03 13:37:31 -0300636 freq_MainPLL = RF_in + 1000000;
Mauro Carvalho Chehab469ffe02011-07-03 18:12:26 -0300637 status = CalcMainPLL(state, freq_MainPLL);
638 if (status < 0)
639 break;
Oliver Endriss0fe44622011-07-03 13:37:31 -0300640 msleep(5);
641 state->m_Regs[EP4] = (state->m_Regs[EP4] & ~0x03) | 1; /* CAL_mode = 1 */
Mauro Carvalho Chehab469ffe02011-07-03 18:12:26 -0300642 status = UpdateReg(state, EP4);
643 if (status < 0)
644 break;
645 status = UpdateReg(state, EP2); /* Launch power measurement */
646 if (status < 0)
647 break;
648 status = ReadExtented(state, Regs);
649 if (status < 0)
650 break;
Oliver Endriss0fe44622011-07-03 13:37:31 -0300651 CID_Gain = Regs[EB10] & 0x3F;
652 state->m_Regs[ID] = Regs[ID]; /* Chip version, (needed for C1 workarround in CalibrateRF) */
Ralph Metzlere8783952011-07-03 13:36:17 -0300653
Oliver Endriss0fe44622011-07-03 13:37:31 -0300654 *pRF_Out = RF_in;
Ralph Metzlere8783952011-07-03 13:36:17 -0300655
Oliver Endriss0fe44622011-07-03 13:37:31 -0300656 while (CID_Gain < CID_Target) {
657 freq_MainPLL = RF_in + sign * Count + 1000000;
Mauro Carvalho Chehab469ffe02011-07-03 18:12:26 -0300658 status = CalcMainPLL(state, freq_MainPLL);
659 if (status < 0)
660 break;
Oliver Endriss0fe44622011-07-03 13:37:31 -0300661 msleep(wait ? 5 : 1);
662 wait = false;
Mauro Carvalho Chehab469ffe02011-07-03 18:12:26 -0300663 status = UpdateReg(state, EP2); /* Launch power measurement */
664 if (status < 0)
665 break;
666 status = ReadExtented(state, Regs);
667 if (status < 0)
668 break;
Oliver Endriss0fe44622011-07-03 13:37:31 -0300669 CID_Gain = Regs[EB10] & 0x3F;
670 Count += 200000;
Ralph Metzlere8783952011-07-03 13:36:17 -0300671
Oliver Endriss0fe44622011-07-03 13:37:31 -0300672 if (Count < CountLimit * 100000)
673 continue;
674 if (sign < 0)
675 break;
676
677 sign = -sign;
678 Count = 200000;
679 wait = true;
680 }
Mauro Carvalho Chehab469ffe02011-07-03 18:12:26 -0300681 status = status;
682 if (status < 0)
683 break;
Oliver Endriss0fe44622011-07-03 13:37:31 -0300684 if (CID_Gain >= CID_Target) {
685 *pbcal = true;
686 *pRF_Out = freq_MainPLL - 1000000;
687 } else
688 *pbcal = false;
689 } while (0);
690
691 return status;
Ralph Metzlere8783952011-07-03 13:36:17 -0300692}
693
694static int PowerScanInit(struct tda_state *state)
695{
Ralph Metzlere8783952011-07-03 13:36:17 -0300696 int status = 0;
Oliver Endriss0fe44622011-07-03 13:37:31 -0300697 do {
Ralph Metzlere8783952011-07-03 13:36:17 -0300698 state->m_Regs[EP3] = (state->m_Regs[EP3] & ~0x1F) | 0x12;
Oliver Endriss0fe44622011-07-03 13:37:31 -0300699 state->m_Regs[EP4] = (state->m_Regs[EP4] & ~0x1F); /* If level = 0, Cal mode = 0 */
Mauro Carvalho Chehab469ffe02011-07-03 18:12:26 -0300700 status = UpdateRegs(state, EP3, EP4);
701 if (status < 0)
702 break;
Oliver Endriss0fe44622011-07-03 13:37:31 -0300703 state->m_Regs[EB18] = (state->m_Regs[EB18] & ~0x03); /* AGC 1 Gain = 0 */
Mauro Carvalho Chehab469ffe02011-07-03 18:12:26 -0300704 status = UpdateReg(state, EB18);
705 if (status < 0)
706 break;
Oliver Endriss0fe44622011-07-03 13:37:31 -0300707 state->m_Regs[EB21] = (state->m_Regs[EB21] & ~0x03); /* AGC 2 Gain = 0 (Datasheet = 3) */
708 state->m_Regs[EB23] = (state->m_Regs[EB23] | 0x06); /* ForceLP_Fc2_En = 1, LPFc[2] = 1 */
Mauro Carvalho Chehab469ffe02011-07-03 18:12:26 -0300709 status = UpdateRegs(state, EB21, EB23);
710 if (status < 0)
711 break;
Oliver Endriss0fe44622011-07-03 13:37:31 -0300712 } while (0);
Ralph Metzlere8783952011-07-03 13:36:17 -0300713 return status;
714}
715
716static int CalcRFFilterCurve(struct tda_state *state)
717{
Ralph Metzlere8783952011-07-03 13:36:17 -0300718 int status = 0;
Oliver Endriss0fe44622011-07-03 13:37:31 -0300719 do {
720 msleep(200); /* Temperature stabilisation */
Mauro Carvalho Chehab469ffe02011-07-03 18:12:26 -0300721 status = PowerScanInit(state);
722 if (status < 0)
723 break;
724 status = RFTrackingFiltersInit(state, 0);
725 if (status < 0)
726 break;
727 status = RFTrackingFiltersInit(state, 1);
728 if (status < 0)
729 break;
730 status = RFTrackingFiltersInit(state, 2);
731 if (status < 0)
732 break;
733 status = RFTrackingFiltersInit(state, 3);
734 if (status < 0)
735 break;
736 status = RFTrackingFiltersInit(state, 4);
737 if (status < 0)
738 break;
739 status = RFTrackingFiltersInit(state, 5);
740 if (status < 0)
741 break;
742 status = RFTrackingFiltersInit(state, 6);
743 if (status < 0)
744 break;
745 status = ThermometerRead(state, &state->m_TMValue_RFCal); /* also switches off Cal mode !!! */
746 if (status < 0)
747 break;
Oliver Endriss0fe44622011-07-03 13:37:31 -0300748 } while (0);
Ralph Metzlere8783952011-07-03 13:36:17 -0300749
750 return status;
751}
752
753static int FixedContentsI2CUpdate(struct tda_state *state)
754{
755 static u8 InitRegs[] = {
Oliver Endriss0fe44622011-07-03 13:37:31 -0300756 0x08, 0x80, 0xC6,
757 0xDF, 0x16, 0x60, 0x80,
758 0x80, 0x00, 0x00, 0x00,
759 0x00, 0x00, 0x00, 0x00,
760 0xFC, 0x01, 0x84, 0x41,
761 0x01, 0x84, 0x40, 0x07,
762 0x00, 0x00, 0x96, 0x3F,
763 0xC1, 0x00, 0x8F, 0x00,
764 0x00, 0x8C, 0x00, 0x20,
765 0xB3, 0x48, 0xB0,
Ralph Metzlere8783952011-07-03 13:36:17 -0300766 };
767 int status = 0;
Oliver Endriss0fe44622011-07-03 13:37:31 -0300768 memcpy(&state->m_Regs[TM], InitRegs, EB23 - TM + 1);
Ralph Metzlere8783952011-07-03 13:36:17 -0300769 do {
Mauro Carvalho Chehab469ffe02011-07-03 18:12:26 -0300770 status = UpdateRegs(state, TM, EB23);
771 if (status < 0)
772 break;
Ralph Metzlere8783952011-07-03 13:36:17 -0300773
Oliver Endriss0fe44622011-07-03 13:37:31 -0300774 /* AGC1 gain setup */
Ralph Metzlere8783952011-07-03 13:36:17 -0300775 state->m_Regs[EB17] = 0x00;
Mauro Carvalho Chehab469ffe02011-07-03 18:12:26 -0300776 status = UpdateReg(state, EB17);
777 if (status < 0)
778 break;
Ralph Metzlere8783952011-07-03 13:36:17 -0300779 state->m_Regs[EB17] = 0x03;
Mauro Carvalho Chehab469ffe02011-07-03 18:12:26 -0300780 status = UpdateReg(state, EB17);
781 if (status < 0)
782 break;
Ralph Metzlere8783952011-07-03 13:36:17 -0300783 state->m_Regs[EB17] = 0x43;
Mauro Carvalho Chehab469ffe02011-07-03 18:12:26 -0300784 status = UpdateReg(state, EB17);
785 if (status < 0)
786 break;
Ralph Metzlere8783952011-07-03 13:36:17 -0300787 state->m_Regs[EB17] = 0x4C;
Mauro Carvalho Chehab469ffe02011-07-03 18:12:26 -0300788 status = UpdateReg(state, EB17);
789 if (status < 0)
790 break;
Ralph Metzlere8783952011-07-03 13:36:17 -0300791
Oliver Endriss0fe44622011-07-03 13:37:31 -0300792 /* IRC Cal Low band */
Ralph Metzlere8783952011-07-03 13:36:17 -0300793 state->m_Regs[EP3] = 0x1F;
794 state->m_Regs[EP4] = 0x66;
795 state->m_Regs[EP5] = 0x81;
796 state->m_Regs[CPD] = 0xCC;
797 state->m_Regs[CD1] = 0x6C;
798 state->m_Regs[CD2] = 0x00;
799 state->m_Regs[CD3] = 0x00;
800 state->m_Regs[MPD] = 0xC5;
801 state->m_Regs[MD1] = 0x77;
802 state->m_Regs[MD2] = 0x08;
803 state->m_Regs[MD3] = 0x00;
Mauro Carvalho Chehab469ffe02011-07-03 18:12:26 -0300804 status = UpdateRegs(state, EP2, MD3); /* diff between sw and datasheet (ep3-md3) */
805 if (status < 0)
806 break;
Ralph Metzlere8783952011-07-03 13:36:17 -0300807
Oliver Endriss0fe44622011-07-03 13:37:31 -0300808#if 0
809 state->m_Regs[EB4] = 0x61; /* missing in sw */
Mauro Carvalho Chehab469ffe02011-07-03 18:12:26 -0300810 status = UpdateReg(state, EB4);
811 if (status < 0)
812 break;
Oliver Endriss0fe44622011-07-03 13:37:31 -0300813 msleep(1);
814 state->m_Regs[EB4] = 0x41;
Mauro Carvalho Chehab469ffe02011-07-03 18:12:26 -0300815 status = UpdateReg(state, EB4);
816 if (status < 0)
817 break;
Oliver Endriss0fe44622011-07-03 13:37:31 -0300818#endif
Ralph Metzlere8783952011-07-03 13:36:17 -0300819
820 msleep(5);
Mauro Carvalho Chehab469ffe02011-07-03 18:12:26 -0300821 status = UpdateReg(state, EP1);
822 if (status < 0)
823 break;
Ralph Metzlere8783952011-07-03 13:36:17 -0300824 msleep(5);
825
826 state->m_Regs[EP5] = 0x85;
827 state->m_Regs[CPD] = 0xCB;
828 state->m_Regs[CD1] = 0x66;
829 state->m_Regs[CD2] = 0x70;
Mauro Carvalho Chehab469ffe02011-07-03 18:12:26 -0300830 status = UpdateRegs(state, EP3, CD3);
831 if (status < 0)
832 break;
Ralph Metzlere8783952011-07-03 13:36:17 -0300833 msleep(5);
Mauro Carvalho Chehab469ffe02011-07-03 18:12:26 -0300834 status = UpdateReg(state, EP2);
835 if (status < 0)
836 break;
Ralph Metzlere8783952011-07-03 13:36:17 -0300837 msleep(30);
838
Oliver Endriss0fe44622011-07-03 13:37:31 -0300839 /* IRC Cal mid band */
Ralph Metzlere8783952011-07-03 13:36:17 -0300840 state->m_Regs[EP5] = 0x82;
841 state->m_Regs[CPD] = 0xA8;
842 state->m_Regs[CD2] = 0x00;
Oliver Endriss0fe44622011-07-03 13:37:31 -0300843 state->m_Regs[MPD] = 0xA1; /* Datasheet = 0xA9 */
Ralph Metzlere8783952011-07-03 13:36:17 -0300844 state->m_Regs[MD1] = 0x73;
845 state->m_Regs[MD2] = 0x1A;
Mauro Carvalho Chehab469ffe02011-07-03 18:12:26 -0300846 status = UpdateRegs(state, EP3, MD3);
847 if (status < 0)
848 break;
Ralph Metzlere8783952011-07-03 13:36:17 -0300849
850 msleep(5);
Mauro Carvalho Chehab469ffe02011-07-03 18:12:26 -0300851 status = UpdateReg(state, EP1);
852 if (status < 0)
853 break;
Ralph Metzlere8783952011-07-03 13:36:17 -0300854 msleep(5);
855
856 state->m_Regs[EP5] = 0x86;
857 state->m_Regs[CPD] = 0xA8;
858 state->m_Regs[CD1] = 0x66;
859 state->m_Regs[CD2] = 0xA0;
Mauro Carvalho Chehab469ffe02011-07-03 18:12:26 -0300860 status = UpdateRegs(state, EP3, CD3);
861 if (status < 0)
862 break;
Ralph Metzlere8783952011-07-03 13:36:17 -0300863 msleep(5);
Mauro Carvalho Chehab469ffe02011-07-03 18:12:26 -0300864 status = UpdateReg(state, EP2);
865 if (status < 0)
866 break;
Ralph Metzlere8783952011-07-03 13:36:17 -0300867 msleep(30);
868
Oliver Endriss0fe44622011-07-03 13:37:31 -0300869 /* IRC Cal high band */
Ralph Metzlere8783952011-07-03 13:36:17 -0300870 state->m_Regs[EP5] = 0x83;
871 state->m_Regs[CPD] = 0x98;
872 state->m_Regs[CD1] = 0x65;
873 state->m_Regs[CD2] = 0x00;
Oliver Endriss0fe44622011-07-03 13:37:31 -0300874 state->m_Regs[MPD] = 0x91; /* Datasheet = 0x91 */
Ralph Metzlere8783952011-07-03 13:36:17 -0300875 state->m_Regs[MD1] = 0x71;
876 state->m_Regs[MD2] = 0xCD;
Mauro Carvalho Chehab469ffe02011-07-03 18:12:26 -0300877 status = UpdateRegs(state, EP3, MD3);
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, EP1);
882 if (status < 0)
883 break;
Ralph Metzlere8783952011-07-03 13:36:17 -0300884 msleep(5);
885 state->m_Regs[EP5] = 0x87;
886 state->m_Regs[CD1] = 0x65;
887 state->m_Regs[CD2] = 0x50;
Mauro Carvalho Chehab469ffe02011-07-03 18:12:26 -0300888 status = UpdateRegs(state, EP3, CD3);
889 if (status < 0)
890 break;
Ralph Metzlere8783952011-07-03 13:36:17 -0300891 msleep(5);
Mauro Carvalho Chehab469ffe02011-07-03 18:12:26 -0300892 status = UpdateReg(state, EP2);
893 if (status < 0)
894 break;
Ralph Metzlere8783952011-07-03 13:36:17 -0300895 msleep(30);
896
Oliver Endriss0fe44622011-07-03 13:37:31 -0300897 /* Back to normal */
Ralph Metzlere8783952011-07-03 13:36:17 -0300898 state->m_Regs[EP4] = 0x64;
Mauro Carvalho Chehab469ffe02011-07-03 18:12:26 -0300899 status = UpdateReg(state, EP4);
900 if (status < 0)
901 break;
902 status = UpdateReg(state, EP1);
903 if (status < 0)
904 break;
Ralph Metzlere8783952011-07-03 13:36:17 -0300905
Oliver Endriss0fe44622011-07-03 13:37:31 -0300906 } while (0);
Ralph Metzlere8783952011-07-03 13:36:17 -0300907 return status;
908}
909
910static int InitCal(struct tda_state *state)
911{
912 int status = 0;
913
Oliver Endriss0fe44622011-07-03 13:37:31 -0300914 do {
Mauro Carvalho Chehab469ffe02011-07-03 18:12:26 -0300915 status = FixedContentsI2CUpdate(state);
916 if (status < 0)
917 break;
918 status = CalcRFFilterCurve(state);
919 if (status < 0)
920 break;
921 status = StandBy(state);
922 if (status < 0)
923 break;
Oliver Endriss0fe44622011-07-03 13:37:31 -0300924 /* m_bInitDone = true; */
925 } while (0);
Ralph Metzlere8783952011-07-03 13:36:17 -0300926 return status;
927};
928
929static int RFTrackingFiltersCorrection(struct tda_state *state,
930 u32 Frequency)
931{
932 int status = 0;
933 s32 Cprog_table;
934 u8 RFBand;
935 u8 dCoverdT;
936
Oliver Endriss0fe44622011-07-03 13:37:31 -0300937 if (!SearchMap2(m_RF_Cal_Map, Frequency, &Cprog_table) ||
938 !SearchMap4(m_RF_Band_Map, Frequency, &RFBand) ||
939 !SearchMap1(m_RF_Cal_DC_Over_DT_Map, Frequency, &dCoverdT))
Ralph Metzlere8783952011-07-03 13:36:17 -0300940
Oliver Endriss0fe44622011-07-03 13:37:31 -0300941 return -EINVAL;
942
943 do {
Ralph Metzlere8783952011-07-03 13:36:17 -0300944 u8 TMValue_Current;
945 u32 RF1 = state->m_RF1[RFBand];
946 u32 RF2 = state->m_RF1[RFBand];
947 u32 RF3 = state->m_RF1[RFBand];
948 s32 RF_A1 = state->m_RF_A1[RFBand];
949 s32 RF_B1 = state->m_RF_B1[RFBand];
950 s32 RF_A2 = state->m_RF_A2[RFBand];
951 s32 RF_B2 = state->m_RF_B2[RFBand];
952 s32 Capprox = 0;
953 int TComp;
954
Oliver Endriss0fe44622011-07-03 13:37:31 -0300955 state->m_Regs[EP3] &= ~0xE0; /* Power up */
Mauro Carvalho Chehab469ffe02011-07-03 18:12:26 -0300956 status = UpdateReg(state, EP3);
957 if (status < 0)
958 break;
Ralph Metzlere8783952011-07-03 13:36:17 -0300959
Mauro Carvalho Chehab469ffe02011-07-03 18:12:26 -0300960 status = ThermometerRead(state, &TMValue_Current);
961 if (status < 0)
962 break;
Ralph Metzlere8783952011-07-03 13:36:17 -0300963
Oliver Endriss0fe44622011-07-03 13:37:31 -0300964 if (RF3 == 0 || Frequency < RF2)
Ralph Metzlere8783952011-07-03 13:36:17 -0300965 Capprox = RF_A1 * ((s32)(Frequency) - (s32)(RF1)) + RF_B1 + Cprog_table;
Ralph Metzlere8783952011-07-03 13:36:17 -0300966 else
Ralph Metzlere8783952011-07-03 13:36:17 -0300967 Capprox = RF_A2 * ((s32)(Frequency) - (s32)(RF2)) + RF_B2 + Cprog_table;
Ralph Metzlere8783952011-07-03 13:36:17 -0300968
969 TComp = (int)(dCoverdT) * ((int)(TMValue_Current) - (int)(state->m_TMValue_RFCal))/1000;
970
971 Capprox += TComp;
972
Oliver Endriss0fe44622011-07-03 13:37:31 -0300973 if (Capprox < 0)
974 Capprox = 0;
975 else if (Capprox > 255)
976 Capprox = 255;
Ralph Metzlere8783952011-07-03 13:36:17 -0300977
978
Oliver Endriss0fe44622011-07-03 13:37:31 -0300979 /* TODO Temperature compensation. There is defenitely a scale factor */
980 /* missing in the datasheet, so leave it out for now. */
981 state->m_Regs[EB14] = Capprox;
Ralph Metzlere8783952011-07-03 13:36:17 -0300982
Mauro Carvalho Chehab469ffe02011-07-03 18:12:26 -0300983 status = UpdateReg(state, EB14);
984 if (status < 0)
985 break;
Ralph Metzlere8783952011-07-03 13:36:17 -0300986
Oliver Endriss0fe44622011-07-03 13:37:31 -0300987 } while (0);
Ralph Metzlere8783952011-07-03 13:36:17 -0300988 return status;
989}
990
991static int ChannelConfiguration(struct tda_state *state,
992 u32 Frequency, int Standard)
993{
994
995 s32 IntermediateFrequency = m_StandardTable[Standard].m_IFFrequency;
996 int status = 0;
997
998 u8 BP_Filter = 0;
999 u8 RF_Band = 0;
1000 u8 GainTaper = 0;
Mauro Carvalho Chehabea90f012011-07-03 18:06:07 -03001001 u8 IR_Meas = 0;
Ralph Metzlere8783952011-07-03 13:36:17 -03001002
Oliver Endriss0fe44622011-07-03 13:37:31 -03001003 state->IF = IntermediateFrequency;
Mauro Carvalho Chehabf3d40bd2011-07-04 14:00:25 -03001004 /* printk("tda18271c2dd: %s Freq = %d Standard = %d IF = %d\n", __func__, Frequency, Standard, IntermediateFrequency); */
Oliver Endriss0fe44622011-07-03 13:37:31 -03001005 /* get values from tables */
Ralph Metzlere8783952011-07-03 13:36:17 -03001006
Oliver Endriss0fe44622011-07-03 13:37:31 -03001007 if (!(SearchMap1(m_BP_Filter_Map, Frequency, &BP_Filter) &&
1008 SearchMap1(m_GainTaper_Map, Frequency, &GainTaper) &&
1009 SearchMap1(m_IR_Meas_Map, Frequency, &IR_Meas) &&
1010 SearchMap4(m_RF_Band_Map, Frequency, &RF_Band))) {
1011
Mauro Carvalho Chehabf3d40bd2011-07-04 14:00:25 -03001012 printk(KERN_ERR "tda18271c2dd: %s SearchMap failed\n", __func__);
Ralph Metzlere8783952011-07-03 13:36:17 -03001013 return -EINVAL;
1014 }
1015
Oliver Endriss0fe44622011-07-03 13:37:31 -03001016 do {
Ralph Metzlere8783952011-07-03 13:36:17 -03001017 state->m_Regs[EP3] = (state->m_Regs[EP3] & ~0x1F) | m_StandardTable[Standard].m_EP3_4_0;
Oliver Endriss0fe44622011-07-03 13:37:31 -03001018 state->m_Regs[EP3] &= ~0x04; /* switch RFAGC to high speed mode */
Ralph Metzlere8783952011-07-03 13:36:17 -03001019
Oliver Endriss0fe44622011-07-03 13:37:31 -03001020 /* m_EP4 default for XToutOn, CAL_Mode (0) */
1021 state->m_Regs[EP4] = state->m_EP4 | ((Standard > HF_AnalogMax) ? state->m_IFLevelDigital : state->m_IFLevelAnalog);
1022 /* state->m_Regs[EP4] = state->m_EP4 | state->m_IFLevelDigital; */
1023 if (Standard <= HF_AnalogMax)
1024 state->m_Regs[EP4] = state->m_EP4 | state->m_IFLevelAnalog;
1025 else if (Standard <= HF_ATSC)
1026 state->m_Regs[EP4] = state->m_EP4 | state->m_IFLevelDVBT;
1027 else if (Standard <= HF_DVBC)
1028 state->m_Regs[EP4] = state->m_EP4 | state->m_IFLevelDVBC;
1029 else
1030 state->m_Regs[EP4] = state->m_EP4 | state->m_IFLevelDigital;
Ralph Metzlere8783952011-07-03 13:36:17 -03001031
Oliver Endriss0fe44622011-07-03 13:37:31 -03001032 if ((Standard == HF_FM_Radio) && state->m_bFMInput)
Dan Carpenter58632812014-02-06 04:49:47 -03001033 state->m_Regs[EP4] |= 0x80;
Ralph Metzlere8783952011-07-03 13:36:17 -03001034
1035 state->m_Regs[MPD] &= ~0x80;
Oliver Endriss0fe44622011-07-03 13:37:31 -03001036 if (Standard > HF_AnalogMax)
1037 state->m_Regs[MPD] |= 0x80; /* Add IF_notch for digital */
Ralph Metzlere8783952011-07-03 13:36:17 -03001038
1039 state->m_Regs[EB22] = m_StandardTable[Standard].m_EB22;
1040
Oliver Endriss0fe44622011-07-03 13:37:31 -03001041 /* Note: This is missing from flowchart in TDA18271 specification ( 1.5 MHz cutoff for FM ) */
1042 if (Standard == HF_FM_Radio)
1043 state->m_Regs[EB23] |= 0x06; /* ForceLP_Fc2_En = 1, LPFc[2] = 1 */
1044 else
1045 state->m_Regs[EB23] &= ~0x06; /* ForceLP_Fc2_En = 0, LPFc[2] = 0 */
Ralph Metzlere8783952011-07-03 13:36:17 -03001046
Mauro Carvalho Chehab469ffe02011-07-03 18:12:26 -03001047 status = UpdateRegs(state, EB22, EB23);
1048 if (status < 0)
1049 break;
Ralph Metzlere8783952011-07-03 13:36:17 -03001050
Oliver Endriss0fe44622011-07-03 13:37:31 -03001051 state->m_Regs[EP1] = (state->m_Regs[EP1] & ~0x07) | 0x40 | BP_Filter; /* Dis_Power_level = 1, Filter */
Ralph Metzlere8783952011-07-03 13:36:17 -03001052 state->m_Regs[EP5] = (state->m_Regs[EP5] & ~0x07) | IR_Meas;
1053 state->m_Regs[EP2] = (RF_Band << 5) | GainTaper;
1054
1055 state->m_Regs[EB1] = (state->m_Regs[EB1] & ~0x07) |
Oliver Endriss0fe44622011-07-03 13:37:31 -03001056 (state->m_bMaster ? 0x04 : 0x00); /* CALVCO_FortLOn = MS */
1057 /* AGC1_always_master = 0 */
1058 /* AGC_firstn = 0 */
Mauro Carvalho Chehab469ffe02011-07-03 18:12:26 -03001059 status = UpdateReg(state, EB1);
1060 if (status < 0)
1061 break;
Ralph Metzlere8783952011-07-03 13:36:17 -03001062
Oliver Endriss0fe44622011-07-03 13:37:31 -03001063 if (state->m_bMaster) {
Mauro Carvalho Chehab469ffe02011-07-03 18:12:26 -03001064 status = CalcMainPLL(state, Frequency + IntermediateFrequency);
1065 if (status < 0)
1066 break;
1067 status = UpdateRegs(state, TM, EP5);
1068 if (status < 0)
1069 break;
Oliver Endriss0fe44622011-07-03 13:37:31 -03001070 state->m_Regs[EB4] |= 0x20; /* LO_forceSrce = 1 */
Mauro Carvalho Chehab469ffe02011-07-03 18:12:26 -03001071 status = UpdateReg(state, EB4);
1072 if (status < 0)
1073 break;
Ralph Metzlere8783952011-07-03 13:36:17 -03001074 msleep(1);
Oliver Endriss0fe44622011-07-03 13:37:31 -03001075 state->m_Regs[EB4] &= ~0x20; /* LO_forceSrce = 0 */
Mauro Carvalho Chehab469ffe02011-07-03 18:12:26 -03001076 status = UpdateReg(state, EB4);
1077 if (status < 0)
1078 break;
Oliver Endriss0fe44622011-07-03 13:37:31 -03001079 } else {
Mauro Carvalho Chehabea90f012011-07-03 18:06:07 -03001080 u8 PostDiv = 0;
Ralph Metzlere8783952011-07-03 13:36:17 -03001081 u8 Div;
Mauro Carvalho Chehab469ffe02011-07-03 18:12:26 -03001082 status = CalcCalPLL(state, Frequency + IntermediateFrequency);
1083 if (status < 0)
1084 break;
Ralph Metzlere8783952011-07-03 13:36:17 -03001085
Oliver Endriss0fe44622011-07-03 13:37:31 -03001086 SearchMap3(m_Cal_PLL_Map, Frequency + IntermediateFrequency, &PostDiv, &Div);
Ralph Metzlere8783952011-07-03 13:36:17 -03001087 state->m_Regs[MPD] = (state->m_Regs[MPD] & ~0x7F) | (PostDiv & 0x77);
Mauro Carvalho Chehab469ffe02011-07-03 18:12:26 -03001088 status = UpdateReg(state, MPD);
1089 if (status < 0)
1090 break;
1091 status = UpdateRegs(state, TM, EP5);
1092 if (status < 0)
1093 break;
Ralph Metzlere8783952011-07-03 13:36:17 -03001094
Oliver Endriss0fe44622011-07-03 13:37:31 -03001095 state->m_Regs[EB7] |= 0x20; /* CAL_forceSrce = 1 */
Mauro Carvalho Chehab469ffe02011-07-03 18:12:26 -03001096 status = UpdateReg(state, EB7);
1097 if (status < 0)
1098 break;
Ralph Metzlere8783952011-07-03 13:36:17 -03001099 msleep(1);
Oliver Endriss0fe44622011-07-03 13:37:31 -03001100 state->m_Regs[EB7] &= ~0x20; /* CAL_forceSrce = 0 */
Mauro Carvalho Chehab469ffe02011-07-03 18:12:26 -03001101 status = UpdateReg(state, EB7);
1102 if (status < 0)
1103 break;
Ralph Metzlere8783952011-07-03 13:36:17 -03001104 }
1105 msleep(20);
Oliver Endriss0fe44622011-07-03 13:37:31 -03001106 if (Standard != HF_FM_Radio)
1107 state->m_Regs[EP3] |= 0x04; /* RFAGC to normal mode */
Mauro Carvalho Chehab469ffe02011-07-03 18:12:26 -03001108 status = UpdateReg(state, EP3);
1109 if (status < 0)
1110 break;
Ralph Metzlere8783952011-07-03 13:36:17 -03001111
Oliver Endriss0fe44622011-07-03 13:37:31 -03001112 } while (0);
Ralph Metzlere8783952011-07-03 13:36:17 -03001113 return status;
1114}
1115
Oliver Endriss0fe44622011-07-03 13:37:31 -03001116static int sleep(struct dvb_frontend *fe)
Ralph Metzlere8783952011-07-03 13:36:17 -03001117{
1118 struct tda_state *state = fe->tuner_priv;
1119
1120 StandBy(state);
1121 return 0;
1122}
1123
Oliver Endriss0fe44622011-07-03 13:37:31 -03001124static int init(struct dvb_frontend *fe)
Ralph Metzlere8783952011-07-03 13:36:17 -03001125{
Ralph Metzlere8783952011-07-03 13:36:17 -03001126 return 0;
1127}
1128
Oliver Endriss0fe44622011-07-03 13:37:31 -03001129static int release(struct dvb_frontend *fe)
Ralph Metzlere8783952011-07-03 13:36:17 -03001130{
1131 kfree(fe->tuner_priv);
1132 fe->tuner_priv = NULL;
1133 return 0;
1134}
1135
Mauro Carvalho Chehabcf845292011-07-28 15:49:43 -03001136
Mauro Carvalho Chehab14d24d12011-12-24 12:24:33 -03001137static int set_params(struct dvb_frontend *fe)
Ralph Metzlere8783952011-07-03 13:36:17 -03001138{
1139 struct tda_state *state = fe->tuner_priv;
1140 int status = 0;
1141 int Standard;
Mauro Carvalho Chehabfd66c452011-12-17 20:36:57 -03001142 u32 bw = fe->dtv_property_cache.bandwidth_hz;
1143 u32 delsys = fe->dtv_property_cache.delivery_system;
Ralph Metzlere8783952011-07-03 13:36:17 -03001144
Mauro Carvalho Chehabfd66c452011-12-17 20:36:57 -03001145 state->m_Frequency = fe->dtv_property_cache.frequency;
Ralph Metzlere8783952011-07-03 13:36:17 -03001146
Mauro Carvalho Chehabfd66c452011-12-17 20:36:57 -03001147 switch (delsys) {
1148 case SYS_DVBT:
1149 case SYS_DVBT2:
1150 switch (bw) {
1151 case 6000000:
Ralph Metzlere8783952011-07-03 13:36:17 -03001152 Standard = HF_DVBT_6MHZ;
1153 break;
Mauro Carvalho Chehabfd66c452011-12-17 20:36:57 -03001154 case 7000000:
Ralph Metzlere8783952011-07-03 13:36:17 -03001155 Standard = HF_DVBT_7MHZ;
1156 break;
Mauro Carvalho Chehabfd66c452011-12-17 20:36:57 -03001157 case 8000000:
Ralph Metzlere8783952011-07-03 13:36:17 -03001158 Standard = HF_DVBT_8MHZ;
1159 break;
Mauro Carvalho Chehabfd66c452011-12-17 20:36:57 -03001160 default:
1161 return -EINVAL;
Ralph Metzlere8783952011-07-03 13:36:17 -03001162 }
Mauro Carvalho Chehabfd66c452011-12-17 20:36:57 -03001163 case SYS_DVBC_ANNEX_A:
1164 case SYS_DVBC_ANNEX_C:
Mauro Carvalho Chehab2440f7a2011-11-11 20:26:03 -02001165 if (bw <= 6000000)
Mauro Carvalho Chehabcf845292011-07-28 15:49:43 -03001166 Standard = HF_DVBC_6MHZ;
Mauro Carvalho Chehab2440f7a2011-11-11 20:26:03 -02001167 else if (bw <= 7000000)
1168 Standard = HF_DVBC_7MHZ;
Mauro Carvalho Chehabcf845292011-07-28 15:49:43 -03001169 else
1170 Standard = HF_DVBC_8MHZ;
Mauro Carvalho Chehab1ca8dde2011-12-30 15:34:51 -02001171 break;
Mauro Carvalho Chehabfd66c452011-12-17 20:36:57 -03001172 default:
Ralph Metzlere8783952011-07-03 13:36:17 -03001173 return -EINVAL;
Mauro Carvalho Chehabfd66c452011-12-17 20:36:57 -03001174 }
Ralph Metzlere8783952011-07-03 13:36:17 -03001175 do {
Mauro Carvalho Chehabfd66c452011-12-17 20:36:57 -03001176 status = RFTrackingFiltersCorrection(state, state->m_Frequency);
Mauro Carvalho Chehab469ffe02011-07-03 18:12:26 -03001177 if (status < 0)
1178 break;
Mauro Carvalho Chehabfd66c452011-12-17 20:36:57 -03001179 status = ChannelConfiguration(state, state->m_Frequency,
1180 Standard);
Mauro Carvalho Chehab469ffe02011-07-03 18:12:26 -03001181 if (status < 0)
1182 break;
Ralph Metzlere8783952011-07-03 13:36:17 -03001183
Oliver Endriss0fe44622011-07-03 13:37:31 -03001184 msleep(state->m_SettlingTime); /* Allow AGC's to settle down */
1185 } while (0);
Ralph Metzlere8783952011-07-03 13:36:17 -03001186 return status;
1187}
1188
1189#if 0
Oliver Endriss0fe44622011-07-03 13:37:31 -03001190static int GetSignalStrength(s32 *pSignalStrength, u32 RFAgc, u32 IFAgc)
Ralph Metzlere8783952011-07-03 13:36:17 -03001191{
Oliver Endriss0fe44622011-07-03 13:37:31 -03001192 if (IFAgc < 500) {
1193 /* Scale this from 0 to 50000 */
Ralph Metzlere8783952011-07-03 13:36:17 -03001194 *pSignalStrength = IFAgc * 100;
1195 } else {
Oliver Endriss0fe44622011-07-03 13:37:31 -03001196 /* Scale range 500-1500 to 50000-80000 */
Ralph Metzlere8783952011-07-03 13:36:17 -03001197 *pSignalStrength = 50000 + (IFAgc - 500) * 30;
1198 }
1199
1200 return 0;
1201}
1202#endif
1203
Mauro Carvalho Chehab8513e142011-09-03 11:40:02 -03001204static int get_if_frequency(struct dvb_frontend *fe, u32 *frequency)
Ralph Metzlere8783952011-07-03 13:36:17 -03001205{
1206 struct tda_state *state = fe->tuner_priv;
1207
1208 *frequency = state->IF;
1209 return 0;
1210}
1211
1212static int get_bandwidth(struct dvb_frontend *fe, u32 *bandwidth)
1213{
Oliver Endriss0fe44622011-07-03 13:37:31 -03001214 /* struct tda_state *state = fe->tuner_priv; */
1215 /* *bandwidth = priv->bandwidth; */
Ralph Metzlere8783952011-07-03 13:36:17 -03001216 return 0;
1217}
1218
1219
1220static struct dvb_tuner_ops tuner_ops = {
1221 .info = {
1222 .name = "NXP TDA18271C2D",
1223 .frequency_min = 47125000,
1224 .frequency_max = 865000000,
1225 .frequency_step = 62500
1226 },
1227 .init = init,
1228 .sleep = sleep,
1229 .set_params = set_params,
1230 .release = release,
Mauro Carvalho Chehab8513e142011-09-03 11:40:02 -03001231 .get_if_frequency = get_if_frequency,
Ralph Metzlere8783952011-07-03 13:36:17 -03001232 .get_bandwidth = get_bandwidth,
1233};
1234
1235struct dvb_frontend *tda18271c2dd_attach(struct dvb_frontend *fe,
1236 struct i2c_adapter *i2c, u8 adr)
1237{
1238 struct tda_state *state;
1239
1240 state = kzalloc(sizeof(struct tda_state), GFP_KERNEL);
1241 if (!state)
1242 return NULL;
1243
1244 fe->tuner_priv = state;
1245 state->adr = adr;
1246 state->i2c = i2c;
1247 memcpy(&fe->ops.tuner_ops, &tuner_ops, sizeof(struct dvb_tuner_ops));
1248 reset(state);
1249 InitCal(state);
1250
1251 return fe;
1252}
Ralph Metzlere8783952011-07-03 13:36:17 -03001253EXPORT_SYMBOL_GPL(tda18271c2dd_attach);
Oliver Endriss0fe44622011-07-03 13:37:31 -03001254
Ralph Metzlere8783952011-07-03 13:36:17 -03001255MODULE_DESCRIPTION("TDA18271C2 driver");
1256MODULE_AUTHOR("DD");
1257MODULE_LICENSE("GPL");