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