summaryrefslogtreecommitdiff
path: root/drivers/gpu/drm/i915/intel_display.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/gpu/drm/i915/intel_display.c')
-rw-r--r--drivers/gpu/drm/i915/intel_display.c151
1 files changed, 107 insertions, 44 deletions
diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c
index fbcc56caffb6..9741cc419e1b 100644
--- a/drivers/gpu/drm/i915/intel_display.c
+++ b/drivers/gpu/drm/i915/intel_display.c
@@ -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]");