Commit bda88e2f authored by Michael Hunold's avatar Michael Hunold Committed by Linus Torvalds

[PATCH] Update V4L2 "Hexium" driver

This updates my two Video4Linux-2 drivers for the "Hexium Gemini" and
"Hexium Orion" cards.

It adds the long missing input handling for the "Gemini" card and
removes the annoying compile time warning about unused structures.

 - remove various hexium header files, put all driver relevant
   informations into the drivers.  these informations are not needed
   anywhere else. 
 - fix driver names in information printk()s
 - fix device initialization for Hexium Gemini cards
 - add input switching for Hexium Gemini cards
 - fix all remaining "fixme"s
parent 5de0b192
#ifndef __HEXIUM__
#define __HEXIUM__
#define HEXIUM_HV_PCI6_ORION 1
#define HEXIUM_ORION_1SVHS_3BNC 2
#define HEXIUM_ORION_4BNC 3
#define HEXIUM_GEMUINI 4
#define HEXIUM_GEMUINI_DUAL 5
static struct saa7146_standard hexium_standards[] = {
{
.name = "PAL", .id = V4L2_STD_PAL,
.v_offset = 0x17, .v_field = 288, .v_calc = 576,
.h_offset = 0x14, .h_pixels = 680, .h_calc = 680+1,
.v_max_out = 576, .h_max_out = 768,
}, {
.name = "NTSC", .id = V4L2_STD_NTSC,
.v_offset = 0x17, .v_field = 240, .v_calc = 480,
.h_offset = 0x06, .h_pixels = 640, .h_calc = 641+1,
.v_max_out = 480, .h_max_out = 640,
}, {
.name = "SECAM", .id = V4L2_STD_SECAM,
.v_offset = 0x14, .v_field = 288, .v_calc = 576,
.h_offset = 0x14, .h_pixels = 720, .h_calc = 720+1,
.v_max_out = 576, .h_max_out = 768,
}
};
#define HEXIUM_INPUTS 9
static struct v4l2_input hexium_inputs[HEXIUM_INPUTS] = {
{ 0, "CVBS 1", V4L2_INPUT_TYPE_CAMERA, 2, 0, V4L2_STD_PAL_BG|V4L2_STD_NTSC_M, 0 },
{ 1, "CVBS 2", V4L2_INPUT_TYPE_CAMERA, 2, 0, V4L2_STD_PAL_BG|V4L2_STD_NTSC_M, 0 },
{ 2, "CVBS 3", V4L2_INPUT_TYPE_CAMERA, 2, 0, V4L2_STD_PAL_BG|V4L2_STD_NTSC_M, 0 },
{ 3, "CVBS 4", V4L2_INPUT_TYPE_CAMERA, 2, 0, V4L2_STD_PAL_BG|V4L2_STD_NTSC_M, 0 },
{ 4, "CVBS 5", V4L2_INPUT_TYPE_CAMERA, 2, 0, V4L2_STD_PAL_BG|V4L2_STD_NTSC_M, 0 },
{ 5, "CVBS 6", V4L2_INPUT_TYPE_CAMERA, 2, 0, V4L2_STD_PAL_BG|V4L2_STD_NTSC_M, 0 },
{ 6, "Y/C 1", V4L2_INPUT_TYPE_CAMERA, 2, 0, V4L2_STD_PAL_BG|V4L2_STD_NTSC_M, 0 },
{ 7, "Y/C 2", V4L2_INPUT_TYPE_CAMERA, 2, 0, V4L2_STD_PAL_BG|V4L2_STD_NTSC_M, 0 },
{ 8, "Y/C 3", V4L2_INPUT_TYPE_CAMERA, 2, 0, V4L2_STD_PAL_BG|V4L2_STD_NTSC_M, 0 },
};
#define HEXIUM_AUDIOS 0
struct hexium_data
{
s8 adr;
u8 byte;
};
#endif
...@@ -32,7 +32,148 @@ MODULE_PARM_DESC(debug, "debug verbosity"); ...@@ -32,7 +32,148 @@ MODULE_PARM_DESC(debug, "debug verbosity");
/* global variables */ /* global variables */
static int hexium_num = 0; static int hexium_num = 0;
#include "hexium_gemini.h" #define HEXIUM_GEMINI 4
#define HEXIUM_GEMINI_DUAL 5
#define HEXIUM_INPUTS 9
static struct v4l2_input hexium_inputs[HEXIUM_INPUTS] = {
{ 0, "CVBS 1", V4L2_INPUT_TYPE_CAMERA, 2, 0, V4L2_STD_PAL_BG|V4L2_STD_NTSC_M, 0 },
{ 1, "CVBS 2", V4L2_INPUT_TYPE_CAMERA, 2, 0, V4L2_STD_PAL_BG|V4L2_STD_NTSC_M, 0 },
{ 2, "CVBS 3", V4L2_INPUT_TYPE_CAMERA, 2, 0, V4L2_STD_PAL_BG|V4L2_STD_NTSC_M, 0 },
{ 3, "CVBS 4", V4L2_INPUT_TYPE_CAMERA, 2, 0, V4L2_STD_PAL_BG|V4L2_STD_NTSC_M, 0 },
{ 4, "CVBS 5", V4L2_INPUT_TYPE_CAMERA, 2, 0, V4L2_STD_PAL_BG|V4L2_STD_NTSC_M, 0 },
{ 5, "CVBS 6", V4L2_INPUT_TYPE_CAMERA, 2, 0, V4L2_STD_PAL_BG|V4L2_STD_NTSC_M, 0 },
{ 6, "Y/C 1", V4L2_INPUT_TYPE_CAMERA, 2, 0, V4L2_STD_PAL_BG|V4L2_STD_NTSC_M, 0 },
{ 7, "Y/C 2", V4L2_INPUT_TYPE_CAMERA, 2, 0, V4L2_STD_PAL_BG|V4L2_STD_NTSC_M, 0 },
{ 8, "Y/C 3", V4L2_INPUT_TYPE_CAMERA, 2, 0, V4L2_STD_PAL_BG|V4L2_STD_NTSC_M, 0 },
};
#define HEXIUM_AUDIOS 0
struct hexium_data
{
s8 adr;
u8 byte;
};
static struct saa7146_extension_ioctls ioctls[] = {
{ VIDIOC_G_INPUT, SAA7146_EXCLUSIVE },
{ VIDIOC_S_INPUT, SAA7146_EXCLUSIVE },
{ VIDIOC_QUERYCTRL, SAA7146_BEFORE },
{ VIDIOC_ENUMINPUT, SAA7146_EXCLUSIVE },
{ VIDIOC_S_STD, SAA7146_AFTER },
{ VIDIOC_G_CTRL, SAA7146_BEFORE },
{ VIDIOC_S_CTRL, SAA7146_BEFORE },
{ 0, 0 }
};
#define HEXIUM_CONTROLS 1
static struct v4l2_queryctrl hexium_controls[] = {
{ V4L2_CID_PRIVATE_BASE, V4L2_CTRL_TYPE_BOOLEAN, "B/W", 0, 1, 1, 0, 0 },
};
#define HEXIUM_GEMINI_V_1_0 1
#define HEXIUM_GEMINI_DUAL_V_1_0 2
struct hexium
{
int type;
struct video_device video_dev;
struct i2c_adapter i2c_adapter;
int cur_input; /* current input */
v4l2_std_id cur_std; /* current standard */
int cur_bw; /* current black/white status */
};
/* Samsung KS0127B decoder default registers */
static u8 hexium_ks0127b[0x100]={
/*00*/ 0x00,0x52,0x30,0x40,0x01,0x0C,0x2A,0x10,
/*08*/ 0x00,0x00,0x00,0x60,0x00,0x00,0x0F,0x06,
/*10*/ 0x00,0x00,0xE4,0xC0,0x00,0x00,0x00,0x00,
/*18*/ 0x14,0x9B,0xFE,0xFF,0xFC,0xFF,0x03,0x22,
/*20*/ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
/*28*/ 0x00,0x00,0x00,0x00,0x00,0x2C,0x9B,0x00,
/*30*/ 0x00,0x00,0x10,0x80,0x80,0x10,0x80,0x80,
/*38*/ 0x01,0x04,0x00,0x00,0x00,0x29,0xC0,0x00,
/*40*/ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
/*48*/ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
/*50*/ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
/*58*/ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
/*60*/ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
/*68*/ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
/*70*/ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
/*78*/ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
/*80*/ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
/*88*/ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
/*90*/ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
/*98*/ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
/*A0*/ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
/*A8*/ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
/*B0*/ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
/*B8*/ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
/*C0*/ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
/*C8*/ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
/*D0*/ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
/*D8*/ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
/*E0*/ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
/*E8*/ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
/*F0*/ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
/*F8*/ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00
};
static struct hexium_data hexium_pal[] = {
{ 0x01, 0x52 }, { 0x12, 0x64 }, { 0x2D, 0x2C }, { 0x2E, 0x9B }, { -1 , 0xFF }
};
static struct hexium_data hexium_pal_bw[] = {
{ 0x01, 0x52 }, { 0x12, 0x64 }, { 0x2D, 0x2C }, { 0x2E, 0x9B }, { -1 , 0xFF }
};
static struct hexium_data hexium_ntsc[] = {
{ 0x01, 0x53 }, { 0x12, 0x04 }, { 0x2D, 0x23 }, { 0x2E, 0x81 }, { -1 , 0xFF }
};
static struct hexium_data hexium_ntsc_bw[] = {
{ 0x01, 0x53 }, { 0x12, 0x04 }, { 0x2D, 0x23 }, { 0x2E, 0x81 }, { -1 , 0xFF }
};
static struct hexium_data hexium_secam[] = {
{ 0x01, 0x52 }, { 0x12, 0x64 }, { 0x2D, 0x2C }, { 0x2E, 0x9B }, { -1 , 0xFF }
};
static struct hexium_data hexium_input_select[] = {
{ 0x02, 0x60 },
{ 0x02, 0x64 },
{ 0x02, 0x61 },
{ 0x02, 0x65 },
{ 0x02, 0x62 },
{ 0x02, 0x66 },
{ 0x02, 0x68 },
{ 0x02, 0x69 },
{ 0x02, 0x6A },
};
/* fixme: h_offset = 0 for Hexium Gemini *Dual*, which
are currently *not* supported*/
static struct saa7146_standard hexium_standards[] = {
{
.name = "PAL", .id = V4L2_STD_PAL,
.v_offset = 28, .v_field = 288, .v_calc = 576,
.h_offset = 1, .h_pixels = 680, .h_calc = 680+1,
.v_max_out = 576, .h_max_out = 768,
}, {
.name = "NTSC", .id = V4L2_STD_NTSC,
.v_offset = 28, .v_field = 240, .v_calc = 480,
.h_offset = 1, .h_pixels = 640, .h_calc = 641+1,
.v_max_out = 480, .h_max_out = 640,
}, {
.name = "SECAM", .id = V4L2_STD_SECAM,
.v_offset = 28, .v_field = 288, .v_calc = 576,
.h_offset = 1, .h_pixels = 720, .h_calc = 720+1,
.v_max_out = 576, .h_max_out = 768,
}
};
/* bring hardware to a sane state. this has to be done, just in case someone /* bring hardware to a sane state. this has to be done, just in case someone
wants to capture from this device before it has been properly initialized. wants to capture from this device before it has been properly initialized.
...@@ -50,7 +191,7 @@ static int hexium_init_done(struct saa7146_dev *dev) ...@@ -50,7 +191,7 @@ static int hexium_init_done(struct saa7146_dev *dev)
for (i = 0; i < sizeof(hexium_ks0127b); i++) { for (i = 0; i < sizeof(hexium_ks0127b); i++) {
data.byte = hexium_ks0127b[i]; data.byte = hexium_ks0127b[i];
if (0 != i2c_smbus_xfer(&hexium->i2c_adapter, 0x6c, 0, I2C_SMBUS_WRITE, i, I2C_SMBUS_BYTE_DATA, &data)) { if (0 != i2c_smbus_xfer(&hexium->i2c_adapter, 0x6c, 0, I2C_SMBUS_WRITE, i, I2C_SMBUS_BYTE_DATA, &data)) {
printk("failed for address 0x%02x\n", i); printk("hexium_gemini: hexium_init_done() failed for address 0x%02x\n", i);
} }
} }
...@@ -81,7 +222,7 @@ static int hexium_set_standard(struct hexium *hexium, struct hexium_data *vdec) ...@@ -81,7 +222,7 @@ static int hexium_set_standard(struct hexium *hexium, struct hexium_data *vdec)
while (vdec[i].adr != -1) { while (vdec[i].adr != -1) {
data.byte = vdec[i].byte; data.byte = vdec[i].byte;
if (0 != i2c_smbus_xfer(&hexium->i2c_adapter, 0x6c, 0, I2C_SMBUS_WRITE, vdec[i].adr, I2C_SMBUS_BYTE_DATA, &data)) { if (0 != i2c_smbus_xfer(&hexium->i2c_adapter, 0x6c, 0, I2C_SMBUS_WRITE, vdec[i].adr, I2C_SMBUS_BYTE_DATA, &data)) {
printk("failed for address 0x%02x\n", i); printk("hexium_init_done: hexium_set_standard() failed for address 0x%02x\n", i);
return -1; return -1;
} }
i++; i++;
...@@ -100,14 +241,13 @@ static int hexium_attach(struct saa7146_dev *dev, struct saa7146_pci_extension_d ...@@ -100,14 +241,13 @@ static int hexium_attach(struct saa7146_dev *dev, struct saa7146_pci_extension_d
hexium = (struct hexium *) kmalloc(sizeof(struct hexium), GFP_KERNEL); hexium = (struct hexium *) kmalloc(sizeof(struct hexium), GFP_KERNEL);
if (NULL == hexium) { if (NULL == hexium) {
printk("hexium_v4l2.o: hexium_probe: not enough kernel memory.\n"); printk("hexium_gemini: not enough kernel memory in hexium_attach().\n");
return -ENOMEM; return -ENOMEM;
} }
memset(hexium, 0x0, sizeof(struct hexium)); memset(hexium, 0x0, sizeof(struct hexium));
(struct hexium *) dev->ext_priv = hexium; (struct hexium *) dev->ext_priv = hexium;
/* FIXME: enable i2c-port pins, video-port-pins /* enable i2c-port pins */
video port pins should be enabled here ?! */
saa7146_write(dev, MC1, (MASK_08 | MASK_24 | MASK_10 | MASK_26)); saa7146_write(dev, MC1, (MASK_08 | MASK_24 | MASK_10 | MASK_26));
saa7146_i2c_adapter_prepare(dev, &hexium->i2c_adapter, SAA7146_I2C_BUS_BIT_RATE_480); saa7146_i2c_adapter_prepare(dev, &hexium->i2c_adapter, SAA7146_I2C_BUS_BIT_RATE_480);
...@@ -135,12 +275,12 @@ static int hexium_attach(struct saa7146_dev *dev, struct saa7146_pci_extension_d ...@@ -135,12 +275,12 @@ static int hexium_attach(struct saa7146_dev *dev, struct saa7146_pci_extension_d
hexium->cur_input = 0; hexium->cur_input = 0;
saa7146_vv_init(dev, &vv_data); saa7146_vv_init(dev, &vv_data);
if (0 != saa7146_register_device(&hexium->video_dev, dev, "hexium", VFL_TYPE_GRABBER)) { if (0 != saa7146_register_device(&hexium->video_dev, dev, "hexium gemini", VFL_TYPE_GRABBER)) {
ERR(("cannot register capture v4l2 device. skipping.\n")); printk("hexium_gemini: cannot register capture v4l2 device. skipping.\n");
return -1; return -1;
} }
printk("hexium: found 'hexium frame grabber'-%d.\n", hexium_num); printk("hexium_gemini: found 'hexium gemini' frame grabber-%d.\n", hexium_num);
hexium_num++; hexium_num++;
return 0; return 0;
...@@ -302,7 +442,7 @@ static int hexium_ioctl(struct saa7146_fh *fh, unsigned int cmd, void *arg) ...@@ -302,7 +442,7 @@ static int hexium_ioctl(struct saa7146_fh *fh, unsigned int cmd, void *arg)
} }
default: default:
/* /*
DEB_D(("v4l2_ioctl does not handle this ioctl.\n")); DEB_D(("hexium_ioctl() does not handle this ioctl.\n"));
*/ */
return -ENOIOCTLCMD; return -ENOIOCTLCMD;
} }
......
#ifndef __HEXIUM_GEMINI__
#define __HEXIUM_GEMINI__
#include "hexium.h"
static struct saa7146_extension_ioctls ioctls[] = {
{ VIDIOC_G_INPUT, SAA7146_EXCLUSIVE },
{ VIDIOC_S_INPUT, SAA7146_EXCLUSIVE },
{ VIDIOC_QUERYCTRL, SAA7146_BEFORE },
{ VIDIOC_ENUMINPUT, SAA7146_EXCLUSIVE },
{ VIDIOC_S_STD, SAA7146_AFTER },
{ VIDIOC_G_CTRL, SAA7146_BEFORE },
{ VIDIOC_S_CTRL, SAA7146_BEFORE },
{ 0, 0 }
};
#define HEXIUM_CONTROLS 1
static struct v4l2_queryctrl hexium_controls[] = {
{ V4L2_CID_PRIVATE_BASE, V4L2_CTRL_TYPE_BOOLEAN, "B/W", 0, 1, 1, 0, 0 },
};
#define HEXIUM_GEMUINI_V_1_0 1
#define HEXIUM_GEMUINI_DUAL_V_1_0 2
struct hexium
{
int type;
struct video_device video_dev;
struct i2c_adapter i2c_adapter;
int cur_input; /* current input */
v4l2_std_id cur_std; /* current standard */
int cur_bw; /* current black/white status */
};
/* Samsung KS0127B decoder default registers */
static u8 hexium_ks0127b[0x100]={
/*00*/ 0x00,0x52,0x30,0x40,0x01,0x0C,0x2A,0x10,
/*08*/ 0x00,0x00,0x00,0x60,0x00,0x00,0x0F,0x06,
/*10*/ 0x00,0x00,0xE4,0xC0,0x00,0x00,0x00,0x00,
/*18*/ 0x14,0x9B,0xFE,0xFF,0xFC,0xFF,0x03,0x22,
/*20*/ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
/*28*/ 0x00,0x00,0x00,0x00,0x00,0x2C,0x9B,0x00,
/*30*/ 0x00,0x00,0x10,0x80,0x80,0x10,0x80,0x80,
/*38*/ 0x01,0x04,0x00,0x00,0x00,0x29,0xC0,0x00,
/*40*/ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
/*48*/ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
/*50*/ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
/*58*/ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
/*60*/ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
/*68*/ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
/*70*/ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
/*78*/ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
/*80*/ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
/*88*/ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
/*90*/ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
/*98*/ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
/*A0*/ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
/*A8*/ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
/*B0*/ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
/*B8*/ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
/*C0*/ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
/*C8*/ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
/*D0*/ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
/*D8*/ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
/*E0*/ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
/*E8*/ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
/*F0*/ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
/*F8*/ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00
};
static struct hexium_data hexium_pal[] = {
{ 0x01, 0x52 }, { 0x12, 0x64 }, { 0x2D, 0x2C }, { 0x2E, 0x9B }, { -1 , 0xFF }
};
static struct hexium_data hexium_pal_bw[] = {
{ 0x01, 0x52 }, { 0x12, 0x64 }, { 0x2D, 0x2C }, { 0x2E, 0x9B }, { -1 , 0xFF }
};
static struct hexium_data hexium_ntsc[] = {
{ 0x01, 0x53 }, { 0x12, 0x04 }, { 0x2D, 0x23 }, { 0x2E, 0x81 }, { -1 , 0xFF }
};
static struct hexium_data hexium_ntsc_bw[] = {
{ 0x01, 0x53 }, { 0x12, 0x04 }, { 0x2D, 0x23 }, { 0x2E, 0x81 }, { -1 , 0xFF }
};
static struct hexium_data hexium_secam[] = {
{ 0x01, 0x52 }, { 0x12, 0x64 }, { 0x2D, 0x2C }, { 0x2E, 0x9B }, { -1 , 0xFF }
};
static struct hexium_data hexium_input_select[] = {
{ 0x02, 0x60 },
{ 0x02, 0x64 },
{ 0x02, 0x61 },
{ 0x02, 0x65 },
{ 0x02, 0x62 },
{ 0x02, 0x66 },
{ 0x02, 0x68 },
{ 0x02, 0x69 },
{ 0x02, 0x6A },
};
#endif
...@@ -30,9 +30,183 @@ MODULE_PARM(debug, "i"); ...@@ -30,9 +30,183 @@ MODULE_PARM(debug, "i");
MODULE_PARM_DESC(debug, "debug verbosity"); MODULE_PARM_DESC(debug, "debug verbosity");
/* global variables */ /* global variables */
int hexium_num = 0; static int hexium_num = 0;
#define HEXIUM_HV_PCI6_ORION 1
#define HEXIUM_ORION_1SVHS_3BNC 2
#define HEXIUM_ORION_4BNC 3
#define HEXIUM_INPUTS 9
static struct v4l2_input hexium_inputs[HEXIUM_INPUTS] = {
{ 0, "CVBS 1", V4L2_INPUT_TYPE_CAMERA, 2, 0, V4L2_STD_PAL_BG|V4L2_STD_NTSC_M, 0 },
{ 1, "CVBS 2", V4L2_INPUT_TYPE_CAMERA, 2, 0, V4L2_STD_PAL_BG|V4L2_STD_NTSC_M, 0 },
{ 2, "CVBS 3", V4L2_INPUT_TYPE_CAMERA, 2, 0, V4L2_STD_PAL_BG|V4L2_STD_NTSC_M, 0 },
{ 3, "CVBS 4", V4L2_INPUT_TYPE_CAMERA, 2, 0, V4L2_STD_PAL_BG|V4L2_STD_NTSC_M, 0 },
{ 4, "CVBS 5", V4L2_INPUT_TYPE_CAMERA, 2, 0, V4L2_STD_PAL_BG|V4L2_STD_NTSC_M, 0 },
{ 5, "CVBS 6", V4L2_INPUT_TYPE_CAMERA, 2, 0, V4L2_STD_PAL_BG|V4L2_STD_NTSC_M, 0 },
{ 6, "Y/C 1", V4L2_INPUT_TYPE_CAMERA, 2, 0, V4L2_STD_PAL_BG|V4L2_STD_NTSC_M, 0 },
{ 7, "Y/C 2", V4L2_INPUT_TYPE_CAMERA, 2, 0, V4L2_STD_PAL_BG|V4L2_STD_NTSC_M, 0 },
{ 8, "Y/C 3", V4L2_INPUT_TYPE_CAMERA, 2, 0, V4L2_STD_PAL_BG|V4L2_STD_NTSC_M, 0 },
};
#define HEXIUM_AUDIOS 0
struct hexium_data
{
s8 adr;
u8 byte;
};
static struct saa7146_extension_ioctls ioctls[] = {
{ VIDIOC_G_INPUT, SAA7146_EXCLUSIVE },
{ VIDIOC_S_INPUT, SAA7146_EXCLUSIVE },
{ VIDIOC_ENUMINPUT, SAA7146_EXCLUSIVE },
{ VIDIOC_S_STD, SAA7146_AFTER },
{ 0, 0 }
};
struct hexium
{
int type;
struct video_device video_dev;
struct i2c_adapter i2c_adapter;
int cur_input; /* current input */
};
#include "hexium_orion.h" /* Philips SAA7110 decoder default registers */
static u8 hexium_saa7110[53]={
/*00*/ 0x4C,0x3C,0x0D,0xEF,0xBD,0xF0,0x00,0x00,
/*08*/ 0xF8,0xF8,0x60,0x60,0x40,0x86,0x18,0x90,
/*10*/ 0x00,0x2C,0x40,0x46,0x42,0x1A,0xFF,0xDA,
/*18*/ 0xF0,0x8B,0x00,0x00,0x00,0x00,0x00,0x00,
/*20*/ 0xD9,0x17,0x40,0x41,0x80,0x41,0x80,0x4F,
/*28*/ 0xFE,0x01,0x0F,0x0F,0x03,0x01,0x81,0x03,
/*30*/ 0x44,0x75,0x01,0x8C,0x03
};
static struct {
struct hexium_data data[8];
} hexium_input_select[] = {
{
{ /* cvbs 1 */
{ 0x06, 0x00 },
{ 0x20, 0xD9 },
{ 0x21, 0x17 }, // 0x16,
{ 0x22, 0x40 },
{ 0x2C, 0x03 },
{ 0x30, 0x44 },
{ 0x31, 0x75 }, // ??
{ 0x21, 0x16 }, // 0x03,
}
}, {
{ /* cvbs 2 */
{ 0x06, 0x00 },
{ 0x20, 0x78 },
{ 0x21, 0x07 }, // 0x03,
{ 0x22, 0xD2 },
{ 0x2C, 0x83 },
{ 0x30, 0x60 },
{ 0x31, 0xB5 }, // ?
{ 0x21, 0x03 },
}
}, {
{ /* cvbs 3 */
{ 0x06, 0x00 },
{ 0x20, 0xBA },
{ 0x21, 0x07 }, // 0x05,
{ 0x22, 0x91 },
{ 0x2C, 0x03 },
{ 0x30, 0x60 },
{ 0x31, 0xB5 }, // ??
{ 0x21, 0x05 }, // 0x03,
}
}, {
{ /* cvbs 4 */
{ 0x06, 0x00 },
{ 0x20, 0xD8 },
{ 0x21, 0x17 }, // 0x16,
{ 0x22, 0x40 },
{ 0x2C, 0x03 },
{ 0x30, 0x44 },
{ 0x31, 0x75 }, // ??
{ 0x21, 0x16 }, // 0x03,
}
}, {
{ /* cvbs 5 */
{ 0x06, 0x00 },
{ 0x20, 0xB8 },
{ 0x21, 0x07 }, // 0x05,
{ 0x22, 0x91 },
{ 0x2C, 0x03 },
{ 0x30, 0x60 },
{ 0x31, 0xB5 }, // ??
{ 0x21, 0x05 }, // 0x03,
}
}, {
{ /* cvbs 6 */
{ 0x06, 0x00 },
{ 0x20, 0x7C },
{ 0x21, 0x07 }, // 0x03
{ 0x22, 0xD2 },
{ 0x2C, 0x83 },
{ 0x30, 0x60 },
{ 0x31, 0xB5 }, // ??
{ 0x21, 0x03 },
}
}, {
{ /* y/c 1 */
{ 0x06, 0x80 },
{ 0x20, 0x59 },
{ 0x21, 0x17 },
{ 0x22, 0x42 },
{ 0x2C, 0xA3 },
{ 0x30, 0x44 },
{ 0x31, 0x75 },
{ 0x21, 0x12 },
}
}, {
{ /* y/c 2 */
{ 0x06, 0x80 },
{ 0x20, 0x9A },
{ 0x21, 0x17 },
{ 0x22, 0xB1 },
{ 0x2C, 0x13 },
{ 0x30, 0x60 },
{ 0x31, 0xB5 },
{ 0x21, 0x14 },
}
}, {
{ /* y/c 3 */
{ 0x06, 0x80 },
{ 0x20, 0x3C },
{ 0x21, 0x27 },
{ 0x22, 0xC1 },
{ 0x2C, 0x23 },
{ 0x30, 0x44 },
{ 0x31, 0x75 },
{ 0x21, 0x21 },
}
}
};
static struct saa7146_standard hexium_standards[] = {
{
.name = "PAL", .id = V4L2_STD_PAL,
.v_offset = 16, .v_field = 288, .v_calc = 576,
.h_offset = 1, .h_pixels = 680, .h_calc = 680+1,
.v_max_out = 576, .h_max_out = 768,
}, {
.name = "NTSC", .id = V4L2_STD_NTSC,
.v_offset = 16, .v_field = 240, .v_calc = 480,
.h_offset = 1, .h_pixels = 640, .h_calc = 641+1,
.v_max_out = 480, .h_max_out = 640,
}, {
.name = "SECAM", .id = V4L2_STD_SECAM,
.v_offset = 16, .v_field = 288, .v_calc = 576,
.h_offset = 1, .h_pixels = 720, .h_calc = 720+1,
.v_max_out = 576, .h_max_out = 768,
}
};
/* this is only called for old HV-PCI6/Orion cards /* this is only called for old HV-PCI6/Orion cards
without eeprom */ without eeprom */
...@@ -51,16 +225,15 @@ static int hexium_probe(struct saa7146_dev *dev) ...@@ -51,16 +225,15 @@ static int hexium_probe(struct saa7146_dev *dev)
hexium = (struct hexium *) kmalloc(sizeof(struct hexium), GFP_KERNEL); hexium = (struct hexium *) kmalloc(sizeof(struct hexium), GFP_KERNEL);
if (NULL == hexium) { if (NULL == hexium) {
printk("hexium_orion.o: hexium_probe: not enough kernel memory.\n"); printk("hexium_orion: hexium_probe: not enough kernel memory.\n");
return -ENOMEM; return -ENOMEM;
} }
memset(hexium, 0x0, sizeof(struct hexium)); memset(hexium, 0x0, sizeof(struct hexium));
/* FIXME: enable i2c-port pins, video-port-pins /* enable i2c-port pins */
video port pins should be enabled here ?! */
saa7146_write(dev, MC1, (MASK_08 | MASK_24 | MASK_10 | MASK_26)); saa7146_write(dev, MC1, (MASK_08 | MASK_24 | MASK_10 | MASK_26));
saa7146_write(dev, DD1_INIT, 0x02000200); saa7146_write(dev, DD1_INIT, 0x01000100);
saa7146_write(dev, DD1_STREAM_B, 0x00000000); saa7146_write(dev, DD1_STREAM_B, 0x00000000);
saa7146_write(dev, MC2, (MASK_09 | MASK_25 | MASK_10 | MASK_26)); saa7146_write(dev, MC2, (MASK_09 | MASK_25 | MASK_10 | MASK_26));
...@@ -80,7 +253,7 @@ static int hexium_probe(struct saa7146_dev *dev) ...@@ -80,7 +253,7 @@ static int hexium_probe(struct saa7146_dev *dev)
/* detect newer Hexium Orion cards by subsystem ids */ /* detect newer Hexium Orion cards by subsystem ids */
if (0x17c8 == dev->pci->subsystem_vendor && 0x0101 == dev->pci->subsystem_device) { if (0x17c8 == dev->pci->subsystem_vendor && 0x0101 == dev->pci->subsystem_device) {
printk("hexium_orion.o: device is a Hexium Orion w/ 1 SVHS + 3 BNC inputs.\n"); printk("hexium_orion: device is a Hexium Orion w/ 1 SVHS + 3 BNC inputs.\n");
/* we store the pointer in our private data field */ /* we store the pointer in our private data field */
(struct hexium *) dev->ext_priv = hexium; (struct hexium *) dev->ext_priv = hexium;
hexium->type = HEXIUM_ORION_1SVHS_3BNC; hexium->type = HEXIUM_ORION_1SVHS_3BNC;
...@@ -88,7 +261,7 @@ static int hexium_probe(struct saa7146_dev *dev) ...@@ -88,7 +261,7 @@ static int hexium_probe(struct saa7146_dev *dev)
} }
if (0x17c8 == dev->pci->subsystem_vendor && 0x2101 == dev->pci->subsystem_device) { if (0x17c8 == dev->pci->subsystem_vendor && 0x2101 == dev->pci->subsystem_device) {
printk("hexium_orion.o: device is a Hexium Orion w/ 4 BNC inputs.\n"); printk("hexium_orion: device is a Hexium Orion w/ 4 BNC inputs.\n");
/* we store the pointer in our private data field */ /* we store the pointer in our private data field */
(struct hexium *) dev->ext_priv = hexium; (struct hexium *) dev->ext_priv = hexium;
hexium->type = HEXIUM_ORION_4BNC; hexium->type = HEXIUM_ORION_4BNC;
...@@ -98,7 +271,7 @@ static int hexium_probe(struct saa7146_dev *dev) ...@@ -98,7 +271,7 @@ static int hexium_probe(struct saa7146_dev *dev)
/* check if this is an old hexium Orion card by looking at /* check if this is an old hexium Orion card by looking at
a saa7110 at address 0x4e */ a saa7110 at address 0x4e */
if (0 == (err = i2c_smbus_xfer(&hexium->i2c_adapter, 0x4e, 0, I2C_SMBUS_READ, 0x00, I2C_SMBUS_BYTE_DATA, &data))) { if (0 == (err = i2c_smbus_xfer(&hexium->i2c_adapter, 0x4e, 0, I2C_SMBUS_READ, 0x00, I2C_SMBUS_BYTE_DATA, &data))) {
printk("hexium_orion.o: device is a Hexium HV-PCI6/Orion (old).\n"); printk("hexium_orion: device is a Hexium HV-PCI6/Orion (old).\n");
/* we store the pointer in our private data field */ /* we store the pointer in our private data field */
(struct hexium *) dev->ext_priv = hexium; (struct hexium *) dev->ext_priv = hexium;
hexium->type = HEXIUM_HV_PCI6_ORION; hexium->type = HEXIUM_HV_PCI6_ORION;
...@@ -133,6 +306,25 @@ static int hexium_init_done(struct saa7146_dev *dev) ...@@ -133,6 +306,25 @@ static int hexium_init_done(struct saa7146_dev *dev)
return 0; return 0;
} }
static int hexium_set_input(struct hexium *hexium, int input)
{
union i2c_smbus_data data;
int i = 0;
DEB_D((".\n"));
for (i = 0; i < 8; i++) {
int adr = hexium_input_select[input].data[i].adr;
data.byte = hexium_input_select[input].data[i].byte;
if (0 != i2c_smbus_xfer(&hexium->i2c_adapter, 0x4e, 0, I2C_SMBUS_WRITE, adr, I2C_SMBUS_BYTE_DATA, &data)) {
return -1;
}
printk("%d: 0x%02x => 0x%02x\n",input, adr,data.byte);
}
return 0;
}
static struct saa7146_ext_vv vv_data; static struct saa7146_ext_vv vv_data;
/* this function only gets called when the probing was successful */ /* this function only gets called when the probing was successful */
...@@ -143,12 +335,12 @@ static int hexium_attach(struct saa7146_dev *dev, struct saa7146_pci_extension_d ...@@ -143,12 +335,12 @@ static int hexium_attach(struct saa7146_dev *dev, struct saa7146_pci_extension_d
DEB_EE((".\n")); DEB_EE((".\n"));
saa7146_vv_init(dev, &vv_data); saa7146_vv_init(dev, &vv_data);
if (0 != saa7146_register_device(&hexium->video_dev, dev, "hexium", VFL_TYPE_GRABBER)) { if (0 != saa7146_register_device(&hexium->video_dev, dev, "hexium orion", VFL_TYPE_GRABBER)) {
ERR(("cannot register capture v4l2 device. skipping.\n")); printk("hexium_orion: cannot register capture v4l2 device. skipping.\n");
return -1; return -1;
} }
printk("hexium_orion.o: found 'hexium orion' frame grabber-%d.\n", hexium_num); printk("hexium_orion: found 'hexium orion' frame grabber-%d.\n", hexium_num);
hexium_num++; hexium_num++;
/* the rest */ /* the rest */
...@@ -213,16 +405,13 @@ static int hexium_ioctl(struct saa7146_fh *fh, unsigned int cmd, void *arg) ...@@ -213,16 +405,13 @@ static int hexium_ioctl(struct saa7146_fh *fh, unsigned int cmd, void *arg)
} }
hexium->cur_input = input; hexium->cur_input = input;
hexium_set_input(hexium, input);
/* fixme: switch input here, switch audio, too! */
// saa7146_set_hps_source_and_sync(dev, input_port_selection[input].hps_source, input_port_selection[input].hps_sync);
printk("hexium_orion.o: VIDIOC_S_INPUT: fixme switch input.\n");
return 0; return 0;
} }
default: default:
/* /*
DEB_D(("v4l2_ioctl does not handle this ioctl.\n")); DEB_D(("hexium_ioctl() does not handle this ioctl.\n"));
*/ */
return -ENOIOCTLCMD; return -ENOIOCTLCMD;
} }
......
#ifndef __HEXIUM_ORION__
#define __HEXIUM_ORION__
#include "hexium.h"
static struct saa7146_extension_ioctls ioctls[] = {
{ VIDIOC_G_INPUT, SAA7146_EXCLUSIVE },
{ VIDIOC_S_INPUT, SAA7146_EXCLUSIVE },
{ VIDIOC_ENUMINPUT, SAA7146_EXCLUSIVE },
{ VIDIOC_S_STD, SAA7146_AFTER },
{ 0, 0 }
};
struct hexium
{
int type;
struct video_device video_dev;
struct i2c_adapter i2c_adapter;
int cur_input; /* current input */
};
/* Philips SAA7110 decoder default registers */
static u8 hexium_saa7110[53]={
/*00*/ 0x4C,0x3C,0x0D,0xEF,0xBD,0xF0,0x00,0x00,
/*08*/ 0xF8,0xF8,0x60,0x60,0x40,0x86,0x18,0x90,
/*10*/ 0x00,0x2C,0x40,0x46,0x42,0x1A,0xFF,0xDA,
/*18*/ 0xF0,0x8B,0x00,0x00,0x00,0x00,0x00,0x00,
/*20*/ 0xD9,0x17,0x40,0x41,0x80,0x41,0x80,0x4F,
/*28*/ 0xFE,0x01,0x0F,0x0F,0x03,0x01,0x81,0x03,
/*30*/ 0x44,0x75,0x01,0x8C,0x03
};
static struct {
struct hexium_data data[8];
} hexium_input_select[] = {
{
{ /* input 0 */
{ 0x06, 0x00 },
{ 0x20, 0xD9 },
{ 0x21, 0x17 }, // 0x16,
{ 0x22, 0x40 },
{ 0x2C, 0x03 },
{ 0x30, 0x44 },
{ 0x31, 0x75 }, // ??
{ 0x21, 0x16 }, // 0x03,
}
}, {
{ /* input 1 */
{ 0x06, 0x00 },
{ 0x20, 0xD8 },
{ 0x21, 0x17 }, // 0x16,
{ 0x22, 0x40 },
{ 0x2C, 0x03 },
{ 0x30, 0x44 },
{ 0x31, 0x75 }, // ??
{ 0x21, 0x16 }, // 0x03,
}
}, {
{ /* input 2 */
{ 0x06, 0x00 },
{ 0x20, 0xBA },
{ 0x21, 0x07 }, // 0x05,
{ 0x22, 0x91 },
{ 0x2C, 0x03 },
{ 0x30, 0x60 },
{ 0x31, 0xB5 }, // ??
{ 0x21, 0x05 }, // 0x03,
}
}, {
{ /* input 3 */
{ 0x06, 0x00 },
{ 0x20, 0xB8 },
{ 0x21, 0x07 }, // 0x05,
{ 0x22, 0x91 },
{ 0x2C, 0x03 },
{ 0x30, 0x60 },
{ 0x31, 0xB5 }, // ??
{ 0x21, 0x05 }, // 0x03,
}
}, {
{ /* input 4 */
{ 0x06, 0x00 },
{ 0x20, 0x7C },
{ 0x21, 0x07 }, // 0x03
{ 0x22, 0xD2 },
{ 0x2C, 0x83 },
{ 0x30, 0x60 },
{ 0x31, 0xB5 }, // ??
{ 0x21, 0x03 },
}
}, {
{ /* input 5 */
{ 0x06, 0x00 },
{ 0x20, 0x78 },
{ 0x21, 0x07 }, // 0x03,
{ 0x22, 0xD2 },
{ 0x2C, 0x83 },
{ 0x30, 0x60 },
{ 0x31, 0xB5 }, // ?
{ 0x21, 0x03 },
}
}, {
{ /* input 6 */
{ 0x06, 0x80 },
{ 0x20, 0x59 },
{ 0x21, 0x17 },
{ 0x22, 0x42 },
{ 0x2C, 0xA3 },
{ 0x30, 0x44 },
{ 0x31, 0x75 },
{ 0x21, 0x12 },
}
}, {
{ /* input 7 */
{ 0x06, 0x80 },
{ 0x20, 0x9A },
{ 0x21, 0x17 },
{ 0x22, 0xB1 },
{ 0x2C, 0x13 },
{ 0x30, 0x60 },
{ 0x31, 0xB5 },
{ 0x21, 0x14 },
}
}, {
{ /* input 8 */
{ 0x06, 0x80 },
{ 0x20, 0x3C },
{ 0x21, 0x27 },
{ 0x22, 0xC1 },
{ 0x2C, 0x23 },
{ 0x30, 0x44 },
{ 0x31, 0x75 },
{ 0x21, 0x21 },
}
}
};
#endif
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment