xref: /linux/drivers/media/i2c/adv7511-v4l2.c (revision 1771e9fb67e2d6df29acb0ee8349c3833a212754)
1b2ce5617SAnders Roxell // SPDX-License-Identifier: GPL-2.0-only
2b2ce5617SAnders Roxell /*
3b2ce5617SAnders Roxell  * Analog Devices ADV7511 HDMI Transmitter Device Driver
4b2ce5617SAnders Roxell  *
5b2ce5617SAnders Roxell  * Copyright 2013 Cisco Systems, Inc. and/or its affiliates. All rights reserved.
6b2ce5617SAnders Roxell  */
7b2ce5617SAnders Roxell 
8b2ce5617SAnders Roxell /*
9b2ce5617SAnders Roxell  * This file is named adv7511-v4l2.c so it doesn't conflict with the Analog
10b2ce5617SAnders Roxell  * Device ADV7511 (config fragment CONFIG_DRM_I2C_ADV7511).
11b2ce5617SAnders Roxell  */
12b2ce5617SAnders Roxell 
13b2ce5617SAnders Roxell 
14b2ce5617SAnders Roxell #include <linux/kernel.h>
15b2ce5617SAnders Roxell #include <linux/module.h>
16b2ce5617SAnders Roxell #include <linux/slab.h>
17b2ce5617SAnders Roxell #include <linux/i2c.h>
18b2ce5617SAnders Roxell #include <linux/delay.h>
19b2ce5617SAnders Roxell #include <linux/videodev2.h>
20b2ce5617SAnders Roxell #include <linux/gpio.h>
21b2ce5617SAnders Roxell #include <linux/workqueue.h>
22b2ce5617SAnders Roxell #include <linux/hdmi.h>
23b2ce5617SAnders Roxell #include <linux/v4l2-dv-timings.h>
24b2ce5617SAnders Roxell #include <media/v4l2-device.h>
25b2ce5617SAnders Roxell #include <media/v4l2-common.h>
26b2ce5617SAnders Roxell #include <media/v4l2-ctrls.h>
27b2ce5617SAnders Roxell #include <media/v4l2-dv-timings.h>
28b2ce5617SAnders Roxell #include <media/i2c/adv7511.h>
29b2ce5617SAnders Roxell #include <media/cec.h>
30b2ce5617SAnders Roxell 
31b2ce5617SAnders Roxell static int debug;
32b2ce5617SAnders Roxell module_param(debug, int, 0644);
33b2ce5617SAnders Roxell MODULE_PARM_DESC(debug, "debug level (0-2)");
34b2ce5617SAnders Roxell 
35b2ce5617SAnders Roxell MODULE_DESCRIPTION("Analog Devices ADV7511 HDMI Transmitter Device Driver");
36b2ce5617SAnders Roxell MODULE_AUTHOR("Hans Verkuil");
37b2ce5617SAnders Roxell MODULE_LICENSE("GPL v2");
38b2ce5617SAnders Roxell 
39b2ce5617SAnders Roxell #define MASK_ADV7511_EDID_RDY_INT   0x04
40b2ce5617SAnders Roxell #define MASK_ADV7511_MSEN_INT       0x40
41b2ce5617SAnders Roxell #define MASK_ADV7511_HPD_INT        0x80
42b2ce5617SAnders Roxell 
43b2ce5617SAnders Roxell #define MASK_ADV7511_HPD_DETECT     0x40
44b2ce5617SAnders Roxell #define MASK_ADV7511_MSEN_DETECT    0x20
45b2ce5617SAnders Roxell #define MASK_ADV7511_EDID_RDY       0x10
46b2ce5617SAnders Roxell 
47b2ce5617SAnders Roxell #define EDID_MAX_RETRIES (8)
48b2ce5617SAnders Roxell #define EDID_DELAY 250
49b2ce5617SAnders Roxell #define EDID_MAX_SEGM 8
50b2ce5617SAnders Roxell 
51b2ce5617SAnders Roxell #define ADV7511_MAX_WIDTH 1920
52b2ce5617SAnders Roxell #define ADV7511_MAX_HEIGHT 1200
53b2ce5617SAnders Roxell #define ADV7511_MIN_PIXELCLOCK 20000000
54b2ce5617SAnders Roxell #define ADV7511_MAX_PIXELCLOCK 225000000
55b2ce5617SAnders Roxell 
56b2ce5617SAnders Roxell #define ADV7511_MAX_ADDRS (3)
57b2ce5617SAnders Roxell 
58b2ce5617SAnders Roxell /*
59b2ce5617SAnders Roxell **********************************************************************
60b2ce5617SAnders Roxell *
61b2ce5617SAnders Roxell *  Arrays with configuration parameters for the ADV7511
62b2ce5617SAnders Roxell *
63b2ce5617SAnders Roxell **********************************************************************
64b2ce5617SAnders Roxell */
65b2ce5617SAnders Roxell 
66b2ce5617SAnders Roxell struct i2c_reg_value {
67b2ce5617SAnders Roxell 	unsigned char reg;
68b2ce5617SAnders Roxell 	unsigned char value;
69b2ce5617SAnders Roxell };
70b2ce5617SAnders Roxell 
71b2ce5617SAnders Roxell struct adv7511_state_edid {
72b2ce5617SAnders Roxell 	/* total number of blocks */
73b2ce5617SAnders Roxell 	u32 blocks;
74b2ce5617SAnders Roxell 	/* Number of segments read */
75b2ce5617SAnders Roxell 	u32 segments;
76b2ce5617SAnders Roxell 	u8 data[EDID_MAX_SEGM * 256];
77b2ce5617SAnders Roxell 	/* Number of EDID read retries left */
78b2ce5617SAnders Roxell 	unsigned read_retries;
79b2ce5617SAnders Roxell 	bool complete;
80b2ce5617SAnders Roxell };
81b2ce5617SAnders Roxell 
82b2ce5617SAnders Roxell struct adv7511_state {
83b2ce5617SAnders Roxell 	struct adv7511_platform_data pdata;
84b2ce5617SAnders Roxell 	struct v4l2_subdev sd;
85b2ce5617SAnders Roxell 	struct media_pad pad;
86b2ce5617SAnders Roxell 	struct v4l2_ctrl_handler hdl;
87b2ce5617SAnders Roxell 	int chip_revision;
88b2ce5617SAnders Roxell 	u8 i2c_edid_addr;
89b2ce5617SAnders Roxell 	u8 i2c_pktmem_addr;
90b2ce5617SAnders Roxell 	u8 i2c_cec_addr;
91b2ce5617SAnders Roxell 
92b2ce5617SAnders Roxell 	struct i2c_client *i2c_cec;
93b2ce5617SAnders Roxell 	struct cec_adapter *cec_adap;
94b2ce5617SAnders Roxell 	u8   cec_addr[ADV7511_MAX_ADDRS];
95b2ce5617SAnders Roxell 	u8   cec_valid_addrs;
96b2ce5617SAnders Roxell 	bool cec_enabled_adap;
97b2ce5617SAnders Roxell 
98b2ce5617SAnders Roxell 	/* Is the adv7511 powered on? */
99b2ce5617SAnders Roxell 	bool power_on;
100b2ce5617SAnders Roxell 	/* Did we receive hotplug and rx-sense signals? */
101b2ce5617SAnders Roxell 	bool have_monitor;
102b2ce5617SAnders Roxell 	bool enabled_irq;
103b2ce5617SAnders Roxell 	/* timings from s_dv_timings */
104b2ce5617SAnders Roxell 	struct v4l2_dv_timings dv_timings;
105b2ce5617SAnders Roxell 	u32 fmt_code;
106b2ce5617SAnders Roxell 	u32 colorspace;
107b2ce5617SAnders Roxell 	u32 ycbcr_enc;
108b2ce5617SAnders Roxell 	u32 quantization;
109b2ce5617SAnders Roxell 	u32 xfer_func;
110b2ce5617SAnders Roxell 	u32 content_type;
111b2ce5617SAnders Roxell 	/* controls */
112b2ce5617SAnders Roxell 	struct v4l2_ctrl *hdmi_mode_ctrl;
113b2ce5617SAnders Roxell 	struct v4l2_ctrl *hotplug_ctrl;
114b2ce5617SAnders Roxell 	struct v4l2_ctrl *rx_sense_ctrl;
115b2ce5617SAnders Roxell 	struct v4l2_ctrl *have_edid0_ctrl;
116b2ce5617SAnders Roxell 	struct v4l2_ctrl *rgb_quantization_range_ctrl;
117b2ce5617SAnders Roxell 	struct v4l2_ctrl *content_type_ctrl;
118b2ce5617SAnders Roxell 	struct i2c_client *i2c_edid;
119b2ce5617SAnders Roxell 	struct i2c_client *i2c_pktmem;
120b2ce5617SAnders Roxell 	struct adv7511_state_edid edid;
121b2ce5617SAnders Roxell 	/* Running counter of the number of detected EDIDs (for debugging) */
122b2ce5617SAnders Roxell 	unsigned edid_detect_counter;
123b2ce5617SAnders Roxell 	struct workqueue_struct *work_queue;
124b2ce5617SAnders Roxell 	struct delayed_work edid_handler; /* work entry */
125b2ce5617SAnders Roxell };
126b2ce5617SAnders Roxell 
127b2ce5617SAnders Roxell static void adv7511_check_monitor_present_status(struct v4l2_subdev *sd);
128b2ce5617SAnders Roxell static bool adv7511_check_edid_status(struct v4l2_subdev *sd);
129b2ce5617SAnders Roxell static void adv7511_setup(struct v4l2_subdev *sd);
130b2ce5617SAnders Roxell static int adv7511_s_i2s_clock_freq(struct v4l2_subdev *sd, u32 freq);
131b2ce5617SAnders Roxell static int adv7511_s_clock_freq(struct v4l2_subdev *sd, u32 freq);
132b2ce5617SAnders Roxell 
133b2ce5617SAnders Roxell 
134b2ce5617SAnders Roxell static const struct v4l2_dv_timings_cap adv7511_timings_cap = {
135b2ce5617SAnders Roxell 	.type = V4L2_DV_BT_656_1120,
136b2ce5617SAnders Roxell 	/* keep this initialization for compatibility with GCC < 4.4.6 */
137b2ce5617SAnders Roxell 	.reserved = { 0 },
138b2ce5617SAnders Roxell 	V4L2_INIT_BT_TIMINGS(640, ADV7511_MAX_WIDTH, 350, ADV7511_MAX_HEIGHT,
139b2ce5617SAnders Roxell 		ADV7511_MIN_PIXELCLOCK, ADV7511_MAX_PIXELCLOCK,
140b2ce5617SAnders Roxell 		V4L2_DV_BT_STD_CEA861 | V4L2_DV_BT_STD_DMT |
141b2ce5617SAnders Roxell 			V4L2_DV_BT_STD_GTF | V4L2_DV_BT_STD_CVT,
142b2ce5617SAnders Roxell 		V4L2_DV_BT_CAP_PROGRESSIVE | V4L2_DV_BT_CAP_REDUCED_BLANKING |
143b2ce5617SAnders Roxell 			V4L2_DV_BT_CAP_CUSTOM)
144b2ce5617SAnders Roxell };
145b2ce5617SAnders Roxell 
146b2ce5617SAnders Roxell static inline struct adv7511_state *get_adv7511_state(struct v4l2_subdev *sd)
147b2ce5617SAnders Roxell {
148b2ce5617SAnders Roxell 	return container_of(sd, struct adv7511_state, sd);
149b2ce5617SAnders Roxell }
150b2ce5617SAnders Roxell 
151b2ce5617SAnders Roxell static inline struct v4l2_subdev *to_sd(struct v4l2_ctrl *ctrl)
152b2ce5617SAnders Roxell {
153b2ce5617SAnders Roxell 	return &container_of(ctrl->handler, struct adv7511_state, hdl)->sd;
154b2ce5617SAnders Roxell }
155b2ce5617SAnders Roxell 
156b2ce5617SAnders Roxell /* ------------------------ I2C ----------------------------------------------- */
157b2ce5617SAnders Roxell 
158b2ce5617SAnders Roxell static s32 adv_smbus_read_byte_data_check(struct i2c_client *client,
159b2ce5617SAnders Roxell 					  u8 command, bool check)
160b2ce5617SAnders Roxell {
161b2ce5617SAnders Roxell 	union i2c_smbus_data data;
162b2ce5617SAnders Roxell 
163b2ce5617SAnders Roxell 	if (!i2c_smbus_xfer(client->adapter, client->addr, client->flags,
164b2ce5617SAnders Roxell 			    I2C_SMBUS_READ, command,
165b2ce5617SAnders Roxell 			    I2C_SMBUS_BYTE_DATA, &data))
166b2ce5617SAnders Roxell 		return data.byte;
167b2ce5617SAnders Roxell 	if (check)
168b2ce5617SAnders Roxell 		v4l_err(client, "error reading %02x, %02x\n",
169b2ce5617SAnders Roxell 			client->addr, command);
170b2ce5617SAnders Roxell 	return -1;
171b2ce5617SAnders Roxell }
172b2ce5617SAnders Roxell 
173b2ce5617SAnders Roxell static s32 adv_smbus_read_byte_data(struct i2c_client *client, u8 command)
174b2ce5617SAnders Roxell {
175b2ce5617SAnders Roxell 	int i;
176b2ce5617SAnders Roxell 	for (i = 0; i < 3; i++) {
177b2ce5617SAnders Roxell 		int ret = adv_smbus_read_byte_data_check(client, command, true);
178b2ce5617SAnders Roxell 		if (ret >= 0) {
179b2ce5617SAnders Roxell 			if (i)
180b2ce5617SAnders Roxell 				v4l_err(client, "read ok after %d retries\n", i);
181b2ce5617SAnders Roxell 			return ret;
182b2ce5617SAnders Roxell 		}
183b2ce5617SAnders Roxell 	}
184b2ce5617SAnders Roxell 	v4l_err(client, "read failed\n");
185b2ce5617SAnders Roxell 	return -1;
186b2ce5617SAnders Roxell }
187b2ce5617SAnders Roxell 
188b2ce5617SAnders Roxell static int adv7511_rd(struct v4l2_subdev *sd, u8 reg)
189b2ce5617SAnders Roxell {
190b2ce5617SAnders Roxell 	struct i2c_client *client = v4l2_get_subdevdata(sd);
191b2ce5617SAnders Roxell 
192b2ce5617SAnders Roxell 	return adv_smbus_read_byte_data(client, reg);
193b2ce5617SAnders Roxell }
194b2ce5617SAnders Roxell 
195b2ce5617SAnders Roxell static int adv7511_wr(struct v4l2_subdev *sd, u8 reg, u8 val)
196b2ce5617SAnders Roxell {
197b2ce5617SAnders Roxell 	struct i2c_client *client = v4l2_get_subdevdata(sd);
198b2ce5617SAnders Roxell 	int ret;
199b2ce5617SAnders Roxell 	int i;
200b2ce5617SAnders Roxell 
201b2ce5617SAnders Roxell 	for (i = 0; i < 3; i++) {
202b2ce5617SAnders Roxell 		ret = i2c_smbus_write_byte_data(client, reg, val);
203b2ce5617SAnders Roxell 		if (ret == 0)
204b2ce5617SAnders Roxell 			return 0;
205b2ce5617SAnders Roxell 	}
206b2ce5617SAnders Roxell 	v4l2_err(sd, "%s: i2c write error\n", __func__);
207b2ce5617SAnders Roxell 	return ret;
208b2ce5617SAnders Roxell }
209b2ce5617SAnders Roxell 
210b2ce5617SAnders Roxell /* To set specific bits in the register, a clear-mask is given (to be AND-ed),
211b2ce5617SAnders Roxell    and then the value-mask (to be OR-ed). */
212b2ce5617SAnders Roxell static inline void adv7511_wr_and_or(struct v4l2_subdev *sd, u8 reg, u8 clr_mask, u8 val_mask)
213b2ce5617SAnders Roxell {
214b2ce5617SAnders Roxell 	adv7511_wr(sd, reg, (adv7511_rd(sd, reg) & clr_mask) | val_mask);
215b2ce5617SAnders Roxell }
216b2ce5617SAnders Roxell 
217b2ce5617SAnders Roxell static int adv_smbus_read_i2c_block_data(struct i2c_client *client,
218b2ce5617SAnders Roxell 					 u8 command, unsigned length, u8 *values)
219b2ce5617SAnders Roxell {
220b2ce5617SAnders Roxell 	union i2c_smbus_data data;
221b2ce5617SAnders Roxell 	int ret;
222b2ce5617SAnders Roxell 
223b2ce5617SAnders Roxell 	if (length > I2C_SMBUS_BLOCK_MAX)
224b2ce5617SAnders Roxell 		length = I2C_SMBUS_BLOCK_MAX;
225b2ce5617SAnders Roxell 	data.block[0] = length;
226b2ce5617SAnders Roxell 
227b2ce5617SAnders Roxell 	ret = i2c_smbus_xfer(client->adapter, client->addr, client->flags,
228b2ce5617SAnders Roxell 			     I2C_SMBUS_READ, command,
229b2ce5617SAnders Roxell 			     I2C_SMBUS_I2C_BLOCK_DATA, &data);
230b2ce5617SAnders Roxell 	memcpy(values, data.block + 1, length);
231b2ce5617SAnders Roxell 	return ret;
232b2ce5617SAnders Roxell }
233b2ce5617SAnders Roxell 
234b2ce5617SAnders Roxell static void adv7511_edid_rd(struct v4l2_subdev *sd, uint16_t len, uint8_t *buf)
235b2ce5617SAnders Roxell {
236b2ce5617SAnders Roxell 	struct adv7511_state *state = get_adv7511_state(sd);
237b2ce5617SAnders Roxell 	int i;
238b2ce5617SAnders Roxell 	int err = 0;
239b2ce5617SAnders Roxell 
240b2ce5617SAnders Roxell 	v4l2_dbg(1, debug, sd, "%s:\n", __func__);
241b2ce5617SAnders Roxell 
242b2ce5617SAnders Roxell 	for (i = 0; !err && i < len; i += I2C_SMBUS_BLOCK_MAX)
243b2ce5617SAnders Roxell 		err = adv_smbus_read_i2c_block_data(state->i2c_edid, i,
244b2ce5617SAnders Roxell 						    I2C_SMBUS_BLOCK_MAX, buf + i);
245b2ce5617SAnders Roxell 	if (err)
246b2ce5617SAnders Roxell 		v4l2_err(sd, "%s: i2c read error\n", __func__);
247b2ce5617SAnders Roxell }
248b2ce5617SAnders Roxell 
249b2ce5617SAnders Roxell static inline int adv7511_cec_read(struct v4l2_subdev *sd, u8 reg)
250b2ce5617SAnders Roxell {
251b2ce5617SAnders Roxell 	struct adv7511_state *state = get_adv7511_state(sd);
252b2ce5617SAnders Roxell 
253b2ce5617SAnders Roxell 	return i2c_smbus_read_byte_data(state->i2c_cec, reg);
254b2ce5617SAnders Roxell }
255b2ce5617SAnders Roxell 
256b2ce5617SAnders Roxell static int adv7511_cec_write(struct v4l2_subdev *sd, u8 reg, u8 val)
257b2ce5617SAnders Roxell {
258b2ce5617SAnders Roxell 	struct adv7511_state *state = get_adv7511_state(sd);
259b2ce5617SAnders Roxell 	int ret;
260b2ce5617SAnders Roxell 	int i;
261b2ce5617SAnders Roxell 
262b2ce5617SAnders Roxell 	for (i = 0; i < 3; i++) {
263b2ce5617SAnders Roxell 		ret = i2c_smbus_write_byte_data(state->i2c_cec, reg, val);
264b2ce5617SAnders Roxell 		if (ret == 0)
265b2ce5617SAnders Roxell 			return 0;
266b2ce5617SAnders Roxell 	}
267b2ce5617SAnders Roxell 	v4l2_err(sd, "%s: I2C Write Problem\n", __func__);
268b2ce5617SAnders Roxell 	return ret;
269b2ce5617SAnders Roxell }
270b2ce5617SAnders Roxell 
271b2ce5617SAnders Roxell static inline int adv7511_cec_write_and_or(struct v4l2_subdev *sd, u8 reg, u8 mask,
272b2ce5617SAnders Roxell 				   u8 val)
273b2ce5617SAnders Roxell {
274b2ce5617SAnders Roxell 	return adv7511_cec_write(sd, reg, (adv7511_cec_read(sd, reg) & mask) | val);
275b2ce5617SAnders Roxell }
276b2ce5617SAnders Roxell 
277b2ce5617SAnders Roxell static int adv7511_pktmem_rd(struct v4l2_subdev *sd, u8 reg)
278b2ce5617SAnders Roxell {
279b2ce5617SAnders Roxell 	struct adv7511_state *state = get_adv7511_state(sd);
280b2ce5617SAnders Roxell 
281b2ce5617SAnders Roxell 	return adv_smbus_read_byte_data(state->i2c_pktmem, reg);
282b2ce5617SAnders Roxell }
283b2ce5617SAnders Roxell 
284b2ce5617SAnders Roxell static int adv7511_pktmem_wr(struct v4l2_subdev *sd, u8 reg, u8 val)
285b2ce5617SAnders Roxell {
286b2ce5617SAnders Roxell 	struct adv7511_state *state = get_adv7511_state(sd);
287b2ce5617SAnders Roxell 	int ret;
288b2ce5617SAnders Roxell 	int i;
289b2ce5617SAnders Roxell 
290b2ce5617SAnders Roxell 	for (i = 0; i < 3; i++) {
291b2ce5617SAnders Roxell 		ret = i2c_smbus_write_byte_data(state->i2c_pktmem, reg, val);
292b2ce5617SAnders Roxell 		if (ret == 0)
293b2ce5617SAnders Roxell 			return 0;
294b2ce5617SAnders Roxell 	}
295b2ce5617SAnders Roxell 	v4l2_err(sd, "%s: i2c write error\n", __func__);
296b2ce5617SAnders Roxell 	return ret;
297b2ce5617SAnders Roxell }
298b2ce5617SAnders Roxell 
299b2ce5617SAnders Roxell /* To set specific bits in the register, a clear-mask is given (to be AND-ed),
300b2ce5617SAnders Roxell    and then the value-mask (to be OR-ed). */
301b2ce5617SAnders Roxell static inline void adv7511_pktmem_wr_and_or(struct v4l2_subdev *sd, u8 reg, u8 clr_mask, u8 val_mask)
302b2ce5617SAnders Roxell {
303b2ce5617SAnders Roxell 	adv7511_pktmem_wr(sd, reg, (adv7511_pktmem_rd(sd, reg) & clr_mask) | val_mask);
304b2ce5617SAnders Roxell }
305b2ce5617SAnders Roxell 
306b2ce5617SAnders Roxell static inline bool adv7511_have_hotplug(struct v4l2_subdev *sd)
307b2ce5617SAnders Roxell {
308b2ce5617SAnders Roxell 	return adv7511_rd(sd, 0x42) & MASK_ADV7511_HPD_DETECT;
309b2ce5617SAnders Roxell }
310b2ce5617SAnders Roxell 
311b2ce5617SAnders Roxell static inline bool adv7511_have_rx_sense(struct v4l2_subdev *sd)
312b2ce5617SAnders Roxell {
313b2ce5617SAnders Roxell 	return adv7511_rd(sd, 0x42) & MASK_ADV7511_MSEN_DETECT;
314b2ce5617SAnders Roxell }
315b2ce5617SAnders Roxell 
316b2ce5617SAnders Roxell static void adv7511_csc_conversion_mode(struct v4l2_subdev *sd, u8 mode)
317b2ce5617SAnders Roxell {
318b2ce5617SAnders Roxell 	adv7511_wr_and_or(sd, 0x18, 0x9f, (mode & 0x3)<<5);
319b2ce5617SAnders Roxell }
320b2ce5617SAnders Roxell 
321b2ce5617SAnders Roxell static void adv7511_csc_coeff(struct v4l2_subdev *sd,
322b2ce5617SAnders Roxell 			      u16 A1, u16 A2, u16 A3, u16 A4,
323b2ce5617SAnders Roxell 			      u16 B1, u16 B2, u16 B3, u16 B4,
324b2ce5617SAnders Roxell 			      u16 C1, u16 C2, u16 C3, u16 C4)
325b2ce5617SAnders Roxell {
326b2ce5617SAnders Roxell 	/* A */
327b2ce5617SAnders Roxell 	adv7511_wr_and_or(sd, 0x18, 0xe0, A1>>8);
328b2ce5617SAnders Roxell 	adv7511_wr(sd, 0x19, A1);
329b2ce5617SAnders Roxell 	adv7511_wr_and_or(sd, 0x1A, 0xe0, A2>>8);
330b2ce5617SAnders Roxell 	adv7511_wr(sd, 0x1B, A2);
331b2ce5617SAnders Roxell 	adv7511_wr_and_or(sd, 0x1c, 0xe0, A3>>8);
332b2ce5617SAnders Roxell 	adv7511_wr(sd, 0x1d, A3);
333b2ce5617SAnders Roxell 	adv7511_wr_and_or(sd, 0x1e, 0xe0, A4>>8);
334b2ce5617SAnders Roxell 	adv7511_wr(sd, 0x1f, A4);
335b2ce5617SAnders Roxell 
336b2ce5617SAnders Roxell 	/* B */
337b2ce5617SAnders Roxell 	adv7511_wr_and_or(sd, 0x20, 0xe0, B1>>8);
338b2ce5617SAnders Roxell 	adv7511_wr(sd, 0x21, B1);
339b2ce5617SAnders Roxell 	adv7511_wr_and_or(sd, 0x22, 0xe0, B2>>8);
340b2ce5617SAnders Roxell 	adv7511_wr(sd, 0x23, B2);
341b2ce5617SAnders Roxell 	adv7511_wr_and_or(sd, 0x24, 0xe0, B3>>8);
342b2ce5617SAnders Roxell 	adv7511_wr(sd, 0x25, B3);
343b2ce5617SAnders Roxell 	adv7511_wr_and_or(sd, 0x26, 0xe0, B4>>8);
344b2ce5617SAnders Roxell 	adv7511_wr(sd, 0x27, B4);
345b2ce5617SAnders Roxell 
346b2ce5617SAnders Roxell 	/* C */
347b2ce5617SAnders Roxell 	adv7511_wr_and_or(sd, 0x28, 0xe0, C1>>8);
348b2ce5617SAnders Roxell 	adv7511_wr(sd, 0x29, C1);
349b2ce5617SAnders Roxell 	adv7511_wr_and_or(sd, 0x2A, 0xe0, C2>>8);
350b2ce5617SAnders Roxell 	adv7511_wr(sd, 0x2B, C2);
351b2ce5617SAnders Roxell 	adv7511_wr_and_or(sd, 0x2C, 0xe0, C3>>8);
352b2ce5617SAnders Roxell 	adv7511_wr(sd, 0x2D, C3);
353b2ce5617SAnders Roxell 	adv7511_wr_and_or(sd, 0x2E, 0xe0, C4>>8);
354b2ce5617SAnders Roxell 	adv7511_wr(sd, 0x2F, C4);
355b2ce5617SAnders Roxell }
356b2ce5617SAnders Roxell 
357b2ce5617SAnders Roxell static void adv7511_csc_rgb_full2limit(struct v4l2_subdev *sd, bool enable)
358b2ce5617SAnders Roxell {
359b2ce5617SAnders Roxell 	if (enable) {
360b2ce5617SAnders Roxell 		u8 csc_mode = 0;
361b2ce5617SAnders Roxell 		adv7511_csc_conversion_mode(sd, csc_mode);
362b2ce5617SAnders Roxell 		adv7511_csc_coeff(sd,
363b2ce5617SAnders Roxell 				  4096-564, 0, 0, 256,
364b2ce5617SAnders Roxell 				  0, 4096-564, 0, 256,
365b2ce5617SAnders Roxell 				  0, 0, 4096-564, 256);
366b2ce5617SAnders Roxell 		/* enable CSC */
367b2ce5617SAnders Roxell 		adv7511_wr_and_or(sd, 0x18, 0x7f, 0x80);
368b2ce5617SAnders Roxell 		/* AVI infoframe: Limited range RGB (16-235) */
369b2ce5617SAnders Roxell 		adv7511_wr_and_or(sd, 0x57, 0xf3, 0x04);
370b2ce5617SAnders Roxell 	} else {
371b2ce5617SAnders Roxell 		/* disable CSC */
372b2ce5617SAnders Roxell 		adv7511_wr_and_or(sd, 0x18, 0x7f, 0x0);
373b2ce5617SAnders Roxell 		/* AVI infoframe: Full range RGB (0-255) */
374b2ce5617SAnders Roxell 		adv7511_wr_and_or(sd, 0x57, 0xf3, 0x08);
375b2ce5617SAnders Roxell 	}
376b2ce5617SAnders Roxell }
377b2ce5617SAnders Roxell 
378b2ce5617SAnders Roxell static void adv7511_set_rgb_quantization_mode(struct v4l2_subdev *sd, struct v4l2_ctrl *ctrl)
379b2ce5617SAnders Roxell {
380b2ce5617SAnders Roxell 	struct adv7511_state *state = get_adv7511_state(sd);
381b2ce5617SAnders Roxell 
382b2ce5617SAnders Roxell 	/* Only makes sense for RGB formats */
383b2ce5617SAnders Roxell 	if (state->fmt_code != MEDIA_BUS_FMT_RGB888_1X24) {
384b2ce5617SAnders Roxell 		/* so just keep quantization */
385b2ce5617SAnders Roxell 		adv7511_csc_rgb_full2limit(sd, false);
386b2ce5617SAnders Roxell 		return;
387b2ce5617SAnders Roxell 	}
388b2ce5617SAnders Roxell 
389b2ce5617SAnders Roxell 	switch (ctrl->val) {
390b2ce5617SAnders Roxell 	case V4L2_DV_RGB_RANGE_AUTO:
391b2ce5617SAnders Roxell 		/* automatic */
392b2ce5617SAnders Roxell 		if (state->dv_timings.bt.flags & V4L2_DV_FL_IS_CE_VIDEO) {
393b2ce5617SAnders Roxell 			/* CE format, RGB limited range (16-235) */
394b2ce5617SAnders Roxell 			adv7511_csc_rgb_full2limit(sd, true);
395b2ce5617SAnders Roxell 		} else {
396b2ce5617SAnders Roxell 			/* not CE format, RGB full range (0-255) */
397b2ce5617SAnders Roxell 			adv7511_csc_rgb_full2limit(sd, false);
398b2ce5617SAnders Roxell 		}
399b2ce5617SAnders Roxell 		break;
400b2ce5617SAnders Roxell 	case V4L2_DV_RGB_RANGE_LIMITED:
401b2ce5617SAnders Roxell 		/* RGB limited range (16-235) */
402b2ce5617SAnders Roxell 		adv7511_csc_rgb_full2limit(sd, true);
403b2ce5617SAnders Roxell 		break;
404b2ce5617SAnders Roxell 	case V4L2_DV_RGB_RANGE_FULL:
405b2ce5617SAnders Roxell 		/* RGB full range (0-255) */
406b2ce5617SAnders Roxell 		adv7511_csc_rgb_full2limit(sd, false);
407b2ce5617SAnders Roxell 		break;
408b2ce5617SAnders Roxell 	}
409b2ce5617SAnders Roxell }
410b2ce5617SAnders Roxell 
411b2ce5617SAnders Roxell /* ------------------------------ CTRL OPS ------------------------------ */
412b2ce5617SAnders Roxell 
413b2ce5617SAnders Roxell static int adv7511_s_ctrl(struct v4l2_ctrl *ctrl)
414b2ce5617SAnders Roxell {
415b2ce5617SAnders Roxell 	struct v4l2_subdev *sd = to_sd(ctrl);
416b2ce5617SAnders Roxell 	struct adv7511_state *state = get_adv7511_state(sd);
417b2ce5617SAnders Roxell 
418b2ce5617SAnders Roxell 	v4l2_dbg(1, debug, sd, "%s: ctrl id: %d, ctrl->val %d\n", __func__, ctrl->id, ctrl->val);
419b2ce5617SAnders Roxell 
420b2ce5617SAnders Roxell 	if (state->hdmi_mode_ctrl == ctrl) {
421b2ce5617SAnders Roxell 		/* Set HDMI or DVI-D */
422b2ce5617SAnders Roxell 		adv7511_wr_and_or(sd, 0xaf, 0xfd, ctrl->val == V4L2_DV_TX_MODE_HDMI ? 0x02 : 0x00);
423b2ce5617SAnders Roxell 		return 0;
424b2ce5617SAnders Roxell 	}
425b2ce5617SAnders Roxell 	if (state->rgb_quantization_range_ctrl == ctrl) {
426b2ce5617SAnders Roxell 		adv7511_set_rgb_quantization_mode(sd, ctrl);
427b2ce5617SAnders Roxell 		return 0;
428b2ce5617SAnders Roxell 	}
429b2ce5617SAnders Roxell 	if (state->content_type_ctrl == ctrl) {
430b2ce5617SAnders Roxell 		u8 itc, cn;
431b2ce5617SAnders Roxell 
432b2ce5617SAnders Roxell 		state->content_type = ctrl->val;
433b2ce5617SAnders Roxell 		itc = state->content_type != V4L2_DV_IT_CONTENT_TYPE_NO_ITC;
434b2ce5617SAnders Roxell 		cn = itc ? state->content_type : V4L2_DV_IT_CONTENT_TYPE_GRAPHICS;
435b2ce5617SAnders Roxell 		adv7511_wr_and_or(sd, 0x57, 0x7f, itc << 7);
436b2ce5617SAnders Roxell 		adv7511_wr_and_or(sd, 0x59, 0xcf, cn << 4);
437b2ce5617SAnders Roxell 		return 0;
438b2ce5617SAnders Roxell 	}
439b2ce5617SAnders Roxell 
440b2ce5617SAnders Roxell 	return -EINVAL;
441b2ce5617SAnders Roxell }
442b2ce5617SAnders Roxell 
443b2ce5617SAnders Roxell static const struct v4l2_ctrl_ops adv7511_ctrl_ops = {
444b2ce5617SAnders Roxell 	.s_ctrl = adv7511_s_ctrl,
445b2ce5617SAnders Roxell };
446b2ce5617SAnders Roxell 
447b2ce5617SAnders Roxell /* ---------------------------- CORE OPS ------------------------------------------- */
448b2ce5617SAnders Roxell 
449b2ce5617SAnders Roxell #ifdef CONFIG_VIDEO_ADV_DEBUG
450b2ce5617SAnders Roxell static void adv7511_inv_register(struct v4l2_subdev *sd)
451b2ce5617SAnders Roxell {
452b2ce5617SAnders Roxell 	struct adv7511_state *state = get_adv7511_state(sd);
453b2ce5617SAnders Roxell 
454b2ce5617SAnders Roxell 	v4l2_info(sd, "0x000-0x0ff: Main Map\n");
455b2ce5617SAnders Roxell 	if (state->i2c_cec)
456b2ce5617SAnders Roxell 		v4l2_info(sd, "0x100-0x1ff: CEC Map\n");
457b2ce5617SAnders Roxell }
458b2ce5617SAnders Roxell 
459b2ce5617SAnders Roxell static int adv7511_g_register(struct v4l2_subdev *sd, struct v4l2_dbg_register *reg)
460b2ce5617SAnders Roxell {
461b2ce5617SAnders Roxell 	struct adv7511_state *state = get_adv7511_state(sd);
462b2ce5617SAnders Roxell 
463b2ce5617SAnders Roxell 	reg->size = 1;
464b2ce5617SAnders Roxell 	switch (reg->reg >> 8) {
465b2ce5617SAnders Roxell 	case 0:
466b2ce5617SAnders Roxell 		reg->val = adv7511_rd(sd, reg->reg & 0xff);
467b2ce5617SAnders Roxell 		break;
468b2ce5617SAnders Roxell 	case 1:
469b2ce5617SAnders Roxell 		if (state->i2c_cec) {
470b2ce5617SAnders Roxell 			reg->val = adv7511_cec_read(sd, reg->reg & 0xff);
471b2ce5617SAnders Roxell 			break;
472b2ce5617SAnders Roxell 		}
473*1771e9fbSGustavo A. R. Silva 		fallthrough;
474b2ce5617SAnders Roxell 	default:
475b2ce5617SAnders Roxell 		v4l2_info(sd, "Register %03llx not supported\n", reg->reg);
476b2ce5617SAnders Roxell 		adv7511_inv_register(sd);
477b2ce5617SAnders Roxell 		break;
478b2ce5617SAnders Roxell 	}
479b2ce5617SAnders Roxell 	return 0;
480b2ce5617SAnders Roxell }
481b2ce5617SAnders Roxell 
482b2ce5617SAnders Roxell static int adv7511_s_register(struct v4l2_subdev *sd, const struct v4l2_dbg_register *reg)
483b2ce5617SAnders Roxell {
484b2ce5617SAnders Roxell 	struct adv7511_state *state = get_adv7511_state(sd);
485b2ce5617SAnders Roxell 
486b2ce5617SAnders Roxell 	switch (reg->reg >> 8) {
487b2ce5617SAnders Roxell 	case 0:
488b2ce5617SAnders Roxell 		adv7511_wr(sd, reg->reg & 0xff, reg->val & 0xff);
489b2ce5617SAnders Roxell 		break;
490b2ce5617SAnders Roxell 	case 1:
491b2ce5617SAnders Roxell 		if (state->i2c_cec) {
492b2ce5617SAnders Roxell 			adv7511_cec_write(sd, reg->reg & 0xff, reg->val & 0xff);
493b2ce5617SAnders Roxell 			break;
494b2ce5617SAnders Roxell 		}
495*1771e9fbSGustavo A. R. Silva 		fallthrough;
496b2ce5617SAnders Roxell 	default:
497b2ce5617SAnders Roxell 		v4l2_info(sd, "Register %03llx not supported\n", reg->reg);
498b2ce5617SAnders Roxell 		adv7511_inv_register(sd);
499b2ce5617SAnders Roxell 		break;
500b2ce5617SAnders Roxell 	}
501b2ce5617SAnders Roxell 	return 0;
502b2ce5617SAnders Roxell }
503b2ce5617SAnders Roxell #endif
504b2ce5617SAnders Roxell 
505b2ce5617SAnders Roxell struct adv7511_cfg_read_infoframe {
506b2ce5617SAnders Roxell 	const char *desc;
507b2ce5617SAnders Roxell 	u8 present_reg;
508b2ce5617SAnders Roxell 	u8 present_mask;
509b2ce5617SAnders Roxell 	u8 header[3];
510b2ce5617SAnders Roxell 	u16 payload_addr;
511b2ce5617SAnders Roxell };
512b2ce5617SAnders Roxell 
513b2ce5617SAnders Roxell static u8 hdmi_infoframe_checksum(u8 *ptr, size_t size)
514b2ce5617SAnders Roxell {
515b2ce5617SAnders Roxell 	u8 csum = 0;
516b2ce5617SAnders Roxell 	size_t i;
517b2ce5617SAnders Roxell 
518b2ce5617SAnders Roxell 	/* compute checksum */
519b2ce5617SAnders Roxell 	for (i = 0; i < size; i++)
520b2ce5617SAnders Roxell 		csum += ptr[i];
521b2ce5617SAnders Roxell 
522b2ce5617SAnders Roxell 	return 256 - csum;
523b2ce5617SAnders Roxell }
524b2ce5617SAnders Roxell 
525b2ce5617SAnders Roxell static void log_infoframe(struct v4l2_subdev *sd, const struct adv7511_cfg_read_infoframe *cri)
526b2ce5617SAnders Roxell {
527b2ce5617SAnders Roxell 	struct i2c_client *client = v4l2_get_subdevdata(sd);
528b2ce5617SAnders Roxell 	struct device *dev = &client->dev;
529b2ce5617SAnders Roxell 	union hdmi_infoframe frame;
530b2ce5617SAnders Roxell 	u8 buffer[32];
531b2ce5617SAnders Roxell 	u8 len;
532b2ce5617SAnders Roxell 	int i;
533b2ce5617SAnders Roxell 
534b2ce5617SAnders Roxell 	if (!(adv7511_rd(sd, cri->present_reg) & cri->present_mask)) {
535b2ce5617SAnders Roxell 		v4l2_info(sd, "%s infoframe not transmitted\n", cri->desc);
536b2ce5617SAnders Roxell 		return;
537b2ce5617SAnders Roxell 	}
538b2ce5617SAnders Roxell 
539b2ce5617SAnders Roxell 	memcpy(buffer, cri->header, sizeof(cri->header));
540b2ce5617SAnders Roxell 
541b2ce5617SAnders Roxell 	len = buffer[2];
542b2ce5617SAnders Roxell 
543b2ce5617SAnders Roxell 	if (len + 4 > sizeof(buffer)) {
544b2ce5617SAnders Roxell 		v4l2_err(sd, "%s: invalid %s infoframe length %d\n", __func__, cri->desc, len);
545b2ce5617SAnders Roxell 		return;
546b2ce5617SAnders Roxell 	}
547b2ce5617SAnders Roxell 
548b2ce5617SAnders Roxell 	if (cri->payload_addr >= 0x100) {
549b2ce5617SAnders Roxell 		for (i = 0; i < len; i++)
550b2ce5617SAnders Roxell 			buffer[i + 4] = adv7511_pktmem_rd(sd, cri->payload_addr + i - 0x100);
551b2ce5617SAnders Roxell 	} else {
552b2ce5617SAnders Roxell 		for (i = 0; i < len; i++)
553b2ce5617SAnders Roxell 			buffer[i + 4] = adv7511_rd(sd, cri->payload_addr + i);
554b2ce5617SAnders Roxell 	}
555b2ce5617SAnders Roxell 	buffer[3] = 0;
556b2ce5617SAnders Roxell 	buffer[3] = hdmi_infoframe_checksum(buffer, len + 4);
557b2ce5617SAnders Roxell 
558b2ce5617SAnders Roxell 	if (hdmi_infoframe_unpack(&frame, buffer, sizeof(buffer)) < 0) {
559b2ce5617SAnders Roxell 		v4l2_err(sd, "%s: unpack of %s infoframe failed\n", __func__, cri->desc);
560b2ce5617SAnders Roxell 		return;
561b2ce5617SAnders Roxell 	}
562b2ce5617SAnders Roxell 
563b2ce5617SAnders Roxell 	hdmi_infoframe_log(KERN_INFO, dev, &frame);
564b2ce5617SAnders Roxell }
565b2ce5617SAnders Roxell 
566b2ce5617SAnders Roxell static void adv7511_log_infoframes(struct v4l2_subdev *sd)
567b2ce5617SAnders Roxell {
568b2ce5617SAnders Roxell 	static const struct adv7511_cfg_read_infoframe cri[] = {
569b2ce5617SAnders Roxell 		{ "AVI", 0x44, 0x10, { 0x82, 2, 13 }, 0x55 },
570b2ce5617SAnders Roxell 		{ "Audio", 0x44, 0x08, { 0x84, 1, 10 }, 0x73 },
571b2ce5617SAnders Roxell 		{ "SDP", 0x40, 0x40, { 0x83, 1, 25 }, 0x103 },
572b2ce5617SAnders Roxell 	};
573b2ce5617SAnders Roxell 	int i;
574b2ce5617SAnders Roxell 
575b2ce5617SAnders Roxell 	for (i = 0; i < ARRAY_SIZE(cri); i++)
576b2ce5617SAnders Roxell 		log_infoframe(sd, &cri[i]);
577b2ce5617SAnders Roxell }
578b2ce5617SAnders Roxell 
579b2ce5617SAnders Roxell static int adv7511_log_status(struct v4l2_subdev *sd)
580b2ce5617SAnders Roxell {
581b2ce5617SAnders Roxell 	struct adv7511_state *state = get_adv7511_state(sd);
582b2ce5617SAnders Roxell 	struct adv7511_state_edid *edid = &state->edid;
583b2ce5617SAnders Roxell 	int i;
584b2ce5617SAnders Roxell 
585b2ce5617SAnders Roxell 	static const char * const states[] = {
586b2ce5617SAnders Roxell 		"in reset",
587b2ce5617SAnders Roxell 		"reading EDID",
588b2ce5617SAnders Roxell 		"idle",
589b2ce5617SAnders Roxell 		"initializing HDCP",
590b2ce5617SAnders Roxell 		"HDCP enabled",
591b2ce5617SAnders Roxell 		"initializing HDCP repeater",
592b2ce5617SAnders Roxell 		"6", "7", "8", "9", "A", "B", "C", "D", "E", "F"
593b2ce5617SAnders Roxell 	};
594b2ce5617SAnders Roxell 	static const char * const errors[] = {
595b2ce5617SAnders Roxell 		"no error",
596b2ce5617SAnders Roxell 		"bad receiver BKSV",
597b2ce5617SAnders Roxell 		"Ri mismatch",
598b2ce5617SAnders Roxell 		"Pj mismatch",
599b2ce5617SAnders Roxell 		"i2c error",
600b2ce5617SAnders Roxell 		"timed out",
601b2ce5617SAnders Roxell 		"max repeater cascade exceeded",
602b2ce5617SAnders Roxell 		"hash check failed",
603b2ce5617SAnders Roxell 		"too many devices",
604b2ce5617SAnders Roxell 		"9", "A", "B", "C", "D", "E", "F"
605b2ce5617SAnders Roxell 	};
606b2ce5617SAnders Roxell 
607b2ce5617SAnders Roxell 	v4l2_info(sd, "power %s\n", state->power_on ? "on" : "off");
608b2ce5617SAnders Roxell 	v4l2_info(sd, "%s hotplug, %s Rx Sense, %s EDID (%d block(s))\n",
609b2ce5617SAnders Roxell 		  (adv7511_rd(sd, 0x42) & MASK_ADV7511_HPD_DETECT) ? "detected" : "no",
610b2ce5617SAnders Roxell 		  (adv7511_rd(sd, 0x42) & MASK_ADV7511_MSEN_DETECT) ? "detected" : "no",
611b2ce5617SAnders Roxell 		  edid->segments ? "found" : "no",
612b2ce5617SAnders Roxell 		  edid->blocks);
613b2ce5617SAnders Roxell 	v4l2_info(sd, "%s output %s\n",
614b2ce5617SAnders Roxell 		  (adv7511_rd(sd, 0xaf) & 0x02) ?
615b2ce5617SAnders Roxell 		  "HDMI" : "DVI-D",
616b2ce5617SAnders Roxell 		  (adv7511_rd(sd, 0xa1) & 0x3c) ?
617b2ce5617SAnders Roxell 		  "disabled" : "enabled");
618b2ce5617SAnders Roxell 	v4l2_info(sd, "state: %s, error: %s, detect count: %u, msk/irq: %02x/%02x\n",
619b2ce5617SAnders Roxell 			  states[adv7511_rd(sd, 0xc8) & 0xf],
620b2ce5617SAnders Roxell 			  errors[adv7511_rd(sd, 0xc8) >> 4], state->edid_detect_counter,
621b2ce5617SAnders Roxell 			  adv7511_rd(sd, 0x94), adv7511_rd(sd, 0x96));
622b2ce5617SAnders Roxell 	v4l2_info(sd, "RGB quantization: %s range\n", adv7511_rd(sd, 0x18) & 0x80 ? "limited" : "full");
623b2ce5617SAnders Roxell 	if (adv7511_rd(sd, 0xaf) & 0x02) {
624b2ce5617SAnders Roxell 		/* HDMI only */
625b2ce5617SAnders Roxell 		u8 manual_cts = adv7511_rd(sd, 0x0a) & 0x80;
626b2ce5617SAnders Roxell 		u32 N = (adv7511_rd(sd, 0x01) & 0xf) << 16 |
627b2ce5617SAnders Roxell 			adv7511_rd(sd, 0x02) << 8 |
628b2ce5617SAnders Roxell 			adv7511_rd(sd, 0x03);
629b2ce5617SAnders Roxell 		u8 vic_detect = adv7511_rd(sd, 0x3e) >> 2;
630b2ce5617SAnders Roxell 		u8 vic_sent = adv7511_rd(sd, 0x3d) & 0x3f;
631b2ce5617SAnders Roxell 		u32 CTS;
632b2ce5617SAnders Roxell 
633b2ce5617SAnders Roxell 		if (manual_cts)
634b2ce5617SAnders Roxell 			CTS = (adv7511_rd(sd, 0x07) & 0xf) << 16 |
635b2ce5617SAnders Roxell 			      adv7511_rd(sd, 0x08) << 8 |
636b2ce5617SAnders Roxell 			      adv7511_rd(sd, 0x09);
637b2ce5617SAnders Roxell 		else
638b2ce5617SAnders Roxell 			CTS = (adv7511_rd(sd, 0x04) & 0xf) << 16 |
639b2ce5617SAnders Roxell 			      adv7511_rd(sd, 0x05) << 8 |
640b2ce5617SAnders Roxell 			      adv7511_rd(sd, 0x06);
641b2ce5617SAnders Roxell 		v4l2_info(sd, "CTS %s mode: N %d, CTS %d\n",
642b2ce5617SAnders Roxell 			  manual_cts ? "manual" : "automatic", N, CTS);
643b2ce5617SAnders Roxell 		v4l2_info(sd, "VIC: detected %d, sent %d\n",
644b2ce5617SAnders Roxell 			  vic_detect, vic_sent);
645b2ce5617SAnders Roxell 		adv7511_log_infoframes(sd);
646b2ce5617SAnders Roxell 	}
647b2ce5617SAnders Roxell 	if (state->dv_timings.type == V4L2_DV_BT_656_1120)
648b2ce5617SAnders Roxell 		v4l2_print_dv_timings(sd->name, "timings: ",
649b2ce5617SAnders Roxell 				&state->dv_timings, false);
650b2ce5617SAnders Roxell 	else
651b2ce5617SAnders Roxell 		v4l2_info(sd, "no timings set\n");
652b2ce5617SAnders Roxell 	v4l2_info(sd, "i2c edid addr: 0x%x\n", state->i2c_edid_addr);
653b2ce5617SAnders Roxell 
654b2ce5617SAnders Roxell 	if (state->i2c_cec == NULL)
655b2ce5617SAnders Roxell 		return 0;
656b2ce5617SAnders Roxell 
657b2ce5617SAnders Roxell 	v4l2_info(sd, "i2c cec addr: 0x%x\n", state->i2c_cec_addr);
658b2ce5617SAnders Roxell 
659b2ce5617SAnders Roxell 	v4l2_info(sd, "CEC: %s\n", state->cec_enabled_adap ?
660b2ce5617SAnders Roxell 			"enabled" : "disabled");
661b2ce5617SAnders Roxell 	if (state->cec_enabled_adap) {
662b2ce5617SAnders Roxell 		for (i = 0; i < ADV7511_MAX_ADDRS; i++) {
663b2ce5617SAnders Roxell 			bool is_valid = state->cec_valid_addrs & (1 << i);
664b2ce5617SAnders Roxell 
665b2ce5617SAnders Roxell 			if (is_valid)
666b2ce5617SAnders Roxell 				v4l2_info(sd, "CEC Logical Address: 0x%x\n",
667b2ce5617SAnders Roxell 					  state->cec_addr[i]);
668b2ce5617SAnders Roxell 		}
669b2ce5617SAnders Roxell 	}
670b2ce5617SAnders Roxell 	v4l2_info(sd, "i2c pktmem addr: 0x%x\n", state->i2c_pktmem_addr);
671b2ce5617SAnders Roxell 	return 0;
672b2ce5617SAnders Roxell }
673b2ce5617SAnders Roxell 
674b2ce5617SAnders Roxell /* Power up/down adv7511 */
675b2ce5617SAnders Roxell static int adv7511_s_power(struct v4l2_subdev *sd, int on)
676b2ce5617SAnders Roxell {
677b2ce5617SAnders Roxell 	struct adv7511_state *state = get_adv7511_state(sd);
678b2ce5617SAnders Roxell 	const int retries = 20;
679b2ce5617SAnders Roxell 	int i;
680b2ce5617SAnders Roxell 
681b2ce5617SAnders Roxell 	v4l2_dbg(1, debug, sd, "%s: power %s\n", __func__, on ? "on" : "off");
682b2ce5617SAnders Roxell 
683b2ce5617SAnders Roxell 	state->power_on = on;
684b2ce5617SAnders Roxell 
685b2ce5617SAnders Roxell 	if (!on) {
686b2ce5617SAnders Roxell 		/* Power down */
687b2ce5617SAnders Roxell 		adv7511_wr_and_or(sd, 0x41, 0xbf, 0x40);
688b2ce5617SAnders Roxell 		return true;
689b2ce5617SAnders Roxell 	}
690b2ce5617SAnders Roxell 
691b2ce5617SAnders Roxell 	/* Power up */
692b2ce5617SAnders Roxell 	/* The adv7511 does not always come up immediately.
693b2ce5617SAnders Roxell 	   Retry multiple times. */
694b2ce5617SAnders Roxell 	for (i = 0; i < retries; i++) {
695b2ce5617SAnders Roxell 		adv7511_wr_and_or(sd, 0x41, 0xbf, 0x0);
696b2ce5617SAnders Roxell 		if ((adv7511_rd(sd, 0x41) & 0x40) == 0)
697b2ce5617SAnders Roxell 			break;
698b2ce5617SAnders Roxell 		adv7511_wr_and_or(sd, 0x41, 0xbf, 0x40);
699b2ce5617SAnders Roxell 		msleep(10);
700b2ce5617SAnders Roxell 	}
701b2ce5617SAnders Roxell 	if (i == retries) {
702b2ce5617SAnders Roxell 		v4l2_dbg(1, debug, sd, "%s: failed to powerup the adv7511!\n", __func__);
703b2ce5617SAnders Roxell 		adv7511_s_power(sd, 0);
704b2ce5617SAnders Roxell 		return false;
705b2ce5617SAnders Roxell 	}
706b2ce5617SAnders Roxell 	if (i > 1)
707b2ce5617SAnders Roxell 		v4l2_dbg(1, debug, sd, "%s: needed %d retries to powerup the adv7511\n", __func__, i);
708b2ce5617SAnders Roxell 
709b2ce5617SAnders Roxell 	/* Reserved registers that must be set */
710b2ce5617SAnders Roxell 	adv7511_wr(sd, 0x98, 0x03);
711b2ce5617SAnders Roxell 	adv7511_wr_and_or(sd, 0x9a, 0xfe, 0x70);
712b2ce5617SAnders Roxell 	adv7511_wr(sd, 0x9c, 0x30);
713b2ce5617SAnders Roxell 	adv7511_wr_and_or(sd, 0x9d, 0xfc, 0x01);
714b2ce5617SAnders Roxell 	adv7511_wr(sd, 0xa2, 0xa4);
715b2ce5617SAnders Roxell 	adv7511_wr(sd, 0xa3, 0xa4);
716b2ce5617SAnders Roxell 	adv7511_wr(sd, 0xe0, 0xd0);
717b2ce5617SAnders Roxell 	adv7511_wr(sd, 0xf9, 0x00);
718b2ce5617SAnders Roxell 
719b2ce5617SAnders Roxell 	adv7511_wr(sd, 0x43, state->i2c_edid_addr);
720b2ce5617SAnders Roxell 	adv7511_wr(sd, 0x45, state->i2c_pktmem_addr);
721b2ce5617SAnders Roxell 
722b2ce5617SAnders Roxell 	/* Set number of attempts to read the EDID */
723b2ce5617SAnders Roxell 	adv7511_wr(sd, 0xc9, 0xf);
724b2ce5617SAnders Roxell 	return true;
725b2ce5617SAnders Roxell }
726b2ce5617SAnders Roxell 
727b2ce5617SAnders Roxell #if IS_ENABLED(CONFIG_VIDEO_ADV7511_CEC)
728b2ce5617SAnders Roxell static int adv7511_cec_adap_enable(struct cec_adapter *adap, bool enable)
729b2ce5617SAnders Roxell {
730b2ce5617SAnders Roxell 	struct adv7511_state *state = cec_get_drvdata(adap);
731b2ce5617SAnders Roxell 	struct v4l2_subdev *sd = &state->sd;
732b2ce5617SAnders Roxell 
733b2ce5617SAnders Roxell 	if (state->i2c_cec == NULL)
734b2ce5617SAnders Roxell 		return -EIO;
735b2ce5617SAnders Roxell 
736b2ce5617SAnders Roxell 	if (!state->cec_enabled_adap && enable) {
737b2ce5617SAnders Roxell 		/* power up cec section */
738b2ce5617SAnders Roxell 		adv7511_cec_write_and_or(sd, 0x4e, 0xfc, 0x01);
739b2ce5617SAnders Roxell 		/* legacy mode and clear all rx buffers */
740b2ce5617SAnders Roxell 		adv7511_cec_write(sd, 0x4a, 0x00);
741b2ce5617SAnders Roxell 		adv7511_cec_write(sd, 0x4a, 0x07);
742b2ce5617SAnders Roxell 		adv7511_cec_write_and_or(sd, 0x11, 0xfe, 0); /* initially disable tx */
743b2ce5617SAnders Roxell 		/* enabled irqs: */
744b2ce5617SAnders Roxell 		/* tx: ready */
745b2ce5617SAnders Roxell 		/* tx: arbitration lost */
746b2ce5617SAnders Roxell 		/* tx: retry timeout */
747b2ce5617SAnders Roxell 		/* rx: ready 1 */
748b2ce5617SAnders Roxell 		if (state->enabled_irq)
749b2ce5617SAnders Roxell 			adv7511_wr_and_or(sd, 0x95, 0xc0, 0x39);
750b2ce5617SAnders Roxell 	} else if (state->cec_enabled_adap && !enable) {
751b2ce5617SAnders Roxell 		if (state->enabled_irq)
752b2ce5617SAnders Roxell 			adv7511_wr_and_or(sd, 0x95, 0xc0, 0x00);
753b2ce5617SAnders Roxell 		/* disable address mask 1-3 */
754b2ce5617SAnders Roxell 		adv7511_cec_write_and_or(sd, 0x4b, 0x8f, 0x00);
755b2ce5617SAnders Roxell 		/* power down cec section */
756b2ce5617SAnders Roxell 		adv7511_cec_write_and_or(sd, 0x4e, 0xfc, 0x00);
757b2ce5617SAnders Roxell 		state->cec_valid_addrs = 0;
758b2ce5617SAnders Roxell 	}
759b2ce5617SAnders Roxell 	state->cec_enabled_adap = enable;
760b2ce5617SAnders Roxell 	return 0;
761b2ce5617SAnders Roxell }
762b2ce5617SAnders Roxell 
763b2ce5617SAnders Roxell static int adv7511_cec_adap_log_addr(struct cec_adapter *adap, u8 addr)
764b2ce5617SAnders Roxell {
765b2ce5617SAnders Roxell 	struct adv7511_state *state = cec_get_drvdata(adap);
766b2ce5617SAnders Roxell 	struct v4l2_subdev *sd = &state->sd;
767b2ce5617SAnders Roxell 	unsigned int i, free_idx = ADV7511_MAX_ADDRS;
768b2ce5617SAnders Roxell 
769b2ce5617SAnders Roxell 	if (!state->cec_enabled_adap)
770b2ce5617SAnders Roxell 		return addr == CEC_LOG_ADDR_INVALID ? 0 : -EIO;
771b2ce5617SAnders Roxell 
772b2ce5617SAnders Roxell 	if (addr == CEC_LOG_ADDR_INVALID) {
773b2ce5617SAnders Roxell 		adv7511_cec_write_and_or(sd, 0x4b, 0x8f, 0);
774b2ce5617SAnders Roxell 		state->cec_valid_addrs = 0;
775b2ce5617SAnders Roxell 		return 0;
776b2ce5617SAnders Roxell 	}
777b2ce5617SAnders Roxell 
778b2ce5617SAnders Roxell 	for (i = 0; i < ADV7511_MAX_ADDRS; i++) {
779b2ce5617SAnders Roxell 		bool is_valid = state->cec_valid_addrs & (1 << i);
780b2ce5617SAnders Roxell 
781b2ce5617SAnders Roxell 		if (free_idx == ADV7511_MAX_ADDRS && !is_valid)
782b2ce5617SAnders Roxell 			free_idx = i;
783b2ce5617SAnders Roxell 		if (is_valid && state->cec_addr[i] == addr)
784b2ce5617SAnders Roxell 			return 0;
785b2ce5617SAnders Roxell 	}
786b2ce5617SAnders Roxell 	if (i == ADV7511_MAX_ADDRS) {
787b2ce5617SAnders Roxell 		i = free_idx;
788b2ce5617SAnders Roxell 		if (i == ADV7511_MAX_ADDRS)
789b2ce5617SAnders Roxell 			return -ENXIO;
790b2ce5617SAnders Roxell 	}
791b2ce5617SAnders Roxell 	state->cec_addr[i] = addr;
792b2ce5617SAnders Roxell 	state->cec_valid_addrs |= 1 << i;
793b2ce5617SAnders Roxell 
794b2ce5617SAnders Roxell 	switch (i) {
795b2ce5617SAnders Roxell 	case 0:
796b2ce5617SAnders Roxell 		/* enable address mask 0 */
797b2ce5617SAnders Roxell 		adv7511_cec_write_and_or(sd, 0x4b, 0xef, 0x10);
798b2ce5617SAnders Roxell 		/* set address for mask 0 */
799b2ce5617SAnders Roxell 		adv7511_cec_write_and_or(sd, 0x4c, 0xf0, addr);
800b2ce5617SAnders Roxell 		break;
801b2ce5617SAnders Roxell 	case 1:
802b2ce5617SAnders Roxell 		/* enable address mask 1 */
803b2ce5617SAnders Roxell 		adv7511_cec_write_and_or(sd, 0x4b, 0xdf, 0x20);
804b2ce5617SAnders Roxell 		/* set address for mask 1 */
805b2ce5617SAnders Roxell 		adv7511_cec_write_and_or(sd, 0x4c, 0x0f, addr << 4);
806b2ce5617SAnders Roxell 		break;
807b2ce5617SAnders Roxell 	case 2:
808b2ce5617SAnders Roxell 		/* enable address mask 2 */
809b2ce5617SAnders Roxell 		adv7511_cec_write_and_or(sd, 0x4b, 0xbf, 0x40);
810b2ce5617SAnders Roxell 		/* set address for mask 1 */
811b2ce5617SAnders Roxell 		adv7511_cec_write_and_or(sd, 0x4d, 0xf0, addr);
812b2ce5617SAnders Roxell 		break;
813b2ce5617SAnders Roxell 	}
814b2ce5617SAnders Roxell 	return 0;
815b2ce5617SAnders Roxell }
816b2ce5617SAnders Roxell 
817b2ce5617SAnders Roxell static int adv7511_cec_adap_transmit(struct cec_adapter *adap, u8 attempts,
818b2ce5617SAnders Roxell 				     u32 signal_free_time, struct cec_msg *msg)
819b2ce5617SAnders Roxell {
820b2ce5617SAnders Roxell 	struct adv7511_state *state = cec_get_drvdata(adap);
821b2ce5617SAnders Roxell 	struct v4l2_subdev *sd = &state->sd;
822b2ce5617SAnders Roxell 	u8 len = msg->len;
823b2ce5617SAnders Roxell 	unsigned int i;
824b2ce5617SAnders Roxell 
825b2ce5617SAnders Roxell 	v4l2_dbg(1, debug, sd, "%s: len %d\n", __func__, len);
826b2ce5617SAnders Roxell 
827b2ce5617SAnders Roxell 	if (len > 16) {
828b2ce5617SAnders Roxell 		v4l2_err(sd, "%s: len exceeded 16 (%d)\n", __func__, len);
829b2ce5617SAnders Roxell 		return -EINVAL;
830b2ce5617SAnders Roxell 	}
831b2ce5617SAnders Roxell 
832b2ce5617SAnders Roxell 	/*
833b2ce5617SAnders Roxell 	 * The number of retries is the number of attempts - 1, but retry
834b2ce5617SAnders Roxell 	 * at least once. It's not clear if a value of 0 is allowed, so
835b2ce5617SAnders Roxell 	 * let's do at least one retry.
836b2ce5617SAnders Roxell 	 */
837b2ce5617SAnders Roxell 	adv7511_cec_write_and_or(sd, 0x12, ~0x70, max(1, attempts - 1) << 4);
838b2ce5617SAnders Roxell 
839b2ce5617SAnders Roxell 	/* clear cec tx irq status */
840b2ce5617SAnders Roxell 	adv7511_wr(sd, 0x97, 0x38);
841b2ce5617SAnders Roxell 
842b2ce5617SAnders Roxell 	/* write data */
843b2ce5617SAnders Roxell 	for (i = 0; i < len; i++)
844b2ce5617SAnders Roxell 		adv7511_cec_write(sd, i, msg->msg[i]);
845b2ce5617SAnders Roxell 
846b2ce5617SAnders Roxell 	/* set length (data + header) */
847b2ce5617SAnders Roxell 	adv7511_cec_write(sd, 0x10, len);
848b2ce5617SAnders Roxell 	/* start transmit, enable tx */
849b2ce5617SAnders Roxell 	adv7511_cec_write(sd, 0x11, 0x01);
850b2ce5617SAnders Roxell 	return 0;
851b2ce5617SAnders Roxell }
852b2ce5617SAnders Roxell 
853b2ce5617SAnders Roxell static void adv_cec_tx_raw_status(struct v4l2_subdev *sd, u8 tx_raw_status)
854b2ce5617SAnders Roxell {
855b2ce5617SAnders Roxell 	struct adv7511_state *state = get_adv7511_state(sd);
856b2ce5617SAnders Roxell 
857b2ce5617SAnders Roxell 	if ((adv7511_cec_read(sd, 0x11) & 0x01) == 0) {
858b2ce5617SAnders Roxell 		v4l2_dbg(1, debug, sd, "%s: tx raw: tx disabled\n", __func__);
859b2ce5617SAnders Roxell 		return;
860b2ce5617SAnders Roxell 	}
861b2ce5617SAnders Roxell 
862b2ce5617SAnders Roxell 	if (tx_raw_status & 0x10) {
863b2ce5617SAnders Roxell 		v4l2_dbg(1, debug, sd,
864b2ce5617SAnders Roxell 			 "%s: tx raw: arbitration lost\n", __func__);
865b2ce5617SAnders Roxell 		cec_transmit_done(state->cec_adap, CEC_TX_STATUS_ARB_LOST,
866b2ce5617SAnders Roxell 				  1, 0, 0, 0);
867b2ce5617SAnders Roxell 		return;
868b2ce5617SAnders Roxell 	}
869b2ce5617SAnders Roxell 	if (tx_raw_status & 0x08) {
870b2ce5617SAnders Roxell 		u8 status;
871b2ce5617SAnders Roxell 		u8 nack_cnt;
872b2ce5617SAnders Roxell 		u8 low_drive_cnt;
873b2ce5617SAnders Roxell 
874b2ce5617SAnders Roxell 		v4l2_dbg(1, debug, sd, "%s: tx raw: retry failed\n", __func__);
875b2ce5617SAnders Roxell 		/*
876b2ce5617SAnders Roxell 		 * We set this status bit since this hardware performs
877b2ce5617SAnders Roxell 		 * retransmissions.
878b2ce5617SAnders Roxell 		 */
879b2ce5617SAnders Roxell 		status = CEC_TX_STATUS_MAX_RETRIES;
880b2ce5617SAnders Roxell 		nack_cnt = adv7511_cec_read(sd, 0x14) & 0xf;
881b2ce5617SAnders Roxell 		if (nack_cnt)
882b2ce5617SAnders Roxell 			status |= CEC_TX_STATUS_NACK;
883b2ce5617SAnders Roxell 		low_drive_cnt = adv7511_cec_read(sd, 0x14) >> 4;
884b2ce5617SAnders Roxell 		if (low_drive_cnt)
885b2ce5617SAnders Roxell 			status |= CEC_TX_STATUS_LOW_DRIVE;
886b2ce5617SAnders Roxell 		cec_transmit_done(state->cec_adap, status,
887b2ce5617SAnders Roxell 				  0, nack_cnt, low_drive_cnt, 0);
888b2ce5617SAnders Roxell 		return;
889b2ce5617SAnders Roxell 	}
890b2ce5617SAnders Roxell 	if (tx_raw_status & 0x20) {
891b2ce5617SAnders Roxell 		v4l2_dbg(1, debug, sd, "%s: tx raw: ready ok\n", __func__);
892b2ce5617SAnders Roxell 		cec_transmit_done(state->cec_adap, CEC_TX_STATUS_OK, 0, 0, 0, 0);
893b2ce5617SAnders Roxell 		return;
894b2ce5617SAnders Roxell 	}
895b2ce5617SAnders Roxell }
896b2ce5617SAnders Roxell 
897b2ce5617SAnders Roxell static const struct cec_adap_ops adv7511_cec_adap_ops = {
898b2ce5617SAnders Roxell 	.adap_enable = adv7511_cec_adap_enable,
899b2ce5617SAnders Roxell 	.adap_log_addr = adv7511_cec_adap_log_addr,
900b2ce5617SAnders Roxell 	.adap_transmit = adv7511_cec_adap_transmit,
901b2ce5617SAnders Roxell };
902b2ce5617SAnders Roxell #endif
903b2ce5617SAnders Roxell 
904b2ce5617SAnders Roxell /* Enable interrupts */
905b2ce5617SAnders Roxell static void adv7511_set_isr(struct v4l2_subdev *sd, bool enable)
906b2ce5617SAnders Roxell {
907b2ce5617SAnders Roxell 	struct adv7511_state *state = get_adv7511_state(sd);
908b2ce5617SAnders Roxell 	u8 irqs = MASK_ADV7511_HPD_INT | MASK_ADV7511_MSEN_INT;
909b2ce5617SAnders Roxell 	u8 irqs_rd;
910b2ce5617SAnders Roxell 	int retries = 100;
911b2ce5617SAnders Roxell 
912b2ce5617SAnders Roxell 	v4l2_dbg(2, debug, sd, "%s: %s\n", __func__, enable ? "enable" : "disable");
913b2ce5617SAnders Roxell 
914b2ce5617SAnders Roxell 	if (state->enabled_irq == enable)
915b2ce5617SAnders Roxell 		return;
916b2ce5617SAnders Roxell 	state->enabled_irq = enable;
917b2ce5617SAnders Roxell 
918b2ce5617SAnders Roxell 	/* The datasheet says that the EDID ready interrupt should be
919b2ce5617SAnders Roxell 	   disabled if there is no hotplug. */
920b2ce5617SAnders Roxell 	if (!enable)
921b2ce5617SAnders Roxell 		irqs = 0;
922b2ce5617SAnders Roxell 	else if (adv7511_have_hotplug(sd))
923b2ce5617SAnders Roxell 		irqs |= MASK_ADV7511_EDID_RDY_INT;
924b2ce5617SAnders Roxell 
925b2ce5617SAnders Roxell 	/*
926b2ce5617SAnders Roxell 	 * This i2c write can fail (approx. 1 in 1000 writes). But it
927b2ce5617SAnders Roxell 	 * is essential that this register is correct, so retry it
928b2ce5617SAnders Roxell 	 * multiple times.
929b2ce5617SAnders Roxell 	 *
930b2ce5617SAnders Roxell 	 * Note that the i2c write does not report an error, but the readback
931b2ce5617SAnders Roxell 	 * clearly shows the wrong value.
932b2ce5617SAnders Roxell 	 */
933b2ce5617SAnders Roxell 	do {
934b2ce5617SAnders Roxell 		adv7511_wr(sd, 0x94, irqs);
935b2ce5617SAnders Roxell 		irqs_rd = adv7511_rd(sd, 0x94);
936b2ce5617SAnders Roxell 	} while (retries-- && irqs_rd != irqs);
937b2ce5617SAnders Roxell 
938b2ce5617SAnders Roxell 	if (irqs_rd != irqs)
939b2ce5617SAnders Roxell 		v4l2_err(sd, "Could not set interrupts: hw failure?\n");
940b2ce5617SAnders Roxell 
941b2ce5617SAnders Roxell 	adv7511_wr_and_or(sd, 0x95, 0xc0,
942b2ce5617SAnders Roxell 			  (state->cec_enabled_adap && enable) ? 0x39 : 0x00);
943b2ce5617SAnders Roxell }
944b2ce5617SAnders Roxell 
945b2ce5617SAnders Roxell /* Interrupt handler */
946b2ce5617SAnders Roxell static int adv7511_isr(struct v4l2_subdev *sd, u32 status, bool *handled)
947b2ce5617SAnders Roxell {
948b2ce5617SAnders Roxell 	u8 irq_status;
949b2ce5617SAnders Roxell 	u8 cec_irq;
950b2ce5617SAnders Roxell 
951b2ce5617SAnders Roxell 	/* disable interrupts to prevent a race condition */
952b2ce5617SAnders Roxell 	adv7511_set_isr(sd, false);
953b2ce5617SAnders Roxell 	irq_status = adv7511_rd(sd, 0x96);
954b2ce5617SAnders Roxell 	cec_irq = adv7511_rd(sd, 0x97);
955b2ce5617SAnders Roxell 	/* clear detected interrupts */
956b2ce5617SAnders Roxell 	adv7511_wr(sd, 0x96, irq_status);
957b2ce5617SAnders Roxell 	adv7511_wr(sd, 0x97, cec_irq);
958b2ce5617SAnders Roxell 
959b2ce5617SAnders Roxell 	v4l2_dbg(1, debug, sd, "%s: irq 0x%x, cec-irq 0x%x\n", __func__,
960b2ce5617SAnders Roxell 		 irq_status, cec_irq);
961b2ce5617SAnders Roxell 
962b2ce5617SAnders Roxell 	if (irq_status & (MASK_ADV7511_HPD_INT | MASK_ADV7511_MSEN_INT))
963b2ce5617SAnders Roxell 		adv7511_check_monitor_present_status(sd);
964b2ce5617SAnders Roxell 	if (irq_status & MASK_ADV7511_EDID_RDY_INT)
965b2ce5617SAnders Roxell 		adv7511_check_edid_status(sd);
966b2ce5617SAnders Roxell 
967b2ce5617SAnders Roxell #if IS_ENABLED(CONFIG_VIDEO_ADV7511_CEC)
968b2ce5617SAnders Roxell 	if (cec_irq & 0x38)
969b2ce5617SAnders Roxell 		adv_cec_tx_raw_status(sd, cec_irq);
970b2ce5617SAnders Roxell 
971b2ce5617SAnders Roxell 	if (cec_irq & 1) {
972b2ce5617SAnders Roxell 		struct adv7511_state *state = get_adv7511_state(sd);
973b2ce5617SAnders Roxell 		struct cec_msg msg;
974b2ce5617SAnders Roxell 
975b2ce5617SAnders Roxell 		msg.len = adv7511_cec_read(sd, 0x25) & 0x1f;
976b2ce5617SAnders Roxell 
977b2ce5617SAnders Roxell 		v4l2_dbg(1, debug, sd, "%s: cec msg len %d\n", __func__,
978b2ce5617SAnders Roxell 			 msg.len);
979b2ce5617SAnders Roxell 
980b2ce5617SAnders Roxell 		if (msg.len > 16)
981b2ce5617SAnders Roxell 			msg.len = 16;
982b2ce5617SAnders Roxell 
983b2ce5617SAnders Roxell 		if (msg.len) {
984b2ce5617SAnders Roxell 			u8 i;
985b2ce5617SAnders Roxell 
986b2ce5617SAnders Roxell 			for (i = 0; i < msg.len; i++)
987b2ce5617SAnders Roxell 				msg.msg[i] = adv7511_cec_read(sd, i + 0x15);
988b2ce5617SAnders Roxell 
989b2ce5617SAnders Roxell 			adv7511_cec_write(sd, 0x4a, 0); /* toggle to re-enable rx 1 */
990b2ce5617SAnders Roxell 			adv7511_cec_write(sd, 0x4a, 1);
991b2ce5617SAnders Roxell 			cec_received_msg(state->cec_adap, &msg);
992b2ce5617SAnders Roxell 		}
993b2ce5617SAnders Roxell 	}
994b2ce5617SAnders Roxell #endif
995b2ce5617SAnders Roxell 
996b2ce5617SAnders Roxell 	/* enable interrupts */
997b2ce5617SAnders Roxell 	adv7511_set_isr(sd, true);
998b2ce5617SAnders Roxell 
999b2ce5617SAnders Roxell 	if (handled)
1000b2ce5617SAnders Roxell 		*handled = true;
1001b2ce5617SAnders Roxell 	return 0;
1002b2ce5617SAnders Roxell }
1003b2ce5617SAnders Roxell 
1004b2ce5617SAnders Roxell static const struct v4l2_subdev_core_ops adv7511_core_ops = {
1005b2ce5617SAnders Roxell 	.log_status = adv7511_log_status,
1006b2ce5617SAnders Roxell #ifdef CONFIG_VIDEO_ADV_DEBUG
1007b2ce5617SAnders Roxell 	.g_register = adv7511_g_register,
1008b2ce5617SAnders Roxell 	.s_register = adv7511_s_register,
1009b2ce5617SAnders Roxell #endif
1010b2ce5617SAnders Roxell 	.s_power = adv7511_s_power,
1011b2ce5617SAnders Roxell 	.interrupt_service_routine = adv7511_isr,
1012b2ce5617SAnders Roxell };
1013b2ce5617SAnders Roxell 
1014b2ce5617SAnders Roxell /* ------------------------------ VIDEO OPS ------------------------------ */
1015b2ce5617SAnders Roxell 
1016b2ce5617SAnders Roxell /* Enable/disable adv7511 output */
1017b2ce5617SAnders Roxell static int adv7511_s_stream(struct v4l2_subdev *sd, int enable)
1018b2ce5617SAnders Roxell {
1019b2ce5617SAnders Roxell 	struct adv7511_state *state = get_adv7511_state(sd);
1020b2ce5617SAnders Roxell 
1021b2ce5617SAnders Roxell 	v4l2_dbg(1, debug, sd, "%s: %sable\n", __func__, (enable ? "en" : "dis"));
1022b2ce5617SAnders Roxell 	adv7511_wr_and_or(sd, 0xa1, ~0x3c, (enable ? 0 : 0x3c));
1023b2ce5617SAnders Roxell 	if (enable) {
1024b2ce5617SAnders Roxell 		adv7511_check_monitor_present_status(sd);
1025b2ce5617SAnders Roxell 	} else {
1026b2ce5617SAnders Roxell 		adv7511_s_power(sd, 0);
1027b2ce5617SAnders Roxell 		state->have_monitor = false;
1028b2ce5617SAnders Roxell 	}
1029b2ce5617SAnders Roxell 	return 0;
1030b2ce5617SAnders Roxell }
1031b2ce5617SAnders Roxell 
1032b2ce5617SAnders Roxell static int adv7511_s_dv_timings(struct v4l2_subdev *sd,
1033b2ce5617SAnders Roxell 			       struct v4l2_dv_timings *timings)
1034b2ce5617SAnders Roxell {
1035b2ce5617SAnders Roxell 	struct adv7511_state *state = get_adv7511_state(sd);
1036b2ce5617SAnders Roxell 	struct v4l2_bt_timings *bt = &timings->bt;
1037b2ce5617SAnders Roxell 	u32 fps;
1038b2ce5617SAnders Roxell 
1039b2ce5617SAnders Roxell 	v4l2_dbg(1, debug, sd, "%s:\n", __func__);
1040b2ce5617SAnders Roxell 
1041b2ce5617SAnders Roxell 	/* quick sanity check */
1042b2ce5617SAnders Roxell 	if (!v4l2_valid_dv_timings(timings, &adv7511_timings_cap, NULL, NULL))
1043b2ce5617SAnders Roxell 		return -EINVAL;
1044b2ce5617SAnders Roxell 
1045b2ce5617SAnders Roxell 	/* Fill the optional fields .standards and .flags in struct v4l2_dv_timings
1046b2ce5617SAnders Roxell 	   if the format is one of the CEA or DMT timings. */
1047b2ce5617SAnders Roxell 	v4l2_find_dv_timings_cap(timings, &adv7511_timings_cap, 0, NULL, NULL);
1048b2ce5617SAnders Roxell 
1049b2ce5617SAnders Roxell 	/* save timings */
1050b2ce5617SAnders Roxell 	state->dv_timings = *timings;
1051b2ce5617SAnders Roxell 
1052b2ce5617SAnders Roxell 	/* set h/vsync polarities */
1053b2ce5617SAnders Roxell 	adv7511_wr_and_or(sd, 0x17, 0x9f,
1054b2ce5617SAnders Roxell 		((bt->polarities & V4L2_DV_VSYNC_POS_POL) ? 0 : 0x40) |
1055b2ce5617SAnders Roxell 		((bt->polarities & V4L2_DV_HSYNC_POS_POL) ? 0 : 0x20));
1056b2ce5617SAnders Roxell 
1057b2ce5617SAnders Roxell 	fps = (u32)bt->pixelclock / (V4L2_DV_BT_FRAME_WIDTH(bt) * V4L2_DV_BT_FRAME_HEIGHT(bt));
1058b2ce5617SAnders Roxell 	switch (fps) {
1059b2ce5617SAnders Roxell 	case 24:
1060b2ce5617SAnders Roxell 		adv7511_wr_and_or(sd, 0xfb, 0xf9, 1 << 1);
1061b2ce5617SAnders Roxell 		break;
1062b2ce5617SAnders Roxell 	case 25:
1063b2ce5617SAnders Roxell 		adv7511_wr_and_or(sd, 0xfb, 0xf9, 2 << 1);
1064b2ce5617SAnders Roxell 		break;
1065b2ce5617SAnders Roxell 	case 30:
1066b2ce5617SAnders Roxell 		adv7511_wr_and_or(sd, 0xfb, 0xf9, 3 << 1);
1067b2ce5617SAnders Roxell 		break;
1068b2ce5617SAnders Roxell 	default:
1069b2ce5617SAnders Roxell 		adv7511_wr_and_or(sd, 0xfb, 0xf9, 0);
1070b2ce5617SAnders Roxell 		break;
1071b2ce5617SAnders Roxell 	}
1072b2ce5617SAnders Roxell 
1073b2ce5617SAnders Roxell 	/* update quantization range based on new dv_timings */
1074b2ce5617SAnders Roxell 	adv7511_set_rgb_quantization_mode(sd, state->rgb_quantization_range_ctrl);
1075b2ce5617SAnders Roxell 
1076b2ce5617SAnders Roxell 	return 0;
1077b2ce5617SAnders Roxell }
1078b2ce5617SAnders Roxell 
1079b2ce5617SAnders Roxell static int adv7511_g_dv_timings(struct v4l2_subdev *sd,
1080b2ce5617SAnders Roxell 				struct v4l2_dv_timings *timings)
1081b2ce5617SAnders Roxell {
1082b2ce5617SAnders Roxell 	struct adv7511_state *state = get_adv7511_state(sd);
1083b2ce5617SAnders Roxell 
1084b2ce5617SAnders Roxell 	v4l2_dbg(1, debug, sd, "%s:\n", __func__);
1085b2ce5617SAnders Roxell 
1086b2ce5617SAnders Roxell 	if (!timings)
1087b2ce5617SAnders Roxell 		return -EINVAL;
1088b2ce5617SAnders Roxell 
1089b2ce5617SAnders Roxell 	*timings = state->dv_timings;
1090b2ce5617SAnders Roxell 
1091b2ce5617SAnders Roxell 	return 0;
1092b2ce5617SAnders Roxell }
1093b2ce5617SAnders Roxell 
1094b2ce5617SAnders Roxell static int adv7511_enum_dv_timings(struct v4l2_subdev *sd,
1095b2ce5617SAnders Roxell 				   struct v4l2_enum_dv_timings *timings)
1096b2ce5617SAnders Roxell {
1097b2ce5617SAnders Roxell 	if (timings->pad != 0)
1098b2ce5617SAnders Roxell 		return -EINVAL;
1099b2ce5617SAnders Roxell 
1100b2ce5617SAnders Roxell 	return v4l2_enum_dv_timings_cap(timings, &adv7511_timings_cap, NULL, NULL);
1101b2ce5617SAnders Roxell }
1102b2ce5617SAnders Roxell 
1103b2ce5617SAnders Roxell static int adv7511_dv_timings_cap(struct v4l2_subdev *sd,
1104b2ce5617SAnders Roxell 				  struct v4l2_dv_timings_cap *cap)
1105b2ce5617SAnders Roxell {
1106b2ce5617SAnders Roxell 	if (cap->pad != 0)
1107b2ce5617SAnders Roxell 		return -EINVAL;
1108b2ce5617SAnders Roxell 
1109b2ce5617SAnders Roxell 	*cap = adv7511_timings_cap;
1110b2ce5617SAnders Roxell 	return 0;
1111b2ce5617SAnders Roxell }
1112b2ce5617SAnders Roxell 
1113b2ce5617SAnders Roxell static const struct v4l2_subdev_video_ops adv7511_video_ops = {
1114b2ce5617SAnders Roxell 	.s_stream = adv7511_s_stream,
1115b2ce5617SAnders Roxell 	.s_dv_timings = adv7511_s_dv_timings,
1116b2ce5617SAnders Roxell 	.g_dv_timings = adv7511_g_dv_timings,
1117b2ce5617SAnders Roxell };
1118b2ce5617SAnders Roxell 
1119b2ce5617SAnders Roxell /* ------------------------------ AUDIO OPS ------------------------------ */
1120b2ce5617SAnders Roxell static int adv7511_s_audio_stream(struct v4l2_subdev *sd, int enable)
1121b2ce5617SAnders Roxell {
1122b2ce5617SAnders Roxell 	v4l2_dbg(1, debug, sd, "%s: %sable\n", __func__, (enable ? "en" : "dis"));
1123b2ce5617SAnders Roxell 
1124b2ce5617SAnders Roxell 	if (enable)
1125b2ce5617SAnders Roxell 		adv7511_wr_and_or(sd, 0x4b, 0x3f, 0x80);
1126b2ce5617SAnders Roxell 	else
1127b2ce5617SAnders Roxell 		adv7511_wr_and_or(sd, 0x4b, 0x3f, 0x40);
1128b2ce5617SAnders Roxell 
1129b2ce5617SAnders Roxell 	return 0;
1130b2ce5617SAnders Roxell }
1131b2ce5617SAnders Roxell 
1132b2ce5617SAnders Roxell static int adv7511_s_clock_freq(struct v4l2_subdev *sd, u32 freq)
1133b2ce5617SAnders Roxell {
1134b2ce5617SAnders Roxell 	u32 N;
1135b2ce5617SAnders Roxell 
1136b2ce5617SAnders Roxell 	switch (freq) {
1137b2ce5617SAnders Roxell 	case 32000:  N = 4096;  break;
1138b2ce5617SAnders Roxell 	case 44100:  N = 6272;  break;
1139b2ce5617SAnders Roxell 	case 48000:  N = 6144;  break;
1140b2ce5617SAnders Roxell 	case 88200:  N = 12544; break;
1141b2ce5617SAnders Roxell 	case 96000:  N = 12288; break;
1142b2ce5617SAnders Roxell 	case 176400: N = 25088; break;
1143b2ce5617SAnders Roxell 	case 192000: N = 24576; break;
1144b2ce5617SAnders Roxell 	default:
1145b2ce5617SAnders Roxell 		return -EINVAL;
1146b2ce5617SAnders Roxell 	}
1147b2ce5617SAnders Roxell 
1148b2ce5617SAnders Roxell 	/* Set N (used with CTS to regenerate the audio clock) */
1149b2ce5617SAnders Roxell 	adv7511_wr(sd, 0x01, (N >> 16) & 0xf);
1150b2ce5617SAnders Roxell 	adv7511_wr(sd, 0x02, (N >> 8) & 0xff);
1151b2ce5617SAnders Roxell 	adv7511_wr(sd, 0x03, N & 0xff);
1152b2ce5617SAnders Roxell 
1153b2ce5617SAnders Roxell 	return 0;
1154b2ce5617SAnders Roxell }
1155b2ce5617SAnders Roxell 
1156b2ce5617SAnders Roxell static int adv7511_s_i2s_clock_freq(struct v4l2_subdev *sd, u32 freq)
1157b2ce5617SAnders Roxell {
1158b2ce5617SAnders Roxell 	u32 i2s_sf;
1159b2ce5617SAnders Roxell 
1160b2ce5617SAnders Roxell 	switch (freq) {
1161b2ce5617SAnders Roxell 	case 32000:  i2s_sf = 0x30; break;
1162b2ce5617SAnders Roxell 	case 44100:  i2s_sf = 0x00; break;
1163b2ce5617SAnders Roxell 	case 48000:  i2s_sf = 0x20; break;
1164b2ce5617SAnders Roxell 	case 88200:  i2s_sf = 0x80; break;
1165b2ce5617SAnders Roxell 	case 96000:  i2s_sf = 0xa0; break;
1166b2ce5617SAnders Roxell 	case 176400: i2s_sf = 0xc0; break;
1167b2ce5617SAnders Roxell 	case 192000: i2s_sf = 0xe0; break;
1168b2ce5617SAnders Roxell 	default:
1169b2ce5617SAnders Roxell 		return -EINVAL;
1170b2ce5617SAnders Roxell 	}
1171b2ce5617SAnders Roxell 
1172b2ce5617SAnders Roxell 	/* Set sampling frequency for I2S audio to 48 kHz */
1173b2ce5617SAnders Roxell 	adv7511_wr_and_or(sd, 0x15, 0xf, i2s_sf);
1174b2ce5617SAnders Roxell 
1175b2ce5617SAnders Roxell 	return 0;
1176b2ce5617SAnders Roxell }
1177b2ce5617SAnders Roxell 
1178b2ce5617SAnders Roxell static int adv7511_s_routing(struct v4l2_subdev *sd, u32 input, u32 output, u32 config)
1179b2ce5617SAnders Roxell {
1180b2ce5617SAnders Roxell 	/* Only 2 channels in use for application */
1181b2ce5617SAnders Roxell 	adv7511_wr_and_or(sd, 0x73, 0xf8, 0x1);
1182b2ce5617SAnders Roxell 	/* Speaker mapping */
1183b2ce5617SAnders Roxell 	adv7511_wr(sd, 0x76, 0x00);
1184b2ce5617SAnders Roxell 
1185b2ce5617SAnders Roxell 	/* 16 bit audio word length */
1186b2ce5617SAnders Roxell 	adv7511_wr_and_or(sd, 0x14, 0xf0, 0x02);
1187b2ce5617SAnders Roxell 
1188b2ce5617SAnders Roxell 	return 0;
1189b2ce5617SAnders Roxell }
1190b2ce5617SAnders Roxell 
1191b2ce5617SAnders Roxell static const struct v4l2_subdev_audio_ops adv7511_audio_ops = {
1192b2ce5617SAnders Roxell 	.s_stream = adv7511_s_audio_stream,
1193b2ce5617SAnders Roxell 	.s_clock_freq = adv7511_s_clock_freq,
1194b2ce5617SAnders Roxell 	.s_i2s_clock_freq = adv7511_s_i2s_clock_freq,
1195b2ce5617SAnders Roxell 	.s_routing = adv7511_s_routing,
1196b2ce5617SAnders Roxell };
1197b2ce5617SAnders Roxell 
1198b2ce5617SAnders Roxell /* ---------------------------- PAD OPS ------------------------------------- */
1199b2ce5617SAnders Roxell 
1200b2ce5617SAnders Roxell static int adv7511_get_edid(struct v4l2_subdev *sd, struct v4l2_edid *edid)
1201b2ce5617SAnders Roxell {
1202b2ce5617SAnders Roxell 	struct adv7511_state *state = get_adv7511_state(sd);
1203b2ce5617SAnders Roxell 
1204b2ce5617SAnders Roxell 	memset(edid->reserved, 0, sizeof(edid->reserved));
1205b2ce5617SAnders Roxell 
1206b2ce5617SAnders Roxell 	if (edid->pad != 0)
1207b2ce5617SAnders Roxell 		return -EINVAL;
1208b2ce5617SAnders Roxell 
1209b2ce5617SAnders Roxell 	if (edid->start_block == 0 && edid->blocks == 0) {
1210b2ce5617SAnders Roxell 		edid->blocks = state->edid.segments * 2;
1211b2ce5617SAnders Roxell 		return 0;
1212b2ce5617SAnders Roxell 	}
1213b2ce5617SAnders Roxell 
1214b2ce5617SAnders Roxell 	if (state->edid.segments == 0)
1215b2ce5617SAnders Roxell 		return -ENODATA;
1216b2ce5617SAnders Roxell 
1217b2ce5617SAnders Roxell 	if (edid->start_block >= state->edid.segments * 2)
1218b2ce5617SAnders Roxell 		return -EINVAL;
1219b2ce5617SAnders Roxell 
1220b2ce5617SAnders Roxell 	if (edid->start_block + edid->blocks > state->edid.segments * 2)
1221b2ce5617SAnders Roxell 		edid->blocks = state->edid.segments * 2 - edid->start_block;
1222b2ce5617SAnders Roxell 
1223b2ce5617SAnders Roxell 	memcpy(edid->edid, &state->edid.data[edid->start_block * 128],
1224b2ce5617SAnders Roxell 			128 * edid->blocks);
1225b2ce5617SAnders Roxell 
1226b2ce5617SAnders Roxell 	return 0;
1227b2ce5617SAnders Roxell }
1228b2ce5617SAnders Roxell 
1229b2ce5617SAnders Roxell static int adv7511_enum_mbus_code(struct v4l2_subdev *sd,
1230b2ce5617SAnders Roxell 				  struct v4l2_subdev_pad_config *cfg,
1231b2ce5617SAnders Roxell 				  struct v4l2_subdev_mbus_code_enum *code)
1232b2ce5617SAnders Roxell {
1233b2ce5617SAnders Roxell 	if (code->pad != 0)
1234b2ce5617SAnders Roxell 		return -EINVAL;
1235b2ce5617SAnders Roxell 
1236b2ce5617SAnders Roxell 	switch (code->index) {
1237b2ce5617SAnders Roxell 	case 0:
1238b2ce5617SAnders Roxell 		code->code = MEDIA_BUS_FMT_RGB888_1X24;
1239b2ce5617SAnders Roxell 		break;
1240b2ce5617SAnders Roxell 	case 1:
1241b2ce5617SAnders Roxell 		code->code = MEDIA_BUS_FMT_YUYV8_1X16;
1242b2ce5617SAnders Roxell 		break;
1243b2ce5617SAnders Roxell 	case 2:
1244b2ce5617SAnders Roxell 		code->code = MEDIA_BUS_FMT_UYVY8_1X16;
1245b2ce5617SAnders Roxell 		break;
1246b2ce5617SAnders Roxell 	default:
1247b2ce5617SAnders Roxell 		return -EINVAL;
1248b2ce5617SAnders Roxell 	}
1249b2ce5617SAnders Roxell 	return 0;
1250b2ce5617SAnders Roxell }
1251b2ce5617SAnders Roxell 
1252b2ce5617SAnders Roxell static void adv7511_fill_format(struct adv7511_state *state,
1253b2ce5617SAnders Roxell 				struct v4l2_mbus_framefmt *format)
1254b2ce5617SAnders Roxell {
1255b2ce5617SAnders Roxell 	format->width = state->dv_timings.bt.width;
1256b2ce5617SAnders Roxell 	format->height = state->dv_timings.bt.height;
1257b2ce5617SAnders Roxell 	format->field = V4L2_FIELD_NONE;
1258b2ce5617SAnders Roxell }
1259b2ce5617SAnders Roxell 
1260b2ce5617SAnders Roxell static int adv7511_get_fmt(struct v4l2_subdev *sd,
1261b2ce5617SAnders Roxell 			   struct v4l2_subdev_pad_config *cfg,
1262b2ce5617SAnders Roxell 			   struct v4l2_subdev_format *format)
1263b2ce5617SAnders Roxell {
1264b2ce5617SAnders Roxell 	struct adv7511_state *state = get_adv7511_state(sd);
1265b2ce5617SAnders Roxell 
1266b2ce5617SAnders Roxell 	if (format->pad != 0)
1267b2ce5617SAnders Roxell 		return -EINVAL;
1268b2ce5617SAnders Roxell 
1269b2ce5617SAnders Roxell 	memset(&format->format, 0, sizeof(format->format));
1270b2ce5617SAnders Roxell 	adv7511_fill_format(state, &format->format);
1271b2ce5617SAnders Roxell 
1272b2ce5617SAnders Roxell 	if (format->which == V4L2_SUBDEV_FORMAT_TRY) {
1273b2ce5617SAnders Roxell 		struct v4l2_mbus_framefmt *fmt;
1274b2ce5617SAnders Roxell 
1275b2ce5617SAnders Roxell 		fmt = v4l2_subdev_get_try_format(sd, cfg, format->pad);
1276b2ce5617SAnders Roxell 		format->format.code = fmt->code;
1277b2ce5617SAnders Roxell 		format->format.colorspace = fmt->colorspace;
1278b2ce5617SAnders Roxell 		format->format.ycbcr_enc = fmt->ycbcr_enc;
1279b2ce5617SAnders Roxell 		format->format.quantization = fmt->quantization;
1280b2ce5617SAnders Roxell 		format->format.xfer_func = fmt->xfer_func;
1281b2ce5617SAnders Roxell 	} else {
1282b2ce5617SAnders Roxell 		format->format.code = state->fmt_code;
1283b2ce5617SAnders Roxell 		format->format.colorspace = state->colorspace;
1284b2ce5617SAnders Roxell 		format->format.ycbcr_enc = state->ycbcr_enc;
1285b2ce5617SAnders Roxell 		format->format.quantization = state->quantization;
1286b2ce5617SAnders Roxell 		format->format.xfer_func = state->xfer_func;
1287b2ce5617SAnders Roxell 	}
1288b2ce5617SAnders Roxell 
1289b2ce5617SAnders Roxell 	return 0;
1290b2ce5617SAnders Roxell }
1291b2ce5617SAnders Roxell 
1292b2ce5617SAnders Roxell static int adv7511_set_fmt(struct v4l2_subdev *sd,
1293b2ce5617SAnders Roxell 			   struct v4l2_subdev_pad_config *cfg,
1294b2ce5617SAnders Roxell 			   struct v4l2_subdev_format *format)
1295b2ce5617SAnders Roxell {
1296b2ce5617SAnders Roxell 	struct adv7511_state *state = get_adv7511_state(sd);
1297b2ce5617SAnders Roxell 	/*
1298b2ce5617SAnders Roxell 	 * Bitfield namings come the CEA-861-F standard, table 8 "Auxiliary
1299b2ce5617SAnders Roxell 	 * Video Information (AVI) InfoFrame Format"
1300b2ce5617SAnders Roxell 	 *
1301b2ce5617SAnders Roxell 	 * c = Colorimetry
1302b2ce5617SAnders Roxell 	 * ec = Extended Colorimetry
1303b2ce5617SAnders Roxell 	 * y = RGB or YCbCr
1304b2ce5617SAnders Roxell 	 * q = RGB Quantization Range
1305b2ce5617SAnders Roxell 	 * yq = YCC Quantization Range
1306b2ce5617SAnders Roxell 	 */
1307b2ce5617SAnders Roxell 	u8 c = HDMI_COLORIMETRY_NONE;
1308b2ce5617SAnders Roxell 	u8 ec = HDMI_EXTENDED_COLORIMETRY_XV_YCC_601;
1309b2ce5617SAnders Roxell 	u8 y = HDMI_COLORSPACE_RGB;
1310b2ce5617SAnders Roxell 	u8 q = HDMI_QUANTIZATION_RANGE_DEFAULT;
1311b2ce5617SAnders Roxell 	u8 yq = HDMI_YCC_QUANTIZATION_RANGE_LIMITED;
1312b2ce5617SAnders Roxell 	u8 itc = state->content_type != V4L2_DV_IT_CONTENT_TYPE_NO_ITC;
1313b2ce5617SAnders Roxell 	u8 cn = itc ? state->content_type : V4L2_DV_IT_CONTENT_TYPE_GRAPHICS;
1314b2ce5617SAnders Roxell 
1315b2ce5617SAnders Roxell 	if (format->pad != 0)
1316b2ce5617SAnders Roxell 		return -EINVAL;
1317b2ce5617SAnders Roxell 	switch (format->format.code) {
1318b2ce5617SAnders Roxell 	case MEDIA_BUS_FMT_UYVY8_1X16:
1319b2ce5617SAnders Roxell 	case MEDIA_BUS_FMT_YUYV8_1X16:
1320b2ce5617SAnders Roxell 	case MEDIA_BUS_FMT_RGB888_1X24:
1321b2ce5617SAnders Roxell 		break;
1322b2ce5617SAnders Roxell 	default:
1323b2ce5617SAnders Roxell 		return -EINVAL;
1324b2ce5617SAnders Roxell 	}
1325b2ce5617SAnders Roxell 
1326b2ce5617SAnders Roxell 	adv7511_fill_format(state, &format->format);
1327b2ce5617SAnders Roxell 	if (format->which == V4L2_SUBDEV_FORMAT_TRY) {
1328b2ce5617SAnders Roxell 		struct v4l2_mbus_framefmt *fmt;
1329b2ce5617SAnders Roxell 
1330b2ce5617SAnders Roxell 		fmt = v4l2_subdev_get_try_format(sd, cfg, format->pad);
1331b2ce5617SAnders Roxell 		fmt->code = format->format.code;
1332b2ce5617SAnders Roxell 		fmt->colorspace = format->format.colorspace;
1333b2ce5617SAnders Roxell 		fmt->ycbcr_enc = format->format.ycbcr_enc;
1334b2ce5617SAnders Roxell 		fmt->quantization = format->format.quantization;
1335b2ce5617SAnders Roxell 		fmt->xfer_func = format->format.xfer_func;
1336b2ce5617SAnders Roxell 		return 0;
1337b2ce5617SAnders Roxell 	}
1338b2ce5617SAnders Roxell 
1339b2ce5617SAnders Roxell 	switch (format->format.code) {
1340b2ce5617SAnders Roxell 	case MEDIA_BUS_FMT_UYVY8_1X16:
1341b2ce5617SAnders Roxell 		adv7511_wr_and_or(sd, 0x15, 0xf0, 0x01);
1342b2ce5617SAnders Roxell 		adv7511_wr_and_or(sd, 0x16, 0x03, 0xb8);
1343b2ce5617SAnders Roxell 		y = HDMI_COLORSPACE_YUV422;
1344b2ce5617SAnders Roxell 		break;
1345b2ce5617SAnders Roxell 	case MEDIA_BUS_FMT_YUYV8_1X16:
1346b2ce5617SAnders Roxell 		adv7511_wr_and_or(sd, 0x15, 0xf0, 0x01);
1347b2ce5617SAnders Roxell 		adv7511_wr_and_or(sd, 0x16, 0x03, 0xbc);
1348b2ce5617SAnders Roxell 		y = HDMI_COLORSPACE_YUV422;
1349b2ce5617SAnders Roxell 		break;
1350b2ce5617SAnders Roxell 	case MEDIA_BUS_FMT_RGB888_1X24:
1351b2ce5617SAnders Roxell 	default:
1352b2ce5617SAnders Roxell 		adv7511_wr_and_or(sd, 0x15, 0xf0, 0x00);
1353b2ce5617SAnders Roxell 		adv7511_wr_and_or(sd, 0x16, 0x03, 0x00);
1354b2ce5617SAnders Roxell 		break;
1355b2ce5617SAnders Roxell 	}
1356b2ce5617SAnders Roxell 	state->fmt_code = format->format.code;
1357b2ce5617SAnders Roxell 	state->colorspace = format->format.colorspace;
1358b2ce5617SAnders Roxell 	state->ycbcr_enc = format->format.ycbcr_enc;
1359b2ce5617SAnders Roxell 	state->quantization = format->format.quantization;
1360b2ce5617SAnders Roxell 	state->xfer_func = format->format.xfer_func;
1361b2ce5617SAnders Roxell 
1362b2ce5617SAnders Roxell 	switch (format->format.colorspace) {
1363b2ce5617SAnders Roxell 	case V4L2_COLORSPACE_OPRGB:
1364b2ce5617SAnders Roxell 		c = HDMI_COLORIMETRY_EXTENDED;
1365b2ce5617SAnders Roxell 		ec = y ? HDMI_EXTENDED_COLORIMETRY_OPYCC_601 :
1366b2ce5617SAnders Roxell 			 HDMI_EXTENDED_COLORIMETRY_OPRGB;
1367b2ce5617SAnders Roxell 		break;
1368b2ce5617SAnders Roxell 	case V4L2_COLORSPACE_SMPTE170M:
1369b2ce5617SAnders Roxell 		c = y ? HDMI_COLORIMETRY_ITU_601 : HDMI_COLORIMETRY_NONE;
1370b2ce5617SAnders Roxell 		if (y && format->format.ycbcr_enc == V4L2_YCBCR_ENC_XV601) {
1371b2ce5617SAnders Roxell 			c = HDMI_COLORIMETRY_EXTENDED;
1372b2ce5617SAnders Roxell 			ec = HDMI_EXTENDED_COLORIMETRY_XV_YCC_601;
1373b2ce5617SAnders Roxell 		}
1374b2ce5617SAnders Roxell 		break;
1375b2ce5617SAnders Roxell 	case V4L2_COLORSPACE_REC709:
1376b2ce5617SAnders Roxell 		c = y ? HDMI_COLORIMETRY_ITU_709 : HDMI_COLORIMETRY_NONE;
1377b2ce5617SAnders Roxell 		if (y && format->format.ycbcr_enc == V4L2_YCBCR_ENC_XV709) {
1378b2ce5617SAnders Roxell 			c = HDMI_COLORIMETRY_EXTENDED;
1379b2ce5617SAnders Roxell 			ec = HDMI_EXTENDED_COLORIMETRY_XV_YCC_709;
1380b2ce5617SAnders Roxell 		}
1381b2ce5617SAnders Roxell 		break;
1382b2ce5617SAnders Roxell 	case V4L2_COLORSPACE_SRGB:
1383b2ce5617SAnders Roxell 		c = y ? HDMI_COLORIMETRY_EXTENDED : HDMI_COLORIMETRY_NONE;
1384b2ce5617SAnders Roxell 		ec = y ? HDMI_EXTENDED_COLORIMETRY_S_YCC_601 :
1385b2ce5617SAnders Roxell 			 HDMI_EXTENDED_COLORIMETRY_XV_YCC_601;
1386b2ce5617SAnders Roxell 		break;
1387b2ce5617SAnders Roxell 	case V4L2_COLORSPACE_BT2020:
1388b2ce5617SAnders Roxell 		c = HDMI_COLORIMETRY_EXTENDED;
1389b2ce5617SAnders Roxell 		if (y && format->format.ycbcr_enc == V4L2_YCBCR_ENC_BT2020_CONST_LUM)
1390b2ce5617SAnders Roxell 			ec = 5; /* Not yet available in hdmi.h */
1391b2ce5617SAnders Roxell 		else
1392b2ce5617SAnders Roxell 			ec = 6; /* Not yet available in hdmi.h */
1393b2ce5617SAnders Roxell 		break;
1394b2ce5617SAnders Roxell 	default:
1395b2ce5617SAnders Roxell 		break;
1396b2ce5617SAnders Roxell 	}
1397b2ce5617SAnders Roxell 
1398b2ce5617SAnders Roxell 	/*
1399b2ce5617SAnders Roxell 	 * CEA-861-F says that for RGB formats the YCC range must match the
1400b2ce5617SAnders Roxell 	 * RGB range, although sources should ignore the YCC range.
1401b2ce5617SAnders Roxell 	 *
1402b2ce5617SAnders Roxell 	 * The RGB quantization range shouldn't be non-zero if the EDID doesn't
1403b2ce5617SAnders Roxell 	 * have the Q bit set in the Video Capabilities Data Block, however this
1404b2ce5617SAnders Roxell 	 * isn't checked at the moment. The assumption is that the application
1405b2ce5617SAnders Roxell 	 * knows the EDID and can detect this.
1406b2ce5617SAnders Roxell 	 *
1407b2ce5617SAnders Roxell 	 * The same is true for the YCC quantization range: non-standard YCC
1408b2ce5617SAnders Roxell 	 * quantization ranges should only be sent if the EDID has the YQ bit
1409b2ce5617SAnders Roxell 	 * set in the Video Capabilities Data Block.
1410b2ce5617SAnders Roxell 	 */
1411b2ce5617SAnders Roxell 	switch (format->format.quantization) {
1412b2ce5617SAnders Roxell 	case V4L2_QUANTIZATION_FULL_RANGE:
1413b2ce5617SAnders Roxell 		q = y ? HDMI_QUANTIZATION_RANGE_DEFAULT :
1414b2ce5617SAnders Roxell 			HDMI_QUANTIZATION_RANGE_FULL;
1415b2ce5617SAnders Roxell 		yq = q ? q - 1 : HDMI_YCC_QUANTIZATION_RANGE_FULL;
1416b2ce5617SAnders Roxell 		break;
1417b2ce5617SAnders Roxell 	case V4L2_QUANTIZATION_LIM_RANGE:
1418b2ce5617SAnders Roxell 		q = y ? HDMI_QUANTIZATION_RANGE_DEFAULT :
1419b2ce5617SAnders Roxell 			HDMI_QUANTIZATION_RANGE_LIMITED;
1420b2ce5617SAnders Roxell 		yq = q ? q - 1 : HDMI_YCC_QUANTIZATION_RANGE_LIMITED;
1421b2ce5617SAnders Roxell 		break;
1422b2ce5617SAnders Roxell 	}
1423b2ce5617SAnders Roxell 
1424b2ce5617SAnders Roxell 	adv7511_wr_and_or(sd, 0x4a, 0xbf, 0);
1425b2ce5617SAnders Roxell 	adv7511_wr_and_or(sd, 0x55, 0x9f, y << 5);
1426b2ce5617SAnders Roxell 	adv7511_wr_and_or(sd, 0x56, 0x3f, c << 6);
1427b2ce5617SAnders Roxell 	adv7511_wr_and_or(sd, 0x57, 0x83, (ec << 4) | (q << 2) | (itc << 7));
1428b2ce5617SAnders Roxell 	adv7511_wr_and_or(sd, 0x59, 0x0f, (yq << 6) | (cn << 4));
1429b2ce5617SAnders Roxell 	adv7511_wr_and_or(sd, 0x4a, 0xff, 1);
1430b2ce5617SAnders Roxell 	adv7511_set_rgb_quantization_mode(sd, state->rgb_quantization_range_ctrl);
1431b2ce5617SAnders Roxell 
1432b2ce5617SAnders Roxell 	return 0;
1433b2ce5617SAnders Roxell }
1434b2ce5617SAnders Roxell 
1435b2ce5617SAnders Roxell static const struct v4l2_subdev_pad_ops adv7511_pad_ops = {
1436b2ce5617SAnders Roxell 	.get_edid = adv7511_get_edid,
1437b2ce5617SAnders Roxell 	.enum_mbus_code = adv7511_enum_mbus_code,
1438b2ce5617SAnders Roxell 	.get_fmt = adv7511_get_fmt,
1439b2ce5617SAnders Roxell 	.set_fmt = adv7511_set_fmt,
1440b2ce5617SAnders Roxell 	.enum_dv_timings = adv7511_enum_dv_timings,
1441b2ce5617SAnders Roxell 	.dv_timings_cap = adv7511_dv_timings_cap,
1442b2ce5617SAnders Roxell };
1443b2ce5617SAnders Roxell 
1444b2ce5617SAnders Roxell /* --------------------- SUBDEV OPS --------------------------------------- */
1445b2ce5617SAnders Roxell 
1446b2ce5617SAnders Roxell static const struct v4l2_subdev_ops adv7511_ops = {
1447b2ce5617SAnders Roxell 	.core  = &adv7511_core_ops,
1448b2ce5617SAnders Roxell 	.pad  = &adv7511_pad_ops,
1449b2ce5617SAnders Roxell 	.video = &adv7511_video_ops,
1450b2ce5617SAnders Roxell 	.audio = &adv7511_audio_ops,
1451b2ce5617SAnders Roxell };
1452b2ce5617SAnders Roxell 
1453b2ce5617SAnders Roxell /* ----------------------------------------------------------------------- */
1454b2ce5617SAnders Roxell static void adv7511_dbg_dump_edid(int lvl, int debug, struct v4l2_subdev *sd, int segment, u8 *buf)
1455b2ce5617SAnders Roxell {
1456b2ce5617SAnders Roxell 	if (debug >= lvl) {
1457b2ce5617SAnders Roxell 		int i, j;
1458b2ce5617SAnders Roxell 		v4l2_dbg(lvl, debug, sd, "edid segment %d\n", segment);
1459b2ce5617SAnders Roxell 		for (i = 0; i < 256; i += 16) {
1460b2ce5617SAnders Roxell 			u8 b[128];
1461b2ce5617SAnders Roxell 			u8 *bp = b;
1462b2ce5617SAnders Roxell 			if (i == 128)
1463b2ce5617SAnders Roxell 				v4l2_dbg(lvl, debug, sd, "\n");
1464b2ce5617SAnders Roxell 			for (j = i; j < i + 16; j++) {
1465b2ce5617SAnders Roxell 				sprintf(bp, "0x%02x, ", buf[j]);
1466b2ce5617SAnders Roxell 				bp += 6;
1467b2ce5617SAnders Roxell 			}
1468b2ce5617SAnders Roxell 			bp[0] = '\0';
1469b2ce5617SAnders Roxell 			v4l2_dbg(lvl, debug, sd, "%s\n", b);
1470b2ce5617SAnders Roxell 		}
1471b2ce5617SAnders Roxell 	}
1472b2ce5617SAnders Roxell }
1473b2ce5617SAnders Roxell 
1474b2ce5617SAnders Roxell static void adv7511_notify_no_edid(struct v4l2_subdev *sd)
1475b2ce5617SAnders Roxell {
1476b2ce5617SAnders Roxell 	struct adv7511_state *state = get_adv7511_state(sd);
1477b2ce5617SAnders Roxell 	struct adv7511_edid_detect ed;
1478b2ce5617SAnders Roxell 
1479b2ce5617SAnders Roxell 	/* We failed to read the EDID, so send an event for this. */
1480b2ce5617SAnders Roxell 	ed.present = false;
1481b2ce5617SAnders Roxell 	ed.segment = adv7511_rd(sd, 0xc4);
1482b2ce5617SAnders Roxell 	ed.phys_addr = CEC_PHYS_ADDR_INVALID;
1483b2ce5617SAnders Roxell 	cec_s_phys_addr(state->cec_adap, ed.phys_addr, false);
1484b2ce5617SAnders Roxell 	v4l2_subdev_notify(sd, ADV7511_EDID_DETECT, (void *)&ed);
1485b2ce5617SAnders Roxell 	v4l2_ctrl_s_ctrl(state->have_edid0_ctrl, 0x0);
1486b2ce5617SAnders Roxell }
1487b2ce5617SAnders Roxell 
1488b2ce5617SAnders Roxell static void adv7511_edid_handler(struct work_struct *work)
1489b2ce5617SAnders Roxell {
1490b2ce5617SAnders Roxell 	struct delayed_work *dwork = to_delayed_work(work);
1491b2ce5617SAnders Roxell 	struct adv7511_state *state = container_of(dwork, struct adv7511_state, edid_handler);
1492b2ce5617SAnders Roxell 	struct v4l2_subdev *sd = &state->sd;
1493b2ce5617SAnders Roxell 
1494b2ce5617SAnders Roxell 	v4l2_dbg(1, debug, sd, "%s:\n", __func__);
1495b2ce5617SAnders Roxell 
1496b2ce5617SAnders Roxell 	if (adv7511_check_edid_status(sd)) {
1497b2ce5617SAnders Roxell 		/* Return if we received the EDID. */
1498b2ce5617SAnders Roxell 		return;
1499b2ce5617SAnders Roxell 	}
1500b2ce5617SAnders Roxell 
1501b2ce5617SAnders Roxell 	if (adv7511_have_hotplug(sd)) {
1502b2ce5617SAnders Roxell 		/* We must retry reading the EDID several times, it is possible
1503b2ce5617SAnders Roxell 		 * that initially the EDID couldn't be read due to i2c errors
1504b2ce5617SAnders Roxell 		 * (DVI connectors are particularly prone to this problem). */
1505b2ce5617SAnders Roxell 		if (state->edid.read_retries) {
1506b2ce5617SAnders Roxell 			state->edid.read_retries--;
1507b2ce5617SAnders Roxell 			v4l2_dbg(1, debug, sd, "%s: edid read failed\n", __func__);
1508b2ce5617SAnders Roxell 			state->have_monitor = false;
1509b2ce5617SAnders Roxell 			adv7511_s_power(sd, false);
1510b2ce5617SAnders Roxell 			adv7511_s_power(sd, true);
1511b2ce5617SAnders Roxell 			queue_delayed_work(state->work_queue, &state->edid_handler, EDID_DELAY);
1512b2ce5617SAnders Roxell 			return;
1513b2ce5617SAnders Roxell 		}
1514b2ce5617SAnders Roxell 	}
1515b2ce5617SAnders Roxell 
1516b2ce5617SAnders Roxell 	/* We failed to read the EDID, so send an event for this. */
1517b2ce5617SAnders Roxell 	adv7511_notify_no_edid(sd);
1518b2ce5617SAnders Roxell 	v4l2_dbg(1, debug, sd, "%s: no edid found\n", __func__);
1519b2ce5617SAnders Roxell }
1520b2ce5617SAnders Roxell 
1521b2ce5617SAnders Roxell static void adv7511_audio_setup(struct v4l2_subdev *sd)
1522b2ce5617SAnders Roxell {
1523b2ce5617SAnders Roxell 	v4l2_dbg(1, debug, sd, "%s\n", __func__);
1524b2ce5617SAnders Roxell 
1525b2ce5617SAnders Roxell 	adv7511_s_i2s_clock_freq(sd, 48000);
1526b2ce5617SAnders Roxell 	adv7511_s_clock_freq(sd, 48000);
1527b2ce5617SAnders Roxell 	adv7511_s_routing(sd, 0, 0, 0);
1528b2ce5617SAnders Roxell }
1529b2ce5617SAnders Roxell 
1530b2ce5617SAnders Roxell /* Configure hdmi transmitter. */
1531b2ce5617SAnders Roxell static void adv7511_setup(struct v4l2_subdev *sd)
1532b2ce5617SAnders Roxell {
1533b2ce5617SAnders Roxell 	struct adv7511_state *state = get_adv7511_state(sd);
1534b2ce5617SAnders Roxell 	v4l2_dbg(1, debug, sd, "%s\n", __func__);
1535b2ce5617SAnders Roxell 
1536b2ce5617SAnders Roxell 	/* Input format: RGB 4:4:4 */
1537b2ce5617SAnders Roxell 	adv7511_wr_and_or(sd, 0x15, 0xf0, 0x0);
1538b2ce5617SAnders Roxell 	/* Output format: RGB 4:4:4 */
1539b2ce5617SAnders Roxell 	adv7511_wr_and_or(sd, 0x16, 0x7f, 0x0);
1540b2ce5617SAnders Roxell 	/* 1st order interpolation 4:2:2 -> 4:4:4 up conversion, Aspect ratio: 16:9 */
1541b2ce5617SAnders Roxell 	adv7511_wr_and_or(sd, 0x17, 0xf9, 0x06);
1542b2ce5617SAnders Roxell 	/* Disable pixel repetition */
1543b2ce5617SAnders Roxell 	adv7511_wr_and_or(sd, 0x3b, 0x9f, 0x0);
1544b2ce5617SAnders Roxell 	/* Disable CSC */
1545b2ce5617SAnders Roxell 	adv7511_wr_and_or(sd, 0x18, 0x7f, 0x0);
1546b2ce5617SAnders Roxell 	/* Output format: RGB 4:4:4, Active Format Information is valid,
1547b2ce5617SAnders Roxell 	 * underscanned */
1548b2ce5617SAnders Roxell 	adv7511_wr_and_or(sd, 0x55, 0x9c, 0x12);
1549b2ce5617SAnders Roxell 	/* AVI Info frame packet enable, Audio Info frame disable */
1550b2ce5617SAnders Roxell 	adv7511_wr_and_or(sd, 0x44, 0xe7, 0x10);
1551b2ce5617SAnders Roxell 	/* Colorimetry, Active format aspect ratio: same as picure. */
1552b2ce5617SAnders Roxell 	adv7511_wr(sd, 0x56, 0xa8);
1553b2ce5617SAnders Roxell 	/* No encryption */
1554b2ce5617SAnders Roxell 	adv7511_wr_and_or(sd, 0xaf, 0xed, 0x0);
1555b2ce5617SAnders Roxell 
1556b2ce5617SAnders Roxell 	/* Positive clk edge capture for input video clock */
1557b2ce5617SAnders Roxell 	adv7511_wr_and_or(sd, 0xba, 0x1f, 0x60);
1558b2ce5617SAnders Roxell 
1559b2ce5617SAnders Roxell 	adv7511_audio_setup(sd);
1560b2ce5617SAnders Roxell 
1561b2ce5617SAnders Roxell 	v4l2_ctrl_handler_setup(&state->hdl);
1562b2ce5617SAnders Roxell }
1563b2ce5617SAnders Roxell 
1564b2ce5617SAnders Roxell static void adv7511_notify_monitor_detect(struct v4l2_subdev *sd)
1565b2ce5617SAnders Roxell {
1566b2ce5617SAnders Roxell 	struct adv7511_monitor_detect mdt;
1567b2ce5617SAnders Roxell 	struct adv7511_state *state = get_adv7511_state(sd);
1568b2ce5617SAnders Roxell 
1569b2ce5617SAnders Roxell 	mdt.present = state->have_monitor;
1570b2ce5617SAnders Roxell 	v4l2_subdev_notify(sd, ADV7511_MONITOR_DETECT, (void *)&mdt);
1571b2ce5617SAnders Roxell }
1572b2ce5617SAnders Roxell 
1573b2ce5617SAnders Roxell static void adv7511_check_monitor_present_status(struct v4l2_subdev *sd)
1574b2ce5617SAnders Roxell {
1575b2ce5617SAnders Roxell 	struct adv7511_state *state = get_adv7511_state(sd);
1576b2ce5617SAnders Roxell 	/* read hotplug and rx-sense state */
1577b2ce5617SAnders Roxell 	u8 status = adv7511_rd(sd, 0x42);
1578b2ce5617SAnders Roxell 
1579b2ce5617SAnders Roxell 	v4l2_dbg(1, debug, sd, "%s: status: 0x%x%s%s\n",
1580b2ce5617SAnders Roxell 			 __func__,
1581b2ce5617SAnders Roxell 			 status,
1582b2ce5617SAnders Roxell 			 status & MASK_ADV7511_HPD_DETECT ? ", hotplug" : "",
1583b2ce5617SAnders Roxell 			 status & MASK_ADV7511_MSEN_DETECT ? ", rx-sense" : "");
1584b2ce5617SAnders Roxell 
1585b2ce5617SAnders Roxell 	/* update read only ctrls */
1586b2ce5617SAnders Roxell 	v4l2_ctrl_s_ctrl(state->hotplug_ctrl, adv7511_have_hotplug(sd) ? 0x1 : 0x0);
1587b2ce5617SAnders Roxell 	v4l2_ctrl_s_ctrl(state->rx_sense_ctrl, adv7511_have_rx_sense(sd) ? 0x1 : 0x0);
1588b2ce5617SAnders Roxell 
1589b2ce5617SAnders Roxell 	if ((status & MASK_ADV7511_HPD_DETECT) && ((status & MASK_ADV7511_MSEN_DETECT) || state->edid.segments)) {
1590b2ce5617SAnders Roxell 		v4l2_dbg(1, debug, sd, "%s: hotplug and (rx-sense or edid)\n", __func__);
1591b2ce5617SAnders Roxell 		if (!state->have_monitor) {
1592b2ce5617SAnders Roxell 			v4l2_dbg(1, debug, sd, "%s: monitor detected\n", __func__);
1593b2ce5617SAnders Roxell 			state->have_monitor = true;
1594b2ce5617SAnders Roxell 			adv7511_set_isr(sd, true);
1595b2ce5617SAnders Roxell 			if (!adv7511_s_power(sd, true)) {
1596b2ce5617SAnders Roxell 				v4l2_dbg(1, debug, sd, "%s: monitor detected, powerup failed\n", __func__);
1597b2ce5617SAnders Roxell 				return;
1598b2ce5617SAnders Roxell 			}
1599b2ce5617SAnders Roxell 			adv7511_setup(sd);
1600b2ce5617SAnders Roxell 			adv7511_notify_monitor_detect(sd);
1601b2ce5617SAnders Roxell 			state->edid.read_retries = EDID_MAX_RETRIES;
1602b2ce5617SAnders Roxell 			queue_delayed_work(state->work_queue, &state->edid_handler, EDID_DELAY);
1603b2ce5617SAnders Roxell 		}
1604b2ce5617SAnders Roxell 	} else if (status & MASK_ADV7511_HPD_DETECT) {
1605b2ce5617SAnders Roxell 		v4l2_dbg(1, debug, sd, "%s: hotplug detected\n", __func__);
1606b2ce5617SAnders Roxell 		state->edid.read_retries = EDID_MAX_RETRIES;
1607b2ce5617SAnders Roxell 		queue_delayed_work(state->work_queue, &state->edid_handler, EDID_DELAY);
1608b2ce5617SAnders Roxell 	} else if (!(status & MASK_ADV7511_HPD_DETECT)) {
1609b2ce5617SAnders Roxell 		v4l2_dbg(1, debug, sd, "%s: hotplug not detected\n", __func__);
1610b2ce5617SAnders Roxell 		if (state->have_monitor) {
1611b2ce5617SAnders Roxell 			v4l2_dbg(1, debug, sd, "%s: monitor not detected\n", __func__);
1612b2ce5617SAnders Roxell 			state->have_monitor = false;
1613b2ce5617SAnders Roxell 			adv7511_notify_monitor_detect(sd);
1614b2ce5617SAnders Roxell 		}
1615b2ce5617SAnders Roxell 		adv7511_s_power(sd, false);
1616b2ce5617SAnders Roxell 		memset(&state->edid, 0, sizeof(struct adv7511_state_edid));
1617b2ce5617SAnders Roxell 		adv7511_notify_no_edid(sd);
1618b2ce5617SAnders Roxell 	}
1619b2ce5617SAnders Roxell }
1620b2ce5617SAnders Roxell 
1621b2ce5617SAnders Roxell static bool edid_block_verify_crc(u8 *edid_block)
1622b2ce5617SAnders Roxell {
1623b2ce5617SAnders Roxell 	u8 sum = 0;
1624b2ce5617SAnders Roxell 	int i;
1625b2ce5617SAnders Roxell 
1626b2ce5617SAnders Roxell 	for (i = 0; i < 128; i++)
1627b2ce5617SAnders Roxell 		sum += edid_block[i];
1628b2ce5617SAnders Roxell 	return sum == 0;
1629b2ce5617SAnders Roxell }
1630b2ce5617SAnders Roxell 
1631b2ce5617SAnders Roxell static bool edid_verify_crc(struct v4l2_subdev *sd, u32 segment)
1632b2ce5617SAnders Roxell {
1633b2ce5617SAnders Roxell 	struct adv7511_state *state = get_adv7511_state(sd);
1634b2ce5617SAnders Roxell 	u32 blocks = state->edid.blocks;
1635b2ce5617SAnders Roxell 	u8 *data = state->edid.data;
1636b2ce5617SAnders Roxell 
1637b2ce5617SAnders Roxell 	if (!edid_block_verify_crc(&data[segment * 256]))
1638b2ce5617SAnders Roxell 		return false;
1639b2ce5617SAnders Roxell 	if ((segment + 1) * 2 <= blocks)
1640b2ce5617SAnders Roxell 		return edid_block_verify_crc(&data[segment * 256 + 128]);
1641b2ce5617SAnders Roxell 	return true;
1642b2ce5617SAnders Roxell }
1643b2ce5617SAnders Roxell 
1644b2ce5617SAnders Roxell static bool edid_verify_header(struct v4l2_subdev *sd, u32 segment)
1645b2ce5617SAnders Roxell {
1646b2ce5617SAnders Roxell 	static const u8 hdmi_header[] = {
1647b2ce5617SAnders Roxell 		0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00
1648b2ce5617SAnders Roxell 	};
1649b2ce5617SAnders Roxell 	struct adv7511_state *state = get_adv7511_state(sd);
1650b2ce5617SAnders Roxell 	u8 *data = state->edid.data;
1651b2ce5617SAnders Roxell 
1652b2ce5617SAnders Roxell 	if (segment != 0)
1653b2ce5617SAnders Roxell 		return true;
1654b2ce5617SAnders Roxell 	return !memcmp(data, hdmi_header, sizeof(hdmi_header));
1655b2ce5617SAnders Roxell }
1656b2ce5617SAnders Roxell 
1657b2ce5617SAnders Roxell static bool adv7511_check_edid_status(struct v4l2_subdev *sd)
1658b2ce5617SAnders Roxell {
1659b2ce5617SAnders Roxell 	struct adv7511_state *state = get_adv7511_state(sd);
1660b2ce5617SAnders Roxell 	u8 edidRdy = adv7511_rd(sd, 0xc5);
1661b2ce5617SAnders Roxell 
1662b2ce5617SAnders Roxell 	v4l2_dbg(1, debug, sd, "%s: edid ready (retries: %d)\n",
1663b2ce5617SAnders Roxell 			 __func__, EDID_MAX_RETRIES - state->edid.read_retries);
1664b2ce5617SAnders Roxell 
1665b2ce5617SAnders Roxell 	if (state->edid.complete)
1666b2ce5617SAnders Roxell 		return true;
1667b2ce5617SAnders Roxell 
1668b2ce5617SAnders Roxell 	if (edidRdy & MASK_ADV7511_EDID_RDY) {
1669b2ce5617SAnders Roxell 		int segment = adv7511_rd(sd, 0xc4);
1670b2ce5617SAnders Roxell 		struct adv7511_edid_detect ed;
1671b2ce5617SAnders Roxell 
1672b2ce5617SAnders Roxell 		if (segment >= EDID_MAX_SEGM) {
1673b2ce5617SAnders Roxell 			v4l2_err(sd, "edid segment number too big\n");
1674b2ce5617SAnders Roxell 			return false;
1675b2ce5617SAnders Roxell 		}
1676b2ce5617SAnders Roxell 		v4l2_dbg(1, debug, sd, "%s: got segment %d\n", __func__, segment);
1677b2ce5617SAnders Roxell 		adv7511_edid_rd(sd, 256, &state->edid.data[segment * 256]);
1678b2ce5617SAnders Roxell 		adv7511_dbg_dump_edid(2, debug, sd, segment, &state->edid.data[segment * 256]);
1679b2ce5617SAnders Roxell 		if (segment == 0) {
1680b2ce5617SAnders Roxell 			state->edid.blocks = state->edid.data[0x7e] + 1;
1681b2ce5617SAnders Roxell 			v4l2_dbg(1, debug, sd, "%s: %d blocks in total\n", __func__, state->edid.blocks);
1682b2ce5617SAnders Roxell 		}
1683b2ce5617SAnders Roxell 		if (!edid_verify_crc(sd, segment) ||
1684b2ce5617SAnders Roxell 		    !edid_verify_header(sd, segment)) {
1685b2ce5617SAnders Roxell 			/* edid crc error, force reread of edid segment */
1686b2ce5617SAnders Roxell 			v4l2_err(sd, "%s: edid crc or header error\n", __func__);
1687b2ce5617SAnders Roxell 			state->have_monitor = false;
1688b2ce5617SAnders Roxell 			adv7511_s_power(sd, false);
1689b2ce5617SAnders Roxell 			adv7511_s_power(sd, true);
1690b2ce5617SAnders Roxell 			return false;
1691b2ce5617SAnders Roxell 		}
1692b2ce5617SAnders Roxell 		/* one more segment read ok */
1693b2ce5617SAnders Roxell 		state->edid.segments = segment + 1;
1694b2ce5617SAnders Roxell 		v4l2_ctrl_s_ctrl(state->have_edid0_ctrl, 0x1);
1695b2ce5617SAnders Roxell 		if (((state->edid.data[0x7e] >> 1) + 1) > state->edid.segments) {
1696b2ce5617SAnders Roxell 			/* Request next EDID segment */
1697b2ce5617SAnders Roxell 			v4l2_dbg(1, debug, sd, "%s: request segment %d\n", __func__, state->edid.segments);
1698b2ce5617SAnders Roxell 			adv7511_wr(sd, 0xc9, 0xf);
1699b2ce5617SAnders Roxell 			adv7511_wr(sd, 0xc4, state->edid.segments);
1700b2ce5617SAnders Roxell 			state->edid.read_retries = EDID_MAX_RETRIES;
1701b2ce5617SAnders Roxell 			queue_delayed_work(state->work_queue, &state->edid_handler, EDID_DELAY);
1702b2ce5617SAnders Roxell 			return false;
1703b2ce5617SAnders Roxell 		}
1704b2ce5617SAnders Roxell 
1705b2ce5617SAnders Roxell 		v4l2_dbg(1, debug, sd, "%s: edid complete with %d segment(s)\n", __func__, state->edid.segments);
1706b2ce5617SAnders Roxell 		state->edid.complete = true;
1707b2ce5617SAnders Roxell 		ed.phys_addr = cec_get_edid_phys_addr(state->edid.data,
1708b2ce5617SAnders Roxell 						      state->edid.segments * 256,
1709b2ce5617SAnders Roxell 						      NULL);
1710b2ce5617SAnders Roxell 		/* report when we have all segments
1711b2ce5617SAnders Roxell 		   but report only for segment 0
1712b2ce5617SAnders Roxell 		 */
1713b2ce5617SAnders Roxell 		ed.present = true;
1714b2ce5617SAnders Roxell 		ed.segment = 0;
1715b2ce5617SAnders Roxell 		state->edid_detect_counter++;
1716b2ce5617SAnders Roxell 		cec_s_phys_addr(state->cec_adap, ed.phys_addr, false);
1717b2ce5617SAnders Roxell 		v4l2_subdev_notify(sd, ADV7511_EDID_DETECT, (void *)&ed);
1718b2ce5617SAnders Roxell 		return ed.present;
1719b2ce5617SAnders Roxell 	}
1720b2ce5617SAnders Roxell 
1721b2ce5617SAnders Roxell 	return false;
1722b2ce5617SAnders Roxell }
1723b2ce5617SAnders Roxell 
1724b2ce5617SAnders Roxell static int adv7511_registered(struct v4l2_subdev *sd)
1725b2ce5617SAnders Roxell {
1726b2ce5617SAnders Roxell 	struct adv7511_state *state = get_adv7511_state(sd);
1727b2ce5617SAnders Roxell 	struct i2c_client *client = v4l2_get_subdevdata(sd);
1728b2ce5617SAnders Roxell 	int err;
1729b2ce5617SAnders Roxell 
1730b2ce5617SAnders Roxell 	err = cec_register_adapter(state->cec_adap, &client->dev);
1731b2ce5617SAnders Roxell 	if (err)
1732b2ce5617SAnders Roxell 		cec_delete_adapter(state->cec_adap);
1733b2ce5617SAnders Roxell 	return err;
1734b2ce5617SAnders Roxell }
1735b2ce5617SAnders Roxell 
1736b2ce5617SAnders Roxell static void adv7511_unregistered(struct v4l2_subdev *sd)
1737b2ce5617SAnders Roxell {
1738b2ce5617SAnders Roxell 	struct adv7511_state *state = get_adv7511_state(sd);
1739b2ce5617SAnders Roxell 
1740b2ce5617SAnders Roxell 	cec_unregister_adapter(state->cec_adap);
1741b2ce5617SAnders Roxell }
1742b2ce5617SAnders Roxell 
1743b2ce5617SAnders Roxell static const struct v4l2_subdev_internal_ops adv7511_int_ops = {
1744b2ce5617SAnders Roxell 	.registered = adv7511_registered,
1745b2ce5617SAnders Roxell 	.unregistered = adv7511_unregistered,
1746b2ce5617SAnders Roxell };
1747b2ce5617SAnders Roxell 
1748b2ce5617SAnders Roxell /* ----------------------------------------------------------------------- */
1749b2ce5617SAnders Roxell /* Setup ADV7511 */
1750b2ce5617SAnders Roxell static void adv7511_init_setup(struct v4l2_subdev *sd)
1751b2ce5617SAnders Roxell {
1752b2ce5617SAnders Roxell 	struct adv7511_state *state = get_adv7511_state(sd);
1753b2ce5617SAnders Roxell 	struct adv7511_state_edid *edid = &state->edid;
1754b2ce5617SAnders Roxell 	u32 cec_clk = state->pdata.cec_clk;
1755b2ce5617SAnders Roxell 	u8 ratio;
1756b2ce5617SAnders Roxell 
1757b2ce5617SAnders Roxell 	v4l2_dbg(1, debug, sd, "%s\n", __func__);
1758b2ce5617SAnders Roxell 
1759b2ce5617SAnders Roxell 	/* clear all interrupts */
1760b2ce5617SAnders Roxell 	adv7511_wr(sd, 0x96, 0xff);
1761b2ce5617SAnders Roxell 	adv7511_wr(sd, 0x97, 0xff);
1762b2ce5617SAnders Roxell 	/*
1763b2ce5617SAnders Roxell 	 * Stop HPD from resetting a lot of registers.
1764b2ce5617SAnders Roxell 	 * It might leave the chip in a partly un-initialized state,
1765b2ce5617SAnders Roxell 	 * in particular with regards to hotplug bounces.
1766b2ce5617SAnders Roxell 	 */
1767b2ce5617SAnders Roxell 	adv7511_wr_and_or(sd, 0xd6, 0x3f, 0xc0);
1768b2ce5617SAnders Roxell 	memset(edid, 0, sizeof(struct adv7511_state_edid));
1769b2ce5617SAnders Roxell 	state->have_monitor = false;
1770b2ce5617SAnders Roxell 	adv7511_set_isr(sd, false);
1771b2ce5617SAnders Roxell 	adv7511_s_stream(sd, false);
1772b2ce5617SAnders Roxell 	adv7511_s_audio_stream(sd, false);
1773b2ce5617SAnders Roxell 
1774b2ce5617SAnders Roxell 	if (state->i2c_cec == NULL)
1775b2ce5617SAnders Roxell 		return;
1776b2ce5617SAnders Roxell 
1777b2ce5617SAnders Roxell 	v4l2_dbg(1, debug, sd, "%s: cec_clk %d\n", __func__, cec_clk);
1778b2ce5617SAnders Roxell 
1779b2ce5617SAnders Roxell 	/* cec soft reset */
1780b2ce5617SAnders Roxell 	adv7511_cec_write(sd, 0x50, 0x01);
1781b2ce5617SAnders Roxell 	adv7511_cec_write(sd, 0x50, 0x00);
1782b2ce5617SAnders Roxell 
1783b2ce5617SAnders Roxell 	/* legacy mode */
1784b2ce5617SAnders Roxell 	adv7511_cec_write(sd, 0x4a, 0x00);
1785b2ce5617SAnders Roxell 	adv7511_cec_write(sd, 0x4a, 0x07);
1786b2ce5617SAnders Roxell 
1787b2ce5617SAnders Roxell 	if (cec_clk % 750000 != 0)
1788b2ce5617SAnders Roxell 		v4l2_err(sd, "%s: cec_clk %d, not multiple of 750 Khz\n",
1789b2ce5617SAnders Roxell 			 __func__, cec_clk);
1790b2ce5617SAnders Roxell 
1791b2ce5617SAnders Roxell 	ratio = (cec_clk / 750000) - 1;
1792b2ce5617SAnders Roxell 	adv7511_cec_write(sd, 0x4e, ratio << 2);
1793b2ce5617SAnders Roxell }
1794b2ce5617SAnders Roxell 
1795b2ce5617SAnders Roxell static int adv7511_probe(struct i2c_client *client, const struct i2c_device_id *id)
1796b2ce5617SAnders Roxell {
1797b2ce5617SAnders Roxell 	struct adv7511_state *state;
1798b2ce5617SAnders Roxell 	struct adv7511_platform_data *pdata = client->dev.platform_data;
1799b2ce5617SAnders Roxell 	struct v4l2_ctrl_handler *hdl;
1800b2ce5617SAnders Roxell 	struct v4l2_subdev *sd;
1801b2ce5617SAnders Roxell 	u8 chip_id[2];
1802b2ce5617SAnders Roxell 	int err = -EIO;
1803b2ce5617SAnders Roxell 
1804b2ce5617SAnders Roxell 	/* Check if the adapter supports the needed features */
1805b2ce5617SAnders Roxell 	if (!i2c_check_functionality(client->adapter, I2C_FUNC_SMBUS_BYTE_DATA))
1806b2ce5617SAnders Roxell 		return -EIO;
1807b2ce5617SAnders Roxell 
1808b2ce5617SAnders Roxell 	state = devm_kzalloc(&client->dev, sizeof(struct adv7511_state), GFP_KERNEL);
1809b2ce5617SAnders Roxell 	if (!state)
1810b2ce5617SAnders Roxell 		return -ENOMEM;
1811b2ce5617SAnders Roxell 
1812b2ce5617SAnders Roxell 	/* Platform data */
1813b2ce5617SAnders Roxell 	if (!pdata) {
1814b2ce5617SAnders Roxell 		v4l_err(client, "No platform data!\n");
1815b2ce5617SAnders Roxell 		return -ENODEV;
1816b2ce5617SAnders Roxell 	}
1817b2ce5617SAnders Roxell 	memcpy(&state->pdata, pdata, sizeof(state->pdata));
1818b2ce5617SAnders Roxell 	state->fmt_code = MEDIA_BUS_FMT_RGB888_1X24;
1819b2ce5617SAnders Roxell 	state->colorspace = V4L2_COLORSPACE_SRGB;
1820b2ce5617SAnders Roxell 
1821b2ce5617SAnders Roxell 	sd = &state->sd;
1822b2ce5617SAnders Roxell 
1823b2ce5617SAnders Roxell 	v4l2_dbg(1, debug, sd, "detecting adv7511 client on address 0x%x\n",
1824b2ce5617SAnders Roxell 			 client->addr << 1);
1825b2ce5617SAnders Roxell 
1826b2ce5617SAnders Roxell 	v4l2_i2c_subdev_init(sd, client, &adv7511_ops);
1827b2ce5617SAnders Roxell 	sd->internal_ops = &adv7511_int_ops;
1828b2ce5617SAnders Roxell 
1829b2ce5617SAnders Roxell 	hdl = &state->hdl;
1830b2ce5617SAnders Roxell 	v4l2_ctrl_handler_init(hdl, 10);
1831b2ce5617SAnders Roxell 	/* add in ascending ID order */
1832b2ce5617SAnders Roxell 	state->hdmi_mode_ctrl = v4l2_ctrl_new_std_menu(hdl, &adv7511_ctrl_ops,
1833b2ce5617SAnders Roxell 			V4L2_CID_DV_TX_MODE, V4L2_DV_TX_MODE_HDMI,
1834b2ce5617SAnders Roxell 			0, V4L2_DV_TX_MODE_DVI_D);
1835b2ce5617SAnders Roxell 	state->hotplug_ctrl = v4l2_ctrl_new_std(hdl, NULL,
1836b2ce5617SAnders Roxell 			V4L2_CID_DV_TX_HOTPLUG, 0, 1, 0, 0);
1837b2ce5617SAnders Roxell 	state->rx_sense_ctrl = v4l2_ctrl_new_std(hdl, NULL,
1838b2ce5617SAnders Roxell 			V4L2_CID_DV_TX_RXSENSE, 0, 1, 0, 0);
1839b2ce5617SAnders Roxell 	state->have_edid0_ctrl = v4l2_ctrl_new_std(hdl, NULL,
1840b2ce5617SAnders Roxell 			V4L2_CID_DV_TX_EDID_PRESENT, 0, 1, 0, 0);
1841b2ce5617SAnders Roxell 	state->rgb_quantization_range_ctrl =
1842b2ce5617SAnders Roxell 		v4l2_ctrl_new_std_menu(hdl, &adv7511_ctrl_ops,
1843b2ce5617SAnders Roxell 			V4L2_CID_DV_TX_RGB_RANGE, V4L2_DV_RGB_RANGE_FULL,
1844b2ce5617SAnders Roxell 			0, V4L2_DV_RGB_RANGE_AUTO);
1845b2ce5617SAnders Roxell 	state->content_type_ctrl =
1846b2ce5617SAnders Roxell 		v4l2_ctrl_new_std_menu(hdl, &adv7511_ctrl_ops,
1847b2ce5617SAnders Roxell 			V4L2_CID_DV_TX_IT_CONTENT_TYPE, V4L2_DV_IT_CONTENT_TYPE_NO_ITC,
1848b2ce5617SAnders Roxell 			0, V4L2_DV_IT_CONTENT_TYPE_NO_ITC);
1849b2ce5617SAnders Roxell 	sd->ctrl_handler = hdl;
1850b2ce5617SAnders Roxell 	if (hdl->error) {
1851b2ce5617SAnders Roxell 		err = hdl->error;
1852b2ce5617SAnders Roxell 		goto err_hdl;
1853b2ce5617SAnders Roxell 	}
1854b2ce5617SAnders Roxell 	state->pad.flags = MEDIA_PAD_FL_SINK;
1855b2ce5617SAnders Roxell 	sd->entity.function = MEDIA_ENT_F_DV_ENCODER;
1856b2ce5617SAnders Roxell 	err = media_entity_pads_init(&sd->entity, 1, &state->pad);
1857b2ce5617SAnders Roxell 	if (err)
1858b2ce5617SAnders Roxell 		goto err_hdl;
1859b2ce5617SAnders Roxell 
1860b2ce5617SAnders Roxell 	/* EDID and CEC i2c addr */
1861b2ce5617SAnders Roxell 	state->i2c_edid_addr = state->pdata.i2c_edid << 1;
1862b2ce5617SAnders Roxell 	state->i2c_cec_addr = state->pdata.i2c_cec << 1;
1863b2ce5617SAnders Roxell 	state->i2c_pktmem_addr = state->pdata.i2c_pktmem << 1;
1864b2ce5617SAnders Roxell 
1865b2ce5617SAnders Roxell 	state->chip_revision = adv7511_rd(sd, 0x0);
1866b2ce5617SAnders Roxell 	chip_id[0] = adv7511_rd(sd, 0xf5);
1867b2ce5617SAnders Roxell 	chip_id[1] = adv7511_rd(sd, 0xf6);
1868b2ce5617SAnders Roxell 	if (chip_id[0] != 0x75 || chip_id[1] != 0x11) {
1869b2ce5617SAnders Roxell 		v4l2_err(sd, "chip_id != 0x7511, read 0x%02x%02x\n", chip_id[0],
1870b2ce5617SAnders Roxell 			 chip_id[1]);
1871b2ce5617SAnders Roxell 		err = -EIO;
1872b2ce5617SAnders Roxell 		goto err_entity;
1873b2ce5617SAnders Roxell 	}
1874b2ce5617SAnders Roxell 
18759524da83SWolfram Sang 	state->i2c_edid = i2c_new_dummy_device(client->adapter,
1876b2ce5617SAnders Roxell 					state->i2c_edid_addr >> 1);
18779524da83SWolfram Sang 	if (IS_ERR(state->i2c_edid)) {
1878b2ce5617SAnders Roxell 		v4l2_err(sd, "failed to register edid i2c client\n");
18799524da83SWolfram Sang 		err = PTR_ERR(state->i2c_edid);
1880b2ce5617SAnders Roxell 		goto err_entity;
1881b2ce5617SAnders Roxell 	}
1882b2ce5617SAnders Roxell 
1883b2ce5617SAnders Roxell 	adv7511_wr(sd, 0xe1, state->i2c_cec_addr);
1884b2ce5617SAnders Roxell 	if (state->pdata.cec_clk < 3000000 ||
1885b2ce5617SAnders Roxell 	    state->pdata.cec_clk > 100000000) {
1886b2ce5617SAnders Roxell 		v4l2_err(sd, "%s: cec_clk %u outside range, disabling cec\n",
1887b2ce5617SAnders Roxell 				__func__, state->pdata.cec_clk);
1888b2ce5617SAnders Roxell 		state->pdata.cec_clk = 0;
1889b2ce5617SAnders Roxell 	}
1890b2ce5617SAnders Roxell 
1891b2ce5617SAnders Roxell 	if (state->pdata.cec_clk) {
18929524da83SWolfram Sang 		state->i2c_cec = i2c_new_dummy_device(client->adapter,
1893b2ce5617SAnders Roxell 					       state->i2c_cec_addr >> 1);
18949524da83SWolfram Sang 		if (IS_ERR(state->i2c_cec)) {
1895b2ce5617SAnders Roxell 			v4l2_err(sd, "failed to register cec i2c client\n");
18969524da83SWolfram Sang 			err = PTR_ERR(state->i2c_cec);
1897b2ce5617SAnders Roxell 			goto err_unreg_edid;
1898b2ce5617SAnders Roxell 		}
1899b2ce5617SAnders Roxell 		adv7511_wr(sd, 0xe2, 0x00); /* power up cec section */
1900b2ce5617SAnders Roxell 	} else {
1901b2ce5617SAnders Roxell 		adv7511_wr(sd, 0xe2, 0x01); /* power down cec section */
1902b2ce5617SAnders Roxell 	}
1903b2ce5617SAnders Roxell 
19049524da83SWolfram Sang 	state->i2c_pktmem = i2c_new_dummy_device(client->adapter, state->i2c_pktmem_addr >> 1);
19059524da83SWolfram Sang 	if (IS_ERR(state->i2c_pktmem)) {
1906b2ce5617SAnders Roxell 		v4l2_err(sd, "failed to register pktmem i2c client\n");
19079524da83SWolfram Sang 		err = PTR_ERR(state->i2c_pktmem);
1908b2ce5617SAnders Roxell 		goto err_unreg_cec;
1909b2ce5617SAnders Roxell 	}
1910b2ce5617SAnders Roxell 
1911b2ce5617SAnders Roxell 	state->work_queue = create_singlethread_workqueue(sd->name);
1912b2ce5617SAnders Roxell 	if (state->work_queue == NULL) {
1913b2ce5617SAnders Roxell 		v4l2_err(sd, "could not create workqueue\n");
1914b2ce5617SAnders Roxell 		err = -ENOMEM;
1915b2ce5617SAnders Roxell 		goto err_unreg_pktmem;
1916b2ce5617SAnders Roxell 	}
1917b2ce5617SAnders Roxell 
1918b2ce5617SAnders Roxell 	INIT_DELAYED_WORK(&state->edid_handler, adv7511_edid_handler);
1919b2ce5617SAnders Roxell 
1920b2ce5617SAnders Roxell 	adv7511_init_setup(sd);
1921b2ce5617SAnders Roxell 
1922b2ce5617SAnders Roxell #if IS_ENABLED(CONFIG_VIDEO_ADV7511_CEC)
1923b2ce5617SAnders Roxell 	state->cec_adap = cec_allocate_adapter(&adv7511_cec_adap_ops,
1924b2ce5617SAnders Roxell 		state, dev_name(&client->dev), CEC_CAP_DEFAULTS,
1925b2ce5617SAnders Roxell 		ADV7511_MAX_ADDRS);
1926b2ce5617SAnders Roxell 	err = PTR_ERR_OR_ZERO(state->cec_adap);
1927b2ce5617SAnders Roxell 	if (err) {
1928b2ce5617SAnders Roxell 		destroy_workqueue(state->work_queue);
1929b2ce5617SAnders Roxell 		goto err_unreg_pktmem;
1930b2ce5617SAnders Roxell 	}
1931b2ce5617SAnders Roxell #endif
1932b2ce5617SAnders Roxell 
1933b2ce5617SAnders Roxell 	adv7511_set_isr(sd, true);
1934b2ce5617SAnders Roxell 	adv7511_check_monitor_present_status(sd);
1935b2ce5617SAnders Roxell 
1936b2ce5617SAnders Roxell 	v4l2_info(sd, "%s found @ 0x%x (%s)\n", client->name,
1937b2ce5617SAnders Roxell 			  client->addr << 1, client->adapter->name);
1938b2ce5617SAnders Roxell 	return 0;
1939b2ce5617SAnders Roxell 
1940b2ce5617SAnders Roxell err_unreg_pktmem:
1941b2ce5617SAnders Roxell 	i2c_unregister_device(state->i2c_pktmem);
1942b2ce5617SAnders Roxell err_unreg_cec:
1943b2ce5617SAnders Roxell 	i2c_unregister_device(state->i2c_cec);
1944b2ce5617SAnders Roxell err_unreg_edid:
1945b2ce5617SAnders Roxell 	i2c_unregister_device(state->i2c_edid);
1946b2ce5617SAnders Roxell err_entity:
1947b2ce5617SAnders Roxell 	media_entity_cleanup(&sd->entity);
1948b2ce5617SAnders Roxell err_hdl:
1949b2ce5617SAnders Roxell 	v4l2_ctrl_handler_free(&state->hdl);
1950b2ce5617SAnders Roxell 	return err;
1951b2ce5617SAnders Roxell }
1952b2ce5617SAnders Roxell 
1953b2ce5617SAnders Roxell /* ----------------------------------------------------------------------- */
1954b2ce5617SAnders Roxell 
1955b2ce5617SAnders Roxell static int adv7511_remove(struct i2c_client *client)
1956b2ce5617SAnders Roxell {
1957b2ce5617SAnders Roxell 	struct v4l2_subdev *sd = i2c_get_clientdata(client);
1958b2ce5617SAnders Roxell 	struct adv7511_state *state = get_adv7511_state(sd);
1959b2ce5617SAnders Roxell 
1960b2ce5617SAnders Roxell 	state->chip_revision = -1;
1961b2ce5617SAnders Roxell 
1962b2ce5617SAnders Roxell 	v4l2_dbg(1, debug, sd, "%s removed @ 0x%x (%s)\n", client->name,
1963b2ce5617SAnders Roxell 		 client->addr << 1, client->adapter->name);
1964b2ce5617SAnders Roxell 
1965b2ce5617SAnders Roxell 	adv7511_set_isr(sd, false);
1966b2ce5617SAnders Roxell 	adv7511_init_setup(sd);
1967b2ce5617SAnders Roxell 	cancel_delayed_work(&state->edid_handler);
1968b2ce5617SAnders Roxell 	i2c_unregister_device(state->i2c_edid);
1969b2ce5617SAnders Roxell 	i2c_unregister_device(state->i2c_cec);
1970b2ce5617SAnders Roxell 	i2c_unregister_device(state->i2c_pktmem);
1971b2ce5617SAnders Roxell 	destroy_workqueue(state->work_queue);
1972b2ce5617SAnders Roxell 	v4l2_device_unregister_subdev(sd);
1973b2ce5617SAnders Roxell 	media_entity_cleanup(&sd->entity);
1974b2ce5617SAnders Roxell 	v4l2_ctrl_handler_free(sd->ctrl_handler);
1975b2ce5617SAnders Roxell 	return 0;
1976b2ce5617SAnders Roxell }
1977b2ce5617SAnders Roxell 
1978b2ce5617SAnders Roxell /* ----------------------------------------------------------------------- */
1979b2ce5617SAnders Roxell 
1980b2ce5617SAnders Roxell static const struct i2c_device_id adv7511_id[] = {
198125a3d6baSHans Verkuil 	{ "adv7511-v4l2", 0 },
1982b2ce5617SAnders Roxell 	{ }
1983b2ce5617SAnders Roxell };
1984b2ce5617SAnders Roxell MODULE_DEVICE_TABLE(i2c, adv7511_id);
1985b2ce5617SAnders Roxell 
1986b2ce5617SAnders Roxell static struct i2c_driver adv7511_driver = {
1987b2ce5617SAnders Roxell 	.driver = {
198825a3d6baSHans Verkuil 		.name = "adv7511-v4l2",
1989b2ce5617SAnders Roxell 	},
1990b2ce5617SAnders Roxell 	.probe = adv7511_probe,
1991b2ce5617SAnders Roxell 	.remove = adv7511_remove,
1992b2ce5617SAnders Roxell 	.id_table = adv7511_id,
1993b2ce5617SAnders Roxell };
1994b2ce5617SAnders Roxell 
1995b2ce5617SAnders Roxell module_i2c_driver(adv7511_driver);
1996