Message ID | 20220404163436.956875-15-vkoul@kernel.org (mailing list archive) |
---|---|
State | New, archived |
Headers | show |
Series | drm/msm: Add Display Stream Compression Support | expand |
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 >
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
On 04/04/2022 19:34, Vinod Koul 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> > --- > 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); reg_ctrl, as reported by testing robot > + 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) |
On 06-04-22, 02:42, Dmitry Baryshkov wrote: > On 04/04/2022 19:34, Vinod Koul 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> > > --- > > 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); > > reg_ctrl, as reported by testing robot Yes, I did run W=1 check for the patches, with gcc I do not see this warning :( I have fixed and will send updated revision shortly
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) |