.. | .. |
---|
114 | 114 | if (dp->data.status & DP_STATUS_PREFER_MULTI_FUNC && |
---|
115 | 115 | pin_assign & DP_PIN_ASSIGN_MULTI_FUNC_MASK) |
---|
116 | 116 | pin_assign &= DP_PIN_ASSIGN_MULTI_FUNC_MASK; |
---|
117 | | - else if (pin_assign & DP_PIN_ASSIGN_DP_ONLY_MASK) |
---|
| 117 | + else if (pin_assign & DP_PIN_ASSIGN_DP_ONLY_MASK) { |
---|
118 | 118 | pin_assign &= DP_PIN_ASSIGN_DP_ONLY_MASK; |
---|
| 119 | + /* Default to pin assign C if available */ |
---|
| 120 | + if (pin_assign & BIT(DP_PIN_ASSIGN_C)) |
---|
| 121 | + pin_assign = BIT(DP_PIN_ASSIGN_C); |
---|
| 122 | + } |
---|
119 | 123 | |
---|
120 | 124 | /* |
---|
121 | 125 | * DFP_U never selects Pin Assignment E when Pin Assignment C |
---|
.. | .. |
---|
444 | 448 | [DP_PIN_ASSIGN_F] = "F", |
---|
445 | 449 | }; |
---|
446 | 450 | |
---|
| 451 | +/* |
---|
| 452 | + * Helper function to extract a peripheral's currently supported |
---|
| 453 | + * Pin Assignments from its DisplayPort alternate mode state. |
---|
| 454 | + */ |
---|
| 455 | +static u8 get_current_pin_assignments(struct dp_altmode *dp) |
---|
| 456 | +{ |
---|
| 457 | + if (DP_CONF_CURRENTLY(dp->data.conf) == DP_CONF_DFP_D) |
---|
| 458 | + return DP_CAP_PIN_ASSIGN_DFP_D(dp->alt->vdo); |
---|
| 459 | + else |
---|
| 460 | + return DP_CAP_PIN_ASSIGN_UFP_D(dp->alt->vdo); |
---|
| 461 | +} |
---|
| 462 | + |
---|
447 | 463 | static ssize_t |
---|
448 | 464 | pin_assignment_store(struct device *dev, struct device_attribute *attr, |
---|
449 | 465 | const char *buf, size_t size) |
---|
.. | .. |
---|
470 | 486 | goto out_unlock; |
---|
471 | 487 | } |
---|
472 | 488 | |
---|
473 | | - assignments = DP_CAP_PIN_ASSIGN(dp->alt->vdo); |
---|
| 489 | + assignments = get_current_pin_assignments(dp); |
---|
474 | 490 | |
---|
475 | 491 | if (!(DP_CONF_GET_PIN_ASSIGN(conf) & assignments)) { |
---|
476 | 492 | ret = -EINVAL; |
---|
.. | .. |
---|
507 | 523 | |
---|
508 | 524 | cur = get_count_order(DP_CONF_GET_PIN_ASSIGN(dp->data.conf)); |
---|
509 | 525 | |
---|
510 | | - assignments = DP_CAP_PIN_ASSIGN(dp->alt->vdo); |
---|
| 526 | + assignments = get_current_pin_assignments(dp); |
---|
511 | 527 | |
---|
512 | 528 | for (i = 0; assignments; assignments >>= 1, i++) { |
---|
513 | 529 | if (assignments & 1) { |
---|
.. | .. |
---|
521 | 537 | } |
---|
522 | 538 | |
---|
523 | 539 | mutex_unlock(&dp->lock); |
---|
| 540 | + |
---|
| 541 | + /* get_current_pin_assignments can return 0 when no matching pin assignments are found */ |
---|
| 542 | + if (len == 0) |
---|
| 543 | + len++; |
---|
524 | 544 | |
---|
525 | 545 | buf[len - 1] = '\n'; |
---|
526 | 546 | return len; |
---|
.. | .. |
---|
548 | 568 | /* FIXME: Port can only be DFP_U. */ |
---|
549 | 569 | |
---|
550 | 570 | /* Make sure we have compatiple pin configurations */ |
---|
551 | | - if (!(DP_CAP_DFP_D_PIN_ASSIGN(port->vdo) & |
---|
552 | | - DP_CAP_UFP_D_PIN_ASSIGN(alt->vdo)) && |
---|
553 | | - !(DP_CAP_UFP_D_PIN_ASSIGN(port->vdo) & |
---|
554 | | - DP_CAP_DFP_D_PIN_ASSIGN(alt->vdo))) |
---|
| 571 | + if (!(DP_CAP_PIN_ASSIGN_DFP_D(port->vdo) & |
---|
| 572 | + DP_CAP_PIN_ASSIGN_UFP_D(alt->vdo)) && |
---|
| 573 | + !(DP_CAP_PIN_ASSIGN_UFP_D(port->vdo) & |
---|
| 574 | + DP_CAP_PIN_ASSIGN_DFP_D(alt->vdo))) |
---|
555 | 575 | return -ENODEV; |
---|
556 | 576 | |
---|
557 | 577 | ret = sysfs_create_group(&alt->dev.kobj, &dp_altmode_group); |
---|