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