Commit 9556be12 authored by Hans Verkuil's avatar Hans Verkuil Committed by Mauro Carvalho Chehab

[media] dt3155v4l: move vb2_queue to top-level

Instead of initializing the vb2_queue in open (and freeing in release)
do this in probe/remove instead. And as a bonus use the vb2 helper
functions to greatly simplify the driver.
Signed-off-by: default avatarHans Verkuil <hans.verkuil@cisco.com>
Signed-off-by: default avatarMauro Carvalho Chehab <mchehab@osg.samsung.com>
parent deb28978
...@@ -201,41 +201,24 @@ static int dt3155_start_acq(struct dt3155_priv *pd) ...@@ -201,41 +201,24 @@ static int dt3155_start_acq(struct dt3155_priv *pd)
} }
static int static int
dt3155_queue_setup(struct vb2_queue *q, const struct v4l2_format *fmt, dt3155_queue_setup(struct vb2_queue *vq, const struct v4l2_format *fmt,
unsigned int *num_buffers, unsigned int *num_planes, unsigned int *nbuffers, unsigned int *num_planes,
unsigned int sizes[], void *alloc_ctxs[]) unsigned int sizes[], void *alloc_ctxs[])
{ {
struct dt3155_priv *pd = vb2_get_drv_priv(q); struct dt3155_priv *pd = vb2_get_drv_priv(vq);
void *ret; unsigned size = img_width * img_height;
if (*num_buffers == 0) if (vq->num_buffers + *nbuffers < 2)
*num_buffers = 1; *nbuffers = 2 - vq->num_buffers;
if (fmt && fmt->fmt.pix.sizeimage < size)
return -EINVAL;
*num_planes = 1; *num_planes = 1;
sizes[0] = img_width * img_height; sizes[0] = fmt ? fmt->fmt.pix.sizeimage : size;
if (pd->q->alloc_ctx[0]) alloc_ctxs[0] = pd->alloc_ctx;
return 0;
ret = vb2_dma_contig_init_ctx(&pd->pdev->dev);
if (IS_ERR(ret))
return PTR_ERR(ret);
pd->q->alloc_ctx[0] = ret;
return 0; return 0;
} }
static void dt3155_wait_prepare(struct vb2_queue *q)
{
struct dt3155_priv *pd = vb2_get_drv_priv(q);
mutex_unlock(pd->vdev.lock);
}
static void dt3155_wait_finish(struct vb2_queue *q)
{
struct dt3155_priv *pd = vb2_get_drv_priv(q);
mutex_lock(pd->vdev.lock);
}
static int dt3155_buf_prepare(struct vb2_buffer *vb) static int dt3155_buf_prepare(struct vb2_buffer *vb)
{ {
vb2_set_plane_payload(vb, 0, img_width * img_height); vb2_set_plane_payload(vb, 0, img_width * img_height);
...@@ -255,6 +238,9 @@ static void dt3155_stop_streaming(struct vb2_queue *q) ...@@ -255,6 +238,9 @@ static void dt3155_stop_streaming(struct vb2_queue *q)
} }
spin_unlock_irq(&pd->lock); spin_unlock_irq(&pd->lock);
msleep(45); /* irq hendler will stop the hardware */ msleep(45); /* irq hendler will stop the hardware */
/* disable all irqs, clear all irq flags */
iowrite32(FLD_START | FLD_END_EVEN | FLD_END_ODD,
pd->regs + INT_CSR);
} }
static void dt3155_buf_queue(struct vb2_buffer *vb) static void dt3155_buf_queue(struct vb2_buffer *vb)
...@@ -274,8 +260,8 @@ static void dt3155_buf_queue(struct vb2_buffer *vb) ...@@ -274,8 +260,8 @@ static void dt3155_buf_queue(struct vb2_buffer *vb)
static const struct vb2_ops q_ops = { static const struct vb2_ops q_ops = {
.queue_setup = dt3155_queue_setup, .queue_setup = dt3155_queue_setup,
.wait_prepare = dt3155_wait_prepare, .wait_prepare = vb2_ops_wait_prepare,
.wait_finish = dt3155_wait_finish, .wait_finish = vb2_ops_wait_finish,
.buf_prepare = dt3155_buf_prepare, .buf_prepare = dt3155_buf_prepare,
.stop_streaming = dt3155_stop_streaming, .stop_streaming = dt3155_stop_streaming,
.buf_queue = dt3155_buf_queue, .buf_queue = dt3155_buf_queue,
...@@ -313,7 +299,7 @@ static irqreturn_t dt3155_irq_handler_even(int irq, void *dev_id) ...@@ -313,7 +299,7 @@ static irqreturn_t dt3155_irq_handler_even(int irq, void *dev_id)
vb2_buffer_done(ipd->curr_buf, VB2_BUF_STATE_DONE); vb2_buffer_done(ipd->curr_buf, VB2_BUF_STATE_DONE);
} }
if (!ipd->q->streaming || list_empty(&ipd->dmaq)) if (!ipd->vidq.streaming || list_empty(&ipd->dmaq))
goto stop_dma; goto stop_dma;
ivb = list_first_entry(&ipd->dmaq, typeof(*ivb), done_entry); ivb = list_first_entry(&ipd->dmaq, typeof(*ivb), done_entry);
list_del(&ivb->done_entry); list_del(&ivb->done_entry);
...@@ -342,124 +328,16 @@ static irqreturn_t dt3155_irq_handler_even(int irq, void *dev_id) ...@@ -342,124 +328,16 @@ static irqreturn_t dt3155_irq_handler_even(int irq, void *dev_id)
return IRQ_HANDLED; return IRQ_HANDLED;
} }
static int dt3155_open(struct file *filp)
{
int ret = 0;
struct dt3155_priv *pd = video_drvdata(filp);
if (mutex_lock_interruptible(&pd->mux))
return -ERESTARTSYS;
if (!pd->users) {
pd->q = kzalloc(sizeof(*pd->q), GFP_KERNEL);
if (!pd->q) {
ret = -ENOMEM;
goto err_alloc_queue;
}
pd->q->type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
pd->q->timestamp_flags = V4L2_BUF_FLAG_TIMESTAMP_MONOTONIC;
pd->q->io_modes = VB2_READ | VB2_MMAP;
pd->q->ops = &q_ops;
pd->q->mem_ops = &vb2_dma_contig_memops;
pd->q->drv_priv = pd;
pd->curr_buf = NULL;
pd->field_count = 0;
ret = vb2_queue_init(pd->q);
if (ret < 0)
goto err_request_irq;
INIT_LIST_HEAD(&pd->dmaq);
spin_lock_init(&pd->lock);
/* disable all irqs, clear all irq flags */
iowrite32(FLD_START | FLD_END_EVEN | FLD_END_ODD,
pd->regs + INT_CSR);
}
pd->users++;
mutex_unlock(&pd->mux);
return 0; /* success */
err_request_irq:
kfree(pd->q);
pd->q = NULL;
err_alloc_queue:
mutex_unlock(&pd->mux);
return ret;
}
static int dt3155_release(struct file *filp)
{
struct dt3155_priv *pd = video_drvdata(filp);
mutex_lock(&pd->mux);
pd->users--;
BUG_ON(pd->users < 0);
if (!pd->users) {
vb2_queue_release(pd->q);
if (pd->q->alloc_ctx[0])
vb2_dma_contig_cleanup_ctx(pd->q->alloc_ctx[0]);
kfree(pd->q);
pd->q = NULL;
}
mutex_unlock(&pd->mux);
return 0;
}
static ssize_t dt3155_read(struct file *filp, char __user *user, size_t size, loff_t *loff)
{
struct dt3155_priv *pd = video_drvdata(filp);
ssize_t res;
if (mutex_lock_interruptible(&pd->mux))
return -ERESTARTSYS;
res = vb2_read(pd->q, user, size, loff, filp->f_flags & O_NONBLOCK);
mutex_unlock(&pd->mux);
return res;
}
static unsigned int dt3155_poll(struct file *filp, struct poll_table_struct *polltbl)
{
struct dt3155_priv *pd = video_drvdata(filp);
unsigned int res;
mutex_lock(&pd->mux);
res = vb2_poll(pd->q, filp, polltbl);
mutex_unlock(&pd->mux);
return res;
}
static int dt3155_mmap(struct file *filp, struct vm_area_struct *vma)
{
struct dt3155_priv *pd = video_drvdata(filp);
int res;
if (mutex_lock_interruptible(&pd->mux))
return -ERESTARTSYS;
res = vb2_mmap(pd->q, vma);
mutex_unlock(&pd->mux);
return res;
}
static const struct v4l2_file_operations dt3155_fops = { static const struct v4l2_file_operations dt3155_fops = {
.owner = THIS_MODULE, .owner = THIS_MODULE,
.open = dt3155_open, .open = v4l2_fh_open,
.release = dt3155_release, .release = vb2_fop_release,
.read = dt3155_read, .unlocked_ioctl = video_ioctl2,
.poll = dt3155_poll, .read = vb2_fop_read,
.unlocked_ioctl = video_ioctl2, /* V4L2 ioctl handler */ .mmap = vb2_fop_mmap,
.mmap = dt3155_mmap, .poll = vb2_fop_poll
}; };
static int dt3155_streamon(struct file *filp, void *p, enum v4l2_buf_type type)
{
struct dt3155_priv *pd = video_drvdata(filp);
return vb2_streamon(pd->q, type);
}
static int dt3155_streamoff(struct file *filp, void *p, enum v4l2_buf_type type)
{
struct dt3155_priv *pd = video_drvdata(filp);
return vb2_streamoff(pd->q, type);
}
static int dt3155_querycap(struct file *filp, void *p, struct v4l2_capability *cap) static int dt3155_querycap(struct file *filp, void *p, struct v4l2_capability *cap)
{ {
struct dt3155_priv *pd = video_drvdata(filp); struct dt3155_priv *pd = video_drvdata(filp);
...@@ -516,34 +394,6 @@ static int dt3155_s_fmt_vid_cap(struct file *filp, void *p, struct v4l2_format * ...@@ -516,34 +394,6 @@ static int dt3155_s_fmt_vid_cap(struct file *filp, void *p, struct v4l2_format *
return dt3155_g_fmt_vid_cap(filp, p, f); return dt3155_g_fmt_vid_cap(filp, p, f);
} }
static int dt3155_reqbufs(struct file *filp, void *p, struct v4l2_requestbuffers *b)
{
struct dt3155_priv *pd = video_drvdata(filp);
return vb2_reqbufs(pd->q, b);
}
static int dt3155_querybuf(struct file *filp, void *p, struct v4l2_buffer *b)
{
struct dt3155_priv *pd = video_drvdata(filp);
return vb2_querybuf(pd->q, b);
}
static int dt3155_qbuf(struct file *filp, void *p, struct v4l2_buffer *b)
{
struct dt3155_priv *pd = video_drvdata(filp);
return vb2_qbuf(pd->q, b);
}
static int dt3155_dqbuf(struct file *filp, void *p, struct v4l2_buffer *b)
{
struct dt3155_priv *pd = video_drvdata(filp);
return vb2_dqbuf(pd->q, b, filp->f_flags & O_NONBLOCK);
}
static int dt3155_querystd(struct file *filp, void *p, v4l2_std_id *norm) static int dt3155_querystd(struct file *filp, void *p, v4l2_std_id *norm)
{ {
*norm = DT3155_CURRENT_NORM; *norm = DT3155_CURRENT_NORM;
...@@ -619,17 +469,19 @@ static int dt3155_s_parm(struct file *filp, void *p, struct v4l2_streamparm *par ...@@ -619,17 +469,19 @@ static int dt3155_s_parm(struct file *filp, void *p, struct v4l2_streamparm *par
} }
static const struct v4l2_ioctl_ops dt3155_ioctl_ops = { static const struct v4l2_ioctl_ops dt3155_ioctl_ops = {
.vidioc_streamon = dt3155_streamon,
.vidioc_streamoff = dt3155_streamoff,
.vidioc_querycap = dt3155_querycap, .vidioc_querycap = dt3155_querycap,
.vidioc_enum_fmt_vid_cap = dt3155_enum_fmt_vid_cap, .vidioc_enum_fmt_vid_cap = dt3155_enum_fmt_vid_cap,
.vidioc_try_fmt_vid_cap = dt3155_try_fmt_vid_cap, .vidioc_try_fmt_vid_cap = dt3155_try_fmt_vid_cap,
.vidioc_g_fmt_vid_cap = dt3155_g_fmt_vid_cap, .vidioc_g_fmt_vid_cap = dt3155_g_fmt_vid_cap,
.vidioc_s_fmt_vid_cap = dt3155_s_fmt_vid_cap, .vidioc_s_fmt_vid_cap = dt3155_s_fmt_vid_cap,
.vidioc_reqbufs = dt3155_reqbufs, .vidioc_reqbufs = vb2_ioctl_reqbufs,
.vidioc_querybuf = dt3155_querybuf, .vidioc_create_bufs = vb2_ioctl_create_bufs,
.vidioc_qbuf = dt3155_qbuf, .vidioc_querybuf = vb2_ioctl_querybuf,
.vidioc_dqbuf = dt3155_dqbuf, .vidioc_expbuf = vb2_ioctl_expbuf,
.vidioc_qbuf = vb2_ioctl_qbuf,
.vidioc_dqbuf = vb2_ioctl_dqbuf,
.vidioc_streamon = vb2_ioctl_streamon,
.vidioc_streamoff = vb2_ioctl_streamoff,
.vidioc_querystd = dt3155_querystd, .vidioc_querystd = dt3155_querystd,
.vidioc_g_std = dt3155_g_std, .vidioc_g_std = dt3155_g_std,
.vidioc_s_std = dt3155_s_std, .vidioc_s_std = dt3155_s_std,
...@@ -740,17 +592,34 @@ static int dt3155_probe(struct pci_dev *pdev, const struct pci_device_id *id) ...@@ -740,17 +592,34 @@ static int dt3155_probe(struct pci_dev *pdev, const struct pci_device_id *id)
pd->vdev = dt3155_vdev; pd->vdev = dt3155_vdev;
pd->vdev.v4l2_dev = &pd->v4l2_dev; pd->vdev.v4l2_dev = &pd->v4l2_dev;
video_set_drvdata(&pd->vdev, pd); /* for use in video_fops */ video_set_drvdata(&pd->vdev, pd); /* for use in video_fops */
pd->users = 0;
pd->pdev = pdev; pd->pdev = pdev;
INIT_LIST_HEAD(&pd->dmaq); INIT_LIST_HEAD(&pd->dmaq);
mutex_init(&pd->mux); mutex_init(&pd->mux);
pd->vdev.lock = &pd->mux; /* for locking v4l2_file_operations */ pd->vdev.lock = &pd->mux; /* for locking v4l2_file_operations */
pd->vidq.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
pd->vidq.timestamp_flags = V4L2_BUF_FLAG_TIMESTAMP_MONOTONIC;
pd->vidq.io_modes = VB2_MMAP | VB2_DMABUF | VB2_READ;
pd->vidq.ops = &q_ops;
pd->vidq.mem_ops = &vb2_dma_contig_memops;
pd->vidq.drv_priv = pd;
pd->vidq.min_buffers_needed = 2;
pd->vidq.lock = &pd->mux; /* for locking v4l2_file_operations */
pd->vdev.queue = &pd->vidq;
err = vb2_queue_init(&pd->vidq);
if (err < 0)
goto err_v4l2_dev_unreg;
pd->alloc_ctx = vb2_dma_contig_init_ctx(&pdev->dev);
if (IS_ERR(pd->alloc_ctx)) {
dev_err(&pdev->dev, "Can't allocate buffer context");
err = PTR_ERR(pd->alloc_ctx);
goto err_v4l2_dev_unreg;
}
spin_lock_init(&pd->lock); spin_lock_init(&pd->lock);
pd->csr2 = csr2_init; pd->csr2 = csr2_init;
pd->config = config_init; pd->config = config_init;
err = pci_enable_device(pdev); err = pci_enable_device(pdev);
if (err) if (err)
goto err_v4l2_dev_unreg; goto err_free_ctx;
err = pci_request_region(pdev, 0, pci_name(pdev)); err = pci_request_region(pdev, 0, pci_name(pdev));
if (err) if (err)
goto err_pci_disable; goto err_pci_disable;
...@@ -780,6 +649,8 @@ static int dt3155_probe(struct pci_dev *pdev, const struct pci_device_id *id) ...@@ -780,6 +649,8 @@ static int dt3155_probe(struct pci_dev *pdev, const struct pci_device_id *id)
pci_release_region(pdev, 0); pci_release_region(pdev, 0);
err_pci_disable: err_pci_disable:
pci_disable_device(pdev); pci_disable_device(pdev);
err_free_ctx:
vb2_dma_contig_cleanup_ctx(pd->alloc_ctx);
err_v4l2_dev_unreg: err_v4l2_dev_unreg:
v4l2_device_unregister(&pd->v4l2_dev); v4l2_device_unregister(&pd->v4l2_dev);
return err; return err;
...@@ -792,10 +663,12 @@ static void dt3155_remove(struct pci_dev *pdev) ...@@ -792,10 +663,12 @@ static void dt3155_remove(struct pci_dev *pdev)
video_unregister_device(&pd->vdev); video_unregister_device(&pd->vdev);
free_irq(pd->pdev->irq, pd); free_irq(pd->pdev->irq, pd);
vb2_queue_release(&pd->vidq);
v4l2_device_unregister(&pd->v4l2_dev); v4l2_device_unregister(&pd->v4l2_dev);
pci_iounmap(pdev, pd->regs); pci_iounmap(pdev, pd->regs);
pci_release_region(pdev, 0); pci_release_region(pdev, 0);
pci_disable_device(pdev); pci_disable_device(pdev);
vb2_dma_contig_cleanup_ctx(pd->alloc_ctx);
} }
static const struct pci_device_id pci_ids[] = { static const struct pci_device_id pci_ids[] = {
......
...@@ -165,14 +165,14 @@ ...@@ -165,14 +165,14 @@
* @v4l2_dev: v4l2_device structure * @v4l2_dev: v4l2_device structure
* @vdev: video_device structure * @vdev: video_device structure
* @pdev: pointer to pci_dev structure * @pdev: pointer to pci_dev structure
* @q pointer to vb2_queue structure * @vidq: vb2_queue structure
* @alloc_ctx: dma_contig allocation context
* @curr_buf: pointer to curren buffer * @curr_buf: pointer to curren buffer
* @mux: mutex to protect the instance * @mux: mutex to protect the instance
* @dmaq queue for dma buffers * @dmaq queue for dma buffers
* @lock spinlock for dma queue * @lock spinlock for dma queue
* @field_count fields counter * @field_count fields counter
* @stats: statistics structure * @stats: statistics structure
* @users open count
* @regs: local copy of mmio base register * @regs: local copy of mmio base register
* @csr2: local copy of csr2 register * @csr2: local copy of csr2 register
* @config: local copy of config register * @config: local copy of config register
...@@ -181,14 +181,14 @@ struct dt3155_priv { ...@@ -181,14 +181,14 @@ struct dt3155_priv {
struct v4l2_device v4l2_dev; struct v4l2_device v4l2_dev;
struct video_device vdev; struct video_device vdev;
struct pci_dev *pdev; struct pci_dev *pdev;
struct vb2_queue *q; struct vb2_queue vidq;
struct vb2_alloc_ctx *alloc_ctx;
struct vb2_buffer *curr_buf; struct vb2_buffer *curr_buf;
struct mutex mux; struct mutex mux;
struct list_head dmaq; struct list_head dmaq;
spinlock_t lock; spinlock_t lock;
unsigned int field_count; unsigned int field_count;
void __iomem *regs; void __iomem *regs;
int users;
u8 csr2, config; u8 csr2, config;
}; };
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment