blob: e064e2b22d9d781b7d83e66d125799d085d23361 [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 *
Sakari Ailusbcb63312016-10-28 09:31:20 -020017 * To obtain the license, point your browser to
18 * http://www.gnu.org/copyleft/gpl.html
Ralph Metzlere8783952011-07-03 13:36:17 -030019 */
20
21#include <linux/kernel.h>
22#include <linux/module.h>
Ralph Metzlere8783952011-07-03 13:36:17 -030023#include <linux/init.h>
24#include <linux/delay.h>
25#include <linux/firmware.h>
26#include <linux/i2c.h>
Ralph Metzlere8783952011-07-03 13:36:17 -030027#include <asm/div64.h>
28
Mauro Carvalho Chehabfada1932017-12-28 13:03:51 -050029#include <media/dvb_frontend.h>
Mauro Carvalho Chehab4e373212012-10-27 11:28:06 -030030#include "tda18271c2dd.h"
Ralph Metzlere8783952011-07-03 13:36:17 -030031
Mauro Carvalho Chehab83937962013-11-02 05:05:18 -030032/* Max transfer size done by I2C transfer functions */
33#define MAX_XFER_SIZE 64
34
Ralph Metzlere8783952011-07-03 13:36:17 -030035struct SStandardParam {
36 s32 m_IFFrequency;
37 u32 m_BandWidth;
38 u8 m_EP3_4_0;
39 u8 m_EB22;
40};
41
42struct SMap {
43 u32 m_Frequency;
44 u8 m_Param;
45};
46
47struct SMapI {
48 u32 m_Frequency;
49 s32 m_Param;
50};
51
52struct SMap2 {
53 u32 m_Frequency;
54 u8 m_Param1;
55 u8 m_Param2;
56};
57
58struct SRFBandMap {
59 u32 m_RF_max;
60 u32 m_RF1_Default;
61 u32 m_RF2_Default;
62 u32 m_RF3_Default;
63};
64
Oliver Endriss0fe44622011-07-03 13:37:31 -030065enum ERegister {
Ralph Metzlere8783952011-07-03 13:36:17 -030066 ID = 0,
67 TM,
68 PL,
69 EP1, EP2, EP3, EP4, EP5,
70 CPD, CD1, CD2, CD3,
71 MPD, MD1, MD2, MD3,
72 EB1, EB2, EB3, EB4, EB5, EB6, EB7, EB8, EB9, EB10,
73 EB11, EB12, EB13, EB14, EB15, EB16, EB17, EB18, EB19, EB20,
74 EB21, EB22, EB23,
75 NUM_REGS
76};
77
78struct tda_state {
79 struct i2c_adapter *i2c;
80 u8 adr;
81
82 u32 m_Frequency;
83 u32 IF;
84
85 u8 m_IFLevelAnalog;
86 u8 m_IFLevelDigital;
87 u8 m_IFLevelDVBC;
88 u8 m_IFLevelDVBT;
89
90 u8 m_EP4;
91 u8 m_EP3_Standby;
92
93 bool m_bMaster;
94
95 s32 m_SettlingTime;
96
97 u8 m_Regs[NUM_REGS];
98
99 /* Tracking filter settings for band 0..6 */
100 u32 m_RF1[7];
101 s32 m_RF_A1[7];
102 s32 m_RF_B1[7];
103 u32 m_RF2[7];
104 s32 m_RF_A2[7];
105 s32 m_RF_B2[7];
106 u32 m_RF3[7];
107
Mauro Carvalho Chehab868c9a12019-02-18 14:28:55 -0500108 u8 m_TMValue_RFCal; /* Calibration temperature */
Ralph Metzlere8783952011-07-03 13:36:17 -0300109
110 bool m_bFMInput; /* true to use Pin 8 for FM Radio */
111
112};
113
114static int PowerScan(struct tda_state *state,
Oliver Endriss0fe44622011-07-03 13:37:31 -0300115 u8 RFBand, u32 RF_in,
116 u32 *pRF_Out, bool *pbcal);
Ralph Metzlere8783952011-07-03 13:36:17 -0300117
118static int i2c_readn(struct i2c_adapter *adapter, u8 adr, u8 *data, int len)
119{
120 struct i2c_msg msgs[1] = {{.addr = adr, .flags = I2C_M_RD,
Oliver Endriss0fe44622011-07-03 13:37:31 -0300121 .buf = data, .len = len} };
Ralph Metzlere8783952011-07-03 13:36:17 -0300122 return (i2c_transfer(adapter, msgs, 1) == 1) ? 0 : -1;
123}
124
125static int i2c_write(struct i2c_adapter *adap, u8 adr, u8 *data, int len)
126{
127 struct i2c_msg msg = {.addr = adr, .flags = 0,
128 .buf = data, .len = len};
129
130 if (i2c_transfer(adap, &msg, 1) != 1) {
Mauro Carvalho Chehabf3d40bd2011-07-04 14:00:25 -0300131 printk(KERN_ERR "tda18271c2dd: i2c write error at addr %i\n", adr);
Ralph Metzlere8783952011-07-03 13:36:17 -0300132 return -1;
133 }
134 return 0;
135}
136
137static int WriteRegs(struct tda_state *state,
138 u8 SubAddr, u8 *Regs, u16 nRegs)
139{
Mauro Carvalho Chehab83937962013-11-02 05:05:18 -0300140 u8 data[MAX_XFER_SIZE];
141
142 if (1 + nRegs > sizeof(data)) {
143 printk(KERN_WARNING
144 "%s: i2c wr: len=%d is too big!\n",
145 KBUILD_MODNAME, nRegs);
146 return -EINVAL;
147 }
Ralph Metzlere8783952011-07-03 13:36:17 -0300148
149 data[0] = SubAddr;
150 memcpy(data + 1, Regs, nRegs);
Mauro Carvalho Chehab83937962013-11-02 05:05:18 -0300151 return i2c_write(state->i2c, state->adr, data, nRegs + 1);
Ralph Metzlere8783952011-07-03 13:36:17 -0300152}
153
Oliver Endriss0fe44622011-07-03 13:37:31 -0300154static int WriteReg(struct tda_state *state, u8 SubAddr, u8 Reg)
Ralph Metzlere8783952011-07-03 13:36:17 -0300155{
156 u8 msg[2] = {SubAddr, Reg};
157
158 return i2c_write(state->i2c, state->adr, msg, 2);
159}
160
161static int Read(struct tda_state *state, u8 * Regs)
162{
163 return i2c_readn(state->i2c, state->adr, Regs, 16);
164}
165
166static int ReadExtented(struct tda_state *state, u8 * Regs)
167{
168 return i2c_readn(state->i2c, state->adr, Regs, NUM_REGS);
169}
170
Oliver Endriss0fe44622011-07-03 13:37:31 -0300171static int UpdateRegs(struct tda_state *state, u8 RegFrom, u8 RegTo)
Ralph Metzlere8783952011-07-03 13:36:17 -0300172{
173 return WriteRegs(state, RegFrom,
174 &state->m_Regs[RegFrom], RegTo-RegFrom+1);
175}
176static int UpdateReg(struct tda_state *state, u8 Reg)
177{
Oliver Endriss0fe44622011-07-03 13:37:31 -0300178 return WriteReg(state, Reg, state->m_Regs[Reg]);
Ralph Metzlere8783952011-07-03 13:36:17 -0300179}
180
181#include "tda18271c2dd_maps.h"
182
Ralph Metzlere8783952011-07-03 13:36:17 -0300183static void reset(struct tda_state *state)
184{
185 u32 ulIFLevelAnalog = 0;
186 u32 ulIFLevelDigital = 2;
187 u32 ulIFLevelDVBC = 7;
188 u32 ulIFLevelDVBT = 6;
189 u32 ulXTOut = 0;
Oliver Endriss0fe44622011-07-03 13:37:31 -0300190 u32 ulStandbyMode = 0x06; /* Send in stdb, but leave osc on */
Ralph Metzlere8783952011-07-03 13:36:17 -0300191 u32 ulSlave = 0;
192 u32 ulFMInput = 0;
193 u32 ulSettlingTime = 100;
194
195 state->m_Frequency = 0;
196 state->m_SettlingTime = 100;
197 state->m_IFLevelAnalog = (ulIFLevelAnalog & 0x07) << 2;
198 state->m_IFLevelDigital = (ulIFLevelDigital & 0x07) << 2;
199 state->m_IFLevelDVBC = (ulIFLevelDVBC & 0x07) << 2;
200 state->m_IFLevelDVBT = (ulIFLevelDVBT & 0x07) << 2;
201
202 state->m_EP4 = 0x20;
Oliver Endriss0fe44622011-07-03 13:37:31 -0300203 if (ulXTOut != 0)
204 state->m_EP4 |= 0x40;
Ralph Metzlere8783952011-07-03 13:36:17 -0300205
206 state->m_EP3_Standby = ((ulStandbyMode & 0x07) << 5) | 0x0F;
207 state->m_bMaster = (ulSlave == 0);
208
209 state->m_SettlingTime = ulSettlingTime;
210
211 state->m_bFMInput = (ulFMInput == 2);
212}
213
214static bool SearchMap1(struct SMap Map[],
215 u32 Frequency, u8 *pParam)
216{
217 int i = 0;
218
Oliver Endriss0fe44622011-07-03 13:37:31 -0300219 while ((Map[i].m_Frequency != 0) && (Frequency > Map[i].m_Frequency))
Ralph Metzlere8783952011-07-03 13:36:17 -0300220 i += 1;
221 if (Map[i].m_Frequency == 0)
222 return false;
223 *pParam = Map[i].m_Param;
224 return true;
225}
226
227static bool SearchMap2(struct SMapI Map[],
228 u32 Frequency, s32 *pParam)
229{
230 int i = 0;
231
232 while ((Map[i].m_Frequency != 0) &&
Oliver Endriss0fe44622011-07-03 13:37:31 -0300233 (Frequency > Map[i].m_Frequency))
Ralph Metzlere8783952011-07-03 13:36:17 -0300234 i += 1;
235 if (Map[i].m_Frequency == 0)
236 return false;
237 *pParam = Map[i].m_Param;
238 return true;
239}
240
Oliver Endriss0fe44622011-07-03 13:37:31 -0300241static bool SearchMap3(struct SMap2 Map[], u32 Frequency,
Ralph Metzlere8783952011-07-03 13:36:17 -0300242 u8 *pParam1, u8 *pParam2)
243{
244 int i = 0;
245
246 while ((Map[i].m_Frequency != 0) &&
Oliver Endriss0fe44622011-07-03 13:37:31 -0300247 (Frequency > Map[i].m_Frequency))
Ralph Metzlere8783952011-07-03 13:36:17 -0300248 i += 1;
249 if (Map[i].m_Frequency == 0)
250 return false;
251 *pParam1 = Map[i].m_Param1;
252 *pParam2 = Map[i].m_Param2;
253 return true;
254}
255
256static bool SearchMap4(struct SRFBandMap Map[],
257 u32 Frequency, u8 *pRFBand)
258{
259 int i = 0;
260
261 while (i < 7 && (Frequency > Map[i].m_RF_max))
262 i += 1;
263 if (i == 7)
264 return false;
265 *pRFBand = i;
266 return true;
267}
268
269static int ThermometerRead(struct tda_state *state, u8 *pTM_Value)
270{
271 int status = 0;
272
273 do {
274 u8 Regs[16];
275 state->m_Regs[TM] |= 0x10;
Mauro Carvalho Chehab469ffe02011-07-03 18:12:26 -0300276 status = UpdateReg(state, TM);
277 if (status < 0)
278 break;
279 status = Read(state, Regs);
280 if (status < 0)
281 break;
Oliver Endriss0fe44622011-07-03 13:37:31 -0300282 if (((Regs[TM] & 0x0F) == 0 && (Regs[TM] & 0x20) == 0x20) ||
283 ((Regs[TM] & 0x0F) == 8 && (Regs[TM] & 0x20) == 0x00)) {
Ralph Metzlere8783952011-07-03 13:36:17 -0300284 state->m_Regs[TM] ^= 0x20;
Mauro Carvalho Chehab469ffe02011-07-03 18:12:26 -0300285 status = UpdateReg(state, TM);
286 if (status < 0)
287 break;
Ralph Metzlere8783952011-07-03 13:36:17 -0300288 msleep(10);
Mauro Carvalho Chehab469ffe02011-07-03 18:12:26 -0300289 status = Read(state, Regs);
290 if (status < 0)
291 break;
Ralph Metzlere8783952011-07-03 13:36:17 -0300292 }
Oliver Endriss0fe44622011-07-03 13:37:31 -0300293 *pTM_Value = (Regs[TM] & 0x20)
294 ? m_Thermometer_Map_2[Regs[TM] & 0x0F]
295 : m_Thermometer_Map_1[Regs[TM] & 0x0F] ;
296 state->m_Regs[TM] &= ~0x10; /* Thermometer off */
Mauro Carvalho Chehab469ffe02011-07-03 18:12:26 -0300297 status = UpdateReg(state, TM);
298 if (status < 0)
299 break;
Oliver Endriss0fe44622011-07-03 13:37:31 -0300300 state->m_Regs[EP4] &= ~0x03; /* CAL_mode = 0 ????????? */
Mauro Carvalho Chehab469ffe02011-07-03 18:12:26 -0300301 status = UpdateReg(state, EP4);
302 if (status < 0)
303 break;
Oliver Endriss0fe44622011-07-03 13:37:31 -0300304 } while (0);
Ralph Metzlere8783952011-07-03 13:36:17 -0300305
306 return status;
307}
308
309static int StandBy(struct tda_state *state)
310{
311 int status = 0;
312 do {
Oliver Endriss0fe44622011-07-03 13:37:31 -0300313 state->m_Regs[EB12] &= ~0x20; /* PD_AGC1_Det = 0 */
Mauro Carvalho Chehab469ffe02011-07-03 18:12:26 -0300314 status = UpdateReg(state, EB12);
315 if (status < 0)
316 break;
Oliver Endriss0fe44622011-07-03 13:37:31 -0300317 state->m_Regs[EB18] &= ~0x83; /* AGC1_loop_off = 0, AGC1_Gain = 6 dB */
Mauro Carvalho Chehab469ffe02011-07-03 18:12:26 -0300318 status = UpdateReg(state, EB18);
319 if (status < 0)
320 break;
Oliver Endriss0fe44622011-07-03 13:37:31 -0300321 state->m_Regs[EB21] |= 0x03; /* AGC2_Gain = -6 dB */
Ralph Metzlere8783952011-07-03 13:36:17 -0300322 state->m_Regs[EP3] = state->m_EP3_Standby;
Mauro Carvalho Chehab469ffe02011-07-03 18:12:26 -0300323 status = UpdateReg(state, EP3);
324 if (status < 0)
325 break;
Oliver Endriss0fe44622011-07-03 13:37:31 -0300326 state->m_Regs[EB23] &= ~0x06; /* ForceLP_Fc2_En = 0, LP_Fc[2] = 0 */
Mauro Carvalho Chehab469ffe02011-07-03 18:12:26 -0300327 status = UpdateRegs(state, EB21, EB23);
328 if (status < 0)
329 break;
Oliver Endriss0fe44622011-07-03 13:37:31 -0300330 } while (0);
Ralph Metzlere8783952011-07-03 13:36:17 -0300331 return status;
332}
333
334static int CalcMainPLL(struct tda_state *state, u32 freq)
335{
336
337 u8 PostDiv;
338 u8 Div;
339 u64 OscFreq;
340 u32 MainDiv;
341
Oliver Endriss0fe44622011-07-03 13:37:31 -0300342 if (!SearchMap3(m_Main_PLL_Map, freq, &PostDiv, &Div))
Ralph Metzlere8783952011-07-03 13:36:17 -0300343 return -EINVAL;
Ralph Metzlere8783952011-07-03 13:36:17 -0300344
345 OscFreq = (u64) freq * (u64) Div;
346 OscFreq *= (u64) 16384;
347 do_div(OscFreq, (u64)16000000);
348 MainDiv = OscFreq;
349
350 state->m_Regs[MPD] = PostDiv & 0x77;
351 state->m_Regs[MD1] = ((MainDiv >> 16) & 0x7F);
352 state->m_Regs[MD2] = ((MainDiv >> 8) & 0xFF);
Oliver Endriss0fe44622011-07-03 13:37:31 -0300353 state->m_Regs[MD3] = (MainDiv & 0xFF);
Ralph Metzlere8783952011-07-03 13:36:17 -0300354
355 return UpdateRegs(state, MPD, MD3);
356}
357
358static int CalcCalPLL(struct tda_state *state, u32 freq)
359{
Ralph Metzlere8783952011-07-03 13:36:17 -0300360 u8 PostDiv;
361 u8 Div;
362 u64 OscFreq;
363 u32 CalDiv;
364
Oliver Endriss0fe44622011-07-03 13:37:31 -0300365 if (!SearchMap3(m_Cal_PLL_Map, freq, &PostDiv, &Div))
Ralph Metzlere8783952011-07-03 13:36:17 -0300366 return -EINVAL;
Ralph Metzlere8783952011-07-03 13:36:17 -0300367
368 OscFreq = (u64)freq * (u64)Div;
Oliver Endriss0fe44622011-07-03 13:37:31 -0300369 /* CalDiv = u32( OscFreq * 16384 / 16000000 ); */
370 OscFreq *= (u64)16384;
Ralph Metzlere8783952011-07-03 13:36:17 -0300371 do_div(OscFreq, (u64)16000000);
Oliver Endriss0fe44622011-07-03 13:37:31 -0300372 CalDiv = OscFreq;
Ralph Metzlere8783952011-07-03 13:36:17 -0300373
374 state->m_Regs[CPD] = PostDiv;
375 state->m_Regs[CD1] = ((CalDiv >> 16) & 0xFF);
376 state->m_Regs[CD2] = ((CalDiv >> 8) & 0xFF);
Oliver Endriss0fe44622011-07-03 13:37:31 -0300377 state->m_Regs[CD3] = (CalDiv & 0xFF);
Ralph Metzlere8783952011-07-03 13:36:17 -0300378
Oliver Endriss0fe44622011-07-03 13:37:31 -0300379 return UpdateRegs(state, CPD, CD3);
Ralph Metzlere8783952011-07-03 13:36:17 -0300380}
381
382static int CalibrateRF(struct tda_state *state,
Oliver Endriss0fe44622011-07-03 13:37:31 -0300383 u8 RFBand, u32 freq, s32 *pCprog)
Ralph Metzlere8783952011-07-03 13:36:17 -0300384{
Ralph Metzlere8783952011-07-03 13:36:17 -0300385 int status = 0;
386 u8 Regs[NUM_REGS];
387 do {
Oliver Endriss0fe44622011-07-03 13:37:31 -0300388 u8 BP_Filter = 0;
389 u8 GainTaper = 0;
390 u8 RFC_K = 0;
391 u8 RFC_M = 0;
Ralph Metzlere8783952011-07-03 13:36:17 -0300392
Oliver Endriss0fe44622011-07-03 13:37:31 -0300393 state->m_Regs[EP4] &= ~0x03; /* CAL_mode = 0 */
Mauro Carvalho Chehab469ffe02011-07-03 18:12:26 -0300394 status = UpdateReg(state, EP4);
395 if (status < 0)
396 break;
Oliver Endriss0fe44622011-07-03 13:37:31 -0300397 state->m_Regs[EB18] |= 0x03; /* AGC1_Gain = 3 */
Mauro Carvalho Chehab469ffe02011-07-03 18:12:26 -0300398 status = UpdateReg(state, EB18);
399 if (status < 0)
400 break;
Ralph Metzlere8783952011-07-03 13:36:17 -0300401
Oliver Endriss0fe44622011-07-03 13:37:31 -0300402 /* Switching off LT (as datasheet says) causes calibration on C1 to fail */
Mauro Carvalho Chehab868c9a12019-02-18 14:28:55 -0500403 /* (Readout of Cprog is always 255) */
Oliver Endriss0fe44622011-07-03 13:37:31 -0300404 if (state->m_Regs[ID] != 0x83) /* C1: ID == 83, C2: ID == 84 */
405 state->m_Regs[EP3] |= 0x40; /* SM_LT = 1 */
Ralph Metzlere8783952011-07-03 13:36:17 -0300406
Oliver Endriss0fe44622011-07-03 13:37:31 -0300407 if (!(SearchMap1(m_BP_Filter_Map, freq, &BP_Filter) &&
408 SearchMap1(m_GainTaper_Map, freq, &GainTaper) &&
409 SearchMap3(m_KM_Map, freq, &RFC_K, &RFC_M)))
Ralph Metzlere8783952011-07-03 13:36:17 -0300410 return -EINVAL;
Ralph Metzlere8783952011-07-03 13:36:17 -0300411
412 state->m_Regs[EP1] = (state->m_Regs[EP1] & ~0x07) | BP_Filter;
413 state->m_Regs[EP2] = (RFBand << 5) | GainTaper;
414
415 state->m_Regs[EB13] = (state->m_Regs[EB13] & ~0x7C) | (RFC_K << 4) | (RFC_M << 2);
416
Mauro Carvalho Chehab469ffe02011-07-03 18:12:26 -0300417 status = UpdateRegs(state, EP1, EP3);
418 if (status < 0)
419 break;
420 status = UpdateReg(state, EB13);
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[EB4] |= 0x20; /* LO_ForceSrce = 1 */
Mauro Carvalho Chehab469ffe02011-07-03 18:12:26 -0300425 status = UpdateReg(state, EB4);
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[EB7] |= 0x20; /* CAL_ForceSrce = 1 */
Mauro Carvalho Chehab469ffe02011-07-03 18:12:26 -0300430 status = UpdateReg(state, EB7);
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[EB14] = 0; /* RFC_Cprog = 0 */
Mauro Carvalho Chehab469ffe02011-07-03 18:12:26 -0300435 status = UpdateReg(state, EB14);
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[EB20] &= ~0x20; /* ForceLock = 0; */
Mauro Carvalho Chehab469ffe02011-07-03 18:12:26 -0300440 status = UpdateReg(state, EB20);
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[EP4] |= 0x03; /* CAL_Mode = 3 */
Mauro Carvalho Chehab469ffe02011-07-03 18:12:26 -0300445 status = UpdateRegs(state, EP4, EP5);
446 if (status < 0)
447 break;
Ralph Metzlere8783952011-07-03 13:36:17 -0300448
Mauro Carvalho Chehab469ffe02011-07-03 18:12:26 -0300449 status = CalcCalPLL(state, freq);
450 if (status < 0)
451 break;
452 status = CalcMainPLL(state, freq + 1000000);
453 if (status < 0)
454 break;
Ralph Metzlere8783952011-07-03 13:36:17 -0300455
456 msleep(5);
Mauro Carvalho Chehab469ffe02011-07-03 18:12:26 -0300457 status = UpdateReg(state, EP2);
458 if (status < 0)
459 break;
460 status = UpdateReg(state, EP1);
461 if (status < 0)
462 break;
463 status = UpdateReg(state, EP2);
464 if (status < 0)
465 break;
466 status = UpdateReg(state, EP1);
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[EB4] &= ~0x20; /* LO_ForceSrce = 0 */
Mauro Carvalho Chehab469ffe02011-07-03 18:12:26 -0300471 status = UpdateReg(state, EB4);
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[EB7] &= ~0x20; /* CAL_ForceSrce = 0 */
Mauro Carvalho Chehab469ffe02011-07-03 18:12:26 -0300476 status = UpdateReg(state, EB7);
477 if (status < 0)
478 break;
Ralph Metzlere8783952011-07-03 13:36:17 -0300479 msleep(10);
480
Oliver Endriss0fe44622011-07-03 13:37:31 -0300481 state->m_Regs[EB20] |= 0x20; /* ForceLock = 1; */
Mauro Carvalho Chehab469ffe02011-07-03 18:12:26 -0300482 status = UpdateReg(state, EB20);
483 if (status < 0)
484 break;
Ralph Metzlere8783952011-07-03 13:36:17 -0300485 msleep(60);
486
Oliver Endriss0fe44622011-07-03 13:37:31 -0300487 state->m_Regs[EP4] &= ~0x03; /* CAL_Mode = 0 */
488 state->m_Regs[EP3] &= ~0x40; /* SM_LT = 0 */
489 state->m_Regs[EB18] &= ~0x03; /* AGC1_Gain = 0 */
Mauro Carvalho Chehab469ffe02011-07-03 18:12:26 -0300490 status = UpdateReg(state, EB18);
491 if (status < 0)
492 break;
493 status = UpdateRegs(state, EP3, EP4);
494 if (status < 0)
495 break;
496 status = UpdateReg(state, EP1);
497 if (status < 0)
498 break;
Ralph Metzlere8783952011-07-03 13:36:17 -0300499
Mauro Carvalho Chehab469ffe02011-07-03 18:12:26 -0300500 status = ReadExtented(state, Regs);
501 if (status < 0)
502 break;
Ralph Metzlere8783952011-07-03 13:36:17 -0300503
504 *pCprog = Regs[EB14];
Ralph Metzlere8783952011-07-03 13:36:17 -0300505
Oliver Endriss0fe44622011-07-03 13:37:31 -0300506 } while (0);
Ralph Metzlere8783952011-07-03 13:36:17 -0300507 return status;
508}
509
510static int RFTrackingFiltersInit(struct tda_state *state,
511 u8 RFBand)
512{
Ralph Metzlere8783952011-07-03 13:36:17 -0300513 int status = 0;
514
515 u32 RF1 = m_RF_Band_Map[RFBand].m_RF1_Default;
516 u32 RF2 = m_RF_Band_Map[RFBand].m_RF2_Default;
517 u32 RF3 = m_RF_Band_Map[RFBand].m_RF3_Default;
518 bool bcal = false;
519
520 s32 Cprog_cal1 = 0;
521 s32 Cprog_table1 = 0;
522 s32 Cprog_cal2 = 0;
523 s32 Cprog_table2 = 0;
524 s32 Cprog_cal3 = 0;
525 s32 Cprog_table3 = 0;
526
527 state->m_RF_A1[RFBand] = 0;
528 state->m_RF_B1[RFBand] = 0;
529 state->m_RF_A2[RFBand] = 0;
530 state->m_RF_B2[RFBand] = 0;
531
532 do {
Mauro Carvalho Chehab469ffe02011-07-03 18:12:26 -0300533 status = PowerScan(state, RFBand, RF1, &RF1, &bcal);
534 if (status < 0)
535 break;
Oliver Endriss0fe44622011-07-03 13:37:31 -0300536 if (bcal) {
Mauro Carvalho Chehab469ffe02011-07-03 18:12:26 -0300537 status = CalibrateRF(state, RFBand, RF1, &Cprog_cal1);
538 if (status < 0)
539 break;
Ralph Metzlere8783952011-07-03 13:36:17 -0300540 }
Oliver Endriss0fe44622011-07-03 13:37:31 -0300541 SearchMap2(m_RF_Cal_Map, RF1, &Cprog_table1);
542 if (!bcal)
Ralph Metzlere8783952011-07-03 13:36:17 -0300543 Cprog_cal1 = Cprog_table1;
Ralph Metzlere8783952011-07-03 13:36:17 -0300544 state->m_RF_B1[RFBand] = Cprog_cal1 - Cprog_table1;
Oliver Endriss0fe44622011-07-03 13:37:31 -0300545 /* state->m_RF_A1[RF_Band] = ???? */
Ralph Metzlere8783952011-07-03 13:36:17 -0300546
Oliver Endriss0fe44622011-07-03 13:37:31 -0300547 if (RF2 == 0)
548 break;
Ralph Metzlere8783952011-07-03 13:36:17 -0300549
Mauro Carvalho Chehab469ffe02011-07-03 18:12:26 -0300550 status = PowerScan(state, RFBand, RF2, &RF2, &bcal);
551 if (status < 0)
552 break;
Oliver Endriss0fe44622011-07-03 13:37:31 -0300553 if (bcal) {
Mauro Carvalho Chehab469ffe02011-07-03 18:12:26 -0300554 status = CalibrateRF(state, RFBand, RF2, &Cprog_cal2);
555 if (status < 0)
556 break;
Ralph Metzlere8783952011-07-03 13:36:17 -0300557 }
Oliver Endriss0fe44622011-07-03 13:37:31 -0300558 SearchMap2(m_RF_Cal_Map, RF2, &Cprog_table2);
559 if (!bcal)
Ralph Metzlere8783952011-07-03 13:36:17 -0300560 Cprog_cal2 = Cprog_table2;
Ralph Metzlere8783952011-07-03 13:36:17 -0300561
562 state->m_RF_A1[RFBand] =
563 (Cprog_cal2 - Cprog_table2 - Cprog_cal1 + Cprog_table1) /
Oliver Endriss0fe44622011-07-03 13:37:31 -0300564 ((s32)(RF2) - (s32)(RF1));
Ralph Metzlere8783952011-07-03 13:36:17 -0300565
Oliver Endriss0fe44622011-07-03 13:37:31 -0300566 if (RF3 == 0)
567 break;
Ralph Metzlere8783952011-07-03 13:36:17 -0300568
Mauro Carvalho Chehab469ffe02011-07-03 18:12:26 -0300569 status = PowerScan(state, RFBand, RF3, &RF3, &bcal);
570 if (status < 0)
571 break;
Oliver Endriss0fe44622011-07-03 13:37:31 -0300572 if (bcal) {
Mauro Carvalho Chehab469ffe02011-07-03 18:12:26 -0300573 status = CalibrateRF(state, RFBand, RF3, &Cprog_cal3);
574 if (status < 0)
575 break;
Ralph Metzlere8783952011-07-03 13:36:17 -0300576 }
Oliver Endriss0fe44622011-07-03 13:37:31 -0300577 SearchMap2(m_RF_Cal_Map, RF3, &Cprog_table3);
578 if (!bcal)
Ralph Metzlere8783952011-07-03 13:36:17 -0300579 Cprog_cal3 = Cprog_table3;
Oliver Endriss0fe44622011-07-03 13:37:31 -0300580 state->m_RF_A2[RFBand] = (Cprog_cal3 - Cprog_table3 - Cprog_cal2 + Cprog_table2) / ((s32)(RF3) - (s32)(RF2));
Ralph Metzlere8783952011-07-03 13:36:17 -0300581 state->m_RF_B2[RFBand] = Cprog_cal2 - Cprog_table2;
582
Oliver Endriss0fe44622011-07-03 13:37:31 -0300583 } while (0);
Ralph Metzlere8783952011-07-03 13:36:17 -0300584
585 state->m_RF1[RFBand] = RF1;
586 state->m_RF2[RFBand] = RF2;
587 state->m_RF3[RFBand] = RF3;
588
589#if 0
Mauro Carvalho Chehabf3d40bd2011-07-04 14:00:25 -0300590 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 -0300591 RFBand, RF1, state->m_RF_A1[RFBand], state->m_RF_B1[RFBand], RF2,
592 state->m_RF_A2[RFBand], state->m_RF_B2[RFBand], RF3);
Ralph Metzlere8783952011-07-03 13:36:17 -0300593#endif
594
595 return status;
596}
597
598static int PowerScan(struct tda_state *state,
Oliver Endriss0fe44622011-07-03 13:37:31 -0300599 u8 RFBand, u32 RF_in, u32 *pRF_Out, bool *pbcal)
Ralph Metzlere8783952011-07-03 13:36:17 -0300600{
Oliver Endriss0fe44622011-07-03 13:37:31 -0300601 int status = 0;
602 do {
603 u8 Gain_Taper = 0;
604 s32 RFC_Cprog = 0;
605 u8 CID_Target = 0;
606 u8 CountLimit = 0;
607 u32 freq_MainPLL;
608 u8 Regs[NUM_REGS];
609 u8 CID_Gain;
610 s32 Count = 0;
611 int sign = 1;
612 bool wait = false;
Ralph Metzlere8783952011-07-03 13:36:17 -0300613
Oliver Endriss0fe44622011-07-03 13:37:31 -0300614 if (!(SearchMap2(m_RF_Cal_Map, RF_in, &RFC_Cprog) &&
615 SearchMap1(m_GainTaper_Map, RF_in, &Gain_Taper) &&
616 SearchMap3(m_CID_Target_Map, RF_in, &CID_Target, &CountLimit))) {
Ralph Metzlere8783952011-07-03 13:36:17 -0300617
Mauro Carvalho Chehabf3d40bd2011-07-04 14:00:25 -0300618 printk(KERN_ERR "tda18271c2dd: %s Search map failed\n", __func__);
Oliver Endriss0fe44622011-07-03 13:37:31 -0300619 return -EINVAL;
620 }
Ralph Metzlere8783952011-07-03 13:36:17 -0300621
Oliver Endriss0fe44622011-07-03 13:37:31 -0300622 state->m_Regs[EP2] = (RFBand << 5) | Gain_Taper;
623 state->m_Regs[EB14] = (RFC_Cprog);
Mauro Carvalho Chehab469ffe02011-07-03 18:12:26 -0300624 status = UpdateReg(state, EP2);
625 if (status < 0)
626 break;
627 status = UpdateReg(state, EB14);
628 if (status < 0)
629 break;
Ralph Metzlere8783952011-07-03 13:36:17 -0300630
Oliver Endriss0fe44622011-07-03 13:37:31 -0300631 freq_MainPLL = RF_in + 1000000;
Mauro Carvalho Chehab469ffe02011-07-03 18:12:26 -0300632 status = CalcMainPLL(state, freq_MainPLL);
633 if (status < 0)
634 break;
Oliver Endriss0fe44622011-07-03 13:37:31 -0300635 msleep(5);
636 state->m_Regs[EP4] = (state->m_Regs[EP4] & ~0x03) | 1; /* CAL_mode = 1 */
Mauro Carvalho Chehab469ffe02011-07-03 18:12:26 -0300637 status = UpdateReg(state, EP4);
638 if (status < 0)
639 break;
640 status = UpdateReg(state, EP2); /* Launch power measurement */
641 if (status < 0)
642 break;
643 status = ReadExtented(state, Regs);
644 if (status < 0)
645 break;
Oliver Endriss0fe44622011-07-03 13:37:31 -0300646 CID_Gain = Regs[EB10] & 0x3F;
Mauro Carvalho Chehab868c9a12019-02-18 14:28:55 -0500647 state->m_Regs[ID] = Regs[ID]; /* Chip version, (needed for C1 workaround in CalibrateRF) */
Ralph Metzlere8783952011-07-03 13:36:17 -0300648
Oliver Endriss0fe44622011-07-03 13:37:31 -0300649 *pRF_Out = RF_in;
Ralph Metzlere8783952011-07-03 13:36:17 -0300650
Oliver Endriss0fe44622011-07-03 13:37:31 -0300651 while (CID_Gain < CID_Target) {
652 freq_MainPLL = RF_in + sign * Count + 1000000;
Mauro Carvalho Chehab469ffe02011-07-03 18:12:26 -0300653 status = CalcMainPLL(state, freq_MainPLL);
654 if (status < 0)
655 break;
Oliver Endriss0fe44622011-07-03 13:37:31 -0300656 msleep(wait ? 5 : 1);
657 wait = false;
Mauro Carvalho Chehab469ffe02011-07-03 18:12:26 -0300658 status = UpdateReg(state, EP2); /* Launch power measurement */
659 if (status < 0)
660 break;
661 status = ReadExtented(state, Regs);
662 if (status < 0)
663 break;
Oliver Endriss0fe44622011-07-03 13:37:31 -0300664 CID_Gain = Regs[EB10] & 0x3F;
665 Count += 200000;
Ralph Metzlere8783952011-07-03 13:36:17 -0300666
Oliver Endriss0fe44622011-07-03 13:37:31 -0300667 if (Count < CountLimit * 100000)
668 continue;
669 if (sign < 0)
670 break;
671
672 sign = -sign;
673 Count = 200000;
674 wait = true;
675 }
Mauro Carvalho Chehab469ffe02011-07-03 18:12:26 -0300676 if (status < 0)
677 break;
Oliver Endriss0fe44622011-07-03 13:37:31 -0300678 if (CID_Gain >= CID_Target) {
679 *pbcal = true;
680 *pRF_Out = freq_MainPLL - 1000000;
681 } else
682 *pbcal = false;
683 } while (0);
684
685 return status;
Ralph Metzlere8783952011-07-03 13:36:17 -0300686}
687
688static int PowerScanInit(struct tda_state *state)
689{
Ralph Metzlere8783952011-07-03 13:36:17 -0300690 int status = 0;
Oliver Endriss0fe44622011-07-03 13:37:31 -0300691 do {
Ralph Metzlere8783952011-07-03 13:36:17 -0300692 state->m_Regs[EP3] = (state->m_Regs[EP3] & ~0x1F) | 0x12;
Oliver Endriss0fe44622011-07-03 13:37:31 -0300693 state->m_Regs[EP4] = (state->m_Regs[EP4] & ~0x1F); /* If level = 0, Cal mode = 0 */
Mauro Carvalho Chehab469ffe02011-07-03 18:12:26 -0300694 status = UpdateRegs(state, EP3, EP4);
695 if (status < 0)
696 break;
Oliver Endriss0fe44622011-07-03 13:37:31 -0300697 state->m_Regs[EB18] = (state->m_Regs[EB18] & ~0x03); /* AGC 1 Gain = 0 */
Mauro Carvalho Chehab469ffe02011-07-03 18:12:26 -0300698 status = UpdateReg(state, EB18);
699 if (status < 0)
700 break;
Oliver Endriss0fe44622011-07-03 13:37:31 -0300701 state->m_Regs[EB21] = (state->m_Regs[EB21] & ~0x03); /* AGC 2 Gain = 0 (Datasheet = 3) */
702 state->m_Regs[EB23] = (state->m_Regs[EB23] | 0x06); /* ForceLP_Fc2_En = 1, LPFc[2] = 1 */
Mauro Carvalho Chehab469ffe02011-07-03 18:12:26 -0300703 status = UpdateRegs(state, EB21, EB23);
704 if (status < 0)
705 break;
Oliver Endriss0fe44622011-07-03 13:37:31 -0300706 } while (0);
Ralph Metzlere8783952011-07-03 13:36:17 -0300707 return status;
708}
709
710static int CalcRFFilterCurve(struct tda_state *state)
711{
Ralph Metzlere8783952011-07-03 13:36:17 -0300712 int status = 0;
Oliver Endriss0fe44622011-07-03 13:37:31 -0300713 do {
714 msleep(200); /* Temperature stabilisation */
Mauro Carvalho Chehab469ffe02011-07-03 18:12:26 -0300715 status = PowerScanInit(state);
716 if (status < 0)
717 break;
718 status = RFTrackingFiltersInit(state, 0);
719 if (status < 0)
720 break;
721 status = RFTrackingFiltersInit(state, 1);
722 if (status < 0)
723 break;
724 status = RFTrackingFiltersInit(state, 2);
725 if (status < 0)
726 break;
727 status = RFTrackingFiltersInit(state, 3);
728 if (status < 0)
729 break;
730 status = RFTrackingFiltersInit(state, 4);
731 if (status < 0)
732 break;
733 status = RFTrackingFiltersInit(state, 5);
734 if (status < 0)
735 break;
736 status = RFTrackingFiltersInit(state, 6);
737 if (status < 0)
738 break;
739 status = ThermometerRead(state, &state->m_TMValue_RFCal); /* also switches off Cal mode !!! */
740 if (status < 0)
741 break;
Oliver Endriss0fe44622011-07-03 13:37:31 -0300742 } while (0);
Ralph Metzlere8783952011-07-03 13:36:17 -0300743
744 return status;
745}
746
747static int FixedContentsI2CUpdate(struct tda_state *state)
748{
749 static u8 InitRegs[] = {
Oliver Endriss0fe44622011-07-03 13:37:31 -0300750 0x08, 0x80, 0xC6,
751 0xDF, 0x16, 0x60, 0x80,
752 0x80, 0x00, 0x00, 0x00,
753 0x00, 0x00, 0x00, 0x00,
754 0xFC, 0x01, 0x84, 0x41,
755 0x01, 0x84, 0x40, 0x07,
756 0x00, 0x00, 0x96, 0x3F,
757 0xC1, 0x00, 0x8F, 0x00,
758 0x00, 0x8C, 0x00, 0x20,
759 0xB3, 0x48, 0xB0,
Ralph Metzlere8783952011-07-03 13:36:17 -0300760 };
761 int status = 0;
Oliver Endriss0fe44622011-07-03 13:37:31 -0300762 memcpy(&state->m_Regs[TM], InitRegs, EB23 - TM + 1);
Ralph Metzlere8783952011-07-03 13:36:17 -0300763 do {
Mauro Carvalho Chehab469ffe02011-07-03 18:12:26 -0300764 status = UpdateRegs(state, TM, EB23);
765 if (status < 0)
766 break;
Ralph Metzlere8783952011-07-03 13:36:17 -0300767
Oliver Endriss0fe44622011-07-03 13:37:31 -0300768 /* AGC1 gain setup */
Ralph Metzlere8783952011-07-03 13:36:17 -0300769 state->m_Regs[EB17] = 0x00;
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] = 0x03;
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] = 0x43;
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 state->m_Regs[EB17] = 0x4C;
Mauro Carvalho Chehab469ffe02011-07-03 18:12:26 -0300782 status = UpdateReg(state, EB17);
783 if (status < 0)
784 break;
Ralph Metzlere8783952011-07-03 13:36:17 -0300785
Oliver Endriss0fe44622011-07-03 13:37:31 -0300786 /* IRC Cal Low band */
Ralph Metzlere8783952011-07-03 13:36:17 -0300787 state->m_Regs[EP3] = 0x1F;
788 state->m_Regs[EP4] = 0x66;
789 state->m_Regs[EP5] = 0x81;
790 state->m_Regs[CPD] = 0xCC;
791 state->m_Regs[CD1] = 0x6C;
792 state->m_Regs[CD2] = 0x00;
793 state->m_Regs[CD3] = 0x00;
794 state->m_Regs[MPD] = 0xC5;
795 state->m_Regs[MD1] = 0x77;
796 state->m_Regs[MD2] = 0x08;
797 state->m_Regs[MD3] = 0x00;
Mauro Carvalho Chehab469ffe02011-07-03 18:12:26 -0300798 status = UpdateRegs(state, EP2, MD3); /* diff between sw and datasheet (ep3-md3) */
799 if (status < 0)
800 break;
Ralph Metzlere8783952011-07-03 13:36:17 -0300801
Oliver Endriss0fe44622011-07-03 13:37:31 -0300802#if 0
803 state->m_Regs[EB4] = 0x61; /* missing in sw */
Mauro Carvalho Chehab469ffe02011-07-03 18:12:26 -0300804 status = UpdateReg(state, EB4);
805 if (status < 0)
806 break;
Oliver Endriss0fe44622011-07-03 13:37:31 -0300807 msleep(1);
808 state->m_Regs[EB4] = 0x41;
Mauro Carvalho Chehab469ffe02011-07-03 18:12:26 -0300809 status = UpdateReg(state, EB4);
810 if (status < 0)
811 break;
Oliver Endriss0fe44622011-07-03 13:37:31 -0300812#endif
Ralph Metzlere8783952011-07-03 13:36:17 -0300813
814 msleep(5);
Mauro Carvalho Chehab469ffe02011-07-03 18:12:26 -0300815 status = UpdateReg(state, EP1);
816 if (status < 0)
817 break;
Ralph Metzlere8783952011-07-03 13:36:17 -0300818 msleep(5);
819
820 state->m_Regs[EP5] = 0x85;
821 state->m_Regs[CPD] = 0xCB;
822 state->m_Regs[CD1] = 0x66;
823 state->m_Regs[CD2] = 0x70;
Mauro Carvalho Chehab469ffe02011-07-03 18:12:26 -0300824 status = UpdateRegs(state, EP3, CD3);
825 if (status < 0)
826 break;
Ralph Metzlere8783952011-07-03 13:36:17 -0300827 msleep(5);
Mauro Carvalho Chehab469ffe02011-07-03 18:12:26 -0300828 status = UpdateReg(state, EP2);
829 if (status < 0)
830 break;
Ralph Metzlere8783952011-07-03 13:36:17 -0300831 msleep(30);
832
Oliver Endriss0fe44622011-07-03 13:37:31 -0300833 /* IRC Cal mid band */
Ralph Metzlere8783952011-07-03 13:36:17 -0300834 state->m_Regs[EP5] = 0x82;
835 state->m_Regs[CPD] = 0xA8;
836 state->m_Regs[CD2] = 0x00;
Oliver Endriss0fe44622011-07-03 13:37:31 -0300837 state->m_Regs[MPD] = 0xA1; /* Datasheet = 0xA9 */
Ralph Metzlere8783952011-07-03 13:36:17 -0300838 state->m_Regs[MD1] = 0x73;
839 state->m_Regs[MD2] = 0x1A;
Mauro Carvalho Chehab469ffe02011-07-03 18:12:26 -0300840 status = UpdateRegs(state, EP3, MD3);
841 if (status < 0)
842 break;
Ralph Metzlere8783952011-07-03 13:36:17 -0300843
844 msleep(5);
Mauro Carvalho Chehab469ffe02011-07-03 18:12:26 -0300845 status = UpdateReg(state, EP1);
846 if (status < 0)
847 break;
Ralph Metzlere8783952011-07-03 13:36:17 -0300848 msleep(5);
849
850 state->m_Regs[EP5] = 0x86;
851 state->m_Regs[CPD] = 0xA8;
852 state->m_Regs[CD1] = 0x66;
853 state->m_Regs[CD2] = 0xA0;
Mauro Carvalho Chehab469ffe02011-07-03 18:12:26 -0300854 status = UpdateRegs(state, EP3, CD3);
855 if (status < 0)
856 break;
Ralph Metzlere8783952011-07-03 13:36:17 -0300857 msleep(5);
Mauro Carvalho Chehab469ffe02011-07-03 18:12:26 -0300858 status = UpdateReg(state, EP2);
859 if (status < 0)
860 break;
Ralph Metzlere8783952011-07-03 13:36:17 -0300861 msleep(30);
862
Oliver Endriss0fe44622011-07-03 13:37:31 -0300863 /* IRC Cal high band */
Ralph Metzlere8783952011-07-03 13:36:17 -0300864 state->m_Regs[EP5] = 0x83;
865 state->m_Regs[CPD] = 0x98;
866 state->m_Regs[CD1] = 0x65;
867 state->m_Regs[CD2] = 0x00;
Oliver Endriss0fe44622011-07-03 13:37:31 -0300868 state->m_Regs[MPD] = 0x91; /* Datasheet = 0x91 */
Ralph Metzlere8783952011-07-03 13:36:17 -0300869 state->m_Regs[MD1] = 0x71;
870 state->m_Regs[MD2] = 0xCD;
Mauro Carvalho Chehab469ffe02011-07-03 18:12:26 -0300871 status = UpdateRegs(state, EP3, MD3);
872 if (status < 0)
873 break;
Ralph Metzlere8783952011-07-03 13:36:17 -0300874 msleep(5);
Mauro Carvalho Chehab469ffe02011-07-03 18:12:26 -0300875 status = UpdateReg(state, EP1);
876 if (status < 0)
877 break;
Ralph Metzlere8783952011-07-03 13:36:17 -0300878 msleep(5);
879 state->m_Regs[EP5] = 0x87;
880 state->m_Regs[CD1] = 0x65;
881 state->m_Regs[CD2] = 0x50;
Mauro Carvalho Chehab469ffe02011-07-03 18:12:26 -0300882 status = UpdateRegs(state, EP3, CD3);
883 if (status < 0)
884 break;
Ralph Metzlere8783952011-07-03 13:36:17 -0300885 msleep(5);
Mauro Carvalho Chehab469ffe02011-07-03 18:12:26 -0300886 status = UpdateReg(state, EP2);
887 if (status < 0)
888 break;
Ralph Metzlere8783952011-07-03 13:36:17 -0300889 msleep(30);
890
Oliver Endriss0fe44622011-07-03 13:37:31 -0300891 /* Back to normal */
Ralph Metzlere8783952011-07-03 13:36:17 -0300892 state->m_Regs[EP4] = 0x64;
Mauro Carvalho Chehab469ffe02011-07-03 18:12:26 -0300893 status = UpdateReg(state, EP4);
894 if (status < 0)
895 break;
896 status = UpdateReg(state, EP1);
897 if (status < 0)
898 break;
Ralph Metzlere8783952011-07-03 13:36:17 -0300899
Oliver Endriss0fe44622011-07-03 13:37:31 -0300900 } while (0);
Ralph Metzlere8783952011-07-03 13:36:17 -0300901 return status;
902}
903
904static int InitCal(struct tda_state *state)
905{
906 int status = 0;
907
Oliver Endriss0fe44622011-07-03 13:37:31 -0300908 do {
Mauro Carvalho Chehab469ffe02011-07-03 18:12:26 -0300909 status = FixedContentsI2CUpdate(state);
910 if (status < 0)
911 break;
912 status = CalcRFFilterCurve(state);
913 if (status < 0)
914 break;
915 status = StandBy(state);
916 if (status < 0)
917 break;
Oliver Endriss0fe44622011-07-03 13:37:31 -0300918 /* m_bInitDone = true; */
919 } while (0);
Ralph Metzlere8783952011-07-03 13:36:17 -0300920 return status;
921};
922
923static int RFTrackingFiltersCorrection(struct tda_state *state,
924 u32 Frequency)
925{
926 int status = 0;
927 s32 Cprog_table;
928 u8 RFBand;
929 u8 dCoverdT;
930
Oliver Endriss0fe44622011-07-03 13:37:31 -0300931 if (!SearchMap2(m_RF_Cal_Map, Frequency, &Cprog_table) ||
932 !SearchMap4(m_RF_Band_Map, Frequency, &RFBand) ||
933 !SearchMap1(m_RF_Cal_DC_Over_DT_Map, Frequency, &dCoverdT))
Ralph Metzlere8783952011-07-03 13:36:17 -0300934
Oliver Endriss0fe44622011-07-03 13:37:31 -0300935 return -EINVAL;
936
937 do {
Ralph Metzlere8783952011-07-03 13:36:17 -0300938 u8 TMValue_Current;
939 u32 RF1 = state->m_RF1[RFBand];
940 u32 RF2 = state->m_RF1[RFBand];
941 u32 RF3 = state->m_RF1[RFBand];
942 s32 RF_A1 = state->m_RF_A1[RFBand];
943 s32 RF_B1 = state->m_RF_B1[RFBand];
944 s32 RF_A2 = state->m_RF_A2[RFBand];
945 s32 RF_B2 = state->m_RF_B2[RFBand];
946 s32 Capprox = 0;
947 int TComp;
948
Oliver Endriss0fe44622011-07-03 13:37:31 -0300949 state->m_Regs[EP3] &= ~0xE0; /* Power up */
Mauro Carvalho Chehab469ffe02011-07-03 18:12:26 -0300950 status = UpdateReg(state, EP3);
951 if (status < 0)
952 break;
Ralph Metzlere8783952011-07-03 13:36:17 -0300953
Mauro Carvalho Chehab469ffe02011-07-03 18:12:26 -0300954 status = ThermometerRead(state, &TMValue_Current);
955 if (status < 0)
956 break;
Ralph Metzlere8783952011-07-03 13:36:17 -0300957
Oliver Endriss0fe44622011-07-03 13:37:31 -0300958 if (RF3 == 0 || Frequency < RF2)
Ralph Metzlere8783952011-07-03 13:36:17 -0300959 Capprox = RF_A1 * ((s32)(Frequency) - (s32)(RF1)) + RF_B1 + Cprog_table;
Ralph Metzlere8783952011-07-03 13:36:17 -0300960 else
Ralph Metzlere8783952011-07-03 13:36:17 -0300961 Capprox = RF_A2 * ((s32)(Frequency) - (s32)(RF2)) + RF_B2 + Cprog_table;
Ralph Metzlere8783952011-07-03 13:36:17 -0300962
963 TComp = (int)(dCoverdT) * ((int)(TMValue_Current) - (int)(state->m_TMValue_RFCal))/1000;
964
965 Capprox += TComp;
966
Oliver Endriss0fe44622011-07-03 13:37:31 -0300967 if (Capprox < 0)
968 Capprox = 0;
969 else if (Capprox > 255)
970 Capprox = 255;
Ralph Metzlere8783952011-07-03 13:36:17 -0300971
972
Oliver Endriss0fe44622011-07-03 13:37:31 -0300973 /* TODO Temperature compensation. There is defenitely a scale factor */
974 /* missing in the datasheet, so leave it out for now. */
975 state->m_Regs[EB14] = Capprox;
Ralph Metzlere8783952011-07-03 13:36:17 -0300976
Mauro Carvalho Chehab469ffe02011-07-03 18:12:26 -0300977 status = UpdateReg(state, EB14);
978 if (status < 0)
979 break;
Ralph Metzlere8783952011-07-03 13:36:17 -0300980
Oliver Endriss0fe44622011-07-03 13:37:31 -0300981 } while (0);
Ralph Metzlere8783952011-07-03 13:36:17 -0300982 return status;
983}
984
985static int ChannelConfiguration(struct tda_state *state,
986 u32 Frequency, int Standard)
987{
988
989 s32 IntermediateFrequency = m_StandardTable[Standard].m_IFFrequency;
990 int status = 0;
991
992 u8 BP_Filter = 0;
993 u8 RF_Band = 0;
994 u8 GainTaper = 0;
Mauro Carvalho Chehabea90f012011-07-03 18:06:07 -0300995 u8 IR_Meas = 0;
Ralph Metzlere8783952011-07-03 13:36:17 -0300996
Oliver Endriss0fe44622011-07-03 13:37:31 -0300997 state->IF = IntermediateFrequency;
Mauro Carvalho Chehabf3d40bd2011-07-04 14:00:25 -0300998 /* printk("tda18271c2dd: %s Freq = %d Standard = %d IF = %d\n", __func__, Frequency, Standard, IntermediateFrequency); */
Oliver Endriss0fe44622011-07-03 13:37:31 -0300999 /* get values from tables */
Ralph Metzlere8783952011-07-03 13:36:17 -03001000
Oliver Endriss0fe44622011-07-03 13:37:31 -03001001 if (!(SearchMap1(m_BP_Filter_Map, Frequency, &BP_Filter) &&
1002 SearchMap1(m_GainTaper_Map, Frequency, &GainTaper) &&
1003 SearchMap1(m_IR_Meas_Map, Frequency, &IR_Meas) &&
1004 SearchMap4(m_RF_Band_Map, Frequency, &RF_Band))) {
1005
Mauro Carvalho Chehabf3d40bd2011-07-04 14:00:25 -03001006 printk(KERN_ERR "tda18271c2dd: %s SearchMap failed\n", __func__);
Ralph Metzlere8783952011-07-03 13:36:17 -03001007 return -EINVAL;
1008 }
1009
Oliver Endriss0fe44622011-07-03 13:37:31 -03001010 do {
Ralph Metzlere8783952011-07-03 13:36:17 -03001011 state->m_Regs[EP3] = (state->m_Regs[EP3] & ~0x1F) | m_StandardTable[Standard].m_EP3_4_0;
Oliver Endriss0fe44622011-07-03 13:37:31 -03001012 state->m_Regs[EP3] &= ~0x04; /* switch RFAGC to high speed mode */
Ralph Metzlere8783952011-07-03 13:36:17 -03001013
Oliver Endriss0fe44622011-07-03 13:37:31 -03001014 /* m_EP4 default for XToutOn, CAL_Mode (0) */
1015 state->m_Regs[EP4] = state->m_EP4 | ((Standard > HF_AnalogMax) ? state->m_IFLevelDigital : state->m_IFLevelAnalog);
1016 /* state->m_Regs[EP4] = state->m_EP4 | state->m_IFLevelDigital; */
1017 if (Standard <= HF_AnalogMax)
1018 state->m_Regs[EP4] = state->m_EP4 | state->m_IFLevelAnalog;
1019 else if (Standard <= HF_ATSC)
1020 state->m_Regs[EP4] = state->m_EP4 | state->m_IFLevelDVBT;
1021 else if (Standard <= HF_DVBC)
1022 state->m_Regs[EP4] = state->m_EP4 | state->m_IFLevelDVBC;
1023 else
1024 state->m_Regs[EP4] = state->m_EP4 | state->m_IFLevelDigital;
Ralph Metzlere8783952011-07-03 13:36:17 -03001025
Oliver Endriss0fe44622011-07-03 13:37:31 -03001026 if ((Standard == HF_FM_Radio) && state->m_bFMInput)
Dan Carpenter58632812014-02-06 04:49:47 -03001027 state->m_Regs[EP4] |= 0x80;
Ralph Metzlere8783952011-07-03 13:36:17 -03001028
1029 state->m_Regs[MPD] &= ~0x80;
Oliver Endriss0fe44622011-07-03 13:37:31 -03001030 if (Standard > HF_AnalogMax)
1031 state->m_Regs[MPD] |= 0x80; /* Add IF_notch for digital */
Ralph Metzlere8783952011-07-03 13:36:17 -03001032
1033 state->m_Regs[EB22] = m_StandardTable[Standard].m_EB22;
1034
Oliver Endriss0fe44622011-07-03 13:37:31 -03001035 /* Note: This is missing from flowchart in TDA18271 specification ( 1.5 MHz cutoff for FM ) */
1036 if (Standard == HF_FM_Radio)
1037 state->m_Regs[EB23] |= 0x06; /* ForceLP_Fc2_En = 1, LPFc[2] = 1 */
1038 else
1039 state->m_Regs[EB23] &= ~0x06; /* ForceLP_Fc2_En = 0, LPFc[2] = 0 */
Ralph Metzlere8783952011-07-03 13:36:17 -03001040
Mauro Carvalho Chehab469ffe02011-07-03 18:12:26 -03001041 status = UpdateRegs(state, EB22, EB23);
1042 if (status < 0)
1043 break;
Ralph Metzlere8783952011-07-03 13:36:17 -03001044
Oliver Endriss0fe44622011-07-03 13:37:31 -03001045 state->m_Regs[EP1] = (state->m_Regs[EP1] & ~0x07) | 0x40 | BP_Filter; /* Dis_Power_level = 1, Filter */
Ralph Metzlere8783952011-07-03 13:36:17 -03001046 state->m_Regs[EP5] = (state->m_Regs[EP5] & ~0x07) | IR_Meas;
1047 state->m_Regs[EP2] = (RF_Band << 5) | GainTaper;
1048
1049 state->m_Regs[EB1] = (state->m_Regs[EB1] & ~0x07) |
Oliver Endriss0fe44622011-07-03 13:37:31 -03001050 (state->m_bMaster ? 0x04 : 0x00); /* CALVCO_FortLOn = MS */
1051 /* AGC1_always_master = 0 */
1052 /* AGC_firstn = 0 */
Mauro Carvalho Chehab469ffe02011-07-03 18:12:26 -03001053 status = UpdateReg(state, EB1);
1054 if (status < 0)
1055 break;
Ralph Metzlere8783952011-07-03 13:36:17 -03001056
Oliver Endriss0fe44622011-07-03 13:37:31 -03001057 if (state->m_bMaster) {
Mauro Carvalho Chehab469ffe02011-07-03 18:12:26 -03001058 status = CalcMainPLL(state, Frequency + IntermediateFrequency);
1059 if (status < 0)
1060 break;
1061 status = UpdateRegs(state, TM, EP5);
1062 if (status < 0)
1063 break;
Oliver Endriss0fe44622011-07-03 13:37:31 -03001064 state->m_Regs[EB4] |= 0x20; /* LO_forceSrce = 1 */
Mauro Carvalho Chehab469ffe02011-07-03 18:12:26 -03001065 status = UpdateReg(state, EB4);
1066 if (status < 0)
1067 break;
Ralph Metzlere8783952011-07-03 13:36:17 -03001068 msleep(1);
Oliver Endriss0fe44622011-07-03 13:37:31 -03001069 state->m_Regs[EB4] &= ~0x20; /* LO_forceSrce = 0 */
Mauro Carvalho Chehab469ffe02011-07-03 18:12:26 -03001070 status = UpdateReg(state, EB4);
1071 if (status < 0)
1072 break;
Oliver Endriss0fe44622011-07-03 13:37:31 -03001073 } else {
Mauro Carvalho Chehabea90f012011-07-03 18:06:07 -03001074 u8 PostDiv = 0;
Ralph Metzlere8783952011-07-03 13:36:17 -03001075 u8 Div;
Mauro Carvalho Chehab469ffe02011-07-03 18:12:26 -03001076 status = CalcCalPLL(state, Frequency + IntermediateFrequency);
1077 if (status < 0)
1078 break;
Ralph Metzlere8783952011-07-03 13:36:17 -03001079
Oliver Endriss0fe44622011-07-03 13:37:31 -03001080 SearchMap3(m_Cal_PLL_Map, Frequency + IntermediateFrequency, &PostDiv, &Div);
Ralph Metzlere8783952011-07-03 13:36:17 -03001081 state->m_Regs[MPD] = (state->m_Regs[MPD] & ~0x7F) | (PostDiv & 0x77);
Mauro Carvalho Chehab469ffe02011-07-03 18:12:26 -03001082 status = UpdateReg(state, MPD);
1083 if (status < 0)
1084 break;
1085 status = UpdateRegs(state, TM, EP5);
1086 if (status < 0)
1087 break;
Ralph Metzlere8783952011-07-03 13:36:17 -03001088
Oliver Endriss0fe44622011-07-03 13:37:31 -03001089 state->m_Regs[EB7] |= 0x20; /* CAL_forceSrce = 1 */
Mauro Carvalho Chehab469ffe02011-07-03 18:12:26 -03001090 status = UpdateReg(state, EB7);
1091 if (status < 0)
1092 break;
Ralph Metzlere8783952011-07-03 13:36:17 -03001093 msleep(1);
Oliver Endriss0fe44622011-07-03 13:37:31 -03001094 state->m_Regs[EB7] &= ~0x20; /* CAL_forceSrce = 0 */
Mauro Carvalho Chehab469ffe02011-07-03 18:12:26 -03001095 status = UpdateReg(state, EB7);
1096 if (status < 0)
1097 break;
Ralph Metzlere8783952011-07-03 13:36:17 -03001098 }
1099 msleep(20);
Oliver Endriss0fe44622011-07-03 13:37:31 -03001100 if (Standard != HF_FM_Radio)
1101 state->m_Regs[EP3] |= 0x04; /* RFAGC to normal mode */
Mauro Carvalho Chehab469ffe02011-07-03 18:12:26 -03001102 status = UpdateReg(state, EP3);
1103 if (status < 0)
1104 break;
Ralph Metzlere8783952011-07-03 13:36:17 -03001105
Oliver Endriss0fe44622011-07-03 13:37:31 -03001106 } while (0);
Ralph Metzlere8783952011-07-03 13:36:17 -03001107 return status;
1108}
1109
Oliver Endriss0fe44622011-07-03 13:37:31 -03001110static int sleep(struct dvb_frontend *fe)
Ralph Metzlere8783952011-07-03 13:36:17 -03001111{
1112 struct tda_state *state = fe->tuner_priv;
1113
1114 StandBy(state);
1115 return 0;
1116}
1117
Oliver Endriss0fe44622011-07-03 13:37:31 -03001118static int init(struct dvb_frontend *fe)
Ralph Metzlere8783952011-07-03 13:36:17 -03001119{
Ralph Metzlere8783952011-07-03 13:36:17 -03001120 return 0;
1121}
1122
Mauro Carvalho Chehabf2709c22016-11-18 20:30:51 -02001123static void release(struct dvb_frontend *fe)
1124{
1125 kfree(fe->tuner_priv);
1126 fe->tuner_priv = NULL;
1127}
1128
1129
Mauro Carvalho Chehab14d24d12011-12-24 12:24:33 -03001130static int set_params(struct dvb_frontend *fe)
Ralph Metzlere8783952011-07-03 13:36:17 -03001131{
1132 struct tda_state *state = fe->tuner_priv;
1133 int status = 0;
1134 int Standard;
Mauro Carvalho Chehabfd66c452011-12-17 20:36:57 -03001135 u32 bw = fe->dtv_property_cache.bandwidth_hz;
1136 u32 delsys = fe->dtv_property_cache.delivery_system;
Ralph Metzlere8783952011-07-03 13:36:17 -03001137
Mauro Carvalho Chehabfd66c452011-12-17 20:36:57 -03001138 state->m_Frequency = fe->dtv_property_cache.frequency;
Ralph Metzlere8783952011-07-03 13:36:17 -03001139
Mauro Carvalho Chehabfd66c452011-12-17 20:36:57 -03001140 switch (delsys) {
1141 case SYS_DVBT:
1142 case SYS_DVBT2:
1143 switch (bw) {
1144 case 6000000:
Ralph Metzlere8783952011-07-03 13:36:17 -03001145 Standard = HF_DVBT_6MHZ;
1146 break;
Mauro Carvalho Chehabfd66c452011-12-17 20:36:57 -03001147 case 7000000:
Ralph Metzlere8783952011-07-03 13:36:17 -03001148 Standard = HF_DVBT_7MHZ;
1149 break;
Mauro Carvalho Chehabfd66c452011-12-17 20:36:57 -03001150 case 8000000:
Ralph Metzlere8783952011-07-03 13:36:17 -03001151 Standard = HF_DVBT_8MHZ;
1152 break;
Mauro Carvalho Chehabfd66c452011-12-17 20:36:57 -03001153 default:
1154 return -EINVAL;
Ralph Metzlere8783952011-07-03 13:36:17 -03001155 }
Daniel Schellerca747d02018-06-24 09:42:50 -04001156 break;
Mauro Carvalho Chehabfd66c452011-12-17 20:36:57 -03001157 case SYS_DVBC_ANNEX_A:
1158 case SYS_DVBC_ANNEX_C:
Mauro Carvalho Chehab2440f7a2011-11-11 20:26:03 -02001159 if (bw <= 6000000)
Mauro Carvalho Chehabcf845292011-07-28 15:49:43 -03001160 Standard = HF_DVBC_6MHZ;
Mauro Carvalho Chehab2440f7a2011-11-11 20:26:03 -02001161 else if (bw <= 7000000)
1162 Standard = HF_DVBC_7MHZ;
Mauro Carvalho Chehabcf845292011-07-28 15:49:43 -03001163 else
1164 Standard = HF_DVBC_8MHZ;
Mauro Carvalho Chehab1ca8dde2011-12-30 15:34:51 -02001165 break;
Mauro Carvalho Chehabfd66c452011-12-17 20:36:57 -03001166 default:
Ralph Metzlere8783952011-07-03 13:36:17 -03001167 return -EINVAL;
Mauro Carvalho Chehabfd66c452011-12-17 20:36:57 -03001168 }
Ralph Metzlere8783952011-07-03 13:36:17 -03001169 do {
Mauro Carvalho Chehabfd66c452011-12-17 20:36:57 -03001170 status = RFTrackingFiltersCorrection(state, state->m_Frequency);
Mauro Carvalho Chehab469ffe02011-07-03 18:12:26 -03001171 if (status < 0)
1172 break;
Mauro Carvalho Chehabfd66c452011-12-17 20:36:57 -03001173 status = ChannelConfiguration(state, state->m_Frequency,
1174 Standard);
Mauro Carvalho Chehab469ffe02011-07-03 18:12:26 -03001175 if (status < 0)
1176 break;
Ralph Metzlere8783952011-07-03 13:36:17 -03001177
Oliver Endriss0fe44622011-07-03 13:37:31 -03001178 msleep(state->m_SettlingTime); /* Allow AGC's to settle down */
1179 } while (0);
Ralph Metzlere8783952011-07-03 13:36:17 -03001180 return status;
1181}
1182
1183#if 0
Oliver Endriss0fe44622011-07-03 13:37:31 -03001184static int GetSignalStrength(s32 *pSignalStrength, u32 RFAgc, u32 IFAgc)
Ralph Metzlere8783952011-07-03 13:36:17 -03001185{
Oliver Endriss0fe44622011-07-03 13:37:31 -03001186 if (IFAgc < 500) {
1187 /* Scale this from 0 to 50000 */
Ralph Metzlere8783952011-07-03 13:36:17 -03001188 *pSignalStrength = IFAgc * 100;
1189 } else {
Oliver Endriss0fe44622011-07-03 13:37:31 -03001190 /* Scale range 500-1500 to 50000-80000 */
Ralph Metzlere8783952011-07-03 13:36:17 -03001191 *pSignalStrength = 50000 + (IFAgc - 500) * 30;
1192 }
1193
1194 return 0;
1195}
1196#endif
1197
Mauro Carvalho Chehab8513e142011-09-03 11:40:02 -03001198static int get_if_frequency(struct dvb_frontend *fe, u32 *frequency)
Ralph Metzlere8783952011-07-03 13:36:17 -03001199{
1200 struct tda_state *state = fe->tuner_priv;
1201
1202 *frequency = state->IF;
1203 return 0;
1204}
1205
1206static int get_bandwidth(struct dvb_frontend *fe, u32 *bandwidth)
1207{
Oliver Endriss0fe44622011-07-03 13:37:31 -03001208 /* struct tda_state *state = fe->tuner_priv; */
1209 /* *bandwidth = priv->bandwidth; */
Ralph Metzlere8783952011-07-03 13:36:17 -03001210 return 0;
1211}
1212
1213
Julia Lawall14c4bf32016-09-11 11:44:12 -03001214static const struct dvb_tuner_ops tuner_ops = {
Ralph Metzlere8783952011-07-03 13:36:17 -03001215 .info = {
1216 .name = "NXP TDA18271C2D",
Mauro Carvalho Chehaba3f90c72018-07-05 18:59:35 -04001217 .frequency_min_hz = 47125 * kHz,
1218 .frequency_max_hz = 865 * MHz,
1219 .frequency_step_hz = 62500
Ralph Metzlere8783952011-07-03 13:36:17 -03001220 },
1221 .init = init,
1222 .sleep = sleep,
1223 .set_params = set_params,
Mauro Carvalho Chehabf2709c22016-11-18 20:30:51 -02001224 .release = release,
Mauro Carvalho Chehab8513e142011-09-03 11:40:02 -03001225 .get_if_frequency = get_if_frequency,
Ralph Metzlere8783952011-07-03 13:36:17 -03001226 .get_bandwidth = get_bandwidth,
1227};
1228
1229struct dvb_frontend *tda18271c2dd_attach(struct dvb_frontend *fe,
1230 struct i2c_adapter *i2c, u8 adr)
1231{
1232 struct tda_state *state;
1233
1234 state = kzalloc(sizeof(struct tda_state), GFP_KERNEL);
1235 if (!state)
1236 return NULL;
1237
1238 fe->tuner_priv = state;
1239 state->adr = adr;
1240 state->i2c = i2c;
1241 memcpy(&fe->ops.tuner_ops, &tuner_ops, sizeof(struct dvb_tuner_ops));
1242 reset(state);
1243 InitCal(state);
1244
1245 return fe;
1246}
Ralph Metzlere8783952011-07-03 13:36:17 -03001247EXPORT_SYMBOL_GPL(tda18271c2dd_attach);
Oliver Endriss0fe44622011-07-03 13:37:31 -03001248
Ralph Metzlere8783952011-07-03 13:36:17 -03001249MODULE_DESCRIPTION("TDA18271C2 driver");
1250MODULE_AUTHOR("DD");
1251MODULE_LICENSE("GPL");