blob: c8f0bfae95afd5c39d8855e6a4933fd70e8f9ed3 [file] [log] [blame]
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03001
Mauro Carvalho Chehab223c7b02011-07-20 19:48:59 -03002#include <linux/init.h>
3#include <linux/kernel.h>
4#include <linux/module.h>
5#include <linux/string.h>
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03006
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03007#include "mt2063.h"
8
9/* Version of this module */
10#define MT2063_VERSION 10018 /* Version 01.18 */
11
Mauro Carvalho Chehab223c7b02011-07-20 19:48:59 -030012static unsigned int verbose;
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -030013module_param(verbose, int, 0644);
14
Mauro Carvalho Chehab0ff48432011-07-20 20:21:42 -030015
16/*****************/
17/* From drivers/media/common/tuners/mt2063_cfg.h */
18
Mauro Carvalho Chehabcfde8922011-07-20 21:01:48 -030019static unsigned int mt2063_setTune(struct dvb_frontend *fe, u32 f_in,
20 u32 bw_in,
Mauro Carvalho Chehab0ff48432011-07-20 20:21:42 -030021 enum MTTune_atv_standard tv_type)
22{
23 //return (int)MT_Tune_atv(h, f_in, bw_in, tv_type);
24
25 struct dvb_frontend_ops *frontend_ops = NULL;
26 struct dvb_tuner_ops *tuner_ops = NULL;
27 struct tuner_state t_state;
28 struct mt2063_state *mt2063State = fe->tuner_priv;
29 int err = 0;
30
31 t_state.frequency = f_in;
32 t_state.bandwidth = bw_in;
33 mt2063State->tv_type = tv_type;
34 if (&fe->ops)
35 frontend_ops = &fe->ops;
36 if (&frontend_ops->tuner_ops)
37 tuner_ops = &frontend_ops->tuner_ops;
38 if (tuner_ops->set_state) {
39 if ((err =
40 tuner_ops->set_state(fe, DVBFE_TUNER_FREQUENCY,
41 &t_state)) < 0) {
42 printk("%s: Invalid parameter\n", __func__);
43 return err;
44 }
45 }
46
47 return err;
48}
49
50static unsigned int mt2063_lockStatus(struct dvb_frontend *fe)
51{
52 struct dvb_frontend_ops *frontend_ops = &fe->ops;
53 struct dvb_tuner_ops *tuner_ops = &frontend_ops->tuner_ops;
54 struct tuner_state t_state;
55 int err = 0;
56
57 if (&fe->ops)
58 frontend_ops = &fe->ops;
59 if (&frontend_ops->tuner_ops)
60 tuner_ops = &frontend_ops->tuner_ops;
61 if (tuner_ops->get_state) {
62 if ((err =
63 tuner_ops->get_state(fe, DVBFE_TUNER_REFCLOCK,
64 &t_state)) < 0) {
65 printk("%s: Invalid parameter\n", __func__);
66 return err;
67 }
68 }
69 return err;
70}
71
72static unsigned int tuner_MT2063_Open(struct dvb_frontend *fe)
73{
74 struct dvb_frontend_ops *frontend_ops = &fe->ops;
75 struct dvb_tuner_ops *tuner_ops = &frontend_ops->tuner_ops;
76 struct tuner_state t_state;
77 int err = 0;
78
79 if (&fe->ops)
80 frontend_ops = &fe->ops;
81 if (&frontend_ops->tuner_ops)
82 tuner_ops = &frontend_ops->tuner_ops;
83 if (tuner_ops->set_state) {
84 if ((err =
85 tuner_ops->set_state(fe, DVBFE_TUNER_OPEN,
86 &t_state)) < 0) {
87 printk("%s: Invalid parameter\n", __func__);
88 return err;
89 }
90 }
91
92 return err;
93}
94
95static unsigned int tuner_MT2063_SoftwareShutdown(struct dvb_frontend *fe)
96{
97 struct dvb_frontend_ops *frontend_ops = &fe->ops;
98 struct dvb_tuner_ops *tuner_ops = &frontend_ops->tuner_ops;
99 struct tuner_state t_state;
100 int err = 0;
101
102 if (&fe->ops)
103 frontend_ops = &fe->ops;
104 if (&frontend_ops->tuner_ops)
105 tuner_ops = &frontend_ops->tuner_ops;
106 if (tuner_ops->set_state) {
107 if ((err =
108 tuner_ops->set_state(fe, DVBFE_TUNER_SOFTWARE_SHUTDOWN,
109 &t_state)) < 0) {
110 printk("%s: Invalid parameter\n", __func__);
111 return err;
112 }
113 }
114
115 return err;
116}
117
118static unsigned int tuner_MT2063_ClearPowerMaskBits(struct dvb_frontend *fe)
119{
120 struct dvb_frontend_ops *frontend_ops = &fe->ops;
121 struct dvb_tuner_ops *tuner_ops = &frontend_ops->tuner_ops;
122 struct tuner_state t_state;
123 int err = 0;
124
125 if (&fe->ops)
126 frontend_ops = &fe->ops;
127 if (&frontend_ops->tuner_ops)
128 tuner_ops = &frontend_ops->tuner_ops;
129 if (tuner_ops->set_state) {
130 if ((err =
131 tuner_ops->set_state(fe, DVBFE_TUNER_CLEAR_POWER_MASKBITS,
132 &t_state)) < 0) {
133 printk("%s: Invalid parameter\n", __func__);
134 return err;
135 }
136 }
137
138 return err;
139}
140
141/*****************/
142
143
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -0300144//i2c operation
145static int mt2063_writeregs(struct mt2063_state *state, u8 reg1,
146 u8 * data, int len)
Mauro Carvalho Chehab223c7b02011-07-20 19:48:59 -0300147{
148 int ret;
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -0300149 u8 buf[60]; /* = { reg1, data }; */
150
Mauro Carvalho Chehab223c7b02011-07-20 19:48:59 -0300151 struct i2c_msg msg = {
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -0300152 .addr = state->config->tuner_address,
153 .flags = 0,
154 .buf = buf,
155 .len = len + 1
Mauro Carvalho Chehab223c7b02011-07-20 19:48:59 -0300156 };
157
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -0300158 msg.buf[0] = reg1;
Mauro Carvalho Chehab223c7b02011-07-20 19:48:59 -0300159 memcpy(msg.buf + 1, data, len);
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -0300160
161 //printk("mt2063_writeregs state->i2c=%p\n", state->i2c);
Mauro Carvalho Chehab223c7b02011-07-20 19:48:59 -0300162 ret = i2c_transfer(state->i2c, &msg, 1);
163
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -0300164 if (ret < 0)
165 printk("mt2063_writeregs error ret=%d\n", ret);
Mauro Carvalho Chehab223c7b02011-07-20 19:48:59 -0300166
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -0300167 return ret;
168}
169
170static int mt2063_read_regs(struct mt2063_state *state, u8 reg1, u8 * b, u8 len)
Mauro Carvalho Chehab223c7b02011-07-20 19:48:59 -0300171{
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -0300172 int ret;
173 u8 b0[] = { reg1 };
Mauro Carvalho Chehab223c7b02011-07-20 19:48:59 -0300174 struct i2c_msg msg[] = {
175 {
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -0300176 .addr = state->config->tuner_address,
177 .flags = I2C_M_RD,
178 .buf = b0,
179 .len = 1}, {
180 .addr = state->config->tuner_address,
181 .flags = I2C_M_RD,
182 .buf = b,
183 .len = len}
Mauro Carvalho Chehab223c7b02011-07-20 19:48:59 -0300184 };
Mauro Carvalho Chehab223c7b02011-07-20 19:48:59 -0300185
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -0300186 //printk("mt2063_read_regs state->i2c=%p\n", state->i2c);
187 ret = i2c_transfer(state->i2c, msg, 2);
188 if (ret < 0)
189 printk("mt2063_readregs error ret=%d\n", ret);
190
191 return ret;
192}
193
194//context of mt2063_userdef.c <Henry> ======================================
195//#################################################################
196//=================================================================
197/*****************************************************************************
198**
199** Name: MT_WriteSub
200**
201** Description: Write values to device using a two-wire serial bus.
202**
203** Parameters: hUserData - User-specific I/O parameter that was
204** passed to tuner's Open function.
205** addr - device serial bus address (value passed
206** as parameter to MTxxxx_Open)
207** subAddress - serial bus sub-address (Register Address)
208** pData - pointer to the Data to be written to the
209** device
210** cnt - number of bytes/registers to be written
211**
212** Returns: status:
213** MT_OK - No errors
214** MT_COMM_ERR - Serial bus communications error
215** user-defined
216**
217** Notes: This is a callback function that is called from the
218** the tuning algorithm. You MUST provide code for this
219** function to write data using the tuner's 2-wire serial
220** bus.
221**
222** The hUserData parameter is a user-specific argument.
223** If additional arguments are needed for the user's
224** serial bus read/write functions, this argument can be
225** used to supply the necessary information.
226** The hUserData parameter is initialized in the tuner's Open
227** function.
228**
229** Revision History:
230**
231** SCR Date Author Description
232** -------------------------------------------------------------------------
233** N/A 03-25-2004 DAD Original
234**
235*****************************************************************************/
Mauro Carvalho Chehabcfde8922011-07-20 21:01:48 -0300236u32 MT2063_WriteSub(void *hUserData,
237 u32 addr,
238 u8 subAddress, u8 * pData, u32 cnt)
Mauro Carvalho Chehab223c7b02011-07-20 19:48:59 -0300239{
Mauro Carvalho Chehabcfde8922011-07-20 21:01:48 -0300240 u32 status = MT2063_OK; /* Status to be returned */
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -0300241 struct dvb_frontend *fe = hUserData;
242 struct mt2063_state *state = fe->tuner_priv;
243 /*
244 ** ToDo: Add code here to implement a serial-bus write
245 ** operation to the MTxxxx tuner. If successful,
246 ** return MT_OK.
247 */
248/* return status; */
249
250//#if !TUNER_CONTROL_BY_DRXK_DRIVER
251 fe->ops.i2c_gate_ctrl(fe, 1); //I2C bypass drxk3926 close i2c bridge
252//#endif
253
254 if (mt2063_writeregs(state, subAddress, pData, cnt) < 0) {
255 status = MT2063_ERROR;
256 }
257//#if !TUNER_CONTROL_BY_DRXK_DRIVER
258 fe->ops.i2c_gate_ctrl(fe, 0); //I2C bypass drxk3926 close i2c bridge
259//#endif
260
261 return (status);
262}
263
264/*****************************************************************************
265**
266** Name: MT_ReadSub
267**
268** Description: Read values from device using a two-wire serial bus.
269**
270** Parameters: hUserData - User-specific I/O parameter that was
271** passed to tuner's Open function.
272** addr - device serial bus address (value passed
273** as parameter to MTxxxx_Open)
274** subAddress - serial bus sub-address (Register Address)
275** pData - pointer to the Data to be written to the
276** device
277** cnt - number of bytes/registers to be written
278**
279** Returns: status:
280** MT_OK - No errors
281** MT_COMM_ERR - Serial bus communications error
282** user-defined
283**
284** Notes: This is a callback function that is called from the
285** the tuning algorithm. You MUST provide code for this
286** function to read data using the tuner's 2-wire serial
287** bus.
288**
289** The hUserData parameter is a user-specific argument.
290** If additional arguments are needed for the user's
291** serial bus read/write functions, this argument can be
292** used to supply the necessary information.
293** The hUserData parameter is initialized in the tuner's Open
294** function.
295**
296** Revision History:
297**
298** SCR Date Author Description
299** -------------------------------------------------------------------------
300** N/A 03-25-2004 DAD Original
301**
302*****************************************************************************/
Mauro Carvalho Chehabcfde8922011-07-20 21:01:48 -0300303u32 MT2063_ReadSub(void *hUserData,
304 u32 addr,
305 u8 subAddress, u8 * pData, u32 cnt)
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -0300306{
307 /*
308 ** ToDo: Add code here to implement a serial-bus read
309 ** operation to the MTxxxx tuner. If successful,
310 ** return MT_OK.
311 */
312/* return status; */
Mauro Carvalho Chehabcfde8922011-07-20 21:01:48 -0300313 u32 status = MT2063_OK; /* Status to be returned */
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -0300314 struct dvb_frontend *fe = hUserData;
315 struct mt2063_state *state = fe->tuner_priv;
Mauro Carvalho Chehabcfde8922011-07-20 21:01:48 -0300316 u32 i = 0;
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -0300317//#if !TUNER_CONTROL_BY_DRXK_DRIVER
318 fe->ops.i2c_gate_ctrl(fe, 1); //I2C bypass drxk3926 close i2c bridge
319//#endif
320
321 for (i = 0; i < cnt; i++) {
322 if (mt2063_read_regs(state, subAddress + i, pData + i, 1) < 0) {
323 status = MT2063_ERROR;
324 break;
325 }
326 }
327
328//#if !TUNER_CONTROL_BY_DRXK_DRIVER
329 fe->ops.i2c_gate_ctrl(fe, 0); //I2C bypass drxk3926 close i2c bridge
330//#endif
331
332 return (status);
333}
334
335/*****************************************************************************
336**
337** Name: MT_Sleep
338**
339** Description: Delay execution for "nMinDelayTime" milliseconds
340**
341** Parameters: hUserData - User-specific I/O parameter that was
342** passed to tuner's Open function.
343** nMinDelayTime - Delay time in milliseconds
344**
345** Returns: None.
346**
347** Notes: This is a callback function that is called from the
348** the tuning algorithm. You MUST provide code that
349** blocks execution for the specified period of time.
350**
351** Revision History:
352**
353** SCR Date Author Description
354** -------------------------------------------------------------------------
355** N/A 03-25-2004 DAD Original
356**
357*****************************************************************************/
Mauro Carvalho Chehabcfde8922011-07-20 21:01:48 -0300358void MT2063_Sleep(void *hUserData, u32 nMinDelayTime)
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -0300359{
360 /*
361 ** ToDo: Add code here to implement a OS blocking
362 ** for a period of "nMinDelayTime" milliseconds.
363 */
364 msleep(nMinDelayTime);
365}
366
367#if defined(MT2060_CNT)
368#if MT2060_CNT > 0
369/*****************************************************************************
370**
371** Name: MT_TunerGain (MT2060 only)
372**
373** Description: Measure the relative tuner gain using the demodulator
374**
375** Parameters: hUserData - User-specific I/O parameter that was
376** passed to tuner's Open function.
377** pMeas - Tuner gain (1/100 of dB scale).
378** ie. 1234 = 12.34 (dB)
379**
380** Returns: status:
381** MT_OK - No errors
382** user-defined errors could be set
383**
384** Notes: This is a callback function that is called from the
385** the 1st IF location routine. You MUST provide
386** code that measures the relative tuner gain in a dB
387** (not linear) scale. The return value is an integer
388** value scaled to 1/100 of a dB.
389**
390** Revision History:
391**
392** SCR Date Author Description
393** -------------------------------------------------------------------------
394** N/A 06-16-2004 DAD Original
395** N/A 11-30-2004 DAD Renamed from MT_DemodInputPower. This name
396** better describes what this function does.
397**
398*****************************************************************************/
Mauro Carvalho Chehabcfde8922011-07-20 21:01:48 -0300399u32 MT2060_TunerGain(void *hUserData, s32 * pMeas)
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -0300400{
Mauro Carvalho Chehabcfde8922011-07-20 21:01:48 -0300401 u32 status = MT2063_OK; /* Status to be returned */
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -0300402
403 /*
404 ** ToDo: Add code here to return the gain / power level measured
405 ** at the input to the demodulator.
406 */
407
408 return (status);
409}
410#endif
411#endif
412//end of mt2063_userdef.c
413//=================================================================
414//#################################################################
415//=================================================================
416
417//context of mt2063_spuravoid.c <Henry> ======================================
418//#################################################################
419//=================================================================
420
421/*****************************************************************************
422**
423** Name: mt_spuravoid.c
424**
425** Description: Microtune spur avoidance software module.
426** Supports Microtune tuner drivers.
427**
428** CVS ID: $Id: mt_spuravoid.c,v 1.3 2008/06/26 15:39:52 software Exp $
429** CVS Source: $Source: /export/home/cvsroot/software/tuners/MT2063/mt_spuravoid.c,v $
430**
431** Revision History:
432**
433** SCR Date Author Description
434** -------------------------------------------------------------------------
435** 082 03-25-2005 JWS Original multi-tuner support - requires
436** MTxxxx_CNT declarations
437** 096 04-06-2005 DAD Ver 1.11: Fix divide by 0 error if maxH==0.
438** 094 04-06-2005 JWS Ver 1.11 Added uceil and ufloor to get rid
439** of compiler warnings
440** N/A 04-07-2005 DAD Ver 1.13: Merged single- and multi-tuner spur
441** avoidance into a single module.
442** 103 01-31-2005 DAD Ver 1.14: In MT_AddExclZone(), if the range
443** (f_min, f_max) < 0, ignore the entry.
444** 115 03-23-2007 DAD Fix declaration of spur due to truncation
445** errors.
446** 117 03-29-2007 RSK Ver 1.15: Re-wrote to match search order from
447** tuner DLL.
448** 137 06-18-2007 DAD Ver 1.16: Fix possible divide-by-0 error for
449** multi-tuners that have
450** (delta IF1) > (f_out-f_outbw/2).
451** 147 07-27-2007 RSK Ver 1.17: Corrected calculation (-) to (+)
452** Added logic to force f_Center within 1/2 f_Step.
453** 177 S 02-26-2008 RSK Ver 1.18: Corrected calculation using LO1 > MAX/2
454** Type casts added to preserve correct sign.
455** N/A I 06-17-2008 RSK Ver 1.19: Refactoring avoidance of DECT
456** frequencies into MT_ResetExclZones().
457** N/A I 06-20-2008 RSK Ver 1.21: New VERSION number for ver checking.
458**
459*****************************************************************************/
460
461#if !defined(MT2063_TUNER_CNT)
462#error MT2063_TUNER_CNT is not defined (see mt_userdef.h)
463#endif
464
465#if MT2063_TUNER_CNT == 0
466#error MT2063_TUNER_CNT must be updated in mt_userdef.h
467#endif
468
469/* Version of this module */
470#define MT2063_SPUR_VERSION 10201 /* Version 01.21 */
471
472/* Implement ceiling, floor functions. */
473#define ceil(n, d) (((n) < 0) ? (-((-(n))/(d))) : (n)/(d) + ((n)%(d) != 0))
474#define uceil(n, d) ((n)/(d) + ((n)%(d) != 0))
475#define floor(n, d) (((n) < 0) ? (-((-(n))/(d))) - ((n)%(d) != 0) : (n)/(d))
476#define ufloor(n, d) ((n)/(d))
477
478struct MT2063_FIFZone_t {
Mauro Carvalho Chehabcfde8922011-07-20 21:01:48 -0300479 s32 min_;
480 s32 max_;
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -0300481};
482
483#if MT2063_TUNER_CNT > 1
484static struct MT2063_AvoidSpursData_t *TunerList[MT2063_TUNER_CNT];
Mauro Carvalho Chehabcfde8922011-07-20 21:01:48 -0300485static u32 TunerCount = 0;
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -0300486#endif
487
Mauro Carvalho Chehabcfde8922011-07-20 21:01:48 -0300488u32 MT2063_RegisterTuner(struct MT2063_AvoidSpursData_t *pAS_Info)
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -0300489{
490#if MT2063_TUNER_CNT == 1
491 pAS_Info->nAS_Algorithm = 1;
492 return MT2063_OK;
493#else
Mauro Carvalho Chehabcfde8922011-07-20 21:01:48 -0300494 u32 index;
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -0300495
496 pAS_Info->nAS_Algorithm = 2;
497
498 /*
499 ** Check to see if tuner is already registered
500 */
501 for (index = 0; index < TunerCount; index++) {
502 if (TunerList[index] == pAS_Info) {
503 return MT2063_OK; /* Already here - no problem */
504 }
505 }
506
507 /*
508 ** Add tuner to list - if there is room.
509 */
510 if (TunerCount < MT2063_TUNER_CNT) {
511 TunerList[TunerCount] = pAS_Info;
512 TunerCount++;
513 return MT2063_OK;
514 } else
515 return MT2063_TUNER_CNT_ERR;
516#endif
517}
518
519void MT2063_UnRegisterTuner(struct MT2063_AvoidSpursData_t *pAS_Info)
520{
521#if MT2063_TUNER_CNT == 1
522 pAS_Info;
523#else
524
Mauro Carvalho Chehabcfde8922011-07-20 21:01:48 -0300525 u32 index;
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -0300526
527 for (index = 0; index < TunerCount; index++) {
528 if (TunerList[index] == pAS_Info) {
529 TunerList[index] = TunerList[--TunerCount];
530 }
531 }
532#endif
533}
534
535/*
536** Reset all exclusion zones.
537** Add zones to protect the PLL FracN regions near zero
538**
539** N/A I 06-17-2008 RSK Ver 1.19: Refactoring avoidance of DECT
540** frequencies into MT_ResetExclZones().
541*/
542void MT2063_ResetExclZones(struct MT2063_AvoidSpursData_t *pAS_Info)
543{
Mauro Carvalho Chehabcfde8922011-07-20 21:01:48 -0300544 u32 center;
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -0300545#if MT2063_TUNER_CNT > 1
Mauro Carvalho Chehabcfde8922011-07-20 21:01:48 -0300546 u32 index;
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -0300547 struct MT2063_AvoidSpursData_t *adj;
548#endif
549
550 pAS_Info->nZones = 0; /* this clears the used list */
551 pAS_Info->usedZones = NULL; /* reset ptr */
552 pAS_Info->freeZones = NULL; /* reset ptr */
553
554 center =
555 pAS_Info->f_ref *
556 ((pAS_Info->f_if1_Center - pAS_Info->f_if1_bw / 2 +
557 pAS_Info->f_in) / pAS_Info->f_ref) - pAS_Info->f_in;
558 while (center <
559 pAS_Info->f_if1_Center + pAS_Info->f_if1_bw / 2 +
560 pAS_Info->f_LO1_FracN_Avoid) {
561 /* Exclude LO1 FracN */
562 MT2063_AddExclZone(pAS_Info,
563 center - pAS_Info->f_LO1_FracN_Avoid,
564 center - 1);
565 MT2063_AddExclZone(pAS_Info, center + 1,
566 center + pAS_Info->f_LO1_FracN_Avoid);
567 center += pAS_Info->f_ref;
568 }
569
570 center =
571 pAS_Info->f_ref *
572 ((pAS_Info->f_if1_Center - pAS_Info->f_if1_bw / 2 -
573 pAS_Info->f_out) / pAS_Info->f_ref) + pAS_Info->f_out;
574 while (center <
575 pAS_Info->f_if1_Center + pAS_Info->f_if1_bw / 2 +
576 pAS_Info->f_LO2_FracN_Avoid) {
577 /* Exclude LO2 FracN */
578 MT2063_AddExclZone(pAS_Info,
579 center - pAS_Info->f_LO2_FracN_Avoid,
580 center - 1);
581 MT2063_AddExclZone(pAS_Info, center + 1,
582 center + pAS_Info->f_LO2_FracN_Avoid);
583 center += pAS_Info->f_ref;
584 }
585
586 if (MT2063_EXCLUDE_US_DECT_FREQUENCIES(pAS_Info->avoidDECT)) {
587 /* Exclude LO1 values that conflict with DECT channels */
588 MT2063_AddExclZone(pAS_Info, 1920836000 - pAS_Info->f_in, 1922236000 - pAS_Info->f_in); /* Ctr = 1921.536 */
589 MT2063_AddExclZone(pAS_Info, 1922564000 - pAS_Info->f_in, 1923964000 - pAS_Info->f_in); /* Ctr = 1923.264 */
590 MT2063_AddExclZone(pAS_Info, 1924292000 - pAS_Info->f_in, 1925692000 - pAS_Info->f_in); /* Ctr = 1924.992 */
591 MT2063_AddExclZone(pAS_Info, 1926020000 - pAS_Info->f_in, 1927420000 - pAS_Info->f_in); /* Ctr = 1926.720 */
592 MT2063_AddExclZone(pAS_Info, 1927748000 - pAS_Info->f_in, 1929148000 - pAS_Info->f_in); /* Ctr = 1928.448 */
593 }
594
595 if (MT2063_EXCLUDE_EURO_DECT_FREQUENCIES(pAS_Info->avoidDECT)) {
596 MT2063_AddExclZone(pAS_Info, 1896644000 - pAS_Info->f_in, 1898044000 - pAS_Info->f_in); /* Ctr = 1897.344 */
597 MT2063_AddExclZone(pAS_Info, 1894916000 - pAS_Info->f_in, 1896316000 - pAS_Info->f_in); /* Ctr = 1895.616 */
598 MT2063_AddExclZone(pAS_Info, 1893188000 - pAS_Info->f_in, 1894588000 - pAS_Info->f_in); /* Ctr = 1893.888 */
599 MT2063_AddExclZone(pAS_Info, 1891460000 - pAS_Info->f_in, 1892860000 - pAS_Info->f_in); /* Ctr = 1892.16 */
600 MT2063_AddExclZone(pAS_Info, 1889732000 - pAS_Info->f_in, 1891132000 - pAS_Info->f_in); /* Ctr = 1890.432 */
601 MT2063_AddExclZone(pAS_Info, 1888004000 - pAS_Info->f_in, 1889404000 - pAS_Info->f_in); /* Ctr = 1888.704 */
602 MT2063_AddExclZone(pAS_Info, 1886276000 - pAS_Info->f_in, 1887676000 - pAS_Info->f_in); /* Ctr = 1886.976 */
603 MT2063_AddExclZone(pAS_Info, 1884548000 - pAS_Info->f_in, 1885948000 - pAS_Info->f_in); /* Ctr = 1885.248 */
604 MT2063_AddExclZone(pAS_Info, 1882820000 - pAS_Info->f_in, 1884220000 - pAS_Info->f_in); /* Ctr = 1883.52 */
605 MT2063_AddExclZone(pAS_Info, 1881092000 - pAS_Info->f_in, 1882492000 - pAS_Info->f_in); /* Ctr = 1881.792 */
606 }
607#if MT2063_TUNER_CNT > 1
608 /*
609 ** Iterate through all adjacent tuners and exclude frequencies related to them
610 */
611 for (index = 0; index < TunerCount; ++index) {
612 adj = TunerList[index];
613 if (pAS_Info == adj) /* skip over our own data, don't process it */
614 continue;
615
616 /*
617 ** Add 1st IF exclusion zone covering adjacent tuner's LO2
618 ** at "adjfLO2 + f_out" +/- m_MinLOSpacing
619 */
620 if (adj->f_LO2 != 0)
621 MT2063_AddExclZone(pAS_Info,
622 (adj->f_LO2 + pAS_Info->f_out) -
623 pAS_Info->f_min_LO_Separation,
624 (adj->f_LO2 + pAS_Info->f_out) +
625 pAS_Info->f_min_LO_Separation);
626
627 /*
628 ** Add 1st IF exclusion zone covering adjacent tuner's LO1
629 ** at "adjfLO1 - f_in" +/- m_MinLOSpacing
630 */
631 if (adj->f_LO1 != 0)
632 MT2063_AddExclZone(pAS_Info,
633 (adj->f_LO1 - pAS_Info->f_in) -
634 pAS_Info->f_min_LO_Separation,
635 (adj->f_LO1 - pAS_Info->f_in) +
636 pAS_Info->f_min_LO_Separation);
637 }
638#endif
639}
640
641static struct MT2063_ExclZone_t *InsertNode(struct MT2063_AvoidSpursData_t
642 *pAS_Info,
643 struct MT2063_ExclZone_t *pPrevNode)
644{
645 struct MT2063_ExclZone_t *pNode;
646 /* Check for a node in the free list */
647 if (pAS_Info->freeZones != NULL) {
648 /* Use one from the free list */
649 pNode = pAS_Info->freeZones;
650 pAS_Info->freeZones = pNode->next_;
651 } else {
652 /* Grab a node from the array */
653 pNode = &pAS_Info->MT2063_ExclZones[pAS_Info->nZones];
654 }
655
656 if (pPrevNode != NULL) {
657 pNode->next_ = pPrevNode->next_;
658 pPrevNode->next_ = pNode;
659 } else { /* insert at the beginning of the list */
660
661 pNode->next_ = pAS_Info->usedZones;
662 pAS_Info->usedZones = pNode;
663 }
664
665 pAS_Info->nZones++;
666 return pNode;
667}
668
669static struct MT2063_ExclZone_t *RemoveNode(struct MT2063_AvoidSpursData_t
670 *pAS_Info,
671 struct MT2063_ExclZone_t *pPrevNode,
672 struct MT2063_ExclZone_t
673 *pNodeToRemove)
674{
675 struct MT2063_ExclZone_t *pNext = pNodeToRemove->next_;
676
677 /* Make previous node point to the subsequent node */
678 if (pPrevNode != NULL)
679 pPrevNode->next_ = pNext;
680
681 /* Add pNodeToRemove to the beginning of the freeZones */
682 pNodeToRemove->next_ = pAS_Info->freeZones;
683 pAS_Info->freeZones = pNodeToRemove;
684
685 /* Decrement node count */
686 pAS_Info->nZones--;
687
688 return pNext;
689}
690
691/*****************************************************************************
692**
693** Name: MT_AddExclZone
694**
695** Description: Add (and merge) an exclusion zone into the list.
696** If the range (f_min, f_max) is totally outside the
697** 1st IF BW, ignore the entry.
698** If the range (f_min, f_max) is negative, ignore the entry.
699**
700** Revision History:
701**
702** SCR Date Author Description
703** -------------------------------------------------------------------------
704** 103 01-31-2005 DAD Ver 1.14: In MT_AddExclZone(), if the range
705** (f_min, f_max) < 0, ignore the entry.
706**
707*****************************************************************************/
708void MT2063_AddExclZone(struct MT2063_AvoidSpursData_t *pAS_Info,
Mauro Carvalho Chehabcfde8922011-07-20 21:01:48 -0300709 u32 f_min, u32 f_max)
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -0300710{
711 struct MT2063_ExclZone_t *pNode = pAS_Info->usedZones;
712 struct MT2063_ExclZone_t *pPrev = NULL;
713 struct MT2063_ExclZone_t *pNext = NULL;
714
715 /* Check to see if this overlaps the 1st IF filter */
716 if ((f_max > (pAS_Info->f_if1_Center - (pAS_Info->f_if1_bw / 2)))
717 && (f_min < (pAS_Info->f_if1_Center + (pAS_Info->f_if1_bw / 2)))
718 && (f_min < f_max)) {
719 /*
720 ** 1 2 3 4 5 6
721 **
722 ** New entry: |---| |--| |--| |-| |---| |--|
723 ** or or or or or
724 ** Existing: |--| |--| |--| |---| |-| |--|
725 */
726
727 /* Check for our place in the list */
728 while ((pNode != NULL) && (pNode->max_ < f_min)) {
729 pPrev = pNode;
730 pNode = pNode->next_;
731 }
732
733 if ((pNode != NULL) && (pNode->min_ < f_max)) {
734 /* Combine me with pNode */
735 if (f_min < pNode->min_)
736 pNode->min_ = f_min;
737 if (f_max > pNode->max_)
738 pNode->max_ = f_max;
739 } else {
740 pNode = InsertNode(pAS_Info, pPrev);
741 pNode->min_ = f_min;
742 pNode->max_ = f_max;
743 }
744
745 /* Look for merging possibilities */
746 pNext = pNode->next_;
747 while ((pNext != NULL) && (pNext->min_ < pNode->max_)) {
748 if (pNext->max_ > pNode->max_)
749 pNode->max_ = pNext->max_;
750 pNext = RemoveNode(pAS_Info, pNode, pNext); /* Remove pNext, return ptr to pNext->next */
751 }
752 }
753}
754
755/*****************************************************************************
756**
757** Name: MT_ChooseFirstIF
758**
759** Description: Choose the best available 1st IF
760** If f_Desired is not excluded, choose that first.
761** Otherwise, return the value closest to f_Center that is
762** not excluded
763**
764** Revision History:
765**
766** SCR Date Author Description
767** -------------------------------------------------------------------------
768** 117 03-29-2007 RSK Ver 1.15: Re-wrote to match search order from
769** tuner DLL.
770** 147 07-27-2007 RSK Ver 1.17: Corrected calculation (-) to (+)
771** Added logic to force f_Center within 1/2 f_Step.
772**
773*****************************************************************************/
Mauro Carvalho Chehabcfde8922011-07-20 21:01:48 -0300774u32 MT2063_ChooseFirstIF(struct MT2063_AvoidSpursData_t *pAS_Info)
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -0300775{
776 /*
777 ** Update "f_Desired" to be the nearest "combinational-multiple" of "f_LO1_Step".
778 ** The resulting number, F_LO1 must be a multiple of f_LO1_Step. And F_LO1 is the arithmetic sum
779 ** of f_in + f_Center. Neither f_in, nor f_Center must be a multiple of f_LO1_Step.
780 ** However, the sum must be.
781 */
Mauro Carvalho Chehabcfde8922011-07-20 21:01:48 -0300782 const u32 f_Desired =
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -0300783 pAS_Info->f_LO1_Step *
784 ((pAS_Info->f_if1_Request + pAS_Info->f_in +
785 pAS_Info->f_LO1_Step / 2) / pAS_Info->f_LO1_Step) -
786 pAS_Info->f_in;
Mauro Carvalho Chehabcfde8922011-07-20 21:01:48 -0300787 const u32 f_Step =
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -0300788 (pAS_Info->f_LO1_Step >
789 pAS_Info->f_LO2_Step) ? pAS_Info->f_LO1_Step : pAS_Info->
790 f_LO2_Step;
Mauro Carvalho Chehabcfde8922011-07-20 21:01:48 -0300791 u32 f_Center;
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -0300792
Mauro Carvalho Chehabcfde8922011-07-20 21:01:48 -0300793 s32 i;
794 s32 j = 0;
795 u32 bDesiredExcluded = 0;
796 u32 bZeroExcluded = 0;
797 s32 tmpMin, tmpMax;
798 s32 bestDiff;
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -0300799 struct MT2063_ExclZone_t *pNode = pAS_Info->usedZones;
800 struct MT2063_FIFZone_t zones[MT2063_MAX_ZONES];
801
802 if (pAS_Info->nZones == 0)
803 return f_Desired;
804
805 /* f_Center needs to be an integer multiple of f_Step away from f_Desired */
806 if (pAS_Info->f_if1_Center > f_Desired)
807 f_Center =
808 f_Desired +
809 f_Step *
810 ((pAS_Info->f_if1_Center - f_Desired +
811 f_Step / 2) / f_Step);
812 else
813 f_Center =
814 f_Desired -
815 f_Step *
816 ((f_Desired - pAS_Info->f_if1_Center +
817 f_Step / 2) / f_Step);
818
819 //assert;
Mauro Carvalho Chehabcfde8922011-07-20 21:01:48 -0300820 //if (!abs((s32) f_Center - (s32) pAS_Info->f_if1_Center) <= (s32) (f_Step/2))
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -0300821 // return 0;
822
823 /* Take MT_ExclZones, center around f_Center and change the resolution to f_Step */
824 while (pNode != NULL) {
825 /* floor function */
826 tmpMin =
Mauro Carvalho Chehabcfde8922011-07-20 21:01:48 -0300827 floor((s32) (pNode->min_ - f_Center), (s32) f_Step);
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -0300828
829 /* ceil function */
830 tmpMax =
Mauro Carvalho Chehabcfde8922011-07-20 21:01:48 -0300831 ceil((s32) (pNode->max_ - f_Center), (s32) f_Step);
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -0300832
833 if ((pNode->min_ < f_Desired) && (pNode->max_ > f_Desired))
834 bDesiredExcluded = 1;
835
836 if ((tmpMin < 0) && (tmpMax > 0))
837 bZeroExcluded = 1;
838
839 /* See if this zone overlaps the previous */
840 if ((j > 0) && (tmpMin < zones[j - 1].max_))
841 zones[j - 1].max_ = tmpMax;
842 else {
843 /* Add new zone */
844 //assert(j<MT2063_MAX_ZONES);
845 //if (j>=MT2063_MAX_ZONES)
846 //break;
847
848 zones[j].min_ = tmpMin;
849 zones[j].max_ = tmpMax;
850 j++;
851 }
852 pNode = pNode->next_;
853 }
854
855 /*
856 ** If the desired is okay, return with it
857 */
858 if (bDesiredExcluded == 0)
859 return f_Desired;
860
861 /*
862 ** If the desired is excluded and the center is okay, return with it
863 */
864 if (bZeroExcluded == 0)
865 return f_Center;
866
867 /* Find the value closest to 0 (f_Center) */
868 bestDiff = zones[0].min_;
869 for (i = 0; i < j; i++) {
870 if (abs(zones[i].min_) < abs(bestDiff))
871 bestDiff = zones[i].min_;
872 if (abs(zones[i].max_) < abs(bestDiff))
873 bestDiff = zones[i].max_;
874 }
875
876 if (bestDiff < 0)
Mauro Carvalho Chehabcfde8922011-07-20 21:01:48 -0300877 return f_Center - ((u32) (-bestDiff) * f_Step);
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -0300878
879 return f_Center + (bestDiff * f_Step);
880}
881
882/****************************************************************************
883**
884** Name: gcd
885**
886** Description: Uses Euclid's algorithm
887**
888** Parameters: u, v - unsigned values whose GCD is desired.
889**
890** Global: None
891**
892** Returns: greatest common divisor of u and v, if either value
893** is 0, the other value is returned as the result.
894**
895** Dependencies: None.
896**
897** Revision History:
898**
899** SCR Date Author Description
900** -------------------------------------------------------------------------
901** N/A 06-01-2004 JWS Original
902** N/A 08-03-2004 DAD Changed to Euclid's since it can handle
903** unsigned numbers.
904**
905****************************************************************************/
Mauro Carvalho Chehabcfde8922011-07-20 21:01:48 -0300906static u32 MT2063_gcd(u32 u, u32 v)
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -0300907{
Mauro Carvalho Chehabcfde8922011-07-20 21:01:48 -0300908 u32 r;
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -0300909
910 while (v != 0) {
911 r = u % v;
912 u = v;
913 v = r;
914 }
915
916 return u;
917}
918
919/****************************************************************************
920**
921** Name: umax
922**
923** Description: Implements a simple maximum function for unsigned numbers.
924** Implemented as a function rather than a macro to avoid
925** multiple evaluation of the calling parameters.
926**
927** Parameters: a, b - Values to be compared
928**
929** Global: None
930**
931** Returns: larger of the input values.
932**
933** Dependencies: None.
934**
935** Revision History:
936**
937** SCR Date Author Description
938** -------------------------------------------------------------------------
939** N/A 06-02-2004 JWS Original
940**
941****************************************************************************/
Mauro Carvalho Chehabcfde8922011-07-20 21:01:48 -0300942static u32 MT2063_umax(u32 a, u32 b)
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -0300943{
944 return (a >= b) ? a : b;
945}
946
947#if MT2063_TUNER_CNT > 1
Mauro Carvalho Chehabcfde8922011-07-20 21:01:48 -0300948static s32 RoundAwayFromZero(s32 n, s32 d)
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -0300949{
950 return (n < 0) ? floor(n, d) : ceil(n, d);
951}
952
953/****************************************************************************
954**
955** Name: IsSpurInAdjTunerBand
956**
957** Description: Checks to see if a spur will be present within the IF's
958** bandwidth or near the zero IF.
959** (fIFOut +/- fIFBW/2, -fIFOut +/- fIFBW/2)
960** and
961** (0 +/- fZIFBW/2)
962**
963** ma mb me mf mc md
964** <--+-+-+-----------------+-+-+-----------------+-+-+-->
965** | ^ 0 ^ |
966** ^ b=-fIFOut+fIFBW/2 -b=+fIFOut-fIFBW/2 ^
967** a=-fIFOut-fIFBW/2 -a=+fIFOut+fIFBW/2
968**
969** Note that some equations are doubled to prevent round-off
970** problems when calculating fIFBW/2
971**
972** The spur frequencies are computed as:
973**
974** fSpur = n * f1 - m * f2 - fOffset
975**
976** Parameters: f1 - The 1st local oscillator (LO) frequency
977** of the tuner whose output we are examining
978** f2 - The 1st local oscillator (LO) frequency
979** of the adjacent tuner
980** fOffset - The 2nd local oscillator of the tuner whose
981** output we are examining
982** fIFOut - Output IF center frequency
983** fIFBW - Output IF Bandwidth
984** nMaxH - max # of LO harmonics to search
985** fp - If spur, positive distance to spur-free band edge (returned)
986** fm - If spur, negative distance to spur-free band edge (returned)
987**
988** Returns: 1 if an LO spur would be present, otherwise 0.
989**
990** Dependencies: None.
991**
992** Revision History:
993**
994** SCR Date Author Description
995** -------------------------------------------------------------------------
996** N/A 01-21-2005 JWS Original, adapted from MT_DoubleConversion.
997** 115 03-23-2007 DAD Fix declaration of spur due to truncation
998** errors.
999** 137 06-18-2007 DAD Ver 1.16: Fix possible divide-by-0 error for
1000** multi-tuners that have
1001** (delta IF1) > (f_out-f_outbw/2).
1002** 177 S 02-26-2008 RSK Ver 1.18: Corrected calculation using LO1 > MAX/2
1003** Type casts added to preserve correct sign.
1004**
1005****************************************************************************/
Mauro Carvalho Chehabcfde8922011-07-20 21:01:48 -03001006static u32 IsSpurInAdjTunerBand(u32 bIsMyOutput,
1007 u32 f1,
1008 u32 f2,
1009 u32 fOffset,
1010 u32 fIFOut,
1011 u32 fIFBW,
1012 u32 fZIFBW,
1013 u32 nMaxH, u32 * fp, u32 * fm)
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03001014{
Mauro Carvalho Chehabcfde8922011-07-20 21:01:48 -03001015 u32 bSpurFound = 0;
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03001016
Mauro Carvalho Chehabcfde8922011-07-20 21:01:48 -03001017 const u32 fHalf_IFBW = fIFBW / 2;
1018 const u32 fHalf_ZIFBW = fZIFBW / 2;
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03001019
1020 /* Calculate a scale factor for all frequencies, so that our
1021 calculations all stay within 31 bits */
Mauro Carvalho Chehabcfde8922011-07-20 21:01:48 -03001022 const u32 f_Scale =
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03001023 ((f1 +
1024 (fOffset + fIFOut +
1025 fHalf_IFBW) / nMaxH) / (MAX_UDATA / 2 / nMaxH)) + 1;
1026
1027 /*
1028 ** After this scaling, _f1, _f2, and _f3 are guaranteed to fit into
1029 ** signed data types (smaller than MAX_UDATA/2)
1030 */
Mauro Carvalho Chehabcfde8922011-07-20 21:01:48 -03001031 const s32 _f1 = (s32) (f1 / f_Scale);
1032 const s32 _f2 = (s32) (f2 / f_Scale);
1033 const s32 _f3 = (s32) (fOffset / f_Scale);
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03001034
Mauro Carvalho Chehabcfde8922011-07-20 21:01:48 -03001035 const s32 c = (s32) (fIFOut - fHalf_IFBW) / (s32) f_Scale;
1036 const s32 d = (s32) ((fIFOut + fHalf_IFBW) / f_Scale);
1037 const s32 f = (s32) (fHalf_ZIFBW / f_Scale);
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03001038
Mauro Carvalho Chehabcfde8922011-07-20 21:01:48 -03001039 s32 ma, mb, mc, md, me, mf;
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03001040
Mauro Carvalho Chehabcfde8922011-07-20 21:01:48 -03001041 s32 fp_ = 0;
1042 s32 fm_ = 0;
1043 s32 n;
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03001044
1045 /*
1046 ** If the other tuner does not have an LO frequency defined,
1047 ** assume that we cannot interfere with it
1048 */
1049 if (f2 == 0)
1050 return 0;
1051
1052 /* Check out all multiples of f1 from -nMaxH to +nMaxH */
Mauro Carvalho Chehabcfde8922011-07-20 21:01:48 -03001053 for (n = -(s32) nMaxH; n <= (s32) nMaxH; ++n) {
1054 const s32 nf1 = n * _f1;
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03001055 md = (_f3 + d - nf1) / _f2;
1056
1057 /* If # f2 harmonics > nMaxH, then no spurs present */
Mauro Carvalho Chehabcfde8922011-07-20 21:01:48 -03001058 if (md <= -(s32) nMaxH)
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03001059 break;
1060
1061 ma = (_f3 - d - nf1) / _f2;
Mauro Carvalho Chehabcfde8922011-07-20 21:01:48 -03001062 if ((ma == md) || (ma >= (s32) (nMaxH)))
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03001063 continue;
1064
1065 mc = (_f3 + c - nf1) / _f2;
1066 if (mc != md) {
Mauro Carvalho Chehabcfde8922011-07-20 21:01:48 -03001067 const s32 m = (n < 0) ? md : mc;
1068 const s32 fspur = (nf1 + m * _f2 - _f3);
1069 const s32 den = (bIsMyOutput ? n - 1 : n);
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03001070 if (den == 0) {
1071 fp_ = (d - fspur) * f_Scale;
1072 fm_ = (fspur - c) * f_Scale;
1073 } else {
1074 fp_ =
Mauro Carvalho Chehabcfde8922011-07-20 21:01:48 -03001075 (s32) RoundAwayFromZero((d - fspur) *
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03001076 f_Scale, den);
1077 fm_ =
Mauro Carvalho Chehabcfde8922011-07-20 21:01:48 -03001078 (s32) RoundAwayFromZero((fspur - c) *
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03001079 f_Scale, den);
1080 }
Mauro Carvalho Chehabcfde8922011-07-20 21:01:48 -03001081 if (((u32) abs(fm_) >= f_Scale)
1082 && ((u32) abs(fp_) >= f_Scale)) {
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03001083 bSpurFound = 1;
1084 break;
1085 }
1086 }
1087
1088 /* Location of Zero-IF-spur to be checked */
1089 mf = (_f3 + f - nf1) / _f2;
1090 me = (_f3 - f - nf1) / _f2;
1091 if (me != mf) {
Mauro Carvalho Chehabcfde8922011-07-20 21:01:48 -03001092 const s32 m = (n < 0) ? mf : me;
1093 const s32 fspur = (nf1 + m * _f2 - _f3);
1094 const s32 den = (bIsMyOutput ? n - 1 : n);
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03001095 if (den == 0) {
1096 fp_ = (d - fspur) * f_Scale;
1097 fm_ = (fspur - c) * f_Scale;
1098 } else {
1099 fp_ =
Mauro Carvalho Chehabcfde8922011-07-20 21:01:48 -03001100 (s32) RoundAwayFromZero((f - fspur) *
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03001101 f_Scale, den);
1102 fm_ =
Mauro Carvalho Chehabcfde8922011-07-20 21:01:48 -03001103 (s32) RoundAwayFromZero((fspur + f) *
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03001104 f_Scale, den);
1105 }
Mauro Carvalho Chehabcfde8922011-07-20 21:01:48 -03001106 if (((u32) abs(fm_) >= f_Scale)
1107 && ((u32) abs(fp_) >= f_Scale)) {
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03001108 bSpurFound = 1;
1109 break;
1110 }
1111 }
1112
1113 mb = (_f3 - c - nf1) / _f2;
1114 if (ma != mb) {
Mauro Carvalho Chehabcfde8922011-07-20 21:01:48 -03001115 const s32 m = (n < 0) ? mb : ma;
1116 const s32 fspur = (nf1 + m * _f2 - _f3);
1117 const s32 den = (bIsMyOutput ? n - 1 : n);
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03001118 if (den == 0) {
1119 fp_ = (d - fspur) * f_Scale;
1120 fm_ = (fspur - c) * f_Scale;
1121 } else {
1122 fp_ =
Mauro Carvalho Chehabcfde8922011-07-20 21:01:48 -03001123 (s32) RoundAwayFromZero((-c - fspur) *
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03001124 f_Scale, den);
1125 fm_ =
Mauro Carvalho Chehabcfde8922011-07-20 21:01:48 -03001126 (s32) RoundAwayFromZero((fspur + d) *
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03001127 f_Scale, den);
1128 }
Mauro Carvalho Chehabcfde8922011-07-20 21:01:48 -03001129 if (((u32) abs(fm_) >= f_Scale)
1130 && ((u32) abs(fp_) >= f_Scale)) {
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03001131 bSpurFound = 1;
1132 break;
1133 }
1134 }
1135 }
1136
1137 /*
1138 ** Verify that fm & fp are both positive
1139 ** Add one to ensure next 1st IF choice is not right on the edge
1140 */
1141 if (fp_ < 0) {
1142 *fp = -fm_ + 1;
1143 *fm = -fp_ + 1;
1144 } else if (fp_ > 0) {
1145 *fp = fp_ + 1;
1146 *fm = fm_ + 1;
1147 } else {
1148 *fp = 1;
1149 *fm = abs(fm_) + 1;
1150 }
1151
1152 return bSpurFound;
1153}
1154#endif
1155
1156/****************************************************************************
1157**
1158** Name: IsSpurInBand
1159**
1160** Description: Checks to see if a spur will be present within the IF's
1161** bandwidth. (fIFOut +/- fIFBW, -fIFOut +/- fIFBW)
1162**
1163** ma mb mc md
1164** <--+-+-+-------------------+-------------------+-+-+-->
1165** | ^ 0 ^ |
1166** ^ b=-fIFOut+fIFBW/2 -b=+fIFOut-fIFBW/2 ^
1167** a=-fIFOut-fIFBW/2 -a=+fIFOut+fIFBW/2
1168**
1169** Note that some equations are doubled to prevent round-off
1170** problems when calculating fIFBW/2
1171**
1172** Parameters: pAS_Info - Avoid Spurs information block
1173** fm - If spur, amount f_IF1 has to move negative
1174** fp - If spur, amount f_IF1 has to move positive
1175**
1176** Global: None
1177**
1178** Returns: 1 if an LO spur would be present, otherwise 0.
1179**
1180** Dependencies: None.
1181**
1182** Revision History:
1183**
1184** SCR Date Author Description
1185** -------------------------------------------------------------------------
1186** N/A 11-28-2002 DAD Implemented algorithm from applied patent
1187**
1188****************************************************************************/
Mauro Carvalho Chehabcfde8922011-07-20 21:01:48 -03001189static u32 IsSpurInBand(struct MT2063_AvoidSpursData_t *pAS_Info,
1190 u32 * fm, u32 * fp)
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03001191{
1192 /*
1193 ** Calculate LO frequency settings.
1194 */
Mauro Carvalho Chehabcfde8922011-07-20 21:01:48 -03001195 u32 n, n0;
1196 const u32 f_LO1 = pAS_Info->f_LO1;
1197 const u32 f_LO2 = pAS_Info->f_LO2;
1198 const u32 d = pAS_Info->f_out + pAS_Info->f_out_bw / 2;
1199 const u32 c = d - pAS_Info->f_out_bw;
1200 const u32 f = pAS_Info->f_zif_bw / 2;
1201 const u32 f_Scale = (f_LO1 / (MAX_UDATA / 2 / pAS_Info->maxH1)) + 1;
1202 s32 f_nsLO1, f_nsLO2;
1203 s32 f_Spur;
1204 u32 ma, mb, mc, md, me, mf;
1205 u32 lo_gcd, gd_Scale, gc_Scale, gf_Scale, hgds, hgfs, hgcs;
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03001206#if MT2063_TUNER_CNT > 1
Mauro Carvalho Chehabcfde8922011-07-20 21:01:48 -03001207 u32 index;
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03001208
1209 struct MT2063_AvoidSpursData_t *adj;
1210#endif
1211 *fm = 0;
1212
1213 /*
1214 ** For each edge (d, c & f), calculate a scale, based on the gcd
1215 ** of f_LO1, f_LO2 and the edge value. Use the larger of this
1216 ** gcd-based scale factor or f_Scale.
1217 */
1218 lo_gcd = MT2063_gcd(f_LO1, f_LO2);
Mauro Carvalho Chehabcfde8922011-07-20 21:01:48 -03001219 gd_Scale = MT2063_umax((u32) MT2063_gcd(lo_gcd, d), f_Scale);
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03001220 hgds = gd_Scale / 2;
Mauro Carvalho Chehabcfde8922011-07-20 21:01:48 -03001221 gc_Scale = MT2063_umax((u32) MT2063_gcd(lo_gcd, c), f_Scale);
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03001222 hgcs = gc_Scale / 2;
Mauro Carvalho Chehabcfde8922011-07-20 21:01:48 -03001223 gf_Scale = MT2063_umax((u32) MT2063_gcd(lo_gcd, f), f_Scale);
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03001224 hgfs = gf_Scale / 2;
1225
1226 n0 = uceil(f_LO2 - d, f_LO1 - f_LO2);
1227
1228 /* Check out all multiples of LO1 from n0 to m_maxLOSpurHarmonic */
1229 for (n = n0; n <= pAS_Info->maxH1; ++n) {
1230 md = (n * ((f_LO1 + hgds) / gd_Scale) -
1231 ((d + hgds) / gd_Scale)) / ((f_LO2 + hgds) / gd_Scale);
1232
1233 /* If # fLO2 harmonics > m_maxLOSpurHarmonic, then no spurs present */
1234 if (md >= pAS_Info->maxH1)
1235 break;
1236
1237 ma = (n * ((f_LO1 + hgds) / gd_Scale) +
1238 ((d + hgds) / gd_Scale)) / ((f_LO2 + hgds) / gd_Scale);
1239
1240 /* If no spurs between +/- (f_out + f_IFBW/2), then try next harmonic */
1241 if (md == ma)
1242 continue;
1243
1244 mc = (n * ((f_LO1 + hgcs) / gc_Scale) -
1245 ((c + hgcs) / gc_Scale)) / ((f_LO2 + hgcs) / gc_Scale);
1246 if (mc != md) {
Mauro Carvalho Chehabcfde8922011-07-20 21:01:48 -03001247 f_nsLO1 = (s32) (n * (f_LO1 / gc_Scale));
1248 f_nsLO2 = (s32) (mc * (f_LO2 / gc_Scale));
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03001249 f_Spur =
1250 (gc_Scale * (f_nsLO1 - f_nsLO2)) +
1251 n * (f_LO1 % gc_Scale) - mc * (f_LO2 % gc_Scale);
1252
Mauro Carvalho Chehabcfde8922011-07-20 21:01:48 -03001253 *fp = ((f_Spur - (s32) c) / (mc - n)) + 1;
1254 *fm = (((s32) d - f_Spur) / (mc - n)) + 1;
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03001255 return 1;
1256 }
1257
1258 /* Location of Zero-IF-spur to be checked */
1259 me = (n * ((f_LO1 + hgfs) / gf_Scale) +
1260 ((f + hgfs) / gf_Scale)) / ((f_LO2 + hgfs) / gf_Scale);
1261 mf = (n * ((f_LO1 + hgfs) / gf_Scale) -
1262 ((f + hgfs) / gf_Scale)) / ((f_LO2 + hgfs) / gf_Scale);
1263 if (me != mf) {
1264 f_nsLO1 = n * (f_LO1 / gf_Scale);
1265 f_nsLO2 = me * (f_LO2 / gf_Scale);
1266 f_Spur =
1267 (gf_Scale * (f_nsLO1 - f_nsLO2)) +
1268 n * (f_LO1 % gf_Scale) - me * (f_LO2 % gf_Scale);
1269
Mauro Carvalho Chehabcfde8922011-07-20 21:01:48 -03001270 *fp = ((f_Spur + (s32) f) / (me - n)) + 1;
1271 *fm = (((s32) f - f_Spur) / (me - n)) + 1;
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03001272 return 1;
1273 }
1274
1275 mb = (n * ((f_LO1 + hgcs) / gc_Scale) +
1276 ((c + hgcs) / gc_Scale)) / ((f_LO2 + hgcs) / gc_Scale);
1277 if (ma != mb) {
1278 f_nsLO1 = n * (f_LO1 / gc_Scale);
1279 f_nsLO2 = ma * (f_LO2 / gc_Scale);
1280 f_Spur =
1281 (gc_Scale * (f_nsLO1 - f_nsLO2)) +
1282 n * (f_LO1 % gc_Scale) - ma * (f_LO2 % gc_Scale);
1283
Mauro Carvalho Chehabcfde8922011-07-20 21:01:48 -03001284 *fp = (((s32) d + f_Spur) / (ma - n)) + 1;
1285 *fm = (-(f_Spur + (s32) c) / (ma - n)) + 1;
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03001286 return 1;
1287 }
1288 }
1289
1290#if MT2063_TUNER_CNT > 1
1291 /* If no spur found, see if there are more tuners on the same board */
1292 for (index = 0; index < TunerCount; ++index) {
1293 adj = TunerList[index];
1294 if (pAS_Info == adj) /* skip over our own data, don't process it */
1295 continue;
1296
1297 /* Look for LO-related spurs from the adjacent tuner generated into my IF output */
1298 if (IsSpurInAdjTunerBand(1, /* check my IF output */
1299 pAS_Info->f_LO1, /* my fLO1 */
1300 adj->f_LO1, /* the other tuner's fLO1 */
1301 pAS_Info->f_LO2, /* my fLO2 */
1302 pAS_Info->f_out, /* my fOut */
1303 pAS_Info->f_out_bw, /* my output IF bandwidth */
1304 pAS_Info->f_zif_bw, /* my Zero-IF bandwidth */
1305 pAS_Info->maxH2, fp, /* minimum amount to move LO's positive */
1306 fm)) /* miminum amount to move LO's negative */
1307 return 1;
1308 /* Look for LO-related spurs from my tuner generated into the adjacent tuner's IF output */
1309 if (IsSpurInAdjTunerBand(0, /* check his IF output */
1310 pAS_Info->f_LO1, /* my fLO1 */
1311 adj->f_LO1, /* the other tuner's fLO1 */
1312 adj->f_LO2, /* the other tuner's fLO2 */
1313 adj->f_out, /* the other tuner's fOut */
1314 adj->f_out_bw, /* the other tuner's output IF bandwidth */
1315 pAS_Info->f_zif_bw, /* the other tuner's Zero-IF bandwidth */
1316 adj->maxH2, fp, /* minimum amount to move LO's positive */
1317 fm)) /* miminum amount to move LO's negative */
1318 return 1;
1319 }
1320#endif
1321 /* No spurs found */
Mauro Carvalho Chehab223c7b02011-07-20 19:48:59 -03001322 return 0;
1323}
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03001324
1325/*****************************************************************************
1326**
1327** Name: MT_AvoidSpurs
1328**
1329** Description: Main entry point to avoid spurs.
1330** Checks for existing spurs in present LO1, LO2 freqs
1331** and if present, chooses spur-free LO1, LO2 combination
1332** that tunes the same input/output frequencies.
1333**
1334** Revision History:
1335**
1336** SCR Date Author Description
1337** -------------------------------------------------------------------------
1338** 096 04-06-2005 DAD Ver 1.11: Fix divide by 0 error if maxH==0.
1339**
1340*****************************************************************************/
Mauro Carvalho Chehabcfde8922011-07-20 21:01:48 -03001341u32 MT2063_AvoidSpurs(void *h, struct MT2063_AvoidSpursData_t * pAS_Info)
Mauro Carvalho Chehab223c7b02011-07-20 19:48:59 -03001342{
Mauro Carvalho Chehabcfde8922011-07-20 21:01:48 -03001343 u32 status = MT2063_OK;
1344 u32 fm, fp; /* restricted range on LO's */
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03001345 pAS_Info->bSpurAvoided = 0;
1346 pAS_Info->nSpursFound = 0;
1347
1348 if (pAS_Info->maxH1 == 0)
1349 return MT2063_OK;
1350
1351 /*
1352 ** Avoid LO Generated Spurs
1353 **
1354 ** Make sure that have no LO-related spurs within the IF output
1355 ** bandwidth.
1356 **
1357 ** If there is an LO spur in this band, start at the current IF1 frequency
1358 ** and work out until we find a spur-free frequency or run up against the
1359 ** 1st IF SAW band edge. Use temporary copies of fLO1 and fLO2 so that they
1360 ** will be unchanged if a spur-free setting is not found.
1361 */
1362 pAS_Info->bSpurPresent = IsSpurInBand(pAS_Info, &fm, &fp);
1363 if (pAS_Info->bSpurPresent) {
Mauro Carvalho Chehabcfde8922011-07-20 21:01:48 -03001364 u32 zfIF1 = pAS_Info->f_LO1 - pAS_Info->f_in; /* current attempt at a 1st IF */
1365 u32 zfLO1 = pAS_Info->f_LO1; /* current attempt at an LO1 freq */
1366 u32 zfLO2 = pAS_Info->f_LO2; /* current attempt at an LO2 freq */
1367 u32 delta_IF1;
1368 u32 new_IF1;
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03001369
1370 /*
1371 ** Spur was found, attempt to find a spur-free 1st IF
1372 */
1373 do {
1374 pAS_Info->nSpursFound++;
1375
1376 /* Raise f_IF1_upper, if needed */
1377 MT2063_AddExclZone(pAS_Info, zfIF1 - fm, zfIF1 + fp);
1378
1379 /* Choose next IF1 that is closest to f_IF1_CENTER */
1380 new_IF1 = MT2063_ChooseFirstIF(pAS_Info);
1381
1382 if (new_IF1 > zfIF1) {
1383 pAS_Info->f_LO1 += (new_IF1 - zfIF1);
1384 pAS_Info->f_LO2 += (new_IF1 - zfIF1);
1385 } else {
1386 pAS_Info->f_LO1 -= (zfIF1 - new_IF1);
1387 pAS_Info->f_LO2 -= (zfIF1 - new_IF1);
1388 }
1389 zfIF1 = new_IF1;
1390
1391 if (zfIF1 > pAS_Info->f_if1_Center)
1392 delta_IF1 = zfIF1 - pAS_Info->f_if1_Center;
1393 else
1394 delta_IF1 = pAS_Info->f_if1_Center - zfIF1;
1395 }
1396 /*
1397 ** Continue while the new 1st IF is still within the 1st IF bandwidth
1398 ** and there is a spur in the band (again)
1399 */
1400 while ((2 * delta_IF1 + pAS_Info->f_out_bw <=
1401 pAS_Info->f_if1_bw)
1402 && (pAS_Info->bSpurPresent =
1403 IsSpurInBand(pAS_Info, &fm, &fp)));
1404
1405 /*
1406 ** Use the LO-spur free values found. If the search went all the way to
1407 ** the 1st IF band edge and always found spurs, just leave the original
1408 ** choice. It's as "good" as any other.
1409 */
1410 if (pAS_Info->bSpurPresent == 1) {
1411 status |= MT2063_SPUR_PRESENT_ERR;
1412 pAS_Info->f_LO1 = zfLO1;
1413 pAS_Info->f_LO2 = zfLO2;
1414 } else
1415 pAS_Info->bSpurAvoided = 1;
1416 }
1417
1418 status |=
1419 ((pAS_Info->
1420 nSpursFound << MT2063_SPUR_SHIFT) & MT2063_SPUR_CNT_MASK);
1421
1422 return (status);
Mauro Carvalho Chehab223c7b02011-07-20 19:48:59 -03001423}
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03001424
Mauro Carvalho Chehabcfde8922011-07-20 21:01:48 -03001425u32 MT2063_AvoidSpursVersion(void)
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03001426{
1427 return (MT2063_SPUR_VERSION);
1428}
1429
1430//end of mt2063_spuravoid.c
1431//=================================================================
1432//#################################################################
1433//=================================================================
1434
1435/*
1436** The expected version of MT_AvoidSpursData_t
1437** If the version is different, an updated file is needed from Microtune
1438*/
1439/* Expecting version 1.21 of the Spur Avoidance API */
1440#define EXPECTED_MT2063_AVOID_SPURS_INFO_VERSION 010201
1441
1442#if MT2063_AVOID_SPURS_INFO_VERSION < EXPECTED_MT2063_AVOID_SPURS_INFO_VERSION
1443#error Contact Microtune for a newer version of MT_SpurAvoid.c
1444#elif MT2063_AVOID_SPURS_INFO_VERSION > EXPECTED_MT2063_AVOID_SPURS_INFO_VERSION
1445#error Contact Microtune for a newer version of mt2063.c
1446#endif
1447
1448#ifndef MT2063_CNT
1449#error You must define MT2063_CNT in the "mt_userdef.h" file
1450#endif
1451
1452typedef enum {
1453 MT2063_SET_ATTEN,
1454 MT2063_INCR_ATTEN,
1455 MT2063_DECR_ATTEN
1456} MT2063_ATTEN_CNTL_MODE;
1457
1458//#define TUNER_MT2063_OPTIMIZATION
1459/*
1460** Constants used by the tuning algorithm
1461*/
1462#define MT2063_REF_FREQ (16000000UL) /* Reference oscillator Frequency (in Hz) */
1463#define MT2063_IF1_BW (22000000UL) /* The IF1 filter bandwidth (in Hz) */
1464#define MT2063_TUNE_STEP_SIZE (50000UL) /* Tune in steps of 50 kHz */
1465#define MT2063_SPUR_STEP_HZ (250000UL) /* Step size (in Hz) to move IF1 when avoiding spurs */
1466#define MT2063_ZIF_BW (2000000UL) /* Zero-IF spur-free bandwidth (in Hz) */
1467#define MT2063_MAX_HARMONICS_1 (15UL) /* Highest intra-tuner LO Spur Harmonic to be avoided */
1468#define MT2063_MAX_HARMONICS_2 (5UL) /* Highest inter-tuner LO Spur Harmonic to be avoided */
1469#define MT2063_MIN_LO_SEP (1000000UL) /* Minimum inter-tuner LO frequency separation */
1470#define MT2063_LO1_FRACN_AVOID (0UL) /* LO1 FracN numerator avoid region (in Hz) */
1471#define MT2063_LO2_FRACN_AVOID (199999UL) /* LO2 FracN numerator avoid region (in Hz) */
1472#define MT2063_MIN_FIN_FREQ (44000000UL) /* Minimum input frequency (in Hz) */
1473#define MT2063_MAX_FIN_FREQ (1100000000UL) /* Maximum input frequency (in Hz) */
1474#define MT2063_MIN_FOUT_FREQ (36000000UL) /* Minimum output frequency (in Hz) */
1475#define MT2063_MAX_FOUT_FREQ (57000000UL) /* Maximum output frequency (in Hz) */
1476#define MT2063_MIN_DNC_FREQ (1293000000UL) /* Minimum LO2 frequency (in Hz) */
1477#define MT2063_MAX_DNC_FREQ (1614000000UL) /* Maximum LO2 frequency (in Hz) */
1478#define MT2063_MIN_UPC_FREQ (1396000000UL) /* Minimum LO1 frequency (in Hz) */
1479#define MT2063_MAX_UPC_FREQ (2750000000UL) /* Maximum LO1 frequency (in Hz) */
1480
1481/*
1482** Define the supported Part/Rev codes for the MT2063
1483*/
1484#define MT2063_B0 (0x9B)
1485#define MT2063_B1 (0x9C)
1486#define MT2063_B2 (0x9D)
1487#define MT2063_B3 (0x9E)
1488
1489/*
1490** The number of Tuner Registers
1491*/
Mauro Carvalho Chehabcfde8922011-07-20 21:01:48 -03001492static const u32 MT2063_Num_Registers = MT2063_REG_END_REGS;
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03001493
1494#define USE_GLOBAL_TUNER 0
1495
Mauro Carvalho Chehabcfde8922011-07-20 21:01:48 -03001496static u32 nMT2063MaxTuners = MT2063_CNT;
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03001497static struct MT2063_Info_t MT2063_Info[MT2063_CNT];
1498static struct MT2063_Info_t *MT2063_Avail[MT2063_CNT];
Mauro Carvalho Chehabcfde8922011-07-20 21:01:48 -03001499static u32 nMT2063OpenTuners = 0;
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03001500
1501/*
1502** Constants for setting receiver modes.
1503** (6 modes defined at this time, enumerated by MT2063_RCVR_MODES)
1504** (DNC1GC & DNC2GC are the values, which are used, when the specific
1505** DNC Output is selected, the other is always off)
1506**
1507** If PAL-L or L' is received, set:
1508** MT2063_SetParam(hMT2063,MT2063_TAGC,1);
1509**
1510** --------------+----------------------------------------------
1511** Mode 0 : | MT2063_CABLE_QAM
1512** Mode 1 : | MT2063_CABLE_ANALOG
1513** Mode 2 : | MT2063_OFFAIR_COFDM
1514** Mode 3 : | MT2063_OFFAIR_COFDM_SAWLESS
1515** Mode 4 : | MT2063_OFFAIR_ANALOG
1516** Mode 5 : | MT2063_OFFAIR_8VSB
1517** --------------+----+----+----+----+-----+-----+--------------
1518** Mode | 0 | 1 | 2 | 3 | 4 | 5 |
1519** --------------+----+----+----+----+-----+-----+
1520**
1521**
1522*/
Mauro Carvalho Chehabcfde8922011-07-20 21:01:48 -03001523static const u8 RFAGCEN[] = { 0, 0, 0, 0, 0, 0 };
1524static const u8 LNARIN[] = { 0, 0, 3, 3, 3, 3 };
1525static const u8 FIFFQEN[] = { 1, 1, 1, 1, 1, 1 };
1526static const u8 FIFFQ[] = { 0, 0, 0, 0, 0, 0 };
1527static const u8 DNC1GC[] = { 0, 0, 0, 0, 0, 0 };
1528static const u8 DNC2GC[] = { 0, 0, 0, 0, 0, 0 };
1529static const u8 ACLNAMAX[] = { 31, 31, 31, 31, 31, 31 };
1530static const u8 LNATGT[] = { 44, 43, 43, 43, 43, 43 };
1531static const u8 RFOVDIS[] = { 0, 0, 0, 0, 0, 0 };
1532static const u8 ACRFMAX[] = { 31, 31, 31, 31, 31, 31 };
1533static const u8 PD1TGT[] = { 36, 36, 38, 38, 36, 38 };
1534static const u8 FIFOVDIS[] = { 0, 0, 0, 0, 0, 0 };
1535static const u8 ACFIFMAX[] = { 29, 29, 29, 29, 29, 29 };
1536static const u8 PD2TGT[] = { 40, 33, 38, 42, 30, 38 };
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03001537
1538/*
1539** Local Function Prototypes - not available for external access.
1540*/
1541
1542/* Forward declaration(s): */
Mauro Carvalho Chehabcfde8922011-07-20 21:01:48 -03001543static u32 MT2063_CalcLO1Mult(u32 * Div, u32 * FracN, u32 f_LO,
1544 u32 f_LO_Step, u32 f_Ref);
1545static u32 MT2063_CalcLO2Mult(u32 * Div, u32 * FracN, u32 f_LO,
1546 u32 f_LO_Step, u32 f_Ref);
1547static u32 MT2063_fLO_FractionalTerm(u32 f_ref, u32 num,
1548 u32 denom);
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03001549
1550/******************************************************************************
1551**
1552** Name: MT2063_Open
1553**
1554** Description: Initialize the tuner's register values.
1555**
1556** Parameters: MT2063_Addr - Serial bus address of the tuner.
1557** hMT2063 - Tuner handle passed back.
1558** hUserData - User-defined data, if needed for the
1559** MT_ReadSub() & MT_WriteSub functions.
1560**
1561** Returns: status:
1562** MT_OK - No errors
1563** MT_TUNER_ID_ERR - Tuner Part/Rev code mismatch
1564** MT_TUNER_INIT_ERR - Tuner initialization failed
1565** MT_COMM_ERR - Serial bus communications error
1566** MT_ARG_NULL - Null pointer argument passed
1567** MT_TUNER_CNT_ERR - Too many tuners open
1568**
1569** Dependencies: MT_ReadSub - Read byte(s) of data from the two-wire bus
1570** MT_WriteSub - Write byte(s) of data to the two-wire bus
1571**
1572** Revision History:
1573**
1574** SCR Date Author Description
1575** -------------------------------------------------------------------------
1576** 138 06-19-2007 DAD Ver 1.00: Initial, derived from mt2067_b.
1577**
1578******************************************************************************/
Mauro Carvalho Chehabcfde8922011-07-20 21:01:48 -03001579u32 MT2063_Open(u32 MT2063_Addr, void ** hMT2063, void *hUserData)
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03001580{
Mauro Carvalho Chehabcfde8922011-07-20 21:01:48 -03001581 u32 status = MT2063_OK; /* Status to be returned. */
1582 s32 i;
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03001583 struct MT2063_Info_t *pInfo = NULL;
1584 struct dvb_frontend *fe = (struct dvb_frontend *)hUserData;
1585 struct mt2063_state *state = fe->tuner_priv;
1586
1587 /* Check the argument before using */
1588 if (hMT2063 == NULL) {
1589 return MT2063_ARG_NULL;
1590 }
1591
1592 /* Default tuner handle to NULL. If successful, it will be reassigned */
1593
1594#if USE_GLOBAL_TUNER
1595 *hMT2063 = NULL;
1596
1597 /*
1598 ** If this is our first tuner, initialize the address fields and
1599 ** the list of available control blocks.
1600 */
1601 if (nMT2063OpenTuners == 0) {
1602 for (i = MT2063_CNT - 1; i >= 0; i--) {
1603 MT2063_Info[i].handle = NULL;
1604 MT2063_Info[i].address = MAX_UDATA;
1605 MT2063_Info[i].rcvr_mode = MT2063_CABLE_QAM;
1606 MT2063_Info[i].hUserData = NULL;
1607 MT2063_Avail[i] = &MT2063_Info[i];
1608 }
1609 }
1610
1611 /*
1612 ** Look for an existing MT2063_State_t entry with this address.
1613 */
1614 for (i = MT2063_CNT - 1; i >= 0; i--) {
1615 /*
1616 ** If an open'ed handle provided, we'll re-initialize that structure.
1617 **
1618 ** We recognize an open tuner because the address and hUserData are
1619 ** the same as one that has already been opened
1620 */
1621 if ((MT2063_Info[i].address == MT2063_Addr) &&
1622 (MT2063_Info[i].hUserData == hUserData)) {
1623 pInfo = &MT2063_Info[i];
1624 break;
1625 }
1626 }
1627
1628 /* If not found, choose an empty spot. */
1629 if (pInfo == NULL) {
1630 /* Check to see that we're not over-allocating */
1631 if (nMT2063OpenTuners == MT2063_CNT) {
1632 return MT2063_TUNER_CNT_ERR;
1633 }
1634 /* Use the next available block from the list */
1635 pInfo = MT2063_Avail[nMT2063OpenTuners];
1636 nMT2063OpenTuners++;
1637 }
1638#else
Mauro Carvalho Chehabcfde8922011-07-20 21:01:48 -03001639 if (state->MT2063_init == false) {
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03001640 pInfo = kzalloc(sizeof(struct MT2063_Info_t), GFP_KERNEL);
1641 if (pInfo == NULL) {
1642 return MT2063_TUNER_OPEN_ERR;
1643 }
1644 pInfo->handle = NULL;
1645 pInfo->address = MAX_UDATA;
1646 pInfo->rcvr_mode = MT2063_CABLE_QAM;
1647 pInfo->hUserData = NULL;
1648 } else {
1649 pInfo = *hMT2063;
1650 }
1651#endif
1652
1653 if (MT2063_NO_ERROR(status)) {
1654 status |= MT2063_RegisterTuner(&pInfo->AS_Data);
1655 }
1656
1657 if (MT2063_NO_ERROR(status)) {
Mauro Carvalho Chehabcfde8922011-07-20 21:01:48 -03001658 pInfo->handle = (void *) pInfo;
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03001659
1660 pInfo->hUserData = hUserData;
1661 pInfo->address = MT2063_Addr;
1662 pInfo->rcvr_mode = MT2063_CABLE_QAM;
Mauro Carvalho Chehabcfde8922011-07-20 21:01:48 -03001663 status |= MT2063_ReInit((void *) pInfo);
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03001664 }
1665
1666 if (MT2063_IS_ERROR(status))
1667 /* MT2063_Close handles the un-registration of the tuner */
Mauro Carvalho Chehabcfde8922011-07-20 21:01:48 -03001668 MT2063_Close((void *) pInfo);
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03001669 else {
Mauro Carvalho Chehabcfde8922011-07-20 21:01:48 -03001670 state->MT2063_init = true;
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03001671 *hMT2063 = pInfo->handle;
1672
1673 }
1674
1675 return (status);
1676}
1677
Mauro Carvalho Chehabcfde8922011-07-20 21:01:48 -03001678static u32 MT2063_IsValidHandle(struct MT2063_Info_t *handle)
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03001679{
1680 return ((handle != NULL) && (handle->handle == handle)) ? 1 : 0;
1681}
1682
1683/******************************************************************************
1684**
1685** Name: MT2063_Close
1686**
1687** Description: Release the handle to the tuner.
1688**
1689** Parameters: hMT2063 - Handle to the MT2063 tuner
1690**
1691** Returns: status:
1692** MT_OK - No errors
1693** MT_INV_HANDLE - Invalid tuner handle
1694**
1695** Dependencies: mt_errordef.h - definition of error codes
1696**
1697** Revision History:
1698**
1699** SCR Date Author Description
1700** -------------------------------------------------------------------------
1701** 138 06-19-2007 DAD Ver 1.00: Initial, derived from mt2067_b.
1702**
1703******************************************************************************/
Mauro Carvalho Chehabcfde8922011-07-20 21:01:48 -03001704u32 MT2063_Close(void *hMT2063)
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03001705{
1706 struct MT2063_Info_t *pInfo = (struct MT2063_Info_t *)hMT2063;
1707
1708 if (!MT2063_IsValidHandle(pInfo))
1709 return MT2063_INV_HANDLE;
1710
1711 /* Unregister tuner with SpurAvoidance routines (if needed) */
1712 MT2063_UnRegisterTuner(&pInfo->AS_Data);
1713 /* Now remove the tuner from our own list of tuners */
1714 pInfo->handle = NULL;
1715 pInfo->address = MAX_UDATA;
1716 pInfo->hUserData = NULL;
1717#if USE_GLOBAL_TUNER
1718 nMT2063OpenTuners--;
1719 MT2063_Avail[nMT2063OpenTuners] = pInfo; /* Return control block to available list */
1720#else
1721 //kfree(pInfo);
1722 //pInfo = NULL;
1723#endif
1724 return MT2063_OK;
1725}
1726
1727/******************************************************************************
1728**
1729** Name: MT2063_GetGPIO
1730**
1731** Description: Get the current MT2063 GPIO value.
1732**
1733** Parameters: h - Open handle to the tuner (from MT2063_Open).
1734** gpio_id - Selects GPIO0, GPIO1 or GPIO2
1735** attr - Selects input readback, I/O direction or
1736** output value
1737** *value - current setting of GPIO pin
1738**
1739** Usage: status = MT2063_GetGPIO(hMT2063, MT2063_GPIO_OUT, &value);
1740**
1741** Returns: status:
1742** MT_OK - No errors
1743** MT_COMM_ERR - Serial bus communications error
1744** MT_INV_HANDLE - Invalid tuner handle
1745** MT_ARG_NULL - Null pointer argument passed
1746**
1747** Dependencies: MT_ReadSub - Read byte(s) of data from the serial bus
1748**
1749** Revision History:
1750**
1751** SCR Date Author Description
1752** -------------------------------------------------------------------------
1753** 138 06-19-2007 DAD Ver 1.00: Initial, derived from mt2067_b.
1754**
1755******************************************************************************/
Mauro Carvalho Chehabcfde8922011-07-20 21:01:48 -03001756u32 MT2063_GetGPIO(void *h, enum MT2063_GPIO_ID gpio_id,
1757 enum MT2063_GPIO_Attr attr, u32 * value)
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03001758{
Mauro Carvalho Chehabcfde8922011-07-20 21:01:48 -03001759 u32 status = MT2063_OK; /* Status to be returned */
1760 u8 regno;
1761 s32 shift;
1762 static u8 GPIOreg[3] =
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03001763 { MT2063_REG_RF_STATUS, MT2063_REG_FIF_OV, MT2063_REG_RF_OV };
1764 struct MT2063_Info_t *pInfo = (struct MT2063_Info_t *)h;
1765
1766 if (MT2063_IsValidHandle(pInfo) == 0)
1767 return MT2063_INV_HANDLE;
1768
1769 if (value == NULL)
1770 return MT2063_ARG_NULL;
1771
1772 regno = GPIOreg[attr];
1773
1774 /* We'll read the register just in case the write didn't work last time */
1775 status =
1776 MT2063_ReadSub(pInfo->hUserData, pInfo->address, regno,
1777 &pInfo->reg[regno], 1);
1778
1779 shift = (gpio_id - MT2063_GPIO0 + 5);
1780 *value = (pInfo->reg[regno] >> shift) & 1;
1781
1782 return (status);
1783}
1784
1785/****************************************************************************
1786**
1787** Name: MT2063_GetLocked
1788**
1789** Description: Checks to see if LO1 and LO2 are locked.
1790**
1791** Parameters: h - Open handle to the tuner (from MT2063_Open).
1792**
1793** Returns: status:
1794** MT_OK - No errors
1795** MT_UPC_UNLOCK - Upconverter PLL unlocked
1796** MT_DNC_UNLOCK - Downconverter PLL unlocked
1797** MT_COMM_ERR - Serial bus communications error
1798** MT_INV_HANDLE - Invalid tuner handle
1799**
1800** Dependencies: MT_ReadSub - Read byte(s) of data from the serial bus
1801** MT_Sleep - Delay execution for x milliseconds
1802**
1803** Revision History:
1804**
1805** SCR Date Author Description
1806** -------------------------------------------------------------------------
1807** 138 06-19-2007 DAD Ver 1.00: Initial, derived from mt2067_b.
1808**
1809****************************************************************************/
Mauro Carvalho Chehabcfde8922011-07-20 21:01:48 -03001810u32 MT2063_GetLocked(void *h)
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03001811{
Mauro Carvalho Chehabcfde8922011-07-20 21:01:48 -03001812 const u32 nMaxWait = 100; /* wait a maximum of 100 msec */
1813 const u32 nPollRate = 2; /* poll status bits every 2 ms */
1814 const u32 nMaxLoops = nMaxWait / nPollRate;
1815 const u8 LO1LK = 0x80;
1816 u8 LO2LK = 0x08;
1817 u32 status = MT2063_OK; /* Status to be returned */
1818 u32 nDelays = 0;
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03001819 struct MT2063_Info_t *pInfo = (struct MT2063_Info_t *)h;
1820
1821 if (MT2063_IsValidHandle(pInfo) == 0)
1822 return MT2063_INV_HANDLE;
1823
1824 /* LO2 Lock bit was in a different place for B0 version */
1825 if (pInfo->tuner_id == MT2063_B0)
1826 LO2LK = 0x40;
1827
1828 do {
1829 status |=
1830 MT2063_ReadSub(pInfo->hUserData, pInfo->address,
1831 MT2063_REG_LO_STATUS,
1832 &pInfo->reg[MT2063_REG_LO_STATUS], 1);
1833
1834 if (MT2063_IS_ERROR(status))
1835 return (status);
1836
1837 if ((pInfo->reg[MT2063_REG_LO_STATUS] & (LO1LK | LO2LK)) ==
1838 (LO1LK | LO2LK)) {
1839 return (status);
1840 }
1841 MT2063_Sleep(pInfo->hUserData, nPollRate); /* Wait between retries */
1842 }
1843 while (++nDelays < nMaxLoops);
1844
1845 if ((pInfo->reg[MT2063_REG_LO_STATUS] & LO1LK) == 0x00)
1846 status |= MT2063_UPC_UNLOCK;
1847 if ((pInfo->reg[MT2063_REG_LO_STATUS] & LO2LK) == 0x00)
1848 status |= MT2063_DNC_UNLOCK;
1849
1850 return (status);
1851}
1852
1853/****************************************************************************
1854**
1855** Name: MT2063_GetParam
1856**
1857** Description: Gets a tuning algorithm parameter.
1858**
1859** This function provides access to the internals of the
1860** tuning algorithm - mostly for testing purposes.
1861**
1862** Parameters: h - Tuner handle (returned by MT2063_Open)
1863** param - Tuning algorithm parameter
1864** (see enum MT2063_Param)
1865** pValue - ptr to returned value
1866**
1867** param Description
1868** ---------------------- --------------------------------
1869** MT2063_IC_ADDR Serial Bus address of this tuner
1870** MT2063_MAX_OPEN Max # of MT2063's allowed open
1871** MT2063_NUM_OPEN # of MT2063's open
1872** MT2063_SRO_FREQ crystal frequency
1873** MT2063_STEPSIZE minimum tuning step size
1874** MT2063_INPUT_FREQ input center frequency
1875** MT2063_LO1_FREQ LO1 Frequency
1876** MT2063_LO1_STEPSIZE LO1 minimum step size
1877** MT2063_LO1_FRACN_AVOID LO1 FracN keep-out region
1878** MT2063_IF1_ACTUAL Current 1st IF in use
1879** MT2063_IF1_REQUEST Requested 1st IF
1880** MT2063_IF1_CENTER Center of 1st IF SAW filter
1881** MT2063_IF1_BW Bandwidth of 1st IF SAW filter
1882** MT2063_ZIF_BW zero-IF bandwidth
1883** MT2063_LO2_FREQ LO2 Frequency
1884** MT2063_LO2_STEPSIZE LO2 minimum step size
1885** MT2063_LO2_FRACN_AVOID LO2 FracN keep-out region
1886** MT2063_OUTPUT_FREQ output center frequency
1887** MT2063_OUTPUT_BW output bandwidth
1888** MT2063_LO_SEPARATION min inter-tuner LO separation
1889** MT2063_AS_ALG ID of avoid-spurs algorithm in use
1890** MT2063_MAX_HARM1 max # of intra-tuner harmonics
1891** MT2063_MAX_HARM2 max # of inter-tuner harmonics
1892** MT2063_EXCL_ZONES # of 1st IF exclusion zones
1893** MT2063_NUM_SPURS # of spurs found/avoided
1894** MT2063_SPUR_AVOIDED >0 spurs avoided
1895** MT2063_SPUR_PRESENT >0 spurs in output (mathematically)
1896** MT2063_RCVR_MODE Predefined modes.
1897** MT2063_ACLNA LNA attenuator gain code
1898** MT2063_ACRF RF attenuator gain code
1899** MT2063_ACFIF FIF attenuator gain code
1900** MT2063_ACLNA_MAX LNA attenuator limit
1901** MT2063_ACRF_MAX RF attenuator limit
1902** MT2063_ACFIF_MAX FIF attenuator limit
1903** MT2063_PD1 Actual value of PD1
1904** MT2063_PD2 Actual value of PD2
1905** MT2063_DNC_OUTPUT_ENABLE DNC output selection
1906** MT2063_VGAGC VGA gain code
1907** MT2063_VGAOI VGA output current
1908** MT2063_TAGC TAGC setting
1909** MT2063_AMPGC AMP gain code
1910** MT2063_AVOID_DECT Avoid DECT Frequencies
1911** MT2063_CTFILT_SW Cleartune filter selection
1912**
1913** Usage: status |= MT2063_GetParam(hMT2063,
1914** MT2063_IF1_ACTUAL,
1915** &f_IF1_Actual);
1916**
1917** Returns: status:
1918** MT_OK - No errors
1919** MT_INV_HANDLE - Invalid tuner handle
1920** MT_ARG_NULL - Null pointer argument passed
1921** MT_ARG_RANGE - Invalid parameter requested
1922**
1923** Dependencies: USERS MUST CALL MT2063_Open() FIRST!
1924**
1925** See Also: MT2063_SetParam, MT2063_Open
1926**
1927** Revision History:
1928**
1929** SCR Date Author Description
1930** -------------------------------------------------------------------------
1931** 138 06-19-2007 DAD Ver 1.00: Initial, derived from mt2067_b.
1932** 154 09-13-2007 RSK Ver 1.05: Get/SetParam changes for LOx_FREQ
1933** 10-31-2007 PINZ Ver 1.08: Get/SetParam add VGAGC, VGAOI, AMPGC, TAGC
1934** 173 M 01-23-2008 RSK Ver 1.12: Read LO1C and LO2C registers from HW
1935** in GetParam.
1936** 04-18-2008 PINZ Ver 1.15: Add SetParam LNARIN & PDxTGT
1937** Split SetParam up to ACLNA / ACLNA_MAX
1938** removed ACLNA_INRC/DECR (+RF & FIF)
1939** removed GCUAUTO / BYPATNDN/UP
1940** 175 I 16-06-2008 PINZ Ver 1.16: Add control to avoid US DECT freqs.
1941** 175 I 06-19-2008 RSK Ver 1.17: Refactor DECT control to SpurAvoid.
1942** 06-24-2008 PINZ Ver 1.18: Add Get/SetParam CTFILT_SW
1943**
1944****************************************************************************/
Mauro Carvalho Chehabcfde8922011-07-20 21:01:48 -03001945u32 MT2063_GetParam(void *h, enum MT2063_Param param, u32 * pValue)
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03001946{
Mauro Carvalho Chehabcfde8922011-07-20 21:01:48 -03001947 u32 status = MT2063_OK; /* Status to be returned */
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03001948 struct MT2063_Info_t *pInfo = (struct MT2063_Info_t *)h;
Mauro Carvalho Chehabcfde8922011-07-20 21:01:48 -03001949 u32 Div;
1950 u32 Num;
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03001951
1952 if (pValue == NULL)
1953 status |= MT2063_ARG_NULL;
1954
1955 /* Verify that the handle passed points to a valid tuner */
1956 if (MT2063_IsValidHandle(pInfo) == 0)
1957 status |= MT2063_INV_HANDLE;
1958
1959 if (MT2063_NO_ERROR(status)) {
1960 switch (param) {
1961 /* Serial Bus address of this tuner */
1962 case MT2063_IC_ADDR:
1963 *pValue = pInfo->address;
1964 break;
1965
1966 /* Max # of MT2063's allowed to be open */
1967 case MT2063_MAX_OPEN:
1968 *pValue = nMT2063MaxTuners;
1969 break;
1970
1971 /* # of MT2063's open */
1972 case MT2063_NUM_OPEN:
1973 *pValue = nMT2063OpenTuners;
1974 break;
1975
1976 /* crystal frequency */
1977 case MT2063_SRO_FREQ:
1978 *pValue = pInfo->AS_Data.f_ref;
1979 break;
1980
1981 /* minimum tuning step size */
1982 case MT2063_STEPSIZE:
1983 *pValue = pInfo->AS_Data.f_LO2_Step;
1984 break;
1985
1986 /* input center frequency */
1987 case MT2063_INPUT_FREQ:
1988 *pValue = pInfo->AS_Data.f_in;
1989 break;
1990
1991 /* LO1 Frequency */
1992 case MT2063_LO1_FREQ:
1993 {
1994 /* read the actual tuner register values for LO1C_1 and LO1C_2 */
1995 status |=
1996 MT2063_ReadSub(pInfo->hUserData,
1997 pInfo->address,
1998 MT2063_REG_LO1C_1,
1999 &pInfo->
2000 reg[MT2063_REG_LO1C_1], 2);
2001 Div = pInfo->reg[MT2063_REG_LO1C_1];
2002 Num = pInfo->reg[MT2063_REG_LO1C_2] & 0x3F;
2003 pInfo->AS_Data.f_LO1 =
2004 (pInfo->AS_Data.f_ref * Div) +
2005 MT2063_fLO_FractionalTerm(pInfo->AS_Data.
2006 f_ref, Num, 64);
2007 }
2008 *pValue = pInfo->AS_Data.f_LO1;
2009 break;
2010
2011 /* LO1 minimum step size */
2012 case MT2063_LO1_STEPSIZE:
2013 *pValue = pInfo->AS_Data.f_LO1_Step;
2014 break;
2015
2016 /* LO1 FracN keep-out region */
2017 case MT2063_LO1_FRACN_AVOID_PARAM:
2018 *pValue = pInfo->AS_Data.f_LO1_FracN_Avoid;
2019 break;
2020
2021 /* Current 1st IF in use */
2022 case MT2063_IF1_ACTUAL:
2023 *pValue = pInfo->f_IF1_actual;
2024 break;
2025
2026 /* Requested 1st IF */
2027 case MT2063_IF1_REQUEST:
2028 *pValue = pInfo->AS_Data.f_if1_Request;
2029 break;
2030
2031 /* Center of 1st IF SAW filter */
2032 case MT2063_IF1_CENTER:
2033 *pValue = pInfo->AS_Data.f_if1_Center;
2034 break;
2035
2036 /* Bandwidth of 1st IF SAW filter */
2037 case MT2063_IF1_BW:
2038 *pValue = pInfo->AS_Data.f_if1_bw;
2039 break;
2040
2041 /* zero-IF bandwidth */
2042 case MT2063_ZIF_BW:
2043 *pValue = pInfo->AS_Data.f_zif_bw;
2044 break;
2045
2046 /* LO2 Frequency */
2047 case MT2063_LO2_FREQ:
2048 {
2049 /* Read the actual tuner register values for LO2C_1, LO2C_2 and LO2C_3 */
2050 status |=
2051 MT2063_ReadSub(pInfo->hUserData,
2052 pInfo->address,
2053 MT2063_REG_LO2C_1,
2054 &pInfo->
2055 reg[MT2063_REG_LO2C_1], 3);
2056 Div =
2057 (pInfo->reg[MT2063_REG_LO2C_1] & 0xFE) >> 1;
2058 Num =
2059 ((pInfo->
2060 reg[MT2063_REG_LO2C_1] & 0x01) << 12) |
2061 (pInfo->
2062 reg[MT2063_REG_LO2C_2] << 4) | (pInfo->
2063 reg
2064 [MT2063_REG_LO2C_3]
2065 & 0x00F);
2066 pInfo->AS_Data.f_LO2 =
2067 (pInfo->AS_Data.f_ref * Div) +
2068 MT2063_fLO_FractionalTerm(pInfo->AS_Data.
2069 f_ref, Num, 8191);
2070 }
2071 *pValue = pInfo->AS_Data.f_LO2;
2072 break;
2073
2074 /* LO2 minimum step size */
2075 case MT2063_LO2_STEPSIZE:
2076 *pValue = pInfo->AS_Data.f_LO2_Step;
2077 break;
2078
2079 /* LO2 FracN keep-out region */
2080 case MT2063_LO2_FRACN_AVOID:
2081 *pValue = pInfo->AS_Data.f_LO2_FracN_Avoid;
2082 break;
2083
2084 /* output center frequency */
2085 case MT2063_OUTPUT_FREQ:
2086 *pValue = pInfo->AS_Data.f_out;
2087 break;
2088
2089 /* output bandwidth */
2090 case MT2063_OUTPUT_BW:
2091 *pValue = pInfo->AS_Data.f_out_bw - 750000;
2092 break;
2093
2094 /* min inter-tuner LO separation */
2095 case MT2063_LO_SEPARATION:
2096 *pValue = pInfo->AS_Data.f_min_LO_Separation;
2097 break;
2098
2099 /* ID of avoid-spurs algorithm in use */
2100 case MT2063_AS_ALG:
2101 *pValue = pInfo->AS_Data.nAS_Algorithm;
2102 break;
2103
2104 /* max # of intra-tuner harmonics */
2105 case MT2063_MAX_HARM1:
2106 *pValue = pInfo->AS_Data.maxH1;
2107 break;
2108
2109 /* max # of inter-tuner harmonics */
2110 case MT2063_MAX_HARM2:
2111 *pValue = pInfo->AS_Data.maxH2;
2112 break;
2113
2114 /* # of 1st IF exclusion zones */
2115 case MT2063_EXCL_ZONES:
2116 *pValue = pInfo->AS_Data.nZones;
2117 break;
2118
2119 /* # of spurs found/avoided */
2120 case MT2063_NUM_SPURS:
2121 *pValue = pInfo->AS_Data.nSpursFound;
2122 break;
2123
2124 /* >0 spurs avoided */
2125 case MT2063_SPUR_AVOIDED:
2126 *pValue = pInfo->AS_Data.bSpurAvoided;
2127 break;
2128
2129 /* >0 spurs in output (mathematically) */
2130 case MT2063_SPUR_PRESENT:
2131 *pValue = pInfo->AS_Data.bSpurPresent;
2132 break;
2133
2134 /* Predefined receiver setup combination */
2135 case MT2063_RCVR_MODE:
2136 *pValue = pInfo->rcvr_mode;
2137 break;
2138
2139 case MT2063_PD1:
2140 case MT2063_PD2:
2141 {
Mauro Carvalho Chehabcfde8922011-07-20 21:01:48 -03002142 u8 mask = (param == MT2063_PD1 ? 0x01 : 0x03); /* PD1 vs PD2 */
2143 u8 orig = (pInfo->reg[MT2063_REG_BYP_CTRL]);
2144 u8 reg = (orig & 0xF1) | mask; /* Only set 3 bits (not 5) */
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03002145 int i;
2146
2147 *pValue = 0;
2148
2149 /* Initiate ADC output to reg 0x0A */
2150 if (reg != orig)
2151 status |=
2152 MT2063_WriteSub(pInfo->hUserData,
2153 pInfo->address,
2154 MT2063_REG_BYP_CTRL,
2155 &reg, 1);
2156
2157 if (MT2063_IS_ERROR(status))
2158 return (status);
2159
2160 for (i = 0; i < 8; i++) {
2161 status |=
2162 MT2063_ReadSub(pInfo->hUserData,
2163 pInfo->address,
2164 MT2063_REG_ADC_OUT,
2165 &pInfo->
2166 reg
2167 [MT2063_REG_ADC_OUT],
2168 1);
2169
2170 if (MT2063_NO_ERROR(status))
2171 *pValue +=
2172 pInfo->
2173 reg[MT2063_REG_ADC_OUT];
2174 else {
2175 if (i)
2176 *pValue /= i;
2177 return (status);
2178 }
2179 }
2180 *pValue /= 8; /* divide by number of reads */
2181 *pValue >>= 2; /* only want 6 MSB's out of 8 */
2182
2183 /* Restore value of Register BYP_CTRL */
2184 if (reg != orig)
2185 status |=
2186 MT2063_WriteSub(pInfo->hUserData,
2187 pInfo->address,
2188 MT2063_REG_BYP_CTRL,
2189 &orig, 1);
2190 }
2191 break;
2192
2193 /* Get LNA attenuator code */
2194 case MT2063_ACLNA:
2195 {
Mauro Carvalho Chehabcfde8922011-07-20 21:01:48 -03002196 u8 val;
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03002197 status |=
2198 MT2063_GetReg(pInfo, MT2063_REG_XO_STATUS,
2199 &val);
2200 *pValue = val & 0x1f;
2201 }
2202 break;
2203
2204 /* Get RF attenuator code */
2205 case MT2063_ACRF:
2206 {
Mauro Carvalho Chehabcfde8922011-07-20 21:01:48 -03002207 u8 val;
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03002208 status |=
2209 MT2063_GetReg(pInfo, MT2063_REG_RF_STATUS,
2210 &val);
2211 *pValue = val & 0x1f;
2212 }
2213 break;
2214
2215 /* Get FIF attenuator code */
2216 case MT2063_ACFIF:
2217 {
Mauro Carvalho Chehabcfde8922011-07-20 21:01:48 -03002218 u8 val;
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03002219 status |=
2220 MT2063_GetReg(pInfo, MT2063_REG_FIF_STATUS,
2221 &val);
2222 *pValue = val & 0x1f;
2223 }
2224 break;
2225
2226 /* Get LNA attenuator limit */
2227 case MT2063_ACLNA_MAX:
2228 {
Mauro Carvalho Chehabcfde8922011-07-20 21:01:48 -03002229 u8 val;
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03002230 status |=
2231 MT2063_GetReg(pInfo, MT2063_REG_LNA_OV,
2232 &val);
2233 *pValue = val & 0x1f;
2234 }
2235 break;
2236
2237 /* Get RF attenuator limit */
2238 case MT2063_ACRF_MAX:
2239 {
Mauro Carvalho Chehabcfde8922011-07-20 21:01:48 -03002240 u8 val;
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03002241 status |=
2242 MT2063_GetReg(pInfo, MT2063_REG_RF_OV,
2243 &val);
2244 *pValue = val & 0x1f;
2245 }
2246 break;
2247
2248 /* Get FIF attenuator limit */
2249 case MT2063_ACFIF_MAX:
2250 {
Mauro Carvalho Chehabcfde8922011-07-20 21:01:48 -03002251 u8 val;
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03002252 status |=
2253 MT2063_GetReg(pInfo, MT2063_REG_FIF_OV,
2254 &val);
2255 *pValue = val & 0x1f;
2256 }
2257 break;
2258
2259 /* Get current used DNC output */
2260 case MT2063_DNC_OUTPUT_ENABLE:
2261 {
2262 if ((pInfo->reg[MT2063_REG_DNC_GAIN] & 0x03) == 0x03) { /* if DNC1 is off */
2263 if ((pInfo->reg[MT2063_REG_VGA_GAIN] & 0x03) == 0x03) /* if DNC2 is off */
2264 *pValue =
Mauro Carvalho Chehabcfde8922011-07-20 21:01:48 -03002265 (u32) MT2063_DNC_NONE;
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03002266 else
2267 *pValue =
Mauro Carvalho Chehabcfde8922011-07-20 21:01:48 -03002268 (u32) MT2063_DNC_2;
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03002269 } else { /* DNC1 is on */
2270
2271 if ((pInfo->reg[MT2063_REG_VGA_GAIN] & 0x03) == 0x03) /* if DNC2 is off */
2272 *pValue =
Mauro Carvalho Chehabcfde8922011-07-20 21:01:48 -03002273 (u32) MT2063_DNC_1;
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03002274 else
2275 *pValue =
Mauro Carvalho Chehabcfde8922011-07-20 21:01:48 -03002276 (u32) MT2063_DNC_BOTH;
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03002277 }
2278 }
2279 break;
2280
2281 /* Get VGA Gain Code */
2282 case MT2063_VGAGC:
2283 *pValue =
2284 ((pInfo->reg[MT2063_REG_VGA_GAIN] & 0x0C) >> 2);
2285 break;
2286
2287 /* Get VGA bias current */
2288 case MT2063_VGAOI:
2289 *pValue = (pInfo->reg[MT2063_REG_RSVD_31] & 0x07);
2290 break;
2291
2292 /* Get TAGC setting */
2293 case MT2063_TAGC:
2294 *pValue = (pInfo->reg[MT2063_REG_RSVD_1E] & 0x03);
2295 break;
2296
2297 /* Get AMP Gain Code */
2298 case MT2063_AMPGC:
2299 *pValue = (pInfo->reg[MT2063_REG_TEMP_SEL] & 0x03);
2300 break;
2301
2302 /* Avoid DECT Frequencies */
2303 case MT2063_AVOID_DECT:
2304 *pValue = pInfo->AS_Data.avoidDECT;
2305 break;
2306
2307 /* Cleartune filter selection: 0 - by IC (default), 1 - by software */
2308 case MT2063_CTFILT_SW:
2309 *pValue = pInfo->ctfilt_sw;
2310 break;
2311
2312 case MT2063_EOP:
2313 default:
2314 status |= MT2063_ARG_RANGE;
2315 }
2316 }
2317 return (status);
2318}
2319
2320/****************************************************************************
2321**
2322** Name: MT2063_GetReg
2323**
2324** Description: Gets an MT2063 register.
2325**
2326** Parameters: h - Tuner handle (returned by MT2063_Open)
2327** reg - MT2063 register/subaddress location
2328** *val - MT2063 register/subaddress value
2329**
2330** Returns: status:
2331** MT_OK - No errors
2332** MT_COMM_ERR - Serial bus communications error
2333** MT_INV_HANDLE - Invalid tuner handle
2334** MT_ARG_NULL - Null pointer argument passed
2335** MT_ARG_RANGE - Argument out of range
2336**
2337** Dependencies: USERS MUST CALL MT2063_Open() FIRST!
2338**
2339** Use this function if you need to read a register from
2340** the MT2063.
2341**
2342** Revision History:
2343**
2344** SCR Date Author Description
2345** -------------------------------------------------------------------------
2346** 138 06-19-2007 DAD Ver 1.00: Initial, derived from mt2067_b.
2347**
2348****************************************************************************/
Mauro Carvalho Chehabcfde8922011-07-20 21:01:48 -03002349u32 MT2063_GetReg(void *h, u8 reg, u8 * val)
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03002350{
Mauro Carvalho Chehabcfde8922011-07-20 21:01:48 -03002351 u32 status = MT2063_OK; /* Status to be returned */
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03002352 struct MT2063_Info_t *pInfo = (struct MT2063_Info_t *)h;
2353
2354 /* Verify that the handle passed points to a valid tuner */
2355 if (MT2063_IsValidHandle(pInfo) == 0)
2356 status |= MT2063_INV_HANDLE;
2357
2358 if (val == NULL)
2359 status |= MT2063_ARG_NULL;
2360
2361 if (reg >= MT2063_REG_END_REGS)
2362 status |= MT2063_ARG_RANGE;
2363
2364 if (MT2063_NO_ERROR(status)) {
2365 status |=
2366 MT2063_ReadSub(pInfo->hUserData, pInfo->address, reg,
2367 &pInfo->reg[reg], 1);
2368 if (MT2063_NO_ERROR(status))
2369 *val = pInfo->reg[reg];
2370 }
2371
2372 return (status);
2373}
2374
2375/******************************************************************************
2376**
2377** Name: MT2063_GetTemp
2378**
2379** Description: Get the MT2063 Temperature register.
2380**
2381** Parameters: h - Open handle to the tuner (from MT2063_Open).
2382** *value - value read from the register
2383**
2384** Binary
2385** Value Returned Value Approx Temp
2386** ---------------------------------------------
2387** MT2063_T_0C 0000 0C
2388** MT2063_T_10C 0001 10C
2389** MT2063_T_20C 0010 20C
2390** MT2063_T_30C 0011 30C
2391** MT2063_T_40C 0100 40C
2392** MT2063_T_50C 0101 50C
2393** MT2063_T_60C 0110 60C
2394** MT2063_T_70C 0111 70C
2395** MT2063_T_80C 1000 80C
2396** MT2063_T_90C 1001 90C
2397** MT2063_T_100C 1010 100C
2398** MT2063_T_110C 1011 110C
2399** MT2063_T_120C 1100 120C
2400** MT2063_T_130C 1101 130C
2401** MT2063_T_140C 1110 140C
2402** MT2063_T_150C 1111 150C
2403**
2404** Returns: status:
2405** MT_OK - No errors
2406** MT_COMM_ERR - Serial bus communications error
2407** MT_INV_HANDLE - Invalid tuner handle
2408** MT_ARG_NULL - Null pointer argument passed
2409** MT_ARG_RANGE - Argument out of range
2410**
2411** Dependencies: MT_ReadSub - Read byte(s) of data from the two-wire bus
2412** MT_WriteSub - Write byte(s) of data to the two-wire bus
2413**
2414** Revision History:
2415**
2416** SCR Date Author Description
2417** -------------------------------------------------------------------------
2418** 138 06-19-2007 DAD Ver 1.00: Initial, derived from mt2067_b.
2419**
2420******************************************************************************/
Mauro Carvalho Chehabcfde8922011-07-20 21:01:48 -03002421u32 MT2063_GetTemp(void *h, enum MT2063_Temperature * value)
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03002422{
Mauro Carvalho Chehabcfde8922011-07-20 21:01:48 -03002423 u32 status = MT2063_OK; /* Status to be returned */
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03002424 struct MT2063_Info_t *pInfo = (struct MT2063_Info_t *)h;
2425
2426 if (MT2063_IsValidHandle(pInfo) == 0)
2427 return MT2063_INV_HANDLE;
2428
2429 if (value == NULL)
2430 return MT2063_ARG_NULL;
2431
2432 if ((MT2063_NO_ERROR(status))
2433 && ((pInfo->reg[MT2063_REG_TEMP_SEL] & 0xE0) != 0x00)) {
2434 pInfo->reg[MT2063_REG_TEMP_SEL] &= (0x1F);
2435 status |= MT2063_WriteSub(pInfo->hUserData,
2436 pInfo->address,
2437 MT2063_REG_TEMP_SEL,
2438 &pInfo->reg[MT2063_REG_TEMP_SEL], 1);
2439 }
2440
2441 if (MT2063_NO_ERROR(status))
2442 status |= MT2063_ReadSub(pInfo->hUserData,
2443 pInfo->address,
2444 MT2063_REG_TEMP_STATUS,
2445 &pInfo->reg[MT2063_REG_TEMP_STATUS],
2446 1);
2447
2448 if (MT2063_NO_ERROR(status))
2449 *value =
2450 (enum MT2063_Temperature)(pInfo->
2451 reg[MT2063_REG_TEMP_STATUS] >> 4);
2452
2453 return (status);
2454}
2455
2456/****************************************************************************
2457**
2458** Name: MT2063_GetUserData
2459**
2460** Description: Gets the user-defined data item.
2461**
2462** Parameters: h - Tuner handle (returned by MT2063_Open)
2463**
2464** Returns: status:
2465** MT_OK - No errors
2466** MT_INV_HANDLE - Invalid tuner handle
2467** MT_ARG_NULL - Null pointer argument passed
2468**
2469** Dependencies: USERS MUST CALL MT2063_Open() FIRST!
2470**
2471** The hUserData parameter is a user-specific argument
2472** that is stored internally with the other tuner-
2473** specific information.
2474**
2475** For example, if additional arguments are needed
2476** for the user to identify the device communicating
2477** with the tuner, this argument can be used to supply
2478** the necessary information.
2479**
2480** The hUserData parameter is initialized in the tuner's
2481** Open function to NULL.
2482**
2483** See Also: MT2063_Open
2484**
2485** Revision History:
2486**
2487** SCR Date Author Description
2488** -------------------------------------------------------------------------
2489** 138 06-19-2007 DAD Ver 1.00: Initial, derived from mt2067_b.
2490**
2491****************************************************************************/
Mauro Carvalho Chehabcfde8922011-07-20 21:01:48 -03002492u32 MT2063_GetUserData(void *h, void ** hUserData)
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03002493{
Mauro Carvalho Chehabcfde8922011-07-20 21:01:48 -03002494 u32 status = MT2063_OK; /* Status to be returned */
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03002495 struct MT2063_Info_t *pInfo = (struct MT2063_Info_t *)h;
2496
2497 /* Verify that the handle passed points to a valid tuner */
2498 if (MT2063_IsValidHandle(pInfo) == 0)
2499 status = MT2063_INV_HANDLE;
2500
2501 if (hUserData == NULL)
2502 status |= MT2063_ARG_NULL;
2503
2504 if (MT2063_NO_ERROR(status))
2505 *hUserData = pInfo->hUserData;
2506
2507 return (status);
2508}
2509
2510/******************************************************************************
2511**
2512** Name: MT2063_SetReceiverMode
2513**
2514** Description: Set the MT2063 receiver mode
2515**
2516** --------------+----------------------------------------------
2517** Mode 0 : | MT2063_CABLE_QAM
2518** Mode 1 : | MT2063_CABLE_ANALOG
2519** Mode 2 : | MT2063_OFFAIR_COFDM
2520** Mode 3 : | MT2063_OFFAIR_COFDM_SAWLESS
2521** Mode 4 : | MT2063_OFFAIR_ANALOG
2522** Mode 5 : | MT2063_OFFAIR_8VSB
2523** --------------+----+----+----+----+-----+--------------------
2524** (DNC1GC & DNC2GC are the values, which are used, when the specific
2525** DNC Output is selected, the other is always off)
2526**
2527** |<---------- Mode -------------->|
2528** Reg Field | 0 | 1 | 2 | 3 | 4 | 5 |
2529** ------------+-----+-----+-----+-----+-----+-----+
2530** RFAGCen | OFF | OFF | OFF | OFF | OFF | OFF
2531** LNARin | 0 | 0 | 3 | 3 | 3 | 3
2532** FIFFQen | 1 | 1 | 1 | 1 | 1 | 1
2533** FIFFq | 0 | 0 | 0 | 0 | 0 | 0
2534** DNC1gc | 0 | 0 | 0 | 0 | 0 | 0
2535** DNC2gc | 0 | 0 | 0 | 0 | 0 | 0
2536** GCU Auto | 1 | 1 | 1 | 1 | 1 | 1
2537** LNA max Atn | 31 | 31 | 31 | 31 | 31 | 31
2538** LNA Target | 44 | 43 | 43 | 43 | 43 | 43
2539** ign RF Ovl | 0 | 0 | 0 | 0 | 0 | 0
2540** RF max Atn | 31 | 31 | 31 | 31 | 31 | 31
2541** PD1 Target | 36 | 36 | 38 | 38 | 36 | 38
2542** ign FIF Ovl | 0 | 0 | 0 | 0 | 0 | 0
2543** FIF max Atn | 5 | 5 | 5 | 5 | 5 | 5
2544** PD2 Target | 40 | 33 | 42 | 42 | 33 | 42
2545**
2546**
2547** Parameters: pInfo - ptr to MT2063_Info_t structure
2548** Mode - desired reciever mode
2549**
2550** Usage: status = MT2063_SetReceiverMode(hMT2063, Mode);
2551**
2552** Returns: status:
2553** MT_OK - No errors
2554** MT_COMM_ERR - Serial bus communications error
2555**
2556** Dependencies: MT2063_SetReg - Write a byte of data to a HW register.
2557** Assumes that the tuner cache is valid.
2558**
2559** Revision History:
2560**
2561** SCR Date Author Description
2562** -------------------------------------------------------------------------
2563** 138 06-19-2007 DAD Ver 1.00: Initial, derived from mt2067_b.
2564** N/A 01-10-2007 PINZ Added additional GCU Settings, FIFF Calib will be triggered
2565** 155 10-01-2007 DAD Ver 1.06: Add receiver mode for SECAM positive
2566** modulation
2567** (MT2063_ANALOG_TV_POS_NO_RFAGC_MODE)
2568** N/A 10-22-2007 PINZ Ver 1.07: Changed some Registers at init to have
2569** the same settings as with MT Launcher
2570** N/A 10-30-2007 PINZ Add SetParam VGAGC & VGAOI
2571** Add SetParam DNC_OUTPUT_ENABLE
2572** Removed VGAGC from receiver mode,
2573** default now 1
2574** N/A 10-31-2007 PINZ Ver 1.08: Add SetParam TAGC, removed from rcvr-mode
2575** Add SetParam AMPGC, removed from rcvr-mode
2576** Corrected names of GCU values
2577** reorganized receiver modes, removed,
2578** (MT2063_ANALOG_TV_POS_NO_RFAGC_MODE)
2579** Actualized Receiver-Mode values
2580** N/A 11-12-2007 PINZ Ver 1.09: Actualized Receiver-Mode values
2581** N/A 11-27-2007 PINZ Improved buffered writing
2582** 01-03-2008 PINZ Ver 1.10: Added a trigger of BYPATNUP for
2583** correct wakeup of the LNA after shutdown
2584** Set AFCsd = 1 as default
2585** Changed CAP1sel default
2586** 01-14-2008 PINZ Ver 1.11: Updated gain settings
2587** 04-18-2008 PINZ Ver 1.15: Add SetParam LNARIN & PDxTGT
2588** Split SetParam up to ACLNA / ACLNA_MAX
2589** removed ACLNA_INRC/DECR (+RF & FIF)
2590** removed GCUAUTO / BYPATNDN/UP
2591**
2592******************************************************************************/
Mauro Carvalho Chehabcfde8922011-07-20 21:01:48 -03002593static u32 MT2063_SetReceiverMode(struct MT2063_Info_t *pInfo,
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03002594 enum MT2063_RCVR_MODES Mode)
2595{
Mauro Carvalho Chehabcfde8922011-07-20 21:01:48 -03002596 u32 status = MT2063_OK; /* Status to be returned */
2597 u8 val;
2598 u32 longval;
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03002599
2600 if (Mode >= MT2063_NUM_RCVR_MODES)
2601 status = MT2063_ARG_RANGE;
2602
2603 /* RFAGCen */
2604 if (MT2063_NO_ERROR(status)) {
2605 val =
2606 (pInfo->
Mauro Carvalho Chehabcfde8922011-07-20 21:01:48 -03002607 reg[MT2063_REG_PD1_TGT] & (u8) ~ 0x40) | (RFAGCEN[Mode]
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03002608 ? 0x40 :
2609 0x00);
2610 if (pInfo->reg[MT2063_REG_PD1_TGT] != val) {
2611 status |= MT2063_SetReg(pInfo, MT2063_REG_PD1_TGT, val);
2612 }
2613 }
2614
2615 /* LNARin */
2616 if (MT2063_NO_ERROR(status)) {
2617 status |= MT2063_SetParam(pInfo, MT2063_LNA_RIN, LNARIN[Mode]);
2618 }
2619
2620 /* FIFFQEN and FIFFQ */
2621 if (MT2063_NO_ERROR(status)) {
2622 val =
2623 (pInfo->
Mauro Carvalho Chehabcfde8922011-07-20 21:01:48 -03002624 reg[MT2063_REG_FIFF_CTRL2] & (u8) ~ 0xF0) |
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03002625 (FIFFQEN[Mode] << 7) | (FIFFQ[Mode] << 4);
2626 if (pInfo->reg[MT2063_REG_FIFF_CTRL2] != val) {
2627 status |=
2628 MT2063_SetReg(pInfo, MT2063_REG_FIFF_CTRL2, val);
2629 /* trigger FIFF calibration, needed after changing FIFFQ */
2630 val =
Mauro Carvalho Chehabcfde8922011-07-20 21:01:48 -03002631 (pInfo->reg[MT2063_REG_FIFF_CTRL] | (u8) 0x01);
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03002632 status |=
2633 MT2063_SetReg(pInfo, MT2063_REG_FIFF_CTRL, val);
2634 val =
2635 (pInfo->
Mauro Carvalho Chehabcfde8922011-07-20 21:01:48 -03002636 reg[MT2063_REG_FIFF_CTRL] & (u8) ~ 0x01);
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03002637 status |=
2638 MT2063_SetReg(pInfo, MT2063_REG_FIFF_CTRL, val);
2639 }
2640 }
2641
2642 /* DNC1GC & DNC2GC */
2643 status |= MT2063_GetParam(pInfo, MT2063_DNC_OUTPUT_ENABLE, &longval);
2644 status |= MT2063_SetParam(pInfo, MT2063_DNC_OUTPUT_ENABLE, longval);
2645
2646 /* acLNAmax */
2647 if (MT2063_NO_ERROR(status)) {
2648 status |=
2649 MT2063_SetParam(pInfo, MT2063_ACLNA_MAX, ACLNAMAX[Mode]);
2650 }
2651
2652 /* LNATGT */
2653 if (MT2063_NO_ERROR(status)) {
2654 status |= MT2063_SetParam(pInfo, MT2063_LNA_TGT, LNATGT[Mode]);
2655 }
2656
2657 /* ACRF */
2658 if (MT2063_NO_ERROR(status)) {
2659 status |=
2660 MT2063_SetParam(pInfo, MT2063_ACRF_MAX, ACRFMAX[Mode]);
2661 }
2662
2663 /* PD1TGT */
2664 if (MT2063_NO_ERROR(status)) {
2665 status |= MT2063_SetParam(pInfo, MT2063_PD1_TGT, PD1TGT[Mode]);
2666 }
2667
2668 /* FIFATN */
2669 if (MT2063_NO_ERROR(status)) {
2670 status |=
2671 MT2063_SetParam(pInfo, MT2063_ACFIF_MAX, ACFIFMAX[Mode]);
2672 }
2673
2674 /* PD2TGT */
2675 if (MT2063_NO_ERROR(status)) {
2676 status |= MT2063_SetParam(pInfo, MT2063_PD2_TGT, PD2TGT[Mode]);
2677 }
2678
2679 /* Ignore ATN Overload */
2680 if (MT2063_NO_ERROR(status)) {
2681 val =
2682 (pInfo->
Mauro Carvalho Chehabcfde8922011-07-20 21:01:48 -03002683 reg[MT2063_REG_LNA_TGT] & (u8) ~ 0x80) | (RFOVDIS[Mode]
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03002684 ? 0x80 :
2685 0x00);
2686 if (pInfo->reg[MT2063_REG_LNA_TGT] != val) {
2687 status |= MT2063_SetReg(pInfo, MT2063_REG_LNA_TGT, val);
2688 }
2689 }
2690
2691 /* Ignore FIF Overload */
2692 if (MT2063_NO_ERROR(status)) {
2693 val =
2694 (pInfo->
Mauro Carvalho Chehabcfde8922011-07-20 21:01:48 -03002695 reg[MT2063_REG_PD1_TGT] & (u8) ~ 0x80) |
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03002696 (FIFOVDIS[Mode] ? 0x80 : 0x00);
2697 if (pInfo->reg[MT2063_REG_PD1_TGT] != val) {
2698 status |= MT2063_SetReg(pInfo, MT2063_REG_PD1_TGT, val);
2699 }
2700 }
2701
2702 if (MT2063_NO_ERROR(status))
2703 pInfo->rcvr_mode = Mode;
2704
2705 return (status);
2706}
2707
2708/******************************************************************************
2709**
2710** Name: MT2063_ReInit
2711**
2712** Description: Initialize the tuner's register values.
2713**
2714** Parameters: h - Tuner handle (returned by MT2063_Open)
2715**
2716** Returns: status:
2717** MT_OK - No errors
2718** MT_TUNER_ID_ERR - Tuner Part/Rev code mismatch
2719** MT_INV_HANDLE - Invalid tuner handle
2720** MT_COMM_ERR - Serial bus communications error
2721**
2722** Dependencies: MT_ReadSub - Read byte(s) of data from the two-wire bus
2723** MT_WriteSub - Write byte(s) of data to the two-wire bus
2724**
2725** Revision History:
2726**
2727** SCR Date Author Description
2728** -------------------------------------------------------------------------
2729** 138 06-19-2007 DAD Ver 1.00: Initial, derived from mt2067_b.
2730** 148 09-04-2007 RSK Ver 1.02: Corrected logic of Reg 3B Reference
2731** 153 09-07-2007 RSK Ver 1.03: Lock Time improvements
2732** N/A 10-31-2007 PINZ Ver 1.08: Changed values suitable to rcvr-mode 0
2733** N/A 11-12-2007 PINZ Ver 1.09: Changed values suitable to rcvr-mode 0
2734** N/A 01-03-2007 PINZ Ver 1.10: Added AFCsd = 1 into defaults
2735** N/A 01-04-2007 PINZ Ver 1.10: Changed CAP1sel default
2736** 01-14-2008 PINZ Ver 1.11: Updated gain settings
2737** 03-18-2008 PINZ Ver 1.13: Added Support for B3
2738** 175 I 06-19-2008 RSK Ver 1.17: Refactor DECT control to SpurAvoid.
2739** 06-24-2008 PINZ Ver 1.18: Add Get/SetParam CTFILT_SW
2740**
2741******************************************************************************/
Mauro Carvalho Chehabcfde8922011-07-20 21:01:48 -03002742u32 MT2063_ReInit(void *h)
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03002743{
Mauro Carvalho Chehabcfde8922011-07-20 21:01:48 -03002744 u8 all_resets = 0xF0; /* reset/load bits */
2745 u32 status = MT2063_OK; /* Status to be returned */
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03002746 struct MT2063_Info_t *pInfo = (struct MT2063_Info_t *)h;
Mauro Carvalho Chehabcfde8922011-07-20 21:01:48 -03002747 u8 *def;
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03002748
Mauro Carvalho Chehabcfde8922011-07-20 21:01:48 -03002749 u8 MT2063B0_defaults[] = { /* Reg, Value */
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03002750 0x19, 0x05,
2751 0x1B, 0x1D,
2752 0x1C, 0x1F,
2753 0x1D, 0x0F,
2754 0x1E, 0x3F,
2755 0x1F, 0x0F,
2756 0x20, 0x3F,
2757 0x22, 0x21,
2758 0x23, 0x3F,
2759 0x24, 0x20,
2760 0x25, 0x3F,
2761 0x27, 0xEE,
2762 0x2C, 0x27, /* bit at 0x20 is cleared below */
2763 0x30, 0x03,
2764 0x2C, 0x07, /* bit at 0x20 is cleared here */
2765 0x2D, 0x87,
2766 0x2E, 0xAA,
2767 0x28, 0xE1, /* Set the FIFCrst bit here */
2768 0x28, 0xE0, /* Clear the FIFCrst bit here */
2769 0x00
2770 };
2771
2772 /* writing 0x05 0xf0 sw-resets all registers, so we write only needed changes */
Mauro Carvalho Chehabcfde8922011-07-20 21:01:48 -03002773 u8 MT2063B1_defaults[] = { /* Reg, Value */
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03002774 0x05, 0xF0,
2775 0x11, 0x10, /* New Enable AFCsd */
2776 0x19, 0x05,
2777 0x1A, 0x6C,
2778 0x1B, 0x24,
2779 0x1C, 0x28,
2780 0x1D, 0x8F,
2781 0x1E, 0x14,
2782 0x1F, 0x8F,
2783 0x20, 0x57,
2784 0x22, 0x21, /* New - ver 1.03 */
2785 0x23, 0x3C, /* New - ver 1.10 */
2786 0x24, 0x20, /* New - ver 1.03 */
2787 0x2C, 0x24, /* bit at 0x20 is cleared below */
2788 0x2D, 0x87, /* FIFFQ=0 */
2789 0x2F, 0xF3,
2790 0x30, 0x0C, /* New - ver 1.11 */
2791 0x31, 0x1B, /* New - ver 1.11 */
2792 0x2C, 0x04, /* bit at 0x20 is cleared here */
2793 0x28, 0xE1, /* Set the FIFCrst bit here */
2794 0x28, 0xE0, /* Clear the FIFCrst bit here */
2795 0x00
2796 };
2797
2798 /* writing 0x05 0xf0 sw-resets all registers, so we write only needed changes */
Mauro Carvalho Chehabcfde8922011-07-20 21:01:48 -03002799 u8 MT2063B3_defaults[] = { /* Reg, Value */
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03002800 0x05, 0xF0,
2801 0x19, 0x3D,
2802 0x2C, 0x24, /* bit at 0x20 is cleared below */
2803 0x2C, 0x04, /* bit at 0x20 is cleared here */
2804 0x28, 0xE1, /* Set the FIFCrst bit here */
2805 0x28, 0xE0, /* Clear the FIFCrst bit here */
2806 0x00
2807 };
2808
2809 /* Verify that the handle passed points to a valid tuner */
2810 if (MT2063_IsValidHandle(pInfo) == 0)
2811 status |= MT2063_INV_HANDLE;
2812
2813 /* Read the Part/Rev code from the tuner */
2814 if (MT2063_NO_ERROR(status)) {
2815 status |=
2816 MT2063_ReadSub(pInfo->hUserData, pInfo->address,
2817 MT2063_REG_PART_REV, pInfo->reg, 1);
2818 }
2819
2820 if (MT2063_NO_ERROR(status) /* Check the part/rev code */
2821 &&((pInfo->reg[MT2063_REG_PART_REV] != MT2063_B0) /* MT2063 B0 */
2822 &&(pInfo->reg[MT2063_REG_PART_REV] != MT2063_B1) /* MT2063 B1 */
2823 &&(pInfo->reg[MT2063_REG_PART_REV] != MT2063_B3))) /* MT2063 B3 */
2824 status |= MT2063_TUNER_ID_ERR; /* Wrong tuner Part/Rev code */
2825
2826 /* Read the Part/Rev code (2nd byte) from the tuner */
2827 if (MT2063_NO_ERROR(status))
2828 status |=
2829 MT2063_ReadSub(pInfo->hUserData, pInfo->address,
2830 MT2063_REG_RSVD_3B,
2831 &pInfo->reg[MT2063_REG_RSVD_3B], 1);
2832
2833 if (MT2063_NO_ERROR(status) /* Check the 2nd part/rev code */
2834 &&((pInfo->reg[MT2063_REG_RSVD_3B] & 0x80) != 0x00)) /* b7 != 0 ==> NOT MT2063 */
2835 status |= MT2063_TUNER_ID_ERR; /* Wrong tuner Part/Rev code */
2836
2837 /* Reset the tuner */
2838 if (MT2063_NO_ERROR(status))
2839 status |= MT2063_WriteSub(pInfo->hUserData,
2840 pInfo->address,
2841 MT2063_REG_LO2CQ_3, &all_resets, 1);
2842
2843 /* change all of the default values that vary from the HW reset values */
2844 /* def = (pInfo->reg[PART_REV] == MT2063_B0) ? MT2063B0_defaults : MT2063B1_defaults; */
2845 switch (pInfo->reg[MT2063_REG_PART_REV]) {
2846 case MT2063_B3:
2847 def = MT2063B3_defaults;
2848 break;
2849
2850 case MT2063_B1:
2851 def = MT2063B1_defaults;
2852 break;
2853
2854 case MT2063_B0:
2855 def = MT2063B0_defaults;
2856 break;
2857
2858 default:
2859 status |= MT2063_TUNER_ID_ERR;
2860 break;
2861 }
2862
2863 while (MT2063_NO_ERROR(status) && *def) {
Mauro Carvalho Chehabcfde8922011-07-20 21:01:48 -03002864 u8 reg = *def++;
2865 u8 val = *def++;
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03002866 status |=
2867 MT2063_WriteSub(pInfo->hUserData, pInfo->address, reg, &val,
2868 1);
2869 }
2870
2871 /* Wait for FIFF location to complete. */
2872 if (MT2063_NO_ERROR(status)) {
Mauro Carvalho Chehabcfde8922011-07-20 21:01:48 -03002873 u32 FCRUN = 1;
2874 s32 maxReads = 10;
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03002875 while (MT2063_NO_ERROR(status) && (FCRUN != 0)
2876 && (maxReads-- > 0)) {
2877 MT2063_Sleep(pInfo->hUserData, 2);
2878 status |= MT2063_ReadSub(pInfo->hUserData,
2879 pInfo->address,
2880 MT2063_REG_XO_STATUS,
2881 &pInfo->
2882 reg[MT2063_REG_XO_STATUS], 1);
2883 FCRUN = (pInfo->reg[MT2063_REG_XO_STATUS] & 0x40) >> 6;
2884 }
2885
2886 if (FCRUN != 0)
2887 status |= MT2063_TUNER_INIT_ERR | MT2063_TUNER_TIMEOUT;
2888
2889 if (MT2063_NO_ERROR(status)) /* Re-read FIFFC value */
2890 status |=
2891 MT2063_ReadSub(pInfo->hUserData, pInfo->address,
2892 MT2063_REG_FIFFC,
2893 &pInfo->reg[MT2063_REG_FIFFC], 1);
2894 }
2895
2896 /* Read back all the registers from the tuner */
2897 if (MT2063_NO_ERROR(status))
2898 status |= MT2063_ReadSub(pInfo->hUserData,
2899 pInfo->address,
2900 MT2063_REG_PART_REV,
2901 pInfo->reg, MT2063_REG_END_REGS);
2902
2903 if (MT2063_NO_ERROR(status)) {
2904 /* Initialize the tuner state. */
2905 pInfo->version = MT2063_VERSION;
2906 pInfo->tuner_id = pInfo->reg[MT2063_REG_PART_REV];
2907 pInfo->AS_Data.f_ref = MT2063_REF_FREQ;
2908 pInfo->AS_Data.f_if1_Center =
2909 (pInfo->AS_Data.f_ref / 8) *
Mauro Carvalho Chehabcfde8922011-07-20 21:01:48 -03002910 ((u32) pInfo->reg[MT2063_REG_FIFFC] + 640);
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03002911 pInfo->AS_Data.f_if1_bw = MT2063_IF1_BW;
2912 pInfo->AS_Data.f_out = 43750000UL;
2913 pInfo->AS_Data.f_out_bw = 6750000UL;
2914 pInfo->AS_Data.f_zif_bw = MT2063_ZIF_BW;
2915 pInfo->AS_Data.f_LO1_Step = pInfo->AS_Data.f_ref / 64;
2916 pInfo->AS_Data.f_LO2_Step = MT2063_TUNE_STEP_SIZE;
2917 pInfo->AS_Data.maxH1 = MT2063_MAX_HARMONICS_1;
2918 pInfo->AS_Data.maxH2 = MT2063_MAX_HARMONICS_2;
2919 pInfo->AS_Data.f_min_LO_Separation = MT2063_MIN_LO_SEP;
2920 pInfo->AS_Data.f_if1_Request = pInfo->AS_Data.f_if1_Center;
2921 pInfo->AS_Data.f_LO1 = 2181000000UL;
2922 pInfo->AS_Data.f_LO2 = 1486249786UL;
2923 pInfo->f_IF1_actual = pInfo->AS_Data.f_if1_Center;
2924 pInfo->AS_Data.f_in =
2925 pInfo->AS_Data.f_LO1 - pInfo->f_IF1_actual;
2926 pInfo->AS_Data.f_LO1_FracN_Avoid = MT2063_LO1_FRACN_AVOID;
2927 pInfo->AS_Data.f_LO2_FracN_Avoid = MT2063_LO2_FRACN_AVOID;
2928 pInfo->num_regs = MT2063_REG_END_REGS;
2929 pInfo->AS_Data.avoidDECT = MT2063_AVOID_BOTH;
2930 pInfo->ctfilt_sw = 0;
2931 }
2932
2933 if (MT2063_NO_ERROR(status)) {
2934 pInfo->CTFiltMax[0] = 69230000;
2935 pInfo->CTFiltMax[1] = 105770000;
2936 pInfo->CTFiltMax[2] = 140350000;
2937 pInfo->CTFiltMax[3] = 177110000;
2938 pInfo->CTFiltMax[4] = 212860000;
2939 pInfo->CTFiltMax[5] = 241130000;
2940 pInfo->CTFiltMax[6] = 274370000;
2941 pInfo->CTFiltMax[7] = 309820000;
2942 pInfo->CTFiltMax[8] = 342450000;
2943 pInfo->CTFiltMax[9] = 378870000;
2944 pInfo->CTFiltMax[10] = 416210000;
2945 pInfo->CTFiltMax[11] = 456500000;
2946 pInfo->CTFiltMax[12] = 495790000;
2947 pInfo->CTFiltMax[13] = 534530000;
2948 pInfo->CTFiltMax[14] = 572610000;
2949 pInfo->CTFiltMax[15] = 598970000;
2950 pInfo->CTFiltMax[16] = 635910000;
2951 pInfo->CTFiltMax[17] = 672130000;
2952 pInfo->CTFiltMax[18] = 714840000;
2953 pInfo->CTFiltMax[19] = 739660000;
2954 pInfo->CTFiltMax[20] = 770410000;
2955 pInfo->CTFiltMax[21] = 814660000;
2956 pInfo->CTFiltMax[22] = 846950000;
2957 pInfo->CTFiltMax[23] = 867820000;
2958 pInfo->CTFiltMax[24] = 915980000;
2959 pInfo->CTFiltMax[25] = 947450000;
2960 pInfo->CTFiltMax[26] = 983110000;
2961 pInfo->CTFiltMax[27] = 1021630000;
2962 pInfo->CTFiltMax[28] = 1061870000;
2963 pInfo->CTFiltMax[29] = 1098330000;
2964 pInfo->CTFiltMax[30] = 1138990000;
2965 }
2966
2967 /*
2968 ** Fetch the FCU osc value and use it and the fRef value to
2969 ** scale all of the Band Max values
2970 */
2971 if (MT2063_NO_ERROR(status)) {
Mauro Carvalho Chehabcfde8922011-07-20 21:01:48 -03002972 u32 fcu_osc;
2973 u32 i;
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03002974
2975 pInfo->reg[MT2063_REG_CTUNE_CTRL] = 0x0A;
2976 status |=
2977 MT2063_WriteSub(pInfo->hUserData, pInfo->address,
2978 MT2063_REG_CTUNE_CTRL,
2979 &pInfo->reg[MT2063_REG_CTUNE_CTRL], 1);
2980 /* Read the ClearTune filter calibration value */
2981 status |=
2982 MT2063_ReadSub(pInfo->hUserData, pInfo->address,
2983 MT2063_REG_FIFFC,
2984 &pInfo->reg[MT2063_REG_FIFFC], 1);
2985 fcu_osc = pInfo->reg[MT2063_REG_FIFFC];
2986
2987 pInfo->reg[MT2063_REG_CTUNE_CTRL] = 0x00;
2988 status |=
2989 MT2063_WriteSub(pInfo->hUserData, pInfo->address,
2990 MT2063_REG_CTUNE_CTRL,
2991 &pInfo->reg[MT2063_REG_CTUNE_CTRL], 1);
2992
2993 /* Adjust each of the values in the ClearTune filter cross-over table */
2994 for (i = 0; i < 31; i++) {
2995 pInfo->CTFiltMax[i] =
2996 (pInfo->CTFiltMax[i] / 768) * (fcu_osc + 640);
2997 }
2998 }
2999
3000 return (status);
3001}
3002
3003/******************************************************************************
3004**
3005** Name: MT2063_SetGPIO
3006**
3007** Description: Modify the MT2063 GPIO value.
3008**
3009** Parameters: h - Open handle to the tuner (from MT2063_Open).
3010** gpio_id - Selects GPIO0, GPIO1 or GPIO2
3011** attr - Selects input readback, I/O direction or
3012** output value
3013** value - value to set GPIO pin 15, 14 or 19
3014**
3015** Usage: status = MT2063_SetGPIO(hMT2063, MT2063_GPIO1, MT2063_GPIO_OUT, 1);
3016**
3017** Returns: status:
3018** MT_OK - No errors
3019** MT_COMM_ERR - Serial bus communications error
3020** MT_INV_HANDLE - Invalid tuner handle
3021**
3022** Dependencies: MT_WriteSub - Write byte(s) of data to the two-wire-bus
3023**
3024** Revision History:
3025**
3026** SCR Date Author Description
3027** -------------------------------------------------------------------------
3028** 138 06-19-2007 DAD Ver 1.00: Initial, derived from mt2067_b.
3029**
3030******************************************************************************/
Mauro Carvalho Chehabcfde8922011-07-20 21:01:48 -03003031u32 MT2063_SetGPIO(void *h, enum MT2063_GPIO_ID gpio_id,
3032 enum MT2063_GPIO_Attr attr, u32 value)
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03003033{
Mauro Carvalho Chehabcfde8922011-07-20 21:01:48 -03003034 u32 status = MT2063_OK; /* Status to be returned */
3035 u8 regno;
3036 s32 shift;
3037 static u8 GPIOreg[3] = { 0x15, 0x19, 0x18 };
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03003038 struct MT2063_Info_t *pInfo = (struct MT2063_Info_t *)h;
3039
3040 if (MT2063_IsValidHandle(pInfo) == 0)
3041 return MT2063_INV_HANDLE;
3042
3043 regno = GPIOreg[attr];
3044
3045 shift = (gpio_id - MT2063_GPIO0 + 5);
3046
3047 if (value & 0x01)
3048 pInfo->reg[regno] |= (0x01 << shift);
3049 else
3050 pInfo->reg[regno] &= ~(0x01 << shift);
3051 status =
3052 MT2063_WriteSub(pInfo->hUserData, pInfo->address, regno,
3053 &pInfo->reg[regno], 1);
3054
3055 return (status);
3056}
3057
3058/****************************************************************************
3059**
3060** Name: MT2063_SetParam
3061**
3062** Description: Sets a tuning algorithm parameter.
3063**
3064** This function provides access to the internals of the
3065** tuning algorithm. You can override many of the tuning
3066** algorithm defaults using this function.
3067**
3068** Parameters: h - Tuner handle (returned by MT2063_Open)
3069** param - Tuning algorithm parameter
3070** (see enum MT2063_Param)
3071** nValue - value to be set
3072**
3073** param Description
3074** ---------------------- --------------------------------
3075** MT2063_SRO_FREQ crystal frequency
3076** MT2063_STEPSIZE minimum tuning step size
3077** MT2063_LO1_FREQ LO1 frequency
3078** MT2063_LO1_STEPSIZE LO1 minimum step size
3079** MT2063_LO1_FRACN_AVOID LO1 FracN keep-out region
3080** MT2063_IF1_REQUEST Requested 1st IF
3081** MT2063_ZIF_BW zero-IF bandwidth
3082** MT2063_LO2_FREQ LO2 frequency
3083** MT2063_LO2_STEPSIZE LO2 minimum step size
3084** MT2063_LO2_FRACN_AVOID LO2 FracN keep-out region
3085** MT2063_OUTPUT_FREQ output center frequency
3086** MT2063_OUTPUT_BW output bandwidth
3087** MT2063_LO_SEPARATION min inter-tuner LO separation
3088** MT2063_MAX_HARM1 max # of intra-tuner harmonics
3089** MT2063_MAX_HARM2 max # of inter-tuner harmonics
3090** MT2063_RCVR_MODE Predefined modes
3091** MT2063_LNA_RIN Set LNA Rin (*)
3092** MT2063_LNA_TGT Set target power level at LNA (*)
3093** MT2063_PD1_TGT Set target power level at PD1 (*)
3094** MT2063_PD2_TGT Set target power level at PD2 (*)
3095** MT2063_ACLNA_MAX LNA attenuator limit (*)
3096** MT2063_ACRF_MAX RF attenuator limit (*)
3097** MT2063_ACFIF_MAX FIF attenuator limit (*)
3098** MT2063_DNC_OUTPUT_ENABLE DNC output selection
3099** MT2063_VGAGC VGA gain code
3100** MT2063_VGAOI VGA output current
3101** MT2063_TAGC TAGC setting
3102** MT2063_AMPGC AMP gain code
3103** MT2063_AVOID_DECT Avoid DECT Frequencies
3104** MT2063_CTFILT_SW Cleartune filter selection
3105**
3106** (*) This parameter is set by MT2063_RCVR_MODE, do not call
3107** additionally.
3108**
3109** Usage: status |= MT2063_SetParam(hMT2063,
3110** MT2063_STEPSIZE,
3111** 50000);
3112**
3113** Returns: status:
3114** MT_OK - No errors
3115** MT_INV_HANDLE - Invalid tuner handle
3116** MT_ARG_NULL - Null pointer argument passed
3117** MT_ARG_RANGE - Invalid parameter requested
3118** or set value out of range
3119** or non-writable parameter
3120**
3121** Dependencies: USERS MUST CALL MT2063_Open() FIRST!
3122**
3123** See Also: MT2063_GetParam, MT2063_Open
3124**
3125** Revision History:
3126**
3127** SCR Date Author Description
3128** -------------------------------------------------------------------------
3129** 138 06-19-2007 DAD Ver 1.00: Initial, derived from mt2067_b.
3130** 154 09-13-2007 RSK Ver 1.05: Get/SetParam changes for LOx_FREQ
3131** 10-31-2007 PINZ Ver 1.08: Get/SetParam add VGAGC, VGAOI, AMPGC, TAGC
3132** 04-18-2008 PINZ Ver 1.15: Add SetParam LNARIN & PDxTGT
3133** Split SetParam up to ACLNA / ACLNA_MAX
3134** removed ACLNA_INRC/DECR (+RF & FIF)
3135** removed GCUAUTO / BYPATNDN/UP
3136** 175 I 06-06-2008 PINZ Ver 1.16: Add control to avoid US DECT freqs.
3137** 175 I 06-19-2008 RSK Ver 1.17: Refactor DECT control to SpurAvoid.
3138** 06-24-2008 PINZ Ver 1.18: Add Get/SetParam CTFILT_SW
3139**
3140****************************************************************************/
Mauro Carvalho Chehabcfde8922011-07-20 21:01:48 -03003141u32 MT2063_SetParam(void *h, enum MT2063_Param param, u32 nValue)
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03003142{
Mauro Carvalho Chehabcfde8922011-07-20 21:01:48 -03003143 u32 status = MT2063_OK; /* Status to be returned */
3144 u8 val = 0;
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03003145 struct MT2063_Info_t *pInfo = (struct MT2063_Info_t *)h;
3146
3147 /* Verify that the handle passed points to a valid tuner */
3148 if (MT2063_IsValidHandle(pInfo) == 0)
3149 status |= MT2063_INV_HANDLE;
3150
3151 if (MT2063_NO_ERROR(status)) {
3152 switch (param) {
3153 /* crystal frequency */
3154 case MT2063_SRO_FREQ:
3155 pInfo->AS_Data.f_ref = nValue;
3156 pInfo->AS_Data.f_LO1_FracN_Avoid = 0;
3157 pInfo->AS_Data.f_LO2_FracN_Avoid = nValue / 80 - 1;
3158 pInfo->AS_Data.f_LO1_Step = nValue / 64;
3159 pInfo->AS_Data.f_if1_Center =
3160 (pInfo->AS_Data.f_ref / 8) *
3161 (pInfo->reg[MT2063_REG_FIFFC] + 640);
3162 break;
3163
3164 /* minimum tuning step size */
3165 case MT2063_STEPSIZE:
3166 pInfo->AS_Data.f_LO2_Step = nValue;
3167 break;
3168
3169 /* LO1 frequency */
3170 case MT2063_LO1_FREQ:
3171 {
3172 /* Note: LO1 and LO2 are BOTH written at toggle of LDLOos */
3173 /* Capture the Divider and Numerator portions of other LO */
Mauro Carvalho Chehabcfde8922011-07-20 21:01:48 -03003174 u8 tempLO2CQ[3];
3175 u8 tempLO2C[3];
3176 u8 tmpOneShot;
3177 u32 Div, FracN;
3178 u8 restore = 0;
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03003179
3180 /* Buffer the queue for restoration later and get actual LO2 values. */
3181 status |=
3182 MT2063_ReadSub(pInfo->hUserData,
3183 pInfo->address,
3184 MT2063_REG_LO2CQ_1,
3185 &(tempLO2CQ[0]), 3);
3186 status |=
3187 MT2063_ReadSub(pInfo->hUserData,
3188 pInfo->address,
3189 MT2063_REG_LO2C_1,
3190 &(tempLO2C[0]), 3);
3191
3192 /* clear the one-shot bits */
3193 tempLO2CQ[2] = tempLO2CQ[2] & 0x0F;
3194 tempLO2C[2] = tempLO2C[2] & 0x0F;
3195
3196 /* only write the queue values if they are different from the actual. */
3197 if ((tempLO2CQ[0] != tempLO2C[0]) ||
3198 (tempLO2CQ[1] != tempLO2C[1]) ||
3199 (tempLO2CQ[2] != tempLO2C[2])) {
3200 /* put actual LO2 value into queue (with 0 in one-shot bits) */
3201 status |=
3202 MT2063_WriteSub(pInfo->hUserData,
3203 pInfo->address,
3204 MT2063_REG_LO2CQ_1,
3205 &(tempLO2C[0]), 3);
3206
3207 if (status == MT2063_OK) {
3208 /* cache the bytes just written. */
3209 pInfo->reg[MT2063_REG_LO2CQ_1] =
3210 tempLO2C[0];
3211 pInfo->reg[MT2063_REG_LO2CQ_2] =
3212 tempLO2C[1];
3213 pInfo->reg[MT2063_REG_LO2CQ_3] =
3214 tempLO2C[2];
3215 }
3216 restore = 1;
3217 }
3218
3219 /* Calculate the Divider and Numberator components of LO1 */
3220 status =
3221 MT2063_CalcLO1Mult(&Div, &FracN, nValue,
3222 pInfo->AS_Data.f_ref /
3223 64,
3224 pInfo->AS_Data.f_ref);
3225 pInfo->reg[MT2063_REG_LO1CQ_1] =
Mauro Carvalho Chehabcfde8922011-07-20 21:01:48 -03003226 (u8) (Div & 0x00FF);
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03003227 pInfo->reg[MT2063_REG_LO1CQ_2] =
Mauro Carvalho Chehabcfde8922011-07-20 21:01:48 -03003228 (u8) (FracN);
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03003229 status |=
3230 MT2063_WriteSub(pInfo->hUserData,
3231 pInfo->address,
3232 MT2063_REG_LO1CQ_1,
3233 &pInfo->
3234 reg[MT2063_REG_LO1CQ_1], 2);
3235
3236 /* set the one-shot bit to load the pair of LO values */
3237 tmpOneShot = tempLO2CQ[2] | 0xE0;
3238 status |=
3239 MT2063_WriteSub(pInfo->hUserData,
3240 pInfo->address,
3241 MT2063_REG_LO2CQ_3,
3242 &tmpOneShot, 1);
3243
3244 /* only restore the queue values if they were different from the actual. */
3245 if (restore) {
3246 /* put actual LO2 value into queue (0 in one-shot bits) */
3247 status |=
3248 MT2063_WriteSub(pInfo->hUserData,
3249 pInfo->address,
3250 MT2063_REG_LO2CQ_1,
3251 &(tempLO2CQ[0]), 3);
3252
3253 /* cache the bytes just written. */
3254 pInfo->reg[MT2063_REG_LO2CQ_1] =
3255 tempLO2CQ[0];
3256 pInfo->reg[MT2063_REG_LO2CQ_2] =
3257 tempLO2CQ[1];
3258 pInfo->reg[MT2063_REG_LO2CQ_3] =
3259 tempLO2CQ[2];
3260 }
3261
3262 MT2063_GetParam(pInfo->hUserData,
3263 MT2063_LO1_FREQ,
3264 &pInfo->AS_Data.f_LO1);
3265 }
3266 break;
3267
3268 /* LO1 minimum step size */
3269 case MT2063_LO1_STEPSIZE:
3270 pInfo->AS_Data.f_LO1_Step = nValue;
3271 break;
3272
3273 /* LO1 FracN keep-out region */
3274 case MT2063_LO1_FRACN_AVOID_PARAM:
3275 pInfo->AS_Data.f_LO1_FracN_Avoid = nValue;
3276 break;
3277
3278 /* Requested 1st IF */
3279 case MT2063_IF1_REQUEST:
3280 pInfo->AS_Data.f_if1_Request = nValue;
3281 break;
3282
3283 /* zero-IF bandwidth */
3284 case MT2063_ZIF_BW:
3285 pInfo->AS_Data.f_zif_bw = nValue;
3286 break;
3287
3288 /* LO2 frequency */
3289 case MT2063_LO2_FREQ:
3290 {
3291 /* Note: LO1 and LO2 are BOTH written at toggle of LDLOos */
3292 /* Capture the Divider and Numerator portions of other LO */
Mauro Carvalho Chehabcfde8922011-07-20 21:01:48 -03003293 u8 tempLO1CQ[2];
3294 u8 tempLO1C[2];
3295 u32 Div2;
3296 u32 FracN2;
3297 u8 tmpOneShot;
3298 u8 restore = 0;
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03003299
3300 /* Buffer the queue for restoration later and get actual LO2 values. */
3301 status |=
3302 MT2063_ReadSub(pInfo->hUserData,
3303 pInfo->address,
3304 MT2063_REG_LO1CQ_1,
3305 &(tempLO1CQ[0]), 2);
3306 status |=
3307 MT2063_ReadSub(pInfo->hUserData,
3308 pInfo->address,
3309 MT2063_REG_LO1C_1,
3310 &(tempLO1C[0]), 2);
3311
3312 /* only write the queue values if they are different from the actual. */
3313 if ((tempLO1CQ[0] != tempLO1C[0])
3314 || (tempLO1CQ[1] != tempLO1C[1])) {
3315 /* put actual LO1 value into queue */
3316 status |=
3317 MT2063_WriteSub(pInfo->hUserData,
3318 pInfo->address,
3319 MT2063_REG_LO1CQ_1,
3320 &(tempLO1C[0]), 2);
3321
3322 /* cache the bytes just written. */
3323 pInfo->reg[MT2063_REG_LO1CQ_1] =
3324 tempLO1C[0];
3325 pInfo->reg[MT2063_REG_LO1CQ_2] =
3326 tempLO1C[1];
3327 restore = 1;
3328 }
3329
3330 /* Calculate the Divider and Numberator components of LO2 */
3331 status =
3332 MT2063_CalcLO2Mult(&Div2, &FracN2, nValue,
3333 pInfo->AS_Data.f_ref /
3334 8191,
3335 pInfo->AS_Data.f_ref);
3336 pInfo->reg[MT2063_REG_LO2CQ_1] =
Mauro Carvalho Chehabcfde8922011-07-20 21:01:48 -03003337 (u8) ((Div2 << 1) |
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03003338 ((FracN2 >> 12) & 0x01)) & 0xFF;
3339 pInfo->reg[MT2063_REG_LO2CQ_2] =
Mauro Carvalho Chehabcfde8922011-07-20 21:01:48 -03003340 (u8) ((FracN2 >> 4) & 0xFF);
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03003341 pInfo->reg[MT2063_REG_LO2CQ_3] =
Mauro Carvalho Chehabcfde8922011-07-20 21:01:48 -03003342 (u8) ((FracN2 & 0x0F));
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03003343 status |=
3344 MT2063_WriteSub(pInfo->hUserData,
3345 pInfo->address,
3346 MT2063_REG_LO1CQ_1,
3347 &pInfo->
3348 reg[MT2063_REG_LO1CQ_1], 3);
3349
3350 /* set the one-shot bit to load the LO values */
3351 tmpOneShot =
3352 pInfo->reg[MT2063_REG_LO2CQ_3] | 0xE0;
3353 status |=
3354 MT2063_WriteSub(pInfo->hUserData,
3355 pInfo->address,
3356 MT2063_REG_LO2CQ_3,
3357 &tmpOneShot, 1);
3358
3359 /* only restore LO1 queue value if they were different from the actual. */
3360 if (restore) {
3361 /* put previous LO1 queue value back into queue */
3362 status |=
3363 MT2063_WriteSub(pInfo->hUserData,
3364 pInfo->address,
3365 MT2063_REG_LO1CQ_1,
3366 &(tempLO1CQ[0]), 2);
3367
3368 /* cache the bytes just written. */
3369 pInfo->reg[MT2063_REG_LO1CQ_1] =
3370 tempLO1CQ[0];
3371 pInfo->reg[MT2063_REG_LO1CQ_2] =
3372 tempLO1CQ[1];
3373 }
3374
3375 MT2063_GetParam(pInfo->hUserData,
3376 MT2063_LO2_FREQ,
3377 &pInfo->AS_Data.f_LO2);
3378 }
3379 break;
3380
3381 /* LO2 minimum step size */
3382 case MT2063_LO2_STEPSIZE:
3383 pInfo->AS_Data.f_LO2_Step = nValue;
3384 break;
3385
3386 /* LO2 FracN keep-out region */
3387 case MT2063_LO2_FRACN_AVOID:
3388 pInfo->AS_Data.f_LO2_FracN_Avoid = nValue;
3389 break;
3390
3391 /* output center frequency */
3392 case MT2063_OUTPUT_FREQ:
3393 pInfo->AS_Data.f_out = nValue;
3394 break;
3395
3396 /* output bandwidth */
3397 case MT2063_OUTPUT_BW:
3398 pInfo->AS_Data.f_out_bw = nValue + 750000;
3399 break;
3400
3401 /* min inter-tuner LO separation */
3402 case MT2063_LO_SEPARATION:
3403 pInfo->AS_Data.f_min_LO_Separation = nValue;
3404 break;
3405
3406 /* max # of intra-tuner harmonics */
3407 case MT2063_MAX_HARM1:
3408 pInfo->AS_Data.maxH1 = nValue;
3409 break;
3410
3411 /* max # of inter-tuner harmonics */
3412 case MT2063_MAX_HARM2:
3413 pInfo->AS_Data.maxH2 = nValue;
3414 break;
3415
3416 case MT2063_RCVR_MODE:
3417 status |=
3418 MT2063_SetReceiverMode(pInfo,
3419 (enum MT2063_RCVR_MODES)
3420 nValue);
3421 break;
3422
3423 /* Set LNA Rin -- nValue is desired value */
3424 case MT2063_LNA_RIN:
3425 val =
3426 (pInfo->
Mauro Carvalho Chehabcfde8922011-07-20 21:01:48 -03003427 reg[MT2063_REG_CTRL_2C] & (u8) ~ 0x03) |
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03003428 (nValue & 0x03);
3429 if (pInfo->reg[MT2063_REG_CTRL_2C] != val) {
3430 status |=
3431 MT2063_SetReg(pInfo, MT2063_REG_CTRL_2C,
3432 val);
3433 }
3434 break;
3435
3436 /* Set target power level at LNA -- nValue is desired value */
3437 case MT2063_LNA_TGT:
3438 val =
3439 (pInfo->
Mauro Carvalho Chehabcfde8922011-07-20 21:01:48 -03003440 reg[MT2063_REG_LNA_TGT] & (u8) ~ 0x3F) |
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03003441 (nValue & 0x3F);
3442 if (pInfo->reg[MT2063_REG_LNA_TGT] != val) {
3443 status |=
3444 MT2063_SetReg(pInfo, MT2063_REG_LNA_TGT,
3445 val);
3446 }
3447 break;
3448
3449 /* Set target power level at PD1 -- nValue is desired value */
3450 case MT2063_PD1_TGT:
3451 val =
3452 (pInfo->
Mauro Carvalho Chehabcfde8922011-07-20 21:01:48 -03003453 reg[MT2063_REG_PD1_TGT] & (u8) ~ 0x3F) |
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03003454 (nValue & 0x3F);
3455 if (pInfo->reg[MT2063_REG_PD1_TGT] != val) {
3456 status |=
3457 MT2063_SetReg(pInfo, MT2063_REG_PD1_TGT,
3458 val);
3459 }
3460 break;
3461
3462 /* Set target power level at PD2 -- nValue is desired value */
3463 case MT2063_PD2_TGT:
3464 val =
3465 (pInfo->
Mauro Carvalho Chehabcfde8922011-07-20 21:01:48 -03003466 reg[MT2063_REG_PD2_TGT] & (u8) ~ 0x3F) |
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03003467 (nValue & 0x3F);
3468 if (pInfo->reg[MT2063_REG_PD2_TGT] != val) {
3469 status |=
3470 MT2063_SetReg(pInfo, MT2063_REG_PD2_TGT,
3471 val);
3472 }
3473 break;
3474
3475 /* Set LNA atten limit -- nValue is desired value */
3476 case MT2063_ACLNA_MAX:
3477 val =
3478 (pInfo->
Mauro Carvalho Chehabcfde8922011-07-20 21:01:48 -03003479 reg[MT2063_REG_LNA_OV] & (u8) ~ 0x1F) | (nValue
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03003480 &
3481 0x1F);
3482 if (pInfo->reg[MT2063_REG_LNA_OV] != val) {
3483 status |=
3484 MT2063_SetReg(pInfo, MT2063_REG_LNA_OV,
3485 val);
3486 }
3487 break;
3488
3489 /* Set RF atten limit -- nValue is desired value */
3490 case MT2063_ACRF_MAX:
3491 val =
3492 (pInfo->
Mauro Carvalho Chehabcfde8922011-07-20 21:01:48 -03003493 reg[MT2063_REG_RF_OV] & (u8) ~ 0x1F) | (nValue
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03003494 &
3495 0x1F);
3496 if (pInfo->reg[MT2063_REG_RF_OV] != val) {
3497 status |=
3498 MT2063_SetReg(pInfo, MT2063_REG_RF_OV, val);
3499 }
3500 break;
3501
3502 /* Set FIF atten limit -- nValue is desired value, max. 5 if no B3 */
3503 case MT2063_ACFIF_MAX:
3504 if (pInfo->reg[MT2063_REG_PART_REV] != MT2063_B3
3505 && nValue > 5)
3506 nValue = 5;
3507 val =
3508 (pInfo->
Mauro Carvalho Chehabcfde8922011-07-20 21:01:48 -03003509 reg[MT2063_REG_FIF_OV] & (u8) ~ 0x1F) | (nValue
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03003510 &
3511 0x1F);
3512 if (pInfo->reg[MT2063_REG_FIF_OV] != val) {
3513 status |=
3514 MT2063_SetReg(pInfo, MT2063_REG_FIF_OV,
3515 val);
3516 }
3517 break;
3518
3519 case MT2063_DNC_OUTPUT_ENABLE:
3520 /* selects, which DNC output is used */
3521 switch ((enum MT2063_DNC_Output_Enable)nValue) {
3522 case MT2063_DNC_NONE:
3523 {
3524 val = (pInfo->reg[MT2063_REG_DNC_GAIN] & 0xFC) | 0x03; /* Set DNC1GC=3 */
3525 if (pInfo->reg[MT2063_REG_DNC_GAIN] !=
3526 val)
3527 status |=
3528 MT2063_SetReg(h,
3529 MT2063_REG_DNC_GAIN,
3530 val);
3531
3532 val = (pInfo->reg[MT2063_REG_VGA_GAIN] & 0xFC) | 0x03; /* Set DNC2GC=3 */
3533 if (pInfo->reg[MT2063_REG_VGA_GAIN] !=
3534 val)
3535 status |=
3536 MT2063_SetReg(h,
3537 MT2063_REG_VGA_GAIN,
3538 val);
3539
3540 val = (pInfo->reg[MT2063_REG_RSVD_20] & ~0x40); /* Set PD2MUX=0 */
3541 if (pInfo->reg[MT2063_REG_RSVD_20] !=
3542 val)
3543 status |=
3544 MT2063_SetReg(h,
3545 MT2063_REG_RSVD_20,
3546 val);
3547
3548 break;
3549 }
3550 case MT2063_DNC_1:
3551 {
3552 val = (pInfo->reg[MT2063_REG_DNC_GAIN] & 0xFC) | (DNC1GC[pInfo->rcvr_mode] & 0x03); /* Set DNC1GC=x */
3553 if (pInfo->reg[MT2063_REG_DNC_GAIN] !=
3554 val)
3555 status |=
3556 MT2063_SetReg(h,
3557 MT2063_REG_DNC_GAIN,
3558 val);
3559
3560 val = (pInfo->reg[MT2063_REG_VGA_GAIN] & 0xFC) | 0x03; /* Set DNC2GC=3 */
3561 if (pInfo->reg[MT2063_REG_VGA_GAIN] !=
3562 val)
3563 status |=
3564 MT2063_SetReg(h,
3565 MT2063_REG_VGA_GAIN,
3566 val);
3567
3568 val = (pInfo->reg[MT2063_REG_RSVD_20] & ~0x40); /* Set PD2MUX=0 */
3569 if (pInfo->reg[MT2063_REG_RSVD_20] !=
3570 val)
3571 status |=
3572 MT2063_SetReg(h,
3573 MT2063_REG_RSVD_20,
3574 val);
3575
3576 break;
3577 }
3578 case MT2063_DNC_2:
3579 {
3580 val = (pInfo->reg[MT2063_REG_DNC_GAIN] & 0xFC) | 0x03; /* Set DNC1GC=3 */
3581 if (pInfo->reg[MT2063_REG_DNC_GAIN] !=
3582 val)
3583 status |=
3584 MT2063_SetReg(h,
3585 MT2063_REG_DNC_GAIN,
3586 val);
3587
3588 val = (pInfo->reg[MT2063_REG_VGA_GAIN] & 0xFC) | (DNC2GC[pInfo->rcvr_mode] & 0x03); /* Set DNC2GC=x */
3589 if (pInfo->reg[MT2063_REG_VGA_GAIN] !=
3590 val)
3591 status |=
3592 MT2063_SetReg(h,
3593 MT2063_REG_VGA_GAIN,
3594 val);
3595
3596 val = (pInfo->reg[MT2063_REG_RSVD_20] | 0x40); /* Set PD2MUX=1 */
3597 if (pInfo->reg[MT2063_REG_RSVD_20] !=
3598 val)
3599 status |=
3600 MT2063_SetReg(h,
3601 MT2063_REG_RSVD_20,
3602 val);
3603
3604 break;
3605 }
3606 case MT2063_DNC_BOTH:
3607 {
3608 val = (pInfo->reg[MT2063_REG_DNC_GAIN] & 0xFC) | (DNC1GC[pInfo->rcvr_mode] & 0x03); /* Set DNC1GC=x */
3609 if (pInfo->reg[MT2063_REG_DNC_GAIN] !=
3610 val)
3611 status |=
3612 MT2063_SetReg(h,
3613 MT2063_REG_DNC_GAIN,
3614 val);
3615
3616 val = (pInfo->reg[MT2063_REG_VGA_GAIN] & 0xFC) | (DNC2GC[pInfo->rcvr_mode] & 0x03); /* Set DNC2GC=x */
3617 if (pInfo->reg[MT2063_REG_VGA_GAIN] !=
3618 val)
3619 status |=
3620 MT2063_SetReg(h,
3621 MT2063_REG_VGA_GAIN,
3622 val);
3623
3624 val = (pInfo->reg[MT2063_REG_RSVD_20] | 0x40); /* Set PD2MUX=1 */
3625 if (pInfo->reg[MT2063_REG_RSVD_20] !=
3626 val)
3627 status |=
3628 MT2063_SetReg(h,
3629 MT2063_REG_RSVD_20,
3630 val);
3631
3632 break;
3633 }
3634 default:
3635 break;
3636 }
3637 break;
3638
3639 case MT2063_VGAGC:
3640 /* Set VGA gain code */
3641 val =
3642 (pInfo->
Mauro Carvalho Chehabcfde8922011-07-20 21:01:48 -03003643 reg[MT2063_REG_VGA_GAIN] & (u8) ~ 0x0C) |
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03003644 ((nValue & 0x03) << 2);
3645 if (pInfo->reg[MT2063_REG_VGA_GAIN] != val) {
3646 status |=
3647 MT2063_SetReg(pInfo, MT2063_REG_VGA_GAIN,
3648 val);
3649 }
3650 break;
3651
3652 case MT2063_VGAOI:
3653 /* Set VGA bias current */
3654 val =
3655 (pInfo->
Mauro Carvalho Chehabcfde8922011-07-20 21:01:48 -03003656 reg[MT2063_REG_RSVD_31] & (u8) ~ 0x07) |
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03003657 (nValue & 0x07);
3658 if (pInfo->reg[MT2063_REG_RSVD_31] != val) {
3659 status |=
3660 MT2063_SetReg(pInfo, MT2063_REG_RSVD_31,
3661 val);
3662 }
3663 break;
3664
3665 case MT2063_TAGC:
3666 /* Set TAGC */
3667 val =
3668 (pInfo->
Mauro Carvalho Chehabcfde8922011-07-20 21:01:48 -03003669 reg[MT2063_REG_RSVD_1E] & (u8) ~ 0x03) |
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03003670 (nValue & 0x03);
3671 if (pInfo->reg[MT2063_REG_RSVD_1E] != val) {
3672 status |=
3673 MT2063_SetReg(pInfo, MT2063_REG_RSVD_1E,
3674 val);
3675 }
3676 break;
3677
3678 case MT2063_AMPGC:
3679 /* Set Amp gain code */
3680 val =
3681 (pInfo->
Mauro Carvalho Chehabcfde8922011-07-20 21:01:48 -03003682 reg[MT2063_REG_TEMP_SEL] & (u8) ~ 0x03) |
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03003683 (nValue & 0x03);
3684 if (pInfo->reg[MT2063_REG_TEMP_SEL] != val) {
3685 status |=
3686 MT2063_SetReg(pInfo, MT2063_REG_TEMP_SEL,
3687 val);
3688 }
3689 break;
3690
3691 /* Avoid DECT Frequencies */
3692 case MT2063_AVOID_DECT:
3693 {
3694 enum MT2063_DECT_Avoid_Type newAvoidSetting =
3695 (enum MT2063_DECT_Avoid_Type)nValue;
3696 if ((newAvoidSetting >=
3697 MT2063_NO_DECT_AVOIDANCE)
3698 && (newAvoidSetting <= MT2063_AVOID_BOTH)) {
3699 pInfo->AS_Data.avoidDECT =
3700 newAvoidSetting;
3701 }
3702 }
3703 break;
3704
3705 /* Cleartune filter selection: 0 - by IC (default), 1 - by software */
3706 case MT2063_CTFILT_SW:
3707 pInfo->ctfilt_sw = (nValue & 0x01);
3708 break;
3709
3710 /* These parameters are read-only */
3711 case MT2063_IC_ADDR:
3712 case MT2063_MAX_OPEN:
3713 case MT2063_NUM_OPEN:
3714 case MT2063_INPUT_FREQ:
3715 case MT2063_IF1_ACTUAL:
3716 case MT2063_IF1_CENTER:
3717 case MT2063_IF1_BW:
3718 case MT2063_AS_ALG:
3719 case MT2063_EXCL_ZONES:
3720 case MT2063_SPUR_AVOIDED:
3721 case MT2063_NUM_SPURS:
3722 case MT2063_SPUR_PRESENT:
3723 case MT2063_ACLNA:
3724 case MT2063_ACRF:
3725 case MT2063_ACFIF:
3726 case MT2063_EOP:
3727 default:
3728 status |= MT2063_ARG_RANGE;
3729 }
3730 }
3731 return (status);
3732}
3733
3734/****************************************************************************
3735**
3736** Name: MT2063_SetPowerMaskBits
3737**
3738** Description: Sets the power-down mask bits for various sections of
3739** the MT2063
3740**
3741** Parameters: h - Tuner handle (returned by MT2063_Open)
3742** Bits - Mask bits to be set.
3743**
3744** See definition of MT2063_Mask_Bits type for description
3745** of each of the power bits.
3746**
3747** Returns: status:
3748** MT_OK - No errors
3749** MT_INV_HANDLE - Invalid tuner handle
3750** MT_COMM_ERR - Serial bus communications error
3751**
3752** Dependencies: USERS MUST CALL MT2063_Open() FIRST!
3753**
3754** Revision History:
3755**
3756** SCR Date Author Description
3757** -------------------------------------------------------------------------
3758** 138 06-19-2007 DAD Ver 1.00: Initial, derived from mt2067_b.
3759**
3760****************************************************************************/
Mauro Carvalho Chehabcfde8922011-07-20 21:01:48 -03003761u32 MT2063_SetPowerMaskBits(void *h, enum MT2063_Mask_Bits Bits)
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03003762{
Mauro Carvalho Chehabcfde8922011-07-20 21:01:48 -03003763 u32 status = MT2063_OK; /* Status to be returned */
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03003764 struct MT2063_Info_t *pInfo = (struct MT2063_Info_t *)h;
3765
3766 /* Verify that the handle passed points to a valid tuner */
3767 if (MT2063_IsValidHandle(pInfo) == 0)
3768 status = MT2063_INV_HANDLE;
3769 else {
3770 Bits = (enum MT2063_Mask_Bits)(Bits & MT2063_ALL_SD); /* Only valid bits for this tuner */
3771 if ((Bits & 0xFF00) != 0) {
3772 pInfo->reg[MT2063_REG_PWR_2] |=
Mauro Carvalho Chehabcfde8922011-07-20 21:01:48 -03003773 (u8) ((Bits & 0xFF00) >> 8);
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03003774 status |=
3775 MT2063_WriteSub(pInfo->hUserData, pInfo->address,
3776 MT2063_REG_PWR_2,
3777 &pInfo->reg[MT2063_REG_PWR_2], 1);
3778 }
3779 if ((Bits & 0xFF) != 0) {
Mauro Carvalho Chehabcfde8922011-07-20 21:01:48 -03003780 pInfo->reg[MT2063_REG_PWR_1] |= ((u8) Bits & 0xFF);
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03003781 status |=
3782 MT2063_WriteSub(pInfo->hUserData, pInfo->address,
3783 MT2063_REG_PWR_1,
3784 &pInfo->reg[MT2063_REG_PWR_1], 1);
3785 }
3786 }
3787
3788 return (status);
3789}
3790
3791/****************************************************************************
3792**
3793** Name: MT2063_ClearPowerMaskBits
3794**
3795** Description: Clears the power-down mask bits for various sections of
3796** the MT2063
3797**
3798** Parameters: h - Tuner handle (returned by MT2063_Open)
3799** Bits - Mask bits to be cleared.
3800**
3801** See definition of MT2063_Mask_Bits type for description
3802** of each of the power bits.
3803**
3804** Returns: status:
3805** MT_OK - No errors
3806** MT_INV_HANDLE - Invalid tuner handle
3807** MT_COMM_ERR - Serial bus communications error
3808**
3809** Dependencies: USERS MUST CALL MT2063_Open() FIRST!
3810**
3811** Revision History:
3812**
3813** SCR Date Author Description
3814** -------------------------------------------------------------------------
3815** 138 06-19-2007 DAD Ver 1.00: Initial, derived from mt2067_b.
3816**
3817****************************************************************************/
Mauro Carvalho Chehabcfde8922011-07-20 21:01:48 -03003818u32 MT2063_ClearPowerMaskBits(void *h, enum MT2063_Mask_Bits Bits)
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03003819{
Mauro Carvalho Chehabcfde8922011-07-20 21:01:48 -03003820 u32 status = MT2063_OK; /* Status to be returned */
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03003821 struct MT2063_Info_t *pInfo = (struct MT2063_Info_t *)h;
3822
3823 /* Verify that the handle passed points to a valid tuner */
3824 if (MT2063_IsValidHandle(pInfo) == 0)
3825 status = MT2063_INV_HANDLE;
3826 else {
3827 Bits = (enum MT2063_Mask_Bits)(Bits & MT2063_ALL_SD); /* Only valid bits for this tuner */
3828 if ((Bits & 0xFF00) != 0) {
Mauro Carvalho Chehabcfde8922011-07-20 21:01:48 -03003829 pInfo->reg[MT2063_REG_PWR_2] &= ~(u8) (Bits >> 8);
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03003830 status |=
3831 MT2063_WriteSub(pInfo->hUserData, pInfo->address,
3832 MT2063_REG_PWR_2,
3833 &pInfo->reg[MT2063_REG_PWR_2], 1);
3834 }
3835 if ((Bits & 0xFF) != 0) {
Mauro Carvalho Chehabcfde8922011-07-20 21:01:48 -03003836 pInfo->reg[MT2063_REG_PWR_1] &= ~(u8) (Bits & 0xFF);
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03003837 status |=
3838 MT2063_WriteSub(pInfo->hUserData, pInfo->address,
3839 MT2063_REG_PWR_1,
3840 &pInfo->reg[MT2063_REG_PWR_1], 1);
3841 }
3842 }
3843
3844 return (status);
3845}
3846
3847/****************************************************************************
3848**
3849** Name: MT2063_GetPowerMaskBits
3850**
3851** Description: Returns a mask of the enabled power shutdown bits
3852**
3853** Parameters: h - Tuner handle (returned by MT2063_Open)
3854** Bits - Mask bits to currently set.
3855**
3856** See definition of MT2063_Mask_Bits type for description
3857** of each of the power bits.
3858**
3859** Returns: status:
3860** MT_OK - No errors
3861** MT_INV_HANDLE - Invalid tuner handle
3862** MT_ARG_NULL - Output argument is NULL
3863** MT_COMM_ERR - Serial bus communications error
3864**
3865** Dependencies: USERS MUST CALL MT2063_Open() FIRST!
3866**
3867** Revision History:
3868**
3869** SCR Date Author Description
3870** -------------------------------------------------------------------------
3871** 138 06-19-2007 DAD Ver 1.00: Initial, derived from mt2067_b.
3872**
3873****************************************************************************/
Mauro Carvalho Chehabcfde8922011-07-20 21:01:48 -03003874u32 MT2063_GetPowerMaskBits(void *h, enum MT2063_Mask_Bits * Bits)
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03003875{
Mauro Carvalho Chehabcfde8922011-07-20 21:01:48 -03003876 u32 status = MT2063_OK; /* Status to be returned */
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03003877 struct MT2063_Info_t *pInfo = (struct MT2063_Info_t *)h;
3878
3879 /* Verify that the handle passed points to a valid tuner */
3880 if (MT2063_IsValidHandle(pInfo) == 0)
3881 status = MT2063_INV_HANDLE;
3882 else {
3883 if (Bits == NULL)
3884 status |= MT2063_ARG_NULL;
3885
3886 if (MT2063_NO_ERROR(status))
3887 status |=
3888 MT2063_ReadSub(pInfo->hUserData, pInfo->address,
3889 MT2063_REG_PWR_1,
3890 &pInfo->reg[MT2063_REG_PWR_1], 2);
3891
3892 if (MT2063_NO_ERROR(status)) {
3893 *Bits =
3894 (enum
Mauro Carvalho Chehabcfde8922011-07-20 21:01:48 -03003895 MT2063_Mask_Bits)(((s32) pInfo->
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03003896 reg[MT2063_REG_PWR_2] << 8) +
3897 pInfo->reg[MT2063_REG_PWR_1]);
3898 *Bits = (enum MT2063_Mask_Bits)(*Bits & MT2063_ALL_SD); /* Only valid bits for this tuner */
3899 }
3900 }
3901
3902 return (status);
3903}
3904
3905/****************************************************************************
3906**
3907** Name: MT2063_EnableExternalShutdown
3908**
3909** Description: Enables or disables the operation of the external
3910** shutdown pin
3911**
3912** Parameters: h - Tuner handle (returned by MT2063_Open)
3913** Enabled - 0 = disable the pin, otherwise enable it
3914**
3915** Returns: status:
3916** MT_OK - No errors
3917** MT_INV_HANDLE - Invalid tuner handle
3918** MT_COMM_ERR - Serial bus communications error
3919**
3920** Dependencies: USERS MUST CALL MT2063_Open() FIRST!
3921**
3922** Revision History:
3923**
3924** SCR Date Author Description
3925** -------------------------------------------------------------------------
3926** 138 06-19-2007 DAD Ver 1.00: Initial, derived from mt2067_b.
3927**
3928****************************************************************************/
Mauro Carvalho Chehabcfde8922011-07-20 21:01:48 -03003929u32 MT2063_EnableExternalShutdown(void *h, u8 Enabled)
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03003930{
Mauro Carvalho Chehabcfde8922011-07-20 21:01:48 -03003931 u32 status = MT2063_OK; /* Status to be returned */
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03003932 struct MT2063_Info_t *pInfo = (struct MT2063_Info_t *)h;
3933
3934 /* Verify that the handle passed points to a valid tuner */
3935 if (MT2063_IsValidHandle(pInfo) == 0)
3936 status = MT2063_INV_HANDLE;
3937 else {
3938 if (Enabled == 0)
3939 pInfo->reg[MT2063_REG_PWR_1] &= ~0x08; /* Turn off the bit */
3940 else
3941 pInfo->reg[MT2063_REG_PWR_1] |= 0x08; /* Turn the bit on */
3942
3943 status |=
3944 MT2063_WriteSub(pInfo->hUserData, pInfo->address,
3945 MT2063_REG_PWR_1,
3946 &pInfo->reg[MT2063_REG_PWR_1], 1);
3947 }
3948
3949 return (status);
3950}
3951
3952/****************************************************************************
3953**
3954** Name: MT2063_SoftwareShutdown
3955**
3956** Description: Enables or disables software shutdown function. When
3957** Shutdown==1, any section whose power mask is set will be
3958** shutdown.
3959**
3960** Parameters: h - Tuner handle (returned by MT2063_Open)
3961** Shutdown - 1 = shutdown the masked sections, otherwise
3962** power all sections on
3963**
3964** Returns: status:
3965** MT_OK - No errors
3966** MT_INV_HANDLE - Invalid tuner handle
3967** MT_COMM_ERR - Serial bus communications error
3968**
3969** Dependencies: USERS MUST CALL MT2063_Open() FIRST!
3970**
3971** Revision History:
3972**
3973** SCR Date Author Description
3974** -------------------------------------------------------------------------
3975** 138 06-19-2007 DAD Ver 1.00: Initial, derived from mt2067_b.
3976** 01-03-2008 PINZ Ver 1.xx: Added a trigger of BYPATNUP for
3977** correct wakeup of the LNA
3978**
3979****************************************************************************/
Mauro Carvalho Chehabcfde8922011-07-20 21:01:48 -03003980u32 MT2063_SoftwareShutdown(void *h, u8 Shutdown)
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03003981{
Mauro Carvalho Chehabcfde8922011-07-20 21:01:48 -03003982 u32 status = MT2063_OK; /* Status to be returned */
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03003983 struct MT2063_Info_t *pInfo = (struct MT2063_Info_t *)h;
3984
3985 /* Verify that the handle passed points to a valid tuner */
3986 if (MT2063_IsValidHandle(pInfo) == 0) {
3987 status = MT2063_INV_HANDLE;
3988 } else {
3989 if (Shutdown == 1)
3990 pInfo->reg[MT2063_REG_PWR_1] |= 0x04; /* Turn the bit on */
3991 else
3992 pInfo->reg[MT2063_REG_PWR_1] &= ~0x04; /* Turn off the bit */
3993
3994 status |=
3995 MT2063_WriteSub(pInfo->hUserData, pInfo->address,
3996 MT2063_REG_PWR_1,
3997 &pInfo->reg[MT2063_REG_PWR_1], 1);
3998
3999 if (Shutdown != 1) {
4000 pInfo->reg[MT2063_REG_BYP_CTRL] =
4001 (pInfo->reg[MT2063_REG_BYP_CTRL] & 0x9F) | 0x40;
4002 status |=
4003 MT2063_WriteSub(pInfo->hUserData, pInfo->address,
4004 MT2063_REG_BYP_CTRL,
4005 &pInfo->reg[MT2063_REG_BYP_CTRL],
4006 1);
4007 pInfo->reg[MT2063_REG_BYP_CTRL] =
4008 (pInfo->reg[MT2063_REG_BYP_CTRL] & 0x9F);
4009 status |=
4010 MT2063_WriteSub(pInfo->hUserData, pInfo->address,
4011 MT2063_REG_BYP_CTRL,
4012 &pInfo->reg[MT2063_REG_BYP_CTRL],
4013 1);
4014 }
4015 }
4016
4017 return (status);
4018}
4019
4020/****************************************************************************
4021**
4022** Name: MT2063_SetExtSRO
4023**
4024** Description: Sets the external SRO driver.
4025**
4026** Parameters: h - Tuner handle (returned by MT2063_Open)
4027** Ext_SRO_Setting - external SRO drive setting
4028**
4029** (default) MT2063_EXT_SRO_OFF - ext driver off
4030** MT2063_EXT_SRO_BY_1 - ext driver = SRO frequency
4031** MT2063_EXT_SRO_BY_2 - ext driver = SRO/2 frequency
4032** MT2063_EXT_SRO_BY_4 - ext driver = SRO/4 frequency
4033**
4034** Returns: status:
4035** MT_OK - No errors
4036** MT_COMM_ERR - Serial bus communications error
4037** MT_INV_HANDLE - Invalid tuner handle
4038**
4039** Dependencies: USERS MUST CALL MT2063_Open() FIRST!
4040**
4041** The Ext_SRO_Setting settings default to OFF
4042** Use this function if you need to override the default
4043**
4044** Revision History:
4045**
4046** SCR Date Author Description
4047** -------------------------------------------------------------------------
4048** 138 06-19-2007 DAD Ver 1.00: Initial, derived from mt2067_b.
4049** 189 S 05-13-2008 RSK Ver 1.16: Correct location for ExtSRO control.
4050**
4051****************************************************************************/
Mauro Carvalho Chehabcfde8922011-07-20 21:01:48 -03004052u32 MT2063_SetExtSRO(void *h, enum MT2063_Ext_SRO Ext_SRO_Setting)
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03004053{
Mauro Carvalho Chehabcfde8922011-07-20 21:01:48 -03004054 u32 status = MT2063_OK; /* Status to be returned */
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03004055 struct MT2063_Info_t *pInfo = (struct MT2063_Info_t *)h;
4056
4057 /* Verify that the handle passed points to a valid tuner */
4058 if (MT2063_IsValidHandle(pInfo) == 0)
4059 status = MT2063_INV_HANDLE;
4060 else {
4061 pInfo->reg[MT2063_REG_CTRL_2C] =
4062 (pInfo->
Mauro Carvalho Chehabcfde8922011-07-20 21:01:48 -03004063 reg[MT2063_REG_CTRL_2C] & 0x3F) | ((u8) Ext_SRO_Setting
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03004064 << 6);
4065 status =
4066 MT2063_WriteSub(pInfo->hUserData, pInfo->address,
4067 MT2063_REG_CTRL_2C,
4068 &pInfo->reg[MT2063_REG_CTRL_2C], 1);
4069 }
4070
4071 return (status);
4072}
4073
4074/****************************************************************************
4075**
4076** Name: MT2063_SetReg
4077**
4078** Description: Sets an MT2063 register.
4079**
4080** Parameters: h - Tuner handle (returned by MT2063_Open)
4081** reg - MT2063 register/subaddress location
4082** val - MT2063 register/subaddress value
4083**
4084** Returns: status:
4085** MT_OK - No errors
4086** MT_COMM_ERR - Serial bus communications error
4087** MT_INV_HANDLE - Invalid tuner handle
4088** MT_ARG_RANGE - Argument out of range
4089**
4090** Dependencies: USERS MUST CALL MT2063_Open() FIRST!
4091**
4092** Use this function if you need to override a default
4093** register value
4094**
4095** Revision History:
4096**
4097** SCR Date Author Description
4098** -------------------------------------------------------------------------
4099** 138 06-19-2007 DAD Ver 1.00: Initial, derived from mt2067_b.
4100**
4101****************************************************************************/
Mauro Carvalho Chehabcfde8922011-07-20 21:01:48 -03004102u32 MT2063_SetReg(void *h, u8 reg, u8 val)
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03004103{
Mauro Carvalho Chehabcfde8922011-07-20 21:01:48 -03004104 u32 status = MT2063_OK; /* Status to be returned */
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03004105 struct MT2063_Info_t *pInfo = (struct MT2063_Info_t *)h;
4106
4107 /* Verify that the handle passed points to a valid tuner */
4108 if (MT2063_IsValidHandle(pInfo) == 0)
4109 status |= MT2063_INV_HANDLE;
4110
4111 if (reg >= MT2063_REG_END_REGS)
4112 status |= MT2063_ARG_RANGE;
4113
4114 if (MT2063_NO_ERROR(status)) {
4115 status |=
4116 MT2063_WriteSub(pInfo->hUserData, pInfo->address, reg, &val,
4117 1);
4118 if (MT2063_NO_ERROR(status))
4119 pInfo->reg[reg] = val;
4120 }
4121
4122 return (status);
4123}
4124
Mauro Carvalho Chehabcfde8922011-07-20 21:01:48 -03004125static u32 MT2063_Round_fLO(u32 f_LO, u32 f_LO_Step, u32 f_ref)
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03004126{
4127 return f_ref * (f_LO / f_ref)
4128 + f_LO_Step * (((f_LO % f_ref) + (f_LO_Step / 2)) / f_LO_Step);
4129}
4130
4131/****************************************************************************
4132**
4133** Name: fLO_FractionalTerm
4134**
4135** Description: Calculates the portion contributed by FracN / denom.
4136**
4137** This function preserves maximum precision without
4138** risk of overflow. It accurately calculates
4139** f_ref * num / denom to within 1 HZ with fixed math.
4140**
4141** Parameters: num - Fractional portion of the multiplier
4142** denom - denominator portion of the ratio
4143** This routine successfully handles denom values
4144** up to and including 2^18.
4145** f_Ref - SRO frequency. This calculation handles
4146** f_ref as two separate 14-bit fields.
4147** Therefore, a maximum value of 2^28-1
4148** may safely be used for f_ref. This is
4149** the genesis of the magic number "14" and the
4150** magic mask value of 0x03FFF.
4151**
4152** Returns: f_ref * num / denom
4153**
4154** Revision History:
4155**
4156** SCR Date Author Description
4157** -------------------------------------------------------------------------
4158** 138 06-19-2007 DAD Ver 1.00: Initial, derived from mt2067_b.
4159**
4160****************************************************************************/
Mauro Carvalho Chehabcfde8922011-07-20 21:01:48 -03004161static u32 MT2063_fLO_FractionalTerm(u32 f_ref,
4162 u32 num, u32 denom)
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03004163{
Mauro Carvalho Chehabcfde8922011-07-20 21:01:48 -03004164 u32 t1 = (f_ref >> 14) * num;
4165 u32 term1 = t1 / denom;
4166 u32 loss = t1 % denom;
4167 u32 term2 =
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03004168 (((f_ref & 0x00003FFF) * num + (loss << 14)) + (denom / 2)) / denom;
4169 return ((term1 << 14) + term2);
4170}
4171
4172/****************************************************************************
4173**
4174** Name: CalcLO1Mult
4175**
4176** Description: Calculates Integer divider value and the numerator
4177** value for a FracN PLL.
4178**
4179** This function assumes that the f_LO and f_Ref are
4180** evenly divisible by f_LO_Step.
4181**
4182** Parameters: Div - OUTPUT: Whole number portion of the multiplier
4183** FracN - OUTPUT: Fractional portion of the multiplier
4184** f_LO - desired LO frequency.
4185** f_LO_Step - Minimum step size for the LO (in Hz).
4186** f_Ref - SRO frequency.
4187** f_Avoid - Range of PLL frequencies to avoid near
4188** integer multiples of f_Ref (in Hz).
4189**
4190** Returns: Recalculated LO frequency.
4191**
4192** Revision History:
4193**
4194** SCR Date Author Description
4195** -------------------------------------------------------------------------
4196** 138 06-19-2007 DAD Ver 1.00: Initial, derived from mt2067_b.
4197**
4198****************************************************************************/
Mauro Carvalho Chehabcfde8922011-07-20 21:01:48 -03004199static u32 MT2063_CalcLO1Mult(u32 * Div,
4200 u32 * FracN,
4201 u32 f_LO,
4202 u32 f_LO_Step, u32 f_Ref)
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03004203{
4204 /* Calculate the whole number portion of the divider */
4205 *Div = f_LO / f_Ref;
4206
4207 /* Calculate the numerator value (round to nearest f_LO_Step) */
4208 *FracN =
4209 (64 * (((f_LO % f_Ref) + (f_LO_Step / 2)) / f_LO_Step) +
4210 (f_Ref / f_LO_Step / 2)) / (f_Ref / f_LO_Step);
4211
4212 return (f_Ref * (*Div)) + MT2063_fLO_FractionalTerm(f_Ref, *FracN, 64);
4213}
4214
4215/****************************************************************************
4216**
4217** Name: CalcLO2Mult
4218**
4219** Description: Calculates Integer divider value and the numerator
4220** value for a FracN PLL.
4221**
4222** This function assumes that the f_LO and f_Ref are
4223** evenly divisible by f_LO_Step.
4224**
4225** Parameters: Div - OUTPUT: Whole number portion of the multiplier
4226** FracN - OUTPUT: Fractional portion of the multiplier
4227** f_LO - desired LO frequency.
4228** f_LO_Step - Minimum step size for the LO (in Hz).
4229** f_Ref - SRO frequency.
4230** f_Avoid - Range of PLL frequencies to avoid near
4231** integer multiples of f_Ref (in Hz).
4232**
4233** Returns: Recalculated LO frequency.
4234**
4235** Revision History:
4236**
4237** SCR Date Author Description
4238** -------------------------------------------------------------------------
4239** 138 06-19-2007 DAD Ver 1.00: Initial, derived from mt2067_b.
4240**
4241****************************************************************************/
Mauro Carvalho Chehabcfde8922011-07-20 21:01:48 -03004242static u32 MT2063_CalcLO2Mult(u32 * Div,
4243 u32 * FracN,
4244 u32 f_LO,
4245 u32 f_LO_Step, u32 f_Ref)
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03004246{
4247 /* Calculate the whole number portion of the divider */
4248 *Div = f_LO / f_Ref;
4249
4250 /* Calculate the numerator value (round to nearest f_LO_Step) */
4251 *FracN =
4252 (8191 * (((f_LO % f_Ref) + (f_LO_Step / 2)) / f_LO_Step) +
4253 (f_Ref / f_LO_Step / 2)) / (f_Ref / f_LO_Step);
4254
4255 return (f_Ref * (*Div)) + MT2063_fLO_FractionalTerm(f_Ref, *FracN,
4256 8191);
4257}
4258
4259/****************************************************************************
4260**
4261** Name: FindClearTuneFilter
4262**
4263** Description: Calculate the corrrect ClearTune filter to be used for
4264** a given input frequency.
4265**
4266** Parameters: pInfo - ptr to tuner data structure
4267** f_in - RF input center frequency (in Hz).
4268**
4269** Returns: ClearTune filter number (0-31)
4270**
4271** Dependencies: MUST CALL MT2064_Open BEFORE FindClearTuneFilter!
4272**
4273** Revision History:
4274**
4275** SCR Date Author Description
4276** -------------------------------------------------------------------------
4277** 04-10-2008 PINZ Ver 1.14: Use software-controlled ClearTune
4278** cross-over frequency values.
4279**
4280****************************************************************************/
Mauro Carvalho Chehabcfde8922011-07-20 21:01:48 -03004281static u32 FindClearTuneFilter(struct MT2063_Info_t *pInfo, u32 f_in)
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03004282{
Mauro Carvalho Chehabcfde8922011-07-20 21:01:48 -03004283 u32 RFBand;
4284 u32 idx; /* index loop */
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03004285
4286 /*
4287 ** Find RF Band setting
4288 */
4289 RFBand = 31; /* def when f_in > all */
4290 for (idx = 0; idx < 31; ++idx) {
4291 if (pInfo->CTFiltMax[idx] >= f_in) {
4292 RFBand = idx;
4293 break;
4294 }
4295 }
4296 return (RFBand);
4297}
4298
4299/****************************************************************************
4300**
4301** Name: MT2063_Tune
4302**
4303** Description: Change the tuner's tuned frequency to RFin.
4304**
4305** Parameters: h - Open handle to the tuner (from MT2063_Open).
4306** f_in - RF input center frequency (in Hz).
4307**
4308** Returns: status:
4309** MT_OK - No errors
4310** MT_INV_HANDLE - Invalid tuner handle
4311** MT_UPC_UNLOCK - Upconverter PLL unlocked
4312** MT_DNC_UNLOCK - Downconverter PLL unlocked
4313** MT_COMM_ERR - Serial bus communications error
4314** MT_SPUR_CNT_MASK - Count of avoided LO spurs
4315** MT_SPUR_PRESENT - LO spur possible in output
4316** MT_FIN_RANGE - Input freq out of range
4317** MT_FOUT_RANGE - Output freq out of range
4318** MT_UPC_RANGE - Upconverter freq out of range
4319** MT_DNC_RANGE - Downconverter freq out of range
4320**
4321** Dependencies: MUST CALL MT2063_Open BEFORE MT2063_Tune!
4322**
4323** MT_ReadSub - Read data from the two-wire serial bus
4324** MT_WriteSub - Write data to the two-wire serial bus
4325** MT_Sleep - Delay execution for x milliseconds
4326** MT2063_GetLocked - Checks to see if LO1 and LO2 are locked
4327**
4328** Revision History:
4329**
4330** SCR Date Author Description
4331** -------------------------------------------------------------------------
4332** 138 06-19-2007 DAD Ver 1.00: Initial, derived from mt2067_b.
4333** 04-10-2008 PINZ Ver 1.05: Use software-controlled ClearTune
4334** cross-over frequency values.
4335** 175 I 16-06-2008 PINZ Ver 1.16: Add control to avoid US DECT freqs.
4336** 175 I 06-19-2008 RSK Ver 1.17: Refactor DECT control to SpurAvoid.
4337** 06-24-2008 PINZ Ver 1.18: Add Get/SetParam CTFILT_SW
4338**
4339****************************************************************************/
Mauro Carvalho Chehabcfde8922011-07-20 21:01:48 -03004340u32 MT2063_Tune(void *h, u32 f_in)
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03004341{ /* RF input center frequency */
4342 struct MT2063_Info_t *pInfo = (struct MT2063_Info_t *)h;
4343
Mauro Carvalho Chehabcfde8922011-07-20 21:01:48 -03004344 u32 status = MT2063_OK; /* status of operation */
4345 u32 LO1; /* 1st LO register value */
4346 u32 Num1; /* Numerator for LO1 reg. value */
4347 u32 f_IF1; /* 1st IF requested */
4348 u32 LO2; /* 2nd LO register value */
4349 u32 Num2; /* Numerator for LO2 reg. value */
4350 u32 ofLO1, ofLO2; /* last time's LO frequencies */
4351 u32 ofin, ofout; /* last time's I/O frequencies */
4352 u8 fiffc = 0x80; /* FIFF center freq from tuner */
4353 u32 fiffof; /* Offset from FIFF center freq */
4354 const u8 LO1LK = 0x80; /* Mask for LO1 Lock bit */
4355 u8 LO2LK = 0x08; /* Mask for LO2 Lock bit */
4356 u8 val;
4357 u32 RFBand;
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03004358
4359 /* Verify that the handle passed points to a valid tuner */
4360 if (MT2063_IsValidHandle(pInfo) == 0)
4361 return MT2063_INV_HANDLE;
4362
4363 /* Check the input and output frequency ranges */
4364 if ((f_in < MT2063_MIN_FIN_FREQ) || (f_in > MT2063_MAX_FIN_FREQ))
4365 status |= MT2063_FIN_RANGE;
4366
4367 if ((pInfo->AS_Data.f_out < MT2063_MIN_FOUT_FREQ)
4368 || (pInfo->AS_Data.f_out > MT2063_MAX_FOUT_FREQ))
4369 status |= MT2063_FOUT_RANGE;
4370
4371 /*
4372 ** Save original LO1 and LO2 register values
4373 */
4374 ofLO1 = pInfo->AS_Data.f_LO1;
4375 ofLO2 = pInfo->AS_Data.f_LO2;
4376 ofin = pInfo->AS_Data.f_in;
4377 ofout = pInfo->AS_Data.f_out;
4378
4379 /*
4380 ** Find and set RF Band setting
4381 */
4382 if (pInfo->ctfilt_sw == 1) {
4383 val = (pInfo->reg[MT2063_REG_CTUNE_CTRL] | 0x08);
4384 if (pInfo->reg[MT2063_REG_CTUNE_CTRL] != val) {
4385 status |=
4386 MT2063_SetReg(pInfo, MT2063_REG_CTUNE_CTRL, val);
4387 }
4388 val = pInfo->reg[MT2063_REG_CTUNE_OV];
4389 RFBand = FindClearTuneFilter(pInfo, f_in);
4390 pInfo->reg[MT2063_REG_CTUNE_OV] =
Mauro Carvalho Chehabcfde8922011-07-20 21:01:48 -03004391 (u8) ((pInfo->reg[MT2063_REG_CTUNE_OV] & ~0x1F)
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03004392 | RFBand);
4393 if (pInfo->reg[MT2063_REG_CTUNE_OV] != val) {
4394 status |=
4395 MT2063_SetReg(pInfo, MT2063_REG_CTUNE_OV, val);
4396 }
4397 }
4398
4399 /*
4400 ** Read the FIFF Center Frequency from the tuner
4401 */
4402 if (MT2063_NO_ERROR(status)) {
4403 status |=
4404 MT2063_ReadSub(pInfo->hUserData, pInfo->address,
4405 MT2063_REG_FIFFC,
4406 &pInfo->reg[MT2063_REG_FIFFC], 1);
4407 fiffc = pInfo->reg[MT2063_REG_FIFFC];
4408 }
4409 /*
4410 ** Assign in the requested values
4411 */
4412 pInfo->AS_Data.f_in = f_in;
4413 /* Request a 1st IF such that LO1 is on a step size */
4414 pInfo->AS_Data.f_if1_Request =
4415 MT2063_Round_fLO(pInfo->AS_Data.f_if1_Request + f_in,
4416 pInfo->AS_Data.f_LO1_Step,
4417 pInfo->AS_Data.f_ref) - f_in;
4418
4419 /*
4420 ** Calculate frequency settings. f_IF1_FREQ + f_in is the
4421 ** desired LO1 frequency
4422 */
4423 MT2063_ResetExclZones(&pInfo->AS_Data);
4424
4425 f_IF1 = MT2063_ChooseFirstIF(&pInfo->AS_Data);
4426
4427 pInfo->AS_Data.f_LO1 =
4428 MT2063_Round_fLO(f_IF1 + f_in, pInfo->AS_Data.f_LO1_Step,
4429 pInfo->AS_Data.f_ref);
4430
4431 pInfo->AS_Data.f_LO2 =
4432 MT2063_Round_fLO(pInfo->AS_Data.f_LO1 - pInfo->AS_Data.f_out - f_in,
4433 pInfo->AS_Data.f_LO2_Step, pInfo->AS_Data.f_ref);
4434
4435 /*
4436 ** Check for any LO spurs in the output bandwidth and adjust
4437 ** the LO settings to avoid them if needed
4438 */
4439 status |= MT2063_AvoidSpurs(h, &pInfo->AS_Data);
4440 /*
4441 ** MT_AvoidSpurs spurs may have changed the LO1 & LO2 values.
4442 ** Recalculate the LO frequencies and the values to be placed
4443 ** in the tuning registers.
4444 */
4445 pInfo->AS_Data.f_LO1 =
4446 MT2063_CalcLO1Mult(&LO1, &Num1, pInfo->AS_Data.f_LO1,
4447 pInfo->AS_Data.f_LO1_Step, pInfo->AS_Data.f_ref);
4448 pInfo->AS_Data.f_LO2 =
4449 MT2063_Round_fLO(pInfo->AS_Data.f_LO1 - pInfo->AS_Data.f_out - f_in,
4450 pInfo->AS_Data.f_LO2_Step, pInfo->AS_Data.f_ref);
4451 pInfo->AS_Data.f_LO2 =
4452 MT2063_CalcLO2Mult(&LO2, &Num2, pInfo->AS_Data.f_LO2,
4453 pInfo->AS_Data.f_LO2_Step, pInfo->AS_Data.f_ref);
4454
4455 /*
4456 ** Check the upconverter and downconverter frequency ranges
4457 */
4458 if ((pInfo->AS_Data.f_LO1 < MT2063_MIN_UPC_FREQ)
4459 || (pInfo->AS_Data.f_LO1 > MT2063_MAX_UPC_FREQ))
4460 status |= MT2063_UPC_RANGE;
4461 if ((pInfo->AS_Data.f_LO2 < MT2063_MIN_DNC_FREQ)
4462 || (pInfo->AS_Data.f_LO2 > MT2063_MAX_DNC_FREQ))
4463 status |= MT2063_DNC_RANGE;
4464 /* LO2 Lock bit was in a different place for B0 version */
4465 if (pInfo->tuner_id == MT2063_B0)
4466 LO2LK = 0x40;
4467
4468 /*
4469 ** If we have the same LO frequencies and we're already locked,
4470 ** then skip re-programming the LO registers.
4471 */
4472 if ((ofLO1 != pInfo->AS_Data.f_LO1)
4473 || (ofLO2 != pInfo->AS_Data.f_LO2)
4474 || ((pInfo->reg[MT2063_REG_LO_STATUS] & (LO1LK | LO2LK)) !=
4475 (LO1LK | LO2LK))) {
4476 /*
4477 ** Calculate the FIFFOF register value
4478 **
4479 ** IF1_Actual
4480 ** FIFFOF = ------------ - 8 * FIFFC - 4992
4481 ** f_ref/64
4482 */
4483 fiffof =
4484 (pInfo->AS_Data.f_LO1 -
Mauro Carvalho Chehabcfde8922011-07-20 21:01:48 -03004485 f_in) / (pInfo->AS_Data.f_ref / 64) - 8 * (u32) fiffc -
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03004486 4992;
4487 if (fiffof > 0xFF)
4488 fiffof = 0xFF;
4489
4490 /*
4491 ** Place all of the calculated values into the local tuner
4492 ** register fields.
4493 */
4494 if (MT2063_NO_ERROR(status)) {
Mauro Carvalho Chehabcfde8922011-07-20 21:01:48 -03004495 pInfo->reg[MT2063_REG_LO1CQ_1] = (u8) (LO1 & 0xFF); /* DIV1q */
4496 pInfo->reg[MT2063_REG_LO1CQ_2] = (u8) (Num1 & 0x3F); /* NUM1q */
4497 pInfo->reg[MT2063_REG_LO2CQ_1] = (u8) (((LO2 & 0x7F) << 1) /* DIV2q */
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03004498 |(Num2 >> 12)); /* NUM2q (hi) */
Mauro Carvalho Chehabcfde8922011-07-20 21:01:48 -03004499 pInfo->reg[MT2063_REG_LO2CQ_2] = (u8) ((Num2 & 0x0FF0) >> 4); /* NUM2q (mid) */
4500 pInfo->reg[MT2063_REG_LO2CQ_3] = (u8) (0xE0 | (Num2 & 0x000F)); /* NUM2q (lo) */
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03004501
4502 /*
4503 ** Now write out the computed register values
4504 ** IMPORTANT: There is a required order for writing
4505 ** (0x05 must follow all the others).
4506 */
4507 status |= MT2063_WriteSub(pInfo->hUserData, pInfo->address, MT2063_REG_LO1CQ_1, &pInfo->reg[MT2063_REG_LO1CQ_1], 5); /* 0x01 - 0x05 */
4508 if (pInfo->tuner_id == MT2063_B0) {
4509 /* Re-write the one-shot bits to trigger the tune operation */
4510 status |= MT2063_WriteSub(pInfo->hUserData, pInfo->address, MT2063_REG_LO2CQ_3, &pInfo->reg[MT2063_REG_LO2CQ_3], 1); /* 0x05 */
4511 }
4512 /* Write out the FIFF offset only if it's changing */
4513 if (pInfo->reg[MT2063_REG_FIFF_OFFSET] !=
Mauro Carvalho Chehabcfde8922011-07-20 21:01:48 -03004514 (u8) fiffof) {
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03004515 pInfo->reg[MT2063_REG_FIFF_OFFSET] =
Mauro Carvalho Chehabcfde8922011-07-20 21:01:48 -03004516 (u8) fiffof;
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03004517 status |=
4518 MT2063_WriteSub(pInfo->hUserData,
4519 pInfo->address,
4520 MT2063_REG_FIFF_OFFSET,
4521 &pInfo->
4522 reg[MT2063_REG_FIFF_OFFSET],
4523 1);
4524 }
4525 }
4526
4527 /*
4528 ** Check for LO's locking
4529 */
4530
4531 if (MT2063_NO_ERROR(status)) {
4532 status |= MT2063_GetLocked(h);
4533 }
4534 /*
4535 ** If we locked OK, assign calculated data to MT2063_Info_t structure
4536 */
4537 if (MT2063_NO_ERROR(status)) {
4538 pInfo->f_IF1_actual = pInfo->AS_Data.f_LO1 - f_in;
4539 }
4540 }
4541
4542 return (status);
4543}
4544
Mauro Carvalho Chehabcfde8922011-07-20 21:01:48 -03004545u32 MT_Tune_atv(void *h, u32 f_in, u32 bw_in,
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03004546 enum MTTune_atv_standard tv_type)
4547{
4548
Mauro Carvalho Chehabcfde8922011-07-20 21:01:48 -03004549 u32 status = MT2063_OK;
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03004550 struct MT2063_Info_t *pInfo = (struct MT2063_Info_t *)h;
4551 struct dvb_frontend *fe = (struct dvb_frontend *)pInfo->hUserData;
4552 struct mt2063_state *state = fe->tuner_priv;
4553
Mauro Carvalho Chehabcfde8922011-07-20 21:01:48 -03004554 s32 pict_car = 0;
4555 s32 pict2chanb_vsb = 0;
4556 s32 pict2chanb_snd = 0;
4557 s32 pict2snd1 = 0;
4558 s32 pict2snd2 = 0;
4559 s32 ch_bw = 0;
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03004560
Mauro Carvalho Chehabcfde8922011-07-20 21:01:48 -03004561 s32 if_mid = 0;
4562 s32 rcvr_mode = 0;
4563 u32 mode_get = 0;
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03004564
4565 switch (tv_type) {
4566 case MTTUNEA_PAL_B:{
4567 pict_car = 38900000;
4568 ch_bw = 8000000;
4569 pict2chanb_vsb = -1250000;
4570 pict2snd1 = 5500000;
4571 pict2snd2 = 5742000;
4572 rcvr_mode = 1;
4573 break;
4574 }
4575 case MTTUNEA_PAL_G:{
4576 pict_car = 38900000;
4577 ch_bw = 7000000;
4578 pict2chanb_vsb = -1250000;
4579 pict2snd1 = 5500000;
4580 pict2snd2 = 0;
4581 rcvr_mode = 1;
4582 break;
4583 }
4584 case MTTUNEA_PAL_I:{
4585 pict_car = 38900000;
4586 ch_bw = 8000000;
4587 pict2chanb_vsb = -1250000;
4588 pict2snd1 = 6000000;
4589 pict2snd2 = 0;
4590 rcvr_mode = 1;
4591 break;
4592 }
4593 case MTTUNEA_PAL_L:{
4594 pict_car = 38900000;
4595 ch_bw = 8000000;
4596 pict2chanb_vsb = -1250000;
4597 pict2snd1 = 6500000;
4598 pict2snd2 = 0;
4599 rcvr_mode = 1;
4600 break;
4601 }
4602 case MTTUNEA_PAL_MN:{
4603 pict_car = 38900000;
4604 ch_bw = 6000000;
4605 pict2chanb_vsb = -1250000;
4606 pict2snd1 = 4500000;
4607 pict2snd2 = 0;
4608 rcvr_mode = 1;
4609 break;
4610 }
4611 case MTTUNEA_PAL_DK:{
4612 pict_car = 38900000;
4613 ch_bw = 8000000;
4614 pict2chanb_vsb = -1250000;
4615 pict2snd1 = 6500000;
4616 pict2snd2 = 0;
4617 rcvr_mode = 1;
4618 break;
4619 }
4620 case MTTUNEA_DIGITAL:{
4621 pict_car = 36125000;
4622 ch_bw = 8000000;
4623 pict2chanb_vsb = -(ch_bw / 2);
4624 pict2snd1 = 0;
4625 pict2snd2 = 0;
4626 rcvr_mode = 2;
4627 break;
4628 }
4629 case MTTUNEA_FMRADIO:{
4630 pict_car = 38900000;
4631 ch_bw = 8000000;
4632 pict2chanb_vsb = -(ch_bw / 2);
4633 pict2snd1 = 0;
4634 pict2snd2 = 0;
4635 rcvr_mode = 4;
4636 //f_in -= 2900000;
4637 break;
4638 }
4639 case MTTUNEA_DVBC:{
4640 pict_car = 36125000;
4641 ch_bw = 8000000;
4642 pict2chanb_vsb = -(ch_bw / 2);
4643 pict2snd1 = 0;
4644 pict2snd2 = 0;
4645 rcvr_mode = MT2063_CABLE_QAM;
4646 break;
4647 }
4648 case MTTUNEA_DVBT:{
4649 pict_car = 36125000;
4650 ch_bw = bw_in; //8000000
4651 pict2chanb_vsb = -(ch_bw / 2);
4652 pict2snd1 = 0;
4653 pict2snd2 = 0;
4654 rcvr_mode = MT2063_OFFAIR_COFDM;
4655 break;
4656 }
4657 case MTTUNEA_UNKNOWN:
4658 break;
4659 default:
4660 break;
4661 }
4662
4663 pict2chanb_snd = pict2chanb_vsb - ch_bw;
4664 if_mid = pict_car - (pict2chanb_vsb + (ch_bw / 2));
4665
4666 status |= MT2063_SetParam(h, MT2063_STEPSIZE, 125000);
4667 status |= MT2063_SetParam(h, MT2063_OUTPUT_FREQ, if_mid);
4668 status |= MT2063_SetParam(h, MT2063_OUTPUT_BW, ch_bw);
4669 status |= MT2063_GetParam(h, MT2063_RCVR_MODE, &mode_get);
4670
4671 status |= MT2063_SetParam(h, MT2063_RCVR_MODE, rcvr_mode);
4672 status |= MT2063_Tune(h, (f_in + (pict2chanb_vsb + (ch_bw / 2))));
4673 status |= MT2063_GetParam(h, MT2063_RCVR_MODE, &mode_get);
4674
Mauro Carvalho Chehabcfde8922011-07-20 21:01:48 -03004675 return (u32) status;
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03004676}
4677
4678static int mt2063_init(struct dvb_frontend *fe)
4679{
Mauro Carvalho Chehabcfde8922011-07-20 21:01:48 -03004680 u32 status = MT2063_ERROR;
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03004681 struct mt2063_state *state = fe->tuner_priv;
4682
4683 status = MT2063_Open(0xC0, &(state->MT2063_ht), fe);
4684 status |= MT2063_SoftwareShutdown(state->MT2063_ht, 1);
4685 status |= MT2063_ClearPowerMaskBits(state->MT2063_ht, MT2063_ALL_SD);
4686
4687 if (MT2063_OK != status) {
4688 printk("%s %d error status = 0x%x!!\n", __func__, __LINE__,
4689 status);
4690 return -1;
4691 }
4692
4693 return 0;
4694}
4695
4696static int mt2063_sleep(struct dvb_frontend *fe)
4697{
4698 /* TODO: power down */
4699 return 0;
4700}
4701
4702static int mt2063_get_status(struct dvb_frontend *fe, u32 * status)
4703{
4704 int rc = 0;
4705
4706 //get tuner lock status
4707
4708 return rc;
4709}
4710
4711static int mt2063_get_state(struct dvb_frontend *fe,
4712 enum tuner_param param, struct tuner_state *state)
4713{
4714 struct mt2063_state *mt2063State = fe->tuner_priv;
4715
Mauro Carvalho Chehab223c7b02011-07-20 19:48:59 -03004716 switch (param) {
4717 case DVBFE_TUNER_FREQUENCY:
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03004718 //get frequency
Mauro Carvalho Chehab223c7b02011-07-20 19:48:59 -03004719 break;
4720 case DVBFE_TUNER_TUNERSTEP:
4721 break;
4722 case DVBFE_TUNER_IFFREQ:
4723 break;
4724 case DVBFE_TUNER_BANDWIDTH:
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03004725 //get bandwidth
Mauro Carvalho Chehab223c7b02011-07-20 19:48:59 -03004726 break;
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03004727 case DVBFE_TUNER_REFCLOCK:
4728 state->refclock =
Mauro Carvalho Chehabcfde8922011-07-20 21:01:48 -03004729 (u32)
4730 MT2063_GetLocked((void *) (mt2063State->MT2063_ht));
Mauro Carvalho Chehab223c7b02011-07-20 19:48:59 -03004731 break;
4732 default:
4733 break;
4734 }
4735
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03004736 return (int)state->refclock;
4737}
4738
4739static int mt2063_set_state(struct dvb_frontend *fe,
4740 enum tuner_param param, struct tuner_state *state)
Mauro Carvalho Chehab223c7b02011-07-20 19:48:59 -03004741{
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03004742 struct mt2063_state *mt2063State = fe->tuner_priv;
Mauro Carvalho Chehabcfde8922011-07-20 21:01:48 -03004743 u32 status = MT2063_OK;
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03004744
Mauro Carvalho Chehab223c7b02011-07-20 19:48:59 -03004745 switch (param) {
4746 case DVBFE_TUNER_FREQUENCY:
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03004747 //set frequency
4748
4749 status =
Mauro Carvalho Chehabcfde8922011-07-20 21:01:48 -03004750 MT_Tune_atv((void *) (mt2063State->MT2063_ht),
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03004751 state->frequency, state->bandwidth,
4752 mt2063State->tv_type);
4753
4754 mt2063State->frequency = state->frequency;
Mauro Carvalho Chehab223c7b02011-07-20 19:48:59 -03004755 break;
4756 case DVBFE_TUNER_TUNERSTEP:
4757 break;
4758 case DVBFE_TUNER_IFFREQ:
4759 break;
4760 case DVBFE_TUNER_BANDWIDTH:
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03004761 //set bandwidth
4762 mt2063State->bandwidth = state->bandwidth;
Mauro Carvalho Chehab223c7b02011-07-20 19:48:59 -03004763 break;
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03004764 case DVBFE_TUNER_REFCLOCK:
4765
4766 break;
4767 case DVBFE_TUNER_OPEN:
4768 status = MT2063_Open(MT2063_I2C, &(mt2063State->MT2063_ht), fe);
4769 break;
4770 case DVBFE_TUNER_SOFTWARE_SHUTDOWN:
4771 status = MT2063_SoftwareShutdown(mt2063State->MT2063_ht, 1);
4772 break;
4773 case DVBFE_TUNER_CLEAR_POWER_MASKBITS:
4774 status =
4775 MT2063_ClearPowerMaskBits(mt2063State->MT2063_ht,
4776 MT2063_ALL_SD);
4777 break;
Mauro Carvalho Chehab223c7b02011-07-20 19:48:59 -03004778 default:
4779 break;
4780 }
4781
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03004782 return (int)status;
4783}
4784
4785static int mt2063_release(struct dvb_frontend *fe)
Mauro Carvalho Chehab223c7b02011-07-20 19:48:59 -03004786{
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03004787 struct mt2063_state *state = fe->tuner_priv;
Mauro Carvalho Chehab223c7b02011-07-20 19:48:59 -03004788
4789 fe->tuner_priv = NULL;
4790 kfree(state);
4791
4792 return 0;
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03004793}
Mauro Carvalho Chehab223c7b02011-07-20 19:48:59 -03004794
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03004795static struct dvb_tuner_ops mt2063_ops = {
4796 .info = {
4797 .name = "MT2063 Silicon Tuner",
4798 .frequency_min = 45000000,
4799 .frequency_max = 850000000,
4800 .frequency_step = 0,
4801 },
4802
4803 .init = mt2063_init,
4804 .sleep = mt2063_sleep,
4805 .get_status = mt2063_get_status,
4806 .get_state = mt2063_get_state,
4807 .set_state = mt2063_set_state,
4808 .release = mt2063_release
Mauro Carvalho Chehab223c7b02011-07-20 19:48:59 -03004809};
4810
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03004811struct dvb_frontend *mt2063_attach(struct dvb_frontend *fe,
4812 struct mt2063_config *config,
4813 struct i2c_adapter *i2c)
Mauro Carvalho Chehab223c7b02011-07-20 19:48:59 -03004814{
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03004815 struct mt2063_state *state = NULL;
Mauro Carvalho Chehab223c7b02011-07-20 19:48:59 -03004816
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03004817 state = kzalloc(sizeof(struct mt2063_state), GFP_KERNEL);
Mauro Carvalho Chehab223c7b02011-07-20 19:48:59 -03004818 if (state == NULL)
4819 goto error;
4820
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03004821 state->config = config;
4822 state->i2c = i2c;
4823 state->frontend = fe;
4824 state->reference = config->refclock / 1000; /* kHz */
Mauro Carvalho Chehabcfde8922011-07-20 21:01:48 -03004825 state->MT2063_init = false;
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03004826 fe->tuner_priv = state;
4827 fe->ops.tuner_ops = mt2063_ops;
Mauro Carvalho Chehab223c7b02011-07-20 19:48:59 -03004828
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03004829 printk("%s: Attaching MT2063 \n", __func__);
Mauro Carvalho Chehab223c7b02011-07-20 19:48:59 -03004830 return fe;
4831
4832error:
4833 kfree(state);
4834 return NULL;
4835}
4836
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03004837EXPORT_SYMBOL(mt2063_attach);
Mauro Carvalho Chehab223c7b02011-07-20 19:48:59 -03004838MODULE_PARM_DESC(verbose, "Set Verbosity level");
4839
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03004840MODULE_AUTHOR("Henry");
4841MODULE_DESCRIPTION("MT2063 Silicon tuner");
4842MODULE_LICENSE("GPL");