diff mbox series

[v6,14/14] drm/msm/dsi: Add support for DSC configuration

Message ID 20220404163436.956875-15-vkoul@kernel.org
State Accepted
Commit 08802f515c3cfea80b48e198de52b4fcbbef27d3
Headers show
Series None | expand

Commit Message

Vinod Koul April 4, 2022, 4:34 p.m. UTC
When DSC is enabled, we need to configure DSI registers accordingly and
configure the respective stream compression registers.

Add support to calculate the register setting based on DSC params and
timing information and configure these registers.

Signed-off-by: Dmitry Baryshkov <dmitry.baryshkov@linaro.org>
Signed-off-by: Vinod Koul <vkoul@kernel.org>
---
 drivers/gpu/drm/msm/dsi/dsi_host.c | 98 +++++++++++++++++++++++++++++-
 1 file changed, 97 insertions(+), 1 deletion(-)

Comments

Dmitry Baryshkov April 5, 2022, 1:58 p.m. UTC | #1
On Mon, 4 Apr 2022 at 19:35, Vinod Koul <vkoul@kernel.org> wrote:
>
> When DSC is enabled, we need to configure DSI registers accordingly and
> configure the respective stream compression registers.
>
> Add support to calculate the register setting based on DSC params and
> timing information and configure these registers.
>
> Signed-off-by: Dmitry Baryshkov <dmitry.baryshkov@linaro.org>
> Signed-off-by: Vinod Koul <vkoul@kernel.org>

Reviewed-by: Dmitry Baryshkov <dmitry.baryshkov@linaro.org>


