[PATCH v4 13/27] drm/i915: Support modeset across multiple pipes

Maarten Lankhorst
2015-06-01T10:50:32Z

From: Ander Conselvan de Oliveira <ander.conselvan.de.oliveira@intel.com>

Compute new pipe_configs for all crtcs in the atomic state. The commit
part of the mode set (__intel_set_mode()) is already enabled to support
multiple pipes, the only thing missing was calculating a new pipe_config
for every crtc.

Signed-off-by: Ander Conselvan de Oliveira <ander.conselvan.de.oliveira@intel.com>
Signed-off-by: Maarten Lankhorst <maarten.lankhorst@linux.intel.com>
Reviewed-by: Matt Roper <matthew.d.roper@intel.com>
---
drivers/gpu/drm/i915/intel_display.c | 108 +++++++++++++++--------------------
1 file changed, 45 insertions(+), 63 deletions(-)

diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c
index c79ff10db43e..4fbff2987d2e 100644
--- a/drivers/gpu/drm/i915/intel_display.c
+++ b/drivers/gpu/drm/i915/intel_display.c
@@ -86,8 +86,7 @@ static void i9xx_crtc_clock_get(struct intel_crtc *crtc,
static void ironlake_pch_clock_get(struct intel_crtc *crtc,
struct intel_crtc_state *pipe_config);

-static int intel_set_mode(struct drm_crtc *crtc,
- struct drm_atomic_state *state);
+static int intel_set_mode(struct drm_atomic_state *state);
static int intel_framebuffer_init(struct drm_device *dev,
struct intel_framebuffer *ifb,
struct drm_mode_fb_cmd2 *mode_cmd,
@@ -10230,7 +10229,7 @@ retry:

drm_mode_copy(&crtc_state->base.mode, mode);

- if (intel_set_mode(crtc, state)) {
+ if (intel_set_mode(state)) {
DRM_DEBUG_KMS("failed to set mode on load-detect pipe\n");
if (old->release_fb)
old->release_fb->funcs->destroy(old->release_fb);
@@ -10304,7 +10303,7 @@ void intel_release_load_detect_pipe(struct drm_connector *connector,
if (ret)
goto fail;

- ret = intel_set_mode(crtc, state);
+ ret = intel_set_mode(state);
if (ret)
goto fail;

@@ -11816,9 +11815,10 @@ clear_intel_crtc_state(struct intel_crtc_state *crtc_state)

static int
intel_modeset_pipe_config(struct drm_crtc *crtc,
- struct drm_atomic_state *state,
- struct intel_crtc_state *pipe_config)
+ struct drm_atomic_state *state)
{
+ struct drm_crtc_state *crtc_state;
+ struct intel_crtc_state *pipe_config;
struct intel_encoder *encoder;
struct drm_connector *connector;
struct drm_connector_state *connector_state;
@@ -11836,6 +11836,12 @@ intel_modeset_pipe_config(struct drm_crtc *crtc,
return -EINVAL;
}

+ crtc_state = drm_atomic_get_existing_crtc_state(state, crtc);
+ if (WARN_ON(!crtc_state))
+ return -EINVAL;
+
+ pipe_config = to_intel_crtc_state(crtc_state);
+
/*
* XXX: Add all connectors to make the crtc state match the encoders.
*/
@@ -12548,45 +12554,35 @@ static void update_scanline_offset(struct intel_crtc *crtc)
crtc->scanline_offset = 1;
}

-static struct intel_crtc_state *
-intel_modeset_compute_config(struct drm_crtc *crtc,
- struct drm_atomic_state *state)
+static int
+intel_modeset_compute_config(struct drm_atomic_state *state)
{
- struct intel_crtc_state *pipe_config;
- int ret = 0;
+ struct drm_crtc *crtc;
+ struct drm_crtc_state *crtc_state;
+ int ret, i;

ret = drm_atomic_helper_check_modeset(state->dev, state);
if (ret)
- return ERR_PTR(ret);
-
- /*
- * Note this needs changes when we start tracking multiple modes
- * and crtcs. At that point we'll need to compute the whole config
- * (i.e. one pipe_config for each crtc) rather than just the one
- * for this crtc.
- */
- pipe_config = intel_atomic_get_crtc_state(state, to_intel_crtc(crtc));
- if (IS_ERR(pipe_config))
- return pipe_config;
-
- if (!pipe_config->base.enable &&
- WARN_ON(pipe_config->base.active))
- pipe_config->base.active = false;
+ return ret;

- if (!pipe_config->base.enable)
- return pipe_config;
+ for_each_crtc_in_state(state, crtc, crtc_state, i) {
+ if (!crtc_state->enable &&
+ WARN_ON(crtc_state->active))
+ crtc_state->active = false;

- ret = intel_modeset_pipe_config(crtc, state, pipe_config);
- if (ret)
- return ERR_PTR(ret);
+ if (!crtc_state->enable)
+ continue;

- intel_dump_pipe_config(to_intel_crtc(crtc), pipe_config, "[modeset]");
+ ret = intel_modeset_pipe_config(crtc, state);
+ if (ret)
+ return ret;

- ret = drm_atomic_helper_check_planes(state->dev, state);
- if (ret)
- return ERR_PTR(ret);
+ intel_dump_pipe_config(to_intel_crtc(crtc),
+ to_intel_crtc_state(crtc_state),
+ "[modeset]");
+ }

- return pipe_config;
+ return drm_atomic_helper_check_planes(state->dev, state);
}

static int __intel_set_mode_setup_plls(struct drm_atomic_state *state)
@@ -12721,37 +12717,27 @@ static int __intel_set_mode(struct drm_atomic_state *state)
return 0;
}

-static int intel_set_mode_with_config(struct drm_crtc *crtc,
- struct intel_crtc_state *pipe_config)
+static int intel_set_mode_checked(struct drm_atomic_state *state)
{
+ struct drm_device *dev = state->dev;
int ret;

- ret = __intel_set_mode(pipe_config->base.state);
-
+ ret = __intel_set_mode(state);
if (ret == 0)
- intel_modeset_check_state(crtc->dev);
+ intel_modeset_check_state(dev);

return ret;
}

-static int intel_set_mode(struct drm_crtc *crtc,
- struct drm_atomic_state *state)
+static int intel_set_mode(struct drm_atomic_state *state)
{
- struct intel_crtc_state *pipe_config;
- int ret = 0;
-
- pipe_config = intel_modeset_compute_config(crtc, state);
- if (IS_ERR(pipe_config)) {
- ret = PTR_ERR(pipe_config);
- goto out;
- }
+ int ret;

- ret = intel_set_mode_with_config(crtc, pipe_config);
+ ret = intel_modeset_compute_config(state);
if (ret)
- goto out;
+ return ret;

-out:
- return ret;
+ return intel_set_mode_checked(state);
}

void intel_crtc_restore_mode(struct drm_crtc *crtc)
@@ -12823,7 +12809,7 @@ void intel_crtc_restore_mode(struct drm_crtc *crtc)
intel_modeset_setup_plane_state(state, crtc, &crtc->mode,
crtc->primary->fb, crtc->x, crtc->y);

- ret = intel_set_mode(crtc, state);
+ ret = intel_set_mode(state);
if (ret)
drm_atomic_state_free(state);
}
@@ -12973,7 +12959,6 @@ static int intel_crtc_set_config(struct drm_mode_set *set)
{
struct drm_device *dev;
struct drm_atomic_state *state = NULL;
- struct intel_crtc_state *pipe_config;
int ret;

BUG_ON(!set);
@@ -13004,16 +12989,13 @@ static int intel_crtc_set_config(struct drm_mode_set *set)
if (ret)
goto out;

- pipe_config = intel_modeset_compute_config(set->crtc, state);
- if (IS_ERR(pipe_config)) {
- ret = PTR_ERR(pipe_config);
+ ret = intel_modeset_compute_config(state);
+ if (ret)
goto out;
- }

intel_update_pipe_size(to_intel_crtc(set->crtc));

- ret = intel_set_mode_with_config(set->crtc, pipe_config);
-
+ ret = intel_set_mode_checked(state);
if (ret) {
DRM_DEBUG_KMS("failed to set mode on [CRTC:%d], err = %d\n",
set->crtc->base.id, ret);