1 // SPDX-License-Identifier: GPL-2.0 2 /* 3 * USB Typec-C DisplayPort Alternate Mode driver 4 * 5 * Copyright (C) 2018 Intel Corporation 6 * Author: Heikki Krogerus <heikki.krogerus@linux.intel.com> 7 * 8 * DisplayPort is trademark of VESA (www.vesa.org) 9 */ 10 11 #include <linux/delay.h> 12 #include <linux/mutex.h> 13 #include <linux/module.h> 14 #include <linux/property.h> 15 #include <linux/usb/pd_vdo.h> 16 #include <linux/usb/typec_dp.h> 17 #include <drm/drm_connector.h> 18 #include "displayport.h" 19 20 #define DP_HEADER(_dp, ver, cmd) (VDO((_dp)->alt->svid, 1, ver, cmd) \ 21 | VDO_OPOS(USB_TYPEC_DP_MODE)) 22 23 enum { 24 DP_CONF_USB, 25 DP_CONF_DFP_D, 26 DP_CONF_UFP_D, 27 DP_CONF_DUAL_D, 28 }; 29 30 /* Pin assignments that use USB3.1 Gen2 signaling to carry DP protocol */ 31 #define DP_PIN_ASSIGN_GEN2_BR_MASK (BIT(DP_PIN_ASSIGN_A) | \ 32 BIT(DP_PIN_ASSIGN_B)) 33 34 /* Pin assignments that use DP v1.3 signaling to carry DP protocol */ 35 #define DP_PIN_ASSIGN_DP_BR_MASK (BIT(DP_PIN_ASSIGN_C) | \ 36 BIT(DP_PIN_ASSIGN_D) | \ 37 BIT(DP_PIN_ASSIGN_E) | \ 38 BIT(DP_PIN_ASSIGN_F)) 39 40 /* DP only pin assignments */ 41 #define DP_PIN_ASSIGN_DP_ONLY_MASK (BIT(DP_PIN_ASSIGN_A) | \ 42 BIT(DP_PIN_ASSIGN_C) | \ 43 BIT(DP_PIN_ASSIGN_E)) 44 45 /* Pin assignments where one channel is for USB */ 46 #define DP_PIN_ASSIGN_MULTI_FUNC_MASK (BIT(DP_PIN_ASSIGN_B) | \ 47 BIT(DP_PIN_ASSIGN_D) | \ 48 BIT(DP_PIN_ASSIGN_F)) 49 50 enum dp_state { 51 DP_STATE_IDLE, 52 DP_STATE_ENTER, 53 DP_STATE_ENTER_PRIME, 54 DP_STATE_UPDATE, 55 DP_STATE_CONFIGURE, 56 DP_STATE_CONFIGURE_PRIME, 57 DP_STATE_EXIT, 58 DP_STATE_EXIT_PRIME, 59 }; 60 61 struct dp_altmode { 62 struct typec_displayport_data data; 63 struct typec_displayport_data data_prime; 64 65 enum dp_state state; 66 bool hpd; 67 bool pending_hpd; 68 u32 irq_hpd_count; 69 /* 70 * hpd is mandatory for irq_hpd assertion, so irq_hpd also needs its own pending flag if 71 * both hpd and irq_hpd are asserted in the first Status Update before the pin assignment 72 * is configured. 73 */ 74 bool pending_irq_hpd; 75 76 struct mutex lock; /* device lock */ 77 struct work_struct work; 78 struct typec_altmode *alt; 79 const struct typec_altmode *port; 80 struct fwnode_handle *connector_fwnode; 81 struct typec_altmode *plug_prime; 82 }; 83 84 static int dp_altmode_notify(struct dp_altmode *dp) 85 { 86 unsigned long conf; 87 u8 state; 88 89 if (dp->data.conf) { 90 state = get_count_order(DP_CONF_GET_PIN_ASSIGN(dp->data.conf)); 91 conf = TYPEC_MODAL_STATE(state); 92 } else { 93 conf = TYPEC_STATE_USB; 94 } 95 96 return typec_altmode_notify(dp->alt, conf, &dp->data); 97 } 98 99 static int dp_altmode_configure(struct dp_altmode *dp, u8 con) 100 { 101 u8 pin_assign = 0; 102 u32 conf; 103 u32 signal; 104 105 /* DP Signalling */ 106 signal = DP_CAP_DP_SIGNALLING(dp->port->vdo) & DP_CAP_DP_SIGNALLING(dp->alt->vdo); 107 if (dp->plug_prime) 108 signal &= DP_CAP_DP_SIGNALLING(dp->plug_prime->vdo); 109 110 conf = signal << DP_CONF_SIGNALLING_SHIFT; 111 112 switch (con) { 113 case DP_STATUS_CON_DISABLED: 114 return 0; 115 case DP_STATUS_CON_DFP_D: 116 conf |= DP_CONF_UFP_U_AS_DFP_D; 117 pin_assign = DP_CAP_UFP_D_PIN_ASSIGN(dp->alt->vdo) & 118 DP_CAP_DFP_D_PIN_ASSIGN(dp->port->vdo); 119 /* Account for active cable capabilities */ 120 if (dp->plug_prime) 121 pin_assign &= DP_CAP_DFP_D_PIN_ASSIGN(dp->plug_prime->vdo); 122 break; 123 case DP_STATUS_CON_UFP_D: 124 case DP_STATUS_CON_BOTH: /* NOTE: First acting as DP source */ 125 conf |= DP_CONF_UFP_U_AS_UFP_D; 126 pin_assign = DP_CAP_PIN_ASSIGN_UFP_D(dp->alt->vdo) & 127 DP_CAP_PIN_ASSIGN_DFP_D(dp->port->vdo); 128 /* Account for active cable capabilities */ 129 if (dp->plug_prime) 130 pin_assign &= DP_CAP_UFP_D_PIN_ASSIGN(dp->plug_prime->vdo); 131 break; 132 default: 133 break; 134 } 135 136 /* Determining the initial pin assignment. */ 137 if (!DP_CONF_GET_PIN_ASSIGN(dp->data.conf)) { 138 /* Is USB together with DP preferred */ 139 if (dp->data.status & DP_STATUS_PREFER_MULTI_FUNC && 140 pin_assign & DP_PIN_ASSIGN_MULTI_FUNC_MASK) 141 pin_assign &= DP_PIN_ASSIGN_MULTI_FUNC_MASK; 142 else if (pin_assign & DP_PIN_ASSIGN_DP_ONLY_MASK) { 143 pin_assign &= DP_PIN_ASSIGN_DP_ONLY_MASK; 144 /* Default to pin assign C if available */ 145 if (pin_assign & BIT(DP_PIN_ASSIGN_C)) 146 pin_assign = BIT(DP_PIN_ASSIGN_C); 147 } 148 149 if (!pin_assign) 150 return -EINVAL; 151 152 conf |= DP_CONF_SET_PIN_ASSIGN(pin_assign); 153 } 154 155 dp->data.conf = conf; 156 if (dp->plug_prime) 157 dp->data_prime.conf = conf; 158 159 return 0; 160 } 161 162 static int dp_altmode_status_update(struct dp_altmode *dp) 163 { 164 bool configured = !!DP_CONF_GET_PIN_ASSIGN(dp->data.conf); 165 bool hpd = !!(dp->data.status & DP_STATUS_HPD_STATE); 166 bool irq_hpd = !!(dp->data.status & DP_STATUS_IRQ_HPD); 167 u8 con = DP_STATUS_CONNECTION(dp->data.status); 168 int ret = 0; 169 170 if (configured && (dp->data.status & DP_STATUS_SWITCH_TO_USB)) { 171 dp->data.conf = 0; 172 dp->data_prime.conf = 0; 173 dp->state = dp->plug_prime ? DP_STATE_CONFIGURE_PRIME : 174 DP_STATE_CONFIGURE; 175 } else if (dp->data.status & DP_STATUS_EXIT_DP_MODE) { 176 dp->state = DP_STATE_EXIT; 177 } else if (!(con & DP_CONF_CURRENTLY(dp->data.conf))) { 178 ret = dp_altmode_configure(dp, con); 179 if (!ret) { 180 dp->state = dp->plug_prime ? DP_STATE_CONFIGURE_PRIME : 181 DP_STATE_CONFIGURE; 182 if (dp->hpd != hpd) { 183 dp->hpd = hpd; 184 dp->pending_hpd = true; 185 } 186 if (dp->hpd && dp->pending_hpd && irq_hpd) 187 dp->pending_irq_hpd = true; 188 } 189 } else { 190 drm_connector_oob_hotplug_event(dp->connector_fwnode, 191 hpd ? connector_status_connected : 192 connector_status_disconnected); 193 dp->hpd = hpd; 194 sysfs_notify(&dp->alt->dev.kobj, "displayport", "hpd"); 195 if (hpd && irq_hpd) { 196 dp->irq_hpd_count++; 197 sysfs_notify(&dp->alt->dev.kobj, "displayport", "irq_hpd"); 198 } 199 } 200 201 return ret; 202 } 203 204 static int dp_altmode_configured(struct dp_altmode *dp) 205 { 206 sysfs_notify(&dp->alt->dev.kobj, "displayport", "configuration"); 207 sysfs_notify(&dp->alt->dev.kobj, "displayport", "pin_assignment"); 208 /* 209 * If the DFP_D/UFP_D sends a change in HPD when first notifying the 210 * DisplayPort driver that it is connected, then we wait until 211 * configuration is complete to signal HPD. 212 */ 213 if (dp->pending_hpd) { 214 drm_connector_oob_hotplug_event(dp->connector_fwnode, 215 connector_status_connected); 216 sysfs_notify(&dp->alt->dev.kobj, "displayport", "hpd"); 217 dp->pending_hpd = false; 218 if (dp->pending_irq_hpd) { 219 dp->irq_hpd_count++; 220 sysfs_notify(&dp->alt->dev.kobj, "displayport", "irq_hpd"); 221 dp->pending_irq_hpd = false; 222 } 223 } 224 225 return dp_altmode_notify(dp); 226 } 227 228 static int dp_altmode_configure_vdm(struct dp_altmode *dp, u32 conf) 229 { 230 int svdm_version = typec_altmode_get_svdm_version(dp->alt); 231 u32 header; 232 int ret; 233 234 if (svdm_version < 0) 235 return svdm_version; 236 237 header = DP_HEADER(dp, svdm_version, DP_CMD_CONFIGURE); 238 ret = typec_altmode_notify(dp->alt, TYPEC_STATE_SAFE, &dp->data); 239 if (ret) { 240 dev_err(&dp->alt->dev, 241 "unable to put to connector to safe mode\n"); 242 return ret; 243 } 244 245 ret = typec_altmode_vdm(dp->alt, header, &conf, 2); 246 if (ret) 247 dp_altmode_notify(dp); 248 249 return ret; 250 } 251 252 static int dp_altmode_configure_vdm_cable(struct dp_altmode *dp, u32 conf) 253 { 254 int svdm_version = typec_altmode_get_cable_svdm_version(dp->plug_prime); 255 u32 header; 256 257 if (svdm_version < 0) 258 return svdm_version; 259 260 header = DP_HEADER(dp, svdm_version, DP_CMD_CONFIGURE); 261 262 return typec_cable_altmode_vdm(dp->plug_prime, TYPEC_PLUG_SOP_P, header, &conf, 2); 263 } 264 265 static void dp_altmode_work(struct work_struct *work) 266 { 267 struct dp_altmode *dp = container_of(work, struct dp_altmode, work); 268 int svdm_version; 269 u32 header; 270 u32 vdo; 271 int ret; 272 273 mutex_lock(&dp->lock); 274 275 switch (dp->state) { 276 case DP_STATE_ENTER: 277 ret = typec_altmode_enter(dp->alt, NULL); 278 if (ret && ret != -EBUSY) 279 dev_err(&dp->alt->dev, "failed to enter mode: %d\n", ret); 280 break; 281 case DP_STATE_ENTER_PRIME: 282 ret = typec_cable_altmode_enter(dp->alt, TYPEC_PLUG_SOP_P, NULL); 283 /* 284 * If we fail to enter Alt Mode on SOP', then we should drop the 285 * plug from the driver and attempt to run the driver without 286 * it. 287 */ 288 if (ret && ret != -EBUSY) { 289 dev_err(&dp->alt->dev, "plug failed to enter mode\n"); 290 dp->state = DP_STATE_ENTER; 291 goto disable_prime; 292 } 293 break; 294 case DP_STATE_UPDATE: 295 svdm_version = typec_altmode_get_svdm_version(dp->alt); 296 if (svdm_version < 0) 297 break; 298 header = DP_HEADER(dp, svdm_version, DP_CMD_STATUS_UPDATE); 299 vdo = 1; 300 ret = typec_altmode_vdm(dp->alt, header, &vdo, 2); 301 if (ret) 302 dev_err(&dp->alt->dev, 303 "unable to send Status Update command (%d)\n", 304 ret); 305 break; 306 case DP_STATE_CONFIGURE: 307 ret = dp_altmode_configure_vdm(dp, dp->data.conf); 308 if (ret) 309 dev_err(&dp->alt->dev, 310 "unable to send Configure command (%d)\n", ret); 311 break; 312 case DP_STATE_CONFIGURE_PRIME: 313 ret = dp_altmode_configure_vdm_cable(dp, dp->data_prime.conf); 314 if (ret) { 315 dev_err(&dp->plug_prime->dev, 316 "unable to send Configure command (%d)\n", 317 ret); 318 dp->state = DP_STATE_CONFIGURE; 319 goto disable_prime; 320 } 321 break; 322 case DP_STATE_EXIT: 323 if (typec_altmode_exit(dp->alt)) 324 dev_err(&dp->alt->dev, "Exit Mode Failed!\n"); 325 break; 326 case DP_STATE_EXIT_PRIME: 327 if (typec_cable_altmode_exit(dp->plug_prime, TYPEC_PLUG_SOP_P)) 328 dev_err(&dp->plug_prime->dev, "Exit Mode Failed!\n"); 329 break; 330 default: 331 break; 332 } 333 334 dp->state = DP_STATE_IDLE; 335 336 mutex_unlock(&dp->lock); 337 return; 338 339 disable_prime: 340 typec_altmode_put_plug(dp->plug_prime); 341 dp->plug_prime = NULL; 342 schedule_work(&dp->work); 343 mutex_unlock(&dp->lock); 344 } 345 346 static void dp_altmode_attention(struct typec_altmode *alt, const u32 vdo) 347 { 348 struct dp_altmode *dp = typec_altmode_get_drvdata(alt); 349 u8 old_state; 350 351 mutex_lock(&dp->lock); 352 353 old_state = dp->state; 354 dp->data.status = vdo; 355 356 if (old_state != DP_STATE_IDLE) 357 dev_warn(&alt->dev, "ATTENTION while processing state %d\n", 358 old_state); 359 360 if (dp_altmode_status_update(dp)) 361 dev_warn(&alt->dev, "%s: status update failed\n", __func__); 362 363 if (dp_altmode_notify(dp)) 364 dev_err(&alt->dev, "%s: notification failed\n", __func__); 365 366 if (old_state == DP_STATE_IDLE && dp->state != DP_STATE_IDLE) 367 schedule_work(&dp->work); 368 369 mutex_unlock(&dp->lock); 370 } 371 372 static int dp_altmode_vdm(struct typec_altmode *alt, 373 const u32 hdr, const u32 *vdo, int count) 374 { 375 struct dp_altmode *dp = typec_altmode_get_drvdata(alt); 376 int cmd_type = PD_VDO_CMDT(hdr); 377 int cmd = PD_VDO_CMD(hdr); 378 int ret = 0; 379 380 mutex_lock(&dp->lock); 381 382 if (dp->state != DP_STATE_IDLE) { 383 ret = -EBUSY; 384 goto err_unlock; 385 } 386 387 switch (cmd_type) { 388 case CMDT_RSP_ACK: 389 switch (cmd) { 390 case CMD_ENTER_MODE: 391 typec_altmode_update_active(alt, true); 392 dp->state = DP_STATE_UPDATE; 393 break; 394 case CMD_EXIT_MODE: 395 typec_altmode_update_active(alt, false); 396 dp->data.status = 0; 397 dp->data.conf = 0; 398 if (dp->hpd) { 399 drm_connector_oob_hotplug_event(dp->connector_fwnode, 400 connector_status_disconnected); 401 dp->hpd = false; 402 sysfs_notify(&dp->alt->dev.kobj, "displayport", "hpd"); 403 } 404 if (dp->plug_prime) 405 dp->state = DP_STATE_EXIT_PRIME; 406 break; 407 case DP_CMD_STATUS_UPDATE: 408 if (count < 2) 409 break; 410 dp->data.status = *vdo; 411 ret = dp_altmode_status_update(dp); 412 break; 413 case DP_CMD_CONFIGURE: 414 ret = dp_altmode_configured(dp); 415 break; 416 default: 417 break; 418 } 419 break; 420 case CMDT_RSP_NAK: 421 switch (cmd) { 422 case DP_CMD_STATUS_UPDATE: 423 dp->state = DP_STATE_EXIT; 424 break; 425 case DP_CMD_CONFIGURE: 426 dp->data.conf = 0; 427 ret = dp_altmode_configured(dp); 428 break; 429 default: 430 break; 431 } 432 break; 433 default: 434 break; 435 } 436 437 if (dp->state != DP_STATE_IDLE) 438 schedule_work(&dp->work); 439 440 err_unlock: 441 mutex_unlock(&dp->lock); 442 return ret; 443 } 444 445 static int dp_cable_altmode_vdm(struct typec_altmode *alt, enum typec_plug_index sop, 446 const u32 hdr, const u32 *vdo, int count) 447 { 448 struct dp_altmode *dp = typec_altmode_get_drvdata(alt); 449 int cmd_type = PD_VDO_CMDT(hdr); 450 int cmd = PD_VDO_CMD(hdr); 451 int ret = 0; 452 453 mutex_lock(&dp->lock); 454 455 if (dp->state != DP_STATE_IDLE) { 456 ret = -EBUSY; 457 goto err_unlock; 458 } 459 460 switch (cmd_type) { 461 case CMDT_RSP_ACK: 462 switch (cmd) { 463 case CMD_ENTER_MODE: 464 typec_altmode_update_active(dp->plug_prime, true); 465 dp->state = DP_STATE_ENTER; 466 break; 467 case CMD_EXIT_MODE: 468 dp->data_prime.status = 0; 469 dp->data_prime.conf = 0; 470 typec_altmode_update_active(dp->plug_prime, false); 471 break; 472 case DP_CMD_CONFIGURE: 473 dp->state = DP_STATE_CONFIGURE; 474 break; 475 default: 476 break; 477 } 478 break; 479 case CMDT_RSP_NAK: 480 switch (cmd) { 481 case DP_CMD_CONFIGURE: 482 dp->data_prime.conf = 0; 483 /* Attempt to configure on SOP, drop plug */ 484 typec_altmode_put_plug(dp->plug_prime); 485 dp->plug_prime = NULL; 486 dp->state = DP_STATE_CONFIGURE; 487 break; 488 default: 489 break; 490 } 491 break; 492 default: 493 break; 494 } 495 496 if (dp->state != DP_STATE_IDLE) 497 schedule_work(&dp->work); 498 499 err_unlock: 500 mutex_unlock(&dp->lock); 501 return ret; 502 } 503 504 static int dp_altmode_activate(struct typec_altmode *alt, int activate) 505 { 506 struct dp_altmode *dp = typec_altmode_get_drvdata(alt); 507 int ret; 508 509 if (activate) { 510 if (dp->plug_prime) { 511 ret = typec_cable_altmode_enter(alt, TYPEC_PLUG_SOP_P, NULL); 512 if (ret < 0) { 513 typec_altmode_put_plug(dp->plug_prime); 514 dp->plug_prime = NULL; 515 } else { 516 return ret; 517 } 518 } 519 return typec_altmode_enter(alt, NULL); 520 } else { 521 return typec_altmode_exit(alt); 522 } 523 } 524 525 static const struct typec_altmode_ops dp_altmode_ops = { 526 .attention = dp_altmode_attention, 527 .vdm = dp_altmode_vdm, 528 .activate = dp_altmode_activate, 529 }; 530 531 static const struct typec_cable_ops dp_cable_ops = { 532 .vdm = dp_cable_altmode_vdm, 533 }; 534 535 static const char * const configurations[] = { 536 [DP_CONF_USB] = "USB", 537 [DP_CONF_DFP_D] = "source", 538 [DP_CONF_UFP_D] = "sink", 539 }; 540 541 static ssize_t 542 configuration_store(struct device *dev, struct device_attribute *attr, 543 const char *buf, size_t size) 544 { 545 struct dp_altmode *dp = dev_get_drvdata(dev); 546 u32 conf; 547 u32 cap; 548 int con; 549 int ret = 0; 550 551 con = sysfs_match_string(configurations, buf); 552 if (con < 0) 553 return con; 554 555 mutex_lock(&dp->lock); 556 557 if (dp->state != DP_STATE_IDLE) { 558 ret = -EBUSY; 559 goto err_unlock; 560 } 561 562 cap = DP_CAP_CAPABILITY(dp->alt->vdo); 563 564 if ((con == DP_CONF_DFP_D && !(cap & DP_CAP_DFP_D)) || 565 (con == DP_CONF_UFP_D && !(cap & DP_CAP_UFP_D))) { 566 ret = -EINVAL; 567 goto err_unlock; 568 } 569 570 conf = dp->data.conf & ~DP_CONF_DUAL_D; 571 conf |= con; 572 573 if (dp->alt->active) { 574 ret = dp_altmode_configure_vdm(dp, conf); 575 if (ret) 576 goto err_unlock; 577 } 578 579 dp->data.conf = conf; 580 581 err_unlock: 582 mutex_unlock(&dp->lock); 583 584 return ret ? ret : size; 585 } 586 587 static ssize_t configuration_show(struct device *dev, 588 struct device_attribute *attr, char *buf) 589 { 590 struct dp_altmode *dp = dev_get_drvdata(dev); 591 int len; 592 u8 cap; 593 u8 cur; 594 int i; 595 596 mutex_lock(&dp->lock); 597 598 cap = DP_CAP_CAPABILITY(dp->alt->vdo); 599 cur = DP_CONF_CURRENTLY(dp->data.conf); 600 601 len = sprintf(buf, "%s ", cur ? "USB" : "[USB]"); 602 603 for (i = 1; i < ARRAY_SIZE(configurations); i++) { 604 if (i == cur) 605 len += sprintf(buf + len, "[%s] ", configurations[i]); 606 else if ((i == DP_CONF_DFP_D && cap & DP_CAP_DFP_D) || 607 (i == DP_CONF_UFP_D && cap & DP_CAP_UFP_D)) 608 len += sprintf(buf + len, "%s ", configurations[i]); 609 } 610 611 mutex_unlock(&dp->lock); 612 613 buf[len - 1] = '\n'; 614 return len; 615 } 616 static DEVICE_ATTR_RW(configuration); 617 618 static const char * const pin_assignments[] = { 619 [DP_PIN_ASSIGN_A] = "A", 620 [DP_PIN_ASSIGN_B] = "B", 621 [DP_PIN_ASSIGN_C] = "C", 622 [DP_PIN_ASSIGN_D] = "D", 623 [DP_PIN_ASSIGN_E] = "E", 624 [DP_PIN_ASSIGN_F] = "F", 625 }; 626 627 /* 628 * Helper function to extract a peripheral's currently supported 629 * Pin Assignments from its DisplayPort alternate mode state. 630 */ 631 static u8 get_current_pin_assignments(struct dp_altmode *dp) 632 { 633 if (DP_CONF_CURRENTLY(dp->data.conf) == DP_CONF_UFP_U_AS_DFP_D) 634 return DP_CAP_PIN_ASSIGN_DFP_D(dp->alt->vdo); 635 else 636 return DP_CAP_PIN_ASSIGN_UFP_D(dp->alt->vdo); 637 } 638 639 static ssize_t 640 pin_assignment_store(struct device *dev, struct device_attribute *attr, 641 const char *buf, size_t size) 642 { 643 struct dp_altmode *dp = dev_get_drvdata(dev); 644 u8 assignments; 645 u32 conf; 646 int ret; 647 648 ret = sysfs_match_string(pin_assignments, buf); 649 if (ret < 0) 650 return ret; 651 652 conf = DP_CONF_SET_PIN_ASSIGN(BIT(ret)); 653 ret = 0; 654 655 mutex_lock(&dp->lock); 656 657 if (conf & dp->data.conf) 658 goto out_unlock; 659 660 if (dp->state != DP_STATE_IDLE) { 661 ret = -EBUSY; 662 goto out_unlock; 663 } 664 665 assignments = get_current_pin_assignments(dp); 666 667 if (!(DP_CONF_GET_PIN_ASSIGN(conf) & assignments)) { 668 ret = -EINVAL; 669 goto out_unlock; 670 } 671 672 conf |= dp->data.conf & ~DP_CONF_PIN_ASSIGNEMENT_MASK; 673 674 /* Only send Configure command if a configuration has been set */ 675 if (dp->alt->active && DP_CONF_CURRENTLY(dp->data.conf)) { 676 /* todo: send manual configure over SOP'*/ 677 ret = dp_altmode_configure_vdm(dp, conf); 678 if (ret) 679 goto out_unlock; 680 } 681 682 dp->data.conf = conf; 683 684 out_unlock: 685 mutex_unlock(&dp->lock); 686 687 return ret ? ret : size; 688 } 689 690 static ssize_t pin_assignment_show(struct device *dev, 691 struct device_attribute *attr, char *buf) 692 { 693 struct dp_altmode *dp = dev_get_drvdata(dev); 694 u8 assignments; 695 int len = 0; 696 u8 cur; 697 int i; 698 699 mutex_lock(&dp->lock); 700 701 cur = get_count_order(DP_CONF_GET_PIN_ASSIGN(dp->data.conf)); 702 703 assignments = get_current_pin_assignments(dp); 704 705 for (i = 0; assignments && i < DP_PIN_ASSIGN_MAX; assignments >>= 1, i++) { 706 if (assignments & 1) { 707 if (i == cur) 708 len += sprintf(buf + len, "[%s] ", 709 pin_assignments[i]); 710 else 711 len += sprintf(buf + len, "%s ", 712 pin_assignments[i]); 713 } 714 } 715 716 mutex_unlock(&dp->lock); 717 718 /* get_current_pin_assignments can return 0 when no matching pin assignments are found */ 719 if (len == 0) 720 len++; 721 722 buf[len - 1] = '\n'; 723 return len; 724 } 725 static DEVICE_ATTR_RW(pin_assignment); 726 727 static ssize_t hpd_show(struct device *dev, struct device_attribute *attr, char *buf) 728 { 729 struct dp_altmode *dp = dev_get_drvdata(dev); 730 731 return sysfs_emit(buf, "%d\n", dp->hpd); 732 } 733 static DEVICE_ATTR_RO(hpd); 734 735 static ssize_t irq_hpd_show(struct device *dev, struct device_attribute *attr, char *buf) 736 { 737 struct dp_altmode *dp = dev_get_drvdata(dev); 738 739 return sysfs_emit(buf, "%d\n", dp->irq_hpd_count); 740 } 741 static DEVICE_ATTR_RO(irq_hpd); 742 743 static struct attribute *displayport_attrs[] = { 744 &dev_attr_configuration.attr, 745 &dev_attr_pin_assignment.attr, 746 &dev_attr_hpd.attr, 747 &dev_attr_irq_hpd.attr, 748 NULL 749 }; 750 751 static const struct attribute_group displayport_group = { 752 .name = "displayport", 753 .attrs = displayport_attrs, 754 }; 755 756 static const struct attribute_group *displayport_groups[] = { 757 &displayport_group, 758 NULL, 759 }; 760 761 int dp_altmode_probe(struct typec_altmode *alt) 762 { 763 const struct typec_altmode *port = typec_altmode_get_partner(alt); 764 struct typec_altmode *plug = typec_altmode_get_plug(alt, TYPEC_PLUG_SOP_P); 765 struct fwnode_handle *fwnode; 766 struct dp_altmode *dp; 767 768 /* Port can only be DFP_U. */ 769 if (typec_altmode_get_data_role(alt) != TYPEC_HOST) 770 return -EPROTO; 771 772 /* Make sure we have compatible pin configurations */ 773 if (!(DP_CAP_PIN_ASSIGN_DFP_D(port->vdo) & 774 DP_CAP_PIN_ASSIGN_UFP_D(alt->vdo)) && 775 !(DP_CAP_PIN_ASSIGN_UFP_D(port->vdo) & 776 DP_CAP_PIN_ASSIGN_DFP_D(alt->vdo))) { 777 typec_altmode_put_plug(plug); 778 return -ENODEV; 779 } 780 781 dp = devm_kzalloc(&alt->dev, sizeof(*dp), GFP_KERNEL); 782 if (!dp) { 783 typec_altmode_put_plug(plug); 784 return -ENOMEM; 785 } 786 787 INIT_WORK(&dp->work, dp_altmode_work); 788 mutex_init(&dp->lock); 789 dp->port = port; 790 dp->alt = alt; 791 792 alt->desc = "DisplayPort"; 793 typec_altmode_set_ops(alt, &dp_altmode_ops); 794 795 if (plug) { 796 plug->desc = "Displayport"; 797 plug->cable_ops = &dp_cable_ops; 798 } 799 800 dp->plug_prime = plug; 801 802 fwnode = dev_fwnode(alt->dev.parent->parent); /* typec_port fwnode */ 803 if (fwnode_property_present(fwnode, "displayport")) 804 dp->connector_fwnode = fwnode_find_reference(fwnode, "displayport", 0); 805 else 806 dp->connector_fwnode = fwnode_handle_get(fwnode); /* embedded DP */ 807 if (IS_ERR(dp->connector_fwnode)) 808 dp->connector_fwnode = NULL; 809 810 typec_altmode_set_drvdata(alt, dp); 811 if (plug) 812 typec_altmode_set_drvdata(plug, dp); 813 814 if (!alt->mode_selection) { 815 dp->state = plug ? DP_STATE_ENTER_PRIME : DP_STATE_ENTER; 816 schedule_work(&dp->work); 817 } 818 819 return 0; 820 } 821 EXPORT_SYMBOL_GPL(dp_altmode_probe); 822 823 void dp_altmode_remove(struct typec_altmode *alt) 824 { 825 struct dp_altmode *dp = typec_altmode_get_drvdata(alt); 826 827 cancel_work_sync(&dp->work); 828 typec_altmode_put_plug(dp->plug_prime); 829 830 if (dp->connector_fwnode) { 831 drm_connector_oob_hotplug_event(dp->connector_fwnode, 832 connector_status_disconnected); 833 834 fwnode_handle_put(dp->connector_fwnode); 835 } 836 } 837 EXPORT_SYMBOL_GPL(dp_altmode_remove); 838 839 static const struct typec_device_id dp_typec_id[] = { 840 { USB_TYPEC_DP_SID }, 841 { }, 842 }; 843 MODULE_DEVICE_TABLE(typec, dp_typec_id); 844 845 static struct typec_altmode_driver dp_altmode_driver = { 846 .id_table = dp_typec_id, 847 .probe = dp_altmode_probe, 848 .remove = dp_altmode_remove, 849 .driver = { 850 .name = "typec_displayport", 851 .dev_groups = displayport_groups, 852 }, 853 }; 854 module_typec_altmode_driver(dp_altmode_driver); 855 856 MODULE_AUTHOR("Heikki Krogerus <heikki.krogerus@linux.intel.com>"); 857 MODULE_LICENSE("GPL v2"); 858 MODULE_DESCRIPTION("DisplayPort Alternate Mode"); 859