aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/media/dvb
diff options
context:
space:
mode:
authorPatrick Boettcher <pb@linuxtv.org>2007-07-30 11:49:04 -0400
committerMauro Carvalho Chehab <mchehab@infradead.org>2007-10-09 21:03:44 -0400
commit01373a5c97ced83d4cb520f7e56c80454a198bfb (patch)
tree4423207d7f0c50de6fa3672943c07ff49d5da773 /drivers/media/dvb
parentb6884a17fc70e979ef34e4b5560988b522bb50a0 (diff)
V4L/DVB (5955): Add support for DiB7070-based devices
This changeset adds support for DiB7070P-based devices by adding the dib0070-driver and putting the appropriate layouts into dib0700_devices.c It also includes a new firmware for the dib0700 which is necessary to make the DiB7070-boards work and it also should fix the i2c-problems on some boards. Signed-off-by: Jean-Philippe Sibers <jpsibers@dibcom.fr> Signed-off-by: Patrick Boettcher <pboettcher@dibcom.fr> Signed-off-by: Mauro Carvalho Chehab <mchehab@infradead.org>
Diffstat (limited to 'drivers/media/dvb')
-rw-r--r--drivers/media/dvb/dvb-usb/Kconfig1
-rw-r--r--drivers/media/dvb/dvb-usb/dib0700_devices.c295
-rw-r--r--drivers/media/dvb/dvb-usb/dvb-usb-ids.h10
-rw-r--r--drivers/media/dvb/frontends/Kconfig9
-rw-r--r--drivers/media/dvb/frontends/Makefile1
-rw-r--r--drivers/media/dvb/frontends/dib0070.c580
-rw-r--r--drivers/media/dvb/frontends/dib0070.h44
-rw-r--r--drivers/media/dvb/frontends/dib3000mc.c2
-rw-r--r--drivers/media/dvb/frontends/dib7000m.c12
-rw-r--r--drivers/media/dvb/frontends/dib7000p.c44
-rw-r--r--drivers/media/dvb/frontends/dib7000p.h9
11 files changed, 974 insertions, 33 deletions
diff --git a/drivers/media/dvb/dvb-usb/Kconfig b/drivers/media/dvb/dvb-usb/Kconfig
index dec03ee32e1a..d73934dd4c57 100644
--- a/drivers/media/dvb/dvb-usb/Kconfig
+++ b/drivers/media/dvb/dvb-usb/Kconfig
@@ -75,6 +75,7 @@ config DVB_USB_DIB0700
75 select DVB_DIB3000MC 75 select DVB_DIB3000MC
76 select DVB_TUNER_MT2060 if !DVB_FE_CUSTOMISE 76 select DVB_TUNER_MT2060 if !DVB_FE_CUSTOMISE
77 select DVB_TUNER_MT2266 if !DVB_FE_CUSTOMISE 77 select DVB_TUNER_MT2266 if !DVB_FE_CUSTOMISE
78 select DVB_TUNER_DIB0070
78 help 79 help
79 Support for USB2.0/1.1 DVB receivers based on the DiB0700 USB bridge. The 80 Support for USB2.0/1.1 DVB receivers based on the DiB0700 USB bridge. The
80 USB bridge is also present in devices having the DiB7700 DVB-T-USB 81 USB bridge is also present in devices having the DiB7700 DVB-T-USB
diff --git a/drivers/media/dvb/dvb-usb/dib0700_devices.c b/drivers/media/dvb/dvb-usb/dib0700_devices.c
index 04b66f6e659f..558ab3bd6889 100644
--- a/drivers/media/dvb/dvb-usb/dib0700_devices.c
+++ b/drivers/media/dvb/dvb-usb/dib0700_devices.c
@@ -13,13 +13,18 @@
13#include "dib7000p.h" 13#include "dib7000p.h"
14#include "mt2060.h" 14#include "mt2060.h"
15#include "mt2266.h" 15#include "mt2266.h"
16#include "dib0070.h"
16 17
17static int force_lna_activation; 18static int force_lna_activation;
18module_param(force_lna_activation, int, 0644); 19module_param(force_lna_activation, int, 0644);
19MODULE_PARM_DESC(force_lna_activation, "force the activation of Low-Noise-Amplifyer(s) (LNA), " 20MODULE_PARM_DESC(force_lna_activation, "force the activation of Low-Noise-Amplifyer(s) (LNA), "
20 "if applicable for the device (default: 0=automatic/off)."); 21 "if applicable for the device (default: 0=automatic/off).");
21 22
22/* Hauppauge Nova-T 500 23struct dib0700_adapter_state {
24 int (*set_param_save) (struct dvb_frontend *, struct dvb_frontend_parameters *);
25};
26
27/* Hauppauge Nova-T 500 (aka Bristol)
23 * has a LNA on GPIO0 which is enabled by setting 1 */ 28 * has a LNA on GPIO0 which is enabled by setting 1 */
24static struct mt2060_config bristol_mt2060_config[2] = { 29static struct mt2060_config bristol_mt2060_config[2] = {
25 { 30 {
@@ -97,7 +102,7 @@ static int bristol_tuner_attach(struct dvb_usb_adapter *adap)
97 st->mt2060_if1[adap->id]) == NULL ? -ENODEV : 0; 102 st->mt2060_if1[adap->id]) == NULL ? -ENODEV : 0;
98} 103}
99 104
100/* STK7700D: Pinnacle Dual DVB-T Diversity */ 105/* STK7700D: Pinnacle/Terratec/Hauppauge Dual DVB-T Diversity */
101 106
102/* MT226x */ 107/* MT226x */
103static struct dibx000_agc_config stk7700d_7000p_mt2266_agc_config[2] = { 108static struct dibx000_agc_config stk7700d_7000p_mt2266_agc_config[2] = {
@@ -539,31 +544,243 @@ static int stk7700p_tuner_attach(struct dvb_usb_adapter *adap)
539 st->mt2060_if1[0]) == NULL ? -ENODEV : 0; 544 st->mt2060_if1[0]) == NULL ? -ENODEV : 0;
540} 545}
541 546
547/* DIB7070 generic */
548static struct dibx000_agc_config dib7070_agc_config = {
549 BAND_UHF | BAND_VHF | BAND_LBAND | BAND_SBAND,
550 /* P_agc_use_sd_mod1=0, P_agc_use_sd_mod2=0, P_agc_freq_pwm_div=5, P_agc_inv_pwm1=0, P_agc_inv_pwm2=0,
551 * P_agc_inh_dc_rv_est=0, P_agc_time_est=3, P_agc_freeze=0, P_agc_nb_est=5, P_agc_write=0 */
552 (0 << 15) | (0 << 14) | (5 << 11) | (0 << 10) | (0 << 9) | (0 << 8) | (3 << 5) | (0 << 4) | (5 << 1) | (0 << 0), // setup
553
554 600, // inv_gain
555 10, // time_stabiliz
556
557 0, // alpha_level
558 118, // thlock
559
560 0, // wbd_inv
561 3530, // wbd_ref
562 1, // wbd_sel
563 5, // wbd_alpha
564
565 65535, // agc1_max
566 0, // agc1_min
567
568 65535, // agc2_max
569 0, // agc2_min
570
571 0, // agc1_pt1
572 40, // agc1_pt2
573 183, // agc1_pt3
574 206, // agc1_slope1
575 255, // agc1_slope2
576 72, // agc2_pt1
577 152, // agc2_pt2
578 88, // agc2_slope1
579 90, // agc2_slope2
580
581 17, // alpha_mant
582 27, // alpha_exp
583 23, // beta_mant
584 51, // beta_exp
585
586 0, // perform_agc_softsplit
587};
588
589static int dib7070_tuner_reset(struct dvb_frontend *fe, int onoff)
590{
591 return dib7000p_set_gpio(fe, 8, 0, !onoff);
592}
593
594static int dib7070_tuner_sleep(struct dvb_frontend *fe, int onoff)
595{
596 return dib7000p_set_gpio(fe, 9, 0, onoff);
597}
598
599static struct dib0070_config dib7070p_dib0070_config[2] = {
600 {
601 .i2c_address = DEFAULT_DIB0070_I2C_ADDRESS,
602 .reset = dib7070_tuner_reset,
603 .sleep = dib7070_tuner_sleep,
604 .clock_khz = 12000,
605 .clock_pad_drive = 4
606 }, {
607 .i2c_address = DEFAULT_DIB0070_I2C_ADDRESS,
608 .reset = dib7070_tuner_reset,
609 .sleep = dib7070_tuner_sleep,
610 .clock_khz = 12000,
611
612 }
613};
614
615static int dib7070_set_param_override(struct dvb_frontend *fe, struct dvb_frontend_parameters *fep)
616{
617 struct dvb_usb_adapter *adap = fe->dvb->priv;
618 struct dib0700_adapter_state *state = adap->priv;
619
620 u16 offset;
621 u8 band = BAND_OF_FREQUENCY(fep->frequency/1000);
622 switch (band) {
623 case BAND_VHF: offset = 950; break;
624 case BAND_UHF:
625 default: offset = 550; break;
626 }
627 deb_info("WBD for DiB7000P: %d\n", offset + dib0070_wbd_offset(fe));
628 dib7000p_set_wbd_ref(fe, offset + dib0070_wbd_offset(fe));
629 return state->set_param_save(fe, fep);
630}
631
632static int dib7070p_tuner_attach(struct dvb_usb_adapter *adap)
633{
634 struct dib0700_adapter_state *st = adap->priv;
635 struct i2c_adapter *tun_i2c = dib7000p_get_i2c_master(adap->fe, DIBX000_I2C_INTERFACE_TUNER, 1);
636
637 if (adap->id == 0) {
638 if (dvb_attach(dib0070_attach, adap->fe, tun_i2c, &dib7070p_dib0070_config[0]) == NULL)
639 return -ENODEV;
640 } else {
641 if (dvb_attach(dib0070_attach, adap->fe, tun_i2c, &dib7070p_dib0070_config[1]) == NULL)
642 return -ENODEV;
643 }
644
645 st->set_param_save = adap->fe->ops.tuner_ops.set_params;
646 adap->fe->ops.tuner_ops.set_params = dib7070_set_param_override;
647 return 0;
648}
649
650static struct dibx000_bandwidth_config dib7070_bw_config_12_mhz = {
651 60000, 15000, // internal, sampling
652 1, 20, 3, 1, 0, // pll_cfg: prediv, ratio, range, reset, bypass
653 0, 0, 1, 1, 2, // misc: refdiv, bypclk_div, IO_CLK_en_core, ADClkSrc, modulo
654 (3 << 14) | (1 << 12) | (524 << 0), // sad_cfg: refsel, sel, freq_15k
655 (0 << 25) | 0, // ifreq = 0.000000 MHz
656 20452225, // timf
657 12000000, // xtal_hz
658};
659
660static struct dib7000p_config dib7070p_dib7000p_config = {
661 .output_mpeg2_in_188_bytes = 1,
662
663 .agc_config_count = 1,
664 .agc = &dib7070_agc_config,
665 .bw = &dib7070_bw_config_12_mhz,
666
667 .gpio_dir = DIB7000P_GPIO_DEFAULT_DIRECTIONS,
668 .gpio_val = DIB7000P_GPIO_DEFAULT_VALUES,
669 .gpio_pwm_pos = DIB7000P_GPIO_DEFAULT_PWM_POS,
670
671 .hostbus_diversity = 1,
672};
673
674/* STK7070P */
675static int stk7070p_frontend_attach(struct dvb_usb_adapter *adap)
676{
677 dib0700_set_gpio(adap->dev, GPIO6, GPIO_OUT, 1);
678 msleep(10);
679 dib0700_set_gpio(adap->dev, GPIO9, GPIO_OUT, 1);
680 dib0700_set_gpio(adap->dev, GPIO4, GPIO_OUT, 1);
681 dib0700_set_gpio(adap->dev, GPIO7, GPIO_OUT, 1);
682 dib0700_set_gpio(adap->dev, GPIO10, GPIO_OUT, 0);
683
684 dib0700_ctrl_clock(adap->dev, 72, 1);
685
686 msleep(10);
687 dib0700_set_gpio(adap->dev, GPIO10, GPIO_OUT, 1);
688 msleep(10);
689 dib0700_set_gpio(adap->dev, GPIO0, GPIO_OUT, 1);
690
691 dib7000p_i2c_enumeration(&adap->dev->i2c_adap, 1, 18, &dib7070p_dib7000p_config);
692
693 adap->fe = dvb_attach(dib7000p_attach, &adap->dev->i2c_adap, 0x80, &dib7070p_dib7000p_config);
694 return adap->fe == NULL ? -ENODEV : 0;
695}
696
697/* STK7070PD */
698static struct dib7000p_config stk7070pd_dib7000p_config[2] = {
699 {
700 .output_mpeg2_in_188_bytes = 1,
701
702 .agc_config_count = 1,
703 .agc = &dib7070_agc_config,
704 .bw = &dib7070_bw_config_12_mhz,
705
706 .gpio_dir = DIB7000P_GPIO_DEFAULT_DIRECTIONS,
707 .gpio_val = DIB7000P_GPIO_DEFAULT_VALUES,
708 .gpio_pwm_pos = DIB7000P_GPIO_DEFAULT_PWM_POS,
709
710 .hostbus_diversity = 1,
711 }, {
712 .output_mpeg2_in_188_bytes = 1,
713
714 .agc_config_count = 1,
715 .agc = &dib7070_agc_config,
716 .bw = &dib7070_bw_config_12_mhz,
717
718 .gpio_dir = DIB7000P_GPIO_DEFAULT_DIRECTIONS,
719 .gpio_val = DIB7000P_GPIO_DEFAULT_VALUES,
720 .gpio_pwm_pos = DIB7000P_GPIO_DEFAULT_PWM_POS,
721
722 .hostbus_diversity = 1,
723 }
724};
725
726static int stk7070pd_frontend_attach0(struct dvb_usb_adapter *adap)
727{
728 dib0700_set_gpio(adap->dev, GPIO6, GPIO_OUT, 1);
729 msleep(10);
730 dib0700_set_gpio(adap->dev, GPIO9, GPIO_OUT, 1);
731 dib0700_set_gpio(adap->dev, GPIO4, GPIO_OUT, 1);
732 dib0700_set_gpio(adap->dev, GPIO7, GPIO_OUT, 1);
733 dib0700_set_gpio(adap->dev, GPIO10, GPIO_OUT, 0);
734
735 dib0700_ctrl_clock(adap->dev, 72, 1);
736
737 msleep(10);
738 dib0700_set_gpio(adap->dev, GPIO10, GPIO_OUT, 1);
739 msleep(10);
740 dib0700_set_gpio(adap->dev, GPIO0, GPIO_OUT, 1);
741
742 dib7000p_i2c_enumeration(&adap->dev->i2c_adap, 2, 18, stk7070pd_dib7000p_config);
743
744 adap->fe = dvb_attach(dib7000p_attach, &adap->dev->i2c_adap, 0x80, &stk7070pd_dib7000p_config[0]);
745 return adap->fe == NULL ? -ENODEV : 0;
746}
747
748static int stk7070pd_frontend_attach1(struct dvb_usb_adapter *adap)
749{
750 adap->fe = dvb_attach(dib7000p_attach, &adap->dev->i2c_adap, 0x82, &stk7070pd_dib7000p_config[1]);
751 return adap->fe == NULL ? -ENODEV : 0;
752}
753
754/* DVB-USB and USB stuff follows */
542struct usb_device_id dib0700_usb_id_table[] = { 755struct usb_device_id dib0700_usb_id_table[] = {
543 { USB_DEVICE(USB_VID_DIBCOM, USB_PID_DIBCOM_STK7700P) }, 756/* 0 */ { USB_DEVICE(USB_VID_DIBCOM, USB_PID_DIBCOM_STK7700P) },
544 { USB_DEVICE(USB_VID_DIBCOM, USB_PID_DIBCOM_STK7700P_PC) }, 757 { USB_DEVICE(USB_VID_DIBCOM, USB_PID_DIBCOM_STK7700P_PC) },
545 758
546 { USB_DEVICE(USB_VID_HAUPPAUGE, USB_PID_HAUPPAUGE_NOVA_T_500) }, 759 { USB_DEVICE(USB_VID_HAUPPAUGE, USB_PID_HAUPPAUGE_NOVA_T_500) },
547 { USB_DEVICE(USB_VID_HAUPPAUGE, USB_PID_HAUPPAUGE_NOVA_T_500_2) }, 760 { USB_DEVICE(USB_VID_HAUPPAUGE, USB_PID_HAUPPAUGE_NOVA_T_500_2) },
548 { USB_DEVICE(USB_VID_HAUPPAUGE, USB_PID_HAUPPAUGE_NOVA_T_STICK) }, 761 { USB_DEVICE(USB_VID_HAUPPAUGE, USB_PID_HAUPPAUGE_NOVA_T_STICK) },
549 { USB_DEVICE(USB_VID_AVERMEDIA, USB_PID_AVERMEDIA_VOLAR) }, 762/* 5 */ { USB_DEVICE(USB_VID_AVERMEDIA, USB_PID_AVERMEDIA_VOLAR) },
550 { USB_DEVICE(USB_VID_COMPRO, USB_PID_COMPRO_VIDEOMATE_U500) }, 763 { USB_DEVICE(USB_VID_COMPRO, USB_PID_COMPRO_VIDEOMATE_U500) },
551 { USB_DEVICE(USB_VID_UNIWILL, USB_PID_UNIWILL_STK7700P) }, 764 { USB_DEVICE(USB_VID_UNIWILL, USB_PID_UNIWILL_STK7700P) },
552 { USB_DEVICE(USB_VID_LEADTEK, USB_PID_WINFAST_DTV_DONGLE_STK7700P) }, 765 { USB_DEVICE(USB_VID_LEADTEK, USB_PID_WINFAST_DTV_DONGLE_STK7700P) },
553 { USB_DEVICE(USB_VID_HAUPPAUGE, USB_PID_HAUPPAUGE_NOVA_T_STICK_2) }, 766 { USB_DEVICE(USB_VID_HAUPPAUGE, USB_PID_HAUPPAUGE_NOVA_T_STICK_2) },
554 { USB_DEVICE(USB_VID_AVERMEDIA, USB_PID_AVERMEDIA_VOLAR_2) }, 767/* 10 */{ USB_DEVICE(USB_VID_AVERMEDIA, USB_PID_AVERMEDIA_VOLAR_2) },
555 { USB_DEVICE(USB_VID_PINNACLE, USB_PID_PINNACLE_PCTV2000E) }, 768 { USB_DEVICE(USB_VID_PINNACLE, USB_PID_PINNACLE_PCTV2000E) },
556 { USB_DEVICE(USB_VID_TERRATEC, USB_PID_TERRATEC_CINERGY_DT_XS_DIVERSITY) }, 769 { USB_DEVICE(USB_VID_TERRATEC, USB_PID_TERRATEC_CINERGY_DT_XS_DIVERSITY) },
557 { USB_DEVICE(USB_VID_HAUPPAUGE, USB_PID_HAUPPAUGE_NOVA_TD_STICK) }, 770 { USB_DEVICE(USB_VID_HAUPPAUGE, USB_PID_HAUPPAUGE_NOVA_TD_STICK) },
558 { USB_DEVICE(USB_VID_DIBCOM, USB_PID_DIBCOM_STK7700D) }, 771 { USB_DEVICE(USB_VID_DIBCOM, USB_PID_DIBCOM_STK7700D) },
559 { } /* Terminating entry */ 772/* 15 */{ USB_DEVICE(USB_VID_DIBCOM, USB_PID_DIBCOM_STK7070P) },
773 { USB_DEVICE(USB_VID_PINNACLE, USB_PID_PINNACLE_PCTV_DVB_T_FLASH) },
774 { USB_DEVICE(USB_VID_DIBCOM, USB_PID_DIBCOM_STK7070PD) },
775 { USB_DEVICE(USB_VID_PINNACLE, USB_PID_PINNACLE_PCTV_DUAL_DIVERSITY_DVB_T) },
776 { 0 } /* Terminating entry */
560}; 777};
561MODULE_DEVICE_TABLE(usb, dib0700_usb_id_table); 778MODULE_DEVICE_TABLE(usb, dib0700_usb_id_table);
562 779
563#define DIB0700_DEFAULT_DEVICE_PROPERTIES \ 780#define DIB0700_DEFAULT_DEVICE_PROPERTIES \
564 .caps = DVB_USB_IS_AN_I2C_ADAPTER, \ 781 .caps = DVB_USB_IS_AN_I2C_ADAPTER, \
565 .usb_ctrl = DEVICE_SPECIFIC, \ 782 .usb_ctrl = DEVICE_SPECIFIC, \
566 .firmware = "dvb-usb-dib0700-01.fw", \ 783 .firmware = "dvb-usb-dib0700-03-pre1.fw", \
567 .download_firmware = dib0700_download_firmware, \ 784 .download_firmware = dib0700_download_firmware, \
568 .no_reconnect = 1, \ 785 .no_reconnect = 1, \
569 .size_of_priv = sizeof(struct dib0700_state), \ 786 .size_of_priv = sizeof(struct dib0700_state), \
@@ -675,11 +892,11 @@ struct dvb_usb_device_properties dib0700_devices[] = {
675 { &dib0700_usb_id_table[12], NULL }, 892 { &dib0700_usb_id_table[12], NULL },
676 { NULL }, 893 { NULL },
677 }, 894 },
678 { "Haupauge Nova-TD Stick", 895 { "Haupauge Nova-TD Stick/Elgato Eye-TV Diversity",
679 { &dib0700_usb_id_table[13], NULL }, 896 { &dib0700_usb_id_table[13], NULL },
680 { NULL }, 897 { NULL },
681 }, 898 },
682 { "DiBcom STK7700D", 899 { "DiBcom STK7700D reference design",
683 { &dib0700_usb_id_table[14], NULL }, 900 { &dib0700_usb_id_table[14], NULL },
684 { NULL }, 901 { NULL },
685 }, 902 },
@@ -688,7 +905,65 @@ struct dvb_usb_device_properties dib0700_devices[] = {
688 .rc_key_map = stk7700d_rc_keys, 905 .rc_key_map = stk7700d_rc_keys,
689 .rc_key_map_size = KEY_MAP_SIZE, 906 .rc_key_map_size = KEY_MAP_SIZE,
690 .rc_query = stk7700d_rc_query 907 .rc_query = stk7700d_rc_query
691 } 908
909 }, { DIB0700_DEFAULT_DEVICE_PROPERTIES,
910
911 .num_adapters = 1,
912 .adapter = {
913 {
914 .frontend_attach = stk7070p_frontend_attach,
915 .tuner_attach = dib7070p_tuner_attach,
916
917 DIB0700_DEFAULT_STREAMING_CONFIG(0x02),
918
919 .size_of_priv = sizeof(struct dib0700_adapter_state),
920 },
921 },
922
923 .num_device_descs = 2,
924 .devices = {
925 { "DiBcom STK7070P reference design",
926 { &dib0700_usb_id_table[15], NULL },
927 { NULL },
928 },
929 { "Pinnacle PCTV DVB-T Flash Stick",
930 { &dib0700_usb_id_table[16], NULL },
931 { NULL },
932 },
933 }
934 }, { DIB0700_DEFAULT_DEVICE_PROPERTIES,
935
936 .num_adapters = 2,
937 .adapter = {
938 {
939 .frontend_attach = stk7070pd_frontend_attach0,
940 .tuner_attach = dib7070p_tuner_attach,
941
942 DIB0700_DEFAULT_STREAMING_CONFIG(0x02),
943
944 .size_of_priv = sizeof(struct dib0700_adapter_state),
945 }, {
946 .frontend_attach = stk7070pd_frontend_attach1,
947 .tuner_attach = dib7070p_tuner_attach,
948
949 DIB0700_DEFAULT_STREAMING_CONFIG(0x03),
950
951 .size_of_priv = sizeof(struct dib0700_adapter_state),
952 }
953 },
954
955 .num_device_descs = 2,
956 .devices = {
957 { "DiBcom STK7070PD reference design",
958 { &dib0700_usb_id_table[17], NULL },
959 { NULL },
960 },
961 { "Pinnacle PCTV Dual DVB-T Diversity Stick",
962 { &dib0700_usb_id_table[18], NULL },
963 { NULL },
964 },
965 }
966 },
692}; 967};
693 968
694int dib0700_device_count = ARRAY_SIZE(dib0700_devices); 969int dib0700_device_count = ARRAY_SIZE(dib0700_devices);
diff --git a/drivers/media/dvb/dvb-usb/dvb-usb-ids.h b/drivers/media/dvb/dvb-usb/dvb-usb-ids.h
index 5657ad8beaac..dae605bbd0f9 100644
--- a/drivers/media/dvb/dvb-usb/dvb-usb-ids.h
+++ b/drivers/media/dvb/dvb-usb/dvb-usb-ids.h
@@ -68,6 +68,8 @@
68#define USB_PID_DIBCOM_STK7700P 0x1e14 68#define USB_PID_DIBCOM_STK7700P 0x1e14
69#define USB_PID_DIBCOM_STK7700P_PC 0x1e78 69#define USB_PID_DIBCOM_STK7700P_PC 0x1e78
70#define USB_PID_DIBCOM_STK7700D 0x1ef0 70#define USB_PID_DIBCOM_STK7700D 0x1ef0
71#define USB_PID_DIBCOM_STK7070P 0x1ebc
72#define USB_PID_DIBCOM_STK7070PD 0x1ebe
71#define USB_PID_DIBCOM_ANCHOR_2135_COLD 0x2131 73#define USB_PID_DIBCOM_ANCHOR_2135_COLD 0x2131
72#define USB_PID_DPOSH_M9206_COLD 0x9206 74#define USB_PID_DPOSH_M9206_COLD 0x9206
73#define USB_PID_DPOSH_M9206_WARM 0xa090 75#define USB_PID_DPOSH_M9206_WARM 0xa090
@@ -122,6 +124,11 @@
122#define USB_PID_AVERMEDIA_VOLAR_2 0xb808 124#define USB_PID_AVERMEDIA_VOLAR_2 0xb808
123#define USB_PID_TERRATEC_CINERGY_DT_XS_DIVERSITY 0x005a 125#define USB_PID_TERRATEC_CINERGY_DT_XS_DIVERSITY 0x005a
124#define USB_PID_PINNACLE_PCTV2000E 0x022c 126#define USB_PID_PINNACLE_PCTV2000E 0x022c
127#define USB_PID_PINNACLE_PCTV_DVB_T_FLASH 0x0228
128#define USB_PID_PINNACLE_PCTV_DUAL_DIVERSITY_DVB_T 0x0229
129#define USB_PID_PCTV_200E 0x020e
130#define USB_PID_PCTV_400E 0x020f
131#define USB_PID_PCTV_450E 0x0222
125#define USB_PID_NEBULA_DIGITV 0x0201 132#define USB_PID_NEBULA_DIGITV 0x0201
126#define USB_PID_DVICO_BLUEBIRD_LGDT 0xd820 133#define USB_PID_DVICO_BLUEBIRD_LGDT 0xd820
127#define USB_PID_DVICO_BLUEBIRD_LG064F_COLD 0xd500 134#define USB_PID_DVICO_BLUEBIRD_LG064F_COLD 0xd500
@@ -141,9 +148,6 @@
141#define USB_PID_MSI_MEGASKY580_55801 0x5581 148#define USB_PID_MSI_MEGASKY580_55801 0x5581
142#define USB_PID_KYE_DVB_T_COLD 0x701e 149#define USB_PID_KYE_DVB_T_COLD 0x701e
143#define USB_PID_KYE_DVB_T_WARM 0x701f 150#define USB_PID_KYE_DVB_T_WARM 0x701f
144#define USB_PID_PCTV_200E 0x020e
145#define USB_PID_PCTV_400E 0x020f
146#define USB_PID_PCTV_450E 0x0222
147#define USB_PID_LITEON_DVB_T_COLD 0xf000 151#define USB_PID_LITEON_DVB_T_COLD 0xf000
148#define USB_PID_LITEON_DVB_T_WARM 0xf001 152#define USB_PID_LITEON_DVB_T_WARM 0xf001
149#define USB_PID_DIGIVOX_MINI_SL_COLD 0xe360 153#define USB_PID_DIGIVOX_MINI_SL_COLD 0xe360
diff --git a/drivers/media/dvb/frontends/Kconfig b/drivers/media/dvb/frontends/Kconfig
index faf9fe3c9cce..53e775539649 100644
--- a/drivers/media/dvb/frontends/Kconfig
+++ b/drivers/media/dvb/frontends/Kconfig
@@ -344,6 +344,15 @@ config DVB_TUNER_MT2131
344 help 344 help
345 A driver for the silicon baseband tuner MT2131 from Microtune. 345 A driver for the silicon baseband tuner MT2131 from Microtune.
346 346
347config DVB_TUNER_DIB0070
348 tristate "DiBcom DiB0070 silicon base-band tuner"
349 depends on I2C
350 default m if DVB_FE_CUSTOMISE
351 help
352 A driver for the silicon baseband tuner DiB0070 from DiBcom.
353 This device is only used inside a SiP called togther with a
354 demodulator for now.
355
347comment "Miscellaneous devices" 356comment "Miscellaneous devices"
348 depends on DVB_CORE 357 depends on DVB_CORE
349 358
diff --git a/drivers/media/dvb/frontends/Makefile b/drivers/media/dvb/frontends/Makefile
index c46b9d8e9313..4b8ad1f132aa 100644
--- a/drivers/media/dvb/frontends/Makefile
+++ b/drivers/media/dvb/frontends/Makefile
@@ -41,6 +41,7 @@ obj-$(CONFIG_DVB_TDA826X) += tda826x.o
41obj-$(CONFIG_DVB_TDA827X) += tda827x.o 41obj-$(CONFIG_DVB_TDA827X) += tda827x.o
42obj-$(CONFIG_DVB_TUNER_MT2060) += mt2060.o 42obj-$(CONFIG_DVB_TUNER_MT2060) += mt2060.o
43obj-$(CONFIG_DVB_TUNER_MT2266) += mt2266.o 43obj-$(CONFIG_DVB_TUNER_MT2266) += mt2266.o
44obj-$(CONFIG_DVB_TUNER_DIB0070) += dib0070.o
44obj-$(CONFIG_DVB_TUNER_QT1010) += qt1010.o 45obj-$(CONFIG_DVB_TUNER_QT1010) += qt1010.o
45obj-$(CONFIG_DVB_TUA6100) += tua6100.o 46obj-$(CONFIG_DVB_TUA6100) += tua6100.o
46obj-$(CONFIG_DVB_TUNER_MT2131) += mt2131.o 47obj-$(CONFIG_DVB_TUNER_MT2131) += mt2131.o
diff --git a/drivers/media/dvb/frontends/dib0070.c b/drivers/media/dvb/frontends/dib0070.c
new file mode 100644
index 000000000000..481eaa684157
--- /dev/null
+++ b/drivers/media/dvb/frontends/dib0070.c
@@ -0,0 +1,580 @@
1/*
2 * Linux-DVB Driver for DiBcom's DiB0070 base-band RF Tuner.
3 *
4 * Copyright (C) 2005-7 DiBcom (http://www.dibcom.fr/)
5 *
6 * This program is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU General Public License as
8 * published by the Free Software Foundation, version 2.
9 */
10#include <linux/kernel.h>
11#include <linux/i2c.h>
12
13#include "dvb_frontend.h"
14
15#include "dib0070.h"
16#include "dibx000_common.h"
17
18static int debug;
19module_param(debug, int, 0644);
20MODULE_PARM_DESC(debug, "turn on debugging (default: 0)");
21
22#define dprintk(args...) do { if (debug) { printk(KERN_DEBUG "DiB0070: "); printk(args); printk("\n"); } } while (0)
23
24#define DIB0070_P1D 0x00
25#define DIB0070_P1F 0x01
26#define DIB0070_P1G 0x03
27#define DIB0070S_P1A 0x02
28
29struct dib0070_state {
30 struct i2c_adapter *i2c;
31 struct dvb_frontend *fe;
32 const struct dib0070_config *cfg;
33 u16 wbd_ff_offset;
34 u8 revision;
35};
36
37static uint16_t dib0070_read_reg(struct dib0070_state *state, u8 reg)
38{
39 u8 b[2];
40 struct i2c_msg msg[2] = {
41 { .addr = state->cfg->i2c_address, .flags = 0, .buf = &reg, .len = 1 },
42 { .addr = state->cfg->i2c_address, .flags = I2C_M_RD, .buf = b, .len = 2 },
43 };
44 if (i2c_transfer(state->i2c, msg, 2) != 2) {
45 printk(KERN_WARNING "DiB0070 I2C read failed\n");
46 return 0;
47 }
48 return (b[0] << 8) | b[1];
49}
50
51static int dib0070_write_reg(struct dib0070_state *state, u8 reg, u16 val)
52{
53 u8 b[3] = { reg, val >> 8, val & 0xff };
54 struct i2c_msg msg = { .addr = state->cfg->i2c_address, .flags = 0, .buf = b, .len = 3 };
55 if (i2c_transfer(state->i2c, &msg, 1) != 1) {
56 printk(KERN_WARNING "DiB0070 I2C write failed\n");
57 return -EREMOTEIO;
58 }
59 return 0;
60}
61
62#define HARD_RESET(state) do { if (state->cfg->reset) { state->cfg->reset(state->fe,1); msleep(10); state->cfg->reset(state->fe,0); msleep(10); } } while (0)
63
64static int dib0070_set_bandwidth(struct dvb_frontend *fe, struct dvb_frontend_parameters *ch)
65{
66 struct dib0070_state *st = fe->tuner_priv;
67 u16 tmp = 0;
68 tmp = dib0070_read_reg(st, 0x02) & 0x3fff;
69
70 switch(BANDWIDTH_TO_KHZ(ch->u.ofdm.bandwidth)) {
71 case 8000:
72 tmp |= (0 << 14);
73 break;
74 case 7000:
75 tmp |= (1 << 14);
76 break;
77 case 6000:
78 tmp |= (2 << 14);
79 break;
80 case 5000:
81 default:
82 tmp |= (3 << 14);
83 break;
84 }
85 dib0070_write_reg(st, 0x02, tmp);
86 return 0;
87}
88
89static void dib0070_captrim(struct dib0070_state *st, u16 LO4)
90{
91 int8_t captrim, fcaptrim, step_sign, step;
92 u16 adc, adc_diff = 3000;
93
94
95
96 dib0070_write_reg(st, 0x0f, 0xed10);
97 dib0070_write_reg(st, 0x17, 0x0034);
98
99 dib0070_write_reg(st, 0x18, 0x0032);
100 msleep(2);
101
102 step = captrim = fcaptrim = 64;
103
104 do {
105 step /= 2;
106 dib0070_write_reg(st, 0x14, LO4 | captrim);
107 msleep(1);
108 adc = dib0070_read_reg(st, 0x19);
109
110 dprintk( "CAPTRIM=%hd; ADC = %hd (ADC) & %dmV", captrim, adc, (u32) adc*(u32)1800/(u32)1024);
111
112 if (adc >= 400) {
113 adc -= 400;
114 step_sign = -1;
115 } else {
116 adc = 400 - adc;
117 step_sign = 1;
118 }
119
120 if (adc < adc_diff) {
121 dprintk( "CAPTRIM=%hd is closer to target (%hd/%hd)", captrim, adc, adc_diff);
122 adc_diff = adc;
123 fcaptrim = captrim;
124
125
126
127 }
128 captrim += (step_sign * step);
129 } while (step >= 1);
130
131 dib0070_write_reg(st, 0x14, LO4 | fcaptrim);
132 dib0070_write_reg(st, 0x18, 0x07ff);
133}
134
135#define LPF 100 // define for the loop filter 100kHz by default 16-07-06
136#define LO4_SET_VCO_HFDIV(l, v, h) l |= ((v) << 11) | ((h) << 7)
137#define LO4_SET_SD(l, s) l |= ((s) << 14) | ((s) << 12)
138#define LO4_SET_CTRIM(l, c) l |= (c) << 10
139static int dib0070_tune_digital(struct dvb_frontend *fe, struct dvb_frontend_parameters *ch)
140{
141 struct dib0070_state *st = fe->tuner_priv;
142 u32 freq = ch->frequency/1000 + (BAND_OF_FREQUENCY(ch->frequency/1000) == BAND_VHF ? st->cfg->freq_offset_khz_vhf : st->cfg->freq_offset_khz_uhf);
143
144 u8 band = BAND_OF_FREQUENCY(freq), c;
145
146 /*******************VCO***********************************/
147 u16 lo4 = 0;
148
149 u8 REFDIV, PRESC = 2;
150 u32 FBDiv, Rest, FREF, VCOF_kHz;
151 u16 Num, Den;
152 /*******************FrontEnd******************************/
153 u16 value = 0;
154
155 dprintk( "Tuning for Band: %hd (%d kHz)", band, freq);
156
157
158 dib0070_write_reg(st, 0x17, 0x30);
159
160 dib0070_set_bandwidth(fe, ch); /* c is used as HF */
161 switch (st->revision) {
162 case DIB0070S_P1A:
163 switch (band) {
164 case BAND_LBAND:
165 LO4_SET_VCO_HFDIV(lo4, 1, 1);
166 c = 2;
167 break;
168 case BAND_SBAND:
169 LO4_SET_VCO_HFDIV(lo4, 0, 0);
170 LO4_SET_CTRIM(lo4, 1);;
171 c = 1;
172 break;
173 case BAND_UHF:
174 default:
175 if (freq < 570000) {
176 LO4_SET_VCO_HFDIV(lo4, 1, 3);
177 PRESC = 6; c = 6;
178 } else if (freq < 680000) {
179 LO4_SET_VCO_HFDIV(lo4, 0, 2);
180 c = 4;
181 } else {
182 LO4_SET_VCO_HFDIV(lo4, 1, 2);
183 c = 4;
184 }
185 break;
186 } break;
187
188 case DIB0070_P1G:
189 case DIB0070_P1F:
190 default:
191 switch (band) {
192 case BAND_FM:
193 LO4_SET_VCO_HFDIV(lo4, 0, 7);
194 c = 24;
195 break;
196 case BAND_LBAND:
197 LO4_SET_VCO_HFDIV(lo4, 1, 0);
198 c = 2;
199 break;
200 case BAND_VHF:
201 if (freq < 180000) {
202 LO4_SET_VCO_HFDIV(lo4, 0, 3);
203 c = 16;
204 } else if (freq < 190000) {
205 LO4_SET_VCO_HFDIV(lo4, 1, 3);
206 c = 16;
207 } else {
208 LO4_SET_VCO_HFDIV(lo4, 0, 6);
209 c = 12;
210 }
211 break;
212
213 case BAND_UHF:
214 default:
215 if (freq < 570000) {
216 LO4_SET_VCO_HFDIV(lo4, 1, 5);
217 c = 6;
218 } else if (freq < 700000) {
219 LO4_SET_VCO_HFDIV(lo4, 0, 1);
220 c = 4;
221 } else {
222 LO4_SET_VCO_HFDIV(lo4, 1, 1);
223 c = 4;
224 }
225 break;
226 }
227 break;
228 }
229
230 dprintk( "HFDIV code: %hd", (lo4 >> 7) & 0xf);
231 dprintk( "VCO = %hd", (lo4 >> 11) & 0x3);
232
233
234 VCOF_kHz = (c * freq) * 2;
235 dprintk( "VCOF in kHz: %d ((%hd*%d) << 1))",VCOF_kHz, c, freq);
236
237 switch (band) {
238 case BAND_VHF:
239 REFDIV = (u8) ((st->cfg->clock_khz + 9999) / 10000);
240 break;
241 case BAND_FM:
242 REFDIV = (u8) ((st->cfg->clock_khz) / 1000);
243 break;
244 default:
245 REFDIV = (u8) ( st->cfg->clock_khz / 10000);
246 break;
247 }
248 FREF = st->cfg->clock_khz / REFDIV;
249
250 dprintk( "REFDIV: %hd, FREF: %d", REFDIV, FREF);
251
252
253
254 switch (st->revision) {
255 case DIB0070S_P1A:
256 FBDiv = (VCOF_kHz / PRESC / FREF);
257 Rest = (VCOF_kHz / PRESC) - FBDiv * FREF;
258 break;
259
260 case DIB0070_P1G:
261 case DIB0070_P1F:
262 default:
263 FBDiv = (freq / (FREF / 2));
264 Rest = 2 * freq - FBDiv * FREF;
265 break;
266 }
267
268
269 if (Rest < LPF) Rest = 0;
270 else if (Rest < 2 * LPF) Rest = 2 * LPF;
271 else if (Rest > (FREF - LPF)) { Rest = 0 ; FBDiv += 1; }
272 else if (Rest > (FREF - 2 * LPF)) Rest = FREF - 2 * LPF;
273 Rest = (Rest * 6528) / (FREF / 10);
274 dprintk( "FBDIV: %d, Rest: %d", FBDiv, Rest);
275
276 Num = 0;
277 Den = 1;
278
279 if (Rest > 0) {
280 LO4_SET_SD(lo4, 1);
281 Den = 255;
282 Num = (u16)Rest;
283 }
284 dprintk( "Num: %hd, Den: %hd, SD: %hd",Num, Den, (lo4 >> 12) & 0x1);
285
286
287
288 dib0070_write_reg(st, 0x11, (u16)FBDiv);
289
290
291 dib0070_write_reg(st, 0x12, (Den << 8) | REFDIV);
292
293
294 dib0070_write_reg(st, 0x13, Num);
295
296
297 value = 0x0040 | 0x0020 | 0x0010 | 0x0008 | 0x0002 | 0x0001;
298
299 switch (band) {
300 case BAND_UHF: value |= 0x4000 | 0x0800; break;
301 case BAND_LBAND: value |= 0x2000 | 0x0400; break;
302 default: value |= 0x8000 | 0x1000; break;
303 }
304 dib0070_write_reg(st, 0x20, value);
305
306 dib0070_captrim(st, lo4);
307 if (st->revision == DIB0070S_P1A) {
308 if (band == BAND_SBAND)
309 dib0070_write_reg(st, 0x15, 0x16e2);
310 else
311 dib0070_write_reg(st, 0x15, 0x56e5);
312 }
313
314
315
316 switch (band) {
317 case BAND_UHF: value = 0x7c82; break;
318 case BAND_LBAND: value = 0x7c84; break;
319 default: value = 0x7c81; break;
320 }
321 dib0070_write_reg(st, 0x0f, value);
322 dib0070_write_reg(st, 0x06, 0x3fff);
323
324 /* Front End */
325 /* c == TUNE, value = SWITCH */
326 c = 0;
327 value = 0;
328 switch (band) {
329 case BAND_FM:
330 c = 0; value = 1;
331 break;
332
333 case BAND_VHF:
334 if (freq <= 180000) c = 0;
335 else if (freq <= 188200) c = 1;
336 else if (freq <= 196400) c = 2;
337 else c = 3;
338 value = 1;
339 break;
340
341 case BAND_LBAND:
342 if (freq <= 1500000) c = 0;
343 else if (freq <= 1600000) c = 1;
344 else c = 3;
345 break;
346
347 case BAND_SBAND:
348 c = 7;
349 dib0070_write_reg(st, 0x1d,0xFFFF);
350 break;
351
352 case BAND_UHF:
353 default:
354 if (st->cfg->flip_chip) {
355 if (freq <= 550000) c = 0;
356 else if (freq <= 590000) c = 1;
357 else if (freq <= 666000) c = 3;
358 else c = 5;
359 } else {
360 if (freq <= 550000) c = 2;
361 else if (freq <= 650000) c = 3;
362 else if (freq <= 750000) c = 5;
363 else if (freq <= 850000) c = 6;
364 else c = 7;
365 }
366 value = 2;
367 break;
368 }
369
370 /* default: LNA_MATCH=7, BIAS=3 */
371 dib0070_write_reg(st, 0x07, (value << 11) | (7 << 8) | (c << 3) | (3 << 0));
372 dib0070_write_reg(st, 0x08, (c << 10) | (3 << 7) | (127));
373 dib0070_write_reg(st, 0x0d, 0x0d80);
374
375
376 dib0070_write_reg(st, 0x18, 0x07ff);
377 dib0070_write_reg(st, 0x17, 0x0033);
378
379 return 0;
380}
381
382static int dib0070_wakeup(struct dvb_frontend *fe)
383{
384 struct dib0070_state *st = fe->tuner_priv;
385 if (st->cfg->sleep)
386 st->cfg->sleep(fe, 0);
387 return 0;
388}
389
390static int dib0070_sleep(struct dvb_frontend *fe)
391{
392 struct dib0070_state *st = fe->tuner_priv;
393 if (st->cfg->sleep)
394 st->cfg->sleep(fe, 1);
395 return 0;
396}
397
398static u16 dib0070_p1f_defaults[] =
399
400{
401 7, 0x02,
402 0x0008,
403 0x0000,
404 0x0000,
405 0x0000,
406 0x0000,
407 0x0002,
408 0x0100,
409
410 3, 0x0d,
411 0x0d80,
412 0x0001,
413 0x0000,
414
415 4, 0x11,
416 0x0000,
417 0x0103,
418 0x0000,
419 0x0000,
420
421 3, 0x16,
422 0x0004 | 0x0040,
423 0x0030,
424 0x07ff,
425
426 6, 0x1b,
427 0x4112,
428 0xff00,
429 0xc07f,
430 0x0000,
431 0x0180,
432 0x4000 | 0x0800 | 0x0040 | 0x0020 | 0x0010 | 0x0008 | 0x0002 | 0x0001,
433
434 0,
435};
436
437static void dib0070_wbd_calibration(struct dib0070_state *state)
438{
439 u16 wbd_offs;
440 dib0070_write_reg(state, 0x0f, 0x6d81);
441 dib0070_write_reg(state, 0x20, 0x0040 | 0x0020 | 0x0010 | 0x0008 | 0x0002 | 0x0001);
442 msleep(9);
443 wbd_offs = dib0070_read_reg(state, 0x19);
444 dib0070_write_reg(state, 0x20, 0);
445 state->wbd_ff_offset = ((wbd_offs * 8 * 18 / 33 + 1) / 2);
446 dprintk( "WBDStart = %d (Vargen) - FF = %hd", (u32) wbd_offs * 1800/1024, state->wbd_ff_offset);
447}
448
449u16 dib0070_wbd_offset(struct dvb_frontend *fe)
450{
451 struct dib0070_state *st = fe->tuner_priv;
452 return st->wbd_ff_offset;
453}
454
455EXPORT_SYMBOL(dib0070_wbd_offset);
456static int dib0070_set_ctrl_lo5(struct dvb_frontend *fe, u8 vco_bias_trim, u8 hf_div_trim, u8 cp_current, u8 third_order_filt)
457{
458 struct dib0070_state *state = fe->tuner_priv;
459 u16 lo5 = (third_order_filt << 14) | (0 << 13) | (1 << 12) | (3 << 9) | (cp_current << 6) | (hf_div_trim << 3) | (vco_bias_trim << 0);
460 dprintk( "CTRL_LO5: 0x%x", lo5);
461 return dib0070_write_reg(state, 0x15, lo5);
462}
463
464#define pgm_read_word(w) (*w)
465static int dib0070_reset(struct dib0070_state *state)
466{
467 u16 l, r, *n;
468
469 HARD_RESET(state);
470
471
472#ifndef FORCE_SBAND_TUNER
473 if ((dib0070_read_reg(state, 0x22) >> 9) & 0x1)
474 state->revision = (dib0070_read_reg(state, 0x1f) >> 8) & 0xff;
475 else
476#endif
477 state->revision = DIB0070S_P1A;
478
479 /* P1F or not */
480 dprintk( "Revision: %x", state->revision);
481
482 if (state->revision == DIB0070_P1D) {
483 dprintk( "Error: this driver is not to be used meant for P1D or earlier");
484 return -EINVAL;
485 }
486
487 n = (u16 *) dib0070_p1f_defaults;
488 l = pgm_read_word(n++);
489 while (l) {
490 r = pgm_read_word(n++);
491 do {
492 dib0070_write_reg(state, (u8)r, pgm_read_word(n++));
493 r++;
494 } while (--l);
495 l = pgm_read_word(n++);
496 }
497
498 if (state->cfg->force_crystal_mode != 0)
499 r = state->cfg->force_crystal_mode;
500 else if (state->cfg->clock_khz >= 24000)
501 r = 1;
502 else
503 r = 2;
504
505 r |= state->cfg->osc_buffer_state << 3;
506
507 dib0070_write_reg(state, 0x10, r);
508 dib0070_write_reg(state, 0x1f, (1 << 8) | ((state->cfg->clock_pad_drive & 0xf) << 4));
509
510 if (state->cfg->invert_iq) {
511 r = dib0070_read_reg(state, 0x02) & 0xffdf;
512 dib0070_write_reg(state, 0x02, r | (1 << 5));
513 }
514
515
516 if (state->revision == DIB0070S_P1A)
517 dib0070_set_ctrl_lo5(state->fe, 4, 7, 3, 1);
518 else
519 dib0070_set_ctrl_lo5(state->fe, 4, 4, 2, 0);
520
521 dib0070_write_reg(state, 0x01, (54 << 9) | 0xc8);
522 return 0;
523}
524
525
526static int dib0070_release(struct dvb_frontend *fe)
527{
528 kfree(fe->tuner_priv);
529 fe->tuner_priv = NULL;
530 return 0;
531}
532
533static struct dvb_tuner_ops dib0070_ops = {
534 .info = {
535 .name = "DiBcom DiB0070",
536 .frequency_min = 45000000,
537 .frequency_max = 860000000,
538 .frequency_step = 1000,
539 },
540 .release = dib0070_release,
541
542 .init = dib0070_wakeup,
543 .sleep = dib0070_sleep,
544 .set_params = dib0070_tune_digital,
545// .get_frequency = dib0070_get_frequency,
546// .get_bandwidth = dib0070_get_bandwidth
547};
548
549struct dvb_frontend * dib0070_attach(struct dvb_frontend *fe, struct i2c_adapter *i2c, struct dib0070_config *cfg)
550{
551 struct dib0070_state *state = kzalloc(sizeof(struct dib0070_state), GFP_KERNEL);
552 if (state == NULL)
553 return NULL;
554
555 state->cfg = cfg;
556 state->i2c = i2c;
557 state->fe = fe;
558 fe->tuner_priv = state;
559
560 if (dib0070_reset(state) != 0)
561 goto free_mem;
562
563 dib0070_wbd_calibration(state);
564
565 printk(KERN_INFO "DiB0070: successfully identified\n");
566 memcpy(&fe->ops.tuner_ops, &dib0070_ops, sizeof(struct dvb_tuner_ops));
567
568 fe->tuner_priv = state;
569 return fe;
570
571free_mem:
572 kfree(state);
573 fe->tuner_priv = NULL;
574 return NULL;
575}
576EXPORT_SYMBOL(dib0070_attach);
577
578MODULE_AUTHOR("Patrick Boettcher <pboettcher@dibcom.fr>");
579MODULE_DESCRIPTION("Driver for the DiBcom 0070 base-band RF Tuner");
580MODULE_LICENSE("GPL");
diff --git a/drivers/media/dvb/frontends/dib0070.h b/drivers/media/dvb/frontends/dib0070.h
new file mode 100644
index 000000000000..786e37d33889
--- /dev/null
+++ b/drivers/media/dvb/frontends/dib0070.h
@@ -0,0 +1,44 @@
1/*
2 * Linux-DVB Driver for DiBcom's DiB0070 base-band RF Tuner.
3 *
4 * Copyright (C) 2005-7 DiBcom (http://www.dibcom.fr/)
5 *
6 * This program is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU General Public License as
8 * published by the Free Software Foundation, version 2.
9 */
10#ifndef DIB0070_H
11#define DIB0070_H
12
13struct dvb_frontend;
14struct i2c_adapter;
15
16#define DEFAULT_DIB0070_I2C_ADDRESS 0x60
17
18struct dib0070_config {
19 u8 i2c_address;
20
21 /* tuner pins controlled externally */
22 int (*reset) (struct dvb_frontend *, int);
23 int (*sleep) (struct dvb_frontend *, int);
24
25 /* offset in kHz */
26 int freq_offset_khz_uhf;
27 int freq_offset_khz_vhf;
28
29 u8 osc_buffer_state; /* 0= normal, 1= tri-state */
30 u32 clock_khz;
31 u8 clock_pad_drive; /* (Drive + 1) * 2mA */
32
33 u8 invert_iq; /* invert Q - in case I or Q is inverted on the board */
34
35 u8 force_crystal_mode; /* if == 0 -> decision is made in the driver default: <24 -> 2, >=24 -> 1 */
36
37 u8 flip_chip;
38};
39
40extern struct dvb_frontend * dib0070_attach(struct dvb_frontend *fe, struct i2c_adapter *i2c, struct dib0070_config *cfg);
41extern void dib0070_ctrl_agc_filter(struct dvb_frontend *, uint8_t open);
42extern u16 dib0070_wbd_offset(struct dvb_frontend *);
43
44#endif
diff --git a/drivers/media/dvb/frontends/dib3000mc.c b/drivers/media/dvb/frontends/dib3000mc.c
index cbbe2c2f05dc..38d2322cbaf6 100644
--- a/drivers/media/dvb/frontends/dib3000mc.c
+++ b/drivers/media/dvb/frontends/dib3000mc.c
@@ -593,7 +593,7 @@ static int dib3000mc_tune(struct dvb_frontend *demod, struct dvb_frontend_parame
593 // activates isi 593 // activates isi
594 dib3000mc_write_word(state, 29, 0x1073); 594 dib3000mc_write_word(state, 29, 0x1073);
595 595
596 dib3000mc_set_adp_cfg(state, (uint8_t)ch->u.ofdm.constellation); 596 dib3000mc_set_adp_cfg(state, (u8)ch->u.ofdm.constellation);
597 if (ch->u.ofdm.transmission_mode == TRANSMISSION_MODE_8K) { 597 if (ch->u.ofdm.transmission_mode == TRANSMISSION_MODE_8K) {
598 dib3000mc_write_word(state, 26, 38528); 598 dib3000mc_write_word(state, 26, 38528);
599 dib3000mc_write_word(state, 33, 8); 599 dib3000mc_write_word(state, 33, 8);
diff --git a/drivers/media/dvb/frontends/dib7000m.c b/drivers/media/dvb/frontends/dib7000m.c
index 608156a691de..0ad9f3eb20a6 100644
--- a/drivers/media/dvb/frontends/dib7000m.c
+++ b/drivers/media/dvb/frontends/dib7000m.c
@@ -42,9 +42,9 @@ struct dib7000m_state {
42 u32 timf_default; 42 u32 timf_default;
43 u32 internal_clk; 43 u32 internal_clk;
44 44
45 uint8_t div_force_off : 1; 45 u8 div_force_off : 1;
46 uint8_t div_state : 1; 46 u8 div_state : 1;
47 uint16_t div_sync_wait; 47 u16 div_sync_wait;
48 48
49 u16 revision; 49 u16 revision;
50 50
@@ -302,7 +302,7 @@ static int dib7000m_set_diversity_in(struct dvb_frontend *demod, int onoff)
302 dprintk( "diversity combination deactivated - forced by COFDM parameters"); 302 dprintk( "diversity combination deactivated - forced by COFDM parameters");
303 onoff = 0; 303 onoff = 0;
304 } 304 }
305 state->div_state = (uint8_t)onoff; 305 state->div_state = (u8)onoff;
306 306
307 if (onoff) { 307 if (onoff) {
308 dib7000m_write_word(state, 263 + state->reg_offs, 6); 308 dib7000m_write_word(state, 263 + state->reg_offs, 6);
@@ -620,7 +620,7 @@ static int dib7000m_update_lna(struct dib7000m_state *state)
620 u16 dyn_gain; 620 u16 dyn_gain;
621 621
622 if (state->cfg.update_lna) { 622 if (state->cfg.update_lna) {
623 // read dyn_gain here (because it is demod-dependent and not tuner) 623 // read dyn_gain here (because it is demod-dependent and not fe)
624 dyn_gain = dib7000m_read_word(state, 390); 624 dyn_gain = dib7000m_read_word(state, 390);
625 625
626 if (state->cfg.update_lna(&state->demod,dyn_gain)) { // LNA has changed 626 if (state->cfg.update_lna(&state->demod,dyn_gain)) { // LNA has changed
@@ -754,7 +754,7 @@ static int dib7000m_agc_startup(struct dvb_frontend *demod, struct dvb_frontend_
754 break; 754 break;
755 755
756 case 3: /* split search ended */ 756 case 3: /* split search ended */
757 agc_split = (uint8_t)dib7000m_read_word(state, 392); /* store the split value for the next time */ 757 agc_split = (u8)dib7000m_read_word(state, 392); /* store the split value for the next time */
758 dib7000m_write_word(state, 75, dib7000m_read_word(state, 390)); /* set AGC gain start value */ 758 dib7000m_write_word(state, 75, dib7000m_read_word(state, 390)); /* set AGC gain start value */
759 759
760 dib7000m_write_word(state, 72, cfg_72 & ~(1 << 4)); /* std AGC loop */ 760 dib7000m_write_word(state, 72, cfg_72 & ~(1 << 4)); /* std AGC loop */
diff --git a/drivers/media/dvb/frontends/dib7000p.c b/drivers/media/dvb/frontends/dib7000p.c
index 156c53ab56db..1175ab9a4532 100644
--- a/drivers/media/dvb/frontends/dib7000p.c
+++ b/drivers/media/dvb/frontends/dib7000p.c
@@ -36,9 +36,9 @@ struct dib7000p_state {
36 struct dibx000_agc_config *current_agc; 36 struct dibx000_agc_config *current_agc;
37 u32 timf; 37 u32 timf;
38 38
39 uint8_t div_force_off : 1; 39 u8 div_force_off : 1;
40 uint8_t div_state : 1; 40 u8 div_state : 1;
41 uint16_t div_sync_wait; 41 u16 div_sync_wait;
42 42
43 u8 agc_state; 43 u8 agc_state;
44 44
@@ -156,7 +156,7 @@ static int dib7000p_set_diversity_in(struct dvb_frontend *demod, int onoff)
156 dprintk( "diversity combination deactivated - forced by COFDM parameters"); 156 dprintk( "diversity combination deactivated - forced by COFDM parameters");
157 onoff = 0; 157 onoff = 0;
158 } 158 }
159 state->div_state = (uint8_t)onoff; 159 state->div_state = (u8)onoff;
160 160
161 if (onoff) { 161 if (onoff) {
162 dib7000p_write_word(state, 204, 6); 162 dib7000p_write_word(state, 204, 6);
@@ -294,6 +294,16 @@ static int dib7000p_sad_calib(struct dib7000p_state *state)
294 return 0; 294 return 0;
295} 295}
296 296
297int dib7000p_set_wbd_ref(struct dvb_frontend *demod, u16 value)
298{
299 struct dib7000p_state *state = demod->demodulator_priv;
300 if (value > 4095)
301 value = 4095;
302 state->wbd_ref = value;
303 return dib7000p_write_word(state, 105, (dib7000p_read_word(state, 105) & 0xf000) | value);
304}
305
306EXPORT_SYMBOL(dib7000p_set_wbd_ref);
297static void dib7000p_reset_pll(struct dib7000p_state *state) 307static void dib7000p_reset_pll(struct dib7000p_state *state)
298{ 308{
299 struct dibx000_bandwidth_config *bw = &state->cfg.bw[0]; 309 struct dibx000_bandwidth_config *bw = &state->cfg.bw[0];
@@ -335,6 +345,28 @@ static int dib7000p_reset_gpio(struct dib7000p_state *st)
335 return 0; 345 return 0;
336} 346}
337 347
348static int dib7000p_cfg_gpio(struct dib7000p_state *st, u8 num, u8 dir, u8 val)
349{
350 st->gpio_dir = dib7000p_read_word(st, 1029);
351 st->gpio_dir &= ~(1 << num); /* reset the direction bit */
352 st->gpio_dir |= (dir & 0x1) << num; /* set the new direction */
353 dib7000p_write_word(st, 1029, st->gpio_dir);
354
355 st->gpio_val = dib7000p_read_word(st, 1030);
356 st->gpio_val &= ~(1 << num); /* reset the direction bit */
357 st->gpio_val |= (val & 0x01) << num; /* set the new value */
358 dib7000p_write_word(st, 1030, st->gpio_val);
359
360 return 0;
361}
362
363int dib7000p_set_gpio(struct dvb_frontend *demod, u8 num, u8 dir, u8 val)
364{
365 struct dib7000p_state *state = demod->demodulator_priv;
366 return dib7000p_cfg_gpio(state, num, dir, val);
367}
368
369EXPORT_SYMBOL(dib7000p_set_gpio);
338static u16 dib7000p_defaults[] = 370static u16 dib7000p_defaults[] =
339 371
340{ 372{
@@ -501,7 +533,7 @@ static int dib7000p_update_lna(struct dib7000p_state *state)
501 533
502 // when there is no LNA to program return immediatly 534 // when there is no LNA to program return immediatly
503 if (state->cfg.update_lna) { 535 if (state->cfg.update_lna) {
504 // read dyn_gain here (because it is demod-dependent and not tuner) 536 // read dyn_gain here (because it is demod-dependent and not fe)
505 dyn_gain = dib7000p_read_word(state, 394); 537 dyn_gain = dib7000p_read_word(state, 394);
506 if (state->cfg.update_lna(&state->demod,dyn_gain)) { // LNA has changed 538 if (state->cfg.update_lna(&state->demod,dyn_gain)) { // LNA has changed
507 dib7000p_restart_agc(state); 539 dib7000p_restart_agc(state);
@@ -617,7 +649,7 @@ static int dib7000p_agc_startup(struct dvb_frontend *demod, struct dvb_frontend_
617 break; 649 break;
618 650
619 case 3: /* split search ended */ 651 case 3: /* split search ended */
620 agc_split = (uint8_t)dib7000p_read_word(state, 396); /* store the split value for the next time */ 652 agc_split = (u8)dib7000p_read_word(state, 396); /* store the split value for the next time */
621 dib7000p_write_word(state, 78, dib7000p_read_word(state, 394)); /* set AGC gain start value */ 653 dib7000p_write_word(state, 78, dib7000p_read_word(state, 394)); /* set AGC gain start value */
622 654
623 dib7000p_write_word(state, 75, state->current_agc->setup); /* std AGC loop */ 655 dib7000p_write_word(state, 75, state->current_agc->setup); /* std AGC loop */
diff --git a/drivers/media/dvb/frontends/dib7000p.h b/drivers/media/dvb/frontends/dib7000p.h
index e7769e7cd92a..eefcac8b5244 100644
--- a/drivers/media/dvb/frontends/dib7000p.h
+++ b/drivers/media/dvb/frontends/dib7000p.h
@@ -40,12 +40,7 @@ extern int dib7000p_i2c_enumeration(struct i2c_adapter *i2c, int no_of_demods, u
40 40
41extern struct i2c_adapter * dib7000p_get_i2c_master(struct dvb_frontend *, enum dibx000_i2c_interface, int); 41extern struct i2c_adapter * dib7000p_get_i2c_master(struct dvb_frontend *, enum dibx000_i2c_interface, int);
42extern int dib7000pc_detection(struct i2c_adapter *i2c_adap); 42extern int dib7000pc_detection(struct i2c_adapter *i2c_adap);
43 43extern int dib7000p_set_gpio(struct dvb_frontend *, u8 num, u8 dir, u8 val);
44/* TODO 44extern int dib7000p_set_wbd_ref(struct dvb_frontend *, u16 value);
45extern INT dib7000p_set_gpio(struct dibDemod *demod, UCHAR num, UCHAR dir, UCHAR val);
46extern INT dib7000p_enable_vbg_voltage(struct dibDemod *demod);
47extern void dib7000p_set_hostbus_diversity(struct dibDemod *demod, UCHAR onoff);
48extern USHORT dib7000p_get_current_agc_global(struct dibDemod *demod);
49*/
50 45
51#endif 46#endif