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

s2250-board.c (14546B)


      1// SPDX-License-Identifier: GPL-2.0-only
      2/*
      3 * Copyright (C) 2008 Sensoray Company Inc.
      4 */
      5
      6#include <linux/module.h>
      7#include <linux/usb.h>
      8#include <linux/i2c.h>
      9#include <linux/videodev2.h>
     10#include <linux/slab.h>
     11#include <media/v4l2-device.h>
     12#include <media/v4l2-common.h>
     13#include <media/v4l2-subdev.h>
     14#include "go7007-priv.h"
     15
     16MODULE_DESCRIPTION("Sensoray 2250/2251 i2c v4l2 subdev driver");
     17MODULE_LICENSE("GPL v2");
     18
     19/*
     20 * Note: this board has two i2c devices: a vpx3226f and a tlv320aic23b.
     21 * Due to the unusual way these are accessed on this device we do not
     22 * reuse the i2c drivers, but instead they are implemented in this
     23 * driver. It would be nice to improve on this, though.
     24 */
     25
     26#define TLV320_ADDRESS      0x34
     27#define VPX322_ADDR_ANALOGCONTROL1	0x02
     28#define VPX322_ADDR_BRIGHTNESS0		0x0127
     29#define VPX322_ADDR_BRIGHTNESS1		0x0131
     30#define VPX322_ADDR_CONTRAST0		0x0128
     31#define VPX322_ADDR_CONTRAST1		0x0132
     32#define VPX322_ADDR_HUE			0x00dc
     33#define VPX322_ADDR_SAT			0x0030
     34
     35struct go7007_usb_board {
     36	unsigned int flags;
     37	struct go7007_board_info main_info;
     38};
     39
     40struct go7007_usb {
     41	struct go7007_usb_board *board;
     42	struct mutex i2c_lock;
     43	struct usb_device *usbdev;
     44	struct urb *video_urbs[8];
     45	struct urb *audio_urbs[8];
     46	struct urb *intr_urb;
     47};
     48
     49static unsigned char aud_regs[] = {
     50	0x1e, 0x00,
     51	0x00, 0x17,
     52	0x02, 0x17,
     53	0x04, 0xf9,
     54	0x06, 0xf9,
     55	0x08, 0x02,
     56	0x0a, 0x00,
     57	0x0c, 0x00,
     58	0x0a, 0x00,
     59	0x0c, 0x00,
     60	0x0e, 0x02,
     61	0x10, 0x00,
     62	0x12, 0x01,
     63	0x00, 0x00,
     64};
     65
     66
     67static unsigned char vid_regs[] = {
     68	0xF2, 0x0f,
     69	0xAA, 0x00,
     70	0xF8, 0xff,
     71	0x00, 0x00,
     72};
     73
     74static u16 vid_regs_fp[] = {
     75	0x028, 0x067,
     76	0x120, 0x016,
     77	0x121, 0xcF2,
     78	0x122, 0x0F2,
     79	0x123, 0x00c,
     80	0x124, 0x2d0,
     81	0x125, 0x2e0,
     82	0x126, 0x004,
     83	0x128, 0x1E0,
     84	0x12A, 0x016,
     85	0x12B, 0x0F2,
     86	0x12C, 0x0F2,
     87	0x12D, 0x00c,
     88	0x12E, 0x2d0,
     89	0x12F, 0x2e0,
     90	0x130, 0x004,
     91	0x132, 0x1E0,
     92	0x140, 0x060,
     93	0x153, 0x00C,
     94	0x154, 0x200,
     95	0x150, 0x801,
     96	0x000, 0x000
     97};
     98
     99/* PAL specific values */
    100static u16 vid_regs_fp_pal[] = {
    101	0x120, 0x017,
    102	0x121, 0xd22,
    103	0x122, 0x122,
    104	0x12A, 0x017,
    105	0x12B, 0x122,
    106	0x12C, 0x122,
    107	0x140, 0x060,
    108	0x000, 0x000,
    109};
    110
    111struct s2250 {
    112	struct v4l2_subdev sd;
    113	struct v4l2_ctrl_handler hdl;
    114	v4l2_std_id std;
    115	int input;
    116	int brightness;
    117	int contrast;
    118	int saturation;
    119	int hue;
    120	int reg12b_val;
    121	int audio_input;
    122	struct i2c_client *audio;
    123};
    124
    125static inline struct s2250 *to_state(struct v4l2_subdev *sd)
    126{
    127	return container_of(sd, struct s2250, sd);
    128}
    129
    130/* from go7007-usb.c which is Copyright (C) 2005-2006 Micronas USA Inc.*/
    131static int go7007_usb_vendor_request(struct go7007 *go, u16 request,
    132	u16 value, u16 index, void *transfer_buffer, int length, int in)
    133{
    134	struct go7007_usb *usb = go->hpi_context;
    135	int timeout = 5000;
    136
    137	if (in) {
    138		return usb_control_msg(usb->usbdev,
    139				usb_rcvctrlpipe(usb->usbdev, 0), request,
    140				USB_TYPE_VENDOR | USB_RECIP_DEVICE | USB_DIR_IN,
    141				value, index, transfer_buffer, length, timeout);
    142	} else {
    143		return usb_control_msg(usb->usbdev,
    144				usb_sndctrlpipe(usb->usbdev, 0), request,
    145				USB_TYPE_VENDOR | USB_RECIP_DEVICE,
    146				value, index, transfer_buffer, length, timeout);
    147	}
    148}
    149/* end from go7007-usb.c which is Copyright (C) 2005-2006 Micronas USA Inc.*/
    150
    151static int write_reg(struct i2c_client *client, u8 reg, u8 value)
    152{
    153	struct go7007 *go = i2c_get_adapdata(client->adapter);
    154	struct go7007_usb *usb;
    155	int rc;
    156	int dev_addr = client->addr << 1;  /* firmware wants 8-bit address */
    157	u8 *buf;
    158
    159	if (go == NULL)
    160		return -ENODEV;
    161
    162	if (go->status == STATUS_SHUTDOWN)
    163		return -EBUSY;
    164
    165	buf = kzalloc(16, GFP_KERNEL);
    166	if (buf == NULL)
    167		return -ENOMEM;
    168
    169	usb = go->hpi_context;
    170	if (mutex_lock_interruptible(&usb->i2c_lock) != 0) {
    171		dev_info(&client->dev, "i2c lock failed\n");
    172		kfree(buf);
    173		return -EINTR;
    174	}
    175	rc = go7007_usb_vendor_request(go, 0x55, dev_addr,
    176				       (reg<<8 | value),
    177				       buf,
    178				       16, 1);
    179
    180	mutex_unlock(&usb->i2c_lock);
    181	kfree(buf);
    182	return rc;
    183}
    184
    185static int write_reg_fp(struct i2c_client *client, u16 addr, u16 val)
    186{
    187	struct go7007 *go = i2c_get_adapdata(client->adapter);
    188	struct go7007_usb *usb;
    189	int rc;
    190	u8 *buf;
    191	struct s2250 *dec = i2c_get_clientdata(client);
    192
    193	if (go == NULL)
    194		return -ENODEV;
    195
    196	if (go->status == STATUS_SHUTDOWN)
    197		return -EBUSY;
    198
    199	buf = kzalloc(16, GFP_KERNEL);
    200
    201	if (buf == NULL)
    202		return -ENOMEM;
    203
    204
    205
    206	memset(buf, 0xcd, 6);
    207
    208	usb = go->hpi_context;
    209	if (mutex_lock_interruptible(&usb->i2c_lock) != 0) {
    210		dev_info(&client->dev, "i2c lock failed\n");
    211		kfree(buf);
    212		return -EINTR;
    213	}
    214	rc = go7007_usb_vendor_request(go, 0x57, addr, val, buf, 16, 1);
    215	mutex_unlock(&usb->i2c_lock);
    216	if (rc < 0) {
    217		kfree(buf);
    218		return rc;
    219	}
    220
    221	if (buf[0] == 0) {
    222		unsigned int subaddr, val_read;
    223
    224		subaddr = (buf[4] << 8) + buf[5];
    225		val_read = (buf[2] << 8) + buf[3];
    226		kfree(buf);
    227		if (val_read != val) {
    228			dev_info(&client->dev, "invalid fp write %x %x\n",
    229				 val_read, val);
    230			return -EFAULT;
    231		}
    232		if (subaddr != addr) {
    233			dev_info(&client->dev, "invalid fp write addr %x %x\n",
    234				 subaddr, addr);
    235			return -EFAULT;
    236		}
    237	} else {
    238		kfree(buf);
    239		return -EFAULT;
    240	}
    241
    242	/* save last 12b value */
    243	if (addr == 0x12b)
    244		dec->reg12b_val = val;
    245
    246	return 0;
    247}
    248
    249static int read_reg_fp(struct i2c_client *client, u16 addr, u16 *val)
    250{
    251	struct go7007 *go = i2c_get_adapdata(client->adapter);
    252	struct go7007_usb *usb;
    253	int rc;
    254	u8 *buf;
    255
    256	if (go == NULL)
    257		return -ENODEV;
    258
    259	if (go->status == STATUS_SHUTDOWN)
    260		return -EBUSY;
    261
    262	buf = kzalloc(16, GFP_KERNEL);
    263
    264	if (buf == NULL)
    265		return -ENOMEM;
    266
    267
    268
    269	memset(buf, 0xcd, 6);
    270	usb = go->hpi_context;
    271	if (mutex_lock_interruptible(&usb->i2c_lock) != 0) {
    272		dev_info(&client->dev, "i2c lock failed\n");
    273		kfree(buf);
    274		return -EINTR;
    275	}
    276	rc = go7007_usb_vendor_request(go, 0x58, addr, 0, buf, 16, 1);
    277	mutex_unlock(&usb->i2c_lock);
    278	if (rc < 0) {
    279		kfree(buf);
    280		return rc;
    281	}
    282
    283	*val = (buf[0] << 8) | buf[1];
    284	kfree(buf);
    285
    286	return 0;
    287}
    288
    289
    290static int write_regs(struct i2c_client *client, u8 *regs)
    291{
    292	int i;
    293
    294	for (i = 0; !((regs[i] == 0x00) && (regs[i+1] == 0x00)); i += 2) {
    295		if (write_reg(client, regs[i], regs[i+1]) < 0) {
    296			dev_info(&client->dev, "failed\n");
    297			return -1;
    298		}
    299	}
    300	return 0;
    301}
    302
    303static int write_regs_fp(struct i2c_client *client, u16 *regs)
    304{
    305	int i;
    306
    307	for (i = 0; !((regs[i] == 0x00) && (regs[i+1] == 0x00)); i += 2) {
    308		if (write_reg_fp(client, regs[i], regs[i+1]) < 0) {
    309			dev_info(&client->dev, "failed fp\n");
    310			return -1;
    311		}
    312	}
    313	return 0;
    314}
    315
    316
    317/* ------------------------------------------------------------------------- */
    318
    319static int s2250_s_video_routing(struct v4l2_subdev *sd, u32 input, u32 output,
    320				 u32 config)
    321{
    322	struct s2250 *state = to_state(sd);
    323	struct i2c_client *client = v4l2_get_subdevdata(sd);
    324	int vidsys;
    325
    326	vidsys = (state->std == V4L2_STD_NTSC) ? 0x01 : 0x00;
    327	if (input == 0) {
    328		/* composite */
    329		write_reg_fp(client, 0x20, 0x020 | vidsys);
    330		write_reg_fp(client, 0x21, 0x662);
    331		write_reg_fp(client, 0x140, 0x060);
    332	} else if (input == 1) {
    333		/* S-Video */
    334		write_reg_fp(client, 0x20, 0x040 | vidsys);
    335		write_reg_fp(client, 0x21, 0x666);
    336		write_reg_fp(client, 0x140, 0x060);
    337	} else {
    338		return -EINVAL;
    339	}
    340	state->input = input;
    341	return 0;
    342}
    343
    344static int s2250_s_std(struct v4l2_subdev *sd, v4l2_std_id norm)
    345{
    346	struct s2250 *state = to_state(sd);
    347	struct i2c_client *client = v4l2_get_subdevdata(sd);
    348	u16 vidsource;
    349
    350	vidsource = (state->input == 1) ? 0x040 : 0x020;
    351	if (norm & V4L2_STD_625_50) {
    352		write_regs_fp(client, vid_regs_fp);
    353		write_regs_fp(client, vid_regs_fp_pal);
    354		write_reg_fp(client, 0x20, vidsource);
    355	} else {
    356		write_regs_fp(client, vid_regs_fp);
    357		write_reg_fp(client, 0x20, vidsource | 1);
    358	}
    359	state->std = norm;
    360	return 0;
    361}
    362
    363static int s2250_s_ctrl(struct v4l2_ctrl *ctrl)
    364{
    365	struct s2250 *state = container_of(ctrl->handler, struct s2250, hdl);
    366	struct i2c_client *client = v4l2_get_subdevdata(&state->sd);
    367	u16 oldvalue;
    368
    369	switch (ctrl->id) {
    370	case V4L2_CID_BRIGHTNESS:
    371		read_reg_fp(client, VPX322_ADDR_BRIGHTNESS0, &oldvalue);
    372		write_reg_fp(client, VPX322_ADDR_BRIGHTNESS0,
    373			     ctrl->val | (oldvalue & ~0xff));
    374		read_reg_fp(client, VPX322_ADDR_BRIGHTNESS1, &oldvalue);
    375		write_reg_fp(client, VPX322_ADDR_BRIGHTNESS1,
    376			     ctrl->val | (oldvalue & ~0xff));
    377		write_reg_fp(client, 0x140, 0x60);
    378		break;
    379	case V4L2_CID_CONTRAST:
    380		read_reg_fp(client, VPX322_ADDR_CONTRAST0, &oldvalue);
    381		write_reg_fp(client, VPX322_ADDR_CONTRAST0,
    382			     ctrl->val | (oldvalue & ~0x3f));
    383		read_reg_fp(client, VPX322_ADDR_CONTRAST1, &oldvalue);
    384		write_reg_fp(client, VPX322_ADDR_CONTRAST1,
    385			     ctrl->val | (oldvalue & ~0x3f));
    386		write_reg_fp(client, 0x140, 0x60);
    387		break;
    388	case V4L2_CID_SATURATION:
    389		write_reg_fp(client, VPX322_ADDR_SAT, ctrl->val);
    390		break;
    391	case V4L2_CID_HUE:
    392		write_reg_fp(client, VPX322_ADDR_HUE, ctrl->val);
    393		break;
    394	default:
    395		return -EINVAL;
    396	}
    397	return 0;
    398}
    399
    400static int s2250_set_fmt(struct v4l2_subdev *sd,
    401		struct v4l2_subdev_state *sd_state,
    402		struct v4l2_subdev_format *format)
    403{
    404	struct v4l2_mbus_framefmt *fmt = &format->format;
    405	struct s2250 *state = to_state(sd);
    406	struct i2c_client *client = v4l2_get_subdevdata(sd);
    407
    408	if (format->pad)
    409		return -EINVAL;
    410
    411	if (format->which == V4L2_SUBDEV_FORMAT_TRY)
    412		return 0;
    413
    414	if (fmt->height < 640) {
    415		write_reg_fp(client, 0x12b, state->reg12b_val | 0x400);
    416		write_reg_fp(client, 0x140, 0x060);
    417	} else {
    418		write_reg_fp(client, 0x12b, state->reg12b_val & ~0x400);
    419		write_reg_fp(client, 0x140, 0x060);
    420	}
    421	return 0;
    422}
    423
    424static int s2250_s_audio_routing(struct v4l2_subdev *sd, u32 input, u32 output,
    425				 u32 config)
    426{
    427	struct s2250 *state = to_state(sd);
    428
    429	switch (input) {
    430	case 0:
    431		write_reg(state->audio, 0x08, 0x02); /* Line In */
    432		break;
    433	case 1:
    434		write_reg(state->audio, 0x08, 0x04); /* Mic */
    435		break;
    436	case 2:
    437		write_reg(state->audio, 0x08, 0x05); /* Mic Boost */
    438		break;
    439	default:
    440		return -EINVAL;
    441	}
    442	state->audio_input = input;
    443	return 0;
    444}
    445
    446
    447static int s2250_log_status(struct v4l2_subdev *sd)
    448{
    449	struct s2250 *state = to_state(sd);
    450
    451	v4l2_info(sd, "Standard: %s\n", state->std == V4L2_STD_NTSC ? "NTSC" :
    452					state->std == V4L2_STD_PAL ? "PAL" :
    453					state->std == V4L2_STD_SECAM ? "SECAM" :
    454					"unknown");
    455	v4l2_info(sd, "Input: %s\n", state->input == 0 ? "Composite" :
    456					state->input == 1 ? "S-video" :
    457					"error");
    458	v4l2_info(sd, "Audio input: %s\n", state->audio_input == 0 ? "Line In" :
    459					state->audio_input == 1 ? "Mic" :
    460					state->audio_input == 2 ? "Mic Boost" :
    461					"error");
    462	return v4l2_ctrl_subdev_log_status(sd);
    463}
    464
    465/* --------------------------------------------------------------------------*/
    466
    467static const struct v4l2_ctrl_ops s2250_ctrl_ops = {
    468	.s_ctrl = s2250_s_ctrl,
    469};
    470
    471static const struct v4l2_subdev_core_ops s2250_core_ops = {
    472	.log_status = s2250_log_status,
    473};
    474
    475static const struct v4l2_subdev_audio_ops s2250_audio_ops = {
    476	.s_routing = s2250_s_audio_routing,
    477};
    478
    479static const struct v4l2_subdev_video_ops s2250_video_ops = {
    480	.s_std = s2250_s_std,
    481	.s_routing = s2250_s_video_routing,
    482};
    483
    484static const struct v4l2_subdev_pad_ops s2250_pad_ops = {
    485	.set_fmt = s2250_set_fmt,
    486};
    487
    488static const struct v4l2_subdev_ops s2250_ops = {
    489	.core = &s2250_core_ops,
    490	.audio = &s2250_audio_ops,
    491	.video = &s2250_video_ops,
    492	.pad = &s2250_pad_ops,
    493};
    494
    495/* --------------------------------------------------------------------------*/
    496
    497static int s2250_probe(struct i2c_client *client,
    498		       const struct i2c_device_id *id)
    499{
    500	struct i2c_client *audio;
    501	struct i2c_adapter *adapter = client->adapter;
    502	struct s2250 *state;
    503	struct v4l2_subdev *sd;
    504	u8 *data;
    505	struct go7007 *go = i2c_get_adapdata(adapter);
    506	struct go7007_usb *usb = go->hpi_context;
    507	int err = -EIO;
    508
    509	audio = i2c_new_dummy_device(adapter, TLV320_ADDRESS >> 1);
    510	if (IS_ERR(audio))
    511		return PTR_ERR(audio);
    512
    513	state = kzalloc(sizeof(struct s2250), GFP_KERNEL);
    514	if (state == NULL) {
    515		i2c_unregister_device(audio);
    516		return -ENOMEM;
    517	}
    518
    519	sd = &state->sd;
    520	v4l2_i2c_subdev_init(sd, client, &s2250_ops);
    521
    522	v4l2_info(sd, "initializing %s at address 0x%x on %s\n",
    523	       "Sensoray 2250/2251", client->addr, client->adapter->name);
    524
    525	v4l2_ctrl_handler_init(&state->hdl, 4);
    526	v4l2_ctrl_new_std(&state->hdl, &s2250_ctrl_ops,
    527		V4L2_CID_BRIGHTNESS, -128, 127, 1, 0);
    528	v4l2_ctrl_new_std(&state->hdl, &s2250_ctrl_ops,
    529		V4L2_CID_CONTRAST, 0, 0x3f, 1, 0x32);
    530	v4l2_ctrl_new_std(&state->hdl, &s2250_ctrl_ops,
    531		V4L2_CID_SATURATION, 0, 4094, 1, 2070);
    532	v4l2_ctrl_new_std(&state->hdl, &s2250_ctrl_ops,
    533		V4L2_CID_HUE, -512, 511, 1, 0);
    534	sd->ctrl_handler = &state->hdl;
    535	if (state->hdl.error) {
    536		err = state->hdl.error;
    537		goto fail;
    538	}
    539
    540	state->std = V4L2_STD_NTSC;
    541	state->brightness = 50;
    542	state->contrast = 50;
    543	state->saturation = 50;
    544	state->hue = 0;
    545	state->audio = audio;
    546
    547	/* initialize the audio */
    548	if (write_regs(audio, aud_regs) < 0) {
    549		dev_err(&client->dev, "error initializing audio\n");
    550		goto fail;
    551	}
    552
    553	if (write_regs(client, vid_regs) < 0) {
    554		dev_err(&client->dev, "error initializing decoder\n");
    555		goto fail;
    556	}
    557	if (write_regs_fp(client, vid_regs_fp) < 0) {
    558		dev_err(&client->dev, "error initializing decoder\n");
    559		goto fail;
    560	}
    561	/* set default channel */
    562	/* composite */
    563	write_reg_fp(client, 0x20, 0x020 | 1);
    564	write_reg_fp(client, 0x21, 0x662);
    565	write_reg_fp(client, 0x140, 0x060);
    566
    567	/* set default audio input */
    568	state->audio_input = 0;
    569	write_reg(client, 0x08, 0x02); /* Line In */
    570
    571	if (mutex_lock_interruptible(&usb->i2c_lock) == 0) {
    572		data = kzalloc(16, GFP_KERNEL);
    573		if (data != NULL) {
    574			int rc = go7007_usb_vendor_request(go, 0x41, 0, 0,
    575						       data, 16, 1);
    576
    577			if (rc > 0) {
    578				u8 mask;
    579
    580				data[0] = 0;
    581				mask = 1<<5;
    582				data[0] &= ~mask;
    583				data[1] |= mask;
    584				go7007_usb_vendor_request(go, 0x40, 0,
    585							  (data[1]<<8)
    586							  + data[1],
    587							  data, 16, 0);
    588			}
    589			kfree(data);
    590		}
    591		mutex_unlock(&usb->i2c_lock);
    592	}
    593
    594	v4l2_info(sd, "initialized successfully\n");
    595	return 0;
    596
    597fail:
    598	i2c_unregister_device(audio);
    599	v4l2_ctrl_handler_free(&state->hdl);
    600	kfree(state);
    601	return err;
    602}
    603
    604static int s2250_remove(struct i2c_client *client)
    605{
    606	struct s2250 *state = to_state(i2c_get_clientdata(client));
    607
    608	i2c_unregister_device(state->audio);
    609	v4l2_device_unregister_subdev(&state->sd);
    610	v4l2_ctrl_handler_free(&state->hdl);
    611	kfree(state);
    612	return 0;
    613}
    614
    615static const struct i2c_device_id s2250_id[] = {
    616	{ "s2250", 0 },
    617	{ }
    618};
    619MODULE_DEVICE_TABLE(i2c, s2250_id);
    620
    621static struct i2c_driver s2250_driver = {
    622	.driver = {
    623		.name	= "s2250",
    624	},
    625	.probe		= s2250_probe,
    626	.remove		= s2250_remove,
    627	.id_table	= s2250_id,
    628};
    629
    630module_i2c_driver(s2250_driver);