blob: b62e030ba83ab80cbb50b037fefdf62d557981f7 [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>
Linus Torvalds1da177e2005-04-16 15:20:36 -070036
Hans Verkuil33b687c2008-07-25 05:32:50 -030037#include <linux/videodev2.h>
Hans Verkuil28959632009-02-18 18:53:47 -030038#include <media/v4l2-device.h>
Yoichi Yuasac2cfcf72008-07-29 05:30:58 -030039#include <media/v4l2-ioctl.h>
Ingo Molnar3593cab2006-02-07 06:49:14 -020040#include <linux/mutex.h>
Ralf Baechled203a7e2005-09-06 15:19:37 -070041
Linus Torvalds1da177e2005-04-16 15:20:36 -070042#include <asm/paccess.h>
43#include <asm/io.h>
44#include <asm/sgi/ip22.h>
Linus Torvalds1da177e2005-04-16 15:20:36 -070045#include <asm/sgi/mc.h>
46
47#include "vino.h"
Ralf Baechled203a7e2005-09-06 15:19:37 -070048#include "saa7191.h"
49#include "indycam.h"
Linus Torvalds1da177e2005-04-16 15:20:36 -070050
Ralf Baechled203a7e2005-09-06 15:19:37 -070051/* Uncomment the following line to get lots and lots of (mostly useless)
52 * debug info.
53 * Note that the debug output also slows down the driver significantly */
54// #define VINO_DEBUG
Ladislav Michla637a112005-09-01 15:07:34 +000055// #define VINO_DEBUG_INT
Ralf Baechled203a7e2005-09-06 15:19:37 -070056
Ladislav Michla637a112005-09-01 15:07:34 +000057#define VINO_MODULE_VERSION "0.0.5"
58#define VINO_VERSION_CODE KERNEL_VERSION(0, 0, 5)
Ralf Baechled203a7e2005-09-06 15:19:37 -070059
60MODULE_DESCRIPTION("SGI VINO Video4Linux2 driver");
61MODULE_VERSION(VINO_MODULE_VERSION);
62MODULE_AUTHOR("Mikael Nousiainen <tmnousia@cc.hut.fi>");
63MODULE_LICENSE("GPL");
64
Ralf Baechled203a7e2005-09-06 15:19:37 -070065#ifdef VINO_DEBUG
66#define dprintk(x...) printk("VINO: " x);
Linus Torvalds1da177e2005-04-16 15:20:36 -070067#else
Ralf Baechled203a7e2005-09-06 15:19:37 -070068#define dprintk(x...)
Linus Torvalds1da177e2005-04-16 15:20:36 -070069#endif
70
Ralf Baechled203a7e2005-09-06 15:19:37 -070071#define VINO_NO_CHANNEL 0
72#define VINO_CHANNEL_A 1
73#define VINO_CHANNEL_B 2
Linus Torvalds1da177e2005-04-16 15:20:36 -070074
Ralf Baechled203a7e2005-09-06 15:19:37 -070075#define VINO_PAL_WIDTH 768
76#define VINO_PAL_HEIGHT 576
77#define VINO_NTSC_WIDTH 640
78#define VINO_NTSC_HEIGHT 480
Linus Torvalds1da177e2005-04-16 15:20:36 -070079
Ralf Baechled203a7e2005-09-06 15:19:37 -070080#define VINO_MIN_WIDTH 32
81#define VINO_MIN_HEIGHT 32
Linus Torvalds1da177e2005-04-16 15:20:36 -070082
Ralf Baechled203a7e2005-09-06 15:19:37 -070083#define VINO_CLIPPING_START_ODD_D1 1
Ladislav Michla637a112005-09-01 15:07:34 +000084#define VINO_CLIPPING_START_ODD_PAL 15
85#define VINO_CLIPPING_START_ODD_NTSC 12
Ralf Baechled203a7e2005-09-06 15:19:37 -070086
87#define VINO_CLIPPING_START_EVEN_D1 2
Ladislav Michla637a112005-09-01 15:07:34 +000088#define VINO_CLIPPING_START_EVEN_PAL 15
89#define VINO_CLIPPING_START_EVEN_NTSC 12
Ralf Baechled203a7e2005-09-06 15:19:37 -070090
91#define VINO_INPUT_CHANNEL_COUNT 3
92
Ladislav Michla637a112005-09-01 15:07:34 +000093/* the number is the index for vino_inputs */
Ralf Baechled203a7e2005-09-06 15:19:37 -070094#define VINO_INPUT_NONE -1
95#define VINO_INPUT_COMPOSITE 0
96#define VINO_INPUT_SVIDEO 1
97#define VINO_INPUT_D1 2
98
99#define VINO_PAGE_RATIO (PAGE_SIZE / VINO_PAGE_SIZE)
100
Ladislav Michla637a112005-09-01 15:07:34 +0000101#define VINO_FIFO_THRESHOLD_DEFAULT 16
Ralf Baechled203a7e2005-09-06 15:19:37 -0700102
Ralf Baechled203a7e2005-09-06 15:19:37 -0700103#define VINO_FRAMEBUFFER_SIZE ((VINO_PAL_WIDTH \
104 * VINO_PAL_HEIGHT * 4 \
105 + 3 * PAGE_SIZE) & ~(PAGE_SIZE - 1))
106
Ladislav Michla637a112005-09-01 15:07:34 +0000107#define VINO_FRAMEBUFFER_COUNT_MAX 8
Ralf Baechled203a7e2005-09-06 15:19:37 -0700108
109#define VINO_FRAMEBUFFER_UNUSED 0
110#define VINO_FRAMEBUFFER_IN_USE 1
111#define VINO_FRAMEBUFFER_READY 2
112
113#define VINO_QUEUE_ERROR -1
114#define VINO_QUEUE_MAGIC 0x20050125
115
116#define VINO_MEMORY_NONE 0
117#define VINO_MEMORY_MMAP 1
118#define VINO_MEMORY_USERPTR 2
119
120#define VINO_DUMMY_DESC_COUNT 4
121#define VINO_DESC_FETCH_DELAY 5 /* microseconds */
122
Ladislav Michla637a112005-09-01 15:07:34 +0000123#define VINO_MAX_FRAME_SKIP_COUNT 128
124
Ralf Baechled203a7e2005-09-06 15:19:37 -0700125/* the number is the index for vino_data_formats */
126#define VINO_DATA_FMT_NONE -1
127#define VINO_DATA_FMT_GREY 0
128#define VINO_DATA_FMT_RGB332 1
129#define VINO_DATA_FMT_RGB32 2
130#define VINO_DATA_FMT_YUV 3
Ralf Baechled203a7e2005-09-06 15:19:37 -0700131
132#define VINO_DATA_FMT_COUNT 4
133
Ladislav Michla637a112005-09-01 15:07:34 +0000134/* the number is the index for vino_data_norms */
Ralf Baechled203a7e2005-09-06 15:19:37 -0700135#define VINO_DATA_NORM_NONE -1
136#define VINO_DATA_NORM_NTSC 0
137#define VINO_DATA_NORM_PAL 1
138#define VINO_DATA_NORM_SECAM 2
139#define VINO_DATA_NORM_D1 3
Ralf Baechled203a7e2005-09-06 15:19:37 -0700140
141#define VINO_DATA_NORM_COUNT 4
142
Jean Delvarecea0c682009-03-06 12:05:43 -0300143/* I2C controller flags */
144#define SGI_I2C_FORCE_IDLE (0 << 0)
145#define SGI_I2C_NOT_IDLE (1 << 0)
146#define SGI_I2C_WRITE (0 << 1)
147#define SGI_I2C_READ (1 << 1)
148#define SGI_I2C_RELEASE_BUS (0 << 2)
149#define SGI_I2C_HOLD_BUS (1 << 2)
150#define SGI_I2C_XFER_DONE (0 << 4)
151#define SGI_I2C_XFER_BUSY (1 << 4)
152#define SGI_I2C_ACK (0 << 5)
153#define SGI_I2C_NACK (1 << 5)
154#define SGI_I2C_BUS_OK (0 << 7)
155#define SGI_I2C_BUS_ERR (1 << 7)
156
Ralf Baechled203a7e2005-09-06 15:19:37 -0700157/* Internal data structure definitions */
158
159struct vino_input {
160 char *name;
161 v4l2_std_id std;
162};
163
164struct vino_clipping {
165 unsigned int left, right, top, bottom;
166};
167
168struct vino_data_format {
169 /* the description */
170 char *description;
171 /* bytes per pixel */
172 unsigned int bpp;
173 /* V4L2 fourcc code */
174 __u32 pixelformat;
175 /* V4L2 colorspace (duh!) */
176 enum v4l2_colorspace colorspace;
177};
178
179struct vino_data_norm {
180 char *description;
181 unsigned int width, height;
182 struct vino_clipping odd;
183 struct vino_clipping even;
184
185 v4l2_std_id std;
186 unsigned int fps_min, fps_max;
187 __u32 framelines;
188};
189
190struct vino_descriptor_table {
191 /* the number of PAGE_SIZE sized pages in the buffer */
192 unsigned int page_count;
193 /* virtual (kmalloc'd) pointers to the actual data
194 * (in PAGE_SIZE chunks, used with mmap streaming) */
195 unsigned long *virtual;
196
197 /* cpu address for the VINO descriptor table
198 * (contains DMA addresses, VINO_PAGE_SIZE chunks) */
199 unsigned long *dma_cpu;
200 /* dma address for the VINO descriptor table
201 * (contains DMA addresses, VINO_PAGE_SIZE chunks) */
202 dma_addr_t dma;
203};
204
205struct vino_framebuffer {
206 /* identifier nubmer */
207 unsigned int id;
208 /* the length of the whole buffer */
209 unsigned int size;
210 /* the length of actual data in buffer */
211 unsigned int data_size;
212 /* the data format */
213 unsigned int data_format;
214 /* the state of buffer data */
215 unsigned int state;
216 /* is the buffer mapped in user space? */
217 unsigned int map_count;
218 /* memory offset for mmap() */
219 unsigned int offset;
220 /* frame counter */
221 unsigned int frame_counter;
222 /* timestamp (written when image capture finishes) */
223 struct timeval timestamp;
224
225 struct vino_descriptor_table desc_table;
226
227 spinlock_t state_lock;
228};
229
230struct vino_framebuffer_fifo {
231 unsigned int length;
232
233 unsigned int used;
234 unsigned int head;
235 unsigned int tail;
236
Ladislav Michla637a112005-09-01 15:07:34 +0000237 unsigned int data[VINO_FRAMEBUFFER_COUNT_MAX];
Ralf Baechled203a7e2005-09-06 15:19:37 -0700238};
239
240struct vino_framebuffer_queue {
241 unsigned int magic;
242
243 /* VINO_MEMORY_NONE, VINO_MEMORY_MMAP or VINO_MEMORY_USERPTR */
244 unsigned int type;
245 unsigned int length;
246
247 /* data field of in and out contain index numbers for buffer */
248 struct vino_framebuffer_fifo in;
249 struct vino_framebuffer_fifo out;
250
Ladislav Michla637a112005-09-01 15:07:34 +0000251 struct vino_framebuffer *buffer[VINO_FRAMEBUFFER_COUNT_MAX];
Ralf Baechled203a7e2005-09-06 15:19:37 -0700252
253 spinlock_t queue_lock;
Ingo Molnar3593cab2006-02-07 06:49:14 -0200254 struct mutex queue_mutex;
Ralf Baechled203a7e2005-09-06 15:19:37 -0700255 wait_queue_head_t frame_wait_queue;
256};
257
Ladislav Michla637a112005-09-01 15:07:34 +0000258struct vino_interrupt_data {
259 struct timeval timestamp;
260 unsigned int frame_counter;
261 unsigned int skip_count;
262 unsigned int skip;
263};
264
Ralf Baechled203a7e2005-09-06 15:19:37 -0700265struct vino_channel_settings {
266 unsigned int channel;
267
268 int input;
269 unsigned int data_format;
270 unsigned int data_norm;
271 struct vino_clipping clipping;
272 unsigned int decimation;
273 unsigned int line_size;
274 unsigned int alpha;
275 unsigned int fps;
276 unsigned int framert_reg;
277
278 unsigned int fifo_threshold;
279
280 struct vino_framebuffer_queue fb_queue;
281
282 /* number of the current field */
283 unsigned int field;
284
285 /* read in progress */
286 int reading;
287 /* streaming is active */
288 int streaming;
289 /* the driver is currently processing the queue */
290 int capturing;
291
Ingo Molnar3593cab2006-02-07 06:49:14 -0200292 struct mutex mutex;
Ralf Baechled203a7e2005-09-06 15:19:37 -0700293 spinlock_t capture_lock;
294
295 unsigned int users;
296
Ladislav Michla637a112005-09-01 15:07:34 +0000297 struct vino_interrupt_data int_data;
298
Ralf Baechled203a7e2005-09-06 15:19:37 -0700299 /* V4L support */
Hans Verkuil0ef4dba2009-02-12 11:31:13 -0300300 struct video_device *vdev;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700301};
302
Ralf Baechled203a7e2005-09-06 15:19:37 -0700303struct vino_settings {
Hans Verkuil28959632009-02-18 18:53:47 -0300304 struct v4l2_device v4l2_dev;
Ralf Baechled203a7e2005-09-06 15:19:37 -0700305 struct vino_channel_settings a;
306 struct vino_channel_settings b;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700307
Hans Verkuil48f4dac2009-02-18 19:18:26 -0300308 /* the channel which owns this client:
309 * VINO_NO_CHANNEL, VINO_CHANNEL_A or VINO_CHANNEL_B */
310 unsigned int decoder_owner;
311 struct v4l2_subdev *decoder;
312 unsigned int camera_owner;
313 struct v4l2_subdev *camera;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700314
Ralf Baechled203a7e2005-09-06 15:19:37 -0700315 /* a lock for vino register access */
316 spinlock_t vino_lock;
317 /* a lock for channel input changes */
318 spinlock_t input_lock;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700319
Linus Torvalds1da177e2005-04-16 15:20:36 -0700320 unsigned long dummy_page;
Ralf Baechled203a7e2005-09-06 15:19:37 -0700321 struct vino_descriptor_table dummy_desc_table;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700322};
323
Ralf Baechled203a7e2005-09-06 15:19:37 -0700324/* Module parameters */
325
326/*
Ladislav Michla637a112005-09-01 15:07:34 +0000327 * Using vino_pixel_conversion the ABGR32-format pixels supplied
Ralf Baechled203a7e2005-09-06 15:19:37 -0700328 * by the VINO chip can be converted to more common formats
329 * like RGBA32 (or probably RGB24 in the future). This way we
330 * can give out data that can be specified correctly with
331 * the V4L2-definitions.
332 *
333 * The pixel format is specified as RGBA32 when no conversion
334 * is used.
335 *
336 * Note that this only affects the 32-bit bit depth.
337 *
338 * Use non-zero value to enable conversion.
339 */
Douglas Schilling Landgrafff699e62008-04-22 14:41:48 -0300340static int vino_pixel_conversion;
Ladislav Michla637a112005-09-01 15:07:34 +0000341
Ralf Baechled203a7e2005-09-06 15:19:37 -0700342module_param_named(pixelconv, vino_pixel_conversion, int, 0);
Ladislav Michla637a112005-09-01 15:07:34 +0000343
Ralf Baechled203a7e2005-09-06 15:19:37 -0700344MODULE_PARM_DESC(pixelconv,
345 "enable pixel conversion (non-zero value enables)");
346
347/* Internal data structures */
348
349static struct sgi_vino *vino;
350
351static struct vino_settings *vino_drvdata;
352
Hans Verkuil48f4dac2009-02-18 19:18:26 -0300353#define camera_call(o, f, args...) \
354 v4l2_subdev_call(vino_drvdata->camera, o, f, ##args)
355#define decoder_call(o, f, args...) \
356 v4l2_subdev_call(vino_drvdata->decoder, o, f, ##args)
357
Ralf Baechled203a7e2005-09-06 15:19:37 -0700358static const char *vino_driver_name = "vino";
359static const char *vino_driver_description = "SGI VINO";
360static const char *vino_bus_name = "GIO64 bus";
Hans Verkuil0ef4dba2009-02-12 11:31:13 -0300361static const char *vino_vdev_name_a = "SGI VINO Channel A";
362static const char *vino_vdev_name_b = "SGI VINO Channel B";
Ralf Baechled203a7e2005-09-06 15:19:37 -0700363
Ladislav Michla637a112005-09-01 15:07:34 +0000364static void vino_capture_tasklet(unsigned long channel);
365
366DECLARE_TASKLET(vino_tasklet_a, vino_capture_tasklet, VINO_CHANNEL_A);
367DECLARE_TASKLET(vino_tasklet_b, vino_capture_tasklet, VINO_CHANNEL_B);
368
Ralf Baechled203a7e2005-09-06 15:19:37 -0700369static const struct vino_input vino_inputs[] = {
370 {
371 .name = "Composite",
Ladislav Michla637a112005-09-01 15:07:34 +0000372 .std = V4L2_STD_NTSC | V4L2_STD_PAL
373 | V4L2_STD_SECAM,
Hans Verkuilcf4e9482009-02-27 09:05:10 -0300374 }, {
Ralf Baechled203a7e2005-09-06 15:19:37 -0700375 .name = "S-Video",
Ladislav Michla637a112005-09-01 15:07:34 +0000376 .std = V4L2_STD_NTSC | V4L2_STD_PAL
377 | V4L2_STD_SECAM,
Hans Verkuilcf4e9482009-02-27 09:05:10 -0300378 }, {
Ladislav Michla637a112005-09-01 15:07:34 +0000379 .name = "D1/IndyCam",
Ralf Baechled203a7e2005-09-06 15:19:37 -0700380 .std = V4L2_STD_NTSC,
381 }
382};
383
384static const struct vino_data_format vino_data_formats[] = {
385 {
386 .description = "8-bit greyscale",
387 .bpp = 1,
388 .pixelformat = V4L2_PIX_FMT_GREY,
389 .colorspace = V4L2_COLORSPACE_SMPTE170M,
Hans Verkuilcf4e9482009-02-27 09:05:10 -0300390 }, {
Ralf Baechled203a7e2005-09-06 15:19:37 -0700391 .description = "8-bit dithered RGB 3-3-2",
392 .bpp = 1,
393 .pixelformat = V4L2_PIX_FMT_RGB332,
394 .colorspace = V4L2_COLORSPACE_SRGB,
Hans Verkuilcf4e9482009-02-27 09:05:10 -0300395 }, {
Ralf Baechled203a7e2005-09-06 15:19:37 -0700396 .description = "32-bit RGB",
397 .bpp = 4,
398 .pixelformat = V4L2_PIX_FMT_RGB32,
399 .colorspace = V4L2_COLORSPACE_SRGB,
Hans Verkuilcf4e9482009-02-27 09:05:10 -0300400 }, {
Ralf Baechled203a7e2005-09-06 15:19:37 -0700401 .description = "YUV 4:2:2",
Ladislav Michla637a112005-09-01 15:07:34 +0000402 .bpp = 2,
Ralf Baechled203a7e2005-09-06 15:19:37 -0700403 .pixelformat = V4L2_PIX_FMT_YUYV, // XXX: swapped?
404 .colorspace = V4L2_COLORSPACE_SMPTE170M,
Ladislav Michla637a112005-09-01 15:07:34 +0000405 }
Ralf Baechled203a7e2005-09-06 15:19:37 -0700406};
407
408static const struct vino_data_norm vino_data_norms[] = {
409 {
410 .description = "NTSC",
411 .std = V4L2_STD_NTSC,
412 .fps_min = 6,
413 .fps_max = 30,
414 .framelines = 525,
415 .width = VINO_NTSC_WIDTH,
416 .height = VINO_NTSC_HEIGHT,
417 .odd = {
Ladislav Michla637a112005-09-01 15:07:34 +0000418 .top = VINO_CLIPPING_START_ODD_NTSC,
419 .left = 0,
Ralf Baechled203a7e2005-09-06 15:19:37 -0700420 .bottom = VINO_CLIPPING_START_ODD_NTSC
421 + VINO_NTSC_HEIGHT / 2 - 1,
Ladislav Michla637a112005-09-01 15:07:34 +0000422 .right = VINO_NTSC_WIDTH,
Ralf Baechled203a7e2005-09-06 15:19:37 -0700423 },
424 .even = {
Ladislav Michla637a112005-09-01 15:07:34 +0000425 .top = VINO_CLIPPING_START_EVEN_NTSC,
426 .left = 0,
Ralf Baechled203a7e2005-09-06 15:19:37 -0700427 .bottom = VINO_CLIPPING_START_EVEN_NTSC
428 + VINO_NTSC_HEIGHT / 2 - 1,
Ladislav Michla637a112005-09-01 15:07:34 +0000429 .right = VINO_NTSC_WIDTH,
Ralf Baechled203a7e2005-09-06 15:19:37 -0700430 },
Hans Verkuilcf4e9482009-02-27 09:05:10 -0300431 }, {
Ralf Baechled203a7e2005-09-06 15:19:37 -0700432 .description = "PAL",
433 .std = V4L2_STD_PAL,
434 .fps_min = 5,
435 .fps_max = 25,
436 .framelines = 625,
437 .width = VINO_PAL_WIDTH,
438 .height = VINO_PAL_HEIGHT,
439 .odd = {
Ladislav Michla637a112005-09-01 15:07:34 +0000440 .top = VINO_CLIPPING_START_ODD_PAL,
441 .left = 0,
Ralf Baechled203a7e2005-09-06 15:19:37 -0700442 .bottom = VINO_CLIPPING_START_ODD_PAL
443 + VINO_PAL_HEIGHT / 2 - 1,
Ladislav Michla637a112005-09-01 15:07:34 +0000444 .right = VINO_PAL_WIDTH,
Ralf Baechled203a7e2005-09-06 15:19:37 -0700445 },
446 .even = {
Ladislav Michla637a112005-09-01 15:07:34 +0000447 .top = VINO_CLIPPING_START_EVEN_PAL,
448 .left = 0,
Ralf Baechled203a7e2005-09-06 15:19:37 -0700449 .bottom = VINO_CLIPPING_START_EVEN_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 },
Hans Verkuilcf4e9482009-02-27 09:05:10 -0300453 }, {
Ralf Baechled203a7e2005-09-06 15:19:37 -0700454 .description = "SECAM",
455 .std = V4L2_STD_SECAM,
456 .fps_min = 5,
457 .fps_max = 25,
458 .framelines = 625,
459 .width = VINO_PAL_WIDTH,
460 .height = VINO_PAL_HEIGHT,
461 .odd = {
Ladislav Michla637a112005-09-01 15:07:34 +0000462 .top = VINO_CLIPPING_START_ODD_PAL,
463 .left = 0,
Ralf Baechled203a7e2005-09-06 15:19:37 -0700464 .bottom = VINO_CLIPPING_START_ODD_PAL
465 + VINO_PAL_HEIGHT / 2 - 1,
Ladislav Michla637a112005-09-01 15:07:34 +0000466 .right = VINO_PAL_WIDTH,
Ralf Baechled203a7e2005-09-06 15:19:37 -0700467 },
468 .even = {
Ladislav Michla637a112005-09-01 15:07:34 +0000469 .top = VINO_CLIPPING_START_EVEN_PAL,
470 .left = 0,
Ralf Baechled203a7e2005-09-06 15:19:37 -0700471 .bottom = VINO_CLIPPING_START_EVEN_PAL
472 + VINO_PAL_HEIGHT / 2 - 1,
Ladislav Michla637a112005-09-01 15:07:34 +0000473 .right = VINO_PAL_WIDTH,
Ralf Baechled203a7e2005-09-06 15:19:37 -0700474 },
Hans Verkuilcf4e9482009-02-27 09:05:10 -0300475 }, {
Ladislav Michla637a112005-09-01 15:07:34 +0000476 .description = "NTSC/D1",
Ralf Baechled203a7e2005-09-06 15:19:37 -0700477 .std = V4L2_STD_NTSC,
478 .fps_min = 6,
479 .fps_max = 30,
480 .framelines = 525,
481 .width = VINO_NTSC_WIDTH,
482 .height = VINO_NTSC_HEIGHT,
483 .odd = {
Ladislav Michla637a112005-09-01 15:07:34 +0000484 .top = VINO_CLIPPING_START_ODD_D1,
485 .left = 0,
Ralf Baechled203a7e2005-09-06 15:19:37 -0700486 .bottom = VINO_CLIPPING_START_ODD_D1
487 + VINO_NTSC_HEIGHT / 2 - 1,
Ladislav Michla637a112005-09-01 15:07:34 +0000488 .right = VINO_NTSC_WIDTH,
Ralf Baechled203a7e2005-09-06 15:19:37 -0700489 },
490 .even = {
Ladislav Michla637a112005-09-01 15:07:34 +0000491 .top = VINO_CLIPPING_START_EVEN_D1,
492 .left = 0,
Ralf Baechled203a7e2005-09-06 15:19:37 -0700493 .bottom = VINO_CLIPPING_START_EVEN_D1
494 + VINO_NTSC_HEIGHT / 2 - 1,
Ladislav Michla637a112005-09-01 15:07:34 +0000495 .right = VINO_NTSC_WIDTH,
Ralf Baechled203a7e2005-09-06 15:19:37 -0700496 },
497 }
498};
499
500#define VINO_INDYCAM_V4L2_CONTROL_COUNT 9
501
502struct v4l2_queryctrl vino_indycam_v4l2_controls[] = {
503 {
504 .id = V4L2_CID_AUTOGAIN,
505 .type = V4L2_CTRL_TYPE_BOOLEAN,
506 .name = "Automatic Gain Control",
507 .minimum = 0,
508 .maximum = 1,
509 .step = 1,
510 .default_value = INDYCAM_AGC_DEFAULT,
Hans Verkuilcf4e9482009-02-27 09:05:10 -0300511 }, {
Ralf Baechled203a7e2005-09-06 15:19:37 -0700512 .id = V4L2_CID_AUTO_WHITE_BALANCE,
513 .type = V4L2_CTRL_TYPE_BOOLEAN,
514 .name = "Automatic White Balance",
515 .minimum = 0,
516 .maximum = 1,
517 .step = 1,
518 .default_value = INDYCAM_AWB_DEFAULT,
Hans Verkuilcf4e9482009-02-27 09:05:10 -0300519 }, {
Ralf Baechled203a7e2005-09-06 15:19:37 -0700520 .id = V4L2_CID_GAIN,
521 .type = V4L2_CTRL_TYPE_INTEGER,
522 .name = "Gain",
523 .minimum = INDYCAM_GAIN_MIN,
524 .maximum = INDYCAM_GAIN_MAX,
525 .step = 1,
526 .default_value = INDYCAM_GAIN_DEFAULT,
Hans Verkuilcf4e9482009-02-27 09:05:10 -0300527 }, {
528 .id = INDYCAM_CONTROL_RED_SATURATION,
Ralf Baechled203a7e2005-09-06 15:19:37 -0700529 .type = V4L2_CTRL_TYPE_INTEGER,
530 .name = "Red Saturation",
531 .minimum = INDYCAM_RED_SATURATION_MIN,
532 .maximum = INDYCAM_RED_SATURATION_MAX,
533 .step = 1,
534 .default_value = INDYCAM_RED_SATURATION_DEFAULT,
Hans Verkuilcf4e9482009-02-27 09:05:10 -0300535 }, {
536 .id = INDYCAM_CONTROL_BLUE_SATURATION,
Ralf Baechled203a7e2005-09-06 15:19:37 -0700537 .type = V4L2_CTRL_TYPE_INTEGER,
538 .name = "Blue Saturation",
539 .minimum = INDYCAM_BLUE_SATURATION_MIN,
540 .maximum = INDYCAM_BLUE_SATURATION_MAX,
541 .step = 1,
542 .default_value = INDYCAM_BLUE_SATURATION_DEFAULT,
Hans Verkuilcf4e9482009-02-27 09:05:10 -0300543 }, {
Ralf Baechled203a7e2005-09-06 15:19:37 -0700544 .id = V4L2_CID_RED_BALANCE,
545 .type = V4L2_CTRL_TYPE_INTEGER,
546 .name = "Red Balance",
547 .minimum = INDYCAM_RED_BALANCE_MIN,
548 .maximum = INDYCAM_RED_BALANCE_MAX,
549 .step = 1,
550 .default_value = INDYCAM_RED_BALANCE_DEFAULT,
Hans Verkuilcf4e9482009-02-27 09:05:10 -0300551 }, {
Ralf Baechled203a7e2005-09-06 15:19:37 -0700552 .id = V4L2_CID_BLUE_BALANCE,
553 .type = V4L2_CTRL_TYPE_INTEGER,
554 .name = "Blue Balance",
555 .minimum = INDYCAM_BLUE_BALANCE_MIN,
556 .maximum = INDYCAM_BLUE_BALANCE_MAX,
557 .step = 1,
558 .default_value = INDYCAM_BLUE_BALANCE_DEFAULT,
Hans Verkuilcf4e9482009-02-27 09:05:10 -0300559 }, {
Ralf Baechled203a7e2005-09-06 15:19:37 -0700560 .id = V4L2_CID_EXPOSURE,
561 .type = V4L2_CTRL_TYPE_INTEGER,
562 .name = "Shutter Control",
563 .minimum = INDYCAM_SHUTTER_MIN,
564 .maximum = INDYCAM_SHUTTER_MAX,
565 .step = 1,
566 .default_value = INDYCAM_SHUTTER_DEFAULT,
Hans Verkuilcf4e9482009-02-27 09:05:10 -0300567 }, {
Ralf Baechled203a7e2005-09-06 15:19:37 -0700568 .id = V4L2_CID_GAMMA,
569 .type = V4L2_CTRL_TYPE_INTEGER,
570 .name = "Gamma",
571 .minimum = INDYCAM_GAMMA_MIN,
572 .maximum = INDYCAM_GAMMA_MAX,
573 .step = 1,
574 .default_value = INDYCAM_GAMMA_DEFAULT,
Ralf Baechled203a7e2005-09-06 15:19:37 -0700575 }
576};
577
Ladislav Michla637a112005-09-01 15:07:34 +0000578#define VINO_SAA7191_V4L2_CONTROL_COUNT 9
Ralf Baechled203a7e2005-09-06 15:19:37 -0700579
580struct v4l2_queryctrl vino_saa7191_v4l2_controls[] = {
581 {
582 .id = V4L2_CID_HUE,
583 .type = V4L2_CTRL_TYPE_INTEGER,
584 .name = "Hue",
585 .minimum = SAA7191_HUE_MIN,
586 .maximum = SAA7191_HUE_MAX,
587 .step = 1,
588 .default_value = SAA7191_HUE_DEFAULT,
Hans Verkuilcf4e9482009-02-27 09:05:10 -0300589 }, {
590 .id = SAA7191_CONTROL_BANDPASS,
Ladislav Michla637a112005-09-01 15:07:34 +0000591 .type = V4L2_CTRL_TYPE_INTEGER,
592 .name = "Luminance Bandpass",
593 .minimum = SAA7191_BANDPASS_MIN,
594 .maximum = SAA7191_BANDPASS_MAX,
595 .step = 1,
596 .default_value = SAA7191_BANDPASS_DEFAULT,
Hans Verkuilcf4e9482009-02-27 09:05:10 -0300597 }, {
598 .id = SAA7191_CONTROL_BANDPASS_WEIGHT,
Ladislav Michla637a112005-09-01 15:07:34 +0000599 .type = V4L2_CTRL_TYPE_INTEGER,
600 .name = "Luminance Bandpass Weight",
601 .minimum = SAA7191_BANDPASS_WEIGHT_MIN,
602 .maximum = SAA7191_BANDPASS_WEIGHT_MAX,
603 .step = 1,
604 .default_value = SAA7191_BANDPASS_WEIGHT_DEFAULT,
Hans Verkuilcf4e9482009-02-27 09:05:10 -0300605 }, {
606 .id = SAA7191_CONTROL_CORING,
Ladislav Michla637a112005-09-01 15:07:34 +0000607 .type = V4L2_CTRL_TYPE_INTEGER,
608 .name = "HF Luminance Coring",
609 .minimum = SAA7191_CORING_MIN,
610 .maximum = SAA7191_CORING_MAX,
611 .step = 1,
612 .default_value = SAA7191_CORING_DEFAULT,
Hans Verkuilcf4e9482009-02-27 09:05:10 -0300613 }, {
614 .id = SAA7191_CONTROL_FORCE_COLOUR,
Ladislav Michla637a112005-09-01 15:07:34 +0000615 .type = V4L2_CTRL_TYPE_BOOLEAN,
616 .name = "Force Colour",
617 .minimum = SAA7191_FORCE_COLOUR_MIN,
618 .maximum = SAA7191_FORCE_COLOUR_MAX,
619 .step = 1,
620 .default_value = SAA7191_FORCE_COLOUR_DEFAULT,
Hans Verkuilcf4e9482009-02-27 09:05:10 -0300621 }, {
622 .id = SAA7191_CONTROL_CHROMA_GAIN,
Ladislav Michla637a112005-09-01 15:07:34 +0000623 .type = V4L2_CTRL_TYPE_INTEGER,
624 .name = "Chrominance Gain Control",
625 .minimum = SAA7191_CHROMA_GAIN_MIN,
626 .maximum = SAA7191_CHROMA_GAIN_MAX,
627 .step = 1,
628 .default_value = SAA7191_CHROMA_GAIN_DEFAULT,
Hans Verkuilcf4e9482009-02-27 09:05:10 -0300629 }, {
630 .id = SAA7191_CONTROL_VTRC,
Ralf Baechled203a7e2005-09-06 15:19:37 -0700631 .type = V4L2_CTRL_TYPE_BOOLEAN,
632 .name = "VTR Time Constant",
633 .minimum = SAA7191_VTRC_MIN,
634 .maximum = SAA7191_VTRC_MAX,
635 .step = 1,
636 .default_value = SAA7191_VTRC_DEFAULT,
Hans Verkuilcf4e9482009-02-27 09:05:10 -0300637 }, {
638 .id = SAA7191_CONTROL_LUMA_DELAY,
Ladislav Michla637a112005-09-01 15:07:34 +0000639 .type = V4L2_CTRL_TYPE_INTEGER,
640 .name = "Luminance Delay Compensation",
641 .minimum = SAA7191_LUMA_DELAY_MIN,
642 .maximum = SAA7191_LUMA_DELAY_MAX,
643 .step = 1,
644 .default_value = SAA7191_LUMA_DELAY_DEFAULT,
Hans Verkuilcf4e9482009-02-27 09:05:10 -0300645 }, {
646 .id = SAA7191_CONTROL_VNR,
Ladislav Michla637a112005-09-01 15:07:34 +0000647 .type = V4L2_CTRL_TYPE_INTEGER,
648 .name = "Vertical Noise Reduction",
649 .minimum = SAA7191_VNR_MIN,
650 .maximum = SAA7191_VNR_MAX,
651 .step = 1,
652 .default_value = SAA7191_VNR_DEFAULT,
Ralf Baechled203a7e2005-09-06 15:19:37 -0700653 }
654};
655
Ralf Baechled203a7e2005-09-06 15:19:37 -0700656/* VINO framebuffer/DMA descriptor management */
657
658static void vino_free_buffer_with_count(struct vino_framebuffer *fb,
659 unsigned int count)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700660{
Ralf Baechled203a7e2005-09-06 15:19:37 -0700661 unsigned int i;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700662
Ralf Baechled203a7e2005-09-06 15:19:37 -0700663 dprintk("vino_free_buffer_with_count(): count = %d\n", count);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700664
Ralf Baechled203a7e2005-09-06 15:19:37 -0700665 for (i = 0; i < count; i++) {
Hans Verkuileda9e4e2008-08-22 17:12:08 -0300666 ClearPageReserved(virt_to_page((void *)fb->desc_table.virtual[i]));
Ralf Baechled203a7e2005-09-06 15:19:37 -0700667 dma_unmap_single(NULL,
668 fb->desc_table.dma_cpu[VINO_PAGE_RATIO * i],
669 PAGE_SIZE, DMA_FROM_DEVICE);
670 free_page(fb->desc_table.virtual[i]);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700671 }
672
Ralf Baechled203a7e2005-09-06 15:19:37 -0700673 dma_free_coherent(NULL,
674 VINO_PAGE_RATIO * (fb->desc_table.page_count + 4) *
675 sizeof(dma_addr_t), (void *)fb->desc_table.dma_cpu,
676 fb->desc_table.dma);
677 kfree(fb->desc_table.virtual);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700678
Ralf Baechled203a7e2005-09-06 15:19:37 -0700679 memset(fb, 0, sizeof(struct vino_framebuffer));
680}
Linus Torvalds1da177e2005-04-16 15:20:36 -0700681
Ralf Baechled203a7e2005-09-06 15:19:37 -0700682static void vino_free_buffer(struct vino_framebuffer *fb)
683{
684 vino_free_buffer_with_count(fb, fb->desc_table.page_count);
685}
686
687static int vino_allocate_buffer(struct vino_framebuffer *fb,
688 unsigned int size)
689{
690 unsigned int count, i, j;
691 int ret = 0;
692
693 dprintk("vino_allocate_buffer():\n");
694
695 if (size < 1)
696 return -EINVAL;
697
698 memset(fb, 0, sizeof(struct vino_framebuffer));
699
700 count = ((size / PAGE_SIZE) + 4) & ~3;
701
702 dprintk("vino_allocate_buffer(): size = %d, count = %d\n",
703 size, count);
704
705 /* allocate memory for table with virtual (page) addresses */
706 fb->desc_table.virtual = (unsigned long *)
707 kmalloc(count * sizeof(unsigned long), GFP_KERNEL);
708 if (!fb->desc_table.virtual)
709 return -ENOMEM;
710
711 /* allocate memory for table with dma addresses
712 * (has space for four extra descriptors) */
713 fb->desc_table.dma_cpu =
714 dma_alloc_coherent(NULL, VINO_PAGE_RATIO * (count + 4) *
715 sizeof(dma_addr_t), &fb->desc_table.dma,
716 GFP_KERNEL | GFP_DMA);
717 if (!fb->desc_table.dma_cpu) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700718 ret = -ENOMEM;
Ralf Baechled203a7e2005-09-06 15:19:37 -0700719 goto out_free_virtual;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700720 }
721
Ralf Baechled203a7e2005-09-06 15:19:37 -0700722 /* allocate pages for the buffer and acquire the according
723 * dma addresses */
724 for (i = 0; i < count; i++) {
725 dma_addr_t dma_data_addr;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700726
Ralf Baechled203a7e2005-09-06 15:19:37 -0700727 fb->desc_table.virtual[i] =
728 get_zeroed_page(GFP_KERNEL | GFP_DMA);
729 if (!fb->desc_table.virtual[i]) {
730 ret = -ENOBUFS;
731 break;
732 }
Linus Torvalds1da177e2005-04-16 15:20:36 -0700733
Ralf Baechled203a7e2005-09-06 15:19:37 -0700734 dma_data_addr =
735 dma_map_single(NULL,
736 (void *)fb->desc_table.virtual[i],
737 PAGE_SIZE, DMA_FROM_DEVICE);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700738
Ralf Baechled203a7e2005-09-06 15:19:37 -0700739 for (j = 0; j < VINO_PAGE_RATIO; j++) {
740 fb->desc_table.dma_cpu[VINO_PAGE_RATIO * i + j] =
741 dma_data_addr + VINO_PAGE_SIZE * j;
742 }
743
Hans Verkuileda9e4e2008-08-22 17:12:08 -0300744 SetPageReserved(virt_to_page((void *)fb->desc_table.virtual[i]));
Linus Torvalds1da177e2005-04-16 15:20:36 -0700745 }
746
Ralf Baechled203a7e2005-09-06 15:19:37 -0700747 /* page_count needs to be set anyway, because the descriptor table has
748 * been allocated according to this number */
749 fb->desc_table.page_count = count;
750
Linus Torvalds1da177e2005-04-16 15:20:36 -0700751 if (ret) {
Ralf Baechled203a7e2005-09-06 15:19:37 -0700752 /* the descriptor with index i doesn't contain
753 * a valid address yet */
754 vino_free_buffer_with_count(fb, i);
755 return ret;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700756 }
757
Ralf Baechled203a7e2005-09-06 15:19:37 -0700758 //fb->size = size;
759 fb->size = count * PAGE_SIZE;
760 fb->data_format = VINO_DATA_FMT_NONE;
761
762 /* set the dma stop-bit for the last (count+1)th descriptor */
763 fb->desc_table.dma_cpu[VINO_PAGE_RATIO * count] = VINO_DESC_STOP;
764 return 0;
765
766 out_free_virtual:
767 kfree(fb->desc_table.virtual);
768 return ret;
769}
770
771#if 0
772/* user buffers not fully implemented yet */
773static int vino_prepare_user_buffer(struct vino_framebuffer *fb,
774 void *user,
775 unsigned int size)
776{
777 unsigned int count, i, j;
778 int ret = 0;
779
780 dprintk("vino_prepare_user_buffer():\n");
781
782 if (size < 1)
783 return -EINVAL;
784
785 memset(fb, 0, sizeof(struct vino_framebuffer));
786
787 count = ((size / PAGE_SIZE)) & ~3;
788
789 dprintk("vino_prepare_user_buffer(): size = %d, count = %d\n",
790 size, count);
791
792 /* allocate memory for table with virtual (page) addresses */
793 fb->desc_table.virtual = (unsigned long *)
794 kmalloc(count * sizeof(unsigned long), GFP_KERNEL);
795 if (!fb->desc_table.virtual)
796 return -ENOMEM;
797
798 /* allocate memory for table with dma addresses
799 * (has space for four extra descriptors) */
800 fb->desc_table.dma_cpu =
801 dma_alloc_coherent(NULL, VINO_PAGE_RATIO * (count + 4) *
802 sizeof(dma_addr_t), &fb->desc_table.dma,
803 GFP_KERNEL | GFP_DMA);
804 if (!fb->desc_table.dma_cpu) {
805 ret = -ENOMEM;
806 goto out_free_virtual;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700807 }
Ralf Baechled203a7e2005-09-06 15:19:37 -0700808
809 /* allocate pages for the buffer and acquire the according
810 * dma addresses */
811 for (i = 0; i < count; i++) {
812 dma_addr_t dma_data_addr;
813
814 fb->desc_table.virtual[i] =
815 get_zeroed_page(GFP_KERNEL | GFP_DMA);
816 if (!fb->desc_table.virtual[i]) {
817 ret = -ENOBUFS;
818 break;
819 }
820
821 dma_data_addr =
822 dma_map_single(NULL,
823 (void *)fb->desc_table.virtual[i],
824 PAGE_SIZE, DMA_FROM_DEVICE);
825
826 for (j = 0; j < VINO_PAGE_RATIO; j++) {
827 fb->desc_table.dma_cpu[VINO_PAGE_RATIO * i + j] =
828 dma_data_addr + VINO_PAGE_SIZE * j;
829 }
830
Hans Verkuileda9e4e2008-08-22 17:12:08 -0300831 SetPageReserved(virt_to_page((void *)fb->desc_table.virtual[i]));
Ralf Baechled203a7e2005-09-06 15:19:37 -0700832 }
833
834 /* page_count needs to be set anyway, because the descriptor table has
835 * been allocated according to this number */
836 fb->desc_table.page_count = count;
837
838 if (ret) {
839 /* the descriptor with index i doesn't contain
840 * a valid address yet */
841 vino_free_buffer_with_count(fb, i);
842 return ret;
843 }
844
845 //fb->size = size;
846 fb->size = count * PAGE_SIZE;
847
848 /* set the dma stop-bit for the last (count+1)th descriptor */
849 fb->desc_table.dma_cpu[VINO_PAGE_RATIO * count] = VINO_DESC_STOP;
850 return 0;
851
852 out_free_virtual:
853 kfree(fb->desc_table.virtual);
854 return ret;
855}
856#endif
857
858static void vino_sync_buffer(struct vino_framebuffer *fb)
859{
860 int i;
861
862 dprintk("vino_sync_buffer():\n");
863
864 for (i = 0; i < fb->desc_table.page_count; i++)
865 dma_sync_single(NULL,
866 fb->desc_table.dma_cpu[VINO_PAGE_RATIO * i],
867 PAGE_SIZE, DMA_FROM_DEVICE);
868}
869
870/* Framebuffer fifo functions (need to be locked externally) */
871
Ladislav Michla637a112005-09-01 15:07:34 +0000872static inline void vino_fifo_init(struct vino_framebuffer_fifo *f,
Ralf Baechled203a7e2005-09-06 15:19:37 -0700873 unsigned int length)
874{
875 f->length = 0;
876 f->used = 0;
877 f->head = 0;
878 f->tail = 0;
879
Ladislav Michla637a112005-09-01 15:07:34 +0000880 if (length > VINO_FRAMEBUFFER_COUNT_MAX)
881 length = VINO_FRAMEBUFFER_COUNT_MAX;
Ralf Baechled203a7e2005-09-06 15:19:37 -0700882
883 f->length = length;
884}
885
886/* returns true/false */
Ladislav Michla637a112005-09-01 15:07:34 +0000887static inline int vino_fifo_has_id(struct vino_framebuffer_fifo *f,
888 unsigned int id)
Ralf Baechled203a7e2005-09-06 15:19:37 -0700889{
890 unsigned int i;
Ladislav Michla637a112005-09-01 15:07:34 +0000891
Ralf Baechled203a7e2005-09-06 15:19:37 -0700892 for (i = f->head; i == (f->tail - 1); i = (i + 1) % f->length) {
893 if (f->data[i] == id)
894 return 1;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700895 }
896
897 return 0;
Ralf Baechled203a7e2005-09-06 15:19:37 -0700898}
Linus Torvalds1da177e2005-04-16 15:20:36 -0700899
Ladislav Michla637a112005-09-01 15:07:34 +0000900#if 0
Ralf Baechled203a7e2005-09-06 15:19:37 -0700901/* returns true/false */
Ladislav Michla637a112005-09-01 15:07:34 +0000902static inline int vino_fifo_full(struct vino_framebuffer_fifo *f)
Ralf Baechled203a7e2005-09-06 15:19:37 -0700903{
904 return (f->used == f->length);
905}
Ladislav Michla637a112005-09-01 15:07:34 +0000906#endif
Ralf Baechled203a7e2005-09-06 15:19:37 -0700907
Ladislav Michla637a112005-09-01 15:07:34 +0000908static inline unsigned int vino_fifo_get_used(struct vino_framebuffer_fifo *f)
Ralf Baechled203a7e2005-09-06 15:19:37 -0700909{
910 return f->used;
911}
912
913static int vino_fifo_enqueue(struct vino_framebuffer_fifo *f, unsigned int id)
914{
915 if (id >= f->length) {
916 return VINO_QUEUE_ERROR;
917 }
918
919 if (vino_fifo_has_id(f, id)) {
920 return VINO_QUEUE_ERROR;
921 }
922
923 if (f->used < f->length) {
924 f->data[f->tail] = id;
925 f->tail = (f->tail + 1) % f->length;
926 f->used++;
927 } else {
928 return VINO_QUEUE_ERROR;
929 }
930
931 return 0;
932}
933
934static int vino_fifo_peek(struct vino_framebuffer_fifo *f, unsigned int *id)
935{
936 if (f->used > 0) {
937 *id = f->data[f->head];
938 } else {
939 return VINO_QUEUE_ERROR;
940 }
941
942 return 0;
943}
944
945static int vino_fifo_dequeue(struct vino_framebuffer_fifo *f, unsigned int *id)
946{
947 if (f->used > 0) {
948 *id = f->data[f->head];
949 f->head = (f->head + 1) % f->length;
950 f->used--;
951 } else {
952 return VINO_QUEUE_ERROR;
953 }
954
955 return 0;
956}
957
958/* Framebuffer queue functions */
959
960/* execute with queue_lock locked */
961static void vino_queue_free_with_count(struct vino_framebuffer_queue *q,
962 unsigned int length)
963{
964 unsigned int i;
965
966 q->length = 0;
967 memset(&q->in, 0, sizeof(struct vino_framebuffer_fifo));
968 memset(&q->out, 0, sizeof(struct vino_framebuffer_fifo));
969 for (i = 0; i < length; i++) {
970 dprintk("vino_queue_free_with_count(): freeing buffer %d\n",
971 i);
972 vino_free_buffer(q->buffer[i]);
973 kfree(q->buffer[i]);
974 }
975
976 q->type = VINO_MEMORY_NONE;
977 q->magic = 0;
978}
979
980static void vino_queue_free(struct vino_framebuffer_queue *q)
981{
982 dprintk("vino_queue_free():\n");
983
984 if (q->magic != VINO_QUEUE_MAGIC)
985 return;
986 if (q->type != VINO_MEMORY_MMAP)
987 return;
988
Ingo Molnar3593cab2006-02-07 06:49:14 -0200989 mutex_lock(&q->queue_mutex);
Ralf Baechled203a7e2005-09-06 15:19:37 -0700990
991 vino_queue_free_with_count(q, q->length);
992
Ingo Molnar3593cab2006-02-07 06:49:14 -0200993 mutex_unlock(&q->queue_mutex);
Ralf Baechled203a7e2005-09-06 15:19:37 -0700994}
995
996static int vino_queue_init(struct vino_framebuffer_queue *q,
997 unsigned int *length)
998{
999 unsigned int i;
1000 int ret = 0;
1001
1002 dprintk("vino_queue_init(): length = %d\n", *length);
1003
1004 if (q->magic == VINO_QUEUE_MAGIC) {
1005 dprintk("vino_queue_init(): queue already initialized!\n");
1006 return -EINVAL;
1007 }
1008
1009 if (q->type != VINO_MEMORY_NONE) {
1010 dprintk("vino_queue_init(): queue already initialized!\n");
1011 return -EINVAL;
1012 }
1013
1014 if (*length < 1)
1015 return -EINVAL;
1016
Ingo Molnar3593cab2006-02-07 06:49:14 -02001017 mutex_lock(&q->queue_mutex);
Ralf Baechled203a7e2005-09-06 15:19:37 -07001018
Ladislav Michla637a112005-09-01 15:07:34 +00001019 if (*length > VINO_FRAMEBUFFER_COUNT_MAX)
1020 *length = VINO_FRAMEBUFFER_COUNT_MAX;
Ralf Baechled203a7e2005-09-06 15:19:37 -07001021
1022 q->length = 0;
1023
1024 for (i = 0; i < *length; i++) {
1025 dprintk("vino_queue_init(): allocating buffer %d\n", i);
1026 q->buffer[i] = kmalloc(sizeof(struct vino_framebuffer),
1027 GFP_KERNEL);
1028 if (!q->buffer[i]) {
1029 dprintk("vino_queue_init(): kmalloc() failed\n");
1030 ret = -ENOMEM;
1031 break;
1032 }
1033
1034 ret = vino_allocate_buffer(q->buffer[i],
1035 VINO_FRAMEBUFFER_SIZE);
1036 if (ret) {
1037 kfree(q->buffer[i]);
1038 dprintk("vino_queue_init(): "
1039 "vino_allocate_buffer() failed\n");
1040 break;
1041 }
1042
1043 q->buffer[i]->id = i;
1044 if (i > 0) {
1045 q->buffer[i]->offset = q->buffer[i - 1]->offset +
1046 q->buffer[i - 1]->size;
1047 } else {
1048 q->buffer[i]->offset = 0;
1049 }
1050
1051 spin_lock_init(&q->buffer[i]->state_lock);
1052
1053 dprintk("vino_queue_init(): buffer = %d, offset = %d, "
1054 "size = %d\n", i, q->buffer[i]->offset,
1055 q->buffer[i]->size);
1056 }
1057
1058 if (ret) {
1059 vino_queue_free_with_count(q, i);
1060 *length = 0;
1061 } else {
1062 q->length = *length;
1063 vino_fifo_init(&q->in, q->length);
1064 vino_fifo_init(&q->out, q->length);
1065 q->type = VINO_MEMORY_MMAP;
1066 q->magic = VINO_QUEUE_MAGIC;
1067 }
1068
Ingo Molnar3593cab2006-02-07 06:49:14 -02001069 mutex_unlock(&q->queue_mutex);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001070
1071 return ret;
1072}
1073
Ralf Baechled203a7e2005-09-06 15:19:37 -07001074static struct vino_framebuffer *vino_queue_add(struct
1075 vino_framebuffer_queue *q,
1076 unsigned int id)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001077{
Ralf Baechled203a7e2005-09-06 15:19:37 -07001078 struct vino_framebuffer *ret = NULL;
1079 unsigned int total;
1080 unsigned long flags;
1081
1082 dprintk("vino_queue_add(): id = %d\n", id);
1083
1084 if (q->magic != VINO_QUEUE_MAGIC) {
1085 return ret;
1086 }
1087
1088 spin_lock_irqsave(&q->queue_lock, flags);
1089
1090 if (q->length == 0)
1091 goto out;
1092
1093 if (id >= q->length)
1094 goto out;
1095
1096 /* not needed?: if (vino_fifo_full(&q->out)) {
1097 goto out;
1098 }*/
1099 /* check that outgoing queue isn't already full
1100 * (or that it won't become full) */
1101 total = vino_fifo_get_used(&q->in) +
1102 vino_fifo_get_used(&q->out);
1103 if (total >= q->length)
1104 goto out;
1105
1106 if (vino_fifo_enqueue(&q->in, id))
1107 goto out;
1108
1109 ret = q->buffer[id];
1110
1111out:
1112 spin_unlock_irqrestore(&q->queue_lock, flags);
1113
1114 return ret;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001115}
1116
Ralf Baechled203a7e2005-09-06 15:19:37 -07001117static struct vino_framebuffer *vino_queue_transfer(struct
1118 vino_framebuffer_queue *q)
1119{
1120 struct vino_framebuffer *ret = NULL;
1121 struct vino_framebuffer *fb;
1122 int id;
1123 unsigned long flags;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001124
Ralf Baechled203a7e2005-09-06 15:19:37 -07001125 dprintk("vino_queue_transfer():\n");
1126
1127 if (q->magic != VINO_QUEUE_MAGIC) {
1128 return ret;
1129 }
1130
1131 spin_lock_irqsave(&q->queue_lock, flags);
1132
1133 if (q->length == 0)
1134 goto out;
1135
1136 // now this actually removes an entry from the incoming queue
1137 if (vino_fifo_dequeue(&q->in, &id)) {
1138 goto out;
1139 }
1140
1141 dprintk("vino_queue_transfer(): id = %d\n", id);
1142 fb = q->buffer[id];
1143
1144 // we have already checked that the outgoing queue is not full, but...
1145 if (vino_fifo_enqueue(&q->out, id)) {
1146 printk(KERN_ERR "vino_queue_transfer(): "
1147 "outgoing queue is full, this shouldn't happen!\n");
1148 goto out;
1149 }
1150
1151 ret = fb;
1152out:
1153 spin_unlock_irqrestore(&q->queue_lock, flags);
1154
1155 return ret;
1156}
1157
1158/* returns true/false */
1159static int vino_queue_incoming_contains(struct vino_framebuffer_queue *q,
1160 unsigned int id)
1161{
1162 int ret = 0;
1163 unsigned long flags;
1164
1165 if (q->magic != VINO_QUEUE_MAGIC) {
1166 return ret;
1167 }
1168
1169 spin_lock_irqsave(&q->queue_lock, flags);
1170
1171 if (q->length == 0)
1172 goto out;
1173
1174 ret = vino_fifo_has_id(&q->in, id);
1175
1176out:
1177 spin_unlock_irqrestore(&q->queue_lock, flags);
1178
1179 return ret;
1180}
1181
1182/* returns true/false */
1183static int vino_queue_outgoing_contains(struct vino_framebuffer_queue *q,
1184 unsigned int id)
1185{
1186 int ret = 0;
1187 unsigned long flags;
1188
1189 if (q->magic != VINO_QUEUE_MAGIC) {
1190 return ret;
1191 }
1192
1193 spin_lock_irqsave(&q->queue_lock, flags);
1194
1195 if (q->length == 0)
1196 goto out;
1197
1198 ret = vino_fifo_has_id(&q->out, id);
1199
1200out:
1201 spin_unlock_irqrestore(&q->queue_lock, flags);
1202
1203 return ret;
1204}
1205
1206static int vino_queue_get_incoming(struct vino_framebuffer_queue *q,
1207 unsigned int *used)
1208{
1209 int ret = 0;
1210 unsigned long flags;
1211
1212 if (q->magic != VINO_QUEUE_MAGIC) {
1213 return VINO_QUEUE_ERROR;
1214 }
1215
1216 spin_lock_irqsave(&q->queue_lock, flags);
1217
1218 if (q->length == 0) {
1219 ret = VINO_QUEUE_ERROR;
1220 goto out;
1221 }
1222
1223 *used = vino_fifo_get_used(&q->in);
1224
1225out:
1226 spin_unlock_irqrestore(&q->queue_lock, flags);
1227
1228 return ret;
1229}
1230
1231static int vino_queue_get_outgoing(struct vino_framebuffer_queue *q,
1232 unsigned int *used)
1233{
1234 int ret = 0;
1235 unsigned long flags;
1236
1237 if (q->magic != VINO_QUEUE_MAGIC) {
1238 return VINO_QUEUE_ERROR;
1239 }
1240
1241 spin_lock_irqsave(&q->queue_lock, flags);
1242
1243 if (q->length == 0) {
1244 ret = VINO_QUEUE_ERROR;
1245 goto out;
1246 }
1247
1248 *used = vino_fifo_get_used(&q->out);
1249
1250out:
1251 spin_unlock_irqrestore(&q->queue_lock, flags);
1252
1253 return ret;
1254}
1255
Ladislav Michla637a112005-09-01 15:07:34 +00001256#if 0
Ralf Baechled203a7e2005-09-06 15:19:37 -07001257static int vino_queue_get_total(struct vino_framebuffer_queue *q,
1258 unsigned int *total)
1259{
1260 int ret = 0;
1261 unsigned long flags;
1262
1263 if (q->magic != VINO_QUEUE_MAGIC) {
1264 return VINO_QUEUE_ERROR;
1265 }
1266
1267 spin_lock_irqsave(&q->queue_lock, flags);
1268
1269 if (q->length == 0) {
1270 ret = VINO_QUEUE_ERROR;
1271 goto out;
1272 }
1273
1274 *total = vino_fifo_get_used(&q->in) +
1275 vino_fifo_get_used(&q->out);
1276
1277out:
1278 spin_unlock_irqrestore(&q->queue_lock, flags);
1279
1280 return ret;
1281}
Ladislav Michla637a112005-09-01 15:07:34 +00001282#endif
Ralf Baechled203a7e2005-09-06 15:19:37 -07001283
1284static struct vino_framebuffer *vino_queue_peek(struct
1285 vino_framebuffer_queue *q,
1286 unsigned int *id)
1287{
1288 struct vino_framebuffer *ret = NULL;
1289 unsigned long flags;
1290
1291 if (q->magic != VINO_QUEUE_MAGIC) {
1292 return ret;
1293 }
1294
1295 spin_lock_irqsave(&q->queue_lock, flags);
1296
1297 if (q->length == 0)
1298 goto out;
1299
1300 if (vino_fifo_peek(&q->in, id)) {
1301 goto out;
1302 }
1303
1304 ret = q->buffer[*id];
1305out:
1306 spin_unlock_irqrestore(&q->queue_lock, flags);
1307
1308 return ret;
1309}
1310
1311static struct vino_framebuffer *vino_queue_remove(struct
1312 vino_framebuffer_queue *q,
1313 unsigned int *id)
1314{
1315 struct vino_framebuffer *ret = NULL;
1316 unsigned long flags;
1317 dprintk("vino_queue_remove():\n");
1318
1319 if (q->magic != VINO_QUEUE_MAGIC) {
1320 return ret;
1321 }
1322
1323 spin_lock_irqsave(&q->queue_lock, flags);
1324
1325 if (q->length == 0)
1326 goto out;
1327
1328 if (vino_fifo_dequeue(&q->out, id)) {
1329 goto out;
1330 }
1331
1332 dprintk("vino_queue_remove(): id = %d\n", *id);
1333 ret = q->buffer[*id];
1334out:
1335 spin_unlock_irqrestore(&q->queue_lock, flags);
1336
1337 return ret;
1338}
1339
1340static struct
1341vino_framebuffer *vino_queue_get_buffer(struct vino_framebuffer_queue *q,
1342 unsigned int id)
1343{
1344 struct vino_framebuffer *ret = NULL;
1345 unsigned long flags;
1346
1347 if (q->magic != VINO_QUEUE_MAGIC) {
1348 return ret;
1349 }
1350
1351 spin_lock_irqsave(&q->queue_lock, flags);
1352
1353 if (q->length == 0)
1354 goto out;
1355
1356 if (id >= q->length)
1357 goto out;
1358
1359 ret = q->buffer[id];
1360 out:
1361 spin_unlock_irqrestore(&q->queue_lock, flags);
1362
1363 return ret;
1364}
1365
1366static unsigned int vino_queue_get_length(struct vino_framebuffer_queue *q)
1367{
1368 unsigned int length = 0;
1369 unsigned long flags;
1370
1371 if (q->magic != VINO_QUEUE_MAGIC) {
1372 return length;
1373 }
1374
1375 spin_lock_irqsave(&q->queue_lock, flags);
1376 length = q->length;
1377 spin_unlock_irqrestore(&q->queue_lock, flags);
1378
1379 return length;
1380}
1381
1382static int vino_queue_has_mapped_buffers(struct vino_framebuffer_queue *q)
1383{
1384 unsigned int i;
1385 int ret = 0;
1386 unsigned long flags;
1387
1388 if (q->magic != VINO_QUEUE_MAGIC) {
1389 return ret;
1390 }
1391
1392 spin_lock_irqsave(&q->queue_lock, flags);
1393 for (i = 0; i < q->length; i++) {
1394 if (q->buffer[i]->map_count > 0) {
1395 ret = 1;
1396 break;
1397 }
1398 }
1399 spin_unlock_irqrestore(&q->queue_lock, flags);
1400
1401 return ret;
1402}
1403
1404/* VINO functions */
1405
1406/* execute with input_lock locked */
1407static void vino_update_line_size(struct vino_channel_settings *vcs)
1408{
1409 unsigned int w = vcs->clipping.right - vcs->clipping.left;
1410 unsigned int d = vcs->decimation;
1411 unsigned int bpp = vino_data_formats[vcs->data_format].bpp;
Mauro Carvalho Chehabd56410e2006-03-25 09:19:53 -03001412 unsigned int lsize;
Ralf Baechled203a7e2005-09-06 15:19:37 -07001413
1414 dprintk("update_line_size(): before: w = %d, d = %d, "
1415 "line_size = %d\n", w, d, vcs->line_size);
Ladislav Michla637a112005-09-01 15:07:34 +00001416
Mauro Carvalho Chehabd56410e2006-03-25 09:19:53 -03001417 /* line size must be multiple of 8 bytes */
Ralf Baechled203a7e2005-09-06 15:19:37 -07001418 lsize = (bpp * (w / d)) & ~7;
1419 w = (lsize / bpp) * d;
1420
1421 vcs->clipping.right = vcs->clipping.left + w;
1422 vcs->line_size = lsize;
Ladislav Michla637a112005-09-01 15:07:34 +00001423
Ralf Baechled203a7e2005-09-06 15:19:37 -07001424 dprintk("update_line_size(): after: w = %d, d = %d, "
1425 "line_size = %d\n", w, d, vcs->line_size);
1426}
1427
1428/* execute with input_lock locked */
1429static void vino_set_clipping(struct vino_channel_settings *vcs,
1430 unsigned int x, unsigned int y,
1431 unsigned int w, unsigned int h)
1432{
1433 unsigned int maxwidth, maxheight;
1434 unsigned int d;
1435
1436 maxwidth = vino_data_norms[vcs->data_norm].width;
1437 maxheight = vino_data_norms[vcs->data_norm].height;
1438 d = vcs->decimation;
1439
1440 y &= ~1; /* odd/even fields */
1441
1442 if (x > maxwidth) {
1443 x = 0;
1444 }
1445 if (y > maxheight) {
1446 y = 0;
1447 }
1448
1449 if (((w / d) < VINO_MIN_WIDTH)
1450 || ((h / d) < VINO_MIN_HEIGHT)) {
1451 w = VINO_MIN_WIDTH * d;
1452 h = VINO_MIN_HEIGHT * d;
1453 }
1454
1455 if ((x + w) > maxwidth) {
1456 w = maxwidth - x;
1457 if ((w / d) < VINO_MIN_WIDTH)
1458 x = maxwidth - VINO_MIN_WIDTH * d;
1459 }
1460 if ((y + h) > maxheight) {
1461 h = maxheight - y;
1462 if ((h / d) < VINO_MIN_HEIGHT)
1463 y = maxheight - VINO_MIN_HEIGHT * d;
1464 }
1465
1466 vcs->clipping.left = x;
1467 vcs->clipping.top = y;
1468 vcs->clipping.right = x + w;
1469 vcs->clipping.bottom = y + h;
1470
1471 vino_update_line_size(vcs);
1472
1473 dprintk("clipping %d, %d, %d, %d / %d - %d\n",
1474 vcs->clipping.left, vcs->clipping.top, vcs->clipping.right,
1475 vcs->clipping.bottom, vcs->decimation, vcs->line_size);
1476}
1477
1478/* execute with input_lock locked */
Ladislav Michla637a112005-09-01 15:07:34 +00001479static inline void vino_set_default_clipping(struct vino_channel_settings *vcs)
Ralf Baechled203a7e2005-09-06 15:19:37 -07001480{
1481 vino_set_clipping(vcs, 0, 0, vino_data_norms[vcs->data_norm].width,
1482 vino_data_norms[vcs->data_norm].height);
1483}
1484
1485/* execute with input_lock locked */
1486static void vino_set_scaling(struct vino_channel_settings *vcs,
1487 unsigned int w, unsigned int h)
1488{
1489 unsigned int x, y, curw, curh, d;
1490
1491 x = vcs->clipping.left;
1492 y = vcs->clipping.top;
1493 curw = vcs->clipping.right - vcs->clipping.left;
1494 curh = vcs->clipping.bottom - vcs->clipping.top;
1495
1496 d = max(curw / w, curh / h);
1497
1498 dprintk("scaling w: %d, h: %d, curw: %d, curh: %d, d: %d\n",
1499 w, h, curw, curh, d);
1500
1501 if (d < 1) {
1502 d = 1;
Ladislav Michla637a112005-09-01 15:07:34 +00001503 } else if (d > 8) {
Ralf Baechled203a7e2005-09-06 15:19:37 -07001504 d = 8;
1505 }
1506
1507 vcs->decimation = d;
1508 vino_set_clipping(vcs, x, y, w * d, h * d);
1509
1510 dprintk("scaling %d, %d, %d, %d / %d - %d\n", vcs->clipping.left,
1511 vcs->clipping.top, vcs->clipping.right, vcs->clipping.bottom,
1512 vcs->decimation, vcs->line_size);
1513}
1514
1515/* execute with input_lock locked */
Ladislav Michla637a112005-09-01 15:07:34 +00001516static inline void vino_set_default_scaling(struct vino_channel_settings *vcs)
Ralf Baechled203a7e2005-09-06 15:19:37 -07001517{
1518 vino_set_scaling(vcs, vcs->clipping.right - vcs->clipping.left,
1519 vcs->clipping.bottom - vcs->clipping.top);
1520}
1521
1522/* execute with input_lock locked */
1523static void vino_set_framerate(struct vino_channel_settings *vcs,
1524 unsigned int fps)
1525{
1526 unsigned int mask;
1527
1528 switch (vcs->data_norm) {
1529 case VINO_DATA_NORM_NTSC:
1530 case VINO_DATA_NORM_D1:
1531 fps = (unsigned int)(fps / 6) * 6; // FIXME: round!
1532
1533 if (fps < vino_data_norms[vcs->data_norm].fps_min)
1534 fps = vino_data_norms[vcs->data_norm].fps_min;
1535 if (fps > vino_data_norms[vcs->data_norm].fps_max)
1536 fps = vino_data_norms[vcs->data_norm].fps_max;
1537
1538 switch (fps) {
1539 case 6:
1540 mask = 0x003;
1541 break;
1542 case 12:
1543 mask = 0x0c3;
1544 break;
1545 case 18:
1546 mask = 0x333;
1547 break;
1548 case 24:
1549 mask = 0x3ff;
1550 break;
1551 case 30:
1552 mask = 0xfff;
1553 break;
1554 default:
1555 mask = VINO_FRAMERT_FULL;
1556 }
1557 vcs->framert_reg = VINO_FRAMERT_RT(mask);
1558 break;
1559 case VINO_DATA_NORM_PAL:
1560 case VINO_DATA_NORM_SECAM:
1561 fps = (unsigned int)(fps / 5) * 5; // FIXME: round!
1562
1563 if (fps < vino_data_norms[vcs->data_norm].fps_min)
1564 fps = vino_data_norms[vcs->data_norm].fps_min;
1565 if (fps > vino_data_norms[vcs->data_norm].fps_max)
1566 fps = vino_data_norms[vcs->data_norm].fps_max;
1567
1568 switch (fps) {
1569 case 5:
1570 mask = 0x003;
1571 break;
1572 case 10:
1573 mask = 0x0c3;
1574 break;
1575 case 15:
1576 mask = 0x333;
1577 break;
1578 case 20:
1579 mask = 0x0ff;
1580 break;
1581 case 25:
1582 mask = 0x3ff;
1583 break;
1584 default:
1585 mask = VINO_FRAMERT_FULL;
1586 }
1587 vcs->framert_reg = VINO_FRAMERT_RT(mask) | VINO_FRAMERT_PAL;
1588 break;
1589 }
1590
1591 vcs->fps = fps;
1592}
1593
1594/* execute with input_lock locked */
Ladislav Michla637a112005-09-01 15:07:34 +00001595static inline void vino_set_default_framerate(struct
1596 vino_channel_settings *vcs)
Ralf Baechled203a7e2005-09-06 15:19:37 -07001597{
1598 vino_set_framerate(vcs, vino_data_norms[vcs->data_norm].fps_max);
1599}
1600
Jean Delvarecea0c682009-03-06 12:05:43 -03001601/* VINO I2C bus functions */
1602
1603struct i2c_algo_sgi_data {
1604 void *data; /* private data for lowlevel routines */
1605 unsigned (*getctrl)(void *data);
1606 void (*setctrl)(void *data, unsigned val);
1607 unsigned (*rdata)(void *data);
1608 void (*wdata)(void *data, unsigned val);
1609
1610 int xfer_timeout;
1611 int ack_timeout;
1612};
1613
1614static int wait_xfer_done(struct i2c_algo_sgi_data *adap)
1615{
1616 int i;
1617
1618 for (i = 0; i < adap->xfer_timeout; i++) {
1619 if ((adap->getctrl(adap->data) & SGI_I2C_XFER_BUSY) == 0)
1620 return 0;
1621 udelay(1);
1622 }
1623
1624 return -ETIMEDOUT;
1625}
1626
1627static int wait_ack(struct i2c_algo_sgi_data *adap)
1628{
1629 int i;
1630
1631 if (wait_xfer_done(adap))
1632 return -ETIMEDOUT;
1633 for (i = 0; i < adap->ack_timeout; i++) {
1634 if ((adap->getctrl(adap->data) & SGI_I2C_NACK) == 0)
1635 return 0;
1636 udelay(1);
1637 }
1638
1639 return -ETIMEDOUT;
1640}
1641
1642static int force_idle(struct i2c_algo_sgi_data *adap)
1643{
1644 int i;
1645
1646 adap->setctrl(adap->data, SGI_I2C_FORCE_IDLE);
1647 for (i = 0; i < adap->xfer_timeout; i++) {
1648 if ((adap->getctrl(adap->data) & SGI_I2C_NOT_IDLE) == 0)
1649 goto out;
1650 udelay(1);
1651 }
1652 return -ETIMEDOUT;
1653out:
1654 if (adap->getctrl(adap->data) & SGI_I2C_BUS_ERR)
1655 return -EIO;
1656 return 0;
1657}
1658
1659static int do_address(struct i2c_algo_sgi_data *adap, unsigned int addr,
1660 int rd)
1661{
1662 if (rd)
1663 adap->setctrl(adap->data, SGI_I2C_NOT_IDLE);
1664 /* Check if bus is idle, eventually force it to do so */
1665 if (adap->getctrl(adap->data) & SGI_I2C_NOT_IDLE)
1666 if (force_idle(adap))
1667 return -EIO;
1668 /* Write out the i2c chip address and specify operation */
1669 adap->setctrl(adap->data,
1670 SGI_I2C_HOLD_BUS | SGI_I2C_WRITE | SGI_I2C_NOT_IDLE);
1671 if (rd)
1672 addr |= 1;
1673 adap->wdata(adap->data, addr);
1674 if (wait_ack(adap))
1675 return -EIO;
1676 return 0;
1677}
1678
1679static int i2c_read(struct i2c_algo_sgi_data *adap, unsigned char *buf,
1680 unsigned int len)
1681{
1682 int i;
1683
1684 adap->setctrl(adap->data,
1685 SGI_I2C_HOLD_BUS | SGI_I2C_READ | SGI_I2C_NOT_IDLE);
1686 for (i = 0; i < len; i++) {
1687 if (wait_xfer_done(adap))
1688 return -EIO;
1689 buf[i] = adap->rdata(adap->data);
1690 }
1691 adap->setctrl(adap->data, SGI_I2C_RELEASE_BUS | SGI_I2C_FORCE_IDLE);
1692
1693 return 0;
1694
1695}
1696
1697static int i2c_write(struct i2c_algo_sgi_data *adap, unsigned char *buf,
1698 unsigned int len)
1699{
1700 int i;
1701
1702 /* We are already in write state */
1703 for (i = 0; i < len; i++) {
1704 adap->wdata(adap->data, buf[i]);
1705 if (wait_ack(adap))
1706 return -EIO;
1707 }
1708 return 0;
1709}
1710
1711static int sgi_xfer(struct i2c_adapter *i2c_adap, struct i2c_msg *msgs,
1712 int num)
1713{
1714 struct i2c_algo_sgi_data *adap = i2c_adap->algo_data;
1715 struct i2c_msg *p;
1716 int i, err = 0;
1717
1718 for (i = 0; !err && i < num; i++) {
1719 p = &msgs[i];
1720 err = do_address(adap, p->addr, p->flags & I2C_M_RD);
1721 if (err || !p->len)
1722 continue;
1723 if (p->flags & I2C_M_RD)
1724 err = i2c_read(adap, p->buf, p->len);
1725 else
1726 err = i2c_write(adap, p->buf, p->len);
1727 }
1728
1729 return (err < 0) ? err : i;
1730}
1731
1732static u32 sgi_func(struct i2c_adapter *adap)
1733{
1734 return I2C_FUNC_SMBUS_EMUL;
1735}
1736
1737static const struct i2c_algorithm sgi_algo = {
1738 .master_xfer = sgi_xfer,
1739 .functionality = sgi_func,
1740};
1741
1742static unsigned i2c_vino_getctrl(void *data)
1743{
1744 return vino->i2c_control;
1745}
1746
1747static void i2c_vino_setctrl(void *data, unsigned val)
1748{
1749 vino->i2c_control = val;
1750}
1751
1752static unsigned i2c_vino_rdata(void *data)
1753{
1754 return vino->i2c_data;
1755}
1756
1757static void i2c_vino_wdata(void *data, unsigned val)
1758{
1759 vino->i2c_data = val;
1760}
1761
1762static struct i2c_algo_sgi_data i2c_sgi_vino_data = {
1763 .getctrl = &i2c_vino_getctrl,
1764 .setctrl = &i2c_vino_setctrl,
1765 .rdata = &i2c_vino_rdata,
1766 .wdata = &i2c_vino_wdata,
1767 .xfer_timeout = 200,
1768 .ack_timeout = 1000,
1769};
1770
1771static struct i2c_adapter vino_i2c_adapter = {
1772 .name = "VINO I2C bus",
1773 .id = I2C_HW_SGI_VINO,
1774 .algo = &sgi_algo,
1775 .algo_data = &i2c_sgi_vino_data,
1776 .owner = THIS_MODULE,
1777};
1778
Ralf Baechled203a7e2005-09-06 15:19:37 -07001779/*
1780 * Prepare VINO for DMA transfer...
1781 * (execute only with vino_lock and input_lock locked)
1782 */
1783static int vino_dma_setup(struct vino_channel_settings *vcs,
1784 struct vino_framebuffer *fb)
1785{
1786 u32 ctrl, intr;
1787 struct sgi_vino_channel *ch;
1788 const struct vino_data_norm *norm;
1789
1790 dprintk("vino_dma_setup():\n");
1791
1792 vcs->field = 0;
1793 fb->frame_counter = 0;
1794
1795 ch = (vcs->channel == VINO_CHANNEL_A) ? &vino->a : &vino->b;
1796 norm = &vino_data_norms[vcs->data_norm];
1797
1798 ch->page_index = 0;
1799 ch->line_count = 0;
1800
1801 /* VINO line size register is set 8 bytes less than actual */
1802 ch->line_size = vcs->line_size - 8;
1803
1804 /* let VINO know where to transfer data */
1805 ch->start_desc_tbl = fb->desc_table.dma;
1806 ch->next_4_desc = fb->desc_table.dma;
1807
1808 /* give vino time to fetch the first four descriptors, 5 usec
1809 * should be more than enough time */
1810 udelay(VINO_DESC_FETCH_DELAY);
1811
Ladislav Michla637a112005-09-01 15:07:34 +00001812 dprintk("vino_dma_setup(): start desc = %08x, next 4 desc = %08x\n",
1813 ch->start_desc_tbl, ch->next_4_desc);
1814
Ralf Baechled203a7e2005-09-06 15:19:37 -07001815 /* set the alpha register */
1816 ch->alpha = vcs->alpha;
1817
1818 /* set clipping registers */
1819 ch->clip_start = VINO_CLIP_ODD(norm->odd.top + vcs->clipping.top / 2) |
1820 VINO_CLIP_EVEN(norm->even.top +
1821 vcs->clipping.top / 2) |
1822 VINO_CLIP_X(vcs->clipping.left);
1823 ch->clip_end = VINO_CLIP_ODD(norm->odd.top +
1824 vcs->clipping.bottom / 2 - 1) |
1825 VINO_CLIP_EVEN(norm->even.top +
1826 vcs->clipping.bottom / 2 - 1) |
1827 VINO_CLIP_X(vcs->clipping.right);
Ralf Baechled203a7e2005-09-06 15:19:37 -07001828
1829 /* set the size of actual content in the buffer (DECIMATION !) */
1830 fb->data_size = ((vcs->clipping.right - vcs->clipping.left) /
1831 vcs->decimation) *
1832 ((vcs->clipping.bottom - vcs->clipping.top) /
1833 vcs->decimation) *
1834 vino_data_formats[vcs->data_format].bpp;
1835
1836 ch->frame_rate = vcs->framert_reg;
1837
1838 ctrl = vino->control;
1839 intr = vino->intr_status;
1840
1841 if (vcs->channel == VINO_CHANNEL_A) {
1842 /* All interrupt conditions for this channel was cleared
1843 * so clear the interrupt status register and enable
1844 * interrupts */
1845 intr &= ~VINO_INTSTAT_A;
1846 ctrl |= VINO_CTRL_A_INT;
1847
1848 /* enable synchronization */
1849 ctrl |= VINO_CTRL_A_SYNC_ENBL;
1850
1851 /* enable frame assembly */
1852 ctrl |= VINO_CTRL_A_INTERLEAVE_ENBL;
1853
1854 /* set decimation used */
1855 if (vcs->decimation < 2)
1856 ctrl &= ~VINO_CTRL_A_DEC_ENBL;
1857 else {
1858 ctrl |= VINO_CTRL_A_DEC_ENBL;
1859 ctrl &= ~VINO_CTRL_A_DEC_SCALE_MASK;
1860 ctrl |= (vcs->decimation - 1) <<
1861 VINO_CTRL_A_DEC_SCALE_SHIFT;
1862 }
1863
1864 /* select input interface */
1865 if (vcs->input == VINO_INPUT_D1)
1866 ctrl |= VINO_CTRL_A_SELECT;
1867 else
1868 ctrl &= ~VINO_CTRL_A_SELECT;
1869
1870 /* palette */
1871 ctrl &= ~(VINO_CTRL_A_LUMA_ONLY | VINO_CTRL_A_RGB |
1872 VINO_CTRL_A_DITHER);
1873 } else {
1874 intr &= ~VINO_INTSTAT_B;
1875 ctrl |= VINO_CTRL_B_INT;
1876
1877 ctrl |= VINO_CTRL_B_SYNC_ENBL;
1878 ctrl |= VINO_CTRL_B_INTERLEAVE_ENBL;
1879
1880 if (vcs->decimation < 2)
1881 ctrl &= ~VINO_CTRL_B_DEC_ENBL;
1882 else {
1883 ctrl |= VINO_CTRL_B_DEC_ENBL;
1884 ctrl &= ~VINO_CTRL_B_DEC_SCALE_MASK;
1885 ctrl |= (vcs->decimation - 1) <<
1886 VINO_CTRL_B_DEC_SCALE_SHIFT;
1887
1888 }
1889 if (vcs->input == VINO_INPUT_D1)
1890 ctrl |= VINO_CTRL_B_SELECT;
1891 else
1892 ctrl &= ~VINO_CTRL_B_SELECT;
1893
1894 ctrl &= ~(VINO_CTRL_B_LUMA_ONLY | VINO_CTRL_B_RGB |
1895 VINO_CTRL_B_DITHER);
1896 }
1897
1898 /* set palette */
1899 fb->data_format = vcs->data_format;
1900
1901 switch (vcs->data_format) {
1902 case VINO_DATA_FMT_GREY:
1903 ctrl |= (vcs->channel == VINO_CHANNEL_A) ?
1904 VINO_CTRL_A_LUMA_ONLY : VINO_CTRL_B_LUMA_ONLY;
1905 break;
1906 case VINO_DATA_FMT_RGB32:
1907 ctrl |= (vcs->channel == VINO_CHANNEL_A) ?
1908 VINO_CTRL_A_RGB : VINO_CTRL_B_RGB;
1909 break;
1910 case VINO_DATA_FMT_YUV:
1911 /* nothing needs to be done */
1912 break;
1913 case VINO_DATA_FMT_RGB332:
1914 ctrl |= (vcs->channel == VINO_CHANNEL_A) ?
1915 VINO_CTRL_A_RGB | VINO_CTRL_A_DITHER :
1916 VINO_CTRL_B_RGB | VINO_CTRL_B_DITHER;
1917 break;
1918 }
1919
1920 vino->intr_status = intr;
1921 vino->control = ctrl;
1922
1923 return 0;
1924}
1925
1926/* (execute only with vino_lock locked) */
Ladislav Michla637a112005-09-01 15:07:34 +00001927static inline void vino_dma_start(struct vino_channel_settings *vcs)
Ralf Baechled203a7e2005-09-06 15:19:37 -07001928{
1929 u32 ctrl = vino->control;
1930
1931 dprintk("vino_dma_start():\n");
1932 ctrl |= (vcs->channel == VINO_CHANNEL_A) ?
1933 VINO_CTRL_A_DMA_ENBL : VINO_CTRL_B_DMA_ENBL;
1934 vino->control = ctrl;
1935}
1936
1937/* (execute only with vino_lock locked) */
Ladislav Michla637a112005-09-01 15:07:34 +00001938static inline void vino_dma_stop(struct vino_channel_settings *vcs)
Ralf Baechled203a7e2005-09-06 15:19:37 -07001939{
1940 u32 ctrl = vino->control;
1941
1942 ctrl &= (vcs->channel == VINO_CHANNEL_A) ?
1943 ~VINO_CTRL_A_DMA_ENBL : ~VINO_CTRL_B_DMA_ENBL;
Ladislav Michla637a112005-09-01 15:07:34 +00001944 ctrl &= (vcs->channel == VINO_CHANNEL_A) ?
1945 ~VINO_CTRL_A_INT : ~VINO_CTRL_B_INT;
Ralf Baechled203a7e2005-09-06 15:19:37 -07001946 vino->control = ctrl;
1947 dprintk("vino_dma_stop():\n");
1948}
1949
1950/*
1951 * Load dummy page to descriptor registers. This prevents generating of
1952 * spurious interrupts. (execute only with vino_lock locked)
1953 */
1954static void vino_clear_interrupt(struct vino_channel_settings *vcs)
1955{
1956 struct sgi_vino_channel *ch;
1957
1958 ch = (vcs->channel == VINO_CHANNEL_A) ? &vino->a : &vino->b;
1959
1960 ch->page_index = 0;
1961 ch->line_count = 0;
1962
1963 ch->start_desc_tbl = vino_drvdata->dummy_desc_table.dma;
1964 ch->next_4_desc = vino_drvdata->dummy_desc_table.dma;
1965
1966 udelay(VINO_DESC_FETCH_DELAY);
1967 dprintk("channel %c clear interrupt condition\n",
1968 (vcs->channel == VINO_CHANNEL_A) ? 'A':'B');
1969}
1970
1971static int vino_capture(struct vino_channel_settings *vcs,
1972 struct vino_framebuffer *fb)
1973{
1974 int err = 0;
1975 unsigned long flags, flags2;
1976
1977 spin_lock_irqsave(&fb->state_lock, flags);
1978
1979 if (fb->state == VINO_FRAMEBUFFER_IN_USE)
1980 err = -EBUSY;
1981 fb->state = VINO_FRAMEBUFFER_IN_USE;
1982
1983 spin_unlock_irqrestore(&fb->state_lock, flags);
1984
1985 if (err)
1986 return err;
1987
1988 spin_lock_irqsave(&vino_drvdata->vino_lock, flags);
1989 spin_lock_irqsave(&vino_drvdata->input_lock, flags2);
1990
1991 vino_dma_setup(vcs, fb);
1992 vino_dma_start(vcs);
1993
1994 spin_unlock_irqrestore(&vino_drvdata->input_lock, flags2);
1995 spin_unlock_irqrestore(&vino_drvdata->vino_lock, flags);
1996
1997 return err;
1998}
1999
2000static
2001struct vino_framebuffer *vino_capture_enqueue(struct
2002 vino_channel_settings *vcs,
2003 unsigned int index)
2004{
2005 struct vino_framebuffer *fb;
2006 unsigned long flags;
2007
2008 dprintk("vino_capture_enqueue():\n");
2009
2010 spin_lock_irqsave(&vcs->capture_lock, flags);
2011
2012 fb = vino_queue_add(&vcs->fb_queue, index);
2013 if (fb == NULL) {
2014 dprintk("vino_capture_enqueue(): vino_queue_add() failed, "
2015 "queue full?\n");
2016 goto out;
2017 }
2018out:
2019 spin_unlock_irqrestore(&vcs->capture_lock, flags);
2020
2021 return fb;
2022}
2023
2024static int vino_capture_next(struct vino_channel_settings *vcs, int start)
2025{
2026 struct vino_framebuffer *fb;
2027 unsigned int incoming, id;
2028 int err = 0;
Ladislav Michla637a112005-09-01 15:07:34 +00002029 unsigned long flags;
Ralf Baechled203a7e2005-09-06 15:19:37 -07002030
2031 dprintk("vino_capture_next():\n");
2032
2033 spin_lock_irqsave(&vcs->capture_lock, flags);
2034
2035 if (start) {
2036 /* start capture only if capture isn't in progress already */
2037 if (vcs->capturing) {
2038 spin_unlock_irqrestore(&vcs->capture_lock, flags);
2039 return 0;
2040 }
2041
2042 } else {
2043 /* capture next frame:
2044 * stop capture if capturing is not set */
2045 if (!vcs->capturing) {
2046 spin_unlock_irqrestore(&vcs->capture_lock, flags);
2047 return 0;
2048 }
2049 }
2050
2051 err = vino_queue_get_incoming(&vcs->fb_queue, &incoming);
2052 if (err) {
2053 dprintk("vino_capture_next(): vino_queue_get_incoming() "
2054 "failed\n");
2055 err = -EINVAL;
2056 goto out;
2057 }
2058 if (incoming == 0) {
2059 dprintk("vino_capture_next(): no buffers available\n");
2060 goto out;
2061 }
2062
2063 fb = vino_queue_peek(&vcs->fb_queue, &id);
2064 if (fb == NULL) {
2065 dprintk("vino_capture_next(): vino_queue_peek() failed\n");
2066 err = -EINVAL;
2067 goto out;
2068 }
2069
Ralf Baechled203a7e2005-09-06 15:19:37 -07002070 if (start) {
2071 vcs->capturing = 1;
2072 }
2073
2074 spin_unlock_irqrestore(&vcs->capture_lock, flags);
2075
2076 err = vino_capture(vcs, fb);
2077
2078 return err;
2079
2080out:
2081 vcs->capturing = 0;
2082 spin_unlock_irqrestore(&vcs->capture_lock, flags);
2083
2084 return err;
2085}
2086
Ladislav Michla637a112005-09-01 15:07:34 +00002087static inline int vino_is_capturing(struct vino_channel_settings *vcs)
Ralf Baechled203a7e2005-09-06 15:19:37 -07002088{
2089 int ret;
2090 unsigned long flags;
2091
2092 spin_lock_irqsave(&vcs->capture_lock, flags);
2093
2094 ret = vcs->capturing;
2095
2096 spin_unlock_irqrestore(&vcs->capture_lock, flags);
2097
2098 return ret;
2099}
2100
2101/* waits until a frame is captured */
2102static int vino_wait_for_frame(struct vino_channel_settings *vcs)
2103{
2104 wait_queue_t wait;
2105 int err = 0;
2106
2107 dprintk("vino_wait_for_frame():\n");
2108
2109 init_waitqueue_entry(&wait, current);
2110 /* add ourselves into wait queue */
2111 add_wait_queue(&vcs->fb_queue.frame_wait_queue, &wait);
Ralf Baechled203a7e2005-09-06 15:19:37 -07002112
2113 /* to ensure that schedule_timeout will return immediately
Robert P. J. Dayf3a43d32007-07-16 10:46:42 -03002114 * if VINO interrupt was triggered meanwhile */
Mauro Carvalho Chehab818ca472007-07-17 16:29:07 -03002115 schedule_timeout_interruptible(msecs_to_jiffies(100));
Ralf Baechled203a7e2005-09-06 15:19:37 -07002116
2117 if (signal_pending(current))
2118 err = -EINTR;
2119
2120 remove_wait_queue(&vcs->fb_queue.frame_wait_queue, &wait);
2121
2122 dprintk("vino_wait_for_frame(): waiting for frame %s\n",
2123 err ? "failed" : "ok");
2124
2125 return err;
2126}
2127
2128/* the function assumes that PAGE_SIZE % 4 == 0 */
2129static void vino_convert_to_rgba(struct vino_framebuffer *fb) {
2130 unsigned char *pageptr;
2131 unsigned int page, i;
2132 unsigned char a;
2133
2134 for (page = 0; page < fb->desc_table.page_count; page++) {
2135 pageptr = (unsigned char *)fb->desc_table.virtual[page];
2136
2137 for (i = 0; i < PAGE_SIZE; i += 4) {
2138 a = pageptr[0];
2139 pageptr[0] = pageptr[3];
2140 pageptr[1] = pageptr[2];
2141 pageptr[2] = pageptr[1];
2142 pageptr[3] = a;
2143 pageptr += 4;
2144 }
2145 }
2146}
2147
2148/* checks if the buffer is in correct state and syncs data */
2149static int vino_check_buffer(struct vino_channel_settings *vcs,
2150 struct vino_framebuffer *fb)
2151{
2152 int err = 0;
2153 unsigned long flags;
2154
2155 dprintk("vino_check_buffer():\n");
2156
2157 spin_lock_irqsave(&fb->state_lock, flags);
2158 switch (fb->state) {
2159 case VINO_FRAMEBUFFER_IN_USE:
2160 err = -EIO;
2161 break;
2162 case VINO_FRAMEBUFFER_READY:
2163 vino_sync_buffer(fb);
2164 fb->state = VINO_FRAMEBUFFER_UNUSED;
2165 break;
2166 default:
2167 err = -EINVAL;
2168 }
2169 spin_unlock_irqrestore(&fb->state_lock, flags);
2170
2171 if (!err) {
2172 if (vino_pixel_conversion
2173 && (fb->data_format == VINO_DATA_FMT_RGB32)) {
2174 vino_convert_to_rgba(fb);
2175 }
2176 } else if (err && (err != -EINVAL)) {
2177 dprintk("vino_check_buffer(): buffer not ready\n");
2178
2179 spin_lock_irqsave(&vino_drvdata->vino_lock, flags);
2180 vino_dma_stop(vcs);
2181 vino_clear_interrupt(vcs);
2182 spin_unlock_irqrestore(&vino_drvdata->vino_lock, flags);
2183 }
2184
2185 return err;
2186}
2187
2188/* forcefully terminates capture */
2189static void vino_capture_stop(struct vino_channel_settings *vcs)
2190{
2191 unsigned int incoming = 0, outgoing = 0, id;
2192 unsigned long flags, flags2;
2193
2194 dprintk("vino_capture_stop():\n");
2195
2196 spin_lock_irqsave(&vcs->capture_lock, flags);
Ladislav Michla637a112005-09-01 15:07:34 +00002197
Ralf Baechled203a7e2005-09-06 15:19:37 -07002198 /* unset capturing to stop queue processing */
2199 vcs->capturing = 0;
2200
2201 spin_lock_irqsave(&vino_drvdata->vino_lock, flags2);
2202
2203 vino_dma_stop(vcs);
2204 vino_clear_interrupt(vcs);
2205
2206 spin_unlock_irqrestore(&vino_drvdata->vino_lock, flags2);
2207
2208 /* remove all items from the queue */
2209 if (vino_queue_get_incoming(&vcs->fb_queue, &incoming)) {
2210 dprintk("vino_capture_stop(): "
2211 "vino_queue_get_incoming() failed\n");
2212 goto out;
2213 }
2214 while (incoming > 0) {
2215 vino_queue_transfer(&vcs->fb_queue);
2216
2217 if (vino_queue_get_incoming(&vcs->fb_queue, &incoming)) {
2218 dprintk("vino_capture_stop(): "
2219 "vino_queue_get_incoming() failed\n");
2220 goto out;
2221 }
2222 }
2223
2224 if (vino_queue_get_outgoing(&vcs->fb_queue, &outgoing)) {
2225 dprintk("vino_capture_stop(): "
2226 "vino_queue_get_outgoing() failed\n");
2227 goto out;
2228 }
2229 while (outgoing > 0) {
2230 vino_queue_remove(&vcs->fb_queue, &id);
2231
2232 if (vino_queue_get_outgoing(&vcs->fb_queue, &outgoing)) {
2233 dprintk("vino_capture_stop(): "
2234 "vino_queue_get_outgoing() failed\n");
2235 goto out;
2236 }
2237 }
2238
2239out:
2240 spin_unlock_irqrestore(&vcs->capture_lock, flags);
2241}
2242
Ladislav Michla637a112005-09-01 15:07:34 +00002243#if 0
Ralf Baechled203a7e2005-09-06 15:19:37 -07002244static int vino_capture_failed(struct vino_channel_settings *vcs)
2245{
2246 struct vino_framebuffer *fb;
2247 unsigned long flags;
2248 unsigned int i;
2249 int ret;
2250
2251 dprintk("vino_capture_failed():\n");
2252
2253 spin_lock_irqsave(&vino_drvdata->vino_lock, flags);
2254
2255 vino_dma_stop(vcs);
2256 vino_clear_interrupt(vcs);
2257
2258 spin_unlock_irqrestore(&vino_drvdata->vino_lock, flags);
2259
2260 ret = vino_queue_get_incoming(&vcs->fb_queue, &i);
2261 if (ret == VINO_QUEUE_ERROR) {
2262 dprintk("vino_queue_get_incoming() failed\n");
2263 return -EINVAL;
2264 }
2265 if (i == 0) {
2266 /* no buffers to process */
2267 return 0;
2268 }
2269
2270 fb = vino_queue_peek(&vcs->fb_queue, &i);
2271 if (fb == NULL) {
2272 dprintk("vino_queue_peek() failed\n");
2273 return -EINVAL;
2274 }
2275
2276 spin_lock_irqsave(&fb->state_lock, flags);
2277 if (fb->state == VINO_FRAMEBUFFER_IN_USE) {
2278 fb->state = VINO_FRAMEBUFFER_UNUSED;
2279 vino_queue_transfer(&vcs->fb_queue);
2280 vino_queue_remove(&vcs->fb_queue, &i);
2281 /* we should actually discard the newest frame,
2282 * but who cares ... */
2283 }
2284 spin_unlock_irqrestore(&fb->state_lock, flags);
2285
2286 return 0;
2287}
Ladislav Michla637a112005-09-01 15:07:34 +00002288#endif
Ralf Baechled203a7e2005-09-06 15:19:37 -07002289
Ladislav Michla637a112005-09-01 15:07:34 +00002290static void vino_skip_frame(struct vino_channel_settings *vcs)
2291{
2292 struct vino_framebuffer *fb;
2293 unsigned long flags;
2294 unsigned int id;
2295
2296 spin_lock_irqsave(&vcs->capture_lock, flags);
2297 fb = vino_queue_peek(&vcs->fb_queue, &id);
2298 if (!fb) {
2299 spin_unlock_irqrestore(&vcs->capture_lock, flags);
2300 dprintk("vino_skip_frame(): vino_queue_peek() failed!\n");
2301 return;
2302 }
2303 spin_unlock_irqrestore(&vcs->capture_lock, flags);
2304
2305 spin_lock_irqsave(&fb->state_lock, flags);
2306 fb->state = VINO_FRAMEBUFFER_UNUSED;
2307 spin_unlock_irqrestore(&fb->state_lock, flags);
2308
2309 vino_capture_next(vcs, 0);
2310}
2311
2312static void vino_frame_done(struct vino_channel_settings *vcs)
Ralf Baechled203a7e2005-09-06 15:19:37 -07002313{
2314 struct vino_framebuffer *fb;
2315 unsigned long flags;
2316
2317 spin_lock_irqsave(&vcs->capture_lock, flags);
2318 fb = vino_queue_transfer(&vcs->fb_queue);
2319 if (!fb) {
2320 spin_unlock_irqrestore(&vcs->capture_lock, flags);
2321 dprintk("vino_frame_done(): vino_queue_transfer() failed!\n");
2322 return;
2323 }
2324 spin_unlock_irqrestore(&vcs->capture_lock, flags);
2325
Ladislav Michla637a112005-09-01 15:07:34 +00002326 fb->frame_counter = vcs->int_data.frame_counter;
2327 memcpy(&fb->timestamp, &vcs->int_data.timestamp,
2328 sizeof(struct timeval));
Ralf Baechled203a7e2005-09-06 15:19:37 -07002329
2330 spin_lock_irqsave(&fb->state_lock, flags);
2331 if (fb->state == VINO_FRAMEBUFFER_IN_USE)
2332 fb->state = VINO_FRAMEBUFFER_READY;
2333 spin_unlock_irqrestore(&fb->state_lock, flags);
2334
2335 wake_up(&vcs->fb_queue.frame_wait_queue);
2336
2337 vino_capture_next(vcs, 0);
2338}
2339
Ladislav Michla637a112005-09-01 15:07:34 +00002340static void vino_capture_tasklet(unsigned long channel) {
2341 struct vino_channel_settings *vcs;
2342
2343 vcs = (channel == VINO_CHANNEL_A)
2344 ? &vino_drvdata->a : &vino_drvdata->b;
2345
2346 if (vcs->int_data.skip)
2347 vcs->int_data.skip_count++;
2348
2349 if (vcs->int_data.skip && (vcs->int_data.skip_count
2350 <= VINO_MAX_FRAME_SKIP_COUNT)) {
2351 vino_skip_frame(vcs);
2352 } else {
2353 vcs->int_data.skip_count = 0;
2354 vino_frame_done(vcs);
2355 }
2356}
2357
David Howells7d12e782006-10-05 14:55:46 +01002358static irqreturn_t vino_interrupt(int irq, void *dev_id)
Ralf Baechled203a7e2005-09-06 15:19:37 -07002359{
Ladislav Michla637a112005-09-01 15:07:34 +00002360 u32 ctrl, intr;
Ralf Baechled203a7e2005-09-06 15:19:37 -07002361 unsigned int fc_a, fc_b;
Ladislav Michla637a112005-09-01 15:07:34 +00002362 int handled_a = 0, skip_a = 0, done_a = 0;
2363 int handled_b = 0, skip_b = 0, done_b = 0;
2364
2365#ifdef VINO_DEBUG_INT
2366 int loop = 0;
2367 unsigned int line_count = vino->a.line_count,
2368 page_index = vino->a.page_index,
2369 field_counter = vino->a.field_counter,
2370 start_desc_tbl = vino->a.start_desc_tbl,
2371 next_4_desc = vino->a.next_4_desc;
2372 unsigned int line_count_2,
2373 page_index_2,
2374 field_counter_2,
2375 start_desc_tbl_2,
2376 next_4_desc_2;
2377#endif
Ralf Baechled203a7e2005-09-06 15:19:37 -07002378
2379 spin_lock(&vino_drvdata->vino_lock);
2380
Ladislav Michla637a112005-09-01 15:07:34 +00002381 while ((intr = vino->intr_status)) {
2382 fc_a = vino->a.field_counter >> 1;
2383 fc_b = vino->b.field_counter >> 1;
Ralf Baechled203a7e2005-09-06 15:19:37 -07002384
Ladislav Michla637a112005-09-01 15:07:34 +00002385 /* handle error-interrupts in some special way ?
2386 * --> skips frames */
2387 if (intr & VINO_INTSTAT_A) {
2388 if (intr & VINO_INTSTAT_A_EOF) {
2389 vino_drvdata->a.field++;
2390 if (vino_drvdata->a.field > 1) {
2391 vino_dma_stop(&vino_drvdata->a);
2392 vino_clear_interrupt(&vino_drvdata->a);
2393 vino_drvdata->a.field = 0;
2394 done_a = 1;
2395 } else {
2396 if (vino->a.page_index
2397 != vino_drvdata->a.line_size) {
2398 vino->a.line_count = 0;
2399 vino->a.page_index =
2400 vino_drvdata->
2401 a.line_size;
2402 vino->a.next_4_desc =
2403 vino->a.start_desc_tbl;
2404 }
2405 }
2406 dprintk("channel A end-of-field "
2407 "interrupt: %04x\n", intr);
2408 } else {
Ralf Baechled203a7e2005-09-06 15:19:37 -07002409 vino_dma_stop(&vino_drvdata->a);
2410 vino_clear_interrupt(&vino_drvdata->a);
2411 vino_drvdata->a.field = 0;
Ladislav Michla637a112005-09-01 15:07:34 +00002412 skip_a = 1;
2413 dprintk("channel A error interrupt: %04x\n",
2414 intr);
Ralf Baechled203a7e2005-09-06 15:19:37 -07002415 }
Ladislav Michla637a112005-09-01 15:07:34 +00002416
2417#ifdef VINO_DEBUG_INT
2418 line_count_2 = vino->a.line_count;
2419 page_index_2 = vino->a.page_index;
2420 field_counter_2 = vino->a.field_counter;
2421 start_desc_tbl_2 = vino->a.start_desc_tbl;
2422 next_4_desc_2 = vino->a.next_4_desc;
2423
2424 printk("intr = %04x, loop = %d, field = %d\n",
2425 intr, loop, vino_drvdata->a.field);
2426 printk("1- line count = %04d, page index = %04d, "
2427 "start = %08x, next = %08x\n"
2428 " fieldc = %d, framec = %d\n",
2429 line_count, page_index, start_desc_tbl,
2430 next_4_desc, field_counter, fc_a);
2431 printk("12-line count = %04d, page index = %04d, "
2432 " start = %08x, next = %08x\n",
2433 line_count_2, page_index_2, start_desc_tbl_2,
2434 next_4_desc_2);
2435
2436 if (done_a)
2437 printk("\n");
2438#endif
Ralf Baechled203a7e2005-09-06 15:19:37 -07002439 }
Ladislav Michla637a112005-09-01 15:07:34 +00002440
2441 if (intr & VINO_INTSTAT_B) {
2442 if (intr & VINO_INTSTAT_B_EOF) {
2443 vino_drvdata->b.field++;
2444 if (vino_drvdata->b.field > 1) {
2445 vino_dma_stop(&vino_drvdata->b);
2446 vino_clear_interrupt(&vino_drvdata->b);
2447 vino_drvdata->b.field = 0;
2448 done_b = 1;
2449 }
2450 dprintk("channel B end-of-field "
2451 "interrupt: %04x\n", intr);
2452 } else {
Ralf Baechled203a7e2005-09-06 15:19:37 -07002453 vino_dma_stop(&vino_drvdata->b);
2454 vino_clear_interrupt(&vino_drvdata->b);
2455 vino_drvdata->b.field = 0;
Ladislav Michla637a112005-09-01 15:07:34 +00002456 skip_b = 1;
2457 dprintk("channel B error interrupt: %04x\n",
2458 intr);
Ralf Baechled203a7e2005-09-06 15:19:37 -07002459 }
Ralf Baechled203a7e2005-09-06 15:19:37 -07002460 }
Ralf Baechled203a7e2005-09-06 15:19:37 -07002461
Ladislav Michla637a112005-09-01 15:07:34 +00002462 /* Always remember to clear interrupt status.
2463 * Disable VINO interrupts while we do this. */
2464 ctrl = vino->control;
2465 vino->control = ctrl & ~(VINO_CTRL_A_INT | VINO_CTRL_B_INT);
2466 vino->intr_status = ~intr;
2467 vino->control = ctrl;
2468
2469 spin_unlock(&vino_drvdata->vino_lock);
2470
2471 if ((!handled_a) && (done_a || skip_a)) {
2472 if (!skip_a) {
2473 do_gettimeofday(&vino_drvdata->
2474 a.int_data.timestamp);
2475 vino_drvdata->a.int_data.frame_counter = fc_a;
2476 }
2477 vino_drvdata->a.int_data.skip = skip_a;
2478
2479 dprintk("channel A %s, interrupt: %d\n",
2480 skip_a ? "skipping frame" : "frame done",
2481 intr);
2482 tasklet_hi_schedule(&vino_tasklet_a);
2483 handled_a = 1;
2484 }
2485
2486 if ((!handled_b) && (done_b || skip_b)) {
2487 if (!skip_b) {
2488 do_gettimeofday(&vino_drvdata->
2489 b.int_data.timestamp);
2490 vino_drvdata->b.int_data.frame_counter = fc_b;
2491 }
2492 vino_drvdata->b.int_data.skip = skip_b;
2493
2494 dprintk("channel B %s, interrupt: %d\n",
2495 skip_b ? "skipping frame" : "frame done",
2496 intr);
2497 tasklet_hi_schedule(&vino_tasklet_b);
2498 handled_b = 1;
2499 }
2500
2501#ifdef VINO_DEBUG_INT
2502 loop++;
2503#endif
2504 spin_lock(&vino_drvdata->vino_lock);
2505 }
Ralf Baechled203a7e2005-09-06 15:19:37 -07002506
2507 spin_unlock(&vino_drvdata->vino_lock);
2508
Ralf Baechled203a7e2005-09-06 15:19:37 -07002509 return IRQ_HANDLED;
2510}
2511
2512/* VINO video input management */
2513
2514static int vino_get_saa7191_input(int input)
2515{
2516 switch (input) {
2517 case VINO_INPUT_COMPOSITE:
2518 return SAA7191_INPUT_COMPOSITE;
2519 case VINO_INPUT_SVIDEO:
2520 return SAA7191_INPUT_SVIDEO;
2521 default:
2522 printk(KERN_ERR "VINO: vino_get_saa7191_input(): "
2523 "invalid input!\n");
2524 return -1;
2525 }
2526}
2527
Ralf Baechled203a7e2005-09-06 15:19:37 -07002528/* execute with input_lock locked */
2529static int vino_is_input_owner(struct vino_channel_settings *vcs)
2530{
2531 switch(vcs->input) {
2532 case VINO_INPUT_COMPOSITE:
2533 case VINO_INPUT_SVIDEO:
Hans Verkuil48f4dac2009-02-18 19:18:26 -03002534 return vino_drvdata->decoder_owner == vcs->channel;
Ralf Baechled203a7e2005-09-06 15:19:37 -07002535 case VINO_INPUT_D1:
Hans Verkuil48f4dac2009-02-18 19:18:26 -03002536 return vino_drvdata->camera_owner == vcs->channel;
Ralf Baechled203a7e2005-09-06 15:19:37 -07002537 default:
2538 return 0;
2539 }
2540}
2541
2542static int vino_acquire_input(struct vino_channel_settings *vcs)
2543{
Ladislav Michla637a112005-09-01 15:07:34 +00002544 unsigned long flags;
Ralf Baechled203a7e2005-09-06 15:19:37 -07002545 int ret = 0;
2546
2547 dprintk("vino_acquire_input():\n");
2548
Ladislav Michla637a112005-09-01 15:07:34 +00002549 spin_lock_irqsave(&vino_drvdata->input_lock, flags);
Ralf Baechled203a7e2005-09-06 15:19:37 -07002550
2551 /* First try D1 and then SAA7191 */
Hans Verkuil48f4dac2009-02-18 19:18:26 -03002552 if (vino_drvdata->camera
2553 && (vino_drvdata->camera_owner == VINO_NO_CHANNEL)) {
2554 vino_drvdata->camera_owner = vcs->channel;
Ralf Baechled203a7e2005-09-06 15:19:37 -07002555 vcs->input = VINO_INPUT_D1;
2556 vcs->data_norm = VINO_DATA_NORM_D1;
Hans Verkuil48f4dac2009-02-18 19:18:26 -03002557 } else if (vino_drvdata->decoder
2558 && (vino_drvdata->decoder_owner == VINO_NO_CHANNEL)) {
Hans Verkuilcf4e9482009-02-27 09:05:10 -03002559 int input;
2560 int data_norm;
2561 v4l2_std_id norm;
2562 struct v4l2_routing route = { 0, 0 };
Ralf Baechled203a7e2005-09-06 15:19:37 -07002563
Ladislav Michla637a112005-09-01 15:07:34 +00002564 input = VINO_INPUT_COMPOSITE;
2565
Hans Verkuilcf4e9482009-02-27 09:05:10 -03002566 route.input = vino_get_saa7191_input(input);
Hans Verkuil48f4dac2009-02-18 19:18:26 -03002567 ret = decoder_call(video, s_routing, &route);
Ladislav Michla637a112005-09-01 15:07:34 +00002568 if (ret) {
2569 ret = -EINVAL;
2570 goto out;
2571 }
2572
2573 spin_unlock_irqrestore(&vino_drvdata->input_lock, flags);
2574
2575 /* Don't hold spinlocks while auto-detecting norm
2576 * as it may take a while... */
2577
Hans Verkuil48f4dac2009-02-18 19:18:26 -03002578 ret = decoder_call(video, querystd, &norm);
Hans Verkuilcf4e9482009-02-27 09:05:10 -03002579 if (!ret) {
2580 for (data_norm = 0; data_norm < 3; data_norm++) {
2581 if (vino_data_norms[data_norm].std & norm)
2582 break;
2583 }
2584 if (data_norm == 3)
2585 data_norm = VINO_DATA_NORM_PAL;
Hans Verkuil48f4dac2009-02-18 19:18:26 -03002586 ret = decoder_call(tuner, s_std, norm);
Ladislav Michla637a112005-09-01 15:07:34 +00002587 }
2588
2589 spin_lock_irqsave(&vino_drvdata->input_lock, flags);
2590
2591 if (ret) {
2592 ret = -EINVAL;
2593 goto out;
2594 }
2595
Hans Verkuil48f4dac2009-02-18 19:18:26 -03002596 vino_drvdata->decoder_owner = vcs->channel;
Ralf Baechled203a7e2005-09-06 15:19:37 -07002597
Ladislav Michla637a112005-09-01 15:07:34 +00002598 vcs->input = input;
2599 vcs->data_norm = data_norm;
Ralf Baechled203a7e2005-09-06 15:19:37 -07002600 } else {
2601 vcs->input = (vcs->channel == VINO_CHANNEL_A) ?
2602 vino_drvdata->b.input : vino_drvdata->a.input;
2603 vcs->data_norm = (vcs->channel == VINO_CHANNEL_A) ?
2604 vino_drvdata->b.data_norm : vino_drvdata->a.data_norm;
2605 }
2606
2607 if (vcs->input == VINO_INPUT_NONE) {
2608 ret = -ENODEV;
2609 goto out;
2610 }
2611
Ladislav Michla637a112005-09-01 15:07:34 +00002612 vino_set_default_clipping(vcs);
2613 vino_set_default_scaling(vcs);
2614 vino_set_default_framerate(vcs);
Ralf Baechled203a7e2005-09-06 15:19:37 -07002615
2616 dprintk("vino_acquire_input(): %s\n", vino_inputs[vcs->input].name);
2617
2618out:
Ladislav Michla637a112005-09-01 15:07:34 +00002619 spin_unlock_irqrestore(&vino_drvdata->input_lock, flags);
Ralf Baechled203a7e2005-09-06 15:19:37 -07002620
2621 return ret;
2622}
2623
2624static int vino_set_input(struct vino_channel_settings *vcs, int input)
2625{
2626 struct vino_channel_settings *vcs2 = (vcs->channel == VINO_CHANNEL_A) ?
2627 &vino_drvdata->b : &vino_drvdata->a;
Ladislav Michla637a112005-09-01 15:07:34 +00002628 unsigned long flags;
Ralf Baechled203a7e2005-09-06 15:19:37 -07002629 int ret = 0;
2630
2631 dprintk("vino_set_input():\n");
2632
Ladislav Michla637a112005-09-01 15:07:34 +00002633 spin_lock_irqsave(&vino_drvdata->input_lock, flags);
Ralf Baechled203a7e2005-09-06 15:19:37 -07002634
2635 if (vcs->input == input)
2636 goto out;
2637
Ladislav Michla637a112005-09-01 15:07:34 +00002638 switch (input) {
Ralf Baechled203a7e2005-09-06 15:19:37 -07002639 case VINO_INPUT_COMPOSITE:
2640 case VINO_INPUT_SVIDEO:
Hans Verkuil48f4dac2009-02-18 19:18:26 -03002641 if (!vino_drvdata->decoder) {
Ralf Baechled203a7e2005-09-06 15:19:37 -07002642 ret = -EINVAL;
2643 goto out;
2644 }
2645
Hans Verkuil48f4dac2009-02-18 19:18:26 -03002646 if (vino_drvdata->decoder_owner == VINO_NO_CHANNEL) {
2647 vino_drvdata->decoder_owner = vcs->channel;
Ralf Baechled203a7e2005-09-06 15:19:37 -07002648 }
2649
Hans Verkuil48f4dac2009-02-18 19:18:26 -03002650 if (vino_drvdata->decoder_owner == vcs->channel) {
Ladislav Michla637a112005-09-01 15:07:34 +00002651 int data_norm;
Hans Verkuilcf4e9482009-02-27 09:05:10 -03002652 v4l2_std_id norm;
2653 struct v4l2_routing route = { 0, 0 };
Ladislav Michla637a112005-09-01 15:07:34 +00002654
Hans Verkuilcf4e9482009-02-27 09:05:10 -03002655 route.input = vino_get_saa7191_input(input);
Hans Verkuil48f4dac2009-02-18 19:18:26 -03002656 ret = decoder_call(video, s_routing, &route);
Ladislav Michla637a112005-09-01 15:07:34 +00002657 if (ret) {
Hans Verkuil48f4dac2009-02-18 19:18:26 -03002658 vino_drvdata->decoder_owner = VINO_NO_CHANNEL;
Ladislav Michla637a112005-09-01 15:07:34 +00002659 ret = -EINVAL;
2660 goto out;
2661 }
2662
2663 spin_unlock_irqrestore(&vino_drvdata->input_lock, flags);
2664
2665 /* Don't hold spinlocks while auto-detecting norm
2666 * as it may take a while... */
2667
Hans Verkuil48f4dac2009-02-18 19:18:26 -03002668 ret = decoder_call(video, querystd, &norm);
Hans Verkuilcf4e9482009-02-27 09:05:10 -03002669 if (!ret) {
2670 for (data_norm = 0; data_norm < 3; data_norm++) {
2671 if (vino_data_norms[data_norm].std & norm)
2672 break;
2673 }
2674 if (data_norm == 3)
2675 data_norm = VINO_DATA_NORM_PAL;
Hans Verkuil48f4dac2009-02-18 19:18:26 -03002676 ret = decoder_call(tuner, s_std, norm);
Ladislav Michla637a112005-09-01 15:07:34 +00002677 }
2678
2679 spin_lock_irqsave(&vino_drvdata->input_lock, flags);
2680
2681 if (ret) {
Hans Verkuil48f4dac2009-02-18 19:18:26 -03002682 vino_drvdata->decoder_owner = VINO_NO_CHANNEL;
Ladislav Michla637a112005-09-01 15:07:34 +00002683 ret = -EINVAL;
2684 goto out;
2685 }
Ralf Baechled203a7e2005-09-06 15:19:37 -07002686
2687 vcs->input = input;
Ladislav Michla637a112005-09-01 15:07:34 +00002688 vcs->data_norm = data_norm;
Ralf Baechled203a7e2005-09-06 15:19:37 -07002689 } else {
Ladislav Michla637a112005-09-01 15:07:34 +00002690 if (input != vcs2->input) {
Ralf Baechled203a7e2005-09-06 15:19:37 -07002691 ret = -EBUSY;
2692 goto out;
2693 }
2694
2695 vcs->input = input;
2696 vcs->data_norm = vcs2->data_norm;
2697 }
2698
Hans Verkuil48f4dac2009-02-18 19:18:26 -03002699 if (vino_drvdata->camera_owner == vcs->channel) {
Ralf Baechled203a7e2005-09-06 15:19:37 -07002700 /* Transfer the ownership or release the input */
2701 if (vcs2->input == VINO_INPUT_D1) {
Hans Verkuil48f4dac2009-02-18 19:18:26 -03002702 vino_drvdata->camera_owner = vcs2->channel;
Ralf Baechled203a7e2005-09-06 15:19:37 -07002703 } else {
Hans Verkuil48f4dac2009-02-18 19:18:26 -03002704 vino_drvdata->camera_owner = VINO_NO_CHANNEL;
Ralf Baechled203a7e2005-09-06 15:19:37 -07002705 }
2706 }
2707 break;
2708 case VINO_INPUT_D1:
Hans Verkuil48f4dac2009-02-18 19:18:26 -03002709 if (!vino_drvdata->camera) {
Ralf Baechled203a7e2005-09-06 15:19:37 -07002710 ret = -EINVAL;
2711 goto out;
2712 }
2713
Hans Verkuil48f4dac2009-02-18 19:18:26 -03002714 if (vino_drvdata->camera_owner == VINO_NO_CHANNEL)
2715 vino_drvdata->camera_owner = vcs->channel;
Ralf Baechled203a7e2005-09-06 15:19:37 -07002716
Hans Verkuil48f4dac2009-02-18 19:18:26 -03002717 if (vino_drvdata->decoder_owner == vcs->channel) {
Ralf Baechled203a7e2005-09-06 15:19:37 -07002718 /* Transfer the ownership or release the input */
2719 if ((vcs2->input == VINO_INPUT_COMPOSITE) ||
2720 (vcs2->input == VINO_INPUT_SVIDEO)) {
Hans Verkuil48f4dac2009-02-18 19:18:26 -03002721 vino_drvdata->decoder_owner = vcs2->channel;
Ralf Baechled203a7e2005-09-06 15:19:37 -07002722 } else {
Hans Verkuil48f4dac2009-02-18 19:18:26 -03002723 vino_drvdata->decoder_owner = VINO_NO_CHANNEL;
Ralf Baechled203a7e2005-09-06 15:19:37 -07002724 }
2725 }
2726
2727 vcs->input = input;
2728 vcs->data_norm = VINO_DATA_NORM_D1;
2729 break;
2730 default:
2731 ret = -EINVAL;
2732 goto out;
2733 }
2734
2735 vino_set_default_clipping(vcs);
Ladislav Michla637a112005-09-01 15:07:34 +00002736 vino_set_default_scaling(vcs);
Ralf Baechled203a7e2005-09-06 15:19:37 -07002737 vino_set_default_framerate(vcs);
2738
2739 dprintk("vino_set_input(): %s\n", vino_inputs[vcs->input].name);
2740
2741out:
Ladislav Michla637a112005-09-01 15:07:34 +00002742 spin_unlock_irqrestore(&vino_drvdata->input_lock, flags);
Ralf Baechled203a7e2005-09-06 15:19:37 -07002743
2744 return ret;
2745}
2746
2747static void vino_release_input(struct vino_channel_settings *vcs)
2748{
2749 struct vino_channel_settings *vcs2 = (vcs->channel == VINO_CHANNEL_A) ?
2750 &vino_drvdata->b : &vino_drvdata->a;
Ladislav Michla637a112005-09-01 15:07:34 +00002751 unsigned long flags;
Ralf Baechled203a7e2005-09-06 15:19:37 -07002752
2753 dprintk("vino_release_input():\n");
2754
Ladislav Michla637a112005-09-01 15:07:34 +00002755 spin_lock_irqsave(&vino_drvdata->input_lock, flags);
Ralf Baechled203a7e2005-09-06 15:19:37 -07002756
2757 /* Release ownership of the channel
2758 * and if the other channel takes input from
2759 * the same source, transfer the ownership */
Hans Verkuil48f4dac2009-02-18 19:18:26 -03002760 if (vino_drvdata->camera_owner == vcs->channel) {
Ralf Baechled203a7e2005-09-06 15:19:37 -07002761 if (vcs2->input == VINO_INPUT_D1) {
Hans Verkuil48f4dac2009-02-18 19:18:26 -03002762 vino_drvdata->camera_owner = vcs2->channel;
Ralf Baechled203a7e2005-09-06 15:19:37 -07002763 } else {
Hans Verkuil48f4dac2009-02-18 19:18:26 -03002764 vino_drvdata->camera_owner = VINO_NO_CHANNEL;
Ralf Baechled203a7e2005-09-06 15:19:37 -07002765 }
Hans Verkuil48f4dac2009-02-18 19:18:26 -03002766 } else if (vino_drvdata->decoder_owner == vcs->channel) {
Ralf Baechled203a7e2005-09-06 15:19:37 -07002767 if ((vcs2->input == VINO_INPUT_COMPOSITE) ||
2768 (vcs2->input == VINO_INPUT_SVIDEO)) {
Hans Verkuil48f4dac2009-02-18 19:18:26 -03002769 vino_drvdata->decoder_owner = vcs2->channel;
Ralf Baechled203a7e2005-09-06 15:19:37 -07002770 } else {
Hans Verkuil48f4dac2009-02-18 19:18:26 -03002771 vino_drvdata->decoder_owner = VINO_NO_CHANNEL;
Ralf Baechled203a7e2005-09-06 15:19:37 -07002772 }
2773 }
2774 vcs->input = VINO_INPUT_NONE;
2775
Ladislav Michla637a112005-09-01 15:07:34 +00002776 spin_unlock_irqrestore(&vino_drvdata->input_lock, flags);
Ralf Baechled203a7e2005-09-06 15:19:37 -07002777}
2778
2779/* execute with input_lock locked */
2780static int vino_set_data_norm(struct vino_channel_settings *vcs,
Ladislav Michla637a112005-09-01 15:07:34 +00002781 unsigned int data_norm,
2782 unsigned long *flags)
Ralf Baechled203a7e2005-09-06 15:19:37 -07002783{
Ladislav Michla637a112005-09-01 15:07:34 +00002784 int err = 0;
2785
2786 if (data_norm == vcs->data_norm)
2787 return 0;
Ralf Baechled203a7e2005-09-06 15:19:37 -07002788
2789 switch (vcs->input) {
2790 case VINO_INPUT_D1:
2791 /* only one "norm" supported */
Hans Verkuilcf4e9482009-02-27 09:05:10 -03002792 if (data_norm != VINO_DATA_NORM_D1)
Ralf Baechled203a7e2005-09-06 15:19:37 -07002793 return -EINVAL;
2794 break;
2795 case VINO_INPUT_COMPOSITE:
Ladislav Michla637a112005-09-01 15:07:34 +00002796 case VINO_INPUT_SVIDEO: {
Hans Verkuilcf4e9482009-02-27 09:05:10 -03002797 v4l2_std_id norm;
2798
Ladislav Michla637a112005-09-01 15:07:34 +00002799 if ((data_norm != VINO_DATA_NORM_PAL)
2800 && (data_norm != VINO_DATA_NORM_NTSC)
Hans Verkuilcf4e9482009-02-27 09:05:10 -03002801 && (data_norm != VINO_DATA_NORM_SECAM))
Ladislav Michla637a112005-09-01 15:07:34 +00002802 return -EINVAL;
Ralf Baechled203a7e2005-09-06 15:19:37 -07002803
Ladislav Michla637a112005-09-01 15:07:34 +00002804 spin_unlock_irqrestore(&vino_drvdata->input_lock, *flags);
Ralf Baechled203a7e2005-09-06 15:19:37 -07002805
Ladislav Michla637a112005-09-01 15:07:34 +00002806 /* Don't hold spinlocks while setting norm
2807 * as it may take a while... */
2808
Hans Verkuilcf4e9482009-02-27 09:05:10 -03002809 norm = vino_data_norms[data_norm].std;
Hans Verkuil48f4dac2009-02-18 19:18:26 -03002810 err = decoder_call(tuner, s_std, norm);
Ladislav Michla637a112005-09-01 15:07:34 +00002811
2812 spin_lock_irqsave(&vino_drvdata->input_lock, *flags);
2813
2814 if (err)
2815 goto out;
2816
Ralf Baechled203a7e2005-09-06 15:19:37 -07002817 vcs->data_norm = data_norm;
Ladislav Michla637a112005-09-01 15:07:34 +00002818
2819 vino_set_default_clipping(vcs);
2820 vino_set_default_scaling(vcs);
2821 vino_set_default_framerate(vcs);
Ralf Baechled203a7e2005-09-06 15:19:37 -07002822 break;
Ladislav Michla637a112005-09-01 15:07:34 +00002823 }
Ralf Baechled203a7e2005-09-06 15:19:37 -07002824 default:
2825 return -EINVAL;
2826 }
2827
Ladislav Michla637a112005-09-01 15:07:34 +00002828out:
2829 return err;
Ralf Baechled203a7e2005-09-06 15:19:37 -07002830}
2831
2832/* V4L2 helper functions */
2833
2834static int vino_find_data_format(__u32 pixelformat)
2835{
2836 int i;
2837
2838 for (i = 0; i < VINO_DATA_FMT_COUNT; i++) {
2839 if (vino_data_formats[i].pixelformat == pixelformat)
2840 return i;
2841 }
2842
2843 return VINO_DATA_FMT_NONE;
2844}
2845
Hans Verkuilc49cb362009-02-12 10:32:50 -03002846static int vino_int_enum_input(struct vino_channel_settings *vcs, __u32 index)
Ralf Baechled203a7e2005-09-06 15:19:37 -07002847{
2848 int input = VINO_INPUT_NONE;
Ladislav Michla637a112005-09-01 15:07:34 +00002849 unsigned long flags;
Ralf Baechled203a7e2005-09-06 15:19:37 -07002850
Ladislav Michla637a112005-09-01 15:07:34 +00002851 spin_lock_irqsave(&vino_drvdata->input_lock, flags);
Hans Verkuil48f4dac2009-02-18 19:18:26 -03002852 if (vino_drvdata->decoder && vino_drvdata->camera) {
Ralf Baechled203a7e2005-09-06 15:19:37 -07002853 switch (index) {
2854 case 0:
2855 input = VINO_INPUT_COMPOSITE;
2856 break;
2857 case 1:
2858 input = VINO_INPUT_SVIDEO;
2859 break;
2860 case 2:
2861 input = VINO_INPUT_D1;
2862 break;
2863 }
Hans Verkuil48f4dac2009-02-18 19:18:26 -03002864 } else if (vino_drvdata->decoder) {
Ralf Baechled203a7e2005-09-06 15:19:37 -07002865 switch (index) {
2866 case 0:
2867 input = VINO_INPUT_COMPOSITE;
2868 break;
2869 case 1:
2870 input = VINO_INPUT_SVIDEO;
2871 break;
2872 }
Hans Verkuil48f4dac2009-02-18 19:18:26 -03002873 } else if (vino_drvdata->camera) {
Ralf Baechled203a7e2005-09-06 15:19:37 -07002874 switch (index) {
2875 case 0:
2876 input = VINO_INPUT_D1;
2877 break;
2878 }
2879 }
Ladislav Michla637a112005-09-01 15:07:34 +00002880 spin_unlock_irqrestore(&vino_drvdata->input_lock, flags);
Ralf Baechled203a7e2005-09-06 15:19:37 -07002881
2882 return input;
2883}
2884
2885/* execute with input_lock locked */
2886static __u32 vino_find_input_index(struct vino_channel_settings *vcs)
2887{
2888 __u32 index = 0;
2889 // FIXME: detect when no inputs available
2890
Hans Verkuil48f4dac2009-02-18 19:18:26 -03002891 if (vino_drvdata->decoder && vino_drvdata->camera) {
Ralf Baechled203a7e2005-09-06 15:19:37 -07002892 switch (vcs->input) {
2893 case VINO_INPUT_COMPOSITE:
2894 index = 0;
2895 break;
2896 case VINO_INPUT_SVIDEO:
2897 index = 1;
2898 break;
2899 case VINO_INPUT_D1:
2900 index = 2;
2901 break;
2902 }
Hans Verkuil48f4dac2009-02-18 19:18:26 -03002903 } else if (vino_drvdata->decoder) {
Ralf Baechled203a7e2005-09-06 15:19:37 -07002904 switch (vcs->input) {
2905 case VINO_INPUT_COMPOSITE:
2906 index = 0;
2907 break;
2908 case VINO_INPUT_SVIDEO:
2909 index = 1;
2910 break;
2911 }
Hans Verkuil48f4dac2009-02-18 19:18:26 -03002912 } else if (vino_drvdata->camera) {
Ralf Baechled203a7e2005-09-06 15:19:37 -07002913 switch (vcs->input) {
2914 case VINO_INPUT_D1:
2915 index = 0;
2916 break;
2917 }
2918 }
2919
2920 return index;
2921}
2922
2923/* V4L2 ioctls */
2924
Hans Verkuilc49cb362009-02-12 10:32:50 -03002925static int vino_querycap(struct file *file, void *__fh,
2926 struct v4l2_capability *cap)
Ralf Baechled203a7e2005-09-06 15:19:37 -07002927{
2928 memset(cap, 0, sizeof(struct v4l2_capability));
2929
2930 strcpy(cap->driver, vino_driver_name);
2931 strcpy(cap->card, vino_driver_description);
2932 strcpy(cap->bus_info, vino_bus_name);
2933 cap->version = VINO_VERSION_CODE;
2934 cap->capabilities =
2935 V4L2_CAP_VIDEO_CAPTURE |
2936 V4L2_CAP_STREAMING;
2937 // V4L2_CAP_OVERLAY, V4L2_CAP_READWRITE
Hans Verkuilc49cb362009-02-12 10:32:50 -03002938 return 0;
Ralf Baechled203a7e2005-09-06 15:19:37 -07002939}
2940
Hans Verkuilc49cb362009-02-12 10:32:50 -03002941static int vino_enum_input(struct file *file, void *__fh,
Ralf Baechled203a7e2005-09-06 15:19:37 -07002942 struct v4l2_input *i)
2943{
Hans Verkuilc49cb362009-02-12 10:32:50 -03002944 struct vino_channel_settings *vcs = video_drvdata(file);
Ralf Baechled203a7e2005-09-06 15:19:37 -07002945 __u32 index = i->index;
2946 int input;
2947 dprintk("requested index = %d\n", index);
2948
Hans Verkuilc49cb362009-02-12 10:32:50 -03002949 input = vino_int_enum_input(vcs, index);
Ralf Baechled203a7e2005-09-06 15:19:37 -07002950 if (input == VINO_INPUT_NONE)
2951 return -EINVAL;
2952
2953 memset(i, 0, sizeof(struct v4l2_input));
2954
2955 i->index = index;
2956 i->type = V4L2_INPUT_TYPE_CAMERA;
2957 i->std = vino_inputs[input].std;
2958 strcpy(i->name, vino_inputs[input].name);
2959
Hans Verkuilcf4e9482009-02-27 09:05:10 -03002960 if (input == VINO_INPUT_COMPOSITE || input == VINO_INPUT_SVIDEO)
Hans Verkuil48f4dac2009-02-18 19:18:26 -03002961 decoder_call(video, g_input_status, &i->status);
Ralf Baechled203a7e2005-09-06 15:19:37 -07002962 return 0;
2963}
2964
Hans Verkuilc49cb362009-02-12 10:32:50 -03002965static int vino_g_input(struct file *file, void *__fh,
Ladislav Michla637a112005-09-01 15:07:34 +00002966 unsigned int *i)
Ralf Baechled203a7e2005-09-06 15:19:37 -07002967{
Hans Verkuilc49cb362009-02-12 10:32:50 -03002968 struct vino_channel_settings *vcs = video_drvdata(file);
Ralf Baechled203a7e2005-09-06 15:19:37 -07002969 __u32 index;
2970 int input;
Ladislav Michla637a112005-09-01 15:07:34 +00002971 unsigned long flags;
Ralf Baechled203a7e2005-09-06 15:19:37 -07002972
Ladislav Michla637a112005-09-01 15:07:34 +00002973 spin_lock_irqsave(&vino_drvdata->input_lock, flags);
Ralf Baechled203a7e2005-09-06 15:19:37 -07002974 input = vcs->input;
2975 index = vino_find_input_index(vcs);
Ladislav Michla637a112005-09-01 15:07:34 +00002976 spin_unlock_irqrestore(&vino_drvdata->input_lock, flags);
Ralf Baechled203a7e2005-09-06 15:19:37 -07002977
2978 dprintk("input = %d\n", input);
2979
2980 if (input == VINO_INPUT_NONE) {
2981 return -EINVAL;
2982 }
2983
Ladislav Michla637a112005-09-01 15:07:34 +00002984 *i = index;
Ralf Baechled203a7e2005-09-06 15:19:37 -07002985
2986 return 0;
2987}
2988
Hans Verkuilc49cb362009-02-12 10:32:50 -03002989static int vino_s_input(struct file *file, void *__fh,
2990 unsigned int i)
Ralf Baechled203a7e2005-09-06 15:19:37 -07002991{
Hans Verkuilc49cb362009-02-12 10:32:50 -03002992 struct vino_channel_settings *vcs = video_drvdata(file);
Ralf Baechled203a7e2005-09-06 15:19:37 -07002993 int input;
Hans Verkuilc49cb362009-02-12 10:32:50 -03002994 dprintk("requested input = %d\n", i);
Ralf Baechled203a7e2005-09-06 15:19:37 -07002995
Hans Verkuilc49cb362009-02-12 10:32:50 -03002996 input = vino_int_enum_input(vcs, i);
Ralf Baechled203a7e2005-09-06 15:19:37 -07002997 if (input == VINO_INPUT_NONE)
2998 return -EINVAL;
2999
3000 return vino_set_input(vcs, input);
3001}
3002
Hans Verkuilc49cb362009-02-12 10:32:50 -03003003static int vino_querystd(struct file *file, void *__fh,
Ladislav Michla637a112005-09-01 15:07:34 +00003004 v4l2_std_id *std)
3005{
Hans Verkuilc49cb362009-02-12 10:32:50 -03003006 struct vino_channel_settings *vcs = video_drvdata(file);
Ladislav Michla637a112005-09-01 15:07:34 +00003007 unsigned long flags;
3008 int err = 0;
3009
3010 spin_lock_irqsave(&vino_drvdata->input_lock, flags);
3011
3012 switch (vcs->input) {
3013 case VINO_INPUT_D1:
3014 *std = vino_inputs[vcs->input].std;
3015 break;
3016 case VINO_INPUT_COMPOSITE:
3017 case VINO_INPUT_SVIDEO: {
Hans Verkuil48f4dac2009-02-18 19:18:26 -03003018 decoder_call(video, querystd, std);
Ladislav Michla637a112005-09-01 15:07:34 +00003019 break;
3020 }
3021 default:
3022 err = -EINVAL;
3023 }
3024
3025 spin_unlock_irqrestore(&vino_drvdata->input_lock, flags);
3026
3027 return err;
3028}
3029
Hans Verkuilc49cb362009-02-12 10:32:50 -03003030static int vino_g_std(struct file *file, void *__fh,
Ralf Baechled203a7e2005-09-06 15:19:37 -07003031 v4l2_std_id *std)
3032{
Hans Verkuilc49cb362009-02-12 10:32:50 -03003033 struct vino_channel_settings *vcs = video_drvdata(file);
Ladislav Michla637a112005-09-01 15:07:34 +00003034 unsigned long flags;
3035
3036 spin_lock_irqsave(&vino_drvdata->input_lock, flags);
3037
Ralf Baechled203a7e2005-09-06 15:19:37 -07003038 *std = vino_data_norms[vcs->data_norm].std;
Ladislav Michla637a112005-09-01 15:07:34 +00003039 dprintk("current standard = %d\n", vcs->data_norm);
3040
3041 spin_unlock_irqrestore(&vino_drvdata->input_lock, flags);
Ralf Baechled203a7e2005-09-06 15:19:37 -07003042
3043 return 0;
3044}
3045
Hans Verkuilc49cb362009-02-12 10:32:50 -03003046static int vino_s_std(struct file *file, void *__fh,
Ralf Baechled203a7e2005-09-06 15:19:37 -07003047 v4l2_std_id *std)
3048{
Hans Verkuilc49cb362009-02-12 10:32:50 -03003049 struct vino_channel_settings *vcs = video_drvdata(file);
Ladislav Michla637a112005-09-01 15:07:34 +00003050 unsigned long flags;
Ralf Baechled203a7e2005-09-06 15:19:37 -07003051 int ret = 0;
3052
Ladislav Michla637a112005-09-01 15:07:34 +00003053 spin_lock_irqsave(&vino_drvdata->input_lock, flags);
3054
3055 if (!vino_is_input_owner(vcs)) {
3056 ret = -EBUSY;
3057 goto out;
3058 }
Ralf Baechled203a7e2005-09-06 15:19:37 -07003059
3060 /* check if the standard is valid for the current input */
Ladislav Michla637a112005-09-01 15:07:34 +00003061 if ((*std) & vino_inputs[vcs->input].std) {
Ralf Baechled203a7e2005-09-06 15:19:37 -07003062 dprintk("standard accepted\n");
3063
3064 /* change the video norm for SAA7191
3065 * and accept NTSC for D1 (do nothing) */
3066
3067 if (vcs->input == VINO_INPUT_D1)
3068 goto out;
3069
Hans Verkuilcf4e9482009-02-27 09:05:10 -03003070 if ((*std) & V4L2_STD_PAL) {
Ladislav Michla637a112005-09-01 15:07:34 +00003071 ret = vino_set_data_norm(vcs, VINO_DATA_NORM_PAL,
3072 &flags);
Ralf Baechled203a7e2005-09-06 15:19:37 -07003073 } else if ((*std) & V4L2_STD_NTSC) {
Ladislav Michla637a112005-09-01 15:07:34 +00003074 ret = vino_set_data_norm(vcs, VINO_DATA_NORM_NTSC,
3075 &flags);
Ralf Baechled203a7e2005-09-06 15:19:37 -07003076 } else if ((*std) & V4L2_STD_SECAM) {
Ladislav Michla637a112005-09-01 15:07:34 +00003077 ret = vino_set_data_norm(vcs, VINO_DATA_NORM_SECAM,
3078 &flags);
Ralf Baechled203a7e2005-09-06 15:19:37 -07003079 } else {
3080 ret = -EINVAL;
3081 }
Ladislav Michla637a112005-09-01 15:07:34 +00003082
3083 if (ret) {
3084 ret = -EINVAL;
3085 }
Ralf Baechled203a7e2005-09-06 15:19:37 -07003086 } else {
3087 ret = -EINVAL;
3088 }
3089
3090out:
Ladislav Michla637a112005-09-01 15:07:34 +00003091 spin_unlock_irqrestore(&vino_drvdata->input_lock, flags);
Ralf Baechled203a7e2005-09-06 15:19:37 -07003092
3093 return ret;
3094}
3095
Hans Verkuilc49cb362009-02-12 10:32:50 -03003096static int vino_enum_fmt_vid_cap(struct file *file, void *__fh,
Ralf Baechled203a7e2005-09-06 15:19:37 -07003097 struct v4l2_fmtdesc *fd)
3098{
3099 enum v4l2_buf_type type = fd->type;
3100 int index = fd->index;
Hans Verkuilc49cb362009-02-12 10:32:50 -03003101
Ralf Baechled203a7e2005-09-06 15:19:37 -07003102 dprintk("format index = %d\n", index);
3103
Hans Verkuilc49cb362009-02-12 10:32:50 -03003104 if ((fd->index < 0) ||
3105 (fd->index >= VINO_DATA_FMT_COUNT))
Ralf Baechled203a7e2005-09-06 15:19:37 -07003106 return -EINVAL;
Hans Verkuilc49cb362009-02-12 10:32:50 -03003107 dprintk("format name = %s\n",
3108 vino_data_formats[index].description);
Ralf Baechled203a7e2005-09-06 15:19:37 -07003109
Hans Verkuilc49cb362009-02-12 10:32:50 -03003110 memset(fd, 0, sizeof(struct v4l2_fmtdesc));
3111 fd->index = index;
3112 fd->type = type;
3113 fd->pixelformat = vino_data_formats[index].pixelformat;
3114 strcpy(fd->description, vino_data_formats[index].description);
Ralf Baechled203a7e2005-09-06 15:19:37 -07003115 return 0;
3116}
3117
Hans Verkuilc49cb362009-02-12 10:32:50 -03003118static int vino_try_fmt_vid_cap(struct file *file, void *__fh,
Ralf Baechled203a7e2005-09-06 15:19:37 -07003119 struct v4l2_format *f)
3120{
Hans Verkuilc49cb362009-02-12 10:32:50 -03003121 struct vino_channel_settings *vcs = video_drvdata(file);
Ralf Baechled203a7e2005-09-06 15:19:37 -07003122 struct vino_channel_settings tempvcs;
Ladislav Michla637a112005-09-01 15:07:34 +00003123 unsigned long flags;
Hans Verkuilc49cb362009-02-12 10:32:50 -03003124 struct v4l2_pix_format *pf = &f->fmt.pix;
Ralf Baechled203a7e2005-09-06 15:19:37 -07003125
Hans Verkuilc49cb362009-02-12 10:32:50 -03003126 dprintk("requested: w = %d, h = %d\n",
3127 pf->width, pf->height);
Ralf Baechled203a7e2005-09-06 15:19:37 -07003128
Hans Verkuilc49cb362009-02-12 10:32:50 -03003129 spin_lock_irqsave(&vino_drvdata->input_lock, flags);
3130 memcpy(&tempvcs, vcs, sizeof(struct vino_channel_settings));
3131 spin_unlock_irqrestore(&vino_drvdata->input_lock, flags);
Ralf Baechled203a7e2005-09-06 15:19:37 -07003132
Hans Verkuilc49cb362009-02-12 10:32:50 -03003133 tempvcs.data_format = vino_find_data_format(pf->pixelformat);
3134 if (tempvcs.data_format == VINO_DATA_FMT_NONE) {
3135 tempvcs.data_format = VINO_DATA_FMT_GREY;
Ralf Baechled203a7e2005-09-06 15:19:37 -07003136 pf->pixelformat =
Hans Verkuilc49cb362009-02-12 10:32:50 -03003137 vino_data_formats[tempvcs.data_format].
3138 pixelformat;
Ralf Baechled203a7e2005-09-06 15:19:37 -07003139 }
3140
Hans Verkuilc49cb362009-02-12 10:32:50 -03003141 /* data format must be set before clipping/scaling */
3142 vino_set_scaling(&tempvcs, pf->width, pf->height);
3143
3144 dprintk("data format = %s\n",
3145 vino_data_formats[tempvcs.data_format].description);
3146
3147 pf->width = (tempvcs.clipping.right - tempvcs.clipping.left) /
3148 tempvcs.decimation;
3149 pf->height = (tempvcs.clipping.bottom - tempvcs.clipping.top) /
3150 tempvcs.decimation;
3151
3152 pf->field = V4L2_FIELD_INTERLACED;
3153 pf->bytesperline = tempvcs.line_size;
3154 pf->sizeimage = tempvcs.line_size *
3155 (tempvcs.clipping.bottom - tempvcs.clipping.top) /
3156 tempvcs.decimation;
3157 pf->colorspace =
3158 vino_data_formats[tempvcs.data_format].colorspace;
3159
3160 pf->priv = 0;
Ralf Baechled203a7e2005-09-06 15:19:37 -07003161 return 0;
3162}
3163
Hans Verkuilc49cb362009-02-12 10:32:50 -03003164static int vino_g_fmt_vid_cap(struct file *file, void *__fh,
Ralf Baechled203a7e2005-09-06 15:19:37 -07003165 struct v4l2_format *f)
3166{
Hans Verkuilc49cb362009-02-12 10:32:50 -03003167 struct vino_channel_settings *vcs = video_drvdata(file);
3168 unsigned long flags;
3169 struct v4l2_pix_format *pf = &f->fmt.pix;
3170
3171 spin_lock_irqsave(&vino_drvdata->input_lock, flags);
3172
3173 pf->width = (vcs->clipping.right - vcs->clipping.left) /
3174 vcs->decimation;
3175 pf->height = (vcs->clipping.bottom - vcs->clipping.top) /
3176 vcs->decimation;
3177 pf->pixelformat =
3178 vino_data_formats[vcs->data_format].pixelformat;
3179
3180 pf->field = V4L2_FIELD_INTERLACED;
3181 pf->bytesperline = vcs->line_size;
3182 pf->sizeimage = vcs->line_size *
3183 (vcs->clipping.bottom - vcs->clipping.top) /
3184 vcs->decimation;
3185 pf->colorspace =
3186 vino_data_formats[vcs->data_format].colorspace;
3187
3188 pf->priv = 0;
3189
3190 spin_unlock_irqrestore(&vino_drvdata->input_lock, flags);
3191 return 0;
3192}
3193
3194static int vino_s_fmt_vid_cap(struct file *file, void *__fh,
3195 struct v4l2_format *f)
3196{
3197 struct vino_channel_settings *vcs = video_drvdata(file);
Ralf Baechled203a7e2005-09-06 15:19:37 -07003198 int data_format;
Ladislav Michla637a112005-09-01 15:07:34 +00003199 unsigned long flags;
Hans Verkuilc49cb362009-02-12 10:32:50 -03003200 struct v4l2_pix_format *pf = &f->fmt.pix;
Ralf Baechled203a7e2005-09-06 15:19:37 -07003201
Hans Verkuilc49cb362009-02-12 10:32:50 -03003202 spin_lock_irqsave(&vino_drvdata->input_lock, flags);
Ralf Baechled203a7e2005-09-06 15:19:37 -07003203
Hans Verkuilc49cb362009-02-12 10:32:50 -03003204 data_format = vino_find_data_format(pf->pixelformat);
Ralf Baechled203a7e2005-09-06 15:19:37 -07003205
Hans Verkuilc49cb362009-02-12 10:32:50 -03003206 if (data_format == VINO_DATA_FMT_NONE) {
3207 vcs->data_format = VINO_DATA_FMT_GREY;
3208 pf->pixelformat =
3209 vino_data_formats[vcs->data_format].
3210 pixelformat;
3211 } else {
3212 vcs->data_format = data_format;
Ralf Baechled203a7e2005-09-06 15:19:37 -07003213 }
3214
Hans Verkuilc49cb362009-02-12 10:32:50 -03003215 /* data format must be set before clipping/scaling */
3216 vino_set_scaling(vcs, pf->width, pf->height);
3217
3218 dprintk("data format = %s\n",
3219 vino_data_formats[vcs->data_format].description);
3220
3221 pf->width = vcs->clipping.right - vcs->clipping.left;
3222 pf->height = vcs->clipping.bottom - vcs->clipping.top;
3223
3224 pf->field = V4L2_FIELD_INTERLACED;
3225 pf->bytesperline = vcs->line_size;
3226 pf->sizeimage = vcs->line_size *
3227 (vcs->clipping.bottom - vcs->clipping.top) /
3228 vcs->decimation;
3229 pf->colorspace =
3230 vino_data_formats[vcs->data_format].colorspace;
3231
3232 pf->priv = 0;
3233
3234 spin_unlock_irqrestore(&vino_drvdata->input_lock, flags);
Ralf Baechled203a7e2005-09-06 15:19:37 -07003235 return 0;
3236}
3237
Hans Verkuilc49cb362009-02-12 10:32:50 -03003238static int vino_cropcap(struct file *file, void *__fh,
Ralf Baechled203a7e2005-09-06 15:19:37 -07003239 struct v4l2_cropcap *ccap)
3240{
Hans Verkuilc49cb362009-02-12 10:32:50 -03003241 struct vino_channel_settings *vcs = video_drvdata(file);
Ralf Baechled203a7e2005-09-06 15:19:37 -07003242 const struct vino_data_norm *norm;
Ladislav Michla637a112005-09-01 15:07:34 +00003243 unsigned long flags;
Ralf Baechled203a7e2005-09-06 15:19:37 -07003244
3245 switch (ccap->type) {
3246 case V4L2_BUF_TYPE_VIDEO_CAPTURE:
Ladislav Michla637a112005-09-01 15:07:34 +00003247 spin_lock_irqsave(&vino_drvdata->input_lock, flags);
3248
Ralf Baechled203a7e2005-09-06 15:19:37 -07003249 norm = &vino_data_norms[vcs->data_norm];
Ladislav Michla637a112005-09-01 15:07:34 +00003250
3251 spin_unlock_irqrestore(&vino_drvdata->input_lock, flags);
Ralf Baechled203a7e2005-09-06 15:19:37 -07003252
3253 ccap->bounds.left = 0;
3254 ccap->bounds.top = 0;
3255 ccap->bounds.width = norm->width;
3256 ccap->bounds.height = norm->height;
3257 memcpy(&ccap->defrect, &ccap->bounds,
3258 sizeof(struct v4l2_rect));
3259
3260 ccap->pixelaspect.numerator = 1;
3261 ccap->pixelaspect.denominator = 1;
3262 break;
3263 case V4L2_BUF_TYPE_VIDEO_OVERLAY:
3264 default:
3265 return -EINVAL;
3266 }
3267
3268 return 0;
3269}
3270
Hans Verkuilc49cb362009-02-12 10:32:50 -03003271static int vino_g_crop(struct file *file, void *__fh,
Ralf Baechled203a7e2005-09-06 15:19:37 -07003272 struct v4l2_crop *c)
3273{
Hans Verkuilc49cb362009-02-12 10:32:50 -03003274 struct vino_channel_settings *vcs = video_drvdata(file);
Ladislav Michla637a112005-09-01 15:07:34 +00003275 unsigned long flags;
3276
Ralf Baechled203a7e2005-09-06 15:19:37 -07003277 switch (c->type) {
3278 case V4L2_BUF_TYPE_VIDEO_CAPTURE:
Ladislav Michla637a112005-09-01 15:07:34 +00003279 spin_lock_irqsave(&vino_drvdata->input_lock, flags);
Ralf Baechled203a7e2005-09-06 15:19:37 -07003280
3281 c->c.left = vcs->clipping.left;
3282 c->c.top = vcs->clipping.top;
3283 c->c.width = vcs->clipping.right - vcs->clipping.left;
3284 c->c.height = vcs->clipping.bottom - vcs->clipping.top;
3285
Ladislav Michla637a112005-09-01 15:07:34 +00003286 spin_unlock_irqrestore(&vino_drvdata->input_lock, flags);
Ralf Baechled203a7e2005-09-06 15:19:37 -07003287 break;
3288 case V4L2_BUF_TYPE_VIDEO_OVERLAY:
3289 default:
3290 return -EINVAL;
3291 }
3292
3293 return 0;
3294}
3295
Hans Verkuilc49cb362009-02-12 10:32:50 -03003296static int vino_s_crop(struct file *file, void *__fh,
Ralf Baechled203a7e2005-09-06 15:19:37 -07003297 struct v4l2_crop *c)
3298{
Hans Verkuilc49cb362009-02-12 10:32:50 -03003299 struct vino_channel_settings *vcs = video_drvdata(file);
Ladislav Michla637a112005-09-01 15:07:34 +00003300 unsigned long flags;
3301
Ralf Baechled203a7e2005-09-06 15:19:37 -07003302 switch (c->type) {
3303 case V4L2_BUF_TYPE_VIDEO_CAPTURE:
Ladislav Michla637a112005-09-01 15:07:34 +00003304 spin_lock_irqsave(&vino_drvdata->input_lock, flags);
Ralf Baechled203a7e2005-09-06 15:19:37 -07003305
Ralf Baechled203a7e2005-09-06 15:19:37 -07003306 vino_set_clipping(vcs, c->c.left, c->c.top,
3307 c->c.width, c->c.height);
3308
Ladislav Michla637a112005-09-01 15:07:34 +00003309 spin_unlock_irqrestore(&vino_drvdata->input_lock, flags);
Ralf Baechled203a7e2005-09-06 15:19:37 -07003310 break;
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_g_parm(struct file *file, void *__fh,
Ralf Baechled203a7e2005-09-06 15:19:37 -07003320 struct v4l2_streamparm *sp)
3321{
Hans Verkuilc49cb362009-02-12 10:32:50 -03003322 struct vino_channel_settings *vcs = video_drvdata(file);
Ladislav Michla637a112005-09-01 15:07:34 +00003323 unsigned long flags;
3324
Ralf Baechled203a7e2005-09-06 15:19:37 -07003325 switch (sp->type) {
3326 case V4L2_BUF_TYPE_VIDEO_CAPTURE: {
3327 struct v4l2_captureparm *cp = &sp->parm.capture;
3328 memset(cp, 0, sizeof(struct v4l2_captureparm));
3329
3330 cp->capability = V4L2_CAP_TIMEPERFRAME;
3331 cp->timeperframe.numerator = 1;
3332
Ladislav Michla637a112005-09-01 15:07:34 +00003333 spin_lock_irqsave(&vino_drvdata->input_lock, flags);
3334
Ralf Baechled203a7e2005-09-06 15:19:37 -07003335 cp->timeperframe.denominator = vcs->fps;
Ladislav Michla637a112005-09-01 15:07:34 +00003336
3337 spin_unlock_irqrestore(&vino_drvdata->input_lock, flags);
Ralf Baechled203a7e2005-09-06 15:19:37 -07003338
3339 // TODO: cp->readbuffers = xxx;
3340 break;
3341 }
3342 case V4L2_BUF_TYPE_VIDEO_OVERLAY:
3343 default:
3344 return -EINVAL;
3345 }
3346
3347 return 0;
3348}
3349
Hans Verkuilc49cb362009-02-12 10:32:50 -03003350static int vino_s_parm(struct file *file, void *__fh,
Ralf Baechled203a7e2005-09-06 15:19:37 -07003351 struct v4l2_streamparm *sp)
3352{
Hans Verkuilc49cb362009-02-12 10:32:50 -03003353 struct vino_channel_settings *vcs = video_drvdata(file);
Ladislav Michla637a112005-09-01 15:07:34 +00003354 unsigned long flags;
3355
Ralf Baechled203a7e2005-09-06 15:19:37 -07003356 switch (sp->type) {
3357 case V4L2_BUF_TYPE_VIDEO_CAPTURE: {
3358 struct v4l2_captureparm *cp = &sp->parm.capture;
3359
Ladislav Michla637a112005-09-01 15:07:34 +00003360 spin_lock_irqsave(&vino_drvdata->input_lock, flags);
Ralf Baechled203a7e2005-09-06 15:19:37 -07003361
3362 if ((cp->timeperframe.numerator == 0) ||
3363 (cp->timeperframe.denominator == 0)) {
3364 /* reset framerate */
3365 vino_set_default_framerate(vcs);
3366 } else {
3367 vino_set_framerate(vcs, cp->timeperframe.denominator /
3368 cp->timeperframe.numerator);
3369 }
Ladislav Michla637a112005-09-01 15:07:34 +00003370
3371 spin_unlock_irqrestore(&vino_drvdata->input_lock, flags);
Ralf Baechled203a7e2005-09-06 15:19:37 -07003372
3373 // TODO: set buffers according to cp->readbuffers
3374 break;
3375 }
3376 case V4L2_BUF_TYPE_VIDEO_OVERLAY:
3377 default:
3378 return -EINVAL;
3379 }
3380
3381 return 0;
3382}
3383
Hans Verkuilc49cb362009-02-12 10:32:50 -03003384static int vino_reqbufs(struct file *file, void *__fh,
Ralf Baechled203a7e2005-09-06 15:19:37 -07003385 struct v4l2_requestbuffers *rb)
3386{
Hans Verkuilc49cb362009-02-12 10:32:50 -03003387 struct vino_channel_settings *vcs = video_drvdata(file);
Ralf Baechled203a7e2005-09-06 15:19:37 -07003388 if (vcs->reading)
3389 return -EBUSY;
3390
3391 switch (rb->type) {
3392 case V4L2_BUF_TYPE_VIDEO_CAPTURE: {
3393 // TODO: check queue type
3394 if (rb->memory != V4L2_MEMORY_MMAP) {
3395 dprintk("type not mmap\n");
3396 return -EINVAL;
3397 }
3398
Ralf Baechled203a7e2005-09-06 15:19:37 -07003399 dprintk("count = %d\n", rb->count);
3400 if (rb->count > 0) {
Ladislav Michla637a112005-09-01 15:07:34 +00003401 if (vino_is_capturing(vcs)) {
3402 dprintk("busy, capturing\n");
3403 return -EBUSY;
3404 }
3405
Ralf Baechled203a7e2005-09-06 15:19:37 -07003406 if (vino_queue_has_mapped_buffers(&vcs->fb_queue)) {
3407 dprintk("busy, buffers still mapped\n");
3408 return -EBUSY;
3409 } else {
Ladislav Michla637a112005-09-01 15:07:34 +00003410 vcs->streaming = 0;
Ralf Baechled203a7e2005-09-06 15:19:37 -07003411 vino_queue_free(&vcs->fb_queue);
3412 vino_queue_init(&vcs->fb_queue, &rb->count);
3413 }
3414 } else {
Ladislav Michla637a112005-09-01 15:07:34 +00003415 vcs->streaming = 0;
Ralf Baechled203a7e2005-09-06 15:19:37 -07003416 vino_capture_stop(vcs);
3417 vino_queue_free(&vcs->fb_queue);
3418 }
3419 break;
3420 }
3421 case V4L2_BUF_TYPE_VIDEO_OVERLAY:
3422 default:
3423 return -EINVAL;
3424 }
3425
3426 return 0;
3427}
3428
3429static void vino_v4l2_get_buffer_status(struct vino_channel_settings *vcs,
3430 struct vino_framebuffer *fb,
3431 struct v4l2_buffer *b)
3432{
3433 if (vino_queue_outgoing_contains(&vcs->fb_queue,
3434 fb->id)) {
3435 b->flags &= ~V4L2_BUF_FLAG_QUEUED;
3436 b->flags |= V4L2_BUF_FLAG_DONE;
3437 } else if (vino_queue_incoming_contains(&vcs->fb_queue,
3438 fb->id)) {
3439 b->flags &= ~V4L2_BUF_FLAG_DONE;
3440 b->flags |= V4L2_BUF_FLAG_QUEUED;
3441 } else {
3442 b->flags &= ~(V4L2_BUF_FLAG_DONE |
3443 V4L2_BUF_FLAG_QUEUED);
3444 }
3445
3446 b->flags &= ~(V4L2_BUF_FLAG_TIMECODE);
3447
3448 if (fb->map_count > 0)
3449 b->flags |= V4L2_BUF_FLAG_MAPPED;
3450
3451 b->index = fb->id;
3452 b->memory = (vcs->fb_queue.type == VINO_MEMORY_MMAP) ?
3453 V4L2_MEMORY_MMAP : V4L2_MEMORY_USERPTR;
3454 b->m.offset = fb->offset;
3455 b->bytesused = fb->data_size;
3456 b->length = fb->size;
3457 b->field = V4L2_FIELD_INTERLACED;
3458 b->sequence = fb->frame_counter;
3459 memcpy(&b->timestamp, &fb->timestamp,
3460 sizeof(struct timeval));
3461 // b->input ?
3462
3463 dprintk("buffer %d: length = %d, bytesused = %d, offset = %d\n",
3464 fb->id, fb->size, fb->data_size, fb->offset);
3465}
3466
Hans Verkuilc49cb362009-02-12 10:32:50 -03003467static int vino_querybuf(struct file *file, void *__fh,
Ralf Baechled203a7e2005-09-06 15:19:37 -07003468 struct v4l2_buffer *b)
3469{
Hans Verkuilc49cb362009-02-12 10:32:50 -03003470 struct vino_channel_settings *vcs = video_drvdata(file);
Ralf Baechled203a7e2005-09-06 15:19:37 -07003471 if (vcs->reading)
3472 return -EBUSY;
3473
3474 switch (b->type) {
3475 case V4L2_BUF_TYPE_VIDEO_CAPTURE: {
3476 struct vino_framebuffer *fb;
3477
3478 // TODO: check queue type
3479 if (b->index >= vino_queue_get_length(&vcs->fb_queue)) {
3480 dprintk("invalid index = %d\n",
3481 b->index);
3482 return -EINVAL;
3483 }
3484
3485 fb = vino_queue_get_buffer(&vcs->fb_queue,
3486 b->index);
3487 if (fb == NULL) {
3488 dprintk("vino_queue_get_buffer() failed");
3489 return -EINVAL;
3490 }
3491
3492 vino_v4l2_get_buffer_status(vcs, fb, b);
3493 break;
3494 }
3495 case V4L2_BUF_TYPE_VIDEO_OVERLAY:
3496 default:
3497 return -EINVAL;
3498 }
3499
3500 return 0;
3501}
3502
Hans Verkuilc49cb362009-02-12 10:32:50 -03003503static int vino_qbuf(struct file *file, void *__fh,
Ralf Baechled203a7e2005-09-06 15:19:37 -07003504 struct v4l2_buffer *b)
3505{
Hans Verkuilc49cb362009-02-12 10:32:50 -03003506 struct vino_channel_settings *vcs = video_drvdata(file);
Ralf Baechled203a7e2005-09-06 15:19:37 -07003507 if (vcs->reading)
3508 return -EBUSY;
3509
3510 switch (b->type) {
3511 case V4L2_BUF_TYPE_VIDEO_CAPTURE: {
3512 struct vino_framebuffer *fb;
3513 int ret;
3514
3515 // TODO: check queue type
3516 if (b->memory != V4L2_MEMORY_MMAP) {
3517 dprintk("type not mmap\n");
3518 return -EINVAL;
3519 }
3520
3521 fb = vino_capture_enqueue(vcs, b->index);
3522 if (fb == NULL)
3523 return -EINVAL;
3524
3525 vino_v4l2_get_buffer_status(vcs, fb, b);
3526
3527 if (vcs->streaming) {
3528 ret = vino_capture_next(vcs, 1);
3529 if (ret)
3530 return ret;
3531 }
3532 break;
3533 }
3534 case V4L2_BUF_TYPE_VIDEO_OVERLAY:
3535 default:
3536 return -EINVAL;
3537 }
3538
3539 return 0;
3540}
3541
Hans Verkuilc49cb362009-02-12 10:32:50 -03003542static int vino_dqbuf(struct file *file, void *__fh,
3543 struct v4l2_buffer *b)
Ralf Baechled203a7e2005-09-06 15:19:37 -07003544{
Hans Verkuilc49cb362009-02-12 10:32:50 -03003545 struct vino_channel_settings *vcs = video_drvdata(file);
3546 unsigned int nonblocking = file->f_flags & O_NONBLOCK;
Ralf Baechled203a7e2005-09-06 15:19:37 -07003547 if (vcs->reading)
3548 return -EBUSY;
3549
3550 switch (b->type) {
3551 case V4L2_BUF_TYPE_VIDEO_CAPTURE: {
3552 struct vino_framebuffer *fb;
3553 unsigned int incoming, outgoing;
3554 int err;
3555
3556 // TODO: check queue type
3557
3558 err = vino_queue_get_incoming(&vcs->fb_queue, &incoming);
3559 if (err) {
3560 dprintk("vino_queue_get_incoming() failed\n");
Ladislav Michla637a112005-09-01 15:07:34 +00003561 return -EINVAL;
Ralf Baechled203a7e2005-09-06 15:19:37 -07003562 }
3563 err = vino_queue_get_outgoing(&vcs->fb_queue, &outgoing);
3564 if (err) {
3565 dprintk("vino_queue_get_outgoing() failed\n");
Ladislav Michla637a112005-09-01 15:07:34 +00003566 return -EINVAL;
Ralf Baechled203a7e2005-09-06 15:19:37 -07003567 }
3568
3569 dprintk("incoming = %d, outgoing = %d\n", incoming, outgoing);
3570
3571 if (outgoing == 0) {
3572 if (incoming == 0) {
3573 dprintk("no incoming or outgoing buffers\n");
3574 return -EINVAL;
3575 }
3576 if (nonblocking) {
3577 dprintk("non-blocking I/O was selected and "
3578 "there are no buffers to dequeue\n");
3579 return -EAGAIN;
3580 }
3581
3582 err = vino_wait_for_frame(vcs);
3583 if (err) {
3584 err = vino_wait_for_frame(vcs);
3585 if (err) {
Ladislav Michla637a112005-09-01 15:07:34 +00003586 /* interrupted or
3587 * no frames captured because
3588 * of frame skipping */
3589 // vino_capture_failed(vcs);
Ralf Baechled203a7e2005-09-06 15:19:37 -07003590 return -EIO;
3591 }
3592 }
3593 }
3594
3595 fb = vino_queue_remove(&vcs->fb_queue, &b->index);
3596 if (fb == NULL) {
3597 dprintk("vino_queue_remove() failed\n");
3598 return -EINVAL;
3599 }
3600
3601 err = vino_check_buffer(vcs, fb);
Ladislav Michla637a112005-09-01 15:07:34 +00003602
3603 vino_v4l2_get_buffer_status(vcs, fb, b);
3604
Ralf Baechled203a7e2005-09-06 15:19:37 -07003605 if (err)
3606 return -EIO;
3607
Ralf Baechled203a7e2005-09-06 15:19:37 -07003608 break;
3609 }
3610 case V4L2_BUF_TYPE_VIDEO_OVERLAY:
3611 default:
3612 return -EINVAL;
3613 }
3614
3615 return 0;
3616}
3617
Hans Verkuilc49cb362009-02-12 10:32:50 -03003618static int vino_streamon(struct file *file, void *__fh,
3619 enum v4l2_buf_type i)
Ralf Baechled203a7e2005-09-06 15:19:37 -07003620{
Hans Verkuilc49cb362009-02-12 10:32:50 -03003621 struct vino_channel_settings *vcs = video_drvdata(file);
Ralf Baechled203a7e2005-09-06 15:19:37 -07003622 unsigned int incoming;
3623 int ret;
3624 if (vcs->reading)
3625 return -EBUSY;
3626
3627 if (vcs->streaming)
3628 return 0;
3629
3630 // TODO: check queue type
3631
3632 if (vino_queue_get_length(&vcs->fb_queue) < 1) {
3633 dprintk("no buffers allocated\n");
3634 return -EINVAL;
3635 }
3636
3637 ret = vino_queue_get_incoming(&vcs->fb_queue, &incoming);
3638 if (ret) {
3639 dprintk("vino_queue_get_incoming() failed\n");
3640 return -EINVAL;
3641 }
3642
3643 vcs->streaming = 1;
3644
3645 if (incoming > 0) {
3646 ret = vino_capture_next(vcs, 1);
3647 if (ret) {
3648 vcs->streaming = 0;
3649
3650 dprintk("couldn't start capture\n");
3651 return -EINVAL;
3652 }
3653 }
3654
3655 return 0;
3656}
3657
Hans Verkuilc49cb362009-02-12 10:32:50 -03003658static int vino_streamoff(struct file *file, void *__fh,
3659 enum v4l2_buf_type i)
Ralf Baechled203a7e2005-09-06 15:19:37 -07003660{
Hans Verkuilc49cb362009-02-12 10:32:50 -03003661 struct vino_channel_settings *vcs = video_drvdata(file);
Ralf Baechled203a7e2005-09-06 15:19:37 -07003662 if (vcs->reading)
3663 return -EBUSY;
3664
3665 if (!vcs->streaming)
3666 return 0;
3667
Ralf Baechled203a7e2005-09-06 15:19:37 -07003668 vcs->streaming = 0;
Ladislav Michla637a112005-09-01 15:07:34 +00003669 vino_capture_stop(vcs);
Ralf Baechled203a7e2005-09-06 15:19:37 -07003670
3671 return 0;
3672}
3673
Hans Verkuilc49cb362009-02-12 10:32:50 -03003674static int vino_queryctrl(struct file *file, void *__fh,
Ralf Baechled203a7e2005-09-06 15:19:37 -07003675 struct v4l2_queryctrl *queryctrl)
3676{
Hans Verkuilc49cb362009-02-12 10:32:50 -03003677 struct vino_channel_settings *vcs = video_drvdata(file);
Ladislav Michla637a112005-09-01 15:07:34 +00003678 unsigned long flags;
Ralf Baechled203a7e2005-09-06 15:19:37 -07003679 int i;
3680 int err = 0;
3681
Ladislav Michla637a112005-09-01 15:07:34 +00003682 spin_lock_irqsave(&vino_drvdata->input_lock, flags);
Ralf Baechled203a7e2005-09-06 15:19:37 -07003683
3684 switch (vcs->input) {
3685 case VINO_INPUT_D1:
3686 for (i = 0; i < VINO_INDYCAM_V4L2_CONTROL_COUNT; i++) {
3687 if (vino_indycam_v4l2_controls[i].id ==
3688 queryctrl->id) {
3689 memcpy(queryctrl,
3690 &vino_indycam_v4l2_controls[i],
3691 sizeof(struct v4l2_queryctrl));
Ladislav Michla637a112005-09-01 15:07:34 +00003692 queryctrl->reserved[0] = 0;
Ralf Baechled203a7e2005-09-06 15:19:37 -07003693 goto found;
3694 }
3695 }
3696
3697 err = -EINVAL;
3698 break;
3699 case VINO_INPUT_COMPOSITE:
3700 case VINO_INPUT_SVIDEO:
3701 for (i = 0; i < VINO_SAA7191_V4L2_CONTROL_COUNT; i++) {
3702 if (vino_saa7191_v4l2_controls[i].id ==
3703 queryctrl->id) {
3704 memcpy(queryctrl,
3705 &vino_saa7191_v4l2_controls[i],
3706 sizeof(struct v4l2_queryctrl));
Ladislav Michla637a112005-09-01 15:07:34 +00003707 queryctrl->reserved[0] = 0;
Ralf Baechled203a7e2005-09-06 15:19:37 -07003708 goto found;
3709 }
3710 }
3711
3712 err = -EINVAL;
3713 break;
3714 default:
3715 err = -EINVAL;
3716 }
3717
3718 found:
Ladislav Michla637a112005-09-01 15:07:34 +00003719 spin_unlock_irqrestore(&vino_drvdata->input_lock, flags);
Ralf Baechled203a7e2005-09-06 15:19:37 -07003720
3721 return err;
3722}
3723
Hans Verkuilc49cb362009-02-12 10:32:50 -03003724static int vino_g_ctrl(struct file *file, void *__fh,
Ralf Baechled203a7e2005-09-06 15:19:37 -07003725 struct v4l2_control *control)
3726{
Hans Verkuilc49cb362009-02-12 10:32:50 -03003727 struct vino_channel_settings *vcs = video_drvdata(file);
Ladislav Michla637a112005-09-01 15:07:34 +00003728 unsigned long flags;
3729 int i;
Ralf Baechled203a7e2005-09-06 15:19:37 -07003730 int err = 0;
3731
Ladislav Michla637a112005-09-01 15:07:34 +00003732 spin_lock_irqsave(&vino_drvdata->input_lock, flags);
Ralf Baechled203a7e2005-09-06 15:19:37 -07003733
3734 switch (vcs->input) {
Ladislav Michla637a112005-09-01 15:07:34 +00003735 case VINO_INPUT_D1: {
Hans Verkuilcf4e9482009-02-27 09:05:10 -03003736 err = -EINVAL;
Ladislav Michla637a112005-09-01 15:07:34 +00003737 for (i = 0; i < VINO_INDYCAM_V4L2_CONTROL_COUNT; i++) {
Hans Verkuilcf4e9482009-02-27 09:05:10 -03003738 if (vino_indycam_v4l2_controls[i].id == control->id) {
3739 err = 0;
3740 break;
Ladislav Michla637a112005-09-01 15:07:34 +00003741 }
Ralf Baechled203a7e2005-09-06 15:19:37 -07003742 }
Ladislav Michla637a112005-09-01 15:07:34 +00003743
Hans Verkuilcf4e9482009-02-27 09:05:10 -03003744 if (err)
Ladislav Michla637a112005-09-01 15:07:34 +00003745 goto out;
Ladislav Michla637a112005-09-01 15:07:34 +00003746
Hans Verkuil48f4dac2009-02-18 19:18:26 -03003747 err = camera_call(core, g_ctrl, control);
Hans Verkuilcf4e9482009-02-27 09:05:10 -03003748 if (err)
3749 err = -EINVAL;
Ralf Baechled203a7e2005-09-06 15:19:37 -07003750 break;
Ladislav Michla637a112005-09-01 15:07:34 +00003751 }
Ralf Baechled203a7e2005-09-06 15:19:37 -07003752 case VINO_INPUT_COMPOSITE:
Ladislav Michla637a112005-09-01 15:07:34 +00003753 case VINO_INPUT_SVIDEO: {
Hans Verkuilcf4e9482009-02-27 09:05:10 -03003754 err = -EINVAL;
Ladislav Michla637a112005-09-01 15:07:34 +00003755 for (i = 0; i < VINO_SAA7191_V4L2_CONTROL_COUNT; i++) {
Hans Verkuilcf4e9482009-02-27 09:05:10 -03003756 if (vino_saa7191_v4l2_controls[i].id == control->id) {
3757 err = 0;
3758 break;
Ladislav Michla637a112005-09-01 15:07:34 +00003759 }
Ralf Baechled203a7e2005-09-06 15:19:37 -07003760 }
Ladislav Michla637a112005-09-01 15:07:34 +00003761
Hans Verkuilcf4e9482009-02-27 09:05:10 -03003762 if (err)
Ladislav Michla637a112005-09-01 15:07:34 +00003763 goto out;
Ladislav Michla637a112005-09-01 15:07:34 +00003764
Hans Verkuil48f4dac2009-02-18 19:18:26 -03003765 err = decoder_call(core, g_ctrl, control);
Hans Verkuilcf4e9482009-02-27 09:05:10 -03003766 if (err)
3767 err = -EINVAL;
Ralf Baechled203a7e2005-09-06 15:19:37 -07003768 break;
Ladislav Michla637a112005-09-01 15:07:34 +00003769 }
Ralf Baechled203a7e2005-09-06 15:19:37 -07003770 default:
3771 err = -EINVAL;
3772 }
3773
Ladislav Michla637a112005-09-01 15:07:34 +00003774out:
3775 spin_unlock_irqrestore(&vino_drvdata->input_lock, flags);
Ralf Baechled203a7e2005-09-06 15:19:37 -07003776
3777 return err;
3778}
3779
Hans Verkuilc49cb362009-02-12 10:32:50 -03003780static int vino_s_ctrl(struct file *file, void *__fh,
Ralf Baechled203a7e2005-09-06 15:19:37 -07003781 struct v4l2_control *control)
3782{
Hans Verkuilc49cb362009-02-12 10:32:50 -03003783 struct vino_channel_settings *vcs = video_drvdata(file);
Ladislav Michla637a112005-09-01 15:07:34 +00003784 unsigned long flags;
Ralf Baechled203a7e2005-09-06 15:19:37 -07003785 int i;
3786 int err = 0;
3787
Ladislav Michla637a112005-09-01 15:07:34 +00003788 spin_lock_irqsave(&vino_drvdata->input_lock, flags);
3789
3790 if (!vino_is_input_owner(vcs)) {
3791 err = -EBUSY;
3792 goto out;
3793 }
Ralf Baechled203a7e2005-09-06 15:19:37 -07003794
3795 switch (vcs->input) {
Ladislav Michla637a112005-09-01 15:07:34 +00003796 case VINO_INPUT_D1: {
Hans Verkuilcf4e9482009-02-27 09:05:10 -03003797 err = -EINVAL;
Ralf Baechled203a7e2005-09-06 15:19:37 -07003798 for (i = 0; i < VINO_INDYCAM_V4L2_CONTROL_COUNT; i++) {
Hans Verkuilcf4e9482009-02-27 09:05:10 -03003799 if (vino_indycam_v4l2_controls[i].id == control->id) {
3800 err = 0;
3801 break;
Ralf Baechled203a7e2005-09-06 15:19:37 -07003802 }
3803 }
Hans Verkuilcf4e9482009-02-27 09:05:10 -03003804 if (err)
3805 goto out;
3806 if (control->value < vino_indycam_v4l2_controls[i].minimum ||
3807 control->value > vino_indycam_v4l2_controls[i].maximum) {
3808 err = -ERANGE;
3809 goto out;
3810 }
Hans Verkuil48f4dac2009-02-18 19:18:26 -03003811 err = camera_call(core, s_ctrl, control);
Ladislav Michla637a112005-09-01 15:07:34 +00003812 if (err)
3813 err = -EINVAL;
Ralf Baechled203a7e2005-09-06 15:19:37 -07003814 break;
Ladislav Michla637a112005-09-01 15:07:34 +00003815 }
Ralf Baechled203a7e2005-09-06 15:19:37 -07003816 case VINO_INPUT_COMPOSITE:
Ladislav Michla637a112005-09-01 15:07:34 +00003817 case VINO_INPUT_SVIDEO: {
Hans Verkuilcf4e9482009-02-27 09:05:10 -03003818 err = -EINVAL;
Ralf Baechled203a7e2005-09-06 15:19:37 -07003819 for (i = 0; i < VINO_SAA7191_V4L2_CONTROL_COUNT; i++) {
Hans Verkuilcf4e9482009-02-27 09:05:10 -03003820 if (vino_saa7191_v4l2_controls[i].id == control->id) {
3821 err = 0;
3822 break;
Ralf Baechled203a7e2005-09-06 15:19:37 -07003823 }
3824 }
Hans Verkuilcf4e9482009-02-27 09:05:10 -03003825 if (err)
3826 goto out;
3827 if (control->value < vino_saa7191_v4l2_controls[i].minimum ||
3828 control->value > vino_saa7191_v4l2_controls[i].maximum) {
3829 err = -ERANGE;
3830 goto out;
3831 }
Ralf Baechled203a7e2005-09-06 15:19:37 -07003832
Hans Verkuil48f4dac2009-02-18 19:18:26 -03003833 err = decoder_call(core, s_ctrl, control);
Ladislav Michla637a112005-09-01 15:07:34 +00003834 if (err)
3835 err = -EINVAL;
Ralf Baechled203a7e2005-09-06 15:19:37 -07003836 break;
Ladislav Michla637a112005-09-01 15:07:34 +00003837 }
Ralf Baechled203a7e2005-09-06 15:19:37 -07003838 default:
3839 err = -EINVAL;
3840 }
3841
Ladislav Michla637a112005-09-01 15:07:34 +00003842out:
3843 spin_unlock_irqrestore(&vino_drvdata->input_lock, flags);
Ralf Baechled203a7e2005-09-06 15:19:37 -07003844
3845 return err;
3846}
3847
3848/* File operations */
3849
Hans Verkuilbec43662008-12-30 06:58:20 -03003850static int vino_open(struct file *file)
Ralf Baechled203a7e2005-09-06 15:19:37 -07003851{
Hans Verkuilc170ecf2008-08-23 08:32:09 -03003852 struct vino_channel_settings *vcs = video_drvdata(file);
Ralf Baechled203a7e2005-09-06 15:19:37 -07003853 int ret = 0;
3854 dprintk("open(): channel = %c\n",
3855 (vcs->channel == VINO_CHANNEL_A) ? 'A' : 'B');
3856
Ingo Molnar3593cab2006-02-07 06:49:14 -02003857 mutex_lock(&vcs->mutex);
Ralf Baechled203a7e2005-09-06 15:19:37 -07003858
3859 if (vcs->users) {
3860 dprintk("open(): driver busy\n");
3861 ret = -EBUSY;
3862 goto out;
3863 }
3864
3865 ret = vino_acquire_input(vcs);
3866 if (ret) {
3867 dprintk("open(): vino_acquire_input() failed\n");
3868 goto out;
3869 }
3870
3871 vcs->users++;
3872
3873 out:
Ingo Molnar3593cab2006-02-07 06:49:14 -02003874 mutex_unlock(&vcs->mutex);
Ralf Baechled203a7e2005-09-06 15:19:37 -07003875
3876 dprintk("open(): %s!\n", ret ? "failed" : "complete");
3877
3878 return ret;
3879}
3880
Hans Verkuilbec43662008-12-30 06:58:20 -03003881static int vino_close(struct file *file)
Ralf Baechled203a7e2005-09-06 15:19:37 -07003882{
Hans Verkuilc170ecf2008-08-23 08:32:09 -03003883 struct vino_channel_settings *vcs = video_drvdata(file);
Ralf Baechled203a7e2005-09-06 15:19:37 -07003884 dprintk("close():\n");
3885
Ingo Molnar3593cab2006-02-07 06:49:14 -02003886 mutex_lock(&vcs->mutex);
Ralf Baechled203a7e2005-09-06 15:19:37 -07003887
3888 vcs->users--;
3889
3890 if (!vcs->users) {
3891 vino_release_input(vcs);
3892
3893 /* stop DMA and free buffers */
3894 vino_capture_stop(vcs);
3895 vino_queue_free(&vcs->fb_queue);
3896 }
3897
Ingo Molnar3593cab2006-02-07 06:49:14 -02003898 mutex_unlock(&vcs->mutex);
Ralf Baechled203a7e2005-09-06 15:19:37 -07003899
3900 return 0;
3901}
3902
3903static void vino_vm_open(struct vm_area_struct *vma)
3904{
3905 struct vino_framebuffer *fb = vma->vm_private_data;
3906
3907 fb->map_count++;
3908 dprintk("vino_vm_open(): count = %d\n", fb->map_count);
3909}
3910
3911static void vino_vm_close(struct vm_area_struct *vma)
3912{
3913 struct vino_framebuffer *fb = vma->vm_private_data;
3914
3915 fb->map_count--;
3916 dprintk("vino_vm_close(): count = %d\n", fb->map_count);
3917}
3918
3919static struct vm_operations_struct vino_vm_ops = {
3920 .open = vino_vm_open,
3921 .close = vino_vm_close,
3922};
3923
3924static int vino_mmap(struct file *file, struct vm_area_struct *vma)
3925{
Hans Verkuilc170ecf2008-08-23 08:32:09 -03003926 struct vino_channel_settings *vcs = video_drvdata(file);
Ralf Baechled203a7e2005-09-06 15:19:37 -07003927
3928 unsigned long start = vma->vm_start;
3929 unsigned long size = vma->vm_end - vma->vm_start;
3930 unsigned long offset = vma->vm_pgoff << PAGE_SHIFT;
3931
3932 struct vino_framebuffer *fb = NULL;
3933 unsigned int i, length;
3934 int ret = 0;
3935
3936 dprintk("mmap():\n");
3937
3938 // TODO: reject mmap if already mapped
3939
Ingo Molnar3593cab2006-02-07 06:49:14 -02003940 if (mutex_lock_interruptible(&vcs->mutex))
Ralf Baechled203a7e2005-09-06 15:19:37 -07003941 return -EINTR;
3942
3943 if (vcs->reading) {
3944 ret = -EBUSY;
3945 goto out;
3946 }
3947
3948 // TODO: check queue type
3949
3950 if (!(vma->vm_flags & VM_WRITE)) {
3951 dprintk("mmap(): app bug: PROT_WRITE please\n");
3952 ret = -EINVAL;
3953 goto out;
3954 }
3955 if (!(vma->vm_flags & VM_SHARED)) {
3956 dprintk("mmap(): app bug: MAP_SHARED please\n");
3957 ret = -EINVAL;
3958 goto out;
3959 }
3960
3961 /* find the correct buffer using offset */
3962 length = vino_queue_get_length(&vcs->fb_queue);
3963 if (length == 0) {
3964 dprintk("mmap(): queue not initialized\n");
3965 ret = -EINVAL;
3966 goto out;
3967 }
3968
3969 for (i = 0; i < length; i++) {
3970 fb = vino_queue_get_buffer(&vcs->fb_queue, i);
3971 if (fb == NULL) {
3972 dprintk("mmap(): vino_queue_get_buffer() failed\n");
3973 ret = -EINVAL;
3974 goto out;
3975 }
3976
3977 if (fb->offset == offset)
3978 goto found;
3979 }
3980
3981 dprintk("mmap(): invalid offset = %lu\n", offset);
3982 ret = -EINVAL;
3983 goto out;
3984
3985found:
3986 dprintk("mmap(): buffer = %d\n", i);
3987
3988 if (size > (fb->desc_table.page_count * PAGE_SIZE)) {
3989 dprintk("mmap(): failed: size = %lu > %lu\n",
3990 size, fb->desc_table.page_count * PAGE_SIZE);
3991 ret = -EINVAL;
3992 goto out;
3993 }
3994
3995 for (i = 0; i < fb->desc_table.page_count; i++) {
3996 unsigned long pfn =
3997 virt_to_phys((void *)fb->desc_table.virtual[i]) >>
3998 PAGE_SHIFT;
3999
4000 if (size < PAGE_SIZE)
4001 break;
4002
4003 // protection was: PAGE_READONLY
4004 if (remap_pfn_range(vma, start, pfn, PAGE_SIZE,
4005 vma->vm_page_prot)) {
4006 dprintk("mmap(): remap_pfn_range() failed\n");
4007 ret = -EAGAIN;
4008 goto out;
4009 }
4010
4011 start += PAGE_SIZE;
4012 size -= PAGE_SIZE;
4013 }
4014
4015 fb->map_count = 1;
4016
4017 vma->vm_flags |= VM_DONTEXPAND | VM_RESERVED;
4018 vma->vm_flags &= ~VM_IO;
4019 vma->vm_private_data = fb;
4020 vma->vm_file = file;
4021 vma->vm_ops = &vino_vm_ops;
4022
4023out:
Ingo Molnar3593cab2006-02-07 06:49:14 -02004024 mutex_unlock(&vcs->mutex);
Ralf Baechled203a7e2005-09-06 15:19:37 -07004025
4026 return ret;
4027}
4028
4029static unsigned int vino_poll(struct file *file, poll_table *pt)
4030{
Hans Verkuilc170ecf2008-08-23 08:32:09 -03004031 struct vino_channel_settings *vcs = video_drvdata(file);
Ralf Baechled203a7e2005-09-06 15:19:37 -07004032 unsigned int outgoing;
4033 unsigned int ret = 0;
4034
4035 // lock mutex (?)
4036 // TODO: this has to be corrected for different read modes
4037
4038 dprintk("poll():\n");
4039
4040 if (vino_queue_get_outgoing(&vcs->fb_queue, &outgoing)) {
4041 dprintk("poll(): vino_queue_get_outgoing() failed\n");
4042 ret = POLLERR;
4043 goto error;
4044 }
4045 if (outgoing > 0)
4046 goto over;
4047
4048 poll_wait(file, &vcs->fb_queue.frame_wait_queue, pt);
4049
4050 if (vino_queue_get_outgoing(&vcs->fb_queue, &outgoing)) {
4051 dprintk("poll(): vino_queue_get_outgoing() failed\n");
4052 ret = POLLERR;
4053 goto error;
4054 }
4055
4056over:
4057 dprintk("poll(): data %savailable\n",
4058 (outgoing > 0) ? "" : "not ");
Ladislav Michla637a112005-09-01 15:07:34 +00004059
4060 if (outgoing > 0)
Ralf Baechled203a7e2005-09-06 15:19:37 -07004061 ret = POLLIN | POLLRDNORM;
Ralf Baechled203a7e2005-09-06 15:19:37 -07004062
4063error:
Ralf Baechled203a7e2005-09-06 15:19:37 -07004064 return ret;
4065}
4066
Hans Verkuil069b7472008-12-30 07:04:34 -03004067static long vino_ioctl(struct file *file,
Ralf Baechled203a7e2005-09-06 15:19:37 -07004068 unsigned int cmd, unsigned long arg)
4069{
Hans Verkuilc170ecf2008-08-23 08:32:09 -03004070 struct vino_channel_settings *vcs = video_drvdata(file);
Hans Verkuil069b7472008-12-30 07:04:34 -03004071 long ret;
Ralf Baechled203a7e2005-09-06 15:19:37 -07004072
Ingo Molnar3593cab2006-02-07 06:49:14 -02004073 if (mutex_lock_interruptible(&vcs->mutex))
Ralf Baechled203a7e2005-09-06 15:19:37 -07004074 return -EINTR;
4075
Hans Verkuilc49cb362009-02-12 10:32:50 -03004076 ret = video_ioctl2(file, cmd, arg);
Ralf Baechled203a7e2005-09-06 15:19:37 -07004077
Ingo Molnar3593cab2006-02-07 06:49:14 -02004078 mutex_unlock(&vcs->mutex);
Ralf Baechled203a7e2005-09-06 15:19:37 -07004079
4080 return ret;
4081}
4082
4083/* Initialization and cleanup */
4084
Douglas Schilling Landgrafff699e62008-04-22 14:41:48 -03004085/* __initdata */
4086static int vino_init_stage;
Ralf Baechled203a7e2005-09-06 15:19:37 -07004087
Hans Verkuilc49cb362009-02-12 10:32:50 -03004088const struct v4l2_ioctl_ops vino_ioctl_ops = {
4089 .vidioc_enum_fmt_vid_cap = vino_enum_fmt_vid_cap,
4090 .vidioc_g_fmt_vid_cap = vino_g_fmt_vid_cap,
4091 .vidioc_s_fmt_vid_cap = vino_s_fmt_vid_cap,
4092 .vidioc_try_fmt_vid_cap = vino_try_fmt_vid_cap,
4093 .vidioc_querycap = vino_querycap,
4094 .vidioc_enum_input = vino_enum_input,
4095 .vidioc_g_input = vino_g_input,
4096 .vidioc_s_input = vino_s_input,
4097 .vidioc_g_std = vino_g_std,
4098 .vidioc_s_std = vino_s_std,
4099 .vidioc_querystd = vino_querystd,
4100 .vidioc_cropcap = vino_cropcap,
4101 .vidioc_s_crop = vino_s_crop,
4102 .vidioc_g_crop = vino_g_crop,
4103 .vidioc_s_parm = vino_s_parm,
4104 .vidioc_g_parm = vino_g_parm,
4105 .vidioc_reqbufs = vino_reqbufs,
4106 .vidioc_querybuf = vino_querybuf,
4107 .vidioc_qbuf = vino_qbuf,
4108 .vidioc_dqbuf = vino_dqbuf,
4109 .vidioc_streamon = vino_streamon,
4110 .vidioc_streamoff = vino_streamoff,
4111 .vidioc_queryctrl = vino_queryctrl,
4112 .vidioc_g_ctrl = vino_g_ctrl,
4113 .vidioc_s_ctrl = vino_s_ctrl,
4114};
4115
Hans Verkuilbec43662008-12-30 06:58:20 -03004116static const struct v4l2_file_operations vino_fops = {
Ralf Baechled203a7e2005-09-06 15:19:37 -07004117 .owner = THIS_MODULE,
4118 .open = vino_open,
4119 .release = vino_close,
Hans Verkuil28959632009-02-18 18:53:47 -03004120 .unlocked_ioctl = vino_ioctl,
Ralf Baechled203a7e2005-09-06 15:19:37 -07004121 .mmap = vino_mmap,
4122 .poll = vino_poll,
Ralf Baechled203a7e2005-09-06 15:19:37 -07004123};
4124
Hans Verkuil0ef4dba2009-02-12 11:31:13 -03004125static struct video_device vdev_template = {
Ralf Baechled203a7e2005-09-06 15:19:37 -07004126 .name = "NOT SET",
Ralf Baechled203a7e2005-09-06 15:19:37 -07004127 .fops = &vino_fops,
Hans Verkuilc49cb362009-02-12 10:32:50 -03004128 .ioctl_ops = &vino_ioctl_ops,
4129 .tvnorms = V4L2_STD_NTSC | V4L2_STD_PAL | V4L2_STD_SECAM,
Ralf Baechled203a7e2005-09-06 15:19:37 -07004130 .minor = -1,
4131};
4132
4133static void vino_module_cleanup(int stage)
4134{
4135 switch(stage) {
Hans Verkuil28959632009-02-18 18:53:47 -03004136 case 11:
Hans Verkuil0ef4dba2009-02-12 11:31:13 -03004137 video_unregister_device(vino_drvdata->b.vdev);
4138 vino_drvdata->b.vdev = NULL;
Hans Verkuil28959632009-02-18 18:53:47 -03004139 case 10:
Hans Verkuil0ef4dba2009-02-12 11:31:13 -03004140 video_unregister_device(vino_drvdata->a.vdev);
4141 vino_drvdata->a.vdev = NULL;
Hans Verkuil28959632009-02-18 18:53:47 -03004142 case 9:
Jean Delvarecea0c682009-03-06 12:05:43 -03004143 i2c_del_adapter(&vino_i2c_adapter);
Hans Verkuil28959632009-02-18 18:53:47 -03004144 case 8:
Ralf Baechled203a7e2005-09-06 15:19:37 -07004145 free_irq(SGI_VINO_IRQ, NULL);
Hans Verkuil28959632009-02-18 18:53:47 -03004146 case 7:
Hans Verkuil0ef4dba2009-02-12 11:31:13 -03004147 if (vino_drvdata->b.vdev) {
4148 video_device_release(vino_drvdata->b.vdev);
4149 vino_drvdata->b.vdev = NULL;
Ralf Baechled203a7e2005-09-06 15:19:37 -07004150 }
Hans Verkuil28959632009-02-18 18:53:47 -03004151 case 6:
Hans Verkuil0ef4dba2009-02-12 11:31:13 -03004152 if (vino_drvdata->a.vdev) {
4153 video_device_release(vino_drvdata->a.vdev);
4154 vino_drvdata->a.vdev = NULL;
Ralf Baechled203a7e2005-09-06 15:19:37 -07004155 }
Hans Verkuil28959632009-02-18 18:53:47 -03004156 case 5:
Ralf Baechled203a7e2005-09-06 15:19:37 -07004157 /* all entries in dma_cpu dummy table have the same address */
4158 dma_unmap_single(NULL,
4159 vino_drvdata->dummy_desc_table.dma_cpu[0],
4160 PAGE_SIZE, DMA_FROM_DEVICE);
4161 dma_free_coherent(NULL, VINO_DUMMY_DESC_COUNT
4162 * sizeof(dma_addr_t),
4163 (void *)vino_drvdata->
4164 dummy_desc_table.dma_cpu,
4165 vino_drvdata->dummy_desc_table.dma);
Hans Verkuil28959632009-02-18 18:53:47 -03004166 case 4:
Ralf Baechled203a7e2005-09-06 15:19:37 -07004167 free_page(vino_drvdata->dummy_page);
Hans Verkuil28959632009-02-18 18:53:47 -03004168 case 3:
4169 v4l2_device_unregister(&vino_drvdata->v4l2_dev);
Ralf Baechled203a7e2005-09-06 15:19:37 -07004170 case 2:
4171 kfree(vino_drvdata);
4172 case 1:
4173 iounmap(vino);
4174 case 0:
4175 break;
4176 default:
4177 dprintk("vino_module_cleanup(): invalid cleanup stage = %d\n",
4178 stage);
4179 }
4180}
4181
4182static int vino_probe(void)
4183{
4184 unsigned long rev_id;
4185
4186 if (ip22_is_fullhouse()) {
4187 printk(KERN_ERR "VINO doesn't exist in IP22 Fullhouse\n");
4188 return -ENODEV;
4189 }
4190
4191 if (!(sgimc->systemid & SGIMC_SYSID_EPRESENT)) {
4192 printk(KERN_ERR "VINO is not found (EISA BUS not present)\n");
4193 return -ENODEV;
4194 }
4195
4196 vino = (struct sgi_vino *)ioremap(VINO_BASE, sizeof(struct sgi_vino));
4197 if (!vino) {
4198 printk(KERN_ERR "VINO: ioremap() failed\n");
4199 return -EIO;
4200 }
4201 vino_init_stage++;
4202
4203 if (get_dbe(rev_id, &(vino->rev_id))) {
4204 printk(KERN_ERR "Failed to read VINO revision register\n");
4205 vino_module_cleanup(vino_init_stage);
4206 return -ENODEV;
4207 }
4208
4209 if (VINO_ID_VALUE(rev_id) != VINO_CHIP_ID) {
4210 printk(KERN_ERR "Unknown VINO chip ID (Rev/ID: 0x%02lx)\n",
4211 rev_id);
4212 vino_module_cleanup(vino_init_stage);
4213 return -ENODEV;
4214 }
4215
Ladislav Michla637a112005-09-01 15:07:34 +00004216 printk(KERN_INFO "VINO revision %ld found\n", VINO_REV_NUM(rev_id));
Ralf Baechled203a7e2005-09-06 15:19:37 -07004217
4218 return 0;
4219}
4220
4221static int vino_init(void)
4222{
4223 dma_addr_t dma_dummy_address;
Hans Verkuil28959632009-02-18 18:53:47 -03004224 int err;
Ralf Baechled203a7e2005-09-06 15:19:37 -07004225 int i;
4226
Panagiotis Issaris74081872006-01-11 19:40:56 -02004227 vino_drvdata = kzalloc(sizeof(struct vino_settings), GFP_KERNEL);
Ralf Baechled203a7e2005-09-06 15:19:37 -07004228 if (!vino_drvdata) {
4229 vino_module_cleanup(vino_init_stage);
4230 return -ENOMEM;
4231 }
Ralf Baechled203a7e2005-09-06 15:19:37 -07004232 vino_init_stage++;
Hans Verkuil28959632009-02-18 18:53:47 -03004233 strlcpy(vino_drvdata->v4l2_dev.name, "vino",
4234 sizeof(vino_drvdata->v4l2_dev.name));
4235 err = v4l2_device_register(NULL, &vino_drvdata->v4l2_dev);
4236 if (err)
4237 return err;
4238 vino_init_stage++;
Ralf Baechled203a7e2005-09-06 15:19:37 -07004239
4240 /* create a dummy dma descriptor */
4241 vino_drvdata->dummy_page = get_zeroed_page(GFP_KERNEL | GFP_DMA);
4242 if (!vino_drvdata->dummy_page) {
4243 vino_module_cleanup(vino_init_stage);
4244 return -ENOMEM;
4245 }
4246 vino_init_stage++;
4247
4248 // TODO: use page_count in dummy_desc_table
4249
4250 vino_drvdata->dummy_desc_table.dma_cpu =
4251 dma_alloc_coherent(NULL,
4252 VINO_DUMMY_DESC_COUNT * sizeof(dma_addr_t),
4253 &vino_drvdata->dummy_desc_table.dma,
4254 GFP_KERNEL | GFP_DMA);
4255 if (!vino_drvdata->dummy_desc_table.dma_cpu) {
4256 vino_module_cleanup(vino_init_stage);
4257 return -ENOMEM;
4258 }
4259 vino_init_stage++;
4260
4261 dma_dummy_address = dma_map_single(NULL,
4262 (void *)vino_drvdata->dummy_page,
4263 PAGE_SIZE, DMA_FROM_DEVICE);
4264 for (i = 0; i < VINO_DUMMY_DESC_COUNT; i++) {
4265 vino_drvdata->dummy_desc_table.dma_cpu[i] = dma_dummy_address;
4266 }
4267
4268 /* initialize VINO */
4269
4270 vino->control = 0;
4271 vino->a.next_4_desc = vino_drvdata->dummy_desc_table.dma;
4272 vino->b.next_4_desc = vino_drvdata->dummy_desc_table.dma;
4273 udelay(VINO_DESC_FETCH_DELAY);
4274
4275 vino->intr_status = 0;
4276
4277 vino->a.fifo_thres = VINO_FIFO_THRESHOLD_DEFAULT;
4278 vino->b.fifo_thres = VINO_FIFO_THRESHOLD_DEFAULT;
4279
4280 return 0;
4281}
4282
4283static int vino_init_channel_settings(struct vino_channel_settings *vcs,
4284 unsigned int channel, const char *name)
4285{
4286 vcs->channel = channel;
4287 vcs->input = VINO_INPUT_NONE;
4288 vcs->alpha = 0;
4289 vcs->users = 0;
4290 vcs->data_format = VINO_DATA_FMT_GREY;
4291 vcs->data_norm = VINO_DATA_NORM_NTSC;
4292 vcs->decimation = 1;
4293 vino_set_default_clipping(vcs);
4294 vino_set_default_framerate(vcs);
4295
4296 vcs->capturing = 0;
4297
Ingo Molnar3593cab2006-02-07 06:49:14 -02004298 mutex_init(&vcs->mutex);
Ralf Baechled203a7e2005-09-06 15:19:37 -07004299 spin_lock_init(&vcs->capture_lock);
4300
Ingo Molnar3593cab2006-02-07 06:49:14 -02004301 mutex_init(&vcs->fb_queue.queue_mutex);
Ralf Baechled203a7e2005-09-06 15:19:37 -07004302 spin_lock_init(&vcs->fb_queue.queue_lock);
4303 init_waitqueue_head(&vcs->fb_queue.frame_wait_queue);
4304
Hans Verkuil0ef4dba2009-02-12 11:31:13 -03004305 vcs->vdev = video_device_alloc();
4306 if (!vcs->vdev) {
Ralf Baechled203a7e2005-09-06 15:19:37 -07004307 vino_module_cleanup(vino_init_stage);
4308 return -ENOMEM;
4309 }
4310 vino_init_stage++;
4311
Hans Verkuil0ef4dba2009-02-12 11:31:13 -03004312 memcpy(vcs->vdev, &vdev_template,
Ralf Baechled203a7e2005-09-06 15:19:37 -07004313 sizeof(struct video_device));
Hans Verkuil0ef4dba2009-02-12 11:31:13 -03004314 strcpy(vcs->vdev->name, name);
4315 vcs->vdev->release = video_device_release;
Hans Verkuil28959632009-02-18 18:53:47 -03004316 vcs->vdev->v4l2_dev = &vino_drvdata->v4l2_dev;
Ralf Baechled203a7e2005-09-06 15:19:37 -07004317
Hans Verkuil0ef4dba2009-02-12 11:31:13 -03004318 video_set_drvdata(vcs->vdev, vcs);
Ralf Baechled203a7e2005-09-06 15:19:37 -07004319
4320 return 0;
4321}
4322
4323static int __init vino_module_init(void)
4324{
Hans Verkuil48f4dac2009-02-18 19:18:26 -03004325 unsigned short addr[] = { 0, I2C_CLIENT_END };
Ralf Baechled203a7e2005-09-06 15:19:37 -07004326 int ret;
4327
4328 printk(KERN_INFO "SGI VINO driver version %s\n",
4329 VINO_MODULE_VERSION);
4330
4331 ret = vino_probe();
4332 if (ret)
4333 return ret;
4334
4335 ret = vino_init();
4336 if (ret)
4337 return ret;
4338
4339 /* initialize data structures */
4340
4341 spin_lock_init(&vino_drvdata->vino_lock);
4342 spin_lock_init(&vino_drvdata->input_lock);
4343
4344 ret = vino_init_channel_settings(&vino_drvdata->a, VINO_CHANNEL_A,
Hans Verkuil0ef4dba2009-02-12 11:31:13 -03004345 vino_vdev_name_a);
Ralf Baechled203a7e2005-09-06 15:19:37 -07004346 if (ret)
4347 return ret;
4348
4349 ret = vino_init_channel_settings(&vino_drvdata->b, VINO_CHANNEL_B,
Hans Verkuil0ef4dba2009-02-12 11:31:13 -03004350 vino_vdev_name_b);
Ralf Baechled203a7e2005-09-06 15:19:37 -07004351 if (ret)
4352 return ret;
4353
4354 /* initialize hardware and register V4L devices */
4355
4356 ret = request_irq(SGI_VINO_IRQ, vino_interrupt, 0,
4357 vino_driver_description, NULL);
4358 if (ret) {
4359 printk(KERN_ERR "VINO: requesting IRQ %02d failed\n",
4360 SGI_VINO_IRQ);
4361 vino_module_cleanup(vino_init_stage);
4362 return -EAGAIN;
4363 }
4364 vino_init_stage++;
4365
Jean Delvarecea0c682009-03-06 12:05:43 -03004366 ret = i2c_add_adapter(&vino_i2c_adapter);
Ralf Baechled203a7e2005-09-06 15:19:37 -07004367 if (ret) {
4368 printk(KERN_ERR "VINO I2C bus registration failed\n");
4369 vino_module_cleanup(vino_init_stage);
4370 return ret;
4371 }
Hans Verkuil28959632009-02-18 18:53:47 -03004372 i2c_set_adapdata(&vino_i2c_adapter, &vino_drvdata->v4l2_dev);
Ralf Baechled203a7e2005-09-06 15:19:37 -07004373 vino_init_stage++;
4374
Hans Verkuil0ef4dba2009-02-12 11:31:13 -03004375 ret = video_register_device(vino_drvdata->a.vdev,
Ralf Baechled203a7e2005-09-06 15:19:37 -07004376 VFL_TYPE_GRABBER, -1);
4377 if (ret < 0) {
4378 printk(KERN_ERR "VINO channel A Video4Linux-device "
4379 "registration failed\n");
4380 vino_module_cleanup(vino_init_stage);
4381 return -EINVAL;
4382 }
4383 vino_init_stage++;
4384
Hans Verkuil0ef4dba2009-02-12 11:31:13 -03004385 ret = video_register_device(vino_drvdata->b.vdev,
Ralf Baechled203a7e2005-09-06 15:19:37 -07004386 VFL_TYPE_GRABBER, -1);
4387 if (ret < 0) {
4388 printk(KERN_ERR "VINO channel B Video4Linux-device "
4389 "registration failed\n");
4390 vino_module_cleanup(vino_init_stage);
4391 return -EINVAL;
4392 }
4393 vino_init_stage++;
4394
Hans Verkuil48f4dac2009-02-18 19:18:26 -03004395 addr[0] = 0x45;
4396 vino_drvdata->decoder = v4l2_i2c_new_probed_subdev(&vino_i2c_adapter,
4397 "saa7191", "saa7191", addr);
4398 addr[0] = 0x2b;
4399 vino_drvdata->camera = v4l2_i2c_new_probed_subdev(&vino_i2c_adapter,
4400 "indycam", "indycam", addr);
Ralf Baechled203a7e2005-09-06 15:19:37 -07004401
4402 dprintk("init complete!\n");
4403
4404 return 0;
4405}
4406
4407static void __exit vino_module_exit(void)
4408{
4409 dprintk("exiting, stage = %d ...\n", vino_init_stage);
4410 vino_module_cleanup(vino_init_stage);
4411 dprintk("cleanup complete, exit!\n");
4412}
4413
4414module_init(vino_module_init);
4415module_exit(vino_module_exit);