disp: msm: dp: add support for 3.75:1 compression

Currently the DP driver always uses a compression ratio of 3, if
DSC is enabled. So if the sink supports 30bpp, the compressed
output is set to 10bpp. But since the hardware supports
compressing this to 8bpp, it would require less link bandwidth
than 10bpp compressed output. For compliance testing, the
test equipment limits the link bandwidth based on the most
efficient compression ratio and for some resolutions there
is not enough link bandwidth for 3:1 compression.

This change always sets the compression output to 8bpp to
minimize the link bandwidth utilization.

Change-Id: Ifa6129444c2bab4e9c357ddfe49f76efa5b04be0
Signed-off-by: Rajkumar Subbiah <rsubbia@codeaurora.org>
This commit is contained in:
Rajkumar Subbiah
2021-06-14 20:03:52 -04:00
parent 17997f6098
commit eebce2ae4c
6 changed files with 49 additions and 61 deletions

View File

@@ -1080,7 +1080,7 @@ static void dp_ctrl_mst_calculate_rg(struct dp_ctrl_private *ctrl,
u64 target_strm_sym, ts_int_fixp, ts_frac_fixp, y_frac_enum_fixp;
lclk = drm_dp_bw_code_to_link_rate(ctrl->link->link_params.bw_code);
if (panel->pinfo.comp_info.comp_ratio > 1)
if (panel->pinfo.comp_info.enabled)
bpp = DSC_BPP(panel->pinfo.comp_info.dsc_info.config);
/* min_slot_cnt */

View File

@@ -1384,7 +1384,7 @@ static void dp_display_update_dsc_resources(struct dp_display_private *dp,
if (enable) {
if (panel->pinfo.comp_info.comp_type == MSM_DISPLAY_COMPRESSION_DSC &&
(panel->pinfo.comp_info.comp_ratio > 1)) {
(panel->pinfo.comp_info.enabled)) {
rc = msm_get_dsc_count(priv, panel->pinfo.h_active,
&dsc_blk_cnt);
if (rc) {
@@ -2719,7 +2719,7 @@ static int dp_display_validate_link_clock(struct dp_display_private *dp,
bool dsc_en;
int rate;
dsc_en = (dp_mode.timing.comp_info.comp_ratio > 1) ? true : false;
dsc_en = dp_mode.timing.comp_info.enabled;
mode_bpp = dsc_en ?
DSC_BPP(dp_mode.timing.comp_info.dsc_info.config)
: dp_mode.timing.bpp;

View File

@@ -431,7 +431,7 @@ int dp_connector_get_mode_info(struct drm_connector *connector,
dp_disp->convert_to_dp_mode(dp_disp, dp_panel, drm_mode, &dp_mode);
if (dp_mode.timing.comp_info.comp_ratio > 1) {
if (dp_mode.timing.comp_info.enabled) {
memcpy(&mode_info->comp_info,
&dp_mode.timing.comp_info,
sizeof(mode_info->comp_info));

View File

@@ -239,7 +239,7 @@ static int dp_mst_calc_pbn_mode(struct dp_display_mode *dp_mode)
bool dsc_en;
s64 pbn_fp;
dsc_en = (dp_mode->timing.comp_info.comp_ratio > 1) ? true : false;
dsc_en = dp_mode->timing.comp_info.enabled;
bpp = dsc_en ?
DSC_BPP(dp_mode->timing.comp_info.dsc_info.config)
: dp_mode->timing.bpp;
@@ -614,7 +614,7 @@ static void dp_mst_bridge_pre_enable(struct drm_bridge *drm_bridge)
DP_MST_INFO("conn:%d mode:%s fps:%d dsc:%d vcpi:%d slots:%d to %d\n",
DP_MST_CONN_ID(bridge), bridge->drm_mode.name,
drm_mode_vrefresh(&bridge->drm_mode),
bridge->dp_mode.timing.comp_info.comp_ratio,
bridge->dp_mode.timing.comp_info.enabled,
bridge->vcpi, bridge->start_slot,
bridge->start_slot + bridge->num_slots);
end:

View File

@@ -15,16 +15,13 @@
#define DP_PANEL_DEFAULT_BPP 24
#define DP_MAX_DS_PORT_COUNT 1
#define DSC_TGT_BPP 8
#define DPRX_FEATURE_ENUMERATION_LIST 0x2210
#define DPRX_EXTENDED_DPCD_FIELD 0x2200
#define VSC_SDP_EXTENSION_FOR_COLORIMETRY_SUPPORTED BIT(3)
#define VSC_EXT_VESA_SDP_SUPPORTED BIT(4)
#define VSC_EXT_VESA_SDP_CHAINING_SUPPORTED BIT(5)
#define DP_COMPRESSION_RATIO_2_TO_1 2
#define DP_COMPRESSION_RATIO_3_TO_1 3
#define DP_COMPRESSION_RATIO_NONE 1
enum dp_panel_hdr_pixel_encoding {
RGB,
YCbCr444,
@@ -1120,8 +1117,9 @@ static void dp_panel_calc_tu_parameters(struct dp_panel *dp_panel,
in.fec_en = dp_panel->fec_en;
in.num_of_dsc_slices = pinfo->comp_info.dsc_info.slice_per_pkt;
if (pinfo->comp_info.comp_ratio)
in.compress_ratio = pinfo->comp_info.comp_ratio * 100;
if (pinfo->comp_info.enabled)
in.compress_ratio = mult_frac(100, pinfo->comp_info.src_bpp,
pinfo->comp_info.tgt_bpp);
_dp_panel_calc_tu(&in, tu_table);
}
@@ -1175,19 +1173,18 @@ static void dp_panel_config_tr_unit(struct dp_panel *dp_panel)
catalog->update_transfer_unit(catalog);
}
static void dp_panel_get_dto_params(u8 comp_ratio, u32 *num, u32 *denom,
u32 org_bpp)
static void dp_panel_get_dto_params(u32 src_bpp, u32 tgt_bpp, u32 *num, u32 *denom)
{
if ((comp_ratio == 2) && (org_bpp == 24)) {
if ((tgt_bpp == 12) && (src_bpp == 24)) {
*num = 1;
*denom = 2;
} else if ((comp_ratio == 2) && (org_bpp == 30)) {
} else if ((tgt_bpp == 15) && (src_bpp == 30)) {
*num = 5;
*denom = 8;
} else if ((comp_ratio == 3) && (org_bpp == 24)) {
} else if ((tgt_bpp == 8) && ((src_bpp == 24) || (src_bpp == 30))) {
*num = 1;
*denom = 3;
} else if ((comp_ratio == 3) && (org_bpp == 30)) {
} else if ((tgt_bpp == 10) && (src_bpp == 30)) {
*num = 5;
*denom = 12;
} else {
@@ -1237,17 +1234,16 @@ static void dp_panel_dsc_prepare_pps_packet(struct dp_panel *dp_panel)
}
}
static void _dp_panel_dsc_get_num_extra_pclk(struct msm_display_dsc_info *dsc,
u8 ratio)
static void _dp_panel_dsc_get_num_extra_pclk(struct msm_compression_info *comp_info)
{
unsigned int dto_n = 0, dto_d = 0, remainder;
int ack_required, last_few_ack_required, accum_ack;
int last_few_pclk, last_few_pclk_required;
struct msm_display_dsc_info *dsc = &comp_info->dsc_info;
int start, temp, line_width = dsc->config.pic_width/2;
s64 temp1_fp, temp2_fp;
dp_panel_get_dto_params(ratio, &dto_n, &dto_d,
dsc->config.bits_per_component * 3);
dp_panel_get_dto_params(comp_info->src_bpp, comp_info->tgt_bpp, &dto_n, &dto_d);
ack_required = dsc->pclk_per_line;
@@ -1325,8 +1321,7 @@ static void _dp_panel_dsc_bw_overhead_calc(struct dp_panel *dp_panel,
}
static void dp_panel_dsc_pclk_param_calc(struct dp_panel *dp_panel,
struct msm_display_dsc_info *dsc,
u8 ratio,
struct msm_compression_info *comp_info,
struct dp_display_mode *dp_mode)
{
int comp_ratio = 100, intf_width;
@@ -1335,6 +1330,7 @@ static void dp_panel_dsc_pclk_param_calc(struct dp_panel *dp_panel,
s64 numerator_fp, denominator_fp;
s64 dsc_byte_count_fp;
u32 dsc_byte_count, temp1, temp2;
struct msm_display_dsc_info *dsc = &comp_info->dsc_info;
intf_width = dp_mode->timing.h_active;
if (!dsc || !dsc->config.slice_width || !dsc->slice_per_pkt ||
@@ -1345,8 +1341,7 @@ static void dp_panel_dsc_pclk_param_calc(struct dp_panel *dp_panel,
slice_per_intf = DIV_ROUND_UP(intf_width,
dsc->config.slice_width);
if (ratio)
comp_ratio = ratio * 100;
comp_ratio = mult_frac(100, comp_info->src_bpp, comp_info->tgt_bpp);
temp1_fp = drm_fixp_from_fraction(comp_ratio, 100);
temp2_fp = drm_fixp_from_fraction(slice_per_pkt * 8, 1);
@@ -1367,7 +1362,7 @@ static void dp_panel_dsc_pclk_param_calc(struct dp_panel *dp_panel,
temp2_fp = drm_fixp_mul(dsc_byte_count_fp, temp1_fp);
dsc->pclk_per_line = fixp2int_ceil(temp2_fp);
_dp_panel_dsc_get_num_extra_pclk(dsc, ratio);
_dp_panel_dsc_get_num_extra_pclk(comp_info);
dsc->pclk_per_line--;
_dp_panel_dsc_bw_overhead_calc(dp_panel, dsc, dp_mode, dsc_byte_count);
@@ -1570,13 +1565,16 @@ static int dp_panel_dsc_prepare_basic_params(
comp_info->dsc_info.config.bits_per_component =
(dp_mode->timing.bpp / 3);
comp_info->dsc_info.config.bits_per_pixel =
comp_info->dsc_info.config.bits_per_component << 4;
comp_info->dsc_info.config.bits_per_pixel = DSC_TGT_BPP << 4;
comp_info->dsc_info.config.slice_count =
DIV_ROUND_UP(dp_mode->timing.h_active, slice_width);
comp_info->comp_type = MSM_DISPLAY_COMPRESSION_DSC;
comp_info->comp_ratio = DP_COMPRESSION_RATIO_3_TO_1;
comp_info->tgt_bpp = DSC_TGT_BPP;
comp_info->src_bpp = dp_mode->timing.bpp;
comp_info->comp_ratio = dp_mode->timing.bpp / DSC_TGT_BPP;
comp_info->enabled = true;
return 0;
}
@@ -1941,7 +1939,7 @@ static u32 dp_panel_get_supported_bpp(struct dp_panel *dp_panel,
else if (bpp == 24 && !(dp_panel->sink_dsc_caps.color_depth & DP_DSC_8_BPC))
continue;
mode_bitrate = mult_frac(mode_pclk_khz, bpp, 3);
mode_bitrate = mode_pclk_khz * DSC_TGT_BPP;
} else {
mode_bitrate = mode_pclk_khz * bpp;
}
@@ -2205,33 +2203,18 @@ end:
static u32 _dp_panel_calc_be_in_lane(struct dp_panel *dp_panel)
{
struct dp_panel_info *pinfo;
struct msm_compression_info *comp_info;
u32 dsc_htot_byte_cnt, mod_result;
u32 numerator, denominator;
s64 temp_fp;
u32 htotal, mod_result;
u32 be_in_lane = 10;
pinfo = &dp_panel->pinfo;
comp_info = &pinfo->comp_info;
comp_info = &dp_panel->pinfo.comp_info;
if (!dp_panel->mst_state)
return be_in_lane;
if (pinfo->comp_info.comp_ratio == DP_COMPRESSION_RATIO_2_TO_1)
denominator = 16; /* 2 * bits-in-byte */
else if (pinfo->comp_info.comp_ratio == DP_COMPRESSION_RATIO_3_TO_1)
denominator = 24; /* 3 * bits-in-byte */
else
denominator = 8;
htotal = comp_info->dsc_info.bytes_per_pkt * comp_info->dsc_info.pkt_per_line;
numerator = (pinfo->h_active + pinfo->h_back_porch +
pinfo->h_front_porch + pinfo->h_sync_width) *
pinfo->bpp;
temp_fp = drm_fixp_from_fraction(numerator, denominator);
dsc_htot_byte_cnt = drm_fixp2int_ceil(temp_fp);
mod_result = dsc_htot_byte_cnt % 12;
mod_result = htotal % 12;
if (mod_result == 0)
be_in_lane = 8;
else if (mod_result <= 3)
@@ -2283,8 +2266,8 @@ static void dp_panel_config_dsc(struct dp_panel *dp_panel, bool enable)
dsc->dsc_en = true;
dsc->dto_en = true;
dsc->continuous_pps = dp_panel->dsc_continuous_pps;
dp_panel_get_dto_params(comp_info->comp_ratio, &dsc->dto_n,
&dsc->dto_d, pinfo->bpp);
dp_panel_get_dto_params(comp_info->src_bpp, comp_info->tgt_bpp, &dsc->dto_n,
&dsc->dto_d);
} else {
dsc->dsc_en = false;
dsc->dto_en = false;
@@ -3000,15 +2983,15 @@ static void dp_panel_convert_to_dp_mode(struct dp_panel *dp_panel,
if (!dp_mode->timing.bpp)
dp_mode->timing.bpp = default_bpp;
dp_mode->timing.bpp = dp_panel_get_mode_bpp(dp_panel,
dp_mode->timing.bpp, dp_mode->timing.pixel_clk_khz);
dp_mode->timing.widebus_en = dp_panel->widebus_en;
dp_mode->timing.dsc_overhead_fp = 0;
comp_info = &dp_mode->timing.comp_info;
comp_info->comp_ratio = DP_COMPRESSION_RATIO_NONE;
comp_info->src_bpp = default_bpp;
comp_info->tgt_bpp = default_bpp;
comp_info->comp_type = MSM_DISPLAY_COMPRESSION_NONE;
comp_info->comp_ratio = 1;
comp_info->enabled = false;
/* As YUV was not supported now, so set the default format to RGB */
dp_mode->output_format = DP_OUTPUT_FORMAT_RGB;
@@ -3025,6 +3008,9 @@ static void dp_panel_convert_to_dp_mode(struct dp_panel *dp_panel,
DP_DEBUG("YCBCR420 was not supported");
}
dp_mode->timing.bpp = dp_panel_get_mode_bpp(dp_panel,
dp_mode->timing.bpp, dp_mode->timing.pixel_clk_khz);
if (dp_panel->dsc_en && dsc_cap) {
if (dp_panel_dsc_prepare_basic_params(comp_info,
dp_mode, dp_panel)) {
@@ -3045,10 +3031,7 @@ static void dp_panel_convert_to_dp_mode(struct dp_panel *dp_panel,
return;
}
dp_panel_dsc_pclk_param_calc(dp_panel,
&comp_info->dsc_info,
comp_info->comp_ratio,
dp_mode);
dp_panel_dsc_pclk_param_calc(dp_panel, comp_info, dp_mode);
}
dp_mode->fec_overhead_fp = dp_panel->fec_overhead_fp;
}

View File

@@ -681,17 +681,22 @@ struct msm_display_vdc_info {
/**
* struct msm_compression_info - defined panel compression
* @enabled: enabled/disabled
* @comp_type: type of compression supported
* @comp_ratio: compression ratio
* @src_bpp: bits per pixel before compression
* @tgt_bpp: bits per pixel after compression
* @dsc_info: dsc configuration if the compression
* supported is DSC
* @vdc_info: vdc configuration if the compression
* supported is VDC
*/
struct msm_compression_info {
bool enabled;
enum msm_display_compression_type comp_type;
u32 comp_ratio;
u32 src_bpp;
u32 tgt_bpp;
union{
struct msm_display_dsc_info dsc_info;
struct msm_display_vdc_info vdc_info;