brintos

brintos / linux-shallow public Read only

0
0
Text · 11.4 KiB · 40b3509 Raw
427 lines · c
1// SPDX-License-Identifier: GPL-2.0-or-later2/*3    hexium_gemini.c - v4l2 driver for Hexium Gemini frame grabber cards4 5    Visit http://www.mihu.de/linux/saa7146/ and follow the link6    to "hexium" for further details about this card.7 8    Copyright (C) 2003 Michael Hunold <michael@mihu.de>9 10*/11 12#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt13 14#define DEBUG_VARIABLE debug15 16#include <media/drv-intf/saa7146_vv.h>17#include <linux/module.h>18#include <linux/kernel.h>19 20static int debug;21module_param(debug, int, 0);22MODULE_PARM_DESC(debug, "debug verbosity");23 24/* global variables */25static int hexium_num;26 27#define HEXIUM_GEMINI			428#define HEXIUM_GEMINI_DUAL		529 30#define HEXIUM_STD (V4L2_STD_PAL | V4L2_STD_SECAM | V4L2_STD_NTSC)31#define HEXIUM_INPUTS	932static struct v4l2_input hexium_inputs[HEXIUM_INPUTS] = {33	{ 0, "CVBS 1",	V4L2_INPUT_TYPE_CAMERA,	0, 0, HEXIUM_STD, 0, V4L2_IN_CAP_STD },34	{ 1, "CVBS 2",	V4L2_INPUT_TYPE_CAMERA,	0, 0, HEXIUM_STD, 0, V4L2_IN_CAP_STD },35	{ 2, "CVBS 3",	V4L2_INPUT_TYPE_CAMERA,	0, 0, HEXIUM_STD, 0, V4L2_IN_CAP_STD },36	{ 3, "CVBS 4",	V4L2_INPUT_TYPE_CAMERA,	0, 0, HEXIUM_STD, 0, V4L2_IN_CAP_STD },37	{ 4, "CVBS 5",	V4L2_INPUT_TYPE_CAMERA,	0, 0, HEXIUM_STD, 0, V4L2_IN_CAP_STD },38	{ 5, "CVBS 6",	V4L2_INPUT_TYPE_CAMERA,	0, 0, HEXIUM_STD, 0, V4L2_IN_CAP_STD },39	{ 6, "Y/C 1",	V4L2_INPUT_TYPE_CAMERA,	0, 0, HEXIUM_STD, 0, V4L2_IN_CAP_STD },40	{ 7, "Y/C 2",	V4L2_INPUT_TYPE_CAMERA,	0, 0, HEXIUM_STD, 0, V4L2_IN_CAP_STD },41	{ 8, "Y/C 3",	V4L2_INPUT_TYPE_CAMERA,	0, 0, HEXIUM_STD, 0, V4L2_IN_CAP_STD },42};43 44#define HEXIUM_AUDIOS	045 46struct hexium_data47{48	s8 adr;49	u8 byte;50};51 52#define HEXIUM_GEMINI_V_1_0		153#define HEXIUM_GEMINI_DUAL_V_1_0	254 55struct hexium56{57	int type;58 59	struct video_device	video_dev;60	struct i2c_adapter	i2c_adapter;61 62	int		cur_input;	/* current input */63	v4l2_std_id	cur_std;	/* current standard */64};65 66/* Samsung KS0127B decoder default registers */67static u8 hexium_ks0127b[0x100]={68/*00*/ 0x00,0x52,0x30,0x40,0x01,0x0C,0x2A,0x10,69/*08*/ 0x00,0x00,0x00,0x60,0x00,0x00,0x0F,0x06,70/*10*/ 0x00,0x00,0xE4,0xC0,0x00,0x00,0x00,0x00,71/*18*/ 0x14,0x9B,0xFE,0xFF,0xFC,0xFF,0x03,0x22,72/*20*/ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,73/*28*/ 0x00,0x00,0x00,0x00,0x00,0x2C,0x9B,0x00,74/*30*/ 0x00,0x00,0x10,0x80,0x80,0x10,0x80,0x80,75/*38*/ 0x01,0x04,0x00,0x00,0x00,0x29,0xC0,0x00,76/*40*/ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,77/*48*/ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,78/*50*/ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,79/*58*/ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,80/*60*/ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,81/*68*/ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,82/*70*/ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,83/*78*/ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,84/*80*/ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,85/*88*/ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,86/*90*/ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,87/*98*/ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,88/*A0*/ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,89/*A8*/ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,90/*B0*/ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,91/*B8*/ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,92/*C0*/ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,93/*C8*/ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,94/*D0*/ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,95/*D8*/ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,96/*E0*/ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,97/*E8*/ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,98/*F0*/ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,99/*F8*/ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00100};101 102static struct hexium_data hexium_pal[] = {103	{ 0x01, 0x52 }, { 0x12, 0x64 }, { 0x2D, 0x2C }, { 0x2E, 0x9B }, { -1 , 0xFF }104};105 106static struct hexium_data hexium_ntsc[] = {107	{ 0x01, 0x53 }, { 0x12, 0x04 }, { 0x2D, 0x23 }, { 0x2E, 0x81 }, { -1 , 0xFF }108};109 110static struct hexium_data hexium_secam[] = {111	{ 0x01, 0x52 }, { 0x12, 0x64 }, { 0x2D, 0x2C }, { 0x2E, 0x9B }, { -1 , 0xFF }112};113 114static struct hexium_data hexium_input_select[] = {115	{ 0x02, 0x60 },116	{ 0x02, 0x64 },117	{ 0x02, 0x61 },118	{ 0x02, 0x65 },119	{ 0x02, 0x62 },120	{ 0x02, 0x66 },121	{ 0x02, 0x68 },122	{ 0x02, 0x69 },123	{ 0x02, 0x6A },124};125 126/* fixme: h_offset = 0 for Hexium Gemini *Dual*, which127   are currently *not* supported*/128static struct saa7146_standard hexium_standards[] = {129	{130		.name	= "PAL",	.id	= V4L2_STD_PAL,131		.v_offset	= 28,	.v_field	= 288,132		.h_offset	= 1,	.h_pixels	= 680,133		.v_max_out	= 576,	.h_max_out	= 768,134	}, {135		.name	= "NTSC",	.id	= V4L2_STD_NTSC,136		.v_offset	= 28,	.v_field	= 240,137		.h_offset	= 1,	.h_pixels	= 640,138		.v_max_out	= 480,	.h_max_out	= 640,139	}, {140		.name	= "SECAM",	.id	= V4L2_STD_SECAM,141		.v_offset	= 28,	.v_field	= 288,142		.h_offset	= 1,	.h_pixels	= 720,143		.v_max_out	= 576,	.h_max_out	= 768,144	}145};146 147/* bring hardware to a sane state. this has to be done, just in case someone148   wants to capture from this device before it has been properly initialized.149   the capture engine would badly fail, because no valid signal arrives on the150   saa7146, thus leading to timeouts and stuff. */151static int hexium_init_done(struct saa7146_dev *dev)152{153	struct hexium *hexium = (struct hexium *) dev->ext_priv;154	union i2c_smbus_data data;155	int i = 0;156 157	DEB_D("hexium_init_done called\n");158 159	/* initialize the helper ics to useful values */160	for (i = 0; i < sizeof(hexium_ks0127b); i++) {161		data.byte = hexium_ks0127b[i];162		if (0 != i2c_smbus_xfer(&hexium->i2c_adapter, 0x6c, 0, I2C_SMBUS_WRITE, i, I2C_SMBUS_BYTE_DATA, &data)) {163			pr_err("hexium_init_done() failed for address 0x%02x\n",164			       i);165		}166	}167 168	return 0;169}170 171static int hexium_set_input(struct hexium *hexium, int input)172{173	union i2c_smbus_data data;174 175	DEB_D("\n");176 177	data.byte = hexium_input_select[input].byte;178	if (0 != i2c_smbus_xfer(&hexium->i2c_adapter, 0x6c, 0, I2C_SMBUS_WRITE, hexium_input_select[input].adr, I2C_SMBUS_BYTE_DATA, &data)) {179		return -1;180	}181 182	return 0;183}184 185static int hexium_set_standard(struct hexium *hexium, struct hexium_data *vdec)186{187	union i2c_smbus_data data;188	int i = 0;189 190	DEB_D("\n");191 192	while (vdec[i].adr != -1) {193		data.byte = vdec[i].byte;194		if (0 != i2c_smbus_xfer(&hexium->i2c_adapter, 0x6c, 0, I2C_SMBUS_WRITE, vdec[i].adr, I2C_SMBUS_BYTE_DATA, &data)) {195			pr_err("hexium_init_done: hexium_set_standard() failed for address 0x%02x\n",196			       i);197			return -1;198		}199		i++;200	}201	return 0;202}203 204static int vidioc_enum_input(struct file *file, void *fh, struct v4l2_input *i)205{206	DEB_EE("VIDIOC_ENUMINPUT %d\n", i->index);207 208	if (i->index >= HEXIUM_INPUTS)209		return -EINVAL;210 211	memcpy(i, &hexium_inputs[i->index], sizeof(struct v4l2_input));212 213	DEB_D("v4l2_ioctl: VIDIOC_ENUMINPUT %d\n", i->index);214	return 0;215}216 217static int vidioc_g_input(struct file *file, void *fh, unsigned int *input)218{219	struct saa7146_dev *dev = video_drvdata(file);220	struct hexium *hexium = (struct hexium *) dev->ext_priv;221 222	*input = hexium->cur_input;223 224	DEB_D("VIDIOC_G_INPUT: %d\n", *input);225	return 0;226}227 228static int vidioc_s_input(struct file *file, void *fh, unsigned int input)229{230	struct saa7146_dev *dev = video_drvdata(file);231	struct hexium *hexium = (struct hexium *) dev->ext_priv;232 233	DEB_EE("VIDIOC_S_INPUT %d\n", input);234 235	if (input >= HEXIUM_INPUTS)236		return -EINVAL;237 238	hexium->cur_input = input;239	hexium_set_input(hexium, input);240	return 0;241}242 243static struct saa7146_ext_vv vv_data;244 245/* this function only gets called when the probing was successful */246static int hexium_attach(struct saa7146_dev *dev, struct saa7146_pci_extension_data *info)247{248	struct hexium *hexium;249	int ret;250 251	DEB_EE("\n");252 253	hexium = kzalloc(sizeof(*hexium), GFP_KERNEL);254	if (!hexium)255		return -ENOMEM;256 257	dev->ext_priv = hexium;258 259	/* enable i2c-port pins */260	saa7146_write(dev, MC1, (MASK_08 | MASK_24 | MASK_10 | MASK_26));261 262	strscpy(hexium->i2c_adapter.name, "hexium gemini",263		sizeof(hexium->i2c_adapter.name));264	saa7146_i2c_adapter_prepare(dev, &hexium->i2c_adapter, SAA7146_I2C_BUS_BIT_RATE_480);265	if (i2c_add_adapter(&hexium->i2c_adapter) < 0) {266		DEB_S("cannot register i2c-device. skipping.\n");267		kfree(hexium);268		return -EFAULT;269	}270 271	/*  set HWControl GPIO number 2 */272	saa7146_setgpio(dev, 2, SAA7146_GPIO_OUTHI);273 274	saa7146_write(dev, DD1_INIT, 0x07000700);275	saa7146_write(dev, DD1_STREAM_B, 0x00000000);276	saa7146_write(dev, MC2, (MASK_09 | MASK_25 | MASK_10 | MASK_26));277 278	/* the rest */279	hexium->cur_input = 0;280	hexium_init_done(dev);281 282	hexium_set_standard(hexium, hexium_pal);283	hexium->cur_std = V4L2_STD_PAL;284 285	hexium_set_input(hexium, 0);286	hexium->cur_input = 0;287 288	ret = saa7146_vv_init(dev, &vv_data);289	if (ret) {290		i2c_del_adapter(&hexium->i2c_adapter);291		kfree(hexium);292		return ret;293	}294 295	vv_data.vid_ops.vidioc_enum_input = vidioc_enum_input;296	vv_data.vid_ops.vidioc_g_input = vidioc_g_input;297	vv_data.vid_ops.vidioc_s_input = vidioc_s_input;298	ret = saa7146_register_device(&hexium->video_dev, dev, "hexium gemini", VFL_TYPE_VIDEO);299	if (ret < 0) {300		pr_err("cannot register capture v4l2 device. skipping.\n");301		saa7146_vv_release(dev);302		i2c_del_adapter(&hexium->i2c_adapter);303		kfree(hexium);304		return ret;305	}306 307	pr_info("found 'hexium gemini' frame grabber-%d\n", hexium_num);308	hexium_num++;309 310	return 0;311}312 313static int hexium_detach(struct saa7146_dev *dev)314{315	struct hexium *hexium = (struct hexium *) dev->ext_priv;316 317	DEB_EE("dev:%p\n", dev);318 319	saa7146_unregister_device(&hexium->video_dev, dev);320	saa7146_vv_release(dev);321 322	hexium_num--;323 324	i2c_del_adapter(&hexium->i2c_adapter);325	kfree(hexium);326	return 0;327}328 329static int std_callback(struct saa7146_dev *dev, struct saa7146_standard *std)330{331	struct hexium *hexium = (struct hexium *) dev->ext_priv;332 333	if (V4L2_STD_PAL == std->id) {334		hexium_set_standard(hexium, hexium_pal);335		hexium->cur_std = V4L2_STD_PAL;336		return 0;337	} else if (V4L2_STD_NTSC == std->id) {338		hexium_set_standard(hexium, hexium_ntsc);339		hexium->cur_std = V4L2_STD_NTSC;340		return 0;341	} else if (V4L2_STD_SECAM == std->id) {342		hexium_set_standard(hexium, hexium_secam);343		hexium->cur_std = V4L2_STD_SECAM;344		return 0;345	}346 347	return -1;348}349 350static struct saa7146_extension hexium_extension;351 352static struct saa7146_pci_extension_data hexium_gemini_4bnc = {353	.ext_priv = "Hexium Gemini (4 BNC)",354	.ext = &hexium_extension,355};356 357static struct saa7146_pci_extension_data hexium_gemini_dual_4bnc = {358	.ext_priv = "Hexium Gemini Dual (4 BNC)",359	.ext = &hexium_extension,360};361 362static const struct pci_device_id pci_tbl[] = {363	{364	 .vendor = PCI_VENDOR_ID_PHILIPS,365	 .device = PCI_DEVICE_ID_PHILIPS_SAA7146,366	 .subvendor = 0x17c8,367	 .subdevice = 0x2401,368	 .driver_data = (unsigned long) &hexium_gemini_4bnc,369	 },370	{371	 .vendor = PCI_VENDOR_ID_PHILIPS,372	 .device = PCI_DEVICE_ID_PHILIPS_SAA7146,373	 .subvendor = 0x17c8,374	 .subdevice = 0x2402,375	 .driver_data = (unsigned long) &hexium_gemini_dual_4bnc,376	 },377	{378	 .vendor = 0,379	 }380};381 382MODULE_DEVICE_TABLE(pci, pci_tbl);383 384static struct saa7146_ext_vv vv_data = {385	.inputs = HEXIUM_INPUTS,386	.capabilities = 0,387	.stds = &hexium_standards[0],388	.num_stds = ARRAY_SIZE(hexium_standards),389	.std_callback = &std_callback,390};391 392static struct saa7146_extension hexium_extension = {393	.name = "hexium gemini",394	.flags = SAA7146_USE_I2C_IRQ,395 396	.pci_tbl = &pci_tbl[0],397	.module = THIS_MODULE,398 399	.attach = hexium_attach,400	.detach = hexium_detach,401 402	.irq_mask = 0,403	.irq_func = NULL,404};405 406static int __init hexium_init_module(void)407{408	if (0 != saa7146_register_extension(&hexium_extension)) {409		DEB_S("failed to register extension\n");410		return -ENODEV;411	}412 413	return 0;414}415 416static void __exit hexium_cleanup_module(void)417{418	saa7146_unregister_extension(&hexium_extension);419}420 421module_init(hexium_init_module);422module_exit(hexium_cleanup_module);423 424MODULE_DESCRIPTION("video4linux-2 driver for Hexium Gemini frame grabber cards");425MODULE_AUTHOR("Michael Hunold <michael@mihu.de>");426MODULE_LICENSE("GPL");427