128abf083d356bc4ec459ded7a95b6a22a20f6c3dDevin Heitmueller/* 228abf083d356bc4ec459ded7a95b6a22a20f6c3dDevin Heitmueller em28xx-vbi.c - VBI driver for em28xx 328abf083d356bc4ec459ded7a95b6a22a20f6c3dDevin Heitmueller 428abf083d356bc4ec459ded7a95b6a22a20f6c3dDevin Heitmueller Copyright (C) 2009 Devin Heitmueller <dheitmueller@kernellabs.com> 528abf083d356bc4ec459ded7a95b6a22a20f6c3dDevin Heitmueller 628abf083d356bc4ec459ded7a95b6a22a20f6c3dDevin Heitmueller This work was sponsored by EyeMagnet Limited. 728abf083d356bc4ec459ded7a95b6a22a20f6c3dDevin Heitmueller 828abf083d356bc4ec459ded7a95b6a22a20f6c3dDevin Heitmueller This program is free software; you can redistribute it and/or modify 928abf083d356bc4ec459ded7a95b6a22a20f6c3dDevin Heitmueller it under the terms of the GNU General Public License as published by 1028abf083d356bc4ec459ded7a95b6a22a20f6c3dDevin Heitmueller the Free Software Foundation; either version 2 of the License, or 1128abf083d356bc4ec459ded7a95b6a22a20f6c3dDevin Heitmueller (at your option) any later version. 1228abf083d356bc4ec459ded7a95b6a22a20f6c3dDevin Heitmueller 1328abf083d356bc4ec459ded7a95b6a22a20f6c3dDevin Heitmueller This program is distributed in the hope that it will be useful, 1428abf083d356bc4ec459ded7a95b6a22a20f6c3dDevin Heitmueller but WITHOUT ANY WARRANTY; without even the implied warranty of 1528abf083d356bc4ec459ded7a95b6a22a20f6c3dDevin Heitmueller MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 1628abf083d356bc4ec459ded7a95b6a22a20f6c3dDevin Heitmueller GNU General Public License for more details. 1728abf083d356bc4ec459ded7a95b6a22a20f6c3dDevin Heitmueller 1828abf083d356bc4ec459ded7a95b6a22a20f6c3dDevin Heitmueller You should have received a copy of the GNU General Public License 1928abf083d356bc4ec459ded7a95b6a22a20f6c3dDevin Heitmueller along with this program; if not, write to the Free Software 2028abf083d356bc4ec459ded7a95b6a22a20f6c3dDevin Heitmueller Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 2128abf083d356bc4ec459ded7a95b6a22a20f6c3dDevin Heitmueller 02110-1301, USA. 2228abf083d356bc4ec459ded7a95b6a22a20f6c3dDevin Heitmueller */ 2328abf083d356bc4ec459ded7a95b6a22a20f6c3dDevin Heitmueller 2428abf083d356bc4ec459ded7a95b6a22a20f6c3dDevin Heitmueller#include <linux/kernel.h> 2528abf083d356bc4ec459ded7a95b6a22a20f6c3dDevin Heitmueller#include <linux/module.h> 26c59a9bfabfc2a6359f046652c6bfa0a82fb17a05Randy Dunlap#include <linux/hardirq.h> 2728abf083d356bc4ec459ded7a95b6a22a20f6c3dDevin Heitmueller#include <linux/init.h> 2828abf083d356bc4ec459ded7a95b6a22a20f6c3dDevin Heitmueller 2928abf083d356bc4ec459ded7a95b6a22a20f6c3dDevin Heitmueller#include "em28xx.h" 3001c2819330b1e0ec6b53dcfac76ad75ff2c8ba4fMauro Carvalho Chehab#include "em28xx-v4l.h" 3128abf083d356bc4ec459ded7a95b6a22a20f6c3dDevin Heitmueller 3228abf083d356bc4ec459ded7a95b6a22a20f6c3dDevin Heitmueller/* ------------------------------------------------------------------ */ 3328abf083d356bc4ec459ded7a95b6a22a20f6c3dDevin Heitmueller 34d3829fadc4611e96aa360b8ead5adefdf61f45eaDevin Heitmuellerstatic int vbi_queue_setup(struct vb2_queue *vq, const struct v4l2_format *fmt, 35d3829fadc4611e96aa360b8ead5adefdf61f45eaDevin Heitmueller unsigned int *nbuffers, unsigned int *nplanes, 36d3829fadc4611e96aa360b8ead5adefdf61f45eaDevin Heitmueller unsigned int sizes[], void *alloc_ctxs[]) 3728abf083d356bc4ec459ded7a95b6a22a20f6c3dDevin Heitmueller{ 38d3829fadc4611e96aa360b8ead5adefdf61f45eaDevin Heitmueller struct em28xx *dev = vb2_get_drv_priv(vq); 39753aee7738ed2ee8c810524ee32b556ac7617f2eFrank Schaefer struct em28xx_v4l2 *v4l2 = dev->v4l2; 40d3829fadc4611e96aa360b8ead5adefdf61f45eaDevin Heitmueller unsigned long size; 4128abf083d356bc4ec459ded7a95b6a22a20f6c3dDevin Heitmueller 42d3829fadc4611e96aa360b8ead5adefdf61f45eaDevin Heitmueller if (fmt) 43d3829fadc4611e96aa360b8ead5adefdf61f45eaDevin Heitmueller size = fmt->fmt.pix.sizeimage; 44d3829fadc4611e96aa360b8ead5adefdf61f45eaDevin Heitmueller else 45753aee7738ed2ee8c810524ee32b556ac7617f2eFrank Schaefer size = v4l2->vbi_width * v4l2->vbi_height * 2; 4628abf083d356bc4ec459ded7a95b6a22a20f6c3dDevin Heitmueller 47d3829fadc4611e96aa360b8ead5adefdf61f45eaDevin Heitmueller if (0 == *nbuffers) 48d3829fadc4611e96aa360b8ead5adefdf61f45eaDevin Heitmueller *nbuffers = 32; 49d3829fadc4611e96aa360b8ead5adefdf61f45eaDevin Heitmueller if (*nbuffers < 2) 50d3829fadc4611e96aa360b8ead5adefdf61f45eaDevin Heitmueller *nbuffers = 2; 51d3829fadc4611e96aa360b8ead5adefdf61f45eaDevin Heitmueller if (*nbuffers > 32) 52d3829fadc4611e96aa360b8ead5adefdf61f45eaDevin Heitmueller *nbuffers = 32; 5366d9cbad5330d6df30c82f10ee18b62b096b84efDevin Heitmueller 54d3829fadc4611e96aa360b8ead5adefdf61f45eaDevin Heitmueller *nplanes = 1; 55d3829fadc4611e96aa360b8ead5adefdf61f45eaDevin Heitmueller sizes[0] = size; 5666d9cbad5330d6df30c82f10ee18b62b096b84efDevin Heitmueller 5728abf083d356bc4ec459ded7a95b6a22a20f6c3dDevin Heitmueller return 0; 5828abf083d356bc4ec459ded7a95b6a22a20f6c3dDevin Heitmueller} 5928abf083d356bc4ec459ded7a95b6a22a20f6c3dDevin Heitmueller 60d3829fadc4611e96aa360b8ead5adefdf61f45eaDevin Heitmuellerstatic int vbi_buffer_prepare(struct vb2_buffer *vb) 6128abf083d356bc4ec459ded7a95b6a22a20f6c3dDevin Heitmueller{ 62753aee7738ed2ee8c810524ee32b556ac7617f2eFrank Schaefer struct em28xx *dev = vb2_get_drv_priv(vb->vb2_queue); 63753aee7738ed2ee8c810524ee32b556ac7617f2eFrank Schaefer struct em28xx_v4l2 *v4l2 = dev->v4l2; 64753aee7738ed2ee8c810524ee32b556ac7617f2eFrank Schaefer struct em28xx_buffer *buf = container_of(vb, struct em28xx_buffer, vb); 65d3829fadc4611e96aa360b8ead5adefdf61f45eaDevin Heitmueller unsigned long size; 6628abf083d356bc4ec459ded7a95b6a22a20f6c3dDevin Heitmueller 67753aee7738ed2ee8c810524ee32b556ac7617f2eFrank Schaefer size = v4l2->vbi_width * v4l2->vbi_height * 2; 6828abf083d356bc4ec459ded7a95b6a22a20f6c3dDevin Heitmueller 69d3829fadc4611e96aa360b8ead5adefdf61f45eaDevin Heitmueller if (vb2_plane_size(vb, 0) < size) { 70d3829fadc4611e96aa360b8ead5adefdf61f45eaDevin Heitmueller printk(KERN_INFO "%s data will not fit into plane (%lu < %lu)\n", 71d3829fadc4611e96aa360b8ead5adefdf61f45eaDevin Heitmueller __func__, vb2_plane_size(vb, 0), size); 7228abf083d356bc4ec459ded7a95b6a22a20f6c3dDevin Heitmueller return -EINVAL; 7328abf083d356bc4ec459ded7a95b6a22a20f6c3dDevin Heitmueller } 74d3829fadc4611e96aa360b8ead5adefdf61f45eaDevin Heitmueller vb2_set_plane_payload(&buf->vb, 0, size); 7528abf083d356bc4ec459ded7a95b6a22a20f6c3dDevin Heitmueller 7628abf083d356bc4ec459ded7a95b6a22a20f6c3dDevin Heitmueller return 0; 7728abf083d356bc4ec459ded7a95b6a22a20f6c3dDevin Heitmueller} 7828abf083d356bc4ec459ded7a95b6a22a20f6c3dDevin Heitmueller 7928abf083d356bc4ec459ded7a95b6a22a20f6c3dDevin Heitmuellerstatic void 80d3829fadc4611e96aa360b8ead5adefdf61f45eaDevin Heitmuellervbi_buffer_queue(struct vb2_buffer *vb) 8128abf083d356bc4ec459ded7a95b6a22a20f6c3dDevin Heitmueller{ 82d3829fadc4611e96aa360b8ead5adefdf61f45eaDevin Heitmueller struct em28xx *dev = vb2_get_drv_priv(vb->vb2_queue); 8328abf083d356bc4ec459ded7a95b6a22a20f6c3dDevin Heitmueller struct em28xx_buffer *buf = container_of(vb, struct em28xx_buffer, vb); 84d3829fadc4611e96aa360b8ead5adefdf61f45eaDevin Heitmueller struct em28xx_dmaqueue *vbiq = &dev->vbiq; 85d3829fadc4611e96aa360b8ead5adefdf61f45eaDevin Heitmueller unsigned long flags = 0; 86d3829fadc4611e96aa360b8ead5adefdf61f45eaDevin Heitmueller 87d3829fadc4611e96aa360b8ead5adefdf61f45eaDevin Heitmueller buf->mem = vb2_plane_vaddr(vb, 0); 88d3829fadc4611e96aa360b8ead5adefdf61f45eaDevin Heitmueller buf->length = vb2_plane_size(vb, 0); 89d3829fadc4611e96aa360b8ead5adefdf61f45eaDevin Heitmueller 90d3829fadc4611e96aa360b8ead5adefdf61f45eaDevin Heitmueller spin_lock_irqsave(&dev->slock, flags); 91d3829fadc4611e96aa360b8ead5adefdf61f45eaDevin Heitmueller list_add_tail(&buf->list, &vbiq->active); 92d3829fadc4611e96aa360b8ead5adefdf61f45eaDevin Heitmueller spin_unlock_irqrestore(&dev->slock, flags); 9328abf083d356bc4ec459ded7a95b6a22a20f6c3dDevin Heitmueller} 9428abf083d356bc4ec459ded7a95b6a22a20f6c3dDevin Heitmueller 95d3829fadc4611e96aa360b8ead5adefdf61f45eaDevin Heitmueller 96d3829fadc4611e96aa360b8ead5adefdf61f45eaDevin Heitmuellerstruct vb2_ops em28xx_vbi_qops = { 97d3829fadc4611e96aa360b8ead5adefdf61f45eaDevin Heitmueller .queue_setup = vbi_queue_setup, 98d3829fadc4611e96aa360b8ead5adefdf61f45eaDevin Heitmueller .buf_prepare = vbi_buffer_prepare, 99d3829fadc4611e96aa360b8ead5adefdf61f45eaDevin Heitmueller .buf_queue = vbi_buffer_queue, 100d3829fadc4611e96aa360b8ead5adefdf61f45eaDevin Heitmueller .start_streaming = em28xx_start_analog_streaming, 101d3829fadc4611e96aa360b8ead5adefdf61f45eaDevin Heitmueller .stop_streaming = em28xx_stop_vbi_streaming, 102d3829fadc4611e96aa360b8ead5adefdf61f45eaDevin Heitmueller .wait_prepare = vb2_ops_wait_prepare, 103d3829fadc4611e96aa360b8ead5adefdf61f45eaDevin Heitmueller .wait_finish = vb2_ops_wait_finish, 10428abf083d356bc4ec459ded7a95b6a22a20f6c3dDevin Heitmueller}; 105