Re: [PATCH 1/9] em28xx: Hauppauge DualHD second tuner functionality
On Thu, Jan 4, 2018 at 7:04 PM, Brad Love wrote: > Implement use of secondary TS port on em28xx. > Adds has_dual_ts field, allows secondary demod/tuner to be > added to a single em28xx device. > > Hauppauge DualHD models are configured to use this feature. > > Signed-off-by: Brad Love :+1 Reviewed-by: Michael Ira Krufky > --- > drivers/media/usb/em28xx/em28xx-cards.c | 126 > +++- > drivers/media/usb/em28xx/em28xx-core.c | 42 +-- > drivers/media/usb/em28xx/em28xx-dvb.c | 33 +++-- > drivers/media/usb/em28xx/em28xx.h | 12 +++ > 4 files changed, 196 insertions(+), 17 deletions(-) > > diff --git a/drivers/media/usb/em28xx/em28xx-cards.c > b/drivers/media/usb/em28xx/em28xx-cards.c > index 34e16f6a..7f5d0b28 100644 > --- a/drivers/media/usb/em28xx/em28xx-cards.c > +++ b/drivers/media/usb/em28xx/em28xx-cards.c > @@ -2402,6 +2402,7 @@ struct em28xx_board em28xx_boards[] = { > .tuner_type= TUNER_ABSENT, > .tuner_gpio= hauppauge_dualhd_dvb, > .has_dvb = 1, > + .has_dual_ts = 1, > .ir_codes = RC_MAP_HAUPPAUGE, > .leds = hauppauge_dualhd_leds, > }, > @@ -2417,6 +2418,7 @@ struct em28xx_board em28xx_boards[] = { > .tuner_type= TUNER_ABSENT, > .tuner_gpio= hauppauge_dualhd_dvb, > .has_dvb = 1, > + .has_dual_ts = 1, > .ir_codes = RC_MAP_HAUPPAUGE, > .leds = hauppauge_dualhd_leds, > }, > @@ -3239,7 +3241,8 @@ static void em28xx_release_resources(struct em28xx *dev) > em28xx_i2c_unregister(dev, 1); > em28xx_i2c_unregister(dev, 0); > > - usb_put_dev(udev); > + if (dev->ts == PRIMARY_TS) > + usb_put_dev(udev); > > /* Mark device as unused */ > clear_bit(dev->devno, em28xx_devused); > @@ -3432,6 +3435,35 @@ static int em28xx_init_dev(struct em28xx *dev, struct > usb_device *udev, > return 0; > } > > +int em28xx_duplicate_dev(struct em28xx *dev) > +{ > + int nr; > + struct em28xx *sec_dev = kzalloc(sizeof(*sec_dev), GFP_KERNEL); > + > + if (sec_dev == NULL) { > + dev->dev_next = NULL; > + return -ENOMEM; > + } > + memcpy(sec_dev, dev, sizeof(sizeof(*sec_dev))); > + /* Check to see next free device and mark as used */ > + do { > + nr = find_first_zero_bit(em28xx_devused, EM28XX_MAXBOARDS); > + if (nr >= EM28XX_MAXBOARDS) { > + /* No free device slots */ > + dev_warn(&dev->intf->dev, ": Supports only %i em28xx > boards.\n", > + EM28XX_MAXBOARDS); > + kfree(sec_dev); > + dev->dev_next = NULL; > + return -ENOMEM; > + } > + } while (test_and_set_bit(nr, em28xx_devused)); > + sec_dev->devno = nr; > + snprintf(sec_dev->name, 28, "em28xx #%d", nr); > + sec_dev->dev_next = NULL; > + dev->dev_next = sec_dev; > + return 0; > +} > + > /* high bandwidth multiplier, as encoded in highspeed endpoint descriptors */ > #define hb_mult(wMaxPacketSize) (1 + (((wMaxPacketSize) >> 11) & 0x03)) > > @@ -3551,6 +3583,17 @@ static int em28xx_usb_probe(struct usb_interface > *interface, > } > } > break; > + case 0x85: > + if (usb_endpoint_xfer_isoc(e)) { > + if (size > > dev->dvb_max_pkt_size_isoc_ts2) { > + dev->dvb_ep_isoc_ts2 > = e->bEndpointAddress; > + > dev->dvb_max_pkt_size_isoc_ts2 = size; > + dev->dvb_alt_isoc = i; > + } > + } else { > + dev->dvb_ep_bulk_ts2 = > e->bEndpointAddress; > + } > + break; > } > } > /* NOTE: > @@ -3565,6 +3608,8 @@ static int em28xx_usb_probe(struct usb_interface > *interface, > * 0x83isoc* => audio > * 0x84isoc=> digital > * 0x84bulk=> analog or digital** > +* 0x85isoc=> digital TS2 > +* 0x85bulk=> digital TS2 >
[PATCH 1/9] em28xx: Hauppauge DualHD second tuner functionality
Implement use of secondary TS port on em28xx. Adds has_dual_ts field, allows secondary demod/tuner to be added to a single em28xx device. Hauppauge DualHD models are configured to use this feature. Signed-off-by: Brad Love --- drivers/media/usb/em28xx/em28xx-cards.c | 126 +++- drivers/media/usb/em28xx/em28xx-core.c | 42 +-- drivers/media/usb/em28xx/em28xx-dvb.c | 33 +++-- drivers/media/usb/em28xx/em28xx.h | 12 +++ 4 files changed, 196 insertions(+), 17 deletions(-) diff --git a/drivers/media/usb/em28xx/em28xx-cards.c b/drivers/media/usb/em28xx/em28xx-cards.c index 34e16f6a..7f5d0b28 100644 --- a/drivers/media/usb/em28xx/em28xx-cards.c +++ b/drivers/media/usb/em28xx/em28xx-cards.c @@ -2402,6 +2402,7 @@ struct em28xx_board em28xx_boards[] = { .tuner_type= TUNER_ABSENT, .tuner_gpio= hauppauge_dualhd_dvb, .has_dvb = 1, + .has_dual_ts = 1, .ir_codes = RC_MAP_HAUPPAUGE, .leds = hauppauge_dualhd_leds, }, @@ -2417,6 +2418,7 @@ struct em28xx_board em28xx_boards[] = { .tuner_type= TUNER_ABSENT, .tuner_gpio= hauppauge_dualhd_dvb, .has_dvb = 1, + .has_dual_ts = 1, .ir_codes = RC_MAP_HAUPPAUGE, .leds = hauppauge_dualhd_leds, }, @@ -3239,7 +3241,8 @@ static void em28xx_release_resources(struct em28xx *dev) em28xx_i2c_unregister(dev, 1); em28xx_i2c_unregister(dev, 0); - usb_put_dev(udev); + if (dev->ts == PRIMARY_TS) + usb_put_dev(udev); /* Mark device as unused */ clear_bit(dev->devno, em28xx_devused); @@ -3432,6 +3435,35 @@ static int em28xx_init_dev(struct em28xx *dev, struct usb_device *udev, return 0; } +int em28xx_duplicate_dev(struct em28xx *dev) +{ + int nr; + struct em28xx *sec_dev = kzalloc(sizeof(*sec_dev), GFP_KERNEL); + + if (sec_dev == NULL) { + dev->dev_next = NULL; + return -ENOMEM; + } + memcpy(sec_dev, dev, sizeof(sizeof(*sec_dev))); + /* Check to see next free device and mark as used */ + do { + nr = find_first_zero_bit(em28xx_devused, EM28XX_MAXBOARDS); + if (nr >= EM28XX_MAXBOARDS) { + /* No free device slots */ + dev_warn(&dev->intf->dev, ": Supports only %i em28xx boards.\n", + EM28XX_MAXBOARDS); + kfree(sec_dev); + dev->dev_next = NULL; + return -ENOMEM; + } + } while (test_and_set_bit(nr, em28xx_devused)); + sec_dev->devno = nr; + snprintf(sec_dev->name, 28, "em28xx #%d", nr); + sec_dev->dev_next = NULL; + dev->dev_next = sec_dev; + return 0; +} + /* high bandwidth multiplier, as encoded in highspeed endpoint descriptors */ #define hb_mult(wMaxPacketSize) (1 + (((wMaxPacketSize) >> 11) & 0x03)) @@ -3551,6 +3583,17 @@ static int em28xx_usb_probe(struct usb_interface *interface, } } break; + case 0x85: + if (usb_endpoint_xfer_isoc(e)) { + if (size > dev->dvb_max_pkt_size_isoc_ts2) { + dev->dvb_ep_isoc_ts2 = e->bEndpointAddress; + dev->dvb_max_pkt_size_isoc_ts2 = size; + dev->dvb_alt_isoc = i; + } + } else { + dev->dvb_ep_bulk_ts2 = e->bEndpointAddress; + } + break; } } /* NOTE: @@ -3565,6 +3608,8 @@ static int em28xx_usb_probe(struct usb_interface *interface, * 0x83isoc* => audio * 0x84isoc=> digital * 0x84bulk=> analog or digital** +* 0x85isoc=> digital TS2 +* 0x85bulk=> digital TS2 * (*: audio should always be isoc) * (**: analog, if ep 0x82 is isoc, otherwise digital) * @@ -3632,6 +3677,10 @@ static int em28xx_usb_probe(struct usb_interface *interface, dev->has_video = has_video; dev->ifnum = ifnum; +