Commit bd86c9e6 authored by Dave Airlie's avatar Dave Airlie

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: default avatarDave 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
parents bfeffd15 f8c15790
...@@ -699,22 +699,36 @@ static void s3_handle_mst(struct drm_device *dev, bool suspend) ...@@ -699,22 +699,36 @@ static void s3_handle_mst(struct drm_device *dev, bool suspend)
{ {
struct amdgpu_dm_connector *aconnector; struct amdgpu_dm_connector *aconnector;
struct drm_connector *connector; struct drm_connector *connector;
struct drm_dp_mst_topology_mgr *mgr;
int ret;
bool need_hotplug = false;
drm_modeset_lock(&dev->mode_config.connection_mutex, NULL); drm_modeset_lock(&dev->mode_config.connection_mutex, NULL);
list_for_each_entry(connector, &dev->mode_config.connector_list, head) { list_for_each_entry(connector, &dev->mode_config.connector_list,
aconnector = to_amdgpu_dm_connector(connector); head) {
if (aconnector->dc_link->type == dc_connection_mst_branch && aconnector = to_amdgpu_dm_connector(connector);
!aconnector->mst_port) { if (aconnector->dc_link->type != dc_connection_mst_branch ||
aconnector->mst_port)
continue;
if (suspend) mgr = &aconnector->mst_mgr;
drm_dp_mst_topology_mgr_suspend(&aconnector->mst_mgr);
else if (suspend) {
drm_dp_mst_topology_mgr_resume(&aconnector->mst_mgr); drm_dp_mst_topology_mgr_suspend(mgr);
} } else {
ret = drm_dp_mst_topology_mgr_resume(mgr);
if (ret < 0) {
drm_dp_mst_topology_mgr_set_mst(mgr, false);
need_hotplug = true;
}
}
} }
drm_modeset_unlock(&dev->mode_config.connection_mutex); drm_modeset_unlock(&dev->mode_config.connection_mutex);
if (need_hotplug)
drm_kms_helper_hotplug_event(dev);
} }
/** /**
...@@ -898,7 +912,6 @@ static int dm_resume(void *handle) ...@@ -898,7 +912,6 @@ static int dm_resume(void *handle)
struct drm_plane_state *new_plane_state; struct drm_plane_state *new_plane_state;
struct dm_plane_state *dm_new_plane_state; struct dm_plane_state *dm_new_plane_state;
enum dc_connection_type new_connection_type = dc_connection_none; enum dc_connection_type new_connection_type = dc_connection_none;
int ret;
int i; int i;
/* power on hardware */ /* power on hardware */
...@@ -971,13 +984,13 @@ static int dm_resume(void *handle) ...@@ -971,13 +984,13 @@ static int dm_resume(void *handle)
} }
} }
ret = drm_atomic_helper_resume(ddev, dm->cached_state); drm_atomic_helper_resume(ddev, dm->cached_state);
dm->cached_state = NULL; dm->cached_state = NULL;
amdgpu_dm_irq_resume_late(adev); amdgpu_dm_irq_resume_late(adev);
return ret; return 0;
} }
/** /**
......
...@@ -98,6 +98,8 @@ ...@@ -98,6 +98,8 @@
#define DP0_STARTVAL 0x064c #define DP0_STARTVAL 0x064c
#define DP0_ACTIVEVAL 0x0650 #define DP0_ACTIVEVAL 0x0650
#define DP0_SYNCVAL 0x0654 #define DP0_SYNCVAL 0x0654
#define SYNCVAL_HS_POL_ACTIVE_LOW (1 << 15)
#define SYNCVAL_VS_POL_ACTIVE_LOW (1 << 31)
#define DP0_MISC 0x0658 #define DP0_MISC 0x0658
#define TU_SIZE_RECOMMENDED (63) /* LSCLK cycles per TU */ #define TU_SIZE_RECOMMENDED (63) /* LSCLK cycles per TU */
#define BPC_6 (0 << 5) #define BPC_6 (0 << 5)
...@@ -142,6 +144,8 @@ ...@@ -142,6 +144,8 @@
#define DP0_LTLOOPCTRL 0x06d8 #define DP0_LTLOOPCTRL 0x06d8
#define DP0_SNKLTCTRL 0x06e4 #define DP0_SNKLTCTRL 0x06e4
#define DP1_SRCCTRL 0x07a0
/* PHY */ /* PHY */
#define DP_PHY_CTRL 0x0800 #define DP_PHY_CTRL 0x0800
#define DP_PHY_RST BIT(28) /* DP PHY Global Soft Reset */ #define DP_PHY_RST BIT(28) /* DP PHY Global Soft Reset */
...@@ -150,6 +154,7 @@ ...@@ -150,6 +154,7 @@
#define PHY_M1_RST BIT(12) /* Reset PHY1 Main Channel */ #define PHY_M1_RST BIT(12) /* Reset PHY1 Main Channel */
#define PHY_RDY BIT(16) /* PHY Main Channels Ready */ #define PHY_RDY BIT(16) /* PHY Main Channels Ready */
#define PHY_M0_RST BIT(8) /* Reset PHY0 Main Channel */ #define PHY_M0_RST BIT(8) /* Reset PHY0 Main Channel */
#define PHY_2LANE BIT(2) /* PHY Enable 2 lanes */
#define PHY_A0_EN BIT(1) /* PHY Aux Channel0 Enable */ #define PHY_A0_EN BIT(1) /* PHY Aux Channel0 Enable */
#define PHY_M0_EN BIT(0) /* PHY Main Channel0 Enable */ #define PHY_M0_EN BIT(0) /* PHY Main Channel0 Enable */
...@@ -540,6 +545,7 @@ static int tc_aux_link_setup(struct tc_data *tc) ...@@ -540,6 +545,7 @@ static int tc_aux_link_setup(struct tc_data *tc)
unsigned long rate; unsigned long rate;
u32 value; u32 value;
int ret; int ret;
u32 dp_phy_ctrl;
rate = clk_get_rate(tc->refclk); rate = clk_get_rate(tc->refclk);
switch (rate) { switch (rate) {
...@@ -564,7 +570,10 @@ static int tc_aux_link_setup(struct tc_data *tc) ...@@ -564,7 +570,10 @@ static int tc_aux_link_setup(struct tc_data *tc)
value |= SYSCLK_SEL_LSCLK | LSCLK_DIV_2; value |= SYSCLK_SEL_LSCLK | LSCLK_DIV_2;
tc_write(SYS_PLLPARAM, value); tc_write(SYS_PLLPARAM, value);
tc_write(DP_PHY_CTRL, BGREN | PWR_SW_EN | BIT(2) | PHY_A0_EN); dp_phy_ctrl = BGREN | PWR_SW_EN | PHY_A0_EN;
if (tc->link.base.num_lanes == 2)
dp_phy_ctrl |= PHY_2LANE;
tc_write(DP_PHY_CTRL, dp_phy_ctrl);
/* /*
* Initially PLLs are in bypass. Force PLL parameter update, * 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,7 +728,9 @@ static int tc_set_video_mode(struct tc_data *tc, struct drm_display_mode *mode)
tc_write(DP0_ACTIVEVAL, (mode->vdisplay << 16) | (mode->hdisplay)); tc_write(DP0_ACTIVEVAL, (mode->vdisplay << 16) | (mode->hdisplay));
tc_write(DP0_SYNCVAL, (vsync_len << 16) | (hsync_len << 0)); tc_write(DP0_SYNCVAL, (vsync_len << 16) | (hsync_len << 0) |
((mode->flags & DRM_MODE_FLAG_NHSYNC) ? SYNCVAL_HS_POL_ACTIVE_LOW : 0) |
((mode->flags & DRM_MODE_FLAG_NVSYNC) ? SYNCVAL_VS_POL_ACTIVE_LOW : 0));
tc_write(DPIPXLFMT, VS_POL_ACTIVE_LOW | HS_POL_ACTIVE_LOW | tc_write(DPIPXLFMT, VS_POL_ACTIVE_LOW | HS_POL_ACTIVE_LOW |
DE_POL_ACTIVE_HIGH | SUB_CFG_TYPE_CONFIG1 | DPI_BPP_RGB888); 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,12 +840,11 @@ static int tc_main_link_setup(struct tc_data *tc)
if (!tc->mode) if (!tc->mode)
return -EINVAL; return -EINVAL;
/* from excel file - DP0_SrcCtrl */ tc_write(DP0_SRCCTRL, tc_srcctrl(tc));
tc_write(DP0_SRCCTRL, DP0_SRCCTRL_SCRMBLDIS | DP0_SRCCTRL_EN810B | /* SSCG and BW27 on DP1 must be set to the same as on DP0 */
DP0_SRCCTRL_LANESKEW | DP0_SRCCTRL_LANES_2 | tc_write(DP1_SRCCTRL,
DP0_SRCCTRL_BW27 | DP0_SRCCTRL_AUTOCORRECT); (tc->link.spread ? DP0_SRCCTRL_SSCG : 0) |
/* from excel file - DP1_SrcCtrl */ ((tc->link.base.rate != 162000) ? DP0_SRCCTRL_BW27 : 0));
tc_write(0x07a0, 0x00003083);
rate = clk_get_rate(tc->refclk); rate = clk_get_rate(tc->refclk);
switch (rate) { switch (rate) {
...@@ -855,8 +865,11 @@ static int tc_main_link_setup(struct tc_data *tc) ...@@ -855,8 +865,11 @@ static int tc_main_link_setup(struct tc_data *tc)
} }
value |= SYSCLK_SEL_LSCLK | LSCLK_DIV_2; value |= SYSCLK_SEL_LSCLK | LSCLK_DIV_2;
tc_write(SYS_PLLPARAM, value); tc_write(SYS_PLLPARAM, value);
/* Setup Main Link */ /* Setup Main Link */
dp_phy_ctrl = BGREN | PWR_SW_EN | BIT(2) | PHY_A0_EN | PHY_M0_EN; dp_phy_ctrl = BGREN | PWR_SW_EN | PHY_A0_EN | PHY_M0_EN;
if (tc->link.base.num_lanes == 2)
dp_phy_ctrl |= PHY_2LANE;
tc_write(DP_PHY_CTRL, dp_phy_ctrl); tc_write(DP_PHY_CTRL, dp_phy_ctrl);
msleep(100); msleep(100);
...@@ -1105,10 +1118,20 @@ static bool tc_bridge_mode_fixup(struct drm_bridge *bridge, ...@@ -1105,10 +1118,20 @@ static bool tc_bridge_mode_fixup(struct drm_bridge *bridge,
static enum drm_mode_status tc_connector_mode_valid(struct drm_connector *connector, static enum drm_mode_status tc_connector_mode_valid(struct drm_connector *connector,
struct drm_display_mode *mode) struct drm_display_mode *mode)
{ {
struct tc_data *tc = connector_to_tc(connector);
u32 req, avail;
u32 bits_per_pixel = 24;
/* DPI interface clock limitation: upto 154 MHz */ /* DPI interface clock limitation: upto 154 MHz */
if (mode->clock > 154000) if (mode->clock > 154000)
return MODE_CLOCK_HIGH; return MODE_CLOCK_HIGH;
req = mode->clock * bits_per_pixel / 8;
avail = tc->link.base.num_lanes * tc->link.base.rate;
if (req > avail)
return MODE_BAD;
return MODE_OK; return MODE_OK;
} }
...@@ -1186,7 +1209,8 @@ static int tc_bridge_attach(struct drm_bridge *bridge) ...@@ -1186,7 +1209,8 @@ static int tc_bridge_attach(struct drm_bridge *bridge)
/* Create eDP connector */ /* Create eDP connector */
drm_connector_helper_add(&tc->connector, &tc_connector_helper_funcs); drm_connector_helper_add(&tc->connector, &tc_connector_helper_funcs);
ret = drm_connector_init(drm, &tc->connector, &tc_connector_funcs, ret = drm_connector_init(drm, &tc->connector, &tc_connector_funcs,
DRM_MODE_CONNECTOR_eDP); tc->panel ? DRM_MODE_CONNECTOR_eDP :
DRM_MODE_CONNECTOR_DisplayPort);
if (ret) if (ret)
return ret; return ret;
...@@ -1195,6 +1219,10 @@ static int tc_bridge_attach(struct drm_bridge *bridge) ...@@ -1195,6 +1219,10 @@ static int tc_bridge_attach(struct drm_bridge *bridge)
drm_display_info_set_bus_formats(&tc->connector.display_info, drm_display_info_set_bus_formats(&tc->connector.display_info,
&bus_format, 1); &bus_format, 1);
tc->connector.display_info.bus_flags =
DRM_BUS_FLAG_DE_HIGH |
DRM_BUS_FLAG_PIXDATA_NEGEDGE |
DRM_BUS_FLAG_SYNC_NEGEDGE;
drm_connector_attach_encoder(&tc->connector, tc->bridge.encoder); drm_connector_attach_encoder(&tc->connector, tc->bridge.encoder);
return 0; return 0;
......
...@@ -616,7 +616,8 @@ void drm_dp_mst_dump_topology(struct seq_file *m, ...@@ -616,7 +616,8 @@ void drm_dp_mst_dump_topology(struct seq_file *m,
struct drm_dp_mst_topology_mgr *mgr); struct drm_dp_mst_topology_mgr *mgr);
void drm_dp_mst_topology_mgr_suspend(struct drm_dp_mst_topology_mgr *mgr); void drm_dp_mst_topology_mgr_suspend(struct drm_dp_mst_topology_mgr *mgr);
int drm_dp_mst_topology_mgr_resume(struct drm_dp_mst_topology_mgr *mgr); int __must_check
drm_dp_mst_topology_mgr_resume(struct drm_dp_mst_topology_mgr *mgr);
struct drm_dp_mst_topology_state *drm_atomic_get_mst_topology_state(struct drm_atomic_state *state, struct drm_dp_mst_topology_state *drm_atomic_get_mst_topology_state(struct drm_atomic_state *state,
struct drm_dp_mst_topology_mgr *mgr); struct drm_dp_mst_topology_mgr *mgr);
int drm_dp_atomic_find_vcpi_slots(struct drm_atomic_state *state, int drm_dp_atomic_find_vcpi_slots(struct drm_atomic_state *state,
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment