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