Commit 67c6ed7c authored by Dave Airlie's avatar Dave Airlie

Merge tag 'drm-intel-fixes-2018-09-05' of...

Merge tag 'drm-intel-fixes-2018-09-05' of git://anongit.freedesktop.org/drm/drm-intel into drm-fixes

The critical fix here on display side is the DP MST regression one.
But this pull also include fixes for DP SST, small VDSC register fix
and GVT's bucked with "BXT fixes, two guest warning fixes, dmabuf
format mod fix and one for recent multiple VM timeout failure."
Signed-off-by: default avatarDave Airlie <airlied@redhat.com>

From: Rodrigo Vivi <rodrigo.vivi@intel.com>
Link: https://patchwork.freedesktop.org/patch/msgid/20180905183000.GA2151@intel.com
parents 57361846 2b82435c
...@@ -170,20 +170,22 @@ static struct drm_i915_gem_object *vgpu_create_gem(struct drm_device *dev, ...@@ -170,20 +170,22 @@ static struct drm_i915_gem_object *vgpu_create_gem(struct drm_device *dev,
unsigned int tiling_mode = 0; unsigned int tiling_mode = 0;
unsigned int stride = 0; unsigned int stride = 0;
switch (info->drm_format_mod << 10) { switch (info->drm_format_mod) {
case PLANE_CTL_TILED_LINEAR: case DRM_FORMAT_MOD_LINEAR:
tiling_mode = I915_TILING_NONE; tiling_mode = I915_TILING_NONE;
break; break;
case PLANE_CTL_TILED_X: case I915_FORMAT_MOD_X_TILED:
tiling_mode = I915_TILING_X; tiling_mode = I915_TILING_X;
stride = info->stride; stride = info->stride;
break; break;
case PLANE_CTL_TILED_Y: case I915_FORMAT_MOD_Y_TILED:
case I915_FORMAT_MOD_Yf_TILED:
tiling_mode = I915_TILING_Y; tiling_mode = I915_TILING_Y;
stride = info->stride; stride = info->stride;
break; break;
default: default:
gvt_dbg_core("not supported tiling mode\n"); gvt_dbg_core("invalid drm_format_mod %llx for tiling\n",
info->drm_format_mod);
} }
obj->tiling_and_stride = tiling_mode | stride; obj->tiling_and_stride = tiling_mode | stride;
} else { } else {
...@@ -222,9 +224,26 @@ static int vgpu_get_plane_info(struct drm_device *dev, ...@@ -222,9 +224,26 @@ static int vgpu_get_plane_info(struct drm_device *dev,
info->height = p.height; info->height = p.height;
info->stride = p.stride; info->stride = p.stride;
info->drm_format = p.drm_format; info->drm_format = p.drm_format;
info->drm_format_mod = p.tiled;
switch (p.tiled) {
case PLANE_CTL_TILED_LINEAR:
info->drm_format_mod = DRM_FORMAT_MOD_LINEAR;
break;
case PLANE_CTL_TILED_X:
info->drm_format_mod = I915_FORMAT_MOD_X_TILED;
break;
case PLANE_CTL_TILED_Y:
info->drm_format_mod = I915_FORMAT_MOD_Y_TILED;
break;
case PLANE_CTL_TILED_YF:
info->drm_format_mod = I915_FORMAT_MOD_Yf_TILED;
break;
default:
gvt_vgpu_err("invalid tiling mode: %x\n", p.tiled);
}
info->size = (((p.stride * p.height * p.bpp) / 8) + info->size = (((p.stride * p.height * p.bpp) / 8) +
(PAGE_SIZE - 1)) >> PAGE_SHIFT; (PAGE_SIZE - 1)) >> PAGE_SHIFT;
} else if (plane_id == DRM_PLANE_TYPE_CURSOR) { } else if (plane_id == DRM_PLANE_TYPE_CURSOR) {
ret = intel_vgpu_decode_cursor_plane(vgpu, &c); ret = intel_vgpu_decode_cursor_plane(vgpu, &c);
if (ret) if (ret)
......
...@@ -220,8 +220,7 @@ int intel_vgpu_decode_primary_plane(struct intel_vgpu *vgpu, ...@@ -220,8 +220,7 @@ int intel_vgpu_decode_primary_plane(struct intel_vgpu *vgpu,
if (IS_SKYLAKE(dev_priv) if (IS_SKYLAKE(dev_priv)
|| IS_KABYLAKE(dev_priv) || IS_KABYLAKE(dev_priv)
|| IS_BROXTON(dev_priv)) { || IS_BROXTON(dev_priv)) {
plane->tiled = (val & PLANE_CTL_TILED_MASK) >> plane->tiled = val & PLANE_CTL_TILED_MASK;
_PLANE_CTL_TILED_SHIFT;
fmt = skl_format_to_drm( fmt = skl_format_to_drm(
val & PLANE_CTL_FORMAT_MASK, val & PLANE_CTL_FORMAT_MASK,
val & PLANE_CTL_ORDER_RGBX, val & PLANE_CTL_ORDER_RGBX,
...@@ -260,7 +259,7 @@ int intel_vgpu_decode_primary_plane(struct intel_vgpu *vgpu, ...@@ -260,7 +259,7 @@ int intel_vgpu_decode_primary_plane(struct intel_vgpu *vgpu,
return -EINVAL; return -EINVAL;
} }
plane->stride = intel_vgpu_get_stride(vgpu, pipe, (plane->tiled << 10), plane->stride = intel_vgpu_get_stride(vgpu, pipe, plane->tiled,
(IS_SKYLAKE(dev_priv) (IS_SKYLAKE(dev_priv)
|| IS_KABYLAKE(dev_priv) || IS_KABYLAKE(dev_priv)
|| IS_BROXTON(dev_priv)) ? || IS_BROXTON(dev_priv)) ?
......
...@@ -101,7 +101,7 @@ struct intel_gvt; ...@@ -101,7 +101,7 @@ struct intel_gvt;
/* color space conversion and gamma correction are not included */ /* color space conversion and gamma correction are not included */
struct intel_vgpu_primary_plane_format { struct intel_vgpu_primary_plane_format {
u8 enabled; /* plane is enabled */ u8 enabled; /* plane is enabled */
u8 tiled; /* X-tiled */ u32 tiled; /* tiling mode: linear, X-tiled, Y tiled, etc */
u8 bpp; /* bits per pixel */ u8 bpp; /* bits per pixel */
u32 hw_format; /* format field in the PRI_CTL register */ u32 hw_format; /* format field in the PRI_CTL register */
u32 drm_format; /* format in DRM definition */ u32 drm_format; /* format in DRM definition */
......
...@@ -1296,6 +1296,19 @@ static int power_well_ctl_mmio_write(struct intel_vgpu *vgpu, ...@@ -1296,6 +1296,19 @@ static int power_well_ctl_mmio_write(struct intel_vgpu *vgpu,
return 0; return 0;
} }
static int gen9_dbuf_ctl_mmio_write(struct intel_vgpu *vgpu,
unsigned int offset, void *p_data, unsigned int bytes)
{
write_vreg(vgpu, offset, p_data, bytes);
if (vgpu_vreg(vgpu, offset) & DBUF_POWER_REQUEST)
vgpu_vreg(vgpu, offset) |= DBUF_POWER_STATE;
else
vgpu_vreg(vgpu, offset) &= ~DBUF_POWER_STATE;
return 0;
}
static int fpga_dbg_mmio_write(struct intel_vgpu *vgpu, static int fpga_dbg_mmio_write(struct intel_vgpu *vgpu,
unsigned int offset, void *p_data, unsigned int bytes) unsigned int offset, void *p_data, unsigned int bytes)
{ {
...@@ -1525,9 +1538,15 @@ static int bxt_phy_ctl_family_write(struct intel_vgpu *vgpu, ...@@ -1525,9 +1538,15 @@ static int bxt_phy_ctl_family_write(struct intel_vgpu *vgpu,
u32 v = *(u32 *)p_data; u32 v = *(u32 *)p_data;
u32 data = v & COMMON_RESET_DIS ? BXT_PHY_LANE_ENABLED : 0; u32 data = v & COMMON_RESET_DIS ? BXT_PHY_LANE_ENABLED : 0;
vgpu_vreg(vgpu, _BXT_PHY_CTL_DDI_A) = data; switch (offset) {
vgpu_vreg(vgpu, _BXT_PHY_CTL_DDI_B) = data; case _PHY_CTL_FAMILY_EDP:
vgpu_vreg(vgpu, _BXT_PHY_CTL_DDI_C) = data; vgpu_vreg(vgpu, _BXT_PHY_CTL_DDI_A) = data;
break;
case _PHY_CTL_FAMILY_DDI:
vgpu_vreg(vgpu, _BXT_PHY_CTL_DDI_B) = data;
vgpu_vreg(vgpu, _BXT_PHY_CTL_DDI_C) = data;
break;
}
vgpu_vreg(vgpu, offset) = v; vgpu_vreg(vgpu, offset) = v;
...@@ -2812,6 +2831,8 @@ static int init_skl_mmio_info(struct intel_gvt *gvt) ...@@ -2812,6 +2831,8 @@ static int init_skl_mmio_info(struct intel_gvt *gvt)
MMIO_DH(HSW_PWR_WELL_CTL_DRIVER(SKL_DISP_PW_MISC_IO), D_SKL_PLUS, NULL, MMIO_DH(HSW_PWR_WELL_CTL_DRIVER(SKL_DISP_PW_MISC_IO), D_SKL_PLUS, NULL,
skl_power_well_ctl_write); skl_power_well_ctl_write);
MMIO_DH(DBUF_CTL, D_SKL_PLUS, NULL, gen9_dbuf_ctl_mmio_write);
MMIO_D(_MMIO(0xa210), D_SKL_PLUS); MMIO_D(_MMIO(0xa210), D_SKL_PLUS);
MMIO_D(GEN9_MEDIA_PG_IDLE_HYSTERESIS, D_SKL_PLUS); MMIO_D(GEN9_MEDIA_PG_IDLE_HYSTERESIS, D_SKL_PLUS);
MMIO_D(GEN9_RENDER_PG_IDLE_HYSTERESIS, D_SKL_PLUS); MMIO_D(GEN9_RENDER_PG_IDLE_HYSTERESIS, D_SKL_PLUS);
...@@ -2987,8 +3008,6 @@ static int init_skl_mmio_info(struct intel_gvt *gvt) ...@@ -2987,8 +3008,6 @@ static int init_skl_mmio_info(struct intel_gvt *gvt)
NULL, gen9_trtte_write); NULL, gen9_trtte_write);
MMIO_DH(_MMIO(0x4dfc), D_SKL_PLUS, NULL, gen9_trtt_chicken_write); MMIO_DH(_MMIO(0x4dfc), D_SKL_PLUS, NULL, gen9_trtt_chicken_write);
MMIO_D(_MMIO(0x45008), D_SKL_PLUS);
MMIO_D(_MMIO(0x46430), D_SKL_PLUS); MMIO_D(_MMIO(0x46430), D_SKL_PLUS);
MMIO_D(_MMIO(0x46520), D_SKL_PLUS); MMIO_D(_MMIO(0x46520), D_SKL_PLUS);
...@@ -3025,7 +3044,9 @@ static int init_skl_mmio_info(struct intel_gvt *gvt) ...@@ -3025,7 +3044,9 @@ static int init_skl_mmio_info(struct intel_gvt *gvt)
MMIO_D(_MMIO(0x44500), D_SKL_PLUS); MMIO_D(_MMIO(0x44500), D_SKL_PLUS);
MMIO_DFH(GEN9_CSFE_CHICKEN1_RCS, D_SKL_PLUS, F_CMD_ACCESS, NULL, NULL); MMIO_DFH(GEN9_CSFE_CHICKEN1_RCS, D_SKL_PLUS, F_CMD_ACCESS, NULL, NULL);
MMIO_DFH(GEN8_HDC_CHICKEN1, D_SKL_PLUS, F_MODE_MASK | F_CMD_ACCESS, MMIO_DFH(GEN8_HDC_CHICKEN1, D_SKL_PLUS, F_MODE_MASK | F_CMD_ACCESS,
NULL, NULL); NULL, NULL);
MMIO_DFH(GEN9_WM_CHICKEN3, D_SKL_PLUS, F_MODE_MASK | F_CMD_ACCESS,
NULL, NULL);
MMIO_D(_MMIO(0x4ab8), D_KBL); MMIO_D(_MMIO(0x4ab8), D_KBL);
MMIO_D(_MMIO(0x2248), D_KBL | D_SKL); MMIO_D(_MMIO(0x2248), D_KBL | D_SKL);
......
...@@ -562,11 +562,9 @@ void intel_gvt_switch_mmio(struct intel_vgpu *pre, ...@@ -562,11 +562,9 @@ void intel_gvt_switch_mmio(struct intel_vgpu *pre,
* performace for batch mmio read/write, so we need * performace for batch mmio read/write, so we need
* handle forcewake mannually. * handle forcewake mannually.
*/ */
intel_runtime_pm_get(dev_priv);
intel_uncore_forcewake_get(dev_priv, FORCEWAKE_ALL); intel_uncore_forcewake_get(dev_priv, FORCEWAKE_ALL);
switch_mmio(pre, next, ring_id); switch_mmio(pre, next, ring_id);
intel_uncore_forcewake_put(dev_priv, FORCEWAKE_ALL); intel_uncore_forcewake_put(dev_priv, FORCEWAKE_ALL);
intel_runtime_pm_put(dev_priv);
} }
/** /**
......
...@@ -47,11 +47,15 @@ static bool vgpu_has_pending_workload(struct intel_vgpu *vgpu) ...@@ -47,11 +47,15 @@ static bool vgpu_has_pending_workload(struct intel_vgpu *vgpu)
return false; return false;
} }
/* We give 2 seconds higher prio for vGPU during start */
#define GVT_SCHED_VGPU_PRI_TIME 2
struct vgpu_sched_data { struct vgpu_sched_data {
struct list_head lru_list; struct list_head lru_list;
struct intel_vgpu *vgpu; struct intel_vgpu *vgpu;
bool active; bool active;
bool pri_sched;
ktime_t pri_time;
ktime_t sched_in_time; ktime_t sched_in_time;
ktime_t sched_time; ktime_t sched_time;
ktime_t left_ts; ktime_t left_ts;
...@@ -183,6 +187,14 @@ static struct intel_vgpu *find_busy_vgpu(struct gvt_sched_data *sched_data) ...@@ -183,6 +187,14 @@ static struct intel_vgpu *find_busy_vgpu(struct gvt_sched_data *sched_data)
if (!vgpu_has_pending_workload(vgpu_data->vgpu)) if (!vgpu_has_pending_workload(vgpu_data->vgpu))
continue; continue;
if (vgpu_data->pri_sched) {
if (ktime_before(ktime_get(), vgpu_data->pri_time)) {
vgpu = vgpu_data->vgpu;
break;
} else
vgpu_data->pri_sched = false;
}
/* Return the vGPU only if it has time slice left */ /* Return the vGPU only if it has time slice left */
if (vgpu_data->left_ts > 0) { if (vgpu_data->left_ts > 0) {
vgpu = vgpu_data->vgpu; vgpu = vgpu_data->vgpu;
...@@ -202,6 +214,7 @@ static void tbs_sched_func(struct gvt_sched_data *sched_data) ...@@ -202,6 +214,7 @@ static void tbs_sched_func(struct gvt_sched_data *sched_data)
struct intel_gvt_workload_scheduler *scheduler = &gvt->scheduler; struct intel_gvt_workload_scheduler *scheduler = &gvt->scheduler;
struct vgpu_sched_data *vgpu_data; struct vgpu_sched_data *vgpu_data;
struct intel_vgpu *vgpu = NULL; struct intel_vgpu *vgpu = NULL;
/* no active vgpu or has already had a target */ /* no active vgpu or has already had a target */
if (list_empty(&sched_data->lru_runq_head) || scheduler->next_vgpu) if (list_empty(&sched_data->lru_runq_head) || scheduler->next_vgpu)
goto out; goto out;
...@@ -209,12 +222,13 @@ static void tbs_sched_func(struct gvt_sched_data *sched_data) ...@@ -209,12 +222,13 @@ static void tbs_sched_func(struct gvt_sched_data *sched_data)
vgpu = find_busy_vgpu(sched_data); vgpu = find_busy_vgpu(sched_data);
if (vgpu) { if (vgpu) {
scheduler->next_vgpu = vgpu; scheduler->next_vgpu = vgpu;
/* Move the last used vGPU to the tail of lru_list */
vgpu_data = vgpu->sched_data; vgpu_data = vgpu->sched_data;
list_del_init(&vgpu_data->lru_list); if (!vgpu_data->pri_sched) {
list_add_tail(&vgpu_data->lru_list, /* Move the last used vGPU to the tail of lru_list */
&sched_data->lru_runq_head); list_del_init(&vgpu_data->lru_list);
list_add_tail(&vgpu_data->lru_list,
&sched_data->lru_runq_head);
}
} else { } else {
scheduler->next_vgpu = gvt->idle_vgpu; scheduler->next_vgpu = gvt->idle_vgpu;
} }
...@@ -328,11 +342,17 @@ static void tbs_sched_start_schedule(struct intel_vgpu *vgpu) ...@@ -328,11 +342,17 @@ static void tbs_sched_start_schedule(struct intel_vgpu *vgpu)
{ {
struct gvt_sched_data *sched_data = vgpu->gvt->scheduler.sched_data; struct gvt_sched_data *sched_data = vgpu->gvt->scheduler.sched_data;
struct vgpu_sched_data *vgpu_data = vgpu->sched_data; struct vgpu_sched_data *vgpu_data = vgpu->sched_data;
ktime_t now;
if (!list_empty(&vgpu_data->lru_list)) if (!list_empty(&vgpu_data->lru_list))
return; return;
list_add_tail(&vgpu_data->lru_list, &sched_data->lru_runq_head); now = ktime_get();
vgpu_data->pri_time = ktime_add(now,
ktime_set(GVT_SCHED_VGPU_PRI_TIME, 0));
vgpu_data->pri_sched = true;
list_add(&vgpu_data->lru_list, &sched_data->lru_runq_head);
if (!hrtimer_active(&sched_data->timer)) if (!hrtimer_active(&sched_data->timer))
hrtimer_start(&sched_data->timer, ktime_add_ns(ktime_get(), hrtimer_start(&sched_data->timer, ktime_add_ns(ktime_get(),
...@@ -426,6 +446,7 @@ void intel_vgpu_stop_schedule(struct intel_vgpu *vgpu) ...@@ -426,6 +446,7 @@ void intel_vgpu_stop_schedule(struct intel_vgpu *vgpu)
&vgpu->gvt->scheduler; &vgpu->gvt->scheduler;
int ring_id; int ring_id;
struct vgpu_sched_data *vgpu_data = vgpu->sched_data; struct vgpu_sched_data *vgpu_data = vgpu->sched_data;
struct drm_i915_private *dev_priv = vgpu->gvt->dev_priv;
if (!vgpu_data->active) if (!vgpu_data->active)
return; return;
...@@ -444,6 +465,7 @@ void intel_vgpu_stop_schedule(struct intel_vgpu *vgpu) ...@@ -444,6 +465,7 @@ void intel_vgpu_stop_schedule(struct intel_vgpu *vgpu)
scheduler->current_vgpu = NULL; scheduler->current_vgpu = NULL;
} }
intel_runtime_pm_get(dev_priv);
spin_lock_bh(&scheduler->mmio_context_lock); spin_lock_bh(&scheduler->mmio_context_lock);
for (ring_id = 0; ring_id < I915_NUM_ENGINES; ring_id++) { for (ring_id = 0; ring_id < I915_NUM_ENGINES; ring_id++) {
if (scheduler->engine_owner[ring_id] == vgpu) { if (scheduler->engine_owner[ring_id] == vgpu) {
...@@ -452,5 +474,6 @@ void intel_vgpu_stop_schedule(struct intel_vgpu *vgpu) ...@@ -452,5 +474,6 @@ void intel_vgpu_stop_schedule(struct intel_vgpu *vgpu)
} }
} }
spin_unlock_bh(&scheduler->mmio_context_lock); spin_unlock_bh(&scheduler->mmio_context_lock);
intel_runtime_pm_put(dev_priv);
mutex_unlock(&vgpu->gvt->sched_lock); mutex_unlock(&vgpu->gvt->sched_lock);
} }
...@@ -10422,7 +10422,7 @@ enum skl_power_gate { ...@@ -10422,7 +10422,7 @@ enum skl_power_gate {
_ICL_DSC0_PICTURE_PARAMETER_SET_4_PB, \ _ICL_DSC0_PICTURE_PARAMETER_SET_4_PB, \
_ICL_DSC0_PICTURE_PARAMETER_SET_4_PC) _ICL_DSC0_PICTURE_PARAMETER_SET_4_PC)
#define ICL_DSC1_PICTURE_PARAMETER_SET_4(pipe) _MMIO_PIPE((pipe) - PIPE_B, \ #define ICL_DSC1_PICTURE_PARAMETER_SET_4(pipe) _MMIO_PIPE((pipe) - PIPE_B, \
_ICL_DSC0_PICTURE_PARAMETER_SET_4_PB, \ _ICL_DSC1_PICTURE_PARAMETER_SET_4_PB, \
_ICL_DSC1_PICTURE_PARAMETER_SET_4_PC) _ICL_DSC1_PICTURE_PARAMETER_SET_4_PC)
#define DSC_INITIAL_DEC_DELAY(dec_delay) ((dec_delay) << 16) #define DSC_INITIAL_DEC_DELAY(dec_delay) ((dec_delay) << 16)
#define DSC_INITIAL_XMIT_DELAY(xmit_delay) ((xmit_delay) << 0) #define DSC_INITIAL_XMIT_DELAY(xmit_delay) ((xmit_delay) << 0)
...@@ -10437,7 +10437,7 @@ enum skl_power_gate { ...@@ -10437,7 +10437,7 @@ enum skl_power_gate {
_ICL_DSC0_PICTURE_PARAMETER_SET_5_PB, \ _ICL_DSC0_PICTURE_PARAMETER_SET_5_PB, \
_ICL_DSC0_PICTURE_PARAMETER_SET_5_PC) _ICL_DSC0_PICTURE_PARAMETER_SET_5_PC)
#define ICL_DSC1_PICTURE_PARAMETER_SET_5(pipe) _MMIO_PIPE((pipe) - PIPE_B, \ #define ICL_DSC1_PICTURE_PARAMETER_SET_5(pipe) _MMIO_PIPE((pipe) - PIPE_B, \
_ICL_DSC1_PICTURE_PARAMETER_SET_5_PC, \ _ICL_DSC1_PICTURE_PARAMETER_SET_5_PB, \
_ICL_DSC1_PICTURE_PARAMETER_SET_5_PC) _ICL_DSC1_PICTURE_PARAMETER_SET_5_PC)
#define DSC_SCALE_DEC_INTINT(scale_dec) ((scale_dec) << 16) #define DSC_SCALE_DEC_INTINT(scale_dec) ((scale_dec) << 16)
#define DSC_SCALE_INC_INT(scale_inc) ((scale_inc) << 0) #define DSC_SCALE_INC_INT(scale_inc) ((scale_inc) << 0)
......
...@@ -2708,7 +2708,8 @@ static void intel_ddi_pre_enable_dp(struct intel_encoder *encoder, ...@@ -2708,7 +2708,8 @@ static void intel_ddi_pre_enable_dp(struct intel_encoder *encoder,
if (port != PORT_A || INTEL_GEN(dev_priv) >= 9) if (port != PORT_A || INTEL_GEN(dev_priv) >= 9)
intel_dp_stop_link_train(intel_dp); intel_dp_stop_link_train(intel_dp);
intel_ddi_enable_pipe_clock(crtc_state); if (!is_mst)
intel_ddi_enable_pipe_clock(crtc_state);
} }
static void intel_ddi_pre_enable_hdmi(struct intel_encoder *encoder, static void intel_ddi_pre_enable_hdmi(struct intel_encoder *encoder,
...@@ -2810,14 +2811,14 @@ static void intel_ddi_post_disable_dp(struct intel_encoder *encoder, ...@@ -2810,14 +2811,14 @@ static void intel_ddi_post_disable_dp(struct intel_encoder *encoder,
bool is_mst = intel_crtc_has_type(old_crtc_state, bool is_mst = intel_crtc_has_type(old_crtc_state,
INTEL_OUTPUT_DP_MST); INTEL_OUTPUT_DP_MST);
intel_ddi_disable_pipe_clock(old_crtc_state); if (!is_mst) {
intel_ddi_disable_pipe_clock(old_crtc_state);
/* /*
* Power down sink before disabling the port, otherwise we end * Power down sink before disabling the port, otherwise we end
* up getting interrupts from the sink on detecting link loss. * up getting interrupts from the sink on detecting link loss.
*/ */
if (!is_mst)
intel_dp_sink_dpms(intel_dp, DRM_MODE_DPMS_OFF); intel_dp_sink_dpms(intel_dp, DRM_MODE_DPMS_OFF);
}
intel_disable_ddi_buf(encoder); intel_disable_ddi_buf(encoder);
......
...@@ -4160,18 +4160,6 @@ intel_dp_needs_link_retrain(struct intel_dp *intel_dp) ...@@ -4160,18 +4160,6 @@ intel_dp_needs_link_retrain(struct intel_dp *intel_dp)
return !drm_dp_channel_eq_ok(link_status, intel_dp->lane_count); return !drm_dp_channel_eq_ok(link_status, intel_dp->lane_count);
} }
/*
* If display is now connected check links status,
* there has been known issues of link loss triggering
* long pulse.
*
* Some sinks (eg. ASUS PB287Q) seem to perform some
* weird HPD ping pong during modesets. So we can apparently
* end up with HPD going low during a modeset, and then
* going back up soon after. And once that happens we must
* retrain the link to get a picture. That's in case no
* userspace component reacted to intermittent HPD dip.
*/
int intel_dp_retrain_link(struct intel_encoder *encoder, int intel_dp_retrain_link(struct intel_encoder *encoder,
struct drm_modeset_acquire_ctx *ctx) struct drm_modeset_acquire_ctx *ctx)
{ {
...@@ -4661,7 +4649,8 @@ intel_dp_unset_edid(struct intel_dp *intel_dp) ...@@ -4661,7 +4649,8 @@ intel_dp_unset_edid(struct intel_dp *intel_dp)
} }
static int static int
intel_dp_long_pulse(struct intel_connector *connector) intel_dp_long_pulse(struct intel_connector *connector,
struct drm_modeset_acquire_ctx *ctx)
{ {
struct drm_i915_private *dev_priv = to_i915(connector->base.dev); struct drm_i915_private *dev_priv = to_i915(connector->base.dev);
struct intel_dp *intel_dp = intel_attached_dp(&connector->base); struct intel_dp *intel_dp = intel_attached_dp(&connector->base);
...@@ -4720,6 +4709,22 @@ intel_dp_long_pulse(struct intel_connector *connector) ...@@ -4720,6 +4709,22 @@ intel_dp_long_pulse(struct intel_connector *connector)
*/ */
status = connector_status_disconnected; status = connector_status_disconnected;
goto out; goto out;
} else {
/*
* If display is now connected check links status,
* there has been known issues of link loss triggering
* long pulse.
*
* Some sinks (eg. ASUS PB287Q) seem to perform some
* weird HPD ping pong during modesets. So we can apparently
* end up with HPD going low during a modeset, and then
* going back up soon after. And once that happens we must
* retrain the link to get a picture. That's in case no
* userspace component reacted to intermittent HPD dip.
*/
struct intel_encoder *encoder = &dp_to_dig_port(intel_dp)->base;
intel_dp_retrain_link(encoder, ctx);
} }
/* /*
...@@ -4781,7 +4786,7 @@ intel_dp_detect(struct drm_connector *connector, ...@@ -4781,7 +4786,7 @@ intel_dp_detect(struct drm_connector *connector,
return ret; return ret;
} }
status = intel_dp_long_pulse(intel_dp->attached_connector); status = intel_dp_long_pulse(intel_dp->attached_connector, ctx);
} }
intel_dp->detect_done = false; intel_dp->detect_done = false;
......
...@@ -166,6 +166,8 @@ static void intel_mst_post_disable_dp(struct intel_encoder *encoder, ...@@ -166,6 +166,8 @@ static void intel_mst_post_disable_dp(struct intel_encoder *encoder,
struct intel_connector *connector = struct intel_connector *connector =
to_intel_connector(old_conn_state->connector); to_intel_connector(old_conn_state->connector);
intel_ddi_disable_pipe_clock(old_crtc_state);
/* this can fail */ /* this can fail */
drm_dp_check_act_status(&intel_dp->mst_mgr); drm_dp_check_act_status(&intel_dp->mst_mgr);
/* and this can also fail */ /* and this can also fail */
...@@ -252,6 +254,8 @@ static void intel_mst_pre_enable_dp(struct intel_encoder *encoder, ...@@ -252,6 +254,8 @@ static void intel_mst_pre_enable_dp(struct intel_encoder *encoder,
I915_WRITE(DP_TP_STATUS(port), temp); I915_WRITE(DP_TP_STATUS(port), temp);
ret = drm_dp_update_payload_part1(&intel_dp->mst_mgr); ret = drm_dp_update_payload_part1(&intel_dp->mst_mgr);
intel_ddi_enable_pipe_clock(pipe_config);
} }
static void intel_mst_enable_dp(struct intel_encoder *encoder, static void intel_mst_enable_dp(struct intel_encoder *encoder,
......
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