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

bt819.c (12850B)


      1// SPDX-License-Identifier: GPL-2.0-or-later
      2/*
      3 *  bt819 - BT819A VideoStream Decoder (Rockwell Part)
      4 *
      5 * Copyright (C) 1999 Mike Bernson <mike@mlb.org>
      6 * Copyright (C) 1998 Dave Perks <dperks@ibm.net>
      7 *
      8 * Modifications for LML33/DC10plus unified driver
      9 * Copyright (C) 2000 Serguei Miridonov <mirsev@cicese.mx>
     10 *
     11 * Changes by Ronald Bultje <rbultje@ronald.bitfreak.net>
     12 *    - moved over to linux>=2.4.x i2c protocol (9/9/2002)
     13 *
     14 * This code was modify/ported from the saa7111 driver written
     15 * by Dave Perks.
     16 */
     17
     18#include <linux/module.h>
     19#include <linux/types.h>
     20#include <linux/ioctl.h>
     21#include <linux/delay.h>
     22#include <linux/i2c.h>
     23#include <linux/videodev2.h>
     24#include <linux/slab.h>
     25#include <media/v4l2-device.h>
     26#include <media/v4l2-ctrls.h>
     27#include <media/i2c/bt819.h>
     28
     29MODULE_DESCRIPTION("Brooktree-819 video decoder driver");
     30MODULE_AUTHOR("Mike Bernson & Dave Perks");
     31MODULE_LICENSE("GPL");
     32
     33static int debug;
     34module_param(debug, int, 0);
     35MODULE_PARM_DESC(debug, "Debug level (0-1)");
     36
     37
     38/* ----------------------------------------------------------------------- */
     39
     40struct bt819 {
     41	struct v4l2_subdev sd;
     42	struct v4l2_ctrl_handler hdl;
     43	unsigned char reg[32];
     44
     45	v4l2_std_id norm;
     46	int input;
     47	int enable;
     48};
     49
     50static inline struct bt819 *to_bt819(struct v4l2_subdev *sd)
     51{
     52	return container_of(sd, struct bt819, sd);
     53}
     54
     55static inline struct v4l2_subdev *to_sd(struct v4l2_ctrl *ctrl)
     56{
     57	return &container_of(ctrl->handler, struct bt819, hdl)->sd;
     58}
     59
     60struct timing {
     61	int hactive;
     62	int hdelay;
     63	int vactive;
     64	int vdelay;
     65	int hscale;
     66	int vscale;
     67};
     68
     69/* for values, see the bt819 datasheet */
     70static struct timing timing_data[] = {
     71	{864 - 24, 20, 625 - 2, 1, 0x0504, 0x0000},
     72	{858 - 24, 20, 525 - 2, 1, 0x00f8, 0x0000},
     73};
     74
     75/* ----------------------------------------------------------------------- */
     76
     77static inline int bt819_write(struct bt819 *decoder, u8 reg, u8 value)
     78{
     79	struct i2c_client *client = v4l2_get_subdevdata(&decoder->sd);
     80
     81	decoder->reg[reg] = value;
     82	return i2c_smbus_write_byte_data(client, reg, value);
     83}
     84
     85static inline int bt819_setbit(struct bt819 *decoder, u8 reg, u8 bit, u8 value)
     86{
     87	return bt819_write(decoder, reg,
     88		(decoder->reg[reg] & ~(1 << bit)) | (value ? (1 << bit) : 0));
     89}
     90
     91static int bt819_write_block(struct bt819 *decoder, const u8 *data, unsigned int len)
     92{
     93	struct i2c_client *client = v4l2_get_subdevdata(&decoder->sd);
     94	int ret = -1;
     95	u8 reg;
     96
     97	/* the bt819 has an autoincrement function, use it if
     98	 * the adapter understands raw I2C */
     99	if (i2c_check_functionality(client->adapter, I2C_FUNC_I2C)) {
    100		/* do raw I2C, not smbus compatible */
    101		u8 block_data[32];
    102		int block_len;
    103
    104		while (len >= 2) {
    105			block_len = 0;
    106			block_data[block_len++] = reg = data[0];
    107			do {
    108				block_data[block_len++] =
    109				    decoder->reg[reg++] = data[1];
    110				len -= 2;
    111				data += 2;
    112			} while (len >= 2 && data[0] == reg && block_len < 32);
    113			ret = i2c_master_send(client, block_data, block_len);
    114			if (ret < 0)
    115				break;
    116		}
    117	} else {
    118		/* do some slow I2C emulation kind of thing */
    119		while (len >= 2) {
    120			reg = *data++;
    121			ret = bt819_write(decoder, reg, *data++);
    122			if (ret < 0)
    123				break;
    124			len -= 2;
    125		}
    126	}
    127
    128	return ret;
    129}
    130
    131static inline int bt819_read(struct bt819 *decoder, u8 reg)
    132{
    133	struct i2c_client *client = v4l2_get_subdevdata(&decoder->sd);
    134
    135	return i2c_smbus_read_byte_data(client, reg);
    136}
    137
    138static int bt819_init(struct v4l2_subdev *sd)
    139{
    140	static unsigned char init[] = {
    141		/*0x1f, 0x00,*/     /* Reset */
    142		0x01, 0x59,	/* 0x01 input format */
    143		0x02, 0x00,	/* 0x02 temporal decimation */
    144		0x03, 0x12,	/* 0x03 Cropping msb */
    145		0x04, 0x16,	/* 0x04 Vertical Delay, lsb */
    146		0x05, 0xe0,	/* 0x05 Vertical Active lsb */
    147		0x06, 0x80,	/* 0x06 Horizontal Delay lsb */
    148		0x07, 0xd0,	/* 0x07 Horizontal Active lsb */
    149		0x08, 0x00,	/* 0x08 Horizontal Scaling msb */
    150		0x09, 0xf8,	/* 0x09 Horizontal Scaling lsb */
    151		0x0a, 0x00,	/* 0x0a Brightness control */
    152		0x0b, 0x30,	/* 0x0b Miscellaneous control */
    153		0x0c, 0xd8,	/* 0x0c Luma Gain lsb */
    154		0x0d, 0xfe,	/* 0x0d Chroma Gain (U) lsb */
    155		0x0e, 0xb4,	/* 0x0e Chroma Gain (V) msb */
    156		0x0f, 0x00,	/* 0x0f Hue control */
    157		0x12, 0x04,	/* 0x12 Output Format */
    158		0x13, 0x20,	/* 0x13 Vertical Scaling msb 0x00
    159					   chroma comb OFF, line drop scaling, interlace scaling
    160					   BUG? Why does turning the chroma comb on screw up color?
    161					   Bug in the bt819 stepping on my board?
    162					*/
    163		0x14, 0x00,	/* 0x14 Vertical Scaling lsb */
    164		0x16, 0x07,	/* 0x16 Video Timing Polarity
    165					   ACTIVE=active low
    166					   FIELD: high=odd,
    167					   vreset=active high,
    168					   hreset=active high */
    169		0x18, 0x68,	/* 0x18 AGC Delay */
    170		0x19, 0x5d,	/* 0x19 Burst Gate Delay */
    171		0x1a, 0x80,	/* 0x1a ADC Interface */
    172	};
    173
    174	struct bt819 *decoder = to_bt819(sd);
    175	struct timing *timing = &timing_data[(decoder->norm & V4L2_STD_525_60) ? 1 : 0];
    176
    177	init[0x03 * 2 - 1] =
    178	    (((timing->vdelay >> 8) & 0x03) << 6) |
    179	    (((timing->vactive >> 8) & 0x03) << 4) |
    180	    (((timing->hdelay >> 8) & 0x03) << 2) |
    181	    ((timing->hactive >> 8) & 0x03);
    182	init[0x04 * 2 - 1] = timing->vdelay & 0xff;
    183	init[0x05 * 2 - 1] = timing->vactive & 0xff;
    184	init[0x06 * 2 - 1] = timing->hdelay & 0xff;
    185	init[0x07 * 2 - 1] = timing->hactive & 0xff;
    186	init[0x08 * 2 - 1] = timing->hscale >> 8;
    187	init[0x09 * 2 - 1] = timing->hscale & 0xff;
    188	/* 0x15 in array is address 0x19 */
    189	init[0x15 * 2 - 1] = (decoder->norm & V4L2_STD_625_50) ? 115 : 93;	/* Chroma burst delay */
    190	/* reset */
    191	bt819_write(decoder, 0x1f, 0x00);
    192	mdelay(1);
    193
    194	/* init */
    195	return bt819_write_block(decoder, init, sizeof(init));
    196}
    197
    198/* ----------------------------------------------------------------------- */
    199
    200static int bt819_status(struct v4l2_subdev *sd, u32 *pstatus, v4l2_std_id *pstd)
    201{
    202	struct bt819 *decoder = to_bt819(sd);
    203	int status = bt819_read(decoder, 0x00);
    204	int res = V4L2_IN_ST_NO_SIGNAL;
    205	v4l2_std_id std = pstd ? *pstd : V4L2_STD_ALL;
    206
    207	if ((status & 0x80))
    208		res = 0;
    209	else
    210		std = V4L2_STD_UNKNOWN;
    211
    212	if ((status & 0x10))
    213		std &= V4L2_STD_PAL;
    214	else
    215		std &= V4L2_STD_NTSC;
    216	if (pstd)
    217		*pstd = std;
    218	if (pstatus)
    219		*pstatus = res;
    220
    221	v4l2_dbg(1, debug, sd, "get status %x\n", status);
    222	return 0;
    223}
    224
    225static int bt819_querystd(struct v4l2_subdev *sd, v4l2_std_id *std)
    226{
    227	return bt819_status(sd, NULL, std);
    228}
    229
    230static int bt819_g_input_status(struct v4l2_subdev *sd, u32 *status)
    231{
    232	return bt819_status(sd, status, NULL);
    233}
    234
    235static int bt819_s_std(struct v4l2_subdev *sd, v4l2_std_id std)
    236{
    237	struct bt819 *decoder = to_bt819(sd);
    238	struct timing *timing = NULL;
    239
    240	v4l2_dbg(1, debug, sd, "set norm %llx\n", (unsigned long long)std);
    241
    242	if (sd->v4l2_dev == NULL || sd->v4l2_dev->notify == NULL)
    243		v4l2_err(sd, "no notify found!\n");
    244
    245	if (std & V4L2_STD_NTSC) {
    246		v4l2_subdev_notify(sd, BT819_FIFO_RESET_LOW, NULL);
    247		bt819_setbit(decoder, 0x01, 0, 1);
    248		bt819_setbit(decoder, 0x01, 1, 0);
    249		bt819_setbit(decoder, 0x01, 5, 0);
    250		bt819_write(decoder, 0x18, 0x68);
    251		bt819_write(decoder, 0x19, 0x5d);
    252		/* bt819_setbit(decoder, 0x1a,  5, 1); */
    253		timing = &timing_data[1];
    254	} else if (std & V4L2_STD_PAL) {
    255		v4l2_subdev_notify(sd, BT819_FIFO_RESET_LOW, NULL);
    256		bt819_setbit(decoder, 0x01, 0, 1);
    257		bt819_setbit(decoder, 0x01, 1, 1);
    258		bt819_setbit(decoder, 0x01, 5, 1);
    259		bt819_write(decoder, 0x18, 0x7f);
    260		bt819_write(decoder, 0x19, 0x72);
    261		/* bt819_setbit(decoder, 0x1a,  5, 0); */
    262		timing = &timing_data[0];
    263	} else {
    264		v4l2_dbg(1, debug, sd, "unsupported norm %llx\n",
    265				(unsigned long long)std);
    266		return -EINVAL;
    267	}
    268	bt819_write(decoder, 0x03,
    269			(((timing->vdelay >> 8) & 0x03) << 6) |
    270			(((timing->vactive >> 8) & 0x03) << 4) |
    271			(((timing->hdelay >> 8) & 0x03) << 2) |
    272			((timing->hactive >> 8) & 0x03));
    273	bt819_write(decoder, 0x04, timing->vdelay & 0xff);
    274	bt819_write(decoder, 0x05, timing->vactive & 0xff);
    275	bt819_write(decoder, 0x06, timing->hdelay & 0xff);
    276	bt819_write(decoder, 0x07, timing->hactive & 0xff);
    277	bt819_write(decoder, 0x08, (timing->hscale >> 8) & 0xff);
    278	bt819_write(decoder, 0x09, timing->hscale & 0xff);
    279	decoder->norm = std;
    280	v4l2_subdev_notify(sd, BT819_FIFO_RESET_HIGH, NULL);
    281	return 0;
    282}
    283
    284static int bt819_s_routing(struct v4l2_subdev *sd,
    285			   u32 input, u32 output, u32 config)
    286{
    287	struct bt819 *decoder = to_bt819(sd);
    288
    289	v4l2_dbg(1, debug, sd, "set input %x\n", input);
    290
    291	if (input > 7)
    292		return -EINVAL;
    293
    294	if (sd->v4l2_dev == NULL || sd->v4l2_dev->notify == NULL)
    295		v4l2_err(sd, "no notify found!\n");
    296
    297	if (decoder->input != input) {
    298		v4l2_subdev_notify(sd, BT819_FIFO_RESET_LOW, NULL);
    299		decoder->input = input;
    300		/* select mode */
    301		if (decoder->input == 0) {
    302			bt819_setbit(decoder, 0x0b, 6, 0);
    303			bt819_setbit(decoder, 0x1a, 1, 1);
    304		} else {
    305			bt819_setbit(decoder, 0x0b, 6, 1);
    306			bt819_setbit(decoder, 0x1a, 1, 0);
    307		}
    308		v4l2_subdev_notify(sd, BT819_FIFO_RESET_HIGH, NULL);
    309	}
    310	return 0;
    311}
    312
    313static int bt819_s_stream(struct v4l2_subdev *sd, int enable)
    314{
    315	struct bt819 *decoder = to_bt819(sd);
    316
    317	v4l2_dbg(1, debug, sd, "enable output %x\n", enable);
    318
    319	if (decoder->enable != enable) {
    320		decoder->enable = enable;
    321		bt819_setbit(decoder, 0x16, 7, !enable);
    322	}
    323	return 0;
    324}
    325
    326static int bt819_s_ctrl(struct v4l2_ctrl *ctrl)
    327{
    328	struct v4l2_subdev *sd = to_sd(ctrl);
    329	struct bt819 *decoder = to_bt819(sd);
    330	int temp;
    331
    332	switch (ctrl->id) {
    333	case V4L2_CID_BRIGHTNESS:
    334		bt819_write(decoder, 0x0a, ctrl->val);
    335		break;
    336
    337	case V4L2_CID_CONTRAST:
    338		bt819_write(decoder, 0x0c, ctrl->val & 0xff);
    339		bt819_setbit(decoder, 0x0b, 2, ((ctrl->val >> 8) & 0x01));
    340		break;
    341
    342	case V4L2_CID_SATURATION:
    343		bt819_write(decoder, 0x0d, (ctrl->val >> 7) & 0xff);
    344		bt819_setbit(decoder, 0x0b, 1, ((ctrl->val >> 15) & 0x01));
    345
    346		/* Ratio between U gain and V gain must stay the same as
    347		   the ratio between the default U and V gain values. */
    348		temp = (ctrl->val * 180) / 254;
    349		bt819_write(decoder, 0x0e, (temp >> 7) & 0xff);
    350		bt819_setbit(decoder, 0x0b, 0, (temp >> 15) & 0x01);
    351		break;
    352
    353	case V4L2_CID_HUE:
    354		bt819_write(decoder, 0x0f, ctrl->val);
    355		break;
    356
    357	default:
    358		return -EINVAL;
    359	}
    360	return 0;
    361}
    362
    363/* ----------------------------------------------------------------------- */
    364
    365static const struct v4l2_ctrl_ops bt819_ctrl_ops = {
    366	.s_ctrl = bt819_s_ctrl,
    367};
    368
    369static const struct v4l2_subdev_video_ops bt819_video_ops = {
    370	.s_std = bt819_s_std,
    371	.s_routing = bt819_s_routing,
    372	.s_stream = bt819_s_stream,
    373	.querystd = bt819_querystd,
    374	.g_input_status = bt819_g_input_status,
    375};
    376
    377static const struct v4l2_subdev_ops bt819_ops = {
    378	.video = &bt819_video_ops,
    379};
    380
    381/* ----------------------------------------------------------------------- */
    382
    383static int bt819_probe(struct i2c_client *client,
    384			const struct i2c_device_id *id)
    385{
    386	int i, ver;
    387	struct bt819 *decoder;
    388	struct v4l2_subdev *sd;
    389	const char *name;
    390
    391	/* Check if the adapter supports the needed features */
    392	if (!i2c_check_functionality(client->adapter, I2C_FUNC_SMBUS_BYTE_DATA))
    393		return -ENODEV;
    394
    395	decoder = devm_kzalloc(&client->dev, sizeof(*decoder), GFP_KERNEL);
    396	if (decoder == NULL)
    397		return -ENOMEM;
    398	sd = &decoder->sd;
    399	v4l2_i2c_subdev_init(sd, client, &bt819_ops);
    400
    401	ver = bt819_read(decoder, 0x17);
    402	switch (ver & 0xf0) {
    403	case 0x70:
    404		name = "bt819a";
    405		break;
    406	case 0x60:
    407		name = "bt817a";
    408		break;
    409	case 0x20:
    410		name = "bt815a";
    411		break;
    412	default:
    413		v4l2_dbg(1, debug, sd,
    414			"unknown chip version 0x%02x\n", ver);
    415		return -ENODEV;
    416	}
    417
    418	v4l_info(client, "%s found @ 0x%x (%s)\n", name,
    419			client->addr << 1, client->adapter->name);
    420
    421	decoder->norm = V4L2_STD_NTSC;
    422	decoder->input = 0;
    423	decoder->enable = 1;
    424
    425	i = bt819_init(sd);
    426	if (i < 0)
    427		v4l2_dbg(1, debug, sd, "init status %d\n", i);
    428
    429	v4l2_ctrl_handler_init(&decoder->hdl, 4);
    430	v4l2_ctrl_new_std(&decoder->hdl, &bt819_ctrl_ops,
    431			V4L2_CID_BRIGHTNESS, -128, 127, 1, 0);
    432	v4l2_ctrl_new_std(&decoder->hdl, &bt819_ctrl_ops,
    433			V4L2_CID_CONTRAST, 0, 511, 1, 0xd8);
    434	v4l2_ctrl_new_std(&decoder->hdl, &bt819_ctrl_ops,
    435			V4L2_CID_SATURATION, 0, 511, 1, 0xfe);
    436	v4l2_ctrl_new_std(&decoder->hdl, &bt819_ctrl_ops,
    437			V4L2_CID_HUE, -128, 127, 1, 0);
    438	sd->ctrl_handler = &decoder->hdl;
    439	if (decoder->hdl.error) {
    440		int err = decoder->hdl.error;
    441
    442		v4l2_ctrl_handler_free(&decoder->hdl);
    443		return err;
    444	}
    445	v4l2_ctrl_handler_setup(&decoder->hdl);
    446	return 0;
    447}
    448
    449static int bt819_remove(struct i2c_client *client)
    450{
    451	struct v4l2_subdev *sd = i2c_get_clientdata(client);
    452	struct bt819 *decoder = to_bt819(sd);
    453
    454	v4l2_device_unregister_subdev(sd);
    455	v4l2_ctrl_handler_free(&decoder->hdl);
    456	return 0;
    457}
    458
    459/* ----------------------------------------------------------------------- */
    460
    461static const struct i2c_device_id bt819_id[] = {
    462	{ "bt819a", 0 },
    463	{ "bt817a", 0 },
    464	{ "bt815a", 0 },
    465	{ }
    466};
    467MODULE_DEVICE_TABLE(i2c, bt819_id);
    468
    469static struct i2c_driver bt819_driver = {
    470	.driver = {
    471		.name	= "bt819",
    472	},
    473	.probe		= bt819_probe,
    474	.remove		= bt819_remove,
    475	.id_table	= bt819_id,
    476};
    477
    478module_i2c_driver(bt819_driver);