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.c325
1 files changed, 189 insertions, 136 deletions
diff --git a/drivers/gpu/drm/i915/display/intel_vdsc.c b/drivers/gpu/drm/i915/display/intel_vdsc.c
index 40525f5c4c42..3ed64c17bdff 100644
--- a/drivers/gpu/drm/i915/display/intel_vdsc.c
+++ b/drivers/gpu/drm/i915/display/intel_vdsc.c
@@ -10,10 +10,11 @@
#include <drm/display/drm_dsc_helper.h>
#include <drm/drm_fixed.h>
-#include "i915_drv.h"
+#include "i915_utils.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"
@@ -21,14 +22,13 @@
bool intel_dsc_source_support(const struct intel_crtc_state *crtc_state)
{
- const struct intel_crtc *crtc = to_intel_crtc(crtc_state->uapi.crtc);
- struct drm_i915_private *i915 = to_i915(crtc->base.dev);
+ struct intel_display *display = to_intel_display(crtc_state);
enum transcoder cpu_transcoder = crtc_state->cpu_transcoder;
- if (!HAS_DSC(i915))
+ if (!HAS_DSC(display))
return false;
- if (DISPLAY_VER(i915) == 11 && cpu_transcoder == TRANSCODER_A)
+ if (DISPLAY_VER(display) == 11 && cpu_transcoder == TRANSCODER_A)
return false;
return true;
@@ -36,9 +36,9 @@ bool intel_dsc_source_support(const struct intel_crtc_state *crtc_state)
static bool is_pipe_dsc(struct intel_crtc *crtc, enum transcoder cpu_transcoder)
{
- struct drm_i915_private *i915 = to_i915(crtc->base.dev);
+ struct intel_display *display = to_intel_display(crtc);
- if (DISPLAY_VER(i915) >= 12)
+ if (DISPLAY_VER(display) >= 12)
return true;
if (cpu_transcoder == TRANSCODER_EDP ||
@@ -47,7 +47,7 @@ static bool is_pipe_dsc(struct intel_crtc *crtc, enum transcoder cpu_transcoder)
return false;
/* There's no pipe A DSC engine on ICL */
- drm_WARN_ON(&i915->drm, crtc->pipe == PIPE_A);
+ drm_WARN_ON(display->drm, crtc->pipe == PIPE_A);
return true;
}
@@ -65,6 +65,13 @@ intel_vdsc_set_min_max_qp(struct drm_dsc_config *vdsc_cfg, int buf,
intel_lookup_range_max_qp(bpc, buf, bpp, vdsc_cfg->native_420);
}
+static int
+get_range_bpg_offset(int bpp_low, int offset_low, int bpp_high, int offset_high, int bpp)
+{
+ return offset_low + DIV_ROUND_UP((offset_high - offset_low) * (bpp - bpp_low),
+ (bpp_low - bpp_high));
+}
+
/*
* We are using the method provided in DSC 1.2a C-Model in codec_main.c
* Above method use a common formula to derive values for any combination of DSC
@@ -82,7 +89,7 @@ calculate_rc_params(struct drm_dsc_config *vdsc_cfg)
int qp_bpc_modifier = (bpc - 8) * 2;
int uncompressed_bpg_rate;
int first_line_bpg_offset;
- u32 res, buf_i, bpp_i;
+ u32 buf_i, bpp_i;
if (vdsc_cfg->slice_height >= 8)
first_line_bpg_offset =
@@ -98,7 +105,7 @@ calculate_rc_params(struct drm_dsc_config *vdsc_cfg)
* According to DSC 1.2 spec in Section 4.1 if native_420 is set:
* -second_line_bpg_offset is 12 in general and equal to 2*(slice_height-1) if slice
* height < 8.
- * -second_line_offset_adj is 512 as shown by emperical values to yield best chroma
+ * -second_line_offset_adj is 512 as shown by empirical values to yield best chroma
* preservation in second line.
* -nsl_bpg_offset is calculated as second_line_offset/slice_height -1 then rounded
* up to 16 fractional bits, we left shift second line offset by 11 to preserve 11
@@ -116,7 +123,6 @@ calculate_rc_params(struct drm_dsc_config *vdsc_cfg)
vdsc_cfg->slice_height - 1);
}
- /* Our hw supports only 444 modes as of today */
if (bpp >= 12)
vdsc_cfg->initial_offset = 2048;
else if (bpp >= 10)
@@ -162,23 +168,19 @@ calculate_rc_params(struct drm_dsc_config *vdsc_cfg)
intel_vdsc_set_min_max_qp(vdsc_cfg, buf_i, bpp_i);
/* Calculate range_bpg_offset */
- if (bpp <= 8) {
+ if (bpp <= 8)
range_bpg_offset = ofs_und4[buf_i];
- } else if (bpp <= 10) {
- res = DIV_ROUND_UP(((bpp - 8) *
- (ofs_und5[buf_i] - ofs_und4[buf_i])), 2);
- range_bpg_offset = ofs_und4[buf_i] + res;
- } else if (bpp <= 12) {
- res = DIV_ROUND_UP(((bpp - 10) *
- (ofs_und6[buf_i] - ofs_und5[buf_i])), 2);
- range_bpg_offset = ofs_und5[buf_i] + res;
- } else if (bpp <= 16) {
- res = DIV_ROUND_UP(((bpp - 12) *
- (ofs_und8[buf_i] - ofs_und6[buf_i])), 4);
- range_bpg_offset = ofs_und6[buf_i] + res;
- } else {
+ else if (bpp <= 10)
+ range_bpg_offset = get_range_bpg_offset(8, ofs_und4[buf_i],
+ 10, ofs_und5[buf_i], bpp);
+ else if (bpp <= 12)
+ range_bpg_offset = get_range_bpg_offset(10, ofs_und5[buf_i],
+ 12, ofs_und6[buf_i], bpp);
+ else if (bpp <= 16)
+ range_bpg_offset = get_range_bpg_offset(12, ofs_und6[buf_i],
+ 16, ofs_und8[buf_i], bpp);
+ else
range_bpg_offset = ofs_und8[buf_i];
- }
vdsc_cfg->rc_range_params[buf_i].range_bpg_offset =
range_bpg_offset & DSC_RANGE_BPG_OFFSET_MASK;
@@ -214,21 +216,19 @@ calculate_rc_params(struct drm_dsc_config *vdsc_cfg)
intel_vdsc_set_min_max_qp(vdsc_cfg, buf_i, bpp_i);
/* Calculate range_bpg_offset */
- if (bpp <= 6) {
+ if (bpp <= 6)
range_bpg_offset = ofs_und6[buf_i];
- } else if (bpp <= 8) {
- res = DIV_ROUND_UP(((bpp - 6) *
- (ofs_und8[buf_i] - ofs_und6[buf_i])), 2);
- range_bpg_offset = ofs_und6[buf_i] + res;
- } else if (bpp <= 12) {
- range_bpg_offset = ofs_und8[buf_i];
- } else if (bpp <= 15) {
- res = DIV_ROUND_UP(((bpp - 12) *
- (ofs_und15[buf_i] - ofs_und12[buf_i])), 3);
- range_bpg_offset = ofs_und12[buf_i] + res;
- } else {
+ else if (bpp <= 8)
+ range_bpg_offset = get_range_bpg_offset(6, ofs_und6[buf_i],
+ 8, ofs_und8[buf_i], bpp);
+ else if (bpp <= 12)
+ range_bpg_offset = get_range_bpg_offset(8, ofs_und8[buf_i],
+ 12, ofs_und12[buf_i], bpp);
+ else if (bpp <= 15)
+ range_bpg_offset = get_range_bpg_offset(12, ofs_und12[buf_i],
+ 15, ofs_und15[buf_i], bpp);
+ else
range_bpg_offset = ofs_und15[buf_i];
- }
vdsc_cfg->rc_range_params[buf_i].range_bpg_offset =
range_bpg_offset & DSC_RANGE_BPG_OFFSET_MASK;
@@ -261,8 +261,7 @@ static int intel_dsc_slice_dimensions_valid(struct intel_crtc_state *pipe_config
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 intel_display *display = to_intel_display(pipe_config);
struct drm_dsc_config *vdsc_cfg = &pipe_config->dsc.config;
u16 compressed_bpp = fxp_q4_to_int(pipe_config->dsc.compressed_bpp_x16);
int err;
@@ -275,7 +274,7 @@ int intel_dsc_compute_params(struct intel_crtc_state *pipe_config)
err = intel_dsc_slice_dimensions_valid(pipe_config, vdsc_cfg);
if (err) {
- drm_dbg_kms(&dev_priv->drm, "Slice dimension requirements not met\n");
+ drm_dbg_kms(display->drm, "Slice dimension requirements not met\n");
return err;
}
@@ -286,7 +285,7 @@ int intel_dsc_compute_params(struct intel_crtc_state *pipe_config)
vdsc_cfg->convert_rgb = pipe_config->output_format != INTEL_OUTPUT_FORMAT_YCBCR420 &&
pipe_config->output_format != INTEL_OUTPUT_FORMAT_YCBCR444;
- if (DISPLAY_VER(dev_priv) >= 14 &&
+ if (DISPLAY_VER(display) >= 14 &&
pipe_config->output_format == INTEL_OUTPUT_FORMAT_YCBCR420)
vdsc_cfg->native_420 = true;
/* We do not support YcBCr422 as of now */
@@ -307,7 +306,7 @@ 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",
+ drm_dbg_kms(display->drm, "DSC bpc requirements not met bpc: %d\n",
vdsc_cfg->bits_per_component);
return -EINVAL;
}
@@ -319,7 +318,7 @@ int intel_dsc_compute_params(struct intel_crtc_state *pipe_config)
* upto uncompressed bpp-1, hence add calculations for all the rc
* parameters
*/
- if (DISPLAY_VER(dev_priv) >= 13) {
+ if (DISPLAY_VER(display) >= 13) {
calculate_rc_params(vdsc_cfg);
} else {
if ((compressed_bpp == 8 ||
@@ -355,7 +354,7 @@ int intel_dsc_compute_params(struct intel_crtc_state *pipe_config)
enum intel_display_power_domain
intel_dsc_power_domain(struct intel_crtc *crtc, enum transcoder cpu_transcoder)
{
- struct drm_i915_private *i915 = to_i915(crtc->base.dev);
+ struct intel_display *display = to_intel_display(crtc);
enum pipe pipe = crtc->pipe;
/*
@@ -369,7 +368,8 @@ intel_dsc_power_domain(struct intel_crtc *crtc, enum transcoder cpu_transcoder)
* the pipe in use. Hence another reference on the pipe power domain
* will suffice. (Except no VDSC/joining on ICL pipe A.)
*/
- if (DISPLAY_VER(i915) == 12 && !IS_ROCKETLAKE(i915) && pipe == PIPE_A)
+ if (DISPLAY_VER(display) == 12 && !display->platform.rocketlake &&
+ pipe == PIPE_A)
return POWER_DOMAIN_TRANSCODER_VDSC_PW2;
else if (is_pipe_dsc(crtc, cpu_transcoder))
return POWER_DOMAIN_PIPE(pipe);
@@ -379,7 +379,7 @@ 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)
@@ -402,8 +402,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)
@@ -413,26 +415,25 @@ static void intel_dsc_get_pps_reg(const struct intel_crtc_state *crtc_state, int
static void intel_dsc_pps_write(const struct intel_crtc_state *crtc_state,
int pps, u32 pps_val)
{
- 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];
+ struct intel_display *display = to_intel_display(crtc_state);
+ 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);
dsc_reg_num = min_t(int, ARRAY_SIZE(dsc_reg), vdsc_per_pipe);
- drm_WARN_ON_ONCE(&i915->drm, dsc_reg_num < vdsc_per_pipe);
+ drm_WARN_ON_ONCE(display->drm, dsc_reg_num < vdsc_per_pipe);
intel_dsc_get_pps_reg(crtc_state, pps, dsc_reg, dsc_reg_num);
for (i = 0; i < dsc_reg_num; i++)
- intel_de_write(i915, dsc_reg[i], pps_val);
+ intel_de_write(display, dsc_reg[i], pps_val);
}
static void intel_dsc_pps_configure(const struct intel_crtc_state *crtc_state)
{
+ struct intel_display *display = to_intel_display(crtc_state);
struct intel_crtc *crtc = to_intel_crtc(crtc_state->uapi.crtc);
- struct drm_i915_private *dev_priv = to_i915(crtc->base.dev);
const struct drm_dsc_config *vdsc_cfg = &crtc_state->dsc.config;
enum transcoder cpu_transcoder = crtc_state->cpu_transcoder;
enum pipe pipe = crtc->pipe;
@@ -526,7 +527,7 @@ static void intel_dsc_pps_configure(const struct intel_crtc_state *crtc_state)
vdsc_cfg->slice_height);
intel_dsc_pps_write(crtc_state, 16, pps_val);
- if (DISPLAY_VER(dev_priv) >= 14) {
+ if (DISPLAY_VER(display) >= 14) {
/* PPS 17 */
pps_val = DSC_PPS17_SL_BPG_OFFSET(vdsc_cfg->second_line_bpg_offset);
intel_dsc_pps_write(crtc_state, 17, pps_val);
@@ -544,44 +545,44 @@ static void intel_dsc_pps_configure(const struct intel_crtc_state *crtc_state)
(u32)(vdsc_cfg->rc_buf_thresh[i] <<
BITS_PER_BYTE * (i % 4));
if (!is_pipe_dsc(crtc, cpu_transcoder)) {
- intel_de_write(dev_priv, DSCA_RC_BUF_THRESH_0,
+ intel_de_write(display, DSCA_RC_BUF_THRESH_0,
rc_buf_thresh_dword[0]);
- intel_de_write(dev_priv, DSCA_RC_BUF_THRESH_0_UDW,
+ intel_de_write(display, DSCA_RC_BUF_THRESH_0_UDW,
rc_buf_thresh_dword[1]);
- intel_de_write(dev_priv, DSCA_RC_BUF_THRESH_1,
+ intel_de_write(display, DSCA_RC_BUF_THRESH_1,
rc_buf_thresh_dword[2]);
- intel_de_write(dev_priv, DSCA_RC_BUF_THRESH_1_UDW,
+ intel_de_write(display, DSCA_RC_BUF_THRESH_1_UDW,
rc_buf_thresh_dword[3]);
if (vdsc_instances_per_pipe > 1) {
- intel_de_write(dev_priv, DSCC_RC_BUF_THRESH_0,
+ intel_de_write(display, DSCC_RC_BUF_THRESH_0,
rc_buf_thresh_dword[0]);
- intel_de_write(dev_priv, DSCC_RC_BUF_THRESH_0_UDW,
+ intel_de_write(display, DSCC_RC_BUF_THRESH_0_UDW,
rc_buf_thresh_dword[1]);
- intel_de_write(dev_priv, DSCC_RC_BUF_THRESH_1,
+ intel_de_write(display, DSCC_RC_BUF_THRESH_1,
rc_buf_thresh_dword[2]);
- intel_de_write(dev_priv, DSCC_RC_BUF_THRESH_1_UDW,
+ intel_de_write(display, DSCC_RC_BUF_THRESH_1_UDW,
rc_buf_thresh_dword[3]);
}
} else {
- intel_de_write(dev_priv, ICL_DSC0_RC_BUF_THRESH_0(pipe),
+ intel_de_write(display, ICL_DSC0_RC_BUF_THRESH_0(pipe),
rc_buf_thresh_dword[0]);
- intel_de_write(dev_priv, ICL_DSC0_RC_BUF_THRESH_0_UDW(pipe),
+ intel_de_write(display, ICL_DSC0_RC_BUF_THRESH_0_UDW(pipe),
rc_buf_thresh_dword[1]);
- intel_de_write(dev_priv, ICL_DSC0_RC_BUF_THRESH_1(pipe),
+ intel_de_write(display, ICL_DSC0_RC_BUF_THRESH_1(pipe),
rc_buf_thresh_dword[2]);
- intel_de_write(dev_priv, ICL_DSC0_RC_BUF_THRESH_1_UDW(pipe),
+ intel_de_write(display, ICL_DSC0_RC_BUF_THRESH_1_UDW(pipe),
rc_buf_thresh_dword[3]);
if (vdsc_instances_per_pipe > 1) {
- intel_de_write(dev_priv,
+ intel_de_write(display,
ICL_DSC1_RC_BUF_THRESH_0(pipe),
rc_buf_thresh_dword[0]);
- intel_de_write(dev_priv,
+ intel_de_write(display,
ICL_DSC1_RC_BUF_THRESH_0_UDW(pipe),
rc_buf_thresh_dword[1]);
- intel_de_write(dev_priv,
+ intel_de_write(display,
ICL_DSC1_RC_BUF_THRESH_1(pipe),
rc_buf_thresh_dword[2]);
- intel_de_write(dev_priv,
+ intel_de_write(display,
ICL_DSC1_RC_BUF_THRESH_1_UDW(pipe),
rc_buf_thresh_dword[3]);
}
@@ -598,88 +599,88 @@ static void intel_dsc_pps_configure(const struct intel_crtc_state *crtc_state)
(vdsc_cfg->rc_range_params[i].range_min_qp <<
RC_MIN_QP_SHIFT)) << 16 * (i % 2));
if (!is_pipe_dsc(crtc, cpu_transcoder)) {
- intel_de_write(dev_priv, DSCA_RC_RANGE_PARAMETERS_0,
+ intel_de_write(display, DSCA_RC_RANGE_PARAMETERS_0,
rc_range_params_dword[0]);
- intel_de_write(dev_priv, DSCA_RC_RANGE_PARAMETERS_0_UDW,
+ intel_de_write(display, DSCA_RC_RANGE_PARAMETERS_0_UDW,
rc_range_params_dword[1]);
- intel_de_write(dev_priv, DSCA_RC_RANGE_PARAMETERS_1,
+ intel_de_write(display, DSCA_RC_RANGE_PARAMETERS_1,
rc_range_params_dword[2]);
- intel_de_write(dev_priv, DSCA_RC_RANGE_PARAMETERS_1_UDW,
+ intel_de_write(display, DSCA_RC_RANGE_PARAMETERS_1_UDW,
rc_range_params_dword[3]);
- intel_de_write(dev_priv, DSCA_RC_RANGE_PARAMETERS_2,
+ intel_de_write(display, DSCA_RC_RANGE_PARAMETERS_2,
rc_range_params_dword[4]);
- intel_de_write(dev_priv, DSCA_RC_RANGE_PARAMETERS_2_UDW,
+ intel_de_write(display, DSCA_RC_RANGE_PARAMETERS_2_UDW,
rc_range_params_dword[5]);
- intel_de_write(dev_priv, DSCA_RC_RANGE_PARAMETERS_3,
+ intel_de_write(display, DSCA_RC_RANGE_PARAMETERS_3,
rc_range_params_dword[6]);
- intel_de_write(dev_priv, DSCA_RC_RANGE_PARAMETERS_3_UDW,
+ intel_de_write(display, DSCA_RC_RANGE_PARAMETERS_3_UDW,
rc_range_params_dword[7]);
if (vdsc_instances_per_pipe > 1) {
- intel_de_write(dev_priv, DSCC_RC_RANGE_PARAMETERS_0,
+ intel_de_write(display, DSCC_RC_RANGE_PARAMETERS_0,
rc_range_params_dword[0]);
- intel_de_write(dev_priv,
+ intel_de_write(display,
DSCC_RC_RANGE_PARAMETERS_0_UDW,
rc_range_params_dword[1]);
- intel_de_write(dev_priv, DSCC_RC_RANGE_PARAMETERS_1,
+ intel_de_write(display, DSCC_RC_RANGE_PARAMETERS_1,
rc_range_params_dword[2]);
- intel_de_write(dev_priv,
+ intel_de_write(display,
DSCC_RC_RANGE_PARAMETERS_1_UDW,
rc_range_params_dword[3]);
- intel_de_write(dev_priv, DSCC_RC_RANGE_PARAMETERS_2,
+ intel_de_write(display, DSCC_RC_RANGE_PARAMETERS_2,
rc_range_params_dword[4]);
- intel_de_write(dev_priv,
+ intel_de_write(display,
DSCC_RC_RANGE_PARAMETERS_2_UDW,
rc_range_params_dword[5]);
- intel_de_write(dev_priv, DSCC_RC_RANGE_PARAMETERS_3,
+ intel_de_write(display, DSCC_RC_RANGE_PARAMETERS_3,
rc_range_params_dword[6]);
- intel_de_write(dev_priv,
+ intel_de_write(display,
DSCC_RC_RANGE_PARAMETERS_3_UDW,
rc_range_params_dword[7]);
}
} else {
- intel_de_write(dev_priv, ICL_DSC0_RC_RANGE_PARAMETERS_0(pipe),
+ intel_de_write(display, ICL_DSC0_RC_RANGE_PARAMETERS_0(pipe),
rc_range_params_dword[0]);
- intel_de_write(dev_priv,
+ intel_de_write(display,
ICL_DSC0_RC_RANGE_PARAMETERS_0_UDW(pipe),
rc_range_params_dword[1]);
- intel_de_write(dev_priv, ICL_DSC0_RC_RANGE_PARAMETERS_1(pipe),
+ intel_de_write(display, ICL_DSC0_RC_RANGE_PARAMETERS_1(pipe),
rc_range_params_dword[2]);
- intel_de_write(dev_priv,
+ intel_de_write(display,
ICL_DSC0_RC_RANGE_PARAMETERS_1_UDW(pipe),
rc_range_params_dword[3]);
- intel_de_write(dev_priv, ICL_DSC0_RC_RANGE_PARAMETERS_2(pipe),
+ intel_de_write(display, ICL_DSC0_RC_RANGE_PARAMETERS_2(pipe),
rc_range_params_dword[4]);
- intel_de_write(dev_priv,
+ intel_de_write(display,
ICL_DSC0_RC_RANGE_PARAMETERS_2_UDW(pipe),
rc_range_params_dword[5]);
- intel_de_write(dev_priv, ICL_DSC0_RC_RANGE_PARAMETERS_3(pipe),
+ intel_de_write(display, ICL_DSC0_RC_RANGE_PARAMETERS_3(pipe),
rc_range_params_dword[6]);
- intel_de_write(dev_priv,
+ intel_de_write(display,
ICL_DSC0_RC_RANGE_PARAMETERS_3_UDW(pipe),
rc_range_params_dword[7]);
if (vdsc_instances_per_pipe > 1) {
- intel_de_write(dev_priv,
+ intel_de_write(display,
ICL_DSC1_RC_RANGE_PARAMETERS_0(pipe),
rc_range_params_dword[0]);
- intel_de_write(dev_priv,
+ intel_de_write(display,
ICL_DSC1_RC_RANGE_PARAMETERS_0_UDW(pipe),
rc_range_params_dword[1]);
- intel_de_write(dev_priv,
+ intel_de_write(display,
ICL_DSC1_RC_RANGE_PARAMETERS_1(pipe),
rc_range_params_dword[2]);
- intel_de_write(dev_priv,
+ intel_de_write(display,
ICL_DSC1_RC_RANGE_PARAMETERS_1_UDW(pipe),
rc_range_params_dword[3]);
- intel_de_write(dev_priv,
+ intel_de_write(display,
ICL_DSC1_RC_RANGE_PARAMETERS_2(pipe),
rc_range_params_dword[4]);
- intel_de_write(dev_priv,
+ intel_de_write(display,
ICL_DSC1_RC_RANGE_PARAMETERS_2_UDW(pipe),
rc_range_params_dword[5]);
- intel_de_write(dev_priv,
+ intel_de_write(display,
ICL_DSC1_RC_RANGE_PARAMETERS_3(pipe),
rc_range_params_dword[6]);
- intel_de_write(dev_priv,
+ intel_de_write(display,
ICL_DSC1_RC_RANGE_PARAMETERS_3_UDW(pipe),
rc_range_params_dword[7]);
}
@@ -743,8 +744,8 @@ static i915_reg_t dss_ctl2_reg(struct intel_crtc *crtc, enum transcoder cpu_tran
void intel_uncompressed_joiner_enable(const struct intel_crtc_state *crtc_state)
{
+ struct intel_display *display = to_intel_display(crtc_state);
struct intel_crtc *crtc = to_intel_crtc(crtc_state->uapi.crtc);
- struct drm_i915_private *dev_priv = to_i915(crtc->base.dev);
u32 dss_ctl1_val = 0;
if (crtc_state->joiner_pipes && !crtc_state->dsc.compression_enable) {
@@ -753,14 +754,15 @@ void intel_uncompressed_joiner_enable(const struct intel_crtc_state *crtc_state)
else
dss_ctl1_val |= UNCOMPRESSED_JOINER_PRIMARY;
- intel_de_write(dev_priv, dss_ctl1_reg(crtc, crtc_state->cpu_transcoder), dss_ctl1_val);
+ intel_de_write(display, dss_ctl1_reg(crtc, crtc_state->cpu_transcoder),
+ dss_ctl1_val);
}
}
void intel_dsc_enable(const struct intel_crtc_state *crtc_state)
{
+ struct intel_display *display = to_intel_display(crtc_state);
struct intel_crtc *crtc = to_intel_crtc(crtc_state->uapi.crtc);
- struct drm_i915_private *dev_priv = to_i915(crtc->base.dev);
u32 dss_ctl1_val = 0;
u32 dss_ctl2_val = 0;
int vdsc_instances_per_pipe = intel_dsc_get_vdsc_per_pipe(crtc_state);
@@ -770,11 +772,17 @@ 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 (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;
@@ -787,45 +795,44 @@ void intel_dsc_enable(const struct intel_crtc_state *crtc_state)
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);
+ intel_de_write(display, dss_ctl1_reg(crtc, crtc_state->cpu_transcoder), dss_ctl1_val);
+ intel_de_write(display, dss_ctl2_reg(crtc, crtc_state->cpu_transcoder), dss_ctl2_val);
}
void intel_dsc_disable(const struct intel_crtc_state *old_crtc_state)
{
+ struct intel_display *display = to_intel_display(old_crtc_state);
struct intel_crtc *crtc = to_intel_crtc(old_crtc_state->uapi.crtc);
- struct drm_i915_private *dev_priv = to_i915(crtc->base.dev);
/* Disable only if either of them is enabled */
if (old_crtc_state->dsc.compression_enable ||
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);
+ intel_de_write(display, dss_ctl1_reg(crtc, old_crtc_state->cpu_transcoder), 0);
+ intel_de_write(display, dss_ctl2_reg(crtc, old_crtc_state->cpu_transcoder), 0);
}
}
static u32 intel_dsc_pps_read(struct intel_crtc_state *crtc_state, int pps,
bool *all_equal)
{
- 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];
+ struct intel_display *display = to_intel_display(crtc_state);
+ i915_reg_t dsc_reg[3];
int i, vdsc_per_pipe, dsc_reg_num;
u32 val;
vdsc_per_pipe = intel_dsc_get_vdsc_per_pipe(crtc_state);
dsc_reg_num = min_t(int, ARRAY_SIZE(dsc_reg), vdsc_per_pipe);
- drm_WARN_ON_ONCE(&i915->drm, dsc_reg_num < vdsc_per_pipe);
+ drm_WARN_ON_ONCE(display->drm, dsc_reg_num < vdsc_per_pipe);
intel_dsc_get_pps_reg(crtc_state, pps, dsc_reg, dsc_reg_num);
*all_equal = true;
- val = intel_de_read(i915, dsc_reg[0]);
+ val = intel_de_read(display, dsc_reg[0]);
for (i = 1; i < dsc_reg_num; i++) {
- if (intel_de_read(i915, dsc_reg[i]) != val) {
+ if (intel_de_read(display, dsc_reg[i]) != val) {
*all_equal = false;
break;
}
@@ -836,22 +843,20 @@ static u32 intel_dsc_pps_read(struct intel_crtc_state *crtc_state, int pps,
static u32 intel_dsc_pps_read_and_verify(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);
+ struct intel_display *display = to_intel_display(crtc_state);
u32 val;
bool all_equal;
val = intel_dsc_pps_read(crtc_state, pps, &all_equal);
- drm_WARN_ON(&i915->drm, !all_equal);
+ drm_WARN_ON(display->drm, !all_equal);
return val;
}
static void intel_dsc_get_pps_config(struct intel_crtc_state *crtc_state)
{
+ struct intel_display *display = to_intel_display(crtc_state);
struct drm_dsc_config *vdsc_cfg = &crtc_state->dsc.config;
- struct intel_crtc *crtc = to_intel_crtc(crtc_state->uapi.crtc);
- struct drm_i915_private *i915 = to_i915(crtc->base.dev);
int num_vdsc_instances = intel_dsc_get_num_vdsc_instances(crtc_state);
u32 pps_temp;
@@ -937,7 +942,7 @@ static void intel_dsc_get_pps_config(struct intel_crtc_state *crtc_state)
vdsc_cfg->slice_chunk_size = REG_FIELD_GET(DSC_PPS16_SLICE_CHUNK_SIZE_MASK, pps_temp);
- if (DISPLAY_VER(i915) >= 14) {
+ if (DISPLAY_VER(display) >= 14) {
/* PPS 17 */
pps_temp = intel_dsc_pps_read_and_verify(crtc_state, 17);
@@ -953,8 +958,8 @@ static void intel_dsc_get_pps_config(struct intel_crtc_state *crtc_state)
void intel_dsc_get_config(struct intel_crtc_state *crtc_state)
{
+ struct intel_display *display = to_intel_display(crtc_state);
struct intel_crtc *crtc = to_intel_crtc(crtc_state->uapi.crtc);
- struct drm_i915_private *dev_priv = to_i915(crtc->base.dev);
enum transcoder cpu_transcoder = crtc_state->cpu_transcoder;
enum intel_display_power_domain power_domain;
intel_wakeref_t wakeref;
@@ -965,33 +970,37 @@ void intel_dsc_get_config(struct intel_crtc_state *crtc_state)
power_domain = intel_dsc_power_domain(crtc, cpu_transcoder);
- wakeref = intel_display_power_get_if_enabled(dev_priv, power_domain);
+ wakeref = intel_display_power_get_if_enabled(display, power_domain);
if (!wakeref)
return;
- 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));
+ dss_ctl1 = intel_de_read(display, dss_ctl1_reg(crtc, cpu_transcoder));
+ dss_ctl2 = intel_de_read(display, 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);
+ intel_display_power_put(display, 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, split: %s\n",
+ "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,
- str_yes_no(crtc_state->dsc.dsc_split));
+ crtc_state->dsc.num_streams);
}
void intel_vdsc_state_dump(struct drm_printer *p, int indent,
@@ -1003,3 +1012,47 @@ void intel_vdsc_state_dump(struct drm_printer *p, int indent,
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_display *display = to_intel_display(crtc_state);
+ 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;
+}