1 // SPDX-License-Identifier: GPL-2.0-or-later
3 * Driver for the internal tuner of Montage M88RS6000
5 * Copyright (C) 2014 Max nibble <nibble.max@gmail.com>
8 #include "m88rs6000t.h"
9 #include <linux/regmap.h>
11 struct m88rs6000t_dev
{
12 struct m88rs6000t_config cfg
;
13 struct i2c_client
*client
;
14 struct regmap
*regmap
;
18 struct m88rs6000t_reg_val
{
23 /* set demod main mclk and ts mclk */
24 static int m88rs6000t_set_demod_mclk(struct dvb_frontend
*fe
)
26 struct m88rs6000t_dev
*dev
= fe
->tuner_priv
;
27 struct dtv_frontend_properties
*c
= &fe
->dtv_property_cache
;
28 u8 reg11
, reg15
, reg16
, reg1D
, reg1E
, reg1F
;
29 u8 N
, f0
= 0, f1
= 0, f2
= 0, f3
= 0;
35 /* select demod main mclk */
36 ret
= regmap_read(dev
->regmap
, 0x15, &utmp
);
40 if (c
->symbol_rate
> 45010000) {
43 reg16
= 115; /* mclk = 110.25MHz */
47 reg16
= 96; /* mclk = 96MHz */
51 if (c
->delivery_system
== SYS_DVBS
)
56 pll_div_fb
= (reg15
& 0x01) << 8;
60 div
= 36000 * pll_div_fb
;
69 } else if (div
<= 48) {
75 } else if (div
<= 64) {
79 f2
= (div
- f0
- f1
) / 2;
80 f3
= div
- f0
- f1
- f2
;
98 ret
= regmap_read(dev
->regmap
, 0x1D, &utmp
);
104 reg1E
= ((f3
<< 4) + f2
) & 0xFF;
105 reg1F
= ((f1
<< 4) + f0
) & 0xFF;
107 /* program and recalibrate demod PLL */
108 ret
= regmap_write(dev
->regmap
, 0x05, 0x40);
111 ret
= regmap_write(dev
->regmap
, 0x11, 0x08);
114 ret
= regmap_write(dev
->regmap
, 0x15, reg15
);
117 ret
= regmap_write(dev
->regmap
, 0x16, reg16
);
120 ret
= regmap_write(dev
->regmap
, 0x1D, reg1D
);
123 ret
= regmap_write(dev
->regmap
, 0x1E, reg1E
);
126 ret
= regmap_write(dev
->regmap
, 0x1F, reg1F
);
129 ret
= regmap_write(dev
->regmap
, 0x17, 0xc1);
132 ret
= regmap_write(dev
->regmap
, 0x17, 0x81);
135 usleep_range(5000, 50000);
136 ret
= regmap_write(dev
->regmap
, 0x05, 0x00);
139 ret
= regmap_write(dev
->regmap
, 0x11, reg11
);
142 usleep_range(5000, 50000);
145 dev_dbg(&dev
->client
->dev
, "failed=%d\n", ret
);
149 static int m88rs6000t_set_pll_freq(struct m88rs6000t_dev
*dev
,
152 u32 fcry_KHz
, ulNDiv1
, ulNDiv2
, ulNDiv
;
153 u8 refDiv
, ucLoDiv1
, ucLomod1
, ucLoDiv2
, ucLomod2
, ucLoDiv
, ucLomod
;
154 u8 reg27
, reg29
, reg42
, reg42buf
;
158 fcry_KHz
= 27000; /* in kHz */
161 ret
= regmap_write(dev
->regmap
, 0x36, (refDiv
- 8));
164 ret
= regmap_write(dev
->regmap
, 0x31, 0x00);
167 ret
= regmap_write(dev
->regmap
, 0x2c, 0x02);
171 if (tuner_freq_MHz
>= 1550) {
176 } else if (tuner_freq_MHz
>= 1380) {
181 } else if (tuner_freq_MHz
>= 1070) {
186 } else if (tuner_freq_MHz
>= 1000) {
191 } else if (tuner_freq_MHz
>= 775) {
196 } else if (tuner_freq_MHz
>= 700) {
201 } else if (tuner_freq_MHz
>= 520) {
213 ulNDiv1
= ((tuner_freq_MHz
* ucLoDiv1
* 1000) * refDiv
214 / fcry_KHz
- 1024) / 2;
215 ulNDiv2
= ((tuner_freq_MHz
* ucLoDiv2
* 1000) * refDiv
216 / fcry_KHz
- 1024) / 2;
218 reg27
= (((ulNDiv1
>> 8) & 0x0F) + ucLomod1
) & 0x7F;
219 ret
= regmap_write(dev
->regmap
, 0x27, reg27
);
222 ret
= regmap_write(dev
->regmap
, 0x28, (u8
)(ulNDiv1
& 0xFF));
225 reg29
= (((ulNDiv2
>> 8) & 0x0F) + ucLomod2
) & 0x7f;
226 ret
= regmap_write(dev
->regmap
, 0x29, reg29
);
229 ret
= regmap_write(dev
->regmap
, 0x2a, (u8
)(ulNDiv2
& 0xFF));
232 ret
= regmap_write(dev
->regmap
, 0x2F, 0xf5);
235 ret
= regmap_write(dev
->regmap
, 0x30, 0x05);
238 ret
= regmap_write(dev
->regmap
, 0x08, 0x1f);
241 ret
= regmap_write(dev
->regmap
, 0x08, 0x3f);
244 ret
= regmap_write(dev
->regmap
, 0x09, 0x20);
247 ret
= regmap_write(dev
->regmap
, 0x09, 0x00);
250 ret
= regmap_write(dev
->regmap
, 0x3e, 0x11);
253 ret
= regmap_write(dev
->regmap
, 0x08, 0x2f);
256 ret
= regmap_write(dev
->regmap
, 0x08, 0x3f);
259 ret
= regmap_write(dev
->regmap
, 0x09, 0x10);
262 ret
= regmap_write(dev
->regmap
, 0x09, 0x00);
265 usleep_range(2000, 50000);
267 ret
= regmap_read(dev
->regmap
, 0x42, &utmp
);
272 ret
= regmap_write(dev
->regmap
, 0x3e, 0x10);
275 ret
= regmap_write(dev
->regmap
, 0x08, 0x2f);
278 ret
= regmap_write(dev
->regmap
, 0x08, 0x3f);
281 ret
= regmap_write(dev
->regmap
, 0x09, 0x10);
284 ret
= regmap_write(dev
->regmap
, 0x09, 0x00);
287 usleep_range(2000, 50000);
289 ret
= regmap_read(dev
->regmap
, 0x42, &utmp
);
293 if (reg42buf
< reg42
) {
294 ret
= regmap_write(dev
->regmap
, 0x3e, 0x11);
298 usleep_range(5000, 50000);
300 ret
= regmap_read(dev
->regmap
, 0x2d, &utmp
);
303 ret
= regmap_write(dev
->regmap
, 0x2d, utmp
);
306 ret
= regmap_read(dev
->regmap
, 0x2e, &utmp
);
309 ret
= regmap_write(dev
->regmap
, 0x2e, utmp
);
313 ret
= regmap_read(dev
->regmap
, 0x27, &utmp
);
317 ret
= regmap_read(dev
->regmap
, 0x83, &utmp
);
320 if (reg27
== (utmp
& 0x70)) {
323 ucLomod
= ucLomod1
/ 16;
327 ucLomod
= ucLomod2
/ 16;
330 if ((ucLoDiv
== 3) || (ucLoDiv
== 6)) {
332 ret
= regmap_write(dev
->regmap
, 0x36, (refDiv
- 8));
335 ulNDiv
= ((tuner_freq_MHz
* ucLoDiv
* 1000) * refDiv
336 / fcry_KHz
- 1024) / 2;
339 reg27
= (0x80 + ((ucLomod
<< 4) & 0x70)
340 + ((ulNDiv
>> 8) & 0x0F)) & 0xFF;
341 ret
= regmap_write(dev
->regmap
, 0x27, reg27
);
344 ret
= regmap_write(dev
->regmap
, 0x28, (u8
)(ulNDiv
& 0xFF));
347 ret
= regmap_write(dev
->regmap
, 0x29, 0x80);
350 ret
= regmap_write(dev
->regmap
, 0x31, 0x03);
358 ret
= regmap_write(dev
->regmap
, 0x3b, utmp
);
362 dev
->frequency_khz
= fcry_KHz
* (ulNDiv
* 2 + 1024) / refDiv
/ ucLoDiv
;
364 dev_dbg(&dev
->client
->dev
,
365 "actual tune frequency=%d\n", dev
->frequency_khz
);
368 dev_dbg(&dev
->client
->dev
, "failed=%d\n", ret
);
372 static int m88rs6000t_set_bb(struct m88rs6000t_dev
*dev
,
373 u32 symbol_rate_KSs
, s32 lpf_offset_KHz
)
378 f3dB
= symbol_rate_KSs
* 9 / 14 + 2000;
379 f3dB
+= lpf_offset_KHz
;
380 f3dB
= clamp_val(f3dB
, 6000U, 43000U);
382 return regmap_write(dev
->regmap
, 0x40, reg40
);
385 static int m88rs6000t_set_params(struct dvb_frontend
*fe
)
387 struct m88rs6000t_dev
*dev
= fe
->tuner_priv
;
388 struct dtv_frontend_properties
*c
= &fe
->dtv_property_cache
;
391 u32 realFreq
, freq_MHz
;
393 dev_dbg(&dev
->client
->dev
,
394 "frequency=%d symbol_rate=%d\n",
395 c
->frequency
, c
->symbol_rate
);
397 if (c
->symbol_rate
< 5000000)
398 lpf_offset_KHz
= 3000;
402 realFreq
= c
->frequency
+ lpf_offset_KHz
;
404 freq_MHz
= (realFreq
+ 500) / 1000;
405 ret
= m88rs6000t_set_pll_freq(dev
, freq_MHz
);
408 ret
= m88rs6000t_set_bb(dev
, c
->symbol_rate
/ 1000, lpf_offset_KHz
);
411 ret
= regmap_write(dev
->regmap
, 0x00, 0x01);
414 ret
= regmap_write(dev
->regmap
, 0x00, 0x00);
418 ret
= m88rs6000t_set_demod_mclk(fe
);
421 dev_dbg(&dev
->client
->dev
, "failed=%d\n", ret
);
425 static int m88rs6000t_init(struct dvb_frontend
*fe
)
427 struct m88rs6000t_dev
*dev
= fe
->tuner_priv
;
430 dev_dbg(&dev
->client
->dev
, "%s:\n", __func__
);
432 ret
= regmap_update_bits(dev
->regmap
, 0x11, 0x08, 0x08);
435 usleep_range(5000, 50000);
436 ret
= regmap_update_bits(dev
->regmap
, 0x10, 0x01, 0x01);
439 usleep_range(10000, 50000);
440 ret
= regmap_write(dev
->regmap
, 0x07, 0x7d);
443 dev_dbg(&dev
->client
->dev
, "failed=%d\n", ret
);
447 static int m88rs6000t_sleep(struct dvb_frontend
*fe
)
449 struct m88rs6000t_dev
*dev
= fe
->tuner_priv
;
452 dev_dbg(&dev
->client
->dev
, "%s:\n", __func__
);
454 ret
= regmap_write(dev
->regmap
, 0x07, 0x6d);
456 dev_dbg(&dev
->client
->dev
, "failed=%d\n", ret
);
459 usleep_range(5000, 10000);
463 static int m88rs6000t_get_frequency(struct dvb_frontend
*fe
, u32
*frequency
)
465 struct m88rs6000t_dev
*dev
= fe
->tuner_priv
;
467 dev_dbg(&dev
->client
->dev
, "\n");
469 *frequency
= dev
->frequency_khz
;
473 static int m88rs6000t_get_if_frequency(struct dvb_frontend
*fe
, u32
*frequency
)
475 struct m88rs6000t_dev
*dev
= fe
->tuner_priv
;
477 dev_dbg(&dev
->client
->dev
, "\n");
479 *frequency
= 0; /* Zero-IF */
484 static int m88rs6000t_get_rf_strength(struct dvb_frontend
*fe
, u16
*strength
)
486 struct m88rs6000t_dev
*dev
= fe
->tuner_priv
;
490 u32 PGA2_cri_GS
= 46, PGA2_crf_GS
= 290, TIA_GS
= 290;
491 u32 RF_GC
= 1200, IF_GC
= 1100, BB_GC
= 300;
492 u32 PGA2_GC
= 300, TIA_GC
= 300, PGA2_cri
= 0, PGA2_crf
= 0;
493 u32 RFG
= 0, IFG
= 0, BBG
= 0, PGA2G
= 0, TIAG
= 0;
494 u32 RFGS
[13] = {0, 245, 266, 268, 270, 285,
495 298, 295, 283, 285, 285, 300, 300};
496 u32 IFGS
[12] = {0, 300, 230, 270, 270, 285,
497 295, 285, 290, 295, 295, 310};
498 u32 BBGS
[14] = {0, 286, 275, 290, 294, 300, 290,
499 290, 285, 283, 260, 295, 290, 260};
501 ret
= regmap_read(dev
->regmap
, 0x5A, &val
);
506 ret
= regmap_read(dev
->regmap
, 0x5F, &val
);
511 ret
= regmap_read(dev
->regmap
, 0x3F, &val
);
514 TIA_GC
= (val
>> 4) & 0x07;
516 ret
= regmap_read(dev
->regmap
, 0x77, &val
);
519 BB_GC
= (val
>> 4) & 0x0f;
521 ret
= regmap_read(dev
->regmap
, 0x76, &val
);
524 PGA2_GC
= val
& 0x3f;
525 PGA2_cri
= PGA2_GC
>> 2;
526 PGA2_crf
= PGA2_GC
& 0x03;
528 for (i
= 0; i
<= RF_GC
; i
++)
540 for (i
= 0; i
<= IF_GC
; i
++)
543 TIAG
= TIA_GC
* TIA_GS
;
545 for (i
= 0; i
<= BB_GC
; i
++)
548 PGA2G
= PGA2_cri
* PGA2_cri_GS
+ PGA2_crf
* PGA2_crf_GS
;
550 gain
= RFG
+ IFG
- TIAG
+ BBG
+ PGA2G
;
552 /* scale value to 0x0000-0xffff */
553 gain
= clamp_val(gain
, 1000U, 10500U);
554 *strength
= (10500 - gain
) * 0xffff / (10500 - 1000);
557 dev_dbg(&dev
->client
->dev
, "failed=%d\n", ret
);
561 static const struct dvb_tuner_ops m88rs6000t_tuner_ops
= {
563 .name
= "Montage M88RS6000 Internal Tuner",
564 .frequency_min_hz
= 950 * MHz
,
565 .frequency_max_hz
= 2150 * MHz
,
568 .init
= m88rs6000t_init
,
569 .sleep
= m88rs6000t_sleep
,
570 .set_params
= m88rs6000t_set_params
,
571 .get_frequency
= m88rs6000t_get_frequency
,
572 .get_if_frequency
= m88rs6000t_get_if_frequency
,
573 .get_rf_strength
= m88rs6000t_get_rf_strength
,
576 static int m88rs6000t_probe(struct i2c_client
*client
,
577 const struct i2c_device_id
*id
)
579 struct m88rs6000t_config
*cfg
= client
->dev
.platform_data
;
580 struct dvb_frontend
*fe
= cfg
->fe
;
581 struct m88rs6000t_dev
*dev
;
584 static const struct regmap_config regmap_config
= {
588 static const struct m88rs6000t_reg_val reg_vals
[] = {
616 dev
= kzalloc(sizeof(*dev
), GFP_KERNEL
);
619 dev_err(&client
->dev
, "kzalloc() failed\n");
623 memcpy(&dev
->cfg
, cfg
, sizeof(struct m88rs6000t_config
));
624 dev
->client
= client
;
625 dev
->regmap
= devm_regmap_init_i2c(client
, ®map_config
);
626 if (IS_ERR(dev
->regmap
)) {
627 ret
= PTR_ERR(dev
->regmap
);
631 ret
= regmap_update_bits(dev
->regmap
, 0x11, 0x08, 0x08);
634 usleep_range(5000, 50000);
635 ret
= regmap_update_bits(dev
->regmap
, 0x10, 0x01, 0x01);
638 usleep_range(10000, 50000);
639 ret
= regmap_write(dev
->regmap
, 0x07, 0x7d);
642 ret
= regmap_write(dev
->regmap
, 0x04, 0x01);
646 /* check tuner chip id */
647 ret
= regmap_read(dev
->regmap
, 0x01, &utmp
);
650 dev_info(&dev
->client
->dev
, "chip_id=%02x\n", utmp
);
657 ret
= regmap_write(dev
->regmap
, 0x05, 0x40);
660 ret
= regmap_write(dev
->regmap
, 0x11, 0x08);
663 ret
= regmap_write(dev
->regmap
, 0x15, 0x6c);
666 ret
= regmap_write(dev
->regmap
, 0x17, 0xc1);
669 ret
= regmap_write(dev
->regmap
, 0x17, 0x81);
672 usleep_range(10000, 50000);
673 ret
= regmap_write(dev
->regmap
, 0x05, 0x00);
676 ret
= regmap_write(dev
->regmap
, 0x11, 0x0a);
680 for (i
= 0; i
< ARRAY_SIZE(reg_vals
); i
++) {
681 ret
= regmap_write(dev
->regmap
,
682 reg_vals
[i
].reg
, reg_vals
[i
].val
);
687 dev_info(&dev
->client
->dev
, "Montage M88RS6000 internal tuner successfully identified\n");
689 fe
->tuner_priv
= dev
;
690 memcpy(&fe
->ops
.tuner_ops
, &m88rs6000t_tuner_ops
,
691 sizeof(struct dvb_tuner_ops
));
692 i2c_set_clientdata(client
, dev
);
695 dev_dbg(&client
->dev
, "failed=%d\n", ret
);
700 static int m88rs6000t_remove(struct i2c_client
*client
)
702 struct m88rs6000t_dev
*dev
= i2c_get_clientdata(client
);
703 struct dvb_frontend
*fe
= dev
->cfg
.fe
;
705 dev_dbg(&client
->dev
, "\n");
707 memset(&fe
->ops
.tuner_ops
, 0, sizeof(struct dvb_tuner_ops
));
708 fe
->tuner_priv
= NULL
;
714 static const struct i2c_device_id m88rs6000t_id
[] = {
718 MODULE_DEVICE_TABLE(i2c
, m88rs6000t_id
);
720 static struct i2c_driver m88rs6000t_driver
= {
722 .name
= "m88rs6000t",
724 .probe
= m88rs6000t_probe
,
725 .remove
= m88rs6000t_remove
,
726 .id_table
= m88rs6000t_id
,
729 module_i2c_driver(m88rs6000t_driver
);
731 MODULE_AUTHOR("Max nibble <nibble.max@gmail.com>");
732 MODULE_DESCRIPTION("Montage M88RS6000 internal tuner driver");
733 MODULE_LICENSE("GPL");