This commit was manufactured by cvs2svn to create branch 'vserver'.
[linux-2.6.git] / drivers / media / dvb / dvb-usb / dib0700_devices.c
diff --git a/drivers/media/dvb/dvb-usb/dib0700_devices.c b/drivers/media/dvb/dvb-usb/dib0700_devices.c
new file mode 100644 (file)
index 0000000..2208757
--- /dev/null
@@ -0,0 +1,378 @@
+/* Linux driver for devices based on the DiBcom DiB0700 USB bridge
+ *
+ *     This program is free software; you can redistribute it and/or modify it
+ *     under the terms of the GNU General Public License as published by the Free
+ *     Software Foundation, version 2.
+ *
+ *  Copyright (C) 2005-6 DiBcom, SA
+ */
+#include "dib0700.h"
+
+#include "dib3000mc.h"
+#include "dib7000m.h"
+#include "dib7000p.h"
+#include "mt2060.h"
+
+static int force_lna_activation;
+module_param(force_lna_activation, int, 0644);
+MODULE_PARM_DESC(force_lna_activation, "force the activation of Low-Noise-Amplifyer(s) (LNA), "
+               "if applicable for the device (default: 0=automatic/off).");
+
+/* Hauppauge Nova-T 500
+ *  has a LNA on GPIO0 which is enabled by setting 1 */
+static struct mt2060_config bristol_mt2060_config[2] = {
+       {
+               .i2c_address = 0x60,
+               .clock_out   = 3,
+       }, {
+               .i2c_address = 0x61,
+       }
+};
+
+static struct dibx000_agc_config bristol_dib3000p_mt2060_agc_config = {
+       .band_caps = BAND_VHF | BAND_UHF,
+       .setup     = (1 << 8) | (5 << 5) | (0 << 4) | (0 << 3) | (0 << 2) | (2 << 0),
+
+       .agc1_max = 42598,
+       .agc1_min = 17694,
+       .agc2_max = 45875,
+       .agc2_min = 0,
+
+       .agc1_pt1 = 0,
+       .agc1_pt2 = 59,
+
+       .agc1_slope1 = 0,
+       .agc1_slope2 = 69,
+
+       .agc2_pt1 = 0,
+       .agc2_pt2 = 59,
+
+       .agc2_slope1 = 111,
+       .agc2_slope2 = 28,
+};
+
+static struct dib3000mc_config bristol_dib3000mc_config[2] = {
+       {       .agc          = &bristol_dib3000p_mt2060_agc_config,
+               .max_time     = 0x196,
+               .ln_adc_level = 0x1cc7,
+               .output_mpeg2_in_188_bytes = 1,
+       },
+       {       .agc          = &bristol_dib3000p_mt2060_agc_config,
+               .max_time     = 0x196,
+               .ln_adc_level = 0x1cc7,
+               .output_mpeg2_in_188_bytes = 1,
+       }
+};
+
+static int bristol_frontend_attach(struct dvb_usb_adapter *adap)
+{
+       struct dib0700_state *st = adap->dev->priv;
+       if (adap->id == 0) {
+               dib0700_set_gpio(adap->dev, GPIO6,  GPIO_OUT, 0); msleep(10);
+               dib0700_set_gpio(adap->dev, GPIO6,  GPIO_OUT, 1); msleep(10);
+               dib0700_set_gpio(adap->dev, GPIO10, GPIO_OUT, 0); msleep(10);
+               dib0700_set_gpio(adap->dev, GPIO10, GPIO_OUT, 1); msleep(10);
+
+               if (force_lna_activation)
+                       dib0700_set_gpio(adap->dev, GPIO0, GPIO_OUT, 1);
+               else
+                       dib0700_set_gpio(adap->dev, GPIO0, GPIO_OUT, 0);
+
+               if (dib3000mc_i2c_enumeration(&adap->dev->i2c_adap, 2, DEFAULT_DIB3000P_I2C_ADDRESS, bristol_dib3000mc_config) != 0) {
+                       dib0700_set_gpio(adap->dev, GPIO6, GPIO_OUT, 0); msleep(10);
+                       return -ENODEV;
+               }
+       }
+       st->mt2060_if1[adap->id] = 1220;
+       return (adap->fe = dvb_attach(dib3000mc_attach, &adap->dev->i2c_adap,
+               (10 + adap->id) << 1, &bristol_dib3000mc_config[adap->id])) == NULL ? -ENODEV : 0;
+}
+
+static int bristol_tuner_attach(struct dvb_usb_adapter *adap)
+{
+       struct dib0700_state *st = adap->dev->priv;
+       struct i2c_adapter *tun_i2c = dib3000mc_get_tuner_i2c_master(adap->fe, 1);
+       return dvb_attach(mt2060_attach,adap->fe, tun_i2c, &bristol_mt2060_config[adap->id],
+               st->mt2060_if1[adap->id]) == NULL ? -ENODEV : 0;
+}
+
+/* STK7700P: Hauppauge Nova-T Stick, AVerMedia Volar */
+static struct dibx000_agc_config stk7700p_7000m_mt2060_agc_config = {
+       BAND_UHF | BAND_VHF,       // band_caps
+
+       /* 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,
+        * P_agc_inh_dc_rv_est=0, P_agc_time_est=3, P_agc_freeze=0, P_agc_nb_est=2, P_agc_write=0 */
+       (0 << 15) | (0 << 14) | (5 << 11) | (0 << 10) | (0 << 9) | (0 << 8) | (3 << 5) | (0 << 4) | (2 << 1) | (0 << 0), // setup
+
+       712,  // inv_gain
+       41,  // time_stabiliz
+
+       0,  // alpha_level
+       118,  // thlock
+
+       0,     // wbd_inv
+       4095,  // wbd_ref
+       0,     // wbd_sel
+       0,     // wbd_alpha
+
+       42598,  // agc1_max
+       17694,  // agc1_min
+       45875,  // agc2_max
+       2621,  // agc2_min
+       0,  // agc1_pt1
+       76,  // agc1_pt2
+       139,  // agc1_pt3
+       52,  // agc1_slope1
+       59,  // agc1_slope2
+       107,  // agc2_pt1
+       172,  // agc2_pt2
+       57,  // agc2_slope1
+       70,  // agc2_slope2
+
+       21,  // alpha_mant
+       25,  // alpha_exp
+       28,  // beta_mant
+       48,  // beta_exp
+
+       1,  // perform_agc_softsplit
+       {  0,     // split_min
+          107,   // split_max
+          51800, // global_split_min
+          24700  // global_split_max
+       },
+};
+
+static struct dibx000_agc_config stk7700p_7000p_mt2060_agc_config = {
+       BAND_UHF | BAND_VHF,
+
+       /* 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,
+        * P_agc_inh_dc_rv_est=0, P_agc_time_est=3, P_agc_freeze=0, P_agc_nb_est=2, P_agc_write=0 */
+       (0 << 15) | (0 << 14) | (5 << 11) | (0 << 10) | (0 << 9) | (0 << 8) | (3 << 5) | (0 << 4) | (2 << 1) | (0 << 0), // setup
+
+       712, // inv_gain
+       41,  // time_stabiliz
+
+       0,   // alpha_level
+       118, // thlock
+
+       0,    // wbd_inv
+       4095, // wbd_ref
+       0,    // wbd_sel
+       0,    // wbd_alpha
+
+       42598, // agc1_max
+       16384, // agc1_min
+       42598, // agc2_max
+           0, // agc2_min
+
+         0,   // agc1_pt1
+       137,   // agc1_pt2
+       255,   // agc1_pt3
+
+         0,   // agc1_slope1
+       255,   // agc1_slope2
+
+       0,     // agc2_pt1
+       0,     // agc2_pt2
+
+        0,    // agc2_slope1
+       41,    // agc2_slope2
+
+       15, // alpha_mant
+       25, // alpha_exp
+
+       28, // beta_mant
+       48, // beta_exp
+
+       0, // perform_agc_softsplit
+};
+
+static struct dibx000_bandwidth_config stk7700p_pll_config = {
+       60000, 30000, // internal, sampling
+       1, 8, 3, 1, 0, // pll_cfg: prediv, ratio, range, reset, bypass
+       0, 0, 1, 1, 0, // misc: refdiv, bypclk_div, IO_CLK_en_core, ADClkSrc, modulo
+       (3 << 14) | (1 << 12) | (524 << 0), // sad_cfg: refsel, sel, freq_15k
+       60258167, // ifreq
+       20452225, // timf
+};
+
+static struct dib7000m_config stk7700p_dib7000m_config = {
+       .dvbt_mode = 1,
+       .output_mpeg2_in_188_bytes = 1,
+       .quartz_direct = 1,
+
+       .agc_config_count = 1,
+       .agc = &stk7700p_7000m_mt2060_agc_config,
+       .bw  = &stk7700p_pll_config,
+
+       .gpio_dir = DIB7000M_GPIO_DEFAULT_DIRECTIONS,
+       .gpio_val = DIB7000M_GPIO_DEFAULT_VALUES,
+       .gpio_pwm_pos = DIB7000M_GPIO_DEFAULT_PWM_POS,
+};
+
+static struct dib7000p_config stk7700p_dib7000p_config = {
+       .output_mpeg2_in_188_bytes = 1,
+
+       .agc = &stk7700p_7000p_mt2060_agc_config,
+       .bw  = &stk7700p_pll_config,
+
+       .gpio_dir = DIB7000M_GPIO_DEFAULT_DIRECTIONS,
+       .gpio_val = DIB7000M_GPIO_DEFAULT_VALUES,
+       .gpio_pwm_pos = DIB7000M_GPIO_DEFAULT_PWM_POS,
+};
+
+static int stk7700p_frontend_attach(struct dvb_usb_adapter *adap)
+{
+       struct dib0700_state *st = adap->dev->priv;
+       /* unless there is no real power management in DVB - we leave the device on GPIO6 */
+
+       dib0700_set_gpio(adap->dev, GPIO10, GPIO_OUT, 0);
+       dib0700_set_gpio(adap->dev, GPIO6,  GPIO_OUT, 0); msleep(50);
+
+       dib0700_set_gpio(adap->dev, GPIO6,  GPIO_OUT, 1); msleep(10);
+       dib0700_set_gpio(adap->dev, GPIO9,  GPIO_OUT, 1);
+
+       dib0700_set_gpio(adap->dev, GPIO10, GPIO_OUT, 0); msleep(10);
+       dib0700_ctrl_clock(adap->dev, 72, 1);
+       dib0700_set_gpio(adap->dev, GPIO10, GPIO_OUT, 1); msleep(100);
+
+       dib0700_set_gpio(adap->dev,  GPIO0, GPIO_OUT, 1);
+
+       st->mt2060_if1[0] = 1220;
+
+       if (dib7000pc_detection(&adap->dev->i2c_adap)) {
+               adap->fe = dvb_attach(dib7000p_attach, &adap->dev->i2c_adap, 18, &stk7700p_dib7000p_config);
+               st->is_dib7000pc = 1;
+       } else
+               adap->fe = dvb_attach(dib7000m_attach, &adap->dev->i2c_adap, 18, &stk7700p_dib7000m_config);
+
+       return adap->fe == NULL ? -ENODEV : 0;
+}
+
+static struct mt2060_config stk7700p_mt2060_config = {
+       0x60
+};
+
+static int stk7700p_tuner_attach(struct dvb_usb_adapter *adap)
+{
+       struct dib0700_state *st = adap->dev->priv;
+       struct i2c_adapter *tun_i2c;
+
+       if (st->is_dib7000pc)
+               tun_i2c = dib7000p_get_i2c_master(adap->fe, DIBX000_I2C_INTERFACE_TUNER, 1);
+       else
+               tun_i2c = dib7000m_get_i2c_master(adap->fe, DIBX000_I2C_INTERFACE_TUNER, 1);
+
+       return dvb_attach(mt2060_attach, adap->fe, tun_i2c, &stk7700p_mt2060_config,
+               st->mt2060_if1[0]) == NULL ? -ENODEV : 0;
+}
+
+struct usb_device_id dib0700_usb_id_table[] = {
+               { USB_DEVICE(USB_VID_DIBCOM,    USB_PID_DIBCOM_STK7700P) },
+               { USB_DEVICE(USB_VID_DIBCOM,    USB_PID_DIBCOM_STK7700P_PC) },
+
+               { USB_DEVICE(USB_VID_HAUPPAUGE, USB_PID_HAUPPAUGE_NOVA_T_500) },
+               { USB_DEVICE(USB_VID_HAUPPAUGE, USB_PID_HAUPPAUGE_NOVA_T_500_2) },
+               { USB_DEVICE(USB_VID_HAUPPAUGE, USB_PID_HAUPPAUGE_NOVA_T_STICK) },
+               { USB_DEVICE(USB_VID_AVERMEDIA, USB_PID_AVERMEDIA_VOLAR) },
+               { USB_DEVICE(USB_VID_COMPRO,    USB_PID_COMPRO_VIDEOMATE_U500) },
+               { USB_DEVICE(USB_VID_UNIWILL,   USB_PID_UNIWILL_STK7700P) },
+               { USB_DEVICE(USB_VID_LEADTEK,   USB_PID_WINFAST_DTV_DONGLE_STK7700P) },
+               { USB_DEVICE(USB_VID_HAUPPAUGE, USB_PID_HAUPPAUGE_NOVA_T_STICK_2) },
+               { USB_DEVICE(USB_VID_AVERMEDIA, USB_PID_AVERMEDIA_VOLAR_2) },
+               { }             /* Terminating entry */
+};
+MODULE_DEVICE_TABLE(usb, dib0700_usb_id_table);
+
+#define DIB0700_DEFAULT_DEVICE_PROPERTIES \
+       .caps              = DVB_USB_IS_AN_I2C_ADAPTER, \
+       .usb_ctrl          = DEVICE_SPECIFIC, \
+       .firmware          = "dvb-usb-dib0700-01.fw", \
+       .download_firmware = dib0700_download_firmware, \
+       .no_reconnect      = 1, \
+       .size_of_priv      = sizeof(struct dib0700_state), \
+       .i2c_algo          = &dib0700_i2c_algo, \
+       .identify_state    = dib0700_identify_state
+
+#define DIB0700_DEFAULT_STREAMING_CONFIG(ep) \
+       .streaming_ctrl   = dib0700_streaming_ctrl, \
+       .stream = { \
+               .type = USB_BULK, \
+               .count = 4, \
+               .endpoint = ep, \
+               .u = { \
+                       .bulk = { \
+                               .buffersize = 39480, \
+                       } \
+               } \
+       }
+
+struct dvb_usb_device_properties dib0700_devices[] = {
+       {
+               DIB0700_DEFAULT_DEVICE_PROPERTIES,
+
+               .num_adapters = 1,
+               .adapter = {
+                       {
+                               .frontend_attach  = stk7700p_frontend_attach,
+                               .tuner_attach     = stk7700p_tuner_attach,
+
+                               DIB0700_DEFAULT_STREAMING_CONFIG(0x02),
+                       },
+               },
+
+               .num_device_descs = 6,
+               .devices = {
+                       {   "DiBcom STK7700P reference design",
+                               { &dib0700_usb_id_table[0], &dib0700_usb_id_table[1] },
+                               { NULL },
+                       },
+                       {   "Hauppauge Nova-T Stick",
+                               { &dib0700_usb_id_table[4], &dib0700_usb_id_table[9], NULL },
+                               { NULL },
+                       },
+                       {   "AVerMedia AVerTV DVB-T Volar",
+                               { &dib0700_usb_id_table[5], &dib0700_usb_id_table[10] },
+                               { NULL },
+                       },
+                       {   "Compro Videomate U500",
+                               { &dib0700_usb_id_table[6], NULL },
+                               { NULL },
+                       },
+                       {   "Uniwill STK7700P based (Hama and others)",
+                               { &dib0700_usb_id_table[7], NULL },
+                               { NULL },
+                       },
+                       {   "Leadtek Winfast DTV Dongle (STK7700P based)",
+                               { &dib0700_usb_id_table[8], NULL },
+                               { NULL },
+                       }
+               }
+       }, { DIB0700_DEFAULT_DEVICE_PROPERTIES,
+
+               .num_adapters = 2,
+               .adapter = {
+                       {
+                               .frontend_attach  = bristol_frontend_attach,
+                               .tuner_attach     = bristol_tuner_attach,
+
+                               DIB0700_DEFAULT_STREAMING_CONFIG(0x02),
+                       }, {
+                               .frontend_attach  = bristol_frontend_attach,
+                               .tuner_attach     = bristol_tuner_attach,
+
+                               DIB0700_DEFAULT_STREAMING_CONFIG(0x03),
+                       }
+               },
+
+               .num_device_descs = 1,
+               .devices = {
+                       {   "Hauppauge Nova-T 500 Dual DVB-T",
+                               { &dib0700_usb_id_table[2], &dib0700_usb_id_table[3], NULL },
+                               { NULL },
+                       },
+               }
+       }
+};
+
+int dib0700_device_count = ARRAY_SIZE(dib0700_devices);