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

ml86v7667.c (12021B)


      1// SPDX-License-Identifier: GPL-2.0-or-later
      2/*
      3 * OKI Semiconductor ML86V7667 video decoder driver
      4 *
      5 * Author: Vladimir Barinov <source@cogentembedded.com>
      6 * Copyright (C) 2013 Cogent Embedded, Inc.
      7 * Copyright (C) 2013 Renesas Solutions Corp.
      8 */
      9
     10#include <linux/init.h>
     11#include <linux/module.h>
     12#include <linux/i2c.h>
     13#include <linux/slab.h>
     14#include <linux/videodev2.h>
     15#include <media/v4l2-subdev.h>
     16#include <media/v4l2-device.h>
     17#include <media/v4l2-ioctl.h>
     18#include <media/v4l2-ctrls.h>
     19
     20#define DRV_NAME "ml86v7667"
     21
     22/* Subaddresses */
     23#define MRA_REG			0x00 /* Mode Register A */
     24#define MRC_REG			0x02 /* Mode Register C */
     25#define LUMC_REG		0x0C /* Luminance Control */
     26#define CLC_REG			0x10 /* Contrast level control */
     27#define SSEPL_REG		0x11 /* Sync separation level */
     28#define CHRCA_REG		0x12 /* Chrominance Control A */
     29#define ACCC_REG		0x14 /* ACC Loop filter & Chrominance control */
     30#define ACCRC_REG		0x15 /* ACC Reference level control */
     31#define HUE_REG			0x16 /* Hue control */
     32#define ADC2_REG		0x1F /* ADC Register 2 */
     33#define PLLR1_REG		0x20 /* PLL Register 1 */
     34#define STATUS_REG		0x2C /* STATUS Register */
     35
     36/* Mode Register A register bits */
     37#define MRA_OUTPUT_MODE_MASK	(3 << 6)
     38#define MRA_ITUR_BT601		(1 << 6)
     39#define MRA_ITUR_BT656		(0 << 6)
     40#define MRA_INPUT_MODE_MASK	(7 << 3)
     41#define MRA_PAL_BT601		(4 << 3)
     42#define MRA_NTSC_BT601		(0 << 3)
     43#define MRA_REGISTER_MODE	(1 << 0)
     44
     45/* Mode Register C register bits */
     46#define MRC_AUTOSELECT		(1 << 7)
     47
     48/* Luminance Control register bits */
     49#define LUMC_ONOFF_SHIFT	7
     50#define LUMC_ONOFF_MASK		(1 << 7)
     51
     52/* Contrast level control register bits */
     53#define CLC_CONTRAST_ONOFF	(1 << 7)
     54#define CLC_CONTRAST_MASK	0x0F
     55
     56/* Sync separation level register bits */
     57#define SSEPL_LUMINANCE_ONOFF	(1 << 7)
     58#define SSEPL_LUMINANCE_MASK	0x7F
     59
     60/* Chrominance Control A register bits */
     61#define CHRCA_MODE_SHIFT	6
     62#define CHRCA_MODE_MASK		(1 << 6)
     63
     64/* ACC Loop filter & Chrominance control register bits */
     65#define ACCC_CHROMA_CR_SHIFT	3
     66#define ACCC_CHROMA_CR_MASK	(7 << 3)
     67#define ACCC_CHROMA_CB_SHIFT	0
     68#define ACCC_CHROMA_CB_MASK	(7 << 0)
     69
     70/* ACC Reference level control register bits */
     71#define ACCRC_CHROMA_MASK	0xfc
     72#define ACCRC_CHROMA_SHIFT	2
     73
     74/* ADC Register 2 register bits */
     75#define ADC2_CLAMP_VOLTAGE_MASK	(7 << 1)
     76#define ADC2_CLAMP_VOLTAGE(n)	((n & 7) << 1)
     77
     78/* PLL Register 1 register bits */
     79#define PLLR1_FIXED_CLOCK	(1 << 7)
     80
     81/* STATUS Register register bits */
     82#define STATUS_HLOCK_DETECT	(1 << 3)
     83#define STATUS_NTSCPAL		(1 << 2)
     84
     85struct ml86v7667_priv {
     86	struct v4l2_subdev		sd;
     87	struct v4l2_ctrl_handler	hdl;
     88	v4l2_std_id			std;
     89};
     90
     91static inline struct ml86v7667_priv *to_ml86v7667(struct v4l2_subdev *subdev)
     92{
     93	return container_of(subdev, struct ml86v7667_priv, sd);
     94}
     95
     96static inline struct v4l2_subdev *to_sd(struct v4l2_ctrl *ctrl)
     97{
     98	return &container_of(ctrl->handler, struct ml86v7667_priv, hdl)->sd;
     99}
    100
    101static int ml86v7667_mask_set(struct i2c_client *client, const u8 reg,
    102			      const u8 mask, const u8 data)
    103{
    104	int val = i2c_smbus_read_byte_data(client, reg);
    105	if (val < 0)
    106		return val;
    107
    108	val = (val & ~mask) | (data & mask);
    109	return i2c_smbus_write_byte_data(client, reg, val);
    110}
    111
    112static int ml86v7667_s_ctrl(struct v4l2_ctrl *ctrl)
    113{
    114	struct v4l2_subdev *sd = to_sd(ctrl);
    115	struct i2c_client *client = v4l2_get_subdevdata(sd);
    116	int ret = -EINVAL;
    117
    118	switch (ctrl->id) {
    119	case V4L2_CID_BRIGHTNESS:
    120		ret = ml86v7667_mask_set(client, SSEPL_REG,
    121					 SSEPL_LUMINANCE_MASK, ctrl->val);
    122		break;
    123	case V4L2_CID_CONTRAST:
    124		ret = ml86v7667_mask_set(client, CLC_REG,
    125					 CLC_CONTRAST_MASK, ctrl->val);
    126		break;
    127	case V4L2_CID_CHROMA_GAIN:
    128		ret = ml86v7667_mask_set(client, ACCRC_REG, ACCRC_CHROMA_MASK,
    129					 ctrl->val << ACCRC_CHROMA_SHIFT);
    130		break;
    131	case V4L2_CID_HUE:
    132		ret = ml86v7667_mask_set(client, HUE_REG, ~0, ctrl->val);
    133		break;
    134	case V4L2_CID_RED_BALANCE:
    135		ret = ml86v7667_mask_set(client, ACCC_REG,
    136					 ACCC_CHROMA_CR_MASK,
    137					 ctrl->val << ACCC_CHROMA_CR_SHIFT);
    138		break;
    139	case V4L2_CID_BLUE_BALANCE:
    140		ret = ml86v7667_mask_set(client, ACCC_REG,
    141					 ACCC_CHROMA_CB_MASK,
    142					 ctrl->val << ACCC_CHROMA_CB_SHIFT);
    143		break;
    144	case V4L2_CID_SHARPNESS:
    145		ret = ml86v7667_mask_set(client, LUMC_REG,
    146					 LUMC_ONOFF_MASK,
    147					 ctrl->val << LUMC_ONOFF_SHIFT);
    148		break;
    149	case V4L2_CID_COLOR_KILLER:
    150		ret = ml86v7667_mask_set(client, CHRCA_REG,
    151					 CHRCA_MODE_MASK,
    152					 ctrl->val << CHRCA_MODE_SHIFT);
    153		break;
    154	}
    155
    156	return ret;
    157}
    158
    159static int ml86v7667_querystd(struct v4l2_subdev *sd, v4l2_std_id *std)
    160{
    161	struct i2c_client *client = v4l2_get_subdevdata(sd);
    162	int status;
    163
    164	status = i2c_smbus_read_byte_data(client, STATUS_REG);
    165	if (status < 0)
    166		return status;
    167
    168	if (status & STATUS_HLOCK_DETECT)
    169		*std &= status & STATUS_NTSCPAL ? V4L2_STD_625_50 : V4L2_STD_525_60;
    170	else
    171		*std = V4L2_STD_UNKNOWN;
    172
    173	return 0;
    174}
    175
    176static int ml86v7667_g_input_status(struct v4l2_subdev *sd, u32 *status)
    177{
    178	struct i2c_client *client = v4l2_get_subdevdata(sd);
    179	int status_reg;
    180
    181	status_reg = i2c_smbus_read_byte_data(client, STATUS_REG);
    182	if (status_reg < 0)
    183		return status_reg;
    184
    185	*status = status_reg & STATUS_HLOCK_DETECT ? 0 : V4L2_IN_ST_NO_SIGNAL;
    186
    187	return 0;
    188}
    189
    190static int ml86v7667_enum_mbus_code(struct v4l2_subdev *sd,
    191		struct v4l2_subdev_state *sd_state,
    192		struct v4l2_subdev_mbus_code_enum *code)
    193{
    194	if (code->pad || code->index > 0)
    195		return -EINVAL;
    196
    197	code->code = MEDIA_BUS_FMT_YUYV8_2X8;
    198
    199	return 0;
    200}
    201
    202static int ml86v7667_fill_fmt(struct v4l2_subdev *sd,
    203		struct v4l2_subdev_state *sd_state,
    204		struct v4l2_subdev_format *format)
    205{
    206	struct ml86v7667_priv *priv = to_ml86v7667(sd);
    207	struct v4l2_mbus_framefmt *fmt = &format->format;
    208
    209	if (format->pad)
    210		return -EINVAL;
    211
    212	fmt->code = MEDIA_BUS_FMT_YUYV8_2X8;
    213	fmt->colorspace = V4L2_COLORSPACE_SMPTE170M;
    214	/* The top field is always transferred first by the chip */
    215	fmt->field = V4L2_FIELD_INTERLACED_TB;
    216	fmt->width = 720;
    217	fmt->height = priv->std & V4L2_STD_525_60 ? 480 : 576;
    218
    219	return 0;
    220}
    221
    222static int ml86v7667_get_mbus_config(struct v4l2_subdev *sd,
    223				     unsigned int pad,
    224				     struct v4l2_mbus_config *cfg)
    225{
    226	cfg->type = V4L2_MBUS_BT656;
    227	cfg->bus.parallel.flags = V4L2_MBUS_MASTER |
    228				  V4L2_MBUS_PCLK_SAMPLE_RISING |
    229				  V4L2_MBUS_DATA_ACTIVE_HIGH;
    230
    231	return 0;
    232}
    233
    234static int ml86v7667_g_std(struct v4l2_subdev *sd, v4l2_std_id *std)
    235{
    236	struct ml86v7667_priv *priv = to_ml86v7667(sd);
    237
    238	*std = priv->std;
    239
    240	return 0;
    241}
    242
    243static int ml86v7667_s_std(struct v4l2_subdev *sd, v4l2_std_id std)
    244{
    245	struct ml86v7667_priv *priv = to_ml86v7667(sd);
    246	struct i2c_client *client = v4l2_get_subdevdata(&priv->sd);
    247	int ret;
    248	u8 mode;
    249
    250	/* PAL/NTSC ITU-R BT.601 input mode */
    251	mode = std & V4L2_STD_525_60 ? MRA_NTSC_BT601 : MRA_PAL_BT601;
    252	ret = ml86v7667_mask_set(client, MRA_REG, MRA_INPUT_MODE_MASK, mode);
    253	if (ret < 0)
    254		return ret;
    255
    256	priv->std = std;
    257
    258	return 0;
    259}
    260
    261#ifdef CONFIG_VIDEO_ADV_DEBUG
    262static int ml86v7667_g_register(struct v4l2_subdev *sd,
    263				struct v4l2_dbg_register *reg)
    264{
    265	struct i2c_client *client = v4l2_get_subdevdata(sd);
    266	int ret;
    267
    268	ret = i2c_smbus_read_byte_data(client, (u8)reg->reg);
    269	if (ret < 0)
    270		return ret;
    271
    272	reg->val = ret;
    273	reg->size = sizeof(u8);
    274
    275	return 0;
    276}
    277
    278static int ml86v7667_s_register(struct v4l2_subdev *sd,
    279				const struct v4l2_dbg_register *reg)
    280{
    281	struct i2c_client *client = v4l2_get_subdevdata(sd);
    282
    283	return i2c_smbus_write_byte_data(client, (u8)reg->reg, (u8)reg->val);
    284}
    285#endif
    286
    287static const struct v4l2_ctrl_ops ml86v7667_ctrl_ops = {
    288	.s_ctrl = ml86v7667_s_ctrl,
    289};
    290
    291static const struct v4l2_subdev_video_ops ml86v7667_subdev_video_ops = {
    292	.g_std = ml86v7667_g_std,
    293	.s_std = ml86v7667_s_std,
    294	.querystd = ml86v7667_querystd,
    295	.g_input_status = ml86v7667_g_input_status,
    296};
    297
    298static const struct v4l2_subdev_pad_ops ml86v7667_subdev_pad_ops = {
    299	.enum_mbus_code = ml86v7667_enum_mbus_code,
    300	.get_fmt = ml86v7667_fill_fmt,
    301	.set_fmt = ml86v7667_fill_fmt,
    302	.get_mbus_config = ml86v7667_get_mbus_config,
    303};
    304
    305static const struct v4l2_subdev_core_ops ml86v7667_subdev_core_ops = {
    306#ifdef CONFIG_VIDEO_ADV_DEBUG
    307	.g_register = ml86v7667_g_register,
    308	.s_register = ml86v7667_s_register,
    309#endif
    310};
    311
    312static const struct v4l2_subdev_ops ml86v7667_subdev_ops = {
    313	.core = &ml86v7667_subdev_core_ops,
    314	.video = &ml86v7667_subdev_video_ops,
    315	.pad = &ml86v7667_subdev_pad_ops,
    316};
    317
    318static int ml86v7667_init(struct ml86v7667_priv *priv)
    319{
    320	struct i2c_client *client = v4l2_get_subdevdata(&priv->sd);
    321	int val;
    322	int ret;
    323
    324	/* BT.656-4 output mode, register mode */
    325	ret = ml86v7667_mask_set(client, MRA_REG,
    326				 MRA_OUTPUT_MODE_MASK | MRA_REGISTER_MODE,
    327				 MRA_ITUR_BT656 | MRA_REGISTER_MODE);
    328
    329	/* PLL circuit fixed clock, 32MHz */
    330	ret |= ml86v7667_mask_set(client, PLLR1_REG, PLLR1_FIXED_CLOCK,
    331				  PLLR1_FIXED_CLOCK);
    332
    333	/* ADC2 clamping voltage maximum  */
    334	ret |= ml86v7667_mask_set(client, ADC2_REG, ADC2_CLAMP_VOLTAGE_MASK,
    335				  ADC2_CLAMP_VOLTAGE(7));
    336
    337	/* enable luminance function */
    338	ret |= ml86v7667_mask_set(client, SSEPL_REG, SSEPL_LUMINANCE_ONOFF,
    339				  SSEPL_LUMINANCE_ONOFF);
    340
    341	/* enable contrast function */
    342	ret |= ml86v7667_mask_set(client, CLC_REG, CLC_CONTRAST_ONOFF, 0);
    343
    344	/*
    345	 * PAL/NTSC autodetection is enabled after reset,
    346	 * set the autodetected std in manual std mode and
    347	 * disable autodetection
    348	 */
    349	val = i2c_smbus_read_byte_data(client, STATUS_REG);
    350	if (val < 0)
    351		return val;
    352
    353	priv->std = val & STATUS_NTSCPAL ? V4L2_STD_625_50 : V4L2_STD_525_60;
    354	ret |= ml86v7667_mask_set(client, MRC_REG, MRC_AUTOSELECT, 0);
    355
    356	val = priv->std & V4L2_STD_525_60 ? MRA_NTSC_BT601 : MRA_PAL_BT601;
    357	ret |= ml86v7667_mask_set(client, MRA_REG, MRA_INPUT_MODE_MASK, val);
    358
    359	return ret;
    360}
    361
    362static int ml86v7667_probe(struct i2c_client *client,
    363			   const struct i2c_device_id *did)
    364{
    365	struct ml86v7667_priv *priv;
    366	int ret;
    367
    368	if (!i2c_check_functionality(client->adapter, I2C_FUNC_SMBUS_BYTE_DATA))
    369		return -EIO;
    370
    371	priv = devm_kzalloc(&client->dev, sizeof(*priv), GFP_KERNEL);
    372	if (!priv)
    373		return -ENOMEM;
    374
    375	v4l2_i2c_subdev_init(&priv->sd, client, &ml86v7667_subdev_ops);
    376
    377	v4l2_ctrl_handler_init(&priv->hdl, 8);
    378	v4l2_ctrl_new_std(&priv->hdl, &ml86v7667_ctrl_ops,
    379			  V4L2_CID_BRIGHTNESS, -64, 63, 1, 0);
    380	v4l2_ctrl_new_std(&priv->hdl, &ml86v7667_ctrl_ops,
    381			  V4L2_CID_CONTRAST, -8, 7, 1, 0);
    382	v4l2_ctrl_new_std(&priv->hdl, &ml86v7667_ctrl_ops,
    383			  V4L2_CID_CHROMA_GAIN, -32, 31, 1, 0);
    384	v4l2_ctrl_new_std(&priv->hdl, &ml86v7667_ctrl_ops,
    385			  V4L2_CID_HUE, -128, 127, 1, 0);
    386	v4l2_ctrl_new_std(&priv->hdl, &ml86v7667_ctrl_ops,
    387			  V4L2_CID_RED_BALANCE, -4, 3, 1, 0);
    388	v4l2_ctrl_new_std(&priv->hdl, &ml86v7667_ctrl_ops,
    389			  V4L2_CID_BLUE_BALANCE, -4, 3, 1, 0);
    390	v4l2_ctrl_new_std(&priv->hdl, &ml86v7667_ctrl_ops,
    391			  V4L2_CID_SHARPNESS, 0, 1, 1, 0);
    392	v4l2_ctrl_new_std(&priv->hdl, &ml86v7667_ctrl_ops,
    393			  V4L2_CID_COLOR_KILLER, 0, 1, 1, 0);
    394	priv->sd.ctrl_handler = &priv->hdl;
    395
    396	ret = priv->hdl.error;
    397	if (ret)
    398		goto cleanup;
    399
    400	v4l2_ctrl_handler_setup(&priv->hdl);
    401
    402	ret = ml86v7667_init(priv);
    403	if (ret)
    404		goto cleanup;
    405
    406	v4l_info(client, "chip found @ 0x%02x (%s)\n",
    407		 client->addr, client->adapter->name);
    408	return 0;
    409
    410cleanup:
    411	v4l2_ctrl_handler_free(&priv->hdl);
    412	v4l2_device_unregister_subdev(&priv->sd);
    413	v4l_err(client, "failed to probe @ 0x%02x (%s)\n",
    414		client->addr, client->adapter->name);
    415	return ret;
    416}
    417
    418static int ml86v7667_remove(struct i2c_client *client)
    419{
    420	struct v4l2_subdev *sd = i2c_get_clientdata(client);
    421	struct ml86v7667_priv *priv = to_ml86v7667(sd);
    422
    423	v4l2_ctrl_handler_free(&priv->hdl);
    424	v4l2_device_unregister_subdev(&priv->sd);
    425
    426	return 0;
    427}
    428
    429static const struct i2c_device_id ml86v7667_id[] = {
    430	{DRV_NAME, 0},
    431	{},
    432};
    433MODULE_DEVICE_TABLE(i2c, ml86v7667_id);
    434
    435static struct i2c_driver ml86v7667_i2c_driver = {
    436	.driver = {
    437		.name	= DRV_NAME,
    438	},
    439	.probe		= ml86v7667_probe,
    440	.remove		= ml86v7667_remove,
    441	.id_table	= ml86v7667_id,
    442};
    443
    444module_i2c_driver(ml86v7667_i2c_driver);
    445
    446MODULE_DESCRIPTION("OKI Semiconductor ML86V7667 video decoder driver");
    447MODULE_AUTHOR("Vladimir Barinov");
    448MODULE_LICENSE("GPL");