Merge tag 'drm-intel-next-fixes-2018-10-18' of git://anongit.freedesktop.org/drm/drm-intel into drm-next

- Fix GPU hang on MacBook2,1 when booting in EFI mode (Bugzilla #105637)
- Fix garbled console on Y tiled BIOS framebuffer configs (Bugzilla #108264)
- Fix black screen on certain eDP panels eg. Dell XPS 9350 (Bugzilla #107489 and #105338)
- MST fixes that Rodrigo dropped from drm-intel-fixes and bunch of Icelake fixes
- Then assorted proactive code fixes caught by CI or developers

Signed-off-by: Dave Airlie <airlied@redhat.com>
From: Joonas Lahtinen <joonas.lahtinen@linux.intel.com>
Link: https://patchwork.freedesktop.org/patch/msgid/20181018165725.GA2281@jlahtine-desk.ger.corp.intel.com
This commit is contained in:
Dave Airlie 2018-10-19 14:28:10 +10:00
commit f2bfc71aee
12 changed files with 227 additions and 104 deletions

View File

@ -4189,7 +4189,7 @@ i915_drop_caches_set(void *data, u64 val)
I915_WAIT_LOCKED,
MAX_SCHEDULE_TIMEOUT);
if (val & DROP_RESET_SEQNO) {
if (ret == 0 && val & DROP_RESET_SEQNO) {
intel_runtime_pm_get(i915);
ret = i915_gem_set_global_seqno(&i915->drm, 1);
intel_runtime_pm_put(i915);

View File

@ -1127,11 +1127,7 @@ i915_gem_shmem_pread(struct drm_i915_gem_object *obj,
offset = offset_in_page(args->offset);
for (idx = args->offset >> PAGE_SHIFT; remain; idx++) {
struct page *page = i915_gem_object_get_page(obj, idx);
int length;
length = remain;
if (offset + length > PAGE_SIZE)
length = PAGE_SIZE - offset;
unsigned int length = min_t(u64, remain, PAGE_SIZE - offset);
ret = shmem_pread(page, offset, length, user_data,
page_to_phys(page) & obj_do_bit17_swizzling,
@ -1575,11 +1571,7 @@ i915_gem_shmem_pwrite(struct drm_i915_gem_object *obj,
offset = offset_in_page(args->offset);
for (idx = args->offset >> PAGE_SHIFT; remain; idx++) {
struct page *page = i915_gem_object_get_page(obj, idx);
int length;
length = remain;
if (offset + length > PAGE_SIZE)
length = PAGE_SIZE - offset;
unsigned int length = min_t(u64, remain, PAGE_SIZE - offset);
ret = shmem_pwrite(page, offset, length, user_data,
page_to_phys(page) & obj_do_bit17_swizzling,

View File

@ -9339,6 +9339,9 @@ enum skl_power_gate {
#define DPCLKA_CFGCR0_ICL _MMIO(0x164280)
#define DPCLKA_CFGCR0_DDI_CLK_OFF(port) (1 << ((port) == PORT_F ? 23 : \
(port) + 10))
#define ICL_DPCLKA_CFGCR0_DDI_CLK_OFF(port) (1 << ((port) + 10))
#define ICL_DPCLKA_CFGCR0_TC_CLK_OFF(tc_port) (1 << ((tc_port) == PORT_TC4 ? \
21 : (tc_port) + 12))
#define DPCLKA_CFGCR0_DDI_CLK_SEL_SHIFT(port) ((port) == PORT_F ? 21 : \
(port) * 2)
#define DPCLKA_CFGCR0_DDI_CLK_SEL_MASK(port) (3 << DPCLKA_CFGCR0_DDI_CLK_SEL_SHIFT(port))

View File

@ -35,6 +35,7 @@
*/
#define I915_CSR_ICL "i915/icl_dmc_ver1_07.bin"
MODULE_FIRMWARE(I915_CSR_ICL);
#define ICL_CSR_VERSION_REQUIRED CSR_VERSION(1, 7)
#define I915_CSR_GLK "i915/glk_dmc_ver1_04.bin"

View File

@ -916,7 +916,7 @@ static int intel_ddi_hdmi_level(struct drm_i915_private *dev_priv, enum port por
level = dev_priv->vbt.ddi_port_info[port].hdmi_level_shift;
if (IS_ICELAKE(dev_priv)) {
if (port == PORT_A || port == PORT_B)
if (intel_port_is_combophy(dev_priv, port))
icl_get_combo_buf_trans(dev_priv, port,
INTEL_OUTPUT_HDMI, &n_entries);
else
@ -1535,7 +1535,7 @@ static void icl_ddi_clock_get(struct intel_encoder *encoder,
uint32_t pll_id;
pll_id = intel_get_shared_dpll_id(dev_priv, pipe_config->shared_dpll);
if (port == PORT_A || port == PORT_B) {
if (intel_port_is_combophy(dev_priv, port)) {
if (intel_crtc_has_type(pipe_config, INTEL_OUTPUT_HDMI))
link_clock = cnl_calc_wrpll_link(dev_priv, pll_id);
else
@ -2235,7 +2235,7 @@ u8 intel_ddi_dp_voltage_max(struct intel_encoder *encoder)
int n_entries;
if (IS_ICELAKE(dev_priv)) {
if (port == PORT_A || port == PORT_B)
if (intel_port_is_combophy(dev_priv, port))
icl_get_combo_buf_trans(dev_priv, port, encoder->type,
&n_entries);
else
@ -2669,9 +2669,10 @@ static void icl_ddi_vswing_sequence(struct intel_encoder *encoder,
u32 level,
enum intel_output_type type)
{
struct drm_i915_private *dev_priv = to_i915(encoder->base.dev);
enum port port = encoder->port;
if (port == PORT_A || port == PORT_B)
if (intel_port_is_combophy(dev_priv, port))
icl_combo_phy_ddi_vswing_sequence(encoder, level, type);
else
icl_mg_phy_ddi_vswing_sequence(encoder, link_clock, level);
@ -2732,6 +2733,21 @@ uint32_t ddi_signal_levels(struct intel_dp *intel_dp)
return DDI_BUF_TRANS_SELECT(level);
}
static inline
uint32_t icl_dpclka_cfgcr0_clk_off(struct drm_i915_private *dev_priv,
enum port port)
{
if (intel_port_is_combophy(dev_priv, port)) {
return ICL_DPCLKA_CFGCR0_DDI_CLK_OFF(port);
} else if (intel_port_is_tc(dev_priv, port)) {
enum tc_port tc_port = intel_port_to_tc(dev_priv, port);
return ICL_DPCLKA_CFGCR0_TC_CLK_OFF(tc_port);
}
return 0;
}
void icl_map_plls_to_ports(struct drm_crtc *crtc,
struct intel_crtc_state *crtc_state,
struct drm_atomic_state *old_state)
@ -2755,16 +2771,16 @@ void icl_map_plls_to_ports(struct drm_crtc *crtc,
mutex_lock(&dev_priv->dpll_lock);
val = I915_READ(DPCLKA_CFGCR0_ICL);
WARN_ON((val & DPCLKA_CFGCR0_DDI_CLK_OFF(port)) == 0);
WARN_ON((val & icl_dpclka_cfgcr0_clk_off(dev_priv, port)) == 0);
if (port == PORT_A || port == PORT_B) {
if (intel_port_is_combophy(dev_priv, port)) {
val &= ~DPCLKA_CFGCR0_DDI_CLK_SEL_MASK(port);
val |= DPCLKA_CFGCR0_DDI_CLK_SEL(pll->info->id, port);
I915_WRITE(DPCLKA_CFGCR0_ICL, val);
POSTING_READ(DPCLKA_CFGCR0_ICL);
}
val &= ~DPCLKA_CFGCR0_DDI_CLK_OFF(port);
val &= ~icl_dpclka_cfgcr0_clk_off(dev_priv, port);
I915_WRITE(DPCLKA_CFGCR0_ICL, val);
mutex_unlock(&dev_priv->dpll_lock);
@ -2792,7 +2808,7 @@ void icl_unmap_plls_to_ports(struct drm_crtc *crtc,
mutex_lock(&dev_priv->dpll_lock);
I915_WRITE(DPCLKA_CFGCR0_ICL,
I915_READ(DPCLKA_CFGCR0_ICL) |
DPCLKA_CFGCR0_DDI_CLK_OFF(port));
icl_dpclka_cfgcr0_clk_off(dev_priv, port));
mutex_unlock(&dev_priv->dpll_lock);
}
}
@ -2810,7 +2826,7 @@ static void intel_ddi_clk_select(struct intel_encoder *encoder,
mutex_lock(&dev_priv->dpll_lock);
if (IS_ICELAKE(dev_priv)) {
if (port >= PORT_C)
if (!intel_port_is_combophy(dev_priv, port))
I915_WRITE(DDI_CLK_SEL(port),
icl_pll_to_ddi_pll_sel(encoder, pll));
} else if (IS_CANNONLAKE(dev_priv)) {
@ -2852,7 +2868,7 @@ static void intel_ddi_clk_disable(struct intel_encoder *encoder)
enum port port = encoder->port;
if (IS_ICELAKE(dev_priv)) {
if (port >= PORT_C)
if (!intel_port_is_combophy(dev_priv, port))
I915_WRITE(DDI_CLK_SEL(port), DDI_CLK_SEL_NONE);
} else if (IS_CANNONLAKE(dev_priv)) {
I915_WRITE(DPCLKA_CFGCR0, I915_READ(DPCLKA_CFGCR0) |

View File

@ -2722,6 +2722,17 @@ intel_alloc_initial_plane_obj(struct intel_crtc *crtc,
if (size_aligned * 2 > dev_priv->stolen_usable_size)
return false;
switch (fb->modifier) {
case DRM_FORMAT_MOD_LINEAR:
case I915_FORMAT_MOD_X_TILED:
case I915_FORMAT_MOD_Y_TILED:
break;
default:
DRM_DEBUG_DRIVER("Unsupported modifier for initial FB: 0x%llx\n",
fb->modifier);
return false;
}
mutex_lock(&dev->struct_mutex);
obj = i915_gem_object_create_stolen_for_preallocated(dev_priv,
base_aligned,
@ -2731,8 +2742,17 @@ intel_alloc_initial_plane_obj(struct intel_crtc *crtc,
if (!obj)
return false;
if (plane_config->tiling == I915_TILING_X)
obj->tiling_and_stride = fb->pitches[0] | I915_TILING_X;
switch (plane_config->tiling) {
case I915_TILING_NONE:
break;
case I915_TILING_X:
case I915_TILING_Y:
obj->tiling_and_stride = fb->pitches[0] | plane_config->tiling;
break;
default:
MISSING_CASE(plane_config->tiling);
return false;
}
mode_cmd.pixel_format = fb->format->format;
mode_cmd.width = fb->width;
@ -2764,20 +2784,33 @@ intel_set_plane_visible(struct intel_crtc_state *crtc_state,
plane_state->base.visible = visible;
/* FIXME pre-g4x don't work like this */
if (visible) {
if (visible)
crtc_state->base.plane_mask |= drm_plane_mask(&plane->base);
crtc_state->active_planes |= BIT(plane->id);
} else {
else
crtc_state->base.plane_mask &= ~drm_plane_mask(&plane->base);
crtc_state->active_planes &= ~BIT(plane->id);
}
DRM_DEBUG_KMS("%s active planes 0x%x\n",
crtc_state->base.crtc->name,
crtc_state->active_planes);
}
static void fixup_active_planes(struct intel_crtc_state *crtc_state)
{
struct drm_i915_private *dev_priv = to_i915(crtc_state->base.crtc->dev);
struct drm_plane *plane;
/*
* Active_planes aliases if multiple "primary" or cursor planes
* have been used on the same (or wrong) pipe. plane_mask uses
* unique ids, hence we can use that to reconstruct active_planes.
*/
crtc_state->active_planes = 0;
drm_for_each_plane_mask(plane, &dev_priv->drm,
crtc_state->base.plane_mask)
crtc_state->active_planes |= BIT(to_intel_plane(plane)->id);
}
static void intel_plane_disable_noatomic(struct intel_crtc *crtc,
struct intel_plane *plane)
{
@ -2787,6 +2820,7 @@ static void intel_plane_disable_noatomic(struct intel_crtc *crtc,
to_intel_plane_state(plane->base.state);
intel_set_plane_visible(crtc_state, plane_state, false);
fixup_active_planes(crtc_state);
if (plane->id == PLANE_PRIMARY)
intel_pre_disable_primary_noatomic(&crtc->base);
@ -2805,7 +2839,6 @@ intel_find_initial_plane_obj(struct intel_crtc *intel_crtc,
struct drm_i915_gem_object *obj;
struct drm_plane *primary = intel_crtc->base.primary;
struct drm_plane_state *plane_state = primary->state;
struct drm_crtc_state *crtc_state = intel_crtc->base.state;
struct intel_plane *intel_plane = to_intel_plane(primary);
struct intel_plane_state *intel_state =
to_intel_plane_state(plane_state);
@ -2900,10 +2933,6 @@ valid_fb:
plane_state->fb = fb;
plane_state->crtc = &intel_crtc->base;
intel_set_plane_visible(to_intel_crtc_state(crtc_state),
to_intel_plane_state(plane_state),
true);
atomic_or(to_intel_plane(primary)->frontbuffer_bit,
&obj->frontbuffer_bits);
}
@ -3151,6 +3180,10 @@ int skl_check_plane_surface(struct intel_plane_state *plane_state)
plane_state->color_plane[0].stride = intel_fb_pitch(fb, 0, rotation);
plane_state->color_plane[1].stride = intel_fb_pitch(fb, 1, rotation);
ret = intel_plane_check_stride(plane_state);
if (ret)
return ret;
if (!plane_state->base.visible)
return 0;
@ -3286,10 +3319,15 @@ int i9xx_check_plane_surface(struct intel_plane_state *plane_state)
int src_x = plane_state->base.src.x1 >> 16;
int src_y = plane_state->base.src.y1 >> 16;
u32 offset;
int ret;
intel_fill_fb_ggtt_view(&plane_state->view, fb, rotation);
plane_state->color_plane[0].stride = intel_fb_pitch(fb, 0, rotation);
ret = intel_plane_check_stride(plane_state);
if (ret)
return ret;
intel_add_fb_offsets(&src_x, &src_y, plane_state, 0);
if (INTEL_GEN(dev_priv) >= 4)
@ -5923,6 +5961,17 @@ static void i9xx_pfit_enable(struct intel_crtc *crtc)
I915_WRITE(BCLRPAT(crtc->pipe), 0);
}
bool intel_port_is_combophy(struct drm_i915_private *dev_priv, enum port port)
{
if (port == PORT_NONE)
return false;
if (IS_ICELAKE(dev_priv))
return port <= PORT_B;
return false;
}
bool intel_port_is_tc(struct drm_i915_private *dev_priv, enum port port)
{
if (IS_ICELAKE(dev_priv))
@ -8847,6 +8896,7 @@ skylake_get_initial_plane_config(struct intel_crtc *crtc,
fb->modifier = I915_FORMAT_MOD_X_TILED;
break;
case PLANE_CTL_TILED_Y:
plane_config->tiling = I915_TILING_Y;
if (val & PLANE_CTL_RENDER_DECOMPRESSION_ENABLE)
fb->modifier = I915_FORMAT_MOD_Y_TILED_CCS;
else
@ -9683,10 +9733,15 @@ static int intel_cursor_check_surface(struct intel_plane_state *plane_state)
unsigned int rotation = plane_state->base.rotation;
int src_x, src_y;
u32 offset;
int ret;
intel_fill_fb_ggtt_view(&plane_state->view, fb, rotation);
plane_state->color_plane[0].stride = intel_fb_pitch(fb, 0, rotation);
ret = intel_plane_check_stride(plane_state);
if (ret)
return ret;
src_x = plane_state->base.src_x >> 16;
src_y = plane_state->base.src_y >> 16;
@ -15436,17 +15491,6 @@ void i830_disable_pipe(struct drm_i915_private *dev_priv, enum pipe pipe)
POSTING_READ(DPLL(pipe));
}
static bool intel_plane_mapping_ok(struct intel_crtc *crtc,
struct intel_plane *plane)
{
enum pipe pipe;
if (!plane->get_hw_state(plane, &pipe))
return true;
return pipe == crtc->pipe;
}
static void
intel_sanitize_plane_mapping(struct drm_i915_private *dev_priv)
{
@ -15458,13 +15502,20 @@ intel_sanitize_plane_mapping(struct drm_i915_private *dev_priv)
for_each_intel_crtc(&dev_priv->drm, crtc) {
struct intel_plane *plane =
to_intel_plane(crtc->base.primary);
struct intel_crtc *plane_crtc;
enum pipe pipe;
if (intel_plane_mapping_ok(crtc, plane))
if (!plane->get_hw_state(plane, &pipe))
continue;
if (pipe == crtc->pipe)
continue;
DRM_DEBUG_KMS("%s attached to the wrong pipe, disabling plane\n",
plane->base.name);
intel_plane_disable_noatomic(crtc, plane);
plane_crtc = intel_get_crtc_for_pipe(dev_priv, pipe);
intel_plane_disable_noatomic(plane_crtc, plane);
}
}
@ -15512,13 +15563,9 @@ static void intel_sanitize_crtc(struct intel_crtc *crtc,
I915_READ(reg) & ~PIPECONF_FRAME_START_DELAY_MASK);
}
/* restore vblank interrupts to correct state */
drm_crtc_vblank_reset(&crtc->base);
if (crtc->active) {
struct intel_plane *plane;
drm_crtc_vblank_on(&crtc->base);
/* Disable everything but the primary plane */
for_each_intel_plane_on_crtc(dev, crtc, plane) {
const struct intel_plane_state *plane_state =
@ -15636,23 +15683,32 @@ void i915_redisable_vga(struct drm_i915_private *dev_priv)
}
/* FIXME read out full plane state for all planes */
static void readout_plane_state(struct intel_crtc *crtc)
static void readout_plane_state(struct drm_i915_private *dev_priv)
{
struct drm_i915_private *dev_priv = to_i915(crtc->base.dev);
struct intel_crtc_state *crtc_state =
to_intel_crtc_state(crtc->base.state);
struct intel_plane *plane;
struct intel_crtc *crtc;
for_each_intel_plane_on_crtc(&dev_priv->drm, crtc, plane) {
for_each_intel_plane(&dev_priv->drm, plane) {
struct intel_plane_state *plane_state =
to_intel_plane_state(plane->base.state);
enum pipe pipe;
struct intel_crtc_state *crtc_state;
enum pipe pipe = PIPE_A;
bool visible;
visible = plane->get_hw_state(plane, &pipe);
crtc = intel_get_crtc_for_pipe(dev_priv, pipe);
crtc_state = to_intel_crtc_state(crtc->base.state);
intel_set_plane_visible(crtc_state, plane_state, visible);
}
for_each_intel_crtc(&dev_priv->drm, crtc) {
struct intel_crtc_state *crtc_state =
to_intel_crtc_state(crtc->base.state);
fixup_active_planes(crtc_state);
}
}
static void intel_modeset_readout_hw_state(struct drm_device *dev)
@ -15684,13 +15740,13 @@ static void intel_modeset_readout_hw_state(struct drm_device *dev)
if (crtc_state->base.active)
dev_priv->active_crtcs |= 1 << crtc->pipe;
readout_plane_state(crtc);
DRM_DEBUG_KMS("[CRTC:%d:%s] hw state readout: %s\n",
crtc->base.base.id, crtc->base.name,
enableddisabled(crtc_state->base.active));
}
readout_plane_state(dev_priv);
for (i = 0; i < dev_priv->num_shared_dpll; i++) {
struct intel_shared_dpll *pll = &dev_priv->shared_dplls[i];
@ -15860,7 +15916,6 @@ intel_modeset_setup_hw_state(struct drm_device *dev,
struct drm_modeset_acquire_ctx *ctx)
{
struct drm_i915_private *dev_priv = to_i915(dev);
enum pipe pipe;
struct intel_crtc *crtc;
struct intel_encoder *encoder;
int i;
@ -15873,15 +15928,23 @@ intel_modeset_setup_hw_state(struct drm_device *dev,
/* HW state is read out, now we need to sanitize this mess. */
get_encoder_power_domains(dev_priv);
intel_sanitize_plane_mapping(dev_priv);
/*
* intel_sanitize_plane_mapping() may need to do vblank
* waits, so we need vblank interrupts restored beforehand.
*/
for_each_intel_crtc(&dev_priv->drm, crtc) {
drm_crtc_vblank_reset(&crtc->base);
for_each_intel_encoder(dev, encoder) {
intel_sanitize_encoder(encoder);
if (crtc->active)
drm_crtc_vblank_on(&crtc->base);
}
for_each_pipe(dev_priv, pipe) {
crtc = intel_get_crtc_for_pipe(dev_priv, pipe);
intel_sanitize_plane_mapping(dev_priv);
for_each_intel_encoder(dev, encoder)
intel_sanitize_encoder(encoder);
for_each_intel_crtc(&dev_priv->drm, crtc) {
intel_sanitize_crtc(crtc, ctx);
intel_dump_pipe_config(crtc, crtc->config,
"[setup_hw_state]");

View File

@ -557,6 +557,22 @@ static bool intel_dp_link_params_valid(struct intel_dp *intel_dp, int link_rate,
return true;
}
static bool intel_dp_can_link_train_fallback_for_edp(struct intel_dp *intel_dp,
int link_rate,
uint8_t lane_count)
{
const struct drm_display_mode *fixed_mode =
intel_dp->attached_connector->panel.fixed_mode;
int mode_rate, max_rate;
mode_rate = intel_dp_link_required(fixed_mode->clock, 18);
max_rate = intel_dp_max_data_rate(link_rate, lane_count);
if (mode_rate > max_rate)
return false;
return true;
}
int intel_dp_get_link_train_fallback_values(struct intel_dp *intel_dp,
int link_rate, uint8_t lane_count)
{
@ -566,9 +582,23 @@ int intel_dp_get_link_train_fallback_values(struct intel_dp *intel_dp,
intel_dp->num_common_rates,
link_rate);
if (index > 0) {
if (intel_dp_is_edp(intel_dp) &&
!intel_dp_can_link_train_fallback_for_edp(intel_dp,
intel_dp->common_rates[index - 1],
lane_count)) {
DRM_DEBUG_KMS("Retrying Link training for eDP with same parameters\n");
return 0;
}
intel_dp->max_link_rate = intel_dp->common_rates[index - 1];
intel_dp->max_link_lane_count = lane_count;
} else if (lane_count > 1) {
if (intel_dp_is_edp(intel_dp) &&
!intel_dp_can_link_train_fallback_for_edp(intel_dp,
intel_dp_max_common_rate(intel_dp),
lane_count >> 1)) {
DRM_DEBUG_KMS("Retrying Link training for eDP with same parameters\n");
return 0;
}
intel_dp->max_link_rate = intel_dp_max_common_rate(intel_dp);
intel_dp->max_link_lane_count = lane_count >> 1;
} else {
@ -3704,7 +3734,7 @@ intel_dp_set_signal_levels(struct intel_dp *intel_dp)
uint32_t signal_levels, mask = 0;
uint8_t train_set = intel_dp->train_set[0];
if (IS_GEN9_LP(dev_priv) || IS_CANNONLAKE(dev_priv)) {
if (IS_GEN9_LP(dev_priv) || INTEL_GEN(dev_priv) >= 10) {
signal_levels = bxt_signal_levels(intel_dp);
} else if (HAS_DDI(dev_priv)) {
signal_levels = ddi_signal_levels(intel_dp);

View File

@ -367,22 +367,14 @@ intel_dp_start_link_train(struct intel_dp *intel_dp)
return;
failure_handling:
/* Dont fallback and prune modes if its eDP */
if (!intel_dp_is_edp(intel_dp)) {
DRM_DEBUG_KMS("[CONNECTOR:%d:%s] Link Training failed at link rate = %d, lane count = %d",
intel_connector->base.base.id,
intel_connector->base.name,
intel_dp->link_rate, intel_dp->lane_count);
if (!intel_dp_get_link_train_fallback_values(intel_dp,
intel_dp->link_rate,
intel_dp->lane_count))
/* Schedule a Hotplug Uevent to userspace to start modeset */
schedule_work(&intel_connector->modeset_retry_work);
} else {
DRM_ERROR("[CONNECTOR:%d:%s] Link Training failed at link rate = %d, lane count = %d",
intel_connector->base.base.id,
intel_connector->base.name,
intel_dp->link_rate, intel_dp->lane_count);
}
DRM_DEBUG_KMS("[CONNECTOR:%d:%s] Link Training failed at link rate = %d, lane count = %d",
intel_connector->base.base.id,
intel_connector->base.name,
intel_dp->link_rate, intel_dp->lane_count);
if (!intel_dp_get_link_train_fallback_values(intel_dp,
intel_dp->link_rate,
intel_dp->lane_count))
/* Schedule a Hotplug Uevent to userspace to start modeset */
schedule_work(&intel_connector->modeset_retry_work);
return;
}

View File

@ -38,11 +38,11 @@ static bool intel_dp_mst_compute_config(struct intel_encoder *encoder,
struct intel_dp_mst_encoder *intel_mst = enc_to_mst(&encoder->base);
struct intel_digital_port *intel_dig_port = intel_mst->primary;
struct intel_dp *intel_dp = &intel_dig_port->dp;
struct intel_connector *connector =
to_intel_connector(conn_state->connector);
struct drm_connector *connector = conn_state->connector;
void *port = to_intel_connector(connector)->port;
struct drm_atomic_state *state = pipe_config->base.state;
int bpp;
int lane_count, slots;
int lane_count, slots = 0;
const struct drm_display_mode *adjusted_mode = &pipe_config->base.adjusted_mode;
int mst_pbn;
bool constant_n = drm_dp_has_quirk(&intel_dp->desc,
@ -70,17 +70,23 @@ static bool intel_dp_mst_compute_config(struct intel_encoder *encoder,
pipe_config->port_clock = intel_dp_max_link_rate(intel_dp);
if (drm_dp_mst_port_has_audio(&intel_dp->mst_mgr, connector->port))
if (drm_dp_mst_port_has_audio(&intel_dp->mst_mgr, port))
pipe_config->has_audio = true;
mst_pbn = drm_dp_calc_pbn_mode(adjusted_mode->crtc_clock, bpp);
pipe_config->pbn = mst_pbn;
slots = drm_dp_atomic_find_vcpi_slots(state, &intel_dp->mst_mgr,
connector->port, mst_pbn);
if (slots < 0) {
DRM_DEBUG_KMS("failed finding vcpi slots:%d\n", slots);
return false;
/* Zombie connectors can't have VCPI slots */
if (READ_ONCE(connector->registered)) {
slots = drm_dp_atomic_find_vcpi_slots(state,
&intel_dp->mst_mgr,
port,
mst_pbn);
if (slots < 0) {
DRM_DEBUG_KMS("failed finding vcpi slots:%d\n",
slots);
return false;
}
}
intel_link_compute_m_n(bpp, lane_count,
@ -307,9 +313,8 @@ static int intel_dp_mst_get_ddc_modes(struct drm_connector *connector)
struct edid *edid;
int ret;
if (!intel_dp) {
if (!READ_ONCE(connector->registered))
return intel_connector_update_modes(connector, NULL);
}
edid = drm_dp_mst_get_edid(connector, &intel_dp->mst_mgr, intel_connector->port);
ret = intel_connector_update_modes(connector, edid);
@ -324,9 +329,10 @@ intel_dp_mst_detect(struct drm_connector *connector, bool force)
struct intel_connector *intel_connector = to_intel_connector(connector);
struct intel_dp *intel_dp = intel_connector->mst_port;
if (!intel_dp)
if (!READ_ONCE(connector->registered))
return connector_status_disconnected;
return drm_dp_mst_detect_port(connector, &intel_dp->mst_mgr, intel_connector->port);
return drm_dp_mst_detect_port(connector, &intel_dp->mst_mgr,
intel_connector->port);
}
static void
@ -366,7 +372,7 @@ intel_dp_mst_mode_valid(struct drm_connector *connector,
int bpp = 24; /* MST uses fixed bpp */
int max_rate, mode_rate, max_lanes, max_link_clock;
if (!intel_dp)
if (!READ_ONCE(connector->registered))
return MODE_ERROR;
if (mode->flags & DRM_MODE_FLAG_DBLSCAN)
@ -398,8 +404,6 @@ static struct drm_encoder *intel_mst_atomic_best_encoder(struct drm_connector *c
struct intel_dp *intel_dp = intel_connector->mst_port;
struct intel_crtc *crtc = to_intel_crtc(state->crtc);
if (!intel_dp)
return NULL;
return &intel_dp->mst_encoders[crtc->pipe]->base.base;
}
@ -499,7 +503,6 @@ static void intel_dp_register_mst_connector(struct drm_connector *connector)
static void intel_dp_destroy_mst_connector(struct drm_dp_mst_topology_mgr *mgr,
struct drm_connector *connector)
{
struct intel_connector *intel_connector = to_intel_connector(connector);
struct drm_i915_private *dev_priv = to_i915(connector->dev);
DRM_DEBUG_KMS("[CONNECTOR:%d:%s]\n", connector->base.id, connector->name);
@ -508,10 +511,6 @@ static void intel_dp_destroy_mst_connector(struct drm_dp_mst_topology_mgr *mgr,
if (dev_priv->fbdev)
drm_fb_helper_remove_one_connector(&dev_priv->fbdev->helper,
connector);
/* prevent race with the check in ->detect */
drm_modeset_lock(&connector->dev->mode_config.connection_mutex, NULL);
intel_connector->mst_port = NULL;
drm_modeset_unlock(&connector->dev->mode_config.connection_mutex);
drm_connector_put(connector);
}

View File

@ -1517,6 +1517,7 @@ void intel_connector_attach_encoder(struct intel_connector *connector,
struct intel_encoder *encoder);
struct drm_display_mode *
intel_encoder_current_mode(struct intel_encoder *encoder);
bool intel_port_is_combophy(struct drm_i915_private *dev_priv, enum port port);
bool intel_port_is_tc(struct drm_i915_private *dev_priv, enum port port);
enum tc_port intel_port_to_tc(struct drm_i915_private *dev_priv,
enum port port);
@ -2140,6 +2141,7 @@ unsigned int skl_plane_max_stride(struct intel_plane *plane,
unsigned int rotation);
int skl_plane_check(struct intel_crtc_state *crtc_state,
struct intel_plane_state *plane_state);
int intel_plane_check_stride(const struct intel_plane_state *plane_state);
int intel_plane_check_src_coordinates(struct intel_plane_state *plane_state);
int chv_plane_check_rotation(const struct intel_plane_state *plane_state);

View File

@ -230,6 +230,28 @@ void intel_pipe_update_end(struct intel_crtc_state *new_crtc_state)
#endif
}
int intel_plane_check_stride(const struct intel_plane_state *plane_state)
{
struct intel_plane *plane = to_intel_plane(plane_state->base.plane);
const struct drm_framebuffer *fb = plane_state->base.fb;
unsigned int rotation = plane_state->base.rotation;
u32 stride, max_stride;
/* FIXME other color planes? */
stride = plane_state->color_plane[0].stride;
max_stride = plane->max_stride(plane, fb->format->format,
fb->modifier, rotation);
if (stride > max_stride) {
DRM_DEBUG_KMS("[FB:%d] stride (%d) exceeds [PLANE:%d:%s] max stride (%d)\n",
fb->base.id, stride,
plane->base.base.id, plane->base.name, max_stride);
return -EINVAL;
}
return 0;
}
int intel_plane_check_src_coordinates(struct intel_plane_state *plane_state)
{
const struct drm_framebuffer *fb = plane_state->base.fb;

View File

@ -501,6 +501,8 @@ static bool assert_mmap_offset(struct drm_i915_private *i915,
static void disable_retire_worker(struct drm_i915_private *i915)
{
i915_gem_shrinker_unregister(i915);
mutex_lock(&i915->drm.struct_mutex);
if (!i915->gt.active_requests++) {
intel_runtime_pm_get(i915);
@ -613,6 +615,7 @@ out_park:
else
queue_delayed_work(i915->wq, &i915->gt.idle_work, 0);
mutex_unlock(&i915->drm.struct_mutex);
i915_gem_shrinker_register(i915);
return err;
err_obj:
i915_gem_object_put(obj);