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