|
26 | 26 | #include "head.h"
|
27 | 27 | #include "ior.h"
|
28 | 28 |
|
| 29 | +#include <drm/display/drm_dp.h> |
| 30 | + |
29 | 31 | #include <subdev/bios.h>
|
30 | 32 | #include <subdev/bios/init.h>
|
31 | 33 | #include <subdev/gpio.h>
|
@@ -634,6 +636,50 @@ nvkm_dp_enable_supported_link_rates(struct nvkm_outp *outp)
|
634 | 636 | return outp->dp.rates != 0;
|
635 | 637 | }
|
636 | 638 |
|
| 639 | +/* XXX: This is a big fat hack, and this is just drm_dp_read_dpcd_caps() |
| 640 | + * converted to work inside nvkm. This is a temporary holdover until we start |
| 641 | + * passing the drm_dp_aux device through NVKM |
| 642 | + */ |
| 643 | +static int |
| 644 | +nvkm_dp_read_dpcd_caps(struct nvkm_outp *outp) |
| 645 | +{ |
| 646 | + struct nvkm_i2c_aux *aux = outp->dp.aux; |
| 647 | + u8 dpcd_ext[DP_RECEIVER_CAP_SIZE]; |
| 648 | + int ret; |
| 649 | + |
| 650 | + ret = nvkm_rdaux(aux, DPCD_RC00_DPCD_REV, outp->dp.dpcd, DP_RECEIVER_CAP_SIZE); |
| 651 | + if (ret < 0) |
| 652 | + return ret; |
| 653 | + |
| 654 | + /* |
| 655 | + * Prior to DP1.3 the bit represented by |
| 656 | + * DP_EXTENDED_RECEIVER_CAP_FIELD_PRESENT was reserved. |
| 657 | + * If it is set DP_DPCD_REV at 0000h could be at a value less than |
| 658 | + * the true capability of the panel. The only way to check is to |
| 659 | + * then compare 0000h and 2200h. |
| 660 | + */ |
| 661 | + if (!(outp->dp.dpcd[DP_TRAINING_AUX_RD_INTERVAL] & |
| 662 | + DP_EXTENDED_RECEIVER_CAP_FIELD_PRESENT)) |
| 663 | + return 0; |
| 664 | + |
| 665 | + ret = nvkm_rdaux(aux, DP_DP13_DPCD_REV, dpcd_ext, sizeof(dpcd_ext)); |
| 666 | + if (ret < 0) |
| 667 | + return ret; |
| 668 | + |
| 669 | + if (outp->dp.dpcd[DP_DPCD_REV] > dpcd_ext[DP_DPCD_REV]) { |
| 670 | + OUTP_DBG(outp, "Extended DPCD rev less than base DPCD rev (%d > %d)\n", |
| 671 | + outp->dp.dpcd[DP_DPCD_REV], dpcd_ext[DP_DPCD_REV]); |
| 672 | + return 0; |
| 673 | + } |
| 674 | + |
| 675 | + if (!memcmp(outp->dp.dpcd, dpcd_ext, sizeof(dpcd_ext))) |
| 676 | + return 0; |
| 677 | + |
| 678 | + memcpy(outp->dp.dpcd, dpcd_ext, sizeof(dpcd_ext)); |
| 679 | + |
| 680 | + return 0; |
| 681 | +} |
| 682 | + |
637 | 683 | void
|
638 | 684 | nvkm_dp_enable(struct nvkm_outp *outp, bool auxpwr)
|
639 | 685 | {
|
@@ -689,7 +735,7 @@ nvkm_dp_enable(struct nvkm_outp *outp, bool auxpwr)
|
689 | 735 | memset(outp->dp.lttpr, 0x00, sizeof(outp->dp.lttpr));
|
690 | 736 | }
|
691 | 737 |
|
692 |
| - if (!nvkm_rdaux(aux, DPCD_RC00_DPCD_REV, outp->dp.dpcd, sizeof(outp->dp.dpcd))) { |
| 738 | + if (!nvkm_dp_read_dpcd_caps(outp)) { |
693 | 739 | const u8 rates[] = { 0x1e, 0x14, 0x0a, 0x06, 0 };
|
694 | 740 | const u8 *rate;
|
695 | 741 | int rate_max;
|
|
0 commit comments