xref: /linux/drivers/media/cec/usb/extron-da-hd-4k-plus/extron-da-hd-4k-plus.c (revision bf4afc53b77aeaa48b5409da5c8da6bb4eff7f43)
1 // SPDX-License-Identifier: GPL-2.0-only
2 /*
3  * Copyright 2021-2024 Cisco Systems, Inc. and/or its affiliates. All rights reserved.
4  */
5 
6 /*
7  * Currently this driver does not fully support the serial port of the
8  * Extron, only the USB port is fully supported.
9  *
10  * Issues specific to using the serial port instead of the USB since the
11  * serial port doesn't detect if the device is powered off:
12  *
13  * - Some periodic ping mechanism is needed to detect when the Extron is
14  *   powered off and when it is powered on again.
15  * - What to do when it is powered off and the driver is modprobed? Keep
16  *   trying to contact the Extron indefinitely?
17  */
18 
19 #include <linux/completion.h>
20 #include <linux/ctype.h>
21 #include <linux/delay.h>
22 #include <linux/hex.h>
23 #include <linux/init.h>
24 #include <linux/interrupt.h>
25 #include <linux/kernel.h>
26 #include <linux/module.h>
27 #include <linux/slab.h>
28 #include <linux/time.h>
29 
30 #include "extron-da-hd-4k-plus.h"
31 
32 MODULE_AUTHOR("Hans Verkuil <hverkuil@kernel.org>");
33 MODULE_DESCRIPTION("Extron DA HD 4K PLUS HDMI CEC driver");
34 MODULE_LICENSE("GPL");
35 
36 static int debug;
37 module_param(debug, int, 0644);
38 MODULE_PARM_DESC(debug, "debug level (0-1)");
39 
40 static unsigned int vendor_id;
41 module_param(vendor_id, uint, 0444);
42 MODULE_PARM_DESC(vendor_id, "CEC Vendor ID");
43 
44 static char manufacturer_name[4];
45 module_param_string(manufacturer_name, manufacturer_name,
46 		    sizeof(manufacturer_name), 0644);
47 MODULE_PARM_DESC(manufacturer_name,
48 		 "EDID Vendor String (3 uppercase characters)");
49 
50 static bool hpd_never_low;
51 module_param(hpd_never_low, bool, 0644);
52 MODULE_PARM_DESC(hpd_never_low, "Input HPD will never go low (1), or go low if all output HPDs are low (0, default)");
53 
54 #define EXTRON_TIMEOUT_SECS 6
55 
56 static const u8 hdmi_edid[256] = {
57 	0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00,
58 	0x31, 0xd8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
59 	0x01, 0x20, 0x01, 0x03, 0x80, 0x60, 0x36, 0x78,
60 	0x0f, 0xee, 0x91, 0xa3, 0x54, 0x4c, 0x99, 0x26,
61 	0x0f, 0x50, 0x54, 0x20, 0x00, 0x00, 0x01, 0x01,
62 	0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
63 	0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x02, 0x3a,
64 	0x80, 0x18, 0x71, 0x38, 0x2d, 0x40, 0x58, 0x2c,
65 	0x45, 0x00, 0xc0, 0x1c, 0x32, 0x00, 0x00, 0x1e,
66 	0x00, 0x00, 0x00, 0xfd, 0x00, 0x18, 0x55, 0x18,
67 	0x87, 0x11, 0x00, 0x0a, 0x20, 0x20, 0x20, 0x20,
68 	0x20, 0x20, 0x00, 0x00, 0x00, 0xfc, 0x00, 0x68,
69 	0x64, 0x6d, 0x69, 0x2d, 0x31, 0x30, 0x38, 0x30,
70 	0x70, 0x36, 0x30, 0x0a, 0x00, 0x00, 0x00, 0xfe,
71 	0x00, 0x73, 0x65, 0x72, 0x69, 0x6f, 0x0a, 0x20,
72 	0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x01, 0x95,
73 
74 	0x02, 0x03, 0x1b, 0xf1, 0x42, 0x10, 0x01, 0x23,
75 	0x09, 0x07, 0x07, 0x83, 0x01, 0x00, 0x00, 0x68,
76 	0x03, 0x0c, 0x00, 0x10, 0x00, 0x00, 0x21, 0x01,
77 	0xe2, 0x00, 0xca, 0x00, 0x00, 0x00, 0x00, 0x00,
78 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
79 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
80 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
81 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
82 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
83 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
84 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
85 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
86 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
87 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
88 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
89 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x89,
90 };
91 
92 static const u8 hdmi_edid_4k_300[256] = {
93 	0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00,
94 	0x31, 0xd8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
95 	0x01, 0x20, 0x01, 0x03, 0x80, 0x60, 0x36, 0x78,
96 	0x0f, 0xee, 0x91, 0xa3, 0x54, 0x4c, 0x99, 0x26,
97 	0x0f, 0x50, 0x54, 0x20, 0x00, 0x00, 0x01, 0x01,
98 	0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
99 	0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x02, 0x3a,
100 	0x80, 0x18, 0x71, 0x38, 0x2d, 0x40, 0x58, 0x2c,
101 	0x45, 0x00, 0xc0, 0x1c, 0x32, 0x00, 0x00, 0x1e,
102 	0x00, 0x00, 0x00, 0xfd, 0x00, 0x18, 0x55, 0x18,
103 	0x87, 0x3c, 0x00, 0x0a, 0x20, 0x20, 0x20, 0x20,
104 	0x20, 0x20, 0x00, 0x00, 0x00, 0xfc, 0x00, 0x68,
105 	0x64, 0x6d, 0x69, 0x2d, 0x34, 0x6b, 0x2d, 0x36,
106 	0x30, 0x30, 0x0a, 0x20, 0x00, 0x00, 0x00, 0xfe,
107 	0x00, 0x73, 0x65, 0x72, 0x69, 0x6f, 0x0a, 0x20,
108 	0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x01, 0x87,
109 
110 	0x02, 0x03, 0x1f, 0xf1, 0x43, 0x10, 0x5f, 0x01,
111 	0x23, 0x09, 0x07, 0x07, 0x83, 0x01, 0x00, 0x00,
112 	0x6b, 0x03, 0x0c, 0x00, 0x10, 0x00, 0x00, 0x3c,
113 	0x21, 0x00, 0x20, 0x01, 0xe2, 0x00, 0xca, 0x00,
114 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
115 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
116 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
117 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
118 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
119 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
120 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
121 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
122 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
123 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
124 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
125 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc6,
126 };
127 
128 static const u8 hdmi_edid_4k_600[256] = {
129 	0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00,
130 	0x31, 0xd8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
131 	0x01, 0x20, 0x01, 0x03, 0x80, 0x60, 0x36, 0x78,
132 	0x0f, 0xee, 0x91, 0xa3, 0x54, 0x4c, 0x99, 0x26,
133 	0x0f, 0x50, 0x54, 0x20, 0x00, 0x00, 0x01, 0x01,
134 	0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
135 	0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x08, 0xe8,
136 	0x00, 0x30, 0xf2, 0x70, 0x5a, 0x80, 0xb0, 0x58,
137 	0x8a, 0x00, 0xc0, 0x1c, 0x32, 0x00, 0x00, 0x1e,
138 	0x00, 0x00, 0x00, 0xfd, 0x00, 0x18, 0x55, 0x18,
139 	0x87, 0x3c, 0x00, 0x0a, 0x20, 0x20, 0x20, 0x20,
140 	0x20, 0x20, 0x00, 0x00, 0x00, 0xfc, 0x00, 0x68,
141 	0x64, 0x6d, 0x69, 0x2d, 0x34, 0x6b, 0x2d, 0x36,
142 	0x30, 0x30, 0x0a, 0x20, 0x00, 0x00, 0x00, 0xfe,
143 	0x00, 0x73, 0x65, 0x72, 0x69, 0x6f, 0x0a, 0x20,
144 	0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x01, 0x4c,
145 
146 	0x02, 0x03, 0x28, 0xf1, 0x44, 0x61, 0x5f, 0x10,
147 	0x01, 0x23, 0x09, 0x07, 0x07, 0x83, 0x01, 0x00,
148 	0x00, 0x6b, 0x03, 0x0c, 0x00, 0x10, 0x00, 0x00,
149 	0x3c, 0x21, 0x00, 0x20, 0x01, 0x67, 0xd8, 0x5d,
150 	0xc4, 0x01, 0x78, 0x00, 0x00, 0xe2, 0x00, 0xca,
151 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
152 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
153 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
154 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
155 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
156 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
157 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
158 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
159 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
160 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
161 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x82,
162 };
163 
extron_send_byte(struct serio * serio,char byte)164 static int extron_send_byte(struct serio *serio, char byte)
165 {
166 	int err, i;
167 
168 	for (i = 0; i < 100; i++) {
169 		err = serio_write(serio, byte);
170 		if (!err)
171 			break;
172 		usleep_range(80, 120);
173 	}
174 	if (err)
175 		dev_warn(&serio->dev, "unable to write byte after 100 attempts\n");
176 	return err ? -EIO : 0;
177 }
178 
extron_send_len(struct serio * serio,const char * command,const unsigned char * bin,unsigned int len)179 static int extron_send_len(struct serio *serio, const char *command,
180 			   const unsigned char *bin, unsigned int len)
181 {
182 	int err = 0;
183 
184 	for (; !err && *command; command++)
185 		err = extron_send_byte(serio, *command);
186 	if (!err)
187 		err = extron_send_byte(serio, '\r');
188 	if (bin)
189 		for (; !err && len; len--)
190 			err = extron_send_byte(serio, *bin++);
191 	return err;
192 }
193 
extron_send_and_wait_len(struct extron * extron,struct extron_port * port,const char * cmd,const unsigned char * bin,unsigned int len,const char * response)194 static int extron_send_and_wait_len(struct extron *extron, struct extron_port *port,
195 				    const char *cmd, const unsigned char *bin,
196 				    unsigned int len, const char *response)
197 {
198 	int timeout = EXTRON_TIMEOUT_SECS * HZ;
199 	int err;
200 
201 	if (debug) {
202 		if (response)
203 			dev_info(extron->dev, "transmit %s (response: %s)\n",
204 				 cmd, response);
205 		else
206 			dev_info(extron->dev, "transmit %s\n", cmd);
207 	}
208 
209 	mutex_lock(&extron->serio_lock);
210 	if (port) {
211 		init_completion(&port->cmd_done);
212 		port->cmd_error = 0;
213 		port->response = response;
214 	} else {
215 		init_completion(&extron->cmd_done);
216 		extron->cmd_error = 0;
217 		extron->response = response;
218 	}
219 	err = extron_send_len(extron->serio, cmd, bin, len);
220 
221 	if (!err && response &&
222 	    !wait_for_completion_timeout(port ? &port->cmd_done : &extron->cmd_done, timeout)) {
223 		dev_info(extron->dev, "transmit %s failed with %s (expected: %s)\n",
224 			 cmd, extron->reply, response);
225 		err = -ETIMEDOUT;
226 	}
227 
228 	if (!err && response && (port ? port->cmd_error : extron->cmd_error)) {
229 		dev_info(extron->dev, "transmit %s failed with E%02u (expected: %s)\n",
230 			 cmd, port ? port->cmd_error : extron->cmd_error, response);
231 		if (port)
232 			port->cmd_error = 0;
233 		else
234 			extron->cmd_error = 0;
235 		err = -EPROTO;
236 	}
237 	if (port)
238 		port->response = NULL;
239 	else
240 		extron->response = NULL;
241 	mutex_unlock(&extron->serio_lock);
242 	return err;
243 }
244 
extron_send_and_wait(struct extron * extron,struct extron_port * port,const char * cmd,const char * response)245 static int extron_send_and_wait(struct extron *extron, struct extron_port *port,
246 				const char *cmd, const char *response)
247 {
248 	return extron_send_and_wait_len(extron, port, cmd, NULL, 0, response);
249 }
250 
extron_parse_edid(struct extron_port * port)251 static void extron_parse_edid(struct extron_port *port)
252 {
253 	const u8 *edid = port->edid;
254 	unsigned int i, end;
255 	u8 d;
256 
257 	port->has_4kp30 = false;
258 	port->has_4kp60 = false;
259 	port->has_qy = false;
260 	port->has_qs = false;
261 	/* Store Established Timings 1 and 2 */
262 	port->est_i = edid[0x23];
263 	port->est_ii = edid[0x24];
264 
265 	// Check DTDs in base block
266 	for (i = 0; i < 4; i++) {
267 		const u8 *dtd = edid + 0x36 + i * 18;
268 		unsigned int w, h;
269 		unsigned int mhz;
270 		u64 pclk;
271 
272 		if (!dtd[0] && !dtd[1])
273 			continue;
274 		w = dtd[2] + ((dtd[4] & 0xf0) << 4);
275 		h = dtd[5] + ((dtd[7] & 0xf0) << 4);
276 		if (w != 3840 || h != 2160)
277 			continue;
278 
279 		w += dtd[3] + ((dtd[4] & 0x0f) << 8);
280 		h += dtd[6] + ((dtd[7] & 0x0f) << 8);
281 		pclk = dtd[0] + (dtd[1] << 8);
282 		pclk *= 100000;
283 		mhz = div_u64(pclk, w * h);
284 		if (mhz >= 297)
285 			port->has_4kp30 = true;
286 		if (mhz >= 594)
287 			port->has_4kp60 = true;
288 	}
289 
290 	if (port->edid_blocks == 1)
291 		return;
292 
293 	edid += 128;
294 
295 	/* Return if not a CTA-861 extension block */
296 	if (edid[0] != 0x02 || edid[1] != 0x03)
297 		return;
298 
299 	/* search Video Data Block (tag 2) */
300 	d = edid[2] & 0x7f;
301 	/* Check if there are Data Blocks */
302 	if (d <= 4)
303 		return;
304 
305 	i = 4;
306 	end = d;
307 
308 	do {
309 		u8 tag = edid[i] >> 5;
310 		u8 len = edid[i] & 0x1f;
311 
312 		/* Avoid buffer overrun in case the EDID is malformed */
313 		if (i + len + 1 > 0x7f)
314 			return;
315 
316 		switch (tag) {
317 		case 2: /* Video Data Block */
318 			/* Search for VIC 97 */
319 			if (memchr(edid + i + 1, 97, len))
320 				port->has_4kp60 = true;
321 			/* Search for VIC 95 */
322 			if (memchr(edid + i + 1, 95, len))
323 				port->has_4kp30 = true;
324 			break;
325 
326 		case 7: /* Use Extended Tag */
327 			switch (edid[i + 1]) {
328 			case 0: /* Video Capability Data Block */
329 				if (edid[i + 2] & 0x80)
330 					port->has_qy = true;
331 				if (edid[i + 2] & 0x40)
332 					port->has_qs = true;
333 				break;
334 			}
335 			break;
336 		}
337 		i += len + 1;
338 	} while (i < end);
339 }
340 
get_edid_tag_location(const u8 * edid,unsigned int size,u8 want_tag,u8 ext_tag)341 static int get_edid_tag_location(const u8 *edid, unsigned int size,
342 				 u8 want_tag, u8 ext_tag)
343 {
344 	unsigned int offset = 128;
345 	int i, end;
346 	u8 d;
347 
348 	edid += offset;
349 
350 	/* Return if not a CTA-861 extension block */
351 	if (size < 256 || edid[0] != 0x02 || edid[1] != 0x03)
352 		return -ENOENT;
353 
354 	/* search tag */
355 	d = edid[0x02] & 0x7f;
356 	if (d <= 4)
357 		return -ENOENT;
358 
359 	i = 0x04;
360 	end = 0x00 + d;
361 
362 	do {
363 		unsigned char tag = edid[i] >> 5;
364 		unsigned char len = edid[i] & 0x1f;
365 
366 		if (tag != want_tag || i + len > end) {
367 			i += len + 1;
368 			continue;
369 		}
370 
371 		if (tag < 7 || (len >= 1 && edid[i + 1] == ext_tag))
372 			return offset + i;
373 		i += len + 1;
374 	} while (i < end);
375 	return -ENOENT;
376 }
377 
extron_edid_crc(u8 * edid)378 static void extron_edid_crc(u8 *edid)
379 {
380 	u8 sum = 0;
381 	int offset;
382 
383 	/* Update CRC */
384 	for (offset = 0; offset < 127; offset++)
385 		sum += edid[offset];
386 	edid[127] = 256 - sum;
387 }
388 
389 /*
390  * Fill in EDID string. As per VESA EDID-1.3, strings are at most 13 chars
391  * long. If shorter then add a 0x0a character after the string and pad the
392  * remainder with spaces.
393  */
extron_set_edid_string(u8 * start,const char * s)394 static void extron_set_edid_string(u8 *start, const char *s)
395 {
396 	const unsigned int max_len = 13;
397 	int len = strlen(s);
398 
399 	memset(start, ' ', max_len);
400 	if (len > max_len)
401 		len = max_len;
402 	memcpy(start, s, len);
403 	if (len < max_len)
404 		start[len] = 0x0a;
405 }
406 
extron_update_edid(struct extron_port * port,unsigned int blocks)407 static void extron_update_edid(struct extron_port *port, unsigned int blocks)
408 {
409 	int offset;
410 	u8 c1, c2;
411 
412 	c1 = ((manufacturer_name[0] - '@') << 2) |
413 		(((manufacturer_name[1] - '@') >> 3) & 0x03);
414 	c2 = (((manufacturer_name[1] - '@') & 0x07) << 5) |
415 		((manufacturer_name[2] - '@') & 0x1f);
416 
417 	port->edid_tmp[8] = c1;
418 	port->edid_tmp[9] = c2;
419 
420 	/* Set Established Timings, but always enable VGA */
421 	port->edid_tmp[0x23] = port->est_i | 0x20;
422 	port->edid_tmp[0x24] = port->est_ii;
423 
424 	/* Set the Monitor Name to the unit name */
425 	extron_set_edid_string(port->edid_tmp + 0x5f, port->extron->unit_name);
426 	/* Set the ASCII String to the CEC adapter name */
427 	extron_set_edid_string(port->edid_tmp + 0x71, port->adap->name);
428 
429 	extron_edid_crc(port->edid_tmp);
430 
431 	/* Find Video Capability Data Block */
432 	offset = get_edid_tag_location(port->edid_tmp, blocks * 128, 7, 0);
433 	if (offset > 0) {
434 		port->edid_tmp[offset + 2] &= ~0xc0;
435 		if (port->has_qy)
436 			port->edid_tmp[offset + 2] |= 0x80;
437 		if (port->has_qs)
438 			port->edid_tmp[offset + 2] |= 0x40;
439 	}
440 
441 	extron_edid_crc(port->edid_tmp + 128);
442 }
443 
extron_write_edid(struct extron_port * port,const u8 * edid,unsigned int blocks)444 static int extron_write_edid(struct extron_port *port,
445 			     const u8 *edid, unsigned int blocks)
446 {
447 	struct extron *extron = port->extron;
448 	u16 phys_addr = CEC_PHYS_ADDR_INVALID;
449 	int ret;
450 
451 	if (cec_get_edid_spa_location(edid, blocks * 128))
452 		phys_addr = 0;
453 
454 	if (mutex_lock_interruptible(&extron->edid_lock))
455 		return -EINTR;
456 
457 	memcpy(port->edid_tmp, edid, blocks * 128);
458 
459 	if (manufacturer_name[0])
460 		extron_update_edid(port, blocks);
461 
462 	ret = extron_send_and_wait_len(port->extron, port, "W+UF256,in.bin",
463 				       port->edid_tmp, sizeof(port->edid_tmp),
464 				       "Upl");
465 	if (ret)
466 		goto unlock;
467 	ret = extron_send_and_wait(port->extron, port, "WI1,in.binEDID",
468 				   "EdidI01");
469 	if (ret)
470 		goto unlock;
471 
472 	port->edid_blocks = blocks;
473 	memcpy(port->edid, port->edid_tmp, blocks * 128);
474 	port->read_edid = true;
475 	mutex_unlock(&extron->edid_lock);
476 
477 	cec_s_phys_addr(port->adap, phys_addr, false);
478 	return 0;
479 
480 unlock:
481 	mutex_unlock(&extron->edid_lock);
482 	return ret;
483 }
484 
update_edid_work(struct work_struct * w)485 static void update_edid_work(struct work_struct *w)
486 {
487 	struct extron *extron = container_of(w, struct extron,
488 					     work_update_edid.work);
489 	struct extron_port *in = extron->ports[extron->num_out_ports];
490 	struct extron_port *p;
491 	bool has_edid = false;
492 	bool has_4kp30 = true;
493 	bool has_4kp60 = true;
494 	bool has_qy = true;
495 	bool has_qs = true;
496 	u8 est_i = 0xff;
497 	u8 est_ii = 0xff;
498 	unsigned int out;
499 
500 	for (out = 0; has_4kp60 && out < extron->num_out_ports; out++) {
501 		p = extron->ports[out];
502 		if (p->read_edid) {
503 			has_4kp60 = p->has_4kp60;
504 			est_i &= p->est_i;
505 			est_ii &= p->est_ii;
506 			has_edid = true;
507 		}
508 	}
509 	for (out = 0; has_4kp30 && out < extron->num_out_ports; out++)
510 		if (extron->ports[out]->read_edid)
511 			has_4kp30 = extron->ports[out]->has_4kp30;
512 
513 	for (out = 0; has_qy && out < extron->num_out_ports; out++)
514 		if (extron->ports[out]->read_edid)
515 			has_qy = extron->ports[out]->has_qy;
516 
517 	for (out = 0; has_qs && out < extron->num_out_ports; out++)
518 		if (extron->ports[out]->read_edid)
519 			has_qs = extron->ports[out]->has_qs;
520 
521 	/* exit if no output port had an EDID */
522 	if (!has_edid)
523 		return;
524 
525 	/* exit if the input EDID properties remained unchanged */
526 	if (has_4kp60 == in->has_4kp60 && has_4kp30 == in->has_4kp30 &&
527 	    has_qy == in->has_qy && has_qs == in->has_qs &&
528 	    est_i == in->est_i && est_ii == in->est_ii)
529 		return;
530 
531 	in->has_4kp60 = has_4kp60;
532 	in->has_4kp30 = has_4kp30;
533 	in->has_qy = has_qy;
534 	in->has_qs = has_qs;
535 	in->est_i = est_i;
536 	in->est_ii = est_ii;
537 	extron_write_edid(extron->ports[extron->num_out_ports],
538 			  has_4kp60 ? hdmi_edid_4k_600 :
539 			  (has_4kp30 ? hdmi_edid_4k_300 : hdmi_edid), 2);
540 }
541 
extron_read_edid(struct extron_port * port)542 static void extron_read_edid(struct extron_port *port)
543 {
544 	struct extron *extron = port->extron;
545 	char cmd[10], reply[10];
546 	unsigned int idx;
547 
548 	idx = port->port.port + (port->is_input ? 0 : extron->num_in_ports);
549 	snprintf(cmd, sizeof(cmd), "WR%uEDID", idx);
550 	snprintf(reply, sizeof(reply), "EdidR%u", idx);
551 	if (mutex_lock_interruptible(&extron->edid_lock))
552 		return;
553 	if (port->read_edid)
554 		goto unlock;
555 	extron->edid_bytes_read = 0;
556 	extron->edid_port = port;
557 	port->edid_blocks = 0;
558 	if (!port->has_edid)
559 		goto no_edid;
560 
561 	extron->edid_reading = true;
562 
563 	if (!extron_send_and_wait(extron, port, cmd, reply))
564 		wait_for_completion_killable_timeout(&extron->edid_completion,
565 						     msecs_to_jiffies(1000));
566 	if (port->edid_blocks) {
567 		extron_parse_edid(port);
568 		port->read_edid = true;
569 		if (!port->is_input)
570 			v4l2_ctrl_s_ctrl(port->ctrl_tx_edid_present, 1);
571 	}
572 no_edid:
573 	extron->edid_reading = false;
574 unlock:
575 	mutex_unlock(&extron->edid_lock);
576 	cancel_delayed_work_sync(&extron->work_update_edid);
577 	if (manufacturer_name[0])
578 		schedule_delayed_work(&extron->work_update_edid,
579 				      msecs_to_jiffies(1000));
580 }
581 
extron_irq_work_handler(struct work_struct * work)582 static void extron_irq_work_handler(struct work_struct *work)
583 {
584 	struct extron_port *port =
585 		container_of(work, struct extron_port, irq_work);
586 	struct extron *extron = port->extron;
587 	unsigned long flags;
588 	bool update_pa;
589 	u16 pa;
590 	bool update_has_signal;
591 	bool has_signal;
592 	bool update_has_edid;
593 	bool has_edid;
594 	u32 status;
595 
596 	spin_lock_irqsave(&port->msg_lock, flags);
597 	while (port->rx_msg_num) {
598 		spin_unlock_irqrestore(&port->msg_lock, flags);
599 		cec_received_msg(port->adap,
600 				 &port->rx_msg[port->rx_msg_cur_idx]);
601 		spin_lock_irqsave(&port->msg_lock, flags);
602 		if (port->rx_msg_num)
603 			port->rx_msg_num--;
604 		port->rx_msg_cur_idx =
605 			(port->rx_msg_cur_idx + 1) % NUM_MSGS;
606 	}
607 	update_pa = port->update_phys_addr;
608 	pa = port->phys_addr;
609 	port->update_phys_addr = false;
610 	update_has_signal = port->update_has_signal;
611 	has_signal = port->has_signal;
612 	port->update_has_signal = false;
613 	update_has_edid = port->update_has_edid;
614 	has_edid = port->has_edid;
615 	port->update_has_edid = false;
616 	status = port->tx_done_status;
617 	port->tx_done_status = 0;
618 	spin_unlock_irqrestore(&port->msg_lock, flags);
619 
620 	if (status)
621 		cec_transmit_done(port->adap, status, 0, 0, 0, 0);
622 
623 	if (update_has_signal && port->is_input)
624 		v4l2_ctrl_s_ctrl(port->ctrl_rx_power_present, has_signal);
625 
626 	if (update_has_edid && !port->is_input) {
627 		v4l2_ctrl_s_ctrl(port->ctrl_tx_hotplug,
628 				 port->has_edid);
629 		if (port->has_edid) {
630 			port->port.found_sink = true;
631 			port->port.lost_sink_ts = ktime_set(0, 0);
632 		} else {
633 			port->port.lost_sink_ts = ktime_get();
634 		}
635 		if (!has_edid) {
636 			port->edid_blocks = 0;
637 			port->read_edid = false;
638 			if (extron->edid_reading && !has_edid &&
639 			    extron->edid_port == port)
640 				extron->edid_reading = false;
641 			v4l2_ctrl_s_ctrl(port->ctrl_tx_edid_present, 0);
642 		} else if (!extron->edid_reading || extron->edid_port != port) {
643 			extron_read_edid(port);
644 		}
645 	}
646 	if (update_pa)
647 		cec_s_phys_addr(port->adap, pa, false);
648 }
649 
extron_process_received(struct extron_port * port,const char * data)650 static void extron_process_received(struct extron_port *port, const char *data)
651 {
652 	struct cec_msg msg = {};
653 	unsigned int len = strlen(data);
654 	unsigned long irq_flags;
655 	unsigned int idx;
656 
657 	if (!port || port->disconnected)
658 		return;
659 
660 	if (len < 5 || (len - 2) % 3 || data[len - 2] != '*')
661 		goto malformed;
662 
663 	while (*data != '*') {
664 		int v = hex2bin(&msg.msg[msg.len], data + 1, 1);
665 
666 		if (*data != '%' || v)
667 			goto malformed;
668 		msg.len++;
669 		data += 3;
670 	}
671 
672 	spin_lock_irqsave(&port->msg_lock, irq_flags);
673 	idx = (port->rx_msg_cur_idx + port->rx_msg_num) %
674 		NUM_MSGS;
675 	if (port->rx_msg_num == NUM_MSGS) {
676 		dev_warn(port->dev,
677 			 "message queue is full, dropping %*ph\n",
678 			 msg.len, msg.msg);
679 		spin_unlock_irqrestore(&port->msg_lock,
680 				       irq_flags);
681 		return;
682 	}
683 	port->rx_msg_num++;
684 	port->rx_msg[idx] = msg;
685 	spin_unlock_irqrestore(&port->msg_lock, irq_flags);
686 	if (!port->disconnected)
687 		schedule_work(&port->irq_work);
688 	return;
689 
690 malformed:
691 	dev_info(port->extron->dev, "malformed msg received: '%s'\n", data);
692 }
693 
extron_port_signal_change(struct extron_port * port,bool has_sig)694 static void extron_port_signal_change(struct extron_port *port, bool has_sig)
695 {
696 	unsigned long irq_flags;
697 	bool update = false;
698 
699 	if (!port)
700 		return;
701 
702 	spin_lock_irqsave(&port->msg_lock, irq_flags);
703 	if (!port->update_has_signal && port->has_signal != has_sig) {
704 		port->update_has_signal = true;
705 		update = true;
706 	}
707 	port->has_signal = has_sig;
708 	spin_unlock_irqrestore(&port->msg_lock, irq_flags);
709 	if (update && !port->disconnected)
710 		schedule_work(&port->irq_work);
711 }
712 
extron_process_signal_change(struct extron * extron,const char * data)713 static void extron_process_signal_change(struct extron *extron, const char *data)
714 {
715 	unsigned int i;
716 
717 	extron_port_signal_change(extron->ports[extron->num_out_ports],
718 				  data[0] == '1');
719 	for (i = 0; i < extron->num_out_ports; i++)
720 		extron_port_signal_change(extron->ports[i],
721 					  data[2 + 2 * i] != '0');
722 }
723 
extron_port_edid_change(struct extron_port * port,bool has_edid)724 static void extron_port_edid_change(struct extron_port *port, bool has_edid)
725 {
726 	unsigned long irq_flags;
727 	bool update = false;
728 
729 	if (!port)
730 		return;
731 
732 	spin_lock_irqsave(&port->msg_lock, irq_flags);
733 	if (!port->update_has_edid && port->has_edid != has_edid) {
734 		port->update_has_edid = true;
735 		update = true;
736 	}
737 	port->has_edid = has_edid;
738 	spin_unlock_irqrestore(&port->msg_lock, irq_flags);
739 	if (update && !port->disconnected)
740 		schedule_work(&port->irq_work);
741 }
742 
extron_process_edid_change(struct extron * extron,const char * data)743 static void extron_process_edid_change(struct extron *extron, const char *data)
744 {
745 	unsigned int i;
746 
747 	/*
748 	 * Do nothing if the Extron isn't ready yet. Trying to do this
749 	 * while the Extron firmware is still settling will fail.
750 	 */
751 	if (!extron->is_ready)
752 		return;
753 
754 	for (i = 0; i < extron->num_out_ports; i++)
755 		extron_port_edid_change(extron->ports[i],
756 					data[2 + 2 * i] != '0');
757 }
758 
extron_phys_addr_change(struct extron_port * port,u16 pa)759 static void extron_phys_addr_change(struct extron_port *port, u16 pa)
760 {
761 	unsigned long irq_flags;
762 	bool update = false;
763 
764 	if (!port)
765 		return;
766 
767 	spin_lock_irqsave(&port->msg_lock, irq_flags);
768 	if (!port->update_phys_addr && port->phys_addr != pa) {
769 		update = true;
770 		port->update_phys_addr = true;
771 	}
772 	port->phys_addr = pa;
773 	spin_unlock_irqrestore(&port->msg_lock, irq_flags);
774 	if (update && !port->disconnected)
775 		schedule_work(&port->irq_work);
776 }
777 
extron_process_tx_done(struct extron_port * port,char status)778 static void extron_process_tx_done(struct extron_port *port, char status)
779 {
780 	unsigned long irq_flags;
781 	unsigned int tx_status;
782 
783 	if (!port)
784 		return;
785 
786 	switch (status) {
787 	case '0':
788 		tx_status = CEC_TX_STATUS_NACK | CEC_TX_STATUS_MAX_RETRIES;
789 		break;
790 	case '1':
791 		tx_status = CEC_TX_STATUS_OK;
792 		break;
793 	default:
794 		tx_status = CEC_TX_STATUS_ERROR;
795 		break;
796 	}
797 	spin_lock_irqsave(&port->msg_lock, irq_flags);
798 	port->tx_done_status = tx_status;
799 	spin_unlock_irqrestore(&port->msg_lock, irq_flags);
800 	if (!port->disconnected)
801 		schedule_work(&port->irq_work);
802 }
803 
extron_add_edid(struct extron_port * port,const char * hex)804 static void extron_add_edid(struct extron_port *port, const char *hex)
805 {
806 	struct extron *extron = port ? port->extron : NULL;
807 
808 	if (!port || port != extron->edid_port)
809 		return;
810 	while (extron->edid_bytes_read < sizeof(port->edid) && *hex) {
811 		int err = hex2bin(&port->edid[extron->edid_bytes_read], hex, 1);
812 
813 		if (err) {
814 			extron->edid_reading = false;
815 			complete(&extron->edid_completion);
816 			break;
817 		}
818 		extron->edid_bytes_read++;
819 		hex += 2;
820 	}
821 	if (extron->edid_bytes_read == 128 &&
822 	    port->edid[126] == 0) {
823 		/* There are no extension blocks, we're done */
824 		port->edid_blocks = 1;
825 		extron->edid_reading = false;
826 		complete(&extron->edid_completion);
827 	}
828 	if (extron->edid_bytes_read < sizeof(port->edid))
829 		return;
830 	if (!*hex)
831 		port->edid_blocks = 2;
832 	extron->edid_reading = false;
833 	complete(&extron->edid_completion);
834 }
835 
extron_interrupt(struct serio * serio,unsigned char data,unsigned int flags)836 static irqreturn_t extron_interrupt(struct serio *serio, unsigned char data,
837 				    unsigned int flags)
838 {
839 	struct extron *extron = serio_get_drvdata(serio);
840 	struct extron_port *port = NULL;
841 	bool found_response;
842 	unsigned int p;
843 
844 	if (data == '\r' || data == '\n') {
845 		if (extron->idx == 0)
846 			return IRQ_HANDLED;
847 		memcpy(extron->data, extron->buf, extron->idx);
848 		extron->len = extron->idx;
849 		extron->data[extron->len] = 0;
850 		if (debug)
851 			dev_info(extron->dev, "received %s\n", extron->data);
852 		extron->idx = 0;
853 		if (!memcmp(extron->data, "Sig", 3) &&
854 		    extron->data[4] == '*') {
855 			extron_process_signal_change(extron, extron->data + 3);
856 		} else if (!memcmp(extron->data, "Hdcp", 4) &&
857 			   extron->data[5] == '*') {
858 			extron_process_edid_change(extron, extron->data + 4);
859 		} else if (!memcmp(extron->data, "DcecI", 5) &&
860 			   extron->data[5] >= '1' &&
861 			   extron->data[5] < '1' + extron->num_in_ports) {
862 			unsigned int p = extron->data[5] - '1';
863 
864 			p += extron->num_out_ports;
865 			extron_process_tx_done(extron->ports[p],
866 					       extron->data[extron->len - 1]);
867 		} else if (!memcmp(extron->data, "Ceci", 4) &&
868 			   extron->data[4] >= '1' &&
869 			   extron->data[4] < '1' + extron->num_in_ports &&
870 			   extron->data[5] == '*') {
871 			unsigned int p = extron->data[4] - '1';
872 
873 			p += extron->num_out_ports;
874 			extron_process_received(extron->ports[p],
875 						extron->data + 6);
876 		} else if (!memcmp(extron->data, "DcecO", 5) &&
877 			   extron->data[5] >= '1' &&
878 			   extron->data[5] < '1' + extron->num_out_ports) {
879 			unsigned int p = extron->data[5] - '1';
880 
881 			extron_process_tx_done(extron->ports[p],
882 					       extron->data[extron->len - 1]);
883 		} else if (!memcmp(extron->data, "Ceco", 4) &&
884 			   extron->data[4] >= '1' &&
885 			   extron->data[4] < '1' + extron->num_out_ports &&
886 			   extron->data[5] == '*') {
887 			unsigned int p = extron->data[4] - '1';
888 
889 			extron_process_received(extron->ports[p],
890 						extron->data + 6);
891 		} else if (!memcmp(extron->data, "Pceco", 5) &&
892 			   extron->data[5] >= '1' &&
893 			   extron->data[5] < '1' + extron->num_out_ports) {
894 			unsigned int p = extron->data[5] - '1';
895 			unsigned int tmp_pa[2] = { 0xff, 0xff };
896 
897 			if (sscanf(extron->data + 7, "%%%02x%%%02x",
898 				   &tmp_pa[0], &tmp_pa[1]) == 2)
899 				extron_phys_addr_change(extron->ports[p],
900 							tmp_pa[0] << 8 | tmp_pa[1]);
901 		} else if (!memcmp(extron->data, "Pceci", 5) &&
902 			   extron->data[5] >= '1' &&
903 			   extron->data[5] < '1' + extron->num_in_ports) {
904 			unsigned int p = extron->data[5] - '1';
905 			unsigned int tmp_pa[2] = { 0xff, 0xff };
906 
907 			p += extron->num_out_ports;
908 			if (sscanf(extron->data + 7, "%%%02x%%%02x",
909 				   &tmp_pa[0], &tmp_pa[1]) == 2)
910 				extron_phys_addr_change(extron->ports[p],
911 							tmp_pa[0] << 8 | tmp_pa[1]);
912 		} else if (!memcmp(extron->data, "EdidR", 5) &&
913 			   extron->data[5] >= '1' &&
914 			   extron->data[5] < '1' + extron->num_ports &&
915 			   extron->data[6] == '*') {
916 			unsigned int p = extron->data[5] - '1';
917 
918 			if (p)
919 				p--;
920 			else
921 				p = extron->num_out_ports;
922 			extron_add_edid(extron->ports[p], extron->data + 7);
923 		} else if (extron->edid_reading && extron->len == 32 &&
924 			   extron->edid_port) {
925 			extron_add_edid(extron->edid_port, extron->data);
926 		}
927 
928 		found_response = false;
929 		if (extron->response &&
930 		    !strncmp(extron->response, extron->data,
931 			     strlen(extron->response)))
932 			found_response = true;
933 
934 		for (p = 0; !found_response && p < extron->num_ports; p++) {
935 			port = extron->ports[p];
936 			if (port && port->response &&
937 			    !strncmp(port->response, extron->data,
938 				     strlen(port->response)))
939 				found_response = true;
940 		}
941 
942 		if (!found_response && extron->response &&
943 		    extron->data[0] == 'E' &&
944 		    isdigit(extron->data[1]) &&
945 		    isdigit(extron->data[2]) &&
946 		    !extron->data[3]) {
947 			extron->cmd_error = (extron->data[1] - '0') * 10 +
948 				extron->data[2] - '0';
949 			extron->response = NULL;
950 			complete(&extron->cmd_done);
951 		}
952 
953 		if (!found_response)
954 			return IRQ_HANDLED;
955 
956 		memcpy(extron->reply, extron->data, extron->len);
957 		extron->reply[extron->len] = 0;
958 		if (!port) {
959 			extron->response = NULL;
960 			complete(&extron->cmd_done);
961 		} else {
962 			port->response = NULL;
963 			complete(&port->cmd_done);
964 		}
965 		return IRQ_HANDLED;
966 	}
967 
968 	if (extron->idx >= DATA_SIZE - 1) {
969 		dev_info(extron->dev,
970 			 "throwing away %d bytes of garbage\n", extron->idx);
971 		extron->idx = 0;
972 	}
973 	extron->buf[extron->idx++] = (char)data;
974 	return IRQ_HANDLED;
975 }
976 
extron_cec_adap_enable(struct cec_adapter * adap,bool enable)977 static int extron_cec_adap_enable(struct cec_adapter *adap, bool enable)
978 {
979 	struct extron_port *port = cec_get_drvdata(adap);
980 
981 	return (port->disconnected && enable) ? -ENODEV : 0;
982 }
983 
extron_cec_adap_log_addr(struct cec_adapter * adap,u8 log_addr)984 static int extron_cec_adap_log_addr(struct cec_adapter *adap, u8 log_addr)
985 {
986 	struct extron_port *port = cec_get_drvdata(adap);
987 	char cmd[26];
988 	char resp[25];
989 	u8 la = log_addr == CEC_LOG_ADDR_INVALID ? 15 : log_addr;
990 	int err;
991 
992 	if (port->disconnected)
993 		return -ENODEV;
994 	snprintf(cmd, sizeof(cmd), "W%c%u*%uLCEC",
995 		 port->direction, port->port.port, la);
996 	snprintf(resp, sizeof(resp), "Lcec%c%u*%u",
997 		 port->direction, port->port.port, la);
998 	err = extron_send_and_wait(port->extron, port, cmd, resp);
999 	return log_addr != CEC_LOG_ADDR_INVALID && err ? err : 0;
1000 }
1001 
extron_cec_adap_transmit(struct cec_adapter * adap,u8 attempts,u32 signal_free_time,struct cec_msg * msg)1002 static int extron_cec_adap_transmit(struct cec_adapter *adap, u8 attempts,
1003 				    u32 signal_free_time, struct cec_msg *msg)
1004 {
1005 	struct extron_port *port = cec_get_drvdata(adap);
1006 	char buf[(CEC_MAX_MSG_SIZE - 1) * 3 + 1];
1007 	char cmd[sizeof(buf) + 14];
1008 	unsigned int i;
1009 
1010 	if (port->disconnected)
1011 		return -ENODEV;
1012 	buf[0] = 0;
1013 	for (i = 0; i < msg->len - 1; i++)
1014 		sprintf(buf + i * 3, "%%%02X", msg->msg[i + 1]);
1015 	snprintf(cmd, sizeof(cmd), "W%c%u*%u*%u*%sDCEC",
1016 		 port->direction, port->port.port,
1017 		 cec_msg_initiator(msg), cec_msg_destination(msg), buf);
1018 	return extron_send_and_wait(port->extron, port, cmd, NULL);
1019 }
1020 
extron_cec_adap_unconfigured(struct cec_adapter * adap)1021 static void extron_cec_adap_unconfigured(struct cec_adapter *adap)
1022 {
1023 	struct extron_port *port = cec_get_drvdata(adap);
1024 
1025 	if (port->disconnected)
1026 		return;
1027 	if (debug)
1028 		dev_info(port->extron->dev, "unconfigured port %d (%s)\n",
1029 			 port->port.port,
1030 			 port->extron->splitter.is_standby ? "Off" : "On");
1031 	if (!port->is_input)
1032 		cec_splitter_unconfigured_output(&port->port);
1033 }
1034 
extron_cec_configured(struct cec_adapter * adap)1035 static void extron_cec_configured(struct cec_adapter *adap)
1036 {
1037 	struct extron_port *port = cec_get_drvdata(adap);
1038 
1039 	if (port->disconnected)
1040 		return;
1041 	if (debug)
1042 		dev_info(port->extron->dev, "configured port %d (%s)\n",
1043 			 port->port.port,
1044 			 port->extron->splitter.is_standby ? "Off" : "On");
1045 	if (!port->is_input)
1046 		cec_splitter_configured_output(&port->port);
1047 }
1048 
extron_cec_adap_nb_transmit_canceled(struct cec_adapter * adap,const struct cec_msg * msg)1049 static void extron_cec_adap_nb_transmit_canceled(struct cec_adapter *adap,
1050 						 const struct cec_msg *msg)
1051 {
1052 	struct extron_port *port = cec_get_drvdata(adap);
1053 	struct cec_adapter *input_adap;
1054 
1055 	if (!vendor_id)
1056 		return;
1057 	if (port->disconnected || port->is_input)
1058 		return;
1059 	input_adap = port->extron->ports[port->extron->num_out_ports]->adap;
1060 	cec_splitter_nb_transmit_canceled_output(&port->port, msg, input_adap);
1061 }
1062 
extron_received(struct cec_adapter * adap,struct cec_msg * msg)1063 static int extron_received(struct cec_adapter *adap, struct cec_msg *msg)
1064 {
1065 	struct extron_port *port = cec_get_drvdata(adap);
1066 
1067 	if (!vendor_id)
1068 		return -ENOMSG;
1069 	if (port->disconnected)
1070 		return -ENOMSG;
1071 	if (port->is_input)
1072 		return cec_splitter_received_input(&port->port, msg);
1073 	return cec_splitter_received_output(&port->port, msg,
1074 					    port->extron->ports[port->extron->num_out_ports]->adap);
1075 }
1076 
1077 #define log_printf(adap, file, fmt, arg...) \
1078 	do { \
1079 		if (file) \
1080 			seq_printf((file), fmt, ## arg); \
1081 		else \
1082 			pr_info("cec-%s: " fmt, (adap)->name, ## arg);	\
1083 	} while (0)
1084 
1085 static const char * const pwr_state[] = {
1086 	"on",
1087 	"standby",
1088 	"to on",
1089 	"to standby",
1090 };
1091 
extron_adap_status_port(struct extron_port * port,struct seq_file * file)1092 static void extron_adap_status_port(struct extron_port *port, struct seq_file *file)
1093 {
1094 	struct cec_adapter *adap = port->adap;
1095 
1096 	if (port->disconnected) {
1097 		log_printf(adap, file,
1098 			   "\tport %u: disconnected\n", port->port.port);
1099 		return;
1100 	}
1101 	if (port->is_input)
1102 		log_printf(adap, file,
1103 			   "\tport %u: %s signal, %s edid, %s 4kp30, %s 4kp60, %sQS/%sQY, is %s\n",
1104 			   port->port.port,
1105 			   port->has_signal ? "has" : "no",
1106 			   port->has_edid ? "has" : "no",
1107 			   port->has_4kp30 ? "has" : "no",
1108 			   port->has_4kp60 ? "has" : "no",
1109 			   port->has_qs ? "" : "no ",
1110 			   port->has_qy ? "" : "no ",
1111 			   !port->port.adap->is_configured ? "not configured" :
1112 				pwr_state[port->extron->splitter.is_standby]);
1113 	else
1114 		log_printf(adap, file,
1115 			   "\tport %u: %s sink, %s signal, %s edid, %s 4kp30, %s 4kp60, %sQS/%sQY, is %sactive source, is %s\n",
1116 			   port->port.port,
1117 			   port->port.found_sink ? "found" : "no",
1118 			   port->has_signal ? "has" : "no",
1119 			   port->has_edid ? "has" : "no",
1120 			   port->has_4kp30 ? "has" : "no",
1121 			   port->has_4kp60 ? "has" : "no",
1122 			   port->has_qs ? "" : "no ",
1123 			   port->has_qy ? "" : "no ",
1124 			   port->port.is_active_source ? "" : "not ",
1125 			   !port->port.adap->is_configured ? "not configured" :
1126 			   pwr_state[port->port.power_status & 3]);
1127 	if (port->port.out_give_device_power_status_seq)
1128 		log_printf(adap, file,
1129 			   "\tport %u: querying power status (%u, %lldms)\n",
1130 			   port->port.port,
1131 			   port->port.out_give_device_power_status_seq & ~(1 << 31),
1132 			   ktime_ms_delta(ktime_get(),
1133 					  port->port.out_give_device_power_status_ts));
1134 	if (port->port.out_request_current_latency_seq)
1135 		log_printf(adap, file,
1136 			   "\tport %u: querying latency (%u, %lldms)\n",
1137 			   port->port.port,
1138 			   port->port.out_request_current_latency_seq & ~(1 << 31),
1139 			   ktime_ms_delta(ktime_get(),
1140 					  port->port.out_request_current_latency_ts));
1141 }
1142 
extron_adap_status(struct cec_adapter * adap,struct seq_file * file)1143 static void extron_adap_status(struct cec_adapter *adap, struct seq_file *file)
1144 {
1145 	struct extron_port *port = cec_get_drvdata(adap);
1146 	struct extron *extron = port->extron;
1147 	unsigned int i;
1148 
1149 	log_printf(adap, file, "name: %s type: %s\n",
1150 		   extron->unit_name, extron->unit_type);
1151 	log_printf(adap, file, "model: 60-160%c-01 (1 input, %u outputs)\n",
1152 		   '6' + extron->num_out_ports / 2, extron->num_out_ports);
1153 	log_printf(adap, file, "firmware version: %s CEC engine version: %s\n",
1154 		   extron->unit_fw_version, extron->unit_cec_engine_version);
1155 	if (extron->hpd_never_low)
1156 		log_printf(adap, file, "always keep input HPD high\n");
1157 	else
1158 		log_printf(adap, file,
1159 			   "pull input HPD low if all output HPDs are low\n");
1160 	if (vendor_id)
1161 		log_printf(adap, file,
1162 			   "splitter vendor ID: 0x%06x\n", vendor_id);
1163 	if (manufacturer_name[0])
1164 		log_printf(adap, file, "splitter manufacturer name: %s\n",
1165 			   manufacturer_name);
1166 	log_printf(adap, file, "splitter power status: %s\n",
1167 		   pwr_state[extron->splitter.is_standby]);
1168 	log_printf(adap, file, "%s port: %d (%s)\n",
1169 		   port->is_input ? "input" : "output",
1170 		   port->port.port, port->name);
1171 	log_printf(adap, file, "splitter input port:\n");
1172 	extron_adap_status_port(extron->ports[extron->num_out_ports], file);
1173 
1174 	log_printf(adap, file, "splitter output ports:\n");
1175 	for (i = 0; i < extron->num_out_ports; i++)
1176 		extron_adap_status_port(extron->ports[i], file);
1177 
1178 	if (!port->has_edid || !port->read_edid)
1179 		return;
1180 
1181 	for (i = 0; i < port->edid_blocks * 128; i += 16) {
1182 		if (i % 128 == 0)
1183 			log_printf(adap, file, "\n");
1184 		log_printf(adap, file, "EDID: %*ph\n", 16, port->edid + i);
1185 	}
1186 }
1187 
1188 static const struct cec_adap_ops extron_cec_adap_ops = {
1189 	.adap_enable = extron_cec_adap_enable,
1190 	.adap_log_addr = extron_cec_adap_log_addr,
1191 	.adap_transmit = extron_cec_adap_transmit,
1192 	.adap_nb_transmit_canceled = extron_cec_adap_nb_transmit_canceled,
1193 	.adap_unconfigured = extron_cec_adap_unconfigured,
1194 	.adap_status = extron_adap_status,
1195 	.configured = extron_cec_configured,
1196 	.received = extron_received,
1197 };
1198 
extron_querycap(struct file * file,void * priv,struct v4l2_capability * cap)1199 static int extron_querycap(struct file *file, void *priv,
1200 			   struct v4l2_capability *cap)
1201 {
1202 	struct extron_port *port = video_drvdata(file);
1203 
1204 	strscpy(cap->driver, "extron-da-hd-4k-plus-cec", sizeof(cap->driver));
1205 	strscpy(cap->card, cap->driver, sizeof(cap->card));
1206 	snprintf(cap->bus_info, sizeof(cap->bus_info), "serio:%s", port->name);
1207 	return 0;
1208 }
1209 
extron_enum_input(struct file * file,void * priv,struct v4l2_input * inp)1210 static int extron_enum_input(struct file *file, void *priv, struct v4l2_input *inp)
1211 {
1212 	struct extron_port *port = video_drvdata(file);
1213 
1214 	if (inp->index)
1215 		return -EINVAL;
1216 	inp->type = V4L2_INPUT_TYPE_CAMERA;
1217 	snprintf(inp->name, sizeof(inp->name), "HDMI IN %u", port->port.port);
1218 	inp->status = v4l2_ctrl_g_ctrl(port->ctrl_rx_power_present) ?
1219 		0 : V4L2_IN_ST_NO_SIGNAL;
1220 	return 0;
1221 }
1222 
extron_g_input(struct file * file,void * priv,unsigned int * i)1223 static int extron_g_input(struct file *file, void *priv, unsigned int *i)
1224 {
1225 	*i = 0;
1226 	return 0;
1227 }
1228 
extron_s_input(struct file * file,void * priv,unsigned int i)1229 static int extron_s_input(struct file *file, void *priv, unsigned int i)
1230 {
1231 	return i ? -EINVAL : 0;
1232 }
1233 
extron_enum_output(struct file * file,void * priv,struct v4l2_output * out)1234 static int extron_enum_output(struct file *file, void *priv, struct v4l2_output *out)
1235 {
1236 	struct extron_port *port = video_drvdata(file);
1237 
1238 	if (out->index)
1239 		return -EINVAL;
1240 	out->type = V4L2_OUTPUT_TYPE_ANALOG;
1241 	snprintf(out->name, sizeof(out->name), "HDMI OUT %u", port->port.port);
1242 	return 0;
1243 }
1244 
extron_g_output(struct file * file,void * priv,unsigned int * o)1245 static int extron_g_output(struct file *file, void *priv, unsigned int *o)
1246 {
1247 	*o = 0;
1248 	return 0;
1249 }
1250 
extron_s_output(struct file * file,void * priv,unsigned int o)1251 static int extron_s_output(struct file *file, void *priv, unsigned int o)
1252 {
1253 	return o ? -EINVAL : 0;
1254 }
1255 
extron_g_edid(struct file * file,void * priv,struct v4l2_edid * edid)1256 static int extron_g_edid(struct file *file, void *priv,
1257 			 struct v4l2_edid *edid)
1258 {
1259 	struct extron_port *port = video_drvdata(file);
1260 
1261 	memset(edid->reserved, 0, sizeof(edid->reserved));
1262 	if (port->disconnected)
1263 		return -ENODEV;
1264 	if (edid->pad)
1265 		return -EINVAL;
1266 	if (!port->has_edid)
1267 		return -ENODATA;
1268 	if (!port->read_edid)
1269 		extron_read_edid(port);
1270 	if (!port->read_edid)
1271 		return -ENODATA;
1272 	if (edid->start_block == 0 && edid->blocks == 0) {
1273 		edid->blocks = port->edid_blocks;
1274 		return 0;
1275 	}
1276 	if (edid->start_block >= port->edid_blocks)
1277 		return -EINVAL;
1278 	if (edid->blocks > port->edid_blocks - edid->start_block)
1279 		edid->blocks = port->edid_blocks - edid->start_block;
1280 	memcpy(edid->edid, port->edid + edid->start_block * 128, edid->blocks * 128);
1281 	return 0;
1282 }
1283 
extron_s_edid(struct file * file,void * priv,struct v4l2_edid * edid)1284 static int extron_s_edid(struct file *file, void *priv, struct v4l2_edid *edid)
1285 {
1286 	struct extron_port *port = video_drvdata(file);
1287 
1288 	memset(edid->reserved, 0, sizeof(edid->reserved));
1289 	if (port->disconnected)
1290 		return -ENODEV;
1291 	if (edid->pad)
1292 		return -EINVAL;
1293 
1294 	/* Unfortunately it is not possible to clear the EDID */
1295 	if (edid->blocks == 0)
1296 		return -EINVAL;
1297 
1298 	if (edid->blocks > MAX_EDID_BLOCKS) {
1299 		edid->blocks = MAX_EDID_BLOCKS;
1300 		return -E2BIG;
1301 	}
1302 
1303 	if (cec_get_edid_spa_location(edid->edid, edid->blocks * 128))
1304 		v4l2_set_edid_phys_addr(edid->edid, edid->blocks * 128, 0);
1305 	extron_parse_edid(port);
1306 	return extron_write_edid(port, edid->edid, edid->blocks);
1307 }
1308 
extron_log_status(struct file * file,void * priv)1309 static int extron_log_status(struct file *file, void *priv)
1310 {
1311 	struct extron_port *port = video_drvdata(file);
1312 
1313 	extron_adap_status(port->adap, NULL);
1314 	return v4l2_ctrl_log_status(file, priv);
1315 }
1316 
1317 static const struct v4l2_ioctl_ops extron_ioctl_ops = {
1318 	.vidioc_querycap		= extron_querycap,
1319 	.vidioc_enum_input		= extron_enum_input,
1320 	.vidioc_g_input			= extron_g_input,
1321 	.vidioc_s_input			= extron_s_input,
1322 	.vidioc_enum_output		= extron_enum_output,
1323 	.vidioc_g_output		= extron_g_output,
1324 	.vidioc_s_output		= extron_s_output,
1325 	.vidioc_g_edid			= extron_g_edid,
1326 	.vidioc_s_edid			= extron_s_edid,
1327 	.vidioc_log_status		= extron_log_status,
1328 	.vidioc_subscribe_event		= v4l2_ctrl_subscribe_event,
1329 	.vidioc_unsubscribe_event	= v4l2_event_unsubscribe,
1330 };
1331 
1332 static const struct v4l2_file_operations extron_fops = {
1333 	.owner		= THIS_MODULE,
1334 	.open		= v4l2_fh_open,
1335 	.release	= v4l2_fh_release,
1336 	.poll		= v4l2_ctrl_poll,
1337 	.unlocked_ioctl	= video_ioctl2,
1338 };
1339 
1340 static const struct video_device extron_videodev = {
1341 	.name		= "extron-da-hd-4k-plus-cec",
1342 	.vfl_dir	= VFL_DIR_RX,
1343 	.fops		= &extron_fops,
1344 	.ioctl_ops	= &extron_ioctl_ops,
1345 	.minor		= -1,
1346 	.release	= video_device_release_empty,
1347 };
1348 
extron_disconnect(struct serio * serio)1349 static void extron_disconnect(struct serio *serio)
1350 {
1351 	struct extron *extron = serio_get_drvdata(serio);
1352 	unsigned int p;
1353 
1354 	kthread_stop(extron->kthread_setup);
1355 
1356 	for (p = 0; p < extron->num_ports; p++) {
1357 		struct extron_port *port = extron->ports[p];
1358 
1359 		if (!port)
1360 			continue;
1361 		port->disconnected = true;
1362 		cancel_work_sync(&port->irq_work);
1363 	}
1364 	cancel_delayed_work_sync(&extron->work_update_edid);
1365 	for (p = 0; p < extron->num_ports; p++) {
1366 		struct extron_port *port = extron->ports[p];
1367 
1368 		if (!port)
1369 			continue;
1370 
1371 		if (port->cec_was_registered) {
1372 			if (cec_is_registered(port->adap))
1373 				cec_unregister_adapter(port->adap);
1374 			/*
1375 			 * After registering the adapter, the
1376 			 * extron_setup_thread() function took an extra
1377 			 * reference to the device. We call the corresponding
1378 			 * put here.
1379 			 */
1380 			cec_put_device(port->adap);
1381 		} else {
1382 			cec_delete_adapter(port->adap);
1383 		}
1384 		video_unregister_device(&port->vdev);
1385 	}
1386 
1387 	complete(&extron->edid_completion);
1388 
1389 	for (p = 0; p < extron->num_ports; p++) {
1390 		struct extron_port *port = extron->ports[p];
1391 
1392 		if (!port)
1393 			continue;
1394 		v4l2_ctrl_handler_free(&port->hdl);
1395 		mutex_destroy(&port->video_lock);
1396 		kfree(port);
1397 	}
1398 	mutex_destroy(&extron->edid_lock);
1399 	mutex_destroy(&extron->serio_lock);
1400 	extron->serio = NULL;
1401 	serio_set_drvdata(serio, NULL);
1402 	serio_close(serio);
1403 }
1404 
extron_setup(struct extron * extron)1405 static int extron_setup(struct extron *extron)
1406 {
1407 	struct serio *serio = extron->serio;
1408 	struct extron_port *port;
1409 	u8 *reply = extron->reply;
1410 	unsigned int p;
1411 	unsigned int major, minor;
1412 	int err;
1413 
1414 	/*
1415 	 * Attempt to disable CEC: avoid received CEC messages
1416 	 * from interfering with the other serial port traffic.
1417 	 */
1418 	extron_send_and_wait(extron, NULL, "WI1*0CCEC", NULL);
1419 	extron_send_and_wait(extron, NULL, "WO0*CCEC", NULL);
1420 
1421 	/* Obtain unit part number */
1422 	err = extron_send_and_wait(extron, NULL, "N", "Pno");
1423 	if (err)
1424 		return err;
1425 	dev_info(extron->dev, "Unit part number: %s\n", reply + 3);
1426 	if (strcmp(reply + 3, "60-1607-01") &&
1427 	    strcmp(reply + 3, "60-1608-01") &&
1428 	    strcmp(reply + 3, "60-1609-01")) {
1429 		dev_err(extron->dev, "Unsupported model\n");
1430 		return -ENODEV;
1431 	}
1432 	/* Up to 6 output ports and one input port */
1433 	extron->num_out_ports = 2 * (reply[9] - '6');
1434 	extron->splitter.num_out_ports = extron->num_out_ports;
1435 	extron->splitter.ports = extron->splitter_ports;
1436 	extron->splitter.dev = extron->dev;
1437 	extron->num_in_ports = 1;
1438 	extron->num_ports = extron->num_out_ports + extron->num_in_ports;
1439 	dev_info(extron->dev, "Unit output ports: %d\n", extron->num_out_ports);
1440 	dev_info(extron->dev, "Unit input ports: %d\n", extron->num_in_ports);
1441 
1442 	err = extron_send_and_wait(extron, NULL, "W CN", "Ipn ");
1443 	if (err)
1444 		return err;
1445 	dev_info(extron->dev, "Unit name: %s\n", reply + 4);
1446 	strscpy(extron->unit_name, reply + 4, sizeof(extron->unit_name));
1447 
1448 	err = extron_send_and_wait(extron, NULL, "*Q", "Bld");
1449 	if (err)
1450 		return err;
1451 	dev_info(extron->dev, "Unit FW Version: %s\n", reply + 3);
1452 	strscpy(extron->unit_fw_version, reply + 3,
1453 		sizeof(extron->unit_fw_version));
1454 	if (sscanf(reply + 3, "%u.%u.", &major, &minor) < 2 ||
1455 	    major < 1 || minor < 2) {
1456 		dev_err(extron->dev,
1457 			"Unsupported FW version (only 1.02 or up is supported)\n");
1458 		return -ENODEV;
1459 	}
1460 
1461 	err = extron_send_and_wait(extron, NULL, "2i", "Inf02*");
1462 	if (err)
1463 		return err;
1464 	dev_info(extron->dev, "Unit Type: %s\n", reply + 6);
1465 	strscpy(extron->unit_type, reply + 6, sizeof(extron->unit_type));
1466 
1467 	err = extron_send_and_wait(extron, NULL, "39Q", "Ver39*");
1468 	if (err)
1469 		return err;
1470 	dev_info(extron->dev, "CEC Engine Version: %s\n", reply + 6);
1471 	strscpy(extron->unit_cec_engine_version, reply + 6,
1472 		sizeof(extron->unit_cec_engine_version));
1473 
1474 	/* Disable CEC */
1475 	err = extron_send_and_wait(extron, NULL, "WI1*0CCEC", "CcecI1*");
1476 	if (err)
1477 		return err;
1478 	err = extron_send_and_wait(extron, NULL, "WO0*CCEC", "CcecO0");
1479 	if (err)
1480 		return err;
1481 
1482 	extron->hpd_never_low = hpd_never_low;
1483 
1484 	/* Pull input port HPD low if all output ports also have a low HPD */
1485 	if (hpd_never_low) {
1486 		dev_info(extron->dev, "Always keep input HPD high\n");
1487 	} else {
1488 		dev_info(extron->dev, "Pull input HPD low if all output HPDs are low\n");
1489 		extron_send_and_wait(extron, NULL, "W1ihpd", "Ihpd1");
1490 	}
1491 
1492 	for (p = 0; p < extron->num_ports; p++) {
1493 		u32 caps = CEC_CAP_DEFAULTS | CEC_CAP_MONITOR_ALL;
1494 
1495 		if (vendor_id)
1496 			caps &= ~CEC_CAP_LOG_ADDRS;
1497 		port = kzalloc_obj(*port);
1498 		if (!port)
1499 			return -ENOMEM;
1500 
1501 		INIT_WORK(&port->irq_work, extron_irq_work_handler);
1502 		spin_lock_init(&port->msg_lock);
1503 		mutex_init(&port->video_lock);
1504 		port->extron = extron;
1505 		port->is_input = p >= extron->num_out_ports;
1506 		port->direction = port->is_input ? 'I' : 'O';
1507 		port->port.port = 1 + (port->is_input ? p - extron->num_out_ports : p);
1508 		port->port.splitter = &extron->splitter;
1509 		port->phys_addr = CEC_PHYS_ADDR_INVALID;
1510 		snprintf(port->name, sizeof(port->name), "%s-%s-%u",
1511 			 dev_name(&serio->dev), port->is_input ? "in" : "out",
1512 			 port->port.port);
1513 
1514 		port->dev = extron->dev;
1515 		port->adap = cec_allocate_adapter(&extron_cec_adap_ops, port,
1516 						  port->name, caps, 1);
1517 		err = PTR_ERR_OR_ZERO(port->adap);
1518 		if (err < 0) {
1519 			kfree(port);
1520 			return err;
1521 		}
1522 
1523 		port->adap->xfer_timeout_ms = EXTRON_TIMEOUT_SECS * 1000;
1524 		port->port.adap = port->adap;
1525 		port->vdev = extron_videodev;
1526 		port->vdev.lock = &port->video_lock;
1527 		port->vdev.v4l2_dev = &extron->v4l2_dev;
1528 		port->vdev.ctrl_handler = &port->hdl;
1529 		port->vdev.device_caps = V4L2_CAP_EDID;
1530 		video_set_drvdata(&port->vdev, port);
1531 
1532 		v4l2_ctrl_handler_init(&port->hdl, 2);
1533 
1534 		if (port->is_input) {
1535 			port->vdev.vfl_dir = VFL_DIR_RX;
1536 			port->ctrl_rx_power_present =
1537 				v4l2_ctrl_new_std(&port->hdl, NULL,
1538 						  V4L2_CID_DV_RX_POWER_PRESENT,
1539 						  0, 1, 0, 0);
1540 			port->has_edid = true;
1541 		} else {
1542 			port->vdev.vfl_dir = VFL_DIR_TX;
1543 			port->ctrl_tx_hotplug =
1544 				v4l2_ctrl_new_std(&port->hdl, NULL,
1545 						  V4L2_CID_DV_TX_HOTPLUG,
1546 						  0, 1, 0, 0);
1547 			port->ctrl_tx_edid_present =
1548 				v4l2_ctrl_new_std(&port->hdl, NULL,
1549 						  V4L2_CID_DV_TX_EDID_PRESENT,
1550 						  0, 1, 0, 0);
1551 		}
1552 
1553 		err = port->hdl.error;
1554 		if (err < 0) {
1555 			cec_delete_adapter(port->adap);
1556 			kfree(port);
1557 			return err;
1558 		}
1559 		extron->ports[p] = port;
1560 		extron->splitter_ports[p] = &port->port;
1561 		if (port->is_input && manufacturer_name[0])
1562 			extron_write_edid(port, hdmi_edid, 2);
1563 	}
1564 
1565 	/* Enable CEC (manual mode, i.e. controlled by the driver) */
1566 	err = extron_send_and_wait(extron, NULL, "WI1*20CCEC", "CcecI1*");
1567 	if (err)
1568 		return err;
1569 
1570 	err = extron_send_and_wait(extron, NULL, "WO20*CCEC", "CcecO20");
1571 	if (err)
1572 		return err;
1573 
1574 	/* Set logical addresses to 15 */
1575 	err = extron_send_and_wait(extron, NULL, "WI1*15LCEC", "LcecI1*15");
1576 	if (err)
1577 		return err;
1578 
1579 	for (p = 0; p < extron->num_out_ports; p++) {
1580 		char cmd[20];
1581 		char resp[20];
1582 
1583 		snprintf(cmd, sizeof(cmd), "WO%u*15LCEC", p + 1);
1584 		snprintf(resp, sizeof(resp), "LcecO%u*15", p + 1);
1585 		err = extron_send_and_wait(extron, extron->ports[p], cmd, resp);
1586 		if (err)
1587 			return err;
1588 	}
1589 
1590 	/*
1591 	 * The Extron is now ready for operation. Specifically it is now
1592 	 * possible to retrieve EDIDs.
1593 	 */
1594 	extron->is_ready = true;
1595 
1596 	/* Query HDCP and Signal states, used to update the initial state */
1597 	err = extron_send_and_wait(extron, NULL, "WHDCP", "Hdcp");
1598 	if (err)
1599 		return err;
1600 
1601 	return extron_send_and_wait(extron, NULL, "WLS", "Sig");
1602 }
1603 
extron_setup_thread(void * _extron)1604 static int extron_setup_thread(void *_extron)
1605 {
1606 	struct extron *extron = _extron;
1607 	struct extron_port *port;
1608 	unsigned int p;
1609 	bool poll_splitter = false;
1610 	bool was_connected = true;
1611 	int err;
1612 
1613 	while (1) {
1614 		if (kthread_should_stop())
1615 			return 0;
1616 		err = extron_send_and_wait(extron, NULL, "W3CV", "Vrb3");
1617 		// that should make it possible to detect a serio disconnect
1618 		// here by stopping the workqueue
1619 		if (err >= 0)
1620 			break;
1621 		was_connected = false;
1622 		ssleep(1);
1623 	}
1624 
1625 	/*
1626 	 * If the Extron was not connected at probe() time, i.e. it just got
1627 	 * powered up and while the serial port is working, the firmware is
1628 	 * still booting up, then wait 10 seconds for the firmware to settle.
1629 	 *
1630 	 * Trying to continue too soon means that some commands will not
1631 	 * work yet.
1632 	 */
1633 	if (!was_connected)
1634 		ssleep(10);
1635 
1636 	err = extron_setup(extron);
1637 	if (err)
1638 		goto disable_ports;
1639 
1640 	for (p = 0; p < extron->num_ports; p++) {
1641 		struct cec_log_addrs log_addrs = {};
1642 
1643 		port = extron->ports[p];
1644 		if (port->is_input && manufacturer_name[0])
1645 			v4l2_disable_ioctl(&port->vdev, VIDIOC_S_EDID);
1646 		err = video_register_device(&port->vdev, VFL_TYPE_VIDEO, -1);
1647 		if (err) {
1648 			v4l2_err(&extron->v4l2_dev, "Failed to register video device\n");
1649 			goto disable_ports;
1650 		}
1651 
1652 		err = cec_register_adapter(port->adap, extron->dev);
1653 		if (err < 0)
1654 			goto disable_ports;
1655 		port->dev = &port->adap->devnode.dev;
1656 		port->cec_was_registered = true;
1657 		/*
1658 		 * This driver is unusual in that the whole setup takes place
1659 		 * in a thread since it can take such a long time before the
1660 		 * Extron Splitter boots up, and you do not want to block the
1661 		 * probe function on this driver. In addition, as soon as
1662 		 * CEC adapters come online, they can be used, and you cannot
1663 		 * just unregister them again if an error occurs, since that
1664 		 * can delete the underlying CEC adapter, which might already
1665 		 * be in use.
1666 		 *
1667 		 * So we take an additional reference to the adapter. This
1668 		 * allows us to unregister the device node if needed, without
1669 		 * deleting the actual adapter.
1670 		 *
1671 		 * In the disconnect function we will do the corresponding
1672 		 * put call to ensure the adapter is deleted.
1673 		 */
1674 		cec_get_device(port->adap);
1675 
1676 		/*
1677 		 * If vendor_id wasn't set, then userspace configures the
1678 		 * CEC devices. Otherwise the driver configures the CEC
1679 		 * devices as TV (input) and Playback (outputs) devices
1680 		 * and the driver processes all CEC messages.
1681 		 */
1682 		if (!vendor_id)
1683 			continue;
1684 
1685 		log_addrs.cec_version = CEC_OP_CEC_VERSION_2_0;
1686 		log_addrs.num_log_addrs = 1;
1687 		log_addrs.vendor_id = vendor_id;
1688 		if (port->is_input) {
1689 			strscpy(log_addrs.osd_name, "Splitter In",
1690 				sizeof(log_addrs.osd_name));
1691 			log_addrs.log_addr_type[0] = CEC_LOG_ADDR_TYPE_TV;
1692 			log_addrs.primary_device_type[0] = CEC_OP_PRIM_DEVTYPE_TV;
1693 			log_addrs.all_device_types[0] = CEC_OP_ALL_DEVTYPE_TV;
1694 		} else {
1695 			snprintf(log_addrs.osd_name, sizeof(log_addrs.osd_name),
1696 				 "Splitter Out%u", port->port.port);
1697 			log_addrs.log_addr_type[0] = CEC_LOG_ADDR_TYPE_PLAYBACK;
1698 			log_addrs.primary_device_type[0] = CEC_OP_PRIM_DEVTYPE_PLAYBACK;
1699 			log_addrs.all_device_types[0] = CEC_OP_ALL_DEVTYPE_PLAYBACK;
1700 		}
1701 		err = cec_s_log_addrs(port->adap, &log_addrs, false);
1702 		if (err < 0)
1703 			goto disable_ports;
1704 	}
1705 	poll_splitter = true;
1706 
1707 	port = extron->ports[extron->num_out_ports];
1708 	while (!kthread_should_stop()) {
1709 		ssleep(1);
1710 		if (hpd_never_low != extron->hpd_never_low) {
1711 			/*
1712 			 * Keep input port HPD high at all times, or pull it low
1713 			 * if all output ports also have a low HPD
1714 			 */
1715 			if (hpd_never_low) {
1716 				dev_info(extron->dev, "Always keep input HPD high\n");
1717 				extron_send_and_wait(extron, NULL, "W0ihpd", "Ihpd0");
1718 			} else {
1719 				dev_info(extron->dev, "Pull input HPD low if all output HPDs are low\n");
1720 				extron_send_and_wait(extron, NULL, "W1ihpd", "Ihpd1");
1721 			}
1722 			extron->hpd_never_low = hpd_never_low;
1723 		}
1724 		if (poll_splitter &&
1725 		    cec_splitter_poll(&extron->splitter, port->adap, debug) &&
1726 		    manufacturer_name[0]) {
1727 			/*
1728 			 * Sinks were lost, so see if the input edid needs to
1729 			 * be updated.
1730 			 */
1731 			cancel_delayed_work_sync(&extron->work_update_edid);
1732 			schedule_delayed_work(&extron->work_update_edid,
1733 					      msecs_to_jiffies(1000));
1734 		}
1735 	}
1736 	return 0;
1737 
1738 disable_ports:
1739 	extron->is_ready = false;
1740 	for (p = 0; p < extron->num_ports; p++) {
1741 		struct extron_port *port = extron->ports[p];
1742 
1743 		if (!port)
1744 			continue;
1745 		port->disconnected = true;
1746 		cancel_work_sync(&port->irq_work);
1747 		video_unregister_device(&port->vdev);
1748 		if (port->cec_was_registered)
1749 			cec_unregister_adapter(port->adap);
1750 	}
1751 	cancel_delayed_work_sync(&extron->work_update_edid);
1752 	complete(&extron->edid_completion);
1753 	dev_err(extron->dev, "Setup failed with error %d\n", err);
1754 	while (!kthread_should_stop())
1755 		ssleep(1);
1756 	return err;
1757 }
1758 
extron_connect(struct serio * serio,struct serio_driver * drv)1759 static int extron_connect(struct serio *serio, struct serio_driver *drv)
1760 {
1761 	struct extron *extron;
1762 	int err = -ENOMEM;
1763 
1764 	if (manufacturer_name[0] &&
1765 	    (!isupper(manufacturer_name[0]) ||
1766 	     !isupper(manufacturer_name[1]) ||
1767 	     !isupper(manufacturer_name[2]))) {
1768 		dev_warn(&serio->dev, "ignoring invalid manufacturer name\n");
1769 		manufacturer_name[0] = 0;
1770 	}
1771 
1772 	extron = kzalloc_obj(*extron);
1773 
1774 	if (!extron)
1775 		return -ENOMEM;
1776 
1777 	extron->serio = serio;
1778 	extron->dev = &serio->dev;
1779 	mutex_init(&extron->serio_lock);
1780 	mutex_init(&extron->edid_lock);
1781 	INIT_DELAYED_WORK(&extron->work_update_edid, update_edid_work);
1782 
1783 	err = v4l2_device_register(extron->dev, &extron->v4l2_dev);
1784 	if (err)
1785 		goto free_device;
1786 
1787 	err = serio_open(serio, drv);
1788 	if (err)
1789 		goto unreg_v4l2_dev;
1790 
1791 	serio_set_drvdata(serio, extron);
1792 	init_completion(&extron->edid_completion);
1793 
1794 	extron->kthread_setup = kthread_run(extron_setup_thread, extron,
1795 					    "extron-da-hd-4k-plus-cec-%s", dev_name(&serio->dev));
1796 	if (!IS_ERR(extron->kthread_setup))
1797 		return 0;
1798 
1799 	dev_err(extron->dev, "kthread_run() failed\n");
1800 	err = PTR_ERR(extron->kthread_setup);
1801 
1802 	extron->serio = NULL;
1803 	serio_set_drvdata(serio, NULL);
1804 	serio_close(serio);
1805 unreg_v4l2_dev:
1806 	v4l2_device_unregister(&extron->v4l2_dev);
1807 free_device:
1808 	mutex_destroy(&extron->edid_lock);
1809 	mutex_destroy(&extron->serio_lock);
1810 	kfree(extron);
1811 	return err;
1812 }
1813 
1814 static const struct serio_device_id extron_serio_ids[] = {
1815 	{
1816 		.type	= SERIO_RS232,
1817 		.proto	= SERIO_EXTRON_DA_HD_4K_PLUS,
1818 		.id	= SERIO_ANY,
1819 		.extra	= SERIO_ANY,
1820 	},
1821 	{ 0 }
1822 };
1823 
1824 MODULE_DEVICE_TABLE(serio, extron_serio_ids);
1825 
1826 static struct serio_driver extron_drv = {
1827 	.driver		= {
1828 		.name	= "extron-da-hd-4k-plus-cec",
1829 	},
1830 	.description	= "Extron DA HD 4K PLUS HDMI CEC driver",
1831 	.id_table	= extron_serio_ids,
1832 	.interrupt	= extron_interrupt,
1833 	.connect	= extron_connect,
1834 	.disconnect	= extron_disconnect,
1835 };
1836 
1837 module_serio_driver(extron_drv);
1838