diff options
author | Dave Airlie <airlied@redhat.com> | 2019-01-10 15:32:37 -0500 |
---|---|---|
committer | Dave Airlie <airlied@redhat.com> | 2019-01-10 15:32:44 -0500 |
commit | bd86c9e66c8385fb437c5ad506243304a8814b65 (patch) | |
tree | dcfa342e7ee31a1450b4101f7b10c483d32ae97e | |
parent | bfeffd155283772bbe78c6a05dec7c0128ee500c (diff) | |
parent | f8c15790e4d8bdf2d21a5e9d43b5f97983af1222 (diff) |
Merge tag 'drm-misc-fixes-2019-01-10' of git://anongit.freedesktop.org/drm/drm-misc into drm-fixes
Pull request for drm-misc-fixes for v5.0-rc2:
- Fixes for the tc358767 bridge to work correctly with
tc358867 using a DP connector.
- Make resume work on amdgpu when a DP-MST display is unplugged.
Signed-off-by: Dave Airlie <airlied@redhat.com>
From: Maarten Lankhorst <maarten.lankhorst@linux.intel.com>
Link: https://patchwork.freedesktop.org/patch/msgid/1c47722d-c416-184d-4340-0dc6a614d685@linux.intel.com
-rw-r--r-- | drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c | 37 | ||||
-rw-r--r-- | drivers/gpu/drm/bridge/tc358767.c | 48 | ||||
-rw-r--r-- | include/drm/drm_dp_mst_helper.h | 3 |
3 files changed, 65 insertions, 23 deletions
diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c index a9a28dbc3e24..34f35e9a3c46 100644 --- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c +++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c | |||
@@ -699,22 +699,36 @@ static void s3_handle_mst(struct drm_device *dev, bool suspend) | |||
699 | { | 699 | { |
700 | struct amdgpu_dm_connector *aconnector; | 700 | struct amdgpu_dm_connector *aconnector; |
701 | struct drm_connector *connector; | 701 | struct drm_connector *connector; |
702 | struct drm_dp_mst_topology_mgr *mgr; | ||
703 | int ret; | ||
704 | bool need_hotplug = false; | ||
702 | 705 | ||
703 | drm_modeset_lock(&dev->mode_config.connection_mutex, NULL); | 706 | drm_modeset_lock(&dev->mode_config.connection_mutex, NULL); |
704 | 707 | ||
705 | list_for_each_entry(connector, &dev->mode_config.connector_list, head) { | 708 | list_for_each_entry(connector, &dev->mode_config.connector_list, |
706 | aconnector = to_amdgpu_dm_connector(connector); | 709 | head) { |
707 | if (aconnector->dc_link->type == dc_connection_mst_branch && | 710 | aconnector = to_amdgpu_dm_connector(connector); |
708 | !aconnector->mst_port) { | 711 | if (aconnector->dc_link->type != dc_connection_mst_branch || |
712 | aconnector->mst_port) | ||
713 | continue; | ||
709 | 714 | ||
710 | if (suspend) | 715 | mgr = &aconnector->mst_mgr; |
711 | drm_dp_mst_topology_mgr_suspend(&aconnector->mst_mgr); | 716 | |
712 | else | 717 | if (suspend) { |
713 | drm_dp_mst_topology_mgr_resume(&aconnector->mst_mgr); | 718 | drm_dp_mst_topology_mgr_suspend(mgr); |
714 | } | 719 | } else { |
720 | ret = drm_dp_mst_topology_mgr_resume(mgr); | ||
721 | if (ret < 0) { | ||
722 | drm_dp_mst_topology_mgr_set_mst(mgr, false); | ||
723 | need_hotplug = true; | ||
724 | } | ||
725 | } | ||
715 | } | 726 | } |
716 | 727 | ||
717 | drm_modeset_unlock(&dev->mode_config.connection_mutex); | 728 | drm_modeset_unlock(&dev->mode_config.connection_mutex); |
729 | |||
730 | if (need_hotplug) | ||
731 | drm_kms_helper_hotplug_event(dev); | ||
718 | } | 732 | } |
719 | 733 | ||
720 | /** | 734 | /** |
@@ -898,7 +912,6 @@ static int dm_resume(void *handle) | |||
898 | struct drm_plane_state *new_plane_state; | 912 | struct drm_plane_state *new_plane_state; |
899 | struct dm_plane_state *dm_new_plane_state; | 913 | struct dm_plane_state *dm_new_plane_state; |
900 | enum dc_connection_type new_connection_type = dc_connection_none; | 914 | enum dc_connection_type new_connection_type = dc_connection_none; |
901 | int ret; | ||
902 | int i; | 915 | int i; |
903 | 916 | ||
904 | /* power on hardware */ | 917 | /* power on hardware */ |
@@ -971,13 +984,13 @@ static int dm_resume(void *handle) | |||
971 | } | 984 | } |
972 | } | 985 | } |
973 | 986 | ||
974 | ret = drm_atomic_helper_resume(ddev, dm->cached_state); | 987 | drm_atomic_helper_resume(ddev, dm->cached_state); |
975 | 988 | ||
976 | dm->cached_state = NULL; | 989 | dm->cached_state = NULL; |
977 | 990 | ||
978 | amdgpu_dm_irq_resume_late(adev); | 991 | amdgpu_dm_irq_resume_late(adev); |
979 | 992 | ||
980 | return ret; | 993 | return 0; |
981 | } | 994 | } |
982 | 995 | ||
983 | /** | 996 | /** |
diff --git a/drivers/gpu/drm/bridge/tc358767.c b/drivers/gpu/drm/bridge/tc358767.c index 8e28e738cb52..e6403b9549f1 100644 --- a/drivers/gpu/drm/bridge/tc358767.c +++ b/drivers/gpu/drm/bridge/tc358767.c | |||
@@ -98,6 +98,8 @@ | |||
98 | #define DP0_STARTVAL 0x064c | 98 | #define DP0_STARTVAL 0x064c |
99 | #define DP0_ACTIVEVAL 0x0650 | 99 | #define DP0_ACTIVEVAL 0x0650 |
100 | #define DP0_SYNCVAL 0x0654 | 100 | #define DP0_SYNCVAL 0x0654 |
101 | #define SYNCVAL_HS_POL_ACTIVE_LOW (1 << 15) | ||
102 | #define SYNCVAL_VS_POL_ACTIVE_LOW (1 << 31) | ||
101 | #define DP0_MISC 0x0658 | 103 | #define DP0_MISC 0x0658 |
102 | #define TU_SIZE_RECOMMENDED (63) /* LSCLK cycles per TU */ | 104 | #define TU_SIZE_RECOMMENDED (63) /* LSCLK cycles per TU */ |
103 | #define BPC_6 (0 << 5) | 105 | #define BPC_6 (0 << 5) |
@@ -142,6 +144,8 @@ | |||
142 | #define DP0_LTLOOPCTRL 0x06d8 | 144 | #define DP0_LTLOOPCTRL 0x06d8 |
143 | #define DP0_SNKLTCTRL 0x06e4 | 145 | #define DP0_SNKLTCTRL 0x06e4 |
144 | 146 | ||
147 | #define DP1_SRCCTRL 0x07a0 | ||
148 | |||
145 | /* PHY */ | 149 | /* PHY */ |
146 | #define DP_PHY_CTRL 0x0800 | 150 | #define DP_PHY_CTRL 0x0800 |
147 | #define DP_PHY_RST BIT(28) /* DP PHY Global Soft Reset */ | 151 | #define DP_PHY_RST BIT(28) /* DP PHY Global Soft Reset */ |
@@ -150,6 +154,7 @@ | |||
150 | #define PHY_M1_RST BIT(12) /* Reset PHY1 Main Channel */ | 154 | #define PHY_M1_RST BIT(12) /* Reset PHY1 Main Channel */ |
151 | #define PHY_RDY BIT(16) /* PHY Main Channels Ready */ | 155 | #define PHY_RDY BIT(16) /* PHY Main Channels Ready */ |
152 | #define PHY_M0_RST BIT(8) /* Reset PHY0 Main Channel */ | 156 | #define PHY_M0_RST BIT(8) /* Reset PHY0 Main Channel */ |
157 | #define PHY_2LANE BIT(2) /* PHY Enable 2 lanes */ | ||
153 | #define PHY_A0_EN BIT(1) /* PHY Aux Channel0 Enable */ | 158 | #define PHY_A0_EN BIT(1) /* PHY Aux Channel0 Enable */ |
154 | #define PHY_M0_EN BIT(0) /* PHY Main Channel0 Enable */ | 159 | #define PHY_M0_EN BIT(0) /* PHY Main Channel0 Enable */ |
155 | 160 | ||
@@ -540,6 +545,7 @@ static int tc_aux_link_setup(struct tc_data *tc) | |||
540 | unsigned long rate; | 545 | unsigned long rate; |
541 | u32 value; | 546 | u32 value; |
542 | int ret; | 547 | int ret; |
548 | u32 dp_phy_ctrl; | ||
543 | 549 | ||
544 | rate = clk_get_rate(tc->refclk); | 550 | rate = clk_get_rate(tc->refclk); |
545 | switch (rate) { | 551 | switch (rate) { |
@@ -564,7 +570,10 @@ static int tc_aux_link_setup(struct tc_data *tc) | |||
564 | value |= SYSCLK_SEL_LSCLK | LSCLK_DIV_2; | 570 | value |= SYSCLK_SEL_LSCLK | LSCLK_DIV_2; |
565 | tc_write(SYS_PLLPARAM, value); | 571 | tc_write(SYS_PLLPARAM, value); |
566 | 572 | ||
567 | tc_write(DP_PHY_CTRL, BGREN | PWR_SW_EN | BIT(2) | PHY_A0_EN); | 573 | dp_phy_ctrl = BGREN | PWR_SW_EN | PHY_A0_EN; |
574 | if (tc->link.base.num_lanes == 2) | ||
575 | dp_phy_ctrl |= PHY_2LANE; | ||
576 | tc_write(DP_PHY_CTRL, dp_phy_ctrl); | ||
568 | 577 | ||
569 | /* | 578 | /* |
570 | * Initially PLLs are in bypass. Force PLL parameter update, | 579 | * Initially PLLs are in bypass. Force PLL parameter update, |
@@ -719,7 +728,9 @@ static int tc_set_video_mode(struct tc_data *tc, struct drm_display_mode *mode) | |||
719 | 728 | ||
720 | tc_write(DP0_ACTIVEVAL, (mode->vdisplay << 16) | (mode->hdisplay)); | 729 | tc_write(DP0_ACTIVEVAL, (mode->vdisplay << 16) | (mode->hdisplay)); |
721 | 730 | ||
722 | tc_write(DP0_SYNCVAL, (vsync_len << 16) | (hsync_len << 0)); | 731 | tc_write(DP0_SYNCVAL, (vsync_len << 16) | (hsync_len << 0) | |
732 | ((mode->flags & DRM_MODE_FLAG_NHSYNC) ? SYNCVAL_HS_POL_ACTIVE_LOW : 0) | | ||
733 | ((mode->flags & DRM_MODE_FLAG_NVSYNC) ? SYNCVAL_VS_POL_ACTIVE_LOW : 0)); | ||
723 | 734 | ||
724 | tc_write(DPIPXLFMT, VS_POL_ACTIVE_LOW | HS_POL_ACTIVE_LOW | | 735 | tc_write(DPIPXLFMT, VS_POL_ACTIVE_LOW | HS_POL_ACTIVE_LOW | |
725 | DE_POL_ACTIVE_HIGH | SUB_CFG_TYPE_CONFIG1 | DPI_BPP_RGB888); | 736 | DE_POL_ACTIVE_HIGH | SUB_CFG_TYPE_CONFIG1 | DPI_BPP_RGB888); |
@@ -829,12 +840,11 @@ static int tc_main_link_setup(struct tc_data *tc) | |||
829 | if (!tc->mode) | 840 | if (!tc->mode) |
830 | return -EINVAL; | 841 | return -EINVAL; |
831 | 842 | ||
832 | /* from excel file - DP0_SrcCtrl */ | 843 | tc_write(DP0_SRCCTRL, tc_srcctrl(tc)); |
833 | tc_write(DP0_SRCCTRL, DP0_SRCCTRL_SCRMBLDIS | DP0_SRCCTRL_EN810B | | 844 | /* SSCG and BW27 on DP1 must be set to the same as on DP0 */ |
834 | DP0_SRCCTRL_LANESKEW | DP0_SRCCTRL_LANES_2 | | 845 | tc_write(DP1_SRCCTRL, |
835 | DP0_SRCCTRL_BW27 | DP0_SRCCTRL_AUTOCORRECT); | 846 | (tc->link.spread ? DP0_SRCCTRL_SSCG : 0) | |
836 | /* from excel file - DP1_SrcCtrl */ | 847 | ((tc->link.base.rate != 162000) ? DP0_SRCCTRL_BW27 : 0)); |
837 | tc_write(0x07a0, 0x00003083); | ||
838 | 848 | ||
839 | rate = clk_get_rate(tc->refclk); | 849 | rate = clk_get_rate(tc->refclk); |
840 | switch (rate) { | 850 | switch (rate) { |
@@ -855,8 +865,11 @@ static int tc_main_link_setup(struct tc_data *tc) | |||
855 | } | 865 | } |
856 | value |= SYSCLK_SEL_LSCLK | LSCLK_DIV_2; | 866 | value |= SYSCLK_SEL_LSCLK | LSCLK_DIV_2; |
857 | tc_write(SYS_PLLPARAM, value); | 867 | tc_write(SYS_PLLPARAM, value); |
868 | |||
858 | /* Setup Main Link */ | 869 | /* Setup Main Link */ |
859 | dp_phy_ctrl = BGREN | PWR_SW_EN | BIT(2) | PHY_A0_EN | PHY_M0_EN; | 870 | dp_phy_ctrl = BGREN | PWR_SW_EN | PHY_A0_EN | PHY_M0_EN; |
871 | if (tc->link.base.num_lanes == 2) | ||
872 | dp_phy_ctrl |= PHY_2LANE; | ||
860 | tc_write(DP_PHY_CTRL, dp_phy_ctrl); | 873 | tc_write(DP_PHY_CTRL, dp_phy_ctrl); |
861 | msleep(100); | 874 | msleep(100); |
862 | 875 | ||
@@ -1105,10 +1118,20 @@ static bool tc_bridge_mode_fixup(struct drm_bridge *bridge, | |||
1105 | static enum drm_mode_status tc_connector_mode_valid(struct drm_connector *connector, | 1118 | static enum drm_mode_status tc_connector_mode_valid(struct drm_connector *connector, |
1106 | struct drm_display_mode *mode) | 1119 | struct drm_display_mode *mode) |
1107 | { | 1120 | { |
1121 | struct tc_data *tc = connector_to_tc(connector); | ||
1122 | u32 req, avail; | ||
1123 | u32 bits_per_pixel = 24; | ||
1124 | |||
1108 | /* DPI interface clock limitation: upto 154 MHz */ | 1125 | /* DPI interface clock limitation: upto 154 MHz */ |
1109 | if (mode->clock > 154000) | 1126 | if (mode->clock > 154000) |
1110 | return MODE_CLOCK_HIGH; | 1127 | return MODE_CLOCK_HIGH; |
1111 | 1128 | ||
1129 | req = mode->clock * bits_per_pixel / 8; | ||
1130 | avail = tc->link.base.num_lanes * tc->link.base.rate; | ||
1131 | |||
1132 | if (req > avail) | ||
1133 | return MODE_BAD; | ||
1134 | |||
1112 | return MODE_OK; | 1135 | return MODE_OK; |
1113 | } | 1136 | } |
1114 | 1137 | ||
@@ -1186,7 +1209,8 @@ static int tc_bridge_attach(struct drm_bridge *bridge) | |||
1186 | /* Create eDP connector */ | 1209 | /* Create eDP connector */ |
1187 | drm_connector_helper_add(&tc->connector, &tc_connector_helper_funcs); | 1210 | drm_connector_helper_add(&tc->connector, &tc_connector_helper_funcs); |
1188 | ret = drm_connector_init(drm, &tc->connector, &tc_connector_funcs, | 1211 | ret = drm_connector_init(drm, &tc->connector, &tc_connector_funcs, |
1189 | DRM_MODE_CONNECTOR_eDP); | 1212 | tc->panel ? DRM_MODE_CONNECTOR_eDP : |
1213 | DRM_MODE_CONNECTOR_DisplayPort); | ||
1190 | if (ret) | 1214 | if (ret) |
1191 | return ret; | 1215 | return ret; |
1192 | 1216 | ||
@@ -1195,6 +1219,10 @@ static int tc_bridge_attach(struct drm_bridge *bridge) | |||
1195 | 1219 | ||
1196 | drm_display_info_set_bus_formats(&tc->connector.display_info, | 1220 | drm_display_info_set_bus_formats(&tc->connector.display_info, |
1197 | &bus_format, 1); | 1221 | &bus_format, 1); |
1222 | tc->connector.display_info.bus_flags = | ||
1223 | DRM_BUS_FLAG_DE_HIGH | | ||
1224 | DRM_BUS_FLAG_PIXDATA_NEGEDGE | | ||
1225 | DRM_BUS_FLAG_SYNC_NEGEDGE; | ||
1198 | drm_connector_attach_encoder(&tc->connector, tc->bridge.encoder); | 1226 | drm_connector_attach_encoder(&tc->connector, tc->bridge.encoder); |
1199 | 1227 | ||
1200 | return 0; | 1228 | return 0; |
diff --git a/include/drm/drm_dp_mst_helper.h b/include/drm/drm_dp_mst_helper.h index 59f005b419cf..727af08e5ea6 100644 --- a/include/drm/drm_dp_mst_helper.h +++ b/include/drm/drm_dp_mst_helper.h | |||
@@ -616,7 +616,8 @@ void drm_dp_mst_dump_topology(struct seq_file *m, | |||
616 | struct drm_dp_mst_topology_mgr *mgr); | 616 | struct drm_dp_mst_topology_mgr *mgr); |
617 | 617 | ||
618 | void drm_dp_mst_topology_mgr_suspend(struct drm_dp_mst_topology_mgr *mgr); | 618 | void drm_dp_mst_topology_mgr_suspend(struct drm_dp_mst_topology_mgr *mgr); |
619 | int drm_dp_mst_topology_mgr_resume(struct drm_dp_mst_topology_mgr *mgr); | 619 | int __must_check |
620 | drm_dp_mst_topology_mgr_resume(struct drm_dp_mst_topology_mgr *mgr); | ||
620 | struct drm_dp_mst_topology_state *drm_atomic_get_mst_topology_state(struct drm_atomic_state *state, | 621 | struct drm_dp_mst_topology_state *drm_atomic_get_mst_topology_state(struct drm_atomic_state *state, |
621 | struct drm_dp_mst_topology_mgr *mgr); | 622 | struct drm_dp_mst_topology_mgr *mgr); |
622 | int drm_dp_atomic_find_vcpi_slots(struct drm_atomic_state *state, | 623 | int drm_dp_atomic_find_vcpi_slots(struct drm_atomic_state *state, |