xref: /openbmc/linux/drivers/media/usb/au0828/au0828-vbi.c (revision 05439b1a36935992785c4f28f6693e73820321cb)
10c0d06caSMauro Carvalho Chehab /*
20c0d06caSMauro Carvalho Chehab    au0828-vbi.c - VBI driver for au0828
30c0d06caSMauro Carvalho Chehab 
40c0d06caSMauro Carvalho Chehab    Copyright (C) 2010 Devin Heitmueller <dheitmueller@kernellabs.com>
50c0d06caSMauro Carvalho Chehab 
60c0d06caSMauro Carvalho Chehab    This work was sponsored by GetWellNetwork Inc.
70c0d06caSMauro Carvalho Chehab 
80c0d06caSMauro Carvalho Chehab    This program is free software; you can redistribute it and/or modify
90c0d06caSMauro Carvalho Chehab    it under the terms of the GNU General Public License as published by
100c0d06caSMauro Carvalho Chehab    the Free Software Foundation; either version 2 of the License, or
110c0d06caSMauro Carvalho Chehab    (at your option) any later version.
120c0d06caSMauro Carvalho Chehab 
130c0d06caSMauro Carvalho Chehab    This program is distributed in the hope that it will be useful,
140c0d06caSMauro Carvalho Chehab    but WITHOUT ANY WARRANTY; without even the implied warranty of
150c0d06caSMauro Carvalho Chehab    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
160c0d06caSMauro Carvalho Chehab    GNU General Public License for more details.
170c0d06caSMauro Carvalho Chehab 
180c0d06caSMauro Carvalho Chehab    You should have received a copy of the GNU General Public License
190c0d06caSMauro Carvalho Chehab    along with this program; if not, write to the Free Software
200c0d06caSMauro Carvalho Chehab    Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
210c0d06caSMauro Carvalho Chehab    02110-1301, USA.
220c0d06caSMauro Carvalho Chehab  */
230c0d06caSMauro Carvalho Chehab 
2483afb32aSMauro Carvalho Chehab #include "au0828.h"
2583afb32aSMauro Carvalho Chehab 
260c0d06caSMauro Carvalho Chehab #include <linux/kernel.h>
270c0d06caSMauro Carvalho Chehab #include <linux/module.h>
280c0d06caSMauro Carvalho Chehab #include <linux/init.h>
290c0d06caSMauro Carvalho Chehab #include <linux/slab.h>
300c0d06caSMauro Carvalho Chehab 
310c0d06caSMauro Carvalho Chehab /* ------------------------------------------------------------------ */
320c0d06caSMauro Carvalho Chehab 
33*05439b1aSShuah Khan static int vbi_queue_setup(struct vb2_queue *vq, const struct v4l2_format *fmt,
34*05439b1aSShuah Khan 			   unsigned int *nbuffers, unsigned int *nplanes,
35*05439b1aSShuah Khan 			   unsigned int sizes[], void *alloc_ctxs[])
360c0d06caSMauro Carvalho Chehab {
37*05439b1aSShuah Khan 	struct au0828_dev *dev = vb2_get_drv_priv(vq);
38*05439b1aSShuah Khan 	unsigned long img_size = dev->vbi_width * dev->vbi_height * 2;
39*05439b1aSShuah Khan 	unsigned long size;
400c0d06caSMauro Carvalho Chehab 
41*05439b1aSShuah Khan 	size = fmt ? (fmt->fmt.vbi.samples_per_line *
42*05439b1aSShuah Khan 		(fmt->fmt.vbi.count[0] + fmt->fmt.vbi.count[1])) : img_size;
43*05439b1aSShuah Khan 	if (size < img_size)
440c0d06caSMauro Carvalho Chehab 		return -EINVAL;
450c0d06caSMauro Carvalho Chehab 
46*05439b1aSShuah Khan 	*nplanes = 1;
47*05439b1aSShuah Khan 	sizes[0] = size;
480c0d06caSMauro Carvalho Chehab 
49*05439b1aSShuah Khan 	return 0;
500c0d06caSMauro Carvalho Chehab }
510c0d06caSMauro Carvalho Chehab 
52*05439b1aSShuah Khan static int vbi_buffer_prepare(struct vb2_buffer *vb)
53*05439b1aSShuah Khan {
54*05439b1aSShuah Khan 	struct au0828_dev *dev = vb2_get_drv_priv(vb->vb2_queue);
55*05439b1aSShuah Khan 	struct au0828_buffer *buf = container_of(vb, struct au0828_buffer, vb);
56*05439b1aSShuah Khan 	unsigned long size;
570c0d06caSMauro Carvalho Chehab 
58*05439b1aSShuah Khan 	size = dev->vbi_width * dev->vbi_height * 2;
59*05439b1aSShuah Khan 
60*05439b1aSShuah Khan 	if (vb2_plane_size(vb, 0) < size) {
61*05439b1aSShuah Khan 		pr_err("%s data will not fit into plane (%lu < %lu)\n",
62*05439b1aSShuah Khan 			__func__, vb2_plane_size(vb, 0), size);
63*05439b1aSShuah Khan 		return -EINVAL;
64*05439b1aSShuah Khan 	}
65*05439b1aSShuah Khan 	vb2_set_plane_payload(&buf->vb, 0, size);
66*05439b1aSShuah Khan 
67*05439b1aSShuah Khan 	return 0;
680c0d06caSMauro Carvalho Chehab }
690c0d06caSMauro Carvalho Chehab 
700c0d06caSMauro Carvalho Chehab static void
71*05439b1aSShuah Khan vbi_buffer_queue(struct vb2_buffer *vb)
720c0d06caSMauro Carvalho Chehab {
73*05439b1aSShuah Khan 	struct au0828_dev *dev = vb2_get_drv_priv(vb->vb2_queue);
740c0d06caSMauro Carvalho Chehab 	struct au0828_buffer *buf = container_of(vb, struct au0828_buffer, vb);
75*05439b1aSShuah Khan 	struct au0828_dmaqueue *vbiq = &dev->vbiq;
76*05439b1aSShuah Khan 	unsigned long flags = 0;
77*05439b1aSShuah Khan 
78*05439b1aSShuah Khan 	buf->mem = vb2_plane_vaddr(vb, 0);
79*05439b1aSShuah Khan 	buf->length = vb2_plane_size(vb, 0);
80*05439b1aSShuah Khan 
81*05439b1aSShuah Khan 	spin_lock_irqsave(&dev->slock, flags);
82*05439b1aSShuah Khan 	list_add_tail(&buf->list, &vbiq->active);
83*05439b1aSShuah Khan 	spin_unlock_irqrestore(&dev->slock, flags);
840c0d06caSMauro Carvalho Chehab }
850c0d06caSMauro Carvalho Chehab 
86*05439b1aSShuah Khan struct vb2_ops au0828_vbi_qops = {
87*05439b1aSShuah Khan 	.queue_setup     = vbi_queue_setup,
88*05439b1aSShuah Khan 	.buf_prepare     = vbi_buffer_prepare,
89*05439b1aSShuah Khan 	.buf_queue       = vbi_buffer_queue,
90*05439b1aSShuah Khan 	.start_streaming = au0828_start_analog_streaming,
91*05439b1aSShuah Khan 	.stop_streaming  = au0828_stop_vbi_streaming,
92*05439b1aSShuah Khan 	.wait_prepare    = vb2_ops_wait_prepare,
93*05439b1aSShuah Khan 	.wait_finish     = vb2_ops_wait_finish,
940c0d06caSMauro Carvalho Chehab };
95