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 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 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 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 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 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 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 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 */ 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 1222 static int extron_g_input(struct file *file, void *priv, unsigned int *i) 1223 { 1224 *i = 0; 1225 return 0; 1226 } 1227 1228 static int extron_s_input(struct file *file, void *priv, unsigned int i) 1229 { 1230 return i ? -EINVAL : 0; 1231 } 1232 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 1244 static int extron_g_output(struct file *file, void *priv, unsigned int *o) 1245 { 1246 *o = 0; 1247 return 0; 1248 } 1249 1250 static int extron_s_output(struct file *file, void *priv, unsigned int o) 1251 { 1252 return o ? -EINVAL : 0; 1253 } 1254 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 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 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 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 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 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 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