Re: [PATCH 1/9] em28xx: Hauppauge DualHD second tuner functionality

2018-01-04 Thread Michael Ira Krufky
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

2018-01-04 Thread Brad Love
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;
 
+