diff options
Diffstat (limited to 'drivers/media/usb')
27 files changed, 191 insertions, 174 deletions
diff --git a/drivers/media/usb/airspy/airspy.c b/drivers/media/usb/airspy/airspy.c index e24e655fb1db..08f0920cf6ca 100644 --- a/drivers/media/usb/airspy/airspy.c +++ b/drivers/media/usb/airspy/airspy.c @@ -603,8 +603,6 @@ static const struct vb2_ops airspy_vb2_ops = { .buf_queue = airspy_buf_queue, .start_streaming = airspy_start_streaming, .stop_streaming = airspy_stop_streaming, - .wait_prepare = vb2_ops_wait_prepare, - .wait_finish = vb2_ops_wait_finish, }; static int airspy_querycap(struct file *file, void *fh, @@ -1017,6 +1015,7 @@ static int airspy_probe(struct usb_interface *intf, s->vb_queue.ops = &airspy_vb2_ops; s->vb_queue.mem_ops = &vb2_vmalloc_memops; s->vb_queue.timestamp_flags = V4L2_BUF_FLAG_TIMESTAMP_MONOTONIC; + s->vb_queue.lock = &s->vb_queue_lock; ret = vb2_queue_init(&s->vb_queue); if (ret) { dev_err(s->dev, "Could not initialize vb2 queue\n"); @@ -1026,7 +1025,6 @@ static int airspy_probe(struct usb_interface *intf, /* Init video_device structure */ s->vdev = airspy_template; s->vdev.queue = &s->vb_queue; - s->vdev.queue->lock = &s->vb_queue_lock; video_set_drvdata(&s->vdev, s); /* Register the v4l2_device structure */ diff --git a/drivers/media/usb/au0828/au0828-vbi.c b/drivers/media/usb/au0828/au0828-vbi.c index b0333637b747..11203adf47ea 100644 --- a/drivers/media/usb/au0828/au0828-vbi.c +++ b/drivers/media/usb/au0828/au0828-vbi.c @@ -74,6 +74,4 @@ const struct vb2_ops au0828_vbi_qops = { .prepare_streaming = v4l_vb2q_enable_media_source, .start_streaming = au0828_start_analog_streaming, .stop_streaming = au0828_stop_vbi_streaming, - .wait_prepare = vb2_ops_wait_prepare, - .wait_finish = vb2_ops_wait_finish, }; diff --git a/drivers/media/usb/au0828/au0828-video.c b/drivers/media/usb/au0828/au0828-video.c index 2ec49ea479d5..e9cd2a335f7f 100644 --- a/drivers/media/usb/au0828/au0828-video.c +++ b/drivers/media/usb/au0828/au0828-video.c @@ -915,8 +915,6 @@ static const struct vb2_ops au0828_video_qops = { .prepare_streaming = v4l_vb2q_enable_media_source, .start_streaming = au0828_start_analog_streaming, .stop_streaming = au0828_stop_streaming, - .wait_prepare = vb2_ops_wait_prepare, - .wait_finish = vb2_ops_wait_finish, }; /* ------------------------------------------------------------------ diff --git a/drivers/media/usb/cx231xx/cx231xx-417.c b/drivers/media/usb/cx231xx/cx231xx-417.c index abb967c8bd35..a4a9781328c5 100644 --- a/drivers/media/usb/cx231xx/cx231xx-417.c +++ b/drivers/media/usb/cx231xx/cx231xx-417.c @@ -1458,8 +1458,6 @@ static const struct vb2_ops cx231xx_video_qops = { .buf_queue = buffer_queue, .start_streaming = start_streaming, .stop_streaming = stop_streaming, - .wait_prepare = vb2_ops_wait_prepare, - .wait_finish = vb2_ops_wait_finish, }; /* ------------------------------------------------------------------ */ diff --git a/drivers/media/usb/cx231xx/cx231xx-avcore.c b/drivers/media/usb/cx231xx/cx231xx-avcore.c index 3d3c881c8e58..6139ef5d891d 100644 --- a/drivers/media/usb/cx231xx/cx231xx-avcore.c +++ b/drivers/media/usb/cx231xx/cx231xx-avcore.c @@ -623,7 +623,7 @@ int cx231xx_set_video_input_mux(struct cx231xx *dev, u8 input) } int cx231xx_set_decoder_video_input(struct cx231xx *dev, - u8 pin_type, u8 input) + u8 pin_type, u32 input) { int status = 0; u32 value = 0; @@ -1338,39 +1338,6 @@ void update_HH_register_after_set_DIF(struct cx231xx *dev) */ } -void cx231xx_dump_HH_reg(struct cx231xx *dev) -{ - u32 value = 0; - u16 i = 0; - - value = 0x45005390; - vid_blk_write_word(dev, 0x104, value); - - for (i = 0x100; i < 0x140; i++) { - vid_blk_read_word(dev, i, &value); - dev_dbg(dev->dev, "reg0x%x=0x%x\n", i, value); - i = i+3; - } - - for (i = 0x300; i < 0x400; i++) { - vid_blk_read_word(dev, i, &value); - dev_dbg(dev->dev, "reg0x%x=0x%x\n", i, value); - i = i+3; - } - - for (i = 0x400; i < 0x440; i++) { - vid_blk_read_word(dev, i, &value); - dev_dbg(dev->dev, "reg0x%x=0x%x\n", i, value); - i = i+3; - } - - vid_blk_read_word(dev, AFE_CTRL_C2HH_SRC_CTRL, &value); - dev_dbg(dev->dev, "AFE_CTRL_C2HH_SRC_CTRL=0x%x\n", value); - vid_blk_write_word(dev, AFE_CTRL_C2HH_SRC_CTRL, 0x4485D390); - vid_blk_read_word(dev, AFE_CTRL_C2HH_SRC_CTRL, &value); - dev_dbg(dev->dev, "AFE_CTRL_C2HH_SRC_CTRL=0x%x\n", value); -} - #if 0 static void cx231xx_dump_SC_reg(struct cx231xx *dev) { @@ -2460,30 +2427,6 @@ int cx231xx_set_power_mode(struct cx231xx *dev, enum AV_MODE mode) return status; } -int cx231xx_power_suspend(struct cx231xx *dev) -{ - u8 value[4] = { 0, 0, 0, 0 }; - u32 tmp = 0; - int status = 0; - - status = cx231xx_read_ctrl_reg(dev, VRT_GET_REGISTER, PWR_CTL_EN, - value, 4); - if (status > 0) - return status; - - tmp = le32_to_cpu(*((__le32 *) value)); - tmp &= (~PWR_MODE_MASK); - - value[0] = (u8) tmp; - value[1] = (u8) (tmp >> 8); - value[2] = (u8) (tmp >> 16); - value[3] = (u8) (tmp >> 24); - status = cx231xx_write_ctrl_reg(dev, VRT_SET_REGISTER, PWR_CTL_EN, - value, 4); - - return status; -} - /****************************************************************************** * S T R E A M C O N T R O L functions * ******************************************************************************/ diff --git a/drivers/media/usb/cx231xx/cx231xx-cards.c b/drivers/media/usb/cx231xx/cx231xx-cards.c index 92efe6c1f47b..691f073892b3 100644 --- a/drivers/media/usb/cx231xx/cx231xx-cards.c +++ b/drivers/media/usb/cx231xx/cx231xx-cards.c @@ -679,8 +679,7 @@ struct cx231xx_board cx231xx_boards[] = { }, { .type = CX231XX_VMUX_SVIDEO, .vmux = CX231XX_VIN_1_1 | - (CX231XX_VIN_1_2 << 8) | - CX25840_SVIDEO_ON, + (CX231XX_VIN_3_2 << 8), .amux = CX231XX_AMUX_LINE_IN, .gpio = NULL, } @@ -990,10 +989,11 @@ struct cx231xx_board cx231xx_boards[] = { } }, }, }; -const unsigned int cx231xx_bcount = ARRAY_SIZE(cx231xx_boards); /* table of devices that work with this driver */ struct usb_device_id cx231xx_id_table[] = { + {USB_DEVICE(0x1D19, 0x6108), + .driver_info = CX231XX_BOARD_PV_XCAPTURE_USB}, {USB_DEVICE(0x1D19, 0x6109), .driver_info = CX231XX_BOARD_PV_XCAPTURE_USB}, {USB_DEVICE(0x0572, 0x5A3C), diff --git a/drivers/media/usb/cx231xx/cx231xx-vbi.c b/drivers/media/usb/cx231xx/cx231xx-vbi.c index 33431d9f54c2..338e10148465 100644 --- a/drivers/media/usb/cx231xx/cx231xx-vbi.c +++ b/drivers/media/usb/cx231xx/cx231xx-vbi.c @@ -243,8 +243,6 @@ struct vb2_ops cx231xx_vbi_qops = { .buf_queue = vbi_buf_queue, .start_streaming = vbi_start_streaming, .stop_streaming = vbi_stop_streaming, - .wait_prepare = vb2_ops_wait_prepare, - .wait_finish = vb2_ops_wait_finish, }; /* ------------------------------------------------------------------ diff --git a/drivers/media/usb/cx231xx/cx231xx-video.c b/drivers/media/usb/cx231xx/cx231xx-video.c index 435eb0b32cb1..2cd4e333bc4b 100644 --- a/drivers/media/usb/cx231xx/cx231xx-video.c +++ b/drivers/media/usb/cx231xx/cx231xx-video.c @@ -800,8 +800,6 @@ static const struct vb2_ops cx231xx_video_qops = { .buf_queue = buffer_queue, .start_streaming = start_streaming, .stop_streaming = stop_streaming, - .wait_prepare = vb2_ops_wait_prepare, - .wait_finish = vb2_ops_wait_finish, }; /********************* v4l2 interface **************************************/ diff --git a/drivers/media/usb/cx231xx/cx231xx.h b/drivers/media/usb/cx231xx/cx231xx.h index 74339a6a2f71..19f5036a78d7 100644 --- a/drivers/media/usb/cx231xx/cx231xx.h +++ b/drivers/media/usb/cx231xx/cx231xx.h @@ -790,7 +790,6 @@ void cx231xx_set_DIF_bandpass(struct cx231xx *dev, u32 if_freq, u8 spectral_invert, u32 mode); void cx231xx_Setup_AFE_for_LowIF(struct cx231xx *dev); void reset_s5h1432_demod(struct cx231xx *dev); -void cx231xx_dump_HH_reg(struct cx231xx *dev); void update_HH_register_after_set_DIF(struct cx231xx *dev); @@ -905,7 +904,6 @@ int cx231xx_initialize_stream_xfer(struct cx231xx *dev, u32 media_type); /* Power control functions */ int cx231xx_set_power_mode(struct cx231xx *dev, enum AV_MODE mode); -int cx231xx_power_suspend(struct cx231xx *dev); /* chip specific control functions */ int cx231xx_init_ctrl_pin_status(struct cx231xx *dev); @@ -916,7 +914,7 @@ int cx231xx_enable_i2c_port_3(struct cx231xx *dev, bool is_port_3); /* video audio decoder related functions */ void video_mux(struct cx231xx *dev, int index); int cx231xx_set_video_input_mux(struct cx231xx *dev, u8 input); -int cx231xx_set_decoder_video_input(struct cx231xx *dev, u8 pin_type, u8 input); +int cx231xx_set_decoder_video_input(struct cx231xx *dev, u8 pin_type, u32 input); int cx231xx_do_mode_ctrl_overrides(struct cx231xx *dev); int cx231xx_set_audio_input(struct cx231xx *dev, u8 input); @@ -949,7 +947,6 @@ extern void cx231xx_pre_card_setup(struct cx231xx *dev); extern void cx231xx_card_setup(struct cx231xx *dev); extern struct cx231xx_board cx231xx_boards[]; extern struct usb_device_id cx231xx_id_table[]; -extern const unsigned int cx231xx_bcount; int cx231xx_tuner_callback(void *ptr, int component, int command, int arg); /* cx23885-417.c */ diff --git a/drivers/media/usb/dvb-usb/cxusb-analog.c b/drivers/media/usb/dvb-usb/cxusb-analog.c index b5d8c6b75ae1..8253046cd6e6 100644 --- a/drivers/media/usb/dvb-usb/cxusb-analog.c +++ b/drivers/media/usb/dvb-usb/cxusb-analog.c @@ -956,8 +956,6 @@ static const struct vb2_ops cxdev_video_qops = { .start_streaming = cxusb_medion_v_start_streaming, .stop_streaming = cxusb_medion_v_stop_streaming, .buf_queue = cxusub_medion_v_buf_queue, - .wait_prepare = vb2_ops_wait_prepare, - .wait_finish = vb2_ops_wait_finish }; static const __u32 videocaps = V4L2_CAP_VIDEO_CAPTURE | V4L2_CAP_TUNER | diff --git a/drivers/media/usb/em28xx/em28xx-vbi.c b/drivers/media/usb/em28xx/em28xx-vbi.c index b253c44c9724..8c5d95181223 100644 --- a/drivers/media/usb/em28xx/em28xx-vbi.c +++ b/drivers/media/usb/em28xx/em28xx-vbi.c @@ -84,6 +84,4 @@ const struct vb2_ops em28xx_vbi_qops = { .buf_queue = vbi_buffer_queue, .start_streaming = em28xx_start_analog_streaming, .stop_streaming = em28xx_stop_vbi_streaming, - .wait_prepare = vb2_ops_wait_prepare, - .wait_finish = vb2_ops_wait_finish, }; diff --git a/drivers/media/usb/em28xx/em28xx-video.c b/drivers/media/usb/em28xx/em28xx-video.c index 4aef584e21da..66c09bc6d59e 100644 --- a/drivers/media/usb/em28xx/em28xx-video.c +++ b/drivers/media/usb/em28xx/em28xx-video.c @@ -1229,8 +1229,6 @@ static const struct vb2_ops em28xx_video_qops = { .buf_queue = buffer_queue, .start_streaming = em28xx_start_analog_streaming, .stop_streaming = em28xx_stop_streaming, - .wait_prepare = vb2_ops_wait_prepare, - .wait_finish = vb2_ops_wait_finish, }; static int em28xx_vb2_setup(struct em28xx *dev) diff --git a/drivers/media/usb/go7007/go7007-v4l2.c b/drivers/media/usb/go7007/go7007-v4l2.c index 13256565b034..2087ffcb85a5 100644 --- a/drivers/media/usb/go7007/go7007-v4l2.c +++ b/drivers/media/usb/go7007/go7007-v4l2.c @@ -452,8 +452,6 @@ static const struct vb2_ops go7007_video_qops = { .buf_finish = go7007_buf_finish, .start_streaming = go7007_start_streaming, .stop_streaming = go7007_stop_streaming, - .wait_prepare = vb2_ops_wait_prepare, - .wait_finish = vb2_ops_wait_finish, }; static int vidioc_g_parm(struct file *filp, void *priv, diff --git a/drivers/media/usb/gspca/gspca.c b/drivers/media/usb/gspca/gspca.c index e8c8bdb9c40b..25edd2189654 100644 --- a/drivers/media/usb/gspca/gspca.c +++ b/drivers/media/usb/gspca/gspca.c @@ -1380,8 +1380,6 @@ static const struct vb2_ops gspca_qops = { .buf_queue = gspca_buffer_queue, .start_streaming = gspca_start_streaming, .stop_streaming = gspca_stop_streaming, - .wait_prepare = vb2_ops_wait_prepare, - .wait_finish = vb2_ops_wait_finish, }; static const struct v4l2_file_operations dev_fops = { diff --git a/drivers/media/usb/gspca/ov534.c b/drivers/media/usb/gspca/ov534.c index 8b6a57f170d0..bdff64a29a33 100644 --- a/drivers/media/usb/gspca/ov534.c +++ b/drivers/media/usb/gspca/ov534.c @@ -847,7 +847,7 @@ static void set_frame_rate(struct gspca_dev *gspca_dev) r = rate_1; i = ARRAY_SIZE(rate_1); } - while (--i > 0) { + while (--i >= 0) { if (sd->frame_rate >= r->fps) break; r++; diff --git a/drivers/media/usb/hackrf/hackrf.c b/drivers/media/usb/hackrf/hackrf.c index 9c0ecd5f056c..0b50de8775a3 100644 --- a/drivers/media/usb/hackrf/hackrf.c +++ b/drivers/media/usb/hackrf/hackrf.c @@ -888,8 +888,6 @@ static const struct vb2_ops hackrf_vb2_ops = { .buf_queue = hackrf_buf_queue, .start_streaming = hackrf_start_streaming, .stop_streaming = hackrf_stop_streaming, - .wait_prepare = vb2_ops_wait_prepare, - .wait_finish = vb2_ops_wait_finish, }; static int hackrf_querycap(struct file *file, void *fh, @@ -1398,6 +1396,7 @@ static int hackrf_probe(struct usb_interface *intf, dev->rx_vb2_queue.drv_priv = dev; dev->rx_vb2_queue.buf_struct_size = sizeof(struct hackrf_buffer); dev->rx_vb2_queue.timestamp_flags = V4L2_BUF_FLAG_TIMESTAMP_MONOTONIC; + dev->rx_vb2_queue.lock = &dev->vb_queue_lock; ret = vb2_queue_init(&dev->rx_vb2_queue); if (ret) { dev_err(dev->dev, "Could not initialize rx vb2 queue\n"); @@ -1413,6 +1412,7 @@ static int hackrf_probe(struct usb_interface *intf, dev->tx_vb2_queue.drv_priv = dev; dev->tx_vb2_queue.buf_struct_size = sizeof(struct hackrf_buffer); dev->tx_vb2_queue.timestamp_flags = V4L2_BUF_FLAG_TIMESTAMP_MONOTONIC; + dev->tx_vb2_queue.lock = &dev->vb_queue_lock; ret = vb2_queue_init(&dev->tx_vb2_queue); if (ret) { dev_err(dev->dev, "Could not initialize tx vb2 queue\n"); @@ -1474,7 +1474,6 @@ static int hackrf_probe(struct usb_interface *intf, /* Init video_device structure for receiver */ dev->rx_vdev = hackrf_template; dev->rx_vdev.queue = &dev->rx_vb2_queue; - dev->rx_vdev.queue->lock = &dev->vb_queue_lock; dev->rx_vdev.v4l2_dev = &dev->v4l2_dev; dev->rx_vdev.ctrl_handler = &dev->rx_ctrl_handler; dev->rx_vdev.lock = &dev->v4l2_lock; @@ -1494,7 +1493,6 @@ static int hackrf_probe(struct usb_interface *intf, /* Init video_device structure for transmitter */ dev->tx_vdev = hackrf_template; dev->tx_vdev.queue = &dev->tx_vb2_queue; - dev->tx_vdev.queue->lock = &dev->vb_queue_lock; dev->tx_vdev.v4l2_dev = &dev->v4l2_dev; dev->tx_vdev.ctrl_handler = &dev->tx_ctrl_handler; dev->tx_vdev.lock = &dev->v4l2_lock; diff --git a/drivers/media/usb/msi2500/msi2500.c b/drivers/media/usb/msi2500/msi2500.c index 05b0550e840c..33099f39146a 100644 --- a/drivers/media/usb/msi2500/msi2500.c +++ b/drivers/media/usb/msi2500/msi2500.c @@ -883,8 +883,6 @@ static const struct vb2_ops msi2500_vb2_ops = { .buf_queue = msi2500_buf_queue, .start_streaming = msi2500_start_streaming, .stop_streaming = msi2500_stop_streaming, - .wait_prepare = vb2_ops_wait_prepare, - .wait_finish = vb2_ops_wait_finish, }; static int msi2500_enum_fmt_sdr_cap(struct file *file, void *priv, @@ -1199,6 +1197,7 @@ static int msi2500_probe(struct usb_interface *intf, dev->vb_queue.ops = &msi2500_vb2_ops; dev->vb_queue.mem_ops = &vb2_vmalloc_memops; dev->vb_queue.timestamp_flags = V4L2_BUF_FLAG_TIMESTAMP_MONOTONIC; + dev->vb_queue.lock = &dev->vb_queue_lock; ret = vb2_queue_init(&dev->vb_queue); if (ret) { dev_err(dev->dev, "Could not initialize vb2 queue\n"); @@ -1208,7 +1207,6 @@ static int msi2500_probe(struct usb_interface *intf, /* Init video_device structure */ dev->vdev = msi2500_template; dev->vdev.queue = &dev->vb_queue; - dev->vdev.queue->lock = &dev->vb_queue_lock; video_set_drvdata(&dev->vdev, dev); /* Register the v4l2_device structure */ diff --git a/drivers/media/usb/pvrusb2/pvrusb2-io.c b/drivers/media/usb/pvrusb2/pvrusb2-io.c index 675dc7153e2b..28ffe7981f8c 100644 --- a/drivers/media/usb/pvrusb2/pvrusb2-io.c +++ b/drivers/media/usb/pvrusb2/pvrusb2-io.c @@ -335,8 +335,8 @@ static int pvr2_stream_buffer_count(struct pvr2_stream *sp, unsigned int cnt) if (scnt < sp->buffer_slot_count) { struct pvr2_buffer **nb = NULL; if (scnt) { - nb = kmemdup(sp->buffers, scnt * sizeof(*nb), - GFP_KERNEL); + nb = kmemdup_array(sp->buffers, scnt, sizeof(*nb), + GFP_KERNEL); if (!nb) return -ENOMEM; } kfree(sp->buffers); diff --git a/drivers/media/usb/pwc/pwc-if.c b/drivers/media/usb/pwc/pwc-if.c index e342199711d3..3ec9eb5956ed 100644 --- a/drivers/media/usb/pwc/pwc-if.c +++ b/drivers/media/usb/pwc/pwc-if.c @@ -760,8 +760,6 @@ static const struct vb2_ops pwc_vb_queue_ops = { .buf_queue = buffer_queue, .start_streaming = start_streaming, .stop_streaming = stop_streaming, - .wait_prepare = vb2_ops_wait_prepare, - .wait_finish = vb2_ops_wait_finish, }; /***************************************************************************/ @@ -1054,6 +1052,7 @@ static int usb_pwc_probe(struct usb_interface *intf, const struct usb_device_id pdev->vb_queue.ops = &pwc_vb_queue_ops; pdev->vb_queue.mem_ops = &vb2_vmalloc_memops; pdev->vb_queue.timestamp_flags = V4L2_BUF_FLAG_TIMESTAMP_MONOTONIC; + pdev->vb_queue.lock = &pdev->vb_queue_lock; rc = vb2_queue_init(&pdev->vb_queue); if (rc < 0) { PWC_ERROR("Oops, could not initialize vb2 queue.\n"); @@ -1064,7 +1063,6 @@ static int usb_pwc_probe(struct usb_interface *intf, const struct usb_device_id pdev->vdev = pwc_template; strscpy(pdev->vdev.name, name, sizeof(pdev->vdev.name)); pdev->vdev.queue = &pdev->vb_queue; - pdev->vdev.queue->lock = &pdev->vb_queue_lock; video_set_drvdata(&pdev->vdev, pdev); pdev->release = le16_to_cpu(udev->descriptor.bcdDevice); diff --git a/drivers/media/usb/s2255/s2255drv.c b/drivers/media/usb/s2255/s2255drv.c index a6e450181fd0..899a7a67e2ba 100644 --- a/drivers/media/usb/s2255/s2255drv.c +++ b/drivers/media/usb/s2255/s2255drv.c @@ -704,8 +704,6 @@ static const struct vb2_ops s2255_video_qops = { .buf_queue = buffer_queue, .start_streaming = start_streaming, .stop_streaming = stop_streaming, - .wait_prepare = vb2_ops_wait_prepare, - .wait_finish = vb2_ops_wait_finish, }; static int vidioc_querycap(struct file *file, void *priv, diff --git a/drivers/media/usb/stk1160/stk1160-v4l.c b/drivers/media/usb/stk1160/stk1160-v4l.c index a1f785a5ffd8..5ba3d9c4b3fb 100644 --- a/drivers/media/usb/stk1160/stk1160-v4l.c +++ b/drivers/media/usb/stk1160/stk1160-v4l.c @@ -734,8 +734,6 @@ static const struct vb2_ops stk1160_video_qops = { .buf_queue = buffer_queue, .start_streaming = start_streaming, .stop_streaming = stop_streaming, - .wait_prepare = vb2_ops_wait_prepare, - .wait_finish = vb2_ops_wait_finish, }; static const struct video_device v4l_template = { diff --git a/drivers/media/usb/usbtv/usbtv-video.c b/drivers/media/usb/usbtv/usbtv-video.c index 702f1c8bd2ab..be22a9697197 100644 --- a/drivers/media/usb/usbtv/usbtv-video.c +++ b/drivers/media/usb/usbtv/usbtv-video.c @@ -780,8 +780,6 @@ static const struct vb2_ops usbtv_vb2_ops = { .buf_queue = usbtv_buf_queue, .start_streaming = usbtv_start_streaming, .stop_streaming = usbtv_stop_streaming, - .wait_prepare = vb2_ops_wait_prepare, - .wait_finish = vb2_ops_wait_finish, }; static int usbtv_s_ctrl(struct v4l2_ctrl *ctrl) diff --git a/drivers/media/usb/uvc/uvc_driver.c b/drivers/media/usb/uvc/uvc_driver.c index 0fac689c6350..faf5386cb061 100644 --- a/drivers/media/usb/uvc/uvc_driver.c +++ b/drivers/media/usb/uvc/uvc_driver.c @@ -775,14 +775,27 @@ static const u8 uvc_media_transport_input_guid[16] = UVC_GUID_UVC_MEDIA_TRANSPORT_INPUT; static const u8 uvc_processing_guid[16] = UVC_GUID_UVC_PROCESSING; -static struct uvc_entity *uvc_alloc_entity(u16 type, u16 id, - unsigned int num_pads, unsigned int extra_size) +static struct uvc_entity *uvc_alloc_new_entity(struct uvc_device *dev, u16 type, + u16 id, unsigned int num_pads, + unsigned int extra_size) { struct uvc_entity *entity; unsigned int num_inputs; unsigned int size; unsigned int i; + /* Per UVC 1.1+ spec 3.7.2, the ID should be non-zero. */ + if (id == 0) { + dev_err(&dev->udev->dev, "Found Unit with invalid ID 0.\n"); + return ERR_PTR(-EINVAL); + } + + /* Per UVC 1.1+ spec 3.7.2, the ID is unique. */ + if (uvc_entity_by_id(dev, id)) { + dev_err(&dev->udev->dev, "Found multiple Units with ID %u\n", id); + return ERR_PTR(-EINVAL); + } + extra_size = roundup(extra_size, sizeof(*entity->pads)); if (num_pads) num_inputs = type & UVC_TERM_OUTPUT ? num_pads : num_pads - 1; @@ -792,7 +805,7 @@ static struct uvc_entity *uvc_alloc_entity(u16 type, u16 id, + num_inputs; entity = kzalloc(size, GFP_KERNEL); if (entity == NULL) - return NULL; + return ERR_PTR(-ENOMEM); entity->id = id; entity->type = type; @@ -904,10 +917,10 @@ static int uvc_parse_vendor_control(struct uvc_device *dev, break; } - unit = uvc_alloc_entity(UVC_VC_EXTENSION_UNIT, buffer[3], - p + 1, 2*n); - if (unit == NULL) - return -ENOMEM; + unit = uvc_alloc_new_entity(dev, UVC_VC_EXTENSION_UNIT, + buffer[3], p + 1, 2 * n); + if (IS_ERR(unit)) + return PTR_ERR(unit); memcpy(unit->guid, &buffer[4], 16); unit->extension.bNumControls = buffer[20]; @@ -1016,10 +1029,10 @@ static int uvc_parse_standard_control(struct uvc_device *dev, return -EINVAL; } - term = uvc_alloc_entity(type | UVC_TERM_INPUT, buffer[3], - 1, n + p); - if (term == NULL) - return -ENOMEM; + term = uvc_alloc_new_entity(dev, type | UVC_TERM_INPUT, + buffer[3], 1, n + p); + if (IS_ERR(term)) + return PTR_ERR(term); if (UVC_ENTITY_TYPE(term) == UVC_ITT_CAMERA) { term->camera.bControlSize = n; @@ -1075,10 +1088,10 @@ static int uvc_parse_standard_control(struct uvc_device *dev, return 0; } - term = uvc_alloc_entity(type | UVC_TERM_OUTPUT, buffer[3], - 1, 0); - if (term == NULL) - return -ENOMEM; + term = uvc_alloc_new_entity(dev, type | UVC_TERM_OUTPUT, + buffer[3], 1, 0); + if (IS_ERR(term)) + return PTR_ERR(term); memcpy(term->baSourceID, &buffer[7], 1); @@ -1097,9 +1110,10 @@ static int uvc_parse_standard_control(struct uvc_device *dev, return -EINVAL; } - unit = uvc_alloc_entity(buffer[2], buffer[3], p + 1, 0); - if (unit == NULL) - return -ENOMEM; + unit = uvc_alloc_new_entity(dev, buffer[2], buffer[3], + p + 1, 0); + if (IS_ERR(unit)) + return PTR_ERR(unit); memcpy(unit->baSourceID, &buffer[5], p); @@ -1119,9 +1133,9 @@ static int uvc_parse_standard_control(struct uvc_device *dev, return -EINVAL; } - unit = uvc_alloc_entity(buffer[2], buffer[3], 2, n); - if (unit == NULL) - return -ENOMEM; + unit = uvc_alloc_new_entity(dev, buffer[2], buffer[3], 2, n); + if (IS_ERR(unit)) + return PTR_ERR(unit); memcpy(unit->baSourceID, &buffer[4], 1); unit->processing.wMaxMultiplier = @@ -1148,9 +1162,10 @@ static int uvc_parse_standard_control(struct uvc_device *dev, return -EINVAL; } - unit = uvc_alloc_entity(buffer[2], buffer[3], p + 1, n); - if (unit == NULL) - return -ENOMEM; + unit = uvc_alloc_new_entity(dev, buffer[2], buffer[3], + p + 1, n); + if (IS_ERR(unit)) + return PTR_ERR(unit); memcpy(unit->guid, &buffer[4], 16); unit->extension.bNumControls = buffer[20]; @@ -1290,9 +1305,10 @@ static int uvc_gpio_parse(struct uvc_device *dev) return dev_err_probe(&dev->udev->dev, irq, "No IRQ for privacy GPIO\n"); - unit = uvc_alloc_entity(UVC_EXT_GPIO_UNIT, UVC_EXT_GPIO_UNIT_ID, 0, 1); - if (!unit) - return -ENOMEM; + unit = uvc_alloc_new_entity(dev, UVC_EXT_GPIO_UNIT, + UVC_EXT_GPIO_UNIT_ID, 0, 1); + if (IS_ERR(unit)) + return PTR_ERR(unit); unit->gpio.gpio_privacy = gpio_privacy; unit->gpio.irq = irq; @@ -1919,11 +1935,41 @@ static void uvc_unregister_video(struct uvc_device *dev) struct uvc_streaming *stream; list_for_each_entry(stream, &dev->streams, list) { + /* Nothing to do here, continue. */ if (!video_is_registered(&stream->vdev)) continue; + /* + * For stream->vdev we follow the same logic as: + * vb2_video_unregister_device(). + */ + + /* 1. Take a reference to vdev */ + get_device(&stream->vdev.dev); + + /* 2. Ensure that no new ioctls can be called. */ video_unregister_device(&stream->vdev); - video_unregister_device(&stream->meta.vdev); + + /* 3. Wait for old ioctls to finish. */ + mutex_lock(&stream->mutex); + + /* 4. Stop streaming. */ + uvc_queue_release(&stream->queue); + + mutex_unlock(&stream->mutex); + + put_device(&stream->vdev.dev); + + /* + * For stream->meta.vdev we can directly call: + * vb2_video_unregister_device(). + */ + vb2_video_unregister_device(&stream->meta.vdev); + + /* + * Now both vdevs are not streaming and all the ioctls will + * return -ENODEV. + */ uvc_debugfs_cleanup_stream(stream); } @@ -2116,7 +2162,6 @@ static int uvc_probe(struct usb_interface *intf, INIT_LIST_HEAD(&dev->streams); kref_init(&dev->ref); atomic_set(&dev->nmappings, 0); - mutex_init(&dev->lock); dev->udev = usb_get_dev(udev); dev->intf = usb_get_intf(intf); @@ -2288,10 +2333,7 @@ static int uvc_suspend(struct usb_interface *intf, pm_message_t message) /* Controls are cached on the fly so they don't need to be saved. */ if (intf->cur_altsetting->desc.bInterfaceSubClass == UVC_SC_VIDEOCONTROL) { - mutex_lock(&dev->lock); - if (dev->users) - uvc_status_stop(dev); - mutex_unlock(&dev->lock); + uvc_status_suspend(dev); return 0; } @@ -2322,12 +2364,7 @@ static int __uvc_resume(struct usb_interface *intf, int reset) return ret; } - mutex_lock(&dev->lock); - if (dev->users) - ret = uvc_status_start(dev, GFP_NOIO); - mutex_unlock(&dev->lock); - - return ret; + return uvc_status_resume(dev); } list_for_each_entry(stream, &dev->streams, list) { @@ -2428,12 +2465,25 @@ static const struct uvc_device_info uvc_quirk_force_y8 = { * The Logitech cameras listed below have their interface class set to * VENDOR_SPEC because they don't announce themselves as UVC devices, even * though they are compliant. + * + * Sort these by vendor/product ID. */ static const struct usb_device_id uvc_ids[] = { /* Quanta ACER HD User Facing */ { .match_flags = USB_DEVICE_ID_MATCH_DEVICE | USB_DEVICE_ID_MATCH_INT_INFO, .idVendor = 0x0408, + .idProduct = 0x4033, + .bInterfaceClass = USB_CLASS_VIDEO, + .bInterfaceSubClass = 1, + .bInterfaceProtocol = UVC_PC_PROTOCOL_15, + .driver_info = (kernel_ulong_t)&(const struct uvc_device_info){ + .uvc_version = 0x010a, + } }, + /* Quanta ACER HD User Facing */ + { .match_flags = USB_DEVICE_ID_MATCH_DEVICE + | USB_DEVICE_ID_MATCH_INT_INFO, + .idVendor = 0x0408, .idProduct = 0x4035, .bInterfaceClass = USB_CLASS_VIDEO, .bInterfaceSubClass = 1, @@ -2964,6 +3014,15 @@ static const struct usb_device_id uvc_ids[] = { .bInterfaceProtocol = 0, .driver_info = UVC_INFO_QUIRK(UVC_QUIRK_PROBE_MINMAX | UVC_QUIRK_IGNORE_SELECTOR_UNIT) }, + /* NXP Semiconductors IR VIDEO */ + { .match_flags = USB_DEVICE_ID_MATCH_DEVICE + | USB_DEVICE_ID_MATCH_INT_INFO, + .idVendor = 0x1fc9, + .idProduct = 0x009b, + .bInterfaceClass = USB_CLASS_VIDEO, + .bInterfaceSubClass = 1, + .bInterfaceProtocol = 0, + .driver_info = (kernel_ulong_t)&uvc_quirk_probe_minmax }, /* Oculus VR Positional Tracker DK2 */ { .match_flags = USB_DEVICE_ID_MATCH_DEVICE | USB_DEVICE_ID_MATCH_INT_INFO, @@ -3072,6 +3131,15 @@ static const struct usb_device_id uvc_ids[] = { .bInterfaceSubClass = 1, .bInterfaceProtocol = 0, .driver_info = UVC_INFO_META(V4L2_META_FMT_D4XX) }, + /* Intel D421 Depth Module */ + { .match_flags = USB_DEVICE_ID_MATCH_DEVICE + | USB_DEVICE_ID_MATCH_INT_INFO, + .idVendor = 0x8086, + .idProduct = 0x1155, + .bInterfaceClass = USB_CLASS_VIDEO, + .bInterfaceSubClass = 1, + .bInterfaceProtocol = 0, + .driver_info = UVC_INFO_META(V4L2_META_FMT_D4XX) }, /* Generic USB Video Class */ { USB_INTERFACE_INFO(USB_CLASS_VIDEO, 1, UVC_PC_PROTOCOL_UNDEFINED) }, { USB_INTERFACE_INFO(USB_CLASS_VIDEO, 1, UVC_PC_PROTOCOL_15) }, diff --git a/drivers/media/usb/uvc/uvc_queue.c b/drivers/media/usb/uvc/uvc_queue.c index 16fa17bbd15e..26ee85657fc8 100644 --- a/drivers/media/usb/uvc/uvc_queue.c +++ b/drivers/media/usb/uvc/uvc_queue.c @@ -197,8 +197,6 @@ static const struct vb2_ops uvc_queue_qops = { .buf_prepare = uvc_buffer_prepare, .buf_queue = uvc_buffer_queue, .buf_finish = uvc_buffer_finish, - .wait_prepare = vb2_ops_wait_prepare, - .wait_finish = vb2_ops_wait_finish, .start_streaming = uvc_start_streaming, .stop_streaming = uvc_stop_streaming, }; @@ -207,8 +205,6 @@ static const struct vb2_ops uvc_meta_queue_qops = { .queue_setup = uvc_queue_setup, .buf_prepare = uvc_buffer_prepare, .buf_queue = uvc_buffer_queue, - .wait_prepare = vb2_ops_wait_prepare, - .wait_finish = vb2_ops_wait_finish, .stop_streaming = uvc_stop_streaming, }; diff --git a/drivers/media/usb/uvc/uvc_status.c b/drivers/media/usb/uvc/uvc_status.c index a78a88c710e2..06c867510c8f 100644 --- a/drivers/media/usb/uvc/uvc_status.c +++ b/drivers/media/usb/uvc/uvc_status.c @@ -257,6 +257,8 @@ int uvc_status_init(struct uvc_device *dev) unsigned int pipe; int interval; + mutex_init(&dev->status_lock); + if (ep == NULL) return 0; @@ -292,7 +294,7 @@ int uvc_status_init(struct uvc_device *dev) void uvc_status_unregister(struct uvc_device *dev) { - usb_kill_urb(dev->int_urb); + uvc_status_suspend(dev); uvc_input_unregister(dev); } @@ -302,18 +304,25 @@ void uvc_status_cleanup(struct uvc_device *dev) kfree(dev->status); } -int uvc_status_start(struct uvc_device *dev, gfp_t flags) +static int uvc_status_start(struct uvc_device *dev, gfp_t flags) { - if (dev->int_urb == NULL) + lockdep_assert_held(&dev->status_lock); + + if (!dev->int_urb) return 0; return usb_submit_urb(dev->int_urb, flags); } -void uvc_status_stop(struct uvc_device *dev) +static void uvc_status_stop(struct uvc_device *dev) { struct uvc_ctrl_work *w = &dev->async_ctrl; + lockdep_assert_held(&dev->status_lock); + + if (!dev->int_urb) + return; + /* * Prevent the asynchronous control handler from requeing the URB. The * barrier is needed so the flush_status change is visible to other @@ -350,3 +359,49 @@ void uvc_status_stop(struct uvc_device *dev) */ smp_store_release(&dev->flush_status, false); } + +int uvc_status_resume(struct uvc_device *dev) +{ + guard(mutex)(&dev->status_lock); + + if (dev->status_users) + return uvc_status_start(dev, GFP_NOIO); + + return 0; +} + +void uvc_status_suspend(struct uvc_device *dev) +{ + guard(mutex)(&dev->status_lock); + + if (dev->status_users) + uvc_status_stop(dev); +} + +int uvc_status_get(struct uvc_device *dev) +{ + int ret; + + guard(mutex)(&dev->status_lock); + + if (!dev->status_users) { + ret = uvc_status_start(dev, GFP_KERNEL); + if (ret) + return ret; + } + + dev->status_users++; + + return 0; +} + +void uvc_status_put(struct uvc_device *dev) +{ + guard(mutex)(&dev->status_lock); + + if (dev->status_users == 1) + uvc_status_stop(dev); + WARN_ON(!dev->status_users); + if (dev->status_users) + dev->status_users--; +} diff --git a/drivers/media/usb/uvc/uvc_v4l2.c b/drivers/media/usb/uvc/uvc_v4l2.c index f4988f03640a..97c5407f6603 100644 --- a/drivers/media/usb/uvc/uvc_v4l2.c +++ b/drivers/media/usb/uvc/uvc_v4l2.c @@ -628,20 +628,13 @@ static int uvc_v4l2_open(struct file *file) return -ENOMEM; } - mutex_lock(&stream->dev->lock); - if (stream->dev->users == 0) { - ret = uvc_status_start(stream->dev, GFP_KERNEL); - if (ret < 0) { - mutex_unlock(&stream->dev->lock); - usb_autopm_put_interface(stream->dev->intf); - kfree(handle); - return ret; - } + ret = uvc_status_get(stream->dev); + if (ret) { + usb_autopm_put_interface(stream->dev->intf); + kfree(handle); + return ret; } - stream->dev->users++; - mutex_unlock(&stream->dev->lock); - v4l2_fh_init(&handle->vfh, &stream->vdev); v4l2_fh_add(&handle->vfh); handle->chain = stream->chain; @@ -670,10 +663,7 @@ static int uvc_v4l2_release(struct file *file) kfree(handle); file->private_data = NULL; - mutex_lock(&stream->dev->lock); - if (--stream->dev->users == 0) - uvc_status_stop(stream->dev); - mutex_unlock(&stream->dev->lock); + uvc_status_put(stream->dev); usb_autopm_put_interface(stream->dev->intf); return 0; diff --git a/drivers/media/usb/uvc/uvcvideo.h b/drivers/media/usb/uvc/uvcvideo.h index b7d24a853ce4..07f9921d83f2 100644 --- a/drivers/media/usb/uvc/uvcvideo.h +++ b/drivers/media/usb/uvc/uvcvideo.h @@ -563,8 +563,6 @@ struct uvc_device { const struct uvc_device_info *info; - struct mutex lock; /* Protects users */ - unsigned int users; atomic_t nmappings; /* Video control interface */ @@ -586,6 +584,8 @@ struct uvc_device { struct usb_host_endpoint *int_ep; struct urb *int_urb; struct uvc_status *status; + struct mutex status_lock; /* Protects status_users */ + unsigned int status_users; bool flush_status; struct input_dev *input; @@ -752,8 +752,10 @@ int uvc_register_video_device(struct uvc_device *dev, int uvc_status_init(struct uvc_device *dev); void uvc_status_unregister(struct uvc_device *dev); void uvc_status_cleanup(struct uvc_device *dev); -int uvc_status_start(struct uvc_device *dev, gfp_t flags); -void uvc_status_stop(struct uvc_device *dev); +int uvc_status_resume(struct uvc_device *dev); +void uvc_status_suspend(struct uvc_device *dev); +int uvc_status_get(struct uvc_device *dev); +void uvc_status_put(struct uvc_device *dev); /* Controls */ extern const struct v4l2_subscribed_event_ops uvc_ctrl_sub_ev_ops; |