2 * Montage M88TS2022 silicon tuner driver
4 * Copyright (C) 2013 Antti Palosaari <crope@iki.fi>
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation; either version 2 of the License, or
9 * (at your option) any later version.
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
16 * Some calculations are taken from existing TS2020 driver.
19 #include "m88ts2022_priv.h"
21 /* write multiple registers */
22 static int m88ts2022_wr_regs(struct m88ts2022_priv
*priv
,
23 u8 reg
, const u8
*val
, int len
)
26 #define MAX_WR_XFER_LEN (MAX_WR_LEN + 1)
28 u8 buf
[MAX_WR_XFER_LEN
];
29 struct i2c_msg msg
[1] = {
31 .addr
= priv
->client
->addr
,
38 if (WARN_ON(len
> MAX_WR_LEN
))
42 memcpy(&buf
[1], val
, len
);
44 ret
= i2c_transfer(priv
->client
->adapter
, msg
, 1);
48 dev_warn(&priv
->client
->dev
,
49 "%s: i2c wr failed=%d reg=%02x len=%d\n",
50 KBUILD_MODNAME
, ret
, reg
, len
);
57 /* read multiple registers */
58 static int m88ts2022_rd_regs(struct m88ts2022_priv
*priv
, u8 reg
,
62 #define MAX_RD_XFER_LEN (MAX_RD_LEN)
64 u8 buf
[MAX_RD_XFER_LEN
];
65 struct i2c_msg msg
[2] = {
67 .addr
= priv
->client
->addr
,
72 .addr
= priv
->client
->addr
,
79 if (WARN_ON(len
> MAX_RD_LEN
))
82 ret
= i2c_transfer(priv
->client
->adapter
, msg
, 2);
84 memcpy(val
, buf
, len
);
87 dev_warn(&priv
->client
->dev
,
88 "%s: i2c rd failed=%d reg=%02x len=%d\n",
89 KBUILD_MODNAME
, ret
, reg
, len
);
96 /* write single register */
97 static int m88ts2022_wr_reg(struct m88ts2022_priv
*priv
, u8 reg
, u8 val
)
99 return m88ts2022_wr_regs(priv
, reg
, &val
, 1);
102 /* read single register */
103 static int m88ts2022_rd_reg(struct m88ts2022_priv
*priv
, u8 reg
, u8
*val
)
105 return m88ts2022_rd_regs(priv
, reg
, val
, 1);
108 /* write single register with mask */
109 static int m88ts2022_wr_reg_mask(struct m88ts2022_priv
*priv
,
110 u8 reg
, u8 val
, u8 mask
)
115 /* no need for read if whole reg is written */
117 ret
= m88ts2022_rd_regs(priv
, reg
, &u8tmp
, 1);
126 return m88ts2022_wr_regs(priv
, reg
, &val
, 1);
129 static int m88ts2022_cmd(struct dvb_frontend
*fe
,
130 int op
, int sleep
, u8 reg
, u8 mask
, u8 val
, u8
*reg_val
)
132 struct m88ts2022_priv
*priv
= fe
->tuner_priv
;
135 struct m88ts2022_reg_val reg_vals
[] = {
142 for (i
= 0; i
< 2; i
++) {
143 dev_dbg(&priv
->client
->dev
,
144 "%s: i=%d op=%02x reg=%02x mask=%02x val=%02x\n",
145 __func__
, i
, op
, reg
, mask
, val
);
147 for (i
= 0; i
< ARRAY_SIZE(reg_vals
); i
++) {
148 ret
= m88ts2022_wr_reg(priv
, reg_vals
[i
].reg
,
154 usleep_range(sleep
* 1000, sleep
* 10000);
156 ret
= m88ts2022_rd_reg(priv
, reg
, &u8tmp
);
160 if ((u8tmp
& mask
) != val
)
170 static int m88ts2022_set_params(struct dvb_frontend
*fe
)
172 struct m88ts2022_priv
*priv
= fe
->tuner_priv
;
173 struct dtv_frontend_properties
*c
= &fe
->dtv_property_cache
;
175 unsigned int frequency_khz
, frequency_offset_khz
, f_3db_hz
;
176 unsigned int f_ref_khz
, f_vco_khz
, div_ref
, div_out
, pll_n
, gdiv28
;
177 u8 buf
[3], u8tmp
, cap_code
, lpf_gm
, lpf_mxdiv
, div_max
, div_min
;
179 dev_dbg(&priv
->client
->dev
,
180 "%s: frequency=%d symbol_rate=%d rolloff=%d\n",
181 __func__
, c
->frequency
, c
->symbol_rate
, c
->rolloff
);
183 * Integer-N PLL synthesizer
184 * kHz is used for all calculations to keep calculations within 32-bit
186 f_ref_khz
= DIV_ROUND_CLOSEST(priv
->cfg
.clock
, 1000);
187 div_ref
= DIV_ROUND_CLOSEST(f_ref_khz
, 2000);
189 if (c
->symbol_rate
< 5000000)
190 frequency_offset_khz
= 3000; /* 3 MHz */
192 frequency_offset_khz
= 0;
194 frequency_khz
= c
->frequency
+ frequency_offset_khz
;
196 if (frequency_khz
< 1103000) {
206 ret
= m88ts2022_wr_regs(priv
, 0x10, buf
, 2);
210 f_vco_khz
= frequency_khz
* div_out
;
211 pll_n
= f_vco_khz
* div_ref
/ f_ref_khz
;
213 priv
->frequency_khz
= pll_n
* f_ref_khz
/ div_ref
/ div_out
;
216 u16tmp
= pll_n
- 1024;
217 else if (pll_n
< 6143)
218 u16tmp
= pll_n
+ 1024;
220 u16tmp
= pll_n
+ 3072;
222 buf
[0] = (u16tmp
>> 8) & 0x3f;
223 buf
[1] = (u16tmp
>> 0) & 0xff;
224 buf
[2] = div_ref
- 8;
225 ret
= m88ts2022_wr_regs(priv
, 0x01, buf
, 3);
229 dev_dbg(&priv
->client
->dev
,
230 "%s: frequency=%u offset=%d f_vco_khz=%u pll_n=%u div_ref=%u div_out=%u\n",
231 __func__
, priv
->frequency_khz
,
232 priv
->frequency_khz
- c
->frequency
, f_vco_khz
, pll_n
,
235 ret
= m88ts2022_cmd(fe
, 0x10, 5, 0x15, 0x40, 0x00, NULL
);
239 ret
= m88ts2022_rd_reg(priv
, 0x14, &u8tmp
);
245 ret
= m88ts2022_wr_reg_mask(priv
, 0x10, 0x80, 0x80);
249 ret
= m88ts2022_wr_reg(priv
, 0x11, 0x6f);
253 ret
= m88ts2022_cmd(fe
, 0x10, 5, 0x15, 0x40, 0x00, NULL
);
258 ret
= m88ts2022_rd_reg(priv
, 0x14, &u8tmp
);
264 ret
= m88ts2022_wr_reg_mask(priv
, 0x10, 0x00, 0x02);
269 ret
= m88ts2022_cmd(fe
, 0x08, 5, 0x3c, 0xff, 0x00, NULL
);
273 ret
= m88ts2022_wr_reg(priv
, 0x25, 0x00);
277 ret
= m88ts2022_wr_reg(priv
, 0x27, 0x70);
281 ret
= m88ts2022_wr_reg(priv
, 0x41, 0x09);
285 ret
= m88ts2022_wr_reg(priv
, 0x08, 0x0b);
290 gdiv28
= DIV_ROUND_CLOSEST(f_ref_khz
* 1694U, 1000000U);
292 ret
= m88ts2022_wr_reg(priv
, 0x04, gdiv28
);
296 ret
= m88ts2022_cmd(fe
, 0x04, 2, 0x26, 0xff, 0x00, &u8tmp
);
300 cap_code
= u8tmp
& 0x3f;
302 ret
= m88ts2022_wr_reg(priv
, 0x41, 0x0d);
306 ret
= m88ts2022_cmd(fe
, 0x04, 2, 0x26, 0xff, 0x00, &u8tmp
);
311 cap_code
= (cap_code
+ u8tmp
) / 2;
312 gdiv28
= gdiv28
* 207 / (cap_code
* 2 + 151);
313 div_max
= gdiv28
* 135 / 100;
314 div_min
= gdiv28
* 78 / 100;
315 div_max
= clamp_val(div_max
, 0U, 63U);
317 f_3db_hz
= c
->symbol_rate
* 135UL / 200UL;
318 f_3db_hz
+= 2000000U + (frequency_offset_khz
* 1000U);
319 f_3db_hz
= clamp(f_3db_hz
, 7000000U, 40000000U);
321 #define LPF_COEFF 3200U
322 lpf_gm
= DIV_ROUND_CLOSEST(f_3db_hz
* gdiv28
, LPF_COEFF
* f_ref_khz
);
323 lpf_gm
= clamp_val(lpf_gm
, 1U, 23U);
325 lpf_mxdiv
= DIV_ROUND_CLOSEST(lpf_gm
* LPF_COEFF
* f_ref_khz
, f_3db_hz
);
326 if (lpf_mxdiv
< div_min
)
327 lpf_mxdiv
= DIV_ROUND_CLOSEST(++lpf_gm
* LPF_COEFF
* f_ref_khz
, f_3db_hz
);
328 lpf_mxdiv
= clamp_val(lpf_mxdiv
, 0U, div_max
);
330 ret
= m88ts2022_wr_reg(priv
, 0x04, lpf_mxdiv
);
334 ret
= m88ts2022_wr_reg(priv
, 0x06, lpf_gm
);
338 ret
= m88ts2022_cmd(fe
, 0x04, 2, 0x26, 0xff, 0x00, &u8tmp
);
342 cap_code
= u8tmp
& 0x3f;
344 ret
= m88ts2022_wr_reg(priv
, 0x41, 0x09);
348 ret
= m88ts2022_cmd(fe
, 0x04, 2, 0x26, 0xff, 0x00, &u8tmp
);
353 cap_code
= (cap_code
+ u8tmp
) / 2;
355 u8tmp
= cap_code
| 0x80;
356 ret
= m88ts2022_wr_reg(priv
, 0x25, u8tmp
);
360 ret
= m88ts2022_wr_reg(priv
, 0x27, 0x30);
364 ret
= m88ts2022_wr_reg(priv
, 0x08, 0x09);
368 ret
= m88ts2022_cmd(fe
, 0x01, 20, 0x21, 0xff, 0x00, NULL
);
373 dev_dbg(&priv
->client
->dev
, "%s: failed=%d\n", __func__
, ret
);
378 static int m88ts2022_init(struct dvb_frontend
*fe
)
380 struct m88ts2022_priv
*priv
= fe
->tuner_priv
;
383 static const struct m88ts2022_reg_val reg_vals
[] = {
396 dev_dbg(&priv
->client
->dev
, "%s:\n", __func__
);
398 ret
= m88ts2022_wr_reg(priv
, 0x00, 0x01);
402 ret
= m88ts2022_wr_reg(priv
, 0x00, 0x03);
406 switch (priv
->cfg
.clock_out
) {
407 case M88TS2022_CLOCK_OUT_DISABLED
:
410 case M88TS2022_CLOCK_OUT_ENABLED
:
412 ret
= m88ts2022_wr_reg(priv
, 0x05, priv
->cfg
.clock_out_div
);
416 case M88TS2022_CLOCK_OUT_ENABLED_XTALOUT
:
423 ret
= m88ts2022_wr_reg(priv
, 0x42, u8tmp
);
427 if (priv
->cfg
.loop_through
)
432 ret
= m88ts2022_wr_reg(priv
, 0x62, u8tmp
);
436 for (i
= 0; i
< ARRAY_SIZE(reg_vals
); i
++) {
437 ret
= m88ts2022_wr_reg(priv
, reg_vals
[i
].reg
, reg_vals
[i
].val
);
443 dev_dbg(&priv
->client
->dev
, "%s: failed=%d\n", __func__
, ret
);
447 static int m88ts2022_sleep(struct dvb_frontend
*fe
)
449 struct m88ts2022_priv
*priv
= fe
->tuner_priv
;
451 dev_dbg(&priv
->client
->dev
, "%s:\n", __func__
);
453 ret
= m88ts2022_wr_reg(priv
, 0x00, 0x00);
458 dev_dbg(&priv
->client
->dev
, "%s: failed=%d\n", __func__
, ret
);
462 static int m88ts2022_get_frequency(struct dvb_frontend
*fe
, u32
*frequency
)
464 struct m88ts2022_priv
*priv
= fe
->tuner_priv
;
465 dev_dbg(&priv
->client
->dev
, "%s:\n", __func__
);
467 *frequency
= priv
->frequency_khz
;
471 static int m88ts2022_get_if_frequency(struct dvb_frontend
*fe
, u32
*frequency
)
473 struct m88ts2022_priv
*priv
= fe
->tuner_priv
;
474 dev_dbg(&priv
->client
->dev
, "%s:\n", __func__
);
476 *frequency
= 0; /* Zero-IF */
480 static int m88ts2022_get_rf_strength(struct dvb_frontend
*fe
, u16
*strength
)
482 struct m88ts2022_priv
*priv
= fe
->tuner_priv
;
486 unsigned int gain1
, gain2
, gain3
;
488 ret
= m88ts2022_rd_reg(priv
, 0x3d, &u8tmp
);
492 gain1
= (u8tmp
>> 0) & 0x1f;
493 gain1
= clamp(gain1
, 0U, 15U);
495 ret
= m88ts2022_rd_reg(priv
, 0x21, &u8tmp
);
499 gain2
= (u8tmp
>> 0) & 0x1f;
500 gain2
= clamp(gain2
, 2U, 16U);
502 ret
= m88ts2022_rd_reg(priv
, 0x66, &u8tmp
);
506 gain3
= (u8tmp
>> 3) & 0x07;
507 gain3
= clamp(gain3
, 0U, 6U);
509 gain
= gain1
* 265 + gain2
* 338 + gain3
* 285;
511 /* scale value to 0x0000-0xffff */
512 u16tmp
= (0xffff - gain
);
513 u16tmp
= clamp_val(u16tmp
, 59000U, 61500U);
515 *strength
= (u16tmp
- 59000) * 0xffff / (61500 - 59000);
518 dev_dbg(&priv
->client
->dev
, "%s: failed=%d\n", __func__
, ret
);
522 static const struct dvb_tuner_ops m88ts2022_tuner_ops
= {
524 .name
= "Montage M88TS2022",
525 .frequency_min
= 950000,
526 .frequency_max
= 2150000,
529 .init
= m88ts2022_init
,
530 .sleep
= m88ts2022_sleep
,
531 .set_params
= m88ts2022_set_params
,
533 .get_frequency
= m88ts2022_get_frequency
,
534 .get_if_frequency
= m88ts2022_get_if_frequency
,
535 .get_rf_strength
= m88ts2022_get_rf_strength
,
538 static int m88ts2022_probe(struct i2c_client
*client
,
539 const struct i2c_device_id
*id
)
541 struct m88ts2022_config
*cfg
= client
->dev
.platform_data
;
542 struct dvb_frontend
*fe
= cfg
->fe
;
543 struct m88ts2022_priv
*priv
;
547 priv
= kzalloc(sizeof(*priv
), GFP_KERNEL
);
550 dev_err(&client
->dev
, "%s: kzalloc() failed\n", KBUILD_MODNAME
);
554 memcpy(&priv
->cfg
, cfg
, sizeof(struct m88ts2022_config
));
555 priv
->client
= client
;
557 /* check if the tuner is there */
558 ret
= m88ts2022_rd_reg(priv
, 0x00, &u8tmp
);
562 if ((u8tmp
& 0x03) == 0x00) {
563 ret
= m88ts2022_wr_reg(priv
, 0x00, 0x01);
567 usleep_range(2000, 50000);
570 ret
= m88ts2022_wr_reg(priv
, 0x00, 0x03);
574 usleep_range(2000, 50000);
576 ret
= m88ts2022_rd_reg(priv
, 0x00, &chip_id
);
580 dev_dbg(&priv
->client
->dev
, "%s: chip_id=%02x\n", __func__
, chip_id
);
590 switch (priv
->cfg
.clock_out
) {
591 case M88TS2022_CLOCK_OUT_DISABLED
:
594 case M88TS2022_CLOCK_OUT_ENABLED
:
596 ret
= m88ts2022_wr_reg(priv
, 0x05, priv
->cfg
.clock_out_div
);
600 case M88TS2022_CLOCK_OUT_ENABLED_XTALOUT
:
607 ret
= m88ts2022_wr_reg(priv
, 0x42, u8tmp
);
611 if (priv
->cfg
.loop_through
)
616 ret
= m88ts2022_wr_reg(priv
, 0x62, u8tmp
);
621 ret
= m88ts2022_wr_reg(priv
, 0x00, 0x00);
625 dev_info(&priv
->client
->dev
,
626 "%s: Montage M88TS2022 successfully identified\n",
629 fe
->tuner_priv
= priv
;
630 memcpy(&fe
->ops
.tuner_ops
, &m88ts2022_tuner_ops
,
631 sizeof(struct dvb_tuner_ops
));
633 i2c_set_clientdata(client
, priv
);
636 dev_dbg(&client
->dev
, "%s: failed=%d\n", __func__
, ret
);
641 static int m88ts2022_remove(struct i2c_client
*client
)
643 struct m88ts2022_priv
*priv
= i2c_get_clientdata(client
);
644 struct dvb_frontend
*fe
= priv
->cfg
.fe
;
645 dev_dbg(&client
->dev
, "%s:\n", __func__
);
647 memset(&fe
->ops
.tuner_ops
, 0, sizeof(struct dvb_tuner_ops
));
648 fe
->tuner_priv
= NULL
;
654 static const struct i2c_device_id m88ts2022_id
[] = {
658 MODULE_DEVICE_TABLE(i2c
, m88ts2022_id
);
660 static struct i2c_driver m88ts2022_driver
= {
662 .owner
= THIS_MODULE
,
665 .probe
= m88ts2022_probe
,
666 .remove
= m88ts2022_remove
,
667 .id_table
= m88ts2022_id
,
670 module_i2c_driver(m88ts2022_driver
);
672 MODULE_DESCRIPTION("Montage M88TS2022 silicon tuner driver");
673 MODULE_AUTHOR("Antti Palosaari <crope@iki.fi>");
674 MODULE_LICENSE("GPL");