Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
73 changes: 73 additions & 0 deletions drivers/gpu/drm/i915/display/intel_cdclk.c
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,8 @@
#include "intel_pcode.h"
#include "intel_psr.h"
#include "intel_vdsc.h"
#include "skl_watermark.h"
#include "skl_watermark_regs.h"
#include "vlv_sideband.h"

/**
Expand Down Expand Up @@ -1580,6 +1582,8 @@ static void bxt_get_cdclk(struct drm_i915_private *dev_priv,
}

out:
if (DISPLAY_VER(dev_priv) >= 20)
cdclk_config->joined_mbus = intel_de_read(dev_priv, MBUS_CTL) & MBUS_JOIN;
/*
* Can't read this out :( Let's assume it's
* at least what the CDCLK frequency requires.
Expand Down Expand Up @@ -1779,6 +1783,29 @@ static int cdclk_squash_divider(u16 waveform)
return hweight16(waveform ?: 0xffff);
}

static bool mdclk_source_is_cdclk_pll(struct drm_i915_private *i915)
{
return DISPLAY_VER(i915) >= 20;
}

int intel_mdclk_cdclk_ratio(struct drm_i915_private *i915,
const struct intel_cdclk_config *cdclk_config)
{
if (mdclk_source_is_cdclk_pll(i915))
return DIV_ROUND_UP(cdclk_config->vco, cdclk_config->cdclk);

/* Otherwise, source for MDCLK is CD2XCLK. */
return 2;
}

static void xe2lpd_mdclk_cdclk_ratio_program(struct drm_i915_private *i915,
const struct intel_cdclk_config *cdclk_config)
{
intel_dbuf_mdclk_cdclk_ratio_update(i915,
intel_mdclk_cdclk_ratio(i915, cdclk_config),
cdclk_config->joined_mbus);
}

