2 * Driver for the internal tuner of Montage M88RS6000
4 * Copyright (C) 2014 Max nibble <nibble.max@gmail.com>
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.
17 #include "m88rs6000t.h"
18 #include <linux/regmap.h>
20 struct m88rs6000t_dev
{
21 struct m88rs6000t_config cfg
;
22 struct i2c_client
*client
;
23 struct regmap
*regmap
;
27 struct m88rs6000t_reg_val
{
32 /* set demod main mclk and ts mclk */
33 static int m88rs6000t_set_demod_mclk(struct dvb_frontend
*fe
)
35 struct m88rs6000t_dev
*dev
= fe
->tuner_priv
;
36 struct dtv_frontend_properties
*c
= &fe
->dtv_property_cache
;
37 u8 reg11
, reg15
, reg16
, reg1D
, reg1E
, reg1F
;
38 u8 N
, f0
= 0, f1
= 0, f2
= 0, f3
= 0;
44 /* select demod main mclk */
45 ret
= regmap_read(dev
->regmap
, 0x15, &utmp
);
49 if (c
->symbol_rate
> 45010000) {
52 reg16
= 115; /* mclk = 110.25MHz */
56 reg16
= 96; /* mclk = 96MHz */
60 if (c
->delivery_system
== SYS_DVBS
)
65 pll_div_fb
= (reg15
& 0x01) << 8;
69 div
= 36000 * pll_div_fb
;
78 } else if (div
<= 48) {
84 } else if (div
<= 64) {
88 f2
= (div
- f0
- f1
) / 2;
89 f3
= div
- f0
- f1
- f2
;
107 ret
= regmap_read(dev
->regmap
, 0x1D, &utmp
);
113 reg1E
= ((f3
<< 4) + f2
) & 0xFF;
114 reg1F
= ((f1
<< 4) + f0
) & 0xFF;
116 /* program and recalibrate demod PLL */
117 ret
= regmap_write(dev
->regmap
, 0x05, 0x40);
120 ret
= regmap_write(dev
->regmap
, 0x11, 0x08);
123 ret
= regmap_write(dev
->regmap
, 0x15, reg15
);
126 ret
= regmap_write(dev
->regmap
, 0x16, reg16
);
129 ret
= regmap_write(dev
->regmap
, 0x1D, reg1D
);
132 ret
= regmap_write(dev
->regmap
, 0x1E, reg1E
);
135 ret
= regmap_write(dev
->regmap
, 0x1F, reg1F
);
138 ret
= regmap_write(dev
->regmap
, 0x17, 0xc1);
141 ret
= regmap_write(dev
->regmap
, 0x17, 0x81);
144 usleep_range(5000, 50000);
145 ret
= regmap_write(dev
->regmap
, 0x05, 0x00);
148 ret
= regmap_write(dev
->regmap
, 0x11, reg11
);
151 usleep_range(5000, 50000);
154 dev_dbg(&dev
->client
->dev
, "failed=%d\n", ret
);
158 static int m88rs6000t_set_pll_freq(struct m88rs6000t_dev
*dev
,
161 u32 fcry_KHz
, ulNDiv1
, ulNDiv2
, ulNDiv
;
162 u8 refDiv
, ucLoDiv1
, ucLomod1
, ucLoDiv2
, ucLomod2
, ucLoDiv
, ucLomod
;
163 u8 reg27
, reg29
, reg42
, reg42buf
;
167 fcry_KHz
= 27000; /* in kHz */
170 ret
= regmap_write(dev
->regmap
, 0x36, (refDiv
- 8));
173 ret
= regmap_write(dev
->regmap
, 0x31, 0x00);
176 ret
= regmap_write(dev
->regmap
, 0x2c, 0x02);
180 if (tuner_freq_MHz
>= 1550) {
185 } else if (tuner_freq_MHz
>= 1380) {
190 } else if (tuner_freq_MHz
>= 1070) {
195 } else if (tuner_freq_MHz
>= 1000) {
200 } else if (tuner_freq_MHz
>= 775) {
205 } else if (tuner_freq_MHz
>= 700) {
210 } else if (tuner_freq_MHz
>= 520) {
222 ulNDiv1
= ((tuner_freq_MHz
* ucLoDiv1
* 1000) * refDiv
223 / fcry_KHz
- 1024) / 2;
224 ulNDiv2
= ((tuner_freq_MHz
* ucLoDiv2
* 1000) * refDiv
225 / fcry_KHz
- 1024) / 2;
227 reg27
= (((ulNDiv1
>> 8) & 0x0F) + ucLomod1
) & 0x7F;
228 ret
= regmap_write(dev
->regmap
, 0x27, reg27
);
231 ret
= regmap_write(dev
->regmap
, 0x28, (u8
)(ulNDiv1
& 0xFF));
234 reg29
= (((ulNDiv2
>> 8) & 0x0F) + ucLomod2
) & 0x7f;
235 ret
= regmap_write(dev
->regmap
, 0x29, reg29
);
238 ret
= regmap_write(dev
->regmap
, 0x2a, (u8
)(ulNDiv2
& 0xFF));
241 ret
= regmap_write(dev
->regmap
, 0x2F, 0xf5);
244 ret
= regmap_write(dev
->regmap
, 0x30, 0x05);
247 ret
= regmap_write(dev
->regmap
, 0x08, 0x1f);
250 ret
= regmap_write(dev
->regmap
, 0x08, 0x3f);
253 ret
= regmap_write(dev
->regmap
, 0x09, 0x20);
256 ret
= regmap_write(dev
->regmap
, 0x09, 0x00);
259 ret
= regmap_write(dev
->regmap
, 0x3e, 0x11);
262 ret
= regmap_write(dev
->regmap
, 0x08, 0x2f);
265 ret
= regmap_write(dev
->regmap
, 0x08, 0x3f);
268 ret
= regmap_write(dev
->regmap
, 0x09, 0x10);
271 ret
= regmap_write(dev
->regmap
, 0x09, 0x00);
274 usleep_range(2000, 50000);
276 ret
= regmap_read(dev
->regmap
, 0x42, &utmp
);
281 ret
= regmap_write(dev
->regmap
, 0x3e, 0x10);
284 ret
= regmap_write(dev
->regmap
, 0x08, 0x2f);
287 ret
= regmap_write(dev
->regmap
, 0x08, 0x3f);
290 ret
= regmap_write(dev
->regmap
, 0x09, 0x10);
293 ret
= regmap_write(dev
->regmap
, 0x09, 0x00);
296 usleep_range(2000, 50000);
298 ret
= regmap_read(dev
->regmap
, 0x42, &utmp
);
302 if (reg42buf
< reg42
) {
303 ret
= regmap_write(dev
->regmap
, 0x3e, 0x11);
307 usleep_range(5000, 50000);
309 ret
= regmap_read(dev
->regmap
, 0x2d, &utmp
);
312 ret
= regmap_write(dev
->regmap
, 0x2d, utmp
);
315 ret
= regmap_read(dev
->regmap
, 0x2e, &utmp
);
318 ret
= regmap_write(dev
->regmap
, 0x2e, utmp
);
322 ret
= regmap_read(dev
->regmap
, 0x27, &utmp
);
326 ret
= regmap_read(dev
->regmap
, 0x83, &utmp
);
329 if (reg27
== (utmp
& 0x70)) {
332 ucLomod
= ucLomod1
/ 16;
336 ucLomod
= ucLomod2
/ 16;
339 if ((ucLoDiv
== 3) || (ucLoDiv
== 6)) {
341 ret
= regmap_write(dev
->regmap
, 0x36, (refDiv
- 8));
344 ulNDiv
= ((tuner_freq_MHz
* ucLoDiv
* 1000) * refDiv
345 / fcry_KHz
- 1024) / 2;
348 reg27
= (0x80 + ((ucLomod
<< 4) & 0x70)
349 + ((ulNDiv
>> 8) & 0x0F)) & 0xFF;
350 ret
= regmap_write(dev
->regmap
, 0x27, reg27
);
353 ret
= regmap_write(dev
->regmap
, 0x28, (u8
)(ulNDiv
& 0xFF));
356 ret
= regmap_write(dev
->regmap
, 0x29, 0x80);
359 ret
= regmap_write(dev
->regmap
, 0x31, 0x03);
367 ret
= regmap_write(dev
->regmap
, 0x3b, utmp
);
371 dev
->frequency_khz
= fcry_KHz
* (ulNDiv
* 2 + 1024) / refDiv
/ ucLoDiv
;
373 dev_dbg(&dev
->client
->dev
,
374 "actual tune frequency=%d\n", dev
->frequency_khz
);
377 dev_dbg(&dev
->client
->dev
, "failed=%d\n", ret
);
381 static int m88rs6000t_set_bb(struct m88rs6000t_dev
*dev
,
382 u32 symbol_rate_KSs
, s32 lpf_offset_KHz
)
387 f3dB
= symbol_rate_KSs
* 9 / 14 + 2000;
388 f3dB
+= lpf_offset_KHz
;
389 f3dB
= clamp_val(f3dB
, 6000U, 43000U);
391 return regmap_write(dev
->regmap
, 0x40, reg40
);
394 static int m88rs6000t_set_params(struct dvb_frontend
*fe
)
396 struct m88rs6000t_dev
*dev
= fe
->tuner_priv
;
397 struct dtv_frontend_properties
*c
= &fe
->dtv_property_cache
;
400 u32 realFreq
, freq_MHz
;
402 dev_dbg(&dev
->client
->dev
,
403 "frequency=%d symbol_rate=%d\n",
404 c
->frequency
, c
->symbol_rate
);
406 if (c
->symbol_rate
< 5000000)
407 lpf_offset_KHz
= 3000;
411 realFreq
= c
->frequency
+ lpf_offset_KHz
;
413 freq_MHz
= (realFreq
+ 500) / 1000;
414 ret
= m88rs6000t_set_pll_freq(dev
, freq_MHz
);
417 ret
= m88rs6000t_set_bb(dev
, c
->symbol_rate
/ 1000, lpf_offset_KHz
);
420 ret
= regmap_write(dev
->regmap
, 0x00, 0x01);
423 ret
= regmap_write(dev
->regmap
, 0x00, 0x00);
427 ret
= m88rs6000t_set_demod_mclk(fe
);
430 dev_dbg(&dev
->client
->dev
, "failed=%d\n", ret
);
434 static int m88rs6000t_init(struct dvb_frontend
*fe
)
436 struct m88rs6000t_dev
*dev
= fe
->tuner_priv
;
439 dev_dbg(&dev
->client
->dev
, "%s:\n", __func__
);
441 ret
= regmap_update_bits(dev
->regmap
, 0x11, 0x08, 0x08);
444 usleep_range(5000, 50000);
445 ret
= regmap_update_bits(dev
->regmap
, 0x10, 0x01, 0x01);
448 usleep_range(10000, 50000);
449 ret
= regmap_write(dev
->regmap
, 0x07, 0x7d);
452 dev_dbg(&dev
->client
->dev
, "failed=%d\n", ret
);
456 static int m88rs6000t_sleep(struct dvb_frontend
*fe
)
458 struct m88rs6000t_dev
*dev
= fe
->tuner_priv
;
461 dev_dbg(&dev
->client
->dev
, "%s:\n", __func__
);
463 ret
= regmap_write(dev
->regmap
, 0x07, 0x6d);
465 dev_dbg(&dev
->client
->dev
, "failed=%d\n", ret
);
468 usleep_range(5000, 10000);
472 static int m88rs6000t_get_frequency(struct dvb_frontend
*fe
, u32
*frequency
)
474 struct m88rs6000t_dev
*dev
= fe
->tuner_priv
;
476 dev_dbg(&dev
->client
->dev
, "\n");
478 *frequency
= dev
->frequency_khz
;
482 static int m88rs6000t_get_if_frequency(struct dvb_frontend
*fe
, u32
*frequency
)
484 struct m88rs6000t_dev
*dev
= fe
->tuner_priv
;
486 dev_dbg(&dev
->client
->dev
, "\n");
488 *frequency
= 0; /* Zero-IF */
493 static int m88rs6000t_get_rf_strength(struct dvb_frontend
*fe
, u16
*strength
)
495 struct m88rs6000t_dev
*dev
= fe
->tuner_priv
;
499 u32 PGA2_cri_GS
= 46, PGA2_crf_GS
= 290, TIA_GS
= 290;
500 u32 RF_GC
= 1200, IF_GC
= 1100, BB_GC
= 300;
501 u32 PGA2_GC
= 300, TIA_GC
= 300, PGA2_cri
= 0, PGA2_crf
= 0;
502 u32 RFG
= 0, IFG
= 0, BBG
= 0, PGA2G
= 0, TIAG
= 0;
503 u32 RFGS
[13] = {0, 245, 266, 268, 270, 285,
504 298, 295, 283, 285, 285, 300, 300};
505 u32 IFGS
[12] = {0, 300, 230, 270, 270, 285,
506 295, 285, 290, 295, 295, 310};
507 u32 BBGS
[14] = {0, 286, 275, 290, 294, 300, 290,
508 290, 285, 283, 260, 295, 290, 260};
510 ret
= regmap_read(dev
->regmap
, 0x5A, &val
);
515 ret
= regmap_read(dev
->regmap
, 0x5F, &val
);
520 ret
= regmap_read(dev
->regmap
, 0x3F, &val
);
523 TIA_GC
= (val
>> 4) & 0x07;
525 ret
= regmap_read(dev
->regmap
, 0x77, &val
);
528 BB_GC
= (val
>> 4) & 0x0f;
530 ret
= regmap_read(dev
->regmap
, 0x76, &val
);
533 PGA2_GC
= val
& 0x3f;
534 PGA2_cri
= PGA2_GC
>> 2;
535 PGA2_crf
= PGA2_GC
& 0x03;
537 for (i
= 0; i
<= RF_GC
; i
++)
549 for (i
= 0; i
<= IF_GC
; i
++)
552 TIAG
= TIA_GC
* TIA_GS
;
554 for (i
= 0; i
<= BB_GC
; i
++)
557 PGA2G
= PGA2_cri
* PGA2_cri_GS
+ PGA2_crf
* PGA2_crf_GS
;
559 gain
= RFG
+ IFG
- TIAG
+ BBG
+ PGA2G
;
561 /* scale value to 0x0000-0xffff */
562 gain
= clamp_val(gain
, 1000U, 10500U);
563 *strength
= (10500 - gain
) * 0xffff / (10500 - 1000);
566 dev_dbg(&dev
->client
->dev
, "failed=%d\n", ret
);
570 static const struct dvb_tuner_ops m88rs6000t_tuner_ops
= {
572 .name
= "Montage M88RS6000 Internal Tuner",
573 .frequency_min
= 950000,
574 .frequency_max
= 2150000,
577 .init
= m88rs6000t_init
,
578 .sleep
= m88rs6000t_sleep
,
579 .set_params
= m88rs6000t_set_params
,
580 .get_frequency
= m88rs6000t_get_frequency
,
581 .get_if_frequency
= m88rs6000t_get_if_frequency
,
582 .get_rf_strength
= m88rs6000t_get_rf_strength
,
585 static int m88rs6000t_probe(struct i2c_client
*client
,
586 const struct i2c_device_id
*id
)
588 struct m88rs6000t_config
*cfg
= client
->dev
.platform_data
;
589 struct dvb_frontend
*fe
= cfg
->fe
;
590 struct m88rs6000t_dev
*dev
;
593 static const struct regmap_config regmap_config
= {
597 static const struct m88rs6000t_reg_val reg_vals
[] = {
625 dev
= kzalloc(sizeof(*dev
), GFP_KERNEL
);
628 dev_err(&client
->dev
, "kzalloc() failed\n");
632 memcpy(&dev
->cfg
, cfg
, sizeof(struct m88rs6000t_config
));
633 dev
->client
= client
;
634 dev
->regmap
= devm_regmap_init_i2c(client
, ®map_config
);
635 if (IS_ERR(dev
->regmap
)) {
636 ret
= PTR_ERR(dev
->regmap
);
640 ret
= regmap_update_bits(dev
->regmap
, 0x11, 0x08, 0x08);
643 usleep_range(5000, 50000);
644 ret
= regmap_update_bits(dev
->regmap
, 0x10, 0x01, 0x01);
647 usleep_range(10000, 50000);
648 ret
= regmap_write(dev
->regmap
, 0x07, 0x7d);
651 ret
= regmap_write(dev
->regmap
, 0x04, 0x01);
655 /* check tuner chip id */
656 ret
= regmap_read(dev
->regmap
, 0x01, &utmp
);
659 dev_info(&dev
->client
->dev
, "chip_id=%02x\n", utmp
);
666 ret
= regmap_write(dev
->regmap
, 0x05, 0x40);
669 ret
= regmap_write(dev
->regmap
, 0x11, 0x08);
672 ret
= regmap_write(dev
->regmap
, 0x15, 0x6c);
675 ret
= regmap_write(dev
->regmap
, 0x17, 0xc1);
678 ret
= regmap_write(dev
->regmap
, 0x17, 0x81);
681 usleep_range(10000, 50000);
682 ret
= regmap_write(dev
->regmap
, 0x05, 0x00);
685 ret
= regmap_write(dev
->regmap
, 0x11, 0x0a);
689 for (i
= 0; i
< ARRAY_SIZE(reg_vals
); i
++) {
690 ret
= regmap_write(dev
->regmap
,
691 reg_vals
[i
].reg
, reg_vals
[i
].val
);
696 dev_info(&dev
->client
->dev
, "Montage M88RS6000 internal tuner successfully identified\n");
698 fe
->tuner_priv
= dev
;
699 memcpy(&fe
->ops
.tuner_ops
, &m88rs6000t_tuner_ops
,
700 sizeof(struct dvb_tuner_ops
));
701 i2c_set_clientdata(client
, dev
);
704 dev_dbg(&client
->dev
, "failed=%d\n", ret
);
709 static int m88rs6000t_remove(struct i2c_client
*client
)
711 struct m88rs6000t_dev
*dev
= i2c_get_clientdata(client
);
712 struct dvb_frontend
*fe
= dev
->cfg
.fe
;
714 dev_dbg(&client
->dev
, "\n");
716 memset(&fe
->ops
.tuner_ops
, 0, sizeof(struct dvb_tuner_ops
));
717 fe
->tuner_priv
= NULL
;
723 static const struct i2c_device_id m88rs6000t_id
[] = {
727 MODULE_DEVICE_TABLE(i2c
, m88rs6000t_id
);
729 static struct i2c_driver m88rs6000t_driver
= {
731 .name
= "m88rs6000t",
733 .probe
= m88rs6000t_probe
,
734 .remove
= m88rs6000t_remove
,
735 .id_table
= m88rs6000t_id
,
738 module_i2c_driver(m88rs6000t_driver
);
740 MODULE_AUTHOR("Max nibble <nibble.max@gmail.com>");
741 MODULE_DESCRIPTION("Montage M88RS6000 internal tuner driver");
742 MODULE_LICENSE("GPL");