diff options
Diffstat (limited to 'drivers/media/usb')
38 files changed, 731 insertions, 1440 deletions
diff --git a/drivers/media/usb/b2c2/flexcop-usb.c b/drivers/media/usb/b2c2/flexcop-usb.c index 1826ff825c2e..039963a7765b 100644 --- a/drivers/media/usb/b2c2/flexcop-usb.c +++ b/drivers/media/usb/b2c2/flexcop-usb.c @@ -295,7 +295,7 @@ static int flexcop_usb_i2c_req(struct flexcop_i2c_adapter *i2c, mutex_unlock(&fc_usb->data_mutex); - return 0; + return ret; } /* actual bus specific access functions, @@ -504,7 +504,13 @@ urb_error: static int flexcop_usb_init(struct flexcop_usb *fc_usb) { /* use the alternate setting with the larges buffer */ - usb_set_interface(fc_usb->udev,0,1); + int ret = usb_set_interface(fc_usb->udev, 0, 1); + + if (ret) { + err("set interface failed."); + return ret; + } + switch (fc_usb->udev->speed) { case USB_SPEED_LOW: err("cannot handle USB speed because it is too slow."); @@ -538,6 +544,9 @@ static int flexcop_usb_probe(struct usb_interface *intf, struct flexcop_device *fc = NULL; int ret; + if (intf->cur_altsetting->desc.bNumEndpoints < 1) + return -ENODEV; + if ((fc = flexcop_device_kmalloc(sizeof(struct flexcop_usb))) == NULL) { err("out of memory\n"); return -ENOMEM; diff --git a/drivers/media/usb/cx231xx/Kconfig b/drivers/media/usb/cx231xx/Kconfig index 74f3b29d9c60..2fe2b2d335ba 100644 --- a/drivers/media/usb/cx231xx/Kconfig +++ b/drivers/media/usb/cx231xx/Kconfig @@ -4,7 +4,7 @@ config VIDEO_CX231XX depends on VIDEO_DEV && I2C && I2C_MUX select VIDEO_TUNER select VIDEO_TVEEPROM - select VIDEOBUF_VMALLOC + select VIDEOBUF2_VMALLOC select VIDEO_CX25840 select VIDEO_CX2341X diff --git a/drivers/media/usb/cx231xx/cx231xx-417.c b/drivers/media/usb/cx231xx/cx231xx-417.c index 6d218a036966..1aec4459f50a 100644 --- a/drivers/media/usb/cx231xx/cx231xx-417.c +++ b/drivers/media/usb/cx231xx/cx231xx-417.c @@ -60,10 +60,6 @@ #define MCI_MODE_MEMORY_READ 0x000 #define MCI_MODE_MEMORY_WRITE 0x4000 -static unsigned int mpegbufs = 8; -module_param(mpegbufs, int, 0644); -MODULE_PARM_DESC(mpegbufs, "number of mpeg buffers, range 2-32"); - static unsigned int mpeglines = 128; module_param(mpeglines, int, 0644); MODULE_PARM_DESC(mpeglines, "number of lines in an MPEG buffer, range 2-32"); @@ -1080,16 +1076,6 @@ static int cx231xx_load_firmware(struct cx231xx *dev) return 0; } -static void cx231xx_417_check_encoder(struct cx231xx *dev) -{ - u32 status, seq; - - status = 0; - seq = 0; - cx231xx_api_cmd(dev, CX2341X_ENC_GET_SEQ_END, 0, 2, &status, &seq); - dprintk(1, "%s() status = %d, seq = %d\n", __func__, status, seq); -} - static void cx231xx_codec_settings(struct cx231xx *dev) { dprintk(1, "%s()\n", __func__); @@ -1227,40 +1213,25 @@ static int cx231xx_initialize_codec(struct cx231xx *dev) /* ------------------------------------------------------------------ */ -static int bb_buf_setup(struct videobuf_queue *q, - unsigned int *count, unsigned int *size) +static int queue_setup(struct vb2_queue *vq, + unsigned int *nbuffers, unsigned int *nplanes, + unsigned int sizes[], struct device *alloc_devs[]) { - struct cx231xx_fh *fh = q->priv_data; + struct cx231xx *dev = vb2_get_drv_priv(vq); + unsigned int size = mpeglinesize * mpeglines; - fh->dev->ts1.ts_packet_size = mpeglinesize; - fh->dev->ts1.ts_packet_count = mpeglines; + dev->ts1.ts_packet_size = mpeglinesize; + dev->ts1.ts_packet_count = mpeglines; - *size = fh->dev->ts1.ts_packet_size * fh->dev->ts1.ts_packet_count; - *count = mpegbufs; + if (vq->num_buffers + *nbuffers < CX231XX_MIN_BUF) + *nbuffers = CX231XX_MIN_BUF - vq->num_buffers; - return 0; -} - -static void free_buffer(struct videobuf_queue *vq, struct cx231xx_buffer *buf) -{ - struct cx231xx_fh *fh = vq->priv_data; - struct cx231xx *dev = fh->dev; - unsigned long flags = 0; + if (*nplanes) + return sizes[0] < size ? -EINVAL : 0; + *nplanes = 1; + sizes[0] = mpeglinesize * mpeglines; - BUG_ON(in_interrupt()); - - spin_lock_irqsave(&dev->video_mode.slock, flags); - if (dev->USE_ISO) { - if (dev->video_mode.isoc_ctl.buf == buf) - dev->video_mode.isoc_ctl.buf = NULL; - } else { - if (dev->video_mode.bulk_ctl.buf == buf) - dev->video_mode.bulk_ctl.buf = NULL; - } - spin_unlock_irqrestore(&dev->video_mode.slock, flags); - videobuf_waiton(vq, &buf->vb, 0, 0); - videobuf_vmalloc_free(&buf->vb); - buf->vb.state = VIDEOBUF_NEEDS_INIT; + return 0; } static void buffer_copy(struct cx231xx *dev, char *data, int len, struct urb *urb, @@ -1276,13 +1247,13 @@ static void buffer_copy(struct cx231xx *dev, char *data, int len, struct urb *ur return; buf = list_entry(dma_q->active.next, - struct cx231xx_buffer, vb.queue); + struct cx231xx_buffer, list); dev->video_mode.isoc_ctl.buf = buf; dma_q->mpeg_buffer_done = 1; } /* Fill buffer */ buf = dev->video_mode.isoc_ctl.buf; - vbuf = videobuf_to_vmalloc(&buf->vb); + vbuf = vb2_plane_vaddr(&buf->vb.vb2_buf, 0); if ((dma_q->mpeg_buffer_completed+len) < mpeglines*mpeglinesize) { @@ -1306,11 +1277,10 @@ static void buffer_copy(struct cx231xx *dev, char *data, int len, struct urb *ur memcpy(vbuf+dma_q->mpeg_buffer_completed, data, tail_data); - buf->vb.state = VIDEOBUF_DONE; - buf->vb.field_count++; - buf->vb.ts = ktime_get_ns(); - list_del(&buf->vb.queue); - wake_up(&buf->vb.done); + buf->vb.vb2_buf.timestamp = ktime_get_ns(); + buf->vb.sequence = dma_q->sequence++; + list_del(&buf->list); + vb2_buffer_done(&buf->vb.vb2_buf, VB2_BUF_STATE_DONE); dma_q->mpeg_buffer_completed = 0; if (len - tail_data > 0) { @@ -1331,17 +1301,15 @@ static void buffer_filled(char *data, int len, struct urb *urb, if (list_empty(&dma_q->active)) return; - buf = list_entry(dma_q->active.next, - struct cx231xx_buffer, vb.queue); + buf = list_entry(dma_q->active.next, struct cx231xx_buffer, list); /* Fill buffer */ - vbuf = videobuf_to_vmalloc(&buf->vb); + vbuf = vb2_plane_vaddr(&buf->vb.vb2_buf, 0); memcpy(vbuf, data, len); - buf->vb.state = VIDEOBUF_DONE; - buf->vb.field_count++; - buf->vb.ts = ktime_get_ns(); - list_del(&buf->vb.queue); - wake_up(&buf->vb.done); + buf->vb.sequence = dma_q->sequence++; + buf->vb.vb2_buf.timestamp = ktime_get_ns(); + list_del(&buf->list); + vb2_buffer_done(&buf->vb.vb2_buf, VB2_BUF_STATE_DONE); } static int cx231xx_isoc_copy(struct cx231xx *dev, struct urb *urb) @@ -1394,100 +1362,104 @@ static int cx231xx_bulk_copy(struct cx231xx *dev, struct urb *urb) return 0; } -static int bb_buf_prepare(struct videobuf_queue *q, - struct videobuf_buffer *vb, enum v4l2_field field) +static void buffer_queue(struct vb2_buffer *vb) { - struct cx231xx_fh *fh = q->priv_data; struct cx231xx_buffer *buf = - container_of(vb, struct cx231xx_buffer, vb); - struct cx231xx *dev = fh->dev; - int rc = 0, urb_init = 0; - int size = fh->dev->ts1.ts_packet_size * fh->dev->ts1.ts_packet_count; + container_of(vb, struct cx231xx_buffer, vb.vb2_buf); + struct cx231xx *dev = vb2_get_drv_priv(vb->vb2_queue); + struct cx231xx_dmaqueue *vidq = &dev->video_mode.vidq; + unsigned long flags; - if (0 != buf->vb.baddr && buf->vb.bsize < size) - return -EINVAL; - buf->vb.width = fh->dev->ts1.ts_packet_size; - buf->vb.height = fh->dev->ts1.ts_packet_count; - buf->vb.size = size; - buf->vb.field = field; - - if (VIDEOBUF_NEEDS_INIT == buf->vb.state) { - rc = videobuf_iolock(q, &buf->vb, NULL); - if (rc < 0) - goto fail; - } + spin_lock_irqsave(&dev->video_mode.slock, flags); + list_add_tail(&buf->list, &vidq->active); + spin_unlock_irqrestore(&dev->video_mode.slock, flags); +} - if (dev->USE_ISO) { - if (!dev->video_mode.isoc_ctl.num_bufs) - urb_init = 1; - } else { - if (!dev->video_mode.bulk_ctl.num_bufs) - urb_init = 1; +static void return_all_buffers(struct cx231xx *dev, + enum vb2_buffer_state state) +{ + struct cx231xx_dmaqueue *vidq = &dev->video_mode.vidq; + struct cx231xx_buffer *buf, *node; + unsigned long flags; + + spin_lock_irqsave(&dev->video_mode.slock, flags); + list_for_each_entry_safe(buf, node, &vidq->active, list) { + vb2_buffer_done(&buf->vb.vb2_buf, state); + list_del(&buf->list); } - dev_dbg(dev->dev, - "urb_init=%d dev->video_mode.max_pkt_size=%d\n", - urb_init, dev->video_mode.max_pkt_size); + spin_unlock_irqrestore(&dev->video_mode.slock, flags); +} + +static int start_streaming(struct vb2_queue *vq, unsigned int count) +{ + struct cx231xx *dev = vb2_get_drv_priv(vq); + struct cx231xx_dmaqueue *vidq = &dev->video_mode.vidq; + int ret = 0; + + vidq->sequence = 0; dev->mode_tv = 1; - if (urb_init) { - rc = cx231xx_set_mode(dev, CX231XX_DIGITAL_MODE); - rc = cx231xx_unmute_audio(dev); - if (dev->USE_ISO) { - cx231xx_set_alt_setting(dev, INDEX_TS1, 4); - rc = cx231xx_init_isoc(dev, mpeglines, - mpegbufs, - dev->ts1_mode.max_pkt_size, - cx231xx_isoc_copy); - } else { - cx231xx_set_alt_setting(dev, INDEX_TS1, 0); - rc = cx231xx_init_bulk(dev, mpeglines, - mpegbufs, - dev->ts1_mode.max_pkt_size, - cx231xx_bulk_copy); - } - if (rc < 0) - goto fail; - } + cx231xx_set_alt_setting(dev, INDEX_VANC, 1); + cx231xx_set_gpio_value(dev, 2, 0); - buf->vb.state = VIDEOBUF_PREPARED; - return 0; + cx231xx_initialize_codec(dev); + + cx231xx_start_TS1(dev); + + cx231xx_set_alt_setting(dev, INDEX_TS1, 0); + cx231xx_set_mode(dev, CX231XX_DIGITAL_MODE); + if (dev->USE_ISO) + ret = cx231xx_init_isoc(dev, CX231XX_NUM_PACKETS, + CX231XX_NUM_BUFS, + dev->ts1_mode.max_pkt_size, + cx231xx_isoc_copy); + else + ret = cx231xx_init_bulk(dev, 320, 5, + dev->ts1_mode.max_pkt_size, + cx231xx_bulk_copy); + if (ret) + return_all_buffers(dev, VB2_BUF_STATE_QUEUED); -fail: - free_buffer(q, buf); - return rc; + call_all(dev, video, s_stream, 1); + return ret; } -static void bb_buf_queue(struct videobuf_queue *q, - struct videobuf_buffer *vb) +static void stop_streaming(struct vb2_queue *vq) { - struct cx231xx_fh *fh = q->priv_data; + struct cx231xx *dev = vb2_get_drv_priv(vq); + unsigned long flags; - struct cx231xx_buffer *buf = - container_of(vb, struct cx231xx_buffer, vb); - struct cx231xx *dev = fh->dev; - struct cx231xx_dmaqueue *vidq = &dev->video_mode.vidq; + call_all(dev, video, s_stream, 0); - buf->vb.state = VIDEOBUF_QUEUED; - list_add_tail(&buf->vb.queue, &vidq->active); + cx231xx_stop_TS1(dev); -} + /* do this before setting alternate! */ + if (dev->USE_ISO) + cx231xx_uninit_isoc(dev); + else + cx231xx_uninit_bulk(dev); + cx231xx_set_mode(dev, CX231XX_SUSPEND); -static void bb_buf_release(struct videobuf_queue *q, - struct videobuf_buffer *vb) -{ - struct cx231xx_buffer *buf = - container_of(vb, struct cx231xx_buffer, vb); - /*struct cx231xx_fh *fh = q->priv_data;*/ - /*struct cx231xx *dev = (struct cx231xx *)fh->dev;*/ + cx231xx_api_cmd(dev, CX2341X_ENC_STOP_CAPTURE, 3, 0, + CX231xx_END_NOW, CX231xx_MPEG_CAPTURE, + CX231xx_RAW_BITS_NONE); - free_buffer(q, buf); + spin_lock_irqsave(&dev->video_mode.slock, flags); + if (dev->USE_ISO) + dev->video_mode.isoc_ctl.buf = NULL; + else + dev->video_mode.bulk_ctl.buf = NULL; + spin_unlock_irqrestore(&dev->video_mode.slock, flags); + return_all_buffers(dev, VB2_BUF_STATE_ERROR); } -static const struct videobuf_queue_ops cx231xx_qops = { - .buf_setup = bb_buf_setup, - .buf_prepare = bb_buf_prepare, - .buf_queue = bb_buf_queue, - .buf_release = bb_buf_release, +static struct vb2_ops cx231xx_video_qops = { + .queue_setup = queue_setup, + .buf_queue = buffer_queue, + .start_streaming = start_streaming, + .stop_streaming = stop_streaming, + .wait_prepare = vb2_ops_wait_prepare, + .wait_finish = vb2_ops_wait_finish, }; /* ------------------------------------------------------------------ */ @@ -1495,8 +1467,7 @@ static const struct videobuf_queue_ops cx231xx_qops = { static int vidioc_g_pixelaspect(struct file *file, void *priv, int type, struct v4l2_fract *f) { - struct cx231xx_fh *fh = priv; - struct cx231xx *dev = fh->dev; + struct cx231xx *dev = video_drvdata(file); bool is_50hz = dev->encodernorm.id & V4L2_STD_625_50; if (type != V4L2_BUF_TYPE_VIDEO_CAPTURE) @@ -1511,8 +1482,7 @@ static int vidioc_g_pixelaspect(struct file *file, void *priv, static int vidioc_g_selection(struct file *file, void *priv, struct v4l2_selection *s) { - struct cx231xx_fh *fh = priv; - struct cx231xx *dev = fh->dev; + struct cx231xx *dev = video_drvdata(file); if (s->type != V4L2_BUF_TYPE_VIDEO_CAPTURE) return -EINVAL; @@ -1533,8 +1503,7 @@ static int vidioc_g_selection(struct file *file, void *priv, static int vidioc_g_std(struct file *file, void *fh0, v4l2_std_id *norm) { - struct cx231xx_fh *fh = file->private_data; - struct cx231xx *dev = fh->dev; + struct cx231xx *dev = video_drvdata(file); *norm = dev->encodernorm.id; return 0; @@ -1542,8 +1511,7 @@ static int vidioc_g_std(struct file *file, void *fh0, v4l2_std_id *norm) static int vidioc_s_std(struct file *file, void *priv, v4l2_std_id id) { - struct cx231xx_fh *fh = file->private_data; - struct cx231xx *dev = fh->dev; + struct cx231xx *dev = video_drvdata(file); unsigned int i; for (i = 0; i < ARRAY_SIZE(cx231xx_tvnorms); i++) @@ -1575,8 +1543,7 @@ static int vidioc_s_std(struct file *file, void *priv, v4l2_std_id id) static int vidioc_s_ctrl(struct file *file, void *priv, struct v4l2_control *ctl) { - struct cx231xx_fh *fh = file->private_data; - struct cx231xx *dev = fh->dev; + struct cx231xx *dev = video_drvdata(file); struct v4l2_subdev *sd; dprintk(3, "enter vidioc_s_ctrl()\n"); @@ -1601,8 +1568,7 @@ static int vidioc_enum_fmt_vid_cap(struct file *file, void *priv, static int vidioc_g_fmt_vid_cap(struct file *file, void *priv, struct v4l2_format *f) { - struct cx231xx_fh *fh = file->private_data; - struct cx231xx *dev = fh->dev; + struct cx231xx *dev = video_drvdata(file); dprintk(3, "enter vidioc_g_fmt_vid_cap()\n"); f->fmt.pix.pixelformat = V4L2_PIX_FMT_MPEG; @@ -1621,8 +1587,7 @@ static int vidioc_g_fmt_vid_cap(struct file *file, void *priv, static int vidioc_try_fmt_vid_cap(struct file *file, void *priv, struct v4l2_format *f) { - struct cx231xx_fh *fh = file->private_data; - struct cx231xx *dev = fh->dev; + struct cx231xx *dev = video_drvdata(file); dprintk(3, "enter vidioc_try_fmt_vid_cap()\n"); f->fmt.pix.pixelformat = V4L2_PIX_FMT_MPEG; @@ -1636,230 +1601,21 @@ static int vidioc_try_fmt_vid_cap(struct file *file, void *priv, return 0; } -static int vidioc_reqbufs(struct file *file, void *priv, - struct v4l2_requestbuffers *p) -{ - struct cx231xx_fh *fh = file->private_data; - - return videobuf_reqbufs(&fh->vidq, p); -} - -static int vidioc_querybuf(struct file *file, void *priv, - struct v4l2_buffer *p) -{ - struct cx231xx_fh *fh = file->private_data; - - return videobuf_querybuf(&fh->vidq, p); -} - -static int vidioc_qbuf(struct file *file, void *priv, - struct v4l2_buffer *p) -{ - struct cx231xx_fh *fh = file->private_data; - - return videobuf_qbuf(&fh->vidq, p); -} - -static int vidioc_dqbuf(struct file *file, void *priv, struct v4l2_buffer *b) -{ - struct cx231xx_fh *fh = priv; - - return videobuf_dqbuf(&fh->vidq, b, file->f_flags & O_NONBLOCK); -} - - -static int vidioc_streamon(struct file *file, void *priv, - enum v4l2_buf_type i) -{ - struct cx231xx_fh *fh = file->private_data; - struct cx231xx *dev = fh->dev; - - dprintk(3, "enter vidioc_streamon()\n"); - cx231xx_set_alt_setting(dev, INDEX_TS1, 0); - cx231xx_set_mode(dev, CX231XX_DIGITAL_MODE); - if (dev->USE_ISO) - cx231xx_init_isoc(dev, CX231XX_NUM_PACKETS, - CX231XX_NUM_BUFS, - dev->video_mode.max_pkt_size, - cx231xx_isoc_copy); - else { - cx231xx_init_bulk(dev, 320, - 5, - dev->ts1_mode.max_pkt_size, - cx231xx_bulk_copy); - } - dprintk(3, "exit vidioc_streamon()\n"); - return videobuf_streamon(&fh->vidq); -} - -static int vidioc_streamoff(struct file *file, void *priv, enum v4l2_buf_type i) -{ - struct cx231xx_fh *fh = file->private_data; - - return videobuf_streamoff(&fh->vidq); -} - static int vidioc_log_status(struct file *file, void *priv) { - struct cx231xx_fh *fh = priv; - struct cx231xx *dev = fh->dev; + struct cx231xx *dev = video_drvdata(file); call_all(dev, core, log_status); return v4l2_ctrl_log_status(file, priv); } -static int mpeg_open(struct file *file) -{ - struct video_device *vdev = video_devdata(file); - struct cx231xx *dev = video_drvdata(file); - struct cx231xx_fh *fh; - - dprintk(2, "%s()\n", __func__); - - if (mutex_lock_interruptible(&dev->lock)) - return -ERESTARTSYS; - - /* allocate + initialize per filehandle data */ - fh = kzalloc(sizeof(*fh), GFP_KERNEL); - if (NULL == fh) { - mutex_unlock(&dev->lock); - return -ENOMEM; - } - - file->private_data = fh; - v4l2_fh_init(&fh->fh, vdev); - fh->dev = dev; - - - videobuf_queue_vmalloc_init(&fh->vidq, &cx231xx_qops, - NULL, &dev->video_mode.slock, - V4L2_BUF_TYPE_VIDEO_CAPTURE, V4L2_FIELD_INTERLACED, - sizeof(struct cx231xx_buffer), fh, &dev->lock); -/* - videobuf_queue_sg_init(&fh->vidq, &cx231xx_qops, - dev->dev, &dev->ts1.slock, - V4L2_BUF_TYPE_VIDEO_CAPTURE, - V4L2_FIELD_INTERLACED, - sizeof(struct cx231xx_buffer), - fh, &dev->lock); -*/ - - cx231xx_set_alt_setting(dev, INDEX_VANC, 1); - cx231xx_set_gpio_value(dev, 2, 0); - - cx231xx_initialize_codec(dev); - - mutex_unlock(&dev->lock); - v4l2_fh_add(&fh->fh); - cx231xx_start_TS1(dev); - - return 0; -} - -static int mpeg_release(struct file *file) -{ - struct cx231xx_fh *fh = file->private_data; - struct cx231xx *dev = fh->dev; - - dprintk(3, "mpeg_release()! dev=0x%p\n", dev); - - mutex_lock(&dev->lock); - - cx231xx_stop_TS1(dev); - - /* do this before setting alternate! */ - if (dev->USE_ISO) - cx231xx_uninit_isoc(dev); - else - cx231xx_uninit_bulk(dev); - cx231xx_set_mode(dev, CX231XX_SUSPEND); - - cx231xx_api_cmd(fh->dev, CX2341X_ENC_STOP_CAPTURE, 3, 0, - CX231xx_END_NOW, CX231xx_MPEG_CAPTURE, - CX231xx_RAW_BITS_NONE); - - /* FIXME: Review this crap */ - /* Shut device down on last close */ - if (atomic_cmpxchg(&fh->v4l_reading, 1, 0) == 1) { - if (atomic_dec_return(&dev->v4l_reader_count) == 0) { - /* stop mpeg capture */ - - msleep(500); - cx231xx_417_check_encoder(dev); - - } - } - - if (fh->vidq.streaming) - videobuf_streamoff(&fh->vidq); - if (fh->vidq.reading) - videobuf_read_stop(&fh->vidq); - - videobuf_mmap_free(&fh->vidq); - v4l2_fh_del(&fh->fh); - v4l2_fh_exit(&fh->fh); - kfree(fh); - mutex_unlock(&dev->lock); - return 0; -} - -static ssize_t mpeg_read(struct file *file, char __user *data, - size_t count, loff_t *ppos) -{ - struct cx231xx_fh *fh = file->private_data; - struct cx231xx *dev = fh->dev; - - /* Deal w/ A/V decoder * and mpeg encoder sync issues. */ - /* Start mpeg encoder on first read. */ - if (atomic_cmpxchg(&fh->v4l_reading, 0, 1) == 0) { - if (atomic_inc_return(&dev->v4l_reader_count) == 1) { - if (cx231xx_initialize_codec(dev) < 0) - return -EINVAL; - } - } - - return videobuf_read_stream(&fh->vidq, data, count, ppos, 0, - file->f_flags & O_NONBLOCK); -} - -static __poll_t mpeg_poll(struct file *file, - struct poll_table_struct *wait) -{ - __poll_t req_events = poll_requested_events(wait); - struct cx231xx_fh *fh = file->private_data; - struct cx231xx *dev = fh->dev; - __poll_t res = 0; - - if (v4l2_event_pending(&fh->fh)) - res |= EPOLLPRI; - else - poll_wait(file, &fh->fh.wait, wait); - - if (!(req_events & (EPOLLIN | EPOLLRDNORM))) - return res; - - mutex_lock(&dev->lock); - res |= videobuf_poll_stream(file, &fh->vidq, wait); - mutex_unlock(&dev->lock); - return res; -} - -static int mpeg_mmap(struct file *file, struct vm_area_struct *vma) -{ - struct cx231xx_fh *fh = file->private_data; - - dprintk(2, "%s()\n", __func__); - - return videobuf_mmap_mapper(&fh->vidq, vma); -} - static const struct v4l2_file_operations mpeg_fops = { .owner = THIS_MODULE, - .open = mpeg_open, - .release = mpeg_release, - .read = mpeg_read, - .poll = mpeg_poll, - .mmap = mpeg_mmap, + .open = v4l2_fh_open, + .release = vb2_fop_release, + .read = vb2_fop_read, + .poll = vb2_fop_poll, + .mmap = vb2_fop_mmap, .unlocked_ioctl = video_ioctl2, }; @@ -1881,12 +1637,12 @@ static const struct v4l2_ioctl_ops mpeg_ioctl_ops = { .vidioc_g_fmt_vid_cap = vidioc_g_fmt_vid_cap, .vidioc_try_fmt_vid_cap = vidioc_try_fmt_vid_cap, .vidioc_s_fmt_vid_cap = vidioc_try_fmt_vid_cap, - .vidioc_reqbufs = vidioc_reqbufs, - .vidioc_querybuf = vidioc_querybuf, - .vidioc_qbuf = vidioc_qbuf, - .vidioc_dqbuf = vidioc_dqbuf, - .vidioc_streamon = vidioc_streamon, - .vidioc_streamoff = vidioc_streamoff, + .vidioc_reqbufs = vb2_ioctl_reqbufs, + .vidioc_querybuf = vb2_ioctl_querybuf, + .vidioc_qbuf = vb2_ioctl_qbuf, + .vidioc_dqbuf = vb2_ioctl_dqbuf, + .vidioc_streamon = vb2_ioctl_streamon, + .vidioc_streamoff = vb2_ioctl_streamoff, .vidioc_log_status = vidioc_log_status, #ifdef CONFIG_VIDEO_ADV_DEBUG .vidioc_g_register = cx231xx_g_register, @@ -1980,6 +1736,7 @@ int cx231xx_417_register(struct cx231xx *dev) /* FIXME: Port1 hardcoded here */ int err = -ENODEV; struct cx231xx_tsport *tsport = &dev->ts1; + struct vb2_queue *q; dprintk(1, "%s()\n", __func__); @@ -2017,6 +1774,21 @@ int cx231xx_417_register(struct cx231xx *dev) /* Allocate and initialize V4L video device */ cx231xx_video_dev_init(dev, dev->udev, &dev->v4l_device, &cx231xx_mpeg_template, "mpeg"); + q = &dev->mpegq; + q->type = V4L2_BUF_TYPE_VIDEO_CAPTURE; + q->io_modes = VB2_USERPTR | VB2_MMAP | VB2_DMABUF | VB2_READ; + q->drv_priv = dev; + q->buf_struct_size = sizeof(struct cx231xx_buffer); + q->ops = &cx231xx_video_qops; + q->mem_ops = &vb2_vmalloc_memops; + q->timestamp_flags = V4L2_BUF_FLAG_TIMESTAMP_MONOTONIC; + q->min_buffers_needed = 1; + q->lock = &dev->lock; + err = vb2_queue_init(q); + if (err) + return err; + dev->v4l_device.queue = q; + err = video_register_device(&dev->v4l_device, VFL_TYPE_GRABBER, -1); if (err < 0) { diff --git a/drivers/media/usb/cx231xx/cx231xx-audio.c b/drivers/media/usb/cx231xx/cx231xx-audio.c index 9ef362e221df..fd6e2df3d1b7 100644 --- a/drivers/media/usb/cx231xx/cx231xx-audio.c +++ b/drivers/media/usb/cx231xx/cx231xx-audio.c @@ -14,7 +14,6 @@ #include <linux/soundcard.h> #include <linux/slab.h> #include <linux/vmalloc.h> -#include <linux/proc_fs.h> #include <linux/module.h> #include <sound/core.h> #include <sound/pcm.h> diff --git a/drivers/media/usb/cx231xx/cx231xx-avcore.c b/drivers/media/usb/cx231xx/cx231xx-avcore.c index d417b5fe4093..0974965e848f 100644 --- a/drivers/media/usb/cx231xx/cx231xx-avcore.c +++ b/drivers/media/usb/cx231xx/cx231xx-avcore.c @@ -1240,7 +1240,7 @@ int cx231xx_init_ctrl_pin_status(struct cx231xx *dev) int cx231xx_set_agc_analog_digital_mux_select(struct cx231xx *dev, u8 analog_or_digital) { - int status = 0; + int status; /* first set the direction to output */ status = cx231xx_set_gpio_direction(dev, diff --git a/drivers/media/usb/cx231xx/cx231xx-cards.c b/drivers/media/usb/cx231xx/cx231xx-cards.c index e123e74c549e..92efe6c1f47b 100644 --- a/drivers/media/usb/cx231xx/cx231xx-cards.c +++ b/drivers/media/usb/cx231xx/cx231xx-cards.c @@ -1479,13 +1479,11 @@ static int cx231xx_init_dev(struct cx231xx *dev, struct usb_device *udev, goto err_dev_init; } - /* init video dma queues */ + /* init video dma queue */ INIT_LIST_HEAD(&dev->video_mode.vidq.active); - INIT_LIST_HEAD(&dev->video_mode.vidq.queued); - /* init vbi dma queues */ + /* init vbi dma queue */ INIT_LIST_HEAD(&dev->vbi_mode.vidq.active); - INIT_LIST_HEAD(&dev->vbi_mode.vidq.queued); /* Reset other chips required if they are tied up with GPIO pins */ cx231xx_add_into_devlist(dev); diff --git a/drivers/media/usb/cx231xx/cx231xx-vbi.c b/drivers/media/usb/cx231xx/cx231xx-vbi.c index fba7ccdf5a25..d2f143a096d1 100644 --- a/drivers/media/usb/cx231xx/cx231xx-vbi.c +++ b/drivers/media/usb/cx231xx/cx231xx-vbi.c @@ -153,131 +153,98 @@ static inline int cx231xx_isoc_vbi_copy(struct cx231xx *dev, struct urb *urb) Vbi buf operations ------------------------------------------------------------------*/ -static int -vbi_buffer_setup(struct videobuf_queue *vq, unsigned int *count, - unsigned int *size) +static int vbi_queue_setup(struct vb2_queue *vq, + unsigned int *nbuffers, unsigned int *nplanes, + unsigned int sizes[], struct device *alloc_devs[]) { - struct cx231xx_fh *fh = vq->priv_data; - struct cx231xx *dev = fh->dev; + struct cx231xx *dev = vb2_get_drv_priv(vq); u32 height = 0; height = ((dev->norm & V4L2_STD_625_50) ? PAL_VBI_LINES : NTSC_VBI_LINES); - *size = (dev->width * height * 2 * 2); - if (0 == *count) - *count = CX231XX_DEF_VBI_BUF; - - if (*count < CX231XX_MIN_BUF) - *count = CX231XX_MIN_BUF; - + *nplanes = 1; + sizes[0] = (dev->width * height * 2 * 2); return 0; } /* This is called *without* dev->slock held; please keep it that way */ -static void free_buffer(struct videobuf_queue *vq, struct cx231xx_buffer *buf) -{ - struct cx231xx_fh *fh = vq->priv_data; - struct cx231xx *dev = fh->dev; - unsigned long flags = 0; - BUG_ON(in_interrupt()); - - /* We used to wait for the buffer to finish here, but this didn't work - because, as we were keeping the state as VIDEOBUF_QUEUED, - videobuf_queue_cancel marked it as finished for us. - (Also, it could wedge forever if the hardware was misconfigured.) - - This should be safe; by the time we get here, the buffer isn't - queued anymore. If we ever start marking the buffers as - VIDEOBUF_ACTIVE, it won't be, though. - */ - spin_lock_irqsave(&dev->vbi_mode.slock, flags); - if (dev->vbi_mode.bulk_ctl.buf == buf) - dev->vbi_mode.bulk_ctl.buf = NULL; - spin_unlock_irqrestore(&dev->vbi_mode.slock, flags); - - videobuf_vmalloc_free(&buf->vb); - buf->vb.state = VIDEOBUF_NEEDS_INIT; -} - -static int -vbi_buffer_prepare(struct videobuf_queue *vq, struct videobuf_buffer *vb, - enum v4l2_field field) +static int vbi_buf_prepare(struct vb2_buffer *vb) { - struct cx231xx_fh *fh = vq->priv_data; - struct cx231xx_buffer *buf = - container_of(vb, struct cx231xx_buffer, vb); - struct cx231xx *dev = fh->dev; - int rc = 0, urb_init = 0; + struct cx231xx *dev = vb2_get_drv_priv(vb->vb2_queue); u32 height = 0; + u32 size; height = ((dev->norm & V4L2_STD_625_50) ? PAL_VBI_LINES : NTSC_VBI_LINES); - buf->vb.size = ((dev->width << 1) * height * 2); + size = ((dev->width << 1) * height * 2); - if (0 != buf->vb.baddr && buf->vb.bsize < buf->vb.size) + if (vb2_plane_size(vb, 0) < size) return -EINVAL; - - buf->vb.width = dev->width; - buf->vb.height = height; - buf->vb.field = field; - buf->vb.field = V4L2_FIELD_SEQ_TB; - - if (VIDEOBUF_NEEDS_INIT == buf->vb.state) { - rc = videobuf_iolock(vq, &buf->vb, NULL); - if (rc < 0) - goto fail; - } - - if (!dev->vbi_mode.bulk_ctl.num_bufs) - urb_init = 1; - - if (urb_init) { - rc = cx231xx_init_vbi_isoc(dev, CX231XX_NUM_VBI_PACKETS, - CX231XX_NUM_VBI_BUFS, - dev->vbi_mode.alt_max_pkt_size[0], - cx231xx_isoc_vbi_copy); - if (rc < 0) - goto fail; - } - - buf->vb.state = VIDEOBUF_PREPARED; + vb2_set_plane_payload(vb, 0, size); return 0; - -fail: - free_buffer(vq, buf); - return rc; } -static void -vbi_buffer_queue(struct videobuf_queue *vq, struct videobuf_buffer *vb) +static void vbi_buf_queue(struct vb2_buffer *vb) { + struct cx231xx *dev = vb2_get_drv_priv(vb->vb2_queue); struct cx231xx_buffer *buf = - container_of(vb, struct cx231xx_buffer, vb); - struct cx231xx_fh *fh = vq->priv_data; - struct cx231xx *dev = fh->dev; + container_of(vb, struct cx231xx_buffer, vb.vb2_buf); struct cx231xx_dmaqueue *vidq = &dev->vbi_mode.vidq; + unsigned long flags; - buf->vb.state = VIDEOBUF_QUEUED; - list_add_tail(&buf->vb.queue, &vidq->active); + spin_lock_irqsave(&dev->vbi_mode.slock, flags); + list_add_tail(&buf->list, &vidq->active); + spin_unlock_irqrestore(&dev->vbi_mode.slock, flags); +} + +static void return_all_buffers(struct cx231xx *dev, + enum vb2_buffer_state state) +{ + struct cx231xx_dmaqueue *vidq = &dev->vbi_mode.vidq; + struct cx231xx_buffer *buf, *node; + unsigned long flags; + spin_lock_irqsave(&dev->vbi_mode.slock, flags); + dev->vbi_mode.bulk_ctl.buf = NULL; + list_for_each_entry_safe(buf, node, &vidq->active, list) { + list_del(&buf->list); + vb2_buffer_done(&buf->vb.vb2_buf, state); + } + spin_unlock_irqrestore(&dev->vbi_mode.slock, flags); } -static void vbi_buffer_release(struct videobuf_queue *vq, - struct videobuf_buffer *vb) +static int vbi_start_streaming(struct vb2_queue *vq, unsigned int count) { - struct cx231xx_buffer *buf = - container_of(vb, struct cx231xx_buffer, vb); + struct cx231xx *dev = vb2_get_drv_priv(vq); + struct cx231xx_dmaqueue *vidq = &dev->vbi_mode.vidq; + int ret; + + vidq->sequence = 0; + ret = cx231xx_init_vbi_isoc(dev, CX231XX_NUM_VBI_PACKETS, + CX231XX_NUM_VBI_BUFS, + dev->vbi_mode.alt_max_pkt_size[0], + cx231xx_isoc_vbi_copy); + if (ret) + return_all_buffers(dev, VB2_BUF_STATE_QUEUED); + return ret; +} +static void vbi_stop_streaming(struct vb2_queue *vq) +{ + struct cx231xx *dev = vb2_get_drv_priv(vq); - free_buffer(vq, buf); + return_all_buffers(dev, VB2_BUF_STATE_ERROR); } -const struct videobuf_queue_ops cx231xx_vbi_qops = { - .buf_setup = vbi_buffer_setup, - .buf_prepare = vbi_buffer_prepare, - .buf_queue = vbi_buffer_queue, - .buf_release = vbi_buffer_release, +struct vb2_ops cx231xx_vbi_qops = { + .queue_setup = vbi_queue_setup, + .buf_prepare = vbi_buf_prepare, + .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, }; /* ------------------------------------------------------------------ @@ -512,16 +479,15 @@ static inline void vbi_buffer_filled(struct cx231xx *dev, struct cx231xx_buffer *buf) { /* Advice that buffer was filled */ - /* dev_dbg(dev->dev, "[%p/%d] wakeup\n", buf, buf->vb.i); */ + /* dev_dbg(dev->dev, "[%p/%d] wakeup\n", buf, buf->vb.index); */ - buf->vb.state = VIDEOBUF_DONE; - buf->vb.field_count++; - buf->vb.ts = ktime_get_ns(); + buf->vb.sequence = dma_q->sequence++; + buf->vb.vb2_buf.timestamp = ktime_get_ns(); dev->vbi_mode.bulk_ctl.buf = NULL; - list_del(&buf->vb.queue); - wake_up(&buf->vb.done); + list_del(&buf->list); + vb2_buffer_done(&buf->vb.vb2_buf, VB2_BUF_STATE_DONE); } u32 cx231xx_copy_vbi_line(struct cx231xx *dev, struct cx231xx_dmaqueue *dma_q, @@ -611,11 +577,11 @@ static inline void get_next_vbi_buf(struct cx231xx_dmaqueue *dma_q, } /* Get the next buffer */ - *buf = list_entry(dma_q->active.next, struct cx231xx_buffer, vb.queue); + *buf = list_entry(dma_q->active.next, struct cx231xx_buffer, list); /* Cleans up buffer - Useful for testing for frame/URB loss */ - outp = videobuf_to_vmalloc(&(*buf)->vb); - memset(outp, 0, (*buf)->vb.size); + outp = vb2_plane_vaddr(&(*buf)->vb.vb2_buf, 0); + memset(outp, 0, vb2_plane_size(&(*buf)->vb.vb2_buf, 0)); dev->vbi_mode.bulk_ctl.buf = *buf; @@ -656,7 +622,7 @@ int cx231xx_do_vbi_copy(struct cx231xx *dev, struct cx231xx_dmaqueue *dma_q, if (buf == NULL) return -EINVAL; - p_out_buffer = videobuf_to_vmalloc(&buf->vb); + p_out_buffer = vb2_plane_vaddr(&buf->vb.vb2_buf, 0); if (dma_q->bytes_left_in_line != _line_size) { current_line_bytes_copied = diff --git a/drivers/media/usb/cx231xx/cx231xx-vbi.h b/drivers/media/usb/cx231xx/cx231xx-vbi.h index 7cddd629fbfc..0b21bee5fa30 100644 --- a/drivers/media/usb/cx231xx/cx231xx-vbi.h +++ b/drivers/media/usb/cx231xx/cx231xx-vbi.h @@ -10,7 +10,7 @@ #ifndef _CX231XX_VBI_H #define _CX231XX_VBI_H -extern const struct videobuf_queue_ops cx231xx_vbi_qops; +extern struct vb2_ops cx231xx_vbi_qops; #define NTSC_VBI_START_LINE 10 /* line 10 - 21 */ #define NTSC_VBI_END_LINE 21 diff --git a/drivers/media/usb/cx231xx/cx231xx-video.c b/drivers/media/usb/cx231xx/cx231xx-video.c index 9b51f07a729e..69abafaebbf3 100644 --- a/drivers/media/usb/cx231xx/cx231xx-video.c +++ b/drivers/media/usb/cx231xx/cx231xx-video.c @@ -58,10 +58,10 @@ MODULE_DESCRIPTION(DRIVER_DESC); MODULE_LICENSE("GPL"); MODULE_VERSION(CX231XX_VERSION); -static unsigned int card[] = {[0 ... (CX231XX_MAXBOARDS - 1)] = UNSET }; -static unsigned int video_nr[] = {[0 ... (CX231XX_MAXBOARDS - 1)] = UNSET }; -static unsigned int vbi_nr[] = {[0 ... (CX231XX_MAXBOARDS - 1)] = UNSET }; -static unsigned int radio_nr[] = {[0 ... (CX231XX_MAXBOARDS - 1)] = UNSET }; +static unsigned int card[] = {[0 ... (CX231XX_MAXBOARDS - 1)] = -1U }; +static unsigned int video_nr[] = {[0 ... (CX231XX_MAXBOARDS - 1)] = -1U }; +static unsigned int vbi_nr[] = {[0 ... (CX231XX_MAXBOARDS - 1)] = -1U }; +static unsigned int radio_nr[] = {[0 ... (CX231XX_MAXBOARDS - 1)] = -1U }; module_param_array(card, int, NULL, 0444); module_param_array(video_nr, int, NULL, 0444); @@ -166,18 +166,19 @@ static inline void buffer_filled(struct cx231xx *dev, struct cx231xx_buffer *buf) { /* Advice that buffer was filled */ - cx231xx_isocdbg("[%p/%d] wakeup\n", buf, buf->vb.i); - buf->vb.state = VIDEOBUF_DONE; - buf->vb.field_count++; - buf->vb.ts = ktime_get_ns(); + cx231xx_isocdbg("[%p/%d] wakeup\n", buf, buf->vb.vb2_buf.index); + buf->vb.sequence = dma_q->sequence++; + buf->vb.field = V4L2_FIELD_INTERLACED; + buf->vb.vb2_buf.timestamp = ktime_get_ns(); + vb2_set_plane_payload(&buf->vb.vb2_buf, 0, dev->size); if (dev->USE_ISO) dev->video_mode.isoc_ctl.buf = NULL; else dev->video_mode.bulk_ctl.buf = NULL; - list_del(&buf->vb.queue); - wake_up(&buf->vb.done); + list_del(&buf->list); + vb2_buffer_done(&buf->vb.vb2_buf, VB2_BUF_STATE_DONE); } static inline void print_err_status(struct cx231xx *dev, int packet, int status) @@ -241,11 +242,11 @@ static inline void get_next_buf(struct cx231xx_dmaqueue *dma_q, } /* Get the next buffer */ - *buf = list_entry(dma_q->active.next, struct cx231xx_buffer, vb.queue); + *buf = list_entry(dma_q->active.next, struct cx231xx_buffer, list); /* Cleans up buffer - Useful for testing for frame/URB loss */ - outp = videobuf_to_vmalloc(&(*buf)->vb); - memset(outp, 0, (*buf)->vb.size); + outp = vb2_plane_vaddr(&(*buf)->vb.vb2_buf, 0); + memset(outp, 0, dev->size); if (dev->USE_ISO) dev->video_mode.isoc_ctl.buf = *buf; @@ -653,7 +654,7 @@ int cx231xx_do_copy(struct cx231xx *dev, struct cx231xx_dmaqueue *dma_q, if (buf == NULL) return -1; - p_out_buffer = videobuf_to_vmalloc(&buf->vb); + p_out_buffer = vb2_plane_vaddr(&buf->vb.vb2_buf, 0); current_line_bytes_copied = _line_size - dma_q->bytes_left_in_line; @@ -672,7 +673,7 @@ int cx231xx_do_copy(struct cx231xx *dev, struct cx231xx_dmaqueue *dma_q, lencopy = dma_q->bytes_left_in_line > bytes_to_copy ? bytes_to_copy : dma_q->bytes_left_in_line; - if ((u8 *)(startwrite + lencopy) > (u8 *)(p_out_buffer + buf->vb.size)) + if ((u8 *)(startwrite + lencopy) > (u8 *)(p_out_buffer + dev->size)) return 0; /* The below copies the UYVY data straight into video buffer */ @@ -708,149 +709,98 @@ u8 cx231xx_is_buffer_done(struct cx231xx *dev, struct cx231xx_dmaqueue *dma_q) Videobuf operations ------------------------------------------------------------------*/ -static int -buffer_setup(struct videobuf_queue *vq, unsigned int *count, unsigned int *size) +static int queue_setup(struct vb2_queue *vq, + unsigned int *nbuffers, unsigned int *nplanes, + unsigned int sizes[], struct device *alloc_devs[]) { - struct cx231xx_fh *fh = vq->priv_data; - struct cx231xx *dev = fh->dev; + struct cx231xx *dev = vb2_get_drv_priv(vq); - *size = (fh->dev->width * fh->dev->height * dev->format->depth + 7)>>3; - if (0 == *count) - *count = CX231XX_DEF_BUF; + dev->size = (dev->width * dev->height * dev->format->depth + 7) >> 3; - if (*count < CX231XX_MIN_BUF) - *count = CX231XX_MIN_BUF; + if (vq->num_buffers + *nbuffers < CX231XX_MIN_BUF) + *nbuffers = CX231XX_MIN_BUF - vq->num_buffers; - - cx231xx_enable_analog_tuner(dev); + if (*nplanes) + return sizes[0] < dev->size ? -EINVAL : 0; + *nplanes = 1; + sizes[0] = dev->size; return 0; } -/* This is called *without* dev->slock held; please keep it that way */ -static void free_buffer(struct videobuf_queue *vq, struct cx231xx_buffer *buf) +static void buffer_queue(struct vb2_buffer *vb) { - struct cx231xx_fh *fh = vq->priv_data; - struct cx231xx *dev = fh->dev; - unsigned long flags = 0; - - BUG_ON(in_interrupt()); - - /* We used to wait for the buffer to finish here, but this didn't work - because, as we were keeping the state as VIDEOBUF_QUEUED, - videobuf_queue_cancel marked it as finished for us. - (Also, it could wedge forever if the hardware was misconfigured.) + struct cx231xx_buffer *buf = + container_of(vb, struct cx231xx_buffer, vb.vb2_buf); + struct cx231xx *dev = vb2_get_drv_priv(vb->vb2_queue); + struct cx231xx_dmaqueue *vidq = &dev->video_mode.vidq; + unsigned long flags; - This should be safe; by the time we get here, the buffer isn't - queued anymore. If we ever start marking the buffers as - VIDEOBUF_ACTIVE, it won't be, though. - */ spin_lock_irqsave(&dev->video_mode.slock, flags); - if (dev->USE_ISO) { - if (dev->video_mode.isoc_ctl.buf == buf) - dev->video_mode.isoc_ctl.buf = NULL; - } else { - if (dev->video_mode.bulk_ctl.buf == buf) - dev->video_mode.bulk_ctl.buf = NULL; - } + list_add_tail(&buf->list, &vidq->active); spin_unlock_irqrestore(&dev->video_mode.slock, flags); - - videobuf_vmalloc_free(&buf->vb); - buf->vb.state = VIDEOBUF_NEEDS_INIT; } -static int -buffer_prepare(struct videobuf_queue *vq, struct videobuf_buffer *vb, - enum v4l2_field field) +static void return_all_buffers(struct cx231xx *dev, + enum vb2_buffer_state state) { - struct cx231xx_fh *fh = vq->priv_data; - struct cx231xx_buffer *buf = - container_of(vb, struct cx231xx_buffer, vb); - struct cx231xx *dev = fh->dev; - int rc = 0, urb_init = 0; - - /* The only currently supported format is 16 bits/pixel */ - buf->vb.size = (fh->dev->width * fh->dev->height * dev->format->depth - + 7) >> 3; - if (0 != buf->vb.baddr && buf->vb.bsize < buf->vb.size) - return -EINVAL; - - buf->vb.width = dev->width; - buf->vb.height = dev->height; - buf->vb.field = field; - - if (VIDEOBUF_NEEDS_INIT == buf->vb.state) { - rc = videobuf_iolock(vq, &buf->vb, NULL); - if (rc < 0) - goto fail; - } + struct cx231xx_dmaqueue *vidq = &dev->video_mode.vidq; + struct cx231xx_buffer *buf, *node; + unsigned long flags; - if (dev->USE_ISO) { - if (!dev->video_mode.isoc_ctl.num_bufs) - urb_init = 1; - } else { - if (!dev->video_mode.bulk_ctl.num_bufs) - urb_init = 1; - } - dev_dbg(dev->dev, - "urb_init=%d dev->video_mode.max_pkt_size=%d\n", - urb_init, dev->video_mode.max_pkt_size); - if (urb_init) { - dev->mode_tv = 0; - if (dev->USE_ISO) - rc = cx231xx_init_isoc(dev, CX231XX_NUM_PACKETS, - CX231XX_NUM_BUFS, - dev->video_mode.max_pkt_size, - cx231xx_isoc_copy); - else - rc = cx231xx_init_bulk(dev, CX231XX_NUM_PACKETS, - CX231XX_NUM_BUFS, - dev->video_mode.max_pkt_size, - cx231xx_bulk_copy); - if (rc < 0) - goto fail; + spin_lock_irqsave(&dev->video_mode.slock, flags); + if (dev->USE_ISO) + dev->video_mode.isoc_ctl.buf = NULL; + else + dev->video_mode.bulk_ctl.buf = NULL; + list_for_each_entry_safe(buf, node, &vidq->active, list) { + list_del(&buf->list); + vb2_buffer_done(&buf->vb.vb2_buf, state); } - - buf->vb.state = VIDEOBUF_PREPARED; - - return 0; - -fail: - free_buffer(vq, buf); - return rc; + spin_unlock_irqrestore(&dev->video_mode.slock, flags); } -static void buffer_queue(struct videobuf_queue *vq, struct videobuf_buffer *vb) +static int start_streaming(struct vb2_queue *vq, unsigned int count) { - struct cx231xx_buffer *buf = - container_of(vb, struct cx231xx_buffer, vb); - struct cx231xx_fh *fh = vq->priv_data; - struct cx231xx *dev = fh->dev; + struct cx231xx *dev = vb2_get_drv_priv(vq); struct cx231xx_dmaqueue *vidq = &dev->video_mode.vidq; + int ret = 0; - buf->vb.state = VIDEOBUF_QUEUED; - list_add_tail(&buf->vb.queue, &vidq->active); + vidq->sequence = 0; + dev->mode_tv = 0; + cx231xx_enable_analog_tuner(dev); + if (dev->USE_ISO) + ret = cx231xx_init_isoc(dev, CX231XX_NUM_PACKETS, + CX231XX_NUM_BUFS, + dev->video_mode.max_pkt_size, + cx231xx_isoc_copy); + else + ret = cx231xx_init_bulk(dev, CX231XX_NUM_PACKETS, + CX231XX_NUM_BUFS, + dev->video_mode.max_pkt_size, + cx231xx_bulk_copy); + if (ret) + return_all_buffers(dev, VB2_BUF_STATE_QUEUED); + call_all(dev, video, s_stream, 1); + return ret; } -static void buffer_release(struct videobuf_queue *vq, - struct videobuf_buffer *vb) +static void stop_streaming(struct vb2_queue *vq) { - struct cx231xx_buffer *buf = - container_of(vb, struct cx231xx_buffer, vb); - struct cx231xx_fh *fh = vq->priv_data; - struct cx231xx *dev = (struct cx231xx *)fh->dev; - - cx231xx_isocdbg("cx231xx: called buffer_release\n"); + struct cx231xx *dev = vb2_get_drv_priv(vq); - free_buffer(vq, buf); + call_all(dev, video, s_stream, 0); + return_all_buffers(dev, VB2_BUF_STATE_ERROR); } -static const struct videobuf_queue_ops cx231xx_video_qops = { - .buf_setup = buffer_setup, - .buf_prepare = buffer_prepare, - .buf_queue = buffer_queue, - .buf_release = buffer_release, +static struct vb2_ops cx231xx_video_qops = { + .queue_setup = queue_setup, + .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 **************************************/ @@ -872,58 +822,6 @@ void video_mux(struct cx231xx *dev, int index) cx231xx_do_mode_ctrl_overrides(dev); } -/* Usage lock check functions */ -static int res_get(struct cx231xx_fh *fh) -{ - struct cx231xx *dev = fh->dev; - int rc = 0; - - /* This instance already has stream_on */ - if (fh->stream_on) - return rc; - - if (fh->type == V4L2_BUF_TYPE_VIDEO_CAPTURE) { - if (dev->stream_on) - return -EBUSY; - dev->stream_on = 1; - } else if (fh->type == V4L2_BUF_TYPE_VBI_CAPTURE) { - if (dev->vbi_stream_on) - return -EBUSY; - dev->vbi_stream_on = 1; - } else - return -EINVAL; - - fh->stream_on = 1; - - return rc; -} - -static int res_check(struct cx231xx_fh *fh) -{ - return fh->stream_on; -} - -static void res_free(struct cx231xx_fh *fh) -{ - struct cx231xx *dev = fh->dev; - - fh->stream_on = 0; - - if (fh->type == V4L2_BUF_TYPE_VIDEO_CAPTURE) - dev->stream_on = 0; - if (fh->type == V4L2_BUF_TYPE_VBI_CAPTURE) - dev->vbi_stream_on = 0; -} - -static int check_dev(struct cx231xx *dev) -{ - if (dev->state & DEV_DISCONNECTED) { - dev_err(dev->dev, "v4l2 ioctl: device not present\n"); - return -ENODEV; - } - return 0; -} - /* ------------------------------------------------------------------ IOCTL vidioc handling ------------------------------------------------------------------*/ @@ -931,8 +829,7 @@ static int check_dev(struct cx231xx *dev) static int vidioc_g_fmt_vid_cap(struct file *file, void *priv, struct v4l2_format *f) { - struct cx231xx_fh *fh = priv; - struct cx231xx *dev = fh->dev; + struct cx231xx *dev = video_drvdata(file); f->fmt.pix.width = dev->width; f->fmt.pix.height = dev->height; @@ -960,8 +857,7 @@ static struct cx231xx_fmt *format_by_fourcc(unsigned int fourcc) static int vidioc_try_fmt_vid_cap(struct file *file, void *priv, struct v4l2_format *f) { - struct cx231xx_fh *fh = priv; - struct cx231xx *dev = fh->dev; + struct cx231xx *dev = video_drvdata(file); unsigned int width = f->fmt.pix.width; unsigned int height = f->fmt.pix.height; unsigned int maxw = norm_maxw(dev); @@ -993,39 +889,25 @@ static int vidioc_try_fmt_vid_cap(struct file *file, void *priv, static int vidioc_s_fmt_vid_cap(struct file *file, void *priv, struct v4l2_format *f) { - struct cx231xx_fh *fh = priv; - struct cx231xx *dev = fh->dev; - int rc; - struct cx231xx_fmt *fmt; + struct cx231xx *dev = video_drvdata(file); struct v4l2_subdev_format format = { .which = V4L2_SUBDEV_FORMAT_ACTIVE, }; + int rc; - rc = check_dev(dev); - if (rc < 0) + rc = vidioc_try_fmt_vid_cap(file, priv, f); + if (rc) return rc; - vidioc_try_fmt_vid_cap(file, priv, f); - - fmt = format_by_fourcc(f->fmt.pix.pixelformat); - if (!fmt) - return -EINVAL; - - if (videobuf_queue_is_busy(&fh->vb_vidq)) { + if (vb2_is_busy(&dev->vidq)) { dev_err(dev->dev, "%s: queue busy\n", __func__); return -EBUSY; } - if (dev->stream_on && !fh->stream_on) { - dev_err(dev->dev, - "%s: device in use by another fh\n", __func__); - return -EBUSY; - } - /* set new image size */ dev->width = f->fmt.pix.width; dev->height = f->fmt.pix.height; - dev->format = fmt; + dev->format = format_by_fourcc(f->fmt.pix.pixelformat); v4l2_fill_mbus_format(&format.format, &f->fmt.pix, MEDIA_BUS_FMT_FIXED); call_all(dev, pad, set_fmt, NULL, &format); @@ -1036,8 +918,7 @@ static int vidioc_s_fmt_vid_cap(struct file *file, void *priv, static int vidioc_g_std(struct file *file, void *priv, v4l2_std_id *id) { - struct cx231xx_fh *fh = priv; - struct cx231xx *dev = fh->dev; + struct cx231xx *dev = video_drvdata(file); *id = dev->norm; return 0; @@ -1045,21 +926,15 @@ static int vidioc_g_std(struct file *file, void *priv, v4l2_std_id *id) static int vidioc_s_std(struct file *file, void *priv, v4l2_std_id norm) { - struct cx231xx_fh *fh = priv; - struct cx231xx *dev = fh->dev; + struct cx231xx *dev = video_drvdata(file); struct v4l2_subdev_format format = { .which = V4L2_SUBDEV_FORMAT_ACTIVE, }; - int rc; - - rc = check_dev(dev); - if (rc < 0) - return rc; if (dev->norm == norm) return 0; - if (videobuf_queue_is_busy(&fh->vb_vidq)) + if (vb2_is_busy(&dev->vidq)) return -EBUSY; dev->norm = norm; @@ -1141,8 +1016,7 @@ void cx231xx_v4l2_create_entities(struct cx231xx *dev) int cx231xx_enum_input(struct file *file, void *priv, struct v4l2_input *i) { - struct cx231xx_fh *fh = priv; - struct cx231xx *dev = fh->dev; + struct cx231xx *dev = video_drvdata(file); u32 gen_stat; unsigned int n; int ret; @@ -1181,8 +1055,7 @@ int cx231xx_enum_input(struct file *file, void *priv, int cx231xx_g_input(struct file *file, void *priv, unsigned int *i) { - struct cx231xx_fh *fh = priv; - struct cx231xx *dev = fh->dev; + struct cx231xx *dev = video_drvdata(file); *i = dev->video_input; @@ -1191,14 +1064,9 @@ int cx231xx_g_input(struct file *file, void *priv, unsigned int *i) int cx231xx_s_input(struct file *file, void *priv, unsigned int i) { - struct cx231xx_fh *fh = priv; - struct cx231xx *dev = fh->dev; - int rc; + struct cx231xx *dev = video_drvdata(file); dev->mode_tv = 0; - rc = check_dev(dev); - if (rc < 0) - return rc; if (i >= MAX_CX231XX_INPUT) return -EINVAL; @@ -1220,13 +1088,7 @@ int cx231xx_s_input(struct file *file, void *priv, unsigned int i) int cx231xx_g_tuner(struct file *file, void *priv, struct v4l2_tuner *t) { - struct cx231xx_fh *fh = priv; - struct cx231xx *dev = fh->dev; - int rc; - - rc = check_dev(dev); - if (rc < 0) - return rc; + struct cx231xx *dev = video_drvdata(file); if (0 != t->index) return -EINVAL; @@ -1244,27 +1106,15 @@ int cx231xx_g_tuner(struct file *file, void *priv, struct v4l2_tuner *t) int cx231xx_s_tuner(struct file *file, void *priv, const struct v4l2_tuner *t) { - struct cx231xx_fh *fh = priv; - struct cx231xx *dev = fh->dev; - int rc; - - rc = check_dev(dev); - if (rc < 0) - return rc; - if (0 != t->index) return -EINVAL; -#if 0 - call_all(dev, tuner, s_tuner, t); -#endif return 0; } int cx231xx_g_frequency(struct file *file, void *priv, struct v4l2_frequency *f) { - struct cx231xx_fh *fh = priv; - struct cx231xx *dev = fh->dev; + struct cx231xx *dev = video_drvdata(file); if (f->tuner) return -EINVAL; @@ -1277,8 +1127,7 @@ int cx231xx_g_frequency(struct file *file, void *priv, int cx231xx_s_frequency(struct file *file, void *priv, const struct v4l2_frequency *f) { - struct cx231xx_fh *fh = priv; - struct cx231xx *dev = fh->dev; + struct cx231xx *dev = video_drvdata(file); struct v4l2_frequency new_freq = *f; int rc; u32 if_frequency = 5400000; @@ -1287,10 +1136,6 @@ int cx231xx_s_frequency(struct file *file, void *priv, "Enter vidioc_s_frequency()f->frequency=%d;f->type=%d\n", f->frequency, f->type); - rc = check_dev(dev); - if (rc < 0) - return rc; - if (0 != f->tuner) return -EINVAL; @@ -1365,8 +1210,7 @@ int cx231xx_g_chip_info(struct file *file, void *fh, int cx231xx_g_register(struct file *file, void *priv, struct v4l2_dbg_register *reg) { - struct cx231xx_fh *fh = priv; - struct cx231xx *dev = fh->dev; + struct cx231xx *dev = video_drvdata(file); int ret; u8 value[4] = { 0, 0, 0, 0 }; u32 data = 0; @@ -1424,8 +1268,7 @@ int cx231xx_g_register(struct file *file, void *priv, int cx231xx_s_register(struct file *file, void *priv, const struct v4l2_dbg_register *reg) { - struct cx231xx_fh *fh = priv; - struct cx231xx *dev = fh->dev; + struct cx231xx *dev = video_drvdata(file); int ret; u8 data[4] = { 0, 0, 0, 0 }; @@ -1472,8 +1315,7 @@ int cx231xx_s_register(struct file *file, void *priv, static int vidioc_g_pixelaspect(struct file *file, void *priv, int type, struct v4l2_fract *f) { - struct cx231xx_fh *fh = priv; - struct cx231xx *dev = fh->dev; + struct cx231xx *dev = video_drvdata(file); bool is_50hz = dev->norm & V4L2_STD_625_50; if (type != V4L2_BUF_TYPE_VIDEO_CAPTURE) @@ -1488,8 +1330,7 @@ static int vidioc_g_pixelaspect(struct file *file, void *priv, static int vidioc_g_selection(struct file *file, void *priv, struct v4l2_selection *s) { - struct cx231xx_fh *fh = priv; - struct cx231xx *dev = fh->dev; + struct cx231xx *dev = video_drvdata(file); if (s->type != V4L2_BUF_TYPE_VIDEO_CAPTURE) return -EINVAL; @@ -1508,54 +1349,10 @@ static int vidioc_g_selection(struct file *file, void *priv, return 0; } -static int vidioc_streamon(struct file *file, void *priv, - enum v4l2_buf_type type) -{ - struct cx231xx_fh *fh = priv; - struct cx231xx *dev = fh->dev; - int rc; - - rc = check_dev(dev); - if (rc < 0) - return rc; - - rc = res_get(fh); - - if (likely(rc >= 0)) - rc = videobuf_streamon(&fh->vb_vidq); - - call_all(dev, video, s_stream, 1); - - return rc; -} - -static int vidioc_streamoff(struct file *file, void *priv, - enum v4l2_buf_type type) -{ - struct cx231xx_fh *fh = priv; - struct cx231xx *dev = fh->dev; - int rc; - - rc = check_dev(dev); - if (rc < 0) - return rc; - - if (type != fh->type) - return -EINVAL; - - cx25840_call(dev, video, s_stream, 0); - - videobuf_streamoff(&fh->vb_vidq); - res_free(fh); - - return 0; -} - int cx231xx_querycap(struct file *file, void *priv, struct v4l2_capability *cap) { - struct cx231xx_fh *fh = priv; - struct cx231xx *dev = fh->dev; + struct cx231xx *dev = video_drvdata(file); strscpy(cap->driver, "cx231xx", sizeof(cap->driver)); strscpy(cap->card, cx231xx_boards[dev->model].name, sizeof(cap->card)); @@ -1587,8 +1384,7 @@ static int vidioc_enum_fmt_vid_cap(struct file *file, void *priv, static int vidioc_g_fmt_vbi_cap(struct file *file, void *priv, struct v4l2_format *f) { - struct cx231xx_fh *fh = priv; - struct cx231xx *dev = fh->dev; + struct cx231xx *dev = video_drvdata(file); f->fmt.vbi.sampling_rate = 6750000 * 4; f->fmt.vbi.samples_per_line = VBI_LINE_LENGTH; @@ -1610,8 +1406,7 @@ static int vidioc_g_fmt_vbi_cap(struct file *file, void *priv, static int vidioc_try_fmt_vbi_cap(struct file *file, void *priv, struct v4l2_format *f) { - struct cx231xx_fh *fh = priv; - struct cx231xx *dev = fh->dev; + struct cx231xx *dev = video_drvdata(file); f->fmt.vbi.sampling_rate = 6750000 * 4; f->fmt.vbi.samples_per_line = VBI_LINE_LENGTH; @@ -1634,77 +1429,16 @@ static int vidioc_try_fmt_vbi_cap(struct file *file, void *priv, static int vidioc_s_fmt_vbi_cap(struct file *file, void *priv, struct v4l2_format *f) { - struct cx231xx_fh *fh = priv; - struct cx231xx *dev = fh->dev; - - if (dev->vbi_stream_on && !fh->stream_on) { - dev_err(dev->dev, - "%s device in use by another fh\n", __func__); - return -EBUSY; - } return vidioc_try_fmt_vbi_cap(file, priv, f); } -static int vidioc_reqbufs(struct file *file, void *priv, - struct v4l2_requestbuffers *rb) -{ - struct cx231xx_fh *fh = priv; - struct cx231xx *dev = fh->dev; - int rc; - - rc = check_dev(dev); - if (rc < 0) - return rc; - - return videobuf_reqbufs(&fh->vb_vidq, rb); -} - -static int vidioc_querybuf(struct file *file, void *priv, struct v4l2_buffer *b) -{ - struct cx231xx_fh *fh = priv; - struct cx231xx *dev = fh->dev; - int rc; - - rc = check_dev(dev); - if (rc < 0) - return rc; - - return videobuf_querybuf(&fh->vb_vidq, b); -} - -static int vidioc_qbuf(struct file *file, void *priv, struct v4l2_buffer *b) -{ - struct cx231xx_fh *fh = priv; - struct cx231xx *dev = fh->dev; - int rc; - - rc = check_dev(dev); - if (rc < 0) - return rc; - - return videobuf_qbuf(&fh->vb_vidq, b); -} - -static int vidioc_dqbuf(struct file *file, void *priv, struct v4l2_buffer *b) -{ - struct cx231xx_fh *fh = priv; - struct cx231xx *dev = fh->dev; - int rc; - - rc = check_dev(dev); - if (rc < 0) - return rc; - - return videobuf_dqbuf(&fh->vb_vidq, b, file->f_flags & O_NONBLOCK); -} - /* ----------------------------------------------------------- */ /* RADIO ESPECIFIC IOCTLS */ /* ----------------------------------------------------------- */ static int radio_g_tuner(struct file *file, void *priv, struct v4l2_tuner *t) { - struct cx231xx *dev = ((struct cx231xx_fh *)priv)->dev; + struct cx231xx *dev = video_drvdata(file); if (t->index) return -EINVAL; @@ -1717,7 +1451,7 @@ static int radio_g_tuner(struct file *file, void *priv, struct v4l2_tuner *t) } static int radio_s_tuner(struct file *file, void *priv, const struct v4l2_tuner *t) { - struct cx231xx *dev = ((struct cx231xx_fh *)priv)->dev; + struct cx231xx *dev = video_drvdata(file); if (t->index) return -EINVAL; @@ -1733,52 +1467,20 @@ static int radio_s_tuner(struct file *file, void *priv, const struct v4l2_tuner */ static int cx231xx_v4l2_open(struct file *filp) { - int radio = 0; struct video_device *vdev = video_devdata(filp); struct cx231xx *dev = video_drvdata(filp); - struct cx231xx_fh *fh; - enum v4l2_buf_type fh_type = 0; - - switch (vdev->vfl_type) { - case VFL_TYPE_GRABBER: - fh_type = V4L2_BUF_TYPE_VIDEO_CAPTURE; - break; - case VFL_TYPE_VBI: - fh_type = V4L2_BUF_TYPE_VBI_CAPTURE; - break; - case VFL_TYPE_RADIO: - radio = 1; - break; - default: - return -EINVAL; - } - - cx231xx_videodbg("open dev=%s type=%s users=%d\n", - video_device_node_name(vdev), v4l2_type_names[fh_type], - dev->users); - -#if 0 - errCode = cx231xx_set_mode(dev, CX231XX_ANALOG_MODE); - if (errCode < 0) { - dev_err(dev->dev, - "Device locked on digital mode. Can't open analog\n"); - return -EBUSY; - } -#endif + int ret; - fh = kzalloc(sizeof(struct cx231xx_fh), GFP_KERNEL); - if (!fh) - return -ENOMEM; - if (mutex_lock_interruptible(&dev->lock)) { - kfree(fh); + if (mutex_lock_interruptible(&dev->lock)) return -ERESTARTSYS; + + ret = v4l2_fh_open(filp); + if (ret) { + mutex_unlock(&dev->lock); + return ret; } - fh->dev = dev; - fh->type = fh_type; - filp->private_data = fh; - v4l2_fh_init(&fh->fh, vdev); - if (fh->type == V4L2_BUF_TYPE_VIDEO_CAPTURE && dev->users == 0) { + if (dev->users++ == 0) { /* Power up in Analog TV mode */ if (dev->board.external_av) cx231xx_set_power_mode(dev, @@ -1786,10 +1488,6 @@ static int cx231xx_v4l2_open(struct file *filp) else cx231xx_set_power_mode(dev, POLARIS_AVMODE_ANALOGT_TV); -#if 0 - cx231xx_set_mode(dev, CX231XX_ANALOG_MODE); -#endif - /* set video alternate setting */ cx231xx_set_video_alternate(dev); @@ -1799,38 +1497,21 @@ static int cx231xx_v4l2_open(struct file *filp) /* device needs to be initialized before isoc transfer */ dev->video_input = dev->video_input > 2 ? 2 : dev->video_input; - } - if (radio) { + + if (vdev->vfl_type == VFL_TYPE_RADIO) { cx231xx_videodbg("video_open: setting radio device\n"); /* cx231xx_start_radio(dev); */ call_all(dev, tuner, s_radio); } - - dev->users++; - - if (fh->type == V4L2_BUF_TYPE_VIDEO_CAPTURE) - videobuf_queue_vmalloc_init(&fh->vb_vidq, &cx231xx_video_qops, - NULL, &dev->video_mode.slock, - fh->type, V4L2_FIELD_INTERLACED, - sizeof(struct cx231xx_buffer), - fh, &dev->lock); - if (fh->type == V4L2_BUF_TYPE_VBI_CAPTURE) { + if (vdev->vfl_type == VFL_TYPE_VBI) { /* Set the required alternate setting VBI interface works in Bulk mode only */ cx231xx_set_alt_setting(dev, INDEX_VANC, 0); - - videobuf_queue_vmalloc_init(&fh->vb_vidq, &cx231xx_vbi_qops, - NULL, &dev->vbi_mode.slock, - fh->type, V4L2_FIELD_SEQ_TB, - sizeof(struct cx231xx_buffer), - fh, &dev->lock); } mutex_unlock(&dev->lock); - v4l2_fh_add(&fh->fh); - return 0; } @@ -1871,68 +1552,12 @@ void cx231xx_release_analog_resources(struct cx231xx *dev) */ static int cx231xx_close(struct file *filp) { - struct cx231xx_fh *fh = filp->private_data; - struct cx231xx *dev = fh->dev; - - cx231xx_videodbg("users=%d\n", dev->users); - - cx231xx_videodbg("users=%d\n", dev->users); - if (res_check(fh)) - res_free(fh); - - /* - * To workaround error number=-71 on EP0 for VideoGrabber, - * need exclude following. - * FIXME: It is probably safe to remove most of these, as we're - * now avoiding the alternate setting for INDEX_VANC - */ - if (!dev->board.no_alt_vanc) - if (fh->type == V4L2_BUF_TYPE_VBI_CAPTURE) { - videobuf_stop(&fh->vb_vidq); - videobuf_mmap_free(&fh->vb_vidq); - - /* the device is already disconnect, - free the remaining resources */ - if (dev->state & DEV_DISCONNECTED) { - if (atomic_read(&dev->devlist_count) > 0) { - cx231xx_release_resources(dev); - fh->dev = NULL; - return 0; - } - return 0; - } - - /* do this before setting alternate! */ - cx231xx_uninit_vbi_isoc(dev); - - /* set alternate 0 */ - if (!dev->vbi_or_sliced_cc_mode) - cx231xx_set_alt_setting(dev, INDEX_VANC, 0); - else - cx231xx_set_alt_setting(dev, INDEX_HANC, 0); - - v4l2_fh_del(&fh->fh); - v4l2_fh_exit(&fh->fh); - kfree(fh); - dev->users--; - wake_up_interruptible(&dev->open); - return 0; - } + struct cx231xx *dev = video_drvdata(filp); + struct video_device *vdev = video_devdata(filp); - v4l2_fh_del(&fh->fh); - dev->users--; - if (!dev->users) { - videobuf_stop(&fh->vb_vidq); - videobuf_mmap_free(&fh->vb_vidq); - - /* the device is already disconnect, - free the remaining resources */ - if (dev->state & DEV_DISCONNECTED) { - cx231xx_release_resources(dev); - fh->dev = NULL; - return 0; - } + _vb2_fop_release(filp, NULL); + if (--dev->users == 0) { /* Save some power by putting tuner to sleep */ call_all(dev, tuner, standby); @@ -1942,20 +1567,40 @@ static int cx231xx_close(struct file *filp) else cx231xx_uninit_bulk(dev); cx231xx_set_mode(dev, CX231XX_SUSPEND); + } + + /* + * To workaround error number=-71 on EP0 for VideoGrabber, + * need exclude following. + * FIXME: It is probably safe to remove most of these, as we're + * now avoiding the alternate setting for INDEX_VANC + */ + if (!dev->board.no_alt_vanc && vdev->vfl_type == VFL_TYPE_VBI) { + /* do this before setting alternate! */ + cx231xx_uninit_vbi_isoc(dev); /* set alternate 0 */ + if (!dev->vbi_or_sliced_cc_mode) + cx231xx_set_alt_setting(dev, INDEX_VANC, 0); + else + cx231xx_set_alt_setting(dev, INDEX_HANC, 0); + + wake_up_interruptible_nr(&dev->open, 1); + return 0; + } + + if (dev->users == 0) { + /* set alternate 0 */ cx231xx_set_alt_setting(dev, INDEX_VIDEO, 0); } - v4l2_fh_exit(&fh->fh); - kfree(fh); + wake_up_interruptible(&dev->open); return 0; } static int cx231xx_v4l2_close(struct file *filp) { - struct cx231xx_fh *fh = filp->private_data; - struct cx231xx *dev = fh->dev; + struct cx231xx *dev = video_drvdata(filp); int rc; mutex_lock(&dev->lock); @@ -1964,116 +1609,13 @@ static int cx231xx_v4l2_close(struct file *filp) return rc; } -/* - * cx231xx_v4l2_read() - * will allocate buffers when called for the first time - */ -static ssize_t -cx231xx_v4l2_read(struct file *filp, char __user *buf, size_t count, - loff_t *pos) -{ - struct cx231xx_fh *fh = filp->private_data; - struct cx231xx *dev = fh->dev; - int rc; - - rc = check_dev(dev); - if (rc < 0) - return rc; - - if ((fh->type == V4L2_BUF_TYPE_VIDEO_CAPTURE) || - (fh->type == V4L2_BUF_TYPE_VBI_CAPTURE)) { - rc = res_get(fh); - - if (unlikely(rc < 0)) - return rc; - - if (mutex_lock_interruptible(&dev->lock)) - return -ERESTARTSYS; - rc = videobuf_read_stream(&fh->vb_vidq, buf, count, pos, 0, - filp->f_flags & O_NONBLOCK); - mutex_unlock(&dev->lock); - return rc; - } - return 0; -} - -/* - * cx231xx_v4l2_poll() - * will allocate buffers when called for the first time - */ -static __poll_t cx231xx_v4l2_poll(struct file *filp, poll_table *wait) -{ - __poll_t req_events = poll_requested_events(wait); - struct cx231xx_fh *fh = filp->private_data; - struct cx231xx *dev = fh->dev; - __poll_t res = 0; - int rc; - - rc = check_dev(dev); - if (rc < 0) - return EPOLLERR; - - rc = res_get(fh); - - if (unlikely(rc < 0)) - return EPOLLERR; - - if (v4l2_event_pending(&fh->fh)) - res |= EPOLLPRI; - else - poll_wait(filp, &fh->fh.wait, wait); - - if (!(req_events & (EPOLLIN | EPOLLRDNORM))) - return res; - - if ((V4L2_BUF_TYPE_VIDEO_CAPTURE == fh->type) || - (V4L2_BUF_TYPE_VBI_CAPTURE == fh->type)) { - mutex_lock(&dev->lock); - res |= videobuf_poll_stream(filp, &fh->vb_vidq, wait); - mutex_unlock(&dev->lock); - return res; - } - return res | EPOLLERR; -} - -/* - * cx231xx_v4l2_mmap() - */ -static int cx231xx_v4l2_mmap(struct file *filp, struct vm_area_struct *vma) -{ - struct cx231xx_fh *fh = filp->private_data; - struct cx231xx *dev = fh->dev; - int rc; - - rc = check_dev(dev); - if (rc < 0) - return rc; - - rc = res_get(fh); - - if (unlikely(rc < 0)) - return rc; - - if (mutex_lock_interruptible(&dev->lock)) - return -ERESTARTSYS; - rc = videobuf_mmap_mapper(&fh->vb_vidq, vma); - mutex_unlock(&dev->lock); - - cx231xx_videodbg("vma start=0x%08lx, size=%ld, ret=%d\n", - (unsigned long)vma->vm_start, - (unsigned long)vma->vm_end - - (unsigned long)vma->vm_start, rc); - - return rc; -} - static const struct v4l2_file_operations cx231xx_v4l_fops = { .owner = THIS_MODULE, .open = cx231xx_v4l2_open, .release = cx231xx_v4l2_close, - .read = cx231xx_v4l2_read, - .poll = cx231xx_v4l2_poll, - .mmap = cx231xx_v4l2_mmap, + .read = vb2_fop_read, + .poll = vb2_fop_poll, + .mmap = vb2_fop_mmap, .unlocked_ioctl = video_ioctl2, }; @@ -2088,17 +1630,17 @@ static const struct v4l2_ioctl_ops video_ioctl_ops = { .vidioc_s_fmt_vbi_cap = vidioc_s_fmt_vbi_cap, .vidioc_g_pixelaspect = vidioc_g_pixelaspect, .vidioc_g_selection = vidioc_g_selection, - .vidioc_reqbufs = vidioc_reqbufs, - .vidioc_querybuf = vidioc_querybuf, - .vidioc_qbuf = vidioc_qbuf, - .vidioc_dqbuf = vidioc_dqbuf, + .vidioc_reqbufs = vb2_ioctl_reqbufs, + .vidioc_querybuf = vb2_ioctl_querybuf, + .vidioc_qbuf = vb2_ioctl_qbuf, + .vidioc_dqbuf = vb2_ioctl_dqbuf, .vidioc_s_std = vidioc_s_std, .vidioc_g_std = vidioc_g_std, .vidioc_enum_input = cx231xx_enum_input, .vidioc_g_input = cx231xx_g_input, .vidioc_s_input = cx231xx_s_input, - .vidioc_streamon = vidioc_streamon, - .vidioc_streamoff = vidioc_streamoff, + .vidioc_streamon = vb2_ioctl_streamon, + .vidioc_streamoff = vb2_ioctl_streamoff, .vidioc_g_tuner = cx231xx_g_tuner, .vidioc_s_tuner = cx231xx_s_tuner, .vidioc_g_frequency = cx231xx_g_frequency, @@ -2175,6 +1717,7 @@ static void cx231xx_vdev_init(struct cx231xx *dev, int cx231xx_register_analog_devices(struct cx231xx *dev) { + struct vb2_queue *q; int ret; dev_info(dev->dev, "v4l2 driver version %s\n", CX231XX_VERSION); @@ -2221,6 +1764,21 @@ int cx231xx_register_analog_devices(struct cx231xx *dev) dev_err(dev->dev, "failed to initialize video media entity!\n"); #endif dev->vdev.ctrl_handler = &dev->ctrl_handler; + + q = &dev->vidq; + q->type = V4L2_BUF_TYPE_VIDEO_CAPTURE; + q->io_modes = VB2_USERPTR | VB2_MMAP | VB2_DMABUF | VB2_READ; + q->drv_priv = dev; + q->buf_struct_size = sizeof(struct cx231xx_buffer); + q->ops = &cx231xx_video_qops; + q->mem_ops = &vb2_vmalloc_memops; + q->timestamp_flags = V4L2_BUF_FLAG_TIMESTAMP_MONOTONIC; + q->min_buffers_needed = 1; + q->lock = &dev->lock; + ret = vb2_queue_init(q); + if (ret) + return ret; + dev->vdev.queue = q; dev->vdev.device_caps = V4L2_CAP_READWRITE | V4L2_CAP_STREAMING | V4L2_CAP_VIDEO_CAPTURE; if (dev->tuner_type != TUNER_ABSENT) @@ -2254,6 +1812,21 @@ int cx231xx_register_analog_devices(struct cx231xx *dev) dev_err(dev->dev, "failed to initialize vbi media entity!\n"); #endif dev->vbi_dev.ctrl_handler = &dev->ctrl_handler; + + q = &dev->vbiq; + q->type = V4L2_BUF_TYPE_VBI_CAPTURE; + q->io_modes = VB2_USERPTR | VB2_MMAP | VB2_DMABUF | VB2_READ; + q->drv_priv = dev; + q->buf_struct_size = sizeof(struct cx231xx_buffer); + q->ops = &cx231xx_vbi_qops; + q->mem_ops = &vb2_vmalloc_memops; + q->timestamp_flags = V4L2_BUF_FLAG_TIMESTAMP_MONOTONIC; + q->min_buffers_needed = 1; + q->lock = &dev->lock; + ret = vb2_queue_init(q); + if (ret) + return ret; + dev->vbi_dev.queue = q; dev->vbi_dev.device_caps = V4L2_CAP_READWRITE | V4L2_CAP_STREAMING | V4L2_CAP_VBI_CAPTURE; if (dev->tuner_type != TUNER_ABSENT) diff --git a/drivers/media/usb/cx231xx/cx231xx.h b/drivers/media/usb/cx231xx/cx231xx.h index b007611abc37..b32eab641793 100644 --- a/drivers/media/usb/cx231xx/cx231xx.h +++ b/drivers/media/usb/cx231xx/cx231xx.h @@ -20,7 +20,7 @@ #include <media/drv-intf/cx2341x.h> -#include <media/videobuf-vmalloc.h> +#include <media/videobuf2-vmalloc.h> #include <media/v4l2-device.h> #include <media/v4l2-ctrls.h> #include <media/v4l2-fh.h> @@ -223,8 +223,8 @@ struct cx231xx_fmt { /* buffer for one video frame */ struct cx231xx_buffer { /* common v4l buffer stuff -- must be first */ - struct videobuf_buffer vb; - + struct vb2_v4l2_buffer vb; + struct list_head list; struct list_head frame; int top_field; int receiving; @@ -237,7 +237,6 @@ enum ps_package_head { struct cx231xx_dmaqueue { struct list_head active; - struct list_head queued; wait_queue_head_t wq; @@ -251,6 +250,7 @@ struct cx231xx_dmaqueue { u32 lines_completed; u8 field1_done; u32 lines_per_field; + u32 sequence; /*Mpeg2 control buffer*/ u8 *p_left_data; @@ -427,23 +427,6 @@ struct cx231xx_audio { struct cx231xx; -struct cx231xx_fh { - struct v4l2_fh fh; - struct cx231xx *dev; - unsigned int stream_on:1; /* Locks streams */ - enum v4l2_buf_type type; - - struct videobuf_queue vb_vidq; - - /* vbi capture */ - struct videobuf_queue vidq; - struct videobuf_queue vbiq; - - /* MPEG Encoder specifics ONLY */ - - atomic_t v4l_reading; -}; - /*****************************************************************/ /* set/get i2c */ /* 00--1Mb/s, 01-400kb/s, 10--100kb/s, 11--5Mb/s */ @@ -634,6 +617,7 @@ struct cx231xx { int width; /* current frame width */ int height; /* current frame height */ int interlaced; /* 1=interlace fields, 0=just top fields */ + unsigned int size; struct cx231xx_audio adev; @@ -657,6 +641,9 @@ struct cx231xx { struct media_pad input_pad[MAX_CX231XX_INPUT]; #endif + struct vb2_queue vidq; + struct vb2_queue vbiq; + unsigned char eedata[256]; struct cx231xx_video_mode video_mode; @@ -717,6 +704,7 @@ struct cx231xx { u8 USE_ISO; struct cx231xx_tvnorm encodernorm; struct cx231xx_tsport ts1, ts2; + struct vb2_queue mpegq; struct video_device v4l_device; atomic_t v4l_reader_count; u32 freq; diff --git a/drivers/media/usb/dvb-usb-v2/af9035.c b/drivers/media/usb/dvb-usb-v2/af9035.c index 3afd18733614..792667ee5ebc 100644 --- a/drivers/media/usb/dvb-usb-v2/af9035.c +++ b/drivers/media/usb/dvb-usb-v2/af9035.c @@ -1197,6 +1197,15 @@ err: return ret; } +/* + * The I2C speed register is calculated with: + * I2C speed register = (1000000000 / (24.4 * 16 * I2C_speed)) + * + * The default speed register for it930x is 7, with means a + * speed of ~366 kbps + */ +#define I2C_SPEED_366K 7 + static int it930x_frontend_attach(struct dvb_usb_adapter *adap) { struct state *state = adap_to_priv(adap); @@ -1208,13 +1217,13 @@ static int it930x_frontend_attach(struct dvb_usb_adapter *adap) dev_dbg(&intf->dev, "adap->id=%d\n", adap->id); - /* I2C master bus 2 clock speed 300k */ - ret = af9035_wr_reg(d, 0x00f6a7, 0x07); + /* I2C master bus 2 clock speed 366k */ + ret = af9035_wr_reg(d, 0x00f6a7, I2C_SPEED_366K); if (ret < 0) goto err; - /* I2C master bus 1,3 clock speed 300k */ - ret = af9035_wr_reg(d, 0x00f103, 0x07); + /* I2C master bus 1,3 clock speed 366k */ + ret = af9035_wr_reg(d, 0x00f103, I2C_SPEED_366K); if (ret < 0) goto err; @@ -1610,6 +1619,24 @@ static int it930x_tuner_attach(struct dvb_usb_adapter *adap) memset(&si2157_config, 0, sizeof(si2157_config)); si2157_config.fe = adap->fe[0]; + + /* + * HACK: The Logilink VG0022A has a bug: when the si2157 + * firmware that came with the device is replaced by a new + * one, the I2C transfers to the tuner will return just 0xff. + * + * Probably, the vendor firmware has some patch specifically + * designed for this device. So, we can't replace by the + * generic firmware. The right solution would be to extract + * the si2157 firmware from the original driver and ask the + * driver to load the specifically designed firmware, but, + * while we don't have that, the next best solution is to just + * keep the original firmware at the device. + */ + if (le16_to_cpu(d->udev->descriptor.idVendor) == USB_VID_DEXATEK && + le16_to_cpu(d->udev->descriptor.idProduct) == 0x0100) + si2157_config.dont_load_firmware = true; + si2157_config.if_port = it930x_addresses_table[state->it930x_addresses].tuner_if_port; ret = af9035_add_i2c_dev(d, "si2157", it930x_addresses_table[state->it930x_addresses].tuner_i2c_addr, @@ -2121,6 +2148,8 @@ static const struct usb_device_id af9035_id_table[] = { &it930x_props, "ITE 9303 Generic", NULL) }, { DVB_USB_DEVICE(USB_VID_AVERMEDIA, USB_PID_AVERMEDIA_TD310, &it930x_props, "AVerMedia TD310 DVB-T2", NULL) }, + { DVB_USB_DEVICE(USB_VID_DEXATEK, 0x0100, + &it930x_props, "Logilink VG0022A", NULL) }, { } }; MODULE_DEVICE_TABLE(usb, af9035_id_table); diff --git a/drivers/media/usb/dvb-usb-v2/dvb_usb.h b/drivers/media/usb/dvb-usb-v2/dvb_usb.h index b874a49ececf..52bcc2d2efe5 100644 --- a/drivers/media/usb/dvb-usb-v2/dvb_usb.h +++ b/drivers/media/usb/dvb-usb-v2/dvb_usb.h @@ -121,6 +121,7 @@ struct dvb_usb_driver_info { * @interval: time in ms between two queries * @driver_type: used to point if a device supports raw mode * @bulk_mode: device supports bulk mode for rc (disable polling mode) + * @timeout: set to length of last space before raw IR goes idle */ struct dvb_usb_rc { const char *map_name; @@ -130,6 +131,7 @@ struct dvb_usb_rc { unsigned int interval; enum rc_driver_type driver_type; bool bulk_mode; + int timeout; }; /** 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 e5e056bf9dfa..f1c79f351ec8 100644 --- a/drivers/media/usb/dvb-usb-v2/dvb_usb_core.c +++ b/drivers/media/usb/dvb-usb-v2/dvb_usb_core.c @@ -150,6 +150,7 @@ static int dvb_usbv2_remote_init(struct dvb_usb_device *d) dev->map_name = d->rc.map_name; dev->allowed_protocols = d->rc.allowed_protos; dev->change_protocol = d->rc.change_protocol; + dev->timeout = d->rc.timeout; dev->priv = d; ret = rc_register_device(dev); diff --git a/drivers/media/usb/dvb-usb-v2/dvbsky.c b/drivers/media/usb/dvb-usb-v2/dvbsky.c index 617a306f6815..356fd8e66834 100644 --- a/drivers/media/usb/dvb-usb-v2/dvbsky.c +++ b/drivers/media/usb/dvb-usb-v2/dvbsky.c @@ -22,7 +22,6 @@ MODULE_PARM_DESC(disable_rc, "Disable inbuilt IR receiver."); DVB_DEFINE_MOD_OPT_ADAPTER_NR(adapter_nr); struct dvbsky_state { - struct mutex stream_mutex; u8 ibuf[DVBSKY_BUF_LEN]; u8 obuf[DVBSKY_BUF_LEN]; u8 last_lock; @@ -60,17 +59,19 @@ static int dvbsky_usb_generic_rw(struct dvb_usb_device *d, static int dvbsky_stream_ctrl(struct dvb_usb_device *d, u8 onoff) { struct dvbsky_state *state = d_to_priv(d); + static const u8 obuf_pre[3] = { 0x37, 0, 0 }; + static const u8 obuf_post[3] = { 0x36, 3, 0 }; int ret; - u8 obuf_pre[3] = { 0x37, 0, 0 }; - u8 obuf_post[3] = { 0x36, 3, 0 }; - mutex_lock(&state->stream_mutex); - ret = dvbsky_usb_generic_rw(d, obuf_pre, 3, NULL, 0); + mutex_lock(&d->usb_mutex); + memcpy(state->obuf, obuf_pre, 3); + ret = dvb_usbv2_generic_write_locked(d, state->obuf, 3); if (!ret && onoff) { msleep(20); - ret = dvbsky_usb_generic_rw(d, obuf_post, 3, NULL, 0); + memcpy(state->obuf, obuf_post, 3); + ret = dvb_usbv2_generic_write_locked(d, state->obuf, 3); } - mutex_unlock(&state->stream_mutex); + mutex_unlock(&d->usb_mutex); return ret; } @@ -591,17 +592,7 @@ static int dvbsky_identify_state(struct dvb_usb_device *d, const char **name) static int dvbsky_init(struct dvb_usb_device *d) { struct dvbsky_state *state = d_to_priv(d); - - /* use default interface */ - /* - ret = usb_set_interface(d->udev, 0, 0); - if (ret) - return ret; - */ - mutex_init(&state->stream_mutex); - state->last_lock = 0; - return 0; } @@ -792,6 +783,9 @@ static const struct usb_device_id dvbsky_id_table[] = { { DVB_USB_DEVICE(USB_VID_CONEXANT, USB_PID_MYGICA_T230C, &mygica_t230c_props, "MyGica Mini DVB-T2 USB Stick T230C", RC_MAP_TOTAL_MEDIA_IN_HAND_02) }, + { DVB_USB_DEVICE(USB_VID_CONEXANT, USB_PID_MYGICA_T230C_LITE, + &mygica_t230c_props, "MyGica Mini DVB-T2 USB Stick T230C Lite", + NULL) }, { DVB_USB_DEVICE(USB_VID_CONEXANT, USB_PID_MYGICA_T230C2, &mygica_t230c_props, "MyGica Mini DVB-T2 USB Stick T230C v2", RC_MAP_TOTAL_MEDIA_IN_HAND_02) }, diff --git a/drivers/media/usb/dvb-usb-v2/gl861.c b/drivers/media/usb/dvb-usb-v2/gl861.c index c7197e534c02..19217dcf20f1 100644 --- a/drivers/media/usb/dvb-usb-v2/gl861.c +++ b/drivers/media/usb/dvb-usb-v2/gl861.c @@ -5,7 +5,7 @@ */ #include <linux/string.h> -#include "gl861.h" +#include "dvb_usb.h" #include "zl10353.h" #include "qt1010.h" @@ -14,93 +14,157 @@ DVB_DEFINE_MOD_OPT_ADAPTER_NR(adapter_nr); -static int gl861_i2c_msg(struct dvb_usb_device *d, u8 addr, - u8 *wbuf, u16 wlen, u8 *rbuf, u16 rlen) -{ - u16 index; - u16 value = addr << (8 + 1); - int wo = (rbuf == NULL || rlen == 0); /* write-only */ - u8 req, type; - u8 *buf; - int ret; +struct gl861 { + /* USB control message buffer */ + u8 buf[16]; - if (wo) { - req = GL861_REQ_I2C_WRITE; - type = GL861_WRITE; - buf = kmemdup(wbuf, wlen, GFP_KERNEL); - } else { /* rw */ - req = GL861_REQ_I2C_READ; - type = GL861_READ; - buf = kmalloc(rlen, GFP_KERNEL); - } - if (!buf) - return -ENOMEM; + struct i2c_adapter *demod_sub_i2c; + struct i2c_client *i2c_client_demod; + struct i2c_client *i2c_client_tuner; +}; - switch (wlen) { - case 1: - index = wbuf[0]; +#define CMD_WRITE_SHORT 0x01 +#define CMD_READ 0x02 +#define CMD_WRITE 0x03 + +static int gl861_ctrl_msg(struct dvb_usb_device *d, u8 request, u16 value, + u16 index, void *data, u16 size) +{ + struct gl861 *ctx = d_to_priv(d); + struct usb_interface *intf = d->intf; + int ret; + unsigned int pipe; + u8 requesttype; + + mutex_lock(&d->usb_mutex); + + switch (request) { + case CMD_WRITE: + memcpy(ctx->buf, data, size); + /* Fall through */ + case CMD_WRITE_SHORT: + pipe = usb_sndctrlpipe(d->udev, 0); + requesttype = USB_TYPE_VENDOR | USB_DIR_OUT; break; - case 2: - index = wbuf[0]; - value = value + wbuf[1]; + case CMD_READ: + pipe = usb_rcvctrlpipe(d->udev, 0); + requesttype = USB_TYPE_VENDOR | USB_DIR_IN; break; default: - dev_err(&d->udev->dev, "%s: wlen=%d, aborting\n", - KBUILD_MODNAME, wlen); - kfree(buf); - return -EINVAL; + ret = -EINVAL; + goto err_mutex_unlock; } - usleep_range(1000, 2000); /* avoid I2C errors */ + ret = usb_control_msg(d->udev, pipe, request, requesttype, value, + index, ctx->buf, size, 200); + dev_dbg(&intf->dev, "%d | %02x %02x %*ph %*ph %*ph %s %*ph\n", + ret, requesttype, request, 2, &value, 2, &index, 2, &size, + (requesttype & USB_DIR_IN) ? "<<<" : ">>>", size, ctx->buf); + if (ret < 0) + goto err_mutex_unlock; - ret = usb_control_msg(d->udev, usb_rcvctrlpipe(d->udev, 0), req, type, - value, index, buf, rlen, 2000); + if (request == CMD_READ) + memcpy(data, ctx->buf, size); - if (!wo && ret > 0) - memcpy(rbuf, buf, rlen); + usleep_range(1000, 2000); /* Avoid I2C errors */ - kfree(buf); + mutex_unlock(&d->usb_mutex); + + return 0; + +err_mutex_unlock: + mutex_unlock(&d->usb_mutex); + dev_dbg(&intf->dev, "failed %d\n", ret); return ret; } -/* I2C */ -static int gl861_i2c_xfer(struct i2c_adapter *adap, struct i2c_msg msg[], - int num) +static int gl861_short_write(struct dvb_usb_device *d, u8 addr, u8 reg, u8 val) +{ + return gl861_ctrl_msg(d, CMD_WRITE_SHORT, + (addr << 9) | val, reg, NULL, 0); +} + +static int gl861_i2c_master_xfer(struct i2c_adapter *adap, struct i2c_msg msg[], + int num) { struct dvb_usb_device *d = i2c_get_adapdata(adap); - int i; + struct usb_interface *intf = d->intf; + struct gl861 *ctx = d_to_priv(d); + int ret; + u8 request, *data; + u16 value, index, size; + + /* XXX: I2C adapter maximum data lengths are not tested */ + if (num == 1 && !(msg[0].flags & I2C_M_RD)) { + /* I2C write */ + if (msg[0].len < 2 || msg[0].len > sizeof(ctx->buf)) { + ret = -EOPNOTSUPP; + goto err; + } + + value = (msg[0].addr << 1) << 8; + index = msg[0].buf[0]; + + if (msg[0].len == 2) { + request = CMD_WRITE_SHORT; + value |= msg[0].buf[1]; + size = 0; + data = NULL; + } else { + request = CMD_WRITE; + size = msg[0].len - 1; + data = &msg[0].buf[1]; + } + + ret = gl861_ctrl_msg(d, request, value, index, data, size); + } else if (num == 2 && !(msg[0].flags & I2C_M_RD) && + (msg[1].flags & I2C_M_RD)) { + /* I2C write + read */ + if (msg[0].len > 1 || msg[1].len > sizeof(ctx->buf)) { + ret = -EOPNOTSUPP; + goto err; + } - if (num > 2) - return -EINVAL; - - if (mutex_lock_interruptible(&d->i2c_mutex) < 0) - return -EAGAIN; - - for (i = 0; i < num; i++) { - /* write/read request */ - if (i+1 < num && (msg[i+1].flags & I2C_M_RD)) { - if (gl861_i2c_msg(d, msg[i].addr, msg[i].buf, - msg[i].len, msg[i+1].buf, msg[i+1].len) < 0) - break; - i++; - } else - if (gl861_i2c_msg(d, msg[i].addr, msg[i].buf, - msg[i].len, NULL, 0) < 0) - break; + value = (msg[0].addr << 1) << 8; + index = msg[0].buf[0]; + request = CMD_READ; + + ret = gl861_ctrl_msg(d, request, value, index, + msg[1].buf, msg[1].len); + } else if (num == 1 && (msg[0].flags & I2C_M_RD)) { + /* I2C read */ + if (msg[0].len > sizeof(ctx->buf)) { + ret = -EOPNOTSUPP; + goto err; + } + value = (msg[0].addr << 1) << 8; + index = 0x0100; + request = CMD_READ; + + ret = gl861_ctrl_msg(d, request, value, index, + msg[0].buf, msg[0].len); + } else { + /* Unsupported I2C message */ + dev_dbg(&intf->dev, "unknown i2c msg, num %u\n", num); + ret = -EOPNOTSUPP; } + if (ret) + goto err; - mutex_unlock(&d->i2c_mutex); - return i; + return num; +err: + dev_dbg(&intf->dev, "failed %d\n", ret); + return ret; } -static u32 gl861_i2c_func(struct i2c_adapter *adapter) +static u32 gl861_i2c_functionality(struct i2c_adapter *adapter) { return I2C_FUNC_I2C; } static struct i2c_algorithm gl861_i2c_algo = { - .master_xfer = gl861_i2c_xfer, - .functionality = gl861_i2c_func, + .master_xfer = gl861_i2c_master_xfer, + .functionality = gl861_i2c_functionality, }; /* Callbacks for DVB USB */ @@ -149,6 +213,8 @@ static struct dvb_usb_device_properties gl861_props = { .owner = THIS_MODULE, .adapter_nr = adapter_nr, + .size_of_priv = sizeof(struct gl861), + .i2c_algo = &gl861_i2c_algo, .frontend_attach = gl861_frontend_attach, .tuner_attach = gl861_tuner_attach, @@ -166,14 +232,6 @@ static struct dvb_usb_device_properties gl861_props = { /* * For Friio */ - -struct friio_priv { - struct i2c_adapter *demod_sub_i2c; - struct i2c_client *i2c_client_demod; - struct i2c_client *i2c_client_tuner; - struct i2c_adapter tuner_adap; -}; - struct friio_config { struct i2c_board_info demod_info; struct tc90522_config demod_cfg; @@ -184,132 +242,10 @@ struct friio_config { static const struct friio_config friio_config = { .demod_info = { I2C_BOARD_INFO(TC90522_I2C_DEV_TER, 0x18), }, + .demod_cfg = { .split_tuner_read_i2c = true, }, .tuner_info = { I2C_BOARD_INFO("tua6034_friio", 0x60), }, }; -/* For another type of I2C: - * message sent by a USB control-read/write transaction with data stage. - * Used in init/config of Friio. - */ -static int -gl861_i2c_write_ex(struct dvb_usb_device *d, u8 addr, u8 *wbuf, u16 wlen) -{ - u8 *buf; - int ret; - - buf = kmemdup(wbuf, wlen, GFP_KERNEL); - if (!buf) - return -ENOMEM; - - ret = usb_control_msg(d->udev, usb_sndctrlpipe(d->udev, 0), - GL861_REQ_I2C_RAW, GL861_WRITE, - addr << (8 + 1), 0x0100, buf, wlen, 2000); - kfree(buf); - return ret; -} - -static int -gl861_i2c_read_ex(struct dvb_usb_device *d, u8 addr, u8 *rbuf, u16 rlen) -{ - u8 *buf; - int ret; - - buf = kmalloc(rlen, GFP_KERNEL); - if (!buf) - return -ENOMEM; - - ret = usb_control_msg(d->udev, usb_rcvctrlpipe(d->udev, 0), - GL861_REQ_I2C_READ, GL861_READ, - addr << (8 + 1), 0x0100, buf, rlen, 2000); - if (ret > 0 && rlen > 0) - memcpy(buf, rbuf, rlen); - kfree(buf); - return ret; -} - -/* For I2C transactions to the tuner of Friio (dvb_pll). - * - * Friio uses irregular USB encapsulation for tuner i2c transactions: - * write transacions are encapsulated with a different USB 'request' value. - * - * Although all transactions are sent via the demod(tc90522) - * and the demod provides an i2c adapter for them, it cannot be used in Friio - * since it assumes using the same parent adapter with the demod, - * which does not use the request value and uses same one for both read/write. - * So we define a dedicated i2c adapter here. - */ - -static int -friio_i2c_tuner_read(struct dvb_usb_device *d, struct i2c_msg *msg) -{ - struct friio_priv *priv; - u8 addr; - - priv = d_to_priv(d); - addr = priv->i2c_client_demod->addr; - return gl861_i2c_read_ex(d, addr, msg->buf, msg->len); -} - -static int -friio_i2c_tuner_write(struct dvb_usb_device *d, struct i2c_msg *msg) -{ - u8 *buf; - int ret; - struct friio_priv *priv; - - priv = d_to_priv(d); - - if (msg->len < 1) - return -EINVAL; - - buf = kmalloc(msg->len + 1, GFP_KERNEL); - if (!buf) - return -ENOMEM; - buf[0] = msg->addr << 1; - memcpy(buf + 1, msg->buf, msg->len); - - ret = usb_control_msg(d->udev, usb_sndctrlpipe(d->udev, 0), - GL861_REQ_I2C_RAW, GL861_WRITE, - priv->i2c_client_demod->addr << (8 + 1), - 0xFE, buf, msg->len + 1, 2000); - kfree(buf); - return ret; -} - -static int friio_tuner_i2c_xfer(struct i2c_adapter *adap, struct i2c_msg msg[], - int num) -{ - struct dvb_usb_device *d = i2c_get_adapdata(adap); - int i; - - if (num > 2) - return -EINVAL; - - if (mutex_lock_interruptible(&d->i2c_mutex) < 0) - return -EAGAIN; - - for (i = 0; i < num; i++) { - int ret; - - if (msg[i].flags & I2C_M_RD) - ret = friio_i2c_tuner_read(d, &msg[i]); - else - ret = friio_i2c_tuner_write(d, &msg[i]); - - if (ret < 0) - break; - - usleep_range(1000, 2000); /* avoid I2C errors */ - } - - mutex_unlock(&d->i2c_mutex); - return i; -} - -static struct i2c_algorithm friio_tuner_i2c_algo = { - .master_xfer = friio_tuner_i2c_xfer, - .functionality = gl861_i2c_func, -}; /* GPIO control in Friio */ @@ -377,9 +313,11 @@ static int friio_ext_ctl(struct dvb_usb_device *d, /* init/config of gl861 for Friio */ /* NOTE: * This function cannot be moved to friio_init()/dvb_usbv2_init(), - * because the init defined here must be done before any activities like I2C, + * because the init defined here includes a whole device reset, + * it must be run early before any activities like I2C, * but friio_init() is called by dvb-usbv2 after {_frontend, _tuner}_attach(), * where I2C communication is used. + * In addition, this reset is required in reset_resume() as well. * Thus this function is set to be called from _power_ctl(). * * Since it will be called on the early init stage @@ -389,7 +327,7 @@ static int friio_ext_ctl(struct dvb_usb_device *d, static int friio_reset(struct dvb_usb_device *d) { int i, ret; - u8 wbuf[2], rbuf[2]; + u8 wbuf[1], rbuf[2]; static const u8 friio_init_cmds[][2] = { {0x33, 0x08}, {0x37, 0x40}, {0x3a, 0x1f}, {0x3b, 0xff}, @@ -401,16 +339,12 @@ static int friio_reset(struct dvb_usb_device *d) if (ret < 0) return ret; - wbuf[0] = 0x11; - wbuf[1] = 0x02; - ret = gl861_i2c_msg(d, 0x00, wbuf, 2, NULL, 0); + ret = gl861_short_write(d, 0x00, 0x11, 0x02); if (ret < 0) return ret; usleep_range(2000, 3000); - wbuf[0] = 0x11; - wbuf[1] = 0x00; - ret = gl861_i2c_msg(d, 0x00, wbuf, 2, NULL, 0); + ret = gl861_short_write(d, 0x00, 0x11, 0x00); if (ret < 0) return ret; @@ -420,14 +354,13 @@ static int friio_reset(struct dvb_usb_device *d) */ usleep_range(1000, 2000); - wbuf[0] = 0x03; - wbuf[1] = 0x80; - ret = gl861_i2c_write_ex(d, 0x09, wbuf, 2); + wbuf[0] = 0x80; + ret = gl861_ctrl_msg(d, CMD_WRITE, 0x09 << 9, 0x03, wbuf, 1); if (ret < 0) return ret; usleep_range(2000, 3000); - ret = gl861_i2c_read_ex(d, 0x09, rbuf, 2); + ret = gl861_ctrl_msg(d, CMD_READ, 0x09 << 9, 0x0100, rbuf, 2); if (ret < 0) return ret; if (rbuf[0] != 0xff || rbuf[1] != 0xff) @@ -435,38 +368,33 @@ static int friio_reset(struct dvb_usb_device *d) usleep_range(1000, 2000); - ret = gl861_i2c_write_ex(d, 0x48, wbuf, 2); + wbuf[0] = 0x80; + ret = gl861_ctrl_msg(d, CMD_WRITE, 0x48 << 9, 0x03, wbuf, 1); if (ret < 0) return ret; usleep_range(2000, 3000); - ret = gl861_i2c_read_ex(d, 0x48, rbuf, 2); + ret = gl861_ctrl_msg(d, CMD_READ, 0x48 << 9, 0x0100, rbuf, 2); if (ret < 0) return ret; if (rbuf[0] != 0xff || rbuf[1] != 0xff) return -ENODEV; - wbuf[0] = 0x30; - wbuf[1] = 0x04; - ret = gl861_i2c_msg(d, 0x00, wbuf, 2, NULL, 0); + ret = gl861_short_write(d, 0x00, 0x30, 0x04); if (ret < 0) return ret; - wbuf[0] = 0x00; - wbuf[1] = 0x01; - ret = gl861_i2c_msg(d, 0x00, wbuf, 2, NULL, 0); + ret = gl861_short_write(d, 0x00, 0x00, 0x01); if (ret < 0) return ret; - wbuf[0] = 0x06; - wbuf[1] = 0x0f; - ret = gl861_i2c_msg(d, 0x00, wbuf, 2, NULL, 0); + ret = gl861_short_write(d, 0x00, 0x06, 0x0f); if (ret < 0) return ret; for (i = 0; i < ARRAY_SIZE(friio_init_cmds); i++) { - ret = gl861_i2c_msg(d, 0x00, (u8 *)friio_init_cmds[i], 2, - NULL, 0); + ret = gl861_short_write(d, 0x00, friio_init_cmds[i][0], + friio_init_cmds[i][1]); if (ret < 0) return ret; } @@ -488,9 +416,10 @@ static int friio_frontend_attach(struct dvb_usb_adapter *adap) struct dvb_usb_device *d; struct tc90522_config cfg; struct i2c_client *cl; - struct friio_priv *priv; + struct gl861 *priv; info = &friio_config.demod_info; + cfg = friio_config.demod_cfg; d = adap_to_d(adap); cl = dvb_module_probe("tc90522", info->type, &d->i2c_adap, info->addr, &cfg); @@ -498,25 +427,17 @@ static int friio_frontend_attach(struct dvb_usb_adapter *adap) return -ENODEV; adap->fe[0] = cfg.fe; - /* ignore cfg.tuner_i2c and create new one */ priv = adap_to_priv(adap); priv->i2c_client_demod = cl; - priv->tuner_adap.algo = &friio_tuner_i2c_algo; - priv->tuner_adap.dev.parent = &d->udev->dev; - strscpy(priv->tuner_adap.name, d->name, sizeof(priv->tuner_adap.name)); - strlcat(priv->tuner_adap.name, "-tuner", sizeof(priv->tuner_adap.name)); - priv->demod_sub_i2c = &priv->tuner_adap; - i2c_set_adapdata(&priv->tuner_adap, d); - - return i2c_add_adapter(&priv->tuner_adap); + priv->demod_sub_i2c = cfg.tuner_i2c; + return 0; } static int friio_frontend_detach(struct dvb_usb_adapter *adap) { - struct friio_priv *priv; + struct gl861 *priv; priv = adap_to_priv(adap); - i2c_del_adapter(&priv->tuner_adap); dvb_module_release(priv->i2c_client_demod); return 0; } @@ -526,7 +447,7 @@ static int friio_tuner_attach(struct dvb_usb_adapter *adap) const struct i2c_board_info *info; struct dvb_pll_config cfg; struct i2c_client *cl; - struct friio_priv *priv; + struct gl861 *priv; priv = adap_to_priv(adap); info = &friio_config.tuner_info; @@ -543,7 +464,7 @@ static int friio_tuner_attach(struct dvb_usb_adapter *adap) static int friio_tuner_detach(struct dvb_usb_adapter *adap) { - struct friio_priv *priv; + struct gl861 *priv; priv = adap_to_priv(adap); dvb_module_release(priv->i2c_client_tuner); @@ -554,7 +475,7 @@ static int friio_init(struct dvb_usb_device *d) { int i; int ret; - struct friio_priv *priv; + struct gl861 *priv; static const u8 demod_init[][2] = { {0x01, 0x40}, {0x04, 0x38}, {0x05, 0x40}, {0x07, 0x40}, @@ -606,7 +527,7 @@ static struct dvb_usb_device_properties friio_props = { .owner = THIS_MODULE, .adapter_nr = adapter_nr, - .size_of_priv = sizeof(struct friio_priv), + .size_of_priv = sizeof(struct gl861), .i2c_algo = &gl861_i2c_algo, .power_ctrl = friio_power_ctrl, diff --git a/drivers/media/usb/dvb-usb-v2/gl861.h b/drivers/media/usb/dvb-usb-v2/gl861.h deleted file mode 100644 index 02c00e10748a..000000000000 --- a/drivers/media/usb/dvb-usb-v2/gl861.h +++ /dev/null @@ -1,14 +0,0 @@ -/* SPDX-License-Identifier: GPL-2.0 */ -#ifndef _DVB_USB_GL861_H_ -#define _DVB_USB_GL861_H_ - -#include "dvb_usb.h" - -#define GL861_WRITE 0x40 -#define GL861_READ 0xc0 - -#define GL861_REQ_I2C_WRITE 0x01 -#define GL861_REQ_I2C_READ 0x02 -#define GL861_REQ_I2C_RAW 0x03 - -#endif diff --git a/drivers/media/usb/dvb-usb-v2/rtl28xxu.c b/drivers/media/usb/dvb-usb-v2/rtl28xxu.c index 1a36bda28542..5016ede7b35f 100644 --- a/drivers/media/usb/dvb-usb-v2/rtl28xxu.c +++ b/drivers/media/usb/dvb-usb-v2/rtl28xxu.c @@ -1781,7 +1781,6 @@ static int rtl2832u_rc_query(struct dvb_usb_device *d) } /* 'flush' ir_raw_event_store_with_filter() */ - ir_raw_event_set_idle(d->rc_dev, true); ir_raw_event_handle(d->rc_dev); exit: return ret; @@ -1804,6 +1803,8 @@ static int rtl2832u_get_rc_config(struct dvb_usb_device *d, rc->driver_type = RC_DRIVER_IR_RAW; rc->query = rtl2832u_rc_query; rc->interval = 200; + /* we program idle len to 0xc0, set timeout to one less */ + rc->timeout = 0xbf * 50800; return 0; } @@ -1957,7 +1958,8 @@ static const struct usb_device_id rtl28xxu_id_table[] = { /* RTL2832P devices: */ { DVB_USB_DEVICE(USB_VID_HANFTEK, 0x0131, - &rtl28xxu_props, "Astrometa DVB-T2", NULL) }, + &rtl28xxu_props, "Astrometa DVB-T2", + RC_MAP_ASTROMETA_T2HYBRID) }, { DVB_USB_DEVICE(0x5654, 0xca42, &rtl28xxu_props, "GoTView MasterHD 3", NULL) }, { } diff --git a/drivers/media/usb/dvb-usb/af9005.c b/drivers/media/usb/dvb-usb/af9005.c index 02697d86e8c1..ac93e88d7038 100644 --- a/drivers/media/usb/dvb-usb/af9005.c +++ b/drivers/media/usb/dvb-usb/af9005.c @@ -976,8 +976,9 @@ static int af9005_identify_state(struct usb_device *udev, else if (reply == 0x02) *cold = 0; else - return -EIO; - deb_info("Identify state cold = %d\n", *cold); + ret = -EIO; + if (!ret) + deb_info("Identify state cold = %d\n", *cold); err: kfree(buf); diff --git a/drivers/media/usb/dvb-usb/cxusb.c b/drivers/media/usb/dvb-usb/cxusb.c index f02fa0a67aa4..fac19ec46089 100644 --- a/drivers/media/usb/dvb-usb/cxusb.c +++ b/drivers/media/usb/dvb-usb/cxusb.c @@ -521,7 +521,8 @@ static int cxusb_rc_query(struct dvb_usb_device *d) { u8 ircode[4]; - cxusb_ctrl_msg(d, CMD_GET_IR_CODE, NULL, 0, ircode, 4); + if (cxusb_ctrl_msg(d, CMD_GET_IR_CODE, NULL, 0, ircode, 4) < 0) + return 0; if (ircode[2] || ircode[3]) rc_keydown(d->rc_dev, RC_PROTO_NEC, diff --git a/drivers/media/usb/em28xx/em28xx-audio.c b/drivers/media/usb/em28xx/em28xx-audio.c index 49c9b70b632b..79dfbb25714b 100644 --- a/drivers/media/usb/em28xx/em28xx-audio.c +++ b/drivers/media/usb/em28xx/em28xx-audio.c @@ -31,7 +31,6 @@ #include <linux/soundcard.h> #include <linux/slab.h> #include <linux/vmalloc.h> -#include <linux/proc_fs.h> #include <linux/module.h> #include <sound/core.h> #include <sound/pcm.h> diff --git a/drivers/media/usb/em28xx/em28xx-cards.c b/drivers/media/usb/em28xx/em28xx-cards.c index 5983e72a0622..def9cdd931a9 100644 --- a/drivers/media/usb/em28xx/em28xx-cards.c +++ b/drivers/media/usb/em28xx/em28xx-cards.c @@ -2487,6 +2487,24 @@ const struct em28xx_board em28xx_boards[] = { .ir_codes = RC_MAP_HAUPPAUGE, .leds = hauppauge_dualhd_leds, }, + /* + * 1b80:e349 Magix USB Videowandler-2 + * (same chips as Honestech VIDBOX NW03) + * Empia EM2860, Philips SAA7113, Empia EMP202, No Tuner + */ + [EM2861_BOARD_MAGIX_VIDEOWANDLER2] = { + .name = "Magix USB Videowandler-2", + .tuner_type = TUNER_ABSENT, + .decoder = EM28XX_SAA711X, + .input = { { + .type = EM28XX_VMUX_COMPOSITE, + .vmux = SAA7115_COMPOSITE0, + .amux = EM28XX_AMUX_LINE_IN, + }, { + .type = EM28XX_VMUX_SVIDEO, + .amux = EM28XX_AMUX_LINE_IN, + } }, + }, }; EXPORT_SYMBOL_GPL(em28xx_boards); @@ -2696,6 +2714,8 @@ struct usb_device_id em28xx_id_table[] = { .driver_info = EM28178_BOARD_PLEX_PX_BCUD }, { USB_DEVICE(0xeb1a, 0x5051), /* Ion Video 2 PC MKII / Startech svid2usb23 / Raygo R12-41373 */ .driver_info = EM2860_BOARD_TVP5150_REFERENCE_DESIGN }, + { USB_DEVICE(0x1b80, 0xe349), /* Magix USB Videowandler-2 */ + .driver_info = EM2861_BOARD_MAGIX_VIDEOWANDLER2 }, { }, }; MODULE_DEVICE_TABLE(usb, em28xx_id_table); diff --git a/drivers/media/usb/em28xx/em28xx-dvb.c b/drivers/media/usb/em28xx/em28xx-dvb.c index a73faf12f7e4..0ab6c493bc74 100644 --- a/drivers/media/usb/em28xx/em28xx-dvb.c +++ b/drivers/media/usb/em28xx/em28xx-dvb.c @@ -471,13 +471,13 @@ static void hauppauge_hvr930c_init(struct em28xx *dev) { int i; - struct em28xx_reg_seq hauppauge_hvr930c_init[] = { + static const struct em28xx_reg_seq hauppauge_hvr930c_init[] = { {EM2874_R80_GPIO_P0_CTRL, 0xff, 0xff, 0x65}, {EM2874_R80_GPIO_P0_CTRL, 0xfb, 0xff, 0x32}, {EM2874_R80_GPIO_P0_CTRL, 0xff, 0xff, 0xb8}, { -1, -1, -1, -1}, }; - struct em28xx_reg_seq hauppauge_hvr930c_end[] = { + static const struct em28xx_reg_seq hauppauge_hvr930c_end[] = { {EM2874_R80_GPIO_P0_CTRL, 0xef, 0xff, 0x01}, {EM2874_R80_GPIO_P0_CTRL, 0xaf, 0xff, 0x65}, {EM2874_R80_GPIO_P0_CTRL, 0xef, 0xff, 0x76}, @@ -493,7 +493,7 @@ static void hauppauge_hvr930c_init(struct em28xx *dev) { -1, -1, -1, -1}, }; - struct { + static const struct { unsigned char r[4]; int len; } regs[] = { @@ -537,20 +537,20 @@ static void hauppauge_hvr930c_init(struct em28xx *dev) static void terratec_h5_init(struct em28xx *dev) { int i; - struct em28xx_reg_seq terratec_h5_init[] = { + static const struct em28xx_reg_seq terratec_h5_init[] = { {EM2820_R08_GPIO_CTRL, 0xff, 0xff, 10}, {EM2874_R80_GPIO_P0_CTRL, 0xf6, 0xff, 100}, {EM2874_R80_GPIO_P0_CTRL, 0xf2, 0xff, 50}, {EM2874_R80_GPIO_P0_CTRL, 0xf6, 0xff, 100}, { -1, -1, -1, -1}, }; - struct em28xx_reg_seq terratec_h5_end[] = { + static const struct em28xx_reg_seq terratec_h5_end[] = { {EM2874_R80_GPIO_P0_CTRL, 0xe6, 0xff, 100}, {EM2874_R80_GPIO_P0_CTRL, 0xa6, 0xff, 50}, {EM2874_R80_GPIO_P0_CTRL, 0xe6, 0xff, 100}, { -1, -1, -1, -1}, }; - struct { + static const struct { unsigned char r[4]; int len; } regs[] = { @@ -594,14 +594,14 @@ static void terratec_htc_stick_init(struct em28xx *dev) * 0xe6: unknown (does not affect DVB-T). * 0xb6: unknown (does not affect DVB-T). */ - struct em28xx_reg_seq terratec_htc_stick_init[] = { + static const struct em28xx_reg_seq terratec_htc_stick_init[] = { {EM2820_R08_GPIO_CTRL, 0xff, 0xff, 10}, {EM2874_R80_GPIO_P0_CTRL, 0xf6, 0xff, 100}, {EM2874_R80_GPIO_P0_CTRL, 0xe6, 0xff, 50}, {EM2874_R80_GPIO_P0_CTRL, 0xf6, 0xff, 100}, { -1, -1, -1, -1}, }; - struct em28xx_reg_seq terratec_htc_stick_end[] = { + static const struct em28xx_reg_seq terratec_htc_stick_end[] = { {EM2874_R80_GPIO_P0_CTRL, 0xb6, 0xff, 100}, {EM2874_R80_GPIO_P0_CTRL, 0xf6, 0xff, 50}, { -1, -1, -1, -1}, @@ -611,7 +611,7 @@ static void terratec_htc_stick_init(struct em28xx *dev) * Init the analog decoder (not yet supported), but * it's probably still a good idea. */ - struct { + static const struct { unsigned char r[4]; int len; } regs[] = { @@ -642,14 +642,14 @@ static void terratec_htc_usb_xs_init(struct em28xx *dev) { int i; - struct em28xx_reg_seq terratec_htc_usb_xs_init[] = { + static const struct em28xx_reg_seq terratec_htc_usb_xs_init[] = { {EM2820_R08_GPIO_CTRL, 0xff, 0xff, 10}, {EM2874_R80_GPIO_P0_CTRL, 0xb2, 0xff, 100}, {EM2874_R80_GPIO_P0_CTRL, 0xb2, 0xff, 50}, {EM2874_R80_GPIO_P0_CTRL, 0xb6, 0xff, 100}, { -1, -1, -1, -1}, }; - struct em28xx_reg_seq terratec_htc_usb_xs_end[] = { + static const struct em28xx_reg_seq terratec_htc_usb_xs_end[] = { {EM2874_R80_GPIO_P0_CTRL, 0xa6, 0xff, 100}, {EM2874_R80_GPIO_P0_CTRL, 0xa6, 0xff, 50}, {EM2874_R80_GPIO_P0_CTRL, 0xe6, 0xff, 100}, @@ -660,7 +660,7 @@ static void terratec_htc_usb_xs_init(struct em28xx *dev) * Init the analog decoder (not yet supported), but * it's probably still a good idea. */ - struct { + static const struct { unsigned char r[4]; int len; } regs[] = { @@ -704,7 +704,7 @@ static void pctv_520e_init(struct em28xx *dev) * digital demodulator and tuner are routed via AVF4910B. */ int i; - struct { + static const struct { unsigned char r[4]; int len; } regs[] = { @@ -800,7 +800,7 @@ static int em28xx_mt352_terratec_xs_init(struct dvb_frontend *fe) static void px_bcud_init(struct em28xx *dev) { int i; - struct { + static const struct { unsigned char r[4]; int len; } regs1[] = { @@ -818,7 +818,7 @@ static void px_bcud_init(struct em28xx *dev) {{ 0x85, 0x7a }, 2}, {{ 0x87, 0x04 }, 2}, }; - static struct em28xx_reg_seq gpio[] = { + static const struct em28xx_reg_seq gpio[] = { {EM28XX_R06_I2C_CLK, 0x40, 0xff, 300}, {EM2874_R80_GPIO_P0_CTRL, 0xfd, 0xff, 60}, {EM28XX_R15_RGAIN, 0x20, 0xff, 0}, diff --git a/drivers/media/usb/em28xx/em28xx-i2c.c b/drivers/media/usb/em28xx/em28xx-i2c.c index a3155ec196cc..592b98b3643a 100644 --- a/drivers/media/usb/em28xx/em28xx-i2c.c +++ b/drivers/media/usb/em28xx/em28xx-i2c.c @@ -949,7 +949,7 @@ void em28xx_do_i2c_scan(struct em28xx *dev, unsigned int bus) unsigned char buf; int i, rc; - memset(i2c_devicelist, 0, ARRAY_SIZE(i2c_devicelist)); + memset(i2c_devicelist, 0, sizeof(i2c_devicelist)); for (i = 0; i < ARRAY_SIZE(i2c_devs); i++) { dev->i2c_client[bus].addr = i; @@ -964,7 +964,7 @@ void em28xx_do_i2c_scan(struct em28xx *dev, unsigned int bus) if (bus == dev->def_i2c_bus) dev->i2c_hash = em28xx_hash_mem(i2c_devicelist, - ARRAY_SIZE(i2c_devicelist), 32); + sizeof(i2c_devicelist), 32); } /* diff --git a/drivers/media/usb/em28xx/em28xx.h b/drivers/media/usb/em28xx/em28xx.h index c8bc59059a19..4ecadd57dac7 100644 --- a/drivers/media/usb/em28xx/em28xx.h +++ b/drivers/media/usb/em28xx/em28xx.h @@ -149,6 +149,7 @@ #define EM28174_BOARD_HAUPPAUGE_WINTV_DUALHD_01595 100 #define EM2884_BOARD_TERRATEC_H6 101 #define EM2882_BOARD_ZOLID_HYBRID_TV_STICK 102 +#define EM2861_BOARD_MAGIX_VIDEOWANDLER2 103 /* Limits minimum and default number of buffers */ #define EM28XX_MIN_BUF 4 diff --git a/drivers/media/usb/gspca/sq905.c b/drivers/media/usb/gspca/sq905.c index 863c485f4275..97799cfb832e 100644 --- a/drivers/media/usb/gspca/sq905.c +++ b/drivers/media/usb/gspca/sq905.c @@ -378,6 +378,9 @@ static int sd_start(struct gspca_dev *gspca_dev) } /* Start the workqueue function to do the streaming */ dev->work_thread = create_singlethread_workqueue(MODULE_NAME); + if (!dev->work_thread) + return -ENOMEM; + queue_work(dev->work_thread, &dev->work_struct); return 0; diff --git a/drivers/media/usb/gspca/sq905c.c b/drivers/media/usb/gspca/sq905c.c index 3d7f6dcdd7a8..6ca947aef298 100644 --- a/drivers/media/usb/gspca/sq905c.c +++ b/drivers/media/usb/gspca/sq905c.c @@ -276,6 +276,9 @@ static int sd_start(struct gspca_dev *gspca_dev) } /* Start the workqueue function to do the streaming */ dev->work_thread = create_singlethread_workqueue(MODULE_NAME); + if (!dev->work_thread) + return -ENOMEM; + queue_work(dev->work_thread, &dev->work_struct); return 0; diff --git a/drivers/media/usb/gspca/stv0680.c b/drivers/media/usb/gspca/stv0680.c index f869eb6065ce..b23988d8c7bc 100644 --- a/drivers/media/usb/gspca/stv0680.c +++ b/drivers/media/usb/gspca/stv0680.c @@ -35,7 +35,7 @@ struct sd { static int stv_sndctrl(struct gspca_dev *gspca_dev, int set, u8 req, u16 val, int size) { - int ret = -1; + int ret; u8 req_type = 0; unsigned int pipe = 0; diff --git a/drivers/media/usb/gspca/stv06xx/stv06xx_st6422.c b/drivers/media/usb/gspca/stv06xx/stv06xx_st6422.c index 7104a88b1e43..aac19d449be2 100644 --- a/drivers/media/usb/gspca/stv06xx/stv06xx_st6422.c +++ b/drivers/media/usb/gspca/stv06xx/stv06xx_st6422.c @@ -117,7 +117,7 @@ static int st6422_init(struct sd *sd) { int err = 0, i; - const u16 st6422_bridge_init[][2] = { + static const u16 st6422_bridge_init[][2] = { { STV_ISO_ENABLE, 0x00 }, /* disable capture */ { 0x1436, 0x00 }, { 0x1432, 0x03 }, /* 0x00-0x1F brightness */ diff --git a/drivers/media/usb/pvrusb2/pvrusb2-v4l2.c b/drivers/media/usb/pvrusb2/pvrusb2-v4l2.c index a34717eba409..eaa08c7999d4 100644 --- a/drivers/media/usb/pvrusb2/pvrusb2-v4l2.c +++ b/drivers/media/usb/pvrusb2/pvrusb2-v4l2.c @@ -898,8 +898,12 @@ static void pvr2_v4l2_internal_check(struct pvr2_channel *chp) pvr2_v4l2_dev_disassociate_parent(vp->dev_video); pvr2_v4l2_dev_disassociate_parent(vp->dev_radio); if (!list_empty(&vp->dev_video->devbase.fh_list) || - !list_empty(&vp->dev_radio->devbase.fh_list)) + (vp->dev_radio && + !list_empty(&vp->dev_radio->devbase.fh_list))) { + pvr2_trace(PVR2_TRACE_STRUCT, + "pvr2_v4l2 internal_check exit-empty id=%p", vp); return; + } pvr2_v4l2_destroy_no_lock(vp); } @@ -935,7 +939,8 @@ static int pvr2_v4l2_release(struct file *file) kfree(fhp); if (vp->channel.mc_head->disconnect_flag && list_empty(&vp->dev_video->devbase.fh_list) && - list_empty(&vp->dev_radio->devbase.fh_list)) { + (!vp->dev_radio || + list_empty(&vp->dev_radio->devbase.fh_list))) { pvr2_v4l2_destroy_no_lock(vp); } return 0; diff --git a/drivers/media/usb/tm6000/tm6000-regs.h b/drivers/media/usb/tm6000/tm6000-regs.h index d10424673db9..6a181f2e7ef2 100644 --- a/drivers/media/usb/tm6000/tm6000-regs.h +++ b/drivers/media/usb/tm6000/tm6000-regs.h @@ -1,5 +1,5 @@ +/* SPDX-License-Identifier: GPL-2.0 */ /* - * SPDX-License-Identifier: GPL-2.0 * tm6000-regs.h - driver for TM5600/TM6000/TM6010 USB video capture devices * * Copyright (c) 2006-2007 Mauro Carvalho Chehab <mchehab@kernel.org> diff --git a/drivers/media/usb/tm6000/tm6000-usb-isoc.h b/drivers/media/usb/tm6000/tm6000-usb-isoc.h index b275dbce3a1b..e3c6933f854d 100644 --- a/drivers/media/usb/tm6000/tm6000-usb-isoc.h +++ b/drivers/media/usb/tm6000/tm6000-usb-isoc.h @@ -1,5 +1,5 @@ +/* SPDX-License-Identifier: GPL-2.0 */ /* - * SPDX-License-Identifier: GPL-2.0 * tm6000-buf.c - driver for TM5600/TM6000/TM6010 USB video capture devices * * Copyright (c) 2006-2007 Mauro Carvalho Chehab <mchehab@kernel.org> diff --git a/drivers/media/usb/tm6000/tm6000.h b/drivers/media/usb/tm6000/tm6000.h index bf396544da9a..c08c95312739 100644 --- a/drivers/media/usb/tm6000/tm6000.h +++ b/drivers/media/usb/tm6000/tm6000.h @@ -1,5 +1,5 @@ +/* SPDX-License-Identifier: GPL-2.0 */ /* - * SPDX-License-Identifier: GPL-2.0 * tm6000.h - driver for TM5600/TM6000/TM6010 USB video capture devices * * Copyright (c) 2006-2007 Mauro Carvalho Chehab <mchehab@kernel.org> diff --git a/drivers/media/usb/usbvision/usbvision-video.c b/drivers/media/usb/usbvision/usbvision-video.c index cdc66adda755..93d36aab824f 100644 --- a/drivers/media/usb/usbvision/usbvision-video.c +++ b/drivers/media/usb/usbvision/usbvision-video.c @@ -314,6 +314,10 @@ static int usbvision_v4l2_open(struct file *file) if (mutex_lock_interruptible(&usbvision->v4l2_lock)) return -ERESTARTSYS; + if (usbvision->remove_pending) { + err_code = -ENODEV; + goto unlock; + } if (usbvision->user) { err_code = -EBUSY; } else { @@ -377,6 +381,7 @@ unlock: static int usbvision_v4l2_close(struct file *file) { struct usb_usbvision *usbvision = video_drvdata(file); + int r; PDEBUG(DBG_IO, "close"); @@ -391,9 +396,10 @@ static int usbvision_v4l2_close(struct file *file) usbvision_scratch_free(usbvision); usbvision->user--; + r = usbvision->remove_pending; mutex_unlock(&usbvision->v4l2_lock); - if (usbvision->remove_pending) { + if (r) { printk(KERN_INFO "%s: Final disconnect\n", __func__); usbvision_release(usbvision); return 0; @@ -453,6 +459,9 @@ static int vidioc_querycap(struct file *file, void *priv, { struct usb_usbvision *usbvision = video_drvdata(file); + if (!usbvision->dev) + return -ENODEV; + strscpy(vc->driver, "USBVision", sizeof(vc->driver)); strscpy(vc->card, usbvision_device_data[usbvision->dev_model].model_string, @@ -1061,6 +1070,11 @@ static int usbvision_radio_open(struct file *file) if (mutex_lock_interruptible(&usbvision->v4l2_lock)) return -ERESTARTSYS; + + if (usbvision->remove_pending) { + err_code = -ENODEV; + goto out; + } err_code = v4l2_fh_open(file); if (err_code) goto out; @@ -1093,21 +1107,24 @@ out: static int usbvision_radio_close(struct file *file) { struct usb_usbvision *usbvision = video_drvdata(file); + int r; PDEBUG(DBG_IO, ""); mutex_lock(&usbvision->v4l2_lock); /* Set packet size to 0 */ usbvision->iface_alt = 0; - usb_set_interface(usbvision->dev, usbvision->iface, - usbvision->iface_alt); + if (usbvision->dev) + usb_set_interface(usbvision->dev, usbvision->iface, + usbvision->iface_alt); usbvision_audio_off(usbvision); usbvision->radio = 0; usbvision->user--; + r = usbvision->remove_pending; mutex_unlock(&usbvision->v4l2_lock); - if (usbvision->remove_pending) { + if (r) { printk(KERN_INFO "%s: Final disconnect\n", __func__); v4l2_fh_release(file); usbvision_release(usbvision); @@ -1539,6 +1556,7 @@ err_usb: static void usbvision_disconnect(struct usb_interface *intf) { struct usb_usbvision *usbvision = to_usbvision(usb_get_intfdata(intf)); + int u; PDEBUG(DBG_PROBE, ""); @@ -1555,13 +1573,14 @@ static void usbvision_disconnect(struct usb_interface *intf) v4l2_device_disconnect(&usbvision->v4l2_dev); usbvision_i2c_unregister(usbvision); usbvision->remove_pending = 1; /* Now all ISO data will be ignored */ + u = usbvision->user; usb_put_dev(usbvision->dev); usbvision->dev = NULL; /* USB device is no more */ mutex_unlock(&usbvision->v4l2_lock); - if (usbvision->user) { + if (u) { printk(KERN_INFO "%s: In use, disconnect pending\n", __func__); wake_up_interruptible(&usbvision->wait_frame); diff --git a/drivers/media/usb/uvc/uvc_driver.c b/drivers/media/usb/uvc/uvc_driver.c index 66ee168ddc7e..428235ca2635 100644 --- a/drivers/media/usb/uvc/uvc_driver.c +++ b/drivers/media/usb/uvc/uvc_driver.c @@ -2151,6 +2151,20 @@ static int uvc_probe(struct usb_interface *intf, sizeof(dev->name) - len); } + /* Initialize the media device. */ +#ifdef CONFIG_MEDIA_CONTROLLER + dev->mdev.dev = &intf->dev; + strscpy(dev->mdev.model, dev->name, sizeof(dev->mdev.model)); + if (udev->serial) + strscpy(dev->mdev.serial, udev->serial, + sizeof(dev->mdev.serial)); + usb_make_path(udev, dev->mdev.bus_info, sizeof(dev->mdev.bus_info)); + dev->mdev.hw_revision = le16_to_cpu(udev->descriptor.bcdDevice); + media_device_init(&dev->mdev); + + dev->vdev.mdev = &dev->mdev; +#endif + /* Parse the Video Class control descriptor. */ if (uvc_parse_control(dev) < 0) { uvc_trace(UVC_TRACE_PROBE, "Unable to parse UVC " @@ -2171,19 +2185,7 @@ static int uvc_probe(struct usb_interface *intf, "linux-uvc-devel mailing list.\n"); } - /* Initialize the media device and register the V4L2 device. */ -#ifdef CONFIG_MEDIA_CONTROLLER - dev->mdev.dev = &intf->dev; - strscpy(dev->mdev.model, dev->name, sizeof(dev->mdev.model)); - if (udev->serial) - strscpy(dev->mdev.serial, udev->serial, - sizeof(dev->mdev.serial)); - usb_make_path(udev, dev->mdev.bus_info, sizeof(dev->mdev.bus_info)); - dev->mdev.hw_revision = le16_to_cpu(udev->descriptor.bcdDevice); - media_device_init(&dev->mdev); - - dev->vdev.mdev = &dev->mdev; -#endif + /* Register the V4L2 device. */ if (v4l2_device_register(&intf->dev, &dev->vdev) < 0) goto error; diff --git a/drivers/media/usb/uvc/uvc_metadata.c b/drivers/media/usb/uvc/uvc_metadata.c index 99bb71b47117..b6279ad7ac84 100644 --- a/drivers/media/usb/uvc/uvc_metadata.c +++ b/drivers/media/usb/uvc/uvc_metadata.c @@ -51,7 +51,7 @@ static int uvc_meta_v4l2_get_format(struct file *file, void *fh, memset(fmt, 0, sizeof(*fmt)); fmt->dataformat = stream->meta.format; - fmt->buffersize = UVC_METATADA_BUF_SIZE; + fmt->buffersize = UVC_METADATA_BUF_SIZE; return 0; } @@ -72,7 +72,7 @@ static int uvc_meta_v4l2_try_format(struct file *file, void *fh, fmt->dataformat = fmeta == dev->info->meta_format ? fmeta : V4L2_META_FMT_UVC; - fmt->buffersize = UVC_METATADA_BUF_SIZE; + fmt->buffersize = UVC_METADATA_BUF_SIZE; return 0; } diff --git a/drivers/media/usb/uvc/uvc_queue.c b/drivers/media/usb/uvc/uvc_queue.c index da72577c2998..cd60c6c1749e 100644 --- a/drivers/media/usb/uvc/uvc_queue.c +++ b/drivers/media/usb/uvc/uvc_queue.c @@ -79,7 +79,7 @@ static int uvc_queue_setup(struct vb2_queue *vq, switch (vq->type) { case V4L2_BUF_TYPE_META_CAPTURE: - size = UVC_METATADA_BUF_SIZE; + size = UVC_METADATA_BUF_SIZE; break; default: diff --git a/drivers/media/usb/uvc/uvcvideo.h b/drivers/media/usb/uvc/uvcvideo.h index c7c1baa90dea..f773dc5d802c 100644 --- a/drivers/media/usb/uvc/uvcvideo.h +++ b/drivers/media/usb/uvc/uvcvideo.h @@ -491,7 +491,7 @@ struct uvc_stats_stream { unsigned int max_sof; /* Maximum STC.SOF value */ }; -#define UVC_METATADA_BUF_SIZE 1024 +#define UVC_METADATA_BUF_SIZE 1024 /** * struct uvc_copy_op: Context structure to schedule asynchronous memcpy diff --git a/drivers/media/usb/zr364xx/zr364xx.c b/drivers/media/usb/zr364xx/zr364xx.c index 637962825d7a..57dbcc8083bf 100644 --- a/drivers/media/usb/zr364xx/zr364xx.c +++ b/drivers/media/usb/zr364xx/zr364xx.c @@ -20,7 +20,6 @@ #include <linux/usb.h> #include <linux/vmalloc.h> #include <linux/slab.h> -#include <linux/proc_fs.h> #include <linux/highmem.h> #include <media/v4l2-common.h> #include <media/v4l2-ioctl.h> @@ -556,14 +555,12 @@ static int zr364xx_read_video_callback(struct zr364xx_camera *cam, { unsigned char *pdest; unsigned char *psrc; - s32 idx = -1; - struct zr364xx_framei *frm; + s32 idx = cam->cur_frame; + struct zr364xx_framei *frm = &cam->buffer.frame[idx]; int i = 0; unsigned char *ptr = NULL; _DBG("buffer to user\n"); - idx = cam->cur_frame; - frm = &cam->buffer.frame[idx]; /* swap bytes if camera needs it */ if (cam->method == METHOD0) { |