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