xref: /linux/drivers/media/i2c/adv7183.c (revision 6d3be300c658ce3f1777a6b1279414c62bc7d817)
1202ea1f0SScott Jiang /*
2202ea1f0SScott Jiang  * adv7183.c Analog Devices ADV7183 video decoder driver
3202ea1f0SScott Jiang  *
4202ea1f0SScott Jiang  * Copyright (c) 2011 Analog Devices Inc.
5202ea1f0SScott Jiang  *
6202ea1f0SScott Jiang  * This program is free software; you can redistribute it and/or modify
7202ea1f0SScott Jiang  * it under the terms of the GNU General Public License version 2 as
8202ea1f0SScott Jiang  * published by the Free Software Foundation.
9202ea1f0SScott Jiang  *
10202ea1f0SScott Jiang  * This program is distributed in the hope that it will be useful,
11202ea1f0SScott Jiang  * but WITHOUT ANY WARRANTY; without even the implied warranty of
12202ea1f0SScott Jiang  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13202ea1f0SScott Jiang  * GNU General Public License for more details.
14202ea1f0SScott Jiang  *
15202ea1f0SScott Jiang  * You should have received a copy of the GNU General Public License
16202ea1f0SScott Jiang  * along with this program; if not, write to the Free Software
17202ea1f0SScott Jiang  * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
18202ea1f0SScott Jiang  */
19202ea1f0SScott Jiang 
20202ea1f0SScott Jiang #include <linux/delay.h>
21202ea1f0SScott Jiang #include <linux/errno.h>
22202ea1f0SScott Jiang #include <linux/gpio.h>
23202ea1f0SScott Jiang #include <linux/i2c.h>
24202ea1f0SScott Jiang #include <linux/init.h>
25202ea1f0SScott Jiang #include <linux/module.h>
26202ea1f0SScott Jiang #include <linux/slab.h>
27202ea1f0SScott Jiang #include <linux/types.h>
28202ea1f0SScott Jiang #include <linux/videodev2.h>
29202ea1f0SScott Jiang 
30202ea1f0SScott Jiang #include <media/adv7183.h>
31202ea1f0SScott Jiang #include <media/v4l2-ctrls.h>
32202ea1f0SScott Jiang #include <media/v4l2-device.h>
33202ea1f0SScott Jiang 
34202ea1f0SScott Jiang #include "adv7183_regs.h"
35202ea1f0SScott Jiang 
36202ea1f0SScott Jiang struct adv7183 {
37202ea1f0SScott Jiang 	struct v4l2_subdev sd;
38202ea1f0SScott Jiang 	struct v4l2_ctrl_handler hdl;
39202ea1f0SScott Jiang 
40202ea1f0SScott Jiang 	v4l2_std_id std; /* Current set standard */
41202ea1f0SScott Jiang 	u32 input;
42202ea1f0SScott Jiang 	u32 output;
43202ea1f0SScott Jiang 	unsigned reset_pin;
44202ea1f0SScott Jiang 	unsigned oe_pin;
45202ea1f0SScott Jiang 	struct v4l2_mbus_framefmt fmt;
46202ea1f0SScott Jiang };
47202ea1f0SScott Jiang 
48202ea1f0SScott Jiang /* EXAMPLES USING 27 MHz CLOCK
49202ea1f0SScott Jiang  * Mode 1 CVBS Input (Composite Video on AIN5)
50202ea1f0SScott Jiang  * All standards are supported through autodetect, 8-bit, 4:2:2, ITU-R BT.656 output on P15 to P8.
51202ea1f0SScott Jiang  */
52202ea1f0SScott Jiang static const unsigned char adv7183_init_regs[] = {
53202ea1f0SScott Jiang 	ADV7183_IN_CTRL, 0x04,           /* CVBS input on AIN5 */
54202ea1f0SScott Jiang 	ADV7183_DIGI_CLAMP_CTRL_1, 0x00, /* Slow down digital clamps */
55202ea1f0SScott Jiang 	ADV7183_SHAP_FILT_CTRL, 0x41,    /* Set CSFM to SH1 */
56202ea1f0SScott Jiang 	ADV7183_ADC_CTRL, 0x16,          /* Power down ADC 1 and ADC 2 */
57202ea1f0SScott Jiang 	ADV7183_CTI_DNR_CTRL_4, 0x04,    /* Set DNR threshold to 4 for flat response */
58202ea1f0SScott Jiang 	/* ADI recommended programming sequence */
59202ea1f0SScott Jiang 	ADV7183_ADI_CTRL, 0x80,
60202ea1f0SScott Jiang 	ADV7183_CTI_DNR_CTRL_4, 0x20,
61202ea1f0SScott Jiang 	0x52, 0x18,
62202ea1f0SScott Jiang 	0x58, 0xED,
63202ea1f0SScott Jiang 	0x77, 0xC5,
64202ea1f0SScott Jiang 	0x7C, 0x93,
65202ea1f0SScott Jiang 	0x7D, 0x00,
66202ea1f0SScott Jiang 	0xD0, 0x48,
67202ea1f0SScott Jiang 	0xD5, 0xA0,
68202ea1f0SScott Jiang 	0xD7, 0xEA,
69202ea1f0SScott Jiang 	ADV7183_SD_SATURATION_CR, 0x3E,
70202ea1f0SScott Jiang 	ADV7183_PAL_V_END, 0x3E,
71202ea1f0SScott Jiang 	ADV7183_PAL_F_TOGGLE, 0x0F,
72202ea1f0SScott Jiang 	ADV7183_ADI_CTRL, 0x00,
73202ea1f0SScott Jiang };
74202ea1f0SScott Jiang 
75202ea1f0SScott Jiang static inline struct adv7183 *to_adv7183(struct v4l2_subdev *sd)
76202ea1f0SScott Jiang {
77202ea1f0SScott Jiang 	return container_of(sd, struct adv7183, sd);
78202ea1f0SScott Jiang }
79202ea1f0SScott Jiang static inline struct v4l2_subdev *to_sd(struct v4l2_ctrl *ctrl)
80202ea1f0SScott Jiang {
81202ea1f0SScott Jiang 	return &container_of(ctrl->handler, struct adv7183, hdl)->sd;
82202ea1f0SScott Jiang }
83202ea1f0SScott Jiang 
84202ea1f0SScott Jiang static inline int adv7183_read(struct v4l2_subdev *sd, unsigned char reg)
85202ea1f0SScott Jiang {
86202ea1f0SScott Jiang 	struct i2c_client *client = v4l2_get_subdevdata(sd);
87202ea1f0SScott Jiang 
88202ea1f0SScott Jiang 	return i2c_smbus_read_byte_data(client, reg);
89202ea1f0SScott Jiang }
90202ea1f0SScott Jiang 
91202ea1f0SScott Jiang static inline int adv7183_write(struct v4l2_subdev *sd, unsigned char reg,
92202ea1f0SScott Jiang 				unsigned char value)
93202ea1f0SScott Jiang {
94202ea1f0SScott Jiang 	struct i2c_client *client = v4l2_get_subdevdata(sd);
95202ea1f0SScott Jiang 
96202ea1f0SScott Jiang 	return i2c_smbus_write_byte_data(client, reg, value);
97202ea1f0SScott Jiang }
98202ea1f0SScott Jiang 
99202ea1f0SScott Jiang static int adv7183_writeregs(struct v4l2_subdev *sd,
100202ea1f0SScott Jiang 		const unsigned char *regs, unsigned int num)
101202ea1f0SScott Jiang {
102202ea1f0SScott Jiang 	unsigned char reg, data;
103202ea1f0SScott Jiang 	unsigned int cnt = 0;
104202ea1f0SScott Jiang 
105202ea1f0SScott Jiang 	if (num & 0x1) {
106202ea1f0SScott Jiang 		v4l2_err(sd, "invalid regs array\n");
107202ea1f0SScott Jiang 		return -1;
108202ea1f0SScott Jiang 	}
109202ea1f0SScott Jiang 
110202ea1f0SScott Jiang 	while (cnt < num) {
111202ea1f0SScott Jiang 		reg = *regs++;
112202ea1f0SScott Jiang 		data = *regs++;
113202ea1f0SScott Jiang 		cnt += 2;
114202ea1f0SScott Jiang 
115202ea1f0SScott Jiang 		adv7183_write(sd, reg, data);
116202ea1f0SScott Jiang 	}
117202ea1f0SScott Jiang 	return 0;
118202ea1f0SScott Jiang }
119202ea1f0SScott Jiang 
120202ea1f0SScott Jiang static int adv7183_log_status(struct v4l2_subdev *sd)
121202ea1f0SScott Jiang {
122202ea1f0SScott Jiang 	struct adv7183 *decoder = to_adv7183(sd);
123202ea1f0SScott Jiang 
124202ea1f0SScott Jiang 	v4l2_info(sd, "adv7183: Input control = 0x%02x\n",
125202ea1f0SScott Jiang 			adv7183_read(sd, ADV7183_IN_CTRL));
126202ea1f0SScott Jiang 	v4l2_info(sd, "adv7183: Video selection = 0x%02x\n",
127202ea1f0SScott Jiang 			adv7183_read(sd, ADV7183_VD_SEL));
128202ea1f0SScott Jiang 	v4l2_info(sd, "adv7183: Output control = 0x%02x\n",
129202ea1f0SScott Jiang 			adv7183_read(sd, ADV7183_OUT_CTRL));
130202ea1f0SScott Jiang 	v4l2_info(sd, "adv7183: Extended output control = 0x%02x\n",
131202ea1f0SScott Jiang 			adv7183_read(sd, ADV7183_EXT_OUT_CTRL));
132202ea1f0SScott Jiang 	v4l2_info(sd, "adv7183: Autodetect enable = 0x%02x\n",
133202ea1f0SScott Jiang 			adv7183_read(sd, ADV7183_AUTO_DET_EN));
134202ea1f0SScott Jiang 	v4l2_info(sd, "adv7183: Contrast = 0x%02x\n",
135202ea1f0SScott Jiang 			adv7183_read(sd, ADV7183_CONTRAST));
136202ea1f0SScott Jiang 	v4l2_info(sd, "adv7183: Brightness = 0x%02x\n",
137202ea1f0SScott Jiang 			adv7183_read(sd, ADV7183_BRIGHTNESS));
138202ea1f0SScott Jiang 	v4l2_info(sd, "adv7183: Hue = 0x%02x\n",
139202ea1f0SScott Jiang 			adv7183_read(sd, ADV7183_HUE));
140202ea1f0SScott Jiang 	v4l2_info(sd, "adv7183: Default value Y = 0x%02x\n",
141202ea1f0SScott Jiang 			adv7183_read(sd, ADV7183_DEF_Y));
142202ea1f0SScott Jiang 	v4l2_info(sd, "adv7183: Default value C = 0x%02x\n",
143202ea1f0SScott Jiang 			adv7183_read(sd, ADV7183_DEF_C));
144202ea1f0SScott Jiang 	v4l2_info(sd, "adv7183: ADI control = 0x%02x\n",
145202ea1f0SScott Jiang 			adv7183_read(sd, ADV7183_ADI_CTRL));
146202ea1f0SScott Jiang 	v4l2_info(sd, "adv7183: Power Management = 0x%02x\n",
147202ea1f0SScott Jiang 			adv7183_read(sd, ADV7183_POW_MANAGE));
148202ea1f0SScott Jiang 	v4l2_info(sd, "adv7183: Status 1 2 and 3 = 0x%02x 0x%02x 0x%02x\n",
149202ea1f0SScott Jiang 			adv7183_read(sd, ADV7183_STATUS_1),
150202ea1f0SScott Jiang 			adv7183_read(sd, ADV7183_STATUS_2),
151202ea1f0SScott Jiang 			adv7183_read(sd, ADV7183_STATUS_3));
152202ea1f0SScott Jiang 	v4l2_info(sd, "adv7183: Ident = 0x%02x\n",
153202ea1f0SScott Jiang 			adv7183_read(sd, ADV7183_IDENT));
154202ea1f0SScott Jiang 	v4l2_info(sd, "adv7183: Analog clamp control = 0x%02x\n",
155202ea1f0SScott Jiang 			adv7183_read(sd, ADV7183_ANAL_CLAMP_CTRL));
156202ea1f0SScott Jiang 	v4l2_info(sd, "adv7183: Digital clamp control 1 = 0x%02x\n",
157202ea1f0SScott Jiang 			adv7183_read(sd, ADV7183_DIGI_CLAMP_CTRL_1));
158202ea1f0SScott Jiang 	v4l2_info(sd, "adv7183: Shaping filter control 1 and 2 = 0x%02x 0x%02x\n",
159202ea1f0SScott Jiang 			adv7183_read(sd, ADV7183_SHAP_FILT_CTRL),
160202ea1f0SScott Jiang 			adv7183_read(sd, ADV7183_SHAP_FILT_CTRL_2));
161202ea1f0SScott Jiang 	v4l2_info(sd, "adv7183: Comb filter control = 0x%02x\n",
162202ea1f0SScott Jiang 			adv7183_read(sd, ADV7183_COMB_FILT_CTRL));
163202ea1f0SScott Jiang 	v4l2_info(sd, "adv7183: ADI control 2 = 0x%02x\n",
164202ea1f0SScott Jiang 			adv7183_read(sd, ADV7183_ADI_CTRL_2));
165202ea1f0SScott Jiang 	v4l2_info(sd, "adv7183: Pixel delay control = 0x%02x\n",
166202ea1f0SScott Jiang 			adv7183_read(sd, ADV7183_PIX_DELAY_CTRL));
167202ea1f0SScott Jiang 	v4l2_info(sd, "adv7183: Misc gain control = 0x%02x\n",
168202ea1f0SScott Jiang 			adv7183_read(sd, ADV7183_MISC_GAIN_CTRL));
169202ea1f0SScott Jiang 	v4l2_info(sd, "adv7183: AGC mode control = 0x%02x\n",
170202ea1f0SScott Jiang 			adv7183_read(sd, ADV7183_AGC_MODE_CTRL));
171202ea1f0SScott Jiang 	v4l2_info(sd, "adv7183: Chroma gain control 1 and 2 = 0x%02x 0x%02x\n",
172202ea1f0SScott Jiang 			adv7183_read(sd, ADV7183_CHRO_GAIN_CTRL_1),
173202ea1f0SScott Jiang 			adv7183_read(sd, ADV7183_CHRO_GAIN_CTRL_2));
174202ea1f0SScott Jiang 	v4l2_info(sd, "adv7183: Luma gain control 1 and 2 = 0x%02x 0x%02x\n",
175202ea1f0SScott Jiang 			adv7183_read(sd, ADV7183_LUMA_GAIN_CTRL_1),
176202ea1f0SScott Jiang 			adv7183_read(sd, ADV7183_LUMA_GAIN_CTRL_2));
177202ea1f0SScott Jiang 	v4l2_info(sd, "adv7183: Vsync field control 1 2 and 3 = 0x%02x 0x%02x 0x%02x\n",
178202ea1f0SScott Jiang 			adv7183_read(sd, ADV7183_VS_FIELD_CTRL_1),
179202ea1f0SScott Jiang 			adv7183_read(sd, ADV7183_VS_FIELD_CTRL_2),
180202ea1f0SScott Jiang 			adv7183_read(sd, ADV7183_VS_FIELD_CTRL_3));
181*6d3be300SMasanari Iida 	v4l2_info(sd, "adv7183: Hsync position control 1 2 and 3 = 0x%02x 0x%02x 0x%02x\n",
182202ea1f0SScott Jiang 			adv7183_read(sd, ADV7183_HS_POS_CTRL_1),
183202ea1f0SScott Jiang 			adv7183_read(sd, ADV7183_HS_POS_CTRL_2),
184202ea1f0SScott Jiang 			adv7183_read(sd, ADV7183_HS_POS_CTRL_3));
185202ea1f0SScott Jiang 	v4l2_info(sd, "adv7183: Polarity = 0x%02x\n",
186202ea1f0SScott Jiang 			adv7183_read(sd, ADV7183_POLARITY));
187202ea1f0SScott Jiang 	v4l2_info(sd, "adv7183: ADC control = 0x%02x\n",
188202ea1f0SScott Jiang 			adv7183_read(sd, ADV7183_ADC_CTRL));
189202ea1f0SScott Jiang 	v4l2_info(sd, "adv7183: SD offset Cb and Cr = 0x%02x 0x%02x\n",
190202ea1f0SScott Jiang 			adv7183_read(sd, ADV7183_SD_OFFSET_CB),
191202ea1f0SScott Jiang 			adv7183_read(sd, ADV7183_SD_OFFSET_CR));
192202ea1f0SScott Jiang 	v4l2_info(sd, "adv7183: SD saturation Cb and Cr = 0x%02x 0x%02x\n",
193202ea1f0SScott Jiang 			adv7183_read(sd, ADV7183_SD_SATURATION_CB),
194202ea1f0SScott Jiang 			adv7183_read(sd, ADV7183_SD_SATURATION_CR));
195202ea1f0SScott Jiang 	v4l2_info(sd, "adv7183: Drive strength = 0x%02x\n",
196202ea1f0SScott Jiang 			adv7183_read(sd, ADV7183_DRIVE_STR));
197202ea1f0SScott Jiang 	v4l2_ctrl_handler_log_status(&decoder->hdl, sd->name);
198202ea1f0SScott Jiang 	return 0;
199202ea1f0SScott Jiang }
200202ea1f0SScott Jiang 
201202ea1f0SScott Jiang static int adv7183_g_std(struct v4l2_subdev *sd, v4l2_std_id *std)
202202ea1f0SScott Jiang {
203202ea1f0SScott Jiang 	struct adv7183 *decoder = to_adv7183(sd);
204202ea1f0SScott Jiang 
205202ea1f0SScott Jiang 	*std = decoder->std;
206202ea1f0SScott Jiang 	return 0;
207202ea1f0SScott Jiang }
208202ea1f0SScott Jiang 
209202ea1f0SScott Jiang static int adv7183_s_std(struct v4l2_subdev *sd, v4l2_std_id std)
210202ea1f0SScott Jiang {
211202ea1f0SScott Jiang 	struct adv7183 *decoder = to_adv7183(sd);
212202ea1f0SScott Jiang 	int reg;
213202ea1f0SScott Jiang 
214202ea1f0SScott Jiang 	reg = adv7183_read(sd, ADV7183_IN_CTRL) & 0xF;
215202ea1f0SScott Jiang 	if (std == V4L2_STD_PAL_60)
216202ea1f0SScott Jiang 		reg |= 0x60;
217202ea1f0SScott Jiang 	else if (std == V4L2_STD_NTSC_443)
218202ea1f0SScott Jiang 		reg |= 0x70;
219202ea1f0SScott Jiang 	else if (std == V4L2_STD_PAL_N)
220202ea1f0SScott Jiang 		reg |= 0x90;
221202ea1f0SScott Jiang 	else if (std == V4L2_STD_PAL_M)
222202ea1f0SScott Jiang 		reg |= 0xA0;
223202ea1f0SScott Jiang 	else if (std == V4L2_STD_PAL_Nc)
224202ea1f0SScott Jiang 		reg |= 0xC0;
225202ea1f0SScott Jiang 	else if (std & V4L2_STD_PAL)
226202ea1f0SScott Jiang 		reg |= 0x80;
227202ea1f0SScott Jiang 	else if (std & V4L2_STD_NTSC)
228202ea1f0SScott Jiang 		reg |= 0x50;
229202ea1f0SScott Jiang 	else if (std & V4L2_STD_SECAM)
230202ea1f0SScott Jiang 		reg |= 0xE0;
231202ea1f0SScott Jiang 	else
232202ea1f0SScott Jiang 		return -EINVAL;
233202ea1f0SScott Jiang 	adv7183_write(sd, ADV7183_IN_CTRL, reg);
234202ea1f0SScott Jiang 
235202ea1f0SScott Jiang 	decoder->std = std;
236202ea1f0SScott Jiang 
237202ea1f0SScott Jiang 	return 0;
238202ea1f0SScott Jiang }
239202ea1f0SScott Jiang 
240202ea1f0SScott Jiang static int adv7183_reset(struct v4l2_subdev *sd, u32 val)
241202ea1f0SScott Jiang {
242202ea1f0SScott Jiang 	int reg;
243202ea1f0SScott Jiang 
244202ea1f0SScott Jiang 	reg = adv7183_read(sd, ADV7183_POW_MANAGE) | 0x80;
245202ea1f0SScott Jiang 	adv7183_write(sd, ADV7183_POW_MANAGE, reg);
246202ea1f0SScott Jiang 	/* wait 5ms before any further i2c writes are performed */
247202ea1f0SScott Jiang 	usleep_range(5000, 10000);
248202ea1f0SScott Jiang 	return 0;
249202ea1f0SScott Jiang }
250202ea1f0SScott Jiang 
251202ea1f0SScott Jiang static int adv7183_s_routing(struct v4l2_subdev *sd,
252202ea1f0SScott Jiang 				u32 input, u32 output, u32 config)
253202ea1f0SScott Jiang {
254202ea1f0SScott Jiang 	struct adv7183 *decoder = to_adv7183(sd);
255202ea1f0SScott Jiang 	int reg;
256202ea1f0SScott Jiang 
257202ea1f0SScott Jiang 	if ((input > ADV7183_COMPONENT1) || (output > ADV7183_16BIT_OUT))
258202ea1f0SScott Jiang 		return -EINVAL;
259202ea1f0SScott Jiang 
260202ea1f0SScott Jiang 	if (input != decoder->input) {
261202ea1f0SScott Jiang 		decoder->input = input;
262202ea1f0SScott Jiang 		reg = adv7183_read(sd, ADV7183_IN_CTRL) & 0xF0;
263202ea1f0SScott Jiang 		switch (input) {
264202ea1f0SScott Jiang 		case ADV7183_COMPOSITE1:
265202ea1f0SScott Jiang 			reg |= 0x1;
266202ea1f0SScott Jiang 			break;
267202ea1f0SScott Jiang 		case ADV7183_COMPOSITE2:
268202ea1f0SScott Jiang 			reg |= 0x2;
269202ea1f0SScott Jiang 			break;
270202ea1f0SScott Jiang 		case ADV7183_COMPOSITE3:
271202ea1f0SScott Jiang 			reg |= 0x3;
272202ea1f0SScott Jiang 			break;
273202ea1f0SScott Jiang 		case ADV7183_COMPOSITE4:
274202ea1f0SScott Jiang 			reg |= 0x4;
275202ea1f0SScott Jiang 			break;
276202ea1f0SScott Jiang 		case ADV7183_COMPOSITE5:
277202ea1f0SScott Jiang 			reg |= 0x5;
278202ea1f0SScott Jiang 			break;
279202ea1f0SScott Jiang 		case ADV7183_COMPOSITE6:
280202ea1f0SScott Jiang 			reg |= 0xB;
281202ea1f0SScott Jiang 			break;
282202ea1f0SScott Jiang 		case ADV7183_COMPOSITE7:
283202ea1f0SScott Jiang 			reg |= 0xC;
284202ea1f0SScott Jiang 			break;
285202ea1f0SScott Jiang 		case ADV7183_COMPOSITE8:
286202ea1f0SScott Jiang 			reg |= 0xD;
287202ea1f0SScott Jiang 			break;
288202ea1f0SScott Jiang 		case ADV7183_COMPOSITE9:
289202ea1f0SScott Jiang 			reg |= 0xE;
290202ea1f0SScott Jiang 			break;
291202ea1f0SScott Jiang 		case ADV7183_COMPOSITE10:
292202ea1f0SScott Jiang 			reg |= 0xF;
293202ea1f0SScott Jiang 			break;
294202ea1f0SScott Jiang 		case ADV7183_SVIDEO0:
295202ea1f0SScott Jiang 			reg |= 0x6;
296202ea1f0SScott Jiang 			break;
297202ea1f0SScott Jiang 		case ADV7183_SVIDEO1:
298202ea1f0SScott Jiang 			reg |= 0x7;
299202ea1f0SScott Jiang 			break;
300202ea1f0SScott Jiang 		case ADV7183_SVIDEO2:
301202ea1f0SScott Jiang 			reg |= 0x8;
302202ea1f0SScott Jiang 			break;
303202ea1f0SScott Jiang 		case ADV7183_COMPONENT0:
304202ea1f0SScott Jiang 			reg |= 0x9;
305202ea1f0SScott Jiang 			break;
306202ea1f0SScott Jiang 		case ADV7183_COMPONENT1:
307202ea1f0SScott Jiang 			reg |= 0xA;
308202ea1f0SScott Jiang 			break;
309202ea1f0SScott Jiang 		default:
310202ea1f0SScott Jiang 			break;
311202ea1f0SScott Jiang 		}
312202ea1f0SScott Jiang 		adv7183_write(sd, ADV7183_IN_CTRL, reg);
313202ea1f0SScott Jiang 	}
314202ea1f0SScott Jiang 
315202ea1f0SScott Jiang 	if (output != decoder->output) {
316202ea1f0SScott Jiang 		decoder->output = output;
317202ea1f0SScott Jiang 		reg = adv7183_read(sd, ADV7183_OUT_CTRL) & 0xC0;
318202ea1f0SScott Jiang 		switch (output) {
319202ea1f0SScott Jiang 		case ADV7183_16BIT_OUT:
320202ea1f0SScott Jiang 			reg |= 0x9;
321202ea1f0SScott Jiang 			break;
322202ea1f0SScott Jiang 		default:
323202ea1f0SScott Jiang 			reg |= 0xC;
324202ea1f0SScott Jiang 			break;
325202ea1f0SScott Jiang 		}
326202ea1f0SScott Jiang 		adv7183_write(sd, ADV7183_OUT_CTRL, reg);
327202ea1f0SScott Jiang 	}
328202ea1f0SScott Jiang 
329202ea1f0SScott Jiang 	return 0;
330202ea1f0SScott Jiang }
331202ea1f0SScott Jiang 
332202ea1f0SScott Jiang static int adv7183_s_ctrl(struct v4l2_ctrl *ctrl)
333202ea1f0SScott Jiang {
334202ea1f0SScott Jiang 	struct v4l2_subdev *sd = to_sd(ctrl);
335202ea1f0SScott Jiang 	int val = ctrl->val;
336202ea1f0SScott Jiang 
337202ea1f0SScott Jiang 	switch (ctrl->id) {
338202ea1f0SScott Jiang 	case V4L2_CID_BRIGHTNESS:
339202ea1f0SScott Jiang 		if (val < 0)
340202ea1f0SScott Jiang 			val = 127 - val;
341202ea1f0SScott Jiang 		adv7183_write(sd, ADV7183_BRIGHTNESS, val);
342202ea1f0SScott Jiang 		break;
343202ea1f0SScott Jiang 	case V4L2_CID_CONTRAST:
344202ea1f0SScott Jiang 		adv7183_write(sd, ADV7183_CONTRAST, val);
345202ea1f0SScott Jiang 		break;
346202ea1f0SScott Jiang 	case V4L2_CID_SATURATION:
347202ea1f0SScott Jiang 		adv7183_write(sd, ADV7183_SD_SATURATION_CB, val >> 8);
348202ea1f0SScott Jiang 		adv7183_write(sd, ADV7183_SD_SATURATION_CR, (val & 0xFF));
349202ea1f0SScott Jiang 		break;
350202ea1f0SScott Jiang 	case V4L2_CID_HUE:
351202ea1f0SScott Jiang 		adv7183_write(sd, ADV7183_SD_OFFSET_CB, val >> 8);
352202ea1f0SScott Jiang 		adv7183_write(sd, ADV7183_SD_OFFSET_CR, (val & 0xFF));
353202ea1f0SScott Jiang 		break;
354202ea1f0SScott Jiang 	default:
355202ea1f0SScott Jiang 		return -EINVAL;
356202ea1f0SScott Jiang 	}
357202ea1f0SScott Jiang 
358202ea1f0SScott Jiang 	return 0;
359202ea1f0SScott Jiang }
360202ea1f0SScott Jiang 
361202ea1f0SScott Jiang static int adv7183_querystd(struct v4l2_subdev *sd, v4l2_std_id *std)
362202ea1f0SScott Jiang {
363202ea1f0SScott Jiang 	struct adv7183 *decoder = to_adv7183(sd);
364202ea1f0SScott Jiang 	int reg;
365202ea1f0SScott Jiang 
366202ea1f0SScott Jiang 	/* enable autodetection block */
367202ea1f0SScott Jiang 	reg = adv7183_read(sd, ADV7183_IN_CTRL) & 0xF;
368202ea1f0SScott Jiang 	adv7183_write(sd, ADV7183_IN_CTRL, reg);
369202ea1f0SScott Jiang 
370202ea1f0SScott Jiang 	/* wait autodetection switch */
371202ea1f0SScott Jiang 	mdelay(10);
372202ea1f0SScott Jiang 
373202ea1f0SScott Jiang 	/* get autodetection result */
374202ea1f0SScott Jiang 	reg = adv7183_read(sd, ADV7183_STATUS_1);
375202ea1f0SScott Jiang 	switch ((reg >> 0x4) & 0x7) {
376202ea1f0SScott Jiang 	case 0:
3777dd8fbbeSHans Verkuil 		*std &= V4L2_STD_NTSC;
378202ea1f0SScott Jiang 		break;
379202ea1f0SScott Jiang 	case 1:
3807dd8fbbeSHans Verkuil 		*std &= V4L2_STD_NTSC_443;
381202ea1f0SScott Jiang 		break;
382202ea1f0SScott Jiang 	case 2:
3837dd8fbbeSHans Verkuil 		*std &= V4L2_STD_PAL_M;
384202ea1f0SScott Jiang 		break;
385202ea1f0SScott Jiang 	case 3:
3867dd8fbbeSHans Verkuil 		*std &= V4L2_STD_PAL_60;
387202ea1f0SScott Jiang 		break;
388202ea1f0SScott Jiang 	case 4:
3897dd8fbbeSHans Verkuil 		*std &= V4L2_STD_PAL;
390202ea1f0SScott Jiang 		break;
391202ea1f0SScott Jiang 	case 5:
3927dd8fbbeSHans Verkuil 		*std &= V4L2_STD_SECAM;
393202ea1f0SScott Jiang 		break;
394202ea1f0SScott Jiang 	case 6:
3957dd8fbbeSHans Verkuil 		*std &= V4L2_STD_PAL_Nc;
396202ea1f0SScott Jiang 		break;
397202ea1f0SScott Jiang 	case 7:
3987dd8fbbeSHans Verkuil 		*std &= V4L2_STD_SECAM;
399202ea1f0SScott Jiang 		break;
400202ea1f0SScott Jiang 	default:
401202ea1f0SScott Jiang 		*std = V4L2_STD_UNKNOWN;
402202ea1f0SScott Jiang 		break;
403202ea1f0SScott Jiang 	}
404202ea1f0SScott Jiang 
405202ea1f0SScott Jiang 	/* after std detection, write back user set std */
406202ea1f0SScott Jiang 	adv7183_s_std(sd, decoder->std);
407202ea1f0SScott Jiang 	return 0;
408202ea1f0SScott Jiang }
409202ea1f0SScott Jiang 
410202ea1f0SScott Jiang static int adv7183_g_input_status(struct v4l2_subdev *sd, u32 *status)
411202ea1f0SScott Jiang {
412202ea1f0SScott Jiang 	int reg;
413202ea1f0SScott Jiang 
414202ea1f0SScott Jiang 	*status = V4L2_IN_ST_NO_SIGNAL;
415202ea1f0SScott Jiang 	reg = adv7183_read(sd, ADV7183_STATUS_1);
416202ea1f0SScott Jiang 	if (reg < 0)
417202ea1f0SScott Jiang 		return reg;
418202ea1f0SScott Jiang 	if (reg & 0x1)
419202ea1f0SScott Jiang 		*status = 0;
420202ea1f0SScott Jiang 	return 0;
421202ea1f0SScott Jiang }
422202ea1f0SScott Jiang 
423202ea1f0SScott Jiang static int adv7183_enum_mbus_fmt(struct v4l2_subdev *sd, unsigned index,
424202ea1f0SScott Jiang 				enum v4l2_mbus_pixelcode *code)
425202ea1f0SScott Jiang {
426202ea1f0SScott Jiang 	if (index > 0)
427202ea1f0SScott Jiang 		return -EINVAL;
428202ea1f0SScott Jiang 
429202ea1f0SScott Jiang 	*code = V4L2_MBUS_FMT_UYVY8_2X8;
430202ea1f0SScott Jiang 	return 0;
431202ea1f0SScott Jiang }
432202ea1f0SScott Jiang 
433202ea1f0SScott Jiang static int adv7183_try_mbus_fmt(struct v4l2_subdev *sd,
434202ea1f0SScott Jiang 				struct v4l2_mbus_framefmt *fmt)
435202ea1f0SScott Jiang {
436202ea1f0SScott Jiang 	struct adv7183 *decoder = to_adv7183(sd);
437202ea1f0SScott Jiang 
438202ea1f0SScott Jiang 	fmt->code = V4L2_MBUS_FMT_UYVY8_2X8;
439202ea1f0SScott Jiang 	fmt->colorspace = V4L2_COLORSPACE_SMPTE170M;
440202ea1f0SScott Jiang 	if (decoder->std & V4L2_STD_525_60) {
441202ea1f0SScott Jiang 		fmt->field = V4L2_FIELD_SEQ_TB;
442202ea1f0SScott Jiang 		fmt->width = 720;
443202ea1f0SScott Jiang 		fmt->height = 480;
444202ea1f0SScott Jiang 	} else {
445202ea1f0SScott Jiang 		fmt->field = V4L2_FIELD_SEQ_BT;
446202ea1f0SScott Jiang 		fmt->width = 720;
447202ea1f0SScott Jiang 		fmt->height = 576;
448202ea1f0SScott Jiang 	}
449202ea1f0SScott Jiang 	return 0;
450202ea1f0SScott Jiang }
451202ea1f0SScott Jiang 
452202ea1f0SScott Jiang static int adv7183_s_mbus_fmt(struct v4l2_subdev *sd,
453202ea1f0SScott Jiang 				struct v4l2_mbus_framefmt *fmt)
454202ea1f0SScott Jiang {
455202ea1f0SScott Jiang 	struct adv7183 *decoder = to_adv7183(sd);
456202ea1f0SScott Jiang 
457202ea1f0SScott Jiang 	adv7183_try_mbus_fmt(sd, fmt);
458202ea1f0SScott Jiang 	decoder->fmt = *fmt;
459202ea1f0SScott Jiang 	return 0;
460202ea1f0SScott Jiang }
461202ea1f0SScott Jiang 
462202ea1f0SScott Jiang static int adv7183_g_mbus_fmt(struct v4l2_subdev *sd,
463202ea1f0SScott Jiang 				struct v4l2_mbus_framefmt *fmt)
464202ea1f0SScott Jiang {
465202ea1f0SScott Jiang 	struct adv7183 *decoder = to_adv7183(sd);
466202ea1f0SScott Jiang 
467202ea1f0SScott Jiang 	*fmt = decoder->fmt;
468202ea1f0SScott Jiang 	return 0;
469202ea1f0SScott Jiang }
470202ea1f0SScott Jiang 
471202ea1f0SScott Jiang static int adv7183_s_stream(struct v4l2_subdev *sd, int enable)
472202ea1f0SScott Jiang {
473202ea1f0SScott Jiang 	struct adv7183 *decoder = to_adv7183(sd);
474202ea1f0SScott Jiang 
475202ea1f0SScott Jiang 	if (enable)
47695323361SLaurent Pinchart 		gpio_set_value(decoder->oe_pin, 0);
477202ea1f0SScott Jiang 	else
47895323361SLaurent Pinchart 		gpio_set_value(decoder->oe_pin, 1);
479202ea1f0SScott Jiang 	udelay(1);
480202ea1f0SScott Jiang 	return 0;
481202ea1f0SScott Jiang }
482202ea1f0SScott Jiang 
483202ea1f0SScott Jiang #ifdef CONFIG_VIDEO_ADV_DEBUG
484202ea1f0SScott Jiang static int adv7183_g_register(struct v4l2_subdev *sd, struct v4l2_dbg_register *reg)
485202ea1f0SScott Jiang {
486202ea1f0SScott Jiang 	reg->val = adv7183_read(sd, reg->reg & 0xff);
487202ea1f0SScott Jiang 	reg->size = 1;
488202ea1f0SScott Jiang 	return 0;
489202ea1f0SScott Jiang }
490202ea1f0SScott Jiang 
491977ba3b1SHans Verkuil static int adv7183_s_register(struct v4l2_subdev *sd, const struct v4l2_dbg_register *reg)
492202ea1f0SScott Jiang {
493202ea1f0SScott Jiang 	adv7183_write(sd, reg->reg & 0xff, reg->val & 0xff);
494202ea1f0SScott Jiang 	return 0;
495202ea1f0SScott Jiang }
496202ea1f0SScott Jiang #endif
497202ea1f0SScott Jiang 
498202ea1f0SScott Jiang static const struct v4l2_ctrl_ops adv7183_ctrl_ops = {
499202ea1f0SScott Jiang 	.s_ctrl = adv7183_s_ctrl,
500202ea1f0SScott Jiang };
501202ea1f0SScott Jiang 
502202ea1f0SScott Jiang static const struct v4l2_subdev_core_ops adv7183_core_ops = {
503202ea1f0SScott Jiang 	.log_status = adv7183_log_status,
504202ea1f0SScott Jiang 	.g_std = adv7183_g_std,
505202ea1f0SScott Jiang 	.s_std = adv7183_s_std,
506202ea1f0SScott Jiang 	.reset = adv7183_reset,
507202ea1f0SScott Jiang #ifdef CONFIG_VIDEO_ADV_DEBUG
508202ea1f0SScott Jiang 	.g_register = adv7183_g_register,
509202ea1f0SScott Jiang 	.s_register = adv7183_s_register,
510202ea1f0SScott Jiang #endif
511202ea1f0SScott Jiang };
512202ea1f0SScott Jiang 
513202ea1f0SScott Jiang static const struct v4l2_subdev_video_ops adv7183_video_ops = {
514202ea1f0SScott Jiang 	.s_routing = adv7183_s_routing,
515202ea1f0SScott Jiang 	.querystd = adv7183_querystd,
516202ea1f0SScott Jiang 	.g_input_status = adv7183_g_input_status,
517202ea1f0SScott Jiang 	.enum_mbus_fmt = adv7183_enum_mbus_fmt,
518202ea1f0SScott Jiang 	.try_mbus_fmt = adv7183_try_mbus_fmt,
519202ea1f0SScott Jiang 	.s_mbus_fmt = adv7183_s_mbus_fmt,
520202ea1f0SScott Jiang 	.g_mbus_fmt = adv7183_g_mbus_fmt,
521202ea1f0SScott Jiang 	.s_stream = adv7183_s_stream,
522202ea1f0SScott Jiang };
523202ea1f0SScott Jiang 
524202ea1f0SScott Jiang static const struct v4l2_subdev_ops adv7183_ops = {
525202ea1f0SScott Jiang 	.core = &adv7183_core_ops,
526202ea1f0SScott Jiang 	.video = &adv7183_video_ops,
527202ea1f0SScott Jiang };
528202ea1f0SScott Jiang 
529202ea1f0SScott Jiang static int adv7183_probe(struct i2c_client *client,
530202ea1f0SScott Jiang 			const struct i2c_device_id *id)
531202ea1f0SScott Jiang {
532202ea1f0SScott Jiang 	struct adv7183 *decoder;
533202ea1f0SScott Jiang 	struct v4l2_subdev *sd;
534202ea1f0SScott Jiang 	struct v4l2_ctrl_handler *hdl;
535202ea1f0SScott Jiang 	int ret;
536202ea1f0SScott Jiang 	struct v4l2_mbus_framefmt fmt;
537202ea1f0SScott Jiang 	const unsigned *pin_array;
538202ea1f0SScott Jiang 
539202ea1f0SScott Jiang 	/* Check if the adapter supports the needed features */
540202ea1f0SScott Jiang 	if (!i2c_check_functionality(client->adapter, I2C_FUNC_SMBUS_BYTE_DATA))
541202ea1f0SScott Jiang 		return -EIO;
542202ea1f0SScott Jiang 
543202ea1f0SScott Jiang 	v4l_info(client, "chip found @ 0x%02x (%s)\n",
544202ea1f0SScott Jiang 			client->addr << 1, client->adapter->name);
545202ea1f0SScott Jiang 
546202ea1f0SScott Jiang 	pin_array = client->dev.platform_data;
547202ea1f0SScott Jiang 	if (pin_array == NULL)
548202ea1f0SScott Jiang 		return -EINVAL;
549202ea1f0SScott Jiang 
550c02b211dSLaurent Pinchart 	decoder = devm_kzalloc(&client->dev, sizeof(*decoder), GFP_KERNEL);
551202ea1f0SScott Jiang 	if (decoder == NULL)
552202ea1f0SScott Jiang 		return -ENOMEM;
553202ea1f0SScott Jiang 
554202ea1f0SScott Jiang 	decoder->reset_pin = pin_array[0];
555202ea1f0SScott Jiang 	decoder->oe_pin = pin_array[1];
556202ea1f0SScott Jiang 
557b015ba29SLaurent Pinchart 	if (devm_gpio_request_one(&client->dev, decoder->reset_pin,
558b015ba29SLaurent Pinchart 				  GPIOF_OUT_INIT_LOW, "ADV7183 Reset")) {
559202ea1f0SScott Jiang 		v4l_err(client, "failed to request GPIO %d\n", decoder->reset_pin);
560c02b211dSLaurent Pinchart 		return -EBUSY;
561202ea1f0SScott Jiang 	}
562202ea1f0SScott Jiang 
563b015ba29SLaurent Pinchart 	if (devm_gpio_request_one(&client->dev, decoder->oe_pin,
564b015ba29SLaurent Pinchart 				  GPIOF_OUT_INIT_HIGH,
56595323361SLaurent Pinchart 				  "ADV7183 Output Enable")) {
566202ea1f0SScott Jiang 		v4l_err(client, "failed to request GPIO %d\n", decoder->oe_pin);
567b015ba29SLaurent Pinchart 		return -EBUSY;
568202ea1f0SScott Jiang 	}
569202ea1f0SScott Jiang 
570202ea1f0SScott Jiang 	sd = &decoder->sd;
571202ea1f0SScott Jiang 	v4l2_i2c_subdev_init(sd, client, &adv7183_ops);
572202ea1f0SScott Jiang 
573202ea1f0SScott Jiang 	hdl = &decoder->hdl;
574202ea1f0SScott Jiang 	v4l2_ctrl_handler_init(hdl, 4);
575202ea1f0SScott Jiang 	v4l2_ctrl_new_std(hdl, &adv7183_ctrl_ops,
576202ea1f0SScott Jiang 			V4L2_CID_BRIGHTNESS, -128, 127, 1, 0);
577202ea1f0SScott Jiang 	v4l2_ctrl_new_std(hdl, &adv7183_ctrl_ops,
578202ea1f0SScott Jiang 			V4L2_CID_CONTRAST, 0, 0xFF, 1, 0x80);
579202ea1f0SScott Jiang 	v4l2_ctrl_new_std(hdl, &adv7183_ctrl_ops,
580202ea1f0SScott Jiang 			V4L2_CID_SATURATION, 0, 0xFFFF, 1, 0x8080);
581202ea1f0SScott Jiang 	v4l2_ctrl_new_std(hdl, &adv7183_ctrl_ops,
582202ea1f0SScott Jiang 			V4L2_CID_HUE, 0, 0xFFFF, 1, 0x8080);
583202ea1f0SScott Jiang 	/* hook the control handler into the driver */
584202ea1f0SScott Jiang 	sd->ctrl_handler = hdl;
585202ea1f0SScott Jiang 	if (hdl->error) {
586202ea1f0SScott Jiang 		ret = hdl->error;
587202ea1f0SScott Jiang 
588202ea1f0SScott Jiang 		v4l2_ctrl_handler_free(hdl);
589b015ba29SLaurent Pinchart 		return ret;
590202ea1f0SScott Jiang 	}
591202ea1f0SScott Jiang 
592202ea1f0SScott Jiang 	/* v4l2 doesn't support an autodetect standard, pick PAL as default */
593202ea1f0SScott Jiang 	decoder->std = V4L2_STD_PAL;
594202ea1f0SScott Jiang 	decoder->input = ADV7183_COMPOSITE4;
595202ea1f0SScott Jiang 	decoder->output = ADV7183_8BIT_OUT;
596202ea1f0SScott Jiang 
597202ea1f0SScott Jiang 	/* reset chip */
598202ea1f0SScott Jiang 	/* reset pulse width at least 5ms */
599202ea1f0SScott Jiang 	mdelay(10);
60095323361SLaurent Pinchart 	gpio_set_value(decoder->reset_pin, 1);
601202ea1f0SScott Jiang 	/* wait 5ms before any further i2c writes are performed */
602202ea1f0SScott Jiang 	mdelay(5);
603202ea1f0SScott Jiang 
604202ea1f0SScott Jiang 	adv7183_writeregs(sd, adv7183_init_regs, ARRAY_SIZE(adv7183_init_regs));
605202ea1f0SScott Jiang 	adv7183_s_std(sd, decoder->std);
606202ea1f0SScott Jiang 	fmt.width = 720;
607202ea1f0SScott Jiang 	fmt.height = 576;
608202ea1f0SScott Jiang 	adv7183_s_mbus_fmt(sd, &fmt);
609202ea1f0SScott Jiang 
610202ea1f0SScott Jiang 	/* initialize the hardware to the default control values */
611202ea1f0SScott Jiang 	ret = v4l2_ctrl_handler_setup(hdl);
612202ea1f0SScott Jiang 	if (ret) {
613202ea1f0SScott Jiang 		v4l2_ctrl_handler_free(hdl);
614b015ba29SLaurent Pinchart 		return ret;
615202ea1f0SScott Jiang 	}
616202ea1f0SScott Jiang 
617202ea1f0SScott Jiang 	return 0;
618202ea1f0SScott Jiang }
619202ea1f0SScott Jiang 
620202ea1f0SScott Jiang static int adv7183_remove(struct i2c_client *client)
621202ea1f0SScott Jiang {
622202ea1f0SScott Jiang 	struct v4l2_subdev *sd = i2c_get_clientdata(client);
623202ea1f0SScott Jiang 
624202ea1f0SScott Jiang 	v4l2_device_unregister_subdev(sd);
625202ea1f0SScott Jiang 	v4l2_ctrl_handler_free(sd->ctrl_handler);
626202ea1f0SScott Jiang 	return 0;
627202ea1f0SScott Jiang }
628202ea1f0SScott Jiang 
629202ea1f0SScott Jiang static const struct i2c_device_id adv7183_id[] = {
630202ea1f0SScott Jiang 	{"adv7183", 0},
631202ea1f0SScott Jiang 	{},
632202ea1f0SScott Jiang };
633202ea1f0SScott Jiang 
634202ea1f0SScott Jiang MODULE_DEVICE_TABLE(i2c, adv7183_id);
635202ea1f0SScott Jiang 
636202ea1f0SScott Jiang static struct i2c_driver adv7183_driver = {
637202ea1f0SScott Jiang 	.driver = {
638202ea1f0SScott Jiang 		.owner  = THIS_MODULE,
639202ea1f0SScott Jiang 		.name   = "adv7183",
640202ea1f0SScott Jiang 	},
641202ea1f0SScott Jiang 	.probe          = adv7183_probe,
6424c62e976SGreg Kroah-Hartman 	.remove         = adv7183_remove,
643202ea1f0SScott Jiang 	.id_table       = adv7183_id,
644202ea1f0SScott Jiang };
645202ea1f0SScott Jiang 
64601aea0bfSWei Yongjun module_i2c_driver(adv7183_driver);
647202ea1f0SScott Jiang 
648202ea1f0SScott Jiang MODULE_DESCRIPTION("Analog Devices ADV7183 video decoder driver");
649202ea1f0SScott Jiang MODULE_AUTHOR("Scott Jiang <Scott.Jiang.Linux@gmail.com>");
650202ea1f0SScott Jiang MODULE_LICENSE("GPL v2");
651