[PATCH 6/8] drm/i915/display: Add DSC pixel replication
Ankit Nautiyal
ankit.k.nautiyal at intel.com
Tue Jun 18 05:50:02 UTC 2024
With 3 VDSC engines and Ultrajoiner, we may encounter a situation where
hdisplay is not a multiple of slice count. In this case we need to add
extra pixels to the last slice to distribute pixels evenly across
slices.
Add member to store DSC pixel replication when hdisplay is not divisible
by slice_width. Fill DSS_CTL3 register with the pixel replication count.
TODO:
1. Scaler:
If the DSC is enabled and pixel replication is occurring, then the
scaler window size and position must fit within the pipe active size
plus the pixel replication.
2. PIPE_SRC:
Horizontal Src size must always be programmed to the same value as the
Horizontal Active except when panel fitting is enabled or DSC pixel
replication is enabled.
Signed-off-by: Ankit Nautiyal <ankit.k.nautiyal at intel.com>
---
drivers/gpu/drm/i915/display/intel_display.c | 1 +
.../drm/i915/display/intel_display_types.h | 1 +
drivers/gpu/drm/i915/display/intel_vdsc.c | 21 ++++++++++++++++++-
.../gpu/drm/i915/display/intel_vdsc_regs.h | 8 +++++++
4 files changed, 30 insertions(+), 1 deletion(-)
diff --git a/drivers/gpu/drm/i915/display/intel_display.c b/drivers/gpu/drm/i915/display/intel_display.c
index cbd15411e39c..5c734bac38e1 100644
--- a/drivers/gpu/drm/i915/display/intel_display.c
+++ b/drivers/gpu/drm/i915/display/intel_display.c
@@ -5461,6 +5461,7 @@ intel_pipe_config_compare(const struct intel_crtc_state *current_config,
PIPE_CONF_CHECK_BOOL(dsc.compression_enable);
PIPE_CONF_CHECK_I(dsc.dsc_split);
PIPE_CONF_CHECK_I(dsc.compressed_bpp_x16);
+ PIPE_CONF_CHECK_I(dsc.pixel_replication_count);
PIPE_CONF_CHECK_BOOL(splitter.enable);
PIPE_CONF_CHECK_I(splitter.link_count);
diff --git a/drivers/gpu/drm/i915/display/intel_display_types.h b/drivers/gpu/drm/i915/display/intel_display_types.h
index 8aa0398391fd..fd40ef4d47f7 100644
--- a/drivers/gpu/drm/i915/display/intel_display_types.h
+++ b/drivers/gpu/drm/i915/display/intel_display_types.h
@@ -1366,6 +1366,7 @@ struct intel_crtc_state {
/* Compressed Bpp in U6.4 format (first 4 bits for fractional part) */
u16 compressed_bpp_x16;
u8 slice_count;
+ int pixel_replication_count;
struct drm_dsc_config config;
} dsc;
diff --git a/drivers/gpu/drm/i915/display/intel_vdsc.c b/drivers/gpu/drm/i915/display/intel_vdsc.c
index 03a15f2360c6..a8c90072edd7 100644
--- a/drivers/gpu/drm/i915/display/intel_vdsc.c
+++ b/drivers/gpu/drm/i915/display/intel_vdsc.c
@@ -787,6 +787,7 @@ void intel_dsc_enable(const struct intel_crtc_state *crtc_state)
struct drm_i915_private *dev_priv = to_i915(crtc->base.dev);
u32 dss_ctl1_val = 0;
u32 dss_ctl2_val = 0;
+ u32 dss_ctl3_val = 0;
int vdsc_instances_per_pipe = intel_dsc_get_vdsc_per_pipe(crtc_state);
if (!crtc_state->dsc.compression_enable)
@@ -810,8 +811,16 @@ void intel_dsc_enable(const struct intel_crtc_state *crtc_state)
if (!intel_crtc_is_joiner_secondary(crtc_state))
dss_ctl1_val |= PRIMARY_BIG_JOINER_ENABLE;
}
+
+ if (crtc_state->dsc.pixel_replication_count)
+ dss_ctl3_val = DSC_PIXEL_REPLICATION(crtc_state->dsc.pixel_replication_count);
+
intel_de_write(dev_priv, dss_ctl1_reg(crtc, crtc_state->cpu_transcoder), dss_ctl1_val);
intel_de_write(dev_priv, dss_ctl2_reg(crtc, crtc_state->cpu_transcoder), dss_ctl2_val);
+
+ if (IS_BATTLEMAGE(dev_priv) && dss_ctl3_val)
+ intel_de_write(dev_priv,
+ BMG_PIPE_DSS_CTL3(crtc_state->cpu_transcoder), dss_ctl3_val);
}
void intel_dsc_disable(const struct intel_crtc_state *old_crtc_state)
@@ -824,6 +833,9 @@ void intel_dsc_disable(const struct intel_crtc_state *old_crtc_state)
old_crtc_state->joiner_pipes) {
intel_de_write(dev_priv, dss_ctl1_reg(crtc, old_crtc_state->cpu_transcoder), 0);
intel_de_write(dev_priv, dss_ctl2_reg(crtc, old_crtc_state->cpu_transcoder), 0);
+
+ if (IS_BATTLEMAGE(dev_priv))
+ intel_de_write(dev_priv, BMG_PIPE_DSS_CTL3(old_crtc_state->cpu_transcoder), 0);
}
}
@@ -981,7 +993,7 @@ void intel_dsc_get_config(struct intel_crtc_state *crtc_state)
enum transcoder cpu_transcoder = crtc_state->cpu_transcoder;
enum intel_display_power_domain power_domain;
intel_wakeref_t wakeref;
- u32 dss_ctl1, dss_ctl2;
+ u32 dss_ctl1, dss_ctl2, dss_ctl3;
if (!intel_dsc_source_support(crtc_state))
return;
@@ -995,6 +1007,9 @@ void intel_dsc_get_config(struct intel_crtc_state *crtc_state)
dss_ctl1 = intel_de_read(dev_priv, dss_ctl1_reg(crtc, cpu_transcoder));
dss_ctl2 = intel_de_read(dev_priv, dss_ctl2_reg(crtc, cpu_transcoder));
+ if (IS_BATTLEMAGE(dev_priv))
+ dss_ctl3 = intel_de_read(dev_priv, BMG_PIPE_DSS_CTL3(crtc_state->cpu_transcoder));
+
crtc_state->dsc.compression_enable = dss_ctl2 & VDSC0_ENABLE;
if (!crtc_state->dsc.compression_enable)
goto out;
@@ -1009,6 +1024,10 @@ void intel_dsc_get_config(struct intel_crtc_state *crtc_state)
crtc_state->dsc.dsc_split = DSC_SPLIT_DISABLED;
}
+ if (dss_ctl3 & DSC_PIXEL_REPLICATION_MASK)
+ crtc_state->dsc.pixel_replication_count =
+ dss_ctl3 & DSC_PIXEL_REPLICATION_MASK;
+
intel_dsc_get_pps_config(crtc_state);
out:
intel_display_power_put(dev_priv, power_domain, wakeref);
diff --git a/drivers/gpu/drm/i915/display/intel_vdsc_regs.h b/drivers/gpu/drm/i915/display/intel_vdsc_regs.h
index 92ea301b6f14..c3120bf71416 100644
--- a/drivers/gpu/drm/i915/display/intel_vdsc_regs.h
+++ b/drivers/gpu/drm/i915/display/intel_vdsc_regs.h
@@ -50,6 +50,14 @@
_ICL_PIPE_DSS_CTL2_PB, \
_ICL_PIPE_DSS_CTL2_PC)
+#define _BMG_PIPE_DSS_CTL3_PB 0x782F0
+#define _BMG_PIPE_DSS_CTL3_PC 0x784F0
+#define BMG_PIPE_DSS_CTL3(pipe) _MMIO_PIPE((pipe) - PIPE_B, \
+ _BMG_PIPE_DSS_CTL3_PB, \
+ _BMG_PIPE_DSS_CTL3_PC)
+#define DSC_PIXEL_REPLICATION_MASK REG_GENMASK(15, 0)
+#define DSC_PIXEL_REPLICATION(count) ((count) << 0)
+
/* Icelake Display Stream Compression Registers */
#define DSCA_PICTURE_PARAMETER_SET_0 _MMIO(0x6B200)
#define DSCC_PICTURE_PARAMETER_SET_0 _MMIO(0x6BA00)
--
2.40.1
More information about the Intel-gfx-trybot
mailing list