[media] mt2063: Remove setParm/getParm abstraction layer
[deliverable/linux.git] / drivers / media / common / tuners / mt2063.c
CommitLineData
223c7b05
MCC
1#include <linux/init.h>
2#include <linux/kernel.h>
3#include <linux/module.h>
4#include <linux/string.h>
0e301442 5
0e301442
MCC
6#include "mt2063.h"
7
223c7b05 8static unsigned int verbose;
0e301442
MCC
9module_param(verbose, int, 0644);
10
31e67fae 11/* positive error codes used internally */
29a0a4fe 12
fdf77a4f 13/* Info: Unavoidable LO-related spur may be present in the output */
29a0a4fe 14#define MT2063_SPUR_PRESENT_ERR (0x00800000)
6d3d748a
MCC
15
16/* Info: Mask of bits used for # of LO-related spurs that were avoided during tuning */
17#define MT2063_SPUR_CNT_MASK (0x001f0000)
18#define MT2063_SPUR_SHIFT (16)
19
6d3d748a
MCC
20/* Info: Upconverter frequency is out of range (may be reason for MT_UPC_UNLOCK) */
21#define MT2063_UPC_RANGE (0x04000000)
22
23/* Info: Downconverter frequency is out of range (may be reason for MT_DPC_UNLOCK) */
24#define MT2063_DNC_RANGE (0x08000000)
25
6d3d748a
MCC
26/*
27 * Constant defining the version of the following structure
28 * and therefore the API for this code.
29 *
30 * When compiling the tuner driver, the preprocessor will
31 * check against this version number to make sure that
32 * it matches the version that the tuner driver knows about.
33 */
6d3d748a
MCC
34
35/* DECT Frequency Avoidance */
36#define MT2063_DECT_AVOID_US_FREQS 0x00000001
37
38#define MT2063_DECT_AVOID_EURO_FREQS 0x00000002
39
40#define MT2063_EXCLUDE_US_DECT_FREQUENCIES(s) (((s) & MT2063_DECT_AVOID_US_FREQS) != 0)
41
42#define MT2063_EXCLUDE_EURO_DECT_FREQUENCIES(s) (((s) & MT2063_DECT_AVOID_EURO_FREQS) != 0)
43
44enum MT2063_DECT_Avoid_Type {
45 MT2063_NO_DECT_AVOIDANCE = 0, /* Do not create DECT exclusion zones. */
46 MT2063_AVOID_US_DECT = MT2063_DECT_AVOID_US_FREQS, /* Avoid US DECT frequencies. */
47 MT2063_AVOID_EURO_DECT = MT2063_DECT_AVOID_EURO_FREQS, /* Avoid European DECT frequencies. */
48 MT2063_AVOID_BOTH /* Avoid both regions. Not typically used. */
49};
50
51#define MT2063_MAX_ZONES 48
52
6d3d748a
MCC
53struct MT2063_ExclZone_t {
54 u32 min_;
55 u32 max_;
56 struct MT2063_ExclZone_t *next_;
57};
58
59/*
60 * Structure of data needed for Spur Avoidance
61 */
62struct MT2063_AvoidSpursData_t {
6d3d748a
MCC
63 u32 f_ref;
64 u32 f_in;
65 u32 f_LO1;
66 u32 f_if1_Center;
67 u32 f_if1_Request;
68 u32 f_if1_bw;
69 u32 f_LO2;
70 u32 f_out;
71 u32 f_out_bw;
72 u32 f_LO1_Step;
73 u32 f_LO2_Step;
74 u32 f_LO1_FracN_Avoid;
75 u32 f_LO2_FracN_Avoid;
76 u32 f_zif_bw;
77 u32 f_min_LO_Separation;
78 u32 maxH1;
79 u32 maxH2;
80 enum MT2063_DECT_Avoid_Type avoidDECT;
81 u32 bSpurPresent;
82 u32 bSpurAvoided;
83 u32 nSpursFound;
84 u32 nZones;
85 struct MT2063_ExclZone_t *freeZones;
86 struct MT2063_ExclZone_t *usedZones;
87 struct MT2063_ExclZone_t MT2063_ExclZones[MT2063_MAX_ZONES];
88};
89
6d3d748a
MCC
90/*
91 * Parameter for function MT2063_SetPowerMask that specifies the power down
92 * of various sections of the MT2063.
93 */
94enum MT2063_Mask_Bits {
95 MT2063_REG_SD = 0x0040, /* Shutdown regulator */
96 MT2063_SRO_SD = 0x0020, /* Shutdown SRO */
97 MT2063_AFC_SD = 0x0010, /* Shutdown AFC A/D */
98 MT2063_PD_SD = 0x0002, /* Enable power detector shutdown */
99 MT2063_PDADC_SD = 0x0001, /* Enable power detector A/D shutdown */
100 MT2063_VCO_SD = 0x8000, /* Enable VCO shutdown */
101 MT2063_LTX_SD = 0x4000, /* Enable LTX shutdown */
102 MT2063_LT1_SD = 0x2000, /* Enable LT1 shutdown */
103 MT2063_LNA_SD = 0x1000, /* Enable LNA shutdown */
104 MT2063_UPC_SD = 0x0800, /* Enable upconverter shutdown */
105 MT2063_DNC_SD = 0x0400, /* Enable downconverter shutdown */
106 MT2063_VGA_SD = 0x0200, /* Enable VGA shutdown */
107 MT2063_AMP_SD = 0x0100, /* Enable AMP shutdown */
108 MT2063_ALL_SD = 0xFF73, /* All shutdown bits for this tuner */
109 MT2063_NONE_SD = 0x0000 /* No shutdown bits */
110};
111
6d3d748a
MCC
112/*
113 * Parameter for selecting tuner mode
114 */
115enum MT2063_RCVR_MODES {
116 MT2063_CABLE_QAM = 0, /* Digital cable */
117 MT2063_CABLE_ANALOG, /* Analog cable */
118 MT2063_OFFAIR_COFDM, /* Digital offair */
119 MT2063_OFFAIR_COFDM_SAWLESS, /* Digital offair without SAW */
120 MT2063_OFFAIR_ANALOG, /* Analog offair */
121 MT2063_OFFAIR_8VSB, /* Analog offair */
122 MT2063_NUM_RCVR_MODES
123};
124
125/*
126 * Possible values for MT2063_DNC_OUTPUT
127 */
128enum MT2063_DNC_Output_Enable {
129 MT2063_DNC_NONE = 0,
130 MT2063_DNC_1,
131 MT2063_DNC_2,
132 MT2063_DNC_BOTH
133};
134
135/*
136** Two-wire serial bus subaddresses of the tuner registers.
137** Also known as the tuner's register addresses.
138*/
139enum MT2063_Register_Offsets {
140 MT2063_REG_PART_REV = 0, /* 0x00: Part/Rev Code */
141 MT2063_REG_LO1CQ_1, /* 0x01: LO1C Queued Byte 1 */
142 MT2063_REG_LO1CQ_2, /* 0x02: LO1C Queued Byte 2 */
143 MT2063_REG_LO2CQ_1, /* 0x03: LO2C Queued Byte 1 */
144 MT2063_REG_LO2CQ_2, /* 0x04: LO2C Queued Byte 2 */
145 MT2063_REG_LO2CQ_3, /* 0x05: LO2C Queued Byte 3 */
146 MT2063_REG_RSVD_06, /* 0x06: Reserved */
147 MT2063_REG_LO_STATUS, /* 0x07: LO Status */
148 MT2063_REG_FIFFC, /* 0x08: FIFF Center */
149 MT2063_REG_CLEARTUNE, /* 0x09: ClearTune Filter */
150 MT2063_REG_ADC_OUT, /* 0x0A: ADC_OUT */
151 MT2063_REG_LO1C_1, /* 0x0B: LO1C Byte 1 */
152 MT2063_REG_LO1C_2, /* 0x0C: LO1C Byte 2 */
153 MT2063_REG_LO2C_1, /* 0x0D: LO2C Byte 1 */
154 MT2063_REG_LO2C_2, /* 0x0E: LO2C Byte 2 */
155 MT2063_REG_LO2C_3, /* 0x0F: LO2C Byte 3 */
156 MT2063_REG_RSVD_10, /* 0x10: Reserved */
157 MT2063_REG_PWR_1, /* 0x11: PWR Byte 1 */
158 MT2063_REG_PWR_2, /* 0x12: PWR Byte 2 */
159 MT2063_REG_TEMP_STATUS, /* 0x13: Temp Status */
160 MT2063_REG_XO_STATUS, /* 0x14: Crystal Status */
161 MT2063_REG_RF_STATUS, /* 0x15: RF Attn Status */
162 MT2063_REG_FIF_STATUS, /* 0x16: FIF Attn Status */
163 MT2063_REG_LNA_OV, /* 0x17: LNA Attn Override */
164 MT2063_REG_RF_OV, /* 0x18: RF Attn Override */
165 MT2063_REG_FIF_OV, /* 0x19: FIF Attn Override */
166 MT2063_REG_LNA_TGT, /* 0x1A: Reserved */
167 MT2063_REG_PD1_TGT, /* 0x1B: Pwr Det 1 Target */
168 MT2063_REG_PD2_TGT, /* 0x1C: Pwr Det 2 Target */
169 MT2063_REG_RSVD_1D, /* 0x1D: Reserved */
170 MT2063_REG_RSVD_1E, /* 0x1E: Reserved */
171 MT2063_REG_RSVD_1F, /* 0x1F: Reserved */
172 MT2063_REG_RSVD_20, /* 0x20: Reserved */
173 MT2063_REG_BYP_CTRL, /* 0x21: Bypass Control */
174 MT2063_REG_RSVD_22, /* 0x22: Reserved */
175 MT2063_REG_RSVD_23, /* 0x23: Reserved */
176 MT2063_REG_RSVD_24, /* 0x24: Reserved */
177 MT2063_REG_RSVD_25, /* 0x25: Reserved */
178 MT2063_REG_RSVD_26, /* 0x26: Reserved */
179 MT2063_REG_RSVD_27, /* 0x27: Reserved */
180 MT2063_REG_FIFF_CTRL, /* 0x28: FIFF Control */
181 MT2063_REG_FIFF_OFFSET, /* 0x29: FIFF Offset */
182 MT2063_REG_CTUNE_CTRL, /* 0x2A: Reserved */
183 MT2063_REG_CTUNE_OV, /* 0x2B: Reserved */
184 MT2063_REG_CTRL_2C, /* 0x2C: Reserved */
185 MT2063_REG_FIFF_CTRL2, /* 0x2D: Fiff Control */
186 MT2063_REG_RSVD_2E, /* 0x2E: Reserved */
187 MT2063_REG_DNC_GAIN, /* 0x2F: DNC Control */
188 MT2063_REG_VGA_GAIN, /* 0x30: VGA Gain Ctrl */
189 MT2063_REG_RSVD_31, /* 0x31: Reserved */
190 MT2063_REG_TEMP_SEL, /* 0x32: Temperature Selection */
191 MT2063_REG_RSVD_33, /* 0x33: Reserved */
192 MT2063_REG_RSVD_34, /* 0x34: Reserved */
193 MT2063_REG_RSVD_35, /* 0x35: Reserved */
194 MT2063_REG_RSVD_36, /* 0x36: Reserved */
195 MT2063_REG_RSVD_37, /* 0x37: Reserved */
196 MT2063_REG_RSVD_38, /* 0x38: Reserved */
197 MT2063_REG_RSVD_39, /* 0x39: Reserved */
198 MT2063_REG_RSVD_3A, /* 0x3A: Reserved */
199 MT2063_REG_RSVD_3B, /* 0x3B: Reserved */
200 MT2063_REG_RSVD_3C, /* 0x3C: Reserved */
201 MT2063_REG_END_REGS
202};
203
6d3d748a
MCC
204enum MTTune_atv_standard {
205 MTTUNEA_UNKNOWN = 0,
206 MTTUNEA_PAL_B,
207 MTTUNEA_PAL_G,
208 MTTUNEA_PAL_I,
209 MTTUNEA_PAL_L,
210 MTTUNEA_PAL_MN,
211 MTTUNEA_PAL_DK,
212 MTTUNEA_DIGITAL,
213 MTTUNEA_FMRADIO,
214 MTTUNEA_DVBC,
215 MTTUNEA_DVBT
216};
217
218
219struct mt2063_state {
220 struct i2c_adapter *i2c;
221
222 const struct mt2063_config *config;
223 struct dvb_tuner_ops ops;
224 struct dvb_frontend *frontend;
225 struct tuner_state status;
6d3d748a
MCC
226
227 enum MTTune_atv_standard tv_type;
228 u32 frequency;
229 u32 srate;
230 u32 bandwidth;
231 u32 reference;
51f0f7b3
MCC
232
233 u32 tuner_id;
234 struct MT2063_AvoidSpursData_t AS_Data;
235 u32 f_IF1_actual;
236 u32 rcvr_mode;
237 u32 ctfilt_sw;
238 u32 CTFiltMax[31];
239 u32 num_regs;
240 u8 reg[MT2063_REG_END_REGS];
6d3d748a 241};
0ff48432 242
bf97555e
MCC
243/* Prototypes */
244static void MT2063_AddExclZone(struct MT2063_AvoidSpursData_t *pAS_Info,
245 u32 f_min, u32 f_max);
dcd52d20 246static u32 MT2063_SetReg(struct mt2063_state *state, u8 reg, u8 val);
8c64f932
MCC
247static u32 MT2063_SoftwareShutdown(struct mt2063_state *state, u8 Shutdown);
248static u32 MT2063_ClearPowerMaskBits(struct mt2063_state *state, enum MT2063_Mask_Bits Bits);
249
bf97555e 250
3d49700f
MCC
251/*
252 * Ancillary routines visible outside mt2063
253 */
f867695a 254unsigned int tuner_MT2063_SoftwareShutdown(struct dvb_frontend *fe)
0ff48432 255{
8c64f932 256 struct mt2063_state *state = fe->tuner_priv;
0ff48432
MCC
257 int err = 0;
258
3d49700f
MCC
259 err = MT2063_SoftwareShutdown(state, 1);
260 if (err < 0)
261 printk(KERN_ERR "%s: Couldn't shutdown\n", __func__);
0ff48432
MCC
262
263 return err;
264}
3d49700f 265EXPORT_SYMBOL_GPL(tuner_MT2063_SoftwareShutdown);
0ff48432 266
f867695a 267unsigned int tuner_MT2063_ClearPowerMaskBits(struct dvb_frontend *fe)
0ff48432 268{
8c64f932 269 struct mt2063_state *state = fe->tuner_priv;
0ff48432
MCC
270 int err = 0;
271
3d49700f
MCC
272 err = MT2063_ClearPowerMaskBits(state, MT2063_ALL_SD);
273 if (err < 0)
274 printk(KERN_ERR "%s: Invalid parameter\n", __func__);
0ff48432
MCC
275
276 return err;
277}
3d49700f 278EXPORT_SYMBOL_GPL(tuner_MT2063_ClearPowerMaskBits);
0ff48432 279
e1de3d18
MCC
280/*
281 * mt2063_write - Write data into the I2C bus
282 */
283static u32 mt2063_write(struct mt2063_state *state,
284 u8 reg, u8 *data, u32 len)
0e301442 285{
e1de3d18 286 struct dvb_frontend *fe = state->frontend;
0e301442 287 int ret;
e1de3d18 288 u8 buf[60];
0e301442
MCC
289 struct i2c_msg msg = {
290 .addr = state->config->tuner_address,
291 .flags = 0,
292 .buf = buf,
293 .len = len + 1
294 };
295
e1de3d18 296 msg.buf[0] = reg;
0e301442
MCC
297 memcpy(msg.buf + 1, data, len);
298
e1de3d18 299 fe->ops.i2c_gate_ctrl(fe, 1);
0e301442 300 ret = i2c_transfer(state->i2c, &msg, 1);
e1de3d18 301 fe->ops.i2c_gate_ctrl(fe, 0);
0e301442
MCC
302
303 if (ret < 0)
304 printk("mt2063_writeregs error ret=%d\n", ret);
305
306 return ret;
307}
308
e1de3d18
MCC
309/*
310 * mt2063_read - Read data from the I2C bus
311 */
312static u32 mt2063_read(struct mt2063_state *state,
51f0f7b3 313 u8 subAddress, u8 *pData, u32 cnt)
0e301442 314{
51f0f7b3
MCC
315 u32 status = 0; /* Status to be returned */
316 struct dvb_frontend *fe = state->frontend;
317 u32 i = 0;
318
e1de3d18 319 fe->ops.i2c_gate_ctrl(fe, 1);
0e301442
MCC
320
321 for (i = 0; i < cnt; i++) {
e1de3d18
MCC
322 int ret;
323 u8 b0[] = { subAddress + i };
324 struct i2c_msg msg[] = {
325 {
326 .addr = state->config->tuner_address,
327 .flags = I2C_M_RD,
328 .buf = b0,
329 .len = 1
330 }, {
331 .addr = state->config->tuner_address,
332 .flags = I2C_M_RD,
333 .buf = pData + 1,
334 .len = 1
335 }
336 };
337
338 ret = i2c_transfer(state->i2c, msg, 2);
339 if (ret < 0)
0e301442 340 break;
0e301442 341 }
e1de3d18 342 fe->ops.i2c_gate_ctrl(fe, 0);
0e301442
MCC
343 return (status);
344}
345
e930b3a0
MCC
346/*
347 * FIXME: Is this really needed?
348 */
f867695a 349static int MT2063_Sleep(struct dvb_frontend *fe)
0e301442
MCC
350{
351 /*
352 ** ToDo: Add code here to implement a OS blocking
353 ** for a period of "nMinDelayTime" milliseconds.
354 */
f867695a
MCC
355 msleep(10);
356
357 return 0;
0e301442
MCC
358}
359
e930b3a0
MCC
360/*
361 * Microtune spur avoidance
362 */
0e301442
MCC
363
364/* Implement ceiling, floor functions. */
365#define ceil(n, d) (((n) < 0) ? (-((-(n))/(d))) : (n)/(d) + ((n)%(d) != 0))
0e301442 366#define floor(n, d) (((n) < 0) ? (-((-(n))/(d))) - ((n)%(d) != 0) : (n)/(d))
0e301442
MCC
367
368struct MT2063_FIFZone_t {
cfde8925
MCC
369 s32 min_;
370 s32 max_;
0e301442
MCC
371};
372
0e301442
MCC
373/*
374** Reset all exclusion zones.
375** Add zones to protect the PLL FracN regions near zero
376**
377** N/A I 06-17-2008 RSK Ver 1.19: Refactoring avoidance of DECT
378** frequencies into MT_ResetExclZones().
379*/
bf97555e 380static void MT2063_ResetExclZones(struct MT2063_AvoidSpursData_t *pAS_Info)
0e301442 381{
cfde8925 382 u32 center;
0e301442
MCC
383
384 pAS_Info->nZones = 0; /* this clears the used list */
385 pAS_Info->usedZones = NULL; /* reset ptr */
386 pAS_Info->freeZones = NULL; /* reset ptr */
387
388 center =
389 pAS_Info->f_ref *
390 ((pAS_Info->f_if1_Center - pAS_Info->f_if1_bw / 2 +
391 pAS_Info->f_in) / pAS_Info->f_ref) - pAS_Info->f_in;
392 while (center <
393 pAS_Info->f_if1_Center + pAS_Info->f_if1_bw / 2 +
394 pAS_Info->f_LO1_FracN_Avoid) {
395 /* Exclude LO1 FracN */
396 MT2063_AddExclZone(pAS_Info,
397 center - pAS_Info->f_LO1_FracN_Avoid,
398 center - 1);
399 MT2063_AddExclZone(pAS_Info, center + 1,
400 center + pAS_Info->f_LO1_FracN_Avoid);
401 center += pAS_Info->f_ref;
402 }
403
404 center =
405 pAS_Info->f_ref *
406 ((pAS_Info->f_if1_Center - pAS_Info->f_if1_bw / 2 -
407 pAS_Info->f_out) / pAS_Info->f_ref) + pAS_Info->f_out;
408 while (center <
409 pAS_Info->f_if1_Center + pAS_Info->f_if1_bw / 2 +
410 pAS_Info->f_LO2_FracN_Avoid) {
411 /* Exclude LO2 FracN */
412 MT2063_AddExclZone(pAS_Info,
413 center - pAS_Info->f_LO2_FracN_Avoid,
414 center - 1);
415 MT2063_AddExclZone(pAS_Info, center + 1,
416 center + pAS_Info->f_LO2_FracN_Avoid);
417 center += pAS_Info->f_ref;
418 }
419
420 if (MT2063_EXCLUDE_US_DECT_FREQUENCIES(pAS_Info->avoidDECT)) {
421 /* Exclude LO1 values that conflict with DECT channels */
422 MT2063_AddExclZone(pAS_Info, 1920836000 - pAS_Info->f_in, 1922236000 - pAS_Info->f_in); /* Ctr = 1921.536 */
423 MT2063_AddExclZone(pAS_Info, 1922564000 - pAS_Info->f_in, 1923964000 - pAS_Info->f_in); /* Ctr = 1923.264 */
424 MT2063_AddExclZone(pAS_Info, 1924292000 - pAS_Info->f_in, 1925692000 - pAS_Info->f_in); /* Ctr = 1924.992 */
425 MT2063_AddExclZone(pAS_Info, 1926020000 - pAS_Info->f_in, 1927420000 - pAS_Info->f_in); /* Ctr = 1926.720 */
426 MT2063_AddExclZone(pAS_Info, 1927748000 - pAS_Info->f_in, 1929148000 - pAS_Info->f_in); /* Ctr = 1928.448 */
427 }
428
429 if (MT2063_EXCLUDE_EURO_DECT_FREQUENCIES(pAS_Info->avoidDECT)) {
430 MT2063_AddExclZone(pAS_Info, 1896644000 - pAS_Info->f_in, 1898044000 - pAS_Info->f_in); /* Ctr = 1897.344 */
431 MT2063_AddExclZone(pAS_Info, 1894916000 - pAS_Info->f_in, 1896316000 - pAS_Info->f_in); /* Ctr = 1895.616 */
432 MT2063_AddExclZone(pAS_Info, 1893188000 - pAS_Info->f_in, 1894588000 - pAS_Info->f_in); /* Ctr = 1893.888 */
433 MT2063_AddExclZone(pAS_Info, 1891460000 - pAS_Info->f_in, 1892860000 - pAS_Info->f_in); /* Ctr = 1892.16 */
434 MT2063_AddExclZone(pAS_Info, 1889732000 - pAS_Info->f_in, 1891132000 - pAS_Info->f_in); /* Ctr = 1890.432 */
435 MT2063_AddExclZone(pAS_Info, 1888004000 - pAS_Info->f_in, 1889404000 - pAS_Info->f_in); /* Ctr = 1888.704 */
436 MT2063_AddExclZone(pAS_Info, 1886276000 - pAS_Info->f_in, 1887676000 - pAS_Info->f_in); /* Ctr = 1886.976 */
437 MT2063_AddExclZone(pAS_Info, 1884548000 - pAS_Info->f_in, 1885948000 - pAS_Info->f_in); /* Ctr = 1885.248 */
438 MT2063_AddExclZone(pAS_Info, 1882820000 - pAS_Info->f_in, 1884220000 - pAS_Info->f_in); /* Ctr = 1883.52 */
439 MT2063_AddExclZone(pAS_Info, 1881092000 - pAS_Info->f_in, 1882492000 - pAS_Info->f_in); /* Ctr = 1881.792 */
440 }
0e301442
MCC
441}
442
443static struct MT2063_ExclZone_t *InsertNode(struct MT2063_AvoidSpursData_t
444 *pAS_Info,
445 struct MT2063_ExclZone_t *pPrevNode)
446{
447 struct MT2063_ExclZone_t *pNode;
448 /* Check for a node in the free list */
449 if (pAS_Info->freeZones != NULL) {
450 /* Use one from the free list */
451 pNode = pAS_Info->freeZones;
452 pAS_Info->freeZones = pNode->next_;
453 } else {
454 /* Grab a node from the array */
455 pNode = &pAS_Info->MT2063_ExclZones[pAS_Info->nZones];
456 }
457
458 if (pPrevNode != NULL) {
459 pNode->next_ = pPrevNode->next_;
460 pPrevNode->next_ = pNode;
461 } else { /* insert at the beginning of the list */
462
463 pNode->next_ = pAS_Info->usedZones;
464 pAS_Info->usedZones = pNode;
465 }
466
467 pAS_Info->nZones++;
468 return pNode;
469}
470
471static struct MT2063_ExclZone_t *RemoveNode(struct MT2063_AvoidSpursData_t
472 *pAS_Info,
473 struct MT2063_ExclZone_t *pPrevNode,
474 struct MT2063_ExclZone_t
475 *pNodeToRemove)
476{
477 struct MT2063_ExclZone_t *pNext = pNodeToRemove->next_;
478
479 /* Make previous node point to the subsequent node */
480 if (pPrevNode != NULL)
481 pPrevNode->next_ = pNext;
482
483 /* Add pNodeToRemove to the beginning of the freeZones */
484 pNodeToRemove->next_ = pAS_Info->freeZones;
485 pAS_Info->freeZones = pNodeToRemove;
486
487 /* Decrement node count */
488 pAS_Info->nZones--;
489
490 return pNext;
491}
492
493/*****************************************************************************
494**
495** Name: MT_AddExclZone
496**
497** Description: Add (and merge) an exclusion zone into the list.
498** If the range (f_min, f_max) is totally outside the
499** 1st IF BW, ignore the entry.
500** If the range (f_min, f_max) is negative, ignore the entry.
501**
502** Revision History:
503**
504** SCR Date Author Description
505** -------------------------------------------------------------------------
506** 103 01-31-2005 DAD Ver 1.14: In MT_AddExclZone(), if the range
507** (f_min, f_max) < 0, ignore the entry.
508**
509*****************************************************************************/
bf97555e 510static void MT2063_AddExclZone(struct MT2063_AvoidSpursData_t *pAS_Info,
cfde8925 511 u32 f_min, u32 f_max)
0e301442
MCC
512{
513 struct MT2063_ExclZone_t *pNode = pAS_Info->usedZones;
514 struct MT2063_ExclZone_t *pPrev = NULL;
515 struct MT2063_ExclZone_t *pNext = NULL;
516
517 /* Check to see if this overlaps the 1st IF filter */
518 if ((f_max > (pAS_Info->f_if1_Center - (pAS_Info->f_if1_bw / 2)))
519 && (f_min < (pAS_Info->f_if1_Center + (pAS_Info->f_if1_bw / 2)))
520 && (f_min < f_max)) {
521 /*
522 ** 1 2 3 4 5 6
523 **
524 ** New entry: |---| |--| |--| |-| |---| |--|
525 ** or or or or or
526 ** Existing: |--| |--| |--| |---| |-| |--|
527 */
528
529 /* Check for our place in the list */
530 while ((pNode != NULL) && (pNode->max_ < f_min)) {
531 pPrev = pNode;
532 pNode = pNode->next_;
533 }
534
535 if ((pNode != NULL) && (pNode->min_ < f_max)) {
536 /* Combine me with pNode */
537 if (f_min < pNode->min_)
538 pNode->min_ = f_min;
539 if (f_max > pNode->max_)
540 pNode->max_ = f_max;
541 } else {
542 pNode = InsertNode(pAS_Info, pPrev);
543 pNode->min_ = f_min;
544 pNode->max_ = f_max;
545 }
546
547 /* Look for merging possibilities */
548 pNext = pNode->next_;
549 while ((pNext != NULL) && (pNext->min_ < pNode->max_)) {
550 if (pNext->max_ > pNode->max_)
551 pNode->max_ = pNext->max_;
552 pNext = RemoveNode(pAS_Info, pNode, pNext); /* Remove pNext, return ptr to pNext->next */
553 }
554 }
555}
556
557/*****************************************************************************
558**
559** Name: MT_ChooseFirstIF
560**
561** Description: Choose the best available 1st IF
562** If f_Desired is not excluded, choose that first.
563** Otherwise, return the value closest to f_Center that is
564** not excluded
565**
566** Revision History:
567**
568** SCR Date Author Description
569** -------------------------------------------------------------------------
570** 117 03-29-2007 RSK Ver 1.15: Re-wrote to match search order from
571** tuner DLL.
572** 147 07-27-2007 RSK Ver 1.17: Corrected calculation (-) to (+)
573** Added logic to force f_Center within 1/2 f_Step.
574**
575*****************************************************************************/
bf97555e 576static u32 MT2063_ChooseFirstIF(struct MT2063_AvoidSpursData_t *pAS_Info)
0e301442
MCC
577{
578 /*
579 ** Update "f_Desired" to be the nearest "combinational-multiple" of "f_LO1_Step".
580 ** The resulting number, F_LO1 must be a multiple of f_LO1_Step. And F_LO1 is the arithmetic sum
581 ** of f_in + f_Center. Neither f_in, nor f_Center must be a multiple of f_LO1_Step.
582 ** However, the sum must be.
583 */
cfde8925 584 const u32 f_Desired =
0e301442
MCC
585 pAS_Info->f_LO1_Step *
586 ((pAS_Info->f_if1_Request + pAS_Info->f_in +
587 pAS_Info->f_LO1_Step / 2) / pAS_Info->f_LO1_Step) -
588 pAS_Info->f_in;
cfde8925 589 const u32 f_Step =
0e301442
MCC
590 (pAS_Info->f_LO1_Step >
591 pAS_Info->f_LO2_Step) ? pAS_Info->f_LO1_Step : pAS_Info->
592 f_LO2_Step;
cfde8925
MCC
593 u32 f_Center;
594
595 s32 i;
596 s32 j = 0;
597 u32 bDesiredExcluded = 0;
598 u32 bZeroExcluded = 0;
599 s32 tmpMin, tmpMax;
600 s32 bestDiff;
0e301442
MCC
601 struct MT2063_ExclZone_t *pNode = pAS_Info->usedZones;
602 struct MT2063_FIFZone_t zones[MT2063_MAX_ZONES];
603
604 if (pAS_Info->nZones == 0)
605 return f_Desired;
606
607 /* f_Center needs to be an integer multiple of f_Step away from f_Desired */
608 if (pAS_Info->f_if1_Center > f_Desired)
609 f_Center =
610 f_Desired +
611 f_Step *
612 ((pAS_Info->f_if1_Center - f_Desired +
613 f_Step / 2) / f_Step);
614 else
615 f_Center =
616 f_Desired -
617 f_Step *
618 ((f_Desired - pAS_Info->f_if1_Center +
619 f_Step / 2) / f_Step);
620
621 //assert;
cfde8925 622 //if (!abs((s32) f_Center - (s32) pAS_Info->f_if1_Center) <= (s32) (f_Step/2))
0e301442
MCC
623 // return 0;
624
625 /* Take MT_ExclZones, center around f_Center and change the resolution to f_Step */
626 while (pNode != NULL) {
627 /* floor function */
628 tmpMin =
cfde8925 629 floor((s32) (pNode->min_ - f_Center), (s32) f_Step);
0e301442
MCC
630
631 /* ceil function */
632 tmpMax =
cfde8925 633 ceil((s32) (pNode->max_ - f_Center), (s32) f_Step);
0e301442
MCC
634
635 if ((pNode->min_ < f_Desired) && (pNode->max_ > f_Desired))
636 bDesiredExcluded = 1;
637
638 if ((tmpMin < 0) && (tmpMax > 0))
639 bZeroExcluded = 1;
640
641 /* See if this zone overlaps the previous */
642 if ((j > 0) && (tmpMin < zones[j - 1].max_))
643 zones[j - 1].max_ = tmpMax;
644 else {
645 /* Add new zone */
646 //assert(j<MT2063_MAX_ZONES);
647 //if (j>=MT2063_MAX_ZONES)
648 //break;
649
650 zones[j].min_ = tmpMin;
651 zones[j].max_ = tmpMax;
652 j++;
653 }
654 pNode = pNode->next_;
655 }
656
657 /*
658 ** If the desired is okay, return with it
659 */
660 if (bDesiredExcluded == 0)
661 return f_Desired;
662
663 /*
664 ** If the desired is excluded and the center is okay, return with it
665 */
666 if (bZeroExcluded == 0)
667 return f_Center;
668
669 /* Find the value closest to 0 (f_Center) */
670 bestDiff = zones[0].min_;
671 for (i = 0; i < j; i++) {
672 if (abs(zones[i].min_) < abs(bestDiff))
673 bestDiff = zones[i].min_;
674 if (abs(zones[i].max_) < abs(bestDiff))
675 bestDiff = zones[i].max_;
676 }
677
678 if (bestDiff < 0)
cfde8925 679 return f_Center - ((u32) (-bestDiff) * f_Step);
0e301442
MCC
680
681 return f_Center + (bestDiff * f_Step);
682}
683
684/****************************************************************************
685**
686** Name: gcd
687**
688** Description: Uses Euclid's algorithm
689**
690** Parameters: u, v - unsigned values whose GCD is desired.
691**
692** Global: None
693**
694** Returns: greatest common divisor of u and v, if either value
695** is 0, the other value is returned as the result.
696**
697** Dependencies: None.
698**
699** Revision History:
700**
701** SCR Date Author Description
702** -------------------------------------------------------------------------
703** N/A 06-01-2004 JWS Original
704** N/A 08-03-2004 DAD Changed to Euclid's since it can handle
705** unsigned numbers.
706**
707****************************************************************************/
cfde8925 708static u32 MT2063_gcd(u32 u, u32 v)
0e301442 709{
cfde8925 710 u32 r;
0e301442
MCC
711
712 while (v != 0) {
713 r = u % v;
714 u = v;
715 v = r;
716 }
717
718 return u;
719}
720
0e301442
MCC
721/****************************************************************************
722**
723** Name: IsSpurInBand
724**
725** Description: Checks to see if a spur will be present within the IF's
726** bandwidth. (fIFOut +/- fIFBW, -fIFOut +/- fIFBW)
727**
728** ma mb mc md
729** <--+-+-+-------------------+-------------------+-+-+-->
730** | ^ 0 ^ |
731** ^ b=-fIFOut+fIFBW/2 -b=+fIFOut-fIFBW/2 ^
732** a=-fIFOut-fIFBW/2 -a=+fIFOut+fIFBW/2
733**
734** Note that some equations are doubled to prevent round-off
735** problems when calculating fIFBW/2
736**
737** Parameters: pAS_Info - Avoid Spurs information block
738** fm - If spur, amount f_IF1 has to move negative
739** fp - If spur, amount f_IF1 has to move positive
740**
741** Global: None
742**
743** Returns: 1 if an LO spur would be present, otherwise 0.
744**
745** Dependencies: None.
746**
747** Revision History:
748**
749** SCR Date Author Description
750** -------------------------------------------------------------------------
751** N/A 11-28-2002 DAD Implemented algorithm from applied patent
752**
753****************************************************************************/
cfde8925
MCC
754static u32 IsSpurInBand(struct MT2063_AvoidSpursData_t *pAS_Info,
755 u32 * fm, u32 * fp)
0e301442
MCC
756{
757 /*
758 ** Calculate LO frequency settings.
759 */
cfde8925
MCC
760 u32 n, n0;
761 const u32 f_LO1 = pAS_Info->f_LO1;
762 const u32 f_LO2 = pAS_Info->f_LO2;
763 const u32 d = pAS_Info->f_out + pAS_Info->f_out_bw / 2;
764 const u32 c = d - pAS_Info->f_out_bw;
765 const u32 f = pAS_Info->f_zif_bw / 2;
d0dcc2da 766 const u32 f_Scale = (f_LO1 / (UINT_MAX / 2 / pAS_Info->maxH1)) + 1;
cfde8925
MCC
767 s32 f_nsLO1, f_nsLO2;
768 s32 f_Spur;
769 u32 ma, mb, mc, md, me, mf;
770 u32 lo_gcd, gd_Scale, gc_Scale, gf_Scale, hgds, hgfs, hgcs;
0e301442
MCC
771 *fm = 0;
772
773 /*
774 ** For each edge (d, c & f), calculate a scale, based on the gcd
775 ** of f_LO1, f_LO2 and the edge value. Use the larger of this
776 ** gcd-based scale factor or f_Scale.
777 */
778 lo_gcd = MT2063_gcd(f_LO1, f_LO2);
fd1126ca 779 gd_Scale = max((u32) MT2063_gcd(lo_gcd, d), f_Scale);
0e301442 780 hgds = gd_Scale / 2;
fd1126ca 781 gc_Scale = max((u32) MT2063_gcd(lo_gcd, c), f_Scale);
0e301442 782 hgcs = gc_Scale / 2;
fd1126ca 783 gf_Scale = max((u32) MT2063_gcd(lo_gcd, f), f_Scale);
0e301442
MCC
784 hgfs = gf_Scale / 2;
785
e930b3a0 786 n0 = DIV_ROUND_UP(f_LO2 - d, f_LO1 - f_LO2);
0e301442
MCC
787
788 /* Check out all multiples of LO1 from n0 to m_maxLOSpurHarmonic */
789 for (n = n0; n <= pAS_Info->maxH1; ++n) {
790 md = (n * ((f_LO1 + hgds) / gd_Scale) -
791 ((d + hgds) / gd_Scale)) / ((f_LO2 + hgds) / gd_Scale);
792
793 /* If # fLO2 harmonics > m_maxLOSpurHarmonic, then no spurs present */
794 if (md >= pAS_Info->maxH1)
795 break;
796
797 ma = (n * ((f_LO1 + hgds) / gd_Scale) +
798 ((d + hgds) / gd_Scale)) / ((f_LO2 + hgds) / gd_Scale);
799
800 /* If no spurs between +/- (f_out + f_IFBW/2), then try next harmonic */
801 if (md == ma)
802 continue;
803
804 mc = (n * ((f_LO1 + hgcs) / gc_Scale) -
805 ((c + hgcs) / gc_Scale)) / ((f_LO2 + hgcs) / gc_Scale);
806 if (mc != md) {
cfde8925
MCC
807 f_nsLO1 = (s32) (n * (f_LO1 / gc_Scale));
808 f_nsLO2 = (s32) (mc * (f_LO2 / gc_Scale));
0e301442
MCC
809 f_Spur =
810 (gc_Scale * (f_nsLO1 - f_nsLO2)) +
811 n * (f_LO1 % gc_Scale) - mc * (f_LO2 % gc_Scale);
812
cfde8925
MCC
813 *fp = ((f_Spur - (s32) c) / (mc - n)) + 1;
814 *fm = (((s32) d - f_Spur) / (mc - n)) + 1;
0e301442
MCC
815 return 1;
816 }
817
818 /* Location of Zero-IF-spur to be checked */
819 me = (n * ((f_LO1 + hgfs) / gf_Scale) +
820 ((f + hgfs) / gf_Scale)) / ((f_LO2 + hgfs) / gf_Scale);
821 mf = (n * ((f_LO1 + hgfs) / gf_Scale) -
822 ((f + hgfs) / gf_Scale)) / ((f_LO2 + hgfs) / gf_Scale);
823 if (me != mf) {
824 f_nsLO1 = n * (f_LO1 / gf_Scale);
825 f_nsLO2 = me * (f_LO2 / gf_Scale);
826 f_Spur =
827 (gf_Scale * (f_nsLO1 - f_nsLO2)) +
828 n * (f_LO1 % gf_Scale) - me * (f_LO2 % gf_Scale);
829
cfde8925
MCC
830 *fp = ((f_Spur + (s32) f) / (me - n)) + 1;
831 *fm = (((s32) f - f_Spur) / (me - n)) + 1;
0e301442
MCC
832 return 1;
833 }
834
835 mb = (n * ((f_LO1 + hgcs) / gc_Scale) +
836 ((c + hgcs) / gc_Scale)) / ((f_LO2 + hgcs) / gc_Scale);
837 if (ma != mb) {
838 f_nsLO1 = n * (f_LO1 / gc_Scale);
839 f_nsLO2 = ma * (f_LO2 / gc_Scale);
840 f_Spur =
841 (gc_Scale * (f_nsLO1 - f_nsLO2)) +
842 n * (f_LO1 % gc_Scale) - ma * (f_LO2 % gc_Scale);
843
cfde8925
MCC
844 *fp = (((s32) d + f_Spur) / (ma - n)) + 1;
845 *fm = (-(f_Spur + (s32) c) / (ma - n)) + 1;
0e301442
MCC
846 return 1;
847 }
848 }
849
0e301442
MCC
850 /* No spurs found */
851 return 0;
852}
853
854/*****************************************************************************
855**
856** Name: MT_AvoidSpurs
857**
858** Description: Main entry point to avoid spurs.
859** Checks for existing spurs in present LO1, LO2 freqs
860** and if present, chooses spur-free LO1, LO2 combination
861** that tunes the same input/output frequencies.
862**
863** Revision History:
864**
865** SCR Date Author Description
866** -------------------------------------------------------------------------
867** 096 04-06-2005 DAD Ver 1.11: Fix divide by 0 error if maxH==0.
868**
869*****************************************************************************/
bf97555e 870static u32 MT2063_AvoidSpurs(void *h, struct MT2063_AvoidSpursData_t * pAS_Info)
0e301442 871{
fdf77a4f 872 u32 status = 0;
cfde8925 873 u32 fm, fp; /* restricted range on LO's */
0e301442
MCC
874 pAS_Info->bSpurAvoided = 0;
875 pAS_Info->nSpursFound = 0;
876
877 if (pAS_Info->maxH1 == 0)
fdf77a4f 878 return 0;
0e301442
MCC
879
880 /*
881 ** Avoid LO Generated Spurs
882 **
883 ** Make sure that have no LO-related spurs within the IF output
884 ** bandwidth.
885 **
886 ** If there is an LO spur in this band, start at the current IF1 frequency
887 ** and work out until we find a spur-free frequency or run up against the
888 ** 1st IF SAW band edge. Use temporary copies of fLO1 and fLO2 so that they
889 ** will be unchanged if a spur-free setting is not found.
890 */
891 pAS_Info->bSpurPresent = IsSpurInBand(pAS_Info, &fm, &fp);
892 if (pAS_Info->bSpurPresent) {
cfde8925
MCC
893 u32 zfIF1 = pAS_Info->f_LO1 - pAS_Info->f_in; /* current attempt at a 1st IF */
894 u32 zfLO1 = pAS_Info->f_LO1; /* current attempt at an LO1 freq */
895 u32 zfLO2 = pAS_Info->f_LO2; /* current attempt at an LO2 freq */
896 u32 delta_IF1;
897 u32 new_IF1;
0e301442
MCC
898
899 /*
900 ** Spur was found, attempt to find a spur-free 1st IF
901 */
902 do {
903 pAS_Info->nSpursFound++;
904
905 /* Raise f_IF1_upper, if needed */
906 MT2063_AddExclZone(pAS_Info, zfIF1 - fm, zfIF1 + fp);
907
908 /* Choose next IF1 that is closest to f_IF1_CENTER */
909 new_IF1 = MT2063_ChooseFirstIF(pAS_Info);
910
911 if (new_IF1 > zfIF1) {
912 pAS_Info->f_LO1 += (new_IF1 - zfIF1);
913 pAS_Info->f_LO2 += (new_IF1 - zfIF1);
914 } else {
915 pAS_Info->f_LO1 -= (zfIF1 - new_IF1);
916 pAS_Info->f_LO2 -= (zfIF1 - new_IF1);
917 }
918 zfIF1 = new_IF1;
919
920 if (zfIF1 > pAS_Info->f_if1_Center)
921 delta_IF1 = zfIF1 - pAS_Info->f_if1_Center;
922 else
923 delta_IF1 = pAS_Info->f_if1_Center - zfIF1;
924 }
925 /*
926 ** Continue while the new 1st IF is still within the 1st IF bandwidth
927 ** and there is a spur in the band (again)
928 */
929 while ((2 * delta_IF1 + pAS_Info->f_out_bw <=
930 pAS_Info->f_if1_bw)
931 && (pAS_Info->bSpurPresent =
932 IsSpurInBand(pAS_Info, &fm, &fp)));
933
934 /*
935 ** Use the LO-spur free values found. If the search went all the way to
936 ** the 1st IF band edge and always found spurs, just leave the original
937 ** choice. It's as "good" as any other.
938 */
939 if (pAS_Info->bSpurPresent == 1) {
940 status |= MT2063_SPUR_PRESENT_ERR;
941 pAS_Info->f_LO1 = zfLO1;
942 pAS_Info->f_LO2 = zfLO2;
943 } else
944 pAS_Info->bSpurAvoided = 1;
945 }
946
947 status |=
948 ((pAS_Info->
949 nSpursFound << MT2063_SPUR_SHIFT) & MT2063_SPUR_CNT_MASK);
950
951 return (status);
952}
953
0e301442
MCC
954/*
955** The expected version of MT_AvoidSpursData_t
956** If the version is different, an updated file is needed from Microtune
957*/
0e301442
MCC
958
959typedef enum {
960 MT2063_SET_ATTEN,
961 MT2063_INCR_ATTEN,
962 MT2063_DECR_ATTEN
963} MT2063_ATTEN_CNTL_MODE;
964
0e301442 965/*
66aea30d
MCC
966 * Constants used by the tuning algorithm
967 */
0e301442
MCC
968#define MT2063_REF_FREQ (16000000UL) /* Reference oscillator Frequency (in Hz) */
969#define MT2063_IF1_BW (22000000UL) /* The IF1 filter bandwidth (in Hz) */
970#define MT2063_TUNE_STEP_SIZE (50000UL) /* Tune in steps of 50 kHz */
971#define MT2063_SPUR_STEP_HZ (250000UL) /* Step size (in Hz) to move IF1 when avoiding spurs */
972#define MT2063_ZIF_BW (2000000UL) /* Zero-IF spur-free bandwidth (in Hz) */
973#define MT2063_MAX_HARMONICS_1 (15UL) /* Highest intra-tuner LO Spur Harmonic to be avoided */
974#define MT2063_MAX_HARMONICS_2 (5UL) /* Highest inter-tuner LO Spur Harmonic to be avoided */
975#define MT2063_MIN_LO_SEP (1000000UL) /* Minimum inter-tuner LO frequency separation */
976#define MT2063_LO1_FRACN_AVOID (0UL) /* LO1 FracN numerator avoid region (in Hz) */
977#define MT2063_LO2_FRACN_AVOID (199999UL) /* LO2 FracN numerator avoid region (in Hz) */
978#define MT2063_MIN_FIN_FREQ (44000000UL) /* Minimum input frequency (in Hz) */
979#define MT2063_MAX_FIN_FREQ (1100000000UL) /* Maximum input frequency (in Hz) */
980#define MT2063_MIN_FOUT_FREQ (36000000UL) /* Minimum output frequency (in Hz) */
981#define MT2063_MAX_FOUT_FREQ (57000000UL) /* Maximum output frequency (in Hz) */
982#define MT2063_MIN_DNC_FREQ (1293000000UL) /* Minimum LO2 frequency (in Hz) */
983#define MT2063_MAX_DNC_FREQ (1614000000UL) /* Maximum LO2 frequency (in Hz) */
984#define MT2063_MIN_UPC_FREQ (1396000000UL) /* Minimum LO1 frequency (in Hz) */
985#define MT2063_MAX_UPC_FREQ (2750000000UL) /* Maximum LO1 frequency (in Hz) */
986
987/*
988** Define the supported Part/Rev codes for the MT2063
989*/
990#define MT2063_B0 (0x9B)
991#define MT2063_B1 (0x9C)
992#define MT2063_B2 (0x9D)
993#define MT2063_B3 (0x9E)
994
0e301442
MCC
995/*
996** Constants for setting receiver modes.
997** (6 modes defined at this time, enumerated by MT2063_RCVR_MODES)
998** (DNC1GC & DNC2GC are the values, which are used, when the specific
999** DNC Output is selected, the other is always off)
1000**
1001** If PAL-L or L' is received, set:
1002** MT2063_SetParam(hMT2063,MT2063_TAGC,1);
1003**
1004** --------------+----------------------------------------------
1005** Mode 0 : | MT2063_CABLE_QAM
1006** Mode 1 : | MT2063_CABLE_ANALOG
1007** Mode 2 : | MT2063_OFFAIR_COFDM
1008** Mode 3 : | MT2063_OFFAIR_COFDM_SAWLESS
1009** Mode 4 : | MT2063_OFFAIR_ANALOG
1010** Mode 5 : | MT2063_OFFAIR_8VSB
1011** --------------+----+----+----+----+-----+-----+--------------
1012** Mode | 0 | 1 | 2 | 3 | 4 | 5 |
1013** --------------+----+----+----+----+-----+-----+
1014**
1015**
1016*/
cfde8925
MCC
1017static const u8 RFAGCEN[] = { 0, 0, 0, 0, 0, 0 };
1018static const u8 LNARIN[] = { 0, 0, 3, 3, 3, 3 };
1019static const u8 FIFFQEN[] = { 1, 1, 1, 1, 1, 1 };
1020static const u8 FIFFQ[] = { 0, 0, 0, 0, 0, 0 };
1021static const u8 DNC1GC[] = { 0, 0, 0, 0, 0, 0 };
1022static const u8 DNC2GC[] = { 0, 0, 0, 0, 0, 0 };
1023static const u8 ACLNAMAX[] = { 31, 31, 31, 31, 31, 31 };
1024static const u8 LNATGT[] = { 44, 43, 43, 43, 43, 43 };
1025static const u8 RFOVDIS[] = { 0, 0, 0, 0, 0, 0 };
1026static const u8 ACRFMAX[] = { 31, 31, 31, 31, 31, 31 };
1027static const u8 PD1TGT[] = { 36, 36, 38, 38, 36, 38 };
1028static const u8 FIFOVDIS[] = { 0, 0, 0, 0, 0, 0 };
1029static const u8 ACFIFMAX[] = { 29, 29, 29, 29, 29, 29 };
1030static const u8 PD2TGT[] = { 40, 33, 38, 42, 30, 38 };
0e301442
MCC
1031
1032/*
1033** Local Function Prototypes - not available for external access.
1034*/
1035
1036/* Forward declaration(s): */
cfde8925
MCC
1037static u32 MT2063_CalcLO1Mult(u32 * Div, u32 * FracN, u32 f_LO,
1038 u32 f_LO_Step, u32 f_Ref);
1039static u32 MT2063_CalcLO2Mult(u32 * Div, u32 * FracN, u32 f_LO,
1040 u32 f_LO_Step, u32 f_Ref);
1041static u32 MT2063_fLO_FractionalTerm(u32 f_ref, u32 num,
1042 u32 denom);
0e301442 1043
31e67fae
MCC
1044/**
1045 * mt2063_lockStatus - Checks to see if LO1 and LO2 are locked
1046 *
1047 * @state: struct mt2063_state pointer
1048 *
1049 * This function returns 0, if no lock, 1 if locked and a value < 1 if error
1050 */
1051unsigned int mt2063_lockStatus(struct mt2063_state *state)
0e301442 1052{
cfde8925
MCC
1053 const u32 nMaxWait = 100; /* wait a maximum of 100 msec */
1054 const u32 nPollRate = 2; /* poll status bits every 2 ms */
1055 const u32 nMaxLoops = nMaxWait / nPollRate;
1056 const u8 LO1LK = 0x80;
1057 u8 LO2LK = 0x08;
31e67fae 1058 u32 status;
cfde8925 1059 u32 nDelays = 0;
0e301442 1060
0e301442 1061 /* LO2 Lock bit was in a different place for B0 version */
dcd52d20 1062 if (state->tuner_id == MT2063_B0)
0e301442
MCC
1063 LO2LK = 0x40;
1064
1065 do {
31e67fae
MCC
1066 status = mt2063_read(state, MT2063_REG_LO_STATUS,
1067 &state->reg[MT2063_REG_LO_STATUS], 1);
0e301442 1068
fdf77a4f 1069 if (status < 0)
31e67fae 1070 return status;
0e301442 1071
dcd52d20 1072 if ((state->reg[MT2063_REG_LO_STATUS] & (LO1LK | LO2LK)) ==
0e301442 1073 (LO1LK | LO2LK)) {
31e67fae 1074 return TUNER_STATUS_LOCKED | TUNER_STATUS_STEREO;
0e301442 1075 }
bf97555e 1076 msleep(nPollRate); /* Wait between retries */
0e301442
MCC
1077 }
1078 while (++nDelays < nMaxLoops);
1079
31e67fae
MCC
1080 /*
1081 * Got no lock or partial lock
1082 */
1083 return 0;
0e301442 1084}
3d49700f 1085EXPORT_SYMBOL_GPL(mt2063_lockStatus);
0e301442 1086
4713e225
MCC
1087/*
1088 * mt2063_set_dnc_output_enable()
1089 */
1090static u32 mt2063_get_dnc_output_enable(struct mt2063_state *state,
1091 enum MT2063_DNC_Output_Enable *pValue)
0e301442 1092{
4713e225
MCC
1093 if ((state->reg[MT2063_REG_DNC_GAIN] & 0x03) == 0x03) { /* if DNC1 is off */
1094 if ((state->reg[MT2063_REG_VGA_GAIN] & 0x03) == 0x03) /* if DNC2 is off */
1095 *pValue = MT2063_DNC_NONE;
1096 else
1097 *pValue = MT2063_DNC_2;
1098 } else { /* DNC1 is on */
1099 if ((state->reg[MT2063_REG_VGA_GAIN] & 0x03) == 0x03) /* if DNC2 is off */
1100 *pValue = MT2063_DNC_1;
1101 else
1102 *pValue = MT2063_DNC_BOTH;
1103 }
1104 return 0;
1105}
0e301442 1106
4713e225
MCC
1107/*
1108 * mt2063_set_dnc_output_enable()
1109 */
1110static u32 mt2063_set_dnc_output_enable(struct mt2063_state *state,
1111 enum MT2063_DNC_Output_Enable nValue)
1112{
1113 u32 status = 0; /* Status to be returned */
1114 u8 val = 0;
51f0f7b3 1115
4713e225
MCC
1116 /* selects, which DNC output is used */
1117 switch (nValue) {
1118 case MT2063_DNC_NONE:
51f0f7b3 1119 {
4713e225
MCC
1120 val = (state->reg[MT2063_REG_DNC_GAIN] & 0xFC) | 0x03; /* Set DNC1GC=3 */
1121 if (state->reg[MT2063_REG_DNC_GAIN] !=
1122 val)
1123 status |=
1124 MT2063_SetReg(state,
1125 MT2063_REG_DNC_GAIN,
1126 val);
51f0f7b3 1127
4713e225
MCC
1128 val = (state->reg[MT2063_REG_VGA_GAIN] & 0xFC) | 0x03; /* Set DNC2GC=3 */
1129 if (state->reg[MT2063_REG_VGA_GAIN] !=
1130 val)
1131 status |=
1132 MT2063_SetReg(state,
1133 MT2063_REG_VGA_GAIN,
1134 val);
51f0f7b3 1135
4713e225
MCC
1136 val = (state->reg[MT2063_REG_RSVD_20] & ~0x40); /* Set PD2MUX=0 */
1137 if (state->reg[MT2063_REG_RSVD_20] !=
1138 val)
1139 status |=
1140 MT2063_SetReg(state,
1141 MT2063_REG_RSVD_20,
1142 val);
51f0f7b3 1143
4713e225 1144 break;
51f0f7b3 1145 }
4713e225
MCC
1146 case MT2063_DNC_1:
1147 {
1148 val = (state->reg[MT2063_REG_DNC_GAIN] & 0xFC) | (DNC1GC[state->rcvr_mode] & 0x03); /* Set DNC1GC=x */
1149 if (state->reg[MT2063_REG_DNC_GAIN] !=
1150 val)
1151 status |=
1152 MT2063_SetReg(state,
1153 MT2063_REG_DNC_GAIN,
1154 val);
51f0f7b3 1155
4713e225
MCC
1156 val = (state->reg[MT2063_REG_VGA_GAIN] & 0xFC) | 0x03; /* Set DNC2GC=3 */
1157 if (state->reg[MT2063_REG_VGA_GAIN] !=
1158 val)
1159 status |=
1160 MT2063_SetReg(state,
1161 MT2063_REG_VGA_GAIN,
1162 val);
51f0f7b3 1163
4713e225
MCC
1164 val = (state->reg[MT2063_REG_RSVD_20] & ~0x40); /* Set PD2MUX=0 */
1165 if (state->reg[MT2063_REG_RSVD_20] !=
1166 val)
1167 status |=
1168 MT2063_SetReg(state,
1169 MT2063_REG_RSVD_20,
1170 val);
51f0f7b3 1171
4713e225 1172 break;
51f0f7b3 1173 }
4713e225
MCC
1174 case MT2063_DNC_2:
1175 {
1176 val = (state->reg[MT2063_REG_DNC_GAIN] & 0xFC) | 0x03; /* Set DNC1GC=3 */
1177 if (state->reg[MT2063_REG_DNC_GAIN] !=
1178 val)
1179 status |=
1180 MT2063_SetReg(state,
1181 MT2063_REG_DNC_GAIN,
1182 val);
51f0f7b3 1183
4713e225
MCC
1184 val = (state->reg[MT2063_REG_VGA_GAIN] & 0xFC) | (DNC2GC[state->rcvr_mode] & 0x03); /* Set DNC2GC=x */
1185 if (state->reg[MT2063_REG_VGA_GAIN] !=
1186 val)
1187 status |=
1188 MT2063_SetReg(state,
1189 MT2063_REG_VGA_GAIN,
1190 val);
fdf77a4f 1191
4713e225
MCC
1192 val = (state->reg[MT2063_REG_RSVD_20] | 0x40); /* Set PD2MUX=1 */
1193 if (state->reg[MT2063_REG_RSVD_20] !=
1194 val)
1195 status |=
1196 MT2063_SetReg(state,
1197 MT2063_REG_RSVD_20,
1198 val);
51f0f7b3 1199
4713e225
MCC
1200 break;
1201 }
1202 case MT2063_DNC_BOTH:
1203 {
1204 val = (state->reg[MT2063_REG_DNC_GAIN] & 0xFC) | (DNC1GC[state->rcvr_mode] & 0x03); /* Set DNC1GC=x */
1205 if (state->reg[MT2063_REG_DNC_GAIN] !=
1206 val)
1207 status |=
1208 MT2063_SetReg(state,
1209 MT2063_REG_DNC_GAIN,
1210 val);
51f0f7b3 1211
4713e225
MCC
1212 val = (state->reg[MT2063_REG_VGA_GAIN] & 0xFC) | (DNC2GC[state->rcvr_mode] & 0x03); /* Set DNC2GC=x */
1213 if (state->reg[MT2063_REG_VGA_GAIN] !=
1214 val)
1215 status |=
1216 MT2063_SetReg(state,
1217 MT2063_REG_VGA_GAIN,
1218 val);
51f0f7b3 1219
4713e225
MCC
1220 val = (state->reg[MT2063_REG_RSVD_20] | 0x40); /* Set PD2MUX=1 */
1221 if (state->reg[MT2063_REG_RSVD_20] !=
1222 val)
1223 status |=
1224 MT2063_SetReg(state,
1225 MT2063_REG_RSVD_20,
1226 val);
51f0f7b3 1227
4713e225 1228 break;
51f0f7b3 1229 }
51f0f7b3 1230 default:
4713e225 1231 break;
51f0f7b3 1232 }
0e301442
MCC
1233
1234 return (status);
1235}
1236
0e301442
MCC
1237/******************************************************************************
1238**
1239** Name: MT2063_SetReceiverMode
1240**
1241** Description: Set the MT2063 receiver mode
1242**
1243** --------------+----------------------------------------------
1244** Mode 0 : | MT2063_CABLE_QAM
1245** Mode 1 : | MT2063_CABLE_ANALOG
1246** Mode 2 : | MT2063_OFFAIR_COFDM
1247** Mode 3 : | MT2063_OFFAIR_COFDM_SAWLESS
1248** Mode 4 : | MT2063_OFFAIR_ANALOG
1249** Mode 5 : | MT2063_OFFAIR_8VSB
1250** --------------+----+----+----+----+-----+--------------------
1251** (DNC1GC & DNC2GC are the values, which are used, when the specific
1252** DNC Output is selected, the other is always off)
1253**
1254** |<---------- Mode -------------->|
1255** Reg Field | 0 | 1 | 2 | 3 | 4 | 5 |
1256** ------------+-----+-----+-----+-----+-----+-----+
1257** RFAGCen | OFF | OFF | OFF | OFF | OFF | OFF
1258** LNARin | 0 | 0 | 3 | 3 | 3 | 3
1259** FIFFQen | 1 | 1 | 1 | 1 | 1 | 1
1260** FIFFq | 0 | 0 | 0 | 0 | 0 | 0
1261** DNC1gc | 0 | 0 | 0 | 0 | 0 | 0
1262** DNC2gc | 0 | 0 | 0 | 0 | 0 | 0
1263** GCU Auto | 1 | 1 | 1 | 1 | 1 | 1
1264** LNA max Atn | 31 | 31 | 31 | 31 | 31 | 31
1265** LNA Target | 44 | 43 | 43 | 43 | 43 | 43
1266** ign RF Ovl | 0 | 0 | 0 | 0 | 0 | 0
1267** RF max Atn | 31 | 31 | 31 | 31 | 31 | 31
1268** PD1 Target | 36 | 36 | 38 | 38 | 36 | 38
1269** ign FIF Ovl | 0 | 0 | 0 | 0 | 0 | 0
1270** FIF max Atn | 5 | 5 | 5 | 5 | 5 | 5
1271** PD2 Target | 40 | 33 | 42 | 42 | 33 | 42
1272**
1273**
dcd52d20 1274** Parameters: state - ptr to mt2063_state structure
0e301442
MCC
1275** Mode - desired reciever mode
1276**
1277** Usage: status = MT2063_SetReceiverMode(hMT2063, Mode);
1278**
1279** Returns: status:
1280** MT_OK - No errors
1281** MT_COMM_ERR - Serial bus communications error
1282**
1283** Dependencies: MT2063_SetReg - Write a byte of data to a HW register.
1284** Assumes that the tuner cache is valid.
1285**
1286** Revision History:
1287**
1288** SCR Date Author Description
1289** -------------------------------------------------------------------------
1290** 138 06-19-2007 DAD Ver 1.00: Initial, derived from mt2067_b.
1291** N/A 01-10-2007 PINZ Added additional GCU Settings, FIFF Calib will be triggered
1292** 155 10-01-2007 DAD Ver 1.06: Add receiver mode for SECAM positive
1293** modulation
1294** (MT2063_ANALOG_TV_POS_NO_RFAGC_MODE)
1295** N/A 10-22-2007 PINZ Ver 1.07: Changed some Registers at init to have
1296** the same settings as with MT Launcher
1297** N/A 10-30-2007 PINZ Add SetParam VGAGC & VGAOI
1298** Add SetParam DNC_OUTPUT_ENABLE
1299** Removed VGAGC from receiver mode,
1300** default now 1
1301** N/A 10-31-2007 PINZ Ver 1.08: Add SetParam TAGC, removed from rcvr-mode
1302** Add SetParam AMPGC, removed from rcvr-mode
1303** Corrected names of GCU values
1304** reorganized receiver modes, removed,
1305** (MT2063_ANALOG_TV_POS_NO_RFAGC_MODE)
1306** Actualized Receiver-Mode values
1307** N/A 11-12-2007 PINZ Ver 1.09: Actualized Receiver-Mode values
1308** N/A 11-27-2007 PINZ Improved buffered writing
1309** 01-03-2008 PINZ Ver 1.10: Added a trigger of BYPATNUP for
1310** correct wakeup of the LNA after shutdown
1311** Set AFCsd = 1 as default
1312** Changed CAP1sel default
1313** 01-14-2008 PINZ Ver 1.11: Updated gain settings
1314** 04-18-2008 PINZ Ver 1.15: Add SetParam LNARIN & PDxTGT
1315** Split SetParam up to ACLNA / ACLNA_MAX
1316** removed ACLNA_INRC/DECR (+RF & FIF)
1317** removed GCUAUTO / BYPATNDN/UP
1318**
1319******************************************************************************/
dcd52d20 1320static u32 MT2063_SetReceiverMode(struct mt2063_state *state,
0e301442
MCC
1321 enum MT2063_RCVR_MODES Mode)
1322{
fdf77a4f 1323 u32 status = 0; /* Status to be returned */
cfde8925
MCC
1324 u8 val;
1325 u32 longval;
0e301442
MCC
1326
1327 if (Mode >= MT2063_NUM_RCVR_MODES)
fdf77a4f 1328 status = -ERANGE;
0e301442
MCC
1329
1330 /* RFAGCen */
fdf77a4f 1331 if (status >= 0) {
0e301442 1332 val =
dcd52d20 1333 (state->
cfde8925 1334 reg[MT2063_REG_PD1_TGT] & (u8) ~ 0x40) | (RFAGCEN[Mode]
0e301442
MCC
1335 ? 0x40 :
1336 0x00);
dcd52d20
MCC
1337 if (state->reg[MT2063_REG_PD1_TGT] != val) {
1338 status |= MT2063_SetReg(state, MT2063_REG_PD1_TGT, val);
0e301442
MCC
1339 }
1340 }
1341
1342 /* LNARin */
fdf77a4f 1343 if (status >= 0) {
4713e225
MCC
1344 u8 val = (state-> reg[MT2063_REG_CTRL_2C] & (u8) ~ 0x03) |
1345 (LNARIN[Mode] & 0x03);
1346 if (state->reg[MT2063_REG_CTRL_2C] != val)
1347 status |= MT2063_SetReg(state, MT2063_REG_CTRL_2C,
1348 val);
0e301442
MCC
1349 }
1350
1351 /* FIFFQEN and FIFFQ */
fdf77a4f 1352 if (status >= 0) {
0e301442 1353 val =
dcd52d20 1354 (state->
cfde8925 1355 reg[MT2063_REG_FIFF_CTRL2] & (u8) ~ 0xF0) |
0e301442 1356 (FIFFQEN[Mode] << 7) | (FIFFQ[Mode] << 4);
dcd52d20 1357 if (state->reg[MT2063_REG_FIFF_CTRL2] != val) {
0e301442 1358 status |=
dcd52d20 1359 MT2063_SetReg(state, MT2063_REG_FIFF_CTRL2, val);
0e301442
MCC
1360 /* trigger FIFF calibration, needed after changing FIFFQ */
1361 val =
dcd52d20 1362 (state->reg[MT2063_REG_FIFF_CTRL] | (u8) 0x01);
0e301442 1363 status |=
dcd52d20 1364 MT2063_SetReg(state, MT2063_REG_FIFF_CTRL, val);
0e301442 1365 val =
dcd52d20 1366 (state->
cfde8925 1367 reg[MT2063_REG_FIFF_CTRL] & (u8) ~ 0x01);
0e301442 1368 status |=
dcd52d20 1369 MT2063_SetReg(state, MT2063_REG_FIFF_CTRL, val);
0e301442
MCC
1370 }
1371 }
1372
1373 /* DNC1GC & DNC2GC */
4713e225
MCC
1374 status |= mt2063_get_dnc_output_enable(state, &longval);
1375 status |= mt2063_set_dnc_output_enable(state, longval);
0e301442
MCC
1376
1377 /* acLNAmax */
fdf77a4f 1378 if (status >= 0) {
4713e225
MCC
1379 u8 val = (state-> reg[MT2063_REG_LNA_OV] & (u8) ~ 0x1F) |
1380 (ACLNAMAX[Mode] & 0x1F);
1381 if (state->reg[MT2063_REG_LNA_OV] != val)
1382 status |= MT2063_SetReg(state, MT2063_REG_LNA_OV, val);
0e301442
MCC
1383 }
1384
1385 /* LNATGT */
fdf77a4f 1386 if (status >= 0) {
4713e225
MCC
1387 u8 val = (state-> reg[MT2063_REG_LNA_TGT] & (u8) ~ 0x3F) |
1388 (LNATGT[Mode] & 0x3F);
1389 if (state->reg[MT2063_REG_LNA_TGT] != val)
1390 status |= MT2063_SetReg(state, MT2063_REG_LNA_TGT, val);
0e301442
MCC
1391 }
1392
1393 /* ACRF */
fdf77a4f 1394 if (status >= 0) {
4713e225
MCC
1395 u8 val = (state-> reg[MT2063_REG_RF_OV] & (u8) ~ 0x1F) |
1396 (ACRFMAX[Mode] & 0x1F);
1397 if (state->reg[MT2063_REG_RF_OV] != val)
1398 status |= MT2063_SetReg(state, MT2063_REG_RF_OV, val);
0e301442
MCC
1399 }
1400
1401 /* PD1TGT */
fdf77a4f 1402 if (status >= 0) {
4713e225
MCC
1403 u8 val = (state-> reg[MT2063_REG_PD1_TGT] & (u8) ~ 0x3F) |
1404 (PD1TGT[Mode] & 0x3F);
1405 if (state->reg[MT2063_REG_PD1_TGT] != val)
1406 status |= MT2063_SetReg(state, MT2063_REG_PD1_TGT, val);
0e301442
MCC
1407 }
1408
1409 /* FIFATN */
fdf77a4f 1410 if (status >= 0) {
4713e225
MCC
1411 u8 val = ACFIFMAX[Mode];
1412 if (state->reg[MT2063_REG_PART_REV] != MT2063_B3 && val > 5)
1413 val = 5;
1414 val = (state-> reg[MT2063_REG_FIF_OV] & (u8) ~ 0x1F) |
1415 (val & 0x1F);
1416 if (state->reg[MT2063_REG_FIF_OV] != val) {
1417 status |= MT2063_SetReg(state, MT2063_REG_FIF_OV, val);
1418 }
0e301442
MCC
1419 }
1420
1421 /* PD2TGT */
fdf77a4f 1422 if (status >= 0) {
4713e225
MCC
1423 u8 val = (state-> reg[MT2063_REG_PD2_TGT] & (u8) ~ 0x3F) |
1424 (PD2TGT[Mode] & 0x3F);
1425 if (state->reg[MT2063_REG_PD2_TGT] != val)
1426 status |= MT2063_SetReg(state, MT2063_REG_PD2_TGT, val);
0e301442
MCC
1427 }
1428
1429 /* Ignore ATN Overload */
fdf77a4f 1430 if (status >= 0) {
0e301442 1431 val =
dcd52d20 1432 (state->
cfde8925 1433 reg[MT2063_REG_LNA_TGT] & (u8) ~ 0x80) | (RFOVDIS[Mode]
0e301442
MCC
1434 ? 0x80 :
1435 0x00);
dcd52d20
MCC
1436 if (state->reg[MT2063_REG_LNA_TGT] != val) {
1437 status |= MT2063_SetReg(state, MT2063_REG_LNA_TGT, val);
0e301442
MCC
1438 }
1439 }
1440
1441 /* Ignore FIF Overload */
fdf77a4f 1442 if (status >= 0) {
0e301442 1443 val =
dcd52d20 1444 (state->
cfde8925 1445 reg[MT2063_REG_PD1_TGT] & (u8) ~ 0x80) |
0e301442 1446 (FIFOVDIS[Mode] ? 0x80 : 0x00);
dcd52d20
MCC
1447 if (state->reg[MT2063_REG_PD1_TGT] != val) {
1448 status |= MT2063_SetReg(state, MT2063_REG_PD1_TGT, val);
0e301442
MCC
1449 }
1450 }
1451
fdf77a4f 1452 if (status >= 0)
dcd52d20 1453 state->rcvr_mode = Mode;
0e301442
MCC
1454
1455 return (status);
1456}
1457
0e301442
MCC
1458/****************************************************************************
1459**
1460** Name: MT2063_ClearPowerMaskBits
1461**
1462** Description: Clears the power-down mask bits for various sections of
1463** the MT2063
1464**
1465** Parameters: h - Tuner handle (returned by MT2063_Open)
1466** Bits - Mask bits to be cleared.
1467**
1468** See definition of MT2063_Mask_Bits type for description
1469** of each of the power bits.
1470**
1471** Returns: status:
1472** MT_OK - No errors
1473** MT_INV_HANDLE - Invalid tuner handle
1474** MT_COMM_ERR - Serial bus communications error
1475**
1476** Dependencies: USERS MUST CALL MT2063_Open() FIRST!
1477**
1478** Revision History:
1479**
1480** SCR Date Author Description
1481** -------------------------------------------------------------------------
1482** 138 06-19-2007 DAD Ver 1.00: Initial, derived from mt2067_b.
1483**
1484****************************************************************************/
dcd52d20 1485static u32 MT2063_ClearPowerMaskBits(struct mt2063_state *state, enum MT2063_Mask_Bits Bits)
0e301442 1486{
fdf77a4f 1487 u32 status = 0; /* Status to be returned */
0e301442 1488
fdf77a4f
MCC
1489 Bits = (enum MT2063_Mask_Bits)(Bits & MT2063_ALL_SD); /* Only valid bits for this tuner */
1490 if ((Bits & 0xFF00) != 0) {
dcd52d20 1491 state->reg[MT2063_REG_PWR_2] &= ~(u8) (Bits >> 8);
fdf77a4f 1492 status |=
e1de3d18 1493 mt2063_write(state,
fdf77a4f 1494 MT2063_REG_PWR_2,
dcd52d20 1495 &state->reg[MT2063_REG_PWR_2], 1);
fdf77a4f
MCC
1496 }
1497 if ((Bits & 0xFF) != 0) {
dcd52d20 1498 state->reg[MT2063_REG_PWR_1] &= ~(u8) (Bits & 0xFF);
fdf77a4f 1499 status |=
e1de3d18 1500 mt2063_write(state,
fdf77a4f 1501 MT2063_REG_PWR_1,
dcd52d20 1502 &state->reg[MT2063_REG_PWR_1], 1);
0e301442
MCC
1503 }
1504
1505 return (status);
1506}
1507
0e301442
MCC
1508/****************************************************************************
1509**
1510** Name: MT2063_SoftwareShutdown
1511**
1512** Description: Enables or disables software shutdown function. When
1513** Shutdown==1, any section whose power mask is set will be
1514** shutdown.
1515**
1516** Parameters: h - Tuner handle (returned by MT2063_Open)
1517** Shutdown - 1 = shutdown the masked sections, otherwise
1518** power all sections on
1519**
1520** Returns: status:
1521** MT_OK - No errors
1522** MT_INV_HANDLE - Invalid tuner handle
1523** MT_COMM_ERR - Serial bus communications error
1524**
1525** Dependencies: USERS MUST CALL MT2063_Open() FIRST!
1526**
1527** Revision History:
1528**
1529** SCR Date Author Description
1530** -------------------------------------------------------------------------
1531** 138 06-19-2007 DAD Ver 1.00: Initial, derived from mt2067_b.
1532** 01-03-2008 PINZ Ver 1.xx: Added a trigger of BYPATNUP for
1533** correct wakeup of the LNA
1534**
1535****************************************************************************/
dcd52d20 1536static u32 MT2063_SoftwareShutdown(struct mt2063_state *state, u8 Shutdown)
0e301442 1537{
31e67fae 1538 u32 status; /* Status to be returned */
0e301442 1539
fdf77a4f 1540 if (Shutdown == 1)
dcd52d20 1541 state->reg[MT2063_REG_PWR_1] |= 0x04; /* Turn the bit on */
fdf77a4f 1542 else
dcd52d20 1543 state->reg[MT2063_REG_PWR_1] &= ~0x04; /* Turn off the bit */
0e301442 1544
31e67fae 1545 status = mt2063_write(state,
fdf77a4f 1546 MT2063_REG_PWR_1,
dcd52d20 1547 &state->reg[MT2063_REG_PWR_1], 1);
fdf77a4f
MCC
1548
1549 if (Shutdown != 1) {
dcd52d20
MCC
1550 state->reg[MT2063_REG_BYP_CTRL] =
1551 (state->reg[MT2063_REG_BYP_CTRL] & 0x9F) | 0x40;
0e301442 1552 status |=
e1de3d18 1553 mt2063_write(state,
fdf77a4f 1554 MT2063_REG_BYP_CTRL,
dcd52d20 1555 &state->reg[MT2063_REG_BYP_CTRL],
fdf77a4f 1556 1);
dcd52d20
MCC
1557 state->reg[MT2063_REG_BYP_CTRL] =
1558 (state->reg[MT2063_REG_BYP_CTRL] & 0x9F);
fdf77a4f 1559 status |=
e1de3d18 1560 mt2063_write(state,
fdf77a4f 1561 MT2063_REG_BYP_CTRL,
dcd52d20 1562 &state->reg[MT2063_REG_BYP_CTRL],
fdf77a4f 1563 1);
0e301442
MCC
1564 }
1565
31e67fae 1566 return status;
0e301442
MCC
1567}
1568
0e301442
MCC
1569/****************************************************************************
1570**
1571** Name: MT2063_SetReg
1572**
1573** Description: Sets an MT2063 register.
1574**
1575** Parameters: h - Tuner handle (returned by MT2063_Open)
1576** reg - MT2063 register/subaddress location
1577** val - MT2063 register/subaddress value
1578**
1579** Returns: status:
1580** MT_OK - No errors
1581** MT_COMM_ERR - Serial bus communications error
1582** MT_INV_HANDLE - Invalid tuner handle
1583** MT_ARG_RANGE - Argument out of range
1584**
1585** Dependencies: USERS MUST CALL MT2063_Open() FIRST!
1586**
1587** Use this function if you need to override a default
1588** register value
1589**
1590** Revision History:
1591**
1592** SCR Date Author Description
1593** -------------------------------------------------------------------------
1594** 138 06-19-2007 DAD Ver 1.00: Initial, derived from mt2067_b.
1595**
1596****************************************************************************/
dcd52d20 1597static u32 MT2063_SetReg(struct mt2063_state *state, u8 reg, u8 val)
0e301442 1598{
31e67fae 1599 u32 status;
0e301442 1600
0e301442 1601 if (reg >= MT2063_REG_END_REGS)
31e67fae 1602 return -ERANGE;
0e301442 1603
31e67fae
MCC
1604 status = mt2063_write(state, reg, &val, 1);
1605 if (status < 0)
1606 return status;
0e301442 1607
31e67fae
MCC
1608 state->reg[reg] = val;
1609
1610 return 0;
0e301442
MCC
1611}
1612
cfde8925 1613static u32 MT2063_Round_fLO(u32 f_LO, u32 f_LO_Step, u32 f_ref)
0e301442
MCC
1614{
1615 return f_ref * (f_LO / f_ref)
1616 + f_LO_Step * (((f_LO % f_ref) + (f_LO_Step / 2)) / f_LO_Step);
1617}
1618
1619/****************************************************************************
1620**
1621** Name: fLO_FractionalTerm
1622**
1623** Description: Calculates the portion contributed by FracN / denom.
1624**
1625** This function preserves maximum precision without
1626** risk of overflow. It accurately calculates
1627** f_ref * num / denom to within 1 HZ with fixed math.
1628**
1629** Parameters: num - Fractional portion of the multiplier
1630** denom - denominator portion of the ratio
1631** This routine successfully handles denom values
1632** up to and including 2^18.
1633** f_Ref - SRO frequency. This calculation handles
1634** f_ref as two separate 14-bit fields.
1635** Therefore, a maximum value of 2^28-1
1636** may safely be used for f_ref. This is
1637** the genesis of the magic number "14" and the
1638** magic mask value of 0x03FFF.
1639**
1640** Returns: f_ref * num / denom
1641**
1642** Revision History:
1643**
1644** SCR Date Author Description
1645** -------------------------------------------------------------------------
1646** 138 06-19-2007 DAD Ver 1.00: Initial, derived from mt2067_b.
1647**
1648****************************************************************************/
cfde8925
MCC
1649static u32 MT2063_fLO_FractionalTerm(u32 f_ref,
1650 u32 num, u32 denom)
0e301442 1651{
cfde8925
MCC
1652 u32 t1 = (f_ref >> 14) * num;
1653 u32 term1 = t1 / denom;
1654 u32 loss = t1 % denom;
1655 u32 term2 =
0e301442
MCC
1656 (((f_ref & 0x00003FFF) * num + (loss << 14)) + (denom / 2)) / denom;
1657 return ((term1 << 14) + term2);
1658}
1659
1660/****************************************************************************
1661**
1662** Name: CalcLO1Mult
1663**
1664** Description: Calculates Integer divider value and the numerator
1665** value for a FracN PLL.
1666**
1667** This function assumes that the f_LO and f_Ref are
1668** evenly divisible by f_LO_Step.
1669**
1670** Parameters: Div - OUTPUT: Whole number portion of the multiplier
1671** FracN - OUTPUT: Fractional portion of the multiplier
1672** f_LO - desired LO frequency.
1673** f_LO_Step - Minimum step size for the LO (in Hz).
1674** f_Ref - SRO frequency.
1675** f_Avoid - Range of PLL frequencies to avoid near
1676** integer multiples of f_Ref (in Hz).
1677**
1678** Returns: Recalculated LO frequency.
1679**
1680** Revision History:
1681**
1682** SCR Date Author Description
1683** -------------------------------------------------------------------------
1684** 138 06-19-2007 DAD Ver 1.00: Initial, derived from mt2067_b.
1685**
1686****************************************************************************/
cfde8925
MCC
1687static u32 MT2063_CalcLO1Mult(u32 * Div,
1688 u32 * FracN,
1689 u32 f_LO,
1690 u32 f_LO_Step, u32 f_Ref)
0e301442
MCC
1691{
1692 /* Calculate the whole number portion of the divider */
1693 *Div = f_LO / f_Ref;
1694
1695 /* Calculate the numerator value (round to nearest f_LO_Step) */
1696 *FracN =
1697 (64 * (((f_LO % f_Ref) + (f_LO_Step / 2)) / f_LO_Step) +
1698 (f_Ref / f_LO_Step / 2)) / (f_Ref / f_LO_Step);
1699
1700 return (f_Ref * (*Div)) + MT2063_fLO_FractionalTerm(f_Ref, *FracN, 64);
1701}
1702
1703/****************************************************************************
1704**
1705** Name: CalcLO2Mult
1706**
1707** Description: Calculates Integer divider value and the numerator
1708** value for a FracN PLL.
1709**
1710** This function assumes that the f_LO and f_Ref are
1711** evenly divisible by f_LO_Step.
1712**
1713** Parameters: Div - OUTPUT: Whole number portion of the multiplier
1714** FracN - OUTPUT: Fractional portion of the multiplier
1715** f_LO - desired LO frequency.
1716** f_LO_Step - Minimum step size for the LO (in Hz).
1717** f_Ref - SRO frequency.
1718** f_Avoid - Range of PLL frequencies to avoid near
1719** integer multiples of f_Ref (in Hz).
1720**
1721** Returns: Recalculated LO frequency.
1722**
1723** Revision History:
1724**
1725** SCR Date Author Description
1726** -------------------------------------------------------------------------
1727** 138 06-19-2007 DAD Ver 1.00: Initial, derived from mt2067_b.
1728**
1729****************************************************************************/
cfde8925
MCC
1730static u32 MT2063_CalcLO2Mult(u32 * Div,
1731 u32 * FracN,
1732 u32 f_LO,
1733 u32 f_LO_Step, u32 f_Ref)
0e301442
MCC
1734{
1735 /* Calculate the whole number portion of the divider */
1736 *Div = f_LO / f_Ref;
1737
1738 /* Calculate the numerator value (round to nearest f_LO_Step) */
1739 *FracN =
1740 (8191 * (((f_LO % f_Ref) + (f_LO_Step / 2)) / f_LO_Step) +
1741 (f_Ref / f_LO_Step / 2)) / (f_Ref / f_LO_Step);
1742
1743 return (f_Ref * (*Div)) + MT2063_fLO_FractionalTerm(f_Ref, *FracN,
1744 8191);
1745}
1746
1747/****************************************************************************
1748**
1749** Name: FindClearTuneFilter
1750**
1751** Description: Calculate the corrrect ClearTune filter to be used for
1752** a given input frequency.
1753**
dcd52d20 1754** Parameters: state - ptr to tuner data structure
0e301442
MCC
1755** f_in - RF input center frequency (in Hz).
1756**
1757** Returns: ClearTune filter number (0-31)
1758**
1759** Dependencies: MUST CALL MT2064_Open BEFORE FindClearTuneFilter!
1760**
1761** Revision History:
1762**
1763** SCR Date Author Description
1764** -------------------------------------------------------------------------
1765** 04-10-2008 PINZ Ver 1.14: Use software-controlled ClearTune
1766** cross-over frequency values.
1767**
1768****************************************************************************/
dcd52d20 1769static u32 FindClearTuneFilter(struct mt2063_state *state, u32 f_in)
0e301442 1770{
cfde8925
MCC
1771 u32 RFBand;
1772 u32 idx; /* index loop */
0e301442
MCC
1773
1774 /*
1775 ** Find RF Band setting
1776 */
1777 RFBand = 31; /* def when f_in > all */
1778 for (idx = 0; idx < 31; ++idx) {
dcd52d20 1779 if (state->CTFiltMax[idx] >= f_in) {
0e301442
MCC
1780 RFBand = idx;
1781 break;
1782 }
1783 }
31e67fae 1784 return RFBand;
0e301442
MCC
1785}
1786
1787/****************************************************************************
1788**
1789** Name: MT2063_Tune
1790**
1791** Description: Change the tuner's tuned frequency to RFin.
1792**
1793** Parameters: h - Open handle to the tuner (from MT2063_Open).
1794** f_in - RF input center frequency (in Hz).
1795**
1796** Returns: status:
1797** MT_OK - No errors
1798** MT_INV_HANDLE - Invalid tuner handle
1799** MT_UPC_UNLOCK - Upconverter PLL unlocked
1800** MT_DNC_UNLOCK - Downconverter PLL unlocked
1801** MT_COMM_ERR - Serial bus communications error
1802** MT_SPUR_CNT_MASK - Count of avoided LO spurs
1803** MT_SPUR_PRESENT - LO spur possible in output
1804** MT_FIN_RANGE - Input freq out of range
1805** MT_FOUT_RANGE - Output freq out of range
1806** MT_UPC_RANGE - Upconverter freq out of range
1807** MT_DNC_RANGE - Downconverter freq out of range
1808**
1809** Dependencies: MUST CALL MT2063_Open BEFORE MT2063_Tune!
1810**
1811** MT_ReadSub - Read data from the two-wire serial bus
1812** MT_WriteSub - Write data to the two-wire serial bus
1813** MT_Sleep - Delay execution for x milliseconds
1814** MT2063_GetLocked - Checks to see if LO1 and LO2 are locked
1815**
1816** Revision History:
1817**
1818** SCR Date Author Description
1819** -------------------------------------------------------------------------
1820** 138 06-19-2007 DAD Ver 1.00: Initial, derived from mt2067_b.
1821** 04-10-2008 PINZ Ver 1.05: Use software-controlled ClearTune
1822** cross-over frequency values.
1823** 175 I 16-06-2008 PINZ Ver 1.16: Add control to avoid US DECT freqs.
1824** 175 I 06-19-2008 RSK Ver 1.17: Refactor DECT control to SpurAvoid.
1825** 06-24-2008 PINZ Ver 1.18: Add Get/SetParam CTFILT_SW
1826**
1827****************************************************************************/
dcd52d20 1828static u32 MT2063_Tune(struct mt2063_state *state, u32 f_in)
0e301442 1829{ /* RF input center frequency */
0e301442 1830
fdf77a4f 1831 u32 status = 0; /* status of operation */
cfde8925
MCC
1832 u32 LO1; /* 1st LO register value */
1833 u32 Num1; /* Numerator for LO1 reg. value */
1834 u32 f_IF1; /* 1st IF requested */
1835 u32 LO2; /* 2nd LO register value */
1836 u32 Num2; /* Numerator for LO2 reg. value */
1837 u32 ofLO1, ofLO2; /* last time's LO frequencies */
1838 u32 ofin, ofout; /* last time's I/O frequencies */
1839 u8 fiffc = 0x80; /* FIFF center freq from tuner */
1840 u32 fiffof; /* Offset from FIFF center freq */
1841 const u8 LO1LK = 0x80; /* Mask for LO1 Lock bit */
1842 u8 LO2LK = 0x08; /* Mask for LO2 Lock bit */
1843 u8 val;
1844 u32 RFBand;
0e301442 1845
0e301442
MCC
1846 /* Check the input and output frequency ranges */
1847 if ((f_in < MT2063_MIN_FIN_FREQ) || (f_in > MT2063_MAX_FIN_FREQ))
fdf77a4f 1848 return -EINVAL;
0e301442 1849
dcd52d20
MCC
1850 if ((state->AS_Data.f_out < MT2063_MIN_FOUT_FREQ)
1851 || (state->AS_Data.f_out > MT2063_MAX_FOUT_FREQ))
fdf77a4f 1852 return -EINVAL;
0e301442
MCC
1853
1854 /*
1855 ** Save original LO1 and LO2 register values
1856 */
dcd52d20
MCC
1857 ofLO1 = state->AS_Data.f_LO1;
1858 ofLO2 = state->AS_Data.f_LO2;
1859 ofin = state->AS_Data.f_in;
1860 ofout = state->AS_Data.f_out;
0e301442
MCC
1861
1862 /*
1863 ** Find and set RF Band setting
1864 */
dcd52d20
MCC
1865 if (state->ctfilt_sw == 1) {
1866 val = (state->reg[MT2063_REG_CTUNE_CTRL] | 0x08);
1867 if (state->reg[MT2063_REG_CTUNE_CTRL] != val) {
0e301442 1868 status |=
dcd52d20 1869 MT2063_SetReg(state, MT2063_REG_CTUNE_CTRL, val);
0e301442 1870 }
dcd52d20
MCC
1871 val = state->reg[MT2063_REG_CTUNE_OV];
1872 RFBand = FindClearTuneFilter(state, f_in);
1873 state->reg[MT2063_REG_CTUNE_OV] =
1874 (u8) ((state->reg[MT2063_REG_CTUNE_OV] & ~0x1F)
0e301442 1875 | RFBand);
dcd52d20 1876 if (state->reg[MT2063_REG_CTUNE_OV] != val) {
0e301442 1877 status |=
dcd52d20 1878 MT2063_SetReg(state, MT2063_REG_CTUNE_OV, val);
0e301442
MCC
1879 }
1880 }
1881
1882 /*
1883 ** Read the FIFF Center Frequency from the tuner
1884 */
fdf77a4f 1885 if (status >= 0) {
0e301442 1886 status |=
e1de3d18 1887 mt2063_read(state,
0e301442 1888 MT2063_REG_FIFFC,
dcd52d20
MCC
1889 &state->reg[MT2063_REG_FIFFC], 1);
1890 fiffc = state->reg[MT2063_REG_FIFFC];
0e301442
MCC
1891 }
1892 /*
1893 ** Assign in the requested values
1894 */
dcd52d20 1895 state->AS_Data.f_in = f_in;
0e301442 1896 /* Request a 1st IF such that LO1 is on a step size */
dcd52d20
MCC
1897 state->AS_Data.f_if1_Request =
1898 MT2063_Round_fLO(state->AS_Data.f_if1_Request + f_in,
1899 state->AS_Data.f_LO1_Step,
1900 state->AS_Data.f_ref) - f_in;
0e301442
MCC
1901
1902 /*
1903 ** Calculate frequency settings. f_IF1_FREQ + f_in is the
1904 ** desired LO1 frequency
1905 */
dcd52d20 1906 MT2063_ResetExclZones(&state->AS_Data);
0e301442 1907
dcd52d20 1908 f_IF1 = MT2063_ChooseFirstIF(&state->AS_Data);
0e301442 1909
dcd52d20
MCC
1910 state->AS_Data.f_LO1 =
1911 MT2063_Round_fLO(f_IF1 + f_in, state->AS_Data.f_LO1_Step,
1912 state->AS_Data.f_ref);
0e301442 1913
dcd52d20
MCC
1914 state->AS_Data.f_LO2 =
1915 MT2063_Round_fLO(state->AS_Data.f_LO1 - state->AS_Data.f_out - f_in,
1916 state->AS_Data.f_LO2_Step, state->AS_Data.f_ref);
0e301442
MCC
1917
1918 /*
1919 ** Check for any LO spurs in the output bandwidth and adjust
1920 ** the LO settings to avoid them if needed
1921 */
dcd52d20 1922 status |= MT2063_AvoidSpurs(state, &state->AS_Data);
0e301442
MCC
1923 /*
1924 ** MT_AvoidSpurs spurs may have changed the LO1 & LO2 values.
1925 ** Recalculate the LO frequencies and the values to be placed
1926 ** in the tuning registers.
1927 */
dcd52d20
MCC
1928 state->AS_Data.f_LO1 =
1929 MT2063_CalcLO1Mult(&LO1, &Num1, state->AS_Data.f_LO1,
1930 state->AS_Data.f_LO1_Step, state->AS_Data.f_ref);
1931 state->AS_Data.f_LO2 =
1932 MT2063_Round_fLO(state->AS_Data.f_LO1 - state->AS_Data.f_out - f_in,
1933 state->AS_Data.f_LO2_Step, state->AS_Data.f_ref);
1934 state->AS_Data.f_LO2 =
1935 MT2063_CalcLO2Mult(&LO2, &Num2, state->AS_Data.f_LO2,
1936 state->AS_Data.f_LO2_Step, state->AS_Data.f_ref);
0e301442
MCC
1937
1938 /*
1939 ** Check the upconverter and downconverter frequency ranges
1940 */
dcd52d20
MCC
1941 if ((state->AS_Data.f_LO1 < MT2063_MIN_UPC_FREQ)
1942 || (state->AS_Data.f_LO1 > MT2063_MAX_UPC_FREQ))
0e301442 1943 status |= MT2063_UPC_RANGE;
dcd52d20
MCC
1944 if ((state->AS_Data.f_LO2 < MT2063_MIN_DNC_FREQ)
1945 || (state->AS_Data.f_LO2 > MT2063_MAX_DNC_FREQ))
0e301442
MCC
1946 status |= MT2063_DNC_RANGE;
1947 /* LO2 Lock bit was in a different place for B0 version */
dcd52d20 1948 if (state->tuner_id == MT2063_B0)
0e301442
MCC
1949 LO2LK = 0x40;
1950
1951 /*
1952 ** If we have the same LO frequencies and we're already locked,
1953 ** then skip re-programming the LO registers.
1954 */
dcd52d20
MCC
1955 if ((ofLO1 != state->AS_Data.f_LO1)
1956 || (ofLO2 != state->AS_Data.f_LO2)
1957 || ((state->reg[MT2063_REG_LO_STATUS] & (LO1LK | LO2LK)) !=
0e301442
MCC
1958 (LO1LK | LO2LK))) {
1959 /*
1960 ** Calculate the FIFFOF register value
1961 **
1962 ** IF1_Actual
1963 ** FIFFOF = ------------ - 8 * FIFFC - 4992
1964 ** f_ref/64
1965 */
1966 fiffof =
dcd52d20
MCC
1967 (state->AS_Data.f_LO1 -
1968 f_in) / (state->AS_Data.f_ref / 64) - 8 * (u32) fiffc -
0e301442
MCC
1969 4992;
1970 if (fiffof > 0xFF)
1971 fiffof = 0xFF;
1972
1973 /*
1974 ** Place all of the calculated values into the local tuner
1975 ** register fields.
1976 */
fdf77a4f 1977 if (status >= 0) {
dcd52d20
MCC
1978 state->reg[MT2063_REG_LO1CQ_1] = (u8) (LO1 & 0xFF); /* DIV1q */
1979 state->reg[MT2063_REG_LO1CQ_2] = (u8) (Num1 & 0x3F); /* NUM1q */
1980 state->reg[MT2063_REG_LO2CQ_1] = (u8) (((LO2 & 0x7F) << 1) /* DIV2q */
0e301442 1981 |(Num2 >> 12)); /* NUM2q (hi) */
dcd52d20
MCC
1982 state->reg[MT2063_REG_LO2CQ_2] = (u8) ((Num2 & 0x0FF0) >> 4); /* NUM2q (mid) */
1983 state->reg[MT2063_REG_LO2CQ_3] = (u8) (0xE0 | (Num2 & 0x000F)); /* NUM2q (lo) */
0e301442
MCC
1984
1985 /*
1986 ** Now write out the computed register values
1987 ** IMPORTANT: There is a required order for writing
1988 ** (0x05 must follow all the others).
1989 */
e1de3d18 1990 status |= mt2063_write(state, MT2063_REG_LO1CQ_1, &state->reg[MT2063_REG_LO1CQ_1], 5); /* 0x01 - 0x05 */
dcd52d20 1991 if (state->tuner_id == MT2063_B0) {
0e301442 1992 /* Re-write the one-shot bits to trigger the tune operation */
e1de3d18 1993 status |= mt2063_write(state, MT2063_REG_LO2CQ_3, &state->reg[MT2063_REG_LO2CQ_3], 1); /* 0x05 */
0e301442
MCC
1994 }
1995 /* Write out the FIFF offset only if it's changing */
dcd52d20 1996 if (state->reg[MT2063_REG_FIFF_OFFSET] !=
cfde8925 1997 (u8) fiffof) {
dcd52d20 1998 state->reg[MT2063_REG_FIFF_OFFSET] =
cfde8925 1999 (u8) fiffof;
0e301442 2000 status |=
e1de3d18 2001 mt2063_write(state,
0e301442 2002 MT2063_REG_FIFF_OFFSET,
dcd52d20 2003 &state->
0e301442
MCC
2004 reg[MT2063_REG_FIFF_OFFSET],
2005 1);
2006 }
2007 }
2008
2009 /*
2010 ** Check for LO's locking
2011 */
2012
31e67fae
MCC
2013 if (status < 0)
2014 return status;
2015
2016 status = mt2063_lockStatus(state);
2017 if (status < 0)
2018 return status;
2019 if (!status)
2020 return -EINVAL; /* Couldn't lock */
2021
0e301442 2022 /*
31e67fae 2023 * If we locked OK, assign calculated data to mt2063_state structure
0e301442 2024 */
31e67fae 2025 state->f_IF1_actual = state->AS_Data.f_LO1 - f_in;
0e301442
MCC
2026 }
2027
31e67fae 2028 return status;
0e301442
MCC
2029}
2030
4713e225 2031int mt2063_setTune(struct dvb_frontend *fe, u32 f_in, u32 bw_in,
fad11dbc 2032 enum MTTune_atv_standard tv_type)
0e301442 2033{
4713e225 2034 struct mt2063_state *state = fe->tuner_priv;
fdf77a4f 2035 u32 status = 0;
cfde8925
MCC
2036 s32 pict_car = 0;
2037 s32 pict2chanb_vsb = 0;
2038 s32 pict2chanb_snd = 0;
2039 s32 pict2snd1 = 0;
2040 s32 pict2snd2 = 0;
2041 s32 ch_bw = 0;
cfde8925
MCC
2042 s32 if_mid = 0;
2043 s32 rcvr_mode = 0;
0e301442
MCC
2044
2045 switch (tv_type) {
2046 case MTTUNEA_PAL_B:{
2047 pict_car = 38900000;
2048 ch_bw = 8000000;
2049 pict2chanb_vsb = -1250000;
2050 pict2snd1 = 5500000;
2051 pict2snd2 = 5742000;
2052 rcvr_mode = 1;
2053 break;
2054 }
2055 case MTTUNEA_PAL_G:{
2056 pict_car = 38900000;
2057 ch_bw = 7000000;
2058 pict2chanb_vsb = -1250000;
2059 pict2snd1 = 5500000;
2060 pict2snd2 = 0;
2061 rcvr_mode = 1;
2062 break;
2063 }
2064 case MTTUNEA_PAL_I:{
2065 pict_car = 38900000;
2066 ch_bw = 8000000;
2067 pict2chanb_vsb = -1250000;
2068 pict2snd1 = 6000000;
2069 pict2snd2 = 0;
2070 rcvr_mode = 1;
2071 break;
2072 }
2073 case MTTUNEA_PAL_L:{
2074 pict_car = 38900000;
2075 ch_bw = 8000000;
2076 pict2chanb_vsb = -1250000;
2077 pict2snd1 = 6500000;
2078 pict2snd2 = 0;
2079 rcvr_mode = 1;
2080 break;
2081 }
2082 case MTTUNEA_PAL_MN:{
2083 pict_car = 38900000;
2084 ch_bw = 6000000;
2085 pict2chanb_vsb = -1250000;
2086 pict2snd1 = 4500000;
2087 pict2snd2 = 0;
2088 rcvr_mode = 1;
2089 break;
2090 }
2091 case MTTUNEA_PAL_DK:{
2092 pict_car = 38900000;
2093 ch_bw = 8000000;
2094 pict2chanb_vsb = -1250000;
2095 pict2snd1 = 6500000;
2096 pict2snd2 = 0;
2097 rcvr_mode = 1;
2098 break;
2099 }
2100 case MTTUNEA_DIGITAL:{
2101 pict_car = 36125000;
2102 ch_bw = 8000000;
2103 pict2chanb_vsb = -(ch_bw / 2);
2104 pict2snd1 = 0;
2105 pict2snd2 = 0;
2106 rcvr_mode = 2;
2107 break;
2108 }
2109 case MTTUNEA_FMRADIO:{
2110 pict_car = 38900000;
2111 ch_bw = 8000000;
2112 pict2chanb_vsb = -(ch_bw / 2);
2113 pict2snd1 = 0;
2114 pict2snd2 = 0;
2115 rcvr_mode = 4;
2116 //f_in -= 2900000;
2117 break;
2118 }
2119 case MTTUNEA_DVBC:{
2120 pict_car = 36125000;
2121 ch_bw = 8000000;
2122 pict2chanb_vsb = -(ch_bw / 2);
2123 pict2snd1 = 0;
2124 pict2snd2 = 0;
2125 rcvr_mode = MT2063_CABLE_QAM;
2126 break;
2127 }
2128 case MTTUNEA_DVBT:{
2129 pict_car = 36125000;
2130 ch_bw = bw_in; //8000000
2131 pict2chanb_vsb = -(ch_bw / 2);
2132 pict2snd1 = 0;
2133 pict2snd2 = 0;
2134 rcvr_mode = MT2063_OFFAIR_COFDM;
2135 break;
2136 }
2137 case MTTUNEA_UNKNOWN:
2138 break;
2139 default:
2140 break;
2141 }
2142
2143 pict2chanb_snd = pict2chanb_vsb - ch_bw;
2144 if_mid = pict_car - (pict2chanb_vsb + (ch_bw / 2));
2145
4713e225
MCC
2146 state->AS_Data.f_LO2_Step = 125000;
2147 state->AS_Data.f_out = if_mid;
2148 state->AS_Data.f_out_bw = ch_bw + 750000;
2149 status = MT2063_SetReceiverMode(state, rcvr_mode);
2150 if (status < 0)
2151 return status;
0e301442 2152
4713e225 2153 status = MT2063_Tune(state, (f_in + (pict2chanb_vsb + (ch_bw / 2))));
0e301442 2154
4713e225 2155 return status;
0e301442
MCC
2156}
2157
01e0dafc
MCC
2158static const u8 MT2063B0_defaults[] = {
2159 /* Reg, Value */
2160 0x19, 0x05,
2161 0x1B, 0x1D,
2162 0x1C, 0x1F,
2163 0x1D, 0x0F,
2164 0x1E, 0x3F,
2165 0x1F, 0x0F,
2166 0x20, 0x3F,
2167 0x22, 0x21,
2168 0x23, 0x3F,
2169 0x24, 0x20,
2170 0x25, 0x3F,
2171 0x27, 0xEE,
2172 0x2C, 0x27, /* bit at 0x20 is cleared below */
2173 0x30, 0x03,
2174 0x2C, 0x07, /* bit at 0x20 is cleared here */
2175 0x2D, 0x87,
2176 0x2E, 0xAA,
2177 0x28, 0xE1, /* Set the FIFCrst bit here */
2178 0x28, 0xE0, /* Clear the FIFCrst bit here */
2179 0x00
2180};
2181
2182/* writing 0x05 0xf0 sw-resets all registers, so we write only needed changes */
2183static const u8 MT2063B1_defaults[] = {
2184 /* Reg, Value */
2185 0x05, 0xF0,
2186 0x11, 0x10, /* New Enable AFCsd */
2187 0x19, 0x05,
2188 0x1A, 0x6C,
2189 0x1B, 0x24,
2190 0x1C, 0x28,
2191 0x1D, 0x8F,
2192 0x1E, 0x14,
2193 0x1F, 0x8F,
2194 0x20, 0x57,
2195 0x22, 0x21, /* New - ver 1.03 */
2196 0x23, 0x3C, /* New - ver 1.10 */
2197 0x24, 0x20, /* New - ver 1.03 */
2198 0x2C, 0x24, /* bit at 0x20 is cleared below */
2199 0x2D, 0x87, /* FIFFQ=0 */
2200 0x2F, 0xF3,
2201 0x30, 0x0C, /* New - ver 1.11 */
2202 0x31, 0x1B, /* New - ver 1.11 */
2203 0x2C, 0x04, /* bit at 0x20 is cleared here */
2204 0x28, 0xE1, /* Set the FIFCrst bit here */
2205 0x28, 0xE0, /* Clear the FIFCrst bit here */
2206 0x00
2207};
2208
2209/* writing 0x05 0xf0 sw-resets all registers, so we write only needed changes */
2210static const u8 MT2063B3_defaults[] = {
2211 /* Reg, Value */
2212 0x05, 0xF0,
2213 0x19, 0x3D,
2214 0x2C, 0x24, /* bit at 0x20 is cleared below */
2215 0x2C, 0x04, /* bit at 0x20 is cleared here */
2216 0x28, 0xE1, /* Set the FIFCrst bit here */
2217 0x28, 0xE0, /* Clear the FIFCrst bit here */
2218 0x00
2219};
2220
0e301442
MCC
2221static int mt2063_init(struct dvb_frontend *fe)
2222{
01e0dafc 2223 u32 status;
0e301442 2224 struct mt2063_state *state = fe->tuner_priv;
01e0dafc
MCC
2225 u8 all_resets = 0xF0; /* reset/load bits */
2226 const u8 *def = NULL;
2227 u32 FCRUN;
2228 s32 maxReads;
2229 u32 fcu_osc;
2230 u32 i;
2231
2232 state->rcvr_mode = MT2063_CABLE_QAM;
2233
2234 /* Read the Part/Rev code from the tuner */
2235 status = mt2063_read(state, MT2063_REG_PART_REV, state->reg, 1);
2236 if (status < 0)
2237 return status;
2238
2239 /* Check the part/rev code */
2240 if (((state->reg[MT2063_REG_PART_REV] != MT2063_B0) /* MT2063 B0 */
2241 &&(state->reg[MT2063_REG_PART_REV] != MT2063_B1) /* MT2063 B1 */
2242 &&(state->reg[MT2063_REG_PART_REV] != MT2063_B3))) /* MT2063 B3 */
2243 return -ENODEV; /* Wrong tuner Part/Rev code */
0e301442 2244
01e0dafc
MCC
2245 /* Check the 2nd byte of the Part/Rev code from the tuner */
2246 status = mt2063_read(state, MT2063_REG_RSVD_3B,
2247 &state->reg[MT2063_REG_RSVD_3B], 1);
0e301442 2248
01e0dafc
MCC
2249 /* b7 != 0 ==> NOT MT2063 */
2250 if (status < 0 ||((state->reg[MT2063_REG_RSVD_3B] & 0x80) != 0x00))
2251 return -ENODEV; /* Wrong tuner Part/Rev code */
2252
2253 /* Reset the tuner */
2254 status = mt2063_write(state, MT2063_REG_LO2CQ_3, &all_resets, 1);
2255 if (status < 0)
2256 return status;
2257
2258 /* change all of the default values that vary from the HW reset values */
2259 /* def = (state->reg[PART_REV] == MT2063_B0) ? MT2063B0_defaults : MT2063B1_defaults; */
2260 switch (state->reg[MT2063_REG_PART_REV]) {
2261 case MT2063_B3:
2262 def = MT2063B3_defaults;
2263 break;
2264
2265 case MT2063_B1:
2266 def = MT2063B1_defaults;
2267 break;
2268
2269 case MT2063_B0:
2270 def = MT2063B0_defaults;
2271 break;
2272
2273 default:
2274 return -ENODEV;
2275 break;
0e301442
MCC
2276 }
2277
01e0dafc
MCC
2278 while (status >= 0 && *def) {
2279 u8 reg = *def++;
2280 u8 val = *def++;
2281 status = mt2063_write(state, reg, &val, 1);
2282 }
2283 if (status < 0)
2284 return status;
2285
2286 /* Wait for FIFF location to complete. */
2287 FCRUN = 1;
2288 maxReads = 10;
2289 while (status >= 0 && (FCRUN != 0) && (maxReads-- > 0)) {
2290 msleep(2);
2291 status = mt2063_read(state,
2292 MT2063_REG_XO_STATUS,
2293 &state->
2294 reg[MT2063_REG_XO_STATUS], 1);
2295 FCRUN = (state->reg[MT2063_REG_XO_STATUS] & 0x40) >> 6;
2296 }
2297
2298 if (FCRUN != 0 || status < 0)
2299 return -ENODEV;
2300
2301 status = mt2063_read(state,
2302 MT2063_REG_FIFFC,
2303 &state->reg[MT2063_REG_FIFFC], 1);
2304 if (status < 0)
2305 return status;
2306
2307 /* Read back all the registers from the tuner */
2308 status = mt2063_read(state,
2309 MT2063_REG_PART_REV,
2310 state->reg, MT2063_REG_END_REGS);
2311 if (status < 0)
2312 return status;
2313
2314 /* Initialize the tuner state. */
2315 state->tuner_id = state->reg[MT2063_REG_PART_REV];
2316 state->AS_Data.f_ref = MT2063_REF_FREQ;
2317 state->AS_Data.f_if1_Center = (state->AS_Data.f_ref / 8) *
2318 ((u32) state->reg[MT2063_REG_FIFFC] + 640);
2319 state->AS_Data.f_if1_bw = MT2063_IF1_BW;
2320 state->AS_Data.f_out = 43750000UL;
2321 state->AS_Data.f_out_bw = 6750000UL;
2322 state->AS_Data.f_zif_bw = MT2063_ZIF_BW;
2323 state->AS_Data.f_LO1_Step = state->AS_Data.f_ref / 64;
2324 state->AS_Data.f_LO2_Step = MT2063_TUNE_STEP_SIZE;
2325 state->AS_Data.maxH1 = MT2063_MAX_HARMONICS_1;
2326 state->AS_Data.maxH2 = MT2063_MAX_HARMONICS_2;
2327 state->AS_Data.f_min_LO_Separation = MT2063_MIN_LO_SEP;
2328 state->AS_Data.f_if1_Request = state->AS_Data.f_if1_Center;
2329 state->AS_Data.f_LO1 = 2181000000UL;
2330 state->AS_Data.f_LO2 = 1486249786UL;
2331 state->f_IF1_actual = state->AS_Data.f_if1_Center;
2332 state->AS_Data.f_in = state->AS_Data.f_LO1 - state->f_IF1_actual;
2333 state->AS_Data.f_LO1_FracN_Avoid = MT2063_LO1_FRACN_AVOID;
2334 state->AS_Data.f_LO2_FracN_Avoid = MT2063_LO2_FRACN_AVOID;
2335 state->num_regs = MT2063_REG_END_REGS;
2336 state->AS_Data.avoidDECT = MT2063_AVOID_BOTH;
2337 state->ctfilt_sw = 0;
2338
2339 state->CTFiltMax[0] = 69230000;
2340 state->CTFiltMax[1] = 105770000;
2341 state->CTFiltMax[2] = 140350000;
2342 state->CTFiltMax[3] = 177110000;
2343 state->CTFiltMax[4] = 212860000;
2344 state->CTFiltMax[5] = 241130000;
2345 state->CTFiltMax[6] = 274370000;
2346 state->CTFiltMax[7] = 309820000;
2347 state->CTFiltMax[8] = 342450000;
2348 state->CTFiltMax[9] = 378870000;
2349 state->CTFiltMax[10] = 416210000;
2350 state->CTFiltMax[11] = 456500000;
2351 state->CTFiltMax[12] = 495790000;
2352 state->CTFiltMax[13] = 534530000;
2353 state->CTFiltMax[14] = 572610000;
2354 state->CTFiltMax[15] = 598970000;
2355 state->CTFiltMax[16] = 635910000;
2356 state->CTFiltMax[17] = 672130000;
2357 state->CTFiltMax[18] = 714840000;
2358 state->CTFiltMax[19] = 739660000;
2359 state->CTFiltMax[20] = 770410000;
2360 state->CTFiltMax[21] = 814660000;
2361 state->CTFiltMax[22] = 846950000;
2362 state->CTFiltMax[23] = 867820000;
2363 state->CTFiltMax[24] = 915980000;
2364 state->CTFiltMax[25] = 947450000;
2365 state->CTFiltMax[26] = 983110000;
2366 state->CTFiltMax[27] = 1021630000;
2367 state->CTFiltMax[28] = 1061870000;
2368 state->CTFiltMax[29] = 1098330000;
2369 state->CTFiltMax[30] = 1138990000;
2370
2371 /*
2372 ** Fetch the FCU osc value and use it and the fRef value to
2373 ** scale all of the Band Max values
2374 */
2375
2376 state->reg[MT2063_REG_CTUNE_CTRL] = 0x0A;
2377 status = mt2063_write(state, MT2063_REG_CTUNE_CTRL,
2378 &state->reg[MT2063_REG_CTUNE_CTRL], 1);
2379 if (status < 0)
2380 return status;
2381
2382 /* Read the ClearTune filter calibration value */
2383 status = mt2063_read(state, MT2063_REG_FIFFC,
2384 &state->reg[MT2063_REG_FIFFC], 1);
2385 if (status < 0)
2386 return status;
2387
2388 fcu_osc = state->reg[MT2063_REG_FIFFC];
2389
2390 state->reg[MT2063_REG_CTUNE_CTRL] = 0x00;
2391 status = mt2063_write(state, MT2063_REG_CTUNE_CTRL,
2392 &state->reg[MT2063_REG_CTUNE_CTRL], 1);
2393 if (status < 0)
2394 return status;
2395
2396 /* Adjust each of the values in the ClearTune filter cross-over table */
2397 for (i = 0; i < 31; i++)
2398 state->CTFiltMax[i] =(state->CTFiltMax[i] / 768) * (fcu_osc + 640);
2399
2400 status = MT2063_SoftwareShutdown(state, 1);
2401 if (status < 0)
2402 return status;
2403 status = MT2063_ClearPowerMaskBits(state, MT2063_ALL_SD);
2404 if (status < 0)
2405 return status;
2406
0e301442
MCC
2407 return 0;
2408}
2409
0e301442 2410static int mt2063_get_status(struct dvb_frontend *fe, u32 * status)
223c7b05 2411{
0e301442
MCC
2412 int rc = 0;
2413
2414 //get tuner lock status
2415
2416 return rc;
223c7b05 2417}
0e301442
MCC
2418
2419static int mt2063_get_state(struct dvb_frontend *fe,
51f0f7b3 2420 enum tuner_param param, struct tuner_state *tunstate)
0e301442 2421{
51f0f7b3 2422 struct mt2063_state *state = fe->tuner_priv;
0e301442 2423
223c7b05
MCC
2424 switch (param) {
2425 case DVBFE_TUNER_FREQUENCY:
0e301442 2426 //get frequency
223c7b05
MCC
2427 break;
2428 case DVBFE_TUNER_TUNERSTEP:
2429 break;
2430 case DVBFE_TUNER_IFFREQ:
2431 break;
2432 case DVBFE_TUNER_BANDWIDTH:
0e301442 2433 //get bandwidth
223c7b05 2434 break;
0e301442 2435 case DVBFE_TUNER_REFCLOCK:
31e67fae 2436 tunstate->refclock = mt2063_lockStatus(state);
223c7b05
MCC
2437 break;
2438 default:
2439 break;
2440 }
2441
51f0f7b3 2442 return (int)tunstate->refclock;
0e301442
MCC
2443}
2444
2445static int mt2063_set_state(struct dvb_frontend *fe,
51f0f7b3 2446 enum tuner_param param, struct tuner_state *tunstate)
223c7b05 2447{
51f0f7b3 2448 struct mt2063_state *state = fe->tuner_priv;
fdf77a4f 2449 u32 status = 0;
0e301442 2450
223c7b05
MCC
2451 switch (param) {
2452 case DVBFE_TUNER_FREQUENCY:
0e301442
MCC
2453 //set frequency
2454
2455 status =
4713e225 2456 mt2063_setTune(fe,
51f0f7b3
MCC
2457 tunstate->frequency, tunstate->bandwidth,
2458 state->tv_type);
0e301442 2459
51f0f7b3 2460 state->frequency = tunstate->frequency;
223c7b05
MCC
2461 break;
2462 case DVBFE_TUNER_TUNERSTEP:
2463 break;
2464 case DVBFE_TUNER_IFFREQ:
2465 break;
2466 case DVBFE_TUNER_BANDWIDTH:
0e301442 2467 //set bandwidth
51f0f7b3 2468 state->bandwidth = tunstate->bandwidth;
0e301442
MCC
2469 break;
2470 case DVBFE_TUNER_REFCLOCK:
2471
0e301442 2472 break;
223c7b05
MCC
2473 default:
2474 break;
2475 }
2476
0e301442
MCC
2477 return (int)status;
2478}
2479
2480static int mt2063_release(struct dvb_frontend *fe)
223c7b05 2481{
0e301442 2482 struct mt2063_state *state = fe->tuner_priv;
223c7b05
MCC
2483
2484 fe->tuner_priv = NULL;
2485 kfree(state);
2486
2487 return 0;
0e301442
MCC
2488}
2489
2490static struct dvb_tuner_ops mt2063_ops = {
223c7b05 2491 .info = {
0e301442
MCC
2492 .name = "MT2063 Silicon Tuner",
2493 .frequency_min = 45000000,
2494 .frequency_max = 850000000,
2495 .frequency_step = 0,
2496 },
2497
2498 .init = mt2063_init,
bf97555e 2499 .sleep = MT2063_Sleep,
0e301442
MCC
2500 .get_status = mt2063_get_status,
2501 .get_state = mt2063_get_state,
2502 .set_state = mt2063_set_state,
2503 .release = mt2063_release
223c7b05
MCC
2504};
2505
0e301442
MCC
2506struct dvb_frontend *mt2063_attach(struct dvb_frontend *fe,
2507 struct mt2063_config *config,
2508 struct i2c_adapter *i2c)
223c7b05 2509{
0e301442 2510 struct mt2063_state *state = NULL;
223c7b05 2511
0e301442 2512 state = kzalloc(sizeof(struct mt2063_state), GFP_KERNEL);
223c7b05
MCC
2513 if (state == NULL)
2514 goto error;
2515
0e301442
MCC
2516 state->config = config;
2517 state->i2c = i2c;
2518 state->frontend = fe;
2519 state->reference = config->refclock / 1000; /* kHz */
0e301442
MCC
2520 fe->tuner_priv = state;
2521 fe->ops.tuner_ops = mt2063_ops;
223c7b05 2522
0e301442 2523 printk("%s: Attaching MT2063 \n", __func__);
223c7b05
MCC
2524 return fe;
2525
2526error:
2527 kfree(state);
2528 return NULL;
2529}
3d49700f 2530EXPORT_SYMBOL_GPL(mt2063_attach);
223c7b05 2531
223c7b05
MCC
2532MODULE_PARM_DESC(verbose, "Set Verbosity level");
2533
0e301442
MCC
2534MODULE_AUTHOR("Henry");
2535MODULE_DESCRIPTION("MT2063 Silicon tuner");
2536MODULE_LICENSE("GPL");
This page took 0.23208 seconds and 5 git commands to generate.