Re: [PATCH] drm/msm: Wire up tlb ops

2024-02-14 Thread Johan Hovold
On Tue, Feb 13, 2024 at 09:23:40AM -0800, Rob Clark wrote:
> From: Rob Clark 
> 
> The brute force iommu_flush_iotlb_all() was good enough for unmap, but
> in some cases a map operation could require removing a table pte entry
> to replace with a block entry.  This also requires tlb invalidation.
> Missing this was resulting an obscure iova fault on what should be a
> valid buffer address.
> 
> Thanks to Robin Murphy for helping me understand the cause of the fault.
> 
> Cc: Robin Murphy 
> Fixes: b145c6e65eb0 ("drm/msm: Add support to create a local pagetable")

Sounds like you're missing a

Cc: sta...@vger.kernel.org

here? Or is there some reason not to backport this fix (to 5.9 and later
kernels)?

> Signed-off-by: Rob Clark 

Johan


Re: [PATCH v2 2/4] dt-bindings: display/msm: Document the DPU for X1E80100

2024-02-14 Thread Rob Herring
On Wed, Feb 14, 2024 at 11:24:31PM +0200, Abel Vesa wrote:
> Document the DPU for Qualcomm X1E80100 platform in the SM8650 schema, as
> they are similar.
> 
> Signed-off-by: Abel Vesa 
> ---
>  Documentation/devicetree/bindings/display/msm/qcom,sm8650-dpu.yaml | 4 +++-
>  1 file changed, 3 insertions(+), 1 deletion(-)
> 
> diff --git 
> a/Documentation/devicetree/bindings/display/msm/qcom,sm8650-dpu.yaml 
> b/Documentation/devicetree/bindings/display/msm/qcom,sm8650-dpu.yaml
> index a01d15a03317..c4087cc5abbd 100644
> --- a/Documentation/devicetree/bindings/display/msm/qcom,sm8650-dpu.yaml
> +++ b/Documentation/devicetree/bindings/display/msm/qcom,sm8650-dpu.yaml
> @@ -13,7 +13,9 @@ $ref: /schemas/display/msm/dpu-common.yaml#
>  
>  properties:
>compatible:
> -const: qcom,sm8650-dpu
> +enum:
> +  - qcom,sm8650-dpu
> +  - qcom,x1e80100-dpu

Patch 1 uses this in the example, so this patch needs to come first.

>  
>reg:
>  items:
> 
> -- 
> 2.34.1
> 


Re: [PATCH v2 1/4] dt-bindings: display/msm: document MDSS on X1E80100

2024-02-14 Thread Rob Herring
On Wed, Feb 14, 2024 at 11:24:30PM +0200, Abel Vesa wrote:
> Document the MDSS hardware found on the Qualcomm X1E80100 platform.
> 
> Reviewed-by: Krzysztof Kozlowski 
> Signed-off-by: Abel Vesa 
> ---
>  .../bindings/display/msm/qcom,x1e80100-mdss.yaml   | 252 
> +
>  1 file changed, 252 insertions(+)
> 
> diff --git 
> a/Documentation/devicetree/bindings/display/msm/qcom,x1e80100-mdss.yaml 
> b/Documentation/devicetree/bindings/display/msm/qcom,x1e80100-mdss.yaml
> new file mode 100644
> index ..c3e38afab76e
> --- /dev/null
> +++ b/Documentation/devicetree/bindings/display/msm/qcom,x1e80100-mdss.yaml
> @@ -0,0 +1,252 @@
> +# SPDX-License-Identifier: GPL-2.0-only OR BSD-2-Clause
> +%YAML 1.2
> +---
> +$id: http://devicetree.org/schemas/display/msm/qcom,x1e80100-mdss.yaml#
> +$schema: http://devicetree.org/meta-schemas/core.yaml#
> +
> +title: Qualcomm X1E80100 Display MDSS
> +
> +maintainers:
> +  - Abel Vesa 
> +
> +description:
> +  X1E80100 MSM Mobile Display Subsystem(MDSS), which encapsulates sub-blocks 
> like
> +  DPU display controller, DP interfaces, etc.
> +
> +$ref: /schemas/display/msm/mdss-common.yaml#
> +
> +properties:
> +  compatible:
> +const: qcom,x1e80100-mdss
> +
> +  clocks:
> +items:
> +  - description: Display AHB
> +  - description: Display hf AXI
> +  - description: Display core
> +
> +  iommus:
> +maxItems: 1
> +
> +  interconnects:
> +maxItems: 3
> +
> +  interconnect-names:
> +maxItems: 3
> +
> +patternProperties:
> +  "^display-controller@[0-9a-f]+$":
> +type: object

   additionalProperties: true

> +properties:
> +  compatible:
> +const: qcom,x1e80100-dpu
> +
> +  "^displayport-controller@[0-9a-f]+$":
> +type: object

   additionalProperties: true

> +properties:
> +  compatible:
> +const: qcom,x1e80100-dp
> +
> +  "^phy@[0-9a-f]+$":
> +type: object

   additionalProperties: true

