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