1ec16dae5453eafd1586f35c4ec1ef854e5a808e0Jaime Velasco Juan/* 2ec16dae5453eafd1586f35c4ec1ef854e5a808e0Jaime Velasco Juan * stk-webcam.c : Driver for Syntek 1125 USB webcam controller 3ec16dae5453eafd1586f35c4ec1ef854e5a808e0Jaime Velasco Juan * 4ec16dae5453eafd1586f35c4ec1ef854e5a808e0Jaime Velasco Juan * Copyright (C) 2006 Nicolas VIVIEN 5ec16dae5453eafd1586f35c4ec1ef854e5a808e0Jaime Velasco Juan * Copyright 2007-2008 Jaime Velasco Juan <jsagarribay@gmail.com> 6ec16dae5453eafd1586f35c4ec1ef854e5a808e0Jaime Velasco Juan * 7ec16dae5453eafd1586f35c4ec1ef854e5a808e0Jaime Velasco Juan * Some parts are inspired from cafe_ccic.c 8ec16dae5453eafd1586f35c4ec1ef854e5a808e0Jaime Velasco Juan * Copyright 2006-2007 Jonathan Corbet 9ec16dae5453eafd1586f35c4ec1ef854e5a808e0Jaime Velasco Juan * 10ec16dae5453eafd1586f35c4ec1ef854e5a808e0Jaime Velasco Juan * This program is free software; you can redistribute it and/or modify 11ec16dae5453eafd1586f35c4ec1ef854e5a808e0Jaime Velasco Juan * it under the terms of the GNU General Public License as published by 12ec16dae5453eafd1586f35c4ec1ef854e5a808e0Jaime Velasco Juan * the Free Software Foundation; either version 2 of the License, or 13ec16dae5453eafd1586f35c4ec1ef854e5a808e0Jaime Velasco Juan * any later version. 14ec16dae5453eafd1586f35c4ec1ef854e5a808e0Jaime Velasco Juan * 15ec16dae5453eafd1586f35c4ec1ef854e5a808e0Jaime Velasco Juan * This program is distributed in the hope that it will be useful, 16ec16dae5453eafd1586f35c4ec1ef854e5a808e0Jaime Velasco Juan * but WITHOUT ANY WARRANTY; without even the implied warranty of 17ec16dae5453eafd1586f35c4ec1ef854e5a808e0Jaime Velasco Juan * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 18ec16dae5453eafd1586f35c4ec1ef854e5a808e0Jaime Velasco Juan * GNU General Public License for more details. 19ec16dae5453eafd1586f35c4ec1ef854e5a808e0Jaime Velasco Juan * 20ec16dae5453eafd1586f35c4ec1ef854e5a808e0Jaime Velasco Juan * You should have received a copy of the GNU General Public License 21ec16dae5453eafd1586f35c4ec1ef854e5a808e0Jaime Velasco Juan * along with this program; if not, write to the Free Software 22ec16dae5453eafd1586f35c4ec1ef854e5a808e0Jaime Velasco Juan * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 23ec16dae5453eafd1586f35c4ec1ef854e5a808e0Jaime Velasco Juan */ 24ec16dae5453eafd1586f35c4ec1ef854e5a808e0Jaime Velasco Juan 25ec16dae5453eafd1586f35c4ec1ef854e5a808e0Jaime Velasco Juan#include <linux/module.h> 26ec16dae5453eafd1586f35c4ec1ef854e5a808e0Jaime Velasco Juan#include <linux/init.h> 27ec16dae5453eafd1586f35c4ec1ef854e5a808e0Jaime Velasco Juan#include <linux/kernel.h> 28ec16dae5453eafd1586f35c4ec1ef854e5a808e0Jaime Velasco Juan#include <linux/errno.h> 29ec16dae5453eafd1586f35c4ec1ef854e5a808e0Jaime Velasco Juan#include <linux/slab.h> 30ec16dae5453eafd1586f35c4ec1ef854e5a808e0Jaime Velasco Juan 31ec16dae5453eafd1586f35c4ec1ef854e5a808e0Jaime Velasco Juan#include <linux/usb.h> 32ef69c8e88bafdeb896395fa5379a4b8c6a10bb08Mauro Carvalho Chehab#include <linux/mm.h> 33387d447776484b6e1d08973337aa4c834ea7c6bcMauro Carvalho Chehab#include <linux/vmalloc.h> 34ec16dae5453eafd1586f35c4ec1ef854e5a808e0Jaime Velasco Juan#include <linux/videodev2.h> 35ec16dae5453eafd1586f35c4ec1ef854e5a808e0Jaime Velasco Juan#include <media/v4l2-common.h> 3635ea11ff84719b1bfab2909903a9640a86552fd1Hans Verkuil#include <media/v4l2-ioctl.h> 37ec16dae5453eafd1586f35c4ec1ef854e5a808e0Jaime Velasco Juan 38ec16dae5453eafd1586f35c4ec1ef854e5a808e0Jaime Velasco Juan#include "stk-webcam.h" 39ec16dae5453eafd1586f35c4ec1ef854e5a808e0Jaime Velasco Juan 40ec16dae5453eafd1586f35c4ec1ef854e5a808e0Jaime Velasco Juan 4190ab5ee94171b3e28de6bb42ee30b527014e0be7Rusty Russellstatic bool hflip = 1; 42ec16dae5453eafd1586f35c4ec1ef854e5a808e0Jaime Velasco Juanmodule_param(hflip, bool, 0444); 43ec16dae5453eafd1586f35c4ec1ef854e5a808e0Jaime Velasco JuanMODULE_PARM_DESC(hflip, "Horizontal image flip (mirror). Defaults to 1"); 44ec16dae5453eafd1586f35c4ec1ef854e5a808e0Jaime Velasco Juan 4590ab5ee94171b3e28de6bb42ee30b527014e0be7Rusty Russellstatic bool vflip = 1; 46ec16dae5453eafd1586f35c4ec1ef854e5a808e0Jaime Velasco Juanmodule_param(vflip, bool, 0444); 47ec16dae5453eafd1586f35c4ec1ef854e5a808e0Jaime Velasco JuanMODULE_PARM_DESC(vflip, "Vertical image flip. Defaults to 1"); 48ec16dae5453eafd1586f35c4ec1ef854e5a808e0Jaime Velasco Juan 49ec16dae5453eafd1586f35c4ec1ef854e5a808e0Jaime Velasco Juanstatic int debug; 50ec16dae5453eafd1586f35c4ec1ef854e5a808e0Jaime Velasco Juanmodule_param(debug, int, 0444); 51ec16dae5453eafd1586f35c4ec1ef854e5a808e0Jaime Velasco JuanMODULE_PARM_DESC(debug, "Debug v4l ioctls. Defaults to 0"); 52ec16dae5453eafd1586f35c4ec1ef854e5a808e0Jaime Velasco Juan 53ec16dae5453eafd1586f35c4ec1ef854e5a808e0Jaime Velasco JuanMODULE_LICENSE("GPL"); 54ec16dae5453eafd1586f35c4ec1ef854e5a808e0Jaime Velasco JuanMODULE_AUTHOR("Jaime Velasco Juan <jsagarribay@gmail.com> and Nicolas VIVIEN"); 55ec16dae5453eafd1586f35c4ec1ef854e5a808e0Jaime Velasco JuanMODULE_DESCRIPTION("Syntek DC1125 webcam driver"); 56ec16dae5453eafd1586f35c4ec1ef854e5a808e0Jaime Velasco Juan 57ec16dae5453eafd1586f35c4ec1ef854e5a808e0Jaime Velasco Juan 587b1c8f58fcdbed75903943705ef41816e9648c1bArvydas Sidorenko/* bool for webcam LED management */ 597b1c8f58fcdbed75903943705ef41816e9648c1bArvydas Sidorenkoint first_init = 1; 60ec16dae5453eafd1586f35c4ec1ef854e5a808e0Jaime Velasco Juan 61ec16dae5453eafd1586f35c4ec1ef854e5a808e0Jaime Velasco Juan/* Some cameras have audio interfaces, we aren't interested in those */ 62ec16dae5453eafd1586f35c4ec1ef854e5a808e0Jaime Velasco Juanstatic struct usb_device_id stkwebcam_table[] = { 63ec16dae5453eafd1586f35c4ec1ef854e5a808e0Jaime Velasco Juan { USB_DEVICE_AND_INTERFACE_INFO(0x174f, 0xa311, 0xff, 0xff, 0xff) }, 64ec16dae5453eafd1586f35c4ec1ef854e5a808e0Jaime Velasco Juan { USB_DEVICE_AND_INTERFACE_INFO(0x05e1, 0x0501, 0xff, 0xff, 0xff) }, 65ec16dae5453eafd1586f35c4ec1ef854e5a808e0Jaime Velasco Juan { } 66ec16dae5453eafd1586f35c4ec1ef854e5a808e0Jaime Velasco Juan}; 67ec16dae5453eafd1586f35c4ec1ef854e5a808e0Jaime Velasco JuanMODULE_DEVICE_TABLE(usb, stkwebcam_table); 68ec16dae5453eafd1586f35c4ec1ef854e5a808e0Jaime Velasco Juan 69ec16dae5453eafd1586f35c4ec1ef854e5a808e0Jaime Velasco Juan/* 70ec16dae5453eafd1586f35c4ec1ef854e5a808e0Jaime Velasco Juan * Basic stuff 71ec16dae5453eafd1586f35c4ec1ef854e5a808e0Jaime Velasco Juan */ 72ec16dae5453eafd1586f35c4ec1ef854e5a808e0Jaime Velasco Juanint stk_camera_write_reg(struct stk_camera *dev, u16 index, u8 value) 73ec16dae5453eafd1586f35c4ec1ef854e5a808e0Jaime Velasco Juan{ 74ec16dae5453eafd1586f35c4ec1ef854e5a808e0Jaime Velasco Juan struct usb_device *udev = dev->udev; 75ec16dae5453eafd1586f35c4ec1ef854e5a808e0Jaime Velasco Juan int ret; 76ec16dae5453eafd1586f35c4ec1ef854e5a808e0Jaime Velasco Juan 77ec16dae5453eafd1586f35c4ec1ef854e5a808e0Jaime Velasco Juan ret = usb_control_msg(udev, usb_sndctrlpipe(udev, 0), 78ec16dae5453eafd1586f35c4ec1ef854e5a808e0Jaime Velasco Juan 0x01, 79ec16dae5453eafd1586f35c4ec1ef854e5a808e0Jaime Velasco Juan USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE, 80ec16dae5453eafd1586f35c4ec1ef854e5a808e0Jaime Velasco Juan value, 81ec16dae5453eafd1586f35c4ec1ef854e5a808e0Jaime Velasco Juan index, 82ec16dae5453eafd1586f35c4ec1ef854e5a808e0Jaime Velasco Juan NULL, 83ec16dae5453eafd1586f35c4ec1ef854e5a808e0Jaime Velasco Juan 0, 84ec16dae5453eafd1586f35c4ec1ef854e5a808e0Jaime Velasco Juan 500); 85ec16dae5453eafd1586f35c4ec1ef854e5a808e0Jaime Velasco Juan if (ret < 0) 86ec16dae5453eafd1586f35c4ec1ef854e5a808e0Jaime Velasco Juan return ret; 87ec16dae5453eafd1586f35c4ec1ef854e5a808e0Jaime Velasco Juan else 88ec16dae5453eafd1586f35c4ec1ef854e5a808e0Jaime Velasco Juan return 0; 89ec16dae5453eafd1586f35c4ec1ef854e5a808e0Jaime Velasco Juan} 90ec16dae5453eafd1586f35c4ec1ef854e5a808e0Jaime Velasco Juan 91ec16dae5453eafd1586f35c4ec1ef854e5a808e0Jaime Velasco Juanint stk_camera_read_reg(struct stk_camera *dev, u16 index, int *value) 92ec16dae5453eafd1586f35c4ec1ef854e5a808e0Jaime Velasco Juan{ 93ec16dae5453eafd1586f35c4ec1ef854e5a808e0Jaime Velasco Juan struct usb_device *udev = dev->udev; 94ec16dae5453eafd1586f35c4ec1ef854e5a808e0Jaime Velasco Juan int ret; 95ec16dae5453eafd1586f35c4ec1ef854e5a808e0Jaime Velasco Juan 96ec16dae5453eafd1586f35c4ec1ef854e5a808e0Jaime Velasco Juan ret = usb_control_msg(udev, usb_rcvctrlpipe(udev, 0), 97ec16dae5453eafd1586f35c4ec1ef854e5a808e0Jaime Velasco Juan 0x00, 98ec16dae5453eafd1586f35c4ec1ef854e5a808e0Jaime Velasco Juan USB_DIR_IN | USB_TYPE_VENDOR | USB_RECIP_DEVICE, 99ec16dae5453eafd1586f35c4ec1ef854e5a808e0Jaime Velasco Juan 0x00, 100ec16dae5453eafd1586f35c4ec1ef854e5a808e0Jaime Velasco Juan index, 101ec16dae5453eafd1586f35c4ec1ef854e5a808e0Jaime Velasco Juan (u8 *) value, 102ec16dae5453eafd1586f35c4ec1ef854e5a808e0Jaime Velasco Juan sizeof(u8), 103ec16dae5453eafd1586f35c4ec1ef854e5a808e0Jaime Velasco Juan 500); 104ec16dae5453eafd1586f35c4ec1ef854e5a808e0Jaime Velasco Juan if (ret < 0) 105ec16dae5453eafd1586f35c4ec1ef854e5a808e0Jaime Velasco Juan return ret; 106ec16dae5453eafd1586f35c4ec1ef854e5a808e0Jaime Velasco Juan else 107ec16dae5453eafd1586f35c4ec1ef854e5a808e0Jaime Velasco Juan return 0; 108ec16dae5453eafd1586f35c4ec1ef854e5a808e0Jaime Velasco Juan} 109ec16dae5453eafd1586f35c4ec1ef854e5a808e0Jaime Velasco Juan 110ec16dae5453eafd1586f35c4ec1ef854e5a808e0Jaime Velasco Juanstatic int stk_start_stream(struct stk_camera *dev) 111ec16dae5453eafd1586f35c4ec1ef854e5a808e0Jaime Velasco Juan{ 112ec16dae5453eafd1586f35c4ec1ef854e5a808e0Jaime Velasco Juan int value; 113ec16dae5453eafd1586f35c4ec1ef854e5a808e0Jaime Velasco Juan int i, ret; 114ec16dae5453eafd1586f35c4ec1ef854e5a808e0Jaime Velasco Juan int value_116, value_117; 115ec16dae5453eafd1586f35c4ec1ef854e5a808e0Jaime Velasco Juan 116ec16dae5453eafd1586f35c4ec1ef854e5a808e0Jaime Velasco Juan if (!is_present(dev)) 117ec16dae5453eafd1586f35c4ec1ef854e5a808e0Jaime Velasco Juan return -ENODEV; 118ec16dae5453eafd1586f35c4ec1ef854e5a808e0Jaime Velasco Juan if (!is_memallocd(dev) || !is_initialised(dev)) { 119ec16dae5453eafd1586f35c4ec1ef854e5a808e0Jaime Velasco Juan STK_ERROR("FIXME: Buffers are not allocated\n"); 120ec16dae5453eafd1586f35c4ec1ef854e5a808e0Jaime Velasco Juan return -EFAULT; 121ec16dae5453eafd1586f35c4ec1ef854e5a808e0Jaime Velasco Juan } 122ec16dae5453eafd1586f35c4ec1ef854e5a808e0Jaime Velasco Juan ret = usb_set_interface(dev->udev, 0, 5); 123ec16dae5453eafd1586f35c4ec1ef854e5a808e0Jaime Velasco Juan 124ec16dae5453eafd1586f35c4ec1ef854e5a808e0Jaime Velasco Juan if (ret < 0) 125ec16dae5453eafd1586f35c4ec1ef854e5a808e0Jaime Velasco Juan STK_ERROR("usb_set_interface failed !\n"); 126ec16dae5453eafd1586f35c4ec1ef854e5a808e0Jaime Velasco Juan if (stk_sensor_wakeup(dev)) 127ec16dae5453eafd1586f35c4ec1ef854e5a808e0Jaime Velasco Juan STK_ERROR("error awaking the sensor\n"); 128ec16dae5453eafd1586f35c4ec1ef854e5a808e0Jaime Velasco Juan 129ec16dae5453eafd1586f35c4ec1ef854e5a808e0Jaime Velasco Juan stk_camera_read_reg(dev, 0x0116, &value_116); 130ec16dae5453eafd1586f35c4ec1ef854e5a808e0Jaime Velasco Juan stk_camera_read_reg(dev, 0x0117, &value_117); 131ec16dae5453eafd1586f35c4ec1ef854e5a808e0Jaime Velasco Juan 132ec16dae5453eafd1586f35c4ec1ef854e5a808e0Jaime Velasco Juan stk_camera_write_reg(dev, 0x0116, 0x0000); 133ec16dae5453eafd1586f35c4ec1ef854e5a808e0Jaime Velasco Juan stk_camera_write_reg(dev, 0x0117, 0x0000); 134ec16dae5453eafd1586f35c4ec1ef854e5a808e0Jaime Velasco Juan 135ec16dae5453eafd1586f35c4ec1ef854e5a808e0Jaime Velasco Juan stk_camera_read_reg(dev, 0x0100, &value); 136ec16dae5453eafd1586f35c4ec1ef854e5a808e0Jaime Velasco Juan stk_camera_write_reg(dev, 0x0100, value | 0x80); 137ec16dae5453eafd1586f35c4ec1ef854e5a808e0Jaime Velasco Juan 138ec16dae5453eafd1586f35c4ec1ef854e5a808e0Jaime Velasco Juan stk_camera_write_reg(dev, 0x0116, value_116); 139ec16dae5453eafd1586f35c4ec1ef854e5a808e0Jaime Velasco Juan stk_camera_write_reg(dev, 0x0117, value_117); 140ec16dae5453eafd1586f35c4ec1ef854e5a808e0Jaime Velasco Juan for (i = 0; i < MAX_ISO_BUFS; i++) { 141ec16dae5453eafd1586f35c4ec1ef854e5a808e0Jaime Velasco Juan if (dev->isobufs[i].urb) { 142ec16dae5453eafd1586f35c4ec1ef854e5a808e0Jaime Velasco Juan ret = usb_submit_urb(dev->isobufs[i].urb, GFP_KERNEL); 143ec16dae5453eafd1586f35c4ec1ef854e5a808e0Jaime Velasco Juan atomic_inc(&dev->urbs_used); 144ec16dae5453eafd1586f35c4ec1ef854e5a808e0Jaime Velasco Juan if (ret) 145ec16dae5453eafd1586f35c4ec1ef854e5a808e0Jaime Velasco Juan return ret; 146ec16dae5453eafd1586f35c4ec1ef854e5a808e0Jaime Velasco Juan } 147ec16dae5453eafd1586f35c4ec1ef854e5a808e0Jaime Velasco Juan } 148ec16dae5453eafd1586f35c4ec1ef854e5a808e0Jaime Velasco Juan set_streaming(dev); 149ec16dae5453eafd1586f35c4ec1ef854e5a808e0Jaime Velasco Juan return 0; 150ec16dae5453eafd1586f35c4ec1ef854e5a808e0Jaime Velasco Juan} 151ec16dae5453eafd1586f35c4ec1ef854e5a808e0Jaime Velasco Juan 152ec16dae5453eafd1586f35c4ec1ef854e5a808e0Jaime Velasco Juanstatic int stk_stop_stream(struct stk_camera *dev) 153ec16dae5453eafd1586f35c4ec1ef854e5a808e0Jaime Velasco Juan{ 154ec16dae5453eafd1586f35c4ec1ef854e5a808e0Jaime Velasco Juan int value; 155ec16dae5453eafd1586f35c4ec1ef854e5a808e0Jaime Velasco Juan int i; 156ec16dae5453eafd1586f35c4ec1ef854e5a808e0Jaime Velasco Juan if (is_present(dev)) { 157ec16dae5453eafd1586f35c4ec1ef854e5a808e0Jaime Velasco Juan stk_camera_read_reg(dev, 0x0100, &value); 158ec16dae5453eafd1586f35c4ec1ef854e5a808e0Jaime Velasco Juan stk_camera_write_reg(dev, 0x0100, value & ~0x80); 159ec16dae5453eafd1586f35c4ec1ef854e5a808e0Jaime Velasco Juan if (dev->isobufs != NULL) { 160ec16dae5453eafd1586f35c4ec1ef854e5a808e0Jaime Velasco Juan for (i = 0; i < MAX_ISO_BUFS; i++) { 161ec16dae5453eafd1586f35c4ec1ef854e5a808e0Jaime Velasco Juan if (dev->isobufs[i].urb) 162ec16dae5453eafd1586f35c4ec1ef854e5a808e0Jaime Velasco Juan usb_kill_urb(dev->isobufs[i].urb); 163ec16dae5453eafd1586f35c4ec1ef854e5a808e0Jaime Velasco Juan } 164ec16dae5453eafd1586f35c4ec1ef854e5a808e0Jaime Velasco Juan } 165ec16dae5453eafd1586f35c4ec1ef854e5a808e0Jaime Velasco Juan unset_streaming(dev); 166ec16dae5453eafd1586f35c4ec1ef854e5a808e0Jaime Velasco Juan 167ec16dae5453eafd1586f35c4ec1ef854e5a808e0Jaime Velasco Juan if (usb_set_interface(dev->udev, 0, 0)) 168ec16dae5453eafd1586f35c4ec1ef854e5a808e0Jaime Velasco Juan STK_ERROR("usb_set_interface failed !\n"); 169ec16dae5453eafd1586f35c4ec1ef854e5a808e0Jaime Velasco Juan if (stk_sensor_sleep(dev)) 170ec16dae5453eafd1586f35c4ec1ef854e5a808e0Jaime Velasco Juan STK_ERROR("error suspending the sensor\n"); 171ec16dae5453eafd1586f35c4ec1ef854e5a808e0Jaime Velasco Juan } 172ec16dae5453eafd1586f35c4ec1ef854e5a808e0Jaime Velasco Juan return 0; 173ec16dae5453eafd1586f35c4ec1ef854e5a808e0Jaime Velasco Juan} 174ec16dae5453eafd1586f35c4ec1ef854e5a808e0Jaime Velasco Juan 175ec16dae5453eafd1586f35c4ec1ef854e5a808e0Jaime Velasco Juan/* 176ec16dae5453eafd1586f35c4ec1ef854e5a808e0Jaime Velasco Juan * This seems to be the shortest init sequence we 177ec16dae5453eafd1586f35c4ec1ef854e5a808e0Jaime Velasco Juan * must do in order to find the sensor 178ec16dae5453eafd1586f35c4ec1ef854e5a808e0Jaime Velasco Juan * Bit 5 of reg. 0x0000 here is important, when reset to 0 the sensor 179ec16dae5453eafd1586f35c4ec1ef854e5a808e0Jaime Velasco Juan * is also reset. Maybe powers down it? 180ec16dae5453eafd1586f35c4ec1ef854e5a808e0Jaime Velasco Juan * Rest of values don't make a difference 181ec16dae5453eafd1586f35c4ec1ef854e5a808e0Jaime Velasco Juan */ 182ec16dae5453eafd1586f35c4ec1ef854e5a808e0Jaime Velasco Juan 183ec16dae5453eafd1586f35c4ec1ef854e5a808e0Jaime Velasco Juanstatic struct regval stk1125_initvals[] = { 184ec16dae5453eafd1586f35c4ec1ef854e5a808e0Jaime Velasco Juan /*TODO: What means this sequence? */ 185ec16dae5453eafd1586f35c4ec1ef854e5a808e0Jaime Velasco Juan {0x0000, 0x24}, 186ec16dae5453eafd1586f35c4ec1ef854e5a808e0Jaime Velasco Juan {0x0100, 0x21}, 187ec16dae5453eafd1586f35c4ec1ef854e5a808e0Jaime Velasco Juan {0x0002, 0x68}, 188ec16dae5453eafd1586f35c4ec1ef854e5a808e0Jaime Velasco Juan {0x0003, 0x80}, 189ec16dae5453eafd1586f35c4ec1ef854e5a808e0Jaime Velasco Juan {0x0005, 0x00}, 190ec16dae5453eafd1586f35c4ec1ef854e5a808e0Jaime Velasco Juan {0x0007, 0x03}, 191ec16dae5453eafd1586f35c4ec1ef854e5a808e0Jaime Velasco Juan {0x000d, 0x00}, 192ec16dae5453eafd1586f35c4ec1ef854e5a808e0Jaime Velasco Juan {0x000f, 0x02}, 193ec16dae5453eafd1586f35c4ec1ef854e5a808e0Jaime Velasco Juan {0x0300, 0x12}, 194ec16dae5453eafd1586f35c4ec1ef854e5a808e0Jaime Velasco Juan {0x0350, 0x41}, 195ec16dae5453eafd1586f35c4ec1ef854e5a808e0Jaime Velasco Juan {0x0351, 0x00}, 196ec16dae5453eafd1586f35c4ec1ef854e5a808e0Jaime Velasco Juan {0x0352, 0x00}, 197ec16dae5453eafd1586f35c4ec1ef854e5a808e0Jaime Velasco Juan {0x0353, 0x00}, 198ec16dae5453eafd1586f35c4ec1ef854e5a808e0Jaime Velasco Juan {0x0018, 0x10}, 199ec16dae5453eafd1586f35c4ec1ef854e5a808e0Jaime Velasco Juan {0x0019, 0x00}, 200ec16dae5453eafd1586f35c4ec1ef854e5a808e0Jaime Velasco Juan {0x001b, 0x0e}, 201ec16dae5453eafd1586f35c4ec1ef854e5a808e0Jaime Velasco Juan {0x001c, 0x46}, 202ec16dae5453eafd1586f35c4ec1ef854e5a808e0Jaime Velasco Juan {0x0300, 0x80}, 203ec16dae5453eafd1586f35c4ec1ef854e5a808e0Jaime Velasco Juan {0x001a, 0x04}, 204ec16dae5453eafd1586f35c4ec1ef854e5a808e0Jaime Velasco Juan {0x0110, 0x00}, 205ec16dae5453eafd1586f35c4ec1ef854e5a808e0Jaime Velasco Juan {0x0111, 0x00}, 206ec16dae5453eafd1586f35c4ec1ef854e5a808e0Jaime Velasco Juan {0x0112, 0x00}, 207ec16dae5453eafd1586f35c4ec1ef854e5a808e0Jaime Velasco Juan {0x0113, 0x00}, 208ec16dae5453eafd1586f35c4ec1ef854e5a808e0Jaime Velasco Juan 209ec16dae5453eafd1586f35c4ec1ef854e5a808e0Jaime Velasco Juan {0xffff, 0xff}, 210ec16dae5453eafd1586f35c4ec1ef854e5a808e0Jaime Velasco Juan}; 211ec16dae5453eafd1586f35c4ec1ef854e5a808e0Jaime Velasco Juan 212ec16dae5453eafd1586f35c4ec1ef854e5a808e0Jaime Velasco Juan 213ec16dae5453eafd1586f35c4ec1ef854e5a808e0Jaime Velasco Juanstatic int stk_initialise(struct stk_camera *dev) 214ec16dae5453eafd1586f35c4ec1ef854e5a808e0Jaime Velasco Juan{ 215ec16dae5453eafd1586f35c4ec1ef854e5a808e0Jaime Velasco Juan struct regval *rv; 216ec16dae5453eafd1586f35c4ec1ef854e5a808e0Jaime Velasco Juan int ret; 217ec16dae5453eafd1586f35c4ec1ef854e5a808e0Jaime Velasco Juan if (!is_present(dev)) 218ec16dae5453eafd1586f35c4ec1ef854e5a808e0Jaime Velasco Juan return -ENODEV; 219ec16dae5453eafd1586f35c4ec1ef854e5a808e0Jaime Velasco Juan if (is_initialised(dev)) 220ec16dae5453eafd1586f35c4ec1ef854e5a808e0Jaime Velasco Juan return 0; 221ec16dae5453eafd1586f35c4ec1ef854e5a808e0Jaime Velasco Juan rv = stk1125_initvals; 222ec16dae5453eafd1586f35c4ec1ef854e5a808e0Jaime Velasco Juan while (rv->reg != 0xffff) { 223ec16dae5453eafd1586f35c4ec1ef854e5a808e0Jaime Velasco Juan ret = stk_camera_write_reg(dev, rv->reg, rv->val); 224ec16dae5453eafd1586f35c4ec1ef854e5a808e0Jaime Velasco Juan if (ret) 225ec16dae5453eafd1586f35c4ec1ef854e5a808e0Jaime Velasco Juan return ret; 226ec16dae5453eafd1586f35c4ec1ef854e5a808e0Jaime Velasco Juan rv++; 227ec16dae5453eafd1586f35c4ec1ef854e5a808e0Jaime Velasco Juan } 228ec16dae5453eafd1586f35c4ec1ef854e5a808e0Jaime Velasco Juan if (stk_sensor_init(dev) == 0) { 229ec16dae5453eafd1586f35c4ec1ef854e5a808e0Jaime Velasco Juan set_initialised(dev); 230ec16dae5453eafd1586f35c4ec1ef854e5a808e0Jaime Velasco Juan return 0; 231ec16dae5453eafd1586f35c4ec1ef854e5a808e0Jaime Velasco Juan } else 232ec16dae5453eafd1586f35c4ec1ef854e5a808e0Jaime Velasco Juan return -1; 233ec16dae5453eafd1586f35c4ec1ef854e5a808e0Jaime Velasco Juan} 234ec16dae5453eafd1586f35c4ec1ef854e5a808e0Jaime Velasco Juan 235ec16dae5453eafd1586f35c4ec1ef854e5a808e0Jaime Velasco Juan/* *********************************************** */ 236ec16dae5453eafd1586f35c4ec1ef854e5a808e0Jaime Velasco Juan/* 237ec16dae5453eafd1586f35c4ec1ef854e5a808e0Jaime Velasco Juan * This function is called as an URB transfert is complete (Isochronous pipe). 238ec16dae5453eafd1586f35c4ec1ef854e5a808e0Jaime Velasco Juan * So, the traitement is done in interrupt time, so it has be fast, not crash, 239ec16dae5453eafd1586f35c4ec1ef854e5a808e0Jaime Velasco Juan * and not stall. Neat. 240ec16dae5453eafd1586f35c4ec1ef854e5a808e0Jaime Velasco Juan */ 241ec16dae5453eafd1586f35c4ec1ef854e5a808e0Jaime Velasco Juanstatic void stk_isoc_handler(struct urb *urb) 242ec16dae5453eafd1586f35c4ec1ef854e5a808e0Jaime Velasco Juan{ 243ec16dae5453eafd1586f35c4ec1ef854e5a808e0Jaime Velasco Juan int i; 244ec16dae5453eafd1586f35c4ec1ef854e5a808e0Jaime Velasco Juan int ret; 245ec16dae5453eafd1586f35c4ec1ef854e5a808e0Jaime Velasco Juan int framelen; 246ec16dae5453eafd1586f35c4ec1ef854e5a808e0Jaime Velasco Juan unsigned long flags; 247ec16dae5453eafd1586f35c4ec1ef854e5a808e0Jaime Velasco Juan 248ec16dae5453eafd1586f35c4ec1ef854e5a808e0Jaime Velasco Juan unsigned char *fill = NULL; 249ec16dae5453eafd1586f35c4ec1ef854e5a808e0Jaime Velasco Juan unsigned char *iso_buf = NULL; 250ec16dae5453eafd1586f35c4ec1ef854e5a808e0Jaime Velasco Juan 251ec16dae5453eafd1586f35c4ec1ef854e5a808e0Jaime Velasco Juan struct stk_camera *dev; 252ec16dae5453eafd1586f35c4ec1ef854e5a808e0Jaime Velasco Juan struct stk_sio_buffer *fb; 253ec16dae5453eafd1586f35c4ec1ef854e5a808e0Jaime Velasco Juan 254ec16dae5453eafd1586f35c4ec1ef854e5a808e0Jaime Velasco Juan dev = (struct stk_camera *) urb->context; 255ec16dae5453eafd1586f35c4ec1ef854e5a808e0Jaime Velasco Juan 256ec16dae5453eafd1586f35c4ec1ef854e5a808e0Jaime Velasco Juan if (dev == NULL) { 257ec16dae5453eafd1586f35c4ec1ef854e5a808e0Jaime Velasco Juan STK_ERROR("isoc_handler called with NULL device !\n"); 258ec16dae5453eafd1586f35c4ec1ef854e5a808e0Jaime Velasco Juan return; 259ec16dae5453eafd1586f35c4ec1ef854e5a808e0Jaime Velasco Juan } 260ec16dae5453eafd1586f35c4ec1ef854e5a808e0Jaime Velasco Juan 261ec16dae5453eafd1586f35c4ec1ef854e5a808e0Jaime Velasco Juan if (urb->status == -ENOENT || urb->status == -ECONNRESET 262ec16dae5453eafd1586f35c4ec1ef854e5a808e0Jaime Velasco Juan || urb->status == -ESHUTDOWN) { 263ec16dae5453eafd1586f35c4ec1ef854e5a808e0Jaime Velasco Juan atomic_dec(&dev->urbs_used); 264ec16dae5453eafd1586f35c4ec1ef854e5a808e0Jaime Velasco Juan return; 265ec16dae5453eafd1586f35c4ec1ef854e5a808e0Jaime Velasco Juan } 266ec16dae5453eafd1586f35c4ec1ef854e5a808e0Jaime Velasco Juan 267ec16dae5453eafd1586f35c4ec1ef854e5a808e0Jaime Velasco Juan spin_lock_irqsave(&dev->spinlock, flags); 268ec16dae5453eafd1586f35c4ec1ef854e5a808e0Jaime Velasco Juan 269ec16dae5453eafd1586f35c4ec1ef854e5a808e0Jaime Velasco Juan if (urb->status != -EINPROGRESS && urb->status != 0) { 270ec16dae5453eafd1586f35c4ec1ef854e5a808e0Jaime Velasco Juan STK_ERROR("isoc_handler: urb->status == %d\n", urb->status); 271ec16dae5453eafd1586f35c4ec1ef854e5a808e0Jaime Velasco Juan goto resubmit; 272ec16dae5453eafd1586f35c4ec1ef854e5a808e0Jaime Velasco Juan } 273ec16dae5453eafd1586f35c4ec1ef854e5a808e0Jaime Velasco Juan 274ec16dae5453eafd1586f35c4ec1ef854e5a808e0Jaime Velasco Juan if (list_empty(&dev->sio_avail)) { 275ec16dae5453eafd1586f35c4ec1ef854e5a808e0Jaime Velasco Juan /*FIXME Stop streaming after a while */ 276ec16dae5453eafd1586f35c4ec1ef854e5a808e0Jaime Velasco Juan (void) (printk_ratelimit() && 277ec16dae5453eafd1586f35c4ec1ef854e5a808e0Jaime Velasco Juan STK_ERROR("isoc_handler without available buffer!\n")); 278ec16dae5453eafd1586f35c4ec1ef854e5a808e0Jaime Velasco Juan goto resubmit; 279ec16dae5453eafd1586f35c4ec1ef854e5a808e0Jaime Velasco Juan } 280ec16dae5453eafd1586f35c4ec1ef854e5a808e0Jaime Velasco Juan fb = list_first_entry(&dev->sio_avail, 281ec16dae5453eafd1586f35c4ec1ef854e5a808e0Jaime Velasco Juan struct stk_sio_buffer, list); 282ec16dae5453eafd1586f35c4ec1ef854e5a808e0Jaime Velasco Juan fill = fb->buffer + fb->v4lbuf.bytesused; 283ec16dae5453eafd1586f35c4ec1ef854e5a808e0Jaime Velasco Juan 284ec16dae5453eafd1586f35c4ec1ef854e5a808e0Jaime Velasco Juan for (i = 0; i < urb->number_of_packets; i++) { 285ec16dae5453eafd1586f35c4ec1ef854e5a808e0Jaime Velasco Juan if (urb->iso_frame_desc[i].status != 0) { 286ec16dae5453eafd1586f35c4ec1ef854e5a808e0Jaime Velasco Juan if (urb->iso_frame_desc[i].status != -EXDEV) 287ec16dae5453eafd1586f35c4ec1ef854e5a808e0Jaime Velasco Juan STK_ERROR("Frame %d has error %d\n", i, 288ec16dae5453eafd1586f35c4ec1ef854e5a808e0Jaime Velasco Juan urb->iso_frame_desc[i].status); 289ec16dae5453eafd1586f35c4ec1ef854e5a808e0Jaime Velasco Juan continue; 290ec16dae5453eafd1586f35c4ec1ef854e5a808e0Jaime Velasco Juan } 291ec16dae5453eafd1586f35c4ec1ef854e5a808e0Jaime Velasco Juan framelen = urb->iso_frame_desc[i].actual_length; 292ec16dae5453eafd1586f35c4ec1ef854e5a808e0Jaime Velasco Juan iso_buf = urb->transfer_buffer + urb->iso_frame_desc[i].offset; 293ec16dae5453eafd1586f35c4ec1ef854e5a808e0Jaime Velasco Juan 294ec16dae5453eafd1586f35c4ec1ef854e5a808e0Jaime Velasco Juan if (framelen <= 4) 295ec16dae5453eafd1586f35c4ec1ef854e5a808e0Jaime Velasco Juan continue; /* no data */ 296ec16dae5453eafd1586f35c4ec1ef854e5a808e0Jaime Velasco Juan 297ec16dae5453eafd1586f35c4ec1ef854e5a808e0Jaime Velasco Juan /* 298ec16dae5453eafd1586f35c4ec1ef854e5a808e0Jaime Velasco Juan * we found something informational from there 299ec16dae5453eafd1586f35c4ec1ef854e5a808e0Jaime Velasco Juan * the isoc frames have to type of headers 300ec16dae5453eafd1586f35c4ec1ef854e5a808e0Jaime Velasco Juan * type1: 00 xx 00 00 or 20 xx 00 00 301ec16dae5453eafd1586f35c4ec1ef854e5a808e0Jaime Velasco Juan * type2: 80 xx 00 00 00 00 00 00 or a0 xx 00 00 00 00 00 00 302ec16dae5453eafd1586f35c4ec1ef854e5a808e0Jaime Velasco Juan * xx is a sequencer which has never been seen over 0x3f 303ec16dae5453eafd1586f35c4ec1ef854e5a808e0Jaime Velasco Juan * imho data written down looks like bayer, i see similarities 304ec16dae5453eafd1586f35c4ec1ef854e5a808e0Jaime Velasco Juan * after every 640 bytes 305ec16dae5453eafd1586f35c4ec1ef854e5a808e0Jaime Velasco Juan */ 306ec16dae5453eafd1586f35c4ec1ef854e5a808e0Jaime Velasco Juan if (*iso_buf & 0x80) { 307ec16dae5453eafd1586f35c4ec1ef854e5a808e0Jaime Velasco Juan framelen -= 8; 308ec16dae5453eafd1586f35c4ec1ef854e5a808e0Jaime Velasco Juan iso_buf += 8; 309ec16dae5453eafd1586f35c4ec1ef854e5a808e0Jaime Velasco Juan /* This marks a new frame */ 310ec16dae5453eafd1586f35c4ec1ef854e5a808e0Jaime Velasco Juan if (fb->v4lbuf.bytesused != 0 311ec16dae5453eafd1586f35c4ec1ef854e5a808e0Jaime Velasco Juan && fb->v4lbuf.bytesused != dev->frame_size) { 312ec16dae5453eafd1586f35c4ec1ef854e5a808e0Jaime Velasco Juan (void) (printk_ratelimit() && 313ec16dae5453eafd1586f35c4ec1ef854e5a808e0Jaime Velasco Juan STK_ERROR("frame %d, " 314ec16dae5453eafd1586f35c4ec1ef854e5a808e0Jaime Velasco Juan "bytesused=%d, skipping\n", 315ec16dae5453eafd1586f35c4ec1ef854e5a808e0Jaime Velasco Juan i, fb->v4lbuf.bytesused)); 316ec16dae5453eafd1586f35c4ec1ef854e5a808e0Jaime Velasco Juan fb->v4lbuf.bytesused = 0; 317ec16dae5453eafd1586f35c4ec1ef854e5a808e0Jaime Velasco Juan fill = fb->buffer; 318ec16dae5453eafd1586f35c4ec1ef854e5a808e0Jaime Velasco Juan } else if (fb->v4lbuf.bytesused == dev->frame_size) { 319b18559076a31ab0be2d980ce2beff8e32504e080Jaime Velasco Juan if (list_is_singular(&dev->sio_avail)) { 320b18559076a31ab0be2d980ce2beff8e32504e080Jaime Velasco Juan /* Always reuse the last buffer */ 321b18559076a31ab0be2d980ce2beff8e32504e080Jaime Velasco Juan fb->v4lbuf.bytesused = 0; 322b18559076a31ab0be2d980ce2beff8e32504e080Jaime Velasco Juan fill = fb->buffer; 323b18559076a31ab0be2d980ce2beff8e32504e080Jaime Velasco Juan } else { 324b18559076a31ab0be2d980ce2beff8e32504e080Jaime Velasco Juan list_move_tail(dev->sio_avail.next, 325b18559076a31ab0be2d980ce2beff8e32504e080Jaime Velasco Juan &dev->sio_full); 326b18559076a31ab0be2d980ce2beff8e32504e080Jaime Velasco Juan wake_up(&dev->wait_frame); 327b18559076a31ab0be2d980ce2beff8e32504e080Jaime Velasco Juan fb = list_first_entry(&dev->sio_avail, 328b18559076a31ab0be2d980ce2beff8e32504e080Jaime Velasco Juan struct stk_sio_buffer, list); 329b18559076a31ab0be2d980ce2beff8e32504e080Jaime Velasco Juan fb->v4lbuf.bytesused = 0; 330b18559076a31ab0be2d980ce2beff8e32504e080Jaime Velasco Juan fill = fb->buffer; 331ec16dae5453eafd1586f35c4ec1ef854e5a808e0Jaime Velasco Juan } 332ec16dae5453eafd1586f35c4ec1ef854e5a808e0Jaime Velasco Juan } 333ec16dae5453eafd1586f35c4ec1ef854e5a808e0Jaime Velasco Juan } else { 334ec16dae5453eafd1586f35c4ec1ef854e5a808e0Jaime Velasco Juan framelen -= 4; 335ec16dae5453eafd1586f35c4ec1ef854e5a808e0Jaime Velasco Juan iso_buf += 4; 336ec16dae5453eafd1586f35c4ec1ef854e5a808e0Jaime Velasco Juan } 337ec16dae5453eafd1586f35c4ec1ef854e5a808e0Jaime Velasco Juan 338ec16dae5453eafd1586f35c4ec1ef854e5a808e0Jaime Velasco Juan /* Our buffer is full !!! */ 339ec16dae5453eafd1586f35c4ec1ef854e5a808e0Jaime Velasco Juan if (framelen + fb->v4lbuf.bytesused > dev->frame_size) { 340ec16dae5453eafd1586f35c4ec1ef854e5a808e0Jaime Velasco Juan (void) (printk_ratelimit() && 341ec16dae5453eafd1586f35c4ec1ef854e5a808e0Jaime Velasco Juan STK_ERROR("Frame buffer overflow, lost sync\n")); 342ec16dae5453eafd1586f35c4ec1ef854e5a808e0Jaime Velasco Juan /*FIXME Do something here? */ 343ec16dae5453eafd1586f35c4ec1ef854e5a808e0Jaime Velasco Juan continue; 344ec16dae5453eafd1586f35c4ec1ef854e5a808e0Jaime Velasco Juan } 345ec16dae5453eafd1586f35c4ec1ef854e5a808e0Jaime Velasco Juan spin_unlock_irqrestore(&dev->spinlock, flags); 346ec16dae5453eafd1586f35c4ec1ef854e5a808e0Jaime Velasco Juan memcpy(fill, iso_buf, framelen); 347ec16dae5453eafd1586f35c4ec1ef854e5a808e0Jaime Velasco Juan spin_lock_irqsave(&dev->spinlock, flags); 348ec16dae5453eafd1586f35c4ec1ef854e5a808e0Jaime Velasco Juan fill += framelen; 349ec16dae5453eafd1586f35c4ec1ef854e5a808e0Jaime Velasco Juan 350ec16dae5453eafd1586f35c4ec1ef854e5a808e0Jaime Velasco Juan /* New size of our buffer */ 351ec16dae5453eafd1586f35c4ec1ef854e5a808e0Jaime Velasco Juan fb->v4lbuf.bytesused += framelen; 352ec16dae5453eafd1586f35c4ec1ef854e5a808e0Jaime Velasco Juan } 353ec16dae5453eafd1586f35c4ec1ef854e5a808e0Jaime Velasco Juan 354ec16dae5453eafd1586f35c4ec1ef854e5a808e0Jaime Velasco Juanresubmit: 355ec16dae5453eafd1586f35c4ec1ef854e5a808e0Jaime Velasco Juan spin_unlock_irqrestore(&dev->spinlock, flags); 356ec16dae5453eafd1586f35c4ec1ef854e5a808e0Jaime Velasco Juan urb->dev = dev->udev; 357ec16dae5453eafd1586f35c4ec1ef854e5a808e0Jaime Velasco Juan ret = usb_submit_urb(urb, GFP_ATOMIC); 358ec16dae5453eafd1586f35c4ec1ef854e5a808e0Jaime Velasco Juan if (ret != 0) { 359ec16dae5453eafd1586f35c4ec1ef854e5a808e0Jaime Velasco Juan STK_ERROR("Error (%d) re-submitting urb in stk_isoc_handler.\n", 360ec16dae5453eafd1586f35c4ec1ef854e5a808e0Jaime Velasco Juan ret); 361ec16dae5453eafd1586f35c4ec1ef854e5a808e0Jaime Velasco Juan } 362ec16dae5453eafd1586f35c4ec1ef854e5a808e0Jaime Velasco Juan} 363ec16dae5453eafd1586f35c4ec1ef854e5a808e0Jaime Velasco Juan 364ec16dae5453eafd1586f35c4ec1ef854e5a808e0Jaime Velasco Juan/* -------------------------------------------- */ 365ec16dae5453eafd1586f35c4ec1ef854e5a808e0Jaime Velasco Juan 366ec16dae5453eafd1586f35c4ec1ef854e5a808e0Jaime Velasco Juanstatic int stk_prepare_iso(struct stk_camera *dev) 367ec16dae5453eafd1586f35c4ec1ef854e5a808e0Jaime Velasco Juan{ 368ec16dae5453eafd1586f35c4ec1ef854e5a808e0Jaime Velasco Juan void *kbuf; 369ec16dae5453eafd1586f35c4ec1ef854e5a808e0Jaime Velasco Juan int i, j; 370ec16dae5453eafd1586f35c4ec1ef854e5a808e0Jaime Velasco Juan struct urb *urb; 371ec16dae5453eafd1586f35c4ec1ef854e5a808e0Jaime Velasco Juan struct usb_device *udev; 372ec16dae5453eafd1586f35c4ec1ef854e5a808e0Jaime Velasco Juan 373ec16dae5453eafd1586f35c4ec1ef854e5a808e0Jaime Velasco Juan if (dev == NULL) 374ec16dae5453eafd1586f35c4ec1ef854e5a808e0Jaime Velasco Juan return -ENXIO; 375ec16dae5453eafd1586f35c4ec1ef854e5a808e0Jaime Velasco Juan udev = dev->udev; 376ec16dae5453eafd1586f35c4ec1ef854e5a808e0Jaime Velasco Juan 377ec16dae5453eafd1586f35c4ec1ef854e5a808e0Jaime Velasco Juan if (dev->isobufs) 378ec16dae5453eafd1586f35c4ec1ef854e5a808e0Jaime Velasco Juan STK_ERROR("isobufs already allocated. Bad\n"); 379ec16dae5453eafd1586f35c4ec1ef854e5a808e0Jaime Velasco Juan else 3809884d7bea756a4657c6a5d20249bffadc460e140Thomas Meyer dev->isobufs = kcalloc(MAX_ISO_BUFS, sizeof(*dev->isobufs), 3819884d7bea756a4657c6a5d20249bffadc460e140Thomas Meyer GFP_KERNEL); 382ec16dae5453eafd1586f35c4ec1ef854e5a808e0Jaime Velasco Juan if (dev->isobufs == NULL) { 383ec16dae5453eafd1586f35c4ec1ef854e5a808e0Jaime Velasco Juan STK_ERROR("Unable to allocate iso buffers\n"); 384ec16dae5453eafd1586f35c4ec1ef854e5a808e0Jaime Velasco Juan return -ENOMEM; 385ec16dae5453eafd1586f35c4ec1ef854e5a808e0Jaime Velasco Juan } 386ec16dae5453eafd1586f35c4ec1ef854e5a808e0Jaime Velasco Juan for (i = 0; i < MAX_ISO_BUFS; i++) { 387ec16dae5453eafd1586f35c4ec1ef854e5a808e0Jaime Velasco Juan if (dev->isobufs[i].data == NULL) { 388ec16dae5453eafd1586f35c4ec1ef854e5a808e0Jaime Velasco Juan kbuf = kzalloc(ISO_BUFFER_SIZE, GFP_KERNEL); 389ec16dae5453eafd1586f35c4ec1ef854e5a808e0Jaime Velasco Juan if (kbuf == NULL) { 390ec16dae5453eafd1586f35c4ec1ef854e5a808e0Jaime Velasco Juan STK_ERROR("Failed to allocate iso buffer %d\n", 391ec16dae5453eafd1586f35c4ec1ef854e5a808e0Jaime Velasco Juan i); 392ec16dae5453eafd1586f35c4ec1ef854e5a808e0Jaime Velasco Juan goto isobufs_out; 393ec16dae5453eafd1586f35c4ec1ef854e5a808e0Jaime Velasco Juan } 394ec16dae5453eafd1586f35c4ec1ef854e5a808e0Jaime Velasco Juan dev->isobufs[i].data = kbuf; 395ec16dae5453eafd1586f35c4ec1ef854e5a808e0Jaime Velasco Juan } else 396ec16dae5453eafd1586f35c4ec1ef854e5a808e0Jaime Velasco Juan STK_ERROR("isobuf data already allocated\n"); 397ec16dae5453eafd1586f35c4ec1ef854e5a808e0Jaime Velasco Juan if (dev->isobufs[i].urb == NULL) { 398ec16dae5453eafd1586f35c4ec1ef854e5a808e0Jaime Velasco Juan urb = usb_alloc_urb(ISO_FRAMES_PER_DESC, GFP_KERNEL); 399ec16dae5453eafd1586f35c4ec1ef854e5a808e0Jaime Velasco Juan if (urb == NULL) { 400ec16dae5453eafd1586f35c4ec1ef854e5a808e0Jaime Velasco Juan STK_ERROR("Failed to allocate URB %d\n", i); 401ec16dae5453eafd1586f35c4ec1ef854e5a808e0Jaime Velasco Juan goto isobufs_out; 402ec16dae5453eafd1586f35c4ec1ef854e5a808e0Jaime Velasco Juan } 403ec16dae5453eafd1586f35c4ec1ef854e5a808e0Jaime Velasco Juan dev->isobufs[i].urb = urb; 404ec16dae5453eafd1586f35c4ec1ef854e5a808e0Jaime Velasco Juan } else { 405ec16dae5453eafd1586f35c4ec1ef854e5a808e0Jaime Velasco Juan STK_ERROR("Killing URB\n"); 406ec16dae5453eafd1586f35c4ec1ef854e5a808e0Jaime Velasco Juan usb_kill_urb(dev->isobufs[i].urb); 407ec16dae5453eafd1586f35c4ec1ef854e5a808e0Jaime Velasco Juan urb = dev->isobufs[i].urb; 408ec16dae5453eafd1586f35c4ec1ef854e5a808e0Jaime Velasco Juan } 409ec16dae5453eafd1586f35c4ec1ef854e5a808e0Jaime Velasco Juan urb->interval = 1; 410ec16dae5453eafd1586f35c4ec1ef854e5a808e0Jaime Velasco Juan urb->dev = udev; 411ec16dae5453eafd1586f35c4ec1ef854e5a808e0Jaime Velasco Juan urb->pipe = usb_rcvisocpipe(udev, dev->isoc_ep); 412ec16dae5453eafd1586f35c4ec1ef854e5a808e0Jaime Velasco Juan urb->transfer_flags = URB_ISO_ASAP; 413ec16dae5453eafd1586f35c4ec1ef854e5a808e0Jaime Velasco Juan urb->transfer_buffer = dev->isobufs[i].data; 414ec16dae5453eafd1586f35c4ec1ef854e5a808e0Jaime Velasco Juan urb->transfer_buffer_length = ISO_BUFFER_SIZE; 415ec16dae5453eafd1586f35c4ec1ef854e5a808e0Jaime Velasco Juan urb->complete = stk_isoc_handler; 416ec16dae5453eafd1586f35c4ec1ef854e5a808e0Jaime Velasco Juan urb->context = dev; 417ec16dae5453eafd1586f35c4ec1ef854e5a808e0Jaime Velasco Juan urb->start_frame = 0; 418ec16dae5453eafd1586f35c4ec1ef854e5a808e0Jaime Velasco Juan urb->number_of_packets = ISO_FRAMES_PER_DESC; 419ec16dae5453eafd1586f35c4ec1ef854e5a808e0Jaime Velasco Juan 420ec16dae5453eafd1586f35c4ec1ef854e5a808e0Jaime Velasco Juan for (j = 0; j < ISO_FRAMES_PER_DESC; j++) { 421ec16dae5453eafd1586f35c4ec1ef854e5a808e0Jaime Velasco Juan urb->iso_frame_desc[j].offset = j * ISO_MAX_FRAME_SIZE; 422ec16dae5453eafd1586f35c4ec1ef854e5a808e0Jaime Velasco Juan urb->iso_frame_desc[j].length = ISO_MAX_FRAME_SIZE; 423ec16dae5453eafd1586f35c4ec1ef854e5a808e0Jaime Velasco Juan } 424ec16dae5453eafd1586f35c4ec1ef854e5a808e0Jaime Velasco Juan } 425ec16dae5453eafd1586f35c4ec1ef854e5a808e0Jaime Velasco Juan set_memallocd(dev); 426ec16dae5453eafd1586f35c4ec1ef854e5a808e0Jaime Velasco Juan return 0; 427ec16dae5453eafd1586f35c4ec1ef854e5a808e0Jaime Velasco Juan 428ec16dae5453eafd1586f35c4ec1ef854e5a808e0Jaime Velasco Juanisobufs_out: 429ec16dae5453eafd1586f35c4ec1ef854e5a808e0Jaime Velasco Juan for (i = 0; i < MAX_ISO_BUFS && dev->isobufs[i].data; i++) 430ec16dae5453eafd1586f35c4ec1ef854e5a808e0Jaime Velasco Juan kfree(dev->isobufs[i].data); 431ec16dae5453eafd1586f35c4ec1ef854e5a808e0Jaime Velasco Juan for (i = 0; i < MAX_ISO_BUFS && dev->isobufs[i].urb; i++) 432ec16dae5453eafd1586f35c4ec1ef854e5a808e0Jaime Velasco Juan usb_free_urb(dev->isobufs[i].urb); 433ec16dae5453eafd1586f35c4ec1ef854e5a808e0Jaime Velasco Juan kfree(dev->isobufs); 434ec16dae5453eafd1586f35c4ec1ef854e5a808e0Jaime Velasco Juan dev->isobufs = NULL; 435ec16dae5453eafd1586f35c4ec1ef854e5a808e0Jaime Velasco Juan return -ENOMEM; 436ec16dae5453eafd1586f35c4ec1ef854e5a808e0Jaime Velasco Juan} 437ec16dae5453eafd1586f35c4ec1ef854e5a808e0Jaime Velasco Juan 438ec16dae5453eafd1586f35c4ec1ef854e5a808e0Jaime Velasco Juanstatic void stk_clean_iso(struct stk_camera *dev) 439ec16dae5453eafd1586f35c4ec1ef854e5a808e0Jaime Velasco Juan{ 440ec16dae5453eafd1586f35c4ec1ef854e5a808e0Jaime Velasco Juan int i; 441ec16dae5453eafd1586f35c4ec1ef854e5a808e0Jaime Velasco Juan 442ec16dae5453eafd1586f35c4ec1ef854e5a808e0Jaime Velasco Juan if (dev == NULL || dev->isobufs == NULL) 443ec16dae5453eafd1586f35c4ec1ef854e5a808e0Jaime Velasco Juan return; 444ec16dae5453eafd1586f35c4ec1ef854e5a808e0Jaime Velasco Juan 445ec16dae5453eafd1586f35c4ec1ef854e5a808e0Jaime Velasco Juan for (i = 0; i < MAX_ISO_BUFS; i++) { 446ec16dae5453eafd1586f35c4ec1ef854e5a808e0Jaime Velasco Juan struct urb *urb; 447ec16dae5453eafd1586f35c4ec1ef854e5a808e0Jaime Velasco Juan 448ec16dae5453eafd1586f35c4ec1ef854e5a808e0Jaime Velasco Juan urb = dev->isobufs[i].urb; 449ec16dae5453eafd1586f35c4ec1ef854e5a808e0Jaime Velasco Juan if (urb) { 450f051ae1866e67567b4f33371969dee9cdddb34edDavid Ellingsworth if (atomic_read(&dev->urbs_used) && is_present(dev)) 451ec16dae5453eafd1586f35c4ec1ef854e5a808e0Jaime Velasco Juan usb_kill_urb(urb); 452ec16dae5453eafd1586f35c4ec1ef854e5a808e0Jaime Velasco Juan usb_free_urb(urb); 453ec16dae5453eafd1586f35c4ec1ef854e5a808e0Jaime Velasco Juan } 454ec16dae5453eafd1586f35c4ec1ef854e5a808e0Jaime Velasco Juan kfree(dev->isobufs[i].data); 455ec16dae5453eafd1586f35c4ec1ef854e5a808e0Jaime Velasco Juan } 456ec16dae5453eafd1586f35c4ec1ef854e5a808e0Jaime Velasco Juan kfree(dev->isobufs); 457ec16dae5453eafd1586f35c4ec1ef854e5a808e0Jaime Velasco Juan dev->isobufs = NULL; 458ec16dae5453eafd1586f35c4ec1ef854e5a808e0Jaime Velasco Juan unset_memallocd(dev); 459ec16dae5453eafd1586f35c4ec1ef854e5a808e0Jaime Velasco Juan} 460ec16dae5453eafd1586f35c4ec1ef854e5a808e0Jaime Velasco Juan 461ec16dae5453eafd1586f35c4ec1ef854e5a808e0Jaime Velasco Juanstatic int stk_setup_siobuf(struct stk_camera *dev, int index) 462ec16dae5453eafd1586f35c4ec1ef854e5a808e0Jaime Velasco Juan{ 463ec16dae5453eafd1586f35c4ec1ef854e5a808e0Jaime Velasco Juan struct stk_sio_buffer *buf = dev->sio_bufs + index; 464ec16dae5453eafd1586f35c4ec1ef854e5a808e0Jaime Velasco Juan INIT_LIST_HEAD(&buf->list); 465ec16dae5453eafd1586f35c4ec1ef854e5a808e0Jaime Velasco Juan buf->v4lbuf.length = PAGE_ALIGN(dev->frame_size); 466ec16dae5453eafd1586f35c4ec1ef854e5a808e0Jaime Velasco Juan buf->buffer = vmalloc_user(buf->v4lbuf.length); 467ec16dae5453eafd1586f35c4ec1ef854e5a808e0Jaime Velasco Juan if (buf->buffer == NULL) 468ec16dae5453eafd1586f35c4ec1ef854e5a808e0Jaime Velasco Juan return -ENOMEM; 469ec16dae5453eafd1586f35c4ec1ef854e5a808e0Jaime Velasco Juan buf->mapcount = 0; 470ec16dae5453eafd1586f35c4ec1ef854e5a808e0Jaime Velasco Juan buf->dev = dev; 471ec16dae5453eafd1586f35c4ec1ef854e5a808e0Jaime Velasco Juan buf->v4lbuf.index = index; 472ec16dae5453eafd1586f35c4ec1ef854e5a808e0Jaime Velasco Juan buf->v4lbuf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE; 473ec16dae5453eafd1586f35c4ec1ef854e5a808e0Jaime Velasco Juan buf->v4lbuf.field = V4L2_FIELD_NONE; 474ec16dae5453eafd1586f35c4ec1ef854e5a808e0Jaime Velasco Juan buf->v4lbuf.memory = V4L2_MEMORY_MMAP; 475ec16dae5453eafd1586f35c4ec1ef854e5a808e0Jaime Velasco Juan buf->v4lbuf.m.offset = 2*index*buf->v4lbuf.length; 476ec16dae5453eafd1586f35c4ec1ef854e5a808e0Jaime Velasco Juan return 0; 477ec16dae5453eafd1586f35c4ec1ef854e5a808e0Jaime Velasco Juan} 478ec16dae5453eafd1586f35c4ec1ef854e5a808e0Jaime Velasco Juan 479ec16dae5453eafd1586f35c4ec1ef854e5a808e0Jaime Velasco Juanstatic int stk_free_sio_buffers(struct stk_camera *dev) 480ec16dae5453eafd1586f35c4ec1ef854e5a808e0Jaime Velasco Juan{ 481ec16dae5453eafd1586f35c4ec1ef854e5a808e0Jaime Velasco Juan int i; 482ec16dae5453eafd1586f35c4ec1ef854e5a808e0Jaime Velasco Juan int nbufs; 483ec16dae5453eafd1586f35c4ec1ef854e5a808e0Jaime Velasco Juan unsigned long flags; 484ec16dae5453eafd1586f35c4ec1ef854e5a808e0Jaime Velasco Juan if (dev->n_sbufs == 0 || dev->sio_bufs == NULL) 485ec16dae5453eafd1586f35c4ec1ef854e5a808e0Jaime Velasco Juan return 0; 486ec16dae5453eafd1586f35c4ec1ef854e5a808e0Jaime Velasco Juan /* 487ec16dae5453eafd1586f35c4ec1ef854e5a808e0Jaime Velasco Juan * If any buffers are mapped, we cannot free them at all. 488ec16dae5453eafd1586f35c4ec1ef854e5a808e0Jaime Velasco Juan */ 489ec16dae5453eafd1586f35c4ec1ef854e5a808e0Jaime Velasco Juan for (i = 0; i < dev->n_sbufs; i++) { 490ec16dae5453eafd1586f35c4ec1ef854e5a808e0Jaime Velasco Juan if (dev->sio_bufs[i].mapcount > 0) 491ec16dae5453eafd1586f35c4ec1ef854e5a808e0Jaime Velasco Juan return -EBUSY; 492ec16dae5453eafd1586f35c4ec1ef854e5a808e0Jaime Velasco Juan } 493ec16dae5453eafd1586f35c4ec1ef854e5a808e0Jaime Velasco Juan /* 494ec16dae5453eafd1586f35c4ec1ef854e5a808e0Jaime Velasco Juan * OK, let's do it. 495ec16dae5453eafd1586f35c4ec1ef854e5a808e0Jaime Velasco Juan */ 496ec16dae5453eafd1586f35c4ec1ef854e5a808e0Jaime Velasco Juan spin_lock_irqsave(&dev->spinlock, flags); 497ec16dae5453eafd1586f35c4ec1ef854e5a808e0Jaime Velasco Juan INIT_LIST_HEAD(&dev->sio_avail); 498ec16dae5453eafd1586f35c4ec1ef854e5a808e0Jaime Velasco Juan INIT_LIST_HEAD(&dev->sio_full); 499ec16dae5453eafd1586f35c4ec1ef854e5a808e0Jaime Velasco Juan nbufs = dev->n_sbufs; 500ec16dae5453eafd1586f35c4ec1ef854e5a808e0Jaime Velasco Juan dev->n_sbufs = 0; 501ec16dae5453eafd1586f35c4ec1ef854e5a808e0Jaime Velasco Juan spin_unlock_irqrestore(&dev->spinlock, flags); 502ec16dae5453eafd1586f35c4ec1ef854e5a808e0Jaime Velasco Juan for (i = 0; i < nbufs; i++) { 503ec16dae5453eafd1586f35c4ec1ef854e5a808e0Jaime Velasco Juan if (dev->sio_bufs[i].buffer != NULL) 504ec16dae5453eafd1586f35c4ec1ef854e5a808e0Jaime Velasco Juan vfree(dev->sio_bufs[i].buffer); 505ec16dae5453eafd1586f35c4ec1ef854e5a808e0Jaime Velasco Juan } 506ec16dae5453eafd1586f35c4ec1ef854e5a808e0Jaime Velasco Juan kfree(dev->sio_bufs); 507ec16dae5453eafd1586f35c4ec1ef854e5a808e0Jaime Velasco Juan dev->sio_bufs = NULL; 508ec16dae5453eafd1586f35c4ec1ef854e5a808e0Jaime Velasco Juan return 0; 509ec16dae5453eafd1586f35c4ec1ef854e5a808e0Jaime Velasco Juan} 510ec16dae5453eafd1586f35c4ec1ef854e5a808e0Jaime Velasco Juan 511ec16dae5453eafd1586f35c4ec1ef854e5a808e0Jaime Velasco Juanstatic int stk_prepare_sio_buffers(struct stk_camera *dev, unsigned n_sbufs) 512ec16dae5453eafd1586f35c4ec1ef854e5a808e0Jaime Velasco Juan{ 513ec16dae5453eafd1586f35c4ec1ef854e5a808e0Jaime Velasco Juan int i; 514ec16dae5453eafd1586f35c4ec1ef854e5a808e0Jaime Velasco Juan if (dev->sio_bufs != NULL) 515ec16dae5453eafd1586f35c4ec1ef854e5a808e0Jaime Velasco Juan STK_ERROR("sio_bufs already allocated\n"); 516ec16dae5453eafd1586f35c4ec1ef854e5a808e0Jaime Velasco Juan else { 517ec16dae5453eafd1586f35c4ec1ef854e5a808e0Jaime Velasco Juan dev->sio_bufs = kzalloc(n_sbufs * sizeof(struct stk_sio_buffer), 518ec16dae5453eafd1586f35c4ec1ef854e5a808e0Jaime Velasco Juan GFP_KERNEL); 519ec16dae5453eafd1586f35c4ec1ef854e5a808e0Jaime Velasco Juan if (dev->sio_bufs == NULL) 520ec16dae5453eafd1586f35c4ec1ef854e5a808e0Jaime Velasco Juan return -ENOMEM; 521ec16dae5453eafd1586f35c4ec1ef854e5a808e0Jaime Velasco Juan for (i = 0; i < n_sbufs; i++) { 522ec16dae5453eafd1586f35c4ec1ef854e5a808e0Jaime Velasco Juan if (stk_setup_siobuf(dev, i)) 523b57ce4179b502b3f481f7632da20aae3e488e31aArvydas Sidorenko return (dev->n_sbufs > 1 ? 0 : -ENOMEM); 524ec16dae5453eafd1586f35c4ec1ef854e5a808e0Jaime Velasco Juan dev->n_sbufs = i+1; 525ec16dae5453eafd1586f35c4ec1ef854e5a808e0Jaime Velasco Juan } 526ec16dae5453eafd1586f35c4ec1ef854e5a808e0Jaime Velasco Juan } 527ec16dae5453eafd1586f35c4ec1ef854e5a808e0Jaime Velasco Juan return 0; 528ec16dae5453eafd1586f35c4ec1ef854e5a808e0Jaime Velasco Juan} 529ec16dae5453eafd1586f35c4ec1ef854e5a808e0Jaime Velasco Juan 530ec16dae5453eafd1586f35c4ec1ef854e5a808e0Jaime Velasco Juanstatic int stk_allocate_buffers(struct stk_camera *dev, unsigned n_sbufs) 531ec16dae5453eafd1586f35c4ec1ef854e5a808e0Jaime Velasco Juan{ 532ec16dae5453eafd1586f35c4ec1ef854e5a808e0Jaime Velasco Juan int err; 533ec16dae5453eafd1586f35c4ec1ef854e5a808e0Jaime Velasco Juan err = stk_prepare_iso(dev); 534ec16dae5453eafd1586f35c4ec1ef854e5a808e0Jaime Velasco Juan if (err) { 535ec16dae5453eafd1586f35c4ec1ef854e5a808e0Jaime Velasco Juan stk_clean_iso(dev); 536ec16dae5453eafd1586f35c4ec1ef854e5a808e0Jaime Velasco Juan return err; 537ec16dae5453eafd1586f35c4ec1ef854e5a808e0Jaime Velasco Juan } 538ec16dae5453eafd1586f35c4ec1ef854e5a808e0Jaime Velasco Juan err = stk_prepare_sio_buffers(dev, n_sbufs); 539ec16dae5453eafd1586f35c4ec1ef854e5a808e0Jaime Velasco Juan if (err) { 540ec16dae5453eafd1586f35c4ec1ef854e5a808e0Jaime Velasco Juan stk_free_sio_buffers(dev); 541ec16dae5453eafd1586f35c4ec1ef854e5a808e0Jaime Velasco Juan return err; 542ec16dae5453eafd1586f35c4ec1ef854e5a808e0Jaime Velasco Juan } 543ec16dae5453eafd1586f35c4ec1ef854e5a808e0Jaime Velasco Juan return 0; 544ec16dae5453eafd1586f35c4ec1ef854e5a808e0Jaime Velasco Juan} 545ec16dae5453eafd1586f35c4ec1ef854e5a808e0Jaime Velasco Juan 546ec16dae5453eafd1586f35c4ec1ef854e5a808e0Jaime Velasco Juanstatic void stk_free_buffers(struct stk_camera *dev) 547ec16dae5453eafd1586f35c4ec1ef854e5a808e0Jaime Velasco Juan{ 548ec16dae5453eafd1586f35c4ec1ef854e5a808e0Jaime Velasco Juan stk_clean_iso(dev); 549ec16dae5453eafd1586f35c4ec1ef854e5a808e0Jaime Velasco Juan stk_free_sio_buffers(dev); 550ec16dae5453eafd1586f35c4ec1ef854e5a808e0Jaime Velasco Juan} 551ec16dae5453eafd1586f35c4ec1ef854e5a808e0Jaime Velasco Juan/* -------------------------------------------- */ 552ec16dae5453eafd1586f35c4ec1ef854e5a808e0Jaime Velasco Juan 553ec16dae5453eafd1586f35c4ec1ef854e5a808e0Jaime Velasco Juan/* v4l file operations */ 554ec16dae5453eafd1586f35c4ec1ef854e5a808e0Jaime Velasco Juan 555bec43661b1dc0075b7445223ba775674133b164dHans Verkuilstatic int v4l_stk_open(struct file *fp) 556ec16dae5453eafd1586f35c4ec1ef854e5a808e0Jaime Velasco Juan{ 557ec16dae5453eafd1586f35c4ec1ef854e5a808e0Jaime Velasco Juan struct stk_camera *dev; 558ec16dae5453eafd1586f35c4ec1ef854e5a808e0Jaime Velasco Juan struct video_device *vdev; 559ec16dae5453eafd1586f35c4ec1ef854e5a808e0Jaime Velasco Juan 560ec16dae5453eafd1586f35c4ec1ef854e5a808e0Jaime Velasco Juan vdev = video_devdata(fp); 561ec16dae5453eafd1586f35c4ec1ef854e5a808e0Jaime Velasco Juan dev = vdev_to_camera(vdev); 562ec16dae5453eafd1586f35c4ec1ef854e5a808e0Jaime Velasco Juan 563b57ce4179b502b3f481f7632da20aae3e488e31aArvydas Sidorenko if (dev == NULL || !is_present(dev)) 564ec16dae5453eafd1586f35c4ec1ef854e5a808e0Jaime Velasco Juan return -ENXIO; 5657b1c8f58fcdbed75903943705ef41816e9648c1bArvydas Sidorenko 5667b1c8f58fcdbed75903943705ef41816e9648c1bArvydas Sidorenko if (!first_init) 5677b1c8f58fcdbed75903943705ef41816e9648c1bArvydas Sidorenko stk_camera_write_reg(dev, 0x0, 0x24); 5687b1c8f58fcdbed75903943705ef41816e9648c1bArvydas Sidorenko else 5697b1c8f58fcdbed75903943705ef41816e9648c1bArvydas Sidorenko first_init = 0; 5707b1c8f58fcdbed75903943705ef41816e9648c1bArvydas Sidorenko 5714aaec3ea41addf6fe4fe029aa535f3c019ee0e6dDavid Ellingsworth fp->private_data = dev; 5721fdd61c0228a32b9a5e10593b225851d8920595bJaime Velasco Juan usb_autopm_get_interface(dev->interface); 573ec16dae5453eafd1586f35c4ec1ef854e5a808e0Jaime Velasco Juan 574ec16dae5453eafd1586f35c4ec1ef854e5a808e0Jaime Velasco Juan return 0; 575ec16dae5453eafd1586f35c4ec1ef854e5a808e0Jaime Velasco Juan} 576ec16dae5453eafd1586f35c4ec1ef854e5a808e0Jaime Velasco Juan 577bec43661b1dc0075b7445223ba775674133b164dHans Verkuilstatic int v4l_stk_release(struct file *fp) 578ec16dae5453eafd1586f35c4ec1ef854e5a808e0Jaime Velasco Juan{ 5794aaec3ea41addf6fe4fe029aa535f3c019ee0e6dDavid Ellingsworth struct stk_camera *dev = fp->private_data; 580ec16dae5453eafd1586f35c4ec1ef854e5a808e0Jaime Velasco Juan 581f051ae1866e67567b4f33371969dee9cdddb34edDavid Ellingsworth if (dev->owner == fp) { 582f051ae1866e67567b4f33371969dee9cdddb34edDavid Ellingsworth stk_stop_stream(dev); 583f051ae1866e67567b4f33371969dee9cdddb34edDavid Ellingsworth stk_free_buffers(dev); 5847b1c8f58fcdbed75903943705ef41816e9648c1bArvydas Sidorenko stk_camera_write_reg(dev, 0x0, 0x49); /* turn off the LED */ 58547a7e6f8d282d199f14abbb068c6c3ba00cb7bfcArvydas Sidorenko unset_initialised(dev); 586f051ae1866e67567b4f33371969dee9cdddb34edDavid Ellingsworth dev->owner = NULL; 587ec16dae5453eafd1586f35c4ec1ef854e5a808e0Jaime Velasco Juan } 588ec16dae5453eafd1586f35c4ec1ef854e5a808e0Jaime Velasco Juan 589b57ce4179b502b3f481f7632da20aae3e488e31aArvydas Sidorenko if (is_present(dev)) 590f051ae1866e67567b4f33371969dee9cdddb34edDavid Ellingsworth usb_autopm_put_interface(dev->interface); 591ec16dae5453eafd1586f35c4ec1ef854e5a808e0Jaime Velasco Juan 592ec16dae5453eafd1586f35c4ec1ef854e5a808e0Jaime Velasco Juan return 0; 593ec16dae5453eafd1586f35c4ec1ef854e5a808e0Jaime Velasco Juan} 594ec16dae5453eafd1586f35c4ec1ef854e5a808e0Jaime Velasco Juan 595ec16dae5453eafd1586f35c4ec1ef854e5a808e0Jaime Velasco Juanstatic ssize_t v4l_stk_read(struct file *fp, char __user *buf, 596ec16dae5453eafd1586f35c4ec1ef854e5a808e0Jaime Velasco Juan size_t count, loff_t *f_pos) 597ec16dae5453eafd1586f35c4ec1ef854e5a808e0Jaime Velasco Juan{ 598ec16dae5453eafd1586f35c4ec1ef854e5a808e0Jaime Velasco Juan int i; 599ec16dae5453eafd1586f35c4ec1ef854e5a808e0Jaime Velasco Juan int ret; 600ec16dae5453eafd1586f35c4ec1ef854e5a808e0Jaime Velasco Juan unsigned long flags; 601ec16dae5453eafd1586f35c4ec1ef854e5a808e0Jaime Velasco Juan struct stk_sio_buffer *sbuf; 6024aaec3ea41addf6fe4fe029aa535f3c019ee0e6dDavid Ellingsworth struct stk_camera *dev = fp->private_data; 603ec16dae5453eafd1586f35c4ec1ef854e5a808e0Jaime Velasco Juan 604ec16dae5453eafd1586f35c4ec1ef854e5a808e0Jaime Velasco Juan if (!is_present(dev)) 605ec16dae5453eafd1586f35c4ec1ef854e5a808e0Jaime Velasco Juan return -EIO; 606ec16dae5453eafd1586f35c4ec1ef854e5a808e0Jaime Velasco Juan if (dev->owner && dev->owner != fp) 607ec16dae5453eafd1586f35c4ec1ef854e5a808e0Jaime Velasco Juan return -EBUSY; 608ec16dae5453eafd1586f35c4ec1ef854e5a808e0Jaime Velasco Juan dev->owner = fp; 609ec16dae5453eafd1586f35c4ec1ef854e5a808e0Jaime Velasco Juan if (!is_streaming(dev)) { 610ec16dae5453eafd1586f35c4ec1ef854e5a808e0Jaime Velasco Juan if (stk_initialise(dev) 611ec16dae5453eafd1586f35c4ec1ef854e5a808e0Jaime Velasco Juan || stk_allocate_buffers(dev, 3) 612ec16dae5453eafd1586f35c4ec1ef854e5a808e0Jaime Velasco Juan || stk_start_stream(dev)) 613ec16dae5453eafd1586f35c4ec1ef854e5a808e0Jaime Velasco Juan return -ENOMEM; 614ec16dae5453eafd1586f35c4ec1ef854e5a808e0Jaime Velasco Juan spin_lock_irqsave(&dev->spinlock, flags); 615ec16dae5453eafd1586f35c4ec1ef854e5a808e0Jaime Velasco Juan for (i = 0; i < dev->n_sbufs; i++) { 616ec16dae5453eafd1586f35c4ec1ef854e5a808e0Jaime Velasco Juan list_add_tail(&dev->sio_bufs[i].list, &dev->sio_avail); 617ec16dae5453eafd1586f35c4ec1ef854e5a808e0Jaime Velasco Juan dev->sio_bufs[i].v4lbuf.flags = V4L2_BUF_FLAG_QUEUED; 618ec16dae5453eafd1586f35c4ec1ef854e5a808e0Jaime Velasco Juan } 619ec16dae5453eafd1586f35c4ec1ef854e5a808e0Jaime Velasco Juan spin_unlock_irqrestore(&dev->spinlock, flags); 620ec16dae5453eafd1586f35c4ec1ef854e5a808e0Jaime Velasco Juan } 621ec16dae5453eafd1586f35c4ec1ef854e5a808e0Jaime Velasco Juan if (*f_pos == 0) { 622ec16dae5453eafd1586f35c4ec1ef854e5a808e0Jaime Velasco Juan if (fp->f_flags & O_NONBLOCK && list_empty(&dev->sio_full)) 623ec16dae5453eafd1586f35c4ec1ef854e5a808e0Jaime Velasco Juan return -EWOULDBLOCK; 624ec16dae5453eafd1586f35c4ec1ef854e5a808e0Jaime Velasco Juan ret = wait_event_interruptible(dev->wait_frame, 625ec16dae5453eafd1586f35c4ec1ef854e5a808e0Jaime Velasco Juan !list_empty(&dev->sio_full) || !is_present(dev)); 626ec16dae5453eafd1586f35c4ec1ef854e5a808e0Jaime Velasco Juan if (ret) 627ec16dae5453eafd1586f35c4ec1ef854e5a808e0Jaime Velasco Juan return ret; 628ec16dae5453eafd1586f35c4ec1ef854e5a808e0Jaime Velasco Juan if (!is_present(dev)) 629ec16dae5453eafd1586f35c4ec1ef854e5a808e0Jaime Velasco Juan return -EIO; 630ec16dae5453eafd1586f35c4ec1ef854e5a808e0Jaime Velasco Juan } 631ec16dae5453eafd1586f35c4ec1ef854e5a808e0Jaime Velasco Juan if (count + *f_pos > dev->frame_size) 632ec16dae5453eafd1586f35c4ec1ef854e5a808e0Jaime Velasco Juan count = dev->frame_size - *f_pos; 633ec16dae5453eafd1586f35c4ec1ef854e5a808e0Jaime Velasco Juan spin_lock_irqsave(&dev->spinlock, flags); 634ec16dae5453eafd1586f35c4ec1ef854e5a808e0Jaime Velasco Juan if (list_empty(&dev->sio_full)) { 635ec16dae5453eafd1586f35c4ec1ef854e5a808e0Jaime Velasco Juan spin_unlock_irqrestore(&dev->spinlock, flags); 636ec16dae5453eafd1586f35c4ec1ef854e5a808e0Jaime Velasco Juan STK_ERROR("BUG: No siobufs ready\n"); 637ec16dae5453eafd1586f35c4ec1ef854e5a808e0Jaime Velasco Juan return 0; 638ec16dae5453eafd1586f35c4ec1ef854e5a808e0Jaime Velasco Juan } 639ec16dae5453eafd1586f35c4ec1ef854e5a808e0Jaime Velasco Juan sbuf = list_first_entry(&dev->sio_full, struct stk_sio_buffer, list); 640ec16dae5453eafd1586f35c4ec1ef854e5a808e0Jaime Velasco Juan spin_unlock_irqrestore(&dev->spinlock, flags); 641ec16dae5453eafd1586f35c4ec1ef854e5a808e0Jaime Velasco Juan 642ec16dae5453eafd1586f35c4ec1ef854e5a808e0Jaime Velasco Juan if (copy_to_user(buf, sbuf->buffer + *f_pos, count)) 643ec16dae5453eafd1586f35c4ec1ef854e5a808e0Jaime Velasco Juan return -EFAULT; 644ec16dae5453eafd1586f35c4ec1ef854e5a808e0Jaime Velasco Juan 645ec16dae5453eafd1586f35c4ec1ef854e5a808e0Jaime Velasco Juan *f_pos += count; 646ec16dae5453eafd1586f35c4ec1ef854e5a808e0Jaime Velasco Juan 647ec16dae5453eafd1586f35c4ec1ef854e5a808e0Jaime Velasco Juan if (*f_pos >= dev->frame_size) { 648ec16dae5453eafd1586f35c4ec1ef854e5a808e0Jaime Velasco Juan *f_pos = 0; 649ec16dae5453eafd1586f35c4ec1ef854e5a808e0Jaime Velasco Juan spin_lock_irqsave(&dev->spinlock, flags); 650ec16dae5453eafd1586f35c4ec1ef854e5a808e0Jaime Velasco Juan list_move_tail(&sbuf->list, &dev->sio_avail); 651ec16dae5453eafd1586f35c4ec1ef854e5a808e0Jaime Velasco Juan spin_unlock_irqrestore(&dev->spinlock, flags); 652ec16dae5453eafd1586f35c4ec1ef854e5a808e0Jaime Velasco Juan } 653ec16dae5453eafd1586f35c4ec1ef854e5a808e0Jaime Velasco Juan return count; 654ec16dae5453eafd1586f35c4ec1ef854e5a808e0Jaime Velasco Juan} 655ec16dae5453eafd1586f35c4ec1ef854e5a808e0Jaime Velasco Juan 656ec16dae5453eafd1586f35c4ec1ef854e5a808e0Jaime Velasco Juanstatic unsigned int v4l_stk_poll(struct file *fp, poll_table *wait) 657ec16dae5453eafd1586f35c4ec1ef854e5a808e0Jaime Velasco Juan{ 6584aaec3ea41addf6fe4fe029aa535f3c019ee0e6dDavid Ellingsworth struct stk_camera *dev = fp->private_data; 659ec16dae5453eafd1586f35c4ec1ef854e5a808e0Jaime Velasco Juan 660ec16dae5453eafd1586f35c4ec1ef854e5a808e0Jaime Velasco Juan poll_wait(fp, &dev->wait_frame, wait); 661ec16dae5453eafd1586f35c4ec1ef854e5a808e0Jaime Velasco Juan 662ec16dae5453eafd1586f35c4ec1ef854e5a808e0Jaime Velasco Juan if (!is_present(dev)) 663ec16dae5453eafd1586f35c4ec1ef854e5a808e0Jaime Velasco Juan return POLLERR; 664ec16dae5453eafd1586f35c4ec1ef854e5a808e0Jaime Velasco Juan 665ec16dae5453eafd1586f35c4ec1ef854e5a808e0Jaime Velasco Juan if (!list_empty(&dev->sio_full)) 666b57ce4179b502b3f481f7632da20aae3e488e31aArvydas Sidorenko return POLLIN | POLLRDNORM; 667ec16dae5453eafd1586f35c4ec1ef854e5a808e0Jaime Velasco Juan 668ec16dae5453eafd1586f35c4ec1ef854e5a808e0Jaime Velasco Juan return 0; 669ec16dae5453eafd1586f35c4ec1ef854e5a808e0Jaime Velasco Juan} 670ec16dae5453eafd1586f35c4ec1ef854e5a808e0Jaime Velasco Juan 671ec16dae5453eafd1586f35c4ec1ef854e5a808e0Jaime Velasco Juan 672ec16dae5453eafd1586f35c4ec1ef854e5a808e0Jaime Velasco Juanstatic void stk_v4l_vm_open(struct vm_area_struct *vma) 673ec16dae5453eafd1586f35c4ec1ef854e5a808e0Jaime Velasco Juan{ 674ec16dae5453eafd1586f35c4ec1ef854e5a808e0Jaime Velasco Juan struct stk_sio_buffer *sbuf = vma->vm_private_data; 675ec16dae5453eafd1586f35c4ec1ef854e5a808e0Jaime Velasco Juan sbuf->mapcount++; 676ec16dae5453eafd1586f35c4ec1ef854e5a808e0Jaime Velasco Juan} 677ec16dae5453eafd1586f35c4ec1ef854e5a808e0Jaime Velasco Juanstatic void stk_v4l_vm_close(struct vm_area_struct *vma) 678ec16dae5453eafd1586f35c4ec1ef854e5a808e0Jaime Velasco Juan{ 679ec16dae5453eafd1586f35c4ec1ef854e5a808e0Jaime Velasco Juan struct stk_sio_buffer *sbuf = vma->vm_private_data; 680ec16dae5453eafd1586f35c4ec1ef854e5a808e0Jaime Velasco Juan sbuf->mapcount--; 681ec16dae5453eafd1586f35c4ec1ef854e5a808e0Jaime Velasco Juan if (sbuf->mapcount == 0) 682ec16dae5453eafd1586f35c4ec1ef854e5a808e0Jaime Velasco Juan sbuf->v4lbuf.flags &= ~V4L2_BUF_FLAG_MAPPED; 683ec16dae5453eafd1586f35c4ec1ef854e5a808e0Jaime Velasco Juan} 684f0f37e2f77731b3473fa6bd5ee53255d9a9cdb40Alexey Dobriyanstatic const struct vm_operations_struct stk_v4l_vm_ops = { 685ec16dae5453eafd1586f35c4ec1ef854e5a808e0Jaime Velasco Juan .open = stk_v4l_vm_open, 686ec16dae5453eafd1586f35c4ec1ef854e5a808e0Jaime Velasco Juan .close = stk_v4l_vm_close 687ec16dae5453eafd1586f35c4ec1ef854e5a808e0Jaime Velasco Juan}; 688ec16dae5453eafd1586f35c4ec1ef854e5a808e0Jaime Velasco Juan 689ec16dae5453eafd1586f35c4ec1ef854e5a808e0Jaime Velasco Juanstatic int v4l_stk_mmap(struct file *fp, struct vm_area_struct *vma) 690ec16dae5453eafd1586f35c4ec1ef854e5a808e0Jaime Velasco Juan{ 691ec16dae5453eafd1586f35c4ec1ef854e5a808e0Jaime Velasco Juan unsigned int i; 692ec16dae5453eafd1586f35c4ec1ef854e5a808e0Jaime Velasco Juan int ret; 693ec16dae5453eafd1586f35c4ec1ef854e5a808e0Jaime Velasco Juan unsigned long offset = vma->vm_pgoff << PAGE_SHIFT; 6944aaec3ea41addf6fe4fe029aa535f3c019ee0e6dDavid Ellingsworth struct stk_camera *dev = fp->private_data; 695ec16dae5453eafd1586f35c4ec1ef854e5a808e0Jaime Velasco Juan struct stk_sio_buffer *sbuf = NULL; 696ec16dae5453eafd1586f35c4ec1ef854e5a808e0Jaime Velasco Juan 697ec16dae5453eafd1586f35c4ec1ef854e5a808e0Jaime Velasco Juan if (!(vma->vm_flags & VM_WRITE) || !(vma->vm_flags & VM_SHARED)) 698ec16dae5453eafd1586f35c4ec1ef854e5a808e0Jaime Velasco Juan return -EINVAL; 699ec16dae5453eafd1586f35c4ec1ef854e5a808e0Jaime Velasco Juan 700ec16dae5453eafd1586f35c4ec1ef854e5a808e0Jaime Velasco Juan for (i = 0; i < dev->n_sbufs; i++) { 701ec16dae5453eafd1586f35c4ec1ef854e5a808e0Jaime Velasco Juan if (dev->sio_bufs[i].v4lbuf.m.offset == offset) { 702ec16dae5453eafd1586f35c4ec1ef854e5a808e0Jaime Velasco Juan sbuf = dev->sio_bufs + i; 703ec16dae5453eafd1586f35c4ec1ef854e5a808e0Jaime Velasco Juan break; 704ec16dae5453eafd1586f35c4ec1ef854e5a808e0Jaime Velasco Juan } 705ec16dae5453eafd1586f35c4ec1ef854e5a808e0Jaime Velasco Juan } 706ec16dae5453eafd1586f35c4ec1ef854e5a808e0Jaime Velasco Juan if (sbuf == NULL) 707ec16dae5453eafd1586f35c4ec1ef854e5a808e0Jaime Velasco Juan return -EINVAL; 708ec16dae5453eafd1586f35c4ec1ef854e5a808e0Jaime Velasco Juan ret = remap_vmalloc_range(vma, sbuf->buffer, 0); 709ec16dae5453eafd1586f35c4ec1ef854e5a808e0Jaime Velasco Juan if (ret) 710ec16dae5453eafd1586f35c4ec1ef854e5a808e0Jaime Velasco Juan return ret; 711ec16dae5453eafd1586f35c4ec1ef854e5a808e0Jaime Velasco Juan vma->vm_flags |= VM_DONTEXPAND; 712ec16dae5453eafd1586f35c4ec1ef854e5a808e0Jaime Velasco Juan vma->vm_private_data = sbuf; 713ec16dae5453eafd1586f35c4ec1ef854e5a808e0Jaime Velasco Juan vma->vm_ops = &stk_v4l_vm_ops; 714ec16dae5453eafd1586f35c4ec1ef854e5a808e0Jaime Velasco Juan sbuf->v4lbuf.flags |= V4L2_BUF_FLAG_MAPPED; 715ec16dae5453eafd1586f35c4ec1ef854e5a808e0Jaime Velasco Juan stk_v4l_vm_open(vma); 716ec16dae5453eafd1586f35c4ec1ef854e5a808e0Jaime Velasco Juan return 0; 717ec16dae5453eafd1586f35c4ec1ef854e5a808e0Jaime Velasco Juan} 718ec16dae5453eafd1586f35c4ec1ef854e5a808e0Jaime Velasco Juan 719ec16dae5453eafd1586f35c4ec1ef854e5a808e0Jaime Velasco Juan/* v4l ioctl handlers */ 720ec16dae5453eafd1586f35c4ec1ef854e5a808e0Jaime Velasco Juan 721ec16dae5453eafd1586f35c4ec1ef854e5a808e0Jaime Velasco Juanstatic int stk_vidioc_querycap(struct file *filp, 722ec16dae5453eafd1586f35c4ec1ef854e5a808e0Jaime Velasco Juan void *priv, struct v4l2_capability *cap) 723ec16dae5453eafd1586f35c4ec1ef854e5a808e0Jaime Velasco Juan{ 724ec16dae5453eafd1586f35c4ec1ef854e5a808e0Jaime Velasco Juan strcpy(cap->driver, "stk"); 725ec16dae5453eafd1586f35c4ec1ef854e5a808e0Jaime Velasco Juan strcpy(cap->card, "stk"); 726ec16dae5453eafd1586f35c4ec1ef854e5a808e0Jaime Velasco Juan cap->version = DRIVER_VERSION_NUM; 727ec16dae5453eafd1586f35c4ec1ef854e5a808e0Jaime Velasco Juan 728ec16dae5453eafd1586f35c4ec1ef854e5a808e0Jaime Velasco Juan cap->capabilities = V4L2_CAP_VIDEO_CAPTURE 729ec16dae5453eafd1586f35c4ec1ef854e5a808e0Jaime Velasco Juan | V4L2_CAP_READWRITE | V4L2_CAP_STREAMING; 730ec16dae5453eafd1586f35c4ec1ef854e5a808e0Jaime Velasco Juan return 0; 731ec16dae5453eafd1586f35c4ec1ef854e5a808e0Jaime Velasco Juan} 732ec16dae5453eafd1586f35c4ec1ef854e5a808e0Jaime Velasco Juan 733ec16dae5453eafd1586f35c4ec1ef854e5a808e0Jaime Velasco Juanstatic int stk_vidioc_enum_input(struct file *filp, 734ec16dae5453eafd1586f35c4ec1ef854e5a808e0Jaime Velasco Juan void *priv, struct v4l2_input *input) 735ec16dae5453eafd1586f35c4ec1ef854e5a808e0Jaime Velasco Juan{ 736ec16dae5453eafd1586f35c4ec1ef854e5a808e0Jaime Velasco Juan if (input->index != 0) 737ec16dae5453eafd1586f35c4ec1ef854e5a808e0Jaime Velasco Juan return -EINVAL; 738ec16dae5453eafd1586f35c4ec1ef854e5a808e0Jaime Velasco Juan 739ec16dae5453eafd1586f35c4ec1ef854e5a808e0Jaime Velasco Juan strcpy(input->name, "Syntek USB Camera"); 740ec16dae5453eafd1586f35c4ec1ef854e5a808e0Jaime Velasco Juan input->type = V4L2_INPUT_TYPE_CAMERA; 741ec16dae5453eafd1586f35c4ec1ef854e5a808e0Jaime Velasco Juan return 0; 742ec16dae5453eafd1586f35c4ec1ef854e5a808e0Jaime Velasco Juan} 743ec16dae5453eafd1586f35c4ec1ef854e5a808e0Jaime Velasco Juan 744ec16dae5453eafd1586f35c4ec1ef854e5a808e0Jaime Velasco Juan 745ec16dae5453eafd1586f35c4ec1ef854e5a808e0Jaime Velasco Juanstatic int stk_vidioc_g_input(struct file *filp, void *priv, unsigned int *i) 746ec16dae5453eafd1586f35c4ec1ef854e5a808e0Jaime Velasco Juan{ 747ec16dae5453eafd1586f35c4ec1ef854e5a808e0Jaime Velasco Juan *i = 0; 748ec16dae5453eafd1586f35c4ec1ef854e5a808e0Jaime Velasco Juan return 0; 749ec16dae5453eafd1586f35c4ec1ef854e5a808e0Jaime Velasco Juan} 750ec16dae5453eafd1586f35c4ec1ef854e5a808e0Jaime Velasco Juan 751ec16dae5453eafd1586f35c4ec1ef854e5a808e0Jaime Velasco Juanstatic int stk_vidioc_s_input(struct file *filp, void *priv, unsigned int i) 752ec16dae5453eafd1586f35c4ec1ef854e5a808e0Jaime Velasco Juan{ 753ec16dae5453eafd1586f35c4ec1ef854e5a808e0Jaime Velasco Juan if (i != 0) 754ec16dae5453eafd1586f35c4ec1ef854e5a808e0Jaime Velasco Juan return -EINVAL; 755ec16dae5453eafd1586f35c4ec1ef854e5a808e0Jaime Velasco Juan else 756ec16dae5453eafd1586f35c4ec1ef854e5a808e0Jaime Velasco Juan return 0; 757ec16dae5453eafd1586f35c4ec1ef854e5a808e0Jaime Velasco Juan} 758ec16dae5453eafd1586f35c4ec1ef854e5a808e0Jaime Velasco Juan 759ec16dae5453eafd1586f35c4ec1ef854e5a808e0Jaime Velasco Juan/* from vivi.c */ 760ec16dae5453eafd1586f35c4ec1ef854e5a808e0Jaime Velasco Juanstatic int stk_vidioc_s_std(struct file *filp, void *priv, v4l2_std_id *a) 761ec16dae5453eafd1586f35c4ec1ef854e5a808e0Jaime Velasco Juan{ 762ec16dae5453eafd1586f35c4ec1ef854e5a808e0Jaime Velasco Juan return 0; 763ec16dae5453eafd1586f35c4ec1ef854e5a808e0Jaime Velasco Juan} 764ec16dae5453eafd1586f35c4ec1ef854e5a808e0Jaime Velasco Juan 765ec16dae5453eafd1586f35c4ec1ef854e5a808e0Jaime Velasco Juan/* List of all V4Lv2 controls supported by the driver */ 766ec16dae5453eafd1586f35c4ec1ef854e5a808e0Jaime Velasco Juanstatic struct v4l2_queryctrl stk_controls[] = { 767ec16dae5453eafd1586f35c4ec1ef854e5a808e0Jaime Velasco Juan { 768ec16dae5453eafd1586f35c4ec1ef854e5a808e0Jaime Velasco Juan .id = V4L2_CID_BRIGHTNESS, 769ec16dae5453eafd1586f35c4ec1ef854e5a808e0Jaime Velasco Juan .type = V4L2_CTRL_TYPE_INTEGER, 770ec16dae5453eafd1586f35c4ec1ef854e5a808e0Jaime Velasco Juan .name = "Brightness", 771ec16dae5453eafd1586f35c4ec1ef854e5a808e0Jaime Velasco Juan .minimum = 0, 772ec16dae5453eafd1586f35c4ec1ef854e5a808e0Jaime Velasco Juan .maximum = 0xffff, 773ec16dae5453eafd1586f35c4ec1ef854e5a808e0Jaime Velasco Juan .step = 0x0100, 774ec16dae5453eafd1586f35c4ec1ef854e5a808e0Jaime Velasco Juan .default_value = 0x6000, 775ec16dae5453eafd1586f35c4ec1ef854e5a808e0Jaime Velasco Juan }, 7760a58d713062fb49952b9b082514a48a0c83b269dHans Verkuil { 7770a58d713062fb49952b9b082514a48a0c83b269dHans Verkuil .id = V4L2_CID_HFLIP, 7780a58d713062fb49952b9b082514a48a0c83b269dHans Verkuil .type = V4L2_CTRL_TYPE_BOOLEAN, 7790a58d713062fb49952b9b082514a48a0c83b269dHans Verkuil .name = "Horizontal Flip", 7800a58d713062fb49952b9b082514a48a0c83b269dHans Verkuil .minimum = 0, 7810a58d713062fb49952b9b082514a48a0c83b269dHans Verkuil .maximum = 1, 7820a58d713062fb49952b9b082514a48a0c83b269dHans Verkuil .step = 1, 7830a58d713062fb49952b9b082514a48a0c83b269dHans Verkuil .default_value = 1, 7840a58d713062fb49952b9b082514a48a0c83b269dHans Verkuil }, 7850a58d713062fb49952b9b082514a48a0c83b269dHans Verkuil { 7860a58d713062fb49952b9b082514a48a0c83b269dHans Verkuil .id = V4L2_CID_VFLIP, 7870a58d713062fb49952b9b082514a48a0c83b269dHans Verkuil .type = V4L2_CTRL_TYPE_BOOLEAN, 7880a58d713062fb49952b9b082514a48a0c83b269dHans Verkuil .name = "Vertical Flip", 7890a58d713062fb49952b9b082514a48a0c83b269dHans Verkuil .minimum = 0, 7900a58d713062fb49952b9b082514a48a0c83b269dHans Verkuil .maximum = 1, 7910a58d713062fb49952b9b082514a48a0c83b269dHans Verkuil .step = 1, 7920a58d713062fb49952b9b082514a48a0c83b269dHans Verkuil .default_value = 1, 7930a58d713062fb49952b9b082514a48a0c83b269dHans Verkuil }, 794ec16dae5453eafd1586f35c4ec1ef854e5a808e0Jaime Velasco Juan}; 795ec16dae5453eafd1586f35c4ec1ef854e5a808e0Jaime Velasco Juan 796ec16dae5453eafd1586f35c4ec1ef854e5a808e0Jaime Velasco Juanstatic int stk_vidioc_queryctrl(struct file *filp, 797ec16dae5453eafd1586f35c4ec1ef854e5a808e0Jaime Velasco Juan void *priv, struct v4l2_queryctrl *c) 798ec16dae5453eafd1586f35c4ec1ef854e5a808e0Jaime Velasco Juan{ 799ec16dae5453eafd1586f35c4ec1ef854e5a808e0Jaime Velasco Juan int i; 800ec16dae5453eafd1586f35c4ec1ef854e5a808e0Jaime Velasco Juan int nbr; 801ec16dae5453eafd1586f35c4ec1ef854e5a808e0Jaime Velasco Juan nbr = ARRAY_SIZE(stk_controls); 802ec16dae5453eafd1586f35c4ec1ef854e5a808e0Jaime Velasco Juan 803ec16dae5453eafd1586f35c4ec1ef854e5a808e0Jaime Velasco Juan for (i = 0; i < nbr; i++) { 804ec16dae5453eafd1586f35c4ec1ef854e5a808e0Jaime Velasco Juan if (stk_controls[i].id == c->id) { 805ec16dae5453eafd1586f35c4ec1ef854e5a808e0Jaime Velasco Juan memcpy(c, &stk_controls[i], 806ec16dae5453eafd1586f35c4ec1ef854e5a808e0Jaime Velasco Juan sizeof(struct v4l2_queryctrl)); 807ec16dae5453eafd1586f35c4ec1ef854e5a808e0Jaime Velasco Juan return 0; 808ec16dae5453eafd1586f35c4ec1ef854e5a808e0Jaime Velasco Juan } 809ec16dae5453eafd1586f35c4ec1ef854e5a808e0Jaime Velasco Juan } 810ec16dae5453eafd1586f35c4ec1ef854e5a808e0Jaime Velasco Juan return -EINVAL; 811ec16dae5453eafd1586f35c4ec1ef854e5a808e0Jaime Velasco Juan} 812ec16dae5453eafd1586f35c4ec1ef854e5a808e0Jaime Velasco Juan 813ec16dae5453eafd1586f35c4ec1ef854e5a808e0Jaime Velasco Juanstatic int stk_vidioc_g_ctrl(struct file *filp, 814ec16dae5453eafd1586f35c4ec1ef854e5a808e0Jaime Velasco Juan void *priv, struct v4l2_control *c) 815ec16dae5453eafd1586f35c4ec1ef854e5a808e0Jaime Velasco Juan{ 816ec16dae5453eafd1586f35c4ec1ef854e5a808e0Jaime Velasco Juan struct stk_camera *dev = priv; 817ec16dae5453eafd1586f35c4ec1ef854e5a808e0Jaime Velasco Juan switch (c->id) { 818ec16dae5453eafd1586f35c4ec1ef854e5a808e0Jaime Velasco Juan case V4L2_CID_BRIGHTNESS: 819ec16dae5453eafd1586f35c4ec1ef854e5a808e0Jaime Velasco Juan c->value = dev->vsettings.brightness; 820ec16dae5453eafd1586f35c4ec1ef854e5a808e0Jaime Velasco Juan break; 8210a58d713062fb49952b9b082514a48a0c83b269dHans Verkuil case V4L2_CID_HFLIP: 8220a58d713062fb49952b9b082514a48a0c83b269dHans Verkuil c->value = dev->vsettings.hflip; 8230a58d713062fb49952b9b082514a48a0c83b269dHans Verkuil break; 8240a58d713062fb49952b9b082514a48a0c83b269dHans Verkuil case V4L2_CID_VFLIP: 8250a58d713062fb49952b9b082514a48a0c83b269dHans Verkuil c->value = dev->vsettings.vflip; 8260a58d713062fb49952b9b082514a48a0c83b269dHans Verkuil break; 827ec16dae5453eafd1586f35c4ec1ef854e5a808e0Jaime Velasco Juan default: 828ec16dae5453eafd1586f35c4ec1ef854e5a808e0Jaime Velasco Juan return -EINVAL; 829ec16dae5453eafd1586f35c4ec1ef854e5a808e0Jaime Velasco Juan } 830ec16dae5453eafd1586f35c4ec1ef854e5a808e0Jaime Velasco Juan return 0; 831ec16dae5453eafd1586f35c4ec1ef854e5a808e0Jaime Velasco Juan} 832ec16dae5453eafd1586f35c4ec1ef854e5a808e0Jaime Velasco Juan 833ec16dae5453eafd1586f35c4ec1ef854e5a808e0Jaime Velasco Juanstatic int stk_vidioc_s_ctrl(struct file *filp, 834ec16dae5453eafd1586f35c4ec1ef854e5a808e0Jaime Velasco Juan void *priv, struct v4l2_control *c) 835ec16dae5453eafd1586f35c4ec1ef854e5a808e0Jaime Velasco Juan{ 836ec16dae5453eafd1586f35c4ec1ef854e5a808e0Jaime Velasco Juan struct stk_camera *dev = priv; 837ec16dae5453eafd1586f35c4ec1ef854e5a808e0Jaime Velasco Juan switch (c->id) { 838ec16dae5453eafd1586f35c4ec1ef854e5a808e0Jaime Velasco Juan case V4L2_CID_BRIGHTNESS: 839ec16dae5453eafd1586f35c4ec1ef854e5a808e0Jaime Velasco Juan dev->vsettings.brightness = c->value; 840ec16dae5453eafd1586f35c4ec1ef854e5a808e0Jaime Velasco Juan return stk_sensor_set_brightness(dev, c->value >> 8); 8410a58d713062fb49952b9b082514a48a0c83b269dHans Verkuil case V4L2_CID_HFLIP: 8420a58d713062fb49952b9b082514a48a0c83b269dHans Verkuil dev->vsettings.hflip = c->value; 8430a58d713062fb49952b9b082514a48a0c83b269dHans Verkuil return 0; 8440a58d713062fb49952b9b082514a48a0c83b269dHans Verkuil case V4L2_CID_VFLIP: 8450a58d713062fb49952b9b082514a48a0c83b269dHans Verkuil dev->vsettings.vflip = c->value; 8460a58d713062fb49952b9b082514a48a0c83b269dHans Verkuil return 0; 847ec16dae5453eafd1586f35c4ec1ef854e5a808e0Jaime Velasco Juan default: 848ec16dae5453eafd1586f35c4ec1ef854e5a808e0Jaime Velasco Juan return -EINVAL; 849ec16dae5453eafd1586f35c4ec1ef854e5a808e0Jaime Velasco Juan } 850ec16dae5453eafd1586f35c4ec1ef854e5a808e0Jaime Velasco Juan return 0; 851ec16dae5453eafd1586f35c4ec1ef854e5a808e0Jaime Velasco Juan} 852ec16dae5453eafd1586f35c4ec1ef854e5a808e0Jaime Velasco Juan 853ec16dae5453eafd1586f35c4ec1ef854e5a808e0Jaime Velasco Juan 85478b526a43561d7e5e702ba27948e422dfbc4bea1Hans Verkuilstatic int stk_vidioc_enum_fmt_vid_cap(struct file *filp, 855ec16dae5453eafd1586f35c4ec1ef854e5a808e0Jaime Velasco Juan void *priv, struct v4l2_fmtdesc *fmtd) 856ec16dae5453eafd1586f35c4ec1ef854e5a808e0Jaime Velasco Juan{ 857ec16dae5453eafd1586f35c4ec1ef854e5a808e0Jaime Velasco Juan switch (fmtd->index) { 858ec16dae5453eafd1586f35c4ec1ef854e5a808e0Jaime Velasco Juan case 0: 859ec16dae5453eafd1586f35c4ec1ef854e5a808e0Jaime Velasco Juan fmtd->pixelformat = V4L2_PIX_FMT_RGB565; 860ec16dae5453eafd1586f35c4ec1ef854e5a808e0Jaime Velasco Juan strcpy(fmtd->description, "r5g6b5"); 861ec16dae5453eafd1586f35c4ec1ef854e5a808e0Jaime Velasco Juan break; 862ec16dae5453eafd1586f35c4ec1ef854e5a808e0Jaime Velasco Juan case 1: 863ec16dae5453eafd1586f35c4ec1ef854e5a808e0Jaime Velasco Juan fmtd->pixelformat = V4L2_PIX_FMT_RGB565X; 864ec16dae5453eafd1586f35c4ec1ef854e5a808e0Jaime Velasco Juan strcpy(fmtd->description, "r5g6b5BE"); 865ec16dae5453eafd1586f35c4ec1ef854e5a808e0Jaime Velasco Juan break; 866ec16dae5453eafd1586f35c4ec1ef854e5a808e0Jaime Velasco Juan case 2: 867ec16dae5453eafd1586f35c4ec1ef854e5a808e0Jaime Velasco Juan fmtd->pixelformat = V4L2_PIX_FMT_UYVY; 868ec16dae5453eafd1586f35c4ec1ef854e5a808e0Jaime Velasco Juan strcpy(fmtd->description, "yuv4:2:2"); 869ec16dae5453eafd1586f35c4ec1ef854e5a808e0Jaime Velasco Juan break; 870ec16dae5453eafd1586f35c4ec1ef854e5a808e0Jaime Velasco Juan case 3: 871ec16dae5453eafd1586f35c4ec1ef854e5a808e0Jaime Velasco Juan fmtd->pixelformat = V4L2_PIX_FMT_SBGGR8; 872ec16dae5453eafd1586f35c4ec1ef854e5a808e0Jaime Velasco Juan strcpy(fmtd->description, "Raw bayer"); 873ec16dae5453eafd1586f35c4ec1ef854e5a808e0Jaime Velasco Juan break; 8741112fb68ae9c838294d38e1f209fedbc0dbf11d5Jaime Velasco Juan case 4: 8751112fb68ae9c838294d38e1f209fedbc0dbf11d5Jaime Velasco Juan fmtd->pixelformat = V4L2_PIX_FMT_YUYV; 8761112fb68ae9c838294d38e1f209fedbc0dbf11d5Jaime Velasco Juan strcpy(fmtd->description, "yuv4:2:2"); 8771112fb68ae9c838294d38e1f209fedbc0dbf11d5Jaime Velasco Juan break; 878ec16dae5453eafd1586f35c4ec1ef854e5a808e0Jaime Velasco Juan default: 879ec16dae5453eafd1586f35c4ec1ef854e5a808e0Jaime Velasco Juan return -EINVAL; 880ec16dae5453eafd1586f35c4ec1ef854e5a808e0Jaime Velasco Juan } 881ec16dae5453eafd1586f35c4ec1ef854e5a808e0Jaime Velasco Juan return 0; 882ec16dae5453eafd1586f35c4ec1ef854e5a808e0Jaime Velasco Juan} 883ec16dae5453eafd1586f35c4ec1ef854e5a808e0Jaime Velasco Juan 884ec16dae5453eafd1586f35c4ec1ef854e5a808e0Jaime Velasco Juanstatic struct stk_size { 885ec16dae5453eafd1586f35c4ec1ef854e5a808e0Jaime Velasco Juan unsigned w; 886ec16dae5453eafd1586f35c4ec1ef854e5a808e0Jaime Velasco Juan unsigned h; 887ec16dae5453eafd1586f35c4ec1ef854e5a808e0Jaime Velasco Juan enum stk_mode m; 888ec16dae5453eafd1586f35c4ec1ef854e5a808e0Jaime Velasco Juan} stk_sizes[] = { 889ec16dae5453eafd1586f35c4ec1ef854e5a808e0Jaime Velasco Juan { .w = 1280, .h = 1024, .m = MODE_SXGA, }, 890ec16dae5453eafd1586f35c4ec1ef854e5a808e0Jaime Velasco Juan { .w = 640, .h = 480, .m = MODE_VGA, }, 891ec16dae5453eafd1586f35c4ec1ef854e5a808e0Jaime Velasco Juan { .w = 352, .h = 288, .m = MODE_CIF, }, 892ec16dae5453eafd1586f35c4ec1ef854e5a808e0Jaime Velasco Juan { .w = 320, .h = 240, .m = MODE_QVGA, }, 893ec16dae5453eafd1586f35c4ec1ef854e5a808e0Jaime Velasco Juan { .w = 176, .h = 144, .m = MODE_QCIF, }, 894ec16dae5453eafd1586f35c4ec1ef854e5a808e0Jaime Velasco Juan}; 895ec16dae5453eafd1586f35c4ec1ef854e5a808e0Jaime Velasco Juan 89678b526a43561d7e5e702ba27948e422dfbc4bea1Hans Verkuilstatic int stk_vidioc_g_fmt_vid_cap(struct file *filp, 897ec16dae5453eafd1586f35c4ec1ef854e5a808e0Jaime Velasco Juan void *priv, struct v4l2_format *f) 898ec16dae5453eafd1586f35c4ec1ef854e5a808e0Jaime Velasco Juan{ 899ec16dae5453eafd1586f35c4ec1ef854e5a808e0Jaime Velasco Juan struct v4l2_pix_format *pix_format = &f->fmt.pix; 900ec16dae5453eafd1586f35c4ec1ef854e5a808e0Jaime Velasco Juan struct stk_camera *dev = priv; 901ec16dae5453eafd1586f35c4ec1ef854e5a808e0Jaime Velasco Juan int i; 902ec16dae5453eafd1586f35c4ec1ef854e5a808e0Jaime Velasco Juan 903b57ce4179b502b3f481f7632da20aae3e488e31aArvydas Sidorenko for (i = 0; i < ARRAY_SIZE(stk_sizes) && 904b57ce4179b502b3f481f7632da20aae3e488e31aArvydas Sidorenko stk_sizes[i].m != dev->vsettings.mode; i++) 905b57ce4179b502b3f481f7632da20aae3e488e31aArvydas Sidorenko ; 906ec16dae5453eafd1586f35c4ec1ef854e5a808e0Jaime Velasco Juan if (i == ARRAY_SIZE(stk_sizes)) { 907ec16dae5453eafd1586f35c4ec1ef854e5a808e0Jaime Velasco Juan STK_ERROR("ERROR: mode invalid\n"); 908ec16dae5453eafd1586f35c4ec1ef854e5a808e0Jaime Velasco Juan return -EINVAL; 909ec16dae5453eafd1586f35c4ec1ef854e5a808e0Jaime Velasco Juan } 910ec16dae5453eafd1586f35c4ec1ef854e5a808e0Jaime Velasco Juan pix_format->width = stk_sizes[i].w; 911ec16dae5453eafd1586f35c4ec1ef854e5a808e0Jaime Velasco Juan pix_format->height = stk_sizes[i].h; 912ec16dae5453eafd1586f35c4ec1ef854e5a808e0Jaime Velasco Juan pix_format->field = V4L2_FIELD_NONE; 913ec16dae5453eafd1586f35c4ec1ef854e5a808e0Jaime Velasco Juan pix_format->colorspace = V4L2_COLORSPACE_SRGB; 914ec16dae5453eafd1586f35c4ec1ef854e5a808e0Jaime Velasco Juan pix_format->pixelformat = dev->vsettings.palette; 915ec16dae5453eafd1586f35c4ec1ef854e5a808e0Jaime Velasco Juan if (dev->vsettings.palette == V4L2_PIX_FMT_SBGGR8) 916ec16dae5453eafd1586f35c4ec1ef854e5a808e0Jaime Velasco Juan pix_format->bytesperline = pix_format->width; 917ec16dae5453eafd1586f35c4ec1ef854e5a808e0Jaime Velasco Juan else 918ec16dae5453eafd1586f35c4ec1ef854e5a808e0Jaime Velasco Juan pix_format->bytesperline = 2 * pix_format->width; 919ec16dae5453eafd1586f35c4ec1ef854e5a808e0Jaime Velasco Juan pix_format->sizeimage = pix_format->bytesperline 920ec16dae5453eafd1586f35c4ec1ef854e5a808e0Jaime Velasco Juan * pix_format->height; 921ec16dae5453eafd1586f35c4ec1ef854e5a808e0Jaime Velasco Juan return 0; 922ec16dae5453eafd1586f35c4ec1ef854e5a808e0Jaime Velasco Juan} 923ec16dae5453eafd1586f35c4ec1ef854e5a808e0Jaime Velasco Juan 92478b526a43561d7e5e702ba27948e422dfbc4bea1Hans Verkuilstatic int stk_vidioc_try_fmt_vid_cap(struct file *filp, 925ec16dae5453eafd1586f35c4ec1ef854e5a808e0Jaime Velasco Juan void *priv, struct v4l2_format *fmtd) 926ec16dae5453eafd1586f35c4ec1ef854e5a808e0Jaime Velasco Juan{ 927ec16dae5453eafd1586f35c4ec1ef854e5a808e0Jaime Velasco Juan int i; 928ec16dae5453eafd1586f35c4ec1ef854e5a808e0Jaime Velasco Juan switch (fmtd->fmt.pix.pixelformat) { 929ec16dae5453eafd1586f35c4ec1ef854e5a808e0Jaime Velasco Juan case V4L2_PIX_FMT_RGB565: 930ec16dae5453eafd1586f35c4ec1ef854e5a808e0Jaime Velasco Juan case V4L2_PIX_FMT_RGB565X: 931ec16dae5453eafd1586f35c4ec1ef854e5a808e0Jaime Velasco Juan case V4L2_PIX_FMT_UYVY: 9321112fb68ae9c838294d38e1f209fedbc0dbf11d5Jaime Velasco Juan case V4L2_PIX_FMT_YUYV: 933ec16dae5453eafd1586f35c4ec1ef854e5a808e0Jaime Velasco Juan case V4L2_PIX_FMT_SBGGR8: 934ec16dae5453eafd1586f35c4ec1ef854e5a808e0Jaime Velasco Juan break; 935ec16dae5453eafd1586f35c4ec1ef854e5a808e0Jaime Velasco Juan default: 936ec16dae5453eafd1586f35c4ec1ef854e5a808e0Jaime Velasco Juan return -EINVAL; 937ec16dae5453eafd1586f35c4ec1ef854e5a808e0Jaime Velasco Juan } 938ec16dae5453eafd1586f35c4ec1ef854e5a808e0Jaime Velasco Juan for (i = 1; i < ARRAY_SIZE(stk_sizes); i++) { 939ec16dae5453eafd1586f35c4ec1ef854e5a808e0Jaime Velasco Juan if (fmtd->fmt.pix.width > stk_sizes[i].w) 940ec16dae5453eafd1586f35c4ec1ef854e5a808e0Jaime Velasco Juan break; 941ec16dae5453eafd1586f35c4ec1ef854e5a808e0Jaime Velasco Juan } 942ec16dae5453eafd1586f35c4ec1ef854e5a808e0Jaime Velasco Juan if (i == ARRAY_SIZE(stk_sizes) 943ec16dae5453eafd1586f35c4ec1ef854e5a808e0Jaime Velasco Juan || (abs(fmtd->fmt.pix.width - stk_sizes[i-1].w) 944ec16dae5453eafd1586f35c4ec1ef854e5a808e0Jaime Velasco Juan < abs(fmtd->fmt.pix.width - stk_sizes[i].w))) { 945ec16dae5453eafd1586f35c4ec1ef854e5a808e0Jaime Velasco Juan fmtd->fmt.pix.height = stk_sizes[i-1].h; 946ec16dae5453eafd1586f35c4ec1ef854e5a808e0Jaime Velasco Juan fmtd->fmt.pix.width = stk_sizes[i-1].w; 947ec16dae5453eafd1586f35c4ec1ef854e5a808e0Jaime Velasco Juan fmtd->fmt.pix.priv = i - 1; 948ec16dae5453eafd1586f35c4ec1ef854e5a808e0Jaime Velasco Juan } else { 949ec16dae5453eafd1586f35c4ec1ef854e5a808e0Jaime Velasco Juan fmtd->fmt.pix.height = stk_sizes[i].h; 950ec16dae5453eafd1586f35c4ec1ef854e5a808e0Jaime Velasco Juan fmtd->fmt.pix.width = stk_sizes[i].w; 951ec16dae5453eafd1586f35c4ec1ef854e5a808e0Jaime Velasco Juan fmtd->fmt.pix.priv = i; 952ec16dae5453eafd1586f35c4ec1ef854e5a808e0Jaime Velasco Juan } 953ec16dae5453eafd1586f35c4ec1ef854e5a808e0Jaime Velasco Juan 954ec16dae5453eafd1586f35c4ec1ef854e5a808e0Jaime Velasco Juan fmtd->fmt.pix.field = V4L2_FIELD_NONE; 955ec16dae5453eafd1586f35c4ec1ef854e5a808e0Jaime Velasco Juan fmtd->fmt.pix.colorspace = V4L2_COLORSPACE_SRGB; 956ec16dae5453eafd1586f35c4ec1ef854e5a808e0Jaime Velasco Juan if (fmtd->fmt.pix.pixelformat == V4L2_PIX_FMT_SBGGR8) 957ec16dae5453eafd1586f35c4ec1ef854e5a808e0Jaime Velasco Juan fmtd->fmt.pix.bytesperline = fmtd->fmt.pix.width; 958ec16dae5453eafd1586f35c4ec1ef854e5a808e0Jaime Velasco Juan else 959ec16dae5453eafd1586f35c4ec1ef854e5a808e0Jaime Velasco Juan fmtd->fmt.pix.bytesperline = 2 * fmtd->fmt.pix.width; 960ec16dae5453eafd1586f35c4ec1ef854e5a808e0Jaime Velasco Juan fmtd->fmt.pix.sizeimage = fmtd->fmt.pix.bytesperline 961ec16dae5453eafd1586f35c4ec1ef854e5a808e0Jaime Velasco Juan * fmtd->fmt.pix.height; 962ec16dae5453eafd1586f35c4ec1ef854e5a808e0Jaime Velasco Juan return 0; 963ec16dae5453eafd1586f35c4ec1ef854e5a808e0Jaime Velasco Juan} 964ec16dae5453eafd1586f35c4ec1ef854e5a808e0Jaime Velasco Juan 9651fdd61c0228a32b9a5e10593b225851d8920595bJaime Velasco Juanstatic int stk_setup_format(struct stk_camera *dev) 9661fdd61c0228a32b9a5e10593b225851d8920595bJaime Velasco Juan{ 9671fdd61c0228a32b9a5e10593b225851d8920595bJaime Velasco Juan int i = 0; 9681fdd61c0228a32b9a5e10593b225851d8920595bJaime Velasco Juan int depth; 9691fdd61c0228a32b9a5e10593b225851d8920595bJaime Velasco Juan if (dev->vsettings.palette == V4L2_PIX_FMT_SBGGR8) 9701fdd61c0228a32b9a5e10593b225851d8920595bJaime Velasco Juan depth = 1; 9711fdd61c0228a32b9a5e10593b225851d8920595bJaime Velasco Juan else 9721fdd61c0228a32b9a5e10593b225851d8920595bJaime Velasco Juan depth = 2; 97377f2c2db1146154fb054e9ce955928a66d8c959fRoel Kluin while (i < ARRAY_SIZE(stk_sizes) && 97477f2c2db1146154fb054e9ce955928a66d8c959fRoel Kluin stk_sizes[i].m != dev->vsettings.mode) 9751fdd61c0228a32b9a5e10593b225851d8920595bJaime Velasco Juan i++; 9761fdd61c0228a32b9a5e10593b225851d8920595bJaime Velasco Juan if (i == ARRAY_SIZE(stk_sizes)) { 9777e28adb2497f6b873516163e2d29210c11777613Harvey Harrison STK_ERROR("Something is broken in %s\n", __func__); 9781fdd61c0228a32b9a5e10593b225851d8920595bJaime Velasco Juan return -EFAULT; 9791fdd61c0228a32b9a5e10593b225851d8920595bJaime Velasco Juan } 9801fdd61c0228a32b9a5e10593b225851d8920595bJaime Velasco Juan /* This registers controls some timings, not sure of what. */ 9811fdd61c0228a32b9a5e10593b225851d8920595bJaime Velasco Juan stk_camera_write_reg(dev, 0x001b, 0x0e); 9821fdd61c0228a32b9a5e10593b225851d8920595bJaime Velasco Juan if (dev->vsettings.mode == MODE_SXGA) 9831fdd61c0228a32b9a5e10593b225851d8920595bJaime Velasco Juan stk_camera_write_reg(dev, 0x001c, 0x0e); 9841fdd61c0228a32b9a5e10593b225851d8920595bJaime Velasco Juan else 9851fdd61c0228a32b9a5e10593b225851d8920595bJaime Velasco Juan stk_camera_write_reg(dev, 0x001c, 0x46); 9861fdd61c0228a32b9a5e10593b225851d8920595bJaime Velasco Juan /* 9871fdd61c0228a32b9a5e10593b225851d8920595bJaime Velasco Juan * Registers 0x0115 0x0114 are the size of each line (bytes), 9881fdd61c0228a32b9a5e10593b225851d8920595bJaime Velasco Juan * regs 0x0117 0x0116 are the heigth of the image. 9891fdd61c0228a32b9a5e10593b225851d8920595bJaime Velasco Juan */ 9901fdd61c0228a32b9a5e10593b225851d8920595bJaime Velasco Juan stk_camera_write_reg(dev, 0x0115, 9911fdd61c0228a32b9a5e10593b225851d8920595bJaime Velasco Juan ((stk_sizes[i].w * depth) >> 8) & 0xff); 9921fdd61c0228a32b9a5e10593b225851d8920595bJaime Velasco Juan stk_camera_write_reg(dev, 0x0114, 9931fdd61c0228a32b9a5e10593b225851d8920595bJaime Velasco Juan (stk_sizes[i].w * depth) & 0xff); 9941fdd61c0228a32b9a5e10593b225851d8920595bJaime Velasco Juan stk_camera_write_reg(dev, 0x0117, 9951fdd61c0228a32b9a5e10593b225851d8920595bJaime Velasco Juan (stk_sizes[i].h >> 8) & 0xff); 9961fdd61c0228a32b9a5e10593b225851d8920595bJaime Velasco Juan stk_camera_write_reg(dev, 0x0116, 9971fdd61c0228a32b9a5e10593b225851d8920595bJaime Velasco Juan stk_sizes[i].h & 0xff); 9981fdd61c0228a32b9a5e10593b225851d8920595bJaime Velasco Juan return stk_sensor_configure(dev); 9991fdd61c0228a32b9a5e10593b225851d8920595bJaime Velasco Juan} 10001fdd61c0228a32b9a5e10593b225851d8920595bJaime Velasco Juan 100178b526a43561d7e5e702ba27948e422dfbc4bea1Hans Verkuilstatic int stk_vidioc_s_fmt_vid_cap(struct file *filp, 1002ec16dae5453eafd1586f35c4ec1ef854e5a808e0Jaime Velasco Juan void *priv, struct v4l2_format *fmtd) 1003ec16dae5453eafd1586f35c4ec1ef854e5a808e0Jaime Velasco Juan{ 1004ec16dae5453eafd1586f35c4ec1ef854e5a808e0Jaime Velasco Juan int ret; 1005ec16dae5453eafd1586f35c4ec1ef854e5a808e0Jaime Velasco Juan struct stk_camera *dev = priv; 1006ec16dae5453eafd1586f35c4ec1ef854e5a808e0Jaime Velasco Juan 1007ec16dae5453eafd1586f35c4ec1ef854e5a808e0Jaime Velasco Juan if (dev == NULL) 1008ec16dae5453eafd1586f35c4ec1ef854e5a808e0Jaime Velasco Juan return -ENODEV; 1009ec16dae5453eafd1586f35c4ec1ef854e5a808e0Jaime Velasco Juan if (!is_present(dev)) 1010ec16dae5453eafd1586f35c4ec1ef854e5a808e0Jaime Velasco Juan return -ENODEV; 1011ec16dae5453eafd1586f35c4ec1ef854e5a808e0Jaime Velasco Juan if (is_streaming(dev)) 1012ec16dae5453eafd1586f35c4ec1ef854e5a808e0Jaime Velasco Juan return -EBUSY; 1013ec16dae5453eafd1586f35c4ec1ef854e5a808e0Jaime Velasco Juan if (dev->owner && dev->owner != filp) 1014ec16dae5453eafd1586f35c4ec1ef854e5a808e0Jaime Velasco Juan return -EBUSY; 101578b526a43561d7e5e702ba27948e422dfbc4bea1Hans Verkuil ret = stk_vidioc_try_fmt_vid_cap(filp, priv, fmtd); 1016ec16dae5453eafd1586f35c4ec1ef854e5a808e0Jaime Velasco Juan if (ret) 1017ec16dae5453eafd1586f35c4ec1ef854e5a808e0Jaime Velasco Juan return ret; 10181fdd61c0228a32b9a5e10593b225851d8920595bJaime Velasco Juan dev->owner = filp; 1019ec16dae5453eafd1586f35c4ec1ef854e5a808e0Jaime Velasco Juan 1020ec16dae5453eafd1586f35c4ec1ef854e5a808e0Jaime Velasco Juan dev->vsettings.palette = fmtd->fmt.pix.pixelformat; 1021ec16dae5453eafd1586f35c4ec1ef854e5a808e0Jaime Velasco Juan stk_free_buffers(dev); 1022ec16dae5453eafd1586f35c4ec1ef854e5a808e0Jaime Velasco Juan dev->frame_size = fmtd->fmt.pix.sizeimage; 1023ec16dae5453eafd1586f35c4ec1ef854e5a808e0Jaime Velasco Juan dev->vsettings.mode = stk_sizes[fmtd->fmt.pix.priv].m; 1024ec16dae5453eafd1586f35c4ec1ef854e5a808e0Jaime Velasco Juan 1025ec16dae5453eafd1586f35c4ec1ef854e5a808e0Jaime Velasco Juan stk_initialise(dev); 10261fdd61c0228a32b9a5e10593b225851d8920595bJaime Velasco Juan return stk_setup_format(dev); 1027ec16dae5453eafd1586f35c4ec1ef854e5a808e0Jaime Velasco Juan} 1028ec16dae5453eafd1586f35c4ec1ef854e5a808e0Jaime Velasco Juan 1029ec16dae5453eafd1586f35c4ec1ef854e5a808e0Jaime Velasco Juanstatic int stk_vidioc_reqbufs(struct file *filp, 1030ec16dae5453eafd1586f35c4ec1ef854e5a808e0Jaime Velasco Juan void *priv, struct v4l2_requestbuffers *rb) 1031ec16dae5453eafd1586f35c4ec1ef854e5a808e0Jaime Velasco Juan{ 1032ec16dae5453eafd1586f35c4ec1ef854e5a808e0Jaime Velasco Juan struct stk_camera *dev = priv; 1033ec16dae5453eafd1586f35c4ec1ef854e5a808e0Jaime Velasco Juan 1034ec16dae5453eafd1586f35c4ec1ef854e5a808e0Jaime Velasco Juan if (dev == NULL) 1035ec16dae5453eafd1586f35c4ec1ef854e5a808e0Jaime Velasco Juan return -ENODEV; 1036ec16dae5453eafd1586f35c4ec1ef854e5a808e0Jaime Velasco Juan if (rb->memory != V4L2_MEMORY_MMAP) 1037ec16dae5453eafd1586f35c4ec1ef854e5a808e0Jaime Velasco Juan return -EINVAL; 1038ec16dae5453eafd1586f35c4ec1ef854e5a808e0Jaime Velasco Juan if (is_streaming(dev) 1039ec16dae5453eafd1586f35c4ec1ef854e5a808e0Jaime Velasco Juan || (dev->owner && dev->owner != filp)) 1040ec16dae5453eafd1586f35c4ec1ef854e5a808e0Jaime Velasco Juan return -EBUSY; 1041ec16dae5453eafd1586f35c4ec1ef854e5a808e0Jaime Velasco Juan dev->owner = filp; 1042ec16dae5453eafd1586f35c4ec1ef854e5a808e0Jaime Velasco Juan 1043ec16dae5453eafd1586f35c4ec1ef854e5a808e0Jaime Velasco Juan /*FIXME If they ask for zero, we must stop streaming and free */ 1044ec16dae5453eafd1586f35c4ec1ef854e5a808e0Jaime Velasco Juan if (rb->count < 3) 1045ec16dae5453eafd1586f35c4ec1ef854e5a808e0Jaime Velasco Juan rb->count = 3; 1046ec16dae5453eafd1586f35c4ec1ef854e5a808e0Jaime Velasco Juan /* Arbitrary limit */ 1047ec16dae5453eafd1586f35c4ec1ef854e5a808e0Jaime Velasco Juan else if (rb->count > 5) 1048ec16dae5453eafd1586f35c4ec1ef854e5a808e0Jaime Velasco Juan rb->count = 5; 1049ec16dae5453eafd1586f35c4ec1ef854e5a808e0Jaime Velasco Juan 1050ec16dae5453eafd1586f35c4ec1ef854e5a808e0Jaime Velasco Juan stk_allocate_buffers(dev, rb->count); 1051ec16dae5453eafd1586f35c4ec1ef854e5a808e0Jaime Velasco Juan rb->count = dev->n_sbufs; 1052ec16dae5453eafd1586f35c4ec1ef854e5a808e0Jaime Velasco Juan return 0; 1053ec16dae5453eafd1586f35c4ec1ef854e5a808e0Jaime Velasco Juan} 1054ec16dae5453eafd1586f35c4ec1ef854e5a808e0Jaime Velasco Juan 1055ec16dae5453eafd1586f35c4ec1ef854e5a808e0Jaime Velasco Juanstatic int stk_vidioc_querybuf(struct file *filp, 1056ec16dae5453eafd1586f35c4ec1ef854e5a808e0Jaime Velasco Juan void *priv, struct v4l2_buffer *buf) 1057ec16dae5453eafd1586f35c4ec1ef854e5a808e0Jaime Velasco Juan{ 1058ec16dae5453eafd1586f35c4ec1ef854e5a808e0Jaime Velasco Juan struct stk_camera *dev = priv; 1059ec16dae5453eafd1586f35c4ec1ef854e5a808e0Jaime Velasco Juan struct stk_sio_buffer *sbuf; 1060ec16dae5453eafd1586f35c4ec1ef854e5a808e0Jaime Velasco Juan 1061223ffe5f8270ba9d069f1cbff9acec095a6f58b1Roel Kluin if (buf->index >= dev->n_sbufs) 1062ec16dae5453eafd1586f35c4ec1ef854e5a808e0Jaime Velasco Juan return -EINVAL; 1063ec16dae5453eafd1586f35c4ec1ef854e5a808e0Jaime Velasco Juan sbuf = dev->sio_bufs + buf->index; 1064ec16dae5453eafd1586f35c4ec1ef854e5a808e0Jaime Velasco Juan *buf = sbuf->v4lbuf; 1065ec16dae5453eafd1586f35c4ec1ef854e5a808e0Jaime Velasco Juan return 0; 1066ec16dae5453eafd1586f35c4ec1ef854e5a808e0Jaime Velasco Juan} 1067ec16dae5453eafd1586f35c4ec1ef854e5a808e0Jaime Velasco Juan 1068ec16dae5453eafd1586f35c4ec1ef854e5a808e0Jaime Velasco Juanstatic int stk_vidioc_qbuf(struct file *filp, 1069ec16dae5453eafd1586f35c4ec1ef854e5a808e0Jaime Velasco Juan void *priv, struct v4l2_buffer *buf) 1070ec16dae5453eafd1586f35c4ec1ef854e5a808e0Jaime Velasco Juan{ 1071ec16dae5453eafd1586f35c4ec1ef854e5a808e0Jaime Velasco Juan struct stk_camera *dev = priv; 1072ec16dae5453eafd1586f35c4ec1ef854e5a808e0Jaime Velasco Juan struct stk_sio_buffer *sbuf; 1073ec16dae5453eafd1586f35c4ec1ef854e5a808e0Jaime Velasco Juan unsigned long flags; 1074ec16dae5453eafd1586f35c4ec1ef854e5a808e0Jaime Velasco Juan 1075ec16dae5453eafd1586f35c4ec1ef854e5a808e0Jaime Velasco Juan if (buf->memory != V4L2_MEMORY_MMAP) 1076ec16dae5453eafd1586f35c4ec1ef854e5a808e0Jaime Velasco Juan return -EINVAL; 1077ec16dae5453eafd1586f35c4ec1ef854e5a808e0Jaime Velasco Juan 1078223ffe5f8270ba9d069f1cbff9acec095a6f58b1Roel Kluin if (buf->index >= dev->n_sbufs) 1079ec16dae5453eafd1586f35c4ec1ef854e5a808e0Jaime Velasco Juan return -EINVAL; 1080ec16dae5453eafd1586f35c4ec1ef854e5a808e0Jaime Velasco Juan sbuf = dev->sio_bufs + buf->index; 1081ec16dae5453eafd1586f35c4ec1ef854e5a808e0Jaime Velasco Juan if (sbuf->v4lbuf.flags & V4L2_BUF_FLAG_QUEUED) 1082ec16dae5453eafd1586f35c4ec1ef854e5a808e0Jaime Velasco Juan return 0; 1083ec16dae5453eafd1586f35c4ec1ef854e5a808e0Jaime Velasco Juan sbuf->v4lbuf.flags |= V4L2_BUF_FLAG_QUEUED; 1084ec16dae5453eafd1586f35c4ec1ef854e5a808e0Jaime Velasco Juan sbuf->v4lbuf.flags &= ~V4L2_BUF_FLAG_DONE; 1085ec16dae5453eafd1586f35c4ec1ef854e5a808e0Jaime Velasco Juan spin_lock_irqsave(&dev->spinlock, flags); 1086ec16dae5453eafd1586f35c4ec1ef854e5a808e0Jaime Velasco Juan list_add_tail(&sbuf->list, &dev->sio_avail); 1087ec16dae5453eafd1586f35c4ec1ef854e5a808e0Jaime Velasco Juan *buf = sbuf->v4lbuf; 1088ec16dae5453eafd1586f35c4ec1ef854e5a808e0Jaime Velasco Juan spin_unlock_irqrestore(&dev->spinlock, flags); 1089ec16dae5453eafd1586f35c4ec1ef854e5a808e0Jaime Velasco Juan return 0; 1090ec16dae5453eafd1586f35c4ec1ef854e5a808e0Jaime Velasco Juan} 1091ec16dae5453eafd1586f35c4ec1ef854e5a808e0Jaime Velasco Juan 1092ec16dae5453eafd1586f35c4ec1ef854e5a808e0Jaime Velasco Juanstatic int stk_vidioc_dqbuf(struct file *filp, 1093ec16dae5453eafd1586f35c4ec1ef854e5a808e0Jaime Velasco Juan void *priv, struct v4l2_buffer *buf) 1094ec16dae5453eafd1586f35c4ec1ef854e5a808e0Jaime Velasco Juan{ 1095ec16dae5453eafd1586f35c4ec1ef854e5a808e0Jaime Velasco Juan struct stk_camera *dev = priv; 1096ec16dae5453eafd1586f35c4ec1ef854e5a808e0Jaime Velasco Juan struct stk_sio_buffer *sbuf; 1097ec16dae5453eafd1586f35c4ec1ef854e5a808e0Jaime Velasco Juan unsigned long flags; 1098ec16dae5453eafd1586f35c4ec1ef854e5a808e0Jaime Velasco Juan int ret; 1099ec16dae5453eafd1586f35c4ec1ef854e5a808e0Jaime Velasco Juan 11002509e1cb3360961113117f25ae482c430f3bd03dTrent Piepho if (!is_streaming(dev)) 1101ec16dae5453eafd1586f35c4ec1ef854e5a808e0Jaime Velasco Juan return -EINVAL; 1102ec16dae5453eafd1586f35c4ec1ef854e5a808e0Jaime Velasco Juan 1103ec16dae5453eafd1586f35c4ec1ef854e5a808e0Jaime Velasco Juan if (filp->f_flags & O_NONBLOCK && list_empty(&dev->sio_full)) 1104ec16dae5453eafd1586f35c4ec1ef854e5a808e0Jaime Velasco Juan return -EWOULDBLOCK; 1105ec16dae5453eafd1586f35c4ec1ef854e5a808e0Jaime Velasco Juan ret = wait_event_interruptible(dev->wait_frame, 1106ec16dae5453eafd1586f35c4ec1ef854e5a808e0Jaime Velasco Juan !list_empty(&dev->sio_full) || !is_present(dev)); 1107ec16dae5453eafd1586f35c4ec1ef854e5a808e0Jaime Velasco Juan if (ret) 1108ec16dae5453eafd1586f35c4ec1ef854e5a808e0Jaime Velasco Juan return ret; 1109ec16dae5453eafd1586f35c4ec1ef854e5a808e0Jaime Velasco Juan if (!is_present(dev)) 1110ec16dae5453eafd1586f35c4ec1ef854e5a808e0Jaime Velasco Juan return -EIO; 1111ec16dae5453eafd1586f35c4ec1ef854e5a808e0Jaime Velasco Juan 1112ec16dae5453eafd1586f35c4ec1ef854e5a808e0Jaime Velasco Juan spin_lock_irqsave(&dev->spinlock, flags); 1113ec16dae5453eafd1586f35c4ec1ef854e5a808e0Jaime Velasco Juan sbuf = list_first_entry(&dev->sio_full, struct stk_sio_buffer, list); 1114ec16dae5453eafd1586f35c4ec1ef854e5a808e0Jaime Velasco Juan list_del_init(&sbuf->list); 1115ec16dae5453eafd1586f35c4ec1ef854e5a808e0Jaime Velasco Juan spin_unlock_irqrestore(&dev->spinlock, flags); 1116ec16dae5453eafd1586f35c4ec1ef854e5a808e0Jaime Velasco Juan sbuf->v4lbuf.flags &= ~V4L2_BUF_FLAG_QUEUED; 1117ec16dae5453eafd1586f35c4ec1ef854e5a808e0Jaime Velasco Juan sbuf->v4lbuf.flags |= V4L2_BUF_FLAG_DONE; 1118ec16dae5453eafd1586f35c4ec1ef854e5a808e0Jaime Velasco Juan sbuf->v4lbuf.sequence = ++dev->sequence; 1119ec16dae5453eafd1586f35c4ec1ef854e5a808e0Jaime Velasco Juan do_gettimeofday(&sbuf->v4lbuf.timestamp); 1120ec16dae5453eafd1586f35c4ec1ef854e5a808e0Jaime Velasco Juan 1121ec16dae5453eafd1586f35c4ec1ef854e5a808e0Jaime Velasco Juan *buf = sbuf->v4lbuf; 1122ec16dae5453eafd1586f35c4ec1ef854e5a808e0Jaime Velasco Juan return 0; 1123ec16dae5453eafd1586f35c4ec1ef854e5a808e0Jaime Velasco Juan} 1124ec16dae5453eafd1586f35c4ec1ef854e5a808e0Jaime Velasco Juan 1125ec16dae5453eafd1586f35c4ec1ef854e5a808e0Jaime Velasco Juanstatic int stk_vidioc_streamon(struct file *filp, 1126ec16dae5453eafd1586f35c4ec1ef854e5a808e0Jaime Velasco Juan void *priv, enum v4l2_buf_type type) 1127ec16dae5453eafd1586f35c4ec1ef854e5a808e0Jaime Velasco Juan{ 1128ec16dae5453eafd1586f35c4ec1ef854e5a808e0Jaime Velasco Juan struct stk_camera *dev = priv; 1129ec16dae5453eafd1586f35c4ec1ef854e5a808e0Jaime Velasco Juan if (is_streaming(dev)) 1130ec16dae5453eafd1586f35c4ec1ef854e5a808e0Jaime Velasco Juan return 0; 1131ec16dae5453eafd1586f35c4ec1ef854e5a808e0Jaime Velasco Juan if (dev->sio_bufs == NULL) 1132ec16dae5453eafd1586f35c4ec1ef854e5a808e0Jaime Velasco Juan return -EINVAL; 1133ec16dae5453eafd1586f35c4ec1ef854e5a808e0Jaime Velasco Juan dev->sequence = 0; 1134ec16dae5453eafd1586f35c4ec1ef854e5a808e0Jaime Velasco Juan return stk_start_stream(dev); 1135ec16dae5453eafd1586f35c4ec1ef854e5a808e0Jaime Velasco Juan} 1136ec16dae5453eafd1586f35c4ec1ef854e5a808e0Jaime Velasco Juan 1137ec16dae5453eafd1586f35c4ec1ef854e5a808e0Jaime Velasco Juanstatic int stk_vidioc_streamoff(struct file *filp, 1138ec16dae5453eafd1586f35c4ec1ef854e5a808e0Jaime Velasco Juan void *priv, enum v4l2_buf_type type) 1139ec16dae5453eafd1586f35c4ec1ef854e5a808e0Jaime Velasco Juan{ 1140ec16dae5453eafd1586f35c4ec1ef854e5a808e0Jaime Velasco Juan struct stk_camera *dev = priv; 1141ec16dae5453eafd1586f35c4ec1ef854e5a808e0Jaime Velasco Juan unsigned long flags; 1142ec16dae5453eafd1586f35c4ec1ef854e5a808e0Jaime Velasco Juan int i; 1143ec16dae5453eafd1586f35c4ec1ef854e5a808e0Jaime Velasco Juan stk_stop_stream(dev); 1144ec16dae5453eafd1586f35c4ec1ef854e5a808e0Jaime Velasco Juan spin_lock_irqsave(&dev->spinlock, flags); 1145ec16dae5453eafd1586f35c4ec1ef854e5a808e0Jaime Velasco Juan INIT_LIST_HEAD(&dev->sio_avail); 1146ec16dae5453eafd1586f35c4ec1ef854e5a808e0Jaime Velasco Juan INIT_LIST_HEAD(&dev->sio_full); 1147ec16dae5453eafd1586f35c4ec1ef854e5a808e0Jaime Velasco Juan for (i = 0; i < dev->n_sbufs; i++) { 1148ec16dae5453eafd1586f35c4ec1ef854e5a808e0Jaime Velasco Juan INIT_LIST_HEAD(&dev->sio_bufs[i].list); 1149ec16dae5453eafd1586f35c4ec1ef854e5a808e0Jaime Velasco Juan dev->sio_bufs[i].v4lbuf.flags = 0; 1150ec16dae5453eafd1586f35c4ec1ef854e5a808e0Jaime Velasco Juan } 1151ec16dae5453eafd1586f35c4ec1ef854e5a808e0Jaime Velasco Juan spin_unlock_irqrestore(&dev->spinlock, flags); 1152ec16dae5453eafd1586f35c4ec1ef854e5a808e0Jaime Velasco Juan return 0; 1153ec16dae5453eafd1586f35c4ec1ef854e5a808e0Jaime Velasco Juan} 1154ec16dae5453eafd1586f35c4ec1ef854e5a808e0Jaime Velasco Juan 1155ec16dae5453eafd1586f35c4ec1ef854e5a808e0Jaime Velasco Juan 1156ec16dae5453eafd1586f35c4ec1ef854e5a808e0Jaime Velasco Juanstatic int stk_vidioc_g_parm(struct file *filp, 1157ec16dae5453eafd1586f35c4ec1ef854e5a808e0Jaime Velasco Juan void *priv, struct v4l2_streamparm *sp) 1158ec16dae5453eafd1586f35c4ec1ef854e5a808e0Jaime Velasco Juan{ 1159ec16dae5453eafd1586f35c4ec1ef854e5a808e0Jaime Velasco Juan /*FIXME This is not correct */ 1160ec16dae5453eafd1586f35c4ec1ef854e5a808e0Jaime Velasco Juan sp->parm.capture.timeperframe.numerator = 1; 1161ec16dae5453eafd1586f35c4ec1ef854e5a808e0Jaime Velasco Juan sp->parm.capture.timeperframe.denominator = 30; 1162ec16dae5453eafd1586f35c4ec1ef854e5a808e0Jaime Velasco Juan sp->parm.capture.readbuffers = 2; 1163ec16dae5453eafd1586f35c4ec1ef854e5a808e0Jaime Velasco Juan return 0; 1164ec16dae5453eafd1586f35c4ec1ef854e5a808e0Jaime Velasco Juan} 1165ec16dae5453eafd1586f35c4ec1ef854e5a808e0Jaime Velasco Juan 1166126be90f720d9b23e89c68519022fb806882f42dJaime Velasco Juanstatic int stk_vidioc_enum_framesizes(struct file *filp, 1167126be90f720d9b23e89c68519022fb806882f42dJaime Velasco Juan void *priv, struct v4l2_frmsizeenum *frms) 1168126be90f720d9b23e89c68519022fb806882f42dJaime Velasco Juan{ 1169126be90f720d9b23e89c68519022fb806882f42dJaime Velasco Juan if (frms->index >= ARRAY_SIZE(stk_sizes)) 1170126be90f720d9b23e89c68519022fb806882f42dJaime Velasco Juan return -EINVAL; 1171126be90f720d9b23e89c68519022fb806882f42dJaime Velasco Juan switch (frms->pixel_format) { 1172126be90f720d9b23e89c68519022fb806882f42dJaime Velasco Juan case V4L2_PIX_FMT_RGB565: 1173126be90f720d9b23e89c68519022fb806882f42dJaime Velasco Juan case V4L2_PIX_FMT_RGB565X: 1174126be90f720d9b23e89c68519022fb806882f42dJaime Velasco Juan case V4L2_PIX_FMT_UYVY: 1175126be90f720d9b23e89c68519022fb806882f42dJaime Velasco Juan case V4L2_PIX_FMT_YUYV: 1176126be90f720d9b23e89c68519022fb806882f42dJaime Velasco Juan case V4L2_PIX_FMT_SBGGR8: 1177126be90f720d9b23e89c68519022fb806882f42dJaime Velasco Juan frms->type = V4L2_FRMSIZE_TYPE_DISCRETE; 1178126be90f720d9b23e89c68519022fb806882f42dJaime Velasco Juan frms->discrete.width = stk_sizes[frms->index].w; 1179126be90f720d9b23e89c68519022fb806882f42dJaime Velasco Juan frms->discrete.height = stk_sizes[frms->index].h; 1180126be90f720d9b23e89c68519022fb806882f42dJaime Velasco Juan return 0; 1181126be90f720d9b23e89c68519022fb806882f42dJaime Velasco Juan default: return -EINVAL; 1182126be90f720d9b23e89c68519022fb806882f42dJaime Velasco Juan } 1183126be90f720d9b23e89c68519022fb806882f42dJaime Velasco Juan} 1184126be90f720d9b23e89c68519022fb806882f42dJaime Velasco Juan 1185bec43661b1dc0075b7445223ba775674133b164dHans Verkuilstatic struct v4l2_file_operations v4l_stk_fops = { 1186ec16dae5453eafd1586f35c4ec1ef854e5a808e0Jaime Velasco Juan .owner = THIS_MODULE, 1187ec16dae5453eafd1586f35c4ec1ef854e5a808e0Jaime Velasco Juan .open = v4l_stk_open, 1188ec16dae5453eafd1586f35c4ec1ef854e5a808e0Jaime Velasco Juan .release = v4l_stk_release, 1189ec16dae5453eafd1586f35c4ec1ef854e5a808e0Jaime Velasco Juan .read = v4l_stk_read, 1190ec16dae5453eafd1586f35c4ec1ef854e5a808e0Jaime Velasco Juan .poll = v4l_stk_poll, 1191ec16dae5453eafd1586f35c4ec1ef854e5a808e0Jaime Velasco Juan .mmap = v4l_stk_mmap, 1192ec16dae5453eafd1586f35c4ec1ef854e5a808e0Jaime Velasco Juan .ioctl = video_ioctl2, 1193ec16dae5453eafd1586f35c4ec1ef854e5a808e0Jaime Velasco Juan}; 1194ec16dae5453eafd1586f35c4ec1ef854e5a808e0Jaime Velasco Juan 1195a399810ca69d9d4bd30ab8c1678c7439e567f90bHans Verkuilstatic const struct v4l2_ioctl_ops v4l_stk_ioctl_ops = { 1196ec16dae5453eafd1586f35c4ec1ef854e5a808e0Jaime Velasco Juan .vidioc_querycap = stk_vidioc_querycap, 119778b526a43561d7e5e702ba27948e422dfbc4bea1Hans Verkuil .vidioc_enum_fmt_vid_cap = stk_vidioc_enum_fmt_vid_cap, 119878b526a43561d7e5e702ba27948e422dfbc4bea1Hans Verkuil .vidioc_try_fmt_vid_cap = stk_vidioc_try_fmt_vid_cap, 119978b526a43561d7e5e702ba27948e422dfbc4bea1Hans Verkuil .vidioc_s_fmt_vid_cap = stk_vidioc_s_fmt_vid_cap, 120078b526a43561d7e5e702ba27948e422dfbc4bea1Hans Verkuil .vidioc_g_fmt_vid_cap = stk_vidioc_g_fmt_vid_cap, 1201ec16dae5453eafd1586f35c4ec1ef854e5a808e0Jaime Velasco Juan .vidioc_enum_input = stk_vidioc_enum_input, 1202ec16dae5453eafd1586f35c4ec1ef854e5a808e0Jaime Velasco Juan .vidioc_s_input = stk_vidioc_s_input, 1203ec16dae5453eafd1586f35c4ec1ef854e5a808e0Jaime Velasco Juan .vidioc_g_input = stk_vidioc_g_input, 1204ec16dae5453eafd1586f35c4ec1ef854e5a808e0Jaime Velasco Juan .vidioc_s_std = stk_vidioc_s_std, 1205ec16dae5453eafd1586f35c4ec1ef854e5a808e0Jaime Velasco Juan .vidioc_reqbufs = stk_vidioc_reqbufs, 1206ec16dae5453eafd1586f35c4ec1ef854e5a808e0Jaime Velasco Juan .vidioc_querybuf = stk_vidioc_querybuf, 1207ec16dae5453eafd1586f35c4ec1ef854e5a808e0Jaime Velasco Juan .vidioc_qbuf = stk_vidioc_qbuf, 1208ec16dae5453eafd1586f35c4ec1ef854e5a808e0Jaime Velasco Juan .vidioc_dqbuf = stk_vidioc_dqbuf, 1209ec16dae5453eafd1586f35c4ec1ef854e5a808e0Jaime Velasco Juan .vidioc_streamon = stk_vidioc_streamon, 1210ec16dae5453eafd1586f35c4ec1ef854e5a808e0Jaime Velasco Juan .vidioc_streamoff = stk_vidioc_streamoff, 1211ec16dae5453eafd1586f35c4ec1ef854e5a808e0Jaime Velasco Juan .vidioc_queryctrl = stk_vidioc_queryctrl, 1212ec16dae5453eafd1586f35c4ec1ef854e5a808e0Jaime Velasco Juan .vidioc_g_ctrl = stk_vidioc_g_ctrl, 1213ec16dae5453eafd1586f35c4ec1ef854e5a808e0Jaime Velasco Juan .vidioc_s_ctrl = stk_vidioc_s_ctrl, 1214ec16dae5453eafd1586f35c4ec1ef854e5a808e0Jaime Velasco Juan .vidioc_g_parm = stk_vidioc_g_parm, 1215126be90f720d9b23e89c68519022fb806882f42dJaime Velasco Juan .vidioc_enum_framesizes = stk_vidioc_enum_framesizes, 1216ec16dae5453eafd1586f35c4ec1ef854e5a808e0Jaime Velasco Juan}; 1217ec16dae5453eafd1586f35c4ec1ef854e5a808e0Jaime Velasco Juan 1218a399810ca69d9d4bd30ab8c1678c7439e567f90bHans Verkuilstatic void stk_v4l_dev_release(struct video_device *vd) 1219a399810ca69d9d4bd30ab8c1678c7439e567f90bHans Verkuil{ 12204aaec3ea41addf6fe4fe029aa535f3c019ee0e6dDavid Ellingsworth struct stk_camera *dev = vdev_to_camera(vd); 12214aaec3ea41addf6fe4fe029aa535f3c019ee0e6dDavid Ellingsworth 12224aaec3ea41addf6fe4fe029aa535f3c019ee0e6dDavid Ellingsworth if (dev->sio_bufs != NULL || dev->isobufs != NULL) 12234aaec3ea41addf6fe4fe029aa535f3c019ee0e6dDavid Ellingsworth STK_ERROR("We are leaking memory\n"); 12244aaec3ea41addf6fe4fe029aa535f3c019ee0e6dDavid Ellingsworth usb_put_intf(dev->interface); 12254aaec3ea41addf6fe4fe029aa535f3c019ee0e6dDavid Ellingsworth kfree(dev); 1226a399810ca69d9d4bd30ab8c1678c7439e567f90bHans Verkuil} 1227a399810ca69d9d4bd30ab8c1678c7439e567f90bHans Verkuil 1228a399810ca69d9d4bd30ab8c1678c7439e567f90bHans Verkuilstatic struct video_device stk_v4l_data = { 1229a399810ca69d9d4bd30ab8c1678c7439e567f90bHans Verkuil .name = "stkwebcam", 1230a399810ca69d9d4bd30ab8c1678c7439e567f90bHans Verkuil .tvnorms = V4L2_STD_UNKNOWN, 1231a399810ca69d9d4bd30ab8c1678c7439e567f90bHans Verkuil .current_norm = V4L2_STD_UNKNOWN, 1232a399810ca69d9d4bd30ab8c1678c7439e567f90bHans Verkuil .fops = &v4l_stk_fops, 1233a399810ca69d9d4bd30ab8c1678c7439e567f90bHans Verkuil .ioctl_ops = &v4l_stk_ioctl_ops, 1234a399810ca69d9d4bd30ab8c1678c7439e567f90bHans Verkuil .release = stk_v4l_dev_release, 1235a399810ca69d9d4bd30ab8c1678c7439e567f90bHans Verkuil}; 1236a399810ca69d9d4bd30ab8c1678c7439e567f90bHans Verkuil 1237ec16dae5453eafd1586f35c4ec1ef854e5a808e0Jaime Velasco Juan 1238ec16dae5453eafd1586f35c4ec1ef854e5a808e0Jaime Velasco Juanstatic int stk_register_video_device(struct stk_camera *dev) 1239ec16dae5453eafd1586f35c4ec1ef854e5a808e0Jaime Velasco Juan{ 1240ec16dae5453eafd1586f35c4ec1ef854e5a808e0Jaime Velasco Juan int err; 1241ec16dae5453eafd1586f35c4ec1ef854e5a808e0Jaime Velasco Juan 1242ec16dae5453eafd1586f35c4ec1ef854e5a808e0Jaime Velasco Juan dev->vdev = stk_v4l_data; 1243ec16dae5453eafd1586f35c4ec1ef854e5a808e0Jaime Velasco Juan dev->vdev.debug = debug; 12445e85e732f0ed56aa97a3ba26ac2b93ffe597a208Hans Verkuil dev->vdev.parent = &dev->interface->dev; 1245ec16dae5453eafd1586f35c4ec1ef854e5a808e0Jaime Velasco Juan err = video_register_device(&dev->vdev, VFL_TYPE_GRABBER, -1); 1246ec16dae5453eafd1586f35c4ec1ef854e5a808e0Jaime Velasco Juan if (err) 1247ec16dae5453eafd1586f35c4ec1ef854e5a808e0Jaime Velasco Juan STK_ERROR("v4l registration failed\n"); 1248ec16dae5453eafd1586f35c4ec1ef854e5a808e0Jaime Velasco Juan else 124938c7c036036c6260606a2a833aaad3794ca22499Laurent Pinchart STK_INFO("Syntek USB2.0 Camera is now controlling device %s\n", 125038c7c036036c6260606a2a833aaad3794ca22499Laurent Pinchart video_device_node_name(&dev->vdev)); 1251ec16dae5453eafd1586f35c4ec1ef854e5a808e0Jaime Velasco Juan return err; 1252ec16dae5453eafd1586f35c4ec1ef854e5a808e0Jaime Velasco Juan} 1253ec16dae5453eafd1586f35c4ec1ef854e5a808e0Jaime Velasco Juan 1254ec16dae5453eafd1586f35c4ec1ef854e5a808e0Jaime Velasco Juan 1255ec16dae5453eafd1586f35c4ec1ef854e5a808e0Jaime Velasco Juan/* USB Stuff */ 1256ec16dae5453eafd1586f35c4ec1ef854e5a808e0Jaime Velasco Juan 1257ec16dae5453eafd1586f35c4ec1ef854e5a808e0Jaime Velasco Juanstatic int stk_camera_probe(struct usb_interface *interface, 1258ec16dae5453eafd1586f35c4ec1ef854e5a808e0Jaime Velasco Juan const struct usb_device_id *id) 1259ec16dae5453eafd1586f35c4ec1ef854e5a808e0Jaime Velasco Juan{ 1260ec16dae5453eafd1586f35c4ec1ef854e5a808e0Jaime Velasco Juan int i; 12614aaec3ea41addf6fe4fe029aa535f3c019ee0e6dDavid Ellingsworth int err = 0; 1262ec16dae5453eafd1586f35c4ec1ef854e5a808e0Jaime Velasco Juan 1263ec16dae5453eafd1586f35c4ec1ef854e5a808e0Jaime Velasco Juan struct stk_camera *dev = NULL; 1264ec16dae5453eafd1586f35c4ec1ef854e5a808e0Jaime Velasco Juan struct usb_device *udev = interface_to_usbdev(interface); 1265ec16dae5453eafd1586f35c4ec1ef854e5a808e0Jaime Velasco Juan struct usb_host_interface *iface_desc; 1266ec16dae5453eafd1586f35c4ec1ef854e5a808e0Jaime Velasco Juan struct usb_endpoint_descriptor *endpoint; 1267ec16dae5453eafd1586f35c4ec1ef854e5a808e0Jaime Velasco Juan 1268ec16dae5453eafd1586f35c4ec1ef854e5a808e0Jaime Velasco Juan dev = kzalloc(sizeof(struct stk_camera), GFP_KERNEL); 1269ec16dae5453eafd1586f35c4ec1ef854e5a808e0Jaime Velasco Juan if (dev == NULL) { 1270ec16dae5453eafd1586f35c4ec1ef854e5a808e0Jaime Velasco Juan STK_ERROR("Out of memory !\n"); 1271ec16dae5453eafd1586f35c4ec1ef854e5a808e0Jaime Velasco Juan return -ENOMEM; 1272ec16dae5453eafd1586f35c4ec1ef854e5a808e0Jaime Velasco Juan } 1273ec16dae5453eafd1586f35c4ec1ef854e5a808e0Jaime Velasco Juan 1274ec16dae5453eafd1586f35c4ec1ef854e5a808e0Jaime Velasco Juan spin_lock_init(&dev->spinlock); 1275ec16dae5453eafd1586f35c4ec1ef854e5a808e0Jaime Velasco Juan init_waitqueue_head(&dev->wait_frame); 1276ec16dae5453eafd1586f35c4ec1ef854e5a808e0Jaime Velasco Juan 1277ec16dae5453eafd1586f35c4ec1ef854e5a808e0Jaime Velasco Juan dev->udev = udev; 1278ec16dae5453eafd1586f35c4ec1ef854e5a808e0Jaime Velasco Juan dev->interface = interface; 1279ec16dae5453eafd1586f35c4ec1ef854e5a808e0Jaime Velasco Juan usb_get_intf(interface); 1280ec16dae5453eafd1586f35c4ec1ef854e5a808e0Jaime Velasco Juan 1281ec16dae5453eafd1586f35c4ec1ef854e5a808e0Jaime Velasco Juan dev->vsettings.vflip = vflip; 1282ec16dae5453eafd1586f35c4ec1ef854e5a808e0Jaime Velasco Juan dev->vsettings.hflip = hflip; 1283ec16dae5453eafd1586f35c4ec1ef854e5a808e0Jaime Velasco Juan dev->n_sbufs = 0; 1284ec16dae5453eafd1586f35c4ec1ef854e5a808e0Jaime Velasco Juan set_present(dev); 1285ec16dae5453eafd1586f35c4ec1ef854e5a808e0Jaime Velasco Juan 1286ec16dae5453eafd1586f35c4ec1ef854e5a808e0Jaime Velasco Juan /* Set up the endpoint information 1287ec16dae5453eafd1586f35c4ec1ef854e5a808e0Jaime Velasco Juan * use only the first isoc-in endpoint 1288ec16dae5453eafd1586f35c4ec1ef854e5a808e0Jaime Velasco Juan * for the current alternate setting */ 1289ec16dae5453eafd1586f35c4ec1ef854e5a808e0Jaime Velasco Juan iface_desc = interface->cur_altsetting; 1290ec16dae5453eafd1586f35c4ec1ef854e5a808e0Jaime Velasco Juan 1291ec16dae5453eafd1586f35c4ec1ef854e5a808e0Jaime Velasco Juan for (i = 0; i < iface_desc->desc.bNumEndpoints; ++i) { 1292ec16dae5453eafd1586f35c4ec1ef854e5a808e0Jaime Velasco Juan endpoint = &iface_desc->endpoint[i].desc; 1293ec16dae5453eafd1586f35c4ec1ef854e5a808e0Jaime Velasco Juan 1294ec16dae5453eafd1586f35c4ec1ef854e5a808e0Jaime Velasco Juan if (!dev->isoc_ep 1295134179823b3ca9c8b98e0631906459dbb022ff9bJulia Lawall && usb_endpoint_is_isoc_in(endpoint)) { 1296ec16dae5453eafd1586f35c4ec1ef854e5a808e0Jaime Velasco Juan /* we found an isoc in endpoint */ 1297134179823b3ca9c8b98e0631906459dbb022ff9bJulia Lawall dev->isoc_ep = usb_endpoint_num(endpoint); 1298ec16dae5453eafd1586f35c4ec1ef854e5a808e0Jaime Velasco Juan break; 1299ec16dae5453eafd1586f35c4ec1ef854e5a808e0Jaime Velasco Juan } 1300ec16dae5453eafd1586f35c4ec1ef854e5a808e0Jaime Velasco Juan } 1301ec16dae5453eafd1586f35c4ec1ef854e5a808e0Jaime Velasco Juan if (!dev->isoc_ep) { 1302ec16dae5453eafd1586f35c4ec1ef854e5a808e0Jaime Velasco Juan STK_ERROR("Could not find isoc-in endpoint"); 13034aaec3ea41addf6fe4fe029aa535f3c019ee0e6dDavid Ellingsworth err = -ENODEV; 13044aaec3ea41addf6fe4fe029aa535f3c019ee0e6dDavid Ellingsworth goto error; 1305ec16dae5453eafd1586f35c4ec1ef854e5a808e0Jaime Velasco Juan } 1306ec16dae5453eafd1586f35c4ec1ef854e5a808e0Jaime Velasco Juan dev->vsettings.brightness = 0x7fff; 1307ec16dae5453eafd1586f35c4ec1ef854e5a808e0Jaime Velasco Juan dev->vsettings.palette = V4L2_PIX_FMT_RGB565; 1308ec16dae5453eafd1586f35c4ec1ef854e5a808e0Jaime Velasco Juan dev->vsettings.mode = MODE_VGA; 13091112fb68ae9c838294d38e1f209fedbc0dbf11d5Jaime Velasco Juan dev->frame_size = 640 * 480 * 2; 1310ec16dae5453eafd1586f35c4ec1ef854e5a808e0Jaime Velasco Juan 1311ec16dae5453eafd1586f35c4ec1ef854e5a808e0Jaime Velasco Juan INIT_LIST_HEAD(&dev->sio_avail); 1312ec16dae5453eafd1586f35c4ec1ef854e5a808e0Jaime Velasco Juan INIT_LIST_HEAD(&dev->sio_full); 1313ec16dae5453eafd1586f35c4ec1ef854e5a808e0Jaime Velasco Juan 1314ec16dae5453eafd1586f35c4ec1ef854e5a808e0Jaime Velasco Juan usb_set_intfdata(interface, dev); 1315ec16dae5453eafd1586f35c4ec1ef854e5a808e0Jaime Velasco Juan 1316ec16dae5453eafd1586f35c4ec1ef854e5a808e0Jaime Velasco Juan err = stk_register_video_device(dev); 1317b57ce4179b502b3f481f7632da20aae3e488e31aArvydas Sidorenko if (err) 13184aaec3ea41addf6fe4fe029aa535f3c019ee0e6dDavid Ellingsworth goto error; 1319ec16dae5453eafd1586f35c4ec1ef854e5a808e0Jaime Velasco Juan 1320ec16dae5453eafd1586f35c4ec1ef854e5a808e0Jaime Velasco Juan return 0; 13214aaec3ea41addf6fe4fe029aa535f3c019ee0e6dDavid Ellingsworth 13224aaec3ea41addf6fe4fe029aa535f3c019ee0e6dDavid Ellingswortherror: 13234aaec3ea41addf6fe4fe029aa535f3c019ee0e6dDavid Ellingsworth kfree(dev); 13244aaec3ea41addf6fe4fe029aa535f3c019ee0e6dDavid Ellingsworth return err; 1325ec16dae5453eafd1586f35c4ec1ef854e5a808e0Jaime Velasco Juan} 1326ec16dae5453eafd1586f35c4ec1ef854e5a808e0Jaime Velasco Juan 1327ec16dae5453eafd1586f35c4ec1ef854e5a808e0Jaime Velasco Juanstatic void stk_camera_disconnect(struct usb_interface *interface) 1328ec16dae5453eafd1586f35c4ec1ef854e5a808e0Jaime Velasco Juan{ 1329ec16dae5453eafd1586f35c4ec1ef854e5a808e0Jaime Velasco Juan struct stk_camera *dev = usb_get_intfdata(interface); 1330ec16dae5453eafd1586f35c4ec1ef854e5a808e0Jaime Velasco Juan 1331ec16dae5453eafd1586f35c4ec1ef854e5a808e0Jaime Velasco Juan usb_set_intfdata(interface, NULL); 1332ec16dae5453eafd1586f35c4ec1ef854e5a808e0Jaime Velasco Juan unset_present(dev); 1333ec16dae5453eafd1586f35c4ec1ef854e5a808e0Jaime Velasco Juan 1334ec16dae5453eafd1586f35c4ec1ef854e5a808e0Jaime Velasco Juan wake_up_interruptible(&dev->wait_frame); 1335ec16dae5453eafd1586f35c4ec1ef854e5a808e0Jaime Velasco Juan 133638c7c036036c6260606a2a833aaad3794ca22499Laurent Pinchart STK_INFO("Syntek USB2.0 Camera release resources device %s\n", 133738c7c036036c6260606a2a833aaad3794ca22499Laurent Pinchart video_device_node_name(&dev->vdev)); 13384aaec3ea41addf6fe4fe029aa535f3c019ee0e6dDavid Ellingsworth 13394aaec3ea41addf6fe4fe029aa535f3c019ee0e6dDavid Ellingsworth video_unregister_device(&dev->vdev); 1340ec16dae5453eafd1586f35c4ec1ef854e5a808e0Jaime Velasco Juan} 1341ec16dae5453eafd1586f35c4ec1ef854e5a808e0Jaime Velasco Juan 13421fdd61c0228a32b9a5e10593b225851d8920595bJaime Velasco Juan#ifdef CONFIG_PM 13434d34dccd5e8af3db8dbb594d6cd1ea74446dbf20Adrian Bunkstatic int stk_camera_suspend(struct usb_interface *intf, pm_message_t message) 13441fdd61c0228a32b9a5e10593b225851d8920595bJaime Velasco Juan{ 13451fdd61c0228a32b9a5e10593b225851d8920595bJaime Velasco Juan struct stk_camera *dev = usb_get_intfdata(intf); 13461fdd61c0228a32b9a5e10593b225851d8920595bJaime Velasco Juan if (is_streaming(dev)) { 13471fdd61c0228a32b9a5e10593b225851d8920595bJaime Velasco Juan stk_stop_stream(dev); 13481fdd61c0228a32b9a5e10593b225851d8920595bJaime Velasco Juan /* yes, this is ugly */ 13491fdd61c0228a32b9a5e10593b225851d8920595bJaime Velasco Juan set_streaming(dev); 13501fdd61c0228a32b9a5e10593b225851d8920595bJaime Velasco Juan } 13511fdd61c0228a32b9a5e10593b225851d8920595bJaime Velasco Juan return 0; 13521fdd61c0228a32b9a5e10593b225851d8920595bJaime Velasco Juan} 13531fdd61c0228a32b9a5e10593b225851d8920595bJaime Velasco Juan 13544d34dccd5e8af3db8dbb594d6cd1ea74446dbf20Adrian Bunkstatic int stk_camera_resume(struct usb_interface *intf) 13551fdd61c0228a32b9a5e10593b225851d8920595bJaime Velasco Juan{ 13561fdd61c0228a32b9a5e10593b225851d8920595bJaime Velasco Juan struct stk_camera *dev = usb_get_intfdata(intf); 13571fdd61c0228a32b9a5e10593b225851d8920595bJaime Velasco Juan if (!is_initialised(dev)) 13581fdd61c0228a32b9a5e10593b225851d8920595bJaime Velasco Juan return 0; 13591fdd61c0228a32b9a5e10593b225851d8920595bJaime Velasco Juan unset_initialised(dev); 13601fdd61c0228a32b9a5e10593b225851d8920595bJaime Velasco Juan stk_initialise(dev); 13617b1c8f58fcdbed75903943705ef41816e9648c1bArvydas Sidorenko stk_camera_write_reg(dev, 0x0, 0x49); 13621fdd61c0228a32b9a5e10593b225851d8920595bJaime Velasco Juan stk_setup_format(dev); 13631fdd61c0228a32b9a5e10593b225851d8920595bJaime Velasco Juan if (is_streaming(dev)) 13641fdd61c0228a32b9a5e10593b225851d8920595bJaime Velasco Juan stk_start_stream(dev); 13651fdd61c0228a32b9a5e10593b225851d8920595bJaime Velasco Juan return 0; 13661fdd61c0228a32b9a5e10593b225851d8920595bJaime Velasco Juan} 13671fdd61c0228a32b9a5e10593b225851d8920595bJaime Velasco Juan#endif 13681fdd61c0228a32b9a5e10593b225851d8920595bJaime Velasco Juan 1369ec16dae5453eafd1586f35c4ec1ef854e5a808e0Jaime Velasco Juanstatic struct usb_driver stk_camera_driver = { 1370ec16dae5453eafd1586f35c4ec1ef854e5a808e0Jaime Velasco Juan .name = "stkwebcam", 1371ec16dae5453eafd1586f35c4ec1ef854e5a808e0Jaime Velasco Juan .probe = stk_camera_probe, 1372ec16dae5453eafd1586f35c4ec1ef854e5a808e0Jaime Velasco Juan .disconnect = stk_camera_disconnect, 1373ec16dae5453eafd1586f35c4ec1ef854e5a808e0Jaime Velasco Juan .id_table = stkwebcam_table, 13741fdd61c0228a32b9a5e10593b225851d8920595bJaime Velasco Juan#ifdef CONFIG_PM 13751fdd61c0228a32b9a5e10593b225851d8920595bJaime Velasco Juan .suspend = stk_camera_suspend, 13761fdd61c0228a32b9a5e10593b225851d8920595bJaime Velasco Juan .resume = stk_camera_resume, 13771fdd61c0228a32b9a5e10593b225851d8920595bJaime Velasco Juan#endif 1378ec16dae5453eafd1586f35c4ec1ef854e5a808e0Jaime Velasco Juan}; 1379ec16dae5453eafd1586f35c4ec1ef854e5a808e0Jaime Velasco Juan 1380ecb3b2b35db49778b6d89e3ffd0c400776c20735Greg Kroah-Hartmanmodule_usb_driver(stk_camera_driver); 1381