• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 // SPDX-License-Identifier: GPL-2.0-only
2 /*
3  * tda18271c2dd: Driver for the TDA18271C2 tuner
4  *
5  * Copyright (C) 2010 Digital Devices GmbH
6  */
7 
8 #include <linux/kernel.h>
9 #include <linux/module.h>
10 #include <linux/init.h>
11 #include <linux/delay.h>
12 #include <linux/firmware.h>
13 #include <linux/i2c.h>
14 #include <asm/div64.h>
15 
16 #include <media/dvb_frontend.h>
17 #include "tda18271c2dd.h"
18 
19 /* Max transfer size done by I2C transfer functions */
20 #define MAX_XFER_SIZE  64
21 
22 struct SStandardParam {
23 	s32   m_IFFrequency;
24 	u32   m_BandWidth;
25 	u8    m_EP3_4_0;
26 	u8    m_EB22;
27 };
28 
29 struct SMap {
30 	u32   m_Frequency;
31 	u8    m_Param;
32 };
33 
34 struct SMapI {
35 	u32   m_Frequency;
36 	s32    m_Param;
37 };
38 
39 struct SMap2 {
40 	u32   m_Frequency;
41 	u8    m_Param1;
42 	u8    m_Param2;
43 };
44 
45 struct SRFBandMap {
46 	u32   m_RF_max;
47 	u32   m_RF1_Default;
48 	u32   m_RF2_Default;
49 	u32   m_RF3_Default;
50 };
51 
52 enum ERegister {
53 	ID = 0,
54 	TM,
55 	PL,
56 	EP1, EP2, EP3, EP4, EP5,
57 	CPD, CD1, CD2, CD3,
58 	MPD, MD1, MD2, MD3,
59 	EB1, EB2, EB3, EB4, EB5, EB6, EB7, EB8, EB9, EB10,
60 	EB11, EB12, EB13, EB14, EB15, EB16, EB17, EB18, EB19, EB20,
61 	EB21, EB22, EB23,
62 	NUM_REGS
63 };
64 
65 struct tda_state {
66 	struct i2c_adapter *i2c;
67 	u8 adr;
68 
69 	u32   m_Frequency;
70 	u32   IF;
71 
72 	u8    m_IFLevelAnalog;
73 	u8    m_IFLevelDigital;
74 	u8    m_IFLevelDVBC;
75 	u8    m_IFLevelDVBT;
76 
77 	u8    m_EP4;
78 	u8    m_EP3_Standby;
79 
80 	bool  m_bMaster;
81 
82 	s32   m_SettlingTime;
83 
84 	u8    m_Regs[NUM_REGS];
85 
86 	/* Tracking filter settings for band 0..6 */
87 	u32   m_RF1[7];
88 	s32   m_RF_A1[7];
89 	s32   m_RF_B1[7];
90 	u32   m_RF2[7];
91 	s32   m_RF_A2[7];
92 	s32   m_RF_B2[7];
93 	u32   m_RF3[7];
94 
95 	u8    m_TMValue_RFCal;    /* Calibration temperature */
96 
97 	bool  m_bFMInput;         /* true to use Pin 8 for FM Radio */
98 
99 };
100 
101 static int PowerScan(struct tda_state *state,
102 		     u8 RFBand, u32 RF_in,
103 		     u32 *pRF_Out, bool *pbcal);
104 
i2c_readn(struct i2c_adapter * adapter,u8 adr,u8 * data,int len)105 static int i2c_readn(struct i2c_adapter *adapter, u8 adr, u8 *data, int len)
106 {
107 	struct i2c_msg msgs[1] = {{.addr = adr,  .flags = I2C_M_RD,
108 				   .buf  = data, .len   = len} };
109 	return (i2c_transfer(adapter, msgs, 1) == 1) ? 0 : -1;
110 }
111 
i2c_write(struct i2c_adapter * adap,u8 adr,u8 * data,int len)112 static int i2c_write(struct i2c_adapter *adap, u8 adr, u8 *data, int len)
113 {
114 	struct i2c_msg msg = {.addr = adr, .flags = 0,
115 			      .buf = data, .len = len};
116 
117 	if (i2c_transfer(adap, &msg, 1) != 1) {
118 		printk(KERN_ERR "tda18271c2dd: i2c write error at addr %i\n", adr);
119 		return -1;
120 	}
121 	return 0;
122 }
123 
WriteRegs(struct tda_state * state,u8 SubAddr,u8 * Regs,u16 nRegs)124 static int WriteRegs(struct tda_state *state,
125 		     u8 SubAddr, u8 *Regs, u16 nRegs)
126 {
127 	u8 data[MAX_XFER_SIZE];
128 
129 	if (1 + nRegs > sizeof(data)) {
130 		printk(KERN_WARNING
131 		       "%s: i2c wr: len=%d is too big!\n",
132 		       KBUILD_MODNAME, nRegs);
133 		return -EINVAL;
134 	}
135 
136 	data[0] = SubAddr;
137 	memcpy(data + 1, Regs, nRegs);
138 	return i2c_write(state->i2c, state->adr, data, nRegs + 1);
139 }
140 
WriteReg(struct tda_state * state,u8 SubAddr,u8 Reg)141 static int WriteReg(struct tda_state *state, u8 SubAddr, u8 Reg)
142 {
143 	u8 msg[2] = {SubAddr, Reg};
144 
145 	return i2c_write(state->i2c, state->adr, msg, 2);
146 }
147 
Read(struct tda_state * state,u8 * Regs)148 static int Read(struct tda_state *state, u8 * Regs)
149 {
150 	return i2c_readn(state->i2c, state->adr, Regs, 16);
151 }
152 
ReadExtented(struct tda_state * state,u8 * Regs)153 static int ReadExtented(struct tda_state *state, u8 * Regs)
154 {
155 	return i2c_readn(state->i2c, state->adr, Regs, NUM_REGS);
156 }
157 
UpdateRegs(struct tda_state * state,u8 RegFrom,u8 RegTo)158 static int UpdateRegs(struct tda_state *state, u8 RegFrom, u8 RegTo)
159 {
160 	return WriteRegs(state, RegFrom,
161 			 &state->m_Regs[RegFrom], RegTo-RegFrom+1);
162 }
UpdateReg(struct tda_state * state,u8 Reg)163 static int UpdateReg(struct tda_state *state, u8 Reg)
164 {
165 	return WriteReg(state, Reg, state->m_Regs[Reg]);
166 }
167 
168 #include "tda18271c2dd_maps.h"
169 
reset(struct tda_state * state)170 static void reset(struct tda_state *state)
171 {
172 	u32   ulIFLevelAnalog = 0;
173 	u32   ulIFLevelDigital = 2;
174 	u32   ulIFLevelDVBC = 7;
175 	u32   ulIFLevelDVBT = 6;
176 	u32   ulXTOut = 0;
177 	u32   ulStandbyMode = 0x06;    /* Send in stdb, but leave osc on */
178 	u32   ulSlave = 0;
179 	u32   ulFMInput = 0;
180 	u32   ulSettlingTime = 100;
181 
182 	state->m_Frequency         = 0;
183 	state->m_SettlingTime = 100;
184 	state->m_IFLevelAnalog = (ulIFLevelAnalog & 0x07) << 2;
185 	state->m_IFLevelDigital = (ulIFLevelDigital & 0x07) << 2;
186 	state->m_IFLevelDVBC = (ulIFLevelDVBC & 0x07) << 2;
187 	state->m_IFLevelDVBT = (ulIFLevelDVBT & 0x07) << 2;
188 
189 	state->m_EP4 = 0x20;
190 	if (ulXTOut != 0)
191 		state->m_EP4 |= 0x40;
192 
193 	state->m_EP3_Standby = ((ulStandbyMode & 0x07) << 5) | 0x0F;
194 	state->m_bMaster = (ulSlave == 0);
195 
196 	state->m_SettlingTime = ulSettlingTime;
197 
198 	state->m_bFMInput = (ulFMInput == 2);
199 }
200 
SearchMap1(const struct SMap map[],u32 frequency,u8 * param)201 static bool SearchMap1(const struct SMap map[], u32 frequency, u8 *param)
202 {
203 	int i = 0;
204 
205 	while ((map[i].m_Frequency != 0) && (frequency > map[i].m_Frequency))
206 		i += 1;
207 	if (map[i].m_Frequency == 0)
208 		return false;
209 	*param = map[i].m_Param;
210 	return true;
211 }
212 
SearchMap2(const struct SMapI map[],u32 frequency,s32 * param)213 static bool SearchMap2(const struct SMapI map[], u32 frequency, s32 *param)
214 {
215 	int i = 0;
216 
217 	while ((map[i].m_Frequency != 0) &&
218 	       (frequency > map[i].m_Frequency))
219 		i += 1;
220 	if (map[i].m_Frequency == 0)
221 		return false;
222 	*param = map[i].m_Param;
223 	return true;
224 }
225 
SearchMap3(const struct SMap2 map[],u32 frequency,u8 * param1,u8 * param2)226 static bool SearchMap3(const struct SMap2 map[], u32 frequency, u8 *param1,
227 		       u8 *param2)
228 {
229 	int i = 0;
230 
231 	while ((map[i].m_Frequency != 0) &&
232 	       (frequency > map[i].m_Frequency))
233 		i += 1;
234 	if (map[i].m_Frequency == 0)
235 		return false;
236 	*param1 = map[i].m_Param1;
237 	*param2 = map[i].m_Param2;
238 	return true;
239 }
240 
SearchMap4(const struct SRFBandMap map[],u32 frequency,u8 * rfband)241 static bool SearchMap4(const struct SRFBandMap map[], u32 frequency, u8 *rfband)
242 {
243 	int i = 0;
244 
245 	while (i < 7 && (frequency > map[i].m_RF_max))
246 		i += 1;
247 	if (i == 7)
248 		return false;
249 	*rfband = i;
250 	return true;
251 }
252 
ThermometerRead(struct tda_state * state,u8 * pTM_Value)253 static int ThermometerRead(struct tda_state *state, u8 *pTM_Value)
254 {
255 	int status = 0;
256 
257 	do {
258 		u8 Regs[16];
259 		state->m_Regs[TM] |= 0x10;
260 		status = UpdateReg(state, TM);
261 		if (status < 0)
262 			break;
263 		status = Read(state, Regs);
264 		if (status < 0)
265 			break;
266 		if (((Regs[TM] & 0x0F) == 0 && (Regs[TM] & 0x20) == 0x20) ||
267 		    ((Regs[TM] & 0x0F) == 8 && (Regs[TM] & 0x20) == 0x00)) {
268 			state->m_Regs[TM] ^= 0x20;
269 			status = UpdateReg(state, TM);
270 			if (status < 0)
271 				break;
272 			msleep(10);
273 			status = Read(state, Regs);
274 			if (status < 0)
275 				break;
276 		}
277 		*pTM_Value = (Regs[TM] & 0x20)
278 				? m_Thermometer_Map_2[Regs[TM] & 0x0F]
279 				: m_Thermometer_Map_1[Regs[TM] & 0x0F] ;
280 		state->m_Regs[TM] &= ~0x10;        /* Thermometer off */
281 		status = UpdateReg(state, TM);
282 		if (status < 0)
283 			break;
284 		state->m_Regs[EP4] &= ~0x03;       /* CAL_mode = 0 ????????? */
285 		status = UpdateReg(state, EP4);
286 		if (status < 0)
287 			break;
288 	} while (0);
289 
290 	return status;
291 }
292 
StandBy(struct tda_state * state)293 static int StandBy(struct tda_state *state)
294 {
295 	int status = 0;
296 	do {
297 		state->m_Regs[EB12] &= ~0x20;  /* PD_AGC1_Det = 0 */
298 		status = UpdateReg(state, EB12);
299 		if (status < 0)
300 			break;
301 		state->m_Regs[EB18] &= ~0x83;  /* AGC1_loop_off = 0, AGC1_Gain = 6 dB */
302 		status = UpdateReg(state, EB18);
303 		if (status < 0)
304 			break;
305 		state->m_Regs[EB21] |= 0x03; /* AGC2_Gain = -6 dB */
306 		state->m_Regs[EP3] = state->m_EP3_Standby;
307 		status = UpdateReg(state, EP3);
308 		if (status < 0)
309 			break;
310 		state->m_Regs[EB23] &= ~0x06; /* ForceLP_Fc2_En = 0, LP_Fc[2] = 0 */
311 		status = UpdateRegs(state, EB21, EB23);
312 		if (status < 0)
313 			break;
314 	} while (0);
315 	return status;
316 }
317 
CalcMainPLL(struct tda_state * state,u32 freq)318 static int CalcMainPLL(struct tda_state *state, u32 freq)
319 {
320 
321 	u8  PostDiv;
322 	u8  Div;
323 	u64 OscFreq;
324 	u32 MainDiv;
325 
326 	if (!SearchMap3(m_Main_PLL_Map, freq, &PostDiv, &Div))
327 		return -EINVAL;
328 
329 	OscFreq = (u64) freq * (u64) Div;
330 	OscFreq *= (u64) 16384;
331 	do_div(OscFreq, (u64)16000000);
332 	MainDiv = OscFreq;
333 
334 	state->m_Regs[MPD] = PostDiv & 0x77;
335 	state->m_Regs[MD1] = ((MainDiv >> 16) & 0x7F);
336 	state->m_Regs[MD2] = ((MainDiv >>  8) & 0xFF);
337 	state->m_Regs[MD3] = (MainDiv & 0xFF);
338 
339 	return UpdateRegs(state, MPD, MD3);
340 }
341 
CalcCalPLL(struct tda_state * state,u32 freq)342 static int CalcCalPLL(struct tda_state *state, u32 freq)
343 {
344 	u8 PostDiv;
345 	u8 Div;
346 	u64 OscFreq;
347 	u32 CalDiv;
348 
349 	if (!SearchMap3(m_Cal_PLL_Map, freq, &PostDiv, &Div))
350 		return -EINVAL;
351 
352 	OscFreq = (u64)freq * (u64)Div;
353 	/* CalDiv = u32( OscFreq * 16384 / 16000000 ); */
354 	OscFreq *= (u64)16384;
355 	do_div(OscFreq, (u64)16000000);
356 	CalDiv = OscFreq;
357 
358 	state->m_Regs[CPD] = PostDiv;
359 	state->m_Regs[CD1] = ((CalDiv >> 16) & 0xFF);
360 	state->m_Regs[CD2] = ((CalDiv >>  8) & 0xFF);
361 	state->m_Regs[CD3] = (CalDiv & 0xFF);
362 
363 	return UpdateRegs(state, CPD, CD3);
364 }
365 
CalibrateRF(struct tda_state * state,u8 RFBand,u32 freq,s32 * pCprog)366 static int CalibrateRF(struct tda_state *state,
367 		       u8 RFBand, u32 freq, s32 *pCprog)
368 {
369 	int status = 0;
370 	u8 Regs[NUM_REGS];
371 	do {
372 		u8 BP_Filter = 0;
373 		u8 GainTaper = 0;
374 		u8 RFC_K = 0;
375 		u8 RFC_M = 0;
376 
377 		state->m_Regs[EP4] &= ~0x03; /* CAL_mode = 0 */
378 		status = UpdateReg(state, EP4);
379 		if (status < 0)
380 			break;
381 		state->m_Regs[EB18] |= 0x03;  /* AGC1_Gain = 3 */
382 		status = UpdateReg(state, EB18);
383 		if (status < 0)
384 			break;
385 
386 		/* Switching off LT (as datasheet says) causes calibration on C1 to fail */
387 		/* (Readout of Cprog is always 255) */
388 		if (state->m_Regs[ID] != 0x83)    /* C1: ID == 83, C2: ID == 84 */
389 			state->m_Regs[EP3] |= 0x40; /* SM_LT = 1 */
390 
391 		if (!(SearchMap1(m_BP_Filter_Map, freq, &BP_Filter) &&
392 			SearchMap1(m_GainTaper_Map, freq, &GainTaper) &&
393 			SearchMap3(m_KM_Map, freq, &RFC_K, &RFC_M)))
394 			return -EINVAL;
395 
396 		state->m_Regs[EP1] = (state->m_Regs[EP1] & ~0x07) | BP_Filter;
397 		state->m_Regs[EP2] = (RFBand << 5) | GainTaper;
398 
399 		state->m_Regs[EB13] = (state->m_Regs[EB13] & ~0x7C) | (RFC_K << 4) | (RFC_M << 2);
400 
401 		status = UpdateRegs(state, EP1, EP3);
402 		if (status < 0)
403 			break;
404 		status = UpdateReg(state, EB13);
405 		if (status < 0)
406 			break;
407 
408 		state->m_Regs[EB4] |= 0x20;    /* LO_ForceSrce = 1 */
409 		status = UpdateReg(state, EB4);
410 		if (status < 0)
411 			break;
412 
413 		state->m_Regs[EB7] |= 0x20;    /* CAL_ForceSrce = 1 */
414 		status = UpdateReg(state, EB7);
415 		if (status < 0)
416 			break;
417 
418 		state->m_Regs[EB14] = 0; /* RFC_Cprog = 0 */
419 		status = UpdateReg(state, EB14);
420 		if (status < 0)
421 			break;
422 
423 		state->m_Regs[EB20] &= ~0x20;  /* ForceLock = 0; */
424 		status = UpdateReg(state, EB20);
425 		if (status < 0)
426 			break;
427 
428 		state->m_Regs[EP4] |= 0x03;  /* CAL_Mode = 3 */
429 		status = UpdateRegs(state, EP4, EP5);
430 		if (status < 0)
431 			break;
432 
433 		status = CalcCalPLL(state, freq);
434 		if (status < 0)
435 			break;
436 		status = CalcMainPLL(state, freq + 1000000);
437 		if (status < 0)
438 			break;
439 
440 		msleep(5);
441 		status = UpdateReg(state, EP2);
442 		if (status < 0)
443 			break;
444 		status = UpdateReg(state, EP1);
445 		if (status < 0)
446 			break;
447 		status = UpdateReg(state, EP2);
448 		if (status < 0)
449 			break;
450 		status = UpdateReg(state, EP1);
451 		if (status < 0)
452 			break;
453 
454 		state->m_Regs[EB4] &= ~0x20;    /* LO_ForceSrce = 0 */
455 		status = UpdateReg(state, EB4);
456 		if (status < 0)
457 			break;
458 
459 		state->m_Regs[EB7] &= ~0x20;    /* CAL_ForceSrce = 0 */
460 		status = UpdateReg(state, EB7);
461 		if (status < 0)
462 			break;
463 		msleep(10);
464 
465 		state->m_Regs[EB20] |= 0x20;  /* ForceLock = 1; */
466 		status = UpdateReg(state, EB20);
467 		if (status < 0)
468 			break;
469 		msleep(60);
470 
471 		state->m_Regs[EP4] &= ~0x03;  /* CAL_Mode = 0 */
472 		state->m_Regs[EP3] &= ~0x40; /* SM_LT = 0 */
473 		state->m_Regs[EB18] &= ~0x03;  /* AGC1_Gain = 0 */
474 		status = UpdateReg(state, EB18);
475 		if (status < 0)
476 			break;
477 		status = UpdateRegs(state, EP3, EP4);
478 		if (status < 0)
479 			break;
480 		status = UpdateReg(state, EP1);
481 		if (status < 0)
482 			break;
483 
484 		status = ReadExtented(state, Regs);
485 		if (status < 0)
486 			break;
487 
488 		*pCprog = Regs[EB14];
489 
490 	} while (0);
491 	return status;
492 }
493 
RFTrackingFiltersInit(struct tda_state * state,u8 RFBand)494 static int RFTrackingFiltersInit(struct tda_state *state,
495 				 u8 RFBand)
496 {
497 	int status = 0;
498 
499 	u32   RF1 = m_RF_Band_Map[RFBand].m_RF1_Default;
500 	u32   RF2 = m_RF_Band_Map[RFBand].m_RF2_Default;
501 	u32   RF3 = m_RF_Band_Map[RFBand].m_RF3_Default;
502 	bool    bcal = false;
503 
504 	s32    Cprog_cal1 = 0;
505 	s32    Cprog_table1 = 0;
506 	s32    Cprog_cal2 = 0;
507 	s32    Cprog_table2 = 0;
508 	s32    Cprog_cal3 = 0;
509 	s32    Cprog_table3 = 0;
510 
511 	state->m_RF_A1[RFBand] = 0;
512 	state->m_RF_B1[RFBand] = 0;
513 	state->m_RF_A2[RFBand] = 0;
514 	state->m_RF_B2[RFBand] = 0;
515 
516 	do {
517 		status = PowerScan(state, RFBand, RF1, &RF1, &bcal);
518 		if (status < 0)
519 			break;
520 		if (bcal) {
521 			status = CalibrateRF(state, RFBand, RF1, &Cprog_cal1);
522 			if (status < 0)
523 				break;
524 		}
525 		SearchMap2(m_RF_Cal_Map, RF1, &Cprog_table1);
526 		if (!bcal)
527 			Cprog_cal1 = Cprog_table1;
528 		state->m_RF_B1[RFBand] = Cprog_cal1 - Cprog_table1;
529 		/* state->m_RF_A1[RF_Band] = ???? */
530 
531 		if (RF2 == 0)
532 			break;
533 
534 		status = PowerScan(state, RFBand, RF2, &RF2, &bcal);
535 		if (status < 0)
536 			break;
537 		if (bcal) {
538 			status = CalibrateRF(state, RFBand, RF2, &Cprog_cal2);
539 			if (status < 0)
540 				break;
541 		}
542 		SearchMap2(m_RF_Cal_Map, RF2, &Cprog_table2);
543 		if (!bcal)
544 			Cprog_cal2 = Cprog_table2;
545 
546 		state->m_RF_A1[RFBand] =
547 			(Cprog_cal2 - Cprog_table2 - Cprog_cal1 + Cprog_table1) /
548 			((s32)(RF2) - (s32)(RF1));
549 
550 		if (RF3 == 0)
551 			break;
552 
553 		status = PowerScan(state, RFBand, RF3, &RF3, &bcal);
554 		if (status < 0)
555 			break;
556 		if (bcal) {
557 			status = CalibrateRF(state, RFBand, RF3, &Cprog_cal3);
558 			if (status < 0)
559 				break;
560 		}
561 		SearchMap2(m_RF_Cal_Map, RF3, &Cprog_table3);
562 		if (!bcal)
563 			Cprog_cal3 = Cprog_table3;
564 		state->m_RF_A2[RFBand] = (Cprog_cal3 - Cprog_table3 - Cprog_cal2 + Cprog_table2) / ((s32)(RF3) - (s32)(RF2));
565 		state->m_RF_B2[RFBand] = Cprog_cal2 - Cprog_table2;
566 
567 	} while (0);
568 
569 	state->m_RF1[RFBand] = RF1;
570 	state->m_RF2[RFBand] = RF2;
571 	state->m_RF3[RFBand] = RF3;
572 
573 #if 0
574 	printk(KERN_ERR "tda18271c2dd: %s %d RF1 = %d A1 = %d B1 = %d RF2 = %d A2 = %d B2 = %d RF3 = %d\n", __func__,
575 	       RFBand, RF1, state->m_RF_A1[RFBand], state->m_RF_B1[RFBand], RF2,
576 	       state->m_RF_A2[RFBand], state->m_RF_B2[RFBand], RF3);
577 #endif
578 
579 	return status;
580 }
581 
PowerScan(struct tda_state * state,u8 RFBand,u32 RF_in,u32 * pRF_Out,bool * pbcal)582 static int PowerScan(struct tda_state *state,
583 		     u8 RFBand, u32 RF_in, u32 *pRF_Out, bool *pbcal)
584 {
585 	int status = 0;
586 	do {
587 		u8   Gain_Taper = 0;
588 		s32  RFC_Cprog = 0;
589 		u8   CID_Target = 0;
590 		u8   CountLimit = 0;
591 		u32  freq_MainPLL;
592 		u8   Regs[NUM_REGS];
593 		u8   CID_Gain;
594 		s32  Count = 0;
595 		int  sign  = 1;
596 		bool wait = false;
597 
598 		if (!(SearchMap2(m_RF_Cal_Map, RF_in, &RFC_Cprog) &&
599 		      SearchMap1(m_GainTaper_Map, RF_in, &Gain_Taper) &&
600 		      SearchMap3(m_CID_Target_Map, RF_in, &CID_Target, &CountLimit))) {
601 
602 			printk(KERN_ERR "tda18271c2dd: %s Search map failed\n", __func__);
603 			return -EINVAL;
604 		}
605 
606 		state->m_Regs[EP2] = (RFBand << 5) | Gain_Taper;
607 		state->m_Regs[EB14] = (RFC_Cprog);
608 		status = UpdateReg(state, EP2);
609 		if (status < 0)
610 			break;
611 		status = UpdateReg(state, EB14);
612 		if (status < 0)
613 			break;
614 
615 		freq_MainPLL = RF_in + 1000000;
616 		status = CalcMainPLL(state, freq_MainPLL);
617 		if (status < 0)
618 			break;
619 		msleep(5);
620 		state->m_Regs[EP4] = (state->m_Regs[EP4] & ~0x03) | 1;    /* CAL_mode = 1 */
621 		status = UpdateReg(state, EP4);
622 		if (status < 0)
623 			break;
624 		status = UpdateReg(state, EP2);  /* Launch power measurement */
625 		if (status < 0)
626 			break;
627 		status = ReadExtented(state, Regs);
628 		if (status < 0)
629 			break;
630 		CID_Gain = Regs[EB10] & 0x3F;
631 		state->m_Regs[ID] = Regs[ID];  /* Chip version, (needed for C1 workaround in CalibrateRF) */
632 
633 		*pRF_Out = RF_in;
634 
635 		while (CID_Gain < CID_Target) {
636 			freq_MainPLL = RF_in + sign * Count + 1000000;
637 			status = CalcMainPLL(state, freq_MainPLL);
638 			if (status < 0)
639 				break;
640 			msleep(wait ? 5 : 1);
641 			wait = false;
642 			status = UpdateReg(state, EP2);  /* Launch power measurement */
643 			if (status < 0)
644 				break;
645 			status = ReadExtented(state, Regs);
646 			if (status < 0)
647 				break;
648 			CID_Gain = Regs[EB10] & 0x3F;
649 			Count += 200000;
650 
651 			if (Count < CountLimit * 100000)
652 				continue;
653 			if (sign < 0)
654 				break;
655 
656 			sign = -sign;
657 			Count = 200000;
658 			wait = true;
659 		}
660 		if (status < 0)
661 			break;
662 		if (CID_Gain >= CID_Target) {
663 			*pbcal = true;
664 			*pRF_Out = freq_MainPLL - 1000000;
665 		} else
666 			*pbcal = false;
667 	} while (0);
668 
669 	return status;
670 }
671 
PowerScanInit(struct tda_state * state)672 static int PowerScanInit(struct tda_state *state)
673 {
674 	int status = 0;
675 	do {
676 		state->m_Regs[EP3] = (state->m_Regs[EP3] & ~0x1F) | 0x12;
677 		state->m_Regs[EP4] = (state->m_Regs[EP4] & ~0x1F); /* If level = 0, Cal mode = 0 */
678 		status = UpdateRegs(state, EP3, EP4);
679 		if (status < 0)
680 			break;
681 		state->m_Regs[EB18] = (state->m_Regs[EB18] & ~0x03); /* AGC 1 Gain = 0 */
682 		status = UpdateReg(state, EB18);
683 		if (status < 0)
684 			break;
685 		state->m_Regs[EB21] = (state->m_Regs[EB21] & ~0x03); /* AGC 2 Gain = 0 (Datasheet = 3) */
686 		state->m_Regs[EB23] = (state->m_Regs[EB23] | 0x06); /* ForceLP_Fc2_En = 1, LPFc[2] = 1 */
687 		status = UpdateRegs(state, EB21, EB23);
688 		if (status < 0)
689 			break;
690 	} while (0);
691 	return status;
692 }
693 
CalcRFFilterCurve(struct tda_state * state)694 static int CalcRFFilterCurve(struct tda_state *state)
695 {
696 	int status = 0;
697 	do {
698 		msleep(200);      /* Temperature stabilisation */
699 		status = PowerScanInit(state);
700 		if (status < 0)
701 			break;
702 		status = RFTrackingFiltersInit(state, 0);
703 		if (status < 0)
704 			break;
705 		status = RFTrackingFiltersInit(state, 1);
706 		if (status < 0)
707 			break;
708 		status = RFTrackingFiltersInit(state, 2);
709 		if (status < 0)
710 			break;
711 		status = RFTrackingFiltersInit(state, 3);
712 		if (status < 0)
713 			break;
714 		status = RFTrackingFiltersInit(state, 4);
715 		if (status < 0)
716 			break;
717 		status = RFTrackingFiltersInit(state, 5);
718 		if (status < 0)
719 			break;
720 		status = RFTrackingFiltersInit(state, 6);
721 		if (status < 0)
722 			break;
723 		status = ThermometerRead(state, &state->m_TMValue_RFCal); /* also switches off Cal mode !!! */
724 		if (status < 0)
725 			break;
726 	} while (0);
727 
728 	return status;
729 }
730 
FixedContentsI2CUpdate(struct tda_state * state)731 static int FixedContentsI2CUpdate(struct tda_state *state)
732 {
733 	static u8 InitRegs[] = {
734 		0x08, 0x80, 0xC6,
735 		0xDF, 0x16, 0x60, 0x80,
736 		0x80, 0x00, 0x00, 0x00,
737 		0x00, 0x00, 0x00, 0x00,
738 		0xFC, 0x01, 0x84, 0x41,
739 		0x01, 0x84, 0x40, 0x07,
740 		0x00, 0x00, 0x96, 0x3F,
741 		0xC1, 0x00, 0x8F, 0x00,
742 		0x00, 0x8C, 0x00, 0x20,
743 		0xB3, 0x48, 0xB0,
744 	};
745 	int status = 0;
746 	memcpy(&state->m_Regs[TM], InitRegs, EB23 - TM + 1);
747 	do {
748 		status = UpdateRegs(state, TM, EB23);
749 		if (status < 0)
750 			break;
751 
752 		/* AGC1 gain setup */
753 		state->m_Regs[EB17] = 0x00;
754 		status = UpdateReg(state, EB17);
755 		if (status < 0)
756 			break;
757 		state->m_Regs[EB17] = 0x03;
758 		status = UpdateReg(state, EB17);
759 		if (status < 0)
760 			break;
761 		state->m_Regs[EB17] = 0x43;
762 		status = UpdateReg(state, EB17);
763 		if (status < 0)
764 			break;
765 		state->m_Regs[EB17] = 0x4C;
766 		status = UpdateReg(state, EB17);
767 		if (status < 0)
768 			break;
769 
770 		/* IRC Cal Low band */
771 		state->m_Regs[EP3] = 0x1F;
772 		state->m_Regs[EP4] = 0x66;
773 		state->m_Regs[EP5] = 0x81;
774 		state->m_Regs[CPD] = 0xCC;
775 		state->m_Regs[CD1] = 0x6C;
776 		state->m_Regs[CD2] = 0x00;
777 		state->m_Regs[CD3] = 0x00;
778 		state->m_Regs[MPD] = 0xC5;
779 		state->m_Regs[MD1] = 0x77;
780 		state->m_Regs[MD2] = 0x08;
781 		state->m_Regs[MD3] = 0x00;
782 		status = UpdateRegs(state, EP2, MD3); /* diff between sw and datasheet (ep3-md3) */
783 		if (status < 0)
784 			break;
785 
786 #if 0
787 		state->m_Regs[EB4] = 0x61;          /* missing in sw */
788 		status = UpdateReg(state, EB4);
789 		if (status < 0)
790 			break;
791 		msleep(1);
792 		state->m_Regs[EB4] = 0x41;
793 		status = UpdateReg(state, EB4);
794 		if (status < 0)
795 			break;
796 #endif
797 
798 		msleep(5);
799 		status = UpdateReg(state, EP1);
800 		if (status < 0)
801 			break;
802 		msleep(5);
803 
804 		state->m_Regs[EP5] = 0x85;
805 		state->m_Regs[CPD] = 0xCB;
806 		state->m_Regs[CD1] = 0x66;
807 		state->m_Regs[CD2] = 0x70;
808 		status = UpdateRegs(state, EP3, CD3);
809 		if (status < 0)
810 			break;
811 		msleep(5);
812 		status = UpdateReg(state, EP2);
813 		if (status < 0)
814 			break;
815 		msleep(30);
816 
817 		/* IRC Cal mid band */
818 		state->m_Regs[EP5] = 0x82;
819 		state->m_Regs[CPD] = 0xA8;
820 		state->m_Regs[CD2] = 0x00;
821 		state->m_Regs[MPD] = 0xA1; /* Datasheet = 0xA9 */
822 		state->m_Regs[MD1] = 0x73;
823 		state->m_Regs[MD2] = 0x1A;
824 		status = UpdateRegs(state, EP3, MD3);
825 		if (status < 0)
826 			break;
827 
828 		msleep(5);
829 		status = UpdateReg(state, EP1);
830 		if (status < 0)
831 			break;
832 		msleep(5);
833 
834 		state->m_Regs[EP5] = 0x86;
835 		state->m_Regs[CPD] = 0xA8;
836 		state->m_Regs[CD1] = 0x66;
837 		state->m_Regs[CD2] = 0xA0;
838 		status = UpdateRegs(state, EP3, CD3);
839 		if (status < 0)
840 			break;
841 		msleep(5);
842 		status = UpdateReg(state, EP2);
843 		if (status < 0)
844 			break;
845 		msleep(30);
846 
847 		/* IRC Cal high band */
848 		state->m_Regs[EP5] = 0x83;
849 		state->m_Regs[CPD] = 0x98;
850 		state->m_Regs[CD1] = 0x65;
851 		state->m_Regs[CD2] = 0x00;
852 		state->m_Regs[MPD] = 0x91;  /* Datasheet = 0x91 */
853 		state->m_Regs[MD1] = 0x71;
854 		state->m_Regs[MD2] = 0xCD;
855 		status = UpdateRegs(state, EP3, MD3);
856 		if (status < 0)
857 			break;
858 		msleep(5);
859 		status = UpdateReg(state, EP1);
860 		if (status < 0)
861 			break;
862 		msleep(5);
863 		state->m_Regs[EP5] = 0x87;
864 		state->m_Regs[CD1] = 0x65;
865 		state->m_Regs[CD2] = 0x50;
866 		status = UpdateRegs(state, EP3, CD3);
867 		if (status < 0)
868 			break;
869 		msleep(5);
870 		status = UpdateReg(state, EP2);
871 		if (status < 0)
872 			break;
873 		msleep(30);
874 
875 		/* Back to normal */
876 		state->m_Regs[EP4] = 0x64;
877 		status = UpdateReg(state, EP4);
878 		if (status < 0)
879 			break;
880 		status = UpdateReg(state, EP1);
881 		if (status < 0)
882 			break;
883 
884 	} while (0);
885 	return status;
886 }
887 
InitCal(struct tda_state * state)888 static int InitCal(struct tda_state *state)
889 {
890 	int status = 0;
891 
892 	do {
893 		status = FixedContentsI2CUpdate(state);
894 		if (status < 0)
895 			break;
896 		status = CalcRFFilterCurve(state);
897 		if (status < 0)
898 			break;
899 		status = StandBy(state);
900 		if (status < 0)
901 			break;
902 		/* m_bInitDone = true; */
903 	} while (0);
904 	return status;
905 };
906 
RFTrackingFiltersCorrection(struct tda_state * state,u32 Frequency)907 static int RFTrackingFiltersCorrection(struct tda_state *state,
908 				       u32 Frequency)
909 {
910 	int status = 0;
911 	s32 Cprog_table;
912 	u8 RFBand;
913 	u8 dCoverdT;
914 
915 	if (!SearchMap2(m_RF_Cal_Map, Frequency, &Cprog_table) ||
916 	    !SearchMap4(m_RF_Band_Map, Frequency, &RFBand) ||
917 	    !SearchMap1(m_RF_Cal_DC_Over_DT_Map, Frequency, &dCoverdT))
918 
919 		return -EINVAL;
920 
921 	do {
922 		u8 TMValue_Current;
923 		u32   RF1 = state->m_RF1[RFBand];
924 		u32   RF2 = state->m_RF1[RFBand];
925 		u32   RF3 = state->m_RF1[RFBand];
926 		s32    RF_A1 = state->m_RF_A1[RFBand];
927 		s32    RF_B1 = state->m_RF_B1[RFBand];
928 		s32    RF_A2 = state->m_RF_A2[RFBand];
929 		s32    RF_B2 = state->m_RF_B2[RFBand];
930 		s32 Capprox = 0;
931 		int TComp;
932 
933 		state->m_Regs[EP3] &= ~0xE0;  /* Power up */
934 		status = UpdateReg(state, EP3);
935 		if (status < 0)
936 			break;
937 
938 		status = ThermometerRead(state, &TMValue_Current);
939 		if (status < 0)
940 			break;
941 
942 		if (RF3 == 0 || Frequency < RF2)
943 			Capprox = RF_A1 * ((s32)(Frequency) - (s32)(RF1)) + RF_B1 + Cprog_table;
944 		else
945 			Capprox = RF_A2 * ((s32)(Frequency) - (s32)(RF2)) + RF_B2 + Cprog_table;
946 
947 		TComp = (int)(dCoverdT) * ((int)(TMValue_Current) - (int)(state->m_TMValue_RFCal))/1000;
948 
949 		Capprox += TComp;
950 
951 		if (Capprox < 0)
952 			Capprox = 0;
953 		else if (Capprox > 255)
954 			Capprox = 255;
955 
956 
957 		/* TODO Temperature compensation. There is defenitely a scale factor */
958 		/*      missing in the datasheet, so leave it out for now.           */
959 		state->m_Regs[EB14] = Capprox;
960 
961 		status = UpdateReg(state, EB14);
962 		if (status < 0)
963 			break;
964 
965 	} while (0);
966 	return status;
967 }
968 
ChannelConfiguration(struct tda_state * state,u32 Frequency,int Standard)969 static int ChannelConfiguration(struct tda_state *state,
970 				u32 Frequency, int Standard)
971 {
972 
973 	s32 IntermediateFrequency = m_StandardTable[Standard].m_IFFrequency;
974 	int status = 0;
975 
976 	u8 BP_Filter = 0;
977 	u8 RF_Band = 0;
978 	u8 GainTaper = 0;
979 	u8 IR_Meas = 0;
980 
981 	state->IF = IntermediateFrequency;
982 	/* printk("tda18271c2dd: %s Freq = %d Standard = %d IF = %d\n", __func__, Frequency, Standard, IntermediateFrequency); */
983 	/* get values from tables */
984 
985 	if (!(SearchMap1(m_BP_Filter_Map, Frequency, &BP_Filter) &&
986 	       SearchMap1(m_GainTaper_Map, Frequency, &GainTaper) &&
987 	       SearchMap1(m_IR_Meas_Map, Frequency, &IR_Meas) &&
988 	       SearchMap4(m_RF_Band_Map, Frequency, &RF_Band))) {
989 
990 		printk(KERN_ERR "tda18271c2dd: %s SearchMap failed\n", __func__);
991 		return -EINVAL;
992 	}
993 
994 	do {
995 		state->m_Regs[EP3] = (state->m_Regs[EP3] & ~0x1F) | m_StandardTable[Standard].m_EP3_4_0;
996 		state->m_Regs[EP3] &= ~0x04;   /* switch RFAGC to high speed mode */
997 
998 		/* m_EP4 default for XToutOn, CAL_Mode (0) */
999 		state->m_Regs[EP4] = state->m_EP4 | ((Standard > HF_AnalogMax) ? state->m_IFLevelDigital : state->m_IFLevelAnalog);
1000 		/* state->m_Regs[EP4] = state->m_EP4 | state->m_IFLevelDigital; */
1001 		if (Standard <= HF_AnalogMax)
1002 			state->m_Regs[EP4] = state->m_EP4 | state->m_IFLevelAnalog;
1003 		else if (Standard <= HF_ATSC)
1004 			state->m_Regs[EP4] = state->m_EP4 | state->m_IFLevelDVBT;
1005 		else if (Standard <= HF_DVBC)
1006 			state->m_Regs[EP4] = state->m_EP4 | state->m_IFLevelDVBC;
1007 		else
1008 			state->m_Regs[EP4] = state->m_EP4 | state->m_IFLevelDigital;
1009 
1010 		if ((Standard == HF_FM_Radio) && state->m_bFMInput)
1011 			state->m_Regs[EP4] |= 0x80;
1012 
1013 		state->m_Regs[MPD] &= ~0x80;
1014 		if (Standard > HF_AnalogMax)
1015 			state->m_Regs[MPD] |= 0x80; /* Add IF_notch for digital */
1016 
1017 		state->m_Regs[EB22] = m_StandardTable[Standard].m_EB22;
1018 
1019 		/* Note: This is missing from flowchart in TDA18271 specification ( 1.5 MHz cutoff for FM ) */
1020 		if (Standard == HF_FM_Radio)
1021 			state->m_Regs[EB23] |=  0x06; /* ForceLP_Fc2_En = 1, LPFc[2] = 1 */
1022 		else
1023 			state->m_Regs[EB23] &= ~0x06; /* ForceLP_Fc2_En = 0, LPFc[2] = 0 */
1024 
1025 		status = UpdateRegs(state, EB22, EB23);
1026 		if (status < 0)
1027 			break;
1028 
1029 		state->m_Regs[EP1] = (state->m_Regs[EP1] & ~0x07) | 0x40 | BP_Filter;   /* Dis_Power_level = 1, Filter */
1030 		state->m_Regs[EP5] = (state->m_Regs[EP5] & ~0x07) | IR_Meas;
1031 		state->m_Regs[EP2] = (RF_Band << 5) | GainTaper;
1032 
1033 		state->m_Regs[EB1] = (state->m_Regs[EB1] & ~0x07) |
1034 			(state->m_bMaster ? 0x04 : 0x00); /* CALVCO_FortLOn = MS */
1035 		/* AGC1_always_master = 0 */
1036 		/* AGC_firstn = 0 */
1037 		status = UpdateReg(state, EB1);
1038 		if (status < 0)
1039 			break;
1040 
1041 		if (state->m_bMaster) {
1042 			status = CalcMainPLL(state, Frequency + IntermediateFrequency);
1043 			if (status < 0)
1044 				break;
1045 			status = UpdateRegs(state, TM, EP5);
1046 			if (status < 0)
1047 				break;
1048 			state->m_Regs[EB4] |= 0x20;    /* LO_forceSrce = 1 */
1049 			status = UpdateReg(state, EB4);
1050 			if (status < 0)
1051 				break;
1052 			msleep(1);
1053 			state->m_Regs[EB4] &= ~0x20;   /* LO_forceSrce = 0 */
1054 			status = UpdateReg(state, EB4);
1055 			if (status < 0)
1056 				break;
1057 		} else {
1058 			u8 PostDiv = 0;
1059 			u8 Div;
1060 			status = CalcCalPLL(state, Frequency + IntermediateFrequency);
1061 			if (status < 0)
1062 				break;
1063 
1064 			SearchMap3(m_Cal_PLL_Map, Frequency + IntermediateFrequency, &PostDiv, &Div);
1065 			state->m_Regs[MPD] = (state->m_Regs[MPD] & ~0x7F) | (PostDiv & 0x77);
1066 			status = UpdateReg(state, MPD);
1067 			if (status < 0)
1068 				break;
1069 			status = UpdateRegs(state, TM, EP5);
1070 			if (status < 0)
1071 				break;
1072 
1073 			state->m_Regs[EB7] |= 0x20;    /* CAL_forceSrce = 1 */
1074 			status = UpdateReg(state, EB7);
1075 			if (status < 0)
1076 				break;
1077 			msleep(1);
1078 			state->m_Regs[EB7] &= ~0x20;   /* CAL_forceSrce = 0 */
1079 			status = UpdateReg(state, EB7);
1080 			if (status < 0)
1081 				break;
1082 		}
1083 		msleep(20);
1084 		if (Standard != HF_FM_Radio)
1085 			state->m_Regs[EP3] |= 0x04;    /* RFAGC to normal mode */
1086 		status = UpdateReg(state, EP3);
1087 		if (status < 0)
1088 			break;
1089 
1090 	} while (0);
1091 	return status;
1092 }
1093 
sleep(struct dvb_frontend * fe)1094 static int sleep(struct dvb_frontend *fe)
1095 {
1096 	struct tda_state *state = fe->tuner_priv;
1097 
1098 	StandBy(state);
1099 	return 0;
1100 }
1101 
init(struct dvb_frontend * fe)1102 static int init(struct dvb_frontend *fe)
1103 {
1104 	return 0;
1105 }
1106 
release(struct dvb_frontend * fe)1107 static void release(struct dvb_frontend *fe)
1108 {
1109 	kfree(fe->tuner_priv);
1110 	fe->tuner_priv = NULL;
1111 }
1112 
1113 
set_params(struct dvb_frontend * fe)1114 static int set_params(struct dvb_frontend *fe)
1115 {
1116 	struct tda_state *state = fe->tuner_priv;
1117 	int status = 0;
1118 	int Standard;
1119 	u32 bw = fe->dtv_property_cache.bandwidth_hz;
1120 	u32 delsys  = fe->dtv_property_cache.delivery_system;
1121 
1122 	state->m_Frequency = fe->dtv_property_cache.frequency;
1123 
1124 	switch (delsys) {
1125 	case  SYS_DVBT:
1126 	case  SYS_DVBT2:
1127 		switch (bw) {
1128 		case 6000000:
1129 			Standard = HF_DVBT_6MHZ;
1130 			break;
1131 		case 7000000:
1132 			Standard = HF_DVBT_7MHZ;
1133 			break;
1134 		case 8000000:
1135 			Standard = HF_DVBT_8MHZ;
1136 			break;
1137 		default:
1138 			return -EINVAL;
1139 		}
1140 		break;
1141 	case SYS_DVBC_ANNEX_A:
1142 	case SYS_DVBC_ANNEX_C:
1143 		if (bw <= 6000000)
1144 			Standard = HF_DVBC_6MHZ;
1145 		else if (bw <= 7000000)
1146 			Standard = HF_DVBC_7MHZ;
1147 		else
1148 			Standard = HF_DVBC_8MHZ;
1149 		break;
1150 	default:
1151 		return -EINVAL;
1152 	}
1153 	do {
1154 		status = RFTrackingFiltersCorrection(state, state->m_Frequency);
1155 		if (status < 0)
1156 			break;
1157 		status = ChannelConfiguration(state, state->m_Frequency,
1158 					      Standard);
1159 		if (status < 0)
1160 			break;
1161 
1162 		msleep(state->m_SettlingTime);  /* Allow AGC's to settle down */
1163 	} while (0);
1164 	return status;
1165 }
1166 
1167 #if 0
1168 static int GetSignalStrength(s32 *pSignalStrength, u32 RFAgc, u32 IFAgc)
1169 {
1170 	if (IFAgc < 500) {
1171 		/* Scale this from 0 to 50000 */
1172 		*pSignalStrength = IFAgc * 100;
1173 	} else {
1174 		/* Scale range 500-1500 to 50000-80000 */
1175 		*pSignalStrength = 50000 + (IFAgc - 500) * 30;
1176 	}
1177 
1178 	return 0;
1179 }
1180 #endif
1181 
get_if_frequency(struct dvb_frontend * fe,u32 * frequency)1182 static int get_if_frequency(struct dvb_frontend *fe, u32 *frequency)
1183 {
1184 	struct tda_state *state = fe->tuner_priv;
1185 
1186 	*frequency = state->IF;
1187 	return 0;
1188 }
1189 
get_bandwidth(struct dvb_frontend * fe,u32 * bandwidth)1190 static int get_bandwidth(struct dvb_frontend *fe, u32 *bandwidth)
1191 {
1192 	/* struct tda_state *state = fe->tuner_priv; */
1193 	/* *bandwidth = priv->bandwidth; */
1194 	return 0;
1195 }
1196 
1197 
1198 static const struct dvb_tuner_ops tuner_ops = {
1199 	.info = {
1200 		.name = "NXP TDA18271C2D",
1201 		.frequency_min_hz  =  47125 * kHz,
1202 		.frequency_max_hz  =    865 * MHz,
1203 		.frequency_step_hz =  62500
1204 	},
1205 	.init              = init,
1206 	.sleep             = sleep,
1207 	.set_params        = set_params,
1208 	.release           = release,
1209 	.get_if_frequency  = get_if_frequency,
1210 	.get_bandwidth     = get_bandwidth,
1211 };
1212 
tda18271c2dd_attach(struct dvb_frontend * fe,struct i2c_adapter * i2c,u8 adr)1213 struct dvb_frontend *tda18271c2dd_attach(struct dvb_frontend *fe,
1214 					 struct i2c_adapter *i2c, u8 adr)
1215 {
1216 	struct tda_state *state;
1217 
1218 	state = kzalloc(sizeof(struct tda_state), GFP_KERNEL);
1219 	if (!state)
1220 		return NULL;
1221 
1222 	fe->tuner_priv = state;
1223 	state->adr = adr;
1224 	state->i2c = i2c;
1225 	memcpy(&fe->ops.tuner_ops, &tuner_ops, sizeof(struct dvb_tuner_ops));
1226 	reset(state);
1227 	InitCal(state);
1228 
1229 	return fe;
1230 }
1231 EXPORT_SYMBOL_GPL(tda18271c2dd_attach);
1232 
1233 MODULE_DESCRIPTION("TDA18271C2 driver");
1234 MODULE_AUTHOR("DD");
1235 MODULE_LICENSE("GPL");
1236