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