blob: 308fa419ae04d37d8cb0a34aa0898d4080222f7c [file] [log] [blame]
Linus Torvalds1da177e2005-04-16 15:20:36 -07001/*
Ralf Baechled203a7e2005-09-06 15:19:37 -07002 * Driver for the VINO (Video In No Out) system found in SGI Indys.
Linus Torvalds1da177e2005-04-16 15:20:36 -07003 *
4 * This file is subject to the terms and conditions of the GNU General Public
5 * License version 2 as published by the Free Software Foundation.
6 *
Ralf Baechled203a7e2005-09-06 15:19:37 -07007 * Copyright (C) 2004,2005 Mikael Nousiainen <tmnousia@cc.hut.fi>
8 *
9 * Based on the previous version of the driver for 2.4 kernels by:
Linus Torvalds1da177e2005-04-16 15:20:36 -070010 * Copyright (C) 2003 Ladislav Michl <ladis@linux-mips.org>
11 */
12
Ralf Baechled203a7e2005-09-06 15:19:37 -070013/*
14 * TODO:
Ladislav Michla637a112005-09-01 15:07:34 +000015 * - remove "mark pages reserved-hacks" from memory allocation code
Nick Piggin3c18ddd2008-04-28 02:12:10 -070016 * and implement fault()
Ralf Baechled203a7e2005-09-06 15:19:37 -070017 * - check decimation, calculating and reporting image size when
18 * using decimation
Ladislav Michla637a112005-09-01 15:07:34 +000019 * - implement read(), user mode buffers and overlay (?)
Ralf Baechled203a7e2005-09-06 15:19:37 -070020 */
21
Linus Torvalds1da177e2005-04-16 15:20:36 -070022#include <linux/init.h>
Ralf Baechled203a7e2005-09-06 15:19:37 -070023#include <linux/module.h>
Linus Torvalds1da177e2005-04-16 15:20:36 -070024#include <linux/delay.h>
Ladislav Michl495515b2005-09-23 10:52:27 +000025#include <linux/dma-mapping.h>
Ralf Baechled203a7e2005-09-06 15:19:37 -070026#include <linux/errno.h>
27#include <linux/fs.h>
Ladislav Michl495515b2005-09-23 10:52:27 +000028#include <linux/interrupt.h>
Ralf Baechled203a7e2005-09-06 15:19:37 -070029#include <linux/kernel.h>
30#include <linux/mm.h>
Ladislav Michl495515b2005-09-23 10:52:27 +000031#include <linux/time.h>
32#include <linux/version.h>
Ralf Baechled203a7e2005-09-06 15:19:37 -070033#include <linux/kmod.h>
Ralf Baechled203a7e2005-09-06 15:19:37 -070034
Linus Torvalds1da177e2005-04-16 15:20:36 -070035#include <linux/i2c.h>
36#include <linux/i2c-algo-sgi.h>
37
Hans Verkuil33b687c2008-07-25 05:32:50 -030038#include <linux/videodev2.h>
Hans Verkuil28959632009-02-18 18:53:47 -030039#include <media/v4l2-device.h>
Yoichi Yuasac2cfcf72008-07-29 05:30:58 -030040#include <media/v4l2-ioctl.h>
Ingo Molnar3593cab2006-02-07 06:49:14 -020041#include <linux/mutex.h>
Ralf Baechled203a7e2005-09-06 15:19:37 -070042
Linus Torvalds1da177e2005-04-16 15:20:36 -070043#include <asm/paccess.h>
44#include <asm/io.h>
45#include <asm/sgi/ip22.h>
Linus Torvalds1da177e2005-04-16 15:20:36 -070046#include <asm/sgi/mc.h>
47
48#include "vino.h"
Ralf Baechled203a7e2005-09-06 15:19:37 -070049#include "saa7191.h"
50#include "indycam.h"
Linus Torvalds1da177e2005-04-16 15:20:36 -070051
Ralf Baechled203a7e2005-09-06 15:19:37 -070052/* Uncomment the following line to get lots and lots of (mostly useless)
53 * debug info.
54 * Note that the debug output also slows down the driver significantly */
55// #define VINO_DEBUG
Ladislav Michla637a112005-09-01 15:07:34 +000056// #define VINO_DEBUG_INT
Ralf Baechled203a7e2005-09-06 15:19:37 -070057
Ladislav Michla637a112005-09-01 15:07:34 +000058#define VINO_MODULE_VERSION "0.0.5"
59#define VINO_VERSION_CODE KERNEL_VERSION(0, 0, 5)
Ralf Baechled203a7e2005-09-06 15:19:37 -070060
61MODULE_DESCRIPTION("SGI VINO Video4Linux2 driver");
62MODULE_VERSION(VINO_MODULE_VERSION);
63MODULE_AUTHOR("Mikael Nousiainen <tmnousia@cc.hut.fi>");
64MODULE_LICENSE("GPL");
65
Ralf Baechled203a7e2005-09-06 15:19:37 -070066#ifdef VINO_DEBUG
67#define dprintk(x...) printk("VINO: " x);
Linus Torvalds1da177e2005-04-16 15:20:36 -070068#else
Ralf Baechled203a7e2005-09-06 15:19:37 -070069#define dprintk(x...)
Linus Torvalds1da177e2005-04-16 15:20:36 -070070#endif
71
Ralf Baechled203a7e2005-09-06 15:19:37 -070072#define VINO_NO_CHANNEL 0
73#define VINO_CHANNEL_A 1
74#define VINO_CHANNEL_B 2
Linus Torvalds1da177e2005-04-16 15:20:36 -070075
Ralf Baechled203a7e2005-09-06 15:19:37 -070076#define VINO_PAL_WIDTH 768
77#define VINO_PAL_HEIGHT 576
78#define VINO_NTSC_WIDTH 640
79#define VINO_NTSC_HEIGHT 480
Linus Torvalds1da177e2005-04-16 15:20:36 -070080
Ralf Baechled203a7e2005-09-06 15:19:37 -070081#define VINO_MIN_WIDTH 32
82#define VINO_MIN_HEIGHT 32
Linus Torvalds1da177e2005-04-16 15:20:36 -070083
Ralf Baechled203a7e2005-09-06 15:19:37 -070084#define VINO_CLIPPING_START_ODD_D1 1
Ladislav Michla637a112005-09-01 15:07:34 +000085#define VINO_CLIPPING_START_ODD_PAL 15
86#define VINO_CLIPPING_START_ODD_NTSC 12
Ralf Baechled203a7e2005-09-06 15:19:37 -070087
88#define VINO_CLIPPING_START_EVEN_D1 2
Ladislav Michla637a112005-09-01 15:07:34 +000089#define VINO_CLIPPING_START_EVEN_PAL 15
90#define VINO_CLIPPING_START_EVEN_NTSC 12
Ralf Baechled203a7e2005-09-06 15:19:37 -070091
92#define VINO_INPUT_CHANNEL_COUNT 3
93
Ladislav Michla637a112005-09-01 15:07:34 +000094/* the number is the index for vino_inputs */
Ralf Baechled203a7e2005-09-06 15:19:37 -070095#define VINO_INPUT_NONE -1
96#define VINO_INPUT_COMPOSITE 0
97#define VINO_INPUT_SVIDEO 1
98#define VINO_INPUT_D1 2
99
100#define VINO_PAGE_RATIO (PAGE_SIZE / VINO_PAGE_SIZE)
101
Ladislav Michla637a112005-09-01 15:07:34 +0000102#define VINO_FIFO_THRESHOLD_DEFAULT 16
Ralf Baechled203a7e2005-09-06 15:19:37 -0700103
Ralf Baechled203a7e2005-09-06 15:19:37 -0700104#define VINO_FRAMEBUFFER_SIZE ((VINO_PAL_WIDTH \
105 * VINO_PAL_HEIGHT * 4 \
106 + 3 * PAGE_SIZE) & ~(PAGE_SIZE - 1))
107
Ladislav Michla637a112005-09-01 15:07:34 +0000108#define VINO_FRAMEBUFFER_COUNT_MAX 8
Ralf Baechled203a7e2005-09-06 15:19:37 -0700109
110#define VINO_FRAMEBUFFER_UNUSED 0
111#define VINO_FRAMEBUFFER_IN_USE 1
112#define VINO_FRAMEBUFFER_READY 2
113
114#define VINO_QUEUE_ERROR -1
115#define VINO_QUEUE_MAGIC 0x20050125
116
117#define VINO_MEMORY_NONE 0
118#define VINO_MEMORY_MMAP 1
119#define VINO_MEMORY_USERPTR 2
120
121#define VINO_DUMMY_DESC_COUNT 4
122#define VINO_DESC_FETCH_DELAY 5 /* microseconds */
123
Ladislav Michla637a112005-09-01 15:07:34 +0000124#define VINO_MAX_FRAME_SKIP_COUNT 128
125
Ralf Baechled203a7e2005-09-06 15:19:37 -0700126/* the number is the index for vino_data_formats */
127#define VINO_DATA_FMT_NONE -1
128#define VINO_DATA_FMT_GREY 0
129#define VINO_DATA_FMT_RGB332 1
130#define VINO_DATA_FMT_RGB32 2
131#define VINO_DATA_FMT_YUV 3
Ralf Baechled203a7e2005-09-06 15:19:37 -0700132
133#define VINO_DATA_FMT_COUNT 4
134
Ladislav Michla637a112005-09-01 15:07:34 +0000135/* the number is the index for vino_data_norms */
Ralf Baechled203a7e2005-09-06 15:19:37 -0700136#define VINO_DATA_NORM_NONE -1
137#define VINO_DATA_NORM_NTSC 0
138#define VINO_DATA_NORM_PAL 1
139#define VINO_DATA_NORM_SECAM 2
140#define VINO_DATA_NORM_D1 3
Ralf Baechled203a7e2005-09-06 15:19:37 -0700141
142#define VINO_DATA_NORM_COUNT 4
143
144/* Internal data structure definitions */
145
146struct vino_input {
147 char *name;
148 v4l2_std_id std;
149};
150
151struct vino_clipping {
152 unsigned int left, right, top, bottom;
153};
154
155struct vino_data_format {
156 /* the description */
157 char *description;
158 /* bytes per pixel */
159 unsigned int bpp;
160 /* V4L2 fourcc code */
161 __u32 pixelformat;
162 /* V4L2 colorspace (duh!) */
163 enum v4l2_colorspace colorspace;
164};
165
166struct vino_data_norm {
167 char *description;
168 unsigned int width, height;
169 struct vino_clipping odd;
170 struct vino_clipping even;
171
172 v4l2_std_id std;
173 unsigned int fps_min, fps_max;
174 __u32 framelines;
175};
176
177struct vino_descriptor_table {
178 /* the number of PAGE_SIZE sized pages in the buffer */
179 unsigned int page_count;
180 /* virtual (kmalloc'd) pointers to the actual data
181 * (in PAGE_SIZE chunks, used with mmap streaming) */
182 unsigned long *virtual;
183
184 /* cpu address for the VINO descriptor table
185 * (contains DMA addresses, VINO_PAGE_SIZE chunks) */
186 unsigned long *dma_cpu;
187 /* dma address for the VINO descriptor table
188 * (contains DMA addresses, VINO_PAGE_SIZE chunks) */
189 dma_addr_t dma;
190};
191
192struct vino_framebuffer {
193 /* identifier nubmer */
194 unsigned int id;
195 /* the length of the whole buffer */
196 unsigned int size;
197 /* the length of actual data in buffer */
198 unsigned int data_size;
199 /* the data format */
200 unsigned int data_format;
201 /* the state of buffer data */
202 unsigned int state;
203 /* is the buffer mapped in user space? */
204 unsigned int map_count;
205 /* memory offset for mmap() */
206 unsigned int offset;
207 /* frame counter */
208 unsigned int frame_counter;
209 /* timestamp (written when image capture finishes) */
210 struct timeval timestamp;
211
212 struct vino_descriptor_table desc_table;
213
214 spinlock_t state_lock;
215};
216
217struct vino_framebuffer_fifo {
218 unsigned int length;
219
220 unsigned int used;
221 unsigned int head;
222 unsigned int tail;
223
Ladislav Michla637a112005-09-01 15:07:34 +0000224 unsigned int data[VINO_FRAMEBUFFER_COUNT_MAX];
Ralf Baechled203a7e2005-09-06 15:19:37 -0700225};
226
227struct vino_framebuffer_queue {
228 unsigned int magic;
229
230 /* VINO_MEMORY_NONE, VINO_MEMORY_MMAP or VINO_MEMORY_USERPTR */
231 unsigned int type;
232 unsigned int length;
233
234 /* data field of in and out contain index numbers for buffer */
235 struct vino_framebuffer_fifo in;
236 struct vino_framebuffer_fifo out;
237
Ladislav Michla637a112005-09-01 15:07:34 +0000238 struct vino_framebuffer *buffer[VINO_FRAMEBUFFER_COUNT_MAX];
Ralf Baechled203a7e2005-09-06 15:19:37 -0700239
240 spinlock_t queue_lock;
Ingo Molnar3593cab2006-02-07 06:49:14 -0200241 struct mutex queue_mutex;
Ralf Baechled203a7e2005-09-06 15:19:37 -0700242 wait_queue_head_t frame_wait_queue;
243};
244
Ladislav Michla637a112005-09-01 15:07:34 +0000245struct vino_interrupt_data {
246 struct timeval timestamp;
247 unsigned int frame_counter;
248 unsigned int skip_count;
249 unsigned int skip;
250};
251
Ralf Baechled203a7e2005-09-06 15:19:37 -0700252struct vino_channel_settings {
253 unsigned int channel;
254
255 int input;
256 unsigned int data_format;
257 unsigned int data_norm;
258 struct vino_clipping clipping;
259 unsigned int decimation;
260 unsigned int line_size;
261 unsigned int alpha;
262 unsigned int fps;
263 unsigned int framert_reg;
264
265 unsigned int fifo_threshold;
266
267 struct vino_framebuffer_queue fb_queue;
268
269 /* number of the current field */
270 unsigned int field;
271
272 /* read in progress */
273 int reading;
274 /* streaming is active */
275 int streaming;
276 /* the driver is currently processing the queue */
277 int capturing;
278
Ingo Molnar3593cab2006-02-07 06:49:14 -0200279 struct mutex mutex;
Ralf Baechled203a7e2005-09-06 15:19:37 -0700280 spinlock_t capture_lock;
281
282 unsigned int users;
283
Ladislav Michla637a112005-09-01 15:07:34 +0000284 struct vino_interrupt_data int_data;
285
Ralf Baechled203a7e2005-09-06 15:19:37 -0700286 /* V4L support */
Hans Verkuil0ef4dba2009-02-12 11:31:13 -0300287 struct video_device *vdev;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700288};
289
290struct vino_client {
Ralf Baechled203a7e2005-09-06 15:19:37 -0700291 /* the channel which owns this client:
292 * VINO_NO_CHANNEL, VINO_CHANNEL_A or VINO_CHANNEL_B */
293 unsigned int owner;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700294 struct i2c_client *driver;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700295};
296
Ralf Baechled203a7e2005-09-06 15:19:37 -0700297struct vino_settings {
Hans Verkuil28959632009-02-18 18:53:47 -0300298 struct v4l2_device v4l2_dev;
Ralf Baechled203a7e2005-09-06 15:19:37 -0700299 struct vino_channel_settings a;
300 struct vino_channel_settings b;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700301
302 struct vino_client decoder;
303 struct vino_client camera;
304
Ralf Baechled203a7e2005-09-06 15:19:37 -0700305 /* a lock for vino register access */
306 spinlock_t vino_lock;
307 /* a lock for channel input changes */
308 spinlock_t input_lock;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700309
Linus Torvalds1da177e2005-04-16 15:20:36 -0700310 unsigned long dummy_page;
Ralf Baechled203a7e2005-09-06 15:19:37 -0700311 struct vino_descriptor_table dummy_desc_table;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700312};
313
Ralf Baechled203a7e2005-09-06 15:19:37 -0700314/* Module parameters */
315
316/*
Ladislav Michla637a112005-09-01 15:07:34 +0000317 * Using vino_pixel_conversion the ABGR32-format pixels supplied
Ralf Baechled203a7e2005-09-06 15:19:37 -0700318 * by the VINO chip can be converted to more common formats
319 * like RGBA32 (or probably RGB24 in the future). This way we
320 * can give out data that can be specified correctly with
321 * the V4L2-definitions.
322 *
323 * The pixel format is specified as RGBA32 when no conversion
324 * is used.
325 *
326 * Note that this only affects the 32-bit bit depth.
327 *
328 * Use non-zero value to enable conversion.
329 */
Douglas Schilling Landgrafff699e62008-04-22 14:41:48 -0300330static int vino_pixel_conversion;
Ladislav Michla637a112005-09-01 15:07:34 +0000331
Ralf Baechled203a7e2005-09-06 15:19:37 -0700332module_param_named(pixelconv, vino_pixel_conversion, int, 0);
Ladislav Michla637a112005-09-01 15:07:34 +0000333
Ralf Baechled203a7e2005-09-06 15:19:37 -0700334MODULE_PARM_DESC(pixelconv,
335 "enable pixel conversion (non-zero value enables)");
336
337/* Internal data structures */
338
339static struct sgi_vino *vino;
340
341static struct vino_settings *vino_drvdata;
342
343static const char *vino_driver_name = "vino";
344static const char *vino_driver_description = "SGI VINO";
345static const char *vino_bus_name = "GIO64 bus";
Hans Verkuil0ef4dba2009-02-12 11:31:13 -0300346static const char *vino_vdev_name_a = "SGI VINO Channel A";
347static const char *vino_vdev_name_b = "SGI VINO Channel B";
Ralf Baechled203a7e2005-09-06 15:19:37 -0700348
Ladislav Michla637a112005-09-01 15:07:34 +0000349static void vino_capture_tasklet(unsigned long channel);
350
351DECLARE_TASKLET(vino_tasklet_a, vino_capture_tasklet, VINO_CHANNEL_A);
352DECLARE_TASKLET(vino_tasklet_b, vino_capture_tasklet, VINO_CHANNEL_B);
353
Ralf Baechled203a7e2005-09-06 15:19:37 -0700354static const struct vino_input vino_inputs[] = {
355 {
356 .name = "Composite",
Ladislav Michla637a112005-09-01 15:07:34 +0000357 .std = V4L2_STD_NTSC | V4L2_STD_PAL
358 | V4L2_STD_SECAM,
Hans Verkuilcf4e9482009-02-27 09:05:10 -0300359 }, {
Ralf Baechled203a7e2005-09-06 15:19:37 -0700360 .name = "S-Video",
Ladislav Michla637a112005-09-01 15:07:34 +0000361 .std = V4L2_STD_NTSC | V4L2_STD_PAL
362 | V4L2_STD_SECAM,
Hans Verkuilcf4e9482009-02-27 09:05:10 -0300363 }, {
Ladislav Michla637a112005-09-01 15:07:34 +0000364 .name = "D1/IndyCam",
Ralf Baechled203a7e2005-09-06 15:19:37 -0700365 .std = V4L2_STD_NTSC,
366 }
367};
368
369static const struct vino_data_format vino_data_formats[] = {
370 {
371 .description = "8-bit greyscale",
372 .bpp = 1,
373 .pixelformat = V4L2_PIX_FMT_GREY,
374 .colorspace = V4L2_COLORSPACE_SMPTE170M,
Hans Verkuilcf4e9482009-02-27 09:05:10 -0300375 }, {
Ralf Baechled203a7e2005-09-06 15:19:37 -0700376 .description = "8-bit dithered RGB 3-3-2",
377 .bpp = 1,
378 .pixelformat = V4L2_PIX_FMT_RGB332,
379 .colorspace = V4L2_COLORSPACE_SRGB,
Hans Verkuilcf4e9482009-02-27 09:05:10 -0300380 }, {
Ralf Baechled203a7e2005-09-06 15:19:37 -0700381 .description = "32-bit RGB",
382 .bpp = 4,
383 .pixelformat = V4L2_PIX_FMT_RGB32,
384 .colorspace = V4L2_COLORSPACE_SRGB,
Hans Verkuilcf4e9482009-02-27 09:05:10 -0300385 }, {
Ralf Baechled203a7e2005-09-06 15:19:37 -0700386 .description = "YUV 4:2:2",
Ladislav Michla637a112005-09-01 15:07:34 +0000387 .bpp = 2,
Ralf Baechled203a7e2005-09-06 15:19:37 -0700388 .pixelformat = V4L2_PIX_FMT_YUYV, // XXX: swapped?
389 .colorspace = V4L2_COLORSPACE_SMPTE170M,
Ladislav Michla637a112005-09-01 15:07:34 +0000390 }
Ralf Baechled203a7e2005-09-06 15:19:37 -0700391};
392
393static const struct vino_data_norm vino_data_norms[] = {
394 {
395 .description = "NTSC",
396 .std = V4L2_STD_NTSC,
397 .fps_min = 6,
398 .fps_max = 30,
399 .framelines = 525,
400 .width = VINO_NTSC_WIDTH,
401 .height = VINO_NTSC_HEIGHT,
402 .odd = {
Ladislav Michla637a112005-09-01 15:07:34 +0000403 .top = VINO_CLIPPING_START_ODD_NTSC,
404 .left = 0,
Ralf Baechled203a7e2005-09-06 15:19:37 -0700405 .bottom = VINO_CLIPPING_START_ODD_NTSC
406 + VINO_NTSC_HEIGHT / 2 - 1,
Ladislav Michla637a112005-09-01 15:07:34 +0000407 .right = VINO_NTSC_WIDTH,
Ralf Baechled203a7e2005-09-06 15:19:37 -0700408 },
409 .even = {
Ladislav Michla637a112005-09-01 15:07:34 +0000410 .top = VINO_CLIPPING_START_EVEN_NTSC,
411 .left = 0,
Ralf Baechled203a7e2005-09-06 15:19:37 -0700412 .bottom = VINO_CLIPPING_START_EVEN_NTSC
413 + VINO_NTSC_HEIGHT / 2 - 1,
Ladislav Michla637a112005-09-01 15:07:34 +0000414 .right = VINO_NTSC_WIDTH,
Ralf Baechled203a7e2005-09-06 15:19:37 -0700415 },
Hans Verkuilcf4e9482009-02-27 09:05:10 -0300416 }, {
Ralf Baechled203a7e2005-09-06 15:19:37 -0700417 .description = "PAL",
418 .std = V4L2_STD_PAL,
419 .fps_min = 5,
420 .fps_max = 25,
421 .framelines = 625,
422 .width = VINO_PAL_WIDTH,
423 .height = VINO_PAL_HEIGHT,
424 .odd = {
Ladislav Michla637a112005-09-01 15:07:34 +0000425 .top = VINO_CLIPPING_START_ODD_PAL,
426 .left = 0,
Ralf Baechled203a7e2005-09-06 15:19:37 -0700427 .bottom = VINO_CLIPPING_START_ODD_PAL
428 + VINO_PAL_HEIGHT / 2 - 1,
Ladislav Michla637a112005-09-01 15:07:34 +0000429 .right = VINO_PAL_WIDTH,
Ralf Baechled203a7e2005-09-06 15:19:37 -0700430 },
431 .even = {
Ladislav Michla637a112005-09-01 15:07:34 +0000432 .top = VINO_CLIPPING_START_EVEN_PAL,
433 .left = 0,
Ralf Baechled203a7e2005-09-06 15:19:37 -0700434 .bottom = VINO_CLIPPING_START_EVEN_PAL
435 + VINO_PAL_HEIGHT / 2 - 1,
Ladislav Michla637a112005-09-01 15:07:34 +0000436 .right = VINO_PAL_WIDTH,
Ralf Baechled203a7e2005-09-06 15:19:37 -0700437 },
Hans Verkuilcf4e9482009-02-27 09:05:10 -0300438 }, {
Ralf Baechled203a7e2005-09-06 15:19:37 -0700439 .description = "SECAM",
440 .std = V4L2_STD_SECAM,
441 .fps_min = 5,
442 .fps_max = 25,
443 .framelines = 625,
444 .width = VINO_PAL_WIDTH,
445 .height = VINO_PAL_HEIGHT,
446 .odd = {
Ladislav Michla637a112005-09-01 15:07:34 +0000447 .top = VINO_CLIPPING_START_ODD_PAL,
448 .left = 0,
Ralf Baechled203a7e2005-09-06 15:19:37 -0700449 .bottom = VINO_CLIPPING_START_ODD_PAL
450 + VINO_PAL_HEIGHT / 2 - 1,
Ladislav Michla637a112005-09-01 15:07:34 +0000451 .right = VINO_PAL_WIDTH,
Ralf Baechled203a7e2005-09-06 15:19:37 -0700452 },
453 .even = {
Ladislav Michla637a112005-09-01 15:07:34 +0000454 .top = VINO_CLIPPING_START_EVEN_PAL,
455 .left = 0,
Ralf Baechled203a7e2005-09-06 15:19:37 -0700456 .bottom = VINO_CLIPPING_START_EVEN_PAL
457 + VINO_PAL_HEIGHT / 2 - 1,
Ladislav Michla637a112005-09-01 15:07:34 +0000458 .right = VINO_PAL_WIDTH,
Ralf Baechled203a7e2005-09-06 15:19:37 -0700459 },
Hans Verkuilcf4e9482009-02-27 09:05:10 -0300460 }, {
Ladislav Michla637a112005-09-01 15:07:34 +0000461 .description = "NTSC/D1",
Ralf Baechled203a7e2005-09-06 15:19:37 -0700462 .std = V4L2_STD_NTSC,
463 .fps_min = 6,
464 .fps_max = 30,
465 .framelines = 525,
466 .width = VINO_NTSC_WIDTH,
467 .height = VINO_NTSC_HEIGHT,
468 .odd = {
Ladislav Michla637a112005-09-01 15:07:34 +0000469 .top = VINO_CLIPPING_START_ODD_D1,
470 .left = 0,
Ralf Baechled203a7e2005-09-06 15:19:37 -0700471 .bottom = VINO_CLIPPING_START_ODD_D1
472 + VINO_NTSC_HEIGHT / 2 - 1,
Ladislav Michla637a112005-09-01 15:07:34 +0000473 .right = VINO_NTSC_WIDTH,
Ralf Baechled203a7e2005-09-06 15:19:37 -0700474 },
475 .even = {
Ladislav Michla637a112005-09-01 15:07:34 +0000476 .top = VINO_CLIPPING_START_EVEN_D1,
477 .left = 0,
Ralf Baechled203a7e2005-09-06 15:19:37 -0700478 .bottom = VINO_CLIPPING_START_EVEN_D1
479 + VINO_NTSC_HEIGHT / 2 - 1,
Ladislav Michla637a112005-09-01 15:07:34 +0000480 .right = VINO_NTSC_WIDTH,
Ralf Baechled203a7e2005-09-06 15:19:37 -0700481 },
482 }
483};
484
485#define VINO_INDYCAM_V4L2_CONTROL_COUNT 9
486
487struct v4l2_queryctrl vino_indycam_v4l2_controls[] = {
488 {
489 .id = V4L2_CID_AUTOGAIN,
490 .type = V4L2_CTRL_TYPE_BOOLEAN,
491 .name = "Automatic Gain Control",
492 .minimum = 0,
493 .maximum = 1,
494 .step = 1,
495 .default_value = INDYCAM_AGC_DEFAULT,
Hans Verkuilcf4e9482009-02-27 09:05:10 -0300496 }, {
Ralf Baechled203a7e2005-09-06 15:19:37 -0700497 .id = V4L2_CID_AUTO_WHITE_BALANCE,
498 .type = V4L2_CTRL_TYPE_BOOLEAN,
499 .name = "Automatic White Balance",
500 .minimum = 0,
501 .maximum = 1,
502 .step = 1,
503 .default_value = INDYCAM_AWB_DEFAULT,
Hans Verkuilcf4e9482009-02-27 09:05:10 -0300504 }, {
Ralf Baechled203a7e2005-09-06 15:19:37 -0700505 .id = V4L2_CID_GAIN,
506 .type = V4L2_CTRL_TYPE_INTEGER,
507 .name = "Gain",
508 .minimum = INDYCAM_GAIN_MIN,
509 .maximum = INDYCAM_GAIN_MAX,
510 .step = 1,
511 .default_value = INDYCAM_GAIN_DEFAULT,
Hans Verkuilcf4e9482009-02-27 09:05:10 -0300512 }, {
513 .id = INDYCAM_CONTROL_RED_SATURATION,
Ralf Baechled203a7e2005-09-06 15:19:37 -0700514 .type = V4L2_CTRL_TYPE_INTEGER,
515 .name = "Red Saturation",
516 .minimum = INDYCAM_RED_SATURATION_MIN,
517 .maximum = INDYCAM_RED_SATURATION_MAX,
518 .step = 1,
519 .default_value = INDYCAM_RED_SATURATION_DEFAULT,
Hans Verkuilcf4e9482009-02-27 09:05:10 -0300520 }, {
521 .id = INDYCAM_CONTROL_BLUE_SATURATION,
Ralf Baechled203a7e2005-09-06 15:19:37 -0700522 .type = V4L2_CTRL_TYPE_INTEGER,
523 .name = "Blue Saturation",
524 .minimum = INDYCAM_BLUE_SATURATION_MIN,
525 .maximum = INDYCAM_BLUE_SATURATION_MAX,
526 .step = 1,
527 .default_value = INDYCAM_BLUE_SATURATION_DEFAULT,
Hans Verkuilcf4e9482009-02-27 09:05:10 -0300528 }, {
Ralf Baechled203a7e2005-09-06 15:19:37 -0700529 .id = V4L2_CID_RED_BALANCE,
530 .type = V4L2_CTRL_TYPE_INTEGER,
531 .name = "Red Balance",
532 .minimum = INDYCAM_RED_BALANCE_MIN,
533 .maximum = INDYCAM_RED_BALANCE_MAX,
534 .step = 1,
535 .default_value = INDYCAM_RED_BALANCE_DEFAULT,
Hans Verkuilcf4e9482009-02-27 09:05:10 -0300536 }, {
Ralf Baechled203a7e2005-09-06 15:19:37 -0700537 .id = V4L2_CID_BLUE_BALANCE,
538 .type = V4L2_CTRL_TYPE_INTEGER,
539 .name = "Blue Balance",
540 .minimum = INDYCAM_BLUE_BALANCE_MIN,
541 .maximum = INDYCAM_BLUE_BALANCE_MAX,
542 .step = 1,
543 .default_value = INDYCAM_BLUE_BALANCE_DEFAULT,
Hans Verkuilcf4e9482009-02-27 09:05:10 -0300544 }, {
Ralf Baechled203a7e2005-09-06 15:19:37 -0700545 .id = V4L2_CID_EXPOSURE,
546 .type = V4L2_CTRL_TYPE_INTEGER,
547 .name = "Shutter Control",
548 .minimum = INDYCAM_SHUTTER_MIN,
549 .maximum = INDYCAM_SHUTTER_MAX,
550 .step = 1,
551 .default_value = INDYCAM_SHUTTER_DEFAULT,
Hans Verkuilcf4e9482009-02-27 09:05:10 -0300552 }, {
Ralf Baechled203a7e2005-09-06 15:19:37 -0700553 .id = V4L2_CID_GAMMA,
554 .type = V4L2_CTRL_TYPE_INTEGER,
555 .name = "Gamma",
556 .minimum = INDYCAM_GAMMA_MIN,
557 .maximum = INDYCAM_GAMMA_MAX,
558 .step = 1,
559 .default_value = INDYCAM_GAMMA_DEFAULT,
Ralf Baechled203a7e2005-09-06 15:19:37 -0700560 }
561};
562
Ladislav Michla637a112005-09-01 15:07:34 +0000563#define VINO_SAA7191_V4L2_CONTROL_COUNT 9
Ralf Baechled203a7e2005-09-06 15:19:37 -0700564
565struct v4l2_queryctrl vino_saa7191_v4l2_controls[] = {
566 {
567 .id = V4L2_CID_HUE,
568 .type = V4L2_CTRL_TYPE_INTEGER,
569 .name = "Hue",
570 .minimum = SAA7191_HUE_MIN,
571 .maximum = SAA7191_HUE_MAX,
572 .step = 1,
573 .default_value = SAA7191_HUE_DEFAULT,
Hans Verkuilcf4e9482009-02-27 09:05:10 -0300574 }, {
575 .id = SAA7191_CONTROL_BANDPASS,
Ladislav Michla637a112005-09-01 15:07:34 +0000576 .type = V4L2_CTRL_TYPE_INTEGER,
577 .name = "Luminance Bandpass",
578 .minimum = SAA7191_BANDPASS_MIN,
579 .maximum = SAA7191_BANDPASS_MAX,
580 .step = 1,
581 .default_value = SAA7191_BANDPASS_DEFAULT,
Hans Verkuilcf4e9482009-02-27 09:05:10 -0300582 }, {
583 .id = SAA7191_CONTROL_BANDPASS_WEIGHT,
Ladislav Michla637a112005-09-01 15:07:34 +0000584 .type = V4L2_CTRL_TYPE_INTEGER,
585 .name = "Luminance Bandpass Weight",
586 .minimum = SAA7191_BANDPASS_WEIGHT_MIN,
587 .maximum = SAA7191_BANDPASS_WEIGHT_MAX,
588 .step = 1,
589 .default_value = SAA7191_BANDPASS_WEIGHT_DEFAULT,
Hans Verkuilcf4e9482009-02-27 09:05:10 -0300590 }, {
591 .id = SAA7191_CONTROL_CORING,
Ladislav Michla637a112005-09-01 15:07:34 +0000592 .type = V4L2_CTRL_TYPE_INTEGER,
593 .name = "HF Luminance Coring",
594 .minimum = SAA7191_CORING_MIN,
595 .maximum = SAA7191_CORING_MAX,
596 .step = 1,
597 .default_value = SAA7191_CORING_DEFAULT,
Hans Verkuilcf4e9482009-02-27 09:05:10 -0300598 }, {
599 .id = SAA7191_CONTROL_FORCE_COLOUR,
Ladislav Michla637a112005-09-01 15:07:34 +0000600 .type = V4L2_CTRL_TYPE_BOOLEAN,
601 .name = "Force Colour",
602 .minimum = SAA7191_FORCE_COLOUR_MIN,
603 .maximum = SAA7191_FORCE_COLOUR_MAX,
604 .step = 1,
605 .default_value = SAA7191_FORCE_COLOUR_DEFAULT,
Hans Verkuilcf4e9482009-02-27 09:05:10 -0300606 }, {
607 .id = SAA7191_CONTROL_CHROMA_GAIN,
Ladislav Michla637a112005-09-01 15:07:34 +0000608 .type = V4L2_CTRL_TYPE_INTEGER,
609 .name = "Chrominance Gain Control",
610 .minimum = SAA7191_CHROMA_GAIN_MIN,
611 .maximum = SAA7191_CHROMA_GAIN_MAX,
612 .step = 1,
613 .default_value = SAA7191_CHROMA_GAIN_DEFAULT,
Hans Verkuilcf4e9482009-02-27 09:05:10 -0300614 }, {
615 .id = SAA7191_CONTROL_VTRC,
Ralf Baechled203a7e2005-09-06 15:19:37 -0700616 .type = V4L2_CTRL_TYPE_BOOLEAN,
617 .name = "VTR Time Constant",
618 .minimum = SAA7191_VTRC_MIN,
619 .maximum = SAA7191_VTRC_MAX,
620 .step = 1,
621 .default_value = SAA7191_VTRC_DEFAULT,
Hans Verkuilcf4e9482009-02-27 09:05:10 -0300622 }, {
623 .id = SAA7191_CONTROL_LUMA_DELAY,
Ladislav Michla637a112005-09-01 15:07:34 +0000624 .type = V4L2_CTRL_TYPE_INTEGER,
625 .name = "Luminance Delay Compensation",
626 .minimum = SAA7191_LUMA_DELAY_MIN,
627 .maximum = SAA7191_LUMA_DELAY_MAX,
628 .step = 1,
629 .default_value = SAA7191_LUMA_DELAY_DEFAULT,
Hans Verkuilcf4e9482009-02-27 09:05:10 -0300630 }, {
631 .id = SAA7191_CONTROL_VNR,
Ladislav Michla637a112005-09-01 15:07:34 +0000632 .type = V4L2_CTRL_TYPE_INTEGER,
633 .name = "Vertical Noise Reduction",
634 .minimum = SAA7191_VNR_MIN,
635 .maximum = SAA7191_VNR_MAX,
636 .step = 1,
637 .default_value = SAA7191_VNR_DEFAULT,
Ralf Baechled203a7e2005-09-06 15:19:37 -0700638 }
639};
640
641/* VINO I2C bus functions */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700642
643unsigned i2c_vino_getctrl(void *data)
644{
645 return vino->i2c_control;
646}
647
648void i2c_vino_setctrl(void *data, unsigned val)
649{
650 vino->i2c_control = val;
651}
652
653unsigned i2c_vino_rdata(void *data)
654{
655 return vino->i2c_data;
656}
657
658void i2c_vino_wdata(void *data, unsigned val)
659{
660 vino->i2c_data = val;
661}
662
663static struct i2c_algo_sgi_data i2c_sgi_vino_data =
664{
665 .getctrl = &i2c_vino_getctrl,
666 .setctrl = &i2c_vino_setctrl,
667 .rdata = &i2c_vino_rdata,
668 .wdata = &i2c_vino_wdata,
669 .xfer_timeout = 200,
670 .ack_timeout = 1000,
671};
672
673/*
674 * There are two possible clients on VINO I2C bus, so we limit usage only
675 * to them.
676 */
677static int i2c_vino_client_reg(struct i2c_client *client)
678{
Ladislav Michla637a112005-09-01 15:07:34 +0000679 unsigned long flags;
Ralf Baechled203a7e2005-09-06 15:19:37 -0700680 int ret = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700681
Ladislav Michla637a112005-09-01 15:07:34 +0000682 spin_lock_irqsave(&vino_drvdata->input_lock, flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700683 switch (client->driver->id) {
684 case I2C_DRIVERID_SAA7191:
Ralf Baechled203a7e2005-09-06 15:19:37 -0700685 if (vino_drvdata->decoder.driver)
686 ret = -EBUSY;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700687 else
Ralf Baechled203a7e2005-09-06 15:19:37 -0700688 vino_drvdata->decoder.driver = client;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700689 break;
690 case I2C_DRIVERID_INDYCAM:
Ralf Baechled203a7e2005-09-06 15:19:37 -0700691 if (vino_drvdata->camera.driver)
692 ret = -EBUSY;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700693 else
Ralf Baechled203a7e2005-09-06 15:19:37 -0700694 vino_drvdata->camera.driver = client;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700695 break;
696 default:
Ralf Baechled203a7e2005-09-06 15:19:37 -0700697 ret = -ENODEV;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700698 }
Ladislav Michla637a112005-09-01 15:07:34 +0000699 spin_unlock_irqrestore(&vino_drvdata->input_lock, flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700700
Ralf Baechled203a7e2005-09-06 15:19:37 -0700701 return ret;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700702}
703
704static int i2c_vino_client_unreg(struct i2c_client *client)
705{
Ladislav Michla637a112005-09-01 15:07:34 +0000706 unsigned long flags;
Ralf Baechled203a7e2005-09-06 15:19:37 -0700707 int ret = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700708
Ladislav Michla637a112005-09-01 15:07:34 +0000709 spin_lock_irqsave(&vino_drvdata->input_lock, flags);
Ralf Baechled203a7e2005-09-06 15:19:37 -0700710 if (client == vino_drvdata->decoder.driver) {
711 if (vino_drvdata->decoder.owner != VINO_NO_CHANNEL)
712 ret = -EBUSY;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700713 else
Ralf Baechled203a7e2005-09-06 15:19:37 -0700714 vino_drvdata->decoder.driver = NULL;
715 } else if (client == vino_drvdata->camera.driver) {
716 if (vino_drvdata->camera.owner != VINO_NO_CHANNEL)
717 ret = -EBUSY;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700718 else
Ralf Baechled203a7e2005-09-06 15:19:37 -0700719 vino_drvdata->camera.driver = NULL;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700720 }
Ladislav Michla637a112005-09-01 15:07:34 +0000721 spin_unlock_irqrestore(&vino_drvdata->input_lock, flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700722
Ralf Baechled203a7e2005-09-06 15:19:37 -0700723 return ret;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700724}
725
726static struct i2c_adapter vino_i2c_adapter =
727{
728 .name = "VINO I2C bus",
729 .id = I2C_HW_SGI_VINO,
730 .algo_data = &i2c_sgi_vino_data,
731 .client_register = &i2c_vino_client_reg,
732 .client_unregister = &i2c_vino_client_unreg,
733};
734
735static int vino_i2c_add_bus(void)
736{
737 return i2c_sgi_add_bus(&vino_i2c_adapter);
738}
739
740static int vino_i2c_del_bus(void)
741{
Jean Delvare32697112006-12-10 21:21:33 +0100742 return i2c_del_adapter(&vino_i2c_adapter);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700743}
744
Ralf Baechled203a7e2005-09-06 15:19:37 -0700745static int i2c_camera_command(unsigned int cmd, void *arg)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700746{
Ralf Baechled203a7e2005-09-06 15:19:37 -0700747 return vino_drvdata->camera.driver->
748 driver->command(vino_drvdata->camera.driver,
749 cmd, arg);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700750}
751
Ralf Baechled203a7e2005-09-06 15:19:37 -0700752static int i2c_decoder_command(unsigned int cmd, void *arg)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700753{
Ralf Baechled203a7e2005-09-06 15:19:37 -0700754 return vino_drvdata->decoder.driver->
755 driver->command(vino_drvdata->decoder.driver,
756 cmd, arg);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700757}
758
Ralf Baechled203a7e2005-09-06 15:19:37 -0700759/* VINO framebuffer/DMA descriptor management */
760
761static void vino_free_buffer_with_count(struct vino_framebuffer *fb,
762 unsigned int count)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700763{
Ralf Baechled203a7e2005-09-06 15:19:37 -0700764 unsigned int i;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700765
Ralf Baechled203a7e2005-09-06 15:19:37 -0700766 dprintk("vino_free_buffer_with_count(): count = %d\n", count);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700767
Ralf Baechled203a7e2005-09-06 15:19:37 -0700768 for (i = 0; i < count; i++) {
Hans Verkuileda9e4e2008-08-22 17:12:08 -0300769 ClearPageReserved(virt_to_page((void *)fb->desc_table.virtual[i]));
Ralf Baechled203a7e2005-09-06 15:19:37 -0700770 dma_unmap_single(NULL,
771 fb->desc_table.dma_cpu[VINO_PAGE_RATIO * i],
772 PAGE_SIZE, DMA_FROM_DEVICE);
773 free_page(fb->desc_table.virtual[i]);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700774 }
775
Ralf Baechled203a7e2005-09-06 15:19:37 -0700776 dma_free_coherent(NULL,
777 VINO_PAGE_RATIO * (fb->desc_table.page_count + 4) *
778 sizeof(dma_addr_t), (void *)fb->desc_table.dma_cpu,
779 fb->desc_table.dma);
780 kfree(fb->desc_table.virtual);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700781
Ralf Baechled203a7e2005-09-06 15:19:37 -0700782 memset(fb, 0, sizeof(struct vino_framebuffer));
783}
Linus Torvalds1da177e2005-04-16 15:20:36 -0700784
Ralf Baechled203a7e2005-09-06 15:19:37 -0700785static void vino_free_buffer(struct vino_framebuffer *fb)
786{
787 vino_free_buffer_with_count(fb, fb->desc_table.page_count);
788}
789
790static int vino_allocate_buffer(struct vino_framebuffer *fb,
791 unsigned int size)
792{
793 unsigned int count, i, j;
794 int ret = 0;
795
796 dprintk("vino_allocate_buffer():\n");
797
798 if (size < 1)
799 return -EINVAL;
800
801 memset(fb, 0, sizeof(struct vino_framebuffer));
802
803 count = ((size / PAGE_SIZE) + 4) & ~3;
804
805 dprintk("vino_allocate_buffer(): size = %d, count = %d\n",
806 size, count);
807
808 /* allocate memory for table with virtual (page) addresses */
809 fb->desc_table.virtual = (unsigned long *)
810 kmalloc(count * sizeof(unsigned long), GFP_KERNEL);
811 if (!fb->desc_table.virtual)
812 return -ENOMEM;
813
814 /* allocate memory for table with dma addresses
815 * (has space for four extra descriptors) */
816 fb->desc_table.dma_cpu =
817 dma_alloc_coherent(NULL, VINO_PAGE_RATIO * (count + 4) *
818 sizeof(dma_addr_t), &fb->desc_table.dma,
819 GFP_KERNEL | GFP_DMA);
820 if (!fb->desc_table.dma_cpu) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700821 ret = -ENOMEM;
Ralf Baechled203a7e2005-09-06 15:19:37 -0700822 goto out_free_virtual;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700823 }
824
Ralf Baechled203a7e2005-09-06 15:19:37 -0700825 /* allocate pages for the buffer and acquire the according
826 * dma addresses */
827 for (i = 0; i < count; i++) {
828 dma_addr_t dma_data_addr;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700829
Ralf Baechled203a7e2005-09-06 15:19:37 -0700830 fb->desc_table.virtual[i] =
831 get_zeroed_page(GFP_KERNEL | GFP_DMA);
832 if (!fb->desc_table.virtual[i]) {
833 ret = -ENOBUFS;
834 break;
835 }
Linus Torvalds1da177e2005-04-16 15:20:36 -0700836
Ralf Baechled203a7e2005-09-06 15:19:37 -0700837 dma_data_addr =
838 dma_map_single(NULL,
839 (void *)fb->desc_table.virtual[i],
840 PAGE_SIZE, DMA_FROM_DEVICE);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700841
Ralf Baechled203a7e2005-09-06 15:19:37 -0700842 for (j = 0; j < VINO_PAGE_RATIO; j++) {
843 fb->desc_table.dma_cpu[VINO_PAGE_RATIO * i + j] =
844 dma_data_addr + VINO_PAGE_SIZE * j;
845 }
846
Hans Verkuileda9e4e2008-08-22 17:12:08 -0300847 SetPageReserved(virt_to_page((void *)fb->desc_table.virtual[i]));
Linus Torvalds1da177e2005-04-16 15:20:36 -0700848 }
849
Ralf Baechled203a7e2005-09-06 15:19:37 -0700850 /* page_count needs to be set anyway, because the descriptor table has
851 * been allocated according to this number */
852 fb->desc_table.page_count = count;
853
Linus Torvalds1da177e2005-04-16 15:20:36 -0700854 if (ret) {
Ralf Baechled203a7e2005-09-06 15:19:37 -0700855 /* the descriptor with index i doesn't contain
856 * a valid address yet */
857 vino_free_buffer_with_count(fb, i);
858 return ret;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700859 }
860
Ralf Baechled203a7e2005-09-06 15:19:37 -0700861 //fb->size = size;
862 fb->size = count * PAGE_SIZE;
863 fb->data_format = VINO_DATA_FMT_NONE;
864
865 /* set the dma stop-bit for the last (count+1)th descriptor */
866 fb->desc_table.dma_cpu[VINO_PAGE_RATIO * count] = VINO_DESC_STOP;
867 return 0;
868
869 out_free_virtual:
870 kfree(fb->desc_table.virtual);
871 return ret;
872}
873
874#if 0
875/* user buffers not fully implemented yet */
876static int vino_prepare_user_buffer(struct vino_framebuffer *fb,
877 void *user,
878 unsigned int size)
879{
880 unsigned int count, i, j;
881 int ret = 0;
882
883 dprintk("vino_prepare_user_buffer():\n");
884
885 if (size < 1)
886 return -EINVAL;
887
888 memset(fb, 0, sizeof(struct vino_framebuffer));
889
890 count = ((size / PAGE_SIZE)) & ~3;
891
892 dprintk("vino_prepare_user_buffer(): size = %d, count = %d\n",
893 size, count);
894
895 /* allocate memory for table with virtual (page) addresses */
896 fb->desc_table.virtual = (unsigned long *)
897 kmalloc(count * sizeof(unsigned long), GFP_KERNEL);
898 if (!fb->desc_table.virtual)
899 return -ENOMEM;
900
901 /* allocate memory for table with dma addresses
902 * (has space for four extra descriptors) */
903 fb->desc_table.dma_cpu =
904 dma_alloc_coherent(NULL, VINO_PAGE_RATIO * (count + 4) *
905 sizeof(dma_addr_t), &fb->desc_table.dma,
906 GFP_KERNEL | GFP_DMA);
907 if (!fb->desc_table.dma_cpu) {
908 ret = -ENOMEM;
909 goto out_free_virtual;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700910 }
Ralf Baechled203a7e2005-09-06 15:19:37 -0700911
912 /* allocate pages for the buffer and acquire the according
913 * dma addresses */
914 for (i = 0; i < count; i++) {
915 dma_addr_t dma_data_addr;
916
917 fb->desc_table.virtual[i] =
918 get_zeroed_page(GFP_KERNEL | GFP_DMA);
919 if (!fb->desc_table.virtual[i]) {
920 ret = -ENOBUFS;
921 break;
922 }
923
924 dma_data_addr =
925 dma_map_single(NULL,
926 (void *)fb->desc_table.virtual[i],
927 PAGE_SIZE, DMA_FROM_DEVICE);
928
929 for (j = 0; j < VINO_PAGE_RATIO; j++) {
930 fb->desc_table.dma_cpu[VINO_PAGE_RATIO * i + j] =
931 dma_data_addr + VINO_PAGE_SIZE * j;
932 }
933
Hans Verkuileda9e4e2008-08-22 17:12:08 -0300934 SetPageReserved(virt_to_page((void *)fb->desc_table.virtual[i]));
Ralf Baechled203a7e2005-09-06 15:19:37 -0700935 }
936
937 /* page_count needs to be set anyway, because the descriptor table has
938 * been allocated according to this number */
939 fb->desc_table.page_count = count;
940
941 if (ret) {
942 /* the descriptor with index i doesn't contain
943 * a valid address yet */
944 vino_free_buffer_with_count(fb, i);
945 return ret;
946 }
947
948 //fb->size = size;
949 fb->size = count * PAGE_SIZE;
950
951 /* set the dma stop-bit for the last (count+1)th descriptor */
952 fb->desc_table.dma_cpu[VINO_PAGE_RATIO * count] = VINO_DESC_STOP;
953 return 0;
954
955 out_free_virtual:
956 kfree(fb->desc_table.virtual);
957 return ret;
958}
959#endif
960
961static void vino_sync_buffer(struct vino_framebuffer *fb)
962{
963 int i;
964
965 dprintk("vino_sync_buffer():\n");
966
967 for (i = 0; i < fb->desc_table.page_count; i++)
968 dma_sync_single(NULL,
969 fb->desc_table.dma_cpu[VINO_PAGE_RATIO * i],
970 PAGE_SIZE, DMA_FROM_DEVICE);
971}
972
973/* Framebuffer fifo functions (need to be locked externally) */
974
Ladislav Michla637a112005-09-01 15:07:34 +0000975static inline void vino_fifo_init(struct vino_framebuffer_fifo *f,
Ralf Baechled203a7e2005-09-06 15:19:37 -0700976 unsigned int length)
977{
978 f->length = 0;
979 f->used = 0;
980 f->head = 0;
981 f->tail = 0;
982
Ladislav Michla637a112005-09-01 15:07:34 +0000983 if (length > VINO_FRAMEBUFFER_COUNT_MAX)
984 length = VINO_FRAMEBUFFER_COUNT_MAX;
Ralf Baechled203a7e2005-09-06 15:19:37 -0700985
986 f->length = length;
987}
988
989/* returns true/false */
Ladislav Michla637a112005-09-01 15:07:34 +0000990static inline int vino_fifo_has_id(struct vino_framebuffer_fifo *f,
991 unsigned int id)
Ralf Baechled203a7e2005-09-06 15:19:37 -0700992{
993 unsigned int i;
Ladislav Michla637a112005-09-01 15:07:34 +0000994
Ralf Baechled203a7e2005-09-06 15:19:37 -0700995 for (i = f->head; i == (f->tail - 1); i = (i + 1) % f->length) {
996 if (f->data[i] == id)
997 return 1;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700998 }
999
1000 return 0;
Ralf Baechled203a7e2005-09-06 15:19:37 -07001001}
Linus Torvalds1da177e2005-04-16 15:20:36 -07001002
Ladislav Michla637a112005-09-01 15:07:34 +00001003#if 0
Ralf Baechled203a7e2005-09-06 15:19:37 -07001004/* returns true/false */
Ladislav Michla637a112005-09-01 15:07:34 +00001005static inline int vino_fifo_full(struct vino_framebuffer_fifo *f)
Ralf Baechled203a7e2005-09-06 15:19:37 -07001006{
1007 return (f->used == f->length);
1008}
Ladislav Michla637a112005-09-01 15:07:34 +00001009#endif
Ralf Baechled203a7e2005-09-06 15:19:37 -07001010
Ladislav Michla637a112005-09-01 15:07:34 +00001011static inline unsigned int vino_fifo_get_used(struct vino_framebuffer_fifo *f)
Ralf Baechled203a7e2005-09-06 15:19:37 -07001012{
1013 return f->used;
1014}
1015
1016static int vino_fifo_enqueue(struct vino_framebuffer_fifo *f, unsigned int id)
1017{
1018 if (id >= f->length) {
1019 return VINO_QUEUE_ERROR;
1020 }
1021
1022 if (vino_fifo_has_id(f, id)) {
1023 return VINO_QUEUE_ERROR;
1024 }
1025
1026 if (f->used < f->length) {
1027 f->data[f->tail] = id;
1028 f->tail = (f->tail + 1) % f->length;
1029 f->used++;
1030 } else {
1031 return VINO_QUEUE_ERROR;
1032 }
1033
1034 return 0;
1035}
1036
1037static int vino_fifo_peek(struct vino_framebuffer_fifo *f, unsigned int *id)
1038{
1039 if (f->used > 0) {
1040 *id = f->data[f->head];
1041 } else {
1042 return VINO_QUEUE_ERROR;
1043 }
1044
1045 return 0;
1046}
1047
1048static int vino_fifo_dequeue(struct vino_framebuffer_fifo *f, unsigned int *id)
1049{
1050 if (f->used > 0) {
1051 *id = f->data[f->head];
1052 f->head = (f->head + 1) % f->length;
1053 f->used--;
1054 } else {
1055 return VINO_QUEUE_ERROR;
1056 }
1057
1058 return 0;
1059}
1060
1061/* Framebuffer queue functions */
1062
1063/* execute with queue_lock locked */
1064static void vino_queue_free_with_count(struct vino_framebuffer_queue *q,
1065 unsigned int length)
1066{
1067 unsigned int i;
1068
1069 q->length = 0;
1070 memset(&q->in, 0, sizeof(struct vino_framebuffer_fifo));
1071 memset(&q->out, 0, sizeof(struct vino_framebuffer_fifo));
1072 for (i = 0; i < length; i++) {
1073 dprintk("vino_queue_free_with_count(): freeing buffer %d\n",
1074 i);
1075 vino_free_buffer(q->buffer[i]);
1076 kfree(q->buffer[i]);
1077 }
1078
1079 q->type = VINO_MEMORY_NONE;
1080 q->magic = 0;
1081}
1082
1083static void vino_queue_free(struct vino_framebuffer_queue *q)
1084{
1085 dprintk("vino_queue_free():\n");
1086
1087 if (q->magic != VINO_QUEUE_MAGIC)
1088 return;
1089 if (q->type != VINO_MEMORY_MMAP)
1090 return;
1091
Ingo Molnar3593cab2006-02-07 06:49:14 -02001092 mutex_lock(&q->queue_mutex);
Ralf Baechled203a7e2005-09-06 15:19:37 -07001093
1094 vino_queue_free_with_count(q, q->length);
1095
Ingo Molnar3593cab2006-02-07 06:49:14 -02001096 mutex_unlock(&q->queue_mutex);
Ralf Baechled203a7e2005-09-06 15:19:37 -07001097}
1098
1099static int vino_queue_init(struct vino_framebuffer_queue *q,
1100 unsigned int *length)
1101{
1102 unsigned int i;
1103 int ret = 0;
1104
1105 dprintk("vino_queue_init(): length = %d\n", *length);
1106
1107 if (q->magic == VINO_QUEUE_MAGIC) {
1108 dprintk("vino_queue_init(): queue already initialized!\n");
1109 return -EINVAL;
1110 }
1111
1112 if (q->type != VINO_MEMORY_NONE) {
1113 dprintk("vino_queue_init(): queue already initialized!\n");
1114 return -EINVAL;
1115 }
1116
1117 if (*length < 1)
1118 return -EINVAL;
1119
Ingo Molnar3593cab2006-02-07 06:49:14 -02001120 mutex_lock(&q->queue_mutex);
Ralf Baechled203a7e2005-09-06 15:19:37 -07001121
Ladislav Michla637a112005-09-01 15:07:34 +00001122 if (*length > VINO_FRAMEBUFFER_COUNT_MAX)
1123 *length = VINO_FRAMEBUFFER_COUNT_MAX;
Ralf Baechled203a7e2005-09-06 15:19:37 -07001124
1125 q->length = 0;
1126
1127 for (i = 0; i < *length; i++) {
1128 dprintk("vino_queue_init(): allocating buffer %d\n", i);
1129 q->buffer[i] = kmalloc(sizeof(struct vino_framebuffer),
1130 GFP_KERNEL);
1131 if (!q->buffer[i]) {
1132 dprintk("vino_queue_init(): kmalloc() failed\n");
1133 ret = -ENOMEM;
1134 break;
1135 }
1136
1137 ret = vino_allocate_buffer(q->buffer[i],
1138 VINO_FRAMEBUFFER_SIZE);
1139 if (ret) {
1140 kfree(q->buffer[i]);
1141 dprintk("vino_queue_init(): "
1142 "vino_allocate_buffer() failed\n");
1143 break;
1144 }
1145
1146 q->buffer[i]->id = i;
1147 if (i > 0) {
1148 q->buffer[i]->offset = q->buffer[i - 1]->offset +
1149 q->buffer[i - 1]->size;
1150 } else {
1151 q->buffer[i]->offset = 0;
1152 }
1153
1154 spin_lock_init(&q->buffer[i]->state_lock);
1155
1156 dprintk("vino_queue_init(): buffer = %d, offset = %d, "
1157 "size = %d\n", i, q->buffer[i]->offset,
1158 q->buffer[i]->size);
1159 }
1160
1161 if (ret) {
1162 vino_queue_free_with_count(q, i);
1163 *length = 0;
1164 } else {
1165 q->length = *length;
1166 vino_fifo_init(&q->in, q->length);
1167 vino_fifo_init(&q->out, q->length);
1168 q->type = VINO_MEMORY_MMAP;
1169 q->magic = VINO_QUEUE_MAGIC;
1170 }
1171
Ingo Molnar3593cab2006-02-07 06:49:14 -02001172 mutex_unlock(&q->queue_mutex);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001173
1174 return ret;
1175}
1176
Ralf Baechled203a7e2005-09-06 15:19:37 -07001177static struct vino_framebuffer *vino_queue_add(struct
1178 vino_framebuffer_queue *q,
1179 unsigned int id)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001180{
Ralf Baechled203a7e2005-09-06 15:19:37 -07001181 struct vino_framebuffer *ret = NULL;
1182 unsigned int total;
1183 unsigned long flags;
1184
1185 dprintk("vino_queue_add(): id = %d\n", id);
1186
1187 if (q->magic != VINO_QUEUE_MAGIC) {
1188 return ret;
1189 }
1190
1191 spin_lock_irqsave(&q->queue_lock, flags);
1192
1193 if (q->length == 0)
1194 goto out;
1195
1196 if (id >= q->length)
1197 goto out;
1198
1199 /* not needed?: if (vino_fifo_full(&q->out)) {
1200 goto out;
1201 }*/
1202 /* check that outgoing queue isn't already full
1203 * (or that it won't become full) */
1204 total = vino_fifo_get_used(&q->in) +
1205 vino_fifo_get_used(&q->out);
1206 if (total >= q->length)
1207 goto out;
1208
1209 if (vino_fifo_enqueue(&q->in, id))
1210 goto out;
1211
1212 ret = q->buffer[id];
1213
1214out:
1215 spin_unlock_irqrestore(&q->queue_lock, flags);
1216
1217 return ret;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001218}
1219
Ralf Baechled203a7e2005-09-06 15:19:37 -07001220static struct vino_framebuffer *vino_queue_transfer(struct
1221 vino_framebuffer_queue *q)
1222{
1223 struct vino_framebuffer *ret = NULL;
1224 struct vino_framebuffer *fb;
1225 int id;
1226 unsigned long flags;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001227
Ralf Baechled203a7e2005-09-06 15:19:37 -07001228 dprintk("vino_queue_transfer():\n");
1229
1230 if (q->magic != VINO_QUEUE_MAGIC) {
1231 return ret;
1232 }
1233
1234 spin_lock_irqsave(&q->queue_lock, flags);
1235
1236 if (q->length == 0)
1237 goto out;
1238
1239 // now this actually removes an entry from the incoming queue
1240 if (vino_fifo_dequeue(&q->in, &id)) {
1241 goto out;
1242 }
1243
1244 dprintk("vino_queue_transfer(): id = %d\n", id);
1245 fb = q->buffer[id];
1246
1247 // we have already checked that the outgoing queue is not full, but...
1248 if (vino_fifo_enqueue(&q->out, id)) {
1249 printk(KERN_ERR "vino_queue_transfer(): "
1250 "outgoing queue is full, this shouldn't happen!\n");
1251 goto out;
1252 }
1253
1254 ret = fb;
1255out:
1256 spin_unlock_irqrestore(&q->queue_lock, flags);
1257
1258 return ret;
1259}
1260
1261/* returns true/false */
1262static int vino_queue_incoming_contains(struct vino_framebuffer_queue *q,
1263 unsigned int id)
1264{
1265 int ret = 0;
1266 unsigned long flags;
1267
1268 if (q->magic != VINO_QUEUE_MAGIC) {
1269 return ret;
1270 }
1271
1272 spin_lock_irqsave(&q->queue_lock, flags);
1273
1274 if (q->length == 0)
1275 goto out;
1276
1277 ret = vino_fifo_has_id(&q->in, id);
1278
1279out:
1280 spin_unlock_irqrestore(&q->queue_lock, flags);
1281
1282 return ret;
1283}
1284
1285/* returns true/false */
1286static int vino_queue_outgoing_contains(struct vino_framebuffer_queue *q,
1287 unsigned int id)
1288{
1289 int ret = 0;
1290 unsigned long flags;
1291
1292 if (q->magic != VINO_QUEUE_MAGIC) {
1293 return ret;
1294 }
1295
1296 spin_lock_irqsave(&q->queue_lock, flags);
1297
1298 if (q->length == 0)
1299 goto out;
1300
1301 ret = vino_fifo_has_id(&q->out, id);
1302
1303out:
1304 spin_unlock_irqrestore(&q->queue_lock, flags);
1305
1306 return ret;
1307}
1308
1309static int vino_queue_get_incoming(struct vino_framebuffer_queue *q,
1310 unsigned int *used)
1311{
1312 int ret = 0;
1313 unsigned long flags;
1314
1315 if (q->magic != VINO_QUEUE_MAGIC) {
1316 return VINO_QUEUE_ERROR;
1317 }
1318
1319 spin_lock_irqsave(&q->queue_lock, flags);
1320
1321 if (q->length == 0) {
1322 ret = VINO_QUEUE_ERROR;
1323 goto out;
1324 }
1325
1326 *used = vino_fifo_get_used(&q->in);
1327
1328out:
1329 spin_unlock_irqrestore(&q->queue_lock, flags);
1330
1331 return ret;
1332}
1333
1334static int vino_queue_get_outgoing(struct vino_framebuffer_queue *q,
1335 unsigned int *used)
1336{
1337 int ret = 0;
1338 unsigned long flags;
1339
1340 if (q->magic != VINO_QUEUE_MAGIC) {
1341 return VINO_QUEUE_ERROR;
1342 }
1343
1344 spin_lock_irqsave(&q->queue_lock, flags);
1345
1346 if (q->length == 0) {
1347 ret = VINO_QUEUE_ERROR;
1348 goto out;
1349 }
1350
1351 *used = vino_fifo_get_used(&q->out);
1352
1353out:
1354 spin_unlock_irqrestore(&q->queue_lock, flags);
1355
1356 return ret;
1357}
1358
Ladislav Michla637a112005-09-01 15:07:34 +00001359#if 0
Ralf Baechled203a7e2005-09-06 15:19:37 -07001360static int vino_queue_get_total(struct vino_framebuffer_queue *q,
1361 unsigned int *total)
1362{
1363 int ret = 0;
1364 unsigned long flags;
1365
1366 if (q->magic != VINO_QUEUE_MAGIC) {
1367 return VINO_QUEUE_ERROR;
1368 }
1369
1370 spin_lock_irqsave(&q->queue_lock, flags);
1371
1372 if (q->length == 0) {
1373 ret = VINO_QUEUE_ERROR;
1374 goto out;
1375 }
1376
1377 *total = vino_fifo_get_used(&q->in) +
1378 vino_fifo_get_used(&q->out);
1379
1380out:
1381 spin_unlock_irqrestore(&q->queue_lock, flags);
1382
1383 return ret;
1384}
Ladislav Michla637a112005-09-01 15:07:34 +00001385#endif
Ralf Baechled203a7e2005-09-06 15:19:37 -07001386
1387static struct vino_framebuffer *vino_queue_peek(struct
1388 vino_framebuffer_queue *q,
1389 unsigned int *id)
1390{
1391 struct vino_framebuffer *ret = NULL;
1392 unsigned long flags;
1393
1394 if (q->magic != VINO_QUEUE_MAGIC) {
1395 return ret;
1396 }
1397
1398 spin_lock_irqsave(&q->queue_lock, flags);
1399
1400 if (q->length == 0)
1401 goto out;
1402
1403 if (vino_fifo_peek(&q->in, id)) {
1404 goto out;
1405 }
1406
1407 ret = q->buffer[*id];
1408out:
1409 spin_unlock_irqrestore(&q->queue_lock, flags);
1410
1411 return ret;
1412}
1413
1414static struct vino_framebuffer *vino_queue_remove(struct
1415 vino_framebuffer_queue *q,
1416 unsigned int *id)
1417{
1418 struct vino_framebuffer *ret = NULL;
1419 unsigned long flags;
1420 dprintk("vino_queue_remove():\n");
1421
1422 if (q->magic != VINO_QUEUE_MAGIC) {
1423 return ret;
1424 }
1425
1426 spin_lock_irqsave(&q->queue_lock, flags);
1427
1428 if (q->length == 0)
1429 goto out;
1430
1431 if (vino_fifo_dequeue(&q->out, id)) {
1432 goto out;
1433 }
1434
1435 dprintk("vino_queue_remove(): id = %d\n", *id);
1436 ret = q->buffer[*id];
1437out:
1438 spin_unlock_irqrestore(&q->queue_lock, flags);
1439
1440 return ret;
1441}
1442
1443static struct
1444vino_framebuffer *vino_queue_get_buffer(struct vino_framebuffer_queue *q,
1445 unsigned int id)
1446{
1447 struct vino_framebuffer *ret = NULL;
1448 unsigned long flags;
1449
1450 if (q->magic != VINO_QUEUE_MAGIC) {
1451 return ret;
1452 }
1453
1454 spin_lock_irqsave(&q->queue_lock, flags);
1455
1456 if (q->length == 0)
1457 goto out;
1458
1459 if (id >= q->length)
1460 goto out;
1461
1462 ret = q->buffer[id];
1463 out:
1464 spin_unlock_irqrestore(&q->queue_lock, flags);
1465
1466 return ret;
1467}
1468
1469static unsigned int vino_queue_get_length(struct vino_framebuffer_queue *q)
1470{
1471 unsigned int length = 0;
1472 unsigned long flags;
1473
1474 if (q->magic != VINO_QUEUE_MAGIC) {
1475 return length;
1476 }
1477
1478 spin_lock_irqsave(&q->queue_lock, flags);
1479 length = q->length;
1480 spin_unlock_irqrestore(&q->queue_lock, flags);
1481
1482 return length;
1483}
1484
1485static int vino_queue_has_mapped_buffers(struct vino_framebuffer_queue *q)
1486{
1487 unsigned int i;
1488 int ret = 0;
1489 unsigned long flags;
1490
1491 if (q->magic != VINO_QUEUE_MAGIC) {
1492 return ret;
1493 }
1494
1495 spin_lock_irqsave(&q->queue_lock, flags);
1496 for (i = 0; i < q->length; i++) {
1497 if (q->buffer[i]->map_count > 0) {
1498 ret = 1;
1499 break;
1500 }
1501 }
1502 spin_unlock_irqrestore(&q->queue_lock, flags);
1503
1504 return ret;
1505}
1506
1507/* VINO functions */
1508
1509/* execute with input_lock locked */
1510static void vino_update_line_size(struct vino_channel_settings *vcs)
1511{
1512 unsigned int w = vcs->clipping.right - vcs->clipping.left;
1513 unsigned int d = vcs->decimation;
1514 unsigned int bpp = vino_data_formats[vcs->data_format].bpp;
Mauro Carvalho Chehabd56410e2006-03-25 09:19:53 -03001515 unsigned int lsize;
Ralf Baechled203a7e2005-09-06 15:19:37 -07001516
1517 dprintk("update_line_size(): before: w = %d, d = %d, "
1518 "line_size = %d\n", w, d, vcs->line_size);
Ladislav Michla637a112005-09-01 15:07:34 +00001519
Mauro Carvalho Chehabd56410e2006-03-25 09:19:53 -03001520 /* line size must be multiple of 8 bytes */
Ralf Baechled203a7e2005-09-06 15:19:37 -07001521 lsize = (bpp * (w / d)) & ~7;
1522 w = (lsize / bpp) * d;
1523
1524 vcs->clipping.right = vcs->clipping.left + w;
1525 vcs->line_size = lsize;
Ladislav Michla637a112005-09-01 15:07:34 +00001526
Ralf Baechled203a7e2005-09-06 15:19:37 -07001527 dprintk("update_line_size(): after: w = %d, d = %d, "
1528 "line_size = %d\n", w, d, vcs->line_size);
1529}
1530
1531/* execute with input_lock locked */
1532static void vino_set_clipping(struct vino_channel_settings *vcs,
1533 unsigned int x, unsigned int y,
1534 unsigned int w, unsigned int h)
1535{
1536 unsigned int maxwidth, maxheight;
1537 unsigned int d;
1538
1539 maxwidth = vino_data_norms[vcs->data_norm].width;
1540 maxheight = vino_data_norms[vcs->data_norm].height;
1541 d = vcs->decimation;
1542
1543 y &= ~1; /* odd/even fields */
1544
1545 if (x > maxwidth) {
1546 x = 0;
1547 }
1548 if (y > maxheight) {
1549 y = 0;
1550 }
1551
1552 if (((w / d) < VINO_MIN_WIDTH)
1553 || ((h / d) < VINO_MIN_HEIGHT)) {
1554 w = VINO_MIN_WIDTH * d;
1555 h = VINO_MIN_HEIGHT * d;
1556 }
1557
1558 if ((x + w) > maxwidth) {
1559 w = maxwidth - x;
1560 if ((w / d) < VINO_MIN_WIDTH)
1561 x = maxwidth - VINO_MIN_WIDTH * d;
1562 }
1563 if ((y + h) > maxheight) {
1564 h = maxheight - y;
1565 if ((h / d) < VINO_MIN_HEIGHT)
1566 y = maxheight - VINO_MIN_HEIGHT * d;
1567 }
1568
1569 vcs->clipping.left = x;
1570 vcs->clipping.top = y;
1571 vcs->clipping.right = x + w;
1572 vcs->clipping.bottom = y + h;
1573
1574 vino_update_line_size(vcs);
1575
1576 dprintk("clipping %d, %d, %d, %d / %d - %d\n",
1577 vcs->clipping.left, vcs->clipping.top, vcs->clipping.right,
1578 vcs->clipping.bottom, vcs->decimation, vcs->line_size);
1579}
1580
1581/* execute with input_lock locked */
Ladislav Michla637a112005-09-01 15:07:34 +00001582static inline void vino_set_default_clipping(struct vino_channel_settings *vcs)
Ralf Baechled203a7e2005-09-06 15:19:37 -07001583{
1584 vino_set_clipping(vcs, 0, 0, vino_data_norms[vcs->data_norm].width,
1585 vino_data_norms[vcs->data_norm].height);
1586}
1587
1588/* execute with input_lock locked */
1589static void vino_set_scaling(struct vino_channel_settings *vcs,
1590 unsigned int w, unsigned int h)
1591{
1592 unsigned int x, y, curw, curh, d;
1593
1594 x = vcs->clipping.left;
1595 y = vcs->clipping.top;
1596 curw = vcs->clipping.right - vcs->clipping.left;
1597 curh = vcs->clipping.bottom - vcs->clipping.top;
1598
1599 d = max(curw / w, curh / h);
1600
1601 dprintk("scaling w: %d, h: %d, curw: %d, curh: %d, d: %d\n",
1602 w, h, curw, curh, d);
1603
1604 if (d < 1) {
1605 d = 1;
Ladislav Michla637a112005-09-01 15:07:34 +00001606 } else if (d > 8) {
Ralf Baechled203a7e2005-09-06 15:19:37 -07001607 d = 8;
1608 }
1609
1610 vcs->decimation = d;
1611 vino_set_clipping(vcs, x, y, w * d, h * d);
1612
1613 dprintk("scaling %d, %d, %d, %d / %d - %d\n", vcs->clipping.left,
1614 vcs->clipping.top, vcs->clipping.right, vcs->clipping.bottom,
1615 vcs->decimation, vcs->line_size);
1616}
1617
1618/* execute with input_lock locked */
Ladislav Michla637a112005-09-01 15:07:34 +00001619static inline void vino_set_default_scaling(struct vino_channel_settings *vcs)
Ralf Baechled203a7e2005-09-06 15:19:37 -07001620{
1621 vino_set_scaling(vcs, vcs->clipping.right - vcs->clipping.left,
1622 vcs->clipping.bottom - vcs->clipping.top);
1623}
1624
1625/* execute with input_lock locked */
1626static void vino_set_framerate(struct vino_channel_settings *vcs,
1627 unsigned int fps)
1628{
1629 unsigned int mask;
1630
1631 switch (vcs->data_norm) {
1632 case VINO_DATA_NORM_NTSC:
1633 case VINO_DATA_NORM_D1:
1634 fps = (unsigned int)(fps / 6) * 6; // FIXME: round!
1635
1636 if (fps < vino_data_norms[vcs->data_norm].fps_min)
1637 fps = vino_data_norms[vcs->data_norm].fps_min;
1638 if (fps > vino_data_norms[vcs->data_norm].fps_max)
1639 fps = vino_data_norms[vcs->data_norm].fps_max;
1640
1641 switch (fps) {
1642 case 6:
1643 mask = 0x003;
1644 break;
1645 case 12:
1646 mask = 0x0c3;
1647 break;
1648 case 18:
1649 mask = 0x333;
1650 break;
1651 case 24:
1652 mask = 0x3ff;
1653 break;
1654 case 30:
1655 mask = 0xfff;
1656 break;
1657 default:
1658 mask = VINO_FRAMERT_FULL;
1659 }
1660 vcs->framert_reg = VINO_FRAMERT_RT(mask);
1661 break;
1662 case VINO_DATA_NORM_PAL:
1663 case VINO_DATA_NORM_SECAM:
1664 fps = (unsigned int)(fps / 5) * 5; // FIXME: round!
1665
1666 if (fps < vino_data_norms[vcs->data_norm].fps_min)
1667 fps = vino_data_norms[vcs->data_norm].fps_min;
1668 if (fps > vino_data_norms[vcs->data_norm].fps_max)
1669 fps = vino_data_norms[vcs->data_norm].fps_max;
1670
1671 switch (fps) {
1672 case 5:
1673 mask = 0x003;
1674 break;
1675 case 10:
1676 mask = 0x0c3;
1677 break;
1678 case 15:
1679 mask = 0x333;
1680 break;
1681 case 20:
1682 mask = 0x0ff;
1683 break;
1684 case 25:
1685 mask = 0x3ff;
1686 break;
1687 default:
1688 mask = VINO_FRAMERT_FULL;
1689 }
1690 vcs->framert_reg = VINO_FRAMERT_RT(mask) | VINO_FRAMERT_PAL;
1691 break;
1692 }
1693
1694 vcs->fps = fps;
1695}
1696
1697/* execute with input_lock locked */
Ladislav Michla637a112005-09-01 15:07:34 +00001698static inline void vino_set_default_framerate(struct
1699 vino_channel_settings *vcs)
Ralf Baechled203a7e2005-09-06 15:19:37 -07001700{
1701 vino_set_framerate(vcs, vino_data_norms[vcs->data_norm].fps_max);
1702}
1703
1704/*
1705 * Prepare VINO for DMA transfer...
1706 * (execute only with vino_lock and input_lock locked)
1707 */
1708static int vino_dma_setup(struct vino_channel_settings *vcs,
1709 struct vino_framebuffer *fb)
1710{
1711 u32 ctrl, intr;
1712 struct sgi_vino_channel *ch;
1713 const struct vino_data_norm *norm;
1714
1715 dprintk("vino_dma_setup():\n");
1716
1717 vcs->field = 0;
1718 fb->frame_counter = 0;
1719
1720 ch = (vcs->channel == VINO_CHANNEL_A) ? &vino->a : &vino->b;
1721 norm = &vino_data_norms[vcs->data_norm];
1722
1723 ch->page_index = 0;
1724 ch->line_count = 0;
1725
1726 /* VINO line size register is set 8 bytes less than actual */
1727 ch->line_size = vcs->line_size - 8;
1728
1729 /* let VINO know where to transfer data */
1730 ch->start_desc_tbl = fb->desc_table.dma;
1731 ch->next_4_desc = fb->desc_table.dma;
1732
1733 /* give vino time to fetch the first four descriptors, 5 usec
1734 * should be more than enough time */
1735 udelay(VINO_DESC_FETCH_DELAY);
1736
Ladislav Michla637a112005-09-01 15:07:34 +00001737 dprintk("vino_dma_setup(): start desc = %08x, next 4 desc = %08x\n",
1738 ch->start_desc_tbl, ch->next_4_desc);
1739
Ralf Baechled203a7e2005-09-06 15:19:37 -07001740 /* set the alpha register */
1741 ch->alpha = vcs->alpha;
1742
1743 /* set clipping registers */
1744 ch->clip_start = VINO_CLIP_ODD(norm->odd.top + vcs->clipping.top / 2) |
1745 VINO_CLIP_EVEN(norm->even.top +
1746 vcs->clipping.top / 2) |
1747 VINO_CLIP_X(vcs->clipping.left);
1748 ch->clip_end = VINO_CLIP_ODD(norm->odd.top +
1749 vcs->clipping.bottom / 2 - 1) |
1750 VINO_CLIP_EVEN(norm->even.top +
1751 vcs->clipping.bottom / 2 - 1) |
1752 VINO_CLIP_X(vcs->clipping.right);
Ralf Baechled203a7e2005-09-06 15:19:37 -07001753
1754 /* set the size of actual content in the buffer (DECIMATION !) */
1755 fb->data_size = ((vcs->clipping.right - vcs->clipping.left) /
1756 vcs->decimation) *
1757 ((vcs->clipping.bottom - vcs->clipping.top) /
1758 vcs->decimation) *
1759 vino_data_formats[vcs->data_format].bpp;
1760
1761 ch->frame_rate = vcs->framert_reg;
1762
1763 ctrl = vino->control;
1764 intr = vino->intr_status;
1765
1766 if (vcs->channel == VINO_CHANNEL_A) {
1767 /* All interrupt conditions for this channel was cleared
1768 * so clear the interrupt status register and enable
1769 * interrupts */
1770 intr &= ~VINO_INTSTAT_A;
1771 ctrl |= VINO_CTRL_A_INT;
1772
1773 /* enable synchronization */
1774 ctrl |= VINO_CTRL_A_SYNC_ENBL;
1775
1776 /* enable frame assembly */
1777 ctrl |= VINO_CTRL_A_INTERLEAVE_ENBL;
1778
1779 /* set decimation used */
1780 if (vcs->decimation < 2)
1781 ctrl &= ~VINO_CTRL_A_DEC_ENBL;
1782 else {
1783 ctrl |= VINO_CTRL_A_DEC_ENBL;
1784 ctrl &= ~VINO_CTRL_A_DEC_SCALE_MASK;
1785 ctrl |= (vcs->decimation - 1) <<
1786 VINO_CTRL_A_DEC_SCALE_SHIFT;
1787 }
1788
1789 /* select input interface */
1790 if (vcs->input == VINO_INPUT_D1)
1791 ctrl |= VINO_CTRL_A_SELECT;
1792 else
1793 ctrl &= ~VINO_CTRL_A_SELECT;
1794
1795 /* palette */
1796 ctrl &= ~(VINO_CTRL_A_LUMA_ONLY | VINO_CTRL_A_RGB |
1797 VINO_CTRL_A_DITHER);
1798 } else {
1799 intr &= ~VINO_INTSTAT_B;
1800 ctrl |= VINO_CTRL_B_INT;
1801
1802 ctrl |= VINO_CTRL_B_SYNC_ENBL;
1803 ctrl |= VINO_CTRL_B_INTERLEAVE_ENBL;
1804
1805 if (vcs->decimation < 2)
1806 ctrl &= ~VINO_CTRL_B_DEC_ENBL;
1807 else {
1808 ctrl |= VINO_CTRL_B_DEC_ENBL;
1809 ctrl &= ~VINO_CTRL_B_DEC_SCALE_MASK;
1810 ctrl |= (vcs->decimation - 1) <<
1811 VINO_CTRL_B_DEC_SCALE_SHIFT;
1812
1813 }
1814 if (vcs->input == VINO_INPUT_D1)
1815 ctrl |= VINO_CTRL_B_SELECT;
1816 else
1817 ctrl &= ~VINO_CTRL_B_SELECT;
1818
1819 ctrl &= ~(VINO_CTRL_B_LUMA_ONLY | VINO_CTRL_B_RGB |
1820 VINO_CTRL_B_DITHER);
1821 }
1822
1823 /* set palette */
1824 fb->data_format = vcs->data_format;
1825
1826 switch (vcs->data_format) {
1827 case VINO_DATA_FMT_GREY:
1828 ctrl |= (vcs->channel == VINO_CHANNEL_A) ?
1829 VINO_CTRL_A_LUMA_ONLY : VINO_CTRL_B_LUMA_ONLY;
1830 break;
1831 case VINO_DATA_FMT_RGB32:
1832 ctrl |= (vcs->channel == VINO_CHANNEL_A) ?
1833 VINO_CTRL_A_RGB : VINO_CTRL_B_RGB;
1834 break;
1835 case VINO_DATA_FMT_YUV:
1836 /* nothing needs to be done */
1837 break;
1838 case VINO_DATA_FMT_RGB332:
1839 ctrl |= (vcs->channel == VINO_CHANNEL_A) ?
1840 VINO_CTRL_A_RGB | VINO_CTRL_A_DITHER :
1841 VINO_CTRL_B_RGB | VINO_CTRL_B_DITHER;
1842 break;
1843 }
1844
1845 vino->intr_status = intr;
1846 vino->control = ctrl;
1847
1848 return 0;
1849}
1850
1851/* (execute only with vino_lock locked) */
Ladislav Michla637a112005-09-01 15:07:34 +00001852static inline void vino_dma_start(struct vino_channel_settings *vcs)
Ralf Baechled203a7e2005-09-06 15:19:37 -07001853{
1854 u32 ctrl = vino->control;
1855
1856 dprintk("vino_dma_start():\n");
1857 ctrl |= (vcs->channel == VINO_CHANNEL_A) ?
1858 VINO_CTRL_A_DMA_ENBL : VINO_CTRL_B_DMA_ENBL;
1859 vino->control = ctrl;
1860}
1861
1862/* (execute only with vino_lock locked) */
Ladislav Michla637a112005-09-01 15:07:34 +00001863static inline void vino_dma_stop(struct vino_channel_settings *vcs)
Ralf Baechled203a7e2005-09-06 15:19:37 -07001864{
1865 u32 ctrl = vino->control;
1866
1867 ctrl &= (vcs->channel == VINO_CHANNEL_A) ?
1868 ~VINO_CTRL_A_DMA_ENBL : ~VINO_CTRL_B_DMA_ENBL;
Ladislav Michla637a112005-09-01 15:07:34 +00001869 ctrl &= (vcs->channel == VINO_CHANNEL_A) ?
1870 ~VINO_CTRL_A_INT : ~VINO_CTRL_B_INT;
Ralf Baechled203a7e2005-09-06 15:19:37 -07001871 vino->control = ctrl;
1872 dprintk("vino_dma_stop():\n");
1873}
1874
1875/*
1876 * Load dummy page to descriptor registers. This prevents generating of
1877 * spurious interrupts. (execute only with vino_lock locked)
1878 */
1879static void vino_clear_interrupt(struct vino_channel_settings *vcs)
1880{
1881 struct sgi_vino_channel *ch;
1882
1883 ch = (vcs->channel == VINO_CHANNEL_A) ? &vino->a : &vino->b;
1884
1885 ch->page_index = 0;
1886 ch->line_count = 0;
1887
1888 ch->start_desc_tbl = vino_drvdata->dummy_desc_table.dma;
1889 ch->next_4_desc = vino_drvdata->dummy_desc_table.dma;
1890
1891 udelay(VINO_DESC_FETCH_DELAY);
1892 dprintk("channel %c clear interrupt condition\n",
1893 (vcs->channel == VINO_CHANNEL_A) ? 'A':'B');
1894}
1895
1896static int vino_capture(struct vino_channel_settings *vcs,
1897 struct vino_framebuffer *fb)
1898{
1899 int err = 0;
1900 unsigned long flags, flags2;
1901
1902 spin_lock_irqsave(&fb->state_lock, flags);
1903
1904 if (fb->state == VINO_FRAMEBUFFER_IN_USE)
1905 err = -EBUSY;
1906 fb->state = VINO_FRAMEBUFFER_IN_USE;
1907
1908 spin_unlock_irqrestore(&fb->state_lock, flags);
1909
1910 if (err)
1911 return err;
1912
1913 spin_lock_irqsave(&vino_drvdata->vino_lock, flags);
1914 spin_lock_irqsave(&vino_drvdata->input_lock, flags2);
1915
1916 vino_dma_setup(vcs, fb);
1917 vino_dma_start(vcs);
1918
1919 spin_unlock_irqrestore(&vino_drvdata->input_lock, flags2);
1920 spin_unlock_irqrestore(&vino_drvdata->vino_lock, flags);
1921
1922 return err;
1923}
1924
1925static
1926struct vino_framebuffer *vino_capture_enqueue(struct
1927 vino_channel_settings *vcs,
1928 unsigned int index)
1929{
1930 struct vino_framebuffer *fb;
1931 unsigned long flags;
1932
1933 dprintk("vino_capture_enqueue():\n");
1934
1935 spin_lock_irqsave(&vcs->capture_lock, flags);
1936
1937 fb = vino_queue_add(&vcs->fb_queue, index);
1938 if (fb == NULL) {
1939 dprintk("vino_capture_enqueue(): vino_queue_add() failed, "
1940 "queue full?\n");
1941 goto out;
1942 }
1943out:
1944 spin_unlock_irqrestore(&vcs->capture_lock, flags);
1945
1946 return fb;
1947}
1948
1949static int vino_capture_next(struct vino_channel_settings *vcs, int start)
1950{
1951 struct vino_framebuffer *fb;
1952 unsigned int incoming, id;
1953 int err = 0;
Ladislav Michla637a112005-09-01 15:07:34 +00001954 unsigned long flags;
Ralf Baechled203a7e2005-09-06 15:19:37 -07001955
1956 dprintk("vino_capture_next():\n");
1957
1958 spin_lock_irqsave(&vcs->capture_lock, flags);
1959
1960 if (start) {
1961 /* start capture only if capture isn't in progress already */
1962 if (vcs->capturing) {
1963 spin_unlock_irqrestore(&vcs->capture_lock, flags);
1964 return 0;
1965 }
1966
1967 } else {
1968 /* capture next frame:
1969 * stop capture if capturing is not set */
1970 if (!vcs->capturing) {
1971 spin_unlock_irqrestore(&vcs->capture_lock, flags);
1972 return 0;
1973 }
1974 }
1975
1976 err = vino_queue_get_incoming(&vcs->fb_queue, &incoming);
1977 if (err) {
1978 dprintk("vino_capture_next(): vino_queue_get_incoming() "
1979 "failed\n");
1980 err = -EINVAL;
1981 goto out;
1982 }
1983 if (incoming == 0) {
1984 dprintk("vino_capture_next(): no buffers available\n");
1985 goto out;
1986 }
1987
1988 fb = vino_queue_peek(&vcs->fb_queue, &id);
1989 if (fb == NULL) {
1990 dprintk("vino_capture_next(): vino_queue_peek() failed\n");
1991 err = -EINVAL;
1992 goto out;
1993 }
1994
Ralf Baechled203a7e2005-09-06 15:19:37 -07001995 if (start) {
1996 vcs->capturing = 1;
1997 }
1998
1999 spin_unlock_irqrestore(&vcs->capture_lock, flags);
2000
2001 err = vino_capture(vcs, fb);
2002
2003 return err;
2004
2005out:
2006 vcs->capturing = 0;
2007 spin_unlock_irqrestore(&vcs->capture_lock, flags);
2008
2009 return err;
2010}
2011
Ladislav Michla637a112005-09-01 15:07:34 +00002012static inline int vino_is_capturing(struct vino_channel_settings *vcs)
Ralf Baechled203a7e2005-09-06 15:19:37 -07002013{
2014 int ret;
2015 unsigned long flags;
2016
2017 spin_lock_irqsave(&vcs->capture_lock, flags);
2018
2019 ret = vcs->capturing;
2020
2021 spin_unlock_irqrestore(&vcs->capture_lock, flags);
2022
2023 return ret;
2024}
2025
2026/* waits until a frame is captured */
2027static int vino_wait_for_frame(struct vino_channel_settings *vcs)
2028{
2029 wait_queue_t wait;
2030 int err = 0;
2031
2032 dprintk("vino_wait_for_frame():\n");
2033
2034 init_waitqueue_entry(&wait, current);
2035 /* add ourselves into wait queue */
2036 add_wait_queue(&vcs->fb_queue.frame_wait_queue, &wait);
Ralf Baechled203a7e2005-09-06 15:19:37 -07002037
2038 /* to ensure that schedule_timeout will return immediately
Robert P. J. Dayf3a43d32007-07-16 10:46:42 -03002039 * if VINO interrupt was triggered meanwhile */
Mauro Carvalho Chehab818ca472007-07-17 16:29:07 -03002040 schedule_timeout_interruptible(msecs_to_jiffies(100));
Ralf Baechled203a7e2005-09-06 15:19:37 -07002041
2042 if (signal_pending(current))
2043 err = -EINTR;
2044
2045 remove_wait_queue(&vcs->fb_queue.frame_wait_queue, &wait);
2046
2047 dprintk("vino_wait_for_frame(): waiting for frame %s\n",
2048 err ? "failed" : "ok");
2049
2050 return err;
2051}
2052
2053/* the function assumes that PAGE_SIZE % 4 == 0 */
2054static void vino_convert_to_rgba(struct vino_framebuffer *fb) {
2055 unsigned char *pageptr;
2056 unsigned int page, i;
2057 unsigned char a;
2058
2059 for (page = 0; page < fb->desc_table.page_count; page++) {
2060 pageptr = (unsigned char *)fb->desc_table.virtual[page];
2061
2062 for (i = 0; i < PAGE_SIZE; i += 4) {
2063 a = pageptr[0];
2064 pageptr[0] = pageptr[3];
2065 pageptr[1] = pageptr[2];
2066 pageptr[2] = pageptr[1];
2067 pageptr[3] = a;
2068 pageptr += 4;
2069 }
2070 }
2071}
2072
2073/* checks if the buffer is in correct state and syncs data */
2074static int vino_check_buffer(struct vino_channel_settings *vcs,
2075 struct vino_framebuffer *fb)
2076{
2077 int err = 0;
2078 unsigned long flags;
2079
2080 dprintk("vino_check_buffer():\n");
2081
2082 spin_lock_irqsave(&fb->state_lock, flags);
2083 switch (fb->state) {
2084 case VINO_FRAMEBUFFER_IN_USE:
2085 err = -EIO;
2086 break;
2087 case VINO_FRAMEBUFFER_READY:
2088 vino_sync_buffer(fb);
2089 fb->state = VINO_FRAMEBUFFER_UNUSED;
2090 break;
2091 default:
2092 err = -EINVAL;
2093 }
2094 spin_unlock_irqrestore(&fb->state_lock, flags);
2095
2096 if (!err) {
2097 if (vino_pixel_conversion
2098 && (fb->data_format == VINO_DATA_FMT_RGB32)) {
2099 vino_convert_to_rgba(fb);
2100 }
2101 } else if (err && (err != -EINVAL)) {
2102 dprintk("vino_check_buffer(): buffer not ready\n");
2103
2104 spin_lock_irqsave(&vino_drvdata->vino_lock, flags);
2105 vino_dma_stop(vcs);
2106 vino_clear_interrupt(vcs);
2107 spin_unlock_irqrestore(&vino_drvdata->vino_lock, flags);
2108 }
2109
2110 return err;
2111}
2112
2113/* forcefully terminates capture */
2114static void vino_capture_stop(struct vino_channel_settings *vcs)
2115{
2116 unsigned int incoming = 0, outgoing = 0, id;
2117 unsigned long flags, flags2;
2118
2119 dprintk("vino_capture_stop():\n");
2120
2121 spin_lock_irqsave(&vcs->capture_lock, flags);
Ladislav Michla637a112005-09-01 15:07:34 +00002122
Ralf Baechled203a7e2005-09-06 15:19:37 -07002123 /* unset capturing to stop queue processing */
2124 vcs->capturing = 0;
2125
2126 spin_lock_irqsave(&vino_drvdata->vino_lock, flags2);
2127
2128 vino_dma_stop(vcs);
2129 vino_clear_interrupt(vcs);
2130
2131 spin_unlock_irqrestore(&vino_drvdata->vino_lock, flags2);
2132
2133 /* remove all items from the queue */
2134 if (vino_queue_get_incoming(&vcs->fb_queue, &incoming)) {
2135 dprintk("vino_capture_stop(): "
2136 "vino_queue_get_incoming() failed\n");
2137 goto out;
2138 }
2139 while (incoming > 0) {
2140 vino_queue_transfer(&vcs->fb_queue);
2141
2142 if (vino_queue_get_incoming(&vcs->fb_queue, &incoming)) {
2143 dprintk("vino_capture_stop(): "
2144 "vino_queue_get_incoming() failed\n");
2145 goto out;
2146 }
2147 }
2148
2149 if (vino_queue_get_outgoing(&vcs->fb_queue, &outgoing)) {
2150 dprintk("vino_capture_stop(): "
2151 "vino_queue_get_outgoing() failed\n");
2152 goto out;
2153 }
2154 while (outgoing > 0) {
2155 vino_queue_remove(&vcs->fb_queue, &id);
2156
2157 if (vino_queue_get_outgoing(&vcs->fb_queue, &outgoing)) {
2158 dprintk("vino_capture_stop(): "
2159 "vino_queue_get_outgoing() failed\n");
2160 goto out;
2161 }
2162 }
2163
2164out:
2165 spin_unlock_irqrestore(&vcs->capture_lock, flags);
2166}
2167
Ladislav Michla637a112005-09-01 15:07:34 +00002168#if 0
Ralf Baechled203a7e2005-09-06 15:19:37 -07002169static int vino_capture_failed(struct vino_channel_settings *vcs)
2170{
2171 struct vino_framebuffer *fb;
2172 unsigned long flags;
2173 unsigned int i;
2174 int ret;
2175
2176 dprintk("vino_capture_failed():\n");
2177
2178 spin_lock_irqsave(&vino_drvdata->vino_lock, flags);
2179
2180 vino_dma_stop(vcs);
2181 vino_clear_interrupt(vcs);
2182
2183 spin_unlock_irqrestore(&vino_drvdata->vino_lock, flags);
2184
2185 ret = vino_queue_get_incoming(&vcs->fb_queue, &i);
2186 if (ret == VINO_QUEUE_ERROR) {
2187 dprintk("vino_queue_get_incoming() failed\n");
2188 return -EINVAL;
2189 }
2190 if (i == 0) {
2191 /* no buffers to process */
2192 return 0;
2193 }
2194
2195 fb = vino_queue_peek(&vcs->fb_queue, &i);
2196 if (fb == NULL) {
2197 dprintk("vino_queue_peek() failed\n");
2198 return -EINVAL;
2199 }
2200
2201 spin_lock_irqsave(&fb->state_lock, flags);
2202 if (fb->state == VINO_FRAMEBUFFER_IN_USE) {
2203 fb->state = VINO_FRAMEBUFFER_UNUSED;
2204 vino_queue_transfer(&vcs->fb_queue);
2205 vino_queue_remove(&vcs->fb_queue, &i);
2206 /* we should actually discard the newest frame,
2207 * but who cares ... */
2208 }
2209 spin_unlock_irqrestore(&fb->state_lock, flags);
2210
2211 return 0;
2212}
Ladislav Michla637a112005-09-01 15:07:34 +00002213#endif
Ralf Baechled203a7e2005-09-06 15:19:37 -07002214
Ladislav Michla637a112005-09-01 15:07:34 +00002215static void vino_skip_frame(struct vino_channel_settings *vcs)
2216{
2217 struct vino_framebuffer *fb;
2218 unsigned long flags;
2219 unsigned int id;
2220
2221 spin_lock_irqsave(&vcs->capture_lock, flags);
2222 fb = vino_queue_peek(&vcs->fb_queue, &id);
2223 if (!fb) {
2224 spin_unlock_irqrestore(&vcs->capture_lock, flags);
2225 dprintk("vino_skip_frame(): vino_queue_peek() failed!\n");
2226 return;
2227 }
2228 spin_unlock_irqrestore(&vcs->capture_lock, flags);
2229
2230 spin_lock_irqsave(&fb->state_lock, flags);
2231 fb->state = VINO_FRAMEBUFFER_UNUSED;
2232 spin_unlock_irqrestore(&fb->state_lock, flags);
2233
2234 vino_capture_next(vcs, 0);
2235}
2236
2237static void vino_frame_done(struct vino_channel_settings *vcs)
Ralf Baechled203a7e2005-09-06 15:19:37 -07002238{
2239 struct vino_framebuffer *fb;
2240 unsigned long flags;
2241
2242 spin_lock_irqsave(&vcs->capture_lock, flags);
2243 fb = vino_queue_transfer(&vcs->fb_queue);
2244 if (!fb) {
2245 spin_unlock_irqrestore(&vcs->capture_lock, flags);
2246 dprintk("vino_frame_done(): vino_queue_transfer() failed!\n");
2247 return;
2248 }
2249 spin_unlock_irqrestore(&vcs->capture_lock, flags);
2250
Ladislav Michla637a112005-09-01 15:07:34 +00002251 fb->frame_counter = vcs->int_data.frame_counter;
2252 memcpy(&fb->timestamp, &vcs->int_data.timestamp,
2253 sizeof(struct timeval));
Ralf Baechled203a7e2005-09-06 15:19:37 -07002254
2255 spin_lock_irqsave(&fb->state_lock, flags);
2256 if (fb->state == VINO_FRAMEBUFFER_IN_USE)
2257 fb->state = VINO_FRAMEBUFFER_READY;
2258 spin_unlock_irqrestore(&fb->state_lock, flags);
2259
2260 wake_up(&vcs->fb_queue.frame_wait_queue);
2261
2262 vino_capture_next(vcs, 0);
2263}
2264
Ladislav Michla637a112005-09-01 15:07:34 +00002265static void vino_capture_tasklet(unsigned long channel) {
2266 struct vino_channel_settings *vcs;
2267
2268 vcs = (channel == VINO_CHANNEL_A)
2269 ? &vino_drvdata->a : &vino_drvdata->b;
2270
2271 if (vcs->int_data.skip)
2272 vcs->int_data.skip_count++;
2273
2274 if (vcs->int_data.skip && (vcs->int_data.skip_count
2275 <= VINO_MAX_FRAME_SKIP_COUNT)) {
2276 vino_skip_frame(vcs);
2277 } else {
2278 vcs->int_data.skip_count = 0;
2279 vino_frame_done(vcs);
2280 }
2281}
2282
David Howells7d12e782006-10-05 14:55:46 +01002283static irqreturn_t vino_interrupt(int irq, void *dev_id)
Ralf Baechled203a7e2005-09-06 15:19:37 -07002284{
Ladislav Michla637a112005-09-01 15:07:34 +00002285 u32 ctrl, intr;
Ralf Baechled203a7e2005-09-06 15:19:37 -07002286 unsigned int fc_a, fc_b;
Ladislav Michla637a112005-09-01 15:07:34 +00002287 int handled_a = 0, skip_a = 0, done_a = 0;
2288 int handled_b = 0, skip_b = 0, done_b = 0;
2289
2290#ifdef VINO_DEBUG_INT
2291 int loop = 0;
2292 unsigned int line_count = vino->a.line_count,
2293 page_index = vino->a.page_index,
2294 field_counter = vino->a.field_counter,
2295 start_desc_tbl = vino->a.start_desc_tbl,
2296 next_4_desc = vino->a.next_4_desc;
2297 unsigned int line_count_2,
2298 page_index_2,
2299 field_counter_2,
2300 start_desc_tbl_2,
2301 next_4_desc_2;
2302#endif
Ralf Baechled203a7e2005-09-06 15:19:37 -07002303
2304 spin_lock(&vino_drvdata->vino_lock);
2305
Ladislav Michla637a112005-09-01 15:07:34 +00002306 while ((intr = vino->intr_status)) {
2307 fc_a = vino->a.field_counter >> 1;
2308 fc_b = vino->b.field_counter >> 1;
Ralf Baechled203a7e2005-09-06 15:19:37 -07002309
Ladislav Michla637a112005-09-01 15:07:34 +00002310 /* handle error-interrupts in some special way ?
2311 * --> skips frames */
2312 if (intr & VINO_INTSTAT_A) {
2313 if (intr & VINO_INTSTAT_A_EOF) {
2314 vino_drvdata->a.field++;
2315 if (vino_drvdata->a.field > 1) {
2316 vino_dma_stop(&vino_drvdata->a);
2317 vino_clear_interrupt(&vino_drvdata->a);
2318 vino_drvdata->a.field = 0;
2319 done_a = 1;
2320 } else {
2321 if (vino->a.page_index
2322 != vino_drvdata->a.line_size) {
2323 vino->a.line_count = 0;
2324 vino->a.page_index =
2325 vino_drvdata->
2326 a.line_size;
2327 vino->a.next_4_desc =
2328 vino->a.start_desc_tbl;
2329 }
2330 }
2331 dprintk("channel A end-of-field "
2332 "interrupt: %04x\n", intr);
2333 } else {
Ralf Baechled203a7e2005-09-06 15:19:37 -07002334 vino_dma_stop(&vino_drvdata->a);
2335 vino_clear_interrupt(&vino_drvdata->a);
2336 vino_drvdata->a.field = 0;
Ladislav Michla637a112005-09-01 15:07:34 +00002337 skip_a = 1;
2338 dprintk("channel A error interrupt: %04x\n",
2339 intr);
Ralf Baechled203a7e2005-09-06 15:19:37 -07002340 }
Ladislav Michla637a112005-09-01 15:07:34 +00002341
2342#ifdef VINO_DEBUG_INT
2343 line_count_2 = vino->a.line_count;
2344 page_index_2 = vino->a.page_index;
2345 field_counter_2 = vino->a.field_counter;
2346 start_desc_tbl_2 = vino->a.start_desc_tbl;
2347 next_4_desc_2 = vino->a.next_4_desc;
2348
2349 printk("intr = %04x, loop = %d, field = %d\n",
2350 intr, loop, vino_drvdata->a.field);
2351 printk("1- line count = %04d, page index = %04d, "
2352 "start = %08x, next = %08x\n"
2353 " fieldc = %d, framec = %d\n",
2354 line_count, page_index, start_desc_tbl,
2355 next_4_desc, field_counter, fc_a);
2356 printk("12-line count = %04d, page index = %04d, "
2357 " start = %08x, next = %08x\n",
2358 line_count_2, page_index_2, start_desc_tbl_2,
2359 next_4_desc_2);
2360
2361 if (done_a)
2362 printk("\n");
2363#endif
Ralf Baechled203a7e2005-09-06 15:19:37 -07002364 }
Ladislav Michla637a112005-09-01 15:07:34 +00002365
2366 if (intr & VINO_INTSTAT_B) {
2367 if (intr & VINO_INTSTAT_B_EOF) {
2368 vino_drvdata->b.field++;
2369 if (vino_drvdata->b.field > 1) {
2370 vino_dma_stop(&vino_drvdata->b);
2371 vino_clear_interrupt(&vino_drvdata->b);
2372 vino_drvdata->b.field = 0;
2373 done_b = 1;
2374 }
2375 dprintk("channel B end-of-field "
2376 "interrupt: %04x\n", intr);
2377 } else {
Ralf Baechled203a7e2005-09-06 15:19:37 -07002378 vino_dma_stop(&vino_drvdata->b);
2379 vino_clear_interrupt(&vino_drvdata->b);
2380 vino_drvdata->b.field = 0;
Ladislav Michla637a112005-09-01 15:07:34 +00002381 skip_b = 1;
2382 dprintk("channel B error interrupt: %04x\n",
2383 intr);
Ralf Baechled203a7e2005-09-06 15:19:37 -07002384 }
Ralf Baechled203a7e2005-09-06 15:19:37 -07002385 }
Ralf Baechled203a7e2005-09-06 15:19:37 -07002386
Ladislav Michla637a112005-09-01 15:07:34 +00002387 /* Always remember to clear interrupt status.
2388 * Disable VINO interrupts while we do this. */
2389 ctrl = vino->control;
2390 vino->control = ctrl & ~(VINO_CTRL_A_INT | VINO_CTRL_B_INT);
2391 vino->intr_status = ~intr;
2392 vino->control = ctrl;
2393
2394 spin_unlock(&vino_drvdata->vino_lock);
2395
2396 if ((!handled_a) && (done_a || skip_a)) {
2397 if (!skip_a) {
2398 do_gettimeofday(&vino_drvdata->
2399 a.int_data.timestamp);
2400 vino_drvdata->a.int_data.frame_counter = fc_a;
2401 }
2402 vino_drvdata->a.int_data.skip = skip_a;
2403
2404 dprintk("channel A %s, interrupt: %d\n",
2405 skip_a ? "skipping frame" : "frame done",
2406 intr);
2407 tasklet_hi_schedule(&vino_tasklet_a);
2408 handled_a = 1;
2409 }
2410
2411 if ((!handled_b) && (done_b || skip_b)) {
2412 if (!skip_b) {
2413 do_gettimeofday(&vino_drvdata->
2414 b.int_data.timestamp);
2415 vino_drvdata->b.int_data.frame_counter = fc_b;
2416 }
2417 vino_drvdata->b.int_data.skip = skip_b;
2418
2419 dprintk("channel B %s, interrupt: %d\n",
2420 skip_b ? "skipping frame" : "frame done",
2421 intr);
2422 tasklet_hi_schedule(&vino_tasklet_b);
2423 handled_b = 1;
2424 }
2425
2426#ifdef VINO_DEBUG_INT
2427 loop++;
2428#endif
2429 spin_lock(&vino_drvdata->vino_lock);
2430 }
Ralf Baechled203a7e2005-09-06 15:19:37 -07002431
2432 spin_unlock(&vino_drvdata->vino_lock);
2433
Ralf Baechled203a7e2005-09-06 15:19:37 -07002434 return IRQ_HANDLED;
2435}
2436
2437/* VINO video input management */
2438
2439static int vino_get_saa7191_input(int input)
2440{
2441 switch (input) {
2442 case VINO_INPUT_COMPOSITE:
2443 return SAA7191_INPUT_COMPOSITE;
2444 case VINO_INPUT_SVIDEO:
2445 return SAA7191_INPUT_SVIDEO;
2446 default:
2447 printk(KERN_ERR "VINO: vino_get_saa7191_input(): "
2448 "invalid input!\n");
2449 return -1;
2450 }
2451}
2452
Ralf Baechled203a7e2005-09-06 15:19:37 -07002453/* execute with input_lock locked */
2454static int vino_is_input_owner(struct vino_channel_settings *vcs)
2455{
2456 switch(vcs->input) {
2457 case VINO_INPUT_COMPOSITE:
2458 case VINO_INPUT_SVIDEO:
2459 return (vino_drvdata->decoder.owner == vcs->channel);
2460 case VINO_INPUT_D1:
2461 return (vino_drvdata->camera.owner == vcs->channel);
2462 default:
2463 return 0;
2464 }
2465}
2466
2467static int vino_acquire_input(struct vino_channel_settings *vcs)
2468{
Ladislav Michla637a112005-09-01 15:07:34 +00002469 unsigned long flags;
Ralf Baechled203a7e2005-09-06 15:19:37 -07002470 int ret = 0;
2471
2472 dprintk("vino_acquire_input():\n");
2473
Ladislav Michla637a112005-09-01 15:07:34 +00002474 spin_lock_irqsave(&vino_drvdata->input_lock, flags);
Ralf Baechled203a7e2005-09-06 15:19:37 -07002475
2476 /* First try D1 and then SAA7191 */
2477 if (vino_drvdata->camera.driver
2478 && (vino_drvdata->camera.owner == VINO_NO_CHANNEL)) {
Jean Delvaree48d3312008-01-27 18:14:48 +01002479 i2c_use_client(vino_drvdata->camera.driver);
Ralf Baechled203a7e2005-09-06 15:19:37 -07002480 vino_drvdata->camera.owner = vcs->channel;
2481 vcs->input = VINO_INPUT_D1;
2482 vcs->data_norm = VINO_DATA_NORM_D1;
2483 } else if (vino_drvdata->decoder.driver
2484 && (vino_drvdata->decoder.owner == VINO_NO_CHANNEL)) {
Hans Verkuilcf4e9482009-02-27 09:05:10 -03002485 int input;
2486 int data_norm;
2487 v4l2_std_id norm;
2488 struct v4l2_routing route = { 0, 0 };
Ralf Baechled203a7e2005-09-06 15:19:37 -07002489
Jean Delvaree48d3312008-01-27 18:14:48 +01002490 i2c_use_client(vino_drvdata->decoder.driver);
Ladislav Michla637a112005-09-01 15:07:34 +00002491 input = VINO_INPUT_COMPOSITE;
2492
Hans Verkuilcf4e9482009-02-27 09:05:10 -03002493 route.input = vino_get_saa7191_input(input);
2494 ret = i2c_decoder_command(VIDIOC_INT_S_VIDEO_ROUTING, &route);
Ladislav Michla637a112005-09-01 15:07:34 +00002495 if (ret) {
2496 ret = -EINVAL;
2497 goto out;
2498 }
2499
2500 spin_unlock_irqrestore(&vino_drvdata->input_lock, flags);
2501
2502 /* Don't hold spinlocks while auto-detecting norm
2503 * as it may take a while... */
2504
Hans Verkuilcf4e9482009-02-27 09:05:10 -03002505 ret = i2c_decoder_command(VIDIOC_QUERYSTD, &norm);
2506 if (!ret) {
2507 for (data_norm = 0; data_norm < 3; data_norm++) {
2508 if (vino_data_norms[data_norm].std & norm)
2509 break;
2510 }
2511 if (data_norm == 3)
2512 data_norm = VINO_DATA_NORM_PAL;
2513 ret = i2c_decoder_command(VIDIOC_S_STD, &norm);
Ladislav Michla637a112005-09-01 15:07:34 +00002514 }
2515
2516 spin_lock_irqsave(&vino_drvdata->input_lock, flags);
2517
2518 if (ret) {
2519 ret = -EINVAL;
2520 goto out;
2521 }
2522
Ralf Baechled203a7e2005-09-06 15:19:37 -07002523 vino_drvdata->decoder.owner = vcs->channel;
Ralf Baechled203a7e2005-09-06 15:19:37 -07002524
Ladislav Michla637a112005-09-01 15:07:34 +00002525 vcs->input = input;
2526 vcs->data_norm = data_norm;
Ralf Baechled203a7e2005-09-06 15:19:37 -07002527 } else {
2528 vcs->input = (vcs->channel == VINO_CHANNEL_A) ?
2529 vino_drvdata->b.input : vino_drvdata->a.input;
2530 vcs->data_norm = (vcs->channel == VINO_CHANNEL_A) ?
2531 vino_drvdata->b.data_norm : vino_drvdata->a.data_norm;
2532 }
2533
2534 if (vcs->input == VINO_INPUT_NONE) {
2535 ret = -ENODEV;
2536 goto out;
2537 }
2538
Ladislav Michla637a112005-09-01 15:07:34 +00002539 vino_set_default_clipping(vcs);
2540 vino_set_default_scaling(vcs);
2541 vino_set_default_framerate(vcs);
Ralf Baechled203a7e2005-09-06 15:19:37 -07002542
2543 dprintk("vino_acquire_input(): %s\n", vino_inputs[vcs->input].name);
2544
2545out:
Ladislav Michla637a112005-09-01 15:07:34 +00002546 spin_unlock_irqrestore(&vino_drvdata->input_lock, flags);
Ralf Baechled203a7e2005-09-06 15:19:37 -07002547
2548 return ret;
2549}
2550
2551static int vino_set_input(struct vino_channel_settings *vcs, int input)
2552{
2553 struct vino_channel_settings *vcs2 = (vcs->channel == VINO_CHANNEL_A) ?
2554 &vino_drvdata->b : &vino_drvdata->a;
Ladislav Michla637a112005-09-01 15:07:34 +00002555 unsigned long flags;
Ralf Baechled203a7e2005-09-06 15:19:37 -07002556 int ret = 0;
2557
2558 dprintk("vino_set_input():\n");
2559
Ladislav Michla637a112005-09-01 15:07:34 +00002560 spin_lock_irqsave(&vino_drvdata->input_lock, flags);
Ralf Baechled203a7e2005-09-06 15:19:37 -07002561
2562 if (vcs->input == input)
2563 goto out;
2564
Ladislav Michla637a112005-09-01 15:07:34 +00002565 switch (input) {
Ralf Baechled203a7e2005-09-06 15:19:37 -07002566 case VINO_INPUT_COMPOSITE:
2567 case VINO_INPUT_SVIDEO:
2568 if (!vino_drvdata->decoder.driver) {
2569 ret = -EINVAL;
2570 goto out;
2571 }
2572
2573 if (vino_drvdata->decoder.owner == VINO_NO_CHANNEL) {
Jean Delvaree48d3312008-01-27 18:14:48 +01002574 i2c_use_client(vino_drvdata->decoder.driver);
Ralf Baechled203a7e2005-09-06 15:19:37 -07002575 vino_drvdata->decoder.owner = vcs->channel;
2576 }
2577
2578 if (vino_drvdata->decoder.owner == vcs->channel) {
Ladislav Michla637a112005-09-01 15:07:34 +00002579 int data_norm;
Hans Verkuilcf4e9482009-02-27 09:05:10 -03002580 v4l2_std_id norm;
2581 struct v4l2_routing route = { 0, 0 };
Ladislav Michla637a112005-09-01 15:07:34 +00002582
Hans Verkuilcf4e9482009-02-27 09:05:10 -03002583 route.input = vino_get_saa7191_input(input);
2584 ret = i2c_decoder_command(VIDIOC_INT_S_VIDEO_ROUTING, &route);
Ladislav Michla637a112005-09-01 15:07:34 +00002585 if (ret) {
2586 vino_drvdata->decoder.owner = VINO_NO_CHANNEL;
2587 ret = -EINVAL;
2588 goto out;
2589 }
2590
2591 spin_unlock_irqrestore(&vino_drvdata->input_lock, flags);
2592
2593 /* Don't hold spinlocks while auto-detecting norm
2594 * as it may take a while... */
2595
Hans Verkuilcf4e9482009-02-27 09:05:10 -03002596 ret = i2c_decoder_command(VIDIOC_QUERYSTD, &norm);
2597 if (!ret) {
2598 for (data_norm = 0; data_norm < 3; data_norm++) {
2599 if (vino_data_norms[data_norm].std & norm)
2600 break;
2601 }
2602 if (data_norm == 3)
2603 data_norm = VINO_DATA_NORM_PAL;
2604 ret = i2c_decoder_command(VIDIOC_S_STD, &norm);
Ladislav Michla637a112005-09-01 15:07:34 +00002605 }
2606
2607 spin_lock_irqsave(&vino_drvdata->input_lock, flags);
2608
2609 if (ret) {
2610 vino_drvdata->decoder.owner = VINO_NO_CHANNEL;
2611 ret = -EINVAL;
2612 goto out;
2613 }
Ralf Baechled203a7e2005-09-06 15:19:37 -07002614
2615 vcs->input = input;
Ladislav Michla637a112005-09-01 15:07:34 +00002616 vcs->data_norm = data_norm;
Ralf Baechled203a7e2005-09-06 15:19:37 -07002617 } else {
Ladislav Michla637a112005-09-01 15:07:34 +00002618 if (input != vcs2->input) {
Ralf Baechled203a7e2005-09-06 15:19:37 -07002619 ret = -EBUSY;
2620 goto out;
2621 }
2622
2623 vcs->input = input;
2624 vcs->data_norm = vcs2->data_norm;
2625 }
2626
2627 if (vino_drvdata->camera.owner == vcs->channel) {
2628 /* Transfer the ownership or release the input */
2629 if (vcs2->input == VINO_INPUT_D1) {
2630 vino_drvdata->camera.owner = vcs2->channel;
2631 } else {
Hans Verkuilcf4e9482009-02-27 09:05:10 -03002632 i2c_release_client(vino_drvdata->camera.driver);
Ralf Baechled203a7e2005-09-06 15:19:37 -07002633 vino_drvdata->camera.owner = VINO_NO_CHANNEL;
2634 }
2635 }
2636 break;
2637 case VINO_INPUT_D1:
2638 if (!vino_drvdata->camera.driver) {
2639 ret = -EINVAL;
2640 goto out;
2641 }
2642
2643 if (vino_drvdata->camera.owner == VINO_NO_CHANNEL) {
Jean Delvaree48d3312008-01-27 18:14:48 +01002644 i2c_use_client(vino_drvdata->camera.driver);
Ralf Baechled203a7e2005-09-06 15:19:37 -07002645 vino_drvdata->camera.owner = vcs->channel;
2646 }
2647
2648 if (vino_drvdata->decoder.owner == vcs->channel) {
2649 /* Transfer the ownership or release the input */
2650 if ((vcs2->input == VINO_INPUT_COMPOSITE) ||
2651 (vcs2->input == VINO_INPUT_SVIDEO)) {
2652 vino_drvdata->decoder.owner = vcs2->channel;
2653 } else {
2654 i2c_release_client(vino_drvdata->
2655 decoder.driver);
2656 vino_drvdata->decoder.owner = VINO_NO_CHANNEL;
2657 }
2658 }
2659
2660 vcs->input = input;
2661 vcs->data_norm = VINO_DATA_NORM_D1;
2662 break;
2663 default:
2664 ret = -EINVAL;
2665 goto out;
2666 }
2667
2668 vino_set_default_clipping(vcs);
Ladislav Michla637a112005-09-01 15:07:34 +00002669 vino_set_default_scaling(vcs);
Ralf Baechled203a7e2005-09-06 15:19:37 -07002670 vino_set_default_framerate(vcs);
2671
2672 dprintk("vino_set_input(): %s\n", vino_inputs[vcs->input].name);
2673
2674out:
Ladislav Michla637a112005-09-01 15:07:34 +00002675 spin_unlock_irqrestore(&vino_drvdata->input_lock, flags);
Ralf Baechled203a7e2005-09-06 15:19:37 -07002676
2677 return ret;
2678}
2679
2680static void vino_release_input(struct vino_channel_settings *vcs)
2681{
2682 struct vino_channel_settings *vcs2 = (vcs->channel == VINO_CHANNEL_A) ?
2683 &vino_drvdata->b : &vino_drvdata->a;
Ladislav Michla637a112005-09-01 15:07:34 +00002684 unsigned long flags;
Ralf Baechled203a7e2005-09-06 15:19:37 -07002685
2686 dprintk("vino_release_input():\n");
2687
Ladislav Michla637a112005-09-01 15:07:34 +00002688 spin_lock_irqsave(&vino_drvdata->input_lock, flags);
Ralf Baechled203a7e2005-09-06 15:19:37 -07002689
2690 /* Release ownership of the channel
2691 * and if the other channel takes input from
2692 * the same source, transfer the ownership */
2693 if (vino_drvdata->camera.owner == vcs->channel) {
2694 if (vcs2->input == VINO_INPUT_D1) {
2695 vino_drvdata->camera.owner = vcs2->channel;
2696 } else {
2697 i2c_release_client(vino_drvdata->camera.driver);
2698 vino_drvdata->camera.owner = VINO_NO_CHANNEL;
2699 }
2700 } else if (vino_drvdata->decoder.owner == vcs->channel) {
2701 if ((vcs2->input == VINO_INPUT_COMPOSITE) ||
2702 (vcs2->input == VINO_INPUT_SVIDEO)) {
2703 vino_drvdata->decoder.owner = vcs2->channel;
2704 } else {
2705 i2c_release_client(vino_drvdata->decoder.driver);
2706 vino_drvdata->decoder.owner = VINO_NO_CHANNEL;
2707 }
2708 }
2709 vcs->input = VINO_INPUT_NONE;
2710
Ladislav Michla637a112005-09-01 15:07:34 +00002711 spin_unlock_irqrestore(&vino_drvdata->input_lock, flags);
Ralf Baechled203a7e2005-09-06 15:19:37 -07002712}
2713
2714/* execute with input_lock locked */
2715static int vino_set_data_norm(struct vino_channel_settings *vcs,
Ladislav Michla637a112005-09-01 15:07:34 +00002716 unsigned int data_norm,
2717 unsigned long *flags)
Ralf Baechled203a7e2005-09-06 15:19:37 -07002718{
Ladislav Michla637a112005-09-01 15:07:34 +00002719 int err = 0;
2720
2721 if (data_norm == vcs->data_norm)
2722 return 0;
Ralf Baechled203a7e2005-09-06 15:19:37 -07002723
2724 switch (vcs->input) {
2725 case VINO_INPUT_D1:
2726 /* only one "norm" supported */
Hans Verkuilcf4e9482009-02-27 09:05:10 -03002727 if (data_norm != VINO_DATA_NORM_D1)
Ralf Baechled203a7e2005-09-06 15:19:37 -07002728 return -EINVAL;
2729 break;
2730 case VINO_INPUT_COMPOSITE:
Ladislav Michla637a112005-09-01 15:07:34 +00002731 case VINO_INPUT_SVIDEO: {
Hans Verkuilcf4e9482009-02-27 09:05:10 -03002732 v4l2_std_id norm;
2733
Ladislav Michla637a112005-09-01 15:07:34 +00002734 if ((data_norm != VINO_DATA_NORM_PAL)
2735 && (data_norm != VINO_DATA_NORM_NTSC)
Hans Verkuilcf4e9482009-02-27 09:05:10 -03002736 && (data_norm != VINO_DATA_NORM_SECAM))
Ladislav Michla637a112005-09-01 15:07:34 +00002737 return -EINVAL;
Ralf Baechled203a7e2005-09-06 15:19:37 -07002738
Ladislav Michla637a112005-09-01 15:07:34 +00002739 spin_unlock_irqrestore(&vino_drvdata->input_lock, *flags);
Ralf Baechled203a7e2005-09-06 15:19:37 -07002740
Ladislav Michla637a112005-09-01 15:07:34 +00002741 /* Don't hold spinlocks while setting norm
2742 * as it may take a while... */
2743
Hans Verkuilcf4e9482009-02-27 09:05:10 -03002744 norm = vino_data_norms[data_norm].std;
2745 err = i2c_decoder_command(VIDIOC_S_STD, &norm);
Ladislav Michla637a112005-09-01 15:07:34 +00002746
2747 spin_lock_irqsave(&vino_drvdata->input_lock, *flags);
2748
2749 if (err)
2750 goto out;
2751
Ralf Baechled203a7e2005-09-06 15:19:37 -07002752 vcs->data_norm = data_norm;
Ladislav Michla637a112005-09-01 15:07:34 +00002753
2754 vino_set_default_clipping(vcs);
2755 vino_set_default_scaling(vcs);
2756 vino_set_default_framerate(vcs);
Ralf Baechled203a7e2005-09-06 15:19:37 -07002757 break;
Ladislav Michla637a112005-09-01 15:07:34 +00002758 }
Ralf Baechled203a7e2005-09-06 15:19:37 -07002759 default:
2760 return -EINVAL;
2761 }
2762
Ladislav Michla637a112005-09-01 15:07:34 +00002763out:
2764 return err;
Ralf Baechled203a7e2005-09-06 15:19:37 -07002765}
2766
2767/* V4L2 helper functions */
2768
2769static int vino_find_data_format(__u32 pixelformat)
2770{
2771 int i;
2772
2773 for (i = 0; i < VINO_DATA_FMT_COUNT; i++) {
2774 if (vino_data_formats[i].pixelformat == pixelformat)
2775 return i;
2776 }
2777
2778 return VINO_DATA_FMT_NONE;
2779}
2780
Hans Verkuilc49cb362009-02-12 10:32:50 -03002781static int vino_int_enum_input(struct vino_channel_settings *vcs, __u32 index)
Ralf Baechled203a7e2005-09-06 15:19:37 -07002782{
2783 int input = VINO_INPUT_NONE;
Ladislav Michla637a112005-09-01 15:07:34 +00002784 unsigned long flags;
Ralf Baechled203a7e2005-09-06 15:19:37 -07002785
Ladislav Michla637a112005-09-01 15:07:34 +00002786 spin_lock_irqsave(&vino_drvdata->input_lock, flags);
Ralf Baechled203a7e2005-09-06 15:19:37 -07002787 if (vino_drvdata->decoder.driver && vino_drvdata->camera.driver) {
2788 switch (index) {
2789 case 0:
2790 input = VINO_INPUT_COMPOSITE;
2791 break;
2792 case 1:
2793 input = VINO_INPUT_SVIDEO;
2794 break;
2795 case 2:
2796 input = VINO_INPUT_D1;
2797 break;
2798 }
2799 } else if (vino_drvdata->decoder.driver) {
2800 switch (index) {
2801 case 0:
2802 input = VINO_INPUT_COMPOSITE;
2803 break;
2804 case 1:
2805 input = VINO_INPUT_SVIDEO;
2806 break;
2807 }
2808 } else if (vino_drvdata->camera.driver) {
2809 switch (index) {
2810 case 0:
2811 input = VINO_INPUT_D1;
2812 break;
2813 }
2814 }
Ladislav Michla637a112005-09-01 15:07:34 +00002815 spin_unlock_irqrestore(&vino_drvdata->input_lock, flags);
Ralf Baechled203a7e2005-09-06 15:19:37 -07002816
2817 return input;
2818}
2819
2820/* execute with input_lock locked */
2821static __u32 vino_find_input_index(struct vino_channel_settings *vcs)
2822{
2823 __u32 index = 0;
2824 // FIXME: detect when no inputs available
2825
2826 if (vino_drvdata->decoder.driver && vino_drvdata->camera.driver) {
2827 switch (vcs->input) {
2828 case VINO_INPUT_COMPOSITE:
2829 index = 0;
2830 break;
2831 case VINO_INPUT_SVIDEO:
2832 index = 1;
2833 break;
2834 case VINO_INPUT_D1:
2835 index = 2;
2836 break;
2837 }
2838 } else if (vino_drvdata->decoder.driver) {
2839 switch (vcs->input) {
2840 case VINO_INPUT_COMPOSITE:
2841 index = 0;
2842 break;
2843 case VINO_INPUT_SVIDEO:
2844 index = 1;
2845 break;
2846 }
2847 } else if (vino_drvdata->camera.driver) {
2848 switch (vcs->input) {
2849 case VINO_INPUT_D1:
2850 index = 0;
2851 break;
2852 }
2853 }
2854
2855 return index;
2856}
2857
2858/* V4L2 ioctls */
2859
Hans Verkuilc49cb362009-02-12 10:32:50 -03002860static int vino_querycap(struct file *file, void *__fh,
2861 struct v4l2_capability *cap)
Ralf Baechled203a7e2005-09-06 15:19:37 -07002862{
2863 memset(cap, 0, sizeof(struct v4l2_capability));
2864
2865 strcpy(cap->driver, vino_driver_name);
2866 strcpy(cap->card, vino_driver_description);
2867 strcpy(cap->bus_info, vino_bus_name);
2868 cap->version = VINO_VERSION_CODE;
2869 cap->capabilities =
2870 V4L2_CAP_VIDEO_CAPTURE |
2871 V4L2_CAP_STREAMING;
2872 // V4L2_CAP_OVERLAY, V4L2_CAP_READWRITE
Hans Verkuilc49cb362009-02-12 10:32:50 -03002873 return 0;
Ralf Baechled203a7e2005-09-06 15:19:37 -07002874}
2875
Hans Verkuilc49cb362009-02-12 10:32:50 -03002876static int vino_enum_input(struct file *file, void *__fh,
Ralf Baechled203a7e2005-09-06 15:19:37 -07002877 struct v4l2_input *i)
2878{
Hans Verkuilc49cb362009-02-12 10:32:50 -03002879 struct vino_channel_settings *vcs = video_drvdata(file);
Ralf Baechled203a7e2005-09-06 15:19:37 -07002880 __u32 index = i->index;
2881 int input;
2882 dprintk("requested index = %d\n", index);
2883
Hans Verkuilc49cb362009-02-12 10:32:50 -03002884 input = vino_int_enum_input(vcs, index);
Ralf Baechled203a7e2005-09-06 15:19:37 -07002885 if (input == VINO_INPUT_NONE)
2886 return -EINVAL;
2887
2888 memset(i, 0, sizeof(struct v4l2_input));
2889
2890 i->index = index;
2891 i->type = V4L2_INPUT_TYPE_CAMERA;
2892 i->std = vino_inputs[input].std;
2893 strcpy(i->name, vino_inputs[input].name);
2894
Hans Verkuilcf4e9482009-02-27 09:05:10 -03002895 if (input == VINO_INPUT_COMPOSITE || input == VINO_INPUT_SVIDEO)
2896 i2c_decoder_command(VIDIOC_INT_G_INPUT_STATUS, &i->status);
Ralf Baechled203a7e2005-09-06 15:19:37 -07002897 return 0;
2898}
2899
Hans Verkuilc49cb362009-02-12 10:32:50 -03002900static int vino_g_input(struct file *file, void *__fh,
Ladislav Michla637a112005-09-01 15:07:34 +00002901 unsigned int *i)
Ralf Baechled203a7e2005-09-06 15:19:37 -07002902{
Hans Verkuilc49cb362009-02-12 10:32:50 -03002903 struct vino_channel_settings *vcs = video_drvdata(file);
Ralf Baechled203a7e2005-09-06 15:19:37 -07002904 __u32 index;
2905 int input;
Ladislav Michla637a112005-09-01 15:07:34 +00002906 unsigned long flags;
Ralf Baechled203a7e2005-09-06 15:19:37 -07002907
Ladislav Michla637a112005-09-01 15:07:34 +00002908 spin_lock_irqsave(&vino_drvdata->input_lock, flags);
Ralf Baechled203a7e2005-09-06 15:19:37 -07002909 input = vcs->input;
2910 index = vino_find_input_index(vcs);
Ladislav Michla637a112005-09-01 15:07:34 +00002911 spin_unlock_irqrestore(&vino_drvdata->input_lock, flags);
Ralf Baechled203a7e2005-09-06 15:19:37 -07002912
2913 dprintk("input = %d\n", input);
2914
2915 if (input == VINO_INPUT_NONE) {
2916 return -EINVAL;
2917 }
2918
Ladislav Michla637a112005-09-01 15:07:34 +00002919 *i = index;
Ralf Baechled203a7e2005-09-06 15:19:37 -07002920
2921 return 0;
2922}
2923
Hans Verkuilc49cb362009-02-12 10:32:50 -03002924static int vino_s_input(struct file *file, void *__fh,
2925 unsigned int i)
Ralf Baechled203a7e2005-09-06 15:19:37 -07002926{
Hans Verkuilc49cb362009-02-12 10:32:50 -03002927 struct vino_channel_settings *vcs = video_drvdata(file);
Ralf Baechled203a7e2005-09-06 15:19:37 -07002928 int input;
Hans Verkuilc49cb362009-02-12 10:32:50 -03002929 dprintk("requested input = %d\n", i);
Ralf Baechled203a7e2005-09-06 15:19:37 -07002930
Hans Verkuilc49cb362009-02-12 10:32:50 -03002931 input = vino_int_enum_input(vcs, i);
Ralf Baechled203a7e2005-09-06 15:19:37 -07002932 if (input == VINO_INPUT_NONE)
2933 return -EINVAL;
2934
2935 return vino_set_input(vcs, input);
2936}
2937
Hans Verkuilc49cb362009-02-12 10:32:50 -03002938static int vino_querystd(struct file *file, void *__fh,
Ladislav Michla637a112005-09-01 15:07:34 +00002939 v4l2_std_id *std)
2940{
Hans Verkuilc49cb362009-02-12 10:32:50 -03002941 struct vino_channel_settings *vcs = video_drvdata(file);
Ladislav Michla637a112005-09-01 15:07:34 +00002942 unsigned long flags;
2943 int err = 0;
2944
2945 spin_lock_irqsave(&vino_drvdata->input_lock, flags);
2946
2947 switch (vcs->input) {
2948 case VINO_INPUT_D1:
2949 *std = vino_inputs[vcs->input].std;
2950 break;
2951 case VINO_INPUT_COMPOSITE:
2952 case VINO_INPUT_SVIDEO: {
Hans Verkuilcf4e9482009-02-27 09:05:10 -03002953 i2c_decoder_command(VIDIOC_QUERYSTD, std);
Ladislav Michla637a112005-09-01 15:07:34 +00002954 break;
2955 }
2956 default:
2957 err = -EINVAL;
2958 }
2959
2960 spin_unlock_irqrestore(&vino_drvdata->input_lock, flags);
2961
2962 return err;
2963}
2964
Hans Verkuilc49cb362009-02-12 10:32:50 -03002965static int vino_g_std(struct file *file, void *__fh,
Ralf Baechled203a7e2005-09-06 15:19:37 -07002966 v4l2_std_id *std)
2967{
Hans Verkuilc49cb362009-02-12 10:32:50 -03002968 struct vino_channel_settings *vcs = video_drvdata(file);
Ladislav Michla637a112005-09-01 15:07:34 +00002969 unsigned long flags;
2970
2971 spin_lock_irqsave(&vino_drvdata->input_lock, flags);
2972
Ralf Baechled203a7e2005-09-06 15:19:37 -07002973 *std = vino_data_norms[vcs->data_norm].std;
Ladislav Michla637a112005-09-01 15:07:34 +00002974 dprintk("current standard = %d\n", vcs->data_norm);
2975
2976 spin_unlock_irqrestore(&vino_drvdata->input_lock, flags);
Ralf Baechled203a7e2005-09-06 15:19:37 -07002977
2978 return 0;
2979}
2980
Hans Verkuilc49cb362009-02-12 10:32:50 -03002981static int vino_s_std(struct file *file, void *__fh,
Ralf Baechled203a7e2005-09-06 15:19:37 -07002982 v4l2_std_id *std)
2983{
Hans Verkuilc49cb362009-02-12 10:32:50 -03002984 struct vino_channel_settings *vcs = video_drvdata(file);
Ladislav Michla637a112005-09-01 15:07:34 +00002985 unsigned long flags;
Ralf Baechled203a7e2005-09-06 15:19:37 -07002986 int ret = 0;
2987
Ladislav Michla637a112005-09-01 15:07:34 +00002988 spin_lock_irqsave(&vino_drvdata->input_lock, flags);
2989
2990 if (!vino_is_input_owner(vcs)) {
2991 ret = -EBUSY;
2992 goto out;
2993 }
Ralf Baechled203a7e2005-09-06 15:19:37 -07002994
2995 /* check if the standard is valid for the current input */
Ladislav Michla637a112005-09-01 15:07:34 +00002996 if ((*std) & vino_inputs[vcs->input].std) {
Ralf Baechled203a7e2005-09-06 15:19:37 -07002997 dprintk("standard accepted\n");
2998
2999 /* change the video norm for SAA7191
3000 * and accept NTSC for D1 (do nothing) */
3001
3002 if (vcs->input == VINO_INPUT_D1)
3003 goto out;
3004
Hans Verkuilcf4e9482009-02-27 09:05:10 -03003005 if ((*std) & V4L2_STD_PAL) {
Ladislav Michla637a112005-09-01 15:07:34 +00003006 ret = vino_set_data_norm(vcs, VINO_DATA_NORM_PAL,
3007 &flags);
Ralf Baechled203a7e2005-09-06 15:19:37 -07003008 } else if ((*std) & V4L2_STD_NTSC) {
Ladislav Michla637a112005-09-01 15:07:34 +00003009 ret = vino_set_data_norm(vcs, VINO_DATA_NORM_NTSC,
3010 &flags);
Ralf Baechled203a7e2005-09-06 15:19:37 -07003011 } else if ((*std) & V4L2_STD_SECAM) {
Ladislav Michla637a112005-09-01 15:07:34 +00003012 ret = vino_set_data_norm(vcs, VINO_DATA_NORM_SECAM,
3013 &flags);
Ralf Baechled203a7e2005-09-06 15:19:37 -07003014 } else {
3015 ret = -EINVAL;
3016 }
Ladislav Michla637a112005-09-01 15:07:34 +00003017
3018 if (ret) {
3019 ret = -EINVAL;
3020 }
Ralf Baechled203a7e2005-09-06 15:19:37 -07003021 } else {
3022 ret = -EINVAL;
3023 }
3024
3025out:
Ladislav Michla637a112005-09-01 15:07:34 +00003026 spin_unlock_irqrestore(&vino_drvdata->input_lock, flags);
Ralf Baechled203a7e2005-09-06 15:19:37 -07003027
3028 return ret;
3029}
3030
Hans Verkuilc49cb362009-02-12 10:32:50 -03003031static int vino_enum_fmt_vid_cap(struct file *file, void *__fh,
Ralf Baechled203a7e2005-09-06 15:19:37 -07003032 struct v4l2_fmtdesc *fd)
3033{
3034 enum v4l2_buf_type type = fd->type;
3035 int index = fd->index;
Hans Verkuilc49cb362009-02-12 10:32:50 -03003036
Ralf Baechled203a7e2005-09-06 15:19:37 -07003037 dprintk("format index = %d\n", index);
3038
Hans Verkuilc49cb362009-02-12 10:32:50 -03003039 if ((fd->index < 0) ||
3040 (fd->index >= VINO_DATA_FMT_COUNT))
Ralf Baechled203a7e2005-09-06 15:19:37 -07003041 return -EINVAL;
Hans Verkuilc49cb362009-02-12 10:32:50 -03003042 dprintk("format name = %s\n",
3043 vino_data_formats[index].description);
Ralf Baechled203a7e2005-09-06 15:19:37 -07003044
Hans Verkuilc49cb362009-02-12 10:32:50 -03003045 memset(fd, 0, sizeof(struct v4l2_fmtdesc));
3046 fd->index = index;
3047 fd->type = type;
3048 fd->pixelformat = vino_data_formats[index].pixelformat;
3049 strcpy(fd->description, vino_data_formats[index].description);
Ralf Baechled203a7e2005-09-06 15:19:37 -07003050 return 0;
3051}
3052
Hans Verkuilc49cb362009-02-12 10:32:50 -03003053static int vino_try_fmt_vid_cap(struct file *file, void *__fh,
Ralf Baechled203a7e2005-09-06 15:19:37 -07003054 struct v4l2_format *f)
3055{
Hans Verkuilc49cb362009-02-12 10:32:50 -03003056 struct vino_channel_settings *vcs = video_drvdata(file);
Ralf Baechled203a7e2005-09-06 15:19:37 -07003057 struct vino_channel_settings tempvcs;
Ladislav Michla637a112005-09-01 15:07:34 +00003058 unsigned long flags;
Hans Verkuilc49cb362009-02-12 10:32:50 -03003059 struct v4l2_pix_format *pf = &f->fmt.pix;
Ralf Baechled203a7e2005-09-06 15:19:37 -07003060
Hans Verkuilc49cb362009-02-12 10:32:50 -03003061 dprintk("requested: w = %d, h = %d\n",
3062 pf->width, pf->height);
Ralf Baechled203a7e2005-09-06 15:19:37 -07003063
Hans Verkuilc49cb362009-02-12 10:32:50 -03003064 spin_lock_irqsave(&vino_drvdata->input_lock, flags);
3065 memcpy(&tempvcs, vcs, sizeof(struct vino_channel_settings));
3066 spin_unlock_irqrestore(&vino_drvdata->input_lock, flags);
Ralf Baechled203a7e2005-09-06 15:19:37 -07003067
Hans Verkuilc49cb362009-02-12 10:32:50 -03003068 tempvcs.data_format = vino_find_data_format(pf->pixelformat);
3069 if (tempvcs.data_format == VINO_DATA_FMT_NONE) {
3070 tempvcs.data_format = VINO_DATA_FMT_GREY;
Ralf Baechled203a7e2005-09-06 15:19:37 -07003071 pf->pixelformat =
Hans Verkuilc49cb362009-02-12 10:32:50 -03003072 vino_data_formats[tempvcs.data_format].
3073 pixelformat;
Ralf Baechled203a7e2005-09-06 15:19:37 -07003074 }
3075
Hans Verkuilc49cb362009-02-12 10:32:50 -03003076 /* data format must be set before clipping/scaling */
3077 vino_set_scaling(&tempvcs, pf->width, pf->height);
3078
3079 dprintk("data format = %s\n",
3080 vino_data_formats[tempvcs.data_format].description);
3081
3082 pf->width = (tempvcs.clipping.right - tempvcs.clipping.left) /
3083 tempvcs.decimation;
3084 pf->height = (tempvcs.clipping.bottom - tempvcs.clipping.top) /
3085 tempvcs.decimation;
3086
3087 pf->field = V4L2_FIELD_INTERLACED;
3088 pf->bytesperline = tempvcs.line_size;
3089 pf->sizeimage = tempvcs.line_size *
3090 (tempvcs.clipping.bottom - tempvcs.clipping.top) /
3091 tempvcs.decimation;
3092 pf->colorspace =
3093 vino_data_formats[tempvcs.data_format].colorspace;
3094
3095 pf->priv = 0;
Ralf Baechled203a7e2005-09-06 15:19:37 -07003096 return 0;
3097}
3098
Hans Verkuilc49cb362009-02-12 10:32:50 -03003099static int vino_g_fmt_vid_cap(struct file *file, void *__fh,
Ralf Baechled203a7e2005-09-06 15:19:37 -07003100 struct v4l2_format *f)
3101{
Hans Verkuilc49cb362009-02-12 10:32:50 -03003102 struct vino_channel_settings *vcs = video_drvdata(file);
3103 unsigned long flags;
3104 struct v4l2_pix_format *pf = &f->fmt.pix;
3105
3106 spin_lock_irqsave(&vino_drvdata->input_lock, flags);
3107
3108 pf->width = (vcs->clipping.right - vcs->clipping.left) /
3109 vcs->decimation;
3110 pf->height = (vcs->clipping.bottom - vcs->clipping.top) /
3111 vcs->decimation;
3112 pf->pixelformat =
3113 vino_data_formats[vcs->data_format].pixelformat;
3114
3115 pf->field = V4L2_FIELD_INTERLACED;
3116 pf->bytesperline = vcs->line_size;
3117 pf->sizeimage = vcs->line_size *
3118 (vcs->clipping.bottom - vcs->clipping.top) /
3119 vcs->decimation;
3120 pf->colorspace =
3121 vino_data_formats[vcs->data_format].colorspace;
3122
3123 pf->priv = 0;
3124
3125 spin_unlock_irqrestore(&vino_drvdata->input_lock, flags);
3126 return 0;
3127}
3128
3129static int vino_s_fmt_vid_cap(struct file *file, void *__fh,
3130 struct v4l2_format *f)
3131{
3132 struct vino_channel_settings *vcs = video_drvdata(file);
Ralf Baechled203a7e2005-09-06 15:19:37 -07003133 int data_format;
Ladislav Michla637a112005-09-01 15:07:34 +00003134 unsigned long flags;
Hans Verkuilc49cb362009-02-12 10:32:50 -03003135 struct v4l2_pix_format *pf = &f->fmt.pix;
Ralf Baechled203a7e2005-09-06 15:19:37 -07003136
Hans Verkuilc49cb362009-02-12 10:32:50 -03003137 spin_lock_irqsave(&vino_drvdata->input_lock, flags);
Ralf Baechled203a7e2005-09-06 15:19:37 -07003138
Hans Verkuilc49cb362009-02-12 10:32:50 -03003139 data_format = vino_find_data_format(pf->pixelformat);
Ralf Baechled203a7e2005-09-06 15:19:37 -07003140
Hans Verkuilc49cb362009-02-12 10:32:50 -03003141 if (data_format == VINO_DATA_FMT_NONE) {
3142 vcs->data_format = VINO_DATA_FMT_GREY;
3143 pf->pixelformat =
3144 vino_data_formats[vcs->data_format].
3145 pixelformat;
3146 } else {
3147 vcs->data_format = data_format;
Ralf Baechled203a7e2005-09-06 15:19:37 -07003148 }
3149
Hans Verkuilc49cb362009-02-12 10:32:50 -03003150 /* data format must be set before clipping/scaling */
3151 vino_set_scaling(vcs, pf->width, pf->height);
3152
3153 dprintk("data format = %s\n",
3154 vino_data_formats[vcs->data_format].description);
3155
3156 pf->width = vcs->clipping.right - vcs->clipping.left;
3157 pf->height = vcs->clipping.bottom - vcs->clipping.top;
3158
3159 pf->field = V4L2_FIELD_INTERLACED;
3160 pf->bytesperline = vcs->line_size;
3161 pf->sizeimage = vcs->line_size *
3162 (vcs->clipping.bottom - vcs->clipping.top) /
3163 vcs->decimation;
3164 pf->colorspace =
3165 vino_data_formats[vcs->data_format].colorspace;
3166
3167 pf->priv = 0;
3168
3169 spin_unlock_irqrestore(&vino_drvdata->input_lock, flags);
Ralf Baechled203a7e2005-09-06 15:19:37 -07003170 return 0;
3171}
3172
Hans Verkuilc49cb362009-02-12 10:32:50 -03003173static int vino_cropcap(struct file *file, void *__fh,
Ralf Baechled203a7e2005-09-06 15:19:37 -07003174 struct v4l2_cropcap *ccap)
3175{
Hans Verkuilc49cb362009-02-12 10:32:50 -03003176 struct vino_channel_settings *vcs = video_drvdata(file);
Ralf Baechled203a7e2005-09-06 15:19:37 -07003177 const struct vino_data_norm *norm;
Ladislav Michla637a112005-09-01 15:07:34 +00003178 unsigned long flags;
Ralf Baechled203a7e2005-09-06 15:19:37 -07003179
3180 switch (ccap->type) {
3181 case V4L2_BUF_TYPE_VIDEO_CAPTURE:
Ladislav Michla637a112005-09-01 15:07:34 +00003182 spin_lock_irqsave(&vino_drvdata->input_lock, flags);
3183
Ralf Baechled203a7e2005-09-06 15:19:37 -07003184 norm = &vino_data_norms[vcs->data_norm];
Ladislav Michla637a112005-09-01 15:07:34 +00003185
3186 spin_unlock_irqrestore(&vino_drvdata->input_lock, flags);
Ralf Baechled203a7e2005-09-06 15:19:37 -07003187
3188 ccap->bounds.left = 0;
3189 ccap->bounds.top = 0;
3190 ccap->bounds.width = norm->width;
3191 ccap->bounds.height = norm->height;
3192 memcpy(&ccap->defrect, &ccap->bounds,
3193 sizeof(struct v4l2_rect));
3194
3195 ccap->pixelaspect.numerator = 1;
3196 ccap->pixelaspect.denominator = 1;
3197 break;
3198 case V4L2_BUF_TYPE_VIDEO_OVERLAY:
3199 default:
3200 return -EINVAL;
3201 }
3202
3203 return 0;
3204}
3205
Hans Verkuilc49cb362009-02-12 10:32:50 -03003206static int vino_g_crop(struct file *file, void *__fh,
Ralf Baechled203a7e2005-09-06 15:19:37 -07003207 struct v4l2_crop *c)
3208{
Hans Verkuilc49cb362009-02-12 10:32:50 -03003209 struct vino_channel_settings *vcs = video_drvdata(file);
Ladislav Michla637a112005-09-01 15:07:34 +00003210 unsigned long flags;
3211
Ralf Baechled203a7e2005-09-06 15:19:37 -07003212 switch (c->type) {
3213 case V4L2_BUF_TYPE_VIDEO_CAPTURE:
Ladislav Michla637a112005-09-01 15:07:34 +00003214 spin_lock_irqsave(&vino_drvdata->input_lock, flags);
Ralf Baechled203a7e2005-09-06 15:19:37 -07003215
3216 c->c.left = vcs->clipping.left;
3217 c->c.top = vcs->clipping.top;
3218 c->c.width = vcs->clipping.right - vcs->clipping.left;
3219 c->c.height = vcs->clipping.bottom - vcs->clipping.top;
3220
Ladislav Michla637a112005-09-01 15:07:34 +00003221 spin_unlock_irqrestore(&vino_drvdata->input_lock, flags);
Ralf Baechled203a7e2005-09-06 15:19:37 -07003222 break;
3223 case V4L2_BUF_TYPE_VIDEO_OVERLAY:
3224 default:
3225 return -EINVAL;
3226 }
3227
3228 return 0;
3229}
3230
Hans Verkuilc49cb362009-02-12 10:32:50 -03003231static int vino_s_crop(struct file *file, void *__fh,
Ralf Baechled203a7e2005-09-06 15:19:37 -07003232 struct v4l2_crop *c)
3233{
Hans Verkuilc49cb362009-02-12 10:32:50 -03003234 struct vino_channel_settings *vcs = video_drvdata(file);
Ladislav Michla637a112005-09-01 15:07:34 +00003235 unsigned long flags;
3236
Ralf Baechled203a7e2005-09-06 15:19:37 -07003237 switch (c->type) {
3238 case V4L2_BUF_TYPE_VIDEO_CAPTURE:
Ladislav Michla637a112005-09-01 15:07:34 +00003239 spin_lock_irqsave(&vino_drvdata->input_lock, flags);
Ralf Baechled203a7e2005-09-06 15:19:37 -07003240
Ralf Baechled203a7e2005-09-06 15:19:37 -07003241 vino_set_clipping(vcs, c->c.left, c->c.top,
3242 c->c.width, c->c.height);
3243
Ladislav Michla637a112005-09-01 15:07:34 +00003244 spin_unlock_irqrestore(&vino_drvdata->input_lock, flags);
Ralf Baechled203a7e2005-09-06 15:19:37 -07003245 break;
3246 case V4L2_BUF_TYPE_VIDEO_OVERLAY:
3247 default:
3248 return -EINVAL;
3249 }
3250
3251 return 0;
3252}
3253
Hans Verkuilc49cb362009-02-12 10:32:50 -03003254static int vino_g_parm(struct file *file, void *__fh,
Ralf Baechled203a7e2005-09-06 15:19:37 -07003255 struct v4l2_streamparm *sp)
3256{
Hans Verkuilc49cb362009-02-12 10:32:50 -03003257 struct vino_channel_settings *vcs = video_drvdata(file);
Ladislav Michla637a112005-09-01 15:07:34 +00003258 unsigned long flags;
3259
Ralf Baechled203a7e2005-09-06 15:19:37 -07003260 switch (sp->type) {
3261 case V4L2_BUF_TYPE_VIDEO_CAPTURE: {
3262 struct v4l2_captureparm *cp = &sp->parm.capture;
3263 memset(cp, 0, sizeof(struct v4l2_captureparm));
3264
3265 cp->capability = V4L2_CAP_TIMEPERFRAME;
3266 cp->timeperframe.numerator = 1;
3267
Ladislav Michla637a112005-09-01 15:07:34 +00003268 spin_lock_irqsave(&vino_drvdata->input_lock, flags);
3269
Ralf Baechled203a7e2005-09-06 15:19:37 -07003270 cp->timeperframe.denominator = vcs->fps;
Ladislav Michla637a112005-09-01 15:07:34 +00003271
3272 spin_unlock_irqrestore(&vino_drvdata->input_lock, flags);
Ralf Baechled203a7e2005-09-06 15:19:37 -07003273
3274 // TODO: cp->readbuffers = xxx;
3275 break;
3276 }
3277 case V4L2_BUF_TYPE_VIDEO_OVERLAY:
3278 default:
3279 return -EINVAL;
3280 }
3281
3282 return 0;
3283}
3284
Hans Verkuilc49cb362009-02-12 10:32:50 -03003285static int vino_s_parm(struct file *file, void *__fh,
Ralf Baechled203a7e2005-09-06 15:19:37 -07003286 struct v4l2_streamparm *sp)
3287{
Hans Verkuilc49cb362009-02-12 10:32:50 -03003288 struct vino_channel_settings *vcs = video_drvdata(file);
Ladislav Michla637a112005-09-01 15:07:34 +00003289 unsigned long flags;
3290
Ralf Baechled203a7e2005-09-06 15:19:37 -07003291 switch (sp->type) {
3292 case V4L2_BUF_TYPE_VIDEO_CAPTURE: {
3293 struct v4l2_captureparm *cp = &sp->parm.capture;
3294
Ladislav Michla637a112005-09-01 15:07:34 +00003295 spin_lock_irqsave(&vino_drvdata->input_lock, flags);
Ralf Baechled203a7e2005-09-06 15:19:37 -07003296
3297 if ((cp->timeperframe.numerator == 0) ||
3298 (cp->timeperframe.denominator == 0)) {
3299 /* reset framerate */
3300 vino_set_default_framerate(vcs);
3301 } else {
3302 vino_set_framerate(vcs, cp->timeperframe.denominator /
3303 cp->timeperframe.numerator);
3304 }
Ladislav Michla637a112005-09-01 15:07:34 +00003305
3306 spin_unlock_irqrestore(&vino_drvdata->input_lock, flags);
Ralf Baechled203a7e2005-09-06 15:19:37 -07003307
3308 // TODO: set buffers according to cp->readbuffers
3309 break;
3310 }
3311 case V4L2_BUF_TYPE_VIDEO_OVERLAY:
3312 default:
3313 return -EINVAL;
3314 }
3315
3316 return 0;
3317}
3318
Hans Verkuilc49cb362009-02-12 10:32:50 -03003319static int vino_reqbufs(struct file *file, void *__fh,
Ralf Baechled203a7e2005-09-06 15:19:37 -07003320 struct v4l2_requestbuffers *rb)
3321{
Hans Verkuilc49cb362009-02-12 10:32:50 -03003322 struct vino_channel_settings *vcs = video_drvdata(file);
Ralf Baechled203a7e2005-09-06 15:19:37 -07003323 if (vcs->reading)
3324 return -EBUSY;
3325
3326 switch (rb->type) {
3327 case V4L2_BUF_TYPE_VIDEO_CAPTURE: {
3328 // TODO: check queue type
3329 if (rb->memory != V4L2_MEMORY_MMAP) {
3330 dprintk("type not mmap\n");
3331 return -EINVAL;
3332 }
3333
Ralf Baechled203a7e2005-09-06 15:19:37 -07003334 dprintk("count = %d\n", rb->count);
3335 if (rb->count > 0) {
Ladislav Michla637a112005-09-01 15:07:34 +00003336 if (vino_is_capturing(vcs)) {
3337 dprintk("busy, capturing\n");
3338 return -EBUSY;
3339 }
3340
Ralf Baechled203a7e2005-09-06 15:19:37 -07003341 if (vino_queue_has_mapped_buffers(&vcs->fb_queue)) {
3342 dprintk("busy, buffers still mapped\n");
3343 return -EBUSY;
3344 } else {
Ladislav Michla637a112005-09-01 15:07:34 +00003345 vcs->streaming = 0;
Ralf Baechled203a7e2005-09-06 15:19:37 -07003346 vino_queue_free(&vcs->fb_queue);
3347 vino_queue_init(&vcs->fb_queue, &rb->count);
3348 }
3349 } else {
Ladislav Michla637a112005-09-01 15:07:34 +00003350 vcs->streaming = 0;
Ralf Baechled203a7e2005-09-06 15:19:37 -07003351 vino_capture_stop(vcs);
3352 vino_queue_free(&vcs->fb_queue);
3353 }
3354 break;
3355 }
3356 case V4L2_BUF_TYPE_VIDEO_OVERLAY:
3357 default:
3358 return -EINVAL;
3359 }
3360
3361 return 0;
3362}
3363
3364static void vino_v4l2_get_buffer_status(struct vino_channel_settings *vcs,
3365 struct vino_framebuffer *fb,
3366 struct v4l2_buffer *b)
3367{
3368 if (vino_queue_outgoing_contains(&vcs->fb_queue,
3369 fb->id)) {
3370 b->flags &= ~V4L2_BUF_FLAG_QUEUED;
3371 b->flags |= V4L2_BUF_FLAG_DONE;
3372 } else if (vino_queue_incoming_contains(&vcs->fb_queue,
3373 fb->id)) {
3374 b->flags &= ~V4L2_BUF_FLAG_DONE;
3375 b->flags |= V4L2_BUF_FLAG_QUEUED;
3376 } else {
3377 b->flags &= ~(V4L2_BUF_FLAG_DONE |
3378 V4L2_BUF_FLAG_QUEUED);
3379 }
3380
3381 b->flags &= ~(V4L2_BUF_FLAG_TIMECODE);
3382
3383 if (fb->map_count > 0)
3384 b->flags |= V4L2_BUF_FLAG_MAPPED;
3385
3386 b->index = fb->id;
3387 b->memory = (vcs->fb_queue.type == VINO_MEMORY_MMAP) ?
3388 V4L2_MEMORY_MMAP : V4L2_MEMORY_USERPTR;
3389 b->m.offset = fb->offset;
3390 b->bytesused = fb->data_size;
3391 b->length = fb->size;
3392 b->field = V4L2_FIELD_INTERLACED;
3393 b->sequence = fb->frame_counter;
3394 memcpy(&b->timestamp, &fb->timestamp,
3395 sizeof(struct timeval));
3396 // b->input ?
3397
3398 dprintk("buffer %d: length = %d, bytesused = %d, offset = %d\n",
3399 fb->id, fb->size, fb->data_size, fb->offset);
3400}
3401
Hans Verkuilc49cb362009-02-12 10:32:50 -03003402static int vino_querybuf(struct file *file, void *__fh,
Ralf Baechled203a7e2005-09-06 15:19:37 -07003403 struct v4l2_buffer *b)
3404{
Hans Verkuilc49cb362009-02-12 10:32:50 -03003405 struct vino_channel_settings *vcs = video_drvdata(file);
Ralf Baechled203a7e2005-09-06 15:19:37 -07003406 if (vcs->reading)
3407 return -EBUSY;
3408
3409 switch (b->type) {
3410 case V4L2_BUF_TYPE_VIDEO_CAPTURE: {
3411 struct vino_framebuffer *fb;
3412
3413 // TODO: check queue type
3414 if (b->index >= vino_queue_get_length(&vcs->fb_queue)) {
3415 dprintk("invalid index = %d\n",
3416 b->index);
3417 return -EINVAL;
3418 }
3419
3420 fb = vino_queue_get_buffer(&vcs->fb_queue,
3421 b->index);
3422 if (fb == NULL) {
3423 dprintk("vino_queue_get_buffer() failed");
3424 return -EINVAL;
3425 }
3426
3427 vino_v4l2_get_buffer_status(vcs, fb, b);
3428 break;
3429 }
3430 case V4L2_BUF_TYPE_VIDEO_OVERLAY:
3431 default:
3432 return -EINVAL;
3433 }
3434
3435 return 0;
3436}
3437
Hans Verkuilc49cb362009-02-12 10:32:50 -03003438static int vino_qbuf(struct file *file, void *__fh,
Ralf Baechled203a7e2005-09-06 15:19:37 -07003439 struct v4l2_buffer *b)
3440{
Hans Verkuilc49cb362009-02-12 10:32:50 -03003441 struct vino_channel_settings *vcs = video_drvdata(file);
Ralf Baechled203a7e2005-09-06 15:19:37 -07003442 if (vcs->reading)
3443 return -EBUSY;
3444
3445 switch (b->type) {
3446 case V4L2_BUF_TYPE_VIDEO_CAPTURE: {
3447 struct vino_framebuffer *fb;
3448 int ret;
3449
3450 // TODO: check queue type
3451 if (b->memory != V4L2_MEMORY_MMAP) {
3452 dprintk("type not mmap\n");
3453 return -EINVAL;
3454 }
3455
3456 fb = vino_capture_enqueue(vcs, b->index);
3457 if (fb == NULL)
3458 return -EINVAL;
3459
3460 vino_v4l2_get_buffer_status(vcs, fb, b);
3461
3462 if (vcs->streaming) {
3463 ret = vino_capture_next(vcs, 1);
3464 if (ret)
3465 return ret;
3466 }
3467 break;
3468 }
3469 case V4L2_BUF_TYPE_VIDEO_OVERLAY:
3470 default:
3471 return -EINVAL;
3472 }
3473
3474 return 0;
3475}
3476
Hans Verkuilc49cb362009-02-12 10:32:50 -03003477static int vino_dqbuf(struct file *file, void *__fh,
3478 struct v4l2_buffer *b)
Ralf Baechled203a7e2005-09-06 15:19:37 -07003479{
Hans Verkuilc49cb362009-02-12 10:32:50 -03003480 struct vino_channel_settings *vcs = video_drvdata(file);
3481 unsigned int nonblocking = file->f_flags & O_NONBLOCK;
Ralf Baechled203a7e2005-09-06 15:19:37 -07003482 if (vcs->reading)
3483 return -EBUSY;
3484
3485 switch (b->type) {
3486 case V4L2_BUF_TYPE_VIDEO_CAPTURE: {
3487 struct vino_framebuffer *fb;
3488 unsigned int incoming, outgoing;
3489 int err;
3490
3491 // TODO: check queue type
3492
3493 err = vino_queue_get_incoming(&vcs->fb_queue, &incoming);
3494 if (err) {
3495 dprintk("vino_queue_get_incoming() failed\n");
Ladislav Michla637a112005-09-01 15:07:34 +00003496 return -EINVAL;
Ralf Baechled203a7e2005-09-06 15:19:37 -07003497 }
3498 err = vino_queue_get_outgoing(&vcs->fb_queue, &outgoing);
3499 if (err) {
3500 dprintk("vino_queue_get_outgoing() failed\n");
Ladislav Michla637a112005-09-01 15:07:34 +00003501 return -EINVAL;
Ralf Baechled203a7e2005-09-06 15:19:37 -07003502 }
3503
3504 dprintk("incoming = %d, outgoing = %d\n", incoming, outgoing);
3505
3506 if (outgoing == 0) {
3507 if (incoming == 0) {
3508 dprintk("no incoming or outgoing buffers\n");
3509 return -EINVAL;
3510 }
3511 if (nonblocking) {
3512 dprintk("non-blocking I/O was selected and "
3513 "there are no buffers to dequeue\n");
3514 return -EAGAIN;
3515 }
3516
3517 err = vino_wait_for_frame(vcs);
3518 if (err) {
3519 err = vino_wait_for_frame(vcs);
3520 if (err) {
Ladislav Michla637a112005-09-01 15:07:34 +00003521 /* interrupted or
3522 * no frames captured because
3523 * of frame skipping */
3524 // vino_capture_failed(vcs);
Ralf Baechled203a7e2005-09-06 15:19:37 -07003525 return -EIO;
3526 }
3527 }
3528 }
3529
3530 fb = vino_queue_remove(&vcs->fb_queue, &b->index);
3531 if (fb == NULL) {
3532 dprintk("vino_queue_remove() failed\n");
3533 return -EINVAL;
3534 }
3535
3536 err = vino_check_buffer(vcs, fb);
Ladislav Michla637a112005-09-01 15:07:34 +00003537
3538 vino_v4l2_get_buffer_status(vcs, fb, b);
3539
Ralf Baechled203a7e2005-09-06 15:19:37 -07003540 if (err)
3541 return -EIO;
3542
Ralf Baechled203a7e2005-09-06 15:19:37 -07003543 break;
3544 }
3545 case V4L2_BUF_TYPE_VIDEO_OVERLAY:
3546 default:
3547 return -EINVAL;
3548 }
3549
3550 return 0;
3551}
3552
Hans Verkuilc49cb362009-02-12 10:32:50 -03003553static int vino_streamon(struct file *file, void *__fh,
3554 enum v4l2_buf_type i)
Ralf Baechled203a7e2005-09-06 15:19:37 -07003555{
Hans Verkuilc49cb362009-02-12 10:32:50 -03003556 struct vino_channel_settings *vcs = video_drvdata(file);
Ralf Baechled203a7e2005-09-06 15:19:37 -07003557 unsigned int incoming;
3558 int ret;
3559 if (vcs->reading)
3560 return -EBUSY;
3561
3562 if (vcs->streaming)
3563 return 0;
3564
3565 // TODO: check queue type
3566
3567 if (vino_queue_get_length(&vcs->fb_queue) < 1) {
3568 dprintk("no buffers allocated\n");
3569 return -EINVAL;
3570 }
3571
3572 ret = vino_queue_get_incoming(&vcs->fb_queue, &incoming);
3573 if (ret) {
3574 dprintk("vino_queue_get_incoming() failed\n");
3575 return -EINVAL;
3576 }
3577
3578 vcs->streaming = 1;
3579
3580 if (incoming > 0) {
3581 ret = vino_capture_next(vcs, 1);
3582 if (ret) {
3583 vcs->streaming = 0;
3584
3585 dprintk("couldn't start capture\n");
3586 return -EINVAL;
3587 }
3588 }
3589
3590 return 0;
3591}
3592
Hans Verkuilc49cb362009-02-12 10:32:50 -03003593static int vino_streamoff(struct file *file, void *__fh,
3594 enum v4l2_buf_type i)
Ralf Baechled203a7e2005-09-06 15:19:37 -07003595{
Hans Verkuilc49cb362009-02-12 10:32:50 -03003596 struct vino_channel_settings *vcs = video_drvdata(file);
Ralf Baechled203a7e2005-09-06 15:19:37 -07003597 if (vcs->reading)
3598 return -EBUSY;
3599
3600 if (!vcs->streaming)
3601 return 0;
3602
Ralf Baechled203a7e2005-09-06 15:19:37 -07003603 vcs->streaming = 0;
Ladislav Michla637a112005-09-01 15:07:34 +00003604 vino_capture_stop(vcs);
Ralf Baechled203a7e2005-09-06 15:19:37 -07003605
3606 return 0;
3607}
3608
Hans Verkuilc49cb362009-02-12 10:32:50 -03003609static int vino_queryctrl(struct file *file, void *__fh,
Ralf Baechled203a7e2005-09-06 15:19:37 -07003610 struct v4l2_queryctrl *queryctrl)
3611{
Hans Verkuilc49cb362009-02-12 10:32:50 -03003612 struct vino_channel_settings *vcs = video_drvdata(file);
Ladislav Michla637a112005-09-01 15:07:34 +00003613 unsigned long flags;
Ralf Baechled203a7e2005-09-06 15:19:37 -07003614 int i;
3615 int err = 0;
3616
Ladislav Michla637a112005-09-01 15:07:34 +00003617 spin_lock_irqsave(&vino_drvdata->input_lock, flags);
Ralf Baechled203a7e2005-09-06 15:19:37 -07003618
3619 switch (vcs->input) {
3620 case VINO_INPUT_D1:
3621 for (i = 0; i < VINO_INDYCAM_V4L2_CONTROL_COUNT; i++) {
3622 if (vino_indycam_v4l2_controls[i].id ==
3623 queryctrl->id) {
3624 memcpy(queryctrl,
3625 &vino_indycam_v4l2_controls[i],
3626 sizeof(struct v4l2_queryctrl));
Ladislav Michla637a112005-09-01 15:07:34 +00003627 queryctrl->reserved[0] = 0;
Ralf Baechled203a7e2005-09-06 15:19:37 -07003628 goto found;
3629 }
3630 }
3631
3632 err = -EINVAL;
3633 break;
3634 case VINO_INPUT_COMPOSITE:
3635 case VINO_INPUT_SVIDEO:
3636 for (i = 0; i < VINO_SAA7191_V4L2_CONTROL_COUNT; i++) {
3637 if (vino_saa7191_v4l2_controls[i].id ==
3638 queryctrl->id) {
3639 memcpy(queryctrl,
3640 &vino_saa7191_v4l2_controls[i],
3641 sizeof(struct v4l2_queryctrl));
Ladislav Michla637a112005-09-01 15:07:34 +00003642 queryctrl->reserved[0] = 0;
Ralf Baechled203a7e2005-09-06 15:19:37 -07003643 goto found;
3644 }
3645 }
3646
3647 err = -EINVAL;
3648 break;
3649 default:
3650 err = -EINVAL;
3651 }
3652
3653 found:
Ladislav Michla637a112005-09-01 15:07:34 +00003654 spin_unlock_irqrestore(&vino_drvdata->input_lock, flags);
Ralf Baechled203a7e2005-09-06 15:19:37 -07003655
3656 return err;
3657}
3658
Hans Verkuilc49cb362009-02-12 10:32:50 -03003659static int vino_g_ctrl(struct file *file, void *__fh,
Ralf Baechled203a7e2005-09-06 15:19:37 -07003660 struct v4l2_control *control)
3661{
Hans Verkuilc49cb362009-02-12 10:32:50 -03003662 struct vino_channel_settings *vcs = video_drvdata(file);
Ladislav Michla637a112005-09-01 15:07:34 +00003663 unsigned long flags;
3664 int i;
Ralf Baechled203a7e2005-09-06 15:19:37 -07003665 int err = 0;
3666
Ladislav Michla637a112005-09-01 15:07:34 +00003667 spin_lock_irqsave(&vino_drvdata->input_lock, flags);
Ralf Baechled203a7e2005-09-06 15:19:37 -07003668
3669 switch (vcs->input) {
Ladislav Michla637a112005-09-01 15:07:34 +00003670 case VINO_INPUT_D1: {
Hans Verkuilcf4e9482009-02-27 09:05:10 -03003671 err = -EINVAL;
Ladislav Michla637a112005-09-01 15:07:34 +00003672 for (i = 0; i < VINO_INDYCAM_V4L2_CONTROL_COUNT; i++) {
Hans Verkuilcf4e9482009-02-27 09:05:10 -03003673 if (vino_indycam_v4l2_controls[i].id == control->id) {
3674 err = 0;
3675 break;
Ladislav Michla637a112005-09-01 15:07:34 +00003676 }
Ralf Baechled203a7e2005-09-06 15:19:37 -07003677 }
Ladislav Michla637a112005-09-01 15:07:34 +00003678
Hans Verkuilcf4e9482009-02-27 09:05:10 -03003679 if (err)
Ladislav Michla637a112005-09-01 15:07:34 +00003680 goto out;
Ladislav Michla637a112005-09-01 15:07:34 +00003681
Hans Verkuilcf4e9482009-02-27 09:05:10 -03003682 err = i2c_camera_command(VIDIOC_G_CTRL, &control);
3683 if (err)
3684 err = -EINVAL;
Ralf Baechled203a7e2005-09-06 15:19:37 -07003685 break;
Ladislav Michla637a112005-09-01 15:07:34 +00003686 }
Ralf Baechled203a7e2005-09-06 15:19:37 -07003687 case VINO_INPUT_COMPOSITE:
Ladislav Michla637a112005-09-01 15:07:34 +00003688 case VINO_INPUT_SVIDEO: {
Hans Verkuilcf4e9482009-02-27 09:05:10 -03003689 err = -EINVAL;
Ladislav Michla637a112005-09-01 15:07:34 +00003690 for (i = 0; i < VINO_SAA7191_V4L2_CONTROL_COUNT; i++) {
Hans Verkuilcf4e9482009-02-27 09:05:10 -03003691 if (vino_saa7191_v4l2_controls[i].id == control->id) {
3692 err = 0;
3693 break;
Ladislav Michla637a112005-09-01 15:07:34 +00003694 }
Ralf Baechled203a7e2005-09-06 15:19:37 -07003695 }
Ladislav Michla637a112005-09-01 15:07:34 +00003696
Hans Verkuilcf4e9482009-02-27 09:05:10 -03003697 if (err)
Ladislav Michla637a112005-09-01 15:07:34 +00003698 goto out;
Ladislav Michla637a112005-09-01 15:07:34 +00003699
Hans Verkuilcf4e9482009-02-27 09:05:10 -03003700 err = i2c_decoder_command(VIDIOC_G_CTRL, &control);
3701 if (err)
3702 err = -EINVAL;
Ralf Baechled203a7e2005-09-06 15:19:37 -07003703 break;
Ladislav Michla637a112005-09-01 15:07:34 +00003704 }
Ralf Baechled203a7e2005-09-06 15:19:37 -07003705 default:
3706 err = -EINVAL;
3707 }
3708
Ladislav Michla637a112005-09-01 15:07:34 +00003709out:
3710 spin_unlock_irqrestore(&vino_drvdata->input_lock, flags);
Ralf Baechled203a7e2005-09-06 15:19:37 -07003711
3712 return err;
3713}
3714
Hans Verkuilc49cb362009-02-12 10:32:50 -03003715static int vino_s_ctrl(struct file *file, void *__fh,
Ralf Baechled203a7e2005-09-06 15:19:37 -07003716 struct v4l2_control *control)
3717{
Hans Verkuilc49cb362009-02-12 10:32:50 -03003718 struct vino_channel_settings *vcs = video_drvdata(file);
Ladislav Michla637a112005-09-01 15:07:34 +00003719 unsigned long flags;
Ralf Baechled203a7e2005-09-06 15:19:37 -07003720 int i;
3721 int err = 0;
3722
Ladislav Michla637a112005-09-01 15:07:34 +00003723 spin_lock_irqsave(&vino_drvdata->input_lock, flags);
3724
3725 if (!vino_is_input_owner(vcs)) {
3726 err = -EBUSY;
3727 goto out;
3728 }
Ralf Baechled203a7e2005-09-06 15:19:37 -07003729
3730 switch (vcs->input) {
Ladislav Michla637a112005-09-01 15:07:34 +00003731 case VINO_INPUT_D1: {
Hans Verkuilcf4e9482009-02-27 09:05:10 -03003732 err = -EINVAL;
Ralf Baechled203a7e2005-09-06 15:19:37 -07003733 for (i = 0; i < VINO_INDYCAM_V4L2_CONTROL_COUNT; i++) {
Hans Verkuilcf4e9482009-02-27 09:05:10 -03003734 if (vino_indycam_v4l2_controls[i].id == control->id) {
3735 err = 0;
3736 break;
Ralf Baechled203a7e2005-09-06 15:19:37 -07003737 }
3738 }
Hans Verkuilcf4e9482009-02-27 09:05:10 -03003739 if (err)
3740 goto out;
3741 if (control->value < vino_indycam_v4l2_controls[i].minimum ||
3742 control->value > vino_indycam_v4l2_controls[i].maximum) {
3743 err = -ERANGE;
3744 goto out;
3745 }
3746 err = i2c_camera_command(VIDIOC_S_CTRL, &control);
Ladislav Michla637a112005-09-01 15:07:34 +00003747 if (err)
3748 err = -EINVAL;
Ralf Baechled203a7e2005-09-06 15:19:37 -07003749 break;
Ladislav Michla637a112005-09-01 15:07:34 +00003750 }
Ralf Baechled203a7e2005-09-06 15:19:37 -07003751 case VINO_INPUT_COMPOSITE:
Ladislav Michla637a112005-09-01 15:07:34 +00003752 case VINO_INPUT_SVIDEO: {
Hans Verkuilcf4e9482009-02-27 09:05:10 -03003753 err = -EINVAL;
Ralf Baechled203a7e2005-09-06 15:19:37 -07003754 for (i = 0; i < VINO_SAA7191_V4L2_CONTROL_COUNT; i++) {
Hans Verkuilcf4e9482009-02-27 09:05:10 -03003755 if (vino_saa7191_v4l2_controls[i].id == control->id) {
3756 err = 0;
3757 break;
Ralf Baechled203a7e2005-09-06 15:19:37 -07003758 }
3759 }
Hans Verkuilcf4e9482009-02-27 09:05:10 -03003760 if (err)
3761 goto out;
3762 if (control->value < vino_saa7191_v4l2_controls[i].minimum ||
3763 control->value > vino_saa7191_v4l2_controls[i].maximum) {
3764 err = -ERANGE;
3765 goto out;
3766 }
Ralf Baechled203a7e2005-09-06 15:19:37 -07003767
Hans Verkuilcf4e9482009-02-27 09:05:10 -03003768 err = i2c_decoder_command(VIDIOC_S_CTRL, &control);
Ladislav Michla637a112005-09-01 15:07:34 +00003769 if (err)
3770 err = -EINVAL;
Ralf Baechled203a7e2005-09-06 15:19:37 -07003771 break;
Ladislav Michla637a112005-09-01 15:07:34 +00003772 }
Ralf Baechled203a7e2005-09-06 15:19:37 -07003773 default:
3774 err = -EINVAL;
3775 }
3776
Ladislav Michla637a112005-09-01 15:07:34 +00003777out:
3778 spin_unlock_irqrestore(&vino_drvdata->input_lock, flags);
Ralf Baechled203a7e2005-09-06 15:19:37 -07003779
3780 return err;
3781}
3782
3783/* File operations */
3784
Hans Verkuilbec43662008-12-30 06:58:20 -03003785static int vino_open(struct file *file)
Ralf Baechled203a7e2005-09-06 15:19:37 -07003786{
Hans Verkuilc170ecf2008-08-23 08:32:09 -03003787 struct vino_channel_settings *vcs = video_drvdata(file);
Ralf Baechled203a7e2005-09-06 15:19:37 -07003788 int ret = 0;
3789 dprintk("open(): channel = %c\n",
3790 (vcs->channel == VINO_CHANNEL_A) ? 'A' : 'B');
3791
Ingo Molnar3593cab2006-02-07 06:49:14 -02003792 mutex_lock(&vcs->mutex);
Ralf Baechled203a7e2005-09-06 15:19:37 -07003793
3794 if (vcs->users) {
3795 dprintk("open(): driver busy\n");
3796 ret = -EBUSY;
3797 goto out;
3798 }
3799
3800 ret = vino_acquire_input(vcs);
3801 if (ret) {
3802 dprintk("open(): vino_acquire_input() failed\n");
3803 goto out;
3804 }
3805
3806 vcs->users++;
3807
3808 out:
Ingo Molnar3593cab2006-02-07 06:49:14 -02003809 mutex_unlock(&vcs->mutex);
Ralf Baechled203a7e2005-09-06 15:19:37 -07003810
3811 dprintk("open(): %s!\n", ret ? "failed" : "complete");
3812
3813 return ret;
3814}
3815
Hans Verkuilbec43662008-12-30 06:58:20 -03003816static int vino_close(struct file *file)
Ralf Baechled203a7e2005-09-06 15:19:37 -07003817{
Hans Verkuilc170ecf2008-08-23 08:32:09 -03003818 struct vino_channel_settings *vcs = video_drvdata(file);
Ralf Baechled203a7e2005-09-06 15:19:37 -07003819 dprintk("close():\n");
3820
Ingo Molnar3593cab2006-02-07 06:49:14 -02003821 mutex_lock(&vcs->mutex);
Ralf Baechled203a7e2005-09-06 15:19:37 -07003822
3823 vcs->users--;
3824
3825 if (!vcs->users) {
3826 vino_release_input(vcs);
3827
3828 /* stop DMA and free buffers */
3829 vino_capture_stop(vcs);
3830 vino_queue_free(&vcs->fb_queue);
3831 }
3832
Ingo Molnar3593cab2006-02-07 06:49:14 -02003833 mutex_unlock(&vcs->mutex);
Ralf Baechled203a7e2005-09-06 15:19:37 -07003834
3835 return 0;
3836}
3837
3838static void vino_vm_open(struct vm_area_struct *vma)
3839{
3840 struct vino_framebuffer *fb = vma->vm_private_data;
3841
3842 fb->map_count++;
3843 dprintk("vino_vm_open(): count = %d\n", fb->map_count);
3844}
3845
3846static void vino_vm_close(struct vm_area_struct *vma)
3847{
3848 struct vino_framebuffer *fb = vma->vm_private_data;
3849
3850 fb->map_count--;
3851 dprintk("vino_vm_close(): count = %d\n", fb->map_count);
3852}
3853
3854static struct vm_operations_struct vino_vm_ops = {
3855 .open = vino_vm_open,
3856 .close = vino_vm_close,
3857};
3858
3859static int vino_mmap(struct file *file, struct vm_area_struct *vma)
3860{
Hans Verkuilc170ecf2008-08-23 08:32:09 -03003861 struct vino_channel_settings *vcs = video_drvdata(file);
Ralf Baechled203a7e2005-09-06 15:19:37 -07003862
3863 unsigned long start = vma->vm_start;
3864 unsigned long size = vma->vm_end - vma->vm_start;
3865 unsigned long offset = vma->vm_pgoff << PAGE_SHIFT;
3866
3867 struct vino_framebuffer *fb = NULL;
3868 unsigned int i, length;
3869 int ret = 0;
3870
3871 dprintk("mmap():\n");
3872
3873 // TODO: reject mmap if already mapped
3874
Ingo Molnar3593cab2006-02-07 06:49:14 -02003875 if (mutex_lock_interruptible(&vcs->mutex))
Ralf Baechled203a7e2005-09-06 15:19:37 -07003876 return -EINTR;
3877
3878 if (vcs->reading) {
3879 ret = -EBUSY;
3880 goto out;
3881 }
3882
3883 // TODO: check queue type
3884
3885 if (!(vma->vm_flags & VM_WRITE)) {
3886 dprintk("mmap(): app bug: PROT_WRITE please\n");
3887 ret = -EINVAL;
3888 goto out;
3889 }
3890 if (!(vma->vm_flags & VM_SHARED)) {
3891 dprintk("mmap(): app bug: MAP_SHARED please\n");
3892 ret = -EINVAL;
3893 goto out;
3894 }
3895
3896 /* find the correct buffer using offset */
3897 length = vino_queue_get_length(&vcs->fb_queue);
3898 if (length == 0) {
3899 dprintk("mmap(): queue not initialized\n");
3900 ret = -EINVAL;
3901 goto out;
3902 }
3903
3904 for (i = 0; i < length; i++) {
3905 fb = vino_queue_get_buffer(&vcs->fb_queue, i);
3906 if (fb == NULL) {
3907 dprintk("mmap(): vino_queue_get_buffer() failed\n");
3908 ret = -EINVAL;
3909 goto out;
3910 }
3911
3912 if (fb->offset == offset)
3913 goto found;
3914 }
3915
3916 dprintk("mmap(): invalid offset = %lu\n", offset);
3917 ret = -EINVAL;
3918 goto out;
3919
3920found:
3921 dprintk("mmap(): buffer = %d\n", i);
3922
3923 if (size > (fb->desc_table.page_count * PAGE_SIZE)) {
3924 dprintk("mmap(): failed: size = %lu > %lu\n",
3925 size, fb->desc_table.page_count * PAGE_SIZE);
3926 ret = -EINVAL;
3927 goto out;
3928 }
3929
3930 for (i = 0; i < fb->desc_table.page_count; i++) {
3931 unsigned long pfn =
3932 virt_to_phys((void *)fb->desc_table.virtual[i]) >>
3933 PAGE_SHIFT;
3934
3935 if (size < PAGE_SIZE)
3936 break;
3937
3938 // protection was: PAGE_READONLY
3939 if (remap_pfn_range(vma, start, pfn, PAGE_SIZE,
3940 vma->vm_page_prot)) {
3941 dprintk("mmap(): remap_pfn_range() failed\n");
3942 ret = -EAGAIN;
3943 goto out;
3944 }
3945
3946 start += PAGE_SIZE;
3947 size -= PAGE_SIZE;
3948 }
3949
3950 fb->map_count = 1;
3951
3952 vma->vm_flags |= VM_DONTEXPAND | VM_RESERVED;
3953 vma->vm_flags &= ~VM_IO;
3954 vma->vm_private_data = fb;
3955 vma->vm_file = file;
3956 vma->vm_ops = &vino_vm_ops;
3957
3958out:
Ingo Molnar3593cab2006-02-07 06:49:14 -02003959 mutex_unlock(&vcs->mutex);
Ralf Baechled203a7e2005-09-06 15:19:37 -07003960
3961 return ret;
3962}
3963
3964static unsigned int vino_poll(struct file *file, poll_table *pt)
3965{
Hans Verkuilc170ecf2008-08-23 08:32:09 -03003966 struct vino_channel_settings *vcs = video_drvdata(file);
Ralf Baechled203a7e2005-09-06 15:19:37 -07003967 unsigned int outgoing;
3968 unsigned int ret = 0;
3969
3970 // lock mutex (?)
3971 // TODO: this has to be corrected for different read modes
3972
3973 dprintk("poll():\n");
3974
3975 if (vino_queue_get_outgoing(&vcs->fb_queue, &outgoing)) {
3976 dprintk("poll(): vino_queue_get_outgoing() failed\n");
3977 ret = POLLERR;
3978 goto error;
3979 }
3980 if (outgoing > 0)
3981 goto over;
3982
3983 poll_wait(file, &vcs->fb_queue.frame_wait_queue, pt);
3984
3985 if (vino_queue_get_outgoing(&vcs->fb_queue, &outgoing)) {
3986 dprintk("poll(): vino_queue_get_outgoing() failed\n");
3987 ret = POLLERR;
3988 goto error;
3989 }
3990
3991over:
3992 dprintk("poll(): data %savailable\n",
3993 (outgoing > 0) ? "" : "not ");
Ladislav Michla637a112005-09-01 15:07:34 +00003994
3995 if (outgoing > 0)
Ralf Baechled203a7e2005-09-06 15:19:37 -07003996 ret = POLLIN | POLLRDNORM;
Ralf Baechled203a7e2005-09-06 15:19:37 -07003997
3998error:
Ralf Baechled203a7e2005-09-06 15:19:37 -07003999 return ret;
4000}
4001
Hans Verkuil069b7472008-12-30 07:04:34 -03004002static long vino_ioctl(struct file *file,
Ralf Baechled203a7e2005-09-06 15:19:37 -07004003 unsigned int cmd, unsigned long arg)
4004{
Hans Verkuilc170ecf2008-08-23 08:32:09 -03004005 struct vino_channel_settings *vcs = video_drvdata(file);
Hans Verkuil069b7472008-12-30 07:04:34 -03004006 long ret;
Ralf Baechled203a7e2005-09-06 15:19:37 -07004007
Ingo Molnar3593cab2006-02-07 06:49:14 -02004008 if (mutex_lock_interruptible(&vcs->mutex))
Ralf Baechled203a7e2005-09-06 15:19:37 -07004009 return -EINTR;
4010
Hans Verkuilc49cb362009-02-12 10:32:50 -03004011 ret = video_ioctl2(file, cmd, arg);
Ralf Baechled203a7e2005-09-06 15:19:37 -07004012
Ingo Molnar3593cab2006-02-07 06:49:14 -02004013 mutex_unlock(&vcs->mutex);
Ralf Baechled203a7e2005-09-06 15:19:37 -07004014
4015 return ret;
4016}
4017
4018/* Initialization and cleanup */
4019
Douglas Schilling Landgrafff699e62008-04-22 14:41:48 -03004020/* __initdata */
4021static int vino_init_stage;
Ralf Baechled203a7e2005-09-06 15:19:37 -07004022
Hans Verkuilc49cb362009-02-12 10:32:50 -03004023const struct v4l2_ioctl_ops vino_ioctl_ops = {
4024 .vidioc_enum_fmt_vid_cap = vino_enum_fmt_vid_cap,
4025 .vidioc_g_fmt_vid_cap = vino_g_fmt_vid_cap,
4026 .vidioc_s_fmt_vid_cap = vino_s_fmt_vid_cap,
4027 .vidioc_try_fmt_vid_cap = vino_try_fmt_vid_cap,
4028 .vidioc_querycap = vino_querycap,
4029 .vidioc_enum_input = vino_enum_input,
4030 .vidioc_g_input = vino_g_input,
4031 .vidioc_s_input = vino_s_input,
4032 .vidioc_g_std = vino_g_std,
4033 .vidioc_s_std = vino_s_std,
4034 .vidioc_querystd = vino_querystd,
4035 .vidioc_cropcap = vino_cropcap,
4036 .vidioc_s_crop = vino_s_crop,
4037 .vidioc_g_crop = vino_g_crop,
4038 .vidioc_s_parm = vino_s_parm,
4039 .vidioc_g_parm = vino_g_parm,
4040 .vidioc_reqbufs = vino_reqbufs,
4041 .vidioc_querybuf = vino_querybuf,
4042 .vidioc_qbuf = vino_qbuf,
4043 .vidioc_dqbuf = vino_dqbuf,
4044 .vidioc_streamon = vino_streamon,
4045 .vidioc_streamoff = vino_streamoff,
4046 .vidioc_queryctrl = vino_queryctrl,
4047 .vidioc_g_ctrl = vino_g_ctrl,
4048 .vidioc_s_ctrl = vino_s_ctrl,
4049};
4050
Hans Verkuilbec43662008-12-30 06:58:20 -03004051static const struct v4l2_file_operations vino_fops = {
Ralf Baechled203a7e2005-09-06 15:19:37 -07004052 .owner = THIS_MODULE,
4053 .open = vino_open,
4054 .release = vino_close,
Hans Verkuil28959632009-02-18 18:53:47 -03004055 .unlocked_ioctl = vino_ioctl,
Ralf Baechled203a7e2005-09-06 15:19:37 -07004056 .mmap = vino_mmap,
4057 .poll = vino_poll,
Ralf Baechled203a7e2005-09-06 15:19:37 -07004058};
4059
Hans Verkuil0ef4dba2009-02-12 11:31:13 -03004060static struct video_device vdev_template = {
Ralf Baechled203a7e2005-09-06 15:19:37 -07004061 .name = "NOT SET",
Ralf Baechled203a7e2005-09-06 15:19:37 -07004062 .fops = &vino_fops,
Hans Verkuilc49cb362009-02-12 10:32:50 -03004063 .ioctl_ops = &vino_ioctl_ops,
4064 .tvnorms = V4L2_STD_NTSC | V4L2_STD_PAL | V4L2_STD_SECAM,
Ralf Baechled203a7e2005-09-06 15:19:37 -07004065 .minor = -1,
4066};
4067
4068static void vino_module_cleanup(int stage)
4069{
4070 switch(stage) {
Hans Verkuil28959632009-02-18 18:53:47 -03004071 case 11:
Hans Verkuil0ef4dba2009-02-12 11:31:13 -03004072 video_unregister_device(vino_drvdata->b.vdev);
4073 vino_drvdata->b.vdev = NULL;
Hans Verkuil28959632009-02-18 18:53:47 -03004074 case 10:
Hans Verkuil0ef4dba2009-02-12 11:31:13 -03004075 video_unregister_device(vino_drvdata->a.vdev);
4076 vino_drvdata->a.vdev = NULL;
Hans Verkuil28959632009-02-18 18:53:47 -03004077 case 9:
Ralf Baechled203a7e2005-09-06 15:19:37 -07004078 vino_i2c_del_bus();
Hans Verkuil28959632009-02-18 18:53:47 -03004079 case 8:
Ralf Baechled203a7e2005-09-06 15:19:37 -07004080 free_irq(SGI_VINO_IRQ, NULL);
Hans Verkuil28959632009-02-18 18:53:47 -03004081 case 7:
Hans Verkuil0ef4dba2009-02-12 11:31:13 -03004082 if (vino_drvdata->b.vdev) {
4083 video_device_release(vino_drvdata->b.vdev);
4084 vino_drvdata->b.vdev = NULL;
Ralf Baechled203a7e2005-09-06 15:19:37 -07004085 }
Hans Verkuil28959632009-02-18 18:53:47 -03004086 case 6:
Hans Verkuil0ef4dba2009-02-12 11:31:13 -03004087 if (vino_drvdata->a.vdev) {
4088 video_device_release(vino_drvdata->a.vdev);
4089 vino_drvdata->a.vdev = NULL;
Ralf Baechled203a7e2005-09-06 15:19:37 -07004090 }
Hans Verkuil28959632009-02-18 18:53:47 -03004091 case 5:
Ralf Baechled203a7e2005-09-06 15:19:37 -07004092 /* all entries in dma_cpu dummy table have the same address */
4093 dma_unmap_single(NULL,
4094 vino_drvdata->dummy_desc_table.dma_cpu[0],
4095 PAGE_SIZE, DMA_FROM_DEVICE);
4096 dma_free_coherent(NULL, VINO_DUMMY_DESC_COUNT
4097 * sizeof(dma_addr_t),
4098 (void *)vino_drvdata->
4099 dummy_desc_table.dma_cpu,
4100 vino_drvdata->dummy_desc_table.dma);
Hans Verkuil28959632009-02-18 18:53:47 -03004101 case 4:
Ralf Baechled203a7e2005-09-06 15:19:37 -07004102 free_page(vino_drvdata->dummy_page);
Hans Verkuil28959632009-02-18 18:53:47 -03004103 case 3:
4104 v4l2_device_unregister(&vino_drvdata->v4l2_dev);
Ralf Baechled203a7e2005-09-06 15:19:37 -07004105 case 2:
4106 kfree(vino_drvdata);
4107 case 1:
4108 iounmap(vino);
4109 case 0:
4110 break;
4111 default:
4112 dprintk("vino_module_cleanup(): invalid cleanup stage = %d\n",
4113 stage);
4114 }
4115}
4116
4117static int vino_probe(void)
4118{
4119 unsigned long rev_id;
4120
4121 if (ip22_is_fullhouse()) {
4122 printk(KERN_ERR "VINO doesn't exist in IP22 Fullhouse\n");
4123 return -ENODEV;
4124 }
4125
4126 if (!(sgimc->systemid & SGIMC_SYSID_EPRESENT)) {
4127 printk(KERN_ERR "VINO is not found (EISA BUS not present)\n");
4128 return -ENODEV;
4129 }
4130
4131 vino = (struct sgi_vino *)ioremap(VINO_BASE, sizeof(struct sgi_vino));
4132 if (!vino) {
4133 printk(KERN_ERR "VINO: ioremap() failed\n");
4134 return -EIO;
4135 }
4136 vino_init_stage++;
4137
4138 if (get_dbe(rev_id, &(vino->rev_id))) {
4139 printk(KERN_ERR "Failed to read VINO revision register\n");
4140 vino_module_cleanup(vino_init_stage);
4141 return -ENODEV;
4142 }
4143
4144 if (VINO_ID_VALUE(rev_id) != VINO_CHIP_ID) {
4145 printk(KERN_ERR "Unknown VINO chip ID (Rev/ID: 0x%02lx)\n",
4146 rev_id);
4147 vino_module_cleanup(vino_init_stage);
4148 return -ENODEV;
4149 }
4150
Ladislav Michla637a112005-09-01 15:07:34 +00004151 printk(KERN_INFO "VINO revision %ld found\n", VINO_REV_NUM(rev_id));
Ralf Baechled203a7e2005-09-06 15:19:37 -07004152
4153 return 0;
4154}
4155
4156static int vino_init(void)
4157{
4158 dma_addr_t dma_dummy_address;
Hans Verkuil28959632009-02-18 18:53:47 -03004159 int err;
Ralf Baechled203a7e2005-09-06 15:19:37 -07004160 int i;
4161
Panagiotis Issaris74081872006-01-11 19:40:56 -02004162 vino_drvdata = kzalloc(sizeof(struct vino_settings), GFP_KERNEL);
Ralf Baechled203a7e2005-09-06 15:19:37 -07004163 if (!vino_drvdata) {
4164 vino_module_cleanup(vino_init_stage);
4165 return -ENOMEM;
4166 }
Ralf Baechled203a7e2005-09-06 15:19:37 -07004167 vino_init_stage++;
Hans Verkuil28959632009-02-18 18:53:47 -03004168 strlcpy(vino_drvdata->v4l2_dev.name, "vino",
4169 sizeof(vino_drvdata->v4l2_dev.name));
4170 err = v4l2_device_register(NULL, &vino_drvdata->v4l2_dev);
4171 if (err)
4172 return err;
4173 vino_init_stage++;
Ralf Baechled203a7e2005-09-06 15:19:37 -07004174
4175 /* create a dummy dma descriptor */
4176 vino_drvdata->dummy_page = get_zeroed_page(GFP_KERNEL | GFP_DMA);
4177 if (!vino_drvdata->dummy_page) {
4178 vino_module_cleanup(vino_init_stage);
4179 return -ENOMEM;
4180 }
4181 vino_init_stage++;
4182
4183 // TODO: use page_count in dummy_desc_table
4184
4185 vino_drvdata->dummy_desc_table.dma_cpu =
4186 dma_alloc_coherent(NULL,
4187 VINO_DUMMY_DESC_COUNT * sizeof(dma_addr_t),
4188 &vino_drvdata->dummy_desc_table.dma,
4189 GFP_KERNEL | GFP_DMA);
4190 if (!vino_drvdata->dummy_desc_table.dma_cpu) {
4191 vino_module_cleanup(vino_init_stage);
4192 return -ENOMEM;
4193 }
4194 vino_init_stage++;
4195
4196 dma_dummy_address = dma_map_single(NULL,
4197 (void *)vino_drvdata->dummy_page,
4198 PAGE_SIZE, DMA_FROM_DEVICE);
4199 for (i = 0; i < VINO_DUMMY_DESC_COUNT; i++) {
4200 vino_drvdata->dummy_desc_table.dma_cpu[i] = dma_dummy_address;
4201 }
4202
4203 /* initialize VINO */
4204
4205 vino->control = 0;
4206 vino->a.next_4_desc = vino_drvdata->dummy_desc_table.dma;
4207 vino->b.next_4_desc = vino_drvdata->dummy_desc_table.dma;
4208 udelay(VINO_DESC_FETCH_DELAY);
4209
4210 vino->intr_status = 0;
4211
4212 vino->a.fifo_thres = VINO_FIFO_THRESHOLD_DEFAULT;
4213 vino->b.fifo_thres = VINO_FIFO_THRESHOLD_DEFAULT;
4214
4215 return 0;
4216}
4217
4218static int vino_init_channel_settings(struct vino_channel_settings *vcs,
4219 unsigned int channel, const char *name)
4220{
4221 vcs->channel = channel;
4222 vcs->input = VINO_INPUT_NONE;
4223 vcs->alpha = 0;
4224 vcs->users = 0;
4225 vcs->data_format = VINO_DATA_FMT_GREY;
4226 vcs->data_norm = VINO_DATA_NORM_NTSC;
4227 vcs->decimation = 1;
4228 vino_set_default_clipping(vcs);
4229 vino_set_default_framerate(vcs);
4230
4231 vcs->capturing = 0;
4232
Ingo Molnar3593cab2006-02-07 06:49:14 -02004233 mutex_init(&vcs->mutex);
Ralf Baechled203a7e2005-09-06 15:19:37 -07004234 spin_lock_init(&vcs->capture_lock);
4235
Ingo Molnar3593cab2006-02-07 06:49:14 -02004236 mutex_init(&vcs->fb_queue.queue_mutex);
Ralf Baechled203a7e2005-09-06 15:19:37 -07004237 spin_lock_init(&vcs->fb_queue.queue_lock);
4238 init_waitqueue_head(&vcs->fb_queue.frame_wait_queue);
4239
Hans Verkuil0ef4dba2009-02-12 11:31:13 -03004240 vcs->vdev = video_device_alloc();
4241 if (!vcs->vdev) {
Ralf Baechled203a7e2005-09-06 15:19:37 -07004242 vino_module_cleanup(vino_init_stage);
4243 return -ENOMEM;
4244 }
4245 vino_init_stage++;
4246
Hans Verkuil0ef4dba2009-02-12 11:31:13 -03004247 memcpy(vcs->vdev, &vdev_template,
Ralf Baechled203a7e2005-09-06 15:19:37 -07004248 sizeof(struct video_device));
Hans Verkuil0ef4dba2009-02-12 11:31:13 -03004249 strcpy(vcs->vdev->name, name);
4250 vcs->vdev->release = video_device_release;
Hans Verkuil28959632009-02-18 18:53:47 -03004251 vcs->vdev->v4l2_dev = &vino_drvdata->v4l2_dev;
Ralf Baechled203a7e2005-09-06 15:19:37 -07004252
Hans Verkuil0ef4dba2009-02-12 11:31:13 -03004253 video_set_drvdata(vcs->vdev, vcs);
Ralf Baechled203a7e2005-09-06 15:19:37 -07004254
4255 return 0;
4256}
4257
4258static int __init vino_module_init(void)
4259{
4260 int ret;
4261
4262 printk(KERN_INFO "SGI VINO driver version %s\n",
4263 VINO_MODULE_VERSION);
4264
4265 ret = vino_probe();
4266 if (ret)
4267 return ret;
4268
4269 ret = vino_init();
4270 if (ret)
4271 return ret;
4272
4273 /* initialize data structures */
4274
4275 spin_lock_init(&vino_drvdata->vino_lock);
4276 spin_lock_init(&vino_drvdata->input_lock);
4277
4278 ret = vino_init_channel_settings(&vino_drvdata->a, VINO_CHANNEL_A,
Hans Verkuil0ef4dba2009-02-12 11:31:13 -03004279 vino_vdev_name_a);
Ralf Baechled203a7e2005-09-06 15:19:37 -07004280 if (ret)
4281 return ret;
4282
4283 ret = vino_init_channel_settings(&vino_drvdata->b, VINO_CHANNEL_B,
Hans Verkuil0ef4dba2009-02-12 11:31:13 -03004284 vino_vdev_name_b);
Ralf Baechled203a7e2005-09-06 15:19:37 -07004285 if (ret)
4286 return ret;
4287
4288 /* initialize hardware and register V4L devices */
4289
4290 ret = request_irq(SGI_VINO_IRQ, vino_interrupt, 0,
4291 vino_driver_description, NULL);
4292 if (ret) {
4293 printk(KERN_ERR "VINO: requesting IRQ %02d failed\n",
4294 SGI_VINO_IRQ);
4295 vino_module_cleanup(vino_init_stage);
4296 return -EAGAIN;
4297 }
4298 vino_init_stage++;
4299
4300 ret = vino_i2c_add_bus();
4301 if (ret) {
4302 printk(KERN_ERR "VINO I2C bus registration failed\n");
4303 vino_module_cleanup(vino_init_stage);
4304 return ret;
4305 }
Hans Verkuil28959632009-02-18 18:53:47 -03004306 i2c_set_adapdata(&vino_i2c_adapter, &vino_drvdata->v4l2_dev);
Ralf Baechled203a7e2005-09-06 15:19:37 -07004307 vino_init_stage++;
4308
Hans Verkuil0ef4dba2009-02-12 11:31:13 -03004309 ret = video_register_device(vino_drvdata->a.vdev,
Ralf Baechled203a7e2005-09-06 15:19:37 -07004310 VFL_TYPE_GRABBER, -1);
4311 if (ret < 0) {
4312 printk(KERN_ERR "VINO channel A Video4Linux-device "
4313 "registration failed\n");
4314 vino_module_cleanup(vino_init_stage);
4315 return -EINVAL;
4316 }
4317 vino_init_stage++;
4318
Hans Verkuil0ef4dba2009-02-12 11:31:13 -03004319 ret = video_register_device(vino_drvdata->b.vdev,
Ralf Baechled203a7e2005-09-06 15:19:37 -07004320 VFL_TYPE_GRABBER, -1);
4321 if (ret < 0) {
4322 printk(KERN_ERR "VINO channel B Video4Linux-device "
4323 "registration failed\n");
4324 vino_module_cleanup(vino_init_stage);
4325 return -EINVAL;
4326 }
4327 vino_init_stage++;
4328
Johannes Berga65e5d72008-07-09 10:28:38 +02004329#ifdef MODULE
Ralf Baechled203a7e2005-09-06 15:19:37 -07004330 request_module("saa7191");
4331 request_module("indycam");
4332#endif
4333
4334 dprintk("init complete!\n");
4335
4336 return 0;
4337}
4338
4339static void __exit vino_module_exit(void)
4340{
4341 dprintk("exiting, stage = %d ...\n", vino_init_stage);
4342 vino_module_cleanup(vino_init_stage);
4343 dprintk("cleanup complete, exit!\n");
4344}
4345
4346module_init(vino_module_init);
4347module_exit(vino_module_exit);