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{
364	struct ml86v7667_priv *priv;
365	int ret;
366
367	if (!i2c_check_functionality(client->adapter, I2C_FUNC_SMBUS_BYTE_DATA))
368		return -EIO;
369
370	priv = devm_kzalloc(&client->dev, sizeof(*priv), GFP_KERNEL);
371	if (!priv)
372		return -ENOMEM;
373
374	v4l2_i2c_subdev_init(&priv->sd, client, &ml86v7667_subdev_ops);
375
376	v4l2_ctrl_handler_init(&priv->hdl, 8);
377	v4l2_ctrl_new_std(&priv->hdl, &ml86v7667_ctrl_ops,
378			  V4L2_CID_BRIGHTNESS, -64, 63, 1, 0);
379	v4l2_ctrl_new_std(&priv->hdl, &ml86v7667_ctrl_ops,
380			  V4L2_CID_CONTRAST, -8, 7, 1, 0);
381	v4l2_ctrl_new_std(&priv->hdl, &ml86v7667_ctrl_ops,
382			  V4L2_CID_CHROMA_GAIN, -32, 31, 1, 0);
383	v4l2_ctrl_new_std(&priv->hdl, &ml86v7667_ctrl_ops,
384			  V4L2_CID_HUE, -128, 127, 1, 0);
385	v4l2_ctrl_new_std(&priv->hdl, &ml86v7667_ctrl_ops,
386			  V4L2_CID_RED_BALANCE, -4, 3, 1, 0);
387	v4l2_ctrl_new_std(&priv->hdl, &ml86v7667_ctrl_ops,
388			  V4L2_CID_BLUE_BALANCE, -4, 3, 1, 0);
389	v4l2_ctrl_new_std(&priv->hdl, &ml86v7667_ctrl_ops,
390			  V4L2_CID_SHARPNESS, 0, 1, 1, 0);
391	v4l2_ctrl_new_std(&priv->hdl, &ml86v7667_ctrl_ops,
392			  V4L2_CID_COLOR_KILLER, 0, 1, 1, 0);
393	priv->sd.ctrl_handler = &priv->hdl;
394
395	ret = priv->hdl.error;
396	if (ret)
397		goto cleanup;
398
399	v4l2_ctrl_handler_setup(&priv->hdl);
400
401	ret = ml86v7667_init(priv);
402	if (ret)
403		goto cleanup;
404
405	v4l_info(client, "chip found @ 0x%02x (%s)\n",
406		 client->addr, client->adapter->name);
407	return 0;
408
409cleanup:
410	v4l2_ctrl_handler_free(&priv->hdl);
411	v4l2_device_unregister_subdev(&priv->sd);
412	v4l_err(client, "failed to probe @ 0x%02x (%s)\n",
413		client->addr, client->adapter->name);
414	return ret;
415}
416
417static void ml86v7667_remove(struct i2c_client *client)
418{
419	struct v4l2_subdev *sd = i2c_get_clientdata(client);
420	struct ml86v7667_priv *priv = to_ml86v7667(sd);
421
422	v4l2_ctrl_handler_free(&priv->hdl);
423	v4l2_device_unregister_subdev(&priv->sd);
424}
425
426static const struct i2c_device_id ml86v7667_id[] = {
427	{DRV_NAME, 0},
428	{},
429};
430MODULE_DEVICE_TABLE(i2c, ml86v7667_id);
431
432static struct i2c_driver ml86v7667_i2c_driver = {
433	.driver = {
434		.name	= DRV_NAME,
435	},
436	.probe		= ml86v7667_probe,
437	.remove		= ml86v7667_remove,
438	.id_table	= ml86v7667_id,
439};
440
441module_i2c_driver(ml86v7667_i2c_driver);
442
443MODULE_DESCRIPTION("OKI Semiconductor ML86V7667 video decoder driver");
444MODULE_AUTHOR("Vladimir Barinov");
445MODULE_LICENSE("GPL");
446