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