@@ -297,7 +297,6 @@ struct intel_shared_dpll_config {
struct intel_shared_dpll {
struct intel_shared_dpll_config config;
- struct intel_shared_dpll_config *new_config;
int active; /* count of number of active CRTCs (i.e. DPMS on) */
bool on; /* is the PLL actually active? Disabled during modeset */
@@ -504,6 +503,7 @@ struct drm_i915_error_state {
struct intel_connector;
struct intel_encoder;
struct intel_crtc_state;
+struct intel_atomic_state;
struct intel_initial_plane_config;
struct intel_crtc;
struct intel_limit;
@@ -546,6 +546,7 @@ struct drm_i915_display_funcs {
void (*get_initial_plane_config)(struct intel_crtc *,
struct intel_initial_plane_config *);
int (*crtc_compute_clock)(struct intel_crtc *crtc,
+ struct intel_atomic_state *state,
struct intel_crtc_state *crtc_state);
void (*crtc_enable)(struct drm_crtc *crtc);
void (*crtc_disable)(struct drm_crtc *crtc);
@@ -909,6 +909,7 @@ hsw_ddi_calculate_wrpll(int clock /* in Hz */,
static bool
hsw_ddi_pll_select(struct intel_crtc *intel_crtc,
+ struct intel_atomic_state *state,
struct intel_crtc_state *crtc_state,
struct intel_encoder *intel_encoder,
int clock)
@@ -926,7 +927,7 @@ hsw_ddi_pll_select(struct intel_crtc *intel_crtc,
crtc_state->dpll_hw_state.wrpll = val;
- pll = intel_get_shared_dpll(intel_crtc, crtc_state);
+ pll = intel_get_shared_dpll(intel_crtc, state, crtc_state);
if (pll == NULL) {
DRM_DEBUG_DRIVER("failed to find PLL for pipe %c\n",
pipe_name(intel_crtc->pipe));
@@ -1096,6 +1097,7 @@ found:
static bool
skl_ddi_pll_select(struct intel_crtc *intel_crtc,
+ struct intel_atomic_state *state,
struct intel_crtc_state *crtc_state,
struct intel_encoder *intel_encoder,
int clock)
@@ -1150,7 +1152,7 @@ skl_ddi_pll_select(struct intel_crtc *intel_crtc,
crtc_state->dpll_hw_state.cfgcr1 = cfgcr1;
crtc_state->dpll_hw_state.cfgcr2 = cfgcr2;
- pll = intel_get_shared_dpll(intel_crtc, crtc_state);
+ pll = intel_get_shared_dpll(intel_crtc, state, crtc_state);
if (pll == NULL) {
DRM_DEBUG_DRIVER("failed to find PLL for pipe %c\n",
pipe_name(intel_crtc->pipe));
@@ -1171,6 +1173,7 @@ skl_ddi_pll_select(struct intel_crtc *intel_crtc,
* function should be folded into compute_config() eventually.
*/
bool intel_ddi_pll_select(struct intel_crtc *intel_crtc,
+ struct intel_atomic_state *state,
struct intel_crtc_state *crtc_state)
{
struct drm_device *dev = intel_crtc->base.dev;
@@ -1179,10 +1182,10 @@ bool intel_ddi_pll_select(struct intel_crtc *intel_crtc,
int clock = crtc_state->port_clock;
if (IS_SKYLAKE(dev))
- return skl_ddi_pll_select(intel_crtc, crtc_state,
+ return skl_ddi_pll_select(intel_crtc, state, crtc_state,
intel_encoder, clock);
else
- return hsw_ddi_pll_select(intel_crtc, crtc_state,
+ return hsw_ddi_pll_select(intel_crtc, state, crtc_state,
intel_encoder, clock);
}
@@ -3891,6 +3891,7 @@ void intel_put_shared_dpll(struct intel_crtc *crtc)
}
struct intel_shared_dpll *intel_get_shared_dpll(struct intel_crtc *crtc,
+ struct intel_atomic_state *state,
struct intel_crtc_state *crtc_state)
{
struct drm_i915_private *dev_priv = crtc->base.dev->dev_private;
@@ -3905,7 +3906,7 @@ struct intel_shared_dpll *intel_get_shared_dpll(struct intel_crtc *crtc,
DRM_DEBUG_KMS("CRTC:%d using pre-allocated %s\n",
crtc->base.base.id, pll->name);
- WARN_ON(pll->new_config->crtc_mask);
+ WARN_ON(state->shared_dpll[i].crtc_mask);
goto found;
}
@@ -3914,15 +3915,15 @@ struct intel_shared_dpll *intel_get_shared_dpll(struct intel_crtc *crtc,
pll = &dev_priv->shared_dplls[i];
/* Only want to check enabled timings first */
- if (pll->new_config->crtc_mask == 0)
+ if (state->shared_dpll[i].crtc_mask == 0)
continue;
if (memcmp(&crtc_state->dpll_hw_state,
- &pll->new_config->hw_state,
- sizeof(pll->new_config->hw_state)) == 0) {
+ &state->shared_dpll[i].hw_state,
+ sizeof(state->shared_dpll[i].hw_state)) == 0) {
DRM_DEBUG_KMS("CRTC:%d sharing existing %s (crtc mask 0x%08x, ative %d)\n",
crtc->base.base.id, pll->name,
- pll->new_config->crtc_mask,
+ state->shared_dpll[i].crtc_mask,
pll->active);
goto found;
}
@@ -3931,7 +3932,7 @@ struct intel_shared_dpll *intel_get_shared_dpll(struct intel_crtc *crtc,
/* Ok no matching timings, maybe there's a free one? */
for (i = 0; i < dev_priv->num_shared_dpll; i++) {
pll = &dev_priv->shared_dplls[i];
- if (pll->new_config->crtc_mask == 0) {
+ if (state->shared_dpll[i].crtc_mask == 0) {
DRM_DEBUG_KMS("CRTC:%d allocated %s\n",
crtc->base.base.id, pll->name);
goto found;
@@ -3941,14 +3942,14 @@ struct intel_shared_dpll *intel_get_shared_dpll(struct intel_crtc *crtc,
return NULL;
found:
- if (pll->new_config->crtc_mask == 0)
- pll->new_config->hw_state = crtc_state->dpll_hw_state;
+ if (state->shared_dpll[i].crtc_mask == 0)
+ state->shared_dpll[i].hw_state = crtc_state->dpll_hw_state;
crtc_state->shared_dpll = i;
DRM_DEBUG_DRIVER("using %s for pipe %c\n", pll->name,
pipe_name(crtc->pipe));
- pll->new_config->crtc_mask |= 1 << crtc->pipe;
+ state->shared_dpll[i].crtc_mask |= 1 << crtc->pipe;
return pll;
}
@@ -3962,6 +3963,7 @@ found:
* releasing the references of pipes specified in clear_pipes.
*/
static int intel_shared_dpll_start_config(struct drm_i915_private *dev_priv,
+ struct intel_atomic_state *state,
unsigned clear_pipes)
{
struct intel_shared_dpll *pll;
@@ -3970,54 +3972,23 @@ static int intel_shared_dpll_start_config(struct drm_i915_private *dev_priv,
for (i = 0; i < dev_priv->num_shared_dpll; i++) {
pll = &dev_priv->shared_dplls[i];
- pll->new_config = kmemdup(&pll->config, sizeof pll->config,
- GFP_KERNEL);
- if (!pll->new_config)
- goto cleanup;
-
- pll->new_config->crtc_mask &= ~clear_pipes;
+ memcpy(&state->shared_dpll[i], &pll->config,
+ sizeof pll->config);
+ state->shared_dpll[i].crtc_mask &= ~clear_pipes;
}
return 0;
-
-cleanup:
- while (--i >= 0) {
- pll = &dev_priv->shared_dplls[i];
- kfree(pll->new_config);
- pll->new_config = NULL;
- }
-
- return -ENOMEM;
}
-static void intel_shared_dpll_commit(struct drm_i915_private *dev_priv)
+static void intel_shared_dpll_commit(struct drm_i915_private *dev_priv,
+ struct intel_atomic_state *state)
{
struct intel_shared_dpll *pll;
enum intel_dpll_id i;
for (i = 0; i < dev_priv->num_shared_dpll; i++) {
pll = &dev_priv->shared_dplls[i];
-
- WARN_ON(pll->new_config == &pll->config);
-
- pll->config = *pll->new_config;
- kfree(pll->new_config);
- pll->new_config = NULL;
- }
-}
-
-static void intel_shared_dpll_abort_config(struct drm_i915_private *dev_priv)
-{
- struct intel_shared_dpll *pll;
- enum intel_dpll_id i;
-
- for (i = 0; i < dev_priv->num_shared_dpll; i++) {
- pll = &dev_priv->shared_dplls[i];
-
- WARN_ON(pll->new_config == &pll->config);
-
- kfree(pll->new_config);
- pll->new_config = NULL;
+ pll->config = state->shared_dpll[i];
}
}
@@ -6426,6 +6397,7 @@ static void i9xx_set_pipeconf(struct intel_crtc *intel_crtc)
}
static int i9xx_crtc_compute_clock(struct intel_crtc *crtc,
+ struct intel_atomic_state *state,
struct intel_crtc_state *crtc_state)
{
struct drm_device *dev = crtc->base.dev;
@@ -7452,6 +7424,7 @@ static uint32_t ironlake_compute_dpll(struct intel_crtc *intel_crtc,
}
static int ironlake_crtc_compute_clock(struct intel_crtc *crtc,
+ struct intel_atomic_state *state,
struct intel_crtc_state *crtc_state)
{
struct drm_device *dev = crtc->base.dev;
@@ -7498,7 +7471,7 @@ static int ironlake_crtc_compute_clock(struct intel_crtc *crtc,
else
crtc_state->dpll_hw_state.fp1 = fp;
- pll = intel_get_shared_dpll(crtc, crtc_state);
+ pll = intel_get_shared_dpll(crtc, state, crtc_state);
if (pll == NULL) {
DRM_DEBUG_DRIVER("failed to find PLL for pipe %c\n",
pipe_name(crtc->pipe));
@@ -8070,9 +8043,10 @@ void hsw_disable_pc8(struct drm_i915_private *dev_priv)
}
static int haswell_crtc_compute_clock(struct intel_crtc *crtc,
+ struct intel_atomic_state *state,
struct intel_crtc_state *crtc_state)
{
- if (!intel_ddi_pll_select(crtc, crtc_state))
+ if (!intel_ddi_pll_select(crtc, state, crtc_state))
return -EINVAL;
crtc->lowfreq_avail = false;
@@ -10417,14 +10391,15 @@ static bool intel_crtc_in_use(struct drm_crtc *crtc)
}
static void
-intel_modeset_update_state(struct drm_device *dev, unsigned prepare_pipes)
+intel_modeset_update_state(struct drm_device *dev, unsigned prepare_pipes,
+ struct intel_atomic_state *state)
{
struct drm_i915_private *dev_priv = dev->dev_private;
struct intel_encoder *intel_encoder;
struct intel_crtc *intel_crtc;
struct drm_connector *connector;
- intel_shared_dpll_commit(dev_priv);
+ intel_shared_dpll_commit(dev_priv, state);
for_each_intel_encoder(dev, intel_encoder) {
if (!intel_encoder->base.crtc)
@@ -11022,6 +10997,7 @@ out:
}
static int __intel_set_mode_setup_plls(struct drm_device *dev,
+ struct intel_atomic_state *state,
unsigned modeset_pipes,
unsigned disable_pipes)
{
@@ -11033,21 +11009,18 @@ static int __intel_set_mode_setup_plls(struct drm_device *dev,
if (!dev_priv->display.crtc_compute_clock)
return 0;
- ret = intel_shared_dpll_start_config(dev_priv, clear_pipes);
+ ret = intel_shared_dpll_start_config(dev_priv, state, clear_pipes);
if (ret)
- goto done;
+ return ret;
for_each_intel_crtc_masked(dev, modeset_pipes, intel_crtc) {
- struct intel_crtc_state *state = intel_crtc->new_config;
+ struct intel_crtc_state *crtc_state = intel_crtc->new_config;
ret = dev_priv->display.crtc_compute_clock(intel_crtc,
- state);
- if (ret) {
- intel_shared_dpll_abort_config(dev_priv);
- goto done;
- }
+ state, crtc_state);
+ if (ret)
+ break;
}
-done:
return ret;
}
@@ -11063,6 +11036,7 @@ static int __intel_set_mode(struct drm_crtc *crtc,
struct drm_i915_private *dev_priv = dev->dev_private;
struct drm_display_mode *saved_mode;
struct intel_crtc *intel_crtc;
+ struct intel_atomic_state *state = NULL;
int ret = 0;
saved_mode = kmalloc(sizeof(*saved_mode), GFP_KERNEL);
@@ -11088,7 +11062,14 @@ static int __intel_set_mode(struct drm_crtc *crtc,
prepare_pipes &= ~disable_pipes;
}
- ret = __intel_set_mode_setup_plls(dev, modeset_pipes, disable_pipes);
+ state = kzalloc(sizeof *state, GFP_KERNEL);
+ if (!state) {
+ ret = -ENOMEM;
+ goto done;
+ }
+
+ ret = __intel_set_mode_setup_plls(dev, state,
+ modeset_pipes, disable_pipes);
if (ret)
goto done;
@@ -11124,7 +11105,7 @@ static int __intel_set_mode(struct drm_crtc *crtc,
/* Only after disabling all output pipelines that will be changed can we
* update the the output configuration. */
- intel_modeset_update_state(dev, prepare_pipes);
+ intel_modeset_update_state(dev, prepare_pipes, state);
modeset_update_crtc_power_domains(dev);
@@ -11155,6 +11136,7 @@ done:
if (ret && crtc->enabled)
crtc->mode = *saved_mode;
+ kfree(state);
kfree(saved_mode);
return ret;
}
@@ -243,6 +243,10 @@ typedef struct dpll {
int p;
} intel_clock_t;
+struct intel_atomic_state {
+ struct intel_shared_dpll_config shared_dpll[I915_NUM_PLLS];
+};
+
struct intel_plane_state {
struct drm_plane_state base;
struct drm_rect src;
@@ -837,6 +841,7 @@ void intel_ddi_disable_transcoder_func(struct drm_i915_private *dev_priv,
void intel_ddi_enable_pipe_clock(struct intel_crtc *intel_crtc);
void intel_ddi_disable_pipe_clock(struct intel_crtc *intel_crtc);
bool intel_ddi_pll_select(struct intel_crtc *crtc,
+ struct intel_atomic_state *state,
struct intel_crtc_state *crtc_state);
void intel_ddi_set_pipe_settings(struct drm_crtc *crtc);
void intel_ddi_prepare_link_retrain(struct drm_encoder *encoder);
@@ -962,7 +967,8 @@ void assert_shared_dpll(struct drm_i915_private *dev_priv,
#define assert_shared_dpll_enabled(d, p) assert_shared_dpll(d, p, true)
#define assert_shared_dpll_disabled(d, p) assert_shared_dpll(d, p, false)
struct intel_shared_dpll *intel_get_shared_dpll(struct intel_crtc *crtc,
- struct intel_crtc_state *state);
+ struct intel_atomic_state *state,
+ struct intel_crtc_state *crtc_state);
void intel_put_shared_dpll(struct intel_crtc *crtc);
void vlv_force_pll_on(struct drm_device *dev, enum pipe pipe,
In order to implement atomic mode sets, we'll need to hold state shared by multiple crtcs in the drm_atomic_state struct. This patch moves towards that goal by introducing struct intel_atomic_state for that purpose and moving the staged pll configuration into it. Current state will be moved in a follow up patch. Signed-off-by: Ander Conselvan de Oliveira <ander.conselvan.de.oliveira@intel.com> --- drivers/gpu/drm/i915/i915_drv.h | 3 +- drivers/gpu/drm/i915/intel_ddi.c | 11 ++-- drivers/gpu/drm/i915/intel_display.c | 104 +++++++++++++++-------------------- drivers/gpu/drm/i915/intel_drv.h | 8 ++- 4 files changed, 59 insertions(+), 67 deletions(-)