Skip to content

Commit

Permalink
drm/i915: Convert cdclk to global state
Browse files Browse the repository at this point in the history
Let's convert cdclk_state to be a proper global state. That allows
us to use the regular atomic old vs. new state accessor, hopefully
making the code less confusing.

We do have to deal with a few more error cases in case the cdclk
state duplication fails. But so be it.

v2: Fix new plane min_cdclk vs. old crtc min_cdclk check

Signed-off-by: Ville Syrjälä <ville.syrjala@linux.intel.com>
Link: https://patchwork.freedesktop.org/patch/msgid/20200121140353.25997-1-ville.syrjala@linux.intel.com
Reviewed-by: Imre Deak <imre.deak@intel.com>
  • Loading branch information
Ville Syrjälä committed Jan 31, 2020
1 parent aac9787 commit 28a30b4
Show file tree
Hide file tree
Showing 9 changed files with 317 additions and 204 deletions.
1 change: 0 additions & 1 deletion drivers/gpu/drm/i915/display/intel_atomic.c
Original file line number Diff line number Diff line change
Expand Up @@ -520,7 +520,6 @@ void intel_atomic_state_clear(struct drm_atomic_state *s)
state->dpll_set = state->modeset = false;
state->global_state_changed = false;
state->active_pipes = 0;
intel_cdclk_clear_state(state);
}

struct intel_crtc_state *
Expand Down
69 changes: 44 additions & 25 deletions drivers/gpu/drm/i915/display/intel_atomic_plane.c
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,7 @@

#include "i915_trace.h"
#include "intel_atomic_plane.h"
#include "intel_cdclk.h"
#include "intel_display_types.h"
#include "intel_pm.h"
#include "intel_sprite.h"
Expand Down Expand Up @@ -155,45 +156,63 @@ unsigned int intel_plane_data_rate(const struct intel_crtc_state *crtc_state,
return cpp * crtc_state->pixel_rate;
}

bool intel_plane_calc_min_cdclk(struct intel_atomic_state *state,
struct intel_plane *plane)
int intel_plane_calc_min_cdclk(struct intel_atomic_state *state,
struct intel_plane *plane,
bool *need_cdclk_calc)
{
struct drm_i915_private *dev_priv = to_i915(plane->base.dev);
const struct intel_cdclk_state *cdclk_state =
&dev_priv->cdclk_state;
const struct intel_plane_state *plane_state =
intel_atomic_get_new_plane_state(state, plane);
struct intel_crtc *crtc = to_intel_crtc(plane_state->hw.crtc);
struct intel_crtc_state *crtc_state;
const struct intel_cdclk_state *cdclk_state;
struct intel_crtc_state *new_crtc_state =
intel_atomic_get_new_crtc_state(state, crtc);
const struct intel_crtc_state *old_crtc_state =
intel_atomic_get_old_crtc_state(state, crtc);

if (!plane_state->uapi.visible || !plane->min_cdclk)
return false;
return 0;

new_crtc_state->min_cdclk[plane->id] =
plane->min_cdclk(new_crtc_state, plane_state);

crtc_state = intel_atomic_get_new_crtc_state(state, crtc);
/*
* No need to check against the cdclk state if
* the min cdclk for the plane doesn't increase.
*
* Ie. we only ever increase the cdclk due to plane
* requirements. This can reduce back and forth
* display blinking due to constant cdclk changes.
*/
if (new_crtc_state->min_cdclk[plane->id] <=
old_crtc_state->min_cdclk[plane->id])
return 0;

crtc_state->min_cdclk[plane->id] =
plane->min_cdclk(crtc_state, plane_state);
cdclk_state = intel_atomic_get_cdclk_state(state);
if (IS_ERR(cdclk_state))
return PTR_ERR(cdclk_state);

/*
* Does the cdclk need to be bumbed up?
* No need to recalculate the cdclk state if
* the min cdclk for the pipe doesn't increase.
*
* Note: we obviously need to be called before the new
* cdclk frequency is calculated so state->cdclk.logical
* hasn't been populated yet. Hence we look at the old
* cdclk state under dev_priv->cdclk.logical. This is
* safe as long we hold at least one crtc mutex (which
* must be true since we have crtc_state).
* Ie. we only ever increase the cdclk due to plane
* requirements. This can reduce back and forth
* display blinking due to constant cdclk changes.
*/
if (crtc_state->min_cdclk[plane->id] > cdclk_state->logical.cdclk) {
drm_dbg_kms(&dev_priv->drm,
"[PLANE:%d:%s] min_cdclk (%d kHz) > logical cdclk (%d kHz)\n",
plane->base.base.id, plane->base.name,
crtc_state->min_cdclk[plane->id],
cdclk_state->logical.cdclk);
return true;
}
if (new_crtc_state->min_cdclk[plane->id] <=
cdclk_state->min_cdclk[crtc->pipe])
return 0;

drm_dbg_kms(&dev_priv->drm,
"[PLANE:%d:%s] min cdclk (%d kHz) > [CRTC:%d:%s] min cdclk (%d kHz)\n",
plane->base.base.id, plane->base.name,
new_crtc_state->min_cdclk[plane->id],
crtc->base.base.id, crtc->base.name,
cdclk_state->min_cdclk[crtc->pipe]);
*need_cdclk_calc = true;

return false;
return 0;
}

