cachepc-linux

Fork of AMDESE/linux with modifications for CachePC side-channel attack
git clone https://git.sinitax.com/sinitax/cachepc-linux
Log | Files | Refs | README | LICENSE | sfeed.txt

hexium_orion.c (12149B)


      1// SPDX-License-Identifier: GPL-2.0-or-later
      2/*
      3    hexium_orion.c - v4l2 driver for the Hexium Orion frame grabber cards
      4
      5    Visit http://www.mihu.de/linux/saa7146/ and follow the link
      6    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 ": " fmt
     13
     14#define DEBUG_VARIABLE debug
     15
     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_HV_PCI6_ORION		1
     28#define HEXIUM_ORION_1SVHS_3BNC		2
     29#define HEXIUM_ORION_4BNC		3
     30
     31#define HEXIUM_INPUTS	9
     32static struct v4l2_input hexium_inputs[HEXIUM_INPUTS] = {
     33	{ 0, "CVBS 1",	V4L2_INPUT_TYPE_CAMERA,	0, 0, V4L2_STD_ALL, 0, V4L2_IN_CAP_STD },
     34	{ 1, "CVBS 2",	V4L2_INPUT_TYPE_CAMERA,	0, 0, V4L2_STD_ALL, 0, V4L2_IN_CAP_STD },
     35	{ 2, "CVBS 3",	V4L2_INPUT_TYPE_CAMERA,	0, 0, V4L2_STD_ALL, 0, V4L2_IN_CAP_STD },
     36	{ 3, "CVBS 4",	V4L2_INPUT_TYPE_CAMERA,	0, 0, V4L2_STD_ALL, 0, V4L2_IN_CAP_STD },
     37	{ 4, "CVBS 5",	V4L2_INPUT_TYPE_CAMERA,	0, 0, V4L2_STD_ALL, 0, V4L2_IN_CAP_STD },
     38	{ 5, "CVBS 6",	V4L2_INPUT_TYPE_CAMERA,	0, 0, V4L2_STD_ALL, 0, V4L2_IN_CAP_STD },
     39	{ 6, "Y/C 1",	V4L2_INPUT_TYPE_CAMERA,	0, 0, V4L2_STD_ALL, 0, V4L2_IN_CAP_STD },
     40	{ 7, "Y/C 2",	V4L2_INPUT_TYPE_CAMERA,	0, 0, V4L2_STD_ALL, 0, V4L2_IN_CAP_STD },
     41	{ 8, "Y/C 3",	V4L2_INPUT_TYPE_CAMERA,	0, 0, V4L2_STD_ALL, 0, V4L2_IN_CAP_STD },
     42};
     43
     44#define HEXIUM_AUDIOS	0
     45
     46struct hexium_data
     47{
     48	s8 adr;
     49	u8 byte;
     50};
     51
     52struct hexium
     53{
     54	int type;
     55	struct video_device	video_dev;
     56	struct i2c_adapter	i2c_adapter;
     57
     58	int cur_input;	/* current input */
     59};
     60
     61/* Philips SAA7110 decoder default registers */
     62static u8 hexium_saa7110[53]={
     63/*00*/ 0x4C,0x3C,0x0D,0xEF,0xBD,0xF0,0x00,0x00,
     64/*08*/ 0xF8,0xF8,0x60,0x60,0x40,0x86,0x18,0x90,
     65/*10*/ 0x00,0x2C,0x40,0x46,0x42,0x1A,0xFF,0xDA,
     66/*18*/ 0xF0,0x8B,0x00,0x00,0x00,0x00,0x00,0x00,
     67/*20*/ 0xD9,0x17,0x40,0x41,0x80,0x41,0x80,0x4F,
     68/*28*/ 0xFE,0x01,0x0F,0x0F,0x03,0x01,0x81,0x03,
     69/*30*/ 0x44,0x75,0x01,0x8C,0x03
     70};
     71
     72static struct {
     73	struct hexium_data data[8];
     74} hexium_input_select[] = {
     75{
     76	{ /* cvbs 1 */
     77		{ 0x06, 0x00 },
     78		{ 0x20, 0xD9 },
     79		{ 0x21, 0x17 }, // 0x16,
     80		{ 0x22, 0x40 },
     81		{ 0x2C, 0x03 },
     82		{ 0x30, 0x44 },
     83		{ 0x31, 0x75 }, // ??
     84		{ 0x21, 0x16 }, // 0x03,
     85	}
     86}, {
     87	{ /* cvbs 2 */
     88		{ 0x06, 0x00 },
     89		{ 0x20, 0x78 },
     90		{ 0x21, 0x07 }, // 0x03,
     91		{ 0x22, 0xD2 },
     92		{ 0x2C, 0x83 },
     93		{ 0x30, 0x60 },
     94		{ 0x31, 0xB5 }, // ?
     95		{ 0x21, 0x03 },
     96	}
     97}, {
     98	{ /* cvbs 3 */
     99		{ 0x06, 0x00 },
    100		{ 0x20, 0xBA },
    101		{ 0x21, 0x07 }, // 0x05,
    102		{ 0x22, 0x91 },
    103		{ 0x2C, 0x03 },
    104		{ 0x30, 0x60 },
    105		{ 0x31, 0xB5 }, // ??
    106		{ 0x21, 0x05 }, // 0x03,
    107	}
    108}, {
    109	{ /* cvbs 4 */
    110		{ 0x06, 0x00 },
    111		{ 0x20, 0xD8 },
    112		{ 0x21, 0x17 }, // 0x16,
    113		{ 0x22, 0x40 },
    114		{ 0x2C, 0x03 },
    115		{ 0x30, 0x44 },
    116		{ 0x31, 0x75 }, // ??
    117		{ 0x21, 0x16 }, // 0x03,
    118	}
    119}, {
    120	{ /* cvbs 5 */
    121		{ 0x06, 0x00 },
    122		{ 0x20, 0xB8 },
    123		{ 0x21, 0x07 }, // 0x05,
    124		{ 0x22, 0x91 },
    125		{ 0x2C, 0x03 },
    126		{ 0x30, 0x60 },
    127		{ 0x31, 0xB5 }, // ??
    128		{ 0x21, 0x05 }, // 0x03,
    129	}
    130}, {
    131	{ /* cvbs 6 */
    132		{ 0x06, 0x00 },
    133		{ 0x20, 0x7C },
    134		{ 0x21, 0x07 }, // 0x03
    135		{ 0x22, 0xD2 },
    136		{ 0x2C, 0x83 },
    137		{ 0x30, 0x60 },
    138		{ 0x31, 0xB5 }, // ??
    139		{ 0x21, 0x03 },
    140	}
    141}, {
    142	{ /* y/c 1 */
    143		{ 0x06, 0x80 },
    144		{ 0x20, 0x59 },
    145		{ 0x21, 0x17 },
    146		{ 0x22, 0x42 },
    147		{ 0x2C, 0xA3 },
    148		{ 0x30, 0x44 },
    149		{ 0x31, 0x75 },
    150		{ 0x21, 0x12 },
    151	}
    152}, {
    153	{ /* y/c 2 */
    154		{ 0x06, 0x80 },
    155		{ 0x20, 0x9A },
    156		{ 0x21, 0x17 },
    157		{ 0x22, 0xB1 },
    158		{ 0x2C, 0x13 },
    159		{ 0x30, 0x60 },
    160		{ 0x31, 0xB5 },
    161		{ 0x21, 0x14 },
    162	}
    163}, {
    164	{ /* y/c 3 */
    165		{ 0x06, 0x80 },
    166		{ 0x20, 0x3C },
    167		{ 0x21, 0x27 },
    168		{ 0x22, 0xC1 },
    169		{ 0x2C, 0x23 },
    170		{ 0x30, 0x44 },
    171		{ 0x31, 0x75 },
    172		{ 0x21, 0x21 },
    173	}
    174}
    175};
    176
    177static struct saa7146_standard hexium_standards[] = {
    178	{
    179		.name	= "PAL",	.id	= V4L2_STD_PAL,
    180		.v_offset	= 16,	.v_field	= 288,
    181		.h_offset	= 1,	.h_pixels	= 680,
    182		.v_max_out	= 576,	.h_max_out	= 768,
    183	}, {
    184		.name	= "NTSC",	.id	= V4L2_STD_NTSC,
    185		.v_offset	= 16,	.v_field	= 240,
    186		.h_offset	= 1,	.h_pixels	= 640,
    187		.v_max_out	= 480,	.h_max_out	= 640,
    188	}, {
    189		.name	= "SECAM",	.id	= V4L2_STD_SECAM,
    190		.v_offset	= 16,	.v_field	= 288,
    191		.h_offset	= 1,	.h_pixels	= 720,
    192		.v_max_out	= 576,	.h_max_out	= 768,
    193	}
    194};
    195
    196/* this is only called for old HV-PCI6/Orion cards
    197   without eeprom */
    198static int hexium_probe(struct saa7146_dev *dev)
    199{
    200	struct hexium *hexium = NULL;
    201	union i2c_smbus_data data;
    202	int err = 0;
    203
    204	DEB_EE("\n");
    205
    206	/* there are no hexium orion cards with revision 0 saa7146s */
    207	if (0 == dev->revision) {
    208		return -EFAULT;
    209	}
    210
    211	hexium = kzalloc(sizeof(*hexium), GFP_KERNEL);
    212	if (!hexium)
    213		return -ENOMEM;
    214
    215	/* enable i2c-port pins */
    216	saa7146_write(dev, MC1, (MASK_08 | MASK_24 | MASK_10 | MASK_26));
    217
    218	saa7146_write(dev, DD1_INIT, 0x01000100);
    219	saa7146_write(dev, DD1_STREAM_B, 0x00000000);
    220	saa7146_write(dev, MC2, (MASK_09 | MASK_25 | MASK_10 | MASK_26));
    221
    222	strscpy(hexium->i2c_adapter.name, "hexium orion",
    223		sizeof(hexium->i2c_adapter.name));
    224	saa7146_i2c_adapter_prepare(dev, &hexium->i2c_adapter, SAA7146_I2C_BUS_BIT_RATE_480);
    225	if (i2c_add_adapter(&hexium->i2c_adapter) < 0) {
    226		DEB_S("cannot register i2c-device. skipping.\n");
    227		kfree(hexium);
    228		return -EFAULT;
    229	}
    230
    231	/* set SAA7110 control GPIO 0 */
    232	saa7146_setgpio(dev, 0, SAA7146_GPIO_OUTHI);
    233	/*  set HWControl GPIO number 2 */
    234	saa7146_setgpio(dev, 2, SAA7146_GPIO_OUTHI);
    235
    236	mdelay(10);
    237
    238	/* detect newer Hexium Orion cards by subsystem ids */
    239	if (0x17c8 == dev->pci->subsystem_vendor && 0x0101 == dev->pci->subsystem_device) {
    240		pr_info("device is a Hexium Orion w/ 1 SVHS + 3 BNC inputs\n");
    241		/* we store the pointer in our private data field */
    242		dev->ext_priv = hexium;
    243		hexium->type = HEXIUM_ORION_1SVHS_3BNC;
    244		return 0;
    245	}
    246
    247	if (0x17c8 == dev->pci->subsystem_vendor && 0x2101 == dev->pci->subsystem_device) {
    248		pr_info("device is a Hexium Orion w/ 4 BNC inputs\n");
    249		/* we store the pointer in our private data field */
    250		dev->ext_priv = hexium;
    251		hexium->type = HEXIUM_ORION_4BNC;
    252		return 0;
    253	}
    254
    255	/* check if this is an old hexium Orion card by looking at
    256	   a saa7110 at address 0x4e */
    257	err = i2c_smbus_xfer(&hexium->i2c_adapter, 0x4e, 0, I2C_SMBUS_READ,
    258			     0x00, I2C_SMBUS_BYTE_DATA, &data);
    259	if (err == 0) {
    260		pr_info("device is a Hexium HV-PCI6/Orion (old)\n");
    261		/* we store the pointer in our private data field */
    262		dev->ext_priv = hexium;
    263		hexium->type = HEXIUM_HV_PCI6_ORION;
    264		return 0;
    265	}
    266
    267	i2c_del_adapter(&hexium->i2c_adapter);
    268	kfree(hexium);
    269	return -EFAULT;
    270}
    271
    272/* bring hardware to a sane state. this has to be done, just in case someone
    273   wants to capture from this device before it has been properly initialized.
    274   the capture engine would badly fail, because no valid signal arrives on the
    275   saa7146, thus leading to timeouts and stuff. */
    276static int hexium_init_done(struct saa7146_dev *dev)
    277{
    278	struct hexium *hexium = (struct hexium *) dev->ext_priv;
    279	union i2c_smbus_data data;
    280	int i = 0;
    281
    282	DEB_D("hexium_init_done called\n");
    283
    284	/* initialize the helper ics to useful values */
    285	for (i = 0; i < sizeof(hexium_saa7110); i++) {
    286		data.byte = hexium_saa7110[i];
    287		if (0 != i2c_smbus_xfer(&hexium->i2c_adapter, 0x4e, 0, I2C_SMBUS_WRITE, i, I2C_SMBUS_BYTE_DATA, &data)) {
    288			pr_err("failed for address 0x%02x\n", i);
    289		}
    290	}
    291
    292	return 0;
    293}
    294
    295static int hexium_set_input(struct hexium *hexium, int input)
    296{
    297	union i2c_smbus_data data;
    298	int i = 0;
    299
    300	DEB_D("\n");
    301
    302	for (i = 0; i < 8; i++) {
    303		int adr = hexium_input_select[input].data[i].adr;
    304		data.byte = hexium_input_select[input].data[i].byte;
    305		if (0 != i2c_smbus_xfer(&hexium->i2c_adapter, 0x4e, 0, I2C_SMBUS_WRITE, adr, I2C_SMBUS_BYTE_DATA, &data)) {
    306			return -1;
    307		}
    308		pr_debug("%d: 0x%02x => 0x%02x\n", input, adr, data.byte);
    309	}
    310
    311	return 0;
    312}
    313
    314static int vidioc_enum_input(struct file *file, void *fh, struct v4l2_input *i)
    315{
    316	DEB_EE("VIDIOC_ENUMINPUT %d\n", i->index);
    317
    318	if (i->index >= HEXIUM_INPUTS)
    319		return -EINVAL;
    320
    321	memcpy(i, &hexium_inputs[i->index], sizeof(struct v4l2_input));
    322
    323	DEB_D("v4l2_ioctl: VIDIOC_ENUMINPUT %d\n", i->index);
    324	return 0;
    325}
    326
    327static int vidioc_g_input(struct file *file, void *fh, unsigned int *input)
    328{
    329	struct saa7146_dev *dev = ((struct saa7146_fh *)fh)->dev;
    330	struct hexium *hexium = (struct hexium *) dev->ext_priv;
    331
    332	*input = hexium->cur_input;
    333
    334	DEB_D("VIDIOC_G_INPUT: %d\n", *input);
    335	return 0;
    336}
    337
    338static int vidioc_s_input(struct file *file, void *fh, unsigned int input)
    339{
    340	struct saa7146_dev *dev = ((struct saa7146_fh *)fh)->dev;
    341	struct hexium *hexium = (struct hexium *) dev->ext_priv;
    342
    343	if (input >= HEXIUM_INPUTS)
    344		return -EINVAL;
    345
    346	hexium->cur_input = input;
    347	hexium_set_input(hexium, input);
    348
    349	return 0;
    350}
    351
    352static struct saa7146_ext_vv vv_data;
    353
    354/* this function only gets called when the probing was successful */
    355static int hexium_attach(struct saa7146_dev *dev, struct saa7146_pci_extension_data *info)
    356{
    357	struct hexium *hexium = (struct hexium *) dev->ext_priv;
    358	int ret;
    359
    360	DEB_EE("\n");
    361
    362	ret = saa7146_vv_init(dev, &vv_data);
    363	if (ret) {
    364		pr_err("Error in saa7146_vv_init()\n");
    365		return ret;
    366	}
    367
    368	vv_data.vid_ops.vidioc_enum_input = vidioc_enum_input;
    369	vv_data.vid_ops.vidioc_g_input = vidioc_g_input;
    370	vv_data.vid_ops.vidioc_s_input = vidioc_s_input;
    371	if (0 != saa7146_register_device(&hexium->video_dev, dev, "hexium orion", VFL_TYPE_VIDEO)) {
    372		pr_err("cannot register capture v4l2 device. skipping.\n");
    373		return -1;
    374	}
    375
    376	pr_err("found 'hexium orion' frame grabber-%d\n", hexium_num);
    377	hexium_num++;
    378
    379	/* the rest */
    380	hexium->cur_input = 0;
    381	hexium_init_done(dev);
    382
    383	return 0;
    384}
    385
    386static int hexium_detach(struct saa7146_dev *dev)
    387{
    388	struct hexium *hexium = (struct hexium *) dev->ext_priv;
    389
    390	DEB_EE("dev:%p\n", dev);
    391
    392	saa7146_unregister_device(&hexium->video_dev, dev);
    393	saa7146_vv_release(dev);
    394
    395	hexium_num--;
    396
    397	i2c_del_adapter(&hexium->i2c_adapter);
    398	kfree(hexium);
    399	return 0;
    400}
    401
    402static int std_callback(struct saa7146_dev *dev, struct saa7146_standard *std)
    403{
    404	return 0;
    405}
    406
    407static struct saa7146_extension extension;
    408
    409static struct saa7146_pci_extension_data hexium_hv_pci6 = {
    410	.ext_priv = "Hexium HV-PCI6 / Orion",
    411	.ext = &extension,
    412};
    413
    414static struct saa7146_pci_extension_data hexium_orion_1svhs_3bnc = {
    415	.ext_priv = "Hexium HV-PCI6 / Orion (1 SVHS/3 BNC)",
    416	.ext = &extension,
    417};
    418
    419static struct saa7146_pci_extension_data hexium_orion_4bnc = {
    420	.ext_priv = "Hexium HV-PCI6 / Orion (4 BNC)",
    421	.ext = &extension,
    422};
    423
    424static const struct pci_device_id pci_tbl[] = {
    425	{
    426	 .vendor = PCI_VENDOR_ID_PHILIPS,
    427	 .device = PCI_DEVICE_ID_PHILIPS_SAA7146,
    428	 .subvendor = 0x0000,
    429	 .subdevice = 0x0000,
    430	 .driver_data = (unsigned long) &hexium_hv_pci6,
    431	 },
    432	{
    433	 .vendor = PCI_VENDOR_ID_PHILIPS,
    434	 .device = PCI_DEVICE_ID_PHILIPS_SAA7146,
    435	 .subvendor = 0x17c8,
    436	 .subdevice = 0x0101,
    437	 .driver_data = (unsigned long) &hexium_orion_1svhs_3bnc,
    438	 },
    439	{
    440	 .vendor = PCI_VENDOR_ID_PHILIPS,
    441	 .device = PCI_DEVICE_ID_PHILIPS_SAA7146,
    442	 .subvendor = 0x17c8,
    443	 .subdevice = 0x2101,
    444	 .driver_data = (unsigned long) &hexium_orion_4bnc,
    445	 },
    446	{
    447	 .vendor = 0,
    448	 }
    449};
    450
    451MODULE_DEVICE_TABLE(pci, pci_tbl);
    452
    453static struct saa7146_ext_vv vv_data = {
    454	.inputs = HEXIUM_INPUTS,
    455	.capabilities = 0,
    456	.stds = &hexium_standards[0],
    457	.num_stds = ARRAY_SIZE(hexium_standards),
    458	.std_callback = &std_callback,
    459};
    460
    461static struct saa7146_extension extension = {
    462	.name = "hexium HV-PCI6 Orion",
    463	.flags = 0,		// SAA7146_USE_I2C_IRQ,
    464
    465	.pci_tbl = &pci_tbl[0],
    466	.module = THIS_MODULE,
    467
    468	.probe = hexium_probe,
    469	.attach = hexium_attach,
    470	.detach = hexium_detach,
    471
    472	.irq_mask = 0,
    473	.irq_func = NULL,
    474};
    475
    476static int __init hexium_init_module(void)
    477{
    478	if (0 != saa7146_register_extension(&extension)) {
    479		DEB_S("failed to register extension\n");
    480		return -ENODEV;
    481	}
    482
    483	return 0;
    484}
    485
    486static void __exit hexium_cleanup_module(void)
    487{
    488	saa7146_unregister_extension(&extension);
    489}
    490
    491module_init(hexium_init_module);
    492module_exit(hexium_cleanup_module);
    493
    494MODULE_DESCRIPTION("video4linux-2 driver for Hexium Orion frame grabber cards");
    495MODULE_AUTHOR("Michael Hunold <michael@mihu.de>");
    496MODULE_LICENSE("GPL");