blob: 53e3960eb7c0a3851f16fb8afb5c9b8481adc11b [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 Chehab31e67fa2011-07-21 10:30:11 -030011/* positive error codes used internally */
Mauro Carvalho Chehab29a0a4f2011-07-20 23:44:10 -030012
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -030013/* Info: Unavoidable LO-related spur may be present in the output */
Mauro Carvalho Chehab29a0a4f2011-07-20 23:44:10 -030014#define MT2063_SPUR_PRESENT_ERR (0x00800000)
Mauro Carvalho Chehab6d3d7482011-07-20 22:21:26 -030015
16/* Info: Mask of bits used for # of LO-related spurs that were avoided during tuning */
17#define MT2063_SPUR_CNT_MASK (0x001f0000)
18#define MT2063_SPUR_SHIFT (16)
19
Mauro Carvalho Chehab6d3d7482011-07-20 22:21:26 -030020/* Info: Upconverter frequency is out of range (may be reason for MT_UPC_UNLOCK) */
21#define MT2063_UPC_RANGE (0x04000000)
22
23/* Info: Downconverter frequency is out of range (may be reason for MT_DPC_UNLOCK) */
24#define MT2063_DNC_RANGE (0x08000000)
25
Mauro Carvalho Chehab6d3d7482011-07-20 22:21:26 -030026/*
27 * Constant defining the version of the following structure
28 * and therefore the API for this code.
29 *
30 * When compiling the tuner driver, the preprocessor will
31 * check against this version number to make sure that
32 * it matches the version that the tuner driver knows about.
33 */
Mauro Carvalho Chehab6d3d7482011-07-20 22:21:26 -030034
35/* DECT Frequency Avoidance */
36#define MT2063_DECT_AVOID_US_FREQS 0x00000001
37
38#define MT2063_DECT_AVOID_EURO_FREQS 0x00000002
39
40#define MT2063_EXCLUDE_US_DECT_FREQUENCIES(s) (((s) & MT2063_DECT_AVOID_US_FREQS) != 0)
41
42#define MT2063_EXCLUDE_EURO_DECT_FREQUENCIES(s) (((s) & MT2063_DECT_AVOID_EURO_FREQS) != 0)
43
44enum MT2063_DECT_Avoid_Type {
45 MT2063_NO_DECT_AVOIDANCE = 0, /* Do not create DECT exclusion zones. */
46 MT2063_AVOID_US_DECT = MT2063_DECT_AVOID_US_FREQS, /* Avoid US DECT frequencies. */
47 MT2063_AVOID_EURO_DECT = MT2063_DECT_AVOID_EURO_FREQS, /* Avoid European DECT frequencies. */
48 MT2063_AVOID_BOTH /* Avoid both regions. Not typically used. */
49};
50
51#define MT2063_MAX_ZONES 48
52
Mauro Carvalho Chehab6d3d7482011-07-20 22:21:26 -030053struct MT2063_ExclZone_t {
54 u32 min_;
55 u32 max_;
56 struct MT2063_ExclZone_t *next_;
57};
58
59/*
60 * Structure of data needed for Spur Avoidance
61 */
62struct MT2063_AvoidSpursData_t {
Mauro Carvalho Chehab6d3d7482011-07-20 22:21:26 -030063 u32 f_ref;
64 u32 f_in;
65 u32 f_LO1;
66 u32 f_if1_Center;
67 u32 f_if1_Request;
68 u32 f_if1_bw;
69 u32 f_LO2;
70 u32 f_out;
71 u32 f_out_bw;
72 u32 f_LO1_Step;
73 u32 f_LO2_Step;
74 u32 f_LO1_FracN_Avoid;
75 u32 f_LO2_FracN_Avoid;
76 u32 f_zif_bw;
77 u32 f_min_LO_Separation;
78 u32 maxH1;
79 u32 maxH2;
80 enum MT2063_DECT_Avoid_Type avoidDECT;
81 u32 bSpurPresent;
82 u32 bSpurAvoided;
83 u32 nSpursFound;
84 u32 nZones;
85 struct MT2063_ExclZone_t *freeZones;
86 struct MT2063_ExclZone_t *usedZones;
87 struct MT2063_ExclZone_t MT2063_ExclZones[MT2063_MAX_ZONES];
88};
89
90/*
Mauro Carvalho Chehab6d3d7482011-07-20 22:21:26 -030091 * Parameter for function MT2063_SetPowerMask that specifies the power down
92 * of various sections of the MT2063.
93 */
94enum MT2063_Mask_Bits {
95 MT2063_REG_SD = 0x0040, /* Shutdown regulator */
96 MT2063_SRO_SD = 0x0020, /* Shutdown SRO */
97 MT2063_AFC_SD = 0x0010, /* Shutdown AFC A/D */
98 MT2063_PD_SD = 0x0002, /* Enable power detector shutdown */
99 MT2063_PDADC_SD = 0x0001, /* Enable power detector A/D shutdown */
100 MT2063_VCO_SD = 0x8000, /* Enable VCO shutdown */
101 MT2063_LTX_SD = 0x4000, /* Enable LTX shutdown */
102 MT2063_LT1_SD = 0x2000, /* Enable LT1 shutdown */
103 MT2063_LNA_SD = 0x1000, /* Enable LNA shutdown */
104 MT2063_UPC_SD = 0x0800, /* Enable upconverter shutdown */
105 MT2063_DNC_SD = 0x0400, /* Enable downconverter shutdown */
106 MT2063_VGA_SD = 0x0200, /* Enable VGA shutdown */
107 MT2063_AMP_SD = 0x0100, /* Enable AMP shutdown */
108 MT2063_ALL_SD = 0xFF73, /* All shutdown bits for this tuner */
109 MT2063_NONE_SD = 0x0000 /* No shutdown bits */
110};
111
112/*
113 * Parameter for function MT2063_GetParam & MT2063_SetParam that
114 * specifies the tuning algorithm parameter to be read/written.
115 */
116enum MT2063_Param {
Mauro Carvalho Chehab6d3d7482011-07-20 22:21:26 -0300117 /* min tuning step size (default: 50000 Hz) */
118 MT2063_STEPSIZE,
119
120 /* input center frequency set by MT2063_Tune() */
121 MT2063_INPUT_FREQ,
122
123 /* LO1 Frequency set by MT2063_Tune() */
124 MT2063_LO1_FREQ,
125
Mauro Carvalho Chehab6d3d7482011-07-20 22:21:26 -0300126 /* LO2 Frequency set by MT2063_Tune() */
127 MT2063_LO2_FREQ,
128
Mauro Carvalho Chehab6d3d7482011-07-20 22:21:26 -0300129 /* output center frequency set by MT2063_Tune() */
130 MT2063_OUTPUT_FREQ,
131
132 /* output bandwidth set by MT2063_Tune() */
133 MT2063_OUTPUT_BW,
134
Mauro Carvalho Chehab6d3d7482011-07-20 22:21:26 -0300135 /* Receiver Mode for some parameters. 1 is DVB-T */
136 MT2063_RCVR_MODE,
137
138 /* directly set LNA attenuation, parameter is value to set */
139 MT2063_ACLNA,
140
141 /* maximum LNA attenuation, parameter is value to set */
142 MT2063_ACLNA_MAX,
143
144 /* directly set ATN attenuation. Paremeter is value to set. */
145 MT2063_ACRF,
146
147 /* maxium ATN attenuation. Paremeter is value to set. */
148 MT2063_ACRF_MAX,
149
150 /* directly set FIF attenuation. Paremeter is value to set. */
151 MT2063_ACFIF,
152
153 /* maxium FIF attenuation. Paremeter is value to set. */
154 MT2063_ACFIF_MAX,
155
156 /* LNA Rin */
157 MT2063_LNA_RIN,
158
159 /* Power Detector LNA level target */
160 MT2063_LNA_TGT,
161
162 /* Power Detector 1 level */
163 MT2063_PD1,
164
165 /* Power Detector 1 level target */
166 MT2063_PD1_TGT,
167
168 /* Power Detector 2 level */
169 MT2063_PD2,
170
171 /* Power Detector 2 level target */
172 MT2063_PD2_TGT,
173
174 /* Selects, which DNC is activ */
175 MT2063_DNC_OUTPUT_ENABLE,
176
Mauro Carvalho Chehab6d3d7482011-07-20 22:21:26 -0300177 MT2063_EOP /* last entry in enumerated list */
178};
179
180/*
181 * Parameter for selecting tuner mode
182 */
183enum MT2063_RCVR_MODES {
184 MT2063_CABLE_QAM = 0, /* Digital cable */
185 MT2063_CABLE_ANALOG, /* Analog cable */
186 MT2063_OFFAIR_COFDM, /* Digital offair */
187 MT2063_OFFAIR_COFDM_SAWLESS, /* Digital offair without SAW */
188 MT2063_OFFAIR_ANALOG, /* Analog offair */
189 MT2063_OFFAIR_8VSB, /* Analog offair */
190 MT2063_NUM_RCVR_MODES
191};
192
193/*
194 * Possible values for MT2063_DNC_OUTPUT
195 */
196enum MT2063_DNC_Output_Enable {
197 MT2063_DNC_NONE = 0,
198 MT2063_DNC_1,
199 MT2063_DNC_2,
200 MT2063_DNC_BOTH
201};
202
203/*
204** Two-wire serial bus subaddresses of the tuner registers.
205** Also known as the tuner's register addresses.
206*/
207enum MT2063_Register_Offsets {
208 MT2063_REG_PART_REV = 0, /* 0x00: Part/Rev Code */
209 MT2063_REG_LO1CQ_1, /* 0x01: LO1C Queued Byte 1 */
210 MT2063_REG_LO1CQ_2, /* 0x02: LO1C Queued Byte 2 */
211 MT2063_REG_LO2CQ_1, /* 0x03: LO2C Queued Byte 1 */
212 MT2063_REG_LO2CQ_2, /* 0x04: LO2C Queued Byte 2 */
213 MT2063_REG_LO2CQ_3, /* 0x05: LO2C Queued Byte 3 */
214 MT2063_REG_RSVD_06, /* 0x06: Reserved */
215 MT2063_REG_LO_STATUS, /* 0x07: LO Status */
216 MT2063_REG_FIFFC, /* 0x08: FIFF Center */
217 MT2063_REG_CLEARTUNE, /* 0x09: ClearTune Filter */
218 MT2063_REG_ADC_OUT, /* 0x0A: ADC_OUT */
219 MT2063_REG_LO1C_1, /* 0x0B: LO1C Byte 1 */
220 MT2063_REG_LO1C_2, /* 0x0C: LO1C Byte 2 */
221 MT2063_REG_LO2C_1, /* 0x0D: LO2C Byte 1 */
222 MT2063_REG_LO2C_2, /* 0x0E: LO2C Byte 2 */
223 MT2063_REG_LO2C_3, /* 0x0F: LO2C Byte 3 */
224 MT2063_REG_RSVD_10, /* 0x10: Reserved */
225 MT2063_REG_PWR_1, /* 0x11: PWR Byte 1 */
226 MT2063_REG_PWR_2, /* 0x12: PWR Byte 2 */
227 MT2063_REG_TEMP_STATUS, /* 0x13: Temp Status */
228 MT2063_REG_XO_STATUS, /* 0x14: Crystal Status */
229 MT2063_REG_RF_STATUS, /* 0x15: RF Attn Status */
230 MT2063_REG_FIF_STATUS, /* 0x16: FIF Attn Status */
231 MT2063_REG_LNA_OV, /* 0x17: LNA Attn Override */
232 MT2063_REG_RF_OV, /* 0x18: RF Attn Override */
233 MT2063_REG_FIF_OV, /* 0x19: FIF Attn Override */
234 MT2063_REG_LNA_TGT, /* 0x1A: Reserved */
235 MT2063_REG_PD1_TGT, /* 0x1B: Pwr Det 1 Target */
236 MT2063_REG_PD2_TGT, /* 0x1C: Pwr Det 2 Target */
237 MT2063_REG_RSVD_1D, /* 0x1D: Reserved */
238 MT2063_REG_RSVD_1E, /* 0x1E: Reserved */
239 MT2063_REG_RSVD_1F, /* 0x1F: Reserved */
240 MT2063_REG_RSVD_20, /* 0x20: Reserved */
241 MT2063_REG_BYP_CTRL, /* 0x21: Bypass Control */
242 MT2063_REG_RSVD_22, /* 0x22: Reserved */
243 MT2063_REG_RSVD_23, /* 0x23: Reserved */
244 MT2063_REG_RSVD_24, /* 0x24: Reserved */
245 MT2063_REG_RSVD_25, /* 0x25: Reserved */
246 MT2063_REG_RSVD_26, /* 0x26: Reserved */
247 MT2063_REG_RSVD_27, /* 0x27: Reserved */
248 MT2063_REG_FIFF_CTRL, /* 0x28: FIFF Control */
249 MT2063_REG_FIFF_OFFSET, /* 0x29: FIFF Offset */
250 MT2063_REG_CTUNE_CTRL, /* 0x2A: Reserved */
251 MT2063_REG_CTUNE_OV, /* 0x2B: Reserved */
252 MT2063_REG_CTRL_2C, /* 0x2C: Reserved */
253 MT2063_REG_FIFF_CTRL2, /* 0x2D: Fiff Control */
254 MT2063_REG_RSVD_2E, /* 0x2E: Reserved */
255 MT2063_REG_DNC_GAIN, /* 0x2F: DNC Control */
256 MT2063_REG_VGA_GAIN, /* 0x30: VGA Gain Ctrl */
257 MT2063_REG_RSVD_31, /* 0x31: Reserved */
258 MT2063_REG_TEMP_SEL, /* 0x32: Temperature Selection */
259 MT2063_REG_RSVD_33, /* 0x33: Reserved */
260 MT2063_REG_RSVD_34, /* 0x34: Reserved */
261 MT2063_REG_RSVD_35, /* 0x35: Reserved */
262 MT2063_REG_RSVD_36, /* 0x36: Reserved */
263 MT2063_REG_RSVD_37, /* 0x37: Reserved */
264 MT2063_REG_RSVD_38, /* 0x38: Reserved */
265 MT2063_REG_RSVD_39, /* 0x39: Reserved */
266 MT2063_REG_RSVD_3A, /* 0x3A: Reserved */
267 MT2063_REG_RSVD_3B, /* 0x3B: Reserved */
268 MT2063_REG_RSVD_3C, /* 0x3C: Reserved */
269 MT2063_REG_END_REGS
270};
271
Mauro Carvalho Chehab6d3d7482011-07-20 22:21:26 -0300272enum MTTune_atv_standard {
273 MTTUNEA_UNKNOWN = 0,
274 MTTUNEA_PAL_B,
275 MTTUNEA_PAL_G,
276 MTTUNEA_PAL_I,
277 MTTUNEA_PAL_L,
278 MTTUNEA_PAL_MN,
279 MTTUNEA_PAL_DK,
280 MTTUNEA_DIGITAL,
281 MTTUNEA_FMRADIO,
282 MTTUNEA_DVBC,
283 MTTUNEA_DVBT
284};
285
286
287struct mt2063_state {
288 struct i2c_adapter *i2c;
289
290 const struct mt2063_config *config;
291 struct dvb_tuner_ops ops;
292 struct dvb_frontend *frontend;
293 struct tuner_state status;
Mauro Carvalho Chehab6d3d7482011-07-20 22:21:26 -0300294
295 enum MTTune_atv_standard tv_type;
296 u32 frequency;
297 u32 srate;
298 u32 bandwidth;
299 u32 reference;
Mauro Carvalho Chehab51f0f7b2011-07-21 02:24:18 -0300300
301 u32 tuner_id;
302 struct MT2063_AvoidSpursData_t AS_Data;
303 u32 f_IF1_actual;
304 u32 rcvr_mode;
305 u32 ctfilt_sw;
306 u32 CTFiltMax[31];
307 u32 num_regs;
308 u8 reg[MT2063_REG_END_REGS];
Mauro Carvalho Chehab6d3d7482011-07-20 22:21:26 -0300309};
Mauro Carvalho Chehab0ff48432011-07-20 20:21:42 -0300310
Mauro Carvalho Chehabbf975552011-07-20 21:43:30 -0300311/* Prototypes */
312static void MT2063_AddExclZone(struct MT2063_AvoidSpursData_t *pAS_Info,
313 u32 f_min, u32 f_max);
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -0300314static u32 MT2063_GetReg(struct mt2063_state *state, u8 reg, u8 * val);
315static u32 MT2063_GetParam(struct mt2063_state *state, enum MT2063_Param param, u32 * pValue);
316static u32 MT2063_SetReg(struct mt2063_state *state, u8 reg, u8 val);
317static u32 MT2063_SetParam(struct mt2063_state *state, enum MT2063_Param param,
Mauro Carvalho Chehab29a0a4f2011-07-20 23:44:10 -0300318 enum MT2063_DNC_Output_Enable nValue);
Mauro Carvalho Chehab8c64f932011-07-21 03:29:06 -0300319static u32 MT2063_SoftwareShutdown(struct mt2063_state *state, u8 Shutdown);
320static u32 MT2063_ClearPowerMaskBits(struct mt2063_state *state, enum MT2063_Mask_Bits Bits);
321
Mauro Carvalho Chehabbf975552011-07-20 21:43:30 -0300322
Mauro Carvalho Chehab0ff48432011-07-20 20:21:42 -0300323/*****************/
324/* From drivers/media/common/tuners/mt2063_cfg.h */
325
Mauro Carvalho Chehab0ff48432011-07-20 20:21:42 -0300326
Mauro Carvalho Chehabf8676952011-07-20 22:00:30 -0300327unsigned int tuner_MT2063_SoftwareShutdown(struct dvb_frontend *fe)
Mauro Carvalho Chehab0ff48432011-07-20 20:21:42 -0300328{
Mauro Carvalho Chehab8c64f932011-07-21 03:29:06 -0300329 struct mt2063_state *state = fe->tuner_priv;
Mauro Carvalho Chehab0ff48432011-07-20 20:21:42 -0300330 struct dvb_frontend_ops *frontend_ops = &fe->ops;
331 struct dvb_tuner_ops *tuner_ops = &frontend_ops->tuner_ops;
Mauro Carvalho Chehab0ff48432011-07-20 20:21:42 -0300332 int err = 0;
333
334 if (&fe->ops)
335 frontend_ops = &fe->ops;
336 if (&frontend_ops->tuner_ops)
337 tuner_ops = &frontend_ops->tuner_ops;
338 if (tuner_ops->set_state) {
Mauro Carvalho Chehab8c64f932011-07-21 03:29:06 -0300339 err = MT2063_SoftwareShutdown(state, 1);
340 if (err < 0) {
Mauro Carvalho Chehab0ff48432011-07-20 20:21:42 -0300341 printk("%s: Invalid parameter\n", __func__);
342 return err;
343 }
344 }
345
346 return err;
347}
348
Mauro Carvalho Chehabf8676952011-07-20 22:00:30 -0300349unsigned int tuner_MT2063_ClearPowerMaskBits(struct dvb_frontend *fe)
Mauro Carvalho Chehab0ff48432011-07-20 20:21:42 -0300350{
Mauro Carvalho Chehab8c64f932011-07-21 03:29:06 -0300351 struct mt2063_state *state = fe->tuner_priv;
Mauro Carvalho Chehab0ff48432011-07-20 20:21:42 -0300352 struct dvb_frontend_ops *frontend_ops = &fe->ops;
353 struct dvb_tuner_ops *tuner_ops = &frontend_ops->tuner_ops;
Mauro Carvalho Chehab0ff48432011-07-20 20:21:42 -0300354 int err = 0;
355
356 if (&fe->ops)
357 frontend_ops = &fe->ops;
358 if (&frontend_ops->tuner_ops)
359 tuner_ops = &frontend_ops->tuner_ops;
360 if (tuner_ops->set_state) {
Mauro Carvalho Chehab8c64f932011-07-21 03:29:06 -0300361 err = MT2063_ClearPowerMaskBits(state, MT2063_ALL_SD);
362 if (err < 0) {
Mauro Carvalho Chehab0ff48432011-07-20 20:21:42 -0300363 printk("%s: Invalid parameter\n", __func__);
364 return err;
365 }
366 }
367
368 return err;
369}
370
Mauro Carvalho Chehabe1de3d12011-07-21 02:46:49 -0300371/*
372 * mt2063_write - Write data into the I2C bus
373 */
374static u32 mt2063_write(struct mt2063_state *state,
375 u8 reg, u8 *data, u32 len)
Mauro Carvalho Chehab223c7b02011-07-20 19:48:59 -0300376{
Mauro Carvalho Chehabe1de3d12011-07-21 02:46:49 -0300377 struct dvb_frontend *fe = state->frontend;
Mauro Carvalho Chehab223c7b02011-07-20 19:48:59 -0300378 int ret;
Mauro Carvalho Chehabe1de3d12011-07-21 02:46:49 -0300379 u8 buf[60];
Mauro Carvalho Chehab223c7b02011-07-20 19:48:59 -0300380 struct i2c_msg msg = {
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -0300381 .addr = state->config->tuner_address,
382 .flags = 0,
383 .buf = buf,
384 .len = len + 1
Mauro Carvalho Chehab223c7b02011-07-20 19:48:59 -0300385 };
386
Mauro Carvalho Chehabe1de3d12011-07-21 02:46:49 -0300387 msg.buf[0] = reg;
Mauro Carvalho Chehab223c7b02011-07-20 19:48:59 -0300388 memcpy(msg.buf + 1, data, len);
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -0300389
Mauro Carvalho Chehabe1de3d12011-07-21 02:46:49 -0300390 fe->ops.i2c_gate_ctrl(fe, 1);
Mauro Carvalho Chehab223c7b02011-07-20 19:48:59 -0300391 ret = i2c_transfer(state->i2c, &msg, 1);
Mauro Carvalho Chehabe1de3d12011-07-21 02:46:49 -0300392 fe->ops.i2c_gate_ctrl(fe, 0);
Mauro Carvalho Chehab223c7b02011-07-20 19:48:59 -0300393
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -0300394 if (ret < 0)
395 printk("mt2063_writeregs error ret=%d\n", ret);
Mauro Carvalho Chehab223c7b02011-07-20 19:48:59 -0300396
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -0300397 return ret;
398}
399
Mauro Carvalho Chehabe1de3d12011-07-21 02:46:49 -0300400/*
401 * mt2063_read - Read data from the I2C bus
402 */
403static u32 mt2063_read(struct mt2063_state *state,
Mauro Carvalho Chehab51f0f7b2011-07-21 02:24:18 -0300404 u8 subAddress, u8 *pData, u32 cnt)
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -0300405{
Mauro Carvalho Chehab51f0f7b2011-07-21 02:24:18 -0300406 u32 status = 0; /* Status to be returned */
407 struct dvb_frontend *fe = state->frontend;
408 u32 i = 0;
409
Mauro Carvalho Chehabe1de3d12011-07-21 02:46:49 -0300410 fe->ops.i2c_gate_ctrl(fe, 1);
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -0300411
412 for (i = 0; i < cnt; i++) {
Mauro Carvalho Chehabe1de3d12011-07-21 02:46:49 -0300413 int ret;
414 u8 b0[] = { subAddress + i };
415 struct i2c_msg msg[] = {
416 {
417 .addr = state->config->tuner_address,
418 .flags = I2C_M_RD,
419 .buf = b0,
420 .len = 1
421 }, {
422 .addr = state->config->tuner_address,
423 .flags = I2C_M_RD,
424 .buf = pData + 1,
425 .len = 1
426 }
427 };
428
429 ret = i2c_transfer(state->i2c, msg, 2);
430 if (ret < 0)
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -0300431 break;
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -0300432 }
Mauro Carvalho Chehabe1de3d12011-07-21 02:46:49 -0300433 fe->ops.i2c_gate_ctrl(fe, 0);
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -0300434 return (status);
435}
436
Mauro Carvalho Chehabe930b3a2011-07-21 03:02:16 -0300437/*
438 * FIXME: Is this really needed?
439 */
Mauro Carvalho Chehabf8676952011-07-20 22:00:30 -0300440static int MT2063_Sleep(struct dvb_frontend *fe)
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -0300441{
442 /*
443 ** ToDo: Add code here to implement a OS blocking
444 ** for a period of "nMinDelayTime" milliseconds.
445 */
Mauro Carvalho Chehabf8676952011-07-20 22:00:30 -0300446 msleep(10);
447
448 return 0;
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -0300449}
450
Mauro Carvalho Chehabe930b3a2011-07-21 03:02:16 -0300451/*
452 * Microtune spur avoidance
453 */
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -0300454
455/* Implement ceiling, floor functions. */
456#define ceil(n, d) (((n) < 0) ? (-((-(n))/(d))) : (n)/(d) + ((n)%(d) != 0))
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -0300457#define floor(n, d) (((n) < 0) ? (-((-(n))/(d))) - ((n)%(d) != 0) : (n)/(d))
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -0300458
459struct MT2063_FIFZone_t {
Mauro Carvalho Chehabcfde8922011-07-20 21:01:48 -0300460 s32 min_;
461 s32 max_;
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -0300462};
463
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -0300464/*
465** Reset all exclusion zones.
466** Add zones to protect the PLL FracN regions near zero
467**
468** N/A I 06-17-2008 RSK Ver 1.19: Refactoring avoidance of DECT
469** frequencies into MT_ResetExclZones().
470*/
Mauro Carvalho Chehabbf975552011-07-20 21:43:30 -0300471static void MT2063_ResetExclZones(struct MT2063_AvoidSpursData_t *pAS_Info)
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -0300472{
Mauro Carvalho Chehabcfde8922011-07-20 21:01:48 -0300473 u32 center;
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -0300474
475 pAS_Info->nZones = 0; /* this clears the used list */
476 pAS_Info->usedZones = NULL; /* reset ptr */
477 pAS_Info->freeZones = NULL; /* reset ptr */
478
479 center =
480 pAS_Info->f_ref *
481 ((pAS_Info->f_if1_Center - pAS_Info->f_if1_bw / 2 +
482 pAS_Info->f_in) / pAS_Info->f_ref) - pAS_Info->f_in;
483 while (center <
484 pAS_Info->f_if1_Center + pAS_Info->f_if1_bw / 2 +
485 pAS_Info->f_LO1_FracN_Avoid) {
486 /* Exclude LO1 FracN */
487 MT2063_AddExclZone(pAS_Info,
488 center - pAS_Info->f_LO1_FracN_Avoid,
489 center - 1);
490 MT2063_AddExclZone(pAS_Info, center + 1,
491 center + pAS_Info->f_LO1_FracN_Avoid);
492 center += pAS_Info->f_ref;
493 }
494
495 center =
496 pAS_Info->f_ref *
497 ((pAS_Info->f_if1_Center - pAS_Info->f_if1_bw / 2 -
498 pAS_Info->f_out) / pAS_Info->f_ref) + pAS_Info->f_out;
499 while (center <
500 pAS_Info->f_if1_Center + pAS_Info->f_if1_bw / 2 +
501 pAS_Info->f_LO2_FracN_Avoid) {
502 /* Exclude LO2 FracN */
503 MT2063_AddExclZone(pAS_Info,
504 center - pAS_Info->f_LO2_FracN_Avoid,
505 center - 1);
506 MT2063_AddExclZone(pAS_Info, center + 1,
507 center + pAS_Info->f_LO2_FracN_Avoid);
508 center += pAS_Info->f_ref;
509 }
510
511 if (MT2063_EXCLUDE_US_DECT_FREQUENCIES(pAS_Info->avoidDECT)) {
512 /* Exclude LO1 values that conflict with DECT channels */
513 MT2063_AddExclZone(pAS_Info, 1920836000 - pAS_Info->f_in, 1922236000 - pAS_Info->f_in); /* Ctr = 1921.536 */
514 MT2063_AddExclZone(pAS_Info, 1922564000 - pAS_Info->f_in, 1923964000 - pAS_Info->f_in); /* Ctr = 1923.264 */
515 MT2063_AddExclZone(pAS_Info, 1924292000 - pAS_Info->f_in, 1925692000 - pAS_Info->f_in); /* Ctr = 1924.992 */
516 MT2063_AddExclZone(pAS_Info, 1926020000 - pAS_Info->f_in, 1927420000 - pAS_Info->f_in); /* Ctr = 1926.720 */
517 MT2063_AddExclZone(pAS_Info, 1927748000 - pAS_Info->f_in, 1929148000 - pAS_Info->f_in); /* Ctr = 1928.448 */
518 }
519
520 if (MT2063_EXCLUDE_EURO_DECT_FREQUENCIES(pAS_Info->avoidDECT)) {
521 MT2063_AddExclZone(pAS_Info, 1896644000 - pAS_Info->f_in, 1898044000 - pAS_Info->f_in); /* Ctr = 1897.344 */
522 MT2063_AddExclZone(pAS_Info, 1894916000 - pAS_Info->f_in, 1896316000 - pAS_Info->f_in); /* Ctr = 1895.616 */
523 MT2063_AddExclZone(pAS_Info, 1893188000 - pAS_Info->f_in, 1894588000 - pAS_Info->f_in); /* Ctr = 1893.888 */
524 MT2063_AddExclZone(pAS_Info, 1891460000 - pAS_Info->f_in, 1892860000 - pAS_Info->f_in); /* Ctr = 1892.16 */
525 MT2063_AddExclZone(pAS_Info, 1889732000 - pAS_Info->f_in, 1891132000 - pAS_Info->f_in); /* Ctr = 1890.432 */
526 MT2063_AddExclZone(pAS_Info, 1888004000 - pAS_Info->f_in, 1889404000 - pAS_Info->f_in); /* Ctr = 1888.704 */
527 MT2063_AddExclZone(pAS_Info, 1886276000 - pAS_Info->f_in, 1887676000 - pAS_Info->f_in); /* Ctr = 1886.976 */
528 MT2063_AddExclZone(pAS_Info, 1884548000 - pAS_Info->f_in, 1885948000 - pAS_Info->f_in); /* Ctr = 1885.248 */
529 MT2063_AddExclZone(pAS_Info, 1882820000 - pAS_Info->f_in, 1884220000 - pAS_Info->f_in); /* Ctr = 1883.52 */
530 MT2063_AddExclZone(pAS_Info, 1881092000 - pAS_Info->f_in, 1882492000 - pAS_Info->f_in); /* Ctr = 1881.792 */
531 }
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -0300532}
533
534static struct MT2063_ExclZone_t *InsertNode(struct MT2063_AvoidSpursData_t
535 *pAS_Info,
536 struct MT2063_ExclZone_t *pPrevNode)
537{
538 struct MT2063_ExclZone_t *pNode;
539 /* Check for a node in the free list */
540 if (pAS_Info->freeZones != NULL) {
541 /* Use one from the free list */
542 pNode = pAS_Info->freeZones;
543 pAS_Info->freeZones = pNode->next_;
544 } else {
545 /* Grab a node from the array */
546 pNode = &pAS_Info->MT2063_ExclZones[pAS_Info->nZones];
547 }
548
549 if (pPrevNode != NULL) {
550 pNode->next_ = pPrevNode->next_;
551 pPrevNode->next_ = pNode;
552 } else { /* insert at the beginning of the list */
553
554 pNode->next_ = pAS_Info->usedZones;
555 pAS_Info->usedZones = pNode;
556 }
557
558 pAS_Info->nZones++;
559 return pNode;
560}
561
562static struct MT2063_ExclZone_t *RemoveNode(struct MT2063_AvoidSpursData_t
563 *pAS_Info,
564 struct MT2063_ExclZone_t *pPrevNode,
565 struct MT2063_ExclZone_t
566 *pNodeToRemove)
567{
568 struct MT2063_ExclZone_t *pNext = pNodeToRemove->next_;
569
570 /* Make previous node point to the subsequent node */
571 if (pPrevNode != NULL)
572 pPrevNode->next_ = pNext;
573
574 /* Add pNodeToRemove to the beginning of the freeZones */
575 pNodeToRemove->next_ = pAS_Info->freeZones;
576 pAS_Info->freeZones = pNodeToRemove;
577
578 /* Decrement node count */
579 pAS_Info->nZones--;
580
581 return pNext;
582}
583
584/*****************************************************************************
585**
586** Name: MT_AddExclZone
587**
588** Description: Add (and merge) an exclusion zone into the list.
589** If the range (f_min, f_max) is totally outside the
590** 1st IF BW, ignore the entry.
591** If the range (f_min, f_max) is negative, ignore the entry.
592**
593** Revision History:
594**
595** SCR Date Author Description
596** -------------------------------------------------------------------------
597** 103 01-31-2005 DAD Ver 1.14: In MT_AddExclZone(), if the range
598** (f_min, f_max) < 0, ignore the entry.
599**
600*****************************************************************************/
Mauro Carvalho Chehabbf975552011-07-20 21:43:30 -0300601static void MT2063_AddExclZone(struct MT2063_AvoidSpursData_t *pAS_Info,
Mauro Carvalho Chehabcfde8922011-07-20 21:01:48 -0300602 u32 f_min, u32 f_max)
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -0300603{
604 struct MT2063_ExclZone_t *pNode = pAS_Info->usedZones;
605 struct MT2063_ExclZone_t *pPrev = NULL;
606 struct MT2063_ExclZone_t *pNext = NULL;
607
608 /* Check to see if this overlaps the 1st IF filter */
609 if ((f_max > (pAS_Info->f_if1_Center - (pAS_Info->f_if1_bw / 2)))
610 && (f_min < (pAS_Info->f_if1_Center + (pAS_Info->f_if1_bw / 2)))
611 && (f_min < f_max)) {
612 /*
613 ** 1 2 3 4 5 6
614 **
615 ** New entry: |---| |--| |--| |-| |---| |--|
616 ** or or or or or
617 ** Existing: |--| |--| |--| |---| |-| |--|
618 */
619
620 /* Check for our place in the list */
621 while ((pNode != NULL) && (pNode->max_ < f_min)) {
622 pPrev = pNode;
623 pNode = pNode->next_;
624 }
625
626 if ((pNode != NULL) && (pNode->min_ < f_max)) {
627 /* Combine me with pNode */
628 if (f_min < pNode->min_)
629 pNode->min_ = f_min;
630 if (f_max > pNode->max_)
631 pNode->max_ = f_max;
632 } else {
633 pNode = InsertNode(pAS_Info, pPrev);
634 pNode->min_ = f_min;
635 pNode->max_ = f_max;
636 }
637
638 /* Look for merging possibilities */
639 pNext = pNode->next_;
640 while ((pNext != NULL) && (pNext->min_ < pNode->max_)) {
641 if (pNext->max_ > pNode->max_)
642 pNode->max_ = pNext->max_;
643 pNext = RemoveNode(pAS_Info, pNode, pNext); /* Remove pNext, return ptr to pNext->next */
644 }
645 }
646}
647
648/*****************************************************************************
649**
650** Name: MT_ChooseFirstIF
651**
652** Description: Choose the best available 1st IF
653** If f_Desired is not excluded, choose that first.
654** Otherwise, return the value closest to f_Center that is
655** not excluded
656**
657** Revision History:
658**
659** SCR Date Author Description
660** -------------------------------------------------------------------------
661** 117 03-29-2007 RSK Ver 1.15: Re-wrote to match search order from
662** tuner DLL.
663** 147 07-27-2007 RSK Ver 1.17: Corrected calculation (-) to (+)
664** Added logic to force f_Center within 1/2 f_Step.
665**
666*****************************************************************************/
Mauro Carvalho Chehabbf975552011-07-20 21:43:30 -0300667static u32 MT2063_ChooseFirstIF(struct MT2063_AvoidSpursData_t *pAS_Info)
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -0300668{
669 /*
670 ** Update "f_Desired" to be the nearest "combinational-multiple" of "f_LO1_Step".
671 ** The resulting number, F_LO1 must be a multiple of f_LO1_Step. And F_LO1 is the arithmetic sum
672 ** of f_in + f_Center. Neither f_in, nor f_Center must be a multiple of f_LO1_Step.
673 ** However, the sum must be.
674 */
Mauro Carvalho Chehabcfde8922011-07-20 21:01:48 -0300675 const u32 f_Desired =
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -0300676 pAS_Info->f_LO1_Step *
677 ((pAS_Info->f_if1_Request + pAS_Info->f_in +
678 pAS_Info->f_LO1_Step / 2) / pAS_Info->f_LO1_Step) -
679 pAS_Info->f_in;
Mauro Carvalho Chehabcfde8922011-07-20 21:01:48 -0300680 const u32 f_Step =
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -0300681 (pAS_Info->f_LO1_Step >
682 pAS_Info->f_LO2_Step) ? pAS_Info->f_LO1_Step : pAS_Info->
683 f_LO2_Step;
Mauro Carvalho Chehabcfde8922011-07-20 21:01:48 -0300684 u32 f_Center;
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -0300685
Mauro Carvalho Chehabcfde8922011-07-20 21:01:48 -0300686 s32 i;
687 s32 j = 0;
688 u32 bDesiredExcluded = 0;
689 u32 bZeroExcluded = 0;
690 s32 tmpMin, tmpMax;
691 s32 bestDiff;
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -0300692 struct MT2063_ExclZone_t *pNode = pAS_Info->usedZones;
693 struct MT2063_FIFZone_t zones[MT2063_MAX_ZONES];
694
695 if (pAS_Info->nZones == 0)
696 return f_Desired;
697
698 /* f_Center needs to be an integer multiple of f_Step away from f_Desired */
699 if (pAS_Info->f_if1_Center > f_Desired)
700 f_Center =
701 f_Desired +
702 f_Step *
703 ((pAS_Info->f_if1_Center - f_Desired +
704 f_Step / 2) / f_Step);
705 else
706 f_Center =
707 f_Desired -
708 f_Step *
709 ((f_Desired - pAS_Info->f_if1_Center +
710 f_Step / 2) / f_Step);
711
712 //assert;
Mauro Carvalho Chehabcfde8922011-07-20 21:01:48 -0300713 //if (!abs((s32) f_Center - (s32) pAS_Info->f_if1_Center) <= (s32) (f_Step/2))
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -0300714 // return 0;
715
716 /* Take MT_ExclZones, center around f_Center and change the resolution to f_Step */
717 while (pNode != NULL) {
718 /* floor function */
719 tmpMin =
Mauro Carvalho Chehabcfde8922011-07-20 21:01:48 -0300720 floor((s32) (pNode->min_ - f_Center), (s32) f_Step);
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -0300721
722 /* ceil function */
723 tmpMax =
Mauro Carvalho Chehabcfde8922011-07-20 21:01:48 -0300724 ceil((s32) (pNode->max_ - f_Center), (s32) f_Step);
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -0300725
726 if ((pNode->min_ < f_Desired) && (pNode->max_ > f_Desired))
727 bDesiredExcluded = 1;
728
729 if ((tmpMin < 0) && (tmpMax > 0))
730 bZeroExcluded = 1;
731
732 /* See if this zone overlaps the previous */
733 if ((j > 0) && (tmpMin < zones[j - 1].max_))
734 zones[j - 1].max_ = tmpMax;
735 else {
736 /* Add new zone */
737 //assert(j<MT2063_MAX_ZONES);
738 //if (j>=MT2063_MAX_ZONES)
739 //break;
740
741 zones[j].min_ = tmpMin;
742 zones[j].max_ = tmpMax;
743 j++;
744 }
745 pNode = pNode->next_;
746 }
747
748 /*
749 ** If the desired is okay, return with it
750 */
751 if (bDesiredExcluded == 0)
752 return f_Desired;
753
754 /*
755 ** If the desired is excluded and the center is okay, return with it
756 */
757 if (bZeroExcluded == 0)
758 return f_Center;
759
760 /* Find the value closest to 0 (f_Center) */
761 bestDiff = zones[0].min_;
762 for (i = 0; i < j; i++) {
763 if (abs(zones[i].min_) < abs(bestDiff))
764 bestDiff = zones[i].min_;
765 if (abs(zones[i].max_) < abs(bestDiff))
766 bestDiff = zones[i].max_;
767 }
768
769 if (bestDiff < 0)
Mauro Carvalho Chehabcfde8922011-07-20 21:01:48 -0300770 return f_Center - ((u32) (-bestDiff) * f_Step);
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -0300771
772 return f_Center + (bestDiff * f_Step);
773}
774
775/****************************************************************************
776**
777** Name: gcd
778**
779** Description: Uses Euclid's algorithm
780**
781** Parameters: u, v - unsigned values whose GCD is desired.
782**
783** Global: None
784**
785** Returns: greatest common divisor of u and v, if either value
786** is 0, the other value is returned as the result.
787**
788** Dependencies: None.
789**
790** Revision History:
791**
792** SCR Date Author Description
793** -------------------------------------------------------------------------
794** N/A 06-01-2004 JWS Original
795** N/A 08-03-2004 DAD Changed to Euclid's since it can handle
796** unsigned numbers.
797**
798****************************************************************************/
Mauro Carvalho Chehabcfde8922011-07-20 21:01:48 -0300799static u32 MT2063_gcd(u32 u, u32 v)
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -0300800{
Mauro Carvalho Chehabcfde8922011-07-20 21:01:48 -0300801 u32 r;
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -0300802
803 while (v != 0) {
804 r = u % v;
805 u = v;
806 v = r;
807 }
808
809 return u;
810}
811
812/****************************************************************************
813**
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -0300814** Name: IsSpurInBand
815**
816** Description: Checks to see if a spur will be present within the IF's
817** bandwidth. (fIFOut +/- fIFBW, -fIFOut +/- fIFBW)
818**
819** ma mb mc md
820** <--+-+-+-------------------+-------------------+-+-+-->
821** | ^ 0 ^ |
822** ^ b=-fIFOut+fIFBW/2 -b=+fIFOut-fIFBW/2 ^
823** a=-fIFOut-fIFBW/2 -a=+fIFOut+fIFBW/2
824**
825** Note that some equations are doubled to prevent round-off
826** problems when calculating fIFBW/2
827**
828** Parameters: pAS_Info - Avoid Spurs information block
829** fm - If spur, amount f_IF1 has to move negative
830** fp - If spur, amount f_IF1 has to move positive
831**
832** Global: None
833**
834** Returns: 1 if an LO spur would be present, otherwise 0.
835**
836** Dependencies: None.
837**
838** Revision History:
839**
840** SCR Date Author Description
841** -------------------------------------------------------------------------
842** N/A 11-28-2002 DAD Implemented algorithm from applied patent
843**
844****************************************************************************/
Mauro Carvalho Chehabcfde8922011-07-20 21:01:48 -0300845static u32 IsSpurInBand(struct MT2063_AvoidSpursData_t *pAS_Info,
846 u32 * fm, u32 * fp)
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -0300847{
848 /*
849 ** Calculate LO frequency settings.
850 */
Mauro Carvalho Chehabcfde8922011-07-20 21:01:48 -0300851 u32 n, n0;
852 const u32 f_LO1 = pAS_Info->f_LO1;
853 const u32 f_LO2 = pAS_Info->f_LO2;
854 const u32 d = pAS_Info->f_out + pAS_Info->f_out_bw / 2;
855 const u32 c = d - pAS_Info->f_out_bw;
856 const u32 f = pAS_Info->f_zif_bw / 2;
Mauro Carvalho Chehabd0dcc2d2011-07-21 02:30:19 -0300857 const u32 f_Scale = (f_LO1 / (UINT_MAX / 2 / pAS_Info->maxH1)) + 1;
Mauro Carvalho Chehabcfde8922011-07-20 21:01:48 -0300858 s32 f_nsLO1, f_nsLO2;
859 s32 f_Spur;
860 u32 ma, mb, mc, md, me, mf;
861 u32 lo_gcd, gd_Scale, gc_Scale, gf_Scale, hgds, hgfs, hgcs;
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -0300862 *fm = 0;
863
864 /*
865 ** For each edge (d, c & f), calculate a scale, based on the gcd
866 ** of f_LO1, f_LO2 and the edge value. Use the larger of this
867 ** gcd-based scale factor or f_Scale.
868 */
869 lo_gcd = MT2063_gcd(f_LO1, f_LO2);
Mauro Carvalho Chehabfd1126c2011-07-21 03:30:57 -0300870 gd_Scale = max((u32) MT2063_gcd(lo_gcd, d), f_Scale);
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -0300871 hgds = gd_Scale / 2;
Mauro Carvalho Chehabfd1126c2011-07-21 03:30:57 -0300872 gc_Scale = max((u32) MT2063_gcd(lo_gcd, c), f_Scale);
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -0300873 hgcs = gc_Scale / 2;
Mauro Carvalho Chehabfd1126c2011-07-21 03:30:57 -0300874 gf_Scale = max((u32) MT2063_gcd(lo_gcd, f), f_Scale);
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -0300875 hgfs = gf_Scale / 2;
876
Mauro Carvalho Chehabe930b3a2011-07-21 03:02:16 -0300877 n0 = DIV_ROUND_UP(f_LO2 - d, f_LO1 - f_LO2);
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -0300878
879 /* Check out all multiples of LO1 from n0 to m_maxLOSpurHarmonic */
880 for (n = n0; n <= pAS_Info->maxH1; ++n) {
881 md = (n * ((f_LO1 + hgds) / gd_Scale) -
882 ((d + hgds) / gd_Scale)) / ((f_LO2 + hgds) / gd_Scale);
883
884 /* If # fLO2 harmonics > m_maxLOSpurHarmonic, then no spurs present */
885 if (md >= pAS_Info->maxH1)
886 break;
887
888 ma = (n * ((f_LO1 + hgds) / gd_Scale) +
889 ((d + hgds) / gd_Scale)) / ((f_LO2 + hgds) / gd_Scale);
890
891 /* If no spurs between +/- (f_out + f_IFBW/2), then try next harmonic */
892 if (md == ma)
893 continue;
894
895 mc = (n * ((f_LO1 + hgcs) / gc_Scale) -
896 ((c + hgcs) / gc_Scale)) / ((f_LO2 + hgcs) / gc_Scale);
897 if (mc != md) {
Mauro Carvalho Chehabcfde8922011-07-20 21:01:48 -0300898 f_nsLO1 = (s32) (n * (f_LO1 / gc_Scale));
899 f_nsLO2 = (s32) (mc * (f_LO2 / gc_Scale));
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -0300900 f_Spur =
901 (gc_Scale * (f_nsLO1 - f_nsLO2)) +
902 n * (f_LO1 % gc_Scale) - mc * (f_LO2 % gc_Scale);
903
Mauro Carvalho Chehabcfde8922011-07-20 21:01:48 -0300904 *fp = ((f_Spur - (s32) c) / (mc - n)) + 1;
905 *fm = (((s32) d - f_Spur) / (mc - n)) + 1;
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -0300906 return 1;
907 }
908
909 /* Location of Zero-IF-spur to be checked */
910 me = (n * ((f_LO1 + hgfs) / gf_Scale) +
911 ((f + hgfs) / gf_Scale)) / ((f_LO2 + hgfs) / gf_Scale);
912 mf = (n * ((f_LO1 + hgfs) / gf_Scale) -
913 ((f + hgfs) / gf_Scale)) / ((f_LO2 + hgfs) / gf_Scale);
914 if (me != mf) {
915 f_nsLO1 = n * (f_LO1 / gf_Scale);
916 f_nsLO2 = me * (f_LO2 / gf_Scale);
917 f_Spur =
918 (gf_Scale * (f_nsLO1 - f_nsLO2)) +
919 n * (f_LO1 % gf_Scale) - me * (f_LO2 % gf_Scale);
920
Mauro Carvalho Chehabcfde8922011-07-20 21:01:48 -0300921 *fp = ((f_Spur + (s32) f) / (me - n)) + 1;
922 *fm = (((s32) f - f_Spur) / (me - n)) + 1;
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -0300923 return 1;
924 }
925
926 mb = (n * ((f_LO1 + hgcs) / gc_Scale) +
927 ((c + hgcs) / gc_Scale)) / ((f_LO2 + hgcs) / gc_Scale);
928 if (ma != mb) {
929 f_nsLO1 = n * (f_LO1 / gc_Scale);
930 f_nsLO2 = ma * (f_LO2 / gc_Scale);
931 f_Spur =
932 (gc_Scale * (f_nsLO1 - f_nsLO2)) +
933 n * (f_LO1 % gc_Scale) - ma * (f_LO2 % gc_Scale);
934
Mauro Carvalho Chehabcfde8922011-07-20 21:01:48 -0300935 *fp = (((s32) d + f_Spur) / (ma - n)) + 1;
936 *fm = (-(f_Spur + (s32) c) / (ma - n)) + 1;
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -0300937 return 1;
938 }
939 }
940
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -0300941 /* No spurs found */
Mauro Carvalho Chehab223c7b02011-07-20 19:48:59 -0300942 return 0;
943}
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -0300944
945/*****************************************************************************
946**
947** Name: MT_AvoidSpurs
948**
949** Description: Main entry point to avoid spurs.
950** Checks for existing spurs in present LO1, LO2 freqs
951** and if present, chooses spur-free LO1, LO2 combination
952** that tunes the same input/output frequencies.
953**
954** Revision History:
955**
956** SCR Date Author Description
957** -------------------------------------------------------------------------
958** 096 04-06-2005 DAD Ver 1.11: Fix divide by 0 error if maxH==0.
959**
960*****************************************************************************/
Mauro Carvalho Chehabbf975552011-07-20 21:43:30 -0300961static u32 MT2063_AvoidSpurs(void *h, struct MT2063_AvoidSpursData_t * pAS_Info)
Mauro Carvalho Chehab223c7b02011-07-20 19:48:59 -0300962{
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -0300963 u32 status = 0;
Mauro Carvalho Chehabcfde8922011-07-20 21:01:48 -0300964 u32 fm, fp; /* restricted range on LO's */
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -0300965 pAS_Info->bSpurAvoided = 0;
966 pAS_Info->nSpursFound = 0;
967
968 if (pAS_Info->maxH1 == 0)
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -0300969 return 0;
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -0300970
971 /*
972 ** Avoid LO Generated Spurs
973 **
974 ** Make sure that have no LO-related spurs within the IF output
975 ** bandwidth.
976 **
977 ** If there is an LO spur in this band, start at the current IF1 frequency
978 ** and work out until we find a spur-free frequency or run up against the
979 ** 1st IF SAW band edge. Use temporary copies of fLO1 and fLO2 so that they
980 ** will be unchanged if a spur-free setting is not found.
981 */
982 pAS_Info->bSpurPresent = IsSpurInBand(pAS_Info, &fm, &fp);
983 if (pAS_Info->bSpurPresent) {
Mauro Carvalho Chehabcfde8922011-07-20 21:01:48 -0300984 u32 zfIF1 = pAS_Info->f_LO1 - pAS_Info->f_in; /* current attempt at a 1st IF */
985 u32 zfLO1 = pAS_Info->f_LO1; /* current attempt at an LO1 freq */
986 u32 zfLO2 = pAS_Info->f_LO2; /* current attempt at an LO2 freq */
987 u32 delta_IF1;
988 u32 new_IF1;
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -0300989
990 /*
991 ** Spur was found, attempt to find a spur-free 1st IF
992 */
993 do {
994 pAS_Info->nSpursFound++;
995
996 /* Raise f_IF1_upper, if needed */
997 MT2063_AddExclZone(pAS_Info, zfIF1 - fm, zfIF1 + fp);
998
999 /* Choose next IF1 that is closest to f_IF1_CENTER */
1000 new_IF1 = MT2063_ChooseFirstIF(pAS_Info);
1001
1002 if (new_IF1 > zfIF1) {
1003 pAS_Info->f_LO1 += (new_IF1 - zfIF1);
1004 pAS_Info->f_LO2 += (new_IF1 - zfIF1);
1005 } else {
1006 pAS_Info->f_LO1 -= (zfIF1 - new_IF1);
1007 pAS_Info->f_LO2 -= (zfIF1 - new_IF1);
1008 }
1009 zfIF1 = new_IF1;
1010
1011 if (zfIF1 > pAS_Info->f_if1_Center)
1012 delta_IF1 = zfIF1 - pAS_Info->f_if1_Center;
1013 else
1014 delta_IF1 = pAS_Info->f_if1_Center - zfIF1;
1015 }
1016 /*
1017 ** Continue while the new 1st IF is still within the 1st IF bandwidth
1018 ** and there is a spur in the band (again)
1019 */
1020 while ((2 * delta_IF1 + pAS_Info->f_out_bw <=
1021 pAS_Info->f_if1_bw)
1022 && (pAS_Info->bSpurPresent =
1023 IsSpurInBand(pAS_Info, &fm, &fp)));
1024
1025 /*
1026 ** Use the LO-spur free values found. If the search went all the way to
1027 ** the 1st IF band edge and always found spurs, just leave the original
1028 ** choice. It's as "good" as any other.
1029 */
1030 if (pAS_Info->bSpurPresent == 1) {
1031 status |= MT2063_SPUR_PRESENT_ERR;
1032 pAS_Info->f_LO1 = zfLO1;
1033 pAS_Info->f_LO2 = zfLO2;
1034 } else
1035 pAS_Info->bSpurAvoided = 1;
1036 }
1037
1038 status |=
1039 ((pAS_Info->
1040 nSpursFound << MT2063_SPUR_SHIFT) & MT2063_SPUR_CNT_MASK);
1041
1042 return (status);
Mauro Carvalho Chehab223c7b02011-07-20 19:48:59 -03001043}
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03001044
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03001045/*
1046** The expected version of MT_AvoidSpursData_t
1047** If the version is different, an updated file is needed from Microtune
1048*/
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03001049
1050typedef enum {
1051 MT2063_SET_ATTEN,
1052 MT2063_INCR_ATTEN,
1053 MT2063_DECR_ATTEN
1054} MT2063_ATTEN_CNTL_MODE;
1055
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03001056/*
Mauro Carvalho Chehab66aea302011-07-21 03:57:10 -03001057 * Constants used by the tuning algorithm
1058 */
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03001059#define MT2063_REF_FREQ (16000000UL) /* Reference oscillator Frequency (in Hz) */
1060#define MT2063_IF1_BW (22000000UL) /* The IF1 filter bandwidth (in Hz) */
1061#define MT2063_TUNE_STEP_SIZE (50000UL) /* Tune in steps of 50 kHz */
1062#define MT2063_SPUR_STEP_HZ (250000UL) /* Step size (in Hz) to move IF1 when avoiding spurs */
1063#define MT2063_ZIF_BW (2000000UL) /* Zero-IF spur-free bandwidth (in Hz) */
1064#define MT2063_MAX_HARMONICS_1 (15UL) /* Highest intra-tuner LO Spur Harmonic to be avoided */
1065#define MT2063_MAX_HARMONICS_2 (5UL) /* Highest inter-tuner LO Spur Harmonic to be avoided */
1066#define MT2063_MIN_LO_SEP (1000000UL) /* Minimum inter-tuner LO frequency separation */
1067#define MT2063_LO1_FRACN_AVOID (0UL) /* LO1 FracN numerator avoid region (in Hz) */
1068#define MT2063_LO2_FRACN_AVOID (199999UL) /* LO2 FracN numerator avoid region (in Hz) */
1069#define MT2063_MIN_FIN_FREQ (44000000UL) /* Minimum input frequency (in Hz) */
1070#define MT2063_MAX_FIN_FREQ (1100000000UL) /* Maximum input frequency (in Hz) */
1071#define MT2063_MIN_FOUT_FREQ (36000000UL) /* Minimum output frequency (in Hz) */
1072#define MT2063_MAX_FOUT_FREQ (57000000UL) /* Maximum output frequency (in Hz) */
1073#define MT2063_MIN_DNC_FREQ (1293000000UL) /* Minimum LO2 frequency (in Hz) */
1074#define MT2063_MAX_DNC_FREQ (1614000000UL) /* Maximum LO2 frequency (in Hz) */
1075#define MT2063_MIN_UPC_FREQ (1396000000UL) /* Minimum LO1 frequency (in Hz) */
1076#define MT2063_MAX_UPC_FREQ (2750000000UL) /* Maximum LO1 frequency (in Hz) */
1077
1078/*
1079** Define the supported Part/Rev codes for the MT2063
1080*/
1081#define MT2063_B0 (0x9B)
1082#define MT2063_B1 (0x9C)
1083#define MT2063_B2 (0x9D)
1084#define MT2063_B3 (0x9E)
1085
1086/*
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03001087** Constants for setting receiver modes.
1088** (6 modes defined at this time, enumerated by MT2063_RCVR_MODES)
1089** (DNC1GC & DNC2GC are the values, which are used, when the specific
1090** DNC Output is selected, the other is always off)
1091**
1092** If PAL-L or L' is received, set:
1093** MT2063_SetParam(hMT2063,MT2063_TAGC,1);
1094**
1095** --------------+----------------------------------------------
1096** Mode 0 : | MT2063_CABLE_QAM
1097** Mode 1 : | MT2063_CABLE_ANALOG
1098** Mode 2 : | MT2063_OFFAIR_COFDM
1099** Mode 3 : | MT2063_OFFAIR_COFDM_SAWLESS
1100** Mode 4 : | MT2063_OFFAIR_ANALOG
1101** Mode 5 : | MT2063_OFFAIR_8VSB
1102** --------------+----+----+----+----+-----+-----+--------------
1103** Mode | 0 | 1 | 2 | 3 | 4 | 5 |
1104** --------------+----+----+----+----+-----+-----+
1105**
1106**
1107*/
Mauro Carvalho Chehabcfde8922011-07-20 21:01:48 -03001108static const u8 RFAGCEN[] = { 0, 0, 0, 0, 0, 0 };
1109static const u8 LNARIN[] = { 0, 0, 3, 3, 3, 3 };
1110static const u8 FIFFQEN[] = { 1, 1, 1, 1, 1, 1 };
1111static const u8 FIFFQ[] = { 0, 0, 0, 0, 0, 0 };
1112static const u8 DNC1GC[] = { 0, 0, 0, 0, 0, 0 };
1113static const u8 DNC2GC[] = { 0, 0, 0, 0, 0, 0 };
1114static const u8 ACLNAMAX[] = { 31, 31, 31, 31, 31, 31 };
1115static const u8 LNATGT[] = { 44, 43, 43, 43, 43, 43 };
1116static const u8 RFOVDIS[] = { 0, 0, 0, 0, 0, 0 };
1117static const u8 ACRFMAX[] = { 31, 31, 31, 31, 31, 31 };
1118static const u8 PD1TGT[] = { 36, 36, 38, 38, 36, 38 };
1119static const u8 FIFOVDIS[] = { 0, 0, 0, 0, 0, 0 };
1120static const u8 ACFIFMAX[] = { 29, 29, 29, 29, 29, 29 };
1121static const u8 PD2TGT[] = { 40, 33, 38, 42, 30, 38 };
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03001122
1123/*
1124** Local Function Prototypes - not available for external access.
1125*/
1126
1127/* Forward declaration(s): */
Mauro Carvalho Chehabcfde8922011-07-20 21:01:48 -03001128static u32 MT2063_CalcLO1Mult(u32 * Div, u32 * FracN, u32 f_LO,
1129 u32 f_LO_Step, u32 f_Ref);
1130static u32 MT2063_CalcLO2Mult(u32 * Div, u32 * FracN, u32 f_LO,
1131 u32 f_LO_Step, u32 f_Ref);
1132static u32 MT2063_fLO_FractionalTerm(u32 f_ref, u32 num,
1133 u32 denom);
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03001134
Mauro Carvalho Chehab31e67fa2011-07-21 10:30:11 -03001135/**
1136 * mt2063_lockStatus - Checks to see if LO1 and LO2 are locked
1137 *
1138 * @state: struct mt2063_state pointer
1139 *
1140 * This function returns 0, if no lock, 1 if locked and a value < 1 if error
1141 */
1142unsigned int mt2063_lockStatus(struct mt2063_state *state)
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03001143{
Mauro Carvalho Chehabcfde8922011-07-20 21:01:48 -03001144 const u32 nMaxWait = 100; /* wait a maximum of 100 msec */
1145 const u32 nPollRate = 2; /* poll status bits every 2 ms */
1146 const u32 nMaxLoops = nMaxWait / nPollRate;
1147 const u8 LO1LK = 0x80;
1148 u8 LO2LK = 0x08;
Mauro Carvalho Chehab31e67fa2011-07-21 10:30:11 -03001149 u32 status;
Mauro Carvalho Chehabcfde8922011-07-20 21:01:48 -03001150 u32 nDelays = 0;
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03001151
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03001152 /* LO2 Lock bit was in a different place for B0 version */
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03001153 if (state->tuner_id == MT2063_B0)
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03001154 LO2LK = 0x40;
1155
1156 do {
Mauro Carvalho Chehab31e67fa2011-07-21 10:30:11 -03001157 status = mt2063_read(state, MT2063_REG_LO_STATUS,
1158 &state->reg[MT2063_REG_LO_STATUS], 1);
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03001159
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03001160 if (status < 0)
Mauro Carvalho Chehab31e67fa2011-07-21 10:30:11 -03001161 return status;
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03001162
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03001163 if ((state->reg[MT2063_REG_LO_STATUS] & (LO1LK | LO2LK)) ==
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03001164 (LO1LK | LO2LK)) {
Mauro Carvalho Chehab31e67fa2011-07-21 10:30:11 -03001165 return TUNER_STATUS_LOCKED | TUNER_STATUS_STEREO;
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03001166 }
Mauro Carvalho Chehabbf975552011-07-20 21:43:30 -03001167 msleep(nPollRate); /* Wait between retries */
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03001168 }
1169 while (++nDelays < nMaxLoops);
1170
Mauro Carvalho Chehab31e67fa2011-07-21 10:30:11 -03001171 /*
1172 * Got no lock or partial lock
1173 */
1174 return 0;
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03001175}
1176
1177/****************************************************************************
1178**
1179** Name: MT2063_GetParam
1180**
1181** Description: Gets a tuning algorithm parameter.
1182**
1183** This function provides access to the internals of the
1184** tuning algorithm - mostly for testing purposes.
1185**
1186** Parameters: h - Tuner handle (returned by MT2063_Open)
1187** param - Tuning algorithm parameter
1188** (see enum MT2063_Param)
1189** pValue - ptr to returned value
1190**
1191** param Description
1192** ---------------------- --------------------------------
1193** MT2063_IC_ADDR Serial Bus address of this tuner
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03001194** MT2063_SRO_FREQ crystal frequency
1195** MT2063_STEPSIZE minimum tuning step size
1196** MT2063_INPUT_FREQ input center frequency
1197** MT2063_LO1_FREQ LO1 Frequency
1198** MT2063_LO1_STEPSIZE LO1 minimum step size
1199** MT2063_LO1_FRACN_AVOID LO1 FracN keep-out region
1200** MT2063_IF1_ACTUAL Current 1st IF in use
1201** MT2063_IF1_REQUEST Requested 1st IF
1202** MT2063_IF1_CENTER Center of 1st IF SAW filter
1203** MT2063_IF1_BW Bandwidth of 1st IF SAW filter
1204** MT2063_ZIF_BW zero-IF bandwidth
1205** MT2063_LO2_FREQ LO2 Frequency
1206** MT2063_LO2_STEPSIZE LO2 minimum step size
1207** MT2063_LO2_FRACN_AVOID LO2 FracN keep-out region
1208** MT2063_OUTPUT_FREQ output center frequency
1209** MT2063_OUTPUT_BW output bandwidth
1210** MT2063_LO_SEPARATION min inter-tuner LO separation
1211** MT2063_AS_ALG ID of avoid-spurs algorithm in use
1212** MT2063_MAX_HARM1 max # of intra-tuner harmonics
1213** MT2063_MAX_HARM2 max # of inter-tuner harmonics
1214** MT2063_EXCL_ZONES # of 1st IF exclusion zones
1215** MT2063_NUM_SPURS # of spurs found/avoided
1216** MT2063_SPUR_AVOIDED >0 spurs avoided
1217** MT2063_SPUR_PRESENT >0 spurs in output (mathematically)
1218** MT2063_RCVR_MODE Predefined modes.
1219** MT2063_ACLNA LNA attenuator gain code
1220** MT2063_ACRF RF attenuator gain code
1221** MT2063_ACFIF FIF attenuator gain code
1222** MT2063_ACLNA_MAX LNA attenuator limit
1223** MT2063_ACRF_MAX RF attenuator limit
1224** MT2063_ACFIF_MAX FIF attenuator limit
1225** MT2063_PD1 Actual value of PD1
1226** MT2063_PD2 Actual value of PD2
1227** MT2063_DNC_OUTPUT_ENABLE DNC output selection
1228** MT2063_VGAGC VGA gain code
1229** MT2063_VGAOI VGA output current
1230** MT2063_TAGC TAGC setting
1231** MT2063_AMPGC AMP gain code
1232** MT2063_AVOID_DECT Avoid DECT Frequencies
1233** MT2063_CTFILT_SW Cleartune filter selection
1234**
1235** Usage: status |= MT2063_GetParam(hMT2063,
1236** MT2063_IF1_ACTUAL,
1237** &f_IF1_Actual);
1238**
1239** Returns: status:
1240** MT_OK - No errors
1241** MT_INV_HANDLE - Invalid tuner handle
1242** MT_ARG_NULL - Null pointer argument passed
1243** MT_ARG_RANGE - Invalid parameter requested
1244**
1245** Dependencies: USERS MUST CALL MT2063_Open() FIRST!
1246**
1247** See Also: MT2063_SetParam, MT2063_Open
1248**
1249** Revision History:
1250**
1251** SCR Date Author Description
1252** -------------------------------------------------------------------------
1253** 138 06-19-2007 DAD Ver 1.00: Initial, derived from mt2067_b.
1254** 154 09-13-2007 RSK Ver 1.05: Get/SetParam changes for LOx_FREQ
1255** 10-31-2007 PINZ Ver 1.08: Get/SetParam add VGAGC, VGAOI, AMPGC, TAGC
1256** 173 M 01-23-2008 RSK Ver 1.12: Read LO1C and LO2C registers from HW
1257** in GetParam.
1258** 04-18-2008 PINZ Ver 1.15: Add SetParam LNARIN & PDxTGT
1259** Split SetParam up to ACLNA / ACLNA_MAX
1260** removed ACLNA_INRC/DECR (+RF & FIF)
1261** removed GCUAUTO / BYPATNDN/UP
1262** 175 I 16-06-2008 PINZ Ver 1.16: Add control to avoid US DECT freqs.
1263** 175 I 06-19-2008 RSK Ver 1.17: Refactor DECT control to SpurAvoid.
1264** 06-24-2008 PINZ Ver 1.18: Add Get/SetParam CTFILT_SW
1265**
1266****************************************************************************/
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03001267static u32 MT2063_GetParam(struct mt2063_state *state, enum MT2063_Param param, u32 *pValue)
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03001268{
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03001269 u32 status = 0; /* Status to be returned */
Mauro Carvalho Chehabcfde8922011-07-20 21:01:48 -03001270 u32 Div;
1271 u32 Num;
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03001272
1273 if (pValue == NULL)
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03001274 return -EINVAL;
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03001275
Mauro Carvalho Chehab51f0f7b2011-07-21 02:24:18 -03001276 switch (param) {
Mauro Carvalho Chehab51f0f7b2011-07-21 02:24:18 -03001277 /* input center frequency */
1278 case MT2063_INPUT_FREQ:
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03001279 *pValue = state->AS_Data.f_in;
Mauro Carvalho Chehab51f0f7b2011-07-21 02:24:18 -03001280 break;
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03001281
Mauro Carvalho Chehab51f0f7b2011-07-21 02:24:18 -03001282 /* LO1 Frequency */
1283 case MT2063_LO1_FREQ:
1284 {
1285 /* read the actual tuner register values for LO1C_1 and LO1C_2 */
1286 status |=
Mauro Carvalho Chehabe1de3d12011-07-21 02:46:49 -03001287 mt2063_read(state,
Mauro Carvalho Chehab51f0f7b2011-07-21 02:24:18 -03001288 MT2063_REG_LO1C_1,
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03001289 &state->
Mauro Carvalho Chehab51f0f7b2011-07-21 02:24:18 -03001290 reg[MT2063_REG_LO1C_1], 2);
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03001291 Div = state->reg[MT2063_REG_LO1C_1];
1292 Num = state->reg[MT2063_REG_LO1C_2] & 0x3F;
1293 state->AS_Data.f_LO1 =
1294 (state->AS_Data.f_ref * Div) +
1295 MT2063_fLO_FractionalTerm(state->AS_Data.
Mauro Carvalho Chehab51f0f7b2011-07-21 02:24:18 -03001296 f_ref, Num, 64);
1297 }
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03001298 *pValue = state->AS_Data.f_LO1;
Mauro Carvalho Chehab51f0f7b2011-07-21 02:24:18 -03001299 break;
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03001300
Mauro Carvalho Chehab51f0f7b2011-07-21 02:24:18 -03001301 /* Bandwidth of 1st IF SAW filter */
1302 case MT2063_IF1_BW:
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03001303 *pValue = state->AS_Data.f_if1_bw;
Mauro Carvalho Chehab51f0f7b2011-07-21 02:24:18 -03001304 break;
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03001305
Mauro Carvalho Chehab51f0f7b2011-07-21 02:24:18 -03001306 /* zero-IF bandwidth */
1307 case MT2063_ZIF_BW:
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03001308 *pValue = state->AS_Data.f_zif_bw;
Mauro Carvalho Chehab51f0f7b2011-07-21 02:24:18 -03001309 break;
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03001310
Mauro Carvalho Chehab51f0f7b2011-07-21 02:24:18 -03001311 /* LO2 Frequency */
1312 case MT2063_LO2_FREQ:
1313 {
1314 /* Read the actual tuner register values for LO2C_1, LO2C_2 and LO2C_3 */
1315 status |=
Mauro Carvalho Chehabe1de3d12011-07-21 02:46:49 -03001316 mt2063_read(state,
Mauro Carvalho Chehab51f0f7b2011-07-21 02:24:18 -03001317 MT2063_REG_LO2C_1,
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03001318 &state->
Mauro Carvalho Chehab51f0f7b2011-07-21 02:24:18 -03001319 reg[MT2063_REG_LO2C_1], 3);
1320 Div =
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03001321 (state->reg[MT2063_REG_LO2C_1] & 0xFE) >> 1;
Mauro Carvalho Chehab51f0f7b2011-07-21 02:24:18 -03001322 Num =
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03001323 ((state->
Mauro Carvalho Chehab51f0f7b2011-07-21 02:24:18 -03001324 reg[MT2063_REG_LO2C_1] & 0x01) << 12) |
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03001325 (state->
1326 reg[MT2063_REG_LO2C_2] << 4) | (state->
Mauro Carvalho Chehab51f0f7b2011-07-21 02:24:18 -03001327 reg
1328 [MT2063_REG_LO2C_3]
1329 & 0x00F);
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03001330 state->AS_Data.f_LO2 =
1331 (state->AS_Data.f_ref * Div) +
1332 MT2063_fLO_FractionalTerm(state->AS_Data.
Mauro Carvalho Chehab51f0f7b2011-07-21 02:24:18 -03001333 f_ref, Num, 8191);
1334 }
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03001335 *pValue = state->AS_Data.f_LO2;
Mauro Carvalho Chehab51f0f7b2011-07-21 02:24:18 -03001336 break;
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03001337
Mauro Carvalho Chehab51f0f7b2011-07-21 02:24:18 -03001338 /* LO2 FracN keep-out region */
1339 case MT2063_LO2_FRACN_AVOID:
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03001340 *pValue = state->AS_Data.f_LO2_FracN_Avoid;
Mauro Carvalho Chehab51f0f7b2011-07-21 02:24:18 -03001341 break;
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03001342
Mauro Carvalho Chehab51f0f7b2011-07-21 02:24:18 -03001343 /* output center frequency */
1344 case MT2063_OUTPUT_FREQ:
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03001345 *pValue = state->AS_Data.f_out;
Mauro Carvalho Chehab51f0f7b2011-07-21 02:24:18 -03001346 break;
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03001347
Mauro Carvalho Chehab51f0f7b2011-07-21 02:24:18 -03001348 /* output bandwidth */
1349 case MT2063_OUTPUT_BW:
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03001350 *pValue = state->AS_Data.f_out_bw - 750000;
Mauro Carvalho Chehab51f0f7b2011-07-21 02:24:18 -03001351 break;
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03001352
Mauro Carvalho Chehab51f0f7b2011-07-21 02:24:18 -03001353 /* Predefined receiver setup combination */
1354 case MT2063_RCVR_MODE:
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03001355 *pValue = state->rcvr_mode;
Mauro Carvalho Chehab51f0f7b2011-07-21 02:24:18 -03001356 break;
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03001357
Mauro Carvalho Chehab51f0f7b2011-07-21 02:24:18 -03001358 case MT2063_PD1:
1359 case MT2063_PD2: {
1360 u8 mask = (param == MT2063_PD1 ? 0x01 : 0x03); /* PD1 vs PD2 */
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03001361 u8 orig = (state->reg[MT2063_REG_BYP_CTRL]);
Mauro Carvalho Chehab51f0f7b2011-07-21 02:24:18 -03001362 u8 reg = (orig & 0xF1) | mask; /* Only set 3 bits (not 5) */
1363 int i;
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03001364
Mauro Carvalho Chehab51f0f7b2011-07-21 02:24:18 -03001365 *pValue = 0;
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03001366
Mauro Carvalho Chehab51f0f7b2011-07-21 02:24:18 -03001367 /* Initiate ADC output to reg 0x0A */
1368 if (reg != orig)
1369 status |=
Mauro Carvalho Chehabe1de3d12011-07-21 02:46:49 -03001370 mt2063_write(state,
Mauro Carvalho Chehab51f0f7b2011-07-21 02:24:18 -03001371 MT2063_REG_BYP_CTRL,
1372 &reg, 1);
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03001373
Mauro Carvalho Chehab51f0f7b2011-07-21 02:24:18 -03001374 if (status < 0)
1375 return (status);
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03001376
Mauro Carvalho Chehab51f0f7b2011-07-21 02:24:18 -03001377 for (i = 0; i < 8; i++) {
1378 status |=
Mauro Carvalho Chehabe1de3d12011-07-21 02:46:49 -03001379 mt2063_read(state,
Mauro Carvalho Chehab51f0f7b2011-07-21 02:24:18 -03001380 MT2063_REG_ADC_OUT,
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03001381 &state->
Mauro Carvalho Chehab51f0f7b2011-07-21 02:24:18 -03001382 reg
1383 [MT2063_REG_ADC_OUT],
1384 1);
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03001385
Mauro Carvalho Chehab51f0f7b2011-07-21 02:24:18 -03001386 if (status >= 0)
1387 *pValue +=
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03001388 state->
Mauro Carvalho Chehab51f0f7b2011-07-21 02:24:18 -03001389 reg[MT2063_REG_ADC_OUT];
1390 else {
1391 if (i)
1392 *pValue /= i;
1393 return (status);
1394 }
1395 }
1396 *pValue /= 8; /* divide by number of reads */
1397 *pValue >>= 2; /* only want 6 MSB's out of 8 */
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03001398
Mauro Carvalho Chehab51f0f7b2011-07-21 02:24:18 -03001399 /* Restore value of Register BYP_CTRL */
1400 if (reg != orig)
1401 status |=
Mauro Carvalho Chehabe1de3d12011-07-21 02:46:49 -03001402 mt2063_write(state,
Mauro Carvalho Chehab51f0f7b2011-07-21 02:24:18 -03001403 MT2063_REG_BYP_CTRL,
1404 &orig, 1);
1405 }
1406 break;
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03001407
Mauro Carvalho Chehab51f0f7b2011-07-21 02:24:18 -03001408 /* Get LNA attenuator code */
1409 case MT2063_ACLNA:
1410 {
1411 u8 val;
1412 status |=
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03001413 MT2063_GetReg(state, MT2063_REG_XO_STATUS,
Mauro Carvalho Chehab51f0f7b2011-07-21 02:24:18 -03001414 &val);
1415 *pValue = val & 0x1f;
1416 }
1417 break;
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03001418
Mauro Carvalho Chehab51f0f7b2011-07-21 02:24:18 -03001419 /* Get RF attenuator code */
1420 case MT2063_ACRF:
1421 {
1422 u8 val;
1423 status |=
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03001424 MT2063_GetReg(state, MT2063_REG_RF_STATUS,
Mauro Carvalho Chehab51f0f7b2011-07-21 02:24:18 -03001425 &val);
1426 *pValue = val & 0x1f;
1427 }
1428 break;
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03001429
Mauro Carvalho Chehab51f0f7b2011-07-21 02:24:18 -03001430 /* Get FIF attenuator code */
1431 case MT2063_ACFIF:
1432 {
1433 u8 val;
1434 status |=
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03001435 MT2063_GetReg(state, MT2063_REG_FIF_STATUS,
Mauro Carvalho Chehab51f0f7b2011-07-21 02:24:18 -03001436 &val);
1437 *pValue = val & 0x1f;
1438 }
1439 break;
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03001440
Mauro Carvalho Chehab51f0f7b2011-07-21 02:24:18 -03001441 /* Get LNA attenuator limit */
1442 case MT2063_ACLNA_MAX:
1443 {
1444 u8 val;
1445 status |=
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03001446 MT2063_GetReg(state, MT2063_REG_LNA_OV,
Mauro Carvalho Chehab51f0f7b2011-07-21 02:24:18 -03001447 &val);
1448 *pValue = val & 0x1f;
1449 }
1450 break;
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03001451
Mauro Carvalho Chehab51f0f7b2011-07-21 02:24:18 -03001452 /* Get RF attenuator limit */
1453 case MT2063_ACRF_MAX:
1454 {
1455 u8 val;
1456 status |=
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03001457 MT2063_GetReg(state, MT2063_REG_RF_OV,
Mauro Carvalho Chehab51f0f7b2011-07-21 02:24:18 -03001458 &val);
1459 *pValue = val & 0x1f;
1460 }
1461 break;
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03001462
Mauro Carvalho Chehab51f0f7b2011-07-21 02:24:18 -03001463 /* Get FIF attenuator limit */
1464 case MT2063_ACFIF_MAX:
1465 {
1466 u8 val;
1467 status |=
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03001468 MT2063_GetReg(state, MT2063_REG_FIF_OV,
Mauro Carvalho Chehab51f0f7b2011-07-21 02:24:18 -03001469 &val);
1470 *pValue = val & 0x1f;
1471 }
1472 break;
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03001473
Mauro Carvalho Chehab51f0f7b2011-07-21 02:24:18 -03001474 /* Get current used DNC output */
1475 case MT2063_DNC_OUTPUT_ENABLE:
1476 {
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03001477 if ((state->reg[MT2063_REG_DNC_GAIN] & 0x03) == 0x03) { /* if DNC1 is off */
1478 if ((state->reg[MT2063_REG_VGA_GAIN] & 0x03) == 0x03) /* if DNC2 is off */
Mauro Carvalho Chehab51f0f7b2011-07-21 02:24:18 -03001479 *pValue =
1480 (u32) MT2063_DNC_NONE;
1481 else
1482 *pValue =
1483 (u32) MT2063_DNC_2;
1484 } else { /* DNC1 is on */
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03001485
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03001486 if ((state->reg[MT2063_REG_VGA_GAIN] & 0x03) == 0x03) /* if DNC2 is off */
Mauro Carvalho Chehab51f0f7b2011-07-21 02:24:18 -03001487 *pValue =
1488 (u32) MT2063_DNC_1;
1489 else
1490 *pValue =
1491 (u32) MT2063_DNC_BOTH;
1492 }
1493 }
1494 break;
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03001495
Mauro Carvalho Chehab51f0f7b2011-07-21 02:24:18 -03001496 default:
1497 status |= -ERANGE;
1498 }
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03001499 return (status);
1500}
1501
1502/****************************************************************************
1503**
1504** Name: MT2063_GetReg
1505**
1506** Description: Gets an MT2063 register.
1507**
1508** Parameters: h - Tuner handle (returned by MT2063_Open)
1509** reg - MT2063 register/subaddress location
1510** *val - MT2063 register/subaddress value
1511**
1512** Returns: status:
1513** MT_OK - No errors
1514** MT_COMM_ERR - Serial bus communications error
1515** MT_INV_HANDLE - Invalid tuner handle
1516** MT_ARG_NULL - Null pointer argument passed
1517** MT_ARG_RANGE - Argument out of range
1518**
1519** Dependencies: USERS MUST CALL MT2063_Open() FIRST!
1520**
1521** Use this function if you need to read a register from
1522** the MT2063.
1523**
1524** Revision History:
1525**
1526** SCR Date Author Description
1527** -------------------------------------------------------------------------
1528** 138 06-19-2007 DAD Ver 1.00: Initial, derived from mt2067_b.
1529**
1530****************************************************************************/
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03001531static u32 MT2063_GetReg(struct mt2063_state *state, u8 reg, u8 * val)
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03001532{
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03001533 u32 status = 0; /* Status to be returned */
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03001534
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03001535 if (val == NULL)
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03001536 return -EINVAL;
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03001537
1538 if (reg >= MT2063_REG_END_REGS)
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03001539 return -ERANGE;
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03001540
Mauro Carvalho Chehabe1de3d12011-07-21 02:46:49 -03001541 status = mt2063_read(state, reg, &state->reg[reg], 1);
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03001542
1543 return (status);
1544}
1545
1546/******************************************************************************
1547**
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03001548** Name: MT2063_SetReceiverMode
1549**
1550** Description: Set the MT2063 receiver mode
1551**
1552** --------------+----------------------------------------------
1553** Mode 0 : | MT2063_CABLE_QAM
1554** Mode 1 : | MT2063_CABLE_ANALOG
1555** Mode 2 : | MT2063_OFFAIR_COFDM
1556** Mode 3 : | MT2063_OFFAIR_COFDM_SAWLESS
1557** Mode 4 : | MT2063_OFFAIR_ANALOG
1558** Mode 5 : | MT2063_OFFAIR_8VSB
1559** --------------+----+----+----+----+-----+--------------------
1560** (DNC1GC & DNC2GC are the values, which are used, when the specific
1561** DNC Output is selected, the other is always off)
1562**
1563** |<---------- Mode -------------->|
1564** Reg Field | 0 | 1 | 2 | 3 | 4 | 5 |
1565** ------------+-----+-----+-----+-----+-----+-----+
1566** RFAGCen | OFF | OFF | OFF | OFF | OFF | OFF
1567** LNARin | 0 | 0 | 3 | 3 | 3 | 3
1568** FIFFQen | 1 | 1 | 1 | 1 | 1 | 1
1569** FIFFq | 0 | 0 | 0 | 0 | 0 | 0
1570** DNC1gc | 0 | 0 | 0 | 0 | 0 | 0
1571** DNC2gc | 0 | 0 | 0 | 0 | 0 | 0
1572** GCU Auto | 1 | 1 | 1 | 1 | 1 | 1
1573** LNA max Atn | 31 | 31 | 31 | 31 | 31 | 31
1574** LNA Target | 44 | 43 | 43 | 43 | 43 | 43
1575** ign RF Ovl | 0 | 0 | 0 | 0 | 0 | 0
1576** RF max Atn | 31 | 31 | 31 | 31 | 31 | 31
1577** PD1 Target | 36 | 36 | 38 | 38 | 36 | 38
1578** ign FIF Ovl | 0 | 0 | 0 | 0 | 0 | 0
1579** FIF max Atn | 5 | 5 | 5 | 5 | 5 | 5
1580** PD2 Target | 40 | 33 | 42 | 42 | 33 | 42
1581**
1582**
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03001583** Parameters: state - ptr to mt2063_state structure
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03001584** Mode - desired reciever mode
1585**
1586** Usage: status = MT2063_SetReceiverMode(hMT2063, Mode);
1587**
1588** Returns: status:
1589** MT_OK - No errors
1590** MT_COMM_ERR - Serial bus communications error
1591**
1592** Dependencies: MT2063_SetReg - Write a byte of data to a HW register.
1593** Assumes that the tuner cache is valid.
1594**
1595** Revision History:
1596**
1597** SCR Date Author Description
1598** -------------------------------------------------------------------------
1599** 138 06-19-2007 DAD Ver 1.00: Initial, derived from mt2067_b.
1600** N/A 01-10-2007 PINZ Added additional GCU Settings, FIFF Calib will be triggered
1601** 155 10-01-2007 DAD Ver 1.06: Add receiver mode for SECAM positive
1602** modulation
1603** (MT2063_ANALOG_TV_POS_NO_RFAGC_MODE)
1604** N/A 10-22-2007 PINZ Ver 1.07: Changed some Registers at init to have
1605** the same settings as with MT Launcher
1606** N/A 10-30-2007 PINZ Add SetParam VGAGC & VGAOI
1607** Add SetParam DNC_OUTPUT_ENABLE
1608** Removed VGAGC from receiver mode,
1609** default now 1
1610** N/A 10-31-2007 PINZ Ver 1.08: Add SetParam TAGC, removed from rcvr-mode
1611** Add SetParam AMPGC, removed from rcvr-mode
1612** Corrected names of GCU values
1613** reorganized receiver modes, removed,
1614** (MT2063_ANALOG_TV_POS_NO_RFAGC_MODE)
1615** Actualized Receiver-Mode values
1616** N/A 11-12-2007 PINZ Ver 1.09: Actualized Receiver-Mode values
1617** N/A 11-27-2007 PINZ Improved buffered writing
1618** 01-03-2008 PINZ Ver 1.10: Added a trigger of BYPATNUP for
1619** correct wakeup of the LNA after shutdown
1620** Set AFCsd = 1 as default
1621** Changed CAP1sel default
1622** 01-14-2008 PINZ Ver 1.11: Updated gain settings
1623** 04-18-2008 PINZ Ver 1.15: Add SetParam LNARIN & PDxTGT
1624** Split SetParam up to ACLNA / ACLNA_MAX
1625** removed ACLNA_INRC/DECR (+RF & FIF)
1626** removed GCUAUTO / BYPATNDN/UP
1627**
1628******************************************************************************/
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03001629static u32 MT2063_SetReceiverMode(struct mt2063_state *state,
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03001630 enum MT2063_RCVR_MODES Mode)
1631{
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03001632 u32 status = 0; /* Status to be returned */
Mauro Carvalho Chehabcfde8922011-07-20 21:01:48 -03001633 u8 val;
1634 u32 longval;
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03001635
1636 if (Mode >= MT2063_NUM_RCVR_MODES)
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03001637 status = -ERANGE;
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03001638
1639 /* RFAGCen */
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03001640 if (status >= 0) {
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03001641 val =
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03001642 (state->
Mauro Carvalho Chehabcfde8922011-07-20 21:01:48 -03001643 reg[MT2063_REG_PD1_TGT] & (u8) ~ 0x40) | (RFAGCEN[Mode]
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03001644 ? 0x40 :
1645 0x00);
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03001646 if (state->reg[MT2063_REG_PD1_TGT] != val) {
1647 status |= MT2063_SetReg(state, MT2063_REG_PD1_TGT, val);
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03001648 }
1649 }
1650
1651 /* LNARin */
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03001652 if (status >= 0) {
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03001653 status |= MT2063_SetParam(state, MT2063_LNA_RIN, LNARIN[Mode]);
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03001654 }
1655
1656 /* FIFFQEN and FIFFQ */
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03001657 if (status >= 0) {
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03001658 val =
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03001659 (state->
Mauro Carvalho Chehabcfde8922011-07-20 21:01:48 -03001660 reg[MT2063_REG_FIFF_CTRL2] & (u8) ~ 0xF0) |
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03001661 (FIFFQEN[Mode] << 7) | (FIFFQ[Mode] << 4);
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03001662 if (state->reg[MT2063_REG_FIFF_CTRL2] != val) {
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03001663 status |=
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03001664 MT2063_SetReg(state, MT2063_REG_FIFF_CTRL2, val);
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03001665 /* trigger FIFF calibration, needed after changing FIFFQ */
1666 val =
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03001667 (state->reg[MT2063_REG_FIFF_CTRL] | (u8) 0x01);
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03001668 status |=
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03001669 MT2063_SetReg(state, MT2063_REG_FIFF_CTRL, val);
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03001670 val =
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03001671 (state->
Mauro Carvalho Chehabcfde8922011-07-20 21:01:48 -03001672 reg[MT2063_REG_FIFF_CTRL] & (u8) ~ 0x01);
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03001673 status |=
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03001674 MT2063_SetReg(state, MT2063_REG_FIFF_CTRL, val);
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03001675 }
1676 }
1677
1678 /* DNC1GC & DNC2GC */
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03001679 status |= MT2063_GetParam(state, MT2063_DNC_OUTPUT_ENABLE, &longval);
1680 status |= MT2063_SetParam(state, MT2063_DNC_OUTPUT_ENABLE, longval);
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03001681
1682 /* acLNAmax */
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03001683 if (status >= 0) {
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03001684 status |=
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03001685 MT2063_SetParam(state, MT2063_ACLNA_MAX, ACLNAMAX[Mode]);
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03001686 }
1687
1688 /* LNATGT */
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03001689 if (status >= 0) {
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03001690 status |= MT2063_SetParam(state, MT2063_LNA_TGT, LNATGT[Mode]);
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03001691 }
1692
1693 /* ACRF */
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03001694 if (status >= 0) {
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03001695 status |=
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03001696 MT2063_SetParam(state, MT2063_ACRF_MAX, ACRFMAX[Mode]);
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03001697 }
1698
1699 /* PD1TGT */
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03001700 if (status >= 0) {
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03001701 status |= MT2063_SetParam(state, MT2063_PD1_TGT, PD1TGT[Mode]);
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03001702 }
1703
1704 /* FIFATN */
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03001705 if (status >= 0) {
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03001706 status |=
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03001707 MT2063_SetParam(state, MT2063_ACFIF_MAX, ACFIFMAX[Mode]);
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03001708 }
1709
1710 /* PD2TGT */
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03001711 if (status >= 0) {
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03001712 status |= MT2063_SetParam(state, MT2063_PD2_TGT, PD2TGT[Mode]);
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03001713 }
1714
1715 /* Ignore ATN Overload */
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03001716 if (status >= 0) {
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03001717 val =
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03001718 (state->
Mauro Carvalho Chehabcfde8922011-07-20 21:01:48 -03001719 reg[MT2063_REG_LNA_TGT] & (u8) ~ 0x80) | (RFOVDIS[Mode]
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03001720 ? 0x80 :
1721 0x00);
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03001722 if (state->reg[MT2063_REG_LNA_TGT] != val) {
1723 status |= MT2063_SetReg(state, MT2063_REG_LNA_TGT, val);
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03001724 }
1725 }
1726
1727 /* Ignore FIF Overload */
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03001728 if (status >= 0) {
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03001729 val =
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03001730 (state->
Mauro Carvalho Chehabcfde8922011-07-20 21:01:48 -03001731 reg[MT2063_REG_PD1_TGT] & (u8) ~ 0x80) |
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03001732 (FIFOVDIS[Mode] ? 0x80 : 0x00);
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03001733 if (state->reg[MT2063_REG_PD1_TGT] != val) {
1734 status |= MT2063_SetReg(state, MT2063_REG_PD1_TGT, val);
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03001735 }
1736 }
1737
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03001738 if (status >= 0)
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03001739 state->rcvr_mode = Mode;
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03001740
1741 return (status);
1742}
1743
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03001744/****************************************************************************
1745**
1746** Name: MT2063_SetParam
1747**
1748** Description: Sets a tuning algorithm parameter.
1749**
1750** This function provides access to the internals of the
1751** tuning algorithm. You can override many of the tuning
1752** algorithm defaults using this function.
1753**
1754** Parameters: h - Tuner handle (returned by MT2063_Open)
1755** param - Tuning algorithm parameter
1756** (see enum MT2063_Param)
1757** nValue - value to be set
1758**
1759** param Description
1760** ---------------------- --------------------------------
1761** MT2063_SRO_FREQ crystal frequency
1762** MT2063_STEPSIZE minimum tuning step size
1763** MT2063_LO1_FREQ LO1 frequency
1764** MT2063_LO1_STEPSIZE LO1 minimum step size
1765** MT2063_LO1_FRACN_AVOID LO1 FracN keep-out region
1766** MT2063_IF1_REQUEST Requested 1st IF
1767** MT2063_ZIF_BW zero-IF bandwidth
1768** MT2063_LO2_FREQ LO2 frequency
1769** MT2063_LO2_STEPSIZE LO2 minimum step size
1770** MT2063_LO2_FRACN_AVOID LO2 FracN keep-out region
1771** MT2063_OUTPUT_FREQ output center frequency
1772** MT2063_OUTPUT_BW output bandwidth
1773** MT2063_LO_SEPARATION min inter-tuner LO separation
1774** MT2063_MAX_HARM1 max # of intra-tuner harmonics
1775** MT2063_MAX_HARM2 max # of inter-tuner harmonics
1776** MT2063_RCVR_MODE Predefined modes
1777** MT2063_LNA_RIN Set LNA Rin (*)
1778** MT2063_LNA_TGT Set target power level at LNA (*)
1779** MT2063_PD1_TGT Set target power level at PD1 (*)
1780** MT2063_PD2_TGT Set target power level at PD2 (*)
1781** MT2063_ACLNA_MAX LNA attenuator limit (*)
1782** MT2063_ACRF_MAX RF attenuator limit (*)
1783** MT2063_ACFIF_MAX FIF attenuator limit (*)
1784** MT2063_DNC_OUTPUT_ENABLE DNC output selection
1785** MT2063_VGAGC VGA gain code
1786** MT2063_VGAOI VGA output current
1787** MT2063_TAGC TAGC setting
1788** MT2063_AMPGC AMP gain code
1789** MT2063_AVOID_DECT Avoid DECT Frequencies
1790** MT2063_CTFILT_SW Cleartune filter selection
1791**
1792** (*) This parameter is set by MT2063_RCVR_MODE, do not call
1793** additionally.
1794**
1795** Usage: status |= MT2063_SetParam(hMT2063,
1796** MT2063_STEPSIZE,
1797** 50000);
1798**
1799** Returns: status:
1800** MT_OK - No errors
1801** MT_INV_HANDLE - Invalid tuner handle
1802** MT_ARG_NULL - Null pointer argument passed
1803** MT_ARG_RANGE - Invalid parameter requested
1804** or set value out of range
1805** or non-writable parameter
1806**
1807** Dependencies: USERS MUST CALL MT2063_Open() FIRST!
1808**
1809** See Also: MT2063_GetParam, MT2063_Open
1810**
1811** Revision History:
1812**
1813** SCR Date Author Description
1814** -------------------------------------------------------------------------
1815** 138 06-19-2007 DAD Ver 1.00: Initial, derived from mt2067_b.
1816** 154 09-13-2007 RSK Ver 1.05: Get/SetParam changes for LOx_FREQ
1817** 10-31-2007 PINZ Ver 1.08: Get/SetParam add VGAGC, VGAOI, AMPGC, TAGC
1818** 04-18-2008 PINZ Ver 1.15: Add SetParam LNARIN & PDxTGT
1819** Split SetParam up to ACLNA / ACLNA_MAX
1820** removed ACLNA_INRC/DECR (+RF & FIF)
1821** removed GCUAUTO / BYPATNDN/UP
1822** 175 I 06-06-2008 PINZ Ver 1.16: Add control to avoid US DECT freqs.
1823** 175 I 06-19-2008 RSK Ver 1.17: Refactor DECT control to SpurAvoid.
1824** 06-24-2008 PINZ Ver 1.18: Add Get/SetParam CTFILT_SW
1825**
1826****************************************************************************/
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03001827static u32 MT2063_SetParam(struct mt2063_state *state,
Mauro Carvalho Chehab29a0a4f2011-07-20 23:44:10 -03001828 enum MT2063_Param param,
1829 enum MT2063_DNC_Output_Enable nValue)
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03001830{
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03001831 u32 status = 0; /* Status to be returned */
Mauro Carvalho Chehabcfde8922011-07-20 21:01:48 -03001832 u8 val = 0;
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03001833
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03001834 switch (param) {
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03001835 /* LO1 frequency */
1836 case MT2063_LO1_FREQ:
1837 {
1838 /* Note: LO1 and LO2 are BOTH written at toggle of LDLOos */
1839 /* Capture the Divider and Numerator portions of other LO */
1840 u8 tempLO2CQ[3];
1841 u8 tempLO2C[3];
1842 u8 tmpOneShot;
1843 u32 Div, FracN;
1844 u8 restore = 0;
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03001845
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03001846 /* Buffer the queue for restoration later and get actual LO2 values. */
1847 status |=
Mauro Carvalho Chehabe1de3d12011-07-21 02:46:49 -03001848 mt2063_read(state,
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03001849 MT2063_REG_LO2CQ_1,
1850 &(tempLO2CQ[0]), 3);
1851 status |=
Mauro Carvalho Chehabe1de3d12011-07-21 02:46:49 -03001852 mt2063_read(state,
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03001853 MT2063_REG_LO2C_1,
1854 &(tempLO2C[0]), 3);
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03001855
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03001856 /* clear the one-shot bits */
1857 tempLO2CQ[2] = tempLO2CQ[2] & 0x0F;
1858 tempLO2C[2] = tempLO2C[2] & 0x0F;
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03001859
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03001860 /* only write the queue values if they are different from the actual. */
1861 if ((tempLO2CQ[0] != tempLO2C[0]) ||
1862 (tempLO2CQ[1] != tempLO2C[1]) ||
1863 (tempLO2CQ[2] != tempLO2C[2])) {
1864 /* put actual LO2 value into queue (with 0 in one-shot bits) */
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03001865 status |=
Mauro Carvalho Chehabe1de3d12011-07-21 02:46:49 -03001866 mt2063_write(state,
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03001867 MT2063_REG_LO2CQ_1,
1868 &(tempLO2C[0]), 3);
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03001869
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03001870 if (status == 0) {
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03001871 /* cache the bytes just written. */
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03001872 state->reg[MT2063_REG_LO2CQ_1] =
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03001873 tempLO2C[0];
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03001874 state->reg[MT2063_REG_LO2CQ_2] =
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03001875 tempLO2C[1];
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03001876 state->reg[MT2063_REG_LO2CQ_3] =
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03001877 tempLO2C[2];
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03001878 }
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03001879 restore = 1;
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03001880 }
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03001881
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03001882 /* Calculate the Divider and Numberator components of LO1 */
1883 status =
1884 MT2063_CalcLO1Mult(&Div, &FracN, nValue,
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03001885 state->AS_Data.f_ref /
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03001886 64,
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03001887 state->AS_Data.f_ref);
1888 state->reg[MT2063_REG_LO1CQ_1] =
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03001889 (u8) (Div & 0x00FF);
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03001890 state->reg[MT2063_REG_LO1CQ_2] =
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03001891 (u8) (FracN);
1892 status |=
Mauro Carvalho Chehabe1de3d12011-07-21 02:46:49 -03001893 mt2063_write(state,
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03001894 MT2063_REG_LO1CQ_1,
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03001895 &state->
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03001896 reg[MT2063_REG_LO1CQ_1], 2);
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03001897
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03001898 /* set the one-shot bit to load the pair of LO values */
1899 tmpOneShot = tempLO2CQ[2] | 0xE0;
1900 status |=
Mauro Carvalho Chehabe1de3d12011-07-21 02:46:49 -03001901 mt2063_write(state,
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03001902 MT2063_REG_LO2CQ_3,
1903 &tmpOneShot, 1);
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03001904
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03001905 /* only restore the queue values if they were different from the actual. */
1906 if (restore) {
1907 /* put actual LO2 value into queue (0 in one-shot bits) */
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03001908 status |=
Mauro Carvalho Chehabe1de3d12011-07-21 02:46:49 -03001909 mt2063_write(state,
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03001910 MT2063_REG_LO2CQ_1,
1911 &(tempLO2CQ[0]), 3);
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03001912
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03001913 /* cache the bytes just written. */
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03001914 state->reg[MT2063_REG_LO2CQ_1] =
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03001915 tempLO2CQ[0];
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03001916 state->reg[MT2063_REG_LO2CQ_2] =
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03001917 tempLO2CQ[1];
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03001918 state->reg[MT2063_REG_LO2CQ_3] =
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03001919 tempLO2CQ[2];
1920 }
1921
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03001922 MT2063_GetParam(state,
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03001923 MT2063_LO1_FREQ,
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03001924 &state->AS_Data.f_LO1);
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03001925 }
1926 break;
1927
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03001928 /* zero-IF bandwidth */
1929 case MT2063_ZIF_BW:
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03001930 state->AS_Data.f_zif_bw = nValue;
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03001931 break;
1932
1933 /* LO2 frequency */
1934 case MT2063_LO2_FREQ:
1935 {
1936 /* Note: LO1 and LO2 are BOTH written at toggle of LDLOos */
1937 /* Capture the Divider and Numerator portions of other LO */
1938 u8 tempLO1CQ[2];
1939 u8 tempLO1C[2];
1940 u32 Div2;
1941 u32 FracN2;
1942 u8 tmpOneShot;
1943 u8 restore = 0;
1944
1945 /* Buffer the queue for restoration later and get actual LO2 values. */
1946 status |=
Mauro Carvalho Chehabe1de3d12011-07-21 02:46:49 -03001947 mt2063_read(state,
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03001948 MT2063_REG_LO1CQ_1,
1949 &(tempLO1CQ[0]), 2);
1950 status |=
Mauro Carvalho Chehabe1de3d12011-07-21 02:46:49 -03001951 mt2063_read(state,
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03001952 MT2063_REG_LO1C_1,
1953 &(tempLO1C[0]), 2);
1954
1955 /* only write the queue values if they are different from the actual. */
1956 if ((tempLO1CQ[0] != tempLO1C[0])
1957 || (tempLO1CQ[1] != tempLO1C[1])) {
1958 /* put actual LO1 value into queue */
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03001959 status |=
Mauro Carvalho Chehabe1de3d12011-07-21 02:46:49 -03001960 mt2063_write(state,
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03001961 MT2063_REG_LO1CQ_1,
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03001962 &(tempLO1C[0]), 2);
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03001963
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03001964 /* cache the bytes just written. */
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03001965 state->reg[MT2063_REG_LO1CQ_1] =
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03001966 tempLO1C[0];
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03001967 state->reg[MT2063_REG_LO1CQ_2] =
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03001968 tempLO1C[1];
1969 restore = 1;
1970 }
1971
1972 /* Calculate the Divider and Numberator components of LO2 */
1973 status =
1974 MT2063_CalcLO2Mult(&Div2, &FracN2, nValue,
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03001975 state->AS_Data.f_ref /
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03001976 8191,
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03001977 state->AS_Data.f_ref);
1978 state->reg[MT2063_REG_LO2CQ_1] =
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03001979 (u8) ((Div2 << 1) |
1980 ((FracN2 >> 12) & 0x01)) & 0xFF;
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03001981 state->reg[MT2063_REG_LO2CQ_2] =
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03001982 (u8) ((FracN2 >> 4) & 0xFF);
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03001983 state->reg[MT2063_REG_LO2CQ_3] =
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03001984 (u8) ((FracN2 & 0x0F));
1985 status |=
Mauro Carvalho Chehabe1de3d12011-07-21 02:46:49 -03001986 mt2063_write(state,
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03001987 MT2063_REG_LO1CQ_1,
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03001988 &state->
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03001989 reg[MT2063_REG_LO1CQ_1], 3);
1990
1991 /* set the one-shot bit to load the LO values */
1992 tmpOneShot =
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03001993 state->reg[MT2063_REG_LO2CQ_3] | 0xE0;
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03001994 status |=
Mauro Carvalho Chehabe1de3d12011-07-21 02:46:49 -03001995 mt2063_write(state,
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03001996 MT2063_REG_LO2CQ_3,
1997 &tmpOneShot, 1);
1998
1999 /* only restore LO1 queue value if they were different from the actual. */
2000 if (restore) {
2001 /* put previous LO1 queue value back into queue */
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03002002 status |=
Mauro Carvalho Chehabe1de3d12011-07-21 02:46:49 -03002003 mt2063_write(state,
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03002004 MT2063_REG_LO1CQ_1,
2005 &(tempLO1CQ[0]), 2);
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03002006
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03002007 /* cache the bytes just written. */
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03002008 state->reg[MT2063_REG_LO1CQ_1] =
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03002009 tempLO1CQ[0];
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03002010 state->reg[MT2063_REG_LO1CQ_2] =
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03002011 tempLO1CQ[1];
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03002012 }
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03002013
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03002014 MT2063_GetParam(state,
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03002015 MT2063_LO2_FREQ,
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03002016 &state->AS_Data.f_LO2);
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03002017 }
2018 break;
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03002019
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03002020 /* LO2 FracN keep-out region */
2021 case MT2063_LO2_FRACN_AVOID:
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03002022 state->AS_Data.f_LO2_FracN_Avoid = nValue;
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03002023 break;
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03002024
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03002025 /* output center frequency */
2026 case MT2063_OUTPUT_FREQ:
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03002027 state->AS_Data.f_out = nValue;
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03002028 break;
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03002029
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03002030 /* output bandwidth */
2031 case MT2063_OUTPUT_BW:
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03002032 state->AS_Data.f_out_bw = nValue + 750000;
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03002033 break;
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03002034
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03002035 case MT2063_RCVR_MODE:
2036 status |=
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03002037 MT2063_SetReceiverMode(state,
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03002038 (enum MT2063_RCVR_MODES)
2039 nValue);
2040 break;
2041
2042 /* Set LNA Rin -- nValue is desired value */
2043 case MT2063_LNA_RIN:
2044 val =
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03002045 (state->
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03002046 reg[MT2063_REG_CTRL_2C] & (u8) ~ 0x03) |
2047 (nValue & 0x03);
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03002048 if (state->reg[MT2063_REG_CTRL_2C] != val) {
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03002049 status |=
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03002050 MT2063_SetReg(state, MT2063_REG_CTRL_2C,
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03002051 val);
2052 }
2053 break;
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03002054
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03002055 /* Set target power level at LNA -- nValue is desired value */
2056 case MT2063_LNA_TGT:
2057 val =
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03002058 (state->
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03002059 reg[MT2063_REG_LNA_TGT] & (u8) ~ 0x3F) |
2060 (nValue & 0x3F);
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03002061 if (state->reg[MT2063_REG_LNA_TGT] != val) {
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03002062 status |=
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03002063 MT2063_SetReg(state, MT2063_REG_LNA_TGT,
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03002064 val);
2065 }
2066 break;
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03002067
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03002068 /* Set target power level at PD1 -- nValue is desired value */
2069 case MT2063_PD1_TGT:
2070 val =
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03002071 (state->
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03002072 reg[MT2063_REG_PD1_TGT] & (u8) ~ 0x3F) |
2073 (nValue & 0x3F);
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03002074 if (state->reg[MT2063_REG_PD1_TGT] != val) {
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03002075 status |=
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03002076 MT2063_SetReg(state, MT2063_REG_PD1_TGT,
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03002077 val);
2078 }
2079 break;
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03002080
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03002081 /* Set target power level at PD2 -- nValue is desired value */
2082 case MT2063_PD2_TGT:
2083 val =
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03002084 (state->
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03002085 reg[MT2063_REG_PD2_TGT] & (u8) ~ 0x3F) |
2086 (nValue & 0x3F);
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03002087 if (state->reg[MT2063_REG_PD2_TGT] != val) {
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03002088 status |=
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03002089 MT2063_SetReg(state, MT2063_REG_PD2_TGT,
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03002090 val);
2091 }
2092 break;
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03002093
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03002094 /* Set LNA atten limit -- nValue is desired value */
2095 case MT2063_ACLNA_MAX:
2096 val =
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03002097 (state->
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03002098 reg[MT2063_REG_LNA_OV] & (u8) ~ 0x1F) | (nValue
2099 &
2100 0x1F);
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03002101 if (state->reg[MT2063_REG_LNA_OV] != val) {
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03002102 status |=
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03002103 MT2063_SetReg(state, MT2063_REG_LNA_OV,
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03002104 val);
2105 }
2106 break;
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03002107
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03002108 /* Set RF atten limit -- nValue is desired value */
2109 case MT2063_ACRF_MAX:
2110 val =
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03002111 (state->
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03002112 reg[MT2063_REG_RF_OV] & (u8) ~ 0x1F) | (nValue
2113 &
2114 0x1F);
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03002115 if (state->reg[MT2063_REG_RF_OV] != val) {
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03002116 status |=
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03002117 MT2063_SetReg(state, MT2063_REG_RF_OV, val);
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03002118 }
2119 break;
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03002120
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03002121 /* Set FIF atten limit -- nValue is desired value, max. 5 if no B3 */
2122 case MT2063_ACFIF_MAX:
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03002123 if (state->reg[MT2063_REG_PART_REV] != MT2063_B3
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03002124 && nValue > 5)
2125 nValue = 5;
2126 val =
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03002127 (state->
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03002128 reg[MT2063_REG_FIF_OV] & (u8) ~ 0x1F) | (nValue
2129 &
2130 0x1F);
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03002131 if (state->reg[MT2063_REG_FIF_OV] != val) {
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03002132 status |=
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03002133 MT2063_SetReg(state, MT2063_REG_FIF_OV,
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 case MT2063_DNC_OUTPUT_ENABLE:
2139 /* selects, which DNC output is used */
Mauro Carvalho Chehab29a0a4f2011-07-20 23:44:10 -03002140 switch (nValue) {
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03002141 case MT2063_DNC_NONE:
2142 {
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03002143 val = (state->reg[MT2063_REG_DNC_GAIN] & 0xFC) | 0x03; /* Set DNC1GC=3 */
2144 if (state->reg[MT2063_REG_DNC_GAIN] !=
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03002145 val)
2146 status |=
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03002147 MT2063_SetReg(state,
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03002148 MT2063_REG_DNC_GAIN,
2149 val);
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03002150
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03002151 val = (state->reg[MT2063_REG_VGA_GAIN] & 0xFC) | 0x03; /* Set DNC2GC=3 */
2152 if (state->reg[MT2063_REG_VGA_GAIN] !=
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03002153 val)
2154 status |=
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03002155 MT2063_SetReg(state,
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03002156 MT2063_REG_VGA_GAIN,
2157 val);
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03002158
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03002159 val = (state->reg[MT2063_REG_RSVD_20] & ~0x40); /* Set PD2MUX=0 */
2160 if (state->reg[MT2063_REG_RSVD_20] !=
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03002161 val)
2162 status |=
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03002163 MT2063_SetReg(state,
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03002164 MT2063_REG_RSVD_20,
2165 val);
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03002166
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03002167 break;
2168 }
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03002169 case MT2063_DNC_1:
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03002170 {
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03002171 val = (state->reg[MT2063_REG_DNC_GAIN] & 0xFC) | (DNC1GC[state->rcvr_mode] & 0x03); /* Set DNC1GC=x */
2172 if (state->reg[MT2063_REG_DNC_GAIN] !=
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03002173 val)
2174 status |=
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03002175 MT2063_SetReg(state,
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03002176 MT2063_REG_DNC_GAIN,
2177 val);
2178
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03002179 val = (state->reg[MT2063_REG_VGA_GAIN] & 0xFC) | 0x03; /* Set DNC2GC=3 */
2180 if (state->reg[MT2063_REG_VGA_GAIN] !=
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03002181 val)
2182 status |=
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03002183 MT2063_SetReg(state,
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03002184 MT2063_REG_VGA_GAIN,
2185 val);
2186
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03002187 val = (state->reg[MT2063_REG_RSVD_20] & ~0x40); /* Set PD2MUX=0 */
2188 if (state->reg[MT2063_REG_RSVD_20] !=
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03002189 val)
2190 status |=
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03002191 MT2063_SetReg(state,
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03002192 MT2063_REG_RSVD_20,
2193 val);
2194
2195 break;
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03002196 }
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03002197 case MT2063_DNC_2:
2198 {
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03002199 val = (state->reg[MT2063_REG_DNC_GAIN] & 0xFC) | 0x03; /* Set DNC1GC=3 */
2200 if (state->reg[MT2063_REG_DNC_GAIN] !=
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03002201 val)
2202 status |=
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03002203 MT2063_SetReg(state,
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03002204 MT2063_REG_DNC_GAIN,
2205 val);
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03002206
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03002207 val = (state->reg[MT2063_REG_VGA_GAIN] & 0xFC) | (DNC2GC[state->rcvr_mode] & 0x03); /* Set DNC2GC=x */
2208 if (state->reg[MT2063_REG_VGA_GAIN] !=
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03002209 val)
2210 status |=
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03002211 MT2063_SetReg(state,
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03002212 MT2063_REG_VGA_GAIN,
2213 val);
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03002214
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03002215 val = (state->reg[MT2063_REG_RSVD_20] | 0x40); /* Set PD2MUX=1 */
2216 if (state->reg[MT2063_REG_RSVD_20] !=
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03002217 val)
2218 status |=
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03002219 MT2063_SetReg(state,
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03002220 MT2063_REG_RSVD_20,
2221 val);
2222
2223 break;
2224 }
2225 case MT2063_DNC_BOTH:
2226 {
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03002227 val = (state->reg[MT2063_REG_DNC_GAIN] & 0xFC) | (DNC1GC[state->rcvr_mode] & 0x03); /* Set DNC1GC=x */
2228 if (state->reg[MT2063_REG_DNC_GAIN] !=
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03002229 val)
2230 status |=
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03002231 MT2063_SetReg(state,
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03002232 MT2063_REG_DNC_GAIN,
2233 val);
2234
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03002235 val = (state->reg[MT2063_REG_VGA_GAIN] & 0xFC) | (DNC2GC[state->rcvr_mode] & 0x03); /* Set DNC2GC=x */
2236 if (state->reg[MT2063_REG_VGA_GAIN] !=
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03002237 val)
2238 status |=
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03002239 MT2063_SetReg(state,
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03002240 MT2063_REG_VGA_GAIN,
2241 val);
2242
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03002243 val = (state->reg[MT2063_REG_RSVD_20] | 0x40); /* Set PD2MUX=1 */
2244 if (state->reg[MT2063_REG_RSVD_20] !=
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03002245 val)
2246 status |=
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03002247 MT2063_SetReg(state,
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03002248 MT2063_REG_RSVD_20,
2249 val);
2250
2251 break;
2252 }
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03002253 default:
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03002254 break;
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03002255 }
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03002256 break;
2257
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03002258 default:
2259 status |= -ERANGE;
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03002260 }
2261 return (status);
2262}
2263
2264/****************************************************************************
2265**
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03002266** Name: MT2063_ClearPowerMaskBits
2267**
2268** Description: Clears the power-down mask bits for various sections of
2269** the MT2063
2270**
2271** Parameters: h - Tuner handle (returned by MT2063_Open)
2272** Bits - Mask bits to be cleared.
2273**
2274** See definition of MT2063_Mask_Bits type for description
2275** of each of the power bits.
2276**
2277** Returns: status:
2278** MT_OK - No errors
2279** MT_INV_HANDLE - Invalid tuner handle
2280** MT_COMM_ERR - Serial bus communications error
2281**
2282** Dependencies: USERS MUST CALL MT2063_Open() FIRST!
2283**
2284** Revision History:
2285**
2286** SCR Date Author Description
2287** -------------------------------------------------------------------------
2288** 138 06-19-2007 DAD Ver 1.00: Initial, derived from mt2067_b.
2289**
2290****************************************************************************/
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03002291static u32 MT2063_ClearPowerMaskBits(struct mt2063_state *state, enum MT2063_Mask_Bits Bits)
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03002292{
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03002293 u32 status = 0; /* Status to be returned */
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03002294
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03002295 Bits = (enum MT2063_Mask_Bits)(Bits & MT2063_ALL_SD); /* Only valid bits for this tuner */
2296 if ((Bits & 0xFF00) != 0) {
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03002297 state->reg[MT2063_REG_PWR_2] &= ~(u8) (Bits >> 8);
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03002298 status |=
Mauro Carvalho Chehabe1de3d12011-07-21 02:46:49 -03002299 mt2063_write(state,
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03002300 MT2063_REG_PWR_2,
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03002301 &state->reg[MT2063_REG_PWR_2], 1);
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03002302 }
2303 if ((Bits & 0xFF) != 0) {
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03002304 state->reg[MT2063_REG_PWR_1] &= ~(u8) (Bits & 0xFF);
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03002305 status |=
Mauro Carvalho Chehabe1de3d12011-07-21 02:46:49 -03002306 mt2063_write(state,
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03002307 MT2063_REG_PWR_1,
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03002308 &state->reg[MT2063_REG_PWR_1], 1);
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03002309 }
2310
2311 return (status);
2312}
2313
2314/****************************************************************************
2315**
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03002316** Name: MT2063_SoftwareShutdown
2317**
2318** Description: Enables or disables software shutdown function. When
2319** Shutdown==1, any section whose power mask is set will be
2320** shutdown.
2321**
2322** Parameters: h - Tuner handle (returned by MT2063_Open)
2323** Shutdown - 1 = shutdown the masked sections, otherwise
2324** power all sections on
2325**
2326** Returns: status:
2327** MT_OK - No errors
2328** MT_INV_HANDLE - Invalid tuner handle
2329** MT_COMM_ERR - Serial bus communications error
2330**
2331** Dependencies: USERS MUST CALL MT2063_Open() FIRST!
2332**
2333** Revision History:
2334**
2335** SCR Date Author Description
2336** -------------------------------------------------------------------------
2337** 138 06-19-2007 DAD Ver 1.00: Initial, derived from mt2067_b.
2338** 01-03-2008 PINZ Ver 1.xx: Added a trigger of BYPATNUP for
2339** correct wakeup of the LNA
2340**
2341****************************************************************************/
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03002342static u32 MT2063_SoftwareShutdown(struct mt2063_state *state, u8 Shutdown)
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03002343{
Mauro Carvalho Chehab31e67fa2011-07-21 10:30:11 -03002344 u32 status; /* Status to be returned */
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03002345
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03002346 if (Shutdown == 1)
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03002347 state->reg[MT2063_REG_PWR_1] |= 0x04; /* Turn the bit on */
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03002348 else
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03002349 state->reg[MT2063_REG_PWR_1] &= ~0x04; /* Turn off the bit */
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03002350
Mauro Carvalho Chehab31e67fa2011-07-21 10:30:11 -03002351 status = mt2063_write(state,
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03002352 MT2063_REG_PWR_1,
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03002353 &state->reg[MT2063_REG_PWR_1], 1);
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03002354
2355 if (Shutdown != 1) {
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03002356 state->reg[MT2063_REG_BYP_CTRL] =
2357 (state->reg[MT2063_REG_BYP_CTRL] & 0x9F) | 0x40;
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03002358 status |=
Mauro Carvalho Chehabe1de3d12011-07-21 02:46:49 -03002359 mt2063_write(state,
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03002360 MT2063_REG_BYP_CTRL,
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03002361 &state->reg[MT2063_REG_BYP_CTRL],
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03002362 1);
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03002363 state->reg[MT2063_REG_BYP_CTRL] =
2364 (state->reg[MT2063_REG_BYP_CTRL] & 0x9F);
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03002365 status |=
Mauro Carvalho Chehabe1de3d12011-07-21 02:46:49 -03002366 mt2063_write(state,
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03002367 MT2063_REG_BYP_CTRL,
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03002368 &state->reg[MT2063_REG_BYP_CTRL],
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03002369 1);
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03002370 }
2371
Mauro Carvalho Chehab31e67fa2011-07-21 10:30:11 -03002372 return status;
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03002373}
2374
2375/****************************************************************************
2376**
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03002377** Name: MT2063_SetReg
2378**
2379** Description: Sets an MT2063 register.
2380**
2381** Parameters: h - Tuner handle (returned by MT2063_Open)
2382** reg - MT2063 register/subaddress location
2383** val - MT2063 register/subaddress value
2384**
2385** Returns: status:
2386** MT_OK - No errors
2387** MT_COMM_ERR - Serial bus communications error
2388** MT_INV_HANDLE - Invalid tuner handle
2389** MT_ARG_RANGE - Argument out of range
2390**
2391** Dependencies: USERS MUST CALL MT2063_Open() FIRST!
2392**
2393** Use this function if you need to override a default
2394** register value
2395**
2396** Revision History:
2397**
2398** SCR Date Author Description
2399** -------------------------------------------------------------------------
2400** 138 06-19-2007 DAD Ver 1.00: Initial, derived from mt2067_b.
2401**
2402****************************************************************************/
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03002403static u32 MT2063_SetReg(struct mt2063_state *state, u8 reg, u8 val)
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03002404{
Mauro Carvalho Chehab31e67fa2011-07-21 10:30:11 -03002405 u32 status;
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03002406
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03002407 if (reg >= MT2063_REG_END_REGS)
Mauro Carvalho Chehab31e67fa2011-07-21 10:30:11 -03002408 return -ERANGE;
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03002409
Mauro Carvalho Chehab31e67fa2011-07-21 10:30:11 -03002410 status = mt2063_write(state, reg, &val, 1);
2411 if (status < 0)
2412 return status;
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03002413
Mauro Carvalho Chehab31e67fa2011-07-21 10:30:11 -03002414 state->reg[reg] = val;
2415
2416 return 0;
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03002417}
2418
Mauro Carvalho Chehabcfde8922011-07-20 21:01:48 -03002419static u32 MT2063_Round_fLO(u32 f_LO, u32 f_LO_Step, u32 f_ref)
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03002420{
2421 return f_ref * (f_LO / f_ref)
2422 + f_LO_Step * (((f_LO % f_ref) + (f_LO_Step / 2)) / f_LO_Step);
2423}
2424
2425/****************************************************************************
2426**
2427** Name: fLO_FractionalTerm
2428**
2429** Description: Calculates the portion contributed by FracN / denom.
2430**
2431** This function preserves maximum precision without
2432** risk of overflow. It accurately calculates
2433** f_ref * num / denom to within 1 HZ with fixed math.
2434**
2435** Parameters: num - Fractional portion of the multiplier
2436** denom - denominator portion of the ratio
2437** This routine successfully handles denom values
2438** up to and including 2^18.
2439** f_Ref - SRO frequency. This calculation handles
2440** f_ref as two separate 14-bit fields.
2441** Therefore, a maximum value of 2^28-1
2442** may safely be used for f_ref. This is
2443** the genesis of the magic number "14" and the
2444** magic mask value of 0x03FFF.
2445**
2446** Returns: f_ref * num / denom
2447**
2448** Revision History:
2449**
2450** SCR Date Author Description
2451** -------------------------------------------------------------------------
2452** 138 06-19-2007 DAD Ver 1.00: Initial, derived from mt2067_b.
2453**
2454****************************************************************************/
Mauro Carvalho Chehabcfde8922011-07-20 21:01:48 -03002455static u32 MT2063_fLO_FractionalTerm(u32 f_ref,
2456 u32 num, u32 denom)
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03002457{
Mauro Carvalho Chehabcfde8922011-07-20 21:01:48 -03002458 u32 t1 = (f_ref >> 14) * num;
2459 u32 term1 = t1 / denom;
2460 u32 loss = t1 % denom;
2461 u32 term2 =
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03002462 (((f_ref & 0x00003FFF) * num + (loss << 14)) + (denom / 2)) / denom;
2463 return ((term1 << 14) + term2);
2464}
2465
2466/****************************************************************************
2467**
2468** Name: CalcLO1Mult
2469**
2470** Description: Calculates Integer divider value and the numerator
2471** value for a FracN PLL.
2472**
2473** This function assumes that the f_LO and f_Ref are
2474** evenly divisible by f_LO_Step.
2475**
2476** Parameters: Div - OUTPUT: Whole number portion of the multiplier
2477** FracN - OUTPUT: Fractional portion of the multiplier
2478** f_LO - desired LO frequency.
2479** f_LO_Step - Minimum step size for the LO (in Hz).
2480** f_Ref - SRO frequency.
2481** f_Avoid - Range of PLL frequencies to avoid near
2482** integer multiples of f_Ref (in Hz).
2483**
2484** Returns: Recalculated LO frequency.
2485**
2486** Revision History:
2487**
2488** SCR Date Author Description
2489** -------------------------------------------------------------------------
2490** 138 06-19-2007 DAD Ver 1.00: Initial, derived from mt2067_b.
2491**
2492****************************************************************************/
Mauro Carvalho Chehabcfde8922011-07-20 21:01:48 -03002493static u32 MT2063_CalcLO1Mult(u32 * Div,
2494 u32 * FracN,
2495 u32 f_LO,
2496 u32 f_LO_Step, u32 f_Ref)
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03002497{
2498 /* Calculate the whole number portion of the divider */
2499 *Div = f_LO / f_Ref;
2500
2501 /* Calculate the numerator value (round to nearest f_LO_Step) */
2502 *FracN =
2503 (64 * (((f_LO % f_Ref) + (f_LO_Step / 2)) / f_LO_Step) +
2504 (f_Ref / f_LO_Step / 2)) / (f_Ref / f_LO_Step);
2505
2506 return (f_Ref * (*Div)) + MT2063_fLO_FractionalTerm(f_Ref, *FracN, 64);
2507}
2508
2509/****************************************************************************
2510**
2511** Name: CalcLO2Mult
2512**
2513** Description: Calculates Integer divider value and the numerator
2514** value for a FracN PLL.
2515**
2516** This function assumes that the f_LO and f_Ref are
2517** evenly divisible by f_LO_Step.
2518**
2519** Parameters: Div - OUTPUT: Whole number portion of the multiplier
2520** FracN - OUTPUT: Fractional portion of the multiplier
2521** f_LO - desired LO frequency.
2522** f_LO_Step - Minimum step size for the LO (in Hz).
2523** f_Ref - SRO frequency.
2524** f_Avoid - Range of PLL frequencies to avoid near
2525** integer multiples of f_Ref (in Hz).
2526**
2527** Returns: Recalculated LO frequency.
2528**
2529** Revision History:
2530**
2531** SCR Date Author Description
2532** -------------------------------------------------------------------------
2533** 138 06-19-2007 DAD Ver 1.00: Initial, derived from mt2067_b.
2534**
2535****************************************************************************/
Mauro Carvalho Chehabcfde8922011-07-20 21:01:48 -03002536static u32 MT2063_CalcLO2Mult(u32 * Div,
2537 u32 * FracN,
2538 u32 f_LO,
2539 u32 f_LO_Step, u32 f_Ref)
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03002540{
2541 /* Calculate the whole number portion of the divider */
2542 *Div = f_LO / f_Ref;
2543
2544 /* Calculate the numerator value (round to nearest f_LO_Step) */
2545 *FracN =
2546 (8191 * (((f_LO % f_Ref) + (f_LO_Step / 2)) / f_LO_Step) +
2547 (f_Ref / f_LO_Step / 2)) / (f_Ref / f_LO_Step);
2548
2549 return (f_Ref * (*Div)) + MT2063_fLO_FractionalTerm(f_Ref, *FracN,
2550 8191);
2551}
2552
2553/****************************************************************************
2554**
2555** Name: FindClearTuneFilter
2556**
2557** Description: Calculate the corrrect ClearTune filter to be used for
2558** a given input frequency.
2559**
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03002560** Parameters: state - ptr to tuner data structure
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03002561** f_in - RF input center frequency (in Hz).
2562**
2563** Returns: ClearTune filter number (0-31)
2564**
2565** Dependencies: MUST CALL MT2064_Open BEFORE FindClearTuneFilter!
2566**
2567** Revision History:
2568**
2569** SCR Date Author Description
2570** -------------------------------------------------------------------------
2571** 04-10-2008 PINZ Ver 1.14: Use software-controlled ClearTune
2572** cross-over frequency values.
2573**
2574****************************************************************************/
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03002575static u32 FindClearTuneFilter(struct mt2063_state *state, u32 f_in)
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03002576{
Mauro Carvalho Chehabcfde8922011-07-20 21:01:48 -03002577 u32 RFBand;
2578 u32 idx; /* index loop */
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03002579
2580 /*
2581 ** Find RF Band setting
2582 */
2583 RFBand = 31; /* def when f_in > all */
2584 for (idx = 0; idx < 31; ++idx) {
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03002585 if (state->CTFiltMax[idx] >= f_in) {
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03002586 RFBand = idx;
2587 break;
2588 }
2589 }
Mauro Carvalho Chehab31e67fa2011-07-21 10:30:11 -03002590 return RFBand;
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03002591}
2592
2593/****************************************************************************
2594**
2595** Name: MT2063_Tune
2596**
2597** Description: Change the tuner's tuned frequency to RFin.
2598**
2599** Parameters: h - Open handle to the tuner (from MT2063_Open).
2600** f_in - RF input center frequency (in Hz).
2601**
2602** Returns: status:
2603** MT_OK - No errors
2604** MT_INV_HANDLE - Invalid tuner handle
2605** MT_UPC_UNLOCK - Upconverter PLL unlocked
2606** MT_DNC_UNLOCK - Downconverter PLL unlocked
2607** MT_COMM_ERR - Serial bus communications error
2608** MT_SPUR_CNT_MASK - Count of avoided LO spurs
2609** MT_SPUR_PRESENT - LO spur possible in output
2610** MT_FIN_RANGE - Input freq out of range
2611** MT_FOUT_RANGE - Output freq out of range
2612** MT_UPC_RANGE - Upconverter freq out of range
2613** MT_DNC_RANGE - Downconverter freq out of range
2614**
2615** Dependencies: MUST CALL MT2063_Open BEFORE MT2063_Tune!
2616**
2617** MT_ReadSub - Read data from the two-wire serial bus
2618** MT_WriteSub - Write data to the two-wire serial bus
2619** MT_Sleep - Delay execution for x milliseconds
2620** MT2063_GetLocked - Checks to see if LO1 and LO2 are locked
2621**
2622** Revision History:
2623**
2624** SCR Date Author Description
2625** -------------------------------------------------------------------------
2626** 138 06-19-2007 DAD Ver 1.00: Initial, derived from mt2067_b.
2627** 04-10-2008 PINZ Ver 1.05: Use software-controlled ClearTune
2628** cross-over frequency values.
2629** 175 I 16-06-2008 PINZ Ver 1.16: Add control to avoid US DECT freqs.
2630** 175 I 06-19-2008 RSK Ver 1.17: Refactor DECT control to SpurAvoid.
2631** 06-24-2008 PINZ Ver 1.18: Add Get/SetParam CTFILT_SW
2632**
2633****************************************************************************/
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03002634static u32 MT2063_Tune(struct mt2063_state *state, u32 f_in)
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03002635{ /* RF input center frequency */
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03002636
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03002637 u32 status = 0; /* status of operation */
Mauro Carvalho Chehabcfde8922011-07-20 21:01:48 -03002638 u32 LO1; /* 1st LO register value */
2639 u32 Num1; /* Numerator for LO1 reg. value */
2640 u32 f_IF1; /* 1st IF requested */
2641 u32 LO2; /* 2nd LO register value */
2642 u32 Num2; /* Numerator for LO2 reg. value */
2643 u32 ofLO1, ofLO2; /* last time's LO frequencies */
2644 u32 ofin, ofout; /* last time's I/O frequencies */
2645 u8 fiffc = 0x80; /* FIFF center freq from tuner */
2646 u32 fiffof; /* Offset from FIFF center freq */
2647 const u8 LO1LK = 0x80; /* Mask for LO1 Lock bit */
2648 u8 LO2LK = 0x08; /* Mask for LO2 Lock bit */
2649 u8 val;
2650 u32 RFBand;
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03002651
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03002652 /* Check the input and output frequency ranges */
2653 if ((f_in < MT2063_MIN_FIN_FREQ) || (f_in > MT2063_MAX_FIN_FREQ))
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03002654 return -EINVAL;
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03002655
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03002656 if ((state->AS_Data.f_out < MT2063_MIN_FOUT_FREQ)
2657 || (state->AS_Data.f_out > MT2063_MAX_FOUT_FREQ))
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03002658 return -EINVAL;
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03002659
2660 /*
2661 ** Save original LO1 and LO2 register values
2662 */
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03002663 ofLO1 = state->AS_Data.f_LO1;
2664 ofLO2 = state->AS_Data.f_LO2;
2665 ofin = state->AS_Data.f_in;
2666 ofout = state->AS_Data.f_out;
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03002667
2668 /*
2669 ** Find and set RF Band setting
2670 */
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03002671 if (state->ctfilt_sw == 1) {
2672 val = (state->reg[MT2063_REG_CTUNE_CTRL] | 0x08);
2673 if (state->reg[MT2063_REG_CTUNE_CTRL] != val) {
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03002674 status |=
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03002675 MT2063_SetReg(state, MT2063_REG_CTUNE_CTRL, val);
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03002676 }
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03002677 val = state->reg[MT2063_REG_CTUNE_OV];
2678 RFBand = FindClearTuneFilter(state, f_in);
2679 state->reg[MT2063_REG_CTUNE_OV] =
2680 (u8) ((state->reg[MT2063_REG_CTUNE_OV] & ~0x1F)
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03002681 | RFBand);
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03002682 if (state->reg[MT2063_REG_CTUNE_OV] != val) {
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03002683 status |=
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03002684 MT2063_SetReg(state, MT2063_REG_CTUNE_OV, val);
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03002685 }
2686 }
2687
2688 /*
2689 ** Read the FIFF Center Frequency from the tuner
2690 */
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03002691 if (status >= 0) {
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03002692 status |=
Mauro Carvalho Chehabe1de3d12011-07-21 02:46:49 -03002693 mt2063_read(state,
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03002694 MT2063_REG_FIFFC,
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03002695 &state->reg[MT2063_REG_FIFFC], 1);
2696 fiffc = state->reg[MT2063_REG_FIFFC];
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03002697 }
2698 /*
2699 ** Assign in the requested values
2700 */
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03002701 state->AS_Data.f_in = f_in;
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03002702 /* Request a 1st IF such that LO1 is on a step size */
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03002703 state->AS_Data.f_if1_Request =
2704 MT2063_Round_fLO(state->AS_Data.f_if1_Request + f_in,
2705 state->AS_Data.f_LO1_Step,
2706 state->AS_Data.f_ref) - f_in;
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03002707
2708 /*
2709 ** Calculate frequency settings. f_IF1_FREQ + f_in is the
2710 ** desired LO1 frequency
2711 */
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03002712 MT2063_ResetExclZones(&state->AS_Data);
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03002713
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03002714 f_IF1 = MT2063_ChooseFirstIF(&state->AS_Data);
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03002715
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03002716 state->AS_Data.f_LO1 =
2717 MT2063_Round_fLO(f_IF1 + f_in, state->AS_Data.f_LO1_Step,
2718 state->AS_Data.f_ref);
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03002719
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03002720 state->AS_Data.f_LO2 =
2721 MT2063_Round_fLO(state->AS_Data.f_LO1 - state->AS_Data.f_out - f_in,
2722 state->AS_Data.f_LO2_Step, state->AS_Data.f_ref);
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03002723
2724 /*
2725 ** Check for any LO spurs in the output bandwidth and adjust
2726 ** the LO settings to avoid them if needed
2727 */
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03002728 status |= MT2063_AvoidSpurs(state, &state->AS_Data);
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03002729 /*
2730 ** MT_AvoidSpurs spurs may have changed the LO1 & LO2 values.
2731 ** Recalculate the LO frequencies and the values to be placed
2732 ** in the tuning registers.
2733 */
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03002734 state->AS_Data.f_LO1 =
2735 MT2063_CalcLO1Mult(&LO1, &Num1, state->AS_Data.f_LO1,
2736 state->AS_Data.f_LO1_Step, state->AS_Data.f_ref);
2737 state->AS_Data.f_LO2 =
2738 MT2063_Round_fLO(state->AS_Data.f_LO1 - state->AS_Data.f_out - f_in,
2739 state->AS_Data.f_LO2_Step, state->AS_Data.f_ref);
2740 state->AS_Data.f_LO2 =
2741 MT2063_CalcLO2Mult(&LO2, &Num2, state->AS_Data.f_LO2,
2742 state->AS_Data.f_LO2_Step, state->AS_Data.f_ref);
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03002743
2744 /*
2745 ** Check the upconverter and downconverter frequency ranges
2746 */
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03002747 if ((state->AS_Data.f_LO1 < MT2063_MIN_UPC_FREQ)
2748 || (state->AS_Data.f_LO1 > MT2063_MAX_UPC_FREQ))
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03002749 status |= MT2063_UPC_RANGE;
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03002750 if ((state->AS_Data.f_LO2 < MT2063_MIN_DNC_FREQ)
2751 || (state->AS_Data.f_LO2 > MT2063_MAX_DNC_FREQ))
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03002752 status |= MT2063_DNC_RANGE;
2753 /* LO2 Lock bit was in a different place for B0 version */
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03002754 if (state->tuner_id == MT2063_B0)
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03002755 LO2LK = 0x40;
2756
2757 /*
2758 ** If we have the same LO frequencies and we're already locked,
2759 ** then skip re-programming the LO registers.
2760 */
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03002761 if ((ofLO1 != state->AS_Data.f_LO1)
2762 || (ofLO2 != state->AS_Data.f_LO2)
2763 || ((state->reg[MT2063_REG_LO_STATUS] & (LO1LK | LO2LK)) !=
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03002764 (LO1LK | LO2LK))) {
2765 /*
2766 ** Calculate the FIFFOF register value
2767 **
2768 ** IF1_Actual
2769 ** FIFFOF = ------------ - 8 * FIFFC - 4992
2770 ** f_ref/64
2771 */
2772 fiffof =
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03002773 (state->AS_Data.f_LO1 -
2774 f_in) / (state->AS_Data.f_ref / 64) - 8 * (u32) fiffc -
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03002775 4992;
2776 if (fiffof > 0xFF)
2777 fiffof = 0xFF;
2778
2779 /*
2780 ** Place all of the calculated values into the local tuner
2781 ** register fields.
2782 */
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03002783 if (status >= 0) {
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03002784 state->reg[MT2063_REG_LO1CQ_1] = (u8) (LO1 & 0xFF); /* DIV1q */
2785 state->reg[MT2063_REG_LO1CQ_2] = (u8) (Num1 & 0x3F); /* NUM1q */
2786 state->reg[MT2063_REG_LO2CQ_1] = (u8) (((LO2 & 0x7F) << 1) /* DIV2q */
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03002787 |(Num2 >> 12)); /* NUM2q (hi) */
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03002788 state->reg[MT2063_REG_LO2CQ_2] = (u8) ((Num2 & 0x0FF0) >> 4); /* NUM2q (mid) */
2789 state->reg[MT2063_REG_LO2CQ_3] = (u8) (0xE0 | (Num2 & 0x000F)); /* NUM2q (lo) */
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03002790
2791 /*
2792 ** Now write out the computed register values
2793 ** IMPORTANT: There is a required order for writing
2794 ** (0x05 must follow all the others).
2795 */
Mauro Carvalho Chehabe1de3d12011-07-21 02:46:49 -03002796 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 -03002797 if (state->tuner_id == MT2063_B0) {
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03002798 /* Re-write the one-shot bits to trigger the tune operation */
Mauro Carvalho Chehabe1de3d12011-07-21 02:46:49 -03002799 status |= mt2063_write(state, MT2063_REG_LO2CQ_3, &state->reg[MT2063_REG_LO2CQ_3], 1); /* 0x05 */
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03002800 }
2801 /* Write out the FIFF offset only if it's changing */
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03002802 if (state->reg[MT2063_REG_FIFF_OFFSET] !=
Mauro Carvalho Chehabcfde8922011-07-20 21:01:48 -03002803 (u8) fiffof) {
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03002804 state->reg[MT2063_REG_FIFF_OFFSET] =
Mauro Carvalho Chehabcfde8922011-07-20 21:01:48 -03002805 (u8) fiffof;
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03002806 status |=
Mauro Carvalho Chehabe1de3d12011-07-21 02:46:49 -03002807 mt2063_write(state,
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03002808 MT2063_REG_FIFF_OFFSET,
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03002809 &state->
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03002810 reg[MT2063_REG_FIFF_OFFSET],
2811 1);
2812 }
2813 }
2814
2815 /*
2816 ** Check for LO's locking
2817 */
2818
Mauro Carvalho Chehab31e67fa2011-07-21 10:30:11 -03002819 if (status < 0)
2820 return status;
2821
2822 status = mt2063_lockStatus(state);
2823 if (status < 0)
2824 return status;
2825 if (!status)
2826 return -EINVAL; /* Couldn't lock */
2827
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03002828 /*
Mauro Carvalho Chehab31e67fa2011-07-21 10:30:11 -03002829 * If we locked OK, assign calculated data to mt2063_state structure
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03002830 */
Mauro Carvalho Chehab31e67fa2011-07-21 10:30:11 -03002831 state->f_IF1_actual = state->AS_Data.f_LO1 - f_in;
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03002832 }
2833
Mauro Carvalho Chehab31e67fa2011-07-21 10:30:11 -03002834 return status;
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03002835}
2836
Mauro Carvalho Chehabfad11db2011-07-21 10:35:30 -03002837unsigned int mt2063_setTune(void *h, u32 f_in, u32 bw_in,
2838 enum MTTune_atv_standard tv_type)
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03002839{
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03002840 u32 status = 0;
Mauro Carvalho Chehabcfde8922011-07-20 21:01:48 -03002841 s32 pict_car = 0;
2842 s32 pict2chanb_vsb = 0;
2843 s32 pict2chanb_snd = 0;
2844 s32 pict2snd1 = 0;
2845 s32 pict2snd2 = 0;
2846 s32 ch_bw = 0;
Mauro Carvalho Chehabcfde8922011-07-20 21:01:48 -03002847 s32 if_mid = 0;
2848 s32 rcvr_mode = 0;
2849 u32 mode_get = 0;
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03002850
2851 switch (tv_type) {
2852 case MTTUNEA_PAL_B:{
2853 pict_car = 38900000;
2854 ch_bw = 8000000;
2855 pict2chanb_vsb = -1250000;
2856 pict2snd1 = 5500000;
2857 pict2snd2 = 5742000;
2858 rcvr_mode = 1;
2859 break;
2860 }
2861 case MTTUNEA_PAL_G:{
2862 pict_car = 38900000;
2863 ch_bw = 7000000;
2864 pict2chanb_vsb = -1250000;
2865 pict2snd1 = 5500000;
2866 pict2snd2 = 0;
2867 rcvr_mode = 1;
2868 break;
2869 }
2870 case MTTUNEA_PAL_I:{
2871 pict_car = 38900000;
2872 ch_bw = 8000000;
2873 pict2chanb_vsb = -1250000;
2874 pict2snd1 = 6000000;
2875 pict2snd2 = 0;
2876 rcvr_mode = 1;
2877 break;
2878 }
2879 case MTTUNEA_PAL_L:{
2880 pict_car = 38900000;
2881 ch_bw = 8000000;
2882 pict2chanb_vsb = -1250000;
2883 pict2snd1 = 6500000;
2884 pict2snd2 = 0;
2885 rcvr_mode = 1;
2886 break;
2887 }
2888 case MTTUNEA_PAL_MN:{
2889 pict_car = 38900000;
2890 ch_bw = 6000000;
2891 pict2chanb_vsb = -1250000;
2892 pict2snd1 = 4500000;
2893 pict2snd2 = 0;
2894 rcvr_mode = 1;
2895 break;
2896 }
2897 case MTTUNEA_PAL_DK:{
2898 pict_car = 38900000;
2899 ch_bw = 8000000;
2900 pict2chanb_vsb = -1250000;
2901 pict2snd1 = 6500000;
2902 pict2snd2 = 0;
2903 rcvr_mode = 1;
2904 break;
2905 }
2906 case MTTUNEA_DIGITAL:{
2907 pict_car = 36125000;
2908 ch_bw = 8000000;
2909 pict2chanb_vsb = -(ch_bw / 2);
2910 pict2snd1 = 0;
2911 pict2snd2 = 0;
2912 rcvr_mode = 2;
2913 break;
2914 }
2915 case MTTUNEA_FMRADIO:{
2916 pict_car = 38900000;
2917 ch_bw = 8000000;
2918 pict2chanb_vsb = -(ch_bw / 2);
2919 pict2snd1 = 0;
2920 pict2snd2 = 0;
2921 rcvr_mode = 4;
2922 //f_in -= 2900000;
2923 break;
2924 }
2925 case MTTUNEA_DVBC:{
2926 pict_car = 36125000;
2927 ch_bw = 8000000;
2928 pict2chanb_vsb = -(ch_bw / 2);
2929 pict2snd1 = 0;
2930 pict2snd2 = 0;
2931 rcvr_mode = MT2063_CABLE_QAM;
2932 break;
2933 }
2934 case MTTUNEA_DVBT:{
2935 pict_car = 36125000;
2936 ch_bw = bw_in; //8000000
2937 pict2chanb_vsb = -(ch_bw / 2);
2938 pict2snd1 = 0;
2939 pict2snd2 = 0;
2940 rcvr_mode = MT2063_OFFAIR_COFDM;
2941 break;
2942 }
2943 case MTTUNEA_UNKNOWN:
2944 break;
2945 default:
2946 break;
2947 }
2948
2949 pict2chanb_snd = pict2chanb_vsb - ch_bw;
2950 if_mid = pict_car - (pict2chanb_vsb + (ch_bw / 2));
2951
2952 status |= MT2063_SetParam(h, MT2063_STEPSIZE, 125000);
2953 status |= MT2063_SetParam(h, MT2063_OUTPUT_FREQ, if_mid);
2954 status |= MT2063_SetParam(h, MT2063_OUTPUT_BW, ch_bw);
2955 status |= MT2063_GetParam(h, MT2063_RCVR_MODE, &mode_get);
2956
2957 status |= MT2063_SetParam(h, MT2063_RCVR_MODE, rcvr_mode);
2958 status |= MT2063_Tune(h, (f_in + (pict2chanb_vsb + (ch_bw / 2))));
2959 status |= MT2063_GetParam(h, MT2063_RCVR_MODE, &mode_get);
2960
Mauro Carvalho Chehabcfde8922011-07-20 21:01:48 -03002961 return (u32) status;
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03002962}
2963
Mauro Carvalho Chehab01e0daf2011-07-21 03:20:43 -03002964static const u8 MT2063B0_defaults[] = {
2965 /* Reg, Value */
2966 0x19, 0x05,
2967 0x1B, 0x1D,
2968 0x1C, 0x1F,
2969 0x1D, 0x0F,
2970 0x1E, 0x3F,
2971 0x1F, 0x0F,
2972 0x20, 0x3F,
2973 0x22, 0x21,
2974 0x23, 0x3F,
2975 0x24, 0x20,
2976 0x25, 0x3F,
2977 0x27, 0xEE,
2978 0x2C, 0x27, /* bit at 0x20 is cleared below */
2979 0x30, 0x03,
2980 0x2C, 0x07, /* bit at 0x20 is cleared here */
2981 0x2D, 0x87,
2982 0x2E, 0xAA,
2983 0x28, 0xE1, /* Set the FIFCrst bit here */
2984 0x28, 0xE0, /* Clear the FIFCrst bit here */
2985 0x00
2986};
2987
2988/* writing 0x05 0xf0 sw-resets all registers, so we write only needed changes */
2989static const u8 MT2063B1_defaults[] = {
2990 /* Reg, Value */
2991 0x05, 0xF0,
2992 0x11, 0x10, /* New Enable AFCsd */
2993 0x19, 0x05,
2994 0x1A, 0x6C,
2995 0x1B, 0x24,
2996 0x1C, 0x28,
2997 0x1D, 0x8F,
2998 0x1E, 0x14,
2999 0x1F, 0x8F,
3000 0x20, 0x57,
3001 0x22, 0x21, /* New - ver 1.03 */
3002 0x23, 0x3C, /* New - ver 1.10 */
3003 0x24, 0x20, /* New - ver 1.03 */
3004 0x2C, 0x24, /* bit at 0x20 is cleared below */
3005 0x2D, 0x87, /* FIFFQ=0 */
3006 0x2F, 0xF3,
3007 0x30, 0x0C, /* New - ver 1.11 */
3008 0x31, 0x1B, /* New - ver 1.11 */
3009 0x2C, 0x04, /* bit at 0x20 is cleared here */
3010 0x28, 0xE1, /* Set the FIFCrst bit here */
3011 0x28, 0xE0, /* Clear the FIFCrst bit here */
3012 0x00
3013};
3014
3015/* writing 0x05 0xf0 sw-resets all registers, so we write only needed changes */
3016static const u8 MT2063B3_defaults[] = {
3017 /* Reg, Value */
3018 0x05, 0xF0,
3019 0x19, 0x3D,
3020 0x2C, 0x24, /* bit at 0x20 is cleared below */
3021 0x2C, 0x04, /* bit at 0x20 is cleared here */
3022 0x28, 0xE1, /* Set the FIFCrst bit here */
3023 0x28, 0xE0, /* Clear the FIFCrst bit here */
3024 0x00
3025};
3026
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03003027static int mt2063_init(struct dvb_frontend *fe)
3028{
Mauro Carvalho Chehab01e0daf2011-07-21 03:20:43 -03003029 u32 status;
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03003030 struct mt2063_state *state = fe->tuner_priv;
Mauro Carvalho Chehab01e0daf2011-07-21 03:20:43 -03003031 u8 all_resets = 0xF0; /* reset/load bits */
3032 const u8 *def = NULL;
3033 u32 FCRUN;
3034 s32 maxReads;
3035 u32 fcu_osc;
3036 u32 i;
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03003037
Mauro Carvalho Chehab01e0daf2011-07-21 03:20:43 -03003038 state->rcvr_mode = MT2063_CABLE_QAM;
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03003039
Mauro Carvalho Chehab01e0daf2011-07-21 03:20:43 -03003040 /* Read the Part/Rev code from the tuner */
3041 status = mt2063_read(state, MT2063_REG_PART_REV, state->reg, 1);
3042 if (status < 0)
3043 return status;
3044
3045 /* Check the part/rev code */
3046 if (((state->reg[MT2063_REG_PART_REV] != MT2063_B0) /* MT2063 B0 */
3047 &&(state->reg[MT2063_REG_PART_REV] != MT2063_B1) /* MT2063 B1 */
3048 &&(state->reg[MT2063_REG_PART_REV] != MT2063_B3))) /* MT2063 B3 */
3049 return -ENODEV; /* Wrong tuner Part/Rev code */
3050
3051 /* Check the 2nd byte of the Part/Rev code from the tuner */
3052 status = mt2063_read(state, MT2063_REG_RSVD_3B,
3053 &state->reg[MT2063_REG_RSVD_3B], 1);
3054
3055 /* b7 != 0 ==> NOT MT2063 */
3056 if (status < 0 ||((state->reg[MT2063_REG_RSVD_3B] & 0x80) != 0x00))
3057 return -ENODEV; /* Wrong tuner Part/Rev code */
3058
3059 /* Reset the tuner */
3060 status = mt2063_write(state, MT2063_REG_LO2CQ_3, &all_resets, 1);
3061 if (status < 0)
3062 return status;
3063
3064 /* change all of the default values that vary from the HW reset values */
3065 /* def = (state->reg[PART_REV] == MT2063_B0) ? MT2063B0_defaults : MT2063B1_defaults; */
3066 switch (state->reg[MT2063_REG_PART_REV]) {
3067 case MT2063_B3:
3068 def = MT2063B3_defaults;
3069 break;
3070
3071 case MT2063_B1:
3072 def = MT2063B1_defaults;
3073 break;
3074
3075 case MT2063_B0:
3076 def = MT2063B0_defaults;
3077 break;
3078
3079 default:
3080 return -ENODEV;
3081 break;
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03003082 }
3083
Mauro Carvalho Chehab01e0daf2011-07-21 03:20:43 -03003084 while (status >= 0 && *def) {
3085 u8 reg = *def++;
3086 u8 val = *def++;
3087 status = mt2063_write(state, reg, &val, 1);
3088 }
3089 if (status < 0)
3090 return status;
3091
3092 /* Wait for FIFF location to complete. */
3093 FCRUN = 1;
3094 maxReads = 10;
3095 while (status >= 0 && (FCRUN != 0) && (maxReads-- > 0)) {
3096 msleep(2);
3097 status = mt2063_read(state,
3098 MT2063_REG_XO_STATUS,
3099 &state->
3100 reg[MT2063_REG_XO_STATUS], 1);
3101 FCRUN = (state->reg[MT2063_REG_XO_STATUS] & 0x40) >> 6;
3102 }
3103
3104 if (FCRUN != 0 || status < 0)
3105 return -ENODEV;
3106
3107 status = mt2063_read(state,
3108 MT2063_REG_FIFFC,
3109 &state->reg[MT2063_REG_FIFFC], 1);
3110 if (status < 0)
3111 return status;
3112
3113 /* Read back all the registers from the tuner */
3114 status = mt2063_read(state,
3115 MT2063_REG_PART_REV,
3116 state->reg, MT2063_REG_END_REGS);
3117 if (status < 0)
3118 return status;
3119
3120 /* Initialize the tuner state. */
3121 state->tuner_id = state->reg[MT2063_REG_PART_REV];
3122 state->AS_Data.f_ref = MT2063_REF_FREQ;
3123 state->AS_Data.f_if1_Center = (state->AS_Data.f_ref / 8) *
3124 ((u32) state->reg[MT2063_REG_FIFFC] + 640);
3125 state->AS_Data.f_if1_bw = MT2063_IF1_BW;
3126 state->AS_Data.f_out = 43750000UL;
3127 state->AS_Data.f_out_bw = 6750000UL;
3128 state->AS_Data.f_zif_bw = MT2063_ZIF_BW;
3129 state->AS_Data.f_LO1_Step = state->AS_Data.f_ref / 64;
3130 state->AS_Data.f_LO2_Step = MT2063_TUNE_STEP_SIZE;
3131 state->AS_Data.maxH1 = MT2063_MAX_HARMONICS_1;
3132 state->AS_Data.maxH2 = MT2063_MAX_HARMONICS_2;
3133 state->AS_Data.f_min_LO_Separation = MT2063_MIN_LO_SEP;
3134 state->AS_Data.f_if1_Request = state->AS_Data.f_if1_Center;
3135 state->AS_Data.f_LO1 = 2181000000UL;
3136 state->AS_Data.f_LO2 = 1486249786UL;
3137 state->f_IF1_actual = state->AS_Data.f_if1_Center;
3138 state->AS_Data.f_in = state->AS_Data.f_LO1 - state->f_IF1_actual;
3139 state->AS_Data.f_LO1_FracN_Avoid = MT2063_LO1_FRACN_AVOID;
3140 state->AS_Data.f_LO2_FracN_Avoid = MT2063_LO2_FRACN_AVOID;
3141 state->num_regs = MT2063_REG_END_REGS;
3142 state->AS_Data.avoidDECT = MT2063_AVOID_BOTH;
3143 state->ctfilt_sw = 0;
3144
3145 state->CTFiltMax[0] = 69230000;
3146 state->CTFiltMax[1] = 105770000;
3147 state->CTFiltMax[2] = 140350000;
3148 state->CTFiltMax[3] = 177110000;
3149 state->CTFiltMax[4] = 212860000;
3150 state->CTFiltMax[5] = 241130000;
3151 state->CTFiltMax[6] = 274370000;
3152 state->CTFiltMax[7] = 309820000;
3153 state->CTFiltMax[8] = 342450000;
3154 state->CTFiltMax[9] = 378870000;
3155 state->CTFiltMax[10] = 416210000;
3156 state->CTFiltMax[11] = 456500000;
3157 state->CTFiltMax[12] = 495790000;
3158 state->CTFiltMax[13] = 534530000;
3159 state->CTFiltMax[14] = 572610000;
3160 state->CTFiltMax[15] = 598970000;
3161 state->CTFiltMax[16] = 635910000;
3162 state->CTFiltMax[17] = 672130000;
3163 state->CTFiltMax[18] = 714840000;
3164 state->CTFiltMax[19] = 739660000;
3165 state->CTFiltMax[20] = 770410000;
3166 state->CTFiltMax[21] = 814660000;
3167 state->CTFiltMax[22] = 846950000;
3168 state->CTFiltMax[23] = 867820000;
3169 state->CTFiltMax[24] = 915980000;
3170 state->CTFiltMax[25] = 947450000;
3171 state->CTFiltMax[26] = 983110000;
3172 state->CTFiltMax[27] = 1021630000;
3173 state->CTFiltMax[28] = 1061870000;
3174 state->CTFiltMax[29] = 1098330000;
3175 state->CTFiltMax[30] = 1138990000;
3176
3177 /*
3178 ** Fetch the FCU osc value and use it and the fRef value to
3179 ** scale all of the Band Max values
3180 */
3181
3182 state->reg[MT2063_REG_CTUNE_CTRL] = 0x0A;
3183 status = mt2063_write(state, MT2063_REG_CTUNE_CTRL,
3184 &state->reg[MT2063_REG_CTUNE_CTRL], 1);
3185 if (status < 0)
3186 return status;
3187
3188 /* Read the ClearTune filter calibration value */
3189 status = mt2063_read(state, MT2063_REG_FIFFC,
3190 &state->reg[MT2063_REG_FIFFC], 1);
3191 if (status < 0)
3192 return status;
3193
3194 fcu_osc = state->reg[MT2063_REG_FIFFC];
3195
3196 state->reg[MT2063_REG_CTUNE_CTRL] = 0x00;
3197 status = mt2063_write(state, MT2063_REG_CTUNE_CTRL,
3198 &state->reg[MT2063_REG_CTUNE_CTRL], 1);
3199 if (status < 0)
3200 return status;
3201
3202 /* Adjust each of the values in the ClearTune filter cross-over table */
3203 for (i = 0; i < 31; i++)
3204 state->CTFiltMax[i] =(state->CTFiltMax[i] / 768) * (fcu_osc + 640);
3205
3206 status = MT2063_SoftwareShutdown(state, 1);
3207 if (status < 0)
3208 return status;
3209 status = MT2063_ClearPowerMaskBits(state, MT2063_ALL_SD);
3210 if (status < 0)
3211 return status;
3212
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03003213 return 0;
3214}
3215
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03003216static int mt2063_get_status(struct dvb_frontend *fe, u32 * status)
3217{
3218 int rc = 0;
3219
3220 //get tuner lock status
3221
3222 return rc;
3223}
3224
3225static int mt2063_get_state(struct dvb_frontend *fe,
Mauro Carvalho Chehab51f0f7b2011-07-21 02:24:18 -03003226 enum tuner_param param, struct tuner_state *tunstate)
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03003227{
Mauro Carvalho Chehab51f0f7b2011-07-21 02:24:18 -03003228 struct mt2063_state *state = fe->tuner_priv;
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03003229
Mauro Carvalho Chehab223c7b02011-07-20 19:48:59 -03003230 switch (param) {
3231 case DVBFE_TUNER_FREQUENCY:
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03003232 //get frequency
Mauro Carvalho Chehab223c7b02011-07-20 19:48:59 -03003233 break;
3234 case DVBFE_TUNER_TUNERSTEP:
3235 break;
3236 case DVBFE_TUNER_IFFREQ:
3237 break;
3238 case DVBFE_TUNER_BANDWIDTH:
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03003239 //get bandwidth
Mauro Carvalho Chehab223c7b02011-07-20 19:48:59 -03003240 break;
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03003241 case DVBFE_TUNER_REFCLOCK:
Mauro Carvalho Chehab31e67fa2011-07-21 10:30:11 -03003242 tunstate->refclock = mt2063_lockStatus(state);
Mauro Carvalho Chehab223c7b02011-07-20 19:48:59 -03003243 break;
3244 default:
3245 break;
3246 }
3247
Mauro Carvalho Chehab51f0f7b2011-07-21 02:24:18 -03003248 return (int)tunstate->refclock;
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03003249}
3250
3251static int mt2063_set_state(struct dvb_frontend *fe,
Mauro Carvalho Chehab51f0f7b2011-07-21 02:24:18 -03003252 enum tuner_param param, struct tuner_state *tunstate)
Mauro Carvalho Chehab223c7b02011-07-20 19:48:59 -03003253{
Mauro Carvalho Chehab51f0f7b2011-07-21 02:24:18 -03003254 struct mt2063_state *state = fe->tuner_priv;
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03003255 u32 status = 0;
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03003256
Mauro Carvalho Chehab223c7b02011-07-20 19:48:59 -03003257 switch (param) {
3258 case DVBFE_TUNER_FREQUENCY:
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03003259 //set frequency
3260
3261 status =
Mauro Carvalho Chehabfad11db2011-07-21 10:35:30 -03003262 mt2063_setTune(state,
Mauro Carvalho Chehab51f0f7b2011-07-21 02:24:18 -03003263 tunstate->frequency, tunstate->bandwidth,
3264 state->tv_type);
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03003265
Mauro Carvalho Chehab51f0f7b2011-07-21 02:24:18 -03003266 state->frequency = tunstate->frequency;
Mauro Carvalho Chehab223c7b02011-07-20 19:48:59 -03003267 break;
3268 case DVBFE_TUNER_TUNERSTEP:
3269 break;
3270 case DVBFE_TUNER_IFFREQ:
3271 break;
3272 case DVBFE_TUNER_BANDWIDTH:
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03003273 //set bandwidth
Mauro Carvalho Chehab51f0f7b2011-07-21 02:24:18 -03003274 state->bandwidth = tunstate->bandwidth;
Mauro Carvalho Chehab223c7b02011-07-20 19:48:59 -03003275 break;
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03003276 case DVBFE_TUNER_REFCLOCK:
3277
3278 break;
Mauro Carvalho Chehab223c7b02011-07-20 19:48:59 -03003279 default:
3280 break;
3281 }
3282
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03003283 return (int)status;
3284}
3285
3286static int mt2063_release(struct dvb_frontend *fe)
Mauro Carvalho Chehab223c7b02011-07-20 19:48:59 -03003287{
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03003288 struct mt2063_state *state = fe->tuner_priv;
Mauro Carvalho Chehab223c7b02011-07-20 19:48:59 -03003289
3290 fe->tuner_priv = NULL;
3291 kfree(state);
3292
3293 return 0;
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03003294}
Mauro Carvalho Chehab223c7b02011-07-20 19:48:59 -03003295
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03003296static struct dvb_tuner_ops mt2063_ops = {
3297 .info = {
3298 .name = "MT2063 Silicon Tuner",
3299 .frequency_min = 45000000,
3300 .frequency_max = 850000000,
3301 .frequency_step = 0,
3302 },
3303
3304 .init = mt2063_init,
Mauro Carvalho Chehabbf975552011-07-20 21:43:30 -03003305 .sleep = MT2063_Sleep,
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03003306 .get_status = mt2063_get_status,
3307 .get_state = mt2063_get_state,
3308 .set_state = mt2063_set_state,
3309 .release = mt2063_release
Mauro Carvalho Chehab223c7b02011-07-20 19:48:59 -03003310};
3311
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03003312struct dvb_frontend *mt2063_attach(struct dvb_frontend *fe,
3313 struct mt2063_config *config,
3314 struct i2c_adapter *i2c)
Mauro Carvalho Chehab223c7b02011-07-20 19:48:59 -03003315{
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03003316 struct mt2063_state *state = NULL;
Mauro Carvalho Chehab223c7b02011-07-20 19:48:59 -03003317
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03003318 state = kzalloc(sizeof(struct mt2063_state), GFP_KERNEL);
Mauro Carvalho Chehab223c7b02011-07-20 19:48:59 -03003319 if (state == NULL)
3320 goto error;
3321
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03003322 state->config = config;
3323 state->i2c = i2c;
3324 state->frontend = fe;
3325 state->reference = config->refclock / 1000; /* kHz */
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03003326 fe->tuner_priv = state;
3327 fe->ops.tuner_ops = mt2063_ops;
Mauro Carvalho Chehab223c7b02011-07-20 19:48:59 -03003328
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03003329 printk("%s: Attaching MT2063 \n", __func__);
Mauro Carvalho Chehab223c7b02011-07-20 19:48:59 -03003330 return fe;
3331
3332error:
3333 kfree(state);
3334 return NULL;
3335}
3336
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03003337EXPORT_SYMBOL(mt2063_attach);
Mauro Carvalho Chehab223c7b02011-07-20 19:48:59 -03003338MODULE_PARM_DESC(verbose, "Set Verbosity level");
3339
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03003340MODULE_AUTHOR("Henry");
3341MODULE_DESCRIPTION("MT2063 Silicon tuner");
3342MODULE_LICENSE("GPL");