> ---
>  drivers/gpu/drm/msm/dsi/dsi_host.c | 98 +++++++++++++++++++++++++++++-
>  1 file changed, 97 insertions(+), 1 deletion(-)
>
> diff --git a/drivers/gpu/drm/msm/dsi/dsi_host.c b/drivers/gpu/drm/msm/dsi/dsi_host.c
> index eb0be34add45..f3ed6c40b9e1 100644
> --- a/drivers/gpu/drm/msm/dsi/dsi_host.c
> +++ b/drivers/gpu/drm/msm/dsi/dsi_host.c
> @@ -912,6 +912,65 @@ static void dsi_ctrl_config(struct msm_dsi_host *msm_host, bool enable,
>                 dsi_write(msm_host, REG_DSI_CPHY_MODE_CTRL, BIT(0));
>  }
>
> +static void dsi_update_dsc_timing(struct msm_dsi_host *msm_host, bool is_cmd_mode, u32 hdisplay)
> +{
> +       struct msm_display_dsc_config *dsc = msm_host->dsc;
> +       u32 reg, intf_width, reg_ctrl, reg_ctrl2;
> +       u32 slice_per_intf, total_bytes_per_intf;
> +       u32 pkt_per_line;
> +       u32 bytes_in_slice;
> +       u32 eol_byte_num;
> +
> +       /* first calculate dsc parameters and then program
> +        * compress mode registers
> +        */
> +       intf_width = hdisplay;
> +       slice_per_intf = DIV_ROUND_UP(intf_width, dsc->drm->slice_width);
> +
> +       /* If slice_per_pkt is greater than slice_per_intf
> +        * then default to 1. This can happen during partial
> +        * update.
> +        */
> +       if (slice_per_intf > dsc->drm->slice_count)
> +               dsc->drm->slice_count = 1;
> +
> +       slice_per_intf = DIV_ROUND_UP(hdisplay, dsc->drm->slice_width);
> +       bytes_in_slice = DIV_ROUND_UP(dsc->drm->slice_width * dsc->drm->bits_per_pixel, 8);
> +
> +       dsc->drm->slice_chunk_size = bytes_in_slice;
> +
> +       total_bytes_per_intf = bytes_in_slice * slice_per_intf;
> +
> +       eol_byte_num = total_bytes_per_intf % 3;
> +       pkt_per_line = slice_per_intf / dsc->drm->slice_count;
> +
> +       if (is_cmd_mode) /* packet data type */
> +               reg = DSI_COMMAND_COMPRESSION_MODE_CTRL_STREAM0_DATATYPE(MIPI_DSI_DCS_LONG_WRITE);
> +       else
> +               reg = DSI_VIDEO_COMPRESSION_MODE_CTRL_DATATYPE(MIPI_DSI_COMPRESSED_PIXEL_STREAM);
> +
> +       /* DSI_VIDEO_COMPRESSION_MODE & DSI_COMMAND_COMPRESSION_MODE
> +        * registers have similar offsets, so for below common code use
> +        * DSI_VIDEO_COMPRESSION_MODE_XXXX for setting bits
> +        */
> +       reg |= DSI_VIDEO_COMPRESSION_MODE_CTRL_PKT_PER_LINE(pkt_per_line >> 1);
> +       reg |= DSI_VIDEO_COMPRESSION_MODE_CTRL_EOL_BYTE_NUM(eol_byte_num);
> +       reg |= DSI_VIDEO_COMPRESSION_MODE_CTRL_EN;
> +
> +       if (is_cmd_mode) {
> +               reg_ctrl = dsi_read(msm_host, REG_DSI_COMMAND_COMPRESSION_MODE_CTRL);
> +               reg_ctrl2 = dsi_read(msm_host, REG_DSI_COMMAND_COMPRESSION_MODE_CTRL2);
> +
> +               reg_ctrl |= reg;
> +               reg_ctrl2 |= DSI_COMMAND_COMPRESSION_MODE_CTRL2_STREAM0_SLICE_WIDTH(bytes_in_slice);
> +
> +               dsi_write(msm_host, REG_DSI_COMMAND_COMPRESSION_MODE_CTRL, reg);
> +               dsi_write(msm_host, REG_DSI_COMMAND_COMPRESSION_MODE_CTRL2, reg_ctrl2);
> +       } else {
> +               dsi_write(msm_host, REG_DSI_VIDEO_COMPRESSION_MODE_CTRL, reg);
> +       }
> +}
> +
>  static void dsi_timing_setup(struct msm_dsi_host *msm_host, bool is_bonded_dsi)
>  {
>         struct drm_display_mode *mode = msm_host->mode;
> @@ -944,7 +1003,38 @@ static void dsi_timing_setup(struct msm_dsi_host *msm_host, bool is_bonded_dsi)
>                 hdisplay /= 2;
>         }
>
> +       if (msm_host->dsc) {
> +               struct msm_display_dsc_config *dsc = msm_host->dsc;
> +
> +               /* update dsc params with timing params */
> +               if (!dsc || !mode->hdisplay || !mode->vdisplay) {
> +                       pr_err("DSI: invalid input: pic_width: %d pic_height: %d\n",
> +                              mode->hdisplay, mode->vdisplay);
> +                       return;
> +               }
> +
> +               dsc->drm->pic_width = mode->hdisplay;
> +               dsc->drm->pic_height = mode->vdisplay;
> +               DBG("Mode %dx%d\n", dsc->drm->pic_width, dsc->drm->pic_height);
> +
> +               /* we do the calculations for dsc parameters here so that
> +                * panel can use these parameters
> +                */
> +               dsi_populate_dsc_params(dsc);
> +
> +               /* Divide the display by 3 but keep back/font porch and
> +                * pulse width same
> +                */
> +               h_total -= hdisplay;
> +               hdisplay /= 3;
> +               h_total += hdisplay;
> +               ha_end = ha_start + hdisplay;
> +       }
> +
>         if (msm_host->mode_flags & MIPI_DSI_MODE_VIDEO) {
> +               if (msm_host->dsc)
> +                       dsi_update_dsc_timing(msm_host, false, mode->hdisplay);
> +
>                 dsi_write(msm_host, REG_DSI_ACTIVE_H,
>                         DSI_ACTIVE_H_START(ha_start) |
>                         DSI_ACTIVE_H_END(ha_end));
> @@ -963,8 +1053,14 @@ static void dsi_timing_setup(struct msm_dsi_host *msm_host, bool is_bonded_dsi)
>                         DSI_ACTIVE_VSYNC_VPOS_START(vs_start) |
>                         DSI_ACTIVE_VSYNC_VPOS_END(vs_end));
>         } else {                /* command mode */
> +               if (msm_host->dsc)
> +                       dsi_update_dsc_timing(msm_host, true, mode->hdisplay);
> +
>                 /* image data and 1 byte write_memory_start cmd */
> -               wc = hdisplay * dsi_get_bpp(msm_host->format) / 8 + 1;
> +               if (!msm_host->dsc)
> +                       wc = hdisplay * dsi_get_bpp(msm_host->format) / 8 + 1;
> +               else
> +                       wc = mode->hdisplay / 2 + 1;
>
>                 dsi_write(msm_host, REG_DSI_CMD_MDP_STREAM0_CTRL,
>                         DSI_CMD_MDP_STREAM0_CTRL_WORD_COUNT(wc) |
> --
> 2.34.1
>
kernel test robot April 5, 2022, 7:12 p.m. UTC | #2
Hi Vinod,

I love your patch! Perhaps something to improve:

[auto build test WARNING on 05241de1f69eb7f56b0a5e0bec96a7752fad1b2f]

url:    https://github.com/intel-lab-lkp/linux/commits/Vinod-Koul/drm-msm-Add-Display-Stream-Compression-Support/20220405-003745
base:   05241de1f69eb7f56b0a5e0bec96a7752fad1b2f
config: hexagon-randconfig-r004-20220405 (https://download.01.org/0day-ci/archive/20220406/202204060308.OkAS3XG3-lkp@intel.com/config)
compiler: clang version 15.0.0 (https://github.com/llvm/llvm-project c4a1b07d0979e7ff20d7d541af666d822d66b566)
reproduce (this is a W=1 build):
        wget https://raw.githubusercontent.com/intel/lkp-tests/master/sbin/make.cross -O ~/bin/make.cross
        chmod +x ~/bin/make.cross
        # https://github.com/intel-lab-lkp/linux/commit/6c54db3ee1e02d639e568c37121f797ac586af3d
        git remote add linux-review https://github.com/intel-lab-lkp/linux
        git fetch --no-tags linux-review Vinod-Koul/drm-msm-Add-Display-Stream-Compression-Support/20220405-003745
        git checkout 6c54db3ee1e02d639e568c37121f797ac586af3d
        # save the config file to linux build tree
        mkdir build_dir
        COMPILER_INSTALL_PATH=$HOME/0day COMPILER=clang make.cross W=1 O=build_dir ARCH=hexagon SHELL=/bin/bash drivers/gpu/drm/msm/

If you fix the issue, kindly add following tag as appropriate
Reported-by: kernel test robot <lkp@intel.com>

All warnings (new ones prefixed by >>):

>> drivers/gpu/drm/msm/dsi/dsi_host.c:918:23: warning: variable 'reg_ctrl' set but not used [-Wunused-but-set-variable]
           u32 reg, intf_width, reg_ctrl, reg_ctrl2;
                                ^
   1 warning generated.


vim +/reg_ctrl +918 drivers/gpu/drm/msm/dsi/dsi_host.c

   914	
   915	static void dsi_update_dsc_timing(struct msm_dsi_host *msm_host, bool is_cmd_mode, u32 hdisplay)
   916	{
   917		struct msm_display_dsc_config *dsc = msm_host->dsc;
 > 918		u32 reg, intf_width, reg_ctrl, reg_ctrl2;
   919		u32 slice_per_intf, total_bytes_per_intf;
   920		u32 pkt_per_line;
   921		u32 bytes_in_slice;
   922		u32 eol_byte_num;
   923	
   924		/* first calculate dsc parameters and then program
   925		 * compress mode registers
   926		 */
   927		intf_width = hdisplay;
   928		slice_per_intf = DIV_ROUND_UP(intf_width, dsc->drm->slice_width);
   929	
   930		/* If slice_per_pkt is greater than slice_per_intf
   931		 * then default to 1. This can happen during partial
   932		 * update.
   933		 */
   934		if (slice_per_intf > dsc->drm->slice_count)
   935			dsc->drm->slice_count = 1;
   936	
   937		slice_per_intf = DIV_ROUND_UP(hdisplay, dsc->drm->slice_width);
   938		bytes_in_slice = DIV_ROUND_UP(dsc->drm->slice_width * dsc->drm->bits_per_pixel, 8);
   939	
   940		dsc->drm->slice_chunk_size = bytes_in_slice;
   941	
   942		total_bytes_per_intf = bytes_in_slice * slice_per_intf;
   943	
   944		eol_byte_num = total_bytes_per_intf % 3;
   945		pkt_per_line = slice_per_intf / dsc->drm->slice_count;
   946	
   947		if (is_cmd_mode) /* packet data type */
   948			reg = DSI_COMMAND_COMPRESSION_MODE_CTRL_STREAM0_DATATYPE(MIPI_DSI_DCS_LONG_WRITE);
   949		else
   950			reg = DSI_VIDEO_COMPRESSION_MODE_CTRL_DATATYPE(MIPI_DSI_COMPRESSED_PIXEL_STREAM);
   951	
   952		/* DSI_VIDEO_COMPRESSION_MODE & DSI_COMMAND_COMPRESSION_MODE
   953		 * registers have similar offsets, so for below common code use
   954		 * DSI_VIDEO_COMPRESSION_MODE_XXXX for setting bits
   955		 */
   956		reg |= DSI_VIDEO_COMPRESSION_MODE_CTRL_PKT_PER_LINE(pkt_per_line >> 1);
   957		reg |= DSI_VIDEO_COMPRESSION_MODE_CTRL_EOL_BYTE_NUM(eol_byte_num);
   958		reg |= DSI_VIDEO_COMPRESSION_MODE_CTRL_EN;
   959	
   960		if (is_cmd_mode) {
   961			reg_ctrl = dsi_read(msm_host, REG_DSI_COMMAND_COMPRESSION_MODE_CTRL);
   962			reg_ctrl2 = dsi_read(msm_host, REG_DSI_COMMAND_COMPRESSION_MODE_CTRL2);
   963	
   964			reg_ctrl |= reg;
   965			reg_ctrl2 |= DSI_COMMAND_COMPRESSION_MODE_CTRL2_STREAM0_SLICE_WIDTH(bytes_in_slice);
   966	
   967			dsi_write(msm_host, REG_DSI_COMMAND_COMPRESSION_MODE_CTRL, reg);
   968			dsi_write(msm_host, REG_DSI_COMMAND_COMPRESSION_MODE_CTRL2, reg_ctrl2);
   969		} else {
   970			dsi_write(msm_host, REG_DSI_VIDEO_COMPRESSION_MODE_CTRL, reg);
   971		}
   972	}
   973
diff mbox series

Patch

diff --git a/drivers/gpu/drm/msm/dsi/dsi_host.c b/drivers/gpu/drm/msm/dsi/dsi_host.c
index eb0be34add45..f3ed6c40b9e1 100644
--- a/drivers/gpu/drm/msm/dsi/dsi_host.c
+++ b/drivers/gpu/drm/msm/dsi/dsi_host.c
@@ -912,6 +912,65 @@  static void dsi_ctrl_config(struct msm_dsi_host *msm_host, bool enable,
 		dsi_write(msm_host, REG_DSI_CPHY_MODE_CTRL, BIT(0));
 }
 
+static void dsi_update_dsc_timing(struct msm_dsi_host *msm_host, bool is_cmd_mode, u32 hdisplay)
+{
+	struct msm_display_dsc_config *dsc = msm_host->dsc;
+	u32 reg, intf_width, reg_ctrl, reg_ctrl2;
+	u32 slice_per_intf, total_bytes_per_intf;
+	u32 pkt_per_line;
+	u32 bytes_in_slice;
+	u32 eol_byte_num;
+
+	/* first calculate dsc parameters and then program
+	 * compress mode registers
+	 */
+	intf_width = hdisplay;
+	slice_per_intf = DIV_ROUND_UP(intf_width, dsc->drm->slice_width);
+
+	/* If slice_per_pkt is greater than slice_per_intf
+	 * then default to 1. This can happen during partial
+	 * update.
+	 */
+	if (slice_per_intf > dsc->drm->slice_count)
+		dsc->drm->slice_count = 1;
+
+	slice_per_intf = DIV_ROUND_UP(hdisplay, dsc->drm->slice_width);
+	bytes_in_slice = DIV_ROUND_UP(dsc->drm->slice_width * dsc->drm->bits_per_pixel, 8);
+
+	dsc->drm->slice_chunk_size = bytes_in_slice;
+
+	total_bytes_per_intf = bytes_in_slice * slice_per_intf;
+
+	eol_byte_num = total_bytes_per_intf % 3;
+	pkt_per_line = slice_per_intf / dsc->drm->slice_count;
+
+	if (is_cmd_mode) /* packet data type */
+		reg = DSI_COMMAND_COMPRESSION_MODE_CTRL_STREAM0_DATATYPE(MIPI_DSI_DCS_LONG_WRITE);
+	else
+		reg = DSI_VIDEO_COMPRESSION_MODE_CTRL_DATATYPE(MIPI_DSI_COMPRESSED_PIXEL_STREAM);
+
+	/* DSI_VIDEO_COMPRESSION_MODE & DSI_COMMAND_COMPRESSION_MODE
+	 * registers have similar offsets, so for below common code use
+	 * DSI_VIDEO_COMPRESSION_MODE_XXXX for setting bits
+	 */
+	reg |= DSI_VIDEO_COMPRESSION_MODE_CTRL_PKT_PER_LINE(pkt_per_line >> 1);
+	reg |= DSI_VIDEO_COMPRESSION_MODE_CTRL_EOL_BYTE_NUM(eol_byte_num);
+	reg |= DSI_VIDEO_COMPRESSION_MODE_CTRL_EN;
+
+	if (is_cmd_mode) {
+		reg_ctrl = dsi_read(msm_host, REG_DSI_COMMAND_COMPRESSION_MODE_CTRL);
+		reg_ctrl2 = dsi_read(msm_host, REG_DSI_COMMAND_COMPRESSION_MODE_CTRL2);
+
+		reg_ctrl |= reg;
+		reg_ctrl2 |= DSI_COMMAND_COMPRESSION_MODE_CTRL2_STREAM0_SLICE_WIDTH(bytes_in_slice);
+
+		dsi_write(msm_host, REG_DSI_COMMAND_COMPRESSION_MODE_CTRL, reg);
+		dsi_write(msm_host, REG_DSI_COMMAND_COMPRESSION_MODE_CTRL2, reg_ctrl2);
+	} else {
+		dsi_write(msm_host, REG_DSI_VIDEO_COMPRESSION_MODE_CTRL, reg);
+	}
+}
+
 static void dsi_timing_setup(struct msm_dsi_host *msm_host, bool is_bonded_dsi)
 {
 	struct drm_display_mode *mode = msm_host->mode;
@@ -944,7 +1003,38 @@  static void dsi_timing_setup(struct msm_dsi_host *msm_host, bool is_bonded_dsi)
 		hdisplay /= 2;
 	}
 
+	if (msm_host->dsc) {
+		struct msm_display_dsc_config *dsc = msm_host->dsc;
+
+		/* update dsc params with timing params */
+		if (!dsc || !mode->hdisplay || !mode->vdisplay) {
+			pr_err("DSI: invalid input: pic_width: %d pic_height: %d\n",
+			       mode->hdisplay, mode->vdisplay);
+			return;
+		}
+
+		dsc->drm->pic_width = mode->hdisplay;
+		dsc->drm->pic_height = mode->vdisplay;
+		DBG("Mode %dx%d\n", dsc->drm->pic_width, dsc->drm->pic_height);
+
+		/* we do the calculations for dsc parameters here so that
+		 * panel can use these parameters
+		 */
+		dsi_populate_dsc_params(dsc);
+
+		/* Divide the display by 3 but keep back/font porch and
+		 * pulse width same
+		 */
+		h_total -= hdisplay;
+		hdisplay /= 3;
+		h_total += hdisplay;
+		ha_end = ha_start + hdisplay;
+	}
+
 	if (msm_host->mode_flags & MIPI_DSI_MODE_VIDEO) {
+		if (msm_host->dsc)
+			dsi_update_dsc_timing(msm_host, false, mode->hdisplay);
+
 		dsi_write(msm_host, REG_DSI_ACTIVE_H,
 			DSI_ACTIVE_H_START(ha_start) |
 			DSI_ACTIVE_H_END(ha_end));
@@ -963,8 +1053,14 @@  static void dsi_timing_setup(struct msm_dsi_host *msm_host, bool is_bonded_dsi)
 			DSI_ACTIVE_VSYNC_VPOS_START(vs_start) |
 			DSI_ACTIVE_VSYNC_VPOS_END(vs_end));
 	} else {		/* command mode */
+		if (msm_host->dsc)
+			dsi_update_dsc_timing(msm_host, true, mode->hdisplay);
+
 		/* image data and 1 byte write_memory_start cmd */
-		wc = hdisplay * dsi_get_bpp(msm_host->format) / 8 + 1;
+		if (!msm_host->dsc)
+			wc = hdisplay * dsi_get_bpp(msm_host->format) / 8 + 1;
+		else
+			wc = mode->hdisplay / 2 + 1;
 
 		dsi_write(msm_host, REG_DSI_CMD_MDP_STREAM0_CTRL,
 			DSI_CMD_MDP_STREAM0_CTRL_WORD_COUNT(wc) |