static bool cdclk_compute_crawl_and_squash_midpoint(struct drm_i915_private *i915,
const struct intel_cdclk_config *old_cdclk_config,
const struct intel_cdclk_config *new_cdclk_config,
Expand Down Expand Up @@ -1932,6 +1959,9 @@ static void bxt_set_cdclk(struct drm_i915_private *dev_priv,
return;
}

if (DISPLAY_VER(dev_priv) >= 20 && cdclk < dev_priv->display.cdclk.hw.cdclk)
xe2lpd_mdclk_cdclk_ratio_program(dev_priv, cdclk_config);

if (cdclk_compute_crawl_and_squash_midpoint(dev_priv, &dev_priv->display.cdclk.hw,
cdclk_config, &mid_cdclk_config)) {
_bxt_set_cdclk(dev_priv, &mid_cdclk_config, pipe);
Expand All @@ -1940,6 +1970,9 @@ static void bxt_set_cdclk(struct drm_i915_private *dev_priv,
_bxt_set_cdclk(dev_priv, cdclk_config, pipe);
}

if (DISPLAY_VER(dev_priv) >= 20 && cdclk > dev_priv->display.cdclk.hw.cdclk)
xe2lpd_mdclk_cdclk_ratio_program(dev_priv, cdclk_config);

if (DISPLAY_VER(dev_priv) >= 14)
/*
* NOOP - No Pcode communication needed for
Expand Down Expand Up @@ -2438,6 +2471,17 @@ static void intel_cdclk_pcode_post_notify(struct intel_atomic_state *state)
update_cdclk, update_pipe_count);
}

bool intel_cdclk_is_decreasing_later(struct intel_atomic_state *state)
{
const struct intel_cdclk_state *old_cdclk_state =
intel_atomic_get_old_cdclk_state(state);
const struct intel_cdclk_state *new_cdclk_state =
intel_atomic_get_new_cdclk_state(state);

return new_cdclk_state && !new_cdclk_state->disable_pipes &&
new_cdclk_state->actual.cdclk < old_cdclk_state->actual.cdclk;
}

/**
* intel_set_cdclk_pre_plane_update - Push the CDCLK state to the hardware
* @state: intel atomic state
Expand Down Expand Up @@ -2479,6 +2523,12 @@ intel_set_cdclk_pre_plane_update(struct intel_atomic_state *state)
old_cdclk_state->actual.voltage_level);
}

/*
* mbus joining will be changed later by
* intel_dbuf_mbus_{pre,post}_ddb_update()
*/
cdclk_config.joined_mbus = old_cdclk_state->actual.joined_mbus;

drm_WARN_ON(&i915->drm, !new_cdclk_state->base.changed);

intel_set_cdclk(i915, &cdclk_config, pipe);
Expand Down Expand Up @@ -3027,6 +3077,20 @@ int intel_cdclk_atomic_check(struct intel_atomic_state *state,
return 0;
}

int intel_cdclk_state_set_joined_mbus(struct intel_atomic_state *state, bool joined_mbus)
{
struct intel_cdclk_state *cdclk_state;

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

cdclk_state->actual.joined_mbus = joined_mbus;
cdclk_state->logical.joined_mbus = joined_mbus;

return intel_atomic_lock_global_state(&cdclk_state->base);
}

int intel_cdclk_init(struct drm_i915_private *dev_priv)
{
struct intel_cdclk_state *cdclk_state;
Expand Down Expand Up @@ -3148,6 +3212,15 @@ int intel_modeset_calc_cdclk(struct intel_atomic_state *state)
"Modeset required for cdclk change\n");
}

if (intel_mdclk_cdclk_ratio(dev_priv, &old_cdclk_state->actual) !=
intel_mdclk_cdclk_ratio(dev_priv, &new_cdclk_state->actual)) {
int ratio = intel_mdclk_cdclk_ratio(dev_priv, &new_cdclk_state->actual);

ret = intel_dbuf_state_set_mdclk_cdclk_ratio(state, ratio);
if (ret)
return ret;
}

drm_dbg_kms(&dev_priv->drm,
"New cdclk calculated to be logical %u kHz, actual %u kHz\n",
new_cdclk_state->logical.cdclk,
Expand Down
6 changes: 6 additions & 0 deletions drivers/gpu/drm/i915/display/intel_cdclk.h
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,8 @@ struct intel_crtc_state;
struct intel_cdclk_config {
unsigned int cdclk, vco, ref, bypass;
u8 voltage_level;
/* This field is only valid for Xe2LPD and above. */
bool joined_mbus;
};

struct intel_cdclk_state {
Expand Down Expand Up @@ -65,6 +67,9 @@ void intel_update_cdclk(struct drm_i915_private *dev_priv);
u32 intel_read_rawclk(struct drm_i915_private *dev_priv);
bool intel_cdclk_needs_modeset(const struct intel_cdclk_config *a,
const struct intel_cdclk_config *b);
int intel_mdclk_cdclk_ratio(struct drm_i915_private *i915,
const struct intel_cdclk_config *cdclk_config);
bool intel_cdclk_is_decreasing_later(struct intel_atomic_state *state);
void intel_set_cdclk_pre_plane_update(struct intel_atomic_state *state);
void intel_set_cdclk_post_plane_update(struct intel_atomic_state *state);
void intel_cdclk_dump_config(struct drm_i915_private *i915,
Expand All @@ -75,6 +80,7 @@ void intel_cdclk_get_cdclk(struct drm_i915_private *dev_priv,
struct intel_cdclk_config *cdclk_config);
int intel_cdclk_atomic_check(struct intel_atomic_state *state,
bool *need_cdclk_calc);
int intel_cdclk_state_set_joined_mbus(struct intel_atomic_state *state, bool joined_mbus);
struct intel_cdclk_state *
intel_atomic_get_cdclk_state(struct intel_atomic_state *state);

Expand Down
77 changes: 62 additions & 15 deletions drivers/gpu/drm/i915/display/intel_display.c
Original file line number Diff line number Diff line change
Expand Up @@ -6555,8 +6555,8 @@ static void intel_enable_crtc(struct intel_atomic_state *state,
intel_crtc_enable_pipe_crc(crtc);
}

static void intel_update_crtc(struct intel_atomic_state *state,
struct intel_crtc *crtc)
static void intel_pre_update_crtc(struct intel_atomic_state *state,
struct intel_crtc *crtc)
{
struct drm_i915_private *i915 = to_i915(state->base.dev);
const struct intel_crtc_state *old_crtc_state =
Expand Down Expand Up @@ -6598,6 +6598,15 @@ static void intel_update_crtc(struct intel_atomic_state *state,
intel_color_commit_noarm(new_crtc_state);

intel_crtc_planes_update_noarm(state, crtc);
}

static void intel_update_crtc(struct intel_atomic_state *state,
struct intel_crtc *crtc)
{
const struct intel_crtc_state *old_crtc_state =
intel_atomic_get_old_crtc_state(state, crtc);
struct intel_crtc_state *new_crtc_state =
intel_atomic_get_new_crtc_state(state, crtc);

/* Perform vblank evasion around commit operation */
intel_pipe_update_start(state, crtc);
Expand Down Expand Up @@ -6626,7 +6635,7 @@ static void intel_update_crtc(struct intel_atomic_state *state,
* valid pipe configuration from the BIOS we need to take care
* of enabling them on the CRTC's first fastset.
*/
if (intel_crtc_needs_fastset(new_crtc_state) && !modeset &&
if (intel_crtc_needs_fastset(new_crtc_state) &&
old_crtc_state->inherited)
intel_crtc_arm_fifo_underrun(crtc, new_crtc_state);
}
Expand Down Expand Up @@ -6654,31 +6663,40 @@ static void intel_old_crtc_state_disables(struct intel_atomic_state *state,

static void intel_commit_modeset_disables(struct intel_atomic_state *state)
{
struct drm_i915_private *i915 = to_i915(state->base.dev);
struct intel_crtc_state *new_crtc_state, *old_crtc_state;
struct intel_crtc *crtc;
u32 handled = 0;
u8 disable_pipes = 0;
int i;

for_each_oldnew_intel_crtc_in_state(state, crtc, old_crtc_state,
new_crtc_state, i) {
if (!intel_crtc_needs_modeset(new_crtc_state))
continue;

/*
* Needs to be done even for pipes
* that weren't enabled previously.
*/
intel_pre_plane_update(state, crtc);

if (!old_crtc_state->hw.active)
continue;

disable_pipes |= BIT(crtc->pipe);
}

for_each_old_intel_crtc_in_state(state, crtc, old_crtc_state, i) {
if ((disable_pipes & BIT(crtc->pipe)) == 0)
continue;

intel_crtc_disable_planes(state, crtc);
}

/* Only disable port sync and MST slaves */
for_each_oldnew_intel_crtc_in_state(state, crtc, old_crtc_state,
new_crtc_state, i) {
if (!intel_crtc_needs_modeset(new_crtc_state))
continue;

if (!old_crtc_state->hw.active)
if ((disable_pipes & BIT(crtc->pipe)) == 0)
continue;

/* In case of Transcoder port Sync master slave CRTCs can be
Expand All @@ -6693,22 +6711,23 @@ static void intel_commit_modeset_disables(struct intel_atomic_state *state)

intel_old_crtc_state_disables(state, old_crtc_state,
new_crtc_state, crtc);
handled |= BIT(crtc->pipe);

disable_pipes &= ~BIT(crtc->pipe);
}

/* Disable everything else left on */
for_each_oldnew_intel_crtc_in_state(state, crtc, old_crtc_state,
new_crtc_state, i) {
if (!intel_crtc_needs_modeset(new_crtc_state) ||
(handled & BIT(crtc->pipe)))
continue;

if (!old_crtc_state->hw.active)
if ((disable_pipes & BIT(crtc->pipe)) == 0)
continue;

intel_old_crtc_state_disables(state, old_crtc_state,
new_crtc_state, crtc);

disable_pipes &= ~BIT(crtc->pipe);
}

drm_WARN_ON(&i915->drm, disable_pipes);
}

static void intel_commit_modeset_enables(struct intel_atomic_state *state)
Expand All @@ -6722,6 +6741,13 @@ static void intel_commit_modeset_enables(struct intel_atomic_state *state)
continue;

intel_enable_crtc(state, crtc);
intel_pre_update_crtc(state, crtc);
}

for_each_new_intel_crtc_in_state(state, crtc, new_crtc_state, i) {
if (!new_crtc_state->hw.active)
continue;

intel_update_crtc(state, crtc);
}
}
Expand Down Expand Up @@ -6759,6 +6785,17 @@ static void skl_commit_modeset_enables(struct intel_atomic_state *state)
* So first lets enable all pipes that do not need a fullmodeset as
* those don't have any external dependency.
*/
for_each_new_intel_crtc_in_state(state, crtc, new_crtc_state, i) {
enum pipe pipe = crtc->pipe;

if ((update_pipes & BIT(pipe)) == 0)
continue;

intel_pre_update_crtc(state, crtc);
}

intel_dbuf_mbus_pre_ddb_update(state);

while (update_pipes) {
for_each_oldnew_intel_crtc_in_state(state, crtc, old_crtc_state,
new_crtc_state, i) {
Expand Down Expand Up @@ -6789,6 +6826,8 @@ static void skl_commit_modeset_enables(struct intel_atomic_state *state)
}
}

intel_dbuf_mbus_post_ddb_update(state);

update_pipes = modeset_pipes;

/*
Expand Down Expand Up @@ -6829,6 +6868,15 @@ static void skl_commit_modeset_enables(struct intel_atomic_state *state)
/*
* Finally we do the plane updates/etc. for all pipes that got enabled.
*/
for_each_new_intel_crtc_in_state(state, crtc, new_crtc_state, i) {
enum pipe pipe = crtc->pipe;

if ((update_pipes & BIT(pipe)) == 0)
continue;

intel_pre_update_crtc(state, crtc);
}

for_each_new_intel_crtc_in_state(state, crtc, new_crtc_state, i) {
enum pipe pipe = crtc->pipe;

Expand Down Expand Up @@ -7050,7 +7098,6 @@ static void intel_atomic_commit_tail(struct intel_atomic_state *state)
intel_encoders_update_prepare(state);

intel_dbuf_pre_plane_update(state);
intel_mbus_dbox_update(state);

for_each_new_intel_crtc_in_state(state, crtc, new_crtc_state, i) {
if (new_crtc_state->do_async_flip)
Expand Down
Loading
Loading