Skip to content

Commit

Permalink
drm/i915: Handle disabling planes better, v2.
Browse files Browse the repository at this point in the history
Read out the initial state, and add a quirk to force add all planes
to crtc_state->plane_mask during initial commit. This will disable
all planes during the initial modeset.

The initial plane quirk is temporary, and will go away when hardware
readout is fully atomic, and the watermark updates in intel_sprite.c
are removed.

Changes since v1:
- Unset state->visible on !primary planes.
- Do not rely on the plane->crtc pointer in intel_atomic_plane,
  instead assume planes are invisible until modeset.

Signed-off-by: Maarten Lankhorst <maarten.lankhorst@linux.intel.com>
Reviewed-by: Matt Roper <matthew.d.roper@intel.com>
Tested-by(IVB): Matt Roper <matthew.d.roper@intel.com>
Signed-off-by: Daniel Vetter <daniel.vetter@ffwll.ch>
  • Loading branch information
Maarten Lankhorst authored and Daniel Vetter committed Jun 22, 2015
1 parent 61333b6 commit d032ffa
Show file tree
Hide file tree
Showing 3 changed files with 106 additions and 22 deletions.
7 changes: 7 additions & 0 deletions drivers/gpu/drm/i915/intel_atomic.c
Original file line number Diff line number Diff line change
Expand Up @@ -96,6 +96,13 @@ int intel_atomic_check(struct drm_device *dev,
return -EINVAL;
}

if (crtc_state &&
crtc_state->quirks & PIPE_CONFIG_QUIRK_INITIAL_PLANES) {
ret = drm_atomic_add_affected_planes(state, &nuclear_crtc->base);
if (ret)
return ret;
}

ret = drm_atomic_helper_check_planes(dev, state);
if (ret)
return ret;
Expand Down
120 changes: 98 additions & 22 deletions drivers/gpu/drm/i915/intel_display.c
Original file line number Diff line number Diff line change
Expand Up @@ -109,8 +109,6 @@ static void skl_init_scalers(struct drm_device *dev, struct intel_crtc *intel_cr
struct intel_crtc_state *crtc_state);
static int i9xx_get_refclk(const struct intel_crtc_state *crtc_state,
int num_connectors);
static void intel_crtc_enable_planes(struct drm_crtc *crtc);
static void intel_crtc_disable_planes(struct drm_crtc *crtc);

static struct intel_encoder *intel_find_encoder(struct intel_connector *connector, int pipe)
{
Expand Down Expand Up @@ -4850,26 +4848,21 @@ static void intel_crtc_enable_planes(struct drm_crtc *crtc)
intel_frontbuffer_flip(dev, INTEL_FRONTBUFFER_ALL_MASK(pipe));
}

