diff options
Diffstat (limited to 'drivers/media/common')
-rw-r--r-- | drivers/media/common/btcx-risc.h | 29 | ||||
-rw-r--r-- | drivers/media/common/saa7146/Kconfig | 2 | ||||
-rw-r--r-- | drivers/media/common/saa7146/saa7146_core.c | 40 | ||||
-rw-r--r-- | drivers/media/common/saa7146/saa7146_fops.c | 373 | ||||
-rw-r--r-- | drivers/media/common/saa7146/saa7146_hlp.c | 355 | ||||
-rw-r--r-- | drivers/media/common/saa7146/saa7146_vbi.c | 287 | ||||
-rw-r--r-- | drivers/media/common/saa7146/saa7146_video.c | 959 | ||||
-rw-r--r-- | drivers/media/common/videobuf2/videobuf2-v4l2.c | 5 |
8 files changed, 450 insertions, 1600 deletions
diff --git a/drivers/media/common/btcx-risc.h b/drivers/media/common/btcx-risc.h deleted file mode 100644 index 76dc16f402b9..000000000000 --- a/drivers/media/common/btcx-risc.h +++ /dev/null @@ -1,29 +0,0 @@ -/* SPDX-License-Identifier: GPL-2.0 */ -/* - */ -struct btcx_riscmem { - unsigned int size; - __le32 *cpu; - __le32 *jmp; - dma_addr_t dma; -}; - -struct btcx_skiplist { - int start; - int end; -}; - -int btcx_riscmem_alloc(struct pci_dev *pci, - struct btcx_riscmem *risc, - unsigned int size); -void btcx_riscmem_free(struct pci_dev *pci, - struct btcx_riscmem *risc); - -int btcx_screen_clips(int swidth, int sheight, struct v4l2_rect *win, - struct v4l2_clip *clips, unsigned int n); -int btcx_align(struct v4l2_rect *win, struct v4l2_clip *clips, - unsigned int n, int mask); -void btcx_sort_clips(struct v4l2_clip *clips, unsigned int nclips); -void btcx_calc_skips(int line, int width, int *maxy, - struct btcx_skiplist *skips, unsigned int *nskips, - const struct v4l2_clip *clips, unsigned int nclips); diff --git a/drivers/media/common/saa7146/Kconfig b/drivers/media/common/saa7146/Kconfig index a0aa155e5d85..dfec86e50dff 100644 --- a/drivers/media/common/saa7146/Kconfig +++ b/drivers/media/common/saa7146/Kconfig @@ -6,5 +6,5 @@ config VIDEO_SAA7146 config VIDEO_SAA7146_VV tristate depends on VIDEO_DEV - select VIDEOBUF_DMA_SG + select VIDEOBUF2_DMA_SG select VIDEO_SAA7146 diff --git a/drivers/media/common/saa7146/saa7146_core.c b/drivers/media/common/saa7146/saa7146_core.c index e50fa0ff7c5d..bcb957883044 100644 --- a/drivers/media/common/saa7146/saa7146_core.c +++ b/drivers/media/common/saa7146/saa7146_core.c @@ -37,7 +37,8 @@ void saa7146_setgpio(struct saa7146_dev *dev, int port, u32 data) { u32 value = 0; - BUG_ON(port > 3); + if (WARN_ON(port > 3)) + return; value = saa7146_read(dev, GPIO_CTRL); value &= ~(0xff << (8*port)); @@ -148,7 +149,8 @@ static struct scatterlist* vmalloc_to_sg(unsigned char *virt, int nr_pages) pg = vmalloc_to_page(virt); if (NULL == pg) goto err; - BUG_ON(PageHighMem(pg)); + if (WARN_ON(PageHighMem(pg))) + return NULL; sg_set_page(&sglist[i], pg, PAGE_SIZE, 0); } return sglist; @@ -233,46 +235,32 @@ int saa7146_pgtable_alloc(struct pci_dev *pci, struct saa7146_pgtable *pt) } int saa7146_pgtable_build_single(struct pci_dev *pci, struct saa7146_pgtable *pt, - struct scatterlist *list, int sglen ) + struct scatterlist *list, int sglen) { + struct sg_dma_page_iter dma_iter; __le32 *ptr, fill; int nr_pages = 0; - int i,p; + int i; - BUG_ON(0 == sglen); - BUG_ON(list->offset > PAGE_SIZE); + if (WARN_ON(!sglen) || + WARN_ON(list->offset > PAGE_SIZE)) + return -EIO; /* if we have a user buffer, the first page may not be aligned to a page boundary. */ pt->offset = list->offset; ptr = pt->cpu; - for (i = 0; i < sglen; i++, list++) { -/* - pr_debug("i:%d, adr:0x%08x, len:%d, offset:%d\n", - i, sg_dma_address(list), sg_dma_len(list), - list->offset); -*/ - for (p = 0; p * 4096 < sg_dma_len(list); p++, ptr++) { - *ptr = cpu_to_le32(sg_dma_address(list) + p * 4096); - nr_pages++; - } + for_each_sg_dma_page(list, &dma_iter, sglen, 0) { + *ptr++ = cpu_to_le32(sg_page_iter_dma_address(&dma_iter)); + nr_pages++; } /* safety; fill the page table up with the last valid page */ fill = *(ptr-1); - for(i=nr_pages;i<1024;i++) { + for (i = nr_pages; i < 1024; i++) *ptr++ = fill; - } - -/* - ptr = pt->cpu; - pr_debug("offset: %d\n", pt->offset); - for(i=0;i<5;i++) { - pr_debug("ptr1 %d: 0x%08x\n", i, ptr[i]); - } -*/ return 0; } diff --git a/drivers/media/common/saa7146/saa7146_fops.c b/drivers/media/common/saa7146/saa7146_fops.c index e9a15de6126e..79214459387a 100644 --- a/drivers/media/common/saa7146/saa7146_fops.c +++ b/drivers/media/common/saa7146/saa7146_fops.c @@ -7,12 +7,11 @@ /****************************************************************************/ /* resource management functions, shamelessly stolen from saa7134 driver */ -int saa7146_res_get(struct saa7146_fh *fh, unsigned int bit) +int saa7146_res_get(struct saa7146_dev *dev, unsigned int bit) { - struct saa7146_dev *dev = fh->dev; struct saa7146_vv *vv = dev->vv_data; - if (fh->resources & bit) { + if (vv->resources & bit) { DEB_D("already allocated! want: 0x%02x, cur:0x%02x\n", bit, vv->resources); /* have it already allocated */ @@ -27,42 +26,23 @@ int saa7146_res_get(struct saa7146_fh *fh, unsigned int bit) return 0; } /* it's free, grab it */ - fh->resources |= bit; vv->resources |= bit; DEB_D("res: get 0x%02x, cur:0x%02x\n", bit, vv->resources); return 1; } -void saa7146_res_free(struct saa7146_fh *fh, unsigned int bits) +void saa7146_res_free(struct saa7146_dev *dev, unsigned int bits) { - struct saa7146_dev *dev = fh->dev; struct saa7146_vv *vv = dev->vv_data; - BUG_ON((fh->resources & bits) != bits); + WARN_ON((vv->resources & bits) != bits); - fh->resources &= ~bits; vv->resources &= ~bits; DEB_D("res: put 0x%02x, cur:0x%02x\n", bits, vv->resources); } /********************************************************************************/ -/* common dma functions */ - -void saa7146_dma_free(struct saa7146_dev *dev,struct videobuf_queue *q, - struct saa7146_buf *buf) -{ - struct videobuf_dmabuf *dma=videobuf_to_dma(&buf->vb); - DEB_EE("dev:%p, buf:%p\n", dev, buf); - - videobuf_waiton(q, &buf->vb, 0, 0); - videobuf_dma_unmap(q->dev, dma); - videobuf_dma_free(dma); - buf->vb.state = VIDEOBUF_NEEDS_INIT; -} - - -/********************************************************************************/ /* common buffer functions */ int saa7146_buffer_queue(struct saa7146_dev *dev, @@ -72,15 +52,15 @@ int saa7146_buffer_queue(struct saa7146_dev *dev, assert_spin_locked(&dev->slock); DEB_EE("dev:%p, dmaq:%p, buf:%p\n", dev, q, buf); - BUG_ON(!q); + if (WARN_ON(!q)) + return -EIO; if (NULL == q->curr) { q->curr = buf; DEB_D("immediately activating buffer %p\n", buf); buf->activate(dev,buf,NULL); } else { - list_add_tail(&buf->vb.queue,&q->queue); - buf->vb.state = VIDEOBUF_QUEUED; + list_add_tail(&buf->list, &q->queue); DEB_D("adding buffer %p to queue. (active buffer present)\n", buf); } @@ -91,21 +71,31 @@ void saa7146_buffer_finish(struct saa7146_dev *dev, struct saa7146_dmaqueue *q, int state) { + struct saa7146_vv *vv = dev->vv_data; + struct saa7146_buf *buf = q->curr; + assert_spin_locked(&dev->slock); DEB_EE("dev:%p, dmaq:%p, state:%d\n", dev, q, state); DEB_EE("q->curr:%p\n", q->curr); /* finish current buffer */ - if (NULL == q->curr) { + if (!buf) { DEB_D("aiii. no current buffer\n"); return; } - q->curr->vb.state = state; - q->curr->vb.ts = ktime_get_ns(); - wake_up(&q->curr->vb.done); - q->curr = NULL; + buf->vb.vb2_buf.timestamp = ktime_get_ns(); + if (vv->video_fmt.field == V4L2_FIELD_ALTERNATE) + buf->vb.field = vv->last_field; + else if (vv->video_fmt.field == V4L2_FIELD_ANY) + buf->vb.field = (vv->video_fmt.height > vv->standard->v_max_out / 2) + ? V4L2_FIELD_INTERLACED + : V4L2_FIELD_BOTTOM; + else + buf->vb.field = vv->video_fmt.field; + buf->vb.sequence = vv->seqnr++; + vb2_buffer_done(&buf->vb.vb2_buf, state); } void saa7146_buffer_next(struct saa7146_dev *dev, @@ -113,17 +103,18 @@ void saa7146_buffer_next(struct saa7146_dev *dev, { struct saa7146_buf *buf,*next = NULL; - BUG_ON(!q); + if (WARN_ON(!q)) + return; DEB_INT("dev:%p, dmaq:%p, vbi:%d\n", dev, q, vbi); assert_spin_locked(&dev->slock); if (!list_empty(&q->queue)) { /* activate next one from queue */ - buf = list_entry(q->queue.next,struct saa7146_buf,vb.queue); - list_del(&buf->vb.queue); + buf = list_entry(q->queue.next, struct saa7146_buf, list); + list_del(&buf->list); if (!list_empty(&q->queue)) - next = list_entry(q->queue.next,struct saa7146_buf, vb.queue); + next = list_entry(q->queue.next, struct saa7146_buf, list); q->curr = buf; DEB_INT("next buffer: buf:%p, prev:%p, next:%p\n", buf, q->queue.prev, q->queue.next); @@ -171,7 +162,7 @@ void saa7146_buffer_timeout(struct timer_list *t) spin_lock_irqsave(&dev->slock,flags); if (q->curr) { DEB_D("timeout on %p\n", q->curr); - saa7146_buffer_finish(dev,q,VIDEOBUF_ERROR); + saa7146_buffer_finish(dev, q, VB2_BUF_STATE_ERROR); } /* we don't restart the transfer here like other drivers do. when @@ -180,256 +171,39 @@ void saa7146_buffer_timeout(struct timer_list *t) we mess up our capture logic. if a timeout occurs on another buffer, then something is seriously broken before, so no need to buffer the next capture IMHO... */ -/* - saa7146_buffer_next(dev,q); -*/ + + saa7146_buffer_next(dev, q, 0); + spin_unlock_irqrestore(&dev->slock,flags); } /********************************************************************************/ /* file operations */ -static int fops_open(struct file *file) +static ssize_t fops_write(struct file *file, const char __user *data, size_t count, loff_t *ppos) { struct video_device *vdev = video_devdata(file); struct saa7146_dev *dev = video_drvdata(file); - struct saa7146_fh *fh = NULL; - int result = 0; - - DEB_EE("file:%p, dev:%s\n", file, video_device_node_name(vdev)); - - if (mutex_lock_interruptible(vdev->lock)) - return -ERESTARTSYS; - - DEB_D("using: %p\n", dev); - - /* check if an extension is registered */ - if( NULL == dev->ext ) { - DEB_S("no extension registered for this device\n"); - result = -ENODEV; - goto out; - } - - /* allocate per open data */ - fh = kzalloc(sizeof(*fh),GFP_KERNEL); - if (NULL == fh) { - DEB_S("cannot allocate memory for per open data\n"); - result = -ENOMEM; - goto out; - } - - v4l2_fh_init(&fh->fh, vdev); - - file->private_data = &fh->fh; - fh->dev = dev; - - if (vdev->vfl_type == VFL_TYPE_VBI) { - DEB_S("initializing vbi...\n"); - if (dev->ext_vv_data->capabilities & V4L2_CAP_VBI_CAPTURE) - result = saa7146_vbi_uops.open(dev,file); - if (dev->ext_vv_data->vbi_fops.open) - dev->ext_vv_data->vbi_fops.open(file); - } else { - DEB_S("initializing video...\n"); - result = saa7146_video_uops.open(dev,file); - } - - if (0 != result) { - goto out; - } - - if( 0 == try_module_get(dev->ext->module)) { - result = -EINVAL; - goto out; - } - - result = 0; - v4l2_fh_add(&fh->fh); -out: - if (fh && result != 0) { - kfree(fh); - file->private_data = NULL; - } - mutex_unlock(vdev->lock); - return result; -} - -static int fops_release(struct file *file) -{ - struct video_device *vdev = video_devdata(file); - struct saa7146_fh *fh = file->private_data; - struct saa7146_dev *dev = fh->dev; - - DEB_EE("file:%p\n", file); - - mutex_lock(vdev->lock); - - if (vdev->vfl_type == VFL_TYPE_VBI) { - if (dev->ext_vv_data->capabilities & V4L2_CAP_VBI_CAPTURE) - saa7146_vbi_uops.release(dev,file); - if (dev->ext_vv_data->vbi_fops.release) - dev->ext_vv_data->vbi_fops.release(file); - } else { - saa7146_video_uops.release(dev,file); - } - - v4l2_fh_del(&fh->fh); - v4l2_fh_exit(&fh->fh); - module_put(dev->ext->module); - file->private_data = NULL; - kfree(fh); - - mutex_unlock(vdev->lock); - - return 0; -} - -static int fops_mmap(struct file *file, struct vm_area_struct * vma) -{ - struct video_device *vdev = video_devdata(file); - struct saa7146_fh *fh = file->private_data; - struct videobuf_queue *q; - int res; - - switch (vdev->vfl_type) { - case VFL_TYPE_VIDEO: { - DEB_EE("V4L2_BUF_TYPE_VIDEO_CAPTURE: file:%p, vma:%p\n", - file, vma); - q = &fh->video_q; - break; - } - case VFL_TYPE_VBI: { - DEB_EE("V4L2_BUF_TYPE_VBI_CAPTURE: file:%p, vma:%p\n", - file, vma); - if (fh->dev->ext_vv_data->capabilities & V4L2_CAP_SLICED_VBI_OUTPUT) - return -ENODEV; - q = &fh->vbi_q; - break; - } - default: - BUG(); - } + int ret; + if (vdev->vfl_type != VFL_TYPE_VBI || !dev->ext_vv_data->vbi_fops.write) + return -EINVAL; if (mutex_lock_interruptible(vdev->lock)) return -ERESTARTSYS; - res = videobuf_mmap_mapper(q, vma); + ret = dev->ext_vv_data->vbi_fops.write(file, data, count, ppos); mutex_unlock(vdev->lock); - return res; -} - -static __poll_t __fops_poll(struct file *file, struct poll_table_struct *wait) -{ - struct video_device *vdev = video_devdata(file); - struct saa7146_fh *fh = file->private_data; - struct videobuf_buffer *buf = NULL; - struct videobuf_queue *q; - __poll_t res = v4l2_ctrl_poll(file, wait); - - DEB_EE("file:%p, poll:%p\n", file, wait); - - if (vdev->vfl_type == VFL_TYPE_VBI) { - if (fh->dev->ext_vv_data->capabilities & V4L2_CAP_SLICED_VBI_OUTPUT) - return res | EPOLLOUT | EPOLLWRNORM; - if( 0 == fh->vbi_q.streaming ) - return res | videobuf_poll_stream(file, &fh->vbi_q, wait); - q = &fh->vbi_q; - } else { - DEB_D("using video queue\n"); - q = &fh->video_q; - } - - if (!list_empty(&q->stream)) - buf = list_entry(q->stream.next, struct videobuf_buffer, stream); - - if (!buf) { - DEB_D("buf == NULL!\n"); - return res | EPOLLERR; - } - - poll_wait(file, &buf->done, wait); - if (buf->state == VIDEOBUF_DONE || buf->state == VIDEOBUF_ERROR) { - DEB_D("poll succeeded!\n"); - return res | EPOLLIN | EPOLLRDNORM; - } - - DEB_D("nothing to poll for, buf->state:%d\n", buf->state); - return res; -} - -static __poll_t fops_poll(struct file *file, struct poll_table_struct *wait) -{ - struct video_device *vdev = video_devdata(file); - __poll_t res; - - mutex_lock(vdev->lock); - res = __fops_poll(file, wait); - mutex_unlock(vdev->lock); - return res; -} - -static ssize_t fops_read(struct file *file, char __user *data, size_t count, loff_t *ppos) -{ - struct video_device *vdev = video_devdata(file); - struct saa7146_fh *fh = file->private_data; - int ret; - - switch (vdev->vfl_type) { - case VFL_TYPE_VIDEO: -/* - DEB_EE("V4L2_BUF_TYPE_VIDEO_CAPTURE: file:%p, data:%p, count:%lun", - file, data, (unsigned long)count); -*/ - return saa7146_video_uops.read(file,data,count,ppos); - case VFL_TYPE_VBI: -/* - DEB_EE("V4L2_BUF_TYPE_VBI_CAPTURE: file:%p, data:%p, count:%lu\n", - file, data, (unsigned long)count); -*/ - if (fh->dev->ext_vv_data->capabilities & V4L2_CAP_VBI_CAPTURE) { - if (mutex_lock_interruptible(vdev->lock)) - return -ERESTARTSYS; - ret = saa7146_vbi_uops.read(file, data, count, ppos); - mutex_unlock(vdev->lock); - return ret; - } - return -EINVAL; - default: - BUG(); - } -} - -static ssize_t fops_write(struct file *file, const char __user *data, size_t count, loff_t *ppos) -{ - struct video_device *vdev = video_devdata(file); - struct saa7146_fh *fh = file->private_data; - int ret; - - switch (vdev->vfl_type) { - case VFL_TYPE_VIDEO: - return -EINVAL; - case VFL_TYPE_VBI: - if (fh->dev->ext_vv_data->vbi_fops.write) { - if (mutex_lock_interruptible(vdev->lock)) - return -ERESTARTSYS; - ret = fh->dev->ext_vv_data->vbi_fops.write(file, data, count, ppos); - mutex_unlock(vdev->lock); - return ret; - } - return -EINVAL; - default: - BUG(); - } + return ret; } static const struct v4l2_file_operations video_fops = { .owner = THIS_MODULE, - .open = fops_open, - .release = fops_release, - .read = fops_read, + .open = v4l2_fh_open, + .release = vb2_fop_release, + .read = vb2_fop_read, .write = fops_write, - .poll = fops_poll, - .mmap = fops_mmap, + .poll = vb2_fop_poll, + .mmap = vb2_fop_mmap, .unlocked_ioctl = video_ioctl2, }; @@ -516,33 +290,15 @@ int saa7146_vv_init(struct saa7146_dev* dev, struct saa7146_ext_vv *ext_vv) configuration data) */ dev->ext_vv_data = ext_vv; - vv->d_clipping.cpu_addr = - dma_alloc_coherent(&dev->pci->dev, SAA7146_CLIPPING_MEM, - &vv->d_clipping.dma_handle, GFP_KERNEL); - if( NULL == vv->d_clipping.cpu_addr ) { - ERR("out of memory. aborting.\n"); - kfree(vv); - v4l2_ctrl_handler_free(hdl); - v4l2_device_unregister(&dev->v4l2_dev); - return -ENOMEM; - } - saa7146_video_uops.init(dev,vv); if (dev->ext_vv_data->capabilities & V4L2_CAP_VBI_CAPTURE) saa7146_vbi_uops.init(dev,vv); - vv->ov_fb.fmt.width = vv->standard->h_max_out; - vv->ov_fb.fmt.height = vv->standard->v_max_out; - vv->ov_fb.fmt.pixelformat = V4L2_PIX_FMT_RGB565; - vv->ov_fb.fmt.bytesperline = 2 * vv->ov_fb.fmt.width; - vv->ov_fb.fmt.sizeimage = vv->ov_fb.fmt.bytesperline * vv->ov_fb.fmt.height; - vv->ov_fb.fmt.colorspace = V4L2_COLORSPACE_SRGB; - fmt = &vv->video_fmt; fmt->width = 384; fmt->height = 288; fmt->pixelformat = V4L2_PIX_FMT_BGR24; - fmt->field = V4L2_FIELD_ANY; + fmt->field = V4L2_FIELD_INTERLACED; fmt->colorspace = V4L2_COLORSPACE_SMPTE170M; fmt->bytesperline = 3 * fmt->width; fmt->sizeimage = fmt->bytesperline * fmt->height; @@ -561,8 +317,6 @@ int saa7146_vv_init(struct saa7146_dev* dev, struct saa7146_ext_vv *ext_vv) timer_setup(&vv->vbi_read_timeout, NULL, 0); - vv->ov_fb.capability = V4L2_FBUF_CAP_LIST_CLIPPING; - vv->ov_fb.flags = V4L2_FBUF_FLAG_PRIMARY; dev->vv_data = vv; dev->vv_callback = &vv_callback; @@ -577,8 +331,6 @@ int saa7146_vv_release(struct saa7146_dev* dev) DEB_EE("dev:%p\n", dev); v4l2_device_unregister(&dev->v4l2_dev); - dma_free_coherent(&dev->pci->dev, SAA7146_CLIPPING_MEM, - vv->d_clipping.cpu_addr, vv->d_clipping.dma_handle); v4l2_ctrl_handler_free(&dev->ctrl_handler); kfree(vv); dev->vv_data = NULL; @@ -591,16 +343,20 @@ EXPORT_SYMBOL_GPL(saa7146_vv_release); int saa7146_register_device(struct video_device *vfd, struct saa7146_dev *dev, char *name, int type) { + struct vb2_queue *q; int err; int i; DEB_EE("dev:%p, name:'%s', type:%d\n", dev, name, type); vfd->fops = &video_fops; - if (type == VFL_TYPE_VIDEO) + if (type == VFL_TYPE_VIDEO) { vfd->ioctl_ops = &dev->ext_vv_data->vid_ops; - else + q = &dev->vv_data->video_dmaq.q; + } else { vfd->ioctl_ops = &dev->ext_vv_data->vbi_ops; + q = &dev->vv_data->vbi_dmaq.q; + } vfd->release = video_device_release_empty; vfd->lock = &dev->v4l2_lock; vfd->v4l2_dev = &dev->v4l2_dev; @@ -608,15 +364,36 @@ int saa7146_register_device(struct video_device *vfd, struct saa7146_dev *dev, for (i = 0; i < dev->ext_vv_data->num_stds; i++) vfd->tvnorms |= dev->ext_vv_data->stds[i].id; strscpy(vfd->name, name, sizeof(vfd->name)); - vfd->device_caps = V4L2_CAP_VIDEO_CAPTURE | V4L2_CAP_VIDEO_OVERLAY | + vfd->device_caps = V4L2_CAP_VIDEO_CAPTURE | V4L2_CAP_READWRITE | V4L2_CAP_STREAMING; vfd->device_caps |= dev->ext_vv_data->capabilities; - if (type == VFL_TYPE_VIDEO) + if (type == VFL_TYPE_VIDEO) { vfd->device_caps &= ~(V4L2_CAP_VBI_CAPTURE | V4L2_CAP_SLICED_VBI_OUTPUT); - else - vfd->device_caps &= - ~(V4L2_CAP_VIDEO_CAPTURE | V4L2_CAP_VIDEO_OVERLAY | V4L2_CAP_AUDIO); + } else if (vfd->device_caps & V4L2_CAP_SLICED_VBI_OUTPUT) { + vfd->vfl_dir = VFL_DIR_TX; + vfd->device_caps &= ~(V4L2_CAP_VIDEO_CAPTURE | V4L2_CAP_STREAMING | + V4L2_CAP_AUDIO | V4L2_CAP_TUNER); + } else { + vfd->device_caps &= ~V4L2_CAP_VIDEO_CAPTURE; + } + + q->type = type == VFL_TYPE_VIDEO ? V4L2_BUF_TYPE_VIDEO_CAPTURE : V4L2_BUF_TYPE_VBI_CAPTURE; + q->timestamp_flags = V4L2_BUF_FLAG_TIMESTAMP_MONOTONIC; + q->io_modes = VB2_MMAP | VB2_READ | VB2_DMABUF; + q->ops = type == VFL_TYPE_VIDEO ? &video_qops : &vbi_qops; + q->mem_ops = &vb2_dma_sg_memops; + q->drv_priv = dev; + q->gfp_flags = __GFP_DMA32; + q->buf_struct_size = sizeof(struct saa7146_buf); + q->lock = &dev->v4l2_lock; + q->min_buffers_needed = 2; + q->dev = &dev->pci->dev; + err = vb2_queue_init(q); + if (err) + return err; + vfd->queue = q; + video_set_drvdata(vfd, dev); err = video_register_device(vfd, type, -1); diff --git a/drivers/media/common/saa7146/saa7146_hlp.c b/drivers/media/common/saa7146/saa7146_hlp.c index 6c9946a402ee..7569d8cdd4d8 100644 --- a/drivers/media/common/saa7146/saa7146_hlp.c +++ b/drivers/media/common/saa7146/saa7146_hlp.c @@ -306,221 +306,6 @@ static int calculate_v_scale_registers(struct saa7146_dev *dev, enum v4l2_field } /* simple bubble-sort algorithm with duplicate elimination */ -static int sort_and_eliminate(u32* values, int* count) -{ - int low = 0, high = 0, top = 0; - int cur = 0, next = 0; - - /* sanity checks */ - if( (0 > *count) || (NULL == values) ) { - return -EINVAL; - } - - /* bubble sort the first @count items of the array @values */ - for( top = *count; top > 0; top--) { - for( low = 0, high = 1; high < top; low++, high++) { - if( values[low] > values[high] ) - swap(values[low], values[high]); - } - } - - /* remove duplicate items */ - for( cur = 0, next = 1; next < *count; next++) { - if( values[cur] != values[next]) - values[++cur] = values[next]; - } - - *count = cur + 1; - - return 0; -} - -static void calculate_clipping_registers_rect(struct saa7146_dev *dev, struct saa7146_fh *fh, - struct saa7146_video_dma *vdma2, u32* clip_format, u32* arbtr_ctrl, enum v4l2_field field) -{ - struct saa7146_vv *vv = dev->vv_data; - __le32 *clipping = vv->d_clipping.cpu_addr; - - int width = vv->ov.win.w.width; - int height = vv->ov.win.w.height; - int clipcount = vv->ov.nclips; - - u32 line_list[32]; - u32 pixel_list[32]; - int numdwords = 0; - - int i = 0, j = 0; - int cnt_line = 0, cnt_pixel = 0; - - int x[32], y[32], w[32], h[32]; - - /* clear out memory */ - memset(&line_list[0], 0x00, sizeof(u32)*32); - memset(&pixel_list[0], 0x00, sizeof(u32)*32); - memset(clipping, 0x00, SAA7146_CLIPPING_MEM); - - /* fill the line and pixel-lists */ - for(i = 0; i < clipcount; i++) { - int l = 0, r = 0, t = 0, b = 0; - - x[i] = vv->ov.clips[i].c.left; - y[i] = vv->ov.clips[i].c.top; - w[i] = vv->ov.clips[i].c.width; - h[i] = vv->ov.clips[i].c.height; - - if( w[i] < 0) { - x[i] += w[i]; w[i] = -w[i]; - } - if( h[i] < 0) { - y[i] += h[i]; h[i] = -h[i]; - } - if( x[i] < 0) { - w[i] += x[i]; x[i] = 0; - } - if( y[i] < 0) { - h[i] += y[i]; y[i] = 0; - } - if( 0 != vv->vflip ) { - y[i] = height - y[i] - h[i]; - } - - l = x[i]; - r = x[i]+w[i]; - t = y[i]; - b = y[i]+h[i]; - - /* insert left/right coordinates */ - pixel_list[ 2*i ] = min_t(int, l, width); - pixel_list[(2*i)+1] = min_t(int, r, width); - /* insert top/bottom coordinates */ - line_list[ 2*i ] = min_t(int, t, height); - line_list[(2*i)+1] = min_t(int, b, height); - } - - /* sort and eliminate lists */ - cnt_line = cnt_pixel = 2*clipcount; - sort_and_eliminate( &pixel_list[0], &cnt_pixel ); - sort_and_eliminate( &line_list[0], &cnt_line ); - - /* calculate the number of used u32s */ - numdwords = max_t(int, (cnt_line+1), (cnt_pixel+1))*2; - numdwords = max_t(int, 4, numdwords); - numdwords = min_t(int, 64, numdwords); - - /* fill up cliptable */ - for(i = 0; i < cnt_pixel; i++) { - clipping[2*i] |= cpu_to_le32(pixel_list[i] << 16); - } - for(i = 0; i < cnt_line; i++) { - clipping[(2*i)+1] |= cpu_to_le32(line_list[i] << 16); - } - - /* fill up cliptable with the display infos */ - for(j = 0; j < clipcount; j++) { - - for(i = 0; i < cnt_pixel; i++) { - - if( x[j] < 0) - x[j] = 0; - - if( pixel_list[i] < (x[j] + w[j])) { - - if ( pixel_list[i] >= x[j] ) { - clipping[2*i] |= cpu_to_le32(1 << j); - } - } - } - for(i = 0; i < cnt_line; i++) { - - if( y[j] < 0) - y[j] = 0; - - if( line_list[i] < (y[j] + h[j]) ) { - - if( line_list[i] >= y[j] ) { - clipping[(2*i)+1] |= cpu_to_le32(1 << j); - } - } - } - } - - /* adjust arbitration control register */ - *arbtr_ctrl &= 0xffff00ff; - *arbtr_ctrl |= 0x00001c00; - - vdma2->base_even = vv->d_clipping.dma_handle; - vdma2->base_odd = vv->d_clipping.dma_handle; - vdma2->prot_addr = vv->d_clipping.dma_handle+((sizeof(u32))*(numdwords)); - vdma2->base_page = 0x04; - vdma2->pitch = 0x00; - vdma2->num_line_byte = (0 << 16 | (sizeof(u32))*(numdwords-1) ); - - /* set clipping-mode. this depends on the field(s) used */ - *clip_format &= 0xfffffff7; - if (V4L2_FIELD_HAS_BOTH(field)) { - *clip_format |= 0x00000008; - } else { - *clip_format |= 0x00000000; - } -} - -/* disable clipping */ -static void saa7146_disable_clipping(struct saa7146_dev *dev) -{ - u32 clip_format = saa7146_read(dev, CLIP_FORMAT_CTRL); - - /* mask out relevant bits (=lower word)*/ - clip_format &= MASK_W1; - - /* upload clipping-registers*/ - saa7146_write(dev, CLIP_FORMAT_CTRL,clip_format); - saa7146_write(dev, MC2, (MASK_05 | MASK_21)); - - /* disable video dma2 */ - saa7146_write(dev, MC1, MASK_21); -} - -static void saa7146_set_clipping_rect(struct saa7146_fh *fh) -{ - struct saa7146_dev *dev = fh->dev; - struct saa7146_vv *vv = dev->vv_data; - enum v4l2_field field = vv->ov.win.field; - struct saa7146_video_dma vdma2; - u32 clip_format; - u32 arbtr_ctrl; - - /* check clipcount, disable clipping if clipcount == 0*/ - if (vv->ov.nclips == 0) { - saa7146_disable_clipping(dev); - return; - } - - clip_format = saa7146_read(dev, CLIP_FORMAT_CTRL); - arbtr_ctrl = saa7146_read(dev, PCI_BT_V1); - - calculate_clipping_registers_rect(dev, fh, &vdma2, &clip_format, &arbtr_ctrl, field); - - /* set clipping format */ - clip_format &= 0xffff0008; - clip_format |= (SAA7146_CLIPPING_RECT << 4); - - /* prepare video dma2 */ - saa7146_write(dev, BASE_EVEN2, vdma2.base_even); - saa7146_write(dev, BASE_ODD2, vdma2.base_odd); - saa7146_write(dev, PROT_ADDR2, vdma2.prot_addr); - saa7146_write(dev, BASE_PAGE2, vdma2.base_page); - saa7146_write(dev, PITCH2, vdma2.pitch); - saa7146_write(dev, NUM_LINE_BYTE2, vdma2.num_line_byte); - - /* prepare the rest */ - saa7146_write(dev, CLIP_FORMAT_CTRL,clip_format); - saa7146_write(dev, PCI_BT_V1, arbtr_ctrl); - - /* upload clip_control-register, clipping-registers, enable video dma2 */ - saa7146_write(dev, MC2, (MASK_05 | MASK_21 | MASK_03 | MASK_19)); - saa7146_write(dev, MC1, (MASK_05 | MASK_21)); -} - static void saa7146_set_window(struct saa7146_dev *dev, int width, int height, enum v4l2_field field) { struct saa7146_vv *vv = dev->vv_data; @@ -556,62 +341,6 @@ static void saa7146_set_window(struct saa7146_dev *dev, int width, int height, e saa7146_write(dev, MC2, (MASK_05 | MASK_06 | MASK_21 | MASK_22) ); } -/* calculate the new memory offsets for a desired position */ -static void saa7146_set_position(struct saa7146_dev *dev, int w_x, int w_y, int w_height, enum v4l2_field field, u32 pixelformat) -{ - struct saa7146_vv *vv = dev->vv_data; - struct saa7146_format *sfmt = saa7146_format_by_fourcc(dev, pixelformat); - - int b_depth = vv->ov_fmt->depth; - int b_bpl = vv->ov_fb.fmt.bytesperline; - /* The unsigned long cast is to remove a 64-bit compile warning since - it looks like a 64-bit address is cast to a 32-bit value, even - though the base pointer is really a 32-bit physical address that - goes into a 32-bit DMA register. - FIXME: might not work on some 64-bit platforms, but see the FIXME - in struct v4l2_framebuffer (videodev2.h) for that. - */ - u32 base = (u32)(unsigned long)vv->ov_fb.base; - - struct saa7146_video_dma vdma1; - - /* calculate memory offsets for picture, look if we shall top-down-flip */ - vdma1.pitch = 2*b_bpl; - if ( 0 == vv->vflip ) { - vdma1.base_even = base + (w_y * (vdma1.pitch/2)) + (w_x * (b_depth / 8)); - vdma1.base_odd = vdma1.base_even + (vdma1.pitch / 2); - vdma1.prot_addr = vdma1.base_even + (w_height * (vdma1.pitch / 2)); - } - else { - vdma1.base_even = base + ((w_y+w_height) * (vdma1.pitch/2)) + (w_x * (b_depth / 8)); - vdma1.base_odd = vdma1.base_even - (vdma1.pitch / 2); - vdma1.prot_addr = vdma1.base_odd - (w_height * (vdma1.pitch / 2)); - } - - if (V4L2_FIELD_HAS_BOTH(field)) { - } else if (field == V4L2_FIELD_ALTERNATE) { - /* fixme */ - vdma1.base_odd = vdma1.prot_addr; - vdma1.pitch /= 2; - } else if (field == V4L2_FIELD_TOP) { - vdma1.base_odd = vdma1.prot_addr; - vdma1.pitch /= 2; - } else if (field == V4L2_FIELD_BOTTOM) { - vdma1.base_odd = vdma1.base_even; - vdma1.base_even = vdma1.prot_addr; - vdma1.pitch /= 2; - } - - if ( 0 != vv->vflip ) { - vdma1.pitch *= -1; - } - - vdma1.base_page = sfmt->swap; - vdma1.num_line_byte = (vv->standard->v_field<<16)+vv->standard->h_pixels; - - saa7146_write_out_dma(dev, 1, &vdma1); -} - static void saa7146_set_output_format(struct saa7146_dev *dev, unsigned long palette) { u32 clip_format = saa7146_read(dev, CLIP_FORMAT_CTRL); @@ -645,30 +374,6 @@ void saa7146_set_hps_source_and_sync(struct saa7146_dev *dev, int source, int sy } EXPORT_SYMBOL_GPL(saa7146_set_hps_source_and_sync); -int saa7146_enable_overlay(struct saa7146_fh *fh) -{ - struct saa7146_dev *dev = fh->dev; - struct saa7146_vv *vv = dev->vv_data; - - saa7146_set_window(dev, vv->ov.win.w.width, vv->ov.win.w.height, vv->ov.win.field); - saa7146_set_position(dev, vv->ov.win.w.left, vv->ov.win.w.top, vv->ov.win.w.height, vv->ov.win.field, vv->ov_fmt->pixelformat); - saa7146_set_output_format(dev, vv->ov_fmt->trans); - saa7146_set_clipping_rect(fh); - - /* enable video dma1 */ - saa7146_write(dev, MC1, (MASK_06 | MASK_22)); - return 0; -} - -void saa7146_disable_overlay(struct saa7146_fh *fh) -{ - struct saa7146_dev *dev = fh->dev; - - /* disable clipping + video dma1 */ - saa7146_disable_clipping(dev); - saa7146_write(dev, MC1, MASK_22); -} - void saa7146_write_out_dma(struct saa7146_dev* dev, int which, struct saa7146_video_dma* vdma) { int where = 0; @@ -702,14 +407,14 @@ void saa7146_write_out_dma(struct saa7146_dev* dev, int which, struct saa7146_vi static int calculate_video_dma_grab_packed(struct saa7146_dev* dev, struct saa7146_buf *buf) { struct saa7146_vv *vv = dev->vv_data; + struct v4l2_pix_format *pix = &vv->video_fmt; struct saa7146_video_dma vdma1; + struct saa7146_format *sfmt = saa7146_format_by_fourcc(dev, pix->pixelformat); - struct saa7146_format *sfmt = saa7146_format_by_fourcc(dev,buf->fmt->pixelformat); - - int width = buf->fmt->width; - int height = buf->fmt->height; - int bytesperline = buf->fmt->bytesperline; - enum v4l2_field field = buf->fmt->field; + int width = pix->width; + int height = pix->height; + int bytesperline = pix->bytesperline; + enum v4l2_field field = pix->field; int depth = sfmt->depth; @@ -764,8 +469,9 @@ static int calculate_video_dma_grab_packed(struct saa7146_dev* dev, struct saa71 static int calc_planar_422(struct saa7146_vv *vv, struct saa7146_buf *buf, struct saa7146_video_dma *vdma2, struct saa7146_video_dma *vdma3) { - int height = buf->fmt->height; - int width = buf->fmt->width; + struct v4l2_pix_format *pix = &vv->video_fmt; + int height = pix->height; + int width = pix->wid |