static void intel_plane_clear_hw_state(struct intel_plane_state *plane_state)
Expand Down
5 changes: 3 additions & 2 deletions drivers/gpu/drm/i915/display/intel_atomic_plane.h
Original file line number Diff line number Diff line change
Expand Up @@ -46,7 +46,8 @@ int intel_plane_atomic_calc_changes(const struct intel_crtc_state *old_crtc_stat
struct intel_crtc_state *crtc_state,
const struct intel_plane_state *old_plane_state,
struct intel_plane_state *plane_state);
bool intel_plane_calc_min_cdclk(struct intel_atomic_state *state,
struct intel_plane *plane);
int intel_plane_calc_min_cdclk(struct intel_atomic_state *state,
struct intel_plane *plane,
bool *need_cdclk_calc);

#endif /* __INTEL_ATOMIC_PLANE_H__ */
39 changes: 30 additions & 9 deletions drivers/gpu/drm/i915/display/intel_audio.c
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,7 @@
#include "i915_drv.h"
#include "intel_atomic.h"
#include "intel_audio.h"
#include "intel_cdclk.h"
#include "intel_display_types.h"
#include "intel_lpe_audio.h"

Expand Down Expand Up @@ -809,6 +810,34 @@ void intel_init_audio_hooks(struct drm_i915_private *dev_priv)
}
}

static int glk_force_audio_cdclk_commit(struct intel_atomic_state *state,
bool enable)
{
struct drm_i915_private *dev_priv = to_i915(state->base.dev);
struct intel_cdclk_state *cdclk_state;
struct intel_crtc *crtc;
int ret;

/* need to hold at least one crtc lock for the global state */
crtc = intel_get_crtc_for_pipe(dev_priv, PIPE_A);
ret = drm_modeset_lock(&crtc->base.mutex, state->base.acquire_ctx);
if (ret)
return ret;

cdclk_state = intel_atomic_get_cdclk_state(state);
if (IS_ERR(cdclk_state))
return PTR_ERR(cdclk_state);

cdclk_state->force_min_cdclk_changed = true;
cdclk_state->force_min_cdclk = enable ? 2 * 96000 : 0;

ret = intel_atomic_lock_global_state(&cdclk_state->base);
if (ret)
return ret;

return drm_atomic_commit(&state->base);
}

static void glk_force_audio_cdclk(struct drm_i915_private *dev_priv,
bool enable)
{
Expand All @@ -824,15 +853,7 @@ static void glk_force_audio_cdclk(struct drm_i915_private *dev_priv,
state->acquire_ctx = &ctx;

retry:
to_intel_atomic_state(state)->cdclk_state.force_min_cdclk_changed = true;
to_intel_atomic_state(state)->cdclk_state.force_min_cdclk =
enable ? 2 * 96000 : 0;

/* Protects dev_priv->cdclk.force_min_cdclk */
ret = _intel_atomic_lock_global_state(to_intel_atomic_state(state));
if (!ret)
ret = drm_atomic_commit(state);

ret = glk_force_audio_cdclk_commit(to_intel_atomic_state(state), enable);
if (ret == -EDEADLK) {
drm_atomic_state_clear(state);
drm_modeset_backoff(&ctx);
Expand Down
Loading

0 comments on commit 28a30b4

Please sign in to comment.