Re: [PATCH] phy: qcom: com-qmp-combo: fix swing and pre-emphasis table for sm8350

2024-08-02 Thread Vinod Koul
On 25-07-24, 15:06, Abhinav Kumar wrote:
> Fix the voltage swing and pre-emphasis tables for sm8350 as the current
> one do not match the hardware docs.
> 
> Fixes: ef14aff107bd ("phy: qcom: com-qmp-combo: add SM8350 & SM8450 support")
> Signed-off-by: Abhinav Kumar 
> ---
>  drivers/phy/qualcomm/phy-qcom-qmp-combo.c | 4 ++--
>  1 file changed, 2 insertions(+), 2 deletions(-)
> 
> diff --git a/drivers/phy/qualcomm/phy-qcom-qmp-combo.c 
> b/drivers/phy/qualcomm/phy-qcom-qmp-combo.c
> index 31e43638a649..c15b01aa5a48 100644
> --- a/drivers/phy/qualcomm/phy-qcom-qmp-combo.c
> +++ b/drivers/phy/qualcomm/phy-qcom-qmp-combo.c
> @@ -1946,8 +1946,8 @@ static const struct qmp_phy_cfg sm8350_usb3dpphy_cfg = {
>  
>   .swing_hbr_rbr  = &qmp_dp_v4_voltage_swing_hbr_rbr,
>   .pre_emphasis_hbr_rbr   = &qmp_dp_v4_pre_emphasis_hbr_rbr,
> - .swing_hbr3_hbr2= &qmp_dp_v3_voltage_swing_hbr3_hbr2,
> - .pre_emphasis_hbr3_hbr2 = &qmp_dp_v4_pre_emphasis_hbr3_hbr2,
> + .swing_hbr3_hbr2= &qmp_dp_v5_voltage_swing_hbr3_hbr2,
> + .pre_emphasis_hbr3_hbr2 = &qmp_dp_v5_pre_emphasis_hbr3_hbr2,

This is fine but you need to drop the unused qmp_dp_v4_pre_emphasis_hbr3_hbr2 
table...

It adds a warning, defined but unused!

-- 
~Vinod


Re: [PATCH v5 1/4] dt-bindings: phy: add qcom,hdmi-phy-8998

2024-07-02 Thread Vinod Koul
On 27-06-24, 17:53, Marc Gonzalez wrote:
> HDMI PHY block embedded in the APQ8098.
> 

Acked-by: Vinod Koul 

-- 
~Vinod


Re: [PATCH v3 2/4] dt-bindings: display/msm: hdmi: add qcom,hdmi-tx-8998

2024-06-12 Thread Vinod Koul
On 06-06-24, 18:07, Marc Gonzalez wrote:
> HDMI TX block embedded in the APQ8098.

This one too

-- 
~Vinod


Re: [PATCH v3 1/4] dt-bindings: display/msm: hdmi: add qcom,hdmi-phy-8998

2024-06-12 Thread Vinod Koul
On 06-06-24, 18:07, Marc Gonzalez wrote:
> HDMI PHY block embedded in the APQ8098.

Why is the patch titled display/msm, this is phy patch and it should be
tagged as such..

Pls update

> 
> Acked-by: Rob Herring (Arm) 
> Signed-off-by: Marc Gonzalez 
> ---
>  Documentation/devicetree/bindings/phy/qcom,hdmi-phy-qmp.yaml | 1 +
>  1 file changed, 1 insertion(+)
> 
> diff --git a/Documentation/devicetree/bindings/phy/qcom,hdmi-phy-qmp.yaml 
> b/Documentation/devicetree/bindings/phy/qcom,hdmi-phy-qmp.yaml
> index 83fe4b39b56f4..78607ee3e2e84 100644
> --- a/Documentation/devicetree/bindings/phy/qcom,hdmi-phy-qmp.yaml
> +++ b/Documentation/devicetree/bindings/phy/qcom,hdmi-phy-qmp.yaml
> @@ -14,6 +14,7 @@ properties:
>compatible:
>  enum:
>- qcom,hdmi-phy-8996
> +  - qcom,hdmi-phy-8998
>  
>reg:
>  maxItems: 6
> 
> -- 
> 2.34.1

-- 
~Vinod


Re: [PATCH] phy: qcom: qmp-combo: Fix register base for QSERDES_DP_PHY_MODE

2024-04-06 Thread Vinod Koul


On Thu, 04 Apr 2024 17:01:03 -0700, Stephen Boyd wrote:
> The register base that was used to write to the QSERDES_DP_PHY_MODE
> register was 'dp_dp_phy' before commit 815891eee668 ("phy:
> qcom-qmp-combo: Introduce orientation variable"). There isn't any
> explanation in the commit why this is changed, so I suspect it was an
> oversight or happened while being extracted from some other series.
> Oddly the value being 0x4c or 0x5c doesn't seem to matter for me, so I
> suspect this is dead code, but that can be fixed in another patch. It's
> not good to write to the wrong register space, and maybe some other
> version of this phy relies on this.
> 
> [...]

Applied, thanks!

[1/1] phy: qcom: qmp-combo: Fix register base for QSERDES_DP_PHY_MODE
  commit: ee13e1f3c72b9464a4d73017c060ab503eed653a

Best regards,
-- 
~Vinod




Re: [PATCH] phy: qcom: qmp-combo: Fix VCO div offset on v3

2024-04-06 Thread Vinod Koul


On Thu, 04 Apr 2024 16:43:44 -0700, Stephen Boyd wrote:
> Commit ec17373aebd0 ("phy: qcom: qmp-combo: extract common function to
> setup clocks") changed the offset that is used to write to
> DP_PHY_VCO_DIV from QSERDES_V3_DP_PHY_VCO_DIV to
> QSERDES_V4_DP_PHY_VCO_DIV. Unfortunately, this offset is different
> between v3 and v4 phys:
> 
>  #define QSERDES_V3_DP_PHY_VCO_DIV 0x064
>  #define QSERDES_V4_DP_PHY_VCO_DIV 0x070
> 
> [...]

Applied, thanks!

[1/1] phy: qcom: qmp-combo: Fix VCO div offset on v3
  commit: 5abed58a8bde6d349bde364a160510b5bb904d18

Best regards,
-- 
~Vinod




Re: (subset) [PATCH 0/6] soc: qcom: pmic_glink_altmode: fix drm bridge use-after-free

2024-03-06 Thread Vinod Koul


On Sat, 17 Feb 2024 16:02:22 +0100, Johan Hovold wrote:
> Starting with 6.8-rc1 the internal display sometimes fails to come up on
> machines like the Lenovo ThinkPad X13s and the logs indicate that this
> is due to a regression in the DRM subsystem [1].
> 
> This series fixes a race in the pmic_glink_altmode driver which was
> exposed / triggered by the transparent DRM bridges rework that went into
> 6.8-rc1 and that manifested itself as a bridge failing to attach and
> sometimes triggering a NULL-pointer dereference.
> 
> [...]

Applied, thanks!

[5/6] phy: qcom-qmp-combo: fix drm bridge registration
  commit: d2d7b8e88023b75320662c2305d61779ff060950
[6/6] phy: qcom-qmp-combo: fix type-c switch registration
  commit: 47b412c1ea77112f1148b4edd71700a388c7c80f

Best regards,
-- 
~Vinod




Re: [PATCH 6/6] phy: qcom-qmp-combo: fix type-c switch registration

2024-02-23 Thread Vinod Koul
On 17-02-24, 16:02, Johan Hovold wrote:
> Due to a long-standing issue in driver core, drivers may not probe defer
> after having registered child devices to avoid triggering a probe
> deferral loop (see fbc35b45f9f6 ("Add documentation on meaning of
> -EPROBE_DEFER")).
> 
> Move registration of the typec switch to after looking up clocks and
> other resources.
> 
> Note that PHY creation can in theory also trigger a probe deferral when
> a 'phy' supply is used. This does not seem to affect the QMP PHY driver
> but the PHY subsystem should be reworked to address this (i.e. by
> separating initialisation and registration of the PHY).

Acked-by: Vinod Koul 

-- 
~Vinod


Re: [PATCH 5/6] phy: qcom-qmp-combo: fix drm bridge registration

2024-02-23 Thread Vinod Koul
On 17-02-24, 16:02, Johan Hovold wrote:
> Due to a long-standing issue in driver core, drivers may not probe defer
> after having registered child devices to avoid triggering a probe
> deferral loop (see fbc35b45f9f6 ("Add documentation on meaning of
> -EPROBE_DEFER")).
> 
> This could potentially also trigger a bug in the DRM bridge
> implementation which does not expect bridges to go away even if device
> links may avoid triggering this (when enabled).
> 
> Move registration of the DRM aux bridge to after looking up clocks and
> other resources.
> 
> Note that PHY creation can in theory also trigger a probe deferral when
> a 'phy' supply is used. This does not seem to affect the QMP PHY driver
> but the PHY subsystem should be reworked to address this (i.e. by
> separating initialisation and registration of the PHY).

Acked-by: Vinod Koul 

-- 
~Vinod


Re: [Freedreno] [PATCH v4 2/3] phy: qcom: qmp-combo: switch to DRM_AUX_BRIDGE

2023-08-22 Thread Vinod Koul
On 17-08-23, 17:55, Dmitry Baryshkov wrote:
> Switch to using the new DRM_AUX_BRIDGE helper to create the
> transparent DRM bridge device instead of handcoding corresponding
> functionality.

Acked-by: Vinod Koul 

-- 
~Vinod


Re: [Freedreno] [RESEND PATCH 0/7] phy: qcom: qmp-combo: rework register access

2023-07-11 Thread Vinod Koul


On Wed, 21 Jun 2023 18:33:10 +0300, Dmitry Baryshkov wrote:
> For some reason I used the wrong script to send this patchset, resend it
> including proper (linux-phy & maintainers) recipients.
> 
> The patch at [1], which added another function just to have v4 vs v6
> register address difference prompted me to take a look at the combo PHY
> driver. We already have mechanism, register layout descriptions, for
> coping with register address differences, which I ignored while adding
> v4 support. It looks like nowadays this has exploded somehow, resulting
> inseveral almost-identicatical functions.
> 
> [...]

Applied, thanks!

[1/7] phy: qcom: qmp-combo: correct bias0_en programming
  commit: 8fa60f5ab940ba732644c996c3570b78b10b8fdc
[2/7] phy: qcom: qmp-combo: reuse register layouts for more registers
  commit: 211ddf1d89cfb6be8aead2092c95bb285bf790b6
[3/7] phy: qcom: qmp-combo: reuse register layouts for even more registers
  commit: 01f363f4eb0c0c35aa88a0ff2a329c4d88dc1da0
[4/7] phy: qcom: qmp-combo: reuse register layouts for some more registers
  commit: 245fa640ea46ad430cd962351fef0618f71ffda9
[5/7] phy: qcom: qmp-combo: drop similar functions
  commit: f4ed3532ca7422811083d15a204f91b8f5f8b49a
[6/7] phy: qcom: qmp-combo: drop qmp_v6_dp_aux_init()
  commit: 8e4137dc4eac0982aeb4f3fd103598a41c4f165d
[7/7] phy: qcom: qmp-combo: extract common function to setup clocks
  commit: 315a1a400d9c6533823e3e3af9b07cb4d0555f77

Best regards,
-- 
~Vinod




Re: [Freedreno] [PATCH 02/15] phy: qualcomm: add QMP HDMI PHY driver

2023-07-11 Thread Vinod Koul
On 23-05-23, 15:14, Dmitry Baryshkov wrote:
> Port Qualcomm QMP HDMI PHY to the generic PHY framework. Split the
> generic part and the msm8996 part. When adding support for msm8992/4 and
> msm8998 (which also employ QMP for HDMI PHY), one will have to provide
> the PLL programming part only.
> 
> Signed-off-by: Dmitry Baryshkov 
> ---
>  drivers/phy/qualcomm/Kconfig  |   7 +
>  drivers/phy/qualcomm/Makefile |   5 +
>  drivers/phy/qualcomm/phy-qcom-qmp-hdmi-base.c | 184 
>  .../phy/qualcomm/phy-qcom-qmp-hdmi-msm8996.c  | 441 ++
>  drivers/phy/qualcomm/phy-qcom-qmp-hdmi.h  |  75 +++
>  5 files changed, 712 insertions(+)
>  create mode 100644 drivers/phy/qualcomm/phy-qcom-qmp-hdmi-base.c
>  create mode 100644 drivers/phy/qualcomm/phy-qcom-qmp-hdmi-msm8996.c
>  create mode 100644 drivers/phy/qualcomm/phy-qcom-qmp-hdmi.h
> 
> diff --git a/drivers/phy/qualcomm/Kconfig b/drivers/phy/qualcomm/Kconfig
> index 4850d48f31fa..94fb5679df4a 100644
> --- a/drivers/phy/qualcomm/Kconfig
> +++ b/drivers/phy/qualcomm/Kconfig
> @@ -65,6 +65,13 @@ config PHY_QCOM_QMP_COMBO
> Enable this to support the QMP Combo PHY transceiver that is used
> with USB3 and DisplayPort controllers on Qualcomm chips.
>  
> +config PHY_QCOM_QMP_HDMI
> + tristate "Qualcomm QMP HDMI PHY Driver"
> + default PHY_QCOM_QMP && DRM_MSM_HDMI
> + help
> +   Enable this to support the QMP HDMI PHY transceiver that is used
> +   with HDMI output on Qualcomm MSM8996 chips.
> +
>  config PHY_QCOM_QMP_PCIE
>   tristate "Qualcomm QMP PCIe PHY Driver"
>   depends on PCI || COMPILE_TEST
> diff --git a/drivers/phy/qualcomm/Makefile b/drivers/phy/qualcomm/Makefile
> index de3dc9ccf067..b877d86ea0b1 100644
> --- a/drivers/phy/qualcomm/Makefile
> +++ b/drivers/phy/qualcomm/Makefile
> @@ -6,7 +6,12 @@ obj-$(CONFIG_PHY_QCOM_IPQ4019_USB)   += 
> phy-qcom-ipq4019-usb.o
>  obj-$(CONFIG_PHY_QCOM_IPQ806X_SATA)  += phy-qcom-ipq806x-sata.o
>  obj-$(CONFIG_PHY_QCOM_PCIE2) += phy-qcom-pcie2.o
>  
> +phy-qcom-qmp-hdmi-y := \
> + phy-qcom-qmp-hdmi-base.o \
> + phy-qcom-qmp-hdmi-msm8996.o \
> +
>  obj-$(CONFIG_PHY_QCOM_QMP_COMBO) += phy-qcom-qmp-combo.o
> +obj-$(CONFIG_PHY_QCOM_QMP_HDMI)  += phy-qcom-qmp-hdmi.o
>  obj-$(CONFIG_PHY_QCOM_QMP_PCIE)  += phy-qcom-qmp-pcie.o
>  obj-$(CONFIG_PHY_QCOM_QMP_PCIE_8996) += phy-qcom-qmp-pcie-msm8996.o
>  obj-$(CONFIG_PHY_QCOM_QMP_UFS)   += phy-qcom-qmp-ufs.o
> diff --git a/drivers/phy/qualcomm/phy-qcom-qmp-hdmi-base.c 
> b/drivers/phy/qualcomm/phy-qcom-qmp-hdmi-base.c
> new file mode 100644
> index ..08132b3f82af
> --- /dev/null
> +++ b/drivers/phy/qualcomm/phy-qcom-qmp-hdmi-base.c
> @@ -0,0 +1,184 @@
> +// SPDX-License-Identifier: GPL-2.0-only
> +/*
> + * Copyright (c) 2016, The Linux Foundation. All rights reserved.
> + * Copyright (c) 2023, Linaro Ltd.
> + */
> +
> +#include 
> +#include 
> +#include 
> +
> +#include "phy-qcom-qmp-hdmi.h"
> +
> +int qmp_hdmi_phy_init(struct phy *phy)
> +{
> + struct qmp_hdmi_phy *hdmi_phy = phy_get_drvdata(phy);
> +
> + return pm_runtime_resume_and_get(hdmi_phy->dev);
> +}
> +
> +int qmp_hdmi_phy_configure(struct phy *phy, union phy_configure_opts *opts)
> +{
> +const struct phy_configure_opts_hdmi *hdmi_opts = &opts->hdmi;
> + struct qmp_hdmi_phy *hdmi_phy = phy_get_drvdata(phy);

wrong alignment

> +int ret = 0;
> +
> +memcpy(&hdmi_phy->hdmi_opts, hdmi_opts, sizeof(*hdmi_opts));
> +
> +return ret;

drop ret, and return 0 here?

> +}
> +
> +int qmp_hdmi_phy_exit(struct phy *phy)
> +{
> + struct qmp_hdmi_phy *hdmi_phy = phy_get_drvdata(phy);
> +
> + pm_runtime_put_noidle(hdmi_phy->dev);
> +
> + return 0;
> +}
> +
> +static int __maybe_unused qmp_hdmi_runtime_resume(struct device *dev)
> +{
> + struct qmp_hdmi_phy *hdmi_phy = dev_get_drvdata(dev);
> + int ret;
> +
> + ret = regulator_bulk_enable(ARRAY_SIZE(hdmi_phy->supplies), 
> hdmi_phy->supplies);
> + if (ret)
> + return ret;
> +
> + ret = clk_bulk_prepare_enable(ARRAY_SIZE(hdmi_phy->clks), 
> hdmi_phy->clks);
> + if (ret)
> + goto out_disable_supplies;
> +
> + return 0;
> +
> +out_disable_supplies:
> + regulator_bulk_disable(ARRAY_SIZE(hdmi_phy->supplies), 
> hdmi_phy->supplies);
> +
> + return ret;
> +}
> +
> +static int __maybe_unused qmp_hdmi_runtime_suspend(struct device *dev)
> +{
> + struct qmp_hdmi_phy *hdmi_phy = dev_get_drvdata(dev);
> +
> + clk_bulk_disable_unprepare(ARRAY_SIZE(hdmi_phy->clks), hdmi_phy->clks);
> + regulator_bulk_disable(ARRAY_SIZE(hdmi_phy->supplies), 
> hdmi_phy->supplies);
> +
> + return 0;
> +}
> +
> +static int qmp_hdmi_probe(struct platform_device *pdev)
> +{
> + struct clk_init_data init = {
> + .name = "hdmipll",
> + .parent_data = (const struct clk_parent_data[]) {
> + { .fw

Re: [Freedreno] [PATCH] dt-bindings: cleanup DTS example whitespaces

2023-07-04 Thread Vinod Koul
On 02-07-23, 20:23, Krzysztof Kozlowski wrote:
> The DTS code coding style expects spaces around '=' sign.
> 
> Signed-off-by: Krzysztof Kozlowski 
> 
> ---
> 
> Rob,
> 
> Maybe this could go via your tree? Rebased on your for-next:
> v6.4-rc2-45-gf0ac35049606
> ---
>  .../bindings/arm/arm,coresight-cti.yaml| 18 +-
>  .../bindings/arm/keystone/ti,sci.yaml  |  8 
>  .../devicetree/bindings/display/msm/gmu.yaml   |  2 +-
>  .../display/panel/samsung,s6e8aa0.yaml |  2 +-
>  .../display/rockchip/rockchip-vop.yaml |  4 ++--
>  .../bindings/iio/adc/ti,adc108s102.yaml|  2 +-
>  .../bindings/media/renesas,rzg2l-cru.yaml  |  4 ++--
>  .../devicetree/bindings/media/renesas,vin.yaml |  4 ++--
>  .../devicetree/bindings/mtd/mtd-physmap.yaml   |  2 +-
>  .../bindings/net/mediatek-dwmac.yaml   |  2 +-
>  .../bindings/perf/amlogic,g12-ddr-pmu.yaml |  4 ++--
>  .../bindings/phy/mediatek,dsi-phy.yaml |  2 +-

Acked-by: Vinod Koul 

-- 
~Vinod


Re: [Freedreno] [PATCH v1 3/5] arm64: dts: qcom: sm8450-hdk: enable display hardware

2022-11-04 Thread Vinod Koul
On 04-11-22, 16:13, Dmitry Baryshkov wrote:
> Enable MDSS/DPU/DSI0 on SM8450-HDK device. Note, there is no panel
> configuration (yet).
> 
> Signed-off-by: Dmitry Baryshkov 
> ---
>  arch/arm64/boot/dts/qcom/sm8450-hdk.dts | 18 ++
>  1 file changed, 18 insertions(+)
> 
> diff --git a/arch/arm64/boot/dts/qcom/sm8450-hdk.dts 
> b/arch/arm64/boot/dts/qcom/sm8450-hdk.dts
> index 38ccd44620d0..e1a4cf1ee51d 100644
> --- a/arch/arm64/boot/dts/qcom/sm8450-hdk.dts
> +++ b/arch/arm64/boot/dts/qcom/sm8450-hdk.dts
> @@ -442,3 +442,21 @@ &usb_1_qmpphy {
>   vdda-phy-supply = <&vreg_l6b_1p2>;
>   vdda-pll-supply = <&vreg_l1b_0p91>;
>  };
> +
> +&mdss {
> + status = "okay";
> +};
> +
> +&mdss_mdp {
> + status = "okay";
> +};
> +
> +&dsi0 {
> + status = "okay";
> + vdda-supply = <&vreg_l6b_1p2>;
> +};
> +
> +&dsi0_phy {
> + status = "okay";
> + vdds-supply = <&vreg_l5b_0p88>;
> +};

This is missing dispcc, please enable that node too.

Also, sort this please

> -- 
> 2.35.1

-- 
~Vinod


Re: [Freedreno] [PATCH 0/5] drm: Fix math issues in MSM DSC implementation

2022-10-03 Thread Vinod Koul
On 01-10-22, 21:08, Marijn Suijten wrote:
> Various removals of complex yet unnecessary math, fixing all uses of
> drm_dsc_config::bits_per_pixel to deal with the fact that this field
> includes four fractional bits, and finally an approach for dealing with
> dsi_host setting negative values in range_bpg_offset, resulting in
> overflow inside drm_dsc_pps_payload_pack().
> 
> Note that updating the static bpg_offset array to limit the size of
> these negative values to 6 bits changes what would be written to the DPU
> hardware at register(s) DSC_RANGE_BPG_OFFSET, hence the choice has been
> made to cover up for this while packing the value into a smaller field
> instead.

Thanks for fixing these. I dont have my pixel3 availble but changes lgtm

Reviewed-by: Vinod Koul 

> Altogether this series is responsible for solving _all_ Display Stream
> Compression issues and artifacts on the Sony Tama (sdm845) Akatsuki
> smartphone (2880x1440p).

Does it need two dsi lanes?

-- 
~Vinod


Re: [Freedreno] [PATCH 0/5] drm/msm: add support for SM8450

2022-09-22 Thread Vinod Koul
On 22-09-22, 14:30, Dmitry Baryshkov wrote:
> This adds support for the MDSS/DPU/DSI on the Qualcomm SM8450 platform.

Tested this on DM8450-HDK with HDMI and it works for me.

For whole series:
Tested-by: Vinod Koul 
Reviewed-by: Vinod Koul 


> 
> Dmitry Baryshkov (5):
>   drm/msm/dsi: add support for DSI-PHY on SM8350 and SM8450
>   drm/msm/dsi: add support for DSI 2.6.0
>   drm/msm/dpu: add support for MDP_TOP blackhole
>   drm/msm/dpu: add support for SM8450
>   drm/msm: mdss add support for SM8450
> 
>  drivers/gpu/drm/msm/Kconfig   |   6 +-
>  .../gpu/drm/msm/disp/dpu1/dpu_hw_catalog.c| 224 ++
>  .../gpu/drm/msm/disp/dpu1/dpu_hw_catalog.h|   2 +
>  drivers/gpu/drm/msm/disp/dpu1/dpu_hw_mdss.h   |   3 +
>  drivers/gpu/drm/msm/disp/dpu1/dpu_kms.c   |  12 +-
>  drivers/gpu/drm/msm/dsi/dsi_cfg.c |   2 +
>  drivers/gpu/drm/msm/dsi/dsi_cfg.h |   1 +
>  drivers/gpu/drm/msm/dsi/phy/dsi_phy.c |   4 +
>  drivers/gpu/drm/msm/dsi/phy/dsi_phy.h |   2 +
>  drivers/gpu/drm/msm/dsi/phy/dsi_phy_7nm.c | 132 ++-
>  drivers/gpu/drm/msm/msm_mdss.c|   8 +
>  11 files changed, 381 insertions(+), 15 deletions(-)
> 
> -- 
> 2.35.1

-- 
~Vinod


Re: [Freedreno] [PATCH v16 0/3] eDP/DP Phy vdda realted function

2022-07-06 Thread Vinod Koul
On 05-07-22, 09:29, Kuogee Hsieh wrote:
> 0) rebase on 
> https://git.kernel.org/pub/scm/linux/kernel/git/phy/linux-phy.git tree
> 1) add regulator_set_load() to eDP phy
> 2) add regulator_set_load() to DP phy
> 3) remove vdda related function out of eDP/DP controller

Applied, thanks

-- 
~Vinod


Re: [Freedreno] [PATCH 1/3] dt-bindings: phy: qcom, hdmi-phy-qmp: add clock-cells

2022-07-05 Thread Vinod Koul
On 17-06-22, 13:36, Dmitry Baryshkov wrote:
> As the QMP HDMI PHY is a clock provider, add constant #clock-cells
> property. For the compatibility with older DTs the property is not
> marked as required.

Acked-By: Vinod Koul 

-- 
~Vinod


Re: [Freedreno] [PATCH v15 2/3] phy: qcom-qmp: add regulator_set_load to dp phy

2022-07-05 Thread Vinod Koul
On 21-06-22, 10:01, Kuogee Hsieh wrote:
> This patch add regulator_set_load() before enable regulator at
> DP phy driver.
> 
> Signed-off-by: Kuogee Hsieh 
> Reviewed-by: Stephen Boyd 
> Reviewed-by: Douglas Anderson 
> ---
>  drivers/phy/qualcomm/phy-qcom-qmp-combo.c | 43 
> ---
>  1 file changed, 33 insertions(+), 10 deletions(-)
> 
> diff --git a/drivers/phy/qualcomm/phy-qcom-qmp-combo.c 
> b/drivers/phy/qualcomm/phy-qcom-qmp-combo.c
> index 893b5a4..df62980 100644
> --- a/drivers/phy/qualcomm/phy-qcom-qmp-combo.c
> +++ b/drivers/phy/qualcomm/phy-qcom-qmp-combo.c
> @@ -604,6 +604,18 @@ static const struct qmp_phy_init_tbl qmp_v4_dp_tx_tbl[] 
> = {
>   QMP_PHY_INIT_CFG(QSERDES_V4_TX_TX_EMP_POST1_LVL, 0x20),
>  };
>  
> +

this makes it double blank lines, pls remove

> +/* list of regulators */
> +struct qmp_regulator_data {
> + const char *name;
> + unsigned int enable_load;
> +};
> +
> +struct qmp_regulator_data qmp_phy_vreg_l[] = {
> + { .name = "vdda-phy", .enable_load = 21800 },
> + { .name = "vdda-pll", .enable_load = 36000 },
> +};
> +
>  struct qmp_phy;
>  
>  /* struct qmp_phy_cfg - per-PHY initialization config */
> @@ -646,7 +658,7 @@ struct qmp_phy_cfg {
>   const char * const *reset_list;
>   int num_resets;
>   /* regulators to be requested */
> - const char * const *vreg_list;
> + const struct qmp_regulator_data *vreg_list;
>   int num_vregs;
>  
>   /* array of registers with different offsets */
> @@ -809,11 +821,6 @@ static const char * const sc7180_usb3phy_reset_l[] = {
>   "phy",
>  };
>  
> -/* list of regulators */
> -static const char * const qmp_phy_vreg_l[] = {
> - "vdda-phy", "vdda-pll",
> -};
> -
>  static const struct qmp_phy_cfg sc7180_usb3phy_cfg = {
>   .type   = PHY_TYPE_USB3,
>   .nlanes = 1,
> @@ -1969,16 +1976,32 @@ static int qcom_qmp_phy_combo_vreg_init(struct device 
> *dev, const struct qmp_phy
>  {
>   struct qcom_qmp *qmp = dev_get_drvdata(dev);
>   int num = cfg->num_vregs;
> - int i;
> + int ret, i;
>  
>   qmp->vregs = devm_kcalloc(dev, num, sizeof(*qmp->vregs), GFP_KERNEL);
>   if (!qmp->vregs)
>   return -ENOMEM;
>  
>   for (i = 0; i < num; i++)
> - qmp->vregs[i].supply = cfg->vreg_list[i];
> -
> - return devm_regulator_bulk_get(dev, num, qmp->vregs);
> + qmp->vregs[i].supply = cfg->vreg_list[i].name;
> +
> +ret = devm_regulator_bulk_get(dev, num, qmp->vregs);
> +if (ret) {
> +dev_err(dev, "failed at devm_regulator_bulk_get\n");
> +return ret;
> +}
> +
> +for (i = 0; i < num; i++) {
> +ret = regulator_set_load(qmp->vregs[i].consumer,
> + cfg->vreg_list[i].enable_load);
> +if (ret) {
> +dev_err(dev, "failed to set load at %s\n",
> +qmp->vregs[i].supply);
> +return ret;
> +}
> +}
> +
> +return 0;

argh!
checkpatch says:
total: 15 errors, 25 warnings, 1 checks, 277 lines checked

Looks like all lines use spaces and not tabs :-(

Pls fix that and resend

-- 
~Vinod


Re: [Freedreno] [PATCH v3 1/3] dt-bindings: phy: qcom, hdmi-phy-qmp: add clock-cells and XO clock

2022-07-05 Thread Vinod Koul
On 04-07-22, 19:11, Dmitry Baryshkov wrote:
> As the QMP HDMI PHY is a clock provider, add constant #clock-cells
> property. For the compatibility with older DTs the property is not
> marked as required. Also add the XO clock to the list of the clocks used
> by the driver.

Acked-By: Vinod Koul 

> 
> Reviewed-by: Krzysztof Kozlowski 
> Signed-off-by: Dmitry Baryshkov 
> ---
>  .../bindings/phy/qcom,hdmi-phy-qmp.yaml   | 15 ---
>  1 file changed, 12 insertions(+), 3 deletions(-)
> 
> diff --git a/Documentation/devicetree/bindings/phy/qcom,hdmi-phy-qmp.yaml 
> b/Documentation/devicetree/bindings/phy/qcom,hdmi-phy-qmp.yaml
> index eea2e02678ed..83fe4b39b56f 100644
> --- a/Documentation/devicetree/bindings/phy/qcom,hdmi-phy-qmp.yaml
> +++ b/Documentation/devicetree/bindings/phy/qcom,hdmi-phy-qmp.yaml
> @@ -28,12 +28,15 @@ properties:
>- const: hdmi_phy
>  
>clocks:
> -maxItems: 2
> +minItems: 2
> +maxItems: 3
>  
>clock-names:
> +minItems: 2
>  items:
>- const: iface
>- const: ref
> +  - const: xo
>  
>power-domains:
>  maxItems: 1
> @@ -44,6 +47,9 @@ properties:
>vddio-supply:
>  description: phandle to VDD I/O supply regulator
>  
> +  '#clock-cells':
> +const: 0
> +
>'#phy-cells':
>  const: 0
>  
> @@ -75,9 +81,12 @@ examples:
>"hdmi_phy";
>  
>clocks = <&mmcc 116>,
> -   <&gcc 214>;
> +   <&gcc 214>,
> +   <&xo_board>;
>clock-names = "iface",
> -"ref";
> +"ref",
> +"xo";
> +  #clock-cells = <0>;
>#phy-cells = <0>;
>  
>vddio-supply = <&vreg_l12a_1p8>;
> -- 
> 2.35.1

-- 
~Vinod


Re: [Freedreno] [PATCH v13 0/3] eDP/DP Phy vdda realted function

2022-06-20 Thread Vinod Koul
On 20-06-22, 13:43, Kuogee Hsieh wrote:
> 
> On 6/20/2022 1:07 PM, Kuogee Hsieh wrote:
> > 
> > On 6/16/2022 5:02 PM, Vinod Koul wrote:
> > > On 25-05-22, 14:02, Kuogee Hsieh wrote:
> > > > 1) add regulator_set_load() to eDP phy
> > > > 2) add regulator_set_load() to DP phy
> > > > 3) remove vdda related function out of eDP/DP controller
> > > > 
> > > > Kuogee Hsieh (3):
> > > >    phy: qcom-edp: add regulator_set_load to edp phy
> > > >    phy: qcom-qmp: add regulator_set_load to dp phy
> > > >    drm/msm/dp: delete vdda regulator related functions from eDP/DP
> > > >  controller
> > > > 
> > > >   drivers/gpu/drm/msm/dp/dp_parser.c  | 14 --
> > > >   drivers/gpu/drm/msm/dp/dp_parser.h  |  8 
> > > >   drivers/gpu/drm/msm/dp/dp_power.c   | 95
> > > > +
> > > >   drivers/phy/qualcomm/phy-qcom-edp.c | 12 +
> > > >   drivers/phy/qualcomm/phy-qcom-qmp.c | 40 
> > > Please rebase this to phy-next and apply to specific qmp phy driver...
> > I will rebase to ==>
> > https://git.kernel.org/pub/scm/linux/kernel/git/phy/linux-phy.git
> 
> Hi Vinod,
> 
> Would you please specify exactly procedures i have to do as to rebase this
> patch series to phy=next tree.

Yes pls rebase to above tree and next branch

-- 
~Vinod


Re: [Freedreno] [PATCH 2/2] dt-bindings: phy: List supplies for qcom, edp-phy

2022-06-16 Thread Vinod Koul
On 16-06-22, 08:35, Doug Anderson wrote:
> Hi,
> 
> On Mon, Apr 25, 2022 at 2:07 PM Douglas Anderson  
> wrote:
> >
> > We're supposed to list the supplies in the dt bindings but there are
> > none in the eDP PHY bindings.
> >
> > Looking at the driver in Linux, I can see that there seem to be two
> > relevant supplies: "vdda-phy" and "vdda-pll". Let's add those to the
> > bindings.
> >
> > NOTE: from looking at the Qualcomm datasheet for sc7280, it's not
> > immediately clear how to figure out how to fill in these supplies. The
> > only two eDP related supplies are simply described as "power for eDP
> > 0.9V circuits" and "power for eDP 1.2V circuits". From guessing and
> > from comparing how a similar PHY is hooked up on other similar
> > Qualcomm boards, I'll make the educated guess that the 1.2V supply
> > goes to "vdda-phy" and the 0.9V supply goes to "vdda-pll" and I'll use
> > that in the example here.
> >
> > Signed-off-by: Douglas Anderson 
> > ---
> >
> >  Documentation/devicetree/bindings/phy/qcom,edp-phy.yaml | 6 ++
> >  1 file changed, 6 insertions(+)
> 
> Even though patch #1 in this series should be dropped, this patch
> (patch #2) is still valid. Vinod: I assume this would land in your
> tree along with the first two patches in Kuogee's series [1], which
> are related. Please let me know if you need me to re-send or anything.

I have applied this patch, thanks

> [1] 
> https://lore.kernel.org/r/1653507433-22585-1-git-send-email-quic_khs...@quicinc.com/

This needs rebase on phy split which I have picked

-- 
~Vinod


Re: [Freedreno] [PATCH v13 0/3] eDP/DP Phy vdda realted function

2022-06-16 Thread Vinod Koul
On 25-05-22, 14:02, Kuogee Hsieh wrote:
> 1) add regulator_set_load() to eDP phy
> 2) add regulator_set_load() to DP phy
> 3) remove vdda related function out of eDP/DP controller
> 
> Kuogee Hsieh (3):
>   phy: qcom-edp: add regulator_set_load to edp phy
>   phy: qcom-qmp: add regulator_set_load to dp phy
>   drm/msm/dp: delete vdda regulator related functions from eDP/DP
> controller
> 
>  drivers/gpu/drm/msm/dp/dp_parser.c  | 14 --
>  drivers/gpu/drm/msm/dp/dp_parser.h  |  8 
>  drivers/gpu/drm/msm/dp/dp_power.c   | 95 
> +
>  drivers/phy/qualcomm/phy-qcom-edp.c | 12 +
>  drivers/phy/qualcomm/phy-qcom-qmp.c | 40 

Please rebase this to phy-next and apply to specific qmp phy driver...

-- 
~Vinod


[Freedreno] [PATCH v2] drm/msm/disp/dpu1: remove superfluous init

2022-05-25 Thread Vinod Koul
Commit 58dca9810749 ("drm/msm/disp/dpu1: Add support for DSC in
encoder") added dsc_common_mode variable which was set to zero but then
again programmed, so drop the superfluous init.

Fixes: 58dca9810749 ("drm/msm/disp/dpu1: Add support for DSC in encoder")
Reported-by: kernel test robot 
Reviewed-by: Dmitry Baryshkov 
Reviewed-by: Abhinav Kumar 
Signed-off-by: Vinod Koul 
---
changes in v2:
 - add r-b from Dmitry & Abhinav
 - fix typo for superfluous

 drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c | 1 -
 1 file changed, 1 deletion(-)

diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c 
b/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c
index 51f24ba68375..388125c8bda1 100644
--- a/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c
+++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c
@@ -1798,7 +1798,6 @@ static void dpu_encoder_prep_dsc(struct dpu_encoder_virt 
*dpu_enc,
}
}
 
-   dsc_common_mode = 0;
pic_width = dsc->drm->pic_width;
 
dsc_common_mode = DSC_MODE_MULTIPLEX | DSC_MODE_SPLIT_PANEL;
-- 
2.34.1



[Freedreno] [PATCH] drm/msm/disp/dpu1: remove supoerflous init

2022-05-24 Thread Vinod Koul
Commit 58dca9810749 ("drm/msm/disp/dpu1: Add support for DSC in
encoder") added dsc_common_mode variable which was set to zero but then
again programmed, so drop the supoerflous init.

Fixes: 58dca9810749 ("drm/msm/disp/dpu1: Add support for DSC in encoder")
Reported-by: kernel test robot 
Signed-off-by: Vinod Koul 
---
 drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c | 1 -
 1 file changed, 1 deletion(-)

diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c 
b/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c
index 51f24ba68375..388125c8bda1 100644
--- a/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c
+++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c
@@ -1798,7 +1798,6 @@ static void dpu_encoder_prep_dsc(struct dpu_encoder_virt 
*dpu_enc,
}
}
 
-   dsc_common_mode = 0;
pic_width = dsc->drm->pic_width;
 
dsc_common_mode = DSC_MODE_MULTIPLEX | DSC_MODE_SPLIT_PANEL;
-- 
2.34.1



Re: [Freedreno] [PATCH v4 2/3] phy/qualcomm: add regulator_set_load to dp phy

2022-05-18 Thread Vinod Koul
On 18-05-22, 14:36, Kuogee Hsieh wrote:
> This patch add regulator_set_load() before enable regulator at
> DP phy driver.

sigh! still wrong tags!

> 
> Signed-off-by: Kuogee Hsieh 
> Reviewed-by: Stephen Boyd 
> ---
>  drivers/phy/qualcomm/phy-qcom-qmp.c | 12 
>  1 file changed, 12 insertions(+)
> 
> diff --git a/drivers/phy/qualcomm/phy-qcom-qmp.c 
> b/drivers/phy/qualcomm/phy-qcom-qmp.c
> index b144ae1..20ac446 100644
> --- a/drivers/phy/qualcomm/phy-qcom-qmp.c
> +++ b/drivers/phy/qualcomm/phy-qcom-qmp.c
> @@ -3130,6 +3130,7 @@ struct qmp_phy_cfg {
>   int num_resets;
>   /* regulators to be requested */
>   const char * const *vreg_list;
> + const unsigned int *vreg_enable_load;
>   int num_vregs;
>  
>   /* array of registers with different offsets */
> @@ -3346,6 +3347,10 @@ static const char * const qmp_phy_vreg_l[] = {
>   "vdda-phy", "vdda-pll",
>  };
>  
> +static const unsigned int qmp_phy_vreg_enable_load[] = {
> + 21800, 36000
> +};
> +
>  static const struct qmp_phy_cfg ipq8074_usb3phy_cfg = {
>   .type   = PHY_TYPE_USB3,
>   .nlanes = 1,
> @@ -4072,6 +4077,7 @@ static const struct qmp_phy_cfg sm8250_usb3phy_cfg = {
>   .reset_list = msm8996_usb3phy_reset_l,
>   .num_resets = ARRAY_SIZE(msm8996_usb3phy_reset_l),
>   .vreg_list  = qmp_phy_vreg_l,
> + .vreg_enable_load   = qmp_phy_vreg_enable_load,
>   .num_vregs  = ARRAY_SIZE(qmp_phy_vreg_l),
>   .regs   = qmp_v4_usb3phy_regs_layout,
>  
> @@ -4139,6 +4145,7 @@ static const struct qmp_phy_cfg sm8250_dpphy_cfg = {
>   .reset_list = msm8996_usb3phy_reset_l,
>   .num_resets = ARRAY_SIZE(msm8996_usb3phy_reset_l),
>   .vreg_list  = qmp_phy_vreg_l,
> + .vreg_enable_load   = qmp_phy_vreg_enable_load,
>   .num_vregs  = ARRAY_SIZE(qmp_phy_vreg_l),
>   .regs   = qmp_v4_usb3phy_regs_layout,
>  
> @@ -5008,6 +5015,11 @@ static int qcom_qmp_phy_com_init(struct qmp_phy *qphy)
>   return 0;
>   }
>  
> + if (cfg->vreg_enable_load) {
> + for (i = cfg->num_vregs - 1; i >= 0; --i)
> + regulator_set_load(qmp->vregs[i].consumer, 
> cfg->vreg_enable_load[i]);
> + }
> +
>   /* turn on regulator supplies */
>   ret = regulator_bulk_enable(cfg->num_vregs, qmp->vregs);
>   if (ret) {
> -- 
> The Qualcomm Innovation Center, Inc. is a member of the Code Aurora Forum,
> a Linux Foundation Collaborative Project

-- 
~Vinod


Re: [Freedreno] [PATCH v1 1/2] phy/qcom: add regulator_set_load to edp/dp phy

2022-05-18 Thread Vinod Koul
On 17-05-22, 10:25, Kuogee Hsieh wrote:

pls use the correct subsystem tag, "phy: xxx" in this case

> This patch add regulator_set_load() to both eDP and DP phy driver
> to have totally control regulators.

Can you explain what is meant by "totally control regulators"

> 
> Signed-off-by: Kuogee Hsieh 
> ---
>  drivers/phy/qualcomm/phy-qcom-edp.c | 25 +
>  drivers/phy/qualcomm/phy-qcom-qmp.c | 24 
>  2 files changed, 45 insertions(+), 4 deletions(-)
> 
> diff --git a/drivers/phy/qualcomm/phy-qcom-edp.c 
> b/drivers/phy/qualcomm/phy-qcom-edp.c
> index cacd32f..9b55095 100644
> --- a/drivers/phy/qualcomm/phy-qcom-edp.c
> +++ b/drivers/phy/qualcomm/phy-qcom-edp.c
> @@ -87,17 +87,24 @@ struct qcom_edp {
>  
>   struct clk_bulk_data clks[2];
>   struct regulator_bulk_data supplies[2];
> + int enable_load[2];
> + int disable_load[2];
>  };
>  
>  static int qcom_edp_phy_init(struct phy *phy)
>  {
>   struct qcom_edp *edp = phy_get_drvdata(phy);
>   int ret;
> + int num_consumers = ARRAY_SIZE(edp->supplies);
> + int i;
>  
> - ret = regulator_bulk_enable(ARRAY_SIZE(edp->supplies), edp->supplies);
> + ret = regulator_bulk_enable(num_consumers, edp->supplies);
>   if (ret)
>   return ret;
>  
> + for (i = num_consumers - 1; i >= 0; --i)
> + regulator_set_load(edp->supplies[i].consumer, 
> edp->enable_load[i]);
> +
>   ret = clk_bulk_prepare_enable(ARRAY_SIZE(edp->clks), edp->clks);
>   if (ret)
>   goto out_disable_supplies;
> @@ -425,9 +432,15 @@ static int qcom_edp_phy_power_off(struct phy *phy)
>  static int qcom_edp_phy_exit(struct phy *phy)
>  {
>   struct qcom_edp *edp = phy_get_drvdata(phy);
> + int num_consumers = ARRAY_SIZE(edp->supplies);
> + int i;
>  
>   clk_bulk_disable_unprepare(ARRAY_SIZE(edp->clks), edp->clks);
> - regulator_bulk_disable(ARRAY_SIZE(edp->supplies), edp->supplies);
> +
> + for (i = num_consumers - 1; i >= 0; --i)
> + regulator_set_load(edp->supplies[i].consumer, 
> edp->disable_load[i]);
> +
> + regulator_bulk_disable(num_consumers, edp->supplies);
>  
>   return 0;
>  }
> @@ -633,8 +646,12 @@ static int qcom_edp_phy_probe(struct platform_device 
> *pdev)
>   if (ret)
>   return ret;
>  
> - edp->supplies[0].supply = "vdda-phy";
> - edp->supplies[1].supply = "vdda-pll";
> + edp->supplies[0].supply = "vdda-1p2";
> + edp->supplies[1].supply = "vdda-0p9";

These are documented in bindings, so cannot be removed, Reminder binding
is an ABI
 
You have not documented the new names either...

> + edp->enable_load[0] = 21800;/* 1.2 V */
> + edp->enable_load[1] = 36000;/* 1.2 V */
> + edp->disable_load[0] = 4;   /* 0.9 V */
> + edp->disable_load[1] = 4;   /* 10.9V */

is that correct, 10.9V?

>   ret = devm_regulator_bulk_get(dev, ARRAY_SIZE(edp->supplies), 
> edp->supplies);
>   if (ret)
>   return ret;
> diff --git a/drivers/phy/qualcomm/phy-qcom-qmp.c 
> b/drivers/phy/qualcomm/phy-qcom-qmp.c
> index b144ae1..c589231 100644
> --- a/drivers/phy/qualcomm/phy-qcom-qmp.c
> +++ b/drivers/phy/qualcomm/phy-qcom-qmp.c

This is a different driver, so should be a different patch!

> @@ -3130,6 +3130,8 @@ struct qmp_phy_cfg {
>   int num_resets;
>   /* regulators to be requested */
>   const char * const *vreg_list;
> + const unsigned int *vreg_enable_load;
> + const unsigned int *vreg_disable_load;
>   int num_vregs;
>  
>   /* array of registers with different offsets */
> @@ -3346,6 +3348,14 @@ static const char * const qmp_phy_vreg_l[] = {
>   "vdda-phy", "vdda-pll",
>  };
>  
> +static const unsigned int qmp_phy_vreg_enable_load[] = {
> + 21800, 36000
> +};
> +
> +static const unsigned int qmp_phy_vreg_disable_load[] = {
> + 4, 32
> +};
> +
>  static const struct qmp_phy_cfg ipq8074_usb3phy_cfg = {
>   .type   = PHY_TYPE_USB3,
>   .nlanes = 1,
> @@ -4072,6 +4082,8 @@ static const struct qmp_phy_cfg sm8250_usb3phy_cfg = {
>   .reset_list = msm8996_usb3phy_reset_l,
>   .num_resets = ARRAY_SIZE(msm8996_usb3phy_reset_l),
>   .vreg_list  = qmp_phy_vreg_l,
> + .vreg_enable_load   = qmp_phy_vreg_enable_load,
> + .vreg_disable_load  = qmp_phy_vreg_disable_load,
>   .num_vregs  = ARRAY_SIZE(qmp_phy_vreg_l),
>   .regs   = qmp_v4_usb3phy_regs_layout,
>  
> @@ -4139,6 +4151,8 @@ static const struct qmp_phy_cfg sm8250_dpphy_cfg = {
>   .reset_list = msm8996_usb3phy_reset_l,
>   .num_resets = ARRAY_SIZE(msm8996_usb3phy_reset_l),
>   .vreg_list  = qmp_phy_vreg_l,
> + .vreg_enable_load   = qmp_phy_vreg_enable_load,
> + .vreg_disable_load  = qmp_phy_vreg_disable_load,
>   .num_vregs  = ARRAY_SIZ

Re: [Freedreno] [PATCH v2] drm/msm/dsi: use RMW cycles in dsi_update_dsc_timing

2022-05-04 Thread Vinod Koul
On 02-05-22, 10:43, Marijn Suijten wrote:
> On 2022-05-02 01:44:20, Dmitry Baryshkov wrote:
> that require DSC for the screen to work.  I've been told the series
> didn't result in positive screen output way back in its infancy, but

I would be intrested to hear about that. I have only pixel3 at my
disposal so tested on that. I would be willing to help with more testing
efforts.

Also, to get DSC to work, the panel needs to be set as well...

> I'll re-evaluate and send fixes or improvements if/when necessary.

That would be nice

-- 
~Vinod


Re: [Freedreno] [PATCH v2] drm/msm/dsi: use RMW cycles in dsi_update_dsc_timing

2022-05-04 Thread Vinod Koul
On 01-05-22, 22:41, Marijn Suijten wrote:
> On 2022-04-30 22:28:42, Dmitry Baryshkov wrote:
> > On 30/04/2022 21:58, Marijn Suijten wrote:
> > > On 2022-04-30 20:55:33, Dmitry Baryshkov wrote:
> > >> The downstream uses read-modify-write for updating command mode
> > >> compression registers. Let's follow this approach. This also fixes the
> > >> following warning:
> > >>
> > >> drivers/gpu/drm/msm/dsi/dsi_host.c:918:23: warning: variable 'reg_ctrl' 
> > >> set but not used [-Wunused-but-set-variable]
> > >>
> > >> Reported-by: kernel test robot 
> > >> Fixes: 08802f515c3c ("drm/msm/dsi: Add support for DSC configuration")
> > >> Signed-off-by: Dmitry Baryshkov 
> > > 
> > > I pointed this out in review multiple times, so you'll obviously get my:
> > 
> > I think I might have also pointed this out once (and then forgot to 
> > check that the issue was fixed by Vinod).
> > 
> > > 
> > > Reviewed-by: Marijn Suijten 
> > > 
> > > (But are you sure there's nothing else to clear in the 1st CTRL
> > > register, only the lowest 16 bits?  That should mean `reg` never
> > > contains anything in 0x)
> > 
> > Judging from the downstream the upper half conains the same fields, but 
> > used for other virtual channel. I didn't research what's the difference 
> > yet. All the dtsi files that I have here at hand use 
> > 'qcom,mdss-dsi-virtual-channel-id = <0>;'
> 
> As replied to Abhinav I'm simply asking whether we should be strict
> and add `reg & 0x` to prevent accidentally writing the top 16 bits,
> which are stream 1.  It doesn't seem like the current code can hit that
> though, with all the macros using masks internally already; but it's

Since the macros were used I skipped setting that up explictly...

> still a little scary since we're assuming the registers for VIDEO are
> identical to CMD (as mentioned in the reply to Abhinav: I wonder if it's

The documentation seems to indicate they are similar and that is the
reason, I merged the code paths and set different registers required for
video and cmd modes

-- 
~Vinod


Re: [Freedreno] [PATCH v2] drm/msm/dsi: use RMW cycles in dsi_update_dsc_timing

2022-05-04 Thread Vinod Koul
On 30-04-22, 22:28, Dmitry Baryshkov wrote:
> On 30/04/2022 21:58, Marijn Suijten wrote:
> > On 2022-04-30 20:55:33, Dmitry Baryshkov wrote:
> > > The downstream uses read-modify-write for updating command mode
> > > compression registers. Let's follow this approach. This also fixes the
> > > following warning:
> > > 
> > > drivers/gpu/drm/msm/dsi/dsi_host.c:918:23: warning: variable 'reg_ctrl' 
> > > set but not used [-Wunused-but-set-variable]
> > > 
> > > Reported-by: kernel test robot 
> > > Fixes: 08802f515c3c ("drm/msm/dsi: Add support for DSC configuration")
> > > Signed-off-by: Dmitry Baryshkov 
> > 
> > I pointed this out in review multiple times, so you'll obviously get my:
> 
> I think I might have also pointed this out once (and then forgot to check
> that the issue was fixed by Vinod).

I think i have tried to reply to all comments, if anything was missed
that would be my mistake..

> > Reviewed-by: Marijn Suijten 
> > 
> > (But are you sure there's nothing else to clear in the 1st CTRL
> > register, only the lowest 16 bits?  That should mean `reg` never
> > contains anything in 0x)
> 
> Judging from the downstream the upper half conains the same fields, but used
> for other virtual channel. I didn't research what's the difference yet. All
> the dtsi files that I have here at hand use
> 'qcom,mdss-dsi-virtual-channel-id = <0>;'

Yes the register description is for STREAM1 in documentation, it is
unclear to me when that can be used

-- 
~Vinod


Re: [Freedreno] [PATCH v2] drm/msm/dsi: use RMW cycles in dsi_update_dsc_timing

2022-05-04 Thread Vinod Koul
On 30-04-22, 20:55, Dmitry Baryshkov wrote:
> The downstream uses read-modify-write for updating command mode
> compression registers. Let's follow this approach. This also fixes the
> following warning:
> 
> drivers/gpu/drm/msm/dsi/dsi_host.c:918:23: warning: variable 'reg_ctrl' set 
> but not used [-Wunused-but-set-variable]

Reviewed-by: Vinod Koul 

Tested on pixel3:
Tested-by: Vinod Koul 

-- 
~Vinod


Re: [Freedreno] [PATCH 0/3] drm: move dsc data pointer from drm_panel to mipi_dsi_device

2022-05-04 Thread Vinod Koul
On 01-05-22, 18:12, Dmitry Baryshkov wrote:
> To properly support DSC the sink driver (panel) has to pass DSC pps data
> to the source (DSI host). The commit 0f40ba48de3b ("drm/msm/dsi: Pass
> DSC params to drm_panel") added a pointer to the DSC data to the struct
> drm_panel. However this is not the ideal solution.
> 
> First, this leaves DSC-supporting DSI sink bridges (like ANX7625 which
> support DSC decoding on the MIPI DSI inputs).
> 
> Second, this does not play well with the panel_bridge. Drivers depending
> solely on the bridge chains will still have to lookup panel and fetch
> data from it.
> 
> Last, but not least, the DSC data is not relevant for the wide variety
> of panels including DPI and LVDS panels.
> 
> To solve all these problems, move struct drm_dsc_config pointer from
> struct drm_panel to struct mipi_host_device. This way MIPI DSI host
> driver receives DSC data during attach callback without additional
> lookups.

Reviewed-by: Vinod Koul 

I tested this on my pixel3 and had to change how panel driver handles
this, with that it worked just fine

Tested-by: Vinod Koul 

-- 
~Vinod


Re: [Freedreno] [PATCH] drm/msm/dsi: fixup DSC support for the cases when there is no pannel attached

2022-04-19 Thread Vinod Koul
On 20-04-22, 00:37, Dmitry Baryshkov wrote:
> Unable to handle kernel paging request at virtual address fe2b

...

> 
> Signed-off-by: Dmitry Baryshkov 
> ---
> 
> Note: I'm going to squash this fix into the respective patch from the
> DSC series

Thanks this looks good to me:

Reviewed-by: Vinod Koul 

-- 
~Vinod


[Freedreno] [PATCH v7 14/14] drm/msm/dsi: Add support for DSC configuration

2022-04-06 Thread Vinod Koul
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 
Reviewed-by: Dmitry Baryshkov 
Signed-off-by: Vinod Koul 
---
 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_ 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_hos

[Freedreno] [PATCH v7 13/14] drm/msm: Update generated headers

2022-04-06 Thread Vinod Koul
Update headers from mesa commit:

  commit 28ae397be111c37c6ced397e12d453a7695701bd
  Author: Vinod Koul 
  Date:   Fri Apr 1 16:53:04 2022 +0530

  freedreno/registers: update dsi registers to support dsc

  Display Stream compression (DSC) compresses the display stream in
  host which is later decoded by panel. This requires addition of 3 new
  DSI registers to support DSC over DSI.

  Signed-off-by: Vinod Koul 
  Part-of: <https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/14967>

Reviewed-by: Dmitry Baryshkov 
Signed-off-by: Vinod Koul 
---
 drivers/gpu/drm/msm/dsi/dsi.xml.h | 80 +++
 1 file changed, 80 insertions(+)

diff --git a/drivers/gpu/drm/msm/dsi/dsi.xml.h 
b/drivers/gpu/drm/msm/dsi/dsi.xml.h
index 4dee6f0bdda6..d1b2a17b0a66 100644
--- a/drivers/gpu/drm/msm/dsi/dsi.xml.h
+++ b/drivers/gpu/drm/msm/dsi/dsi.xml.h
@@ -704,5 +704,85 @@ static inline uint32_t DSI_VERSION_MAJOR(uint32_t val)
 
 #define REG_DSI_CPHY_MODE_CTRL 0x02d4
 
+#define REG_DSI_VIDEO_COMPRESSION_MODE_CTRL0x029c
+#define DSI_VIDEO_COMPRESSION_MODE_CTRL_WC__MASK   0x
+#define DSI_VIDEO_COMPRESSION_MODE_CTRL_WC__SHIFT  16
+static inline uint32_t DSI_VIDEO_COMPRESSION_MODE_CTRL_WC(uint32_t val)
+{
+   return ((val) << DSI_VIDEO_COMPRESSION_MODE_CTRL_WC__SHIFT) & 
DSI_VIDEO_COMPRESSION_MODE_CTRL_WC__MASK;
+}
+#define DSI_VIDEO_COMPRESSION_MODE_CTRL_DATATYPE__MASK 0x3f00
+#define DSI_VIDEO_COMPRESSION_MODE_CTRL_DATATYPE__SHIFT8
+static inline uint32_t DSI_VIDEO_COMPRESSION_MODE_CTRL_DATATYPE(uint32_t val)
+{
+   return ((val) << DSI_VIDEO_COMPRESSION_MODE_CTRL_DATATYPE__SHIFT) & 
DSI_VIDEO_COMPRESSION_MODE_CTRL_DATATYPE__MASK;
+}
+#define DSI_VIDEO_COMPRESSION_MODE_CTRL_PKT_PER_LINE__MASK 0x00c0
+#define DSI_VIDEO_COMPRESSION_MODE_CTRL_PKT_PER_LINE__SHIFT6
+static inline uint32_t DSI_VIDEO_COMPRESSION_MODE_CTRL_PKT_PER_LINE(uint32_t 
val)
+{
+   return ((val) << DSI_VIDEO_COMPRESSION_MODE_CTRL_PKT_PER_LINE__SHIFT) & 
DSI_VIDEO_COMPRESSION_MODE_CTRL_PKT_PER_LINE__MASK;
+}
+#define DSI_VIDEO_COMPRESSION_MODE_CTRL_EOL_BYTE_NUM__MASK 0x0030
+#define DSI_VIDEO_COMPRESSION_MODE_CTRL_EOL_BYTE_NUM__SHIFT4
+static inline uint32_t DSI_VIDEO_COMPRESSION_MODE_CTRL_EOL_BYTE_NUM(uint32_t 
val)
+{
+   return ((val) << DSI_VIDEO_COMPRESSION_MODE_CTRL_EOL_BYTE_NUM__SHIFT) & 
DSI_VIDEO_COMPRESSION_MODE_CTRL_EOL_BYTE_NUM__MASK;
+}
+#define DSI_VIDEO_COMPRESSION_MODE_CTRL_EN 0x0001
+
+#define REG_DSI_COMMAND_COMPRESSION_MODE_CTRL  0x02a4
+#define DSI_COMMAND_COMPRESSION_MODE_CTRL_STREAM1_DATATYPE__MASK   
0x3f00
+#define DSI_COMMAND_COMPRESSION_MODE_CTRL_STREAM1_DATATYPE__SHIFT  24
+static inline uint32_t 
DSI_COMMAND_COMPRESSION_MODE_CTRL_STREAM1_DATATYPE(uint32_t val)
+{
+   return ((val) << 
DSI_COMMAND_COMPRESSION_MODE_CTRL_STREAM1_DATATYPE__SHIFT) & 
DSI_COMMAND_COMPRESSION_MODE_CTRL_STREAM1_DATATYPE__MASK;
+}
+#define DSI_COMMAND_COMPRESSION_MODE_CTRL_STREAM1_PKT_PER_LINE__MASK   
0x00c0
+#define DSI_COMMAND_COMPRESSION_MODE_CTRL_STREAM1_PKT_PER_LINE__SHIFT  22
+static inline uint32_t 
DSI_COMMAND_COMPRESSION_MODE_CTRL_STREAM1_PKT_PER_LINE(uint32_t val)
+{
+   return ((val) << 
DSI_COMMAND_COMPRESSION_MODE_CTRL_STREAM1_PKT_PER_LINE__SHIFT) & 
DSI_COMMAND_COMPRESSION_MODE_CTRL_STREAM1_PKT_PER_LINE__MASK;
+}
+#define DSI_COMMAND_COMPRESSION_MODE_CTRL_STREAM1_EOL_BYTE_NUM__MASK   
0x0030
+#define DSI_COMMAND_COMPRESSION_MODE_CTRL_STREAM1_EOL_BYTE_NUM__SHIFT  20
+static inline uint32_t 
DSI_COMMAND_COMPRESSION_MODE_CTRL_STREAM1_EOL_BYTE_NUM(uint32_t val)
+{
+   return ((val) << 
DSI_COMMAND_COMPRESSION_MODE_CTRL_STREAM1_EOL_BYTE_NUM__SHIFT) & 
DSI_COMMAND_COMPRESSION_MODE_CTRL_STREAM1_EOL_BYTE_NUM__MASK;
+}
+#define DSI_COMMAND_COMPRESSION_MODE_CTRL_STREAM1_EN   0x0001
+#define DSI_COMMAND_COMPRESSION_MODE_CTRL_STREAM0_DATATYPE__MASK   
0x3f00
+#define DSI_COMMAND_COMPRESSION_MODE_CTRL_STREAM0_DATATYPE__SHIFT  8
+static inline uint32_t 
DSI_COMMAND_COMPRESSION_MODE_CTRL_STREAM0_DATATYPE(uint32_t val)
+{
+   return ((val) << 
DSI_COMMAND_COMPRESSION_MODE_CTRL_STREAM0_DATATYPE__SHIFT) & 
DSI_COMMAND_COMPRESSION_MODE_CTRL_STREAM0_DATATYPE__MASK;
+}
+#define DSI_COMMAND_COMPRESSION_MODE_CTRL_STREAM0_PKT_PER_LINE__MASK   
0x00c0
+#define DSI_COMMAND_COMPRESSION_MODE_CTRL_STREAM0_PKT_PER_LINE__SHIFT  6
+static inline uint32_t 
DSI_COMMAND_COMPRESSION_MODE_CTRL_STREAM0_PKT_PER_LINE(uint32_t val)
+{
+   return ((val) << 
DSI_COMMAND_COMPRESSION_MODE_CTRL_STREAM0_PKT_PER_LINE__SHIFT) & 
DSI_COMMAND_COMPRESSION_MODE_CTRL_STREAM0_PKT_PER_LINE__MASK;
+}
+#define DSI_COMMAND_COMPRESSION_MODE_CTRL_STREAM0_EOL_BYTE_NUM__MASK   
0x0030
+

[Freedreno] [PATCH v7 12/14] drm/msm/dsi: add mode valid callback for dsi_mgr

2022-04-06 Thread Vinod Koul
Add a mode valid callback for dsi_mgr for checking mode being valid in
case of DSC. For DSC the height and width needs to be multiple of slice,
so we check that here

Reviewed-by: Dmitry Baryshkov 
Reviewed-by: Abhinav Kumar 
Signed-off-by: Vinod Koul 
---
 drivers/gpu/drm/msm/dsi/dsi.h |  2 ++
 drivers/gpu/drm/msm/dsi/dsi_host.c| 26 ++
 drivers/gpu/drm/msm/dsi/dsi_manager.c | 12 
 3 files changed, 40 insertions(+)

diff --git a/drivers/gpu/drm/msm/dsi/dsi.h b/drivers/gpu/drm/msm/dsi/dsi.h
index 16cd9b2fce86..580a1e6358bf 100644
--- a/drivers/gpu/drm/msm/dsi/dsi.h
+++ b/drivers/gpu/drm/msm/dsi/dsi.h
@@ -114,6 +114,8 @@ int msm_dsi_host_power_on(struct mipi_dsi_host *host,
 int msm_dsi_host_power_off(struct mipi_dsi_host *host);
 int msm_dsi_host_set_display_mode(struct mipi_dsi_host *host,
  const struct drm_display_mode *mode);
+enum drm_mode_status msm_dsi_host_check_dsc(struct mipi_dsi_host *host,
+   const struct drm_display_mode 
*mode);
 struct drm_panel *msm_dsi_host_get_panel(struct mipi_dsi_host *host);
 unsigned long msm_dsi_host_get_mode_flags(struct mipi_dsi_host *host);
 struct drm_bridge *msm_dsi_host_get_bridge(struct mipi_dsi_host *host);
diff --git a/drivers/gpu/drm/msm/dsi/dsi_host.c 
b/drivers/gpu/drm/msm/dsi/dsi_host.c
index cb2e179127ea..eb0be34add45 100644
--- a/drivers/gpu/drm/msm/dsi/dsi_host.c
+++ b/drivers/gpu/drm/msm/dsi/dsi_host.c
@@ -2554,6 +2554,32 @@ int msm_dsi_host_set_display_mode(struct mipi_dsi_host 
*host,
return 0;
 }
 
+enum drm_mode_status msm_dsi_host_check_dsc(struct mipi_dsi_host *host,
+   const struct drm_display_mode *mode)
+{
+   struct msm_dsi_host *msm_host = to_msm_dsi_host(host);
+   struct msm_display_dsc_config *dsc = msm_host->dsc;
+   int pic_width = mode->hdisplay;
+   int pic_height = mode->vdisplay;
+
+   if (!msm_host->dsc)
+   return MODE_OK;
+
+   if (pic_width % dsc->drm->slice_width) {
+   pr_err("DSI: pic_width %d has to be multiple of slice %d\n",
+  pic_width, dsc->drm->slice_width);
+   return MODE_H_ILLEGAL;
+   }
+
+   if (pic_height % dsc->drm->slice_height) {
+   pr_err("DSI: pic_height %d has to be multiple of slice %d\n",
+  pic_height, dsc->drm->slice_height);
+   return MODE_V_ILLEGAL;
+   }
+
+   return MODE_OK;
+}
+
 struct drm_panel *msm_dsi_host_get_panel(struct mipi_dsi_host *host)
 {
return of_drm_find_panel(to_msm_dsi_host(host)->device_node);
diff --git a/drivers/gpu/drm/msm/dsi/dsi_manager.c 
b/drivers/gpu/drm/msm/dsi/dsi_manager.c
index 0c1b7dde377c..100a8fcbddee 100644
--- a/drivers/gpu/drm/msm/dsi/dsi_manager.c
+++ b/drivers/gpu/drm/msm/dsi/dsi_manager.c
@@ -573,6 +573,17 @@ static void dsi_mgr_bridge_mode_set(struct drm_bridge 
*bridge,
dsi_mgr_bridge_power_on(bridge);
 }
 
+static enum drm_mode_status dsi_mgr_bridge_mode_valid(struct drm_bridge 
*bridge,
+ const struct 
drm_display_info *info,
+ const struct 
drm_display_mode *mode)
+{
+   int id = dsi_mgr_bridge_get_id(bridge);
+   struct msm_dsi *msm_dsi = dsi_mgr_get_dsi(id);
+   struct mipi_dsi_host *host = msm_dsi->host;
+
+   return msm_dsi_host_check_dsc(host, mode);
+}
+
 static const struct drm_connector_funcs dsi_mgr_connector_funcs = {
.detect = dsi_mgr_connector_detect,
.fill_modes = drm_helper_probe_single_connector_modes,
@@ -593,6 +604,7 @@ static const struct drm_bridge_funcs dsi_mgr_bridge_funcs = 
{
.disable = dsi_mgr_bridge_disable,
.post_disable = dsi_mgr_bridge_post_disable,
.mode_set = dsi_mgr_bridge_mode_set,
+   .mode_valid = dsi_mgr_bridge_mode_valid,
 };
 
 /* initialize connector when we're connected to a drm_panel */
-- 
2.34.1



[Freedreno] [PATCH v7 11/14] drm/msm/disp/dpu1: Add DSC support in RM

2022-04-06 Thread Vinod Koul
This add the bits in RM to enable the DSC blocks

Reviewed-by: Dmitry Baryshkov 
Reviewed-by: Abhinav Kumar 
Signed-off-by: Vinod Koul 
---
 drivers/gpu/drm/msm/disp/dpu1/dpu_kms.h |  1 +
 drivers/gpu/drm/msm/disp/dpu1/dpu_rm.c  | 56 +
 drivers/gpu/drm/msm/disp/dpu1/dpu_rm.h  |  1 +
 3 files changed, 58 insertions(+)

diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_kms.h 
b/drivers/gpu/drm/msm/disp/dpu1/dpu_kms.h
index 779e7bd01efd..a41f0eb2761b 100644
--- a/drivers/gpu/drm/msm/disp/dpu1/dpu_kms.h
+++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_kms.h
@@ -145,6 +145,7 @@ struct dpu_global_state {
uint32_t mixer_to_enc_id[LM_MAX - LM_0];
uint32_t ctl_to_enc_id[CTL_MAX - CTL_0];
uint32_t dspp_to_enc_id[DSPP_MAX - DSPP_0];
+   uint32_t dsc_to_enc_id[DSC_MAX - DSC_0];
 };
 
 struct dpu_global_state
diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_rm.c 
b/drivers/gpu/drm/msm/disp/dpu1/dpu_rm.c
index 7497538adae1..0e6634b217aa 100644
--- a/drivers/gpu/drm/msm/disp/dpu1/dpu_rm.c
+++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_rm.c
@@ -11,6 +11,7 @@
 #include "dpu_hw_intf.h"
 #include "dpu_hw_dspp.h"
 #include "dpu_hw_merge3d.h"
+#include "dpu_hw_dsc.h"
 #include "dpu_encoder.h"
 #include "dpu_trace.h"
 
@@ -77,6 +78,15 @@ int dpu_rm_destroy(struct dpu_rm *rm)
for (i = 0; i < ARRAY_SIZE(rm->hw_intf); i++)
dpu_hw_intf_destroy(rm->hw_intf[i]);
 
+   for (i = 0; i < ARRAY_SIZE(rm->dsc_blks); i++) {
+   struct dpu_hw_dsc *hw;
+
+   if (rm->dsc_blks[i]) {
+   hw = to_dpu_hw_dsc(rm->dsc_blks[i]);
+   dpu_hw_dsc_destroy(hw);
+   }
+   }
+
return 0;
 }
 
@@ -210,6 +220,19 @@ int dpu_rm_init(struct dpu_rm *rm,
rm->dspp_blks[dspp->id - DSPP_0] = &hw->base;
}
 
+   for (i = 0; i < cat->dsc_count; i++) {
+   struct dpu_hw_dsc *hw;
+   const struct dpu_dsc_cfg *dsc = &cat->dsc[i];
+
+   hw = dpu_hw_dsc_init(dsc->id, mmio, cat);
+   if (IS_ERR_OR_NULL(hw)) {
+   rc = PTR_ERR(hw);
+   DPU_ERROR("failed dsc object creation: err %d\n", rc);
+   goto fail;
+   }
+   rm->dsc_blks[dsc->id - DSC_0] = &hw->base;
+   }
+
return 0;
 
 fail:
@@ -441,6 +464,28 @@ static int _dpu_rm_reserve_ctls(
return 0;
 }
 
+static int _dpu_rm_reserve_dsc(struct dpu_rm *rm,
+  struct dpu_global_state *global_state,
+  struct drm_encoder *enc,
+  const struct msm_display_topology *top)
+{
+   int num_dsc = top->num_dsc;
+   int i;
+
+   /* check if DSC required are allocated or not */
+   for (i = 0; i < num_dsc; i++) {
+   if (global_state->dsc_to_enc_id[i]) {
+   DPU_ERROR("DSC %d is already allocated\n", i);
+   return -EIO;
+   }
+   }
+
+   for (i = 0; i < num_dsc; i++)
+   global_state->dsc_to_enc_id[i] = enc->base.id;
+
+   return 0;
+}
+
 static int _dpu_rm_make_reservation(
struct dpu_rm *rm,
struct dpu_global_state *global_state,
@@ -462,6 +507,10 @@ static int _dpu_rm_make_reservation(
return ret;
}
 
+   ret  = _dpu_rm_reserve_dsc(rm, global_state, enc, &reqs->topology);
+   if (ret)
+   return ret;
+
return ret;
 }
 
@@ -499,6 +548,8 @@ void dpu_rm_release(struct dpu_global_state *global_state,
ARRAY_SIZE(global_state->mixer_to_enc_id), enc->base.id);
_dpu_rm_clear_mapping(global_state->ctl_to_enc_id,
ARRAY_SIZE(global_state->ctl_to_enc_id), enc->base.id);
+   _dpu_rm_clear_mapping(global_state->dsc_to_enc_id,
+   ARRAY_SIZE(global_state->dsc_to_enc_id), enc->base.id);
 }
 
 int dpu_rm_reserve(
@@ -567,6 +618,11 @@ int dpu_rm_get_assigned_resources(struct dpu_rm *rm,
hw_to_enc_id = global_state->dspp_to_enc_id;
max_blks = ARRAY_SIZE(rm->dspp_blks);
break;
+   case DPU_HW_BLK_DSC:
+   hw_blks = rm->dsc_blks;
+   hw_to_enc_id = global_state->dsc_to_enc_id;
+   max_blks = ARRAY_SIZE(rm->dsc_blks);
+   break;
default:
DPU_ERROR("blk type %d not managed by rm\n", type);
return 0;
diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_rm.h 
b/drivers/gpu/drm/msm/disp/dpu1/dpu_rm.h
index 9b13200a050a..32e0d8aa65ab 100644
--- a/drivers/gpu/drm/msm/disp/dpu1/dpu_rm.h
+++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_rm.h
@@ -28,6 +28,7 @@ struct dpu_rm {
struct d

[Freedreno] [PATCH v7 10/14] drm/msm/disp/dpu1: Add support for DSC in topology

2022-04-06 Thread Vinod Koul
For DSC to work we typically need a 2,2,1 configuration. This should
suffice for resolutions up to 4k. For more resolutions like 8k this won't
work.

Also, it is better to use 2 LMs and DSC instances as half width results
in lesser power consumption as compared to single LM, DSC at full width.

The panel has been tested only with 2,2,1 configuration, so for
now we blindly create 2,2,1 topology when DSC is enabled

Co-developed-by: Abhinav Kumar 
Signed-off-by: Abhinav Kumar 
Reviewed-by: Dmitry Baryshkov 
Signed-off-by: Vinod Koul 
---
 drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c | 13 +
 drivers/gpu/drm/msm/msm_drv.h   |  2 ++
 2 files changed, 15 insertions(+)

diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c 
b/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c
index 95d1588f3bb6..51f24ba68375 100644
--- a/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c
+++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c
@@ -567,8 +567,21 @@ static struct msm_display_topology 
dpu_encoder_get_topology(
topology.num_enc = 0;
topology.num_intf = intf_count;
 
+   if (dpu_enc->dsc) {
+   /* In case of Display Stream Compression (DSC), we would use
+* 2 encoders, 2 layer mixers and 1 interface
+* this is power optimal and can drive up to (including) 4k
+* screens
+*/
+   topology.num_enc = 2;
+   topology.num_dsc = 2;
+   topology.num_intf = 1;
+   topology.num_lm = 2;
+   }
+
return topology;
 }
+
 static int dpu_encoder_virt_atomic_check(
struct drm_encoder *drm_enc,
struct drm_crtc_state *crtc_state,
diff --git a/drivers/gpu/drm/msm/msm_drv.h b/drivers/gpu/drm/msm/msm_drv.h
index bf2ccff97562..0ace9b0549a4 100644
--- a/drivers/gpu/drm/msm/msm_drv.h
+++ b/drivers/gpu/drm/msm/msm_drv.h
@@ -103,12 +103,14 @@ enum msm_event_wait {
  * @num_enc:  number of compression encoder blocks used
  * @num_intf: number of interfaces the panel is mounted on
  * @num_dspp: number of dspp blocks used
+ * @num_dsc:  number of Display Stream Compression (DSC) blocks used
  */
 struct msm_display_topology {
u32 num_lm;
u32 num_enc;
u32 num_intf;
u32 num_dspp;
+   u32 num_dsc;
 };
 
 /* Commit/Event thread specific structure */
-- 
2.34.1



[Freedreno] [PATCH v7 09/14] drm/msm: Add missing num_dspp field documentation

2022-04-06 Thread Vinod Koul
Somehow documentation for num_dspp was missed, so add that

Reviewed-by: Dmitry Baryshkov 
Reviewed-by: Abhinav Kumar 
Signed-off-by: Vinod Koul 
---
 drivers/gpu/drm/msm/msm_drv.h | 1 +
 1 file changed, 1 insertion(+)

diff --git a/drivers/gpu/drm/msm/msm_drv.h b/drivers/gpu/drm/msm/msm_drv.h
index 2a3280df7b12..bf2ccff97562 100644
--- a/drivers/gpu/drm/msm/msm_drv.h
+++ b/drivers/gpu/drm/msm/msm_drv.h
@@ -102,6 +102,7 @@ enum msm_event_wait {
  * @num_lm:   number of layer mixers used
  * @num_enc:  number of compression encoder blocks used
  * @num_intf: number of interfaces the panel is mounted on
+ * @num_dspp: number of dspp blocks used
  */
 struct msm_display_topology {
u32 num_lm;
-- 
2.34.1



[Freedreno] [PATCH v7 08/14] drm/msm/dpu: don't use merge_3d if DSC merge topology is used

2022-04-06 Thread Vinod Koul
From: Dmitry Baryshkov 

DPU supports different topologies for the case when multiple INTFs are
being driven by the single phys_enc. The driver defaults to using 3DMux
in such cases. Don't use it if DSC merge is used instead.

Suggested-by: Abhinav Kumar 
Signed-off-by: Dmitry Baryshkov 
Signed-off-by: Vinod Koul 
---
 drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c  | 16 
 drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.h  |  6 ++
 drivers/gpu/drm/msm/disp/dpu1/dpu_encoder_phys.h |  4 +++-
 3 files changed, 25 insertions(+), 1 deletion(-)

diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c 
b/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c
index 4052486f19d8..95d1588f3bb6 100644
--- a/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c
+++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c
@@ -511,6 +511,22 @@ void dpu_encoder_helper_split_config(
}
 }
 
+bool dpu_encoder_use_dsc_merge(struct drm_encoder *drm_enc)
+{
+   struct dpu_encoder_virt *dpu_enc = to_dpu_encoder_virt(drm_enc);
+   int i, intf_count = 0, num_dsc = 0;
+
+   for (i = 0; i < MAX_PHYS_ENCODERS_PER_VIRTUAL; i++)
+   if (dpu_enc->phys_encs[i])
+   intf_count++;
+
+   /* See dpu_encoder_get_topology, we only support 2:2:1 topology */
+   if (dpu_enc->dsc)
+   num_dsc = 2;
+
+   return (num_dsc > 0) && (num_dsc > intf_count);
+}
+
 static struct msm_display_topology dpu_encoder_get_topology(
struct dpu_encoder_virt *dpu_enc,
struct dpu_kms *dpu_kms,
diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.h 
b/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.h
index ef873e5285a0..084c5265d7e5 100644
--- a/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.h
+++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.h
@@ -172,4 +172,10 @@ int dpu_encoder_get_linecount(struct drm_encoder *drm_enc);
  */
 int dpu_encoder_get_vsync_count(struct drm_encoder *drm_enc);
 
+/**
+ * dpu_encoder_use_dsc_merge - returns true if the encoder uses DSC merge 
topology.
+ * @drm_enc:Pointer to previously created drm encoder structure
+ */
+bool dpu_encoder_use_dsc_merge(struct drm_encoder *drm_enc);
+
 #endif /* __DPU_ENCODER_H__ */
diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder_phys.h 
b/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder_phys.h
index 4842070fdfa8..b5ad43b8a19b 100644
--- a/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder_phys.h
+++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder_phys.h
@@ -314,8 +314,10 @@ static inline enum dpu_3d_blend_mode 
dpu_encoder_helper_get_3d_blend_mode(
 
dpu_cstate = to_dpu_crtc_state(phys_enc->parent->crtc->state);
 
+   /* Use merge_3d unless DSC MERGE topology is used */
if (phys_enc->split_role == ENC_ROLE_SOLO &&
-   dpu_cstate->num_mixers == CRTC_DUAL_MIXERS)
+   dpu_cstate->num_mixers == CRTC_DUAL_MIXERS &&
+   !dpu_encoder_use_dsc_merge(phys_enc->parent))
return BLEND_3D_H_ROW_INT;
 
return BLEND_3D_NONE;
-- 
2.34.1



[Freedreno] [PATCH v7 07/14] drm/msm/disp/dpu1: Add support for DSC in encoder

2022-04-06 Thread Vinod Koul
We need to configure the encoder for DSC configuration and calculate DSC
parameters for the given timing so this patch adds that support by
adding dpu_encoder_prep_dsc() which is invoked when DSC is enabled.

Reviewed-by: Dmitry Baryshkov 
Reviewed-by: Abhinav Kumar 
Signed-off-by: Vinod Koul 
---
 drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c   | 128 +-
 .../gpu/drm/msm/disp/dpu1/dpu_encoder_phys.h  |   8 ++
 2 files changed, 135 insertions(+), 1 deletion(-)

diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c 
b/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c
index 3940b9c6323b..4052486f19d8 100644
--- a/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c
+++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c
@@ -21,6 +21,7 @@
 #include "dpu_hw_intf.h"
 #include "dpu_hw_ctl.h"
 #include "dpu_hw_dspp.h"
+#include "dpu_hw_dsc.h"
 #include "dpu_formats.h"
 #include "dpu_encoder_phys.h"
 #include "dpu_crtc.h"
@@ -135,6 +136,8 @@ enum dpu_enc_rc_states {
  * @cur_slave: As above but for the slave encoder.
  * @hw_pp: Handle to the pingpong blocks used for the display. No.
  * pingpong blocks can be different than num_phys_encs.
+ * @hw_dsc:Handle to the DSC blocks used for the display.
+ * @dsc_mask:  Bitmask of used DSC blocks.
  * @intfs_swapped: Whether or not the phys_enc interfaces have been swapped
  * for partial update right-only cases, such as pingpong
  * split where virtual pingpong does not generate IRQs
@@ -168,6 +171,7 @@ enum dpu_enc_rc_states {
  * @vsync_event_work:  worker to handle vsync event for autorefresh
  * @topology:   topology of the display
  * @idle_timeout:  idle timeout duration in milliseconds
+ * @dsc:   msm_display_dsc_config pointer, for DSC-enabled 
encoders
  */
 struct dpu_encoder_virt {
struct drm_encoder base;
@@ -180,6 +184,9 @@ struct dpu_encoder_virt {
struct dpu_encoder_phys *cur_master;
struct dpu_encoder_phys *cur_slave;
struct dpu_hw_pingpong *hw_pp[MAX_CHANNELS_PER_ENC];
+   struct dpu_hw_dsc *hw_dsc[MAX_CHANNELS_PER_ENC];
+
+   unsigned int dsc_mask;
 
bool intfs_swapped;
 
@@ -206,6 +213,9 @@ struct dpu_encoder_virt {
struct msm_display_topology topology;
 
u32 idle_timeout;
+
+   /* DSC configuration */
+   struct msm_display_dsc_config *dsc;
 };
 
 #define to_dpu_encoder_virt(x) container_of(x, struct dpu_encoder_virt, base)
@@ -942,7 +952,9 @@ static void dpu_encoder_virt_atomic_mode_set(struct 
drm_encoder *drm_enc,
struct dpu_hw_blk *hw_ctl[MAX_CHANNELS_PER_ENC];
struct dpu_hw_blk *hw_lm[MAX_CHANNELS_PER_ENC];
struct dpu_hw_blk *hw_dspp[MAX_CHANNELS_PER_ENC] = { NULL };
-   int num_lm, num_ctl, num_pp;
+   struct dpu_hw_blk *hw_dsc[MAX_CHANNELS_PER_ENC];
+   int num_lm, num_ctl, num_pp, num_dsc;
+   unsigned int dsc_mask = 0;
int i;
 
if (!drm_enc) {
@@ -980,6 +992,18 @@ static void dpu_encoder_virt_atomic_mode_set(struct 
drm_encoder *drm_enc,
dpu_enc->hw_pp[i] = i < num_pp ? to_dpu_hw_pingpong(hw_pp[i])
: NULL;
 
+   if (dpu_enc->dsc) {
+   num_dsc = dpu_rm_get_assigned_resources(&dpu_kms->rm, 
global_state,
+   drm_enc->base.id, 
DPU_HW_BLK_DSC,
+   hw_dsc, 
ARRAY_SIZE(hw_dsc));
+   for (i = 0; i < num_dsc; i++) {
+   dpu_enc->hw_dsc[i] = to_dpu_hw_dsc(hw_dsc[i]);
+   dsc_mask |= BIT(dpu_enc->hw_dsc[i]->idx - DSC_0);
+   }
+   }
+
+   dpu_enc->dsc_mask = dsc_mask;
+
cstate = to_dpu_crtc_state(crtc_state);
 
for (i = 0; i < num_lm; i++) {
@@ -1677,6 +1701,95 @@ static void dpu_encoder_vsync_event_work_handler(struct 
kthread_work *work)
nsecs_to_jiffies(ktime_to_ns(wakeup_time)));
 }
 
+static u32
+dpu_encoder_dsc_initial_line_calc(struct msm_display_dsc_config *dsc,
+ u32 enc_ip_width)
+{
+   int ssm_delay, total_pixels, soft_slice_per_enc;
+
+   soft_slice_per_enc = enc_ip_width / dsc->drm->slice_width;
+
+   /*
+* minimum number of initial line pixels is a sum of:
+* 1. sub-stream multiplexer delay (83 groups for 8bpc,
+*91 for 10 bpc) * 3
+* 2. for two soft slice cases, add extra sub-stream multiplexer * 3
+* 3. the initial xmit delay
+* 4. total pipeline delay through the "lock step" of encoder (47)
+* 5. 6 additional pixels as the output of the rate buffer is
+*48 bits wide
+*/
+   ssm_delay = ((dsc->drm->bits_per_com

[Freedreno] [PATCH v7 06/14] drm/msm/disp/dpu1: Add DSC support in hw_ctl

2022-04-06 Thread Vinod Koul
Later gens of hardware have DSC bits moved to hw_ctl, so configure these
bits so that DSC would work there as well

Reviewed-by: Dmitry Baryshkov 
Reviewed-by: Abhinav Kumar 
Signed-off-by: Vinod Koul 
---
 drivers/gpu/drm/msm/disp/dpu1/dpu_hw_ctl.c | 11 ++-
 drivers/gpu/drm/msm/disp/dpu1/dpu_hw_ctl.h |  2 ++
 2 files changed, 12 insertions(+), 1 deletion(-)

diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_ctl.c 
b/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_ctl.c
index 3584f5ee6bb3..dc27579bb5f6 100644
--- a/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_ctl.c
+++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_ctl.c
@@ -25,6 +25,8 @@
 #define   CTL_MERGE_3D_ACTIVE   0x0E4
 #define   CTL_INTF_ACTIVE   0x0F4
 #define   CTL_MERGE_3D_FLUSH0x100
+#define   CTL_DSC_ACTIVE0x0E8
+#define   CTL_DSC_FLUSH0x104
 #define   CTL_INTF_FLUSH0x110
 #define   CTL_INTF_MASTER   0x134
 #define   CTL_FETCH_PIPE_ACTIVE 0x0FC
@@ -34,6 +36,7 @@
 
 #define DPU_REG_RESET_TIMEOUT_US2000
 #define  MERGE_3D_IDX   23
+#define  DSC_IDX22
 #define  INTF_IDX   31
 #define CTL_INVALID_BIT 0x
 #define CTL_DEFAULT_GROUP_ID   0xf
@@ -126,7 +129,6 @@ static u32 dpu_hw_ctl_get_pending_flush(struct dpu_hw_ctl 
*ctx)
 
 static inline void dpu_hw_ctl_trigger_flush_v1(struct dpu_hw_ctl *ctx)
 {
-
if (ctx->pending_flush_mask & BIT(MERGE_3D_IDX))
DPU_REG_WRITE(&ctx->hw, CTL_MERGE_3D_FLUSH,
ctx->pending_merge_3d_flush_mask);
@@ -511,6 +513,9 @@ static void dpu_hw_ctl_intf_cfg_v1(struct dpu_hw_ctl *ctx,
if ((test_bit(DPU_CTL_VM_CFG, &ctx->caps->features)))
mode_sel = CTL_DEFAULT_GROUP_ID  << 28;
 
+   if (cfg->dsc)
+   DPU_REG_WRITE(&ctx->hw, CTL_DSC_FLUSH, cfg->dsc);
+
if (cfg->intf_mode_sel == DPU_CTL_MODE_SEL_CMD)
mode_sel |= BIT(17);
 
@@ -522,6 +527,10 @@ static void dpu_hw_ctl_intf_cfg_v1(struct dpu_hw_ctl *ctx,
if (cfg->merge_3d)
DPU_REG_WRITE(c, CTL_MERGE_3D_ACTIVE,
  BIT(cfg->merge_3d - MERGE_3D_0));
+   if (cfg->dsc) {
+   DPU_REG_WRITE(&ctx->hw, CTL_FLUSH, DSC_IDX);
+   DPU_REG_WRITE(c, CTL_DSC_ACTIVE, cfg->dsc);
+   }
 }
 
 static void dpu_hw_ctl_intf_cfg(struct dpu_hw_ctl *ctx,
diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_ctl.h 
b/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_ctl.h
index ac1544474022..97f326dff0af 100644
--- a/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_ctl.h
+++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_ctl.h
@@ -40,6 +40,7 @@ struct dpu_hw_stage_cfg {
  * @merge_3d:  3d merge block used
  * @intf_mode_sel: Interface mode, cmd / vid
  * @stream_sel:Stream selection for multi-stream interfaces
+ * @dsc:   DSC BIT masks used
  */
 struct dpu_hw_intf_cfg {
enum dpu_intf intf;
@@ -47,6 +48,7 @@ struct dpu_hw_intf_cfg {
enum dpu_merge_3d merge_3d;
enum dpu_ctl_mode_sel intf_mode_sel;
int stream_sel;
+   unsigned int dsc;
 };
 
 /**
-- 
2.34.1



[Freedreno] [PATCH v7 05/14] drm/msm/disp/dpu1: Add DSC for SDM845 to hw_catalog

2022-04-06 Thread Vinod Koul
This adds SDM845 DSC blocks into hw_catalog

Reviewed-by: Dmitry Baryshkov 
Reviewed-by: Abhinav Kumar 
Signed-off-by: Vinod Koul 
---
 .../gpu/drm/msm/disp/dpu1/dpu_hw_catalog.c| 20 +++
 1 file changed, 20 insertions(+)

diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_catalog.c 
b/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_catalog.c
index a4fe77cddfea..d15fa5845066 100644
--- a/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_catalog.c
+++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_catalog.c
@@ -1117,6 +1117,24 @@ static const struct dpu_pingpong_cfg sc7280_pp[] = {
PP_BLK("pingpong_2", PINGPONG_2, 0x6b000, 0, sc7280_pp_sblk, -1, -1),
PP_BLK("pingpong_3", PINGPONG_3, 0x6c000, 0, sc7280_pp_sblk, -1, -1),
 };
+
+/*
+ * DSC sub blocks config
+ */
+#define DSC_BLK(_name, _id, _base) \
+   {\
+   .name = _name, .id = _id, \
+   .base = _base, .len = 0x140, \
+   .features = 0, \
+   }
+
+static struct dpu_dsc_cfg sdm845_dsc[] = {
+   DSC_BLK("dsc_0", DSC_0, 0x8),
+   DSC_BLK("dsc_1", DSC_1, 0x80400),
+   DSC_BLK("dsc_2", DSC_2, 0x80800),
+   DSC_BLK("dsc_3", DSC_3, 0x80c00),
+};
+
 /*
  * INTF sub blocks config
  */
@@ -1643,6 +1661,8 @@ static void sdm845_cfg_init(struct dpu_mdss_cfg *dpu_cfg)
.mixer = sdm845_lm,
.pingpong_count = ARRAY_SIZE(sdm845_pp),
.pingpong = sdm845_pp,
+   .dsc_count = ARRAY_SIZE(sdm845_dsc),
+   .dsc = sdm845_dsc,
.intf_count = ARRAY_SIZE(sdm845_intf),
.intf = sdm845_intf,
.vbif_count = ARRAY_SIZE(sdm845_vbif),
-- 
2.34.1



[Freedreno] [PATCH v7 04/14] drm/msm/disp/dpu1: Add support for DSC in pingpong block

2022-04-06 Thread Vinod Koul
In SDM845, DSC can be enabled by writing to pingpong block registers, so
add support for DSC in hw_pp

Reviewed-by: Abhinav Kumar 
Reviewed-by: Dmitry Baryshkov 
Signed-off-by: Vinod Koul 
---
 .../gpu/drm/msm/disp/dpu1/dpu_hw_pingpong.c   | 32 +++
 .../gpu/drm/msm/disp/dpu1/dpu_hw_pingpong.h   | 14 
 2 files changed, 46 insertions(+)

diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_pingpong.c 
b/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_pingpong.c
index 55766c97c4c8..47c6ab6caf95 100644
--- a/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_pingpong.c
+++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_pingpong.c
@@ -28,6 +28,9 @@
 #define PP_FBC_MODE 0x034
 #define PP_FBC_BUDGET_CTL   0x038
 #define PP_FBC_LOSSY_MODE   0x03C
+#define PP_DSC_MODE 0x0a0
+#define PP_DCE_DATA_IN_SWAP 0x0ac
+#define PP_DCE_DATA_OUT_SWAP0x0c8
 
 #define PP_DITHER_EN   0x000
 #define PP_DITHER_BITDEPTH 0x004
@@ -245,6 +248,32 @@ static u32 dpu_hw_pp_get_line_count(struct dpu_hw_pingpong 
*pp)
return line;
 }
 
+static int dpu_hw_pp_dsc_enable(struct dpu_hw_pingpong *pp)
+{
+   struct dpu_hw_blk_reg_map *c = &pp->hw;
+
+   DPU_REG_WRITE(c, PP_DSC_MODE, 1);
+   return 0;
+}
+
+static void dpu_hw_pp_dsc_disable(struct dpu_hw_pingpong *pp)
+{
+   struct dpu_hw_blk_reg_map *c = &pp->hw;
+
+   DPU_REG_WRITE(c, PP_DSC_MODE, 0);
+}
+
+static int dpu_hw_pp_setup_dsc(struct dpu_hw_pingpong *pp)
+{
+   struct dpu_hw_blk_reg_map *pp_c = &pp->hw;
+   int data;
+
+   data = DPU_REG_READ(pp_c, PP_DCE_DATA_OUT_SWAP);
+   data |= BIT(18); /* endian flip */
+   DPU_REG_WRITE(pp_c, PP_DCE_DATA_OUT_SWAP, data);
+   return 0;
+}
+
 static void _setup_pingpong_ops(struct dpu_hw_pingpong *c,
unsigned long features)
 {
@@ -256,6 +285,9 @@ static void _setup_pingpong_ops(struct dpu_hw_pingpong *c,
c->ops.get_autorefresh = dpu_hw_pp_get_autorefresh_config;
c->ops.poll_timeout_wr_ptr = dpu_hw_pp_poll_timeout_wr_ptr;
c->ops.get_line_count = dpu_hw_pp_get_line_count;
+   c->ops.setup_dsc = dpu_hw_pp_setup_dsc;
+   c->ops.enable_dsc = dpu_hw_pp_dsc_enable;
+   c->ops.disable_dsc = dpu_hw_pp_dsc_disable;
 
if (test_bit(DPU_PINGPONG_DITHER, &features))
c->ops.setup_dither = dpu_hw_pp_setup_dither;
diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_pingpong.h 
b/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_pingpong.h
index 89d08a715c16..12758468d9ca 100644
--- a/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_pingpong.h
+++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_pingpong.h
@@ -124,6 +124,20 @@ struct dpu_hw_pingpong_ops {
 */
void (*setup_dither)(struct dpu_hw_pingpong *pp,
struct dpu_hw_dither_cfg *cfg);
+   /**
+* Enable DSC
+*/
+   int (*enable_dsc)(struct dpu_hw_pingpong *pp);
+
+   /**
+* Disable DSC
+*/
+   void (*disable_dsc)(struct dpu_hw_pingpong *pp);
+
+   /**
+* Setup DSC
+*/
+   int (*setup_dsc)(struct dpu_hw_pingpong *pp);
 };
 
 struct dpu_hw_merge_3d;
-- 
2.34.1



[Freedreno] [PATCH v7 03/14] drm/msm/disp/dpu1: Add support for DSC

2022-04-06 Thread Vinod Koul
Display Stream Compression (DSC) is one of the hw blocks in dpu, so add
support by adding hw blocks for DSC

Reviewed-by: Dmitry Baryshkov 
Signed-off-by: Vinod Koul 
---
 drivers/gpu/drm/msm/Makefile  |   1 +
 .../gpu/drm/msm/disp/dpu1/dpu_hw_catalog.h|  13 ++
 drivers/gpu/drm/msm/disp/dpu1/dpu_hw_dsc.c| 215 ++
 drivers/gpu/drm/msm/disp/dpu1/dpu_hw_dsc.h|  80 +++
 drivers/gpu/drm/msm/disp/dpu1/dpu_hw_mdss.h   |  13 ++
 5 files changed, 322 insertions(+)
 create mode 100644 drivers/gpu/drm/msm/disp/dpu1/dpu_hw_dsc.c
 create mode 100644 drivers/gpu/drm/msm/disp/dpu1/dpu_hw_dsc.h

diff --git a/drivers/gpu/drm/msm/Makefile b/drivers/gpu/drm/msm/Makefile
index e9cc7d8ac301..f551ecc0fefa 100644
--- a/drivers/gpu/drm/msm/Makefile
+++ b/drivers/gpu/drm/msm/Makefile
@@ -56,6 +56,7 @@ msm-y := \
disp/dpu1/dpu_formats.o \
disp/dpu1/dpu_hw_catalog.o \
disp/dpu1/dpu_hw_ctl.o \
+   disp/dpu1/dpu_hw_dsc.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 b85b24bd3f53..f05c4cdcb7f9 100644
--- a/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_catalog.h
+++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_catalog.h
@@ -561,6 +561,16 @@ struct dpu_merge_3d_cfg  {
const struct dpu_merge_3d_sub_blks *sblk;
 };
 
+/**
+ * struct dpu_dsc_cfg - information of DSC blocks
+ * @id enum identifying this block
+ * @base   register offset of this block
+ * @features   bit mask identifying sub-blocks/features
+ */
+struct dpu_dsc_cfg {
+   DPU_HW_BLK_INFO;
+};
+
 /**
  * struct dpu_intf_cfg - information of timing engine blocks
  * @id enum identifying this block
@@ -757,6 +767,9 @@ struct dpu_mdss_cfg {
u32 merge_3d_count;
const struct dpu_merge_3d_cfg *merge_3d;
 
+   u32 dsc_count;
+   struct dpu_dsc_cfg *dsc;
+
u32 intf_count;
const struct dpu_intf_cfg *intf;
 
diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_dsc.c 
b/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_dsc.c
new file mode 100644
index ..426224e34900
--- /dev/null
+++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_dsc.c
@@ -0,0 +1,215 @@
+// SPDX-License-Identifier: GPL-2.0-only
+/*
+ * Copyright (c) 2020-2022, Linaro Limited
+ */
+
+#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_COMMON_MODE0x000
+#define DSC_ENC 0X004
+#define DSC_PICTURE 0x008
+#define DSC_SLICE   0x00C
+#define DSC_CHUNK_SIZE  0x010
+#define DSC_DELAY   0x014
+#define DSC_SCALE_INITIAL   0x018
+#define DSC_SCALE_DEC_INTERVAL  0x01C
+#define DSC_SCALE_INC_INTERVAL  0x020
+#define DSC_FIRST_LINE_BPG_OFFSET   0x024
+#define DSC_BPG_OFFSET  0x028
+#define DSC_DSC_OFFSET  0x02C
+#define DSC_FLATNESS0x030
+#define DSC_RC_MODEL_SIZE   0x034
+#define DSC_RC  0x038
+#define DSC_RC_BUF_THRESH   0x03C
+#define DSC_RANGE_MIN_QP0x074
+#define DSC_RANGE_MAX_QP0x0B0
+#define DSC_RANGE_BPG_OFFSET0x0EC
+
+static void dpu_hw_dsc_disable(struct dpu_hw_dsc *dsc)
+{
+   struct dpu_hw_blk_reg_map *c = &dsc->hw;
+
+   DPU_REG_WRITE(c, DSC_COMMON_MODE, 0);
+}
+
+static void dpu_hw_dsc_config(struct dpu_hw_dsc *hw_dsc,
+ struct msm_display_dsc_config *dsc,
+ u32 mode,
+ u32 initial_lines)
+{
+   struct dpu_hw_blk_reg_map *c = &hw_dsc->hw;
+   u32 data, lsb, bpp;
+   u32 slice_last_group_size;
+   u32 det_thresh_flatness;
+   bool is_cmd_mode = !(mode & DSC_MODE_VIDEO);
+
+   DPU_REG_WRITE(c, DSC_COMMON_MODE, mode);
+
+   if (is_cmd_mode)
+   initial_lines += 1;
+
+   slice_last_group_size = 3 - (dsc->drm->slice_width % 3);
+   data = (initial_lines << 20);
+   data |= ((slice_last_group_size - 1) << 18);
+   /* bpp is 6.4 format, 4 LSBs bits are for fractional part */
+   data |= dsc->drm->bits_per_pixel << 12;
+   lsb = dsc->drm->bits_per_pixel % 4;
+   bpp = dsc->drm->bits_per_pixel / 4;
+   bpp *= 4;
+   bpp <<= 4;
+   bpp |= lsb;
+
+   data |= bpp << 8;
+   data |= (dsc->drm->block_pred_enable << 7);
+   data |= (dsc->drm->line_buf_depth << 3);
+   data |= (dsc->drm->simple_422 << 2);
+   data |= (dsc->drm->convert_rgb << 1);
+   data |= dsc->

[Freedreno] [PATCH v7 02/14] drm/msm/dsi: Pass DSC params to drm_panel

2022-04-06 Thread Vinod Koul
When DSC is enabled, we need to get the DSC parameters from the panel
driver, so add a dsc parameter in panel to fetch and pass DSC
configuration for DSI panels to DPU encoder, which will enable and
then configure DSC hardware blocks accordingly.

Signed-off-by: Dmitry Baryshkov 
Reviewed-by: Abhinav Kumar 
Signed-off-by: Vinod Koul 
---
 drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.h |  2 ++
 drivers/gpu/drm/msm/disp/dpu1/dpu_kms.c |  2 ++
 drivers/gpu/drm/msm/dsi/dsi.c   |  5 +
 drivers/gpu/drm/msm/dsi/dsi.h   |  1 +
 drivers/gpu/drm/msm/dsi/dsi_host.c  | 22 +
 drivers/gpu/drm/msm/msm_drv.h   |  6 ++
 include/drm/drm_panel.h |  7 +++
 7 files changed, 45 insertions(+)

diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.h 
b/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.h
index 42db6ce12caf..ef873e5285a0 100644
--- a/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.h
+++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.h
@@ -27,6 +27,7 @@
  *  based on num_of_h_tiles
  * @is_te_using_watchdog_timer:  Boolean to indicate watchdog TE is
  *  used instead of panel TE in cmd mode panels
+ * @dsc:   DSC configuration data for DSC-enabled displays
  */
 struct msm_display_info {
int intf_type;
@@ -34,6 +35,7 @@ struct msm_display_info {
uint32_t num_of_h_tiles;
uint32_t h_tile_instance[MAX_H_TILES_PER_DISPLAY];
bool is_te_using_watchdog_timer;
+   struct msm_display_dsc_config *dsc;
 };
 
 /**
diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_kms.c 
b/drivers/gpu/drm/msm/disp/dpu1/dpu_kms.c
index e29796c4f27b..e64154407425 100644
--- a/drivers/gpu/drm/msm/disp/dpu1/dpu_kms.c
+++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_kms.c
@@ -582,6 +582,8 @@ static int _dpu_kms_initialize_dsi(struct drm_device *dev,
MSM_DISPLAY_CAP_CMD_MODE :
MSM_DISPLAY_CAP_VID_MODE;
 
+   info.dsc = msm_dsi_get_dsc_config(priv->dsi[i]);
+
if (msm_dsi_is_bonded_dsi(priv->dsi[i]) && priv->dsi[other]) {
rc = msm_dsi_modeset_init(priv->dsi[other], dev, 
encoder);
if (rc) {
diff --git a/drivers/gpu/drm/msm/dsi/dsi.c b/drivers/gpu/drm/msm/dsi/dsi.c
index c12e66aa42a3..06a76834be52 100644
--- a/drivers/gpu/drm/msm/dsi/dsi.c
+++ b/drivers/gpu/drm/msm/dsi/dsi.c
@@ -21,6 +21,11 @@ bool msm_dsi_is_cmd_mode(struct msm_dsi *msm_dsi)
return !(host_flags & MIPI_DSI_MODE_VIDEO);
 }
 
+struct msm_display_dsc_config *msm_dsi_get_dsc_config(struct msm_dsi *msm_dsi)
+{
+   return msm_dsi_host_get_dsc_config(msm_dsi->host);
+}
+
 static int dsi_get_phy(struct msm_dsi *msm_dsi)
 {
struct platform_device *pdev = msm_dsi->pdev;
diff --git a/drivers/gpu/drm/msm/dsi/dsi.h b/drivers/gpu/drm/msm/dsi/dsi.h
index c8dedc95428c..16cd9b2fce86 100644
--- a/drivers/gpu/drm/msm/dsi/dsi.h
+++ b/drivers/gpu/drm/msm/dsi/dsi.h
@@ -152,6 +152,7 @@ int dsi_calc_clk_rate_v2(struct msm_dsi_host *msm_host, 
bool is_bonded_dsi);
 int dsi_calc_clk_rate_6g(struct msm_dsi_host *msm_host, bool is_bonded_dsi);
 void msm_dsi_host_snapshot(struct msm_disp_state *disp_state, struct 
mipi_dsi_host *host);
 void msm_dsi_host_test_pattern_en(struct mipi_dsi_host *host);
+struct msm_display_dsc_config *msm_dsi_host_get_dsc_config(struct 
mipi_dsi_host *host);
 
 /* dsi phy */
 struct msm_dsi_phy;
diff --git a/drivers/gpu/drm/msm/dsi/dsi_host.c 
b/drivers/gpu/drm/msm/dsi/dsi_host.c
index 4a8a9b31ce1d..cb2e179127ea 100644
--- a/drivers/gpu/drm/msm/dsi/dsi_host.c
+++ b/drivers/gpu/drm/msm/dsi/dsi_host.c
@@ -2061,9 +2061,24 @@ 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 drm_panel *panel;
int ret;
 
msm_host->dev = dev;
+   panel = msm_dsi_host_get_panel(&msm_host->base);
+
+   if (panel && panel->dsc) {
+   struct msm_display_dsc_config *dsc = msm_host->dsc;
+
+   if (!dsc) {
+   dsc = devm_kzalloc(&msm_host->pdev->dev, sizeof(*dsc), 
GFP_KERNEL);
+   if (!dsc)
+   return -ENOMEM;
+   dsc->drm = panel->dsc;
+   msm_host->dsc = 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);
@@ -2628,3 +2643,10 @@ void msm_dsi_host_test_pattern_en(struct mipi_dsi_host 
*host)
dsi_write(msm_host, 
REG_DSI_TEST_PATTERN_GEN_CMD_STREAM0_TRIGGER,

DSI_TEST_PATTERN_GEN_CMD_STREAM0_TRIGGER_SW_TRIGGER);
 }
+
+struct msm_di

[Freedreno] [PATCH v7 01/14] drm/msm/dsi: add support for dsc data

2022-04-06 Thread Vinod Koul
Display Stream Compression (DSC) parameters need to be calculated. Add
helpers and struct msm_display_dsc_config in msm_drv for this
msm_display_dsc_config uses drm_dsc_config for DSC parameters.

Reviewed-by: Dmitry Baryshkov 
Reviewed-by: Abhinav Kumar 
Signed-off-by: Vinod Koul 
---
 drivers/gpu/drm/msm/dsi/dsi_host.c | 130 +
 drivers/gpu/drm/msm/msm_drv.h  |   6 ++
 2 files changed, 136 insertions(+)

diff --git a/drivers/gpu/drm/msm/dsi/dsi_host.c 
b/drivers/gpu/drm/msm/dsi/dsi_host.c
index d51e70fab93d..4a8a9b31ce1d 100644
--- a/drivers/gpu/drm/msm/dsi/dsi_host.c
+++ b/drivers/gpu/drm/msm/dsi/dsi_host.c
@@ -31,6 +31,8 @@
 
 #define DSI_RESET_TOGGLE_DELAY_MS 20
 
+static int dsi_populate_dsc_params(struct msm_display_dsc_config *dsc);
+
 static int dsi_get_version(const void __iomem *base, u32 *major, u32 *minor)
 {
u32 ver;
@@ -157,6 +159,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;
@@ -1722,6 +1725,133 @@ 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 mux_words_size;
+   int groups_per_line, groups_total;
+   int min_rate_buffer_size;
+   int hrd_delay;
+   int pre_num_extra_mux_bits, num_extra_mux_bits;
+   int slice_bits;
+   int target_bpp_x16;
+   int data;
+   int final_value, final_scale;
+   int i;
+
+   dsc->drm->rc_model_size = 8192;
+   dsc->drm->first_line_bpg_offset = 12;
+   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; /* Not bpp 12 */
+   if (dsc->drm->bits_per_pixel != 8)
+   dsc->drm->initial_offset = 2048;/* bpp = 12 */
+
+   mux_words_size = 48;/* bpc == 8/10 */
+   if (dsc->drm->bits_per_component == 12)
+   mux_words_size = 64;
+
+   dsc->drm->initial_xmit_delay = 512;
+   dsc->drm->initial_scale_value = 32;
+   dsc->drm->first_line_bpg_offset = 12;
+   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;
+
+   /* FIXME: need to call drm_dsc_compute_rc_parameters() so that rest of
+* params are calculated
+*/
+   groups_per_line = DIV_ROUND_UP(dsc->drm->slice_width, 3);
+   dsc->drm->slice_chunk_size = dsc->drm->slice_width * 
dsc->drm->bits_per_pixel / 8;
+   if ((dsc->drm->slice_width * dsc->drm->bits_per_pixel) % 8)
+   dsc->drm->slice_chunk_size++;
+
+   /* rbs-min */
+   min_rate_buffer_size =  dsc->drm->rc_model_size - 
dsc->drm->initial_offset +
+   dsc->drm->initial_xmit_delay * 
dsc->drm->bits_per_pixel +
+   groups_per_line * 
dsc->drm->first_line_bpg_offset;
+
+   hrd_delay = DIV_ROUND_UP(min_rate_buffer_size, 
dsc->drm->bits_per_pixel);
+
+   dsc->drm->initial_dec_delay = hrd_delay - dsc->drm->initial_xmit_delay;
+
+   dsc->drm->initial_scale_value = 8 * dsc->drm->rc_model_size /
+  (dsc->drm->rc_model_size - 
dsc->drm->initial_offset);
+
+   sl

[Freedreno] [PATCH v7 00/14] drm/msm: Add Display Stream Compression Support

2022-04-06 Thread Vinod Koul
Display Stream Compression (DSC) compresses the display stream in host which
is later decoded by panel. This series enables this for Qualcomm msm driver.
This was tested on Google Pixel3 phone which use LGE SW43408 panel.
 
The changes include DSC data and hardware block enabling for DPU1 then
support in encoder. We also add support in DSI and introduce required
topology changes.
 
In order for panel to set the DSC parameters we add dsc in drm_panel and
pass the dsc configuration from the panel driver

Complete changes which enable this for Pixel3 along with panel driver (not
part of this series) and DT changes can be found at:
git.linaro.org/people/vinod.koul/kernel.git pixel/dsc_v7
 
Comments welcome!

Changes since v6:
 - Fix warning reported by kbuild bot
 - Add r-b by Dmitry

Changes since v5:
 - rebase on msm-next
 - use generated header patch from mesa for dsc registers
 - use generated header macros for dsc register calculation
 - remove msm dsc struct (Dmitry)

Changes since v4:
 - Use new apprach based on Abhinav suggestion for dsc with 3d-merge
 - Make common function for dsc timing caln and call that from video and cmd
   mode
 - update description for patch "Pass DSC params to drm_panel"
 - update couple of typos as pointed by Marijn
 - drop dpu_encoder_dsc_pclk_param_calc() as that was duplicating the caln
   done in dsi timing
 - Update copyright to 2022 to new files
 - Update Abhinav's email to new quic one

Changes since v3:
 - Merge changes from Dmitry to have dsc per encoder instance
 - add warning for dsc and mode3d enabled together
 - set dsc in dpu_encoder_phys_vid as well
 - remove dsc hardcoded mask
 - use devm_kzalloc for memory allocation for dsc

Changes since v2:
 - Fix comments by Dimitry except the dsc being global.
 - Move RM patch later for dependency on topology now
 - Add patch for mode valid callback for dsi_mgr
 - Add missing structure documentation patch
 - Fix errors in mode_3d changes
 - Rebase on v5.16-rc1 and test

Changes since v1:
 - Fix various issues spotted by kbuildbot
 - Rebase to v5.15-rc3
 - Remove unused fields and duplicate defines
 - Enable DSC blocks only when DSC is enabled
 - remove sdm845 feature mask, use 0
 - Check for DSC in hw_ctl

Changes since RFC:
 - Drop the DT binding patch as we derive the configuration from panel
 - Drop the drm api patch as we no longer need it (use pps drm api)
 - Fix comments raised by Dimitry
 - Add dsc parameters calculation from downstream

Dmitry Baryshkov (1):
  drm/msm/dpu: don't use merge_3d if DSC merge topology is used

Vinod Koul (13):
  drm/msm/dsi: add support for dsc data
  drm/msm/dsi: Pass DSC params to drm_panel
  drm/msm/disp/dpu1: Add support for DSC
  drm/msm/disp/dpu1: Add support for DSC in pingpong block
  drm/msm/disp/dpu1: Add DSC for SDM845 to hw_catalog
  drm/msm/disp/dpu1: Add DSC support in hw_ctl
  drm/msm/disp/dpu1: Add support for DSC in encoder
  drm/msm: Add missing num_dspp field documentation
  drm/msm/disp/dpu1: Add support for DSC in topology
  drm/msm/disp/dpu1: Add DSC support in RM
  drm/msm/dsi: add mode valid callback for dsi_mgr
  drm/msm: Update generated headers
  drm/msm/dsi: Add support for DSC configuration

 drivers/gpu/drm/msm/Makefile  |   1 +
 drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c   | 157 +-
 drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.h   |   8 +
 .../gpu/drm/msm/disp/dpu1/dpu_encoder_phys.h  |  12 +-
 .../gpu/drm/msm/disp/dpu1/dpu_hw_catalog.c|  20 ++
 .../gpu/drm/msm/disp/dpu1/dpu_hw_catalog.h|  13 +
 drivers/gpu/drm/msm/disp/dpu1/dpu_hw_ctl.c|  11 +-
 drivers/gpu/drm/msm/disp/dpu1/dpu_hw_ctl.h|   2 +
 drivers/gpu/drm/msm/disp/dpu1/dpu_hw_dsc.c| 215 ++
 drivers/gpu/drm/msm/disp/dpu1/dpu_hw_dsc.h|  80 +
 drivers/gpu/drm/msm/disp/dpu1/dpu_hw_mdss.h   |  13 +
 .../gpu/drm/msm/disp/dpu1/dpu_hw_pingpong.c   |  32 ++
 .../gpu/drm/msm/disp/dpu1/dpu_hw_pingpong.h   |  14 +
 drivers/gpu/drm/msm/disp/dpu1/dpu_kms.c   |   2 +
 drivers/gpu/drm/msm/disp/dpu1/dpu_kms.h   |   1 +
 drivers/gpu/drm/msm/disp/dpu1/dpu_rm.c|  56 
 drivers/gpu/drm/msm/disp/dpu1/dpu_rm.h|   1 +
 drivers/gpu/drm/msm/dsi/dsi.c |   5 +
 drivers/gpu/drm/msm/dsi/dsi.h |   3 +
 drivers/gpu/drm/msm/dsi/dsi.xml.h |  80 +
 drivers/gpu/drm/msm/dsi/dsi_host.c| 276 +-
 drivers/gpu/drm/msm/dsi/dsi_manager.c |  12 +
 drivers/gpu/drm/msm/msm_drv.h |  15 +
 include/drm/drm_panel.h   |   7 +
 24 files changed, 1032 insertions(+), 4 deletions(-)
 create mode 100644 drivers/gpu/drm/msm/disp/dpu1/dpu_hw_dsc.c
 create mode 100644 drivers/gpu/drm/msm/disp/dpu1/dpu_hw_dsc.h

-- 
2.34.1



Re: [Freedreno] [PATCH v6 14/14] drm/msm/dsi: Add support for DSC configuration

2022-04-05 Thread Vinod Koul
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 
> > Signed-off-by: Vinod Koul 
> > ---
> >   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_ 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

-- 
~Vinod


[Freedreno] [PATCH v6 14/14] drm/msm/dsi: Add support for DSC configuration

2022-04-04 Thread Vinod Koul
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 
Signed-off-by: Vinod Koul 
---
 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_ 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_tim

[Freedreno] [PATCH v6 13/14] drm/msm: Update generated headers

2022-04-04 Thread Vinod Koul
Update headers from mesa commit:

  commit 28ae397be111c37c6ced397e12d453a7695701bd
  Author: Vinod Koul 
  Date:   Fri Apr 1 16:53:04 2022 +0530

  freedreno/registers: update dsi registers to support dsc

  Display Stream compression (DSC) compresses the display stream in
  host which is later decoded by panel. This requires addition of 3 new
  DSI registers to support DSC over DSI.

  Signed-off-by: Vinod Koul 
  Part-of: <https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/14967>

Signed-off-by: Vinod Koul 
---
 drivers/gpu/drm/msm/dsi/dsi.xml.h | 80 +++
 1 file changed, 80 insertions(+)

diff --git a/drivers/gpu/drm/msm/dsi/dsi.xml.h 
b/drivers/gpu/drm/msm/dsi/dsi.xml.h
index 4dee6f0bdda6..d1b2a17b0a66 100644
--- a/drivers/gpu/drm/msm/dsi/dsi.xml.h
+++ b/drivers/gpu/drm/msm/dsi/dsi.xml.h
@@ -704,5 +704,85 @@ static inline uint32_t DSI_VERSION_MAJOR(uint32_t val)
 
 #define REG_DSI_CPHY_MODE_CTRL 0x02d4
 
+#define REG_DSI_VIDEO_COMPRESSION_MODE_CTRL0x029c
+#define DSI_VIDEO_COMPRESSION_MODE_CTRL_WC__MASK   0x
+#define DSI_VIDEO_COMPRESSION_MODE_CTRL_WC__SHIFT  16
+static inline uint32_t DSI_VIDEO_COMPRESSION_MODE_CTRL_WC(uint32_t val)
+{
+   return ((val) << DSI_VIDEO_COMPRESSION_MODE_CTRL_WC__SHIFT) & 
DSI_VIDEO_COMPRESSION_MODE_CTRL_WC__MASK;
+}
+#define DSI_VIDEO_COMPRESSION_MODE_CTRL_DATATYPE__MASK 0x3f00
+#define DSI_VIDEO_COMPRESSION_MODE_CTRL_DATATYPE__SHIFT8
+static inline uint32_t DSI_VIDEO_COMPRESSION_MODE_CTRL_DATATYPE(uint32_t val)
+{
+   return ((val) << DSI_VIDEO_COMPRESSION_MODE_CTRL_DATATYPE__SHIFT) & 
DSI_VIDEO_COMPRESSION_MODE_CTRL_DATATYPE__MASK;
+}
+#define DSI_VIDEO_COMPRESSION_MODE_CTRL_PKT_PER_LINE__MASK 0x00c0
+#define DSI_VIDEO_COMPRESSION_MODE_CTRL_PKT_PER_LINE__SHIFT6
+static inline uint32_t DSI_VIDEO_COMPRESSION_MODE_CTRL_PKT_PER_LINE(uint32_t 
val)
+{
+   return ((val) << DSI_VIDEO_COMPRESSION_MODE_CTRL_PKT_PER_LINE__SHIFT) & 
DSI_VIDEO_COMPRESSION_MODE_CTRL_PKT_PER_LINE__MASK;
+}
+#define DSI_VIDEO_COMPRESSION_MODE_CTRL_EOL_BYTE_NUM__MASK 0x0030
+#define DSI_VIDEO_COMPRESSION_MODE_CTRL_EOL_BYTE_NUM__SHIFT4
+static inline uint32_t DSI_VIDEO_COMPRESSION_MODE_CTRL_EOL_BYTE_NUM(uint32_t 
val)
+{
+   return ((val) << DSI_VIDEO_COMPRESSION_MODE_CTRL_EOL_BYTE_NUM__SHIFT) & 
DSI_VIDEO_COMPRESSION_MODE_CTRL_EOL_BYTE_NUM__MASK;
+}
+#define DSI_VIDEO_COMPRESSION_MODE_CTRL_EN 0x0001
+
+#define REG_DSI_COMMAND_COMPRESSION_MODE_CTRL  0x02a4
+#define DSI_COMMAND_COMPRESSION_MODE_CTRL_STREAM1_DATATYPE__MASK   
0x3f00
+#define DSI_COMMAND_COMPRESSION_MODE_CTRL_STREAM1_DATATYPE__SHIFT  24
+static inline uint32_t 
DSI_COMMAND_COMPRESSION_MODE_CTRL_STREAM1_DATATYPE(uint32_t val)
+{
+   return ((val) << 
DSI_COMMAND_COMPRESSION_MODE_CTRL_STREAM1_DATATYPE__SHIFT) & 
DSI_COMMAND_COMPRESSION_MODE_CTRL_STREAM1_DATATYPE__MASK;
+}
+#define DSI_COMMAND_COMPRESSION_MODE_CTRL_STREAM1_PKT_PER_LINE__MASK   
0x00c0
+#define DSI_COMMAND_COMPRESSION_MODE_CTRL_STREAM1_PKT_PER_LINE__SHIFT  22
+static inline uint32_t 
DSI_COMMAND_COMPRESSION_MODE_CTRL_STREAM1_PKT_PER_LINE(uint32_t val)
+{
+   return ((val) << 
DSI_COMMAND_COMPRESSION_MODE_CTRL_STREAM1_PKT_PER_LINE__SHIFT) & 
DSI_COMMAND_COMPRESSION_MODE_CTRL_STREAM1_PKT_PER_LINE__MASK;
+}
+#define DSI_COMMAND_COMPRESSION_MODE_CTRL_STREAM1_EOL_BYTE_NUM__MASK   
0x0030
+#define DSI_COMMAND_COMPRESSION_MODE_CTRL_STREAM1_EOL_BYTE_NUM__SHIFT  20
+static inline uint32_t 
DSI_COMMAND_COMPRESSION_MODE_CTRL_STREAM1_EOL_BYTE_NUM(uint32_t val)
+{
+   return ((val) << 
DSI_COMMAND_COMPRESSION_MODE_CTRL_STREAM1_EOL_BYTE_NUM__SHIFT) & 
DSI_COMMAND_COMPRESSION_MODE_CTRL_STREAM1_EOL_BYTE_NUM__MASK;
+}
+#define DSI_COMMAND_COMPRESSION_MODE_CTRL_STREAM1_EN   0x0001
+#define DSI_COMMAND_COMPRESSION_MODE_CTRL_STREAM0_DATATYPE__MASK   
0x3f00
+#define DSI_COMMAND_COMPRESSION_MODE_CTRL_STREAM0_DATATYPE__SHIFT  8
+static inline uint32_t 
DSI_COMMAND_COMPRESSION_MODE_CTRL_STREAM0_DATATYPE(uint32_t val)
+{
+   return ((val) << 
DSI_COMMAND_COMPRESSION_MODE_CTRL_STREAM0_DATATYPE__SHIFT) & 
DSI_COMMAND_COMPRESSION_MODE_CTRL_STREAM0_DATATYPE__MASK;
+}
+#define DSI_COMMAND_COMPRESSION_MODE_CTRL_STREAM0_PKT_PER_LINE__MASK   
0x00c0
+#define DSI_COMMAND_COMPRESSION_MODE_CTRL_STREAM0_PKT_PER_LINE__SHIFT  6
+static inline uint32_t 
DSI_COMMAND_COMPRESSION_MODE_CTRL_STREAM0_PKT_PER_LINE(uint32_t val)
+{
+   return ((val) << 
DSI_COMMAND_COMPRESSION_MODE_CTRL_STREAM0_PKT_PER_LINE__SHIFT) & 
DSI_COMMAND_COMPRESSION_MODE_CTRL_STREAM0_PKT_PER_LINE__MASK;
+}
+#define DSI_COMMAND_COMPRESSION_MODE_CTRL_STREAM0_EOL_BYTE_NUM__MASK   
0x0030
+

[Freedreno] [PATCH v6 12/14] drm/msm/dsi: add mode valid callback for dsi_mgr

2022-04-04 Thread Vinod Koul
Add a mode valid callback for dsi_mgr for checking mode being valid in
case of DSC. For DSC the height and width needs to be multiple of slice,
so we check that here

Reviewed-by: Dmitry Baryshkov 
Reviewed-by: Abhinav Kumar 
Signed-off-by: Vinod Koul 
---
 drivers/gpu/drm/msm/dsi/dsi.h |  2 ++
 drivers/gpu/drm/msm/dsi/dsi_host.c| 26 ++
 drivers/gpu/drm/msm/dsi/dsi_manager.c | 12 
 3 files changed, 40 insertions(+)

diff --git a/drivers/gpu/drm/msm/dsi/dsi.h b/drivers/gpu/drm/msm/dsi/dsi.h
index 16cd9b2fce86..580a1e6358bf 100644
--- a/drivers/gpu/drm/msm/dsi/dsi.h
+++ b/drivers/gpu/drm/msm/dsi/dsi.h
@@ -114,6 +114,8 @@ int msm_dsi_host_power_on(struct mipi_dsi_host *host,
 int msm_dsi_host_power_off(struct mipi_dsi_host *host);
 int msm_dsi_host_set_display_mode(struct mipi_dsi_host *host,
  const struct drm_display_mode *mode);
+enum drm_mode_status msm_dsi_host_check_dsc(struct mipi_dsi_host *host,
+   const struct drm_display_mode 
*mode);
 struct drm_panel *msm_dsi_host_get_panel(struct mipi_dsi_host *host);
 unsigned long msm_dsi_host_get_mode_flags(struct mipi_dsi_host *host);
 struct drm_bridge *msm_dsi_host_get_bridge(struct mipi_dsi_host *host);
diff --git a/drivers/gpu/drm/msm/dsi/dsi_host.c 
b/drivers/gpu/drm/msm/dsi/dsi_host.c
index cb2e179127ea..eb0be34add45 100644
--- a/drivers/gpu/drm/msm/dsi/dsi_host.c
+++ b/drivers/gpu/drm/msm/dsi/dsi_host.c
@@ -2554,6 +2554,32 @@ int msm_dsi_host_set_display_mode(struct mipi_dsi_host 
*host,
return 0;
 }
 
+enum drm_mode_status msm_dsi_host_check_dsc(struct mipi_dsi_host *host,
+   const struct drm_display_mode *mode)
+{
+   struct msm_dsi_host *msm_host = to_msm_dsi_host(host);
+   struct msm_display_dsc_config *dsc = msm_host->dsc;
+   int pic_width = mode->hdisplay;
+   int pic_height = mode->vdisplay;
+
+   if (!msm_host->dsc)
+   return MODE_OK;
+
+   if (pic_width % dsc->drm->slice_width) {
+   pr_err("DSI: pic_width %d has to be multiple of slice %d\n",
+  pic_width, dsc->drm->slice_width);
+   return MODE_H_ILLEGAL;
+   }
+
+   if (pic_height % dsc->drm->slice_height) {
+   pr_err("DSI: pic_height %d has to be multiple of slice %d\n",
+  pic_height, dsc->drm->slice_height);
+   return MODE_V_ILLEGAL;
+   }
+
+   return MODE_OK;
+}
+
 struct drm_panel *msm_dsi_host_get_panel(struct mipi_dsi_host *host)
 {
return of_drm_find_panel(to_msm_dsi_host(host)->device_node);
diff --git a/drivers/gpu/drm/msm/dsi/dsi_manager.c 
b/drivers/gpu/drm/msm/dsi/dsi_manager.c
index 0c1b7dde377c..100a8fcbddee 100644
--- a/drivers/gpu/drm/msm/dsi/dsi_manager.c
+++ b/drivers/gpu/drm/msm/dsi/dsi_manager.c
@@ -573,6 +573,17 @@ static void dsi_mgr_bridge_mode_set(struct drm_bridge 
*bridge,
dsi_mgr_bridge_power_on(bridge);
 }
 
+static enum drm_mode_status dsi_mgr_bridge_mode_valid(struct drm_bridge 
*bridge,
+ const struct 
drm_display_info *info,
+ const struct 
drm_display_mode *mode)
+{
+   int id = dsi_mgr_bridge_get_id(bridge);
+   struct msm_dsi *msm_dsi = dsi_mgr_get_dsi(id);
+   struct mipi_dsi_host *host = msm_dsi->host;
+
+   return msm_dsi_host_check_dsc(host, mode);
+}
+
 static const struct drm_connector_funcs dsi_mgr_connector_funcs = {
.detect = dsi_mgr_connector_detect,
.fill_modes = drm_helper_probe_single_connector_modes,
@@ -593,6 +604,7 @@ static const struct drm_bridge_funcs dsi_mgr_bridge_funcs = 
{
.disable = dsi_mgr_bridge_disable,
.post_disable = dsi_mgr_bridge_post_disable,
.mode_set = dsi_mgr_bridge_mode_set,
+   .mode_valid = dsi_mgr_bridge_mode_valid,
 };
 
 /* initialize connector when we're connected to a drm_panel */
-- 
2.34.1



[Freedreno] [PATCH v6 11/14] drm/msm/disp/dpu1: Add DSC support in RM

2022-04-04 Thread Vinod Koul
This add the bits in RM to enable the DSC blocks

Reviewed-by: Dmitry Baryshkov 
Reviewed-by: Abhinav Kumar 
Signed-off-by: Vinod Koul 
---
 drivers/gpu/drm/msm/disp/dpu1/dpu_kms.h |  1 +
 drivers/gpu/drm/msm/disp/dpu1/dpu_rm.c  | 56 +
 drivers/gpu/drm/msm/disp/dpu1/dpu_rm.h  |  1 +
 3 files changed, 58 insertions(+)

diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_kms.h 
b/drivers/gpu/drm/msm/disp/dpu1/dpu_kms.h
index 779e7bd01efd..a41f0eb2761b 100644
--- a/drivers/gpu/drm/msm/disp/dpu1/dpu_kms.h
+++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_kms.h
@@ -145,6 +145,7 @@ struct dpu_global_state {
uint32_t mixer_to_enc_id[LM_MAX - LM_0];
uint32_t ctl_to_enc_id[CTL_MAX - CTL_0];
uint32_t dspp_to_enc_id[DSPP_MAX - DSPP_0];
+   uint32_t dsc_to_enc_id[DSC_MAX - DSC_0];
 };
 
 struct dpu_global_state
diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_rm.c 
b/drivers/gpu/drm/msm/disp/dpu1/dpu_rm.c
index 7497538adae1..0e6634b217aa 100644
--- a/drivers/gpu/drm/msm/disp/dpu1/dpu_rm.c
+++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_rm.c
@@ -11,6 +11,7 @@
 #include "dpu_hw_intf.h"
 #include "dpu_hw_dspp.h"
 #include "dpu_hw_merge3d.h"
+#include "dpu_hw_dsc.h"
 #include "dpu_encoder.h"
 #include "dpu_trace.h"
 
@@ -77,6 +78,15 @@ int dpu_rm_destroy(struct dpu_rm *rm)
for (i = 0; i < ARRAY_SIZE(rm->hw_intf); i++)
dpu_hw_intf_destroy(rm->hw_intf[i]);
 
+   for (i = 0; i < ARRAY_SIZE(rm->dsc_blks); i++) {
+   struct dpu_hw_dsc *hw;
+
+   if (rm->dsc_blks[i]) {
+   hw = to_dpu_hw_dsc(rm->dsc_blks[i]);
+   dpu_hw_dsc_destroy(hw);
+   }
+   }
+
return 0;
 }
 
@@ -210,6 +220,19 @@ int dpu_rm_init(struct dpu_rm *rm,
rm->dspp_blks[dspp->id - DSPP_0] = &hw->base;
}
 
+   for (i = 0; i < cat->dsc_count; i++) {
+   struct dpu_hw_dsc *hw;
+   const struct dpu_dsc_cfg *dsc = &cat->dsc[i];
+
+   hw = dpu_hw_dsc_init(dsc->id, mmio, cat);
+   if (IS_ERR_OR_NULL(hw)) {
+   rc = PTR_ERR(hw);
+   DPU_ERROR("failed dsc object creation: err %d\n", rc);
+   goto fail;
+   }
+   rm->dsc_blks[dsc->id - DSC_0] = &hw->base;
+   }
+
return 0;
 
 fail:
@@ -441,6 +464,28 @@ static int _dpu_rm_reserve_ctls(
return 0;
 }
 
+static int _dpu_rm_reserve_dsc(struct dpu_rm *rm,
+  struct dpu_global_state *global_state,
+  struct drm_encoder *enc,
+  const struct msm_display_topology *top)
+{
+   int num_dsc = top->num_dsc;
+   int i;
+
+   /* check if DSC required are allocated or not */
+   for (i = 0; i < num_dsc; i++) {
+   if (global_state->dsc_to_enc_id[i]) {
+   DPU_ERROR("DSC %d is already allocated\n", i);
+   return -EIO;
+   }
+   }
+
+   for (i = 0; i < num_dsc; i++)
+   global_state->dsc_to_enc_id[i] = enc->base.id;
+
+   return 0;
+}
+
 static int _dpu_rm_make_reservation(
struct dpu_rm *rm,
struct dpu_global_state *global_state,
@@ -462,6 +507,10 @@ static int _dpu_rm_make_reservation(
return ret;
}
 
+   ret  = _dpu_rm_reserve_dsc(rm, global_state, enc, &reqs->topology);
+   if (ret)
+   return ret;
+
return ret;
 }
 
@@ -499,6 +548,8 @@ void dpu_rm_release(struct dpu_global_state *global_state,
ARRAY_SIZE(global_state->mixer_to_enc_id), enc->base.id);
_dpu_rm_clear_mapping(global_state->ctl_to_enc_id,
ARRAY_SIZE(global_state->ctl_to_enc_id), enc->base.id);
+   _dpu_rm_clear_mapping(global_state->dsc_to_enc_id,
+   ARRAY_SIZE(global_state->dsc_to_enc_id), enc->base.id);
 }
 
 int dpu_rm_reserve(
@@ -567,6 +618,11 @@ int dpu_rm_get_assigned_resources(struct dpu_rm *rm,
hw_to_enc_id = global_state->dspp_to_enc_id;
max_blks = ARRAY_SIZE(rm->dspp_blks);
break;
+   case DPU_HW_BLK_DSC:
+   hw_blks = rm->dsc_blks;
+   hw_to_enc_id = global_state->dsc_to_enc_id;
+   max_blks = ARRAY_SIZE(rm->dsc_blks);
+   break;
default:
DPU_ERROR("blk type %d not managed by rm\n", type);
return 0;
diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_rm.h 
b/drivers/gpu/drm/msm/disp/dpu1/dpu_rm.h
index 9b13200a050a..32e0d8aa65ab 100644
--- a/drivers/gpu/drm/msm/disp/dpu1/dpu_rm.h
+++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_rm.h
@@ -28,6 +28,7 @@ struct dpu_rm {
struct d

[Freedreno] [PATCH v6 10/14] drm/msm/disp/dpu1: Add support for DSC in topology

2022-04-04 Thread Vinod Koul
For DSC to work we typically need a 2,2,1 configuration. This should
suffice for resolutions up to 4k. For more resolutions like 8k this won't
work.

Also, it is better to use 2 LMs and DSC instances as half width results
in lesser power consumption as compared to single LM, DSC at full width.

The panel has been tested only with 2,2,1 configuration, so for
now we blindly create 2,2,1 topology when DSC is enabled

Co-developed-by: Abhinav Kumar 
Signed-off-by: Abhinav Kumar 
Reviewed-by: Dmitry Baryshkov 
Signed-off-by: Vinod Koul 
---
 drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c | 13 +
 drivers/gpu/drm/msm/msm_drv.h   |  2 ++
 2 files changed, 15 insertions(+)

diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c 
b/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c
index 95d1588f3bb6..51f24ba68375 100644
--- a/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c
+++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c
@@ -567,8 +567,21 @@ static struct msm_display_topology 
dpu_encoder_get_topology(
topology.num_enc = 0;
topology.num_intf = intf_count;
 
+   if (dpu_enc->dsc) {
+   /* In case of Display Stream Compression (DSC), we would use
+* 2 encoders, 2 layer mixers and 1 interface
+* this is power optimal and can drive up to (including) 4k
+* screens
+*/
+   topology.num_enc = 2;
+   topology.num_dsc = 2;
+   topology.num_intf = 1;
+   topology.num_lm = 2;
+   }
+
return topology;
 }
+
 static int dpu_encoder_virt_atomic_check(
struct drm_encoder *drm_enc,
struct drm_crtc_state *crtc_state,
diff --git a/drivers/gpu/drm/msm/msm_drv.h b/drivers/gpu/drm/msm/msm_drv.h
index bf2ccff97562..0ace9b0549a4 100644
--- a/drivers/gpu/drm/msm/msm_drv.h
+++ b/drivers/gpu/drm/msm/msm_drv.h
@@ -103,12 +103,14 @@ enum msm_event_wait {
  * @num_enc:  number of compression encoder blocks used
  * @num_intf: number of interfaces the panel is mounted on
  * @num_dspp: number of dspp blocks used
+ * @num_dsc:  number of Display Stream Compression (DSC) blocks used
  */
 struct msm_display_topology {
u32 num_lm;
u32 num_enc;
u32 num_intf;
u32 num_dspp;
+   u32 num_dsc;
 };
 
 /* Commit/Event thread specific structure */
-- 
2.34.1



[Freedreno] [PATCH v6 09/14] drm/msm: Add missing num_dspp field documentation

2022-04-04 Thread Vinod Koul
Somehow documentation for num_dspp was missed, so add that

Reviewed-by: Dmitry Baryshkov 
Reviewed-by: Abhinav Kumar 
Signed-off-by: Vinod Koul 
---
 drivers/gpu/drm/msm/msm_drv.h | 1 +
 1 file changed, 1 insertion(+)

diff --git a/drivers/gpu/drm/msm/msm_drv.h b/drivers/gpu/drm/msm/msm_drv.h
index 2a3280df7b12..bf2ccff97562 100644
--- a/drivers/gpu/drm/msm/msm_drv.h
+++ b/drivers/gpu/drm/msm/msm_drv.h
@@ -102,6 +102,7 @@ enum msm_event_wait {
  * @num_lm:   number of layer mixers used
  * @num_enc:  number of compression encoder blocks used
  * @num_intf: number of interfaces the panel is mounted on
+ * @num_dspp: number of dspp blocks used
  */
 struct msm_display_topology {
u32 num_lm;
-- 
2.34.1



[Freedreno] [PATCH v6 08/14] drm/msm/dpu: don't use merge_3d if DSC merge topology is used

2022-04-04 Thread Vinod Koul
From: Dmitry Baryshkov 

DPU supports different topologies for the case when multiple INTFs are
being driven by the single phys_enc. The driver defaults to using 3DMux
in such cases. Don't use it if DSC merge is used instead.

Suggested-by: Abhinav Kumar 
Signed-off-by: Dmitry Baryshkov 
Signed-off-by: Vinod Koul 
---
 drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c  | 16 
 drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.h  |  6 ++
 drivers/gpu/drm/msm/disp/dpu1/dpu_encoder_phys.h |  4 +++-
 3 files changed, 25 insertions(+), 1 deletion(-)

diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c 
b/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c
index 4052486f19d8..95d1588f3bb6 100644
--- a/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c
+++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c
@@ -511,6 +511,22 @@ void dpu_encoder_helper_split_config(
}
 }
 
+bool dpu_encoder_use_dsc_merge(struct drm_encoder *drm_enc)
+{
+   struct dpu_encoder_virt *dpu_enc = to_dpu_encoder_virt(drm_enc);
+   int i, intf_count = 0, num_dsc = 0;
+
+   for (i = 0; i < MAX_PHYS_ENCODERS_PER_VIRTUAL; i++)
+   if (dpu_enc->phys_encs[i])
+   intf_count++;
+
+   /* See dpu_encoder_get_topology, we only support 2:2:1 topology */
+   if (dpu_enc->dsc)
+   num_dsc = 2;
+
+   return (num_dsc > 0) && (num_dsc > intf_count);
+}
+
 static struct msm_display_topology dpu_encoder_get_topology(
struct dpu_encoder_virt *dpu_enc,
struct dpu_kms *dpu_kms,
diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.h 
b/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.h
index ef873e5285a0..084c5265d7e5 100644
--- a/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.h
+++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.h
@@ -172,4 +172,10 @@ int dpu_encoder_get_linecount(struct drm_encoder *drm_enc);
  */
 int dpu_encoder_get_vsync_count(struct drm_encoder *drm_enc);
 
+/**
+ * dpu_encoder_use_dsc_merge - returns true if the encoder uses DSC merge 
topology.
+ * @drm_enc:Pointer to previously created drm encoder structure
+ */
+bool dpu_encoder_use_dsc_merge(struct drm_encoder *drm_enc);
+
 #endif /* __DPU_ENCODER_H__ */
diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder_phys.h 
b/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder_phys.h
index 4842070fdfa8..b5ad43b8a19b 100644
--- a/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder_phys.h
+++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder_phys.h
@@ -314,8 +314,10 @@ static inline enum dpu_3d_blend_mode 
dpu_encoder_helper_get_3d_blend_mode(
 
dpu_cstate = to_dpu_crtc_state(phys_enc->parent->crtc->state);
 
+   /* Use merge_3d unless DSC MERGE topology is used */
if (phys_enc->split_role == ENC_ROLE_SOLO &&
-   dpu_cstate->num_mixers == CRTC_DUAL_MIXERS)
+   dpu_cstate->num_mixers == CRTC_DUAL_MIXERS &&
+   !dpu_encoder_use_dsc_merge(phys_enc->parent))
return BLEND_3D_H_ROW_INT;
 
return BLEND_3D_NONE;
-- 
2.34.1



[Freedreno] [PATCH v6 07/14] drm/msm/disp/dpu1: Add support for DSC in encoder

2022-04-04 Thread Vinod Koul
We need to configure the encoder for DSC configuration and calculate DSC
parameters for the given timing so this patch adds that support by
adding dpu_encoder_prep_dsc() which is invoked when DSC is enabled.

Reviewed-by: Dmitry Baryshkov 
Reviewed-by: Abhinav Kumar 
Signed-off-by: Vinod Koul 
---
 drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c   | 128 +-
 .../gpu/drm/msm/disp/dpu1/dpu_encoder_phys.h  |   8 ++
 2 files changed, 135 insertions(+), 1 deletion(-)

diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c 
b/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c
index 3940b9c6323b..4052486f19d8 100644
--- a/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c
+++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c
@@ -21,6 +21,7 @@
 #include "dpu_hw_intf.h"
 #include "dpu_hw_ctl.h"
 #include "dpu_hw_dspp.h"
+#include "dpu_hw_dsc.h"
 #include "dpu_formats.h"
 #include "dpu_encoder_phys.h"
 #include "dpu_crtc.h"
@@ -135,6 +136,8 @@ enum dpu_enc_rc_states {
  * @cur_slave: As above but for the slave encoder.
  * @hw_pp: Handle to the pingpong blocks used for the display. No.
  * pingpong blocks can be different than num_phys_encs.
+ * @hw_dsc:Handle to the DSC blocks used for the display.
+ * @dsc_mask:  Bitmask of used DSC blocks.
  * @intfs_swapped: Whether or not the phys_enc interfaces have been swapped
  * for partial update right-only cases, such as pingpong
  * split where virtual pingpong does not generate IRQs
@@ -168,6 +171,7 @@ enum dpu_enc_rc_states {
  * @vsync_event_work:  worker to handle vsync event for autorefresh
  * @topology:   topology of the display
  * @idle_timeout:  idle timeout duration in milliseconds
+ * @dsc:   msm_display_dsc_config pointer, for DSC-enabled 
encoders
  */
 struct dpu_encoder_virt {
struct drm_encoder base;
@@ -180,6 +184,9 @@ struct dpu_encoder_virt {
struct dpu_encoder_phys *cur_master;
struct dpu_encoder_phys *cur_slave;
struct dpu_hw_pingpong *hw_pp[MAX_CHANNELS_PER_ENC];
+   struct dpu_hw_dsc *hw_dsc[MAX_CHANNELS_PER_ENC];
+
+   unsigned int dsc_mask;
 
bool intfs_swapped;
 
@@ -206,6 +213,9 @@ struct dpu_encoder_virt {
struct msm_display_topology topology;
 
u32 idle_timeout;
+
+   /* DSC configuration */
+   struct msm_display_dsc_config *dsc;
 };
 
 #define to_dpu_encoder_virt(x) container_of(x, struct dpu_encoder_virt, base)
@@ -942,7 +952,9 @@ static void dpu_encoder_virt_atomic_mode_set(struct 
drm_encoder *drm_enc,
struct dpu_hw_blk *hw_ctl[MAX_CHANNELS_PER_ENC];
struct dpu_hw_blk *hw_lm[MAX_CHANNELS_PER_ENC];
struct dpu_hw_blk *hw_dspp[MAX_CHANNELS_PER_ENC] = { NULL };
-   int num_lm, num_ctl, num_pp;
+   struct dpu_hw_blk *hw_dsc[MAX_CHANNELS_PER_ENC];
+   int num_lm, num_ctl, num_pp, num_dsc;
+   unsigned int dsc_mask = 0;
int i;
 
if (!drm_enc) {
@@ -980,6 +992,18 @@ static void dpu_encoder_virt_atomic_mode_set(struct 
drm_encoder *drm_enc,
dpu_enc->hw_pp[i] = i < num_pp ? to_dpu_hw_pingpong(hw_pp[i])
: NULL;
 
+   if (dpu_enc->dsc) {
+   num_dsc = dpu_rm_get_assigned_resources(&dpu_kms->rm, 
global_state,
+   drm_enc->base.id, 
DPU_HW_BLK_DSC,
+   hw_dsc, 
ARRAY_SIZE(hw_dsc));
+   for (i = 0; i < num_dsc; i++) {
+   dpu_enc->hw_dsc[i] = to_dpu_hw_dsc(hw_dsc[i]);
+   dsc_mask |= BIT(dpu_enc->hw_dsc[i]->idx - DSC_0);
+   }
+   }
+
+   dpu_enc->dsc_mask = dsc_mask;
+
cstate = to_dpu_crtc_state(crtc_state);
 
for (i = 0; i < num_lm; i++) {
@@ -1677,6 +1701,95 @@ static void dpu_encoder_vsync_event_work_handler(struct 
kthread_work *work)
nsecs_to_jiffies(ktime_to_ns(wakeup_time)));
 }
 
+static u32
+dpu_encoder_dsc_initial_line_calc(struct msm_display_dsc_config *dsc,
+ u32 enc_ip_width)
+{
+   int ssm_delay, total_pixels, soft_slice_per_enc;
+
+   soft_slice_per_enc = enc_ip_width / dsc->drm->slice_width;
+
+   /*
+* minimum number of initial line pixels is a sum of:
+* 1. sub-stream multiplexer delay (83 groups for 8bpc,
+*91 for 10 bpc) * 3
+* 2. for two soft slice cases, add extra sub-stream multiplexer * 3
+* 3. the initial xmit delay
+* 4. total pipeline delay through the "lock step" of encoder (47)
+* 5. 6 additional pixels as the output of the rate buffer is
+*48 bits wide
+*/
+   ssm_delay = ((dsc->drm->bits_per_com

[Freedreno] [PATCH v6 06/14] drm/msm/disp/dpu1: Add DSC support in hw_ctl

2022-04-04 Thread Vinod Koul
Later gens of hardware have DSC bits moved to hw_ctl, so configure these
bits so that DSC would work there as well

Reviewed-by: Dmitry Baryshkov 
Reviewed-by: Abhinav Kumar 
Signed-off-by: Vinod Koul 
---
 drivers/gpu/drm/msm/disp/dpu1/dpu_hw_ctl.c | 11 ++-
 drivers/gpu/drm/msm/disp/dpu1/dpu_hw_ctl.h |  2 ++
 2 files changed, 12 insertions(+), 1 deletion(-)

diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_ctl.c 
b/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_ctl.c
index 3584f5ee6bb3..dc27579bb5f6 100644
--- a/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_ctl.c
+++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_ctl.c
@@ -25,6 +25,8 @@
 #define   CTL_MERGE_3D_ACTIVE   0x0E4
 #define   CTL_INTF_ACTIVE   0x0F4
 #define   CTL_MERGE_3D_FLUSH0x100
+#define   CTL_DSC_ACTIVE0x0E8
+#define   CTL_DSC_FLUSH0x104
 #define   CTL_INTF_FLUSH0x110
 #define   CTL_INTF_MASTER   0x134
 #define   CTL_FETCH_PIPE_ACTIVE 0x0FC
@@ -34,6 +36,7 @@
 
 #define DPU_REG_RESET_TIMEOUT_US2000
 #define  MERGE_3D_IDX   23
+#define  DSC_IDX22
 #define  INTF_IDX   31
 #define CTL_INVALID_BIT 0x
 #define CTL_DEFAULT_GROUP_ID   0xf
@@ -126,7 +129,6 @@ static u32 dpu_hw_ctl_get_pending_flush(struct dpu_hw_ctl 
*ctx)
 
 static inline void dpu_hw_ctl_trigger_flush_v1(struct dpu_hw_ctl *ctx)
 {
-
if (ctx->pending_flush_mask & BIT(MERGE_3D_IDX))
DPU_REG_WRITE(&ctx->hw, CTL_MERGE_3D_FLUSH,
ctx->pending_merge_3d_flush_mask);
@@ -511,6 +513,9 @@ static void dpu_hw_ctl_intf_cfg_v1(struct dpu_hw_ctl *ctx,
if ((test_bit(DPU_CTL_VM_CFG, &ctx->caps->features)))
mode_sel = CTL_DEFAULT_GROUP_ID  << 28;
 
+   if (cfg->dsc)
+   DPU_REG_WRITE(&ctx->hw, CTL_DSC_FLUSH, cfg->dsc);
+
if (cfg->intf_mode_sel == DPU_CTL_MODE_SEL_CMD)
mode_sel |= BIT(17);
 
@@ -522,6 +527,10 @@ static void dpu_hw_ctl_intf_cfg_v1(struct dpu_hw_ctl *ctx,
if (cfg->merge_3d)
DPU_REG_WRITE(c, CTL_MERGE_3D_ACTIVE,
  BIT(cfg->merge_3d - MERGE_3D_0));
+   if (cfg->dsc) {
+   DPU_REG_WRITE(&ctx->hw, CTL_FLUSH, DSC_IDX);
+   DPU_REG_WRITE(c, CTL_DSC_ACTIVE, cfg->dsc);
+   }
 }
 
 static void dpu_hw_ctl_intf_cfg(struct dpu_hw_ctl *ctx,
diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_ctl.h 
b/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_ctl.h
index ac1544474022..97f326dff0af 100644
--- a/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_ctl.h
+++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_ctl.h
@@ -40,6 +40,7 @@ struct dpu_hw_stage_cfg {
  * @merge_3d:  3d merge block used
  * @intf_mode_sel: Interface mode, cmd / vid
  * @stream_sel:Stream selection for multi-stream interfaces
+ * @dsc:   DSC BIT masks used
  */
 struct dpu_hw_intf_cfg {
enum dpu_intf intf;
@@ -47,6 +48,7 @@ struct dpu_hw_intf_cfg {
enum dpu_merge_3d merge_3d;
enum dpu_ctl_mode_sel intf_mode_sel;
int stream_sel;
+   unsigned int dsc;
 };
 
 /**
-- 
2.34.1



[Freedreno] [PATCH v6 05/14] drm/msm/disp/dpu1: Add DSC for SDM845 to hw_catalog

2022-04-04 Thread Vinod Koul
This adds SDM845 DSC blocks into hw_catalog

Reviewed-by: Dmitry Baryshkov 
Reviewed-by: Abhinav Kumar 
Signed-off-by: Vinod Koul 
---
 .../gpu/drm/msm/disp/dpu1/dpu_hw_catalog.c| 20 +++
 1 file changed, 20 insertions(+)

diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_catalog.c 
b/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_catalog.c
index a4fe77cddfea..d15fa5845066 100644
--- a/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_catalog.c
+++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_catalog.c
@@ -1117,6 +1117,24 @@ static const struct dpu_pingpong_cfg sc7280_pp[] = {
PP_BLK("pingpong_2", PINGPONG_2, 0x6b000, 0, sc7280_pp_sblk, -1, -1),
PP_BLK("pingpong_3", PINGPONG_3, 0x6c000, 0, sc7280_pp_sblk, -1, -1),
 };
+
+/*
+ * DSC sub blocks config
+ */
+#define DSC_BLK(_name, _id, _base) \
+   {\
+   .name = _name, .id = _id, \
+   .base = _base, .len = 0x140, \
+   .features = 0, \
+   }
+
+static struct dpu_dsc_cfg sdm845_dsc[] = {
+   DSC_BLK("dsc_0", DSC_0, 0x8),
+   DSC_BLK("dsc_1", DSC_1, 0x80400),
+   DSC_BLK("dsc_2", DSC_2, 0x80800),
+   DSC_BLK("dsc_3", DSC_3, 0x80c00),
+};
+
 /*
  * INTF sub blocks config
  */
@@ -1643,6 +1661,8 @@ static void sdm845_cfg_init(struct dpu_mdss_cfg *dpu_cfg)
.mixer = sdm845_lm,
.pingpong_count = ARRAY_SIZE(sdm845_pp),
.pingpong = sdm845_pp,
+   .dsc_count = ARRAY_SIZE(sdm845_dsc),
+   .dsc = sdm845_dsc,
.intf_count = ARRAY_SIZE(sdm845_intf),
.intf = sdm845_intf,
.vbif_count = ARRAY_SIZE(sdm845_vbif),
-- 
2.34.1



[Freedreno] [PATCH v6 04/14] drm/msm/disp/dpu1: Add support for DSC in pingpong block

2022-04-04 Thread Vinod Koul
In SDM845, DSC can be enabled by writing to pingpong block registers, so
add support for DSC in hw_pp

Reviewed-by: Abhinav Kumar 
Reviewed-by: Dmitry Baryshkov 
Signed-off-by: Vinod Koul 
---
 .../gpu/drm/msm/disp/dpu1/dpu_hw_pingpong.c   | 32 +++
 .../gpu/drm/msm/disp/dpu1/dpu_hw_pingpong.h   | 14 
 2 files changed, 46 insertions(+)

diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_pingpong.c 
b/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_pingpong.c
index 55766c97c4c8..47c6ab6caf95 100644
--- a/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_pingpong.c
+++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_pingpong.c
@@ -28,6 +28,9 @@
 #define PP_FBC_MODE 0x034
 #define PP_FBC_BUDGET_CTL   0x038
 #define PP_FBC_LOSSY_MODE   0x03C
+#define PP_DSC_MODE 0x0a0
+#define PP_DCE_DATA_IN_SWAP 0x0ac
+#define PP_DCE_DATA_OUT_SWAP0x0c8
 
 #define PP_DITHER_EN   0x000
 #define PP_DITHER_BITDEPTH 0x004
@@ -245,6 +248,32 @@ static u32 dpu_hw_pp_get_line_count(struct dpu_hw_pingpong 
*pp)
return line;
 }
 
+static int dpu_hw_pp_dsc_enable(struct dpu_hw_pingpong *pp)
+{
+   struct dpu_hw_blk_reg_map *c = &pp->hw;
+
+   DPU_REG_WRITE(c, PP_DSC_MODE, 1);
+   return 0;
+}
+
+static void dpu_hw_pp_dsc_disable(struct dpu_hw_pingpong *pp)
+{
+   struct dpu_hw_blk_reg_map *c = &pp->hw;
+
+   DPU_REG_WRITE(c, PP_DSC_MODE, 0);
+}
+
+static int dpu_hw_pp_setup_dsc(struct dpu_hw_pingpong *pp)
+{
+   struct dpu_hw_blk_reg_map *pp_c = &pp->hw;
+   int data;
+
+   data = DPU_REG_READ(pp_c, PP_DCE_DATA_OUT_SWAP);
+   data |= BIT(18); /* endian flip */
+   DPU_REG_WRITE(pp_c, PP_DCE_DATA_OUT_SWAP, data);
+   return 0;
+}
+
 static void _setup_pingpong_ops(struct dpu_hw_pingpong *c,
unsigned long features)
 {
@@ -256,6 +285,9 @@ static void _setup_pingpong_ops(struct dpu_hw_pingpong *c,
c->ops.get_autorefresh = dpu_hw_pp_get_autorefresh_config;
c->ops.poll_timeout_wr_ptr = dpu_hw_pp_poll_timeout_wr_ptr;
c->ops.get_line_count = dpu_hw_pp_get_line_count;
+   c->ops.setup_dsc = dpu_hw_pp_setup_dsc;
+   c->ops.enable_dsc = dpu_hw_pp_dsc_enable;
+   c->ops.disable_dsc = dpu_hw_pp_dsc_disable;
 
if (test_bit(DPU_PINGPONG_DITHER, &features))
c->ops.setup_dither = dpu_hw_pp_setup_dither;
diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_pingpong.h 
b/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_pingpong.h
index 89d08a715c16..12758468d9ca 100644
--- a/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_pingpong.h
+++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_pingpong.h
@@ -124,6 +124,20 @@ struct dpu_hw_pingpong_ops {
 */
void (*setup_dither)(struct dpu_hw_pingpong *pp,
struct dpu_hw_dither_cfg *cfg);
+   /**
+* Enable DSC
+*/
+   int (*enable_dsc)(struct dpu_hw_pingpong *pp);
+
+   /**
+* Disable DSC
+*/
+   void (*disable_dsc)(struct dpu_hw_pingpong *pp);
+
+   /**
+* Setup DSC
+*/
+   int (*setup_dsc)(struct dpu_hw_pingpong *pp);
 };
 
 struct dpu_hw_merge_3d;
-- 
2.34.1



[Freedreno] [PATCH v6 03/14] drm/msm/disp/dpu1: Add support for DSC

2022-04-04 Thread Vinod Koul
Display Stream Compression (DSC) is one of the hw blocks in dpu, so add
support by adding hw blocks for DSC

Reviewed-by: Dmitry Baryshkov 
Signed-off-by: Vinod Koul 
---
 drivers/gpu/drm/msm/Makefile  |   1 +
 .../gpu/drm/msm/disp/dpu1/dpu_hw_catalog.h|  13 ++
 drivers/gpu/drm/msm/disp/dpu1/dpu_hw_dsc.c| 215 ++
 drivers/gpu/drm/msm/disp/dpu1/dpu_hw_dsc.h|  80 +++
 drivers/gpu/drm/msm/disp/dpu1/dpu_hw_mdss.h   |  13 ++
 5 files changed, 322 insertions(+)
 create mode 100644 drivers/gpu/drm/msm/disp/dpu1/dpu_hw_dsc.c
 create mode 100644 drivers/gpu/drm/msm/disp/dpu1/dpu_hw_dsc.h

diff --git a/drivers/gpu/drm/msm/Makefile b/drivers/gpu/drm/msm/Makefile
index e9cc7d8ac301..f551ecc0fefa 100644
--- a/drivers/gpu/drm/msm/Makefile
+++ b/drivers/gpu/drm/msm/Makefile
@@ -56,6 +56,7 @@ msm-y := \
disp/dpu1/dpu_formats.o \
disp/dpu1/dpu_hw_catalog.o \
disp/dpu1/dpu_hw_ctl.o \
+   disp/dpu1/dpu_hw_dsc.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 b85b24bd3f53..f05c4cdcb7f9 100644
--- a/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_catalog.h
+++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_catalog.h
@@ -561,6 +561,16 @@ struct dpu_merge_3d_cfg  {
const struct dpu_merge_3d_sub_blks *sblk;
 };
 
+/**
+ * struct dpu_dsc_cfg - information of DSC blocks
+ * @id enum identifying this block
+ * @base   register offset of this block
+ * @features   bit mask identifying sub-blocks/features
+ */
+struct dpu_dsc_cfg {
+   DPU_HW_BLK_INFO;
+};
+
 /**
  * struct dpu_intf_cfg - information of timing engine blocks
  * @id enum identifying this block
@@ -757,6 +767,9 @@ struct dpu_mdss_cfg {
u32 merge_3d_count;
const struct dpu_merge_3d_cfg *merge_3d;
 
+   u32 dsc_count;
+   struct dpu_dsc_cfg *dsc;
+
u32 intf_count;
const struct dpu_intf_cfg *intf;
 
diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_dsc.c 
b/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_dsc.c
new file mode 100644
index ..426224e34900
--- /dev/null
+++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_dsc.c
@@ -0,0 +1,215 @@
+// SPDX-License-Identifier: GPL-2.0-only
+/*
+ * Copyright (c) 2020-2022, Linaro Limited
+ */
+
+#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_COMMON_MODE0x000
+#define DSC_ENC 0X004
+#define DSC_PICTURE 0x008
+#define DSC_SLICE   0x00C
+#define DSC_CHUNK_SIZE  0x010
+#define DSC_DELAY   0x014
+#define DSC_SCALE_INITIAL   0x018
+#define DSC_SCALE_DEC_INTERVAL  0x01C
+#define DSC_SCALE_INC_INTERVAL  0x020
+#define DSC_FIRST_LINE_BPG_OFFSET   0x024
+#define DSC_BPG_OFFSET  0x028
+#define DSC_DSC_OFFSET  0x02C
+#define DSC_FLATNESS0x030
+#define DSC_RC_MODEL_SIZE   0x034
+#define DSC_RC  0x038
+#define DSC_RC_BUF_THRESH   0x03C
+#define DSC_RANGE_MIN_QP0x074
+#define DSC_RANGE_MAX_QP0x0B0
+#define DSC_RANGE_BPG_OFFSET0x0EC
+
+static void dpu_hw_dsc_disable(struct dpu_hw_dsc *dsc)
+{
+   struct dpu_hw_blk_reg_map *c = &dsc->hw;
+
+   DPU_REG_WRITE(c, DSC_COMMON_MODE, 0);
+}
+
+static void dpu_hw_dsc_config(struct dpu_hw_dsc *hw_dsc,
+ struct msm_display_dsc_config *dsc,
+ u32 mode,
+ u32 initial_lines)
+{
+   struct dpu_hw_blk_reg_map *c = &hw_dsc->hw;
+   u32 data, lsb, bpp;
+   u32 slice_last_group_size;
+   u32 det_thresh_flatness;
+   bool is_cmd_mode = !(mode & DSC_MODE_VIDEO);
+
+   DPU_REG_WRITE(c, DSC_COMMON_MODE, mode);
+
+   if (is_cmd_mode)
+   initial_lines += 1;
+
+   slice_last_group_size = 3 - (dsc->drm->slice_width % 3);
+   data = (initial_lines << 20);
+   data |= ((slice_last_group_size - 1) << 18);
+   /* bpp is 6.4 format, 4 LSBs bits are for fractional part */
+   data |= dsc->drm->bits_per_pixel << 12;
+   lsb = dsc->drm->bits_per_pixel % 4;
+   bpp = dsc->drm->bits_per_pixel / 4;
+   bpp *= 4;
+   bpp <<= 4;
+   bpp |= lsb;
+
+   data |= bpp << 8;
+   data |= (dsc->drm->block_pred_enable << 7);
+   data |= (dsc->drm->line_buf_depth << 3);
+   data |= (dsc->drm->simple_422 << 2);
+   data |= (dsc->drm->convert_rgb << 1);
+   data |= dsc->

[Freedreno] [PATCH v6 02/14] drm/msm/dsi: Pass DSC params to drm_panel

2022-04-04 Thread Vinod Koul
When DSC is enabled, we need to get the DSC parameters from the panel
driver, so add a dsc parameter in panel to fetch and pass DSC
configuration for DSI panels to DPU encoder, which will enable and
then configure DSC hardware blocks accordingly.

Signed-off-by: Dmitry Baryshkov 
Reviewed-by: Abhinav Kumar 
Signed-off-by: Vinod Koul 
---
 drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.h |  2 ++
 drivers/gpu/drm/msm/disp/dpu1/dpu_kms.c |  2 ++
 drivers/gpu/drm/msm/dsi/dsi.c   |  5 +
 drivers/gpu/drm/msm/dsi/dsi.h   |  1 +
 drivers/gpu/drm/msm/dsi/dsi_host.c  | 22 +
 drivers/gpu/drm/msm/msm_drv.h   |  6 ++
 include/drm/drm_panel.h |  7 +++
 7 files changed, 45 insertions(+)

diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.h 
b/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.h
index 42db6ce12caf..ef873e5285a0 100644
--- a/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.h
+++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.h
@@ -27,6 +27,7 @@
  *  based on num_of_h_tiles
  * @is_te_using_watchdog_timer:  Boolean to indicate watchdog TE is
  *  used instead of panel TE in cmd mode panels
+ * @dsc:   DSC configuration data for DSC-enabled displays
  */
 struct msm_display_info {
int intf_type;
@@ -34,6 +35,7 @@ struct msm_display_info {
uint32_t num_of_h_tiles;
uint32_t h_tile_instance[MAX_H_TILES_PER_DISPLAY];
bool is_te_using_watchdog_timer;
+   struct msm_display_dsc_config *dsc;
 };
 
 /**
diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_kms.c 
b/drivers/gpu/drm/msm/disp/dpu1/dpu_kms.c
index e29796c4f27b..e64154407425 100644
--- a/drivers/gpu/drm/msm/disp/dpu1/dpu_kms.c
+++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_kms.c
@@ -582,6 +582,8 @@ static int _dpu_kms_initialize_dsi(struct drm_device *dev,
MSM_DISPLAY_CAP_CMD_MODE :
MSM_DISPLAY_CAP_VID_MODE;
 
+   info.dsc = msm_dsi_get_dsc_config(priv->dsi[i]);
+
if (msm_dsi_is_bonded_dsi(priv->dsi[i]) && priv->dsi[other]) {
rc = msm_dsi_modeset_init(priv->dsi[other], dev, 
encoder);
if (rc) {
diff --git a/drivers/gpu/drm/msm/dsi/dsi.c b/drivers/gpu/drm/msm/dsi/dsi.c
index c12e66aa42a3..06a76834be52 100644
--- a/drivers/gpu/drm/msm/dsi/dsi.c
+++ b/drivers/gpu/drm/msm/dsi/dsi.c
@@ -21,6 +21,11 @@ bool msm_dsi_is_cmd_mode(struct msm_dsi *msm_dsi)
return !(host_flags & MIPI_DSI_MODE_VIDEO);
 }
 
+struct msm_display_dsc_config *msm_dsi_get_dsc_config(struct msm_dsi *msm_dsi)
+{
+   return msm_dsi_host_get_dsc_config(msm_dsi->host);
+}
+
 static int dsi_get_phy(struct msm_dsi *msm_dsi)
 {
struct platform_device *pdev = msm_dsi->pdev;
diff --git a/drivers/gpu/drm/msm/dsi/dsi.h b/drivers/gpu/drm/msm/dsi/dsi.h
index c8dedc95428c..16cd9b2fce86 100644
--- a/drivers/gpu/drm/msm/dsi/dsi.h
+++ b/drivers/gpu/drm/msm/dsi/dsi.h
@@ -152,6 +152,7 @@ int dsi_calc_clk_rate_v2(struct msm_dsi_host *msm_host, 
bool is_bonded_dsi);
 int dsi_calc_clk_rate_6g(struct msm_dsi_host *msm_host, bool is_bonded_dsi);
 void msm_dsi_host_snapshot(struct msm_disp_state *disp_state, struct 
mipi_dsi_host *host);
 void msm_dsi_host_test_pattern_en(struct mipi_dsi_host *host);
+struct msm_display_dsc_config *msm_dsi_host_get_dsc_config(struct 
mipi_dsi_host *host);
 
 /* dsi phy */
 struct msm_dsi_phy;
diff --git a/drivers/gpu/drm/msm/dsi/dsi_host.c 
b/drivers/gpu/drm/msm/dsi/dsi_host.c
index 4a8a9b31ce1d..cb2e179127ea 100644
--- a/drivers/gpu/drm/msm/dsi/dsi_host.c
+++ b/drivers/gpu/drm/msm/dsi/dsi_host.c
@@ -2061,9 +2061,24 @@ 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 drm_panel *panel;
int ret;
 
msm_host->dev = dev;
+   panel = msm_dsi_host_get_panel(&msm_host->base);
+
+   if (panel && panel->dsc) {
+   struct msm_display_dsc_config *dsc = msm_host->dsc;
+
+   if (!dsc) {
+   dsc = devm_kzalloc(&msm_host->pdev->dev, sizeof(*dsc), 
GFP_KERNEL);
+   if (!dsc)
+   return -ENOMEM;
+   dsc->drm = panel->dsc;
+   msm_host->dsc = 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);
@@ -2628,3 +2643,10 @@ void msm_dsi_host_test_pattern_en(struct mipi_dsi_host 
*host)
dsi_write(msm_host, 
REG_DSI_TEST_PATTERN_GEN_CMD_STREAM0_TRIGGER,

DSI_TEST_PATTERN_GEN_CMD_STREAM0_TRIGGER_SW_TRIGGER);
 }
+
+struct msm_di

[Freedreno] [PATCH v6 01/14] drm/msm/dsi: add support for dsc data

2022-04-04 Thread Vinod Koul
Display Stream Compression (DSC) parameters need to be calculated. Add
helpers and struct msm_display_dsc_config in msm_drv for this
msm_display_dsc_config uses drm_dsc_config for DSC parameters.

Reviewed-by: Dmitry Baryshkov 
Reviewed-by: Abhinav Kumar 
Signed-off-by: Vinod Koul 
---
 drivers/gpu/drm/msm/dsi/dsi_host.c | 130 +
 drivers/gpu/drm/msm/msm_drv.h  |   6 ++
 2 files changed, 136 insertions(+)

diff --git a/drivers/gpu/drm/msm/dsi/dsi_host.c 
b/drivers/gpu/drm/msm/dsi/dsi_host.c
index d51e70fab93d..4a8a9b31ce1d 100644
--- a/drivers/gpu/drm/msm/dsi/dsi_host.c
+++ b/drivers/gpu/drm/msm/dsi/dsi_host.c
@@ -31,6 +31,8 @@
 
 #define DSI_RESET_TOGGLE_DELAY_MS 20
 
+static int dsi_populate_dsc_params(struct msm_display_dsc_config *dsc);
+
 static int dsi_get_version(const void __iomem *base, u32 *major, u32 *minor)
 {
u32 ver;
@@ -157,6 +159,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;
@@ -1722,6 +1725,133 @@ 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 mux_words_size;
+   int groups_per_line, groups_total;
+   int min_rate_buffer_size;
+   int hrd_delay;
+   int pre_num_extra_mux_bits, num_extra_mux_bits;
+   int slice_bits;
+   int target_bpp_x16;
+   int data;
+   int final_value, final_scale;
+   int i;
+
+   dsc->drm->rc_model_size = 8192;
+   dsc->drm->first_line_bpg_offset = 12;
+   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; /* Not bpp 12 */
+   if (dsc->drm->bits_per_pixel != 8)
+   dsc->drm->initial_offset = 2048;/* bpp = 12 */
+
+   mux_words_size = 48;/* bpc == 8/10 */
+   if (dsc->drm->bits_per_component == 12)
+   mux_words_size = 64;
+
+   dsc->drm->initial_xmit_delay = 512;
+   dsc->drm->initial_scale_value = 32;
+   dsc->drm->first_line_bpg_offset = 12;
+   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;
+
+   /* FIXME: need to call drm_dsc_compute_rc_parameters() so that rest of
+* params are calculated
+*/
+   groups_per_line = DIV_ROUND_UP(dsc->drm->slice_width, 3);
+   dsc->drm->slice_chunk_size = dsc->drm->slice_width * 
dsc->drm->bits_per_pixel / 8;
+   if ((dsc->drm->slice_width * dsc->drm->bits_per_pixel) % 8)
+   dsc->drm->slice_chunk_size++;
+
+   /* rbs-min */
+   min_rate_buffer_size =  dsc->drm->rc_model_size - 
dsc->drm->initial_offset +
+   dsc->drm->initial_xmit_delay * 
dsc->drm->bits_per_pixel +
+   groups_per_line * 
dsc->drm->first_line_bpg_offset;
+
+   hrd_delay = DIV_ROUND_UP(min_rate_buffer_size, 
dsc->drm->bits_per_pixel);
+
+   dsc->drm->initial_dec_delay = hrd_delay - dsc->drm->initial_xmit_delay;
+
+   dsc->drm->initial_scale_value = 8 * dsc->drm->rc_model_size /
+  (dsc->drm->rc_model_size - 
dsc->drm->initial_offset);
+
+   sl

[Freedreno] [PATCH v6 00/14] drm/msm: Add Display Stream Compression Support

2022-04-04 Thread Vinod Koul
Display Stream Compression (DSC) compresses the display stream in host which
is later decoded by panel. This series enables this for Qualcomm msm driver.
This was tested on Google Pixel3 phone which use LGE SW43408 panel.
 
The changes include DSC data and hardware block enabling for DPU1 then
support in encoder. We also add support in DSI and introduce required
topology changes.
 
In order for panel to set the DSC parameters we add dsc in drm_panel and
pass the dsc configuration from the panel driver

Complete changes which enable this for Pixel3 along with panel driver (not
part of this series) and DT changes can be found at:
git.linaro.org/people/vinod.koul/kernel.git pixel/dsc_v6
 
Comments welcome!

Changes since v5:
 - rebase on msm-next
 - use generated header patch from mesa for dsc registers
 - use generated header macros for dsc register calculation
 - remove msm dsc struct (Dmitry)

Changes since v4:
 - Use new apprach based on Abhinav suggestion for dsc with 3d-merge
 - Make common function for dsc timing caln and call that from video and cmd
   mode
 - update description for patch "Pass DSC params to drm_panel"
 - update couple of typos as pointed by Marijn
 - drop dpu_encoder_dsc_pclk_param_calc() as that was duplicating the caln
   done in dsi timing
 - Update copyright to 2022 to new files
 - Update Abhinav's email to new quic one

Changes since v3:
 - Merge changes from Dmitry to have dsc per encoder instance
 - add warning for dsc and mode3d enabled together
 - set dsc in dpu_encoder_phys_vid as well
 - remove dsc hardcoded mask
 - use devm_kzalloc for memory allocation for dsc

Changes since v2:
 - Fix comments by Dimitry except the dsc being global.
 - Move RM patch later for dependency on topology now
 - Add patch for mode valid callback for dsi_mgr
 - Add missing structure documentation patch
 - Fix errors in mode_3d changes
 - Rebase on v5.16-rc1 and test

Changes since v1:
 - Fix various issues spotted by kbuildbot
 - Rebase to v5.15-rc3
 - Remove unused fields and duplicate defines
 - Enable DSC blocks only when DSC is enabled
 - remove sdm845 feature mask, use 0
 - Check for DSC in hw_ctl

Changes since RFC:
 - Drop the DT binding patch as we derive the configuration from panel
 - Drop the drm api patch as we no longer need it (use pps drm api)
 - Fix comments raised by Dimitry
 - Add dsc parameters calculation from downstream

*** SUBJECT HERE ***

*** BLURB HERE ***

Dmitry Baryshkov (1):
  drm/msm/dpu: don't use merge_3d if DSC merge topology is used

Vinod Koul (13):
  drm/msm/dsi: add support for dsc data
  drm/msm/dsi: Pass DSC params to drm_panel
  drm/msm/disp/dpu1: Add support for DSC
  drm/msm/disp/dpu1: Add support for DSC in pingpong block
  drm/msm/disp/dpu1: Add DSC for SDM845 to hw_catalog
  drm/msm/disp/dpu1: Add DSC support in hw_ctl
  drm/msm/disp/dpu1: Add support for DSC in encoder
  drm/msm: Add missing num_dspp field documentation
  drm/msm/disp/dpu1: Add support for DSC in topology
  drm/msm/disp/dpu1: Add DSC support in RM
  drm/msm/dsi: add mode valid callback for dsi_mgr
  drm/msm: Update generated headers
  drm/msm/dsi: Add support for DSC configuration

 drivers/gpu/drm/msm/Makefile  |   1 +
 drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c   | 157 +-
 drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.h   |   8 +
 .../gpu/drm/msm/disp/dpu1/dpu_encoder_phys.h  |  12 +-
 .../gpu/drm/msm/disp/dpu1/dpu_hw_catalog.c|  20 ++
 .../gpu/drm/msm/disp/dpu1/dpu_hw_catalog.h|  13 +
 drivers/gpu/drm/msm/disp/dpu1/dpu_hw_ctl.c|  11 +-
 drivers/gpu/drm/msm/disp/dpu1/dpu_hw_ctl.h|   2 +
 drivers/gpu/drm/msm/disp/dpu1/dpu_hw_dsc.c| 215 ++
 drivers/gpu/drm/msm/disp/dpu1/dpu_hw_dsc.h|  80 +
 drivers/gpu/drm/msm/disp/dpu1/dpu_hw_mdss.h   |  13 +
 .../gpu/drm/msm/disp/dpu1/dpu_hw_pingpong.c   |  32 ++
 .../gpu/drm/msm/disp/dpu1/dpu_hw_pingpong.h   |  14 +
 drivers/gpu/drm/msm/disp/dpu1/dpu_kms.c   |   2 +
 drivers/gpu/drm/msm/disp/dpu1/dpu_kms.h   |   1 +
 drivers/gpu/drm/msm/disp/dpu1/dpu_rm.c|  56 
 drivers/gpu/drm/msm/disp/dpu1/dpu_rm.h|   1 +
 drivers/gpu/drm/msm/dsi/dsi.c |   5 +
 drivers/gpu/drm/msm/dsi/dsi.h |   3 +
 drivers/gpu/drm/msm/dsi/dsi.xml.h |  80 +
 drivers/gpu/drm/msm/dsi/dsi_host.c| 276 +-
 drivers/gpu/drm/msm/dsi/dsi_manager.c |  12 +
 drivers/gpu/drm/msm/msm_drv.h |  15 +
 include/drm/drm_panel.h   |   7 +
 24 files changed, 1032 insertions(+), 4 deletions(-)
 create mode 100644 drivers/gpu/drm/msm/disp/dpu1/dpu_hw_dsc.c
 create mode 100644 drivers/gpu/drm/msm/disp/dpu1/dpu_hw_dsc.h


base-commit: 05241de1f69eb7f56b0a5e0bec96a7752fad1b2f
-- 
2.34.1



Re: [Freedreno] [PATCH] dt-bindings: display: msm: dsi: remove address/size cells

2022-03-30 Thread Vinod Koul
On 29-03-22, 10:52, Rob Herring wrote:
> On Tue, Mar 29, 2022 at 12:01:52PM +0530, Vinod Koul wrote:
> > On 28-03-22, 13:21, Rob Herring wrote:
> > > On Mon, Mar 28, 2022 at 12:18 PM Krzysztof Kozlowski
> > >  wrote:
> > > >
> > > > On 28/03/2022 19:16, Vinod Koul wrote:
> > > > > On 28-03-22, 19:43, Dmitry Baryshkov wrote:
> > > > >> On Mon, 28 Mar 2022 at 18:30, Krzysztof Kozlowski
> > > > >>  wrote:
> > > > >>>
> > > > >>> The DSI node is not a bus and the children do not have unit 
> > > > >>> addresses.
> > > > >>>
> > > > >>> Reported-by: Vinod Koul 
> > > > >>> Signed-off-by: Krzysztof Kozlowski 
> > > > >>
> > > > >> NAK.
> > > > >> DSI panels are children of the DSI device tree node with the reg = 
> > > > >> <0>; address.
> > > > >> This is the convention used by other platforms too (see e.g.
> > > > >> arch/arm64/boot/dts/freescale/imx8mq-evk.dts).
> > > > >
> > > > > So we should add reg = 0, i will update my dtsi fix
> > > > >
> > > >
> > > > To "ports" node? No. The reg=0 is for children of the bus, so the
> > > > panels. How to combine both without warnings - ports and panel@0 - I
> > > > don't know yet...
> > > 
> > > I don't think that should case a warning. Or at least it's one we turn 
> > > off.
> > 
> > Well in this case I think we might need a fix:
> > Here is the example quoted in the binding. We have ports{} and then the
> > two port@0 and port@1 underneath.
> 
> It's the #address-cells/#size-cells under 'ports' that applies to 'port' 
> nodes. As 'ports' has no address (reg) itself, it doesn't need 
> #address-cells/#size-cells in its parent node.
> 
> > 
> > So it should be okay to drop #address-cells/#size-cells from dsi node
> > but keep in ports node...
> 
> Yes.
> 
> > Thoughts...?
> 
> But I thought a panel@0 node was being added? If so then you need to add 
> them back.

I guess we should make this optional, keep it when adding panel@0 node
and skip for rest where not applicable..? Dmitry is that fine with you?

-- 
~Vinod


Re: [Freedreno] [PATCH] dt-bindings: display: msm: dsi: remove address/size cells

2022-03-28 Thread Vinod Koul
On 28-03-22, 13:21, Rob Herring wrote:
> On Mon, Mar 28, 2022 at 12:18 PM Krzysztof Kozlowski
>  wrote:
> >
> > On 28/03/2022 19:16, Vinod Koul wrote:
> > > On 28-03-22, 19:43, Dmitry Baryshkov wrote:
> > >> On Mon, 28 Mar 2022 at 18:30, Krzysztof Kozlowski
> > >>  wrote:
> > >>>
> > >>> The DSI node is not a bus and the children do not have unit addresses.
> > >>>
> > >>> Reported-by: Vinod Koul 
> > >>> Signed-off-by: Krzysztof Kozlowski 
> > >>
> > >> NAK.
> > >> DSI panels are children of the DSI device tree node with the reg = <0>; 
> > >> address.
> > >> This is the convention used by other platforms too (see e.g.
> > >> arch/arm64/boot/dts/freescale/imx8mq-evk.dts).
> > >
> > > So we should add reg = 0, i will update my dtsi fix
> > >
> >
> > To "ports" node? No. The reg=0 is for children of the bus, so the
> > panels. How to combine both without warnings - ports and panel@0 - I
> > don't know yet...
> 
> I don't think that should case a warning. Or at least it's one we turn off.

Well in this case I think we might need a fix:
Here is the example quoted in the binding. We have ports{} and then the
two port@0 and port@1 underneath.

So it should be okay to drop #address-cells/#size-cells from dsi node
but keep in ports node...

Thoughts...?


 dsi@ae94000 {
   compatible = "qcom,mdss-dsi-ctrl";
   reg = <0x0ae94000 0x400>;
   reg-names = "dsi_ctrl";

   #address-cells = <1>;
   #size-cells = <0>;

   interrupt-parent = <&mdss>;
   interrupts = <4>;

   clocks = <&dispcc DISP_CC_MDSS_BYTE0_CLK>,
<&dispcc DISP_CC_MDSS_BYTE0_INTF_CLK>,
<&dispcc DISP_CC_MDSS_PCLK0_CLK>,
<&dispcc DISP_CC_MDSS_ESC0_CLK>,
<&dispcc DISP_CC_MDSS_AHB_CLK>,
<&dispcc DISP_CC_MDSS_AXI_CLK>;
   clock-names = "byte",
 "byte_intf",
 "pixel",
 "core",
 "iface",
 "bus";

   phys = <&dsi0_phy>;
   phy-names = "dsi";

   assigned-clocks = <&dispcc DISP_CC_MDSS_BYTE0_CLK_SRC>, <&dispcc 
DISP_CC_MDSS_PCLK0_CLK_SRC>;
   assigned-clock-parents = <&dsi_phy 0>, <&dsi_phy 1>;

   power-domains = <&rpmhpd SC7180_CX>;
   operating-points-v2 = <&dsi_opp_table>;

   ports {
  #address-cells = <1>;
  #size-cells = <0>;

  port@0 {
  reg = <0>;
  dsi0_in: endpoint {
   remote-endpoint = <&dpu_intf1_out>;
  };
  };

  port@1 {
  reg = <1>;
  dsi0_out: endpoint {
   remote-endpoint = <&sn65dsi86_in>;
   data-lanes = <0 1 2 3>;
  };
  };
   };
 };

> 
> Rob

-- 
~Vinod


Re: [Freedreno] [PATCH] dt-bindings: display: msm: dsi: remove address/size cells

2022-03-28 Thread Vinod Koul
On 28-03-22, 19:43, Dmitry Baryshkov wrote:
> On Mon, 28 Mar 2022 at 18:30, Krzysztof Kozlowski
>  wrote:
> >
> > The DSI node is not a bus and the children do not have unit addresses.
> >
> > Reported-by: Vinod Koul 
> > Signed-off-by: Krzysztof Kozlowski 
> 
> NAK.
> DSI panels are children of the DSI device tree node with the reg = <0>; 
> address.
> This is the convention used by other platforms too (see e.g.
> arch/arm64/boot/dts/freescale/imx8mq-evk.dts).

So we should add reg = 0, i will update my dtsi fix

> With the DSI split link it is possible to attach two panels to a
> single DSI host, so addresses are necessary.
> 
> > ---
> >  .../bindings/display/msm/dsi-controller-main.yaml  | 7 ---
> >  1 file changed, 7 deletions(-)
> >
> > diff --git 
> > a/Documentation/devicetree/bindings/display/msm/dsi-controller-main.yaml 
> > b/Documentation/devicetree/bindings/display/msm/dsi-controller-main.yaml
> > index 7095ec3c890d..57f238f72326 100644
> > --- a/Documentation/devicetree/bindings/display/msm/dsi-controller-main.yaml
> > +++ b/Documentation/devicetree/bindings/display/msm/dsi-controller-main.yaml
> > @@ -51,10 +51,6 @@ properties:
> >phy-names:
> >  const: dsi
> >
> > -  "#address-cells": true
> > -
> > -  "#size-cells": true
> > -
> >syscon-sfpb:
> >  description: A phandle to mmss_sfpb syscon node (only for DSIv2).
> >  $ref: "/schemas/types.yaml#/definitions/phandle"
> > @@ -154,9 +150,6 @@ examples:
> > reg = <0x0ae94000 0x400>;
> > reg-names = "dsi_ctrl";
> >
> > -   #address-cells = <1>;
> > -   #size-cells = <0>;
> > -
> > interrupt-parent = <&mdss>;
> > interrupts = <4>;
> >
> > --
> > 2.32.0
> >
> 
> 
> -- 
> With best wishes
> Dmitry

-- 
~Vinod


[Freedreno] [PATCH v5 13/13] drm/msm/dsi: Add support for DSC configuration

2022-03-25 Thread Vinod Koul
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 
Signed-off-by: Vinod Koul 
---
 drivers/gpu/drm/msm/dsi/dsi.xml.h  | 10 
 drivers/gpu/drm/msm/dsi/dsi_host.c | 94 +-
 2 files changed, 103 insertions(+), 1 deletion(-)

diff --git a/drivers/gpu/drm/msm/dsi/dsi.xml.h 
b/drivers/gpu/drm/msm/dsi/dsi.xml.h
index 49b551ad1bff..c1c85df58c4b 100644
--- a/drivers/gpu/drm/msm/dsi/dsi.xml.h
+++ b/drivers/gpu/drm/msm/dsi/dsi.xml.h
@@ -706,4 +706,14 @@ static inline uint32_t DSI_VERSION_MAJOR(uint32_t val)
 #define REG_DSI_CPHY_MODE_CTRL 0x02d4
 
 
+#define REG_DSI_VIDEO_COMPRESSION_MODE_CTRL0x029c
+
+#define REG_DSI_VIDEO_COMPRESSION_MODE_CTRL2   0x02a0
+
+#define REG_DSI_COMMAND_COMPRESSION_MODE_CTRL  0x02a4
+
+#define REG_DSI_COMMAND_COMPRESSION_MODE_CTRL2 0x02a8
+
+#define REG_DSI_COMMAND_COMPRESSION_MODE_CTRL3 0x02ac
+
 #endif /* DSI_XML */
diff --git a/drivers/gpu/drm/msm/dsi/dsi_host.c 
b/drivers/gpu/drm/msm/dsi/dsi_host.c
index 438c80750682..0f33e678103f 100644
--- a/drivers/gpu/drm/msm/dsi/dsi_host.c
+++ b/drivers/gpu/drm/msm/dsi/dsi_host.c
@@ -908,6 +908,61 @@ 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;
+
+   /* 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);
+   dsc->bytes_in_slice = DIV_ROUND_UP(dsc->drm->slice_width *
+  dsc->drm->bits_per_pixel, 8);
+
+   dsc->drm->slice_chunk_size = dsc->bytes_in_slice;
+
+   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;
+
+   if (is_cmd_mode) /* packet data type */
+   reg = MIPI_DSI_DCS_LONG_WRITE << 8;
+   else
+   reg = MIPI_DSI_COMPRESSED_PIXEL_STREAM << 8;
+
+   reg |= (dsc->pkt_per_line >> 1) << 6;
+   reg |= dsc->eol_byte_num << 4;
+   reg |= 1;
+
+   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 |= dsc->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;
@@ -940,7 +995,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 

[Freedreno] [PATCH v5 12/13] drm/msm/dsi: add mode valid callback for dsi_mgr

2022-03-25 Thread Vinod Koul
Add a mode valid callback for dsi_mgr for checking mode being valid in
case of DSC. For DSC the height and width needs to be multiple of slice,
so we check that here

Reviewed-by: Dmitry Baryshkov 
Reviewed-by: Abhinav Kumar 
Signed-off-by: Vinod Koul 
---
 drivers/gpu/drm/msm/dsi/dsi.h |  2 ++
 drivers/gpu/drm/msm/dsi/dsi_host.c| 26 ++
 drivers/gpu/drm/msm/dsi/dsi_manager.c | 12 
 3 files changed, 40 insertions(+)

diff --git a/drivers/gpu/drm/msm/dsi/dsi.h b/drivers/gpu/drm/msm/dsi/dsi.h
index 16cd9b2fce86..580a1e6358bf 100644
--- a/drivers/gpu/drm/msm/dsi/dsi.h
+++ b/drivers/gpu/drm/msm/dsi/dsi.h
@@ -114,6 +114,8 @@ int msm_dsi_host_power_on(struct mipi_dsi_host *host,
 int msm_dsi_host_power_off(struct mipi_dsi_host *host);
 int msm_dsi_host_set_display_mode(struct mipi_dsi_host *host,
  const struct drm_display_mode *mode);
+enum drm_mode_status msm_dsi_host_check_dsc(struct mipi_dsi_host *host,
+   const struct drm_display_mode 
*mode);
 struct drm_panel *msm_dsi_host_get_panel(struct mipi_dsi_host *host);
 unsigned long msm_dsi_host_get_mode_flags(struct mipi_dsi_host *host);
 struct drm_bridge *msm_dsi_host_get_bridge(struct mipi_dsi_host *host);
diff --git a/drivers/gpu/drm/msm/dsi/dsi_host.c 
b/drivers/gpu/drm/msm/dsi/dsi_host.c
index 7e9913eff724..438c80750682 100644
--- a/drivers/gpu/drm/msm/dsi/dsi_host.c
+++ b/drivers/gpu/drm/msm/dsi/dsi_host.c
@@ -2552,6 +2552,32 @@ int msm_dsi_host_set_display_mode(struct mipi_dsi_host 
*host,
return 0;
 }
 
+enum drm_mode_status msm_dsi_host_check_dsc(struct mipi_dsi_host *host,
+   const struct drm_display_mode *mode)
+{
+   struct msm_dsi_host *msm_host = to_msm_dsi_host(host);
+   struct msm_display_dsc_config *dsc = msm_host->dsc;
+   int pic_width = mode->hdisplay;
+   int pic_height = mode->vdisplay;
+
+   if (!msm_host->dsc)
+   return MODE_OK;
+
+   if (pic_width % dsc->drm->slice_width) {
+   pr_err("DSI: pic_width %d has to be multiple of slice %d\n",
+  pic_width, dsc->drm->slice_width);
+   return MODE_H_ILLEGAL;
+   }
+
+   if (pic_height % dsc->drm->slice_height) {
+   pr_err("DSI: pic_height %d has to be multiple of slice %d\n",
+  pic_height, dsc->drm->slice_height);
+   return MODE_V_ILLEGAL;
+   }
+
+   return MODE_OK;
+}
+
 struct drm_panel *msm_dsi_host_get_panel(struct mipi_dsi_host *host)
 {
return of_drm_find_panel(to_msm_dsi_host(host)->device_node);
diff --git a/drivers/gpu/drm/msm/dsi/dsi_manager.c 
b/drivers/gpu/drm/msm/dsi/dsi_manager.c
index f19bae475c96..e7f6cc88f7a4 100644
--- a/drivers/gpu/drm/msm/dsi/dsi_manager.c
+++ b/drivers/gpu/drm/msm/dsi/dsi_manager.c
@@ -575,6 +575,17 @@ static void dsi_mgr_bridge_mode_set(struct drm_bridge 
*bridge,
msm_dsi_host_set_display_mode(other_dsi->host, adjusted_mode);
 }
 
+static enum drm_mode_status dsi_mgr_bridge_mode_valid(struct drm_bridge 
*bridge,
+ const struct 
drm_display_info *info,
+ const struct 
drm_display_mode *mode)
+{
+   int id = dsi_mgr_bridge_get_id(bridge);
+   struct msm_dsi *msm_dsi = dsi_mgr_get_dsi(id);
+   struct mipi_dsi_host *host = msm_dsi->host;
+
+   return msm_dsi_host_check_dsc(host, mode);
+}
+
 static const struct drm_connector_funcs dsi_mgr_connector_funcs = {
.detect = dsi_mgr_connector_detect,
.fill_modes = drm_helper_probe_single_connector_modes,
@@ -596,6 +607,7 @@ static const struct drm_bridge_funcs dsi_mgr_bridge_funcs = 
{
.disable = dsi_mgr_bridge_disable,
.post_disable = dsi_mgr_bridge_post_disable,
.mode_set = dsi_mgr_bridge_mode_set,
+   .mode_valid = dsi_mgr_bridge_mode_valid,
 };
 
 /* initialize connector when we're connected to a drm_panel */
-- 
2.34.1



[Freedreno] [PATCH v5 11/13] drm/msm/disp/dpu1: Add DSC support in RM

2022-03-25 Thread Vinod Koul
This add the bits in RM to enable the DSC blocks

Reviewed-by: Dmitry Baryshkov 
Reviewed-by: Abhinav Kumar 
Signed-off-by: Vinod Koul 
---
 drivers/gpu/drm/msm/disp/dpu1/dpu_kms.h |  1 +
 drivers/gpu/drm/msm/disp/dpu1/dpu_rm.c  | 56 +
 drivers/gpu/drm/msm/disp/dpu1/dpu_rm.h  |  1 +
 3 files changed, 58 insertions(+)

diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_kms.h 
b/drivers/gpu/drm/msm/disp/dpu1/dpu_kms.h
index 2d385b4b7f5e..8f2fb667b05c 100644
--- a/drivers/gpu/drm/msm/disp/dpu1/dpu_kms.h
+++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_kms.h
@@ -146,6 +146,7 @@ struct dpu_global_state {
uint32_t ctl_to_enc_id[CTL_MAX - CTL_0];
uint32_t intf_to_enc_id[INTF_MAX - INTF_0];
uint32_t dspp_to_enc_id[DSPP_MAX - DSPP_0];
+   uint32_t dsc_to_enc_id[DSC_MAX - DSC_0];
 };
 
 struct dpu_global_state
diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_rm.c 
b/drivers/gpu/drm/msm/disp/dpu1/dpu_rm.c
index f9c83d6e427a..fbb24bb2b998 100644
--- a/drivers/gpu/drm/msm/disp/dpu1/dpu_rm.c
+++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_rm.c
@@ -11,6 +11,7 @@
 #include "dpu_hw_intf.h"
 #include "dpu_hw_dspp.h"
 #include "dpu_hw_merge3d.h"
+#include "dpu_hw_dsc.h"
 #include "dpu_encoder.h"
 #include "dpu_trace.h"
 
@@ -75,6 +76,14 @@ int dpu_rm_destroy(struct dpu_rm *rm)
dpu_hw_intf_destroy(hw);
}
}
+   for (i = 0; i < ARRAY_SIZE(rm->dsc_blks); i++) {
+   struct dpu_hw_dsc *hw;
+
+   if (rm->dsc_blks[i]) {
+   hw = to_dpu_hw_dsc(rm->dsc_blks[i]);
+   dpu_hw_dsc_destroy(hw);
+   }
+   }
 
return 0;
 }
@@ -221,6 +230,19 @@ int dpu_rm_init(struct dpu_rm *rm,
rm->dspp_blks[dspp->id - DSPP_0] = &hw->base;
}
 
+   for (i = 0; i < cat->dsc_count; i++) {
+   struct dpu_hw_dsc *hw;
+   const struct dpu_dsc_cfg *dsc = &cat->dsc[i];
+
+   hw = dpu_hw_dsc_init(dsc->id, mmio, cat);
+   if (IS_ERR_OR_NULL(hw)) {
+   rc = PTR_ERR(hw);
+   DPU_ERROR("failed dsc object creation: err %d\n", rc);
+   goto fail;
+   }
+   rm->dsc_blks[dsc->id - DSC_0] = &hw->base;
+   }
+
return 0;
 
 fail:
@@ -476,6 +498,7 @@ static int _dpu_rm_reserve_intf(
}
 
global_state->intf_to_enc_id[idx] = enc_id;
+
return 0;
 }
 
@@ -500,6 +523,28 @@ static int _dpu_rm_reserve_intf_related_hw(
return ret;
 }
 
+static int _dpu_rm_reserve_dsc(struct dpu_rm *rm,
+  struct dpu_global_state *global_state,
+  struct drm_encoder *enc,
+  const struct msm_display_topology *top)
+{
+   int num_dsc = top->num_dsc;
+   int i;
+
+   /* check if DSC required are allocated or not */
+   for (i = 0; i < num_dsc; i++) {
+   if (global_state->dsc_to_enc_id[i]) {
+   DPU_ERROR("DSC %d is already allocated\n", i);
+   return -EIO;
+   }
+   }
+
+   for (i = 0; i < num_dsc; i++)
+   global_state->dsc_to_enc_id[i] = enc->base.id;
+
+   return 0;
+}
+
 static int _dpu_rm_make_reservation(
struct dpu_rm *rm,
struct dpu_global_state *global_state,
@@ -526,6 +571,10 @@ static int _dpu_rm_make_reservation(
if (ret)
return ret;
 
+   ret  = _dpu_rm_reserve_dsc(rm, global_state, enc, &reqs->topology);
+   if (ret)
+   return ret;
+
return ret;
 }
 
@@ -567,6 +616,8 @@ void dpu_rm_release(struct dpu_global_state *global_state,
ARRAY_SIZE(global_state->ctl_to_enc_id), enc->base.id);
_dpu_rm_clear_mapping(global_state->intf_to_enc_id,
ARRAY_SIZE(global_state->intf_to_enc_id), enc->base.id);
+   _dpu_rm_clear_mapping(global_state->dsc_to_enc_id,
+   ARRAY_SIZE(global_state->dsc_to_enc_id), enc->base.id);
 }
 
 int dpu_rm_reserve(
@@ -640,6 +691,11 @@ int dpu_rm_get_assigned_resources(struct dpu_rm *rm,
hw_to_enc_id = global_state->dspp_to_enc_id;
max_blks = ARRAY_SIZE(rm->dspp_blks);
break;
+   case DPU_HW_BLK_DSC:
+   hw_blks = rm->dsc_blks;
+   hw_to_enc_id = global_state->dsc_to_enc_id;
+   max_blks = ARRAY_SIZE(rm->dsc_blks);
+   break;
default:
DPU_ERROR("blk type %d not managed by rm\n", type);
return 0;
diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_rm.h 
b/drivers/gpu/drm/msm/disp/dpu1/dpu_rm.h
index 1f12c8d5b8aa..278d2a510b80 100644
--- a/drivers/g

[Freedreno] [PATCH v5 10/13] drm/msm/disp/dpu1: Add support for DSC in topology

2022-03-25 Thread Vinod Koul
For DSC to work we typically need a 2,2,1 configuration. This should
suffice for resolutions up to 4k. For more resolutions like 8k this won't
work.

Also, it is better to use 2 LMs and DSC instances as half width results
in lesser power consumption as compared to single LM, DSC at full width.

The panel has been tested only with 2,2,1 configuration, so for
now we blindly create 2,2,1 topology when DSC is enabled

Co-developed-by: Abhinav Kumar 
Signed-off-by: Abhinav Kumar 
Reviewed-by: Dmitry Baryshkov 
Signed-off-by: Vinod Koul 
---
 drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c | 13 +
 drivers/gpu/drm/msm/msm_drv.h   |  2 ++
 2 files changed, 15 insertions(+)

diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c 
b/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c
index a672c91dbb8b..7dff39c20dab 100644
--- a/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c
+++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c
@@ -590,8 +590,21 @@ static struct msm_display_topology 
dpu_encoder_get_topology(
topology.num_enc = 0;
topology.num_intf = intf_count;
 
+   if (dpu_enc->dsc) {
+   /* In case of Display Stream Compression (DSC), we would use
+* 2 encoders, 2 layer mixers and 1 interface
+* this is power optimal and can drive up to (including) 4k
+* screens
+*/
+   topology.num_enc = 2;
+   topology.num_dsc = 2;
+   topology.num_intf = 1;
+   topology.num_lm = 2;
+   }
+
return topology;
 }
+
 static int dpu_encoder_virt_atomic_check(
struct drm_encoder *drm_enc,
struct drm_crtc_state *crtc_state,
diff --git a/drivers/gpu/drm/msm/msm_drv.h b/drivers/gpu/drm/msm/msm_drv.h
index 6425a42e997c..994d895d1a47 100644
--- a/drivers/gpu/drm/msm/msm_drv.h
+++ b/drivers/gpu/drm/msm/msm_drv.h
@@ -103,12 +103,14 @@ enum msm_event_wait {
  * @num_enc:  number of compression encoder blocks used
  * @num_intf: number of interfaces the panel is mounted on
  * @num_dspp: number of dspp blocks used
+ * @num_dsc:  number of Display Stream Compression (DSC) blocks used
  */
 struct msm_display_topology {
u32 num_lm;
u32 num_enc;
u32 num_intf;
u32 num_dspp;
+   u32 num_dsc;
 };
 
 /**
-- 
2.34.1



[Freedreno] [PATCH v5 08/13] drm/msm/dpu: don't use merge_3d if DSC merge topology is used

2022-03-25 Thread Vinod Koul
From: Dmitry Baryshkov 

DPU supports different topologies for the case when multiple INTFs are
being driven by the single phys_enc. The driver defaults to using 3DMux
in such cases. Don't use it if DSC merge is used instead.

Suggested-by: Abhinav Kumar 
Signed-off-by: Dmitry Baryshkov 
Signed-off-by: Vinod Koul 
---
 drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c  | 16 
 drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.h  |  6 ++
 drivers/gpu/drm/msm/disp/dpu1/dpu_encoder_phys.h |  4 +++-
 3 files changed, 25 insertions(+), 1 deletion(-)

diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c 
b/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c
index 2219dbfa5ee7..a672c91dbb8b 100644
--- a/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c
+++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c
@@ -534,6 +534,22 @@ void dpu_encoder_helper_split_config(
}
 }
 
+bool dpu_encoder_use_dsc_merge(struct drm_encoder *drm_enc)
+{
+   struct dpu_encoder_virt *dpu_enc = to_dpu_encoder_virt(drm_enc);
+   int i, intf_count = 0, num_dsc = 0;
+
+   for (i = 0; i < MAX_PHYS_ENCODERS_PER_VIRTUAL; i++)
+   if (dpu_enc->phys_encs[i])
+   intf_count++;
+
+   /* See dpu_encoder_get_topology, we only support 2:2:1 topology */
+   if (dpu_enc->dsc)
+   num_dsc = 2;
+
+   return (num_dsc > 0) && (num_dsc > intf_count);
+}
+
 static struct msm_display_topology dpu_encoder_get_topology(
struct dpu_encoder_virt *dpu_enc,
struct dpu_kms *dpu_kms,
diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.h 
b/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.h
index e241914a9677..76fd48c0b17c 100644
--- a/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.h
+++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.h
@@ -168,4 +168,10 @@ int dpu_encoder_get_linecount(struct drm_encoder *drm_enc);
  */
 int dpu_encoder_get_vsync_count(struct drm_encoder *drm_enc);
 
+/**
+ * dpu_encoder_use_dsc_merge - returns true if the encoder uses DSC merge 
topology.
+ * @drm_enc:Pointer to previously created drm encoder structure
+ */
+bool dpu_encoder_use_dsc_merge(struct drm_encoder *drm_enc);
+
 #endif /* __DPU_ENCODER_H__ */
diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder_phys.h 
b/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder_phys.h
index 7b90d644a41b..a19140590eaa 100644
--- a/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder_phys.h
+++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder_phys.h
@@ -325,8 +325,10 @@ static inline enum dpu_3d_blend_mode 
dpu_encoder_helper_get_3d_blend_mode(
 
dpu_cstate = to_dpu_crtc_state(phys_enc->parent->crtc->state);
 
+   /* Use merge_3d unless DSC MERGE topology is used */
if (phys_enc->split_role == ENC_ROLE_SOLO &&
-   dpu_cstate->num_mixers == CRTC_DUAL_MIXERS)
+   dpu_cstate->num_mixers == CRTC_DUAL_MIXERS &&
+   !dpu_encoder_use_dsc_merge(phys_enc->parent))
return BLEND_3D_H_ROW_INT;
 
return BLEND_3D_NONE;
-- 
2.34.1



[Freedreno] [PATCH v5 09/13] drm/msm: Add missing num_dspp field documentation

2022-03-25 Thread Vinod Koul
Somehow documentation for num_dspp was missed, so add that

Reviewed-by: Dmitry Baryshkov 
Reviewed-by: Abhinav Kumar 
Signed-off-by: Vinod Koul 
---
 drivers/gpu/drm/msm/msm_drv.h | 1 +
 1 file changed, 1 insertion(+)

diff --git a/drivers/gpu/drm/msm/msm_drv.h b/drivers/gpu/drm/msm/msm_drv.h
index e7a312edfe67..6425a42e997c 100644
--- a/drivers/gpu/drm/msm/msm_drv.h
+++ b/drivers/gpu/drm/msm/msm_drv.h
@@ -102,6 +102,7 @@ enum msm_event_wait {
  * @num_lm:   number of layer mixers used
  * @num_enc:  number of compression encoder blocks used
  * @num_intf: number of interfaces the panel is mounted on
+ * @num_dspp: number of dspp blocks used
  */
 struct msm_display_topology {
u32 num_lm;
-- 
2.34.1



[Freedreno] [PATCH v5 07/13] drm/msm/disp/dpu1: Add support for DSC in encoder

2022-03-25 Thread Vinod Koul
We need to configure the encoder for DSC configuration and calculate DSC
parameters for the given timing so this patch adds that support by
adding dpu_encoder_prep_dsc() which is invoked when DSC is enabled.

Reviewed-by: Dmitry Baryshkov 
Reviewed-by: Abhinav Kumar 
Signed-off-by: Vinod Koul 
---
 drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c   | 126 +-
 .../gpu/drm/msm/disp/dpu1/dpu_encoder_phys.h  |   8 ++
 2 files changed, 133 insertions(+), 1 deletion(-)

diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c 
b/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c
index 1e648db439f9..2219dbfa5ee7 100644
--- a/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c
+++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c
@@ -21,6 +21,7 @@
 #include "dpu_hw_intf.h"
 #include "dpu_hw_ctl.h"
 #include "dpu_hw_dspp.h"
+#include "dpu_hw_dsc.h"
 #include "dpu_formats.h"
 #include "dpu_encoder_phys.h"
 #include "dpu_crtc.h"
@@ -136,6 +137,8 @@ enum dpu_enc_rc_states {
  * @cur_slave: As above but for the slave encoder.
  * @hw_pp: Handle to the pingpong blocks used for the display. No.
  * pingpong blocks can be different than num_phys_encs.
+ * @hw_dsc:Handle to the DSC blocks used for the display.
+ * @dsc_mask:  Bitmask of used DSC blocks.
  * @intfs_swapped: Whether or not the phys_enc interfaces have been swapped
  * for partial update right-only cases, such as pingpong
  * split where virtual pingpong does not generate IRQs
@@ -169,6 +172,7 @@ enum dpu_enc_rc_states {
  * @topology:   topology of the display
  * @idle_timeout:  idle timeout duration in milliseconds
  * @dp:msm_dp pointer, for DP encoders
+ * @dsc:   msm_display_dsc_config pointer, for DSC-enabled 
encoders
  */
 struct dpu_encoder_virt {
struct drm_encoder base;
@@ -182,6 +186,9 @@ struct dpu_encoder_virt {
struct dpu_encoder_phys *cur_master;
struct dpu_encoder_phys *cur_slave;
struct dpu_hw_pingpong *hw_pp[MAX_CHANNELS_PER_ENC];
+   struct dpu_hw_dsc *hw_dsc[MAX_CHANNELS_PER_ENC];
+
+   unsigned int dsc_mask;
 
bool intfs_swapped;
 
@@ -209,6 +216,9 @@ struct dpu_encoder_virt {
u32 idle_timeout;
 
struct msm_dp *dp;
+
+   /* DSC configuration */
+   struct msm_display_dsc_config *dsc;
 };
 
 #define to_dpu_encoder_virt(x) container_of(x, struct dpu_encoder_virt, base)
@@ -972,7 +982,9 @@ static void dpu_encoder_virt_mode_set(struct drm_encoder 
*drm_enc,
struct dpu_hw_blk *hw_ctl[MAX_CHANNELS_PER_ENC];
struct dpu_hw_blk *hw_lm[MAX_CHANNELS_PER_ENC];
struct dpu_hw_blk *hw_dspp[MAX_CHANNELS_PER_ENC] = { NULL };
-   int num_lm, num_ctl, num_pp;
+   struct dpu_hw_blk *hw_dsc[MAX_CHANNELS_PER_ENC];
+   int num_lm, num_ctl, num_pp, num_dsc;
+   unsigned int dsc_mask = 0;
int i, j;
 
if (!drm_enc) {
@@ -1027,6 +1039,18 @@ static void dpu_encoder_virt_mode_set(struct drm_encoder 
*drm_enc,
dpu_enc->hw_pp[i] = i < num_pp ? to_dpu_hw_pingpong(hw_pp[i])
: NULL;
 
+   if (dpu_enc->dsc) {
+   num_dsc = dpu_rm_get_assigned_resources(&dpu_kms->rm, 
global_state,
+   drm_enc->base.id, 
DPU_HW_BLK_DSC,
+   hw_dsc, 
ARRAY_SIZE(hw_dsc));
+   for (i = 0; i < num_dsc; i++) {
+   dpu_enc->hw_dsc[i] = to_dpu_hw_dsc(hw_dsc[i]);
+   dsc_mask |= BIT(dpu_enc->hw_dsc[i]->idx - DSC_0);
+   }
+   }
+
+   dpu_enc->dsc_mask = dsc_mask;
+
cstate = to_dpu_crtc_state(drm_crtc->state);
 
for (i = 0; i < num_lm; i++) {
@@ -1739,6 +1763,93 @@ static void dpu_encoder_vsync_event_work_handler(struct 
kthread_work *work)
nsecs_to_jiffies(ktime_to_ns(wakeup_time)));
 }
 
+static void
+dpu_encoder_dsc_initial_line_calc(struct msm_display_dsc_config *dsc,
+ u32 enc_ip_width)
+{
+   int ssm_delay, total_pixels, soft_slice_per_enc;
+
+   soft_slice_per_enc = enc_ip_width / dsc->drm->slice_width;
+
+   /*
+* minimum number of initial line pixels is a sum of:
+* 1. sub-stream multiplexer delay (83 groups for 8bpc,
+*91 for 10 bpc) * 3
+* 2. for two soft slice cases, add extra sub-stream multiplexer * 3
+* 3. the initial xmit delay
+* 4. total pipeline delay through the "lock step" of encoder (47)
+* 5. 6 additional pixels as the output of the rate buffer is
+*48 bits wide
+*/
+   ssm_delay = ((dsc->drm->bits_per_comp

[Freedreno] [PATCH v5 06/13] drm/msm/disp/dpu1: Add DSC support in hw_ctl

2022-03-25 Thread Vinod Koul
Later gens of hardware have DSC bits moved to hw_ctl, so configure these
bits so that DSC would work there as well

Reviewed-by: Dmitry Baryshkov 
Reviewed-by: Abhinav Kumar 
Signed-off-by: Vinod Koul 
---
 drivers/gpu/drm/msm/disp/dpu1/dpu_hw_ctl.c | 11 ++-
 drivers/gpu/drm/msm/disp/dpu1/dpu_hw_ctl.h |  2 ++
 2 files changed, 12 insertions(+), 1 deletion(-)

diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_ctl.c 
b/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_ctl.c
index 02da9ecf71f1..cba94aa9fdcc 100644
--- a/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_ctl.c
+++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_ctl.c
@@ -25,6 +25,8 @@
 #define   CTL_MERGE_3D_ACTIVE   0x0E4
 #define   CTL_INTF_ACTIVE   0x0F4
 #define   CTL_MERGE_3D_FLUSH0x100
+#define   CTL_DSC_ACTIVE0x0E8
+#define   CTL_DSC_FLUSH0x104
 #define   CTL_INTF_FLUSH0x110
 #define   CTL_INTF_MASTER   0x134
 #define   CTL_FETCH_PIPE_ACTIVE 0x0FC
@@ -34,6 +36,7 @@
 
 #define DPU_REG_RESET_TIMEOUT_US2000
 #define  MERGE_3D_IDX   23
+#define  DSC_IDX22
 #define  INTF_IDX   31
 #define CTL_INVALID_BIT 0x
 #define CTL_DEFAULT_GROUP_ID   0xf
@@ -121,7 +124,6 @@ static u32 dpu_hw_ctl_get_pending_flush(struct dpu_hw_ctl 
*ctx)
 
 static inline void dpu_hw_ctl_trigger_flush_v1(struct dpu_hw_ctl *ctx)
 {
-
if (ctx->pending_flush_mask & BIT(MERGE_3D_IDX))
DPU_REG_WRITE(&ctx->hw, CTL_MERGE_3D_FLUSH,
ctx->pending_merge_3d_flush_mask);
@@ -506,6 +508,9 @@ static void dpu_hw_ctl_intf_cfg_v1(struct dpu_hw_ctl *ctx,
if ((test_bit(DPU_CTL_VM_CFG, &ctx->caps->features)))
mode_sel = CTL_DEFAULT_GROUP_ID  << 28;
 
+   if (cfg->dsc)
+   DPU_REG_WRITE(&ctx->hw, CTL_DSC_FLUSH, cfg->dsc);
+
if (cfg->intf_mode_sel == DPU_CTL_MODE_SEL_CMD)
mode_sel |= BIT(17);
 
@@ -517,6 +522,10 @@ static void dpu_hw_ctl_intf_cfg_v1(struct dpu_hw_ctl *ctx,
if (cfg->merge_3d)
DPU_REG_WRITE(c, CTL_MERGE_3D_ACTIVE,
  BIT(cfg->merge_3d - MERGE_3D_0));
+   if (cfg->dsc) {
+   DPU_REG_WRITE(&ctx->hw, CTL_FLUSH, DSC_IDX);
+   DPU_REG_WRITE(c, CTL_DSC_ACTIVE, cfg->dsc);
+   }
 }
 
 static void dpu_hw_ctl_intf_cfg(struct dpu_hw_ctl *ctx,
diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_ctl.h 
b/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_ctl.h
index 806c171e5df2..75db89f66abd 100644
--- a/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_ctl.h
+++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_ctl.h
@@ -40,6 +40,7 @@ struct dpu_hw_stage_cfg {
  * @merge_3d:  3d merge block used
  * @intf_mode_sel: Interface mode, cmd / vid
  * @stream_sel:Stream selection for multi-stream interfaces
+ * @dsc:   DSC BIT masks used
  */
 struct dpu_hw_intf_cfg {
enum dpu_intf intf;
@@ -47,6 +48,7 @@ struct dpu_hw_intf_cfg {
enum dpu_merge_3d merge_3d;
enum dpu_ctl_mode_sel intf_mode_sel;
int stream_sel;
+   unsigned int dsc;
 };
 
 /**
-- 
2.34.1



[Freedreno] [PATCH v5 05/13] drm/msm/disp/dpu1: Add DSC for SDM845 to hw_catalog

2022-03-25 Thread Vinod Koul
This adds SDM845 DSC blocks into hw_catalog

Reviewed-by: Dmitry Baryshkov 
Reviewed-by: Abhinav Kumar 
Signed-off-by: Vinod Koul 
---
 .../gpu/drm/msm/disp/dpu1/dpu_hw_catalog.c| 20 +++
 1 file changed, 20 insertions(+)

diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_catalog.c 
b/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_catalog.c
index aa75991903a6..9c09cf318dfb 100644
--- a/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_catalog.c
+++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_catalog.c
@@ -821,6 +821,24 @@ static const struct dpu_pingpong_cfg sc7280_pp[] = {
PP_BLK("pingpong_2", PINGPONG_2, 0x6b000, 0, sc7280_pp_sblk, -1, -1),
PP_BLK("pingpong_3", PINGPONG_3, 0x6c000, 0, sc7280_pp_sblk, -1, -1),
 };
+
+/*
+ * DSC sub blocks config
+ */
+#define DSC_BLK(_name, _id, _base) \
+   {\
+   .name = _name, .id = _id, \
+   .base = _base, .len = 0x140, \
+   .features = 0, \
+   }
+
+static struct dpu_dsc_cfg sdm845_dsc[] = {
+   DSC_BLK("dsc_0", DSC_0, 0x8),
+   DSC_BLK("dsc_1", DSC_1, 0x80400),
+   DSC_BLK("dsc_2", DSC_2, 0x80800),
+   DSC_BLK("dsc_3", DSC_3, 0x80c00),
+};
+
 /*
  * INTF sub blocks config
  */
@@ -1124,6 +1142,8 @@ static void sdm845_cfg_init(struct dpu_mdss_cfg *dpu_cfg)
.mixer = sdm845_lm,
.pingpong_count = ARRAY_SIZE(sdm845_pp),
.pingpong = sdm845_pp,
+   .dsc_count = ARRAY_SIZE(sdm845_dsc),
+   .dsc = sdm845_dsc,
.intf_count = ARRAY_SIZE(sdm845_intf),
.intf = sdm845_intf,
.vbif_count = ARRAY_SIZE(sdm845_vbif),
-- 
2.34.1



[Freedreno] [PATCH v5 04/13] drm/msm/disp/dpu1: Add support for DSC in pingpong block

2022-03-25 Thread Vinod Koul
In SDM845, DSC can be enabled by writing to pingpong block registers, so
add support for DSC in hw_pp

Reviewed-by: Abhinav Kumar 
Reviewed-by: Dmitry Baryshkov 
Signed-off-by: Vinod Koul 
---
 .../gpu/drm/msm/disp/dpu1/dpu_hw_pingpong.c   | 32 +++
 .../gpu/drm/msm/disp/dpu1/dpu_hw_pingpong.h   | 14 
 2 files changed, 46 insertions(+)

diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_pingpong.c 
b/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_pingpong.c
index 55766c97c4c8..47c6ab6caf95 100644
--- a/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_pingpong.c
+++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_pingpong.c
@@ -28,6 +28,9 @@
 #define PP_FBC_MODE 0x034
 #define PP_FBC_BUDGET_CTL   0x038
 #define PP_FBC_LOSSY_MODE   0x03C
+#define PP_DSC_MODE 0x0a0
+#define PP_DCE_DATA_IN_SWAP 0x0ac
+#define PP_DCE_DATA_OUT_SWAP0x0c8
 
 #define PP_DITHER_EN   0x000
 #define PP_DITHER_BITDEPTH 0x004
@@ -245,6 +248,32 @@ static u32 dpu_hw_pp_get_line_count(struct dpu_hw_pingpong 
*pp)
return line;
 }
 
+static int dpu_hw_pp_dsc_enable(struct dpu_hw_pingpong *pp)
+{
+   struct dpu_hw_blk_reg_map *c = &pp->hw;
+
+   DPU_REG_WRITE(c, PP_DSC_MODE, 1);
+   return 0;
+}
+
+static void dpu_hw_pp_dsc_disable(struct dpu_hw_pingpong *pp)
+{
+   struct dpu_hw_blk_reg_map *c = &pp->hw;
+
+   DPU_REG_WRITE(c, PP_DSC_MODE, 0);
+}
+
+static int dpu_hw_pp_setup_dsc(struct dpu_hw_pingpong *pp)
+{
+   struct dpu_hw_blk_reg_map *pp_c = &pp->hw;
+   int data;
+
+   data = DPU_REG_READ(pp_c, PP_DCE_DATA_OUT_SWAP);
+   data |= BIT(18); /* endian flip */
+   DPU_REG_WRITE(pp_c, PP_DCE_DATA_OUT_SWAP, data);
+   return 0;
+}
+
 static void _setup_pingpong_ops(struct dpu_hw_pingpong *c,
unsigned long features)
 {
@@ -256,6 +285,9 @@ static void _setup_pingpong_ops(struct dpu_hw_pingpong *c,
c->ops.get_autorefresh = dpu_hw_pp_get_autorefresh_config;
c->ops.poll_timeout_wr_ptr = dpu_hw_pp_poll_timeout_wr_ptr;
c->ops.get_line_count = dpu_hw_pp_get_line_count;
+   c->ops.setup_dsc = dpu_hw_pp_setup_dsc;
+   c->ops.enable_dsc = dpu_hw_pp_dsc_enable;
+   c->ops.disable_dsc = dpu_hw_pp_dsc_disable;
 
if (test_bit(DPU_PINGPONG_DITHER, &features))
c->ops.setup_dither = dpu_hw_pp_setup_dither;
diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_pingpong.h 
b/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_pingpong.h
index 89d08a715c16..12758468d9ca 100644
--- a/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_pingpong.h
+++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_pingpong.h
@@ -124,6 +124,20 @@ struct dpu_hw_pingpong_ops {
 */
void (*setup_dither)(struct dpu_hw_pingpong *pp,
struct dpu_hw_dither_cfg *cfg);
+   /**
+* Enable DSC
+*/
+   int (*enable_dsc)(struct dpu_hw_pingpong *pp);
+
+   /**
+* Disable DSC
+*/
+   void (*disable_dsc)(struct dpu_hw_pingpong *pp);
+
+   /**
+* Setup DSC
+*/
+   int (*setup_dsc)(struct dpu_hw_pingpong *pp);
 };
 
 struct dpu_hw_merge_3d;
-- 
2.34.1



[Freedreno] [PATCH v5 02/13] drm/msm/dsi: Pass DSC params to drm_panel

2022-03-25 Thread Vinod Koul
When DSC is enabled, we need to get the DSC parameters from the panel
driver, so add a dsc parameter in panel to fetch and pass DSC
configuration for DSI panels to DPU encoder, which will enable and
then configure DSC hardware blocks accordingly.

Signed-off-by: Dmitry Baryshkov 
Reviewed-by: Abhinav Kumar 
Signed-off-by: Vinod Koul 
---
 drivers/gpu/drm/msm/disp/dpu1/dpu_kms.c |  2 ++
 drivers/gpu/drm/msm/dsi/dsi.c   |  5 +
 drivers/gpu/drm/msm/dsi/dsi.h   |  1 +
 drivers/gpu/drm/msm/dsi/dsi_host.c  | 22 ++
 drivers/gpu/drm/msm/msm_drv.h   |  8 
 include/drm/drm_panel.h |  7 +++
 6 files changed, 45 insertions(+)

diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_kms.c 
b/drivers/gpu/drm/msm/disp/dpu1/dpu_kms.c
index 47fe11a84a77..ef6ddac22767 100644
--- a/drivers/gpu/drm/msm/disp/dpu1/dpu_kms.c
+++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_kms.c
@@ -578,6 +578,8 @@ static int _dpu_kms_initialize_dsi(struct drm_device *dev,
MSM_DISPLAY_CAP_CMD_MODE :
MSM_DISPLAY_CAP_VID_MODE;
 
+   info.dsc = msm_dsi_get_dsc_config(priv->dsi[i]);
+
if (msm_dsi_is_bonded_dsi(priv->dsi[i]) && priv->dsi[other]) {
rc = msm_dsi_modeset_init(priv->dsi[other], dev, 
encoder);
if (rc) {
diff --git a/drivers/gpu/drm/msm/dsi/dsi.c b/drivers/gpu/drm/msm/dsi/dsi.c
index 052548883d27..3aeac15e7421 100644
--- a/drivers/gpu/drm/msm/dsi/dsi.c
+++ b/drivers/gpu/drm/msm/dsi/dsi.c
@@ -20,6 +20,11 @@ bool msm_dsi_is_cmd_mode(struct msm_dsi *msm_dsi)
return !(host_flags & MIPI_DSI_MODE_VIDEO);
 }
 
+struct msm_display_dsc_config *msm_dsi_get_dsc_config(struct msm_dsi *msm_dsi)
+{
+   return msm_dsi_host_get_dsc_config(msm_dsi->host);
+}
+
 static int dsi_get_phy(struct msm_dsi *msm_dsi)
 {
struct platform_device *pdev = msm_dsi->pdev;
diff --git a/drivers/gpu/drm/msm/dsi/dsi.h b/drivers/gpu/drm/msm/dsi/dsi.h
index c8dedc95428c..16cd9b2fce86 100644
--- a/drivers/gpu/drm/msm/dsi/dsi.h
+++ b/drivers/gpu/drm/msm/dsi/dsi.h
@@ -152,6 +152,7 @@ int dsi_calc_clk_rate_v2(struct msm_dsi_host *msm_host, 
bool is_bonded_dsi);
 int dsi_calc_clk_rate_6g(struct msm_dsi_host *msm_host, bool is_bonded_dsi);
 void msm_dsi_host_snapshot(struct msm_disp_state *disp_state, struct 
mipi_dsi_host *host);
 void msm_dsi_host_test_pattern_en(struct mipi_dsi_host *host);
+struct msm_display_dsc_config *msm_dsi_host_get_dsc_config(struct 
mipi_dsi_host *host);
 
 /* dsi phy */
 struct msm_dsi_phy;
diff --git a/drivers/gpu/drm/msm/dsi/dsi_host.c 
b/drivers/gpu/drm/msm/dsi/dsi_host.c
index 27553194f9fa..7e9913eff724 100644
--- a/drivers/gpu/drm/msm/dsi/dsi_host.c
+++ b/drivers/gpu/drm/msm/dsi/dsi_host.c
@@ -2059,9 +2059,24 @@ 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 drm_panel *panel;
int ret;
 
msm_host->dev = dev;
+   panel = msm_dsi_host_get_panel(&msm_host->base);
+
+   if (panel && panel->dsc) {
+   struct msm_display_dsc_config *dsc = msm_host->dsc;
+
+   if (!dsc) {
+   dsc = devm_kzalloc(&msm_host->pdev->dev, sizeof(*dsc), 
GFP_KERNEL);
+   if (!dsc)
+   return -ENOMEM;
+   dsc->drm = panel->dsc;
+   msm_host->dsc = 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);
@@ -2626,3 +2641,10 @@ void msm_dsi_host_test_pattern_en(struct mipi_dsi_host 
*host)
dsi_write(msm_host, 
REG_DSI_TEST_PATTERN_GEN_CMD_STREAM0_TRIGGER,

DSI_TEST_PATTERN_GEN_CMD_STREAM0_TRIGGER_SW_TRIGGER);
 }
+
+struct msm_display_dsc_config *msm_dsi_host_get_dsc_config(struct 
mipi_dsi_host *host)
+{
+   struct msm_dsi_host *msm_host = to_msm_dsi_host(host);
+
+   return msm_host->dsc;
+}
diff --git a/drivers/gpu/drm/msm/msm_drv.h b/drivers/gpu/drm/msm/msm_drv.h
index 384f9bad4760..e7a312edfe67 100644
--- a/drivers/gpu/drm/msm/msm_drv.h
+++ b/drivers/gpu/drm/msm/msm_drv.h
@@ -119,6 +119,7 @@ struct msm_display_topology {
  *  based on num_of_h_tiles
  * @is_te_using_watchdog_timer:  Boolean to indicate watchdog TE is
  *  used instead of panel TE in cmd mode panels
+ * @dsc:   DSC configuration data for DSC-enabled displays
  */
 struct msm_display_info {
int intf_type;
@@ -126,6 +127,7 @@ struct msm_display_info {
uint32_t num_of_h_tiles;
uint32_t h_tile_instance[MAX_H_TILES_PER_DISPLAY];
bool

[Freedreno] [PATCH v5 03/13] drm/msm/disp/dpu1: Add support for DSC

2022-03-25 Thread Vinod Koul
Display Stream Compression (DSC) is one of the hw blocks in dpu, so add
support by adding hw blocks for DSC

Reviewed-by: Dmitry Baryshkov 
Signed-off-by: Vinod Koul 
---
 drivers/gpu/drm/msm/Makefile  |   1 +
 .../gpu/drm/msm/disp/dpu1/dpu_hw_catalog.h|  13 ++
 drivers/gpu/drm/msm/disp/dpu1/dpu_hw_dsc.c| 210 ++
 drivers/gpu/drm/msm/disp/dpu1/dpu_hw_dsc.h|  77 +++
 drivers/gpu/drm/msm/disp/dpu1/dpu_hw_mdss.h   |  13 ++
 5 files changed, 314 insertions(+)
 create mode 100644 drivers/gpu/drm/msm/disp/dpu1/dpu_hw_dsc.c
 create mode 100644 drivers/gpu/drm/msm/disp/dpu1/dpu_hw_dsc.h

diff --git a/drivers/gpu/drm/msm/Makefile b/drivers/gpu/drm/msm/Makefile
index 03ab55c37beb..7ec3c70c77ce 100644
--- a/drivers/gpu/drm/msm/Makefile
+++ b/drivers/gpu/drm/msm/Makefile
@@ -56,6 +56,7 @@ msm-y := \
disp/dpu1/dpu_formats.o \
disp/dpu1/dpu_hw_catalog.o \
disp/dpu1/dpu_hw_ctl.o \
+   disp/dpu1/dpu_hw_dsc.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 31af04afda7d..5fc0888351c7 100644
--- a/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_catalog.h
+++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_catalog.h
@@ -556,6 +556,16 @@ struct dpu_merge_3d_cfg  {
const struct dpu_merge_3d_sub_blks *sblk;
 };
 
+/**
+ * struct dpu_dsc_cfg - information of DSC blocks
+ * @id enum identifying this block
+ * @base   register offset of this block
+ * @features   bit mask identifying sub-blocks/features
+ */
+struct dpu_dsc_cfg {
+   DPU_HW_BLK_INFO;
+};
+
 /**
  * struct dpu_intf_cfg - information of timing engine blocks
  * @id enum identifying this block
@@ -752,6 +762,9 @@ struct dpu_mdss_cfg {
u32 merge_3d_count;
const struct dpu_merge_3d_cfg *merge_3d;
 
+   u32 dsc_count;
+   struct dpu_dsc_cfg *dsc;
+
u32 intf_count;
const struct dpu_intf_cfg *intf;
 
diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_dsc.c 
b/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_dsc.c
new file mode 100644
index ..ff1d74e4aa2c
--- /dev/null
+++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_dsc.c
@@ -0,0 +1,210 @@
+// SPDX-License-Identifier: GPL-2.0-only
+/*
+ * Copyright (c) 2020-2022, Linaro Limited
+ */
+
+#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_COMMON_MODE0x000
+#define DSC_ENC 0X004
+#define DSC_PICTURE 0x008
+#define DSC_SLICE   0x00C
+#define DSC_CHUNK_SIZE  0x010
+#define DSC_DELAY   0x014
+#define DSC_SCALE_INITIAL   0x018
+#define DSC_SCALE_DEC_INTERVAL  0x01C
+#define DSC_SCALE_INC_INTERVAL  0x020
+#define DSC_FIRST_LINE_BPG_OFFSET   0x024
+#define DSC_BPG_OFFSET  0x028
+#define DSC_DSC_OFFSET  0x02C
+#define DSC_FLATNESS0x030
+#define DSC_RC_MODEL_SIZE   0x034
+#define DSC_RC  0x038
+#define DSC_RC_BUF_THRESH   0x03C
+#define DSC_RANGE_MIN_QP0x074
+#define DSC_RANGE_MAX_QP0x0B0
+#define DSC_RANGE_BPG_OFFSET0x0EC
+
+static void dpu_hw_dsc_disable(struct dpu_hw_dsc *dsc)
+{
+   struct dpu_hw_blk_reg_map *c = &dsc->hw;
+
+   DPU_REG_WRITE(c, DSC_COMMON_MODE, 0);
+}
+
+static void dpu_hw_dsc_config(struct dpu_hw_dsc *hw_dsc,
+ struct msm_display_dsc_config *dsc, u32 mode)
+{
+   struct dpu_hw_blk_reg_map *c = &hw_dsc->hw;
+   u32 data, lsb, bpp;
+   u32 initial_lines = dsc->initial_lines;
+   bool is_cmd_mode = !(mode & DSC_MODE_VIDEO);
+
+   DPU_REG_WRITE(c, DSC_COMMON_MODE, mode);
+
+   if (is_cmd_mode)
+   initial_lines += 1;
+
+   data = (initial_lines << 20);
+   data |= ((dsc->slice_last_group_size - 1) << 18);
+   /* bpp is 6.4 format, 4 LSBs bits are for fractional part */
+   data |= dsc->drm->bits_per_pixel << 12;
+   lsb = dsc->drm->bits_per_pixel % 4;
+   bpp = dsc->drm->bits_per_pixel / 4;
+   bpp *= 4;
+   bpp <<= 4;
+   bpp |= lsb;
+
+   data |= bpp << 8;
+   data |= (dsc->drm->block_pred_enable << 7);
+   data |= (dsc->drm->line_buf_depth << 3);
+   data |= (dsc->drm->simple_422 << 2);
+   data |= (dsc->drm->convert_rgb << 1);
+   data |= dsc->drm->bits_per_component;
+
+   DPU_REG_WRITE(c, DSC_ENC, data);
+
+   data = dsc->drm->pic_width << 16;
+   data |= dsc->drm->pic_he

[Freedreno] [PATCH v5 00/13] drm/msm: Add Display Stream Compression Support

2022-03-25 Thread Vinod Koul
Display Stream Compression (DSC) compresses the display stream in host which
is later decoded by panel. This series enables this for Qualcomm msm driver.
This was tested on Google Pixel3 phone which use LGE SW43408 panel.
 
The changes include DSC data and hardware block enabling for DPU1 then
support in encoder. We also add support in DSI and introduce required
topology changes.
 
In order for panel to set the DSC parameters we add dsc in drm_panel and
pass the dsc configuration from the panel driver

We still have dsc as a globabl entity. I think while doing DP + DSC we
should be able to update it, right now comprehending the requirements are
bit difficult.
 
Complete changes which enable this for Pixel3 along with panel driver (not
part of this series) and DT changes can be found at:
git.linaro.org/people/vinod.koul/kernel.git pixel/dsc_v5
 
Comments welcome!

Changes since v4:
 - Use new apprach based on Abhinav suggestion for dsc with 3d-merge
 - Make common function for dsc timing caln and call that from video and cmd
   mode
 - update description for patch "Pass DSC params to drm_panel"
 - update couple of typos as pointed by Marijn
 - drop dpu_encoder_dsc_pclk_param_calc() as that was duplicating the caln
   done in dsi timing
 - Update copyright to 2022 to new files
 - Update Abhinav's email to new quic one

Changes since v3:
 - Merge changes from Dmitry to have dsc per encoder instance
 - add warning for dsc and mode3d enabled together
 - set dsc in dpu_encoder_phys_vid as well
 - remove dsc hardcoded mask
 - use devm_kzalloc for memory allocation for dsc

Changes since v2:
 - Fix comments by Dimitry except the dsc being global.
 - Move RM patch later for dependency on topology now
 - Add patch for mode valid callback for dsi_mgr
 - Add missing structure documentation patch
 - Fix errors in mode_3d changes
 - Rebase on v5.16-rc1 and test

Changes since v1:
 - Fix various issues spotted by kbuildbot
 - Rebase to v5.15-rc3
 - Remove unused fields and duplicate defines
 - Enable DSC blocks only when DSC is enabled
 - remove sdm845 feature mask, use 0
 - Check for DSC in hw_ctl

Changes since RFC:
 - Drop the DT binding patch as we derive the configuration from panel
 - Drop the drm api patch as we no longer need it (use pps drm api)
 - Fix comments raised by Dimitry
 - Add dsc parameters calculation from downstream

Dmitry Baryshkov (1):
  drm/msm/dpu: don't use merge_3d if DSC merge topology is used

Vinod Koul (12):
  drm/msm/dsi: add support for dsc data
  drm/msm/dsi: Pass DSC params to drm_panel
  drm/msm/disp/dpu1: Add support for DSC
  drm/msm/disp/dpu1: Add support for DSC in pingpong block
  drm/msm/disp/dpu1: Add DSC for SDM845 to hw_catalog
  drm/msm/disp/dpu1: Add DSC support in hw_ctl
  drm/msm/disp/dpu1: Add support for DSC in encoder
  drm/msm: Add missing num_dspp field documentation
  drm/msm/disp/dpu1: Add support for DSC in topology
  drm/msm/disp/dpu1: Add DSC support in RM
  drm/msm/dsi: add mode valid callback for dsi_mgr
  drm/msm/dsi: Add support for DSC configuration

 drivers/gpu/drm/msm/Makefile  |   1 +
 drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c   | 155 +-
 drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.h   |   6 +
 .../gpu/drm/msm/disp/dpu1/dpu_encoder_phys.h  |  12 +-
 .../gpu/drm/msm/disp/dpu1/dpu_hw_catalog.c|  20 ++
 .../gpu/drm/msm/disp/dpu1/dpu_hw_catalog.h|  13 +
 drivers/gpu/drm/msm/disp/dpu1/dpu_hw_ctl.c|  11 +-
 drivers/gpu/drm/msm/disp/dpu1/dpu_hw_ctl.h|   2 +
 drivers/gpu/drm/msm/disp/dpu1/dpu_hw_dsc.c| 210 ++
 drivers/gpu/drm/msm/disp/dpu1/dpu_hw_dsc.h|  77 +
 drivers/gpu/drm/msm/disp/dpu1/dpu_hw_mdss.h   |  13 +
 .../gpu/drm/msm/disp/dpu1/dpu_hw_pingpong.c   |  32 ++
 .../gpu/drm/msm/disp/dpu1/dpu_hw_pingpong.h   |  14 +
 drivers/gpu/drm/msm/disp/dpu1/dpu_kms.c   |   2 +
 drivers/gpu/drm/msm/disp/dpu1/dpu_kms.h   |   1 +
 drivers/gpu/drm/msm/disp/dpu1/dpu_rm.c|  56 
 drivers/gpu/drm/msm/disp/dpu1/dpu_rm.h|   1 +
 drivers/gpu/drm/msm/dsi/dsi.c |   5 +
 drivers/gpu/drm/msm/dsi/dsi.h |   3 +
 drivers/gpu/drm/msm/dsi/dsi.xml.h |  10 +
 drivers/gpu/drm/msm/dsi/dsi_host.c| 274 +-
 drivers/gpu/drm/msm/dsi/dsi_manager.c |  12 +
 drivers/gpu/drm/msm/msm_drv.h |  26 ++
 include/drm/drm_panel.h   |   7 +
 24 files changed, 959 insertions(+), 4 deletions(-)
 create mode 100644 drivers/gpu/drm/msm/disp/dpu1/dpu_hw_dsc.c
 create mode 100644 drivers/gpu/drm/msm/disp/dpu1/dpu_hw_dsc.h

-- 
2.34.1



[Freedreno] [PATCH v5 01/13] drm/msm/dsi: add support for dsc data

2022-03-25 Thread Vinod Koul
Display Stream Compression (DSC) parameters need to be calculated. Add
helpers and struct msm_display_dsc_config in msm_drv for this
msm_display_dsc_config uses drm_dsc_config for DSC parameters.

Reviewed-by: Dmitry Baryshkov 
Reviewed-by: Abhinav Kumar 
Signed-off-by: Vinod Koul 
---
 drivers/gpu/drm/msm/dsi/dsi_host.c | 132 +
 drivers/gpu/drm/msm/msm_drv.h  |  15 
 2 files changed, 147 insertions(+)

diff --git a/drivers/gpu/drm/msm/dsi/dsi_host.c 
b/drivers/gpu/drm/msm/dsi/dsi_host.c
index 6b3ced4aaaf5..27553194f9fa 100644
--- a/drivers/gpu/drm/msm/dsi/dsi_host.c
+++ b/drivers/gpu/drm/msm/dsi/dsi_host.c
@@ -31,6 +31,8 @@
 
 #define DSI_RESET_TOGGLE_DELAY_MS 20
 
+static int dsi_populate_dsc_params(struct msm_display_dsc_config *dsc);
+
 static int dsi_get_version(const void __iomem *base, u32 *major, u32 *minor)
 {
u32 ver;
@@ -157,6 +159,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;
@@ -1718,6 +1721,135 @@ 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 mux_words_size;
+   int groups_per_line, groups_total;
+   int min_rate_buffer_size;
+   int hrd_delay;
+   int pre_num_extra_mux_bits, num_extra_mux_bits;
+   int slice_bits;
+   int target_bpp_x16;
+   int data;
+   int final_value, final_scale;
+   int i;
+
+   dsc->drm->rc_model_size = 8192;
+   dsc->drm->first_line_bpg_offset = 12;
+   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; /* Not bpp 12 */
+   if (dsc->drm->bits_per_pixel != 8)
+   dsc->drm->initial_offset = 2048;/* bpp = 12 */
+
+   mux_words_size = 48;/* bpc == 8/10 */
+   if (dsc->drm->bits_per_component == 12)
+   mux_words_size = 64;
+
+   dsc->drm->initial_xmit_delay = 512;
+   dsc->drm->initial_scale_value = 32;
+   dsc->drm->first_line_bpg_offset = 12;
+   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->det_thresh_flatness = 7 + 2 * (dsc->drm->bits_per_component - 8);
+   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;
+
+   /* FIXME: need to call drm_dsc_compute_rc_parameters() so that rest of
+* params are calculated
+*/
+   dsc->slice_last_group_size = 3 - (dsc->drm->slice_width % 3);
+   groups_per_line = DIV_ROUND_UP(dsc->drm->slice_width, 3);
+   dsc->drm->slice_chunk_size = dsc->drm->slice_width * 
dsc->drm->bits_per_pixel / 8;
+   if ((dsc->drm->slice_width * dsc->drm->bits_per_pixel) % 8)
+   dsc->drm->slice_chunk_size++;
+
+   /* rbs-min */
+   min_rate_buffer_size =  dsc->drm->rc_model_size - 
dsc->drm->initial_offset +
+   dsc->drm->initial_xmit_delay * 
dsc->drm->bits_per_pixel +
+   groups_per_line * 
dsc->drm->first_line_bpg_offset;
+
+   hrd_delay = DIV_ROUND_UP(min_rate_buffer_size, 
dsc->drm->bits_per_pixel);
+
+   dsc->drm->initial_dec_delay = hrd_delay - dsc->drm->initial_xmit_delay;
+
+   dsc->drm->i

Re: [Freedreno] [REPOST PATCH v4 06/13] drm/msm/disp/dpu1: Add DSC support in hw_ctl

2022-03-24 Thread Vinod Koul
On 17-02-22, 23:20, Marijn Suijten wrote:
> On 2022-02-10 16:04:16, Vinod Koul wrote:
> > Later gens of hardware have DSC bits moved to hw_ctl, so configure these
> > bits so that DSC would work there as well
> > 
> > Reviewed-by: Dmitry Baryshkov 
> > Signed-off-by: Vinod Koul 
> > ---
> >  drivers/gpu/drm/msm/disp/dpu1/dpu_hw_ctl.c | 11 ++-
> >  drivers/gpu/drm/msm/disp/dpu1/dpu_hw_ctl.h |  2 ++
> >  2 files changed, 12 insertions(+), 1 deletion(-)
> > 
> > diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_ctl.c 
> > b/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_ctl.c
> > index 02da9ecf71f1..49659165cea8 100644
> > --- a/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_ctl.c
> > +++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_ctl.c
> > @@ -25,6 +25,8 @@
> >  #define   CTL_MERGE_3D_ACTIVE   0x0E4
> >  #define   CTL_INTF_ACTIVE   0x0F4
> >  #define   CTL_MERGE_3D_FLUSH0x100
> > +#define   CTL_DSC_ACTIVE0x0E8
> > +#define   CTL_DSC_FLUSH0x104
> >  #define   CTL_INTF_FLUSH0x110
> >  #define   CTL_INTF_MASTER   0x134
> >  #define   CTL_FETCH_PIPE_ACTIVE 0x0FC
> > @@ -34,6 +36,7 @@
> >  
> >  #define DPU_REG_RESET_TIMEOUT_US2000
> >  #define  MERGE_3D_IDX   23
> > +#define  DSC_IDX22
> 
> This define does not seem used in any of these patches.  Is that
> intended?

This should used in the below case you pointed, updated now

> >  static void dpu_hw_ctl_intf_cfg(struct dpu_hw_ctl *ctx,
> > diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_ctl.h 
> > b/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_ctl.h
> > index 806c171e5df2..9847c9c46d6f 100644
> > --- a/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_ctl.h
> > +++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_ctl.h
> > @@ -40,6 +40,7 @@ struct dpu_hw_stage_cfg {
> >   * @merge_3d:  3d merge block used
> >   * @intf_mode_sel: Interface mode, cmd / vid
> >   * @stream_sel:Stream selection for multi-stream interfaces
> > + * @dsc:   DSC BIT masks
> 
> Bit masks of what?  Enabled DSCs?  A more verbose doc-comment is desired
> here, matching the rest of the fields :) - something like "DSC block(s)
> used" similar to merge_3d?  Or copy the docs from `dsc_mask`, which is
> the value that is written into this field.

Updated

-- 
~Vinod


Re: [Freedreno] [REPOST PATCH v4 13/13] drm/msm/dsi: Add support for DSC configuration

2022-03-24 Thread Vinod Koul
On 21-02-22, 05:11, Dmitry Baryshkov wrote:
> On 10/02/2022 13: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 
> > Signed-off-by: Vinod Koul 
> > ---
> >   drivers/gpu/drm/msm/dsi/dsi.xml.h  |  10 +++
> >   drivers/gpu/drm/msm/dsi/dsi_host.c | 109 -
> >   2 files changed, 118 insertions(+), 1 deletion(-)
> > 
> > diff --git a/drivers/gpu/drm/msm/dsi/dsi.xml.h 
> > b/drivers/gpu/drm/msm/dsi/dsi.xml.h
> > index 49b551ad1bff..c1c85df58c4b 100644
> > --- a/drivers/gpu/drm/msm/dsi/dsi.xml.h
> > +++ b/drivers/gpu/drm/msm/dsi/dsi.xml.h
> > @@ -706,4 +706,14 @@ static inline uint32_t DSI_VERSION_MAJOR(uint32_t val)
> >   #define REG_DSI_CPHY_MODE_CTRL
> > 0x02d4
> > +#define REG_DSI_VIDEO_COMPRESSION_MODE_CTRL
> > 0x029c
> > +
> > +#define REG_DSI_VIDEO_COMPRESSION_MODE_CTRL2   
> > 0x02a0
> > +
> > +#define REG_DSI_COMMAND_COMPRESSION_MODE_CTRL  
> > 0x02a4
> > +
> > +#define REG_DSI_COMMAND_COMPRESSION_MODE_CTRL2 
> > 0x02a8
> > +
> > +#define REG_DSI_COMMAND_COMPRESSION_MODE_CTRL3 
> > 0x02ac
> > +
> >   #endif /* DSI_XML */
> > diff --git a/drivers/gpu/drm/msm/dsi/dsi_host.c 
> > b/drivers/gpu/drm/msm/dsi/dsi_host.c
> > index 438c80750682..3d8d5a1daaa3 100644
> > --- a/drivers/gpu/drm/msm/dsi/dsi_host.c
> > +++ b/drivers/gpu/drm/msm/dsi/dsi_host.c
> > @@ -908,6 +908,20 @@ 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 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;
> > +   }
> > +
> > +   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_bonded_dsi)
> >   {
> > struct drm_display_mode *mode = msm_host->mode;
> > @@ -940,7 +954,68 @@ 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 */
> > +   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;
> > +   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);
> > +
> > +   dsc->drm->slice_count = 1;
> > +   dsc->bytes_in_slice = 
> > DIV_ROUND_UP(ds

Re: [Freedreno] [REPOST PATCH v4 07/13] drm/msm/disp/dpu1: Add support for DSC in encoder

2022-03-24 Thread Vinod Koul
On 23-03-22, 20:10, Vinod Koul wrote:
> On 17-02-22, 23:32, Marijn Suijten wrote:
> > On 2022-02-10 16:04:17, Vinod Koul wrote:

> > > +
> > > + slice_count = dsc->drm->slice_count;
> > > + slice_per_intf = DIV_ROUND_UP(width, dsc->drm->slice_width);
> > > +
> > > + /*
> > > +  * If slice_count is greater than slice_per_intf then default to 1.
> > > +  * This can happen during partial update.
> > > +  */
> > > + if (slice_count > slice_per_intf)
> > > + slice_count = 1;
> > > +
> > > + bytes_in_slice = DIV_ROUND_UP(dsc->drm->slice_width *
> > > +   dsc->drm->bits_per_pixel, 8);
> > > + total_bytes_per_intf = 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_in_slice = bytes_in_slice;
> > > + dsc->bytes_per_pkt = bytes_in_slice * slice_count;
> > > + dsc->pkt_per_line = slice_per_intf / slice_count;
> > > +}
> > 
> > I've seen the same calculations duplicated twice in dsi code.  Since the
> > msm_display_dsc_config struct is available in a header, perhaps a single
> > - easily reviewable and maintainable - calculation function should be
> > available there too?
> 
> Let me try check if we can make it common..

I rechecked and we can actually remove this as we do this caln in timing
and update the dsc structure there. So this fn is dropped now

-- 
~Vinod


Re: [Freedreno] [REPOST PATCH v4 07/13] drm/msm/disp/dpu1: Add support for DSC in encoder

2022-03-23 Thread Vinod Koul
On 17-02-22, 23:32, Marijn Suijten wrote:
> On 2022-02-10 16:04:17, Vinod Koul wrote:
> > We need to configure the encoder for DSC configuration and calculate DSC
> > parameters for the given timing so this patch adds that support by
> > adding dpu_encoder_prep_dsc() which is invoked when DSC is enabled.
> > 
> > Signed-off-by: Vinod Koul 
> > ---
> >  drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c   | 164 +-
> >  .../gpu/drm/msm/disp/dpu1/dpu_encoder_phys.h  |   8 +
> >  2 files changed, 171 insertions(+), 1 deletion(-)
> > 
> > diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c 
> > b/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c
> > index 1e648db439f9..95a7bf362e81 100644
> > --- a/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c
> > +++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c
> > @@ -21,6 +21,7 @@
> >  #include "dpu_hw_intf.h"
> >  #include "dpu_hw_ctl.h"
> >  #include "dpu_hw_dspp.h"
> > +#include "dpu_hw_dsc.h"
> >  #include "dpu_formats.h"
> >  #include "dpu_encoder_phys.h"
> >  #include "dpu_crtc.h"
> > @@ -136,6 +137,8 @@ enum dpu_enc_rc_states {
> >   * @cur_slave: As above but for the slave encoder.
> >   * @hw_pp: Handle to the pingpong blocks used for the display. No.
> >   * pingpong blocks can be different than num_phys_encs.
> > + * @hw_dsc:Handle to the DSC blocks used for the display.
> > + * @dsc_mask:  The bitmask of used DSC blocks.
> 
> No need for "^The" prefix here.

Removed

> 
> >   * @intfs_swapped: Whether or not the phys_enc interfaces have been swapped
> >   * for partial update right-only cases, such as pingpong
> >   * split where virtual pingpong does not generate IRQs
> > @@ -169,6 +172,7 @@ enum dpu_enc_rc_states {
> >   * @topology:   topology of the display
> >   * @idle_timeout:  idle timeout duration in milliseconds
> >   * @dp:msm_dp pointer, for DP encoders
> > + * @dsc:   msm_display_dsc_config pointer, for DSC-enabled 
> > encoders
> >   */
> >  struct dpu_encoder_virt {
> > struct drm_encoder base;
> > @@ -182,6 +186,9 @@ struct dpu_encoder_virt {
> > struct dpu_encoder_phys *cur_master;
> > struct dpu_encoder_phys *cur_slave;
> > struct dpu_hw_pingpong *hw_pp[MAX_CHANNELS_PER_ENC];
> > +   struct dpu_hw_dsc *hw_dsc[MAX_CHANNELS_PER_ENC];
> > +
> > +   unsigned int dsc_mask;
> >  
> > bool intfs_swapped;
> >  
> > @@ -209,6 +216,9 @@ struct dpu_encoder_virt {
> > u32 idle_timeout;
> >  
> > struct msm_dp *dp;
> > +
> > +   /* DSC configuration */
> > +   struct msm_display_dsc_config *dsc;
> >  };
> >  
> >  #define to_dpu_encoder_virt(x) container_of(x, struct dpu_encoder_virt, 
> > base)
> > @@ -972,7 +982,8 @@ static void dpu_encoder_virt_mode_set(struct 
> > drm_encoder *drm_enc,
> > struct dpu_hw_blk *hw_ctl[MAX_CHANNELS_PER_ENC];
> > struct dpu_hw_blk *hw_lm[MAX_CHANNELS_PER_ENC];
> > struct dpu_hw_blk *hw_dspp[MAX_CHANNELS_PER_ENC] = { NULL };
> > -   int num_lm, num_ctl, num_pp;
> > +   struct dpu_hw_blk *hw_dsc[MAX_CHANNELS_PER_ENC];
> > +   int num_lm, num_ctl, num_pp, num_dsc;
> > int i, j;
> >  
> > if (!drm_enc) {
> > @@ -1027,6 +1038,23 @@ static void dpu_encoder_virt_mode_set(struct 
> > drm_encoder *drm_enc,
> > dpu_enc->hw_pp[i] = i < num_pp ? to_dpu_hw_pingpong(hw_pp[i])
> > : NULL;
> >  
> > +   dpu_enc->dsc_mask = 0;
> > +
> > +   if (dpu_enc->dsc) {
> > +   unsigned int dsc_mask = 0;
> 
> Perhaps move this definition outside the if, and unconditionally
> perform:
> 
>   dpu_enc->dsc_mask = dsc_mask;
> 
> Below the if, instead of having to write it twice when ->dsc is truthy?

That is a good suggestion, updated now

> 
> > +
> > +   num_dsc = dpu_rm_get_assigned_resources(&dpu_kms->rm, 
> > global_state,
> > +   drm_enc->base.id, 
> > DPU_HW_BLK_DSC,
> > +   hw_dsc, 
> > ARRAY_SIZE(hw_dsc));
> > +   for (i = 0; i < MAX_CHANNELS_PER_ENC; i++)
> > +   dpu_enc->hw_dsc[i] = i < num_dsc ? 
> > to_dpu_hw_dsc

Re: [Freedreno] [REPOST PATCH v4 10/13] drm/msm/disp/dpu1: Add support for DSC in topology

2022-03-23 Thread Vinod Koul
On 17-02-22, 23:37, Marijn Suijten wrote:
> On 2022-02-10 16:04:20, Vinod Koul wrote:
> > For DSC to work we typically need a 2,2,1 configuration. This should
> > suffice for resolutions up to 4k. For more resolutions like 8k this won't
> > work.
> > 
> > Also, it is better to use 2 LMs and DSC instances as half width results
> > in lesser power consumption as compared to single LM, DSC at full width.
> > 
> > The panel has been tested only with 2,2,1 configuration, so for
> > now we blindly create 2,2,1 topology when DSC is enabled
> > 
> > Co-developed-by: Abhinav Kumar 
> > Signed-off-by: Abhinav Kumar 
> > Signed-off-by: Vinod Koul 
> > ---
> >  drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c | 13 +
> >  drivers/gpu/drm/msm/msm_drv.h   |  2 ++
> >  2 files changed, 15 insertions(+)
> > 
> > diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c 
> > b/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c
> > index 95a7bf362e81..13ccb7b3cce5 100644
> > --- a/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c
> > +++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c
> > @@ -574,8 +574,21 @@ static struct msm_display_topology 
> > dpu_encoder_get_topology(
> > topology.num_enc = 0;
> > topology.num_intf = intf_count;
> >  
> > +   if (dpu_enc->dsc) {
> > +   /* In case of Display Stream Compression DSC, we would use
> 
> Just like elsewhere, since you wrote out Display Stream Compression,
> write the "DSC" abbreviation between parentheses ()?

Updated

-- 
~Vinod


Re: [Freedreno] [REPOST PATCH v4 10/13] drm/msm/disp/dpu1: Add support for DSC in topology

2022-03-23 Thread Vinod Koul
On 17-02-22, 22:44, Marijn Suijten wrote:
> On 2022-02-10 16:04:20, Vinod Koul wrote:
> > For DSC to work we typically need a 2,2,1 configuration. This should
> > suffice for resolutions up to 4k. For more resolutions like 8k this won't
> > work.
> > 
> > Also, it is better to use 2 LMs and DSC instances as half width results
> > in lesser power consumption as compared to single LM, DSC at full width.
> > 
> > The panel has been tested only with 2,2,1 configuration, so for
> > now we blindly create 2,2,1 topology when DSC is enabled
> > 
> > Co-developed-by: Abhinav Kumar 
> > Signed-off-by: Abhinav Kumar 
> > Signed-off-by: Vinod Koul 
> > ---
> >  drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c | 13 +
> >  drivers/gpu/drm/msm/msm_drv.h   |  2 ++
> >  2 files changed, 15 insertions(+)
> > 
> > diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c 
> > b/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c
> > index 95a7bf362e81..13ccb7b3cce5 100644
> > --- a/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c
> > +++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c
> > @@ -574,8 +574,21 @@ static struct msm_display_topology 
> > dpu_encoder_get_topology(
> > topology.num_enc = 0;
> > topology.num_intf = intf_count;
> >  
> > +   if (dpu_enc->dsc) {
> > +   /* In case of Display Stream Compression DSC, we would use
> > +* 2 encoders, 2 line mixers and 1 interface
> 
> LM is a layer mixer, not a line mixer, right?

Right, thanks for spotting

-- 
~Vinod


Re: [Freedreno] [PATCH v3 12/13] drm/msm/dsi: Add support for DSC configuration

2022-03-23 Thread Vinod Koul
On 22-03-22, 19:59, Marijn Suijten wrote:
> On 2022-03-22 22:46:50, Vinod Koul wrote:
> > On 17-02-22, 16:11, Marijn Suijten wrote:
> > > Hi Vinod,
> > > 
> > > Thanks for taking time to go through this review, please find some
> > > clarifications below.
> > > 
> > > On 2022-02-17 16:44:04, Vinod Koul wrote:
> > > > Hi Marijn,
> > > > 
> > > > On 11-12-21, 01:03, Marijn Suijten wrote:
> > > > 
> > > > > > +static int dsi_dsc_update_pic_dim(struct msm_display_dsc_config 
> > > > > > *dsc,
> > > > > > + int pic_width, int pic_height)
> > > > > 
> > > > > This function - adopted from downstream - does not seem to perform a
> > > > > whole lot, especially without the modulo checks against the slice 
> > > > > size.
> > > > > Perhaps it can be inlined?
> > > > 
> > > > Most of the code here is :)
> > > > 
> > > > This was split from downstream code to check and update dimension. We
> > > > can inline this, or should we leave that to compiler. I am not a very
> > > > big fan of inlining...
> > > 
> > > It doesn't seem beneficial to code readability to have this function,
> > > which is only called just once and also has the same struct members read
> > > in a `DBG()` directly, abstracted away to a function.  Not really
> > > concerned about generated code/performance FWIW.
> > > 
> > > Also note that the caller isn't checking the `-EINVAL` result...
> > 
> > I have made this void inline.
> 
> Perhaps there is a misunderstanding here: with inlining I am referring
> to the process of transplanting the _function body_ to the only
> call-site, not adding the `inline` keyword nor changing this to `void`.
> 
> The checks that make this function return `-EINVAL` seem valid, so the
> caller should check it instead of removing the return?

Okay somehow I misunderstood then, let me see how the code looks in this
case then
-- 
~Vinod


Re: [Freedreno] [PATCH v3 12/13] drm/msm/dsi: Add support for DSC configuration

2022-03-22 Thread Vinod Koul
On 17-02-22, 16:11, Marijn Suijten wrote:
> Hi Vinod,
> 
> Thanks for taking time to go through this review, please find some
> clarifications below.
> 
> On 2022-02-17 16:44:04, Vinod Koul wrote:
> > Hi Marijn,
> > 
> > On 11-12-21, 01:03, Marijn Suijten wrote:
> > 
> > > > +static int dsi_dsc_update_pic_dim(struct msm_display_dsc_config *dsc,
> > > > + int pic_width, int pic_height)
> > > 
> > > This function - adopted from downstream - does not seem to perform a
> > > whole lot, especially without the modulo checks against the slice size.
> > > Perhaps it can be inlined?
> > 
> > Most of the code here is :)
> > 
> > This was split from downstream code to check and update dimension. We
> > can inline this, or should we leave that to compiler. I am not a very
> > big fan of inlining...
> 
> It doesn't seem beneficial to code readability to have this function,
> which is only called just once and also has the same struct members read
> in a `DBG()` directly, abstracted away to a function.  Not really
> concerned about generated code/performance FWIW.
> 
> Also note that the caller isn't checking the `-EINVAL` result...

I have made this void inline.

> > > 
> > > > +{
> > > > +   if (!dsc || !pic_width || !pic_height) {
> > > > +   pr_err("DSI: invalid input: pic_width: %d pic_height: 
> > > > %d\n", pic_width, pic_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_bonded_dsi)
> > > >  {
> > > > struct drm_display_mode *mode = msm_host->mode;
> > > > @@ -940,7 +954,68 @@ 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 */
> > > > +   dsi_dsc_update_pic_dim(dsc, mode->hdisplay, 
> > > > mode->vdisplay);
> 
> That is, the result code here should be checked (or function inlined).

This function return void, so no point in checking

> > > > +
> > > > +   /* 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
> > > > +*/
> > > 
> > > A more general nit on the comments in this patch series: it is
> > > appreciated if comments explain the rationale rather than - or in
> > > addition to - merely paraphrasing the code that follows.
> > 
> > Yes it might be the case here, but in this case I wanted to explicitly
> > point out hat we need to divide display by 3...
> 
> The main point here is justifying _why_ there's a division by 3 for the
> active portion of the signal, I presume that's the compression ratio
> (having not read into the DSC compression standard yet at all)?

I have updated this comment

> > > > +   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);
> > > 
> > > Shouldn't old values be masked out first, before writing new bits or
> > > values below?  The video-mode variant doesn't read back old register
> > > values.
> > 
> > This follows downstream where the registers are read, modified and
> > written back
> 
> Are you sure about this?  The register values are never cleared, meaning
> that only bits get added through the `|=` below but never unset - unless
> downstream clears these registers elsewhere before ending up in (their
> equivalent of) dsi_timing_setup.

I have modified video mode to write and not read now. For command mode
all bits are set to some value so no need to mask old values for that

> Thanks.  I forgot to mention: there seem to be a lot of similarities
> between the video and commandmode computations, can those possibly be
> factored out of the if-else to save on duplication and accidental
> mismatches like these?

Thanks, this was a good suggestion and am happy to report that I have
incorporated this and indeed code looks better

-- 
~Vinod


Re: [Freedreno] [PATCH v3 12/13] drm/msm/dsi: Add support for DSC configuration

2022-02-17 Thread Vinod Koul
Hi Marijn,

On 11-12-21, 01:03, Marijn Suijten wrote:

> > +static int dsi_dsc_update_pic_dim(struct msm_display_dsc_config *dsc,
> > + int pic_width, int pic_height)
> 
> This function - adopted from downstream - does not seem to perform a
> whole lot, especially without the modulo checks against the slice size.
> Perhaps it can be inlined?

Most of the code here is :)

This was split from downstream code to check and update dimension. We
can inline this, or should we leave that to compiler. I am not a very
big fan of inlining...

> 
> > +{
> > +   if (!dsc || !pic_width || !pic_height) {
> > +   pr_err("DSI: invalid input: pic_width: %d pic_height: %d\n", 
> > pic_width, pic_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_bonded_dsi)
> >  {
> > struct drm_display_mode *mode = msm_host->mode;
> > @@ -940,7 +954,68 @@ 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 */
> > +   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);
> 
> This seems to be pretty non-standard and perhaps unnecessary debug code,
> with a stray dash in there.  Is is needed here, and if so how about
> using %dx%d\n to format width and height?

I can update that, sure...

> 
> > +
> > +   /* 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
> > +*/
> 
> A more general nit on the comments in this patch series: it is
> appreciated if comments explain the rationale rather than - or in
> addition to - merely paraphrasing the code that follows.

Yes it might be the case here, but in this case I wanted to explicitly
point out hat we need to divide display by 3...

> 
> > +   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;
> > +   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);
> > +
> > +   dsc->drm->slice_count = 1;
> > +   dsc->bytes_in_slice = 
> > DIV_ROUND_UP(dsc->drm->slice_width * 8, 8);
> 
> If I am not mistaken this is the same value as dsc->drm->slice_width,
> since a multiple of 8 is inherently "a multiple of 8" and hence needs no
> rounding when divided by 8 again.

Yes this doesnt look right, I will update

> Also note that the cmdmode variant below uses bits_per_pixel here; is
> that discrepancy intended?

Nope both should use bits_per_pixel..

> > +   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;
> > +
> > +   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;
> 
> This was already calculated and assigned just a couple lines above.

Yup, dropped now.

> 
> > +   reg |= dsc->eol_byte_num << 4;
> > +   reg |= 1;
> 
> Note that the XML register file exists to map out the layout of these
> registers, including 

Re: [Freedreno] [REPOST PATCH v4 13/13] drm/msm/dsi: Add support for DSC configuration

2022-02-17 Thread Vinod Koul
Hi Marijn,

On 17-02-22, 10:27, Marijn Suijten wrote:
> Vinod,
> 
> On 2022-02-10 16:04:23, 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 
> > Signed-off-by: Vinod Koul 
> 
> I supplied a rather extensive - yet merely scratching the surface -
> review of this patch in:
> 
> 
> https://lore.kernel.org/linux-arm-msm/20211211000315.pavmcc7cc73il...@somainline.org/

Sorry somehow I seem to have overlooked this one.
> 
> It seems none of those points have been addressed, bar creating a mesa
> MR to update dsi.xml with a subpar description of the registers (offsets
> only).

Mesa MR was planned as we get more closer to having reviews.

> For every point that is intentionally ignored, please at least supply a
> justification of why you think this is the right thing to do.

Ofcourse, i will reply to these now and address as required.

-- 
~Vinod


Re: [Freedreno] [REPOST PATCH v4 13/13] drm/msm/dsi: Add support for DSC configuration

2022-02-16 Thread Vinod Koul
On 16-02-22, 19:44, Abhinav Kumar wrote:
> 
> 
> On 2/10/2022 2:34 AM, 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 
> > Signed-off-by: Vinod Koul 
> > ---
> >   drivers/gpu/drm/msm/dsi/dsi.xml.h  |  10 +++
> >   drivers/gpu/drm/msm/dsi/dsi_host.c | 109 -
> >   2 files changed, 118 insertions(+), 1 deletion(-)
> > 
> > diff --git a/drivers/gpu/drm/msm/dsi/dsi.xml.h 
> > b/drivers/gpu/drm/msm/dsi/dsi.xml.h
> > index 49b551ad1bff..c1c85df58c4b 100644
> > --- a/drivers/gpu/drm/msm/dsi/dsi.xml.h
> > +++ b/drivers/gpu/drm/msm/dsi/dsi.xml.h
> > @@ -706,4 +706,14 @@ static inline uint32_t DSI_VERSION_MAJOR(uint32_t val)
> >   #define REG_DSI_CPHY_MODE_CTRL
> > 0x02d4
> > +#define REG_DSI_VIDEO_COMPRESSION_MODE_CTRL
> > 0x029c
> > +
> > +#define REG_DSI_VIDEO_COMPRESSION_MODE_CTRL2   
> > 0x02a0
> > +
> > +#define REG_DSI_COMMAND_COMPRESSION_MODE_CTRL  
> > 0x02a4
> > +
> > +#define REG_DSI_COMMAND_COMPRESSION_MODE_CTRL2 
> > 0x02a8
> > +
> > +#define REG_DSI_COMMAND_COMPRESSION_MODE_CTRL3 
> > 0x02ac
> > +
> 
> This file should not be edited manually. The updates have to be generated
> using the headergen tool.

I have already send mesa patch for that. 
https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/14967#note_1253974
You should chime in there as well :)

I will split these and get these generated one as a separate patch..


> 
> >   #endif /* DSI_XML */
> > diff --git a/drivers/gpu/drm/msm/dsi/dsi_host.c 
> > b/drivers/gpu/drm/msm/dsi/dsi_host.c
> > index 438c80750682..3d8d5a1daaa3 100644
> > --- a/drivers/gpu/drm/msm/dsi/dsi_host.c
> > +++ b/drivers/gpu/drm/msm/dsi/dsi_host.c
> > @@ -908,6 +908,20 @@ 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 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;
> > +   }
> > +
> > +   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_bonded_dsi)
> >   {
> > struct drm_display_mode *mode = msm_host->mode;
> > @@ -940,7 +954,68 @@ 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 */
> > +   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;
> > +   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);
> > +
> > +   dsc->drm->slice_count = 1;
> 
> Why is this hard-coded to 1 here? Am i missing something?
> I think I need another day to look into these calculations.

Thanks for spotting this, it should be:
dsc->drm->slice_count = DIV_ROUND_UP(intf_width, 
dsc->drm->slice_widths);

which is slice_per_intf so I will update this

-- 
~Vinod


Re: [Freedreno] [REPOST PATCH v4 08/13] drm/msm/disp/dpu1: Don't use DSC with mode_3d

2022-02-16 Thread Vinod Koul
On 16-02-22, 19:11, Abhinav Kumar wrote:
> 
> 
> On 2/10/2022 2:34 AM, Vinod Koul wrote:
> > We cannot enable mode_3d when we are using the DSC. So pass
> > configuration to detect DSC is enabled and not enable mode_3d
> > when we are using DSC
> > 
> > We add a helper dpu_encoder_helper_get_dsc() to detect dsc
> > enabled and pass this to .setup_intf_cfg()
> > 
> > Signed-off-by: Vinod Koul 
> 
> We should not use 3D mux only when we use DSC merge topology.
> I agree that today we use only 2-2-1 topology for DSC which means its using
> DSC merge.
> 
> But generalizing that 3D mux should not be used for DSC is not right.
> 
> You can detect DSC merge by checking if there are two encoders and one
> interface in the topology and if so, you can disable 3D mux.

Right now with DSC we disable that as suggested by Dmitry last time.
Whenever we introduce merge we should revisit this, for now this should
suffice

-- 
~Vinod


Re: [Freedreno] [REPOST PATCH v4 07/13] drm/msm/disp/dpu1: Add support for DSC in encoder

2022-02-16 Thread Vinod Koul
On 16-02-22, 11:54, Abhinav Kumar wrote:

> > +/**
> > + * dpu_encoder_helper_get_dsc - get DSC blocks mask for the DPU encoder
> > + *   This helper function is used by physical encoder to get DSC blocks 
> > mask
> > + *   used for this encoder.
> 
> This looks slightly misaligned to me or not sure if its my mail client.
> Please check it once.

This looks fine in code as well as in mutt for me.. Maybe client issue

-- 
~Vinod


Re: [Freedreno] [REPOST PATCH v4 04/13] drm/msm/disp/dpu1: Add support for DSC in pingpong block

2022-02-16 Thread Vinod Koul
On 16-02-22, 11:49, Abhinav Kumar wrote:
> 
> 
> On 2/10/2022 2:34 AM, Vinod Koul wrote:
> > In SDM845, DSC can be enabled by writing to pingpong block registers, so
> > add support for DSC in hw_pp
> > 
> > Reviewed-by: Abhinav Kumar 
> 
> For the sake of uniformity, please use
> 
> Reviewed-by: Abhinav Kumar 

This one has been carry fwd from few versions back :) will update
everywhere...

-- 
~Vinod


Re: [Freedreno] [REPOST PATCH v4 03/13] drm/msm/disp/dpu1: Add support for DSC

2022-02-16 Thread Vinod Koul
On 16-02-22, 22:46, Dmitry Baryshkov wrote:
> On 16/02/2022 21:57, Abhinav Kumar wrote:
> > 
> > 
> > On 2/10/2022 2:34 AM, Vinod Koul wrote:
> > > Display Stream Compression (DSC) is one of the hw blocks in dpu, so add
> > > support by adding hw blocks for DSC
> > > 
> > > Reviewed-by: Dmitry Baryshkov 
> > > Signed-off-by: Vinod Koul 
> > 
> > Somehow second patch of this series is not showing up on patchwork in
> > your REPOST.
> > 
> > It jumps from 1 to 3.
> 
> patch 2: https://patchwork.freedesktop.org/patch/473356/?series=99959&rev=1

yeah it seems to be there.. As well os arm-msm and dri-devel on k.org
pwProblem with QC delivery...?
-- 
~Vinod


[Freedreno] [PATCH 2/3] drm/msm/dpu: Update the comment style

2022-02-10 Thread Vinod Koul
The multi line comment style is wrongly used as kernel-doc comment. This
gives a warning:

drivers/gpu/drm/msm/disp/dpu1/dpu_hw_interrupts.c:17:
warning: This comment starts with '/**', but isn't a kernel-doc comment.
Refer Documentation/doc-guide/kernel-doc.rst

Update the style to fix this.

Signed-off-by: Vinod Koul 
---
 drivers/gpu/drm/msm/disp/dpu1/dpu_hw_interrupts.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_interrupts.c 
b/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_interrupts.c
index a77a5eaa78ad..9341c88a336f 100644
--- a/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_interrupts.c
+++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_interrupts.c
@@ -13,7 +13,7 @@
 #include "dpu_hw_mdss.h"
 #include "dpu_trace.h"
 
-/**
+/*
  * Register offsets in MDSS register file for the interrupt registers
  * w.r.t. to the MDP base
  */
-- 
2.31.1



[Freedreno] [PATCH 3/3] drm/msm/dpu: Update function parameter documentation

2022-02-10 Thread Vinod Koul
dpu_core_irq_callback_handler() function comments seem to have become
stale and emit a warning:

drivers/gpu/drm/msm/disp/dpu1/dpu_hw_interrupts.c:147:
warning: Function parameter or member 'dpu_kms' not described in 
'dpu_core_irq_callback_handler'
drivers/gpu/drm/msm/disp/dpu1/dpu_hw_interrupts.c:147:
warning: Excess function parameter 'arg' description in 
'dpu_core_irq_callback_handler'

Fix by updating the documentation

Signed-off-by: Vinod Koul 
---
 drivers/gpu/drm/msm/disp/dpu1/dpu_hw_interrupts.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_interrupts.c 
b/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_interrupts.c
index 9341c88a336f..27073fd49fee 100644
--- a/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_interrupts.c
+++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_interrupts.c
@@ -140,7 +140,7 @@ static const struct dpu_intr_reg dpu_intr_set[] = {
 
 /**
  * dpu_core_irq_callback_handler - dispatch core interrupts
- * @arg:   private data of callback handler
+ * @dpu_kms:   Pointer to DPU's KMS structure
  * @irq_idx:   interrupt index
  */
 static void dpu_core_irq_callback_handler(struct dpu_kms *dpu_kms, int irq_idx)
-- 
2.31.1



[Freedreno] [PATCH 1/3] drm/msm/dpu: Remove set but unused variables

2022-02-10 Thread Vinod Koul
We get warning:

In function ‘dpu_encoder_virt_enable’: 
drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c:1145:33:
warning: variable ‘priv’ set but not used [-Wunused-but-set-variable]
 1145 | struct msm_drm_private *priv;

In function ‘dpu_encoder_virt_disable’: 
drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c:1182:33:
warning: variable ‘priv’ set but not used [-Wunused-but-set-variable]
 1182 | struct msm_drm_private *priv;

Remove these unused but set variables

Signed-off-by: Vinod Koul 
---
 drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c | 5 -
 1 file changed, 5 deletions(-)

diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c 
b/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c
index 1e648db439f9..132844801e92 100644
--- a/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c
+++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c
@@ -1142,14 +1142,12 @@ static void dpu_encoder_virt_enable(struct drm_encoder 
*drm_enc)
 {
struct dpu_encoder_virt *dpu_enc = NULL;
int ret = 0;
-   struct msm_drm_private *priv;
struct drm_display_mode *cur_mode = NULL;
 
dpu_enc = to_dpu_encoder_virt(drm_enc);
 
mutex_lock(&dpu_enc->enc_lock);
cur_mode = &dpu_enc->base.crtc->state->adjusted_mode;
-   priv = drm_enc->dev->dev_private;
 
trace_dpu_enc_enable(DRMID(drm_enc), cur_mode->hdisplay,
 cur_mode->vdisplay);
@@ -1179,7 +1177,6 @@ static void dpu_encoder_virt_enable(struct drm_encoder 
*drm_enc)
 static void dpu_encoder_virt_disable(struct drm_encoder *drm_enc)
 {
struct dpu_encoder_virt *dpu_enc = NULL;
-   struct msm_drm_private *priv;
int i = 0;
 
dpu_enc = to_dpu_encoder_virt(drm_enc);
@@ -1188,8 +1185,6 @@ static void dpu_encoder_virt_disable(struct drm_encoder 
*drm_enc)
mutex_lock(&dpu_enc->enc_lock);
dpu_enc->enabled = false;
 
-   priv = drm_enc->dev->dev_private;
-
trace_dpu_enc_disable(DRMID(drm_enc));
 
/* wait for idle */
-- 
2.31.1



[Freedreno] [REPOST PATCH v4 13/13] drm/msm/dsi: Add support for DSC configuration

2022-02-10 Thread Vinod Koul
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 
Signed-off-by: Vinod Koul 
---
 drivers/gpu/drm/msm/dsi/dsi.xml.h  |  10 +++
 drivers/gpu/drm/msm/dsi/dsi_host.c | 109 -
 2 files changed, 118 insertions(+), 1 deletion(-)

diff --git a/drivers/gpu/drm/msm/dsi/dsi.xml.h 
b/drivers/gpu/drm/msm/dsi/dsi.xml.h
index 49b551ad1bff..c1c85df58c4b 100644
--- a/drivers/gpu/drm/msm/dsi/dsi.xml.h
+++ b/drivers/gpu/drm/msm/dsi/dsi.xml.h
@@ -706,4 +706,14 @@ static inline uint32_t DSI_VERSION_MAJOR(uint32_t val)
 #define REG_DSI_CPHY_MODE_CTRL 0x02d4
 
 
+#define REG_DSI_VIDEO_COMPRESSION_MODE_CTRL0x029c
+
+#define REG_DSI_VIDEO_COMPRESSION_MODE_CTRL2   0x02a0
+
+#define REG_DSI_COMMAND_COMPRESSION_MODE_CTRL  0x02a4
+
+#define REG_DSI_COMMAND_COMPRESSION_MODE_CTRL2 0x02a8
+
+#define REG_DSI_COMMAND_COMPRESSION_MODE_CTRL3 0x02ac
+
 #endif /* DSI_XML */
diff --git a/drivers/gpu/drm/msm/dsi/dsi_host.c 
b/drivers/gpu/drm/msm/dsi/dsi_host.c
index 438c80750682..3d8d5a1daaa3 100644
--- a/drivers/gpu/drm/msm/dsi/dsi_host.c
+++ b/drivers/gpu/drm/msm/dsi/dsi_host.c
@@ -908,6 +908,20 @@ 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 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;
+   }
+
+   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_bonded_dsi)
 {
struct drm_display_mode *mode = msm_host->mode;
@@ -940,7 +954,68 @@ 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 */
+   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;
+   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);
+
+   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;
+
+   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;
+
+ 

  1   2   3   >