aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/staging
diff options
context:
space:
mode:
authorHans Verkuil <hans.verkuil@cisco.com>2014-12-02 10:40:31 -0500
committerMauro Carvalho Chehab <mchehab@osg.samsung.com>2014-12-16 20:21:42 -0500
commitc1d9e03d4ef47de60b414fa25f05f9c867f43c5a (patch)
treee020a2ff0493627e0be0103e151070d1a2f45122 /drivers/staging
parent77911fd267cd8b564f03f025eb128b115489bbe5 (diff)
[media] vino/saa7191: move to staging in preparation for removal
These drivers haven't been tested in a long, long time. The hardware is ancient and hopelessly obsolete. These drivers also need to be converted to newer media frameworks but due to the lack of hardware that's going to be impossible. So these drivers are a prime candidate for removal. If someone is interested in working on these drivers to prevent their removal, then please contact the linux-media mailinglist. Signed-off-by: Hans Verkuil <hans.verkuil@cisco.com> Signed-off-by: Mauro Carvalho Chehab <mchehab@osg.samsung.com>
Diffstat (limited to 'drivers/staging')
-rw-r--r--drivers/staging/media/Kconfig2
-rw-r--r--drivers/staging/media/Makefile1
-rw-r--r--drivers/staging/media/vino/Kconfig24
-rw-r--r--drivers/staging/media/vino/Makefile3
-rw-r--r--drivers/staging/media/vino/indycam.c378
-rw-r--r--drivers/staging/media/vino/indycam.h93
-rw-r--r--drivers/staging/media/vino/saa7191.c649
-rw-r--r--drivers/staging/media/vino/saa7191.h245
-rw-r--r--drivers/staging/media/vino/vino.c4345
-rw-r--r--drivers/staging/media/vino/vino.h138
10 files changed, 5878 insertions, 0 deletions
diff --git a/drivers/staging/media/Kconfig b/drivers/staging/media/Kconfig
index 96498b7fc20e..6dce44ed48b8 100644
--- a/drivers/staging/media/Kconfig
+++ b/drivers/staging/media/Kconfig
@@ -33,6 +33,8 @@ source "drivers/staging/media/mn88473/Kconfig"
33 33
34source "drivers/staging/media/omap4iss/Kconfig" 34source "drivers/staging/media/omap4iss/Kconfig"
35 35
36source "drivers/staging/media/vino/Kconfig"
37
36# Keep LIRC at the end, as it has sub-menus 38# Keep LIRC at the end, as it has sub-menus
37source "drivers/staging/media/lirc/Kconfig" 39source "drivers/staging/media/lirc/Kconfig"
38 40
diff --git a/drivers/staging/media/Makefile b/drivers/staging/media/Makefile
index 30fb352fc4a9..7b713e73bc59 100644
--- a/drivers/staging/media/Makefile
+++ b/drivers/staging/media/Makefile
@@ -6,4 +6,5 @@ obj-$(CONFIG_VIDEO_DM365_VPFE) += davinci_vpfe/
6obj-$(CONFIG_VIDEO_OMAP4) += omap4iss/ 6obj-$(CONFIG_VIDEO_OMAP4) += omap4iss/
7obj-$(CONFIG_DVB_MN88472) += mn88472/ 7obj-$(CONFIG_DVB_MN88472) += mn88472/
8obj-$(CONFIG_DVB_MN88473) += mn88473/ 8obj-$(CONFIG_DVB_MN88473) += mn88473/
9obj-y += vino/
9 10
diff --git a/drivers/staging/media/vino/Kconfig b/drivers/staging/media/vino/Kconfig
new file mode 100644
index 000000000000..03700dadafd8
--- /dev/null
+++ b/drivers/staging/media/vino/Kconfig
@@ -0,0 +1,24 @@
1config VIDEO_VINO
2 tristate "SGI Vino Video For Linux (Deprecated)"
3 depends on I2C && SGI_IP22 && VIDEO_V4L2
4 select VIDEO_SAA7191 if MEDIA_SUBDRV_AUTOSELECT
5 help
6 Say Y here to build in support for the Vino video input system found
7 on SGI Indy machines.
8
9 This driver is deprecated and will be removed soon. If you have
10 hardware for this and you want to work on this driver, then contact
11 the linux-media mailinglist.
12
13config VIDEO_SAA7191
14 tristate "Philips SAA7191 video decoder (Deprecated)"
15 depends on VIDEO_V4L2 && I2C
16 ---help---
17 Support for the Philips SAA7191 video decoder.
18
19 This driver is deprecated and will be removed soon. If you have
20 hardware for this and you want to work on this driver, then contact
21 the linux-media mailinglist.
22
23 To compile this driver as a module, choose M here: the
24 module will be called saa7191.
diff --git a/drivers/staging/media/vino/Makefile b/drivers/staging/media/vino/Makefile
new file mode 100644
index 000000000000..914c2513687c
--- /dev/null
+++ b/drivers/staging/media/vino/Makefile
@@ -0,0 +1,3 @@
1obj-$(CONFIG_VIDEO_VINO) += indycam.o
2obj-$(CONFIG_VIDEO_VINO) += vino.o
3obj-$(CONFIG_VIDEO_SAA7191) += saa7191.o
diff --git a/drivers/staging/media/vino/indycam.c b/drivers/staging/media/vino/indycam.c
new file mode 100644
index 000000000000..f1d192bbcb4c
--- /dev/null
+++ b/drivers/staging/media/vino/indycam.c
@@ -0,0 +1,378 @@
1/*
2 * indycam.c - Silicon Graphics IndyCam digital camera driver
3 *
4 * Copyright (C) 2003 Ladislav Michl <ladis@linux-mips.org>
5 * Copyright (C) 2004,2005 Mikael Nousiainen <tmnousia@cc.hut.fi>
6 *
7 * This program is free software; you can redistribute it and/or modify
8 * it under the terms of the GNU General Public License version 2 as
9 * published by the Free Software Foundation.
10 */
11
12#include <linux/delay.h>
13#include <linux/errno.h>
14#include <linux/fs.h>
15#include <linux/init.h>
16#include <linux/kernel.h>
17#include <linux/major.h>
18#include <linux/module.h>
19#include <linux/mm.h>
20#include <linux/slab.h>
21
22/* IndyCam decodes stream of photons into digital image representation ;-) */
23#include <linux/videodev2.h>
24#include <linux/i2c.h>
25#include <media/v4l2-device.h>
26
27#include "indycam.h"
28
29#define INDYCAM_MODULE_VERSION "0.0.5"
30
31MODULE_DESCRIPTION("SGI IndyCam driver");
32MODULE_VERSION(INDYCAM_MODULE_VERSION);
33MODULE_AUTHOR("Mikael Nousiainen <tmnousia@cc.hut.fi>");
34MODULE_LICENSE("GPL");
35
36
37// #define INDYCAM_DEBUG
38
39#ifdef INDYCAM_DEBUG
40#define dprintk(x...) printk("IndyCam: " x);
41#define indycam_regdump(client) indycam_regdump_debug(client)
42#else
43#define dprintk(x...)
44#define indycam_regdump(client)
45#endif
46
47struct indycam {
48 struct v4l2_subdev sd;
49 u8 version;
50};
51
52static inline struct indycam *to_indycam(struct v4l2_subdev *sd)
53{
54 return container_of(sd, struct indycam, sd);
55}
56
57static const u8 initseq[] = {
58 INDYCAM_CONTROL_AGCENA, /* INDYCAM_CONTROL */
59 INDYCAM_SHUTTER_60, /* INDYCAM_SHUTTER */
60 INDYCAM_GAIN_DEFAULT, /* INDYCAM_GAIN */
61 0x00, /* INDYCAM_BRIGHTNESS (read-only) */
62 INDYCAM_RED_BALANCE_DEFAULT, /* INDYCAM_RED_BALANCE */
63 INDYCAM_BLUE_BALANCE_DEFAULT, /* INDYCAM_BLUE_BALANCE */
64 INDYCAM_RED_SATURATION_DEFAULT, /* INDYCAM_RED_SATURATION */
65 INDYCAM_BLUE_SATURATION_DEFAULT,/* INDYCAM_BLUE_SATURATION */
66};
67
68/* IndyCam register handling */
69
70static int indycam_read_reg(struct v4l2_subdev *sd, u8 reg, u8 *value)
71{
72 struct i2c_client *client = v4l2_get_subdevdata(sd);
73 int ret;
74
75 if (reg == INDYCAM_REG_RESET) {
76 dprintk("indycam_read_reg(): "
77 "skipping write-only register %d\n", reg);
78 *value = 0;
79 return 0;
80 }
81
82 ret = i2c_smbus_read_byte_data(client, reg);
83
84 if (ret < 0) {
85 printk(KERN_ERR "IndyCam: indycam_read_reg(): read failed, "
86 "register = 0x%02x\n", reg);
87 return ret;
88 }
89
90 *value = (u8)ret;
91
92 return 0;
93}
94
95static int indycam_write_reg(struct v4l2_subdev *sd, u8 reg, u8 value)
96{
97 struct i2c_client *client = v4l2_get_subdevdata(sd);
98 int err;
99
100 if (reg == INDYCAM_REG_BRIGHTNESS || reg == INDYCAM_REG_VERSION) {
101 dprintk("indycam_write_reg(): "
102 "skipping read-only register %d\n", reg);
103 return 0;
104 }
105
106 dprintk("Writing Reg %d = 0x%02x\n", reg, value);
107 err = i2c_smbus_write_byte_data(client, reg, value);
108
109 if (err) {
110 printk(KERN_ERR "IndyCam: indycam_write_reg(): write failed, "
111 "register = 0x%02x, value = 0x%02x\n", reg, value);
112 }
113 return err;
114}
115
116static int indycam_write_block(struct v4l2_subdev *sd, u8 reg,
117 u8 length, u8 *data)
118{
119 int i, err;
120
121 for (i = 0; i < length; i++) {
122 err = indycam_write_reg(sd, reg + i, data[i]);
123 if (err)
124 return err;
125 }
126
127 return 0;
128}
129
130/* Helper functions */
131
132#ifdef INDYCAM_DEBUG
133static void indycam_regdump_debug(struct v4l2_subdev *sd)
134{
135 int i;
136 u8 val;
137
138 for (i = 0; i < 9; i++) {
139 indycam_read_reg(sd, i, &val);
140 dprintk("Reg %d = 0x%02x\n", i, val);
141 }
142}
143#endif
144
145static int indycam_g_ctrl(struct v4l2_subdev *sd, struct v4l2_control *ctrl)
146{
147 struct indycam *camera = to_indycam(sd);
148 u8 reg;
149 int ret = 0;
150
151 switch (ctrl->id) {
152 case V4L2_CID_AUTOGAIN:
153 case V4L2_CID_AUTO_WHITE_BALANCE:
154 ret = indycam_read_reg(sd, INDYCAM_REG_CONTROL, &reg);
155 if (ret)
156 return -EIO;
157 if (ctrl->id == V4L2_CID_AUTOGAIN)
158 ctrl->value = (reg & INDYCAM_CONTROL_AGCENA)
159 ? 1 : 0;
160 else
161 ctrl->value = (reg & INDYCAM_CONTROL_AWBCTL)
162 ? 1 : 0;
163 break;
164 case V4L2_CID_EXPOSURE:
165 ret = indycam_read_reg(sd, INDYCAM_REG_SHUTTER, &reg);
166 if (ret)
167 return -EIO;
168 ctrl->value = ((s32)reg == 0x00) ? 0xff : ((s32)reg - 1);
169 break;
170 case V4L2_CID_GAIN:
171 ret = indycam_read_reg(sd, INDYCAM_REG_GAIN, &reg);
172 if (ret)
173 return -EIO;
174 ctrl->value = (s32)reg;
175 break;
176 case V4L2_CID_RED_BALANCE:
177 ret = indycam_read_reg(sd, INDYCAM_REG_RED_BALANCE, &reg);
178 if (ret)
179 return -EIO;
180 ctrl->value = (s32)reg;
181 break;
182 case V4L2_CID_BLUE_BALANCE:
183 ret = indycam_read_reg(sd, INDYCAM_REG_BLUE_BALANCE, &reg);
184 if (ret)
185 return -EIO;
186 ctrl->value = (s32)reg;
187 break;
188 case INDYCAM_CONTROL_RED_SATURATION:
189 ret = indycam_read_reg(sd,
190 INDYCAM_REG_RED_SATURATION, &reg);
191 if (ret)
192 return -EIO;
193 ctrl->value = (s32)reg;
194 break;
195 case INDYCAM_CONTROL_BLUE_SATURATION:
196 ret = indycam_read_reg(sd,
197 INDYCAM_REG_BLUE_SATURATION, &reg);
198 if (ret)
199 return -EIO;
200 ctrl->value = (s32)reg;
201 break;
202 case V4L2_CID_GAMMA:
203 if (camera->version == CAMERA_VERSION_MOOSE) {
204 ret = indycam_read_reg(sd,
205 INDYCAM_REG_GAMMA, &reg);
206 if (ret)
207 return -EIO;
208 ctrl->value = (s32)reg;
209 } else {
210 ctrl->value = INDYCAM_GAMMA_DEFAULT;
211 }
212 break;
213 default:
214 ret = -EINVAL;
215 }
216
217 return ret;
218}
219
220static int indycam_s_ctrl(struct v4l2_subdev *sd, struct v4l2_control *ctrl)
221{
222 struct indycam *camera = to_indycam(sd);
223 u8 reg;
224 int ret = 0;
225
226 switch (ctrl->id) {
227 case V4L2_CID_AUTOGAIN:
228 case V4L2_CID_AUTO_WHITE_BALANCE:
229 ret = indycam_read_reg(sd, INDYCAM_REG_CONTROL, &reg);
230 if (ret)
231 break;
232
233 if (ctrl->id == V4L2_CID_AUTOGAIN) {
234 if (ctrl->value)
235 reg |= INDYCAM_CONTROL_AGCENA;
236 else
237 reg &= ~INDYCAM_CONTROL_AGCENA;
238 } else {
239 if (ctrl->value)
240 reg |= INDYCAM_CONTROL_AWBCTL;
241 else
242 reg &= ~INDYCAM_CONTROL_AWBCTL;
243 }
244
245 ret = indycam_write_reg(sd, INDYCAM_REG_CONTROL, reg);
246 break;
247 case V4L2_CID_EXPOSURE:
248 reg = (ctrl->value == 0xff) ? 0x00 : (ctrl->value + 1);
249 ret = indycam_write_reg(sd, INDYCAM_REG_SHUTTER, reg);
250 break;
251 case V4L2_CID_GAIN:
252 ret = indycam_write_reg(sd, INDYCAM_REG_GAIN, ctrl->value);
253 break;
254 case V4L2_CID_RED_BALANCE:
255 ret = indycam_write_reg(sd, INDYCAM_REG_RED_BALANCE,
256 ctrl->value);
257 break;
258 case V4L2_CID_BLUE_BALANCE:
259 ret = indycam_write_reg(sd, INDYCAM_REG_BLUE_BALANCE,
260 ctrl->value);
261 break;
262 case INDYCAM_CONTROL_RED_SATURATION:
263 ret = indycam_write_reg(sd, INDYCAM_REG_RED_SATURATION,
264 ctrl->value);
265 break;
266 case INDYCAM_CONTROL_BLUE_SATURATION:
267 ret = indycam_write_reg(sd, INDYCAM_REG_BLUE_SATURATION,
268 ctrl->value);
269 break;
270 case V4L2_CID_GAMMA:
271 if (camera->version == CAMERA_VERSION_MOOSE) {
272 ret = indycam_write_reg(sd, INDYCAM_REG_GAMMA,
273 ctrl->value);
274 }
275 break;
276 default:
277 ret = -EINVAL;
278 }
279
280 return ret;
281}
282
283/* I2C-interface */
284
285/* ----------------------------------------------------------------------- */
286
287static const struct v4l2_subdev_core_ops indycam_core_ops = {
288 .g_ctrl = indycam_g_ctrl,
289 .s_ctrl = indycam_s_ctrl,
290};
291
292static const struct v4l2_subdev_ops indycam_ops = {
293 .core = &indycam_core_ops,
294};
295
296static int indycam_probe(struct i2c_client *client,
297 const struct i2c_device_id *id)
298{
299 int err = 0;
300 struct indycam *camera;
301 struct v4l2_subdev *sd;
302
303 v4l_info(client, "chip found @ 0x%x (%s)\n",
304 client->addr << 1, client->adapter->name);
305
306 camera = kzalloc(sizeof(struct indycam), GFP_KERNEL);
307 if (!camera)
308 return -ENOMEM;
309
310 sd = &camera->sd;
311 v4l2_i2c_subdev_init(sd, client, &indycam_ops);
312
313 camera->version = i2c_smbus_read_byte_data(client,
314 INDYCAM_REG_VERSION);
315 if (camera->version != CAMERA_VERSION_INDY &&
316 camera->version != CAMERA_VERSION_MOOSE) {
317 kfree(camera);
318 return -ENODEV;
319 }
320
321 printk(KERN_INFO "IndyCam v%d.%d detected\n",
322 INDYCAM_VERSION_MAJOR(camera->version),
323 INDYCAM_VERSION_MINOR(camera->version));
324
325 indycam_regdump(sd);
326
327 // initialize
328 err = indycam_write_block(sd, 0, sizeof(initseq), (u8 *)&initseq);
329 if (err) {
330 printk(KERN_ERR "IndyCam initialization failed\n");
331 kfree(camera);
332 return -EIO;
333 }
334
335 indycam_regdump(sd);
336
337 // white balance
338 err = indycam_write_reg(sd, INDYCAM_REG_CONTROL,
339 INDYCAM_CONTROL_AGCENA | INDYCAM_CONTROL_AWBCTL);
340 if (err) {
341 printk(KERN_ERR "IndyCam: White balancing camera failed\n");
342 kfree(camera);
343 return -EIO;
344 }
345
346 indycam_regdump(sd);
347
348 printk(KERN_INFO "IndyCam initialized\n");
349
350 return 0;
351}
352
353static int indycam_remove(struct i2c_client *client)
354{
355 struct v4l2_subdev *sd = i2c_get_clientdata(client);
356
357 v4l2_device_unregister_subdev(sd);
358 kfree(to_indycam(sd));
359 return 0;
360}
361
362static const struct i2c_device_id indycam_id[] = {
363 { "indycam", 0 },
364 { }
365};
366MODULE_DEVICE_TABLE(i2c, indycam_id);
367
368static struct i2c_driver indycam_driver = {
369 .driver = {
370 .owner = THIS_MODULE,
371 .name = "indycam",
372 },
373 .probe = indycam_probe,
374 .remove = indycam_remove,
375 .id_table = indycam_id,
376};
377
378module_i2c_driver(indycam_driver);
diff --git a/drivers/staging/media/vino/indycam.h b/drivers/staging/media/vino/indycam.h
new file mode 100644
index 000000000000..881f21c474c4
--- /dev/null
+++ b/drivers/staging/media/vino/indycam.h
@@ -0,0 +1,93 @@
1/*
2 * indycam.h - Silicon Graphics IndyCam digital camera driver
3 *
4 * Copyright (C) 2003 Ladislav Michl <ladis@linux-mips.org>
5 * Copyright (C) 2004,2005 Mikael Nousiainen <tmnousia@cc.hut.fi>
6 *
7 * This program is free software; you can redistribute it and/or modify
8 * it under the terms of the GNU General Public License version 2 as
9 * published by the Free Software Foundation.
10 */
11
12#ifndef _INDYCAM_H_
13#define _INDYCAM_H_
14
15/* I2C address for the Guinness Camera */
16#define INDYCAM_ADDR 0x56
17
18/* Camera version */
19#define CAMERA_VERSION_INDY 0x10 /* v1.0 */
20#define CAMERA_VERSION_MOOSE 0x12 /* v1.2 */
21#define INDYCAM_VERSION_MAJOR(x) (((x) & 0xf0) >> 4)
22#define INDYCAM_VERSION_MINOR(x) ((x) & 0x0f)
23
24/* Register bus addresses */
25#define INDYCAM_REG_CONTROL 0x00
26#define INDYCAM_REG_SHUTTER 0x01
27#define INDYCAM_REG_GAIN 0x02
28#define INDYCAM_REG_BRIGHTNESS 0x03 /* read-only */
29#define INDYCAM_REG_RED_BALANCE 0x04
30#define INDYCAM_REG_BLUE_BALANCE 0x05
31#define INDYCAM_REG_RED_SATURATION 0x06
32#define INDYCAM_REG_BLUE_SATURATION 0x07
33#define INDYCAM_REG_GAMMA 0x08
34#define INDYCAM_REG_VERSION 0x0e /* read-only */
35#define INDYCAM_REG_RESET 0x0f /* write-only */
36
37#define INDYCAM_REG_LED 0x46
38#define INDYCAM_REG_ORIENTATION 0x47
39#define INDYCAM_REG_BUTTON 0x48
40
41/* Field definitions of registers */
42#define INDYCAM_CONTROL_AGCENA (1<<0) /* automatic gain control */
43#define INDYCAM_CONTROL_AWBCTL (1<<1) /* automatic white balance */
44 /* 2-3 are reserved */
45#define INDYCAM_CONTROL_EVNFLD (1<<4) /* read-only */
46
47#define INDYCAM_SHUTTER_10000 0x02 /* 1/10000 second */
48#define INDYCAM_SHUTTER_4000 0x04 /* 1/4000 second */
49#define INDYCAM_SHUTTER_2000 0x08 /* 1/2000 second */
50#define INDYCAM_SHUTTER_1000 0x10 /* 1/1000 second */
51#define INDYCAM_SHUTTER_500 0x20 /* 1/500 second */
52#define INDYCAM_SHUTTER_250 0x3f /* 1/250 second */
53#define INDYCAM_SHUTTER_125 0x7e /* 1/125 second */
54#define INDYCAM_SHUTTER_100 0x9e /* 1/100 second */
55#define INDYCAM_SHUTTER_60 0x00 /* 1/60 second */
56
57#define INDYCAM_LED_ACTIVE 0x10
58#define INDYCAM_LED_INACTIVE 0x30
59#define INDYCAM_ORIENTATION_BOTTOM_TO_TOP 0x40
60#define INDYCAM_BUTTON_RELEASED 0x10
61
62/* Values for controls */
63#define INDYCAM_SHUTTER_MIN 0x00
64#define INDYCAM_SHUTTER_MAX 0xff
65#define INDYCAM_GAIN_MIN 0x00
66#define INDYCAM_GAIN_MAX 0xff
67#define INDYCAM_RED_BALANCE_MIN 0x00
68#define INDYCAM_RED_BALANCE_MAX 0xff
69#define INDYCAM_BLUE_BALANCE_MIN 0x00
70#define INDYCAM_BLUE_BALANCE_MAX 0xff
71#define INDYCAM_RED_SATURATION_MIN 0x00
72#define INDYCAM_RED_SATURATION_MAX 0xff
73#define INDYCAM_BLUE_SATURATION_MIN 0x00
74#define INDYCAM_BLUE_SATURATION_MAX 0xff
75#define INDYCAM_GAMMA_MIN 0x00
76#define INDYCAM_GAMMA_MAX 0xff
77
78#define INDYCAM_AGC_DEFAULT 1
79#define INDYCAM_AWB_DEFAULT 0
80#define INDYCAM_SHUTTER_DEFAULT 0xff
81#define INDYCAM_GAIN_DEFAULT 0x80
82#define INDYCAM_RED_BALANCE_DEFAULT 0x18
83#define INDYCAM_BLUE_BALANCE_DEFAULT 0xa4
84#define INDYCAM_RED_SATURATION_DEFAULT 0x80
85#define INDYCAM_BLUE_SATURATION_DEFAULT 0xc0
86#define INDYCAM_GAMMA_DEFAULT 0x80
87
88/* Driver interface definitions */
89
90#define INDYCAM_CONTROL_RED_SATURATION (V4L2_CID_PRIVATE_BASE + 0)
91#define INDYCAM_CONTROL_BLUE_SATURATION (V4L2_CID_PRIVATE_BASE + 1)
92
93#endif
diff --git a/drivers/staging/media/vino/saa7191.c b/drivers/staging/media/vino/saa7191.c
new file mode 100644
index 000000000000..8e9699268a63
--- /dev/null
+++ b/drivers/staging/media/vino/saa7191.c
@@ -0,0 +1,649 @@
1/*
2 * saa7191.c - Philips SAA7191 video decoder driver
3 *
4 * Copyright (C) 2003 Ladislav Michl <ladis@linux-mips.org>
5 * Copyright (C) 2004,2005 Mikael Nousiainen <tmnousia@cc.hut.fi>
6 *
7 * This program is free software; you can redistribute it and/or modify
8 * it under the terms of the GNU General Public License version 2 as
9 * published by the Free Software Foundation.
10 */
11
12#include <linux/delay.h>
13#include <linux/errno.h>
14#include <linux/fs.h>
15#include <linux/init.h>
16#include <linux/kernel.h>
17#include <linux/major.h>
18#include <linux/module.h>
19#include <linux/mm.h>
20#include <linux/slab.h>
21
22#include <linux/videodev2.h>
23#include <linux/i2c.h>
24#include <media/v4l2-device.h>
25
26#include "saa7191.h"
27
28#define SAA7191_MODULE_VERSION "0.0.5"
29
30MODULE_DESCRIPTION("Philips SAA7191 video decoder driver");
31MODULE_VERSION(SAA7191_MODULE_VERSION);
32MODULE_AUTHOR("Mikael Nousiainen <tmnousia@cc.hut.fi>");
33MODULE_LICENSE("GPL");
34
35
36// #define SAA7191_DEBUG
37
38#ifdef SAA7191_DEBUG
39#define dprintk(x...) printk("SAA7191: " x);
40#else
41#define dprintk(x...)
42#endif
43
44#define SAA7191_SYNC_COUNT 30
45#define SAA7191_SYNC_DELAY 100 /* milliseconds */
46
47struct saa7191 {
48 struct v4l2_subdev sd;
49
50 /* the register values are stored here as the actual
51 * I2C-registers are write-only */
52 u8 reg[25];
53
54 int input;
55 v4l2_std_id norm;
56};
57
58static inline struct saa7191 *to_saa7191(struct v4l2_subdev *sd)
59{
60 return container_of(sd, struct saa7191, sd);
61}
62
63static const u8 initseq[] = {
64 0, /* Subaddress */
65
66 0x50, /* (0x50) SAA7191_REG_IDEL */
67
68 /* 50 Hz signal timing */
69 0x30, /* (0x30) SAA7191_REG_HSYB */
70 0x00, /* (0x00) SAA7191_REG_HSYS */
71 0xe8, /* (0xe8) SAA7191_REG_HCLB */
72 0xb6, /* (0xb6) SAA7191_REG_HCLS */
73 0xf4, /* (0xf4) SAA7191_REG_HPHI */
74
75 /* control */
76 SAA7191_LUMA_APER_1, /* (0x01) SAA7191_REG_LUMA - CVBS mode */
77 0x00, /* (0x00) SAA7191_REG_HUEC */
78 0xf8, /* (0xf8) SAA7191_REG_CKTQ */
79 0xf8, /* (0xf8) SAA7191_REG_CKTS */
80 0x90, /* (0x90) SAA7191_REG_PLSE */
81 0x90, /* (0x90) SAA7191_REG_SESE */
82 0x00, /* (0x00) SAA7191_REG_GAIN */
83 SAA7191_STDC_NFEN | SAA7191_STDC_HRMV, /* (0x0c) SAA7191_REG_STDC
84 * - not SECAM,
85 * slow time constant */
86 SAA7191_IOCK_OEDC | SAA7191_IOCK_OEHS | SAA7191_IOCK_OEVS
87 | SAA7191_IOCK_OEDY, /* (0x78) SAA7191_REG_IOCK
88 * - chroma from CVBS, GPSW1 & 2 off */
89 SAA7191_CTL3_AUFD | SAA7191_CTL3_SCEN | SAA7191_CTL3_OFTS
90 | SAA7191_CTL3_YDEL0, /* (0x99) SAA7191_REG_CTL3
91 * - automatic field detection */
92 0x00, /* (0x00) SAA7191_REG_CTL4 */
93 0x2c, /* (0x2c) SAA7191_REG_CHCV - PAL nominal value */
94 0x00, /* unused */
95 0x00, /* unused */
96
97 /* 60 Hz signal timing */
98 0x34, /* (0x34) SAA7191_REG_HS6B */
99 0x0a, /* (0x0a) SAA7191_REG_HS6S */
100 0xf4, /* (0xf4) SAA7191_REG_HC6B */
101 0xce, /* (0xce) SAA7191_REG_HC6S */
102 0xf4, /* (0xf4) SAA7191_REG_HP6I */
103};
104
105/* SAA7191 register handling */
106
107static u8 saa7191_read_reg(struct v4l2_subdev *sd, u8 reg)
108{
109 return to_saa7191(sd)->reg[reg];
110}
111
112static int saa7191_read_status(struct v4l2_subdev *sd, u8 *value)
113{
114 struct i2c_client *client = v4l2_get_subdevdata(sd);
115 int ret;
116
117 ret = i2c_master_recv(client, value, 1);
118 if (ret < 0) {
119 printk(KERN_ERR "SAA7191: saa7191_read_status(): read failed\n");
120 return ret;
121 }
122
123 return 0;
124}
125
126
127static int saa7191_write_reg(struct v4l2_subdev *sd, u8 reg, u8 value)
128{
129 struct i2c_client *client = v4l2_get_subdevdata(sd);
130
131 to_saa7191(sd)->reg[reg] = value;
132 return i2c_smbus_write_byte_data(client, reg, value);
133}
134
135/* the first byte of data must be the first subaddress number (register) */
136static int saa7191_write_block(struct v4l2_subdev *sd,
137 u8 length, const u8 *data)
138{
139 struct i2c_client *client = v4l2_get_subdevdata(sd);
140 struct saa7191 *decoder = to_saa7191(sd);
141 int i;
142 int ret;
143
144 for (i = 0; i < (length - 1); i++) {
145 decoder->reg[data[0] + i] = data[i + 1];
146 }
147
148 ret = i2c_master_send(client, data, length);
149 if (ret < 0) {
150 printk(KERN_ERR "SAA7191: saa7191_write_block(): "
151 "write failed\n");
152 return ret;
153 }
154
155 return 0;
156}
157
158/* Helper functions */
159
160static int saa7191_s_routing(struct v4l2_subdev *sd,
161 u32 input, u32 output, u32 config)
162{
163 struct saa7191 *decoder = to_saa7191(sd);
164 u8 luma = saa7191_read_reg(sd, SAA7191_REG_LUMA);
165 u8 iock = saa7191_read_reg(sd, SAA7191_REG_IOCK);
166 int err;
167
168 switch (input) {
169 case SAA7191_INPUT_COMPOSITE: /* Set Composite input */
170 iock &= ~(SAA7191_IOCK_CHRS | SAA7191_IOCK_GPSW1
171 | SAA7191_IOCK_GPSW2);
172 /* Chrominance trap active */
173 luma &= ~SAA7191_LUMA_BYPS;
174 break;
175 case SAA7191_INPUT_SVIDEO: /* Set S-Video input */
176 iock |= SAA7191_IOCK_CHRS | SAA7191_IOCK_GPSW2;
177 /* Chrominance trap bypassed */
178 luma |= SAA7191_LUMA_BYPS;
179 break;
180 default:
181 return -EINVAL;
182 }
183
184 err = saa7191_write_reg(sd, SAA7191_REG_LUMA, luma);
185 if (err)
186 return -EIO;
187 err = saa7191_write_reg(sd, SAA7191_REG_IOCK, iock);
188 if (err)
189 return -EIO;
190
191 decoder->input = input;
192
193 return 0;
194}
195
196static int saa7191_s_std(struct v4l2_subdev *sd, v4l2_std_id norm)
197{
198 struct saa7191 *decoder = to_saa7191(sd);
199 u8 stdc = saa7191_read_reg(sd, SAA7191_REG_STDC);
200 u8 ctl3 = saa7191_read_reg(sd, SAA7191_REG_CTL3);
201 u8 chcv = saa7191_read_reg(sd, SAA7191_REG_CHCV);
202 int err;
203
204 if (norm & V4L2_STD_PAL) {
205 stdc &= ~SAA7191_STDC_SECS;
206 ctl3 &= ~(SAA7191_CTL3_AUFD | SAA7191_CTL3_FSEL);
207 chcv = SAA7191_CHCV_PAL;
208 } else if (norm & V4L2_STD_NTSC) {
209 stdc &= ~SAA7191_STDC_SECS;
210 ctl3 &= ~SAA7191_CTL3_AUFD;
211 ctl3 |= SAA7191_CTL3_FSEL;
212 chcv = SAA7191_CHCV_NTSC;
213 } else if (norm & V4L2_STD_SECAM) {
214 stdc |= SAA7191_STDC_SECS;
215 ctl3 &= ~(SAA7191_CTL3_AUFD | SAA7191_CTL3_FSEL);
216 chcv = SAA7191_CHCV_PAL;
217 } else {
218 return -EINVAL;
219 }
220
221 err = saa7191_write_reg(sd, SAA7191_REG_CTL3, ctl3);
222 if (err)
223 return -EIO;
224 err = saa7191_write_reg(sd, SAA7191_REG_STDC, stdc);
225 if (err)
226 return -EIO;
227 err = saa7191_write_reg(sd, SAA7191_REG_CHCV, chcv);
228 if (err)
229 return -EIO;
230
231 decoder->norm = norm;
232
233 dprintk("ctl3: %02x stdc: %02x chcv: %02x\n", ctl3,
234 stdc, chcv);
235 dprintk("norm: %llx\n", norm);
236
237 return 0;
238}
239
240static int saa7191_wait_for_signal(struct v4l2_subdev *sd, u8 *status)
241{
242 int i = 0;
243
244 dprintk("Checking for signal...\n");
245
246 for (i = 0; i < SAA7191_SYNC_COUNT; i++) {
247 if (saa7191_read_status(sd, status))
248 return -EIO;
249
250 if (((*status) & SAA7191_STATUS_HLCK) == 0) {
251 dprintk("Signal found\n");
252 return 0;
253 }
254
255 msleep(SAA7191_SYNC_DELAY);
256 }
257
258 dprintk("No signal\n");
259
260 return -EBUSY;
261}
262
263static int saa7191_querystd(struct v4l2_subdev *sd, v4l2_std_id *norm)
264{
265 struct saa7191 *decoder = to_saa7191(sd);
266 u8 stdc = saa7191_read_reg(sd, SAA7191_REG_STDC);
267 u8 ctl3 = saa7191_read_reg(sd, SAA7191_REG_CTL3);
268 u8 status;
269 v4l2_std_id old_norm = decoder->norm;
270 int err = 0;
271
272 dprintk("SAA7191 extended signal auto-detection...\n");
273
274 *norm &= V4L2_STD_NTSC | V4L2_STD_PAL | V4L2_STD_SECAM;
275 stdc &= ~SAA7191_STDC_SECS;
276 ctl3 &= ~(SAA7191_CTL3_FSEL);
277
278 err = saa7191_write_reg(sd, SAA7191_REG_STDC, stdc);
279 if (err) {
280 err = -EIO;
281 goto out;
282 }
283 err = saa7191_write_reg(sd, SAA7191_REG_CTL3, ctl3);
284 if (err) {
285 err = -EIO;
286 goto out;
287 }
288
289 ctl3 |= SAA7191_CTL3_AUFD;
290 err = saa7191_write_reg(sd, SAA7191_REG_CTL3, ctl3);
291 if (err) {
292 err = -EIO;
293 goto out;
294 }
295
296 msleep(SAA7191_SYNC_DELAY);
297
298 err = saa7191_wait_for_signal(sd, &status);
299 if (err)
300 goto out;
301
302 if (status & SAA7191_STATUS_FIDT) {
303 /* 60Hz signal -> NTSC */
304 dprintk("60Hz signal: NTSC\n");
305 *norm &= V4L2_STD_NTSC;
306 return 0;
307 }
308
309 /* 50Hz signal */
310 dprintk("50Hz signal: Trying PAL...\n");
311
312 /* try PAL first */
313 err = saa7191_s_std(sd, V4L2_STD_PAL);
314 if (err)
315 goto out;
316
317 msleep(SAA7191_SYNC_DELAY);
318
319 err = saa7191_wait_for_signal(sd, &status);
320 if (err)
321 goto out;
322
323 /* not 50Hz ? */
324 if (status & SAA7191_STATUS_FIDT) {
325 dprintk("No 50Hz signal\n");
326 saa7191_s_std(sd, old_norm);
327 *norm = V4L2_STD_UNKNOWN;
328 return 0;
329 }
330
331 if (status & SAA7191_STATUS_CODE) {
332 dprintk("PAL\n");
333 *norm &= V4L2_STD_PAL;
334 return saa7191_s_std(sd, old_norm);
335 }
336
337 dprintk("No color detected with PAL - Trying SECAM...\n");
338
339 /* no color detected ? -> try SECAM */
340 err = saa7191_s_std(sd, V4L2_STD_SECAM);
341 if (err)
342 goto out;
343
344 msleep(SAA7191_SYNC_DELAY);
345
346 err = saa7191_wait_for_signal(sd, &status);
347 if (err)
348 goto out;
349
350 /* not 50Hz ? */
351 if (status & SAA7191_STATUS_FIDT) {
352 dprintk("No 50Hz signal\n");
353 *norm = V4L2_STD_UNKNOWN;
354 goto out;
355 }
356
357 if (status & SAA7191_STATUS_CODE) {
358 /* Color detected -> SECAM */
359 dprintk("SECAM\n");
360 *norm &= V4L2_STD_SECAM;
361 return saa7191_s_std(sd, old_norm);
362 }
363
364 dprintk("No color detected with SECAM - Going back to PAL.\n");
365 *norm = V4L2_STD_UNKNOWN;
366
367out:
368 return saa7191_s_std(sd, old_norm);
369}
370
371static int saa7191_autodetect_norm(struct v4l2_subdev *sd)
372{
373 u8 status;
374
375 dprintk("SAA7191 signal auto-detection...\n");
376
377 dprintk("Reading status...\n");
378
379 if (saa7191_read_status(sd, &status))
380 return -EIO;
381
382 dprintk("Checking for signal...\n");
383
384 /* no signal ? */
385 if (status & SAA7191_STATUS_HLCK) {
386 dprintk("No signal\n");
387 return -EBUSY;
388 }
389
390 dprintk("Signal found\n");
391
392 if (status & SAA7191_STATUS_FIDT) {
393 /* 60hz signal -> NTSC */
394 dprintk("NTSC\n");
395 return saa7191_s_std(sd, V4L2_STD_NTSC);
396 } else {
397 /* 50hz signal -> PAL */
398 dprintk("PAL\n");
399 return saa7191_s_std(sd, V4L2_STD_PAL);
400 }
401}
402
403static int saa7191_g_ctrl(struct v4l2_subdev *sd, struct v4l2_control *ctrl)
404{
405 u8 reg;
406 int ret = 0;
407
408 switch (ctrl->id) {
409 case SAA7191_CONTROL_BANDPASS:
410 case SAA7191_CONTROL_BANDPASS_WEIGHT:
411 case SAA7191_CONTROL_CORING:
412 reg = saa7191_read_reg(sd, SAA7191_REG_LUMA);
413 switch (ctrl->id) {
414 case SAA7191_CONTROL_BANDPASS:
415 ctrl->value = ((s32)reg & SAA7191_LUMA_BPSS_MASK)
416 >> SAA7191_LUMA_BPSS_SHIFT;
417 break;
418 case SAA7191_CONTROL_BANDPASS_WEIGHT:
419 ctrl->value = ((s32)reg & SAA7191_LUMA_APER_MASK)
420 >> SAA7191_LUMA_APER_SHIFT;
421 break;
422 case SAA7191_CONTROL_CORING:
423 ctrl->value = ((s32)reg & SAA7191_LUMA_CORI_MASK)
424 >> SAA7191_LUMA_CORI_SHIFT;
425 break;
426 }
427 break;
428 case SAA7191_CONTROL_FORCE_COLOUR:
429 case SAA7191_CONTROL_CHROMA_GAIN:
430 reg = saa7191_read_reg(sd, SAA7191_REG_GAIN);
431 if (ctrl->id == SAA7191_CONTROL_FORCE_COLOUR)
432 ctrl->value = ((s32)reg & SAA7191_GAIN_COLO) ? 1 : 0;
433 else
434 ctrl->value = ((s32)reg & SAA7191_GAIN_LFIS_MASK)
435 >> SAA7191_GAIN_LFIS_SHIFT;
436 break;
437 case V4L2_CID_HUE:
438 reg = saa7191_read_reg(sd, SAA7191_REG_HUEC);
439 if (reg < 0x80)
440 reg += 0x80;
441 else
442 reg -= 0x80;
443 ctrl->value = (s32)reg;
444 break;
445 case SAA7191_CONTROL_VTRC:
446 reg = saa7191_read_reg(sd, SAA7191_REG_STDC);
447 ctrl->value = ((s32)reg & SAA7191_STDC_VTRC) ? 1 : 0;
448 break;
449 case SAA7191_CONTROL_LUMA_DELAY:
450 reg = saa7191_read_reg(sd, SAA7191_REG_CTL3);
451 ctrl->value = ((s32)reg & SAA7191_CTL3_YDEL_MASK)
452 >> SAA7191_CTL3_YDEL_SHIFT;
453 if (ctrl->value >= 4)
454 ctrl->value -= 8;
455 break;
456 case SAA7191_CONTROL_VNR:
457 reg = saa7191_read_reg(sd, SAA7191_REG_CTL4);
458 ctrl->value = ((s32)reg & SAA7191_CTL4_VNOI_MASK)
459 >> SAA7191_CTL4_VNOI_SHIFT;
460 break;
461 default:
462 ret = -EINVAL;
463 }
464
465 return ret;
466}
467
468static int saa7191_s_ctrl(struct v4l2_subdev *sd, struct v4l2_control *ctrl)
469{
470 u8 reg;
471 int ret = 0;
472
473 switch (ctrl->id) {
474 case SAA7191_CONTROL_BANDPASS:
475 case SAA7191_CONTROL_BANDPASS_WEIGHT:
476 case SAA7191_CONTROL_CORING:
477 reg = saa7191_read_reg(sd, SAA7191_REG_LUMA);
478 switch (ctrl->id) {
479 case SAA7191_CONTROL_BANDPASS:
480 reg &= ~SAA7191_LUMA_BPSS_MASK;
481 reg |= (ctrl->value << SAA7191_LUMA_BPSS_SHIFT)
482 & SAA7191_LUMA_BPSS_MASK;
483 break;
484 case SAA7191_CONTROL_BANDPASS_WEIGHT:
485 reg &= ~SAA7191_LUMA_APER_MASK;
486 reg |= (ctrl->value << SAA7191_LUMA_APER_SHIFT)
487 & SAA7191_LUMA_APER_MASK;
488 break;
489 case SAA7191_CONTROL_CORING:
490 reg &= ~SAA7191_LUMA_CORI_MASK;
491 reg |= (ctrl->value << SAA7191_LUMA_CORI_SHIFT)
492 & SAA7191_LUMA_CORI_MASK;
493 break;
494 }
495 ret = saa7191_write_reg(sd, SAA7191_REG_LUMA, reg);
496 break;
497 case SAA7191_CONTROL_FORCE_COLOUR:
498 case SAA7191_CONTROL_CHROMA_GAIN:
499 reg = saa7191_read_reg(sd, SAA7191_REG_GAIN);
500 if (ctrl->id == SAA7191_CONTROL_FORCE_COLOUR) {
501 if (ctrl->value)
502 reg |= SAA7191_GAIN_COLO;
503 else
504 reg &= ~SAA7191_GAIN_COLO;
505 } else {
506 reg &= ~SAA7191_GAIN_LFIS_MASK;
507 reg |= (ctrl->value << SAA7191_GAIN_LFIS_SHIFT)
508 & SAA7191_GAIN_LFIS_MASK;
509 }
510 ret = saa7191_write_reg(sd, SAA7191_REG_GAIN, reg);
511 break;
512 case V4L2_CID_HUE:
513 reg = ctrl->value & 0xff;
514 if (reg < 0x80)
515 reg += 0x80;
516 else
517 reg -= 0x80;
518 ret = saa7191_write_reg(sd, SAA7191_REG_HUEC, reg);
519 break;
520 case SAA7191_CONTROL_VTRC:
521 reg = saa7191_read_reg(sd, SAA7191_REG_STDC);
522 if (ctrl->value)
523 reg |= SAA7191_STDC_VTRC;
524 else
525 reg &= ~SAA7191_STDC_VTRC;
526 ret = saa7191_write_reg(sd, SAA7191_REG_STDC, reg);
527 break;
528 case SAA7191_CONTROL_LUMA_DELAY: {
529 s32 value = ctrl->value;
530 if (value < 0)
531 value += 8;
532 reg = saa7191_read_reg(sd, SAA7191_REG_CTL3);
533 reg &= ~SAA7191_CTL3_YDEL_MASK;
534 reg |= (value << SAA7191_CTL3_YDEL_SHIFT)
535 & SAA7191_CTL3_YDEL_MASK;
536 ret = saa7191_write_reg(sd, SAA7191_REG_CTL3, reg);
537 break;
538 }
539 case SAA7191_CONTROL_VNR:
540 reg = saa7191_read_reg(sd, SAA7191_REG_CTL4);
541 reg &= ~SAA7191_CTL4_VNOI_MASK;
542 reg |= (ctrl->value << SAA7191_CTL4_VNOI_SHIFT)
543 & SAA7191_CTL4_VNOI_MASK;
544 ret = saa7191_write_reg(sd, SAA7191_REG_CTL4, reg);
545 break;
546 default:
547 ret = -EINVAL;
548 }
549
550 return ret;
551}
552
553/* I2C-interface */
554
555static int saa7191_g_input_status(struct v4l2_subdev *sd, u32 *status)
556{
557 u8 status_reg;
558 int res = V4L2_IN_ST_NO_SIGNAL;
559
560 if (saa7191_read_status(sd, &status_reg))
561 return -EIO;
562 if ((status_reg & SAA7191_STATUS_HLCK) == 0)
563 res = 0;
564 if (!(status_reg & SAA7191_STATUS_CODE))
565 res |= V4L2_IN_ST_NO_COLOR;
566 *status = res;
567 return 0;
568}
569
570
571/* ----------------------------------------------------------------------- */
572
573static const struct v4l2_subdev_core_ops saa7191_core_ops = {
574 .g_ctrl = saa7191_g_ctrl,
575 .s_ctrl = saa7191_s_ctrl,
576};
577
578static const struct v4l2_subdev_video_ops saa7191_video_ops = {
579 .s_std = saa7191_s_std,
580 .s_routing = saa7191_s_routing,
581 .querystd = saa7191_querystd,
582 .g_input_status = saa7191_g_input_status,
583};
584
585static const struct v4l2_subdev_ops saa7191_ops = {
586 .core = &saa7191_core_ops,
587 .video = &saa7191_video_ops,
588};
589
590static int saa7191_probe(struct i2c_client *client,
591 const struct i2c_device_id *id)
592{
593 int err = 0;
594 struct saa7191 *decoder;
595 struct v4l2_subdev *sd;
596
597 v4l_info(client, "chip found @ 0x%x (%s)\n",
598 client->addr << 1, client->adapter->name);
599
600 decoder = devm_kzalloc(&client->dev, sizeof(*decoder), GFP_KERNEL);
601 if (!decoder)
602 return -ENOMEM;
603
604 sd = &decoder->sd;
605 v4l2_i2c_subdev_init(sd, client, &saa7191_ops);
606
607 err = saa7191_write_block(sd, sizeof(initseq), initseq);
608 if (err) {
609 printk(KERN_ERR "SAA7191 initialization failed\n");
610 return err;
611 }
612
613 printk(KERN_INFO "SAA7191 initialized\n");
614
615 decoder->input = SAA7191_INPUT_COMPOSITE;
616 decoder->norm = V4L2_STD_PAL;
617
618 err = saa7191_autodetect_norm(sd);
619 if (err && (err != -EBUSY))
620 printk(KERN_ERR "SAA7191: Signal auto-detection failed\n");
621
622 return 0;
623}
624
625static int saa7191_remove(struct i2c_client *client)
626{
627 struct v4l2_subdev *sd = i2c_get_clientdata(client);
628
629 v4l2_device_unregister_subdev(sd);
630 return 0;
631}
632
633static const struct i2c_device_id saa7191_id[] = {
634 { "saa7191", 0 },
635 { }
636};
637MODULE_DEVICE_TABLE(i2c, saa7191_id);
638
639static struct i2c_driver saa7191_driver = {
640 .driver = {
641 .owner = THIS_MODULE,
642 .name = "saa7191",
643 },
644 .probe = saa7191_probe,
645 .remove = saa7191_remove,
646 .id_table = saa7191_id,
647};
648
649module_i2c_driver(saa7191_driver);
diff --git a/drivers/staging/media/vino/saa7191.h b/drivers/staging/media/vino/saa7191.h
new file mode 100644
index 000000000000..803c74d6066f
--- /dev/null
+++ b/drivers/staging/media/vino/saa7191.h
@@ -0,0 +1,245 @@
1/*
2 * saa7191.h - Philips SAA7191 video decoder driver
3 *
4 * Copyright (C) 2003 Ladislav Michl <ladis@linux-mips.org>
5 * Copyright (C) 2004,2005 Mikael Nousiainen <tmnousia@cc.hut.fi>
6 *
7 * This program is free software; you can redistribute it and/or modify
8 * it under the terms of the GNU General Public License version 2 as
9 * published by the Free Software Foundation.
10 */
11
12#ifndef _SAA7191_H_
13#define _SAA7191_H_
14
15/* Philips SAA7191 DMSD I2C bus address */
16#define SAA7191_ADDR 0x8a
17
18/* Register subaddresses. */
19#define SAA7191_REG_IDEL 0x00
20#define SAA7191_REG_HSYB 0x01
21#define SAA7191_REG_HSYS 0x02
22#define SAA7191_REG_HCLB 0x03
23#define SAA7191_REG_HCLS 0x04
24#define SAA7191_REG_HPHI 0x05
25#define SAA7191_REG_LUMA 0x06
26#define SAA7191_REG_HUEC 0x07
27#define SAA7191_REG_CKTQ 0x08 /* bits 3-7 */
28#define SAA7191_REG_CKTS 0x09 /* bits 3-7 */
29#define SAA7191_REG_PLSE 0x0a
30#define SAA7191_REG_SESE 0x0b
31#define SAA7191_REG_GAIN 0x0c
32#define SAA7191_REG_STDC 0x0d
33#define SAA7191_REG_IOCK 0x0e
34#define SAA7191_REG_CTL3 0x0f
35#define SAA7191_REG_CTL4 0x10
36#define SAA7191_REG_CHCV 0x11
37#define SAA7191_REG_HS6B 0x14
38#define SAA7191_REG_HS6S 0x15
39#define SAA7191_REG_HC6B 0x16
40#define SAA7191_REG_HC6S 0x17
41#define SAA7191_REG_HP6I 0x18
42#define SAA7191_REG_STATUS 0xff /* not really a subaddress */
43
44/* Status Register definitions */
45#define SAA7191_STATUS_CODE 0x01 /* color detected flag */
46#define SAA7191_STATUS_FIDT 0x20 /* signal type 50/60 Hz */
47#define SAA7191_STATUS_HLCK 0x40 /* PLL unlocked(1)/locked(0) */
48#define SAA7191_STATUS_STTC 0x80 /* tv/vtr time constant */
49
50/* Luminance Control Register definitions */
51/* input mode select bit:
52 * 0=CVBS (chrominance trap active), 1=S-Video (trap bypassed) */
53#define SAA7191_LUMA_BYPS 0x80
54/* pre-filter (only when chrominance trap is active) */
55#define SAA7191_LUMA_PREF 0x40
56/* aperture bandpass to select different characteristics with maximums
57 * (bits 4-5) */
58#define SAA7191_LUMA_BPSS_MASK 0x30
59#define SAA7191_LUMA_BPSS_SHIFT 4
60#define SAA7191_LUMA_BPSS_3 0x30
61#define SAA7191_LUMA_BPSS_2 0x20
62#define SAA7191_LUMA_BPSS_1 0x10
63#define SAA7191_LUMA_BPSS_0 0x00
64/* coring range for high frequency components according to 8-bit luminance
65 * (bits 2-3)
66 * 0=coring off, n= (+-)n LSB */
67#define SAA7191_LUMA_CORI_MASK 0x0c
68#define SAA7191_LUMA_CORI_SHIFT 2
69#define SAA7191_LUMA_CORI_3 0x0c
70#define SAA7191_LUMA_CORI_2 0x08
71#define SAA7191_LUMA_CORI_1 0x04
72#define SAA7191_LUMA_CORI_0 0x00
73/* aperture bandpass filter weights high frequency components of luminance
74 * signal (bits 0-1)
75 * 0=factor 0, 1=0.25, 2=0.5, 3=1 */
76#define SAA7191_LUMA_APER_MASK 0x03
77#define SAA7191_LUMA_APER_SHIFT 0
78#define SAA7191_LUMA_APER_3 0x03
79#define SAA7191_LUMA_APER_2 0x02
80#define SAA7191_LUMA_APER_1 0x01
81#define SAA7191_LUMA_APER_0 0x00
82
83/* Chrominance Gain Control Settings Register definitions */
84/* colour on: 0=automatic colour-killer enabled, 1=forced colour on */
85#define SAA7191_GAIN_COLO 0x80
86/* chrominance gain control (AGC filter)
87 * 0=loop filter time constant slow, 1=medium, 2=fast, 3=actual gain */
88#define SAA7191_GAIN_LFIS_MASK 0x60
89#define SAA7191_GAIN_LFIS_SHIFT 5
90#define SAA7191_GAIN_LFIS_3 0x60
91#define SAA7191_GAIN_LFIS_2 0x40
92#define SAA7191_GAIN_LFIS_1 0x20
93#define SAA7191_GAIN_LFIS_0 0x00
94
95/* Standard/Mode Control Register definitions */
96/* tv/vtr mode bit: 0=TV mode (slow time constant),
97 * 1=VTR mode (fast time constant) */
98#define SAA7191_STDC_VTRC 0x80
99/* SAA7191B-specific functions enable (RTCO, ODD and GPSW0 outputs)
100 * 0=outputs set to high-impedance (circuit equals SAA7191), 1=enabled */
101#define SAA7191_STDC_NFEN 0x08
102/* HREF generation: 0=like SAA7191, 1=HREF is 8xLLC2 clocks earlier */
103#define SAA7191_STDC_HRMV 0x04
104/* general purpose switch 0
105 * (not used with VINO afaik) */
106#define SAA7191_STDC_GPSW0 0x02
107/* SECAM mode bit: 0=other standards, 1=SECAM */
108#define SAA7191_STDC_SECS 0x01
109
110/* I/O and Clock Control Register definitions */
111/* horizontal clock PLL: 0=PLL closed,
112 * 1=PLL circuit open and horizontal freq fixed */
113#define SAA7191_IOCK_HPLL 0x80
114/* colour-difference output enable (outputs UV0-UV7) */
115#define SAA7191_IOCK_OEDC 0x40
116/* H-sync output enable */
117#define SAA7191_IOCK_OEHS 0x20
118/* V-sync output enable */
119#define SAA7191_IOCK_OEVS 0x10
120/* luminance output enable (outputs Y0-Y7) */
121#define SAA7191_IOCK_OEDY 0x08
122/* S-VHS bit (chrominance from CVBS or from chrominance input):
123 * 0=controlled by BYPS-bit, 1=from chrominance input */
124#define SAA7191_IOCK_CHRS 0x04
125/* general purpose switch 2
126 * VINO-specific: 0=used with CVBS, 1=used with S-Video */
127#define SAA7191_IOCK_GPSW2 0x02
128/* general purpose switch 1 */
129/* VINO-specific: 0=always, 1=not used!*/
130#define SAA7191_IOCK_GPSW1 0x01
131
132/* Miscellaneous Control #1 Register definitions */
133/* automatic field detection (50/60Hz standard) */
134#define SAA7191_CTL3_AUFD 0x80
135/* field select: (if AUFD=0)
136 * 0=50Hz (625 lines), 1=60Hz (525 lines) */
137#define SAA7191_CTL3_FSEL 0x40
138/* SECAM cross-colour reduction enable */
139#define SAA7191_CTL3_SXCR 0x20
140/* sync and clamping pulse enable (HCL and HSY outputs) */
141#define SAA7191_CTL3_SCEN 0x10
142/* output format: 0=4:1:1, 1=4:2:2 (4:2:2 for VINO) */
143#define SAA7191_CTL3_OFTS 0x08
144/* luminance delay compensation
145 * 0=0*2/LLC, 1=+1*2/LLC, 2=+2*2/LLC, 3=+3*2/LLC,
146 * 4=-4*2/LLC, 5=-3*2/LLC, 6=-2*2/LLC, 7=-1*2/LLC
147 * step size = 2/LLC = 67.8ns for 50Hz, 81.5ns for 60Hz */
148#define SAA7191_CTL3_YDEL_MASK 0x07
149#define SAA7191_CTL3_YDEL_SHIFT 0
150#define SAA7191_CTL3_YDEL2 0x04
151#define SAA7191_CTL3_YDEL1 0x02
152#define SAA7191_CTL3_YDEL0 0x01
153
154/* Miscellaneous Control #2 Register definitions */
155/* select HREF position
156 * 0=normal, HREF is matched to YUV output port,
157 * 1=HREF is matched to CVBS input port */
158#define SAA7191_CTL4_HRFS 0x04
159/* vertical noise reduction
160 * 0=normal, 1=searching window, 2=auto-deflection, 3=reduction bypassed */
161#define SAA7191_CTL4_VNOI_MASK 0x03
162#define SAA7191_CTL4_VNOI_SHIFT 0
163#define SAA7191_CTL4_VNOI_3 0x03
164#define SAA7191_CTL4_VNOI_2 0x02
165#define SAA7191_CTL4_VNOI_1 0x01
166#define SAA7191_CTL4_VNOI_0 0x00
167
168/* Chrominance Gain Control Register definitions
169 * - for QAM-modulated input signals, effects output amplitude
170 * (SECAM gain fixed)
171 * (nominal values for UV CCIR level) */
172#define SAA7191_CHCV_NTSC 0x2c
173#define SAA7191_CHCV_PAL 0x59
174
175/* Driver interface definitions */
176#define SAA7191_INPUT_COMPOSITE 0
177#define SAA7191_INPUT_SVIDEO 1
178
179#define SAA7191_NORM_PAL 1
180#define SAA7191_NORM_NTSC 2
181#define SAA7191_NORM_SECAM 3
182
183struct saa7191_status {
184 /* 0=no signal, 1=signal detected */
185 int signal;
186 /* 0=50hz (pal) signal, 1=60hz (ntsc) signal */
187 int signal_60hz;
188 /* 0=no color detected, 1=color detected */
189 int color;
190
191 /* current SAA7191_INPUT_ */
192 int input;
193 /* current SAA7191_NORM_ */
194 int norm;
195};
196
197#define SAA7191_BANDPASS_MIN 0x00
198#define SAA7191_BANDPASS_MAX 0x03
199#define SAA7191_BANDPASS_DEFAULT 0x00
200
201#define SAA7191_BANDPASS_WEIGHT_MIN 0x00
202#define SAA7191_BANDPASS_WEIGHT_MAX 0x03
203#define SAA7191_BANDPASS_WEIGHT_DEFAULT 0x01
204
205#define SAA7191_CORING_MIN 0x00
206#define SAA7191_CORING_MAX 0x03
207#define SAA7191_CORING_DEFAULT 0x00
208
209#define SAA7191_HUE_MIN 0x00
210#define SAA7191_HUE_MAX 0xff
211#define SAA7191_HUE_DEFAULT 0x80
212
213#define SAA7191_VTRC_MIN 0x00
214#define SAA7191_VTRC_MAX 0x01
215#define SAA7191_VTRC_DEFAULT 0x00
216
217#define SAA7191_FORCE_COLOUR_MIN 0x00
218#define SAA7191_FORCE_COLOUR_MAX 0x01
219#define SAA7191_FORCE_COLOUR_DEFAULT 0x00
220
221#define SAA7191_CHROMA_GAIN_MIN 0x00
222#define SAA7191_CHROMA_GAIN_MAX 0x03
223#define SAA7191_CHROMA_GAIN_DEFAULT 0x00
224
225#define SAA7191_LUMA_DELAY_MIN -0x04
226#define SAA7191_LUMA_DELAY_MAX 0x03
227#define SAA7191_LUMA_DELAY_DEFAULT 0x01
228
229#define SAA7191_VNR_MIN 0x00
230#define SAA7191_VNR_MAX 0x03
231#define SAA7191_VNR_DEFAULT 0x00
232
233#define SAA7191_CONTROL_BANDPASS (V4L2_CID_PRIVATE_BASE + 0)
234#define SAA7191_CONTROL_BANDPASS_WEIGHT (V4L2_CID_PRIVATE_BASE + 1)
235#define SAA7191_CONTROL_CORING (V4L2_CID_PRIVATE_BASE + 2)
236#define SAA7191_CONTROL_FORCE_COLOUR (V4L2_CID_PRIVATE_BASE + 3)
237#define SAA7191_CONTROL_CHROMA_GAIN (V4L2_CID_PRIVATE_BASE + 4)
238#define SAA7191_CONTROL_VTRC (V4L2_CID_PRIVATE_BASE + 5)
239#define SAA7191_CONTROL_LUMA_DELAY (V4L2_CID_PRIVATE_BASE + 6)
240#define SAA7191_CONTROL_VNR (V4L2_CID_PRIVATE_BASE + 7)
241
242#define DECODER_SAA7191_GET_STATUS _IOR('d', 195, struct saa7191_status)
243#define DECODER_SAA7191_SET_NORM _IOW('d', 196, int)
244
245#endif
diff --git a/drivers/staging/media/vino/vino.c b/drivers/staging/media/vino/vino.c
new file mode 100644
index 000000000000..2c85357f774d
--- /dev/null
+++ b/drivers/staging/media/vino/vino.c
@@ -0,0 +1,4345 @@
1/*
2 * Driver for the VINO (Video In No Out) system found in SGI Indys.
3 *
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 *
7 * 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:
10 * Copyright (C) 2003 Ladislav Michl <ladis@linux-mips.org>
11 *
12 * v4l2_device/v4l2_subdev conversion by:
13 * Copyright (C) 2009 Hans Verkuil <hverkuil@xs4all.nl>
14 *
15 * Note: this conversion is untested! Please contact the linux-media
16 * mailinglist if you can test this, together with the test results.
17 */
18
19/*
20 * TODO:
21 * - remove "mark pages reserved-hacks" from memory allocation code
22 * and implement fault()
23 * - check decimation, calculating and reporting image size when
24 * using decimation
25 * - implement read(), user mode buffers and overlay (?)
26 */
27
28#include <linux/init.h>
29#include <linux/module.h>
30#include <linux/delay.h>
31#include <linux/dma-mapping.h>
32#include <linux/errno.h>
33#include <linux/fs.h>
34#include <linux/interrupt.h>
35#include <linux/kernel.h>
36#include <linux/slab.h>
37#include <linux/mm.h>
38#include <linux/time.h>
39#include <linux/kmod.h>
40
41#include <linux/i2c.h>
42
43#include <linux/videodev2.h>
44#include <media/v4l2-device.h>
45#include <media/v4l2-ioctl.h>
46#include <linux/mutex.h>
47
48#include <asm/paccess.h>
49#include <asm/io.h>
50#include <asm/sgi/ip22.h>
51#include <asm/sgi/mc.h>
52
53#include "vino.h"
54#include "saa7191.h"
55#include "indycam.h"
56
57/* Uncomment the following line to get lots and lots of (mostly useless)
58 * debug info.
59 * Note that the debug output also slows down the driver significantly */
60// #define VINO_DEBUG
61// #define VINO_DEBUG_INT
62
63#define VINO_MODULE_VERSION "0.0.7"
64
65MODULE_DESCRIPTION("SGI VINO Video4Linux2 driver");
66MODULE_VERSION(VINO_MODULE_VERSION);
67MODULE_AUTHOR("Mikael Nousiainen <tmnousia@cc.hut.fi>");
68MODULE_LICENSE("GPL");
69
70#ifdef VINO_DEBUG
71#define dprintk(x...) printk("VINO: " x);
72#else
73#define dprintk(x...)
74#endif
75
76#define VINO_NO_CHANNEL 0
77#define VINO_CHANNEL_A 1
78#define VINO_CHANNEL_B 2
79
80#define VINO_PAL_WIDTH 768
81#define VINO_PAL_HEIGHT 576
82#define VINO_NTSC_WIDTH 640
83#define VINO_NTSC_HEIGHT 480
84
85#define VINO_MIN_WIDTH 32
86#define VINO_MIN_HEIGHT 32
87
88#define VINO_CLIPPING_START_ODD_D1 1
89#define VINO_CLIPPING_START_ODD_PAL 15
90#define VINO_CLIPPING_START_ODD_NTSC 12
91
92#define VINO_CLIPPING_START_EVEN_D1 2
93#define VINO_CLIPPING_START_EVEN_PAL 15
94#define VINO_CLIPPING_START_EVEN_NTSC 12
95
96#define VINO_INPUT_CHANNEL_COUNT 3
97
98/* the number is the index for vino_inputs */
99#define VINO_INPUT_NONE -1
100#define VINO_INPUT_COMPOSITE 0
101#define VINO_INPUT_SVIDEO 1
102#define VINO_INPUT_D1 2
103
104#define VINO_PAGE_RATIO (PAGE_SIZE / VINO_PAGE_SIZE)
105
106#define VINO_FIFO_THRESHOLD_DEFAULT 16
107
108#define VINO_FRAMEBUFFER_SIZE ((VINO_PAL_WIDTH \
109 * VINO_PAL_HEIGHT * 4 \
110 + 3 * PAGE_SIZE) & ~(PAGE_SIZE - 1))
111
112#define VINO_FRAMEBUFFER_COUNT_MAX 8
113
114#define VINO_FRAMEBUFFER_UNUSED 0
115#define VINO_FRAMEBUFFER_IN_USE 1
116#define VINO_FRAMEBUFFER_READY 2
117
118#define VINO_QUEUE_ERROR -1
119#define VINO_QUEUE_MAGIC 0x20050125
120
121#define VINO_MEMORY_NONE 0
122#define VINO_MEMORY_MMAP 1
123#define VINO_MEMORY_USERPTR 2
124
125#define VINO_DUMMY_DESC_COUNT 4
126#define VINO_DESC_FETCH_DELAY 5 /* microseconds */
127
128#define VINO_MAX_FRAME_SKIP_COUNT 128
129
130/* the number is the index for vino_data_formats */
131#define VINO_DATA_FMT_NONE -1
132#define VINO_DATA_FMT_GREY 0
133#define VINO_DATA_FMT_RGB332 1
134#define VINO_DATA_FMT_RGB32 2
135#define VINO_DATA_FMT_YUV 3
136
137#define VINO_DATA_FMT_COUNT 4
138
139/* the number is the index for vino_data_norms */
140#define VINO_DATA_NORM_NONE -1
141#define VINO_DATA_NORM_NTSC 0
142#define VINO_DATA_NORM_PAL 1
143#define VINO_DATA_NORM_SECAM 2
144#define VINO_DATA_NORM_D1 3
145
146#define VINO_DATA_NORM_COUNT 4
147
148/* I2C controller flags */
149#define SGI_I2C_FORCE_IDLE (0 << 0)
150#define SGI_I2C_NOT_IDLE (1 << 0)
151#define SGI_I2C_WRITE (0 << 1)
152#define SGI_I2C_READ (1 << 1)
153#define SGI_I2C_RELEASE_BUS (0 << 2)
154#define SGI_I2C_HOLD_BUS (1 << 2)
155#define SGI_I2C_XFER_DONE (0 << 4)
156#define SGI_I2C_XFER_BUSY (1 << 4)
157#define SGI_I2C_ACK (0 << 5)
158#define SGI_I2C_NACK (1 << 5)
159#define SGI_I2C_BUS_OK (0 << 7)
160#define SGI_I2C_BUS_ERR (1 << 7)
161
162/* Internal data structure definitions */
163
164struct vino_input {
165 char *name;
166 v4l2_std_id std;
167};
168
169struct vino_clipping {
170 unsigned int left, right, top, bottom;
171};
172
173struct vino_data_format {
174 /* the description */
175 char *description;
176 /* bytes per pixel */
177 unsigned int bpp;
178 /* V4L2 fourcc code */
179 __u32 pixelformat;
180 /* V4L2 colorspace (duh!) */
181 enum v4l2_colorspace colorspace;
182};
183
184struct vino_data_norm {
185 char *description;
186 unsigned int width, height;
187 struct vino_clipping odd;
188 struct vino_clipping even;
189
190 v4l2_std_id std;
191 unsigned int fps_min, fps_max;
192 __u32 framelines;
193};
194
195struct vino_descriptor_table {
196 /* the number of PAGE_SIZE sized pages in the buffer */
197 unsigned int page_count;
198 /* virtual (kmalloc'd) pointers to the actual data
199 * (in PAGE_SIZE chunks, used with mmap streaming) */
200 unsigned long *virtual;
201
202 /* cpu address for the VINO descriptor table
203 * (contains DMA addresses, VINO_PAGE_SIZE chunks) */
204 unsigned long *dma_cpu;
205 /* dma address for the VINO descriptor table
206 * (contains DMA addresses, VINO_PAGE_SIZE chunks) */
207 dma_addr_t dma;
208};
209
210struct vino_framebuffer {
211 /* identifier nubmer */
212 unsigned int id;
213 /* the length of the whole buffer */
214 unsigned int size;
215 /* the length of actual data in buffer */
216 unsigned int data_size;
217 /* the data format */
218 unsigned int data_format;
219 /* the state of buffer data */
220 unsigned int state;
221 /* is the buffer mapped in user space? */
222 unsigned int map_count;
223 /* memory offset for mmap() */
224 unsigned int offset;
225 /* frame counter */
226 unsigned int frame_counter;
227 /* timestamp (written when image capture finishes) */
228 struct timeval timestamp;
229
230 struct vino_descriptor_table desc_table;
231
232 spinlock_t state_lock;
233};
234
235struct vino_framebuffer_fifo {
236 unsigned int length;
237
238 unsigned int used;
239 unsigned int head;
240 unsigned int tail;
241
242 unsigned int data[VINO_FRAMEBUFFER_COUNT_MAX];
243};
244
245struct vino_framebuffer_queue {
246 unsigned int magic;
247
248 /* VINO_MEMORY_NONE, VINO_MEMORY_MMAP or VINO_MEMORY_USERPTR */
249 unsigned int type;
250 unsigned int length;
251
252 /* data field of in and out contain index numbers for buffer */
253 struct vino_framebuffer_fifo in;
254 struct vino_framebuffer_fifo out;
255
256 struct vino_framebuffer *buffer[VINO_FRAMEBUFFER_COUNT_MAX];
257
258 spinlock_t queue_lock;
259 struct mutex queue_mutex;
260 wait_queue_head_t frame_wait_queue;
261};
262
263struct vino_interrupt_data {
264 struct timeval timestamp;
265 unsigned int frame_counter;
266 unsigned int skip_count;
267 unsigned int skip;
268};
269
270struct vino_channel_settings {
271 unsigned int channel;
272
273 int input;
274 unsigned int data_format;
275 unsigned int data_norm;
276 struct vino_clipping clipping;
277 unsigned int decimation;
278 unsigned int line_size;
279 unsigned int alpha;
280 unsigned int fps;
281 unsigned int framert_reg;
282
283 unsigned int fifo_threshold;
284
285 struct vino_framebuffer_queue fb_queue;
286
287 /* number of the current field */
288 unsigned int field;
289
290 /* read in progress */
291 int reading;
292 /* streaming is active */
293 int streaming;
294 /* the driver is currently processing the queue */
295 int capturing;
296
297 struct mutex mutex;
298 spinlock_t capture_lock;
299
300 unsigned int users;
301
302 struct vino_interrupt_data int_data;
303
304 /* V4L support */
305 struct video_device *vdev;
306};
307
308struct vino_settings {
309 struct v4l2_device v4l2_dev;
310 struct vino_channel_settings a;
311 struct vino_channel_settings b;
312
313 /* the channel which owns this client:
314 * VINO_NO_CHANNEL, VINO_CHANNEL_A or VINO_CHANNEL_B */
315 unsigned int decoder_owner;
316 struct v4l2_subdev *decoder;
317 unsigned int camera_owner;
318 struct v4l2_subdev *camera;
319
320 /* a lock for vino register access */
321 spinlock_t vino_lock;
322 /* a lock for channel input changes */
323 spinlock_t input_lock;
324
325 unsigned long dummy_page;
326 struct vino_descriptor_table dummy_desc_table;
327};
328
329/* Module parameters */
330
331/*
332 * Using vino_pixel_conversion the ABGR32-format pixels supplied
333 * by the VINO chip can be converted to more common formats
334 * like RGBA32 (or probably RGB24 in the future). This way we
335 * can give out data that can be specified correctly with
336 * the V4L2-definitions.
337 *
338 * The pixel format is specified as RGBA32 when no conversion
339 * is used.
340 *
341 * Note that this only affects the 32-bit bit depth.
342 *
343 * Use non-zero value to enable conversion.
344 */
345static int vino_pixel_conversion;
346
347module_param_named(pixelconv, vino_pixel_conversion, int, 0);
348
349MODULE_PARM_DESC(pixelconv,
350 "enable pixel conversion (non-zero value enables)");
351
352/* Internal data structures */
353
354static struct sgi_vino *vino;
355
356static struct vino_settings *vino_drvdata;
357
358#define camera_call(o, f, args...) \
359 v4l2_subdev_call(vino_drvdata->camera, o, f, ##args)
360#define decoder_call(o, f, args...) \
361 v4l2_subdev_call(vino_drvdata->decoder, o, f, ##args)
362
363static const char *vino_driver_name = "vino";
364static const char *vino_driver_description = "SGI VINO";
365static const char *vino_bus_name = "GIO64 bus";
366static const char *vino_vdev_name_a = "SGI VINO Channel A";
367static const char *vino_vdev_name_b = "SGI VINO Channel B";
368
369static void vino_capture_tasklet(unsigned long channel);
370
371DECLARE_TASKLET(vino_tasklet_a, vino_capture_tasklet, VINO_CHANNEL_A);
372DECLARE_TASKLET(vino_tasklet_b, vino_capture_tasklet, VINO_CHANNEL_B);
373
374static const struct vino_input vino_inputs[] = {
375 {
376 .name = "Composite",
377 .std = V4L2_STD_NTSC | V4L2_STD_PAL
378 | V4L2_STD_SECAM,
379 }, {
380 .name = "S-Video",
381 .std = V4L2_STD_NTSC | V4L2_STD_PAL
382 | V4L2_STD_SECAM,
383 }, {
384 .name = "D1/IndyCam",
385 .std = V4L2_STD_NTSC,
386 }
387};
388
389static const struct vino_data_format vino_data_formats[] = {
390 {
391 .description = "8-bit greyscale",
392 .bpp = 1,
393 .pixelformat = V4L2_PIX_FMT_GREY,
394 .colorspace = V4L2_COLORSPACE_SMPTE170M,
395 }, {
396 .description = "8-bit dithered RGB 3-3-2",
397 .bpp = 1,
398 .pixelformat = V4L2_PIX_FMT_RGB332,
399 .colorspace = V4L2_COLORSPACE_SRGB,
400 }, {
401 .description = "32-bit RGB",
402 .bpp = 4,
403 .pixelformat = V4L2_PIX_FMT_RGB32,
404 .colorspace = V4L2_COLORSPACE_SRGB,
405 }, {
406 .description = "YUV 4:2:2",
407 .bpp = 2,
408 .pixelformat = V4L2_PIX_FMT_YUYV, // XXX: swapped?
409 .colorspace = V4L2_COLORSPACE_SMPTE170M,
410 }
411};
412
413static const struct vino_data_norm vino_data_norms[] = {
414 {
415 .description = "NTSC",
416 .std = V4L2_STD_NTSC,
417 .fps_min = 6,
418 .fps_max = 30,
419 .framelines = 525,
420 .width = VINO_NTSC_WIDTH,
421 .height = VINO_NTSC_HEIGHT,
422 .odd = {
423 .top = VINO_CLIPPING_START_ODD_NTSC,
424 .left = 0,
425 .bottom = VINO_CLIPPING_START_ODD_NTSC
426 + VINO_NTSC_HEIGHT / 2 - 1,
427 .right = VINO_NTSC_WIDTH,
428 },
429 .even = {
430 .top = VINO_CLIPPING_START_EVEN_NTSC,
431 .left = 0,
432 .bottom = VINO_CLIPPING_START_EVEN_NTSC
433 + VINO_NTSC_HEIGHT / 2 - 1,
434 .right = VINO_NTSC_WIDTH,
435 },
436 }, {
437 .description = "PAL",
438 .std = V4L2_STD_PAL,
439 .fps_min = 5,
440 .fps_max = 25,
441 .framelines = 625,
442 .width = VINO_PAL_WIDTH,
443 .height = VINO_PAL_HEIGHT,
444 .odd = {
445 .top = VINO_CLIPPING_START_ODD_PAL,
446 .left = 0,
447 .bottom = VINO_CLIPPING_START_ODD_PAL
448 + VINO_PAL_HEIGHT / 2 - 1,
449 .right = VINO_PAL_WIDTH,
450 },
451 .even = {
452 .top = VINO_CLIPPING_START_EVEN_PAL,
453 .left = 0,
454 .bottom = VINO_CLIPPING_START_EVEN_PAL
455 + VINO_PAL_HEIGHT / 2 - 1,
456 .right = VINO_PAL_WIDTH,
457 },
458 }, {
459 .description = "SECAM",
460 .std = V4L2_STD_SECAM,
461 .fps_min = 5,
462 .fps_max = 25,
463 .framelines = 625,
464 .width = VINO_PAL_WIDTH,
465 .height = VINO_PAL_HEIGHT,
466 .odd = {
467 .top = VINO_CLIPPING_START_ODD_PAL,
468 .left = 0,
469 .bottom = VINO_CLIPPING_START_ODD_PAL
470 + VINO_PAL_HEIGHT / 2 - 1,
471 .right = VINO_PAL_WIDTH,
472 },
473 .even = {
474 .top = VINO_CLIPPING_START_EVEN_PAL,
475 .left = 0,
476 .bottom = VINO_CLIPPING_START_EVEN_PAL
477 + VINO_PAL_HEIGHT / 2 - 1,
478 .right = VINO_PAL_WIDTH,
479 },
480 }, {
481 .description = "NTSC/D1",
482 .std = V4L2_STD_NTSC,
483 .fps_min = 6,
484 .fps_max = 30,
485 .framelines = 525,
486 .width = VINO_NTSC_WIDTH,
487 .height = VINO_NTSC_HEIGHT,
488 .odd = {
489 .top = VINO_CLIPPING_START_ODD_D1,
490 .left = 0,
491 .bottom = VINO_CLIPPING_START_ODD_D1
492 + VINO_NTSC_HEIGHT / 2 - 1,
493 .right = VINO_NTSC_WIDTH,
494 },
495 .even = {
496 .top = VINO_CLIPPING_START_EVEN_D1,
497 .left = 0,
498 .bottom = VINO_CLIPPING_START_EVEN_D1
499 + VINO_NTSC_HEIGHT / 2 - 1,
500 .right = VINO_NTSC_WIDTH,
501 },
502 }
503};
504
505#define VINO_INDYCAM_V4L2_CONTROL_COUNT 9
506
507struct v4l2_queryctrl vino_indycam_v4l2_controls[] = {
508 {
509 .id = V4L2_CID_AUTOGAIN,
510 .type = V4L2_CTRL_TYPE_BOOLEAN,
511 .name = "Automatic Gain Control",
512 .minimum = 0,
513 .maximum = 1,
514 .step = 1,
515 .default_value = INDYCAM_AGC_DEFAULT,
516 }, {
517 .id = V4L2_CID_AUTO_WHITE_BALANCE,
518 .type = V4L2_CTRL_TYPE_BOOLEAN,
519 .name = "Automatic White Balance",
520 .minimum = 0,
521 .maximum = 1,
522 .step = 1,
523 .default_value = INDYCAM_AWB_DEFAULT,
524 }, {
525 .id = V4L2_CID_GAIN,
526 .type = V4L2_CTRL_TYPE_INTEGER,
527 .name = "Gain",
528 .minimum = INDYCAM_GAIN_MIN,
529 .maximum = INDYCAM_GAIN_MAX,
530 .step = 1,
531 .default_value = INDYCAM_GAIN_DEFAULT,
532 }, {
533 .id = INDYCAM_CONTROL_RED_SATURATION,
534 .type = V4L2_CTRL_TYPE_INTEGER,
535 .name = "Red Saturation",
536 .minimum = INDYCAM_RED_SATURATION_MIN,
537 .maximum = INDYCAM_RED_SATURATION_MAX,
538 .step = 1,
539 .default_value = INDYCAM_RED_SATURATION_DEFAULT,
540 }, {
541 .id = INDYCAM_CONTROL_BLUE_SATURATION,
542 .type = V4L2_CTRL_TYPE_INTEGER,
543 .name = "Blue Saturation",
544 .minimum = INDYCAM_BLUE_SATURATION_MIN,
545 .maximum = INDYCAM_BLUE_SATURATION_MAX,
546 .step = 1,
547 .default_value = INDYCAM_BLUE_SATURATION_DEFAULT,
548 }, {
549 .id = V4L2_CID_RED_BALANCE,
550 .type = V4L2_CTRL_TYPE_INTEGER,
551 .name = "Red Balance",
552 .minimum = INDYCAM_RED_BALANCE_MIN,
553 .maximum = INDYCAM_RED_BALANCE_MAX,
554 .step = 1,
555 .default_value = INDYCAM_RED_BALANCE_DEFAULT,
556 }, {
557 .id = V4L2_CID_BLUE_BALANCE,
558 .type = V4L2_CTRL_TYPE_INTEGER,
559 .name = "Blue Balance",
560 .minimum = INDYCAM_BLUE_BALANCE_MIN,
561 .maximum = INDYCAM_BLUE_BALANCE_MAX,
562 .step = 1,
563 .default_value = INDYCAM_BLUE_BALANCE_DEFAULT,
564 }, {
565 .id = V4L2_CID_EXPOSURE,
566 .type = V4L2_CTRL_TYPE_INTEGER,
567 .name = "Shutter Control",
568 .minimum = INDYCAM_SHUTTER_MIN,
569 .maximum = INDYCAM_SHUTTER_MAX,
570 .step = 1,
571 .default_value = INDYCAM_SHUTTER_DEFAULT,
572 }, {
573 .id = V4L2_CID_GAMMA,
574 .type = V4L2_CTRL_TYPE_INTEGER,
575 .name = "Gamma",
576 .minimum = INDYCAM_GAMMA_MIN,
577 .maximum = INDYCAM_GAMMA_MAX,
578 .step = 1,
579 .default_value = INDYCAM_GAMMA_DEFAULT,
580 }
581};
582
583#define VINO_SAA7191_V4L2_CONTROL_COUNT 9
584
585struct v4l2_queryctrl vino_saa7191_v4l2_controls[] = {
586 {
587 .id = V4L2_CID_HUE,
588 .type = V4L2_CTRL_TYPE_INTEGER,
589 .name = "Hue",
590 .minimum = SAA7191_HUE_MIN,
591 .maximum = SAA7191_HUE_MAX,
592 .step = 1,
593 .default_value = SAA7191_HUE_DEFAULT,
594 }, {
595 .id = SAA7191_CONTROL_BANDPASS,
596 .type = V4L2_CTRL_TYPE_INTEGER,
597 .name = "Luminance Bandpass",
598 .minimum = SAA7191_BANDPASS_MIN,
599 .maximum = SAA7191_BANDPASS_MAX,
600 .step = 1,
601 .default_value = SAA7191_BANDPASS_DEFAULT,
602 }, {
603 .id = SAA7191_CONTROL_BANDPASS_WEIGHT,
604 .type = V4L2_CTRL_TYPE_INTEGER,
605 .name = "Luminance Bandpass Weight",
606 .minimum = SAA7191_BANDPASS_WEIGHT_MIN,
607 .maximum = SAA7191_BANDPASS_WEIGHT_MAX,
608 .step = 1,
609 .default_value = SAA7191_BANDPASS_WEIGHT_DEFAULT,
610 }, {
611 .id = SAA7191_CONTROL_CORING,
612 .type = V4L2_CTRL_TYPE_INTEGER,
613 .name = "HF Luminance Coring",
614 .minimum = SAA7191_CORING_MIN,
615 .maximum = SAA7191_CORING_MAX,
616 .step = 1,
617 .default_value = SAA7191_CORING_DEFAULT,
618 }, {
619 .id = SAA7191_CONTROL_FORCE_COLOUR,
620 .type = V4L2_CTRL_TYPE_BOOLEAN,
621 .name = "Force Colour",
622 .minimum = SAA7191_FORCE_COLOUR_MIN,
623 .maximum = SAA7191_FORCE_COLOUR_MAX,
624 .step = 1,
625 .default_value = SAA7191_FORCE_COLOUR_DEFAULT,
626 }, {
627 .id = SAA7191_CONTROL_CHROMA_GAIN,
628 .type = V4L2_CTRL_TYPE_INTEGER,
629 .name = "Chrominance Gain Control",
630 .minimum = SAA7191_CHROMA_GAIN_MIN,
631 .maximum = SAA7191_CHROMA_GAIN_MAX,
632 .step = 1,
633 .default_value = SAA7191_CHROMA_GAIN_DEFAULT,
634 }, {
635 .id = SAA7191_CONTROL_VTRC,
636 .type = V4L2_CTRL_TYPE_BOOLEAN,
637 .name = "VTR Time Constant",
638 .minimum = SAA7191_VTRC_MIN,
639 .maximum = SAA7191_VTRC_MAX,
640 .step = 1,
641 .default_value = SAA7191_VTRC_DEFAULT,
642 }, {
643 .id = SAA7191_CONTROL_LUMA_DELAY,
644 .type = V4L2_CTRL_TYPE_INTEGER,
645 .name = "Luminance Delay Compensation",
646 .minimum = SAA7191_LUMA_DELAY_MIN,
647 .maximum = SAA7191_LUMA_DELAY_MAX,
648 .step = 1,
649 .default_value = SAA7191_LUMA_DELAY_DEFAULT,
650 }, {
651 .id = SAA7191_CONTROL_VNR,
652 .type = V4L2_CTRL_TYPE_INTEGER,
653 .name = "Vertical Noise Reduction",
654 .minimum = SAA7191_VNR_MIN,
655 .maximum = SAA7191_VNR_MAX,
656 .step = 1,
657 .default_value = SAA7191_VNR_DEFAULT,
658 }
659};
660
661/* VINO framebuffer/DMA descriptor management */
662
663static void vino_free_buffer_with_count(struct vino_framebuffer *fb,
664 unsigned int count)
665{
666 unsigned int i;
667
668 dprintk("vino_free_buffer_with_count(): count = %d\n", count);
669
670 for (i = 0; i < count; i++) {
671 ClearPageReserved(virt_to_page((void *)fb->desc_table.virtual[i]));
672 dma_unmap_single(NULL,
673 fb->desc_table.dma_cpu[VINO_PAGE_RATIO * i],
674 PAGE_SIZE, DMA_FROM_DEVICE);
675 free_page(fb->desc_table.virtual[i]);
676 }
677
678 dma_free_coherent(NULL,
679 VINO_PAGE_RATIO * (fb->desc_table.page_count + 4) *
680 sizeof(dma_addr_t), (void *)fb->desc_table.dma_cpu,
681 fb->desc_table.dma);
682 kfree(fb->desc_table.virtual);
683
684 memset(fb, 0, sizeof(struct vino_framebuffer));
685}
686
687static void vino_free_buffer(struct vino_framebuffer *fb)
688{
689 vino_free_buffer_with_count(fb, fb->desc_table.page_count);
690}
691
692static int vino_allocate_buffer(struct vino_framebuffer *fb,
693 unsigned int size)
694{
695 unsigned int count, i, j;
696 int ret = 0;
697
698 dprintk("vino_allocate_buffer():\n");
699
700 if (size < 1)
701 return -EINVAL;
702
703 memset(fb, 0, sizeof(struct vino_framebuffer));
704
705 count = ((size / PAGE_SIZE) + 4) & ~3;
706
707 dprintk("vino_allocate_buffer(): size = %d, count = %d\n",
708 size, count);
709
710 /* allocate memory for table with virtual (page) addresses */
711 fb->desc_table.virtual =
712 kmalloc(count * sizeof(unsigned long), GFP_KERNEL);
713 if (!fb->desc_table.virtual)
714 return -ENOMEM;
715
716 /* allocate memory for table with dma addresses
717 * (has space for four extra descriptors) */
718 fb->desc_table.dma_cpu =
719 dma_alloc_coherent(NULL, VINO_PAGE_RATIO * (count + 4) *
720 sizeof(dma_addr_t), &fb->desc_table.dma,
721 GFP_KERNEL | GFP_DMA);
722 if (!fb->desc_table.dma_cpu) {
723 ret = -ENOMEM;
724 goto out_free_virtual;
725 }
726
727 /* allocate pages for the buffer and acquire the according
728 * dma addresses */
729 for (i = 0; i < count; i++) {
730 dma_addr_t dma_data_addr;
731
732 fb->desc_table.virtual[i] =
733 get_zeroed_page(GFP_KERNEL | GFP_DMA);
734 if (!fb->desc_table.virtual[i]) {
735 ret = -ENOBUFS;
736 break;
737 }
738
739 dma_data_addr =
740 dma_map_single(NULL,
741 (void *)fb->desc_table.virtual[i],
742 PAGE_SIZE, DMA_FROM_DEVICE);
743
744 for (j = 0; j < VINO_PAGE_RATIO; j++) {
745 fb->desc_table.dma_cpu[VINO_PAGE_RATIO * i + j] =
746 dma_data_addr + VINO_PAGE_SIZE * j;
747 }
748
749 SetPageReserved(virt_to_page((void *)fb->desc_table.virtual[i]));
750 }
751
752 /* page_count needs to be set anyway, because the descriptor table has
753 * been allocated according to this number */
754 fb->desc_table.page_count = count;
755
756 if (ret) {
757 /* the descriptor with index i doesn't contain
758 * a valid address yet */
759 vino_free_buffer_with_count(fb, i);
760 return ret;
761 }
762
763 //fb->size = size;
764 fb->size = count * PAGE_SIZE;
765 fb->data_format = VINO_DATA_FMT_NONE;
766
767 /* set the dma stop-bit for the last (count+1)th descriptor */
768 fb->desc_table.dma_cpu[VINO_PAGE_RATIO * count] = VINO_DESC_STOP;
769 return 0;
770
771 out_free_virtual:
772 kfree(fb->desc_table.virtual);
773 return ret;
774}
775
776#if 0
777/* user buffers not fully implemented yet */
778static int vino_prepare_user_buffer(struct vino_framebuffer *fb,
779 void *user,
780 unsigned int size)
781{
782 unsigned int count, i, j;
783 int ret = 0;
784
785 dprintk("vino_prepare_user_buffer():\n");
786
787 if (size < 1)
788 return -EINVAL;
789
790 memset(fb, 0, sizeof(struct vino_framebuffer));
791
792 count = ((size / PAGE_SIZE)) & ~3;
793
794 dprintk("vino_prepare_user_buffer(): size = %d, count = %d\n",
795 size, count);
796
797 /* allocate memory for table with virtual (page) addresses */
798 fb->desc_table.virtual = (unsigned long *)
799 kmalloc(count * sizeof(unsigned long), GFP_KERNEL);
800 if (!fb->desc_table.virtual)
801 return -ENOMEM;
802
803 /* allocate memory for table with dma addresses
804 * (has space for four extra descriptors) */
805 fb->desc_table.dma_cpu =
806 dma_alloc_coherent(NULL, VINO_PAGE_RATIO * (count + 4) *
807 sizeof(dma_addr_t), &fb->desc_table.dma,
808 GFP_KERNEL | GFP_DMA);
809 if (!fb->desc_table.dma_cpu) {
810 ret = -ENOMEM;
811 goto out_free_virtual;
812 }
813
814 /* allocate pages for the buffer and acquire the according
815 * dma addresses */
816 for (i = 0; i < count; i++) {
817 dma_addr_t dma_data_addr;
818
819 fb->desc_table.virtual[i] =
820 get_zeroed_page(GFP_KERNEL | GFP_DMA);
821 if (!fb->desc_table.virtual[i]) {
822 ret = -ENOBUFS;
823 break;
824 }
825
826 dma_data_addr =
827 dma_map_single(NULL,
828 (void *)fb->desc_table.virtual[i],
829 PAGE_SIZE, DMA_FROM_DEVICE);
830
831 for (j = 0; j < VINO_PAGE_RATIO; j++) {
832 fb->desc_table.dma_cpu[VINO_PAGE_RATIO * i + j] =
833 dma_data_addr + VINO_PAGE_SIZE * j;
834 }
835
836 SetPageReserved(virt_to_page((void *)fb->desc_table.virtual[i]));
837 }
838
839 /* page_count needs to be set anyway, because the descriptor table has
840 * been allocated according to this number */
841 fb->desc_table.page_count = count;
842
843 if (ret) {
844 /* the descriptor with index i doesn't contain
845 * a valid address yet */
846 vino_free_buffer_with_count(fb, i);
847 return ret;
848 }
849
850 //fb->size = size;
851 fb->size = count * PAGE_SIZE;
852
853 /* set the dma stop-bit for the last (count+1)th descriptor */
854 fb->desc_table.dma_cpu[VINO_PAGE_RATIO * count] = VINO_DESC_STOP;
855 return 0;
856
857 out_free_virtual:
858 kfree(fb->desc_table.virtual);
859 return ret;
860}
861#endif
862
863static void vino_sync_buffer(struct vino_framebuffer *fb)
864{
865 int i;
866
867 dprintk("vino_sync_buffer():\n");
868
869 for (i = 0; i < fb->desc_table.page_count; i++)
870 dma_sync_single_for_cpu(NULL,
871 fb->desc_table.dma_cpu[VINO_PAGE_RATIO * i],
872 PAGE_SIZE, DMA_FROM_DEVICE);
873}
874
875/* Framebuffer fifo functions (need to be locked externally) */
876
877static inline void vino_fifo_init(struct vino_framebuffer_fifo *f,
878 unsigned int length)
879{
880 f->length = 0;
881 f->used = 0;
882 f->head = 0;
883 f->tail = 0;
884
885 if (length > VINO_FRAMEBUFFER_COUNT_MAX)
886 length = VINO_FRAMEBUFFER_COUNT_MAX;
887
888 f->length = length;
889}
890
891/* returns true/false */
892static inline int vino_fifo_has_id(struct vino_framebuffer_fifo *f,
893 unsigned int id)
894{
895 unsigned int i;
896
897 for (i = f->head; i == (f->tail - 1); i = (i + 1) % f->length) {
898 if (f->data[i] == id)
899 return 1;
900 }
901
902 return 0;
903}
904
905#if 0
906/* returns true/false */
907static inline int vino_fifo_full(struct vino_framebuffer_fifo *f)
908{
909 return (f->used == f->length);
910}
911#endif
912
913static inline unsigned int vino_fifo_get_used(struct vino_framebuffer_fifo *f)
914{
915 return f->used;
916}
917
918static int vino_fifo_enqueue(struct vino_framebuffer_fifo *f, unsigned int id)
919{
920 if (id >= f->length) {
921 return VINO_QUEUE_ERROR;
922 }
923
924 if (vino_fifo_has_id(f, id)) {
925 return VINO_QUEUE_ERROR;
926 }
927
928 if (f->used < f->length) {
929 f->data[f->tail] = id;
930 f->tail = (f->tail + 1) % f->length;
931 f->used++;
932 } else {
933 return VINO_QUEUE_ERROR;
934 }
935
936 return 0;
937}
938
939static int vino_fifo_peek(struct vino_framebuffer_fifo *f, unsigned int *id)
940{
941 if (f->used > 0) {
942 *id = f->data[f->head];
943 } else {
944 return VINO_QUEUE_ERROR;
945 }
946
947 return 0;
948}
949
950static int vino_fifo_dequeue(struct vino_framebuffer_fifo *f, unsigned int *id)
951{
952 if (f->used > 0) {
953 *id = f->data[f->head];
954 f->head = (f->head + 1) % f->length;
955 f->used--;
956 } else {
957 return VINO_QUEUE_ERROR;
958 }
959
960 return 0;
961}
962
963/* Framebuffer queue functions */
964
965/* execute with queue_lock locked */
966static void vino_queue_free_with_count(struct vino_framebuffer_queue *q,
967 unsigned int length)
968{
969 unsigned int i;
970
971 q->length = 0;
972 memset(&q->in, 0, sizeof(struct vino_framebuffer_fifo));
973 memset(&q->out, 0, sizeof(struct vino_framebuffer_fifo));
974 for (i = 0; i < length; i++) {
975 dprintk("vino_queue_free_with_count(): freeing buffer %d\n",
976 i);
977 vino_free_buffer(q->buffer[i]);
978 kfree(q->buffer[i]);
979 }
980
981 q->type = VINO_MEMORY_NONE;
982 q->magic = 0;
983}
984
985static void vino_queue_free(struct vino_framebuffer_queue *q)
986{
987 dprintk("vino_queue_free():\n");
988
989 if (q->magic != VINO_QUEUE_MAGIC)
990 return;
991 if (q->type != VINO_MEMORY_MMAP)
992 return;
993
994 mutex_lock(&q->queue_mutex);
995
996 vino_queue_free_with_count(q, q->length);
997
998 mutex_unlock(&q->queue_mutex);
999}
1000
1001static int vino_queue_init(struct vino_framebuffer_queue *q,
1002 unsigned int *length)
1003{
1004 unsigned int i;
1005 int ret = 0;
1006
1007 dprintk("vino_queue_init(): length = %d\n", *length);
1008
1009 if (q->magic == VINO_QUEUE_MAGIC) {
1010 dprintk("vino_queue_init(): queue already initialized!\n");
1011 return -EINVAL;
1012 }
1013
1014 if (q->type != VINO_MEMORY_NONE) {
1015 dprintk("vino_queue_init(): queue already initialized!\n");
1016 return -EINVAL;
1017 }
1018
1019 if (*length < 1)
1020 return -EINVAL;
1021
1022 mutex_lock(&q->queue_mutex);
1023
1024 if (*length > VINO_FRAMEBUFFER_COUNT_MAX)
1025 *length = VINO_FRAMEBUFFER_COUNT_MAX;
1026
1027 q->length = 0;
1028
1029 for (i = 0; i < *length; i++) {
1030 dprintk("vino_queue_init(): allocating buffer %d\n", i);
1031 q->buffer[i] = kmalloc(sizeof(struct vino_framebuffer),
1032 GFP_KERNEL);
1033 if (!q->buffer[i]) {
1034 dprintk("vino_queue_init(): kmalloc() failed\n");
1035 ret = -ENOMEM;
1036 break;
1037 }
1038
1039 ret = vino_allocate_buffer(q->buffer[i],
1040 VINO_FRAMEBUFFER_SIZE);
1041 if (ret) {
1042 kfree(q->buffer[i]);
1043 dprintk("vino_queue_init(): "
1044 "vino_allocate_buffer() failed\n");
1045 break;
1046 }
1047
1048 q->buffer[i]->id = i;
1049 if (i > 0) {
1050 q->buffer[i]->offset = q->buffer[i - 1]->offset +
1051 q->buffer[i - 1]->size;
1052 } else {
1053 q->buffer[i]->offset = 0;
1054 }
1055
1056 spin_lock_init(&q->buffer[i]->state_lock);
1057
1058 dprintk("vino_queue_init(): buffer = %d, offset = %d, "
1059 "size = %d\n", i, q->buffer[i]->offset,
1060 q->buffer[i]->size);
1061 }
1062
1063 if (ret) {
1064 vino_queue_free_with_count(q, i);
1065 *length = 0;
1066 } else {
1067 q->length = *length;
1068 vino_fifo_init(&q->in, q->length);
1069 vino_fifo_init(&q->out, q->length);
1070 q->type = VINO_MEMORY_MMAP;
1071 q->magic = VINO_QUEUE_MAGIC;
1072 }
1073
1074 mutex_unlock(&q->queue_mutex);
1075
1076 return ret;
1077}
1078
1079static struct vino_framebuffer *vino_queue_add(struct
1080 vino_framebuffer_queue *q,
1081 unsigned int id)
1082{
1083 struct vino_framebuffer *ret = NULL;
1084 unsigned int total;
1085 unsigned long flags;
1086
1087 dprintk("vino_queue_add(): id = %d\n", id);
1088
1089 if (q->magic != VINO_QUEUE_MAGIC) {
1090 return ret;
1091 }
1092
1093 spin_lock_irqsave(&q->queue_lock, flags);
1094
1095 if (q->length == 0)
1096 goto out;
1097
1098 if (id >= q->length)
1099 goto out;
1100
1101 /* not needed?: if (vino_fifo_full(&q->out)) {
1102 goto out;
1103 }*/
1104 /* check that outgoing queue isn't already full
1105 * (or that it won't become full) */
1106 total = vino_fifo_get_used(&q->in) +
1107 vino_fifo_get_used(&q->out);
1108 if (total >= q->length)
1109 goto out;
1110
1111 if (vino_fifo_enqueue(&q->in, id))
1112 goto out;
1113
1114 ret = q->buffer[id];
1115
1116out:
1117 spin_unlock_irqrestore(&q->queue_lock, flags);
1118
1119 return ret;
1120}
1121
1122static struct vino_framebuffer *vino_queue_transfer(struct
1123 vino_framebuffer_queue *q)
1124{
1125 struct vino_framebuffer *ret = NULL;
1126 struct vino_framebuffer *fb;
1127 int id;
1128 unsigned long flags;
1129
1130 dprintk("vino_queue_transfer():\n");
1131
1132 if (q->magic != VINO_QUEUE_MAGIC) {
1133 return ret;
1134 }
1135
1136 spin_lock_irqsave(&q->queue_lock, flags);
1137
1138 if (q->length == 0)
1139 goto out;
1140
1141 // now this actually removes an entry from the incoming queue
1142 if (vino_fifo_dequeue(&q->in, &id)) {
1143 goto out;
1144 }
1145
1146 dprintk("vino_queue_transfer(): id = %d\n", id);
1147 fb = q->buffer[id];
1148
1149 // we have already checked that the outgoing queue is not full, but...
1150 if (vino_fifo_enqueue(&q->out, id)) {
1151 printk(KERN_ERR "vino_queue_transfer(): "
1152 "outgoing queue is full, this shouldn't happen!\n");
1153 goto out;
1154 }
1155
1156 ret = fb;
1157out:
1158 spin_unlock_irqrestore(&q->queue_lock, flags);
1159
1160 return ret;
1161}
1162
1163/* returns true/false */
1164static int vino_queue_incoming_contains(struct vino_framebuffer_queue *q,
1165 unsigned int id)
1166{
1167 int ret = 0;
1168 unsigned long flags;
1169
1170 if (q->magic != VINO_QUEUE_MAGIC) {
1171 return ret;
1172 }
1173
1174 spin_lock_irqsave(&q->queue_lock, flags);
1175
1176 if (q->length == 0)
1177 goto out;
1178
1179 ret = vino_fifo_has_id(&q->in, id);
1180
1181out:
1182 spin_unlock_irqrestore(&q->queue_lock, flags);
1183
1184 return ret;
1185}
1186
1187/* returns true/false */
1188static int vino_queue_outgoing_contains(struct vino_framebuffer_queue *q,
1189 unsigned int id)
1190{
1191 int ret = 0;
1192 unsigned long flags;
1193
1194 if (q->magic != VINO_QUEUE_MAGIC) {
1195 return ret;
1196 }
1197
1198 spin_lock_irqsave(&q->queue_lock, flags);
1199
1200 if (q->length == 0)
1201 goto out;
1202
1203 ret = vino_fifo_has_id(&q->out, id);
1204
1205out:
1206 spin_unlock_irqrestore(&q->queue_lock, flags);
1207
1208 return ret;
1209}
1210
1211static int vino_queue_get_incoming(struct vino_framebuffer_queue *q,
1212 unsigned int *used)
1213{
1214 int ret = 0;
1215 unsigned long flags;
1216
1217 if (q->magic != VINO_QUEUE_MAGIC) {
1218 return VINO_QUEUE_ERROR;
1219 }
1220
1221 spin_lock_irqsave(&q->queue_lock, flags);
1222
1223 if (q->length == 0) {
1224 ret = VINO_QUEUE_ERROR;
1225 goto out;
1226 }
1227
1228 *used = vino_fifo_get_used(&q->in);
1229
1230out:
1231 spin_unlock_irqrestore(&q->queue_lock, flags);
1232
1233 return ret;
1234}
1235
1236static int vino_queue_get_outgoing(struct vino_framebuffer_queue *q,
1237 unsigned int *used)
1238{
1239 int ret = 0;
1240 unsigned long flags;
1241
1242 if (q->magic != VINO_QUEUE_MAGIC) {
1243 return VINO_QUEUE_ERROR;
1244 }
1245
1246 spin_lock_irqsave(&q->queue_lock, flags);
1247
1248 if (q->length == 0) {
1249 ret = VINO_QUEUE_ERROR;
1250 goto out;
1251 }
1252
1253 *used = vino_fifo_get_used(&q->out);
1254
1255out:
1256 spin_unlock_irqrestore(&q->queue_lock, flags);
1257
1258 return ret;
1259}
1260
1261#if 0
1262static int vino_queue_get_total(struct vino_framebuffer_queue *q,
1263 unsigned int *total)
1264{
1265 int ret = 0;
1266 unsigned long flags;
1267
1268 if (q->magic != VINO_QUEUE_MAGIC) {
1269 return VINO_QUEUE_ERROR;
1270 }
1271
1272 spin_lock_irqsave(&q->queue_lock, flags);
1273
1274 if (q->length == 0) {
1275 ret = VINO_QUEUE_ERROR;
1276 goto out;
1277 }
1278
1279 *total = vino_fifo_get_used(&q->in) +
1280 vino_fifo_get_used(&q->out);
1281
1282out:
1283 spin_unlock_irqrestore(&q->queue_lock, flags);
1284
1285 return ret;
1286}
1287#endif
1288
1289static struct vino_framebuffer *vino_queue_peek(struct
1290 vino_framebuffer_queue *q,
1291 unsigned int *id)
1292{
1293 struct vino_framebuffer *ret = NULL;
1294 unsigned long flags;
1295
1296 if (q->magic != VINO_QUEUE_MAGIC) {
1297 return ret;
1298 }
1299
1300 spin_lock_irqsave(&q->queue_lock, flags);
1301
1302 if (q->length == 0)
1303 goto out;
1304
1305 if (vino_fifo_peek(&q->in, id)) {
1306 goto out;
1307 }
1308
1309 ret = q->buffer[*id];
1310out:
1311 spin_unlock_irqrestore(&q->queue_lock, flags);
1312
1313 return ret;
1314}
1315
1316static struct vino_framebuffer *vino_queue_remove(struct
1317 vino_framebuffer_queue *q,
1318 unsigned int *id)
1319{
1320 struct vino_framebuffer *ret = NULL;
1321 unsigned long flags;
1322 dprintk("vino_queue_remove():\n");
1323
1324 if (q->magic != VINO_QUEUE_MAGIC) {
1325 return ret;
1326 }
1327
1328 spin_lock_irqsave(&q->queue_lock, flags);
1329
1330 if (q->length == 0)
1331 goto out;
1332
1333 if (vino_fifo_dequeue(&q->out, id)) {
1334 goto out;
1335 }
1336
1337 dprintk("vino_queue_remove(): id = %d\n", *id);
1338 ret = q->buffer[*id];
1339out:
1340 spin_unlock_irqrestore(&q->queue_lock, flags);
1341
1342 return ret;
1343}
1344
1345static struct
1346vino_framebuffer *vino_queue_get_buffer(struct vino_framebuffer_queue *q,
1347 unsigned int id)
1348{
1349 struct vino_framebuffer *ret = NULL;
1350 unsigned long flags;
1351
1352 if (q->magic != VINO_QUEUE_MAGIC) {
1353 return ret;
1354 }
1355
1356 spin_lock_irqsave(&q->queue_lock, flags);
1357
1358 if (q->length == 0)
1359 goto out;
1360
1361 if (id >= q->length)
1362 goto out;
1363
1364 ret = q->buffer[id];
1365 out:
1366 spin_unlock_irqrestore(&q->queue_lock, flags);
1367
1368 return ret;
1369}
1370
1371static unsigned int vino_queue_get_length(struct vino_framebuffer_queue *q)
1372{
1373 unsigned int length = 0;
1374 unsigned long flags;
1375
1376 if (q->magic != VINO_QUEUE_MAGIC) {
1377 return length;
1378 }
1379
1380 spin_lock_irqsave(&q->queue_lock, flags);
1381 length = q->length;
1382 spin_unlock_irqrestore(&q->queue_lock, flags);
1383
1384 return length;
1385}
1386
1387static int vino_queue_has_mapped_buffers(struct vino_framebuffer_queue *q)
1388{
1389 unsigned int i;
1390 int ret = 0;
1391 unsigned long flags;
1392
1393 if (q->magic != VINO_QUEUE_MAGIC) {
1394 return ret;
1395 }
1396
1397 spin_lock_irqsave(&q->queue_lock, flags);
1398 for (i = 0; i < q->length; i++) {
1399 if (q->buffer[i]->map_count > 0) {
1400 ret = 1;
1401 break;
1402 }
1403 }
1404 spin_unlock_irqrestore(&q->queue_lock, flags);
1405
1406 return ret;
1407}
1408
1409/* VINO functions */
1410
1411/* execute with input_lock locked */
1412static void vino_update_line_size(struct vino_channel_settings *vcs)
1413{
1414 unsigned int w = vcs->clipping.right - vcs->clipping.left;
1415 unsigned int d = vcs->decimation;
1416 unsigned int bpp = vino_data_formats[vcs->data_format].bpp;
1417 unsigned int lsize;
1418
1419 dprintk("update_line_size(): before: w = %d, d = %d, "
1420 "line_size = %d\n", w, d, vcs->line_size);
1421
1422 /* line size must be multiple of 8 bytes */
1423 lsize = (bpp * (w / d)) & ~7;
1424 w = (lsize / bpp) * d;
1425
1426 vcs->clipping.right = vcs->clipping.left + w;
1427 vcs->line_size = lsize;
1428
1429 dprintk("update_line_size(): after: w = %d, d = %d, "
1430 "line_size = %d\n", w, d, vcs->line_size);
1431}
1432
1433/* execute with input_lock locked */
1434static void vino_set_clipping(struct vino_channel_settings *vcs,
1435 unsigned int x, unsigned int y,
1436 unsigned int w, unsigned int h)
1437{
1438 unsigned int maxwidth, maxheight;
1439 unsigned int d;
1440
1441 maxwidth = vino_data_norms[vcs->data_norm].width;
1442 maxheight = vino_data_norms[vcs->data_norm].height;
1443 d = vcs->decimation;
1444
1445 y &= ~1; /* odd/even fields */
1446
1447 if (x > maxwidth) {
1448 x = 0;
1449 }
1450 if (y > maxheight) {
1451 y = 0;
1452 }
1453
1454 if (((w / d) < VINO_MIN_WIDTH)
1455 || ((h / d) < VINO_MIN_HEIGHT)) {
1456 w = VINO_MIN_WIDTH * d;
1457 h = VINO_MIN_HEIGHT * d;
1458 }
1459
1460 if ((x + w) > maxwidth) {
1461 w = maxwidth - x;
1462 if ((w / d) < VINO_MIN_WIDTH)
1463 x = maxwidth - VINO_MIN_WIDTH * d;
1464 }
1465 if ((y + h) > maxheight) {
1466 h = maxheight - y;
1467 if ((h / d) < VINO_MIN_HEIGHT)
1468 y = maxheight - VINO_MIN_HEIGHT * d;
1469 }
1470
1471 vcs->clipping.left = x;
1472 vcs->clipping.top = y;
1473 vcs->clipping.right = x + w;
1474 vcs->clipping.bottom = y + h;
1475
1476 vino_update_line_size(vcs);
1477
1478 dprintk("clipping %d, %d, %d, %d / %d - %d\n",
1479 vcs->clipping.left, vcs->clipping.top, vcs->clipping.right,
1480 vcs->clipping.bottom, vcs->decimation, vcs->line_size);
1481}
1482
1483/* execute with input_lock locked */
1484static inline void vino_set_default_clipping(struct vino_channel_settings *vcs)
1485{
1486 vino_set_clipping(vcs, 0, 0, vino_data_norms[vcs->data_norm].width,
1487 vino_data_norms[vcs->data_norm].height);
1488}
1489
1490/* execute with input_lock locked */
1491static void vino_set_scaling(struct vino_channel_settings *vcs,
1492 unsigned int w, unsigned int h)
1493{
1494 unsigned int x, y, curw, curh, d;
1495
1496 x = vcs->clipping.left;
1497 y = vcs->clipping.top;
1498 curw = vcs->clipping.right - vcs->clipping.left;
1499 curh = vcs->clipping.bottom - vcs->clipping.top;
1500
1501 d = max(curw / w, curh / h);
1502
1503 dprintk("scaling w: %d, h: %d, curw: %d, curh: %d, d: %d\n",
1504 w, h, curw, curh, d);
1505
1506 if (d < 1) {
1507 d = 1;
1508 } else if (d > 8) {
1509 d = 8;
1510 }
1511
1512 vcs->decimation = d;
1513 vino_set_clipping(vcs, x, y, w * d, h * d);
1514
1515 dprintk("scaling %d, %d, %d, %d / %d - %d\n", vcs->clipping.left,
1516 vcs->clipping.top, vcs->clipping.right, vcs->clipping.bottom,
1517 vcs->decimation, vcs->line_size);
1518}
1519
1520/* execute with input_lock locked */
1521static inline void vino_set_default_scaling(struct vino_channel_settings *vcs)
1522{
1523 vino_set_scaling(vcs, vcs->clipping.right - vcs->clipping.left,
1524 vcs->clipping.bottom - vcs->clipping.top);
1525}
1526
1527/* execute with input_lock locked */
1528static void vino_set_framerate(struct vino_channel_settings *vcs,
1529 unsigned int fps)
1530{
1531 unsigned int mask;
1532
1533 switch (vcs->data_norm) {
1534 case VINO_DATA_NORM_NTSC:
1535 case VINO_DATA_NORM_D1:
1536 fps = (unsigned int)(fps / 6) * 6; // FIXME: round!
1537
1538 if (fps < vino_data_norms[vcs->data_norm].fps_min)
1539 fps = vino_data_norms[vcs->data_norm].fps_min;
1540 if (fps > vino_data_norms[vcs->data_norm].fps_max)
1541 fps = vino_data_norms[vcs->data_norm].fps_max;
1542
1543 switch (fps) {
1544 case 6:
1545 mask = 0x003;
1546 break;
1547 case 12:
1548 mask = 0x0c3;
1549 break;
1550 case 18:
1551 mask = 0x333;
1552 break;
1553 case 24:
1554 mask = 0x3ff;
1555 break;
1556 case 30:
1557 mask = 0xfff;
1558 break;
1559 default:
1560 mask = VINO_FRAMERT_FULL;
1561 }
1562 vcs->framert_reg = VINO_FRAMERT_RT(mask);
1563 break;
1564 case VINO_DATA_NORM_PAL:
1565 case VINO_DATA_NORM_SECAM:
1566 fps = (unsigned int)(fps / 5) * 5; // FIXME: round!
1567
1568 if (fps < vino_data_norms[vcs->data_norm].fps_min)
1569 fps = vino_data_norms[vcs->data_norm].fps_min;
1570 if (fps > vino_data_norms[vcs->data_norm].fps_max)
1571 fps = vino_data_norms[vcs->data_norm].fps_max;
1572
1573 switch (fps) {
1574 case 5:
1575 mask = 0x003;
1576 break;
1577 case 10:
1578 mask = 0x0c3;
1579 break;
1580 case 15:
1581 mask = 0x333;
1582 break;
1583 case 20:
1584 mask = 0x0ff;
1585 break;
1586 case 25:
1587 mask = 0x3ff;
1588 break;
1589 default:
1590 mask = VINO_FRAMERT_FULL;
1591 }
1592 vcs->framert_reg = VINO_FRAMERT_RT(mask) | VINO_FRAMERT_PAL;
1593 break;
1594 }
1595
1596 vcs->fps = fps;
1597}
1598
1599/* execute with input_lock locked */
1600static inline void vino_set_default_framerate(struct
1601 vino_channel_settings *vcs)
1602{
1603 vino_set_framerate(vcs, vino_data_norms[vcs->data_norm].fps_max);
1604}
1605
1606/* VINO I2C bus functions */
1607
1608struct i2c_algo_sgi_data {
1609 void *data; /* private data for lowlevel routines */
1610 unsigned (*getctrl)(void *data);
1611 void (*setctrl)(void *data, unsigned val);
1612 unsigned (*rdata)(void *data);
1613 void (*wdata)(void *data, unsigned val);
1614
1615 int xfer_timeout;
1616 int ack_timeout;
1617};
1618
1619static int wait_xfer_done(struct i2c_algo_sgi_data *adap)
1620{
1621 int i;
1622
1623 for (i = 0; i < adap->xfer_timeout; i++) {
1624 if ((adap->getctrl(adap->data) & SGI_I2C_XFER_BUSY) == 0)
1625 return 0;
1626 udelay(1);
1627 }
1628
1629 return -ETIMEDOUT;
1630}
1631
1632static int wait_ack(struct i2c_algo_sgi_data *adap)
1633{
1634 int i;
1635
1636 if (wait_xfer_done(adap))
1637 return -ETIMEDOUT;
1638 for (i = 0; i < adap->ack_timeout; i++) {
1639 if ((adap->getctrl(adap->data) & SGI_I2C_NACK) == 0)
1640 return 0;
1641 udelay(1);
1642 }
1643
1644 return -ETIMEDOUT;
1645}
1646
1647static int force_idle(struct i2c_algo_sgi_data *adap)
1648{
1649 int i;
1650
1651 adap->setctrl(adap->data, SGI_I2C_FORCE_IDLE);
1652 for (i = 0; i < adap->xfer_timeout; i++) {
1653 if ((adap->getctrl(adap->data) & SGI_I2C_NOT_IDLE) == 0)
1654 goto out;
1655 udelay(1);
1656 }
1657 return -ETIMEDOUT;
1658out:
1659 if (adap->getctrl(adap->data) & SGI_I2C_BUS_ERR)
1660 return -EIO;
1661 return 0;
1662}
1663
1664static int do_address(struct i2c_algo_sgi_data *adap, unsigned int addr,
1665 int rd)
1666{
1667 if (rd)
1668 adap->setctrl(adap->data, SGI_I2C_NOT_IDLE);
1669 /* Check if bus is idle, eventually force it to do so */
1670 if (adap->getctrl(adap->data) & SGI_I2C_NOT_IDLE)
1671 if (force_idle(adap))
1672 return -EIO;
1673 /* Write out the i2c chip address and specify operation */
1674 adap->setctrl(adap->data,
1675 SGI_I2C_HOLD_BUS | SGI_I2C_WRITE | SGI_I2C_NOT_IDLE);
1676 if (rd)
1677 addr |= 1;
1678 adap->wdata(adap->data, addr);
1679 if (wait_ack(adap))
1680 return -EIO;
1681 return 0;
1682}
1683
1684static int i2c_read(struct i2c_algo_sgi_data *adap, unsigned char *buf,
1685 unsigned int len)
1686{
1687 int i;
1688
1689 adap->setctrl(adap->data,
1690 SGI_I2C_HOLD_BUS | SGI_I2C_READ | SGI_I2C_NOT_IDLE);
1691 for (i = 0; i < len; i++) {
1692 if (wait_xfer_done(adap))
1693 return -EIO;
1694 buf[i] = adap->rdata(adap->data);
1695 }
1696 adap->setctrl(adap->data, SGI_I2C_RELEASE_BUS | SGI_I2C_FORCE_IDLE);
1697
1698 return 0;
1699
1700}
1701
1702static int i2c_write(struct i2c_algo_sgi_data *adap, unsigned char *buf,
1703 unsigned int len)
1704{
1705 int i;
1706
1707 /* We are already in write state */
1708 for (i = 0; i < len; i++) {
1709 adap->wdata(adap->data, buf[i]);
1710 if (wait_ack(adap))
1711 return -EIO;
1712 }
1713 return 0;
1714}
1715
1716static int sgi_xfer(struct i2c_adapter *i2c_adap, struct i2c_msg *msgs,
1717 int num)
1718{
1719 struct i2c_algo_sgi_data *adap = i2c_adap->algo_data;
1720 struct i2c_msg *p;
1721 int i, err = 0;
1722
1723 for (i = 0; !err && i < num; i++) {
1724 p = &msgs[i];
1725 err = do_address(adap, p->addr, p->flags & I2C_M_RD);
1726 if (err || !p->len)
1727 continue;
1728 if (p->flags & I2C_M_RD)
1729 err = i2c_read(adap, p->buf, p->len);
1730 else
1731 err = i2c_write(adap, p->buf, p->len);
1732 }
1733
1734 return (err < 0) ? err : i;
1735}
1736
1737static u32 sgi_func(struct i2c_adapter *adap)
1738{
1739 return I2C_FUNC_SMBUS_EMUL;
1740}
1741
1742static const struct i2c_algorithm sgi_algo = {
1743 .master_xfer = sgi_xfer,
1744 .functionality = sgi_func,
1745};
1746
1747static unsigned i2c_vino_getctrl(void *data)
1748{
1749 return vino->i2c_control;
1750}
1751
1752static void i2c_vino_setctrl(void *data, unsigned val)
1753{
1754 vino->i2c_control = val;
1755}
1756
1757static unsigned i2c_vino_rdata(void *data)
1758{
1759 return vino->i2c_data;
1760}
1761
1762static void i2c_vino_wdata(void *data, unsigned val)
1763{
1764 vino->i2c_data = val;
1765}
1766
1767static struct i2c_algo_sgi_data i2c_sgi_vino_data = {
1768 .getctrl = &i2c_vino_getctrl,
1769 .setctrl = &i2c_vino_setctrl,
1770 .rdata = &i2c_vino_rdata,
1771 .wdata = &i2c_vino_wdata,
1772 .xfer_timeout = 200,
1773 .ack_timeout = 1000,
1774};
1775
1776static struct i2c_adapter vino_i2c_adapter = {
1777 .name = "VINO I2C bus",
1778 .algo = &sgi_algo,
1779 .algo_data = &i2c_sgi_vino_data,
1780 .owner = THIS_MODULE,
1781};
1782
1783/*
1784 * Prepare VINO for DMA transfer...
1785 * (execute only with vino_lock and input_lock locked)
1786 */
1787static int vino_dma_setup(struct vino_channel_settings *vcs,
1788 struct vino_framebuffer *fb)
1789{
1790 u32 ctrl, intr;
1791 struct sgi_vino_channel *ch;
1792 const struct vino_data_norm *norm;
1793
1794 dprintk("vino_dma_setup():\n");
1795
1796 vcs->field = 0;
1797 fb->frame_counter = 0;
1798
1799 ch = (vcs->channel == VINO_CHANNEL_A) ? &vino->a : &vino->b;
1800 norm = &vino_data_norms[vcs->data_norm];
1801
1802 ch->page_index = 0;
1803 ch->line_count = 0;
1804
1805 /* VINO line size register is set 8 bytes less than actual */
1806 ch->line_size = vcs->line_size - 8;
1807
1808 /* let VINO know where to transfer data */
1809 ch->start_desc_tbl = fb->desc_table.dma;
1810 ch->next_4_desc = fb->desc_table.dma;
1811
1812 /* give vino time to fetch the first four descriptors, 5 usec
1813 * should be more than enough time */
1814 udelay(VINO_DESC_FETCH_DELAY);
1815
1816 dprintk("vino_dma_setup(): start desc = %08x, next 4 desc = %08x\n",
1817 ch->start_desc_tbl, ch->next_4_desc);
1818
1819 /* set the alpha register */
1820 ch->alpha = vcs->alpha;
1821
1822 /* set clipping registers */
1823 ch->clip_start = VINO_CLIP_ODD(norm->odd.top + vcs->clipping.top / 2) |
1824 VINO_CLIP_EVEN(norm->even.top +
1825 vcs->clipping.top / 2) |
1826 VINO_CLIP_X(vcs->clipping.left);
1827 ch->clip_end = VINO_CLIP_ODD(norm->odd.top +
1828 vcs->clipping.bottom / 2 - 1) |
1829 VINO_CLIP_EVEN(norm->even.top +
1830 vcs->clipping.bottom / 2 - 1) |
1831 VINO_CLIP_X(vcs->clipping.right);
1832
1833 /* set the size of actual content in the buffer (DECIMATION !) */
1834 fb->data_size = ((vcs->clipping.right - vcs->clipping.left) /
1835 vcs->decimation) *
1836 ((vcs->clipping.bottom - vcs->clipping.top) /
1837 vcs->decimation) *
1838 vino_data_formats[vcs->data_format].bpp;
1839
1840 ch->frame_rate = vcs->framert_reg;
1841
1842 ctrl = vino->control;
1843 intr = vino->intr_status;
1844
1845 if (vcs->channel == VINO_CHANNEL_A) {
1846 /* All interrupt conditions for this channel was cleared
1847 * so clear the interrupt status register and enable
1848 * interrupts */
1849 intr &= ~VINO_INTSTAT_A;
1850 ctrl |= VINO_CTRL_A_INT;
1851
1852 /* enable synchronization */
1853 ctrl |= VINO_CTRL_A_SYNC_ENBL;
1854
1855 /* enable frame assembly */
1856 ctrl |= VINO_CTRL_A_INTERLEAVE_ENBL;
1857
1858 /* set decimation used */
1859 if (vcs->decimation < 2)
1860 ctrl &= ~VINO_CTRL_A_DEC_ENBL;
1861 else {
1862 ctrl |= VINO_CTRL_A_DEC_ENBL;
1863 ctrl &= ~VINO_CTRL_A_DEC_SCALE_MASK;
1864 ctrl |= (vcs->decimation - 1) <<
1865 VINO_CTRL_A_DEC_SCALE_SHIFT;
1866 }
1867
1868 /* select input interface */
1869 if (vcs->input == VINO_INPUT_D1)
1870 ctrl |= VINO_CTRL_A_SELECT;
1871 else
1872 ctrl &= ~VINO_CTRL_A_SELECT;
1873
1874 /* palette */
1875 ctrl &= ~(VINO_CTRL_A_LUMA_ONLY | VINO_CTRL_A_RGB |
1876 VINO_CTRL_A_DITHER);
1877 } else {
1878 intr &= ~VINO_INTSTAT_B;
1879 ctrl |= VINO_CTRL_B_INT;
1880
1881 ctrl |= VINO_CTRL_B_SYNC_ENBL;
1882 ctrl |= VINO_CTRL_B_INTERLEAVE_ENBL;
1883
1884 if (vcs->decimation < 2)
1885 ctrl &= ~VINO_CTRL_B_DEC_ENBL;
1886 else {
1887 ctrl |= VINO_CTRL_B_DEC_ENBL;
1888 ctrl &= ~VINO_CTRL_B_DEC_SCALE_MASK;
1889 ctrl |= (vcs->decimation - 1) <<
1890 VINO_CTRL_B_DEC_SCALE_SHIFT;
1891
1892 }
1893 if (vcs->input == VINO_INPUT_D1)
1894 ctrl |= VINO_CTRL_B_SELECT;
1895 else
1896 ctrl &= ~VINO_CTRL_B_SELECT;
1897
1898 ctrl &= ~(VINO_CTRL_B_LUMA_ONLY | VINO_CTRL_B_RGB |
1899 VINO_CTRL_B_DITHER);
1900 }
1901
1902 /* set palette */
1903 fb->data_format = vcs->data_format;
1904
1905 switch (vcs->data_format) {
1906 case VINO_DATA_FMT_GREY:
1907 ctrl |= (vcs->channel == VINO_CHANNEL_A) ?
1908 VINO_CTRL_A_LUMA_ONLY : VINO_CTRL_B_LUMA_ONLY;
1909 break;
1910 case VINO_DATA_FMT_RGB32:
1911 ctrl |= (vcs->channel == VINO_CHANNEL_A) ?
1912 VINO_CTRL_A_RGB : VINO_CTRL_B_RGB;
1913 break;
1914 case VINO_DATA_FMT_YUV:
1915 /* nothing needs to be done */
1916 break;
1917 case VINO_DATA_FMT_RGB332:
1918 ctrl |= (vcs->channel == VINO_CHANNEL_A) ?
1919 VINO_CTRL_A_RGB | VINO_CTRL_A_DITHER :
1920 VINO_CTRL_B_RGB | VINO_CTRL_B_DITHER;
1921 break;
1922 }
1923
1924 vino->intr_status = intr;
1925 vino->control = ctrl;
1926
1927 return 0;
1928}
1929
1930/* (execute only with vino_lock locked) */
1931static inline void vino_dma_start(struct vino_channel_settings *vcs)
1932{
1933 u32 ctrl = vino->control;
1934
1935 dprintk("vino_dma_start():\n");
1936 ctrl |= (vcs->channel == VINO_CHANNEL_A) ?
1937 VINO_CTRL_A_DMA_ENBL : VINO_CTRL_B_DMA_ENBL;
1938 vino->control = ctrl;
1939}
1940
1941/* (execute only with vino_lock locked) */
1942static inline void vino_dma_stop(struct vino_channel_settings *vcs)
1943{
1944 u32 ctrl = vino->control;
1945
1946 ctrl &= (vcs->channel == VINO_CHANNEL_A) ?
1947 ~VINO_CTRL_A_DMA_ENBL : ~VINO_CTRL_B_DMA_ENBL;
1948 ctrl &= (vcs->channel == VINO_CHANNEL_A) ?
1949 ~VINO_CTRL_A_INT : ~VINO_CTRL_B_INT;
1950 vino->control = ctrl;
1951 dprintk("vino_dma_stop():\n");
1952}
1953
1954/*
1955 * Load dummy page to descriptor registers. This prevents generating of
1956 * spurious interrupts. (execute only with vino_lock locked)
1957 */
1958static void vino_clear_interrupt(struct vino_channel_settings *vcs)
1959{
1960 struct sgi_vino_channel *ch;
1961
1962 ch = (vcs->channel == VINO_CHANNEL_A) ? &vino->a : &vino->b;
1963
1964 ch->page_index = 0;
1965 ch->line_count = 0;
1966
1967 ch->start_desc_tbl = vino_drvdata->dummy_desc_table.dma;
1968 ch->next_4_desc = vino_drvdata->dummy_desc_table.dma;
1969
1970 udelay(VINO_DESC_FETCH_DELAY);
1971 dprintk("channel %c clear interrupt condition\n",
1972 (vcs->channel == VINO_CHANNEL_A) ? 'A':'B');
1973}
1974
1975static int vino_capture(struct vino_channel_settings *vcs,
1976 struct vino_framebuffer *fb)
1977{
1978 int err = 0;
1979 unsigned long flags, flags2;
1980
1981 spin_lock_irqsave(&fb->state_lock, flags);
1982
1983 if (fb->state == VINO_FRAMEBUFFER_IN_USE)
1984 err = -EBUSY;
1985 fb->state = VINO_FRAMEBUFFER_IN_USE;
1986
1987 spin_unlock_irqrestore(&fb->state_lock, flags);
1988
1989 if (err)
1990 return err;
1991
1992 spin_lock_irqsave(&vino_drvdata->vino_lock, flags);
1993 spin_lock_irqsave(&vino_drvdata->input_lock, flags2);
1994
1995 vino_dma_setup(vcs, fb);
1996 vino_dma_start(vcs);
1997
1998 spin_unlock_irqrestore(&vino_drvdata->input_lock, flags2);
1999 spin_unlock_irqrestore(&vino_drvdata->vino_lock, flags);
2000
2001 return err;
2002}
2003
2004static
2005struct vino_framebuffer *vino_capture_enqueue(struct
2006 vino_channel_settings *vcs,
2007 unsigned int index)
2008{
2009 struct vino_framebuffer *fb;
2010 unsigned long flags;
2011
2012 dprintk("vino_capture_enqueue():\n");
2013
2014 spin_lock_irqsave(&vcs->capture_lock, flags);
2015
2016 fb = vino_queue_add(&vcs->fb_queue, index);
2017 if (fb == NULL) {
2018 dprintk("vino_capture_enqueue(): vino_queue_add() failed, "
2019 "queue full?\n");
2020 goto out;
2021 }
2022out:
2023 spin_unlock_irqrestore(&vcs->capture_lock, flags);
2024
2025 return fb;
2026}
2027
2028static int vino_capture_next(struct vino_channel_settings *vcs, int start)
2029{
2030 struct vino_framebuffer *fb;
2031 unsigned int incoming, id;
2032 int err = 0;
2033 unsigned long flags;
2034
2035 dprintk("vino_capture_next():\n");
2036
2037 spin_lock_irqsave(&vcs->capture_lock, flags);
2038
2039 if (start) {
2040 /* start capture only if capture isn't in progress already */
2041 if (vcs->capturing) {
2042 spin_unlock_irqrestore(&vcs->capture_lock, flags);
2043 return 0;
2044 }
2045
2046 } else {
2047 /* capture next frame:
2048 * stop capture if capturing is not set */
2049 if (!vcs->capturing) {
2050 spin_unlock_irqrestore(&vcs->capture_lock, flags);
2051 return 0;
2052 }
2053 }
2054
2055 err = vino_queue_get_incoming(&vcs->fb_queue, &incoming);
2056 if (err) {
2057 dprintk("vino_capture_next(): vino_queue_get_incoming() "
2058 "failed\n");
2059 err = -EINVAL;
2060 goto out;
2061 }
2062 if (incoming == 0) {
2063 dprintk("vino_capture_next(): no buffers available\n");
2064 goto out;
2065 }
2066
2067 fb = vino_queue_peek(&vcs->fb_queue, &id);
2068 if (fb == NULL) {
2069 dprintk("vino_capture_next(): vino_queue_peek() failed\n");
2070 err = -EINVAL;
2071 goto out;
2072 }
2073
2074 if (start) {
2075 vcs->capturing = 1;
2076 }
2077
2078 spin_unlock_irqrestore(&vcs->capture_lock, flags);
2079
2080 err = vino_capture(vcs, fb);
2081
2082 return err;
2083
2084out:
2085 vcs->capturing = 0;
2086 spin_unlock_irqrestore(&vcs->capture_lock, flags);
2087
2088 return err;
2089}
2090
2091static inline int vino_is_capturing(struct vino_channel_settings *vcs)
2092{
2093 int ret;
2094 unsigned long flags;
2095
2096 spin_lock_irqsave(&vcs->capture_lock, flags);
2097
2098 ret = vcs->capturing;
2099
2100 spin_unlock_irqrestore(&vcs->capture_lock, flags);
2101
2102 return ret;
2103}
2104
2105/* waits until a frame is captured */
2106static int vino_wait_for_frame(struct vino_channel_settings *vcs)
2107{
2108 wait_queue_t wait;
2109 int err = 0;
2110
2111 dprintk("vino_wait_for_frame():\n");
2112
2113 init_waitqueue_entry(&wait, current);
2114 /* add ourselves into wait queue */
2115 add_wait_queue(&vcs->fb_queue.frame_wait_queue, &wait);
2116
2117 /* to ensure that schedule_timeout will return immediately
2118 * if VINO interrupt was triggered meanwhile */
2119 schedule_timeout_interruptible(msecs_to_jiffies(100));
2120
2121 if (signal_pending(current))
2122 err = -EINTR;
2123
2124 remove_wait_queue(&vcs->fb_queue.frame_wait_queue, &wait);
2125
2126 dprintk("vino_wait_for_frame(): waiting for frame %s\n",
2127 err ? "failed" : "ok");
2128
2129 return err;
2130}
2131
2132/* the function assumes that PAGE_SIZE % 4 == 0 */
2133static void vino_convert_to_rgba(struct vino_framebuffer *fb) {
2134 unsigned char *pageptr;
2135 unsigned int page, i;
2136 unsigned char a;
2137
2138 for (page = 0; page < fb->desc_table.page_count; page++) {
2139 pageptr = (unsigned char *)fb->desc_table.virtual[page];
2140
2141 for (i = 0; i < PAGE_SIZE; i += 4) {
2142 a = pageptr[0];
2143 pageptr[0] = pageptr[3];
2144 pageptr[1] = pageptr[2];
2145 pageptr[2] = pageptr[1];
2146 pageptr[3] = a;
2147 pageptr += 4;
2148 }
2149 }
2150}
2151
2152/* checks if the buffer is in correct state and syncs data */
2153static int vino_check_buffer(struct vino_channel_settings *vcs,
2154 struct vino_framebuffer *fb)
2155{
2156 int err = 0;
2157 unsigned long flags;
2158
2159 dprintk("vino_check_buffer():\n");
2160
2161 spin_lock_irqsave(&fb->state_lock, flags);
2162 switch (fb->state) {
2163 case VINO_FRAMEBUFFER_IN_USE:
2164 err = -EIO;
2165 break;
2166 case VINO_FRAMEBUFFER_READY:
2167 vino_sync_buffer(fb);
2168 fb->state = VINO_FRAMEBUFFER_UNUSED;
2169 break;
2170 default:
2171 err = -EINVAL;
2172 }
2173 spin_unlock_irqrestore(&fb->state_lock, flags);
2174
2175 if (!err) {
2176 if (vino_pixel_conversion
2177 && (fb->data_format == VINO_DATA_FMT_RGB32)) {
2178 vino_convert_to_rgba(fb);
2179 }
2180 } else if (err && (err != -EINVAL)) {
2181 dprintk("vino_check_buffer(): buffer not ready\n");
2182
2183 spin_lock_irqsave(&vino_drvdata->vino_lock, flags);
2184 vino_dma_stop(vcs);
2185 vino_clear_interrupt(vcs);
2186 spin_unlock_irqrestore(&vino_drvdata->vino_lock, flags);
2187 }
2188
2189 return err;
2190}
2191
2192/* forcefully terminates capture */
2193static void vino_capture_stop(struct vino_channel_settings *vcs)
2194{
2195 unsigned int incoming = 0, outgoing = 0, id;
2196 unsigned long flags, flags2;
2197
2198 dprintk("vino_capture_stop():\n");
2199
2200 spin_lock_irqsave(&vcs->capture_lock, flags);
2201
2202 /* unset capturing to stop queue processing */
2203 vcs->capturing = 0;
2204
2205 spin_lock_irqsave(&vino_drvdata->vino_lock, flags2);
2206
2207 vino_dma_stop(vcs);
2208 vino_clear_interrupt(vcs);
2209
2210 spin_unlock_irqrestore(&vino_drvdata->vino_lock, flags2);
2211
2212 /* remove all items from the queue */
2213 if (vino_queue_get_incoming(&vcs->fb_queue, &incoming)) {
2214 dprintk("vino_capture_stop(): "
2215 "vino_queue_get_incoming() failed\n");
2216 goto out;
2217 }
2218 while (incoming > 0) {
2219 vino_queue_transfer(&vcs->fb_queue);
2220
2221 if (vino_queue_get_incoming(&vcs->fb_queue, &incoming)) {
2222 dprintk("vino_capture_stop(): "
2223 "vino_queue_get_incoming() failed\n");
2224 goto out;
2225 }
2226 }
2227
2228 if (vino_queue_get_outgoing(&vcs->fb_queue, &outgoing)) {
2229 dprintk("vino_capture_stop(): "
2230 "vino_queue_get_outgoing() failed\n");
2231 goto out;
2232 }
2233 while (outgoing > 0) {
2234 vino_queue_remove(&vcs->fb_queue, &id);
2235
2236 if (vino_queue_get_outgoing(&vcs->fb_queue, &outgoing)) {
2237 dprintk("vino_capture_stop(): "
2238 "vino_queue_get_outgoing() failed\n");
2239 goto out;
2240 }
2241 }
2242
2243out:
2244 spin_unlock_irqrestore(&vcs->capture_lock, flags);
2245}
2246
2247#if 0
2248static int vino_capture_failed(struct vino_channel_settings *vcs)
2249{
2250 struct vino_framebuffer *fb;
2251 unsigned long flags;
2252 unsigned int i;
2253 int ret;
2254
2255 dprintk("vino_capture_failed():\n");
2256
2257 spin_lock_irqsave(&vino_drvdata->vino_lock, flags);
2258
2259 vino_dma_stop(vcs);
2260 vino_clear_interrupt(vcs);
2261
2262 spin_unlock_irqrestore(&vino_drvdata->vino_lock, flags);
2263
2264 ret = vino_queue_get_incoming(&vcs->fb_queue, &i);
2265 if (ret == VINO_QUEUE_ERROR) {
2266 dprintk("vino_queue_get_incoming() failed\n");
2267 return -EINVAL;
2268 }
2269 if (i == 0) {
2270 /* no buffers to process */
2271 return 0;
2272 }
2273
2274 fb = vino_queue_peek(&vcs->fb_queue, &i);
2275 if (fb == NULL) {
2276 dprintk("vino_queue_peek() failed\n");
2277 return -EINVAL;
2278 }
2279
2280 spin_lock_irqsave(&fb->state_lock, flags);
2281 if (fb->state == VINO_FRAMEBUFFER_IN_USE) {
2282 fb->state = VINO_FRAMEBUFFER_UNUSED;
2283 vino_queue_transfer(&vcs->fb_queue);
2284 vino_queue_remove(&vcs->fb_queue, &i);
2285 /* we should actually discard the newest frame,
2286 * but who cares ... */
2287 }
2288 spin_unlock_irqrestore(&fb->state_lock, flags);
2289
2290 return 0;
2291}
2292#endif
2293
2294static void vino_skip_frame(struct vino_channel_settings *vcs)
2295{
2296 struct vino_framebuffer *fb;
2297 unsigned long flags;
2298 unsigned int id;
2299
2300 spin_lock_irqsave(&vcs->capture_lock, flags);
2301 fb = vino_queue_peek(&vcs->fb_queue, &id);
2302 if (!fb) {
2303 spin_unlock_irqrestore(&vcs->capture_lock, flags);
2304 dprintk("vino_skip_frame(): vino_queue_peek() failed!\n");
2305 return;
2306 }
2307 spin_unlock_irqrestore(&vcs->capture_lock, flags);
2308
2309 spin_lock_irqsave(&fb->state_lock, flags);
2310 fb->state = VINO_FRAMEBUFFER_UNUSED;
2311 spin_unlock_irqrestore(&fb->state_lock, flags);
2312
2313 vino_capture_next(vcs, 0);
2314}
2315
2316static void vino_frame_done(struct vino_channel_settings *vcs)
2317{
2318 struct vino_framebuffer *fb;
2319 unsigned long flags;
2320
2321 spin_lock_irqsave(&vcs->capture_lock, flags);
2322 fb = vino_queue_transfer(&vcs->fb_queue);
2323 if (!fb) {
2324 spin_unlock_irqrestore(&vcs->capture_lock, flags);
2325 dprintk("vino_frame_done(): vino_queue_transfer() failed!\n");
2326 return;
2327 }
2328 spin_unlock_irqrestore(&vcs->capture_lock, flags);
2329
2330 fb->frame_counter = vcs->int_data.frame_counter;
2331 memcpy(&fb->timestamp, &vcs->int_data.timestamp,
2332 sizeof(struct timeval));
2333
2334 spin_lock_irqsave(&fb->state_lock, flags);
2335 if (fb->state == VINO_FRAMEBUFFER_IN_USE)
2336 fb->state = VINO_FRAMEBUFFER_READY;
2337 spin_unlock_irqrestore(&fb->state_lock, flags);
2338
2339 wake_up(&vcs->fb_queue.frame_wait_queue);
2340
2341 vino_capture_next(vcs, 0);
2342}
2343
2344static void vino_capture_tasklet(unsigned long channel) {
2345 struct vino_channel_settings *vcs;
2346
2347 vcs = (channel == VINO_CHANNEL_A)
2348 ? &vino_drvdata->a : &vino_drvdata->b;
2349
2350 if (vcs->int_data.skip)
2351 vcs->int_data.skip_count++;
2352
2353 if (vcs->int_data.skip && (vcs->int_data.skip_count
2354 <= VINO_MAX_FRAME_SKIP_COUNT)) {
2355 vino_skip_frame(vcs);
2356 } else {
2357 vcs->int_data.skip_count = 0;
2358 vino_frame_done(vcs);
2359 }
2360}
2361
2362static irqreturn_t vino_interrupt(int irq, void *dev_id)
2363{
2364 u32 ctrl, intr;
2365 unsigned int fc_a, fc_b;
2366 int handled_a = 0, skip_a = 0, done_a = 0;
2367 int handled_b = 0, skip_b = 0, done_b = 0;
2368
2369#ifdef VINO_DEBUG_INT
2370 int loop = 0;
2371 unsigned int line_count = vino->a.line_count,
2372 page_index = vino->a.page_index,
2373 field_counter = vino->a.field_counter,
2374 start_desc_tbl = vino->a.start_desc_tbl,
2375 next_4_desc = vino->a.next_4_desc;
2376 unsigned int line_count_2,
2377 page_index_2,
2378 field_counter_2,
2379 start_desc_tbl_2,
2380 next_4_desc_2;
2381#endif
2382
2383 spin_lock(&vino_drvdata->vino_lock);
2384
2385 while ((intr = vino->intr_status)) {
2386 fc_a = vino->a.field_counter >> 1;
2387 fc_b = vino->b.field_counter >> 1;
2388
2389 /* handle error-interrupts in some special way ?
2390 * --> skips frames */
2391 if (intr & VINO_INTSTAT_A) {
2392 if (intr & VINO_INTSTAT_A_EOF) {
2393 vino_drvdata->a.field++;
2394 if (vino_drvdata->a.field > 1) {
2395 vino_dma_stop(&vino_drvdata->a);
2396 vino_clear_interrupt(&vino_drvdata->a);
2397 vino_drvdata->a.field = 0;
2398 done_a = 1;
2399 } else {
2400 if (vino->a.page_index
2401 != vino_drvdata->a.line_size) {
2402 vino->a.line_count = 0;
2403 vino->a.page_index =
2404 vino_drvdata->
2405 a.line_size;
2406 vino->a.next_4_desc =
2407 vino->a.start_desc_tbl;
2408 }
2409 }
2410 dprintk("channel A end-of-field "
2411 "interrupt: %04x\n", intr);
2412 } else {
2413 vino_dma_stop(&vino_drvdata->a);
2414 vino_clear_interrupt(&vino_drvdata->a);
2415 vino_drvdata->a.field = 0;
2416 skip_a = 1;
2417 dprintk("channel A error interrupt: %04x\n",
2418 intr);
2419 }
2420
2421#ifdef VINO_DEBUG_INT
2422 line_count_2 = vino->a.line_count;
2423 page_index_2 = vino->a.page_index;
2424 field_counter_2 = vino->a.field_counter;
2425 start_desc_tbl_2 = vino->a.start_desc_tbl;
2426 next_4_desc_2 = vino->a.next_4_desc;
2427
2428 printk("intr = %04x, loop = %d, field = %d\n",
2429 intr, loop, vino_drvdata->a.field);
2430 printk("1- line count = %04d, page index = %04d, "
2431 "start = %08x, next = %08x\n"
2432 " fieldc = %d, framec = %d\n",
2433 line_count, page_index, start_desc_tbl,
2434 next_4_desc, field_counter, fc_a);
2435 printk("12-line count = %04d, page index = %04d, "
2436 " start = %08x, next = %08x\n",
2437 line_count_2, page_index_2, start_desc_tbl_2,
2438 next_4_desc_2);
2439
2440 if (done_a)
2441 printk("\n");
2442#endif
2443 }
2444
2445 if (intr & VINO_INTSTAT_B) {
2446 if (intr & VINO_INTSTAT_B_EOF) {
2447 vino_drvdata->b.field++;
2448 if (vino_drvdata->b.field > 1) {
2449 vino_dma_stop(&vino_drvdata->b);
2450 vino_clear_interrupt(&vino_drvdata->b);
2451 vino_drvdata->b.field = 0;
2452 done_b = 1;
2453 }
2454 dprintk("channel B end-of-field "
2455 "interrupt: %04x\n", intr);
2456 } else {
2457 vino_dma_stop(&vino_drvdata->b);
2458 vino_clear_interrupt(&vino_drvdata->b);
2459 vino_drvdata->b.field = 0;
2460 skip_b = 1;
2461 dprintk("channel B error interrupt: %04x\n",
2462 intr);
2463 }
2464 }
2465
2466 /* Always remember to clear interrupt status.
2467 * Disable VINO interrupts while we do this. */
2468 ctrl = vino->control;
2469 vino->control = ctrl & ~(VINO_CTRL_A_INT | VINO_CTRL_B_INT);
2470 vino->intr_status = ~intr;
2471 vino->control = ctrl;
2472
2473 spin_unlock(&vino_drvdata->vino_lock);
2474
2475 if ((!handled_a) && (done_a || skip_a)) {
2476 if (!skip_a) {
2477 v4l2_get_timestamp(
2478 &vino_drvdata->a.int_data.timestamp);
2479 vino_drvdata->a.int_data.frame_counter = fc_a;
2480 }
2481 vino_drvdata->a.int_data.skip = skip_a;
2482
2483 dprintk("channel A %s, interrupt: %d\n",
2484 skip_a ? "skipping frame" : "frame done",
2485 intr);
2486 tasklet_hi_schedule(&vino_tasklet_a);
2487 handled_a = 1;
2488 }
2489
2490 if ((!handled_b) && (done_b || skip_b)) {
2491 if (!skip_b) {
2492 v4l2_get_timestamp(
2493 &vino_drvdata->b.int_data.timestamp);
2494 vino_drvdata->b.int_data.frame_counter = fc_b;
2495 }
2496 vino_drvdata->b.int_data.skip = skip_b;
2497
2498 dprintk("channel B %s, interrupt: %d\n",
2499 skip_b ? "skipping frame" : "frame done",
2500 intr);
2501 tasklet_hi_schedule(&vino_tasklet_b);
2502 handled_b = 1;
2503 }
2504
2505#ifdef VINO_DEBUG_INT
2506 loop++;
2507#endif
2508 spin_lock(&vino_drvdata->vino_lock);
2509 }
2510
2511 spin_unlock(&vino_drvdata->vino_lock);
2512
2513 return IRQ_HANDLED;
2514}
2515
2516/* VINO video input management */
2517
2518static int vino_get_saa7191_input(int input)
2519{
2520 switch (input) {
2521 case VINO_INPUT_COMPOSITE:
2522 return SAA7191_INPUT_COMPOSITE;
2523 case VINO_INPUT_SVIDEO:
2524 return SAA7191_INPUT_SVIDEO;
2525 default:
2526 printk(KERN_ERR "VINO: vino_get_saa7191_input(): "
2527 "invalid input!\n");
2528 return -1;
2529 }
2530}
2531
2532/* execute with input_lock locked */
2533static int vino_is_input_owner(struct vino_channel_settings *vcs)
2534{
2535 switch(vcs->input) {
2536 case VINO_INPUT_COMPOSITE:
2537 case VINO_INPUT_SVIDEO:
2538 return vino_drvdata->decoder_owner == vcs->channel;
2539 case VINO_INPUT_D1:
2540 return vino_drvdata->camera_owner == vcs->channel;
2541 default:
2542 return 0;
2543 }
2544}
2545
2546static int vino_acquire_input(struct vino_channel_settings *vcs)
2547{
2548 unsigned long flags;
2549 int ret = 0;
2550
2551 dprintk("vino_acquire_input():\n");
2552
2553 spin_lock_irqsave(&vino_drvdata->input_lock, flags);
2554
2555 /* First try D1 and then SAA7191 */
2556 if (vino_drvdata->camera
2557 && (vino_drvdata->camera_owner == VINO_NO_CHANNEL)) {
2558 vino_drvdata->camera_owner = vcs->channel;
2559 vcs->input = VINO_INPUT_D1;
2560 vcs->data_norm = VINO_DATA_NORM_D1;
2561 } else if (vino_drvdata->decoder
2562 && (vino_drvdata->decoder_owner == VINO_NO_CHANNEL)) {
2563 int input;
2564 int data_norm = 0;
2565 v4l2_std_id norm;
2566
2567 input = VINO_INPUT_COMPOSITE;
2568
2569 ret = decoder_call(video, s_routing,
2570 vino_get_saa7191_input(input), 0, 0);
2571 if (ret) {
2572 ret = -EINVAL;
2573 goto out;
2574 }
2575
2576 spin_unlock_irqrestore(&vino_drvdata->input_lock, flags);
2577
2578 /* Don't hold spinlocks while auto-detecting norm
2579 * as it may take a while... */
2580
2581 ret = decoder_call(video, querystd, &norm);
2582 if (!ret) {
2583 for (data_norm = 0; data_norm < 3; data_norm++) {
2584 if (vino_data_norms[data_norm].std & norm)
2585 break;
2586 }
2587 if (data_norm == 3)
2588 data_norm = VINO_DATA_NORM_PAL;
2589 ret = decoder_call(video, s_std, norm);
2590 }
2591
2592 spin_lock_irqsave(&vino_drvdata->input_lock, flags);
2593
2594 if (ret) {
2595 ret = -EINVAL;
2596 goto out;
2597 }
2598
2599 vino_drvdata->decoder_owner = vcs->channel;
2600
2601 vcs->input = input;
2602 vcs->data_norm = data_norm;
2603 } else {
2604 vcs->input = (vcs->channel == VINO_CHANNEL_A) ?
2605 vino_drvdata->b.input : vino_drvdata->a.input;
2606 vcs->data_norm = (vcs->channel == VINO_CHANNEL_A) ?
2607 vino_drvdata->b.data_norm : vino_drvdata->a.data_norm;
2608 }
2609
2610 if (vcs->input == VINO_INPUT_NONE) {
2611 ret = -ENODEV;
2612 goto out;
2613 }
2614
2615 vino_set_default_clipping(vcs);
2616 vino_set_default_scaling(vcs);
2617 vino_set_default_framerate(vcs);
2618
2619 dprintk("vino_acquire_input(): %s\n", vino_inputs[vcs->input].name);
2620
2621out:
2622 spin_unlock_irqrestore(&vino_drvdata->input_lock, flags);
2623
2624 return ret;
2625}
2626
2627static int vino_set_input(struct vino_channel_settings *vcs, int input)
2628{
2629 struct vino_channel_settings *vcs2 = (vcs->channel == VINO_CHANNEL_A) ?
2630 &vino_drvdata->b : &vino_drvdata->a;
2631 unsigned long flags;
2632 int ret = 0;
2633
2634 dprintk("vino_set_input():\n");
2635
2636 spin_lock_irqsave(&vino_drvdata->input_lock, flags);
2637
2638 if (vcs->input == input)
2639 goto out;
2640
2641 switch (input) {
2642 case VINO_INPUT_COMPOSITE:
2643 case VINO_INPUT_SVIDEO:
2644 if (!vino_drvdata->decoder) {
2645 ret = -EINVAL;
2646 goto out;
2647 }
2648
2649 if (vino_drvdata->decoder_owner == VINO_NO_CHANNEL) {
2650 vino_drvdata->decoder_owner = vcs->channel;
2651 }
2652
2653 if (vino_drvdata->decoder_owner == vcs->channel) {
2654 int data_norm = 0;
2655 v4l2_std_id norm;
2656
2657 ret = decoder_call(video, s_routing,
2658 vino_get_saa7191_input(input), 0, 0);
2659 if (ret) {
2660 vino_drvdata->decoder_owner = VINO_NO_CHANNEL;
2661 ret = -EINVAL;
2662 goto out;
2663 }
2664
2665 spin_unlock_irqrestore(&vino_drvdata->input_lock, flags);
2666
2667 /* Don't hold spinlocks while auto-detecting norm
2668 * as it may take a while... */
2669
2670 ret = decoder_call(video, querystd, &norm);
2671 if (!ret) {
2672 for (data_norm = 0; data_norm < 3; data_norm++) {
2673 if (vino_data_norms[data_norm].std & norm)
2674 break;
2675 }
2676 if (data_norm == 3)
2677 data_norm = VINO_DATA_NORM_PAL;
2678 ret = decoder_call(video, s_std, norm);
2679 }
2680
2681 spin_lock_irqsave(&vino_drvdata->input_lock, flags);
2682
2683 if (ret) {
2684 vino_drvdata->decoder_owner = VINO_NO_CHANNEL;
2685 ret = -EINVAL;
2686 goto out;
2687 }
2688
2689 vcs->input = input;
2690 vcs->data_norm = data_norm;
2691 } else {
2692 if (input != vcs2->input) {
2693 ret = -EBUSY;
2694 goto out;
2695 }
2696
2697 vcs->input = input;
2698 vcs->data_norm = vcs2->data_norm;
2699 }
2700
2701 if (vino_drvdata->camera_owner == vcs->channel) {
2702 /* Transfer the ownership or release the input */
2703 if (vcs2->input == VINO_INPUT_D1) {
2704 vino_drvdata->camera_owner = vcs2->channel;
2705 } else {
2706 vino_drvdata->camera_owner = VINO_NO_CHANNEL;
2707 }
2708 }
2709 break;
2710 case VINO_INPUT_D1:
2711 if (!vino_drvdata->camera) {
2712 ret = -EINVAL;
2713 goto out;
2714 }
2715
2716 if (vino_drvdata->camera_owner == VINO_NO_CHANNEL)
2717 vino_drvdata->camera_owner = vcs->channel;
2718
2719 if (vino_drvdata->decoder_owner == vcs->channel) {
2720 /* Transfer the ownership or release the input */
2721 if ((vcs2->input == VINO_INPUT_COMPOSITE) ||
2722 (vcs2->input == VINO_INPUT_SVIDEO)) {
2723 vino_drvdata->decoder_owner = vcs2->channel;
2724 } else {
2725 vino_drvdata->decoder_owner = VINO_NO_CHANNEL;
2726 }
2727 }
2728
2729 vcs->input = input;
2730 vcs->data_norm = VINO_DATA_NORM_D1;
2731 break;
2732 default:
2733 ret = -EINVAL;
2734 goto out;
2735 }
2736
2737 vino_set_default_clipping(vcs);
2738 vino_set_default_scaling(vcs);
2739 vino_set_default_framerate(vcs);
2740
2741 dprintk("vino_set_input(): %s\n", vino_inputs[vcs->input].name);
2742
2743out:
2744 spin_unlock_irqrestore(&vino_drvdata->input_lock, flags);
2745
2746 return ret;
2747}
2748
2749static void vino_release_input(struct vino_channel_settings *vcs)
2750{
2751 struct vino_channel_settings *vcs2 = (vcs->channel == VINO_CHANNEL_A) ?
2752 &vino_drvdata->b : &vino_drvdata->a;
2753 unsigned long flags;
2754
2755 dprintk("vino_release_input():\n");
2756
2757 spin_lock_irqsave(&vino_drvdata->input_lock, flags);
2758
2759 /* Release ownership of the channel
2760 * and if the other channel takes input from
2761 * the same source, transfer the ownership */
2762 if (vino_drvdata->camera_owner == vcs->channel) {
2763 if (vcs2->input == VINO_INPUT_D1) {
2764 vino_drvdata->camera_owner = vcs2->channel;
2765 } else {
2766 vino_drvdata->camera_owner = VINO_NO_CHANNEL;
2767 }
2768 } else if (vino_drvdata->decoder_owner == vcs->channel) {
2769 if ((vcs2->input == VINO_INPUT_COMPOSITE) ||
2770 (vcs2->input == VINO_INPUT_SVIDEO)) {
2771 vino_drvdata->decoder_owner = vcs2->channel;
2772 } else {
2773 vino_drvdata->decoder_owner = VINO_NO_CHANNEL;
2774 }
2775 }
2776 vcs->input = VINO_INPUT_NONE;
2777
2778 spin_unlock_irqrestore(&vino_drvdata->input_lock, flags);
2779}
2780
2781/* execute with input_lock locked */
2782static int vino_set_data_norm(struct vino_channel_settings *vcs,
2783 unsigned int data_norm,
2784 unsigned long *flags)
2785{
2786 int err = 0;
2787
2788 if (data_norm == vcs->data_norm)
2789 return 0;
2790
2791 switch (vcs->input) {
2792 case VINO_INPUT_D1:
2793 /* only one "norm" supported */
2794 if (data_norm != VINO_DATA_NORM_D1)
2795 return -EINVAL;
2796 break;
2797 case VINO_INPUT_COMPOSITE:
2798 case VINO_INPUT_SVIDEO: {
2799 v4l2_std_id norm;
2800
2801 if ((data_norm != VINO_DATA_NORM_PAL)
2802 && (data_norm != VINO_DATA_NORM_NTSC)
2803 && (data_norm != VINO_DATA_NORM_SECAM))
2804 return -EINVAL;
2805
2806 spin_unlock_irqrestore(&vino_drvdata->input_lock, *flags);
2807
2808 /* Don't hold spinlocks while setting norm
2809 * as it may take a while... */
2810
2811 norm = vino_data_norms[data_norm].std;
2812 err = decoder_call(video, s_std, norm);
2813
2814 spin_lock_irqsave(&vino_drvdata->input_lock, *flags);
2815
2816 if (err)
2817 goto out;
2818
2819 vcs->data_norm = data_norm;
2820
2821 vino_set_default_clipping(vcs);
2822 vino_set_default_scaling(vcs);
2823 vino_set_default_framerate(vcs);
2824 break;
2825 }
2826 default:
2827 return -EINVAL;
2828 }
2829
2830out:
2831 return err;
2832}
2833
2834/* V4L2 helper functions */
2835
2836static int vino_find_data_format(__u32 pixelformat)
2837{
2838 int i;
2839
2840 for (i = 0; i < VINO_DATA_FMT_COUNT; i++) {
2841 if (vino_data_formats[i].pixelformat == pixelformat)
2842 return i;
2843 }
2844
2845 return VINO_DATA_FMT_NONE;
2846}
2847
2848static int vino_int_enum_input(struct vino_channel_settings *vcs, __u32 index)
2849{
2850 int input = VINO_INPUT_NONE;
2851 unsigned long flags;
2852
2853 spin_lock_irqsave(&vino_drvdata->input_lock, flags);
2854 if (vino_drvdata->decoder && vino_drvdata->camera) {
2855 switch (index) {
2856 case 0:
2857 input = VINO_INPUT_COMPOSITE;
2858 break;
2859 case 1:
2860 input = VINO_INPUT_SVIDEO;
2861 break;
2862 case 2:
2863 input = VINO_INPUT_D1;
2864 break;
2865 }
2866 } else if (vino_drvdata->decoder) {
2867 switch (index) {
2868 case 0:
2869 input = VINO_INPUT_COMPOSITE;
2870 break;
2871 case 1:
2872 input = VINO_INPUT_SVIDEO;
2873 break;
2874 }
2875 } else if (vino_drvdata->camera) {
2876 switch (index) {
2877 case 0:
2878 input = VINO_INPUT_D1;
2879 break;
2880 }
2881 }
2882 spin_unlock_irqrestore(&vino_drvdata->input_lock, flags);
2883
2884 return input;
2885}
2886
2887/* execute with input_lock locked */
2888static __u32 vino_find_input_index(struct vino_channel_settings *vcs)
2889{
2890 __u32 index = 0;
2891 // FIXME: detect when no inputs available
2892
2893 if (vino_drvdata->decoder && vino_drvdata->camera) {
2894 switch (vcs->input) {
2895 case VINO_INPUT_COMPOSITE:
2896 index = 0;
2897 break;
2898 case VINO_INPUT_SVIDEO:
2899 index = 1;
2900 break;
2901 case VINO_INPUT_D1:
2902 index = 2;
2903 break;
2904 }
2905 } else if (vino_drvdata->decoder) {
2906 switch (vcs->input) {
2907 case VINO_INPUT_COMPOSITE:
2908 index = 0;
2909 break;
2910 case VINO_INPUT_SVIDEO:
2911 index = 1;
2912 break;
2913 }
2914 } else if (vino_drvdata->camera) {
2915 switch (vcs->input) {
2916 case VINO_INPUT_D1:
2917 index = 0;
2918 break;
2919 }
2920 }
2921
2922 return index;
2923}
2924
2925/* V4L2 ioctls */
2926
2927static int vino_querycap(struct file *file, void *__fh,
2928 struct v4l2_capability *cap)
2929{
2930 memset(cap, 0, sizeof(struct v4l2_capability));
2931
2932 strcpy(cap->driver, vino_driver_name);
2933 strcpy(cap->card, vino_driver_description);
2934 strcpy(cap->bus_info, vino_bus_name);
2935 cap->device_caps = V4L2_CAP_VIDEO_CAPTURE | V4L2_CAP_STREAMING;
2936 cap->capabilities = cap->device_caps | V4L2_CAP_DEVICE_CAPS;
2937 return 0;
2938}
2939
2940static int vino_enum_input(struct file *file, void *__fh,
2941 struct v4l2_input *i)
2942{
2943 struct vino_channel_settings *vcs = video_drvdata(file);
2944 __u32 index = i->index;
2945 int input;
2946 dprintk("requested index = %d\n", index);
2947
2948 input = vino_int_enum_input(vcs, index);
2949 if (input == VINO_INPUT_NONE)
2950 return -EINVAL;
2951
2952 i->type = V4L2_INPUT_TYPE_CAMERA;
2953 i->std = vino_inputs[input].std;
2954 strcpy(i->name, vino_inputs[input].name);
2955
2956 if (input == VINO_INPUT_COMPOSITE || input == VINO_INPUT_SVIDEO)
2957 decoder_call(video, g_input_status, &i->status);
2958 return 0;
2959}
2960
2961static int vino_g_input(struct file *file, void *__fh,
2962 unsigned int *i)
2963{
2964 struct vino_channel_settings *vcs = video_drvdata(file);
2965 __u32 index;
2966 int input;
2967 unsigned long flags;
2968
2969 spin_lock_irqsave(&vino_drvdata->input_lock, flags);
2970 input = vcs->input;
2971 index = vino_find_input_index(vcs);
2972 spin_unlock_irqrestore(&vino_drvdata->input_lock, flags);
2973
2974 dprintk("input = %d\n", input);
2975
2976 if (input == VINO_INPUT_NONE) {
2977 return -EINVAL;
2978 }
2979
2980 *i = index;
2981
2982 return 0;
2983}
2984
2985static int vino_s_input(struct file *file, void *__fh,
2986 unsigned int i)
2987{
2988 struct vino_channel_settings *vcs = video_drvdata(file);
2989 int input;
2990 dprintk("requested input = %d\n", i);
2991
2992 input = vino_int_enum_input(vcs, i);
2993 if (input == VINO_INPUT_NONE)
2994 return -EINVAL;
2995
2996 return vino_set_input(vcs, input);
2997}
2998
2999static int vino_querystd(struct file *file, void *__fh,
3000 v4l2_std_id *std)
3001{
3002 struct vino_channel_settings *vcs = video_drvdata(file);
3003 unsigned long flags;
3004 int err = 0;
3005
3006 spin_lock_irqsave(&vino_drvdata->input_lock, flags);
3007
3008 switch (vcs->input) {
3009 case VINO_INPUT_D1:
3010 *std = vino_inputs[vcs->input].std;
3011 break;
3012 case VINO_INPUT_COMPOSITE:
3013 case VINO_INPUT_SVIDEO: {
3014 decoder_call(video, querystd, std);
3015 break;
3016 }
3017 default:
3018 err = -EINVAL;
3019 }
3020
3021 spin_unlock_irqrestore(&vino_drvdata->input_lock, flags);
3022
3023 return err;
3024}
3025
3026static int vino_g_std(struct file *file, void *__fh,
3027 v4l2_std_id *std)
3028{
3029 struct vino_channel_settings *vcs = video_drvdata(file);
3030 unsigned long flags;
3031
3032 spin_lock_irqsave(&vino_drvdata->input_lock, flags);
3033
3034 *std = vino_data_norms[vcs->data_norm].std;
3035 dprintk("current standard = %d\n", vcs->data_norm);
3036
3037 spin_unlock_irqrestore(&vino_drvdata->input_lock, flags);
3038
3039 return 0;
3040}
3041
3042static int vino_s_std(struct file *file, void *__fh,
3043 v4l2_std_id std)
3044{
3045 struct vino_channel_settings *vcs = video_drvdata(file);
3046 unsigned long flags;
3047 int ret = 0;
3048
3049 spin_lock_irqsave(&vino_drvdata->input_lock, flags);
3050
3051 if (!vino_is_input_owner(vcs)) {
3052 ret = -EBUSY;
3053 goto out;
3054 }
3055
3056 /* check if the standard is valid for the current input */
3057 if (std & vino_inputs[vcs->input].std) {
3058 dprintk("standard accepted\n");
3059
3060 /* change the video norm for SAA7191
3061 * and accept NTSC for D1 (do nothing) */
3062
3063 if (vcs->input == VINO_INPUT_D1)
3064 goto out;
3065
3066 if (std & V4L2_STD_PAL) {
3067 ret = vino_set_data_norm(vcs, VINO_DATA_NORM_PAL,
3068 &flags);
3069 } else if (std & V4L2_STD_NTSC) {
3070 ret = vino_set_data_norm(vcs, VINO_DATA_NORM_NTSC,
3071 &flags);
3072 } else if (std & V4L2_STD_SECAM) {
3073 ret = vino_set_data_norm(vcs, VINO_DATA_NORM_SECAM,
3074 &flags);
3075 } else {
3076 ret = -EINVAL;
3077 }
3078
3079 if (ret) {
3080 ret = -EINVAL;
3081 }
3082 } else {
3083 ret = -EINVAL;
3084 }
3085
3086out:
3087 spin_unlock_irqrestore(&vino_drvdata->input_lock, flags);
3088
3089 return ret;
3090}
3091
3092static int vino_enum_fmt_vid_cap(struct file *file, void *__fh,
3093 struct v4l2_fmtdesc *fd)
3094{
3095 dprintk("format index = %d\n", fd->index);
3096
3097 if (fd->index >= VINO_DATA_FMT_COUNT)
3098 return -EINVAL;
3099 dprintk("format name = %s\n", vino_data_formats[fd->index].description);
3100
3101 fd->pixelformat = vino_data_formats[fd->index].pixelformat;
3102 strcpy(fd->description, vino_data_formats[fd->index].description);
3103 return 0;
3104}
3105
3106static int vino_try_fmt_vid_cap(struct file *file, void *__fh,
3107 struct v4l2_format *f)
3108{
3109 struct vino_channel_settings *vcs = video_drvdata(file);
3110 struct vino_channel_settings tempvcs;
3111 unsigned long flags;
3112 struct v4l2_pix_format *pf = &f->fmt.pix;
3113
3114 dprintk("requested: w = %d, h = %d\n",
3115 pf->width, pf->height);
3116
3117 spin_lock_irqsave(&vino_drvdata->input_lock, flags);
3118 memcpy(&tempvcs, vcs, sizeof(struct vino_channel_settings));
3119 spin_unlock_irqrestore(&vino_drvdata->input_lock, flags);
3120
3121 tempvcs.data_format = vino_find_data_format(pf->pixelformat);
3122 if (tempvcs.data_format == VINO_DATA_FMT_NONE) {
3123 tempvcs.data_format = VINO_DATA_FMT_GREY;
3124 pf->pixelformat =
3125 vino_data_formats[tempvcs.data_format].
3126 pixelformat;
3127 }
3128
3129 /* data format must be set before clipping/scaling */
3130 vino_set_scaling(&tempvcs, pf->width, pf->height);
3131
3132 dprintk("data format = %s\n",
3133 vino_data_formats[tempvcs.data_format].description);
3134
3135 pf->width = (tempvcs.clipping.right - tempvcs.clipping.left) /
3136 tempvcs.decimation;
3137 pf->height = (tempvcs.clipping.bottom - tempvcs.clipping.top) /
3138 tempvcs.decimation;
3139
3140 pf->field = V4L2_FIELD_INTERLACED;
3141 pf->bytesperline = tempvcs.line_size;
3142 pf->sizeimage = tempvcs.line_size *
3143 (tempvcs.clipping.bottom - tempvcs.clipping.top) /
3144 tempvcs.decimation;
3145 pf->colorspace =
3146 vino_data_formats[tempvcs.data_format].colorspace;
3147
3148 return 0;
3149}
3150
3151static int vino_g_fmt_vid_cap(struct file *file, void *__fh,
3152 struct v4l2_format *f)
3153{
3154 struct vino_channel_settings *vcs = video_drvdata(file);
3155 unsigned long flags;
3156 struct v4l2_pix_format *pf = &f->fmt.pix;
3157
3158 spin_lock_irqsave(&vino_drvdata->input_lock, flags);
3159
3160 pf->width = (vcs->clipping.right - vcs->clipping.left) /
3161 vcs->decimation;
3162 pf->height = (vcs->clipping.bottom - vcs->clipping.top) /
3163 vcs->decimation;
3164 pf->pixelformat =
3165 vino_data_formats[vcs->data_format].pixelformat;
3166
3167 pf->field = V4L2_FIELD_INTERLACED;
3168 pf->bytesperline = vcs->line_size;
3169 pf->sizeimage = vcs->line_size *
3170 (vcs->clipping.bottom - vcs->clipping.top) /
3171 vcs->decimation;
3172 pf->colorspace =
3173 vino_data_formats[vcs->data_format].colorspace;
3174
3175 spin_unlock_irqrestore(&vino_drvdata->input_lock, flags);
3176 return 0;
3177}
3178
3179static int vino_s_fmt_vid_cap(struct file *file, void *__fh,
3180 struct v4l2_format *f)
3181{
3182 struct vino_channel_settings *vcs = video_drvdata(file);
3183 int data_format;
3184 unsigned long flags;
3185 struct v4l2_pix_format *pf = &f->fmt.pix;
3186
3187 spin_lock_irqsave(&vino_drvdata->input_lock, flags);
3188
3189 data_format = vino_find_data_format(pf->pixelformat);
3190
3191 if (data_format == VINO_DATA_FMT_NONE) {
3192 vcs->data_format = VINO_DATA_FMT_GREY;
3193 pf->pixelformat =
3194 vino_data_formats[vcs->data_format].
3195 pixelformat;
3196 } else {
3197 vcs->data_format = data_format;
3198 }
3199
3200 /* data format must be set before clipping/scaling */
3201 vino_set_scaling(vcs, pf->width, pf->height);
3202
3203 dprintk("data format = %s\n",
3204 vino_data_formats[vcs->data_format].description);
3205
3206 pf->width = vcs->clipping.right - vcs->clipping.left;
3207 pf->height = vcs->clipping.bottom - vcs->clipping.top;
3208
3209 pf->field = V4L2_FIELD_INTERLACED;
3210 pf->bytesperline = vcs->line_size;
3211 pf->sizeimage = vcs->line_size *
3212 (vcs->clipping.bottom - vcs->clipping.top) /
3213 vcs->decimation;
3214 pf->colorspace =
3215 vino_data_formats[vcs->data_format].colorspace;
3216
3217 spin_unlock_irqrestore(&vino_drvdata->input_lock, flags);
3218 return 0;
3219}
3220
3221static int vino_cropcap(struct file *file, void *__fh,
3222 struct v4l2_cropcap *ccap)
3223{
3224 struct vino_channel_settings *vcs = video_drvdata(file);
3225 const struct vino_data_norm *norm;
3226 unsigned long flags;
3227
3228 switch (ccap->type) {
3229 case V4L2_BUF_TYPE_VIDEO_CAPTURE:
3230 spin_lock_irqsave(&vino_drvdata->input_lock, flags);
3231
3232 norm = &vino_data_norms[vcs->data_norm];
3233
3234 spin_unlock_irqrestore(&vino_drvdata->input_lock, flags);
3235
3236 ccap->bounds.left = 0;
3237 ccap->bounds.top = 0;
3238 ccap->bounds.width = norm->width;
3239 ccap->bounds.height = norm->height;
3240 memcpy(&ccap->defrect, &ccap->bounds,
3241 sizeof(struct v4l2_rect));
3242
3243 ccap->pixelaspect.numerator = 1;
3244 ccap->pixelaspect.denominator = 1;
3245 break;
3246 case V4L2_BUF_TYPE_VIDEO_OVERLAY:
3247 default:
3248 return -EINVAL;
3249 }
3250
3251 return 0;
3252}
3253
3254static int vino_g_crop(struct file *file, void *__fh,
3255 struct v4l2_crop *c)
3256{
3257 struct vino_channel_settings *vcs = video_drvdata(file);
3258 unsigned long flags;
3259
3260 switch (c->type) {
3261 case V4L2_BUF_TYPE_VIDEO_CAPTURE:
3262 spin_lock_irqsave(&vino_drvdata->input_lock, flags);
3263
3264 c->c.left = vcs->clipping.left;
3265 c->c.top = vcs->clipping.top;
3266 c->c.width = vcs->clipping.right - vcs->clipping.left;
3267 c->c.height = vcs->clipping.bottom - vcs->clipping.top;
3268
3269 spin_unlock_irqrestore(&vino_drvdata->input_lock, flags);
3270 break;
3271 case V4L2_BUF_TYPE_VIDEO_OVERLAY:
3272 default:
3273 return -EINVAL;
3274 }
3275
3276 return 0;
3277}
3278
3279static int vino_s_crop(struct file *file, void *__fh,
3280 const struct v4l2_crop *c)
3281{
3282 struct vino_channel_settings *vcs = video_drvdata(file);
3283 unsigned long flags;
3284
3285 switch (c->type) {
3286 case V4L2_BUF_TYPE_VIDEO_CAPTURE:
3287 spin_lock_irqsave(&vino_drvdata->input_lock, flags);
3288
3289 vino_set_clipping(vcs, c->c.left, c->c.top,
3290 c->c.width, c->c.height);
3291
3292 spin_unlock_irqrestore(&vino_drvdata->input_lock, flags);
3293 break;
3294 case V4L2_BUF_TYPE_VIDEO_OVERLAY:
3295 default:
3296 return -EINVAL;
3297 }
3298
3299 return 0;
3300}
3301
3302static int vino_g_parm(struct file *file, void *__fh,
3303 struct v4l2_streamparm *sp)
3304{
3305 struct vino_channel_settings *vcs = video_drvdata(file);
3306 unsigned long flags;
3307 struct v4l2_captureparm *cp = &sp->parm.capture;
3308
3309 cp->capability = V4L2_CAP_TIMEPERFRAME;
3310 cp->timeperframe.numerator = 1;
3311
3312 spin_lock_irqsave(&vino_drvdata->input_lock, flags);
3313
3314 cp->timeperframe.denominator = vcs->fps;
3315
3316 spin_unlock_irqrestore(&vino_drvdata->input_lock, flags);
3317
3318 /* TODO: cp->readbuffers = xxx; */
3319
3320 return 0;
3321}
3322
3323static int vino_s_parm(struct file *file, void *__fh,
3324 struct v4l2_streamparm *sp)
3325{
3326 struct vino_channel_settings *vcs = video_drvdata(file);
3327 unsigned long flags;
3328 struct v4l2_captureparm *cp = &sp->parm.capture;
3329
3330 spin_lock_irqsave(&vino_drvdata->input_lock, flags);
3331
3332 if ((cp->timeperframe.numerator == 0) ||
3333 (cp->timeperframe.denominator == 0)) {
3334 /* reset framerate */
3335 vino_set_default_framerate(vcs);
3336 } else {
3337 vino_set_framerate(vcs, cp->timeperframe.denominator /
3338 cp->timeperframe.numerator);
3339 }
3340
3341 spin_unlock_irqrestore(&vino_drvdata->input_lock, flags);
3342
3343 return 0;
3344}
3345
3346static int vino_reqbufs(struct file *file, void *__fh,
3347 struct v4l2_requestbuffers *rb)
3348{
3349 struct vino_channel_settings *vcs = video_drvdata(file);
3350
3351 if (vcs->reading)
3352 return -EBUSY;
3353
3354 /* TODO: check queue type */
3355 if (rb->memory != V4L2_MEMORY_MMAP) {
3356 dprintk("type not mmap\n");
3357 return -EINVAL;
3358 }
3359
3360 dprintk("count = %d\n", rb->count);
3361 if (rb->count > 0) {
3362 if (vino_is_capturing(vcs)) {
3363 dprintk("busy, capturing\n");
3364 return -EBUSY;
3365 }
3366
3367 if (vino_queue_has_mapped_buffers(&vcs->fb_queue)) {
3368 dprintk("busy, buffers still mapped\n");
3369 return -EBUSY;
3370 } else {
3371 vcs->streaming = 0;
3372 vino_queue_free(&vcs->fb_queue);
3373 vino_queue_init(&vcs->fb_queue, &rb->count);
3374 }
3375 } else {
3376 vcs->streaming = 0;
3377 vino_capture_stop(vcs);
3378 vino_queue_free(&vcs->fb_queue);
3379 }
3380
3381 return 0;
3382}
3383
3384static void vino_v4l2_get_buffer_status(struct vino_channel_settings *vcs,
3385 struct vino_framebuffer *fb,
3386 struct v4l2_buffer *b)
3387{
3388 if (vino_queue_outgoing_contains(&vcs->fb_queue,
3389 fb->id)) {
3390 b->flags &= ~V4L2_BUF_FLAG_QUEUED;
3391 b->flags |= V4L2_BUF_FLAG_DONE;
3392 } else if (vino_queue_incoming_contains(&vcs->fb_queue,
3393 fb->id)) {
3394 b->flags &= ~V4L2_BUF_FLAG_DONE;
3395 b->flags |= V4L2_BUF_FLAG_QUEUED;
3396 } else {
3397 b->flags &= ~(V4L2_BUF_FLAG_DONE |
3398 V4L2_BUF_FLAG_QUEUED);
3399 }
3400
3401 b->flags &= ~(V4L2_BUF_FLAG_TIMECODE);
3402
3403 if (fb->map_count > 0)
3404 b->flags |= V4L2_BUF_FLAG_MAPPED;
3405
3406 b->flags &= ~V4L2_BUF_FLAG_TIMESTAMP_MASK;
3407 b->flags |= V4L2_BUF_FLAG_TIMESTAMP_MONOTONIC;
3408
3409 b->index = fb->id;
3410 b->memory = (vcs->fb_queue.type == VINO_MEMORY_MMAP) ?
3411 V4L2_MEMORY_MMAP : V4L2_MEMORY_USERPTR;
3412 b->m.offset = fb->offset;
3413 b->bytesused = fb->data_size;
3414 b->length = fb->size;
3415 b->field = V4L2_FIELD_INTERLACED;
3416 b->sequence = fb->frame_counter;
3417 memcpy(&b->timestamp, &fb->timestamp,
3418 sizeof(struct timeval));
3419 // b->input ?
3420
3421 dprintk("buffer %d: length = %d, bytesused = %d, offset = %d\n",
3422 fb->id, fb->size, fb->data_size, fb->offset);
3423}
3424
3425static int vino_querybuf(struct file *file, void *__fh,
3426 struct v4l2_buffer *b)
3427{
3428 struct vino_channel_settings *vcs = video_drvdata(file);
3429 struct vino_framebuffer *fb;
3430
3431 if (vcs->reading)
3432 return -EBUSY;
3433
3434 /* TODO: check queue type */
3435 if (b->index >= vino_queue_get_length(&vcs->fb_queue)) {
3436 dprintk("invalid index = %d\n",
3437 b->index);
3438 return -EINVAL;
3439 }
3440
3441 fb = vino_queue_get_buffer(&vcs->fb_queue,
3442 b->index);
3443 if (fb == NULL) {
3444 dprintk("vino_queue_get_buffer() failed");
3445 return -EINVAL;
3446 }
3447
3448 vino_v4l2_get_buffer_status(vcs, fb, b);
3449
3450 return 0;
3451}
3452
3453static int vino_qbuf(struct file *file, void *__fh,
3454 struct v4l2_buffer *b)
3455{
3456 struct vino_channel_settings *vcs = video_drvdata(file);
3457 struct vino_framebuffer *fb;
3458 int ret;
3459
3460 if (vcs->reading)
3461 return -EBUSY;
3462
3463 /* TODO: check queue type */
3464 if (b->memory != V4L2_MEMORY_MMAP) {
3465 dprintk("type not mmap\n");
3466 return -EINVAL;
3467 }
3468
3469 fb = vino_capture_enqueue(vcs, b->index);
3470 if (fb == NULL)
3471 return -EINVAL;
3472
3473 vino_v4l2_get_buffer_status(vcs, fb, b);
3474
3475 if (vcs->streaming) {
3476 ret = vino_capture_next(vcs, 1);
3477 if (ret)
3478 return ret;
3479 }
3480
3481 return 0;
3482}
3483
3484static int vino_dqbuf(struct file *file, void *__fh,
3485 struct v4l2_buffer *b)
3486{
3487 struct vino_channel_settings *vcs = video_drvdata(file);
3488 unsigned int nonblocking = file->f_flags & O_NONBLOCK;
3489 struct vino_framebuffer *fb;
3490 unsigned int incoming, outgoing;
3491 int err;
3492
3493 if (vcs->reading)
3494 return -EBUSY;
3495
3496 /* TODO: check queue type */
3497
3498 err = vino_queue_get_incoming(&vcs->fb_queue, &incoming);
3499 if (err) {
3500 dprintk("vino_queue_get_incoming() failed\n");
3501 return -EINVAL;
3502 }
3503 err = vino_queue_get_outgoing(&vcs->fb_queue, &outgoing);
3504 if (err) {
3505 dprintk("vino_queue_get_outgoing() failed\n");
3506 return -EINVAL;
3507 }
3508
3509 dprintk("incoming = %d, outgoing = %d\n", incoming, outgoing);
3510
3511 if (outgoing == 0) {
3512 if (incoming == 0) {
3513 dprintk("no incoming or outgoing buffers\n");
3514 return -EINVAL;
3515 }
3516 if (nonblocking) {
3517 dprintk("non-blocking I/O was selected and "
3518 "there are no buffers to dequeue\n");
3519 return -EAGAIN;
3520 }
3521
3522 err = vino_wait_for_frame(vcs);
3523 if (err) {
3524 err = vino_wait_for_frame(vcs);
3525 if (err) {
3526 /* interrupted or no frames captured because of
3527 * frame skipping */
3528 /* vino_capture_failed(vcs); */
3529 return -EIO;
3530 }
3531 }
3532 }
3533
3534 fb = vino_queue_remove(&vcs->fb_queue, &b->index);
3535 if (fb == NULL) {
3536 dprintk("vino_queue_remove() failed\n");
3537 return -EINVAL;
3538 }
3539
3540 err = vino_check_buffer(vcs, fb);
3541
3542 vino_v4l2_get_buffer_status(vcs, fb, b);
3543
3544 if (err)
3545 return -EIO;
3546
3547 return 0;
3548}
3549
3550static int vino_streamon(struct file *file, void *__fh,
3551 enum v4l2_buf_type i)
3552{
3553 struct vino_channel_settings *vcs = video_drvdata(file);
3554 unsigned int incoming;
3555 int ret;
3556 if (vcs->reading)
3557 return -EBUSY;
3558
3559 if (vcs->streaming)
3560 return 0;
3561
3562 // TODO: check queue type
3563
3564 if (vino_queue_get_length(&vcs->fb_queue) < 1) {
3565 dprintk("no buffers allocated\n");
3566 return -EINVAL;
3567 }
3568
3569 ret = vino_queue_get_incoming(&vcs->fb_queue, &incoming);
3570 if (ret) {
3571 dprintk("vino_queue_get_incoming() failed\n");
3572 return -EINVAL;
3573 }
3574
3575 vcs->streaming = 1;
3576
3577 if (incoming > 0) {
3578 ret = vino_capture_next(vcs, 1);
3579 if (ret) {
3580 vcs->streaming = 0;
3581
3582 dprintk("couldn't start capture\n");
3583 return -EINVAL;
3584 }
3585 }
3586
3587 return 0;
3588}
3589
3590static int vino_streamoff(struct file *file, void *__fh,
3591 enum v4l2_buf_type i)
3592{
3593 struct vino_channel_settings *vcs = video_drvdata(file);
3594 if (vcs->reading)
3595 return -EBUSY;
3596
3597 if (!vcs->streaming)
3598 return 0;
3599
3600 vcs->streaming = 0;
3601 vino_capture_stop(vcs);
3602
3603 return 0;
3604}
3605
3606static int vino_queryctrl(struct file *file, void *__fh,
3607 struct v4l2_queryctrl *queryctrl)
3608{
3609 struct vino_channel_settings *vcs = video_drvdata(file);
3610 unsigned long flags;
3611 int i;
3612 int err = 0;
3613
3614 spin_lock_irqsave(&vino_drvdata->input_lock, flags);
3615
3616 switch (vcs->input) {
3617 case VINO_INPUT_D1:
3618 for (i = 0; i < VINO_INDYCAM_V4L2_CONTROL_COUNT; i++) {
3619 if (vino_indycam_v4l2_controls[i].id ==
3620 queryctrl->id) {
3621 memcpy(queryctrl,
3622 &vino_indycam_v4l2_controls[i],
3623 sizeof(struct v4l2_queryctrl));
3624 queryctrl->reserved[0] = 0;
3625 goto found;
3626 }
3627 }
3628
3629 err = -EINVAL;
3630 break;
3631 case VINO_INPUT_COMPOSITE:
3632 case VINO_INPUT_SVIDEO:
3633 for (i = 0; i < VINO_SAA7191_V4L2_CONTROL_COUNT; i++) {
3634 if (vino_saa7191_v4l2_controls[i].id ==
3635 queryctrl->id) {
3636 memcpy(queryctrl,
3637 &vino_saa7191_v4l2_controls[i],
3638 sizeof(struct v4l2_queryctrl));
3639 queryctrl->reserved[0] = 0;
3640 goto found;
3641 }
3642 }
3643
3644 err = -EINVAL;
3645 break;
3646 default:
3647 err = -EINVAL;
3648 }
3649
3650 found:
3651 spin_unlock_irqrestore(&vino_drvdata->input_lock, flags);
3652
3653 return err;
3654}
3655
3656static int vino_g_ctrl(struct file *file, void *__fh,
3657 struct v4l2_control *control)
3658{
3659 struct vino_channel_settings *vcs = video_drvdata(file);
3660 unsigned long flags;
3661 int i;
3662 int err = 0;
3663
3664 spin_lock_irqsave(&vino_drvdata->input_lock, flags);
3665
3666 switch (vcs->input) {
3667 case VINO_INPUT_D1: {
3668 err = -EINVAL;
3669 for (i = 0; i < VINO_INDYCAM_V4L2_CONTROL_COUNT; i++) {
3670 if (vino_indycam_v4l2_controls[i].id == control->id) {
3671 err = 0;
3672 break;
3673 }
3674 }
3675
3676 if (err)
3677 goto out;
3678
3679 err = camera_call(core, g_ctrl, control);
3680 if (err)
3681 err = -EINVAL;
3682 break;
3683 }
3684 case VINO_INPUT_COMPOSITE:
3685 case VINO_INPUT_SVIDEO: {
3686 err = -EINVAL;
3687 for (i = 0; i < VINO_SAA7191_V4L2_CONTROL_COUNT; i++) {
3688 if (vino_saa7191_v4l2_controls[i].id == control->id) {
3689 err = 0;
3690 break;
3691 }
3692 }
3693
3694 if (err)
3695 goto out;
3696
3697 err = decoder_call(core, g_ctrl, control);
3698 if (err)
3699 err = -EINVAL;
3700 break;
3701 }
3702 default:
3703 err = -EINVAL;
3704 }
3705
3706out:
3707 spin_unlock_irqrestore(&vino_drvdata->input_lock, flags);
3708
3709 return err;
3710}
3711
3712static int vino_s_ctrl(struct file *file, void *__fh,
3713 struct v4l2_control *control)
3714{
3715 struct vino_channel_settings *vcs = video_drvdata(file);
3716 unsigned long flags;
3717 int i;
3718 int err = 0;
3719
3720 spin_lock_irqsave(&vino_drvdata->input_lock, flags);
3721
3722 if (!vino_is_input_owner(vcs)) {
3723 err = -EBUSY;
3724 goto out;
3725 }
3726
3727 switch (vcs->input) {
3728 case VINO_INPUT_D1: {
3729 err = -EINVAL;
3730 for (i = 0; i < VINO_INDYCAM_V4L2_CONTROL_COUNT; i++) {
3731 if (vino_indycam_v4l2_controls[i].id == control->id) {
3732 err = 0;
3733 break;
3734 }
3735 }
3736 if (err)
3737 goto out;
3738 if (control->value < vino_indycam_v4l2_controls[i].minimum ||
3739 control->value > vino_indycam_v4l2_controls[i].maximum) {
3740 err = -ERANGE;
3741 goto out;
3742 }
3743 err = camera_call(core, s_ctrl, control);
3744 if (err)
3745 err = -EINVAL;
3746 break;
3747 }
3748 case VINO_INPUT_COMPOSITE:
3749 case VINO_INPUT_SVIDEO: {
3750 err = -EINVAL;
3751 for (i = 0; i < VINO_SAA7191_V4L2_CONTROL_COUNT; i++) {
3752 if (vino_saa7191_v4l2_controls[i].id == control->id) {
3753 err = 0;
3754 break;
3755 }
3756 }
3757 if (err)
3758 goto out;
3759 if (control->value < vino_saa7191_v4l2_controls[i].minimum ||
3760 control->value > vino_saa7191_v4l2_controls[i].maximum) {
3761 err = -ERANGE;
3762 goto out;
3763 }
3764
3765 err = decoder_call(core, s_ctrl, control);
3766 if (err)
3767 err = -EINVAL;
3768 break;
3769 }
3770 default:
3771 err = -EINVAL;
3772 }
3773
3774out:
3775 spin_unlock_irqrestore(&vino_drvdata->input_lock, flags);
3776
3777 return err;
3778}
3779
3780/* File operations */
3781
3782static int vino_open(struct file *file)
3783{
3784 struct vino_channel_settings *vcs = video_drvdata(file);
3785 int ret = 0;
3786 dprintk("open(): channel = %c\n",
3787 (vcs->channel == VINO_CHANNEL_A) ? 'A' : 'B');
3788
3789 mutex_lock(&vcs->mutex);
3790
3791 if (vcs->users) {
3792 dprintk("open(): driver busy\n");
3793 ret = -EBUSY;
3794 goto out;
3795 }
3796
3797 ret = vino_acquire_input(vcs);
3798 if (ret) {
3799 dprintk("open(): vino_acquire_input() failed\n");
3800 goto out;
3801 }
3802
3803 vcs->users++;
3804
3805 out:
3806 mutex_unlock(&vcs->mutex);
3807
3808 dprintk("open(): %s!\n", ret ? "failed" : "complete");
3809
3810 return ret;
3811}
3812
3813static int vino_close(struct file *file)
3814{
3815 struct vino_channel_settings *vcs = video_drvdata(file);
3816 dprintk("close():\n");
3817
3818 mutex_lock(&vcs->mutex);
3819
3820 vcs->users--;
3821
3822 if (!vcs->users) {
3823 vino_release_input(vcs);
3824
3825 /* stop DMA and free buffers */
3826 vino_capture_stop(vcs);
3827 vino_queue_free(&vcs->fb_queue);
3828 }
3829
3830 mutex_unlock(&vcs->mutex);
3831
3832 return 0;
3833}
3834
3835static void vino_vm_open(struct vm_area_struct *vma)
3836{
3837 struct vino_framebuffer *fb = vma->vm_private_data;
3838
3839 fb->map_count++;
3840 dprintk("vino_vm_open(): count = %d\n", fb->map_count);
3841}
3842
3843static void vino_vm_close(struct vm_area_struct *vma)
3844{
3845 struct vino_framebuffer *fb = vma->vm_private_data;
3846
3847 fb->map_count--;
3848 dprintk("vino_vm_close(): count = %d\n", fb->map_count);
3849}
3850
3851static const struct vm_operations_struct vino_vm_ops = {
3852 .open = vino_vm_open,
3853 .close = vino_vm_close,
3854};
3855
3856static int vino_mmap(struct file *file, struct vm_area_struct *vma)
3857{
3858 struct vino_channel_settings *vcs = video_drvdata(file);
3859
3860 unsigned long start = vma->vm_start;
3861 unsigned long size = vma->vm_end - vma->vm_start;
3862 unsigned long offset = vma->vm_pgoff << PAGE_SHIFT;
3863
3864 struct vino_framebuffer *fb = NULL;
3865 unsigned int i, length;
3866 int ret = 0;
3867
3868 dprintk("mmap():\n");
3869
3870 // TODO: reject mmap if already mapped
3871
3872 if (mutex_lock_interruptible(&vcs->mutex))
3873 return -EINTR;
3874
3875 if (vcs->reading) {
3876 ret = -EBUSY;
3877 goto out;
3878 }
3879
3880 // TODO: check queue type
3881
3882 if (!(vma->vm_flags & VM_WRITE)) {
3883 dprintk("mmap(): app bug: PROT_WRITE please\n");
3884 ret = -EINVAL;
3885 goto out;
3886 }
3887 if (!(vma->vm_flags & VM_SHARED)) {
3888 dprintk("mmap(): app bug: MAP_SHARED please\n");
3889 ret = -EINVAL;
3890 goto out;
3891 }
3892
3893 /* find the correct buffer using offset */
3894 length = vino_queue_get_length(&vcs->fb_queue);
3895 if (length == 0) {
3896 dprintk("mmap(): queue not initialized\n");
3897 ret = -EINVAL;
3898 goto out;
3899 }
3900
3901 for (i = 0; i < length; i++) {
3902 fb = vino_queue_get_buffer(&vcs->fb_queue, i);
3903 if (fb == NULL) {
3904 dprintk("mmap(): vino_queue_get_buffer() failed\n");
3905 ret = -EINVAL;
3906 goto out;
3907 }
3908
3909 if (fb->offset == offset)
3910 goto found;
3911 }
3912
3913 dprintk("mmap(): invalid offset = %lu\n", offset);
3914 ret = -EINVAL;
3915 goto out;
3916
3917found:
3918 dprintk("mmap(): buffer = %d\n", i);
3919
3920 if (size > (fb->desc_table.page_count * PAGE_SIZE)) {
3921 dprintk("mmap(): failed: size = %lu > %lu\n",
3922 size, fb->desc_table.page_count * PAGE_SIZE);
3923 ret = -EINVAL;
3924 goto out;
3925 }
3926
3927 for (i = 0; i < fb->desc_table.page_count; i++) {
3928 unsigned long pfn =
3929 virt_to_phys((void *)fb->desc_table.virtual[i]) >>
3930 PAGE_SHIFT;
3931
3932 if (size < PAGE_SIZE)
3933 break;
3934
3935 // protection was: PAGE_READONLY
3936 if (remap_pfn_range(vma, start, pfn, PAGE_SIZE,
3937 vma->vm_page_prot)) {
3938 dprintk("mmap(): remap_pfn_range() failed\n");
3939 ret = -EAGAIN;
3940 goto out;
3941 }
3942
3943 start += PAGE_SIZE;
3944 size -= PAGE_SIZE;
3945 }
3946
3947 fb->map_count = 1;
3948
3949 vma->vm_flags |= VM_DONTEXPAND | VM_DONTDUMP;
3950 vma->vm_flags &= ~VM_IO;
3951 vma->vm_private_data = fb;
3952 vma->vm_file = file;
3953 vma->vm_ops = &vino_vm_ops;
3954
3955out:
3956 mutex_unlock(&vcs->mutex);
3957
3958 return ret;
3959}
3960
3961static unsigned int vino_poll(struct file *file, poll_table *pt)
3962{
3963 struct vino_channel_settings *vcs = video_drvdata(file);
3964 unsigned int outgoing;
3965 unsigned int ret = 0;
3966
3967 // lock mutex (?)
3968 // TODO: this has to be corrected for different read modes
3969
3970 dprintk("poll():\n");
3971
3972 if (vino_queue_get_outgoing(&vcs->fb_queue, &outgoing)) {
3973 dprintk("poll(): vino_queue_get_outgoing() failed\n");
3974 ret = POLLERR;
3975 goto error;
3976 }
3977 if (outgoing > 0)
3978 goto over;
3979
3980 poll_wait(file, &vcs->fb_queue.frame_wait_queue, pt);
3981
3982 if (vino_queue_get_outgoing(&vcs->fb_queue, &outgoing)) {
3983 dprintk("poll(): vino_queue_get_outgoing() failed\n");
3984 ret = POLLERR;
3985 goto error;
3986 }
3987
3988over:
3989 dprintk("poll(): data %savailable\n",
3990 (outgoing > 0) ? "" : "not ");
3991
3992 if (outgoing > 0)
3993 ret = POLLIN | POLLRDNORM;
3994
3995error:
3996 return ret;
3997}
3998
3999static long vino_ioctl(struct file *file,
4000 unsigned int cmd, unsigned long arg)
4001{
4002 struct vino_channel_settings *vcs = video_drvdata(file);
4003 long ret;
4004
4005 if (mutex_lock_interruptible(&vcs->mutex))
4006 return -EINTR;
4007
4008 ret = video_ioctl2(file, cmd, arg);
4009
4010 mutex_unlock(&vcs->mutex);
4011
4012 return ret;
4013}
4014
4015/* Initialization and cleanup */
4016
4017/* __initdata */
4018static int vino_init_stage;
4019
4020const struct v4l2_ioctl_ops vino_ioctl_ops = {
4021 .vidioc_enum_fmt_vid_cap = vino_enum_fmt_vid_cap,
4022 .vidioc_g_fmt_vid_cap = vino_g_fmt_vid_cap,
4023 .vidioc_s_fmt_vid_cap = vino_s_fmt_vid_cap,
4024 .vidioc_try_fmt_vid_cap = vino_try_fmt_vid_cap,
4025 .vidioc_querycap = vino_querycap,
4026 .vidioc_enum_input = vino_enum_input,
4027 .vidioc_g_input = vino_g_input,
4028 .vidioc_s_input = vino_s_input,
4029 .vidioc_g_std = vino_g_std,
4030 .vidioc_s_std = vino_s_std,
4031 .vidioc_querystd = vino_querystd,
4032 .vidioc_cropcap = vino_cropcap,
4033 .vidioc_s_crop = vino_s_crop,
4034 .vidioc_g_crop = vino_g_crop,
4035 .vidioc_s_parm = vino_s_parm,
4036 .vidioc_g_parm = vino_g_parm,
4037 .vidioc_reqbufs = vino_reqbufs,
4038 .vidioc_querybuf = vino_querybuf,
4039 .vidioc_qbuf = vino_qbuf,
4040 .vidioc_dqbuf = vino_dqbuf,
4041 .vidioc_streamon = vino_streamon,
4042 .vidioc_streamoff = vino_streamoff,
4043 .vidioc_queryctrl = vino_queryctrl,
4044 .vidioc_g_ctrl = vino_g_ctrl,
4045 .vidioc_s_ctrl = vino_s_ctrl,
4046};
4047
4048static const struct v4l2_file_operations vino_fops = {
4049 .owner = THIS_MODULE,
4050 .open = vino_open,
4051 .release = vino_close,
4052 .unlocked_ioctl = vino_ioctl,
4053 .mmap = vino_mmap,
4054 .poll = vino_poll,
4055};
4056
4057static struct video_device vdev_template = {
4058 .name = "NOT SET",
4059 .fops = &vino_fops,
4060 .ioctl_ops = &vino_ioctl_ops,
4061 .tvnorms = V4L2_STD_NTSC | V4L2_STD_PAL | V4L2_STD_SECAM,
4062};
4063
4064static void vino_module_cleanup(int stage)
4065{
4066 switch(stage) {
4067 case 11:
4068 video_unregister_device(vino_drvdata->b.vdev);
4069 vino_drvdata->b.vdev = NULL;
4070 case 10:
4071 video_unregister_device(vino_drvdata->a.vdev);
4072 vino_drvdata->a.vdev = NULL;
4073 case 9:
4074 i2c_del_adapter(&vino_i2c_adapter);
4075 case 8:
4076 free_irq(SGI_VINO_IRQ, NULL);
4077 case 7:
4078 if (vino_drvdata->b.vdev) {
4079 video_device_release(vino_drvdata->b.vdev);
4080 vino_drvdata->b.vdev = NULL;
4081 }
4082 case 6:
4083 if (vino_drvdata->a.vdev) {
4084 video_device_release(vino_drvdata->a.vdev);
4085 vino_drvdata->a.vdev = NULL;
4086 }
4087 case 5:
4088 /* all entries in dma_cpu dummy table have the same address */
4089 dma_unmap_single(NULL,
4090 vino_drvdata->dummy_desc_table.dma_cpu[0],
4091 PAGE_SIZE, DMA_FROM_DEVICE);
4092 dma_free_coherent(NULL, VINO_DUMMY_DESC_COUNT
4093 * sizeof(dma_addr_t),
4094 (void *)vino_drvdata->
4095 dummy_desc_table.dma_cpu,
4096 vino_drvdata->dummy_desc_table.dma);
4097 case 4:
4098 free_page(vino_drvdata->dummy_page);
4099 case 3:
4100 v4l2_device_unregister(&vino_drvdata->v4l2_dev);
4101 case 2:
4102 kfree(vino_drvdata);
4103 case 1:
4104 iounmap(vino);
4105 case 0:
4106 break;
4107 default:
4108 dprintk("vino_module_cleanup(): invalid cleanup stage = %d\n",
4109 stage);
4110 }
4111}
4112
4113static int vino_probe(void)
4114{
4115 unsigned long rev_id;
4116
4117 if (ip22_is_fullhouse()) {
4118 printk(KERN_ERR "VINO doesn't exist in IP22 Fullhouse\n");
4119 return -ENODEV;
4120 }
4121
4122 if (!(sgimc->systemid & SGIMC_SYSID_EPRESENT)) {
4123 printk(KERN_ERR "VINO is not found (EISA BUS not present)\n");
4124 return -ENODEV;
4125 }
4126
4127 vino = (struct sgi_vino *)ioremap(VINO_BASE, sizeof(struct sgi_vino));
4128 if (!vino) {
4129 printk(KERN_ERR "VINO: ioremap() failed\n");
4130 return -EIO;
4131 }
4132 vino_init_stage++;
4133
4134 if (get_dbe(rev_id, &(vino->rev_id))) {
4135 printk(KERN_ERR "Failed to read VINO revision register\n");
4136 vino_module_cleanup(vino_init_stage);
4137 return -ENODEV;
4138 }
4139
4140 if (VINO_ID_VALUE(rev_id) != VINO_CHIP_ID) {
4141 printk(KERN_ERR "Unknown VINO chip ID (Rev/ID: 0x%02lx)\n",
4142 rev_id);
4143 vino_module_cleanup(vino_init_stage);
4144 return -ENODEV;
4145 }
4146
4147 printk(KERN_INFO "VINO revision %ld found\n", VINO_REV_NUM(rev_id));
4148
4149 return 0;
4150}
4151
4152static int vino_init(void)
4153{
4154 dma_addr_t dma_dummy_address;
4155 int err;
4156 int i;
4157
4158 vino_drvdata = kzalloc(sizeof(struct vino_settings), GFP_KERNEL);
4159 if (!vino_drvdata) {
4160 vino_module_cleanup(vino_init_stage);
4161 return -ENOMEM;
4162 }
4163 vino_init_stage++;
4164 strlcpy(vino_drvdata->v4l2_dev.name, "vino",
4165 sizeof(vino_drvdata->v4l2_dev.name));
4166 err = v4l2_device_register(NULL, &vino_drvdata->v4l2_dev);
4167 if (err)
4168 return err;
4169 vino_init_stage++;
4170
4171 /* create a dummy dma descriptor */
4172 vino_drvdata->dummy_page = get_zeroed_page(GFP_KERNEL | GFP_DMA);
4173 if (!vino_drvdata->dummy_page) {
4174 vino_module_cleanup(vino_init_stage);
4175 return -ENOMEM;
4176 }
4177 vino_init_stage++;
4178
4179 // TODO: use page_count in dummy_desc_table
4180
4181 vino_drvdata->dummy_desc_table.dma_cpu =
4182 dma_alloc_coherent(NULL,
4183 VINO_DUMMY_DESC_COUNT * sizeof(dma_addr_t),
4184 &vino_drvdata->dummy_desc_table.dma,
4185 GFP_KERNEL | GFP_DMA);
4186 if (!vino_drvdata->dummy_desc_table.dma_cpu) {
4187 vino_module_cleanup(vino_init_stage);
4188 return -ENOMEM;
4189 }
4190 vino_init_stage++;
4191
4192 dma_dummy_address = dma_map_single(NULL,
4193 (void *)vino_drvdata->dummy_page,
4194 PAGE_SIZE, DMA_FROM_DEVICE);
4195 for (i = 0; i < VINO_DUMMY_DESC_COUNT; i++) {
4196 vino_drvdata->dummy_desc_table.dma_cpu[i] = dma_dummy_address;
4197 }
4198
4199 /* initialize VINO */
4200
4201 vino->control = 0;
4202 vino->a.next_4_desc = vino_drvdata->dummy_desc_table.dma;
4203 vino->b.next_4_desc = vino_drvdata->dummy_desc_table.dma;
4204 udelay(VINO_DESC_FETCH_DELAY);
4205
4206 vino->intr_status = 0;
4207
4208 vino->a.fifo_thres = VINO_FIFO_THRESHOLD_DEFAULT;
4209 vino->b.fifo_thres = VINO_FIFO_THRESHOLD_DEFAULT;
4210
4211 return 0;
4212}
4213
4214static int vino_init_channel_settings(struct vino_channel_settings *vcs,
4215 unsigned int channel, const char *name)
4216{
4217 vcs->channel = channel;
4218 vcs->input = VINO_INPUT_NONE;
4219 vcs->alpha = 0;
4220 vcs->users = 0;
4221 vcs->data_format = VINO_DATA_FMT_GREY;
4222 vcs->data_norm = VINO_DATA_NORM_NTSC;
4223 vcs->decimation = 1;
4224 vino_set_default_clipping(vcs);
4225 vino_set_default_framerate(vcs);
4226
4227 vcs->capturing = 0;
4228
4229 mutex_init(&vcs->mutex);
4230 spin_lock_init(&vcs->capture_lock);
4231
4232 mutex_init(&vcs->fb_queue.queue_mutex);
4233 spin_lock_init(&vcs->fb_queue.queue_lock);
4234 init_waitqueue_head(&vcs->fb_queue.frame_wait_queue);
4235
4236 vcs->vdev = video_device_alloc();
4237 if (!vcs->vdev) {
4238 vino_module_cleanup(vino_init_stage);
4239 return -ENOMEM;
4240 }
4241 vino_init_stage++;
4242
4243 memcpy(vcs->vdev, &vdev_template,
4244 sizeof(struct video_device));
4245 strcpy(vcs->vdev->name, name);
4246 vcs->vdev->release = video_device_release;
4247 vcs->vdev->v4l2_dev = &vino_drvdata->v4l2_dev;
4248
4249 video_set_drvdata(vcs->vdev, vcs);
4250
4251 return 0;
4252}
4253
4254static int __init vino_module_init(void)
4255{
4256 int ret;
4257
4258 printk(KERN_INFO "SGI VINO driver version %s\n",
4259 VINO_MODULE_VERSION);
4260
4261 ret = vino_probe();
4262 if (ret)
4263 return ret;
4264
4265 ret = vino_init();
4266 if (ret)
4267 return ret;
4268
4269 /* initialize data structures */
4270
4271 spin_lock_init(&vino_drvdata->vino_lock);
4272 spin_lock_init(&vino_drvdata->input_lock);
4273
4274 ret = vino_init_channel_settings(&vino_drvdata->a, VINO_CHANNEL_A,
4275 vino_vdev_name_a);
4276 if (ret)
4277 return ret;
4278
4279 ret = vino_init_channel_settings(&vino_drvdata->b, VINO_CHANNEL_B,
4280 vino_vdev_name_b);
4281 if (ret)
4282 return ret;
4283
4284 /* initialize hardware and register V4L devices */
4285
4286 ret = request_irq(SGI_VINO_IRQ, vino_interrupt, 0,
4287 vino_driver_description, NULL);
4288 if (ret) {
4289 printk(KERN_ERR "VINO: requesting IRQ %02d failed\n",
4290 SGI_VINO_IRQ);
4291 vino_module_cleanup(vino_init_stage);
4292 return -EAGAIN;
4293 }
4294 vino_init_stage++;
4295
4296 ret = i2c_add_adapter(&vino_i2c_adapter);
4297 if (ret) {
4298 printk(KERN_ERR "VINO I2C bus registration failed\n");
4299 vino_module_cleanup(vino_init_stage);
4300 return ret;
4301 }
4302 i2c_set_adapdata(&vino_i2c_adapter, &vino_drvdata->v4l2_dev);
4303 vino_init_stage++;
4304
4305 ret = video_register_device(vino_drvdata->a.vdev,
4306 VFL_TYPE_GRABBER, -1);
4307 if (ret < 0) {
4308 printk(KERN_ERR "VINO channel A Video4Linux-device "
4309 "registration failed\n");
4310 vino_module_cleanup(vino_init_stage);
4311 return -EINVAL;
4312 }
4313 vino_init_stage++;
4314
4315 ret = video_register_device(vino_drvdata->b.vdev,
4316 VFL_TYPE_GRABBER, -1);
4317 if (ret < 0) {
4318 printk(KERN_ERR "VINO channel B Video4Linux-device "
4319 "registration failed\n");
4320 vino_module_cleanup(vino_init_stage);
4321 return -EINVAL;
4322 }
4323 vino_init_stage++;
4324
4325 vino_drvdata->decoder =
4326 v4l2_i2c_new_subdev(&vino_drvdata->v4l2_dev, &vino_i2c_adapter,
4327 "saa7191", 0, I2C_ADDRS(0x45));
4328 vino_drvdata->camera =
4329 v4l2_i2c_new_subdev(&vino_drvdata->v4l2_dev, &vino_i2c_adapter,
4330 "indycam", 0, I2C_ADDRS(0x2b));
4331
4332 dprintk("init complete!\n");
4333
4334 return 0;
4335}
4336
4337static void __exit vino_module_exit(void)
4338{
4339 dprintk("exiting, stage = %d ...\n", vino_init_stage);
4340 vino_module_cleanup(vino_init_stage);
4341 dprintk("cleanup complete, exit!\n");
4342}
4343
4344module_init(vino_module_init);
4345module_exit(vino_module_exit);
diff --git a/drivers/staging/media/vino/vino.h b/drivers/staging/media/vino/vino.h
new file mode 100644
index 000000000000..de2d615ae7c9
--- /dev/null
+++ b/drivers/staging/media/vino/vino.h
@@ -0,0 +1,138 @@
1/*
2 * Driver for the VINO (Video In No Out) system found in SGI Indys.
3 *
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 *
7 * Copyright (C) 1999 Ulf Karlsson <ulfc@bun.falkenberg.se>
8 * Copyright (C) 2003 Ladislav Michl <ladis@linux-mips.org>
9 */
10
11#ifndef _VINO_H_
12#define _VINO_H_
13
14#define VINO_BASE 0x00080000 /* Vino is in the EISA address space,
15 * but it is not an EISA bus card */
16#define VINO_PAGE_SIZE 4096
17
18struct sgi_vino_channel {
19 u32 _pad_alpha;
20 volatile u32 alpha;
21
22#define VINO_CLIP_X(x) ((x) & 0x3ff) /* bits 0:9 */
23#define VINO_CLIP_ODD(x) (((x) & 0x1ff) << 10) /* bits 10:18 */
24#define VINO_CLIP_EVEN(x) (((x) & 0x1ff) << 19) /* bits 19:27 */
25 u32 _pad_clip_start;
26 volatile u32 clip_start;
27 u32 _pad_clip_end;
28 volatile u32 clip_end;
29
30#define VINO_FRAMERT_FULL 0xfff
31#define VINO_FRAMERT_PAL (1<<0) /* 0=NTSC 1=PAL */
32#define VINO_FRAMERT_RT(x) (((x) & 0xfff) << 1) /* bits 1:12 */
33 u32 _pad_frame_rate;
34 volatile u32 frame_rate;
35
36 u32 _pad_field_counter;
37 volatile u32 field_counter;
38 u32 _pad_line_size;
39 volatile u32 line_size;
40 u32 _pad_line_count;
41 volatile u32 line_count;
42 u32 _pad_page_index;
43 volatile u32 page_index;
44 u32 _pad_next_4_desc;
45 volatile u32 next_4_desc;
46 u32 _pad_start_desc_tbl;
47 volatile u32 start_desc_tbl;
48
49#define VINO_DESC_JUMP (1<<30)
50#define VINO_DESC_STOP (1<<31)
51#define VINO_DESC_VALID (1<<32)
52 u32 _pad_desc_0;
53 volatile u32 desc_0;
54 u32 _pad_desc_1;
55 volatile u32 desc_1;
56 u32 _pad_desc_2;
57 volatile u32 desc_2;
58 u32 _pad_Bdesc_3;
59 volatile u32 desc_3;
60
61 u32 _pad_fifo_thres;
62 volatile u32 fifo_thres;
63 u32 _pad_fifo_read;
64 volatile u32 fifo_read;
65 u32 _pad_fifo_write;
66 volatile u32 fifo_write;
67};
68
69struct sgi_vino {
70#define VINO_CHIP_ID 0xb
71#define VINO_REV_NUM(x) ((x) & 0x0f)
72#define VINO_ID_VALUE(x) (((x) & 0xf0) >> 4)
73 u32 _pad_rev_id;
74 volatile u32 rev_id;
75
76#define VINO_CTRL_LITTLE_ENDIAN (1<<0)
77#define VINO_CTRL_A_EOF_INT (1<<1) /* Field transferred int */
78#define VINO_CTRL_A_FIFO_INT (1<<2) /* FIFO overflow int */
79#define VINO_CTRL_A_EOD_INT (1<<3) /* End of desc table int */
80#define VINO_CTRL_A_INT (VINO_CTRL_A_EOF_INT | \
81 VINO_CTRL_A_FIFO_INT | \
82 VINO_CTRL_A_EOD_INT)
83#define VINO_CTRL_B_EOF_INT (1<<4) /* Field transferred int */
84#define VINO_CTRL_B_FIFO_INT (1<<5) /* FIFO overflow int */
85#define VINO_CTRL_B_EOD_INT (1<<6) /* End of desc table int */
86#define VINO_CTRL_B_INT (VINO_CTRL_B_EOF_INT | \
87 VINO_CTRL_B_FIFO_INT | \
88 VINO_CTRL_B_EOD_INT)
89#define VINO_CTRL_A_DMA_ENBL (1<<7)
90#define VINO_CTRL_A_INTERLEAVE_ENBL (1<<8)
91#define VINO_CTRL_A_SYNC_ENBL (1<<9)
92#define VINO_CTRL_A_SELECT (1<<10) /* 1=D1 0=Philips */
93#define VINO_CTRL_A_RGB (1<<11) /* 1=RGB 0=YUV */
94#define VINO_CTRL_A_LUMA_ONLY (1<<12)
95#define VINO_CTRL_A_DEC_ENBL (1<<13) /* Decimation */
96#define VINO_CTRL_A_DEC_SCALE_MASK 0x1c000 /* bits 14:17 */
97#define VINO_CTRL_A_DEC_SCALE_SHIFT (14)
98#define VINO_CTRL_A_DEC_HOR_ONLY (1<<17) /* Horizontal only */
99#define VINO_CTRL_A_DITHER (1<<18) /* 24 -> 8 bit dither */
100#define VINO_CTRL_B_DMA_ENBL (1<<19)
101#define VINO_CTRL_B_INTERLEAVE_ENBL (1<<20)
102#define VINO_CTRL_B_SYNC_ENBL (1<<21)
103#define VINO_CTRL_B_SELECT (1<<22) /* 1=D1 0=Philips */
104#define VINO_CTRL_B_RGB (1<<23) /* 1=RGB 0=YUV */
105#define VINO_CTRL_B_LUMA_ONLY (1<<24)
106#define VINO_CTRL_B_DEC_ENBL (1<<25) /* Decimation */
107#define VINO_CTRL_B_DEC_SCALE_MASK 0x1c000000 /* bits 26:28 */
108#define VINO_CTRL_B_DEC_SCALE_SHIFT (26)
109#define VINO_CTRL_B_DEC_HOR_ONLY (1<<29) /* Decimation horizontal only */
110#define VINO_CTRL_B_DITHER (1<<30) /* ChanB 24 -> 8 bit dither */
111 u32 _pad_control;
112 volatile u32 control;
113
114#define VINO_INTSTAT_A_EOF (1<<0) /* Field transferred int */
115#define VINO_INTSTAT_A_FIFO (1<<1) /* FIFO overflow int */
116#define VINO_INTSTAT_A_EOD (1<<2) /* End of desc table int */
117#define VINO_INTSTAT_A (VINO_INTSTAT_A_EOF | \
118 VINO_INTSTAT_A_FIFO | \
119 VINO_INTSTAT_A_EOD)
120#define VINO_INTSTAT_B_EOF (1<<3) /* Field transferred int */
121#define VINO_INTSTAT_B_FIFO (1<<4) /* FIFO overflow int */
122#define VINO_INTSTAT_B_EOD (1<<5) /* End of desc table int */
123#define VINO_INTSTAT_B (VINO_INTSTAT_B_EOF | \
124 VINO_INTSTAT_B_FIFO | \
125 VINO_INTSTAT_B_EOD)
126 u32 _pad_intr_status;
127 volatile u32 intr_status;
128
129 u32 _pad_i2c_control;
130 volatile u32 i2c_control;
131 u32 _pad_i2c_data;
132 volatile u32 i2c_data;
133
134 struct sgi_vino_channel a;
135 struct sgi_vino_channel b;
136};
137
138#endif