From 08d4cb208f2462833d9bbc73fd00f2d01ebba97a Mon Sep 17 00:00:00 2001 From: Vinod Koul Date: Tue, 11 Feb 2020 23:17:55 +0530 Subject: drm:msm:dsi: update dsc config settings Update the DSC config to latest one and parse the DT for other params too Also set panel and msm_drv dsc pointers after allocating Signed-off-by: Vinod Koul --- drivers/gpu/drm/msm/dsi/dsi_host.c | 235 ++++++++++++++++++++++++++----------- 1 file changed, 168 insertions(+), 67 deletions(-) diff --git a/drivers/gpu/drm/msm/dsi/dsi_host.c b/drivers/gpu/drm/msm/dsi/dsi_host.c index 53659eb88c1b..19a0999f47fc 100644 --- a/drivers/gpu/drm/msm/dsi/dsi_host.c +++ b/drivers/gpu/drm/msm/dsi/dsi_host.c @@ -93,14 +93,6 @@ static int dsi_get_version(const void __iomem *base, u32 *major, u32 *minor) DSI_CLK_CTRL_BYTECLK_ON | DSI_CLK_CTRL_ESCCLK_ON | \ DSI_CLK_CTRL_FORCE_ON_DYN_AHBM_HCLK) -struct msm_dsc_config { - u32 slice_height; - u32 slice_width; - u32 slice_per_pkt; - u32 bit_per_component; - u32 bit_per_pixel; -}; - struct msm_dsi_host { struct mipi_dsi_host base; @@ -164,6 +156,7 @@ struct msm_dsi_host { struct regmap *sfpb; struct drm_display_mode *mode; + struct msm_display_dsc_config *dsc; /* connected device info */ struct device_node *device_node; @@ -176,10 +169,6 @@ struct msm_dsi_host { int dlane_swap; int num_data_lanes; - /* dsc config via DT */ - bool is_dsc_enabled; - struct msm_dsc_config *dsc_config; - u32 dma_cmd_ctrl_restore; bool registered; @@ -983,41 +972,39 @@ static void dsi_timing_setup(struct msm_dsi_host *msm_host, bool is_dual_dsi) hdisplay /= 2; } + pr_err("VK: msm_host->mode_flags: %lx\n", msm_host->mode_flags); if (msm_host->mode_flags & MIPI_DSI_MODE_VIDEO) { - if (msm_host->is_dsc_enabled) { - struct msm_dsc_config *dsc = msm_host->dsc_config; + + pr_err("VKA: in %s doing MIPI_DSI_MODE_VIDEO\n", __func__); + + if (msm_host->dsc) { + struct msm_display_dsc_config *dsc = msm_host->dsc; u32 reg, intf_width, slice_per_intf, width; - u32 bytes_in_slice, total_bytes_per_intf, bytes_per_pkt; - u32 eol_byte_num, pclk_per_line, slice_per_pkt, pkt_per_line; + 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->slice_width); + slice_per_intf = DIV_ROUND_UP(intf_width, dsc->drm.slice_width); /* If slice_per_pkt > slice_per_intf, then use 1 * This can happen during partial update */ - slice_per_pkt = dsc->slice_per_pkt; - if (slice_per_pkt > slice_per_intf) - slice_per_pkt = 1; - - bytes_in_slice = DIV_ROUND_UP( - dsc->slice_width * - dsi_get_bpp(msm_host->format), 8); - total_bytes_per_intf = bytes_in_slice * slice_per_intf; + if (dsc->slice_per_pkt > slice_per_intf) + dsc->slice_per_pkt = 1; - eol_byte_num = total_bytes_per_intf % 3; - pclk_per_line = DIV_ROUND_UP(total_bytes_per_intf, 3); - bytes_per_pkt = bytes_in_slice * slice_per_pkt; - pkt_per_line = slice_per_intf / slice_per_pkt; + dsc->bytes_in_slice = DIV_ROUND_UP(dsc->drm.slice_width * + dsi_get_bpp(msm_host->format), 8); + total_bytes_per_intf = dsc->bytes_in_slice * slice_per_intf; - reg = mode->clock << 16; - reg |= (0x0b << 8); /* dtype of compressed image */ + 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->slice_per_pkt; + dsc->pkt_per_line = slice_per_intf / dsc->slice_per_pkt; - width = pclk_per_line; - reg = bytes_per_pkt << 16; + width = dsc->pclk_per_line; + reg = dsc->bytes_per_pkt << 16; reg |= (0x0b << 8); /* dtype of compressed image */ /* pkt_per_line: @@ -1027,10 +1014,10 @@ static void dsi_timing_setup(struct msm_dsi_host *msm_host, bool is_dual_dsi) * 3 pkt is not supported * above translates to ffs() - 1 */ - reg = (ffs(pkt_per_line) - 1) << 6; + reg = (ffs(dsc->pkt_per_line) - 1) << 6; - eol_byte_num = total_bytes_per_intf % 3; - reg |= eol_byte_num << 4; + dsc->eol_byte_num = total_bytes_per_intf % 3; + reg |= dsc->eol_byte_num << 4; reg |= 1; dsi_write(msm_host, @@ -1055,28 +1042,28 @@ 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->is_dsc_enabled) { - struct msm_dsc_config *dsc = msm_host->dsc_config; + pr_err("VKA: in %s in cmd mode\n", __func__); + + 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; - u32 pkt_per_line, eol_byte_num; 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->slice_width); - bytes_in_slice = DIV_ROUND_UP( - dsc->slice_width * - dsi_get_bpp(msm_host->format), 8); - total_bytes_per_intf = bytes_in_slice * slice_per_intf; - pkt_per_line = slice_per_intf / dsc->slice_per_pkt; + slice_per_intf = DIV_ROUND_UP(hdisplay, dsc->drm.slice_width); + bytes_in_slice = DIV_ROUND_UP(dsc->drm.slice_width * + dsi_get_bpp(msm_host->format), 8); + total_bytes_per_intf = dsc->bytes_in_slice * slice_per_intf; + dsc->pkt_per_line = slice_per_intf / dsc->slice_per_pkt; reg = 0x39 << 8; - reg = (ffs(pkt_per_line) - 1) << 6; + reg = (ffs(dsc->pkt_per_line) - 1) << 6; - eol_byte_num = total_bytes_per_intf % 3; - reg |= eol_byte_num << 4; + dsc->eol_byte_num = total_bytes_per_intf % 3; + reg |= dsc->eol_byte_num << 4; reg |= 1; reg_ctrl |= reg; @@ -1701,6 +1688,7 @@ static int dsi_host_attach(struct mipi_dsi_host *host, struct mipi_dsi_device *dsi) { struct msm_dsi_host *msm_host = to_msm_dsi_host(host); + struct drm_panel *panel; int ret; if (dsi->lanes > msm_host->num_data_lanes) @@ -1720,6 +1708,10 @@ static int dsi_host_attach(struct mipi_dsi_host *host, if (msm_host->dev) queue_work(msm_host->workqueue, &msm_host->hpd_work); + panel = msm_dsi_host_get_panel(host); + if (panel) + panel->dsc = &msm_host->dsc->drm; + return 0; } @@ -1840,58 +1832,160 @@ static int dsi_host_parse_lane_data(struct msm_dsi_host *msm_host, return -EINVAL; } +static u32 dsi_dsc_rc_buf_thresh[DSC_NUM_BUF_RANGES - 1] = { + 0x0e, 0x1c, 0x2a, 0x38, 0x46, 0x54, 0x62, + 0x69, 0x70, 0x77, 0x79, 0x7b, 0x7d, 0x7e +}; + +/* only 8bpc, 8bpp added */ +static char min_qp[DSC_NUM_BUF_RANGES] = { + 0, 0, 1, 1, 3, 3, 3, 3, 3, 3, 5, 5, 5, 7, 13 +}; + +static char max_qp[DSC_NUM_BUF_RANGES] = { + 4, 4, 5, 6, 7, 7, 7, 8, 9, 10, 11, 12, 13, 13, 15 +}; + +static char bpg_offset[DSC_NUM_BUF_RANGES] = { + 2, 0, 0, -2, -4, -6, -8, -8, -8, -10, -10, -12, -12, -12, -12 +}; + +static int dsi_populate_dsc_params(struct msm_display_dsc_config *dsc) +{ + int i; + + dsc->drm.rc_model_size = 8192; + dsc->drm.first_line_bpg_offset = 15; + dsc->drm.rc_edge_factor = 6; + dsc->drm.rc_tgt_offset_high = 3; + dsc->drm.rc_tgt_offset_low = 3; + dsc->drm.simple_422 = 0; + dsc->drm.convert_rgb = 1; + dsc->drm.vbr_enable = 0; + + /* handle only bpp = bpc = 8 */ + for (i = 0; i < DSC_NUM_BUF_RANGES -1 ; i++) + dsc->drm.rc_buf_thresh[i] = dsi_dsc_rc_buf_thresh[i]; + + for (i = 0; i < DSC_NUM_BUF_RANGES; i++) { + dsc->drm.rc_range_params[i].range_min_qp = min_qp[i]; + dsc->drm.rc_range_params[i].range_max_qp = max_qp[i]; + dsc->drm.rc_range_params[i].range_bpg_offset = bpg_offset[i]; + } + + dsc->drm.initial_offset = 6144; + dsc->drm.initial_xmit_delay = 512; + dsc->drm.line_buf_depth = dsc->drm.bits_per_component + 1; + + /* bpc 8 */ + dsc->drm.flatness_min_qp = 3; + dsc->drm.flatness_max_qp = 12; + dsc->drm.rc_quant_incr_limit0 = 11; + dsc->drm.rc_quant_incr_limit1 = 11; + dsc->drm.mux_word_size = DSC_MUX_WORD_SIZE_8_10_BPC; + + /* need to call drm_dsc_compute_rc_parameters() so that rest of + * params are calculated + */ + + i = dsc->drm.slice_width % 3; + switch (i) { + case 0: + dsc->slice_last_group_size = 2; + break; + + case 1: + dsc->slice_last_group_size = 0; + break; + + case 2: + dsc->slice_last_group_size = 0; + break; + + default: + break; + } + + dsc->det_thresh_flatness = 2 << (dsc->drm.bits_per_component - 8); + + return 0; +} + static int dsi_host_parse_dsc(struct msm_dsi_host *msm_host, struct device_node *np) { struct device *dev = &msm_host->pdev->dev; - struct msm_dsc_config *dsc; + struct msm_display_dsc_config *dsc; + bool is_dsc_enabled; + u32 data; int ret; - msm_host->is_dsc_enabled = of_property_read_bool( - np, "qcom,dsc-enabled"); - if (!msm_host->is_dsc_enabled) + is_dsc_enabled = of_property_read_bool(np, "qcom,mdss-dsc-enabled"); + + if (!is_dsc_enabled) return 0; - dsc = kzalloc(sizeof(*msm_host->dsc_config), GFP_KERNEL); + dsc = kzalloc(sizeof(*dsc), GFP_KERNEL); if (!dsc) return -ENOMEM; - ret = of_property_read_u32(np, "qcom,dsc-slice-height", - &dsc->slice_height); + ret = of_property_read_u32(np, "qcom,mdss-dsc-version", &data); + if (ret) { + dsc->drm.dsc_version_major = 0x1; + dsc->drm.dsc_version_minor = 0x1; + } else { + dsc->drm.dsc_version_major = (data >> 4) & 0xf; + dsc->drm.dsc_version_minor = data & 0xf; + } + + ret = of_property_read_u32(np, "qcom,mdss-scr-version", &data); + if (ret) + dsc->scr_rev = 0; + else + dsc->scr_rev = data & 0xff; + + ret = of_property_read_u32(np, "qcom,mdss-slice-height", &data); if (ret) { DRM_DEV_ERROR(dev, "failed to read dsc slice height\n"); goto err; } + dsc->drm.slice_height = data; - ret = of_property_read_u32(np, "qcom,dsc-slice-width", - &dsc->slice_width); + ret = of_property_read_u32(np, "qcom,mdss-slice-width", &data); if (ret) { DRM_DEV_ERROR(dev, "failed to read dsc slice width\n"); goto err; } + dsc->drm.slice_width = data; - ret = of_property_read_u32(np, "qcom,dsc-slice-per-pkt", - &dsc->slice_per_pkt); + ret = of_property_read_u32(np, "qcom,mdss-slice-per-pkt", &data); if (ret) { - DRM_DEV_ERROR(dev, "failed to read dsc slice per pkt\n"); + DRM_DEV_ERROR(dev, "failed to read mdss-slice-per-pkt\n"); goto err; } + dsc->slice_per_pkt = data; - ret = of_property_read_u32(np, "qcom,dsc-bit-per-component", - &dsc->bit_per_component); + ret = of_property_read_u32(np, "qcom,mdss-bit-per-component", &data); if (ret) { - DRM_DEV_ERROR(dev, "failed to read dsc bit-per-component\n"); + DRM_DEV_ERROR(dev, "failed to read mdss-bit-per-component\n"); goto err; } + dsc->drm.bits_per_component = data; - ret = of_property_read_u32(np, "qcom,dsc-bit-per-pixel", - &dsc->bit_per_pixel); + ret = of_property_read_u32(np, "qcom,mdss-bit-per-pixel", &data); if (ret) { - DRM_DEV_ERROR(dev, "failed to read dsc bit-per-pixel\n"); + DRM_DEV_ERROR(dev, "failed to read bit-per-pixel\n"); goto err; } + dsc->drm.bits_per_pixel = data; + + dsc->drm.block_pred_enable = of_property_read_bool(np, + "qcom,mdss-block-prediction-enable"); + + dsi_populate_dsc_params(dsc); + + msm_host->dsc = dsc; - msm_host->dsc_config = dsc; return 0; err: @@ -2569,6 +2663,13 @@ int msm_dsi_host_power_on(struct mipi_dsi_host *host, msm_host->power_on = true; mutex_unlock(&msm_host->dev_mutex); + if (msm_host->dsc) { + struct drm_device *drm = msm_host->dev; + struct msm_drm_private *priv = drm->dev_private; + + priv->dsc = msm_host->dsc; + } + return 0; fail_disable_clk: -- cgit v1.2.3