Received: by 2002:a05:6358:9144:b0:117:f937:c515 with SMTP id r4csp10688782rwr; Fri, 12 May 2023 11:24:57 -0700 (PDT) X-Google-Smtp-Source: ACHHUZ6eDIymKHFGyL3xuccYl/48USSfMwnQ5kRBOoz/8X1hoiIkxqRal20ai0Xu9D90FdqC2bVV X-Received: by 2002:a05:6a00:1390:b0:646:3162:31a2 with SMTP id t16-20020a056a00139000b00646316231a2mr24934938pfg.17.1683915897310; Fri, 12 May 2023 11:24:57 -0700 (PDT) ARC-Seal: i=1; a=rsa-sha256; t=1683915897; cv=none; d=google.com; s=arc-20160816; b=LkFgL7xhY3uEpr50OGZ5f2m6uNmnl3Sd9mzYhPmoMLU8UkkbWY3yqOdvhBiCG6AMn3 yF3lmL3JPv6KYyAITLpJyoSIveJtWGejawY9HtbaZVS610Ck1MJDliREZKJ5ekpsCBJh 15stVBL8w0/LPeFHqI8kPv3tvukMO9hlvJuLf5lNBYPS4zqEb7FUqyRM8MNnJoZhoBEv hssauQENR2dRtC05CVixP7wSweP2CGjS00H0XaQoJbAU/XNDMaVLDRxT/VTbhGSWW3cx znV09PyTtlMBxt9EzkDq3/WHRcv6Gl/IkT+SNFRh8qcd5xXDapq4P5aX4OaS601wxNsQ KPOg== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20160816; h=list-id:precedence:content-transfer-encoding:in-reply-to:from :references:cc:to:content-language:subject:user-agent:mime-version :date:message-id:dkim-signature; bh=sqf0/LfiTNNVSyKdEjZ7e1bRfwP2OjT/192EJd8bpCQ=; b=LZvuipEIvLJ9eywnWCIynW40n/O8rx2ztFV9/vPoqRApsC+dMN5pz4++rNcB1ih+Pw /8YYmegw9x6Hp//ZCyzu36gs4uOg5BERQ4rXq6coA9x+ceuyQVaXcvT9TjG78Udlr/ig yFyYi0ls2GESWtu1BeJ5zFaWiHi0LineSHh1xoa3J6K1tLckNt/BCpfQhEu8oyNKvPOy GQcysW4Nis7/14IKS5hL1aa5mK4AhuvUAI83kDTYZNl82EwO2oS2CxDz7fzdfyypbsci EaynZaWM4OS7vmm2UqlEuQfn5UHZzBHDFuHXQlcQpHFk+1OqvswJrsw4s0I35H6lHHH0 4Jig== ARC-Authentication-Results: i=1; mx.google.com; dkim=pass header.i=@linaro.org header.s=google header.b="Ww/+ALI8"; spf=pass (google.com: domain of linux-kernel-owner@vger.kernel.org designates 2620:137:e000::1:20 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org; dmarc=pass (p=NONE sp=NONE dis=NONE) header.from=linaro.org Return-Path: Received: from out1.vger.email (out1.vger.email. [2620:137:e000::1:20]) by mx.google.com with ESMTP id c17-20020aa79531000000b00643b4daa91asi10813570pfp.369.2023.05.12.11.24.42; Fri, 12 May 2023 11:24:57 -0700 (PDT) Received-SPF: pass (google.com: domain of linux-kernel-owner@vger.kernel.org designates 2620:137:e000::1:20 as permitted sender) client-ip=2620:137:e000::1:20; Authentication-Results: mx.google.com; dkim=pass header.i=@linaro.org header.s=google header.b="Ww/+ALI8"; spf=pass (google.com: domain of linux-kernel-owner@vger.kernel.org designates 2620:137:e000::1:20 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org; dmarc=pass (p=NONE sp=NONE dis=NONE) header.from=linaro.org Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S230443AbjELST0 (ORCPT + 99 others); Fri, 12 May 2023 14:19:26 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:34056 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S233590AbjELSTZ (ORCPT ); Fri, 12 May 2023 14:19:25 -0400 Received: from mail-lf1-x136.google.com (mail-lf1-x136.google.com [IPv6:2a00:1450:4864:20::136]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 6F9BAE50 for ; Fri, 12 May 2023 11:19:22 -0700 (PDT) Received: by mail-lf1-x136.google.com with SMTP id 2adb3069b0e04-4effb818c37so11668575e87.3 for ; Fri, 12 May 2023 11:19:22 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=linaro.org; s=google; t=1683915560; x=1686507560; 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=sqf0/LfiTNNVSyKdEjZ7e1bRfwP2OjT/192EJd8bpCQ=; b=Ww/+ALI8imk6IyIv/m1xA+Y8vuaBOvvYId3PlZcI9tD8jNJ+MujBPj29rCKv3e5+vY RSnJYQHUy75OGPAkKnIX+bSZ1y7Av7EJcOqW7tBVoXu8E2wBB+U3K0vJqyfl1Aq6q7Kz EUj9kb/Eb8jyqwhCfJPKrVIwzbOur+4vrLRH159hdRpsGuOZ8cs4DZ/G2X2r02Ie2Wt7 ZHvIb9uN7K3POYsIkVpTZjPmMeWYOWWpgZkw7UNg50vRerg5hKUvxc6q9QW0Cpuy4DW4 rYpGO6qtA41JTiPhNV+m7V/lgbS4p5E+kOhxHyojQst5m7jbFH84IPdb3ezABWTuE8hF 9K/w== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20221208; t=1683915560; x=1686507560; 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=sqf0/LfiTNNVSyKdEjZ7e1bRfwP2OjT/192EJd8bpCQ=; b=PfifyvHC5qLJd9rncEOFj72RE0qopRax90k9Kn2TbI84293Yvd5hRwQV4LE6gXOLTd 3fcXOtsPuAUlXdSocQDB15MN+FCr2pohG0Qb1leNkYMgR90q80FLFCVmsNAeLicdSnbn TLOZShY7KUQUrHpKfuCjhwWURZh1gCC32GYG7l7Luy616tsQA4NjE5iZALeORyEYNqY7 eEjBdw7V0A+iBpknu8LzKVyg09xWMlIfG0OtfGkkchJz42A1QTujIzxtd6p62PkDFb16 t0C9i6PQEPz9odN+DM5mbWJKC0NYcVr3uvDH+kBpZTZ3YbgQHGbKfTUkrTkU5PcwUxe6 rN9A== X-Gm-Message-State: AC+VfDzwGwd/1Ug0TZcsocOVEUCuq5m4SGbus8/4y/1w58Yiw+y7Sqwo jMNjdaQEjopmwbQ0oiwZJNpe9g== X-Received: by 2002:a19:ad0a:0:b0:4ef:eb50:4d3d with SMTP id t10-20020a19ad0a000000b004efeb504d3dmr4232465lfc.18.1683915560486; Fri, 12 May 2023 11:19:20 -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 e24-20020ac25478000000b004f25df23cddsm1267564lfn.170.2023.05.12.11.19.19 (version=TLS1_3 cipher=TLS_AES_128_GCM_SHA256 bits=128/128); Fri, 12 May 2023 11:19:20 -0700 (PDT) Message-ID: <41243dc6-eb9d-dea6-f945-cb1f6594a2a4@linaro.org> Date: Fri, 12 May 2023 21:19:19 +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 v8 5/8] drm/msm/dpu: add support for DSC encoder v1.2 engine Content-Language: en-GB To: Kuogee Hsieh , 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 Cc: quic_abhinavk@quicinc.com, quic_jesszhan@quicinc.com, quic_sbillaka@quicinc.com, marijn.suijten@somainline.org, freedreno@lists.freedesktop.org, linux-arm-msm@vger.kernel.org, linux-kernel@vger.kernel.org References: <1683914423-17612-1-git-send-email-quic_khsieh@quicinc.com> <1683914423-17612-6-git-send-email-quic_khsieh@quicinc.com> From: Dmitry Baryshkov In-Reply-To: <1683914423-17612-6-git-send-email-quic_khsieh@quicinc.com> Content-Type: text/plain; charset=UTF-8; format=flowed Content-Transfer-Encoding: 7bit X-Spam-Status: No, score=-4.0 required=5.0 tests=BAYES_00,DKIM_SIGNED, DKIM_VALID,DKIM_VALID_AU,DKIM_VALID_EF,NICE_REPLY_A,RCVD_IN_DNSWL_NONE, SPF_HELO_NONE,SPF_PASS,T_SCC_BODY_TEXT_LINE,URIBL_BLOCKED autolearn=unavailable autolearn_force=no version=3.4.6 X-Spam-Checker-Version: SpamAssassin 3.4.6 (2021-04-09) on lindbergh.monkeyblade.net Precedence: bulk List-ID: X-Mailing-List: linux-kernel@vger.kernel.org On 12/05/2023 21:00, 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 > > Signed-off-by: Kuogee Hsieh > --- > drivers/gpu/drm/msm/Makefile | 1 + > drivers/gpu/drm/msm/disp/dpu1/dpu_hw_catalog.h | 32 ++- > drivers/gpu/drm/msm/disp/dpu1/dpu_hw_dsc.h | 14 +- > drivers/gpu/drm/msm/disp/dpu1/dpu_hw_dsc_1_2.c | 382 +++++++++++++++++++++++++ > drivers/gpu/drm/msm/disp/dpu1/dpu_rm.c | 7 +- > 5 files changed, 432 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 dc0a4da..4eda2cc 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_422_EN Supports native422 and native420 encoding > + * @DPU_DSC_MAX > */ > enum { > DPU_DSC_OUTPUT_CTRL = 0x1, > + DPU_DSC_HW_REV_1_2, > + DPU_DSC_NATIVE_422_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,17 @@ 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 +630,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..44fd624 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 > + * @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..5bd84bd > --- /dev/null > +++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_dsc_1_2.c > @@ -0,0 +1,382 @@ > +// 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 inline int _dsc_calc_ob_max_addr(struct dpu_hw_dsc *hw_dsc, int num_ss) > +{ > + int max_addr = 2400 / num_ss; > + > + if (hw_dsc->caps->features & BIT(DPU_DSC_NATIVE_422_EN)) > + max_addr /= 2; > + > + return max_addr - 1; > +}; > + > +static inline 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 inline 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 >> 1; > + > + 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_ob_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 |= (dsc->block_pred_enable ? 1 : 0) << 20; > + data |= bpp << 10; > + data |= (dsc->line_buf_depth & 0xf) << 6; > + data |= dsc->convert_rgb << 4; > + 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); > + > + data = (dsc->flatness_min_qp & 0x1f); > + data |= (dsc->flatness_max_qp & 0x1f) << 5; > + > + det_thresh_flatness = drm_dsc_calculate_flatness_det_thresh(dsc); > + data |= (det_thresh_flatness & 0xff) << 10; > + > + 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 inline 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 inline 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; Do we need an unbind support here like we do for the DSC 1.1? > + > + 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); -- With best wishes Dmitry