aboutsummaryrefslogtreecommitdiff
path: root/drivers/media/usb
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/media/usb')
-rw-r--r--drivers/media/usb/au0828/au0828-dvb.c57
-rw-r--r--drivers/media/usb/au0828/au0828.h2
-rw-r--r--drivers/media/usb/dvb-usb-v2/af9035.c40
-rw-r--r--drivers/media/usb/dvb-usb-v2/dvb_usb_core.c6
-rw-r--r--drivers/media/usb/dvb-usb/az6027.c7
-rw-r--r--drivers/media/usb/dvb-usb/dib0700.h2
-rw-r--r--drivers/media/usb/dvb-usb/dib0700_core.c43
-rw-r--r--drivers/media/usb/dvb-usb/dib0700_devices.c2
-rw-r--r--drivers/media/usb/gspca/pac7302.c1
-rw-r--r--drivers/media/usb/hdpvr/hdpvr-video.c6
10 files changed, 137 insertions, 29 deletions
diff --git a/drivers/media/usb/au0828/au0828-dvb.c b/drivers/media/usb/au0828/au0828-dvb.c
index 4ae8b107464..d8b5d948027 100644
--- a/drivers/media/usb/au0828/au0828-dvb.c
+++ b/drivers/media/usb/au0828/au0828-dvb.c
@@ -114,16 +114,20 @@ static void urb_completion(struct urb *purb)
int ptype = usb_pipetype(purb->pipe);
unsigned char *ptr;
- dprintk(2, "%s()\n", __func__);
+ dprintk(2, "%s: %d\n", __func__, purb->actual_length);
- if (!dev)
+ if (!dev) {
+ dprintk(2, "%s: no dev!\n", __func__);
return;
+ }
- if (dev->urb_streaming == 0)
+ if (dev->urb_streaming == 0) {
+ dprintk(2, "%s: not streaming!\n", __func__);
return;
+ }
if (ptype != PIPE_BULK) {
- printk(KERN_ERR "%s() Unsupported URB type %d\n",
+ printk(KERN_ERR "%s: Unsupported URB type %d\n",
__func__, ptype);
return;
}
@@ -252,8 +256,6 @@ static void au0828_stop_transport(struct au0828_dev *dev, int full_stop)
au0828_write(dev, 0x60b, 0x00);
}
-
-
static int au0828_dvb_start_feed(struct dvb_demux_feed *feed)
{
struct dvb_demux *demux = feed->demux;
@@ -296,6 +298,8 @@ static int au0828_dvb_stop_feed(struct dvb_demux_feed *feed)
dprintk(1, "%s()\n", __func__);
if (dvb) {
+ cancel_work_sync(&dev->restart_streaming);
+
mutex_lock(&dvb->lock);
dvb->stop_count++;
dprintk(1, "%s(), start_count: %d, stop_count: %d\n", __func__,
@@ -338,6 +342,41 @@ static void au0828_restart_dvb_streaming(struct work_struct *work)
mutex_unlock(&dvb->lock);
}
+static int au0828_set_frontend(struct dvb_frontend *fe)
+{
+ struct au0828_dev *dev = fe->dvb->priv;
+ struct au0828_dvb *dvb = &dev->dvb;
+ int ret, was_streaming;
+
+ mutex_lock(&dvb->lock);
+ was_streaming = dev->urb_streaming;
+ if (was_streaming) {
+ au0828_stop_transport(dev, 1);
+
+ /*
+ * We can't hold a mutex here, as the restart_streaming
+ * kthread may also hold it.
+ */
+ mutex_unlock(&dvb->lock);
+ cancel_work_sync(&dev->restart_streaming);
+ mutex_lock(&dvb->lock);
+
+ stop_urb_transfer(dev);
+ }
+ mutex_unlock(&dvb->lock);
+
+ ret = dvb->set_frontend(fe);
+
+ if (was_streaming) {
+ mutex_lock(&dvb->lock);
+ au0828_start_transport(dev);
+ start_urb_transfer(dev);
+ mutex_unlock(&dvb->lock);
+ }
+
+ return ret;
+}
+
static int dvb_register(struct au0828_dev *dev)
{
struct au0828_dvb *dvb = &dev->dvb;
@@ -382,6 +421,10 @@ static int dvb_register(struct au0828_dev *dev)
goto fail_frontend;
}
+ /* Hook dvb frontend */
+ dvb->set_frontend = dvb->frontend->ops.set_frontend;
+ dvb->frontend->ops.set_frontend = au0828_set_frontend;
+
/* register demux stuff */
dvb->demux.dmx.capabilities =
DMX_TS_FILTERING | DMX_SECTION_FILTERING |
@@ -471,6 +514,8 @@ void au0828_dvb_unregister(struct au0828_dev *dev)
if (dvb->frontend == NULL)
return;
+ cancel_work_sync(&dev->restart_streaming);
+
dvb_net_release(&dvb->net);
dvb->demux.dmx.remove_frontend(&dvb->demux.dmx, &dvb->fe_mem);
dvb->demux.dmx.remove_frontend(&dvb->demux.dmx, &dvb->fe_hw);
diff --git a/drivers/media/usb/au0828/au0828.h b/drivers/media/usb/au0828/au0828.h
index 5439772c155..7112b9d956f 100644
--- a/drivers/media/usb/au0828/au0828.h
+++ b/drivers/media/usb/au0828/au0828.h
@@ -104,6 +104,8 @@ struct au0828_dvb {
int feeding;
int start_count;
int stop_count;
+
+ int (*set_frontend)(struct dvb_frontend *fe);
};
enum au0828_stream_state {
diff --git a/drivers/media/usb/dvb-usb-v2/af9035.c b/drivers/media/usb/dvb-usb-v2/af9035.c
index 021e4d35e4d..7b9b75f6077 100644
--- a/drivers/media/usb/dvb-usb-v2/af9035.c
+++ b/drivers/media/usb/dvb-usb-v2/af9035.c
@@ -704,15 +704,41 @@ static int af9035_read_config(struct dvb_usb_device *d)
if (ret < 0)
goto err;
- if (tmp == 0x00)
- dev_dbg(&d->udev->dev,
- "%s: [%d]tuner not set, using default\n",
- __func__, i);
- else
+ dev_dbg(&d->udev->dev, "%s: [%d]tuner=%02x\n",
+ __func__, i, tmp);
+
+ /* tuner sanity check */
+ if (state->chip_type == 0x9135) {
+ if (state->chip_version == 0x02) {
+ /* IT9135 BX (v2) */
+ switch (tmp) {
+ case AF9033_TUNER_IT9135_60:
+ case AF9033_TUNER_IT9135_61:
+ case AF9033_TUNER_IT9135_62:
+ state->af9033_config[i].tuner = tmp;
+ break;
+ }
+ } else {
+ /* IT9135 AX (v1) */
+ switch (tmp) {
+ case AF9033_TUNER_IT9135_38:
+ case AF9033_TUNER_IT9135_51:
+ case AF9033_TUNER_IT9135_52:
+ state->af9033_config[i].tuner = tmp;
+ break;
+ }
+ }
+ } else {
+ /* AF9035 */
state->af9033_config[i].tuner = tmp;
+ }
- dev_dbg(&d->udev->dev, "%s: [%d]tuner=%02x\n",
- __func__, i, state->af9033_config[i].tuner);
+ if (state->af9033_config[i].tuner != tmp) {
+ dev_info(&d->udev->dev,
+ "%s: [%d] overriding tuner from %02x to %02x\n",
+ KBUILD_MODNAME, i, tmp,
+ state->af9033_config[i].tuner);
+ }
switch (state->af9033_config[i].tuner) {
case AF9033_TUNER_TUA9001:
diff --git a/drivers/media/usb/dvb-usb-v2/dvb_usb_core.c b/drivers/media/usb/dvb-usb-v2/dvb_usb_core.c
index de02db802ac..e3558061893 100644
--- a/drivers/media/usb/dvb-usb-v2/dvb_usb_core.c
+++ b/drivers/media/usb/dvb-usb-v2/dvb_usb_core.c
@@ -399,7 +399,7 @@ static int dvb_usb_stop_feed(struct dvb_demux_feed *dvbdmxfeed)
/* clear 'streaming' status bit */
clear_bit(ADAP_STREAMING, &adap->state_bits);
- smp_mb__after_clear_bit();
+ smp_mb__after_atomic();
wake_up_bit(&adap->state_bits, ADAP_STREAMING);
skip_feed_stop:
@@ -550,7 +550,7 @@ static int dvb_usb_fe_init(struct dvb_frontend *fe)
err:
if (!adap->suspend_resume_active) {
clear_bit(ADAP_INIT, &adap->state_bits);
- smp_mb__after_clear_bit();
+ smp_mb__after_atomic();
wake_up_bit(&adap->state_bits, ADAP_INIT);
}
@@ -591,7 +591,7 @@ err:
if (!adap->suspend_resume_active) {
adap->active_fe = -1;
clear_bit(ADAP_SLEEP, &adap->state_bits);
- smp_mb__after_clear_bit();
+ smp_mb__after_atomic();
wake_up_bit(&adap->state_bits, ADAP_SLEEP);
}
diff --git a/drivers/media/usb/dvb-usb/az6027.c b/drivers/media/usb/dvb-usb/az6027.c
index c11138ebf6f..0df52ab32a7 100644
--- a/drivers/media/usb/dvb-usb/az6027.c
+++ b/drivers/media/usb/dvb-usb/az6027.c
@@ -1088,6 +1088,7 @@ static struct usb_device_id az6027_usb_table[] = {
{ USB_DEVICE(USB_VID_TECHNISAT, USB_PID_TECHNISAT_USB2_HDCI_V1) },
{ USB_DEVICE(USB_VID_TECHNISAT, USB_PID_TECHNISAT_USB2_HDCI_V2) },
{ USB_DEVICE(USB_VID_ELGATO, USB_PID_ELGATO_EYETV_SAT) },
+ { USB_DEVICE(USB_VID_ELGATO, USB_PID_ELGATO_EYETV_SAT_V2) },
{ },
};
@@ -1136,7 +1137,7 @@ static struct dvb_usb_device_properties az6027_properties = {
.i2c_algo = &az6027_i2c_algo,
- .num_device_descs = 6,
+ .num_device_descs = 7,
.devices = {
{
.name = "AZUREWAVE DVB-S/S2 USB2.0 (AZ6027)",
@@ -1162,6 +1163,10 @@ static struct dvb_usb_device_properties az6027_properties = {
.name = "Elgato EyeTV Sat",
.cold_ids = { &az6027_usb_table[5], NULL },
.warm_ids = { NULL },
+ }, {
+ .name = "Elgato EyeTV Sat",
+ .cold_ids = { &az6027_usb_table[6], NULL },
+ .warm_ids = { NULL },
},
{ NULL },
}
diff --git a/drivers/media/usb/dvb-usb/dib0700.h b/drivers/media/usb/dvb-usb/dib0700.h
index 637b6123f39..927617d9561 100644
--- a/drivers/media/usb/dvb-usb/dib0700.h
+++ b/drivers/media/usb/dvb-usb/dib0700.h
@@ -59,7 +59,7 @@ extern int dib0700_set_gpio(struct dvb_usb_device *, enum dib07x0_gpios gpio, u8
extern int dib0700_ctrl_clock(struct dvb_usb_device *d, u32 clk_MHz, u8 clock_out_gp3);
extern int dib0700_ctrl_rd(struct dvb_usb_device *d, u8 *tx, u8 txlen, u8 *rx, u8 rxlen);
extern int dib0700_download_firmware(struct usb_device *udev, const struct firmware *fw);
-extern int dib0700_rc_setup(struct dvb_usb_device *d);
+extern int dib0700_rc_setup(struct dvb_usb_device *d, struct usb_interface *intf);
extern int dib0700_streaming_ctrl(struct dvb_usb_adapter *adap, int onoff);
extern struct i2c_algorithm dib0700_i2c_algo;
extern int dib0700_identify_state(struct usb_device *udev, struct dvb_usb_device_properties *props,
diff --git a/drivers/media/usb/dvb-usb/dib0700_core.c b/drivers/media/usb/dvb-usb/dib0700_core.c
index bf2a908d74c..c14285fa827 100644
--- a/drivers/media/usb/dvb-usb/dib0700_core.c
+++ b/drivers/media/usb/dvb-usb/dib0700_core.c
@@ -754,17 +754,20 @@ resubmit:
usb_submit_urb(purb, GFP_ATOMIC);
}
-int dib0700_rc_setup(struct dvb_usb_device *d)
+int dib0700_rc_setup(struct dvb_usb_device *d, struct usb_interface *intf)
{
struct dib0700_state *st = d->priv;
struct urb *purb;
- int ret;
+ const struct usb_endpoint_descriptor *e;
+ int ret, rc_ep = 1;
+ unsigned int pipe = 0;
/* Poll-based. Don't initialize bulk mode */
- if (st->fw_version < 0x10200)
+ if (st->fw_version < 0x10200 || !intf)
return 0;
/* Starting in firmware 1.20, the RC info is provided on a bulk pipe */
+
purb = usb_alloc_urb(0, GFP_KERNEL);
if (purb == NULL) {
err("rc usb alloc urb failed");
@@ -779,9 +782,35 @@ int dib0700_rc_setup(struct dvb_usb_device *d)
}
purb->status = -EINPROGRESS;
- usb_fill_bulk_urb(purb, d->udev, usb_rcvbulkpipe(d->udev, 1),
- purb->transfer_buffer, RC_MSG_SIZE_V1_20,
- dib0700_rc_urb_completion, d);
+
+ /*
+ * Some devices like the Hauppauge NovaTD model 52009 use an interrupt
+ * endpoint, while others use a bulk one.
+ */
+ e = &intf->altsetting[0].endpoint[rc_ep].desc;
+ if (usb_endpoint_dir_in(e)) {
+ if (usb_endpoint_xfer_bulk(e)) {
+ pipe = usb_rcvbulkpipe(d->udev, rc_ep);
+ usb_fill_bulk_urb(purb, d->udev, pipe,
+ purb->transfer_buffer,
+ RC_MSG_SIZE_V1_20,
+ dib0700_rc_urb_completion, d);
+
+ } else if (usb_endpoint_xfer_int(e)) {
+ pipe = usb_rcvintpipe(d->udev, rc_ep);
+ usb_fill_int_urb(purb, d->udev, pipe,
+ purb->transfer_buffer,
+ RC_MSG_SIZE_V1_20,
+ dib0700_rc_urb_completion, d, 1);
+ }
+ }
+
+ if (!pipe) {
+ err("There's no endpoint for remote controller");
+ kfree(purb->transfer_buffer);
+ usb_free_urb(purb);
+ return 0;
+ }
ret = usb_submit_urb(purb, GFP_ATOMIC);
if (ret) {
@@ -820,7 +849,7 @@ static int dib0700_probe(struct usb_interface *intf,
else
dev->props.rc.core.bulk_mode = false;
- dib0700_rc_setup(dev);
+ dib0700_rc_setup(dev, intf);
return 0;
}
diff --git a/drivers/media/usb/dvb-usb/dib0700_devices.c b/drivers/media/usb/dvb-usb/dib0700_devices.c
index 829323e42ca..10e0db8d185 100644
--- a/drivers/media/usb/dvb-usb/dib0700_devices.c
+++ b/drivers/media/usb/dvb-usb/dib0700_devices.c
@@ -514,7 +514,7 @@ static int dib0700_rc_query_old_firmware(struct dvb_usb_device *d)
/* info("%d: %2X %2X %2X %2X",dvb_usb_dib0700_ir_proto,(int)key[3-2],(int)key[3-3],(int)key[3-1],(int)key[3]); */
- dib0700_rc_setup(d); /* reset ir sensor data to prevent false events */
+ dib0700_rc_setup(d, NULL); /* reset ir sensor data to prevent false events */
d->last_event = 0;
switch (d->props.rc.core.protocol) {
diff --git a/drivers/media/usb/gspca/pac7302.c b/drivers/media/usb/gspca/pac7302.c
index 2fd1c5e31a0..339adce7c7a 100644
--- a/drivers/media/usb/gspca/pac7302.c
+++ b/drivers/media/usb/gspca/pac7302.c
@@ -928,6 +928,7 @@ static const struct usb_device_id device_table[] = {
{USB_DEVICE(0x093a, 0x2620)},
{USB_DEVICE(0x093a, 0x2621)},
{USB_DEVICE(0x093a, 0x2622), .driver_info = FL_VFLIP},
+ {USB_DEVICE(0x093a, 0x2623), .driver_info = FL_VFLIP},
{USB_DEVICE(0x093a, 0x2624), .driver_info = FL_VFLIP},
{USB_DEVICE(0x093a, 0x2625)},
{USB_DEVICE(0x093a, 0x2626)},
diff --git a/drivers/media/usb/hdpvr/hdpvr-video.c b/drivers/media/usb/hdpvr/hdpvr-video.c
index 0500c4175d5..6bce01a674f 100644
--- a/drivers/media/usb/hdpvr/hdpvr-video.c
+++ b/drivers/media/usb/hdpvr/hdpvr-video.c
@@ -82,7 +82,7 @@ static void hdpvr_read_bulk_callback(struct urb *urb)
}
/*=========================================================================*/
-/* bufffer bits */
+/* buffer bits */
/* function expects dev->io_mutex to be hold by caller */
int hdpvr_cancel_queue(struct hdpvr_device *dev)
@@ -926,7 +926,7 @@ static int hdpvr_s_ctrl(struct v4l2_ctrl *ctrl)
case V4L2_CID_MPEG_AUDIO_ENCODING:
if (dev->flags & HDPVR_FLAG_AC3_CAP) {
opt->audio_codec = ctrl->val;
- return hdpvr_set_audio(dev, opt->audio_input,
+ return hdpvr_set_audio(dev, opt->audio_input + 1,
opt->audio_codec);
}
return 0;
@@ -1198,7 +1198,7 @@ int hdpvr_register_videodev(struct hdpvr_device *dev, struct device *parent,
v4l2_ctrl_new_std_menu(hdl, &hdpvr_ctrl_ops,
V4L2_CID_MPEG_AUDIO_ENCODING,
ac3 ? V4L2_MPEG_AUDIO_ENCODING_AC3 : V4L2_MPEG_AUDIO_ENCODING_AAC,
- 0x7, V4L2_MPEG_AUDIO_ENCODING_AAC);
+ 0x7, ac3 ? dev->options.audio_codec : V4L2_MPEG_AUDIO_ENCODING_AAC);
v4l2_ctrl_new_std_menu(hdl, &hdpvr_ctrl_ops,
V4L2_CID_MPEG_VIDEO_ENCODING,
V4L2_MPEG_VIDEO_ENCODING_MPEG_4_AVC, 0x3,