Message ID | 20210715065203.709914-11-vkoul@kernel.org |
---|---|
State | Superseded |
Headers | show |
Series | [01/11] drm/msm/dsi: add support for dsc data | expand |
Hi Vinod, I love your patch! Perhaps something to improve: [auto build test WARNING on v5.13] [cannot apply to linus/master v5.14-rc1 next-20210716] [If your patch is applied to the wrong git tree, kindly drop us a note. And when submitting patch, we suggest to use '--base' as documented in https://git-scm.com/docs/git-format-patch] url: https://github.com/0day-ci/linux/commits/Vinod-Koul/drm-msm-Add-Display-Stream-Compression-Support/20210715-145540 base: 62fb9874f5da54fdb243003b386128037319b219 config: arm-defconfig (attached as .config) compiler: arm-linux-gnueabi-gcc (GCC) 10.3.0 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/0day-ci/linux/commit/67410f51d0cd25256b7926c30f27071291244ef3 git remote add linux-review https://github.com/0day-ci/linux git fetch --no-tags linux-review Vinod-Koul/drm-msm-Add-Display-Stream-Compression-Support/20210715-145540 git checkout 67410f51d0cd25256b7926c30f27071291244ef3 # save the attached .config to linux build tree COMPILER_INSTALL_PATH=$HOME/0day COMPILER=gcc-10.3.0 make.cross ARCH=arm 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: In function 'dsi_timing_setup': >> drivers/gpu/drm/msm/dsi/dsi_host.c:1022:41: warning: variable 'width' set but not used [-Wunused-but-set-variable] 1022 | u32 reg, intf_width, slice_per_intf, width; | ^~~~~ vim +/width +1022 drivers/gpu/drm/msm/dsi/dsi_host.c 964 965 static void dsi_timing_setup(struct msm_dsi_host *msm_host, bool is_dual_dsi) 966 { 967 struct drm_display_mode *mode = msm_host->mode; 968 u32 hs_start = 0, vs_start = 0; /* take sync start as 0 */ 969 u32 h_total = mode->htotal; 970 u32 v_total = mode->vtotal; 971 u32 hs_end = mode->hsync_end - mode->hsync_start; 972 u32 vs_end = mode->vsync_end - mode->vsync_start; 973 u32 ha_start = h_total - mode->hsync_start; 974 u32 ha_end = ha_start + mode->hdisplay; 975 u32 va_start = v_total - mode->vsync_start; 976 u32 va_end = va_start + mode->vdisplay; 977 u32 hdisplay = mode->hdisplay; 978 u32 wc; 979 u32 data; 980 981 DBG(""); 982 983 /* 984 * For dual DSI mode, the current DRM mode has 985 * the complete width of the panel. Since, the complete 986 * panel is driven by two DSI controllers, the horizontal 987 * timings have to be split between the two dsi controllers. 988 * Adjust the DSI host timing values accordingly. 989 */ 990 if (is_dual_dsi) { 991 h_total /= 2; 992 hs_end /= 2; 993 ha_start /= 2; 994 ha_end /= 2; 995 hdisplay /= 2; 996 } 997 998 if (msm_host->dsc) { 999 struct msm_display_dsc_config *dsc = msm_host->dsc; 1000 1001 /* update dsc params with timing params */ 1002 dsi_dsc_update_pic_dim(dsc, mode->hdisplay, mode->vdisplay); 1003 DBG("Mode Width- %d x Height %d\n", dsc->drm->pic_width, dsc->drm->pic_height); 1004 1005 /* we do the calculations for dsc parameters here so that 1006 * panel can use these parameters 1007 */ 1008 dsi_populate_dsc_params(dsc); 1009 1010 /* Divide the display by 3 but keep back/font porch and 1011 * pulse width same 1012 */ 1013 h_total -= hdisplay; 1014 hdisplay /= 3; 1015 h_total += hdisplay; 1016 ha_end = ha_start + hdisplay; 1017 } 1018 1019 if (msm_host->mode_flags & MIPI_DSI_MODE_VIDEO) { 1020 if (msm_host->dsc) { 1021 struct msm_display_dsc_config *dsc = msm_host->dsc; > 1022 u32 reg, intf_width, slice_per_intf, width; 1023 u32 total_bytes_per_intf; 1024 1025 /* first calculate dsc parameters and then program 1026 * compress mode registers 1027 */ 1028 intf_width = hdisplay; 1029 slice_per_intf = DIV_ROUND_UP(intf_width, dsc->drm->slice_width); 1030 1031 /* If slice_count > slice_per_intf, then use 1 1032 * This can happen during partial update 1033 */ 1034 dsc->drm->slice_count = 1; 1035 1036 dsc->bytes_in_slice = DIV_ROUND_UP(dsc->drm->slice_width * 8, 8); 1037 total_bytes_per_intf = dsc->bytes_in_slice * slice_per_intf; 1038 1039 dsc->eol_byte_num = total_bytes_per_intf % 3; 1040 dsc->pclk_per_line = DIV_ROUND_UP(total_bytes_per_intf, 3); 1041 dsc->bytes_per_pkt = dsc->bytes_in_slice * dsc->drm->slice_count; 1042 dsc->pkt_per_line = slice_per_intf / dsc->drm->slice_count; 1043 1044 width = dsc->pclk_per_line; 1045 reg = dsc->bytes_per_pkt << 16; 1046 reg |= (0x0b << 8); /* dtype of compressed image */ 1047 1048 /* pkt_per_line: 1049 * 0 == 1 pkt 1050 * 1 == 2 pkt 1051 * 2 == 4 pkt 1052 * 3 pkt is not supported 1053 * above translates to ffs() - 1 1054 */ 1055 reg |= (ffs(dsc->pkt_per_line) - 1) << 6; 1056 1057 dsc->eol_byte_num = total_bytes_per_intf % 3; 1058 reg |= dsc->eol_byte_num << 4; 1059 reg |= 1; 1060 1061 dsi_write(msm_host, 1062 REG_DSI_VIDEO_COMPRESSION_MODE_CTRL, reg); 1063 } 1064 1065 dsi_write(msm_host, REG_DSI_ACTIVE_H, 1066 DSI_ACTIVE_H_START(ha_start) | 1067 DSI_ACTIVE_H_END(ha_end)); 1068 dsi_write(msm_host, REG_DSI_ACTIVE_V, 1069 DSI_ACTIVE_V_START(va_start) | 1070 DSI_ACTIVE_V_END(va_end)); 1071 dsi_write(msm_host, REG_DSI_TOTAL, 1072 DSI_TOTAL_H_TOTAL(h_total - 1) | 1073 DSI_TOTAL_V_TOTAL(v_total - 1)); 1074 1075 dsi_write(msm_host, REG_DSI_ACTIVE_HSYNC, 1076 DSI_ACTIVE_HSYNC_START(hs_start) | 1077 DSI_ACTIVE_HSYNC_END(hs_end)); 1078 dsi_write(msm_host, REG_DSI_ACTIVE_VSYNC_HPOS, 0); 1079 dsi_write(msm_host, REG_DSI_ACTIVE_VSYNC_VPOS, 1080 DSI_ACTIVE_VSYNC_VPOS_START(vs_start) | 1081 DSI_ACTIVE_VSYNC_VPOS_END(vs_end)); 1082 } else { /* command mode */ 1083 if (msm_host->dsc) { 1084 struct msm_display_dsc_config *dsc = msm_host->dsc; 1085 u32 reg, reg_ctrl, reg_ctrl2; 1086 u32 slice_per_intf, bytes_in_slice, total_bytes_per_intf; 1087 1088 reg_ctrl = dsi_read(msm_host, REG_DSI_COMMAND_COMPRESSION_MODE_CTRL); 1089 reg_ctrl2 = dsi_read(msm_host, REG_DSI_COMMAND_COMPRESSION_MODE_CTRL2); 1090 1091 slice_per_intf = DIV_ROUND_UP(hdisplay, dsc->drm->slice_width); 1092 bytes_in_slice = DIV_ROUND_UP(dsc->drm->slice_width * 1093 dsc->drm->bits_per_pixel, 8); 1094 dsc->drm->slice_chunk_size = bytes_in_slice; 1095 total_bytes_per_intf = dsc->bytes_in_slice * slice_per_intf; 1096 dsc->pkt_per_line = slice_per_intf / dsc->drm->slice_count; 1097 1098 reg = 0x39 << 8; 1099 reg |= ffs(dsc->pkt_per_line) << 6; 1100 1101 dsc->eol_byte_num = total_bytes_per_intf % 3; 1102 reg |= dsc->eol_byte_num << 4; 1103 reg |= 1; 1104 1105 reg_ctrl |= reg; 1106 reg_ctrl2 |= bytes_in_slice; 1107 1108 dsi_write(msm_host, REG_DSI_COMMAND_COMPRESSION_MODE_CTRL, reg); 1109 dsi_write(msm_host, REG_DSI_COMMAND_COMPRESSION_MODE_CTRL2, reg_ctrl2); 1110 } 1111 1112 /* image data and 1 byte write_memory_start cmd */ 1113 if (!msm_host->dsc) 1114 wc = hdisplay * dsi_get_bpp(msm_host->format) / 8 + 1; 1115 else 1116 wc = mode->hdisplay / 2 + 1; 1117 1118 data = DSI_CMD_MDP_STREAM0_CTRL_WORD_COUNT(wc) | 1119 DSI_CMD_MDP_STREAM0_CTRL_VIRTUAL_CHANNEL(msm_host->channel) | 1120 DSI_CMD_MDP_STREAM0_CTRL_DATA_TYPE(MIPI_DSI_DCS_LONG_WRITE); 1121 1122 dsi_write(msm_host, REG_DSI_CMD_MDP_STREAM0_CTRL, data); 1123 1124 data = DSI_CMD_MDP_STREAM0_TOTAL_H_TOTAL(hdisplay) | 1125 DSI_CMD_MDP_STREAM0_TOTAL_V_TOTAL(mode->vdisplay); 1126 dsi_write(msm_host, REG_DSI_CMD_MDP_STREAM0_TOTAL, data); 1127 } 1128 } 1129 --- 0-DAY CI Kernel Test Service, Intel Corporation https://lists.01.org/hyperkitty/list/kbuild-all@lists.01.org
On 15/07/2021 09:52, 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: Vinod Koul <vkoul@kernel.org> > --- > drivers/gpu/drm/msm/dsi/dsi.xml.h | 10 ++ > drivers/gpu/drm/msm/dsi/dsi_host.c | 142 +++++++++++++++++++++++++++-- > 2 files changed, 142 insertions(+), 10 deletions(-) > > diff --git a/drivers/gpu/drm/msm/dsi/dsi.xml.h b/drivers/gpu/drm/msm/dsi/dsi.xml.h > index 50eb4d1b8fdd..b8e9e608abfc 100644 > --- a/drivers/gpu/drm/msm/dsi/dsi.xml.h > +++ b/drivers/gpu/drm/msm/dsi/dsi.xml.h > @@ -2310,4 +2310,14 @@ static inline uint32_t REG_DSI_7nm_PHY_LN_TX_DCTRL(uint32_t i0) { return 0x00000 > > #define REG_DSI_7nm_PHY_PLL_PERF_OPTIMIZE 0x00000260 > > +#define REG_DSI_VIDEO_COMPRESSION_MODE_CTRL 0x0000029c > + > +#define REG_DSI_VIDEO_COMPRESSION_MODE_CTRL2 0x000002a0 > + > +#define REG_DSI_COMMAND_COMPRESSION_MODE_CTRL 0x000002a4 > + > +#define REG_DSI_COMMAND_COMPRESSION_MODE_CTRL2 0x000002a8 > + > +#define REG_DSI_COMMAND_COMPRESSION_MODE_CTRL3 0x000002ac > + > #endif /* DSI_XML */ Could you please post the patch to mesa3d to add these registers? > diff --git a/drivers/gpu/drm/msm/dsi/dsi_host.c b/drivers/gpu/drm/msm/dsi/dsi_host.c > index e1e5d91809b5..4e8ab1b1df8b 100644 > --- a/drivers/gpu/drm/msm/dsi/dsi_host.c > +++ b/drivers/gpu/drm/msm/dsi/dsi_host.c > @@ -942,6 +942,26 @@ static void dsi_ctrl_config(struct msm_dsi_host *msm_host, bool enable, > dsi_write(msm_host, REG_DSI_CTRL, data); > } > > +static int dsi_dsc_update_pic_dim(struct msm_display_dsc_config *dsc, > + int pic_width, int pic_height) > +{ > + if (!dsc || !pic_width || !pic_height) { > + pr_err("DSI: invalid input: pic_width: %d pic_height: %d\n", pic_width, pic_height); > + return -EINVAL; > + } > + > + if ((pic_width % dsc->drm->slice_width) || (pic_height % dsc->drm->slice_height)) { > + pr_err("DSI: pic_dim %dx%d has to be multiple of slice %dx%d\n", > + pic_width, pic_height, dsc->drm->slice_width, dsc->drm->slice_height); > + return -EINVAL; > + } > + > + dsc->drm->pic_width = pic_width; > + dsc->drm->pic_height = pic_height; > + > + return 0; > +} > + > static void dsi_timing_setup(struct msm_dsi_host *msm_host, bool is_dual_dsi) > { > struct drm_display_mode *mode = msm_host->mode; > @@ -956,6 +976,7 @@ static void dsi_timing_setup(struct msm_dsi_host *msm_host, bool is_dual_dsi) > u32 va_end = va_start + mode->vdisplay; > u32 hdisplay = mode->hdisplay; > u32 wc; > + u32 data; > > DBG(""); > > @@ -974,7 +995,73 @@ static void dsi_timing_setup(struct msm_dsi_host *msm_host, bool is_dual_dsi) > hdisplay /= 2; > } > > + if (msm_host->dsc) { > + struct msm_display_dsc_config *dsc = msm_host->dsc; > + > + /* update dsc params with timing params */ > + dsi_dsc_update_pic_dim(dsc, mode->hdisplay, mode->vdisplay); > + DBG("Mode Width- %d x Height %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) { > + struct msm_display_dsc_config *dsc = msm_host->dsc; > + u32 reg, intf_width, slice_per_intf, width; > + u32 total_bytes_per_intf; > + > + /* 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_count > slice_per_intf, then use 1 > + * This can happen during partial update > + */ > + dsc->drm->slice_count = 1; > + > + dsc->bytes_in_slice = DIV_ROUND_UP(dsc->drm->slice_width * 8, 8); > + total_bytes_per_intf = dsc->bytes_in_slice * slice_per_intf; > + > + dsc->eol_byte_num = total_bytes_per_intf % 3; > + dsc->pclk_per_line = DIV_ROUND_UP(total_bytes_per_intf, 3); > + dsc->bytes_per_pkt = dsc->bytes_in_slice * dsc->drm->slice_count; > + dsc->pkt_per_line = slice_per_intf / dsc->drm->slice_count; > + > + width = dsc->pclk_per_line; > + reg = dsc->bytes_per_pkt << 16; > + reg |= (0x0b << 8); /* dtype of compressed image */ > + > + /* pkt_per_line: > + * 0 == 1 pkt > + * 1 == 2 pkt > + * 2 == 4 pkt > + * 3 pkt is not supported > + * above translates to ffs() - 1 > + */ > + reg |= (ffs(dsc->pkt_per_line) - 1) << 6; > + > + dsc->eol_byte_num = total_bytes_per_intf % 3; > + reg |= dsc->eol_byte_num << 4; > + reg |= 1; > + > + dsi_write(msm_host, > + REG_DSI_VIDEO_COMPRESSION_MODE_CTRL, reg); > + } > + > dsi_write(msm_host, REG_DSI_ACTIVE_H, > DSI_ACTIVE_H_START(ha_start) | > DSI_ACTIVE_H_END(ha_end)); > @@ -993,19 +1080,50 @@ static void dsi_timing_setup(struct msm_dsi_host *msm_host, bool is_dual_dsi) > DSI_ACTIVE_VSYNC_VPOS_START(vs_start) | > DSI_ACTIVE_VSYNC_VPOS_END(vs_end)); > } else { /* command mode */ > + if (msm_host->dsc) { > + struct msm_display_dsc_config *dsc = msm_host->dsc; > + u32 reg, reg_ctrl, reg_ctrl2; > + u32 slice_per_intf, bytes_in_slice, total_bytes_per_intf; > + > + reg_ctrl = dsi_read(msm_host, REG_DSI_COMMAND_COMPRESSION_MODE_CTRL); > + reg_ctrl2 = dsi_read(msm_host, REG_DSI_COMMAND_COMPRESSION_MODE_CTRL2); > + > + 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 = dsc->bytes_in_slice * slice_per_intf; > + dsc->pkt_per_line = slice_per_intf / dsc->drm->slice_count; > + > + reg = 0x39 << 8; > + reg |= ffs(dsc->pkt_per_line) << 6; > + > + dsc->eol_byte_num = total_bytes_per_intf % 3; > + reg |= dsc->eol_byte_num << 4; > + reg |= 1; > + > + reg_ctrl |= reg; > + reg_ctrl2 |= 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); > + } > + > /* 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) | > - DSI_CMD_MDP_STREAM0_CTRL_VIRTUAL_CHANNEL( > - msm_host->channel) | > - DSI_CMD_MDP_STREAM0_CTRL_DATA_TYPE( > - MIPI_DSI_DCS_LONG_WRITE)); > + data = DSI_CMD_MDP_STREAM0_CTRL_WORD_COUNT(wc) | > + DSI_CMD_MDP_STREAM0_CTRL_VIRTUAL_CHANNEL(msm_host->channel) | > + DSI_CMD_MDP_STREAM0_CTRL_DATA_TYPE(MIPI_DSI_DCS_LONG_WRITE); > > - dsi_write(msm_host, REG_DSI_CMD_MDP_STREAM0_TOTAL, > - DSI_CMD_MDP_STREAM0_TOTAL_H_TOTAL(hdisplay) | > - DSI_CMD_MDP_STREAM0_TOTAL_V_TOTAL(mode->vdisplay)); > + dsi_write(msm_host, REG_DSI_CMD_MDP_STREAM0_CTRL, data); > + > + data = DSI_CMD_MDP_STREAM0_TOTAL_H_TOTAL(hdisplay) | > + DSI_CMD_MDP_STREAM0_TOTAL_V_TOTAL(mode->vdisplay); > + dsi_write(msm_host, REG_DSI_CMD_MDP_STREAM0_TOTAL, data); Could you please separate this cleanup away. > } > } > > @@ -2074,6 +2192,7 @@ int msm_dsi_host_modeset_init(struct mipi_dsi_host *host, > struct msm_dsi_host *msm_host = to_msm_dsi_host(host); > const struct msm_dsi_cfg_handler *cfg_hnd = msm_host->cfg_hnd; > struct platform_device *pdev = msm_host->pdev; > + struct msm_drm_private *priv; > int ret; > > msm_host->irq = irq_of_parse_and_map(pdev->dev.of_node, 0); > @@ -2093,6 +2212,9 @@ int msm_dsi_host_modeset_init(struct mipi_dsi_host *host, > } > > msm_host->dev = dev; > + priv = dev->dev_private; > + priv->dsc = msm_host->dsc; I'd prefer not to push dsc config into msm_drm_private and to get it as necessary using msm_dsi function calls. > + > ret = cfg_hnd->ops->tx_buf_alloc(msm_host, SZ_4K); > if (ret) { > pr_err("%s: alloc tx gem obj failed, %d\n", __func__, ret); > -- With best wishes Dmitry
On 2021-07-14 23:52, 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: Vinod Koul <vkoul@kernel.org> same comments as dmitry on this one: https://patchwork.freedesktop.org/patch/444082/?series=90413&rev=2 nothing more to add. > --- > drivers/gpu/drm/msm/dsi/dsi.xml.h | 10 ++ > drivers/gpu/drm/msm/dsi/dsi_host.c | 142 +++++++++++++++++++++++++++-- > 2 files changed, 142 insertions(+), 10 deletions(-) > > diff --git a/drivers/gpu/drm/msm/dsi/dsi.xml.h > b/drivers/gpu/drm/msm/dsi/dsi.xml.h > index 50eb4d1b8fdd..b8e9e608abfc 100644 > --- a/drivers/gpu/drm/msm/dsi/dsi.xml.h > +++ b/drivers/gpu/drm/msm/dsi/dsi.xml.h > @@ -2310,4 +2310,14 @@ static inline uint32_t > REG_DSI_7nm_PHY_LN_TX_DCTRL(uint32_t i0) { return 0x00000 > > #define REG_DSI_7nm_PHY_PLL_PERF_OPTIMIZE 0x00000260 > > +#define REG_DSI_VIDEO_COMPRESSION_MODE_CTRL 0x0000029c > + > +#define REG_DSI_VIDEO_COMPRESSION_MODE_CTRL2 0x000002a0 > + > +#define REG_DSI_COMMAND_COMPRESSION_MODE_CTRL 0x000002a4 > + > +#define REG_DSI_COMMAND_COMPRESSION_MODE_CTRL2 0x000002a8 > + > +#define REG_DSI_COMMAND_COMPRESSION_MODE_CTRL3 0x000002ac > + > #endif /* DSI_XML */ > diff --git a/drivers/gpu/drm/msm/dsi/dsi_host.c > b/drivers/gpu/drm/msm/dsi/dsi_host.c > index e1e5d91809b5..4e8ab1b1df8b 100644 > --- a/drivers/gpu/drm/msm/dsi/dsi_host.c > +++ b/drivers/gpu/drm/msm/dsi/dsi_host.c > @@ -942,6 +942,26 @@ static void dsi_ctrl_config(struct msm_dsi_host > *msm_host, bool enable, > dsi_write(msm_host, REG_DSI_CTRL, data); > } > > +static int dsi_dsc_update_pic_dim(struct msm_display_dsc_config *dsc, > + int pic_width, int pic_height) > +{ > + if (!dsc || !pic_width || !pic_height) { > + pr_err("DSI: invalid input: pic_width: %d pic_height: %d\n", > pic_width, pic_height); > + return -EINVAL; > + } > + > + if ((pic_width % dsc->drm->slice_width) || (pic_height % > dsc->drm->slice_height)) { > + pr_err("DSI: pic_dim %dx%d has to be multiple of slice %dx%d\n", > + pic_width, pic_height, dsc->drm->slice_width, > dsc->drm->slice_height); > + return -EINVAL; > + } > + > + dsc->drm->pic_width = pic_width; > + dsc->drm->pic_height = pic_height; > + > + return 0; > +} > + > static void dsi_timing_setup(struct msm_dsi_host *msm_host, bool > is_dual_dsi) > { > struct drm_display_mode *mode = msm_host->mode; > @@ -956,6 +976,7 @@ static void dsi_timing_setup(struct msm_dsi_host > *msm_host, bool is_dual_dsi) > u32 va_end = va_start + mode->vdisplay; > u32 hdisplay = mode->hdisplay; > u32 wc; > + u32 data; > > DBG(""); > > @@ -974,7 +995,73 @@ static void dsi_timing_setup(struct msm_dsi_host > *msm_host, bool is_dual_dsi) > hdisplay /= 2; > } > > + if (msm_host->dsc) { > + struct msm_display_dsc_config *dsc = msm_host->dsc; > + > + /* update dsc params with timing params */ > + dsi_dsc_update_pic_dim(dsc, mode->hdisplay, mode->vdisplay); > + DBG("Mode Width- %d x Height %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) { > + struct msm_display_dsc_config *dsc = msm_host->dsc; > + u32 reg, intf_width, slice_per_intf, width; > + u32 total_bytes_per_intf; > + > + /* 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_count > slice_per_intf, then use 1 > + * This can happen during partial update > + */ > + dsc->drm->slice_count = 1; > + > + dsc->bytes_in_slice = DIV_ROUND_UP(dsc->drm->slice_width * 8, 8); > + total_bytes_per_intf = dsc->bytes_in_slice * slice_per_intf; > + > + dsc->eol_byte_num = total_bytes_per_intf % 3; > + dsc->pclk_per_line = DIV_ROUND_UP(total_bytes_per_intf, 3); > + dsc->bytes_per_pkt = dsc->bytes_in_slice * dsc->drm->slice_count; > + dsc->pkt_per_line = slice_per_intf / dsc->drm->slice_count; > + > + width = dsc->pclk_per_line; > + reg = dsc->bytes_per_pkt << 16; > + reg |= (0x0b << 8); /* dtype of compressed image */ > + > + /* pkt_per_line: > + * 0 == 1 pkt > + * 1 == 2 pkt > + * 2 == 4 pkt > + * 3 pkt is not supported > + * above translates to ffs() - 1 > + */ > + reg |= (ffs(dsc->pkt_per_line) - 1) << 6; > + > + dsc->eol_byte_num = total_bytes_per_intf % 3; > + reg |= dsc->eol_byte_num << 4; > + reg |= 1; > + > + dsi_write(msm_host, > + REG_DSI_VIDEO_COMPRESSION_MODE_CTRL, reg); > + } > + > dsi_write(msm_host, REG_DSI_ACTIVE_H, > DSI_ACTIVE_H_START(ha_start) | > DSI_ACTIVE_H_END(ha_end)); > @@ -993,19 +1080,50 @@ static void dsi_timing_setup(struct > msm_dsi_host *msm_host, bool is_dual_dsi) > DSI_ACTIVE_VSYNC_VPOS_START(vs_start) | > DSI_ACTIVE_VSYNC_VPOS_END(vs_end)); > } else { /* command mode */ > + if (msm_host->dsc) { > + struct msm_display_dsc_config *dsc = msm_host->dsc; > + u32 reg, reg_ctrl, reg_ctrl2; > + u32 slice_per_intf, bytes_in_slice, total_bytes_per_intf; > + > + reg_ctrl = dsi_read(msm_host, > REG_DSI_COMMAND_COMPRESSION_MODE_CTRL); > + reg_ctrl2 = dsi_read(msm_host, > REG_DSI_COMMAND_COMPRESSION_MODE_CTRL2); > + > + 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 = dsc->bytes_in_slice * slice_per_intf; > + dsc->pkt_per_line = slice_per_intf / dsc->drm->slice_count; > + > + reg = 0x39 << 8; > + reg |= ffs(dsc->pkt_per_line) << 6; > + > + dsc->eol_byte_num = total_bytes_per_intf % 3; > + reg |= dsc->eol_byte_num << 4; > + reg |= 1; > + > + reg_ctrl |= reg; > + reg_ctrl2 |= 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); > + } > + > /* 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) | > - DSI_CMD_MDP_STREAM0_CTRL_VIRTUAL_CHANNEL( > - msm_host->channel) | > - DSI_CMD_MDP_STREAM0_CTRL_DATA_TYPE( > - MIPI_DSI_DCS_LONG_WRITE)); > + data = DSI_CMD_MDP_STREAM0_CTRL_WORD_COUNT(wc) | > + DSI_CMD_MDP_STREAM0_CTRL_VIRTUAL_CHANNEL(msm_host->channel) | > + DSI_CMD_MDP_STREAM0_CTRL_DATA_TYPE(MIPI_DSI_DCS_LONG_WRITE); > > - dsi_write(msm_host, REG_DSI_CMD_MDP_STREAM0_TOTAL, > - DSI_CMD_MDP_STREAM0_TOTAL_H_TOTAL(hdisplay) | > - DSI_CMD_MDP_STREAM0_TOTAL_V_TOTAL(mode->vdisplay)); > + dsi_write(msm_host, REG_DSI_CMD_MDP_STREAM0_CTRL, data); > + > + data = DSI_CMD_MDP_STREAM0_TOTAL_H_TOTAL(hdisplay) | > + DSI_CMD_MDP_STREAM0_TOTAL_V_TOTAL(mode->vdisplay); > + dsi_write(msm_host, REG_DSI_CMD_MDP_STREAM0_TOTAL, data); > } > } > > @@ -2074,6 +2192,7 @@ int msm_dsi_host_modeset_init(struct > mipi_dsi_host *host, > struct msm_dsi_host *msm_host = to_msm_dsi_host(host); > const struct msm_dsi_cfg_handler *cfg_hnd = msm_host->cfg_hnd; > struct platform_device *pdev = msm_host->pdev; > + struct msm_drm_private *priv; > int ret; > > msm_host->irq = irq_of_parse_and_map(pdev->dev.of_node, 0); > @@ -2093,6 +2212,9 @@ int msm_dsi_host_modeset_init(struct > mipi_dsi_host *host, > } > > msm_host->dev = dev; > + priv = dev->dev_private; > + priv->dsc = msm_host->dsc; > + > ret = cfg_hnd->ops->tx_buf_alloc(msm_host, SZ_4K); > if (ret) { > pr_err("%s: alloc tx gem obj failed, %d\n", __func__, ret);
diff --git a/drivers/gpu/drm/msm/dsi/dsi.xml.h b/drivers/gpu/drm/msm/dsi/dsi.xml.h index 50eb4d1b8fdd..b8e9e608abfc 100644 --- a/drivers/gpu/drm/msm/dsi/dsi.xml.h +++ b/drivers/gpu/drm/msm/dsi/dsi.xml.h @@ -2310,4 +2310,14 @@ static inline uint32_t REG_DSI_7nm_PHY_LN_TX_DCTRL(uint32_t i0) { return 0x00000 #define REG_DSI_7nm_PHY_PLL_PERF_OPTIMIZE 0x00000260 +#define REG_DSI_VIDEO_COMPRESSION_MODE_CTRL 0x0000029c + +#define REG_DSI_VIDEO_COMPRESSION_MODE_CTRL2 0x000002a0 + +#define REG_DSI_COMMAND_COMPRESSION_MODE_CTRL 0x000002a4 + +#define REG_DSI_COMMAND_COMPRESSION_MODE_CTRL2 0x000002a8 + +#define REG_DSI_COMMAND_COMPRESSION_MODE_CTRL3 0x000002ac + #endif /* DSI_XML */ diff --git a/drivers/gpu/drm/msm/dsi/dsi_host.c b/drivers/gpu/drm/msm/dsi/dsi_host.c index e1e5d91809b5..4e8ab1b1df8b 100644 --- a/drivers/gpu/drm/msm/dsi/dsi_host.c +++ b/drivers/gpu/drm/msm/dsi/dsi_host.c @@ -942,6 +942,26 @@ static void dsi_ctrl_config(struct msm_dsi_host *msm_host, bool enable, dsi_write(msm_host, REG_DSI_CTRL, data); } +static int dsi_dsc_update_pic_dim(struct msm_display_dsc_config *dsc, + int pic_width, int pic_height) +{ + if (!dsc || !pic_width || !pic_height) { + pr_err("DSI: invalid input: pic_width: %d pic_height: %d\n", pic_width, pic_height); + return -EINVAL; + } + + if ((pic_width % dsc->drm->slice_width) || (pic_height % dsc->drm->slice_height)) { + pr_err("DSI: pic_dim %dx%d has to be multiple of slice %dx%d\n", + pic_width, pic_height, dsc->drm->slice_width, dsc->drm->slice_height); + return -EINVAL; + } + + dsc->drm->pic_width = pic_width; + dsc->drm->pic_height = pic_height; + + return 0; +} + static void dsi_timing_setup(struct msm_dsi_host *msm_host, bool is_dual_dsi) { struct drm_display_mode *mode = msm_host->mode; @@ -956,6 +976,7 @@ static void dsi_timing_setup(struct msm_dsi_host *msm_host, bool is_dual_dsi) u32 va_end = va_start + mode->vdisplay; u32 hdisplay = mode->hdisplay; u32 wc; + u32 data; DBG(""); @@ -974,7 +995,73 @@ static void dsi_timing_setup(struct msm_dsi_host *msm_host, bool is_dual_dsi) hdisplay /= 2; } + if (msm_host->dsc) { + struct msm_display_dsc_config *dsc = msm_host->dsc; + + /* update dsc params with timing params */ + dsi_dsc_update_pic_dim(dsc, mode->hdisplay, mode->vdisplay); + DBG("Mode Width- %d x Height %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) { + struct msm_display_dsc_config *dsc = msm_host->dsc; + u32 reg, intf_width, slice_per_intf, width; + u32 total_bytes_per_intf; + + /* 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_count > slice_per_intf, then use 1 + * This can happen during partial update + */ + dsc->drm->slice_count = 1; + + dsc->bytes_in_slice = DIV_ROUND_UP(dsc->drm->slice_width * 8, 8); + total_bytes_per_intf = dsc->bytes_in_slice * slice_per_intf; + + dsc->eol_byte_num = total_bytes_per_intf % 3; + dsc->pclk_per_line = DIV_ROUND_UP(total_bytes_per_intf, 3); + dsc->bytes_per_pkt = dsc->bytes_in_slice * dsc->drm->slice_count; + dsc->pkt_per_line = slice_per_intf / dsc->drm->slice_count; + + width = dsc->pclk_per_line; + reg = dsc->bytes_per_pkt << 16; + reg |= (0x0b << 8); /* dtype of compressed image */ + + /* pkt_per_line: + * 0 == 1 pkt + * 1 == 2 pkt + * 2 == 4 pkt + * 3 pkt is not supported + * above translates to ffs() - 1 + */ + reg |= (ffs(dsc->pkt_per_line) - 1) << 6; + + dsc->eol_byte_num = total_bytes_per_intf % 3; + reg |= dsc->eol_byte_num << 4; + reg |= 1; + + dsi_write(msm_host, + REG_DSI_VIDEO_COMPRESSION_MODE_CTRL, reg); + } + dsi_write(msm_host, REG_DSI_ACTIVE_H, DSI_ACTIVE_H_START(ha_start) | DSI_ACTIVE_H_END(ha_end)); @@ -993,19 +1080,50 @@ static void dsi_timing_setup(struct msm_dsi_host *msm_host, bool is_dual_dsi) DSI_ACTIVE_VSYNC_VPOS_START(vs_start) | DSI_ACTIVE_VSYNC_VPOS_END(vs_end)); } else { /* command mode */ + if (msm_host->dsc) { + struct msm_display_dsc_config *dsc = msm_host->dsc; + u32 reg, reg_ctrl, reg_ctrl2; + u32 slice_per_intf, bytes_in_slice, total_bytes_per_intf; + + reg_ctrl = dsi_read(msm_host, REG_DSI_COMMAND_COMPRESSION_MODE_CTRL); + reg_ctrl2 = dsi_read(msm_host, REG_DSI_COMMAND_COMPRESSION_MODE_CTRL2); + + 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 = dsc->bytes_in_slice * slice_per_intf; + dsc->pkt_per_line = slice_per_intf / dsc->drm->slice_count; + + reg = 0x39 << 8; + reg |= ffs(dsc->pkt_per_line) << 6; + + dsc->eol_byte_num = total_bytes_per_intf % 3; + reg |= dsc->eol_byte_num << 4; + reg |= 1; + + reg_ctrl |= reg; + reg_ctrl2 |= 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); + } + /* 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) | - DSI_CMD_MDP_STREAM0_CTRL_VIRTUAL_CHANNEL( - msm_host->channel) | - DSI_CMD_MDP_STREAM0_CTRL_DATA_TYPE( - MIPI_DSI_DCS_LONG_WRITE)); + data = DSI_CMD_MDP_STREAM0_CTRL_WORD_COUNT(wc) | + DSI_CMD_MDP_STREAM0_CTRL_VIRTUAL_CHANNEL(msm_host->channel) | + DSI_CMD_MDP_STREAM0_CTRL_DATA_TYPE(MIPI_DSI_DCS_LONG_WRITE); - dsi_write(msm_host, REG_DSI_CMD_MDP_STREAM0_TOTAL, - DSI_CMD_MDP_STREAM0_TOTAL_H_TOTAL(hdisplay) | - DSI_CMD_MDP_STREAM0_TOTAL_V_TOTAL(mode->vdisplay)); + dsi_write(msm_host, REG_DSI_CMD_MDP_STREAM0_CTRL, data); + + data = DSI_CMD_MDP_STREAM0_TOTAL_H_TOTAL(hdisplay) | + DSI_CMD_MDP_STREAM0_TOTAL_V_TOTAL(mode->vdisplay); + dsi_write(msm_host, REG_DSI_CMD_MDP_STREAM0_TOTAL, data); } } @@ -2074,6 +2192,7 @@ int msm_dsi_host_modeset_init(struct mipi_dsi_host *host, struct msm_dsi_host *msm_host = to_msm_dsi_host(host); const struct msm_dsi_cfg_handler *cfg_hnd = msm_host->cfg_hnd; struct platform_device *pdev = msm_host->pdev; + struct msm_drm_private *priv; int ret; msm_host->irq = irq_of_parse_and_map(pdev->dev.of_node, 0); @@ -2093,6 +2212,9 @@ int msm_dsi_host_modeset_init(struct mipi_dsi_host *host, } msm_host->dev = dev; + priv = dev->dev_private; + priv->dsc = msm_host->dsc; + ret = cfg_hnd->ops->tx_buf_alloc(msm_host, SZ_4K); if (ret) { pr_err("%s: alloc tx gem obj failed, %d\n", __func__, ret);
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: Vinod Koul <vkoul@kernel.org> --- drivers/gpu/drm/msm/dsi/dsi.xml.h | 10 ++ drivers/gpu/drm/msm/dsi/dsi_host.c | 142 +++++++++++++++++++++++++++-- 2 files changed, 142 insertions(+), 10 deletions(-) -- 2.31.1