static void intel_crtc_disable_planes(struct drm_crtc *crtc)
static void intel_crtc_disable_planes(struct drm_crtc *crtc, unsigned plane_mask)
{
struct drm_device *dev = crtc->dev;
struct intel_crtc *intel_crtc = to_intel_crtc(crtc);
struct intel_plane *intel_plane;
struct drm_plane *p;
int pipe = intel_crtc->pipe;

intel_crtc_wait_for_pending_flips(crtc);

intel_pre_disable_primary(crtc);

intel_crtc_dpms_overlay_disable(intel_crtc);
for_each_intel_plane(dev, intel_plane) {
if (intel_plane->pipe == pipe) {
struct drm_crtc *from = intel_plane->base.crtc;

intel_plane->disable_plane(&intel_plane->base,
from ?: crtc);
}
}
drm_for_each_plane_mask(p, dev, plane_mask)
to_intel_plane(p)->disable_plane(p, crtc);

/*
* FIXME: Once we grow proper nuclear flip support out of this we need
Expand Down Expand Up @@ -6289,7 +6282,7 @@ static void intel_crtc_disable_noatomic(struct drm_crtc *crtc)
if (!intel_crtc->active)
return;

intel_crtc_disable_planes(crtc);
intel_crtc_disable_planes(crtc, crtc->state->plane_mask);
dev_priv->display.crtc_disable(crtc);

domains = intel_crtc->enabled_power_domains;
Expand Down Expand Up @@ -11885,7 +11878,7 @@ int intel_plane_atomic_calc_changes(struct drm_crtc_state *crtc_state,
intel_crtc->atomic.fb_bits |=
INTEL_FRONTBUFFER_SPRITE(intel_crtc->pipe);

if (turn_off && is_crtc_enabled) {
if (turn_off && !mode_changed) {
intel_crtc->atomic.wait_vblank = true;
intel_crtc->atomic.update_sprite_watermarks |=
1 << i;
Expand Down Expand Up @@ -11945,6 +11938,34 @@ static bool check_encoder_cloning(struct drm_atomic_state *state,
return true;
}

static void intel_crtc_check_initial_planes(struct drm_crtc *crtc,
struct drm_crtc_state *crtc_state)
{
struct intel_crtc_state *pipe_config =
to_intel_crtc_state(crtc_state);
struct drm_plane *p;
unsigned visible_mask = 0;

drm_for_each_plane_mask(p, crtc->dev, crtc_state->plane_mask) {
struct drm_plane_state *plane_state =
drm_atomic_get_existing_plane_state(crtc_state->state, p);

if (WARN_ON(!plane_state))
continue;

if (!plane_state->fb)
crtc_state->plane_mask &=
~(1 << drm_plane_index(p));
else if (to_intel_plane_state(plane_state)->visible)
visible_mask |= 1 << drm_plane_index(p);
}

if (!visible_mask)
return;

pipe_config->quirks &= ~PIPE_CONFIG_QUIRK_INITIAL_PLANES;
}

static int intel_crtc_atomic_check(struct drm_crtc *crtc,
struct drm_crtc_state *crtc_state)
{
Expand All @@ -11966,6 +11987,10 @@ static int intel_crtc_atomic_check(struct drm_crtc *crtc,
"[CRTC:%i] mismatch between state->active(%i) and crtc->active(%i)\n",
idx, crtc->state->active, intel_crtc->active);

/* plane mask is fixed up after all initial planes are calculated */
if (pipe_config->quirks & PIPE_CONFIG_QUIRK_INITIAL_PLANES)
intel_crtc_check_initial_planes(crtc, crtc_state);

if (mode_changed && crtc_state->enable &&
dev_priv->display.crtc_compute_clock &&
!WARN_ON(pipe_config->shared_dpll != DPLL_ID_PRIVATE)) {
Expand Down Expand Up @@ -13182,6 +13207,20 @@ intel_modeset_compute_config(struct drm_atomic_state *state)
continue;
}

if (to_intel_crtc_state(crtc_state)->quirks &
PIPE_CONFIG_QUIRK_INITIAL_PLANES) {
ret = drm_atomic_add_affected_planes(state, crtc);
if (ret)
return ret;

/*
* We ought to handle i915.fastboot here.
* If no modeset is required and the primary plane has
* a fb, update the members of crtc_state as needed,
* and run the necessary updates during vblank evasion.
*/
}

if (!needs_modeset(crtc_state)) {
ret = drm_atomic_add_affected_connectors(state, crtc);
if (ret)
Expand Down Expand Up @@ -13235,7 +13274,7 @@ static int __intel_set_mode(struct drm_atomic_state *state)
if (!crtc_state->active)
continue;

intel_crtc_disable_planes(crtc);
intel_crtc_disable_planes(crtc, crtc_state->plane_mask);
dev_priv->display.crtc_disable(crtc);
}

Expand Down Expand Up @@ -15403,10 +15442,51 @@ static bool primary_get_hw_state(struct intel_crtc *crtc)
{
struct drm_i915_private *dev_priv = crtc->base.dev->dev_private;

if (!crtc->active)
return false;
return !!(I915_READ(DSPCNTR(crtc->plane)) & DISPLAY_PLANE_ENABLE);
}

static void readout_plane_state(struct intel_crtc *crtc,
struct intel_crtc_state *crtc_state)
{
struct intel_plane *p;
struct drm_plane_state *drm_plane_state;
bool active = crtc_state->base.active;

if (active) {
crtc_state->quirks |= PIPE_CONFIG_QUIRK_INITIAL_PLANES;

/* apply to previous sw state too */
to_intel_crtc_state(crtc->base.state)->quirks |=
PIPE_CONFIG_QUIRK_INITIAL_PLANES;
}

return I915_READ(DSPCNTR(crtc->plane)) & DISPLAY_PLANE_ENABLE;
for_each_intel_plane(crtc->base.dev, p) {
bool visible = active;

if (crtc->pipe != p->pipe)
continue;

drm_plane_state = p->base.state;
if (active && p->base.type == DRM_PLANE_TYPE_PRIMARY) {
visible = primary_get_hw_state(crtc);
to_intel_plane_state(drm_plane_state)->visible = visible;
} else {
/*
* unknown state, assume it's off to force a transition
* to on when calculating state changes.
*/
to_intel_plane_state(drm_plane_state)->visible = false;
}

if (visible) {
crtc_state->base.plane_mask |=
1 << drm_plane_index(&p->base);
} else if (crtc_state->base.state) {
/* Make this unconditional for atomic hw readout. */
crtc_state->base.plane_mask &=
~(1 << drm_plane_index(&p->base));
}
}
}

static void intel_modeset_readout_hw_state(struct drm_device *dev)
Expand All @@ -15419,9 +15499,6 @@ static void intel_modeset_readout_hw_state(struct drm_device *dev)
int i;

for_each_intel_crtc(dev, crtc) {
struct drm_plane *primary = crtc->base.primary;
struct intel_plane_state *plane_state;

memset(crtc->config, 0, sizeof(*crtc->config));
crtc->config->base.crtc = &crtc->base;

Expand All @@ -15435,8 +15512,7 @@ static void intel_modeset_readout_hw_state(struct drm_device *dev)
crtc->base.enabled = crtc->active;
crtc->base.hwmode = crtc->config->base.adjusted_mode;

plane_state = to_intel_plane_state(primary->state);
plane_state->visible = primary_get_hw_state(crtc);
readout_plane_state(crtc, to_intel_crtc_state(crtc->base.state));

DRM_DEBUG_KMS("[CRTC:%d] hw state readout: %s\n",
crtc->base.base.id,
Expand Down
1 change: 1 addition & 0 deletions drivers/gpu/drm/i915/intel_drv.h
Original file line number Diff line number Diff line change
Expand Up @@ -338,6 +338,7 @@ struct intel_crtc_state {
*/
#define PIPE_CONFIG_QUIRK_MODE_SYNC_FLAGS (1<<0) /* unreliable sync mode.flags */
#define PIPE_CONFIG_QUIRK_INHERITED_MODE (1<<1) /* mode inherited from firmware */
#define PIPE_CONFIG_QUIRK_INITIAL_PLANES (1<<2) /* planes are in unknown state */
unsigned long quirks;

/* Pipe source size (ie. panel fitter input size)
Expand Down

0 comments on commit d032ffa

Please sign in to comment.