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