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