diff options
Diffstat (limited to 'drivers/gpu/drm/i915/display/intel_vdsc.c')
-rw-r--r-- | drivers/gpu/drm/i915/display/intel_vdsc.c | 161 |
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; +} |