From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by smtp.lore.kernel.org (Postfix) with ESMTP id B88A9C7EE23 for ; Thu, 18 May 2023 00:32:36 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S229753AbjERAcf (ORCPT ); Wed, 17 May 2023 20:32:35 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:49580 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S229458AbjERAce (ORCPT ); Wed, 17 May 2023 20:32:34 -0400 Received: from mail-lj1-x231.google.com (mail-lj1-x231.google.com [IPv6:2a00:1450:4864:20::231]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 0792E26B9 for ; Wed, 17 May 2023 17:32:31 -0700 (PDT) Received: by mail-lj1-x231.google.com with SMTP id 38308e7fff4ca-2ac735fee70so7930191fa.0 for ; Wed, 17 May 2023 17:32:30 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=linaro.org; s=google; t=1684369949; x=1686961949; h=content-transfer-encoding:in-reply-to:from:references:cc:to :content-language:subject:user-agent:mime-version:date:message-id :from:to:cc:subject:date:message-id:reply-to; bh=JGAGGyttsyY8AFtihLUDv+NIKWF7FZKnXsNzq4OJc4g=; b=qSxcBL3rOeSnnifSyaOLt9btu+qtIM93J8RRQgu5Qpym+bKvXsq29eL0EW5aYqX+Ns hg6IrtKpGt2qd+aOPRd633BO7DJpHei7fI+Fbkd24YYEr16BM4w/pM2Kgg91eAEGwAKP DoznvYaZU7AIC/ZPREureORzypWe3rqMEbpU3QjCUj0HLTgZjBPcfCMjPX4/HPiFguYp IV94jDwDwPph765bJ0Xs064i1FJRBJd/lyWUz/mhi6C8znHJvCDiUEQz1iSQc0BqtsZw lD8zutlThl20+3bO8GV2lQno2T4fBxuEP8shSBK+A2oySyJTBZCtH7ByfKz4MbLBlhsW wlVw== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20221208; t=1684369949; x=1686961949; h=content-transfer-encoding:in-reply-to:from:references:cc:to :content-language:subject:user-agent:mime-version:date:message-id :x-gm-message-state:from:to:cc:subject:date:message-id:reply-to; bh=JGAGGyttsyY8AFtihLUDv+NIKWF7FZKnXsNzq4OJc4g=; b=IABH1kCY3PpXRmAln4y1sM8Ltx28OQhpglAo6DZQe4ab5+fIFj4lCDuLmamkS2NivM nwOA/zjbEOFJbt34W+yfZezsg7vG6vnzc1BDbVnrJLr40/J0brnM3/IHTA/IqKuLP+XZ 9ON9mbXBbtqPlpG/c4WG+YUPQHHx5sHTp/kdxBRnfzuzE7IWu8B7022UCCKE36KYKluk nJPKHETThnhkFUNPSxsqYXPTkgFxzjoiTT1V+SmxzJfBoc65nDuKJ9wpvMdOdexdCyVS ltFs9q8WjIuLgY4ntsQm0+aEcCtcG4faj0UqVd9+wWC5YGHZ3RE6abakkZpkjsHGMCj+ 5cTQ== X-Gm-Message-State: AC+VfDxlQToNYEkUqz4iVtIn7cmg4DmQoIfCB+Z+7XNUsbaqpr5+dSLn zdRQPUHsbh3V5bXzmJyUmdeJgQ== X-Google-Smtp-Source: ACHHUZ77CWj/pbOTs7FC8NSq/QBFv0dDnUwOzHV3+gtB6ghLskdapB0BJzddE94FT007hlNo/vvL7A== X-Received: by 2002:a2e:b748:0:b0:2a8:b792:d7cd with SMTP id k8-20020a2eb748000000b002a8b792d7cdmr1277155ljo.4.1684369949192; Wed, 17 May 2023 17:32:29 -0700 (PDT) Received: from ?IPV6:2001:14ba:a0db:1f00::8a5? (dzdqv0yyyyyyyyyyybcwt-3.rev.dnainternet.fi. [2001:14ba:a0db:1f00::8a5]) by smtp.gmail.com with ESMTPSA id w2-20020a2e3002000000b002a8c2a4fe99sm7257ljw.28.2023.05.17.17.32.28 (version=TLS1_3 cipher=TLS_AES_128_GCM_SHA256 bits=128/128); Wed, 17 May 2023 17:32:28 -0700 (PDT) Message-ID: Date: Thu, 18 May 2023 03:32:28 +0300 MIME-Version: 1.0 User-Agent: Mozilla/5.0 (X11; Linux x86_64; rv:102.0) Gecko/20100101 Thunderbird/102.10.0 Subject: Re: [PATCH v10 5/8] drm/msm/dpu: add support for DSC encoder v1.2 engine Content-Language: en-GB To: Marijn Suijten , Kuogee Hsieh Cc: dri-devel@lists.freedesktop.org, robdclark@gmail.com, sean@poorly.run, swboyd@chromium.org, dianders@chromium.org, vkoul@kernel.org, daniel@ffwll.ch, airlied@gmail.com, agross@kernel.org, andersson@kernel.org, quic_abhinavk@quicinc.com, quic_jesszhan@quicinc.com, quic_sbillaka@quicinc.com, freedreno@lists.freedesktop.org, linux-arm-msm@vger.kernel.org, linux-kernel@vger.kernel.org References: <1684360919-28458-1-git-send-email-quic_khsieh@quicinc.com> <1684360919-28458-6-git-send-email-quic_khsieh@quicinc.com> From: Dmitry Baryshkov In-Reply-To: Content-Type: text/plain; charset=UTF-8; format=flowed Content-Transfer-Encoding: 7bit Precedence: bulk List-ID: X-Mailing-List: linux-kernel@vger.kernel.org On 18/05/2023 01:22, Marijn Suijten wrote: > On 2023-05-17 15:01:56, Kuogee Hsieh wrote: >> Add support for DSC 1.2 by providing the necessary hooks to program >> the DPU DSC 1.2 encoder. >> >> Changes in v3: >> -- fixed kernel test rebot report that "__iomem *off" is declared but not >> used at dpu_hw_dsc_config_1_2() >> -- unrolling thresh loops >> >> Changes in v4: >> -- delete DPU_DSC_HW_REV_1_1 >> -- delete off and used real register name directly >> >> Changes in v7: >> -- replace offset with sblk->enc.base >> -- replace ss with slice >> >> Changes in v8: >> -- fixed checkpatch warning >> >> Changes in v9: >> -- replaced __dsc_calc_ob_max_addr() with __dsc_calc_output_buf_max_addr() >> -- replaced variable num_ss with num_softslice >> -- remove inline from function declaration >> >> changes in v10: >> -- rewording text of changes in v9 >> -- replace DPU_DSC_NATIVE_422_EN with DPU_DSC_NATIVE_42x_EN > > Besides this rename and commit-body fix, you skipped all my other > comments in v9. Do I really have to repeat them? > >> >> Signed-off-by: Kuogee Hsieh >> Reviewed-by: Dmitry Baryshkov >> --- >> drivers/gpu/drm/msm/Makefile | 1 + >> drivers/gpu/drm/msm/disp/dpu1/dpu_hw_catalog.h | 31 +- >> drivers/gpu/drm/msm/disp/dpu1/dpu_hw_dsc.h | 14 +- >> drivers/gpu/drm/msm/disp/dpu1/dpu_hw_dsc_1_2.c | 386 +++++++++++++++++++++++++ >> drivers/gpu/drm/msm/disp/dpu1/dpu_rm.c | 7 +- >> 5 files changed, 435 insertions(+), 4 deletions(-) >> create mode 100644 drivers/gpu/drm/msm/disp/dpu1/dpu_hw_dsc_1_2.c >> >> diff --git a/drivers/gpu/drm/msm/Makefile b/drivers/gpu/drm/msm/Makefile >> index b814fc8..b9af5e4 100644 >> --- a/drivers/gpu/drm/msm/Makefile >> +++ b/drivers/gpu/drm/msm/Makefile >> @@ -65,6 +65,7 @@ msm-$(CONFIG_DRM_MSM_DPU) += \ >> disp/dpu1/dpu_hw_catalog.o \ >> disp/dpu1/dpu_hw_ctl.o \ >> disp/dpu1/dpu_hw_dsc.o \ >> + disp/dpu1/dpu_hw_dsc_1_2.o \ >> disp/dpu1/dpu_hw_interrupts.o \ >> disp/dpu1/dpu_hw_intf.o \ >> disp/dpu1/dpu_hw_lm.o \ >> diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_catalog.h b/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_catalog.h >> index 83854e8..11610f7 100644 >> --- a/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_catalog.h >> +++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_catalog.h >> @@ -1,6 +1,6 @@ >> /* SPDX-License-Identifier: GPL-2.0-only */ >> /* >> - * Copyright (c) 2022. Qualcomm Innovation Center, Inc. All rights reserved. >> + * Copyright (c) 2022-2023, Qualcomm Innovation Center, Inc. All rights reserved. >> * Copyright (c) 2015-2018, 2020 The Linux Foundation. All rights reserved. >> */ >> >> @@ -244,12 +244,18 @@ enum { >> }; >> >> /** >> - * DSC features >> + * DSC sub-blocks/features >> * @DPU_DSC_OUTPUT_CTRL Configure which PINGPONG block gets >> * the pixel output from this DSC. >> + * @DPU_DSC_HW_REV_1_2 DSC block supports DSC 1.1 and 1.2 >> + * @DPU_DSC_NATIVE_42x_EN Supports NATIVE_422_EN and NATIVE_420_EN encoding >> + * @DPU_DSC_MAX >> */ >> enum { >> DPU_DSC_OUTPUT_CTRL = 0x1, >> + DPU_DSC_HW_REV_1_2, >> + DPU_DSC_NATIVE_42x_EN, >> + DPU_DSC_MAX >> }; >> >> /** >> @@ -306,6 +312,14 @@ struct dpu_pp_blk { >> }; >> >> /** >> + * struct dpu_dsc_blk - DSC Encoder sub-blk information >> + * @info: HW register and features supported by this sub-blk >> + */ >> +struct dpu_dsc_blk { >> + DPU_HW_SUBBLK_INFO; >> +}; >> + >> +/** >> * enum dpu_qos_lut_usage - define QoS LUT use cases >> */ >> enum dpu_qos_lut_usage { >> @@ -452,6 +466,16 @@ struct dpu_pingpong_sub_blks { >> }; >> >> /** >> + * struct dpu_dsc_sub_blks - DSC sub-blks >> + * @enc: DSC encoder sub-block >> + * @ctl: DSC controller sub-block >> + */ >> +struct dpu_dsc_sub_blks { >> + struct dpu_dsc_blk enc; >> + struct dpu_dsc_blk ctl; >> +}; >> + >> +/** >> * dpu_clk_ctrl_type - Defines top level clock control signals >> */ >> enum dpu_clk_ctrl_type { >> @@ -605,10 +629,13 @@ struct dpu_merge_3d_cfg { >> * struct dpu_dsc_cfg - information of DSC blocks >> * @id enum identifying this block >> * @base register offset of this block >> + * @len: length of hardware block >> * @features bit mask identifying sub-blocks/features >> + * @sblk: sub-blocks information >> */ >> struct dpu_dsc_cfg { >> DPU_HW_BLK_INFO; >> + const struct dpu_dsc_sub_blks *sblk; >> }; >> >> /** >> diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_dsc.h b/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_dsc.h >> index 138080a..41e39d0 100644 >> --- a/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_dsc.h >> +++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_dsc.h >> @@ -1,5 +1,8 @@ >> /* SPDX-License-Identifier: GPL-2.0-only */ >> -/* Copyright (c) 2020-2022, Linaro Limited */ >> +/* >> + * Copyright (c) 2020-2022, Linaro Limited >> + * Copyright (c) 2023 Qualcomm Innovation Center, Inc. All rights reserved >> + */ >> >> #ifndef _DPU_HW_DSC_H >> #define _DPU_HW_DSC_H >> @@ -69,6 +72,15 @@ struct dpu_hw_dsc *dpu_hw_dsc_init(const struct dpu_dsc_cfg *cfg, >> void __iomem *addr); >> >> /** >> + * dpu_hw_dsc_init_1_2() - initializes the v1.2 DSC hw driver block > > DSC hw driver object. (v8 review) > >> + * @cfg: DSC catalog entry for which driver object is required >> + * @addr: Mapped register io address of MDP >> + * Returns: Error code or allocated dpu_hw_dsc context >> + */ >> +struct dpu_hw_dsc *dpu_hw_dsc_init_1_2(const struct dpu_dsc_cfg *cfg, >> + void __iomem *addr); >> + >> +/** >> * dpu_hw_dsc_destroy - destroys dsc driver context >> * @dsc: Pointer to dsc driver context returned by dpu_hw_dsc_init >> */ >> diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_dsc_1_2.c b/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_dsc_1_2.c >> new file mode 100644 >> index 00000000..c3f1998 >> --- /dev/null >> +++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_dsc_1_2.c >> @@ -0,0 +1,386 @@ >> +// SPDX-License-Identifier: GPL-2.0-only >> +/* >> + * Copyright (c) 2020-2021, The Linux Foundation. All rights reserved. >> + * Copyright (c) 2023 Qualcomm Innovation Center, Inc. All rights reserved >> + */ >> + >> +#include >> + >> +#include "dpu_kms.h" >> +#include "dpu_hw_catalog.h" >> +#include "dpu_hwio.h" >> +#include "dpu_hw_mdss.h" >> +#include "dpu_hw_dsc.h" >> + >> +#define DSC_CMN_MAIN_CNF 0x00 >> + >> +/* DPU_DSC_ENC register offsets */ >> +#define ENC_DF_CTRL 0x00 >> +#define ENC_GENERAL_STATUS 0x04 >> +#define ENC_HSLICE_STATUS 0x08 >> +#define ENC_OUT_STATUS 0x0C >> +#define ENC_INT_STAT 0x10 >> +#define ENC_INT_CLR 0x14 >> +#define ENC_INT_MASK 0x18 >> +#define DSC_MAIN_CONF 0x30 >> +#define DSC_PICTURE_SIZE 0x34 >> +#define DSC_SLICE_SIZE 0x38 >> +#define DSC_MISC_SIZE 0x3C >> +#define DSC_HRD_DELAYS 0x40 >> +#define DSC_RC_SCALE 0x44 >> +#define DSC_RC_SCALE_INC_DEC 0x48 >> +#define DSC_RC_OFFSETS_1 0x4C >> +#define DSC_RC_OFFSETS_2 0x50 >> +#define DSC_RC_OFFSETS_3 0x54 >> +#define DSC_RC_OFFSETS_4 0x58 >> +#define DSC_FLATNESS_QP 0x5C >> +#define DSC_RC_MODEL_SIZE 0x60 >> +#define DSC_RC_CONFIG 0x64 >> +#define DSC_RC_BUF_THRESH_0 0x68 >> +#define DSC_RC_BUF_THRESH_1 0x6C >> +#define DSC_RC_BUF_THRESH_2 0x70 >> +#define DSC_RC_BUF_THRESH_3 0x74 >> +#define DSC_RC_MIN_QP_0 0x78 >> +#define DSC_RC_MIN_QP_1 0x7C >> +#define DSC_RC_MIN_QP_2 0x80 >> +#define DSC_RC_MAX_QP_0 0x84 >> +#define DSC_RC_MAX_QP_1 0x88 >> +#define DSC_RC_MAX_QP_2 0x8C >> +#define DSC_RC_RANGE_BPG_OFFSETS_0 0x90 >> +#define DSC_RC_RANGE_BPG_OFFSETS_1 0x94 >> +#define DSC_RC_RANGE_BPG_OFFSETS_2 0x98 >> + >> +/* DPU_DSC_CTL register offsets */ >> +#define DSC_CTL 0x00 >> +#define DSC_CFG 0x04 >> +#define DSC_DATA_IN_SWAP 0x08 >> +#define DSC_CLK_CTRL 0x0C >> + >> +static int _dsc_calc_output_buf_max_addr(struct dpu_hw_dsc *hw_dsc, int num_softslice) >> +{ >> + int max_addr = 2400 / num_softslice; >> + >> + if (hw_dsc->caps->features & BIT(DPU_DSC_NATIVE_42x_EN)) >> + max_addr /= 2; >> + >> + return max_addr - 1; >> +}; >> + >> +static void dpu_hw_dsc_disable_1_2(struct dpu_hw_dsc *hw_dsc) >> +{ >> + struct dpu_hw_blk_reg_map *hw; >> + const struct dpu_dsc_sub_blks *sblk; >> + >> + if (!hw_dsc) >> + return; >> + >> + hw = &hw_dsc->hw; >> + sblk = hw_dsc->caps->sblk; >> + DPU_REG_WRITE(hw, sblk->ctl.base + DSC_CFG, 0); >> + >> + DPU_REG_WRITE(hw, sblk->enc.base + ENC_DF_CTRL, 0); >> + DPU_REG_WRITE(hw, sblk->enc.base + DSC_MAIN_CONF, 0); >> +} >> + >> +static void dpu_hw_dsc_config_1_2(struct dpu_hw_dsc *hw_dsc, >> + struct drm_dsc_config *dsc, >> + u32 mode, >> + u32 initial_lines) >> +{ >> + struct dpu_hw_blk_reg_map *hw; >> + const struct dpu_dsc_sub_blks *sblk; >> + u32 data = 0; >> + u32 det_thresh_flatness; >> + u32 num_active_slice_per_enc; >> + u32 bpp; >> + >> + if (!hw_dsc || !dsc) >> + return; >> + >> + hw = &hw_dsc->hw; >> + >> + sblk = hw_dsc->caps->sblk; >> + >> + if (mode & DSC_MODE_SPLIT_PANEL) >> + data |= BIT(0); >> + >> + if (mode & DSC_MODE_MULTIPLEX) >> + data |= BIT(1); >> + >> + num_active_slice_per_enc = dsc->slice_count; >> + if (mode & DSC_MODE_MULTIPLEX) >> + num_active_slice_per_enc = dsc->slice_count / 2; >> + >> + data |= (num_active_slice_per_enc & 0x3) << 7; >> + >> + DPU_REG_WRITE(hw, DSC_CMN_MAIN_CNF, data); >> + >> + data = (initial_lines & 0xff); >> + >> + if (mode & DSC_MODE_VIDEO) >> + data |= BIT(9); >> + >> + data |= (_dsc_calc_output_buf_max_addr(hw_dsc, num_active_slice_per_enc) << 18); >> + >> + DPU_REG_WRITE(hw, sblk->enc.base + ENC_DF_CTRL, data); >> + >> + data = (dsc->dsc_version_minor & 0xf) << 28; >> + if (dsc->dsc_version_minor == 0x2) { >> + if (dsc->native_422) >> + data |= BIT(22); >> + if (dsc->native_420) >> + data |= BIT(21); >> + } >> + >> + bpp = dsc->bits_per_pixel; >> + /* as per hw requirement bpp should be programmed >> + * twice the actual value in case of 420 or 422 encoding >> + */ >> + if (dsc->native_422 || dsc->native_420) >> + bpp = 2 * bpp; >> + >> + data |= bpp << 10; >> + >> + if (dsc->block_pred_enable) >> + data |= BIT(20); > > Use tabs for indentation like everywhere else. (v9 review) I'd say: please use checkpatch.pl --strict when preparing the patchset. > >> + >> + if (dsc->convert_rgb) >> + data |= BIT(4); >> + >> + data |= (dsc->line_buf_depth & 0xf) << 6; >> + data |= dsc->bits_per_component & 0xf; >> + >> + DPU_REG_WRITE(hw, sblk->enc.base + DSC_MAIN_CONF, data); >> + >> + data = (dsc->pic_width & 0xffff) | >> + ((dsc->pic_height & 0xffff) << 16); >> + >> + DPU_REG_WRITE(hw, sblk->enc.base + DSC_PICTURE_SIZE, data); >> + >> + data = (dsc->slice_width & 0xffff) | >> + ((dsc->slice_height & 0xffff) << 16); >> + >> + DPU_REG_WRITE(hw, sblk->enc.base + DSC_SLICE_SIZE, data); >> + >> + DPU_REG_WRITE(hw, sblk->enc.base + DSC_MISC_SIZE, >> + (dsc->slice_chunk_size) & 0xffff); >> + >> + data = (dsc->initial_xmit_delay & 0xffff) | >> + ((dsc->initial_dec_delay & 0xffff) << 16); >> + >> + DPU_REG_WRITE(hw, sblk->enc.base + DSC_HRD_DELAYS, data); >> + >> + DPU_REG_WRITE(hw, sblk->enc.base + DSC_RC_SCALE, >> + dsc->initial_scale_value & 0x3f); >> + >> + data = (dsc->scale_increment_interval & 0xffff) | >> + ((dsc->scale_decrement_interval & 0x7ff) << 16); >> + >> + DPU_REG_WRITE(hw, sblk->enc.base + DSC_RC_SCALE_INC_DEC, data); >> + >> + data = (dsc->first_line_bpg_offset & 0x1f) | >> + ((dsc->second_line_bpg_offset & 0x1f) << 5); >> + >> + DPU_REG_WRITE(hw, sblk->enc.base + DSC_RC_OFFSETS_1, data); >> + >> + data = (dsc->nfl_bpg_offset & 0xffff) | >> + ((dsc->slice_bpg_offset & 0xffff) << 16); >> + >> + DPU_REG_WRITE(hw, sblk->enc.base + DSC_RC_OFFSETS_2, data); >> + >> + data = (dsc->initial_offset & 0xffff) | >> + ((dsc->final_offset & 0xffff) << 16); >> + >> + DPU_REG_WRITE(hw, sblk->enc.base + DSC_RC_OFFSETS_3, data); >> + >> + data = (dsc->nsl_bpg_offset & 0xffff) | >> + ((dsc->second_line_offset_adj & 0xffff) << 16); >> + >> + DPU_REG_WRITE(hw, sblk->enc.base + DSC_RC_OFFSETS_4, data); >> + >> + det_thresh_flatness = drm_dsc_calculate_flatness_det_thresh(dsc); > > Don't forget that Jessica renamed this to drm_dsc_flatness_det_thresh() > in v10. (v9 review) > >> + data = (dsc->flatness_min_qp & 0x1f) | ((dsc->flatness_max_qp & 0x1f) << 5) | >> + ((det_thresh_flatness & 0xff) << 10); > > Thanks for updating this, but while it might fit under 100 chars this is > perhaps clearer to read when split out over 3 lines. (v9 review): > > data = (dsc->flatness_min_qp & 0x1f) | > ((dsc->flatness_max_qp & 0x1f) << 5) | > ((det_thresh_flatness & 0xff) << 10); With the proper alignment, please. > > - Marijn > >> + >> + DPU_REG_WRITE(hw, sblk->enc.base + DSC_FLATNESS_QP, data); >> + >> + DPU_REG_WRITE(hw, sblk->enc.base + DSC_RC_MODEL_SIZE, >> + (dsc->rc_model_size) & 0xffff); >> + >> + data = dsc->rc_edge_factor & 0xf; >> + data |= (dsc->rc_quant_incr_limit0 & 0x1f) << 8; >> + data |= (dsc->rc_quant_incr_limit1 & 0x1f) << 13; >> + data |= (dsc->rc_tgt_offset_high & 0xf) << 20; >> + data |= (dsc->rc_tgt_offset_low & 0xf) << 24; >> + >> + DPU_REG_WRITE(hw, sblk->enc.base + DSC_RC_CONFIG, data); >> + >> + /* program the dsc wrapper */ >> + data = BIT(0); /* encoder enable */ >> + if (dsc->native_422) >> + data |= BIT(8); >> + else if (dsc->native_420) >> + data |= BIT(9); >> + if (!dsc->convert_rgb) >> + data |= BIT(10); >> + if (dsc->bits_per_component == 8) >> + data |= BIT(11); >> + if (mode & DSC_MODE_SPLIT_PANEL) >> + data |= BIT(12); >> + if (mode & DSC_MODE_MULTIPLEX) >> + data |= BIT(13); >> + if (!(mode & DSC_MODE_VIDEO)) >> + data |= BIT(17); >> + >> + DPU_REG_WRITE(hw, sblk->ctl.base + DSC_CFG, data); >> +} >> + >> +static void dpu_hw_dsc_config_thresh_1_2(struct dpu_hw_dsc *hw_dsc, >> + struct drm_dsc_config *dsc) >> +{ >> + struct dpu_hw_blk_reg_map *hw; >> + const struct dpu_dsc_sub_blks *sblk; >> + struct drm_dsc_rc_range_parameters *rc; >> + >> + if (!hw_dsc || !dsc) >> + return; >> + >> + hw = &hw_dsc->hw; >> + >> + sblk = hw_dsc->caps->sblk; >> + >> + rc = dsc->rc_range_params; >> + >> + /* >> + * With BUF_THRESH -- 14 in total >> + * each register contains 4 thresh values with the last register >> + * containing only 2 thresh values >> + */ >> + DPU_REG_WRITE(hw, sblk->enc.base + DSC_RC_BUF_THRESH_0, >> + (dsc->rc_buf_thresh[0] << 0) | >> + (dsc->rc_buf_thresh[1] << 8) | >> + (dsc->rc_buf_thresh[2] << 16) | >> + (dsc->rc_buf_thresh[3] << 24)); >> + DPU_REG_WRITE(hw, sblk->enc.base + DSC_RC_BUF_THRESH_1, >> + (dsc->rc_buf_thresh[4] << 0) | >> + (dsc->rc_buf_thresh[5] << 8) | >> + (dsc->rc_buf_thresh[6] << 16) | >> + (dsc->rc_buf_thresh[7] << 24)); >> + DPU_REG_WRITE(hw, sblk->enc.base + DSC_RC_BUF_THRESH_2, >> + (dsc->rc_buf_thresh[8] << 0) | >> + (dsc->rc_buf_thresh[9] << 8) | >> + (dsc->rc_buf_thresh[10] << 16) | >> + (dsc->rc_buf_thresh[11] << 24)); >> + DPU_REG_WRITE(hw, sblk->enc.base + DSC_RC_BUF_THRESH_3, >> + (dsc->rc_buf_thresh[12] << 0) | >> + (dsc->rc_buf_thresh[13] << 8)); >> + >> + /* >> + * with min/max_QP -- 5 bits >> + * each register contains 5 min_qp or max_qp for total of 15 >> + * >> + * With BPG_OFFSET -- 6 bits >> + * each register contains 5 BPG_offset for total of 15 >> + */ >> + DPU_REG_WRITE(hw, sblk->enc.base + DSC_RC_MIN_QP_0, >> + (rc[0].range_min_qp << 0) | >> + (rc[1].range_min_qp << 5) | >> + (rc[2].range_min_qp << 10) | >> + (rc[3].range_min_qp << 15) | >> + (rc[4].range_min_qp << 20)); >> + DPU_REG_WRITE(hw, sblk->enc.base + DSC_RC_MAX_QP_0, >> + (rc[0].range_max_qp << 0) | >> + (rc[1].range_max_qp << 5) | >> + (rc[2].range_max_qp << 10) | >> + (rc[3].range_max_qp << 15) | >> + (rc[4].range_max_qp << 20)); >> + DPU_REG_WRITE(hw, sblk->enc.base + DSC_RC_RANGE_BPG_OFFSETS_0, >> + (rc[0].range_bpg_offset << 0) | >> + (rc[1].range_bpg_offset << 6) | >> + (rc[2].range_bpg_offset << 12) | >> + (rc[3].range_bpg_offset << 18) | >> + (rc[4].range_bpg_offset << 24)); >> + >> + DPU_REG_WRITE(hw, sblk->enc.base + DSC_RC_MIN_QP_1, >> + (rc[5].range_min_qp << 0) | >> + (rc[6].range_min_qp << 5) | >> + (rc[7].range_min_qp << 10) | >> + (rc[8].range_min_qp << 15) | >> + (rc[9].range_min_qp << 20)); >> + DPU_REG_WRITE(hw, sblk->enc.base + DSC_RC_MAX_QP_1, >> + (rc[5].range_max_qp << 0) | >> + (rc[6].range_max_qp << 5) | >> + (rc[7].range_max_qp << 10) | >> + (rc[8].range_max_qp << 15) | >> + (rc[9].range_max_qp << 20)); >> + DPU_REG_WRITE(hw, sblk->enc.base + DSC_RC_RANGE_BPG_OFFSETS_1, >> + (rc[5].range_bpg_offset << 0) | >> + (rc[6].range_bpg_offset << 6) | >> + (rc[7].range_bpg_offset << 12) | >> + (rc[8].range_bpg_offset << 18) | >> + (rc[9].range_bpg_offset << 24)); >> + >> + DPU_REG_WRITE(hw, sblk->enc.base + DSC_RC_MIN_QP_2, >> + (rc[10].range_min_qp << 0) | >> + (rc[11].range_min_qp << 5) | >> + (rc[12].range_min_qp << 10) | >> + (rc[13].range_min_qp << 15) | >> + (rc[14].range_min_qp << 20)); >> + DPU_REG_WRITE(hw, sblk->enc.base + DSC_RC_MAX_QP_2, >> + (rc[10].range_max_qp << 0) | >> + (rc[11].range_max_qp << 5) | >> + (rc[12].range_max_qp << 10) | >> + (rc[13].range_max_qp << 15) | >> + (rc[14].range_max_qp << 20)); >> + DPU_REG_WRITE(hw, sblk->enc.base + DSC_RC_RANGE_BPG_OFFSETS_2, >> + (rc[10].range_bpg_offset << 0) | >> + (rc[11].range_bpg_offset << 6) | >> + (rc[12].range_bpg_offset << 12) | >> + (rc[13].range_bpg_offset << 18) | >> + (rc[14].range_bpg_offset << 24)); >> +} >> + >> +static void dpu_hw_dsc_bind_pingpong_blk_1_2(struct dpu_hw_dsc *hw_dsc, >> + const enum dpu_pingpong pp) >> +{ >> + struct dpu_hw_blk_reg_map *hw; >> + const struct dpu_dsc_sub_blks *sblk; >> + int mux_cfg = 0xf; /* Disabled */ >> + >> + hw = &hw_dsc->hw; >> + >> + sblk = hw_dsc->caps->sblk; >> + >> + if (pp) >> + mux_cfg = (pp - PINGPONG_0) & 0x7; >> + >> + DPU_REG_WRITE(hw, sblk->ctl.base + DSC_CTL, mux_cfg); >> +} >> + >> +static void _setup_dcs_ops_1_2(struct dpu_hw_dsc_ops *ops, >> + const unsigned long features) >> +{ >> + ops->dsc_disable = dpu_hw_dsc_disable_1_2; >> + ops->dsc_config = dpu_hw_dsc_config_1_2; >> + ops->dsc_config_thresh = dpu_hw_dsc_config_thresh_1_2; >> + ops->dsc_bind_pingpong_blk = dpu_hw_dsc_bind_pingpong_blk_1_2; >> +} >> + >> +struct dpu_hw_dsc *dpu_hw_dsc_init_1_2(const struct dpu_dsc_cfg *cfg, >> + void __iomem *addr) >> +{ >> + struct dpu_hw_dsc *c; >> + >> + c = kzalloc(sizeof(*c), GFP_KERNEL); >> + if (!c) >> + return ERR_PTR(-ENOMEM); >> + >> + c->hw.blk_addr = addr + cfg->base; >> + c->hw.log_mask = DPU_DBG_MASK_DSC; >> + >> + c->idx = cfg->id; >> + c->caps = cfg; >> + _setup_dcs_ops_1_2(&c->ops, c->caps->features); >> + >> + return c; >> +} >> diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_rm.c b/drivers/gpu/drm/msm/disp/dpu1/dpu_rm.c >> index f0fc704..502dd60 100644 >> --- a/drivers/gpu/drm/msm/disp/dpu1/dpu_rm.c >> +++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_rm.c >> @@ -1,6 +1,7 @@ >> // SPDX-License-Identifier: GPL-2.0-only >> /* >> * Copyright (c) 2016-2018, The Linux Foundation. All rights reserved. >> + * Copyright (c) 2023 Qualcomm Innovation Center, Inc. All rights reserved. >> */ >> >> #define pr_fmt(fmt) "[drm:%s] " fmt, __func__ >> @@ -246,7 +247,11 @@ int dpu_rm_init(struct dpu_rm *rm, >> struct dpu_hw_dsc *hw; >> const struct dpu_dsc_cfg *dsc = &cat->dsc[i]; >> >> - hw = dpu_hw_dsc_init(dsc, mmio); >> + if (test_bit(DPU_DSC_HW_REV_1_2, &dsc->features)) >> + hw = dpu_hw_dsc_init_1_2(dsc, mmio); >> + else >> + hw = dpu_hw_dsc_init(dsc, mmio); >> + >> if (IS_ERR_OR_NULL(hw)) { >> rc = PTR_ERR(hw); >> DPU_ERROR("failed dsc object creation: err %d\n", rc); >> -- >> 2.7.4 >> -- With best wishes Dmitry