summaryrefslogtreecommitdiff
path: root/drivers/gpu/drm/i915/display/intel_vdsc.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/gpu/drm/i915/display/intel_vdsc.c')
-rw-r--r--drivers/gpu/drm/i915/display/intel_vdsc.c161
1 files changed, 116 insertions, 45 deletions
diff --git a/drivers/gpu/drm/i915/display/intel_vdsc.c b/drivers/gpu/drm/i915/display/intel_vdsc.c
index 17d6572f9d0a..b355c479eda3 100644
--- a/drivers/gpu/drm/i915/display/intel_vdsc.c
+++ b/drivers/gpu/drm/i915/display/intel_vdsc.c
@@ -8,12 +8,13 @@
#include <linux/limits.h>
#include <drm/display/drm_dsc_helper.h>
+#include <drm/drm_fixed.h>
#include "i915_drv.h"
-#include "i915_reg.h"
#include "intel_crtc.h"
#include "intel_de.h"
#include "intel_display_types.h"
+#include "intel_dp.h"
#include "intel_dsi.h"
#include "intel_qp_tables.h"
#include "intel_vdsc.h"
@@ -77,7 +78,7 @@ intel_vdsc_set_min_max_qp(struct drm_dsc_config *vdsc_cfg, int buf,
static void
calculate_rc_params(struct drm_dsc_config *vdsc_cfg)
{
- int bpp = to_bpp_int(vdsc_cfg->bits_per_pixel);
+ int bpp = fxp_q4_to_int(vdsc_cfg->bits_per_pixel);
int bpc = vdsc_cfg->bits_per_component;
int qp_bpc_modifier = (bpc - 8) * 2;
int uncompressed_bpg_rate;
@@ -185,7 +186,7 @@ calculate_rc_params(struct drm_dsc_config *vdsc_cfg)
}
} else {
/* fractional bpp part * 10000 (for precision up to 4 decimal places) */
- int fractional_bits = to_bpp_frac(vdsc_cfg->bits_per_pixel);
+ int fractional_bits = fxp_q4_to_frac(vdsc_cfg->bits_per_pixel);
static const s8 ofs_und6[] = {
0, -2, -2, -4, -6, -6, -8, -8, -8, -10, -10, -12, -12, -12, -12
@@ -264,7 +265,7 @@ int intel_dsc_compute_params(struct intel_crtc_state *pipe_config)
struct intel_crtc *crtc = to_intel_crtc(pipe_config->uapi.crtc);
struct drm_i915_private *dev_priv = to_i915(crtc->base.dev);
struct drm_dsc_config *vdsc_cfg = &pipe_config->dsc.config;
- u16 compressed_bpp = to_bpp_int(pipe_config->dsc.compressed_bpp_x16);
+ u16 compressed_bpp = fxp_q4_to_int(pipe_config->dsc.compressed_bpp_x16);
int err;
int ret;
@@ -306,6 +307,12 @@ int intel_dsc_compute_params(struct intel_crtc_state *pipe_config)
vdsc_cfg->bits_per_component = pipe_config->pipe_bpp / 3;
+ if (vdsc_cfg->bits_per_component < 8) {
+ drm_dbg_kms(&dev_priv->drm, "DSC bpc requirements not met bpc: %d\n",
+ vdsc_cfg->bits_per_component);
+ return -EINVAL;
+ }
+
drm_dsc_set_rc_buf_thresh(vdsc_cfg);
/*
@@ -373,15 +380,15 @@ intel_dsc_power_domain(struct intel_crtc *crtc, enum transcoder cpu_transcoder)
static int intel_dsc_get_vdsc_per_pipe(const struct intel_crtc_state *crtc_state)
{
- return crtc_state->dsc.dsc_split ? 2 : 1;
+ return crtc_state->dsc.num_streams;
}
int intel_dsc_get_num_vdsc_instances(const struct intel_crtc_state *crtc_state)
{
int num_vdsc_instances = intel_dsc_get_vdsc_per_pipe(crtc_state);
+ int num_joined_pipes = intel_crtc_num_joined_pipes(crtc_state);
- if (crtc_state->bigjoiner_pipes)
- num_vdsc_instances *= 2;
+ num_vdsc_instances *= num_joined_pipes;
return num_vdsc_instances;
}
@@ -396,8 +403,10 @@ static void intel_dsc_get_pps_reg(const struct intel_crtc_state *crtc_state, int
pipe_dsc = is_pipe_dsc(crtc, cpu_transcoder);
- if (dsc_reg_num >= 3)
+ if (dsc_reg_num >= 4)
MISSING_CASE(dsc_reg_num);
+ if (dsc_reg_num >= 3)
+ dsc_reg[2] = BMG_DSC2_PPS(pipe, pps);
if (dsc_reg_num >= 2)
dsc_reg[1] = pipe_dsc ? ICL_DSC1_PPS(pipe, pps) : DSCC_PPS(pps);
if (dsc_reg_num >= 1)
@@ -409,7 +418,7 @@ static void intel_dsc_pps_write(const struct intel_crtc_state *crtc_state,
{
struct intel_crtc *crtc = to_intel_crtc(crtc_state->uapi.crtc);
struct drm_i915_private *i915 = to_i915(crtc->base.dev);
- i915_reg_t dsc_reg[2];
+ i915_reg_t dsc_reg[3];
int i, vdsc_per_pipe, dsc_reg_num;
vdsc_per_pipe = intel_dsc_get_vdsc_per_pipe(crtc_state);
@@ -457,36 +466,30 @@ static void intel_dsc_pps_configure(const struct intel_crtc_state *crtc_state)
pps_val |= DSC_PPS0_422_ENABLE;
if (vdsc_cfg->vbr_enable)
pps_val |= DSC_PPS0_VBR_ENABLE;
- drm_dbg_kms(&dev_priv->drm, "PPS0 = 0x%08x\n", pps_val);
intel_dsc_pps_write(crtc_state, 0, pps_val);
/* PPS 1 */
pps_val = DSC_PPS1_BPP(vdsc_cfg->bits_per_pixel);
- drm_dbg_kms(&dev_priv->drm, "PPS1 = 0x%08x\n", pps_val);
intel_dsc_pps_write(crtc_state, 1, pps_val);
/* PPS 2 */
pps_val = DSC_PPS2_PIC_HEIGHT(vdsc_cfg->pic_height) |
DSC_PPS2_PIC_WIDTH(vdsc_cfg->pic_width / num_vdsc_instances);
- drm_dbg_kms(&dev_priv->drm, "PPS2 = 0x%08x\n", pps_val);
intel_dsc_pps_write(crtc_state, 2, pps_val);
/* PPS 3 */
pps_val = DSC_PPS3_SLICE_HEIGHT(vdsc_cfg->slice_height) |
DSC_PPS3_SLICE_WIDTH(vdsc_cfg->slice_width);
- drm_dbg_kms(&dev_priv->drm, "PPS3 = 0x%08x\n", pps_val);
intel_dsc_pps_write(crtc_state, 3, pps_val);
/* PPS 4 */
pps_val = DSC_PPS4_INITIAL_XMIT_DELAY(vdsc_cfg->initial_xmit_delay) |
DSC_PPS4_INITIAL_DEC_DELAY(vdsc_cfg->initial_dec_delay);
- drm_dbg_kms(&dev_priv->drm, "PPS4 = 0x%08x\n", pps_val);
intel_dsc_pps_write(crtc_state, 4, pps_val);
/* PPS 5 */
pps_val = DSC_PPS5_SCALE_INC_INT(vdsc_cfg->scale_increment_interval) |
DSC_PPS5_SCALE_DEC_INT(vdsc_cfg->scale_decrement_interval);
- drm_dbg_kms(&dev_priv->drm, "PPS5 = 0x%08x\n", pps_val);
intel_dsc_pps_write(crtc_state, 5, pps_val);
/* PPS 6 */
@@ -494,25 +497,21 @@ static void intel_dsc_pps_configure(const struct intel_crtc_state *crtc_state)
DSC_PPS6_FIRST_LINE_BPG_OFFSET(vdsc_cfg->first_line_bpg_offset) |
DSC_PPS6_FLATNESS_MIN_QP(vdsc_cfg->flatness_min_qp) |
DSC_PPS6_FLATNESS_MAX_QP(vdsc_cfg->flatness_max_qp);
- drm_dbg_kms(&dev_priv->drm, "PPS6 = 0x%08x\n", pps_val);
intel_dsc_pps_write(crtc_state, 6, pps_val);
/* PPS 7 */
pps_val = DSC_PPS7_SLICE_BPG_OFFSET(vdsc_cfg->slice_bpg_offset) |
DSC_PPS7_NFL_BPG_OFFSET(vdsc_cfg->nfl_bpg_offset);
- drm_dbg_kms(&dev_priv->drm, "PPS7 = 0x%08x\n", pps_val);
intel_dsc_pps_write(crtc_state, 7, pps_val);
/* PPS 8 */
pps_val = DSC_PPS8_FINAL_OFFSET(vdsc_cfg->final_offset) |
DSC_PPS8_INITIAL_OFFSET(vdsc_cfg->initial_offset);
- drm_dbg_kms(&dev_priv->drm, "PPS8 = 0x%08x\n", pps_val);
intel_dsc_pps_write(crtc_state, 8, pps_val);
/* PPS 9 */
pps_val = DSC_PPS9_RC_MODEL_SIZE(vdsc_cfg->rc_model_size) |
DSC_PPS9_RC_EDGE_FACTOR(DSC_RC_EDGE_FACTOR_CONST);
- drm_dbg_kms(&dev_priv->drm, "PPS9 = 0x%08x\n", pps_val);
intel_dsc_pps_write(crtc_state, 9, pps_val);
/* PPS 10 */
@@ -520,7 +519,6 @@ static void intel_dsc_pps_configure(const struct intel_crtc_state *crtc_state)
DSC_PPS10_RC_QUANT_INC_LIMIT1(vdsc_cfg->rc_quant_incr_limit1) |
DSC_PPS10_RC_TARGET_OFF_HIGH(DSC_RC_TGT_OFFSET_HI_CONST) |
DSC_PPS10_RC_TARGET_OFF_LOW(DSC_RC_TGT_OFFSET_LO_CONST);
- drm_dbg_kms(&dev_priv->drm, "PPS10 = 0x%08x\n", pps_val);
intel_dsc_pps_write(crtc_state, 10, pps_val);
/* PPS 16 */
@@ -529,31 +527,25 @@ static void intel_dsc_pps_configure(const struct intel_crtc_state *crtc_state)
vdsc_cfg->slice_width) |
DSC_PPS16_SLICE_ROW_PER_FRAME(vdsc_cfg->pic_height /
vdsc_cfg->slice_height);
- drm_dbg_kms(&dev_priv->drm, "PPS16 = 0x%08x\n", pps_val);
intel_dsc_pps_write(crtc_state, 16, pps_val);
if (DISPLAY_VER(dev_priv) >= 14) {
/* PPS 17 */
pps_val = DSC_PPS17_SL_BPG_OFFSET(vdsc_cfg->second_line_bpg_offset);
- drm_dbg_kms(&dev_priv->drm, "PPS17 = 0x%08x\n", pps_val);
intel_dsc_pps_write(crtc_state, 17, pps_val);
/* PPS 18 */
pps_val = DSC_PPS18_NSL_BPG_OFFSET(vdsc_cfg->nsl_bpg_offset) |
DSC_PPS18_SL_OFFSET_ADJ(vdsc_cfg->second_line_offset_adj);
- drm_dbg_kms(&dev_priv->drm, "PPS18 = 0x%08x\n", pps_val);
intel_dsc_pps_write(crtc_state, 18, pps_val);
}
/* Populate the RC_BUF_THRESH registers */
memset(rc_buf_thresh_dword, 0, sizeof(rc_buf_thresh_dword));
- for (i = 0; i < DSC_NUM_BUF_RANGES - 1; i++) {
+ for (i = 0; i < DSC_NUM_BUF_RANGES - 1; i++)
rc_buf_thresh_dword[i / 4] |=
(u32)(vdsc_cfg->rc_buf_thresh[i] <<
BITS_PER_BYTE * (i % 4));
- drm_dbg_kms(&dev_priv->drm, "RC_BUF_THRESH_%d = 0x%08x\n", i,
- rc_buf_thresh_dword[i / 4]);
- }
if (!is_pipe_dsc(crtc, cpu_transcoder)) {
intel_de_write(dev_priv, DSCA_RC_BUF_THRESH_0,
rc_buf_thresh_dword[0]);
@@ -600,7 +592,7 @@ static void intel_dsc_pps_configure(const struct intel_crtc_state *crtc_state)
/* Populate the RC_RANGE_PARAMETERS registers */
memset(rc_range_params_dword, 0, sizeof(rc_range_params_dword));
- for (i = 0; i < DSC_NUM_BUF_RANGES; i++) {
+ for (i = 0; i < DSC_NUM_BUF_RANGES; i++)
rc_range_params_dword[i / 2] |=
(u32)(((vdsc_cfg->rc_range_params[i].range_bpg_offset <<
RC_BPG_OFFSET_SHIFT) |
@@ -608,9 +600,6 @@ static void intel_dsc_pps_configure(const struct intel_crtc_state *crtc_state)
RC_MAX_QP_SHIFT) |
(vdsc_cfg->rc_range_params[i].range_min_qp <<
RC_MIN_QP_SHIFT)) << 16 * (i % 2));
- drm_dbg_kms(&dev_priv->drm, "RC_RANGE_PARAM_%d = 0x%08x\n", i,
- rc_range_params_dword[i / 2]);
- }
if (!is_pipe_dsc(crtc, cpu_transcoder)) {
intel_de_write(dev_priv, DSCA_RC_RANGE_PARAMETERS_0,
rc_range_params_dword[0]);
@@ -761,11 +750,11 @@ void intel_uncompressed_joiner_enable(const struct intel_crtc_state *crtc_state)
struct drm_i915_private *dev_priv = to_i915(crtc->base.dev);
u32 dss_ctl1_val = 0;
- if (crtc_state->bigjoiner_pipes && !crtc_state->dsc.compression_enable) {
- if (intel_crtc_is_bigjoiner_slave(crtc_state))
- dss_ctl1_val |= UNCOMPRESSED_JOINER_SLAVE;
+ if (crtc_state->joiner_pipes && !crtc_state->dsc.compression_enable) {
+ if (intel_crtc_is_bigjoiner_secondary(crtc_state))
+ dss_ctl1_val |= UNCOMPRESSED_JOINER_SECONDARY;
else
- dss_ctl1_val |= UNCOMPRESSED_JOINER_MASTER;
+ dss_ctl1_val |= UNCOMPRESSED_JOINER_PRIMARY;
intel_de_write(dev_priv, dss_ctl1_reg(crtc, crtc_state->cpu_transcoder), dss_ctl1_val);
}
@@ -784,15 +773,28 @@ void intel_dsc_enable(const struct intel_crtc_state *crtc_state)
intel_dsc_pps_configure(crtc_state);
- dss_ctl2_val |= LEFT_BRANCH_VDSC_ENABLE;
+ dss_ctl2_val |= VDSC0_ENABLE;
if (vdsc_instances_per_pipe > 1) {
- dss_ctl2_val |= RIGHT_BRANCH_VDSC_ENABLE;
+ dss_ctl2_val |= VDSC1_ENABLE;
dss_ctl1_val |= JOINER_ENABLE;
}
- if (crtc_state->bigjoiner_pipes) {
+
+ if (vdsc_instances_per_pipe > 2) {
+ dss_ctl2_val |= VDSC2_ENABLE;
+ dss_ctl2_val |= SMALL_JOINER_CONFIG_3_ENGINES;
+ }
+
+ if (crtc_state->joiner_pipes) {
+ if (intel_crtc_ultrajoiner_enable_needed(crtc_state))
+ dss_ctl1_val |= ULTRA_JOINER_ENABLE;
+
+ if (intel_crtc_is_ultrajoiner_primary(crtc_state))
+ dss_ctl1_val |= PRIMARY_ULTRA_JOINER_ENABLE;
+
dss_ctl1_val |= BIG_JOINER_ENABLE;
- if (!intel_crtc_is_bigjoiner_slave(crtc_state))
- dss_ctl1_val |= MASTER_BIG_JOINER_ENABLE;
+
+ if (intel_crtc_is_bigjoiner_primary(crtc_state))
+ dss_ctl1_val |= PRIMARY_BIG_JOINER_ENABLE;
}
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);
@@ -805,7 +807,7 @@ void intel_dsc_disable(const struct intel_crtc_state *old_crtc_state)
/* Disable only if either of them is enabled */
if (old_crtc_state->dsc.compression_enable ||
- old_crtc_state->bigjoiner_pipes) {
+ 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);
}
@@ -816,7 +818,7 @@ static u32 intel_dsc_pps_read(struct intel_crtc_state *crtc_state, int pps,
{
struct intel_crtc *crtc = to_intel_crtc(crtc_state->uapi.crtc);
struct drm_i915_private *i915 = to_i915(crtc->base.dev);
- i915_reg_t dsc_reg[2];
+ i915_reg_t dsc_reg[3];
int i, vdsc_per_pipe, dsc_reg_num;
u32 val;
@@ -979,14 +981,83 @@ 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));
- crtc_state->dsc.compression_enable = dss_ctl2 & LEFT_BRANCH_VDSC_ENABLE;
+ crtc_state->dsc.compression_enable = dss_ctl2 & VDSC0_ENABLE;
if (!crtc_state->dsc.compression_enable)
goto out;
- crtc_state->dsc.dsc_split = (dss_ctl2 & RIGHT_BRANCH_VDSC_ENABLE) &&
- (dss_ctl1 & JOINER_ENABLE);
+ if (dss_ctl1 & JOINER_ENABLE && dss_ctl2 & (VDSC2_ENABLE | SMALL_JOINER_CONFIG_3_ENGINES))
+ crtc_state->dsc.num_streams = 3;
+ else if (dss_ctl1 & JOINER_ENABLE && dss_ctl2 & VDSC1_ENABLE)
+ crtc_state->dsc.num_streams = 2;
+ else
+ crtc_state->dsc.num_streams = 1;
intel_dsc_get_pps_config(crtc_state);
out:
intel_display_power_put(dev_priv, power_domain, wakeref);
}
+
+static void intel_vdsc_dump_state(struct drm_printer *p, int indent,
+ const struct intel_crtc_state *crtc_state)
+{
+ drm_printf_indent(p, indent,
+ "dsc-dss: compressed-bpp:" FXP_Q4_FMT ", slice-count: %d, num_streams: %d\n",
+ FXP_Q4_ARGS(crtc_state->dsc.compressed_bpp_x16),
+ crtc_state->dsc.slice_count,
+ crtc_state->dsc.num_streams);
+}
+
+void intel_vdsc_state_dump(struct drm_printer *p, int indent,
+ const struct intel_crtc_state *crtc_state)
+{
+ if (!crtc_state->dsc.compression_enable)
+ return;
+
+ intel_vdsc_dump_state(p, indent, crtc_state);
+ drm_dsc_dump_config(p, indent, &crtc_state->dsc.config);
+}
+
+int intel_vdsc_min_cdclk(const struct intel_crtc_state *crtc_state)
+{
+ struct intel_crtc *crtc = to_intel_crtc(crtc_state->uapi.crtc);
+ struct intel_display *display = to_intel_display(crtc);
+ int num_vdsc_instances = intel_dsc_get_num_vdsc_instances(crtc_state);
+ int min_cdclk;
+
+ if (!crtc_state->dsc.compression_enable)
+ return 0;
+
+ /*
+ * When we decide to use only one VDSC engine, since
+ * each VDSC operates with 1 ppc throughput, pixel clock
+ * cannot be higher than the VDSC clock (cdclk)
+ * If there 2 VDSC engines, then pixel clock can't be higher than
+ * VDSC clock(cdclk) * 2 and so on.
+ */
+ min_cdclk = DIV_ROUND_UP(crtc_state->pixel_rate, num_vdsc_instances);
+
+ if (crtc_state->joiner_pipes) {
+ int pixel_clock = intel_dp_mode_to_fec_clock(crtc_state->hw.adjusted_mode.clock);
+
+ /*
+ * According to Bigjoiner bw check:
+ * compressed_bpp <= PPC * CDCLK * Big joiner Interface bits / Pixel clock
+ *
+ * We have already computed compressed_bpp, so now compute the min CDCLK that
+ * is required to support this compressed_bpp.
+ *
+ * => CDCLK >= compressed_bpp * Pixel clock / (PPC * Bigjoiner Interface bits)
+ *
+ * Since PPC = 2 with bigjoiner
+ * => CDCLK >= compressed_bpp * Pixel clock / 2 * Bigjoiner Interface bits
+ */
+ int bigjoiner_interface_bits = DISPLAY_VER(display) >= 14 ? 36 : 24;
+ int min_cdclk_bj =
+ (fxp_q4_to_int_roundup(crtc_state->dsc.compressed_bpp_x16) *
+ pixel_clock) / (2 * bigjoiner_interface_bits);
+
+ min_cdclk = max(min_cdclk, min_cdclk_bj);
+ }
+
+ return min_cdclk;
+}