> +properties:
> +  compatible:
> +const: qcom,x1e80100-dp-phy
> +
> +required:
> +  - compatible
> +
> +unevaluatedProperties: false
> +
> +examples:
> +  - |
> +#include 
> +#include 
> +#include 
> +#include 
> +#include 
> +#include 
> +#include 
> +
> +display-subsystem@ae0 {
> +compatible = "qcom,x1e80100-mdss";
> +reg = <0x0ae0 0x1000>;
> +reg-names = "mdss";
> +
> +interconnects = <_noc MASTER_MDP 0 _noc SLAVE_LLCC 0>,
> +<_virt MASTER_LLCC 0 _virt SLAVE_EBI1 0>,
> +<_noc MASTER_APPSS_PROC 0 _noc 
> SLAVE_DISPLAY_CFG 0>;
> +interconnect-names = "mdp0-mem", "mdp1-mem", "cpu-cfg";
> +
> +resets = <_core_bcr>;
> +
> +power-domains = <_gdsc>;
> +
> +clocks = < DISP_CC_MDSS_AHB_CLK>,
> + < GCC_DISP_HF_AXI_CLK>,
> + < DISP_CC_MDSS_MDP_CLK>;
> +clock-names = "bus", "nrt_bus", "core";
> +
> +interrupts = ;
> +interrupt-controller;
> +#interrupt-cells = <1>;
> +
> +iommus = <_smmu 0x1c00 0x2>;
> +
> +#address-cells = <1>;
> +#size-cells = <1>;
> +ranges;
> +
> +display-controller@ae01000 {
> +compatible = "qcom,x1e80100-dpu";
> +reg = <0x0ae01000 0x8f000>,
> +  <0x0aeb 0x2008>;
> +reg-names = "mdp", "vbif";
> +
> +clocks = <_axi_clk>,
> + <_ahb_clk>,
> + <_mdp_lut_clk>,
> + <_mdp_clk>,
> + <_mdp_vsync_clk>;
> +clock-names = "nrt_bus",
> +  "iface",
> +  "lut",
> +  "core",
> +  "vsync";
> +
> +assigned-clocks = <_mdp_vsync_clk>;
> +assigned-clock-rates = <1920>;
> +
> +operating-points-v2 = <_opp_table>;
> +power-domains = < RPMHPD_MMCX>;
> +
> +interrupt-parent = <>;
> +interrupts = <0>;
> +
> +ports {
> +#address-cells = <1>;
> +#size-cells = <0>;
> +
> +port@0 {
> +reg = <0>;
> +dpu_intf1_out: endpoint {
> +remote-endpoint = <_in>;
> +};
> +};
> +
> +port@1 {
> +reg = <1>;
> +dpu_intf2_out: endpoint {
> +remote-endpoint = <_in>;
> +};
> +};
> +};
> +
> +mdp_opp_table: opp-table {
> +compatible = "operating-points-v2";
> +
> +opp-2 {
> +opp-hz = /bits/ 64 <2>;
> +required-opps = <_opp_low_svs>;
> +};
> +
> +opp-32500 {
> +opp-hz = /bits/ 64 

Re: [PATCH v2 1/4] dt-bindings: display/msm: document MDSS on X1E80100

2024-02-14 Thread Rob Herring


On Wed, 14 Feb 2024 23:24:30 +0200, Abel Vesa wrote:
> Document the MDSS hardware found on the Qualcomm X1E80100 platform.
> 
> Reviewed-by: Krzysztof Kozlowski 
> Signed-off-by: Abel Vesa 
> ---
>  .../bindings/display/msm/qcom,x1e80100-mdss.yaml   | 252 
> +
>  1 file changed, 252 insertions(+)
> 

My bot found errors running 'make DT_CHECKER_FLAGS=-m dt_binding_check'
on your patch (DT_CHECKER_FLAGS is new in v5.13):

yamllint warnings/errors:

dtschema/dtc warnings/errors:
Documentation/devicetree/bindings/display/msm/qcom,x1e80100-mdss.example.dts:24:18:
 fatal error: dt-bindings/clock/qcom,x1e80100-dispcc.h: No such file or 
directory
   24 | #include 
  |  ^~
compilation terminated.
make[2]: *** [scripts/Makefile.lib:419: 
Documentation/devicetree/bindings/display/msm/qcom,x1e80100-mdss.example.dtb] 
Error 1
make[2]: *** Waiting for unfinished jobs
make[1]: *** [/builds/robherring/dt-review-ci/linux/Makefile:1428: 
dt_binding_check] Error 2
make: *** [Makefile:240: __sub-make] Error 2

doc reference errors (make refcheckdocs):

See 
https://patchwork.ozlabs.org/project/devicetree-bindings/patch/20240214-x1e80100-display-v2-1-cf05ba887...@linaro.org

The base for the series is generally the latest rc1. A different dependency
should be noted in *this* patch.

If you already ran 'make dt_binding_check' and didn't see the above
error(s), then make sure 'yamllint' is installed and dt-schema is up to
date:

pip3 install dtschema --upgrade

Please check and re-submit after running the above command yourself. Note
that DT_SCHEMA_FILES can be set to your schema file to speed up checking
your schema. However, it must be unset to test all examples with your schema.



Re: [PATCH v2 2/4] dt-bindings: display/msm: Document the DPU for X1E80100

2024-02-14 Thread Rob Herring


On Wed, 14 Feb 2024 23:24:31 +0200, Abel Vesa wrote:
> Document the DPU for Qualcomm X1E80100 platform in the SM8650 schema, as
> they are similar.
> 
> Signed-off-by: Abel Vesa 
> ---
>  Documentation/devicetree/bindings/display/msm/qcom,sm8650-dpu.yaml | 4 +++-
>  1 file changed, 3 insertions(+), 1 deletion(-)
> 

My bot found errors running 'make DT_CHECKER_FLAGS=-m dt_binding_check'
on your patch (DT_CHECKER_FLAGS is new in v5.13):

yamllint warnings/errors:

dtschema/dtc warnings/errors:


doc reference errors (make refcheckdocs):

See 
https://patchwork.ozlabs.org/project/devicetree-bindings/patch/20240214-x1e80100-display-v2-2-cf05ba887...@linaro.org

The base for the series is generally the latest rc1. A different dependency
should be noted in *this* patch.

If you already ran 'make dt_binding_check' and didn't see the above
error(s), then make sure 'yamllint' is installed and dt-schema is up to
date:

pip3 install dtschema --upgrade

Please check and re-submit after running the above command yourself. Note
that DT_SCHEMA_FILES can be set to your schema file to speed up checking
your schema. However, it must be unset to test all examples with your schema.



Re: [PATCH 3/5] drm: msm: add support for A750 GPU

2024-02-14 Thread Konrad Dybcio
On 12.02.2024 15:45, Neil Armstrong wrote:
> On 12/02/2024 11:46, Konrad Dybcio wrote:
>> On 12.02.2024 11:37, Neil Armstrong wrote:
>>> Add support for the A750 GPU found on the SM8650 platform
>>>
>>> Unlike the the very close A740 GPU on the SM8550 SoC, the A750 GPU
>>> doesn't have an HWCFG block but a separate register set.
>>>
>>> The missing registers are added in the a6xx.xml.h file that would
>>> require a subsequent sync and the non-existent hwcfg is handled
>>> in a6xx_set_hwcg().
>>
>> These should also be submitted to mesa to make sure the next header sync
>> doesn't wipe them
> 
> Ack submitting them right now: 
> https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/27576

Thanks

> 
>>
>> [...]
>>
>>> --- a/drivers/gpu/drm/msm/adreno/a6xx_gpu.c
>>> +++ b/drivers/gpu/drm/msm/adreno/a6xx_gpu.c
>>> @@ -958,10 +958,11 @@ static void a6xx_set_hwcg(struct msm_gpu *gpu, bool 
>>> state)
>>>   struct a6xx_gpu *a6xx_gpu = to_a6xx_gpu(adreno_gpu);
>>>   struct a6xx_gmu *gmu = _gpu->gmu;
>>>   const struct adreno_reglist *reg;
>>> +    bool skip_programming = !(adreno_gpu->info->hwcg || 
>>> adreno_is_a7xx(adreno_gpu));
>>
>> is_a750?
> 
> OK right, I was thinking of the next gpu which will probably also miss an 
> hwcfg
> 
>>
>>>   unsigned int i;
>>>   u32 val, clock_cntl_on, cgc_mode;
>>>   -    if (!adreno_gpu->info->hwcg)
>>> +    if (skip_programming)
>>>   return;
>>>     if (adreno_is_a630(adreno_gpu))
>>> @@ -982,6 +983,25 @@ static void a6xx_set_hwcg(struct msm_gpu *gpu, bool 
>>> state)
>>>     state ? 0x : 0);
>>>   }
>>>   +    if (!adreno_gpu->info->hwcg) {
>>
>> I don't think this block of code is reachable now, no?
> 
> It is because we didn't skip when adreno_is_a7xx(adreno_gpu)

Ahh I misread the brackets within the assignment

> 
>>
>> Maybe remove the skip_programming and if_a750 here?
> This would require:
>>> -    if (!adreno_gpu->info->hwcg || )
>>> +    if (!(adreno_gpu->info->hwcg || adreno_is_a750(adreno_gpu)))
> 
> and:
> 
>>> +    if (adreno_is_a750(adreno_gpu)) {
> 
> But if the next gpu also doesn't have an hwcfg, we will need to use
> the current design...
> 
> I just tried with:
> ><===
> @@ -961,7 +961,7 @@ static void a6xx_set_hwcg(struct msm_gpu *gpu, bool state)
>     unsigned int i;
>     u32 val, clock_cntl_on, cgc_mode;
> 
> -   if (!adreno_gpu->info->hwcg)
> +   if (!(adreno_gpu->info->hwcg || adreno_is_a750(adreno_gpu)))
>     return;
> 
>     if (adreno_is_a630(adreno_gpu))
> @@ -982,6 +982,25 @@ static void a6xx_set_hwcg(struct msm_gpu *gpu, bool 
> state)
>   state ? 0x : 0);
>     }
> 
> +   if (adreno_is_a750(adreno_gpu)) {
> +   gpu_write(gpu, REG_A7XX_RBBM_CLOCK_CNTL_GLOBAL, 1);
> +   gpu_write(gpu, REG_A7XX_RBBM_CGC_GLOBAL_LOAD_CMD, state ? 1 : 
> 0);
> +
> +   if (state) {
> +   gpu_write(gpu, REG_A7XX_RBBM_CGC_P2S_TRIG_CMD, 1);
> +
> +   if (gpu_poll_timeout(gpu, 
> REG_A7XX_RBBM_CGC_P2S_STATUS, val,
> +    val & 
> A7XX_RBBM_CGC_P2S_STATUS_TXDONE, 1, 10)) {
> +   dev_err(>pdev->dev, "RBBM_CGC_P2S_STATUS 
> TXDONE Poll failed\n");
> +   return;
> +   }
> +
> +   gpu_write(gpu, REG_A7XX_RBBM_CLOCK_CNTL_GLOBAL, 0);
> +   }
> +
> +   return;
> +   }
> +
>     val = gpu_read(gpu, REG_A6XX_RBBM_CLOCK_CNTL);
> 
>     /* Don't re-program the registers if they are already correct */
> ><===
> 
> And it works fine, does it work it for you ?

Let's keep it as-is in the original submission, as I've mentioned, I had
misread the code

Konrad

> 
>>
>>> +    gpu_write(gpu, REG_A7XX_RBBM_CLOCK_CNTL_GLOBAL, 1);
>>> +    gpu_write(gpu, REG_A7XX_RBBM_CGC_GLOBAL_LOAD_CMD, state ? 1 : 0);
>>> +
>>> +    if (state) {
>>> +    gpu_write(gpu, REG_A7XX_RBBM_CGC_P2S_TRIG_CMD, 1);
>>> +
>>> +    if (gpu_poll_timeout(gpu, REG_A7XX_RBBM_CGC_P2S_STATUS, val,
>>> + val & BIT(0), 1, 10)) {
>>
>> We should define that bit name (the err suggests it's
>> REG_A7XX_RBBM_GCC_P2S_STATUS_TXDONE or so)
>>
>> [...]
>>
>>> +static inline int adreno_is_a750(struct adreno_gpu *gpu)
>>> +{
>>> +    return gpu->info->chip_ids[0] == 0x43051401;
>>> +}
>>> +
>>>   /* Placeholder to make future diffs smaller */
>>
>> Please also remove this comment now that it's invalid
> 
> Ack
> 
>>
>> Konrad
> 
> Thanks,
> Neil
> 


[PATCH v2 4/4] drm/msm/dpu: Add X1E80100 support

2024-02-14 Thread Abel Vesa
Add definitions for the display hardware used on the Qualcomm X1E80100
platform.

Co-developed-by: Abhinav Kumar 
Signed-off-by: Abhinav Kumar 
Reviewed-by: Dmitry Baryshkov 
Signed-off-by: Abel Vesa 
---
 .../drm/msm/disp/dpu1/catalog/dpu_9_2_x1e80100.h   | 449 +
 drivers/gpu/drm/msm/disp/dpu1/dpu_hw_catalog.c |   2 +
 drivers/gpu/drm/msm/disp/dpu1/dpu_hw_catalog.h |   1 +
 drivers/gpu/drm/msm/disp/dpu1/dpu_kms.c|   1 +
 4 files changed, 453 insertions(+)

diff --git a/drivers/gpu/drm/msm/disp/dpu1/catalog/dpu_9_2_x1e80100.h 
b/drivers/gpu/drm/msm/disp/dpu1/catalog/dpu_9_2_x1e80100.h
new file mode 100644
index ..9a9f7092c526
--- /dev/null
+++ b/drivers/gpu/drm/msm/disp/dpu1/catalog/dpu_9_2_x1e80100.h
@@ -0,0 +1,449 @@
+/* SPDX-License-Identifier: GPL-2.0-only */
+/*
+ * Copyright (c) 2023, Linaro Limited
+ */
+
+#ifndef _DPU_9_2_X1E80100_H
+#define _DPU_9_2_X1E80100_H
+
+static const struct dpu_caps x1e80100_dpu_caps = {
+   .max_mixer_width = DEFAULT_DPU_OUTPUT_LINE_WIDTH,
+   .max_mixer_blendstages = 0xb,
+   .has_src_split = true,
+   .has_dim_layer = true,
+   .has_idle_pc = true,
+   .has_3d_merge = true,
+   .max_linewidth = 5120,
+   .pixel_ram_size = DEFAULT_PIXEL_RAM_SIZE,
+};
+
+static const struct dpu_mdp_cfg x1e80100_mdp = {
+   .name = "top_0",
+   .base = 0, .len = 0x494,
+   .features = BIT(DPU_MDP_PERIPH_0_REMOVED),
+   .clk_ctrls = {
+   [DPU_CLK_CTRL_REG_DMA] = { .reg_off = 0x2bc, .bit_off = 20 },
+   },
+};
+
+/* FIXME: get rid of DPU_CTL_SPLIT_DISPLAY in favour of proper ACTIVE_CTL 
support */
+static const struct dpu_ctl_cfg x1e80100_ctl[] = {
+   {
+   .name = "ctl_0", .id = CTL_0,
+   .base = 0x15000, .len = 0x290,
+   .features = CTL_SM8550_MASK | BIT(DPU_CTL_SPLIT_DISPLAY),
+   .intr_start = DPU_IRQ_IDX(MDP_SSPP_TOP0_INTR2, 9),
+   }, {
+   .name = "ctl_1", .id = CTL_1,
+   .base = 0x16000, .len = 0x290,
+   .features = CTL_SM8550_MASK | BIT(DPU_CTL_SPLIT_DISPLAY),
+   .intr_start = DPU_IRQ_IDX(MDP_SSPP_TOP0_INTR2, 10),
+   }, {
+   .name = "ctl_2", .id = CTL_2,
+   .base = 0x17000, .len = 0x290,
+   .features = CTL_SM8550_MASK,
+   .intr_start = DPU_IRQ_IDX(MDP_SSPP_TOP0_INTR2, 11),
+   }, {
+   .name = "ctl_3", .id = CTL_3,
+   .base = 0x18000, .len = 0x290,
+   .features = CTL_SM8550_MASK,
+   .intr_start = DPU_IRQ_IDX(MDP_SSPP_TOP0_INTR2, 12),
+   }, {
+   .name = "ctl_4", .id = CTL_4,
+   .base = 0x19000, .len = 0x290,
+   .features = CTL_SM8550_MASK,
+   .intr_start = DPU_IRQ_IDX(MDP_SSPP_TOP0_INTR2, 13),
+   }, {
+   .name = "ctl_5", .id = CTL_5,
+   .base = 0x1a000, .len = 0x290,
+   .features = CTL_SM8550_MASK,
+   .intr_start = DPU_IRQ_IDX(MDP_SSPP_TOP0_INTR2, 23),
+   },
+};
+
+static const struct dpu_sspp_cfg x1e80100_sspp[] = {
+   {
+   .name = "sspp_0", .id = SSPP_VIG0,
+   .base = 0x4000, .len = 0x344,
+   .features = VIG_SDM845_MASK_SDMA,
+   .sblk = _vig_sblk_qseed3_3_3,
+   .xin_id = 0,
+   .type = SSPP_TYPE_VIG,
+   }, {
+   .name = "sspp_1", .id = SSPP_VIG1,
+   .base = 0x6000, .len = 0x344,
+   .features = VIG_SDM845_MASK_SDMA,
+   .sblk = _vig_sblk_qseed3_3_3,
+   .xin_id = 4,
+   .type = SSPP_TYPE_VIG,
+   }, {
+   .name = "sspp_2", .id = SSPP_VIG2,
+   .base = 0x8000, .len = 0x344,
+   .features = VIG_SDM845_MASK_SDMA,
+   .sblk = _vig_sblk_qseed3_3_3,
+   .xin_id = 8,
+   .type = SSPP_TYPE_VIG,
+   }, {
+   .name = "sspp_3", .id = SSPP_VIG3,
+   .base = 0xa000, .len = 0x344,
+   .features = VIG_SDM845_MASK_SDMA,
+   .sblk = _vig_sblk_qseed3_3_3,
+   .xin_id = 12,
+   .type = SSPP_TYPE_VIG,
+   }, {
+   .name = "sspp_8", .id = SSPP_DMA0,
+   .base = 0x24000, .len = 0x344,
+   .features = DMA_SDM845_MASK_SDMA,
+   .sblk = _dma_sblk,
+   .xin_id = 1,
+   .type = SSPP_TYPE_DMA,
+   }, {
+   .name = "sspp_9", .id = SSPP_DMA1,
+   .base = 0x26000, .len = 0x344,
+   .features = DMA_SDM845_MASK_SDMA,
+   .sblk = _dma_sblk,
+   .xin_id = 5,
+   .type = SSPP_TYPE_DMA,
+   }, {
+   .name = "sspp_10", .id = SSPP_DMA2,
+   .base = 0x28000, .len = 0x344,
+   .features = DMA_SDM845_MASK_SDMA,
+   .sblk = _dma_sblk,
+   .xin_id = 9,
+   

[PATCH v2 3/4] drm/msm: mdss: Add X1E80100 support

2024-02-14 Thread Abel Vesa
Add support for MDSS on X1E80100.

Signed-off-by: Abel Vesa 
---
 drivers/gpu/drm/msm/msm_mdss.c | 13 +
 1 file changed, 13 insertions(+)

diff --git a/drivers/gpu/drm/msm/msm_mdss.c b/drivers/gpu/drm/msm/msm_mdss.c
index 35423d10aafa..6eda501e2a1a 100644
--- a/drivers/gpu/drm/msm/msm_mdss.c
+++ b/drivers/gpu/drm/msm/msm_mdss.c
@@ -636,6 +636,18 @@ static const struct msm_mdss_data sm8550_data = {
.macrotile_mode = 1,
.reg_bus_bw = 57000,
 };
+
+static const struct msm_mdss_data x1e80100_data = {
+   .ubwc_enc_version = UBWC_4_0,
+   .ubwc_dec_version = UBWC_4_3,
+   .ubwc_swizzle = 6,
+   .ubwc_static = 1,
+   /* TODO: highest_bank_bit = 2 for LP_DDR4 */
+   .highest_bank_bit = 3,
+   .macrotile_mode = 1,
+   /* TODO: Add reg_bus_bw with real value */
+};
+
 static const struct of_device_id mdss_dt_match[] = {
{ .compatible = "qcom,mdss" },
{ .compatible = "qcom,msm8998-mdss", .data = _data },
@@ -656,6 +668,7 @@ static const struct of_device_id mdss_dt_match[] = {
{ .compatible = "qcom,sm8450-mdss", .data = _data },
{ .compatible = "qcom,sm8550-mdss", .data = _data },
{ .compatible = "qcom,sm8650-mdss", .data = _data},
+   { .compatible = "qcom,x1e80100-mdss", .data = _data},
{}
 };
 MODULE_DEVICE_TABLE(of, mdss_dt_match);

-- 
2.34.1



[PATCH v2 1/4] dt-bindings: display/msm: document MDSS on X1E80100

2024-02-14 Thread Abel Vesa
Document the MDSS hardware found on the Qualcomm X1E80100 platform.

Reviewed-by: Krzysztof Kozlowski 
Signed-off-by: Abel Vesa 
---
 .../bindings/display/msm/qcom,x1e80100-mdss.yaml   | 252 +
 1 file changed, 252 insertions(+)

diff --git 
a/Documentation/devicetree/bindings/display/msm/qcom,x1e80100-mdss.yaml 
b/Documentation/devicetree/bindings/display/msm/qcom,x1e80100-mdss.yaml
new file mode 100644
index ..c3e38afab76e
--- /dev/null
+++ b/Documentation/devicetree/bindings/display/msm/qcom,x1e80100-mdss.yaml
@@ -0,0 +1,252 @@
+# SPDX-License-Identifier: GPL-2.0-only OR BSD-2-Clause
+%YAML 1.2
+---
+$id: http://devicetree.org/schemas/display/msm/qcom,x1e80100-mdss.yaml#
+$schema: http://devicetree.org/meta-schemas/core.yaml#
+
+title: Qualcomm X1E80100 Display MDSS
+
+maintainers:
+  - Abel Vesa 
+
+description:
+  X1E80100 MSM Mobile Display Subsystem(MDSS), which encapsulates sub-blocks 
like
+  DPU display controller, DP interfaces, etc.
+
+$ref: /schemas/display/msm/mdss-common.yaml#
+
+properties:
+  compatible:
+const: qcom,x1e80100-mdss
+
+  clocks:
+items:
+  - description: Display AHB
+  - description: Display hf AXI
+  - description: Display core
+
+  iommus:
+maxItems: 1
+
+  interconnects:
+maxItems: 3
+
+  interconnect-names:
+maxItems: 3
+
+patternProperties:
+  "^display-controller@[0-9a-f]+$":
+type: object
+properties:
+  compatible:
+const: qcom,x1e80100-dpu
+
+  "^displayport-controller@[0-9a-f]+$":
+type: object
+properties:
+  compatible:
+const: qcom,x1e80100-dp
+
+  "^phy@[0-9a-f]+$":
+type: object
+properties:
+  compatible:
+const: qcom,x1e80100-dp-phy
+
+required:
+  - compatible
+
+unevaluatedProperties: false
+
+examples:
+  - |
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+
+display-subsystem@ae0 {
+compatible = "qcom,x1e80100-mdss";
+reg = <0x0ae0 0x1000>;
+reg-names = "mdss";
+
+interconnects = <_noc MASTER_MDP 0 _noc SLAVE_LLCC 0>,
+<_virt MASTER_LLCC 0 _virt SLAVE_EBI1 0>,
+<_noc MASTER_APPSS_PROC 0 _noc 
SLAVE_DISPLAY_CFG 0>;
+interconnect-names = "mdp0-mem", "mdp1-mem", "cpu-cfg";
+
+resets = <_core_bcr>;
+
+power-domains = <_gdsc>;
+
+clocks = < DISP_CC_MDSS_AHB_CLK>,
+ < GCC_DISP_HF_AXI_CLK>,
+ < DISP_CC_MDSS_MDP_CLK>;
+clock-names = "bus", "nrt_bus", "core";
+
+interrupts = ;
+interrupt-controller;
+#interrupt-cells = <1>;
+
+iommus = <_smmu 0x1c00 0x2>;
+
+#address-cells = <1>;
+#size-cells = <1>;
+ranges;
+
+display-controller@ae01000 {
+compatible = "qcom,x1e80100-dpu";
+reg = <0x0ae01000 0x8f000>,
+  <0x0aeb 0x2008>;
+reg-names = "mdp", "vbif";
+
+clocks = <_axi_clk>,
+ <_ahb_clk>,
+ <_mdp_lut_clk>,
+ <_mdp_clk>,
+ <_mdp_vsync_clk>;
+clock-names = "nrt_bus",
+  "iface",
+  "lut",
+  "core",
+  "vsync";
+
+assigned-clocks = <_mdp_vsync_clk>;
+assigned-clock-rates = <1920>;
+
+operating-points-v2 = <_opp_table>;
+power-domains = < RPMHPD_MMCX>;
+
+interrupt-parent = <>;
+interrupts = <0>;
+
+ports {
+#address-cells = <1>;
+#size-cells = <0>;
+
+port@0 {
+reg = <0>;
+dpu_intf1_out: endpoint {
+remote-endpoint = <_in>;
+};
+};
+
+port@1 {
+reg = <1>;
+dpu_intf2_out: endpoint {
+remote-endpoint = <_in>;
+};
+};
+};
+
+mdp_opp_table: opp-table {
+compatible = "operating-points-v2";
+
+opp-2 {
+opp-hz = /bits/ 64 <2>;
+required-opps = <_opp_low_svs>;
+};
+
+opp-32500 {
+opp-hz = /bits/ 64 <32500>;
+required-opps = <_opp_svs>;
+};
+
+opp-37500 {
+opp-hz = /bits/ 64 <37500>;
+required-opps = <_opp_svs_l1>;
+};
+
+opp-51400 {
+opp-hz = /bits/ 64 <51400>;
+required-opps = <_opp_nom>;
+};
+};
+};
+
+displayport-controller@ae9 {
+compatible = "qcom,x1e80100-dp";
+   

[PATCH v2 0/4] drm/msm: Add display support for X1E80100

2024-02-14 Thread Abel Vesa
This patchset adds support for display for X1E80100.
The support for embedded DisplayPort on this platform will not
be enabled using the connetor type from driver match data,
but through some 'is-edp' property via DT. This subsequent work
will be part of a separate patchset.

Signed-off-by: Abel Vesa 
---
Changes in v2:
- Dropped the 4th patch:
  "drm/msm/dp: Try looking for link-frequencies into the port@0's endpoint 
first"
- Fixed the qcom,x1e80100-mdss schema by including some missing headers
  in the example
- Added TODO comment for reg_bus_bw
- Switched to SDMA features mask
- Added Krzysztof's R-b tag to mdss schema patch
- Added Dmitry's R-b tag to the dpu patch
- Link to v1: 
https://lore.kernel.org/r/20240129-x1e80100-display-v1-0-0d9eb8254...@linaro.org

---
Abel Vesa (4):
  dt-bindings: display/msm: document MDSS on X1E80100
  dt-bindings: display/msm: Document the DPU for X1E80100
  drm/msm: mdss: Add X1E80100 support
  drm/msm/dpu: Add X1E80100 support

 .../bindings/display/msm/qcom,sm8650-dpu.yaml  |   4 +-
 .../bindings/display/msm/qcom,x1e80100-mdss.yaml   | 252 
 .../drm/msm/disp/dpu1/catalog/dpu_9_2_x1e80100.h   | 449 +
 drivers/gpu/drm/msm/disp/dpu1/dpu_hw_catalog.c |   2 +
 drivers/gpu/drm/msm/disp/dpu1/dpu_hw_catalog.h |   1 +
 drivers/gpu/drm/msm/disp/dpu1/dpu_kms.c|   1 +
 drivers/gpu/drm/msm/msm_mdss.c |  13 +
 7 files changed, 721 insertions(+), 1 deletion(-)
---
base-commit: 85a96a047f413da4b663919a4ced39a4715c6835
change-id: 20231201-x1e80100-display-a46324400baf

Best regards,
-- 
Abel Vesa 



[PATCH v2 2/4] dt-bindings: display/msm: Document the DPU for X1E80100

2024-02-14 Thread Abel Vesa
Document the DPU for Qualcomm X1E80100 platform in the SM8650 schema, as
they are similar.

Signed-off-by: Abel Vesa 
---
 Documentation/devicetree/bindings/display/msm/qcom,sm8650-dpu.yaml | 4 +++-
 1 file changed, 3 insertions(+), 1 deletion(-)

diff --git a/Documentation/devicetree/bindings/display/msm/qcom,sm8650-dpu.yaml 
b/Documentation/devicetree/bindings/display/msm/qcom,sm8650-dpu.yaml
index a01d15a03317..c4087cc5abbd 100644
--- a/Documentation/devicetree/bindings/display/msm/qcom,sm8650-dpu.yaml
+++ b/Documentation/devicetree/bindings/display/msm/qcom,sm8650-dpu.yaml
@@ -13,7 +13,9 @@ $ref: /schemas/display/msm/dpu-common.yaml#
 
 properties:
   compatible:
-const: qcom,sm8650-dpu
+enum:
+  - qcom,sm8650-dpu
+  - qcom,x1e80100-dpu
 
   reg:
 items:

-- 
2.34.1



Re: [PATCH v2] drm/msm/dpu: make "vblank timeout" more useful

2024-02-14 Thread Abhinav Kumar




On 2/14/2024 11:20 AM, Dmitry Baryshkov wrote:

On Wed, 14 Feb 2024 at 20:02, Abhinav Kumar  wrote:




On 2/8/2024 6:50 AM, Dmitry Baryshkov wrote:

We have several reports of vblank timeout messages. However after some
debugging it was found that there might be different causes to that.
To allow us to identify the DPU block that gets stuck, include the
actual CTL_FLUSH value into the timeout message and trigger the devcore
snapshot capture.

Signed-off-by: Dmitry Baryshkov 
---
Changes in v2:
- Added a call to msm_disp_snapshot_state() to trigger devcore dump
(Abhinav)
- Link to v1: 
https://lore.kernel.org/r/20240106-fd-dpu-debug-timeout-v1-1-6d9762884...@linaro.org
---
   drivers/gpu/drm/msm/disp/dpu1/dpu_encoder_phys_vid.c | 3 ++-
   1 file changed, 2 insertions(+), 1 deletion(-)

diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder_phys_vid.c 
b/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder_phys_vid.c
index d0f56c5c4cce..a8d6165b3c0a 100644
--- a/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder_phys_vid.c
+++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder_phys_vid.c
@@ -489,7 +489,8 @@ static int dpu_encoder_phys_vid_wait_for_commit_done(
   (hw_ctl->ops.get_flush_register(hw_ctl) == 0),
   msecs_to_jiffies(50));
   if (ret <= 0) {
- DPU_ERROR("vblank timeout\n");
+ DPU_ERROR("vblank timeout: %x\n", 
hw_ctl->ops.get_flush_register(hw_ctl));
+ msm_disp_snapshot_state(phys_enc->parent->dev);



There is no rate limiting in this piece of code unfortunately. So this
will flood the number of snapshots.


Well... Yes and no. The devcoredump will destroy other snapshots if
there is a pending one. So only the console will be flooded and only
in case when MSM_DISP_SNAPSHOT_DUMP_IN_CONSOLE is enabled.



Yes, true but at the same time this makes it hard to capture a good dump 
as potentially every vblank you could timeout so this destroy/create 
cycle wont end.




Short-term solution is you can go with a vblank_timeout_cnt and reset it
in the enable() like other similar error counters.

long-term solution is we need to centralize these error locations to one
single dpu_encoder_error_handler() with a single counter and the error
handler will print out the error code along with the snapshot instead of
the snapshot being called from all over the place.




   return -ETIMEDOUT;
   }


---
base-commit: 39676dfe52331dba909c617f213fdb21015c8d10
change-id: 20240106-fd-dpu-debug-timeout-e917f0bc8063

Best regards,






Re: [PATCH v3 13/19] drm/msm/dp: add VSC SDP support for YUV420 over DP

2024-02-14 Thread Abhinav Kumar




On 2/14/2024 11:39 AM, Dmitry Baryshkov wrote:

On Wed, 14 Feb 2024 at 20:04, Paloma Arellano  wrote:


Add support to pack and send the VSC SDP packet for DP. This therefore
allows the transmision of format information to the sinks which is
needed for YUV420 support over DP.

Changes in v3:
 - Create a new struct, msm_dp_sdp_with_parity, which holds the
   packing information for VSC SDP
 - Use drm_dp_vsc_sdp_pack() to pack the data into the new
   msm_dp_sdp_with_parity struct instead of specifically packing
   for YUV420 format
 - Modify dp_catalog_panel_send_vsc_sdp() to send the VSC SDP
   data using the new msm_dp_sdp_with_parity struct

Changes in v2:
 - Rename GENERIC0_SDPSIZE macro to GENERIC0_SDPSIZE_VALID
 - Remove dp_sdp from the dp_catalog struct since this data is
   being allocated at the point used
 - Create a new function in dp_utils to pack the VSC SDP data
   into a buffer
 - Create a new function that packs the SDP header bytes into a
   buffer. This function is made generic so that it can be
   utilized by dp_audio
   header bytes into a buffer
 - Create a new function in dp_utils that takes the packed buffer
   and writes to the DP_GENERIC0_* registers
 - Split the dp_catalog_panel_config_vsc_sdp() function into two
   to disable/enable sending VSC SDP packets
 - Check the DP HW version using the original useage of
   dp_catalog_hw_revision() and correct the version checking
   logic
 - Rename dp_panel_setup_vsc_sdp() to
   dp_panel_setup_vsc_sdp_yuv_420() to explicitly state that
   currently VSC SDP is only being set up to support YUV420 modes

Signed-off-by: Paloma Arellano 
---
  drivers/gpu/drm/msm/dp/dp_catalog.c | 113 
  drivers/gpu/drm/msm/dp/dp_catalog.h |   7 ++
  drivers/gpu/drm/msm/dp/dp_ctrl.c|   4 +
  drivers/gpu/drm/msm/dp/dp_panel.c   |  55 ++
  drivers/gpu/drm/msm/dp/dp_reg.h |   3 +
  drivers/gpu/drm/msm/dp/dp_utils.c   |  48 
  drivers/gpu/drm/msm/dp/dp_utils.h   |  18 +
  7 files changed, 248 insertions(+)

diff --git a/drivers/gpu/drm/msm/dp/dp_catalog.c 
b/drivers/gpu/drm/msm/dp/dp_catalog.c
index 5d84c089e520a..61d5317efe683 100644
--- a/drivers/gpu/drm/msm/dp/dp_catalog.c
+++ b/drivers/gpu/drm/msm/dp/dp_catalog.c
@@ -901,6 +901,119 @@ int dp_catalog_panel_timing_cfg(struct dp_catalog 
*dp_catalog)
 return 0;
  }

+static void dp_catalog_panel_send_vsc_sdp(struct dp_catalog *dp_catalog,
+ struct msm_dp_sdp_with_parity 
*msm_dp_sdp)
+{
+   struct dp_catalog_private *catalog;
+   u32 val;
+
+   if (!dp_catalog) {
+   DRM_ERROR("invalid input\n");
+   return;
+   }
+
+   catalog = container_of(dp_catalog, struct dp_catalog_private, 
dp_catalog);
+
+   val = ((msm_dp_sdp->vsc_sdp.sdp_header.HB0) << HEADER_BYTE_0_BIT |
+  (msm_dp_sdp->pb.PB0 << PARITY_BYTE_0_BIT) |
+  (msm_dp_sdp->vsc_sdp.sdp_header.HB1) << HEADER_BYTE_1_BIT |
+  (msm_dp_sdp->pb.PB1 << PARITY_BYTE_1_BIT));
+   dp_write_link(catalog, MMSS_DP_GENERIC0_0, val);
+
+   val = ((msm_dp_sdp->vsc_sdp.sdp_header.HB2) << HEADER_BYTE_2_BIT |
+  (msm_dp_sdp->pb.PB2 << PARITY_BYTE_2_BIT) |
+  (msm_dp_sdp->vsc_sdp.sdp_header.HB3) << HEADER_BYTE_3_BIT |
+  (msm_dp_sdp->pb.PB3 << PARITY_BYTE_3_BIT));
+   dp_write_link(catalog, MMSS_DP_GENERIC0_1, val);


I still think that this is not the way to do it. Could you please
extract the function that takes struct dp_sdp_header, calculates
padding and writes resulting data to the hardware? This way we can
reuse it later for all the dp_audio stuff.



hmmm ... dp_utils_pack_sdp_header() does that you are asking for right?

OR are you asking for another function like:

1) rename dp_utils_pack_sdp_header() to dp_utils_calc_sdp_parity()
2) dp_utils_pack_sdp() takes two u32 to pack the header and parity 
together and we move the << HEADER_BYTE_xx | part to it


dp_catalog_panel_send_vsc_sdp() just uses these two u32 to write the 
headers.




+
+   val = ((msm_dp_sdp->vsc_sdp.db[16]) | (msm_dp_sdp->vsc_sdp.db[17] << 8) 
|
+  (msm_dp_sdp->vsc_sdp.db[18] << 16));
+   dp_write_link(catalog, MMSS_DP_GENERIC0_6, val);


Shouldn't we write full dp_sdp data, including all zeroes? Here you
assume that there is no other data in dp_sdp and also that nobody
wrote anything senseless to those registers.



As per documentation, it says db[0] to db[15] are reserved so I thought 
its better not to touch/use them and start writing for 16 onwards.


1592  * VSC SDP Payload for Pixel Encoding/Colorimetry Format
1593  * db[0] - db[15]: Reserved
1594  * db[16]: Pixel Encoding and Colorimetry Formats
1595  * db[17]: Dynamic Range 

Re: [PATCH v3 15/19] drm/msm/dp: enable SDP and SDE periph flush update

2024-02-14 Thread Paloma Arellano



On 2/14/2024 11:41 AM, Dmitry Baryshkov wrote:

On Wed, 14 Feb 2024 at 20:04, Paloma Arellano  wrote:

DP controller can be setup to operate in either SDP update flush mode or
peripheral flush mode based on the DP controller hardware version.

Starting in DP v1.2, the hardware documents require the use of
peripheral flush mode for SDP packets such as PPS OR VSC SDP packets.

In-line with this guidance, lets program the DP controller to use
peripheral flush mode starting DP v1.2

Changes in v3:
 - Clear up that the DP_MAINLINK_FLUSH_MODE_SDE_PERIPH_UPDATE
   macro is setting bits [24:23] to a value of 3

Changes in v2:
 - Use the original dp_catalog_hw_revision() function to
   correctly check the DP HW version

Signed-off-by: Paloma Arellano 
---
  drivers/gpu/drm/msm/dp/dp_catalog.c | 17 +
  drivers/gpu/drm/msm/dp/dp_catalog.h |  1 +
  drivers/gpu/drm/msm/dp/dp_ctrl.c|  1 +
  drivers/gpu/drm/msm/dp/dp_reg.h |  5 +
  4 files changed, 24 insertions(+)

diff --git a/drivers/gpu/drm/msm/dp/dp_catalog.c 
b/drivers/gpu/drm/msm/dp/dp_catalog.c
index 61d5317efe683..823eeba7e71d3 100644
--- a/drivers/gpu/drm/msm/dp/dp_catalog.c
+++ b/drivers/gpu/drm/msm/dp/dp_catalog.c
@@ -440,6 +440,23 @@ void dp_catalog_ctrl_config_misc(struct dp_catalog 
*dp_catalog,
 dp_write_link(catalog, REG_DP_MISC1_MISC0, misc_val);
  }

+void dp_catalog_setup_peripheral_flush(struct dp_catalog *dp_catalog)
+{
+   u32 mainlink_ctrl, hw_revision;
+   struct dp_catalog_private *catalog = container_of(dp_catalog,
+   struct dp_catalog_private, dp_catalog);
+
+   mainlink_ctrl = dp_read_link(catalog, REG_DP_MAINLINK_CTRL);
+
+   hw_revision = dp_catalog_hw_revision(dp_catalog);
+   if (hw_revision >= DP_HW_VERSION_1_2)
+   mainlink_ctrl |= DP_MAINLINK_FLUSH_MODE_SDE_PERIPH_UPDATE;
+   else
+   mainlink_ctrl |= DP_MAINLINK_FLUSH_MODE_UPDATE_SDP;
+
+   dp_write_link(catalog, REG_DP_MAINLINK_CTRL, mainlink_ctrl);
+}
+
  void dp_catalog_ctrl_config_msa(struct dp_catalog *dp_catalog,
 u32 rate, u32 stream_rate_khz,
 bool fixed_nvid, bool is_ycbcr_420)
diff --git a/drivers/gpu/drm/msm/dp/dp_catalog.h 
b/drivers/gpu/drm/msm/dp/dp_catalog.h
index 4bf08c27a9bf3..eb05a37837beb 100644
--- a/drivers/gpu/drm/msm/dp/dp_catalog.h
+++ b/drivers/gpu/drm/msm/dp/dp_catalog.h
@@ -98,6 +98,7 @@ void dp_catalog_ctrl_config_ctrl(struct dp_catalog 
*dp_catalog, u32 config);
  void dp_catalog_ctrl_lane_mapping(struct dp_catalog *dp_catalog);
  void dp_catalog_ctrl_mainlink_ctrl(struct dp_catalog *dp_catalog, bool 
enable);
  void dp_catalog_ctrl_psr_mainlink_enable(struct dp_catalog *dp_catalog, bool 
enable);
+void dp_catalog_setup_peripheral_flush(struct dp_catalog *dp_catalog);
  void dp_catalog_ctrl_config_misc(struct dp_catalog *dp_catalog, u32 cc, u32 
tb);
  void dp_catalog_ctrl_config_msa(struct dp_catalog *dp_catalog, u32 rate,
 u32 stream_rate_khz, bool fixed_nvid, bool 
is_ycbcr_420);
diff --git a/drivers/gpu/drm/msm/dp/dp_ctrl.c b/drivers/gpu/drm/msm/dp/dp_ctrl.c
index beef86b1aaf81..f1e7b0a5ee5d1 100644
--- a/drivers/gpu/drm/msm/dp/dp_ctrl.c
+++ b/drivers/gpu/drm/msm/dp/dp_ctrl.c
@@ -170,6 +170,7 @@ static void dp_ctrl_configure_source_params(struct 
dp_ctrl_private *ctrl)

 dp_catalog_ctrl_lane_mapping(ctrl->catalog);
 dp_catalog_ctrl_mainlink_ctrl(ctrl->catalog, true);
+   dp_catalog_setup_peripheral_flush(ctrl->catalog);

 dp_ctrl_config_ctrl(ctrl);

diff --git a/drivers/gpu/drm/msm/dp/dp_reg.h b/drivers/gpu/drm/msm/dp/dp_reg.h
index 2983756c125cd..d4fb8572cd1e4 100644
--- a/drivers/gpu/drm/msm/dp/dp_reg.h
+++ b/drivers/gpu/drm/msm/dp/dp_reg.h
@@ -6,6 +6,9 @@
  #ifndef _DP_REG_H_
  #define _DP_REG_H_

+#include 
+#include 
+
  /* DP_TX Registers */
  #define REG_DP_HW_VERSION  (0x)

@@ -102,6 +105,8 @@
  #define DP_MAINLINK_CTRL_ENABLE(0x0001)
  #define DP_MAINLINK_CTRL_RESET (0x0002)
  #define DP_MAINLINK_CTRL_SW_BYPASS_SCRAMBLER   (0x0010)
+#define DP_MAINLINK_FLUSH_MODE_UPDATE_SDP  (0x0080)

This define covers data from the same bit field. Please use FIELD_PREP too.


Ack





+#define DP_MAINLINK_FLUSH_MODE_SDE_PERIPH_UPDATE   FIELD_PREP(GENMASK(24, 
23), 3)

#define DP_foo_MASK GENMASK(24,23)



Ack





  #define DP_MAINLINK_FB_BOUNDARY_SEL(0x0200)

  #define REG_DP_STATE_CTRL  (0x0004)
--
2.39.2





Re: [PATCH v3 01/12] drm/atomic-helper: split not-scaling part of drm_atomic_helper_check_plane_state

2024-02-14 Thread Dmitry Baryshkov
On Wed, 14 Feb 2024 at 21:39, Ville Syrjälä
 wrote:
>
> On Wed, Feb 14, 2024 at 09:17:06PM +0200, Dmitry Baryshkov wrote:
> > On Wed, 14 Feb 2024 at 20:47, Ville Syrjälä
> >  wrote:
> > >
> > > On Wed, Feb 14, 2024 at 08:37:02PM +0200, Ville Syrjälä wrote:
> > > > On Thu, Sep 14, 2023 at 08:06:55AM +0300, Dmitry Baryshkov wrote:
> > > > > The helper drm_atomic_helper_check_plane_state() runs several checks 
> > > > > on
> > > > > plane src and dst rectangles, including the check whether required
> > > > > scaling fits into the required margins. The msm driver would benefit
> > > > > from having a function that does all these checks except the scaling
> > > > > one. Split them into a new helper called
> > > > > drm_atomic_helper_check_plane_noscale().
> > > >
> > > > What's the point in eliminating a nop scaling check?
> > >
> > > Actually, what are you even doing in there? Are you saying that
> > > the hardware has absolutely no limits on how much it can scale
> > > in either direction?
> >
> > No, I'm just saying that the scaling ability depends on the rotation
> > and other plane properties. So I had to separate the basic plane
> > checks and the scaling check.
> > Basic (noscale) plane check source and destination rectangles, etc.
> > After that the driver identifies possible hardware pipe usage and
> > after that it can perform a scaling check.
>
> Hmm. We have sport of similar situation in i915 where we pick a scaler
> much later and so don't know the exact scaling limits at the time when
> we do this check. But we opted to pass the lower/upper bounds of the
> scaling limits instead. That will guarantee that at least completely
> illegal values are rejected as early as possible, and so we don't have
> to worry about running into them later on.

Ack, I'll follow this approach then.

-- 
With best wishes
Dmitry


Re: [PATCH v3 15/19] drm/msm/dp: enable SDP and SDE periph flush update

2024-02-14 Thread Dmitry Baryshkov
On Wed, 14 Feb 2024 at 20:04, Paloma Arellano  wrote:
>
> DP controller can be setup to operate in either SDP update flush mode or
> peripheral flush mode based on the DP controller hardware version.
>
> Starting in DP v1.2, the hardware documents require the use of
> peripheral flush mode for SDP packets such as PPS OR VSC SDP packets.
>
> In-line with this guidance, lets program the DP controller to use
> peripheral flush mode starting DP v1.2
>
> Changes in v3:
> - Clear up that the DP_MAINLINK_FLUSH_MODE_SDE_PERIPH_UPDATE
>   macro is setting bits [24:23] to a value of 3
>
> Changes in v2:
> - Use the original dp_catalog_hw_revision() function to
>   correctly check the DP HW version
>
> Signed-off-by: Paloma Arellano 
> ---
>  drivers/gpu/drm/msm/dp/dp_catalog.c | 17 +
>  drivers/gpu/drm/msm/dp/dp_catalog.h |  1 +
>  drivers/gpu/drm/msm/dp/dp_ctrl.c|  1 +
>  drivers/gpu/drm/msm/dp/dp_reg.h |  5 +
>  4 files changed, 24 insertions(+)
>
> diff --git a/drivers/gpu/drm/msm/dp/dp_catalog.c 
> b/drivers/gpu/drm/msm/dp/dp_catalog.c
> index 61d5317efe683..823eeba7e71d3 100644
> --- a/drivers/gpu/drm/msm/dp/dp_catalog.c
> +++ b/drivers/gpu/drm/msm/dp/dp_catalog.c
> @@ -440,6 +440,23 @@ void dp_catalog_ctrl_config_misc(struct dp_catalog 
> *dp_catalog,
> dp_write_link(catalog, REG_DP_MISC1_MISC0, misc_val);
>  }
>
> +void dp_catalog_setup_peripheral_flush(struct dp_catalog *dp_catalog)
> +{
> +   u32 mainlink_ctrl, hw_revision;
> +   struct dp_catalog_private *catalog = container_of(dp_catalog,
> +   struct dp_catalog_private, dp_catalog);
> +
> +   mainlink_ctrl = dp_read_link(catalog, REG_DP_MAINLINK_CTRL);
> +
> +   hw_revision = dp_catalog_hw_revision(dp_catalog);
> +   if (hw_revision >= DP_HW_VERSION_1_2)
> +   mainlink_ctrl |= DP_MAINLINK_FLUSH_MODE_SDE_PERIPH_UPDATE;
> +   else
> +   mainlink_ctrl |= DP_MAINLINK_FLUSH_MODE_UPDATE_SDP;
> +
> +   dp_write_link(catalog, REG_DP_MAINLINK_CTRL, mainlink_ctrl);
> +}
> +
>  void dp_catalog_ctrl_config_msa(struct dp_catalog *dp_catalog,
> u32 rate, u32 stream_rate_khz,
> bool fixed_nvid, bool is_ycbcr_420)
> diff --git a/drivers/gpu/drm/msm/dp/dp_catalog.h 
> b/drivers/gpu/drm/msm/dp/dp_catalog.h
> index 4bf08c27a9bf3..eb05a37837beb 100644
> --- a/drivers/gpu/drm/msm/dp/dp_catalog.h
> +++ b/drivers/gpu/drm/msm/dp/dp_catalog.h
> @@ -98,6 +98,7 @@ void dp_catalog_ctrl_config_ctrl(struct dp_catalog 
> *dp_catalog, u32 config);
>  void dp_catalog_ctrl_lane_mapping(struct dp_catalog *dp_catalog);
>  void dp_catalog_ctrl_mainlink_ctrl(struct dp_catalog *dp_catalog, bool 
> enable);
>  void dp_catalog_ctrl_psr_mainlink_enable(struct dp_catalog *dp_catalog, bool 
> enable);
> +void dp_catalog_setup_peripheral_flush(struct dp_catalog *dp_catalog);
>  void dp_catalog_ctrl_config_misc(struct dp_catalog *dp_catalog, u32 cc, u32 
> tb);
>  void dp_catalog_ctrl_config_msa(struct dp_catalog *dp_catalog, u32 rate,
> u32 stream_rate_khz, bool fixed_nvid, bool 
> is_ycbcr_420);
> diff --git a/drivers/gpu/drm/msm/dp/dp_ctrl.c 
> b/drivers/gpu/drm/msm/dp/dp_ctrl.c
> index beef86b1aaf81..f1e7b0a5ee5d1 100644
> --- a/drivers/gpu/drm/msm/dp/dp_ctrl.c
> +++ b/drivers/gpu/drm/msm/dp/dp_ctrl.c
> @@ -170,6 +170,7 @@ static void dp_ctrl_configure_source_params(struct 
> dp_ctrl_private *ctrl)
>
> dp_catalog_ctrl_lane_mapping(ctrl->catalog);
> dp_catalog_ctrl_mainlink_ctrl(ctrl->catalog, true);
> +   dp_catalog_setup_peripheral_flush(ctrl->catalog);
>
> dp_ctrl_config_ctrl(ctrl);
>
> diff --git a/drivers/gpu/drm/msm/dp/dp_reg.h b/drivers/gpu/drm/msm/dp/dp_reg.h
> index 2983756c125cd..d4fb8572cd1e4 100644
> --- a/drivers/gpu/drm/msm/dp/dp_reg.h
> +++ b/drivers/gpu/drm/msm/dp/dp_reg.h
> @@ -6,6 +6,9 @@
>  #ifndef _DP_REG_H_
>  #define _DP_REG_H_
>
> +#include 
> +#include 
> +
>  /* DP_TX Registers */
>  #define REG_DP_HW_VERSION  (0x)
>
> @@ -102,6 +105,8 @@
>  #define DP_MAINLINK_CTRL_ENABLE(0x0001)
>  #define DP_MAINLINK_CTRL_RESET (0x0002)
>  #define DP_MAINLINK_CTRL_SW_BYPASS_SCRAMBLER   (0x0010)
> +#define DP_MAINLINK_FLUSH_MODE_UPDATE_SDP  (0x0080)

This define covers data from the same bit field. Please use FIELD_PREP too.

> +#define DP_MAINLINK_FLUSH_MODE_SDE_PERIPH_UPDATE   
> FIELD_PREP(GENMASK(24, 23), 3)

#define DP_foo_MASK GENMASK(24,23)

>  #define DP_MAINLINK_FB_BOUNDARY_SEL(0x0200)
>
>  #define REG_DP_STATE_CTRL  (0x0004)
> --
> 2.39.2
>


-- 
With best wishes
Dmitry


Re: [PATCH v3 13/19] drm/msm/dp: add VSC SDP support for YUV420 over DP

2024-02-14 Thread Dmitry Baryshkov
On Wed, 14 Feb 2024 at 20:04, Paloma Arellano  wrote:
>
> Add support to pack and send the VSC SDP packet for DP. This therefore
> allows the transmision of format information to the sinks which is
> needed for YUV420 support over DP.
>
> Changes in v3:
> - Create a new struct, msm_dp_sdp_with_parity, which holds the
>   packing information for VSC SDP
> - Use drm_dp_vsc_sdp_pack() to pack the data into the new
>   msm_dp_sdp_with_parity struct instead of specifically packing
>   for YUV420 format
> - Modify dp_catalog_panel_send_vsc_sdp() to send the VSC SDP
>   data using the new msm_dp_sdp_with_parity struct
>
> Changes in v2:
> - Rename GENERIC0_SDPSIZE macro to GENERIC0_SDPSIZE_VALID
> - Remove dp_sdp from the dp_catalog struct since this data is
>   being allocated at the point used
> - Create a new function in dp_utils to pack the VSC SDP data
>   into a buffer
> - Create a new function that packs the SDP header bytes into a
>   buffer. This function is made generic so that it can be
>   utilized by dp_audio
>   header bytes into a buffer
> - Create a new function in dp_utils that takes the packed buffer
>   and writes to the DP_GENERIC0_* registers
> - Split the dp_catalog_panel_config_vsc_sdp() function into two
>   to disable/enable sending VSC SDP packets
> - Check the DP HW version using the original useage of
>   dp_catalog_hw_revision() and correct the version checking
>   logic
> - Rename dp_panel_setup_vsc_sdp() to
>   dp_panel_setup_vsc_sdp_yuv_420() to explicitly state that
>   currently VSC SDP is only being set up to support YUV420 modes
>
> Signed-off-by: Paloma Arellano 
> ---
>  drivers/gpu/drm/msm/dp/dp_catalog.c | 113 
>  drivers/gpu/drm/msm/dp/dp_catalog.h |   7 ++
>  drivers/gpu/drm/msm/dp/dp_ctrl.c|   4 +
>  drivers/gpu/drm/msm/dp/dp_panel.c   |  55 ++
>  drivers/gpu/drm/msm/dp/dp_reg.h |   3 +
>  drivers/gpu/drm/msm/dp/dp_utils.c   |  48 
>  drivers/gpu/drm/msm/dp/dp_utils.h   |  18 +
>  7 files changed, 248 insertions(+)
>
> diff --git a/drivers/gpu/drm/msm/dp/dp_catalog.c 
> b/drivers/gpu/drm/msm/dp/dp_catalog.c
> index 5d84c089e520a..61d5317efe683 100644
> --- a/drivers/gpu/drm/msm/dp/dp_catalog.c
> +++ b/drivers/gpu/drm/msm/dp/dp_catalog.c
> @@ -901,6 +901,119 @@ int dp_catalog_panel_timing_cfg(struct dp_catalog 
> *dp_catalog)
> return 0;
>  }
>
> +static void dp_catalog_panel_send_vsc_sdp(struct dp_catalog *dp_catalog,
> + struct msm_dp_sdp_with_parity 
> *msm_dp_sdp)
> +{
> +   struct dp_catalog_private *catalog;
> +   u32 val;
> +
> +   if (!dp_catalog) {
> +   DRM_ERROR("invalid input\n");
> +   return;
> +   }
> +
> +   catalog = container_of(dp_catalog, struct dp_catalog_private, 
> dp_catalog);
> +
> +   val = ((msm_dp_sdp->vsc_sdp.sdp_header.HB0) << HEADER_BYTE_0_BIT |
> +  (msm_dp_sdp->pb.PB0 << PARITY_BYTE_0_BIT) |
> +  (msm_dp_sdp->vsc_sdp.sdp_header.HB1) << HEADER_BYTE_1_BIT |
> +  (msm_dp_sdp->pb.PB1 << PARITY_BYTE_1_BIT));
> +   dp_write_link(catalog, MMSS_DP_GENERIC0_0, val);
> +
> +   val = ((msm_dp_sdp->vsc_sdp.sdp_header.HB2) << HEADER_BYTE_2_BIT |
> +  (msm_dp_sdp->pb.PB2 << PARITY_BYTE_2_BIT) |
> +  (msm_dp_sdp->vsc_sdp.sdp_header.HB3) << HEADER_BYTE_3_BIT |
> +  (msm_dp_sdp->pb.PB3 << PARITY_BYTE_3_BIT));
> +   dp_write_link(catalog, MMSS_DP_GENERIC0_1, val);

I still think that this is not the way to do it. Could you please
extract the function that takes struct dp_sdp_header, calculates
padding and writes resulting data to the hardware? This way we can
reuse it later for all the dp_audio stuff.

> +
> +   val = ((msm_dp_sdp->vsc_sdp.db[16]) | (msm_dp_sdp->vsc_sdp.db[17] << 
> 8) |
> +  (msm_dp_sdp->vsc_sdp.db[18] << 16));
> +   dp_write_link(catalog, MMSS_DP_GENERIC0_6, val);

Shouldn't we write full dp_sdp data, including all zeroes? Here you
assume that there is no other data in dp_sdp and also that nobody
wrote anything senseless to those registers.

> +}
> +
> +static void dp_catalog_panel_update_sdp(struct dp_catalog *dp_catalog)
> +{
> +   struct dp_catalog_private *catalog;
> +   u32 hw_revision;
> +
> +   catalog = container_of(dp_catalog, struct dp_catalog_private, 
> dp_catalog);
> +
> +   hw_revision = dp_catalog_hw_revision(dp_catalog);
> +   if (hw_revision < DP_HW_VERSION_1_2 && hw_revision >= 
> DP_HW_VERSION_1_0) {
> +   dp_write_link(catalog, MMSS_DP_SDP_CFG3, 0x01);
> +   dp_write_link(catalog, MMSS_DP_SDP_CFG3, 0x00);
> +   }
> +}
> +
> +void dp_catalog_panel_enable_vsc_sdp(struct dp_catalog *dp_catalog,
> +  

Re: [PATCH v3 01/12] drm/atomic-helper: split not-scaling part of drm_atomic_helper_check_plane_state

2024-02-14 Thread Ville Syrjälä
On Wed, Feb 14, 2024 at 09:17:06PM +0200, Dmitry Baryshkov wrote:
> On Wed, 14 Feb 2024 at 20:47, Ville Syrjälä
>  wrote:
> >
> > On Wed, Feb 14, 2024 at 08:37:02PM +0200, Ville Syrjälä wrote:
> > > On Thu, Sep 14, 2023 at 08:06:55AM +0300, Dmitry Baryshkov wrote:
> > > > The helper drm_atomic_helper_check_plane_state() runs several checks on
> > > > plane src and dst rectangles, including the check whether required
> > > > scaling fits into the required margins. The msm driver would benefit
> > > > from having a function that does all these checks except the scaling
> > > > one. Split them into a new helper called
> > > > drm_atomic_helper_check_plane_noscale().
> > >
> > > What's the point in eliminating a nop scaling check?
> >
> > Actually, what are you even doing in there? Are you saying that
> > the hardware has absolutely no limits on how much it can scale
> > in either direction?
> 
> No, I'm just saying that the scaling ability depends on the rotation
> and other plane properties. So I had to separate the basic plane
> checks and the scaling check.
> Basic (noscale) plane check source and destination rectangles, etc.
> After that the driver identifies possible hardware pipe usage and
> after that it can perform a scaling check.

Hmm. We have sport of similar situation in i915 where we pick a scaler
much later and so don't know the exact scaling limits at the time when
we do this check. But we opted to pass the lower/upper bounds of the
scaling limits instead. That will guarantee that at least completely
illegal values are rejected as early as possible, and so we don't have
to worry about running into them later on.

-- 
Ville Syrjälä
Intel


Re: [PATCH v2] drm/msm/dpu: make "vblank timeout" more useful

2024-02-14 Thread Dmitry Baryshkov
On Wed, 14 Feb 2024 at 20:02, Abhinav Kumar  wrote:
>
>
>
> On 2/8/2024 6:50 AM, Dmitry Baryshkov wrote:
> > We have several reports of vblank timeout messages. However after some
> > debugging it was found that there might be different causes to that.
> > To allow us to identify the DPU block that gets stuck, include the
> > actual CTL_FLUSH value into the timeout message and trigger the devcore
> > snapshot capture.
> >
> > Signed-off-by: Dmitry Baryshkov 
> > ---
> > Changes in v2:
> > - Added a call to msm_disp_snapshot_state() to trigger devcore dump
> >(Abhinav)
> > - Link to v1: 
> > https://lore.kernel.org/r/20240106-fd-dpu-debug-timeout-v1-1-6d9762884...@linaro.org
> > ---
> >   drivers/gpu/drm/msm/disp/dpu1/dpu_encoder_phys_vid.c | 3 ++-
> >   1 file changed, 2 insertions(+), 1 deletion(-)
> >
> > diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder_phys_vid.c 
> > b/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder_phys_vid.c
> > index d0f56c5c4cce..a8d6165b3c0a 100644
> > --- a/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder_phys_vid.c
> > +++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder_phys_vid.c
> > @@ -489,7 +489,8 @@ static int dpu_encoder_phys_vid_wait_for_commit_done(
> >   (hw_ctl->ops.get_flush_register(hw_ctl) == 0),
> >   msecs_to_jiffies(50));
> >   if (ret <= 0) {
> > - DPU_ERROR("vblank timeout\n");
> > + DPU_ERROR("vblank timeout: %x\n", 
> > hw_ctl->ops.get_flush_register(hw_ctl));
> > + msm_disp_snapshot_state(phys_enc->parent->dev);
>
>
> There is no rate limiting in this piece of code unfortunately. So this
> will flood the number of snapshots.

Well... Yes and no. The devcoredump will destroy other snapshots if
there is a pending one. So only the console will be flooded and only
in case when MSM_DISP_SNAPSHOT_DUMP_IN_CONSOLE is enabled.

>
> Short-term solution is you can go with a vblank_timeout_cnt and reset it
> in the enable() like other similar error counters.
>
> long-term solution is we need to centralize these error locations to one
> single dpu_encoder_error_handler() with a single counter and the error
> handler will print out the error code along with the snapshot instead of
> the snapshot being called from all over the place.
>
>
>
> >   return -ETIMEDOUT;
> >   }
> >
> >
> > ---
> > base-commit: 39676dfe52331dba909c617f213fdb21015c8d10
> > change-id: 20240106-fd-dpu-debug-timeout-e917f0bc8063
> >
> > Best regards,



-- 
With best wishes
Dmitry


Re: [PATCH v3 02/12] drm/msm/dpu: add current resource allocation to dumped state

2024-02-14 Thread Dmitry Baryshkov
On Wed, 14 Feb 2024 at 20:41, Abhinav Kumar  wrote:
>
>
>
> On 9/13/2023 10:06 PM, Dmitry Baryshkov wrote:
> > Provide atomic_print_state callback to the DPU's private object. This
> > way the debugfs/dri/0/state will also include RM's internal state.
> >
>
> I like this idea !
>
> > Signed-off-by: Dmitry Baryshkov 
> > ---
> >   drivers/gpu/drm/msm/disp/dpu1/dpu_kms.c |  4 +++
> >   drivers/gpu/drm/msm/disp/dpu1/dpu_kms.h |  2 ++
> >   drivers/gpu/drm/msm/disp/dpu1/dpu_rm.c  | 48 +
> >   drivers/gpu/drm/msm/disp/dpu1/dpu_rm.h  |  8 +
> >   4 files changed, 62 insertions(+)
> >
> > diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_kms.c 
> > b/drivers/gpu/drm/msm/disp/dpu1/dpu_kms.c
> > index ee84160592ce..172b64dc60e6 100644
> > --- a/drivers/gpu/drm/msm/disp/dpu1/dpu_kms.c
> > +++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_kms.c
> > @@ -362,6 +362,7 @@ static void dpu_kms_global_destroy_state(struct 
> > drm_private_obj *obj,
> >   static const struct drm_private_state_funcs dpu_kms_global_state_funcs = {
> >   .atomic_duplicate_state = dpu_kms_global_duplicate_state,
> >   .atomic_destroy_state = dpu_kms_global_destroy_state,
> > + .atomic_print_state = dpu_rm_print_state,
> >   };
> >
> >   static int dpu_kms_global_obj_init(struct dpu_kms *dpu_kms)
> > @@ -375,6 +376,9 @@ static int dpu_kms_global_obj_init(struct dpu_kms 
> > *dpu_kms)
> >   drm_atomic_private_obj_init(dpu_kms->dev, _kms->global_state,
> >   >base,
> >   _kms_global_state_funcs);
> > +
> > + state->rm = _kms->rm;
> > +
> >   return 0;
> >   }
> >
> > diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_kms.h 
> > b/drivers/gpu/drm/msm/disp/dpu1/dpu_kms.h
> > index ed549f0f7c65..dd2be279b366 100644
> > --- a/drivers/gpu/drm/msm/disp/dpu1/dpu_kms.h
> > +++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_kms.h
> > @@ -130,6 +130,8 @@ struct vsync_info {
> >   struct dpu_global_state {
> >   struct drm_private_state base;
> >
> > + struct dpu_rm *rm;
> > +
> >   uint32_t pingpong_to_enc_id[PINGPONG_MAX - PINGPONG_0];
> >   uint32_t mixer_to_enc_id[LM_MAX - LM_0];
> >   uint32_t ctl_to_enc_id[CTL_MAX - CTL_0];
> > diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_rm.c 
> > b/drivers/gpu/drm/msm/disp/dpu1/dpu_rm.c
> > index f9215643c71a..5e3442fb8678 100644
> > --- a/drivers/gpu/drm/msm/disp/dpu1/dpu_rm.c
> > +++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_rm.c
> > @@ -652,3 +652,51 @@ int dpu_rm_get_assigned_resources(struct dpu_rm *rm,
> >
> >   return num_blks;
> >   }
> > +
> > +void dpu_rm_print_state(struct drm_printer *p,
> > + const struct drm_private_state *state)
> > +{
> > + const struct dpu_global_state *global_state = 
> > to_dpu_global_state(state);
> > + const struct dpu_rm *rm = global_state->rm;
> > + int i;
> > +
> > + drm_puts(p, "pingpong:");
> > + for (i = 0; i < ARRAY_SIZE(global_state->pingpong_to_enc_id); i++)
> > + if (rm->pingpong_blks[i])
> > + drm_printf(p, " %d,", 
> > global_state->pingpong_to_enc_id[i]);
> > + else
> > + drm_puts(p, " -,");
> > + drm_puts(p, "\n");
> > +
> > + drm_puts(p, "mixer:");
> > + for (i = 0; i < ARRAY_SIZE(global_state->mixer_to_enc_id); i++)
> > + if (rm->mixer_blks[i])
> > + drm_printf(p, " %d,", 
> > global_state->mixer_to_enc_id[i]);
> > + else
> > + drm_puts(p, " -,");
> > + drm_puts(p, "\n");
> > +
> > + drm_puts(p, "ctl:");
> > + for (i = 0; i < ARRAY_SIZE(global_state->ctl_to_enc_id); i++)
> > + if (rm->ctl_blks[i])
> > + drm_printf(p, " %d,", global_state->ctl_to_enc_id[i]);
> > + else
> > + drm_puts(p, " -,");
> > + drm_puts(p, "\n");
> > +
> > + drm_puts(p, "dspp:");
> > + for (i = 0; i < ARRAY_SIZE(global_state->dspp_to_enc_id); i++)
> > + if (rm->dspp_blks[i])
> > + drm_printf(p, " %d,", 
> > global_state->dspp_to_enc_id[i]);
> > + else
> > + drm_puts(p, " -,");
> > + drm_puts(p, "\n");
> > +
> > + drm_puts(p, "dsc:");
> > + for (i = 0; i < ARRAY_SIZE(global_state->dsc_to_enc_id); i++)
> > + if (rm->dsc_blks[i])
> > + drm_printf(p, " %d,", global_state->dsc_to_enc_id[i]);
> > + else
> > + drm_puts(p, " -,");
> > + drm_puts(p, "\n");
> > +}
>
> You also need to include cdm_to_enc_id now. But otherwise LGTM.
>
> If you have run this before, do you have a sample output to share?

No, I don't have a dump at hand. But I can post this patch separately,
including the CDM change.

>
>
> > diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_rm.h 
> > b/drivers/gpu/drm/msm/disp/dpu1/dpu_rm.h
> > index 2b551566cbf4..913baca81a42 100644
> > --- a/drivers/gpu/drm/msm/disp/dpu1/dpu_rm.h

Re: [PATCH v3 01/12] drm/atomic-helper: split not-scaling part of drm_atomic_helper_check_plane_state

2024-02-14 Thread Dmitry Baryshkov
On Wed, 14 Feb 2024 at 20:47, Ville Syrjälä
 wrote:
>
> On Wed, Feb 14, 2024 at 08:37:02PM +0200, Ville Syrjälä wrote:
> > On Thu, Sep 14, 2023 at 08:06:55AM +0300, Dmitry Baryshkov wrote:
> > > The helper drm_atomic_helper_check_plane_state() runs several checks on
> > > plane src and dst rectangles, including the check whether required
> > > scaling fits into the required margins. The msm driver would benefit
> > > from having a function that does all these checks except the scaling
> > > one. Split them into a new helper called
> > > drm_atomic_helper_check_plane_noscale().
> >
> > What's the point in eliminating a nop scaling check?
>
> Actually, what are you even doing in there? Are you saying that
> the hardware has absolutely no limits on how much it can scale
> in either direction?

No, I'm just saying that the scaling ability depends on the rotation
and other plane properties. So I had to separate the basic plane
checks and the scaling check.
Basic (noscale) plane check source and destination rectangles, etc.
After that the driver identifies possible hardware pipe usage and
after that it can perform a scaling check.

>
> >
> > >
> > > Signed-off-by: Dmitry Baryshkov 
> > > ---
> > >  drivers/gpu/drm/drm_atomic_helper.c | 110 ++--
> > >  include/drm/drm_atomic_helper.h |   7 ++
> > >  2 files changed, 96 insertions(+), 21 deletions(-)
> > >
> > > diff --git a/drivers/gpu/drm/drm_atomic_helper.c 
> > > b/drivers/gpu/drm/drm_atomic_helper.c
> > > index 292e38eb6218..2d7dd66181c9 100644
> > > --- a/drivers/gpu/drm/drm_atomic_helper.c
> > > +++ b/drivers/gpu/drm/drm_atomic_helper.c
> > > @@ -825,11 +825,9 @@ drm_atomic_helper_check_wb_encoder_state(struct 
> > > drm_encoder *encoder,
> > >  EXPORT_SYMBOL(drm_atomic_helper_check_wb_encoder_state);
> > >
> > >  /**
> > > - * drm_atomic_helper_check_plane_state() - Check plane state for validity
> > > + * drm_atomic_helper_check_plane_noscale() - Check plane state for 
> > > validity
> > >   * @plane_state: plane state to check
> > >   * @crtc_state: CRTC state to check
> > > - * @min_scale: minimum @src:@dest scaling factor in 16.16 fixed point
> > > - * @max_scale: maximum @src:@dest scaling factor in 16.16 fixed point
> > >   * @can_position: is it legal to position the plane such that it
> > >   *doesn't cover the entire CRTC?  This will generally
> > >   *only be false for primary planes.
> > > @@ -845,19 +843,16 @@ 
> > > EXPORT_SYMBOL(drm_atomic_helper_check_wb_encoder_state);
> > >   * RETURNS:
> > >   * Zero if update appears valid, error code on failure
> > >   */
> > > -int drm_atomic_helper_check_plane_state(struct drm_plane_state 
> > > *plane_state,
> > > -   const struct drm_crtc_state 
> > > *crtc_state,
> > > -   int min_scale,
> > > -   int max_scale,
> > > -   bool can_position,
> > > -   bool can_update_disabled)
> > > +int drm_atomic_helper_check_plane_noscale(struct drm_plane_state 
> > > *plane_state,
> > > + const struct drm_crtc_state 
> > > *crtc_state,
> > > + bool can_position,
> > > + bool can_update_disabled)
> > >  {
> > > struct drm_framebuffer *fb = plane_state->fb;
> > > struct drm_rect *src = _state->src;
> > > struct drm_rect *dst = _state->dst;
> > > unsigned int rotation = plane_state->rotation;
> > > struct drm_rect clip = {};
> > > -   int hscale, vscale;
> > >
> > > WARN_ON(plane_state->crtc && plane_state->crtc != crtc_state->crtc);
> > >
> > > @@ -883,17 +878,6 @@ int drm_atomic_helper_check_plane_state(struct 
> > > drm_plane_state *plane_state,
> > >
> > > drm_rect_rotate(src, fb->width << 16, fb->height << 16, rotation);
> > >
> > > -   /* Check scaling */
> > > -   hscale = drm_rect_calc_hscale(src, dst, min_scale, max_scale);
> > > -   vscale = drm_rect_calc_vscale(src, dst, min_scale, max_scale);
> > > -   if (hscale < 0 || vscale < 0) {
> > > -   drm_dbg_kms(plane_state->plane->dev,
> > > -   "Invalid scaling of plane\n");
> > > -   drm_rect_debug_print("src: ", _state->src, true);
> > > -   drm_rect_debug_print("dst: ", _state->dst, false);
> > > -   return -ERANGE;
> > > -   }
> > > -
> > > if (crtc_state->enable)
> > > drm_mode_get_hv_timing(_state->mode, , );
> > >
> > > @@ -921,6 +905,90 @@ int drm_atomic_helper_check_plane_state(struct 
> > > drm_plane_state *plane_state,
> > >
> > > return 0;
> > >  }
> > > +EXPORT_SYMBOL(drm_atomic_helper_check_plane_noscale);
> > > +
> > > +/**
> > > + * drm_atomic_helper_check_plane_scale() - Check whether plane can be 
> > > scaled
> > > + * @plane_state: plane state to check
> > > + * @min_scale: minimum @src:@dest scaling factor in 16.16 

Re: [PATCH] drm/dp: move intel_dp_vsc_sdp_pack() to generic helper

2024-02-14 Thread Dmitry Baryshkov
On Wed, 14 Feb 2024 at 20:08, Abhinav Kumar  wrote:
>
>
>
> On 2/14/2024 10:02 AM, Ville Syrjälä wrote:
> > On Wed, Feb 14, 2024 at 09:17:34AM -0800, Abhinav Kumar wrote:
> >>
> >>
> >> On 2/14/2024 12:15 AM, Dmitry Baryshkov wrote:
> >>> On Wed, 14 Feb 2024 at 01:45, Abhinav Kumar  
> >>> wrote:
> 
>  intel_dp_vsc_sdp_pack() can be re-used by other DRM drivers as well.
>  Lets move this to drm_dp_helper to achieve this.
> 
>  Signed-off-by: Abhinav Kumar 
> >>>
> >>> My preference would be to have packing functions in
> >>> drivers/video/hdmi.c, as we already have
> >>> hdmi_audio_infoframe_pack_for_dp() there.
> >>>
> >>
> >> My preference is drm_dp_helper because it already has some VSC SDP stuff
> >> and after discussion with Ville on IRC, I decided to post it this way.
> >>
> >> hdmi_audio_infoframe_pack_for_dp() is an exception from my PoV as the
> >> hdmi audio infoframe fields were re-used and packed into a DP SDP
> >> thereby re-using the existing struct hdmi_audio_infoframe .
> >>
> >> This is not like that. Here we pack from struct drm_dp_vsc_sdp to struct
> >> dp_sdp both of which had prior usages already in this file.
> >>
> >> So it all adds up and makes sense to me to be in this file.
> >>
> >> I will let the other DRM core maintainers comment on this.
> >>
> >> Ville, Jani?
> >
> > Yeah, I'm not sure bloating the (poorly named) hdmi.c with all
> > SDP stuff is a great idea. Since other related stuff already
> > lives in the drm_dp_helper.c that seems reasonable to me at this
> > time. And if we get a decent amount of this then probably all
> > DP SDP stuff should be extracted into its own file.
> >
>
> Yes, thanks.
>
> > There are of course a few overlaps here andthere (the audio SDP
> > I guess, and the CTA infoframe SDP). But I'm not sure that actually
> > needs any SDP specific stuff in hdmi.c, or could we just let hdmi.c
> > deal with the actual CTA-861 stuff and then have the DP SDP code
> > wrap that up in its own thing externally? Dunno, haven't really
> > looked at the details.
> >
>
> Thats a good way to look at it. this packing is from DP spec and not CTA
> so makes more sense to be in this file.
>
> In that case, R-b?
>
> >>
>  ---
> drivers/gpu/drm/display/drm_dp_helper.c | 78 +
> drivers/gpu/drm/i915/display/intel_dp.c | 73 +--
> include/drm/display/drm_dp_helper.h |  3 +
> 3 files changed, 84 insertions(+), 70 deletions(-)
> 
>  diff --git a/drivers/gpu/drm/display/drm_dp_helper.c 
>  b/drivers/gpu/drm/display/drm_dp_helper.c
>  index b1ca3a1100da..066cfbbf7a91 100644
>  --- a/drivers/gpu/drm/display/drm_dp_helper.c
>  +++ b/drivers/gpu/drm/display/drm_dp_helper.c
>  @@ -2916,6 +2916,84 @@ void drm_dp_vsc_sdp_log(const char *level, struct 
>  device *dev,
> }
> EXPORT_SYMBOL(drm_dp_vsc_sdp_log);
> 
>  +/**
>  + * drm_dp_vsc_sdp_pack() - pack a given vsc sdp into generic dp_sdp
>  + * @vsc: vsc sdp initialized according to its purpose as defined in
>  + *   table 2-118 - table 2-120 in DP 1.4a specification
>  + * @sdp: valid handle to the generic dp_sdp which will be packed
>  + * @size: valid size of the passed sdp handle
>  + *
>  + * Returns length of sdp on success and error code on failure
>  + */
>  +ssize_t drm_dp_vsc_sdp_pack(const struct drm_dp_vsc_sdp *vsc,
>  +   struct dp_sdp *sdp, size_t size)
> >>>
> >>> I know that you are just moving the function. Maybe there can be
> >>> patch#2, which drops the size argument? The struct dp_sdp already has
> >>> a defined size. The i915 driver just passes sizeof(sdp), which is more
> >>> or less useless.
> >>>
> >>
> >> Yes this is a valid point, I also noticed this. I can post it on top of
> >> this once we get an agreement and ack on this patch first.
> >>

>From my side, with the promise of the size fixup.

Acked-by: Dmitry Baryshkov 


-- 
With best wishes
Dmitry


Re: [PATCH v3 03/12] drm/msm/dpu: take plane rotation into account for wide planes

2024-02-14 Thread Abhinav Kumar




On 9/13/2023 10:06 PM, Dmitry Baryshkov wrote:

Take into account the plane rotation and flipping when calculating src
positions for the wide plane parts.

This is not an issue yet, because rotation is only supported for the
UBWC planes and wide UBWC planes are rejected anyway because in parallel
multirect case only the half of the usual width is supported for tiled
formats. However it's better to fix this now rather than stumbling upon
it later.

Fixes: 80e8ae3b38ab ("drm/msm/dpu: add support for wide planes")
Signed-off-by: Dmitry Baryshkov 
---
  drivers/gpu/drm/msm/disp/dpu1/dpu_plane.c | 27 ++-
  1 file changed, 17 insertions(+), 10 deletions(-)

diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_plane.c 
b/drivers/gpu/drm/msm/disp/dpu1/dpu_plane.c
index c2aaaded07ed..67f9c2a62a17 100644
--- a/drivers/gpu/drm/msm/disp/dpu1/dpu_plane.c
+++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_plane.c
@@ -827,16 +827,6 @@ static int dpu_plane_atomic_check(struct drm_plane *plane,
return -EINVAL;
}
  
-	pipe_cfg->src_rect = new_plane_state->src;

-
-   /* state->src is 16.16, src_rect is not */
-   pipe_cfg->src_rect.x1 >>= 16;
-   pipe_cfg->src_rect.x2 >>= 16;
-   pipe_cfg->src_rect.y1 >>= 16;
-   pipe_cfg->src_rect.y2 >>= 16;
-
-   pipe_cfg->dst_rect = new_plane_state->dst;
-


Why were these lines moved down?

So this change is doing two things:

1) Using drm_rect_fp_to_int() instead of the hand-rolled right shifting
2) Considering rotation for wide plane cases

Do we need to break this up into 2?


fb_rect.x2 = new_plane_state->fb->width;
fb_rect.y2 = new_plane_state->fb->height;
  
@@ -852,6 +842,15 @@ static int dpu_plane_atomic_check(struct drm_plane *plane,
  
  	max_linewidth = pdpu->catalog->caps->max_linewidth;
  
+	/* state->src is 16.16, src_rect is not */

+   drm_rect_fp_to_int(_cfg->src_rect, _plane_state->src);
+
+   pipe_cfg->dst_rect = new_plane_state->dst;
+
+   drm_rect_rotate(_cfg->src_rect,
+   new_plane_state->fb->width, new_plane_state->fb->height,
+   new_plane_state->rotation);
+
if (drm_rect_width(_cfg->src_rect) > max_linewidth) {
/*
 * In parallel multirect case only the half of the usual width
@@ -899,6 +898,14 @@ static int dpu_plane_atomic_check(struct drm_plane *plane,
r_pipe_cfg->dst_rect.x1 = pipe_cfg->dst_rect.x2;
}
  
+	drm_rect_rotate_inv(_cfg->src_rect,

+   new_plane_state->fb->width, 
new_plane_state->fb->height,
+   new_plane_state->rotation);
+   if (r_pipe->sspp)
+   drm_rect_rotate_inv(_pipe_cfg->src_rect,
+   new_plane_state->fb->width, 
new_plane_state->fb->height,
+   new_plane_state->rotation);
+


iiuc, so we do

1) rotate() on full plane
2) rotate_inv() on left half-plane
3) rotate_inv() on right half-plane

If so, looks right to me.



ret = dpu_plane_atomic_check_pipe(pdpu, pipe, pipe_cfg, fmt);
if (ret)
return ret;


Re: [PATCH v3 01/12] drm/atomic-helper: split not-scaling part of drm_atomic_helper_check_plane_state

2024-02-14 Thread Ville Syrjälä
On Wed, Feb 14, 2024 at 08:37:02PM +0200, Ville Syrjälä wrote:
> On Thu, Sep 14, 2023 at 08:06:55AM +0300, Dmitry Baryshkov wrote:
> > The helper drm_atomic_helper_check_plane_state() runs several checks on
> > plane src and dst rectangles, including the check whether required
> > scaling fits into the required margins. The msm driver would benefit
> > from having a function that does all these checks except the scaling
> > one. Split them into a new helper called
> > drm_atomic_helper_check_plane_noscale().
> 
> What's the point in eliminating a nop scaling check?

Actually, what are you even doing in there? Are you saying that
the hardware has absolutely no limits on how much it can scale
in either direction?

> 
> > 
> > Signed-off-by: Dmitry Baryshkov 
> > ---
> >  drivers/gpu/drm/drm_atomic_helper.c | 110 ++--
> >  include/drm/drm_atomic_helper.h |   7 ++
> >  2 files changed, 96 insertions(+), 21 deletions(-)
> > 
> > diff --git a/drivers/gpu/drm/drm_atomic_helper.c 
> > b/drivers/gpu/drm/drm_atomic_helper.c
> > index 292e38eb6218..2d7dd66181c9 100644
> > --- a/drivers/gpu/drm/drm_atomic_helper.c
> > +++ b/drivers/gpu/drm/drm_atomic_helper.c
> > @@ -825,11 +825,9 @@ drm_atomic_helper_check_wb_encoder_state(struct 
> > drm_encoder *encoder,
> >  EXPORT_SYMBOL(drm_atomic_helper_check_wb_encoder_state);
> >  
> >  /**
> > - * drm_atomic_helper_check_plane_state() - Check plane state for validity
> > + * drm_atomic_helper_check_plane_noscale() - Check plane state for validity
> >   * @plane_state: plane state to check
> >   * @crtc_state: CRTC state to check
> > - * @min_scale: minimum @src:@dest scaling factor in 16.16 fixed point
> > - * @max_scale: maximum @src:@dest scaling factor in 16.16 fixed point
> >   * @can_position: is it legal to position the plane such that it
> >   *doesn't cover the entire CRTC?  This will generally
> >   *only be false for primary planes.
> > @@ -845,19 +843,16 @@ 
> > EXPORT_SYMBOL(drm_atomic_helper_check_wb_encoder_state);
> >   * RETURNS:
> >   * Zero if update appears valid, error code on failure
> >   */
> > -int drm_atomic_helper_check_plane_state(struct drm_plane_state 
> > *plane_state,
> > -   const struct drm_crtc_state *crtc_state,
> > -   int min_scale,
> > -   int max_scale,
> > -   bool can_position,
> > -   bool can_update_disabled)
> > +int drm_atomic_helper_check_plane_noscale(struct drm_plane_state 
> > *plane_state,
> > + const struct drm_crtc_state 
> > *crtc_state,
> > + bool can_position,
> > + bool can_update_disabled)
> >  {
> > struct drm_framebuffer *fb = plane_state->fb;
> > struct drm_rect *src = _state->src;
> > struct drm_rect *dst = _state->dst;
> > unsigned int rotation = plane_state->rotation;
> > struct drm_rect clip = {};
> > -   int hscale, vscale;
> >  
> > WARN_ON(plane_state->crtc && plane_state->crtc != crtc_state->crtc);
> >  
> > @@ -883,17 +878,6 @@ int drm_atomic_helper_check_plane_state(struct 
> > drm_plane_state *plane_state,
> >  
> > drm_rect_rotate(src, fb->width << 16, fb->height << 16, rotation);
> >  
> > -   /* Check scaling */
> > -   hscale = drm_rect_calc_hscale(src, dst, min_scale, max_scale);
> > -   vscale = drm_rect_calc_vscale(src, dst, min_scale, max_scale);
> > -   if (hscale < 0 || vscale < 0) {
> > -   drm_dbg_kms(plane_state->plane->dev,
> > -   "Invalid scaling of plane\n");
> > -   drm_rect_debug_print("src: ", _state->src, true);
> > -   drm_rect_debug_print("dst: ", _state->dst, false);
> > -   return -ERANGE;
> > -   }
> > -
> > if (crtc_state->enable)
> > drm_mode_get_hv_timing(_state->mode, , );
> >  
> > @@ -921,6 +905,90 @@ int drm_atomic_helper_check_plane_state(struct 
> > drm_plane_state *plane_state,
> >  
> > return 0;
> >  }
> > +EXPORT_SYMBOL(drm_atomic_helper_check_plane_noscale);
> > +
> > +/**
> > + * drm_atomic_helper_check_plane_scale() - Check whether plane can be 
> > scaled
> > + * @plane_state: plane state to check
> > + * @min_scale: minimum @src:@dest scaling factor in 16.16 fixed point
> > + * @max_scale: maximum @src:@dest scaling factor in 16.16 fixed point
> > + *
> > + * Checks that a desired plane scale fits into the min_scale..max_scale
> > + * boundaries.
> > + * Drivers that provide their own plane handling rather than 
> > helper-provided
> > + * implementations may still wish to call this function to avoid 
> > duplication of
> > + * error checking code.
> > + *
> > + * RETURNS:
> > + * Zero if update appears valid, error code on failure
> > + */
> > +int drm_atomic_helper_check_plane_scale(struct drm_plane_state 
> > *plane_state,
> > +   

Re: [PATCH v3 02/12] drm/msm/dpu: add current resource allocation to dumped state

2024-02-14 Thread Abhinav Kumar




On 9/13/2023 10:06 PM, Dmitry Baryshkov wrote:

Provide atomic_print_state callback to the DPU's private object. This
way the debugfs/dri/0/state will also include RM's internal state.



I like this idea !


Signed-off-by: Dmitry Baryshkov 
---
  drivers/gpu/drm/msm/disp/dpu1/dpu_kms.c |  4 +++
  drivers/gpu/drm/msm/disp/dpu1/dpu_kms.h |  2 ++
  drivers/gpu/drm/msm/disp/dpu1/dpu_rm.c  | 48 +
  drivers/gpu/drm/msm/disp/dpu1/dpu_rm.h  |  8 +
  4 files changed, 62 insertions(+)

diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_kms.c 
b/drivers/gpu/drm/msm/disp/dpu1/dpu_kms.c
index ee84160592ce..172b64dc60e6 100644
--- a/drivers/gpu/drm/msm/disp/dpu1/dpu_kms.c
+++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_kms.c
@@ -362,6 +362,7 @@ static void dpu_kms_global_destroy_state(struct 
drm_private_obj *obj,
  static const struct drm_private_state_funcs dpu_kms_global_state_funcs = {
.atomic_duplicate_state = dpu_kms_global_duplicate_state,
.atomic_destroy_state = dpu_kms_global_destroy_state,
+   .atomic_print_state = dpu_rm_print_state,
  };
  
  static int dpu_kms_global_obj_init(struct dpu_kms *dpu_kms)

@@ -375,6 +376,9 @@ static int dpu_kms_global_obj_init(struct dpu_kms *dpu_kms)
drm_atomic_private_obj_init(dpu_kms->dev, _kms->global_state,
>base,
_kms_global_state_funcs);
+
+   state->rm = _kms->rm;
+
return 0;
  }
  
diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_kms.h b/drivers/gpu/drm/msm/disp/dpu1/dpu_kms.h

index ed549f0f7c65..dd2be279b366 100644
--- a/drivers/gpu/drm/msm/disp/dpu1/dpu_kms.h
+++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_kms.h
@@ -130,6 +130,8 @@ struct vsync_info {
  struct dpu_global_state {
struct drm_private_state base;
  
+	struct dpu_rm *rm;

+
uint32_t pingpong_to_enc_id[PINGPONG_MAX - PINGPONG_0];
uint32_t mixer_to_enc_id[LM_MAX - LM_0];
uint32_t ctl_to_enc_id[CTL_MAX - CTL_0];
diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_rm.c 
b/drivers/gpu/drm/msm/disp/dpu1/dpu_rm.c
index f9215643c71a..5e3442fb8678 100644
--- a/drivers/gpu/drm/msm/disp/dpu1/dpu_rm.c
+++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_rm.c
@@ -652,3 +652,51 @@ int dpu_rm_get_assigned_resources(struct dpu_rm *rm,
  
  	return num_blks;

  }
+
+void dpu_rm_print_state(struct drm_printer *p,
+   const struct drm_private_state *state)
+{
+   const struct dpu_global_state *global_state = 
to_dpu_global_state(state);
+   const struct dpu_rm *rm = global_state->rm;
+   int i;
+
+   drm_puts(p, "pingpong:");
+   for (i = 0; i < ARRAY_SIZE(global_state->pingpong_to_enc_id); i++)
+   if (rm->pingpong_blks[i])
+   drm_printf(p, " %d,", 
global_state->pingpong_to_enc_id[i]);
+   else
+   drm_puts(p, " -,");
+   drm_puts(p, "\n");
+
+   drm_puts(p, "mixer:");
+   for (i = 0; i < ARRAY_SIZE(global_state->mixer_to_enc_id); i++)
+   if (rm->mixer_blks[i])
+   drm_printf(p, " %d,", global_state->mixer_to_enc_id[i]);
+   else
+   drm_puts(p, " -,");
+   drm_puts(p, "\n");
+
+   drm_puts(p, "ctl:");
+   for (i = 0; i < ARRAY_SIZE(global_state->ctl_to_enc_id); i++)
+   if (rm->ctl_blks[i])
+   drm_printf(p, " %d,", global_state->ctl_to_enc_id[i]);
+   else
+   drm_puts(p, " -,");
+   drm_puts(p, "\n");
+
+   drm_puts(p, "dspp:");
+   for (i = 0; i < ARRAY_SIZE(global_state->dspp_to_enc_id); i++)
+   if (rm->dspp_blks[i])
+   drm_printf(p, " %d,", global_state->dspp_to_enc_id[i]);
+   else
+   drm_puts(p, " -,");
+   drm_puts(p, "\n");
+
+   drm_puts(p, "dsc:");
+   for (i = 0; i < ARRAY_SIZE(global_state->dsc_to_enc_id); i++)
+   if (rm->dsc_blks[i])
+   drm_printf(p, " %d,", global_state->dsc_to_enc_id[i]);
+   else
+   drm_puts(p, " -,");
+   drm_puts(p, "\n");
+}


You also need to include cdm_to_enc_id now. But otherwise LGTM.

If you have run this before, do you have a sample output to share?



diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_rm.h 
b/drivers/gpu/drm/msm/disp/dpu1/dpu_rm.h
index 2b551566cbf4..913baca81a42 100644
--- a/drivers/gpu/drm/msm/disp/dpu1/dpu_rm.h
+++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_rm.h
@@ -92,6 +92,14 @@ int dpu_rm_get_assigned_resources(struct dpu_rm *rm,
struct dpu_global_state *global_state, uint32_t enc_id,
enum dpu_hw_blk_type type, struct dpu_hw_blk **blks, int blks_size);
  
+/**

+ * dpu_rm_print_state - output the RM private state
+ * @p: DRM printer
+ * @state: private object state
+ */
+void dpu_rm_print_state(struct drm_printer *p,
+   const struct drm_private_state *state);
+
  /**
   * 

Re: [PATCH v3 01/12] drm/atomic-helper: split not-scaling part of drm_atomic_helper_check_plane_state

2024-02-14 Thread Ville Syrjälä
On Thu, Sep 14, 2023 at 08:06:55AM +0300, Dmitry Baryshkov wrote:
> The helper drm_atomic_helper_check_plane_state() runs several checks on
> plane src and dst rectangles, including the check whether required
> scaling fits into the required margins. The msm driver would benefit
> from having a function that does all these checks except the scaling
> one. Split them into a new helper called
> drm_atomic_helper_check_plane_noscale().

What's the point in eliminating a nop scaling check?

> 
> Signed-off-by: Dmitry Baryshkov 
> ---
>  drivers/gpu/drm/drm_atomic_helper.c | 110 ++--
>  include/drm/drm_atomic_helper.h |   7 ++
>  2 files changed, 96 insertions(+), 21 deletions(-)
> 
> diff --git a/drivers/gpu/drm/drm_atomic_helper.c 
> b/drivers/gpu/drm/drm_atomic_helper.c
> index 292e38eb6218..2d7dd66181c9 100644
> --- a/drivers/gpu/drm/drm_atomic_helper.c
> +++ b/drivers/gpu/drm/drm_atomic_helper.c
> @@ -825,11 +825,9 @@ drm_atomic_helper_check_wb_encoder_state(struct 
> drm_encoder *encoder,
>  EXPORT_SYMBOL(drm_atomic_helper_check_wb_encoder_state);
>  
>  /**
> - * drm_atomic_helper_check_plane_state() - Check plane state for validity
> + * drm_atomic_helper_check_plane_noscale() - Check plane state for validity
>   * @plane_state: plane state to check
>   * @crtc_state: CRTC state to check
> - * @min_scale: minimum @src:@dest scaling factor in 16.16 fixed point
> - * @max_scale: maximum @src:@dest scaling factor in 16.16 fixed point
>   * @can_position: is it legal to position the plane such that it
>   *doesn't cover the entire CRTC?  This will generally
>   *only be false for primary planes.
> @@ -845,19 +843,16 @@ EXPORT_SYMBOL(drm_atomic_helper_check_wb_encoder_state);
>   * RETURNS:
>   * Zero if update appears valid, error code on failure
>   */
> -int drm_atomic_helper_check_plane_state(struct drm_plane_state *plane_state,
> - const struct drm_crtc_state *crtc_state,
> - int min_scale,
> - int max_scale,
> - bool can_position,
> - bool can_update_disabled)
> +int drm_atomic_helper_check_plane_noscale(struct drm_plane_state 
> *plane_state,
> +   const struct drm_crtc_state 
> *crtc_state,
> +   bool can_position,
> +   bool can_update_disabled)
>  {
>   struct drm_framebuffer *fb = plane_state->fb;
>   struct drm_rect *src = _state->src;
>   struct drm_rect *dst = _state->dst;
>   unsigned int rotation = plane_state->rotation;
>   struct drm_rect clip = {};
> - int hscale, vscale;
>  
>   WARN_ON(plane_state->crtc && plane_state->crtc != crtc_state->crtc);
>  
> @@ -883,17 +878,6 @@ int drm_atomic_helper_check_plane_state(struct 
> drm_plane_state *plane_state,
>  
>   drm_rect_rotate(src, fb->width << 16, fb->height << 16, rotation);
>  
> - /* Check scaling */
> - hscale = drm_rect_calc_hscale(src, dst, min_scale, max_scale);
> - vscale = drm_rect_calc_vscale(src, dst, min_scale, max_scale);
> - if (hscale < 0 || vscale < 0) {
> - drm_dbg_kms(plane_state->plane->dev,
> - "Invalid scaling of plane\n");
> - drm_rect_debug_print("src: ", _state->src, true);
> - drm_rect_debug_print("dst: ", _state->dst, false);
> - return -ERANGE;
> - }
> -
>   if (crtc_state->enable)
>   drm_mode_get_hv_timing(_state->mode, , );
>  
> @@ -921,6 +905,90 @@ int drm_atomic_helper_check_plane_state(struct 
> drm_plane_state *plane_state,
>  
>   return 0;
>  }
> +EXPORT_SYMBOL(drm_atomic_helper_check_plane_noscale);
> +
> +/**
> + * drm_atomic_helper_check_plane_scale() - Check whether plane can be scaled
> + * @plane_state: plane state to check
> + * @min_scale: minimum @src:@dest scaling factor in 16.16 fixed point
> + * @max_scale: maximum @src:@dest scaling factor in 16.16 fixed point
> + *
> + * Checks that a desired plane scale fits into the min_scale..max_scale
> + * boundaries.
> + * Drivers that provide their own plane handling rather than helper-provided
> + * implementations may still wish to call this function to avoid duplication 
> of
> + * error checking code.
> + *
> + * RETURNS:
> + * Zero if update appears valid, error code on failure
> + */
> +int drm_atomic_helper_check_plane_scale(struct drm_plane_state *plane_state,
> + int min_scale,
> + int max_scale)
> +{
> + struct drm_framebuffer *fb = plane_state->fb;
> + struct drm_rect src;
> + struct drm_rect dst;
> + int hscale, vscale;
> +
> + if (!plane_state->visible)
> + return 0;
> +
> + src = drm_plane_state_src(plane_state);
> + dst = 

Re: [PATCH v3 01/12] drm/atomic-helper: split not-scaling part of drm_atomic_helper_check_plane_state

2024-02-14 Thread Abhinav Kumar




On 9/13/2023 10:06 PM, Dmitry Baryshkov wrote:

The helper drm_atomic_helper_check_plane_state() runs several checks on
plane src and dst rectangles, including the check whether required
scaling fits into the required margins. The msm driver would benefit
from having a function that does all these checks except the scaling
one. Split them into a new helper called
drm_atomic_helper_check_plane_noscale().

Signed-off-by: Dmitry Baryshkov 
---
  drivers/gpu/drm/drm_atomic_helper.c | 110 ++--
  include/drm/drm_atomic_helper.h |   7 ++
  2 files changed, 96 insertions(+), 21 deletions(-)

diff --git a/drivers/gpu/drm/drm_atomic_helper.c 
b/drivers/gpu/drm/drm_atomic_helper.c
index 292e38eb6218..2d7dd66181c9 100644
--- a/drivers/gpu/drm/drm_atomic_helper.c
+++ b/drivers/gpu/drm/drm_atomic_helper.c
@@ -825,11 +825,9 @@ drm_atomic_helper_check_wb_encoder_state(struct 
drm_encoder *encoder,
  EXPORT_SYMBOL(drm_atomic_helper_check_wb_encoder_state);
  
  /**

- * drm_atomic_helper_check_plane_state() - Check plane state for validity
+ * drm_atomic_helper_check_plane_noscale() - Check plane state for validity
   * @plane_state: plane state to check
   * @crtc_state: CRTC state to check
- * @min_scale: minimum @src:@dest scaling factor in 16.16 fixed point
- * @max_scale: maximum @src:@dest scaling factor in 16.16 fixed point
   * @can_position: is it legal to position the plane such that it
   *doesn't cover the entire CRTC?  This will generally
   *only be false for primary planes.
@@ -845,19 +843,16 @@ EXPORT_SYMBOL(drm_atomic_helper_check_wb_encoder_state);
   * RETURNS:
   * Zero if update appears valid, error code on failure
   */
-int drm_atomic_helper_check_plane_state(struct drm_plane_state *plane_state,
-   const struct drm_crtc_state *crtc_state,
-   int min_scale,
-   int max_scale,
-   bool can_position,
-   bool can_update_disabled)
+int drm_atomic_helper_check_plane_noscale(struct drm_plane_state *plane_state,
+ const struct drm_crtc_state 
*crtc_state,
+ bool can_position,
+ bool can_update_disabled)
  {
struct drm_framebuffer *fb = plane_state->fb;
struct drm_rect *src = _state->src;
struct drm_rect *dst = _state->dst;
unsigned int rotation = plane_state->rotation;
struct drm_rect clip = {};
-   int hscale, vscale;
  
  	WARN_ON(plane_state->crtc && plane_state->crtc != crtc_state->crtc);
  
@@ -883,17 +878,6 @@ int drm_atomic_helper_check_plane_state(struct drm_plane_state *plane_state,
  
  	drm_rect_rotate(src, fb->width << 16, fb->height << 16, rotation);
  


Do we need to do the rotation even for noscale before validation?


-   /* Check scaling */
-   hscale = drm_rect_calc_hscale(src, dst, min_scale, max_scale);
-   vscale = drm_rect_calc_vscale(src, dst, min_scale, max_scale);
-   if (hscale < 0 || vscale < 0) {
-   drm_dbg_kms(plane_state->plane->dev,
-   "Invalid scaling of plane\n");
-   drm_rect_debug_print("src: ", _state->src, true);
-   drm_rect_debug_print("dst: ", _state->dst, false);
-   return -ERANGE;
-   }
-
if (crtc_state->enable)
drm_mode_get_hv_timing(_state->mode, , );
  
@@ -921,6 +905,90 @@ int drm_atomic_helper_check_plane_state(struct drm_plane_state *plane_state,
  
  	return 0;

  }
+EXPORT_SYMBOL(drm_atomic_helper_check_plane_noscale);
+
+/**
+ * drm_atomic_helper_check_plane_scale() - Check whether plane can be scaled
+ * @plane_state: plane state to check
+ * @min_scale: minimum @src:@dest scaling factor in 16.16 fixed point
+ * @max_scale: maximum @src:@dest scaling factor in 16.16 fixed point
+ *
+ * Checks that a desired plane scale fits into the min_scale..max_scale
+ * boundaries.
+ * Drivers that provide their own plane handling rather than helper-provided
+ * implementations may still wish to call this function to avoid duplication of
+ * error checking code.
+ *
+ * RETURNS:
+ * Zero if update appears valid, error code on failure
+ */
+int drm_atomic_helper_check_plane_scale(struct drm_plane_state *plane_state,
+   int min_scale,
+   int max_scale)
+{
+   struct drm_framebuffer *fb = plane_state->fb;
+   struct drm_rect src;
+   struct drm_rect dst;
+   int hscale, vscale;
+
+   if (!plane_state->visible)
+   return 0;
+
+   src = drm_plane_state_src(plane_state);
+   dst = drm_plane_state_dest(plane_state);
+
+   drm_rect_rotate(, fb->width << 16, fb->height << 16, 
plane_state->rotation);
+


Does this need to be accompanied by 

Re: [PATCH] drm/dp: move intel_dp_vsc_sdp_pack() to generic helper

2024-02-14 Thread Abhinav Kumar




On 2/14/2024 10:02 AM, Ville Syrjälä wrote:

On Wed, Feb 14, 2024 at 09:17:34AM -0800, Abhinav Kumar wrote:



On 2/14/2024 12:15 AM, Dmitry Baryshkov wrote:

On Wed, 14 Feb 2024 at 01:45, Abhinav Kumar  wrote:


intel_dp_vsc_sdp_pack() can be re-used by other DRM drivers as well.
Lets move this to drm_dp_helper to achieve this.

Signed-off-by: Abhinav Kumar 


My preference would be to have packing functions in
drivers/video/hdmi.c, as we already have
hdmi_audio_infoframe_pack_for_dp() there.



My preference is drm_dp_helper because it already has some VSC SDP stuff
and after discussion with Ville on IRC, I decided to post it this way.

hdmi_audio_infoframe_pack_for_dp() is an exception from my PoV as the
hdmi audio infoframe fields were re-used and packed into a DP SDP
thereby re-using the existing struct hdmi_audio_infoframe .

This is not like that. Here we pack from struct drm_dp_vsc_sdp to struct
dp_sdp both of which had prior usages already in this file.

So it all adds up and makes sense to me to be in this file.

I will let the other DRM core maintainers comment on this.

Ville, Jani?


Yeah, I'm not sure bloating the (poorly named) hdmi.c with all
SDP stuff is a great idea. Since other related stuff already
lives in the drm_dp_helper.c that seems reasonable to me at this
time. And if we get a decent amount of this then probably all
DP SDP stuff should be extracted into its own file.



Yes, thanks.


There are of course a few overlaps here andthere (the audio SDP
I guess, and the CTA infoframe SDP). But I'm not sure that actually
needs any SDP specific stuff in hdmi.c, or could we just let hdmi.c
deal with the actual CTA-861 stuff and then have the DP SDP code
wrap that up in its own thing externally? Dunno, haven't really
looked at the details.



Thats a good way to look at it. this packing is from DP spec and not CTA 
so makes more sense to be in this file.


In that case, R-b?




---
   drivers/gpu/drm/display/drm_dp_helper.c | 78 +
   drivers/gpu/drm/i915/display/intel_dp.c | 73 +--
   include/drm/display/drm_dp_helper.h |  3 +
   3 files changed, 84 insertions(+), 70 deletions(-)

diff --git a/drivers/gpu/drm/display/drm_dp_helper.c 
b/drivers/gpu/drm/display/drm_dp_helper.c
index b1ca3a1100da..066cfbbf7a91 100644
--- a/drivers/gpu/drm/display/drm_dp_helper.c
+++ b/drivers/gpu/drm/display/drm_dp_helper.c
@@ -2916,6 +2916,84 @@ void drm_dp_vsc_sdp_log(const char *level, struct device 
*dev,
   }
   EXPORT_SYMBOL(drm_dp_vsc_sdp_log);

+/**
+ * drm_dp_vsc_sdp_pack() - pack a given vsc sdp into generic dp_sdp
+ * @vsc: vsc sdp initialized according to its purpose as defined in
+ *   table 2-118 - table 2-120 in DP 1.4a specification
+ * @sdp: valid handle to the generic dp_sdp which will be packed
+ * @size: valid size of the passed sdp handle
+ *
+ * Returns length of sdp on success and error code on failure
+ */
+ssize_t drm_dp_vsc_sdp_pack(const struct drm_dp_vsc_sdp *vsc,
+   struct dp_sdp *sdp, size_t size)


I know that you are just moving the function. Maybe there can be
patch#2, which drops the size argument? The struct dp_sdp already has
a defined size. The i915 driver just passes sizeof(sdp), which is more
or less useless.



Yes this is a valid point, I also noticed this. I can post it on top of
this once we get an agreement and ack on this patch first.


+{
+   size_t length = sizeof(struct dp_sdp);
+
+   if (size < length)
+   return -ENOSPC;
+
+   memset(sdp, 0, size);
+
+   /*
+* Prepare VSC Header for SU as per DP 1.4a spec, Table 2-119
+* VSC SDP Header Bytes
+*/
+   sdp->sdp_header.HB0 = 0; /* Secondary-Data Packet ID = 0 */
+   sdp->sdp_header.HB1 = vsc->sdp_type; /* Secondary-data Packet Type */
+   sdp->sdp_header.HB2 = vsc->revision; /* Revision Number */
+   sdp->sdp_header.HB3 = vsc->length; /* Number of Valid Data Bytes */
+
+   if (vsc->revision == 0x6) {
+   sdp->db[0] = 1;
+   sdp->db[3] = 1;
+   }
+
+   /*
+* Revision 0x5 and revision 0x7 supports Pixel Encoding/Colorimetry
+* Format as per DP 1.4a spec and DP 2.0 respectively.
+*/
+   if (!(vsc->revision == 0x5 || vsc->revision == 0x7))
+   goto out;
+
+   /* VSC SDP Payload for DB16 through DB18 */
+   /* Pixel Encoding and Colorimetry Formats  */
+   sdp->db[16] = (vsc->pixelformat & 0xf) << 4; /* DB16[7:4] */
+   sdp->db[16] |= vsc->colorimetry & 0xf; /* DB16[3:0] */
+
+   switch (vsc->bpc) {
+   case 6:
+   /* 6bpc: 0x0 */
+   break;
+   case 8:
+   sdp->db[17] = 0x1; /* DB17[3:0] */
+   break;
+   case 10:
+   sdp->db[17] = 0x2;
+   break;
+   case 12:
+   sdp->db[17] = 0x3;
+   break;
+   case 16:
+   sdp->db[17] = 0x4;
+   

[PATCH v3 18/19] drm/msm/dpu: reserve CDM blocks for DP if mode is YUV420

2024-02-14 Thread Paloma Arellano
Reserve CDM blocks for DP if the mode format is YUV420. Currently this
reservation only works for writeback and DP if the format is YUV420. But
this can be easily extented to other YUV formats for DP.

Changes in v2:
- Minor code simplification

Signed-off-by: Paloma Arellano 
Reviewed-by: Dmitry Baryshkov 
---
 drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c | 22 +
 1 file changed, 14 insertions(+), 8 deletions(-)

diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c 
b/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c
index 6280c6be6dca9..ec53e5f4a696d 100644
--- a/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c
+++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c
@@ -639,6 +639,7 @@ static int dpu_encoder_virt_atomic_check(
struct dpu_kms *dpu_kms;
struct drm_display_mode *adj_mode;
struct msm_display_topology topology;
+   struct msm_display_info *disp_info;
struct dpu_global_state *global_state;
struct drm_framebuffer *fb;
struct drm_dsc_config *dsc;
@@ -655,6 +656,7 @@ static int dpu_encoder_virt_atomic_check(
DPU_DEBUG_ENC(dpu_enc, "\n");
 
priv = drm_enc->dev->dev_private;
+   disp_info = _enc->disp_info;
dpu_kms = to_dpu_kms(priv->kms);
adj_mode = _state->adjusted_mode;
global_state = dpu_kms_get_global_state(crtc_state->state);
@@ -682,21 +684,24 @@ static int dpu_encoder_virt_atomic_check(
topology = dpu_encoder_get_topology(dpu_enc, dpu_kms, adj_mode, 
crtc_state, dsc);
 
/*
-* Use CDM only for writeback at the moment as other interfaces cannot 
handle it.
-* if writeback itself cannot handle cdm for some reason it will fail 
in its atomic_check()
+* Use CDM only for writeback or DP at the moment as other interfaces 
cannot handle it.
+* If writeback itself cannot handle cdm for some reason it will fail 
in its atomic_check()
 * earlier.
 */
-   if (dpu_enc->disp_info.intf_type == INTF_WB && 
conn_state->writeback_job) {
+   if (disp_info->intf_type == INTF_WB && conn_state->writeback_job) {
fb = conn_state->writeback_job->fb;
 
if (fb && 
DPU_FORMAT_IS_YUV(to_dpu_format(msm_framebuffer_format(fb
topology.needs_cdm = true;
-   if (topology.needs_cdm && !dpu_enc->cur_master->hw_cdm)
-   crtc_state->mode_changed = true;
-   else if (!topology.needs_cdm && dpu_enc->cur_master->hw_cdm)
-   crtc_state->mode_changed = true;
+   } else if (disp_info->intf_type == INTF_DP) {
+   if 
(msm_dp_is_yuv_420_enabled(priv->dp[disp_info->h_tile_instance[0]], adj_mode))
+   topology.needs_cdm = true;
}
 
+   if (topology.needs_cdm && !dpu_enc->cur_master->hw_cdm)
+   crtc_state->mode_changed = true;
+   else if (!topology.needs_cdm && dpu_enc->cur_master->hw_cdm)
+   crtc_state->mode_changed = true;
/*
 * Release and Allocate resources on every modeset
 * Dont allocate when active is false.
@@ -1137,7 +1142,8 @@ static void dpu_encoder_virt_atomic_mode_set(struct 
drm_encoder *drm_enc,
 
dpu_enc->dsc_mask = dsc_mask;
 
-   if (dpu_enc->disp_info.intf_type == INTF_WB && 
conn_state->writeback_job) {
+   if ((dpu_enc->disp_info.intf_type == INTF_WB && 
conn_state->writeback_job) ||
+   dpu_enc->disp_info.intf_type == INTF_DP) {
struct dpu_hw_blk *hw_cdm = NULL;
 
dpu_rm_get_assigned_resources(_kms->rm, global_state,
-- 
2.39.2



[PATCH v3 12/19] drm/msm/dp: move parity calculation to dp_utils

2024-02-14 Thread Paloma Arellano
Parity calculation is necessary for VSC SDP implementation. Therefore
create new files dp_utils.c and dp_utils.h and move the parity
calculating functions here. This ensures that they are usable by SDP
programming in both dp_catalog.c and dp_audio.c

Changes in v3:
- Change ordering of the header byte macros

Changes in v2:
- Create new files dp_utils.c and dp_utils.h
- Move the parity calculation to these new files instead of
  having them in dp_catalog.c and dp_catalog.h

Signed-off-by: Paloma Arellano 
Reviewed-by: Dmitry Baryshkov 
---
 drivers/gpu/drm/msm/Makefile  |   3 +-
 drivers/gpu/drm/msm/dp/dp_audio.c | 101 +-
 drivers/gpu/drm/msm/dp/dp_utils.c |  73 +
 drivers/gpu/drm/msm/dp/dp_utils.h |  22 +++
 4 files changed, 112 insertions(+), 87 deletions(-)
 create mode 100644 drivers/gpu/drm/msm/dp/dp_utils.c
 create mode 100644 drivers/gpu/drm/msm/dp/dp_utils.h

diff --git a/drivers/gpu/drm/msm/Makefile b/drivers/gpu/drm/msm/Makefile
index b1173128b5b97..998b155e4a979 100644
--- a/drivers/gpu/drm/msm/Makefile
+++ b/drivers/gpu/drm/msm/Makefile
@@ -129,7 +129,8 @@ msm-$(CONFIG_DRM_MSM_DP)+= dp/dp_aux.o \
dp/dp_panel.o \
dp/dp_parser.o \
dp/dp_power.o \
-   dp/dp_audio.o
+   dp/dp_audio.o \
+   dp/dp_utils.o
 
 msm-$(CONFIG_DRM_FBDEV_EMULATION) += msm_fbdev.o
 
diff --git a/drivers/gpu/drm/msm/dp/dp_audio.c 
b/drivers/gpu/drm/msm/dp/dp_audio.c
index 4a2e479723a85..7634e4b742084 100644
--- a/drivers/gpu/drm/msm/dp/dp_audio.c
+++ b/drivers/gpu/drm/msm/dp/dp_audio.c
@@ -15,13 +15,7 @@
 #include "dp_audio.h"
 #include "dp_panel.h"
 #include "dp_display.h"
-
-#define HEADER_BYTE_2_BIT   0
-#define PARITY_BYTE_2_BIT   8
-#define HEADER_BYTE_1_BIT  16
-#define PARITY_BYTE_1_BIT  24
-#define HEADER_BYTE_3_BIT  16
-#define PARITY_BYTE_3_BIT  24
+#include "dp_utils.h"
 
 struct dp_audio_private {
struct platform_device *audio_pdev;
@@ -36,71 +30,6 @@ struct dp_audio_private {
struct dp_audio dp_audio;
 };
 
-static u8 dp_audio_get_g0_value(u8 data)
-{
-   u8 c[4];
-   u8 g[4];
-   u8 ret_data = 0;
-   u8 i;
-
-   for (i = 0; i < 4; i++)
-   c[i] = (data >> i) & 0x01;
-
-   g[0] = c[3];
-   g[1] = c[0] ^ c[3];
-   g[2] = c[1];
-   g[3] = c[2];
-
-   for (i = 0; i < 4; i++)
-   ret_data = ((g[i] & 0x01) << i) | ret_data;
-
-   return ret_data;
-}
-
-static u8 dp_audio_get_g1_value(u8 data)
-{
-   u8 c[4];
-   u8 g[4];
-   u8 ret_data = 0;
-   u8 i;
-
-   for (i = 0; i < 4; i++)
-   c[i] = (data >> i) & 0x01;
-
-   g[0] = c[0] ^ c[3];
-   g[1] = c[0] ^ c[1] ^ c[3];
-   g[2] = c[1] ^ c[2];
-   g[3] = c[2] ^ c[3];
-
-   for (i = 0; i < 4; i++)
-   ret_data = ((g[i] & 0x01) << i) | ret_data;
-
-   return ret_data;
-}
-
-static u8 dp_audio_calculate_parity(u32 data)
-{
-   u8 x0 = 0;
-   u8 x1 = 0;
-   u8 ci = 0;
-   u8 iData = 0;
-   u8 i = 0;
-   u8 parity_byte;
-   u8 num_byte = (data & 0xFF00) > 0 ? 8 : 2;
-
-   for (i = 0; i < num_byte; i++) {
-   iData = (data >> i*4) & 0xF;
-
-   ci = iData ^ x1;
-   x1 = x0 ^ dp_audio_get_g1_value(ci);
-   x0 = dp_audio_get_g0_value(ci);
-   }
-
-   parity_byte = x1 | (x0 << 4);
-
-   return parity_byte;
-}
-
 static u32 dp_audio_get_header(struct dp_catalog *catalog,
enum dp_catalog_audio_sdp_type sdp,
enum dp_catalog_audio_header_type header)
@@ -134,7 +63,7 @@ static void dp_audio_stream_sdp(struct dp_audio_private 
*audio)
DP_AUDIO_SDP_STREAM, DP_AUDIO_SDP_HEADER_1);
 
new_value = 0x02;
-   parity_byte = dp_audio_calculate_parity(new_value);
+   parity_byte = dp_utils_calculate_parity(new_value);
value |= ((new_value << HEADER_BYTE_1_BIT)
| (parity_byte << PARITY_BYTE_1_BIT));
drm_dbg_dp(audio->drm_dev,
@@ -147,7 +76,7 @@ static void dp_audio_stream_sdp(struct dp_audio_private 
*audio)
value = dp_audio_get_header(catalog,
DP_AUDIO_SDP_STREAM, DP_AUDIO_SDP_HEADER_2);
new_value = value;
-   parity_byte = dp_audio_calculate_parity(new_value);
+   parity_byte = dp_utils_calculate_parity(new_value);
value |= ((new_value << HEADER_BYTE_2_BIT)
| (parity_byte << PARITY_BYTE_2_BIT));
drm_dbg_dp(audio->drm_dev,
@@ -162,7 +91,7 @@ static void dp_audio_stream_sdp(struct dp_audio_private 
*audio)
DP_AUDIO_SDP_STREAM, DP_AUDIO_SDP_HEADER_3);
 
new_value = audio->channels - 1;
-   parity_byte = dp_audio_calculate_parity(new_value);
+   parity_byte = dp_utils_calculate_parity(new_value);
value |= ((new_value << HEADER_BYTE_3_BIT)
| 

[PATCH v3 10/19] drm/msm/dp: program config ctrl for YUV420 over DP

2024-02-14 Thread Paloma Arellano
Change relevant DP controller related programming for YUV420 cases.
Program the configuration control register to indicate YUV420.

Changes in v2:
- Create a new patch only for configuration control programming

Signed-off-by: Paloma Arellano 
Reviewed-by: Dmitry Baryshkov 
---
 drivers/gpu/drm/msm/dp/dp_ctrl.c | 3 +++
 1 file changed, 3 insertions(+)

diff --git a/drivers/gpu/drm/msm/dp/dp_ctrl.c b/drivers/gpu/drm/msm/dp/dp_ctrl.c
index 77a8d9366ed7b..da8f0d9f98718 100644
--- a/drivers/gpu/drm/msm/dp/dp_ctrl.c
+++ b/drivers/gpu/drm/msm/dp/dp_ctrl.c
@@ -128,6 +128,9 @@ static void dp_ctrl_config_ctrl(struct dp_ctrl_private 
*ctrl)
/* Default-> LSCLK DIV: 1/4 LCLK  */
config |= (2 << DP_CONFIGURATION_CTRL_LSCLK_DIV_SHIFT);
 
+   if (ctrl->panel->dp_mode.out_fmt_is_yuv_420)
+   config |= DP_CONFIGURATION_CTRL_RGB_YUV; /* YUV420 */
+
/* Scrambler reset enable */
if (drm_dp_alternate_scrambler_reset_cap(dpcd))
config |= DP_CONFIGURATION_CTRL_ASSR;
-- 
2.39.2



[PATCH v3 19/19] drm/msm/dp: allow YUV420 mode for DP connector when CDM available

2024-02-14 Thread Paloma Arellano
All the components of YUV420 over DP are added. Therefore, let's mark the
connector property as true for DP connector when the DP type is not eDP
and when there is a CDM block available.

Changes in v3:
- Move setting the connector's ycbcr_420_allowed parameter so
  that it is not dependent on if the dp_display is not eDP

Changes in v2:
- Check for if dp_catalog has a CDM block available instead of
  checking if VSC SDP is allowed when setting the dp connector's
  ycbcr_420_allowed parameter

Signed-off-by: Paloma Arellano 
---
 drivers/gpu/drm/msm/disp/dpu1/dpu_kms.c | 4 +++-
 drivers/gpu/drm/msm/dp/dp_display.c | 4 ++--
 drivers/gpu/drm/msm/dp/dp_drm.c | 6 +-
 drivers/gpu/drm/msm/dp/dp_drm.h | 3 ++-
 drivers/gpu/drm/msm/msm_drv.h   | 5 +++--
 5 files changed, 15 insertions(+), 7 deletions(-)

diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_kms.c 
b/drivers/gpu/drm/msm/disp/dpu1/dpu_kms.c
index 723cc1d821431..8d326fb36550a 100644
--- a/drivers/gpu/drm/msm/disp/dpu1/dpu_kms.c
+++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_kms.c
@@ -565,6 +565,7 @@ static int _dpu_kms_initialize_displayport(struct 
drm_device *dev,
 {
struct drm_encoder *encoder = NULL;
struct msm_display_info info;
+   bool yuv_supported;
int rc;
int i;
 
@@ -583,7 +584,8 @@ static int _dpu_kms_initialize_displayport(struct 
drm_device *dev,
return PTR_ERR(encoder);
}
 
-   rc = msm_dp_modeset_init(priv->dp[i], dev, encoder);
+   yuv_supported = !!dpu_kms->catalog->cdm;
+   rc = msm_dp_modeset_init(priv->dp[i], dev, encoder, 
yuv_supported);
if (rc) {
DPU_ERROR("modeset_init failed for DP, rc = %d\n", rc);
return rc;
diff --git a/drivers/gpu/drm/msm/dp/dp_display.c 
b/drivers/gpu/drm/msm/dp/dp_display.c
index ebcc76ef1d590..9b9f5f2921903 100644
--- a/drivers/gpu/drm/msm/dp/dp_display.c
+++ b/drivers/gpu/drm/msm/dp/dp_display.c
@@ -1471,7 +1471,7 @@ static int dp_display_get_next_bridge(struct msm_dp *dp)
 }
 
 int msm_dp_modeset_init(struct msm_dp *dp_display, struct drm_device *dev,
-   struct drm_encoder *encoder)
+   struct drm_encoder *encoder, bool yuv_supported)
 {
struct dp_display_private *dp_priv;
int ret;
@@ -1487,7 +1487,7 @@ int msm_dp_modeset_init(struct msm_dp *dp_display, struct 
drm_device *dev,
return ret;
}
 
-   dp_display->connector = dp_drm_connector_init(dp_display, encoder);
+   dp_display->connector = dp_drm_connector_init(dp_display, encoder, 
yuv_supported);
if (IS_ERR(dp_display->connector)) {
ret = PTR_ERR(dp_display->connector);
DRM_DEV_ERROR(dev->dev,
diff --git a/drivers/gpu/drm/msm/dp/dp_drm.c b/drivers/gpu/drm/msm/dp/dp_drm.c
index 46e6889037e88..a819a4ff76a9f 100644
--- a/drivers/gpu/drm/msm/dp/dp_drm.c
+++ b/drivers/gpu/drm/msm/dp/dp_drm.c
@@ -353,7 +353,8 @@ int dp_bridge_init(struct msm_dp *dp_display, struct 
drm_device *dev,
 }
 
 /* connector initialization */
-struct drm_connector *dp_drm_connector_init(struct msm_dp *dp_display, struct 
drm_encoder *encoder)
+struct drm_connector *dp_drm_connector_init(struct msm_dp *dp_display, struct 
drm_encoder *encoder,
+   bool yuv_supported)
 {
struct drm_connector *connector = NULL;
 
@@ -364,6 +365,9 @@ struct drm_connector *dp_drm_connector_init(struct msm_dp 
*dp_display, struct dr
if (!dp_display->is_edp)
drm_connector_attach_dp_subconnector_property(connector);
 
+   if (yuv_supported)
+   connector->ycbcr_420_allowed = true;
+
drm_connector_attach_encoder(connector, encoder);
 
return connector;
diff --git a/drivers/gpu/drm/msm/dp/dp_drm.h b/drivers/gpu/drm/msm/dp/dp_drm.h
index b3d684db2383b..45e57ac25a4d9 100644
--- a/drivers/gpu/drm/msm/dp/dp_drm.h
+++ b/drivers/gpu/drm/msm/dp/dp_drm.h
@@ -19,7 +19,8 @@ struct msm_dp_bridge {
 
 #define to_dp_bridge(x) container_of((x), struct msm_dp_bridge, bridge)
 
-struct drm_connector *dp_drm_connector_init(struct msm_dp *dp_display, struct 
drm_encoder *encoder);
+struct drm_connector *dp_drm_connector_init(struct msm_dp *dp_display, struct 
drm_encoder *encoder,
+   bool yuv_supported);
 int dp_bridge_init(struct msm_dp *dp_display, struct drm_device *dev,
struct drm_encoder *encoder);
 
diff --git a/drivers/gpu/drm/msm/msm_drv.h b/drivers/gpu/drm/msm/msm_drv.h
index b876ebd48effe..37335777f5c09 100644
--- a/drivers/gpu/drm/msm/msm_drv.h
+++ b/drivers/gpu/drm/msm/msm_drv.h
@@ -385,7 +385,7 @@ static inline struct drm_dsc_config 
*msm_dsi_get_dsc_config(struct msm_dsi *msm_
 int __init msm_dp_register(void);
 void __exit msm_dp_unregister(void);
 int msm_dp_modeset_init(struct 

[PATCH v3 04/19] drm/msm/dpu: allow dpu_encoder_helper_phys_setup_cdm to work for DP

2024-02-14 Thread Paloma Arellano
Generalize dpu_encoder_helper_phys_setup_cdm to be compatible with DP.

Changes in v2:
- Minor formatting changes
- Move the modification of the dimensions for CDM setup to a new
  patch

Signed-off-by: Paloma Arellano 
Reviewed-by: Dmitry Baryshkov 
---
 .../gpu/drm/msm/disp/dpu1/dpu_encoder_phys.h  |  4 +--
 .../drm/msm/disp/dpu1/dpu_encoder_phys_wb.c   | 27 ++-
 2 files changed, 16 insertions(+), 15 deletions(-)

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 993f263433314..204d7cc3c1de8 100644
--- a/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder_phys.h
+++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder_phys.h
@@ -154,6 +154,7 @@ enum dpu_intr_idx {
  * @hw_wb: Hardware interface to the wb registers
  * @hw_cdm:Hardware interface to the CDM registers
  * @dpu_kms:   Pointer to the dpu_kms top level
+ * @cdm_cfg:   CDM block config needed to store WB/DP block's CDM 
configuration
  * @cached_mode:   DRM mode cached at mode_set time, acted on in enable
  * @vblank_ctl_lock:   Vblank ctl mutex lock to protect vblank_refcount
  * @enabled:   Whether the encoder has enabled and running a mode
@@ -184,6 +185,7 @@ struct dpu_encoder_phys {
struct dpu_hw_wb *hw_wb;
struct dpu_hw_cdm *hw_cdm;
struct dpu_kms *dpu_kms;
+   struct dpu_hw_cdm_cfg cdm_cfg;
struct drm_display_mode cached_mode;
struct mutex vblank_ctl_lock;
enum dpu_enc_split_role split_role;
@@ -213,7 +215,6 @@ static inline int dpu_encoder_phys_inc_pending(struct 
dpu_encoder_phys *phys)
  * @wbirq_refcount: Reference count of writeback interrupt
  * @wb_done_timeout_cnt: number of wb done irq timeout errors
  * @wb_cfg:  writeback block config to store fb related details
- * @cdm_cfg: cdm block config needed to store writeback block's CDM 
configuration
  * @wb_conn: backpointer to writeback connector
  * @wb_job: backpointer to current writeback job
  * @dest:   dpu buffer layout for current writeback output buffer
@@ -223,7 +224,6 @@ struct dpu_encoder_phys_wb {
atomic_t wbirq_refcount;
int wb_done_timeout_cnt;
struct dpu_hw_wb_cfg wb_cfg;
-   struct dpu_hw_cdm_cfg cdm_cfg;
struct drm_writeback_connector *wb_conn;
struct drm_writeback_job *wb_job;
struct dpu_hw_fmt_layout dest;
diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder_phys_wb.c 
b/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder_phys_wb.c
index ec9e053d3947d..072fc6950e496 100644
--- a/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder_phys_wb.c
+++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder_phys_wb.c
@@ -269,28 +269,21 @@ static void dpu_encoder_phys_wb_setup_ctl(struct 
dpu_encoder_phys *phys_enc)
  * This API does not handle 
DPU_CHROMA_H1V2.
  * @phys_enc:Pointer to physical encoder
  */
-static void dpu_encoder_helper_phys_setup_cdm(struct dpu_encoder_phys 
*phys_enc)
+static void dpu_encoder_helper_phys_setup_cdm(struct dpu_encoder_phys 
*phys_enc,
+ const struct dpu_format *dpu_fmt,
+ u32 output_type)
 {
struct dpu_hw_cdm *hw_cdm;
struct dpu_hw_cdm_cfg *cdm_cfg;
struct dpu_hw_pingpong *hw_pp;
-   struct dpu_encoder_phys_wb *wb_enc;
-   const struct msm_format *format;
-   const struct dpu_format *dpu_fmt;
-   struct drm_writeback_job *wb_job;
int ret;
 
if (!phys_enc)
return;
 
-   wb_enc = to_dpu_encoder_phys_wb(phys_enc);
-   cdm_cfg = _enc->cdm_cfg;
+   cdm_cfg = _enc->cdm_cfg;
hw_pp = phys_enc->hw_pp;
hw_cdm = phys_enc->hw_cdm;
-   wb_job = wb_enc->wb_job;
-
-   format = msm_framebuffer_format(wb_enc->wb_job->fb);
-   dpu_fmt = dpu_get_dpu_format_ext(format->pixel_format, 
wb_job->fb->modifier);
 
if (!hw_cdm)
return;
@@ -309,7 +302,7 @@ static void dpu_encoder_helper_phys_setup_cdm(struct 
dpu_encoder_phys *phys_enc)
cdm_cfg->output_width = phys_enc->cached_mode.hdisplay;
cdm_cfg->output_height = phys_enc->cached_mode.vdisplay;
cdm_cfg->output_fmt = dpu_fmt;
-   cdm_cfg->output_type = CDM_CDWN_OUTPUT_WB;
+   cdm_cfg->output_type = output_type;
cdm_cfg->output_bit_depth = DPU_FORMAT_IS_DX(dpu_fmt) ?
CDM_CDWN_OUTPUT_10BIT : CDM_CDWN_OUTPUT_8BIT;
cdm_cfg->csc_cfg = _csc10_rgb2yuv_601l;
@@ -462,6 +455,14 @@ static void dpu_encoder_phys_wb_setup(
struct dpu_hw_wb *hw_wb = phys_enc->hw_wb;
struct drm_display_mode mode = phys_enc->cached_mode;
struct drm_framebuffer *fb = NULL;
+   struct dpu_encoder_phys_wb *wb_enc = to_dpu_encoder_phys_wb(phys_enc);
+   struct drm_writeback_job *wb_job;
+   const struct msm_format *format;
+   const struct dpu_format *dpu_fmt;
+
+   

[PATCH v3 11/19] drm/msm/dp: change clock related programming for YUV420 over DP

2024-02-14 Thread Paloma Arellano
Change all relevant DP controller related programming for YUV420 cases.
Namely, change the pixel clock math to consider YUV420 and modify the
MVID programming to consider YUV420.

Changes in v2:
- Move configuration control programming to a different commit
- Slight code simplification
- Add VSC SDP check when doing mode_pclk_khz division in
  dp_bridge_mode_valid

Signed-off-by: Paloma Arellano 
Reviewed-by: Dmitry Baryshkov 
---
 drivers/gpu/drm/msm/dp/dp_catalog.c | 5 -
 drivers/gpu/drm/msm/dp/dp_catalog.h | 2 +-
 drivers/gpu/drm/msm/dp/dp_ctrl.c| 9 ++---
 drivers/gpu/drm/msm/dp/dp_display.c | 4 
 4 files changed, 15 insertions(+), 5 deletions(-)

diff --git a/drivers/gpu/drm/msm/dp/dp_catalog.c 
b/drivers/gpu/drm/msm/dp/dp_catalog.c
index 5142aeb705a44..5d84c089e520a 100644
--- a/drivers/gpu/drm/msm/dp/dp_catalog.c
+++ b/drivers/gpu/drm/msm/dp/dp_catalog.c
@@ -442,7 +442,7 @@ void dp_catalog_ctrl_config_misc(struct dp_catalog 
*dp_catalog,
 
 void dp_catalog_ctrl_config_msa(struct dp_catalog *dp_catalog,
u32 rate, u32 stream_rate_khz,
-   bool fixed_nvid)
+   bool fixed_nvid, bool is_ycbcr_420)
 {
u32 pixel_m, pixel_n;
u32 mvid, nvid, pixel_div = 0, dispcc_input_rate;
@@ -485,6 +485,9 @@ void dp_catalog_ctrl_config_msa(struct dp_catalog 
*dp_catalog,
nvid = temp;
}
 
+   if (is_ycbcr_420)
+   mvid /= 2;
+
if (link_rate_hbr2 == rate)
nvid *= 2;
 
diff --git a/drivers/gpu/drm/msm/dp/dp_catalog.h 
b/drivers/gpu/drm/msm/dp/dp_catalog.h
index 38786e855b51a..6cb5e2a243de2 100644
--- a/drivers/gpu/drm/msm/dp/dp_catalog.h
+++ b/drivers/gpu/drm/msm/dp/dp_catalog.h
@@ -96,7 +96,7 @@ void dp_catalog_ctrl_mainlink_ctrl(struct dp_catalog 
*dp_catalog, bool enable);
 void dp_catalog_ctrl_psr_mainlink_enable(struct dp_catalog *dp_catalog, bool 
enable);
 void dp_catalog_ctrl_config_misc(struct dp_catalog *dp_catalog, u32 cc, u32 
tb);
 void dp_catalog_ctrl_config_msa(struct dp_catalog *dp_catalog, u32 rate,
-   u32 stream_rate_khz, bool fixed_nvid);
+   u32 stream_rate_khz, bool fixed_nvid, bool 
is_ycbcr_420);
 int dp_catalog_ctrl_set_pattern_state_bit(struct dp_catalog *dp_catalog, u32 
pattern);
 u32 dp_catalog_hw_revision(const struct dp_catalog *dp_catalog);
 void dp_catalog_ctrl_reset(struct dp_catalog *dp_catalog);
diff --git a/drivers/gpu/drm/msm/dp/dp_ctrl.c b/drivers/gpu/drm/msm/dp/dp_ctrl.c
index da8f0d9f98718..209cf2a35642f 100644
--- a/drivers/gpu/drm/msm/dp/dp_ctrl.c
+++ b/drivers/gpu/drm/msm/dp/dp_ctrl.c
@@ -960,7 +960,7 @@ static void dp_ctrl_calc_tu_parameters(struct 
dp_ctrl_private *ctrl,
in.hporch = drm_mode->htotal - drm_mode->hdisplay;
in.nlanes = ctrl->link->link_params.num_lanes;
in.bpp = ctrl->panel->dp_mode.bpp;
-   in.pixel_enc = 444;
+   in.pixel_enc = ctrl->panel->dp_mode.out_fmt_is_yuv_420 ? 420 : 444;
in.dsc_en = 0;
in.async_en = 0;
in.fec_en = 0;
@@ -1766,6 +1766,8 @@ int dp_ctrl_on_link(struct dp_ctrl *dp_ctrl)
ctrl->link->link_params.rate = rate;
ctrl->link->link_params.num_lanes =
ctrl->panel->link_info.num_lanes;
+   if (ctrl->panel->dp_mode.out_fmt_is_yuv_420)
+   pixel_rate >>= 1;
}
 
drm_dbg_dp(ctrl->drm_dev, "rate=%d, num_lanes=%d, pixel_rate=%lu\n",
@@ -1881,7 +1883,7 @@ int dp_ctrl_on_stream(struct dp_ctrl *dp_ctrl, bool 
force_link_train)
 
pixel_rate = pixel_rate_orig = ctrl->panel->dp_mode.drm_mode.clock;
 
-   if (dp_ctrl->wide_bus_en)
+   if (dp_ctrl->wide_bus_en || ctrl->panel->dp_mode.out_fmt_is_yuv_420)
pixel_rate >>= 1;
 
drm_dbg_dp(ctrl->drm_dev, "rate=%d, num_lanes=%d, pixel_rate=%lu\n",
@@ -1920,7 +1922,8 @@ int dp_ctrl_on_stream(struct dp_ctrl *dp_ctrl, bool 
force_link_train)
 
dp_catalog_ctrl_config_msa(ctrl->catalog,
ctrl->link->link_params.rate,
-   pixel_rate_orig, dp_ctrl_use_fixed_nvid(ctrl));
+   pixel_rate_orig, dp_ctrl_use_fixed_nvid(ctrl),
+   ctrl->panel->dp_mode.out_fmt_is_yuv_420);
 
dp_ctrl_setup_tr_unit(ctrl);
 
diff --git a/drivers/gpu/drm/msm/dp/dp_display.c 
b/drivers/gpu/drm/msm/dp/dp_display.c
index 6323dc08d5eb8..4b04388719363 100644
--- a/drivers/gpu/drm/msm/dp/dp_display.c
+++ b/drivers/gpu/drm/msm/dp/dp_display.c
@@ -933,6 +933,10 @@ enum drm_mode_status dp_bridge_mode_valid(struct 
drm_bridge *bridge,
dp_display = container_of(dp, struct dp_display_private, dp_display);
link_info = _display->panel->link_info;
 
+   if (drm_mode_is_420_only(>connector->display_info, mode) &&
+   dp_display->panel->vsc_sdp_supported)
+   mode_pclk_khz /= 2;
+

[PATCH v3 16/19] drm/msm/dpu: modify encoder programming for CDM over DP

2024-02-14 Thread Paloma Arellano
Adjust the encoder format programming in the case of video mode for DP
to accommodate CDM related changes.

Changes in v2:
- Move timing engine programming to a separate patch from this
  one
- Move update_pending_flush_periph() invocation completely to
  this patch
- Change the logic of dpu_encoder_get_drm_fmt() so that it only
  calls drm_mode_is_420_only() instead of doing additional
  unnecessary checks
- Create new functions msm_dp_needs_periph_flush() and it's
  supporting function dpu_encoder_needs_periph_flush() to check
  if the mode is YUV420 and VSC SDP is enabled before doing a
  peripheral flush

Signed-off-by: Paloma Arellano 
---
 drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c   | 35 +++
 .../gpu/drm/msm/disp/dpu1/dpu_encoder_phys.h  | 13 +++
 .../drm/msm/disp/dpu1/dpu_encoder_phys_vid.c  | 19 ++
 drivers/gpu/drm/msm/dp/dp_display.c   | 18 ++
 drivers/gpu/drm/msm/msm_drv.h | 17 -
 5 files changed, 101 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 7e7796561009a..6280c6be6dca9 100644
--- a/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c
+++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c
@@ -222,6 +222,41 @@ static u32 dither_matrix[DITHER_MATRIX_SZ] = {
15, 7, 13, 5, 3, 11, 1, 9, 12, 4, 14, 6, 0, 8, 2, 10
 };
 
+u32 dpu_encoder_get_drm_fmt(struct dpu_encoder_phys *phys_enc)
+{
+   struct drm_encoder *drm_enc;
+   struct dpu_encoder_virt *dpu_enc;
+   struct drm_display_info *info;
+   struct drm_display_mode *mode;
+
+   drm_enc = phys_enc->parent;
+   dpu_enc = to_dpu_encoder_virt(drm_enc);
+   info = _enc->connector->display_info;
+   mode = _enc->cached_mode;
+
+   if (drm_mode_is_420_only(info, mode))
+   return DRM_FORMAT_YUV420;
+
+   return DRM_FORMAT_RGB888;
+}
+
+bool dpu_encoder_needs_periph_flush(struct dpu_encoder_phys *phys_enc)
+{
+   struct drm_encoder *drm_enc;
+   struct dpu_encoder_virt *dpu_enc;
+   struct msm_display_info *disp_info;
+   struct msm_drm_private *priv;
+   struct drm_display_mode *mode;
+
+   drm_enc = phys_enc->parent;
+   dpu_enc = to_dpu_encoder_virt(drm_enc);
+   disp_info = _enc->disp_info;
+   priv = drm_enc->dev->dev_private;
+   mode = _enc->cached_mode;
+
+   return phys_enc->hw_intf->cap->type == INTF_DP && phys_enc->hw_cdm &&
+  
msm_dp_needs_periph_flush(priv->dp[disp_info->h_tile_instance[0]], mode);
+}
 
 bool dpu_encoder_is_widebus_enabled(const struct drm_encoder *drm_enc)
 {
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 f43d57d9c74e1..211a3d90eb690 100644
--- a/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder_phys.h
+++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder_phys.h
@@ -341,6 +341,19 @@ static inline enum dpu_3d_blend_mode 
dpu_encoder_helper_get_3d_blend_mode(
  */
 unsigned int dpu_encoder_helper_get_dsc(struct dpu_encoder_phys *phys_enc);
 
+/**
+ * dpu_encoder_get_drm_fmt - return DRM fourcc format
+ * @phys_enc: Pointer to physical encoder structure
+ */
+u32 dpu_encoder_get_drm_fmt(struct dpu_encoder_phys *phys_enc);
+
+/**
+ * dpu_encoder_needs_periph_flush - return true if physical encoder requires
+ * peripheral flush
+ * @phys_enc: Pointer to physical encoder structure
+ */
+bool dpu_encoder_needs_periph_flush(struct dpu_encoder_phys *phys_enc);
+
 /**
  * dpu_encoder_helper_split_config - split display configuration helper 
function
  * This helper function may be used by physical encoders to configure
diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder_phys_vid.c 
b/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder_phys_vid.c
index f02411b062c4c..e29bc4bd39208 100644
--- a/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder_phys_vid.c
+++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder_phys_vid.c
@@ -415,8 +415,15 @@ static int dpu_encoder_phys_vid_control_vblank_irq(
 static void dpu_encoder_phys_vid_enable(struct dpu_encoder_phys *phys_enc)
 {
struct dpu_hw_ctl *ctl;
+   struct dpu_hw_cdm *hw_cdm;
+   const struct dpu_format *fmt = NULL;
+   u32 fmt_fourcc = DRM_FORMAT_RGB888;
 
ctl = phys_enc->hw_ctl;
+   hw_cdm = phys_enc->hw_cdm;
+   if (hw_cdm)
+   fmt_fourcc = dpu_encoder_get_drm_fmt(phys_enc);
+   fmt = dpu_get_dpu_format(fmt_fourcc);
 
DPU_DEBUG_VIDENC(phys_enc, "\n");
 
@@ -425,6 +432,8 @@ static void dpu_encoder_phys_vid_enable(struct 
dpu_encoder_phys *phys_enc)
 
dpu_encoder_helper_split_config(phys_enc, phys_enc->hw_intf->idx);
 
+   dpu_encoder_helper_phys_setup_cdm(phys_enc, fmt, CDM_CDWN_OUTPUT_HDMI);
+
dpu_encoder_phys_vid_setup_timing_engine(phys_enc);
 
/*
@@ -440,6 +449,16 @@ static void 

[PATCH v3 17/19] drm/msm/dpu: modify timing engine programming for YUV420 over DP

2024-02-14 Thread Paloma Arellano
Adjust the encoder timing engine setup programming in the case of video
mode for YUV420 over DP to accommodate CDM.

Changes in v3:
- Move drm_display_mode's hskew division to another patch
- Minor cleanup

Changes in v2:
- Move timing engine programming to this patch

Signed-off-by: Paloma Arellano 
---
 drivers/gpu/drm/msm/disp/dpu1/dpu_encoder_phys_vid.c | 8 ++--
 1 file changed, 6 insertions(+), 2 deletions(-)

diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder_phys_vid.c 
b/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder_phys_vid.c
index e29bc4bd39208..04df501d23bfa 100644
--- a/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder_phys_vid.c
+++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder_phys_vid.c
@@ -236,7 +236,7 @@ static void dpu_encoder_phys_vid_setup_timing_engine(
struct drm_display_mode mode;
struct dpu_hw_intf_timing_params timing_params = { 0 };
const struct dpu_format *fmt = NULL;
-   u32 fmt_fourcc = DRM_FORMAT_RGB888;
+   u32 fmt_fourcc;
unsigned long lock_flags;
struct dpu_hw_intf_cfg intf_cfg = { 0 };
 
@@ -255,7 +255,9 @@ static void dpu_encoder_phys_vid_setup_timing_engine(
DPU_DEBUG_VIDENC(phys_enc, "enabling mode:\n");
drm_mode_debug_printmodeline();
 
-   if (phys_enc->split_role != ENC_ROLE_SOLO) {
+   fmt_fourcc = dpu_encoder_get_drm_fmt(phys_enc);
+
+   if (phys_enc->split_role != ENC_ROLE_SOLO || fmt_fourcc == 
DRM_FORMAT_YUV420) {
mode.hdisplay >>= 1;
mode.htotal >>= 1;
mode.hsync_start >>= 1;
@@ -275,6 +277,8 @@ static void dpu_encoder_phys_vid_setup_timing_engine(
fmt = dpu_get_dpu_format(fmt_fourcc);
DPU_DEBUG_VIDENC(phys_enc, "fmt_fourcc 0x%X\n", fmt_fourcc);
 
+   if (phys_enc->hw_cdm)
+   intf_cfg.cdm = phys_enc->hw_cdm->idx;
intf_cfg.intf = phys_enc->hw_intf->idx;
intf_cfg.intf_mode_sel = DPU_CTL_MODE_SEL_VID;
intf_cfg.stream_sel = 0; /* Don't care value for video mode */
-- 
2.39.2



[PATCH v3 15/19] drm/msm/dp: enable SDP and SDE periph flush update

2024-02-14 Thread Paloma Arellano
DP controller can be setup to operate in either SDP update flush mode or
peripheral flush mode based on the DP controller hardware version.

Starting in DP v1.2, the hardware documents require the use of
peripheral flush mode for SDP packets such as PPS OR VSC SDP packets.

In-line with this guidance, lets program the DP controller to use
peripheral flush mode starting DP v1.2

Changes in v3:
- Clear up that the DP_MAINLINK_FLUSH_MODE_SDE_PERIPH_UPDATE
  macro is setting bits [24:23] to a value of 3

Changes in v2:
- Use the original dp_catalog_hw_revision() function to
  correctly check the DP HW version

Signed-off-by: Paloma Arellano 
---
 drivers/gpu/drm/msm/dp/dp_catalog.c | 17 +
 drivers/gpu/drm/msm/dp/dp_catalog.h |  1 +
 drivers/gpu/drm/msm/dp/dp_ctrl.c|  1 +
 drivers/gpu/drm/msm/dp/dp_reg.h |  5 +
 4 files changed, 24 insertions(+)

diff --git a/drivers/gpu/drm/msm/dp/dp_catalog.c 
b/drivers/gpu/drm/msm/dp/dp_catalog.c
index 61d5317efe683..823eeba7e71d3 100644
--- a/drivers/gpu/drm/msm/dp/dp_catalog.c
+++ b/drivers/gpu/drm/msm/dp/dp_catalog.c
@@ -440,6 +440,23 @@ void dp_catalog_ctrl_config_misc(struct dp_catalog 
*dp_catalog,
dp_write_link(catalog, REG_DP_MISC1_MISC0, misc_val);
 }
 
+void dp_catalog_setup_peripheral_flush(struct dp_catalog *dp_catalog)
+{
+   u32 mainlink_ctrl, hw_revision;
+   struct dp_catalog_private *catalog = container_of(dp_catalog,
+   struct dp_catalog_private, dp_catalog);
+
+   mainlink_ctrl = dp_read_link(catalog, REG_DP_MAINLINK_CTRL);
+
+   hw_revision = dp_catalog_hw_revision(dp_catalog);
+   if (hw_revision >= DP_HW_VERSION_1_2)
+   mainlink_ctrl |= DP_MAINLINK_FLUSH_MODE_SDE_PERIPH_UPDATE;
+   else
+   mainlink_ctrl |= DP_MAINLINK_FLUSH_MODE_UPDATE_SDP;
+
+   dp_write_link(catalog, REG_DP_MAINLINK_CTRL, mainlink_ctrl);
+}
+
 void dp_catalog_ctrl_config_msa(struct dp_catalog *dp_catalog,
u32 rate, u32 stream_rate_khz,
bool fixed_nvid, bool is_ycbcr_420)
diff --git a/drivers/gpu/drm/msm/dp/dp_catalog.h 
b/drivers/gpu/drm/msm/dp/dp_catalog.h
index 4bf08c27a9bf3..eb05a37837beb 100644
--- a/drivers/gpu/drm/msm/dp/dp_catalog.h
+++ b/drivers/gpu/drm/msm/dp/dp_catalog.h
@@ -98,6 +98,7 @@ void dp_catalog_ctrl_config_ctrl(struct dp_catalog 
*dp_catalog, u32 config);
 void dp_catalog_ctrl_lane_mapping(struct dp_catalog *dp_catalog);
 void dp_catalog_ctrl_mainlink_ctrl(struct dp_catalog *dp_catalog, bool enable);
 void dp_catalog_ctrl_psr_mainlink_enable(struct dp_catalog *dp_catalog, bool 
enable);
+void dp_catalog_setup_peripheral_flush(struct dp_catalog *dp_catalog);
 void dp_catalog_ctrl_config_misc(struct dp_catalog *dp_catalog, u32 cc, u32 
tb);
 void dp_catalog_ctrl_config_msa(struct dp_catalog *dp_catalog, u32 rate,
u32 stream_rate_khz, bool fixed_nvid, bool 
is_ycbcr_420);
diff --git a/drivers/gpu/drm/msm/dp/dp_ctrl.c b/drivers/gpu/drm/msm/dp/dp_ctrl.c
index beef86b1aaf81..f1e7b0a5ee5d1 100644
--- a/drivers/gpu/drm/msm/dp/dp_ctrl.c
+++ b/drivers/gpu/drm/msm/dp/dp_ctrl.c
@@ -170,6 +170,7 @@ static void dp_ctrl_configure_source_params(struct 
dp_ctrl_private *ctrl)
 
dp_catalog_ctrl_lane_mapping(ctrl->catalog);
dp_catalog_ctrl_mainlink_ctrl(ctrl->catalog, true);
+   dp_catalog_setup_peripheral_flush(ctrl->catalog);
 
dp_ctrl_config_ctrl(ctrl);
 
diff --git a/drivers/gpu/drm/msm/dp/dp_reg.h b/drivers/gpu/drm/msm/dp/dp_reg.h
index 2983756c125cd..d4fb8572cd1e4 100644
--- a/drivers/gpu/drm/msm/dp/dp_reg.h
+++ b/drivers/gpu/drm/msm/dp/dp_reg.h
@@ -6,6 +6,9 @@
 #ifndef _DP_REG_H_
 #define _DP_REG_H_
 
+#include 
+#include 
+
 /* DP_TX Registers */
 #define REG_DP_HW_VERSION  (0x)
 
@@ -102,6 +105,8 @@
 #define DP_MAINLINK_CTRL_ENABLE(0x0001)
 #define DP_MAINLINK_CTRL_RESET (0x0002)
 #define DP_MAINLINK_CTRL_SW_BYPASS_SCRAMBLER   (0x0010)
+#define DP_MAINLINK_FLUSH_MODE_UPDATE_SDP  (0x0080)
+#define DP_MAINLINK_FLUSH_MODE_SDE_PERIPH_UPDATE   FIELD_PREP(GENMASK(24, 
23), 3)
 #define DP_MAINLINK_FB_BOUNDARY_SEL(0x0200)
 
 #define REG_DP_STATE_CTRL  (0x0004)
-- 
2.39.2



[PATCH v3 09/19] drm/msm/dpu: move widebus logic to its own API

2024-02-14 Thread Paloma Arellano
Widebus enablement is decided by the interfaces based on their specific
checks and that already happens with DSI/DP specific helpers. Let's
invoke these helpers from dpu_encoder_is_widebus_enabled() to make it
cleaner overall.

Signed-off-by: Paloma Arellano 
Reviewed-by: Dmitry Baryshkov 
---
 drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c | 29 -
 drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.h |  4 +++
 2 files changed, 20 insertions(+), 13 deletions(-)

diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c 
b/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c
index 3c55d6290b708..7e7796561009a 100644
--- a/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c
+++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c
@@ -225,9 +225,21 @@ static u32 dither_matrix[DITHER_MATRIX_SZ] = {
 
 bool dpu_encoder_is_widebus_enabled(const struct drm_encoder *drm_enc)
 {
-   const struct dpu_encoder_virt *dpu_enc = to_dpu_encoder_virt(drm_enc);
+   const struct dpu_encoder_virt *dpu_enc;
+   struct msm_drm_private *priv = drm_enc->dev->dev_private;
+   const struct msm_display_info *disp_info;
+   int index;
+
+   dpu_enc = to_dpu_encoder_virt(drm_enc);
+   disp_info = _enc->disp_info;
+   index = disp_info->h_tile_instance[0];
+
+   if (disp_info->intf_type == INTF_DP)
+   return msm_dp_wide_bus_available(priv->dp[index]);
+   else if (disp_info->intf_type == INTF_DSI)
+   return msm_dsi_wide_bus_enabled(priv->dsi[index]);
 
-   return dpu_enc->wide_bus_en;
+   return false;
 }
 
 bool dpu_encoder_is_dsc_enabled(const struct drm_encoder *drm_enc)
@@ -1199,26 +1211,17 @@ static void dpu_encoder_virt_atomic_enable(struct 
drm_encoder *drm_enc,
struct dpu_encoder_virt *dpu_enc = NULL;
int ret = 0;
struct drm_display_mode *cur_mode = NULL;
-   struct msm_drm_private *priv = drm_enc->dev->dev_private;
-   struct msm_display_info *disp_info;
-   int index;
 
dpu_enc = to_dpu_encoder_virt(drm_enc);
-   disp_info = _enc->disp_info;
-   index = disp_info->h_tile_instance[0];
-
dpu_enc->dsc = dpu_encoder_get_dsc_config(drm_enc);
 
atomic_set(_enc->frame_done_timeout_cnt, 0);
 
-   if (disp_info->intf_type == INTF_DP)
-   dpu_enc->wide_bus_en = 
msm_dp_wide_bus_available(priv->dp[index]);
-   else if (disp_info->intf_type == INTF_DSI)
-   dpu_enc->wide_bus_en = 
msm_dsi_wide_bus_enabled(priv->dsi[index]);
-
mutex_lock(_enc->enc_lock);
cur_mode = _enc->base.crtc->state->adjusted_mode;
 
+   dpu_enc->wide_bus_en = dpu_encoder_is_widebus_enabled(drm_enc);
+
trace_dpu_enc_enable(DRMID(drm_enc), cur_mode->hdisplay,
 cur_mode->vdisplay);
 
diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.h 
b/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.h
index fe6b1d312a742..67aef59c1f99c 100644
--- a/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.h
+++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.h
@@ -156,6 +156,10 @@ int dpu_encoder_get_linecount(struct drm_encoder *drm_enc);
  */
 int dpu_encoder_get_vsync_count(struct drm_encoder *drm_enc);
 
+/**
+ * dpu_encoder_is_widebus_enabled - return bool value if widebus is enabled
+ * @drm_enc:Pointer to previously created drm encoder structure
+ */
 bool dpu_encoder_is_widebus_enabled(const struct drm_encoder *drm_enc);
 
 /**
-- 
2.39.2



[PATCH v3 02/19] drm/msm/dpu: add division of drm_display_mode's hskew parameter

2024-02-14 Thread Paloma Arellano
Setting up the timing engine when the physical encoder has a split role
neglects dividing the drm_display_mode's hskew parameter. Let's fix this
since this must also be done in preparation for implementing YUV420 over
DP.

Fixes: 25fdd5933e4c ("drm/msm: Add SDM845 DPU support")
Signed-off-by: Paloma Arellano 
---
 drivers/gpu/drm/msm/disp/dpu1/dpu_encoder_phys_vid.c | 6 --
 1 file changed, 4 insertions(+), 2 deletions(-)

diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder_phys_vid.c 
b/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder_phys_vid.c
index f562beb6f7971..f02411b062c4c 100644
--- a/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder_phys_vid.c
+++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder_phys_vid.c
@@ -260,12 +260,14 @@ static void dpu_encoder_phys_vid_setup_timing_engine(
mode.htotal >>= 1;
mode.hsync_start >>= 1;
mode.hsync_end >>= 1;
+   mode.hskew >>= 1;
 
DPU_DEBUG_VIDENC(phys_enc,
-   "split_role %d, halve horizontal %d %d %d %d\n",
+   "split_role %d, halve horizontal %d %d %d %d %d\n",
phys_enc->split_role,
mode.hdisplay, mode.htotal,
-   mode.hsync_start, mode.hsync_end);
+   mode.hsync_start, mode.hsync_end,
+   mode.hskew);
}
 
drm_mode_to_intf_timing_params(phys_enc, , _params);
-- 
2.39.2



[PATCH v3 13/19] drm/msm/dp: add VSC SDP support for YUV420 over DP

2024-02-14 Thread Paloma Arellano
Add support to pack and send the VSC SDP packet for DP. This therefore
allows the transmision of format information to the sinks which is
needed for YUV420 support over DP.

Changes in v3:
- Create a new struct, msm_dp_sdp_with_parity, which holds the
  packing information for VSC SDP
- Use drm_dp_vsc_sdp_pack() to pack the data into the new
  msm_dp_sdp_with_parity struct instead of specifically packing
  for YUV420 format
- Modify dp_catalog_panel_send_vsc_sdp() to send the VSC SDP
  data using the new msm_dp_sdp_with_parity struct

Changes in v2:
- Rename GENERIC0_SDPSIZE macro to GENERIC0_SDPSIZE_VALID
- Remove dp_sdp from the dp_catalog struct since this data is
  being allocated at the point used
- Create a new function in dp_utils to pack the VSC SDP data
  into a buffer
- Create a new function that packs the SDP header bytes into a
  buffer. This function is made generic so that it can be
  utilized by dp_audio
  header bytes into a buffer
- Create a new function in dp_utils that takes the packed buffer
  and writes to the DP_GENERIC0_* registers
- Split the dp_catalog_panel_config_vsc_sdp() function into two
  to disable/enable sending VSC SDP packets
- Check the DP HW version using the original useage of
  dp_catalog_hw_revision() and correct the version checking
  logic
- Rename dp_panel_setup_vsc_sdp() to
  dp_panel_setup_vsc_sdp_yuv_420() to explicitly state that
  currently VSC SDP is only being set up to support YUV420 modes

Signed-off-by: Paloma Arellano 
---
 drivers/gpu/drm/msm/dp/dp_catalog.c | 113 
 drivers/gpu/drm/msm/dp/dp_catalog.h |   7 ++
 drivers/gpu/drm/msm/dp/dp_ctrl.c|   4 +
 drivers/gpu/drm/msm/dp/dp_panel.c   |  55 ++
 drivers/gpu/drm/msm/dp/dp_reg.h |   3 +
 drivers/gpu/drm/msm/dp/dp_utils.c   |  48 
 drivers/gpu/drm/msm/dp/dp_utils.h   |  18 +
 7 files changed, 248 insertions(+)

diff --git a/drivers/gpu/drm/msm/dp/dp_catalog.c 
b/drivers/gpu/drm/msm/dp/dp_catalog.c
index 5d84c089e520a..61d5317efe683 100644
--- a/drivers/gpu/drm/msm/dp/dp_catalog.c
+++ b/drivers/gpu/drm/msm/dp/dp_catalog.c
@@ -901,6 +901,119 @@ int dp_catalog_panel_timing_cfg(struct dp_catalog 
*dp_catalog)
return 0;
 }
 
+static void dp_catalog_panel_send_vsc_sdp(struct dp_catalog *dp_catalog,
+ struct msm_dp_sdp_with_parity 
*msm_dp_sdp)
+{
+   struct dp_catalog_private *catalog;
+   u32 val;
+
+   if (!dp_catalog) {
+   DRM_ERROR("invalid input\n");
+   return;
+   }
+
+   catalog = container_of(dp_catalog, struct dp_catalog_private, 
dp_catalog);
+
+   val = ((msm_dp_sdp->vsc_sdp.sdp_header.HB0) << HEADER_BYTE_0_BIT |
+  (msm_dp_sdp->pb.PB0 << PARITY_BYTE_0_BIT) |
+  (msm_dp_sdp->vsc_sdp.sdp_header.HB1) << HEADER_BYTE_1_BIT |
+  (msm_dp_sdp->pb.PB1 << PARITY_BYTE_1_BIT));
+   dp_write_link(catalog, MMSS_DP_GENERIC0_0, val);
+
+   val = ((msm_dp_sdp->vsc_sdp.sdp_header.HB2) << HEADER_BYTE_2_BIT |
+  (msm_dp_sdp->pb.PB2 << PARITY_BYTE_2_BIT) |
+  (msm_dp_sdp->vsc_sdp.sdp_header.HB3) << HEADER_BYTE_3_BIT |
+  (msm_dp_sdp->pb.PB3 << PARITY_BYTE_3_BIT));
+   dp_write_link(catalog, MMSS_DP_GENERIC0_1, val);
+
+   val = ((msm_dp_sdp->vsc_sdp.db[16]) | (msm_dp_sdp->vsc_sdp.db[17] << 8) 
|
+  (msm_dp_sdp->vsc_sdp.db[18] << 16));
+   dp_write_link(catalog, MMSS_DP_GENERIC0_6, val);
+}
+
+static void dp_catalog_panel_update_sdp(struct dp_catalog *dp_catalog)
+{
+   struct dp_catalog_private *catalog;
+   u32 hw_revision;
+
+   catalog = container_of(dp_catalog, struct dp_catalog_private, 
dp_catalog);
+
+   hw_revision = dp_catalog_hw_revision(dp_catalog);
+   if (hw_revision < DP_HW_VERSION_1_2 && hw_revision >= 
DP_HW_VERSION_1_0) {
+   dp_write_link(catalog, MMSS_DP_SDP_CFG3, 0x01);
+   dp_write_link(catalog, MMSS_DP_SDP_CFG3, 0x00);
+   }
+}
+
+void dp_catalog_panel_enable_vsc_sdp(struct dp_catalog *dp_catalog,
+struct msm_dp_sdp_with_parity *msm_dp_sdp)
+{
+   struct dp_catalog_private *catalog;
+   u32 cfg, cfg2, misc;
+
+   if (!dp_catalog) {
+   DRM_ERROR("invalid input\n");
+   return;
+   }
+
+   catalog = container_of(dp_catalog, struct dp_catalog_private, 
dp_catalog);
+
+   cfg = dp_read_link(catalog, MMSS_DP_SDP_CFG);
+   cfg2 = dp_read_link(catalog, MMSS_DP_SDP_CFG2);
+   misc = dp_read_link(catalog, REG_DP_MISC1_MISC0);
+
+   cfg |= GEN0_SDP_EN;
+   dp_write_link(catalog, MMSS_DP_SDP_CFG, cfg);
+
+   cfg2 |= GENERIC0_SDPSIZE_VALID;
+   dp_write_link(catalog, MMSS_DP_SDP_CFG2, 

[PATCH v3 14/19] drm/msm/dpu: add support of new peripheral flush mechanism

2024-02-14 Thread Paloma Arellano
From: Kuogee Hsieh 

Introduce a peripheral flushing mechanism to decouple peripheral
metadata flushing from timing engine related flush.

Changes in v2:
- Fixed some misalignment issues

Signed-off-by: Kuogee Hsieh 
Signed-off-by: Paloma Arellano 
Reviewed-by: Dmitry Baryshkov 
---
 drivers/gpu/drm/msm/disp/dpu1/dpu_hw_ctl.c | 17 +
 drivers/gpu/drm/msm/disp/dpu1/dpu_hw_ctl.h | 10 ++
 2 files changed, 27 insertions(+)

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 e76565c3e6a43..a06f69d0b257d 100644
--- a/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_ctl.c
+++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_ctl.c
@@ -39,6 +39,7 @@
 #define   CTL_WB_FLUSH  0x108
 #define   CTL_INTF_FLUSH0x110
 #define   CTL_CDM_FLUSH0x114
+#define   CTL_PERIPH_FLUSH  0x128
 #define   CTL_INTF_MASTER   0x134
 #define   CTL_DSPP_n_FLUSH(n)   ((0x13C) + ((n) * 4))
 
@@ -49,6 +50,7 @@
 #define  MERGE_3D_IDX   23
 #define  DSC_IDX22
 #define CDM_IDX 26
+#define  PERIPH_IDX 30
 #define  INTF_IDX   31
 #define WB_IDX  16
 #define  DSPP_IDX   29  /* From DPU hw rev 7.x.x */
@@ -151,6 +153,10 @@ static inline void dpu_hw_ctl_trigger_flush_v1(struct 
dpu_hw_ctl *ctx)
ctx->pending_dspp_flush_mask[dspp - DSPP_0]);
}
 
+   if (ctx->pending_flush_mask & BIT(PERIPH_IDX))
+   DPU_REG_WRITE(>hw, CTL_PERIPH_FLUSH,
+ ctx->pending_periph_flush_mask);
+
if (ctx->pending_flush_mask & BIT(DSC_IDX))
DPU_REG_WRITE(>hw, CTL_DSC_FLUSH,
  ctx->pending_dsc_flush_mask);
@@ -311,6 +317,13 @@ static void dpu_hw_ctl_update_pending_flush_intf_v1(struct 
dpu_hw_ctl *ctx,
ctx->pending_flush_mask |= BIT(INTF_IDX);
 }
 
+static void dpu_hw_ctl_update_pending_flush_periph_v1(struct dpu_hw_ctl *ctx,
+ enum dpu_intf intf)
+{
+   ctx->pending_periph_flush_mask |= BIT(intf - INTF_0);
+   ctx->pending_flush_mask |= BIT(PERIPH_IDX);
+}
+
 static void dpu_hw_ctl_update_pending_flush_merge_3d_v1(struct dpu_hw_ctl *ctx,
enum dpu_merge_3d merge_3d)
 {
@@ -680,6 +693,10 @@ static void _setup_ctl_ops(struct dpu_hw_ctl_ops *ops,
ops->reset_intf_cfg = dpu_hw_ctl_reset_intf_cfg_v1;
ops->update_pending_flush_intf =
dpu_hw_ctl_update_pending_flush_intf_v1;
+
+   ops->update_pending_flush_periph =
+   dpu_hw_ctl_update_pending_flush_periph_v1;
+
ops->update_pending_flush_merge_3d =
dpu_hw_ctl_update_pending_flush_merge_3d_v1;
ops->update_pending_flush_wb = 
dpu_hw_ctl_update_pending_flush_wb_v1;
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 ff85b5ee0acf8..ef56280bea932 100644
--- a/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_ctl.h
+++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_ctl.h
@@ -122,6 +122,15 @@ struct dpu_hw_ctl_ops {
void (*update_pending_flush_intf)(struct dpu_hw_ctl *ctx,
enum dpu_intf blk);
 
+   /**
+* OR in the given flushbits to the cached pending_(periph_)flush_mask
+* No effect on hardware
+* @ctx   : ctl path ctx pointer
+* @blk   : interface block index
+*/
+   void (*update_pending_flush_periph)(struct dpu_hw_ctl *ctx,
+   enum dpu_intf blk);
+
/**
 * OR in the given flushbits to the cached pending_(merge_3d_)flush_mask
 * No effect on hardware
@@ -264,6 +273,7 @@ struct dpu_hw_ctl {
u32 pending_flush_mask;
u32 pending_intf_flush_mask;
u32 pending_wb_flush_mask;
+   u32 pending_periph_flush_mask;
u32 pending_merge_3d_flush_mask;
u32 pending_dspp_flush_mask[DSPP_MAX - DSPP_0];
u32 pending_dsc_flush_mask;
-- 
2.39.2



[PATCH v3 07/19] drm/msm/dp: store mode YUV420 information to be used by rest of DP

2024-02-14 Thread Paloma Arellano
Wide bus is not supported when the mode is YUV420 in DP. In preparation
for changing the DPU programming to reflect this, the value and
assignment location of wide_bus_en for the DP submodules must be
changed. Move it from boot time in dp_init_sub_modules() to run time in
dp_display_mode_set.

Signed-off-by: Paloma Arellano 
Reviewed-by: Dmitry Baryshkov 
---
 drivers/gpu/drm/msm/dp/dp_display.c | 17 +
 drivers/gpu/drm/msm/dp/dp_panel.h   |  1 +
 2 files changed, 14 insertions(+), 4 deletions(-)

diff --git a/drivers/gpu/drm/msm/dp/dp_display.c 
b/drivers/gpu/drm/msm/dp/dp_display.c
index 9df2a8b21021e..ddac55f45a722 100644
--- a/drivers/gpu/drm/msm/dp/dp_display.c
+++ b/drivers/gpu/drm/msm/dp/dp_display.c
@@ -784,10 +784,6 @@ static int dp_init_sub_modules(struct dp_display_private 
*dp)
goto error_ctrl;
}
 
-   /* populate wide_bus_supported to different layers */
-   dp->ctrl->wide_bus_en = dp->wide_bus_supported;
-   dp->catalog->wide_bus_en = dp->wide_bus_supported;
-
return rc;
 
 error_ctrl:
@@ -808,6 +804,7 @@ static int dp_display_set_mode(struct msm_dp *dp_display,
drm_mode_copy(>panel->dp_mode.drm_mode, >drm_mode);
dp->panel->dp_mode.bpp = mode->bpp;
dp->panel->dp_mode.capabilities = mode->capabilities;
+   dp->panel->dp_mode.out_fmt_is_yuv_420 = mode->out_fmt_is_yuv_420;
dp_panel_init_panel_info(dp->panel);
return 0;
 }
@@ -1402,6 +1399,9 @@ bool msm_dp_wide_bus_available(const struct msm_dp 
*dp_display)
 
dp = container_of(dp_display, struct dp_display_private, dp_display);
 
+   if (dp->dp_mode.out_fmt_is_yuv_420)
+   return false;
+
return dp->wide_bus_supported;
 }
 
@@ -1615,6 +1615,15 @@ void dp_bridge_mode_set(struct drm_bridge *drm_bridge,
 
dp_display->dp_mode.h_active_low =
!!(dp_display->dp_mode.drm_mode.flags & DRM_MODE_FLAG_NHSYNC);
+
+   dp_display->dp_mode.out_fmt_is_yuv_420 =
+   drm_mode_is_420_only(>connector->display_info, 
adjusted_mode);
+
+   /* populate wide_bus_support to different layers */
+   dp_display->ctrl->wide_bus_en =
+   dp_display->dp_mode.out_fmt_is_yuv_420 ? false : 
dp_display->wide_bus_supported;
+   dp_display->catalog->wide_bus_en =
+   dp_display->dp_mode.out_fmt_is_yuv_420 ? false : 
dp_display->wide_bus_supported;
 }
 
 void dp_bridge_hpd_enable(struct drm_bridge *bridge)
diff --git a/drivers/gpu/drm/msm/dp/dp_panel.h 
b/drivers/gpu/drm/msm/dp/dp_panel.h
index a0dfc579c5f9f..6ec68be9f2366 100644
--- a/drivers/gpu/drm/msm/dp/dp_panel.h
+++ b/drivers/gpu/drm/msm/dp/dp_panel.h
@@ -19,6 +19,7 @@ struct dp_display_mode {
u32 bpp;
u32 h_active_low;
u32 v_active_low;
+   bool out_fmt_is_yuv_420;
 };
 
 struct dp_panel_in {
-- 
2.39.2



[PATCH v3 05/19] drm/msm/dpu: move dpu_encoder_helper_phys_setup_cdm to dpu_encoder

2024-02-14 Thread Paloma Arellano
Move dpu_encoder_helper_phys_setup_cdm to dpu_encoder in preparation for
implementing YUV420 over DP, which requires CDM compatibility.

Changes in v2:
- Slightly change the wording of the commit text to make clear
  that YUV over DP requires CDM

Signed-off-by: Paloma Arellano 
Reviewed-by: Dmitry Baryshkov 
---
 drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c   | 78 +
 .../gpu/drm/msm/disp/dpu1/dpu_encoder_phys.h  |  9 ++
 .../drm/msm/disp/dpu1/dpu_encoder_phys_wb.c   | 83 ---
 3 files changed, 87 insertions(+), 83 deletions(-)

diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c 
b/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c
index 467f874979d5c..3c55d6290b708 100644
--- a/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c
+++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c
@@ -2121,6 +2121,84 @@ void dpu_encoder_helper_phys_cleanup(struct 
dpu_encoder_phys *phys_enc)
ctl->ops.clear_pending_flush(ctl);
 }
 
+void dpu_encoder_helper_phys_setup_cdm(struct dpu_encoder_phys *phys_enc,
+  const struct dpu_format *dpu_fmt,
+  u32 output_type)
+{
+   struct dpu_hw_cdm *hw_cdm;
+   struct dpu_hw_cdm_cfg *cdm_cfg;
+   struct dpu_hw_pingpong *hw_pp;
+   int ret;
+
+   if (!phys_enc)
+   return;
+
+   cdm_cfg = _enc->cdm_cfg;
+   hw_pp = phys_enc->hw_pp;
+   hw_cdm = phys_enc->hw_cdm;
+
+   if (!hw_cdm)
+   return;
+
+   if (!DPU_FORMAT_IS_YUV(dpu_fmt)) {
+   DPU_DEBUG("[enc:%d] cdm_disable fmt:%x\n", 
DRMID(phys_enc->parent),
+ dpu_fmt->base.pixel_format);
+   if (hw_cdm->ops.bind_pingpong_blk)
+   hw_cdm->ops.bind_pingpong_blk(hw_cdm, PINGPONG_NONE);
+
+   return;
+   }
+
+   memset(cdm_cfg, 0, sizeof(struct dpu_hw_cdm_cfg));
+
+   cdm_cfg->output_width = phys_enc->cached_mode.hdisplay;
+   cdm_cfg->output_height = phys_enc->cached_mode.vdisplay;
+   cdm_cfg->output_fmt = dpu_fmt;
+   cdm_cfg->output_type = output_type;
+   cdm_cfg->output_bit_depth = DPU_FORMAT_IS_DX(dpu_fmt) ?
+   CDM_CDWN_OUTPUT_10BIT : CDM_CDWN_OUTPUT_8BIT;
+   cdm_cfg->csc_cfg = _csc10_rgb2yuv_601l;
+
+   /* enable 10 bit logic */
+   switch (cdm_cfg->output_fmt->chroma_sample) {
+   case DPU_CHROMA_RGB:
+   cdm_cfg->h_cdwn_type = CDM_CDWN_DISABLE;
+   cdm_cfg->v_cdwn_type = CDM_CDWN_DISABLE;
+   break;
+   case DPU_CHROMA_H2V1:
+   cdm_cfg->h_cdwn_type = CDM_CDWN_COSITE;
+   cdm_cfg->v_cdwn_type = CDM_CDWN_DISABLE;
+   break;
+   case DPU_CHROMA_420:
+   cdm_cfg->h_cdwn_type = CDM_CDWN_COSITE;
+   cdm_cfg->v_cdwn_type = CDM_CDWN_OFFSITE;
+   break;
+   case DPU_CHROMA_H1V2:
+   default:
+   DPU_ERROR("[enc:%d] unsupported chroma sampling type\n",
+ DRMID(phys_enc->parent));
+   cdm_cfg->h_cdwn_type = CDM_CDWN_DISABLE;
+   cdm_cfg->v_cdwn_type = CDM_CDWN_DISABLE;
+   break;
+   }
+
+   DPU_DEBUG("[enc:%d] cdm_enable:%d,%d,%X,%d,%d,%d,%d]\n",
+ DRMID(phys_enc->parent), cdm_cfg->output_width,
+ cdm_cfg->output_height, 
cdm_cfg->output_fmt->base.pixel_format,
+ cdm_cfg->output_type, cdm_cfg->output_bit_depth,
+ cdm_cfg->h_cdwn_type, cdm_cfg->v_cdwn_type);
+
+   if (hw_cdm->ops.enable) {
+   cdm_cfg->pp_id = hw_pp->idx;
+   ret = hw_cdm->ops.enable(hw_cdm, cdm_cfg);
+   if (ret < 0) {
+   DPU_ERROR("[enc:%d] failed to enable CDM; ret:%d\n",
+ DRMID(phys_enc->parent), ret);
+   return;
+   }
+   }
+}
+
 #ifdef CONFIG_DEBUG_FS
 static int _dpu_encoder_status_show(struct seq_file *s, void *data)
 {
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 204d7cc3c1de8..f43d57d9c74e1 100644
--- a/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder_phys.h
+++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder_phys.h
@@ -381,6 +381,15 @@ int dpu_encoder_helper_wait_for_irq(struct 
dpu_encoder_phys *phys_enc,
  */
 void dpu_encoder_helper_phys_cleanup(struct dpu_encoder_phys *phys_enc);
 
+/**
+ * dpu_encoder_helper_phys_setup_cdm - setup chroma down sampling block
+ * @phys_enc: Pointer to physical encoder
+ * @output_type: HDMI/WB
+ */
+void dpu_encoder_helper_phys_setup_cdm(struct dpu_encoder_phys *phys_enc,
+  const struct dpu_format *dpu_fmt,
+  u32 output_type);
+
 /**
  * dpu_encoder_vblank_callback - Notify virtual encoder of vblank IRQ reception
  * @drm_enc:Pointer to drm encoder structure
diff --git 

[PATCH v3 00/19] Add support for CDM over DP

2024-02-14 Thread Paloma Arellano
The Chroma Down Sampling (CDM) block is a hardware component in the DPU
pipeline that includes a CSC block capable of converting RGB input from
the DPU to YUV data.

This block can be used with either HDMI, DP, or writeback interfaces.
This series adds support for the CDM block to be used with DP in
YUV420 mode format.

This series allows selection of the YUV420 format for monitors which support
certain resolutions only in YUV420 thus unblocking the validation of many
other resolutions which were previously filtered out if the connector did
not support YUV420.

This was validated using a DP connected monitor requiring the use of
YUV420 format.

This series is dependent on [1], [2], and [3]:
[1] https://patchwork.freedesktop.org/series/118831/
[2] https://patchwork.freedesktop.org/series/129395/
[3] https://patchwork.freedesktop.org/series/129864/

Changes in v3:
- Change ordering of the header byte macros in dp_utils.h
- Create a new struct, msm_dp_sdp_with_parity
- Utilize drm_dp_vsc_sdp_pack() from a new added dependency of
  series [3] to pack the VSC SDP data into the new
  msm_dp_sdp_with_parity struct instead of packing only for
  YUV420
- Modify dp_catalog_panel_send_vsc_sdp() so that it sends the VSC SDP 
data
  using the new msm_dp_sdp_with_parity struct
- Clear up that the DP_MAINLINK_FLUSH_MODE_SDE_PERIPH_UPDATE macro is 
setting
  multiple bits and not just one
- Move the connector's ycbcr_420_allowed parameter so it is no longer
  dependent on if the dp_display is not eDP

Changes in v2:
- Minor formatting changes throughout
- Move 'fixes' patch to the top
- Move VSC SDP support check API from dp_panel.c to drm_dp_helper.c
- Create a separate patch for modifying the dimensions for CDM setup to 
be
  non-WB specific
- Remove a patch that modified the INTF_CONFIG2 register in favor of 
having
  this series be dependent on [2]
- Separate configuration ctrl programming from clock related 
programming into
  two patches
- Add a VSC SDP check in dp_bridge_mode_valid()
- Move parity calculation functions to new files dp_utils.c and 
dp_utils.h
- Remove dp_catalog_hw_revision() changes and utilize the original 
version of
  the function when checking the DP hardware version
- Create separate packing and programming functions for the VSC SDP
- Make the packing header bytes function generic so it can be used with
  dp_audio.c
- Create two separate enable/disable VSC SDP functions instead of 
having one
  with the ability to do both
- Move timing engine programming to a separate patch from original 
encoder
  programming patch
- Move update_pending_flush_periph() code to be in the same patch as the
  encoder programming
- Create new API's to check if the dpu encoder needs a peripheral flush
- Allow YUV420 modes for the DP connector when there's a CDM block 
available
  instead of checking if VSC SDP is supported

Kuogee Hsieh (1):
  drm/msm/dpu: add support of new peripheral flush mechanism

Paloma Arellano (18):
  drm/msm/dpu: allow certain formats for CDM for DP
  drm/msm/dpu: add division of drm_display_mode's hskew parameter
  drm/msm/dpu: pass mode dimensions instead of fb size in CDM setup
  drm/msm/dpu: allow dpu_encoder_helper_phys_setup_cdm to work for DP
  drm/msm/dpu: move dpu_encoder_helper_phys_setup_cdm to dpu_encoder
  drm/msm/dp: rename wide_bus_en to wide_bus_supported
  drm/msm/dp: store mode YUV420 information to be used by rest of DP
  drm/msm/dp: check if VSC SDP is supported in DP programming
  drm/msm/dpu: move widebus logic to its own API
  drm/msm/dp: program config ctrl for YUV420 over DP
  drm/msm/dp: change clock related programming for YUV420 over DP
  drm/msm/dp: move parity calculation to dp_utils
  drm/msm/dp: add VSC SDP support for YUV420 over DP
  drm/msm/dp: enable SDP and SDE periph flush update
  drm/msm/dpu: modify encoder programming for CDM over DP
  drm/msm/dpu: modify timing engine programming for YUV420 over DP
  drm/msm/dpu: reserve CDM blocks for DP if mode is YUV420
  drm/msm/dp: allow YUV420 mode for DP connector when CDM available

 drivers/gpu/drm/msm/Makefile  |   3 +-
 drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c   | 164 +++---
 drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.h   |   4 +
 .../gpu/drm/msm/disp/dpu1/dpu_encoder_phys.h  |  26 ++-
 .../drm/msm/disp/dpu1/dpu_encoder_phys_vid.c  |  33 +++-
 .../drm/msm/disp/dpu1/dpu_encoder_phys_wb.c   | 100 +--
 drivers/gpu/drm/msm/disp/dpu1/dpu_hw_cdm.c|   2 +-
 drivers/gpu/drm/msm/disp/dpu1/dpu_hw_ctl.c|  17 ++
 drivers/gpu/drm/msm/disp/dpu1/dpu_hw_ctl.h|  10 ++
 drivers/gpu/drm/msm/disp/dpu1/dpu_kms.c   |   4 +-
 drivers/gpu/drm/msm/dp/dp_audio.c | 101 

[PATCH v3 01/19] drm/msm/dpu: allow certain formats for CDM for DP

2024-02-14 Thread Paloma Arellano
CDM block supports formats other than H1V2 for DP. Since we are now
adding support for CDM over DP, relax the checks to allow all other
formats for DP other than H1V2.

Changes in v2:
- Add fixes tag
- Move patch to top of series

Fixes: 0afac0ba6024 ("drm/msm/dpu: add dpu_hw_cdm abstraction for CDM block")
Signed-off-by: Paloma Arellano 
Reviewed-by: Dmitry Baryshkov 
---
 drivers/gpu/drm/msm/disp/dpu1/dpu_hw_cdm.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_cdm.c 
b/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_cdm.c
index e9cdc7934a499..9016b3ade6bc3 100644
--- a/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_cdm.c
+++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_cdm.c
@@ -186,7 +186,7 @@ static int dpu_hw_cdm_enable(struct dpu_hw_cdm *ctx, struct 
dpu_hw_cdm_cfg *cdm)
dpu_hw_cdm_setup_cdwn(ctx, cdm);
 
if (cdm->output_type == CDM_CDWN_OUTPUT_HDMI) {
-   if (fmt->chroma_sample != DPU_CHROMA_H1V2)
+   if (fmt->chroma_sample == DPU_CHROMA_H1V2)
return -EINVAL; /*unsupported format */
opmode = CDM_HDMI_PACK_OP_MODE_EN;
opmode |= (fmt->chroma_sample << 1);
-- 
2.39.2



[PATCH v3 03/19] drm/msm/dpu: pass mode dimensions instead of fb size in CDM setup

2024-02-14 Thread Paloma Arellano
Modify the output width and height parameters of hw_cdm to utilize the
physical encoder's data instead of obtaining the information from the
framebuffer. CDM is to be set up to utilize the actual output data since
at CDM setup, there is no difference between the two sources.

Changes in v2:
- Move the modification of the dimensions for CDM setup to this
  new patch

Signed-off-by: Paloma Arellano 
Reviewed-by: Dmitry Baryshkov 
---
 drivers/gpu/drm/msm/disp/dpu1/dpu_encoder_phys_wb.c | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder_phys_wb.c 
b/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder_phys_wb.c
index 4cd2d9e3131a4..ec9e053d3947d 100644
--- a/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder_phys_wb.c
+++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder_phys_wb.c
@@ -306,8 +306,8 @@ static void dpu_encoder_helper_phys_setup_cdm(struct 
dpu_encoder_phys *phys_enc)
 
memset(cdm_cfg, 0, sizeof(struct dpu_hw_cdm_cfg));
 
-   cdm_cfg->output_width = wb_job->fb->width;
-   cdm_cfg->output_height = wb_job->fb->height;
+   cdm_cfg->output_width = phys_enc->cached_mode.hdisplay;
+   cdm_cfg->output_height = phys_enc->cached_mode.vdisplay;
cdm_cfg->output_fmt = dpu_fmt;
cdm_cfg->output_type = CDM_CDWN_OUTPUT_WB;
cdm_cfg->output_bit_depth = DPU_FORMAT_IS_DX(dpu_fmt) ?
-- 
2.39.2



[PATCH v3 08/19] drm/msm/dp: check if VSC SDP is supported in DP programming

2024-02-14 Thread Paloma Arellano
In the DP driver, check if VSC SDP is supported and propagate this value
to dp_panel. In dp_display's dp_mode, the out_fmt_is_yuv_420 parameter
must also utilize this value since YUV420 is only allowed when VSC SDP
is supported.

Changes in v2:
- Move DP programming when VSC SDP is supported to this patch

Signed-off-by: Paloma Arellano 
Reviewed-by: Dmitry Baryshkov 
---
 drivers/gpu/drm/msm/dp/dp_display.c | 5 -
 drivers/gpu/drm/msm/dp/dp_panel.c   | 1 +
 drivers/gpu/drm/msm/dp/dp_panel.h   | 1 +
 3 files changed, 6 insertions(+), 1 deletion(-)

diff --git a/drivers/gpu/drm/msm/dp/dp_display.c 
b/drivers/gpu/drm/msm/dp/dp_display.c
index ddac55f45a722..6323dc08d5eb8 100644
--- a/drivers/gpu/drm/msm/dp/dp_display.c
+++ b/drivers/gpu/drm/msm/dp/dp_display.c
@@ -1595,8 +1595,10 @@ void dp_bridge_mode_set(struct drm_bridge *drm_bridge,
struct msm_dp_bridge *dp_bridge = to_dp_bridge(drm_bridge);
struct msm_dp *dp = dp_bridge->dp_display;
struct dp_display_private *dp_display;
+   struct dp_panel *dp_panel;
 
dp_display = container_of(dp, struct dp_display_private, dp_display);
+   dp_panel = dp_display->panel;
 
memset(_display->dp_mode, 0x0, sizeof(struct dp_display_mode));
 
@@ -1617,7 +1619,8 @@ void dp_bridge_mode_set(struct drm_bridge *drm_bridge,
!!(dp_display->dp_mode.drm_mode.flags & DRM_MODE_FLAG_NHSYNC);
 
dp_display->dp_mode.out_fmt_is_yuv_420 =
-   drm_mode_is_420_only(>connector->display_info, 
adjusted_mode);
+   drm_mode_is_420_only(>connector->display_info, 
adjusted_mode) &&
+   dp_panel->vsc_sdp_supported;
 
/* populate wide_bus_support to different layers */
dp_display->ctrl->wide_bus_en =
diff --git a/drivers/gpu/drm/msm/dp/dp_panel.c 
b/drivers/gpu/drm/msm/dp/dp_panel.c
index 127f6af995cd1..db1942794f1a4 100644
--- a/drivers/gpu/drm/msm/dp/dp_panel.c
+++ b/drivers/gpu/drm/msm/dp/dp_panel.c
@@ -53,6 +53,7 @@ static int dp_panel_read_dpcd(struct dp_panel *dp_panel)
if (rc)
return rc;
 
+   dp_panel->vsc_sdp_supported = drm_dp_vsc_sdp_supported(panel->aux, 
dpcd);
link_info = _panel->link_info;
link_info->revision = dpcd[DP_DPCD_REV];
major = (link_info->revision >> 4) & 0x0f;
diff --git a/drivers/gpu/drm/msm/dp/dp_panel.h 
b/drivers/gpu/drm/msm/dp/dp_panel.h
index 6ec68be9f2366..e843f5062d1f6 100644
--- a/drivers/gpu/drm/msm/dp/dp_panel.h
+++ b/drivers/gpu/drm/msm/dp/dp_panel.h
@@ -46,6 +46,7 @@ struct dp_panel {
struct dp_display_mode dp_mode;
struct dp_panel_psr psr_cap;
bool video_test;
+   bool vsc_sdp_supported;
 
u32 vic;
u32 max_dp_lanes;
-- 
2.39.2



[PATCH v3 06/19] drm/msm/dp: rename wide_bus_en to wide_bus_supported

2024-02-14 Thread Paloma Arellano
Rename wide_bus_en to wide_bus_supported in dp_display_private to
correctly establish that the parameter is referencing if wide bus is
supported instead of enabled.

Signed-off-by: Paloma Arellano 
Reviewed-by: Dmitry Baryshkov 
---
 drivers/gpu/drm/msm/dp/dp_display.c | 42 ++---
 1 file changed, 21 insertions(+), 21 deletions(-)

diff --git a/drivers/gpu/drm/msm/dp/dp_display.c 
b/drivers/gpu/drm/msm/dp/dp_display.c
index d37d599aec273..9df2a8b21021e 100644
--- a/drivers/gpu/drm/msm/dp/dp_display.c
+++ b/drivers/gpu/drm/msm/dp/dp_display.c
@@ -113,7 +113,7 @@ struct dp_display_private {
struct dp_event event_list[DP_EVENT_Q_MAX];
spinlock_t event_lock;
 
-   bool wide_bus_en;
+   bool wide_bus_supported;
 
struct dp_audio *audio;
 };
@@ -122,7 +122,7 @@ struct msm_dp_desc {
phys_addr_t io_start;
unsigned int id;
unsigned int connector_type;
-   bool wide_bus_en;
+   bool wide_bus_supported;
 };
 
 static const struct msm_dp_desc sc7180_dp_descs[] = {
@@ -131,8 +131,8 @@ static const struct msm_dp_desc sc7180_dp_descs[] = {
 };
 
 static const struct msm_dp_desc sc7280_dp_descs[] = {
-   { .io_start = 0x0ae9, .id = MSM_DP_CONTROLLER_0, .connector_type = 
DRM_MODE_CONNECTOR_DisplayPort, .wide_bus_en = true },
-   { .io_start = 0x0aea, .id = MSM_DP_CONTROLLER_1, .connector_type = 
DRM_MODE_CONNECTOR_eDP, .wide_bus_en = true },
+   { .io_start = 0x0ae9, .id = MSM_DP_CONTROLLER_0, .connector_type = 
DRM_MODE_CONNECTOR_DisplayPort, .wide_bus_supported = true },
+   { .io_start = 0x0aea, .id = MSM_DP_CONTROLLER_1, .connector_type = 
DRM_MODE_CONNECTOR_eDP, .wide_bus_supported = true },
{}
 };
 
@@ -144,22 +144,22 @@ static const struct msm_dp_desc sc8180x_dp_descs[] = {
 };
 
 static const struct msm_dp_desc sc8280xp_dp_descs[] = {
-   { .io_start = 0x0ae9, .id = MSM_DP_CONTROLLER_0, .connector_type = 
DRM_MODE_CONNECTOR_DisplayPort, .wide_bus_en = true },
-   { .io_start = 0x0ae98000, .id = MSM_DP_CONTROLLER_1, .connector_type = 
DRM_MODE_CONNECTOR_DisplayPort, .wide_bus_en = true },
-   { .io_start = 0x0ae9a000, .id = MSM_DP_CONTROLLER_2, .connector_type = 
DRM_MODE_CONNECTOR_DisplayPort, .wide_bus_en = true },
-   { .io_start = 0x0aea, .id = MSM_DP_CONTROLLER_3, .connector_type = 
DRM_MODE_CONNECTOR_DisplayPort, .wide_bus_en = true },
-   { .io_start = 0x2209, .id = MSM_DP_CONTROLLER_0, .connector_type = 
DRM_MODE_CONNECTOR_DisplayPort, .wide_bus_en = true },
-   { .io_start = 0x22098000, .id = MSM_DP_CONTROLLER_1, .connector_type = 
DRM_MODE_CONNECTOR_DisplayPort, .wide_bus_en = true },
-   { .io_start = 0x2209a000, .id = MSM_DP_CONTROLLER_2, .connector_type = 
DRM_MODE_CONNECTOR_DisplayPort, .wide_bus_en = true },
-   { .io_start = 0x220a, .id = MSM_DP_CONTROLLER_3, .connector_type = 
DRM_MODE_CONNECTOR_DisplayPort, .wide_bus_en = true },
+   { .io_start = 0x0ae9, .id = MSM_DP_CONTROLLER_0, .connector_type = 
DRM_MODE_CONNECTOR_DisplayPort, .wide_bus_supported = true },
+   { .io_start = 0x0ae98000, .id = MSM_DP_CONTROLLER_1, .connector_type = 
DRM_MODE_CONNECTOR_DisplayPort, .wide_bus_supported = true },
+   { .io_start = 0x0ae9a000, .id = MSM_DP_CONTROLLER_2, .connector_type = 
DRM_MODE_CONNECTOR_DisplayPort, .wide_bus_supported = true },
+   { .io_start = 0x0aea, .id = MSM_DP_CONTROLLER_3, .connector_type = 
DRM_MODE_CONNECTOR_DisplayPort, .wide_bus_supported = true },
+   { .io_start = 0x2209, .id = MSM_DP_CONTROLLER_0, .connector_type = 
DRM_MODE_CONNECTOR_DisplayPort, .wide_bus_supported = true },
+   { .io_start = 0x22098000, .id = MSM_DP_CONTROLLER_1, .connector_type = 
DRM_MODE_CONNECTOR_DisplayPort, .wide_bus_supported = true },
+   { .io_start = 0x2209a000, .id = MSM_DP_CONTROLLER_2, .connector_type = 
DRM_MODE_CONNECTOR_DisplayPort, .wide_bus_supported = true },
+   { .io_start = 0x220a, .id = MSM_DP_CONTROLLER_3, .connector_type = 
DRM_MODE_CONNECTOR_DisplayPort, .wide_bus_supported = true },
{}
 };
 
 static const struct msm_dp_desc sc8280xp_edp_descs[] = {
-   { .io_start = 0x0ae9a000, .id = MSM_DP_CONTROLLER_2, .connector_type = 
DRM_MODE_CONNECTOR_eDP, .wide_bus_en = true },
-   { .io_start = 0x0aea, .id = MSM_DP_CONTROLLER_3, .connector_type = 
DRM_MODE_CONNECTOR_eDP, .wide_bus_en = true },
-   { .io_start = 0x2209a000, .id = MSM_DP_CONTROLLER_2, .connector_type = 
DRM_MODE_CONNECTOR_eDP, .wide_bus_en = true },
-   { .io_start = 0x220a, .id = MSM_DP_CONTROLLER_3, .connector_type = 
DRM_MODE_CONNECTOR_eDP, .wide_bus_en = true },
+   { .io_start = 0x0ae9a000, .id = MSM_DP_CONTROLLER_2, .connector_type = 
DRM_MODE_CONNECTOR_eDP, .wide_bus_supported = true },
+   { .io_start = 0x0aea, .id = MSM_DP_CONTROLLER_3, .connector_type = 
DRM_MODE_CONNECTOR_eDP, .wide_bus_supported = true },
+   { .io_start = 0x2209a000, .id = 

Re: [PATCH] drm/dp: move intel_dp_vsc_sdp_pack() to generic helper

2024-02-14 Thread Ville Syrjälä
On Wed, Feb 14, 2024 at 09:17:34AM -0800, Abhinav Kumar wrote:
> 
> 
> On 2/14/2024 12:15 AM, Dmitry Baryshkov wrote:
> > On Wed, 14 Feb 2024 at 01:45, Abhinav Kumar  
> > wrote:
> >>
> >> intel_dp_vsc_sdp_pack() can be re-used by other DRM drivers as well.
> >> Lets move this to drm_dp_helper to achieve this.
> >>
> >> Signed-off-by: Abhinav Kumar 
> > 
> > My preference would be to have packing functions in
> > drivers/video/hdmi.c, as we already have
> > hdmi_audio_infoframe_pack_for_dp() there.
> > 
> 
> My preference is drm_dp_helper because it already has some VSC SDP stuff 
> and after discussion with Ville on IRC, I decided to post it this way.
> 
> hdmi_audio_infoframe_pack_for_dp() is an exception from my PoV as the 
> hdmi audio infoframe fields were re-used and packed into a DP SDP 
> thereby re-using the existing struct hdmi_audio_infoframe .
> 
> This is not like that. Here we pack from struct drm_dp_vsc_sdp to struct 
> dp_sdp both of which had prior usages already in this file.
> 
> So it all adds up and makes sense to me to be in this file.
> 
> I will let the other DRM core maintainers comment on this.
> 
> Ville, Jani?

Yeah, I'm not sure bloating the (poorly named) hdmi.c with all
SDP stuff is a great idea. Since other related stuff already
lives in the drm_dp_helper.c that seems reasonable to me at this
time. And if we get a decent amount of this then probably all
DP SDP stuff should be extracted into its own file.

There are of course a few overlaps here andthere (the audio SDP
I guess, and the CTA infoframe SDP). But I'm not sure that actually
needs any SDP specific stuff in hdmi.c, or could we just let hdmi.c
deal with the actual CTA-861 stuff and then have the DP SDP code
wrap that up in its own thing externally? Dunno, haven't really
looked at the details.

> 
> >> ---
> >>   drivers/gpu/drm/display/drm_dp_helper.c | 78 +
> >>   drivers/gpu/drm/i915/display/intel_dp.c | 73 +--
> >>   include/drm/display/drm_dp_helper.h |  3 +
> >>   3 files changed, 84 insertions(+), 70 deletions(-)
> >>
> >> diff --git a/drivers/gpu/drm/display/drm_dp_helper.c 
> >> b/drivers/gpu/drm/display/drm_dp_helper.c
> >> index b1ca3a1100da..066cfbbf7a91 100644
> >> --- a/drivers/gpu/drm/display/drm_dp_helper.c
> >> +++ b/drivers/gpu/drm/display/drm_dp_helper.c
> >> @@ -2916,6 +2916,84 @@ void drm_dp_vsc_sdp_log(const char *level, struct 
> >> device *dev,
> >>   }
> >>   EXPORT_SYMBOL(drm_dp_vsc_sdp_log);
> >>
> >> +/**
> >> + * drm_dp_vsc_sdp_pack() - pack a given vsc sdp into generic dp_sdp
> >> + * @vsc: vsc sdp initialized according to its purpose as defined in
> >> + *   table 2-118 - table 2-120 in DP 1.4a specification
> >> + * @sdp: valid handle to the generic dp_sdp which will be packed
> >> + * @size: valid size of the passed sdp handle
> >> + *
> >> + * Returns length of sdp on success and error code on failure
> >> + */
> >> +ssize_t drm_dp_vsc_sdp_pack(const struct drm_dp_vsc_sdp *vsc,
> >> +   struct dp_sdp *sdp, size_t size)
> > 
> > I know that you are just moving the function. Maybe there can be
> > patch#2, which drops the size argument? The struct dp_sdp already has
> > a defined size. The i915 driver just passes sizeof(sdp), which is more
> > or less useless.
> > 
> 
> Yes this is a valid point, I also noticed this. I can post it on top of 
> this once we get an agreement and ack on this patch first.
> 
> >> +{
> >> +   size_t length = sizeof(struct dp_sdp);
> >> +
> >> +   if (size < length)
> >> +   return -ENOSPC;
> >> +
> >> +   memset(sdp, 0, size);
> >> +
> >> +   /*
> >> +* Prepare VSC Header for SU as per DP 1.4a spec, Table 2-119
> >> +* VSC SDP Header Bytes
> >> +*/
> >> +   sdp->sdp_header.HB0 = 0; /* Secondary-Data Packet ID = 0 */
> >> +   sdp->sdp_header.HB1 = vsc->sdp_type; /* Secondary-data Packet Type 
> >> */
> >> +   sdp->sdp_header.HB2 = vsc->revision; /* Revision Number */
> >> +   sdp->sdp_header.HB3 = vsc->length; /* Number of Valid Data Bytes */
> >> +
> >> +   if (vsc->revision == 0x6) {
> >> +   sdp->db[0] = 1;
> >> +   sdp->db[3] = 1;
> >> +   }
> >> +
> >> +   /*
> >> +* Revision 0x5 and revision 0x7 supports Pixel 
> >> Encoding/Colorimetry
> >> +* Format as per DP 1.4a spec and DP 2.0 respectively.
> >> +*/
> >> +   if (!(vsc->revision == 0x5 || vsc->revision == 0x7))
> >> +   goto out;
> >> +
> >> +   /* VSC SDP Payload for DB16 through DB18 */
> >> +   /* Pixel Encoding and Colorimetry Formats  */
> >> +   sdp->db[16] = (vsc->pixelformat & 0xf) << 4; /* DB16[7:4] */
> >> +   sdp->db[16] |= vsc->colorimetry & 0xf; /* DB16[3:0] */
> >> +
> >> +   switch (vsc->bpc) {
> >> +   case 6:
> >> +   /* 6bpc: 0x0 */
> >> +   break;
> >> +   case 8:
> >> +   sdp->db[17] = 0x1; /* 

Re: [PATCH v2] drm/msm/dpu: make "vblank timeout" more useful

2024-02-14 Thread Abhinav Kumar




On 2/8/2024 6:50 AM, Dmitry Baryshkov wrote:

We have several reports of vblank timeout messages. However after some
debugging it was found that there might be different causes to that.
To allow us to identify the DPU block that gets stuck, include the
actual CTL_FLUSH value into the timeout message and trigger the devcore
snapshot capture.

Signed-off-by: Dmitry Baryshkov 
---
Changes in v2:
- Added a call to msm_disp_snapshot_state() to trigger devcore dump
   (Abhinav)
- Link to v1: 
https://lore.kernel.org/r/20240106-fd-dpu-debug-timeout-v1-1-6d9762884...@linaro.org
---
  drivers/gpu/drm/msm/disp/dpu1/dpu_encoder_phys_vid.c | 3 ++-
  1 file changed, 2 insertions(+), 1 deletion(-)

diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder_phys_vid.c 
b/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder_phys_vid.c
index d0f56c5c4cce..a8d6165b3c0a 100644
--- a/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder_phys_vid.c
+++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder_phys_vid.c
@@ -489,7 +489,8 @@ static int dpu_encoder_phys_vid_wait_for_commit_done(
(hw_ctl->ops.get_flush_register(hw_ctl) == 0),
msecs_to_jiffies(50));
if (ret <= 0) {
-   DPU_ERROR("vblank timeout\n");
+   DPU_ERROR("vblank timeout: %x\n", 
hw_ctl->ops.get_flush_register(hw_ctl));
+   msm_disp_snapshot_state(phys_enc->parent->dev);



There is no rate limiting in this piece of code unfortunately. So this 
will flood the number of snapshots.


Short-term solution is you can go with a vblank_timeout_cnt and reset it 
in the enable() like other similar error counters.


long-term solution is we need to centralize these error locations to one 
single dpu_encoder_error_handler() with a single counter and the error 
handler will print out the error code along with the snapshot instead of 
the snapshot being called from all over the place.





return -ETIMEDOUT;
}
  


---
base-commit: 39676dfe52331dba909c617f213fdb21015c8d10
change-id: 20240106-fd-dpu-debug-timeout-e917f0bc8063

Best regards,


Re: [PATCH] drm/dp: move intel_dp_vsc_sdp_pack() to generic helper

2024-02-14 Thread Abhinav Kumar




On 2/14/2024 12:15 AM, Dmitry Baryshkov wrote:

On Wed, 14 Feb 2024 at 01:45, Abhinav Kumar  wrote:


intel_dp_vsc_sdp_pack() can be re-used by other DRM drivers as well.
Lets move this to drm_dp_helper to achieve this.

Signed-off-by: Abhinav Kumar 


My preference would be to have packing functions in
drivers/video/hdmi.c, as we already have
hdmi_audio_infoframe_pack_for_dp() there.



My preference is drm_dp_helper because it already has some VSC SDP stuff 
and after discussion with Ville on IRC, I decided to post it this way.


hdmi_audio_infoframe_pack_for_dp() is an exception from my PoV as the 
hdmi audio infoframe fields were re-used and packed into a DP SDP 
thereby re-using the existing struct hdmi_audio_infoframe .


This is not like that. Here we pack from struct drm_dp_vsc_sdp to struct 
dp_sdp both of which had prior usages already in this file.


So it all adds up and makes sense to me to be in this file.

I will let the other DRM core maintainers comment on this.

Ville, Jani?


---
  drivers/gpu/drm/display/drm_dp_helper.c | 78 +
  drivers/gpu/drm/i915/display/intel_dp.c | 73 +--
  include/drm/display/drm_dp_helper.h |  3 +
  3 files changed, 84 insertions(+), 70 deletions(-)

diff --git a/drivers/gpu/drm/display/drm_dp_helper.c 
b/drivers/gpu/drm/display/drm_dp_helper.c
index b1ca3a1100da..066cfbbf7a91 100644
--- a/drivers/gpu/drm/display/drm_dp_helper.c
+++ b/drivers/gpu/drm/display/drm_dp_helper.c
@@ -2916,6 +2916,84 @@ void drm_dp_vsc_sdp_log(const char *level, struct device 
*dev,
  }
  EXPORT_SYMBOL(drm_dp_vsc_sdp_log);

+/**
+ * drm_dp_vsc_sdp_pack() - pack a given vsc sdp into generic dp_sdp
+ * @vsc: vsc sdp initialized according to its purpose as defined in
+ *   table 2-118 - table 2-120 in DP 1.4a specification
+ * @sdp: valid handle to the generic dp_sdp which will be packed
+ * @size: valid size of the passed sdp handle
+ *
+ * Returns length of sdp on success and error code on failure
+ */
+ssize_t drm_dp_vsc_sdp_pack(const struct drm_dp_vsc_sdp *vsc,
+   struct dp_sdp *sdp, size_t size)


I know that you are just moving the function. Maybe there can be
patch#2, which drops the size argument? The struct dp_sdp already has
a defined size. The i915 driver just passes sizeof(sdp), which is more
or less useless.



Yes this is a valid point, I also noticed this. I can post it on top of 
this once we get an agreement and ack on this patch first.



+{
+   size_t length = sizeof(struct dp_sdp);
+
+   if (size < length)
+   return -ENOSPC;
+
+   memset(sdp, 0, size);
+
+   /*
+* Prepare VSC Header for SU as per DP 1.4a spec, Table 2-119
+* VSC SDP Header Bytes
+*/
+   sdp->sdp_header.HB0 = 0; /* Secondary-Data Packet ID = 0 */
+   sdp->sdp_header.HB1 = vsc->sdp_type; /* Secondary-data Packet Type */
+   sdp->sdp_header.HB2 = vsc->revision; /* Revision Number */
+   sdp->sdp_header.HB3 = vsc->length; /* Number of Valid Data Bytes */
+
+   if (vsc->revision == 0x6) {
+   sdp->db[0] = 1;
+   sdp->db[3] = 1;
+   }
+
+   /*
+* Revision 0x5 and revision 0x7 supports Pixel Encoding/Colorimetry
+* Format as per DP 1.4a spec and DP 2.0 respectively.
+*/
+   if (!(vsc->revision == 0x5 || vsc->revision == 0x7))
+   goto out;
+
+   /* VSC SDP Payload for DB16 through DB18 */
+   /* Pixel Encoding and Colorimetry Formats  */
+   sdp->db[16] = (vsc->pixelformat & 0xf) << 4; /* DB16[7:4] */
+   sdp->db[16] |= vsc->colorimetry & 0xf; /* DB16[3:0] */
+
+   switch (vsc->bpc) {
+   case 6:
+   /* 6bpc: 0x0 */
+   break;
+   case 8:
+   sdp->db[17] = 0x1; /* DB17[3:0] */
+   break;
+   case 10:
+   sdp->db[17] = 0x2;
+   break;
+   case 12:
+   sdp->db[17] = 0x3;
+   break;
+   case 16:
+   sdp->db[17] = 0x4;
+   break;
+   default:
+   WARN(1, "Missing case %d\n", vsc->bpc);
+   return -EINVAL;
+   }
+
+   /* Dynamic Range and Component Bit Depth */
+   if (vsc->dynamic_range == DP_DYNAMIC_RANGE_CTA)
+   sdp->db[17] |= 0x80;  /* DB17[7] */
+
+   /* Content Type */
+   sdp->db[18] = vsc->content_type & 0x7;
+
+out:
+   return length;
+}
+EXPORT_SYMBOL(drm_dp_vsc_sdp_pack);
+
  /**
   * drm_dp_get_pcon_max_frl_bw() - maximum frl supported by PCON
   * @dpcd: DisplayPort configuration data
diff --git a/drivers/gpu/drm/i915/display/intel_dp.c 
b/drivers/gpu/drm/i915/display/intel_dp.c
index f5ef95da5534..e94db51aeeb7 100644
--- a/drivers/gpu/drm/i915/display/intel_dp.c
+++ b/drivers/gpu/drm/i915/display/intel_dp.c
@@ -4110,73 +4110,6 @@ intel_dp_needs_vsc_sdp(const struct intel_crtc_state 
*crtc_state,
 return false;
  }

-static ssize_t 

Re: [PATCH v2 16/19] drm/msm/dpu: modify encoder programming for CDM over DP

2024-02-14 Thread Dmitry Baryshkov
On Wed, 14 Feb 2024 at 00:11, Abhinav Kumar  wrote:
>
>
>
> On 2/13/2024 1:16 PM, Dmitry Baryshkov wrote:
> > On Tue, 13 Feb 2024 at 23:10, Abhinav Kumar  
> > wrote:
> >>
> >>
> >>
> >> On 2/13/2024 11:31 AM, Dmitry Baryshkov wrote:
> >>> On Tue, 13 Feb 2024 at 20:46, Abhinav Kumar  
> >>> wrote:
> 
> 
> 
>  On 2/13/2024 10:23 AM, Dmitry Baryshkov wrote:
> > On Tue, 13 Feb 2024 at 19:32, Abhinav Kumar  
> > wrote:
> >>
> >>
> >>
> >> On 2/13/2024 3:18 AM, Dmitry Baryshkov wrote:
> >>> On Sat, 10 Feb 2024 at 03:53, Paloma Arellano 
> >>>  wrote:
> 
>  Adjust the encoder format programming in the case of video mode for 
>  DP
>  to accommodate CDM related changes.
> 
>  Changes in v2:
>  - Move timing engine programming to a separate patch 
>  from this
>    one
>  - Move update_pending_flush_periph() invocation 
>  completely to
>    this patch
>  - Change the logic of dpu_encoder_get_drm_fmt() so that 
>  it only
>    calls drm_mode_is_420_only() instead of doing 
>  additional
>    unnecessary checks
>  - Create new functions msm_dp_needs_periph_flush() and 
>  it's
>    supporting function dpu_encoder_needs_periph_flush() 
>  to check
>    if the mode is YUV420 and VSC SDP is enabled before 
>  doing a
>    peripheral flush
> 
>  Signed-off-by: Paloma Arellano 
>  ---
>   drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c   | 35 
>  +++
>   .../gpu/drm/msm/disp/dpu1/dpu_encoder_phys.h  | 13 +++
>   .../drm/msm/disp/dpu1/dpu_encoder_phys_vid.c  | 19 ++
>   drivers/gpu/drm/msm/dp/dp_display.c   | 18 ++
>   drivers/gpu/drm/msm/msm_drv.h | 17 -
>   5 files changed, 101 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 7e7796561009a..6280c6be6dca9 100644
>  --- a/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c
>  +++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c
>  @@ -222,6 +222,41 @@ static u32 dither_matrix[DITHER_MATRIX_SZ] = {
>  15, 7, 13, 5, 3, 11, 1, 9, 12, 4, 14, 6, 0, 8, 2, 10
>   };
> 
>  +u32 dpu_encoder_get_drm_fmt(struct dpu_encoder_phys *phys_enc)
>  +{
>  +   struct drm_encoder *drm_enc;
>  +   struct dpu_encoder_virt *dpu_enc;
>  +   struct drm_display_info *info;
>  +   struct drm_display_mode *mode;
>  +
>  +   drm_enc = phys_enc->parent;
>  +   dpu_enc = to_dpu_encoder_virt(drm_enc);
>  +   info = _enc->connector->display_info;
>  +   mode = _enc->cached_mode;
>  +
>  +   if (drm_mode_is_420_only(info, mode))
>  +   return DRM_FORMAT_YUV420;
>  +
>  +   return DRM_FORMAT_RGB888;
>  +}
>  +
>  +bool dpu_encoder_needs_periph_flush(struct dpu_encoder_phys 
>  *phys_enc)
>  +{
>  +   struct drm_encoder *drm_enc;
>  +   struct dpu_encoder_virt *dpu_enc;
>  +   struct msm_display_info *disp_info;
>  +   struct msm_drm_private *priv;
>  +   struct drm_display_mode *mode;
>  +
>  +   drm_enc = phys_enc->parent;
>  +   dpu_enc = to_dpu_encoder_virt(drm_enc);
>  +   disp_info = _enc->disp_info;
>  +   priv = drm_enc->dev->dev_private;
>  +   mode = _enc->cached_mode;
>  +
>  +   return phys_enc->hw_intf->cap->type == INTF_DP && 
>  phys_enc->hw_cdm &&
> >>>
> >>> Do we really need to check for phys_enc->hw_cdm here?
> >>>
> >>
> >> hmmm I dont think so. If CDM was not there, then after the last patch,
> >> YUV420 removes will not be present at all.
> >>
> >> The only other case I could think of was, if for some reason CDM was
> >> used by some other interface such as WB, then hw_cdm will not be 
> >> assigned.
> >>
> >> But, I think even for that msm_dp_needs_periph_flush() will take care 
> >> of
> >> it because we use the cached_mode which is assigned only in mode_set().
> >>
>  +  
>  msm_dp_needs_periph_flush(priv->dp[disp_info->h_tile_instance[0]], 
>  mode);
>  +}
> 
>   bool dpu_encoder_is_widebus_enabled(const struct drm_encoder 
>  *drm_enc)
>   {
>  diff 

Re: [PATCH v2] drm: ci: use clk_ignore_unused for apq8016

2024-02-14 Thread Helen Koike




On 14/02/2024 10:30, Helen Koike wrote:



On 14/02/2024 05:37, Dmitry Baryshkov wrote:

If the ADV7511 bridge driver is compiled as a module, while DRM_MSM is
built-in, the clk_disable_unused congests with the runtime PM handling
of the DSI PHY for the clk_prepare_lock(). This causes apq8016 runner to
fail without completing any jobs ([1]). Drop the BM_CMDLINE which
duplicate the command line from the .baremetal-igt-arm64 clause and
enforce the clk_ignore_unused kernelarg instead to make apq8016 runner
work.

[1] https://gitlab.freedesktop.org/drm/msm/-/jobs/54990475

Fixes: 0119c894ab0d ("drm: Add initial ci/ subdirectory")
Reviewed-by: Javier Martinez Canillas 
Signed-off-by: Dmitry Baryshkov 


Acked-by: Helen Koike 


Applied to drm-misc-next.

Regards,
Helen



Thanks
Helen


---

Changes in v2:
- Added a comment, describing the issue and a way to reproduce it
   (Javier)

---
  drivers/gpu/drm/ci/test.yml | 5 -
  1 file changed, 4 insertions(+), 1 deletion(-)

diff --git a/drivers/gpu/drm/ci/test.yml b/drivers/gpu/drm/ci/test.yml
index 7ffb620d7398..e64205286a27 100644
--- a/drivers/gpu/drm/ci/test.yml
+++ b/drivers/gpu/drm/ci/test.yml
@@ -119,7 +119,10 @@ msm:apq8016:
  DRIVER_NAME: msm
  BM_DTB: 
https://${PIPELINE_ARTIFACTS_BASE}/arm64/apq8016-sbc-usb-host.dtb

  GPU_VERSION: apq8016
-    BM_CMDLINE: "ip=dhcp console=ttyMSM0,115200n8 
$BM_KERNEL_EXTRA_ARGS root=/dev/nfs rw nfsrootdebug 
nfsroot=,tcp,nfsvers=4.2 init=/init $BM_KERNELARGS"
+    # disabling unused clocks congests with the MDSS runtime PM 
trying to

+    # disable those clocks and causes boot to fail.
+    # Reproducer: DRM_MSM=y, DRM_I2C_ADV7511=m
+    BM_KERNEL_EXTRA_ARGS: clk_ignore_unused
  RUNNER_TAG: google-freedreno-db410c
    script:
  - ./install/bare-metal/fastboot.sh


Re: drm/msm: DisplayPort regressions in 6.8-rc1

2024-02-14 Thread Johan Hovold
On Tue, Feb 13, 2024 at 10:00:13AM -0800, Abhinav Kumar wrote:

> I do agree that pm runtime eDP driver got merged that time but I think 
> the issue is either a combination of that along with DRM aux bridge 
> https://patchwork.freedesktop.org/series/122584/ OR just the latter as 
> even that went in around the same time.

Yes, indeed there was a lot of changes that went into the MSM drm driver
in 6.8-rc1 and since I have not tried to debug this myself I can't say
for sure which change or changes that triggered this regression (or
possibly regressions).

The fact that the USB-C/DP PHY appears to be involved
(/soc@0/phy@88eb000) could indeed point to the series you mentioned.

> Thats why perhaps this issue was not seen with the chromebooks we tested 
> on as they do not use pmic_glink (aux bridge).
> 
> So we will need to debug this on sc8280xp specifically or an equivalent 
> device which uses aux bridge.

I've hit the NULL-pointer deference three times now in the last few days
on the sc8280xp CRD. But since it doesn't trigger on every boot it seems
you need to go back to the series that could potentially have caused
this regression and review them again. There's clearly something quite
broken here.

> On 2/13/2024 3:42 AM, Johan Hovold wrote:

> > Since 6.8-rc1 the internal eDP display on the Lenovo ThinkPad X13s does
> > not always show up on boot.

> > [6.007872] [drm:drm_bridge_attach [drm]] *ERROR* failed to attach 
> > bridge /soc@0/phy@88eb000 to encoder TMDS-31: -16

> > and this can also manifest itself as a NULL-pointer dereference:
> > 
> > [7.339447] Unable to handle kernel NULL pointer dereference at 
> > virtual address 
> > 
> > [7.643705] pc : drm_bridge_attach+0x70/0x1a8 [drm]
> > [7.686415] lr : drm_aux_bridge_attach+0x24/0x38 [aux_bridge]
> > 
> > [7.769039] Call trace:
> > [7.771564]  drm_bridge_attach+0x70/0x1a8 [drm]
> > [7.776234]  drm_aux_bridge_attach+0x24/0x38 [aux_bridge]
> > [7.781782]  drm_bridge_attach+0x80/0x1a8 [drm]
> > [7.786454]  dp_bridge_init+0xa8/0x15c [msm]
> > [7.790856]  msm_dp_modeset_init+0x28/0xc4 [msm]
> > [7.795617]  _dpu_kms_drm_obj_init+0x19c/0x680 [msm]
> > [7.800731]  dpu_kms_hw_init+0x348/0x4c4 [msm]
> > [7.805306]  msm_drm_kms_init+0x84/0x324 [msm]
> > [7.809891]  msm_drm_bind+0x1d8/0x3a8 [msm]
> > [7.814196]  try_to_bring_up_aggregate_device+0x1f0/0x2f8
> > [7.819747]  __component_add+0xa4/0x18c
> > [7.823703]  component_add+0x14/0x20
> > [7.827389]  dp_display_probe+0x47c/0x568 [msm]
> > [7.832052]  platform_probe+0x68/0xd8
> > 
> > Users have also reported random crashes at boot since 6.8-rc1, and I've
> > been able to trigger hard crashes twice when testing an external display
> > (USB-C/DP), which may also be related to the DP regressions.

Johan


Re: drm/msm: DisplayPort regressions in 6.8-rc1

2024-02-14 Thread Linux regression tracking (Thorsten Leemhuis)
On 13.02.24 19:00, Abhinav Kumar wrote:
> 
> Thanks for the report.
> 
> I do agree that pm runtime eDP driver got merged that time but I think
> the issue is either a combination of that along with DRM aux bridge
> https://patchwork.freedesktop.org/series/122584/ OR just the latter as
> even that went in around the same time.

In that case allow me a stupid question from the cheap seats:

Is there anything affected users can do to help getting us closer to the
real problem? Like testing a specific commit or two before or after the
merge of one of those features for example? That might help to rule out
a few things.

Ciao, Thorsten

> Thats why perhaps this issue was not seen with the chromebooks we tested
> on as they do not use pmic_glink (aux bridge).
> 
> So we will need to debug this on sc8280xp specifically or an equivalent
> device which uses aux bridge.
> 
> On 2/13/2024 3:42 AM, Johan Hovold wrote:
>> Hi,
>>
>> Since 6.8-rc1 the internal eDP display on the Lenovo ThinkPad X13s does
>> not always show up on boot.
>>
>> The logs indicate problems with the runtime PM and eDP rework that went
>> into 6.8-rc1:
>>
>> [    6.006236] Console: switching to colour dummy device 80x25
>> [    6.007542] [drm:dpu_kms_hw_init:1048] dpu hardware
>> revision:0x8000
>> [    6.007872] [drm:drm_bridge_attach [drm]] *ERROR* failed to
>> attach bridge /soc@0/phy@88eb000 to encoder TMDS-31: -16
>> [    6.007934] [drm:dp_bridge_init [msm]] *ERROR* failed to attach
>> panel bridge: -16
>> [    6.007983] msm_dpu ae01000.display-controller:
>> [drm:msm_dp_modeset_init [msm]] *ERROR* failed to create dp bridge: -16
>> [    6.008030] [drm:_dpu_kms_initialize_displayport:588] [dpu
>> error]modeset_init failed for DP, rc = -16
>> [    6.008050] [drm:_dpu_kms_setup_displays:681] [dpu
>> error]initialize_DP failed, rc = -16
>> [    6.008068] [drm:dpu_kms_hw_init:1153] [dpu error]modeset init
>> failed: -16
>> [    6.008388] msm_dpu ae01000.display-controller:
>> [drm:msm_drm_kms_init [msm]] *ERROR* kms hw init failed: -16
>> 
>> and this can also manifest itself as a NULL-pointer dereference:
>>
>> [    7.339447] Unable to handle kernel NULL pointer dereference at
>> virtual address 
>> 
>> [    7.643705] pc : drm_bridge_attach+0x70/0x1a8 [drm]
>> [    7.686415] lr : drm_aux_bridge_attach+0x24/0x38 [aux_bridge]
>> 
>> [    7.769039] Call trace:
>> [    7.771564]  drm_bridge_attach+0x70/0x1a8 [drm]
>> [    7.776234]  drm_aux_bridge_attach+0x24/0x38 [aux_bridge]
>> [    7.781782]  drm_bridge_attach+0x80/0x1a8 [drm]
>> [    7.786454]  dp_bridge_init+0xa8/0x15c [msm]
>> [    7.790856]  msm_dp_modeset_init+0x28/0xc4 [msm]
>> [    7.795617]  _dpu_kms_drm_obj_init+0x19c/0x680 [msm]
>> [    7.800731]  dpu_kms_hw_init+0x348/0x4c4 [msm]
>> [    7.805306]  msm_drm_kms_init+0x84/0x324 [msm]
>> [    7.809891]  msm_drm_bind+0x1d8/0x3a8 [msm]
>> [    7.814196]  try_to_bring_up_aggregate_device+0x1f0/0x2f8
>> [    7.819747]  __component_add+0xa4/0x18c
>> [    7.823703]  component_add+0x14/0x20
>> [    7.827389]  dp_display_probe+0x47c/0x568 [msm]
>> [    7.832052]  platform_probe+0x68/0xd8
>>
>> Users have also reported random crashes at boot since 6.8-rc1, and I've
>> been able to trigger hard crashes twice when testing an external display
>> (USB-C/DP), which may also be related to the DP regressions.
>>
>> I've opened an issue here:
>>
>> https://gitlab.freedesktop.org/drm/msm/-/issues/51
>>
>> but I also want Thorsten's help to track this so that it gets fixed
>> before 6.8 is released.
>>
>> #regzbot introduced: v6.7..v6.8-rc1
>>
>> The following series is likely the culprit:
>>
>> 
>> https://lore.kernel.org/all/1701472789-25951-1-git-send-email-quic_khs...@quicinc.com/
>>
>> Johan
> 
> 


Re: [PATCH v2] drm: ci: use clk_ignore_unused for apq8016

2024-02-14 Thread Helen Koike




On 14/02/2024 05:37, Dmitry Baryshkov wrote:

If the ADV7511 bridge driver is compiled as a module, while DRM_MSM is
built-in, the clk_disable_unused congests with the runtime PM handling
of the DSI PHY for the clk_prepare_lock(). This causes apq8016 runner to
fail without completing any jobs ([1]). Drop the BM_CMDLINE which
duplicate the command line from the .baremetal-igt-arm64 clause and
enforce the clk_ignore_unused kernelarg instead to make apq8016 runner
work.

[1] https://gitlab.freedesktop.org/drm/msm/-/jobs/54990475

Fixes: 0119c894ab0d ("drm: Add initial ci/ subdirectory")
Reviewed-by: Javier Martinez Canillas 
Signed-off-by: Dmitry Baryshkov 


Acked-by: Helen Koike 

Thanks
Helen


---

Changes in v2:
- Added a comment, describing the issue and a way to reproduce it
   (Javier)

---
  drivers/gpu/drm/ci/test.yml | 5 -
  1 file changed, 4 insertions(+), 1 deletion(-)

diff --git a/drivers/gpu/drm/ci/test.yml b/drivers/gpu/drm/ci/test.yml
index 7ffb620d7398..e64205286a27 100644
--- a/drivers/gpu/drm/ci/test.yml
+++ b/drivers/gpu/drm/ci/test.yml
@@ -119,7 +119,10 @@ msm:apq8016:
  DRIVER_NAME: msm
  BM_DTB: https://${PIPELINE_ARTIFACTS_BASE}/arm64/apq8016-sbc-usb-host.dtb
  GPU_VERSION: apq8016
-BM_CMDLINE: "ip=dhcp console=ttyMSM0,115200n8 $BM_KERNEL_EXTRA_ARGS 
root=/dev/nfs rw nfsrootdebug nfsroot=,tcp,nfsvers=4.2 init=/init $BM_KERNELARGS"
+# disabling unused clocks congests with the MDSS runtime PM trying to
+# disable those clocks and causes boot to fail.
+# Reproducer: DRM_MSM=y, DRM_I2C_ADV7511=m
+BM_KERNEL_EXTRA_ARGS: clk_ignore_unused
  RUNNER_TAG: google-freedreno-db410c
script:
  - ./install/bare-metal/fastboot.sh


[PATCH v2] drm: ci: use clk_ignore_unused for apq8016

2024-02-14 Thread Dmitry Baryshkov
If the ADV7511 bridge driver is compiled as a module, while DRM_MSM is
built-in, the clk_disable_unused congests with the runtime PM handling
of the DSI PHY for the clk_prepare_lock(). This causes apq8016 runner to
fail without completing any jobs ([1]). Drop the BM_CMDLINE which
duplicate the command line from the .baremetal-igt-arm64 clause and
enforce the clk_ignore_unused kernelarg instead to make apq8016 runner
work.

[1] https://gitlab.freedesktop.org/drm/msm/-/jobs/54990475

Fixes: 0119c894ab0d ("drm: Add initial ci/ subdirectory")
Reviewed-by: Javier Martinez Canillas 
Signed-off-by: Dmitry Baryshkov 
---

Changes in v2:
- Added a comment, describing the issue and a way to reproduce it
  (Javier)

---
 drivers/gpu/drm/ci/test.yml | 5 -
 1 file changed, 4 insertions(+), 1 deletion(-)

diff --git a/drivers/gpu/drm/ci/test.yml b/drivers/gpu/drm/ci/test.yml
index 7ffb620d7398..e64205286a27 100644
--- a/drivers/gpu/drm/ci/test.yml
+++ b/drivers/gpu/drm/ci/test.yml
@@ -119,7 +119,10 @@ msm:apq8016:
 DRIVER_NAME: msm
 BM_DTB: https://${PIPELINE_ARTIFACTS_BASE}/arm64/apq8016-sbc-usb-host.dtb
 GPU_VERSION: apq8016
-BM_CMDLINE: "ip=dhcp console=ttyMSM0,115200n8 $BM_KERNEL_EXTRA_ARGS 
root=/dev/nfs rw nfsrootdebug nfsroot=,tcp,nfsvers=4.2 init=/init 
$BM_KERNELARGS"
+# disabling unused clocks congests with the MDSS runtime PM trying to
+# disable those clocks and causes boot to fail.
+# Reproducer: DRM_MSM=y, DRM_I2C_ADV7511=m
+BM_KERNEL_EXTRA_ARGS: clk_ignore_unused
 RUNNER_TAG: google-freedreno-db410c
   script:
 - ./install/bare-metal/fastboot.sh
-- 
2.39.2



Re: [PATCH] drm: ci: use clk_ignore_unused for apq8016

2024-02-14 Thread Javier Martinez Canillas
Dmitry Baryshkov  writes:

Hello Dmitry,

> If the ADV7511 bridge driver is compiled as a module, while DRM_MSM is
> built-in, the clk_disable_unused congests with the runtime PM handling
> of the DSI PHY for the clk_prepare_lock(). This causes apq8016 runner to
> fail without completing any jobs ([1]). Drop the BM_CMDLINE which
> duplicate the command line from the .baremetal-igt-arm64 clause and
> enforce the clk_ignore_unused kernelarg instead to make apq8016 runner
> work.
>

Agree that this is the only practical option for the short term...

> [1] https://gitlab.freedesktop.org/drm/msm/-/jobs/54990475
>
> Fixes: 0119c894ab0d ("drm: Add initial ci/ subdirectory")
> Signed-off-by: Dmitry Baryshkov 
> ---

Reviewed-by: Javier Martinez Canillas 

>  drivers/gpu/drm/ci/test.yml | 2 +-
>  1 file changed, 1 insertion(+), 1 deletion(-)
>
> diff --git a/drivers/gpu/drm/ci/test.yml b/drivers/gpu/drm/ci/test.yml
> index 355b794ef2b1..b9f864e062df 100644
> --- a/drivers/gpu/drm/ci/test.yml
> +++ b/drivers/gpu/drm/ci/test.yml
> @@ -119,7 +119,7 @@ msm:apq8016:
>  DRIVER_NAME: msm
>  BM_DTB: https://${PIPELINE_ARTIFACTS_BASE}/arm64/apq8016-sbc-usb-host.dtb
>  GPU_VERSION: apq8016
> -BM_CMDLINE: "ip=dhcp console=ttyMSM0,115200n8 $BM_KERNEL_EXTRA_ARGS 
> root=/dev/nfs rw nfsrootdebug nfsroot=,tcp,nfsvers=4.2 init=/init 
> $BM_KERNELARGS"

Maybe add a comment here explaining why the clk_ignore_unused param is
needed ? (basically what you have in your commit message), that way it
could be dropped once the underlying issue is fixed.

> +BM_KERNEL_EXTRA_ARGS: clk_ignore_unused
>  RUNNER_TAG: google-freedreno-db410c
>script:
>  - ./install/bare-metal/fastboot.sh
> -- 
> 2.39.2
>

-- 
Best regards,

Javier Martinez Canillas
Core Platforms
Red Hat



Re: [PATCH] drm/dp: move intel_dp_vsc_sdp_pack() to generic helper

2024-02-14 Thread Dmitry Baryshkov
On Wed, 14 Feb 2024 at 01:45, Abhinav Kumar  wrote:
>
> intel_dp_vsc_sdp_pack() can be re-used by other DRM drivers as well.
> Lets move this to drm_dp_helper to achieve this.
>
> Signed-off-by: Abhinav Kumar 

My preference would be to have packing functions in
drivers/video/hdmi.c, as we already have
hdmi_audio_infoframe_pack_for_dp() there.

> ---
>  drivers/gpu/drm/display/drm_dp_helper.c | 78 +
>  drivers/gpu/drm/i915/display/intel_dp.c | 73 +--
>  include/drm/display/drm_dp_helper.h |  3 +
>  3 files changed, 84 insertions(+), 70 deletions(-)
>
> diff --git a/drivers/gpu/drm/display/drm_dp_helper.c 
> b/drivers/gpu/drm/display/drm_dp_helper.c
> index b1ca3a1100da..066cfbbf7a91 100644
> --- a/drivers/gpu/drm/display/drm_dp_helper.c
> +++ b/drivers/gpu/drm/display/drm_dp_helper.c
> @@ -2916,6 +2916,84 @@ void drm_dp_vsc_sdp_log(const char *level, struct 
> device *dev,
>  }
>  EXPORT_SYMBOL(drm_dp_vsc_sdp_log);
>
> +/**
> + * drm_dp_vsc_sdp_pack() - pack a given vsc sdp into generic dp_sdp
> + * @vsc: vsc sdp initialized according to its purpose as defined in
> + *   table 2-118 - table 2-120 in DP 1.4a specification
> + * @sdp: valid handle to the generic dp_sdp which will be packed
> + * @size: valid size of the passed sdp handle
> + *
> + * Returns length of sdp on success and error code on failure
> + */
> +ssize_t drm_dp_vsc_sdp_pack(const struct drm_dp_vsc_sdp *vsc,
> +   struct dp_sdp *sdp, size_t size)

I know that you are just moving the function. Maybe there can be
patch#2, which drops the size argument? The struct dp_sdp already has
a defined size. The i915 driver just passes sizeof(sdp), which is more
or less useless.

> +{
> +   size_t length = sizeof(struct dp_sdp);
> +
> +   if (size < length)
> +   return -ENOSPC;
> +
> +   memset(sdp, 0, size);
> +
> +   /*
> +* Prepare VSC Header for SU as per DP 1.4a spec, Table 2-119
> +* VSC SDP Header Bytes
> +*/
> +   sdp->sdp_header.HB0 = 0; /* Secondary-Data Packet ID = 0 */
> +   sdp->sdp_header.HB1 = vsc->sdp_type; /* Secondary-data Packet Type */
> +   sdp->sdp_header.HB2 = vsc->revision; /* Revision Number */
> +   sdp->sdp_header.HB3 = vsc->length; /* Number of Valid Data Bytes */
> +
> +   if (vsc->revision == 0x6) {
> +   sdp->db[0] = 1;
> +   sdp->db[3] = 1;
> +   }
> +
> +   /*
> +* Revision 0x5 and revision 0x7 supports Pixel Encoding/Colorimetry
> +* Format as per DP 1.4a spec and DP 2.0 respectively.
> +*/
> +   if (!(vsc->revision == 0x5 || vsc->revision == 0x7))
> +   goto out;
> +
> +   /* VSC SDP Payload for DB16 through DB18 */
> +   /* Pixel Encoding and Colorimetry Formats  */
> +   sdp->db[16] = (vsc->pixelformat & 0xf) << 4; /* DB16[7:4] */
> +   sdp->db[16] |= vsc->colorimetry & 0xf; /* DB16[3:0] */
> +
> +   switch (vsc->bpc) {
> +   case 6:
> +   /* 6bpc: 0x0 */
> +   break;
> +   case 8:
> +   sdp->db[17] = 0x1; /* DB17[3:0] */
> +   break;
> +   case 10:
> +   sdp->db[17] = 0x2;
> +   break;
> +   case 12:
> +   sdp->db[17] = 0x3;
> +   break;
> +   case 16:
> +   sdp->db[17] = 0x4;
> +   break;
> +   default:
> +   WARN(1, "Missing case %d\n", vsc->bpc);
> +   return -EINVAL;
> +   }
> +
> +   /* Dynamic Range and Component Bit Depth */
> +   if (vsc->dynamic_range == DP_DYNAMIC_RANGE_CTA)
> +   sdp->db[17] |= 0x80;  /* DB17[7] */
> +
> +   /* Content Type */
> +   sdp->db[18] = vsc->content_type & 0x7;
> +
> +out:
> +   return length;
> +}
> +EXPORT_SYMBOL(drm_dp_vsc_sdp_pack);
> +
>  /**
>   * drm_dp_get_pcon_max_frl_bw() - maximum frl supported by PCON
>   * @dpcd: DisplayPort configuration data
> diff --git a/drivers/gpu/drm/i915/display/intel_dp.c 
> b/drivers/gpu/drm/i915/display/intel_dp.c
> index f5ef95da5534..e94db51aeeb7 100644
> --- a/drivers/gpu/drm/i915/display/intel_dp.c
> +++ b/drivers/gpu/drm/i915/display/intel_dp.c
> @@ -4110,73 +4110,6 @@ intel_dp_needs_vsc_sdp(const struct intel_crtc_state 
> *crtc_state,
> return false;
>  }
>
> -static ssize_t intel_dp_vsc_sdp_pack(const struct drm_dp_vsc_sdp *vsc,
> -struct dp_sdp *sdp, size_t size)
> -{
> -   size_t length = sizeof(struct dp_sdp);
> -
> -   if (size < length)
> -   return -ENOSPC;
> -
> -   memset(sdp, 0, size);
> -
> -   /*
> -* Prepare VSC Header for SU as per DP 1.4a spec, Table 2-119
> -* VSC SDP Header Bytes
> -*/
> -   sdp->sdp_header.HB0 = 0; /* Secondary-Data Packet ID = 0 */
> -   sdp->sdp_header.HB1 = vsc->sdp_type; /* Secondary-data Packet Type */
> -   sdp->sdp_header.HB2 = vsc->revision; /*