1// SPDX-License-Identifier: GPL-2.0-or-later
2/*
3 * mxl5007t.c - driver for the MaxLinear MxL5007T silicon tuner
4 *
5 * Copyright (C) 2008, 2009 Michael Krufky <mkrufky@linuxtv.org>
6 */
7
8#include <linux/i2c.h>
9#include <linux/types.h>
10#include <linux/videodev2.h>
11#include "tuner-i2c.h"
12#include "mxl5007t.h"
13
14static DEFINE_MUTEX(mxl5007t_list_mutex);
15static LIST_HEAD(hybrid_tuner_instance_list);
16
17static int mxl5007t_debug;
18module_param_named(debug, mxl5007t_debug, int, 0644);
19MODULE_PARM_DESC(debug, "set debug level");
20
21/* ------------------------------------------------------------------------- */
22
23#define mxl_printk(kern, fmt, arg...) \
24 printk(kern "%s: " fmt "\n", __func__, ##arg)
25
26#define mxl_err(fmt, arg...) \
27 mxl_printk(KERN_ERR, "%d: " fmt, __LINE__, ##arg)
28
29#define mxl_warn(fmt, arg...) \
30 mxl_printk(KERN_WARNING, fmt, ##arg)
31
32#define mxl_info(fmt, arg...) \
33 mxl_printk(KERN_INFO, fmt, ##arg)
34
35#define mxl_debug(fmt, arg...) \
36({ \
37 if (mxl5007t_debug) \
38 mxl_printk(KERN_DEBUG, fmt, ##arg); \
39})
40
41#define mxl_fail(ret) \
42({ \
43 int __ret; \
44 __ret = (ret < 0); \
45 if (__ret) \
46 mxl_printk(KERN_ERR, "error %d on line %d", \
47 ret, __LINE__); \
48 __ret; \
49})
50
51/* ------------------------------------------------------------------------- */
52
53enum mxl5007t_mode {
54 MxL_MODE_ISDBT = 0,
55 MxL_MODE_DVBT = 1,
56 MxL_MODE_ATSC = 2,
57 MxL_MODE_CABLE = 0x10,
58};
59
60enum mxl5007t_chip_version {
61 MxL_UNKNOWN_ID = 0x00,
62 MxL_5007_V1_F1 = 0x11,
63 MxL_5007_V1_F2 = 0x12,
64 MxL_5007_V4 = 0x14,
65 MxL_5007_V2_100_F1 = 0x21,
66 MxL_5007_V2_100_F2 = 0x22,
67 MxL_5007_V2_200_F1 = 0x23,
68 MxL_5007_V2_200_F2 = 0x24,
69};
70
71struct reg_pair_t {
72 u8 reg;
73 u8 val;
74};
75
76/* ------------------------------------------------------------------------- */
77
78static struct reg_pair_t init_tab[] = {
79 { 0x02, 0x06 },
80 { 0x03, 0x48 },
81 { 0x05, 0x04 },
82 { 0x06, 0x10 },
83 { 0x2e, 0x15 }, /* OVERRIDE */
84 { 0x30, 0x10 }, /* OVERRIDE */
85 { 0x45, 0x58 }, /* OVERRIDE */
86 { 0x48, 0x19 }, /* OVERRIDE */
87 { 0x52, 0x03 }, /* OVERRIDE */
88 { 0x53, 0x44 }, /* OVERRIDE */
89 { 0x6a, 0x4b }, /* OVERRIDE */
90 { 0x76, 0x00 }, /* OVERRIDE */
91 { 0x78, 0x18 }, /* OVERRIDE */
92 { 0x7a, 0x17 }, /* OVERRIDE */
93 { 0x85, 0x06 }, /* OVERRIDE */
94 { 0x01, 0x01 }, /* TOP_MASTER_ENABLE */
95 { 0, 0 }
96};
97
98static struct reg_pair_t init_tab_cable[] = {
99 { 0x02, 0x06 },
100 { 0x03, 0x48 },
101 { 0x05, 0x04 },
102 { 0x06, 0x10 },
103 { 0x09, 0x3f },
104 { 0x0a, 0x3f },
105 { 0x0b, 0x3f },
106 { 0x2e, 0x15 }, /* OVERRIDE */
107 { 0x30, 0x10 }, /* OVERRIDE */
108 { 0x45, 0x58 }, /* OVERRIDE */
109 { 0x48, 0x19 }, /* OVERRIDE */
110 { 0x52, 0x03 }, /* OVERRIDE */
111 { 0x53, 0x44 }, /* OVERRIDE */
112 { 0x6a, 0x4b }, /* OVERRIDE */
113 { 0x76, 0x00 }, /* OVERRIDE */
114 { 0x78, 0x18 }, /* OVERRIDE */
115 { 0x7a, 0x17 }, /* OVERRIDE */
116 { 0x85, 0x06 }, /* OVERRIDE */
117 { 0x01, 0x01 }, /* TOP_MASTER_ENABLE */
118 { 0, 0 }
119};
120
121/* ------------------------------------------------------------------------- */
122
123static struct reg_pair_t reg_pair_rftune[] = {
124 { 0x0f, 0x00 }, /* abort tune */
125 { 0x0c, 0x15 },
126 { 0x0d, 0x40 },
127 { 0x0e, 0x0e },
128 { 0x1f, 0x87 }, /* OVERRIDE */
129 { 0x20, 0x1f }, /* OVERRIDE */
130 { 0x21, 0x87 }, /* OVERRIDE */
131 { 0x22, 0x1f }, /* OVERRIDE */
132 { 0x80, 0x01 }, /* freq dependent */
133 { 0x0f, 0x01 }, /* start tune */
134 { 0, 0 }
135};
136
137/* ------------------------------------------------------------------------- */
138
139struct mxl5007t_state {
140 struct list_head hybrid_tuner_instance_list;
141 struct tuner_i2c_props i2c_props;
142
143 struct mutex lock;
144
145 struct mxl5007t_config *config;
146
147 enum mxl5007t_chip_version chip_id;
148
149 struct reg_pair_t tab_init[ARRAY_SIZE(init_tab)];
150 struct reg_pair_t tab_init_cable[ARRAY_SIZE(init_tab_cable)];
151 struct reg_pair_t tab_rftune[ARRAY_SIZE(reg_pair_rftune)];
152
153 enum mxl5007t_if_freq if_freq;
154
155 u32 frequency;
156 u32 bandwidth;
157};
158
159/* ------------------------------------------------------------------------- */
160
161/* called by _init and _rftun to manipulate the register arrays */
162
163static void set_reg_bits(struct reg_pair_t *reg_pair, u8 reg, u8 mask, u8 val)
164{
165 unsigned int i = 0;
166
167 while (reg_pair[i].reg || reg_pair[i].val) {
168 if (reg_pair[i].reg == reg) {
169 reg_pair[i].val &= ~mask;
170 reg_pair[i].val |= val;
171 }
172 i++;
173
174 }
175}
176
177static void copy_reg_bits(struct reg_pair_t *reg_pair1,
178 struct reg_pair_t *reg_pair2)
179{
180 unsigned int i, j;
181
182 i = j = 0;
183
184 while (reg_pair1[i].reg || reg_pair1[i].val) {
185 while (reg_pair2[j].reg || reg_pair2[j].val) {
186 if (reg_pair1[i].reg != reg_pair2[j].reg) {
187 j++;
188 continue;
189 }
190 reg_pair2[j].val = reg_pair1[i].val;
191 break;
192 }
193 i++;
194 }
195}
196
197/* ------------------------------------------------------------------------- */
198
199static void mxl5007t_set_mode_bits(struct mxl5007t_state *state,
200 enum mxl5007t_mode mode,
201 s32 if_diff_out_level)
202{
203 switch (mode) {
204 case MxL_MODE_ATSC:
205 set_reg_bits(reg_pair: state->tab_init, reg: 0x06, mask: 0x1f, val: 0x12);
206 break;
207 case MxL_MODE_DVBT:
208 set_reg_bits(reg_pair: state->tab_init, reg: 0x06, mask: 0x1f, val: 0x11);
209 break;
210 case MxL_MODE_ISDBT:
211 set_reg_bits(reg_pair: state->tab_init, reg: 0x06, mask: 0x1f, val: 0x10);
212 break;
213 case MxL_MODE_CABLE:
214 set_reg_bits(reg_pair: state->tab_init_cable, reg: 0x09, mask: 0xff, val: 0xc1);
215 set_reg_bits(reg_pair: state->tab_init_cable, reg: 0x0a, mask: 0xff,
216 val: 8 - if_diff_out_level);
217 set_reg_bits(reg_pair: state->tab_init_cable, reg: 0x0b, mask: 0xff, val: 0x17);
218 break;
219 default:
220 mxl_fail(-EINVAL);
221 }
222}
223
224static void mxl5007t_set_if_freq_bits(struct mxl5007t_state *state,
225 enum mxl5007t_if_freq if_freq,
226 int invert_if)
227{
228 u8 val;
229
230 switch (if_freq) {
231 case MxL_IF_4_MHZ:
232 val = 0x00;
233 break;
234 case MxL_IF_4_5_MHZ:
235 val = 0x02;
236 break;
237 case MxL_IF_4_57_MHZ:
238 val = 0x03;
239 break;
240 case MxL_IF_5_MHZ:
241 val = 0x04;
242 break;
243 case MxL_IF_5_38_MHZ:
244 val = 0x05;
245 break;
246 case MxL_IF_6_MHZ:
247 val = 0x06;
248 break;
249 case MxL_IF_6_28_MHZ:
250 val = 0x07;
251 break;
252 case MxL_IF_9_1915_MHZ:
253 val = 0x08;
254 break;
255 case MxL_IF_35_25_MHZ:
256 val = 0x09;
257 break;
258 case MxL_IF_36_15_MHZ:
259 val = 0x0a;
260 break;
261 case MxL_IF_44_MHZ:
262 val = 0x0b;
263 break;
264 default:
265 mxl_fail(-EINVAL);
266 return;
267 }
268 set_reg_bits(reg_pair: state->tab_init, reg: 0x02, mask: 0x0f, val);
269
270 /* set inverted IF or normal IF */
271 set_reg_bits(reg_pair: state->tab_init, reg: 0x02, mask: 0x10, val: invert_if ? 0x10 : 0x00);
272
273 state->if_freq = if_freq;
274}
275
276static void mxl5007t_set_xtal_freq_bits(struct mxl5007t_state *state,
277 enum mxl5007t_xtal_freq xtal_freq)
278{
279 switch (xtal_freq) {
280 case MxL_XTAL_16_MHZ:
281 /* select xtal freq & ref freq */
282 set_reg_bits(reg_pair: state->tab_init, reg: 0x03, mask: 0xf0, val: 0x00);
283 set_reg_bits(reg_pair: state->tab_init, reg: 0x05, mask: 0x0f, val: 0x00);
284 break;
285 case MxL_XTAL_20_MHZ:
286 set_reg_bits(reg_pair: state->tab_init, reg: 0x03, mask: 0xf0, val: 0x10);
287 set_reg_bits(reg_pair: state->tab_init, reg: 0x05, mask: 0x0f, val: 0x01);
288 break;
289 case MxL_XTAL_20_25_MHZ:
290 set_reg_bits(reg_pair: state->tab_init, reg: 0x03, mask: 0xf0, val: 0x20);
291 set_reg_bits(reg_pair: state->tab_init, reg: 0x05, mask: 0x0f, val: 0x02);
292 break;
293 case MxL_XTAL_20_48_MHZ:
294 set_reg_bits(reg_pair: state->tab_init, reg: 0x03, mask: 0xf0, val: 0x30);
295 set_reg_bits(reg_pair: state->tab_init, reg: 0x05, mask: 0x0f, val: 0x03);
296 break;
297 case MxL_XTAL_24_MHZ:
298 set_reg_bits(reg_pair: state->tab_init, reg: 0x03, mask: 0xf0, val: 0x40);
299 set_reg_bits(reg_pair: state->tab_init, reg: 0x05, mask: 0x0f, val: 0x04);
300 break;
301 case MxL_XTAL_25_MHZ:
302 set_reg_bits(reg_pair: state->tab_init, reg: 0x03, mask: 0xf0, val: 0x50);
303 set_reg_bits(reg_pair: state->tab_init, reg: 0x05, mask: 0x0f, val: 0x05);
304 break;
305 case MxL_XTAL_25_14_MHZ:
306 set_reg_bits(reg_pair: state->tab_init, reg: 0x03, mask: 0xf0, val: 0x60);
307 set_reg_bits(reg_pair: state->tab_init, reg: 0x05, mask: 0x0f, val: 0x06);
308 break;
309 case MxL_XTAL_27_MHZ:
310 set_reg_bits(reg_pair: state->tab_init, reg: 0x03, mask: 0xf0, val: 0x70);
311 set_reg_bits(reg_pair: state->tab_init, reg: 0x05, mask: 0x0f, val: 0x07);
312 break;
313 case MxL_XTAL_28_8_MHZ:
314 set_reg_bits(reg_pair: state->tab_init, reg: 0x03, mask: 0xf0, val: 0x80);
315 set_reg_bits(reg_pair: state->tab_init, reg: 0x05, mask: 0x0f, val: 0x08);
316 break;
317 case MxL_XTAL_32_MHZ:
318 set_reg_bits(reg_pair: state->tab_init, reg: 0x03, mask: 0xf0, val: 0x90);
319 set_reg_bits(reg_pair: state->tab_init, reg: 0x05, mask: 0x0f, val: 0x09);
320 break;
321 case MxL_XTAL_40_MHZ:
322 set_reg_bits(reg_pair: state->tab_init, reg: 0x03, mask: 0xf0, val: 0xa0);
323 set_reg_bits(reg_pair: state->tab_init, reg: 0x05, mask: 0x0f, val: 0x0a);
324 break;
325 case MxL_XTAL_44_MHZ:
326 set_reg_bits(reg_pair: state->tab_init, reg: 0x03, mask: 0xf0, val: 0xb0);
327 set_reg_bits(reg_pair: state->tab_init, reg: 0x05, mask: 0x0f, val: 0x0b);
328 break;
329 case MxL_XTAL_48_MHZ:
330 set_reg_bits(reg_pair: state->tab_init, reg: 0x03, mask: 0xf0, val: 0xc0);
331 set_reg_bits(reg_pair: state->tab_init, reg: 0x05, mask: 0x0f, val: 0x0c);
332 break;
333 case MxL_XTAL_49_3811_MHZ:
334 set_reg_bits(reg_pair: state->tab_init, reg: 0x03, mask: 0xf0, val: 0xd0);
335 set_reg_bits(reg_pair: state->tab_init, reg: 0x05, mask: 0x0f, val: 0x0d);
336 break;
337 default:
338 mxl_fail(-EINVAL);
339 return;
340 }
341}
342
343static struct reg_pair_t *mxl5007t_calc_init_regs(struct mxl5007t_state *state,
344 enum mxl5007t_mode mode)
345{
346 struct mxl5007t_config *cfg = state->config;
347
348 memcpy(&state->tab_init, &init_tab, sizeof(init_tab));
349 memcpy(&state->tab_init_cable, &init_tab_cable, sizeof(init_tab_cable));
350
351 mxl5007t_set_mode_bits(state, mode, if_diff_out_level: cfg->if_diff_out_level);
352 mxl5007t_set_if_freq_bits(state, if_freq: cfg->if_freq_hz, invert_if: cfg->invert_if);
353 mxl5007t_set_xtal_freq_bits(state, xtal_freq: cfg->xtal_freq_hz);
354
355 set_reg_bits(reg_pair: state->tab_init, reg: 0x03, mask: 0x08, val: cfg->clk_out_enable << 3);
356 set_reg_bits(reg_pair: state->tab_init, reg: 0x03, mask: 0x07, val: cfg->clk_out_amp);
357
358 if (mode >= MxL_MODE_CABLE) {
359 copy_reg_bits(reg_pair1: state->tab_init, reg_pair2: state->tab_init_cable);
360 return state->tab_init_cable;
361 } else
362 return state->tab_init;
363}
364
365/* ------------------------------------------------------------------------- */
366
367enum mxl5007t_bw_mhz {
368 MxL_BW_6MHz = 6,
369 MxL_BW_7MHz = 7,
370 MxL_BW_8MHz = 8,
371};
372
373static void mxl5007t_set_bw_bits(struct mxl5007t_state *state,
374 enum mxl5007t_bw_mhz bw)
375{
376 u8 val;
377
378 switch (bw) {
379 case MxL_BW_6MHz:
380 val = 0x15; /* set DIG_MODEINDEX, DIG_MODEINDEX_A,
381 * and DIG_MODEINDEX_CSF */
382 break;
383 case MxL_BW_7MHz:
384 val = 0x2a;
385 break;
386 case MxL_BW_8MHz:
387 val = 0x3f;
388 break;
389 default:
390 mxl_fail(-EINVAL);
391 return;
392 }
393 set_reg_bits(reg_pair: state->tab_rftune, reg: 0x0c, mask: 0x3f, val);
394}
395
396static struct
397reg_pair_t *mxl5007t_calc_rf_tune_regs(struct mxl5007t_state *state,
398 u32 rf_freq, enum mxl5007t_bw_mhz bw)
399{
400 u32 dig_rf_freq = 0;
401 u32 temp;
402 u32 frac_divider = 1000000;
403 unsigned int i;
404
405 memcpy(&state->tab_rftune, &reg_pair_rftune, sizeof(reg_pair_rftune));
406
407 mxl5007t_set_bw_bits(state, bw);
408
409 /* Convert RF frequency into 16 bits =>
410 * 10 bit integer (MHz) + 6 bit fraction */
411 dig_rf_freq = rf_freq / MHz;
412
413 temp = rf_freq % MHz;
414
415 for (i = 0; i < 6; i++) {
416 dig_rf_freq <<= 1;
417 frac_divider /= 2;
418 if (temp > frac_divider) {
419 temp -= frac_divider;
420 dig_rf_freq++;
421 }
422 }
423
424 /* add to have shift center point by 7.8124 kHz */
425 if (temp > 7812)
426 dig_rf_freq++;
427
428 set_reg_bits(reg_pair: state->tab_rftune, reg: 0x0d, mask: 0xff, val: (u8) dig_rf_freq);
429 set_reg_bits(reg_pair: state->tab_rftune, reg: 0x0e, mask: 0xff, val: (u8) (dig_rf_freq >> 8));
430
431 if (rf_freq >= 333000000)
432 set_reg_bits(reg_pair: state->tab_rftune, reg: 0x80, mask: 0x40, val: 0x40);
433
434 return state->tab_rftune;
435}
436
437/* ------------------------------------------------------------------------- */
438
439static int mxl5007t_write_reg(struct mxl5007t_state *state, u8 reg, u8 val)
440{
441 u8 buf[] = { reg, val };
442 struct i2c_msg msg = { .addr = state->i2c_props.addr, .flags = 0,
443 .buf = buf, .len = 2 };
444 int ret;
445
446 ret = i2c_transfer(adap: state->i2c_props.adap, msgs: &msg, num: 1);
447 if (ret != 1) {
448 mxl_err("failed!");
449 return -EREMOTEIO;
450 }
451 return 0;
452}
453
454static int mxl5007t_write_regs(struct mxl5007t_state *state,
455 struct reg_pair_t *reg_pair)
456{
457 unsigned int i = 0;
458 int ret = 0;
459
460 while ((ret == 0) && (reg_pair[i].reg || reg_pair[i].val)) {
461 ret = mxl5007t_write_reg(state,
462 reg: reg_pair[i].reg, val: reg_pair[i].val);
463 i++;
464 }
465 return ret;
466}
467
468static int mxl5007t_read_reg(struct mxl5007t_state *state, u8 reg, u8 *val)
469{
470 u8 buf[2] = { 0xfb, reg };
471 struct i2c_msg msg[] = {
472 { .addr = state->i2c_props.addr, .flags = 0,
473 .buf = buf, .len = 2 },
474 { .addr = state->i2c_props.addr, .flags = I2C_M_RD,
475 .buf = val, .len = 1 },
476 };
477 int ret;
478
479 ret = i2c_transfer(adap: state->i2c_props.adap, msgs: msg, num: 2);
480 if (ret != 2) {
481 mxl_err("failed!");
482 return -EREMOTEIO;
483 }
484 return 0;
485}
486
487static int mxl5007t_soft_reset(struct mxl5007t_state *state)
488{
489 u8 d = 0xff;
490 struct i2c_msg msg = {
491 .addr = state->i2c_props.addr, .flags = 0,
492 .buf = &d, .len = 1
493 };
494 int ret = i2c_transfer(adap: state->i2c_props.adap, msgs: &msg, num: 1);
495
496 if (ret != 1) {
497 mxl_err("failed!");
498 return -EREMOTEIO;
499 }
500 return 0;
501}
502
503static int mxl5007t_tuner_init(struct mxl5007t_state *state,
504 enum mxl5007t_mode mode)
505{
506 struct reg_pair_t *init_regs;
507 int ret;
508
509 /* calculate initialization reg array */
510 init_regs = mxl5007t_calc_init_regs(state, mode);
511
512 ret = mxl5007t_write_regs(state, reg_pair: init_regs);
513 if (mxl_fail(ret))
514 goto fail;
515 mdelay(1);
516fail:
517 return ret;
518}
519
520static int mxl5007t_tuner_rf_tune(struct mxl5007t_state *state, u32 rf_freq_hz,
521 enum mxl5007t_bw_mhz bw)
522{
523 struct reg_pair_t *rf_tune_regs;
524 int ret;
525
526 /* calculate channel change reg array */
527 rf_tune_regs = mxl5007t_calc_rf_tune_regs(state, rf_freq: rf_freq_hz, bw);
528
529 ret = mxl5007t_write_regs(state, reg_pair: rf_tune_regs);
530 if (mxl_fail(ret))
531 goto fail;
532 msleep(msecs: 3);
533fail:
534 return ret;
535}
536
537/* ------------------------------------------------------------------------- */
538
539static int mxl5007t_synth_lock_status(struct mxl5007t_state *state,
540 int *rf_locked, int *ref_locked)
541{
542 u8 d;
543 int ret;
544
545 *rf_locked = 0;
546 *ref_locked = 0;
547
548 ret = mxl5007t_read_reg(state, reg: 0xd8, val: &d);
549 if (mxl_fail(ret))
550 goto fail;
551
552 if ((d & 0x0c) == 0x0c)
553 *rf_locked = 1;
554
555 if ((d & 0x03) == 0x03)
556 *ref_locked = 1;
557fail:
558 return ret;
559}
560
561/* ------------------------------------------------------------------------- */
562
563static int mxl5007t_get_status(struct dvb_frontend *fe, u32 *status)
564{
565 struct mxl5007t_state *state = fe->tuner_priv;
566 int rf_locked, ref_locked, ret;
567
568 *status = 0;
569
570 if (fe->ops.i2c_gate_ctrl)
571 fe->ops.i2c_gate_ctrl(fe, 1);
572
573 ret = mxl5007t_synth_lock_status(state, rf_locked: &rf_locked, ref_locked: &ref_locked);
574 if (mxl_fail(ret))
575 goto fail;
576 mxl_debug("%s%s", rf_locked ? "rf locked " : "",
577 ref_locked ? "ref locked" : "");
578
579 if ((rf_locked) || (ref_locked))
580 *status |= TUNER_STATUS_LOCKED;
581fail:
582 if (fe->ops.i2c_gate_ctrl)
583 fe->ops.i2c_gate_ctrl(fe, 0);
584
585 return ret;
586}
587
588/* ------------------------------------------------------------------------- */
589
590static int mxl5007t_set_params(struct dvb_frontend *fe)
591{
592 struct dtv_frontend_properties *c = &fe->dtv_property_cache;
593 u32 delsys = c->delivery_system;
594 struct mxl5007t_state *state = fe->tuner_priv;
595 enum mxl5007t_bw_mhz bw;
596 enum mxl5007t_mode mode;
597 int ret;
598 u32 freq = c->frequency;
599
600 switch (delsys) {
601 case SYS_ATSC:
602 mode = MxL_MODE_ATSC;
603 bw = MxL_BW_6MHz;
604 break;
605 case SYS_DVBC_ANNEX_B:
606 mode = MxL_MODE_CABLE;
607 bw = MxL_BW_6MHz;
608 break;
609 case SYS_DVBT:
610 case SYS_DVBT2:
611 mode = MxL_MODE_DVBT;
612 switch (c->bandwidth_hz) {
613 case 6000000:
614 bw = MxL_BW_6MHz;
615 break;
616 case 7000000:
617 bw = MxL_BW_7MHz;
618 break;
619 case 8000000:
620 bw = MxL_BW_8MHz;
621 break;
622 default:
623 return -EINVAL;
624 }
625 break;
626 default:
627 mxl_err("modulation type not supported!");
628 return -EINVAL;
629 }
630
631 if (fe->ops.i2c_gate_ctrl)
632 fe->ops.i2c_gate_ctrl(fe, 1);
633
634 mutex_lock(&state->lock);
635
636 ret = mxl5007t_tuner_init(state, mode);
637 if (mxl_fail(ret))
638 goto fail;
639
640 ret = mxl5007t_tuner_rf_tune(state, rf_freq_hz: freq, bw);
641 if (mxl_fail(ret))
642 goto fail;
643
644 state->frequency = freq;
645 state->bandwidth = c->bandwidth_hz;
646fail:
647 mutex_unlock(lock: &state->lock);
648
649 if (fe->ops.i2c_gate_ctrl)
650 fe->ops.i2c_gate_ctrl(fe, 0);
651
652 return ret;
653}
654
655/* ------------------------------------------------------------------------- */
656
657static int mxl5007t_init(struct dvb_frontend *fe)
658{
659 struct mxl5007t_state *state = fe->tuner_priv;
660 int ret;
661
662 if (fe->ops.i2c_gate_ctrl)
663 fe->ops.i2c_gate_ctrl(fe, 1);
664
665 /* wake from standby */
666 ret = mxl5007t_write_reg(state, reg: 0x01, val: 0x01);
667 mxl_fail(ret);
668
669 if (fe->ops.i2c_gate_ctrl)
670 fe->ops.i2c_gate_ctrl(fe, 0);
671
672 return ret;
673}
674
675static int mxl5007t_sleep(struct dvb_frontend *fe)
676{
677 struct mxl5007t_state *state = fe->tuner_priv;
678 int ret;
679
680 if (fe->ops.i2c_gate_ctrl)
681 fe->ops.i2c_gate_ctrl(fe, 1);
682
683 /* enter standby mode */
684 ret = mxl5007t_write_reg(state, reg: 0x01, val: 0x00);
685 mxl_fail(ret);
686 ret = mxl5007t_write_reg(state, reg: 0x0f, val: 0x00);
687 mxl_fail(ret);
688
689 if (fe->ops.i2c_gate_ctrl)
690 fe->ops.i2c_gate_ctrl(fe, 0);
691
692 return ret;
693}
694
695/* ------------------------------------------------------------------------- */
696
697static int mxl5007t_get_frequency(struct dvb_frontend *fe, u32 *frequency)
698{
699 struct mxl5007t_state *state = fe->tuner_priv;
700 *frequency = state->frequency;
701 return 0;
702}
703
704static int mxl5007t_get_bandwidth(struct dvb_frontend *fe, u32 *bandwidth)
705{
706 struct mxl5007t_state *state = fe->tuner_priv;
707 *bandwidth = state->bandwidth;
708 return 0;
709}
710
711static int mxl5007t_get_if_frequency(struct dvb_frontend *fe, u32 *frequency)
712{
713 struct mxl5007t_state *state = fe->tuner_priv;
714
715 *frequency = 0;
716
717 switch (state->if_freq) {
718 case MxL_IF_4_MHZ:
719 *frequency = 4000000;
720 break;
721 case MxL_IF_4_5_MHZ:
722 *frequency = 4500000;
723 break;
724 case MxL_IF_4_57_MHZ:
725 *frequency = 4570000;
726 break;
727 case MxL_IF_5_MHZ:
728 *frequency = 5000000;
729 break;
730 case MxL_IF_5_38_MHZ:
731 *frequency = 5380000;
732 break;
733 case MxL_IF_6_MHZ:
734 *frequency = 6000000;
735 break;
736 case MxL_IF_6_28_MHZ:
737 *frequency = 6280000;
738 break;
739 case MxL_IF_9_1915_MHZ:
740 *frequency = 9191500;
741 break;
742 case MxL_IF_35_25_MHZ:
743 *frequency = 35250000;
744 break;
745 case MxL_IF_36_15_MHZ:
746 *frequency = 36150000;
747 break;
748 case MxL_IF_44_MHZ:
749 *frequency = 44000000;
750 break;
751 }
752 return 0;
753}
754
755static void mxl5007t_release(struct dvb_frontend *fe)
756{
757 struct mxl5007t_state *state = fe->tuner_priv;
758
759 mutex_lock(&mxl5007t_list_mutex);
760
761 if (state)
762 hybrid_tuner_release_state(state);
763
764 mutex_unlock(lock: &mxl5007t_list_mutex);
765
766 fe->tuner_priv = NULL;
767}
768
769/* ------------------------------------------------------------------------- */
770
771static const struct dvb_tuner_ops mxl5007t_tuner_ops = {
772 .info = {
773 .name = "MaxLinear MxL5007T",
774 },
775 .init = mxl5007t_init,
776 .sleep = mxl5007t_sleep,
777 .set_params = mxl5007t_set_params,
778 .get_status = mxl5007t_get_status,
779 .get_frequency = mxl5007t_get_frequency,
780 .get_bandwidth = mxl5007t_get_bandwidth,
781 .release = mxl5007t_release,
782 .get_if_frequency = mxl5007t_get_if_frequency,
783};
784
785static int mxl5007t_get_chip_id(struct mxl5007t_state *state)
786{
787 char *name;
788 int ret;
789 u8 id;
790
791 ret = mxl5007t_read_reg(state, reg: 0xd9, val: &id);
792 if (mxl_fail(ret))
793 goto fail;
794
795 switch (id) {
796 case MxL_5007_V1_F1:
797 name = "MxL5007.v1.f1";
798 break;
799 case MxL_5007_V1_F2:
800 name = "MxL5007.v1.f2";
801 break;
802 case MxL_5007_V2_100_F1:
803 name = "MxL5007.v2.100.f1";
804 break;
805 case MxL_5007_V2_100_F2:
806 name = "MxL5007.v2.100.f2";
807 break;
808 case MxL_5007_V2_200_F1:
809 name = "MxL5007.v2.200.f1";
810 break;
811 case MxL_5007_V2_200_F2:
812 name = "MxL5007.v2.200.f2";
813 break;
814 case MxL_5007_V4:
815 name = "MxL5007T.v4";
816 break;
817 default:
818 name = "MxL5007T";
819 printk(KERN_WARNING "%s: unknown rev (%02x)\n", __func__, id);
820 id = MxL_UNKNOWN_ID;
821 }
822 state->chip_id = id;
823 mxl_info("%s detected @ %d-%04x", name,
824 i2c_adapter_id(state->i2c_props.adap),
825 state->i2c_props.addr);
826 return 0;
827fail:
828 mxl_warn("unable to identify device @ %d-%04x",
829 i2c_adapter_id(state->i2c_props.adap),
830 state->i2c_props.addr);
831
832 state->chip_id = MxL_UNKNOWN_ID;
833 return ret;
834}
835
836struct dvb_frontend *mxl5007t_attach(struct dvb_frontend *fe,
837 struct i2c_adapter *i2c, u8 addr,
838 struct mxl5007t_config *cfg)
839{
840 struct mxl5007t_state *state = NULL;
841 int instance, ret;
842
843 mutex_lock(&mxl5007t_list_mutex);
844 instance = hybrid_tuner_request_state(struct mxl5007t_state, state,
845 hybrid_tuner_instance_list,
846 i2c, addr, "mxl5007t");
847 switch (instance) {
848 case 0:
849 goto fail;
850 case 1:
851 /* new tuner instance */
852 state->config = cfg;
853
854 mutex_init(&state->lock);
855
856 if (fe->ops.i2c_gate_ctrl)
857 fe->ops.i2c_gate_ctrl(fe, 1);
858
859 ret = mxl5007t_get_chip_id(state);
860
861 if (fe->ops.i2c_gate_ctrl)
862 fe->ops.i2c_gate_ctrl(fe, 0);
863
864 /* check return value of mxl5007t_get_chip_id */
865 if (mxl_fail(ret))
866 goto fail;
867 break;
868 default:
869 /* existing tuner instance */
870 break;
871 }
872
873 if (fe->ops.i2c_gate_ctrl)
874 fe->ops.i2c_gate_ctrl(fe, 1);
875
876 ret = mxl5007t_soft_reset(state);
877
878 if (fe->ops.i2c_gate_ctrl)
879 fe->ops.i2c_gate_ctrl(fe, 0);
880
881 if (mxl_fail(ret))
882 goto fail;
883
884 if (fe->ops.i2c_gate_ctrl)
885 fe->ops.i2c_gate_ctrl(fe, 1);
886
887 ret = mxl5007t_write_reg(state, reg: 0x04,
888 val: state->config->loop_thru_enable);
889
890 if (fe->ops.i2c_gate_ctrl)
891 fe->ops.i2c_gate_ctrl(fe, 0);
892
893 if (mxl_fail(ret))
894 goto fail;
895
896 fe->tuner_priv = state;
897
898 mutex_unlock(lock: &mxl5007t_list_mutex);
899
900 memcpy(&fe->ops.tuner_ops, &mxl5007t_tuner_ops,
901 sizeof(struct dvb_tuner_ops));
902
903 return fe;
904fail:
905 mutex_unlock(lock: &mxl5007t_list_mutex);
906
907 mxl5007t_release(fe);
908 return NULL;
909}
910EXPORT_SYMBOL_GPL(mxl5007t_attach);
911MODULE_DESCRIPTION("MaxLinear MxL5007T Silicon IC tuner driver");
912MODULE_AUTHOR("Michael Krufky <mkrufky@linuxtv.org>");
913MODULE_LICENSE("GPL");
914MODULE_VERSION("0.2");
915

source code of linux/drivers/media/tuners/mxl5007t.c