blob: 96ce68a3dd9553cf6cf20afff6ec192c1f4b78d4 [file] [log] [blame]
Linus Torvalds1da177e2005-04-16 15:20:36 -07001/*
Ralf Baechled203a7e2005-09-06 15:19:37 -07002 * Driver for the VINO (Video In No Out) system found in SGI Indys.
Linus Torvalds1da177e2005-04-16 15:20:36 -07003 *
4 * This file is subject to the terms and conditions of the GNU General Public
5 * License version 2 as published by the Free Software Foundation.
6 *
Ralf Baechled203a7e2005-09-06 15:19:37 -07007 * Copyright (C) 2004,2005 Mikael Nousiainen <tmnousia@cc.hut.fi>
8 *
9 * Based on the previous version of the driver for 2.4 kernels by:
Linus Torvalds1da177e2005-04-16 15:20:36 -070010 * Copyright (C) 2003 Ladislav Michl <ladis@linux-mips.org>
11 */
12
Ralf Baechled203a7e2005-09-06 15:19:37 -070013/*
14 * TODO:
Ladislav Michla637a112005-09-01 15:07:34 +000015 * - remove "mark pages reserved-hacks" from memory allocation code
Nick Piggin3c18ddd2008-04-28 02:12:10 -070016 * and implement fault()
Ralf Baechled203a7e2005-09-06 15:19:37 -070017 * - check decimation, calculating and reporting image size when
18 * using decimation
Ladislav Michla637a112005-09-01 15:07:34 +000019 * - implement read(), user mode buffers and overlay (?)
Ralf Baechled203a7e2005-09-06 15:19:37 -070020 */
21
Linus Torvalds1da177e2005-04-16 15:20:36 -070022#include <linux/init.h>
Ralf Baechled203a7e2005-09-06 15:19:37 -070023#include <linux/module.h>
Linus Torvalds1da177e2005-04-16 15:20:36 -070024#include <linux/delay.h>
Ladislav Michl495515b2005-09-23 10:52:27 +000025#include <linux/dma-mapping.h>
Ralf Baechled203a7e2005-09-06 15:19:37 -070026#include <linux/errno.h>
27#include <linux/fs.h>
Ladislav Michl495515b2005-09-23 10:52:27 +000028#include <linux/interrupt.h>
Ralf Baechled203a7e2005-09-06 15:19:37 -070029#include <linux/kernel.h>
30#include <linux/mm.h>
Ladislav Michl495515b2005-09-23 10:52:27 +000031#include <linux/time.h>
32#include <linux/version.h>
Ralf Baechled203a7e2005-09-06 15:19:37 -070033#include <linux/kmod.h>
Ralf Baechled203a7e2005-09-06 15:19:37 -070034
Linus Torvalds1da177e2005-04-16 15:20:36 -070035#include <linux/i2c.h>
36#include <linux/i2c-algo-sgi.h>
37
Hans Verkuil33b687c2008-07-25 05:32:50 -030038#include <linux/videodev2.h>
Hans Verkuil28959632009-02-18 18:53:47 -030039#include <media/v4l2-device.h>
Yoichi Yuasac2cfcf72008-07-29 05:30:58 -030040#include <media/v4l2-ioctl.h>
Ingo Molnar3593cab2006-02-07 06:49:14 -020041#include <linux/mutex.h>
Ralf Baechled203a7e2005-09-06 15:19:37 -070042
Linus Torvalds1da177e2005-04-16 15:20:36 -070043#include <asm/paccess.h>
44#include <asm/io.h>
45#include <asm/sgi/ip22.h>
Linus Torvalds1da177e2005-04-16 15:20:36 -070046#include <asm/sgi/mc.h>
47
48#include "vino.h"
Ralf Baechled203a7e2005-09-06 15:19:37 -070049#include "saa7191.h"
50#include "indycam.h"
Linus Torvalds1da177e2005-04-16 15:20:36 -070051
Ralf Baechled203a7e2005-09-06 15:19:37 -070052/* Uncomment the following line to get lots and lots of (mostly useless)
53 * debug info.
54 * Note that the debug output also slows down the driver significantly */
55// #define VINO_DEBUG
Ladislav Michla637a112005-09-01 15:07:34 +000056// #define VINO_DEBUG_INT
Ralf Baechled203a7e2005-09-06 15:19:37 -070057
Ladislav Michla637a112005-09-01 15:07:34 +000058#define VINO_MODULE_VERSION "0.0.5"
59#define VINO_VERSION_CODE KERNEL_VERSION(0, 0, 5)
Ralf Baechled203a7e2005-09-06 15:19:37 -070060
61MODULE_DESCRIPTION("SGI VINO Video4Linux2 driver");
62MODULE_VERSION(VINO_MODULE_VERSION);
63MODULE_AUTHOR("Mikael Nousiainen <tmnousia@cc.hut.fi>");
64MODULE_LICENSE("GPL");
65
Ralf Baechled203a7e2005-09-06 15:19:37 -070066#ifdef VINO_DEBUG
67#define dprintk(x...) printk("VINO: " x);
Linus Torvalds1da177e2005-04-16 15:20:36 -070068#else
Ralf Baechled203a7e2005-09-06 15:19:37 -070069#define dprintk(x...)
Linus Torvalds1da177e2005-04-16 15:20:36 -070070#endif
71
Ralf Baechled203a7e2005-09-06 15:19:37 -070072#define VINO_NO_CHANNEL 0
73#define VINO_CHANNEL_A 1
74#define VINO_CHANNEL_B 2
Linus Torvalds1da177e2005-04-16 15:20:36 -070075
Ralf Baechled203a7e2005-09-06 15:19:37 -070076#define VINO_PAL_WIDTH 768
77#define VINO_PAL_HEIGHT 576
78#define VINO_NTSC_WIDTH 640
79#define VINO_NTSC_HEIGHT 480
Linus Torvalds1da177e2005-04-16 15:20:36 -070080
Ralf Baechled203a7e2005-09-06 15:19:37 -070081#define VINO_MIN_WIDTH 32
82#define VINO_MIN_HEIGHT 32
Linus Torvalds1da177e2005-04-16 15:20:36 -070083
Ralf Baechled203a7e2005-09-06 15:19:37 -070084#define VINO_CLIPPING_START_ODD_D1 1
Ladislav Michla637a112005-09-01 15:07:34 +000085#define VINO_CLIPPING_START_ODD_PAL 15
86#define VINO_CLIPPING_START_ODD_NTSC 12
Ralf Baechled203a7e2005-09-06 15:19:37 -070087
88#define VINO_CLIPPING_START_EVEN_D1 2
Ladislav Michla637a112005-09-01 15:07:34 +000089#define VINO_CLIPPING_START_EVEN_PAL 15
90#define VINO_CLIPPING_START_EVEN_NTSC 12
Ralf Baechled203a7e2005-09-06 15:19:37 -070091
92#define VINO_INPUT_CHANNEL_COUNT 3
93
Ladislav Michla637a112005-09-01 15:07:34 +000094/* the number is the index for vino_inputs */
Ralf Baechled203a7e2005-09-06 15:19:37 -070095#define VINO_INPUT_NONE -1
96#define VINO_INPUT_COMPOSITE 0
97#define VINO_INPUT_SVIDEO 1
98#define VINO_INPUT_D1 2
99
100#define VINO_PAGE_RATIO (PAGE_SIZE / VINO_PAGE_SIZE)
101
Ladislav Michla637a112005-09-01 15:07:34 +0000102#define VINO_FIFO_THRESHOLD_DEFAULT 16
Ralf Baechled203a7e2005-09-06 15:19:37 -0700103
Ralf Baechled203a7e2005-09-06 15:19:37 -0700104#define VINO_FRAMEBUFFER_SIZE ((VINO_PAL_WIDTH \
105 * VINO_PAL_HEIGHT * 4 \
106 + 3 * PAGE_SIZE) & ~(PAGE_SIZE - 1))
107
Ladislav Michla637a112005-09-01 15:07:34 +0000108#define VINO_FRAMEBUFFER_COUNT_MAX 8
Ralf Baechled203a7e2005-09-06 15:19:37 -0700109
110#define VINO_FRAMEBUFFER_UNUSED 0
111#define VINO_FRAMEBUFFER_IN_USE 1
112#define VINO_FRAMEBUFFER_READY 2
113
114#define VINO_QUEUE_ERROR -1
115#define VINO_QUEUE_MAGIC 0x20050125
116
117#define VINO_MEMORY_NONE 0
118#define VINO_MEMORY_MMAP 1
119#define VINO_MEMORY_USERPTR 2
120
121#define VINO_DUMMY_DESC_COUNT 4
122#define VINO_DESC_FETCH_DELAY 5 /* microseconds */
123
Ladislav Michla637a112005-09-01 15:07:34 +0000124#define VINO_MAX_FRAME_SKIP_COUNT 128
125
Ralf Baechled203a7e2005-09-06 15:19:37 -0700126/* the number is the index for vino_data_formats */
127#define VINO_DATA_FMT_NONE -1
128#define VINO_DATA_FMT_GREY 0
129#define VINO_DATA_FMT_RGB332 1
130#define VINO_DATA_FMT_RGB32 2
131#define VINO_DATA_FMT_YUV 3
Ralf Baechled203a7e2005-09-06 15:19:37 -0700132
133#define VINO_DATA_FMT_COUNT 4
134
Ladislav Michla637a112005-09-01 15:07:34 +0000135/* the number is the index for vino_data_norms */
Ralf Baechled203a7e2005-09-06 15:19:37 -0700136#define VINO_DATA_NORM_NONE -1
137#define VINO_DATA_NORM_NTSC 0
138#define VINO_DATA_NORM_PAL 1
139#define VINO_DATA_NORM_SECAM 2
140#define VINO_DATA_NORM_D1 3
Ralf Baechled203a7e2005-09-06 15:19:37 -0700141
142#define VINO_DATA_NORM_COUNT 4
143
144/* Internal data structure definitions */
145
146struct vino_input {
147 char *name;
148 v4l2_std_id std;
149};
150
151struct vino_clipping {
152 unsigned int left, right, top, bottom;
153};
154
155struct vino_data_format {
156 /* the description */
157 char *description;
158 /* bytes per pixel */
159 unsigned int bpp;
160 /* V4L2 fourcc code */
161 __u32 pixelformat;
162 /* V4L2 colorspace (duh!) */
163 enum v4l2_colorspace colorspace;
164};
165
166struct vino_data_norm {
167 char *description;
168 unsigned int width, height;
169 struct vino_clipping odd;
170 struct vino_clipping even;
171
172 v4l2_std_id std;
173 unsigned int fps_min, fps_max;
174 __u32 framelines;
175};
176
177struct vino_descriptor_table {
178 /* the number of PAGE_SIZE sized pages in the buffer */
179 unsigned int page_count;
180 /* virtual (kmalloc'd) pointers to the actual data
181 * (in PAGE_SIZE chunks, used with mmap streaming) */
182 unsigned long *virtual;
183
184 /* cpu address for the VINO descriptor table
185 * (contains DMA addresses, VINO_PAGE_SIZE chunks) */
186 unsigned long *dma_cpu;
187 /* dma address for the VINO descriptor table
188 * (contains DMA addresses, VINO_PAGE_SIZE chunks) */
189 dma_addr_t dma;
190};
191
192struct vino_framebuffer {
193 /* identifier nubmer */
194 unsigned int id;
195 /* the length of the whole buffer */
196 unsigned int size;
197 /* the length of actual data in buffer */
198 unsigned int data_size;
199 /* the data format */
200 unsigned int data_format;
201 /* the state of buffer data */
202 unsigned int state;
203 /* is the buffer mapped in user space? */
204 unsigned int map_count;
205 /* memory offset for mmap() */
206 unsigned int offset;
207 /* frame counter */
208 unsigned int frame_counter;
209 /* timestamp (written when image capture finishes) */
210 struct timeval timestamp;
211
212 struct vino_descriptor_table desc_table;
213
214 spinlock_t state_lock;
215};
216
217struct vino_framebuffer_fifo {
218 unsigned int length;
219
220 unsigned int used;
221 unsigned int head;
222 unsigned int tail;
223
Ladislav Michla637a112005-09-01 15:07:34 +0000224 unsigned int data[VINO_FRAMEBUFFER_COUNT_MAX];
Ralf Baechled203a7e2005-09-06 15:19:37 -0700225};
226
227struct vino_framebuffer_queue {
228 unsigned int magic;
229
230 /* VINO_MEMORY_NONE, VINO_MEMORY_MMAP or VINO_MEMORY_USERPTR */
231 unsigned int type;
232 unsigned int length;
233
234 /* data field of in and out contain index numbers for buffer */
235 struct vino_framebuffer_fifo in;
236 struct vino_framebuffer_fifo out;
237
Ladislav Michla637a112005-09-01 15:07:34 +0000238 struct vino_framebuffer *buffer[VINO_FRAMEBUFFER_COUNT_MAX];
Ralf Baechled203a7e2005-09-06 15:19:37 -0700239
240 spinlock_t queue_lock;
Ingo Molnar3593cab2006-02-07 06:49:14 -0200241 struct mutex queue_mutex;
Ralf Baechled203a7e2005-09-06 15:19:37 -0700242 wait_queue_head_t frame_wait_queue;
243};
244
Ladislav Michla637a112005-09-01 15:07:34 +0000245struct vino_interrupt_data {
246 struct timeval timestamp;
247 unsigned int frame_counter;
248 unsigned int skip_count;
249 unsigned int skip;
250};
251
Ralf Baechled203a7e2005-09-06 15:19:37 -0700252struct vino_channel_settings {
253 unsigned int channel;
254
255 int input;
256 unsigned int data_format;
257 unsigned int data_norm;
258 struct vino_clipping clipping;
259 unsigned int decimation;
260 unsigned int line_size;
261 unsigned int alpha;
262 unsigned int fps;
263 unsigned int framert_reg;
264
265 unsigned int fifo_threshold;
266
267 struct vino_framebuffer_queue fb_queue;
268
269 /* number of the current field */
270 unsigned int field;
271
272 /* read in progress */
273 int reading;
274 /* streaming is active */
275 int streaming;
276 /* the driver is currently processing the queue */
277 int capturing;
278
Ingo Molnar3593cab2006-02-07 06:49:14 -0200279 struct mutex mutex;
Ralf Baechled203a7e2005-09-06 15:19:37 -0700280 spinlock_t capture_lock;
281
282 unsigned int users;
283
Ladislav Michla637a112005-09-01 15:07:34 +0000284 struct vino_interrupt_data int_data;
285
Ralf Baechled203a7e2005-09-06 15:19:37 -0700286 /* V4L support */
Hans Verkuil0ef4dba2009-02-12 11:31:13 -0300287 struct video_device *vdev;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700288};
289
Ralf Baechled203a7e2005-09-06 15:19:37 -0700290struct vino_settings {
Hans Verkuil28959632009-02-18 18:53:47 -0300291 struct v4l2_device v4l2_dev;
Ralf Baechled203a7e2005-09-06 15:19:37 -0700292 struct vino_channel_settings a;
293 struct vino_channel_settings b;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700294
Hans Verkuil48f4dac2009-02-18 19:18:26 -0300295 /* the channel which owns this client:
296 * VINO_NO_CHANNEL, VINO_CHANNEL_A or VINO_CHANNEL_B */
297 unsigned int decoder_owner;
298 struct v4l2_subdev *decoder;
299 unsigned int camera_owner;
300 struct v4l2_subdev *camera;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700301
Ralf Baechled203a7e2005-09-06 15:19:37 -0700302 /* a lock for vino register access */
303 spinlock_t vino_lock;
304 /* a lock for channel input changes */
305 spinlock_t input_lock;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700306
Linus Torvalds1da177e2005-04-16 15:20:36 -0700307 unsigned long dummy_page;
Ralf Baechled203a7e2005-09-06 15:19:37 -0700308 struct vino_descriptor_table dummy_desc_table;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700309};
310
Ralf Baechled203a7e2005-09-06 15:19:37 -0700311/* Module parameters */
312
313/*
Ladislav Michla637a112005-09-01 15:07:34 +0000314 * Using vino_pixel_conversion the ABGR32-format pixels supplied
Ralf Baechled203a7e2005-09-06 15:19:37 -0700315 * by the VINO chip can be converted to more common formats
316 * like RGBA32 (or probably RGB24 in the future). This way we
317 * can give out data that can be specified correctly with
318 * the V4L2-definitions.
319 *
320 * The pixel format is specified as RGBA32 when no conversion
321 * is used.
322 *
323 * Note that this only affects the 32-bit bit depth.
324 *
325 * Use non-zero value to enable conversion.
326 */
Douglas Schilling Landgrafff699e62008-04-22 14:41:48 -0300327static int vino_pixel_conversion;
Ladislav Michla637a112005-09-01 15:07:34 +0000328
Ralf Baechled203a7e2005-09-06 15:19:37 -0700329module_param_named(pixelconv, vino_pixel_conversion, int, 0);
Ladislav Michla637a112005-09-01 15:07:34 +0000330
Ralf Baechled203a7e2005-09-06 15:19:37 -0700331MODULE_PARM_DESC(pixelconv,
332 "enable pixel conversion (non-zero value enables)");
333
334/* Internal data structures */
335
336static struct sgi_vino *vino;
337
338static struct vino_settings *vino_drvdata;
339
Hans Verkuil48f4dac2009-02-18 19:18:26 -0300340#define camera_call(o, f, args...) \
341 v4l2_subdev_call(vino_drvdata->camera, o, f, ##args)
342#define decoder_call(o, f, args...) \
343 v4l2_subdev_call(vino_drvdata->decoder, o, f, ##args)
344
Ralf Baechled203a7e2005-09-06 15:19:37 -0700345static const char *vino_driver_name = "vino";
346static const char *vino_driver_description = "SGI VINO";
347static const char *vino_bus_name = "GIO64 bus";
Hans Verkuil0ef4dba2009-02-12 11:31:13 -0300348static const char *vino_vdev_name_a = "SGI VINO Channel A";
349static const char *vino_vdev_name_b = "SGI VINO Channel B";
Ralf Baechled203a7e2005-09-06 15:19:37 -0700350
Ladislav Michla637a112005-09-01 15:07:34 +0000351static void vino_capture_tasklet(unsigned long channel);
352
353DECLARE_TASKLET(vino_tasklet_a, vino_capture_tasklet, VINO_CHANNEL_A);
354DECLARE_TASKLET(vino_tasklet_b, vino_capture_tasklet, VINO_CHANNEL_B);
355
Ralf Baechled203a7e2005-09-06 15:19:37 -0700356static const struct vino_input vino_inputs[] = {
357 {
358 .name = "Composite",
Ladislav Michla637a112005-09-01 15:07:34 +0000359 .std = V4L2_STD_NTSC | V4L2_STD_PAL
360 | V4L2_STD_SECAM,
Hans Verkuilcf4e9482009-02-27 09:05:10 -0300361 }, {
Ralf Baechled203a7e2005-09-06 15:19:37 -0700362 .name = "S-Video",
Ladislav Michla637a112005-09-01 15:07:34 +0000363 .std = V4L2_STD_NTSC | V4L2_STD_PAL
364 | V4L2_STD_SECAM,
Hans Verkuilcf4e9482009-02-27 09:05:10 -0300365 }, {
Ladislav Michla637a112005-09-01 15:07:34 +0000366 .name = "D1/IndyCam",
Ralf Baechled203a7e2005-09-06 15:19:37 -0700367 .std = V4L2_STD_NTSC,
368 }
369};
370
371static const struct vino_data_format vino_data_formats[] = {
372 {
373 .description = "8-bit greyscale",
374 .bpp = 1,
375 .pixelformat = V4L2_PIX_FMT_GREY,
376 .colorspace = V4L2_COLORSPACE_SMPTE170M,
Hans Verkuilcf4e9482009-02-27 09:05:10 -0300377 }, {
Ralf Baechled203a7e2005-09-06 15:19:37 -0700378 .description = "8-bit dithered RGB 3-3-2",
379 .bpp = 1,
380 .pixelformat = V4L2_PIX_FMT_RGB332,
381 .colorspace = V4L2_COLORSPACE_SRGB,
Hans Verkuilcf4e9482009-02-27 09:05:10 -0300382 }, {
Ralf Baechled203a7e2005-09-06 15:19:37 -0700383 .description = "32-bit RGB",
384 .bpp = 4,
385 .pixelformat = V4L2_PIX_FMT_RGB32,
386 .colorspace = V4L2_COLORSPACE_SRGB,
Hans Verkuilcf4e9482009-02-27 09:05:10 -0300387 }, {
Ralf Baechled203a7e2005-09-06 15:19:37 -0700388 .description = "YUV 4:2:2",
Ladislav Michla637a112005-09-01 15:07:34 +0000389 .bpp = 2,
Ralf Baechled203a7e2005-09-06 15:19:37 -0700390 .pixelformat = V4L2_PIX_FMT_YUYV, // XXX: swapped?
391 .colorspace = V4L2_COLORSPACE_SMPTE170M,
Ladislav Michla637a112005-09-01 15:07:34 +0000392 }
Ralf Baechled203a7e2005-09-06 15:19:37 -0700393};
394
395static const struct vino_data_norm vino_data_norms[] = {
396 {
397 .description = "NTSC",
398 .std = V4L2_STD_NTSC,
399 .fps_min = 6,
400 .fps_max = 30,
401 .framelines = 525,
402 .width = VINO_NTSC_WIDTH,
403 .height = VINO_NTSC_HEIGHT,
404 .odd = {
Ladislav Michla637a112005-09-01 15:07:34 +0000405 .top = VINO_CLIPPING_START_ODD_NTSC,
406 .left = 0,
Ralf Baechled203a7e2005-09-06 15:19:37 -0700407 .bottom = VINO_CLIPPING_START_ODD_NTSC
408 + VINO_NTSC_HEIGHT / 2 - 1,
Ladislav Michla637a112005-09-01 15:07:34 +0000409 .right = VINO_NTSC_WIDTH,
Ralf Baechled203a7e2005-09-06 15:19:37 -0700410 },
411 .even = {
Ladislav Michla637a112005-09-01 15:07:34 +0000412 .top = VINO_CLIPPING_START_EVEN_NTSC,
413 .left = 0,
Ralf Baechled203a7e2005-09-06 15:19:37 -0700414 .bottom = VINO_CLIPPING_START_EVEN_NTSC
415 + VINO_NTSC_HEIGHT / 2 - 1,
Ladislav Michla637a112005-09-01 15:07:34 +0000416 .right = VINO_NTSC_WIDTH,
Ralf Baechled203a7e2005-09-06 15:19:37 -0700417 },
Hans Verkuilcf4e9482009-02-27 09:05:10 -0300418 }, {
Ralf Baechled203a7e2005-09-06 15:19:37 -0700419 .description = "PAL",
420 .std = V4L2_STD_PAL,
421 .fps_min = 5,
422 .fps_max = 25,
423 .framelines = 625,
424 .width = VINO_PAL_WIDTH,
425 .height = VINO_PAL_HEIGHT,
426 .odd = {
Ladislav Michla637a112005-09-01 15:07:34 +0000427 .top = VINO_CLIPPING_START_ODD_PAL,
428 .left = 0,
Ralf Baechled203a7e2005-09-06 15:19:37 -0700429 .bottom = VINO_CLIPPING_START_ODD_PAL
430 + VINO_PAL_HEIGHT / 2 - 1,
Ladislav Michla637a112005-09-01 15:07:34 +0000431 .right = VINO_PAL_WIDTH,
Ralf Baechled203a7e2005-09-06 15:19:37 -0700432 },
433 .even = {
Ladislav Michla637a112005-09-01 15:07:34 +0000434 .top = VINO_CLIPPING_START_EVEN_PAL,
435 .left = 0,
Ralf Baechled203a7e2005-09-06 15:19:37 -0700436 .bottom = VINO_CLIPPING_START_EVEN_PAL
437 + VINO_PAL_HEIGHT / 2 - 1,
Ladislav Michla637a112005-09-01 15:07:34 +0000438 .right = VINO_PAL_WIDTH,
Ralf Baechled203a7e2005-09-06 15:19:37 -0700439 },
Hans Verkuilcf4e9482009-02-27 09:05:10 -0300440 }, {
Ralf Baechled203a7e2005-09-06 15:19:37 -0700441 .description = "SECAM",
442 .std = V4L2_STD_SECAM,
443 .fps_min = 5,
444 .fps_max = 25,
445 .framelines = 625,
446 .width = VINO_PAL_WIDTH,
447 .height = VINO_PAL_HEIGHT,
448 .odd = {
Ladislav Michla637a112005-09-01 15:07:34 +0000449 .top = VINO_CLIPPING_START_ODD_PAL,
450 .left = 0,
Ralf Baechled203a7e2005-09-06 15:19:37 -0700451 .bottom = VINO_CLIPPING_START_ODD_PAL
452 + VINO_PAL_HEIGHT / 2 - 1,
Ladislav Michla637a112005-09-01 15:07:34 +0000453 .right = VINO_PAL_WIDTH,
Ralf Baechled203a7e2005-09-06 15:19:37 -0700454 },
455 .even = {
Ladislav Michla637a112005-09-01 15:07:34 +0000456 .top = VINO_CLIPPING_START_EVEN_PAL,
457 .left = 0,
Ralf Baechled203a7e2005-09-06 15:19:37 -0700458 .bottom = VINO_CLIPPING_START_EVEN_PAL
459 + VINO_PAL_HEIGHT / 2 - 1,
Ladislav Michla637a112005-09-01 15:07:34 +0000460 .right = VINO_PAL_WIDTH,
Ralf Baechled203a7e2005-09-06 15:19:37 -0700461 },
Hans Verkuilcf4e9482009-02-27 09:05:10 -0300462 }, {
Ladislav Michla637a112005-09-01 15:07:34 +0000463 .description = "NTSC/D1",
Ralf Baechled203a7e2005-09-06 15:19:37 -0700464 .std = V4L2_STD_NTSC,
465 .fps_min = 6,
466 .fps_max = 30,
467 .framelines = 525,
468 .width = VINO_NTSC_WIDTH,
469 .height = VINO_NTSC_HEIGHT,
470 .odd = {
Ladislav Michla637a112005-09-01 15:07:34 +0000471 .top = VINO_CLIPPING_START_ODD_D1,
472 .left = 0,
Ralf Baechled203a7e2005-09-06 15:19:37 -0700473 .bottom = VINO_CLIPPING_START_ODD_D1
474 + VINO_NTSC_HEIGHT / 2 - 1,
Ladislav Michla637a112005-09-01 15:07:34 +0000475 .right = VINO_NTSC_WIDTH,
Ralf Baechled203a7e2005-09-06 15:19:37 -0700476 },
477 .even = {
Ladislav Michla637a112005-09-01 15:07:34 +0000478 .top = VINO_CLIPPING_START_EVEN_D1,
479 .left = 0,
Ralf Baechled203a7e2005-09-06 15:19:37 -0700480 .bottom = VINO_CLIPPING_START_EVEN_D1
481 + VINO_NTSC_HEIGHT / 2 - 1,
Ladislav Michla637a112005-09-01 15:07:34 +0000482 .right = VINO_NTSC_WIDTH,
Ralf Baechled203a7e2005-09-06 15:19:37 -0700483 },
484 }
485};
486
487#define VINO_INDYCAM_V4L2_CONTROL_COUNT 9
488
489struct v4l2_queryctrl vino_indycam_v4l2_controls[] = {
490 {
491 .id = V4L2_CID_AUTOGAIN,
492 .type = V4L2_CTRL_TYPE_BOOLEAN,
493 .name = "Automatic Gain Control",
494 .minimum = 0,
495 .maximum = 1,
496 .step = 1,
497 .default_value = INDYCAM_AGC_DEFAULT,
Hans Verkuilcf4e9482009-02-27 09:05:10 -0300498 }, {
Ralf Baechled203a7e2005-09-06 15:19:37 -0700499 .id = V4L2_CID_AUTO_WHITE_BALANCE,
500 .type = V4L2_CTRL_TYPE_BOOLEAN,
501 .name = "Automatic White Balance",
502 .minimum = 0,
503 .maximum = 1,
504 .step = 1,
505 .default_value = INDYCAM_AWB_DEFAULT,
Hans Verkuilcf4e9482009-02-27 09:05:10 -0300506 }, {
Ralf Baechled203a7e2005-09-06 15:19:37 -0700507 .id = V4L2_CID_GAIN,
508 .type = V4L2_CTRL_TYPE_INTEGER,
509 .name = "Gain",
510 .minimum = INDYCAM_GAIN_MIN,
511 .maximum = INDYCAM_GAIN_MAX,
512 .step = 1,
513 .default_value = INDYCAM_GAIN_DEFAULT,
Hans Verkuilcf4e9482009-02-27 09:05:10 -0300514 }, {
515 .id = INDYCAM_CONTROL_RED_SATURATION,
Ralf Baechled203a7e2005-09-06 15:19:37 -0700516 .type = V4L2_CTRL_TYPE_INTEGER,
517 .name = "Red Saturation",
518 .minimum = INDYCAM_RED_SATURATION_MIN,
519 .maximum = INDYCAM_RED_SATURATION_MAX,
520 .step = 1,
521 .default_value = INDYCAM_RED_SATURATION_DEFAULT,
Hans Verkuilcf4e9482009-02-27 09:05:10 -0300522 }, {
523 .id = INDYCAM_CONTROL_BLUE_SATURATION,
Ralf Baechled203a7e2005-09-06 15:19:37 -0700524 .type = V4L2_CTRL_TYPE_INTEGER,
525 .name = "Blue Saturation",
526 .minimum = INDYCAM_BLUE_SATURATION_MIN,
527 .maximum = INDYCAM_BLUE_SATURATION_MAX,
528 .step = 1,
529 .default_value = INDYCAM_BLUE_SATURATION_DEFAULT,
Hans Verkuilcf4e9482009-02-27 09:05:10 -0300530 }, {
Ralf Baechled203a7e2005-09-06 15:19:37 -0700531 .id = V4L2_CID_RED_BALANCE,
532 .type = V4L2_CTRL_TYPE_INTEGER,
533 .name = "Red Balance",
534 .minimum = INDYCAM_RED_BALANCE_MIN,
535 .maximum = INDYCAM_RED_BALANCE_MAX,
536 .step = 1,
537 .default_value = INDYCAM_RED_BALANCE_DEFAULT,
Hans Verkuilcf4e9482009-02-27 09:05:10 -0300538 }, {
Ralf Baechled203a7e2005-09-06 15:19:37 -0700539 .id = V4L2_CID_BLUE_BALANCE,
540 .type = V4L2_CTRL_TYPE_INTEGER,
541 .name = "Blue Balance",
542 .minimum = INDYCAM_BLUE_BALANCE_MIN,
543 .maximum = INDYCAM_BLUE_BALANCE_MAX,
544 .step = 1,
545 .default_value = INDYCAM_BLUE_BALANCE_DEFAULT,
Hans Verkuilcf4e9482009-02-27 09:05:10 -0300546 }, {
Ralf Baechled203a7e2005-09-06 15:19:37 -0700547 .id = V4L2_CID_EXPOSURE,
548 .type = V4L2_CTRL_TYPE_INTEGER,
549 .name = "Shutter Control",
550 .minimum = INDYCAM_SHUTTER_MIN,
551 .maximum = INDYCAM_SHUTTER_MAX,
552 .step = 1,
553 .default_value = INDYCAM_SHUTTER_DEFAULT,
Hans Verkuilcf4e9482009-02-27 09:05:10 -0300554 }, {
Ralf Baechled203a7e2005-09-06 15:19:37 -0700555 .id = V4L2_CID_GAMMA,
556 .type = V4L2_CTRL_TYPE_INTEGER,
557 .name = "Gamma",
558 .minimum = INDYCAM_GAMMA_MIN,
559 .maximum = INDYCAM_GAMMA_MAX,
560 .step = 1,
561 .default_value = INDYCAM_GAMMA_DEFAULT,
Ralf Baechled203a7e2005-09-06 15:19:37 -0700562 }
563};
564
Ladislav Michla637a112005-09-01 15:07:34 +0000565#define VINO_SAA7191_V4L2_CONTROL_COUNT 9
Ralf Baechled203a7e2005-09-06 15:19:37 -0700566
567struct v4l2_queryctrl vino_saa7191_v4l2_controls[] = {
568 {
569 .id = V4L2_CID_HUE,
570 .type = V4L2_CTRL_TYPE_INTEGER,
571 .name = "Hue",
572 .minimum = SAA7191_HUE_MIN,
573 .maximum = SAA7191_HUE_MAX,
574 .step = 1,
575 .default_value = SAA7191_HUE_DEFAULT,
Hans Verkuilcf4e9482009-02-27 09:05:10 -0300576 }, {
577 .id = SAA7191_CONTROL_BANDPASS,
Ladislav Michla637a112005-09-01 15:07:34 +0000578 .type = V4L2_CTRL_TYPE_INTEGER,
579 .name = "Luminance Bandpass",
580 .minimum = SAA7191_BANDPASS_MIN,
581 .maximum = SAA7191_BANDPASS_MAX,
582 .step = 1,
583 .default_value = SAA7191_BANDPASS_DEFAULT,
Hans Verkuilcf4e9482009-02-27 09:05:10 -0300584 }, {
585 .id = SAA7191_CONTROL_BANDPASS_WEIGHT,
Ladislav Michla637a112005-09-01 15:07:34 +0000586 .type = V4L2_CTRL_TYPE_INTEGER,
587 .name = "Luminance Bandpass Weight",
588 .minimum = SAA7191_BANDPASS_WEIGHT_MIN,
589 .maximum = SAA7191_BANDPASS_WEIGHT_MAX,
590 .step = 1,
591 .default_value = SAA7191_BANDPASS_WEIGHT_DEFAULT,
Hans Verkuilcf4e9482009-02-27 09:05:10 -0300592 }, {
593 .id = SAA7191_CONTROL_CORING,
Ladislav Michla637a112005-09-01 15:07:34 +0000594 .type = V4L2_CTRL_TYPE_INTEGER,
595 .name = "HF Luminance Coring",
596 .minimum = SAA7191_CORING_MIN,
597 .maximum = SAA7191_CORING_MAX,
598 .step = 1,
599 .default_value = SAA7191_CORING_DEFAULT,
Hans Verkuilcf4e9482009-02-27 09:05:10 -0300600 }, {
601 .id = SAA7191_CONTROL_FORCE_COLOUR,
Ladislav Michla637a112005-09-01 15:07:34 +0000602 .type = V4L2_CTRL_TYPE_BOOLEAN,
603 .name = "Force Colour",
604 .minimum = SAA7191_FORCE_COLOUR_MIN,
605 .maximum = SAA7191_FORCE_COLOUR_MAX,
606 .step = 1,
607 .default_value = SAA7191_FORCE_COLOUR_DEFAULT,
Hans Verkuilcf4e9482009-02-27 09:05:10 -0300608 }, {
609 .id = SAA7191_CONTROL_CHROMA_GAIN,
Ladislav Michla637a112005-09-01 15:07:34 +0000610 .type = V4L2_CTRL_TYPE_INTEGER,
611 .name = "Chrominance Gain Control",
612 .minimum = SAA7191_CHROMA_GAIN_MIN,
613 .maximum = SAA7191_CHROMA_GAIN_MAX,
614 .step = 1,
615 .default_value = SAA7191_CHROMA_GAIN_DEFAULT,
Hans Verkuilcf4e9482009-02-27 09:05:10 -0300616 }, {
617 .id = SAA7191_CONTROL_VTRC,
Ralf Baechled203a7e2005-09-06 15:19:37 -0700618 .type = V4L2_CTRL_TYPE_BOOLEAN,
619 .name = "VTR Time Constant",
620 .minimum = SAA7191_VTRC_MIN,
621 .maximum = SAA7191_VTRC_MAX,
622 .step = 1,
623 .default_value = SAA7191_VTRC_DEFAULT,
Hans Verkuilcf4e9482009-02-27 09:05:10 -0300624 }, {
625 .id = SAA7191_CONTROL_LUMA_DELAY,
Ladislav Michla637a112005-09-01 15:07:34 +0000626 .type = V4L2_CTRL_TYPE_INTEGER,
627 .name = "Luminance Delay Compensation",
628 .minimum = SAA7191_LUMA_DELAY_MIN,
629 .maximum = SAA7191_LUMA_DELAY_MAX,
630 .step = 1,
631 .default_value = SAA7191_LUMA_DELAY_DEFAULT,
Hans Verkuilcf4e9482009-02-27 09:05:10 -0300632 }, {
633 .id = SAA7191_CONTROL_VNR,
Ladislav Michla637a112005-09-01 15:07:34 +0000634 .type = V4L2_CTRL_TYPE_INTEGER,
635 .name = "Vertical Noise Reduction",
636 .minimum = SAA7191_VNR_MIN,
637 .maximum = SAA7191_VNR_MAX,
638 .step = 1,
639 .default_value = SAA7191_VNR_DEFAULT,
Ralf Baechled203a7e2005-09-06 15:19:37 -0700640 }
641};
642
643/* VINO I2C bus functions */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700644
645unsigned i2c_vino_getctrl(void *data)
646{
647 return vino->i2c_control;
648}
649
650void i2c_vino_setctrl(void *data, unsigned val)
651{
652 vino->i2c_control = val;
653}
654
655unsigned i2c_vino_rdata(void *data)
656{
657 return vino->i2c_data;
658}
659
660void i2c_vino_wdata(void *data, unsigned val)
661{
662 vino->i2c_data = val;
663}
664
665static struct i2c_algo_sgi_data i2c_sgi_vino_data =
666{
667 .getctrl = &i2c_vino_getctrl,
668 .setctrl = &i2c_vino_setctrl,
669 .rdata = &i2c_vino_rdata,
670 .wdata = &i2c_vino_wdata,
671 .xfer_timeout = 200,
672 .ack_timeout = 1000,
673};
674
Linus Torvalds1da177e2005-04-16 15:20:36 -0700675static struct i2c_adapter vino_i2c_adapter =
676{
677 .name = "VINO I2C bus",
678 .id = I2C_HW_SGI_VINO,
679 .algo_data = &i2c_sgi_vino_data,
Hans Verkuil48f4dac2009-02-18 19:18:26 -0300680 .owner = THIS_MODULE,
Linus Torvalds1da177e2005-04-16 15:20:36 -0700681};
682
683static int vino_i2c_add_bus(void)
684{
685 return i2c_sgi_add_bus(&vino_i2c_adapter);
686}
687
688static int vino_i2c_del_bus(void)
689{
Jean Delvare32697112006-12-10 21:21:33 +0100690 return i2c_del_adapter(&vino_i2c_adapter);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700691}
692
Ralf Baechled203a7e2005-09-06 15:19:37 -0700693/* VINO framebuffer/DMA descriptor management */
694
695static void vino_free_buffer_with_count(struct vino_framebuffer *fb,
696 unsigned int count)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700697{
Ralf Baechled203a7e2005-09-06 15:19:37 -0700698 unsigned int i;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700699
Ralf Baechled203a7e2005-09-06 15:19:37 -0700700 dprintk("vino_free_buffer_with_count(): count = %d\n", count);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700701
Ralf Baechled203a7e2005-09-06 15:19:37 -0700702 for (i = 0; i < count; i++) {
Hans Verkuileda9e4e2008-08-22 17:12:08 -0300703 ClearPageReserved(virt_to_page((void *)fb->desc_table.virtual[i]));
Ralf Baechled203a7e2005-09-06 15:19:37 -0700704 dma_unmap_single(NULL,
705 fb->desc_table.dma_cpu[VINO_PAGE_RATIO * i],
706 PAGE_SIZE, DMA_FROM_DEVICE);
707 free_page(fb->desc_table.virtual[i]);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700708 }
709
Ralf Baechled203a7e2005-09-06 15:19:37 -0700710 dma_free_coherent(NULL,
711 VINO_PAGE_RATIO * (fb->desc_table.page_count + 4) *
712 sizeof(dma_addr_t), (void *)fb->desc_table.dma_cpu,
713 fb->desc_table.dma);
714 kfree(fb->desc_table.virtual);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700715
Ralf Baechled203a7e2005-09-06 15:19:37 -0700716 memset(fb, 0, sizeof(struct vino_framebuffer));
717}
Linus Torvalds1da177e2005-04-16 15:20:36 -0700718
Ralf Baechled203a7e2005-09-06 15:19:37 -0700719static void vino_free_buffer(struct vino_framebuffer *fb)
720{
721 vino_free_buffer_with_count(fb, fb->desc_table.page_count);
722}
723
724static int vino_allocate_buffer(struct vino_framebuffer *fb,
725 unsigned int size)
726{
727 unsigned int count, i, j;
728 int ret = 0;
729
730 dprintk("vino_allocate_buffer():\n");
731
732 if (size < 1)
733 return -EINVAL;
734
735 memset(fb, 0, sizeof(struct vino_framebuffer));
736
737 count = ((size / PAGE_SIZE) + 4) & ~3;
738
739 dprintk("vino_allocate_buffer(): size = %d, count = %d\n",
740 size, count);
741
742 /* allocate memory for table with virtual (page) addresses */
743 fb->desc_table.virtual = (unsigned long *)
744 kmalloc(count * sizeof(unsigned long), GFP_KERNEL);
745 if (!fb->desc_table.virtual)
746 return -ENOMEM;
747
748 /* allocate memory for table with dma addresses
749 * (has space for four extra descriptors) */
750 fb->desc_table.dma_cpu =
751 dma_alloc_coherent(NULL, VINO_PAGE_RATIO * (count + 4) *
752 sizeof(dma_addr_t), &fb->desc_table.dma,
753 GFP_KERNEL | GFP_DMA);
754 if (!fb->desc_table.dma_cpu) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700755 ret = -ENOMEM;
Ralf Baechled203a7e2005-09-06 15:19:37 -0700756 goto out_free_virtual;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700757 }
758
Ralf Baechled203a7e2005-09-06 15:19:37 -0700759 /* allocate pages for the buffer and acquire the according
760 * dma addresses */
761 for (i = 0; i < count; i++) {
762 dma_addr_t dma_data_addr;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700763
Ralf Baechled203a7e2005-09-06 15:19:37 -0700764 fb->desc_table.virtual[i] =
765 get_zeroed_page(GFP_KERNEL | GFP_DMA);
766 if (!fb->desc_table.virtual[i]) {
767 ret = -ENOBUFS;
768 break;
769 }
Linus Torvalds1da177e2005-04-16 15:20:36 -0700770
Ralf Baechled203a7e2005-09-06 15:19:37 -0700771 dma_data_addr =
772 dma_map_single(NULL,
773 (void *)fb->desc_table.virtual[i],
774 PAGE_SIZE, DMA_FROM_DEVICE);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700775
Ralf Baechled203a7e2005-09-06 15:19:37 -0700776 for (j = 0; j < VINO_PAGE_RATIO; j++) {
777 fb->desc_table.dma_cpu[VINO_PAGE_RATIO * i + j] =
778 dma_data_addr + VINO_PAGE_SIZE * j;
779 }
780
Hans Verkuileda9e4e2008-08-22 17:12:08 -0300781 SetPageReserved(virt_to_page((void *)fb->desc_table.virtual[i]));
Linus Torvalds1da177e2005-04-16 15:20:36 -0700782 }
783
Ralf Baechled203a7e2005-09-06 15:19:37 -0700784 /* page_count needs to be set anyway, because the descriptor table has
785 * been allocated according to this number */
786 fb->desc_table.page_count = count;
787
Linus Torvalds1da177e2005-04-16 15:20:36 -0700788 if (ret) {
Ralf Baechled203a7e2005-09-06 15:19:37 -0700789 /* the descriptor with index i doesn't contain
790 * a valid address yet */
791 vino_free_buffer_with_count(fb, i);
792 return ret;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700793 }
794
Ralf Baechled203a7e2005-09-06 15:19:37 -0700795 //fb->size = size;
796 fb->size = count * PAGE_SIZE;
797 fb->data_format = VINO_DATA_FMT_NONE;
798
799 /* set the dma stop-bit for the last (count+1)th descriptor */
800 fb->desc_table.dma_cpu[VINO_PAGE_RATIO * count] = VINO_DESC_STOP;
801 return 0;
802
803 out_free_virtual:
804 kfree(fb->desc_table.virtual);
805 return ret;
806}
807
808#if 0
809/* user buffers not fully implemented yet */
810static int vino_prepare_user_buffer(struct vino_framebuffer *fb,
811 void *user,
812 unsigned int size)
813{
814 unsigned int count, i, j;
815 int ret = 0;
816
817 dprintk("vino_prepare_user_buffer():\n");
818
819 if (size < 1)
820 return -EINVAL;
821
822 memset(fb, 0, sizeof(struct vino_framebuffer));
823
824 count = ((size / PAGE_SIZE)) & ~3;
825
826 dprintk("vino_prepare_user_buffer(): size = %d, count = %d\n",
827 size, count);
828
829 /* allocate memory for table with virtual (page) addresses */
830 fb->desc_table.virtual = (unsigned long *)
831 kmalloc(count * sizeof(unsigned long), GFP_KERNEL);
832 if (!fb->desc_table.virtual)
833 return -ENOMEM;
834
835 /* allocate memory for table with dma addresses
836 * (has space for four extra descriptors) */
837 fb->desc_table.dma_cpu =
838 dma_alloc_coherent(NULL, VINO_PAGE_RATIO * (count + 4) *
839 sizeof(dma_addr_t), &fb->desc_table.dma,
840 GFP_KERNEL | GFP_DMA);
841 if (!fb->desc_table.dma_cpu) {
842 ret = -ENOMEM;
843 goto out_free_virtual;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700844 }
Ralf Baechled203a7e2005-09-06 15:19:37 -0700845
846 /* allocate pages for the buffer and acquire the according
847 * dma addresses */
848 for (i = 0; i < count; i++) {
849 dma_addr_t dma_data_addr;
850
851 fb->desc_table.virtual[i] =
852 get_zeroed_page(GFP_KERNEL | GFP_DMA);
853 if (!fb->desc_table.virtual[i]) {
854 ret = -ENOBUFS;
855 break;
856 }
857
858 dma_data_addr =
859 dma_map_single(NULL,
860 (void *)fb->desc_table.virtual[i],
861 PAGE_SIZE, DMA_FROM_DEVICE);
862
863 for (j = 0; j < VINO_PAGE_RATIO; j++) {
864 fb->desc_table.dma_cpu[VINO_PAGE_RATIO * i + j] =
865 dma_data_addr + VINO_PAGE_SIZE * j;
866 }
867
Hans Verkuileda9e4e2008-08-22 17:12:08 -0300868 SetPageReserved(virt_to_page((void *)fb->desc_table.virtual[i]));
Ralf Baechled203a7e2005-09-06 15:19:37 -0700869 }
870
871 /* page_count needs to be set anyway, because the descriptor table has
872 * been allocated according to this number */
873 fb->desc_table.page_count = count;
874
875 if (ret) {
876 /* the descriptor with index i doesn't contain
877 * a valid address yet */
878 vino_free_buffer_with_count(fb, i);
879 return ret;
880 }
881
882 //fb->size = size;
883 fb->size = count * PAGE_SIZE;
884
885 /* set the dma stop-bit for the last (count+1)th descriptor */
886 fb->desc_table.dma_cpu[VINO_PAGE_RATIO * count] = VINO_DESC_STOP;
887 return 0;
888
889 out_free_virtual:
890 kfree(fb->desc_table.virtual);
891 return ret;
892}
893#endif
894
895static void vino_sync_buffer(struct vino_framebuffer *fb)
896{
897 int i;
898
899 dprintk("vino_sync_buffer():\n");
900
901 for (i = 0; i < fb->desc_table.page_count; i++)
902 dma_sync_single(NULL,
903 fb->desc_table.dma_cpu[VINO_PAGE_RATIO * i],
904 PAGE_SIZE, DMA_FROM_DEVICE);
905}
906
907/* Framebuffer fifo functions (need to be locked externally) */
908
Ladislav Michla637a112005-09-01 15:07:34 +0000909static inline void vino_fifo_init(struct vino_framebuffer_fifo *f,
Ralf Baechled203a7e2005-09-06 15:19:37 -0700910 unsigned int length)
911{
912 f->length = 0;
913 f->used = 0;
914 f->head = 0;
915 f->tail = 0;
916
Ladislav Michla637a112005-09-01 15:07:34 +0000917 if (length > VINO_FRAMEBUFFER_COUNT_MAX)
918 length = VINO_FRAMEBUFFER_COUNT_MAX;
Ralf Baechled203a7e2005-09-06 15:19:37 -0700919
920 f->length = length;
921}
922
923/* returns true/false */
Ladislav Michla637a112005-09-01 15:07:34 +0000924static inline int vino_fifo_has_id(struct vino_framebuffer_fifo *f,
925 unsigned int id)
Ralf Baechled203a7e2005-09-06 15:19:37 -0700926{
927 unsigned int i;
Ladislav Michla637a112005-09-01 15:07:34 +0000928
Ralf Baechled203a7e2005-09-06 15:19:37 -0700929 for (i = f->head; i == (f->tail - 1); i = (i + 1) % f->length) {
930 if (f->data[i] == id)
931 return 1;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700932 }
933
934 return 0;
Ralf Baechled203a7e2005-09-06 15:19:37 -0700935}
Linus Torvalds1da177e2005-04-16 15:20:36 -0700936
Ladislav Michla637a112005-09-01 15:07:34 +0000937#if 0
Ralf Baechled203a7e2005-09-06 15:19:37 -0700938/* returns true/false */
Ladislav Michla637a112005-09-01 15:07:34 +0000939static inline int vino_fifo_full(struct vino_framebuffer_fifo *f)
Ralf Baechled203a7e2005-09-06 15:19:37 -0700940{
941 return (f->used == f->length);
942}
Ladislav Michla637a112005-09-01 15:07:34 +0000943#endif
Ralf Baechled203a7e2005-09-06 15:19:37 -0700944
Ladislav Michla637a112005-09-01 15:07:34 +0000945static inline unsigned int vino_fifo_get_used(struct vino_framebuffer_fifo *f)
Ralf Baechled203a7e2005-09-06 15:19:37 -0700946{
947 return f->used;
948}
949
950static int vino_fifo_enqueue(struct vino_framebuffer_fifo *f, unsigned int id)
951{
952 if (id >= f->length) {
953 return VINO_QUEUE_ERROR;
954 }
955
956 if (vino_fifo_has_id(f, id)) {
957 return VINO_QUEUE_ERROR;
958 }
959
960 if (f->used < f->length) {
961 f->data[f->tail] = id;
962 f->tail = (f->tail + 1) % f->length;
963 f->used++;
964 } else {
965 return VINO_QUEUE_ERROR;
966 }
967
968 return 0;
969}
970
971static int vino_fifo_peek(struct vino_framebuffer_fifo *f, unsigned int *id)
972{
973 if (f->used > 0) {
974 *id = f->data[f->head];
975 } else {
976 return VINO_QUEUE_ERROR;
977 }
978
979 return 0;
980}
981
982static int vino_fifo_dequeue(struct vino_framebuffer_fifo *f, unsigned int *id)
983{
984 if (f->used > 0) {
985 *id = f->data[f->head];
986 f->head = (f->head + 1) % f->length;
987 f->used--;
988 } else {
989 return VINO_QUEUE_ERROR;
990 }
991
992 return 0;
993}
994
995/* Framebuffer queue functions */
996
997/* execute with queue_lock locked */
998static void vino_queue_free_with_count(struct vino_framebuffer_queue *q,
999 unsigned int length)
1000{
1001 unsigned int i;
1002
1003 q->length = 0;
1004 memset(&q->in, 0, sizeof(struct vino_framebuffer_fifo));
1005 memset(&q->out, 0, sizeof(struct vino_framebuffer_fifo));
1006 for (i = 0; i < length; i++) {
1007 dprintk("vino_queue_free_with_count(): freeing buffer %d\n",
1008 i);
1009 vino_free_buffer(q->buffer[i]);
1010 kfree(q->buffer[i]);
1011 }
1012
1013 q->type = VINO_MEMORY_NONE;
1014 q->magic = 0;
1015}
1016
1017static void vino_queue_free(struct vino_framebuffer_queue *q)
1018{
1019 dprintk("vino_queue_free():\n");
1020
1021 if (q->magic != VINO_QUEUE_MAGIC)
1022 return;
1023 if (q->type != VINO_MEMORY_MMAP)
1024 return;
1025
Ingo Molnar3593cab2006-02-07 06:49:14 -02001026 mutex_lock(&q->queue_mutex);
Ralf Baechled203a7e2005-09-06 15:19:37 -07001027
1028 vino_queue_free_with_count(q, q->length);
1029
Ingo Molnar3593cab2006-02-07 06:49:14 -02001030 mutex_unlock(&q->queue_mutex);
Ralf Baechled203a7e2005-09-06 15:19:37 -07001031}
1032
1033static int vino_queue_init(struct vino_framebuffer_queue *q,
1034 unsigned int *length)
1035{
1036 unsigned int i;
1037 int ret = 0;
1038
1039 dprintk("vino_queue_init(): length = %d\n", *length);
1040
1041 if (q->magic == VINO_QUEUE_MAGIC) {
1042 dprintk("vino_queue_init(): queue already initialized!\n");
1043 return -EINVAL;
1044 }
1045
1046 if (q->type != VINO_MEMORY_NONE) {
1047 dprintk("vino_queue_init(): queue already initialized!\n");
1048 return -EINVAL;
1049 }
1050
1051 if (*length < 1)
1052 return -EINVAL;
1053
Ingo Molnar3593cab2006-02-07 06:49:14 -02001054 mutex_lock(&q->queue_mutex);
Ralf Baechled203a7e2005-09-06 15:19:37 -07001055
Ladislav Michla637a112005-09-01 15:07:34 +00001056 if (*length > VINO_FRAMEBUFFER_COUNT_MAX)
1057 *length = VINO_FRAMEBUFFER_COUNT_MAX;
Ralf Baechled203a7e2005-09-06 15:19:37 -07001058
1059 q->length = 0;
1060
1061 for (i = 0; i < *length; i++) {
1062 dprintk("vino_queue_init(): allocating buffer %d\n", i);
1063 q->buffer[i] = kmalloc(sizeof(struct vino_framebuffer),
1064 GFP_KERNEL);
1065 if (!q->buffer[i]) {
1066 dprintk("vino_queue_init(): kmalloc() failed\n");
1067 ret = -ENOMEM;
1068 break;
1069 }
1070
1071 ret = vino_allocate_buffer(q->buffer[i],
1072 VINO_FRAMEBUFFER_SIZE);
1073 if (ret) {
1074 kfree(q->buffer[i]);
1075 dprintk("vino_queue_init(): "
1076 "vino_allocate_buffer() failed\n");
1077 break;
1078 }
1079
1080 q->buffer[i]->id = i;
1081 if (i > 0) {
1082 q->buffer[i]->offset = q->buffer[i - 1]->offset +
1083 q->buffer[i - 1]->size;
1084 } else {
1085 q->buffer[i]->offset = 0;
1086 }
1087
1088 spin_lock_init(&q->buffer[i]->state_lock);
1089
1090 dprintk("vino_queue_init(): buffer = %d, offset = %d, "
1091 "size = %d\n", i, q->buffer[i]->offset,
1092 q->buffer[i]->size);
1093 }
1094
1095 if (ret) {
1096 vino_queue_free_with_count(q, i);
1097 *length = 0;
1098 } else {
1099 q->length = *length;
1100 vino_fifo_init(&q->in, q->length);
1101 vino_fifo_init(&q->out, q->length);
1102 q->type = VINO_MEMORY_MMAP;
1103 q->magic = VINO_QUEUE_MAGIC;
1104 }
1105
Ingo Molnar3593cab2006-02-07 06:49:14 -02001106 mutex_unlock(&q->queue_mutex);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001107
1108 return ret;
1109}
1110
Ralf Baechled203a7e2005-09-06 15:19:37 -07001111static struct vino_framebuffer *vino_queue_add(struct
1112 vino_framebuffer_queue *q,
1113 unsigned int id)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001114{
Ralf Baechled203a7e2005-09-06 15:19:37 -07001115 struct vino_framebuffer *ret = NULL;
1116 unsigned int total;
1117 unsigned long flags;
1118
1119 dprintk("vino_queue_add(): id = %d\n", id);
1120
1121 if (q->magic != VINO_QUEUE_MAGIC) {
1122 return ret;
1123 }
1124
1125 spin_lock_irqsave(&q->queue_lock, flags);
1126
1127 if (q->length == 0)
1128 goto out;
1129
1130 if (id >= q->length)
1131 goto out;
1132
1133 /* not needed?: if (vino_fifo_full(&q->out)) {
1134 goto out;
1135 }*/
1136 /* check that outgoing queue isn't already full
1137 * (or that it won't become full) */
1138 total = vino_fifo_get_used(&q->in) +
1139 vino_fifo_get_used(&q->out);
1140 if (total >= q->length)
1141 goto out;
1142
1143 if (vino_fifo_enqueue(&q->in, id))
1144 goto out;
1145
1146 ret = q->buffer[id];
1147
1148out:
1149 spin_unlock_irqrestore(&q->queue_lock, flags);
1150
1151 return ret;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001152}
1153
Ralf Baechled203a7e2005-09-06 15:19:37 -07001154static struct vino_framebuffer *vino_queue_transfer(struct
1155 vino_framebuffer_queue *q)
1156{
1157 struct vino_framebuffer *ret = NULL;
1158 struct vino_framebuffer *fb;
1159 int id;
1160 unsigned long flags;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001161
Ralf Baechled203a7e2005-09-06 15:19:37 -07001162 dprintk("vino_queue_transfer():\n");
1163
1164 if (q->magic != VINO_QUEUE_MAGIC) {
1165 return ret;
1166 }
1167
1168 spin_lock_irqsave(&q->queue_lock, flags);
1169
1170 if (q->length == 0)
1171 goto out;
1172
1173 // now this actually removes an entry from the incoming queue
1174 if (vino_fifo_dequeue(&q->in, &id)) {
1175 goto out;
1176 }
1177
1178 dprintk("vino_queue_transfer(): id = %d\n", id);
1179 fb = q->buffer[id];
1180
1181 // we have already checked that the outgoing queue is not full, but...
1182 if (vino_fifo_enqueue(&q->out, id)) {
1183 printk(KERN_ERR "vino_queue_transfer(): "
1184 "outgoing queue is full, this shouldn't happen!\n");
1185 goto out;
1186 }
1187
1188 ret = fb;
1189out:
1190 spin_unlock_irqrestore(&q->queue_lock, flags);
1191
1192 return ret;
1193}
1194
1195/* returns true/false */
1196static int vino_queue_incoming_contains(struct vino_framebuffer_queue *q,
1197 unsigned int id)
1198{
1199 int ret = 0;
1200 unsigned long flags;
1201
1202 if (q->magic != VINO_QUEUE_MAGIC) {
1203 return ret;
1204 }
1205
1206 spin_lock_irqsave(&q->queue_lock, flags);
1207
1208 if (q->length == 0)
1209 goto out;
1210
1211 ret = vino_fifo_has_id(&q->in, id);
1212
1213out:
1214 spin_unlock_irqrestore(&q->queue_lock, flags);
1215
1216 return ret;
1217}
1218
1219/* returns true/false */
1220static int vino_queue_outgoing_contains(struct vino_framebuffer_queue *q,
1221 unsigned int id)
1222{
1223 int ret = 0;
1224 unsigned long flags;
1225
1226 if (q->magic != VINO_QUEUE_MAGIC) {
1227 return ret;
1228 }
1229
1230 spin_lock_irqsave(&q->queue_lock, flags);
1231
1232 if (q->length == 0)
1233 goto out;
1234
1235 ret = vino_fifo_has_id(&q->out, id);
1236
1237out:
1238 spin_unlock_irqrestore(&q->queue_lock, flags);
1239
1240 return ret;
1241}
1242
1243static int vino_queue_get_incoming(struct vino_framebuffer_queue *q,
1244 unsigned int *used)
1245{
1246 int ret = 0;
1247 unsigned long flags;
1248
1249 if (q->magic != VINO_QUEUE_MAGIC) {
1250 return VINO_QUEUE_ERROR;
1251 }
1252
1253 spin_lock_irqsave(&q->queue_lock, flags);
1254
1255 if (q->length == 0) {
1256 ret = VINO_QUEUE_ERROR;
1257 goto out;
1258 }
1259
1260 *used = vino_fifo_get_used(&q->in);
1261
1262out:
1263 spin_unlock_irqrestore(&q->queue_lock, flags);
1264
1265 return ret;
1266}
1267
1268static int vino_queue_get_outgoing(struct vino_framebuffer_queue *q,
1269 unsigned int *used)
1270{
1271 int ret = 0;
1272 unsigned long flags;
1273
1274 if (q->magic != VINO_QUEUE_MAGIC) {
1275 return VINO_QUEUE_ERROR;
1276 }
1277
1278 spin_lock_irqsave(&q->queue_lock, flags);
1279
1280 if (q->length == 0) {
1281 ret = VINO_QUEUE_ERROR;
1282 goto out;
1283 }
1284
1285 *used = vino_fifo_get_used(&q->out);
1286
1287out:
1288 spin_unlock_irqrestore(&q->queue_lock, flags);
1289
1290 return ret;
1291}
1292
Ladislav Michla637a112005-09-01 15:07:34 +00001293#if 0
Ralf Baechled203a7e2005-09-06 15:19:37 -07001294static int vino_queue_get_total(struct vino_framebuffer_queue *q,
1295 unsigned int *total)
1296{
1297 int ret = 0;
1298 unsigned long flags;
1299
1300 if (q->magic != VINO_QUEUE_MAGIC) {
1301 return VINO_QUEUE_ERROR;
1302 }
1303
1304 spin_lock_irqsave(&q->queue_lock, flags);
1305
1306 if (q->length == 0) {
1307 ret = VINO_QUEUE_ERROR;
1308 goto out;
1309 }
1310
1311 *total = vino_fifo_get_used(&q->in) +
1312 vino_fifo_get_used(&q->out);
1313
1314out:
1315 spin_unlock_irqrestore(&q->queue_lock, flags);
1316
1317 return ret;
1318}
Ladislav Michla637a112005-09-01 15:07:34 +00001319#endif
Ralf Baechled203a7e2005-09-06 15:19:37 -07001320
1321static struct vino_framebuffer *vino_queue_peek(struct
1322 vino_framebuffer_queue *q,
1323 unsigned int *id)
1324{
1325 struct vino_framebuffer *ret = NULL;
1326 unsigned long flags;
1327
1328 if (q->magic != VINO_QUEUE_MAGIC) {
1329 return ret;
1330 }
1331
1332 spin_lock_irqsave(&q->queue_lock, flags);
1333
1334 if (q->length == 0)
1335 goto out;
1336
1337 if (vino_fifo_peek(&q->in, id)) {
1338 goto out;
1339 }
1340
1341 ret = q->buffer[*id];
1342out:
1343 spin_unlock_irqrestore(&q->queue_lock, flags);
1344
1345 return ret;
1346}
1347
1348static struct vino_framebuffer *vino_queue_remove(struct
1349 vino_framebuffer_queue *q,
1350 unsigned int *id)
1351{
1352 struct vino_framebuffer *ret = NULL;
1353 unsigned long flags;
1354 dprintk("vino_queue_remove():\n");
1355
1356 if (q->magic != VINO_QUEUE_MAGIC) {
1357 return ret;
1358 }
1359
1360 spin_lock_irqsave(&q->queue_lock, flags);
1361
1362 if (q->length == 0)
1363 goto out;
1364
1365 if (vino_fifo_dequeue(&q->out, id)) {
1366 goto out;
1367 }
1368
1369 dprintk("vino_queue_remove(): id = %d\n", *id);
1370 ret = q->buffer[*id];
1371out:
1372 spin_unlock_irqrestore(&q->queue_lock, flags);
1373
1374 return ret;
1375}
1376
1377static struct
1378vino_framebuffer *vino_queue_get_buffer(struct vino_framebuffer_queue *q,
1379 unsigned int id)
1380{
1381 struct vino_framebuffer *ret = NULL;
1382 unsigned long flags;
1383
1384 if (q->magic != VINO_QUEUE_MAGIC) {
1385 return ret;
1386 }
1387
1388 spin_lock_irqsave(&q->queue_lock, flags);
1389
1390 if (q->length == 0)
1391 goto out;
1392
1393 if (id >= q->length)
1394 goto out;
1395
1396 ret = q->buffer[id];
1397 out:
1398 spin_unlock_irqrestore(&q->queue_lock, flags);
1399
1400 return ret;
1401}
1402
1403static unsigned int vino_queue_get_length(struct vino_framebuffer_queue *q)
1404{
1405 unsigned int length = 0;
1406 unsigned long flags;
1407
1408 if (q->magic != VINO_QUEUE_MAGIC) {
1409 return length;
1410 }
1411
1412 spin_lock_irqsave(&q->queue_lock, flags);
1413 length = q->length;
1414 spin_unlock_irqrestore(&q->queue_lock, flags);
1415
1416 return length;
1417}
1418
1419static int vino_queue_has_mapped_buffers(struct vino_framebuffer_queue *q)
1420{
1421 unsigned int i;
1422 int ret = 0;
1423 unsigned long flags;
1424
1425 if (q->magic != VINO_QUEUE_MAGIC) {
1426 return ret;
1427 }
1428
1429 spin_lock_irqsave(&q->queue_lock, flags);
1430 for (i = 0; i < q->length; i++) {
1431 if (q->buffer[i]->map_count > 0) {
1432 ret = 1;
1433 break;
1434 }
1435 }
1436 spin_unlock_irqrestore(&q->queue_lock, flags);
1437
1438 return ret;
1439}
1440
1441/* VINO functions */
1442
1443/* execute with input_lock locked */
1444static void vino_update_line_size(struct vino_channel_settings *vcs)
1445{
1446 unsigned int w = vcs->clipping.right - vcs->clipping.left;
1447 unsigned int d = vcs->decimation;
1448 unsigned int bpp = vino_data_formats[vcs->data_format].bpp;
Mauro Carvalho Chehabd56410e2006-03-25 09:19:53 -03001449 unsigned int lsize;
Ralf Baechled203a7e2005-09-06 15:19:37 -07001450
1451 dprintk("update_line_size(): before: w = %d, d = %d, "
1452 "line_size = %d\n", w, d, vcs->line_size);
Ladislav Michla637a112005-09-01 15:07:34 +00001453
Mauro Carvalho Chehabd56410e2006-03-25 09:19:53 -03001454 /* line size must be multiple of 8 bytes */
Ralf Baechled203a7e2005-09-06 15:19:37 -07001455 lsize = (bpp * (w / d)) & ~7;
1456 w = (lsize / bpp) * d;
1457
1458 vcs->clipping.right = vcs->clipping.left + w;
1459 vcs->line_size = lsize;
Ladislav Michla637a112005-09-01 15:07:34 +00001460
Ralf Baechled203a7e2005-09-06 15:19:37 -07001461 dprintk("update_line_size(): after: w = %d, d = %d, "
1462 "line_size = %d\n", w, d, vcs->line_size);
1463}
1464
1465/* execute with input_lock locked */
1466static void vino_set_clipping(struct vino_channel_settings *vcs,
1467 unsigned int x, unsigned int y,
1468 unsigned int w, unsigned int h)
1469{
1470 unsigned int maxwidth, maxheight;
1471 unsigned int d;
1472
1473 maxwidth = vino_data_norms[vcs->data_norm].width;
1474 maxheight = vino_data_norms[vcs->data_norm].height;
1475 d = vcs->decimation;
1476
1477 y &= ~1; /* odd/even fields */
1478
1479 if (x > maxwidth) {
1480 x = 0;
1481 }
1482 if (y > maxheight) {
1483 y = 0;
1484 }
1485
1486 if (((w / d) < VINO_MIN_WIDTH)
1487 || ((h / d) < VINO_MIN_HEIGHT)) {
1488 w = VINO_MIN_WIDTH * d;
1489 h = VINO_MIN_HEIGHT * d;
1490 }
1491
1492 if ((x + w) > maxwidth) {
1493 w = maxwidth - x;
1494 if ((w / d) < VINO_MIN_WIDTH)
1495 x = maxwidth - VINO_MIN_WIDTH * d;
1496 }
1497 if ((y + h) > maxheight) {
1498 h = maxheight - y;
1499 if ((h / d) < VINO_MIN_HEIGHT)
1500 y = maxheight - VINO_MIN_HEIGHT * d;
1501 }
1502
1503 vcs->clipping.left = x;
1504 vcs->clipping.top = y;
1505 vcs->clipping.right = x + w;
1506 vcs->clipping.bottom = y + h;
1507
1508 vino_update_line_size(vcs);
1509
1510 dprintk("clipping %d, %d, %d, %d / %d - %d\n",
1511 vcs->clipping.left, vcs->clipping.top, vcs->clipping.right,
1512 vcs->clipping.bottom, 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_clipping(struct vino_channel_settings *vcs)
Ralf Baechled203a7e2005-09-06 15:19:37 -07001517{
1518 vino_set_clipping(vcs, 0, 0, vino_data_norms[vcs->data_norm].width,
1519 vino_data_norms[vcs->data_norm].height);
1520}
1521
1522/* execute with input_lock locked */
1523static void vino_set_scaling(struct vino_channel_settings *vcs,
1524 unsigned int w, unsigned int h)
1525{
1526 unsigned int x, y, curw, curh, d;
1527
1528 x = vcs->clipping.left;
1529 y = vcs->clipping.top;
1530 curw = vcs->clipping.right - vcs->clipping.left;
1531 curh = vcs->clipping.bottom - vcs->clipping.top;
1532
1533 d = max(curw / w, curh / h);
1534
1535 dprintk("scaling w: %d, h: %d, curw: %d, curh: %d, d: %d\n",
1536 w, h, curw, curh, d);
1537
1538 if (d < 1) {
1539 d = 1;
Ladislav Michla637a112005-09-01 15:07:34 +00001540 } else if (d > 8) {
Ralf Baechled203a7e2005-09-06 15:19:37 -07001541 d = 8;
1542 }
1543
1544 vcs->decimation = d;
1545 vino_set_clipping(vcs, x, y, w * d, h * d);
1546
1547 dprintk("scaling %d, %d, %d, %d / %d - %d\n", vcs->clipping.left,
1548 vcs->clipping.top, vcs->clipping.right, vcs->clipping.bottom,
1549 vcs->decimation, vcs->line_size);
1550}
1551
1552/* execute with input_lock locked */
Ladislav Michla637a112005-09-01 15:07:34 +00001553static inline void vino_set_default_scaling(struct vino_channel_settings *vcs)
Ralf Baechled203a7e2005-09-06 15:19:37 -07001554{
1555 vino_set_scaling(vcs, vcs->clipping.right - vcs->clipping.left,
1556 vcs->clipping.bottom - vcs->clipping.top);
1557}
1558
1559/* execute with input_lock locked */
1560static void vino_set_framerate(struct vino_channel_settings *vcs,
1561 unsigned int fps)
1562{
1563 unsigned int mask;
1564
1565 switch (vcs->data_norm) {
1566 case VINO_DATA_NORM_NTSC:
1567 case VINO_DATA_NORM_D1:
1568 fps = (unsigned int)(fps / 6) * 6; // FIXME: round!
1569
1570 if (fps < vino_data_norms[vcs->data_norm].fps_min)
1571 fps = vino_data_norms[vcs->data_norm].fps_min;
1572 if (fps > vino_data_norms[vcs->data_norm].fps_max)
1573 fps = vino_data_norms[vcs->data_norm].fps_max;
1574
1575 switch (fps) {
1576 case 6:
1577 mask = 0x003;
1578 break;
1579 case 12:
1580 mask = 0x0c3;
1581 break;
1582 case 18:
1583 mask = 0x333;
1584 break;
1585 case 24:
1586 mask = 0x3ff;
1587 break;
1588 case 30:
1589 mask = 0xfff;
1590 break;
1591 default:
1592 mask = VINO_FRAMERT_FULL;
1593 }
1594 vcs->framert_reg = VINO_FRAMERT_RT(mask);
1595 break;
1596 case VINO_DATA_NORM_PAL:
1597 case VINO_DATA_NORM_SECAM:
1598 fps = (unsigned int)(fps / 5) * 5; // FIXME: round!
1599
1600 if (fps < vino_data_norms[vcs->data_norm].fps_min)
1601 fps = vino_data_norms[vcs->data_norm].fps_min;
1602 if (fps > vino_data_norms[vcs->data_norm].fps_max)
1603 fps = vino_data_norms[vcs->data_norm].fps_max;
1604
1605 switch (fps) {
1606 case 5:
1607 mask = 0x003;
1608 break;
1609 case 10:
1610 mask = 0x0c3;
1611 break;
1612 case 15:
1613 mask = 0x333;
1614 break;
1615 case 20:
1616 mask = 0x0ff;
1617 break;
1618 case 25:
1619 mask = 0x3ff;
1620 break;
1621 default:
1622 mask = VINO_FRAMERT_FULL;
1623 }
1624 vcs->framert_reg = VINO_FRAMERT_RT(mask) | VINO_FRAMERT_PAL;
1625 break;
1626 }
1627
1628 vcs->fps = fps;
1629}
1630
1631/* execute with input_lock locked */
Ladislav Michla637a112005-09-01 15:07:34 +00001632static inline void vino_set_default_framerate(struct
1633 vino_channel_settings *vcs)
Ralf Baechled203a7e2005-09-06 15:19:37 -07001634{
1635 vino_set_framerate(vcs, vino_data_norms[vcs->data_norm].fps_max);
1636}
1637
1638/*
1639 * Prepare VINO for DMA transfer...
1640 * (execute only with vino_lock and input_lock locked)
1641 */
1642static int vino_dma_setup(struct vino_channel_settings *vcs,
1643 struct vino_framebuffer *fb)
1644{
1645 u32 ctrl, intr;
1646 struct sgi_vino_channel *ch;
1647 const struct vino_data_norm *norm;
1648
1649 dprintk("vino_dma_setup():\n");
1650
1651 vcs->field = 0;
1652 fb->frame_counter = 0;
1653
1654 ch = (vcs->channel == VINO_CHANNEL_A) ? &vino->a : &vino->b;
1655 norm = &vino_data_norms[vcs->data_norm];
1656
1657 ch->page_index = 0;
1658 ch->line_count = 0;
1659
1660 /* VINO line size register is set 8 bytes less than actual */
1661 ch->line_size = vcs->line_size - 8;
1662
1663 /* let VINO know where to transfer data */
1664 ch->start_desc_tbl = fb->desc_table.dma;
1665 ch->next_4_desc = fb->desc_table.dma;
1666
1667 /* give vino time to fetch the first four descriptors, 5 usec
1668 * should be more than enough time */
1669 udelay(VINO_DESC_FETCH_DELAY);
1670
Ladislav Michla637a112005-09-01 15:07:34 +00001671 dprintk("vino_dma_setup(): start desc = %08x, next 4 desc = %08x\n",
1672 ch->start_desc_tbl, ch->next_4_desc);
1673
Ralf Baechled203a7e2005-09-06 15:19:37 -07001674 /* set the alpha register */
1675 ch->alpha = vcs->alpha;
1676
1677 /* set clipping registers */
1678 ch->clip_start = VINO_CLIP_ODD(norm->odd.top + vcs->clipping.top / 2) |
1679 VINO_CLIP_EVEN(norm->even.top +
1680 vcs->clipping.top / 2) |
1681 VINO_CLIP_X(vcs->clipping.left);
1682 ch->clip_end = VINO_CLIP_ODD(norm->odd.top +
1683 vcs->clipping.bottom / 2 - 1) |
1684 VINO_CLIP_EVEN(norm->even.top +
1685 vcs->clipping.bottom / 2 - 1) |
1686 VINO_CLIP_X(vcs->clipping.right);
Ralf Baechled203a7e2005-09-06 15:19:37 -07001687
1688 /* set the size of actual content in the buffer (DECIMATION !) */
1689 fb->data_size = ((vcs->clipping.right - vcs->clipping.left) /
1690 vcs->decimation) *
1691 ((vcs->clipping.bottom - vcs->clipping.top) /
1692 vcs->decimation) *
1693 vino_data_formats[vcs->data_format].bpp;
1694
1695 ch->frame_rate = vcs->framert_reg;
1696
1697 ctrl = vino->control;
1698 intr = vino->intr_status;
1699
1700 if (vcs->channel == VINO_CHANNEL_A) {
1701 /* All interrupt conditions for this channel was cleared
1702 * so clear the interrupt status register and enable
1703 * interrupts */
1704 intr &= ~VINO_INTSTAT_A;
1705 ctrl |= VINO_CTRL_A_INT;
1706
1707 /* enable synchronization */
1708 ctrl |= VINO_CTRL_A_SYNC_ENBL;
1709
1710 /* enable frame assembly */
1711 ctrl |= VINO_CTRL_A_INTERLEAVE_ENBL;
1712
1713 /* set decimation used */
1714 if (vcs->decimation < 2)
1715 ctrl &= ~VINO_CTRL_A_DEC_ENBL;
1716 else {
1717 ctrl |= VINO_CTRL_A_DEC_ENBL;
1718 ctrl &= ~VINO_CTRL_A_DEC_SCALE_MASK;
1719 ctrl |= (vcs->decimation - 1) <<
1720 VINO_CTRL_A_DEC_SCALE_SHIFT;
1721 }
1722
1723 /* select input interface */
1724 if (vcs->input == VINO_INPUT_D1)
1725 ctrl |= VINO_CTRL_A_SELECT;
1726 else
1727 ctrl &= ~VINO_CTRL_A_SELECT;
1728
1729 /* palette */
1730 ctrl &= ~(VINO_CTRL_A_LUMA_ONLY | VINO_CTRL_A_RGB |
1731 VINO_CTRL_A_DITHER);
1732 } else {
1733 intr &= ~VINO_INTSTAT_B;
1734 ctrl |= VINO_CTRL_B_INT;
1735
1736 ctrl |= VINO_CTRL_B_SYNC_ENBL;
1737 ctrl |= VINO_CTRL_B_INTERLEAVE_ENBL;
1738
1739 if (vcs->decimation < 2)
1740 ctrl &= ~VINO_CTRL_B_DEC_ENBL;
1741 else {
1742 ctrl |= VINO_CTRL_B_DEC_ENBL;
1743 ctrl &= ~VINO_CTRL_B_DEC_SCALE_MASK;
1744 ctrl |= (vcs->decimation - 1) <<
1745 VINO_CTRL_B_DEC_SCALE_SHIFT;
1746
1747 }
1748 if (vcs->input == VINO_INPUT_D1)
1749 ctrl |= VINO_CTRL_B_SELECT;
1750 else
1751 ctrl &= ~VINO_CTRL_B_SELECT;
1752
1753 ctrl &= ~(VINO_CTRL_B_LUMA_ONLY | VINO_CTRL_B_RGB |
1754 VINO_CTRL_B_DITHER);
1755 }
1756
1757 /* set palette */
1758 fb->data_format = vcs->data_format;
1759
1760 switch (vcs->data_format) {
1761 case VINO_DATA_FMT_GREY:
1762 ctrl |= (vcs->channel == VINO_CHANNEL_A) ?
1763 VINO_CTRL_A_LUMA_ONLY : VINO_CTRL_B_LUMA_ONLY;
1764 break;
1765 case VINO_DATA_FMT_RGB32:
1766 ctrl |= (vcs->channel == VINO_CHANNEL_A) ?
1767 VINO_CTRL_A_RGB : VINO_CTRL_B_RGB;
1768 break;
1769 case VINO_DATA_FMT_YUV:
1770 /* nothing needs to be done */
1771 break;
1772 case VINO_DATA_FMT_RGB332:
1773 ctrl |= (vcs->channel == VINO_CHANNEL_A) ?
1774 VINO_CTRL_A_RGB | VINO_CTRL_A_DITHER :
1775 VINO_CTRL_B_RGB | VINO_CTRL_B_DITHER;
1776 break;
1777 }
1778
1779 vino->intr_status = intr;
1780 vino->control = ctrl;
1781
1782 return 0;
1783}
1784
1785/* (execute only with vino_lock locked) */
Ladislav Michla637a112005-09-01 15:07:34 +00001786static inline void vino_dma_start(struct vino_channel_settings *vcs)
Ralf Baechled203a7e2005-09-06 15:19:37 -07001787{
1788 u32 ctrl = vino->control;
1789
1790 dprintk("vino_dma_start():\n");
1791 ctrl |= (vcs->channel == VINO_CHANNEL_A) ?
1792 VINO_CTRL_A_DMA_ENBL : VINO_CTRL_B_DMA_ENBL;
1793 vino->control = ctrl;
1794}
1795
1796/* (execute only with vino_lock locked) */
Ladislav Michla637a112005-09-01 15:07:34 +00001797static inline void vino_dma_stop(struct vino_channel_settings *vcs)
Ralf Baechled203a7e2005-09-06 15:19:37 -07001798{
1799 u32 ctrl = vino->control;
1800
1801 ctrl &= (vcs->channel == VINO_CHANNEL_A) ?
1802 ~VINO_CTRL_A_DMA_ENBL : ~VINO_CTRL_B_DMA_ENBL;
Ladislav Michla637a112005-09-01 15:07:34 +00001803 ctrl &= (vcs->channel == VINO_CHANNEL_A) ?
1804 ~VINO_CTRL_A_INT : ~VINO_CTRL_B_INT;
Ralf Baechled203a7e2005-09-06 15:19:37 -07001805 vino->control = ctrl;
1806 dprintk("vino_dma_stop():\n");
1807}
1808
1809/*
1810 * Load dummy page to descriptor registers. This prevents generating of
1811 * spurious interrupts. (execute only with vino_lock locked)
1812 */
1813static void vino_clear_interrupt(struct vino_channel_settings *vcs)
1814{
1815 struct sgi_vino_channel *ch;
1816
1817 ch = (vcs->channel == VINO_CHANNEL_A) ? &vino->a : &vino->b;
1818
1819 ch->page_index = 0;
1820 ch->line_count = 0;
1821
1822 ch->start_desc_tbl = vino_drvdata->dummy_desc_table.dma;
1823 ch->next_4_desc = vino_drvdata->dummy_desc_table.dma;
1824
1825 udelay(VINO_DESC_FETCH_DELAY);
1826 dprintk("channel %c clear interrupt condition\n",
1827 (vcs->channel == VINO_CHANNEL_A) ? 'A':'B');
1828}
1829
1830static int vino_capture(struct vino_channel_settings *vcs,
1831 struct vino_framebuffer *fb)
1832{
1833 int err = 0;
1834 unsigned long flags, flags2;
1835
1836 spin_lock_irqsave(&fb->state_lock, flags);
1837
1838 if (fb->state == VINO_FRAMEBUFFER_IN_USE)
1839 err = -EBUSY;
1840 fb->state = VINO_FRAMEBUFFER_IN_USE;
1841
1842 spin_unlock_irqrestore(&fb->state_lock, flags);
1843
1844 if (err)
1845 return err;
1846
1847 spin_lock_irqsave(&vino_drvdata->vino_lock, flags);
1848 spin_lock_irqsave(&vino_drvdata->input_lock, flags2);
1849
1850 vino_dma_setup(vcs, fb);
1851 vino_dma_start(vcs);
1852
1853 spin_unlock_irqrestore(&vino_drvdata->input_lock, flags2);
1854 spin_unlock_irqrestore(&vino_drvdata->vino_lock, flags);
1855
1856 return err;
1857}
1858
1859static
1860struct vino_framebuffer *vino_capture_enqueue(struct
1861 vino_channel_settings *vcs,
1862 unsigned int index)
1863{
1864 struct vino_framebuffer *fb;
1865 unsigned long flags;
1866
1867 dprintk("vino_capture_enqueue():\n");
1868
1869 spin_lock_irqsave(&vcs->capture_lock, flags);
1870
1871 fb = vino_queue_add(&vcs->fb_queue, index);
1872 if (fb == NULL) {
1873 dprintk("vino_capture_enqueue(): vino_queue_add() failed, "
1874 "queue full?\n");
1875 goto out;
1876 }
1877out:
1878 spin_unlock_irqrestore(&vcs->capture_lock, flags);
1879
1880 return fb;
1881}
1882
1883static int vino_capture_next(struct vino_channel_settings *vcs, int start)
1884{
1885 struct vino_framebuffer *fb;
1886 unsigned int incoming, id;
1887 int err = 0;
Ladislav Michla637a112005-09-01 15:07:34 +00001888 unsigned long flags;
Ralf Baechled203a7e2005-09-06 15:19:37 -07001889
1890 dprintk("vino_capture_next():\n");
1891
1892 spin_lock_irqsave(&vcs->capture_lock, flags);
1893
1894 if (start) {
1895 /* start capture only if capture isn't in progress already */
1896 if (vcs->capturing) {
1897 spin_unlock_irqrestore(&vcs->capture_lock, flags);
1898 return 0;
1899 }
1900
1901 } else {
1902 /* capture next frame:
1903 * stop capture if capturing is not set */
1904 if (!vcs->capturing) {
1905 spin_unlock_irqrestore(&vcs->capture_lock, flags);
1906 return 0;
1907 }
1908 }
1909
1910 err = vino_queue_get_incoming(&vcs->fb_queue, &incoming);
1911 if (err) {
1912 dprintk("vino_capture_next(): vino_queue_get_incoming() "
1913 "failed\n");
1914 err = -EINVAL;
1915 goto out;
1916 }
1917 if (incoming == 0) {
1918 dprintk("vino_capture_next(): no buffers available\n");
1919 goto out;
1920 }
1921
1922 fb = vino_queue_peek(&vcs->fb_queue, &id);
1923 if (fb == NULL) {
1924 dprintk("vino_capture_next(): vino_queue_peek() failed\n");
1925 err = -EINVAL;
1926 goto out;
1927 }
1928
Ralf Baechled203a7e2005-09-06 15:19:37 -07001929 if (start) {
1930 vcs->capturing = 1;
1931 }
1932
1933 spin_unlock_irqrestore(&vcs->capture_lock, flags);
1934
1935 err = vino_capture(vcs, fb);
1936
1937 return err;
1938
1939out:
1940 vcs->capturing = 0;
1941 spin_unlock_irqrestore(&vcs->capture_lock, flags);
1942
1943 return err;
1944}
1945
Ladislav Michla637a112005-09-01 15:07:34 +00001946static inline int vino_is_capturing(struct vino_channel_settings *vcs)
Ralf Baechled203a7e2005-09-06 15:19:37 -07001947{
1948 int ret;
1949 unsigned long flags;
1950
1951 spin_lock_irqsave(&vcs->capture_lock, flags);
1952
1953 ret = vcs->capturing;
1954
1955 spin_unlock_irqrestore(&vcs->capture_lock, flags);
1956
1957 return ret;
1958}
1959
1960/* waits until a frame is captured */
1961static int vino_wait_for_frame(struct vino_channel_settings *vcs)
1962{
1963 wait_queue_t wait;
1964 int err = 0;
1965
1966 dprintk("vino_wait_for_frame():\n");
1967
1968 init_waitqueue_entry(&wait, current);
1969 /* add ourselves into wait queue */
1970 add_wait_queue(&vcs->fb_queue.frame_wait_queue, &wait);
Ralf Baechled203a7e2005-09-06 15:19:37 -07001971
1972 /* to ensure that schedule_timeout will return immediately
Robert P. J. Dayf3a43d32007-07-16 10:46:42 -03001973 * if VINO interrupt was triggered meanwhile */
Mauro Carvalho Chehab818ca472007-07-17 16:29:07 -03001974 schedule_timeout_interruptible(msecs_to_jiffies(100));
Ralf Baechled203a7e2005-09-06 15:19:37 -07001975
1976 if (signal_pending(current))
1977 err = -EINTR;
1978
1979 remove_wait_queue(&vcs->fb_queue.frame_wait_queue, &wait);
1980
1981 dprintk("vino_wait_for_frame(): waiting for frame %s\n",
1982 err ? "failed" : "ok");
1983
1984 return err;
1985}
1986
1987/* the function assumes that PAGE_SIZE % 4 == 0 */
1988static void vino_convert_to_rgba(struct vino_framebuffer *fb) {
1989 unsigned char *pageptr;
1990 unsigned int page, i;
1991 unsigned char a;
1992
1993 for (page = 0; page < fb->desc_table.page_count; page++) {
1994 pageptr = (unsigned char *)fb->desc_table.virtual[page];
1995
1996 for (i = 0; i < PAGE_SIZE; i += 4) {
1997 a = pageptr[0];
1998 pageptr[0] = pageptr[3];
1999 pageptr[1] = pageptr[2];
2000 pageptr[2] = pageptr[1];
2001 pageptr[3] = a;
2002 pageptr += 4;
2003 }
2004 }
2005}
2006
2007/* checks if the buffer is in correct state and syncs data */
2008static int vino_check_buffer(struct vino_channel_settings *vcs,
2009 struct vino_framebuffer *fb)
2010{
2011 int err = 0;
2012 unsigned long flags;
2013
2014 dprintk("vino_check_buffer():\n");
2015
2016 spin_lock_irqsave(&fb->state_lock, flags);
2017 switch (fb->state) {
2018 case VINO_FRAMEBUFFER_IN_USE:
2019 err = -EIO;
2020 break;
2021 case VINO_FRAMEBUFFER_READY:
2022 vino_sync_buffer(fb);
2023 fb->state = VINO_FRAMEBUFFER_UNUSED;
2024 break;
2025 default:
2026 err = -EINVAL;
2027 }
2028 spin_unlock_irqrestore(&fb->state_lock, flags);
2029
2030 if (!err) {
2031 if (vino_pixel_conversion
2032 && (fb->data_format == VINO_DATA_FMT_RGB32)) {
2033 vino_convert_to_rgba(fb);
2034 }
2035 } else if (err && (err != -EINVAL)) {
2036 dprintk("vino_check_buffer(): buffer not ready\n");
2037
2038 spin_lock_irqsave(&vino_drvdata->vino_lock, flags);
2039 vino_dma_stop(vcs);
2040 vino_clear_interrupt(vcs);
2041 spin_unlock_irqrestore(&vino_drvdata->vino_lock, flags);
2042 }
2043
2044 return err;
2045}
2046
2047/* forcefully terminates capture */
2048static void vino_capture_stop(struct vino_channel_settings *vcs)
2049{
2050 unsigned int incoming = 0, outgoing = 0, id;
2051 unsigned long flags, flags2;
2052
2053 dprintk("vino_capture_stop():\n");
2054
2055 spin_lock_irqsave(&vcs->capture_lock, flags);
Ladislav Michla637a112005-09-01 15:07:34 +00002056
Ralf Baechled203a7e2005-09-06 15:19:37 -07002057 /* unset capturing to stop queue processing */
2058 vcs->capturing = 0;
2059
2060 spin_lock_irqsave(&vino_drvdata->vino_lock, flags2);
2061
2062 vino_dma_stop(vcs);
2063 vino_clear_interrupt(vcs);
2064
2065 spin_unlock_irqrestore(&vino_drvdata->vino_lock, flags2);
2066
2067 /* remove all items from the queue */
2068 if (vino_queue_get_incoming(&vcs->fb_queue, &incoming)) {
2069 dprintk("vino_capture_stop(): "
2070 "vino_queue_get_incoming() failed\n");
2071 goto out;
2072 }
2073 while (incoming > 0) {
2074 vino_queue_transfer(&vcs->fb_queue);
2075
2076 if (vino_queue_get_incoming(&vcs->fb_queue, &incoming)) {
2077 dprintk("vino_capture_stop(): "
2078 "vino_queue_get_incoming() failed\n");
2079 goto out;
2080 }
2081 }
2082
2083 if (vino_queue_get_outgoing(&vcs->fb_queue, &outgoing)) {
2084 dprintk("vino_capture_stop(): "
2085 "vino_queue_get_outgoing() failed\n");
2086 goto out;
2087 }
2088 while (outgoing > 0) {
2089 vino_queue_remove(&vcs->fb_queue, &id);
2090
2091 if (vino_queue_get_outgoing(&vcs->fb_queue, &outgoing)) {
2092 dprintk("vino_capture_stop(): "
2093 "vino_queue_get_outgoing() failed\n");
2094 goto out;
2095 }
2096 }
2097
2098out:
2099 spin_unlock_irqrestore(&vcs->capture_lock, flags);
2100}
2101
Ladislav Michla637a112005-09-01 15:07:34 +00002102#if 0
Ralf Baechled203a7e2005-09-06 15:19:37 -07002103static int vino_capture_failed(struct vino_channel_settings *vcs)
2104{
2105 struct vino_framebuffer *fb;
2106 unsigned long flags;
2107 unsigned int i;
2108 int ret;
2109
2110 dprintk("vino_capture_failed():\n");
2111
2112 spin_lock_irqsave(&vino_drvdata->vino_lock, flags);
2113
2114 vino_dma_stop(vcs);
2115 vino_clear_interrupt(vcs);
2116
2117 spin_unlock_irqrestore(&vino_drvdata->vino_lock, flags);
2118
2119 ret = vino_queue_get_incoming(&vcs->fb_queue, &i);
2120 if (ret == VINO_QUEUE_ERROR) {
2121 dprintk("vino_queue_get_incoming() failed\n");
2122 return -EINVAL;
2123 }
2124 if (i == 0) {
2125 /* no buffers to process */
2126 return 0;
2127 }
2128
2129 fb = vino_queue_peek(&vcs->fb_queue, &i);
2130 if (fb == NULL) {
2131 dprintk("vino_queue_peek() failed\n");
2132 return -EINVAL;
2133 }
2134
2135 spin_lock_irqsave(&fb->state_lock, flags);
2136 if (fb->state == VINO_FRAMEBUFFER_IN_USE) {
2137 fb->state = VINO_FRAMEBUFFER_UNUSED;
2138 vino_queue_transfer(&vcs->fb_queue);
2139 vino_queue_remove(&vcs->fb_queue, &i);
2140 /* we should actually discard the newest frame,
2141 * but who cares ... */
2142 }
2143 spin_unlock_irqrestore(&fb->state_lock, flags);
2144
2145 return 0;
2146}
Ladislav Michla637a112005-09-01 15:07:34 +00002147#endif
Ralf Baechled203a7e2005-09-06 15:19:37 -07002148
Ladislav Michla637a112005-09-01 15:07:34 +00002149static void vino_skip_frame(struct vino_channel_settings *vcs)
2150{
2151 struct vino_framebuffer *fb;
2152 unsigned long flags;
2153 unsigned int id;
2154
2155 spin_lock_irqsave(&vcs->capture_lock, flags);
2156 fb = vino_queue_peek(&vcs->fb_queue, &id);
2157 if (!fb) {
2158 spin_unlock_irqrestore(&vcs->capture_lock, flags);
2159 dprintk("vino_skip_frame(): vino_queue_peek() failed!\n");
2160 return;
2161 }
2162 spin_unlock_irqrestore(&vcs->capture_lock, flags);
2163
2164 spin_lock_irqsave(&fb->state_lock, flags);
2165 fb->state = VINO_FRAMEBUFFER_UNUSED;
2166 spin_unlock_irqrestore(&fb->state_lock, flags);
2167
2168 vino_capture_next(vcs, 0);
2169}
2170
2171static void vino_frame_done(struct vino_channel_settings *vcs)
Ralf Baechled203a7e2005-09-06 15:19:37 -07002172{
2173 struct vino_framebuffer *fb;
2174 unsigned long flags;
2175
2176 spin_lock_irqsave(&vcs->capture_lock, flags);
2177 fb = vino_queue_transfer(&vcs->fb_queue);
2178 if (!fb) {
2179 spin_unlock_irqrestore(&vcs->capture_lock, flags);
2180 dprintk("vino_frame_done(): vino_queue_transfer() failed!\n");
2181 return;
2182 }
2183 spin_unlock_irqrestore(&vcs->capture_lock, flags);
2184
Ladislav Michla637a112005-09-01 15:07:34 +00002185 fb->frame_counter = vcs->int_data.frame_counter;
2186 memcpy(&fb->timestamp, &vcs->int_data.timestamp,
2187 sizeof(struct timeval));
Ralf Baechled203a7e2005-09-06 15:19:37 -07002188
2189 spin_lock_irqsave(&fb->state_lock, flags);
2190 if (fb->state == VINO_FRAMEBUFFER_IN_USE)
2191 fb->state = VINO_FRAMEBUFFER_READY;
2192 spin_unlock_irqrestore(&fb->state_lock, flags);
2193
2194 wake_up(&vcs->fb_queue.frame_wait_queue);
2195
2196 vino_capture_next(vcs, 0);
2197}
2198
Ladislav Michla637a112005-09-01 15:07:34 +00002199static void vino_capture_tasklet(unsigned long channel) {
2200 struct vino_channel_settings *vcs;
2201
2202 vcs = (channel == VINO_CHANNEL_A)
2203 ? &vino_drvdata->a : &vino_drvdata->b;
2204
2205 if (vcs->int_data.skip)
2206 vcs->int_data.skip_count++;
2207
2208 if (vcs->int_data.skip && (vcs->int_data.skip_count
2209 <= VINO_MAX_FRAME_SKIP_COUNT)) {
2210 vino_skip_frame(vcs);
2211 } else {
2212 vcs->int_data.skip_count = 0;
2213 vino_frame_done(vcs);
2214 }
2215}
2216
David Howells7d12e782006-10-05 14:55:46 +01002217static irqreturn_t vino_interrupt(int irq, void *dev_id)
Ralf Baechled203a7e2005-09-06 15:19:37 -07002218{
Ladislav Michla637a112005-09-01 15:07:34 +00002219 u32 ctrl, intr;
Ralf Baechled203a7e2005-09-06 15:19:37 -07002220 unsigned int fc_a, fc_b;
Ladislav Michla637a112005-09-01 15:07:34 +00002221 int handled_a = 0, skip_a = 0, done_a = 0;
2222 int handled_b = 0, skip_b = 0, done_b = 0;
2223
2224#ifdef VINO_DEBUG_INT
2225 int loop = 0;
2226 unsigned int line_count = vino->a.line_count,
2227 page_index = vino->a.page_index,
2228 field_counter = vino->a.field_counter,
2229 start_desc_tbl = vino->a.start_desc_tbl,
2230 next_4_desc = vino->a.next_4_desc;
2231 unsigned int line_count_2,
2232 page_index_2,
2233 field_counter_2,
2234 start_desc_tbl_2,
2235 next_4_desc_2;
2236#endif
Ralf Baechled203a7e2005-09-06 15:19:37 -07002237
2238 spin_lock(&vino_drvdata->vino_lock);
2239
Ladislav Michla637a112005-09-01 15:07:34 +00002240 while ((intr = vino->intr_status)) {
2241 fc_a = vino->a.field_counter >> 1;
2242 fc_b = vino->b.field_counter >> 1;
Ralf Baechled203a7e2005-09-06 15:19:37 -07002243
Ladislav Michla637a112005-09-01 15:07:34 +00002244 /* handle error-interrupts in some special way ?
2245 * --> skips frames */
2246 if (intr & VINO_INTSTAT_A) {
2247 if (intr & VINO_INTSTAT_A_EOF) {
2248 vino_drvdata->a.field++;
2249 if (vino_drvdata->a.field > 1) {
2250 vino_dma_stop(&vino_drvdata->a);
2251 vino_clear_interrupt(&vino_drvdata->a);
2252 vino_drvdata->a.field = 0;
2253 done_a = 1;
2254 } else {
2255 if (vino->a.page_index
2256 != vino_drvdata->a.line_size) {
2257 vino->a.line_count = 0;
2258 vino->a.page_index =
2259 vino_drvdata->
2260 a.line_size;
2261 vino->a.next_4_desc =
2262 vino->a.start_desc_tbl;
2263 }
2264 }
2265 dprintk("channel A end-of-field "
2266 "interrupt: %04x\n", intr);
2267 } else {
Ralf Baechled203a7e2005-09-06 15:19:37 -07002268 vino_dma_stop(&vino_drvdata->a);
2269 vino_clear_interrupt(&vino_drvdata->a);
2270 vino_drvdata->a.field = 0;
Ladislav Michla637a112005-09-01 15:07:34 +00002271 skip_a = 1;
2272 dprintk("channel A error interrupt: %04x\n",
2273 intr);
Ralf Baechled203a7e2005-09-06 15:19:37 -07002274 }
Ladislav Michla637a112005-09-01 15:07:34 +00002275
2276#ifdef VINO_DEBUG_INT
2277 line_count_2 = vino->a.line_count;
2278 page_index_2 = vino->a.page_index;
2279 field_counter_2 = vino->a.field_counter;
2280 start_desc_tbl_2 = vino->a.start_desc_tbl;
2281 next_4_desc_2 = vino->a.next_4_desc;
2282
2283 printk("intr = %04x, loop = %d, field = %d\n",
2284 intr, loop, vino_drvdata->a.field);
2285 printk("1- line count = %04d, page index = %04d, "
2286 "start = %08x, next = %08x\n"
2287 " fieldc = %d, framec = %d\n",
2288 line_count, page_index, start_desc_tbl,
2289 next_4_desc, field_counter, fc_a);
2290 printk("12-line count = %04d, page index = %04d, "
2291 " start = %08x, next = %08x\n",
2292 line_count_2, page_index_2, start_desc_tbl_2,
2293 next_4_desc_2);
2294
2295 if (done_a)
2296 printk("\n");
2297#endif
Ralf Baechled203a7e2005-09-06 15:19:37 -07002298 }
Ladislav Michla637a112005-09-01 15:07:34 +00002299
2300 if (intr & VINO_INTSTAT_B) {
2301 if (intr & VINO_INTSTAT_B_EOF) {
2302 vino_drvdata->b.field++;
2303 if (vino_drvdata->b.field > 1) {
2304 vino_dma_stop(&vino_drvdata->b);
2305 vino_clear_interrupt(&vino_drvdata->b);
2306 vino_drvdata->b.field = 0;
2307 done_b = 1;
2308 }
2309 dprintk("channel B end-of-field "
2310 "interrupt: %04x\n", intr);
2311 } else {
Ralf Baechled203a7e2005-09-06 15:19:37 -07002312 vino_dma_stop(&vino_drvdata->b);
2313 vino_clear_interrupt(&vino_drvdata->b);
2314 vino_drvdata->b.field = 0;
Ladislav Michla637a112005-09-01 15:07:34 +00002315 skip_b = 1;
2316 dprintk("channel B error interrupt: %04x\n",
2317 intr);
Ralf Baechled203a7e2005-09-06 15:19:37 -07002318 }
Ralf Baechled203a7e2005-09-06 15:19:37 -07002319 }
Ralf Baechled203a7e2005-09-06 15:19:37 -07002320
Ladislav Michla637a112005-09-01 15:07:34 +00002321 /* Always remember to clear interrupt status.
2322 * Disable VINO interrupts while we do this. */
2323 ctrl = vino->control;
2324 vino->control = ctrl & ~(VINO_CTRL_A_INT | VINO_CTRL_B_INT);
2325 vino->intr_status = ~intr;
2326 vino->control = ctrl;
2327
2328 spin_unlock(&vino_drvdata->vino_lock);
2329
2330 if ((!handled_a) && (done_a || skip_a)) {
2331 if (!skip_a) {
2332 do_gettimeofday(&vino_drvdata->
2333 a.int_data.timestamp);
2334 vino_drvdata->a.int_data.frame_counter = fc_a;
2335 }
2336 vino_drvdata->a.int_data.skip = skip_a;
2337
2338 dprintk("channel A %s, interrupt: %d\n",
2339 skip_a ? "skipping frame" : "frame done",
2340 intr);
2341 tasklet_hi_schedule(&vino_tasklet_a);
2342 handled_a = 1;
2343 }
2344
2345 if ((!handled_b) && (done_b || skip_b)) {
2346 if (!skip_b) {
2347 do_gettimeofday(&vino_drvdata->
2348 b.int_data.timestamp);
2349 vino_drvdata->b.int_data.frame_counter = fc_b;
2350 }
2351 vino_drvdata->b.int_data.skip = skip_b;
2352
2353 dprintk("channel B %s, interrupt: %d\n",
2354 skip_b ? "skipping frame" : "frame done",
2355 intr);
2356 tasklet_hi_schedule(&vino_tasklet_b);
2357 handled_b = 1;
2358 }
2359
2360#ifdef VINO_DEBUG_INT
2361 loop++;
2362#endif
2363 spin_lock(&vino_drvdata->vino_lock);
2364 }
Ralf Baechled203a7e2005-09-06 15:19:37 -07002365
2366 spin_unlock(&vino_drvdata->vino_lock);
2367
Ralf Baechled203a7e2005-09-06 15:19:37 -07002368 return IRQ_HANDLED;
2369}
2370
2371/* VINO video input management */
2372
2373static int vino_get_saa7191_input(int input)
2374{
2375 switch (input) {
2376 case VINO_INPUT_COMPOSITE:
2377 return SAA7191_INPUT_COMPOSITE;
2378 case VINO_INPUT_SVIDEO:
2379 return SAA7191_INPUT_SVIDEO;
2380 default:
2381 printk(KERN_ERR "VINO: vino_get_saa7191_input(): "
2382 "invalid input!\n");
2383 return -1;
2384 }
2385}
2386
Ralf Baechled203a7e2005-09-06 15:19:37 -07002387/* execute with input_lock locked */
2388static int vino_is_input_owner(struct vino_channel_settings *vcs)
2389{
2390 switch(vcs->input) {
2391 case VINO_INPUT_COMPOSITE:
2392 case VINO_INPUT_SVIDEO:
Hans Verkuil48f4dac2009-02-18 19:18:26 -03002393 return vino_drvdata->decoder_owner == vcs->channel;
Ralf Baechled203a7e2005-09-06 15:19:37 -07002394 case VINO_INPUT_D1:
Hans Verkuil48f4dac2009-02-18 19:18:26 -03002395 return vino_drvdata->camera_owner == vcs->channel;
Ralf Baechled203a7e2005-09-06 15:19:37 -07002396 default:
2397 return 0;
2398 }
2399}
2400
2401static int vino_acquire_input(struct vino_channel_settings *vcs)
2402{
Ladislav Michla637a112005-09-01 15:07:34 +00002403 unsigned long flags;
Ralf Baechled203a7e2005-09-06 15:19:37 -07002404 int ret = 0;
2405
2406 dprintk("vino_acquire_input():\n");
2407
Ladislav Michla637a112005-09-01 15:07:34 +00002408 spin_lock_irqsave(&vino_drvdata->input_lock, flags);
Ralf Baechled203a7e2005-09-06 15:19:37 -07002409
2410 /* First try D1 and then SAA7191 */
Hans Verkuil48f4dac2009-02-18 19:18:26 -03002411 if (vino_drvdata->camera
2412 && (vino_drvdata->camera_owner == VINO_NO_CHANNEL)) {
2413 vino_drvdata->camera_owner = vcs->channel;
Ralf Baechled203a7e2005-09-06 15:19:37 -07002414 vcs->input = VINO_INPUT_D1;
2415 vcs->data_norm = VINO_DATA_NORM_D1;
Hans Verkuil48f4dac2009-02-18 19:18:26 -03002416 } else if (vino_drvdata->decoder
2417 && (vino_drvdata->decoder_owner == VINO_NO_CHANNEL)) {
Hans Verkuilcf4e9482009-02-27 09:05:10 -03002418 int input;
2419 int data_norm;
2420 v4l2_std_id norm;
2421 struct v4l2_routing route = { 0, 0 };
Ralf Baechled203a7e2005-09-06 15:19:37 -07002422
Ladislav Michla637a112005-09-01 15:07:34 +00002423 input = VINO_INPUT_COMPOSITE;
2424
Hans Verkuilcf4e9482009-02-27 09:05:10 -03002425 route.input = vino_get_saa7191_input(input);
Hans Verkuil48f4dac2009-02-18 19:18:26 -03002426 ret = decoder_call(video, s_routing, &route);
Ladislav Michla637a112005-09-01 15:07:34 +00002427 if (ret) {
2428 ret = -EINVAL;
2429 goto out;
2430 }
2431
2432 spin_unlock_irqrestore(&vino_drvdata->input_lock, flags);
2433
2434 /* Don't hold spinlocks while auto-detecting norm
2435 * as it may take a while... */
2436
Hans Verkuil48f4dac2009-02-18 19:18:26 -03002437 ret = decoder_call(video, querystd, &norm);
Hans Verkuilcf4e9482009-02-27 09:05:10 -03002438 if (!ret) {
2439 for (data_norm = 0; data_norm < 3; data_norm++) {
2440 if (vino_data_norms[data_norm].std & norm)
2441 break;
2442 }
2443 if (data_norm == 3)
2444 data_norm = VINO_DATA_NORM_PAL;
Hans Verkuil48f4dac2009-02-18 19:18:26 -03002445 ret = decoder_call(tuner, s_std, norm);
Ladislav Michla637a112005-09-01 15:07:34 +00002446 }
2447
2448 spin_lock_irqsave(&vino_drvdata->input_lock, flags);
2449
2450 if (ret) {
2451 ret = -EINVAL;
2452 goto out;
2453 }
2454
Hans Verkuil48f4dac2009-02-18 19:18:26 -03002455 vino_drvdata->decoder_owner = vcs->channel;
Ralf Baechled203a7e2005-09-06 15:19:37 -07002456
Ladislav Michla637a112005-09-01 15:07:34 +00002457 vcs->input = input;
2458 vcs->data_norm = data_norm;
Ralf Baechled203a7e2005-09-06 15:19:37 -07002459 } else {
2460 vcs->input = (vcs->channel == VINO_CHANNEL_A) ?
2461 vino_drvdata->b.input : vino_drvdata->a.input;
2462 vcs->data_norm = (vcs->channel == VINO_CHANNEL_A) ?
2463 vino_drvdata->b.data_norm : vino_drvdata->a.data_norm;
2464 }
2465
2466 if (vcs->input == VINO_INPUT_NONE) {
2467 ret = -ENODEV;
2468 goto out;
2469 }
2470
Ladislav Michla637a112005-09-01 15:07:34 +00002471 vino_set_default_clipping(vcs);
2472 vino_set_default_scaling(vcs);
2473 vino_set_default_framerate(vcs);
Ralf Baechled203a7e2005-09-06 15:19:37 -07002474
2475 dprintk("vino_acquire_input(): %s\n", vino_inputs[vcs->input].name);
2476
2477out:
Ladislav Michla637a112005-09-01 15:07:34 +00002478 spin_unlock_irqrestore(&vino_drvdata->input_lock, flags);
Ralf Baechled203a7e2005-09-06 15:19:37 -07002479
2480 return ret;
2481}
2482
2483static int vino_set_input(struct vino_channel_settings *vcs, int input)
2484{
2485 struct vino_channel_settings *vcs2 = (vcs->channel == VINO_CHANNEL_A) ?
2486 &vino_drvdata->b : &vino_drvdata->a;
Ladislav Michla637a112005-09-01 15:07:34 +00002487 unsigned long flags;
Ralf Baechled203a7e2005-09-06 15:19:37 -07002488 int ret = 0;
2489
2490 dprintk("vino_set_input():\n");
2491
Ladislav Michla637a112005-09-01 15:07:34 +00002492 spin_lock_irqsave(&vino_drvdata->input_lock, flags);
Ralf Baechled203a7e2005-09-06 15:19:37 -07002493
2494 if (vcs->input == input)
2495 goto out;
2496
Ladislav Michla637a112005-09-01 15:07:34 +00002497 switch (input) {
Ralf Baechled203a7e2005-09-06 15:19:37 -07002498 case VINO_INPUT_COMPOSITE:
2499 case VINO_INPUT_SVIDEO:
Hans Verkuil48f4dac2009-02-18 19:18:26 -03002500 if (!vino_drvdata->decoder) {
Ralf Baechled203a7e2005-09-06 15:19:37 -07002501 ret = -EINVAL;
2502 goto out;
2503 }
2504
Hans Verkuil48f4dac2009-02-18 19:18:26 -03002505 if (vino_drvdata->decoder_owner == VINO_NO_CHANNEL) {
2506 vino_drvdata->decoder_owner = vcs->channel;
Ralf Baechled203a7e2005-09-06 15:19:37 -07002507 }
2508
Hans Verkuil48f4dac2009-02-18 19:18:26 -03002509 if (vino_drvdata->decoder_owner == vcs->channel) {
Ladislav Michla637a112005-09-01 15:07:34 +00002510 int data_norm;
Hans Verkuilcf4e9482009-02-27 09:05:10 -03002511 v4l2_std_id norm;
2512 struct v4l2_routing route = { 0, 0 };
Ladislav Michla637a112005-09-01 15:07:34 +00002513
Hans Verkuilcf4e9482009-02-27 09:05:10 -03002514 route.input = vino_get_saa7191_input(input);
Hans Verkuil48f4dac2009-02-18 19:18:26 -03002515 ret = decoder_call(video, s_routing, &route);
Ladislav Michla637a112005-09-01 15:07:34 +00002516 if (ret) {
Hans Verkuil48f4dac2009-02-18 19:18:26 -03002517 vino_drvdata->decoder_owner = VINO_NO_CHANNEL;
Ladislav Michla637a112005-09-01 15:07:34 +00002518 ret = -EINVAL;
2519 goto out;
2520 }
2521
2522 spin_unlock_irqrestore(&vino_drvdata->input_lock, flags);
2523
2524 /* Don't hold spinlocks while auto-detecting norm
2525 * as it may take a while... */
2526
Hans Verkuil48f4dac2009-02-18 19:18:26 -03002527 ret = decoder_call(video, querystd, &norm);
Hans Verkuilcf4e9482009-02-27 09:05:10 -03002528 if (!ret) {
2529 for (data_norm = 0; data_norm < 3; data_norm++) {
2530 if (vino_data_norms[data_norm].std & norm)
2531 break;
2532 }
2533 if (data_norm == 3)
2534 data_norm = VINO_DATA_NORM_PAL;
Hans Verkuil48f4dac2009-02-18 19:18:26 -03002535 ret = decoder_call(tuner, s_std, norm);
Ladislav Michla637a112005-09-01 15:07:34 +00002536 }
2537
2538 spin_lock_irqsave(&vino_drvdata->input_lock, flags);
2539
2540 if (ret) {
Hans Verkuil48f4dac2009-02-18 19:18:26 -03002541 vino_drvdata->decoder_owner = VINO_NO_CHANNEL;
Ladislav Michla637a112005-09-01 15:07:34 +00002542 ret = -EINVAL;
2543 goto out;
2544 }
Ralf Baechled203a7e2005-09-06 15:19:37 -07002545
2546 vcs->input = input;
Ladislav Michla637a112005-09-01 15:07:34 +00002547 vcs->data_norm = data_norm;
Ralf Baechled203a7e2005-09-06 15:19:37 -07002548 } else {
Ladislav Michla637a112005-09-01 15:07:34 +00002549 if (input != vcs2->input) {
Ralf Baechled203a7e2005-09-06 15:19:37 -07002550 ret = -EBUSY;
2551 goto out;
2552 }
2553
2554 vcs->input = input;
2555 vcs->data_norm = vcs2->data_norm;
2556 }
2557
Hans Verkuil48f4dac2009-02-18 19:18:26 -03002558 if (vino_drvdata->camera_owner == vcs->channel) {
Ralf Baechled203a7e2005-09-06 15:19:37 -07002559 /* Transfer the ownership or release the input */
2560 if (vcs2->input == VINO_INPUT_D1) {
Hans Verkuil48f4dac2009-02-18 19:18:26 -03002561 vino_drvdata->camera_owner = vcs2->channel;
Ralf Baechled203a7e2005-09-06 15:19:37 -07002562 } else {
Hans Verkuil48f4dac2009-02-18 19:18:26 -03002563 vino_drvdata->camera_owner = VINO_NO_CHANNEL;
Ralf Baechled203a7e2005-09-06 15:19:37 -07002564 }
2565 }
2566 break;
2567 case VINO_INPUT_D1:
Hans Verkuil48f4dac2009-02-18 19:18:26 -03002568 if (!vino_drvdata->camera) {
Ralf Baechled203a7e2005-09-06 15:19:37 -07002569 ret = -EINVAL;
2570 goto out;
2571 }
2572
Hans Verkuil48f4dac2009-02-18 19:18:26 -03002573 if (vino_drvdata->camera_owner == VINO_NO_CHANNEL)
2574 vino_drvdata->camera_owner = vcs->channel;
Ralf Baechled203a7e2005-09-06 15:19:37 -07002575
Hans Verkuil48f4dac2009-02-18 19:18:26 -03002576 if (vino_drvdata->decoder_owner == vcs->channel) {
Ralf Baechled203a7e2005-09-06 15:19:37 -07002577 /* Transfer the ownership or release the input */
2578 if ((vcs2->input == VINO_INPUT_COMPOSITE) ||
2579 (vcs2->input == VINO_INPUT_SVIDEO)) {
Hans Verkuil48f4dac2009-02-18 19:18:26 -03002580 vino_drvdata->decoder_owner = vcs2->channel;
Ralf Baechled203a7e2005-09-06 15:19:37 -07002581 } else {
Hans Verkuil48f4dac2009-02-18 19:18:26 -03002582 vino_drvdata->decoder_owner = VINO_NO_CHANNEL;
Ralf Baechled203a7e2005-09-06 15:19:37 -07002583 }
2584 }
2585
2586 vcs->input = input;
2587 vcs->data_norm = VINO_DATA_NORM_D1;
2588 break;
2589 default:
2590 ret = -EINVAL;
2591 goto out;
2592 }
2593
2594 vino_set_default_clipping(vcs);
Ladislav Michla637a112005-09-01 15:07:34 +00002595 vino_set_default_scaling(vcs);
Ralf Baechled203a7e2005-09-06 15:19:37 -07002596 vino_set_default_framerate(vcs);
2597
2598 dprintk("vino_set_input(): %s\n", vino_inputs[vcs->input].name);
2599
2600out:
Ladislav Michla637a112005-09-01 15:07:34 +00002601 spin_unlock_irqrestore(&vino_drvdata->input_lock, flags);
Ralf Baechled203a7e2005-09-06 15:19:37 -07002602
2603 return ret;
2604}
2605
2606static void vino_release_input(struct vino_channel_settings *vcs)
2607{
2608 struct vino_channel_settings *vcs2 = (vcs->channel == VINO_CHANNEL_A) ?
2609 &vino_drvdata->b : &vino_drvdata->a;
Ladislav Michla637a112005-09-01 15:07:34 +00002610 unsigned long flags;
Ralf Baechled203a7e2005-09-06 15:19:37 -07002611
2612 dprintk("vino_release_input():\n");
2613
Ladislav Michla637a112005-09-01 15:07:34 +00002614 spin_lock_irqsave(&vino_drvdata->input_lock, flags);
Ralf Baechled203a7e2005-09-06 15:19:37 -07002615
2616 /* Release ownership of the channel
2617 * and if the other channel takes input from
2618 * the same source, transfer the ownership */
Hans Verkuil48f4dac2009-02-18 19:18:26 -03002619 if (vino_drvdata->camera_owner == vcs->channel) {
Ralf Baechled203a7e2005-09-06 15:19:37 -07002620 if (vcs2->input == VINO_INPUT_D1) {
Hans Verkuil48f4dac2009-02-18 19:18:26 -03002621 vino_drvdata->camera_owner = vcs2->channel;
Ralf Baechled203a7e2005-09-06 15:19:37 -07002622 } else {
Hans Verkuil48f4dac2009-02-18 19:18:26 -03002623 vino_drvdata->camera_owner = VINO_NO_CHANNEL;
Ralf Baechled203a7e2005-09-06 15:19:37 -07002624 }
Hans Verkuil48f4dac2009-02-18 19:18:26 -03002625 } else if (vino_drvdata->decoder_owner == vcs->channel) {
Ralf Baechled203a7e2005-09-06 15:19:37 -07002626 if ((vcs2->input == VINO_INPUT_COMPOSITE) ||
2627 (vcs2->input == VINO_INPUT_SVIDEO)) {
Hans Verkuil48f4dac2009-02-18 19:18:26 -03002628 vino_drvdata->decoder_owner = vcs2->channel;
Ralf Baechled203a7e2005-09-06 15:19:37 -07002629 } else {
Hans Verkuil48f4dac2009-02-18 19:18:26 -03002630 vino_drvdata->decoder_owner = VINO_NO_CHANNEL;
Ralf Baechled203a7e2005-09-06 15:19:37 -07002631 }
2632 }
2633 vcs->input = VINO_INPUT_NONE;
2634
Ladislav Michla637a112005-09-01 15:07:34 +00002635 spin_unlock_irqrestore(&vino_drvdata->input_lock, flags);
Ralf Baechled203a7e2005-09-06 15:19:37 -07002636}
2637
2638/* execute with input_lock locked */
2639static int vino_set_data_norm(struct vino_channel_settings *vcs,
Ladislav Michla637a112005-09-01 15:07:34 +00002640 unsigned int data_norm,
2641 unsigned long *flags)
Ralf Baechled203a7e2005-09-06 15:19:37 -07002642{
Ladislav Michla637a112005-09-01 15:07:34 +00002643 int err = 0;
2644
2645 if (data_norm == vcs->data_norm)
2646 return 0;
Ralf Baechled203a7e2005-09-06 15:19:37 -07002647
2648 switch (vcs->input) {
2649 case VINO_INPUT_D1:
2650 /* only one "norm" supported */
Hans Verkuilcf4e9482009-02-27 09:05:10 -03002651 if (data_norm != VINO_DATA_NORM_D1)
Ralf Baechled203a7e2005-09-06 15:19:37 -07002652 return -EINVAL;
2653 break;
2654 case VINO_INPUT_COMPOSITE:
Ladislav Michla637a112005-09-01 15:07:34 +00002655 case VINO_INPUT_SVIDEO: {
Hans Verkuilcf4e9482009-02-27 09:05:10 -03002656 v4l2_std_id norm;
2657
Ladislav Michla637a112005-09-01 15:07:34 +00002658 if ((data_norm != VINO_DATA_NORM_PAL)
2659 && (data_norm != VINO_DATA_NORM_NTSC)
Hans Verkuilcf4e9482009-02-27 09:05:10 -03002660 && (data_norm != VINO_DATA_NORM_SECAM))
Ladislav Michla637a112005-09-01 15:07:34 +00002661 return -EINVAL;
Ralf Baechled203a7e2005-09-06 15:19:37 -07002662
Ladislav Michla637a112005-09-01 15:07:34 +00002663 spin_unlock_irqrestore(&vino_drvdata->input_lock, *flags);
Ralf Baechled203a7e2005-09-06 15:19:37 -07002664
Ladislav Michla637a112005-09-01 15:07:34 +00002665 /* Don't hold spinlocks while setting norm
2666 * as it may take a while... */
2667
Hans Verkuilcf4e9482009-02-27 09:05:10 -03002668 norm = vino_data_norms[data_norm].std;
Hans Verkuil48f4dac2009-02-18 19:18:26 -03002669 err = decoder_call(tuner, s_std, norm);
Ladislav Michla637a112005-09-01 15:07:34 +00002670
2671 spin_lock_irqsave(&vino_drvdata->input_lock, *flags);
2672
2673 if (err)
2674 goto out;
2675
Ralf Baechled203a7e2005-09-06 15:19:37 -07002676 vcs->data_norm = data_norm;
Ladislav Michla637a112005-09-01 15:07:34 +00002677
2678 vino_set_default_clipping(vcs);
2679 vino_set_default_scaling(vcs);
2680 vino_set_default_framerate(vcs);
Ralf Baechled203a7e2005-09-06 15:19:37 -07002681 break;
Ladislav Michla637a112005-09-01 15:07:34 +00002682 }
Ralf Baechled203a7e2005-09-06 15:19:37 -07002683 default:
2684 return -EINVAL;
2685 }
2686
Ladislav Michla637a112005-09-01 15:07:34 +00002687out:
2688 return err;
Ralf Baechled203a7e2005-09-06 15:19:37 -07002689}
2690
2691/* V4L2 helper functions */
2692
2693static int vino_find_data_format(__u32 pixelformat)
2694{
2695 int i;
2696
2697 for (i = 0; i < VINO_DATA_FMT_COUNT; i++) {
2698 if (vino_data_formats[i].pixelformat == pixelformat)
2699 return i;
2700 }
2701
2702 return VINO_DATA_FMT_NONE;
2703}
2704
Hans Verkuilc49cb362009-02-12 10:32:50 -03002705static int vino_int_enum_input(struct vino_channel_settings *vcs, __u32 index)
Ralf Baechled203a7e2005-09-06 15:19:37 -07002706{
2707 int input = VINO_INPUT_NONE;
Ladislav Michla637a112005-09-01 15:07:34 +00002708 unsigned long flags;
Ralf Baechled203a7e2005-09-06 15:19:37 -07002709
Ladislav Michla637a112005-09-01 15:07:34 +00002710 spin_lock_irqsave(&vino_drvdata->input_lock, flags);
Hans Verkuil48f4dac2009-02-18 19:18:26 -03002711 if (vino_drvdata->decoder && vino_drvdata->camera) {
Ralf Baechled203a7e2005-09-06 15:19:37 -07002712 switch (index) {
2713 case 0:
2714 input = VINO_INPUT_COMPOSITE;
2715 break;
2716 case 1:
2717 input = VINO_INPUT_SVIDEO;
2718 break;
2719 case 2:
2720 input = VINO_INPUT_D1;
2721 break;
2722 }
Hans Verkuil48f4dac2009-02-18 19:18:26 -03002723 } else if (vino_drvdata->decoder) {
Ralf Baechled203a7e2005-09-06 15:19:37 -07002724 switch (index) {
2725 case 0:
2726 input = VINO_INPUT_COMPOSITE;
2727 break;
2728 case 1:
2729 input = VINO_INPUT_SVIDEO;
2730 break;
2731 }
Hans Verkuil48f4dac2009-02-18 19:18:26 -03002732 } else if (vino_drvdata->camera) {
Ralf Baechled203a7e2005-09-06 15:19:37 -07002733 switch (index) {
2734 case 0:
2735 input = VINO_INPUT_D1;
2736 break;
2737 }
2738 }
Ladislav Michla637a112005-09-01 15:07:34 +00002739 spin_unlock_irqrestore(&vino_drvdata->input_lock, flags);
Ralf Baechled203a7e2005-09-06 15:19:37 -07002740
2741 return input;
2742}
2743
2744/* execute with input_lock locked */
2745static __u32 vino_find_input_index(struct vino_channel_settings *vcs)
2746{
2747 __u32 index = 0;
2748 // FIXME: detect when no inputs available
2749
Hans Verkuil48f4dac2009-02-18 19:18:26 -03002750 if (vino_drvdata->decoder && vino_drvdata->camera) {
Ralf Baechled203a7e2005-09-06 15:19:37 -07002751 switch (vcs->input) {
2752 case VINO_INPUT_COMPOSITE:
2753 index = 0;
2754 break;
2755 case VINO_INPUT_SVIDEO:
2756 index = 1;
2757 break;
2758 case VINO_INPUT_D1:
2759 index = 2;
2760 break;
2761 }
Hans Verkuil48f4dac2009-02-18 19:18:26 -03002762 } else if (vino_drvdata->decoder) {
Ralf Baechled203a7e2005-09-06 15:19:37 -07002763 switch (vcs->input) {
2764 case VINO_INPUT_COMPOSITE:
2765 index = 0;
2766 break;
2767 case VINO_INPUT_SVIDEO:
2768 index = 1;
2769 break;
2770 }
Hans Verkuil48f4dac2009-02-18 19:18:26 -03002771 } else if (vino_drvdata->camera) {
Ralf Baechled203a7e2005-09-06 15:19:37 -07002772 switch (vcs->input) {
2773 case VINO_INPUT_D1:
2774 index = 0;
2775 break;
2776 }
2777 }
2778
2779 return index;
2780}
2781
2782/* V4L2 ioctls */
2783
Hans Verkuilc49cb362009-02-12 10:32:50 -03002784static int vino_querycap(struct file *file, void *__fh,
2785 struct v4l2_capability *cap)
Ralf Baechled203a7e2005-09-06 15:19:37 -07002786{
2787 memset(cap, 0, sizeof(struct v4l2_capability));
2788
2789 strcpy(cap->driver, vino_driver_name);
2790 strcpy(cap->card, vino_driver_description);
2791 strcpy(cap->bus_info, vino_bus_name);
2792 cap->version = VINO_VERSION_CODE;
2793 cap->capabilities =
2794 V4L2_CAP_VIDEO_CAPTURE |
2795 V4L2_CAP_STREAMING;
2796 // V4L2_CAP_OVERLAY, V4L2_CAP_READWRITE
Hans Verkuilc49cb362009-02-12 10:32:50 -03002797 return 0;
Ralf Baechled203a7e2005-09-06 15:19:37 -07002798}
2799
Hans Verkuilc49cb362009-02-12 10:32:50 -03002800static int vino_enum_input(struct file *file, void *__fh,
Ralf Baechled203a7e2005-09-06 15:19:37 -07002801 struct v4l2_input *i)
2802{
Hans Verkuilc49cb362009-02-12 10:32:50 -03002803 struct vino_channel_settings *vcs = video_drvdata(file);
Ralf Baechled203a7e2005-09-06 15:19:37 -07002804 __u32 index = i->index;
2805 int input;
2806 dprintk("requested index = %d\n", index);
2807
Hans Verkuilc49cb362009-02-12 10:32:50 -03002808 input = vino_int_enum_input(vcs, index);
Ralf Baechled203a7e2005-09-06 15:19:37 -07002809 if (input == VINO_INPUT_NONE)
2810 return -EINVAL;
2811
2812 memset(i, 0, sizeof(struct v4l2_input));
2813
2814 i->index = index;
2815 i->type = V4L2_INPUT_TYPE_CAMERA;
2816 i->std = vino_inputs[input].std;
2817 strcpy(i->name, vino_inputs[input].name);
2818
Hans Verkuilcf4e9482009-02-27 09:05:10 -03002819 if (input == VINO_INPUT_COMPOSITE || input == VINO_INPUT_SVIDEO)
Hans Verkuil48f4dac2009-02-18 19:18:26 -03002820 decoder_call(video, g_input_status, &i->status);
Ralf Baechled203a7e2005-09-06 15:19:37 -07002821 return 0;
2822}
2823
Hans Verkuilc49cb362009-02-12 10:32:50 -03002824static int vino_g_input(struct file *file, void *__fh,
Ladislav Michla637a112005-09-01 15:07:34 +00002825 unsigned int *i)
Ralf Baechled203a7e2005-09-06 15:19:37 -07002826{
Hans Verkuilc49cb362009-02-12 10:32:50 -03002827 struct vino_channel_settings *vcs = video_drvdata(file);
Ralf Baechled203a7e2005-09-06 15:19:37 -07002828 __u32 index;
2829 int input;
Ladislav Michla637a112005-09-01 15:07:34 +00002830 unsigned long flags;
Ralf Baechled203a7e2005-09-06 15:19:37 -07002831
Ladislav Michla637a112005-09-01 15:07:34 +00002832 spin_lock_irqsave(&vino_drvdata->input_lock, flags);
Ralf Baechled203a7e2005-09-06 15:19:37 -07002833 input = vcs->input;
2834 index = vino_find_input_index(vcs);
Ladislav Michla637a112005-09-01 15:07:34 +00002835 spin_unlock_irqrestore(&vino_drvdata->input_lock, flags);
Ralf Baechled203a7e2005-09-06 15:19:37 -07002836
2837 dprintk("input = %d\n", input);
2838
2839 if (input == VINO_INPUT_NONE) {
2840 return -EINVAL;
2841 }
2842
Ladislav Michla637a112005-09-01 15:07:34 +00002843 *i = index;
Ralf Baechled203a7e2005-09-06 15:19:37 -07002844
2845 return 0;
2846}
2847
Hans Verkuilc49cb362009-02-12 10:32:50 -03002848static int vino_s_input(struct file *file, void *__fh,
2849 unsigned int i)
Ralf Baechled203a7e2005-09-06 15:19:37 -07002850{
Hans Verkuilc49cb362009-02-12 10:32:50 -03002851 struct vino_channel_settings *vcs = video_drvdata(file);
Ralf Baechled203a7e2005-09-06 15:19:37 -07002852 int input;
Hans Verkuilc49cb362009-02-12 10:32:50 -03002853 dprintk("requested input = %d\n", i);
Ralf Baechled203a7e2005-09-06 15:19:37 -07002854
Hans Verkuilc49cb362009-02-12 10:32:50 -03002855 input = vino_int_enum_input(vcs, i);
Ralf Baechled203a7e2005-09-06 15:19:37 -07002856 if (input == VINO_INPUT_NONE)
2857 return -EINVAL;
2858
2859 return vino_set_input(vcs, input);
2860}
2861
Hans Verkuilc49cb362009-02-12 10:32:50 -03002862static int vino_querystd(struct file *file, void *__fh,
Ladislav Michla637a112005-09-01 15:07:34 +00002863 v4l2_std_id *std)
2864{
Hans Verkuilc49cb362009-02-12 10:32:50 -03002865 struct vino_channel_settings *vcs = video_drvdata(file);
Ladislav Michla637a112005-09-01 15:07:34 +00002866 unsigned long flags;
2867 int err = 0;
2868
2869 spin_lock_irqsave(&vino_drvdata->input_lock, flags);
2870
2871 switch (vcs->input) {
2872 case VINO_INPUT_D1:
2873 *std = vino_inputs[vcs->input].std;
2874 break;
2875 case VINO_INPUT_COMPOSITE:
2876 case VINO_INPUT_SVIDEO: {
Hans Verkuil48f4dac2009-02-18 19:18:26 -03002877 decoder_call(video, querystd, std);
Ladislav Michla637a112005-09-01 15:07:34 +00002878 break;
2879 }
2880 default:
2881 err = -EINVAL;
2882 }
2883
2884 spin_unlock_irqrestore(&vino_drvdata->input_lock, flags);
2885
2886 return err;
2887}
2888
Hans Verkuilc49cb362009-02-12 10:32:50 -03002889static int vino_g_std(struct file *file, void *__fh,
Ralf Baechled203a7e2005-09-06 15:19:37 -07002890 v4l2_std_id *std)
2891{
Hans Verkuilc49cb362009-02-12 10:32:50 -03002892 struct vino_channel_settings *vcs = video_drvdata(file);
Ladislav Michla637a112005-09-01 15:07:34 +00002893 unsigned long flags;
2894
2895 spin_lock_irqsave(&vino_drvdata->input_lock, flags);
2896
Ralf Baechled203a7e2005-09-06 15:19:37 -07002897 *std = vino_data_norms[vcs->data_norm].std;
Ladislav Michla637a112005-09-01 15:07:34 +00002898 dprintk("current standard = %d\n", vcs->data_norm);
2899
2900 spin_unlock_irqrestore(&vino_drvdata->input_lock, flags);
Ralf Baechled203a7e2005-09-06 15:19:37 -07002901
2902 return 0;
2903}
2904
Hans Verkuilc49cb362009-02-12 10:32:50 -03002905static int vino_s_std(struct file *file, void *__fh,
Ralf Baechled203a7e2005-09-06 15:19:37 -07002906 v4l2_std_id *std)
2907{
Hans Verkuilc49cb362009-02-12 10:32:50 -03002908 struct vino_channel_settings *vcs = video_drvdata(file);
Ladislav Michla637a112005-09-01 15:07:34 +00002909 unsigned long flags;
Ralf Baechled203a7e2005-09-06 15:19:37 -07002910 int ret = 0;
2911
Ladislav Michla637a112005-09-01 15:07:34 +00002912 spin_lock_irqsave(&vino_drvdata->input_lock, flags);
2913
2914 if (!vino_is_input_owner(vcs)) {
2915 ret = -EBUSY;
2916 goto out;
2917 }
Ralf Baechled203a7e2005-09-06 15:19:37 -07002918
2919 /* check if the standard is valid for the current input */
Ladislav Michla637a112005-09-01 15:07:34 +00002920 if ((*std) & vino_inputs[vcs->input].std) {
Ralf Baechled203a7e2005-09-06 15:19:37 -07002921 dprintk("standard accepted\n");
2922
2923 /* change the video norm for SAA7191
2924 * and accept NTSC for D1 (do nothing) */
2925
2926 if (vcs->input == VINO_INPUT_D1)
2927 goto out;
2928
Hans Verkuilcf4e9482009-02-27 09:05:10 -03002929 if ((*std) & V4L2_STD_PAL) {
Ladislav Michla637a112005-09-01 15:07:34 +00002930 ret = vino_set_data_norm(vcs, VINO_DATA_NORM_PAL,
2931 &flags);
Ralf Baechled203a7e2005-09-06 15:19:37 -07002932 } else if ((*std) & V4L2_STD_NTSC) {
Ladislav Michla637a112005-09-01 15:07:34 +00002933 ret = vino_set_data_norm(vcs, VINO_DATA_NORM_NTSC,
2934 &flags);
Ralf Baechled203a7e2005-09-06 15:19:37 -07002935 } else if ((*std) & V4L2_STD_SECAM) {
Ladislav Michla637a112005-09-01 15:07:34 +00002936 ret = vino_set_data_norm(vcs, VINO_DATA_NORM_SECAM,
2937 &flags);
Ralf Baechled203a7e2005-09-06 15:19:37 -07002938 } else {
2939 ret = -EINVAL;
2940 }
Ladislav Michla637a112005-09-01 15:07:34 +00002941
2942 if (ret) {
2943 ret = -EINVAL;
2944 }
Ralf Baechled203a7e2005-09-06 15:19:37 -07002945 } else {
2946 ret = -EINVAL;
2947 }
2948
2949out:
Ladislav Michla637a112005-09-01 15:07:34 +00002950 spin_unlock_irqrestore(&vino_drvdata->input_lock, flags);
Ralf Baechled203a7e2005-09-06 15:19:37 -07002951
2952 return ret;
2953}
2954
Hans Verkuilc49cb362009-02-12 10:32:50 -03002955static int vino_enum_fmt_vid_cap(struct file *file, void *__fh,
Ralf Baechled203a7e2005-09-06 15:19:37 -07002956 struct v4l2_fmtdesc *fd)
2957{
2958 enum v4l2_buf_type type = fd->type;
2959 int index = fd->index;
Hans Verkuilc49cb362009-02-12 10:32:50 -03002960
Ralf Baechled203a7e2005-09-06 15:19:37 -07002961 dprintk("format index = %d\n", index);
2962
Hans Verkuilc49cb362009-02-12 10:32:50 -03002963 if ((fd->index < 0) ||
2964 (fd->index >= VINO_DATA_FMT_COUNT))
Ralf Baechled203a7e2005-09-06 15:19:37 -07002965 return -EINVAL;
Hans Verkuilc49cb362009-02-12 10:32:50 -03002966 dprintk("format name = %s\n",
2967 vino_data_formats[index].description);
Ralf Baechled203a7e2005-09-06 15:19:37 -07002968
Hans Verkuilc49cb362009-02-12 10:32:50 -03002969 memset(fd, 0, sizeof(struct v4l2_fmtdesc));
2970 fd->index = index;
2971 fd->type = type;
2972 fd->pixelformat = vino_data_formats[index].pixelformat;
2973 strcpy(fd->description, vino_data_formats[index].description);
Ralf Baechled203a7e2005-09-06 15:19:37 -07002974 return 0;
2975}
2976
Hans Verkuilc49cb362009-02-12 10:32:50 -03002977static int vino_try_fmt_vid_cap(struct file *file, void *__fh,
Ralf Baechled203a7e2005-09-06 15:19:37 -07002978 struct v4l2_format *f)
2979{
Hans Verkuilc49cb362009-02-12 10:32:50 -03002980 struct vino_channel_settings *vcs = video_drvdata(file);
Ralf Baechled203a7e2005-09-06 15:19:37 -07002981 struct vino_channel_settings tempvcs;
Ladislav Michla637a112005-09-01 15:07:34 +00002982 unsigned long flags;
Hans Verkuilc49cb362009-02-12 10:32:50 -03002983 struct v4l2_pix_format *pf = &f->fmt.pix;
Ralf Baechled203a7e2005-09-06 15:19:37 -07002984
Hans Verkuilc49cb362009-02-12 10:32:50 -03002985 dprintk("requested: w = %d, h = %d\n",
2986 pf->width, pf->height);
Ralf Baechled203a7e2005-09-06 15:19:37 -07002987
Hans Verkuilc49cb362009-02-12 10:32:50 -03002988 spin_lock_irqsave(&vino_drvdata->input_lock, flags);
2989 memcpy(&tempvcs, vcs, sizeof(struct vino_channel_settings));
2990 spin_unlock_irqrestore(&vino_drvdata->input_lock, flags);
Ralf Baechled203a7e2005-09-06 15:19:37 -07002991
Hans Verkuilc49cb362009-02-12 10:32:50 -03002992 tempvcs.data_format = vino_find_data_format(pf->pixelformat);
2993 if (tempvcs.data_format == VINO_DATA_FMT_NONE) {
2994 tempvcs.data_format = VINO_DATA_FMT_GREY;
Ralf Baechled203a7e2005-09-06 15:19:37 -07002995 pf->pixelformat =
Hans Verkuilc49cb362009-02-12 10:32:50 -03002996 vino_data_formats[tempvcs.data_format].
2997 pixelformat;
Ralf Baechled203a7e2005-09-06 15:19:37 -07002998 }
2999
Hans Verkuilc49cb362009-02-12 10:32:50 -03003000 /* data format must be set before clipping/scaling */
3001 vino_set_scaling(&tempvcs, pf->width, pf->height);
3002
3003 dprintk("data format = %s\n",
3004 vino_data_formats[tempvcs.data_format].description);
3005
3006 pf->width = (tempvcs.clipping.right - tempvcs.clipping.left) /
3007 tempvcs.decimation;
3008 pf->height = (tempvcs.clipping.bottom - tempvcs.clipping.top) /
3009 tempvcs.decimation;
3010
3011 pf->field = V4L2_FIELD_INTERLACED;
3012 pf->bytesperline = tempvcs.line_size;
3013 pf->sizeimage = tempvcs.line_size *
3014 (tempvcs.clipping.bottom - tempvcs.clipping.top) /
3015 tempvcs.decimation;
3016 pf->colorspace =
3017 vino_data_formats[tempvcs.data_format].colorspace;
3018
3019 pf->priv = 0;
Ralf Baechled203a7e2005-09-06 15:19:37 -07003020 return 0;
3021}
3022
Hans Verkuilc49cb362009-02-12 10:32:50 -03003023static int vino_g_fmt_vid_cap(struct file *file, void *__fh,
Ralf Baechled203a7e2005-09-06 15:19:37 -07003024 struct v4l2_format *f)
3025{
Hans Verkuilc49cb362009-02-12 10:32:50 -03003026 struct vino_channel_settings *vcs = video_drvdata(file);
3027 unsigned long flags;
3028 struct v4l2_pix_format *pf = &f->fmt.pix;
3029
3030 spin_lock_irqsave(&vino_drvdata->input_lock, flags);
3031
3032 pf->width = (vcs->clipping.right - vcs->clipping.left) /
3033 vcs->decimation;
3034 pf->height = (vcs->clipping.bottom - vcs->clipping.top) /
3035 vcs->decimation;
3036 pf->pixelformat =
3037 vino_data_formats[vcs->data_format].pixelformat;
3038
3039 pf->field = V4L2_FIELD_INTERLACED;
3040 pf->bytesperline = vcs->line_size;
3041 pf->sizeimage = vcs->line_size *
3042 (vcs->clipping.bottom - vcs->clipping.top) /
3043 vcs->decimation;
3044 pf->colorspace =
3045 vino_data_formats[vcs->data_format].colorspace;
3046
3047 pf->priv = 0;
3048
3049 spin_unlock_irqrestore(&vino_drvdata->input_lock, flags);
3050 return 0;
3051}
3052
3053static int vino_s_fmt_vid_cap(struct file *file, void *__fh,
3054 struct v4l2_format *f)
3055{
3056 struct vino_channel_settings *vcs = video_drvdata(file);
Ralf Baechled203a7e2005-09-06 15:19:37 -07003057 int data_format;
Ladislav Michla637a112005-09-01 15:07:34 +00003058 unsigned long flags;
Hans Verkuilc49cb362009-02-12 10:32:50 -03003059 struct v4l2_pix_format *pf = &f->fmt.pix;
Ralf Baechled203a7e2005-09-06 15:19:37 -07003060
Hans Verkuilc49cb362009-02-12 10:32:50 -03003061 spin_lock_irqsave(&vino_drvdata->input_lock, flags);
Ralf Baechled203a7e2005-09-06 15:19:37 -07003062
Hans Verkuilc49cb362009-02-12 10:32:50 -03003063 data_format = vino_find_data_format(pf->pixelformat);
Ralf Baechled203a7e2005-09-06 15:19:37 -07003064
Hans Verkuilc49cb362009-02-12 10:32:50 -03003065 if (data_format == VINO_DATA_FMT_NONE) {
3066 vcs->data_format = VINO_DATA_FMT_GREY;
3067 pf->pixelformat =
3068 vino_data_formats[vcs->data_format].
3069 pixelformat;
3070 } else {
3071 vcs->data_format = data_format;
Ralf Baechled203a7e2005-09-06 15:19:37 -07003072 }
3073
Hans Verkuilc49cb362009-02-12 10:32:50 -03003074 /* data format must be set before clipping/scaling */
3075 vino_set_scaling(vcs, pf->width, pf->height);
3076
3077 dprintk("data format = %s\n",
3078 vino_data_formats[vcs->data_format].description);
3079
3080 pf->width = vcs->clipping.right - vcs->clipping.left;
3081 pf->height = vcs->clipping.bottom - vcs->clipping.top;
3082
3083 pf->field = V4L2_FIELD_INTERLACED;
3084 pf->bytesperline = vcs->line_size;
3085 pf->sizeimage = vcs->line_size *
3086 (vcs->clipping.bottom - vcs->clipping.top) /
3087 vcs->decimation;
3088 pf->colorspace =
3089 vino_data_formats[vcs->data_format].colorspace;
3090
3091 pf->priv = 0;
3092
3093 spin_unlock_irqrestore(&vino_drvdata->input_lock, flags);
Ralf Baechled203a7e2005-09-06 15:19:37 -07003094 return 0;
3095}
3096
Hans Verkuilc49cb362009-02-12 10:32:50 -03003097static int vino_cropcap(struct file *file, void *__fh,
Ralf Baechled203a7e2005-09-06 15:19:37 -07003098 struct v4l2_cropcap *ccap)
3099{
Hans Verkuilc49cb362009-02-12 10:32:50 -03003100 struct vino_channel_settings *vcs = video_drvdata(file);
Ralf Baechled203a7e2005-09-06 15:19:37 -07003101 const struct vino_data_norm *norm;
Ladislav Michla637a112005-09-01 15:07:34 +00003102 unsigned long flags;
Ralf Baechled203a7e2005-09-06 15:19:37 -07003103
3104 switch (ccap->type) {
3105 case V4L2_BUF_TYPE_VIDEO_CAPTURE:
Ladislav Michla637a112005-09-01 15:07:34 +00003106 spin_lock_irqsave(&vino_drvdata->input_lock, flags);
3107
Ralf Baechled203a7e2005-09-06 15:19:37 -07003108 norm = &vino_data_norms[vcs->data_norm];
Ladislav Michla637a112005-09-01 15:07:34 +00003109
3110 spin_unlock_irqrestore(&vino_drvdata->input_lock, flags);
Ralf Baechled203a7e2005-09-06 15:19:37 -07003111
3112 ccap->bounds.left = 0;
3113 ccap->bounds.top = 0;
3114 ccap->bounds.width = norm->width;
3115 ccap->bounds.height = norm->height;
3116 memcpy(&ccap->defrect, &ccap->bounds,
3117 sizeof(struct v4l2_rect));
3118
3119 ccap->pixelaspect.numerator = 1;
3120 ccap->pixelaspect.denominator = 1;
3121 break;
3122 case V4L2_BUF_TYPE_VIDEO_OVERLAY:
3123 default:
3124 return -EINVAL;
3125 }
3126
3127 return 0;
3128}
3129
Hans Verkuilc49cb362009-02-12 10:32:50 -03003130static int vino_g_crop(struct file *file, void *__fh,
Ralf Baechled203a7e2005-09-06 15:19:37 -07003131 struct v4l2_crop *c)
3132{
Hans Verkuilc49cb362009-02-12 10:32:50 -03003133 struct vino_channel_settings *vcs = video_drvdata(file);
Ladislav Michla637a112005-09-01 15:07:34 +00003134 unsigned long flags;
3135
Ralf Baechled203a7e2005-09-06 15:19:37 -07003136 switch (c->type) {
3137 case V4L2_BUF_TYPE_VIDEO_CAPTURE:
Ladislav Michla637a112005-09-01 15:07:34 +00003138 spin_lock_irqsave(&vino_drvdata->input_lock, flags);
Ralf Baechled203a7e2005-09-06 15:19:37 -07003139
3140 c->c.left = vcs->clipping.left;
3141 c->c.top = vcs->clipping.top;
3142 c->c.width = vcs->clipping.right - vcs->clipping.left;
3143 c->c.height = vcs->clipping.bottom - vcs->clipping.top;
3144
Ladislav Michla637a112005-09-01 15:07:34 +00003145 spin_unlock_irqrestore(&vino_drvdata->input_lock, flags);
Ralf Baechled203a7e2005-09-06 15:19:37 -07003146 break;
3147 case V4L2_BUF_TYPE_VIDEO_OVERLAY:
3148 default:
3149 return -EINVAL;
3150 }
3151
3152 return 0;
3153}
3154
Hans Verkuilc49cb362009-02-12 10:32:50 -03003155static int vino_s_crop(struct file *file, void *__fh,
Ralf Baechled203a7e2005-09-06 15:19:37 -07003156 struct v4l2_crop *c)
3157{
Hans Verkuilc49cb362009-02-12 10:32:50 -03003158 struct vino_channel_settings *vcs = video_drvdata(file);
Ladislav Michla637a112005-09-01 15:07:34 +00003159 unsigned long flags;
3160
Ralf Baechled203a7e2005-09-06 15:19:37 -07003161 switch (c->type) {
3162 case V4L2_BUF_TYPE_VIDEO_CAPTURE:
Ladislav Michla637a112005-09-01 15:07:34 +00003163 spin_lock_irqsave(&vino_drvdata->input_lock, flags);
Ralf Baechled203a7e2005-09-06 15:19:37 -07003164
Ralf Baechled203a7e2005-09-06 15:19:37 -07003165 vino_set_clipping(vcs, c->c.left, c->c.top,
3166 c->c.width, c->c.height);
3167
Ladislav Michla637a112005-09-01 15:07:34 +00003168 spin_unlock_irqrestore(&vino_drvdata->input_lock, flags);
Ralf Baechled203a7e2005-09-06 15:19:37 -07003169 break;
3170 case V4L2_BUF_TYPE_VIDEO_OVERLAY:
3171 default:
3172 return -EINVAL;
3173 }
3174
3175 return 0;
3176}
3177
Hans Verkuilc49cb362009-02-12 10:32:50 -03003178static int vino_g_parm(struct file *file, void *__fh,
Ralf Baechled203a7e2005-09-06 15:19:37 -07003179 struct v4l2_streamparm *sp)
3180{
Hans Verkuilc49cb362009-02-12 10:32:50 -03003181 struct vino_channel_settings *vcs = video_drvdata(file);
Ladislav Michla637a112005-09-01 15:07:34 +00003182 unsigned long flags;
3183
Ralf Baechled203a7e2005-09-06 15:19:37 -07003184 switch (sp->type) {
3185 case V4L2_BUF_TYPE_VIDEO_CAPTURE: {
3186 struct v4l2_captureparm *cp = &sp->parm.capture;
3187 memset(cp, 0, sizeof(struct v4l2_captureparm));
3188
3189 cp->capability = V4L2_CAP_TIMEPERFRAME;
3190 cp->timeperframe.numerator = 1;
3191
Ladislav Michla637a112005-09-01 15:07:34 +00003192 spin_lock_irqsave(&vino_drvdata->input_lock, flags);
3193
Ralf Baechled203a7e2005-09-06 15:19:37 -07003194 cp->timeperframe.denominator = vcs->fps;
Ladislav Michla637a112005-09-01 15:07:34 +00003195
3196 spin_unlock_irqrestore(&vino_drvdata->input_lock, flags);
Ralf Baechled203a7e2005-09-06 15:19:37 -07003197
3198 // TODO: cp->readbuffers = xxx;
3199 break;
3200 }
3201 case V4L2_BUF_TYPE_VIDEO_OVERLAY:
3202 default:
3203 return -EINVAL;
3204 }
3205
3206 return 0;
3207}
3208
Hans Verkuilc49cb362009-02-12 10:32:50 -03003209static int vino_s_parm(struct file *file, void *__fh,
Ralf Baechled203a7e2005-09-06 15:19:37 -07003210 struct v4l2_streamparm *sp)
3211{
Hans Verkuilc49cb362009-02-12 10:32:50 -03003212 struct vino_channel_settings *vcs = video_drvdata(file);
Ladislav Michla637a112005-09-01 15:07:34 +00003213 unsigned long flags;
3214
Ralf Baechled203a7e2005-09-06 15:19:37 -07003215 switch (sp->type) {
3216 case V4L2_BUF_TYPE_VIDEO_CAPTURE: {
3217 struct v4l2_captureparm *cp = &sp->parm.capture;
3218
Ladislav Michla637a112005-09-01 15:07:34 +00003219 spin_lock_irqsave(&vino_drvdata->input_lock, flags);
Ralf Baechled203a7e2005-09-06 15:19:37 -07003220
3221 if ((cp->timeperframe.numerator == 0) ||
3222 (cp->timeperframe.denominator == 0)) {
3223 /* reset framerate */
3224 vino_set_default_framerate(vcs);
3225 } else {
3226 vino_set_framerate(vcs, cp->timeperframe.denominator /
3227 cp->timeperframe.numerator);
3228 }
Ladislav Michla637a112005-09-01 15:07:34 +00003229
3230 spin_unlock_irqrestore(&vino_drvdata->input_lock, flags);
Ralf Baechled203a7e2005-09-06 15:19:37 -07003231
3232 // TODO: set buffers according to cp->readbuffers
3233 break;
3234 }
3235 case V4L2_BUF_TYPE_VIDEO_OVERLAY:
3236 default:
3237 return -EINVAL;
3238 }
3239
3240 return 0;
3241}
3242
Hans Verkuilc49cb362009-02-12 10:32:50 -03003243static int vino_reqbufs(struct file *file, void *__fh,
Ralf Baechled203a7e2005-09-06 15:19:37 -07003244 struct v4l2_requestbuffers *rb)
3245{
Hans Verkuilc49cb362009-02-12 10:32:50 -03003246 struct vino_channel_settings *vcs = video_drvdata(file);
Ralf Baechled203a7e2005-09-06 15:19:37 -07003247 if (vcs->reading)
3248 return -EBUSY;
3249
3250 switch (rb->type) {
3251 case V4L2_BUF_TYPE_VIDEO_CAPTURE: {
3252 // TODO: check queue type
3253 if (rb->memory != V4L2_MEMORY_MMAP) {
3254 dprintk("type not mmap\n");
3255 return -EINVAL;
3256 }
3257
Ralf Baechled203a7e2005-09-06 15:19:37 -07003258 dprintk("count = %d\n", rb->count);
3259 if (rb->count > 0) {
Ladislav Michla637a112005-09-01 15:07:34 +00003260 if (vino_is_capturing(vcs)) {
3261 dprintk("busy, capturing\n");
3262 return -EBUSY;
3263 }
3264
Ralf Baechled203a7e2005-09-06 15:19:37 -07003265 if (vino_queue_has_mapped_buffers(&vcs->fb_queue)) {
3266 dprintk("busy, buffers still mapped\n");
3267 return -EBUSY;
3268 } else {
Ladislav Michla637a112005-09-01 15:07:34 +00003269 vcs->streaming = 0;
Ralf Baechled203a7e2005-09-06 15:19:37 -07003270 vino_queue_free(&vcs->fb_queue);
3271 vino_queue_init(&vcs->fb_queue, &rb->count);
3272 }
3273 } else {
Ladislav Michla637a112005-09-01 15:07:34 +00003274 vcs->streaming = 0;
Ralf Baechled203a7e2005-09-06 15:19:37 -07003275 vino_capture_stop(vcs);
3276 vino_queue_free(&vcs->fb_queue);
3277 }
3278 break;
3279 }
3280 case V4L2_BUF_TYPE_VIDEO_OVERLAY:
3281 default:
3282 return -EINVAL;
3283 }
3284
3285 return 0;
3286}
3287
3288static void vino_v4l2_get_buffer_status(struct vino_channel_settings *vcs,
3289 struct vino_framebuffer *fb,
3290 struct v4l2_buffer *b)
3291{
3292 if (vino_queue_outgoing_contains(&vcs->fb_queue,
3293 fb->id)) {
3294 b->flags &= ~V4L2_BUF_FLAG_QUEUED;
3295 b->flags |= V4L2_BUF_FLAG_DONE;
3296 } else if (vino_queue_incoming_contains(&vcs->fb_queue,
3297 fb->id)) {
3298 b->flags &= ~V4L2_BUF_FLAG_DONE;
3299 b->flags |= V4L2_BUF_FLAG_QUEUED;
3300 } else {
3301 b->flags &= ~(V4L2_BUF_FLAG_DONE |
3302 V4L2_BUF_FLAG_QUEUED);
3303 }
3304
3305 b->flags &= ~(V4L2_BUF_FLAG_TIMECODE);
3306
3307 if (fb->map_count > 0)
3308 b->flags |= V4L2_BUF_FLAG_MAPPED;
3309
3310 b->index = fb->id;
3311 b->memory = (vcs->fb_queue.type == VINO_MEMORY_MMAP) ?
3312 V4L2_MEMORY_MMAP : V4L2_MEMORY_USERPTR;
3313 b->m.offset = fb->offset;
3314 b->bytesused = fb->data_size;
3315 b->length = fb->size;
3316 b->field = V4L2_FIELD_INTERLACED;
3317 b->sequence = fb->frame_counter;
3318 memcpy(&b->timestamp, &fb->timestamp,
3319 sizeof(struct timeval));
3320 // b->input ?
3321
3322 dprintk("buffer %d: length = %d, bytesused = %d, offset = %d\n",
3323 fb->id, fb->size, fb->data_size, fb->offset);
3324}
3325
Hans Verkuilc49cb362009-02-12 10:32:50 -03003326static int vino_querybuf(struct file *file, void *__fh,
Ralf Baechled203a7e2005-09-06 15:19:37 -07003327 struct v4l2_buffer *b)
3328{
Hans Verkuilc49cb362009-02-12 10:32:50 -03003329 struct vino_channel_settings *vcs = video_drvdata(file);
Ralf Baechled203a7e2005-09-06 15:19:37 -07003330 if (vcs->reading)
3331 return -EBUSY;
3332
3333 switch (b->type) {
3334 case V4L2_BUF_TYPE_VIDEO_CAPTURE: {
3335 struct vino_framebuffer *fb;
3336
3337 // TODO: check queue type
3338 if (b->index >= vino_queue_get_length(&vcs->fb_queue)) {
3339 dprintk("invalid index = %d\n",
3340 b->index);
3341 return -EINVAL;
3342 }
3343
3344 fb = vino_queue_get_buffer(&vcs->fb_queue,
3345 b->index);
3346 if (fb == NULL) {
3347 dprintk("vino_queue_get_buffer() failed");
3348 return -EINVAL;
3349 }
3350
3351 vino_v4l2_get_buffer_status(vcs, fb, b);
3352 break;
3353 }
3354 case V4L2_BUF_TYPE_VIDEO_OVERLAY:
3355 default:
3356 return -EINVAL;
3357 }
3358
3359 return 0;
3360}
3361
Hans Verkuilc49cb362009-02-12 10:32:50 -03003362static int vino_qbuf(struct file *file, void *__fh,
Ralf Baechled203a7e2005-09-06 15:19:37 -07003363 struct v4l2_buffer *b)
3364{
Hans Verkuilc49cb362009-02-12 10:32:50 -03003365 struct vino_channel_settings *vcs = video_drvdata(file);
Ralf Baechled203a7e2005-09-06 15:19:37 -07003366 if (vcs->reading)
3367 return -EBUSY;
3368
3369 switch (b->type) {
3370 case V4L2_BUF_TYPE_VIDEO_CAPTURE: {
3371 struct vino_framebuffer *fb;
3372 int ret;
3373
3374 // TODO: check queue type
3375 if (b->memory != V4L2_MEMORY_MMAP) {
3376 dprintk("type not mmap\n");
3377 return -EINVAL;
3378 }
3379
3380 fb = vino_capture_enqueue(vcs, b->index);
3381 if (fb == NULL)
3382 return -EINVAL;
3383
3384 vino_v4l2_get_buffer_status(vcs, fb, b);
3385
3386 if (vcs->streaming) {
3387 ret = vino_capture_next(vcs, 1);
3388 if (ret)
3389 return ret;
3390 }
3391 break;
3392 }
3393 case V4L2_BUF_TYPE_VIDEO_OVERLAY:
3394 default:
3395 return -EINVAL;
3396 }
3397
3398 return 0;
3399}
3400
Hans Verkuilc49cb362009-02-12 10:32:50 -03003401static int vino_dqbuf(struct file *file, void *__fh,
3402 struct v4l2_buffer *b)
Ralf Baechled203a7e2005-09-06 15:19:37 -07003403{
Hans Verkuilc49cb362009-02-12 10:32:50 -03003404 struct vino_channel_settings *vcs = video_drvdata(file);
3405 unsigned int nonblocking = file->f_flags & O_NONBLOCK;
Ralf Baechled203a7e2005-09-06 15:19:37 -07003406 if (vcs->reading)
3407 return -EBUSY;
3408
3409 switch (b->type) {
3410 case V4L2_BUF_TYPE_VIDEO_CAPTURE: {
3411 struct vino_framebuffer *fb;
3412 unsigned int incoming, outgoing;
3413 int err;
3414
3415 // TODO: check queue type
3416
3417 err = vino_queue_get_incoming(&vcs->fb_queue, &incoming);
3418 if (err) {
3419 dprintk("vino_queue_get_incoming() failed\n");
Ladislav Michla637a112005-09-01 15:07:34 +00003420 return -EINVAL;
Ralf Baechled203a7e2005-09-06 15:19:37 -07003421 }
3422 err = vino_queue_get_outgoing(&vcs->fb_queue, &outgoing);
3423 if (err) {
3424 dprintk("vino_queue_get_outgoing() failed\n");
Ladislav Michla637a112005-09-01 15:07:34 +00003425 return -EINVAL;
Ralf Baechled203a7e2005-09-06 15:19:37 -07003426 }
3427
3428 dprintk("incoming = %d, outgoing = %d\n", incoming, outgoing);
3429
3430 if (outgoing == 0) {
3431 if (incoming == 0) {
3432 dprintk("no incoming or outgoing buffers\n");
3433 return -EINVAL;
3434 }
3435 if (nonblocking) {
3436 dprintk("non-blocking I/O was selected and "
3437 "there are no buffers to dequeue\n");
3438 return -EAGAIN;
3439 }
3440
3441 err = vino_wait_for_frame(vcs);
3442 if (err) {
3443 err = vino_wait_for_frame(vcs);
3444 if (err) {
Ladislav Michla637a112005-09-01 15:07:34 +00003445 /* interrupted or
3446 * no frames captured because
3447 * of frame skipping */
3448 // vino_capture_failed(vcs);
Ralf Baechled203a7e2005-09-06 15:19:37 -07003449 return -EIO;
3450 }
3451 }
3452 }
3453
3454 fb = vino_queue_remove(&vcs->fb_queue, &b->index);
3455 if (fb == NULL) {
3456 dprintk("vino_queue_remove() failed\n");
3457 return -EINVAL;
3458 }
3459
3460 err = vino_check_buffer(vcs, fb);
Ladislav Michla637a112005-09-01 15:07:34 +00003461
3462 vino_v4l2_get_buffer_status(vcs, fb, b);
3463
Ralf Baechled203a7e2005-09-06 15:19:37 -07003464 if (err)
3465 return -EIO;
3466
Ralf Baechled203a7e2005-09-06 15:19:37 -07003467 break;
3468 }
3469 case V4L2_BUF_TYPE_VIDEO_OVERLAY:
3470 default:
3471 return -EINVAL;
3472 }
3473
3474 return 0;
3475}
3476
Hans Verkuilc49cb362009-02-12 10:32:50 -03003477static int vino_streamon(struct file *file, void *__fh,
3478 enum v4l2_buf_type i)
Ralf Baechled203a7e2005-09-06 15:19:37 -07003479{
Hans Verkuilc49cb362009-02-12 10:32:50 -03003480 struct vino_channel_settings *vcs = video_drvdata(file);
Ralf Baechled203a7e2005-09-06 15:19:37 -07003481 unsigned int incoming;
3482 int ret;
3483 if (vcs->reading)
3484 return -EBUSY;
3485
3486 if (vcs->streaming)
3487 return 0;
3488
3489 // TODO: check queue type
3490
3491 if (vino_queue_get_length(&vcs->fb_queue) < 1) {
3492 dprintk("no buffers allocated\n");
3493 return -EINVAL;
3494 }
3495
3496 ret = vino_queue_get_incoming(&vcs->fb_queue, &incoming);
3497 if (ret) {
3498 dprintk("vino_queue_get_incoming() failed\n");
3499 return -EINVAL;
3500 }
3501
3502 vcs->streaming = 1;
3503
3504 if (incoming > 0) {
3505 ret = vino_capture_next(vcs, 1);
3506 if (ret) {
3507 vcs->streaming = 0;
3508
3509 dprintk("couldn't start capture\n");
3510 return -EINVAL;
3511 }
3512 }
3513
3514 return 0;
3515}
3516
Hans Verkuilc49cb362009-02-12 10:32:50 -03003517static int vino_streamoff(struct file *file, void *__fh,
3518 enum v4l2_buf_type i)
Ralf Baechled203a7e2005-09-06 15:19:37 -07003519{
Hans Verkuilc49cb362009-02-12 10:32:50 -03003520 struct vino_channel_settings *vcs = video_drvdata(file);
Ralf Baechled203a7e2005-09-06 15:19:37 -07003521 if (vcs->reading)
3522 return -EBUSY;
3523
3524 if (!vcs->streaming)
3525 return 0;
3526
Ralf Baechled203a7e2005-09-06 15:19:37 -07003527 vcs->streaming = 0;
Ladislav Michla637a112005-09-01 15:07:34 +00003528 vino_capture_stop(vcs);
Ralf Baechled203a7e2005-09-06 15:19:37 -07003529
3530 return 0;
3531}
3532
Hans Verkuilc49cb362009-02-12 10:32:50 -03003533static int vino_queryctrl(struct file *file, void *__fh,
Ralf Baechled203a7e2005-09-06 15:19:37 -07003534 struct v4l2_queryctrl *queryctrl)
3535{
Hans Verkuilc49cb362009-02-12 10:32:50 -03003536 struct vino_channel_settings *vcs = video_drvdata(file);
Ladislav Michla637a112005-09-01 15:07:34 +00003537 unsigned long flags;
Ralf Baechled203a7e2005-09-06 15:19:37 -07003538 int i;
3539 int err = 0;
3540
Ladislav Michla637a112005-09-01 15:07:34 +00003541 spin_lock_irqsave(&vino_drvdata->input_lock, flags);
Ralf Baechled203a7e2005-09-06 15:19:37 -07003542
3543 switch (vcs->input) {
3544 case VINO_INPUT_D1:
3545 for (i = 0; i < VINO_INDYCAM_V4L2_CONTROL_COUNT; i++) {
3546 if (vino_indycam_v4l2_controls[i].id ==
3547 queryctrl->id) {
3548 memcpy(queryctrl,
3549 &vino_indycam_v4l2_controls[i],
3550 sizeof(struct v4l2_queryctrl));
Ladislav Michla637a112005-09-01 15:07:34 +00003551 queryctrl->reserved[0] = 0;
Ralf Baechled203a7e2005-09-06 15:19:37 -07003552 goto found;
3553 }
3554 }
3555
3556 err = -EINVAL;
3557 break;
3558 case VINO_INPUT_COMPOSITE:
3559 case VINO_INPUT_SVIDEO:
3560 for (i = 0; i < VINO_SAA7191_V4L2_CONTROL_COUNT; i++) {
3561 if (vino_saa7191_v4l2_controls[i].id ==
3562 queryctrl->id) {
3563 memcpy(queryctrl,
3564 &vino_saa7191_v4l2_controls[i],
3565 sizeof(struct v4l2_queryctrl));
Ladislav Michla637a112005-09-01 15:07:34 +00003566 queryctrl->reserved[0] = 0;
Ralf Baechled203a7e2005-09-06 15:19:37 -07003567 goto found;
3568 }
3569 }
3570
3571 err = -EINVAL;
3572 break;
3573 default:
3574 err = -EINVAL;
3575 }
3576
3577 found:
Ladislav Michla637a112005-09-01 15:07:34 +00003578 spin_unlock_irqrestore(&vino_drvdata->input_lock, flags);
Ralf Baechled203a7e2005-09-06 15:19:37 -07003579
3580 return err;
3581}
3582
Hans Verkuilc49cb362009-02-12 10:32:50 -03003583static int vino_g_ctrl(struct file *file, void *__fh,
Ralf Baechled203a7e2005-09-06 15:19:37 -07003584 struct v4l2_control *control)
3585{
Hans Verkuilc49cb362009-02-12 10:32:50 -03003586 struct vino_channel_settings *vcs = video_drvdata(file);
Ladislav Michla637a112005-09-01 15:07:34 +00003587 unsigned long flags;
3588 int i;
Ralf Baechled203a7e2005-09-06 15:19:37 -07003589 int err = 0;
3590
Ladislav Michla637a112005-09-01 15:07:34 +00003591 spin_lock_irqsave(&vino_drvdata->input_lock, flags);
Ralf Baechled203a7e2005-09-06 15:19:37 -07003592
3593 switch (vcs->input) {
Ladislav Michla637a112005-09-01 15:07:34 +00003594 case VINO_INPUT_D1: {
Hans Verkuilcf4e9482009-02-27 09:05:10 -03003595 err = -EINVAL;
Ladislav Michla637a112005-09-01 15:07:34 +00003596 for (i = 0; i < VINO_INDYCAM_V4L2_CONTROL_COUNT; i++) {
Hans Verkuilcf4e9482009-02-27 09:05:10 -03003597 if (vino_indycam_v4l2_controls[i].id == control->id) {
3598 err = 0;
3599 break;
Ladislav Michla637a112005-09-01 15:07:34 +00003600 }
Ralf Baechled203a7e2005-09-06 15:19:37 -07003601 }
Ladislav Michla637a112005-09-01 15:07:34 +00003602
Hans Verkuilcf4e9482009-02-27 09:05:10 -03003603 if (err)
Ladislav Michla637a112005-09-01 15:07:34 +00003604 goto out;
Ladislav Michla637a112005-09-01 15:07:34 +00003605
Hans Verkuil48f4dac2009-02-18 19:18:26 -03003606 err = camera_call(core, g_ctrl, control);
Hans Verkuilcf4e9482009-02-27 09:05:10 -03003607 if (err)
3608 err = -EINVAL;
Ralf Baechled203a7e2005-09-06 15:19:37 -07003609 break;
Ladislav Michla637a112005-09-01 15:07:34 +00003610 }
Ralf Baechled203a7e2005-09-06 15:19:37 -07003611 case VINO_INPUT_COMPOSITE:
Ladislav Michla637a112005-09-01 15:07:34 +00003612 case VINO_INPUT_SVIDEO: {
Hans Verkuilcf4e9482009-02-27 09:05:10 -03003613 err = -EINVAL;
Ladislav Michla637a112005-09-01 15:07:34 +00003614 for (i = 0; i < VINO_SAA7191_V4L2_CONTROL_COUNT; i++) {
Hans Verkuilcf4e9482009-02-27 09:05:10 -03003615 if (vino_saa7191_v4l2_controls[i].id == control->id) {
3616 err = 0;
3617 break;
Ladislav Michla637a112005-09-01 15:07:34 +00003618 }
Ralf Baechled203a7e2005-09-06 15:19:37 -07003619 }
Ladislav Michla637a112005-09-01 15:07:34 +00003620
Hans Verkuilcf4e9482009-02-27 09:05:10 -03003621 if (err)
Ladislav Michla637a112005-09-01 15:07:34 +00003622 goto out;
Ladislav Michla637a112005-09-01 15:07:34 +00003623
Hans Verkuil48f4dac2009-02-18 19:18:26 -03003624 err = decoder_call(core, g_ctrl, control);
Hans Verkuilcf4e9482009-02-27 09:05:10 -03003625 if (err)
3626 err = -EINVAL;
Ralf Baechled203a7e2005-09-06 15:19:37 -07003627 break;
Ladislav Michla637a112005-09-01 15:07:34 +00003628 }
Ralf Baechled203a7e2005-09-06 15:19:37 -07003629 default:
3630 err = -EINVAL;
3631 }
3632
Ladislav Michla637a112005-09-01 15:07:34 +00003633out:
3634 spin_unlock_irqrestore(&vino_drvdata->input_lock, flags);
Ralf Baechled203a7e2005-09-06 15:19:37 -07003635
3636 return err;
3637}
3638
Hans Verkuilc49cb362009-02-12 10:32:50 -03003639static int vino_s_ctrl(struct file *file, void *__fh,
Ralf Baechled203a7e2005-09-06 15:19:37 -07003640 struct v4l2_control *control)
3641{
Hans Verkuilc49cb362009-02-12 10:32:50 -03003642 struct vino_channel_settings *vcs = video_drvdata(file);
Ladislav Michla637a112005-09-01 15:07:34 +00003643 unsigned long flags;
Ralf Baechled203a7e2005-09-06 15:19:37 -07003644 int i;
3645 int err = 0;
3646
Ladislav Michla637a112005-09-01 15:07:34 +00003647 spin_lock_irqsave(&vino_drvdata->input_lock, flags);
3648
3649 if (!vino_is_input_owner(vcs)) {
3650 err = -EBUSY;
3651 goto out;
3652 }
Ralf Baechled203a7e2005-09-06 15:19:37 -07003653
3654 switch (vcs->input) {
Ladislav Michla637a112005-09-01 15:07:34 +00003655 case VINO_INPUT_D1: {
Hans Verkuilcf4e9482009-02-27 09:05:10 -03003656 err = -EINVAL;
Ralf Baechled203a7e2005-09-06 15:19:37 -07003657 for (i = 0; i < VINO_INDYCAM_V4L2_CONTROL_COUNT; i++) {
Hans Verkuilcf4e9482009-02-27 09:05:10 -03003658 if (vino_indycam_v4l2_controls[i].id == control->id) {
3659 err = 0;
3660 break;
Ralf Baechled203a7e2005-09-06 15:19:37 -07003661 }
3662 }
Hans Verkuilcf4e9482009-02-27 09:05:10 -03003663 if (err)
3664 goto out;
3665 if (control->value < vino_indycam_v4l2_controls[i].minimum ||
3666 control->value > vino_indycam_v4l2_controls[i].maximum) {
3667 err = -ERANGE;
3668 goto out;
3669 }
Hans Verkuil48f4dac2009-02-18 19:18:26 -03003670 err = camera_call(core, s_ctrl, control);
Ladislav Michla637a112005-09-01 15:07:34 +00003671 if (err)
3672 err = -EINVAL;
Ralf Baechled203a7e2005-09-06 15:19:37 -07003673 break;
Ladislav Michla637a112005-09-01 15:07:34 +00003674 }
Ralf Baechled203a7e2005-09-06 15:19:37 -07003675 case VINO_INPUT_COMPOSITE:
Ladislav Michla637a112005-09-01 15:07:34 +00003676 case VINO_INPUT_SVIDEO: {
Hans Verkuilcf4e9482009-02-27 09:05:10 -03003677 err = -EINVAL;
Ralf Baechled203a7e2005-09-06 15:19:37 -07003678 for (i = 0; i < VINO_SAA7191_V4L2_CONTROL_COUNT; i++) {
Hans Verkuilcf4e9482009-02-27 09:05:10 -03003679 if (vino_saa7191_v4l2_controls[i].id == control->id) {
3680 err = 0;
3681 break;
Ralf Baechled203a7e2005-09-06 15:19:37 -07003682 }
3683 }
Hans Verkuilcf4e9482009-02-27 09:05:10 -03003684 if (err)
3685 goto out;
3686 if (control->value < vino_saa7191_v4l2_controls[i].minimum ||
3687 control->value > vino_saa7191_v4l2_controls[i].maximum) {
3688 err = -ERANGE;
3689 goto out;
3690 }
Ralf Baechled203a7e2005-09-06 15:19:37 -07003691
Hans Verkuil48f4dac2009-02-18 19:18:26 -03003692 err = decoder_call(core, s_ctrl, control);
Ladislav Michla637a112005-09-01 15:07:34 +00003693 if (err)
3694 err = -EINVAL;
Ralf Baechled203a7e2005-09-06 15:19:37 -07003695 break;
Ladislav Michla637a112005-09-01 15:07:34 +00003696 }
Ralf Baechled203a7e2005-09-06 15:19:37 -07003697 default:
3698 err = -EINVAL;
3699 }
3700
Ladislav Michla637a112005-09-01 15:07:34 +00003701out:
3702 spin_unlock_irqrestore(&vino_drvdata->input_lock, flags);
Ralf Baechled203a7e2005-09-06 15:19:37 -07003703
3704 return err;
3705}
3706
3707/* File operations */
3708
Hans Verkuilbec43662008-12-30 06:58:20 -03003709static int vino_open(struct file *file)
Ralf Baechled203a7e2005-09-06 15:19:37 -07003710{
Hans Verkuilc170ecf2008-08-23 08:32:09 -03003711 struct vino_channel_settings *vcs = video_drvdata(file);
Ralf Baechled203a7e2005-09-06 15:19:37 -07003712 int ret = 0;
3713 dprintk("open(): channel = %c\n",
3714 (vcs->channel == VINO_CHANNEL_A) ? 'A' : 'B');
3715
Ingo Molnar3593cab2006-02-07 06:49:14 -02003716 mutex_lock(&vcs->mutex);
Ralf Baechled203a7e2005-09-06 15:19:37 -07003717
3718 if (vcs->users) {
3719 dprintk("open(): driver busy\n");
3720 ret = -EBUSY;
3721 goto out;
3722 }
3723
3724 ret = vino_acquire_input(vcs);
3725 if (ret) {
3726 dprintk("open(): vino_acquire_input() failed\n");
3727 goto out;
3728 }
3729
3730 vcs->users++;
3731
3732 out:
Ingo Molnar3593cab2006-02-07 06:49:14 -02003733 mutex_unlock(&vcs->mutex);
Ralf Baechled203a7e2005-09-06 15:19:37 -07003734
3735 dprintk("open(): %s!\n", ret ? "failed" : "complete");
3736
3737 return ret;
3738}
3739
Hans Verkuilbec43662008-12-30 06:58:20 -03003740static int vino_close(struct file *file)
Ralf Baechled203a7e2005-09-06 15:19:37 -07003741{
Hans Verkuilc170ecf2008-08-23 08:32:09 -03003742 struct vino_channel_settings *vcs = video_drvdata(file);
Ralf Baechled203a7e2005-09-06 15:19:37 -07003743 dprintk("close():\n");
3744
Ingo Molnar3593cab2006-02-07 06:49:14 -02003745 mutex_lock(&vcs->mutex);
Ralf Baechled203a7e2005-09-06 15:19:37 -07003746
3747 vcs->users--;
3748
3749 if (!vcs->users) {
3750 vino_release_input(vcs);
3751
3752 /* stop DMA and free buffers */
3753 vino_capture_stop(vcs);
3754 vino_queue_free(&vcs->fb_queue);
3755 }
3756
Ingo Molnar3593cab2006-02-07 06:49:14 -02003757 mutex_unlock(&vcs->mutex);
Ralf Baechled203a7e2005-09-06 15:19:37 -07003758
3759 return 0;
3760}
3761
3762static void vino_vm_open(struct vm_area_struct *vma)
3763{
3764 struct vino_framebuffer *fb = vma->vm_private_data;
3765
3766 fb->map_count++;
3767 dprintk("vino_vm_open(): count = %d\n", fb->map_count);
3768}
3769
3770static void vino_vm_close(struct vm_area_struct *vma)
3771{
3772 struct vino_framebuffer *fb = vma->vm_private_data;
3773
3774 fb->map_count--;
3775 dprintk("vino_vm_close(): count = %d\n", fb->map_count);
3776}
3777
3778static struct vm_operations_struct vino_vm_ops = {
3779 .open = vino_vm_open,
3780 .close = vino_vm_close,
3781};
3782
3783static int vino_mmap(struct file *file, struct vm_area_struct *vma)
3784{
Hans Verkuilc170ecf2008-08-23 08:32:09 -03003785 struct vino_channel_settings *vcs = video_drvdata(file);
Ralf Baechled203a7e2005-09-06 15:19:37 -07003786
3787 unsigned long start = vma->vm_start;
3788 unsigned long size = vma->vm_end - vma->vm_start;
3789 unsigned long offset = vma->vm_pgoff << PAGE_SHIFT;
3790
3791 struct vino_framebuffer *fb = NULL;
3792 unsigned int i, length;
3793 int ret = 0;
3794
3795 dprintk("mmap():\n");
3796
3797 // TODO: reject mmap if already mapped
3798
Ingo Molnar3593cab2006-02-07 06:49:14 -02003799 if (mutex_lock_interruptible(&vcs->mutex))
Ralf Baechled203a7e2005-09-06 15:19:37 -07003800 return -EINTR;
3801
3802 if (vcs->reading) {
3803 ret = -EBUSY;
3804 goto out;
3805 }
3806
3807 // TODO: check queue type
3808
3809 if (!(vma->vm_flags & VM_WRITE)) {
3810 dprintk("mmap(): app bug: PROT_WRITE please\n");
3811 ret = -EINVAL;
3812 goto out;
3813 }
3814 if (!(vma->vm_flags & VM_SHARED)) {
3815 dprintk("mmap(): app bug: MAP_SHARED please\n");
3816 ret = -EINVAL;
3817 goto out;
3818 }
3819
3820 /* find the correct buffer using offset */
3821 length = vino_queue_get_length(&vcs->fb_queue);
3822 if (length == 0) {
3823 dprintk("mmap(): queue not initialized\n");
3824 ret = -EINVAL;
3825 goto out;
3826 }
3827
3828 for (i = 0; i < length; i++) {
3829 fb = vino_queue_get_buffer(&vcs->fb_queue, i);
3830 if (fb == NULL) {
3831 dprintk("mmap(): vino_queue_get_buffer() failed\n");
3832 ret = -EINVAL;
3833 goto out;
3834 }
3835
3836 if (fb->offset == offset)
3837 goto found;
3838 }
3839
3840 dprintk("mmap(): invalid offset = %lu\n", offset);
3841 ret = -EINVAL;
3842 goto out;
3843
3844found:
3845 dprintk("mmap(): buffer = %d\n", i);
3846
3847 if (size > (fb->desc_table.page_count * PAGE_SIZE)) {
3848 dprintk("mmap(): failed: size = %lu > %lu\n",
3849 size, fb->desc_table.page_count * PAGE_SIZE);
3850 ret = -EINVAL;
3851 goto out;
3852 }
3853
3854 for (i = 0; i < fb->desc_table.page_count; i++) {
3855 unsigned long pfn =
3856 virt_to_phys((void *)fb->desc_table.virtual[i]) >>
3857 PAGE_SHIFT;
3858
3859 if (size < PAGE_SIZE)
3860 break;
3861
3862 // protection was: PAGE_READONLY
3863 if (remap_pfn_range(vma, start, pfn, PAGE_SIZE,
3864 vma->vm_page_prot)) {
3865 dprintk("mmap(): remap_pfn_range() failed\n");
3866 ret = -EAGAIN;
3867 goto out;
3868 }
3869
3870 start += PAGE_SIZE;
3871 size -= PAGE_SIZE;
3872 }
3873
3874 fb->map_count = 1;
3875
3876 vma->vm_flags |= VM_DONTEXPAND | VM_RESERVED;
3877 vma->vm_flags &= ~VM_IO;
3878 vma->vm_private_data = fb;
3879 vma->vm_file = file;
3880 vma->vm_ops = &vino_vm_ops;
3881
3882out:
Ingo Molnar3593cab2006-02-07 06:49:14 -02003883 mutex_unlock(&vcs->mutex);
Ralf Baechled203a7e2005-09-06 15:19:37 -07003884
3885 return ret;
3886}
3887
3888static unsigned int vino_poll(struct file *file, poll_table *pt)
3889{
Hans Verkuilc170ecf2008-08-23 08:32:09 -03003890 struct vino_channel_settings *vcs = video_drvdata(file);
Ralf Baechled203a7e2005-09-06 15:19:37 -07003891 unsigned int outgoing;
3892 unsigned int ret = 0;
3893
3894 // lock mutex (?)
3895 // TODO: this has to be corrected for different read modes
3896
3897 dprintk("poll():\n");
3898
3899 if (vino_queue_get_outgoing(&vcs->fb_queue, &outgoing)) {
3900 dprintk("poll(): vino_queue_get_outgoing() failed\n");
3901 ret = POLLERR;
3902 goto error;
3903 }
3904 if (outgoing > 0)
3905 goto over;
3906
3907 poll_wait(file, &vcs->fb_queue.frame_wait_queue, pt);
3908
3909 if (vino_queue_get_outgoing(&vcs->fb_queue, &outgoing)) {
3910 dprintk("poll(): vino_queue_get_outgoing() failed\n");
3911 ret = POLLERR;
3912 goto error;
3913 }
3914
3915over:
3916 dprintk("poll(): data %savailable\n",
3917 (outgoing > 0) ? "" : "not ");
Ladislav Michla637a112005-09-01 15:07:34 +00003918
3919 if (outgoing > 0)
Ralf Baechled203a7e2005-09-06 15:19:37 -07003920 ret = POLLIN | POLLRDNORM;
Ralf Baechled203a7e2005-09-06 15:19:37 -07003921
3922error:
Ralf Baechled203a7e2005-09-06 15:19:37 -07003923 return ret;
3924}
3925
Hans Verkuil069b7472008-12-30 07:04:34 -03003926static long vino_ioctl(struct file *file,
Ralf Baechled203a7e2005-09-06 15:19:37 -07003927 unsigned int cmd, unsigned long arg)
3928{
Hans Verkuilc170ecf2008-08-23 08:32:09 -03003929 struct vino_channel_settings *vcs = video_drvdata(file);
Hans Verkuil069b7472008-12-30 07:04:34 -03003930 long ret;
Ralf Baechled203a7e2005-09-06 15:19:37 -07003931
Ingo Molnar3593cab2006-02-07 06:49:14 -02003932 if (mutex_lock_interruptible(&vcs->mutex))
Ralf Baechled203a7e2005-09-06 15:19:37 -07003933 return -EINTR;
3934
Hans Verkuilc49cb362009-02-12 10:32:50 -03003935 ret = video_ioctl2(file, cmd, arg);
Ralf Baechled203a7e2005-09-06 15:19:37 -07003936
Ingo Molnar3593cab2006-02-07 06:49:14 -02003937 mutex_unlock(&vcs->mutex);
Ralf Baechled203a7e2005-09-06 15:19:37 -07003938
3939 return ret;
3940}
3941
3942/* Initialization and cleanup */
3943
Douglas Schilling Landgrafff699e62008-04-22 14:41:48 -03003944/* __initdata */
3945static int vino_init_stage;
Ralf Baechled203a7e2005-09-06 15:19:37 -07003946
Hans Verkuilc49cb362009-02-12 10:32:50 -03003947const struct v4l2_ioctl_ops vino_ioctl_ops = {
3948 .vidioc_enum_fmt_vid_cap = vino_enum_fmt_vid_cap,
3949 .vidioc_g_fmt_vid_cap = vino_g_fmt_vid_cap,
3950 .vidioc_s_fmt_vid_cap = vino_s_fmt_vid_cap,
3951 .vidioc_try_fmt_vid_cap = vino_try_fmt_vid_cap,
3952 .vidioc_querycap = vino_querycap,
3953 .vidioc_enum_input = vino_enum_input,
3954 .vidioc_g_input = vino_g_input,
3955 .vidioc_s_input = vino_s_input,
3956 .vidioc_g_std = vino_g_std,
3957 .vidioc_s_std = vino_s_std,
3958 .vidioc_querystd = vino_querystd,
3959 .vidioc_cropcap = vino_cropcap,
3960 .vidioc_s_crop = vino_s_crop,
3961 .vidioc_g_crop = vino_g_crop,
3962 .vidioc_s_parm = vino_s_parm,
3963 .vidioc_g_parm = vino_g_parm,
3964 .vidioc_reqbufs = vino_reqbufs,
3965 .vidioc_querybuf = vino_querybuf,
3966 .vidioc_qbuf = vino_qbuf,
3967 .vidioc_dqbuf = vino_dqbuf,
3968 .vidioc_streamon = vino_streamon,
3969 .vidioc_streamoff = vino_streamoff,
3970 .vidioc_queryctrl = vino_queryctrl,
3971 .vidioc_g_ctrl = vino_g_ctrl,
3972 .vidioc_s_ctrl = vino_s_ctrl,
3973};
3974
Hans Verkuilbec43662008-12-30 06:58:20 -03003975static const struct v4l2_file_operations vino_fops = {
Ralf Baechled203a7e2005-09-06 15:19:37 -07003976 .owner = THIS_MODULE,
3977 .open = vino_open,
3978 .release = vino_close,
Hans Verkuil28959632009-02-18 18:53:47 -03003979 .unlocked_ioctl = vino_ioctl,
Ralf Baechled203a7e2005-09-06 15:19:37 -07003980 .mmap = vino_mmap,
3981 .poll = vino_poll,
Ralf Baechled203a7e2005-09-06 15:19:37 -07003982};
3983
Hans Verkuil0ef4dba2009-02-12 11:31:13 -03003984static struct video_device vdev_template = {
Ralf Baechled203a7e2005-09-06 15:19:37 -07003985 .name = "NOT SET",
Ralf Baechled203a7e2005-09-06 15:19:37 -07003986 .fops = &vino_fops,
Hans Verkuilc49cb362009-02-12 10:32:50 -03003987 .ioctl_ops = &vino_ioctl_ops,
3988 .tvnorms = V4L2_STD_NTSC | V4L2_STD_PAL | V4L2_STD_SECAM,
Ralf Baechled203a7e2005-09-06 15:19:37 -07003989 .minor = -1,
3990};
3991
3992static void vino_module_cleanup(int stage)
3993{
3994 switch(stage) {
Hans Verkuil28959632009-02-18 18:53:47 -03003995 case 11:
Hans Verkuil0ef4dba2009-02-12 11:31:13 -03003996 video_unregister_device(vino_drvdata->b.vdev);
3997 vino_drvdata->b.vdev = NULL;
Hans Verkuil28959632009-02-18 18:53:47 -03003998 case 10:
Hans Verkuil0ef4dba2009-02-12 11:31:13 -03003999 video_unregister_device(vino_drvdata->a.vdev);
4000 vino_drvdata->a.vdev = NULL;
Hans Verkuil28959632009-02-18 18:53:47 -03004001 case 9:
Ralf Baechled203a7e2005-09-06 15:19:37 -07004002 vino_i2c_del_bus();
Hans Verkuil28959632009-02-18 18:53:47 -03004003 case 8:
Ralf Baechled203a7e2005-09-06 15:19:37 -07004004 free_irq(SGI_VINO_IRQ, NULL);
Hans Verkuil28959632009-02-18 18:53:47 -03004005 case 7:
Hans Verkuil0ef4dba2009-02-12 11:31:13 -03004006 if (vino_drvdata->b.vdev) {
4007 video_device_release(vino_drvdata->b.vdev);
4008 vino_drvdata->b.vdev = NULL;
Ralf Baechled203a7e2005-09-06 15:19:37 -07004009 }
Hans Verkuil28959632009-02-18 18:53:47 -03004010 case 6:
Hans Verkuil0ef4dba2009-02-12 11:31:13 -03004011 if (vino_drvdata->a.vdev) {
4012 video_device_release(vino_drvdata->a.vdev);
4013 vino_drvdata->a.vdev = NULL;
Ralf Baechled203a7e2005-09-06 15:19:37 -07004014 }
Hans Verkuil28959632009-02-18 18:53:47 -03004015 case 5:
Ralf Baechled203a7e2005-09-06 15:19:37 -07004016 /* all entries in dma_cpu dummy table have the same address */
4017 dma_unmap_single(NULL,
4018 vino_drvdata->dummy_desc_table.dma_cpu[0],
4019 PAGE_SIZE, DMA_FROM_DEVICE);
4020 dma_free_coherent(NULL, VINO_DUMMY_DESC_COUNT
4021 * sizeof(dma_addr_t),
4022 (void *)vino_drvdata->
4023 dummy_desc_table.dma_cpu,
4024 vino_drvdata->dummy_desc_table.dma);
Hans Verkuil28959632009-02-18 18:53:47 -03004025 case 4:
Ralf Baechled203a7e2005-09-06 15:19:37 -07004026 free_page(vino_drvdata->dummy_page);
Hans Verkuil28959632009-02-18 18:53:47 -03004027 case 3:
4028 v4l2_device_unregister(&vino_drvdata->v4l2_dev);
Ralf Baechled203a7e2005-09-06 15:19:37 -07004029 case 2:
4030 kfree(vino_drvdata);
4031 case 1:
4032 iounmap(vino);
4033 case 0:
4034 break;
4035 default:
4036 dprintk("vino_module_cleanup(): invalid cleanup stage = %d\n",
4037 stage);
4038 }
4039}
4040
4041static int vino_probe(void)
4042{
4043 unsigned long rev_id;
4044
4045 if (ip22_is_fullhouse()) {
4046 printk(KERN_ERR "VINO doesn't exist in IP22 Fullhouse\n");
4047 return -ENODEV;
4048 }
4049
4050 if (!(sgimc->systemid & SGIMC_SYSID_EPRESENT)) {
4051 printk(KERN_ERR "VINO is not found (EISA BUS not present)\n");
4052 return -ENODEV;
4053 }
4054
4055 vino = (struct sgi_vino *)ioremap(VINO_BASE, sizeof(struct sgi_vino));
4056 if (!vino) {
4057 printk(KERN_ERR "VINO: ioremap() failed\n");
4058 return -EIO;
4059 }
4060 vino_init_stage++;
4061
4062 if (get_dbe(rev_id, &(vino->rev_id))) {
4063 printk(KERN_ERR "Failed to read VINO revision register\n");
4064 vino_module_cleanup(vino_init_stage);
4065 return -ENODEV;
4066 }
4067
4068 if (VINO_ID_VALUE(rev_id) != VINO_CHIP_ID) {
4069 printk(KERN_ERR "Unknown VINO chip ID (Rev/ID: 0x%02lx)\n",
4070 rev_id);
4071 vino_module_cleanup(vino_init_stage);
4072 return -ENODEV;
4073 }
4074
Ladislav Michla637a112005-09-01 15:07:34 +00004075 printk(KERN_INFO "VINO revision %ld found\n", VINO_REV_NUM(rev_id));
Ralf Baechled203a7e2005-09-06 15:19:37 -07004076
4077 return 0;
4078}
4079
4080static int vino_init(void)
4081{
4082 dma_addr_t dma_dummy_address;
Hans Verkuil28959632009-02-18 18:53:47 -03004083 int err;
Ralf Baechled203a7e2005-09-06 15:19:37 -07004084 int i;
4085
Panagiotis Issaris74081872006-01-11 19:40:56 -02004086 vino_drvdata = kzalloc(sizeof(struct vino_settings), GFP_KERNEL);
Ralf Baechled203a7e2005-09-06 15:19:37 -07004087 if (!vino_drvdata) {
4088 vino_module_cleanup(vino_init_stage);
4089 return -ENOMEM;
4090 }
Ralf Baechled203a7e2005-09-06 15:19:37 -07004091 vino_init_stage++;
Hans Verkuil28959632009-02-18 18:53:47 -03004092 strlcpy(vino_drvdata->v4l2_dev.name, "vino",
4093 sizeof(vino_drvdata->v4l2_dev.name));
4094 err = v4l2_device_register(NULL, &vino_drvdata->v4l2_dev);
4095 if (err)
4096 return err;
4097 vino_init_stage++;
Ralf Baechled203a7e2005-09-06 15:19:37 -07004098
4099 /* create a dummy dma descriptor */
4100 vino_drvdata->dummy_page = get_zeroed_page(GFP_KERNEL | GFP_DMA);
4101 if (!vino_drvdata->dummy_page) {
4102 vino_module_cleanup(vino_init_stage);
4103 return -ENOMEM;
4104 }
4105 vino_init_stage++;
4106
4107 // TODO: use page_count in dummy_desc_table
4108
4109 vino_drvdata->dummy_desc_table.dma_cpu =
4110 dma_alloc_coherent(NULL,
4111 VINO_DUMMY_DESC_COUNT * sizeof(dma_addr_t),
4112 &vino_drvdata->dummy_desc_table.dma,
4113 GFP_KERNEL | GFP_DMA);
4114 if (!vino_drvdata->dummy_desc_table.dma_cpu) {
4115 vino_module_cleanup(vino_init_stage);
4116 return -ENOMEM;
4117 }
4118 vino_init_stage++;
4119
4120 dma_dummy_address = dma_map_single(NULL,
4121 (void *)vino_drvdata->dummy_page,
4122 PAGE_SIZE, DMA_FROM_DEVICE);
4123 for (i = 0; i < VINO_DUMMY_DESC_COUNT; i++) {
4124 vino_drvdata->dummy_desc_table.dma_cpu[i] = dma_dummy_address;
4125 }
4126
4127 /* initialize VINO */
4128
4129 vino->control = 0;
4130 vino->a.next_4_desc = vino_drvdata->dummy_desc_table.dma;
4131 vino->b.next_4_desc = vino_drvdata->dummy_desc_table.dma;
4132 udelay(VINO_DESC_FETCH_DELAY);
4133
4134 vino->intr_status = 0;
4135
4136 vino->a.fifo_thres = VINO_FIFO_THRESHOLD_DEFAULT;
4137 vino->b.fifo_thres = VINO_FIFO_THRESHOLD_DEFAULT;
4138
4139 return 0;
4140}
4141
4142static int vino_init_channel_settings(struct vino_channel_settings *vcs,
4143 unsigned int channel, const char *name)
4144{
4145 vcs->channel = channel;
4146 vcs->input = VINO_INPUT_NONE;
4147 vcs->alpha = 0;
4148 vcs->users = 0;
4149 vcs->data_format = VINO_DATA_FMT_GREY;
4150 vcs->data_norm = VINO_DATA_NORM_NTSC;
4151 vcs->decimation = 1;
4152 vino_set_default_clipping(vcs);
4153 vino_set_default_framerate(vcs);
4154
4155 vcs->capturing = 0;
4156
Ingo Molnar3593cab2006-02-07 06:49:14 -02004157 mutex_init(&vcs->mutex);
Ralf Baechled203a7e2005-09-06 15:19:37 -07004158 spin_lock_init(&vcs->capture_lock);
4159
Ingo Molnar3593cab2006-02-07 06:49:14 -02004160 mutex_init(&vcs->fb_queue.queue_mutex);
Ralf Baechled203a7e2005-09-06 15:19:37 -07004161 spin_lock_init(&vcs->fb_queue.queue_lock);
4162 init_waitqueue_head(&vcs->fb_queue.frame_wait_queue);
4163
Hans Verkuil0ef4dba2009-02-12 11:31:13 -03004164 vcs->vdev = video_device_alloc();
4165 if (!vcs->vdev) {
Ralf Baechled203a7e2005-09-06 15:19:37 -07004166 vino_module_cleanup(vino_init_stage);
4167 return -ENOMEM;
4168 }
4169 vino_init_stage++;
4170
Hans Verkuil0ef4dba2009-02-12 11:31:13 -03004171 memcpy(vcs->vdev, &vdev_template,
Ralf Baechled203a7e2005-09-06 15:19:37 -07004172 sizeof(struct video_device));
Hans Verkuil0ef4dba2009-02-12 11:31:13 -03004173 strcpy(vcs->vdev->name, name);
4174 vcs->vdev->release = video_device_release;
Hans Verkuil28959632009-02-18 18:53:47 -03004175 vcs->vdev->v4l2_dev = &vino_drvdata->v4l2_dev;
Ralf Baechled203a7e2005-09-06 15:19:37 -07004176
Hans Verkuil0ef4dba2009-02-12 11:31:13 -03004177 video_set_drvdata(vcs->vdev, vcs);
Ralf Baechled203a7e2005-09-06 15:19:37 -07004178
4179 return 0;
4180}
4181
4182static int __init vino_module_init(void)
4183{
Hans Verkuil48f4dac2009-02-18 19:18:26 -03004184 unsigned short addr[] = { 0, I2C_CLIENT_END };
Ralf Baechled203a7e2005-09-06 15:19:37 -07004185 int ret;
4186
4187 printk(KERN_INFO "SGI VINO driver version %s\n",
4188 VINO_MODULE_VERSION);
4189
4190 ret = vino_probe();
4191 if (ret)
4192 return ret;
4193
4194 ret = vino_init();
4195 if (ret)
4196 return ret;
4197
4198 /* initialize data structures */
4199
4200 spin_lock_init(&vino_drvdata->vino_lock);
4201 spin_lock_init(&vino_drvdata->input_lock);
4202
4203 ret = vino_init_channel_settings(&vino_drvdata->a, VINO_CHANNEL_A,
Hans Verkuil0ef4dba2009-02-12 11:31:13 -03004204 vino_vdev_name_a);
Ralf Baechled203a7e2005-09-06 15:19:37 -07004205 if (ret)
4206 return ret;
4207
4208 ret = vino_init_channel_settings(&vino_drvdata->b, VINO_CHANNEL_B,
Hans Verkuil0ef4dba2009-02-12 11:31:13 -03004209 vino_vdev_name_b);
Ralf Baechled203a7e2005-09-06 15:19:37 -07004210 if (ret)
4211 return ret;
4212
4213 /* initialize hardware and register V4L devices */
4214
4215 ret = request_irq(SGI_VINO_IRQ, vino_interrupt, 0,
4216 vino_driver_description, NULL);
4217 if (ret) {
4218 printk(KERN_ERR "VINO: requesting IRQ %02d failed\n",
4219 SGI_VINO_IRQ);
4220 vino_module_cleanup(vino_init_stage);
4221 return -EAGAIN;
4222 }
4223 vino_init_stage++;
4224
4225 ret = vino_i2c_add_bus();
4226 if (ret) {
4227 printk(KERN_ERR "VINO I2C bus registration failed\n");
4228 vino_module_cleanup(vino_init_stage);
4229 return ret;
4230 }
Hans Verkuil28959632009-02-18 18:53:47 -03004231 i2c_set_adapdata(&vino_i2c_adapter, &vino_drvdata->v4l2_dev);
Ralf Baechled203a7e2005-09-06 15:19:37 -07004232 vino_init_stage++;
4233
Hans Verkuil0ef4dba2009-02-12 11:31:13 -03004234 ret = video_register_device(vino_drvdata->a.vdev,
Ralf Baechled203a7e2005-09-06 15:19:37 -07004235 VFL_TYPE_GRABBER, -1);
4236 if (ret < 0) {
4237 printk(KERN_ERR "VINO channel A Video4Linux-device "
4238 "registration failed\n");
4239 vino_module_cleanup(vino_init_stage);
4240 return -EINVAL;
4241 }
4242 vino_init_stage++;
4243
Hans Verkuil0ef4dba2009-02-12 11:31:13 -03004244 ret = video_register_device(vino_drvdata->b.vdev,
Ralf Baechled203a7e2005-09-06 15:19:37 -07004245 VFL_TYPE_GRABBER, -1);
4246 if (ret < 0) {
4247 printk(KERN_ERR "VINO channel B Video4Linux-device "
4248 "registration failed\n");
4249 vino_module_cleanup(vino_init_stage);
4250 return -EINVAL;
4251 }
4252 vino_init_stage++;
4253
Hans Verkuil48f4dac2009-02-18 19:18:26 -03004254 addr[0] = 0x45;
4255 vino_drvdata->decoder = v4l2_i2c_new_probed_subdev(&vino_i2c_adapter,
4256 "saa7191", "saa7191", addr);
4257 addr[0] = 0x2b;
4258 vino_drvdata->camera = v4l2_i2c_new_probed_subdev(&vino_i2c_adapter,
4259 "indycam", "indycam", addr);
Ralf Baechled203a7e2005-09-06 15:19:37 -07004260
4261 dprintk("init complete!\n");
4262
4263 return 0;
4264}
4265
4266static void __exit vino_module_exit(void)
4267{
4268 dprintk("exiting, stage = %d ...\n", vino_init_stage);
4269 vino_module_cleanup(vino_init_stage);
4270 dprintk("cleanup complete, exit!\n");
4271}
4272
4273module_init(vino_module_init);
4274module_exit(vino_module_exit);