summaryrefslogtreecommitdiff
path: root/linux/drivers
diff options
context:
space:
mode:
authorMauro Carvalho Chehab <mchehab@redhat.com>2009-03-09 22:10:14 -0300
committerMauro Carvalho Chehab <mchehab@redhat.com>2009-03-09 22:10:14 -0300
commit1ca5e4c0dffa7cabe5bac2ca5d44e104bf674f33 (patch)
treebf2bd9f13bdbb0f8daec4e09e68efc9b6af39b9d /linux/drivers
parenta290b0de64aabced5f3bebd88fc75aaf96e74c36 (diff)
parent065193c75af7a295d98a8cad617537d45f69a23a (diff)
downloadmediapointer-dvb-s2-1ca5e4c0dffa7cabe5bac2ca5d44e104bf674f33.tar.gz
mediapointer-dvb-s2-1ca5e4c0dffa7cabe5bac2ca5d44e104bf674f33.tar.bz2
merge: http://www.linuxtv.org/hg/~hverkuil/v4l-dvb-vino
From: Mauro Carvalho Chehab <mchehab@redhat.com> Signed-off-by: Mauro Carvalho Chehab <mchehab@redhat.com>
Diffstat (limited to 'linux/drivers')
-rw-r--r--linux/drivers/media/video/Kconfig1
-rw-r--r--linux/drivers/media/video/indycam.c323
-rw-r--r--linux/drivers/media/video/indycam.h19
-rw-r--r--linux/drivers/media/video/saa7191.c508
-rw-r--r--linux/drivers/media/video/saa7191.h26
-rw-r--r--linux/drivers/media/video/vino.c1389
6 files changed, 898 insertions, 1368 deletions
diff --git a/linux/drivers/media/video/Kconfig b/linux/drivers/media/video/Kconfig
index 6c26618b8..534a022c4 100644
--- a/linux/drivers/media/video/Kconfig
+++ b/linux/drivers/media/video/Kconfig
@@ -582,7 +582,6 @@ config VIDEO_SAA5249
config VIDEO_VINO
tristate "SGI Vino Video For Linux (EXPERIMENTAL)"
depends on I2C && SGI_IP22 && EXPERIMENTAL && VIDEO_V4L2
- select I2C_ALGO_SGI
select VIDEO_SAA7191 if VIDEO_HELPER_CHIPS_AUTO
help
Say Y here to build in support for the Vino video input system found
diff --git a/linux/drivers/media/video/indycam.c b/linux/drivers/media/video/indycam.c
index 84b9e4f2b..f2da0550b 100644
--- a/linux/drivers/media/video/indycam.c
+++ b/linux/drivers/media/video/indycam.c
@@ -19,10 +19,12 @@
#include <linux/mm.h>
#include <linux/slab.h>
-#include <linux/videodev.h>
/* IndyCam decodes stream of photons into digital image representation ;-) */
-#include <linux/video_decoder.h>
+#include <linux/videodev2.h>
#include <linux/i2c.h>
+#include <media/v4l2-device.h>
+#include <media/v4l2-chip-ident.h>
+#include <media/v4l2-i2c-drv.h>
#include "indycam.h"
@@ -33,6 +35,12 @@ MODULE_VERSION(INDYCAM_MODULE_VERSION);
MODULE_AUTHOR("Mikael Nousiainen <tmnousia@cc.hut.fi>");
MODULE_LICENSE("GPL");
+#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 22)
+static unsigned short normal_i2c[] = { 0x56 >> 1, I2C_CLIENT_END };
+
+I2C_CLIENT_INSMOD;
+#endif
+
// #define INDYCAM_DEBUG
#ifdef INDYCAM_DEBUG
@@ -44,11 +52,14 @@ MODULE_LICENSE("GPL");
#endif
struct indycam {
- struct i2c_client *client;
+ struct v4l2_subdev sd;
u8 version;
};
-static struct i2c_driver i2c_driver_indycam;
+static inline struct indycam *to_indycam(struct v4l2_subdev *sd)
+{
+ return container_of(sd, struct indycam, sd);
+}
static const u8 initseq[] = {
INDYCAM_CONTROL_AGCENA, /* INDYCAM_CONTROL */
@@ -63,8 +74,9 @@ static const u8 initseq[] = {
/* IndyCam register handling */
-static int indycam_read_reg(struct i2c_client *client, u8 reg, u8 *value)
+static int indycam_read_reg(struct v4l2_subdev *sd, u8 reg, u8 *value)
{
+ struct i2c_client *client = v4l2_get_subdevdata(sd);
int ret;
if (reg == INDYCAM_REG_RESET) {
@@ -87,12 +99,12 @@ static int indycam_read_reg(struct i2c_client *client, u8 reg, u8 *value)
return 0;
}
-static int indycam_write_reg(struct i2c_client *client, u8 reg, u8 value)
+static int indycam_write_reg(struct v4l2_subdev *sd, u8 reg, u8 value)
{
+ struct i2c_client *client = v4l2_get_subdevdata(sd);
int err;
- if ((reg == INDYCAM_REG_BRIGHTNESS)
- || (reg == INDYCAM_REG_VERSION)) {
+ if (reg == INDYCAM_REG_BRIGHTNESS || reg == INDYCAM_REG_VERSION) {
dprintk("indycam_write_reg(): "
"skipping read-only register %d\n", reg);
return 0;
@@ -108,13 +120,13 @@ static int indycam_write_reg(struct i2c_client *client, u8 reg, u8 value)
return err;
}
-static int indycam_write_block(struct i2c_client *client, u8 reg,
+static int indycam_write_block(struct v4l2_subdev *sd, u8 reg,
u8 length, u8 *data)
{
int i, err;
for (i = 0; i < length; i++) {
- err = indycam_write_reg(client, reg + i, data[i]);
+ err = indycam_write_reg(sd, reg + i, data[i]);
if (err)
return err;
}
@@ -125,79 +137,78 @@ static int indycam_write_block(struct i2c_client *client, u8 reg,
/* Helper functions */
#ifdef INDYCAM_DEBUG
-static void indycam_regdump_debug(struct i2c_client *client)
+static void indycam_regdump_debug(struct v4l2_subdev *sd)
{
int i;
u8 val;
for (i = 0; i < 9; i++) {
- indycam_read_reg(client, i, &val);
+ indycam_read_reg(sd, i, &val);
dprintk("Reg %d = 0x%02x\n", i, val);
}
}
#endif
-static int indycam_get_control(struct i2c_client *client,
- struct indycam_control *ctrl)
+static int indycam_g_ctrl(struct v4l2_subdev *sd, struct v4l2_control *ctrl)
{
- struct indycam *camera = i2c_get_clientdata(client);
+ struct indycam *camera = to_indycam(sd);
u8 reg;
int ret = 0;
- switch (ctrl->type) {
- case INDYCAM_CONTROL_AGC:
- case INDYCAM_CONTROL_AWB:
- ret = indycam_read_reg(client, INDYCAM_REG_CONTROL, &reg);
+ switch (ctrl->id) {
+ case V4L2_CID_AUTOGAIN:
+ case V4L2_CID_AUTO_WHITE_BALANCE:
+ ret = indycam_read_reg(sd, INDYCAM_REG_CONTROL, &reg);
if (ret)
return -EIO;
- if (ctrl->type == INDYCAM_CONTROL_AGC)
+ if (ctrl->id == V4L2_CID_AUTOGAIN)
ctrl->value = (reg & INDYCAM_CONTROL_AGCENA)
? 1 : 0;
else
ctrl->value = (reg & INDYCAM_CONTROL_AWBCTL)
? 1 : 0;
break;
- case INDYCAM_CONTROL_SHUTTER:
- ret = indycam_read_reg(client, INDYCAM_REG_SHUTTER, &reg);
+ case V4L2_CID_EXPOSURE:
+ ret = indycam_read_reg(sd, INDYCAM_REG_SHUTTER, &reg);
if (ret)
return -EIO;
ctrl->value = ((s32)reg == 0x00) ? 0xff : ((s32)reg - 1);
break;
- case INDYCAM_CONTROL_GAIN:
- ret = indycam_read_reg(client, INDYCAM_REG_GAIN, &reg);
+ case V4L2_CID_GAIN:
+ ret = indycam_read_reg(sd, INDYCAM_REG_GAIN, &reg);
if (ret)
return -EIO;
ctrl->value = (s32)reg;
break;
- case INDYCAM_CONTROL_RED_BALANCE:
- ret = indycam_read_reg(client, INDYCAM_REG_RED_BALANCE, &reg);
+ case V4L2_CID_RED_BALANCE:
+ ret = indycam_read_reg(sd, INDYCAM_REG_RED_BALANCE, &reg);
if (ret)
return -EIO;
ctrl->value = (s32)reg;
break;
- case INDYCAM_CONTROL_BLUE_BALANCE:
- ret = indycam_read_reg(client, INDYCAM_REG_BLUE_BALANCE, &reg);
+ case V4L2_CID_BLUE_BALANCE:
+ ret = indycam_read_reg(sd, INDYCAM_REG_BLUE_BALANCE, &reg);
if (ret)
return -EIO;
ctrl->value = (s32)reg;
break;
case INDYCAM_CONTROL_RED_SATURATION:
- ret = indycam_read_reg(client,
+ ret = indycam_read_reg(sd,
INDYCAM_REG_RED_SATURATION, &reg);
if (ret)
return -EIO;
ctrl->value = (s32)reg;
break;
case INDYCAM_CONTROL_BLUE_SATURATION:
- ret = indycam_read_reg(client,
+ ret = indycam_read_reg(sd,
INDYCAM_REG_BLUE_SATURATION, &reg);
if (ret)
return -EIO;
ctrl->value = (s32)reg;
break;
- case INDYCAM_CONTROL_GAMMA:
+ case V4L2_CID_GAMMA:
if (camera->version == CAMERA_VERSION_MOOSE) {
- ret = indycam_read_reg(client,
+ ret = indycam_read_reg(sd,
INDYCAM_REG_GAMMA, &reg);
if (ret)
return -EIO;
@@ -213,21 +224,20 @@ static int indycam_get_control(struct i2c_client *client,
return ret;
}
-static int indycam_set_control(struct i2c_client *client,
- struct indycam_control *ctrl)
+static int indycam_s_ctrl(struct v4l2_subdev *sd, struct v4l2_control *ctrl)
{
- struct indycam *camera = i2c_get_clientdata(client);
+ struct indycam *camera = to_indycam(sd);
u8 reg;
int ret = 0;
- switch (ctrl->type) {
- case INDYCAM_CONTROL_AGC:
- case INDYCAM_CONTROL_AWB:
- ret = indycam_read_reg(client, INDYCAM_REG_CONTROL, &reg);
+ switch (ctrl->id) {
+ case V4L2_CID_AUTOGAIN:
+ case V4L2_CID_AUTO_WHITE_BALANCE:
+ ret = indycam_read_reg(sd, INDYCAM_REG_CONTROL, &reg);
if (ret)
break;
- if (ctrl->type == INDYCAM_CONTROL_AGC) {
+ if (ctrl->id == V4L2_CID_AUTOGAIN) {
if (ctrl->value)
reg |= INDYCAM_CONTROL_AGCENA;
else
@@ -239,34 +249,34 @@ static int indycam_set_control(struct i2c_client *client,
reg &= ~INDYCAM_CONTROL_AWBCTL;
}
- ret = indycam_write_reg(client, INDYCAM_REG_CONTROL, reg);
+ ret = indycam_write_reg(sd, INDYCAM_REG_CONTROL, reg);
break;
- case INDYCAM_CONTROL_SHUTTER:
+ case V4L2_CID_EXPOSURE:
reg = (ctrl->value == 0xff) ? 0x00 : (ctrl->value + 1);
- ret = indycam_write_reg(client, INDYCAM_REG_SHUTTER, reg);
+ ret = indycam_write_reg(sd, INDYCAM_REG_SHUTTER, reg);
break;
- case INDYCAM_CONTROL_GAIN:
- ret = indycam_write_reg(client, INDYCAM_REG_GAIN, ctrl->value);
+ case V4L2_CID_GAIN:
+ ret = indycam_write_reg(sd, INDYCAM_REG_GAIN, ctrl->value);
break;
- case INDYCAM_CONTROL_RED_BALANCE:
- ret = indycam_write_reg(client, INDYCAM_REG_RED_BALANCE,
+ case V4L2_CID_RED_BALANCE:
+ ret = indycam_write_reg(sd, INDYCAM_REG_RED_BALANCE,
ctrl->value);
break;
- case INDYCAM_CONTROL_BLUE_BALANCE:
- ret = indycam_write_reg(client, INDYCAM_REG_BLUE_BALANCE,
+ case V4L2_CID_BLUE_BALANCE:
+ ret = indycam_write_reg(sd, INDYCAM_REG_BLUE_BALANCE,
ctrl->value);
break;
case INDYCAM_CONTROL_RED_SATURATION:
- ret = indycam_write_reg(client, INDYCAM_REG_RED_SATURATION,
+ ret = indycam_write_reg(sd, INDYCAM_REG_RED_SATURATION,
ctrl->value);
break;
case INDYCAM_CONTROL_BLUE_SATURATION:
- ret = indycam_write_reg(client, INDYCAM_REG_BLUE_SATURATION,
+ ret = indycam_write_reg(sd, INDYCAM_REG_BLUE_SATURATION,
ctrl->value);
break;
- case INDYCAM_CONTROL_GAMMA:
+ case V4L2_CID_GAMMA:
if (camera->version == CAMERA_VERSION_MOOSE) {
- ret = indycam_write_reg(client, INDYCAM_REG_GAMMA,
+ ret = indycam_write_reg(sd, INDYCAM_REG_GAMMA,
ctrl->value);
}
break;
@@ -279,192 +289,107 @@ static int indycam_set_control(struct i2c_client *client,
/* I2C-interface */
-static int indycam_attach(struct i2c_adapter *adap, int addr, int kind)
+static int indycam_g_chip_ident(struct v4l2_subdev *sd,
+ struct v4l2_dbg_chip_ident *chip)
+{
+ struct i2c_client *client = v4l2_get_subdevdata(sd);
+ struct indycam *camera = to_indycam(sd);
+
+ return v4l2_chip_ident_i2c_client(client, chip, V4L2_IDENT_INDYCAM,
+ camera->version);
+}
+
+/* ----------------------------------------------------------------------- */
+
+static const struct v4l2_subdev_core_ops indycam_core_ops = {
+ .g_chip_ident = indycam_g_chip_ident,
+ .g_ctrl = indycam_g_ctrl,
+ .s_ctrl = indycam_s_ctrl,
+};
+
+static const struct v4l2_subdev_ops indycam_ops = {
+ .core = &indycam_core_ops,
+};
+
+static int indycam_probe(struct i2c_client *client,
+ const struct i2c_device_id *id)
{
int err = 0;
struct indycam *camera;
- struct i2c_client *client;
+ struct v4l2_subdev *sd;
- printk(KERN_INFO "SGI IndyCam driver version %s\n",
- INDYCAM_MODULE_VERSION);
+ v4l_info(client, "chip found @ 0x%x (%s)\n",
+ client->addr << 1, client->adapter->name);
- client = kzalloc(sizeof(struct i2c_client), GFP_KERNEL);
- if (!client)
- return -ENOMEM;
camera = kzalloc(sizeof(struct indycam), GFP_KERNEL);
- if (!camera) {
- err = -ENOMEM;
- goto out_free_client;
- }
-
- client->addr = addr;
- client->adapter = adap;
- client->driver = &i2c_driver_indycam;
- client->flags = 0;
- strcpy(client->name, "IndyCam client");
- i2c_set_clientdata(client, camera);
-
- camera->client = client;
+ if (!camera)
+ return -ENOMEM;
- err = i2c_attach_client(client);
- if (err)
- goto out_free_camera;
+ sd = &camera->sd;
+ v4l2_i2c_subdev_init(sd, client, &indycam_ops);
camera->version = i2c_smbus_read_byte_data(client,
INDYCAM_REG_VERSION);
if (camera->version != CAMERA_VERSION_INDY &&
camera->version != CAMERA_VERSION_MOOSE) {
- err = -ENODEV;
- goto out_detach_client;
+ kfree(camera);
+ return -ENODEV;
}
+
printk(KERN_INFO "IndyCam v%d.%d detected\n",
INDYCAM_VERSION_MAJOR(camera->version),
INDYCAM_VERSION_MINOR(camera->version));
- indycam_regdump(client);
+ indycam_regdump(sd);
// initialize
- err = indycam_write_block(client, 0, sizeof(initseq), (u8 *)&initseq);
+ err = indycam_write_block(sd, 0, sizeof(initseq), (u8 *)&initseq);
if (err) {
printk(KERN_ERR "IndyCam initialization failed\n");
- err = -EIO;
- goto out_detach_client;
+ kfree(camera);
+ return -EIO;
}
- indycam_regdump(client);
+ indycam_regdump(sd);
// white balance
- err = indycam_write_reg(client, INDYCAM_REG_CONTROL,
+ err = indycam_write_reg(sd, INDYCAM_REG_CONTROL,
INDYCAM_CONTROL_AGCENA | INDYCAM_CONTROL_AWBCTL);
if (err) {
printk(KERN_ERR "IndyCam: White balancing camera failed\n");
- err = -EIO;
- goto out_detach_client;
+ kfree(camera);
+ return -EIO;
}
- indycam_regdump(client);
+ indycam_regdump(sd);
printk(KERN_INFO "IndyCam initialized\n");
return 0;
-
-out_detach_client:
- i2c_detach_client(client);
-out_free_camera:
- kfree(camera);
-out_free_client:
- kfree(client);
- return err;
-}
-
-static int indycam_probe(struct i2c_adapter *adap)
-{
- /* Indy specific crap */
- if (adap->id == I2C_HW_SGI_VINO)
- return indycam_attach(adap, INDYCAM_ADDR, 0);
- /* Feel free to add probe here :-) */
- return -ENODEV;
}
-static int indycam_detach(struct i2c_client *client)
+static int indycam_remove(struct i2c_client *client)
{
- struct indycam *camera = i2c_get_clientdata(client);
+ struct v4l2_subdev *sd = i2c_get_clientdata(client);
- i2c_detach_client(client);
- kfree(camera);
- kfree(client);
+ v4l2_device_unregister_subdev(sd);
+ kfree(to_indycam(sd));
return 0;
}
-static int indycam_command(struct i2c_client *client, unsigned int cmd,
- void *arg)
-{
- // struct indycam *camera = i2c_get_clientdata(client);
-
- /* The old video_decoder interface just isn't enough,
- * so we'll use some custom commands. */
- switch (cmd) {
- case DECODER_GET_CAPABILITIES: {
- struct video_decoder_capability *cap = arg;
-
- cap->flags = VIDEO_DECODER_NTSC;
- cap->inputs = 1;
- cap->outputs = 1;
- break;
- }
- case DECODER_GET_STATUS: {
- int *iarg = arg;
-
- *iarg = DECODER_STATUS_GOOD | DECODER_STATUS_NTSC |
- DECODER_STATUS_COLOR;
- break;
- }
- case DECODER_SET_NORM: {
- int *iarg = arg;
-
- switch (*iarg) {
- case VIDEO_MODE_NTSC:
- break;
- default:
- return -EINVAL;
- }
- break;
- }
- case DECODER_SET_INPUT: {
- int *iarg = arg;
-
- if (*iarg != 0)
- return -EINVAL;
- break;
- }
- case DECODER_SET_OUTPUT: {
- int *iarg = arg;
-
- if (*iarg != 0)
- return -EINVAL;
- break;
- }
- case DECODER_ENABLE_OUTPUT: {
- /* Always enabled */
- break;
- }
- case DECODER_SET_PICTURE: {
- // struct video_picture *pic = arg;
- /* TODO: convert values for indycam_set_controls() */
- break;
- }
- case DECODER_INDYCAM_GET_CONTROL: {
- return indycam_get_control(client, arg);
- }
- case DECODER_INDYCAM_SET_CONTROL: {
- return indycam_set_control(client, arg);
- }
- default:
- return -EINVAL;
- }
-
- return 0;
-}
-
-static struct i2c_driver i2c_driver_indycam = {
- .driver = {
- .name = "indycam",
- },
- .id = I2C_DRIVERID_INDYCAM,
- .attach_adapter = indycam_probe,
- .detach_client = indycam_detach,
- .command = indycam_command,
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 26)
+static const struct i2c_device_id indycam_id[] = {
+ { "indycam", 0 },
+ { }
};
+MODULE_DEVICE_TABLE(i2c, indycam_id);
-static int __init indycam_init(void)
-{
- return i2c_add_driver(&i2c_driver_indycam);
-}
-
-static void __exit indycam_exit(void)
-{
- i2c_del_driver(&i2c_driver_indycam);
-}
-
-module_init(indycam_init);
-module_exit(indycam_exit);
+#endif
+static struct v4l2_i2c_driver_data v4l2_i2c_data = {
+ .name = "indycam",
+ .probe = indycam_probe,
+ .remove = indycam_remove,
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 26)
+ .id_table = indycam_id,
+#endif
+};
diff --git a/linux/drivers/media/video/indycam.h b/linux/drivers/media/video/indycam.h
index e6ee82063..881f21c47 100644
--- a/linux/drivers/media/video/indycam.h
+++ b/linux/drivers/media/video/indycam.h
@@ -87,22 +87,7 @@
/* Driver interface definitions */
-#define INDYCAM_CONTROL_AGC 0 /* boolean */
-#define INDYCAM_CONTROL_AWB 1 /* boolean */
-#define INDYCAM_CONTROL_SHUTTER 2
-#define INDYCAM_CONTROL_GAIN 3
-#define INDYCAM_CONTROL_RED_BALANCE 4
-#define INDYCAM_CONTROL_BLUE_BALANCE 5
-#define INDYCAM_CONTROL_RED_SATURATION 6
-#define INDYCAM_CONTROL_BLUE_SATURATION 7
-#define INDYCAM_CONTROL_GAMMA 8
-
-struct indycam_control {
- u8 type;
- s32 value;
-};
-
-#define DECODER_INDYCAM_GET_CONTROL _IOR('d', 193, struct indycam_control)
-#define DECODER_INDYCAM_SET_CONTROL _IOW('d', 194, struct indycam_control)
+#define INDYCAM_CONTROL_RED_SATURATION (V4L2_CID_PRIVATE_BASE + 0)
+#define INDYCAM_CONTROL_BLUE_SATURATION (V4L2_CID_PRIVATE_BASE + 1)
#endif
diff --git a/linux/drivers/media/video/saa7191.c b/linux/drivers/media/video/saa7191.c
index c4f169c95..9df505e0f 100644
--- a/linux/drivers/media/video/saa7191.c
+++ b/linux/drivers/media/video/saa7191.c
@@ -19,9 +19,11 @@
#include <linux/mm.h>
#include <linux/slab.h>
-#include <linux/videodev.h>
-#include <linux/video_decoder.h>
+#include <linux/videodev2.h>
#include <linux/i2c.h>
+#include <media/v4l2-device.h>
+#include <media/v4l2-chip-ident.h>
+#include <media/v4l2-i2c-drv.h>
#include "compat.h"
#include "saa7191.h"
@@ -33,6 +35,12 @@ MODULE_VERSION(SAA7191_MODULE_VERSION);
MODULE_AUTHOR("Mikael Nousiainen <tmnousia@cc.hut.fi>");
MODULE_LICENSE("GPL");
+#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 22)
+static unsigned short normal_i2c[] = { 0x8a >> 1, 0x8e >> 1, I2C_CLIENT_END };
+
+I2C_CLIENT_INSMOD;
+#endif
+
// #define SAA7191_DEBUG
#ifdef SAA7191_DEBUG
@@ -45,17 +53,20 @@ MODULE_LICENSE("GPL");
#define SAA7191_SYNC_DELAY 100 /* milliseconds */
struct saa7191 {
- struct i2c_client *client;
+ struct v4l2_subdev sd;
/* the register values are stored here as the actual
* I2C-registers are write-only */
u8 reg[25];
int input;
- int norm;
+ v4l2_std_id norm;
};
-static struct i2c_driver i2c_driver_saa7191;
+static inline struct saa7191 *to_saa7191(struct v4l2_subdev *sd)
+{
+ return container_of(sd, struct saa7191, sd);
+}
static const u8 initseq[] = {
0, /* Subaddress */
@@ -101,15 +112,14 @@ static const u8 initseq[] = {
/* SAA7191 register handling */
-static u8 saa7191_read_reg(struct i2c_client *client,
- u8 reg)
+static u8 saa7191_read_reg(struct v4l2_subdev *sd, u8 reg)
{
- return ((struct saa7191 *)i2c_get_clientdata(client))->reg[reg];
+ return to_saa7191(sd)->reg[reg];
}
-static int saa7191_read_status(struct i2c_client *client,
- u8 *value)
+static int saa7191_read_status(struct v4l2_subdev *sd, u8 *value)
{
+ struct i2c_client *client = v4l2_get_subdevdata(sd);
int ret;
ret = i2c_master_recv(client, value, 1);
@@ -122,21 +132,23 @@ static int saa7191_read_status(struct i2c_client *client,
}
-static int saa7191_write_reg(struct i2c_client *client, u8 reg,
- u8 value)
+static int saa7191_write_reg(struct v4l2_subdev *sd, u8 reg, u8 value)
{
- ((struct saa7191 *)i2c_get_clientdata(client))->reg[reg] = value;
+ struct i2c_client *client = v4l2_get_subdevdata(sd);
+
+ to_saa7191(sd)->reg[reg] = value;
return i2c_smbus_write_byte_data(client, reg, value);
}
/* the first byte of data must be the first subaddress number (register) */
-static int saa7191_write_block(struct i2c_client *client,
+static int saa7191_write_block(struct v4l2_subdev *sd,
u8 length, const u8 *data)
{
+ struct i2c_client *client = v4l2_get_subdevdata(sd);
+ struct saa7191 *decoder = to_saa7191(sd);
int i;
int ret;
- struct saa7191 *decoder = (struct saa7191 *)i2c_get_clientdata(client);
for (i = 0; i < (length - 1); i++) {
decoder->reg[data[0] + i] = data[i + 1];
}
@@ -153,14 +165,15 @@ static int saa7191_write_block(struct i2c_client *client,
/* Helper functions */
-static int saa7191_set_input(struct i2c_client *client, int input)
+static int saa7191_s_routing(struct v4l2_subdev *sd,
+ const struct v4l2_routing *route)
{
- struct saa7191 *decoder = i2c_get_clientdata(client);
- u8 luma = saa7191_read_reg(client, SAA7191_REG_LUMA);
- u8 iock = saa7191_read_reg(client, SAA7191_REG_IOCK);
+ struct saa7191 *decoder = to_saa7191(sd);
+ u8 luma = saa7191_read_reg(sd, SAA7191_REG_LUMA);
+ u8 iock = saa7191_read_reg(sd, SAA7191_REG_IOCK);
int err;
- switch (input) {
+ switch (route->input) {
case SAA7191_INPUT_COMPOSITE: /* Set Composite input */
iock &= ~(SAA7191_IOCK_CHRS | SAA7191_IOCK_GPSW1
| SAA7191_IOCK_GPSW2);
@@ -176,54 +189,50 @@ static int saa7191_set_input(struct i2c_client *client, int input)
return -EINVAL;
}
- err = saa7191_write_reg(client, SAA7191_REG_LUMA, luma);
+ err = saa7191_write_reg(sd, SAA7191_REG_LUMA, luma);
if (err)
return -EIO;
- err = saa7191_write_reg(client, SAA7191_REG_IOCK, iock);
+ err = saa7191_write_reg(sd, SAA7191_REG_IOCK, iock);
if (err)
return -EIO;
- decoder->input = input;
+ decoder->input = route->input;
return 0;
}
-static int saa7191_set_norm(struct i2c_client *client, int norm)
+static int saa7191_s_std(struct v4l2_subdev *sd, v4l2_std_id norm)
{
- struct saa7191 *decoder = i2c_get_clientdata(client);
- u8 stdc = saa7191_read_reg(client, SAA7191_REG_STDC);
- u8 ctl3 = saa7191_read_reg(client, SAA7191_REG_CTL3);
- u8 chcv = saa7191_read_reg(client, SAA7191_REG_CHCV);
+ struct saa7191 *decoder = to_saa7191(sd);
+ u8 stdc = saa7191_read_reg(sd, SAA7191_REG_STDC);
+ u8 ctl3 = saa7191_read_reg(sd, SAA7191_REG_CTL3);
+ u8 chcv = saa7191_read_reg(sd, SAA7191_REG_CHCV);
int err;
- switch(norm) {
- case SAA7191_NORM_PAL:
+ if (norm & V4L2_STD_PAL) {
stdc &= ~SAA7191_STDC_SECS;
ctl3 &= ~(SAA7191_CTL3_AUFD | SAA7191_CTL3_FSEL);
chcv = SAA7191_CHCV_PAL;
- break;
- case SAA7191_NORM_NTSC:
+ } else if (norm & V4L2_STD_NTSC) {
stdc &= ~SAA7191_STDC_SECS;
ctl3 &= ~SAA7191_CTL3_AUFD;
ctl3 |= SAA7191_CTL3_FSEL;
chcv = SAA7191_CHCV_NTSC;
- break;
- case SAA7191_NORM_SECAM:
+ } else if (norm & V4L2_STD_SECAM) {
stdc |= SAA7191_STDC_SECS;
ctl3 &= ~(SAA7191_CTL3_AUFD | SAA7191_CTL3_FSEL);
chcv = SAA7191_CHCV_PAL;
- break;
- default:
+ } else {
return -EINVAL;
}
- err = saa7191_write_reg(client, SAA7191_REG_CTL3, ctl3);
+ err = saa7191_write_reg(sd, SAA7191_REG_CTL3, ctl3);
if (err)
return -EIO;
- err = saa7191_write_reg(client, SAA7191_REG_STDC, stdc);
+ err = saa7191_write_reg(sd, SAA7191_REG_STDC, stdc);
if (err)
return -EIO;
- err = saa7191_write_reg(client, SAA7191_REG_CHCV, chcv);
+ err = saa7191_write_reg(sd, SAA7191_REG_CHCV, chcv);
if (err)
return -EIO;
@@ -231,19 +240,19 @@ static int saa7191_set_norm(struct i2c_client *client, int norm)
dprintk("ctl3: %02x stdc: %02x chcv: %02x\n", ctl3,
stdc, chcv);
- dprintk("norm: %d\n", norm);
+ dprintk("norm: %llx\n", norm);
return 0;
}
-static int saa7191_wait_for_signal(struct i2c_client *client, u8 *status)
+static int saa7191_wait_for_signal(struct v4l2_subdev *sd, u8 *status)
{
int i = 0;
dprintk("Checking for signal...\n");
for (i = 0; i < SAA7191_SYNC_COUNT; i++) {
- if (saa7191_read_status(client, status))
+ if (saa7191_read_status(sd, status))
return -EIO;
if (((*status) & SAA7191_STATUS_HLCK) == 0) {
@@ -259,31 +268,34 @@ static int saa7191_wait_for_signal(struct i2c_client *client, u8 *status)
return -EBUSY;
}
-static int saa7191_autodetect_norm_extended(struct i2c_client *client)
+static int saa7191_querystd(struct v4l2_subdev *sd, v4l2_std_id *norm)
{
- u8 stdc = saa7191_read_reg(client, SAA7191_REG_STDC);
- u8 ctl3 = saa7191_read_reg(client, SAA7191_REG_CTL3);
+ struct saa7191 *decoder = to_saa7191(sd);
+ u8 stdc = saa7191_read_reg(sd, SAA7191_REG_STDC);
+ u8 ctl3 = saa7191_read_reg(sd, SAA7191_REG_CTL3);
u8 status;
+ v4l2_std_id old_norm = decoder->norm;
int err = 0;
dprintk("SAA7191 extended signal auto-detection...\n");
+ *norm = V4L2_STD_NTSC | V4L2_STD_PAL | V4L2_STD_SECAM;
stdc &= ~SAA7191_STDC_SECS;
ctl3 &= ~(SAA7191_CTL3_FSEL);
- err = saa7191_write_reg(client, SAA7191_REG_STDC, stdc);
+ err = saa7191_write_reg(sd, SAA7191_REG_STDC, stdc);
if (err) {
err = -EIO;
goto out;
}
- err = saa7191_write_reg(client, SAA7191_REG_CTL3, ctl3);
+ err = saa7191_write_reg(sd, SAA7191_REG_CTL3, ctl3);
if (err) {
err = -EIO;
goto out;
}
ctl3 |= SAA7191_CTL3_AUFD;
- err = saa7191_write_reg(client, SAA7191_REG_CTL3, ctl3);
+ err = saa7191_write_reg(sd, SAA7191_REG_CTL3, ctl3);
if (err) {
err = -EIO;
goto out;
@@ -291,53 +303,54 @@ static int saa7191_autodetect_norm_extended(struct i2c_client *client)
msleep(SAA7191_SYNC_DELAY);
- err = saa7191_wait_for_signal(client, &status);
+ err = saa7191_wait_for_signal(sd, &status);
if (err)
goto out;
if (status & SAA7191_STATUS_FIDT) {
/* 60Hz signal -> NTSC */
dprintk("60Hz signal: NTSC\n");
- return saa7191_set_norm(client, SAA7191_NORM_NTSC);
+ *norm = V4L2_STD_NTSC;
+ return 0;
}
/* 50Hz signal */
dprintk("50Hz signal: Trying PAL...\n");
/* try PAL first */
- err = saa7191_set_norm(client, SAA7191_NORM_PAL);
+ err = saa7191_s_std(sd, V4L2_STD_PAL);
if (err)
goto out;
msleep(SAA7191_SYNC_DELAY);
- err = saa7191_wait_for_signal(client, &status);
+ err = saa7191_wait_for_signal(sd, &status);
if (err)
goto out;
/* not 50Hz ? */
if (status & SAA7191_STATUS_FIDT) {
dprintk("No 50Hz signal\n");
- err = -EAGAIN;
- goto out;
+ saa7191_s_std(sd, old_norm);
+ return -EAGAIN;
}
if (status & SAA7191_STATUS_CODE) {
dprintk("PAL\n");
- return 0;
+ *norm = V4L2_STD_PAL;
+ return saa7191_s_std(sd, old_norm);
}
dprintk("No color detected with PAL - Trying SECAM...\n");
/* no color detected ? -> try SECAM */
- err = saa7191_set_norm(client,
- SAA7191_NORM_SECAM);
+ err = saa7191_s_std(sd, V4L2_STD_SECAM);
if (err)
goto out;
msleep(SAA7191_SYNC_DELAY);
- err = saa7191_wait_for_signal(client, &status);
+ err = saa7191_wait_for_signal(sd, &status);
if (err)
goto out;
@@ -351,32 +364,17 @@ static int saa7191_autodetect_norm_extended(struct i2c_client *client)
if (status & SAA7191_STATUS_CODE) {
/* Color detected -> SECAM */
dprintk("SECAM\n");
- return 0;
+ *norm = V4L2_STD_SECAM;
+ return saa7191_s_std(sd, old_norm);
}
dprintk("No color detected with SECAM - Going back to PAL.\n");
- /* still no color detected ?
- * -> set norm back to PAL */
- err = saa7191_set_norm(client,
- SAA7191_NORM_PAL);
- if (err)
- goto out;
-
out:
- ctl3 = saa7191_read_reg(client, SAA7191_REG_CTL3);
- if (ctl3 & SAA7191_CTL3_AUFD) {
- ctl3 &= ~(SAA7191_CTL3_AUFD);
- err = saa7191_write_reg(client, SAA7191_REG_CTL3, ctl3);
- if (err) {
- err = -EIO;
- }
- }
-
- return err;
+ return saa7191_s_std(sd, old_norm);
}
-static int saa7191_autodetect_norm(struct i2c_client *client)
+static int saa7191_autodetect_norm(struct v4l2_subdev *sd)
{
u8 status;
@@ -384,7 +382,7 @@ static int saa7191_autodetect_norm(struct i2c_client *client)
dprintk("Reading status...\n");
- if (saa7191_read_status(client, &status))
+ if (saa7191_read_status(sd, &status))
return -EIO;
dprintk("Checking for signal...\n");
@@ -400,26 +398,25 @@ static int saa7191_autodetect_norm(struct i2c_client *client)
if (status & SAA7191_STATUS_FIDT) {
/* 60hz signal -> NTSC */
dprintk("NTSC\n");
- return saa7191_set_norm(client, SAA7191_NORM_NTSC);
+ return saa7191_s_std(sd, V4L2_STD_NTSC);
} else {
/* 50hz signal -> PAL */
dprintk("PAL\n");
- return saa7191_set_norm(client, SAA7191_NORM_PAL);
+ return saa7191_s_std(sd, V4L2_STD_PAL);
}
}
-static int saa7191_get_control(struct i2c_client *client,
- struct saa7191_control *ctrl)
+static int saa7191_g_ctrl(struct v4l2_subdev *sd, struct v4l2_control *ctrl)
{
u8 reg;
int ret = 0;
- switch (ctrl->type) {
+ switch (ctrl->id) {
case SAA7191_CONTROL_BANDPASS:
case SAA7191_CONTROL_BANDPASS_WEIGHT:
case SAA7191_CONTROL_CORING:
- reg = saa7191_read_reg(client, SAA7191_REG_LUMA);
- switch (ctrl->type) {
+ reg = saa7191_read_reg(sd, SAA7191_REG_LUMA);
+ switch (ctrl->id) {
case SAA7191_CONTROL_BANDPASS:
ctrl->value = ((s32)reg & SAA7191_LUMA_BPSS_MASK)
>> SAA7191_LUMA_BPSS_SHIFT;
@@ -436,15 +433,15 @@ static int saa7191_get_control(struct i2c_client *client,
break;
case SAA7191_CONTROL_FORCE_COLOUR:
case SAA7191_CONTROL_CHROMA_GAIN:
- reg = saa7191_read_reg(client, SAA7191_REG_GAIN);
- if (ctrl->type == SAA7191_CONTROL_FORCE_COLOUR)
+ reg = saa7191_read_reg(sd, SAA7191_REG_GAIN);
+ if (ctrl->id == SAA7191_CONTROL_FORCE_COLOUR)
ctrl->value = ((s32)reg & SAA7191_GAIN_COLO) ? 1 : 0;
else
ctrl->value = ((s32)reg & SAA7191_GAIN_LFIS_MASK)
>> SAA7191_GAIN_LFIS_SHIFT;
break;
- case SAA7191_CONTROL_HUE:
- reg = saa7191_read_reg(client, SAA7191_REG_HUEC);
+ case V4L2_CID_HUE:
+ reg = saa7191_read_reg(sd, SAA7191_REG_HUEC);
if (reg < 0x80)
reg += 0x80;
else
@@ -452,18 +449,18 @@ static int saa7191_get_control(struct i2c_client *client,
ctrl->value = (s32)reg;
break;
case SAA7191_CONTROL_VTRC:
- reg = saa7191_read_reg(client, SAA7191_REG_STDC);
+ reg = saa7191_read_reg(sd, SAA7191_REG_STDC);
ctrl->value = ((s32)reg & SAA7191_STDC_VTRC) ? 1 : 0;
break;
case SAA7191_CONTROL_LUMA_DELAY:
- reg = saa7191_read_reg(client, SAA7191_REG_CTL3);
+ reg = saa7191_read_reg(sd, SAA7191_REG_CTL3);
ctrl->value = ((s32)reg & SAA7191_CTL3_YDEL_MASK)
>> SAA7191_CTL3_YDEL_SHIFT;
if (ctrl->value >= 4)
ctrl->value -= 8;
break;
case SAA7191_CONTROL_VNR:
- reg = saa7191_read_reg(client, SAA7191_REG_CTL4);
+ reg = saa7191_read_reg(sd, SAA7191_REG_CTL4);
ctrl->value = ((s32)reg & SAA7191_CTL4_VNOI_MASK)
>> SAA7191_CTL4_VNOI_SHIFT;
break;
@@ -474,18 +471,17 @@ static int saa7191_get_control(struct i2c_client *client,
return ret;
}
-static int saa7191_set_control(struct i2c_client *client,
- struct saa7191_control *ctrl)
+static int saa7191_s_ctrl(struct v4l2_subdev *sd, struct v4l2_control *ctrl)
{
u8 reg;
int ret = 0;
- switch (ctrl->type) {
+ switch (ctrl->id) {
case SAA7191_CONTROL_BANDPASS:
case SAA7191_CONTROL_BANDPASS_WEIGHT:
case SAA7191_CONTROL_CORING:
- reg = saa7191_read_reg(client, SAA7191_REG_LUMA);
- switch (ctrl->type) {
+ reg = saa7191_read_reg(sd, SAA7191_REG_LUMA);
+ switch (ctrl->id) {
case SAA7191_CONTROL_BANDPASS:
reg &= ~SAA7191_LUMA_BPSS_MASK;
reg |= (ctrl->value << SAA7191_LUMA_BPSS_SHIFT)
@@ -502,12 +498,12 @@ static int saa7191_set_control(struct i2c_client *client,
& SAA7191_LUMA_CORI_MASK;
break;
}
- ret = saa7191_write_reg(client, SAA7191_REG_LUMA, reg);
+ ret = saa7191_write_reg(sd, SAA7191_REG_LUMA, reg);
break;
case SAA7191_CONTROL_FORCE_COLOUR:
case SAA7191_CONTROL_CHROMA_GAIN:
- reg = saa7191_read_reg(client, SAA7191_REG_GAIN);
- if (ctrl->type == SAA7191_CONTROL_FORCE_COLOUR) {
+ reg = saa7191_read_reg(sd, SAA7191_REG_GAIN);
+ if (ctrl->id == SAA7191_CONTROL_FORCE_COLOUR) {
if (ctrl->value)
reg |= SAA7191_GAIN_COLO;
else
@@ -517,41 +513,41 @@ static int saa7191_set_control(struct i2c_client *client,
reg |= (ctrl->value << SAA7191_GAIN_LFIS_SHIFT)
& SAA7191_GAIN_LFIS_MASK;
}
- ret = saa7191_write_reg(client, SAA7191_REG_GAIN, reg);
+ ret = saa7191_write_reg(sd, SAA7191_REG_GAIN, reg);
break;
- case SAA7191_CONTROL_HUE:
+ case V4L2_CID_HUE:
reg = ctrl->value & 0xff;
if (reg < 0x80)
reg += 0x80;
else
reg -= 0x80;
- ret = saa7191_write_reg(client, SAA7191_REG_HUEC, reg);
+ ret = saa7191_write_reg(sd, SAA7191_REG_HUEC, reg);
break;
case SAA7191_CONTROL_VTRC:
- reg = saa7191_read_reg(client, SAA7191_REG_STDC);
+ reg = saa7191_read_reg(sd, SAA7191_REG_STDC);
if (ctrl->value)
reg |= SAA7191_STDC_VTRC;
else
reg &= ~SAA7191_STDC_VTRC;
- ret = saa7191_write_reg(client, SAA7191_REG_STDC, reg);
+ ret = saa7191_write_reg(sd, SAA7191_REG_STDC, reg);
break;
case SAA7191_CONTROL_LUMA_DELAY: {
s32 value = ctrl->value;
if (value < 0)
value += 8;
- reg = saa7191_read_reg(client, SAA7191_REG_CTL3);
+ reg = saa7191_read_reg(sd, SAA7191_REG_CTL3);
reg &= ~SAA7191_CTL3_YDEL_MASK;
reg |= (value << SAA7191_CTL3_YDEL_SHIFT)
& SAA7191_CTL3_YDEL_MASK;
- ret = saa7191_write_reg(client, SAA7191_REG_CTL3, reg);
+ ret = saa7191_write_reg(sd, SAA7191_REG_CTL3, reg);
break;
}
case SAA7191_CONTROL_VNR:
- reg = saa7191_read_reg(client, SAA7191_REG_CTL4);
+ reg = saa7191_read_reg(sd, SAA7191_REG_CTL4);
reg &= ~SAA7191_CTL4_VNOI_MASK;
reg |= (ctrl->value << SAA7191_CTL4_VNOI_SHIFT)
& SAA7191_CTL4_VNOI_MASK;
- ret = saa7191_write_reg(client, SAA7191_REG_CTL4, reg);
+ ret = saa7191_write_reg(sd, SAA7191_REG_CTL4, reg);
break;
default:
ret = -EINVAL;
@@ -562,247 +558,111 @@ static int saa7191_set_control(struct i2c_client *client,
/* I2C-interface */
-static int saa7191_attach(struct i2c_adapter *adap, int addr, int kind)
+static int saa7191_g_input_status(struct v4l2_subdev *sd, u32 *status)
{
- int err = 0;
- struct saa7191 *decoder;
- struct i2c_client *client;
-
- printk(KERN_INFO "Philips SAA7191 driver version %s\n",
- SAA7191_MODULE_VERSION);
-
- client = kzalloc(sizeof(*client), GFP_KERNEL);
- if (!client)
- return -ENOMEM;
- decoder = kzalloc(sizeof(*decoder), GFP_KERNEL);
- if (!decoder) {
- err = -ENOMEM;
- goto out_free_client;
- }
-
- client->addr = addr;
- client->adapter = adap;
- client->driver = &i2c_driver_saa7191;
- client->flags = 0;
- strcpy(client->name, "saa7191 client");
- i2c_set_clientdata(client, decoder);
-
- decoder->client = client;
-
- err = i2c_attach_client(client);
- if (err)
- goto out_free_decoder;
-
- err = saa7191_write_block(client, sizeof(initseq), initseq);
- if (err) {
- printk(KERN_ERR "SAA7191 initialization failed\n");
- goto out_detach_client;
- }
-
- printk(KERN_INFO "SAA7191 initialized\n");
-
- decoder->input = SAA7191_INPUT_COMPOSITE;
- decoder->norm = SAA7191_NORM_PAL;
-
- err = saa7191_autodetect_norm(client);
- if (err && (err != -EBUSY)) {
- printk(KERN_ERR "SAA7191: Signal auto-detection failed\n");
- }
+ u8 status_reg;
+ int res = V4L2_IN_ST_NO_SIGNAL;
+ if (saa7191_read_status(sd, &status_reg))
+ return -EIO;
+ if ((status_reg & SAA7191_STATUS_HLCK) == 0)
+ res = 0;
+ if (!(status_reg & SAA7191_STATUS_CODE))
+ res |= V4L2_IN_ST_NO_COLOR;
+ *status = res;
return 0;
-
-out_detach_client:
- i2c_detach_client(client);
-out_free_decoder:
- kfree(decoder);
-out_free_client:
- kfree(client);
- return err;
}
-static int saa7191_probe(struct i2c_adapter *adap)
-{
- /* Always connected to VINO */
- if (adap->id == I2C_HW_SGI_VINO)
- return saa7191_attach(adap, SAA7191_ADDR, 0);
- /* Feel free to add probe here :-) */
- return -ENODEV;
-}
-static int saa7191_detach(struct i2c_client *client)
+static int saa7191_g_chip_ident(struct v4l2_subdev *sd,
+ struct v4l2_dbg_chip_ident *chip)
{
- struct saa7191 *decoder = i2c_get_clientdata(client);
+ struct i2c_client *client = v4l2_get_subdevdata(sd);
- i2c_detach_client(client);
- kfree(decoder);
- kfree(client);
- return 0;
+ return v4l2_chip_ident_i2c_client(client, chip, V4L2_IDENT_SAA7191, 0);
}
-static int saa7191_command(struct i2c_client *client, unsigned int cmd,
- void *arg)
-{
- struct saa7191 *decoder = i2c_get_clientdata(client);
+/* ----------------------------------------------------------------------- */
- switch (cmd) {
- case DECODER_GET_CAPABILITIES: {
- struct video_decoder_capability *cap = arg;
+static const struct v4l2_subdev_core_ops saa7191_core_ops = {
+ .g_chip_ident = saa7191_g_chip_ident,
+ .g_ctrl = saa7191_g_ctrl,
+ .s_ctrl = saa7191_s_ctrl,
+};
- cap->flags = VIDEO_DECODER_PAL | VIDEO_DECODER_NTSC |
- VIDEO_DECODER_SECAM | VIDEO_DECODER_AUTO;
- cap->inputs = (client->adapter->id == I2C_HW_SGI_VINO) ? 2 : 1;
- cap->outputs = 1;
- break;
- }
- case DECODER_GET_STATUS: {
- int *iarg = arg;
- u8 status;
- int res = 0;
+static const struct v4l2_subdev_tuner_ops saa7191_tuner_ops = {
+ .s_std = saa7191_s_std,
+};
- if (saa7191_read_status(client, &status)) {
- return -EIO;
- }
- if ((status & SAA7191_STATUS_HLCK) == 0)
- res |= DECODER_STATUS_GOOD;
- if (status & SAA7191_STATUS_CODE)
- res |= DECODER_STATUS_COLOR;
- switch (decoder->norm) {
- case SAA7191_NORM_NTSC:
- res |= DECODER_STATUS_NTSC;
- break;
- case SAA7191_NORM_PAL:
- res |= DECODER_STATUS_PAL;
- break;
- case SAA7191_NORM_SECAM:
- res |= DECODER_STATUS_SECAM;
- break;
- case SAA7191_NORM_AUTO:
- default:
- if (status & SAA7191_STATUS_FIDT)
- res |= DECODER_STATUS_NTSC;
- else
- res |= DECODER_STATUS_PAL;
- break;
- }
- *iarg = res;
- break;
- }
- case DECODER_SET_NORM: {
- int *iarg = arg;
-
- switch (*iarg) {
- case VIDEO_MODE_AUTO:
- return saa7191_autodetect_norm(client);
- case VIDEO_MODE_PAL:
- return saa7191_set_norm(client, SAA7191_NORM_PAL);
- case VIDEO_MODE_NTSC:
- return saa7191_set_norm(client, SAA7191_NORM_NTSC);
- case VIDEO_MODE_SECAM:
- return saa7191_set_norm(client, SAA7191_NORM_SECAM);
- default:
- return -EINVAL;
- }
- break;
- }
- case DECODER_SET_INPUT: {
- int *iarg = arg;
-
- switch (client->adapter->id) {
- case I2C_HW_SGI_VINO:
- return saa7191_set_input(client, *iarg);
- default:
- if (*iarg != 0)
- return -EINVAL;
- }
- break;
- }
- case DECODER_SET_OUTPUT: {
- int *iarg = arg;
+static const struct v4l2_subdev_video_ops saa7191_video_ops = {
+ .s_routing = saa7191_s_routing,
+ .querystd = saa7191_querystd,
+ .g_input_status = saa7191_g_input_status,
+};
- /* not much choice of outputs */
- if (*iarg != 0)
- return -EINVAL;
- break;
- }
- case DECODER_ENABLE_OUTPUT: {
- /* Always enabled */
- break;
- }
- case DECODER_SET_PICTURE: {
- struct video_picture *pic = arg;
- unsigned val;
- int err;
+static const struct v4l2_subdev_ops saa7191_ops = {
+ .core = &saa7191_core_ops,
+ .video = &saa7191_video_ops,
+};
- val = (pic->hue >> 8) - 0x80;
+static int saa7191_probe(struct i2c_client *client,
+ const struct i2c_device_id *id)
+{
+ int err = 0;
+ struct saa7191 *decoder;
+ struct v4l2_subdev *sd;
- err = saa7191_write_reg(client, SAA7191_REG_HUEC, val);
- if (err)
- return -EIO;
+ v4l_info(client, "chip found @ 0x%x (%s)\n",
+ client->addr << 1, client->adapter->name);
- break;
- }
- case DECODER_SAA7191_GET_STATUS: {
- struct saa7191_status *status = arg;
- u8 status_reg;
+ decoder = kzalloc(sizeof(*decoder), GFP_KERNEL);
+ if (!decoder)
+ return -ENOMEM;
- if (saa7191_read_status(client, &status_reg))
- return -EIO;
+ sd = &decoder->sd;
+ v4l2_i2c_subdev_init(sd, client, &saa7191_ops);
- status->signal = ((status_reg & SAA7191_STATUS_HLCK) == 0)
- ? 1 : 0;
- status->signal_60hz = (status_reg & SAA7191_STATUS_FIDT)
- ? 1 : 0;
- status->color = (status_reg & SAA7191_STATUS_CODE) ? 1 : 0;
+ err = saa7191_write_block(sd, sizeof(initseq), initseq);
+ if (err) {
+ printk(KERN_ERR "SAA7191 initialization failed\n");
+ kfree(decoder);
+ return err;
+ }
- status->input = decoder->input;
- status->norm = decoder->norm;
+ printk(KERN_INFO "SAA7191 initialized\n");
- break;
- }
- case DECODER_SAA7191_SET_NORM: {
- int *norm = arg;
-
- switch (*norm) {
- case SAA7191_NORM_AUTO:
- return saa7191_autodetect_norm(client);
- case SAA7191_NORM_AUTO_EXT:
- return saa7191_autodetect_norm_extended(client);
- default:
- return saa7191_set_norm(client, *norm);
- }
- }
- case DECODER_SAA7191_GET_CONTROL: {
- return saa7191_get_control(client, arg);
- }
- case DECODER_SAA7191_SET_CONTROL: {
- return saa7191_set_control(client, arg);
- }
- default:
- return -EINVAL;
- }
+ decoder->input = SAA7191_INPUT_COMPOSITE;
+ decoder->norm = V4L2_STD_PAL;
+
+ err = saa7191_autodetect_norm(sd);
+ if (err && (err != -EBUSY))
+ printk(KERN_ERR "SAA7191: Signal auto-detection failed\n");
return 0;
}
-static struct i2c_driver i2c_driver_saa7191 = {
- .driver = {
- .name = "saa7191",
- },
- .id = I2C_DRIVERID_SAA7191,
- .attach_adapter = saa7191_probe,
- .detach_client = saa7191_detach,
- .command = saa7191_command
-};
-
-static int saa7191_init(void)
+static int saa7191_remove(struct i2c_client *client)
{
- return i2c_add_driver(&i2c_driver_saa7191);
-}
+ struct v4l2_subdev *sd = i2c_get_clientdata(client);
-static void saa7191_exit(void)
-{
- i2c_del_driver(&i2c_driver_saa7191);
+ v4l2_device_unregister_subdev(sd);
+ kfree(to_saa7191(sd));
+ return 0;
}
-module_init(saa7191_init);
-module_exit(saa7191_exit);
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 26)
+static const struct i2c_device_id saa7191_id[] = {
+ { "saa7191", 0 },
+ { }
+};
+MODULE_DEVICE_TABLE(i2c, saa7191_id);
+
+#endif
+static struct v4l2_i2c_driver_data v4l2_i2c_data = {
+ .name = "saa7191",
+ .probe = saa7191_probe,
+ .remove = saa7191_remove,
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 26)
+ .id_table = saa7191_id,
+#endif
+};
diff --git a/linux/drivers/media/video/saa7191.h b/linux/drivers/media/video/saa7191.h
index a2310da19..803c74d60 100644
--- a/linux/drivers/media/video/saa7191.h
+++ b/linux/drivers/media/video/saa7191.h
@@ -176,11 +176,9 @@
#define SAA7191_INPUT_COMPOSITE 0
#define SAA7191_INPUT_SVIDEO 1
-#define SAA7191_NORM_AUTO 0
#define SAA7191_NORM_PAL 1
#define SAA7191_NORM_NTSC 2
#define SAA7191_NORM_SECAM 3
-#define SAA7191_NORM_AUTO_EXT 4 /* extended auto-detection */
struct saa7191_status {
/* 0=no signal, 1=signal detected */
@@ -232,24 +230,16 @@ struct saa7191_status {
#define SAA7191_VNR_MAX 0x03
#define SAA7191_VNR_DEFAULT 0x00
-#define SAA7191_CONTROL_BANDPASS 0
-#define SAA7191_CONTROL_BANDPASS_WEIGHT 1
-#define SAA7191_CONTROL_CORING 2
-#define SAA7191_CONTROL_FORCE_COLOUR 3 /* boolean */
-#define SAA7191_CONTROL_CHROMA_GAIN 4
-#define SAA7191_CONTROL_HUE 5
-#define SAA7191_CONTROL_VTRC 6 /* boolean */
-#define SAA7191_CONTROL_LUMA_DELAY 7
-#define SAA7191_CONTROL_VNR 8
-
-struct saa7191_control {
- u8 type;
- s32 value;
-};
+#define SAA7191_CONTROL_BANDPASS (V4L2_CID_PRIVATE_BASE + 0)
+#define SAA7191_CONTROL_BANDPASS_WEIGHT (V4L2_CID_PRIVATE_BASE + 1)
+#define SAA7191_CONTROL_CORING (V4L2_CID_PRIVATE_BASE + 2)
+#define SAA7191_CONTROL_FORCE_COLOUR (V4L2_CID_PRIVATE_BASE + 3)
+#define SAA7191_CONTROL_CHROMA_GAIN (V4L2_CID_PRIVATE_BASE + 4)
+#define SAA7191_CONTROL_VTRC (V4L2_CID_PRIVATE_BASE + 5)
+#define SAA7191_CONTROL_LUMA_DELAY (V4L2_CID_PRIVATE_BASE + 6)
+#define SAA7191_CONTROL_VNR (V4L2_CID_PRIVATE_BASE + 7)
#define DECODER_SAA7191_GET_STATUS _IOR('d', 195, struct saa7191_status)
#define DECODER_SAA7191_SET_NORM _IOW('d', 196, int)
-#define DECODER_SAA7191_GET_CONTROL _IOR('d', 197, struct saa7191_control)
-#define DECODER_SAA7191_SET_CONTROL _IOW('d', 198, struct saa7191_control)
#endif
diff --git a/linux/drivers/media/video/vino.c b/linux/drivers/media/video/vino.c
index 349ef053f..ba4e8b97d 100644
--- a/linux/drivers/media/video/vino.c
+++ b/linux/drivers/media/video/vino.c
@@ -8,6 +8,12 @@
*
* Based on the previous version of the driver for 2.4 kernels by:
* Copyright (C) 2003 Ladislav Michl <ladis@linux-mips.org>
+ *
+ * v4l2_device/v4l2_subdev conversion by:
+ * Copyright (C) 2009 Hans Verkuil <hverkuil@xs4all.nl>
+ *
+ * Note: this conversion is untested! Please contact the linux-media
+ * mailinglist if you can test this, together with the test results.
*/
/*
@@ -33,12 +39,10 @@
#include <linux/kmod.h>
#include <linux/i2c.h>
-#include <linux/i2c-algo-sgi.h>
#include <linux/videodev2.h>
-#include <media/v4l2-common.h>
+#include <media/v4l2-device.h>
#include <media/v4l2-ioctl.h>
-#include <linux/video_decoder.h>
#include <linux/mutex.h>
#include <asm/paccess.h>
@@ -139,13 +143,23 @@ MODULE_LICENSE("GPL");
#define VINO_DATA_NORM_PAL 1
#define VINO_DATA_NORM_SECAM 2
#define VINO_DATA_NORM_D1 3
-/* The following are special entries that can be used to
- * autodetect the norm. */
-#define VINO_DATA_NORM_AUTO 0xfe
-#define VINO_DATA_NORM_AUTO_EXT 0xff
#define VINO_DATA_NORM_COUNT 4
+/* I2C controller flags */
+#define SGI_I2C_FORCE_IDLE (0 << 0)
+#define SGI_I2C_NOT_IDLE (1 << 0)
+#define SGI_I2C_WRITE (0 << 1)
+#define SGI_I2C_READ (1 << 1)
+#define SGI_I2C_RELEASE_BUS (0 << 2)
+#define SGI_I2C_HOLD_BUS (1 << 2)
+#define SGI_I2C_XFER_DONE (0 << 4)
+#define SGI_I2C_XFER_BUSY (1 << 4)
+#define SGI_I2C_ACK (0 << 5)
+#define SGI_I2C_NACK (1 << 5)
+#define SGI_I2C_BUS_OK (0 << 7)
+#define SGI_I2C_BUS_ERR (1 << 7)
+
/* Internal data structure definitions */
struct vino_input {
@@ -289,22 +303,20 @@ struct vino_channel_settings {
struct vino_interrupt_data int_data;
/* V4L support */
- struct video_device *v4l_device;
-};
-
-struct vino_client {
- /* the channel which owns this client:
- * VINO_NO_CHANNEL, VINO_CHANNEL_A or VINO_CHANNEL_B */
- unsigned int owner;
- struct i2c_client *driver;
+ struct video_device *vdev;
};
struct vino_settings {
+ struct v4l2_device v4l2_dev;
struct vino_channel_settings a;
struct vino_channel_settings b;
- struct vino_client decoder;
- struct vino_client camera;
+ /* the channel which owns this client:
+ * VINO_NO_CHANNEL, VINO_CHANNEL_A or VINO_CHANNEL_B */
+ unsigned int decoder_owner;
+ struct v4l2_subdev *decoder;
+ unsigned int camera_owner;
+ struct v4l2_subdev *camera;
/* a lock for vino register access */
spinlock_t vino_lock;
@@ -344,11 +356,16 @@ static struct sgi_vino *vino;
static struct vino_settings *vino_drvdata;
+#define camera_call(o, f, args...) \
+ v4l2_subdev_call(vino_drvdata->camera, o, f, ##args)
+#define decoder_call(o, f, args...) \
+ v4l2_subdev_call(vino_drvdata->decoder, o, f, ##args)
+
static const char *vino_driver_name = "vino";
static const char *vino_driver_description = "SGI VINO";
static const char *vino_bus_name = "GIO64 bus";
-static const char *vino_v4l_device_name_a = "SGI VINO Channel A";
-static const char *vino_v4l_device_name_b = "SGI VINO Channel B";
+static const char *vino_vdev_name_a = "SGI VINO Channel A";
+static const char *vino_vdev_name_b = "SGI VINO Channel B";
static void vino_capture_tasklet(unsigned long channel);
@@ -360,11 +377,11 @@ static const struct vino_input vino_inputs[] = {
.name = "Composite",
.std = V4L2_STD_NTSC | V4L2_STD_PAL
| V4L2_STD_SECAM,
- },{
+ }, {
.name = "S-Video",
.std = V4L2_STD_NTSC | V4L2_STD_PAL
| V4L2_STD_SECAM,
- },{
+ }, {
.name = "D1/IndyCam",
.std = V4L2_STD_NTSC,
}
@@ -376,17 +393,17 @@ static const struct vino_data_format vino_data_formats[] = {
.bpp = 1,
.pixelformat = V4L2_PIX_FMT_GREY,
.colorspace = V4L2_COLORSPACE_SMPTE170M,
- },{
+ }, {
.description = "8-bit dithered RGB 3-3-2",
.bpp = 1,
.pixelformat = V4L2_PIX_FMT_RGB332,
.colorspace = V4L2_COLORSPACE_SRGB,
- },{
+ }, {
.description = "32-bit RGB",
.bpp = 4,
.pixelformat = V4L2_PIX_FMT_RGB32,
.colorspace = V4L2_COLORSPACE_SRGB,
- },{
+ }, {
.description = "YUV 4:2:2",
.bpp = 2,
.pixelformat = V4L2_PIX_FMT_YUYV, // XXX: swapped?
@@ -417,7 +434,7 @@ static const struct vino_data_norm vino_data_norms[] = {
+ VINO_NTSC_HEIGHT / 2 - 1,
.right = VINO_NTSC_WIDTH,
},
- },{
+ }, {
.description = "PAL",
.std = V4L2_STD_PAL,
.fps_min = 5,
@@ -439,7 +456,7 @@ static const struct vino_data_norm vino_data_norms[] = {
+ VINO_PAL_HEIGHT / 2 - 1,
.right = VINO_PAL_WIDTH,
},
- },{
+ }, {
.description = "SECAM",
.std = V4L2_STD_SECAM,
.fps_min = 5,
@@ -461,7 +478,7 @@ static const struct vino_data_norm vino_data_norms[] = {
+ VINO_PAL_HEIGHT / 2 - 1,
.right = VINO_PAL_WIDTH,
},
- },{
+ }, {
.description = "NTSC/D1",
.std = V4L2_STD_NTSC,
.fps_min = 6,
@@ -497,9 +514,7 @@ struct v4l2_queryctrl vino_indycam_v4l2_controls[] = {
.maximum = 1,
.step = 1,
.default_value = INDYCAM_AGC_DEFAULT,
- .flags = 0,
- .reserved = { INDYCAM_CONTROL_AGC, 0 },
- },{
+ }, {
.id = V4L2_CID_AUTO_WHITE_BALANCE,
.type = V4L2_CTRL_TYPE_BOOLEAN,
.name = "Automatic White Balance",
@@ -507,9 +522,7 @@ struct v4l2_queryctrl vino_indycam_v4l2_controls[] = {
.maximum = 1,
.step = 1,
.default_value = INDYCAM_AWB_DEFAULT,
- .flags = 0,
- .reserved = { INDYCAM_CONTROL_AWB, 0 },
- },{
+ }, {
.id = V4L2_CID_GAIN,
.type = V4L2_CTRL_TYPE_INTEGER,
.name = "Gain",
@@ -517,29 +530,23 @@ struct v4l2_queryctrl vino_indycam_v4l2_controls[] = {
.maximum = INDYCAM_GAIN_MAX,
.step = 1,
.default_value = INDYCAM_GAIN_DEFAULT,
- .flags = 0,
- .reserved = { INDYCAM_CONTROL_GAIN, 0 },
- },{
- .id = V4L2_CID_PRIVATE_BASE,
+ }, {
+ .id = INDYCAM_CONTROL_RED_SATURATION,
.type = V4L2_CTRL_TYPE_INTEGER,
.name = "Red Saturation",
.minimum = INDYCAM_RED_SATURATION_MIN,
.maximum = INDYCAM_RED_SATURATION_MAX,
.step = 1,
.default_value = INDYCAM_RED_SATURATION_DEFAULT,
- .flags = 0,
- .reserved = { INDYCAM_CONTROL_RED_SATURATION, 0 },
- },{
- .id = V4L2_CID_PRIVATE_BASE + 1,
+ }, {
+ .id = INDYCAM_CONTROL_BLUE_SATURATION,
.type = V4L2_CTRL_TYPE_INTEGER,
.name = "Blue Saturation",
.minimum = INDYCAM_BLUE_SATURATION_MIN,
.maximum = INDYCAM_BLUE_SATURATION_MAX,
.step = 1,
.default_value = INDYCAM_BLUE_SATURATION_DEFAULT,
- .flags = 0,
- .reserved = { INDYCAM_CONTROL_BLUE_SATURATION, 0 },
- },{
+ }, {
.id = V4L2_CID_RED_BALANCE,
.type = V4L2_CTRL_TYPE_INTEGER,
.name = "Red Balance",
@@ -547,9 +554,7 @@ struct v4l2_queryctrl vino_indycam_v4l2_controls[] = {
.maximum = INDYCAM_RED_BALANCE_MAX,
.step = 1,
.default_value = INDYCAM_RED_BALANCE_DEFAULT,
- .flags = 0,
- .reserved = { INDYCAM_CONTROL_RED_BALANCE, 0 },
- },{
+ }, {
.id = V4L2_CID_BLUE_BALANCE,
.type = V4L2_CTRL_TYPE_INTEGER,
.name = "Blue Balance",
@@ -557,9 +562,7 @@ struct v4l2_queryctrl vino_indycam_v4l2_controls[] = {
.maximum = INDYCAM_BLUE_BALANCE_MAX,
.step = 1,
.default_value = INDYCAM_BLUE_BALANCE_DEFAULT,
- .flags = 0,
- .reserved = { INDYCAM_CONTROL_BLUE_BALANCE, 0 },
- },{
+ }, {
.id = V4L2_CID_EXPOSURE,
.type = V4L2_CTRL_TYPE_INTEGER,
.name = "Shutter Control",
@@ -567,9 +570,7 @@ struct v4l2_queryctrl vino_indycam_v4l2_controls[] = {
.maximum = INDYCAM_SHUTTER_MAX,
.step = 1,
.default_value = INDYCAM_SHUTTER_DEFAULT,
- .flags = 0,
- .reserved = { INDYCAM_CONTROL_SHUTTER, 0 },
- },{
+ }, {
.id = V4L2_CID_GAMMA,
.type = V4L2_CTRL_TYPE_INTEGER,
.name = "Gamma",
@@ -577,8 +578,6 @@ struct v4l2_queryctrl vino_indycam_v4l2_controls[] = {
.maximum = INDYCAM_GAMMA_MAX,
.step = 1,
.default_value = INDYCAM_GAMMA_DEFAULT,
- .flags = 0,
- .reserved = { INDYCAM_CONTROL_GAMMA, 0 },
}
};
@@ -593,209 +592,73 @@ struct v4l2_queryctrl vino_saa7191_v4l2_controls[] = {
.maximum = SAA7191_HUE_MAX,
.step = 1,
.default_value = SAA7191_HUE_DEFAULT,
- .flags = 0,
- .reserved = { SAA7191_CONTROL_HUE, 0 },
- },{
- .id = V4L2_CID_PRIVATE_BASE,
+ }, {
+ .id = SAA7191_CONTROL_BANDPASS,
.type = V4L2_CTRL_TYPE_INTEGER,
.name = "Luminance Bandpass",
.minimum = SAA7191_BANDPASS_MIN,
.maximum = SAA7191_BANDPASS_MAX,
.step = 1,
.default_value = SAA7191_BANDPASS_DEFAULT,
- .flags = 0,
- .reserved = { SAA7191_CONTROL_BANDPASS, 0 },
- },{
- .id = V4L2_CID_PRIVATE_BASE + 1,
+ }, {
+ .id = SAA7191_CONTROL_BANDPASS_WEIGHT,
.type = V4L2_CTRL_TYPE_INTEGER,
.name = "Luminance Bandpass Weight",
.minimum = SAA7191_BANDPASS_WEIGHT_MIN,
.maximum = SAA7191_BANDPASS_WEIGHT_MAX,
.step = 1,
.default_value = SAA7191_BANDPASS_WEIGHT_DEFAULT,
- .flags = 0,
- .reserved = { SAA7191_CONTROL_BANDPASS_WEIGHT, 0 },
- },{
- .id = V4L2_CID_PRIVATE_BASE + 2,
+ }, {
+ .id = SAA7191_CONTROL_CORING,
.type = V4L2_CTRL_TYPE_INTEGER,
.name = "HF Luminance Coring",
.minimum = SAA7191_CORING_MIN,
.maximum = SAA7191_CORING_MAX,
.step = 1,
.default_value = SAA7191_CORING_DEFAULT,
- .flags = 0,
- .reserved = { SAA7191_CONTROL_CORING, 0 },
- },{
- .id = V4L2_CID_PRIVATE_BASE + 3,
+ }, {
+ .id = SAA7191_CONTROL_FORCE_COLOUR,
.type = V4L2_CTRL_TYPE_BOOLEAN,
.name = "Force Colour",
.minimum = SAA7191_FORCE_COLOUR_MIN,
.maximum = SAA7191_FORCE_COLOUR_MAX,
.step = 1,
.default_value = SAA7191_FORCE_COLOUR_DEFAULT,
- .flags = 0,
- .reserved = { SAA7191_CONTROL_FORCE_COLOUR, 0 },
- },{
- .id = V4L2_CID_PRIVATE_BASE + 4,
+ }, {
+ .id = SAA7191_CONTROL_CHROMA_GAIN,
.type = V4L2_CTRL_TYPE_INTEGER,
.name = "Chrominance Gain Control",
.minimum = SAA7191_CHROMA_GAIN_MIN,
.maximum = SAA7191_CHROMA_GAIN_MAX,
.step = 1,
.default_value = SAA7191_CHROMA_GAIN_DEFAULT,
- .flags = 0,
- .reserved = { SAA7191_CONTROL_CHROMA_GAIN, 0 },
- },{
- .id = V4L2_CID_PRIVATE_BASE + 5,
+ }, {
+ .id = SAA7191_CONTROL_VTRC,
.type = V4L2_CTRL_TYPE_BOOLEAN,
.name = "VTR Time Constant",
.minimum = SAA7191_VTRC_MIN,
.maximum = SAA7191_VTRC_MAX,
.step = 1,
.default_value = SAA7191_VTRC_DEFAULT,
- .flags = 0,
- .reserved = { SAA7191_CONTROL_VTRC, 0 },
- },{
- .id = V4L2_CID_PRIVATE_BASE + 6,
+ }, {
+ .id = SAA7191_CONTROL_LUMA_DELAY,
.type = V4L2_CTRL_TYPE_INTEGER,
.name = "Luminance Delay Compensation",
.minimum = SAA7191_LUMA_DELAY_MIN,
.maximum = SAA7191_LUMA_DELAY_MAX,
.step = 1,
.default_value = SAA7191_LUMA_DELAY_DEFAULT,
- .flags = 0,
- .reserved = { SAA7191_CONTROL_LUMA_DELAY, 0 },
- },{
- .id = V4L2_CID_PRIVATE_BASE + 7,
+ }, {
+ .id = SAA7191_CONTROL_VNR,
.type = V4L2_CTRL_TYPE_INTEGER,
.name = "Vertical Noise Reduction",
.minimum = SAA7191_VNR_MIN,
.maximum = SAA7191_VNR_MAX,
.step = 1,
.default_value = SAA7191_VNR_DEFAULT,
- .flags = 0,
- .reserved = { SAA7191_CONTROL_VNR, 0 },
- }
-};
-
-/* VINO I2C bus functions */
-
-unsigned i2c_vino_getctrl(void *data)
-{
- return vino->i2c_control;
-}
-
-void i2c_vino_setctrl(void *data, unsigned val)
-{
- vino->i2c_control = val;
-}
-
-unsigned i2c_vino_rdata(void *data)
-{
- return vino->i2c_data;
-}
-
-void i2c_vino_wdata(void *data, unsigned val)
-{
- vino->i2c_data = val;
-}
-
-static struct i2c_algo_sgi_data i2c_sgi_vino_data =
-{
- .getctrl = &i2c_vino_getctrl,
- .setctrl = &i2c_vino_setctrl,
- .rdata = &i2c_vino_rdata,
- .wdata = &i2c_vino_wdata,
- .xfer_timeout = 200,
- .ack_timeout = 1000,
-};
-
-/*
- * There are two possible clients on VINO I2C bus, so we limit usage only
- * to them.
- */
-static int i2c_vino_client_reg(struct i2c_client *client)
-{
- unsigned long flags;
- int ret = 0;
-
- spin_lock_irqsave(&vino_drvdata->input_lock, flags);
- switch (client->driver->id) {
- case I2C_DRIVERID_SAA7191:
- if (vino_drvdata->decoder.driver)
- ret = -EBUSY;
- else
- vino_drvdata->decoder.driver = client;
- break;
- case I2C_DRIVERID_INDYCAM:
- if (vino_drvdata->camera.driver)
- ret = -EBUSY;
- else
- vino_drvdata->camera.driver = client;
- break;
- default:
- ret = -ENODEV;
- }
- spin_unlock_irqrestore(&vino_drvdata->input_lock, flags);
-
- return ret;
-}
-
-static int i2c_vino_client_unreg(struct i2c_client *client)
-{
- unsigned long flags;
- int ret = 0;
-
- spin_lock_irqsave(&vino_drvdata->input_lock, flags);
- if (client == vino_drvdata->decoder.driver) {
- if (vino_drvdata->decoder.owner != VINO_NO_CHANNEL)
- ret = -EBUSY;
- else
- vino_drvdata->decoder.driver = NULL;
- } else if (client == vino_drvdata->camera.driver) {
- if (vino_drvdata->camera.owner != VINO_NO_CHANNEL)
- ret = -EBUSY;
- else
- vino_drvdata->camera.driver = NULL;
}
- spin_unlock_irqrestore(&vino_drvdata->input_lock, flags);
-
- return ret;
-}
-
-static struct i2c_adapter vino_i2c_adapter =
-{
- .name = "VINO I2C bus",
- .id = I2C_HW_SGI_VINO,
- .algo_data = &i2c_sgi_vino_data,
- .client_register = &i2c_vino_client_reg,
- .client_unregister = &i2c_vino_client_unreg,
};
-static int vino_i2c_add_bus(void)
-{
- return i2c_sgi_add_bus(&vino_i2c_adapter);
-}
-
-static int vino_i2c_del_bus(void)
-{
- return i2c_del_adapter(&vino_i2c_adapter);
-}
-
-static int i2c_camera_command(unsigned int cmd, void *arg)
-{
- return vino_drvdata->camera.driver->
- driver->command(vino_drvdata->camera.driver,
- cmd, arg);
-}
-
-static int i2c_decoder_command(unsigned int cmd, void *arg)
-{
- return vino_drvdata->decoder.driver->
- driver->command(vino_drvdata->decoder.driver,
- cmd, arg);
-}
-
/* VINO framebuffer/DMA descriptor management */
static void vino_free_buffer_with_count(struct vino_framebuffer *fb,
@@ -1741,6 +1604,184 @@ static inline void vino_set_default_framerate(struct
vino_set_framerate(vcs, vino_data_norms[vcs->data_norm].fps_max);
}
+/* VINO I2C bus functions */
+
+struct i2c_algo_sgi_data {
+ void *data; /* private data for lowlevel routines */
+ unsigned (*getctrl)(void *data);
+ void (*setctrl)(void *data, unsigned val);
+ unsigned (*rdata)(void *data);
+ void (*wdata)(void *data, unsigned val);
+
+ int xfer_timeout;
+ int ack_timeout;
+};
+
+static int wait_xfer_done(struct i2c_algo_sgi_data *adap)
+{
+ int i;
+
+ for (i = 0; i < adap->xfer_timeout; i++) {
+ if ((adap->getctrl(adap->data) & SGI_I2C_XFER_BUSY) == 0)
+ return 0;
+ udelay(1);
+ }
+
+ return -ETIMEDOUT;
+}
+
+static int wait_ack(struct i2c_algo_sgi_data *adap)
+{
+ int i;
+
+ if (wait_xfer_done(adap))
+ return -ETIMEDOUT;
+ for (i = 0; i < adap->ack_timeout; i++) {
+ if ((adap->getctrl(adap->data) & SGI_I2C_NACK) == 0)
+ return 0;
+ udelay(1);
+ }
+
+ return -ETIMEDOUT;
+}
+
+static int force_idle(struct i2c_algo_sgi_data *adap)
+{
+ int i;
+
+ adap->setctrl(adap->data, SGI_I2C_FORCE_IDLE);
+ for (i = 0; i < adap->xfer_timeout; i++) {
+ if ((adap->getctrl(adap->data) & SGI_I2C_NOT_IDLE) == 0)
+ goto out;
+ udelay(1);
+ }
+ return -ETIMEDOUT;
+out:
+ if (adap->getctrl(adap->data) & SGI_I2C_BUS_ERR)
+ return -EIO;
+ return 0;
+}
+
+static int do_address(struct i2c_algo_sgi_data *adap, unsigned int addr,
+ int rd)
+{
+ if (rd)
+ adap->setctrl(adap->data, SGI_I2C_NOT_IDLE);
+ /* Check if bus is idle, eventually force it to do so */
+ if (adap->getctrl(adap->data) & SGI_I2C_NOT_IDLE)
+ if (force_idle(adap))
+ return -EIO;
+ /* Write out the i2c chip address and specify operation */
+ adap->setctrl(adap->data,
+ SGI_I2C_HOLD_BUS | SGI_I2C_WRITE | SGI_I2C_NOT_IDLE);
+ if (rd)
+ addr |= 1;
+ adap->wdata(adap->data, addr);
+ if (wait_ack(adap))
+ return -EIO;
+ return 0;
+}
+
+static int i2c_read(struct i2c_algo_sgi_data *adap, unsigned char *buf,
+ unsigned int len)
+{
+ int i;
+
+ adap->setctrl(adap->data,
+ SGI_I2C_HOLD_BUS | SGI_I2C_READ | SGI_I2C_NOT_IDLE);
+ for (i = 0; i < len; i++) {
+ if (wait_xfer_done(adap))
+ return -EIO;
+ buf[i] = adap->rdata(adap->data);
+ }
+ adap->setctrl(adap->data, SGI_I2C_RELEASE_BUS | SGI_I2C_FORCE_IDLE);
+
+ return 0;
+
+}
+
+static int i2c_write(struct i2c_algo_sgi_data *adap, unsigned char *buf,
+ unsigned int len)
+{
+ int i;
+
+ /* We are already in write state */
+ for (i = 0; i < len; i++) {
+ adap->wdata(adap->data, buf[i]);
+ if (wait_ack(adap))
+ return -EIO;
+ }
+ return 0;
+}
+
+static int sgi_xfer(struct i2c_adapter *i2c_adap, struct i2c_msg *msgs,
+ int num)
+{
+ struct i2c_algo_sgi_data *adap = i2c_adap->algo_data;
+ struct i2c_msg *p;
+ int i, err = 0;
+
+ for (i = 0; !err && i < num; i++) {
+ p = &msgs[i];
+ err = do_address(adap, p->addr, p->flags & I2C_M_RD);
+ if (err || !p->len)
+ continue;
+ if (p->flags & I2C_M_RD)
+ err = i2c_read(adap, p->buf, p->len);
+ else
+ err = i2c_write(adap, p->buf, p->len);
+ }
+
+ return (err < 0) ? err : i;
+}
+
+static u32 sgi_func(struct i2c_adapter *adap)
+{
+ return I2C_FUNC_SMBUS_EMUL;
+}
+
+static const struct i2c_algorithm sgi_algo = {
+ .master_xfer = sgi_xfer,
+ .functionality = sgi_func,
+};
+
+static unsigned i2c_vino_getctrl(void *data)
+{
+ return vino->i2c_control;
+}
+
+static void i2c_vino_setctrl(void *data, unsigned val)
+{
+ vino->i2c_control = val;
+}
+
+static unsigned i2c_vino_rdata(void *data)
+{
+ return vino->i2c_data;
+}
+
+static void i2c_vino_wdata(void *data, unsigned val)
+{
+ vino->i2c_data = val;
+}
+
+static struct i2c_algo_sgi_data i2c_sgi_vino_data = {
+ .getctrl = &i2c_vino_getctrl,
+ .setctrl = &i2c_vino_setctrl,
+ .rdata = &i2c_vino_rdata,
+ .wdata = &i2c_vino_wdata,
+ .xfer_timeout = 200,
+ .ack_timeout = 1000,
+};
+
+static struct i2c_adapter vino_i2c_adapter = {
+ .name = "VINO I2C bus",
+ .id = I2C_HW_SGI_VINO,
+ .algo = &sgi_algo,
+ .algo_data = &i2c_sgi_vino_data,
+ .owner = THIS_MODULE,
+};
+
/*
* Prepare VINO for DMA transfer...
* (execute only with vino_lock and input_lock locked)
@@ -2494,86 +2535,15 @@ static int vino_get_saa7191_input(int input)
}
}
-static int vino_get_saa7191_norm(unsigned int data_norm)
-{
- switch (data_norm) {
- case VINO_DATA_NORM_AUTO:
- return SAA7191_NORM_AUTO;
- case VINO_DATA_NORM_AUTO_EXT:
- return SAA7191_NORM_AUTO_EXT;
- case VINO_DATA_NORM_PAL:
- return SAA7191_NORM_PAL;
- case VINO_DATA_NORM_NTSC:
- return SAA7191_NORM_NTSC;
- case VINO_DATA_NORM_SECAM:
- return SAA7191_NORM_SECAM;
- default:
- printk(KERN_ERR "VINO: vino_get_saa7191_norm(): "
- "invalid norm!\n");
- return -1;
- }
-}
-
-static int vino_get_from_saa7191_norm(int saa7191_norm)
-{
- switch (saa7191_norm) {
- case SAA7191_NORM_PAL:
- return VINO_DATA_NORM_PAL;
- case SAA7191_NORM_NTSC:
- return VINO_DATA_NORM_NTSC;
- case SAA7191_NORM_SECAM:
- return VINO_DATA_NORM_SECAM;
- default:
- printk(KERN_ERR "VINO: vino_get_from_saa7191_norm(): "
- "invalid norm!\n");
- return VINO_DATA_NORM_NONE;
- }
-}
-
-static int vino_saa7191_set_norm(unsigned int *data_norm)
-{
- int saa7191_norm, new_data_norm;
- int err = 0;
-
- saa7191_norm = vino_get_saa7191_norm(*data_norm);
-
- err = i2c_decoder_command(DECODER_SAA7191_SET_NORM,
- &saa7191_norm);
- if (err)
- goto out;
-
- if ((*data_norm == VINO_DATA_NORM_AUTO)
- || (*data_norm == VINO_DATA_NORM_AUTO_EXT)) {
- struct saa7191_status status;
-
- err = i2c_decoder_command(DECODER_SAA7191_GET_STATUS,
- &status);
- if (err)
- goto out;
-
- new_data_norm =
- vino_get_from_saa7191_norm(status.norm);
- if (new_data_norm == VINO_DATA_NORM_NONE) {
- err = -EINVAL;
- goto out;
- }
-
- *data_norm = (unsigned int)new_data_norm;
- }
-
-out:
- return err;
-}
-
/* execute with input_lock locked */
static int vino_is_input_owner(struct vino_channel_settings *vcs)
{
switch(vcs->input) {
case VINO_INPUT_COMPOSITE:
case VINO_INPUT_SVIDEO:
- return (vino_drvdata->decoder.owner == vcs->channel);
+ return vino_drvdata->decoder_owner == vcs->channel;
case VINO_INPUT_D1:
- return (vino_drvdata->camera.owner == vcs->channel);
+ return vino_drvdata->camera_owner == vcs->channel;
default:
return 0;
}
@@ -2589,23 +2559,22 @@ static int vino_acquire_input(struct vino_channel_settings *vcs)
spin_lock_irqsave(&vino_drvdata->input_lock, flags);
/* First try D1 and then SAA7191 */
- if (vino_drvdata->camera.driver
- && (vino_drvdata->camera.owner == VINO_NO_CHANNEL)) {
- i2c_use_client(vino_drvdata->camera.driver);
- vino_drvdata->camera.owner = vcs->channel;
+ if (vino_drvdata->camera
+ && (vino_drvdata->camera_owner == VINO_NO_CHANNEL)) {
+ vino_drvdata->camera_owner = vcs->channel;
vcs->input = VINO_INPUT_D1;
vcs->data_norm = VINO_DATA_NORM_D1;
- } else if (vino_drvdata->decoder.driver
- && (vino_drvdata->decoder.owner == VINO_NO_CHANNEL)) {
- int input, data_norm;
- int saa7191_input;
+ } else if (vino_drvdata->decoder
+ && (vino_drvdata->decoder_owner == VINO_NO_CHANNEL)) {
+ int input;
+ int data_norm;
+ v4l2_std_id norm;
+ struct v4l2_routing route = { 0, 0 };
- i2c_use_client(vino_drvdata->decoder.driver);
input = VINO_INPUT_COMPOSITE;
- saa7191_input = vino_get_saa7191_input(input);
- ret = i2c_decoder_command(DECODER_SET_INPUT,
- &saa7191_input);
+ route.input = vino_get_saa7191_input(input);
+ ret = decoder_call(video, s_routing, &route);
if (ret) {
ret = -EINVAL;
goto out;
@@ -2616,12 +2585,15 @@ static int vino_acquire_input(struct vino_channel_settings *vcs)
/* Don't hold spinlocks while auto-detecting norm
* as it may take a while... */
- data_norm = VINO_DATA_NORM_AUTO_EXT;
-
- ret = vino_saa7191_set_norm(&data_norm);
- if ((ret == -EBUSY) || (ret == -EAGAIN)) {
- data_norm = VINO_DATA_NORM_PAL;
- ret = vino_saa7191_set_norm(&data_norm);
+ ret = decoder_call(video, querystd, &norm);
+ if (!ret) {
+ for (data_norm = 0; data_norm < 3; data_norm++) {
+ if (vino_data_norms[data_norm].std & norm)
+ break;
+ }
+ if (data_norm == 3)
+ data_norm = VINO_DATA_NORM_PAL;
+ ret = decoder_call(tuner, s_std, norm);
}
spin_lock_irqsave(&vino_drvdata->input_lock, flags);
@@ -2631,7 +2603,7 @@ static int vino_acquire_input(struct vino_channel_settings *vcs)
goto out;
}
- vino_drvdata->decoder.owner = vcs->channel;
+ vino_drvdata->decoder_owner = vcs->channel;
vcs->input = input;
vcs->data_norm = data_norm;
@@ -2676,25 +2648,24 @@ static int vino_set_input(struct vino_channel_settings *vcs, int input)
switch (input) {
case VINO_INPUT_COMPOSITE:
case VINO_INPUT_SVIDEO:
- if (!vino_drvdata->decoder.driver) {
+ if (!vino_drvdata->decoder) {
ret = -EINVAL;
goto out;
}
- if (vino_drvdata->decoder.owner == VINO_NO_CHANNEL) {
- i2c_use_client(vino_drvdata->decoder.driver);
- vino_drvdata->decoder.owner = vcs->channel;
+ if (vino_drvdata->decoder_owner == VINO_NO_CHANNEL) {
+ vino_drvdata->decoder_owner = vcs->channel;
}
- if (vino_drvdata->decoder.owner == vcs->channel) {
+ if (vino_drvdata->decoder_owner == vcs->channel) {
int data_norm;
- int saa7191_input;
+ v4l2_std_id norm;
+ struct v4l2_routing route = { 0, 0 };
- saa7191_input = vino_get_saa7191_input(input);
- ret = i2c_decoder_command(DECODER_SET_INPUT,
- &saa7191_input);
+ route.input = vino_get_saa7191_input(input);
+ ret = decoder_call(video, s_routing, &route);
if (ret) {
- vino_drvdata->decoder.owner = VINO_NO_CHANNEL;
+ vino_drvdata->decoder_owner = VINO_NO_CHANNEL;
ret = -EINVAL;
goto out;
}
@@ -2704,18 +2675,21 @@ static int vino_set_input(struct vino_channel_settings *vcs, int input)
/* Don't hold spinlocks while auto-detecting norm
* as it may take a while... */
- data_norm = VINO_DATA_NORM_AUTO_EXT;
-
- ret = vino_saa7191_set_norm(&data_norm);
- if ((ret == -EBUSY) || (ret == -EAGAIN)) {
- data_norm = VINO_DATA_NORM_PAL;
- ret = vino_saa7191_set_norm(&data_norm);
+ ret = decoder_call(video, querystd, &norm);
+ if (!ret) {
+ for (data_norm = 0; data_norm < 3; data_norm++) {
+ if (vino_data_norms[data_norm].std & norm)
+ break;
+ }
+ if (data_norm == 3)
+ data_norm = VINO_DATA_NORM_PAL;
+ ret = decoder_call(tuner, s_std, norm);
}
spin_lock_irqsave(&vino_drvdata->input_lock, flags);
if (ret) {
- vino_drvdata->decoder.owner = VINO_NO_CHANNEL;
+ vino_drvdata->decoder_owner = VINO_NO_CHANNEL;
ret = -EINVAL;
goto out;
}
@@ -2732,37 +2706,31 @@ static int vino_set_input(struct vino_channel_settings *vcs, int input)
vcs->data_norm = vcs2->data_norm;
}
- if (vino_drvdata->camera.owner == vcs->channel) {
+ if (vino_drvdata->camera_owner == vcs->channel) {
/* Transfer the ownership or release the input */
if (vcs2->input == VINO_INPUT_D1) {
- vino_drvdata->camera.owner = vcs2->channel;
+ vino_drvdata->camera_owner = vcs2->channel;
} else {
- i2c_release_client(vino_drvdata->
- camera.driver);
- vino_drvdata->camera.owner = VINO_NO_CHANNEL;
+ vino_drvdata->camera_owner = VINO_NO_CHANNEL;
}
}
break;
case VINO_INPUT_D1:
- if (!vino_drvdata->camera.driver) {
+ if (!vino_drvdata->camera) {
ret = -EINVAL;
goto out;
}
- if (vino_drvdata->camera.owner == VINO_NO_CHANNEL) {
- i2c_use_client(vino_drvdata->camera.driver);
- vino_drvdata->camera.owner = vcs->channel;
- }
+ if (vino_drvdata->camera_owner == VINO_NO_CHANNEL)
+ vino_drvdata->camera_owner = vcs->channel;
- if (vino_drvdata->decoder.owner == vcs->channel) {
+ if (vino_drvdata->decoder_owner == vcs->channel) {
/* Transfer the ownership or release the input */
if ((vcs2->input == VINO_INPUT_COMPOSITE) ||
(vcs2->input == VINO_INPUT_SVIDEO)) {
- vino_drvdata->decoder.owner = vcs2->channel;
+ vino_drvdata->decoder_owner = vcs2->channel;
} else {
- i2c_release_client(vino_drvdata->
- decoder.driver);
- vino_drvdata->decoder.owner = VINO_NO_CHANNEL;
+ vino_drvdata->decoder_owner = VINO_NO_CHANNEL;
}
}
@@ -2799,20 +2767,18 @@ static void vino_release_input(struct vino_channel_settings *vcs)
/* Release ownership of the channel
* and if the other channel takes input from
* the same source, transfer the ownership */
- if (vino_drvdata->camera.owner == vcs->channel) {
+ if (vino_drvdata->camera_owner == vcs->channel) {
if (vcs2->input == VINO_INPUT_D1) {
- vino_drvdata->camera.owner = vcs2->channel;
+ vino_drvdata->camera_owner = vcs2->channel;
} else {
- i2c_release_client(vino_drvdata->camera.driver);
- vino_drvdata->camera.owner = VINO_NO_CHANNEL;
+ vino_drvdata->camera_owner = VINO_NO_CHANNEL;
}
- } else if (vino_drvdata->decoder.owner == vcs->channel) {
+ } else if (vino_drvdata->decoder_owner == vcs->channel) {
if ((vcs2->input == VINO_INPUT_COMPOSITE) ||
(vcs2->input == VINO_INPUT_SVIDEO)) {
- vino_drvdata->decoder.owner = vcs2->channel;
+ vino_drvdata->decoder_owner = vcs2->channel;
} else {
- i2c_release_client(vino_drvdata->decoder.driver);
- vino_drvdata->decoder.owner = VINO_NO_CHANNEL;
+ vino_drvdata->decoder_owner = VINO_NO_CHANNEL;
}
}
vcs->input = VINO_INPUT_NONE;
@@ -2833,18 +2799,16 @@ static int vino_set_data_norm(struct vino_channel_settings *vcs,
switch (vcs->input) {
case VINO_INPUT_D1:
/* only one "norm" supported */
- if ((data_norm != VINO_DATA_NORM_D1)
- && (data_norm != VINO_DATA_NORM_AUTO)
- && (data_norm != VINO_DATA_NORM_AUTO_EXT))
+ if (data_norm != VINO_DATA_NORM_D1)
return -EINVAL;
break;
case VINO_INPUT_COMPOSITE:
case VINO_INPUT_SVIDEO: {
+ v4l2_std_id norm;
+
if ((data_norm != VINO_DATA_NORM_PAL)
&& (data_norm != VINO_DATA_NORM_NTSC)
- && (data_norm != VINO_DATA_NORM_SECAM)
- && (data_norm != VINO_DATA_NORM_AUTO)
- && (data_norm != VINO_DATA_NORM_AUTO_EXT))
+ && (data_norm != VINO_DATA_NORM_SECAM))
return -EINVAL;
spin_unlock_irqrestore(&vino_drvdata->input_lock, *flags);
@@ -2852,7 +2816,8 @@ static int vino_set_data_norm(struct vino_channel_settings *vcs,
/* Don't hold spinlocks while setting norm
* as it may take a while... */
- err = vino_saa7191_set_norm(&data_norm);
+ norm = vino_data_norms[data_norm].std;
+ err = decoder_call(tuner, s_std, norm);
spin_lock_irqsave(&vino_drvdata->input_lock, *flags);
@@ -2888,41 +2853,13 @@ static int vino_find_data_format(__u32 pixelformat)
return VINO_DATA_FMT_NONE;
}
-static int vino_enum_data_norm(struct vino_channel_settings *vcs, __u32 index)
-{
- int data_norm = VINO_DATA_NORM_NONE;
- unsigned long flags;
-
- spin_lock_irqsave(&vino_drvdata->input_lock, flags);
- switch(vcs->input) {
- case VINO_INPUT_COMPOSITE:
- case VINO_INPUT_SVIDEO:
- if (index == 0) {
- data_norm = VINO_DATA_NORM_PAL;
- } else if (index == 1) {
- data_norm = VINO_DATA_NORM_NTSC;
- } else if (index == 2) {
- data_norm = VINO_DATA_NORM_SECAM;
- }
- break;
- case VINO_INPUT_D1:
- if (index == 0) {
- data_norm = VINO_DATA_NORM_D1;
- }
- break;
- }
- spin_unlock_irqrestore(&vino_drvdata->input_lock, flags);
-
- return data_norm;
-}
-
-static int vino_enum_input(struct vino_channel_settings *vcs, __u32 index)
+static int vino_int_enum_input(struct vino_channel_settings *vcs, __u32 index)
{
int input = VINO_INPUT_NONE;
unsigned long flags;
spin_lock_irqsave(&vino_drvdata->input_lock, flags);
- if (vino_drvdata->decoder.driver && vino_drvdata->camera.driver) {
+ if (vino_drvdata->decoder && vino_drvdata->camera) {
switch (index) {
case 0:
input = VINO_INPUT_COMPOSITE;
@@ -2934,7 +2871,7 @@ static int vino_enum_input(struct vino_channel_settings *vcs, __u32 index)
input = VINO_INPUT_D1;
break;
}
- } else if (vino_drvdata->decoder.driver) {
+ } else if (vino_drvdata->decoder) {
switch (index) {
case 0:
input = VINO_INPUT_COMPOSITE;
@@ -2943,7 +2880,7 @@ static int vino_enum_input(struct vino_channel_settings *vcs, __u32 index)
input = VINO_INPUT_SVIDEO;
break;
}
- } else if (vino_drvdata->camera.driver) {
+ } else if (vino_drvdata->camera) {
switch (index) {
case 0:
input = VINO_INPUT_D1;
@@ -2961,7 +2898,7 @@ static __u32 vino_find_input_index(struct vino_channel_settings *vcs)
__u32 index = 0;
// FIXME: detect when no inputs available
- if (vino_drvdata->decoder.driver && vino_drvdata->camera.driver) {
+ if (vino_drvdata->decoder && vino_drvdata->camera) {
switch (vcs->input) {
case VINO_INPUT_COMPOSITE:
index = 0;
@@ -2973,7 +2910,7 @@ static __u32 vino_find_input_index(struct vino_channel_settings *vcs)
index = 2;
break;
}
- } else if (vino_drvdata->decoder.driver) {
+ } else if (vino_drvdata->decoder) {
switch (vcs->input) {
case VINO_INPUT_COMPOSITE:
index = 0;
@@ -2982,7 +2919,7 @@ static __u32 vino_find_input_index(struct vino_channel_settings *vcs)
index = 1;
break;
}
- } else if (vino_drvdata->camera.driver) {
+ } else if (vino_drvdata->camera) {
switch (vcs->input) {
case VINO_INPUT_D1:
index = 0;
@@ -2995,7 +2932,8 @@ static __u32 vino_find_input_index(struct vino_channel_settings *vcs)
/* V4L2 ioctls */
-static void vino_v4l2_querycap(struct v4l2_capability *cap)
+static int vino_querycap(struct file *file, void *__fh,
+ struct v4l2_capability *cap)
{
memset(cap, 0, sizeof(struct v4l2_capability));
@@ -3007,16 +2945,18 @@ static void vino_v4l2_querycap(struct v4l2_capability *cap)
V4L2_CAP_VIDEO_CAPTURE |
V4L2_CAP_STREAMING;
// V4L2_CAP_OVERLAY, V4L2_CAP_READWRITE
+ return 0;
}
-static int vino_v4l2_enuminput(struct vino_channel_settings *vcs,
+static int vino_enum_input(struct file *file, void *__fh,
struct v4l2_input *i)
{
+ struct vino_channel_settings *vcs = video_drvdata(file);
__u32 index = i->index;
int input;
dprintk("requested index = %d\n", index);
- input = vino_enum_input(vcs, index);
+ input = vino_int_enum_input(vcs, index);
if (input == VINO_INPUT_NONE)
return -EINVAL;
@@ -3027,20 +2967,15 @@ static int vino_v4l2_enuminput(struct vino_channel_settings *vcs,
i->std = vino_inputs[input].std;
strcpy(i->name, vino_inputs[input].name);
- if ((input == VINO_INPUT_COMPOSITE)
- || (input == VINO_INPUT_SVIDEO)) {
- struct saa7191_status status;
- i2c_decoder_command(DECODER_SAA7191_GET_STATUS, &status);
- i->status |= status.signal ? 0 : V4L2_IN_ST_NO_SIGNAL;
- i->status |= status.color ? 0 : V4L2_IN_ST_NO_COLOR;
- }
-
+ if (input == VINO_INPUT_COMPOSITE || input == VINO_INPUT_SVIDEO)
+ decoder_call(video, g_input_status, &i->status);
return 0;
}
-static int vino_v4l2_g_input(struct vino_channel_settings *vcs,
+static int vino_g_input(struct file *file, void *__fh,
unsigned int *i)
{
+ struct vino_channel_settings *vcs = video_drvdata(file);
__u32 index;
int input;
unsigned long flags;
@@ -3061,52 +2996,24 @@ static int vino_v4l2_g_input(struct vino_channel_settings *vcs,
return 0;
}
-static int vino_v4l2_s_input(struct vino_channel_settings *vcs,
- unsigned int *i)
+static int vino_s_input(struct file *file, void *__fh,
+ unsigned int i)
{
+ struct vino_channel_settings *vcs = video_drvdata(file);
int input;
- dprintk("requested input = %d\n", *i);
+ dprintk("requested input = %d\n", i);
- input = vino_enum_input(vcs, *i);
+ input = vino_int_enum_input(vcs, i);
if (input == VINO_INPUT_NONE)
return -EINVAL;
return vino_set_input(vcs, input);
}
-static int vino_v4l2_enumstd(struct vino_channel_settings *vcs,
- struct v4l2_standard *s)
-{
- int index = s->index;
- int data_norm;
-
- data_norm = vino_enum_data_norm(vcs, index);
- dprintk("standard index = %d\n", index);
-
- if (data_norm == VINO_DATA_NORM_NONE)
- return -EINVAL;
-
- dprintk("standard name = %s\n",
- vino_data_norms[data_norm].description);
-
- memset(s, 0, sizeof(struct v4l2_standard));
- s->index = index;
-
- s->id = vino_data_norms[data_norm].std;
- s->frameperiod.numerator = 1;
- s->frameperiod.denominator =
- vino_data_norms[data_norm].fps_max;
- s->framelines =
- vino_data_norms[data_norm].framelines;
- strcpy(s->name,
- vino_data_norms[data_norm].description);
-
- return 0;
-}
-
-static int vino_v4l2_querystd(struct vino_channel_settings *vcs,
+static int vino_querystd(struct file *file, void *__fh,
v4l2_std_id *std)
{
+ struct vino_channel_settings *vcs = video_drvdata(file);
unsigned long flags;
int err = 0;
@@ -3118,19 +3025,7 @@ static int vino_v4l2_querystd(struct vino_channel_settings *vcs,
break;
case VINO_INPUT_COMPOSITE:
case VINO_INPUT_SVIDEO: {
- struct saa7191_status status;
-
- i2c_decoder_command(DECODER_SAA7191_GET_STATUS, &status);
-
- if (status.signal) {
- if (status.signal_60hz) {
- *std = V4L2_STD_NTSC;
- } else {
- *std = V4L2_STD_PAL | V4L2_STD_SECAM;
- }
- } else {
- *std = vino_inputs[vcs->input].std;
- }
+ decoder_call(video, querystd, std);
break;
}
default:
@@ -3142,9 +3037,10 @@ static int vino_v4l2_querystd(struct vino_channel_settings *vcs,
return err;
}
-static int vino_v4l2_g_std(struct vino_channel_settings *vcs,
+static int vino_g_std(struct file *file, void *__fh,
v4l2_std_id *std)
{
+ struct vino_channel_settings *vcs = video_drvdata(file);
unsigned long flags;
spin_lock_irqsave(&vino_drvdata->input_lock, flags);
@@ -3157,9 +3053,10 @@ static int vino_v4l2_g_std(struct vino_channel_settings *vcs,
return 0;
}
-static int vino_v4l2_s_std(struct vino_channel_settings *vcs,
+static int vino_s_std(struct file *file, void *__fh,
v4l2_std_id *std)
{
+ struct vino_channel_settings *vcs = video_drvdata(file);
unsigned long flags;
int ret = 0;
@@ -3180,12 +3077,7 @@ static int vino_v4l2_s_std(struct vino_channel_settings *vcs,
if (vcs->input == VINO_INPUT_D1)
goto out;
- if (((*std) & V4L2_STD_PAL)
- && ((*std) & V4L2_STD_NTSC)
- && ((*std) & V4L2_STD_SECAM)) {
- ret = vino_set_data_norm(vcs, VINO_DATA_NORM_AUTO_EXT,
- &flags);
- } else if ((*std) & V4L2_STD_PAL) {
+ if ((*std) & V4L2_STD_PAL) {
ret = vino_set_data_norm(vcs, VINO_DATA_NORM_PAL,
&flags);
} else if ((*std) & V4L2_STD_NTSC) {
@@ -3211,185 +3103,152 @@ out:
return ret;
}
-static int vino_v4l2_enum_fmt(struct vino_channel_settings *vcs,
+static int vino_enum_fmt_vid_cap(struct file *file, void *__fh,
struct v4l2_fmtdesc *fd)
{
enum v4l2_buf_type type = fd->type;
int index = fd->index;
+
dprintk("format index = %d\n", index);
- switch (fd->type) {
- case V4L2_BUF_TYPE_VIDEO_CAPTURE:
- if ((fd->index < 0) ||
- (fd->index >= VINO_DATA_FMT_COUNT))
- return -EINVAL;
- dprintk("format name = %s\n",
- vino_data_formats[index].description);
-
- memset(fd, 0, sizeof(struct v4l2_fmtdesc));
- fd->index = index;
- fd->type = type;
- fd->pixelformat = vino_data_formats[index].pixelformat;
- strcpy(fd->description, vino_data_formats[index].description);
- break;
- case V4L2_BUF_TYPE_VIDEO_OVERLAY:
- default:
+ if ((fd->index < 0) ||
+ (fd->index >= VINO_DATA_FMT_COUNT))
return -EINVAL;
- }
-
+ dprintk("format name = %s\n",
+ vino_data_formats[index].description);
+
+ memset(fd, 0, sizeof(struct v4l2_fmtdesc));
+ fd->index = index;
+ fd->type = type;
+ fd->pixelformat = vino_data_formats[index].pixelformat;
+ strcpy(fd->description, vino_data_formats[index].description);
return 0;
}
-static int vino_v4l2_try_fmt(struct vino_channel_settings *vcs,
+static int vino_try_fmt_vid_cap(struct file *file, void *__fh,
struct v4l2_format *f)
{
+ struct vino_channel_settings *vcs = video_drvdata(file);
struct vino_channel_settings tempvcs;
unsigned long flags;
+ struct v4l2_pix_format *pf = &f->fmt.pix;
- switch (f->type) {
- case V4L2_BUF_TYPE_VIDEO_CAPTURE: {
- struct v4l2_pix_format *pf = &f->fmt.pix;
-
- dprintk("requested: w = %d, h = %d\n",
- pf->width, pf->height);
-
- spin_lock_irqsave(&vino_drvdata->input_lock, flags);
- memcpy(&tempvcs, vcs, sizeof(struct vino_channel_settings));
- spin_unlock_irqrestore(&vino_drvdata->input_lock, flags);
+ dprintk("requested: w = %d, h = %d\n",
+ pf->width, pf->height);
- tempvcs.data_format = vino_find_data_format(pf->pixelformat);
- if (tempvcs.data_format == VINO_DATA_FMT_NONE) {
- tempvcs.data_format = VINO_DATA_FMT_GREY;
- pf->pixelformat =
- vino_data_formats[tempvcs.data_format].
- pixelformat;
- }
+ spin_lock_irqsave(&vino_drvdata->input_lock, flags);
+ memcpy(&tempvcs, vcs, sizeof(struct vino_channel_settings));
+ spin_unlock_irqrestore(&vino_drvdata->input_lock, flags);
- /* data format must be set before clipping/scaling */
- vino_set_scaling(&tempvcs, pf->width, pf->height);
+ tempvcs.data_format = vino_find_data_format(pf->pixelformat);
+ if (tempvcs.data_format == VINO_DATA_FMT_NONE) {
+ tempvcs.data_format = VINO_DATA_FMT_GREY;
+ pf->pixelformat =
+ vino_data_formats[tempvcs.data_format].
+ pixelformat;
+ }
- dprintk("data format = %s\n",
- vino_data_formats[tempvcs.data_format].description);
+ /* data format must be set before clipping/scaling */
+ vino_set_scaling(&tempvcs, pf->width, pf->height);
- pf->width = (tempvcs.clipping.right - tempvcs.clipping.left) /
- tempvcs.decimation;
- pf->height = (tempvcs.clipping.bottom - tempvcs.clipping.top) /
- tempvcs.decimation;
+ dprintk("data format = %s\n",
+ vino_data_formats[tempvcs.data_format].description);
- pf->field = V4L2_FIELD_INTERLACED;
- pf->bytesperline = tempvcs.line_size;
- pf->sizeimage = tempvcs.line_size *
- (tempvcs.clipping.bottom - tempvcs.clipping.top) /
- tempvcs.decimation;
- pf->colorspace =
- vino_data_formats[tempvcs.data_format].colorspace;
+ pf->width = (tempvcs.clipping.right - tempvcs.clipping.left) /
+ tempvcs.decimation;
+ pf->height = (tempvcs.clipping.bottom - tempvcs.clipping.top) /
+ tempvcs.decimation;
- pf->priv = 0;
- break;
- }
- case V4L2_BUF_TYPE_VIDEO_OVERLAY:
- default:
- return -EINVAL;
- }
+ pf->field = V4L2_FIELD_INTERLACED;
+ pf->bytesperline = tempvcs.line_size;
+ pf->sizeimage = tempvcs.line_size *
+ (tempvcs.clipping.bottom - tempvcs.clipping.top) /
+ tempvcs.decimation;
+ pf->colorspace =
+ vino_data_formats[tempvcs.data_format].colorspace;
+ pf->priv = 0;
return 0;
}
-static int vino_v4l2_g_fmt(struct vino_channel_settings *vcs,
+static int vino_g_fmt_vid_cap(struct file *file, void *__fh,
struct v4l2_format *f)
{
+ struct vino_channel_settings *vcs = video_drvdata(file);
unsigned long flags;
+ struct v4l2_pix_format *pf = &f->fmt.pix;
- switch (f->type) {
- case V4L2_BUF_TYPE_VIDEO_CAPTURE: {
- struct v4l2_pix_format *pf = &f->fmt.pix;
-
- spin_lock_irqsave(&vino_drvdata->input_lock, flags);
-
- pf->width = (vcs->clipping.right - vcs->clipping.left) /
- vcs->decimation;
- pf->height = (vcs->clipping.bottom - vcs->clipping.top) /
- vcs->decimation;
- pf->pixelformat =
- vino_data_formats[vcs->data_format].pixelformat;
+ spin_lock_irqsave(&vino_drvdata->input_lock, flags);
- pf->field = V4L2_FIELD_INTERLACED;
- pf->bytesperline = vcs->line_size;
- pf->sizeimage = vcs->line_size *
- (vcs->clipping.bottom - vcs->clipping.top) /
- vcs->decimation;
- pf->colorspace =
- vino_data_formats[vcs->data_format].colorspace;
+ pf->width = (vcs->clipping.right - vcs->clipping.left) /
+ vcs->decimation;
+ pf->height = (vcs->clipping.bottom - vcs->clipping.top) /
+ vcs->decimation;
+ pf->pixelformat =
+ vino_data_formats[vcs->data_format].pixelformat;
- pf->priv = 0;
+ pf->field = V4L2_FIELD_INTERLACED;
+ pf->bytesperline = vcs->line_size;
+ pf->sizeimage = vcs->line_size *
+ (vcs->clipping.bottom - vcs->clipping.top) /
+ vcs->decimation;
+ pf->colorspace =
+ vino_data_formats[vcs->data_format].colorspace;
- spin_unlock_irqrestore(&vino_drvdata->input_lock, flags);
- break;
- }
- case V4L2_BUF_TYPE_VIDEO_OVERLAY:
- default:
- return -EINVAL;
- }
+ pf->priv = 0;
+ spin_unlock_irqrestore(&vino_drvdata->input_lock, flags);
return 0;
}
-static int vino_v4l2_s_fmt(struct vino_channel_settings *vcs,
+static int vino_s_fmt_vid_cap(struct file *file, void *__fh,
struct v4l2_format *f)
{
+ struct vino_channel_settings *vcs = video_drvdata(file);
int data_format;
unsigned long flags;
+ struct v4l2_pix_format *pf = &f->fmt.pix;
- switch (f->type) {
- case V4L2_BUF_TYPE_VIDEO_CAPTURE: {
- struct v4l2_pix_format *pf = &f->fmt.pix;
-
- spin_lock_irqsave(&vino_drvdata->input_lock, flags);
+ spin_lock_irqsave(&vino_drvdata->input_lock, flags);
- data_format = vino_find_data_format(pf->pixelformat);
+ data_format = vino_find_data_format(pf->pixelformat);
- if (data_format == VINO_DATA_FMT_NONE) {
- vcs->data_format = VINO_DATA_FMT_GREY;
- pf->pixelformat =
- vino_data_formats[vcs->data_format].
- pixelformat;
- } else {
- vcs->data_format = data_format;
- }
-
- /* data format must be set before clipping/scaling */
- vino_set_scaling(vcs, pf->width, pf->height);
+ if (data_format == VINO_DATA_FMT_NONE) {
+ vcs->data_format = VINO_DATA_FMT_GREY;
+ pf->pixelformat =
+ vino_data_formats[vcs->data_format].
+ pixelformat;
+ } else {
+ vcs->data_format = data_format;
+ }
- dprintk("data format = %s\n",
- vino_data_formats[vcs->data_format].description);
+ /* data format must be set before clipping/scaling */
+ vino_set_scaling(vcs, pf->width, pf->height);
- pf->width = vcs->clipping.right - vcs->clipping.left;
- pf->height = vcs->clipping.bottom - vcs->clipping.top;
+ dprintk("data format = %s\n",
+ vino_data_formats[vcs->data_format].description);
- pf->field = V4L2_FIELD_INTERLACED;
- pf->bytesperline = vcs->line_size;
- pf->sizeimage = vcs->line_size *
- (vcs->clipping.bottom - vcs->clipping.top) /
- vcs->decimation;
- pf->colorspace =
- vino_data_formats[vcs->data_format].colorspace;
+ pf->width = vcs->clipping.right - vcs->clipping.left;
+ pf->height = vcs->clipping.bottom - vcs->clipping.top;
- pf->priv = 0;
+ pf->field = V4L2_FIELD_INTERLACED;
+ pf->bytesperline = vcs->line_size;
+ pf->sizeimage = vcs->line_size *
+ (vcs->clipping.bottom - vcs->clipping.top) /
+ vcs->decimation;
+ pf->colorspace =
+ vino_data_formats[vcs->data_format].colorspace;
- spin_unlock_irqrestore(&vino_drvdata->input_lock, flags);
- break;
- }
- case V4L2_BUF_TYPE_VIDEO_OVERLAY:
- default:
- return -EINVAL;
- }
+ pf->priv = 0;
+ spin_unlock_irqrestore(&vino_drvdata->input_lock, flags);
return 0;
}
-static int vino_v4l2_cropcap(struct vino_channel_settings *vcs,
+static int vino_cropcap(struct file *file, void *__fh,
struct v4l2_cropcap *ccap)
{
+ struct vino_channel_settings *vcs = video_drvdata(file);
const struct vino_data_norm *norm;
unsigned long flags;
@@ -3419,9 +3278,10 @@ static int vino_v4l2_cropcap(struct vino_channel_settings *vcs,
return 0;
}
-static int vino_v4l2_g_crop(struct vino_channel_settings *vcs,
+static int vino_g_crop(struct file *file, void *__fh,
struct v4l2_crop *c)
{
+ struct vino_channel_settings *vcs = video_drvdata(file);
unsigned long flags;
switch (c->type) {
@@ -3443,9 +3303,10 @@ static int vino_v4l2_g_crop(struct vino_channel_settings *vcs,
return 0;
}
-static int vino_v4l2_s_crop(struct vino_channel_settings *vcs,
+static int vino_s_crop(struct file *file, void *__fh,
struct v4l2_crop *c)
{
+ struct vino_channel_settings *vcs = video_drvdata(file);
unsigned long flags;
switch (c->type) {
@@ -3465,9 +3326,10 @@ static int vino_v4l2_s_crop(struct vino_channel_settings *vcs,
return 0;
}
-static int vino_v4l2_g_parm(struct vino_channel_settings *vcs,
+static int vino_g_parm(struct file *file, void *__fh,
struct v4l2_streamparm *sp)
{
+ struct vino_channel_settings *vcs = video_drvdata(file);
unsigned long flags;
switch (sp->type) {
@@ -3495,9 +3357,10 @@ static int vino_v4l2_g_parm(struct vino_channel_settings *vcs,
return 0;
}
-static int vino_v4l2_s_parm(struct vino_channel_settings *vcs,
+static int vino_s_parm(struct file *file, void *__fh,
struct v4l2_streamparm *sp)
{
+ struct vino_channel_settings *vcs = video_drvdata(file);
unsigned long flags;
switch (sp->type) {
@@ -3528,9 +3391,10 @@ static int vino_v4l2_s_parm(struct vino_channel_settings *vcs,
return 0;
}
-static int vino_v4l2_reqbufs(struct vino_channel_settings *vcs,
+static int vino_reqbufs(struct file *file, void *__fh,
struct v4l2_requestbuffers *rb)
{
+ struct vino_channel_settings *vcs = video_drvdata(file);
if (vcs->reading)
return -EBUSY;
@@ -3610,9 +3474,10 @@ static void vino_v4l2_get_buffer_status(struct vino_channel_settings *vcs,
fb->id, fb->size, fb->data_size, fb->offset);
}
-static int vino_v4l2_querybuf(struct vino_channel_settings *vcs,
+static int vino_querybuf(struct file *file, void *__fh,
struct v4l2_buffer *b)
{
+ struct vino_channel_settings *vcs = video_drvdata(file);
if (vcs->reading)
return -EBUSY;
@@ -3645,9 +3510,10 @@ static int vino_v4l2_querybuf(struct vino_channel_settings *vcs,
return 0;
}
-static int vino_v4l2_qbuf(struct vino_channel_settings *vcs,
+static int vino_qbuf(struct file *file, void *__fh,
struct v4l2_buffer *b)
{
+ struct vino_channel_settings *vcs = video_drvdata(file);
if (vcs->reading)
return -EBUSY;
@@ -3683,10 +3549,11 @@ static int vino_v4l2_qbuf(struct vino_channel_settings *vcs,
return 0;
}
-static int vino_v4l2_dqbuf(struct vino_channel_settings *vcs,
- struct v4l2_buffer *b,
- unsigned int nonblocking)
+static int vino_dqbuf(struct file *file, void *__fh,
+ struct v4l2_buffer *b)
{
+ struct vino_channel_settings *vcs = video_drvdata(file);
+ unsigned int nonblocking = file->f_flags & O_NONBLOCK;
if (vcs->reading)
return -EBUSY;
@@ -3758,8 +3625,10 @@ static int vino_v4l2_dqbuf(struct vino_channel_settings *vcs,
return 0;
}
-static int vino_v4l2_streamon(struct vino_channel_settings *vcs)
+static int vino_streamon(struct file *file, void *__fh,
+ enum v4l2_buf_type i)
{
+ struct vino_channel_settings *vcs = video_drvdata(file);
unsigned int incoming;
int ret;
if (vcs->reading)
@@ -3796,8 +3665,10 @@ static int vino_v4l2_streamon(struct vino_channel_settings *vcs)
return 0;
}
-static int vino_v4l2_streamoff(struct vino_channel_settings *vcs)
+static int vino_streamoff(struct file *file, void *__fh,
+ enum v4l2_buf_type i)
{
+ struct vino_channel_settings *vcs = video_drvdata(file);
if (vcs->reading)
return -EBUSY;
@@ -3810,9 +3681,10 @@ static int vino_v4l2_streamoff(struct vino_channel_settings *vcs)
return 0;
}
-static int vino_v4l2_queryctrl(struct vino_channel_settings *vcs,
+static int vino_queryctrl(struct file *file, void *__fh,
struct v4l2_queryctrl *queryctrl)
{
+ struct vino_channel_settings *vcs = video_drvdata(file);
unsigned long flags;
int i;
int err = 0;
@@ -3859,9 +3731,10 @@ static int vino_v4l2_queryctrl(struct vino_channel_settings *vcs,
return err;
}
-static int vino_v4l2_g_ctrl(struct vino_channel_settings *vcs,
+static int vino_g_ctrl(struct file *file, void *__fh,
struct v4l2_control *control)
{
+ struct vino_channel_settings *vcs = video_drvdata(file);
unsigned long flags;
int i;
int err = 0;
@@ -3870,56 +3743,38 @@ static int vino_v4l2_g_ctrl(struct vino_channel_settings *vcs,
switch (vcs->input) {
case VINO_INPUT_D1: {
- struct indycam_control indycam_ctrl;
-
+ err = -EINVAL;
for (i = 0; i < VINO_INDYCAM_V4L2_CONTROL_COUNT; i++) {
- if (vino_indycam_v4l2_controls[i].id ==
- control->id) {
- goto found1;
+ if (vino_indycam_v4l2_controls[i].id == control->id) {
+ err = 0;
+ break;
}
}
- err = -EINVAL;
- goto out;
-
-found1:
- indycam_ctrl.type = vino_indycam_v4l2_controls[i].reserved[0];
-
- err = i2c_camera_command(DECODER_INDYCAM_GET_CONTROL,
- &indycam_ctrl);
- if (err) {
- err = -EINVAL;
+ if (err)
goto out;
- }
- control->value = indycam_ctrl.value;
+ err = camera_call(core, g_ctrl, control);
+ if (err)
+ err = -EINVAL;
break;
}
case VINO_INPUT_COMPOSITE:
case VINO_INPUT_SVIDEO: {
- struct saa7191_control saa7191_ctrl;
-
+ err = -EINVAL;
for (i = 0; i < VINO_SAA7191_V4L2_CONTROL_COUNT; i++) {
- if (vino_saa7191_v4l2_controls[i].id ==
- control->id) {
- goto found2;
+ if (vino_saa7191_v4l2_controls[i].id == control->id) {
+ err = 0;
+ break;
}
}
- err = -EINVAL;
- goto out;
-
-found2:
- saa7191_ctrl.type = vino_saa7191_v4l2_controls[i].reserved[0];
-
- err = i2c_decoder_command(DECODER_SAA7191_GET_CONTROL,
- &saa7191_ctrl);
- if (err) {
- err = -EINVAL;
+ if (err)
goto out;
- }
- control->value = saa7191_ctrl.value;
+ err = decoder_call(core, g_ctrl, control);
+ if (err)
+ err = -EINVAL;
break;
}
default:
@@ -3932,9 +3787,10 @@ out:
return err;
}
-static int vino_v4l2_s_ctrl(struct vino_channel_settings *vcs,
+static int vino_s_ctrl(struct file *file, void *__fh,
struct v4l2_control *control)
{
+ struct vino_channel_settings *vcs = video_drvdata(file);
unsigned long flags;
int i;
int err = 0;
@@ -3948,65 +3804,43 @@ static int vino_v4l2_s_ctrl(struct vino_channel_settings *vcs,
switch (vcs->input) {
case VINO_INPUT_D1: {
- struct indycam_control indycam_ctrl;
-
+ err = -EINVAL;
for (i = 0; i < VINO_INDYCAM_V4L2_CONTROL_COUNT; i++) {
- if (vino_indycam_v4l2_controls[i].id ==
- control->id) {
- if ((control->value >=
- vino_indycam_v4l2_controls[i].minimum)
- && (control->value <=
- vino_indycam_v4l2_controls[i].
- maximum)) {
- goto found1;
- } else {
- err = -ERANGE;
- goto out;
- }
+ if (vino_indycam_v4l2_controls[i].id == control->id) {
+ err = 0;
+ break;
}
}
-
- err = -EINVAL;
- goto out;
-
-found1:
- indycam_ctrl.type = vino_indycam_v4l2_controls[i].reserved[0];
- indycam_ctrl.value = control->value;
-
- err = i2c_camera_command(DECODER_INDYCAM_SET_CONTROL,
- &indycam_ctrl);
+ if (err)
+ goto out;
+ if (control->value < vino_indycam_v4l2_controls[i].minimum ||
+ control->value > vino_indycam_v4l2_controls[i].maximum) {
+ err = -ERANGE;
+ goto out;
+ }
+ err = camera_call(core, s_ctrl, control);
if (err)
err = -EINVAL;
break;
}
case VINO_INPUT_COMPOSITE:
case VINO_INPUT_SVIDEO: {
- struct saa7191_control saa7191_ctrl;
-
+ err = -EINVAL;
for (i = 0; i < VINO_SAA7191_V4L2_CONTROL_COUNT; i++) {
- if (vino_saa7191_v4l2_controls[i].id ==
- control->id) {
- if ((control->value >=
- vino_saa7191_v4l2_controls[i].minimum)
- && (control->value <=
- vino_saa7191_v4l2_controls[i].
- maximum)) {
- goto found2;
- } else {
- err = -ERANGE;
- goto out;
- }
+ if (vino_saa7191_v4l2_controls[i].id == control->id) {
+ err = 0;
+ break;
}
}
- err = -EINVAL;
- goto out;
-
-found2:
- saa7191_ctrl.type = vino_saa7191_v4l2_controls[i].reserved[0];
- saa7191_ctrl.value = control->value;
+ if (err)
+ goto out;
+ if (control->value < vino_saa7191_v4l2_controls[i].minimum ||
+ control->value > vino_saa7191_v4l2_controls[i].maximum) {
+ err = -ERANGE;
+ goto out;
+ }
- err = i2c_decoder_command(DECODER_SAA7191_SET_CONTROL,
- &saa7191_ctrl);
+ err = decoder_call(core, s_ctrl, control);
if (err)
err = -EINVAL;
break;
@@ -4237,116 +4071,9 @@ over:
ret = POLLIN | POLLRDNORM;
error:
-
return ret;
}
-static long vino_do_ioctl(struct file *file, unsigned int cmd, void *arg)
-{
- struct vino_channel_settings *vcs = video_drvdata(file);
-
-#ifdef VINO_DEBUG
- switch (_IOC_TYPE(cmd)) {
- case 'v':
- dprintk("ioctl(): V4L1 unsupported (0x%08x)\n", cmd);
- break;
- case 'V':
- dprintk("ioctl(): V4L2 %s (0x%08x)\n",
- v4l2_ioctl_names[_IOC_NR(cmd)], cmd);
- break;
- default:
- dprintk("ioctl(): unsupported command 0x%08x\n", cmd);
- }
-#endif
-
- switch (cmd) {
- /* V4L2 interface */
- case VIDIOC_QUERYCAP: {
- vino_v4l2_querycap(arg);
- break;
- }
- case VIDIOC_ENUMINPUT: {
- return vino_v4l2_enuminput(vcs, arg);
- }
- case VIDIOC_G_INPUT: {
- return vino_v4l2_g_input(vcs, arg);
- }
- case VIDIOC_S_INPUT: {
- return vino_v4l2_s_input(vcs, arg);
- }
- case VIDIOC_ENUMSTD: {
- return vino_v4l2_enumstd(vcs, arg);
- }
- case VIDIOC_QUERYSTD: {
- return vino_v4l2_querystd(vcs, arg);
- }
- case VIDIOC_G_STD: {
- return vino_v4l2_g_std(vcs, arg);
- }
- case VIDIOC_S_STD: {
- return vino_v4l2_s_std(vcs, arg);
- }
- case VIDIOC_ENUM_FMT: {
- return vino_v4l2_enum_fmt(vcs, arg);
- }
- case VIDIOC_TRY_FMT: {
- return vino_v4l2_try_fmt(vcs, arg);
- }
- case VIDIOC_G_FMT: {
- return vino_v4l2_g_fmt(vcs, arg);
- }
- case VIDIOC_S_FMT: {
- return vino_v4l2_s_fmt(vcs, arg);
- }
- case VIDIOC_CROPCAP: {
- return vino_v4l2_cropcap(vcs, arg);
- }
- case VIDIOC_G_CROP: {
- return vino_v4l2_g_crop(vcs, arg);
- }
- case VIDIOC_S_CROP: {
- return vino_v4l2_s_crop(vcs, arg);
- }
- case VIDIOC_G_PARM: {
- return vino_v4l2_g_parm(vcs, arg);
- }
- case VIDIOC_S_PARM: {
- return vino_v4l2_s_parm(vcs, arg);
- }
- case VIDIOC_REQBUFS: {
- return vino_v4l2_reqbufs(vcs, arg);
- }
- case VIDIOC_QUERYBUF: {
- return vino_v4l2_querybuf(vcs, arg);
- }
- case VIDIOC_QBUF: {
- return vino_v4l2_qbuf(vcs, arg);
- }
- case VIDIOC_DQBUF: {
- return vino_v4l2_dqbuf(vcs, arg, file->f_flags & O_NONBLOCK);
- }
- case VIDIOC_STREAMON: {
- return vino_v4l2_streamon(vcs);
- }
- case VIDIOC_STREAMOFF: {
- return vino_v4l2_streamoff(vcs);
- }
- case VIDIOC_QUERYCTRL: {
- return vino_v4l2_queryctrl(vcs, arg);
- }
- case VIDIOC_G_CTRL: {
- return vino_v4l2_g_ctrl(vcs, arg);
- }
- case VIDIOC_S_CTRL: {
- return vino_v4l2_s_ctrl(vcs, arg);
- }
- default:
- return -ENOIOCTLCMD;
- }
-
- return 0;
-}
-
static long vino_ioctl(struct file *file,
unsigned int cmd, unsigned long arg)
{
@@ -4356,7 +4083,7 @@ static long vino_ioctl(struct file *file,
if (mutex_lock_interruptible(&vcs->mutex))
return -EINTR;
- ret = video_usercopy(file, cmd, arg, vino_do_ioctl);
+ ret = video_ioctl2(file, cmd, arg);
mutex_unlock(&vcs->mutex);
@@ -4368,45 +4095,75 @@ static long vino_ioctl(struct file *file,
/* __initdata */
static int vino_init_stage;
+const struct v4l2_ioctl_ops vino_ioctl_ops = {
+ .vidioc_enum_fmt_vid_cap = vino_enum_fmt_vid_cap,
+ .vidioc_g_fmt_vid_cap = vino_g_fmt_vid_cap,
+ .vidioc_s_fmt_vid_cap = vino_s_fmt_vid_cap,
+ .vidioc_try_fmt_vid_cap = vino_try_fmt_vid_cap,
+ .vidioc_querycap = vino_querycap,
+ .vidioc_enum_input = vino_enum_input,
+ .vidioc_g_input = vino_g_input,
+ .vidioc_s_input = vino_s_input,
+ .vidioc_g_std = vino_g_std,
+ .vidioc_s_std = vino_s_std,
+ .vidioc_querystd = vino_querystd,
+ .vidioc_cropcap = vino_cropcap,
+ .vidioc_s_crop = vino_s_crop,
+ .vidioc_g_crop = vino_g_crop,
+ .vidioc_s_parm = vino_s_parm,
+ .vidioc_g_parm = vino_g_parm,
+ .vidioc_reqbufs = vino_reqbufs,
+ .vidioc_querybuf = vino_querybuf,
+ .vidioc_qbuf = vino_qbuf,
+ .vidioc_dqbuf = vino_dqbuf,
+ .vidioc_streamon = vino_streamon,
+ .vidioc_streamoff = vino_streamoff,
+ .vidioc_queryctrl = vino_queryctrl,
+ .vidioc_g_ctrl = vino_g_ctrl,
+ .vidioc_s_ctrl = vino_s_ctrl,
+};
+
static const struct v4l2_file_operations vino_fops = {
.owner = THIS_MODULE,
.open = vino_open,
.release = vino_close,
- .ioctl = vino_ioctl,
+ .unlocked_ioctl = vino_ioctl,
.mmap = vino_mmap,
.poll = vino_poll,
};
-static struct video_device v4l_device_template = {
+static struct video_device vdev_template = {
.name = "NOT SET",
.fops = &vino_fops,
+ .ioctl_ops = &vino_ioctl_ops,
+ .tvnorms = V4L2_STD_NTSC | V4L2_STD_PAL | V4L2_STD_SECAM,
.minor = -1,
};
static void vino_module_cleanup(int stage)
{
switch(stage) {
+ case 11:
+ video_unregister_device(vino_drvdata->b.vdev);
+ vino_drvdata->b.vdev = NULL;
case 10:
- video_unregister_device(vino_drvdata->b.v4l_device);
- vino_drvdata->b.v4l_device = NULL;
+ video_unregister_device(vino_drvdata->a.vdev);
+ vino_drvdata->a.vdev = NULL;
case 9:
- video_unregister_device(vino_drvdata->a.v4l_device);
- vino_drvdata->a.v4l_device = NULL;
+ i2c_del_adapter(&vino_i2c_adapter);
case 8:
- vino_i2c_del_bus();
- case 7:
free_irq(SGI_VINO_IRQ, NULL);
+ case 7:
+ if (vino_drvdata->b.vdev) {
+ video_device_release(vino_drvdata->b.vdev);
+ vino_drvdata->b.vdev = NULL;
+ }
case 6:
- if (vino_drvdata->b.v4l_device) {
- video_device_release(vino_drvdata->b.v4l_device);
- vino_drvdata->b.v4l_device = NULL;
+ if (vino_drvdata->a.vdev) {
+ video_device_release(vino_drvdata->a.vdev);
+ vino_drvdata->a.vdev = NULL;
}
case 5:
- if (vino_drvdata->a.v4l_device) {
- video_device_release(vino_drvdata->a.v4l_device);
- vino_drvdata->a.v4l_device = NULL;
- }
- case 4:
/* all entries in dma_cpu dummy table have the same address */
dma_unmap_single(NULL,
vino_drvdata->dummy_desc_table.dma_cpu[0],
@@ -4416,8 +4173,10 @@ static void vino_module_cleanup(int stage)
(void *)vino_drvdata->
dummy_desc_table.dma_cpu,
vino_drvdata->dummy_desc_table.dma);
- case 3:
+ case 4:
free_page(vino_drvdata->dummy_page);
+ case 3:
+ v4l2_device_unregister(&vino_drvdata->v4l2_dev);
case 2:
kfree(vino_drvdata);
case 1:
@@ -4472,6 +4231,7 @@ static int vino_probe(void)
static int vino_init(void)
{
dma_addr_t dma_dummy_address;
+ int err;
int i;
vino_drvdata = kzalloc(sizeof(struct vino_settings), GFP_KERNEL);
@@ -4480,6 +4240,12 @@ static int vino_init(void)
return -ENOMEM;
}
vino_init_stage++;
+ strlcpy(vino_drvdata->v4l2_dev.name, "vino",
+ sizeof(vino_drvdata->v4l2_dev.name));
+ err = v4l2_device_register(NULL, &vino_drvdata->v4l2_dev);
+ if (err)
+ return err;
+ vino_init_stage++;
/* create a dummy dma descriptor */
vino_drvdata->dummy_page = get_zeroed_page(GFP_KERNEL | GFP_DMA);
@@ -4546,25 +4312,27 @@ static int vino_init_channel_settings(struct vino_channel_settings *vcs,
spin_lock_init(&vcs->fb_queue.queue_lock);
init_waitqueue_head(&vcs->fb_queue.frame_wait_queue);
- vcs->v4l_device = video_device_alloc();
- if (!vcs->v4l_device) {
+ vcs->vdev = video_device_alloc();
+ if (!vcs->vdev) {
vino_module_cleanup(vino_init_stage);
return -ENOMEM;
}
vino_init_stage++;
- memcpy(vcs->v4l_device, &v4l_device_template,
+ memcpy(vcs->vdev, &vdev_template,
sizeof(struct video_device));
- strcpy(vcs->v4l_device->name, name);
- vcs->v4l_device->release = video_device_release;
+ strcpy(vcs->vdev->name, name);
+ vcs->vdev->release = video_device_release;
+ vcs->vdev->v4l2_dev = &vino_drvdata->v4l2_dev;
- video_set_drvdata(vcs->v4l_device, vcs);
+ video_set_drvdata(vcs->vdev, vcs);
return 0;
}
static int __init vino_module_init(void)
{
+ unsigned short addr[] = { 0, I2C_CLIENT_END };
int ret;
printk(KERN_INFO "SGI VINO driver version %s\n",
@@ -4584,12 +4352,12 @@ static int __init vino_module_init(void)
spin_lock_init(&vino_drvdata->input_lock);
ret = vino_init_channel_settings(&vino_drvdata->a, VINO_CHANNEL_A,
- vino_v4l_device_name_a);
+ vino_vdev_name_a);
if (ret)
return ret;
ret = vino_init_channel_settings(&vino_drvdata->b, VINO_CHANNEL_B,
- vino_v4l_device_name_b);
+ vino_vdev_name_b);
if (ret)
return ret;
@@ -4605,15 +4373,16 @@ static int __init vino_module_init(void)
}
vino_init_stage++;
- ret = vino_i2c_add_bus();
+ ret = i2c_add_adapter(&vino_i2c_adapter);
if (ret) {
printk(KERN_ERR "VINO I2C bus registration failed\n");
vino_module_cleanup(vino_init_stage);
return ret;
}
+ i2c_set_adapdata(&vino_i2c_adapter, &vino_drvdata->v4l2_dev);
vino_init_stage++;
- ret = video_register_device(vino_drvdata->a.v4l_device,
+ ret = video_register_device(vino_drvdata->a.vdev,
VFL_TYPE_GRABBER, -1);
if (ret < 0) {
printk(KERN_ERR "VINO channel A Video4Linux-device "
@@ -4623,7 +4392,7 @@ static int __init vino_module_init(void)
}
vino_init_stage++;
- ret = video_register_device(vino_drvdata->b.v4l_device,
+ ret = video_register_device(vino_drvdata->b.vdev,
VFL_TYPE_GRABBER, -1);
if (ret < 0) {
printk(KERN_ERR "VINO channel B Video4Linux-device "
@@ -4633,10 +4402,12 @@ static int __init vino_module_init(void)
}
vino_init_stage++;
-#ifdef MODULE
- request_module("saa7191");
- request_module("indycam");
-#endif
+ addr[0] = 0x45;
+ vino_drvdata->decoder = v4l2_i2c_new_probed_subdev(&vino_i2c_adapter,
+ "saa7191", "saa7191", addr);
+ addr[0] = 0x2b;
+ vino_drvdata->camera = v4l2_i2c_new_probed_subdev(&vino_i2c_adapter,
+ "indycam", "indycam", addr);
dprintk("init complete!\n");