2022-10-09 19:19:23

by Marijn Suijten

[permalink] [raw]
Subject: [PATCH v3 00/10] drm/msm: Fix math issues in MSM DSC implementation

Various removals of complex yet unnecessary math, fixing all uses of
drm_dsc_config::bits_per_pixel to deal with the fact that this field
includes four fractional bits, and finally making sure that
range_bpg_offset contains values 6-bits wide to prevent overflows in
drm_dsc_pps_payload_pack().

Altogether this series is responsible for solving _all_ Display Stream
Compression issues and artifacts on the Sony Tama (sdm845) Akatsuki
smartphone (2880x1440p).

Changes since v2:
- Generalize mux_word_size setting depending on bits_per_component;
- Migrate DSI's DSC calculations to drm_dsc_compute_rc_parameters(),
implicitly addressing existing math issues;
- Disallow any bits_per_component other than 8, until hardcoded values
are updated and tested to support such cases.

v2: https://lore.kernel.org/linux-arm-msm/[email protected]/T/#u

Changes since v1:

- Propagate r-b's, except (obviously) in patches that were (heavily)
modified;
- Remove accidental debug code in dsi_cmd_dma_add;
- Move Range BPG Offset masking out of DCS PPS packing, back into the
DSI driver when it is assigned to drm_dsc_config (this series is now
strictly focusing on drm/msm again);
- Replace modulo-check resulting in conditional increment with
DIV_ROUND_UP;
- Remove repeated calculation of slice_chunk_size;
- Use u16 instead of int when handling bits_per_pixel;
- Use DRM_DEV_ERROR instead of pr_err in DSI code;
- Also remove redundant target_bpp_x16 variable.

v1: https://lore.kernel.org/linux-arm-msm/[email protected]/T/#u

Marijn Suijten (10):
drm/msm/dsi: Remove useless math in DSC calculations
drm/msm/dsi: Remove repeated calculation of slice_per_intf
drm/msm/dsi: Use DIV_ROUND_UP instead of conditional increment on
modulo
drm/msm/dsi: Reuse earlier computed dsc->slice_chunk_size
drm/msm/dsi: Appropriately set dsc->mux_word_size based on bpc
drm/msm/dsi: Migrate to drm_dsc_compute_rc_parameters()
drm/msm/dsi: Disallow 8 BPC DSC configuration for alternative BPC
values
drm/msm/dsi: Account for DSC's bits_per_pixel having 4 fractional bits
drm/msm/dpu1: Account for DSC's bits_per_pixel having 4 fractional
bits
drm/msm/dsi: Prevent signed BPG offsets from bleeding into adjacent
bits

drivers/gpu/drm/msm/disp/dpu1/dpu_hw_dsc.c | 11 +-
drivers/gpu/drm/msm/dsi/dsi_host.c | 121 ++++++---------------
2 files changed, 37 insertions(+), 95 deletions(-)

--
2.38.0


2022-10-09 19:29:24

by Marijn Suijten

[permalink] [raw]
Subject: [PATCH v3 09/10] drm/msm/dpu1: Account for DSC's bits_per_pixel having 4 fractional bits

According to the comment this DPU register contains the bits per pixel
as a 6.4 fractional value, conveniently matching the contents of
bits_per_pixel in struct drm_dsc_config which also uses 4 fractional
bits. However, the downstream source this implementation was
copy-pasted from has its bpp field stored _without_ fractional part.

This makes the entire convoluted math obsolete as it is impossible to
pull those 4 fractional bits out of thin air, by somehow trying to reuse
the lowest 2 bits of a non-fractional bpp (lsb = bpp % 4??).

The rest of the code merely attempts to keep the integer part a multiple
of 4, which is rendered useless thanks to data |= dsc->bits_per_pixel <<
12; already filling up those bits anyway (but not on downstream).

Fixes: c110cfd1753e ("drm/msm/disp/dpu1: Add support for DSC")
Signed-off-by: Marijn Suijten <[email protected]>
Reviewed-by: Abhinav Kumar <[email protected]>
Reviewed-by: Dmitry Baryshkov <[email protected]>
Reviewed-by: Vinod Koul <[email protected]>
---
drivers/gpu/drm/msm/disp/dpu1/dpu_hw_dsc.c | 11 ++---------
1 file changed, 2 insertions(+), 9 deletions(-)

diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_dsc.c b/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_dsc.c
index 46cc2afd2bb9..c63e6eef1ba6 100644
--- a/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_dsc.c
+++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_dsc.c
@@ -47,7 +47,7 @@ static void dpu_hw_dsc_config(struct dpu_hw_dsc *hw_dsc,
u32 initial_lines)
{
struct dpu_hw_blk_reg_map *c = &hw_dsc->hw;
- u32 data, lsb, bpp;
+ u32 data;
u32 slice_last_group_size;
u32 det_thresh_flatness;
bool is_cmd_mode = !(mode & DSC_MODE_VIDEO);
@@ -61,14 +61,7 @@ static void dpu_hw_dsc_config(struct dpu_hw_dsc *hw_dsc,
data = (initial_lines << 20);
data |= ((slice_last_group_size - 1) << 18);
/* bpp is 6.4 format, 4 LSBs bits are for fractional part */
- data |= dsc->bits_per_pixel << 12;
- lsb = dsc->bits_per_pixel % 4;
- bpp = dsc->bits_per_pixel / 4;
- bpp *= 4;
- bpp <<= 4;
- bpp |= lsb;
-
- data |= bpp << 8;
+ data |= (dsc->bits_per_pixel << 8);
data |= (dsc->block_pred_enable << 7);
data |= (dsc->line_buf_depth << 3);
data |= (dsc->simple_422 << 2);
--
2.38.0

2022-10-09 19:34:09

by Marijn Suijten

[permalink] [raw]
Subject: [PATCH v3 02/10] drm/msm/dsi: Remove repeated calculation of slice_per_intf

slice_per_intf is already computed for intf_width, which holds the same
value as hdisplay.

Fixes: 08802f515c3c ("drm/msm/dsi: Add support for DSC configuration")
Signed-off-by: Marijn Suijten <[email protected]>
Reviewed-by: Bjorn Andersson <[email protected]>
Reviewed-by: Konrad Dybcio <[email protected]>
Reviewed-by: Abhinav Kumar <[email protected]>
Reviewed-by: Vinod Koul <[email protected]>
---
drivers/gpu/drm/msm/dsi/dsi_host.c | 6 ++----
1 file changed, 2 insertions(+), 4 deletions(-)

diff --git a/drivers/gpu/drm/msm/dsi/dsi_host.c b/drivers/gpu/drm/msm/dsi/dsi_host.c
index 70077d1f0f21..c746ed5d61f9 100644
--- a/drivers/gpu/drm/msm/dsi/dsi_host.c
+++ b/drivers/gpu/drm/msm/dsi/dsi_host.c
@@ -842,7 +842,7 @@ static void dsi_ctrl_config(struct msm_dsi_host *msm_host, bool enable,
static void dsi_update_dsc_timing(struct msm_dsi_host *msm_host, bool is_cmd_mode, u32 hdisplay)
{
struct drm_dsc_config *dsc = msm_host->dsc;
- u32 reg, intf_width, reg_ctrl, reg_ctrl2;
+ u32 reg, reg_ctrl, reg_ctrl2;
u32 slice_per_intf, total_bytes_per_intf;
u32 pkt_per_line;
u32 bytes_in_slice;
@@ -851,8 +851,7 @@ static void dsi_update_dsc_timing(struct msm_dsi_host *msm_host, bool is_cmd_mod
/* first calculate dsc parameters and then program
* compress mode registers
*/
- intf_width = hdisplay;
- slice_per_intf = DIV_ROUND_UP(intf_width, dsc->slice_width);
+ slice_per_intf = DIV_ROUND_UP(hdisplay, dsc->slice_width);

/* If slice_per_pkt is greater than slice_per_intf
* then default to 1. This can happen during partial
@@ -861,7 +860,6 @@ static void dsi_update_dsc_timing(struct msm_dsi_host *msm_host, bool is_cmd_mod
if (slice_per_intf > dsc->slice_count)
dsc->slice_count = 1;

- slice_per_intf = DIV_ROUND_UP(hdisplay, dsc->slice_width);
bytes_in_slice = DIV_ROUND_UP(dsc->slice_width * dsc->bits_per_pixel, 8);

dsc->slice_chunk_size = bytes_in_slice;
--
2.38.0

2022-10-09 20:04:42

by Marijn Suijten

[permalink] [raw]
Subject: [PATCH v3 05/10] drm/msm/dsi: Appropriately set dsc->mux_word_size based on bpc

This field is currently unread but will come into effect when duplicated
code below is migrated to call drm_dsc_compute_rc_parameters(), which
uses the bpc-dependent value of the local variable mux_words_size in
much the same way.

The hardcoded constant seems to be a remnant from the `/* bpc 8 */`
comment right above, indicating that this group of field assignments is
applicable to bpc = 8 exclusively and should probably bail out on
different bpc values, until constants for other bpc values are added (or
the current ones are confirmed to be correct across multiple bpc's).

Fixes: b9080324d6ca ("drm/msm/dsi: add support for dsc data")
Signed-off-by: Marijn Suijten <[email protected]>
---
drivers/gpu/drm/msm/dsi/dsi_host.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/drivers/gpu/drm/msm/dsi/dsi_host.c b/drivers/gpu/drm/msm/dsi/dsi_host.c
index f42794cdd4c1..83cde4d62b68 100644
--- a/drivers/gpu/drm/msm/dsi/dsi_host.c
+++ b/drivers/gpu/drm/msm/dsi/dsi_host.c
@@ -1808,6 +1808,7 @@ static int dsi_populate_dsc_params(struct drm_dsc_config *dsc)
if (dsc->bits_per_component == 12)
mux_words_size = 64;

+ dsc->mux_word_size = mux_words_size;
dsc->initial_xmit_delay = 512;
dsc->initial_scale_value = 32;
dsc->first_line_bpg_offset = 12;
@@ -1818,7 +1819,6 @@ static int dsi_populate_dsc_params(struct drm_dsc_config *dsc)
dsc->flatness_max_qp = 12;
dsc->rc_quant_incr_limit0 = 11;
dsc->rc_quant_incr_limit1 = 11;
- dsc->mux_word_size = DSC_MUX_WORD_SIZE_8_10_BPC;

/* FIXME: need to call drm_dsc_compute_rc_parameters() so that rest of
* params are calculated
--
2.38.0

2022-10-12 23:17:24

by Abhinav Kumar

[permalink] [raw]
Subject: Re: [PATCH v3 05/10] drm/msm/dsi: Appropriately set dsc->mux_word_size based on bpc



On 10/9/2022 11:48 AM, Marijn Suijten wrote:
> This field is currently unread but will come into effect when duplicated
> code below is migrated to call drm_dsc_compute_rc_parameters(), which
> uses the bpc-dependent value of the local variable mux_words_size in
> much the same way.
>
> The hardcoded constant seems to be a remnant from the `/* bpc 8 */`
> comment right above, indicating that this group of field assignments is
> applicable to bpc = 8 exclusively and should probably bail out on
> different bpc values, until constants for other bpc values are added (or
> the current ones are confirmed to be correct across multiple bpc's).
>

Yes, this seems to hard-code it to 8bpc/10bpc. So your code-change is fine.

Reviewed-by: Abhinav Kumar <[email protected]>
> Fixes: b9080324d6ca ("drm/msm/dsi: add support for dsc data")
> Signed-off-by: Marijn Suijten <[email protected]>
> ---
> drivers/gpu/drm/msm/dsi/dsi_host.c | 2 +-
> 1 file changed, 1 insertion(+), 1 deletion(-)
>
> diff --git a/drivers/gpu/drm/msm/dsi/dsi_host.c b/drivers/gpu/drm/msm/dsi/dsi_host.c
> index f42794cdd4c1..83cde4d62b68 100644
> --- a/drivers/gpu/drm/msm/dsi/dsi_host.c
> +++ b/drivers/gpu/drm/msm/dsi/dsi_host.c
> @@ -1808,6 +1808,7 @@ static int dsi_populate_dsc_params(struct drm_dsc_config *dsc)
> if (dsc->bits_per_component == 12)
> mux_words_size = 64;
>
> + dsc->mux_word_size = mux_words_size;
> dsc->initial_xmit_delay = 512;
> dsc->initial_scale_value = 32;
> dsc->first_line_bpg_offset = 12;
> @@ -1818,7 +1819,6 @@ static int dsi_populate_dsc_params(struct drm_dsc_config *dsc)
> dsc->flatness_max_qp = 12;
> dsc->rc_quant_incr_limit0 = 11;
> dsc->rc_quant_incr_limit1 = 11;
> - dsc->mux_word_size = DSC_MUX_WORD_SIZE_8_10_BPC;
>
> /* FIXME: need to call drm_dsc_compute_rc_parameters() so that rest of
> * params are calculated