Merge branch 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/roland...
[pandora-kernel.git] / drivers / media / dvb / dvb-usb / m920x.c
index c546dde..a12e6f7 100644 (file)
@@ -22,6 +22,10 @@ static int dvb_usb_m920x_debug;
 module_param_named(debug,dvb_usb_m920x_debug, int, 0644);
 MODULE_PARM_DESC(debug, "set debugging level (1=rc (or-able))." DVB_USB_DEBUG_STATUS);
 
+DVB_DEFINE_MOD_OPT_ADAPTER_NR(adapter_nr);
+
+static int m920x_set_filter(struct dvb_usb_device *d, int type, int idx, int pid);
+
 static inline int m920x_read(struct usb_device *udev, u8 request, u16 value,
                             u16 index, void *data, int size)
 {
@@ -57,7 +61,8 @@ static inline int m920x_write(struct usb_device *udev, u8 request,
 
 static int m920x_init(struct dvb_usb_device *d, struct m920x_inits *rc_seq)
 {
-       int ret = 0;
+       int ret = 0, i, epi, flags = 0;
+       int adap_enabled[M9206_MAX_ADAPTERS] = { 0 };
 
        /* Remote controller init. */
        if (d->props.rc_query) {
@@ -76,9 +81,51 @@ static int m920x_init(struct dvb_usb_device *d, struct m920x_inits *rc_seq)
                deb("Initialising remote control success\n");
        }
 
+       for (i = 0; i < d->props.num_adapters; i++)
+               flags |= d->adapter[i].props.caps;
+
+       /* Some devices(Dposh) might crash if we attempt touch at all. */
+       if (flags & DVB_USB_ADAP_HAS_PID_FILTER) {
+               for (i = 0; i < d->props.num_adapters; i++) {
+                       epi = d->adapter[i].props.stream.endpoint - 0x81;
+
+                       if (epi < 0 || epi >= M9206_MAX_ADAPTERS) {
+                               printk(KERN_INFO "m920x: Unexpected adapter endpoint!\n");
+                               return -EINVAL;
+                       }
+
+                       adap_enabled[epi] = 1;
+               }
+
+               for (i = 0; i < M9206_MAX_ADAPTERS; i++) {
+                       if (adap_enabled[i])
+                               continue;
+
+                       if ((ret = m920x_set_filter(d, 0x81 + i, 0, 0x0)) != 0)
+                               return ret;
+
+                       if ((ret = m920x_set_filter(d, 0x81 + i, 0, 0x02f5)) != 0)
+                               return ret;
+               }
+       }
+
        return ret;
 }
 
+static int m920x_init_ep(struct usb_interface *intf)
+{
+       struct usb_device *udev = interface_to_usbdev(intf);
+       struct usb_host_interface *alt;
+
+       if ((alt = usb_altnum_to_altsetting(intf, 1)) == NULL) {
+               deb("No alt found!\n");
+               return -ENODEV;
+       }
+
+       return usb_set_interface(udev, alt->desc.bInterfaceNumber,
+                                alt->desc.bAlternateSetting);
+}
+
 static int m920x_rc_query(struct dvb_usb_device *d, u32 *event, int *state)
 {
        struct m920x_state *m = d->priv;
@@ -211,8 +258,7 @@ static struct i2c_algorithm m920x_i2c_algo = {
 };
 
 /* pid filter */
-static int m920x_set_filter(struct dvb_usb_adapter *adap,
-                           int type, int idx, int pid)
+static int m920x_set_filter(struct dvb_usb_device *d, int type, int idx, int pid)
 {
        int ret = 0;
 
@@ -221,10 +267,10 @@ static int m920x_set_filter(struct dvb_usb_adapter *adap,
 
        pid |= 0x8000;
 
-       if ((ret = m920x_write(adap->dev->udev, M9206_FILTER, pid, (type << 8) | (idx * 4) )) != 0)
+       if ((ret = m920x_write(d->udev, M9206_FILTER, pid, (type << 8) | (idx * 4) )) != 0)
                return ret;
 
-       if ((ret = m920x_write(adap->dev->udev, M9206_FILTER, 0, (type << 8) | (idx * 4) )) != 0)
+       if ((ret = m920x_write(d->udev, M9206_FILTER, 0, (type << 8) | (idx * 4) )) != 0)
                return ret;
 
        return ret;
@@ -233,40 +279,35 @@ static int m920x_set_filter(struct dvb_usb_adapter *adap,
 static int m920x_update_filters(struct dvb_usb_adapter *adap)
 {
        struct m920x_state *m = adap->dev->priv;
-       int enabled = m->filtering_enabled;
+       int enabled = m->filtering_enabled[adap->id];
        int i, ret = 0, filter = 0;
+       int ep = adap->props.stream.endpoint;
 
        for (i = 0; i < M9206_MAX_FILTERS; i++)
-               if (m->filters[i] == 8192)
+               if (m->filters[adap->id][i] == 8192)
                        enabled = 0;
 
        /* Disable all filters */
-       if ((ret = m920x_set_filter(adap, 0x81, 1, enabled)) != 0)
+       if ((ret = m920x_set_filter(adap->dev, ep, 1, enabled)) != 0)
                return ret;
 
        for (i = 0; i < M9206_MAX_FILTERS; i++)
-               if ((ret = m920x_set_filter(adap, 0x81, i + 2, 0)) != 0)
+               if ((ret = m920x_set_filter(adap->dev, ep, i + 2, 0)) != 0)
                        return ret;
 
-       if ((ret = m920x_set_filter(adap, 0x82, 0, 0x0)) != 0)
-               return ret;
-
        /* Set */
        if (enabled) {
                for (i = 0; i < M9206_MAX_FILTERS; i++) {
-                       if (m->filters[i] == 0)
+                       if (m->filters[adap->id][i] == 0)
                                continue;
 
-                       if ((ret = m920x_set_filter(adap, 0x81, filter + 2, m->filters[i])) != 0)
+                       if ((ret = m920x_set_filter(adap->dev, ep, filter + 2, m->filters[adap->id][i])) != 0)
                                return ret;
 
                        filter++;
                }
        }
 
-       if ((ret = m920x_set_filter(adap, 0x82, 0, 0x02f5)) != 0)
-               return ret;
-
        return ret;
 }
 
@@ -274,7 +315,7 @@ static int m920x_pid_filter_ctrl(struct dvb_usb_adapter *adap, int onoff)
 {
        struct m920x_state *m = adap->dev->priv;
 
-       m->filtering_enabled = onoff ? 1 : 0;
+       m->filtering_enabled[adap->id] = onoff ? 1 : 0;
 
        return m920x_update_filters(adap);
 }
@@ -283,7 +324,7 @@ static int m920x_pid_filter(struct dvb_usb_adapter *adap, int index, u16 pid, in
 {
        struct m920x_state *m = adap->dev->priv;
 
-       m->filters[index] = onoff ? pid : 0;
+       m->filters[adap->id][index] = onoff ? pid : 0;
 
        return m920x_update_filters(adap);
 }
@@ -368,6 +409,7 @@ static int m920x_identify_state(struct usb_device *udev,
 /* demod configurations */
 static int m920x_mt352_demod_init(struct dvb_frontend *fe)
 {
+       int ret;
        u8 config[] = { CONFIG, 0x3d };
        u8 clock[] = { CLOCK_CTL, 0x30 };
        u8 reset[] = { RESET, 0x80 };
@@ -377,17 +419,25 @@ static int m920x_mt352_demod_init(struct dvb_frontend *fe)
        u8 unk1[] = { 0x93, 0x1a };
        u8 unk2[] = { 0xb5, 0x7a };
 
-       mt352_write(fe, config, ARRAY_SIZE(config));
-       mt352_write(fe, clock, ARRAY_SIZE(clock));
-       mt352_write(fe, reset, ARRAY_SIZE(reset));
-       mt352_write(fe, adc_ctl, ARRAY_SIZE(adc_ctl));
-       mt352_write(fe, agc, ARRAY_SIZE(agc));
-       mt352_write(fe, sec_agc, ARRAY_SIZE(sec_agc));
-       mt352_write(fe, unk1, ARRAY_SIZE(unk1));
-       mt352_write(fe, unk2, ARRAY_SIZE(unk2));
-
        deb("Demod init!\n");
 
+       if ((ret = mt352_write(fe, config, ARRAY_SIZE(config))) != 0)
+               return ret;
+       if ((ret = mt352_write(fe, clock, ARRAY_SIZE(clock))) != 0)
+               return ret;
+       if ((ret = mt352_write(fe, reset, ARRAY_SIZE(reset))) != 0)
+               return ret;
+       if ((ret = mt352_write(fe, adc_ctl, ARRAY_SIZE(adc_ctl))) != 0)
+               return ret;
+       if ((ret = mt352_write(fe, agc, ARRAY_SIZE(agc))) != 0)
+               return ret;
+       if ((ret = mt352_write(fe, sec_agc, ARRAY_SIZE(sec_agc))) != 0)
+               return ret;
+       if ((ret = mt352_write(fe, unk1, ARRAY_SIZE(unk1))) != 0)
+               return ret;
+       if ((ret = mt352_write(fe, unk2, ARRAY_SIZE(unk2))) != 0)
+               return ret;
+
        return 0;
 }
 
@@ -429,7 +479,7 @@ static struct qt1010_config m920x_qt1010_config = {
 /* Callbacks for DVB USB */
 static int m920x_mt352_frontend_attach(struct dvb_usb_adapter *adap)
 {
-       deb("%s\n",__FUNCTION__);
+       deb("%s\n",__func__);
 
        if ((adap->fe = dvb_attach(mt352_attach,
                                   &m920x_mt352_config,
@@ -441,7 +491,7 @@ static int m920x_mt352_frontend_attach(struct dvb_usb_adapter *adap)
 
 static int m920x_tda10046_08_frontend_attach(struct dvb_usb_adapter *adap)
 {
-       deb("%s\n",__FUNCTION__);
+       deb("%s\n",__func__);
 
        if ((adap->fe = dvb_attach(tda10046_attach,
                                   &m920x_tda10046_08_config,
@@ -453,7 +503,7 @@ static int m920x_tda10046_08_frontend_attach(struct dvb_usb_adapter *adap)
 
 static int m920x_tda10046_0b_frontend_attach(struct dvb_usb_adapter *adap)
 {
-       deb("%s\n",__FUNCTION__);
+       deb("%s\n",__func__);
 
        if ((adap->fe = dvb_attach(tda10046_attach,
                                   &m920x_tda10046_0b_config,
@@ -465,7 +515,7 @@ static int m920x_tda10046_0b_frontend_attach(struct dvb_usb_adapter *adap)
 
 static int m920x_qt1010_tuner_attach(struct dvb_usb_adapter *adap)
 {
-       deb("%s\n",__FUNCTION__);
+       deb("%s\n",__func__);
 
        if (dvb_attach(qt1010_attach, adap->fe, &adap->dev->i2c_adap, &m920x_qt1010_config) == NULL)
                return -ENODEV;
@@ -475,7 +525,7 @@ static int m920x_qt1010_tuner_attach(struct dvb_usb_adapter *adap)
 
 static int m920x_tda8275_60_tuner_attach(struct dvb_usb_adapter *adap)
 {
-       deb("%s\n",__FUNCTION__);
+       deb("%s\n",__func__);
 
        if (dvb_attach(tda827x_attach, adap->fe, 0x60, &adap->dev->i2c_adap, NULL) == NULL)
                return -ENODEV;
@@ -485,7 +535,7 @@ static int m920x_tda8275_60_tuner_attach(struct dvb_usb_adapter *adap)
 
 static int m920x_tda8275_61_tuner_attach(struct dvb_usb_adapter *adap)
 {
-       deb("%s\n",__FUNCTION__);
+       deb("%s\n",__func__);
 
        if (dvb_attach(tda827x_attach, adap->fe, 0x61, &adap->dev->i2c_adap, NULL) == NULL)
                return -ENODEV;
@@ -558,8 +608,7 @@ static struct dvb_usb_device_properties dposh_properties;
 static int m920x_probe(struct usb_interface *intf,
                       const struct usb_device_id *id)
 {
-       struct dvb_usb_device *d;
-       struct usb_host_interface *alt;
+       struct dvb_usb_device *d = NULL;
        int ret;
        struct m920x_inits *rc_init_seq = NULL;
        int bInterfaceNumber = intf->cur_altsetting->desc.bInterfaceNumber;
@@ -571,27 +620,31 @@ static int m920x_probe(struct usb_interface *intf,
                 * multi-tuner device
                 */
 
-               if ((ret = dvb_usb_device_init(intf, &megasky_properties,
-                                              THIS_MODULE, &d)) == 0) {
+               ret = dvb_usb_device_init(intf, &megasky_properties,
+                                         THIS_MODULE, &d, adapter_nr);
+               if (ret == 0) {
                        rc_init_seq = megasky_rc_init;
                        goto found;
                }
 
-               if ((ret = dvb_usb_device_init(intf, &digivox_mini_ii_properties,
-                                              THIS_MODULE, &d)) == 0) {
+               ret = dvb_usb_device_init(intf, &digivox_mini_ii_properties,
+                                         THIS_MODULE, &d, adapter_nr);
+               if (ret == 0) {
                        /* No remote control, so no rc_init_seq */
                        goto found;
                }
 
                /* This configures both tuners on the TV Walker Twin */
-               if ((ret = dvb_usb_device_init(intf, &tvwalkertwin_properties,
-                                              THIS_MODULE, &d)) == 0) {
+               ret = dvb_usb_device_init(intf, &tvwalkertwin_properties,
+                                         THIS_MODULE, &d, adapter_nr);
+               if (ret == 0) {
                        rc_init_seq = tvwalkertwin_rc_init;
                        goto found;
                }
 
-               if ((ret = dvb_usb_device_init(intf, &dposh_properties,
-                                              THIS_MODULE, &d)) == 0) {
+               ret = dvb_usb_device_init(intf, &dposh_properties,
+                                         THIS_MODULE, &d, adapter_nr);
+               if (ret == 0) {
                        /* Remote controller not supported yet. */
                        goto found;
                }
@@ -604,23 +657,13 @@ static int m920x_probe(struct usb_interface *intf,
                 * tvwalkertwin_properties already configured both
                 * tuners, so there is nothing for us to do here
                 */
-
-               return -ENODEV;
        }
 
  found:
-       alt = usb_altnum_to_altsetting(intf, 1);
-       if (alt == NULL) {
-               deb("No alt found!\n");
-               return -ENODEV;
-       }
-
-       ret = usb_set_interface(d->udev, alt->desc.bInterfaceNumber,
-                               alt->desc.bAlternateSetting);
-       if (ret < 0)
+       if ((ret = m920x_init_ep(intf)) < 0)
                return ret;
 
-       if ((ret = m920x_init(d, rc_init_seq)) != 0)
+       if (d && (ret = m920x_init(d, rc_init_seq)) != 0)
                return ret;
 
        return ret;
@@ -737,9 +780,9 @@ static struct dvb_usb_device_properties digivox_mini_ii_properties = {
  *
  * LifeView TV Walker Twin has 1 x M9206, 2 x TDA10046, 2 x TDA8275A
  * TDA10046 #0 is located at i2c address 0x08
- * TDA10046 #1 is located at i2c address 0x0b (presently disabled - not yet working)
+ * TDA10046 #1 is located at i2c address 0x0b
  * TDA8275A #0 is located at i2c address 0x60
- * TDA8275A #1 is located at i2c address 0x61 (presently disabled - not yet working)
+ * TDA8275A #1 is located at i2c address 0x61
  */
 static struct dvb_usb_device_properties tvwalkertwin_properties = {
        .caps = DVB_USB_IS_AN_I2C_ADAPTER,
@@ -756,7 +799,7 @@ static struct dvb_usb_device_properties tvwalkertwin_properties = {
        .size_of_priv     = sizeof(struct m920x_state),
 
        .identify_state   = m920x_identify_state,
-       .num_adapters = 1,
+       .num_adapters = 2,
        .adapter = {{
                .caps = DVB_USB_ADAP_HAS_PID_FILTER |
                        DVB_USB_ADAP_PID_FILTER_CAN_BE_TURNED_OFF,