0001
0002
0003
0004
0005
0006
0007
0008
0009
0010
0011
0012 #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
0013
0014 #define DEBUG_VARIABLE debug
0015
0016 #include <media/drv-intf/saa7146_vv.h>
0017 #include <linux/module.h>
0018 #include <linux/kernel.h>
0019
0020 static int debug;
0021 module_param(debug, int, 0);
0022 MODULE_PARM_DESC(debug, "debug verbosity");
0023
0024
0025 static int hexium_num;
0026
0027 #define HEXIUM_GEMINI 4
0028 #define HEXIUM_GEMINI_DUAL 5
0029
0030 #define HEXIUM_INPUTS 9
0031 static struct v4l2_input hexium_inputs[HEXIUM_INPUTS] = {
0032 { 0, "CVBS 1", V4L2_INPUT_TYPE_CAMERA, 0, 0, V4L2_STD_ALL, 0, V4L2_IN_CAP_STD },
0033 { 1, "CVBS 2", V4L2_INPUT_TYPE_CAMERA, 0, 0, V4L2_STD_ALL, 0, V4L2_IN_CAP_STD },
0034 { 2, "CVBS 3", V4L2_INPUT_TYPE_CAMERA, 0, 0, V4L2_STD_ALL, 0, V4L2_IN_CAP_STD },
0035 { 3, "CVBS 4", V4L2_INPUT_TYPE_CAMERA, 0, 0, V4L2_STD_ALL, 0, V4L2_IN_CAP_STD },
0036 { 4, "CVBS 5", V4L2_INPUT_TYPE_CAMERA, 0, 0, V4L2_STD_ALL, 0, V4L2_IN_CAP_STD },
0037 { 5, "CVBS 6", V4L2_INPUT_TYPE_CAMERA, 0, 0, V4L2_STD_ALL, 0, V4L2_IN_CAP_STD },
0038 { 6, "Y/C 1", V4L2_INPUT_TYPE_CAMERA, 0, 0, V4L2_STD_ALL, 0, V4L2_IN_CAP_STD },
0039 { 7, "Y/C 2", V4L2_INPUT_TYPE_CAMERA, 0, 0, V4L2_STD_ALL, 0, V4L2_IN_CAP_STD },
0040 { 8, "Y/C 3", V4L2_INPUT_TYPE_CAMERA, 0, 0, V4L2_STD_ALL, 0, V4L2_IN_CAP_STD },
0041 };
0042
0043 #define HEXIUM_AUDIOS 0
0044
0045 struct hexium_data
0046 {
0047 s8 adr;
0048 u8 byte;
0049 };
0050
0051 #define HEXIUM_GEMINI_V_1_0 1
0052 #define HEXIUM_GEMINI_DUAL_V_1_0 2
0053
0054 struct hexium
0055 {
0056 int type;
0057
0058 struct video_device video_dev;
0059 struct i2c_adapter i2c_adapter;
0060
0061 int cur_input;
0062 v4l2_std_id cur_std;
0063 };
0064
0065
0066 static u8 hexium_ks0127b[0x100]={
0067 0x00,0x52,0x30,0x40,0x01,0x0C,0x2A,0x10,
0068 0x00,0x00,0x00,0x60,0x00,0x00,0x0F,0x06,
0069 0x00,0x00,0xE4,0xC0,0x00,0x00,0x00,0x00,
0070 0x14,0x9B,0xFE,0xFF,0xFC,0xFF,0x03,0x22,
0071 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
0072 0x00,0x00,0x00,0x00,0x00,0x2C,0x9B,0x00,
0073 0x00,0x00,0x10,0x80,0x80,0x10,0x80,0x80,
0074 0x01,0x04,0x00,0x00,0x00,0x29,0xC0,0x00,
0075 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
0076 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
0077 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
0078 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
0079 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
0080 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
0081 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
0082 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
0083 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
0084 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
0085 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
0086 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
0087 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
0088 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
0089 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
0090 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
0091 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
0092 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
0093 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
0094 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
0095 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
0096 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
0097 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
0098 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00
0099 };
0100
0101 static struct hexium_data hexium_pal[] = {
0102 { 0x01, 0x52 }, { 0x12, 0x64 }, { 0x2D, 0x2C }, { 0x2E, 0x9B }, { -1 , 0xFF }
0103 };
0104
0105 static struct hexium_data hexium_ntsc[] = {
0106 { 0x01, 0x53 }, { 0x12, 0x04 }, { 0x2D, 0x23 }, { 0x2E, 0x81 }, { -1 , 0xFF }
0107 };
0108
0109 static struct hexium_data hexium_secam[] = {
0110 { 0x01, 0x52 }, { 0x12, 0x64 }, { 0x2D, 0x2C }, { 0x2E, 0x9B }, { -1 , 0xFF }
0111 };
0112
0113 static struct hexium_data hexium_input_select[] = {
0114 { 0x02, 0x60 },
0115 { 0x02, 0x64 },
0116 { 0x02, 0x61 },
0117 { 0x02, 0x65 },
0118 { 0x02, 0x62 },
0119 { 0x02, 0x66 },
0120 { 0x02, 0x68 },
0121 { 0x02, 0x69 },
0122 { 0x02, 0x6A },
0123 };
0124
0125
0126
0127 static struct saa7146_standard hexium_standards[] = {
0128 {
0129 .name = "PAL", .id = V4L2_STD_PAL,
0130 .v_offset = 28, .v_field = 288,
0131 .h_offset = 1, .h_pixels = 680,
0132 .v_max_out = 576, .h_max_out = 768,
0133 }, {
0134 .name = "NTSC", .id = V4L2_STD_NTSC,
0135 .v_offset = 28, .v_field = 240,
0136 .h_offset = 1, .h_pixels = 640,
0137 .v_max_out = 480, .h_max_out = 640,
0138 }, {
0139 .name = "SECAM", .id = V4L2_STD_SECAM,
0140 .v_offset = 28, .v_field = 288,
0141 .h_offset = 1, .h_pixels = 720,
0142 .v_max_out = 576, .h_max_out = 768,
0143 }
0144 };
0145
0146
0147
0148
0149
0150 static int hexium_init_done(struct saa7146_dev *dev)
0151 {
0152 struct hexium *hexium = (struct hexium *) dev->ext_priv;
0153 union i2c_smbus_data data;
0154 int i = 0;
0155
0156 DEB_D("hexium_init_done called\n");
0157
0158
0159 for (i = 0; i < sizeof(hexium_ks0127b); i++) {
0160 data.byte = hexium_ks0127b[i];
0161 if (0 != i2c_smbus_xfer(&hexium->i2c_adapter, 0x6c, 0, I2C_SMBUS_WRITE, i, I2C_SMBUS_BYTE_DATA, &data)) {
0162 pr_err("hexium_init_done() failed for address 0x%02x\n",
0163 i);
0164 }
0165 }
0166
0167 return 0;
0168 }
0169
0170 static int hexium_set_input(struct hexium *hexium, int input)
0171 {
0172 union i2c_smbus_data data;
0173
0174 DEB_D("\n");
0175
0176 data.byte = hexium_input_select[input].byte;
0177 if (0 != i2c_smbus_xfer(&hexium->i2c_adapter, 0x6c, 0, I2C_SMBUS_WRITE, hexium_input_select[input].adr, I2C_SMBUS_BYTE_DATA, &data)) {
0178 return -1;
0179 }
0180
0181 return 0;
0182 }
0183
0184 static int hexium_set_standard(struct hexium *hexium, struct hexium_data *vdec)
0185 {
0186 union i2c_smbus_data data;
0187 int i = 0;
0188
0189 DEB_D("\n");
0190
0191 while (vdec[i].adr != -1) {
0192 data.byte = vdec[i].byte;
0193 if (0 != i2c_smbus_xfer(&hexium->i2c_adapter, 0x6c, 0, I2C_SMBUS_WRITE, vdec[i].adr, I2C_SMBUS_BYTE_DATA, &data)) {
0194 pr_err("hexium_init_done: hexium_set_standard() failed for address 0x%02x\n",
0195 i);
0196 return -1;
0197 }
0198 i++;
0199 }
0200 return 0;
0201 }
0202
0203 static int vidioc_enum_input(struct file *file, void *fh, struct v4l2_input *i)
0204 {
0205 DEB_EE("VIDIOC_ENUMINPUT %d\n", i->index);
0206
0207 if (i->index >= HEXIUM_INPUTS)
0208 return -EINVAL;
0209
0210 memcpy(i, &hexium_inputs[i->index], sizeof(struct v4l2_input));
0211
0212 DEB_D("v4l2_ioctl: VIDIOC_ENUMINPUT %d\n", i->index);
0213 return 0;
0214 }
0215
0216 static int vidioc_g_input(struct file *file, void *fh, unsigned int *input)
0217 {
0218 struct saa7146_dev *dev = ((struct saa7146_fh *)fh)->dev;
0219 struct hexium *hexium = (struct hexium *) dev->ext_priv;
0220
0221 *input = hexium->cur_input;
0222
0223 DEB_D("VIDIOC_G_INPUT: %d\n", *input);
0224 return 0;
0225 }
0226
0227 static int vidioc_s_input(struct file *file, void *fh, unsigned int input)
0228 {
0229 struct saa7146_dev *dev = ((struct saa7146_fh *)fh)->dev;
0230 struct hexium *hexium = (struct hexium *) dev->ext_priv;
0231
0232 DEB_EE("VIDIOC_S_INPUT %d\n", input);
0233
0234 if (input >= HEXIUM_INPUTS)
0235 return -EINVAL;
0236
0237 hexium->cur_input = input;
0238 hexium_set_input(hexium, input);
0239 return 0;
0240 }
0241
0242 static struct saa7146_ext_vv vv_data;
0243
0244
0245 static int hexium_attach(struct saa7146_dev *dev, struct saa7146_pci_extension_data *info)
0246 {
0247 struct hexium *hexium;
0248 int ret;
0249
0250 DEB_EE("\n");
0251
0252 hexium = kzalloc(sizeof(*hexium), GFP_KERNEL);
0253 if (!hexium)
0254 return -ENOMEM;
0255
0256 dev->ext_priv = hexium;
0257
0258
0259 saa7146_write(dev, MC1, (MASK_08 | MASK_24 | MASK_10 | MASK_26));
0260
0261 strscpy(hexium->i2c_adapter.name, "hexium gemini",
0262 sizeof(hexium->i2c_adapter.name));
0263 saa7146_i2c_adapter_prepare(dev, &hexium->i2c_adapter, SAA7146_I2C_BUS_BIT_RATE_480);
0264 if (i2c_add_adapter(&hexium->i2c_adapter) < 0) {
0265 DEB_S("cannot register i2c-device. skipping.\n");
0266 kfree(hexium);
0267 return -EFAULT;
0268 }
0269
0270
0271 saa7146_setgpio(dev, 2, SAA7146_GPIO_OUTHI);
0272
0273 saa7146_write(dev, DD1_INIT, 0x07000700);
0274 saa7146_write(dev, DD1_STREAM_B, 0x00000000);
0275 saa7146_write(dev, MC2, (MASK_09 | MASK_25 | MASK_10 | MASK_26));
0276
0277
0278 hexium->cur_input = 0;
0279 hexium_init_done(dev);
0280
0281 hexium_set_standard(hexium, hexium_pal);
0282 hexium->cur_std = V4L2_STD_PAL;
0283
0284 hexium_set_input(hexium, 0);
0285 hexium->cur_input = 0;
0286
0287 ret = saa7146_vv_init(dev, &vv_data);
0288 if (ret) {
0289 i2c_del_adapter(&hexium->i2c_adapter);
0290 kfree(hexium);
0291 return ret;
0292 }
0293
0294 vv_data.vid_ops.vidioc_enum_input = vidioc_enum_input;
0295 vv_data.vid_ops.vidioc_g_input = vidioc_g_input;
0296 vv_data.vid_ops.vidioc_s_input = vidioc_s_input;
0297 ret = saa7146_register_device(&hexium->video_dev, dev, "hexium gemini", VFL_TYPE_VIDEO);
0298 if (ret < 0) {
0299 pr_err("cannot register capture v4l2 device. skipping.\n");
0300 saa7146_vv_release(dev);
0301 i2c_del_adapter(&hexium->i2c_adapter);
0302 kfree(hexium);
0303 return ret;
0304 }
0305
0306 pr_info("found 'hexium gemini' frame grabber-%d\n", hexium_num);
0307 hexium_num++;
0308
0309 return 0;
0310 }
0311
0312 static int hexium_detach(struct saa7146_dev *dev)
0313 {
0314 struct hexium *hexium = (struct hexium *) dev->ext_priv;
0315
0316 DEB_EE("dev:%p\n", dev);
0317
0318 saa7146_unregister_device(&hexium->video_dev, dev);
0319 saa7146_vv_release(dev);
0320
0321 hexium_num--;
0322
0323 i2c_del_adapter(&hexium->i2c_adapter);
0324 kfree(hexium);
0325 return 0;
0326 }
0327
0328 static int std_callback(struct saa7146_dev *dev, struct saa7146_standard *std)
0329 {
0330 struct hexium *hexium = (struct hexium *) dev->ext_priv;
0331
0332 if (V4L2_STD_PAL == std->id) {
0333 hexium_set_standard(hexium, hexium_pal);
0334 hexium->cur_std = V4L2_STD_PAL;
0335 return 0;
0336 } else if (V4L2_STD_NTSC == std->id) {
0337 hexium_set_standard(hexium, hexium_ntsc);
0338 hexium->cur_std = V4L2_STD_NTSC;
0339 return 0;
0340 } else if (V4L2_STD_SECAM == std->id) {
0341 hexium_set_standard(hexium, hexium_secam);
0342 hexium->cur_std = V4L2_STD_SECAM;
0343 return 0;
0344 }
0345
0346 return -1;
0347 }
0348
0349 static struct saa7146_extension hexium_extension;
0350
0351 static struct saa7146_pci_extension_data hexium_gemini_4bnc = {
0352 .ext_priv = "Hexium Gemini (4 BNC)",
0353 .ext = &hexium_extension,
0354 };
0355
0356 static struct saa7146_pci_extension_data hexium_gemini_dual_4bnc = {
0357 .ext_priv = "Hexium Gemini Dual (4 BNC)",
0358 .ext = &hexium_extension,
0359 };
0360
0361 static const struct pci_device_id pci_tbl[] = {
0362 {
0363 .vendor = PCI_VENDOR_ID_PHILIPS,
0364 .device = PCI_DEVICE_ID_PHILIPS_SAA7146,
0365 .subvendor = 0x17c8,
0366 .subdevice = 0x2401,
0367 .driver_data = (unsigned long) &hexium_gemini_4bnc,
0368 },
0369 {
0370 .vendor = PCI_VENDOR_ID_PHILIPS,
0371 .device = PCI_DEVICE_ID_PHILIPS_SAA7146,
0372 .subvendor = 0x17c8,
0373 .subdevice = 0x2402,
0374 .driver_data = (unsigned long) &hexium_gemini_dual_4bnc,
0375 },
0376 {
0377 .vendor = 0,
0378 }
0379 };
0380
0381 MODULE_DEVICE_TABLE(pci, pci_tbl);
0382
0383 static struct saa7146_ext_vv vv_data = {
0384 .inputs = HEXIUM_INPUTS,
0385 .capabilities = 0,
0386 .stds = &hexium_standards[0],
0387 .num_stds = ARRAY_SIZE(hexium_standards),
0388 .std_callback = &std_callback,
0389 };
0390
0391 static struct saa7146_extension hexium_extension = {
0392 .name = "hexium gemini",
0393 .flags = SAA7146_USE_I2C_IRQ,
0394
0395 .pci_tbl = &pci_tbl[0],
0396 .module = THIS_MODULE,
0397
0398 .attach = hexium_attach,
0399 .detach = hexium_detach,
0400
0401 .irq_mask = 0,
0402 .irq_func = NULL,
0403 };
0404
0405 static int __init hexium_init_module(void)
0406 {
0407 if (0 != saa7146_register_extension(&hexium_extension)) {
0408 DEB_S("failed to register extension\n");
0409 return -ENODEV;
0410 }
0411
0412 return 0;
0413 }
0414
0415 static void __exit hexium_cleanup_module(void)
0416 {
0417 saa7146_unregister_extension(&hexium_extension);
0418 }
0419
0420 module_init(hexium_init_module);
0421 module_exit(hexium_cleanup_module);
0422
0423 MODULE_DESCRIPTION("video4linux-2 driver for Hexium Gemini frame grabber cards");
0424 MODULE_AUTHOR("Michael Hunold <michael@mihu.de>");
0425 MODULE_LICENSE("GPL");