@@ -2402,6 +2402,7 @@ struct em28xx_board em28xx_boards[] = {
2402
2402
.tuner_type = TUNER_ABSENT ,
2403
2403
.tuner_gpio = hauppauge_dualhd_dvb ,
2404
2404
.has_dvb = 1 ,
2405
+ .has_dual_ts = 1 ,
2405
2406
.ir_codes = RC_MAP_HAUPPAUGE ,
2406
2407
.leds = hauppauge_dualhd_leds ,
2407
2408
},
@@ -2417,6 +2418,7 @@ struct em28xx_board em28xx_boards[] = {
2417
2418
.tuner_type = TUNER_ABSENT ,
2418
2419
.tuner_gpio = hauppauge_dualhd_dvb ,
2419
2420
.has_dvb = 1 ,
2421
+ .has_dual_ts = 1 ,
2420
2422
.ir_codes = RC_MAP_HAUPPAUGE ,
2421
2423
.leds = hauppauge_dualhd_leds ,
2422
2424
},
@@ -3239,7 +3241,8 @@ static void em28xx_release_resources(struct em28xx *dev)
3239
3241
em28xx_i2c_unregister (dev , 1 );
3240
3242
em28xx_i2c_unregister (dev , 0 );
3241
3243
3242
- usb_put_dev (udev );
3244
+ if (dev -> ts == PRIMARY_TS )
3245
+ usb_put_dev (udev );
3243
3246
3244
3247
/* Mark device as unused */
3245
3248
clear_bit (dev -> devno , em28xx_devused );
@@ -3432,6 +3435,35 @@ static int em28xx_init_dev(struct em28xx *dev, struct usb_device *udev,
3432
3435
return 0 ;
3433
3436
}
3434
3437
3438
+ int em28xx_duplicate_dev (struct em28xx * dev )
3439
+ {
3440
+ int nr ;
3441
+ struct em28xx * sec_dev = kzalloc (sizeof (* sec_dev ), GFP_KERNEL );
3442
+
3443
+ if (sec_dev == NULL ) {
3444
+ dev -> dev_next = NULL ;
3445
+ return - ENOMEM ;
3446
+ }
3447
+ memcpy (sec_dev , dev , sizeof (sizeof (* sec_dev )));
3448
+ /* Check to see next free device and mark as used */
3449
+ do {
3450
+ nr = find_first_zero_bit (em28xx_devused , EM28XX_MAXBOARDS );
3451
+ if (nr >= EM28XX_MAXBOARDS ) {
3452
+ /* No free device slots */
3453
+ dev_warn (& dev -> intf -> dev , ": Supports only %i em28xx boards.\n" ,
3454
+ EM28XX_MAXBOARDS );
3455
+ kfree (sec_dev );
3456
+ dev -> dev_next = NULL ;
3457
+ return - ENOMEM ;
3458
+ }
3459
+ } while (test_and_set_bit (nr , em28xx_devused ));
3460
+ sec_dev -> devno = nr ;
3461
+ snprintf (sec_dev -> name , 28 , "em28xx #%d" , nr );
3462
+ sec_dev -> dev_next = NULL ;
3463
+ dev -> dev_next = sec_dev ;
3464
+ return 0 ;
3465
+ }
3466
+
3435
3467
/* high bandwidth multiplier, as encoded in highspeed endpoint descriptors */
3436
3468
#define hb_mult (wMaxPacketSize ) (1 + (((wMaxPacketSize) >> 11) & 0x03))
3437
3469
@@ -3551,6 +3583,17 @@ static int em28xx_usb_probe(struct usb_interface *interface,
3551
3583
}
3552
3584
}
3553
3585
break ;
3586
+ case 0x85 :
3587
+ if (usb_endpoint_xfer_isoc (e )) {
3588
+ if (size > dev -> dvb_max_pkt_size_isoc_ts2 ) {
3589
+ dev -> dvb_ep_isoc_ts2 = e -> bEndpointAddress ;
3590
+ dev -> dvb_max_pkt_size_isoc_ts2 = size ;
3591
+ dev -> dvb_alt_isoc = i ;
3592
+ }
3593
+ } else {
3594
+ dev -> dvb_ep_bulk_ts2 = e -> bEndpointAddress ;
3595
+ }
3596
+ break ;
3554
3597
}
3555
3598
}
3556
3599
/* NOTE:
@@ -3565,6 +3608,8 @@ static int em28xx_usb_probe(struct usb_interface *interface,
3565
3608
* 0x83 isoc* => audio
3566
3609
* 0x84 isoc => digital
3567
3610
* 0x84 bulk => analog or digital**
3611
+ * 0x85 isoc => digital TS2
3612
+ * 0x85 bulk => digital TS2
3568
3613
* (*: audio should always be isoc)
3569
3614
* (**: analog, if ep 0x82 is isoc, otherwise digital)
3570
3615
*
@@ -3632,6 +3677,10 @@ static int em28xx_usb_probe(struct usb_interface *interface,
3632
3677
dev -> has_video = has_video ;
3633
3678
dev -> ifnum = ifnum ;
3634
3679
3680
+ dev -> ts = PRIMARY_TS ;
3681
+ snprintf (dev -> name , 28 , "em28xx" );
3682
+ dev -> dev_next = NULL ;
3683
+
3635
3684
if (has_vendor_audio ) {
3636
3685
dev_err (& interface -> dev ,
3637
3686
"Audio interface %i found (Vendor Class)\n" , ifnum );
@@ -3711,6 +3760,65 @@ static int em28xx_usb_probe(struct usb_interface *interface,
3711
3760
dev -> dvb_xfer_bulk ? "bulk" : "isoc" );
3712
3761
}
3713
3762
3763
+ if (dev -> board .has_dual_ts && em28xx_duplicate_dev (dev ) == 0 ) {
3764
+ dev -> dev_next -> ts = SECONDARY_TS ;
3765
+ dev -> dev_next -> alt = -1 ;
3766
+ dev -> dev_next -> is_audio_only = has_vendor_audio &&
3767
+ !(has_video || has_dvb );
3768
+ dev -> dev_next -> has_video = false;
3769
+ dev -> dev_next -> ifnum = ifnum ;
3770
+ dev -> dev_next -> model = id -> driver_info ;
3771
+
3772
+ mutex_init (& dev -> dev_next -> lock );
3773
+ retval = em28xx_init_dev (dev -> dev_next , udev , interface ,
3774
+ dev -> dev_next -> devno );
3775
+ if (retval )
3776
+ goto err_free ;
3777
+
3778
+ dev -> dev_next -> board .ir_codes = NULL ; /* No IR for 2nd tuner */
3779
+ dev -> dev_next -> board .has_ir_i2c = 0 ; /* No IR for 2nd tuner */
3780
+
3781
+ if (usb_xfer_mode < 0 ) {
3782
+ if (dev -> dev_next -> board .is_webcam )
3783
+ try_bulk = 1 ;
3784
+ else
3785
+ try_bulk = 0 ;
3786
+ } else {
3787
+ try_bulk = usb_xfer_mode > 0 ;
3788
+ }
3789
+
3790
+ /* Select USB transfer types to use */
3791
+ if (has_dvb ) {
3792
+ if (!dev -> dvb_ep_isoc_ts2 ||
3793
+ (try_bulk && dev -> dvb_ep_bulk_ts2 ))
3794
+ dev -> dev_next -> dvb_xfer_bulk = 1 ;
3795
+ dev_info (& dev -> intf -> dev , "dvb ts2 set to %s mode.\n" ,
3796
+ dev -> dev_next -> dvb_xfer_bulk ? "bulk" : "isoc" );
3797
+ }
3798
+
3799
+ dev -> dev_next -> dvb_ep_isoc = dev -> dvb_ep_isoc_ts2 ;
3800
+ dev -> dev_next -> dvb_ep_bulk = dev -> dvb_ep_bulk_ts2 ;
3801
+ dev -> dev_next -> dvb_max_pkt_size_isoc = dev -> dvb_max_pkt_size_isoc_ts2 ;
3802
+ dev -> dev_next -> dvb_alt_isoc = dev -> dvb_alt_isoc ;
3803
+
3804
+ /* Configuare hardware to support TS2*/
3805
+ if (dev -> dvb_xfer_bulk ) {
3806
+ /* The ep4 and ep5 are configuared for BULK */
3807
+ em28xx_write_reg (dev , 0x0b , 0x96 );
3808
+ mdelay (100 );
3809
+ em28xx_write_reg (dev , 0x0b , 0x80 );
3810
+ mdelay (100 );
3811
+ } else {
3812
+ /* The ep4 and ep5 are configuared for ISO */
3813
+ em28xx_write_reg (dev , 0x0b , 0x96 );
3814
+ mdelay (100 );
3815
+ em28xx_write_reg (dev , 0x0b , 0x82 );
3816
+ mdelay (100 );
3817
+ }
3818
+
3819
+ kref_init (& dev -> dev_next -> ref );
3820
+ }
3821
+
3714
3822
kref_init (& dev -> ref );
3715
3823
3716
3824
request_modules (dev );
@@ -3753,15 +3861,29 @@ static void em28xx_usb_disconnect(struct usb_interface *interface)
3753
3861
if (!dev )
3754
3862
return ;
3755
3863
3864
+ if (dev -> dev_next != NULL ) {
3865
+ dev -> dev_next -> disconnected = 1 ;
3866
+ dev_info (& dev -> intf -> dev , "Disconnecting %s\n" ,
3867
+ dev -> dev_next -> name );
3868
+ flush_request_modules (dev -> dev_next );
3869
+ }
3870
+
3756
3871
dev -> disconnected = 1 ;
3757
3872
3758
- dev_err (& dev -> intf -> dev , "Disconnecting\n" );
3873
+ dev_err (& dev -> intf -> dev , "Disconnecting %s \n" , dev -> name );
3759
3874
3760
3875
flush_request_modules (dev );
3761
3876
3762
3877
em28xx_close_extension (dev );
3763
3878
3879
+ if (dev -> dev_next != NULL )
3880
+ em28xx_release_resources (dev -> dev_next );
3764
3881
em28xx_release_resources (dev );
3882
+
3883
+ if (dev -> dev_next != NULL ) {
3884
+ kref_put (& dev -> dev_next -> ref , em28xx_free_device );
3885
+ dev -> dev_next = NULL ;
3886
+ }
3765
3887
kref_put (& dev -> ref , em28xx_free_device );
3766
3888
}
3767
3889
0 commit comments