blob: a43a859cf0631faee417a8e747584790af366ca1 [file] [log] [blame]
Mauro Carvalho Chehab223c7b02011-07-20 19:48:59 -03001#include <linux/init.h>
2#include <linux/kernel.h>
3#include <linux/module.h>
4#include <linux/string.h>
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03005
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03006#include "mt2063.h"
7
Mauro Carvalho Chehab223c7b02011-07-20 19:48:59 -03008static unsigned int verbose;
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03009module_param(verbose, int, 0644);
10
Mauro Carvalho Chehab6d3d7482011-07-20 22:21:26 -030011/* Internal structures and types */
12
Mauro Carvalho Chehab29a0a4fe2011-07-20 23:44:10 -030013/* FIXME: Those two error codes need conversion*/
Mauro Carvalho Chehab6d3d7482011-07-20 22:21:26 -030014/* Error: Upconverter PLL is not locked */
15#define MT2063_UPC_UNLOCK (0x80000002)
Mauro Carvalho Chehab6d3d7482011-07-20 22:21:26 -030016/* Error: Downconverter PLL is not locked */
17#define MT2063_DNC_UNLOCK (0x80000004)
Mauro Carvalho Chehab29a0a4fe2011-07-20 23:44:10 -030018
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -030019/* Info: Unavoidable LO-related spur may be present in the output */
Mauro Carvalho Chehab29a0a4fe2011-07-20 23:44:10 -030020#define MT2063_SPUR_PRESENT_ERR (0x00800000)
Mauro Carvalho Chehab6d3d7482011-07-20 22:21:26 -030021
22/* Info: Mask of bits used for # of LO-related spurs that were avoided during tuning */
23#define MT2063_SPUR_CNT_MASK (0x001f0000)
24#define MT2063_SPUR_SHIFT (16)
25
Mauro Carvalho Chehab6d3d7482011-07-20 22:21:26 -030026/* Info: Upconverter frequency is out of range (may be reason for MT_UPC_UNLOCK) */
27#define MT2063_UPC_RANGE (0x04000000)
28
29/* Info: Downconverter frequency is out of range (may be reason for MT_DPC_UNLOCK) */
30#define MT2063_DNC_RANGE (0x08000000)
31
Mauro Carvalho Chehab6d3d7482011-07-20 22:21:26 -030032/*
Mauro Carvalho Chehab29a0a4fe2011-07-20 23:44:10 -030033 * Data Types
34 */
35
36/*
Mauro Carvalho Chehab6d3d7482011-07-20 22:21:26 -030037 * Constant defining the version of the following structure
38 * and therefore the API for this code.
39 *
40 * When compiling the tuner driver, the preprocessor will
41 * check against this version number to make sure that
42 * it matches the version that the tuner driver knows about.
43 */
Mauro Carvalho Chehab6d3d7482011-07-20 22:21:26 -030044
45/* DECT Frequency Avoidance */
46#define MT2063_DECT_AVOID_US_FREQS 0x00000001
47
48#define MT2063_DECT_AVOID_EURO_FREQS 0x00000002
49
50#define MT2063_EXCLUDE_US_DECT_FREQUENCIES(s) (((s) & MT2063_DECT_AVOID_US_FREQS) != 0)
51
52#define MT2063_EXCLUDE_EURO_DECT_FREQUENCIES(s) (((s) & MT2063_DECT_AVOID_EURO_FREQS) != 0)
53
54enum MT2063_DECT_Avoid_Type {
55 MT2063_NO_DECT_AVOIDANCE = 0, /* Do not create DECT exclusion zones. */
56 MT2063_AVOID_US_DECT = MT2063_DECT_AVOID_US_FREQS, /* Avoid US DECT frequencies. */
57 MT2063_AVOID_EURO_DECT = MT2063_DECT_AVOID_EURO_FREQS, /* Avoid European DECT frequencies. */
58 MT2063_AVOID_BOTH /* Avoid both regions. Not typically used. */
59};
60
61#define MT2063_MAX_ZONES 48
62
Mauro Carvalho Chehab6d3d7482011-07-20 22:21:26 -030063struct MT2063_ExclZone_t {
64 u32 min_;
65 u32 max_;
66 struct MT2063_ExclZone_t *next_;
67};
68
69/*
70 * Structure of data needed for Spur Avoidance
71 */
72struct MT2063_AvoidSpursData_t {
Mauro Carvalho Chehab6d3d7482011-07-20 22:21:26 -030073 u32 f_ref;
74 u32 f_in;
75 u32 f_LO1;
76 u32 f_if1_Center;
77 u32 f_if1_Request;
78 u32 f_if1_bw;
79 u32 f_LO2;
80 u32 f_out;
81 u32 f_out_bw;
82 u32 f_LO1_Step;
83 u32 f_LO2_Step;
84 u32 f_LO1_FracN_Avoid;
85 u32 f_LO2_FracN_Avoid;
86 u32 f_zif_bw;
87 u32 f_min_LO_Separation;
88 u32 maxH1;
89 u32 maxH2;
90 enum MT2063_DECT_Avoid_Type avoidDECT;
91 u32 bSpurPresent;
92 u32 bSpurAvoided;
93 u32 nSpursFound;
94 u32 nZones;
95 struct MT2063_ExclZone_t *freeZones;
96 struct MT2063_ExclZone_t *usedZones;
97 struct MT2063_ExclZone_t MT2063_ExclZones[MT2063_MAX_ZONES];
98};
99
100/*
Mauro Carvalho Chehab6d3d7482011-07-20 22:21:26 -0300101 * Parameter for function MT2063_SetPowerMask that specifies the power down
102 * of various sections of the MT2063.
103 */
104enum MT2063_Mask_Bits {
105 MT2063_REG_SD = 0x0040, /* Shutdown regulator */
106 MT2063_SRO_SD = 0x0020, /* Shutdown SRO */
107 MT2063_AFC_SD = 0x0010, /* Shutdown AFC A/D */
108 MT2063_PD_SD = 0x0002, /* Enable power detector shutdown */
109 MT2063_PDADC_SD = 0x0001, /* Enable power detector A/D shutdown */
110 MT2063_VCO_SD = 0x8000, /* Enable VCO shutdown */
111 MT2063_LTX_SD = 0x4000, /* Enable LTX shutdown */
112 MT2063_LT1_SD = 0x2000, /* Enable LT1 shutdown */
113 MT2063_LNA_SD = 0x1000, /* Enable LNA shutdown */
114 MT2063_UPC_SD = 0x0800, /* Enable upconverter shutdown */
115 MT2063_DNC_SD = 0x0400, /* Enable downconverter shutdown */
116 MT2063_VGA_SD = 0x0200, /* Enable VGA shutdown */
117 MT2063_AMP_SD = 0x0100, /* Enable AMP shutdown */
118 MT2063_ALL_SD = 0xFF73, /* All shutdown bits for this tuner */
119 MT2063_NONE_SD = 0x0000 /* No shutdown bits */
120};
121
122/*
123 * Parameter for function MT2063_GetParam & MT2063_SetParam that
124 * specifies the tuning algorithm parameter to be read/written.
125 */
126enum MT2063_Param {
Mauro Carvalho Chehab6d3d7482011-07-20 22:21:26 -0300127 /* min tuning step size (default: 50000 Hz) */
128 MT2063_STEPSIZE,
129
130 /* input center frequency set by MT2063_Tune() */
131 MT2063_INPUT_FREQ,
132
133 /* LO1 Frequency set by MT2063_Tune() */
134 MT2063_LO1_FREQ,
135
Mauro Carvalho Chehab6d3d7482011-07-20 22:21:26 -0300136 /* LO2 Frequency set by MT2063_Tune() */
137 MT2063_LO2_FREQ,
138
Mauro Carvalho Chehab6d3d7482011-07-20 22:21:26 -0300139 /* output center frequency set by MT2063_Tune() */
140 MT2063_OUTPUT_FREQ,
141
142 /* output bandwidth set by MT2063_Tune() */
143 MT2063_OUTPUT_BW,
144
Mauro Carvalho Chehab6d3d7482011-07-20 22:21:26 -0300145 /* Receiver Mode for some parameters. 1 is DVB-T */
146 MT2063_RCVR_MODE,
147
148 /* directly set LNA attenuation, parameter is value to set */
149 MT2063_ACLNA,
150
151 /* maximum LNA attenuation, parameter is value to set */
152 MT2063_ACLNA_MAX,
153
154 /* directly set ATN attenuation. Paremeter is value to set. */
155 MT2063_ACRF,
156
157 /* maxium ATN attenuation. Paremeter is value to set. */
158 MT2063_ACRF_MAX,
159
160 /* directly set FIF attenuation. Paremeter is value to set. */
161 MT2063_ACFIF,
162
163 /* maxium FIF attenuation. Paremeter is value to set. */
164 MT2063_ACFIF_MAX,
165
166 /* LNA Rin */
167 MT2063_LNA_RIN,
168
169 /* Power Detector LNA level target */
170 MT2063_LNA_TGT,
171
172 /* Power Detector 1 level */
173 MT2063_PD1,
174
175 /* Power Detector 1 level target */
176 MT2063_PD1_TGT,
177
178 /* Power Detector 2 level */
179 MT2063_PD2,
180
181 /* Power Detector 2 level target */
182 MT2063_PD2_TGT,
183
184 /* Selects, which DNC is activ */
185 MT2063_DNC_OUTPUT_ENABLE,
186
Mauro Carvalho Chehab6d3d7482011-07-20 22:21:26 -0300187 MT2063_EOP /* last entry in enumerated list */
188};
189
190/*
191 * Parameter for selecting tuner mode
192 */
193enum MT2063_RCVR_MODES {
194 MT2063_CABLE_QAM = 0, /* Digital cable */
195 MT2063_CABLE_ANALOG, /* Analog cable */
196 MT2063_OFFAIR_COFDM, /* Digital offair */
197 MT2063_OFFAIR_COFDM_SAWLESS, /* Digital offair without SAW */
198 MT2063_OFFAIR_ANALOG, /* Analog offair */
199 MT2063_OFFAIR_8VSB, /* Analog offair */
200 MT2063_NUM_RCVR_MODES
201};
202
203/*
204 * Possible values for MT2063_DNC_OUTPUT
205 */
206enum MT2063_DNC_Output_Enable {
207 MT2063_DNC_NONE = 0,
208 MT2063_DNC_1,
209 MT2063_DNC_2,
210 MT2063_DNC_BOTH
211};
212
213/*
214** Two-wire serial bus subaddresses of the tuner registers.
215** Also known as the tuner's register addresses.
216*/
217enum MT2063_Register_Offsets {
218 MT2063_REG_PART_REV = 0, /* 0x00: Part/Rev Code */
219 MT2063_REG_LO1CQ_1, /* 0x01: LO1C Queued Byte 1 */
220 MT2063_REG_LO1CQ_2, /* 0x02: LO1C Queued Byte 2 */
221 MT2063_REG_LO2CQ_1, /* 0x03: LO2C Queued Byte 1 */
222 MT2063_REG_LO2CQ_2, /* 0x04: LO2C Queued Byte 2 */
223 MT2063_REG_LO2CQ_3, /* 0x05: LO2C Queued Byte 3 */
224 MT2063_REG_RSVD_06, /* 0x06: Reserved */
225 MT2063_REG_LO_STATUS, /* 0x07: LO Status */
226 MT2063_REG_FIFFC, /* 0x08: FIFF Center */
227 MT2063_REG_CLEARTUNE, /* 0x09: ClearTune Filter */
228 MT2063_REG_ADC_OUT, /* 0x0A: ADC_OUT */
229 MT2063_REG_LO1C_1, /* 0x0B: LO1C Byte 1 */
230 MT2063_REG_LO1C_2, /* 0x0C: LO1C Byte 2 */
231 MT2063_REG_LO2C_1, /* 0x0D: LO2C Byte 1 */
232 MT2063_REG_LO2C_2, /* 0x0E: LO2C Byte 2 */
233 MT2063_REG_LO2C_3, /* 0x0F: LO2C Byte 3 */
234 MT2063_REG_RSVD_10, /* 0x10: Reserved */
235 MT2063_REG_PWR_1, /* 0x11: PWR Byte 1 */
236 MT2063_REG_PWR_2, /* 0x12: PWR Byte 2 */
237 MT2063_REG_TEMP_STATUS, /* 0x13: Temp Status */
238 MT2063_REG_XO_STATUS, /* 0x14: Crystal Status */
239 MT2063_REG_RF_STATUS, /* 0x15: RF Attn Status */
240 MT2063_REG_FIF_STATUS, /* 0x16: FIF Attn Status */
241 MT2063_REG_LNA_OV, /* 0x17: LNA Attn Override */
242 MT2063_REG_RF_OV, /* 0x18: RF Attn Override */
243 MT2063_REG_FIF_OV, /* 0x19: FIF Attn Override */
244 MT2063_REG_LNA_TGT, /* 0x1A: Reserved */
245 MT2063_REG_PD1_TGT, /* 0x1B: Pwr Det 1 Target */
246 MT2063_REG_PD2_TGT, /* 0x1C: Pwr Det 2 Target */
247 MT2063_REG_RSVD_1D, /* 0x1D: Reserved */
248 MT2063_REG_RSVD_1E, /* 0x1E: Reserved */
249 MT2063_REG_RSVD_1F, /* 0x1F: Reserved */
250 MT2063_REG_RSVD_20, /* 0x20: Reserved */
251 MT2063_REG_BYP_CTRL, /* 0x21: Bypass Control */
252 MT2063_REG_RSVD_22, /* 0x22: Reserved */
253 MT2063_REG_RSVD_23, /* 0x23: Reserved */
254 MT2063_REG_RSVD_24, /* 0x24: Reserved */
255 MT2063_REG_RSVD_25, /* 0x25: Reserved */
256 MT2063_REG_RSVD_26, /* 0x26: Reserved */
257 MT2063_REG_RSVD_27, /* 0x27: Reserved */
258 MT2063_REG_FIFF_CTRL, /* 0x28: FIFF Control */
259 MT2063_REG_FIFF_OFFSET, /* 0x29: FIFF Offset */
260 MT2063_REG_CTUNE_CTRL, /* 0x2A: Reserved */
261 MT2063_REG_CTUNE_OV, /* 0x2B: Reserved */
262 MT2063_REG_CTRL_2C, /* 0x2C: Reserved */
263 MT2063_REG_FIFF_CTRL2, /* 0x2D: Fiff Control */
264 MT2063_REG_RSVD_2E, /* 0x2E: Reserved */
265 MT2063_REG_DNC_GAIN, /* 0x2F: DNC Control */
266 MT2063_REG_VGA_GAIN, /* 0x30: VGA Gain Ctrl */
267 MT2063_REG_RSVD_31, /* 0x31: Reserved */
268 MT2063_REG_TEMP_SEL, /* 0x32: Temperature Selection */
269 MT2063_REG_RSVD_33, /* 0x33: Reserved */
270 MT2063_REG_RSVD_34, /* 0x34: Reserved */
271 MT2063_REG_RSVD_35, /* 0x35: Reserved */
272 MT2063_REG_RSVD_36, /* 0x36: Reserved */
273 MT2063_REG_RSVD_37, /* 0x37: Reserved */
274 MT2063_REG_RSVD_38, /* 0x38: Reserved */
275 MT2063_REG_RSVD_39, /* 0x39: Reserved */
276 MT2063_REG_RSVD_3A, /* 0x3A: Reserved */
277 MT2063_REG_RSVD_3B, /* 0x3B: Reserved */
278 MT2063_REG_RSVD_3C, /* 0x3C: Reserved */
279 MT2063_REG_END_REGS
280};
281
Mauro Carvalho Chehab6d3d7482011-07-20 22:21:26 -0300282enum MTTune_atv_standard {
283 MTTUNEA_UNKNOWN = 0,
284 MTTUNEA_PAL_B,
285 MTTUNEA_PAL_G,
286 MTTUNEA_PAL_I,
287 MTTUNEA_PAL_L,
288 MTTUNEA_PAL_MN,
289 MTTUNEA_PAL_DK,
290 MTTUNEA_DIGITAL,
291 MTTUNEA_FMRADIO,
292 MTTUNEA_DVBC,
293 MTTUNEA_DVBT
294};
295
296
297struct mt2063_state {
298 struct i2c_adapter *i2c;
299
300 const struct mt2063_config *config;
301 struct dvb_tuner_ops ops;
302 struct dvb_frontend *frontend;
303 struct tuner_state status;
Mauro Carvalho Chehab6d3d7482011-07-20 22:21:26 -0300304
305 enum MTTune_atv_standard tv_type;
306 u32 frequency;
307 u32 srate;
308 u32 bandwidth;
309 u32 reference;
Mauro Carvalho Chehab51f0f7b2011-07-21 02:24:18 -0300310
311 u32 tuner_id;
312 struct MT2063_AvoidSpursData_t AS_Data;
313 u32 f_IF1_actual;
314 u32 rcvr_mode;
315 u32 ctfilt_sw;
316 u32 CTFiltMax[31];
317 u32 num_regs;
318 u8 reg[MT2063_REG_END_REGS];
Mauro Carvalho Chehab6d3d7482011-07-20 22:21:26 -0300319};
Mauro Carvalho Chehab0ff48432011-07-20 20:21:42 -0300320
Mauro Carvalho Chehabbf975552011-07-20 21:43:30 -0300321/* Prototypes */
322static void MT2063_AddExclZone(struct MT2063_AvoidSpursData_t *pAS_Info,
323 u32 f_min, u32 f_max);
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -0300324static u32 MT2063_GetReg(struct mt2063_state *state, u8 reg, u8 * val);
325static u32 MT2063_GetParam(struct mt2063_state *state, enum MT2063_Param param, u32 * pValue);
326static u32 MT2063_SetReg(struct mt2063_state *state, u8 reg, u8 val);
327static u32 MT2063_SetParam(struct mt2063_state *state, enum MT2063_Param param,
Mauro Carvalho Chehab29a0a4fe2011-07-20 23:44:10 -0300328 enum MT2063_DNC_Output_Enable nValue);
Mauro Carvalho Chehab8c64f9322011-07-21 03:29:06 -0300329static u32 MT2063_SoftwareShutdown(struct mt2063_state *state, u8 Shutdown);
330static u32 MT2063_ClearPowerMaskBits(struct mt2063_state *state, enum MT2063_Mask_Bits Bits);
331
Mauro Carvalho Chehabbf975552011-07-20 21:43:30 -0300332
Mauro Carvalho Chehab0ff48432011-07-20 20:21:42 -0300333/*****************/
334/* From drivers/media/common/tuners/mt2063_cfg.h */
335
Mauro Carvalho Chehabf8676952011-07-20 22:00:30 -0300336unsigned int mt2063_setTune(struct dvb_frontend *fe, u32 f_in,
Mauro Carvalho Chehab51f0f7b2011-07-21 02:24:18 -0300337 u32 bw_in,
338 enum MTTune_atv_standard tv_type)
Mauro Carvalho Chehab0ff48432011-07-20 20:21:42 -0300339{
Mauro Carvalho Chehab0ff48432011-07-20 20:21:42 -0300340 struct dvb_frontend_ops *frontend_ops = NULL;
341 struct dvb_tuner_ops *tuner_ops = NULL;
342 struct tuner_state t_state;
Mauro Carvalho Chehab51f0f7b2011-07-21 02:24:18 -0300343 struct mt2063_state *state = fe->tuner_priv;
Mauro Carvalho Chehab0ff48432011-07-20 20:21:42 -0300344 int err = 0;
345
346 t_state.frequency = f_in;
347 t_state.bandwidth = bw_in;
Mauro Carvalho Chehab51f0f7b2011-07-21 02:24:18 -0300348 state->tv_type = tv_type;
Mauro Carvalho Chehab0ff48432011-07-20 20:21:42 -0300349 if (&fe->ops)
350 frontend_ops = &fe->ops;
351 if (&frontend_ops->tuner_ops)
352 tuner_ops = &frontend_ops->tuner_ops;
353 if (tuner_ops->set_state) {
354 if ((err =
355 tuner_ops->set_state(fe, DVBFE_TUNER_FREQUENCY,
356 &t_state)) < 0) {
357 printk("%s: Invalid parameter\n", __func__);
358 return err;
359 }
360 }
361
362 return err;
363}
364
Mauro Carvalho Chehabf8676952011-07-20 22:00:30 -0300365unsigned int mt2063_lockStatus(struct dvb_frontend *fe)
Mauro Carvalho Chehab0ff48432011-07-20 20:21:42 -0300366{
367 struct dvb_frontend_ops *frontend_ops = &fe->ops;
368 struct dvb_tuner_ops *tuner_ops = &frontend_ops->tuner_ops;
369 struct tuner_state t_state;
370 int err = 0;
371
372 if (&fe->ops)
373 frontend_ops = &fe->ops;
374 if (&frontend_ops->tuner_ops)
375 tuner_ops = &frontend_ops->tuner_ops;
376 if (tuner_ops->get_state) {
377 if ((err =
378 tuner_ops->get_state(fe, DVBFE_TUNER_REFCLOCK,
379 &t_state)) < 0) {
380 printk("%s: Invalid parameter\n", __func__);
381 return err;
382 }
383 }
384 return err;
385}
386
Mauro Carvalho Chehab0ff48432011-07-20 20:21:42 -0300387
Mauro Carvalho Chehabf8676952011-07-20 22:00:30 -0300388unsigned int tuner_MT2063_SoftwareShutdown(struct dvb_frontend *fe)
Mauro Carvalho Chehab0ff48432011-07-20 20:21:42 -0300389{
Mauro Carvalho Chehab8c64f9322011-07-21 03:29:06 -0300390 struct mt2063_state *state = fe->tuner_priv;
Mauro Carvalho Chehab0ff48432011-07-20 20:21:42 -0300391 struct dvb_frontend_ops *frontend_ops = &fe->ops;
392 struct dvb_tuner_ops *tuner_ops = &frontend_ops->tuner_ops;
Mauro Carvalho Chehab0ff48432011-07-20 20:21:42 -0300393 int err = 0;
394
395 if (&fe->ops)
396 frontend_ops = &fe->ops;
397 if (&frontend_ops->tuner_ops)
398 tuner_ops = &frontend_ops->tuner_ops;
399 if (tuner_ops->set_state) {
Mauro Carvalho Chehab8c64f9322011-07-21 03:29:06 -0300400 err = MT2063_SoftwareShutdown(state, 1);
401 if (err < 0) {
Mauro Carvalho Chehab0ff48432011-07-20 20:21:42 -0300402 printk("%s: Invalid parameter\n", __func__);
403 return err;
404 }
405 }
406
407 return err;
408}
409
Mauro Carvalho Chehabf8676952011-07-20 22:00:30 -0300410unsigned int tuner_MT2063_ClearPowerMaskBits(struct dvb_frontend *fe)
Mauro Carvalho Chehab0ff48432011-07-20 20:21:42 -0300411{
Mauro Carvalho Chehab8c64f9322011-07-21 03:29:06 -0300412 struct mt2063_state *state = fe->tuner_priv;
Mauro Carvalho Chehab0ff48432011-07-20 20:21:42 -0300413 struct dvb_frontend_ops *frontend_ops = &fe->ops;
414 struct dvb_tuner_ops *tuner_ops = &frontend_ops->tuner_ops;
Mauro Carvalho Chehab0ff48432011-07-20 20:21:42 -0300415 int err = 0;
416
417 if (&fe->ops)
418 frontend_ops = &fe->ops;
419 if (&frontend_ops->tuner_ops)
420 tuner_ops = &frontend_ops->tuner_ops;
421 if (tuner_ops->set_state) {
Mauro Carvalho Chehab8c64f9322011-07-21 03:29:06 -0300422 err = MT2063_ClearPowerMaskBits(state, MT2063_ALL_SD);
423 if (err < 0) {
Mauro Carvalho Chehab0ff48432011-07-20 20:21:42 -0300424 printk("%s: Invalid parameter\n", __func__);
425 return err;
426 }
427 }
428
429 return err;
430}
431
Mauro Carvalho Chehabe1de3d12011-07-21 02:46:49 -0300432/*
433 * mt2063_write - Write data into the I2C bus
434 */
435static u32 mt2063_write(struct mt2063_state *state,
436 u8 reg, u8 *data, u32 len)
Mauro Carvalho Chehab223c7b02011-07-20 19:48:59 -0300437{
Mauro Carvalho Chehabe1de3d12011-07-21 02:46:49 -0300438 struct dvb_frontend *fe = state->frontend;
Mauro Carvalho Chehab223c7b02011-07-20 19:48:59 -0300439 int ret;
Mauro Carvalho Chehabe1de3d12011-07-21 02:46:49 -0300440 u8 buf[60];
Mauro Carvalho Chehab223c7b02011-07-20 19:48:59 -0300441 struct i2c_msg msg = {
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -0300442 .addr = state->config->tuner_address,
443 .flags = 0,
444 .buf = buf,
445 .len = len + 1
Mauro Carvalho Chehab223c7b02011-07-20 19:48:59 -0300446 };
447
Mauro Carvalho Chehabe1de3d12011-07-21 02:46:49 -0300448 msg.buf[0] = reg;
Mauro Carvalho Chehab223c7b02011-07-20 19:48:59 -0300449 memcpy(msg.buf + 1, data, len);
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -0300450
Mauro Carvalho Chehabe1de3d12011-07-21 02:46:49 -0300451 fe->ops.i2c_gate_ctrl(fe, 1);
Mauro Carvalho Chehab223c7b02011-07-20 19:48:59 -0300452 ret = i2c_transfer(state->i2c, &msg, 1);
Mauro Carvalho Chehabe1de3d12011-07-21 02:46:49 -0300453 fe->ops.i2c_gate_ctrl(fe, 0);
Mauro Carvalho Chehab223c7b02011-07-20 19:48:59 -0300454
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -0300455 if (ret < 0)
456 printk("mt2063_writeregs error ret=%d\n", ret);
Mauro Carvalho Chehab223c7b02011-07-20 19:48:59 -0300457
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -0300458 return ret;
459}
460
Mauro Carvalho Chehabe1de3d12011-07-21 02:46:49 -0300461/*
462 * mt2063_read - Read data from the I2C bus
463 */
464static u32 mt2063_read(struct mt2063_state *state,
Mauro Carvalho Chehab51f0f7b2011-07-21 02:24:18 -0300465 u8 subAddress, u8 *pData, u32 cnt)
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -0300466{
Mauro Carvalho Chehab51f0f7b2011-07-21 02:24:18 -0300467 u32 status = 0; /* Status to be returned */
468 struct dvb_frontend *fe = state->frontend;
469 u32 i = 0;
470
Mauro Carvalho Chehabe1de3d12011-07-21 02:46:49 -0300471 fe->ops.i2c_gate_ctrl(fe, 1);
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -0300472
473 for (i = 0; i < cnt; i++) {
Mauro Carvalho Chehabe1de3d12011-07-21 02:46:49 -0300474 int ret;
475 u8 b0[] = { subAddress + i };
476 struct i2c_msg msg[] = {
477 {
478 .addr = state->config->tuner_address,
479 .flags = I2C_M_RD,
480 .buf = b0,
481 .len = 1
482 }, {
483 .addr = state->config->tuner_address,
484 .flags = I2C_M_RD,
485 .buf = pData + 1,
486 .len = 1
487 }
488 };
489
490 ret = i2c_transfer(state->i2c, msg, 2);
491 if (ret < 0)
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -0300492 break;
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -0300493 }
Mauro Carvalho Chehabe1de3d12011-07-21 02:46:49 -0300494 fe->ops.i2c_gate_ctrl(fe, 0);
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -0300495 return (status);
496}
497
Mauro Carvalho Chehabe930b3a2011-07-21 03:02:16 -0300498/*
499 * FIXME: Is this really needed?
500 */
Mauro Carvalho Chehabf8676952011-07-20 22:00:30 -0300501static int MT2063_Sleep(struct dvb_frontend *fe)
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -0300502{
503 /*
504 ** ToDo: Add code here to implement a OS blocking
505 ** for a period of "nMinDelayTime" milliseconds.
506 */
Mauro Carvalho Chehabf8676952011-07-20 22:00:30 -0300507 msleep(10);
508
509 return 0;
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -0300510}
511
Mauro Carvalho Chehabe930b3a2011-07-21 03:02:16 -0300512/*
513 * Microtune spur avoidance
514 */
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -0300515
516/* Implement ceiling, floor functions. */
517#define ceil(n, d) (((n) < 0) ? (-((-(n))/(d))) : (n)/(d) + ((n)%(d) != 0))
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -0300518#define floor(n, d) (((n) < 0) ? (-((-(n))/(d))) - ((n)%(d) != 0) : (n)/(d))
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -0300519
520struct MT2063_FIFZone_t {
Mauro Carvalho Chehabcfde8922011-07-20 21:01:48 -0300521 s32 min_;
522 s32 max_;
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -0300523};
524
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -0300525/*
526** Reset all exclusion zones.
527** Add zones to protect the PLL FracN regions near zero
528**
529** N/A I 06-17-2008 RSK Ver 1.19: Refactoring avoidance of DECT
530** frequencies into MT_ResetExclZones().
531*/
Mauro Carvalho Chehabbf975552011-07-20 21:43:30 -0300532static void MT2063_ResetExclZones(struct MT2063_AvoidSpursData_t *pAS_Info)
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -0300533{
Mauro Carvalho Chehabcfde8922011-07-20 21:01:48 -0300534 u32 center;
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -0300535
536 pAS_Info->nZones = 0; /* this clears the used list */
537 pAS_Info->usedZones = NULL; /* reset ptr */
538 pAS_Info->freeZones = NULL; /* reset ptr */
539
540 center =
541 pAS_Info->f_ref *
542 ((pAS_Info->f_if1_Center - pAS_Info->f_if1_bw / 2 +
543 pAS_Info->f_in) / pAS_Info->f_ref) - pAS_Info->f_in;
544 while (center <
545 pAS_Info->f_if1_Center + pAS_Info->f_if1_bw / 2 +
546 pAS_Info->f_LO1_FracN_Avoid) {
547 /* Exclude LO1 FracN */
548 MT2063_AddExclZone(pAS_Info,
549 center - pAS_Info->f_LO1_FracN_Avoid,
550 center - 1);
551 MT2063_AddExclZone(pAS_Info, center + 1,
552 center + pAS_Info->f_LO1_FracN_Avoid);
553 center += pAS_Info->f_ref;
554 }
555
556 center =
557 pAS_Info->f_ref *
558 ((pAS_Info->f_if1_Center - pAS_Info->f_if1_bw / 2 -
559 pAS_Info->f_out) / pAS_Info->f_ref) + pAS_Info->f_out;
560 while (center <
561 pAS_Info->f_if1_Center + pAS_Info->f_if1_bw / 2 +
562 pAS_Info->f_LO2_FracN_Avoid) {
563 /* Exclude LO2 FracN */
564 MT2063_AddExclZone(pAS_Info,
565 center - pAS_Info->f_LO2_FracN_Avoid,
566 center - 1);
567 MT2063_AddExclZone(pAS_Info, center + 1,
568 center + pAS_Info->f_LO2_FracN_Avoid);
569 center += pAS_Info->f_ref;
570 }
571
572 if (MT2063_EXCLUDE_US_DECT_FREQUENCIES(pAS_Info->avoidDECT)) {
573 /* Exclude LO1 values that conflict with DECT channels */
574 MT2063_AddExclZone(pAS_Info, 1920836000 - pAS_Info->f_in, 1922236000 - pAS_Info->f_in); /* Ctr = 1921.536 */
575 MT2063_AddExclZone(pAS_Info, 1922564000 - pAS_Info->f_in, 1923964000 - pAS_Info->f_in); /* Ctr = 1923.264 */
576 MT2063_AddExclZone(pAS_Info, 1924292000 - pAS_Info->f_in, 1925692000 - pAS_Info->f_in); /* Ctr = 1924.992 */
577 MT2063_AddExclZone(pAS_Info, 1926020000 - pAS_Info->f_in, 1927420000 - pAS_Info->f_in); /* Ctr = 1926.720 */
578 MT2063_AddExclZone(pAS_Info, 1927748000 - pAS_Info->f_in, 1929148000 - pAS_Info->f_in); /* Ctr = 1928.448 */
579 }
580
581 if (MT2063_EXCLUDE_EURO_DECT_FREQUENCIES(pAS_Info->avoidDECT)) {
582 MT2063_AddExclZone(pAS_Info, 1896644000 - pAS_Info->f_in, 1898044000 - pAS_Info->f_in); /* Ctr = 1897.344 */
583 MT2063_AddExclZone(pAS_Info, 1894916000 - pAS_Info->f_in, 1896316000 - pAS_Info->f_in); /* Ctr = 1895.616 */
584 MT2063_AddExclZone(pAS_Info, 1893188000 - pAS_Info->f_in, 1894588000 - pAS_Info->f_in); /* Ctr = 1893.888 */
585 MT2063_AddExclZone(pAS_Info, 1891460000 - pAS_Info->f_in, 1892860000 - pAS_Info->f_in); /* Ctr = 1892.16 */
586 MT2063_AddExclZone(pAS_Info, 1889732000 - pAS_Info->f_in, 1891132000 - pAS_Info->f_in); /* Ctr = 1890.432 */
587 MT2063_AddExclZone(pAS_Info, 1888004000 - pAS_Info->f_in, 1889404000 - pAS_Info->f_in); /* Ctr = 1888.704 */
588 MT2063_AddExclZone(pAS_Info, 1886276000 - pAS_Info->f_in, 1887676000 - pAS_Info->f_in); /* Ctr = 1886.976 */
589 MT2063_AddExclZone(pAS_Info, 1884548000 - pAS_Info->f_in, 1885948000 - pAS_Info->f_in); /* Ctr = 1885.248 */
590 MT2063_AddExclZone(pAS_Info, 1882820000 - pAS_Info->f_in, 1884220000 - pAS_Info->f_in); /* Ctr = 1883.52 */
591 MT2063_AddExclZone(pAS_Info, 1881092000 - pAS_Info->f_in, 1882492000 - pAS_Info->f_in); /* Ctr = 1881.792 */
592 }
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -0300593}
594
595static struct MT2063_ExclZone_t *InsertNode(struct MT2063_AvoidSpursData_t
596 *pAS_Info,
597 struct MT2063_ExclZone_t *pPrevNode)
598{
599 struct MT2063_ExclZone_t *pNode;
600 /* Check for a node in the free list */
601 if (pAS_Info->freeZones != NULL) {
602 /* Use one from the free list */
603 pNode = pAS_Info->freeZones;
604 pAS_Info->freeZones = pNode->next_;
605 } else {
606 /* Grab a node from the array */
607 pNode = &pAS_Info->MT2063_ExclZones[pAS_Info->nZones];
608 }
609
610 if (pPrevNode != NULL) {
611 pNode->next_ = pPrevNode->next_;
612 pPrevNode->next_ = pNode;
613 } else { /* insert at the beginning of the list */
614
615 pNode->next_ = pAS_Info->usedZones;
616 pAS_Info->usedZones = pNode;
617 }
618
619 pAS_Info->nZones++;
620 return pNode;
621}
622
623static struct MT2063_ExclZone_t *RemoveNode(struct MT2063_AvoidSpursData_t
624 *pAS_Info,
625 struct MT2063_ExclZone_t *pPrevNode,
626 struct MT2063_ExclZone_t
627 *pNodeToRemove)
628{
629 struct MT2063_ExclZone_t *pNext = pNodeToRemove->next_;
630
631 /* Make previous node point to the subsequent node */
632 if (pPrevNode != NULL)
633 pPrevNode->next_ = pNext;
634
635 /* Add pNodeToRemove to the beginning of the freeZones */
636 pNodeToRemove->next_ = pAS_Info->freeZones;
637 pAS_Info->freeZones = pNodeToRemove;
638
639 /* Decrement node count */
640 pAS_Info->nZones--;
641
642 return pNext;
643}
644
645/*****************************************************************************
646**
647** Name: MT_AddExclZone
648**
649** Description: Add (and merge) an exclusion zone into the list.
650** If the range (f_min, f_max) is totally outside the
651** 1st IF BW, ignore the entry.
652** If the range (f_min, f_max) is negative, ignore the entry.
653**
654** Revision History:
655**
656** SCR Date Author Description
657** -------------------------------------------------------------------------
658** 103 01-31-2005 DAD Ver 1.14: In MT_AddExclZone(), if the range
659** (f_min, f_max) < 0, ignore the entry.
660**
661*****************************************************************************/
Mauro Carvalho Chehabbf975552011-07-20 21:43:30 -0300662static void MT2063_AddExclZone(struct MT2063_AvoidSpursData_t *pAS_Info,
Mauro Carvalho Chehabcfde8922011-07-20 21:01:48 -0300663 u32 f_min, u32 f_max)
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -0300664{
665 struct MT2063_ExclZone_t *pNode = pAS_Info->usedZones;
666 struct MT2063_ExclZone_t *pPrev = NULL;
667 struct MT2063_ExclZone_t *pNext = NULL;
668
669 /* Check to see if this overlaps the 1st IF filter */
670 if ((f_max > (pAS_Info->f_if1_Center - (pAS_Info->f_if1_bw / 2)))
671 && (f_min < (pAS_Info->f_if1_Center + (pAS_Info->f_if1_bw / 2)))
672 && (f_min < f_max)) {
673 /*
674 ** 1 2 3 4 5 6
675 **
676 ** New entry: |---| |--| |--| |-| |---| |--|
677 ** or or or or or
678 ** Existing: |--| |--| |--| |---| |-| |--|
679 */
680
681 /* Check for our place in the list */
682 while ((pNode != NULL) && (pNode->max_ < f_min)) {
683 pPrev = pNode;
684 pNode = pNode->next_;
685 }
686
687 if ((pNode != NULL) && (pNode->min_ < f_max)) {
688 /* Combine me with pNode */
689 if (f_min < pNode->min_)
690 pNode->min_ = f_min;
691 if (f_max > pNode->max_)
692 pNode->max_ = f_max;
693 } else {
694 pNode = InsertNode(pAS_Info, pPrev);
695 pNode->min_ = f_min;
696 pNode->max_ = f_max;
697 }
698
699 /* Look for merging possibilities */
700 pNext = pNode->next_;
701 while ((pNext != NULL) && (pNext->min_ < pNode->max_)) {
702 if (pNext->max_ > pNode->max_)
703 pNode->max_ = pNext->max_;
704 pNext = RemoveNode(pAS_Info, pNode, pNext); /* Remove pNext, return ptr to pNext->next */
705 }
706 }
707}
708
709/*****************************************************************************
710**
711** Name: MT_ChooseFirstIF
712**
713** Description: Choose the best available 1st IF
714** If f_Desired is not excluded, choose that first.
715** Otherwise, return the value closest to f_Center that is
716** not excluded
717**
718** Revision History:
719**
720** SCR Date Author Description
721** -------------------------------------------------------------------------
722** 117 03-29-2007 RSK Ver 1.15: Re-wrote to match search order from
723** tuner DLL.
724** 147 07-27-2007 RSK Ver 1.17: Corrected calculation (-) to (+)
725** Added logic to force f_Center within 1/2 f_Step.
726**
727*****************************************************************************/
Mauro Carvalho Chehabbf975552011-07-20 21:43:30 -0300728static u32 MT2063_ChooseFirstIF(struct MT2063_AvoidSpursData_t *pAS_Info)
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -0300729{
730 /*
731 ** Update "f_Desired" to be the nearest "combinational-multiple" of "f_LO1_Step".
732 ** The resulting number, F_LO1 must be a multiple of f_LO1_Step. And F_LO1 is the arithmetic sum
733 ** of f_in + f_Center. Neither f_in, nor f_Center must be a multiple of f_LO1_Step.
734 ** However, the sum must be.
735 */
Mauro Carvalho Chehabcfde8922011-07-20 21:01:48 -0300736 const u32 f_Desired =
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -0300737 pAS_Info->f_LO1_Step *
738 ((pAS_Info->f_if1_Request + pAS_Info->f_in +
739 pAS_Info->f_LO1_Step / 2) / pAS_Info->f_LO1_Step) -
740 pAS_Info->f_in;
Mauro Carvalho Chehabcfde8922011-07-20 21:01:48 -0300741 const u32 f_Step =
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -0300742 (pAS_Info->f_LO1_Step >
743 pAS_Info->f_LO2_Step) ? pAS_Info->f_LO1_Step : pAS_Info->
744 f_LO2_Step;
Mauro Carvalho Chehabcfde8922011-07-20 21:01:48 -0300745 u32 f_Center;
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -0300746
Mauro Carvalho Chehabcfde8922011-07-20 21:01:48 -0300747 s32 i;
748 s32 j = 0;
749 u32 bDesiredExcluded = 0;
750 u32 bZeroExcluded = 0;
751 s32 tmpMin, tmpMax;
752 s32 bestDiff;
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -0300753 struct MT2063_ExclZone_t *pNode = pAS_Info->usedZones;
754 struct MT2063_FIFZone_t zones[MT2063_MAX_ZONES];
755
756 if (pAS_Info->nZones == 0)
757 return f_Desired;
758
759 /* f_Center needs to be an integer multiple of f_Step away from f_Desired */
760 if (pAS_Info->f_if1_Center > f_Desired)
761 f_Center =
762 f_Desired +
763 f_Step *
764 ((pAS_Info->f_if1_Center - f_Desired +
765 f_Step / 2) / f_Step);
766 else
767 f_Center =
768 f_Desired -
769 f_Step *
770 ((f_Desired - pAS_Info->f_if1_Center +
771 f_Step / 2) / f_Step);
772
773 //assert;
Mauro Carvalho Chehabcfde8922011-07-20 21:01:48 -0300774 //if (!abs((s32) f_Center - (s32) pAS_Info->f_if1_Center) <= (s32) (f_Step/2))
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -0300775 // return 0;
776
777 /* Take MT_ExclZones, center around f_Center and change the resolution to f_Step */
778 while (pNode != NULL) {
779 /* floor function */
780 tmpMin =
Mauro Carvalho Chehabcfde8922011-07-20 21:01:48 -0300781 floor((s32) (pNode->min_ - f_Center), (s32) f_Step);
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -0300782
783 /* ceil function */
784 tmpMax =
Mauro Carvalho Chehabcfde8922011-07-20 21:01:48 -0300785 ceil((s32) (pNode->max_ - f_Center), (s32) f_Step);
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -0300786
787 if ((pNode->min_ < f_Desired) && (pNode->max_ > f_Desired))
788 bDesiredExcluded = 1;
789
790 if ((tmpMin < 0) && (tmpMax > 0))
791 bZeroExcluded = 1;
792
793 /* See if this zone overlaps the previous */
794 if ((j > 0) && (tmpMin < zones[j - 1].max_))
795 zones[j - 1].max_ = tmpMax;
796 else {
797 /* Add new zone */
798 //assert(j<MT2063_MAX_ZONES);
799 //if (j>=MT2063_MAX_ZONES)
800 //break;
801
802 zones[j].min_ = tmpMin;
803 zones[j].max_ = tmpMax;
804 j++;
805 }
806 pNode = pNode->next_;
807 }
808
809 /*
810 ** If the desired is okay, return with it
811 */
812 if (bDesiredExcluded == 0)
813 return f_Desired;
814
815 /*
816 ** If the desired is excluded and the center is okay, return with it
817 */
818 if (bZeroExcluded == 0)
819 return f_Center;
820
821 /* Find the value closest to 0 (f_Center) */
822 bestDiff = zones[0].min_;
823 for (i = 0; i < j; i++) {
824 if (abs(zones[i].min_) < abs(bestDiff))
825 bestDiff = zones[i].min_;
826 if (abs(zones[i].max_) < abs(bestDiff))
827 bestDiff = zones[i].max_;
828 }
829
830 if (bestDiff < 0)
Mauro Carvalho Chehabcfde8922011-07-20 21:01:48 -0300831 return f_Center - ((u32) (-bestDiff) * f_Step);
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -0300832
833 return f_Center + (bestDiff * f_Step);
834}
835
836/****************************************************************************
837**
838** Name: gcd
839**
840** Description: Uses Euclid's algorithm
841**
842** Parameters: u, v - unsigned values whose GCD is desired.
843**
844** Global: None
845**
846** Returns: greatest common divisor of u and v, if either value
847** is 0, the other value is returned as the result.
848**
849** Dependencies: None.
850**
851** Revision History:
852**
853** SCR Date Author Description
854** -------------------------------------------------------------------------
855** N/A 06-01-2004 JWS Original
856** N/A 08-03-2004 DAD Changed to Euclid's since it can handle
857** unsigned numbers.
858**
859****************************************************************************/
Mauro Carvalho Chehabcfde8922011-07-20 21:01:48 -0300860static u32 MT2063_gcd(u32 u, u32 v)
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -0300861{
Mauro Carvalho Chehabcfde8922011-07-20 21:01:48 -0300862 u32 r;
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -0300863
864 while (v != 0) {
865 r = u % v;
866 u = v;
867 v = r;
868 }
869
870 return u;
871}
872
873/****************************************************************************
874**
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -0300875** Name: IsSpurInBand
876**
877** Description: Checks to see if a spur will be present within the IF's
878** bandwidth. (fIFOut +/- fIFBW, -fIFOut +/- fIFBW)
879**
880** ma mb mc md
881** <--+-+-+-------------------+-------------------+-+-+-->
882** | ^ 0 ^ |
883** ^ b=-fIFOut+fIFBW/2 -b=+fIFOut-fIFBW/2 ^
884** a=-fIFOut-fIFBW/2 -a=+fIFOut+fIFBW/2
885**
886** Note that some equations are doubled to prevent round-off
887** problems when calculating fIFBW/2
888**
889** Parameters: pAS_Info - Avoid Spurs information block
890** fm - If spur, amount f_IF1 has to move negative
891** fp - If spur, amount f_IF1 has to move positive
892**
893** Global: None
894**
895** Returns: 1 if an LO spur would be present, otherwise 0.
896**
897** Dependencies: None.
898**
899** Revision History:
900**
901** SCR Date Author Description
902** -------------------------------------------------------------------------
903** N/A 11-28-2002 DAD Implemented algorithm from applied patent
904**
905****************************************************************************/
Mauro Carvalho Chehabcfde8922011-07-20 21:01:48 -0300906static u32 IsSpurInBand(struct MT2063_AvoidSpursData_t *pAS_Info,
907 u32 * fm, u32 * fp)
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -0300908{
909 /*
910 ** Calculate LO frequency settings.
911 */
Mauro Carvalho Chehabcfde8922011-07-20 21:01:48 -0300912 u32 n, n0;
913 const u32 f_LO1 = pAS_Info->f_LO1;
914 const u32 f_LO2 = pAS_Info->f_LO2;
915 const u32 d = pAS_Info->f_out + pAS_Info->f_out_bw / 2;
916 const u32 c = d - pAS_Info->f_out_bw;
917 const u32 f = pAS_Info->f_zif_bw / 2;
Mauro Carvalho Chehabd0dcc2d2011-07-21 02:30:19 -0300918 const u32 f_Scale = (f_LO1 / (UINT_MAX / 2 / pAS_Info->maxH1)) + 1;
Mauro Carvalho Chehabcfde8922011-07-20 21:01:48 -0300919 s32 f_nsLO1, f_nsLO2;
920 s32 f_Spur;
921 u32 ma, mb, mc, md, me, mf;
922 u32 lo_gcd, gd_Scale, gc_Scale, gf_Scale, hgds, hgfs, hgcs;
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -0300923 *fm = 0;
924
925 /*
926 ** For each edge (d, c & f), calculate a scale, based on the gcd
927 ** of f_LO1, f_LO2 and the edge value. Use the larger of this
928 ** gcd-based scale factor or f_Scale.
929 */
930 lo_gcd = MT2063_gcd(f_LO1, f_LO2);
Mauro Carvalho Chehabfd1126c2011-07-21 03:30:57 -0300931 gd_Scale = max((u32) MT2063_gcd(lo_gcd, d), f_Scale);
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -0300932 hgds = gd_Scale / 2;
Mauro Carvalho Chehabfd1126c2011-07-21 03:30:57 -0300933 gc_Scale = max((u32) MT2063_gcd(lo_gcd, c), f_Scale);
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -0300934 hgcs = gc_Scale / 2;
Mauro Carvalho Chehabfd1126c2011-07-21 03:30:57 -0300935 gf_Scale = max((u32) MT2063_gcd(lo_gcd, f), f_Scale);
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -0300936 hgfs = gf_Scale / 2;
937
Mauro Carvalho Chehabe930b3a2011-07-21 03:02:16 -0300938 n0 = DIV_ROUND_UP(f_LO2 - d, f_LO1 - f_LO2);
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -0300939
940 /* Check out all multiples of LO1 from n0 to m_maxLOSpurHarmonic */
941 for (n = n0; n <= pAS_Info->maxH1; ++n) {
942 md = (n * ((f_LO1 + hgds) / gd_Scale) -
943 ((d + hgds) / gd_Scale)) / ((f_LO2 + hgds) / gd_Scale);
944
945 /* If # fLO2 harmonics > m_maxLOSpurHarmonic, then no spurs present */
946 if (md >= pAS_Info->maxH1)
947 break;
948
949 ma = (n * ((f_LO1 + hgds) / gd_Scale) +
950 ((d + hgds) / gd_Scale)) / ((f_LO2 + hgds) / gd_Scale);
951
952 /* If no spurs between +/- (f_out + f_IFBW/2), then try next harmonic */
953 if (md == ma)
954 continue;
955
956 mc = (n * ((f_LO1 + hgcs) / gc_Scale) -
957 ((c + hgcs) / gc_Scale)) / ((f_LO2 + hgcs) / gc_Scale);
958 if (mc != md) {
Mauro Carvalho Chehabcfde8922011-07-20 21:01:48 -0300959 f_nsLO1 = (s32) (n * (f_LO1 / gc_Scale));
960 f_nsLO2 = (s32) (mc * (f_LO2 / gc_Scale));
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -0300961 f_Spur =
962 (gc_Scale * (f_nsLO1 - f_nsLO2)) +
963 n * (f_LO1 % gc_Scale) - mc * (f_LO2 % gc_Scale);
964
Mauro Carvalho Chehabcfde8922011-07-20 21:01:48 -0300965 *fp = ((f_Spur - (s32) c) / (mc - n)) + 1;
966 *fm = (((s32) d - f_Spur) / (mc - n)) + 1;
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -0300967 return 1;
968 }
969
970 /* Location of Zero-IF-spur to be checked */
971 me = (n * ((f_LO1 + hgfs) / gf_Scale) +
972 ((f + hgfs) / gf_Scale)) / ((f_LO2 + hgfs) / gf_Scale);
973 mf = (n * ((f_LO1 + hgfs) / gf_Scale) -
974 ((f + hgfs) / gf_Scale)) / ((f_LO2 + hgfs) / gf_Scale);
975 if (me != mf) {
976 f_nsLO1 = n * (f_LO1 / gf_Scale);
977 f_nsLO2 = me * (f_LO2 / gf_Scale);
978 f_Spur =
979 (gf_Scale * (f_nsLO1 - f_nsLO2)) +
980 n * (f_LO1 % gf_Scale) - me * (f_LO2 % gf_Scale);
981
Mauro Carvalho Chehabcfde8922011-07-20 21:01:48 -0300982 *fp = ((f_Spur + (s32) f) / (me - n)) + 1;
983 *fm = (((s32) f - f_Spur) / (me - n)) + 1;
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -0300984 return 1;
985 }
986
987 mb = (n * ((f_LO1 + hgcs) / gc_Scale) +
988 ((c + hgcs) / gc_Scale)) / ((f_LO2 + hgcs) / gc_Scale);
989 if (ma != mb) {
990 f_nsLO1 = n * (f_LO1 / gc_Scale);
991 f_nsLO2 = ma * (f_LO2 / gc_Scale);
992 f_Spur =
993 (gc_Scale * (f_nsLO1 - f_nsLO2)) +
994 n * (f_LO1 % gc_Scale) - ma * (f_LO2 % gc_Scale);
995
Mauro Carvalho Chehabcfde8922011-07-20 21:01:48 -0300996 *fp = (((s32) d + f_Spur) / (ma - n)) + 1;
997 *fm = (-(f_Spur + (s32) c) / (ma - n)) + 1;
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -0300998 return 1;
999 }
1000 }
1001
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03001002 /* No spurs found */
Mauro Carvalho Chehab223c7b02011-07-20 19:48:59 -03001003 return 0;
1004}
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03001005
1006/*****************************************************************************
1007**
1008** Name: MT_AvoidSpurs
1009**
1010** Description: Main entry point to avoid spurs.
1011** Checks for existing spurs in present LO1, LO2 freqs
1012** and if present, chooses spur-free LO1, LO2 combination
1013** that tunes the same input/output frequencies.
1014**
1015** Revision History:
1016**
1017** SCR Date Author Description
1018** -------------------------------------------------------------------------
1019** 096 04-06-2005 DAD Ver 1.11: Fix divide by 0 error if maxH==0.
1020**
1021*****************************************************************************/
Mauro Carvalho Chehabbf975552011-07-20 21:43:30 -03001022static u32 MT2063_AvoidSpurs(void *h, struct MT2063_AvoidSpursData_t * pAS_Info)
Mauro Carvalho Chehab223c7b02011-07-20 19:48:59 -03001023{
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03001024 u32 status = 0;
Mauro Carvalho Chehabcfde8922011-07-20 21:01:48 -03001025 u32 fm, fp; /* restricted range on LO's */
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03001026 pAS_Info->bSpurAvoided = 0;
1027 pAS_Info->nSpursFound = 0;
1028
1029 if (pAS_Info->maxH1 == 0)
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03001030 return 0;
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03001031
1032 /*
1033 ** Avoid LO Generated Spurs
1034 **
1035 ** Make sure that have no LO-related spurs within the IF output
1036 ** bandwidth.
1037 **
1038 ** If there is an LO spur in this band, start at the current IF1 frequency
1039 ** and work out until we find a spur-free frequency or run up against the
1040 ** 1st IF SAW band edge. Use temporary copies of fLO1 and fLO2 so that they
1041 ** will be unchanged if a spur-free setting is not found.
1042 */
1043 pAS_Info->bSpurPresent = IsSpurInBand(pAS_Info, &fm, &fp);
1044 if (pAS_Info->bSpurPresent) {
Mauro Carvalho Chehabcfde8922011-07-20 21:01:48 -03001045 u32 zfIF1 = pAS_Info->f_LO1 - pAS_Info->f_in; /* current attempt at a 1st IF */
1046 u32 zfLO1 = pAS_Info->f_LO1; /* current attempt at an LO1 freq */
1047 u32 zfLO2 = pAS_Info->f_LO2; /* current attempt at an LO2 freq */
1048 u32 delta_IF1;
1049 u32 new_IF1;
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03001050
1051 /*
1052 ** Spur was found, attempt to find a spur-free 1st IF
1053 */
1054 do {
1055 pAS_Info->nSpursFound++;
1056
1057 /* Raise f_IF1_upper, if needed */
1058 MT2063_AddExclZone(pAS_Info, zfIF1 - fm, zfIF1 + fp);
1059
1060 /* Choose next IF1 that is closest to f_IF1_CENTER */
1061 new_IF1 = MT2063_ChooseFirstIF(pAS_Info);
1062
1063 if (new_IF1 > zfIF1) {
1064 pAS_Info->f_LO1 += (new_IF1 - zfIF1);
1065 pAS_Info->f_LO2 += (new_IF1 - zfIF1);
1066 } else {
1067 pAS_Info->f_LO1 -= (zfIF1 - new_IF1);
1068 pAS_Info->f_LO2 -= (zfIF1 - new_IF1);
1069 }
1070 zfIF1 = new_IF1;
1071
1072 if (zfIF1 > pAS_Info->f_if1_Center)
1073 delta_IF1 = zfIF1 - pAS_Info->f_if1_Center;
1074 else
1075 delta_IF1 = pAS_Info->f_if1_Center - zfIF1;
1076 }
1077 /*
1078 ** Continue while the new 1st IF is still within the 1st IF bandwidth
1079 ** and there is a spur in the band (again)
1080 */
1081 while ((2 * delta_IF1 + pAS_Info->f_out_bw <=
1082 pAS_Info->f_if1_bw)
1083 && (pAS_Info->bSpurPresent =
1084 IsSpurInBand(pAS_Info, &fm, &fp)));
1085
1086 /*
1087 ** Use the LO-spur free values found. If the search went all the way to
1088 ** the 1st IF band edge and always found spurs, just leave the original
1089 ** choice. It's as "good" as any other.
1090 */
1091 if (pAS_Info->bSpurPresent == 1) {
1092 status |= MT2063_SPUR_PRESENT_ERR;
1093 pAS_Info->f_LO1 = zfLO1;
1094 pAS_Info->f_LO2 = zfLO2;
1095 } else
1096 pAS_Info->bSpurAvoided = 1;
1097 }
1098
1099 status |=
1100 ((pAS_Info->
1101 nSpursFound << MT2063_SPUR_SHIFT) & MT2063_SPUR_CNT_MASK);
1102
1103 return (status);
Mauro Carvalho Chehab223c7b02011-07-20 19:48:59 -03001104}
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03001105
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03001106/*
1107** The expected version of MT_AvoidSpursData_t
1108** If the version is different, an updated file is needed from Microtune
1109*/
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03001110
1111typedef enum {
1112 MT2063_SET_ATTEN,
1113 MT2063_INCR_ATTEN,
1114 MT2063_DECR_ATTEN
1115} MT2063_ATTEN_CNTL_MODE;
1116
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03001117/*
Mauro Carvalho Chehab66aea302011-07-21 03:57:10 -03001118 * Constants used by the tuning algorithm
1119 */
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03001120#define MT2063_REF_FREQ (16000000UL) /* Reference oscillator Frequency (in Hz) */
1121#define MT2063_IF1_BW (22000000UL) /* The IF1 filter bandwidth (in Hz) */
1122#define MT2063_TUNE_STEP_SIZE (50000UL) /* Tune in steps of 50 kHz */
1123#define MT2063_SPUR_STEP_HZ (250000UL) /* Step size (in Hz) to move IF1 when avoiding spurs */
1124#define MT2063_ZIF_BW (2000000UL) /* Zero-IF spur-free bandwidth (in Hz) */
1125#define MT2063_MAX_HARMONICS_1 (15UL) /* Highest intra-tuner LO Spur Harmonic to be avoided */
1126#define MT2063_MAX_HARMONICS_2 (5UL) /* Highest inter-tuner LO Spur Harmonic to be avoided */
1127#define MT2063_MIN_LO_SEP (1000000UL) /* Minimum inter-tuner LO frequency separation */
1128#define MT2063_LO1_FRACN_AVOID (0UL) /* LO1 FracN numerator avoid region (in Hz) */
1129#define MT2063_LO2_FRACN_AVOID (199999UL) /* LO2 FracN numerator avoid region (in Hz) */
1130#define MT2063_MIN_FIN_FREQ (44000000UL) /* Minimum input frequency (in Hz) */
1131#define MT2063_MAX_FIN_FREQ (1100000000UL) /* Maximum input frequency (in Hz) */
1132#define MT2063_MIN_FOUT_FREQ (36000000UL) /* Minimum output frequency (in Hz) */
1133#define MT2063_MAX_FOUT_FREQ (57000000UL) /* Maximum output frequency (in Hz) */
1134#define MT2063_MIN_DNC_FREQ (1293000000UL) /* Minimum LO2 frequency (in Hz) */
1135#define MT2063_MAX_DNC_FREQ (1614000000UL) /* Maximum LO2 frequency (in Hz) */
1136#define MT2063_MIN_UPC_FREQ (1396000000UL) /* Minimum LO1 frequency (in Hz) */
1137#define MT2063_MAX_UPC_FREQ (2750000000UL) /* Maximum LO1 frequency (in Hz) */
1138
1139/*
1140** Define the supported Part/Rev codes for the MT2063
1141*/
1142#define MT2063_B0 (0x9B)
1143#define MT2063_B1 (0x9C)
1144#define MT2063_B2 (0x9D)
1145#define MT2063_B3 (0x9E)
1146
1147/*
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03001148** Constants for setting receiver modes.
1149** (6 modes defined at this time, enumerated by MT2063_RCVR_MODES)
1150** (DNC1GC & DNC2GC are the values, which are used, when the specific
1151** DNC Output is selected, the other is always off)
1152**
1153** If PAL-L or L' is received, set:
1154** MT2063_SetParam(hMT2063,MT2063_TAGC,1);
1155**
1156** --------------+----------------------------------------------
1157** Mode 0 : | MT2063_CABLE_QAM
1158** Mode 1 : | MT2063_CABLE_ANALOG
1159** Mode 2 : | MT2063_OFFAIR_COFDM
1160** Mode 3 : | MT2063_OFFAIR_COFDM_SAWLESS
1161** Mode 4 : | MT2063_OFFAIR_ANALOG
1162** Mode 5 : | MT2063_OFFAIR_8VSB
1163** --------------+----+----+----+----+-----+-----+--------------
1164** Mode | 0 | 1 | 2 | 3 | 4 | 5 |
1165** --------------+----+----+----+----+-----+-----+
1166**
1167**
1168*/
Mauro Carvalho Chehabcfde8922011-07-20 21:01:48 -03001169static const u8 RFAGCEN[] = { 0, 0, 0, 0, 0, 0 };
1170static const u8 LNARIN[] = { 0, 0, 3, 3, 3, 3 };
1171static const u8 FIFFQEN[] = { 1, 1, 1, 1, 1, 1 };
1172static const u8 FIFFQ[] = { 0, 0, 0, 0, 0, 0 };
1173static const u8 DNC1GC[] = { 0, 0, 0, 0, 0, 0 };
1174static const u8 DNC2GC[] = { 0, 0, 0, 0, 0, 0 };
1175static const u8 ACLNAMAX[] = { 31, 31, 31, 31, 31, 31 };
1176static const u8 LNATGT[] = { 44, 43, 43, 43, 43, 43 };
1177static const u8 RFOVDIS[] = { 0, 0, 0, 0, 0, 0 };
1178static const u8 ACRFMAX[] = { 31, 31, 31, 31, 31, 31 };
1179static const u8 PD1TGT[] = { 36, 36, 38, 38, 36, 38 };
1180static const u8 FIFOVDIS[] = { 0, 0, 0, 0, 0, 0 };
1181static const u8 ACFIFMAX[] = { 29, 29, 29, 29, 29, 29 };
1182static const u8 PD2TGT[] = { 40, 33, 38, 42, 30, 38 };
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03001183
1184/*
1185** Local Function Prototypes - not available for external access.
1186*/
1187
1188/* Forward declaration(s): */
Mauro Carvalho Chehabcfde8922011-07-20 21:01:48 -03001189static u32 MT2063_CalcLO1Mult(u32 * Div, u32 * FracN, u32 f_LO,
1190 u32 f_LO_Step, u32 f_Ref);
1191static u32 MT2063_CalcLO2Mult(u32 * Div, u32 * FracN, u32 f_LO,
1192 u32 f_LO_Step, u32 f_Ref);
1193static u32 MT2063_fLO_FractionalTerm(u32 f_ref, u32 num,
1194 u32 denom);
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03001195
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03001196/****************************************************************************
1197**
1198** Name: MT2063_GetLocked
1199**
1200** Description: Checks to see if LO1 and LO2 are locked.
1201**
1202** Parameters: h - Open handle to the tuner (from MT2063_Open).
1203**
1204** Returns: status:
1205** MT_OK - No errors
1206** MT_UPC_UNLOCK - Upconverter PLL unlocked
1207** MT_DNC_UNLOCK - Downconverter PLL unlocked
1208** MT_COMM_ERR - Serial bus communications error
1209** MT_INV_HANDLE - Invalid tuner handle
1210**
1211** Dependencies: MT_ReadSub - Read byte(s) of data from the serial bus
1212** MT_Sleep - Delay execution for x milliseconds
1213**
1214** Revision History:
1215**
1216** SCR Date Author Description
1217** -------------------------------------------------------------------------
1218** 138 06-19-2007 DAD Ver 1.00: Initial, derived from mt2067_b.
1219**
1220****************************************************************************/
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03001221static u32 MT2063_GetLocked(struct mt2063_state *state)
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03001222{
Mauro Carvalho Chehabcfde8922011-07-20 21:01:48 -03001223 const u32 nMaxWait = 100; /* wait a maximum of 100 msec */
1224 const u32 nPollRate = 2; /* poll status bits every 2 ms */
1225 const u32 nMaxLoops = nMaxWait / nPollRate;
1226 const u8 LO1LK = 0x80;
1227 u8 LO2LK = 0x08;
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03001228 u32 status = 0; /* Status to be returned */
Mauro Carvalho Chehabcfde8922011-07-20 21:01:48 -03001229 u32 nDelays = 0;
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03001230
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03001231 /* LO2 Lock bit was in a different place for B0 version */
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03001232 if (state->tuner_id == MT2063_B0)
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03001233 LO2LK = 0x40;
1234
1235 do {
1236 status |=
Mauro Carvalho Chehabe1de3d12011-07-21 02:46:49 -03001237 mt2063_read(state,
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03001238 MT2063_REG_LO_STATUS,
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03001239 &state->reg[MT2063_REG_LO_STATUS], 1);
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03001240
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03001241 if (status < 0)
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03001242 return (status);
1243
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03001244 if ((state->reg[MT2063_REG_LO_STATUS] & (LO1LK | LO2LK)) ==
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03001245 (LO1LK | LO2LK)) {
1246 return (status);
1247 }
Mauro Carvalho Chehabbf975552011-07-20 21:43:30 -03001248 msleep(nPollRate); /* Wait between retries */
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03001249 }
1250 while (++nDelays < nMaxLoops);
1251
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03001252 if ((state->reg[MT2063_REG_LO_STATUS] & LO1LK) == 0x00)
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03001253 status |= MT2063_UPC_UNLOCK;
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03001254 if ((state->reg[MT2063_REG_LO_STATUS] & LO2LK) == 0x00)
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03001255 status |= MT2063_DNC_UNLOCK;
1256
1257 return (status);
1258}
1259
1260/****************************************************************************
1261**
1262** Name: MT2063_GetParam
1263**
1264** Description: Gets a tuning algorithm parameter.
1265**
1266** This function provides access to the internals of the
1267** tuning algorithm - mostly for testing purposes.
1268**
1269** Parameters: h - Tuner handle (returned by MT2063_Open)
1270** param - Tuning algorithm parameter
1271** (see enum MT2063_Param)
1272** pValue - ptr to returned value
1273**
1274** param Description
1275** ---------------------- --------------------------------
1276** MT2063_IC_ADDR Serial Bus address of this tuner
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03001277** MT2063_SRO_FREQ crystal frequency
1278** MT2063_STEPSIZE minimum tuning step size
1279** MT2063_INPUT_FREQ input center frequency
1280** MT2063_LO1_FREQ LO1 Frequency
1281** MT2063_LO1_STEPSIZE LO1 minimum step size
1282** MT2063_LO1_FRACN_AVOID LO1 FracN keep-out region
1283** MT2063_IF1_ACTUAL Current 1st IF in use
1284** MT2063_IF1_REQUEST Requested 1st IF
1285** MT2063_IF1_CENTER Center of 1st IF SAW filter
1286** MT2063_IF1_BW Bandwidth of 1st IF SAW filter
1287** MT2063_ZIF_BW zero-IF bandwidth
1288** MT2063_LO2_FREQ LO2 Frequency
1289** MT2063_LO2_STEPSIZE LO2 minimum step size
1290** MT2063_LO2_FRACN_AVOID LO2 FracN keep-out region
1291** MT2063_OUTPUT_FREQ output center frequency
1292** MT2063_OUTPUT_BW output bandwidth
1293** MT2063_LO_SEPARATION min inter-tuner LO separation
1294** MT2063_AS_ALG ID of avoid-spurs algorithm in use
1295** MT2063_MAX_HARM1 max # of intra-tuner harmonics
1296** MT2063_MAX_HARM2 max # of inter-tuner harmonics
1297** MT2063_EXCL_ZONES # of 1st IF exclusion zones
1298** MT2063_NUM_SPURS # of spurs found/avoided
1299** MT2063_SPUR_AVOIDED >0 spurs avoided
1300** MT2063_SPUR_PRESENT >0 spurs in output (mathematically)
1301** MT2063_RCVR_MODE Predefined modes.
1302** MT2063_ACLNA LNA attenuator gain code
1303** MT2063_ACRF RF attenuator gain code
1304** MT2063_ACFIF FIF attenuator gain code
1305** MT2063_ACLNA_MAX LNA attenuator limit
1306** MT2063_ACRF_MAX RF attenuator limit
1307** MT2063_ACFIF_MAX FIF attenuator limit
1308** MT2063_PD1 Actual value of PD1
1309** MT2063_PD2 Actual value of PD2
1310** MT2063_DNC_OUTPUT_ENABLE DNC output selection
1311** MT2063_VGAGC VGA gain code
1312** MT2063_VGAOI VGA output current
1313** MT2063_TAGC TAGC setting
1314** MT2063_AMPGC AMP gain code
1315** MT2063_AVOID_DECT Avoid DECT Frequencies
1316** MT2063_CTFILT_SW Cleartune filter selection
1317**
1318** Usage: status |= MT2063_GetParam(hMT2063,
1319** MT2063_IF1_ACTUAL,
1320** &f_IF1_Actual);
1321**
1322** Returns: status:
1323** MT_OK - No errors
1324** MT_INV_HANDLE - Invalid tuner handle
1325** MT_ARG_NULL - Null pointer argument passed
1326** MT_ARG_RANGE - Invalid parameter requested
1327**
1328** Dependencies: USERS MUST CALL MT2063_Open() FIRST!
1329**
1330** See Also: MT2063_SetParam, MT2063_Open
1331**
1332** Revision History:
1333**
1334** SCR Date Author Description
1335** -------------------------------------------------------------------------
1336** 138 06-19-2007 DAD Ver 1.00: Initial, derived from mt2067_b.
1337** 154 09-13-2007 RSK Ver 1.05: Get/SetParam changes for LOx_FREQ
1338** 10-31-2007 PINZ Ver 1.08: Get/SetParam add VGAGC, VGAOI, AMPGC, TAGC
1339** 173 M 01-23-2008 RSK Ver 1.12: Read LO1C and LO2C registers from HW
1340** in GetParam.
1341** 04-18-2008 PINZ Ver 1.15: Add SetParam LNARIN & PDxTGT
1342** Split SetParam up to ACLNA / ACLNA_MAX
1343** removed ACLNA_INRC/DECR (+RF & FIF)
1344** removed GCUAUTO / BYPATNDN/UP
1345** 175 I 16-06-2008 PINZ Ver 1.16: Add control to avoid US DECT freqs.
1346** 175 I 06-19-2008 RSK Ver 1.17: Refactor DECT control to SpurAvoid.
1347** 06-24-2008 PINZ Ver 1.18: Add Get/SetParam CTFILT_SW
1348**
1349****************************************************************************/
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03001350static u32 MT2063_GetParam(struct mt2063_state *state, enum MT2063_Param param, u32 *pValue)
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03001351{
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03001352 u32 status = 0; /* Status to be returned */
Mauro Carvalho Chehabcfde8922011-07-20 21:01:48 -03001353 u32 Div;
1354 u32 Num;
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03001355
1356 if (pValue == NULL)
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03001357 return -EINVAL;
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03001358
Mauro Carvalho Chehab51f0f7b2011-07-21 02:24:18 -03001359 switch (param) {
Mauro Carvalho Chehab51f0f7b2011-07-21 02:24:18 -03001360 /* input center frequency */
1361 case MT2063_INPUT_FREQ:
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03001362 *pValue = state->AS_Data.f_in;
Mauro Carvalho Chehab51f0f7b2011-07-21 02:24:18 -03001363 break;
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03001364
Mauro Carvalho Chehab51f0f7b2011-07-21 02:24:18 -03001365 /* LO1 Frequency */
1366 case MT2063_LO1_FREQ:
1367 {
1368 /* read the actual tuner register values for LO1C_1 and LO1C_2 */
1369 status |=
Mauro Carvalho Chehabe1de3d12011-07-21 02:46:49 -03001370 mt2063_read(state,
Mauro Carvalho Chehab51f0f7b2011-07-21 02:24:18 -03001371 MT2063_REG_LO1C_1,
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03001372 &state->
Mauro Carvalho Chehab51f0f7b2011-07-21 02:24:18 -03001373 reg[MT2063_REG_LO1C_1], 2);
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03001374 Div = state->reg[MT2063_REG_LO1C_1];
1375 Num = state->reg[MT2063_REG_LO1C_2] & 0x3F;
1376 state->AS_Data.f_LO1 =
1377 (state->AS_Data.f_ref * Div) +
1378 MT2063_fLO_FractionalTerm(state->AS_Data.
Mauro Carvalho Chehab51f0f7b2011-07-21 02:24:18 -03001379 f_ref, Num, 64);
1380 }
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03001381 *pValue = state->AS_Data.f_LO1;
Mauro Carvalho Chehab51f0f7b2011-07-21 02:24:18 -03001382 break;
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03001383
Mauro Carvalho Chehab51f0f7b2011-07-21 02:24:18 -03001384 /* Bandwidth of 1st IF SAW filter */
1385 case MT2063_IF1_BW:
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03001386 *pValue = state->AS_Data.f_if1_bw;
Mauro Carvalho Chehab51f0f7b2011-07-21 02:24:18 -03001387 break;
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03001388
Mauro Carvalho Chehab51f0f7b2011-07-21 02:24:18 -03001389 /* zero-IF bandwidth */
1390 case MT2063_ZIF_BW:
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03001391 *pValue = state->AS_Data.f_zif_bw;
Mauro Carvalho Chehab51f0f7b2011-07-21 02:24:18 -03001392 break;
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03001393
Mauro Carvalho Chehab51f0f7b2011-07-21 02:24:18 -03001394 /* LO2 Frequency */
1395 case MT2063_LO2_FREQ:
1396 {
1397 /* Read the actual tuner register values for LO2C_1, LO2C_2 and LO2C_3 */
1398 status |=
Mauro Carvalho Chehabe1de3d12011-07-21 02:46:49 -03001399 mt2063_read(state,
Mauro Carvalho Chehab51f0f7b2011-07-21 02:24:18 -03001400 MT2063_REG_LO2C_1,
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03001401 &state->
Mauro Carvalho Chehab51f0f7b2011-07-21 02:24:18 -03001402 reg[MT2063_REG_LO2C_1], 3);
1403 Div =
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03001404 (state->reg[MT2063_REG_LO2C_1] & 0xFE) >> 1;
Mauro Carvalho Chehab51f0f7b2011-07-21 02:24:18 -03001405 Num =
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03001406 ((state->
Mauro Carvalho Chehab51f0f7b2011-07-21 02:24:18 -03001407 reg[MT2063_REG_LO2C_1] & 0x01) << 12) |
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03001408 (state->
1409 reg[MT2063_REG_LO2C_2] << 4) | (state->
Mauro Carvalho Chehab51f0f7b2011-07-21 02:24:18 -03001410 reg
1411 [MT2063_REG_LO2C_3]
1412 & 0x00F);
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03001413 state->AS_Data.f_LO2 =
1414 (state->AS_Data.f_ref * Div) +
1415 MT2063_fLO_FractionalTerm(state->AS_Data.
Mauro Carvalho Chehab51f0f7b2011-07-21 02:24:18 -03001416 f_ref, Num, 8191);
1417 }
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03001418 *pValue = state->AS_Data.f_LO2;
Mauro Carvalho Chehab51f0f7b2011-07-21 02:24:18 -03001419 break;
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03001420
Mauro Carvalho Chehab51f0f7b2011-07-21 02:24:18 -03001421 /* LO2 FracN keep-out region */
1422 case MT2063_LO2_FRACN_AVOID:
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03001423 *pValue = state->AS_Data.f_LO2_FracN_Avoid;
Mauro Carvalho Chehab51f0f7b2011-07-21 02:24:18 -03001424 break;
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03001425
Mauro Carvalho Chehab51f0f7b2011-07-21 02:24:18 -03001426 /* output center frequency */
1427 case MT2063_OUTPUT_FREQ:
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03001428 *pValue = state->AS_Data.f_out;
Mauro Carvalho Chehab51f0f7b2011-07-21 02:24:18 -03001429 break;
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03001430
Mauro Carvalho Chehab51f0f7b2011-07-21 02:24:18 -03001431 /* output bandwidth */
1432 case MT2063_OUTPUT_BW:
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03001433 *pValue = state->AS_Data.f_out_bw - 750000;
Mauro Carvalho Chehab51f0f7b2011-07-21 02:24:18 -03001434 break;
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03001435
Mauro Carvalho Chehab51f0f7b2011-07-21 02:24:18 -03001436 /* Predefined receiver setup combination */
1437 case MT2063_RCVR_MODE:
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03001438 *pValue = state->rcvr_mode;
Mauro Carvalho Chehab51f0f7b2011-07-21 02:24:18 -03001439 break;
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03001440
Mauro Carvalho Chehab51f0f7b2011-07-21 02:24:18 -03001441 case MT2063_PD1:
1442 case MT2063_PD2: {
1443 u8 mask = (param == MT2063_PD1 ? 0x01 : 0x03); /* PD1 vs PD2 */
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03001444 u8 orig = (state->reg[MT2063_REG_BYP_CTRL]);
Mauro Carvalho Chehab51f0f7b2011-07-21 02:24:18 -03001445 u8 reg = (orig & 0xF1) | mask; /* Only set 3 bits (not 5) */
1446 int i;
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03001447
Mauro Carvalho Chehab51f0f7b2011-07-21 02:24:18 -03001448 *pValue = 0;
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03001449
Mauro Carvalho Chehab51f0f7b2011-07-21 02:24:18 -03001450 /* Initiate ADC output to reg 0x0A */
1451 if (reg != orig)
1452 status |=
Mauro Carvalho Chehabe1de3d12011-07-21 02:46:49 -03001453 mt2063_write(state,
Mauro Carvalho Chehab51f0f7b2011-07-21 02:24:18 -03001454 MT2063_REG_BYP_CTRL,
1455 &reg, 1);
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03001456
Mauro Carvalho Chehab51f0f7b2011-07-21 02:24:18 -03001457 if (status < 0)
1458 return (status);
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03001459
Mauro Carvalho Chehab51f0f7b2011-07-21 02:24:18 -03001460 for (i = 0; i < 8; i++) {
1461 status |=
Mauro Carvalho Chehabe1de3d12011-07-21 02:46:49 -03001462 mt2063_read(state,
Mauro Carvalho Chehab51f0f7b2011-07-21 02:24:18 -03001463 MT2063_REG_ADC_OUT,
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03001464 &state->
Mauro Carvalho Chehab51f0f7b2011-07-21 02:24:18 -03001465 reg
1466 [MT2063_REG_ADC_OUT],
1467 1);
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03001468
Mauro Carvalho Chehab51f0f7b2011-07-21 02:24:18 -03001469 if (status >= 0)
1470 *pValue +=
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03001471 state->
Mauro Carvalho Chehab51f0f7b2011-07-21 02:24:18 -03001472 reg[MT2063_REG_ADC_OUT];
1473 else {
1474 if (i)
1475 *pValue /= i;
1476 return (status);
1477 }
1478 }
1479 *pValue /= 8; /* divide by number of reads */
1480 *pValue >>= 2; /* only want 6 MSB's out of 8 */
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03001481
Mauro Carvalho Chehab51f0f7b2011-07-21 02:24:18 -03001482 /* Restore value of Register BYP_CTRL */
1483 if (reg != orig)
1484 status |=
Mauro Carvalho Chehabe1de3d12011-07-21 02:46:49 -03001485 mt2063_write(state,
Mauro Carvalho Chehab51f0f7b2011-07-21 02:24:18 -03001486 MT2063_REG_BYP_CTRL,
1487 &orig, 1);
1488 }
1489 break;
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03001490
Mauro Carvalho Chehab51f0f7b2011-07-21 02:24:18 -03001491 /* Get LNA attenuator code */
1492 case MT2063_ACLNA:
1493 {
1494 u8 val;
1495 status |=
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03001496 MT2063_GetReg(state, MT2063_REG_XO_STATUS,
Mauro Carvalho Chehab51f0f7b2011-07-21 02:24:18 -03001497 &val);
1498 *pValue = val & 0x1f;
1499 }
1500 break;
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03001501
Mauro Carvalho Chehab51f0f7b2011-07-21 02:24:18 -03001502 /* Get RF attenuator code */
1503 case MT2063_ACRF:
1504 {
1505 u8 val;
1506 status |=
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03001507 MT2063_GetReg(state, MT2063_REG_RF_STATUS,
Mauro Carvalho Chehab51f0f7b2011-07-21 02:24:18 -03001508 &val);
1509 *pValue = val & 0x1f;
1510 }
1511 break;
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03001512
Mauro Carvalho Chehab51f0f7b2011-07-21 02:24:18 -03001513 /* Get FIF attenuator code */
1514 case MT2063_ACFIF:
1515 {
1516 u8 val;
1517 status |=
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03001518 MT2063_GetReg(state, MT2063_REG_FIF_STATUS,
Mauro Carvalho Chehab51f0f7b2011-07-21 02:24:18 -03001519 &val);
1520 *pValue = val & 0x1f;
1521 }
1522 break;
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03001523
Mauro Carvalho Chehab51f0f7b2011-07-21 02:24:18 -03001524 /* Get LNA attenuator limit */
1525 case MT2063_ACLNA_MAX:
1526 {
1527 u8 val;
1528 status |=
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03001529 MT2063_GetReg(state, MT2063_REG_LNA_OV,
Mauro Carvalho Chehab51f0f7b2011-07-21 02:24:18 -03001530 &val);
1531 *pValue = val & 0x1f;
1532 }
1533 break;
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03001534
Mauro Carvalho Chehab51f0f7b2011-07-21 02:24:18 -03001535 /* Get RF attenuator limit */
1536 case MT2063_ACRF_MAX:
1537 {
1538 u8 val;
1539 status |=
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03001540 MT2063_GetReg(state, MT2063_REG_RF_OV,
Mauro Carvalho Chehab51f0f7b2011-07-21 02:24:18 -03001541 &val);
1542 *pValue = val & 0x1f;
1543 }
1544 break;
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03001545
Mauro Carvalho Chehab51f0f7b2011-07-21 02:24:18 -03001546 /* Get FIF attenuator limit */
1547 case MT2063_ACFIF_MAX:
1548 {
1549 u8 val;
1550 status |=
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03001551 MT2063_GetReg(state, MT2063_REG_FIF_OV,
Mauro Carvalho Chehab51f0f7b2011-07-21 02:24:18 -03001552 &val);
1553 *pValue = val & 0x1f;
1554 }
1555 break;
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03001556
Mauro Carvalho Chehab51f0f7b2011-07-21 02:24:18 -03001557 /* Get current used DNC output */
1558 case MT2063_DNC_OUTPUT_ENABLE:
1559 {
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03001560 if ((state->reg[MT2063_REG_DNC_GAIN] & 0x03) == 0x03) { /* if DNC1 is off */
1561 if ((state->reg[MT2063_REG_VGA_GAIN] & 0x03) == 0x03) /* if DNC2 is off */
Mauro Carvalho Chehab51f0f7b2011-07-21 02:24:18 -03001562 *pValue =
1563 (u32) MT2063_DNC_NONE;
1564 else
1565 *pValue =
1566 (u32) MT2063_DNC_2;
1567 } else { /* DNC1 is on */
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03001568
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03001569 if ((state->reg[MT2063_REG_VGA_GAIN] & 0x03) == 0x03) /* if DNC2 is off */
Mauro Carvalho Chehab51f0f7b2011-07-21 02:24:18 -03001570 *pValue =
1571 (u32) MT2063_DNC_1;
1572 else
1573 *pValue =
1574 (u32) MT2063_DNC_BOTH;
1575 }
1576 }
1577 break;
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03001578
Mauro Carvalho Chehab51f0f7b2011-07-21 02:24:18 -03001579 default:
1580 status |= -ERANGE;
1581 }
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03001582 return (status);
1583}
1584
1585/****************************************************************************
1586**
1587** Name: MT2063_GetReg
1588**
1589** Description: Gets an MT2063 register.
1590**
1591** Parameters: h - Tuner handle (returned by MT2063_Open)
1592** reg - MT2063 register/subaddress location
1593** *val - MT2063 register/subaddress value
1594**
1595** Returns: status:
1596** MT_OK - No errors
1597** MT_COMM_ERR - Serial bus communications error
1598** MT_INV_HANDLE - Invalid tuner handle
1599** MT_ARG_NULL - Null pointer argument passed
1600** MT_ARG_RANGE - Argument out of range
1601**
1602** Dependencies: USERS MUST CALL MT2063_Open() FIRST!
1603**
1604** Use this function if you need to read a register from
1605** the MT2063.
1606**
1607** Revision History:
1608**
1609** SCR Date Author Description
1610** -------------------------------------------------------------------------
1611** 138 06-19-2007 DAD Ver 1.00: Initial, derived from mt2067_b.
1612**
1613****************************************************************************/
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03001614static u32 MT2063_GetReg(struct mt2063_state *state, u8 reg, u8 * val)
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03001615{
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03001616 u32 status = 0; /* Status to be returned */
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03001617
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03001618 if (val == NULL)
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03001619 return -EINVAL;
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03001620
1621 if (reg >= MT2063_REG_END_REGS)
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03001622 return -ERANGE;
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03001623
Mauro Carvalho Chehabe1de3d12011-07-21 02:46:49 -03001624 status = mt2063_read(state, reg, &state->reg[reg], 1);
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03001625
1626 return (status);
1627}
1628
1629/******************************************************************************
1630**
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03001631** Name: MT2063_SetReceiverMode
1632**
1633** Description: Set the MT2063 receiver mode
1634**
1635** --------------+----------------------------------------------
1636** Mode 0 : | MT2063_CABLE_QAM
1637** Mode 1 : | MT2063_CABLE_ANALOG
1638** Mode 2 : | MT2063_OFFAIR_COFDM
1639** Mode 3 : | MT2063_OFFAIR_COFDM_SAWLESS
1640** Mode 4 : | MT2063_OFFAIR_ANALOG
1641** Mode 5 : | MT2063_OFFAIR_8VSB
1642** --------------+----+----+----+----+-----+--------------------
1643** (DNC1GC & DNC2GC are the values, which are used, when the specific
1644** DNC Output is selected, the other is always off)
1645**
1646** |<---------- Mode -------------->|
1647** Reg Field | 0 | 1 | 2 | 3 | 4 | 5 |
1648** ------------+-----+-----+-----+-----+-----+-----+
1649** RFAGCen | OFF | OFF | OFF | OFF | OFF | OFF
1650** LNARin | 0 | 0 | 3 | 3 | 3 | 3
1651** FIFFQen | 1 | 1 | 1 | 1 | 1 | 1
1652** FIFFq | 0 | 0 | 0 | 0 | 0 | 0
1653** DNC1gc | 0 | 0 | 0 | 0 | 0 | 0
1654** DNC2gc | 0 | 0 | 0 | 0 | 0 | 0
1655** GCU Auto | 1 | 1 | 1 | 1 | 1 | 1
1656** LNA max Atn | 31 | 31 | 31 | 31 | 31 | 31
1657** LNA Target | 44 | 43 | 43 | 43 | 43 | 43
1658** ign RF Ovl | 0 | 0 | 0 | 0 | 0 | 0
1659** RF max Atn | 31 | 31 | 31 | 31 | 31 | 31
1660** PD1 Target | 36 | 36 | 38 | 38 | 36 | 38
1661** ign FIF Ovl | 0 | 0 | 0 | 0 | 0 | 0
1662** FIF max Atn | 5 | 5 | 5 | 5 | 5 | 5
1663** PD2 Target | 40 | 33 | 42 | 42 | 33 | 42
1664**
1665**
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03001666** Parameters: state - ptr to mt2063_state structure
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03001667** Mode - desired reciever mode
1668**
1669** Usage: status = MT2063_SetReceiverMode(hMT2063, Mode);
1670**
1671** Returns: status:
1672** MT_OK - No errors
1673** MT_COMM_ERR - Serial bus communications error
1674**
1675** Dependencies: MT2063_SetReg - Write a byte of data to a HW register.
1676** Assumes that the tuner cache is valid.
1677**
1678** Revision History:
1679**
1680** SCR Date Author Description
1681** -------------------------------------------------------------------------
1682** 138 06-19-2007 DAD Ver 1.00: Initial, derived from mt2067_b.
1683** N/A 01-10-2007 PINZ Added additional GCU Settings, FIFF Calib will be triggered
1684** 155 10-01-2007 DAD Ver 1.06: Add receiver mode for SECAM positive
1685** modulation
1686** (MT2063_ANALOG_TV_POS_NO_RFAGC_MODE)
1687** N/A 10-22-2007 PINZ Ver 1.07: Changed some Registers at init to have
1688** the same settings as with MT Launcher
1689** N/A 10-30-2007 PINZ Add SetParam VGAGC & VGAOI
1690** Add SetParam DNC_OUTPUT_ENABLE
1691** Removed VGAGC from receiver mode,
1692** default now 1
1693** N/A 10-31-2007 PINZ Ver 1.08: Add SetParam TAGC, removed from rcvr-mode
1694** Add SetParam AMPGC, removed from rcvr-mode
1695** Corrected names of GCU values
1696** reorganized receiver modes, removed,
1697** (MT2063_ANALOG_TV_POS_NO_RFAGC_MODE)
1698** Actualized Receiver-Mode values
1699** N/A 11-12-2007 PINZ Ver 1.09: Actualized Receiver-Mode values
1700** N/A 11-27-2007 PINZ Improved buffered writing
1701** 01-03-2008 PINZ Ver 1.10: Added a trigger of BYPATNUP for
1702** correct wakeup of the LNA after shutdown
1703** Set AFCsd = 1 as default
1704** Changed CAP1sel default
1705** 01-14-2008 PINZ Ver 1.11: Updated gain settings
1706** 04-18-2008 PINZ Ver 1.15: Add SetParam LNARIN & PDxTGT
1707** Split SetParam up to ACLNA / ACLNA_MAX
1708** removed ACLNA_INRC/DECR (+RF & FIF)
1709** removed GCUAUTO / BYPATNDN/UP
1710**
1711******************************************************************************/
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03001712static u32 MT2063_SetReceiverMode(struct mt2063_state *state,
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03001713 enum MT2063_RCVR_MODES Mode)
1714{
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03001715 u32 status = 0; /* Status to be returned */
Mauro Carvalho Chehabcfde8922011-07-20 21:01:48 -03001716 u8 val;
1717 u32 longval;
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03001718
1719 if (Mode >= MT2063_NUM_RCVR_MODES)
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03001720 status = -ERANGE;
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03001721
1722 /* RFAGCen */
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03001723 if (status >= 0) {
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03001724 val =
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03001725 (state->
Mauro Carvalho Chehabcfde8922011-07-20 21:01:48 -03001726 reg[MT2063_REG_PD1_TGT] & (u8) ~ 0x40) | (RFAGCEN[Mode]
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03001727 ? 0x40 :
1728 0x00);
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03001729 if (state->reg[MT2063_REG_PD1_TGT] != val) {
1730 status |= MT2063_SetReg(state, MT2063_REG_PD1_TGT, val);
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03001731 }
1732 }
1733
1734 /* LNARin */
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03001735 if (status >= 0) {
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03001736 status |= MT2063_SetParam(state, MT2063_LNA_RIN, LNARIN[Mode]);
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03001737 }
1738
1739 /* FIFFQEN and FIFFQ */
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03001740 if (status >= 0) {
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03001741 val =
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03001742 (state->
Mauro Carvalho Chehabcfde8922011-07-20 21:01:48 -03001743 reg[MT2063_REG_FIFF_CTRL2] & (u8) ~ 0xF0) |
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03001744 (FIFFQEN[Mode] << 7) | (FIFFQ[Mode] << 4);
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03001745 if (state->reg[MT2063_REG_FIFF_CTRL2] != val) {
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03001746 status |=
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03001747 MT2063_SetReg(state, MT2063_REG_FIFF_CTRL2, val);
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03001748 /* trigger FIFF calibration, needed after changing FIFFQ */
1749 val =
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03001750 (state->reg[MT2063_REG_FIFF_CTRL] | (u8) 0x01);
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03001751 status |=
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03001752 MT2063_SetReg(state, MT2063_REG_FIFF_CTRL, val);
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03001753 val =
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03001754 (state->
Mauro Carvalho Chehabcfde8922011-07-20 21:01:48 -03001755 reg[MT2063_REG_FIFF_CTRL] & (u8) ~ 0x01);
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03001756 status |=
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03001757 MT2063_SetReg(state, MT2063_REG_FIFF_CTRL, val);
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03001758 }
1759 }
1760
1761 /* DNC1GC & DNC2GC */
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03001762 status |= MT2063_GetParam(state, MT2063_DNC_OUTPUT_ENABLE, &longval);
1763 status |= MT2063_SetParam(state, MT2063_DNC_OUTPUT_ENABLE, longval);
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03001764
1765 /* acLNAmax */
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03001766 if (status >= 0) {
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03001767 status |=
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03001768 MT2063_SetParam(state, MT2063_ACLNA_MAX, ACLNAMAX[Mode]);
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03001769 }
1770
1771 /* LNATGT */
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03001772 if (status >= 0) {
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03001773 status |= MT2063_SetParam(state, MT2063_LNA_TGT, LNATGT[Mode]);
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03001774 }
1775
1776 /* ACRF */
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03001777 if (status >= 0) {
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03001778 status |=
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03001779 MT2063_SetParam(state, MT2063_ACRF_MAX, ACRFMAX[Mode]);
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03001780 }
1781
1782 /* PD1TGT */
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03001783 if (status >= 0) {
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03001784 status |= MT2063_SetParam(state, MT2063_PD1_TGT, PD1TGT[Mode]);
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03001785 }
1786
1787 /* FIFATN */
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03001788 if (status >= 0) {
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03001789 status |=
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03001790 MT2063_SetParam(state, MT2063_ACFIF_MAX, ACFIFMAX[Mode]);
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03001791 }
1792
1793 /* PD2TGT */
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03001794 if (status >= 0) {
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03001795 status |= MT2063_SetParam(state, MT2063_PD2_TGT, PD2TGT[Mode]);
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03001796 }
1797
1798 /* Ignore ATN Overload */
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03001799 if (status >= 0) {
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03001800 val =
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03001801 (state->
Mauro Carvalho Chehabcfde8922011-07-20 21:01:48 -03001802 reg[MT2063_REG_LNA_TGT] & (u8) ~ 0x80) | (RFOVDIS[Mode]
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03001803 ? 0x80 :
1804 0x00);
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03001805 if (state->reg[MT2063_REG_LNA_TGT] != val) {
1806 status |= MT2063_SetReg(state, MT2063_REG_LNA_TGT, val);
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03001807 }
1808 }
1809
1810 /* Ignore FIF Overload */
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03001811 if (status >= 0) {
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03001812 val =
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03001813 (state->
Mauro Carvalho Chehabcfde8922011-07-20 21:01:48 -03001814 reg[MT2063_REG_PD1_TGT] & (u8) ~ 0x80) |
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03001815 (FIFOVDIS[Mode] ? 0x80 : 0x00);
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03001816 if (state->reg[MT2063_REG_PD1_TGT] != val) {
1817 status |= MT2063_SetReg(state, MT2063_REG_PD1_TGT, val);
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03001818 }
1819 }
1820
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03001821 if (status >= 0)
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03001822 state->rcvr_mode = Mode;
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03001823
1824 return (status);
1825}
1826
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03001827/****************************************************************************
1828**
1829** Name: MT2063_SetParam
1830**
1831** Description: Sets a tuning algorithm parameter.
1832**
1833** This function provides access to the internals of the
1834** tuning algorithm. You can override many of the tuning
1835** algorithm defaults using this function.
1836**
1837** Parameters: h - Tuner handle (returned by MT2063_Open)
1838** param - Tuning algorithm parameter
1839** (see enum MT2063_Param)
1840** nValue - value to be set
1841**
1842** param Description
1843** ---------------------- --------------------------------
1844** MT2063_SRO_FREQ crystal frequency
1845** MT2063_STEPSIZE minimum tuning step size
1846** MT2063_LO1_FREQ LO1 frequency
1847** MT2063_LO1_STEPSIZE LO1 minimum step size
1848** MT2063_LO1_FRACN_AVOID LO1 FracN keep-out region
1849** MT2063_IF1_REQUEST Requested 1st IF
1850** MT2063_ZIF_BW zero-IF bandwidth
1851** MT2063_LO2_FREQ LO2 frequency
1852** MT2063_LO2_STEPSIZE LO2 minimum step size
1853** MT2063_LO2_FRACN_AVOID LO2 FracN keep-out region
1854** MT2063_OUTPUT_FREQ output center frequency
1855** MT2063_OUTPUT_BW output bandwidth
1856** MT2063_LO_SEPARATION min inter-tuner LO separation
1857** MT2063_MAX_HARM1 max # of intra-tuner harmonics
1858** MT2063_MAX_HARM2 max # of inter-tuner harmonics
1859** MT2063_RCVR_MODE Predefined modes
1860** MT2063_LNA_RIN Set LNA Rin (*)
1861** MT2063_LNA_TGT Set target power level at LNA (*)
1862** MT2063_PD1_TGT Set target power level at PD1 (*)
1863** MT2063_PD2_TGT Set target power level at PD2 (*)
1864** MT2063_ACLNA_MAX LNA attenuator limit (*)
1865** MT2063_ACRF_MAX RF attenuator limit (*)
1866** MT2063_ACFIF_MAX FIF attenuator limit (*)
1867** MT2063_DNC_OUTPUT_ENABLE DNC output selection
1868** MT2063_VGAGC VGA gain code
1869** MT2063_VGAOI VGA output current
1870** MT2063_TAGC TAGC setting
1871** MT2063_AMPGC AMP gain code
1872** MT2063_AVOID_DECT Avoid DECT Frequencies
1873** MT2063_CTFILT_SW Cleartune filter selection
1874**
1875** (*) This parameter is set by MT2063_RCVR_MODE, do not call
1876** additionally.
1877**
1878** Usage: status |= MT2063_SetParam(hMT2063,
1879** MT2063_STEPSIZE,
1880** 50000);
1881**
1882** Returns: status:
1883** MT_OK - No errors
1884** MT_INV_HANDLE - Invalid tuner handle
1885** MT_ARG_NULL - Null pointer argument passed
1886** MT_ARG_RANGE - Invalid parameter requested
1887** or set value out of range
1888** or non-writable parameter
1889**
1890** Dependencies: USERS MUST CALL MT2063_Open() FIRST!
1891**
1892** See Also: MT2063_GetParam, MT2063_Open
1893**
1894** Revision History:
1895**
1896** SCR Date Author Description
1897** -------------------------------------------------------------------------
1898** 138 06-19-2007 DAD Ver 1.00: Initial, derived from mt2067_b.
1899** 154 09-13-2007 RSK Ver 1.05: Get/SetParam changes for LOx_FREQ
1900** 10-31-2007 PINZ Ver 1.08: Get/SetParam add VGAGC, VGAOI, AMPGC, TAGC
1901** 04-18-2008 PINZ Ver 1.15: Add SetParam LNARIN & PDxTGT
1902** Split SetParam up to ACLNA / ACLNA_MAX
1903** removed ACLNA_INRC/DECR (+RF & FIF)
1904** removed GCUAUTO / BYPATNDN/UP
1905** 175 I 06-06-2008 PINZ Ver 1.16: Add control to avoid US DECT freqs.
1906** 175 I 06-19-2008 RSK Ver 1.17: Refactor DECT control to SpurAvoid.
1907** 06-24-2008 PINZ Ver 1.18: Add Get/SetParam CTFILT_SW
1908**
1909****************************************************************************/
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03001910static u32 MT2063_SetParam(struct mt2063_state *state,
Mauro Carvalho Chehab29a0a4fe2011-07-20 23:44:10 -03001911 enum MT2063_Param param,
1912 enum MT2063_DNC_Output_Enable nValue)
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03001913{
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03001914 u32 status = 0; /* Status to be returned */
Mauro Carvalho Chehabcfde8922011-07-20 21:01:48 -03001915 u8 val = 0;
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03001916
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03001917 switch (param) {
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03001918 /* LO1 frequency */
1919 case MT2063_LO1_FREQ:
1920 {
1921 /* Note: LO1 and LO2 are BOTH written at toggle of LDLOos */
1922 /* Capture the Divider and Numerator portions of other LO */
1923 u8 tempLO2CQ[3];
1924 u8 tempLO2C[3];
1925 u8 tmpOneShot;
1926 u32 Div, FracN;
1927 u8 restore = 0;
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03001928
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03001929 /* Buffer the queue for restoration later and get actual LO2 values. */
1930 status |=
Mauro Carvalho Chehabe1de3d12011-07-21 02:46:49 -03001931 mt2063_read(state,
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03001932 MT2063_REG_LO2CQ_1,
1933 &(tempLO2CQ[0]), 3);
1934 status |=
Mauro Carvalho Chehabe1de3d12011-07-21 02:46:49 -03001935 mt2063_read(state,
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03001936 MT2063_REG_LO2C_1,
1937 &(tempLO2C[0]), 3);
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03001938
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03001939 /* clear the one-shot bits */
1940 tempLO2CQ[2] = tempLO2CQ[2] & 0x0F;
1941 tempLO2C[2] = tempLO2C[2] & 0x0F;
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03001942
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03001943 /* only write the queue values if they are different from the actual. */
1944 if ((tempLO2CQ[0] != tempLO2C[0]) ||
1945 (tempLO2CQ[1] != tempLO2C[1]) ||
1946 (tempLO2CQ[2] != tempLO2C[2])) {
1947 /* put actual LO2 value into queue (with 0 in one-shot bits) */
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03001948 status |=
Mauro Carvalho Chehabe1de3d12011-07-21 02:46:49 -03001949 mt2063_write(state,
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03001950 MT2063_REG_LO2CQ_1,
1951 &(tempLO2C[0]), 3);
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03001952
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03001953 if (status == 0) {
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03001954 /* cache the bytes just written. */
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03001955 state->reg[MT2063_REG_LO2CQ_1] =
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03001956 tempLO2C[0];
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03001957 state->reg[MT2063_REG_LO2CQ_2] =
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03001958 tempLO2C[1];
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03001959 state->reg[MT2063_REG_LO2CQ_3] =
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03001960 tempLO2C[2];
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03001961 }
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03001962 restore = 1;
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03001963 }
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03001964
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03001965 /* Calculate the Divider and Numberator components of LO1 */
1966 status =
1967 MT2063_CalcLO1Mult(&Div, &FracN, nValue,
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03001968 state->AS_Data.f_ref /
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03001969 64,
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03001970 state->AS_Data.f_ref);
1971 state->reg[MT2063_REG_LO1CQ_1] =
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03001972 (u8) (Div & 0x00FF);
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03001973 state->reg[MT2063_REG_LO1CQ_2] =
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03001974 (u8) (FracN);
1975 status |=
Mauro Carvalho Chehabe1de3d12011-07-21 02:46:49 -03001976 mt2063_write(state,
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03001977 MT2063_REG_LO1CQ_1,
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03001978 &state->
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03001979 reg[MT2063_REG_LO1CQ_1], 2);
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03001980
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03001981 /* set the one-shot bit to load the pair of LO values */
1982 tmpOneShot = tempLO2CQ[2] | 0xE0;
1983 status |=
Mauro Carvalho Chehabe1de3d12011-07-21 02:46:49 -03001984 mt2063_write(state,
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03001985 MT2063_REG_LO2CQ_3,
1986 &tmpOneShot, 1);
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03001987
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03001988 /* only restore the queue values if they were different from the actual. */
1989 if (restore) {
1990 /* put actual LO2 value into queue (0 in one-shot bits) */
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03001991 status |=
Mauro Carvalho Chehabe1de3d12011-07-21 02:46:49 -03001992 mt2063_write(state,
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03001993 MT2063_REG_LO2CQ_1,
1994 &(tempLO2CQ[0]), 3);
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03001995
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03001996 /* cache the bytes just written. */
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03001997 state->reg[MT2063_REG_LO2CQ_1] =
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03001998 tempLO2CQ[0];
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03001999 state->reg[MT2063_REG_LO2CQ_2] =
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03002000 tempLO2CQ[1];
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03002001 state->reg[MT2063_REG_LO2CQ_3] =
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03002002 tempLO2CQ[2];
2003 }
2004
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03002005 MT2063_GetParam(state,
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03002006 MT2063_LO1_FREQ,
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03002007 &state->AS_Data.f_LO1);
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03002008 }
2009 break;
2010
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03002011 /* zero-IF bandwidth */
2012 case MT2063_ZIF_BW:
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03002013 state->AS_Data.f_zif_bw = nValue;
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03002014 break;
2015
2016 /* LO2 frequency */
2017 case MT2063_LO2_FREQ:
2018 {
2019 /* Note: LO1 and LO2 are BOTH written at toggle of LDLOos */
2020 /* Capture the Divider and Numerator portions of other LO */
2021 u8 tempLO1CQ[2];
2022 u8 tempLO1C[2];
2023 u32 Div2;
2024 u32 FracN2;
2025 u8 tmpOneShot;
2026 u8 restore = 0;
2027
2028 /* Buffer the queue for restoration later and get actual LO2 values. */
2029 status |=
Mauro Carvalho Chehabe1de3d12011-07-21 02:46:49 -03002030 mt2063_read(state,
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03002031 MT2063_REG_LO1CQ_1,
2032 &(tempLO1CQ[0]), 2);
2033 status |=
Mauro Carvalho Chehabe1de3d12011-07-21 02:46:49 -03002034 mt2063_read(state,
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03002035 MT2063_REG_LO1C_1,
2036 &(tempLO1C[0]), 2);
2037
2038 /* only write the queue values if they are different from the actual. */
2039 if ((tempLO1CQ[0] != tempLO1C[0])
2040 || (tempLO1CQ[1] != tempLO1C[1])) {
2041 /* put actual LO1 value into queue */
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03002042 status |=
Mauro Carvalho Chehabe1de3d12011-07-21 02:46:49 -03002043 mt2063_write(state,
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03002044 MT2063_REG_LO1CQ_1,
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03002045 &(tempLO1C[0]), 2);
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03002046
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03002047 /* cache the bytes just written. */
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03002048 state->reg[MT2063_REG_LO1CQ_1] =
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03002049 tempLO1C[0];
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03002050 state->reg[MT2063_REG_LO1CQ_2] =
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03002051 tempLO1C[1];
2052 restore = 1;
2053 }
2054
2055 /* Calculate the Divider and Numberator components of LO2 */
2056 status =
2057 MT2063_CalcLO2Mult(&Div2, &FracN2, nValue,
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03002058 state->AS_Data.f_ref /
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03002059 8191,
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03002060 state->AS_Data.f_ref);
2061 state->reg[MT2063_REG_LO2CQ_1] =
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03002062 (u8) ((Div2 << 1) |
2063 ((FracN2 >> 12) & 0x01)) & 0xFF;
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03002064 state->reg[MT2063_REG_LO2CQ_2] =
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03002065 (u8) ((FracN2 >> 4) & 0xFF);
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03002066 state->reg[MT2063_REG_LO2CQ_3] =
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03002067 (u8) ((FracN2 & 0x0F));
2068 status |=
Mauro Carvalho Chehabe1de3d12011-07-21 02:46:49 -03002069 mt2063_write(state,
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03002070 MT2063_REG_LO1CQ_1,
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03002071 &state->
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03002072 reg[MT2063_REG_LO1CQ_1], 3);
2073
2074 /* set the one-shot bit to load the LO values */
2075 tmpOneShot =
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03002076 state->reg[MT2063_REG_LO2CQ_3] | 0xE0;
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03002077 status |=
Mauro Carvalho Chehabe1de3d12011-07-21 02:46:49 -03002078 mt2063_write(state,
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03002079 MT2063_REG_LO2CQ_3,
2080 &tmpOneShot, 1);
2081
2082 /* only restore LO1 queue value if they were different from the actual. */
2083 if (restore) {
2084 /* put previous LO1 queue value back into queue */
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03002085 status |=
Mauro Carvalho Chehabe1de3d12011-07-21 02:46:49 -03002086 mt2063_write(state,
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03002087 MT2063_REG_LO1CQ_1,
2088 &(tempLO1CQ[0]), 2);
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03002089
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03002090 /* cache the bytes just written. */
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03002091 state->reg[MT2063_REG_LO1CQ_1] =
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03002092 tempLO1CQ[0];
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03002093 state->reg[MT2063_REG_LO1CQ_2] =
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03002094 tempLO1CQ[1];
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03002095 }
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03002096
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03002097 MT2063_GetParam(state,
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03002098 MT2063_LO2_FREQ,
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03002099 &state->AS_Data.f_LO2);
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03002100 }
2101 break;
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03002102
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03002103 /* LO2 FracN keep-out region */
2104 case MT2063_LO2_FRACN_AVOID:
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03002105 state->AS_Data.f_LO2_FracN_Avoid = nValue;
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03002106 break;
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03002107
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03002108 /* output center frequency */
2109 case MT2063_OUTPUT_FREQ:
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03002110 state->AS_Data.f_out = nValue;
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03002111 break;
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03002112
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03002113 /* output bandwidth */
2114 case MT2063_OUTPUT_BW:
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03002115 state->AS_Data.f_out_bw = nValue + 750000;
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03002116 break;
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03002117
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03002118 case MT2063_RCVR_MODE:
2119 status |=
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03002120 MT2063_SetReceiverMode(state,
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03002121 (enum MT2063_RCVR_MODES)
2122 nValue);
2123 break;
2124
2125 /* Set LNA Rin -- nValue is desired value */
2126 case MT2063_LNA_RIN:
2127 val =
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03002128 (state->
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03002129 reg[MT2063_REG_CTRL_2C] & (u8) ~ 0x03) |
2130 (nValue & 0x03);
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03002131 if (state->reg[MT2063_REG_CTRL_2C] != val) {
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03002132 status |=
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03002133 MT2063_SetReg(state, MT2063_REG_CTRL_2C,
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03002134 val);
2135 }
2136 break;
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03002137
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03002138 /* Set target power level at LNA -- nValue is desired value */
2139 case MT2063_LNA_TGT:
2140 val =
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03002141 (state->
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03002142 reg[MT2063_REG_LNA_TGT] & (u8) ~ 0x3F) |
2143 (nValue & 0x3F);
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03002144 if (state->reg[MT2063_REG_LNA_TGT] != val) {
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03002145 status |=
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03002146 MT2063_SetReg(state, MT2063_REG_LNA_TGT,
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03002147 val);
2148 }
2149 break;
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03002150
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03002151 /* Set target power level at PD1 -- nValue is desired value */
2152 case MT2063_PD1_TGT:
2153 val =
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03002154 (state->
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03002155 reg[MT2063_REG_PD1_TGT] & (u8) ~ 0x3F) |
2156 (nValue & 0x3F);
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03002157 if (state->reg[MT2063_REG_PD1_TGT] != val) {
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03002158 status |=
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03002159 MT2063_SetReg(state, MT2063_REG_PD1_TGT,
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03002160 val);
2161 }
2162 break;
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03002163
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03002164 /* Set target power level at PD2 -- nValue is desired value */
2165 case MT2063_PD2_TGT:
2166 val =
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03002167 (state->
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03002168 reg[MT2063_REG_PD2_TGT] & (u8) ~ 0x3F) |
2169 (nValue & 0x3F);
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03002170 if (state->reg[MT2063_REG_PD2_TGT] != val) {
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03002171 status |=
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03002172 MT2063_SetReg(state, MT2063_REG_PD2_TGT,
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03002173 val);
2174 }
2175 break;
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03002176
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03002177 /* Set LNA atten limit -- nValue is desired value */
2178 case MT2063_ACLNA_MAX:
2179 val =
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03002180 (state->
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03002181 reg[MT2063_REG_LNA_OV] & (u8) ~ 0x1F) | (nValue
2182 &
2183 0x1F);
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03002184 if (state->reg[MT2063_REG_LNA_OV] != val) {
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03002185 status |=
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03002186 MT2063_SetReg(state, MT2063_REG_LNA_OV,
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03002187 val);
2188 }
2189 break;
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03002190
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03002191 /* Set RF atten limit -- nValue is desired value */
2192 case MT2063_ACRF_MAX:
2193 val =
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03002194 (state->
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03002195 reg[MT2063_REG_RF_OV] & (u8) ~ 0x1F) | (nValue
2196 &
2197 0x1F);
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03002198 if (state->reg[MT2063_REG_RF_OV] != val) {
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03002199 status |=
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03002200 MT2063_SetReg(state, MT2063_REG_RF_OV, val);
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03002201 }
2202 break;
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03002203
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03002204 /* Set FIF atten limit -- nValue is desired value, max. 5 if no B3 */
2205 case MT2063_ACFIF_MAX:
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03002206 if (state->reg[MT2063_REG_PART_REV] != MT2063_B3
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03002207 && nValue > 5)
2208 nValue = 5;
2209 val =
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03002210 (state->
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03002211 reg[MT2063_REG_FIF_OV] & (u8) ~ 0x1F) | (nValue
2212 &
2213 0x1F);
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03002214 if (state->reg[MT2063_REG_FIF_OV] != val) {
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03002215 status |=
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03002216 MT2063_SetReg(state, MT2063_REG_FIF_OV,
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03002217 val);
2218 }
2219 break;
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03002220
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03002221 case MT2063_DNC_OUTPUT_ENABLE:
2222 /* selects, which DNC output is used */
Mauro Carvalho Chehab29a0a4fe2011-07-20 23:44:10 -03002223 switch (nValue) {
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03002224 case MT2063_DNC_NONE:
2225 {
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03002226 val = (state->reg[MT2063_REG_DNC_GAIN] & 0xFC) | 0x03; /* Set DNC1GC=3 */
2227 if (state->reg[MT2063_REG_DNC_GAIN] !=
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03002228 val)
2229 status |=
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03002230 MT2063_SetReg(state,
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03002231 MT2063_REG_DNC_GAIN,
2232 val);
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03002233
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03002234 val = (state->reg[MT2063_REG_VGA_GAIN] & 0xFC) | 0x03; /* Set DNC2GC=3 */
2235 if (state->reg[MT2063_REG_VGA_GAIN] !=
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03002236 val)
2237 status |=
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03002238 MT2063_SetReg(state,
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03002239 MT2063_REG_VGA_GAIN,
2240 val);
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03002241
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03002242 val = (state->reg[MT2063_REG_RSVD_20] & ~0x40); /* Set PD2MUX=0 */
2243 if (state->reg[MT2063_REG_RSVD_20] !=
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03002244 val)
2245 status |=
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03002246 MT2063_SetReg(state,
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03002247 MT2063_REG_RSVD_20,
2248 val);
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03002249
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03002250 break;
2251 }
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03002252 case MT2063_DNC_1:
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03002253 {
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03002254 val = (state->reg[MT2063_REG_DNC_GAIN] & 0xFC) | (DNC1GC[state->rcvr_mode] & 0x03); /* Set DNC1GC=x */
2255 if (state->reg[MT2063_REG_DNC_GAIN] !=
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03002256 val)
2257 status |=
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03002258 MT2063_SetReg(state,
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03002259 MT2063_REG_DNC_GAIN,
2260 val);
2261
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03002262 val = (state->reg[MT2063_REG_VGA_GAIN] & 0xFC) | 0x03; /* Set DNC2GC=3 */
2263 if (state->reg[MT2063_REG_VGA_GAIN] !=
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03002264 val)
2265 status |=
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03002266 MT2063_SetReg(state,
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03002267 MT2063_REG_VGA_GAIN,
2268 val);
2269
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03002270 val = (state->reg[MT2063_REG_RSVD_20] & ~0x40); /* Set PD2MUX=0 */
2271 if (state->reg[MT2063_REG_RSVD_20] !=
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03002272 val)
2273 status |=
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03002274 MT2063_SetReg(state,
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03002275 MT2063_REG_RSVD_20,
2276 val);
2277
2278 break;
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03002279 }
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03002280 case MT2063_DNC_2:
2281 {
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03002282 val = (state->reg[MT2063_REG_DNC_GAIN] & 0xFC) | 0x03; /* Set DNC1GC=3 */
2283 if (state->reg[MT2063_REG_DNC_GAIN] !=
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03002284 val)
2285 status |=
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03002286 MT2063_SetReg(state,
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03002287 MT2063_REG_DNC_GAIN,
2288 val);
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03002289
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03002290 val = (state->reg[MT2063_REG_VGA_GAIN] & 0xFC) | (DNC2GC[state->rcvr_mode] & 0x03); /* Set DNC2GC=x */
2291 if (state->reg[MT2063_REG_VGA_GAIN] !=
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03002292 val)
2293 status |=
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03002294 MT2063_SetReg(state,
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03002295 MT2063_REG_VGA_GAIN,
2296 val);
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03002297
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03002298 val = (state->reg[MT2063_REG_RSVD_20] | 0x40); /* Set PD2MUX=1 */
2299 if (state->reg[MT2063_REG_RSVD_20] !=
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03002300 val)
2301 status |=
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03002302 MT2063_SetReg(state,
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03002303 MT2063_REG_RSVD_20,
2304 val);
2305
2306 break;
2307 }
2308 case MT2063_DNC_BOTH:
2309 {
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03002310 val = (state->reg[MT2063_REG_DNC_GAIN] & 0xFC) | (DNC1GC[state->rcvr_mode] & 0x03); /* Set DNC1GC=x */
2311 if (state->reg[MT2063_REG_DNC_GAIN] !=
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03002312 val)
2313 status |=
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03002314 MT2063_SetReg(state,
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03002315 MT2063_REG_DNC_GAIN,
2316 val);
2317
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03002318 val = (state->reg[MT2063_REG_VGA_GAIN] & 0xFC) | (DNC2GC[state->rcvr_mode] & 0x03); /* Set DNC2GC=x */
2319 if (state->reg[MT2063_REG_VGA_GAIN] !=
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03002320 val)
2321 status |=
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03002322 MT2063_SetReg(state,
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03002323 MT2063_REG_VGA_GAIN,
2324 val);
2325
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03002326 val = (state->reg[MT2063_REG_RSVD_20] | 0x40); /* Set PD2MUX=1 */
2327 if (state->reg[MT2063_REG_RSVD_20] !=
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03002328 val)
2329 status |=
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03002330 MT2063_SetReg(state,
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03002331 MT2063_REG_RSVD_20,
2332 val);
2333
2334 break;
2335 }
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03002336 default:
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03002337 break;
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03002338 }
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03002339 break;
2340
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03002341 default:
2342 status |= -ERANGE;
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03002343 }
2344 return (status);
2345}
2346
2347/****************************************************************************
2348**
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03002349** Name: MT2063_ClearPowerMaskBits
2350**
2351** Description: Clears the power-down mask bits for various sections of
2352** the MT2063
2353**
2354** Parameters: h - Tuner handle (returned by MT2063_Open)
2355** Bits - Mask bits to be cleared.
2356**
2357** See definition of MT2063_Mask_Bits type for description
2358** of each of the power bits.
2359**
2360** Returns: status:
2361** MT_OK - No errors
2362** MT_INV_HANDLE - Invalid tuner handle
2363** MT_COMM_ERR - Serial bus communications error
2364**
2365** Dependencies: USERS MUST CALL MT2063_Open() FIRST!
2366**
2367** Revision History:
2368**
2369** SCR Date Author Description
2370** -------------------------------------------------------------------------
2371** 138 06-19-2007 DAD Ver 1.00: Initial, derived from mt2067_b.
2372**
2373****************************************************************************/
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03002374static u32 MT2063_ClearPowerMaskBits(struct mt2063_state *state, enum MT2063_Mask_Bits Bits)
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03002375{
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03002376 u32 status = 0; /* Status to be returned */
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03002377
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03002378 Bits = (enum MT2063_Mask_Bits)(Bits & MT2063_ALL_SD); /* Only valid bits for this tuner */
2379 if ((Bits & 0xFF00) != 0) {
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03002380 state->reg[MT2063_REG_PWR_2] &= ~(u8) (Bits >> 8);
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03002381 status |=
Mauro Carvalho Chehabe1de3d12011-07-21 02:46:49 -03002382 mt2063_write(state,
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03002383 MT2063_REG_PWR_2,
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03002384 &state->reg[MT2063_REG_PWR_2], 1);
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03002385 }
2386 if ((Bits & 0xFF) != 0) {
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03002387 state->reg[MT2063_REG_PWR_1] &= ~(u8) (Bits & 0xFF);
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03002388 status |=
Mauro Carvalho Chehabe1de3d12011-07-21 02:46:49 -03002389 mt2063_write(state,
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03002390 MT2063_REG_PWR_1,
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03002391 &state->reg[MT2063_REG_PWR_1], 1);
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03002392 }
2393
2394 return (status);
2395}
2396
2397/****************************************************************************
2398**
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03002399** Name: MT2063_SoftwareShutdown
2400**
2401** Description: Enables or disables software shutdown function. When
2402** Shutdown==1, any section whose power mask is set will be
2403** shutdown.
2404**
2405** Parameters: h - Tuner handle (returned by MT2063_Open)
2406** Shutdown - 1 = shutdown the masked sections, otherwise
2407** power all sections on
2408**
2409** Returns: status:
2410** MT_OK - No errors
2411** MT_INV_HANDLE - Invalid tuner handle
2412** MT_COMM_ERR - Serial bus communications error
2413**
2414** Dependencies: USERS MUST CALL MT2063_Open() FIRST!
2415**
2416** Revision History:
2417**
2418** SCR Date Author Description
2419** -------------------------------------------------------------------------
2420** 138 06-19-2007 DAD Ver 1.00: Initial, derived from mt2067_b.
2421** 01-03-2008 PINZ Ver 1.xx: Added a trigger of BYPATNUP for
2422** correct wakeup of the LNA
2423**
2424****************************************************************************/
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03002425static u32 MT2063_SoftwareShutdown(struct mt2063_state *state, u8 Shutdown)
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03002426{
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03002427 u32 status = 0; /* Status to be returned */
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03002428
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03002429 if (Shutdown == 1)
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03002430 state->reg[MT2063_REG_PWR_1] |= 0x04; /* Turn the bit on */
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03002431 else
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03002432 state->reg[MT2063_REG_PWR_1] &= ~0x04; /* Turn off the bit */
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03002433
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03002434 status |=
Mauro Carvalho Chehabe1de3d12011-07-21 02:46:49 -03002435 mt2063_write(state,
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03002436 MT2063_REG_PWR_1,
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03002437 &state->reg[MT2063_REG_PWR_1], 1);
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03002438
2439 if (Shutdown != 1) {
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03002440 state->reg[MT2063_REG_BYP_CTRL] =
2441 (state->reg[MT2063_REG_BYP_CTRL] & 0x9F) | 0x40;
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03002442 status |=
Mauro Carvalho Chehabe1de3d12011-07-21 02:46:49 -03002443 mt2063_write(state,
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03002444 MT2063_REG_BYP_CTRL,
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03002445 &state->reg[MT2063_REG_BYP_CTRL],
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03002446 1);
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03002447 state->reg[MT2063_REG_BYP_CTRL] =
2448 (state->reg[MT2063_REG_BYP_CTRL] & 0x9F);
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03002449 status |=
Mauro Carvalho Chehabe1de3d12011-07-21 02:46:49 -03002450 mt2063_write(state,
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03002451 MT2063_REG_BYP_CTRL,
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03002452 &state->reg[MT2063_REG_BYP_CTRL],
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03002453 1);
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03002454 }
2455
2456 return (status);
2457}
2458
2459/****************************************************************************
2460**
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03002461** Name: MT2063_SetReg
2462**
2463** Description: Sets an MT2063 register.
2464**
2465** Parameters: h - Tuner handle (returned by MT2063_Open)
2466** reg - MT2063 register/subaddress location
2467** val - MT2063 register/subaddress value
2468**
2469** Returns: status:
2470** MT_OK - No errors
2471** MT_COMM_ERR - Serial bus communications error
2472** MT_INV_HANDLE - Invalid tuner handle
2473** MT_ARG_RANGE - Argument out of range
2474**
2475** Dependencies: USERS MUST CALL MT2063_Open() FIRST!
2476**
2477** Use this function if you need to override a default
2478** register value
2479**
2480** Revision History:
2481**
2482** SCR Date Author Description
2483** -------------------------------------------------------------------------
2484** 138 06-19-2007 DAD Ver 1.00: Initial, derived from mt2067_b.
2485**
2486****************************************************************************/
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03002487static u32 MT2063_SetReg(struct mt2063_state *state, u8 reg, u8 val)
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03002488{
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03002489 u32 status = 0; /* Status to be returned */
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03002490
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03002491 if (reg >= MT2063_REG_END_REGS)
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03002492 status |= -ERANGE;
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03002493
Mauro Carvalho Chehabe1de3d12011-07-21 02:46:49 -03002494 status = mt2063_write(state, reg, &val,
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03002495 1);
2496 if (status >= 0)
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03002497 state->reg[reg] = val;
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03002498
2499 return (status);
2500}
2501
Mauro Carvalho Chehabcfde8922011-07-20 21:01:48 -03002502static u32 MT2063_Round_fLO(u32 f_LO, u32 f_LO_Step, u32 f_ref)
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03002503{
2504 return f_ref * (f_LO / f_ref)
2505 + f_LO_Step * (((f_LO % f_ref) + (f_LO_Step / 2)) / f_LO_Step);
2506}
2507
2508/****************************************************************************
2509**
2510** Name: fLO_FractionalTerm
2511**
2512** Description: Calculates the portion contributed by FracN / denom.
2513**
2514** This function preserves maximum precision without
2515** risk of overflow. It accurately calculates
2516** f_ref * num / denom to within 1 HZ with fixed math.
2517**
2518** Parameters: num - Fractional portion of the multiplier
2519** denom - denominator portion of the ratio
2520** This routine successfully handles denom values
2521** up to and including 2^18.
2522** f_Ref - SRO frequency. This calculation handles
2523** f_ref as two separate 14-bit fields.
2524** Therefore, a maximum value of 2^28-1
2525** may safely be used for f_ref. This is
2526** the genesis of the magic number "14" and the
2527** magic mask value of 0x03FFF.
2528**
2529** Returns: f_ref * num / denom
2530**
2531** Revision History:
2532**
2533** SCR Date Author Description
2534** -------------------------------------------------------------------------
2535** 138 06-19-2007 DAD Ver 1.00: Initial, derived from mt2067_b.
2536**
2537****************************************************************************/
Mauro Carvalho Chehabcfde8922011-07-20 21:01:48 -03002538static u32 MT2063_fLO_FractionalTerm(u32 f_ref,
2539 u32 num, u32 denom)
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03002540{
Mauro Carvalho Chehabcfde8922011-07-20 21:01:48 -03002541 u32 t1 = (f_ref >> 14) * num;
2542 u32 term1 = t1 / denom;
2543 u32 loss = t1 % denom;
2544 u32 term2 =
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03002545 (((f_ref & 0x00003FFF) * num + (loss << 14)) + (denom / 2)) / denom;
2546 return ((term1 << 14) + term2);
2547}
2548
2549/****************************************************************************
2550**
2551** Name: CalcLO1Mult
2552**
2553** Description: Calculates Integer divider value and the numerator
2554** value for a FracN PLL.
2555**
2556** This function assumes that the f_LO and f_Ref are
2557** evenly divisible by f_LO_Step.
2558**
2559** Parameters: Div - OUTPUT: Whole number portion of the multiplier
2560** FracN - OUTPUT: Fractional portion of the multiplier
2561** f_LO - desired LO frequency.
2562** f_LO_Step - Minimum step size for the LO (in Hz).
2563** f_Ref - SRO frequency.
2564** f_Avoid - Range of PLL frequencies to avoid near
2565** integer multiples of f_Ref (in Hz).
2566**
2567** Returns: Recalculated LO frequency.
2568**
2569** Revision History:
2570**
2571** SCR Date Author Description
2572** -------------------------------------------------------------------------
2573** 138 06-19-2007 DAD Ver 1.00: Initial, derived from mt2067_b.
2574**
2575****************************************************************************/
Mauro Carvalho Chehabcfde8922011-07-20 21:01:48 -03002576static u32 MT2063_CalcLO1Mult(u32 * Div,
2577 u32 * FracN,
2578 u32 f_LO,
2579 u32 f_LO_Step, u32 f_Ref)
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03002580{
2581 /* Calculate the whole number portion of the divider */
2582 *Div = f_LO / f_Ref;
2583
2584 /* Calculate the numerator value (round to nearest f_LO_Step) */
2585 *FracN =
2586 (64 * (((f_LO % f_Ref) + (f_LO_Step / 2)) / f_LO_Step) +
2587 (f_Ref / f_LO_Step / 2)) / (f_Ref / f_LO_Step);
2588
2589 return (f_Ref * (*Div)) + MT2063_fLO_FractionalTerm(f_Ref, *FracN, 64);
2590}
2591
2592/****************************************************************************
2593**
2594** Name: CalcLO2Mult
2595**
2596** Description: Calculates Integer divider value and the numerator
2597** value for a FracN PLL.
2598**
2599** This function assumes that the f_LO and f_Ref are
2600** evenly divisible by f_LO_Step.
2601**
2602** Parameters: Div - OUTPUT: Whole number portion of the multiplier
2603** FracN - OUTPUT: Fractional portion of the multiplier
2604** f_LO - desired LO frequency.
2605** f_LO_Step - Minimum step size for the LO (in Hz).
2606** f_Ref - SRO frequency.
2607** f_Avoid - Range of PLL frequencies to avoid near
2608** integer multiples of f_Ref (in Hz).
2609**
2610** Returns: Recalculated LO frequency.
2611**
2612** Revision History:
2613**
2614** SCR Date Author Description
2615** -------------------------------------------------------------------------
2616** 138 06-19-2007 DAD Ver 1.00: Initial, derived from mt2067_b.
2617**
2618****************************************************************************/
Mauro Carvalho Chehabcfde8922011-07-20 21:01:48 -03002619static u32 MT2063_CalcLO2Mult(u32 * Div,
2620 u32 * FracN,
2621 u32 f_LO,
2622 u32 f_LO_Step, u32 f_Ref)
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03002623{
2624 /* Calculate the whole number portion of the divider */
2625 *Div = f_LO / f_Ref;
2626
2627 /* Calculate the numerator value (round to nearest f_LO_Step) */
2628 *FracN =
2629 (8191 * (((f_LO % f_Ref) + (f_LO_Step / 2)) / f_LO_Step) +
2630 (f_Ref / f_LO_Step / 2)) / (f_Ref / f_LO_Step);
2631
2632 return (f_Ref * (*Div)) + MT2063_fLO_FractionalTerm(f_Ref, *FracN,
2633 8191);
2634}
2635
2636/****************************************************************************
2637**
2638** Name: FindClearTuneFilter
2639**
2640** Description: Calculate the corrrect ClearTune filter to be used for
2641** a given input frequency.
2642**
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03002643** Parameters: state - ptr to tuner data structure
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03002644** f_in - RF input center frequency (in Hz).
2645**
2646** Returns: ClearTune filter number (0-31)
2647**
2648** Dependencies: MUST CALL MT2064_Open BEFORE FindClearTuneFilter!
2649**
2650** Revision History:
2651**
2652** SCR Date Author Description
2653** -------------------------------------------------------------------------
2654** 04-10-2008 PINZ Ver 1.14: Use software-controlled ClearTune
2655** cross-over frequency values.
2656**
2657****************************************************************************/
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03002658static u32 FindClearTuneFilter(struct mt2063_state *state, u32 f_in)
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03002659{
Mauro Carvalho Chehabcfde8922011-07-20 21:01:48 -03002660 u32 RFBand;
2661 u32 idx; /* index loop */
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03002662
2663 /*
2664 ** Find RF Band setting
2665 */
2666 RFBand = 31; /* def when f_in > all */
2667 for (idx = 0; idx < 31; ++idx) {
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03002668 if (state->CTFiltMax[idx] >= f_in) {
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03002669 RFBand = idx;
2670 break;
2671 }
2672 }
2673 return (RFBand);
2674}
2675
2676/****************************************************************************
2677**
2678** Name: MT2063_Tune
2679**
2680** Description: Change the tuner's tuned frequency to RFin.
2681**
2682** Parameters: h - Open handle to the tuner (from MT2063_Open).
2683** f_in - RF input center frequency (in Hz).
2684**
2685** Returns: status:
2686** MT_OK - No errors
2687** MT_INV_HANDLE - Invalid tuner handle
2688** MT_UPC_UNLOCK - Upconverter PLL unlocked
2689** MT_DNC_UNLOCK - Downconverter PLL unlocked
2690** MT_COMM_ERR - Serial bus communications error
2691** MT_SPUR_CNT_MASK - Count of avoided LO spurs
2692** MT_SPUR_PRESENT - LO spur possible in output
2693** MT_FIN_RANGE - Input freq out of range
2694** MT_FOUT_RANGE - Output freq out of range
2695** MT_UPC_RANGE - Upconverter freq out of range
2696** MT_DNC_RANGE - Downconverter freq out of range
2697**
2698** Dependencies: MUST CALL MT2063_Open BEFORE MT2063_Tune!
2699**
2700** MT_ReadSub - Read data from the two-wire serial bus
2701** MT_WriteSub - Write data to the two-wire serial bus
2702** MT_Sleep - Delay execution for x milliseconds
2703** MT2063_GetLocked - Checks to see if LO1 and LO2 are locked
2704**
2705** Revision History:
2706**
2707** SCR Date Author Description
2708** -------------------------------------------------------------------------
2709** 138 06-19-2007 DAD Ver 1.00: Initial, derived from mt2067_b.
2710** 04-10-2008 PINZ Ver 1.05: Use software-controlled ClearTune
2711** cross-over frequency values.
2712** 175 I 16-06-2008 PINZ Ver 1.16: Add control to avoid US DECT freqs.
2713** 175 I 06-19-2008 RSK Ver 1.17: Refactor DECT control to SpurAvoid.
2714** 06-24-2008 PINZ Ver 1.18: Add Get/SetParam CTFILT_SW
2715**
2716****************************************************************************/
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03002717static u32 MT2063_Tune(struct mt2063_state *state, u32 f_in)
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03002718{ /* RF input center frequency */
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03002719
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03002720 u32 status = 0; /* status of operation */
Mauro Carvalho Chehabcfde8922011-07-20 21:01:48 -03002721 u32 LO1; /* 1st LO register value */
2722 u32 Num1; /* Numerator for LO1 reg. value */
2723 u32 f_IF1; /* 1st IF requested */
2724 u32 LO2; /* 2nd LO register value */
2725 u32 Num2; /* Numerator for LO2 reg. value */
2726 u32 ofLO1, ofLO2; /* last time's LO frequencies */
2727 u32 ofin, ofout; /* last time's I/O frequencies */
2728 u8 fiffc = 0x80; /* FIFF center freq from tuner */
2729 u32 fiffof; /* Offset from FIFF center freq */
2730 const u8 LO1LK = 0x80; /* Mask for LO1 Lock bit */
2731 u8 LO2LK = 0x08; /* Mask for LO2 Lock bit */
2732 u8 val;
2733 u32 RFBand;
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03002734
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03002735 /* Check the input and output frequency ranges */
2736 if ((f_in < MT2063_MIN_FIN_FREQ) || (f_in > MT2063_MAX_FIN_FREQ))
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03002737 return -EINVAL;
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03002738
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03002739 if ((state->AS_Data.f_out < MT2063_MIN_FOUT_FREQ)
2740 || (state->AS_Data.f_out > MT2063_MAX_FOUT_FREQ))
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03002741 return -EINVAL;
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03002742
2743 /*
2744 ** Save original LO1 and LO2 register values
2745 */
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03002746 ofLO1 = state->AS_Data.f_LO1;
2747 ofLO2 = state->AS_Data.f_LO2;
2748 ofin = state->AS_Data.f_in;
2749 ofout = state->AS_Data.f_out;
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03002750
2751 /*
2752 ** Find and set RF Band setting
2753 */
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03002754 if (state->ctfilt_sw == 1) {
2755 val = (state->reg[MT2063_REG_CTUNE_CTRL] | 0x08);
2756 if (state->reg[MT2063_REG_CTUNE_CTRL] != val) {
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03002757 status |=
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03002758 MT2063_SetReg(state, MT2063_REG_CTUNE_CTRL, val);
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03002759 }
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03002760 val = state->reg[MT2063_REG_CTUNE_OV];
2761 RFBand = FindClearTuneFilter(state, f_in);
2762 state->reg[MT2063_REG_CTUNE_OV] =
2763 (u8) ((state->reg[MT2063_REG_CTUNE_OV] & ~0x1F)
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03002764 | RFBand);
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03002765 if (state->reg[MT2063_REG_CTUNE_OV] != val) {
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03002766 status |=
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03002767 MT2063_SetReg(state, MT2063_REG_CTUNE_OV, val);
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03002768 }
2769 }
2770
2771 /*
2772 ** Read the FIFF Center Frequency from the tuner
2773 */
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03002774 if (status >= 0) {
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03002775 status |=
Mauro Carvalho Chehabe1de3d12011-07-21 02:46:49 -03002776 mt2063_read(state,
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03002777 MT2063_REG_FIFFC,
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03002778 &state->reg[MT2063_REG_FIFFC], 1);
2779 fiffc = state->reg[MT2063_REG_FIFFC];
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03002780 }
2781 /*
2782 ** Assign in the requested values
2783 */
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03002784 state->AS_Data.f_in = f_in;
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03002785 /* Request a 1st IF such that LO1 is on a step size */
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03002786 state->AS_Data.f_if1_Request =
2787 MT2063_Round_fLO(state->AS_Data.f_if1_Request + f_in,
2788 state->AS_Data.f_LO1_Step,
2789 state->AS_Data.f_ref) - f_in;
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03002790
2791 /*
2792 ** Calculate frequency settings. f_IF1_FREQ + f_in is the
2793 ** desired LO1 frequency
2794 */
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03002795 MT2063_ResetExclZones(&state->AS_Data);
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03002796
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03002797 f_IF1 = MT2063_ChooseFirstIF(&state->AS_Data);
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03002798
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03002799 state->AS_Data.f_LO1 =
2800 MT2063_Round_fLO(f_IF1 + f_in, state->AS_Data.f_LO1_Step,
2801 state->AS_Data.f_ref);
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03002802
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03002803 state->AS_Data.f_LO2 =
2804 MT2063_Round_fLO(state->AS_Data.f_LO1 - state->AS_Data.f_out - f_in,
2805 state->AS_Data.f_LO2_Step, state->AS_Data.f_ref);
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03002806
2807 /*
2808 ** Check for any LO spurs in the output bandwidth and adjust
2809 ** the LO settings to avoid them if needed
2810 */
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03002811 status |= MT2063_AvoidSpurs(state, &state->AS_Data);
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03002812 /*
2813 ** MT_AvoidSpurs spurs may have changed the LO1 & LO2 values.
2814 ** Recalculate the LO frequencies and the values to be placed
2815 ** in the tuning registers.
2816 */
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03002817 state->AS_Data.f_LO1 =
2818 MT2063_CalcLO1Mult(&LO1, &Num1, state->AS_Data.f_LO1,
2819 state->AS_Data.f_LO1_Step, state->AS_Data.f_ref);
2820 state->AS_Data.f_LO2 =
2821 MT2063_Round_fLO(state->AS_Data.f_LO1 - state->AS_Data.f_out - f_in,
2822 state->AS_Data.f_LO2_Step, state->AS_Data.f_ref);
2823 state->AS_Data.f_LO2 =
2824 MT2063_CalcLO2Mult(&LO2, &Num2, state->AS_Data.f_LO2,
2825 state->AS_Data.f_LO2_Step, state->AS_Data.f_ref);
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03002826
2827 /*
2828 ** Check the upconverter and downconverter frequency ranges
2829 */
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03002830 if ((state->AS_Data.f_LO1 < MT2063_MIN_UPC_FREQ)
2831 || (state->AS_Data.f_LO1 > MT2063_MAX_UPC_FREQ))
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03002832 status |= MT2063_UPC_RANGE;
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03002833 if ((state->AS_Data.f_LO2 < MT2063_MIN_DNC_FREQ)
2834 || (state->AS_Data.f_LO2 > MT2063_MAX_DNC_FREQ))
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03002835 status |= MT2063_DNC_RANGE;
2836 /* LO2 Lock bit was in a different place for B0 version */
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03002837 if (state->tuner_id == MT2063_B0)
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03002838 LO2LK = 0x40;
2839
2840 /*
2841 ** If we have the same LO frequencies and we're already locked,
2842 ** then skip re-programming the LO registers.
2843 */
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03002844 if ((ofLO1 != state->AS_Data.f_LO1)
2845 || (ofLO2 != state->AS_Data.f_LO2)
2846 || ((state->reg[MT2063_REG_LO_STATUS] & (LO1LK | LO2LK)) !=
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03002847 (LO1LK | LO2LK))) {
2848 /*
2849 ** Calculate the FIFFOF register value
2850 **
2851 ** IF1_Actual
2852 ** FIFFOF = ------------ - 8 * FIFFC - 4992
2853 ** f_ref/64
2854 */
2855 fiffof =
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03002856 (state->AS_Data.f_LO1 -
2857 f_in) / (state->AS_Data.f_ref / 64) - 8 * (u32) fiffc -
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03002858 4992;
2859 if (fiffof > 0xFF)
2860 fiffof = 0xFF;
2861
2862 /*
2863 ** Place all of the calculated values into the local tuner
2864 ** register fields.
2865 */
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03002866 if (status >= 0) {
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03002867 state->reg[MT2063_REG_LO1CQ_1] = (u8) (LO1 & 0xFF); /* DIV1q */
2868 state->reg[MT2063_REG_LO1CQ_2] = (u8) (Num1 & 0x3F); /* NUM1q */
2869 state->reg[MT2063_REG_LO2CQ_1] = (u8) (((LO2 & 0x7F) << 1) /* DIV2q */
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03002870 |(Num2 >> 12)); /* NUM2q (hi) */
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03002871 state->reg[MT2063_REG_LO2CQ_2] = (u8) ((Num2 & 0x0FF0) >> 4); /* NUM2q (mid) */
2872 state->reg[MT2063_REG_LO2CQ_3] = (u8) (0xE0 | (Num2 & 0x000F)); /* NUM2q (lo) */
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03002873
2874 /*
2875 ** Now write out the computed register values
2876 ** IMPORTANT: There is a required order for writing
2877 ** (0x05 must follow all the others).
2878 */
Mauro Carvalho Chehabe1de3d12011-07-21 02:46:49 -03002879 status |= mt2063_write(state, MT2063_REG_LO1CQ_1, &state->reg[MT2063_REG_LO1CQ_1], 5); /* 0x01 - 0x05 */
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03002880 if (state->tuner_id == MT2063_B0) {
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03002881 /* Re-write the one-shot bits to trigger the tune operation */
Mauro Carvalho Chehabe1de3d12011-07-21 02:46:49 -03002882 status |= mt2063_write(state, MT2063_REG_LO2CQ_3, &state->reg[MT2063_REG_LO2CQ_3], 1); /* 0x05 */
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03002883 }
2884 /* Write out the FIFF offset only if it's changing */
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03002885 if (state->reg[MT2063_REG_FIFF_OFFSET] !=
Mauro Carvalho Chehabcfde8922011-07-20 21:01:48 -03002886 (u8) fiffof) {
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03002887 state->reg[MT2063_REG_FIFF_OFFSET] =
Mauro Carvalho Chehabcfde8922011-07-20 21:01:48 -03002888 (u8) fiffof;
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03002889 status |=
Mauro Carvalho Chehabe1de3d12011-07-21 02:46:49 -03002890 mt2063_write(state,
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03002891 MT2063_REG_FIFF_OFFSET,
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03002892 &state->
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03002893 reg[MT2063_REG_FIFF_OFFSET],
2894 1);
2895 }
2896 }
2897
2898 /*
2899 ** Check for LO's locking
2900 */
2901
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03002902 if (status >= 0) {
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03002903 status |= MT2063_GetLocked(state);
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03002904 }
2905 /*
Mauro Carvalho Chehab51f0f7b2011-07-21 02:24:18 -03002906 ** If we locked OK, assign calculated data to mt2063_state structure
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03002907 */
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03002908 if (status >= 0) {
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03002909 state->f_IF1_actual = state->AS_Data.f_LO1 - f_in;
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03002910 }
2911 }
2912
2913 return (status);
2914}
2915
Mauro Carvalho Chehabbf975552011-07-20 21:43:30 -03002916static u32 MT_Tune_atv(void *h, u32 f_in, u32 bw_in,
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03002917 enum MTTune_atv_standard tv_type)
2918{
2919
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03002920 u32 status = 0;
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03002921
Mauro Carvalho Chehabcfde8922011-07-20 21:01:48 -03002922 s32 pict_car = 0;
2923 s32 pict2chanb_vsb = 0;
2924 s32 pict2chanb_snd = 0;
2925 s32 pict2snd1 = 0;
2926 s32 pict2snd2 = 0;
2927 s32 ch_bw = 0;
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03002928
Mauro Carvalho Chehabcfde8922011-07-20 21:01:48 -03002929 s32 if_mid = 0;
2930 s32 rcvr_mode = 0;
2931 u32 mode_get = 0;
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03002932
2933 switch (tv_type) {
2934 case MTTUNEA_PAL_B:{
2935 pict_car = 38900000;
2936 ch_bw = 8000000;
2937 pict2chanb_vsb = -1250000;
2938 pict2snd1 = 5500000;
2939 pict2snd2 = 5742000;
2940 rcvr_mode = 1;
2941 break;
2942 }
2943 case MTTUNEA_PAL_G:{
2944 pict_car = 38900000;
2945 ch_bw = 7000000;
2946 pict2chanb_vsb = -1250000;
2947 pict2snd1 = 5500000;
2948 pict2snd2 = 0;
2949 rcvr_mode = 1;
2950 break;
2951 }
2952 case MTTUNEA_PAL_I:{
2953 pict_car = 38900000;
2954 ch_bw = 8000000;
2955 pict2chanb_vsb = -1250000;
2956 pict2snd1 = 6000000;
2957 pict2snd2 = 0;
2958 rcvr_mode = 1;
2959 break;
2960 }
2961 case MTTUNEA_PAL_L:{
2962 pict_car = 38900000;
2963 ch_bw = 8000000;
2964 pict2chanb_vsb = -1250000;
2965 pict2snd1 = 6500000;
2966 pict2snd2 = 0;
2967 rcvr_mode = 1;
2968 break;
2969 }
2970 case MTTUNEA_PAL_MN:{
2971 pict_car = 38900000;
2972 ch_bw = 6000000;
2973 pict2chanb_vsb = -1250000;
2974 pict2snd1 = 4500000;
2975 pict2snd2 = 0;
2976 rcvr_mode = 1;
2977 break;
2978 }
2979 case MTTUNEA_PAL_DK:{
2980 pict_car = 38900000;
2981 ch_bw = 8000000;
2982 pict2chanb_vsb = -1250000;
2983 pict2snd1 = 6500000;
2984 pict2snd2 = 0;
2985 rcvr_mode = 1;
2986 break;
2987 }
2988 case MTTUNEA_DIGITAL:{
2989 pict_car = 36125000;
2990 ch_bw = 8000000;
2991 pict2chanb_vsb = -(ch_bw / 2);
2992 pict2snd1 = 0;
2993 pict2snd2 = 0;
2994 rcvr_mode = 2;
2995 break;
2996 }
2997 case MTTUNEA_FMRADIO:{
2998 pict_car = 38900000;
2999 ch_bw = 8000000;
3000 pict2chanb_vsb = -(ch_bw / 2);
3001 pict2snd1 = 0;
3002 pict2snd2 = 0;
3003 rcvr_mode = 4;
3004 //f_in -= 2900000;
3005 break;
3006 }
3007 case MTTUNEA_DVBC:{
3008 pict_car = 36125000;
3009 ch_bw = 8000000;
3010 pict2chanb_vsb = -(ch_bw / 2);
3011 pict2snd1 = 0;
3012 pict2snd2 = 0;
3013 rcvr_mode = MT2063_CABLE_QAM;
3014 break;
3015 }
3016 case MTTUNEA_DVBT:{
3017 pict_car = 36125000;
3018 ch_bw = bw_in; //8000000
3019 pict2chanb_vsb = -(ch_bw / 2);
3020 pict2snd1 = 0;
3021 pict2snd2 = 0;
3022 rcvr_mode = MT2063_OFFAIR_COFDM;
3023 break;
3024 }
3025 case MTTUNEA_UNKNOWN:
3026 break;
3027 default:
3028 break;
3029 }
3030
3031 pict2chanb_snd = pict2chanb_vsb - ch_bw;
3032 if_mid = pict_car - (pict2chanb_vsb + (ch_bw / 2));
3033
3034 status |= MT2063_SetParam(h, MT2063_STEPSIZE, 125000);
3035 status |= MT2063_SetParam(h, MT2063_OUTPUT_FREQ, if_mid);
3036 status |= MT2063_SetParam(h, MT2063_OUTPUT_BW, ch_bw);
3037 status |= MT2063_GetParam(h, MT2063_RCVR_MODE, &mode_get);
3038
3039 status |= MT2063_SetParam(h, MT2063_RCVR_MODE, rcvr_mode);
3040 status |= MT2063_Tune(h, (f_in + (pict2chanb_vsb + (ch_bw / 2))));
3041 status |= MT2063_GetParam(h, MT2063_RCVR_MODE, &mode_get);
3042
Mauro Carvalho Chehabcfde8922011-07-20 21:01:48 -03003043 return (u32) status;
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03003044}
3045
Mauro Carvalho Chehab01e0daf2011-07-21 03:20:43 -03003046static const u8 MT2063B0_defaults[] = {
3047 /* Reg, Value */
3048 0x19, 0x05,
3049 0x1B, 0x1D,
3050 0x1C, 0x1F,
3051 0x1D, 0x0F,
3052 0x1E, 0x3F,
3053 0x1F, 0x0F,
3054 0x20, 0x3F,
3055 0x22, 0x21,
3056 0x23, 0x3F,
3057 0x24, 0x20,
3058 0x25, 0x3F,
3059 0x27, 0xEE,
3060 0x2C, 0x27, /* bit at 0x20 is cleared below */
3061 0x30, 0x03,
3062 0x2C, 0x07, /* bit at 0x20 is cleared here */
3063 0x2D, 0x87,
3064 0x2E, 0xAA,
3065 0x28, 0xE1, /* Set the FIFCrst bit here */
3066 0x28, 0xE0, /* Clear the FIFCrst bit here */
3067 0x00
3068};
3069
3070/* writing 0x05 0xf0 sw-resets all registers, so we write only needed changes */
3071static const u8 MT2063B1_defaults[] = {
3072 /* Reg, Value */
3073 0x05, 0xF0,
3074 0x11, 0x10, /* New Enable AFCsd */
3075 0x19, 0x05,
3076 0x1A, 0x6C,
3077 0x1B, 0x24,
3078 0x1C, 0x28,
3079 0x1D, 0x8F,
3080 0x1E, 0x14,
3081 0x1F, 0x8F,
3082 0x20, 0x57,
3083 0x22, 0x21, /* New - ver 1.03 */
3084 0x23, 0x3C, /* New - ver 1.10 */
3085 0x24, 0x20, /* New - ver 1.03 */
3086 0x2C, 0x24, /* bit at 0x20 is cleared below */
3087 0x2D, 0x87, /* FIFFQ=0 */
3088 0x2F, 0xF3,
3089 0x30, 0x0C, /* New - ver 1.11 */
3090 0x31, 0x1B, /* New - ver 1.11 */
3091 0x2C, 0x04, /* bit at 0x20 is cleared here */
3092 0x28, 0xE1, /* Set the FIFCrst bit here */
3093 0x28, 0xE0, /* Clear the FIFCrst bit here */
3094 0x00
3095};
3096
3097/* writing 0x05 0xf0 sw-resets all registers, so we write only needed changes */
3098static const u8 MT2063B3_defaults[] = {
3099 /* Reg, Value */
3100 0x05, 0xF0,
3101 0x19, 0x3D,
3102 0x2C, 0x24, /* bit at 0x20 is cleared below */
3103 0x2C, 0x04, /* bit at 0x20 is cleared here */
3104 0x28, 0xE1, /* Set the FIFCrst bit here */
3105 0x28, 0xE0, /* Clear the FIFCrst bit here */
3106 0x00
3107};
3108
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03003109static int mt2063_init(struct dvb_frontend *fe)
3110{
Mauro Carvalho Chehab01e0daf2011-07-21 03:20:43 -03003111 u32 status;
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03003112 struct mt2063_state *state = fe->tuner_priv;
Mauro Carvalho Chehab01e0daf2011-07-21 03:20:43 -03003113 u8 all_resets = 0xF0; /* reset/load bits */
3114 const u8 *def = NULL;
3115 u32 FCRUN;
3116 s32 maxReads;
3117 u32 fcu_osc;
3118 u32 i;
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03003119
Mauro Carvalho Chehab01e0daf2011-07-21 03:20:43 -03003120 state->rcvr_mode = MT2063_CABLE_QAM;
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03003121
Mauro Carvalho Chehab01e0daf2011-07-21 03:20:43 -03003122 /* Read the Part/Rev code from the tuner */
3123 status = mt2063_read(state, MT2063_REG_PART_REV, state->reg, 1);
3124 if (status < 0)
3125 return status;
3126
3127 /* Check the part/rev code */
3128 if (((state->reg[MT2063_REG_PART_REV] != MT2063_B0) /* MT2063 B0 */
3129 &&(state->reg[MT2063_REG_PART_REV] != MT2063_B1) /* MT2063 B1 */
3130 &&(state->reg[MT2063_REG_PART_REV] != MT2063_B3))) /* MT2063 B3 */
3131 return -ENODEV; /* Wrong tuner Part/Rev code */
3132
3133 /* Check the 2nd byte of the Part/Rev code from the tuner */
3134 status = mt2063_read(state, MT2063_REG_RSVD_3B,
3135 &state->reg[MT2063_REG_RSVD_3B], 1);
3136
3137 /* b7 != 0 ==> NOT MT2063 */
3138 if (status < 0 ||((state->reg[MT2063_REG_RSVD_3B] & 0x80) != 0x00))
3139 return -ENODEV; /* Wrong tuner Part/Rev code */
3140
3141 /* Reset the tuner */
3142 status = mt2063_write(state, MT2063_REG_LO2CQ_3, &all_resets, 1);
3143 if (status < 0)
3144 return status;
3145
3146 /* change all of the default values that vary from the HW reset values */
3147 /* def = (state->reg[PART_REV] == MT2063_B0) ? MT2063B0_defaults : MT2063B1_defaults; */
3148 switch (state->reg[MT2063_REG_PART_REV]) {
3149 case MT2063_B3:
3150 def = MT2063B3_defaults;
3151 break;
3152
3153 case MT2063_B1:
3154 def = MT2063B1_defaults;
3155 break;
3156
3157 case MT2063_B0:
3158 def = MT2063B0_defaults;
3159 break;
3160
3161 default:
3162 return -ENODEV;
3163 break;
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03003164 }
3165
Mauro Carvalho Chehab01e0daf2011-07-21 03:20:43 -03003166 while (status >= 0 && *def) {
3167 u8 reg = *def++;
3168 u8 val = *def++;
3169 status = mt2063_write(state, reg, &val, 1);
3170 }
3171 if (status < 0)
3172 return status;
3173
3174 /* Wait for FIFF location to complete. */
3175 FCRUN = 1;
3176 maxReads = 10;
3177 while (status >= 0 && (FCRUN != 0) && (maxReads-- > 0)) {
3178 msleep(2);
3179 status = mt2063_read(state,
3180 MT2063_REG_XO_STATUS,
3181 &state->
3182 reg[MT2063_REG_XO_STATUS], 1);
3183 FCRUN = (state->reg[MT2063_REG_XO_STATUS] & 0x40) >> 6;
3184 }
3185
3186 if (FCRUN != 0 || status < 0)
3187 return -ENODEV;
3188
3189 status = mt2063_read(state,
3190 MT2063_REG_FIFFC,
3191 &state->reg[MT2063_REG_FIFFC], 1);
3192 if (status < 0)
3193 return status;
3194
3195 /* Read back all the registers from the tuner */
3196 status = mt2063_read(state,
3197 MT2063_REG_PART_REV,
3198 state->reg, MT2063_REG_END_REGS);
3199 if (status < 0)
3200 return status;
3201
3202 /* Initialize the tuner state. */
3203 state->tuner_id = state->reg[MT2063_REG_PART_REV];
3204 state->AS_Data.f_ref = MT2063_REF_FREQ;
3205 state->AS_Data.f_if1_Center = (state->AS_Data.f_ref / 8) *
3206 ((u32) state->reg[MT2063_REG_FIFFC] + 640);
3207 state->AS_Data.f_if1_bw = MT2063_IF1_BW;
3208 state->AS_Data.f_out = 43750000UL;
3209 state->AS_Data.f_out_bw = 6750000UL;
3210 state->AS_Data.f_zif_bw = MT2063_ZIF_BW;
3211 state->AS_Data.f_LO1_Step = state->AS_Data.f_ref / 64;
3212 state->AS_Data.f_LO2_Step = MT2063_TUNE_STEP_SIZE;
3213 state->AS_Data.maxH1 = MT2063_MAX_HARMONICS_1;
3214 state->AS_Data.maxH2 = MT2063_MAX_HARMONICS_2;
3215 state->AS_Data.f_min_LO_Separation = MT2063_MIN_LO_SEP;
3216 state->AS_Data.f_if1_Request = state->AS_Data.f_if1_Center;
3217 state->AS_Data.f_LO1 = 2181000000UL;
3218 state->AS_Data.f_LO2 = 1486249786UL;
3219 state->f_IF1_actual = state->AS_Data.f_if1_Center;
3220 state->AS_Data.f_in = state->AS_Data.f_LO1 - state->f_IF1_actual;
3221 state->AS_Data.f_LO1_FracN_Avoid = MT2063_LO1_FRACN_AVOID;
3222 state->AS_Data.f_LO2_FracN_Avoid = MT2063_LO2_FRACN_AVOID;
3223 state->num_regs = MT2063_REG_END_REGS;
3224 state->AS_Data.avoidDECT = MT2063_AVOID_BOTH;
3225 state->ctfilt_sw = 0;
3226
3227 state->CTFiltMax[0] = 69230000;
3228 state->CTFiltMax[1] = 105770000;
3229 state->CTFiltMax[2] = 140350000;
3230 state->CTFiltMax[3] = 177110000;
3231 state->CTFiltMax[4] = 212860000;
3232 state->CTFiltMax[5] = 241130000;
3233 state->CTFiltMax[6] = 274370000;
3234 state->CTFiltMax[7] = 309820000;
3235 state->CTFiltMax[8] = 342450000;
3236 state->CTFiltMax[9] = 378870000;
3237 state->CTFiltMax[10] = 416210000;
3238 state->CTFiltMax[11] = 456500000;
3239 state->CTFiltMax[12] = 495790000;
3240 state->CTFiltMax[13] = 534530000;
3241 state->CTFiltMax[14] = 572610000;
3242 state->CTFiltMax[15] = 598970000;
3243 state->CTFiltMax[16] = 635910000;
3244 state->CTFiltMax[17] = 672130000;
3245 state->CTFiltMax[18] = 714840000;
3246 state->CTFiltMax[19] = 739660000;
3247 state->CTFiltMax[20] = 770410000;
3248 state->CTFiltMax[21] = 814660000;
3249 state->CTFiltMax[22] = 846950000;
3250 state->CTFiltMax[23] = 867820000;
3251 state->CTFiltMax[24] = 915980000;
3252 state->CTFiltMax[25] = 947450000;
3253 state->CTFiltMax[26] = 983110000;
3254 state->CTFiltMax[27] = 1021630000;
3255 state->CTFiltMax[28] = 1061870000;
3256 state->CTFiltMax[29] = 1098330000;
3257 state->CTFiltMax[30] = 1138990000;
3258
3259 /*
3260 ** Fetch the FCU osc value and use it and the fRef value to
3261 ** scale all of the Band Max values
3262 */
3263
3264 state->reg[MT2063_REG_CTUNE_CTRL] = 0x0A;
3265 status = mt2063_write(state, MT2063_REG_CTUNE_CTRL,
3266 &state->reg[MT2063_REG_CTUNE_CTRL], 1);
3267 if (status < 0)
3268 return status;
3269
3270 /* Read the ClearTune filter calibration value */
3271 status = mt2063_read(state, MT2063_REG_FIFFC,
3272 &state->reg[MT2063_REG_FIFFC], 1);
3273 if (status < 0)
3274 return status;
3275
3276 fcu_osc = state->reg[MT2063_REG_FIFFC];
3277
3278 state->reg[MT2063_REG_CTUNE_CTRL] = 0x00;
3279 status = mt2063_write(state, MT2063_REG_CTUNE_CTRL,
3280 &state->reg[MT2063_REG_CTUNE_CTRL], 1);
3281 if (status < 0)
3282 return status;
3283
3284 /* Adjust each of the values in the ClearTune filter cross-over table */
3285 for (i = 0; i < 31; i++)
3286 state->CTFiltMax[i] =(state->CTFiltMax[i] / 768) * (fcu_osc + 640);
3287
3288 status = MT2063_SoftwareShutdown(state, 1);
3289 if (status < 0)
3290 return status;
3291 status = MT2063_ClearPowerMaskBits(state, MT2063_ALL_SD);
3292 if (status < 0)
3293 return status;
3294
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03003295 return 0;
3296}
3297
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03003298static int mt2063_get_status(struct dvb_frontend *fe, u32 * status)
3299{
3300 int rc = 0;
3301
3302 //get tuner lock status
3303
3304 return rc;
3305}
3306
3307static int mt2063_get_state(struct dvb_frontend *fe,
Mauro Carvalho Chehab51f0f7b2011-07-21 02:24:18 -03003308 enum tuner_param param, struct tuner_state *tunstate)
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03003309{
Mauro Carvalho Chehab51f0f7b2011-07-21 02:24:18 -03003310 struct mt2063_state *state = fe->tuner_priv;
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03003311
Mauro Carvalho Chehab223c7b02011-07-20 19:48:59 -03003312 switch (param) {
3313 case DVBFE_TUNER_FREQUENCY:
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03003314 //get frequency
Mauro Carvalho Chehab223c7b02011-07-20 19:48:59 -03003315 break;
3316 case DVBFE_TUNER_TUNERSTEP:
3317 break;
3318 case DVBFE_TUNER_IFFREQ:
3319 break;
3320 case DVBFE_TUNER_BANDWIDTH:
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03003321 //get bandwidth
Mauro Carvalho Chehab223c7b02011-07-20 19:48:59 -03003322 break;
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03003323 case DVBFE_TUNER_REFCLOCK:
Mauro Carvalho Chehab51f0f7b2011-07-21 02:24:18 -03003324 tunstate->refclock = (u32) MT2063_GetLocked(state);
Mauro Carvalho Chehab223c7b02011-07-20 19:48:59 -03003325 break;
3326 default:
3327 break;
3328 }
3329
Mauro Carvalho Chehab51f0f7b2011-07-21 02:24:18 -03003330 return (int)tunstate->refclock;
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03003331}
3332
3333static int mt2063_set_state(struct dvb_frontend *fe,
Mauro Carvalho Chehab51f0f7b2011-07-21 02:24:18 -03003334 enum tuner_param param, struct tuner_state *tunstate)
Mauro Carvalho Chehab223c7b02011-07-20 19:48:59 -03003335{
Mauro Carvalho Chehab51f0f7b2011-07-21 02:24:18 -03003336 struct mt2063_state *state = fe->tuner_priv;
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03003337 u32 status = 0;
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03003338
Mauro Carvalho Chehab223c7b02011-07-20 19:48:59 -03003339 switch (param) {
3340 case DVBFE_TUNER_FREQUENCY:
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03003341 //set frequency
3342
3343 status =
Mauro Carvalho Chehab51f0f7b2011-07-21 02:24:18 -03003344 MT_Tune_atv(state,
3345 tunstate->frequency, tunstate->bandwidth,
3346 state->tv_type);
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03003347
Mauro Carvalho Chehab51f0f7b2011-07-21 02:24:18 -03003348 state->frequency = tunstate->frequency;
Mauro Carvalho Chehab223c7b02011-07-20 19:48:59 -03003349 break;
3350 case DVBFE_TUNER_TUNERSTEP:
3351 break;
3352 case DVBFE_TUNER_IFFREQ:
3353 break;
3354 case DVBFE_TUNER_BANDWIDTH:
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03003355 //set bandwidth
Mauro Carvalho Chehab51f0f7b2011-07-21 02:24:18 -03003356 state->bandwidth = tunstate->bandwidth;
Mauro Carvalho Chehab223c7b02011-07-20 19:48:59 -03003357 break;
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03003358 case DVBFE_TUNER_REFCLOCK:
3359
3360 break;
Mauro Carvalho Chehab223c7b02011-07-20 19:48:59 -03003361 default:
3362 break;
3363 }
3364
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03003365 return (int)status;
3366}
3367
3368static int mt2063_release(struct dvb_frontend *fe)
Mauro Carvalho Chehab223c7b02011-07-20 19:48:59 -03003369{
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03003370 struct mt2063_state *state = fe->tuner_priv;
Mauro Carvalho Chehab223c7b02011-07-20 19:48:59 -03003371
3372 fe->tuner_priv = NULL;
3373 kfree(state);
3374
3375 return 0;
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03003376}
Mauro Carvalho Chehab223c7b02011-07-20 19:48:59 -03003377
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03003378static struct dvb_tuner_ops mt2063_ops = {
3379 .info = {
3380 .name = "MT2063 Silicon Tuner",
3381 .frequency_min = 45000000,
3382 .frequency_max = 850000000,
3383 .frequency_step = 0,
3384 },
3385
3386 .init = mt2063_init,
Mauro Carvalho Chehabbf975552011-07-20 21:43:30 -03003387 .sleep = MT2063_Sleep,
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03003388 .get_status = mt2063_get_status,
3389 .get_state = mt2063_get_state,
3390 .set_state = mt2063_set_state,
3391 .release = mt2063_release
Mauro Carvalho Chehab223c7b02011-07-20 19:48:59 -03003392};
3393
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03003394struct dvb_frontend *mt2063_attach(struct dvb_frontend *fe,
3395 struct mt2063_config *config,
3396 struct i2c_adapter *i2c)
Mauro Carvalho Chehab223c7b02011-07-20 19:48:59 -03003397{
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03003398 struct mt2063_state *state = NULL;
Mauro Carvalho Chehab223c7b02011-07-20 19:48:59 -03003399
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03003400 state = kzalloc(sizeof(struct mt2063_state), GFP_KERNEL);
Mauro Carvalho Chehab223c7b02011-07-20 19:48:59 -03003401 if (state == NULL)
3402 goto error;
3403
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03003404 state->config = config;
3405 state->i2c = i2c;
3406 state->frontend = fe;
3407 state->reference = config->refclock / 1000; /* kHz */
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03003408 fe->tuner_priv = state;
3409 fe->ops.tuner_ops = mt2063_ops;
Mauro Carvalho Chehab223c7b02011-07-20 19:48:59 -03003410
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03003411 printk("%s: Attaching MT2063 \n", __func__);
Mauro Carvalho Chehab223c7b02011-07-20 19:48:59 -03003412 return fe;
3413
3414error:
3415 kfree(state);
3416 return NULL;
3417}
3418
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03003419EXPORT_SYMBOL(mt2063_attach);
Mauro Carvalho Chehab223c7b02011-07-20 19:48:59 -03003420MODULE_PARM_DESC(verbose, "Set Verbosity level");
3421
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03003422MODULE_AUTHOR("Henry");
3423MODULE_DESCRIPTION("MT2063 Silicon tuner");
3424MODULE_LICENSE("GPL");