|
|
|
@ -4717,6 +4717,10 @@ static const struct dbuf_slice_conf_entry dg2_allowed_dbufs[] = {
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
static const struct dbuf_slice_conf_entry adlp_allowed_dbufs[] = {
|
|
|
|
|
/*
|
|
|
|
|
* Keep the join_mbus cases first so check_mbus_joined()
|
|
|
|
|
* will prefer them over the !join_mbus cases.
|
|
|
|
|
*/
|
|
|
|
|
{
|
|
|
|
|
.active_pipes = BIT(PIPE_A),
|
|
|
|
|
.dbuf_mask = {
|
|
|
|
@ -4731,6 +4735,20 @@ static const struct dbuf_slice_conf_entry adlp_allowed_dbufs[] = {
|
|
|
|
|
},
|
|
|
|
|
.join_mbus = true,
|
|
|
|
|
},
|
|
|
|
|
{
|
|
|
|
|
.active_pipes = BIT(PIPE_A),
|
|
|
|
|
.dbuf_mask = {
|
|
|
|
|
[PIPE_A] = BIT(DBUF_S1) | BIT(DBUF_S2),
|
|
|
|
|
},
|
|
|
|
|
.join_mbus = false,
|
|
|
|
|
},
|
|
|
|
|
{
|
|
|
|
|
.active_pipes = BIT(PIPE_B),
|
|
|
|
|
.dbuf_mask = {
|
|
|
|
|
[PIPE_B] = BIT(DBUF_S3) | BIT(DBUF_S4),
|
|
|
|
|
},
|
|
|
|
|
.join_mbus = false,
|
|
|
|
|
},
|
|
|
|
|
{
|
|
|
|
|
.active_pipes = BIT(PIPE_A) | BIT(PIPE_B),
|
|
|
|
|
.dbuf_mask = {
|
|
|
|
@ -4847,13 +4865,14 @@ static bool adlp_check_mbus_joined(u8 active_pipes)
|
|
|
|
|
return check_mbus_joined(active_pipes, adlp_allowed_dbufs);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static u8 compute_dbuf_slices(enum pipe pipe, u8 active_pipes,
|
|
|
|
|
static u8 compute_dbuf_slices(enum pipe pipe, u8 active_pipes, bool join_mbus,
|
|
|
|
|
const struct dbuf_slice_conf_entry *dbuf_slices)
|
|
|
|
|
{
|
|
|
|
|
int i;
|
|
|
|
|
|
|
|
|
|
for (i = 0; i < dbuf_slices[i].active_pipes; i++) {
|
|
|
|
|
if (dbuf_slices[i].active_pipes == active_pipes)
|
|
|
|
|
if (dbuf_slices[i].active_pipes == active_pipes &&
|
|
|
|
|
dbuf_slices[i].join_mbus == join_mbus)
|
|
|
|
|
return dbuf_slices[i].dbuf_mask[pipe];
|
|
|
|
|
}
|
|
|
|
|
return 0;
|
|
|
|
@ -4864,7 +4883,7 @@ static u8 compute_dbuf_slices(enum pipe pipe, u8 active_pipes,
|
|
|
|
|
* returns correspondent DBuf slice mask as stated in BSpec for particular
|
|
|
|
|
* platform.
|
|
|
|
|
*/
|
|
|
|
|
static u8 icl_compute_dbuf_slices(enum pipe pipe, u8 active_pipes)
|
|
|
|
|
static u8 icl_compute_dbuf_slices(enum pipe pipe, u8 active_pipes, bool join_mbus)
|
|
|
|
|
{
|
|
|
|
|
/*
|
|
|
|
|
* FIXME: For ICL this is still a bit unclear as prev BSpec revision
|
|
|
|
@ -4878,37 +4897,41 @@ static u8 icl_compute_dbuf_slices(enum pipe pipe, u8 active_pipes)
|
|
|
|
|
* still here - we will need it once those additional constraints
|
|
|
|
|
* pop up.
|
|
|
|
|
*/
|
|
|
|
|
return compute_dbuf_slices(pipe, active_pipes, icl_allowed_dbufs);
|
|
|
|
|
return compute_dbuf_slices(pipe, active_pipes, join_mbus,
|
|
|
|
|
icl_allowed_dbufs);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static u8 tgl_compute_dbuf_slices(enum pipe pipe, u8 active_pipes)
|
|
|
|
|
static u8 tgl_compute_dbuf_slices(enum pipe pipe, u8 active_pipes, bool join_mbus)
|
|
|
|
|
{
|
|
|
|
|
return compute_dbuf_slices(pipe, active_pipes, tgl_allowed_dbufs);
|
|
|
|
|
return compute_dbuf_slices(pipe, active_pipes, join_mbus,
|
|
|
|
|
tgl_allowed_dbufs);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static u32 adlp_compute_dbuf_slices(enum pipe pipe, u32 active_pipes)
|
|
|
|
|
static u8 adlp_compute_dbuf_slices(enum pipe pipe, u8 active_pipes, bool join_mbus)
|
|
|
|
|
{
|
|
|
|
|
return compute_dbuf_slices(pipe, active_pipes, adlp_allowed_dbufs);
|
|
|
|
|
return compute_dbuf_slices(pipe, active_pipes, join_mbus,
|
|
|
|
|
adlp_allowed_dbufs);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static u32 dg2_compute_dbuf_slices(enum pipe pipe, u32 active_pipes)
|
|
|
|
|
static u8 dg2_compute_dbuf_slices(enum pipe pipe, u8 active_pipes, bool join_mbus)
|
|
|
|
|
{
|
|
|
|
|
return compute_dbuf_slices(pipe, active_pipes, dg2_allowed_dbufs);
|
|
|
|
|
return compute_dbuf_slices(pipe, active_pipes, join_mbus,
|
|
|
|
|
dg2_allowed_dbufs);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static u8 skl_compute_dbuf_slices(struct intel_crtc *crtc, u8 active_pipes)
|
|
|
|
|
static u8 skl_compute_dbuf_slices(struct intel_crtc *crtc, u8 active_pipes, bool join_mbus)
|
|
|
|
|
{
|
|
|
|
|
struct drm_i915_private *dev_priv = to_i915(crtc->base.dev);
|
|
|
|
|
enum pipe pipe = crtc->pipe;
|
|
|
|
|
|
|
|
|
|
if (IS_DG2(dev_priv))
|
|
|
|
|
return dg2_compute_dbuf_slices(pipe, active_pipes);
|
|
|
|
|
return dg2_compute_dbuf_slices(pipe, active_pipes, join_mbus);
|
|
|
|
|
else if (IS_ALDERLAKE_P(dev_priv))
|
|
|
|
|
return adlp_compute_dbuf_slices(pipe, active_pipes);
|
|
|
|
|
return adlp_compute_dbuf_slices(pipe, active_pipes, join_mbus);
|
|
|
|
|
else if (DISPLAY_VER(dev_priv) == 12)
|
|
|
|
|
return tgl_compute_dbuf_slices(pipe, active_pipes);
|
|
|
|
|
return tgl_compute_dbuf_slices(pipe, active_pipes, join_mbus);
|
|
|
|
|
else if (DISPLAY_VER(dev_priv) == 11)
|
|
|
|
|
return icl_compute_dbuf_slices(pipe, active_pipes);
|
|
|
|
|
return icl_compute_dbuf_slices(pipe, active_pipes, join_mbus);
|
|
|
|
|
/*
|
|
|
|
|
* For anything else just return one slice yet.
|
|
|
|
|
* Should be extended for other platforms.
|
|
|
|
@ -6127,11 +6150,16 @@ skl_compute_ddb(struct intel_atomic_state *state)
|
|
|
|
|
return ret;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (IS_ALDERLAKE_P(dev_priv))
|
|
|
|
|
new_dbuf_state->joined_mbus =
|
|
|
|
|
adlp_check_mbus_joined(new_dbuf_state->active_pipes);
|
|
|
|
|
|
|
|
|
|
for_each_intel_crtc(&dev_priv->drm, crtc) {
|
|
|
|
|
enum pipe pipe = crtc->pipe;
|
|
|
|
|
|
|
|
|
|
new_dbuf_state->slices[pipe] =
|
|
|
|
|
skl_compute_dbuf_slices(crtc, new_dbuf_state->active_pipes);
|
|
|
|
|
skl_compute_dbuf_slices(crtc, new_dbuf_state->active_pipes,
|
|
|
|
|
new_dbuf_state->joined_mbus);
|
|
|
|
|
|
|
|
|
|
if (old_dbuf_state->slices[pipe] == new_dbuf_state->slices[pipe])
|
|
|
|
|
continue;
|
|
|
|
@ -6143,9 +6171,6 @@ skl_compute_ddb(struct intel_atomic_state *state)
|
|
|
|
|
|
|
|
|
|
new_dbuf_state->enabled_slices = intel_dbuf_enabled_slices(new_dbuf_state);
|
|
|
|
|
|
|
|
|
|
if (IS_ALDERLAKE_P(dev_priv))
|
|
|
|
|
new_dbuf_state->joined_mbus = adlp_check_mbus_joined(new_dbuf_state->active_pipes);
|
|
|
|
|
|
|
|
|
|
if (old_dbuf_state->enabled_slices != new_dbuf_state->enabled_slices ||
|
|
|
|
|
old_dbuf_state->joined_mbus != new_dbuf_state->joined_mbus) {
|
|
|
|
|
ret = intel_atomic_serialize_global_state(&new_dbuf_state->base);
|
|
|
|
@ -6626,6 +6651,7 @@ void skl_wm_get_hw_state(struct drm_i915_private *dev_priv)
|
|
|
|
|
enum pipe pipe = crtc->pipe;
|
|
|
|
|
unsigned int mbus_offset;
|
|
|
|
|
enum plane_id plane_id;
|
|
|
|
|
u8 slices;
|
|
|
|
|
|
|
|
|
|
skl_pipe_wm_get_hw_state(crtc, &crtc_state->wm.skl.optimal);
|
|
|
|
|
crtc_state->wm.skl.raw = crtc_state->wm.skl.optimal;
|
|
|
|
@ -6645,19 +6671,22 @@ void skl_wm_get_hw_state(struct drm_i915_private *dev_priv)
|
|
|
|
|
skl_ddb_entry_union(&dbuf_state->ddb[pipe], ddb_uv);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
dbuf_state->slices[pipe] =
|
|
|
|
|
skl_compute_dbuf_slices(crtc, dbuf_state->active_pipes);
|
|
|
|
|
|
|
|
|
|
dbuf_state->weight[pipe] = intel_crtc_ddb_weight(crtc_state);
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
|
* Used for checking overlaps, so we need absolute
|
|
|
|
|
* offsets instead of MBUS relative offsets.
|
|
|
|
|
*/
|
|
|
|
|
mbus_offset = mbus_ddb_offset(dev_priv, dbuf_state->slices[pipe]);
|
|
|
|
|
slices = skl_compute_dbuf_slices(crtc, dbuf_state->active_pipes,
|
|
|
|
|
dbuf_state->joined_mbus);
|
|
|
|
|
mbus_offset = mbus_ddb_offset(dev_priv, slices);
|
|
|
|
|
crtc_state->wm.skl.ddb.start = mbus_offset + dbuf_state->ddb[pipe].start;
|
|
|
|
|
crtc_state->wm.skl.ddb.end = mbus_offset + dbuf_state->ddb[pipe].end;
|
|
|
|
|
|
|
|
|
|
/* The slices actually used by the planes on the pipe */
|
|
|
|
|
dbuf_state->slices[pipe] =
|
|
|
|
|
skl_ddb_dbuf_slice_mask(dev_priv, &crtc_state->wm.skl.ddb);
|
|
|
|
|
|
|
|
|
|
drm_dbg_kms(&dev_priv->drm,
|
|
|
|
|
"[CRTC:%d:%s] dbuf slices 0x%x, ddb (%d - %d), active pipes 0x%x, mbus joined: %s\n",
|
|
|
|
|
crtc->base.base.id, crtc->base.name,
|
|
|
|
@ -6669,6 +6698,74 @@ void skl_wm_get_hw_state(struct drm_i915_private *dev_priv)
|
|
|
|
|
dbuf_state->enabled_slices = dev_priv->dbuf.enabled_slices;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static bool skl_dbuf_is_misconfigured(struct drm_i915_private *i915)
|
|
|
|
|
{
|
|
|
|
|
const struct intel_dbuf_state *dbuf_state =
|
|
|
|
|
to_intel_dbuf_state(i915->dbuf.obj.state);
|
|
|
|
|
struct skl_ddb_entry entries[I915_MAX_PIPES] = {};
|
|
|
|
|
struct intel_crtc *crtc;
|
|
|
|
|
|
|
|
|
|
for_each_intel_crtc(&i915->drm, crtc) {
|
|
|
|
|
const struct intel_crtc_state *crtc_state =
|
|
|
|
|
to_intel_crtc_state(crtc->base.state);
|
|
|
|
|
|
|
|
|
|
entries[crtc->pipe] = crtc_state->wm.skl.ddb;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
for_each_intel_crtc(&i915->drm, crtc) {
|
|
|
|
|
const struct intel_crtc_state *crtc_state =
|
|
|
|
|
to_intel_crtc_state(crtc->base.state);
|
|
|
|
|
u8 slices;
|
|
|
|
|
|
|
|
|
|
slices = skl_compute_dbuf_slices(crtc, dbuf_state->active_pipes,
|
|
|
|
|
dbuf_state->joined_mbus);
|
|
|
|
|
if (dbuf_state->slices[crtc->pipe] & ~slices)
|
|
|
|
|
return true;
|
|
|
|
|
|
|
|
|
|
if (skl_ddb_allocation_overlaps(&crtc_state->wm.skl.ddb, entries,
|
|
|
|
|
I915_MAX_PIPES, crtc->pipe))
|
|
|
|
|
return true;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void skl_wm_sanitize(struct drm_i915_private *i915)
|
|
|
|
|
{
|
|
|
|
|
struct intel_crtc *crtc;
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
|
* On TGL/RKL (at least) the BIOS likes to assign the planes
|
|
|
|
|
* to the wrong DBUF slices. This will cause an infinite loop
|
|
|
|
|
* in skl_commit_modeset_enables() as it can't find a way to
|
|
|
|
|
* transition between the old bogus DBUF layout to the new
|
|
|
|
|
* proper DBUF layout without DBUF allocation overlaps between
|
|
|
|
|
* the planes (which cannot be allowed or else the hardware
|
|
|
|
|
* may hang). If we detect a bogus DBUF layout just turn off
|
|
|
|
|
* all the planes so that skl_commit_modeset_enables() can
|
|
|
|
|
* simply ignore them.
|
|
|
|
|
*/
|
|
|
|
|
if (!skl_dbuf_is_misconfigured(i915))
|
|
|
|
|
return;
|
|
|
|
|
|
|
|
|
|
drm_dbg_kms(&i915->drm, "BIOS has misprogrammed the DBUF, disabling all planes\n");
|
|
|
|
|
|
|
|
|
|
for_each_intel_crtc(&i915->drm, crtc) {
|
|
|
|
|
struct intel_plane *plane = to_intel_plane(crtc->base.primary);
|
|
|
|
|
const struct intel_plane_state *plane_state =
|
|
|
|
|
to_intel_plane_state(plane->base.state);
|
|
|
|
|
struct intel_crtc_state *crtc_state =
|
|
|
|
|
to_intel_crtc_state(crtc->base.state);
|
|
|
|
|
|
|
|
|
|
if (plane_state->uapi.visible)
|
|
|
|
|
intel_plane_disable_noatomic(crtc, plane);
|
|
|
|
|
|
|
|
|
|
drm_WARN_ON(&i915->drm, crtc_state->active_planes != 0);
|
|
|
|
|
|
|
|
|
|
memset(&crtc_state->wm.skl.ddb, 0, sizeof(crtc_state->wm.skl.ddb));
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static void ilk_pipe_wm_get_hw_state(struct intel_crtc *crtc)
|
|
|
|
|
{
|
|
|
|
|
struct drm_device *dev = crtc->base.dev;
|
|
|
|
|