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 3305439b1aSShuah Khan static int vbi_queue_setup(struct vb2_queue *vq, const struct v4l2_format *fmt, 3405439b1aSShuah Khan unsigned int *nbuffers, unsigned int *nplanes, 3505439b1aSShuah Khan unsigned int sizes[], void *alloc_ctxs[]) 360c0d06caSMauro Carvalho Chehab { 3705439b1aSShuah Khan struct au0828_dev *dev = vb2_get_drv_priv(vq); 3805439b1aSShuah Khan unsigned long img_size = dev->vbi_width * dev->vbi_height * 2; 3905439b1aSShuah Khan unsigned long size; 400c0d06caSMauro Carvalho Chehab 4105439b1aSShuah Khan size = fmt ? (fmt->fmt.vbi.samples_per_line * 4205439b1aSShuah Khan (fmt->fmt.vbi.count[0] + fmt->fmt.vbi.count[1])) : img_size; 4305439b1aSShuah Khan if (size < img_size) 440c0d06caSMauro Carvalho Chehab return -EINVAL; 450c0d06caSMauro Carvalho Chehab 4605439b1aSShuah Khan *nplanes = 1; 4705439b1aSShuah Khan sizes[0] = size; 480c0d06caSMauro Carvalho Chehab 4905439b1aSShuah Khan return 0; 500c0d06caSMauro Carvalho Chehab } 510c0d06caSMauro Carvalho Chehab 5205439b1aSShuah Khan static int vbi_buffer_prepare(struct vb2_buffer *vb) 5305439b1aSShuah Khan { 5405439b1aSShuah Khan struct au0828_dev *dev = vb2_get_drv_priv(vb->vb2_queue); 5505439b1aSShuah Khan unsigned long size; 560c0d06caSMauro Carvalho Chehab 5705439b1aSShuah Khan size = dev->vbi_width * dev->vbi_height * 2; 5805439b1aSShuah Khan 5905439b1aSShuah Khan if (vb2_plane_size(vb, 0) < size) { 6005439b1aSShuah Khan pr_err("%s data will not fit into plane (%lu < %lu)\n", 6105439b1aSShuah Khan __func__, vb2_plane_size(vb, 0), size); 6205439b1aSShuah Khan return -EINVAL; 6305439b1aSShuah Khan } 64*2d700715SJunghak Sung vb2_set_plane_payload(vb, 0, size); 6505439b1aSShuah Khan 6605439b1aSShuah Khan return 0; 670c0d06caSMauro Carvalho Chehab } 680c0d06caSMauro Carvalho Chehab 690c0d06caSMauro Carvalho Chehab static void 7005439b1aSShuah Khan vbi_buffer_queue(struct vb2_buffer *vb) 710c0d06caSMauro Carvalho Chehab { 7205439b1aSShuah Khan struct au0828_dev *dev = vb2_get_drv_priv(vb->vb2_queue); 73*2d700715SJunghak Sung struct vb2_v4l2_buffer *vbuf = to_vb2_v4l2_buffer(vb); 74*2d700715SJunghak Sung struct au0828_buffer *buf = 75*2d700715SJunghak Sung container_of(vbuf, struct au0828_buffer, vb); 7605439b1aSShuah Khan struct au0828_dmaqueue *vbiq = &dev->vbiq; 7705439b1aSShuah Khan unsigned long flags = 0; 7805439b1aSShuah Khan 7905439b1aSShuah Khan buf->mem = vb2_plane_vaddr(vb, 0); 8005439b1aSShuah Khan buf->length = vb2_plane_size(vb, 0); 8105439b1aSShuah Khan 8205439b1aSShuah Khan spin_lock_irqsave(&dev->slock, flags); 8305439b1aSShuah Khan list_add_tail(&buf->list, &vbiq->active); 8405439b1aSShuah Khan spin_unlock_irqrestore(&dev->slock, flags); 850c0d06caSMauro Carvalho Chehab } 860c0d06caSMauro Carvalho Chehab 8705439b1aSShuah Khan struct vb2_ops au0828_vbi_qops = { 8805439b1aSShuah Khan .queue_setup = vbi_queue_setup, 8905439b1aSShuah Khan .buf_prepare = vbi_buffer_prepare, 9005439b1aSShuah Khan .buf_queue = vbi_buffer_queue, 9105439b1aSShuah Khan .start_streaming = au0828_start_analog_streaming, 9205439b1aSShuah Khan .stop_streaming = au0828_stop_vbi_streaming, 9305439b1aSShuah Khan .wait_prepare = vb2_ops_wait_prepare, 9405439b1aSShuah Khan .wait_finish = vb2_ops_wait_finish, 950c0d06caSMauro Carvalho Chehab }; 96