Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

Merge tag 'drm-msm-next-2023-06-18' of https://gitlab.freedesktop.org/drm/msm into drm-next

Updates for v6.5.. this includes a backmerg of drm-next tree to be able
to use new DRM DSC helpers.

Core:
+ Add Marijn Suijten as drm/msm reviewer
+ Adreno A660 bindings
+ SM8350 MDSS bindings fix
+ Fix adreno_is_a690() warnings
+ More generic (DRM) and MSM-specific DSC helpers

DP:
+ Removed obsolete USB-PD remains
+ Documented DP compatible string for sm8550 platform

DPU:
+ Enable missing features (DSPP, DSC, split display) on sc8180x,
sc8280xp, sm8450
+ Enabled writeback on sc7280
+ Implemented tearcheck support to support vsync on SM150 and
newer platforms
+ Native HDMI output support
+ Dropped unused features: regdma, GC, IGC
+ Fixed the DSC flush operations
+ Simplified QoS handling, removing obsolete and unused features
and merging SSPP and WB code paths
+ Reworked dpu_encoder initialisation path
+ Enabled DSPP support on sdm845
+ Disabled color-management if DSPP blocks are not available
+ Added support for DSC 1.2 blocks found on sm8350 and later
+ Added .fb_dirty to fix CMD panels

DSI:
+ Drop powerup quirks in favour of using pre_enable_prev_first for
downstream bridges
+ Fixed 14nm DSI PHY programming
+ Added support for DSI and 28nm DSI PHY on MSM8226 platform
+ Make use of DRM and MSM DSC helpers

MDP5:
+ Added support for display controller on MSM8226 platform

GPU:
+ A690 support
+ Don't set IO_PGTABLE_QUIRK_ARM_OUTER_WBWA on devices with coherent SMMU
(like A690)
+ Move cmdstream dumping out of fence signaling path
+ Cleanups
+ Support for a6xx devices without GMU (aka "GMU wrapper"
+ a610 support
+ a619_holi support (a619 variant without GMU)

Signed-off-by: Dave Airlie <airlied@redhat.com>
From: Rob Clark <robdclark@gmail.com>
Link: https://patchwork.freedesktop.org/patch/msgid/CAF6AEGsUB=tRB4nR6ZCJMuLhro5zN3BQWUSywVYbaipqqDZ_cQ@mail.gmail.com

+4451 -2502
+1
Documentation/devicetree/bindings/display/msm/dp-controller.yaml
··· 29 29 - items: 30 30 - enum: 31 31 - qcom,sm8450-dp 32 + - qcom,sm8550-dp 32 33 - const: qcom,sm8350-dp 33 34 34 35 reg:
+6
Documentation/devicetree/bindings/display/msm/dsi-controller-main.yaml
··· 15 15 - items: 16 16 - enum: 17 17 - qcom,apq8064-dsi-ctrl 18 + - qcom,msm8226-dsi-ctrl 18 19 - qcom,msm8916-dsi-ctrl 19 20 - qcom,msm8953-dsi-ctrl 20 21 - qcom,msm8974-dsi-ctrl ··· 27 26 - qcom,sdm660-dsi-ctrl 28 27 - qcom,sdm845-dsi-ctrl 29 28 - qcom,sm6115-dsi-ctrl 29 + - qcom,sm6350-dsi-ctrl 30 + - qcom,sm6375-dsi-ctrl 30 31 - qcom,sm8150-dsi-ctrl 31 32 - qcom,sm8250-dsi-ctrl 32 33 - qcom,sm8350-dsi-ctrl ··· 259 256 compatible: 260 257 contains: 261 258 enum: 259 + - qcom,msm8226-dsi-ctrl 262 260 - qcom,msm8974-dsi-ctrl 263 261 then: 264 262 properties: ··· 301 297 contains: 302 298 enum: 303 299 - qcom,msm8998-dsi-ctrl 300 + - qcom,sm6350-dsi-ctrl 304 301 then: 305 302 properties: 306 303 clocks: ··· 369 364 enum: 370 365 - qcom,sdm845-dsi-ctrl 371 366 - qcom,sm6115-dsi-ctrl 367 + - qcom,sm6375-dsi-ctrl 372 368 then: 373 369 properties: 374 370 clocks:
+2 -1
Documentation/devicetree/bindings/display/msm/dsi-phy-28nm.yaml
··· 15 15 properties: 16 16 compatible: 17 17 enum: 18 + - qcom,dsi-phy-28nm-8226 19 + - qcom,dsi-phy-28nm-8960 18 20 - qcom,dsi-phy-28nm-hpm 19 21 - qcom,dsi-phy-28nm-hpm-fam-b 20 22 - qcom,dsi-phy-28nm-lp 21 - - qcom,dsi-phy-28nm-8960 22 23 23 24 reg: 24 25 items:
+39 -12
Documentation/devicetree/bindings/display/msm/gmu.yaml
··· 19 19 20 20 properties: 21 21 compatible: 22 - items: 23 - - pattern: '^qcom,adreno-gmu-6[0-9][0-9]\.[0-9]$' 24 - - const: qcom,adreno-gmu 22 + oneOf: 23 + - items: 24 + - pattern: '^qcom,adreno-gmu-6[0-9][0-9]\.[0-9]$' 25 + - const: qcom,adreno-gmu 26 + - const: qcom,adreno-gmu-wrapper 25 27 26 28 reg: 27 - minItems: 3 29 + minItems: 1 28 30 maxItems: 4 29 31 30 32 reg-names: 31 - minItems: 3 33 + minItems: 1 32 34 maxItems: 4 33 35 34 36 clocks: ··· 45 43 items: 46 44 - description: GMU HFI interrupt 47 45 - description: GMU interrupt 48 - 49 46 50 47 interrupt-names: 51 48 items: ··· 73 72 - compatible 74 73 - reg 75 74 - reg-names 76 - - clocks 77 - - clock-names 78 - - interrupts 79 - - interrupt-names 80 75 - power-domains 81 76 - power-domain-names 82 - - iommus 83 - - operating-points-v2 84 77 85 78 additionalProperties: false 86 79 ··· 117 122 contains: 118 123 enum: 119 124 - qcom,adreno-gmu-635.0 125 + - qcom,adreno-gmu-660.1 120 126 then: 121 127 properties: 122 128 reg: ··· 213 217 - const: axi 214 218 - const: memnoc 215 219 220 + - if: 221 + properties: 222 + compatible: 223 + contains: 224 + const: qcom,adreno-gmu-wrapper 225 + then: 226 + properties: 227 + reg: 228 + items: 229 + - description: GMU wrapper register space 230 + reg-names: 231 + items: 232 + - const: gmu 233 + else: 234 + required: 235 + - clocks 236 + - clock-names 237 + - interrupts 238 + - interrupt-names 239 + - iommus 240 + - operating-points-v2 241 + 216 242 examples: 217 243 - | 218 244 #include <dt-bindings/clock/qcom,gpucc-sdm845.h> ··· 266 248 267 249 iommus = <&adreno_smmu 5>; 268 250 operating-points-v2 = <&gmu_opp_table>; 251 + }; 252 + 253 + gmu_wrapper: gmu@596a000 { 254 + compatible = "qcom,adreno-gmu-wrapper"; 255 + reg = <0x0596a000 0x30000>; 256 + reg-names = "gmu"; 257 + power-domains = <&gpucc GPU_CX_GDSC>, 258 + <&gpucc GPU_GX_GDSC>; 259 + power-domain-names = "cx", "gx"; 269 260 };
+52 -9
Documentation/devicetree/bindings/display/msm/gpu.yaml
··· 36 36 37 37 reg-names: 38 38 minItems: 1 39 - items: 40 - - const: kgsl_3d0_reg_memory 41 - - const: cx_mem 42 - - const: cx_dbgc 39 + maxItems: 3 43 40 44 41 interrupts: 45 42 maxItems: 1 ··· 154 157 required: 155 158 - clocks 156 159 - clock-names 160 + 157 161 - if: 158 162 properties: 159 163 compatible: 160 164 contains: 161 - pattern: '^qcom,adreno-6[0-9][0-9]\.[0-9]$' 162 - 163 - then: # Since Adreno 6xx series clocks should be defined in GMU 165 + enum: 166 + - qcom,adreno-610.0 167 + - qcom,adreno-619.1 168 + then: 164 169 properties: 165 - clocks: false 166 - clock-names: false 170 + clocks: 171 + minItems: 6 172 + maxItems: 6 173 + 174 + clock-names: 175 + items: 176 + - const: core 177 + description: GPU Core clock 178 + - const: iface 179 + description: GPU Interface clock 180 + - const: mem_iface 181 + description: GPU Memory Interface clock 182 + - const: alt_mem_iface 183 + description: GPU Alternative Memory Interface clock 184 + - const: gmu 185 + description: CX GMU clock 186 + - const: xo 187 + description: GPUCC clocksource clock 188 + 189 + reg-names: 190 + minItems: 1 191 + items: 192 + - const: kgsl_3d0_reg_memory 193 + - const: cx_dbgc 194 + 195 + required: 196 + - clocks 197 + - clock-names 198 + else: 199 + if: 200 + properties: 201 + compatible: 202 + contains: 203 + pattern: '^qcom,adreno-6[0-9][0-9]\.[0-9]$' 204 + 205 + then: # Starting with A6xx, the clocks are usually defined in the GMU node 206 + properties: 207 + clocks: false 208 + clock-names: false 209 + 210 + reg-names: 211 + minItems: 1 212 + items: 213 + - const: kgsl_3d0_reg_memory 214 + - const: cx_mem 215 + - const: cx_dbgc 167 216 168 217 examples: 169 218 - |
+1
Documentation/devicetree/bindings/display/msm/qcom,mdp5.yaml
··· 22 22 - items: 23 23 - enum: 24 24 - qcom,apq8084-mdp5 25 + - qcom,msm8226-mdp5 25 26 - qcom,msm8916-mdp5 26 27 - qcom,msm8917-mdp5 27 28 - qcom,msm8953-mdp5
+1
Documentation/devicetree/bindings/display/msm/qcom,mdss.yaml
··· 125 125 - qcom,dsi-phy-14nm-660 126 126 - qcom,dsi-phy-14nm-8953 127 127 - qcom,dsi-phy-20nm 128 + - qcom,dsi-phy-28nm-8226 128 129 - qcom,dsi-phy-28nm-hpm 129 130 - qcom,dsi-phy-28nm-lp 130 131 - qcom,hdmi-phy-8084
+22 -1
Documentation/devicetree/bindings/display/msm/qcom,sc7180-dpu.yaml
··· 13 13 14 14 properties: 15 15 compatible: 16 - const: qcom,sc7180-dpu 16 + enum: 17 + - qcom,sc7180-dpu 18 + - qcom,sm6350-dpu 19 + - qcom,sm6375-dpu 17 20 18 21 reg: 19 22 items: ··· 29 26 - const: vbif 30 27 31 28 clocks: 29 + minItems: 6 32 30 items: 33 31 - description: Display hf axi clock 34 32 - description: Display ahb clock ··· 37 33 - description: Display lut clock 38 34 - description: Display core clock 39 35 - description: Display vsync clock 36 + - description: Display core throttle clock 40 37 41 38 clock-names: 39 + minItems: 6 42 40 items: 43 41 - const: bus 44 42 - const: iface ··· 48 42 - const: lut 49 43 - const: core 50 44 - const: vsync 45 + - const: throttle 51 46 52 47 required: 53 48 - compatible ··· 58 51 - clock-names 59 52 60 53 unevaluatedProperties: false 54 + 55 + allOf: 56 + - if: 57 + properties: 58 + compatible: 59 + const: qcom,sm6375-dpu 60 + 61 + then: 62 + properties: 63 + clocks: 64 + minItems: 7 65 + 66 + clock-names: 67 + minItems: 7 61 68 62 69 examples: 63 70 - |
+213
Documentation/devicetree/bindings/display/msm/qcom,sm6350-mdss.yaml
··· 1 + # SPDX-License-Identifier: GPL-2.0-only or BSD-2-Clause 2 + %YAML 1.2 3 + --- 4 + $id: http://devicetree.org/schemas/display/msm/qcom,sm6350-mdss.yaml# 5 + $schema: http://devicetree.org/meta-schemas/core.yaml# 6 + 7 + title: Qualcomm SM6350 Display MDSS 8 + 9 + maintainers: 10 + - Krishna Manikandan <quic_mkrishn@quicinc.com> 11 + 12 + description: 13 + SM6350 MSM Mobile Display Subsystem (MDSS), which encapsulates sub-blocks 14 + like DPU display controller, DSI and DP interfaces etc. 15 + 16 + $ref: /schemas/display/msm/mdss-common.yaml# 17 + 18 + properties: 19 + compatible: 20 + const: qcom,sm6350-mdss 21 + 22 + clocks: 23 + items: 24 + - description: Display AHB clock from gcc 25 + - description: Display AXI clock from gcc 26 + - description: Display core clock 27 + 28 + clock-names: 29 + items: 30 + - const: iface 31 + - const: bus 32 + - const: core 33 + 34 + iommus: 35 + maxItems: 1 36 + 37 + interconnects: 38 + maxItems: 2 39 + 40 + interconnect-names: 41 + maxItems: 2 42 + 43 + patternProperties: 44 + "^display-controller@[0-9a-f]+$": 45 + type: object 46 + properties: 47 + compatible: 48 + const: qcom,sm6350-dpu 49 + 50 + "^dsi@[0-9a-f]+$": 51 + type: object 52 + properties: 53 + compatible: 54 + items: 55 + - const: qcom,sm6350-dsi-ctrl 56 + - const: qcom,mdss-dsi-ctrl 57 + 58 + "^phy@[0-9a-f]+$": 59 + type: object 60 + properties: 61 + compatible: 62 + const: qcom,dsi-phy-10nm 63 + 64 + unevaluatedProperties: false 65 + 66 + examples: 67 + - | 68 + #include <dt-bindings/clock/qcom,dispcc-sm6350.h> 69 + #include <dt-bindings/clock/qcom,gcc-sm6350.h> 70 + #include <dt-bindings/clock/qcom,rpmh.h> 71 + #include <dt-bindings/interrupt-controller/arm-gic.h> 72 + #include <dt-bindings/power/qcom-rpmpd.h> 73 + 74 + display-subsystem@ae00000 { 75 + compatible = "qcom,sm6350-mdss"; 76 + reg = <0x0ae00000 0x1000>; 77 + reg-names = "mdss"; 78 + 79 + power-domains = <&dispcc MDSS_GDSC>; 80 + 81 + clocks = <&gcc GCC_DISP_AHB_CLK>, 82 + <&gcc GCC_DISP_AXI_CLK>, 83 + <&dispcc DISP_CC_MDSS_MDP_CLK>; 84 + clock-names = "iface", "bus", "core"; 85 + 86 + interrupts = <GIC_SPI 83 IRQ_TYPE_LEVEL_HIGH>; 87 + interrupt-controller; 88 + #interrupt-cells = <1>; 89 + 90 + iommus = <&apps_smmu 0x800 0x2>; 91 + #address-cells = <1>; 92 + #size-cells = <1>; 93 + ranges; 94 + 95 + display-controller@ae01000 { 96 + compatible = "qcom,sm6350-dpu"; 97 + reg = <0x0ae01000 0x8f000>, 98 + <0x0aeb0000 0x2008>; 99 + reg-names = "mdp", "vbif"; 100 + 101 + clocks = <&gcc GCC_DISP_AXI_CLK>, 102 + <&dispcc DISP_CC_MDSS_AHB_CLK>, 103 + <&dispcc DISP_CC_MDSS_ROT_CLK>, 104 + <&dispcc DISP_CC_MDSS_MDP_LUT_CLK>, 105 + <&dispcc DISP_CC_MDSS_MDP_CLK>, 106 + <&dispcc DISP_CC_MDSS_VSYNC_CLK>; 107 + clock-names = "bus", "iface", "rot", "lut", "core", 108 + "vsync"; 109 + 110 + assigned-clocks = <&dispcc DISP_CC_MDSS_MDP_CLK>, 111 + <&dispcc DISP_CC_MDSS_VSYNC_CLK>, 112 + <&dispcc DISP_CC_MDSS_ROT_CLK>, 113 + <&dispcc DISP_CC_MDSS_AHB_CLK>; 114 + assigned-clock-rates = <300000000>, 115 + <19200000>, 116 + <19200000>, 117 + <19200000>; 118 + 119 + interrupt-parent = <&mdss>; 120 + interrupts = <0>; 121 + operating-points-v2 = <&mdp_opp_table>; 122 + power-domains = <&rpmhpd SM6350_CX>; 123 + 124 + ports { 125 + #address-cells = <1>; 126 + #size-cells = <0>; 127 + 128 + port@0 { 129 + reg = <0>; 130 + dpu_intf1_out: endpoint { 131 + remote-endpoint = <&dsi0_in>; 132 + }; 133 + }; 134 + 135 + port@1 { 136 + reg = <1>; 137 + dpu_intf2_out: endpoint { 138 + remote-endpoint = <&dsi1_in>; 139 + }; 140 + }; 141 + }; 142 + }; 143 + 144 + dsi@ae94000 { 145 + compatible = "qcom,sm6350-dsi-ctrl", "qcom,mdss-dsi-ctrl"; 146 + reg = <0x0ae94000 0x400>; 147 + reg-names = "dsi_ctrl"; 148 + 149 + interrupt-parent = <&mdss>; 150 + interrupts = <4>; 151 + 152 + clocks = <&dispcc DISP_CC_MDSS_BYTE0_CLK>, 153 + <&dispcc DISP_CC_MDSS_BYTE0_INTF_CLK>, 154 + <&dispcc DISP_CC_MDSS_PCLK0_CLK>, 155 + <&dispcc DISP_CC_MDSS_ESC0_CLK>, 156 + <&dispcc DISP_CC_MDSS_AHB_CLK>, 157 + <&gcc GCC_DISP_AXI_CLK>; 158 + clock-names = "byte", 159 + "byte_intf", 160 + "pixel", 161 + "core", 162 + "iface", 163 + "bus"; 164 + 165 + assigned-clocks = <&dispcc DISP_CC_MDSS_BYTE0_CLK_SRC>, 166 + <&dispcc DISP_CC_MDSS_PCLK0_CLK_SRC>; 167 + assigned-clock-parents = <&dsi0_phy 0>, <&dsi0_phy 1>; 168 + 169 + operating-points-v2 = <&dsi_opp_table>; 170 + power-domains = <&rpmhpd SM6350_MX>; 171 + 172 + phys = <&dsi0_phy>; 173 + phy-names = "dsi"; 174 + 175 + #address-cells = <1>; 176 + #size-cells = <0>; 177 + 178 + ports { 179 + #address-cells = <1>; 180 + #size-cells = <0>; 181 + 182 + port@0 { 183 + reg = <0>; 184 + dsi0_in: endpoint { 185 + remote-endpoint = <&dpu_intf1_out>; 186 + }; 187 + }; 188 + 189 + port@1 { 190 + reg = <1>; 191 + dsi0_out: endpoint { 192 + }; 193 + }; 194 + }; 195 + }; 196 + 197 + dsi0_phy: phy@ae94400 { 198 + compatible = "qcom,dsi-phy-10nm"; 199 + reg = <0x0ae94400 0x200>, 200 + <0x0ae94600 0x280>, 201 + <0x0ae94a00 0x1e0>; 202 + reg-names = "dsi_phy", 203 + "dsi_phy_lane", 204 + "dsi_pll"; 205 + 206 + #clock-cells = <1>; 207 + #phy-cells = <0>; 208 + 209 + clocks = <&dispcc DISP_CC_MDSS_AHB_CLK>, <&rpmhcc RPMH_CXO_CLK>; 210 + clock-names = "iface", "ref"; 211 + }; 212 + }; 213 + ...
+215
Documentation/devicetree/bindings/display/msm/qcom,sm6375-mdss.yaml
··· 1 + # SPDX-License-Identifier: GPL-2.0-only or BSD-2-Clause 2 + %YAML 1.2 3 + --- 4 + $id: http://devicetree.org/schemas/display/msm/qcom,sm6375-mdss.yaml# 5 + $schema: http://devicetree.org/meta-schemas/core.yaml# 6 + 7 + title: Qualcomm SM6375 Display MDSS 8 + 9 + maintainers: 10 + - Konrad Dybcio <konrad.dybcio@linaro.org> 11 + 12 + description: 13 + SM6375 MSM Mobile Display Subsystem (MDSS), which encapsulates sub-blocks 14 + like DPU display controller, DSI and DP interfaces etc. 15 + 16 + $ref: /schemas/display/msm/mdss-common.yaml# 17 + 18 + properties: 19 + compatible: 20 + const: qcom,sm6375-mdss 21 + 22 + clocks: 23 + items: 24 + - description: Display AHB clock from gcc 25 + - description: Display AHB clock 26 + - description: Display core clock 27 + 28 + clock-names: 29 + items: 30 + - const: iface 31 + - const: ahb 32 + - const: core 33 + 34 + iommus: 35 + maxItems: 1 36 + 37 + interconnects: 38 + maxItems: 2 39 + 40 + interconnect-names: 41 + maxItems: 2 42 + 43 + patternProperties: 44 + "^display-controller@[0-9a-f]+$": 45 + type: object 46 + properties: 47 + compatible: 48 + const: qcom,sm6375-dpu 49 + 50 + "^dsi@[0-9a-f]+$": 51 + type: object 52 + properties: 53 + compatible: 54 + items: 55 + - const: qcom,sm6375-dsi-ctrl 56 + - const: qcom,mdss-dsi-ctrl 57 + 58 + "^phy@[0-9a-f]+$": 59 + type: object 60 + properties: 61 + compatible: 62 + const: qcom,sm6375-dsi-phy-7nm 63 + 64 + unevaluatedProperties: false 65 + 66 + examples: 67 + - | 68 + #include <dt-bindings/clock/qcom,rpmcc.h> 69 + #include <dt-bindings/clock/qcom,sm6375-gcc.h> 70 + #include <dt-bindings/clock/qcom,sm6375-dispcc.h> 71 + #include <dt-bindings/interrupt-controller/arm-gic.h> 72 + #include <dt-bindings/power/qcom-rpmpd.h> 73 + 74 + display-subsystem@5e00000 { 75 + compatible = "qcom,sm6375-mdss"; 76 + reg = <0x05e00000 0x1000>; 77 + reg-names = "mdss"; 78 + 79 + power-domains = <&dispcc MDSS_GDSC>; 80 + 81 + clocks = <&gcc GCC_DISP_AHB_CLK>, 82 + <&dispcc DISP_CC_MDSS_AHB_CLK>, 83 + <&dispcc DISP_CC_MDSS_MDP_CLK>; 84 + clock-names = "iface", "ahb", "core"; 85 + 86 + interrupts = <GIC_SPI 83 IRQ_TYPE_LEVEL_HIGH>; 87 + interrupt-controller; 88 + #interrupt-cells = <1>; 89 + 90 + iommus = <&apps_smmu 0x820 0x2>; 91 + #address-cells = <1>; 92 + #size-cells = <1>; 93 + ranges; 94 + 95 + display-controller@5e01000 { 96 + compatible = "qcom,sm6375-dpu"; 97 + reg = <0x05e01000 0x8e030>, 98 + <0x05eb0000 0x2008>; 99 + reg-names = "mdp", "vbif"; 100 + 101 + clocks = <&gcc GCC_DISP_HF_AXI_CLK>, 102 + <&dispcc DISP_CC_MDSS_AHB_CLK>, 103 + <&dispcc DISP_CC_MDSS_ROT_CLK>, 104 + <&dispcc DISP_CC_MDSS_MDP_LUT_CLK>, 105 + <&dispcc DISP_CC_MDSS_MDP_CLK>, 106 + <&dispcc DISP_CC_MDSS_VSYNC_CLK>, 107 + <&gcc GCC_DISP_THROTTLE_CORE_CLK>; 108 + clock-names = "bus", 109 + "iface", 110 + "rot", 111 + "lut", 112 + "core", 113 + "vsync", 114 + "throttle"; 115 + 116 + assigned-clocks = <&dispcc DISP_CC_MDSS_VSYNC_CLK>; 117 + assigned-clock-rates = <19200000>; 118 + 119 + operating-points-v2 = <&mdp_opp_table>; 120 + power-domains = <&rpmpd SM6375_VDDCX>; 121 + 122 + interrupt-parent = <&mdss>; 123 + interrupts = <0>; 124 + 125 + ports { 126 + #address-cells = <1>; 127 + #size-cells = <0>; 128 + 129 + port@0 { 130 + reg = <0>; 131 + dpu_intf1_out: endpoint { 132 + remote-endpoint = <&dsi0_in>; 133 + }; 134 + }; 135 + 136 + port@1 { 137 + reg = <1>; 138 + dpu_intf2_out: endpoint { 139 + remote-endpoint = <&dsi1_in>; 140 + }; 141 + }; 142 + }; 143 + }; 144 + 145 + dsi@5e94000 { 146 + compatible = "qcom,sm6375-dsi-ctrl", "qcom,mdss-dsi-ctrl"; 147 + reg = <0x05e94000 0x400>; 148 + reg-names = "dsi_ctrl"; 149 + 150 + interrupt-parent = <&mdss>; 151 + interrupts = <4>; 152 + 153 + clocks = <&dispcc DISP_CC_MDSS_BYTE0_CLK>, 154 + <&dispcc DISP_CC_MDSS_BYTE0_INTF_CLK>, 155 + <&dispcc DISP_CC_MDSS_PCLK0_CLK>, 156 + <&dispcc DISP_CC_MDSS_ESC0_CLK>, 157 + <&dispcc DISP_CC_MDSS_AHB_CLK>, 158 + <&gcc GCC_DISP_HF_AXI_CLK>; 159 + clock-names = "byte", 160 + "byte_intf", 161 + "pixel", 162 + "core", 163 + "iface", 164 + "bus"; 165 + 166 + assigned-clocks = <&dispcc DISP_CC_MDSS_BYTE0_CLK_SRC>, 167 + <&dispcc DISP_CC_MDSS_PCLK0_CLK_SRC>; 168 + assigned-clock-parents = <&mdss_dsi0_phy 0>, <&mdss_dsi0_phy 1>; 169 + 170 + operating-points-v2 = <&dsi_opp_table>; 171 + power-domains = <&rpmpd SM6375_VDDMX>; 172 + 173 + phys = <&mdss_dsi0_phy>; 174 + phy-names = "dsi"; 175 + 176 + #address-cells = <1>; 177 + #size-cells = <0>; 178 + 179 + ports { 180 + #address-cells = <1>; 181 + #size-cells = <0>; 182 + 183 + port@0 { 184 + reg = <0>; 185 + dsi0_in: endpoint { 186 + remote-endpoint = <&dpu_intf1_out>; 187 + }; 188 + }; 189 + 190 + port@1 { 191 + reg = <1>; 192 + dsi0_out: endpoint { 193 + }; 194 + }; 195 + }; 196 + }; 197 + 198 + mdss_dsi0_phy: phy@5e94400 { 199 + compatible = "qcom,sm6375-dsi-phy-7nm"; 200 + reg = <0x05e94400 0x200>, 201 + <0x05e94600 0x280>, 202 + <0x05e94900 0x264>; 203 + reg-names = "dsi_phy", 204 + "dsi_phy_lane", 205 + "dsi_pll"; 206 + 207 + #clock-cells = <1>; 208 + #phy-cells = <0>; 209 + 210 + clocks = <&dispcc DISP_CC_MDSS_AHB_CLK>, 211 + <&rpmcc RPM_SMD_XO_CLK_SRC>; 212 + clock-names = "iface", "ref"; 213 + }; 214 + }; 215 + ...
+1 -1
Documentation/devicetree/bindings/display/msm/qcom,sm8350-mdss.yaml
··· 64 64 type: object 65 65 properties: 66 66 compatible: 67 - const: qcom,dsi-phy-5nm-8350 67 + const: qcom,sm8350-dsi-phy-5nm 68 68 69 69 unevaluatedProperties: false 70 70
+1
MAINTAINERS
··· 6583 6583 M: Abhinav Kumar <quic_abhinavk@quicinc.com> 6584 6584 M: Dmitry Baryshkov <dmitry.baryshkov@linaro.org> 6585 6585 R: Sean Paul <sean@poorly.run> 6586 + R: Marijn Suijten <marijn.suijten@somainline.org> 6586 6587 L: linux-arm-msm@vger.kernel.org 6587 6588 L: dri-devel@lists.freedesktop.org 6588 6589 L: freedreno@lists.freedesktop.org
+59
drivers/gpu/drm/display/drm_dsc_helper.c
··· 270 270 } 271 271 EXPORT_SYMBOL(drm_dsc_pps_payload_pack); 272 272 273 + /** 274 + * drm_dsc_set_const_params() - Set DSC parameters considered typically 275 + * constant across operation modes 276 + * 277 + * @vdsc_cfg: 278 + * DSC Configuration data partially filled by driver 279 + */ 280 + void drm_dsc_set_const_params(struct drm_dsc_config *vdsc_cfg) 281 + { 282 + if (!vdsc_cfg->rc_model_size) 283 + vdsc_cfg->rc_model_size = DSC_RC_MODEL_SIZE_CONST; 284 + vdsc_cfg->rc_edge_factor = DSC_RC_EDGE_FACTOR_CONST; 285 + vdsc_cfg->rc_tgt_offset_high = DSC_RC_TGT_OFFSET_HI_CONST; 286 + vdsc_cfg->rc_tgt_offset_low = DSC_RC_TGT_OFFSET_LO_CONST; 287 + 288 + if (vdsc_cfg->bits_per_component <= 10) 289 + vdsc_cfg->mux_word_size = DSC_MUX_WORD_SIZE_8_10_BPC; 290 + else 291 + vdsc_cfg->mux_word_size = DSC_MUX_WORD_SIZE_12_BPC; 292 + } 293 + EXPORT_SYMBOL(drm_dsc_set_const_params); 294 + 273 295 /* From DSC_v1.11 spec, rc_parameter_Set syntax element typically constant */ 274 296 static const u16 drm_dsc_rc_buf_thresh[] = { 275 297 896, 1792, 2688, 3584, 4480, 5376, 6272, 6720, 7168, 7616, ··· 1435 1413 return 0; 1436 1414 } 1437 1415 EXPORT_SYMBOL(drm_dsc_compute_rc_parameters); 1416 + 1417 + /** 1418 + * drm_dsc_get_bpp_int() - Get integer bits per pixel value for the given DRM DSC config 1419 + * @vdsc_cfg: Pointer to DRM DSC config struct 1420 + * 1421 + * Return: Integer BPP value 1422 + */ 1423 + u32 drm_dsc_get_bpp_int(const struct drm_dsc_config *vdsc_cfg) 1424 + { 1425 + WARN_ON_ONCE(vdsc_cfg->bits_per_pixel & 0xf); 1426 + return vdsc_cfg->bits_per_pixel >> 4; 1427 + } 1428 + EXPORT_SYMBOL(drm_dsc_get_bpp_int); 1429 + 1430 + /** 1431 + * drm_dsc_initial_scale_value() - Calculate the initial scale value for the given DSC config 1432 + * @dsc: Pointer to DRM DSC config struct 1433 + * 1434 + * Return: Calculated initial scale value 1435 + */ 1436 + u8 drm_dsc_initial_scale_value(const struct drm_dsc_config *dsc) 1437 + { 1438 + return 8 * dsc->rc_model_size / (dsc->rc_model_size - dsc->initial_offset); 1439 + } 1440 + EXPORT_SYMBOL(drm_dsc_initial_scale_value); 1441 + 1442 + /** 1443 + * drm_dsc_flatness_det_thresh() - Calculate the flatness_det_thresh for the given DSC config 1444 + * @dsc: Pointer to DRM DSC config struct 1445 + * 1446 + * Return: Calculated flatness det thresh value 1447 + */ 1448 + u32 drm_dsc_flatness_det_thresh(const struct drm_dsc_config *dsc) 1449 + { 1450 + return 2 << (dsc->bits_per_component - 8); 1451 + } 1452 + EXPORT_SYMBOL(drm_dsc_flatness_det_thresh);
+1 -1
drivers/gpu/drm/msm/Makefile
··· 65 65 disp/dpu1/dpu_hw_catalog.o \ 66 66 disp/dpu1/dpu_hw_ctl.o \ 67 67 disp/dpu1/dpu_hw_dsc.o \ 68 + disp/dpu1/dpu_hw_dsc_1_2.o \ 68 69 disp/dpu1/dpu_hw_interrupts.o \ 69 70 disp/dpu1/dpu_hw_intf.o \ 70 71 disp/dpu1/dpu_hw_lm.o \ ··· 123 122 dp/dp_ctrl.o \ 124 123 dp/dp_display.o \ 125 124 dp/dp_drm.o \ 126 - dp/dp_hpd.o \ 127 125 dp/dp_link.o \ 128 126 dp/dp_panel.o \ 129 127 dp/dp_parser.o \
+1 -1
drivers/gpu/drm/msm/adreno/a5xx_debugfs.c
··· 69 69 70 70 static int show(struct seq_file *m, void *arg) 71 71 { 72 - struct drm_info_node *node = (struct drm_info_node *) m->private; 72 + struct drm_info_node *node = m->private; 73 73 struct drm_device *dev = node->minor->dev; 74 74 struct msm_drm_private *priv = dev->dev_private; 75 75 struct drm_printer p = drm_seq_file_printer(m);
+2 -1
drivers/gpu/drm/msm/adreno/a5xx_gpu.c
··· 1743 1743 { 1744 1744 struct msm_drm_private *priv = dev->dev_private; 1745 1745 struct platform_device *pdev = priv->gpu_pdev; 1746 + struct adreno_platform_config *config = pdev->dev.platform_data; 1746 1747 struct a5xx_gpu *a5xx_gpu = NULL; 1747 1748 struct adreno_gpu *adreno_gpu; 1748 1749 struct msm_gpu *gpu; ··· 1770 1769 1771 1770 nr_rings = 4; 1772 1771 1773 - if (adreno_is_a510(adreno_gpu)) 1772 + if (adreno_cmp_rev(ADRENO_REV(5, 1, 0, ANY_ID), config->rev)) 1774 1773 nr_rings = 1; 1775 1774 1776 1775 ret = adreno_gpu_init(dev, pdev, adreno_gpu, &funcs, nr_rings);
+78 -50
drivers/gpu/drm/msm/adreno/a6xx_gmu.c
··· 354 354 } 355 355 356 356 /* Enable CPU control of SPTP power power collapse */ 357 - static int a6xx_sptprac_enable(struct a6xx_gmu *gmu) 357 + int a6xx_sptprac_enable(struct a6xx_gmu *gmu) 358 358 { 359 359 int ret; 360 360 u32 val; ··· 376 376 } 377 377 378 378 /* Disable CPU control of SPTP power power collapse */ 379 - static void a6xx_sptprac_disable(struct a6xx_gmu *gmu) 379 + void a6xx_sptprac_disable(struct a6xx_gmu *gmu) 380 380 { 381 381 u32 val; 382 382 int ret; ··· 479 479 480 480 gmu_write(gmu, REG_A6XX_GMU_RSCC_CONTROL_REQ, 0); 481 481 482 - /* Set up CX GMU counter 0 to count busy ticks */ 483 - gmu_write(gmu, REG_A6XX_GPU_GMU_AO_GPU_CX_BUSY_MASK, 0xff000000); 484 - gmu_rmw(gmu, REG_A6XX_GMU_CX_GMU_POWER_COUNTER_SELECT_0, 0xff, 0x20); 485 - 486 - /* Enable the power counter */ 487 - gmu_write(gmu, REG_A6XX_GMU_CX_GMU_POWER_COUNTER_ENABLE, 1); 488 482 return 0; 489 483 } 490 484 ··· 862 868 (val & 1), 100, 1000); 863 869 } 864 870 865 - #define GBIF_CLIENT_HALT_MASK BIT(0) 866 - #define GBIF_ARB_HALT_MASK BIT(1) 867 - 868 - static void a6xx_bus_clear_pending_transactions(struct adreno_gpu *adreno_gpu, 869 - bool gx_off) 870 - { 871 - struct msm_gpu *gpu = &adreno_gpu->base; 872 - 873 - if (!a6xx_has_gbif(adreno_gpu)) { 874 - gpu_write(gpu, REG_A6XX_VBIF_XIN_HALT_CTRL0, 0xf); 875 - spin_until((gpu_read(gpu, REG_A6XX_VBIF_XIN_HALT_CTRL1) & 876 - 0xf) == 0xf); 877 - gpu_write(gpu, REG_A6XX_VBIF_XIN_HALT_CTRL0, 0); 878 - 879 - return; 880 - } 881 - 882 - if (gx_off) { 883 - /* Halt the gx side of GBIF */ 884 - gpu_write(gpu, REG_A6XX_RBBM_GBIF_HALT, 1); 885 - spin_until(gpu_read(gpu, REG_A6XX_RBBM_GBIF_HALT_ACK) & 1); 886 - } 887 - 888 - /* Halt new client requests on GBIF */ 889 - gpu_write(gpu, REG_A6XX_GBIF_HALT, GBIF_CLIENT_HALT_MASK); 890 - spin_until((gpu_read(gpu, REG_A6XX_GBIF_HALT_ACK) & 891 - (GBIF_CLIENT_HALT_MASK)) == GBIF_CLIENT_HALT_MASK); 892 - 893 - /* Halt all AXI requests on GBIF */ 894 - gpu_write(gpu, REG_A6XX_GBIF_HALT, GBIF_ARB_HALT_MASK); 895 - spin_until((gpu_read(gpu, REG_A6XX_GBIF_HALT_ACK) & 896 - (GBIF_ARB_HALT_MASK)) == GBIF_ARB_HALT_MASK); 897 - 898 - /* The GBIF halt needs to be explicitly cleared */ 899 - gpu_write(gpu, REG_A6XX_GBIF_HALT, 0x0); 900 - } 901 - 902 871 /* Force the GMU off in case it isn't responsive */ 903 872 static void a6xx_gmu_force_off(struct a6xx_gmu *gmu) 904 873 { 905 874 struct a6xx_gpu *a6xx_gpu = container_of(gmu, struct a6xx_gpu, gmu); 906 875 struct adreno_gpu *adreno_gpu = &a6xx_gpu->base; 907 876 struct msm_gpu *gpu = &adreno_gpu->base; 877 + 878 + /* 879 + * Turn off keep alive that might have been enabled by the hang 880 + * interrupt 881 + */ 882 + gmu_write(&a6xx_gpu->gmu, REG_A6XX_GMU_GMU_PWR_COL_KEEPALIVE, 0); 908 883 909 884 /* Flush all the queues */ 910 885 a6xx_hfi_stop(gmu); ··· 893 930 a6xx_bus_clear_pending_transactions(adreno_gpu, true); 894 931 895 932 /* Reset GPU core blocks */ 896 - gpu_write(gpu, REG_A6XX_RBBM_SW_RESET_CMD, 1); 897 - udelay(100); 933 + a6xx_gpu_sw_reset(gpu, true); 898 934 } 899 935 900 936 static void a6xx_gmu_set_initial_freq(struct msm_gpu *gpu, struct a6xx_gmu *gmu) ··· 1431 1469 1432 1470 void a6xx_gmu_remove(struct a6xx_gpu *a6xx_gpu) 1433 1471 { 1472 + struct adreno_gpu *adreno_gpu = &a6xx_gpu->base; 1434 1473 struct a6xx_gmu *gmu = &a6xx_gpu->gmu; 1435 1474 struct platform_device *pdev = to_platform_device(gmu->dev); 1436 1475 ··· 1457 1494 gmu->mmio = NULL; 1458 1495 gmu->rscc = NULL; 1459 1496 1460 - a6xx_gmu_memory_free(gmu); 1497 + if (!adreno_has_gmu_wrapper(adreno_gpu)) { 1498 + a6xx_gmu_memory_free(gmu); 1461 1499 1462 - free_irq(gmu->gmu_irq, gmu); 1463 - free_irq(gmu->hfi_irq, gmu); 1500 + free_irq(gmu->gmu_irq, gmu); 1501 + free_irq(gmu->hfi_irq, gmu); 1502 + } 1464 1503 1465 1504 /* Drop reference taken in of_find_device_by_node */ 1466 1505 put_device(gmu->dev); ··· 1479 1514 complete_all(&gmu->pd_gate); 1480 1515 1481 1516 return 0; 1517 + } 1518 + 1519 + int a6xx_gmu_wrapper_init(struct a6xx_gpu *a6xx_gpu, struct device_node *node) 1520 + { 1521 + struct platform_device *pdev = of_find_device_by_node(node); 1522 + struct a6xx_gmu *gmu = &a6xx_gpu->gmu; 1523 + int ret; 1524 + 1525 + if (!pdev) 1526 + return -ENODEV; 1527 + 1528 + gmu->dev = &pdev->dev; 1529 + 1530 + of_dma_configure(gmu->dev, node, true); 1531 + 1532 + pm_runtime_enable(gmu->dev); 1533 + 1534 + /* Mark legacy for manual SPTPRAC control */ 1535 + gmu->legacy = true; 1536 + 1537 + /* Map the GMU registers */ 1538 + gmu->mmio = a6xx_gmu_get_mmio(pdev, "gmu"); 1539 + if (IS_ERR(gmu->mmio)) { 1540 + ret = PTR_ERR(gmu->mmio); 1541 + goto err_mmio; 1542 + } 1543 + 1544 + gmu->cxpd = dev_pm_domain_attach_by_name(gmu->dev, "cx"); 1545 + if (IS_ERR(gmu->cxpd)) { 1546 + ret = PTR_ERR(gmu->cxpd); 1547 + goto err_mmio; 1548 + } 1549 + 1550 + if (!device_link_add(gmu->dev, gmu->cxpd, DL_FLAG_PM_RUNTIME)) { 1551 + ret = -ENODEV; 1552 + goto detach_cxpd; 1553 + } 1554 + 1555 + init_completion(&gmu->pd_gate); 1556 + complete_all(&gmu->pd_gate); 1557 + gmu->pd_nb.notifier_call = cxpd_notifier_cb; 1558 + 1559 + /* Get a link to the GX power domain to reset the GPU */ 1560 + gmu->gxpd = dev_pm_domain_attach_by_name(gmu->dev, "gx"); 1561 + if (IS_ERR(gmu->gxpd)) { 1562 + ret = PTR_ERR(gmu->gxpd); 1563 + goto err_mmio; 1564 + } 1565 + 1566 + gmu->initialized = true; 1567 + 1568 + return 0; 1569 + 1570 + detach_cxpd: 1571 + dev_pm_domain_detach(gmu->cxpd, false); 1572 + 1573 + err_mmio: 1574 + iounmap(gmu->mmio); 1575 + 1576 + /* Drop reference taken in of_find_device_by_node */ 1577 + put_device(gmu->dev); 1578 + 1579 + return ret; 1482 1580 } 1483 1581 1484 1582 int a6xx_gmu_init(struct a6xx_gpu *a6xx_gpu, struct device_node *node)
+4 -2
drivers/gpu/drm/msm/adreno/a6xx_gmu.h
··· 51 51 52 52 struct msm_gem_address_space *aspace; 53 53 54 - void * __iomem mmio; 55 - void * __iomem rscc; 54 + void __iomem *mmio; 55 + void __iomem *rscc; 56 56 57 57 int hfi_irq; 58 58 int gmu_irq; ··· 193 193 194 194 bool a6xx_gmu_gx_is_on(struct a6xx_gmu *gmu); 195 195 bool a6xx_gmu_sptprac_is_on(struct a6xx_gmu *gmu); 196 + void a6xx_sptprac_disable(struct a6xx_gmu *gmu); 197 + int a6xx_sptprac_enable(struct a6xx_gmu *gmu); 196 198 197 199 #endif
+559 -61
drivers/gpu/drm/msm/adreno/a6xx_gpu.c
··· 21 21 struct a6xx_gpu *a6xx_gpu = to_a6xx_gpu(adreno_gpu); 22 22 23 23 /* Check that the GMU is idle */ 24 - if (!a6xx_gmu_isidle(&a6xx_gpu->gmu)) 24 + if (!adreno_has_gmu_wrapper(adreno_gpu) && !a6xx_gmu_isidle(&a6xx_gpu->gmu)) 25 25 return false; 26 26 27 27 /* Check tha the CX master is idle */ ··· 251 251 252 252 a6xx_flush(gpu, ring); 253 253 } 254 + 255 + const struct adreno_reglist a612_hwcg[] = { 256 + {REG_A6XX_RBBM_CLOCK_CNTL_SP0, 0x22222222}, 257 + {REG_A6XX_RBBM_CLOCK_CNTL2_SP0, 0x02222220}, 258 + {REG_A6XX_RBBM_CLOCK_DELAY_SP0, 0x00000081}, 259 + {REG_A6XX_RBBM_CLOCK_HYST_SP0, 0x0000f3cf}, 260 + {REG_A6XX_RBBM_CLOCK_CNTL_TP0, 0x22222222}, 261 + {REG_A6XX_RBBM_CLOCK_CNTL2_TP0, 0x22222222}, 262 + {REG_A6XX_RBBM_CLOCK_CNTL3_TP0, 0x22222222}, 263 + {REG_A6XX_RBBM_CLOCK_CNTL4_TP0, 0x00022222}, 264 + {REG_A6XX_RBBM_CLOCK_DELAY_TP0, 0x11111111}, 265 + {REG_A6XX_RBBM_CLOCK_DELAY2_TP0, 0x11111111}, 266 + {REG_A6XX_RBBM_CLOCK_DELAY3_TP0, 0x11111111}, 267 + {REG_A6XX_RBBM_CLOCK_DELAY4_TP0, 0x00011111}, 268 + {REG_A6XX_RBBM_CLOCK_HYST_TP0, 0x77777777}, 269 + {REG_A6XX_RBBM_CLOCK_HYST2_TP0, 0x77777777}, 270 + {REG_A6XX_RBBM_CLOCK_HYST3_TP0, 0x77777777}, 271 + {REG_A6XX_RBBM_CLOCK_HYST4_TP0, 0x00077777}, 272 + {REG_A6XX_RBBM_CLOCK_CNTL_RB0, 0x22222222}, 273 + {REG_A6XX_RBBM_CLOCK_CNTL2_RB0, 0x01202222}, 274 + {REG_A6XX_RBBM_CLOCK_CNTL_CCU0, 0x00002220}, 275 + {REG_A6XX_RBBM_CLOCK_HYST_RB_CCU0, 0x00040f00}, 276 + {REG_A6XX_RBBM_CLOCK_CNTL_RAC, 0x05522022}, 277 + {REG_A6XX_RBBM_CLOCK_CNTL2_RAC, 0x00005555}, 278 + {REG_A6XX_RBBM_CLOCK_DELAY_RAC, 0x00000011}, 279 + {REG_A6XX_RBBM_CLOCK_HYST_RAC, 0x00445044}, 280 + {REG_A6XX_RBBM_CLOCK_CNTL_TSE_RAS_RBBM, 0x04222222}, 281 + {REG_A6XX_RBBM_CLOCK_MODE_VFD, 0x00002222}, 282 + {REG_A6XX_RBBM_CLOCK_MODE_GPC, 0x02222222}, 283 + {REG_A6XX_RBBM_CLOCK_DELAY_HLSQ_2, 0x00000002}, 284 + {REG_A6XX_RBBM_CLOCK_MODE_HLSQ, 0x00002222}, 285 + {REG_A6XX_RBBM_CLOCK_DELAY_TSE_RAS_RBBM, 0x00004000}, 286 + {REG_A6XX_RBBM_CLOCK_DELAY_VFD, 0x00002222}, 287 + {REG_A6XX_RBBM_CLOCK_DELAY_GPC, 0x00000200}, 288 + {REG_A6XX_RBBM_CLOCK_DELAY_HLSQ, 0x00000000}, 289 + {REG_A6XX_RBBM_CLOCK_HYST_TSE_RAS_RBBM, 0x00000000}, 290 + {REG_A6XX_RBBM_CLOCK_HYST_VFD, 0x00000000}, 291 + {REG_A6XX_RBBM_CLOCK_HYST_GPC, 0x04104004}, 292 + {REG_A6XX_RBBM_CLOCK_HYST_HLSQ, 0x00000000}, 293 + {REG_A6XX_RBBM_CLOCK_CNTL_UCHE, 0x22222222}, 294 + {REG_A6XX_RBBM_CLOCK_HYST_UCHE, 0x00000004}, 295 + {REG_A6XX_RBBM_CLOCK_DELAY_UCHE, 0x00000002}, 296 + {REG_A6XX_RBBM_ISDB_CNT, 0x00000182}, 297 + {REG_A6XX_RBBM_RAC_THRESHOLD_CNT, 0x00000000}, 298 + {REG_A6XX_RBBM_SP_HYST_CNT, 0x00000000}, 299 + {REG_A6XX_RBBM_CLOCK_CNTL_GMU_GX, 0x00000222}, 300 + {REG_A6XX_RBBM_CLOCK_DELAY_GMU_GX, 0x00000111}, 301 + {REG_A6XX_RBBM_CLOCK_HYST_GMU_GX, 0x00000555}, 302 + {}, 303 + }; 254 304 255 305 /* For a615 family (a615, a616, a618 and a619) */ 256 306 const struct adreno_reglist a615_hwcg[] = { ··· 638 588 {}, 639 589 }; 640 590 591 + const struct adreno_reglist a690_hwcg[] = { 592 + {REG_A6XX_RBBM_CLOCK_CNTL_SP0, 0x02222222}, 593 + {REG_A6XX_RBBM_CLOCK_CNTL2_SP0, 0x02222220}, 594 + {REG_A6XX_RBBM_CLOCK_DELAY_SP0, 0x00000080}, 595 + {REG_A6XX_RBBM_CLOCK_HYST_SP0, 0x0000F3CF}, 596 + {REG_A6XX_RBBM_CLOCK_CNTL_TP0, 0x22222222}, 597 + {REG_A6XX_RBBM_CLOCK_CNTL2_TP0, 0x22222222}, 598 + {REG_A6XX_RBBM_CLOCK_CNTL3_TP0, 0x22222222}, 599 + {REG_A6XX_RBBM_CLOCK_CNTL4_TP0, 0x00022222}, 600 + {REG_A6XX_RBBM_CLOCK_DELAY_TP0, 0x11111111}, 601 + {REG_A6XX_RBBM_CLOCK_DELAY2_TP0, 0x11111111}, 602 + {REG_A6XX_RBBM_CLOCK_DELAY3_TP0, 0x11111111}, 603 + {REG_A6XX_RBBM_CLOCK_DELAY4_TP0, 0x00011111}, 604 + {REG_A6XX_RBBM_CLOCK_HYST_TP0, 0x77777777}, 605 + {REG_A6XX_RBBM_CLOCK_HYST2_TP0, 0x77777777}, 606 + {REG_A6XX_RBBM_CLOCK_HYST3_TP0, 0x77777777}, 607 + {REG_A6XX_RBBM_CLOCK_HYST4_TP0, 0x00077777}, 608 + {REG_A6XX_RBBM_CLOCK_CNTL_RB0, 0x22222222}, 609 + {REG_A6XX_RBBM_CLOCK_CNTL2_RB0, 0x01002222}, 610 + {REG_A6XX_RBBM_CLOCK_CNTL_CCU0, 0x00002220}, 611 + {REG_A6XX_RBBM_CLOCK_HYST_RB_CCU0, 0x00040F00}, 612 + {REG_A6XX_RBBM_CLOCK_CNTL_RAC, 0x25222022}, 613 + {REG_A6XX_RBBM_CLOCK_CNTL2_RAC, 0x00005555}, 614 + {REG_A6XX_RBBM_CLOCK_DELAY_RAC, 0x00000011}, 615 + {REG_A6XX_RBBM_CLOCK_HYST_RAC, 0x00445044}, 616 + {REG_A6XX_RBBM_CLOCK_CNTL_TSE_RAS_RBBM, 0x04222222}, 617 + {REG_A6XX_RBBM_CLOCK_MODE_VFD, 0x00002222}, 618 + {REG_A6XX_RBBM_CLOCK_MODE_GPC, 0x00222222}, 619 + {REG_A6XX_RBBM_CLOCK_DELAY_HLSQ_2, 0x00000002}, 620 + {REG_A6XX_RBBM_CLOCK_MODE_HLSQ, 0x00002222}, 621 + {REG_A6XX_RBBM_CLOCK_DELAY_TSE_RAS_RBBM, 0x00004000}, 622 + {REG_A6XX_RBBM_CLOCK_DELAY_VFD, 0x00002222}, 623 + {REG_A6XX_RBBM_CLOCK_DELAY_GPC, 0x00000200}, 624 + {REG_A6XX_RBBM_CLOCK_DELAY_HLSQ, 0x00000000}, 625 + {REG_A6XX_RBBM_CLOCK_HYST_TSE_RAS_RBBM, 0x00000000}, 626 + {REG_A6XX_RBBM_CLOCK_HYST_VFD, 0x00000000}, 627 + {REG_A6XX_RBBM_CLOCK_HYST_GPC, 0x04104004}, 628 + {REG_A6XX_RBBM_CLOCK_HYST_HLSQ, 0x00000000}, 629 + {REG_A6XX_RBBM_CLOCK_CNTL_TEX_FCHE, 0x00000222}, 630 + {REG_A6XX_RBBM_CLOCK_DELAY_TEX_FCHE, 0x00000111}, 631 + {REG_A6XX_RBBM_CLOCK_HYST_TEX_FCHE, 0x00000000}, 632 + {REG_A6XX_RBBM_CLOCK_CNTL_UCHE, 0x22222222}, 633 + {REG_A6XX_RBBM_CLOCK_HYST_UCHE, 0x00000004}, 634 + {REG_A6XX_RBBM_CLOCK_DELAY_UCHE, 0x00000002}, 635 + {REG_A6XX_RBBM_CLOCK_CNTL, 0x8AA8AA82}, 636 + {REG_A6XX_RBBM_ISDB_CNT, 0x00000182}, 637 + {REG_A6XX_RBBM_RAC_THRESHOLD_CNT, 0x00000000}, 638 + {REG_A6XX_RBBM_SP_HYST_CNT, 0x00000000}, 639 + {REG_A6XX_RBBM_CLOCK_CNTL_GMU_GX, 0x00000222}, 640 + {REG_A6XX_RBBM_CLOCK_DELAY_GMU_GX, 0x00000111}, 641 + {REG_A6XX_RBBM_CLOCK_HYST_GMU_GX, 0x00000555}, 642 + {REG_A6XX_GPU_GMU_AO_GMU_CGC_MODE_CNTL, 0x20200}, 643 + {REG_A6XX_GPU_GMU_AO_GMU_CGC_DELAY_CNTL, 0x10111}, 644 + {REG_A6XX_GPU_GMU_AO_GMU_CGC_HYST_CNTL, 0x5555}, 645 + {} 646 + }; 647 + 641 648 static void a6xx_set_hwcg(struct msm_gpu *gpu, bool state) 642 649 { 643 650 struct adreno_gpu *adreno_gpu = to_adreno_gpu(gpu); ··· 709 602 710 603 if (adreno_is_a630(adreno_gpu)) 711 604 clock_cntl_on = 0x8aa8aa02; 605 + else if (adreno_is_a610(adreno_gpu)) 606 + clock_cntl_on = 0xaaa8aa82; 712 607 else 713 608 clock_cntl_on = 0x8aa8aa82; 714 609 ··· 721 612 return; 722 613 723 614 /* Disable SP clock before programming HWCG registers */ 724 - gmu_rmw(gmu, REG_A6XX_GPU_GMU_GX_SPTPRAC_CLOCK_CONTROL, 1, 0); 615 + if (!adreno_is_a610(adreno_gpu)) 616 + gmu_rmw(gmu, REG_A6XX_GPU_GMU_GX_SPTPRAC_CLOCK_CONTROL, 1, 0); 725 617 726 618 for (i = 0; (reg = &adreno_gpu->info->hwcg[i], reg->offset); i++) 727 619 gpu_write(gpu, reg->offset, state ? reg->value : 0); 728 620 729 621 /* Enable SP clock */ 730 - gmu_rmw(gmu, REG_A6XX_GPU_GMU_GX_SPTPRAC_CLOCK_CONTROL, 0, 1); 622 + if (!adreno_is_a610(adreno_gpu)) 623 + gmu_rmw(gmu, REG_A6XX_GPU_GMU_GX_SPTPRAC_CLOCK_CONTROL, 0, 1); 731 624 732 625 gpu_write(gpu, REG_A6XX_RBBM_CLOCK_CNTL, state ? clock_cntl_on : 0); 733 626 } ··· 858 747 A6XX_PROTECT_NORDWR(0x1f8c0, 0x0000), /* note: infinite range */ 859 748 }; 860 749 750 + /* These are for a690 */ 751 + static const u32 a690_protect[] = { 752 + A6XX_PROTECT_RDONLY(0x00000, 0x004ff), 753 + A6XX_PROTECT_RDONLY(0x00501, 0x00001), 754 + A6XX_PROTECT_RDONLY(0x0050b, 0x002f4), 755 + A6XX_PROTECT_NORDWR(0x0050e, 0x00000), 756 + A6XX_PROTECT_NORDWR(0x00510, 0x00000), 757 + A6XX_PROTECT_NORDWR(0x00534, 0x00000), 758 + A6XX_PROTECT_NORDWR(0x00800, 0x00082), 759 + A6XX_PROTECT_NORDWR(0x008a0, 0x00008), 760 + A6XX_PROTECT_NORDWR(0x008ab, 0x00024), 761 + A6XX_PROTECT_RDONLY(0x008de, 0x000ae), 762 + A6XX_PROTECT_NORDWR(0x00900, 0x0004d), 763 + A6XX_PROTECT_NORDWR(0x0098d, 0x00272), 764 + A6XX_PROTECT_NORDWR(0x00e00, 0x00001), 765 + A6XX_PROTECT_NORDWR(0x00e03, 0x0000c), 766 + A6XX_PROTECT_NORDWR(0x03c00, 0x000c3), 767 + A6XX_PROTECT_RDONLY(0x03cc4, 0x01fff), 768 + A6XX_PROTECT_NORDWR(0x08630, 0x001cf), 769 + A6XX_PROTECT_NORDWR(0x08e00, 0x00000), 770 + A6XX_PROTECT_NORDWR(0x08e08, 0x00007), 771 + A6XX_PROTECT_NORDWR(0x08e50, 0x0001f), 772 + A6XX_PROTECT_NORDWR(0x08e80, 0x0027f), 773 + A6XX_PROTECT_NORDWR(0x09624, 0x001db), 774 + A6XX_PROTECT_NORDWR(0x09e60, 0x00011), 775 + A6XX_PROTECT_NORDWR(0x09e78, 0x00187), 776 + A6XX_PROTECT_NORDWR(0x0a630, 0x001cf), 777 + A6XX_PROTECT_NORDWR(0x0ae02, 0x00000), 778 + A6XX_PROTECT_NORDWR(0x0ae50, 0x0012f), 779 + A6XX_PROTECT_NORDWR(0x0b604, 0x00000), 780 + A6XX_PROTECT_NORDWR(0x0b608, 0x00006), 781 + A6XX_PROTECT_NORDWR(0x0be02, 0x00001), 782 + A6XX_PROTECT_NORDWR(0x0be20, 0x0015f), 783 + A6XX_PROTECT_NORDWR(0x0d000, 0x005ff), 784 + A6XX_PROTECT_NORDWR(0x0f000, 0x00bff), 785 + A6XX_PROTECT_RDONLY(0x0fc00, 0x01fff), 786 + A6XX_PROTECT_NORDWR(0x11c00, 0x00000), /*note: infiite range */ 787 + }; 788 + 861 789 static void a6xx_set_cp_protect(struct msm_gpu *gpu) 862 790 { 863 791 struct adreno_gpu *adreno_gpu = to_adreno_gpu(gpu); ··· 908 758 count = ARRAY_SIZE(a650_protect); 909 759 count_max = 48; 910 760 BUILD_BUG_ON(ARRAY_SIZE(a650_protect) > 48); 761 + } else if (adreno_is_a690(adreno_gpu)) { 762 + regs = a690_protect; 763 + count = ARRAY_SIZE(a690_protect); 764 + count_max = 48; 765 + BUILD_BUG_ON(ARRAY_SIZE(a690_protect) > 48); 911 766 } else if (adreno_is_a660_family(adreno_gpu)) { 912 767 regs = a660_protect; 913 768 count = ARRAY_SIZE(a660_protect); ··· 941 786 static void a6xx_set_ubwc_config(struct msm_gpu *gpu) 942 787 { 943 788 struct adreno_gpu *adreno_gpu = to_adreno_gpu(gpu); 944 - u32 lower_bit = 2; 945 - u32 amsbc = 0; 789 + /* Unknown, introduced with A650 family, related to UBWC mode/ver 4 */ 946 790 u32 rgb565_predicator = 0; 791 + /* Unknown, introduced with A650 family */ 947 792 u32 uavflagprd_inv = 0; 793 + /* Whether the minimum access length is 64 bits */ 794 + u32 min_acc_len = 0; 795 + /* Entirely magic, per-GPU-gen value */ 796 + u32 ubwc_mode = 0; 797 + /* 798 + * The Highest Bank Bit value represents the bit of the highest DDR bank. 799 + * We then subtract 13 from it (13 is the minimum value allowed by hw) and 800 + * write the lowest two bits of the remaining value as hbb_lo and the 801 + * one above it as hbb_hi to the hardware. This should ideally use DRAM 802 + * type detection. 803 + */ 804 + u32 hbb_hi = 0; 805 + u32 hbb_lo = 2; 806 + /* Unknown, introduced with A640/680 */ 807 + u32 amsbc = 0; 808 + 809 + if (adreno_is_a610(adreno_gpu)) { 810 + /* HBB = 14 */ 811 + hbb_lo = 1; 812 + min_acc_len = 1; 813 + ubwc_mode = 1; 814 + } 948 815 949 816 /* a618 is using the hw default values */ 950 817 if (adreno_is_a618(adreno_gpu)) 951 818 return; 819 + 820 + if (adreno_is_a619_holi(adreno_gpu)) 821 + hbb_lo = 0; 952 822 953 823 if (adreno_is_a640_family(adreno_gpu)) 954 824 amsbc = 1; 955 825 956 826 if (adreno_is_a650(adreno_gpu) || adreno_is_a660(adreno_gpu)) { 957 827 /* TODO: get ddr type from bootloader and use 2 for LPDDR4 */ 958 - lower_bit = 3; 828 + hbb_lo = 3; 829 + amsbc = 1; 830 + rgb565_predicator = 1; 831 + uavflagprd_inv = 2; 832 + } 833 + 834 + if (adreno_is_a690(adreno_gpu)) { 835 + hbb_lo = 2; 959 836 amsbc = 1; 960 837 rgb565_predicator = 1; 961 838 uavflagprd_inv = 2; 962 839 } 963 840 964 841 if (adreno_is_7c3(adreno_gpu)) { 965 - lower_bit = 1; 842 + hbb_lo = 1; 966 843 amsbc = 1; 967 844 rgb565_predicator = 1; 968 845 uavflagprd_inv = 2; 969 846 } 970 847 971 848 gpu_write(gpu, REG_A6XX_RB_NC_MODE_CNTL, 972 - rgb565_predicator << 11 | amsbc << 4 | lower_bit << 1); 973 - gpu_write(gpu, REG_A6XX_TPL1_NC_MODE_CNTL, lower_bit << 1); 974 - gpu_write(gpu, REG_A6XX_SP_NC_MODE_CNTL, 975 - uavflagprd_inv << 4 | lower_bit << 1); 976 - gpu_write(gpu, REG_A6XX_UCHE_MODE_CNTL, lower_bit << 21); 849 + rgb565_predicator << 11 | hbb_hi << 10 | amsbc << 4 | 850 + min_acc_len << 3 | hbb_lo << 1 | ubwc_mode); 851 + 852 + gpu_write(gpu, REG_A6XX_TPL1_NC_MODE_CNTL, hbb_hi << 4 | 853 + min_acc_len << 3 | hbb_lo << 1 | ubwc_mode); 854 + 855 + gpu_write(gpu, REG_A6XX_SP_NC_MODE_CNTL, hbb_hi << 10 | 856 + uavflagprd_inv << 4 | min_acc_len << 3 | 857 + hbb_lo << 1 | ubwc_mode); 858 + 859 + gpu_write(gpu, REG_A6XX_UCHE_MODE_CNTL, min_acc_len << 23 | hbb_lo << 21); 977 860 } 978 861 979 862 static int a6xx_cp_init(struct msm_gpu *gpu) ··· 1190 997 { 1191 998 struct adreno_gpu *adreno_gpu = to_adreno_gpu(gpu); 1192 999 struct a6xx_gpu *a6xx_gpu = to_a6xx_gpu(adreno_gpu); 1000 + struct a6xx_gmu *gmu = &a6xx_gpu->gmu; 1193 1001 int ret; 1194 1002 1195 - /* Make sure the GMU keeps the GPU on while we set it up */ 1196 - a6xx_gmu_set_oob(&a6xx_gpu->gmu, GMU_OOB_GPU_SET); 1003 + if (!adreno_has_gmu_wrapper(adreno_gpu)) { 1004 + /* Make sure the GMU keeps the GPU on while we set it up */ 1005 + a6xx_gmu_set_oob(&a6xx_gpu->gmu, GMU_OOB_GPU_SET); 1006 + } 1197 1007 1198 1008 /* Clear GBIF halt in case GX domain was not collapsed */ 1199 - if (a6xx_has_gbif(adreno_gpu)) 1009 + if (adreno_is_a619_holi(adreno_gpu)) { 1010 + gpu_write(gpu, REG_A6XX_GBIF_HALT, 0); 1011 + gpu_write(gpu, REG_A6XX_RBBM_GPR0_CNTL, 0); 1012 + /* Let's make extra sure that the GPU can access the memory.. */ 1013 + mb(); 1014 + } else if (a6xx_has_gbif(adreno_gpu)) { 1015 + gpu_write(gpu, REG_A6XX_GBIF_HALT, 0); 1200 1016 gpu_write(gpu, REG_A6XX_RBBM_GBIF_HALT, 0); 1017 + /* Let's make extra sure that the GPU can access the memory.. */ 1018 + mb(); 1019 + } 1201 1020 1202 1021 gpu_write(gpu, REG_A6XX_RBBM_SECVID_TSB_CNTL, 0); 1022 + 1023 + if (adreno_is_a619_holi(adreno_gpu)) 1024 + a6xx_sptprac_enable(gmu); 1203 1025 1204 1026 /* 1205 1027 * Disable the trusted memory range - we don't actually supported secure ··· 1242 1034 a6xx_set_hwcg(gpu, true); 1243 1035 1244 1036 /* VBIF/GBIF start*/ 1245 - if (adreno_is_a640_family(adreno_gpu) || 1037 + if (adreno_is_a610(adreno_gpu) || 1038 + adreno_is_a640_family(adreno_gpu) || 1246 1039 adreno_is_a650_family(adreno_gpu)) { 1247 1040 gpu_write(gpu, REG_A6XX_GBIF_QSB_SIDE0, 0x00071620); 1248 1041 gpu_write(gpu, REG_A6XX_GBIF_QSB_SIDE1, 0x00071620); 1249 1042 gpu_write(gpu, REG_A6XX_GBIF_QSB_SIDE2, 0x00071620); 1250 - gpu_write(gpu, REG_A6XX_GBIF_QSB_SIDE3, 0x00071620); 1251 1043 gpu_write(gpu, REG_A6XX_GBIF_QSB_SIDE3, 0x00071620); 1252 1044 gpu_write(gpu, REG_A6XX_RBBM_GBIF_CLIENT_QOS_CNTL, 0x3); 1253 1045 } else { ··· 1276 1068 gpu_write(gpu, REG_A6XX_UCHE_FILTER_CNTL, 0x804); 1277 1069 gpu_write(gpu, REG_A6XX_UCHE_CACHE_WAYS, 0x4); 1278 1070 1279 - if (adreno_is_a640_family(adreno_gpu) || 1280 - adreno_is_a650_family(adreno_gpu)) 1071 + if (adreno_is_a640_family(adreno_gpu) || adreno_is_a650_family(adreno_gpu)) { 1281 1072 gpu_write(gpu, REG_A6XX_CP_ROQ_THRESHOLDS_2, 0x02000140); 1282 - else 1073 + gpu_write(gpu, REG_A6XX_CP_ROQ_THRESHOLDS_1, 0x8040362c); 1074 + } else if (adreno_is_a610(adreno_gpu)) { 1075 + gpu_write(gpu, REG_A6XX_CP_ROQ_THRESHOLDS_2, 0x00800060); 1076 + gpu_write(gpu, REG_A6XX_CP_ROQ_THRESHOLDS_1, 0x40201b16); 1077 + } else { 1283 1078 gpu_write(gpu, REG_A6XX_CP_ROQ_THRESHOLDS_2, 0x010000c0); 1284 - gpu_write(gpu, REG_A6XX_CP_ROQ_THRESHOLDS_1, 0x8040362c); 1079 + gpu_write(gpu, REG_A6XX_CP_ROQ_THRESHOLDS_1, 0x8040362c); 1080 + } 1285 1081 1286 1082 if (adreno_is_a660_family(adreno_gpu)) 1287 1083 gpu_write(gpu, REG_A6XX_CP_LPAC_PROG_FIFO_SIZE, 0x00000020); 1288 1084 1289 1085 /* Setting the mem pool size */ 1290 - gpu_write(gpu, REG_A6XX_CP_MEM_POOL_SIZE, 128); 1086 + if (adreno_is_a610(adreno_gpu)) { 1087 + gpu_write(gpu, REG_A6XX_CP_MEM_POOL_SIZE, 48); 1088 + gpu_write(gpu, REG_A6XX_CP_MEM_POOL_DBG_ADDR, 47); 1089 + } else 1090 + gpu_write(gpu, REG_A6XX_CP_MEM_POOL_SIZE, 128); 1291 1091 1292 1092 /* Setting the primFifo thresholds default values, 1293 1093 * and vccCacheSkipDis=1 bit (0x200) for A640 and newer 1294 1094 */ 1295 - if (adreno_is_a650(adreno_gpu) || adreno_is_a660(adreno_gpu)) 1095 + if (adreno_is_a650(adreno_gpu) || adreno_is_a660(adreno_gpu) || adreno_is_a690(adreno_gpu)) 1296 1096 gpu_write(gpu, REG_A6XX_PC_DBG_ECO_CNTL, 0x00300200); 1297 1097 else if (adreno_is_a640_family(adreno_gpu) || adreno_is_7c3(adreno_gpu)) 1298 1098 gpu_write(gpu, REG_A6XX_PC_DBG_ECO_CNTL, 0x00200200); 1299 1099 else if (adreno_is_a650(adreno_gpu) || adreno_is_a660(adreno_gpu)) 1300 1100 gpu_write(gpu, REG_A6XX_PC_DBG_ECO_CNTL, 0x00300200); 1101 + else if (adreno_is_a619(adreno_gpu)) 1102 + gpu_write(gpu, REG_A6XX_PC_DBG_ECO_CNTL, 0x00018000); 1103 + else if (adreno_is_a610(adreno_gpu)) 1104 + gpu_write(gpu, REG_A6XX_PC_DBG_ECO_CNTL, 0x00080000); 1301 1105 else 1302 1106 gpu_write(gpu, REG_A6XX_PC_DBG_ECO_CNTL, 0x00180000); 1303 1107 ··· 1325 1105 a6xx_set_ubwc_config(gpu); 1326 1106 1327 1107 /* Enable fault detection */ 1328 - gpu_write(gpu, REG_A6XX_RBBM_INTERFACE_HANG_INT_CNTL, 1329 - (1 << 30) | 0x1fffff); 1108 + if (adreno_is_a619(adreno_gpu)) 1109 + gpu_write(gpu, REG_A6XX_RBBM_INTERFACE_HANG_INT_CNTL, (1 << 30) | 0x3fffff); 1110 + else if (adreno_is_a610(adreno_gpu)) 1111 + gpu_write(gpu, REG_A6XX_RBBM_INTERFACE_HANG_INT_CNTL, (1 << 30) | 0x3ffff); 1112 + else 1113 + gpu_write(gpu, REG_A6XX_RBBM_INTERFACE_HANG_INT_CNTL, (1 << 30) | 0x1fffff); 1330 1114 1331 1115 gpu_write(gpu, REG_A6XX_UCHE_CLIENT_PF, 1); 1332 1116 ··· 1346 1122 gpu_write(gpu, REG_A6XX_TPL1_BICUBIC_WEIGHTS_TABLE_4, 1347 1123 0x3f0243f0); 1348 1124 } 1125 + 1126 + /* Set up the CX GMU counter 0 to count busy ticks */ 1127 + gmu_write(gmu, REG_A6XX_GPU_GMU_AO_GPU_CX_BUSY_MASK, 0xff000000); 1128 + 1129 + /* Enable the power counter */ 1130 + gmu_rmw(gmu, REG_A6XX_GMU_CX_GMU_POWER_COUNTER_SELECT_0, 0xff, BIT(5)); 1131 + gmu_write(gmu, REG_A6XX_GMU_CX_GMU_POWER_COUNTER_ENABLE, 1); 1349 1132 1350 1133 /* Protect registers from the CP */ 1351 1134 a6xx_set_cp_protect(gpu); ··· 1443 1212 } 1444 1213 1445 1214 out: 1215 + if (adreno_has_gmu_wrapper(adreno_gpu)) 1216 + return ret; 1446 1217 /* 1447 1218 * Tell the GMU that we are done touching the GPU and it can start power 1448 1219 * management ··· 1479 1246 adreno_dump(gpu); 1480 1247 } 1481 1248 1482 - #define VBIF_RESET_ACK_TIMEOUT 100 1483 - #define VBIF_RESET_ACK_MASK 0x00f0 1484 - 1485 1249 static void a6xx_recover(struct msm_gpu *gpu) 1486 1250 { 1487 1251 struct adreno_gpu *adreno_gpu = to_adreno_gpu(gpu); ··· 1504 1274 /* Halt SQE first */ 1505 1275 gpu_write(gpu, REG_A6XX_CP_SQE_CNTL, 3); 1506 1276 1507 - /* 1508 - * Turn off keep alive that might have been enabled by the hang 1509 - * interrupt 1510 - */ 1511 - gmu_write(&a6xx_gpu->gmu, REG_A6XX_GMU_GMU_PWR_COL_KEEPALIVE, 0); 1512 - 1513 1277 pm_runtime_dont_use_autosuspend(&gpu->pdev->dev); 1514 1278 1515 1279 /* active_submit won't change until we make a submission */ ··· 1515 1291 * runtime suspend cb 1516 1292 */ 1517 1293 gpu->active_submits = 0; 1294 + 1295 + if (adreno_has_gmu_wrapper(adreno_gpu)) { 1296 + /* Drain the outstanding traffic on memory buses */ 1297 + a6xx_bus_clear_pending_transactions(adreno_gpu, true); 1298 + 1299 + /* Reset the GPU to a clean state */ 1300 + a6xx_gpu_sw_reset(gpu, true); 1301 + a6xx_gpu_sw_reset(gpu, false); 1302 + } 1518 1303 1519 1304 reinit_completion(&gmu->pd_gate); 1520 1305 dev_pm_genpd_add_notifier(gmu->cxpd, &gmu->pd_nb); ··· 1675 1442 * Force the GPU to stay on until after we finish 1676 1443 * collecting information 1677 1444 */ 1678 - gmu_write(&a6xx_gpu->gmu, REG_A6XX_GMU_GMU_PWR_COL_KEEPALIVE, 1); 1445 + if (!adreno_has_gmu_wrapper(adreno_gpu)) 1446 + gmu_write(&a6xx_gpu->gmu, REG_A6XX_GMU_GMU_PWR_COL_KEEPALIVE, 1); 1679 1447 1680 1448 DRM_DEV_ERROR(&gpu->pdev->dev, 1681 1449 "gpu fault ring %d fence %x status %8.8X rb %4.4x/%4.4x ib1 %16.16llX/%4.4x ib2 %16.16llX/%4.4x\n", ··· 1807 1573 1808 1574 static void a6xx_llc_slices_destroy(struct a6xx_gpu *a6xx_gpu) 1809 1575 { 1576 + /* No LLCC on non-RPMh (and by extension, non-GMU) SoCs */ 1577 + if (adreno_has_gmu_wrapper(&a6xx_gpu->base)) 1578 + return; 1579 + 1810 1580 llcc_slice_putd(a6xx_gpu->llc_slice); 1811 1581 llcc_slice_putd(a6xx_gpu->htw_llc_slice); 1812 1582 } ··· 1819 1581 struct a6xx_gpu *a6xx_gpu) 1820 1582 { 1821 1583 struct device_node *phandle; 1584 + 1585 + /* No LLCC on non-RPMh (and by extension, non-GMU) SoCs */ 1586 + if (adreno_has_gmu_wrapper(&a6xx_gpu->base)) 1587 + return; 1822 1588 1823 1589 /* 1824 1590 * There is a different programming path for targets with an mmu500 ··· 1845 1603 a6xx_gpu->llc_mmio = ERR_PTR(-EINVAL); 1846 1604 } 1847 1605 1848 - static int a6xx_pm_resume(struct msm_gpu *gpu) 1606 + #define GBIF_CLIENT_HALT_MASK BIT(0) 1607 + #define GBIF_ARB_HALT_MASK BIT(1) 1608 + #define VBIF_XIN_HALT_CTRL0_MASK GENMASK(3, 0) 1609 + #define VBIF_RESET_ACK_MASK 0xF0 1610 + #define GPR0_GBIF_HALT_REQUEST 0x1E0 1611 + 1612 + void a6xx_bus_clear_pending_transactions(struct adreno_gpu *adreno_gpu, bool gx_off) 1613 + { 1614 + struct msm_gpu *gpu = &adreno_gpu->base; 1615 + 1616 + if (adreno_is_a619_holi(adreno_gpu)) { 1617 + gpu_write(gpu, REG_A6XX_RBBM_GPR0_CNTL, GPR0_GBIF_HALT_REQUEST); 1618 + spin_until((gpu_read(gpu, REG_A6XX_RBBM_VBIF_GX_RESET_STATUS) & 1619 + (VBIF_RESET_ACK_MASK)) == VBIF_RESET_ACK_MASK); 1620 + } else if (!a6xx_has_gbif(adreno_gpu)) { 1621 + gpu_write(gpu, REG_A6XX_VBIF_XIN_HALT_CTRL0, VBIF_XIN_HALT_CTRL0_MASK); 1622 + spin_until((gpu_read(gpu, REG_A6XX_VBIF_XIN_HALT_CTRL1) & 1623 + (VBIF_XIN_HALT_CTRL0_MASK)) == VBIF_XIN_HALT_CTRL0_MASK); 1624 + gpu_write(gpu, REG_A6XX_VBIF_XIN_HALT_CTRL0, 0); 1625 + 1626 + return; 1627 + } 1628 + 1629 + if (gx_off) { 1630 + /* Halt the gx side of GBIF */ 1631 + gpu_write(gpu, REG_A6XX_RBBM_GBIF_HALT, 1); 1632 + spin_until(gpu_read(gpu, REG_A6XX_RBBM_GBIF_HALT_ACK) & 1); 1633 + } 1634 + 1635 + /* Halt new client requests on GBIF */ 1636 + gpu_write(gpu, REG_A6XX_GBIF_HALT, GBIF_CLIENT_HALT_MASK); 1637 + spin_until((gpu_read(gpu, REG_A6XX_GBIF_HALT_ACK) & 1638 + (GBIF_CLIENT_HALT_MASK)) == GBIF_CLIENT_HALT_MASK); 1639 + 1640 + /* Halt all AXI requests on GBIF */ 1641 + gpu_write(gpu, REG_A6XX_GBIF_HALT, GBIF_ARB_HALT_MASK); 1642 + spin_until((gpu_read(gpu, REG_A6XX_GBIF_HALT_ACK) & 1643 + (GBIF_ARB_HALT_MASK)) == GBIF_ARB_HALT_MASK); 1644 + 1645 + /* The GBIF halt needs to be explicitly cleared */ 1646 + gpu_write(gpu, REG_A6XX_GBIF_HALT, 0x0); 1647 + } 1648 + 1649 + void a6xx_gpu_sw_reset(struct msm_gpu *gpu, bool assert) 1650 + { 1651 + /* 11nm chips (e.g. ones with A610) have hw issues with the reset line! */ 1652 + if (adreno_is_a610(to_adreno_gpu(gpu))) 1653 + return; 1654 + 1655 + gpu_write(gpu, REG_A6XX_RBBM_SW_RESET_CMD, assert); 1656 + /* Perform a bogus read and add a brief delay to ensure ordering. */ 1657 + gpu_read(gpu, REG_A6XX_RBBM_SW_RESET_CMD); 1658 + udelay(1); 1659 + 1660 + /* The reset line needs to be asserted for at least 100 us */ 1661 + if (assert) 1662 + udelay(100); 1663 + } 1664 + 1665 + static int a6xx_gmu_pm_resume(struct msm_gpu *gpu) 1849 1666 { 1850 1667 struct adreno_gpu *adreno_gpu = to_adreno_gpu(gpu); 1851 1668 struct a6xx_gpu *a6xx_gpu = to_a6xx_gpu(adreno_gpu); ··· 1924 1623 1925 1624 a6xx_llc_activate(a6xx_gpu); 1926 1625 1927 - return 0; 1626 + return ret; 1928 1627 } 1929 1628 1930 - static int a6xx_pm_suspend(struct msm_gpu *gpu) 1629 + static int a6xx_pm_resume(struct msm_gpu *gpu) 1630 + { 1631 + struct adreno_gpu *adreno_gpu = to_adreno_gpu(gpu); 1632 + struct a6xx_gpu *a6xx_gpu = to_a6xx_gpu(adreno_gpu); 1633 + struct a6xx_gmu *gmu = &a6xx_gpu->gmu; 1634 + unsigned long freq = gpu->fast_rate; 1635 + struct dev_pm_opp *opp; 1636 + int ret; 1637 + 1638 + gpu->needs_hw_init = true; 1639 + 1640 + trace_msm_gpu_resume(0); 1641 + 1642 + mutex_lock(&a6xx_gpu->gmu.lock); 1643 + 1644 + opp = dev_pm_opp_find_freq_ceil(&gpu->pdev->dev, &freq); 1645 + if (IS_ERR(opp)) { 1646 + ret = PTR_ERR(opp); 1647 + goto err_set_opp; 1648 + } 1649 + dev_pm_opp_put(opp); 1650 + 1651 + /* Set the core clock and bus bw, having VDD scaling in mind */ 1652 + dev_pm_opp_set_opp(&gpu->pdev->dev, opp); 1653 + 1654 + pm_runtime_resume_and_get(gmu->dev); 1655 + pm_runtime_resume_and_get(gmu->gxpd); 1656 + 1657 + ret = clk_bulk_prepare_enable(gpu->nr_clocks, gpu->grp_clks); 1658 + if (ret) 1659 + goto err_bulk_clk; 1660 + 1661 + if (adreno_is_a619_holi(adreno_gpu)) 1662 + a6xx_sptprac_enable(gmu); 1663 + 1664 + /* If anything goes south, tear the GPU down piece by piece.. */ 1665 + if (ret) { 1666 + err_bulk_clk: 1667 + pm_runtime_put(gmu->gxpd); 1668 + pm_runtime_put(gmu->dev); 1669 + dev_pm_opp_set_opp(&gpu->pdev->dev, NULL); 1670 + } 1671 + err_set_opp: 1672 + mutex_unlock(&a6xx_gpu->gmu.lock); 1673 + 1674 + if (!ret) 1675 + msm_devfreq_resume(gpu); 1676 + 1677 + return ret; 1678 + } 1679 + 1680 + static int a6xx_gmu_pm_suspend(struct msm_gpu *gpu) 1931 1681 { 1932 1682 struct adreno_gpu *adreno_gpu = to_adreno_gpu(gpu); 1933 1683 struct a6xx_gpu *a6xx_gpu = to_a6xx_gpu(adreno_gpu); ··· 2005 1653 return 0; 2006 1654 } 2007 1655 2008 - static int a6xx_get_timestamp(struct msm_gpu *gpu, uint64_t *value) 1656 + static int a6xx_pm_suspend(struct msm_gpu *gpu) 1657 + { 1658 + struct adreno_gpu *adreno_gpu = to_adreno_gpu(gpu); 1659 + struct a6xx_gpu *a6xx_gpu = to_a6xx_gpu(adreno_gpu); 1660 + struct a6xx_gmu *gmu = &a6xx_gpu->gmu; 1661 + int i; 1662 + 1663 + trace_msm_gpu_suspend(0); 1664 + 1665 + msm_devfreq_suspend(gpu); 1666 + 1667 + mutex_lock(&a6xx_gpu->gmu.lock); 1668 + 1669 + /* Drain the outstanding traffic on memory buses */ 1670 + a6xx_bus_clear_pending_transactions(adreno_gpu, true); 1671 + 1672 + if (adreno_is_a619_holi(adreno_gpu)) 1673 + a6xx_sptprac_disable(gmu); 1674 + 1675 + clk_bulk_disable_unprepare(gpu->nr_clocks, gpu->grp_clks); 1676 + 1677 + pm_runtime_put_sync(gmu->gxpd); 1678 + dev_pm_opp_set_opp(&gpu->pdev->dev, NULL); 1679 + pm_runtime_put_sync(gmu->dev); 1680 + 1681 + mutex_unlock(&a6xx_gpu->gmu.lock); 1682 + 1683 + if (a6xx_gpu->shadow_bo) 1684 + for (i = 0; i < gpu->nr_rings; i++) 1685 + a6xx_gpu->shadow[i] = 0; 1686 + 1687 + gpu->suspend_count++; 1688 + 1689 + return 0; 1690 + } 1691 + 1692 + static int a6xx_gmu_get_timestamp(struct msm_gpu *gpu, uint64_t *value) 2009 1693 { 2010 1694 struct adreno_gpu *adreno_gpu = to_adreno_gpu(gpu); 2011 1695 struct a6xx_gpu *a6xx_gpu = to_a6xx_gpu(adreno_gpu); ··· 2057 1669 2058 1670 mutex_unlock(&a6xx_gpu->gmu.lock); 2059 1671 1672 + return 0; 1673 + } 1674 + 1675 + static int a6xx_get_timestamp(struct msm_gpu *gpu, uint64_t *value) 1676 + { 1677 + *value = gpu_read64(gpu, REG_A6XX_CP_ALWAYS_ON_COUNTER); 2060 1678 return 0; 2061 1679 } 2062 1680 ··· 2138 1744 * This allows GPU to set the bus attributes required to use system 2139 1745 * cache on behalf of the iommu page table walker. 2140 1746 */ 2141 - if (!IS_ERR_OR_NULL(a6xx_gpu->htw_llc_slice)) 1747 + if (!IS_ERR_OR_NULL(a6xx_gpu->htw_llc_slice) && 1748 + !device_iommu_capable(&pdev->dev, IOMMU_CAP_CACHE_COHERENCY)) 2142 1749 quirks |= IO_PGTABLE_QUIRK_ARM_OUTER_WBWA; 2143 1750 2144 1751 return adreno_iommu_create_address_space(gpu, pdev, quirks); ··· 2204 1809 return progress; 2205 1810 } 2206 1811 1812 + static u32 a610_get_speed_bin(u32 fuse) 1813 + { 1814 + /* 1815 + * There are (at least) three SoCs implementing A610: SM6125 (trinket), 1816 + * SM6115 (bengal) and SM6225 (khaje). Trinket does not have speedbinning, 1817 + * as only a single SKU exists and we don't support khaje upstream yet. 1818 + * Hence, this matching table is only valid for bengal and can be easily 1819 + * expanded if need be. 1820 + */ 1821 + 1822 + if (fuse == 0) 1823 + return 0; 1824 + else if (fuse == 206) 1825 + return 1; 1826 + else if (fuse == 200) 1827 + return 2; 1828 + else if (fuse == 157) 1829 + return 3; 1830 + else if (fuse == 127) 1831 + return 4; 1832 + 1833 + return UINT_MAX; 1834 + } 1835 + 2207 1836 static u32 a618_get_speed_bin(u32 fuse) 2208 1837 { 2209 1838 if (fuse == 0) ··· 2236 1817 return 1; 2237 1818 else if (fuse == 174) 2238 1819 return 2; 1820 + 1821 + return UINT_MAX; 1822 + } 1823 + 1824 + static u32 a619_holi_get_speed_bin(u32 fuse) 1825 + { 1826 + /* 1827 + * There are (at least) two SoCs implementing A619_holi: SM4350 (holi) 1828 + * and SM6375 (blair). Limit the fuse matching to the corresponding 1829 + * SoC to prevent bogus frequency setting (as improbable as it may be, 1830 + * given unexpected fuse values are.. unexpected! But still possible.) 1831 + */ 1832 + 1833 + if (fuse == 0) 1834 + return 0; 1835 + 1836 + if (of_machine_is_compatible("qcom,sm4350")) { 1837 + if (fuse == 138) 1838 + return 1; 1839 + else if (fuse == 92) 1840 + return 2; 1841 + } else if (of_machine_is_compatible("qcom,sm6375")) { 1842 + if (fuse == 190) 1843 + return 1; 1844 + else if (fuse == 177) 1845 + return 2; 1846 + } else 1847 + pr_warn("Unknown SoC implementing A619_holi!\n"); 2239 1848 2240 1849 return UINT_MAX; 2241 1850 } ··· 2321 1874 return UINT_MAX; 2322 1875 } 2323 1876 2324 - static u32 fuse_to_supp_hw(struct device *dev, struct adreno_rev rev, u32 fuse) 1877 + static u32 fuse_to_supp_hw(struct device *dev, struct adreno_gpu *adreno_gpu, u32 fuse) 2325 1878 { 2326 1879 u32 val = UINT_MAX; 2327 1880 2328 - if (adreno_cmp_rev(ADRENO_REV(6, 1, 8, ANY_ID), rev)) 1881 + if (adreno_is_a610(adreno_gpu)) 1882 + val = a610_get_speed_bin(fuse); 1883 + 1884 + if (adreno_is_a618(adreno_gpu)) 2329 1885 val = a618_get_speed_bin(fuse); 2330 1886 2331 - if (adreno_cmp_rev(ADRENO_REV(6, 1, 9, ANY_ID), rev)) 1887 + else if (adreno_is_a619_holi(adreno_gpu)) 1888 + val = a619_holi_get_speed_bin(fuse); 1889 + 1890 + else if (adreno_is_a619(adreno_gpu)) 2332 1891 val = a619_get_speed_bin(fuse); 2333 1892 2334 - if (adreno_cmp_rev(ADRENO_REV(6, 3, 5, ANY_ID), rev)) 1893 + else if (adreno_is_7c3(adreno_gpu)) 2335 1894 val = adreno_7c3_get_speed_bin(fuse); 2336 1895 2337 - if (adreno_cmp_rev(ADRENO_REV(6, 4, 0, ANY_ID), rev)) 1896 + else if (adreno_is_a640(adreno_gpu)) 2338 1897 val = a640_get_speed_bin(fuse); 2339 1898 2340 - if (adreno_cmp_rev(ADRENO_REV(6, 5, 0, ANY_ID), rev)) 1899 + else if (adreno_is_a650(adreno_gpu)) 2341 1900 val = a650_get_speed_bin(fuse); 2342 1901 2343 1902 if (val == UINT_MAX) { ··· 2356 1903 return (1 << val); 2357 1904 } 2358 1905 2359 - static int a6xx_set_supported_hw(struct device *dev, struct adreno_rev rev) 1906 + static int a6xx_set_supported_hw(struct device *dev, struct adreno_gpu *adreno_gpu) 2360 1907 { 2361 1908 u32 supp_hw; 2362 1909 u32 speedbin; ··· 2375 1922 return ret; 2376 1923 } 2377 1924 2378 - supp_hw = fuse_to_supp_hw(dev, rev, speedbin); 1925 + supp_hw = fuse_to_supp_hw(dev, adreno_gpu, speedbin); 2379 1926 2380 1927 ret = devm_pm_opp_set_supported_hw(dev, &supp_hw, 1); 2381 1928 if (ret) ··· 2385 1932 } 2386 1933 2387 1934 static const struct adreno_gpu_funcs funcs = { 1935 + .base = { 1936 + .get_param = adreno_get_param, 1937 + .set_param = adreno_set_param, 1938 + .hw_init = a6xx_hw_init, 1939 + .ucode_load = a6xx_ucode_load, 1940 + .pm_suspend = a6xx_gmu_pm_suspend, 1941 + .pm_resume = a6xx_gmu_pm_resume, 1942 + .recover = a6xx_recover, 1943 + .submit = a6xx_submit, 1944 + .active_ring = a6xx_active_ring, 1945 + .irq = a6xx_irq, 1946 + .destroy = a6xx_destroy, 1947 + #if defined(CONFIG_DRM_MSM_GPU_STATE) 1948 + .show = a6xx_show, 1949 + #endif 1950 + .gpu_busy = a6xx_gpu_busy, 1951 + .gpu_get_freq = a6xx_gmu_get_freq, 1952 + .gpu_set_freq = a6xx_gpu_set_freq, 1953 + #if defined(CONFIG_DRM_MSM_GPU_STATE) 1954 + .gpu_state_get = a6xx_gpu_state_get, 1955 + .gpu_state_put = a6xx_gpu_state_put, 1956 + #endif 1957 + .create_address_space = a6xx_create_address_space, 1958 + .create_private_address_space = a6xx_create_private_address_space, 1959 + .get_rptr = a6xx_get_rptr, 1960 + .progress = a6xx_progress, 1961 + }, 1962 + .get_timestamp = a6xx_gmu_get_timestamp, 1963 + }; 1964 + 1965 + static const struct adreno_gpu_funcs funcs_gmuwrapper = { 2388 1966 .base = { 2389 1967 .get_param = adreno_get_param, 2390 1968 .set_param = adreno_set_param, ··· 2432 1948 .show = a6xx_show, 2433 1949 #endif 2434 1950 .gpu_busy = a6xx_gpu_busy, 2435 - .gpu_get_freq = a6xx_gmu_get_freq, 2436 - .gpu_set_freq = a6xx_gpu_set_freq, 2437 1951 #if defined(CONFIG_DRM_MSM_GPU_STATE) 2438 1952 .gpu_state_get = a6xx_gpu_state_get, 2439 1953 .gpu_state_put = a6xx_gpu_state_put, ··· 2467 1985 2468 1986 adreno_gpu->registers = NULL; 2469 1987 1988 + /* Check if there is a GMU phandle and set it up */ 1989 + node = of_parse_phandle(pdev->dev.of_node, "qcom,gmu", 0); 1990 + /* FIXME: How do we gracefully handle this? */ 1991 + BUG_ON(!node); 1992 + 1993 + adreno_gpu->gmu_is_wrapper = of_device_is_compatible(node, "qcom,adreno-gmu-wrapper"); 1994 + 2470 1995 /* 2471 1996 * We need to know the platform type before calling into adreno_gpu_init 2472 1997 * so that the hw_apriv flag can be correctly set. Snoop into the info 2473 1998 * and grab the revision number 2474 1999 */ 2475 2000 info = adreno_info(config->rev); 2001 + if (!info) 2002 + return ERR_PTR(-EINVAL); 2476 2003 2477 - if (info && (info->revn == 650 || info->revn == 660 || 2478 - adreno_cmp_rev(ADRENO_REV(6, 3, 5, ANY_ID), info->rev))) 2004 + /* Assign these early so that we can use the is_aXYZ helpers */ 2005 + /* Numeric revision IDs (e.g. 630) */ 2006 + adreno_gpu->revn = info->revn; 2007 + /* New-style ADRENO_REV()-only */ 2008 + adreno_gpu->rev = info->rev; 2009 + /* Quirk data */ 2010 + adreno_gpu->info = info; 2011 + 2012 + if (adreno_is_a650(adreno_gpu) || adreno_is_a660_family(adreno_gpu)) 2479 2013 adreno_gpu->base.hw_apriv = true; 2480 2014 2481 2015 a6xx_llc_slices_init(pdev, a6xx_gpu); 2482 2016 2483 - ret = a6xx_set_supported_hw(&pdev->dev, config->rev); 2017 + ret = a6xx_set_supported_hw(&pdev->dev, adreno_gpu); 2484 2018 if (ret) { 2485 2019 a6xx_destroy(&(a6xx_gpu->base.base)); 2486 2020 return ERR_PTR(ret); 2487 2021 } 2488 2022 2489 - ret = adreno_gpu_init(dev, pdev, adreno_gpu, &funcs, 1); 2023 + if (adreno_has_gmu_wrapper(adreno_gpu)) 2024 + ret = adreno_gpu_init(dev, pdev, adreno_gpu, &funcs_gmuwrapper, 1); 2025 + else 2026 + ret = adreno_gpu_init(dev, pdev, adreno_gpu, &funcs, 1); 2490 2027 if (ret) { 2491 2028 a6xx_destroy(&(a6xx_gpu->base.base)); 2492 2029 return ERR_PTR(ret); ··· 2518 2017 if (adreno_is_a618(adreno_gpu) || adreno_is_7c3(adreno_gpu)) 2519 2018 priv->gpu_clamp_to_idle = true; 2520 2019 2521 - /* Check if there is a GMU phandle and set it up */ 2522 - node = of_parse_phandle(pdev->dev.of_node, "qcom,gmu", 0); 2523 - 2524 - /* FIXME: How do we gracefully handle this? */ 2525 - BUG_ON(!node); 2526 - 2527 - ret = a6xx_gmu_init(a6xx_gpu, node); 2020 + if (adreno_has_gmu_wrapper(adreno_gpu)) 2021 + ret = a6xx_gmu_wrapper_init(a6xx_gpu, node); 2022 + else 2023 + ret = a6xx_gmu_init(a6xx_gpu, node); 2528 2024 of_node_put(node); 2529 2025 if (ret) { 2530 2026 a6xx_destroy(&(a6xx_gpu->base.base));
+4
drivers/gpu/drm/msm/adreno/a6xx_gpu.h
··· 76 76 void a6xx_gmu_clear_oob(struct a6xx_gmu *gmu, enum a6xx_gmu_oob_state state); 77 77 78 78 int a6xx_gmu_init(struct a6xx_gpu *a6xx_gpu, struct device_node *node); 79 + int a6xx_gmu_wrapper_init(struct a6xx_gpu *a6xx_gpu, struct device_node *node); 79 80 void a6xx_gmu_remove(struct a6xx_gpu *a6xx_gpu); 80 81 81 82 void a6xx_gmu_set_freq(struct msm_gpu *gpu, struct dev_pm_opp *opp, ··· 88 87 89 88 struct msm_gpu_state *a6xx_gpu_state_get(struct msm_gpu *gpu); 90 89 int a6xx_gpu_state_put(struct msm_gpu_state *state); 90 + 91 + void a6xx_bus_clear_pending_transactions(struct adreno_gpu *adreno_gpu, bool gx_off); 92 + void a6xx_gpu_sw_reset(struct msm_gpu *gpu, bool assert); 91 93 92 94 #endif /* __A6XX_GPU_H__ */
+8 -6
drivers/gpu/drm/msm/adreno/a6xx_gpu_state.c
··· 1041 1041 /* Get the generic state from the adreno core */ 1042 1042 adreno_gpu_state_get(gpu, &a6xx_state->base); 1043 1043 1044 - a6xx_get_gmu_registers(gpu, a6xx_state); 1044 + if (!adreno_has_gmu_wrapper(adreno_gpu)) { 1045 + a6xx_get_gmu_registers(gpu, a6xx_state); 1045 1046 1046 - a6xx_state->gmu_log = a6xx_snapshot_gmu_bo(a6xx_state, &a6xx_gpu->gmu.log); 1047 - a6xx_state->gmu_hfi = a6xx_snapshot_gmu_bo(a6xx_state, &a6xx_gpu->gmu.hfi); 1048 - a6xx_state->gmu_debug = a6xx_snapshot_gmu_bo(a6xx_state, &a6xx_gpu->gmu.debug); 1047 + a6xx_state->gmu_log = a6xx_snapshot_gmu_bo(a6xx_state, &a6xx_gpu->gmu.log); 1048 + a6xx_state->gmu_hfi = a6xx_snapshot_gmu_bo(a6xx_state, &a6xx_gpu->gmu.hfi); 1049 + a6xx_state->gmu_debug = a6xx_snapshot_gmu_bo(a6xx_state, &a6xx_gpu->gmu.debug); 1049 1050 1050 - a6xx_snapshot_gmu_hfi_history(gpu, a6xx_state); 1051 + a6xx_snapshot_gmu_hfi_history(gpu, a6xx_state); 1052 + } 1051 1053 1052 1054 /* If GX isn't on the rest of the data isn't going to be accessible */ 1053 - if (!a6xx_gmu_gx_is_on(&a6xx_gpu->gmu)) 1055 + if (!adreno_has_gmu_wrapper(adreno_gpu) && !a6xx_gmu_gx_is_on(&a6xx_gpu->gmu)) 1054 1056 return &a6xx_state->base; 1055 1057 1056 1058 /* Get the banks of indexed registers */
+33
drivers/gpu/drm/msm/adreno/a6xx_hfi.c
··· 414 414 msg->cnoc_cmds_data[1][0] = 0x60000001; 415 415 } 416 416 417 + static void a690_build_bw_table(struct a6xx_hfi_msg_bw_table *msg) 418 + { 419 + /* 420 + * Send a single "off" entry just to get things running 421 + * TODO: bus scaling 422 + */ 423 + msg->bw_level_num = 1; 424 + 425 + msg->ddr_cmds_num = 3; 426 + msg->ddr_wait_bitmask = 0x01; 427 + 428 + msg->ddr_cmds_addrs[0] = 0x50004; 429 + msg->ddr_cmds_addrs[1] = 0x50000; 430 + msg->ddr_cmds_addrs[2] = 0x500ac; 431 + 432 + msg->ddr_cmds_data[0][0] = 0x40000000; 433 + msg->ddr_cmds_data[0][1] = 0x40000000; 434 + msg->ddr_cmds_data[0][2] = 0x40000000; 435 + 436 + /* 437 + * These are the CX (CNOC) votes - these are used by the GMU but the 438 + * votes are known and fixed for the target 439 + */ 440 + msg->cnoc_cmds_num = 1; 441 + msg->cnoc_wait_bitmask = 0x01; 442 + 443 + msg->cnoc_cmds_addrs[0] = 0x5003c; 444 + msg->cnoc_cmds_data[0][0] = 0x40000000; 445 + msg->cnoc_cmds_data[1][0] = 0x60000001; 446 + } 447 + 417 448 static void a660_build_bw_table(struct a6xx_hfi_msg_bw_table *msg) 418 449 { 419 450 /* ··· 562 531 adreno_7c3_build_bw_table(&msg); 563 532 else if (adreno_is_a660(adreno_gpu)) 564 533 a660_build_bw_table(&msg); 534 + else if (adreno_is_a690(adreno_gpu)) 535 + a690_build_bw_table(&msg); 565 536 else 566 537 a6xx_build_bw_table(&msg); 567 538
+30 -1
drivers/gpu/drm/msm/adreno/adreno_device.c
··· 254 254 .init = a5xx_gpu_init, 255 255 .zapfw = "a540_zap.mdt", 256 256 }, { 257 + .rev = ADRENO_REV(6, 1, 0, ANY_ID), 258 + .revn = 610, 259 + .name = "A610", 260 + .fw = { 261 + [ADRENO_FW_SQE] = "a630_sqe.fw", 262 + }, 263 + .gmem = (SZ_128K + SZ_4K), 264 + .inactive_period = DRM_MSM_INACTIVE_PERIOD, 265 + .init = a6xx_gpu_init, 266 + .zapfw = "a610_zap.mdt", 267 + .hwcg = a612_hwcg, 268 + }, { 257 269 .rev = ADRENO_REV(6, 1, 8, ANY_ID), 258 270 .revn = 618, 259 271 .name = "A618", ··· 367 355 .init = a6xx_gpu_init, 368 356 .zapfw = "a640_zap.mdt", 369 357 .hwcg = a640_hwcg, 358 + }, { 359 + .rev = ADRENO_REV(6, 9, 0, ANY_ID), 360 + .revn = 690, 361 + .name = "A690", 362 + .fw = { 363 + [ADRENO_FW_SQE] = "a660_sqe.fw", 364 + [ADRENO_FW_GMU] = "a690_gmu.bin", 365 + }, 366 + .gmem = SZ_4M, 367 + .inactive_period = DRM_MSM_INACTIVE_PERIOD, 368 + .init = a6xx_gpu_init, 369 + .zapfw = "a690_zap.mdt", 370 + .hwcg = a690_hwcg, 371 + .address_space_size = SZ_16G, 370 372 }, 371 373 }; 372 374 ··· 577 551 config.rev.minor, config.rev.patchid); 578 552 579 553 priv->is_a2xx = config.rev.core == 2; 580 - priv->has_cached_coherent = config.rev.core >= 6; 581 554 582 555 gpu = info->init(drm); 583 556 if (IS_ERR(gpu)) { ··· 587 562 ret = dev_pm_opp_of_find_icc_paths(dev, NULL); 588 563 if (ret) 589 564 return ret; 565 + 566 + if (config.rev.core >= 6) 567 + if (!adreno_has_gmu_wrapper(to_adreno_gpu(gpu))) 568 + priv->has_cached_coherent = true; 590 569 591 570 return 0; 592 571 }
+6 -2
drivers/gpu/drm/msm/adreno/adreno_gpu.c
··· 528 528 if (!adreno_gpu->info->fw[i]) 529 529 continue; 530 530 531 + /* Skip loading GMU firwmare with GMU Wrapper */ 532 + if (adreno_has_gmu_wrapper(adreno_gpu) && i == ADRENO_FW_GMU) 533 + continue; 534 + 531 535 /* Skip if the firmware has already been loaded */ 532 536 if (adreno_gpu->fw[i]) 533 537 continue; ··· 1078 1074 u32 speedbin; 1079 1075 int ret; 1080 1076 1081 - /* Only handle the core clock when GMU is not in use */ 1082 - if (config->rev.core < 6) { 1077 + /* Only handle the core clock when GMU is not in use (or is absent). */ 1078 + if (adreno_has_gmu_wrapper(adreno_gpu) || config->rev.core < 6) { 1083 1079 /* 1084 1080 * This can only be done before devm_pm_opp_of_add_table(), or 1085 1081 * dev_pm_opp_set_config() will WARN_ON()
+101 -53
drivers/gpu/drm/msm/adreno/adreno_gpu.h
··· 55 55 u32 value; 56 56 }; 57 57 58 - extern const struct adreno_reglist a615_hwcg[], a630_hwcg[], a640_hwcg[], a650_hwcg[], a660_hwcg[]; 58 + extern const struct adreno_reglist a612_hwcg[], a615_hwcg[], a630_hwcg[], a640_hwcg[], a650_hwcg[]; 59 + extern const struct adreno_reglist a660_hwcg[], a690_hwcg[]; 59 60 60 61 struct adreno_info { 61 62 struct adreno_rev rev; ··· 116 115 * code (a3xx_gpu.c) and stored in this common location. 117 116 */ 118 117 const unsigned int *reg_offsets; 118 + bool gmu_is_wrapper; 119 119 }; 120 120 #define to_adreno_gpu(x) container_of(x, struct adreno_gpu, base) 121 121 ··· 147 145 148 146 bool adreno_cmp_rev(struct adreno_rev rev1, struct adreno_rev rev2); 149 147 150 - static inline bool adreno_is_a2xx(struct adreno_gpu *gpu) 148 + static inline bool adreno_is_revn(const struct adreno_gpu *gpu, uint32_t revn) 151 149 { 150 + WARN_ON_ONCE(!gpu->revn); 151 + 152 + return gpu->revn == revn; 153 + } 154 + 155 + static inline bool adreno_has_gmu_wrapper(const struct adreno_gpu *gpu) 156 + { 157 + return gpu->gmu_is_wrapper; 158 + } 159 + 160 + static inline bool adreno_is_a2xx(const struct adreno_gpu *gpu) 161 + { 162 + WARN_ON_ONCE(!gpu->revn); 163 + 152 164 return (gpu->revn < 300); 153 165 } 154 166 155 - static inline bool adreno_is_a20x(struct adreno_gpu *gpu) 167 + static inline bool adreno_is_a20x(const struct adreno_gpu *gpu) 156 168 { 169 + WARN_ON_ONCE(!gpu->revn); 170 + 157 171 return (gpu->revn < 210); 158 172 } 159 173 160 - static inline bool adreno_is_a225(struct adreno_gpu *gpu) 174 + static inline bool adreno_is_a225(const struct adreno_gpu *gpu) 161 175 { 162 - return gpu->revn == 225; 176 + return adreno_is_revn(gpu, 225); 163 177 } 164 178 165 - static inline bool adreno_is_a305(struct adreno_gpu *gpu) 179 + static inline bool adreno_is_a305(const struct adreno_gpu *gpu) 166 180 { 167 - return gpu->revn == 305; 181 + return adreno_is_revn(gpu, 305); 168 182 } 169 183 170 - static inline bool adreno_is_a306(struct adreno_gpu *gpu) 184 + static inline bool adreno_is_a306(const struct adreno_gpu *gpu) 171 185 { 172 186 /* yes, 307, because a305c is 306 */ 173 - return gpu->revn == 307; 187 + return adreno_is_revn(gpu, 307); 174 188 } 175 189 176 - static inline bool adreno_is_a320(struct adreno_gpu *gpu) 190 + static inline bool adreno_is_a320(const struct adreno_gpu *gpu) 177 191 { 178 - return gpu->revn == 320; 192 + return adreno_is_revn(gpu, 320); 179 193 } 180 194 181 - static inline bool adreno_is_a330(struct adreno_gpu *gpu) 195 + static inline bool adreno_is_a330(const struct adreno_gpu *gpu) 182 196 { 183 - return gpu->revn == 330; 197 + return adreno_is_revn(gpu, 330); 184 198 } 185 199 186 - static inline bool adreno_is_a330v2(struct adreno_gpu *gpu) 200 + static inline bool adreno_is_a330v2(const struct adreno_gpu *gpu) 187 201 { 188 202 return adreno_is_a330(gpu) && (gpu->rev.patchid > 0); 189 203 } 190 204 191 - static inline int adreno_is_a405(struct adreno_gpu *gpu) 205 + static inline int adreno_is_a405(const struct adreno_gpu *gpu) 192 206 { 193 - return gpu->revn == 405; 207 + return adreno_is_revn(gpu, 405); 194 208 } 195 209 196 - static inline int adreno_is_a420(struct adreno_gpu *gpu) 210 + static inline int adreno_is_a420(const struct adreno_gpu *gpu) 197 211 { 198 - return gpu->revn == 420; 212 + return adreno_is_revn(gpu, 420); 199 213 } 200 214 201 - static inline int adreno_is_a430(struct adreno_gpu *gpu) 215 + static inline int adreno_is_a430(const struct adreno_gpu *gpu) 202 216 { 203 - return gpu->revn == 430; 217 + return adreno_is_revn(gpu, 430); 204 218 } 205 219 206 - static inline int adreno_is_a506(struct adreno_gpu *gpu) 220 + static inline int adreno_is_a506(const struct adreno_gpu *gpu) 207 221 { 208 - return gpu->revn == 506; 222 + return adreno_is_revn(gpu, 506); 209 223 } 210 224 211 - static inline int adreno_is_a508(struct adreno_gpu *gpu) 225 + static inline int adreno_is_a508(const struct adreno_gpu *gpu) 212 226 { 213 - return gpu->revn == 508; 227 + return adreno_is_revn(gpu, 508); 214 228 } 215 229 216 - static inline int adreno_is_a509(struct adreno_gpu *gpu) 230 + static inline int adreno_is_a509(const struct adreno_gpu *gpu) 217 231 { 218 - return gpu->revn == 509; 232 + return adreno_is_revn(gpu, 509); 219 233 } 220 234 221 - static inline int adreno_is_a510(struct adreno_gpu *gpu) 235 + static inline int adreno_is_a510(const struct adreno_gpu *gpu) 222 236 { 223 - return gpu->revn == 510; 237 + return adreno_is_revn(gpu, 510); 224 238 } 225 239 226 - static inline int adreno_is_a512(struct adreno_gpu *gpu) 240 + static inline int adreno_is_a512(const struct adreno_gpu *gpu) 227 241 { 228 - return gpu->revn == 512; 242 + return adreno_is_revn(gpu, 512); 229 243 } 230 244 231 - static inline int adreno_is_a530(struct adreno_gpu *gpu) 245 + static inline int adreno_is_a530(const struct adreno_gpu *gpu) 232 246 { 233 - return gpu->revn == 530; 247 + return adreno_is_revn(gpu, 530); 234 248 } 235 249 236 - static inline int adreno_is_a540(struct adreno_gpu *gpu) 250 + static inline int adreno_is_a540(const struct adreno_gpu *gpu) 237 251 { 238 - return gpu->revn == 540; 252 + return adreno_is_revn(gpu, 540); 239 253 } 240 254 241 - static inline int adreno_is_a618(struct adreno_gpu *gpu) 255 + static inline int adreno_is_a610(const struct adreno_gpu *gpu) 242 256 { 243 - return gpu->revn == 618; 257 + return adreno_is_revn(gpu, 610); 244 258 } 245 259 246 - static inline int adreno_is_a619(struct adreno_gpu *gpu) 260 + static inline int adreno_is_a618(const struct adreno_gpu *gpu) 247 261 { 248 - return gpu->revn == 619; 262 + return adreno_is_revn(gpu, 618); 249 263 } 250 264 251 - static inline int adreno_is_a630(struct adreno_gpu *gpu) 265 + static inline int adreno_is_a619(const struct adreno_gpu *gpu) 252 266 { 253 - return gpu->revn == 630; 267 + return adreno_is_revn(gpu, 619); 254 268 } 255 269 256 - static inline int adreno_is_a640_family(struct adreno_gpu *gpu) 270 + static inline int adreno_is_a619_holi(const struct adreno_gpu *gpu) 257 271 { 258 - return (gpu->revn == 640) || (gpu->revn == 680); 272 + return adreno_is_a619(gpu) && adreno_has_gmu_wrapper(gpu); 259 273 } 260 274 261 - static inline int adreno_is_a650(struct adreno_gpu *gpu) 275 + static inline int adreno_is_a630(const struct adreno_gpu *gpu) 262 276 { 263 - return gpu->revn == 650; 277 + return adreno_is_revn(gpu, 630); 264 278 } 265 279 266 - static inline int adreno_is_7c3(struct adreno_gpu *gpu) 280 + static inline int adreno_is_a640(const struct adreno_gpu *gpu) 281 + { 282 + return adreno_is_revn(gpu, 640); 283 + } 284 + 285 + static inline int adreno_is_a650(const struct adreno_gpu *gpu) 286 + { 287 + return adreno_is_revn(gpu, 650); 288 + } 289 + 290 + static inline int adreno_is_7c3(const struct adreno_gpu *gpu) 267 291 { 268 292 /* The order of args is important here to handle ANY_ID correctly */ 269 293 return adreno_cmp_rev(ADRENO_REV(6, 3, 5, ANY_ID), gpu->rev); 270 294 } 271 295 272 - static inline int adreno_is_a660(struct adreno_gpu *gpu) 296 + static inline int adreno_is_a660(const struct adreno_gpu *gpu) 273 297 { 274 - return gpu->revn == 660; 298 + return adreno_is_revn(gpu, 660); 275 299 } 300 + 301 + static inline int adreno_is_a680(const struct adreno_gpu *gpu) 302 + { 303 + return adreno_is_revn(gpu, 680); 304 + } 305 + 306 + static inline int adreno_is_a690(const struct adreno_gpu *gpu) 307 + { 308 + return adreno_is_revn(gpu, 690); 309 + }; 276 310 277 311 /* check for a615, a616, a618, a619 or any derivatives */ 278 - static inline int adreno_is_a615_family(struct adreno_gpu *gpu) 312 + static inline int adreno_is_a615_family(const struct adreno_gpu *gpu) 279 313 { 280 - return gpu->revn == 615 || gpu->revn == 616 || gpu->revn == 618 || gpu->revn == 619; 314 + return adreno_is_revn(gpu, 615) || 315 + adreno_is_revn(gpu, 616) || 316 + adreno_is_revn(gpu, 618) || 317 + adreno_is_revn(gpu, 619); 281 318 } 282 319 283 - static inline int adreno_is_a660_family(struct adreno_gpu *gpu) 320 + static inline int adreno_is_a660_family(const struct adreno_gpu *gpu) 284 321 { 285 - return adreno_is_a660(gpu) || adreno_is_7c3(gpu); 322 + return adreno_is_a660(gpu) || adreno_is_a690(gpu) || adreno_is_7c3(gpu); 286 323 } 287 324 288 325 /* check for a650, a660, or any derivatives */ 289 - static inline int adreno_is_a650_family(struct adreno_gpu *gpu) 326 + static inline int adreno_is_a650_family(const struct adreno_gpu *gpu) 290 327 { 291 - return gpu->revn == 650 || gpu->revn == 620 || adreno_is_a660_family(gpu); 328 + return adreno_is_revn(gpu, 650) || 329 + adreno_is_revn(gpu, 620) || 330 + adreno_is_a660_family(gpu); 331 + } 332 + 333 + static inline int adreno_is_a640_family(const struct adreno_gpu *gpu) 334 + { 335 + return adreno_is_a640(gpu) || adreno_is_a680(gpu); 292 336 } 293 337 294 338 u64 adreno_private_address_space_size(struct msm_gpu *gpu);
+30 -16
drivers/gpu/drm/msm/disp/dpu1/catalog/dpu_3_0_msm8998.h
··· 30 30 { 31 31 .name = "top_0", .id = MDP_TOP, 32 32 .base = 0x0, .len = 0x458, 33 - .features = 0, 33 + .features = BIT(DPU_MDP_VSYNC_SEL), 34 34 .clk_ctrls[DPU_CLK_CTRL_VIG0] = { .reg_off = 0x2ac, .bit_off = 0 }, 35 35 .clk_ctrls[DPU_CLK_CTRL_VIG1] = { .reg_off = 0x2b4, .bit_off = 0 }, 36 36 .clk_ctrls[DPU_CLK_CTRL_VIG2] = { .reg_off = 0x2bc, .bit_off = 0 }, ··· 39 39 .clk_ctrls[DPU_CLK_CTRL_DMA1] = { .reg_off = 0x2b4, .bit_off = 8 }, 40 40 .clk_ctrls[DPU_CLK_CTRL_DMA2] = { .reg_off = 0x2c4, .bit_off = 8 }, 41 41 .clk_ctrls[DPU_CLK_CTRL_DMA3] = { .reg_off = 0x2c4, .bit_off = 12 }, 42 - .clk_ctrls[DPU_CLK_CTRL_CURSOR0] = { .reg_off = 0x3a8, .bit_off = 15 }, 43 - .clk_ctrls[DPU_CLK_CTRL_CURSOR1] = { .reg_off = 0x3b0, .bit_off = 15 }, 42 + .clk_ctrls[DPU_CLK_CTRL_CURSOR0] = { .reg_off = 0x3a8, .bit_off = 16 }, 43 + .clk_ctrls[DPU_CLK_CTRL_CURSOR1] = { .reg_off = 0x3b0, .bit_off = 16 }, 44 44 }, 45 45 }; 46 46 ··· 104 104 LM_BLK("lm_2", LM_2, 0x46000, MIXER_MSM8998_MASK, 105 105 &msm8998_lm_sblk, PINGPONG_2, LM_5, 0), 106 106 LM_BLK("lm_3", LM_3, 0x47000, MIXER_MSM8998_MASK, 107 - &msm8998_lm_sblk, PINGPONG_MAX, 0, 0), 107 + &msm8998_lm_sblk, PINGPONG_NONE, 0, 0), 108 108 LM_BLK("lm_4", LM_4, 0x48000, MIXER_MSM8998_MASK, 109 - &msm8998_lm_sblk, PINGPONG_MAX, 0, 0), 109 + &msm8998_lm_sblk, PINGPONG_NONE, 0, 0), 110 110 LM_BLK("lm_5", LM_5, 0x49000, MIXER_MSM8998_MASK, 111 111 &msm8998_lm_sblk, PINGPONG_3, LM_2, 0), 112 112 }; 113 113 114 114 static const struct dpu_pingpong_cfg msm8998_pp[] = { 115 - PP_BLK_TE("pingpong_0", PINGPONG_0, 0x70000, 0, sdm845_pp_sblk_te, 115 + PP_BLK("pingpong_0", PINGPONG_0, 0x70000, PINGPONG_SDM845_TE2_MASK, 0, sdm845_pp_sblk_te, 116 116 DPU_IRQ_IDX(MDP_SSPP_TOP0_INTR, 8), 117 117 DPU_IRQ_IDX(MDP_SSPP_TOP0_INTR, 12)), 118 - PP_BLK_TE("pingpong_1", PINGPONG_1, 0x70800, 0, sdm845_pp_sblk_te, 118 + PP_BLK("pingpong_1", PINGPONG_1, 0x70800, PINGPONG_SDM845_TE2_MASK, 0, sdm845_pp_sblk_te, 119 119 DPU_IRQ_IDX(MDP_SSPP_TOP0_INTR, 9), 120 120 DPU_IRQ_IDX(MDP_SSPP_TOP0_INTR, 13)), 121 - PP_BLK("pingpong_2", PINGPONG_2, 0x71000, 0, sdm845_pp_sblk, 121 + PP_BLK("pingpong_2", PINGPONG_2, 0x71000, PINGPONG_SDM845_MASK, 0, sdm845_pp_sblk, 122 122 DPU_IRQ_IDX(MDP_SSPP_TOP0_INTR, 10), 123 123 DPU_IRQ_IDX(MDP_SSPP_TOP0_INTR, 14)), 124 - PP_BLK("pingpong_3", PINGPONG_3, 0x71800, 0, sdm845_pp_sblk, 124 + PP_BLK("pingpong_3", PINGPONG_3, 0x71800, PINGPONG_SDM845_MASK, 0, sdm845_pp_sblk, 125 125 DPU_IRQ_IDX(MDP_SSPP_TOP0_INTR, 11), 126 126 DPU_IRQ_IDX(MDP_SSPP_TOP0_INTR, 15)), 127 127 }; 128 128 129 + static const struct dpu_dsc_cfg msm8998_dsc[] = { 130 + DSC_BLK("dsc_0", DSC_0, 0x80000, 0), 131 + DSC_BLK("dsc_1", DSC_1, 0x80400, 0), 132 + }; 133 + 129 134 static const struct dpu_dspp_cfg msm8998_dspp[] = { 130 - DSPP_BLK("dspp_0", DSPP_0, 0x54000, DSPP_MSM8998_MASK, 135 + DSPP_BLK("dspp_0", DSPP_0, 0x54000, DSPP_SC7180_MASK, 131 136 &msm8998_dspp_sblk), 132 - DSPP_BLK("dspp_1", DSPP_1, 0x56000, DSPP_MSM8998_MASK, 137 + DSPP_BLK("dspp_1", DSPP_1, 0x56000, DSPP_SC7180_MASK, 133 138 &msm8998_dspp_sblk), 134 139 }; 135 140 136 141 static const struct dpu_intf_cfg msm8998_intf[] = { 137 - INTF_BLK("intf_0", INTF_0, 0x6a000, 0x280, INTF_DP, 0, 21, INTF_SDM845_MASK, MDP_SSPP_TOP0_INTR, 24, 25), 138 - INTF_BLK("intf_1", INTF_1, 0x6a800, 0x280, INTF_DSI, 0, 21, INTF_SDM845_MASK, MDP_SSPP_TOP0_INTR, 26, 27), 139 - INTF_BLK("intf_2", INTF_2, 0x6b000, 0x280, INTF_DSI, 1, 21, INTF_SDM845_MASK, MDP_SSPP_TOP0_INTR, 28, 29), 140 - INTF_BLK("intf_3", INTF_3, 0x6b800, 0x280, INTF_HDMI, 0, 21, INTF_SDM845_MASK, MDP_SSPP_TOP0_INTR, 30, 31), 142 + INTF_BLK("intf_0", INTF_0, 0x6a000, 0x280, INTF_DP, 0, 21, INTF_SDM845_MASK, 143 + DPU_IRQ_IDX(MDP_SSPP_TOP0_INTR, 24), 144 + DPU_IRQ_IDX(MDP_SSPP_TOP0_INTR, 25)), 145 + INTF_BLK("intf_1", INTF_1, 0x6a800, 0x280, INTF_DSI, 0, 21, INTF_SDM845_MASK, 146 + DPU_IRQ_IDX(MDP_SSPP_TOP0_INTR, 26), 147 + DPU_IRQ_IDX(MDP_SSPP_TOP0_INTR, 27)), 148 + INTF_BLK("intf_2", INTF_2, 0x6b000, 0x280, INTF_DSI, 1, 21, INTF_SDM845_MASK, 149 + DPU_IRQ_IDX(MDP_SSPP_TOP0_INTR, 28), 150 + DPU_IRQ_IDX(MDP_SSPP_TOP0_INTR, 29)), 151 + INTF_BLK("intf_3", INTF_3, 0x6b800, 0x280, INTF_HDMI, 0, 21, INTF_SDM845_MASK, 152 + DPU_IRQ_IDX(MDP_SSPP_TOP0_INTR, 30), 153 + DPU_IRQ_IDX(MDP_SSPP_TOP0_INTR, 31)), 141 154 }; 142 155 143 156 static const struct dpu_perf_cfg msm8998_perf_data = { ··· 204 191 .dspp = msm8998_dspp, 205 192 .pingpong_count = ARRAY_SIZE(msm8998_pp), 206 193 .pingpong = msm8998_pp, 194 + .dsc_count = ARRAY_SIZE(msm8998_dsc), 195 + .dsc = msm8998_dsc, 207 196 .intf_count = ARRAY_SIZE(msm8998_intf), 208 197 .intf = msm8998_intf, 209 198 .vbif_count = ARRAY_SIZE(msm8998_vbif), 210 199 .vbif = msm8998_vbif, 211 - .reg_dma_count = 0, 212 200 .perf = &msm8998_perf_data, 213 201 .mdss_irqs = BIT(MDP_SSPP_TOP0_INTR) | \ 214 202 BIT(MDP_SSPP_TOP0_INTR2) | \
+35 -16
drivers/gpu/drm/msm/disp/dpu1/catalog/dpu_4_0_sdm845.h
··· 30 30 { 31 31 .name = "top_0", .id = MDP_TOP, 32 32 .base = 0x0, .len = 0x45c, 33 - .features = BIT(DPU_MDP_AUDIO_SELECT), 33 + .features = BIT(DPU_MDP_AUDIO_SELECT) | BIT(DPU_MDP_VSYNC_SEL), 34 34 .clk_ctrls[DPU_CLK_CTRL_VIG0] = { .reg_off = 0x2ac, .bit_off = 0 }, 35 35 .clk_ctrls[DPU_CLK_CTRL_VIG1] = { .reg_off = 0x2b4, .bit_off = 0 }, 36 36 .clk_ctrls[DPU_CLK_CTRL_VIG2] = { .reg_off = 0x2bc, .bit_off = 0 }, ··· 96 96 97 97 static const struct dpu_lm_cfg sdm845_lm[] = { 98 98 LM_BLK("lm_0", LM_0, 0x44000, MIXER_SDM845_MASK, 99 - &sdm845_lm_sblk, PINGPONG_0, LM_1, 0), 99 + &sdm845_lm_sblk, PINGPONG_0, LM_1, DSPP_0), 100 100 LM_BLK("lm_1", LM_1, 0x45000, MIXER_SDM845_MASK, 101 - &sdm845_lm_sblk, PINGPONG_1, LM_0, 0), 101 + &sdm845_lm_sblk, PINGPONG_1, LM_0, DSPP_1), 102 102 LM_BLK("lm_2", LM_2, 0x46000, MIXER_SDM845_MASK, 103 - &sdm845_lm_sblk, PINGPONG_2, LM_5, 0), 103 + &sdm845_lm_sblk, PINGPONG_2, LM_5, DSPP_2), 104 104 LM_BLK("lm_3", LM_3, 0x0, MIXER_SDM845_MASK, 105 - &sdm845_lm_sblk, PINGPONG_MAX, 0, 0), 105 + &sdm845_lm_sblk, PINGPONG_NONE, 0, DSPP_3), 106 106 LM_BLK("lm_4", LM_4, 0x0, MIXER_SDM845_MASK, 107 - &sdm845_lm_sblk, PINGPONG_MAX, 0, 0), 107 + &sdm845_lm_sblk, PINGPONG_NONE, 0, 0), 108 108 LM_BLK("lm_5", LM_5, 0x49000, MIXER_SDM845_MASK, 109 109 &sdm845_lm_sblk, PINGPONG_3, LM_2, 0), 110 110 }; 111 111 112 + static const struct dpu_dspp_cfg sdm845_dspp[] = { 113 + DSPP_BLK("dspp_0", DSPP_0, 0x54000, DSPP_SC7180_MASK, 114 + &sm8150_dspp_sblk), 115 + DSPP_BLK("dspp_1", DSPP_1, 0x56000, DSPP_SC7180_MASK, 116 + &sm8150_dspp_sblk), 117 + DSPP_BLK("dspp_2", DSPP_2, 0x58000, DSPP_SC7180_MASK, 118 + &sm8150_dspp_sblk), 119 + DSPP_BLK("dspp_3", DSPP_3, 0x5a000, DSPP_SC7180_MASK, 120 + &sm8150_dspp_sblk), 121 + }; 122 + 112 123 static const struct dpu_pingpong_cfg sdm845_pp[] = { 113 - PP_BLK_TE("pingpong_0", PINGPONG_0, 0x70000, 0, sdm845_pp_sblk_te, 124 + PP_BLK("pingpong_0", PINGPONG_0, 0x70000, PINGPONG_SDM845_TE2_MASK, 0, sdm845_pp_sblk_te, 114 125 DPU_IRQ_IDX(MDP_SSPP_TOP0_INTR, 8), 115 126 DPU_IRQ_IDX(MDP_SSPP_TOP0_INTR, 12)), 116 - PP_BLK_TE("pingpong_1", PINGPONG_1, 0x70800, 0, sdm845_pp_sblk_te, 127 + PP_BLK("pingpong_1", PINGPONG_1, 0x70800, PINGPONG_SDM845_TE2_MASK, 0, sdm845_pp_sblk_te, 117 128 DPU_IRQ_IDX(MDP_SSPP_TOP0_INTR, 9), 118 129 DPU_IRQ_IDX(MDP_SSPP_TOP0_INTR, 13)), 119 - PP_BLK("pingpong_2", PINGPONG_2, 0x71000, 0, sdm845_pp_sblk, 130 + PP_BLK("pingpong_2", PINGPONG_2, 0x71000, PINGPONG_SDM845_MASK, 0, sdm845_pp_sblk, 120 131 DPU_IRQ_IDX(MDP_SSPP_TOP0_INTR, 10), 121 132 DPU_IRQ_IDX(MDP_SSPP_TOP0_INTR, 14)), 122 - PP_BLK("pingpong_3", PINGPONG_3, 0x71800, 0, sdm845_pp_sblk, 133 + PP_BLK("pingpong_3", PINGPONG_3, 0x71800, PINGPONG_SDM845_MASK, 0, sdm845_pp_sblk, 123 134 DPU_IRQ_IDX(MDP_SSPP_TOP0_INTR, 11), 124 135 DPU_IRQ_IDX(MDP_SSPP_TOP0_INTR, 15)), 125 136 }; ··· 143 132 }; 144 133 145 134 static const struct dpu_intf_cfg sdm845_intf[] = { 146 - INTF_BLK("intf_0", INTF_0, 0x6a000, 0x280, INTF_DP, 0, 24, INTF_SDM845_MASK, MDP_SSPP_TOP0_INTR, 24, 25), 147 - INTF_BLK("intf_1", INTF_1, 0x6a800, 0x280, INTF_DSI, 0, 24, INTF_SDM845_MASK, MDP_SSPP_TOP0_INTR, 26, 27), 148 - INTF_BLK("intf_2", INTF_2, 0x6b000, 0x280, INTF_DSI, 1, 24, INTF_SDM845_MASK, MDP_SSPP_TOP0_INTR, 28, 29), 149 - INTF_BLK("intf_3", INTF_3, 0x6b800, 0x280, INTF_DP, 1, 24, INTF_SDM845_MASK, MDP_SSPP_TOP0_INTR, 30, 31), 135 + INTF_BLK("intf_0", INTF_0, 0x6a000, 0x280, INTF_DP, 0, 24, INTF_SDM845_MASK, 136 + DPU_IRQ_IDX(MDP_SSPP_TOP0_INTR, 24), 137 + DPU_IRQ_IDX(MDP_SSPP_TOP0_INTR, 25)), 138 + INTF_BLK("intf_1", INTF_1, 0x6a800, 0x280, INTF_DSI, 0, 24, INTF_SDM845_MASK, 139 + DPU_IRQ_IDX(MDP_SSPP_TOP0_INTR, 26), 140 + DPU_IRQ_IDX(MDP_SSPP_TOP0_INTR, 27)), 141 + INTF_BLK("intf_2", INTF_2, 0x6b000, 0x280, INTF_DSI, 1, 24, INTF_SDM845_MASK, 142 + DPU_IRQ_IDX(MDP_SSPP_TOP0_INTR, 28), 143 + DPU_IRQ_IDX(MDP_SSPP_TOP0_INTR, 29)), 144 + INTF_BLK("intf_3", INTF_3, 0x6b800, 0x280, INTF_DP, 1, 24, INTF_SDM845_MASK, 145 + DPU_IRQ_IDX(MDP_SSPP_TOP0_INTR, 30), 146 + DPU_IRQ_IDX(MDP_SSPP_TOP0_INTR, 31)), 150 147 }; 151 148 152 149 static const struct dpu_perf_cfg sdm845_perf_data = { ··· 204 185 .sspp = sdm845_sspp, 205 186 .mixer_count = ARRAY_SIZE(sdm845_lm), 206 187 .mixer = sdm845_lm, 188 + .dspp_count = ARRAY_SIZE(sdm845_dspp), 189 + .dspp = sdm845_dspp, 207 190 .pingpong_count = ARRAY_SIZE(sdm845_pp), 208 191 .pingpong = sdm845_pp, 209 192 .dsc_count = ARRAY_SIZE(sdm845_dsc), ··· 214 193 .intf = sdm845_intf, 215 194 .vbif_count = ARRAY_SIZE(sdm845_vbif), 216 195 .vbif = sdm845_vbif, 217 - .reg_dma_count = 1, 218 - .dma_cfg = &sdm845_regdma, 219 196 .perf = &sdm845_perf_data, 220 197 .mdss_irqs = BIT(MDP_SSPP_TOP0_INTR) | \ 221 198 BIT(MDP_SSPP_TOP0_INTR2) | \
+26 -16
drivers/gpu/drm/msm/disp/dpu1/catalog/dpu_5_0_sm8150.h
··· 128 128 }; 129 129 130 130 static const struct dpu_pingpong_cfg sm8150_pp[] = { 131 - PP_BLK("pingpong_0", PINGPONG_0, 0x70000, MERGE_3D_0, sdm845_pp_sblk, 131 + PP_BLK("pingpong_0", PINGPONG_0, 0x70000, PINGPONG_SM8150_MASK, MERGE_3D_0, sdm845_pp_sblk, 132 132 DPU_IRQ_IDX(MDP_SSPP_TOP0_INTR, 8), 133 - DPU_IRQ_IDX(MDP_SSPP_TOP0_INTR, 12)), 134 - PP_BLK("pingpong_1", PINGPONG_1, 0x70800, MERGE_3D_0, sdm845_pp_sblk, 133 + -1), 134 + PP_BLK("pingpong_1", PINGPONG_1, 0x70800, PINGPONG_SM8150_MASK, MERGE_3D_0, sdm845_pp_sblk, 135 135 DPU_IRQ_IDX(MDP_SSPP_TOP0_INTR, 9), 136 - DPU_IRQ_IDX(MDP_SSPP_TOP0_INTR, 13)), 137 - PP_BLK("pingpong_2", PINGPONG_2, 0x71000, MERGE_3D_1, sdm845_pp_sblk, 136 + -1), 137 + PP_BLK("pingpong_2", PINGPONG_2, 0x71000, PINGPONG_SM8150_MASK, MERGE_3D_1, sdm845_pp_sblk, 138 138 DPU_IRQ_IDX(MDP_SSPP_TOP0_INTR, 10), 139 - DPU_IRQ_IDX(MDP_SSPP_TOP0_INTR, 14)), 140 - PP_BLK("pingpong_3", PINGPONG_3, 0x71800, MERGE_3D_1, sdm845_pp_sblk, 139 + -1), 140 + PP_BLK("pingpong_3", PINGPONG_3, 0x71800, PINGPONG_SM8150_MASK, MERGE_3D_1, sdm845_pp_sblk, 141 141 DPU_IRQ_IDX(MDP_SSPP_TOP0_INTR, 11), 142 - DPU_IRQ_IDX(MDP_SSPP_TOP0_INTR, 15)), 143 - PP_BLK("pingpong_4", PINGPONG_4, 0x72000, MERGE_3D_2, sdm845_pp_sblk, 142 + -1), 143 + PP_BLK("pingpong_4", PINGPONG_4, 0x72000, PINGPONG_SM8150_MASK, MERGE_3D_2, sdm845_pp_sblk, 144 144 DPU_IRQ_IDX(MDP_SSPP_TOP0_INTR2, 30), 145 145 -1), 146 - PP_BLK("pingpong_5", PINGPONG_5, 0x72800, MERGE_3D_2, sdm845_pp_sblk, 146 + PP_BLK("pingpong_5", PINGPONG_5, 0x72800, PINGPONG_SM8150_MASK, MERGE_3D_2, sdm845_pp_sblk, 147 147 DPU_IRQ_IDX(MDP_SSPP_TOP0_INTR2, 31), 148 148 -1), 149 149 }; ··· 162 162 }; 163 163 164 164 static const struct dpu_intf_cfg sm8150_intf[] = { 165 - INTF_BLK("intf_0", INTF_0, 0x6a000, 0x280, INTF_DP, 0, 24, INTF_SC7180_MASK, MDP_SSPP_TOP0_INTR, 24, 25), 166 - INTF_BLK("intf_1", INTF_1, 0x6a800, 0x2bc, INTF_DSI, 0, 24, INTF_SC7180_MASK, MDP_SSPP_TOP0_INTR, 26, 27), 167 - INTF_BLK("intf_2", INTF_2, 0x6b000, 0x2bc, INTF_DSI, 1, 24, INTF_SC7180_MASK, MDP_SSPP_TOP0_INTR, 28, 29), 168 - INTF_BLK("intf_3", INTF_3, 0x6b800, 0x280, INTF_DP, 1, 24, INTF_SC7180_MASK, MDP_SSPP_TOP0_INTR, 30, 31), 165 + INTF_BLK("intf_0", INTF_0, 0x6a000, 0x280, INTF_DP, 0, 24, INTF_SC7180_MASK, 166 + DPU_IRQ_IDX(MDP_SSPP_TOP0_INTR, 24), 167 + DPU_IRQ_IDX(MDP_SSPP_TOP0_INTR, 25)), 168 + INTF_BLK_DSI_TE("intf_1", INTF_1, 0x6a800, 0x2bc, INTF_DSI, 0, 24, INTF_SC7180_MASK, 169 + DPU_IRQ_IDX(MDP_SSPP_TOP0_INTR, 26), 170 + DPU_IRQ_IDX(MDP_SSPP_TOP0_INTR, 27), 171 + DPU_IRQ_IDX(MDP_INTF1_TEAR_INTR, 2)), 172 + INTF_BLK_DSI_TE("intf_2", INTF_2, 0x6b000, 0x2bc, INTF_DSI, 1, 24, INTF_SC7180_MASK, 173 + DPU_IRQ_IDX(MDP_SSPP_TOP0_INTR, 28), 174 + DPU_IRQ_IDX(MDP_SSPP_TOP0_INTR, 29), 175 + DPU_IRQ_IDX(MDP_INTF2_TEAR_INTR, 2)), 176 + INTF_BLK("intf_3", INTF_3, 0x6b800, 0x280, INTF_DP, 1, 24, INTF_SC7180_MASK, 177 + DPU_IRQ_IDX(MDP_SSPP_TOP0_INTR, 30), 178 + DPU_IRQ_IDX(MDP_SSPP_TOP0_INTR, 31)), 169 179 }; 170 180 171 181 static const struct dpu_perf_cfg sm8150_perf_data = { ··· 230 220 .intf = sm8150_intf, 231 221 .vbif_count = ARRAY_SIZE(sdm845_vbif), 232 222 .vbif = sdm845_vbif, 233 - .reg_dma_count = 1, 234 - .dma_cfg = &sm8150_regdma, 235 223 .perf = &sm8150_perf_data, 236 224 .mdss_irqs = BIT(MDP_SSPP_TOP0_INTR) | \ 237 225 BIT(MDP_SSPP_TOP0_INTR2) | \ 238 226 BIT(MDP_SSPP_TOP0_HIST_INTR) | \ 239 227 BIT(MDP_INTF0_INTR) | \ 240 228 BIT(MDP_INTF1_INTR) | \ 229 + BIT(MDP_INTF1_TEAR_INTR) | \ 241 230 BIT(MDP_INTF2_INTR) | \ 231 + BIT(MDP_INTF2_TEAR_INTR) | \ 242 232 BIT(MDP_INTF3_INTR) | \ 243 233 BIT(MDP_AD4_0_INTR) | \ 244 234 BIT(MDP_AD4_1_INTR),
+58 -20
drivers/gpu/drm/msm/disp/dpu1/catalog/dpu_5_1_sc8180x.h
··· 102 102 103 103 static const struct dpu_lm_cfg sc8180x_lm[] = { 104 104 LM_BLK("lm_0", LM_0, 0x44000, MIXER_SDM845_MASK, 105 - &sdm845_lm_sblk, PINGPONG_0, LM_1, 0), 105 + &sdm845_lm_sblk, PINGPONG_0, LM_1, DSPP_0), 106 106 LM_BLK("lm_1", LM_1, 0x45000, MIXER_SDM845_MASK, 107 - &sdm845_lm_sblk, PINGPONG_1, LM_0, 0), 107 + &sdm845_lm_sblk, PINGPONG_1, LM_0, DSPP_1), 108 108 LM_BLK("lm_2", LM_2, 0x46000, MIXER_SDM845_MASK, 109 109 &sdm845_lm_sblk, PINGPONG_2, LM_3, 0), 110 110 LM_BLK("lm_3", LM_3, 0x47000, MIXER_SDM845_MASK, ··· 115 115 &sdm845_lm_sblk, PINGPONG_5, LM_4, 0), 116 116 }; 117 117 118 + static const struct dpu_dspp_cfg sc8180x_dspp[] = { 119 + DSPP_BLK("dspp_0", DSPP_0, 0x54000, DSPP_SC7180_MASK, 120 + &sm8150_dspp_sblk), 121 + DSPP_BLK("dspp_1", DSPP_1, 0x56000, DSPP_SC7180_MASK, 122 + &sm8150_dspp_sblk), 123 + DSPP_BLK("dspp_2", DSPP_2, 0x58000, DSPP_SC7180_MASK, 124 + &sm8150_dspp_sblk), 125 + DSPP_BLK("dspp_3", DSPP_3, 0x5a000, DSPP_SC7180_MASK, 126 + &sm8150_dspp_sblk), 127 + }; 128 + 118 129 static const struct dpu_pingpong_cfg sc8180x_pp[] = { 119 - PP_BLK("pingpong_0", PINGPONG_0, 0x70000, MERGE_3D_0, sdm845_pp_sblk, 130 + PP_BLK("pingpong_0", PINGPONG_0, 0x70000, PINGPONG_SM8150_MASK, MERGE_3D_0, sdm845_pp_sblk, 120 131 DPU_IRQ_IDX(MDP_SSPP_TOP0_INTR, 8), 121 - DPU_IRQ_IDX(MDP_SSPP_TOP0_INTR, 12)), 122 - PP_BLK("pingpong_1", PINGPONG_1, 0x70800, MERGE_3D_0, sdm845_pp_sblk, 132 + -1), 133 + PP_BLK("pingpong_1", PINGPONG_1, 0x70800, PINGPONG_SM8150_MASK, MERGE_3D_0, sdm845_pp_sblk, 123 134 DPU_IRQ_IDX(MDP_SSPP_TOP0_INTR, 9), 124 - DPU_IRQ_IDX(MDP_SSPP_TOP0_INTR, 13)), 125 - PP_BLK("pingpong_2", PINGPONG_2, 0x71000, MERGE_3D_1, sdm845_pp_sblk, 135 + -1), 136 + PP_BLK("pingpong_2", PINGPONG_2, 0x71000, PINGPONG_SM8150_MASK, MERGE_3D_1, sdm845_pp_sblk, 126 137 DPU_IRQ_IDX(MDP_SSPP_TOP0_INTR, 10), 127 - DPU_IRQ_IDX(MDP_SSPP_TOP0_INTR, 14)), 128 - PP_BLK("pingpong_3", PINGPONG_3, 0x71800, MERGE_3D_1, sdm845_pp_sblk, 138 + -1), 139 + PP_BLK("pingpong_3", PINGPONG_3, 0x71800, PINGPONG_SM8150_MASK, MERGE_3D_1, sdm845_pp_sblk, 129 140 DPU_IRQ_IDX(MDP_SSPP_TOP0_INTR, 11), 130 - DPU_IRQ_IDX(MDP_SSPP_TOP0_INTR, 15)), 131 - PP_BLK("pingpong_4", PINGPONG_4, 0x72000, MERGE_3D_2, sdm845_pp_sblk, 141 + -1), 142 + PP_BLK("pingpong_4", PINGPONG_4, 0x72000, PINGPONG_SM8150_MASK, MERGE_3D_2, sdm845_pp_sblk, 132 143 DPU_IRQ_IDX(MDP_SSPP_TOP0_INTR2, 30), 133 144 -1), 134 - PP_BLK("pingpong_5", PINGPONG_5, 0x72800, MERGE_3D_2, sdm845_pp_sblk, 145 + PP_BLK("pingpong_5", PINGPONG_5, 0x72800, PINGPONG_SM8150_MASK, MERGE_3D_2, sdm845_pp_sblk, 135 146 DPU_IRQ_IDX(MDP_SSPP_TOP0_INTR2, 31), 136 147 -1), 137 148 }; ··· 153 142 MERGE_3D_BLK("merge_3d_2", MERGE_3D_2, 0x83200), 154 143 }; 155 144 145 + static const struct dpu_dsc_cfg sc8180x_dsc[] = { 146 + DSC_BLK("dsc_0", DSC_0, 0x80000, BIT(DPU_DSC_OUTPUT_CTRL)), 147 + DSC_BLK("dsc_1", DSC_1, 0x80400, BIT(DPU_DSC_OUTPUT_CTRL)), 148 + DSC_BLK("dsc_2", DSC_2, 0x80800, BIT(DPU_DSC_OUTPUT_CTRL)), 149 + DSC_BLK("dsc_3", DSC_3, 0x80c00, BIT(DPU_DSC_OUTPUT_CTRL)), 150 + DSC_BLK("dsc_4", DSC_4, 0x81000, BIT(DPU_DSC_OUTPUT_CTRL)), 151 + DSC_BLK("dsc_5", DSC_5, 0x81400, BIT(DPU_DSC_OUTPUT_CTRL)), 152 + }; 153 + 156 154 static const struct dpu_intf_cfg sc8180x_intf[] = { 157 - INTF_BLK("intf_0", INTF_0, 0x6a000, 0x280, INTF_DP, MSM_DP_CONTROLLER_0, 24, INTF_SC7180_MASK, MDP_SSPP_TOP0_INTR, 24, 25), 158 - INTF_BLK("intf_1", INTF_1, 0x6a800, 0x2bc, INTF_DSI, 0, 24, INTF_SC7180_MASK, MDP_SSPP_TOP0_INTR, 26, 27), 159 - INTF_BLK("intf_2", INTF_2, 0x6b000, 0x2bc, INTF_DSI, 1, 24, INTF_SC7180_MASK, MDP_SSPP_TOP0_INTR, 28, 29), 155 + INTF_BLK("intf_0", INTF_0, 0x6a000, 0x280, INTF_DP, MSM_DP_CONTROLLER_0, 24, INTF_SC7180_MASK, 156 + DPU_IRQ_IDX(MDP_SSPP_TOP0_INTR, 24), 157 + DPU_IRQ_IDX(MDP_SSPP_TOP0_INTR, 25)), 158 + INTF_BLK_DSI_TE("intf_1", INTF_1, 0x6a800, 0x2bc, INTF_DSI, 0, 24, INTF_SC7180_MASK, 159 + DPU_IRQ_IDX(MDP_SSPP_TOP0_INTR, 26), 160 + DPU_IRQ_IDX(MDP_SSPP_TOP0_INTR, 27), 161 + DPU_IRQ_IDX(MDP_INTF1_TEAR_INTR, 2)), 162 + INTF_BLK_DSI_TE("intf_2", INTF_2, 0x6b000, 0x2bc, INTF_DSI, 1, 24, INTF_SC7180_MASK, 163 + DPU_IRQ_IDX(MDP_SSPP_TOP0_INTR, 28), 164 + DPU_IRQ_IDX(MDP_SSPP_TOP0_INTR, 29), 165 + DPU_IRQ_IDX(MDP_INTF2_TEAR_INTR, 2)), 160 166 /* INTF_3 is for MST, wired to INTF_DP 0 and 1, use dummy index until this is supported */ 161 - INTF_BLK("intf_3", INTF_3, 0x6b800, 0x280, INTF_DP, 999, 24, INTF_SC7180_MASK, MDP_SSPP_TOP0_INTR, 30, 31), 162 - INTF_BLK("intf_4", INTF_4, 0x6c000, 0x280, INTF_DP, MSM_DP_CONTROLLER_1, 24, INTF_SC7180_MASK, MDP_SSPP_TOP0_INTR, 20, 21), 163 - INTF_BLK("intf_5", INTF_5, 0x6c800, 0x280, INTF_DP, MSM_DP_CONTROLLER_2, 24, INTF_SC7180_MASK, MDP_SSPP_TOP0_INTR, 22, 23), 167 + INTF_BLK("intf_3", INTF_3, 0x6b800, 0x280, INTF_DP, 999, 24, INTF_SC7180_MASK, 168 + DPU_IRQ_IDX(MDP_SSPP_TOP0_INTR, 30), 169 + DPU_IRQ_IDX(MDP_SSPP_TOP0_INTR, 31)), 170 + INTF_BLK("intf_4", INTF_4, 0x6c000, 0x280, INTF_DP, MSM_DP_CONTROLLER_1, 24, INTF_SC7180_MASK, 171 + DPU_IRQ_IDX(MDP_SSPP_TOP0_INTR, 20), 172 + DPU_IRQ_IDX(MDP_SSPP_TOP0_INTR, 21)), 173 + INTF_BLK("intf_5", INTF_5, 0x6c800, 0x280, INTF_DP, MSM_DP_CONTROLLER_2, 24, INTF_SC7180_MASK, 174 + DPU_IRQ_IDX(MDP_SSPP_TOP0_INTR, 22), 175 + DPU_IRQ_IDX(MDP_SSPP_TOP0_INTR, 23)), 164 176 }; 165 177 166 178 static const struct dpu_perf_cfg sc8180x_perf_data = { ··· 224 190 .sspp = sc8180x_sspp, 225 191 .mixer_count = ARRAY_SIZE(sc8180x_lm), 226 192 .mixer = sc8180x_lm, 193 + .dspp_count = ARRAY_SIZE(sc8180x_dspp), 194 + .dspp = sc8180x_dspp, 195 + .dsc_count = ARRAY_SIZE(sc8180x_dsc), 196 + .dsc = sc8180x_dsc, 227 197 .pingpong_count = ARRAY_SIZE(sc8180x_pp), 228 198 .pingpong = sc8180x_pp, 229 199 .merge_3d_count = ARRAY_SIZE(sc8180x_merge_3d), ··· 236 198 .intf = sc8180x_intf, 237 199 .vbif_count = ARRAY_SIZE(sdm845_vbif), 238 200 .vbif = sdm845_vbif, 239 - .reg_dma_count = 1, 240 - .dma_cfg = &sm8150_regdma, 241 201 .perf = &sc8180x_perf_data, 242 202 .mdss_irqs = BIT(MDP_SSPP_TOP0_INTR) | \ 243 203 BIT(MDP_SSPP_TOP0_INTR2) | \ 244 204 BIT(MDP_SSPP_TOP0_HIST_INTR) | \ 245 205 BIT(MDP_INTF0_INTR) | \ 246 206 BIT(MDP_INTF1_INTR) | \ 207 + BIT(MDP_INTF1_TEAR_INTR) | \ 247 208 BIT(MDP_INTF2_INTR) | \ 209 + BIT(MDP_INTF2_TEAR_INTR) | \ 248 210 BIT(MDP_INTF3_INTR) | \ 249 211 BIT(MDP_INTF4_INTR) | \ 250 212 BIT(MDP_INTF5_INTR) | \
+26 -16
drivers/gpu/drm/msm/disp/dpu1/catalog/dpu_6_0_sm8250.h
··· 129 129 }; 130 130 131 131 static const struct dpu_pingpong_cfg sm8250_pp[] = { 132 - PP_BLK("pingpong_0", PINGPONG_0, 0x70000, MERGE_3D_0, sdm845_pp_sblk, 132 + PP_BLK("pingpong_0", PINGPONG_0, 0x70000, PINGPONG_SM8150_MASK, MERGE_3D_0, sdm845_pp_sblk, 133 133 DPU_IRQ_IDX(MDP_SSPP_TOP0_INTR, 8), 134 - DPU_IRQ_IDX(MDP_SSPP_TOP0_INTR, 12)), 135 - PP_BLK("pingpong_1", PINGPONG_1, 0x70800, MERGE_3D_0, sdm845_pp_sblk, 134 + -1), 135 + PP_BLK("pingpong_1", PINGPONG_1, 0x70800, PINGPONG_SM8150_MASK, MERGE_3D_0, sdm845_pp_sblk, 136 136 DPU_IRQ_IDX(MDP_SSPP_TOP0_INTR, 9), 137 - DPU_IRQ_IDX(MDP_SSPP_TOP0_INTR, 13)), 138 - PP_BLK("pingpong_2", PINGPONG_2, 0x71000, MERGE_3D_1, sdm845_pp_sblk, 137 + -1), 138 + PP_BLK("pingpong_2", PINGPONG_2, 0x71000, PINGPONG_SM8150_MASK, MERGE_3D_1, sdm845_pp_sblk, 139 139 DPU_IRQ_IDX(MDP_SSPP_TOP0_INTR, 10), 140 - DPU_IRQ_IDX(MDP_SSPP_TOP0_INTR, 14)), 141 - PP_BLK("pingpong_3", PINGPONG_3, 0x71800, MERGE_3D_1, sdm845_pp_sblk, 140 + -1), 141 + PP_BLK("pingpong_3", PINGPONG_3, 0x71800, PINGPONG_SM8150_MASK, MERGE_3D_1, sdm845_pp_sblk, 142 142 DPU_IRQ_IDX(MDP_SSPP_TOP0_INTR, 11), 143 - DPU_IRQ_IDX(MDP_SSPP_TOP0_INTR, 15)), 144 - PP_BLK("pingpong_4", PINGPONG_4, 0x72000, MERGE_3D_2, sdm845_pp_sblk, 143 + -1), 144 + PP_BLK("pingpong_4", PINGPONG_4, 0x72000, PINGPONG_SM8150_MASK, MERGE_3D_2, sdm845_pp_sblk, 145 145 DPU_IRQ_IDX(MDP_SSPP_TOP0_INTR2, 30), 146 146 -1), 147 - PP_BLK("pingpong_5", PINGPONG_5, 0x72800, MERGE_3D_2, sdm845_pp_sblk, 147 + PP_BLK("pingpong_5", PINGPONG_5, 0x72800, PINGPONG_SM8150_MASK, MERGE_3D_2, sdm845_pp_sblk, 148 148 DPU_IRQ_IDX(MDP_SSPP_TOP0_INTR2, 31), 149 149 -1), 150 150 }; ··· 163 163 }; 164 164 165 165 static const struct dpu_intf_cfg sm8250_intf[] = { 166 - INTF_BLK("intf_0", INTF_0, 0x6a000, 0x280, INTF_DP, 0, 24, INTF_SC7180_MASK, MDP_SSPP_TOP0_INTR, 24, 25), 167 - INTF_BLK("intf_1", INTF_1, 0x6a800, 0x2c0, INTF_DSI, 0, 24, INTF_SC7180_MASK, MDP_SSPP_TOP0_INTR, 26, 27), 168 - INTF_BLK("intf_2", INTF_2, 0x6b000, 0x2c0, INTF_DSI, 1, 24, INTF_SC7180_MASK, MDP_SSPP_TOP0_INTR, 28, 29), 169 - INTF_BLK("intf_3", INTF_3, 0x6b800, 0x280, INTF_DP, 1, 24, INTF_SC7180_MASK, MDP_SSPP_TOP0_INTR, 30, 31), 166 + INTF_BLK("intf_0", INTF_0, 0x6a000, 0x280, INTF_DP, 0, 24, INTF_SC7180_MASK, 167 + DPU_IRQ_IDX(MDP_SSPP_TOP0_INTR, 24), 168 + DPU_IRQ_IDX(MDP_SSPP_TOP0_INTR, 25)), 169 + INTF_BLK_DSI_TE("intf_1", INTF_1, 0x6a800, 0x2c0, INTF_DSI, 0, 24, INTF_SC7180_MASK, 170 + DPU_IRQ_IDX(MDP_SSPP_TOP0_INTR, 26), 171 + DPU_IRQ_IDX(MDP_SSPP_TOP0_INTR, 27), 172 + DPU_IRQ_IDX(MDP_INTF1_TEAR_INTR, 2)), 173 + INTF_BLK_DSI_TE("intf_2", INTF_2, 0x6b000, 0x2c0, INTF_DSI, 1, 24, INTF_SC7180_MASK, 174 + DPU_IRQ_IDX(MDP_SSPP_TOP0_INTR, 28), 175 + DPU_IRQ_IDX(MDP_SSPP_TOP0_INTR, 29), 176 + DPU_IRQ_IDX(MDP_INTF2_TEAR_INTR, 2)), 177 + INTF_BLK("intf_3", INTF_3, 0x6b800, 0x280, INTF_DP, 1, 24, INTF_SC7180_MASK, 178 + DPU_IRQ_IDX(MDP_SSPP_TOP0_INTR, 30), 179 + DPU_IRQ_IDX(MDP_SSPP_TOP0_INTR, 31)), 170 180 }; 171 181 172 182 static const struct dpu_wb_cfg sm8250_wb[] = { ··· 238 228 .vbif = sdm845_vbif, 239 229 .wb_count = ARRAY_SIZE(sm8250_wb), 240 230 .wb = sm8250_wb, 241 - .reg_dma_count = 1, 242 - .dma_cfg = &sm8250_regdma, 243 231 .perf = &sm8250_perf_data, 244 232 .mdss_irqs = BIT(MDP_SSPP_TOP0_INTR) | \ 245 233 BIT(MDP_SSPP_TOP0_INTR2) | \ 246 234 BIT(MDP_SSPP_TOP0_HIST_INTR) | \ 247 235 BIT(MDP_INTF0_INTR) | \ 248 236 BIT(MDP_INTF1_INTR) | \ 237 + BIT(MDP_INTF1_TEAR_INTR) | \ 249 238 BIT(MDP_INTF2_INTR) | \ 239 + BIT(MDP_INTF2_TEAR_INTR) | \ 250 240 BIT(MDP_INTF3_INTR) | \ 251 241 BIT(MDP_INTF4_INTR), 252 242 };
+16 -8
drivers/gpu/drm/msm/disp/dpu1/catalog/dpu_6_2_sc7180.h
··· 76 76 77 77 static const struct dpu_dspp_cfg sc7180_dspp[] = { 78 78 DSPP_BLK("dspp_0", DSPP_0, 0x54000, DSPP_SC7180_MASK, 79 - &sc7180_dspp_sblk), 79 + &sm8150_dspp_sblk), 80 80 }; 81 81 82 82 static const struct dpu_pingpong_cfg sc7180_pp[] = { 83 - PP_BLK("pingpong_0", PINGPONG_0, 0x70000, 0, sdm845_pp_sblk, -1, -1), 84 - PP_BLK("pingpong_1", PINGPONG_1, 0x70800, 0, sdm845_pp_sblk, -1, -1), 83 + PP_BLK("pingpong_0", PINGPONG_0, 0x70000, PINGPONG_SM8150_MASK, 0, sdm845_pp_sblk, 84 + DPU_IRQ_IDX(MDP_SSPP_TOP0_INTR, 8), 85 + -1), 86 + PP_BLK("pingpong_1", PINGPONG_1, 0x70800, PINGPONG_SM8150_MASK, 0, sdm845_pp_sblk, 87 + DPU_IRQ_IDX(MDP_SSPP_TOP0_INTR, 9), 88 + -1), 85 89 }; 86 90 87 91 static const struct dpu_intf_cfg sc7180_intf[] = { 88 - INTF_BLK("intf_0", INTF_0, 0x6a000, 0x280, INTF_DP, MSM_DP_CONTROLLER_0, 24, INTF_SC7180_MASK, MDP_SSPP_TOP0_INTR, 24, 25), 89 - INTF_BLK("intf_1", INTF_1, 0x6a800, 0x2c0, INTF_DSI, 0, 24, INTF_SC7180_MASK, MDP_SSPP_TOP0_INTR, 26, 27), 92 + INTF_BLK("intf_0", INTF_0, 0x6a000, 0x280, INTF_DP, MSM_DP_CONTROLLER_0, 24, INTF_SC7180_MASK, 93 + DPU_IRQ_IDX(MDP_SSPP_TOP0_INTR, 24), 94 + DPU_IRQ_IDX(MDP_SSPP_TOP0_INTR, 25)), 95 + INTF_BLK_DSI_TE("intf_1", INTF_1, 0x6a800, 0x2c0, INTF_DSI, 0, 24, INTF_SC7180_MASK, 96 + DPU_IRQ_IDX(MDP_SSPP_TOP0_INTR, 26), 97 + DPU_IRQ_IDX(MDP_SSPP_TOP0_INTR, 27), 98 + DPU_IRQ_IDX(MDP_INTF1_TEAR_INTR, 2)), 90 99 }; 91 100 92 101 static const struct dpu_wb_cfg sc7180_wb[] = { ··· 152 143 .wb = sc7180_wb, 153 144 .vbif_count = ARRAY_SIZE(sdm845_vbif), 154 145 .vbif = sdm845_vbif, 155 - .reg_dma_count = 1, 156 - .dma_cfg = &sdm845_regdma, 157 146 .perf = &sc7180_perf_data, 158 147 .mdss_irqs = BIT(MDP_SSPP_TOP0_INTR) | \ 159 148 BIT(MDP_SSPP_TOP0_INTR2) | \ 160 149 BIT(MDP_SSPP_TOP0_HIST_INTR) | \ 161 150 BIT(MDP_INTF0_INTR) | \ 162 - BIT(MDP_INTF1_INTR), 151 + BIT(MDP_INTF1_INTR) | \ 152 + BIT(MDP_INTF1_TEAR_INTR), 163 153 }; 164 154 165 155 #endif
+8 -5
drivers/gpu/drm/msm/disp/dpu1/catalog/dpu_6_3_sm6115.h
··· 60 60 }; 61 61 62 62 static const struct dpu_pingpong_cfg sm6115_pp[] = { 63 - PP_BLK("pingpong_0", PINGPONG_0, 0x70000, 0, sdm845_pp_sblk, 63 + PP_BLK("pingpong_0", PINGPONG_0, 0x70000, PINGPONG_SM8150_MASK, 0, sdm845_pp_sblk, 64 64 DPU_IRQ_IDX(MDP_SSPP_TOP0_INTR, 8), 65 - DPU_IRQ_IDX(MDP_SSPP_TOP0_INTR, 12)), 65 + -1), 66 66 }; 67 67 68 68 static const struct dpu_intf_cfg sm6115_intf[] = { 69 - INTF_BLK("intf_0", INTF_0, 0x00000, 0x280, INTF_NONE, 0, 0, 0, 0, 0, 0), 70 - INTF_BLK("intf_1", INTF_1, 0x6a800, 0x2c0, INTF_DSI, 0, 24, INTF_SC7180_MASK, MDP_SSPP_TOP0_INTR, 26, 27), 69 + INTF_BLK_DSI_TE("intf_1", INTF_1, 0x6a800, 0x2c0, INTF_DSI, 0, 24, INTF_SC7180_MASK, 70 + DPU_IRQ_IDX(MDP_SSPP_TOP0_INTR, 26), 71 + DPU_IRQ_IDX(MDP_SSPP_TOP0_INTR, 27), 72 + DPU_IRQ_IDX(MDP_INTF1_TEAR_INTR, 2)), 71 73 }; 72 74 73 75 static const struct dpu_perf_cfg sm6115_perf_data = { ··· 124 122 .mdss_irqs = BIT(MDP_SSPP_TOP0_INTR) | \ 125 123 BIT(MDP_SSPP_TOP0_INTR2) | \ 126 124 BIT(MDP_SSPP_TOP0_HIST_INTR) | \ 127 - BIT(MDP_INTF1_INTR), 125 + BIT(MDP_INTF1_INTR) | \ 126 + BIT(MDP_INTF1_TEAR_INTR), 128 127 }; 129 128 130 129 #endif
+173
drivers/gpu/drm/msm/disp/dpu1/catalog/dpu_6_4_sm6350.h
··· 1 + /* SPDX-License-Identifier: GPL-2.0-only */ 2 + /* 3 + * Copyright (c) 2022. Qualcomm Innovation Center, Inc. All rights reserved. 4 + * Copyright (c) 2015-2018, 2020 The Linux Foundation. All rights reserved. 5 + * Copyright (c) 2023, Linaro Limited 6 + */ 7 + 8 + #ifndef _DPU_6_4_SM6350_H 9 + #define _DPU_6_4_SM6350_H 10 + 11 + static const struct dpu_caps sm6350_dpu_caps = { 12 + .max_mixer_width = DEFAULT_DPU_OUTPUT_LINE_WIDTH, 13 + .max_mixer_blendstages = 0x7, 14 + .qseed_type = DPU_SSPP_SCALER_QSEED4, 15 + .has_src_split = true, 16 + .has_dim_layer = true, 17 + .has_idle_pc = true, 18 + .max_linewidth = DEFAULT_DPU_OUTPUT_LINE_WIDTH, 19 + .pixel_ram_size = DEFAULT_PIXEL_RAM_SIZE, 20 + }; 21 + 22 + static const struct dpu_ubwc_cfg sm6350_ubwc_cfg = { 23 + .ubwc_version = DPU_HW_UBWC_VER_20, 24 + .ubwc_swizzle = 6, 25 + .highest_bank_bit = 1, 26 + }; 27 + 28 + static const struct dpu_mdp_cfg sm6350_mdp[] = { 29 + { 30 + .name = "top_0", .id = MDP_TOP, 31 + .base = 0x0, .len = 0x494, 32 + .features = 0, 33 + .clk_ctrls[DPU_CLK_CTRL_VIG0] = { .reg_off = 0x2ac, .bit_off = 0 }, 34 + .clk_ctrls[DPU_CLK_CTRL_DMA0] = { .reg_off = 0x2ac, .bit_off = 8 }, 35 + .clk_ctrls[DPU_CLK_CTRL_DMA1] = { .reg_off = 0x2b4, .bit_off = 8 }, 36 + .clk_ctrls[DPU_CLK_CTRL_DMA2] = { .reg_off = 0x2c4, .bit_off = 8 }, 37 + .clk_ctrls[DPU_CLK_CTRL_REG_DMA] = { .reg_off = 0x2bc, .bit_off = 20 }, 38 + }, 39 + }; 40 + 41 + static const struct dpu_ctl_cfg sm6350_ctl[] = { 42 + { 43 + .name = "ctl_0", .id = CTL_0, 44 + .base = 0x1000, .len = 0x1dc, 45 + .features = BIT(DPU_CTL_ACTIVE_CFG), 46 + .intr_start = DPU_IRQ_IDX(MDP_SSPP_TOP0_INTR2, 9), 47 + }, 48 + { 49 + .name = "ctl_1", .id = CTL_1, 50 + .base = 0x1200, .len = 0x1dc, 51 + .features = BIT(DPU_CTL_ACTIVE_CFG), 52 + .intr_start = DPU_IRQ_IDX(MDP_SSPP_TOP0_INTR2, 10), 53 + }, 54 + { 55 + .name = "ctl_2", .id = CTL_2, 56 + .base = 0x1400, .len = 0x1dc, 57 + .features = BIT(DPU_CTL_ACTIVE_CFG), 58 + .intr_start = DPU_IRQ_IDX(MDP_SSPP_TOP0_INTR2, 11), 59 + }, 60 + { 61 + .name = "ctl_3", .id = CTL_3, 62 + .base = 0x1600, .len = 0x1dc, 63 + .features = BIT(DPU_CTL_ACTIVE_CFG), 64 + .intr_start = DPU_IRQ_IDX(MDP_SSPP_TOP0_INTR2, 12), 65 + }, 66 + }; 67 + 68 + static const struct dpu_sspp_cfg sm6350_sspp[] = { 69 + SSPP_BLK("sspp_0", SSPP_VIG0, 0x4000, 0x1f8, VIG_SC7180_MASK, 70 + sc7180_vig_sblk_0, 0, SSPP_TYPE_VIG, DPU_CLK_CTRL_VIG0), 71 + SSPP_BLK("sspp_8", SSPP_DMA0, 0x24000, 0x1f8, DMA_SDM845_MASK, 72 + sdm845_dma_sblk_0, 1, SSPP_TYPE_DMA, DPU_CLK_CTRL_DMA0), 73 + SSPP_BLK("sspp_9", SSPP_DMA1, 0x26000, 0x1f8, DMA_CURSOR_SDM845_MASK, 74 + sdm845_dma_sblk_1, 5, SSPP_TYPE_DMA, DPU_CLK_CTRL_DMA1), 75 + SSPP_BLK("sspp_10", SSPP_DMA2, 0x28000, 0x1f8, DMA_CURSOR_SDM845_MASK, 76 + sdm845_dma_sblk_2, 9, SSPP_TYPE_DMA, DPU_CLK_CTRL_DMA2), 77 + }; 78 + 79 + static const struct dpu_lm_cfg sm6350_lm[] = { 80 + LM_BLK("lm_0", LM_0, 0x44000, MIXER_SDM845_MASK, 81 + &sc7180_lm_sblk, PINGPONG_0, LM_1, DSPP_0), 82 + LM_BLK("lm_1", LM_1, 0x45000, MIXER_SDM845_MASK, 83 + &sc7180_lm_sblk, PINGPONG_1, LM_0, 0), 84 + }; 85 + 86 + static const struct dpu_dspp_cfg sm6350_dspp[] = { 87 + DSPP_BLK("dspp_0", DSPP_0, 0x54000, DSPP_SC7180_MASK, 88 + &sm8150_dspp_sblk), 89 + }; 90 + 91 + static struct dpu_pingpong_cfg sm6350_pp[] = { 92 + PP_BLK("pingpong_0", PINGPONG_0, 0x70000, PINGPONG_SM8150_MASK, 0, sdm845_pp_sblk, 93 + DPU_IRQ_IDX(MDP_SSPP_TOP0_INTR, 8), 94 + -1), 95 + PP_BLK("pingpong_1", PINGPONG_1, 0x70800, PINGPONG_SM8150_MASK, 0, sdm845_pp_sblk, 96 + DPU_IRQ_IDX(MDP_SSPP_TOP0_INTR, 9), 97 + -1), 98 + }; 99 + 100 + static const struct dpu_dsc_cfg sm6350_dsc[] = { 101 + DSC_BLK("dsc_0", DSC_0, 0x80000, BIT(DPU_DSC_OUTPUT_CTRL)), 102 + }; 103 + 104 + static const struct dpu_intf_cfg sm6350_intf[] = { 105 + INTF_BLK("intf_0", INTF_0, 0x6a000, 0x280, INTF_DP, 0, 35, INTF_SC7180_MASK, 106 + DPU_IRQ_IDX(MDP_SSPP_TOP0_INTR, 24), 107 + DPU_IRQ_IDX(MDP_SSPP_TOP0_INTR, 25)), 108 + INTF_BLK_DSI_TE("intf_1", INTF_1, 0x6a800, 0x2c0, INTF_DSI, 0, 35, INTF_SC7180_MASK, 109 + DPU_IRQ_IDX(MDP_SSPP_TOP0_INTR, 26), 110 + DPU_IRQ_IDX(MDP_SSPP_TOP0_INTR, 27), 111 + DPU_IRQ_IDX(MDP_INTF1_TEAR_INTR, 2)), 112 + }; 113 + 114 + static const struct dpu_perf_cfg sm6350_perf_data = { 115 + .max_bw_low = 4200000, 116 + .max_bw_high = 5100000, 117 + .min_core_ib = 2500000, 118 + .min_llcc_ib = 0, 119 + .min_dram_ib = 1600000, 120 + .min_prefill_lines = 35, 121 + /* TODO: confirm danger_lut_tbl */ 122 + .danger_lut_tbl = {0xffff, 0xffff, 0x0}, 123 + .safe_lut_tbl = {0xff00, 0xff00, 0xffff}, 124 + .qos_lut_tbl = { 125 + {.nentry = ARRAY_SIZE(sm6350_qos_linear_macrotile), 126 + .entries = sm6350_qos_linear_macrotile 127 + }, 128 + {.nentry = ARRAY_SIZE(sm6350_qos_linear_macrotile), 129 + .entries = sm6350_qos_linear_macrotile 130 + }, 131 + {.nentry = ARRAY_SIZE(sc7180_qos_nrt), 132 + .entries = sc7180_qos_nrt 133 + }, 134 + }, 135 + .cdp_cfg = { 136 + {.rd_enable = 1, .wr_enable = 1}, 137 + {.rd_enable = 1, .wr_enable = 0} 138 + }, 139 + .clk_inefficiency_factor = 105, 140 + .bw_inefficiency_factor = 120, 141 + }; 142 + 143 + const struct dpu_mdss_cfg dpu_sm6350_cfg = { 144 + .caps = &sm6350_dpu_caps, 145 + .ubwc = &sm6350_ubwc_cfg, 146 + .mdp_count = ARRAY_SIZE(sm6350_mdp), 147 + .mdp = sm6350_mdp, 148 + .ctl_count = ARRAY_SIZE(sm6350_ctl), 149 + .ctl = sm6350_ctl, 150 + .sspp_count = ARRAY_SIZE(sm6350_sspp), 151 + .sspp = sm6350_sspp, 152 + .mixer_count = ARRAY_SIZE(sm6350_lm), 153 + .mixer = sm6350_lm, 154 + .dspp_count = ARRAY_SIZE(sm6350_dspp), 155 + .dspp = sm6350_dspp, 156 + .dsc_count = ARRAY_SIZE(sm6350_dsc), 157 + .dsc = sm6350_dsc, 158 + .pingpong_count = ARRAY_SIZE(sm6350_pp), 159 + .pingpong = sm6350_pp, 160 + .intf_count = ARRAY_SIZE(sm6350_intf), 161 + .intf = sm6350_intf, 162 + .vbif_count = ARRAY_SIZE(sdm845_vbif), 163 + .vbif = sdm845_vbif, 164 + .perf = &sm6350_perf_data, 165 + .mdss_irqs = BIT(MDP_SSPP_TOP0_INTR) | \ 166 + BIT(MDP_SSPP_TOP0_INTR2) | \ 167 + BIT(MDP_SSPP_TOP0_HIST_INTR) | \ 168 + BIT(MDP_INTF0_INTR) | \ 169 + BIT(MDP_INTF1_INTR) | \ 170 + BIT(MDP_INTF1_TEAR_INTR), 171 + }; 172 + 173 + #endif
+8 -5
drivers/gpu/drm/msm/disp/dpu1/catalog/dpu_6_5_qcm2290.h
··· 57 57 }; 58 58 59 59 static const struct dpu_pingpong_cfg qcm2290_pp[] = { 60 - PP_BLK("pingpong_0", PINGPONG_0, 0x70000, 0, sdm845_pp_sblk, 60 + PP_BLK("pingpong_0", PINGPONG_0, 0x70000, PINGPONG_SM8150_MASK, 0, sdm845_pp_sblk, 61 61 DPU_IRQ_IDX(MDP_SSPP_TOP0_INTR, 8), 62 - DPU_IRQ_IDX(MDP_SSPP_TOP0_INTR, 12)), 62 + -1), 63 63 }; 64 64 65 65 static const struct dpu_intf_cfg qcm2290_intf[] = { 66 - INTF_BLK("intf_0", INTF_0, 0x00000, 0x280, INTF_NONE, 0, 0, 0, 0, 0, 0), 67 - INTF_BLK("intf_1", INTF_1, 0x6a800, 0x2c0, INTF_DSI, 0, 24, INTF_SC7180_MASK, MDP_SSPP_TOP0_INTR, 26, 27), 66 + INTF_BLK_DSI_TE("intf_1", INTF_1, 0x6a800, 0x2c0, INTF_DSI, 0, 24, INTF_SC7180_MASK, 67 + DPU_IRQ_IDX(MDP_SSPP_TOP0_INTR, 26), 68 + DPU_IRQ_IDX(MDP_SSPP_TOP0_INTR, 27), 69 + DPU_IRQ_IDX(MDP_INTF1_TEAR_INTR, 2)), 68 70 }; 69 71 70 72 static const struct dpu_perf_cfg qcm2290_perf_data = { ··· 114 112 .mdss_irqs = BIT(MDP_SSPP_TOP0_INTR) | \ 115 113 BIT(MDP_SSPP_TOP0_INTR2) | \ 116 114 BIT(MDP_SSPP_TOP0_HIST_INTR) | \ 117 - BIT(MDP_INTF1_INTR), 115 + BIT(MDP_INTF1_INTR) | \ 116 + BIT(MDP_INTF1_TEAR_INTR), 118 117 }; 119 118 120 119 #endif
+138
drivers/gpu/drm/msm/disp/dpu1/catalog/dpu_6_9_sm6375.h
··· 1 + /* SPDX-License-Identifier: GPL-2.0-only */ 2 + /* 3 + * Copyright (c) 2022. Qualcomm Innovation Center, Inc. All rights reserved. 4 + * Copyright (c) 2015-2018, 2020 The Linux Foundation. All rights reserved. 5 + * Copyright (c) 2023, Linaro Limited 6 + */ 7 + 8 + #ifndef _DPU_6_9_SM6375_H 9 + #define _DPU_6_9_SM6375_H 10 + 11 + static const struct dpu_caps sm6375_dpu_caps = { 12 + .max_mixer_width = DEFAULT_DPU_LINE_WIDTH, 13 + .max_mixer_blendstages = 0x4, 14 + .qseed_type = DPU_SSPP_SCALER_QSEED4, 15 + .has_dim_layer = true, 16 + .has_idle_pc = true, 17 + .max_linewidth = 2160, 18 + .pixel_ram_size = DEFAULT_PIXEL_RAM_SIZE, 19 + }; 20 + 21 + static const struct dpu_ubwc_cfg sm6375_ubwc_cfg = { 22 + .ubwc_version = DPU_HW_UBWC_VER_20, 23 + .ubwc_swizzle = 6, 24 + .highest_bank_bit = 1, 25 + }; 26 + 27 + static const struct dpu_mdp_cfg sm6375_mdp[] = { 28 + { 29 + .name = "top_0", .id = MDP_TOP, 30 + .base = 0x0, .len = 0x494, 31 + .features = 0, 32 + .clk_ctrls[DPU_CLK_CTRL_VIG0] = { .reg_off = 0x2ac, .bit_off = 0 }, 33 + .clk_ctrls[DPU_CLK_CTRL_DMA0] = { .reg_off = 0x2ac, .bit_off = 8 }, 34 + }, 35 + }; 36 + 37 + static const struct dpu_ctl_cfg sm6375_ctl[] = { 38 + { 39 + .name = "ctl_0", .id = CTL_0, 40 + .base = 0x1000, .len = 0x1dc, 41 + .features = BIT(DPU_CTL_ACTIVE_CFG), 42 + .intr_start = DPU_IRQ_IDX(MDP_SSPP_TOP0_INTR2, 9), 43 + }, 44 + }; 45 + 46 + static const struct dpu_sspp_cfg sm6375_sspp[] = { 47 + SSPP_BLK("sspp_0", SSPP_VIG0, 0x4000, 0x1f8, VIG_SC7180_MASK, 48 + sm6115_vig_sblk_0, 0, SSPP_TYPE_VIG, DPU_CLK_CTRL_VIG0), 49 + SSPP_BLK("sspp_8", SSPP_DMA0, 0x24000, 0x1f8, DMA_SDM845_MASK, 50 + sdm845_dma_sblk_0, 1, SSPP_TYPE_DMA, DPU_CLK_CTRL_DMA0), 51 + }; 52 + 53 + static const struct dpu_lm_cfg sm6375_lm[] = { 54 + LM_BLK("lm_0", LM_0, 0x44000, MIXER_QCM2290_MASK, 55 + &qcm2290_lm_sblk, PINGPONG_0, 0, DSPP_0), 56 + }; 57 + 58 + static const struct dpu_dspp_cfg sm6375_dspp[] = { 59 + DSPP_BLK("dspp_0", DSPP_0, 0x54000, DSPP_SC7180_MASK, 60 + &sm8150_dspp_sblk), 61 + }; 62 + 63 + static const struct dpu_pingpong_cfg sm6375_pp[] = { 64 + PP_BLK("pingpong_0", PINGPONG_0, 0x70000, PINGPONG_SM8150_MASK, 0, sdm845_pp_sblk, 65 + DPU_IRQ_IDX(MDP_SSPP_TOP0_INTR, 8), 66 + -1), 67 + }; 68 + 69 + static const struct dpu_dsc_cfg sm6375_dsc[] = { 70 + DSC_BLK("dsc_0", DSC_0, 0x80000, BIT(DPU_DSC_OUTPUT_CTRL)), 71 + }; 72 + 73 + static const struct dpu_intf_cfg sm6375_intf[] = { 74 + INTF_BLK_DSI_TE("intf_1", INTF_1, 0x6a800, 0x2c0, INTF_DSI, 0, 24, INTF_SC7180_MASK, 75 + DPU_IRQ_IDX(MDP_SSPP_TOP0_INTR, 26), 76 + DPU_IRQ_IDX(MDP_SSPP_TOP0_INTR, 27), 77 + DPU_IRQ_IDX(MDP_INTF1_TEAR_INTR, 2)), 78 + }; 79 + 80 + static const struct dpu_perf_cfg sm6375_perf_data = { 81 + .max_bw_low = 5200000, 82 + .max_bw_high = 6200000, 83 + .min_core_ib = 2500000, 84 + .min_llcc_ib = 0, /* No LLCC on this SoC */ 85 + .min_dram_ib = 1600000, 86 + .min_prefill_lines = 24, 87 + /* TODO: confirm danger_lut_tbl */ 88 + .danger_lut_tbl = {0xffff, 0xffff, 0x0}, 89 + .safe_lut_tbl = {0xfe00, 0xfe00, 0xffff}, 90 + .qos_lut_tbl = { 91 + {.nentry = ARRAY_SIZE(sm6350_qos_linear_macrotile), 92 + .entries = sm6350_qos_linear_macrotile 93 + }, 94 + {.nentry = ARRAY_SIZE(sm6350_qos_linear_macrotile), 95 + .entries = sm6350_qos_linear_macrotile 96 + }, 97 + {.nentry = ARRAY_SIZE(sc7180_qos_nrt), 98 + .entries = sc7180_qos_nrt 99 + }, 100 + }, 101 + .cdp_cfg = { 102 + {.rd_enable = 1, .wr_enable = 1}, 103 + {.rd_enable = 1, .wr_enable = 0} 104 + }, 105 + .clk_inefficiency_factor = 105, 106 + .bw_inefficiency_factor = 120, 107 + }; 108 + 109 + const struct dpu_mdss_cfg dpu_sm6375_cfg = { 110 + .caps = &sm6375_dpu_caps, 111 + .ubwc = &sm6375_ubwc_cfg, 112 + .mdp_count = ARRAY_SIZE(sm6375_mdp), 113 + .mdp = sm6375_mdp, 114 + .ctl_count = ARRAY_SIZE(sm6375_ctl), 115 + .ctl = sm6375_ctl, 116 + .sspp_count = ARRAY_SIZE(sm6375_sspp), 117 + .sspp = sm6375_sspp, 118 + .mixer_count = ARRAY_SIZE(sm6375_lm), 119 + .mixer = sm6375_lm, 120 + .dspp_count = ARRAY_SIZE(sm6375_dspp), 121 + .dspp = sm6375_dspp, 122 + .dsc_count = ARRAY_SIZE(sm6375_dsc), 123 + .dsc = sm6375_dsc, 124 + .pingpong_count = ARRAY_SIZE(sm6375_pp), 125 + .pingpong = sm6375_pp, 126 + .intf_count = ARRAY_SIZE(sm6375_intf), 127 + .intf = sm6375_intf, 128 + .vbif_count = ARRAY_SIZE(sdm845_vbif), 129 + .vbif = sdm845_vbif, 130 + .perf = &sm6375_perf_data, 131 + .mdss_irqs = BIT(MDP_SSPP_TOP0_INTR) | \ 132 + BIT(MDP_SSPP_TOP0_INTR2) | \ 133 + BIT(MDP_SSPP_TOP0_HIST_INTR) | \ 134 + BIT(MDP_INTF1_INTR) | \ 135 + BIT(MDP_INTF1_TEAR_INTR), 136 + }; 137 + 138 + #endif
+34 -10
drivers/gpu/drm/msm/disp/dpu1/catalog/dpu_7_0_sm8350.h
··· 129 129 static const struct dpu_pingpong_cfg sm8350_pp[] = { 130 130 PP_BLK_DITHER("pingpong_0", PINGPONG_0, 0x69000, MERGE_3D_0, sc7280_pp_sblk, 131 131 DPU_IRQ_IDX(MDP_SSPP_TOP0_INTR, 8), 132 - DPU_IRQ_IDX(MDP_SSPP_TOP0_INTR, 12)), 132 + -1), 133 133 PP_BLK_DITHER("pingpong_1", PINGPONG_1, 0x6a000, MERGE_3D_0, sc7280_pp_sblk, 134 134 DPU_IRQ_IDX(MDP_SSPP_TOP0_INTR, 9), 135 - DPU_IRQ_IDX(MDP_SSPP_TOP0_INTR, 13)), 135 + -1), 136 136 PP_BLK_DITHER("pingpong_2", PINGPONG_2, 0x6b000, MERGE_3D_1, sc7280_pp_sblk, 137 137 DPU_IRQ_IDX(MDP_SSPP_TOP0_INTR, 10), 138 - DPU_IRQ_IDX(MDP_SSPP_TOP0_INTR, 14)), 138 + -1), 139 139 PP_BLK_DITHER("pingpong_3", PINGPONG_3, 0x6c000, MERGE_3D_1, sc7280_pp_sblk, 140 140 DPU_IRQ_IDX(MDP_SSPP_TOP0_INTR, 11), 141 - DPU_IRQ_IDX(MDP_SSPP_TOP0_INTR, 15)), 141 + -1), 142 142 PP_BLK_DITHER("pingpong_4", PINGPONG_4, 0x6d000, MERGE_3D_2, sc7280_pp_sblk, 143 143 DPU_IRQ_IDX(MDP_SSPP_TOP0_INTR2, 30), 144 144 -1), ··· 153 153 MERGE_3D_BLK("merge_3d_2", MERGE_3D_2, 0x50000), 154 154 }; 155 155 156 + /* 157 + * NOTE: Each display compression engine (DCE) contains dual hard 158 + * slice DSC encoders so both share same base address but with 159 + * its own different sub block address. 160 + */ 161 + static const struct dpu_dsc_cfg sm8350_dsc[] = { 162 + DSC_BLK_1_2("dce_0_0", DSC_0, 0x80000, 0x29c, 0, dsc_sblk_0), 163 + DSC_BLK_1_2("dce_0_1", DSC_1, 0x80000, 0x29c, 0, dsc_sblk_1), 164 + DSC_BLK_1_2("dce_1_0", DSC_2, 0x81000, 0x29c, BIT(DPU_DSC_NATIVE_42x_EN), dsc_sblk_0), 165 + DSC_BLK_1_2("dce_1_1", DSC_3, 0x81000, 0x29c, BIT(DPU_DSC_NATIVE_42x_EN), dsc_sblk_1), 166 + }; 167 + 156 168 static const struct dpu_intf_cfg sm8350_intf[] = { 157 - INTF_BLK("intf_0", INTF_0, 0x34000, 0x280, INTF_DP, MSM_DP_CONTROLLER_0, 24, INTF_SC7280_MASK, MDP_SSPP_TOP0_INTR, 24, 25), 158 - INTF_BLK("intf_1", INTF_1, 0x35000, 0x2c4, INTF_DSI, 0, 24, INTF_SC7280_MASK, MDP_SSPP_TOP0_INTR, 26, 27), 159 - INTF_BLK("intf_2", INTF_2, 0x36000, 0x2c4, INTF_DSI, 1, 24, INTF_SC7280_MASK, MDP_SSPP_TOP0_INTR, 28, 29), 160 - INTF_BLK("intf_3", INTF_3, 0x37000, 0x280, INTF_DP, MSM_DP_CONTROLLER_1, 24, INTF_SC7280_MASK, MDP_SSPP_TOP0_INTR, 30, 31), 169 + INTF_BLK("intf_0", INTF_0, 0x34000, 0x280, INTF_DP, MSM_DP_CONTROLLER_0, 24, INTF_SC7280_MASK, 170 + DPU_IRQ_IDX(MDP_SSPP_TOP0_INTR, 24), 171 + DPU_IRQ_IDX(MDP_SSPP_TOP0_INTR, 25)), 172 + INTF_BLK_DSI_TE("intf_1", INTF_1, 0x35000, 0x2c4, INTF_DSI, 0, 24, INTF_SC7280_MASK, 173 + DPU_IRQ_IDX(MDP_SSPP_TOP0_INTR, 26), 174 + DPU_IRQ_IDX(MDP_SSPP_TOP0_INTR, 27), 175 + DPU_IRQ_IDX(MDP_INTF1_7xxx_TEAR_INTR, 2)), 176 + INTF_BLK_DSI_TE("intf_2", INTF_2, 0x36000, 0x2c4, INTF_DSI, 1, 24, INTF_SC7280_MASK, 177 + DPU_IRQ_IDX(MDP_SSPP_TOP0_INTR, 28), 178 + DPU_IRQ_IDX(MDP_SSPP_TOP0_INTR, 29), 179 + DPU_IRQ_IDX(MDP_INTF2_7xxx_TEAR_INTR, 2)), 180 + INTF_BLK("intf_3", INTF_3, 0x37000, 0x280, INTF_DP, MSM_DP_CONTROLLER_1, 24, INTF_SC7280_MASK, 181 + DPU_IRQ_IDX(MDP_SSPP_TOP0_INTR, 30), 182 + DPU_IRQ_IDX(MDP_SSPP_TOP0_INTR, 31)), 161 183 }; 162 184 163 185 static const struct dpu_perf_cfg sm8350_perf_data = { ··· 227 205 .dspp = sm8350_dspp, 228 206 .pingpong_count = ARRAY_SIZE(sm8350_pp), 229 207 .pingpong = sm8350_pp, 208 + .dsc_count = ARRAY_SIZE(sm8350_dsc), 209 + .dsc = sm8350_dsc, 230 210 .merge_3d_count = ARRAY_SIZE(sm8350_merge_3d), 231 211 .merge_3d = sm8350_merge_3d, 232 212 .intf_count = ARRAY_SIZE(sm8350_intf), 233 213 .intf = sm8350_intf, 234 214 .vbif_count = ARRAY_SIZE(sdm845_vbif), 235 215 .vbif = sdm845_vbif, 236 - .reg_dma_count = 1, 237 - .dma_cfg = &sm8350_regdma, 238 216 .perf = &sm8350_perf_data, 239 217 .mdss_irqs = BIT(MDP_SSPP_TOP0_INTR) | \ 240 218 BIT(MDP_SSPP_TOP0_INTR2) | \ 241 219 BIT(MDP_SSPP_TOP0_HIST_INTR) | \ 242 220 BIT(MDP_INTF0_7xxx_INTR) | \ 243 221 BIT(MDP_INTF1_7xxx_INTR) | \ 222 + BIT(MDP_INTF1_7xxx_TEAR_INTR) | \ 244 223 BIT(MDP_INTF2_7xxx_INTR) | \ 224 + BIT(MDP_INTF2_7xxx_TEAR_INTR) | \ 245 225 BIT(MDP_INTF3_7xxx_INTR), 246 226 }; 247 227
+39 -8
drivers/gpu/drm/msm/disp/dpu1/catalog/dpu_7_2_sc7280.h
··· 31 31 .clk_ctrls[DPU_CLK_CTRL_DMA0] = { .reg_off = 0x2ac, .bit_off = 8 }, 32 32 .clk_ctrls[DPU_CLK_CTRL_DMA1] = { .reg_off = 0x2b4, .bit_off = 8 }, 33 33 .clk_ctrls[DPU_CLK_CTRL_DMA2] = { .reg_off = 0x2c4, .bit_off = 8 }, 34 + .clk_ctrls[DPU_CLK_CTRL_WB2] = { .reg_off = 0x3b8, .bit_off = 24 }, 34 35 }, 35 36 }; 36 37 ··· 84 83 85 84 static const struct dpu_dspp_cfg sc7280_dspp[] = { 86 85 DSPP_BLK("dspp_0", DSPP_0, 0x54000, DSPP_SC7180_MASK, 87 - &sc7180_dspp_sblk), 86 + &sm8150_dspp_sblk), 88 87 }; 89 88 90 89 static const struct dpu_pingpong_cfg sc7280_pp[] = { 91 - PP_BLK_DITHER("pingpong_0", PINGPONG_0, 0x69000, 0, sc7280_pp_sblk, -1, -1), 92 - PP_BLK_DITHER("pingpong_1", PINGPONG_1, 0x6a000, 0, sc7280_pp_sblk, -1, -1), 93 - PP_BLK_DITHER("pingpong_2", PINGPONG_2, 0x6b000, 0, sc7280_pp_sblk, -1, -1), 94 - PP_BLK_DITHER("pingpong_3", PINGPONG_3, 0x6c000, 0, sc7280_pp_sblk, -1, -1), 90 + PP_BLK_DITHER("pingpong_0", PINGPONG_0, 0x69000, 0, sc7280_pp_sblk, 91 + DPU_IRQ_IDX(MDP_SSPP_TOP0_INTR, 8), 92 + -1), 93 + PP_BLK_DITHER("pingpong_1", PINGPONG_1, 0x6a000, 0, sc7280_pp_sblk, 94 + DPU_IRQ_IDX(MDP_SSPP_TOP0_INTR, 9), 95 + -1), 96 + PP_BLK_DITHER("pingpong_2", PINGPONG_2, 0x6b000, 0, sc7280_pp_sblk, 97 + DPU_IRQ_IDX(MDP_SSPP_TOP0_INTR, 10), 98 + -1), 99 + PP_BLK_DITHER("pingpong_3", PINGPONG_3, 0x6c000, 0, sc7280_pp_sblk, 100 + DPU_IRQ_IDX(MDP_SSPP_TOP0_INTR, 11), 101 + -1), 102 + }; 103 + 104 + /* NOTE: sc7280 only has one DSC hard slice encoder */ 105 + static const struct dpu_dsc_cfg sc7280_dsc[] = { 106 + DSC_BLK_1_2("dce_0_0", DSC_0, 0x80000, 0x29c, BIT(DPU_DSC_NATIVE_42x_EN), dsc_sblk_0), 107 + }; 108 + 109 + static const struct dpu_wb_cfg sc7280_wb[] = { 110 + WB_BLK("wb_2", WB_2, 0x65000, WB_SM8250_MASK, DPU_CLK_CTRL_WB2, 6, 111 + VBIF_RT, MDP_SSPP_TOP0_INTR, 4096, 4), 95 112 }; 96 113 97 114 static const struct dpu_intf_cfg sc7280_intf[] = { 98 - INTF_BLK("intf_0", INTF_0, 0x34000, 0x280, INTF_DP, MSM_DP_CONTROLLER_0, 24, INTF_SC7280_MASK, MDP_SSPP_TOP0_INTR, 24, 25), 99 - INTF_BLK("intf_1", INTF_1, 0x35000, 0x2c4, INTF_DSI, 0, 24, INTF_SC7280_MASK, MDP_SSPP_TOP0_INTR, 26, 27), 100 - INTF_BLK("intf_5", INTF_5, 0x39000, 0x280, INTF_DP, MSM_DP_CONTROLLER_1, 24, INTF_SC7280_MASK, MDP_SSPP_TOP0_INTR, 22, 23), 115 + INTF_BLK("intf_0", INTF_0, 0x34000, 0x280, INTF_DP, MSM_DP_CONTROLLER_0, 24, INTF_SC7280_MASK, 116 + DPU_IRQ_IDX(MDP_SSPP_TOP0_INTR, 24), 117 + DPU_IRQ_IDX(MDP_SSPP_TOP0_INTR, 25)), 118 + INTF_BLK_DSI_TE("intf_1", INTF_1, 0x35000, 0x2c4, INTF_DSI, 0, 24, INTF_SC7280_MASK, 119 + DPU_IRQ_IDX(MDP_SSPP_TOP0_INTR, 26), 120 + DPU_IRQ_IDX(MDP_SSPP_TOP0_INTR, 27), 121 + DPU_IRQ_IDX(MDP_INTF1_7xxx_TEAR_INTR, 2)), 122 + INTF_BLK("intf_5", INTF_5, 0x39000, 0x280, INTF_DP, MSM_DP_CONTROLLER_1, 24, INTF_SC7280_MASK, 123 + DPU_IRQ_IDX(MDP_SSPP_TOP0_INTR, 22), 124 + DPU_IRQ_IDX(MDP_SSPP_TOP0_INTR, 23)), 101 125 }; 102 126 103 127 static const struct dpu_perf_cfg sc7280_perf_data = { ··· 168 142 .mixer = sc7280_lm, 169 143 .pingpong_count = ARRAY_SIZE(sc7280_pp), 170 144 .pingpong = sc7280_pp, 145 + .dsc_count = ARRAY_SIZE(sc7280_dsc), 146 + .dsc = sc7280_dsc, 147 + .wb_count = ARRAY_SIZE(sc7280_wb), 148 + .wb = sc7280_wb, 171 149 .intf_count = ARRAY_SIZE(sc7280_intf), 172 150 .intf = sc7280_intf, 173 151 .vbif_count = ARRAY_SIZE(sdm845_vbif), ··· 182 152 BIT(MDP_SSPP_TOP0_HIST_INTR) | \ 183 153 BIT(MDP_INTF0_7xxx_INTR) | \ 184 154 BIT(MDP_INTF1_7xxx_INTR) | \ 155 + BIT(MDP_INTF1_7xxx_TEAR_INTR) | \ 185 156 BIT(MDP_INTF5_7xxx_INTR), 186 157 }; 187 158
+50 -13
drivers/gpu/drm/msm/disp/dpu1/catalog/dpu_8_0_sc8280xp.h
··· 42 42 }, 43 43 }; 44 44 45 + /* FIXME: get rid of DPU_CTL_SPLIT_DISPLAY in favour of proper ACTIVE_CTL support */ 45 46 static const struct dpu_ctl_cfg sc8280xp_ctl[] = { 46 47 { 47 48 .name = "ctl_0", .id = CTL_0, 48 49 .base = 0x15000, .len = 0x204, 49 - .features = CTL_SC7280_MASK, 50 + .features = BIT(DPU_CTL_SPLIT_DISPLAY) | CTL_SC7280_MASK, 50 51 .intr_start = DPU_IRQ_IDX(MDP_SSPP_TOP0_INTR2, 9), 51 52 }, 52 53 { 53 54 .name = "ctl_1", .id = CTL_1, 54 55 .base = 0x16000, .len = 0x204, 55 - .features = CTL_SC7280_MASK, 56 + .features = BIT(DPU_CTL_SPLIT_DISPLAY) | CTL_SC7280_MASK, 56 57 .intr_start = DPU_IRQ_IDX(MDP_SSPP_TOP0_INTR2, 10), 57 58 }, 58 59 { ··· 142 141 MERGE_3D_BLK("merge_3d_2", MERGE_3D_2, 0x50000), 143 142 }; 144 143 144 + /* 145 + * NOTE: Each display compression engine (DCE) contains dual hard 146 + * slice DSC encoders so both share same base address but with 147 + * its own different sub block address. 148 + */ 149 + static const struct dpu_dsc_cfg sc8280xp_dsc[] = { 150 + DSC_BLK_1_2("dce_0_0", DSC_0, 0x80000, 0x29c, 0, dsc_sblk_0), 151 + DSC_BLK_1_2("dce_0_1", DSC_1, 0x80000, 0x29c, 0, dsc_sblk_1), 152 + DSC_BLK_1_2("dce_1_0", DSC_2, 0x81000, 0x29c, BIT(DPU_DSC_NATIVE_42x_EN), dsc_sblk_0), 153 + DSC_BLK_1_2("dce_1_1", DSC_3, 0x81000, 0x29c, BIT(DPU_DSC_NATIVE_42x_EN), dsc_sblk_1), 154 + DSC_BLK_1_2("dce_2_0", DSC_4, 0x82000, 0x29c, 0, dsc_sblk_0), 155 + DSC_BLK_1_2("dce_2_1", DSC_5, 0x82000, 0x29c, 0, dsc_sblk_1), 156 + }; 157 + 145 158 /* TODO: INTF 3, 8 and 7 are used for MST, marked as INTF_NONE for now */ 146 159 static const struct dpu_intf_cfg sc8280xp_intf[] = { 147 - INTF_BLK("intf_0", INTF_0, 0x34000, 0x280, INTF_DP, MSM_DP_CONTROLLER_0, 24, INTF_SC7280_MASK, MDP_SSPP_TOP0_INTR, 24, 25), 148 - INTF_BLK("intf_1", INTF_1, 0x35000, 0x300, INTF_DSI, 0, 24, INTF_SC7280_MASK, MDP_SSPP_TOP0_INTR, 26, 27), 149 - INTF_BLK("intf_2", INTF_2, 0x36000, 0x300, INTF_DSI, 1, 24, INTF_SC7280_MASK, MDP_SSPP_TOP0_INTR, 28, 29), 150 - INTF_BLK("intf_3", INTF_3, 0x37000, 0x280, INTF_NONE, MSM_DP_CONTROLLER_0, 24, INTF_SC7280_MASK, MDP_SSPP_TOP0_INTR, 30, 31), 151 - INTF_BLK("intf_4", INTF_4, 0x38000, 0x280, INTF_DP, MSM_DP_CONTROLLER_1, 24, INTF_SC7280_MASK, MDP_SSPP_TOP0_INTR, 20, 21), 152 - INTF_BLK("intf_5", INTF_5, 0x39000, 0x280, INTF_DP, MSM_DP_CONTROLLER_3, 24, INTF_SC7280_MASK, MDP_SSPP_TOP0_INTR, 22, 23), 153 - INTF_BLK("intf_6", INTF_6, 0x3a000, 0x280, INTF_DP, MSM_DP_CONTROLLER_2, 24, INTF_SC7280_MASK, MDP_SSPP_TOP0_INTR, 16, 17), 154 - INTF_BLK("intf_7", INTF_7, 0x3b000, 0x280, INTF_NONE, MSM_DP_CONTROLLER_2, 24, INTF_SC7280_MASK, MDP_SSPP_TOP0_INTR, 18, 19), 155 - INTF_BLK("intf_8", INTF_8, 0x3c000, 0x280, INTF_NONE, MSM_DP_CONTROLLER_1, 24, INTF_SC7280_MASK, MDP_SSPP_TOP0_INTR, 12, 13), 160 + INTF_BLK("intf_0", INTF_0, 0x34000, 0x280, INTF_DP, MSM_DP_CONTROLLER_0, 24, INTF_SC7280_MASK, 161 + DPU_IRQ_IDX(MDP_SSPP_TOP0_INTR, 24), 162 + DPU_IRQ_IDX(MDP_SSPP_TOP0_INTR, 25)), 163 + INTF_BLK_DSI_TE("intf_1", INTF_1, 0x35000, 0x300, INTF_DSI, 0, 24, INTF_SC7280_MASK, 164 + DPU_IRQ_IDX(MDP_SSPP_TOP0_INTR, 26), 165 + DPU_IRQ_IDX(MDP_SSPP_TOP0_INTR, 27), 166 + DPU_IRQ_IDX(MDP_INTF1_7xxx_TEAR_INTR, 2)), 167 + INTF_BLK_DSI_TE("intf_2", INTF_2, 0x36000, 0x300, INTF_DSI, 1, 24, INTF_SC7280_MASK, 168 + DPU_IRQ_IDX(MDP_SSPP_TOP0_INTR, 28), 169 + DPU_IRQ_IDX(MDP_SSPP_TOP0_INTR, 29), 170 + DPU_IRQ_IDX(MDP_INTF2_7xxx_TEAR_INTR, 2)), 171 + INTF_BLK("intf_3", INTF_3, 0x37000, 0x280, INTF_NONE, MSM_DP_CONTROLLER_0, 24, INTF_SC7280_MASK, 172 + DPU_IRQ_IDX(MDP_SSPP_TOP0_INTR, 30), 173 + DPU_IRQ_IDX(MDP_SSPP_TOP0_INTR, 31)), 174 + INTF_BLK("intf_4", INTF_4, 0x38000, 0x280, INTF_DP, MSM_DP_CONTROLLER_1, 24, INTF_SC7280_MASK, 175 + DPU_IRQ_IDX(MDP_SSPP_TOP0_INTR, 20), 176 + DPU_IRQ_IDX(MDP_SSPP_TOP0_INTR, 21)), 177 + INTF_BLK("intf_5", INTF_5, 0x39000, 0x280, INTF_DP, MSM_DP_CONTROLLER_3, 24, INTF_SC7280_MASK, 178 + DPU_IRQ_IDX(MDP_SSPP_TOP0_INTR, 22), 179 + DPU_IRQ_IDX(MDP_SSPP_TOP0_INTR, 23)), 180 + INTF_BLK("intf_6", INTF_6, 0x3a000, 0x280, INTF_DP, MSM_DP_CONTROLLER_2, 24, INTF_SC7280_MASK, 181 + DPU_IRQ_IDX(MDP_SSPP_TOP0_INTR, 16), 182 + DPU_IRQ_IDX(MDP_SSPP_TOP0_INTR, 17)), 183 + INTF_BLK("intf_7", INTF_7, 0x3b000, 0x280, INTF_NONE, MSM_DP_CONTROLLER_2, 24, INTF_SC7280_MASK, 184 + DPU_IRQ_IDX(MDP_SSPP_TOP0_INTR, 18), 185 + DPU_IRQ_IDX(MDP_SSPP_TOP0_INTR, 19)), 186 + INTF_BLK("intf_8", INTF_8, 0x3c000, 0x280, INTF_NONE, MSM_DP_CONTROLLER_1, 24, INTF_SC7280_MASK, 187 + DPU_IRQ_IDX(MDP_SSPP_TOP0_INTR, 12), 188 + DPU_IRQ_IDX(MDP_SSPP_TOP0_INTR, 13)), 156 189 }; 157 190 158 191 static const struct dpu_perf_cfg sc8280xp_perf_data = { ··· 231 196 .dspp = sc8280xp_dspp, 232 197 .pingpong_count = ARRAY_SIZE(sc8280xp_pp), 233 198 .pingpong = sc8280xp_pp, 199 + .dsc_count = ARRAY_SIZE(sc8280xp_dsc), 200 + .dsc = sc8280xp_dsc, 234 201 .merge_3d_count = ARRAY_SIZE(sc8280xp_merge_3d), 235 202 .merge_3d = sc8280xp_merge_3d, 236 203 .intf_count = ARRAY_SIZE(sc8280xp_intf), 237 204 .intf = sc8280xp_intf, 238 205 .vbif_count = ARRAY_SIZE(sdm845_vbif), 239 206 .vbif = sdm845_vbif, 240 - .reg_dma_count = 1, 241 - .dma_cfg = &sc8280xp_regdma, 242 207 .perf = &sc8280xp_perf_data, 243 208 .mdss_irqs = BIT(MDP_SSPP_TOP0_INTR) | \ 244 209 BIT(MDP_SSPP_TOP0_INTR2) | \ 245 210 BIT(MDP_SSPP_TOP0_HIST_INTR) | \ 246 211 BIT(MDP_INTF0_7xxx_INTR) | \ 247 212 BIT(MDP_INTF1_7xxx_INTR) | \ 213 + BIT(MDP_INTF1_7xxx_TEAR_INTR) | \ 248 214 BIT(MDP_INTF2_7xxx_INTR) | \ 215 + BIT(MDP_INTF2_7xxx_TEAR_INTR) | \ 249 216 BIT(MDP_INTF3_7xxx_INTR) | \ 250 217 BIT(MDP_INTF4_7xxx_INTR) | \ 251 218 BIT(MDP_INTF5_7xxx_INTR) | \
+38 -14
drivers/gpu/drm/msm/disp/dpu1/catalog/dpu_8_1_sm8450.h
··· 47 47 { 48 48 .name = "ctl_0", .id = CTL_0, 49 49 .base = 0x15000, .len = 0x204, 50 - .features = BIT(DPU_CTL_ACTIVE_CFG) | BIT(DPU_CTL_SPLIT_DISPLAY) | BIT(DPU_CTL_FETCH_ACTIVE), 50 + .features = BIT(DPU_CTL_SPLIT_DISPLAY) | CTL_SC7280_MASK, 51 51 .intr_start = DPU_IRQ_IDX(MDP_SSPP_TOP0_INTR2, 9), 52 52 }, 53 53 { ··· 107 107 LM_BLK("lm_1", LM_1, 0x45000, MIXER_SDM845_MASK, 108 108 &sdm845_lm_sblk, PINGPONG_1, LM_0, DSPP_1), 109 109 LM_BLK("lm_2", LM_2, 0x46000, MIXER_SDM845_MASK, 110 - &sdm845_lm_sblk, PINGPONG_2, LM_3, 0), 110 + &sdm845_lm_sblk, PINGPONG_2, LM_3, DSPP_2), 111 111 LM_BLK("lm_3", LM_3, 0x47000, MIXER_SDM845_MASK, 112 - &sdm845_lm_sblk, PINGPONG_3, LM_2, 0), 112 + &sdm845_lm_sblk, PINGPONG_3, LM_2, DSPP_3), 113 113 LM_BLK("lm_4", LM_4, 0x48000, MIXER_SDM845_MASK, 114 114 &sdm845_lm_sblk, PINGPONG_4, LM_5, 0), 115 115 LM_BLK("lm_5", LM_5, 0x49000, MIXER_SDM845_MASK, ··· 126 126 DSPP_BLK("dspp_3", DSPP_3, 0x5a000, DSPP_SC7180_MASK, 127 127 &sm8150_dspp_sblk), 128 128 }; 129 - /* FIXME: interrupts */ 129 + 130 130 static const struct dpu_pingpong_cfg sm8450_pp[] = { 131 131 PP_BLK_DITHER("pingpong_0", PINGPONG_0, 0x69000, MERGE_3D_0, sc7280_pp_sblk, 132 132 DPU_IRQ_IDX(MDP_SSPP_TOP0_INTR, 8), 133 - DPU_IRQ_IDX(MDP_SSPP_TOP0_INTR, 12)), 133 + -1), 134 134 PP_BLK_DITHER("pingpong_1", PINGPONG_1, 0x6a000, MERGE_3D_0, sc7280_pp_sblk, 135 135 DPU_IRQ_IDX(MDP_SSPP_TOP0_INTR, 9), 136 - DPU_IRQ_IDX(MDP_SSPP_TOP0_INTR, 13)), 136 + -1), 137 137 PP_BLK_DITHER("pingpong_2", PINGPONG_2, 0x6b000, MERGE_3D_1, sc7280_pp_sblk, 138 138 DPU_IRQ_IDX(MDP_SSPP_TOP0_INTR, 10), 139 - DPU_IRQ_IDX(MDP_SSPP_TOP0_INTR, 14)), 139 + -1), 140 140 PP_BLK_DITHER("pingpong_3", PINGPONG_3, 0x6c000, MERGE_3D_1, sc7280_pp_sblk, 141 141 DPU_IRQ_IDX(MDP_SSPP_TOP0_INTR, 11), 142 - DPU_IRQ_IDX(MDP_SSPP_TOP0_INTR, 15)), 142 + -1), 143 143 PP_BLK_DITHER("pingpong_4", PINGPONG_4, 0x6d000, MERGE_3D_2, sc7280_pp_sblk, 144 144 DPU_IRQ_IDX(MDP_SSPP_TOP0_INTR2, 30), 145 145 -1), ··· 161 161 MERGE_3D_BLK("merge_3d_3", MERGE_3D_3, 0x65f00), 162 162 }; 163 163 164 + /* 165 + * NOTE: Each display compression engine (DCE) contains dual hard 166 + * slice DSC encoders so both share same base address but with 167 + * its own different sub block address. 168 + */ 169 + static const struct dpu_dsc_cfg sm8450_dsc[] = { 170 + DSC_BLK_1_2("dce_0_0", DSC_0, 0x80000, 0x29c, 0, dsc_sblk_0), 171 + DSC_BLK_1_2("dce_0_1", DSC_1, 0x80000, 0x29c, 0, dsc_sblk_1), 172 + DSC_BLK_1_2("dce_1_0", DSC_2, 0x81000, 0x29c, BIT(DPU_DSC_NATIVE_42x_EN), dsc_sblk_0), 173 + DSC_BLK_1_2("dce_1_1", DSC_3, 0x81000, 0x29c, BIT(DPU_DSC_NATIVE_42x_EN), dsc_sblk_1), 174 + }; 175 + 164 176 static const struct dpu_intf_cfg sm8450_intf[] = { 165 - INTF_BLK("intf_0", INTF_0, 0x34000, 0x280, INTF_DP, MSM_DP_CONTROLLER_0, 24, INTF_SC7280_MASK, MDP_SSPP_TOP0_INTR, 24, 25), 166 - INTF_BLK("intf_1", INTF_1, 0x35000, 0x300, INTF_DSI, 0, 24, INTF_SC7280_MASK, MDP_SSPP_TOP0_INTR, 26, 27), 167 - INTF_BLK("intf_2", INTF_2, 0x36000, 0x300, INTF_DSI, 1, 24, INTF_SC7280_MASK, MDP_SSPP_TOP0_INTR, 28, 29), 168 - INTF_BLK("intf_3", INTF_3, 0x37000, 0x280, INTF_DP, MSM_DP_CONTROLLER_1, 24, INTF_SC7280_MASK, MDP_SSPP_TOP0_INTR, 30, 31), 177 + INTF_BLK("intf_0", INTF_0, 0x34000, 0x280, INTF_DP, MSM_DP_CONTROLLER_0, 24, INTF_SC7280_MASK, 178 + DPU_IRQ_IDX(MDP_SSPP_TOP0_INTR, 24), 179 + DPU_IRQ_IDX(MDP_SSPP_TOP0_INTR, 25)), 180 + INTF_BLK_DSI_TE("intf_1", INTF_1, 0x35000, 0x300, INTF_DSI, 0, 24, INTF_SC7280_MASK, 181 + DPU_IRQ_IDX(MDP_SSPP_TOP0_INTR, 26), 182 + DPU_IRQ_IDX(MDP_SSPP_TOP0_INTR, 27), 183 + DPU_IRQ_IDX(MDP_INTF1_7xxx_TEAR_INTR, 2)), 184 + INTF_BLK_DSI_TE("intf_2", INTF_2, 0x36000, 0x300, INTF_DSI, 1, 24, INTF_SC7280_MASK, 185 + DPU_IRQ_IDX(MDP_SSPP_TOP0_INTR, 28), 186 + DPU_IRQ_IDX(MDP_SSPP_TOP0_INTR, 29), 187 + DPU_IRQ_IDX(MDP_INTF2_7xxx_TEAR_INTR, 2)), 188 + INTF_BLK("intf_3", INTF_3, 0x37000, 0x280, INTF_DP, MSM_DP_CONTROLLER_1, 24, INTF_SC7280_MASK, 189 + DPU_IRQ_IDX(MDP_SSPP_TOP0_INTR, 30), 190 + DPU_IRQ_IDX(MDP_SSPP_TOP0_INTR, 31)), 169 191 }; 170 192 171 193 static const struct dpu_perf_cfg sm8450_perf_data = { ··· 235 213 .dspp = sm8450_dspp, 236 214 .pingpong_count = ARRAY_SIZE(sm8450_pp), 237 215 .pingpong = sm8450_pp, 216 + .dsc_count = ARRAY_SIZE(sm8450_dsc), 217 + .dsc = sm8450_dsc, 238 218 .merge_3d_count = ARRAY_SIZE(sm8450_merge_3d), 239 219 .merge_3d = sm8450_merge_3d, 240 220 .intf_count = ARRAY_SIZE(sm8450_intf), 241 221 .intf = sm8450_intf, 242 222 .vbif_count = ARRAY_SIZE(sdm845_vbif), 243 223 .vbif = sdm845_vbif, 244 - .reg_dma_count = 1, 245 - .dma_cfg = &sm8450_regdma, 246 224 .perf = &sm8450_perf_data, 247 225 .mdss_irqs = BIT(MDP_SSPP_TOP0_INTR) | \ 248 226 BIT(MDP_SSPP_TOP0_INTR2) | \ 249 227 BIT(MDP_SSPP_TOP0_HIST_INTR) | \ 250 228 BIT(MDP_INTF0_7xxx_INTR) | \ 251 229 BIT(MDP_INTF1_7xxx_INTR) | \ 230 + BIT(MDP_INTF1_7xxx_TEAR_INTR) | \ 252 231 BIT(MDP_INTF2_7xxx_INTR) | \ 232 + BIT(MDP_INTF2_7xxx_TEAR_INTR) | \ 253 233 BIT(MDP_INTF3_7xxx_INTR), 254 234 }; 255 235
+30 -7
drivers/gpu/drm/msm/disp/dpu1/catalog/dpu_9_0_sm8550.h
··· 165 165 MERGE_3D_BLK("merge_3d_3", MERGE_3D_3, 0x66700), 166 166 }; 167 167 168 + /* 169 + * NOTE: Each display compression engine (DCE) contains dual hard 170 + * slice DSC encoders so both share same base address but with 171 + * its own different sub block address. 172 + */ 173 + static const struct dpu_dsc_cfg sm8550_dsc[] = { 174 + DSC_BLK_1_2("dce_0_0", DSC_0, 0x80000, 0x29c, 0, dsc_sblk_0), 175 + DSC_BLK_1_2("dce_0_1", DSC_1, 0x80000, 0x29c, 0, dsc_sblk_1), 176 + DSC_BLK_1_2("dce_1_0", DSC_2, 0x81000, 0x29c, BIT(DPU_DSC_NATIVE_42x_EN), dsc_sblk_0), 177 + DSC_BLK_1_2("dce_1_1", DSC_3, 0x81000, 0x29c, BIT(DPU_DSC_NATIVE_42x_EN), dsc_sblk_1), 178 + }; 179 + 168 180 static const struct dpu_intf_cfg sm8550_intf[] = { 169 - INTF_BLK("intf_0", INTF_0, 0x34000, 0x280, INTF_DP, MSM_DP_CONTROLLER_0, 24, INTF_SC7280_MASK, MDP_SSPP_TOP0_INTR, 24, 25), 170 - /* TODO TE sub-blocks for intf1 & intf2 */ 171 - INTF_BLK("intf_1", INTF_1, 0x35000, 0x300, INTF_DSI, 0, 24, INTF_SC7280_MASK, MDP_SSPP_TOP0_INTR, 26, 27), 172 - INTF_BLK("intf_2", INTF_2, 0x36000, 0x300, INTF_DSI, 1, 24, INTF_SC7280_MASK, MDP_SSPP_TOP0_INTR, 28, 29), 173 - INTF_BLK("intf_3", INTF_3, 0x37000, 0x280, INTF_DP, MSM_DP_CONTROLLER_1, 24, INTF_SC7280_MASK, MDP_SSPP_TOP0_INTR, 30, 31), 181 + INTF_BLK("intf_0", INTF_0, 0x34000, 0x280, INTF_DP, MSM_DP_CONTROLLER_0, 24, INTF_SC7280_MASK, 182 + DPU_IRQ_IDX(MDP_SSPP_TOP0_INTR, 24), 183 + DPU_IRQ_IDX(MDP_SSPP_TOP0_INTR, 25)), 184 + INTF_BLK_DSI_TE("intf_1", INTF_1, 0x35000, 0x300, INTF_DSI, 0, 24, INTF_SC7280_MASK, 185 + DPU_IRQ_IDX(MDP_SSPP_TOP0_INTR, 26), 186 + DPU_IRQ_IDX(MDP_SSPP_TOP0_INTR, 27), 187 + DPU_IRQ_IDX(MDP_INTF1_7xxx_TEAR_INTR, 2)), 188 + INTF_BLK_DSI_TE("intf_2", INTF_2, 0x36000, 0x300, INTF_DSI, 1, 24, INTF_SC7280_MASK, 189 + DPU_IRQ_IDX(MDP_SSPP_TOP0_INTR, 28), 190 + DPU_IRQ_IDX(MDP_SSPP_TOP0_INTR, 29), 191 + DPU_IRQ_IDX(MDP_INTF2_7xxx_TEAR_INTR, 2)), 192 + INTF_BLK("intf_3", INTF_3, 0x37000, 0x280, INTF_DP, MSM_DP_CONTROLLER_1, 24, INTF_SC7280_MASK, 193 + DPU_IRQ_IDX(MDP_SSPP_TOP0_INTR, 30), 194 + DPU_IRQ_IDX(MDP_SSPP_TOP0_INTR, 31)), 174 195 }; 175 196 176 197 static const struct dpu_perf_cfg sm8550_perf_data = { ··· 239 218 .dspp = sm8550_dspp, 240 219 .pingpong_count = ARRAY_SIZE(sm8550_pp), 241 220 .pingpong = sm8550_pp, 221 + .dsc_count = ARRAY_SIZE(sm8550_dsc), 222 + .dsc = sm8550_dsc, 242 223 .merge_3d_count = ARRAY_SIZE(sm8550_merge_3d), 243 224 .merge_3d = sm8550_merge_3d, 244 225 .intf_count = ARRAY_SIZE(sm8550_intf), 245 226 .intf = sm8550_intf, 246 227 .vbif_count = ARRAY_SIZE(sdm845_vbif), 247 228 .vbif = sdm845_vbif, 248 - .reg_dma_count = 1, 249 - .dma_cfg = &sm8450_regdma, 250 229 .perf = &sm8550_perf_data, 251 230 .mdss_irqs = BIT(MDP_SSPP_TOP0_INTR) | \ 252 231 BIT(MDP_SSPP_TOP0_INTR2) | \ 253 232 BIT(MDP_SSPP_TOP0_HIST_INTR) | \ 254 233 BIT(MDP_INTF0_7xxx_INTR) | \ 255 234 BIT(MDP_INTF1_7xxx_INTR) | \ 235 + BIT(MDP_INTF1_7xxx_TEAR_INTR) | \ 256 236 BIT(MDP_INTF2_7xxx_INTR) | \ 237 + BIT(MDP_INTF2_7xxx_TEAR_INTR) | \ 257 238 BIT(MDP_INTF3_7xxx_INTR), 258 239 }; 259 240
+5 -2
drivers/gpu/drm/msm/disp/dpu1/dpu_crtc.c
··· 1392 1392 1393 1393 static int dpu_crtc_debugfs_state_show(struct seq_file *s, void *v) 1394 1394 { 1395 - struct drm_crtc *crtc = (struct drm_crtc *) s->private; 1395 + struct drm_crtc *crtc = s->private; 1396 1396 struct dpu_crtc *dpu_crtc = to_dpu_crtc(crtc); 1397 1397 1398 1398 seq_printf(s, "client type: %d\n", dpu_crtc_get_client_type(crtc)); ··· 1463 1463 struct drm_crtc *dpu_crtc_init(struct drm_device *dev, struct drm_plane *plane, 1464 1464 struct drm_plane *cursor) 1465 1465 { 1466 + struct msm_drm_private *priv = dev->dev_private; 1467 + struct dpu_kms *dpu_kms = to_dpu_kms(priv->kms); 1466 1468 struct drm_crtc *crtc = NULL; 1467 1469 struct dpu_crtc *dpu_crtc = NULL; 1468 1470 int i, ret; ··· 1496 1494 1497 1495 drm_crtc_helper_add(crtc, &dpu_crtc_helper_funcs); 1498 1496 1499 - drm_crtc_enable_color_mgmt(crtc, 0, true, 0); 1497 + if (dpu_kms->catalog->dspp_count) 1498 + drm_crtc_enable_color_mgmt(crtc, 0, true, 0); 1500 1499 1501 1500 /* save user friendly CRTC name for later */ 1502 1501 snprintf(dpu_crtc->name, DPU_CRTC_NAME_SIZE, "crtc%u", crtc->base.id);
+149 -138
drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c
··· 339 339 DRM_ERROR("irq timeout id=%u, intf_mode=%s intf=%d wb=%d, pp=%d, intr=%d\n", 340 340 DRMID(phys_enc->parent), 341 341 dpu_encoder_helper_get_intf_type(phys_enc->intf_mode), 342 - phys_enc->intf_idx - INTF_0, phys_enc->wb_idx - WB_0, 342 + phys_enc->hw_intf ? phys_enc->hw_intf->idx - INTF_0 : -1, 343 + phys_enc->hw_wb ? phys_enc->hw_wb->idx - WB_0 : -1, 343 344 phys_enc->hw_pp->idx - PINGPONG_0, intr_idx); 344 345 345 346 dpu_encoder_frame_done_callback(phys_enc->parent, phys_enc, ··· 496 495 hw_mdptop = phys_enc->hw_mdptop; 497 496 disp_info = &dpu_enc->disp_info; 498 497 499 - if (disp_info->intf_type != DRM_MODE_ENCODER_DSI) 498 + if (disp_info->intf_type != INTF_DSI) 500 499 return; 501 500 502 501 /** ··· 667 666 struct dpu_kms *dpu_kms; 668 667 struct dpu_hw_mdp *hw_mdptop; 669 668 struct drm_encoder *drm_enc; 669 + struct dpu_encoder_phys *phys_enc; 670 670 int i; 671 671 672 672 if (!dpu_enc || !disp_info) { ··· 698 696 vsync_cfg.ppnumber[i] = dpu_enc->hw_pp[i]->idx; 699 697 700 698 vsync_cfg.pp_count = dpu_enc->num_phys_encs; 699 + vsync_cfg.frame_rate = drm_mode_vrefresh(&dpu_enc->base.crtc->state->adjusted_mode); 700 + 701 701 if (disp_info->is_te_using_watchdog_timer) 702 702 vsync_cfg.vsync_source = DPU_VSYNC_SOURCE_WD_TIMER_0; 703 703 else 704 704 vsync_cfg.vsync_source = DPU_VSYNC0_SOURCE_GPIO; 705 705 706 706 hw_mdptop->ops.setup_vsync_source(hw_mdptop, &vsync_cfg); 707 + 708 + for (i = 0; i < dpu_enc->num_phys_encs; i++) { 709 + phys_enc = dpu_enc->phys_encs[i]; 710 + 711 + if (phys_enc->has_intf_te && phys_enc->hw_intf->ops.vsync_sel) 712 + phys_enc->hw_intf->ops.vsync_sel(phys_enc->hw_intf, 713 + vsync_cfg.vsync_source); 714 + } 707 715 } 708 716 } 709 717 ··· 1139 1127 } 1140 1128 1141 1129 1142 - if (dpu_enc->disp_info.intf_type == DRM_MODE_ENCODER_TMDS && 1130 + if (dpu_enc->disp_info.intf_type == INTF_DP && 1143 1131 dpu_enc->cur_master->hw_mdptop && 1144 1132 dpu_enc->cur_master->hw_mdptop->ops.intf_audio_select) 1145 1133 dpu_enc->cur_master->hw_mdptop->ops.intf_audio_select( ··· 1147 1135 1148 1136 _dpu_encoder_update_vsync_source(dpu_enc, &dpu_enc->disp_info); 1149 1137 1150 - if (dpu_enc->disp_info.intf_type == DRM_MODE_ENCODER_DSI && 1138 + if (dpu_enc->disp_info.intf_type == INTF_DSI && 1151 1139 !WARN_ON(dpu_enc->num_phys_encs == 0)) { 1152 1140 unsigned bpc = dpu_enc->connector->display_info.bpc; 1153 1141 for (i = 0; i < MAX_CHANNELS_PER_ENC; i++) { ··· 1270 1258 mutex_unlock(&dpu_enc->enc_lock); 1271 1259 } 1272 1260 1273 - static enum dpu_intf dpu_encoder_get_intf(const struct dpu_mdss_cfg *catalog, 1261 + static struct dpu_hw_intf *dpu_encoder_get_intf(const struct dpu_mdss_cfg *catalog, 1262 + struct dpu_rm *dpu_rm, 1274 1263 enum dpu_intf_type type, u32 controller_id) 1275 1264 { 1276 1265 int i = 0; 1277 1266 1278 1267 if (type == INTF_WB) 1279 - return INTF_MAX; 1268 + return NULL; 1280 1269 1281 1270 for (i = 0; i < catalog->intf_count; i++) { 1282 1271 if (catalog->intf[i].type == type 1283 1272 && catalog->intf[i].controller_id == controller_id) { 1284 - return catalog->intf[i].id; 1273 + return dpu_rm_get_intf(dpu_rm, catalog->intf[i].id); 1285 1274 } 1286 1275 } 1287 1276 1288 - return INTF_MAX; 1289 - } 1290 - 1291 - static enum dpu_wb dpu_encoder_get_wb(const struct dpu_mdss_cfg *catalog, 1292 - enum dpu_intf_type type, u32 controller_id) 1293 - { 1294 - int i = 0; 1295 - 1296 - if (type != INTF_WB) 1297 - return WB_MAX; 1298 - 1299 - for (i = 0; i < catalog->wb_count; i++) { 1300 - if (catalog->wb[i].id == controller_id) 1301 - return catalog->wb[i].id; 1302 - } 1303 - 1304 - return WB_MAX; 1277 + return NULL; 1305 1278 } 1306 1279 1307 1280 void dpu_encoder_vblank_callback(struct drm_encoder *drm_enc, ··· 1405 1408 */ 1406 1409 trace_dpu_enc_frame_done_cb_not_busy(DRMID(drm_enc), event, 1407 1410 dpu_encoder_helper_get_intf_type(ready_phys->intf_mode), 1408 - ready_phys->intf_idx, ready_phys->wb_idx); 1411 + ready_phys->hw_intf ? ready_phys->hw_intf->idx : -1, 1412 + ready_phys->hw_wb ? ready_phys->hw_wb->idx : -1); 1409 1413 return; 1410 1414 } 1411 1415 ··· 1486 1488 1487 1489 trace_dpu_enc_trigger_flush(DRMID(drm_enc), 1488 1490 dpu_encoder_helper_get_intf_type(phys->intf_mode), 1489 - phys->intf_idx, phys->wb_idx, 1491 + phys->hw_intf ? phys->hw_intf->idx : -1, 1492 + phys->hw_wb ? phys->hw_wb->idx : -1, 1490 1493 pending_kickoff_cnt, ctl->idx, 1491 1494 extra_flush_bits, ret); 1492 1495 } ··· 1822 1823 return DIV_ROUND_UP(total_pixels, dsc->slice_width); 1823 1824 } 1824 1825 1825 - static void dpu_encoder_dsc_pipe_cfg(struct dpu_hw_dsc *hw_dsc, 1826 + static void dpu_encoder_dsc_pipe_cfg(struct dpu_hw_ctl *ctl, 1827 + struct dpu_hw_dsc *hw_dsc, 1826 1828 struct dpu_hw_pingpong *hw_pp, 1827 1829 struct drm_dsc_config *dsc, 1828 1830 u32 common_mode, ··· 1839 1839 hw_pp->ops.setup_dsc(hw_pp); 1840 1840 1841 1841 if (hw_dsc->ops.dsc_bind_pingpong_blk) 1842 - hw_dsc->ops.dsc_bind_pingpong_blk(hw_dsc, true, hw_pp->idx); 1842 + hw_dsc->ops.dsc_bind_pingpong_blk(hw_dsc, hw_pp->idx); 1843 1843 1844 1844 if (hw_pp->ops.enable_dsc) 1845 1845 hw_pp->ops.enable_dsc(hw_pp); 1846 + 1847 + if (ctl->ops.update_pending_flush_dsc) 1848 + ctl->ops.update_pending_flush_dsc(ctl, hw_dsc->idx); 1846 1849 } 1847 1850 1848 1851 static void dpu_encoder_prep_dsc(struct dpu_encoder_virt *dpu_enc, ··· 1853 1850 { 1854 1851 /* coding only for 2LM, 2enc, 1 dsc config */ 1855 1852 struct dpu_encoder_phys *enc_master = dpu_enc->cur_master; 1853 + struct dpu_hw_ctl *ctl = enc_master->hw_ctl; 1856 1854 struct dpu_hw_dsc *hw_dsc[MAX_CHANNELS_PER_ENC]; 1857 1855 struct dpu_hw_pingpong *hw_pp[MAX_CHANNELS_PER_ENC]; 1858 1856 int this_frame_slices; ··· 1891 1887 initial_lines = dpu_encoder_dsc_initial_line_calc(dsc, enc_ip_w); 1892 1888 1893 1889 for (i = 0; i < MAX_CHANNELS_PER_ENC; i++) 1894 - dpu_encoder_dsc_pipe_cfg(hw_dsc[i], hw_pp[i], dsc, dsc_common_mode, initial_lines); 1890 + dpu_encoder_dsc_pipe_cfg(ctl, hw_dsc[i], hw_pp[i], 1891 + dsc, dsc_common_mode, initial_lines); 1895 1892 } 1896 1893 1897 1894 void dpu_encoder_prepare_for_kickoff(struct drm_encoder *drm_enc) ··· 1982 1977 phys->ops.handle_post_kickoff(phys); 1983 1978 } 1984 1979 1985 - if (dpu_enc->disp_info.intf_type == DRM_MODE_ENCODER_DSI && 1980 + if (dpu_enc->disp_info.intf_type == INTF_DSI && 1986 1981 !dpu_encoder_vsync_time(drm_enc, &wakeup_time)) { 1987 1982 trace_dpu_enc_early_kickoff(DRMID(drm_enc), 1988 1983 ktime_to_ms(wakeup_time)); ··· 2024 2019 } 2025 2020 } 2026 2021 2022 + static void dpu_encoder_dsc_pipe_clr(struct dpu_hw_ctl *ctl, 2023 + struct dpu_hw_dsc *hw_dsc, 2024 + struct dpu_hw_pingpong *hw_pp) 2025 + { 2026 + if (hw_dsc->ops.dsc_disable) 2027 + hw_dsc->ops.dsc_disable(hw_dsc); 2028 + 2029 + if (hw_pp->ops.disable_dsc) 2030 + hw_pp->ops.disable_dsc(hw_pp); 2031 + 2032 + if (hw_dsc->ops.dsc_bind_pingpong_blk) 2033 + hw_dsc->ops.dsc_bind_pingpong_blk(hw_dsc, PINGPONG_NONE); 2034 + 2035 + if (ctl->ops.update_pending_flush_dsc) 2036 + ctl->ops.update_pending_flush_dsc(ctl, hw_dsc->idx); 2037 + } 2038 + 2039 + static void dpu_encoder_unprep_dsc(struct dpu_encoder_virt *dpu_enc) 2040 + { 2041 + /* coding only for 2LM, 2enc, 1 dsc config */ 2042 + struct dpu_encoder_phys *enc_master = dpu_enc->cur_master; 2043 + struct dpu_hw_ctl *ctl = enc_master->hw_ctl; 2044 + struct dpu_hw_dsc *hw_dsc[MAX_CHANNELS_PER_ENC]; 2045 + struct dpu_hw_pingpong *hw_pp[MAX_CHANNELS_PER_ENC]; 2046 + int i; 2047 + 2048 + for (i = 0; i < MAX_CHANNELS_PER_ENC; i++) { 2049 + hw_pp[i] = dpu_enc->hw_pp[i]; 2050 + hw_dsc[i] = dpu_enc->hw_dsc[i]; 2051 + 2052 + if (hw_pp[i] && hw_dsc[i]) 2053 + dpu_encoder_dsc_pipe_clr(ctl, hw_dsc[i], hw_pp[i]); 2054 + } 2055 + } 2056 + 2027 2057 void dpu_encoder_helper_phys_cleanup(struct dpu_encoder_phys *phys_enc) 2028 2058 { 2029 2059 struct dpu_hw_ctl *ctl = phys_enc->hw_ctl; ··· 2080 2040 if (phys_enc->hw_wb) { 2081 2041 /* disable the PP block */ 2082 2042 if (phys_enc->hw_wb->ops.bind_pingpong_blk) 2083 - phys_enc->hw_wb->ops.bind_pingpong_blk(phys_enc->hw_wb, false, 2084 - phys_enc->hw_pp->idx); 2043 + phys_enc->hw_wb->ops.bind_pingpong_blk(phys_enc->hw_wb, PINGPONG_NONE); 2085 2044 2086 2045 /* mark WB flush as pending */ 2087 2046 if (phys_enc->hw_ctl->ops.update_pending_flush_wb) ··· 2089 2050 for (i = 0; i < dpu_enc->num_phys_encs; i++) { 2090 2051 if (dpu_enc->phys_encs[i] && phys_enc->hw_intf->ops.bind_pingpong_blk) 2091 2052 phys_enc->hw_intf->ops.bind_pingpong_blk( 2092 - dpu_enc->phys_encs[i]->hw_intf, false, 2093 - dpu_enc->phys_encs[i]->hw_pp->idx); 2053 + dpu_enc->phys_encs[i]->hw_intf, 2054 + PINGPONG_NONE); 2094 2055 2095 2056 /* mark INTF flush as pending */ 2096 2057 if (phys_enc->hw_ctl->ops.update_pending_flush_intf) ··· 2108 2069 phys_enc->hw_pp->merge_3d->idx); 2109 2070 } 2110 2071 2072 + if (dpu_enc->dsc) 2073 + dpu_encoder_unprep_dsc(dpu_enc); 2074 + 2111 2075 intf_cfg.stream_sel = 0; /* Don't care value for video mode */ 2112 2076 intf_cfg.mode_3d = dpu_encoder_helper_get_3d_blend_mode(phys_enc); 2077 + intf_cfg.dsc = dpu_encoder_helper_get_dsc(phys_enc); 2113 2078 2114 2079 if (phys_enc->hw_intf) 2115 2080 intf_cfg.intf = phys_enc->hw_intf->idx; ··· 2142 2099 struct dpu_encoder_phys *phys = dpu_enc->phys_encs[i]; 2143 2100 2144 2101 seq_printf(s, "intf:%d wb:%d vsync:%8d underrun:%8d ", 2145 - phys->intf_idx - INTF_0, phys->wb_idx - WB_0, 2102 + phys->hw_intf ? phys->hw_intf->idx - INTF_0 : -1, 2103 + phys->hw_wb ? phys->hw_wb->idx - WB_0 : -1, 2146 2104 atomic_read(&phys->vsync_cnt), 2147 2105 atomic_read(&phys->underrun_cnt)); 2148 2106 ··· 2159 2115 static int _dpu_encoder_init_debugfs(struct drm_encoder *drm_enc) 2160 2116 { 2161 2117 struct dpu_encoder_virt *dpu_enc = to_dpu_encoder_virt(drm_enc); 2162 - int i; 2163 2118 2164 - char name[DPU_NAME_SIZE]; 2119 + char name[12]; 2165 2120 2166 2121 if (!drm_enc->dev) { 2167 2122 DPU_ERROR("invalid encoder or kms\n"); 2168 2123 return -EINVAL; 2169 2124 } 2170 2125 2171 - snprintf(name, DPU_NAME_SIZE, "encoder%u", drm_enc->base.id); 2126 + snprintf(name, sizeof(name), "encoder%u", drm_enc->base.id); 2172 2127 2173 2128 /* create overall sub-directory for the encoder */ 2174 2129 dpu_enc->debugfs_root = debugfs_create_dir(name, ··· 2176 2133 /* don't error check these */ 2177 2134 debugfs_create_file("status", 0600, 2178 2135 dpu_enc->debugfs_root, dpu_enc, &_dpu_encoder_status_fops); 2179 - 2180 - for (i = 0; i < dpu_enc->num_phys_encs; i++) 2181 - if (dpu_enc->phys_encs[i]->ops.late_register) 2182 - dpu_enc->phys_encs[i]->ops.late_register( 2183 - dpu_enc->phys_encs[i], 2184 - dpu_enc->debugfs_root); 2185 2136 2186 2137 return 0; 2187 2138 } ··· 2219 2182 } 2220 2183 2221 2184 2222 - if (disp_info->intf_type == DRM_MODE_ENCODER_VIRTUAL) { 2185 + if (disp_info->intf_type == INTF_WB) { 2223 2186 enc = dpu_encoder_phys_wb_init(params); 2224 2187 2225 2188 if (IS_ERR(enc)) { ··· 2268 2231 { 2269 2232 int ret = 0; 2270 2233 int i = 0; 2271 - enum dpu_intf_type intf_type = INTF_NONE; 2272 2234 struct dpu_enc_phys_init_params phys_params; 2273 2235 2274 2236 if (!dpu_enc) { ··· 2282 2246 phys_params.parent = &dpu_enc->base; 2283 2247 phys_params.enc_spinlock = &dpu_enc->enc_spinlock; 2284 2248 2285 - switch (disp_info->intf_type) { 2286 - case DRM_MODE_ENCODER_DSI: 2287 - intf_type = INTF_DSI; 2288 - break; 2289 - case DRM_MODE_ENCODER_TMDS: 2290 - intf_type = INTF_DP; 2291 - break; 2292 - case DRM_MODE_ENCODER_VIRTUAL: 2293 - intf_type = INTF_WB; 2294 - break; 2295 - } 2296 - 2297 2249 WARN_ON(disp_info->num_of_h_tiles < 1); 2298 2250 2299 2251 DPU_DEBUG("dsi_info->num_of_h_tiles %d\n", disp_info->num_of_h_tiles); 2300 2252 2301 - if (disp_info->intf_type != DRM_MODE_ENCODER_VIRTUAL) 2253 + if (disp_info->intf_type != INTF_WB) 2302 2254 dpu_enc->idle_pc_supported = 2303 2255 dpu_kms->catalog->caps->has_idle_pc; 2304 2256 ··· 2313 2289 DPU_DEBUG("h_tile_instance %d = %d, split_role %d\n", 2314 2290 i, controller_id, phys_params.split_role); 2315 2291 2316 - phys_params.intf_idx = dpu_encoder_get_intf(dpu_kms->catalog, 2317 - intf_type, 2318 - controller_id); 2292 + phys_params.hw_intf = dpu_encoder_get_intf(dpu_kms->catalog, &dpu_kms->rm, 2293 + disp_info->intf_type, 2294 + controller_id); 2319 2295 2320 - phys_params.wb_idx = dpu_encoder_get_wb(dpu_kms->catalog, 2321 - intf_type, controller_id); 2322 - /* 2323 - * The phys_params might represent either an INTF or a WB unit, but not 2324 - * both of them at the same time. 2325 - */ 2326 - if ((phys_params.intf_idx == INTF_MAX) && 2327 - (phys_params.wb_idx == WB_MAX)) { 2328 - DPU_ERROR_ENC(dpu_enc, "could not get intf or wb: type %d, id %d\n", 2329 - intf_type, controller_id); 2330 - ret = -EINVAL; 2331 - } 2296 + if (disp_info->intf_type == INTF_WB && controller_id < WB_MAX) 2297 + phys_params.hw_wb = dpu_rm_get_wb(&dpu_kms->rm, controller_id); 2332 2298 2333 - if ((phys_params.intf_idx != INTF_MAX) && 2334 - (phys_params.wb_idx != WB_MAX)) { 2335 - DPU_ERROR_ENC(dpu_enc, "both intf and wb present: type %d, id %d\n", 2336 - intf_type, controller_id); 2337 - ret = -EINVAL; 2338 - } 2339 - 2340 - if (!ret) { 2341 - ret = dpu_encoder_virt_add_phys_encs(disp_info, 2342 - dpu_enc, &phys_params); 2343 - if (ret) 2344 - DPU_ERROR_ENC(dpu_enc, "failed to add phys encs\n"); 2345 - } 2346 - } 2347 - 2348 - for (i = 0; i < dpu_enc->num_phys_encs; i++) { 2349 - struct dpu_encoder_phys *phys = dpu_enc->phys_encs[i]; 2350 - atomic_set(&phys->vsync_cnt, 0); 2351 - atomic_set(&phys->underrun_cnt, 0); 2352 - 2353 - if (phys->intf_idx >= INTF_0 && phys->intf_idx < INTF_MAX) 2354 - phys->hw_intf = dpu_rm_get_intf(&dpu_kms->rm, phys->intf_idx); 2355 - 2356 - if (phys->wb_idx >= WB_0 && phys->wb_idx < WB_MAX) 2357 - phys->hw_wb = dpu_rm_get_wb(&dpu_kms->rm, phys->wb_idx); 2358 - 2359 - if (!phys->hw_intf && !phys->hw_wb) { 2299 + if (!phys_params.hw_intf && !phys_params.hw_wb) { 2360 2300 DPU_ERROR_ENC(dpu_enc, "no intf or wb block assigned at idx: %d\n", i); 2361 2301 ret = -EINVAL; 2302 + break; 2362 2303 } 2363 2304 2364 - if (phys->hw_intf && phys->hw_wb) { 2305 + if (phys_params.hw_intf && phys_params.hw_wb) { 2365 2306 DPU_ERROR_ENC(dpu_enc, 2366 2307 "invalid phys both intf and wb block at idx: %d\n", i); 2367 2308 ret = -EINVAL; 2309 + break; 2310 + } 2311 + 2312 + ret = dpu_encoder_virt_add_phys_encs(disp_info, 2313 + dpu_enc, &phys_params); 2314 + if (ret) { 2315 + DPU_ERROR_ENC(dpu_enc, "failed to add phys encs\n"); 2316 + break; 2368 2317 } 2369 2318 } 2370 2319 ··· 2387 2390 .early_unregister = dpu_encoder_early_unregister, 2388 2391 }; 2389 2392 2390 - int dpu_encoder_setup(struct drm_device *dev, struct drm_encoder *enc, 2393 + struct drm_encoder *dpu_encoder_init(struct drm_device *dev, 2394 + int drm_enc_mode, 2391 2395 struct msm_display_info *disp_info) 2392 2396 { 2393 2397 struct msm_drm_private *priv = dev->dev_private; ··· 2397 2399 struct dpu_encoder_virt *dpu_enc = NULL; 2398 2400 int ret = 0; 2399 2401 2400 - dpu_enc = to_dpu_encoder_virt(enc); 2402 + dpu_enc = devm_kzalloc(dev->dev, sizeof(*dpu_enc), GFP_KERNEL); 2403 + if (!dpu_enc) 2404 + return ERR_PTR(-ENOMEM); 2405 + 2406 + ret = drm_encoder_init(dev, &dpu_enc->base, &dpu_encoder_funcs, 2407 + drm_enc_mode, NULL); 2408 + if (ret) { 2409 + devm_kfree(dev->dev, dpu_enc); 2410 + return ERR_PTR(ret); 2411 + } 2412 + 2413 + drm_encoder_helper_add(&dpu_enc->base, &dpu_encoder_helper_funcs); 2414 + 2415 + spin_lock_init(&dpu_enc->enc_spinlock); 2416 + dpu_enc->enabled = false; 2417 + mutex_init(&dpu_enc->enc_lock); 2418 + mutex_init(&dpu_enc->rc_lock); 2401 2419 2402 2420 ret = dpu_encoder_setup_display(dpu_enc, dpu_kms, disp_info); 2403 2421 if (ret) ··· 2423 2409 timer_setup(&dpu_enc->frame_done_timer, 2424 2410 dpu_encoder_frame_done_timeout, 0); 2425 2411 2426 - if (disp_info->intf_type == DRM_MODE_ENCODER_DSI) 2412 + if (disp_info->intf_type == INTF_DSI) 2427 2413 timer_setup(&dpu_enc->vsync_event_timer, 2428 2414 dpu_encoder_vsync_event_handler, 2429 2415 0); 2430 - else if (disp_info->intf_type == DRM_MODE_ENCODER_TMDS) 2416 + else if (disp_info->intf_type == INTF_DP) 2431 2417 dpu_enc->wide_bus_en = msm_dp_wide_bus_available( 2432 2418 priv->dp[disp_info->h_tile_instance[0]]); 2433 2419 ··· 2442 2428 2443 2429 DPU_DEBUG_ENC(dpu_enc, "created\n"); 2444 2430 2445 - return ret; 2431 + return &dpu_enc->base; 2446 2432 2447 2433 fail: 2448 2434 DPU_ERROR("failed to create encoder\n"); 2449 2435 if (drm_enc) 2450 2436 dpu_encoder_destroy(drm_enc); 2451 2437 2452 - return ret; 2453 - 2454 - 2455 - } 2456 - 2457 - struct drm_encoder *dpu_encoder_init(struct drm_device *dev, 2458 - int drm_enc_mode) 2459 - { 2460 - struct dpu_encoder_virt *dpu_enc = NULL; 2461 - int rc = 0; 2462 - 2463 - dpu_enc = devm_kzalloc(dev->dev, sizeof(*dpu_enc), GFP_KERNEL); 2464 - if (!dpu_enc) 2465 - return ERR_PTR(-ENOMEM); 2466 - 2467 - 2468 - rc = drm_encoder_init(dev, &dpu_enc->base, &dpu_encoder_funcs, 2469 - drm_enc_mode, NULL); 2470 - if (rc) { 2471 - devm_kfree(dev->dev, dpu_enc); 2472 - return ERR_PTR(rc); 2473 - } 2474 - 2475 - drm_encoder_helper_add(&dpu_enc->base, &dpu_encoder_helper_funcs); 2476 - 2477 - spin_lock_init(&dpu_enc->enc_spinlock); 2478 - dpu_enc->enabled = false; 2479 - mutex_init(&dpu_enc->enc_lock); 2480 - mutex_init(&dpu_enc->rc_lock); 2481 - 2482 - return &dpu_enc->base; 2438 + return ERR_PTR(ret); 2483 2439 } 2484 2440 2485 2441 int dpu_encoder_wait_for_event(struct drm_encoder *drm_enc, ··· 2522 2538 struct dpu_encoder_virt *dpu_enc = to_dpu_encoder_virt(encoder); 2523 2539 2524 2540 return dpu_enc->dsc_mask; 2541 + } 2542 + 2543 + void dpu_encoder_phys_init(struct dpu_encoder_phys *phys_enc, 2544 + struct dpu_enc_phys_init_params *p) 2545 + { 2546 + int i; 2547 + 2548 + phys_enc->hw_mdptop = p->dpu_kms->hw_mdp; 2549 + phys_enc->hw_intf = p->hw_intf; 2550 + phys_enc->hw_wb = p->hw_wb; 2551 + phys_enc->parent = p->parent; 2552 + phys_enc->dpu_kms = p->dpu_kms; 2553 + phys_enc->split_role = p->split_role; 2554 + phys_enc->enc_spinlock = p->enc_spinlock; 2555 + phys_enc->enable_state = DPU_ENC_DISABLED; 2556 + 2557 + for (i = 0; i < ARRAY_SIZE(phys_enc->irq); i++) 2558 + phys_enc->irq[i] = -EINVAL; 2559 + 2560 + atomic_set(&phys_enc->vblank_refcount, 0); 2561 + atomic_set(&phys_enc->pending_kickoff_cnt, 0); 2562 + atomic_set(&phys_enc->pending_ctlstart_cnt, 0); 2563 + 2564 + atomic_set(&phys_enc->vsync_cnt, 0); 2565 + atomic_set(&phys_enc->underrun_cnt, 0); 2566 + 2567 + init_waitqueue_head(&phys_enc->pending_kickoff_wq); 2525 2568 }
+5 -13
drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.h
··· 21 21 22 22 /** 23 23 * struct msm_display_info - defines display properties 24 - * @intf_type: DRM_MODE_ENCODER_ type 24 + * @intf_type: INTF_ type 25 25 * @num_of_h_tiles: Number of horizontal tiles in case of split interface 26 26 * @h_tile_instance: Controller instance used per tile. Number of elements is 27 27 * based on num_of_h_tiles ··· 31 31 * @dsc: DSC configuration data for DSC-enabled displays 32 32 */ 33 33 struct msm_display_info { 34 - int intf_type; 34 + enum dpu_intf_type intf_type; 35 35 uint32_t num_of_h_tiles; 36 36 uint32_t h_tile_instance[MAX_H_TILES_PER_DISPLAY]; 37 37 bool is_cmd_mode; ··· 130 130 /** 131 131 * dpu_encoder_init - initialize virtual encoder object 132 132 * @dev: Pointer to drm device structure 133 + * @drm_enc_mode: corresponding DRM_MODE_ENCODER_* constant 133 134 * @disp_info: Pointer to display information structure 134 135 * Returns: Pointer to newly created drm encoder 135 136 */ 136 - struct drm_encoder *dpu_encoder_init( 137 - struct drm_device *dev, 138 - int drm_enc_mode); 139 - 140 - /** 141 - * dpu_encoder_setup - setup dpu_encoder for the display probed 142 - * @dev: Pointer to drm device structure 143 - * @enc: Pointer to the drm_encoder 144 - * @disp_info: Pointer to the display info 145 - */ 146 - int dpu_encoder_setup(struct drm_device *dev, struct drm_encoder *enc, 137 + struct drm_encoder *dpu_encoder_init(struct drm_device *dev, 138 + int drm_enc_mode, 147 139 struct msm_display_info *disp_info); 148 140 149 141 /**
+13 -15
drivers/gpu/drm/msm/disp/dpu1/dpu_encoder_phys.h
··· 63 63 /** 64 64 * struct dpu_encoder_phys_ops - Interface the physical encoders provide to 65 65 * the containing virtual encoder. 66 - * @late_register: DRM Call. Add Userspace interfaces, debugfs. 67 66 * @prepare_commit: MSM Atomic Call, start of atomic commit sequence 68 67 * @is_master: Whether this phys_enc is the current master 69 68 * encoder. Can be switched at enable time. Based ··· 92 93 */ 93 94 94 95 struct dpu_encoder_phys_ops { 95 - int (*late_register)(struct dpu_encoder_phys *encoder, 96 - struct dentry *debugfs_root); 97 96 void (*prepare_commit)(struct dpu_encoder_phys *encoder); 98 97 bool (*is_master)(struct dpu_encoder_phys *encoder); 99 98 void (*atomic_mode_set)(struct dpu_encoder_phys *encoder, ··· 126 129 /** 127 130 * enum dpu_intr_idx - dpu encoder interrupt index 128 131 * @INTR_IDX_VSYNC: Vsync interrupt for video mode panel 129 - * @INTR_IDX_PINGPONG: Pingpong done unterrupt for cmd mode panel 130 - * @INTR_IDX_UNDERRUN: Underrun unterrupt for video and cmd mode panel 131 - * @INTR_IDX_RDPTR: Readpointer done unterrupt for cmd mode panel 132 - * @INTR_IDX_WB_DONE: Writeback fone interrupt for virtual connector 132 + * @INTR_IDX_PINGPONG: Pingpong done interrupt for cmd mode panel 133 + * @INTR_IDX_UNDERRUN: Underrun interrupt for video and cmd mode panel 134 + * @INTR_IDX_RDPTR: Readpointer done interrupt for cmd mode panel 135 + * @INTR_IDX_WB_DONE: Writeback done interrupt for virtual connector 133 136 */ 134 137 enum dpu_intr_idx { 135 138 INTR_IDX_VSYNC, ··· 158 161 * @enabled: Whether the encoder has enabled and running a mode 159 162 * @split_role: Role to play in a split-panel configuration 160 163 * @intf_mode: Interface mode 161 - * @intf_idx: Interface index on dpu hardware 162 - * @wb_idx: Writeback index on dpu hardware 163 164 * @enc_spinlock: Virtual-Encoder-Wide Spin Lock for IRQ purposes 164 165 * @enable_state: Enable state tracking 165 166 * @vblank_refcount: Reference count of vblank request ··· 171 176 * pending. 172 177 * @pending_kickoff_wq: Wait queue for blocking until kickoff completes 173 178 * @irq: IRQ indices 179 + * @has_intf_te: Interface TE configuration support 174 180 */ 175 181 struct dpu_encoder_phys { 176 182 struct drm_encoder *parent; ··· 185 189 struct drm_display_mode cached_mode; 186 190 enum dpu_enc_split_role split_role; 187 191 enum dpu_intf_mode intf_mode; 188 - enum dpu_intf intf_idx; 189 - enum dpu_wb wb_idx; 190 192 spinlock_t *enc_spinlock; 191 193 enum dpu_enc_enable_state enable_state; 192 194 atomic_t vblank_refcount; ··· 194 200 atomic_t pending_kickoff_cnt; 195 201 wait_queue_head_t pending_kickoff_wq; 196 202 int irq[INTR_IDX_MAX]; 203 + bool has_intf_te; 197 204 }; 198 205 199 206 static inline int dpu_encoder_phys_inc_pending(struct dpu_encoder_phys *phys) ··· 251 256 * @parent: Pointer to the containing virtual encoder 252 257 * @parent_ops: Callbacks exposed by the parent to the phys_enc 253 258 * @split_role: Role to play in a split-panel configuration 254 - * @intf_idx: Interface index this phys_enc will control 255 - * @wb_idx: Writeback index this phys_enc will control 259 + * @hw_intf: Hardware interface to the intf registers 260 + * @hw_wb: Hardware interface to the wb registers 256 261 * @enc_spinlock: Virtual-Encoder-Wide Spin Lock for IRQ purposes 257 262 */ 258 263 struct dpu_enc_phys_init_params { 259 264 struct dpu_kms *dpu_kms; 260 265 struct drm_encoder *parent; 261 266 enum dpu_enc_split_role split_role; 262 - enum dpu_intf intf_idx; 263 - enum dpu_wb wb_idx; 267 + struct dpu_hw_intf *hw_intf; 268 + struct dpu_hw_wb *hw_wb; 264 269 spinlock_t *enc_spinlock; 265 270 }; 266 271 ··· 399 404 void dpu_encoder_frame_done_callback( 400 405 struct drm_encoder *drm_enc, 401 406 struct dpu_encoder_phys *ready_phys, u32 event); 407 + 408 + void dpu_encoder_phys_init(struct dpu_encoder_phys *phys, 409 + struct dpu_enc_phys_init_params *p); 402 410 403 411 #endif /* __dpu_encoder_phys_H__ */
+124 -137
drivers/gpu/drm/msm/disp/dpu1/dpu_encoder_phys_cmd.c
··· 16 16 #define DPU_DEBUG_CMDENC(e, fmt, ...) DPU_DEBUG("enc%d intf%d " fmt, \ 17 17 (e) && (e)->base.parent ? \ 18 18 (e)->base.parent->base.id : -1, \ 19 - (e) ? (e)->base.intf_idx - INTF_0 : -1, ##__VA_ARGS__) 19 + (e) ? (e)->base.hw_intf->idx - INTF_0 : -1, ##__VA_ARGS__) 20 20 21 21 #define DPU_ERROR_CMDENC(e, fmt, ...) DPU_ERROR("enc%d intf%d " fmt, \ 22 22 (e) && (e)->base.parent ? \ 23 23 (e)->base.parent->base.id : -1, \ 24 - (e) ? (e)->base.intf_idx - INTF_0 : -1, ##__VA_ARGS__) 24 + (e) ? (e)->base.hw_intf->idx - INTF_0 : -1, ##__VA_ARGS__) 25 25 26 26 #define to_dpu_encoder_phys_cmd(x) \ 27 27 container_of(x, struct dpu_encoder_phys_cmd, base) ··· 35 35 */ 36 36 #define DEFAULT_TEARCHECK_SYNC_THRESH_START 4 37 37 #define DEFAULT_TEARCHECK_SYNC_THRESH_CONTINUE 4 38 - 39 - #define DPU_ENC_WR_PTR_START_TIMEOUT_US 20000 40 - 41 - #define DPU_ENC_MAX_POLL_TIMEOUT_US 2000 42 38 43 39 static void dpu_encoder_phys_cmd_enable_te(struct dpu_encoder_phys *phys_enc); 44 40 ··· 55 59 if (!ctl->ops.setup_intf_cfg) 56 60 return; 57 61 58 - intf_cfg.intf = phys_enc->intf_idx; 62 + intf_cfg.intf = phys_enc->hw_intf->idx; 59 63 intf_cfg.intf_mode_sel = DPU_CTL_MODE_SEL_CMD; 60 64 intf_cfg.stream_sel = cmd_enc->stream_sel; 61 65 intf_cfg.mode_3d = dpu_encoder_helper_get_3d_blend_mode(phys_enc); ··· 66 70 if (test_bit(DPU_CTL_ACTIVE_CFG, &ctl->caps->features) && phys_enc->hw_intf->ops.bind_pingpong_blk) 67 71 phys_enc->hw_intf->ops.bind_pingpong_blk( 68 72 phys_enc->hw_intf, 69 - true, 70 73 phys_enc->hw_pp->idx); 74 + 75 + if (intf_cfg.dsc != 0 && phys_enc->hw_intf->ops.enable_compression) 76 + phys_enc->hw_intf->ops.enable_compression(phys_enc->hw_intf); 71 77 } 72 78 73 79 static void dpu_encoder_phys_cmd_pp_tx_done_irq(void *arg, int irq_idx) ··· 99 101 DPU_ATRACE_END("pp_done_irq"); 100 102 } 101 103 102 - static void dpu_encoder_phys_cmd_pp_rd_ptr_irq(void *arg, int irq_idx) 104 + static void dpu_encoder_phys_cmd_te_rd_ptr_irq(void *arg, int irq_idx) 103 105 { 104 106 struct dpu_encoder_phys *phys_enc = arg; 105 107 struct dpu_encoder_phys_cmd *cmd_enc; 106 108 107 - if (!phys_enc->hw_pp) 108 - return; 109 + if (phys_enc->has_intf_te) { 110 + if (!phys_enc->hw_intf) 111 + return; 112 + } else { 113 + if (!phys_enc->hw_pp) 114 + return; 115 + } 109 116 110 117 DPU_ATRACE_BEGIN("rd_ptr_irq"); 111 118 cmd_enc = to_dpu_encoder_phys_cmd(phys_enc); ··· 151 148 152 149 phys_enc->irq[INTR_IDX_PINGPONG] = phys_enc->hw_pp->caps->intr_done; 153 150 154 - phys_enc->irq[INTR_IDX_RDPTR] = phys_enc->hw_pp->caps->intr_rdptr; 151 + if (phys_enc->has_intf_te) 152 + phys_enc->irq[INTR_IDX_RDPTR] = phys_enc->hw_intf->cap->intr_tear_rd_ptr; 153 + else 154 + phys_enc->irq[INTR_IDX_RDPTR] = phys_enc->hw_pp->caps->intr_rdptr; 155 155 156 156 phys_enc->irq[INTR_IDX_UNDERRUN] = phys_enc->hw_intf->cap->intr_underrun; 157 157 } ··· 265 259 if (enable && atomic_inc_return(&phys_enc->vblank_refcount) == 1) 266 260 ret = dpu_core_irq_register_callback(phys_enc->dpu_kms, 267 261 phys_enc->irq[INTR_IDX_RDPTR], 268 - dpu_encoder_phys_cmd_pp_rd_ptr_irq, 262 + dpu_encoder_phys_cmd_te_rd_ptr_irq, 269 263 phys_enc); 270 264 else if (!enable && atomic_dec_return(&phys_enc->vblank_refcount) == 0) 271 265 ret = dpu_core_irq_unregister_callback(phys_enc->dpu_kms, ··· 326 320 struct dpu_hw_tear_check tc_cfg = { 0 }; 327 321 struct drm_display_mode *mode; 328 322 bool tc_enable = true; 329 - u32 vsync_hz; 323 + unsigned long vsync_hz; 330 324 struct dpu_kms *dpu_kms; 331 325 332 - if (!phys_enc->hw_pp) { 333 - DPU_ERROR("invalid encoder\n"); 334 - return; 326 + if (phys_enc->has_intf_te) { 327 + if (!phys_enc->hw_intf || 328 + !phys_enc->hw_intf->ops.enable_tearcheck) { 329 + DPU_DEBUG_CMDENC(cmd_enc, "tearcheck not supported\n"); 330 + return; 331 + } 332 + 333 + DPU_DEBUG_CMDENC(cmd_enc, ""); 334 + } else { 335 + if (!phys_enc->hw_pp || 336 + !phys_enc->hw_pp->ops.enable_tearcheck) { 337 + DPU_DEBUG_CMDENC(cmd_enc, "tearcheck not supported\n"); 338 + return; 339 + } 340 + 341 + DPU_DEBUG_CMDENC(cmd_enc, "pp %d\n", phys_enc->hw_pp->idx - PINGPONG_0); 335 342 } 343 + 336 344 mode = &phys_enc->cached_mode; 337 - 338 - DPU_DEBUG_CMDENC(cmd_enc, "pp %d\n", phys_enc->hw_pp->idx - PINGPONG_0); 339 - 340 - if (!phys_enc->hw_pp->ops.setup_tearcheck || 341 - !phys_enc->hw_pp->ops.enable_tearcheck) { 342 - DPU_DEBUG_CMDENC(cmd_enc, "tearcheck not supported\n"); 343 - return; 344 - } 345 345 346 346 dpu_kms = phys_enc->dpu_kms; 347 347 ··· 361 349 * frequency divided by the no. of rows (lines) in the LCDpanel. 362 350 */ 363 351 vsync_hz = dpu_kms_get_clk_rate(dpu_kms, "vsync"); 364 - if (vsync_hz <= 0) { 365 - DPU_DEBUG_CMDENC(cmd_enc, "invalid - vsync_hz %u\n", 366 - vsync_hz); 352 + if (!vsync_hz) { 353 + DPU_DEBUG_CMDENC(cmd_enc, "invalid - no vsync clock\n"); 367 354 return; 368 355 } 369 356 ··· 382 371 tc_cfg.rd_ptr_irq = mode->vdisplay + 1; 383 372 384 373 DPU_DEBUG_CMDENC(cmd_enc, 385 - "tc %d vsync_clk_speed_hz %u vtotal %u vrefresh %u\n", 386 - phys_enc->hw_pp->idx - PINGPONG_0, vsync_hz, 387 - mode->vtotal, drm_mode_vrefresh(mode)); 374 + "tc vsync_clk_speed_hz %lu vtotal %u vrefresh %u\n", 375 + vsync_hz, mode->vtotal, drm_mode_vrefresh(mode)); 388 376 DPU_DEBUG_CMDENC(cmd_enc, 389 - "tc %d enable %u start_pos %u rd_ptr_irq %u\n", 390 - phys_enc->hw_pp->idx - PINGPONG_0, tc_enable, tc_cfg.start_pos, 391 - tc_cfg.rd_ptr_irq); 377 + "tc enable %u start_pos %u rd_ptr_irq %u\n", 378 + tc_enable, tc_cfg.start_pos, tc_cfg.rd_ptr_irq); 392 379 DPU_DEBUG_CMDENC(cmd_enc, 393 - "tc %d hw_vsync_mode %u vsync_count %u vsync_init_val %u\n", 394 - phys_enc->hw_pp->idx - PINGPONG_0, tc_cfg.hw_vsync_mode, 395 - tc_cfg.vsync_count, tc_cfg.vsync_init_val); 380 + "tc hw_vsync_mode %u vsync_count %u vsync_init_val %u\n", 381 + tc_cfg.hw_vsync_mode, tc_cfg.vsync_count, 382 + tc_cfg.vsync_init_val); 396 383 DPU_DEBUG_CMDENC(cmd_enc, 397 - "tc %d cfgheight %u thresh_start %u thresh_cont %u\n", 398 - phys_enc->hw_pp->idx - PINGPONG_0, tc_cfg.sync_cfg_height, 399 - tc_cfg.sync_threshold_start, tc_cfg.sync_threshold_continue); 384 + "tc cfgheight %u thresh_start %u thresh_cont %u\n", 385 + tc_cfg.sync_cfg_height, tc_cfg.sync_threshold_start, 386 + tc_cfg.sync_threshold_continue); 400 387 401 - phys_enc->hw_pp->ops.setup_tearcheck(phys_enc->hw_pp, &tc_cfg); 402 - phys_enc->hw_pp->ops.enable_tearcheck(phys_enc->hw_pp, tc_enable); 388 + if (phys_enc->has_intf_te) 389 + phys_enc->hw_intf->ops.enable_tearcheck(phys_enc->hw_intf, &tc_cfg); 390 + else 391 + phys_enc->hw_pp->ops.enable_tearcheck(phys_enc->hw_pp, &tc_cfg); 403 392 } 404 393 405 394 static void _dpu_encoder_phys_cmd_pingpong_config( ··· 441 430 return; 442 431 } 443 432 444 - dpu_encoder_helper_split_config(phys_enc, phys_enc->intf_idx); 433 + dpu_encoder_helper_split_config(phys_enc, phys_enc->hw_intf->idx); 445 434 446 435 _dpu_encoder_phys_cmd_pingpong_config(phys_enc); 447 436 ··· 449 438 return; 450 439 451 440 ctl = phys_enc->hw_ctl; 452 - ctl->ops.update_pending_flush_intf(ctl, phys_enc->intf_idx); 441 + ctl->ops.update_pending_flush_intf(ctl, phys_enc->hw_intf->idx); 453 442 } 454 443 455 444 static void dpu_encoder_phys_cmd_enable(struct dpu_encoder_phys *phys_enc) ··· 476 465 static void _dpu_encoder_phys_cmd_connect_te( 477 466 struct dpu_encoder_phys *phys_enc, bool enable) 478 467 { 479 - if (!phys_enc->hw_pp || !phys_enc->hw_pp->ops.connect_external_te) 480 - return; 468 + if (phys_enc->has_intf_te) { 469 + if (!phys_enc->hw_intf || !phys_enc->hw_intf->ops.connect_external_te) 470 + return; 481 471 482 - trace_dpu_enc_phys_cmd_connect_te(DRMID(phys_enc->parent), enable); 483 - phys_enc->hw_pp->ops.connect_external_te(phys_enc->hw_pp, enable); 472 + trace_dpu_enc_phys_cmd_connect_te(DRMID(phys_enc->parent), enable); 473 + phys_enc->hw_intf->ops.connect_external_te(phys_enc->hw_intf, enable); 474 + } else { 475 + if (!phys_enc->hw_pp || !phys_enc->hw_pp->ops.connect_external_te) 476 + return; 477 + 478 + trace_dpu_enc_phys_cmd_connect_te(DRMID(phys_enc->parent), enable); 479 + phys_enc->hw_pp->ops.connect_external_te(phys_enc->hw_pp, enable); 480 + } 484 481 } 485 482 486 483 static void dpu_encoder_phys_cmd_prepare_idle_pc( ··· 501 482 struct dpu_encoder_phys *phys_enc) 502 483 { 503 484 struct dpu_hw_pingpong *hw_pp; 504 - 505 - if (!phys_enc->hw_pp) 506 - return -EINVAL; 485 + struct dpu_hw_intf *hw_intf; 507 486 508 487 if (!dpu_encoder_phys_cmd_is_master(phys_enc)) 509 488 return -EINVAL; 510 489 511 - hw_pp = phys_enc->hw_pp; 512 - if (!hw_pp->ops.get_line_count) 513 - return -EINVAL; 490 + if (phys_enc->has_intf_te) { 491 + hw_intf = phys_enc->hw_intf; 492 + if (!hw_intf || !hw_intf->ops.get_line_count) 493 + return -EINVAL; 494 + return hw_intf->ops.get_line_count(hw_intf); 495 + } 514 496 497 + hw_pp = phys_enc->hw_pp; 498 + if (!hw_pp || !hw_pp->ops.get_line_count) 499 + return -EINVAL; 515 500 return hw_pp->ops.get_line_count(hw_pp); 516 501 } 517 502 ··· 525 502 to_dpu_encoder_phys_cmd(phys_enc); 526 503 struct dpu_hw_ctl *ctl; 527 504 528 - if (!phys_enc->hw_pp) { 529 - DPU_ERROR("invalid encoder\n"); 530 - return; 531 - } 532 - DRM_DEBUG_KMS("id:%u pp:%d state:%d\n", DRMID(phys_enc->parent), 533 - phys_enc->hw_pp->idx - PINGPONG_0, 534 - phys_enc->enable_state); 535 - 536 505 if (phys_enc->enable_state == DPU_ENC_DISABLED) { 537 506 DPU_ERROR_CMDENC(cmd_enc, "already disabled\n"); 538 507 return; 539 508 } 540 509 541 - if (phys_enc->hw_pp->ops.enable_tearcheck) 542 - phys_enc->hw_pp->ops.enable_tearcheck(phys_enc->hw_pp, false); 510 + if (phys_enc->has_intf_te) { 511 + DRM_DEBUG_KMS("id:%u intf:%d state:%d\n", DRMID(phys_enc->parent), 512 + phys_enc->hw_intf->idx - INTF_0, 513 + phys_enc->enable_state); 514 + 515 + if (phys_enc->hw_intf->ops.disable_tearcheck) 516 + phys_enc->hw_intf->ops.disable_tearcheck(phys_enc->hw_intf); 517 + } else { 518 + if (!phys_enc->hw_pp) { 519 + DPU_ERROR("invalid encoder\n"); 520 + return; 521 + } 522 + 523 + DRM_DEBUG_KMS("id:%u pp:%d state:%d\n", DRMID(phys_enc->parent), 524 + phys_enc->hw_pp->idx - PINGPONG_0, 525 + phys_enc->enable_state); 526 + 527 + if (phys_enc->hw_pp->ops.disable_tearcheck) 528 + phys_enc->hw_pp->ops.disable_tearcheck(phys_enc->hw_pp); 529 + } 543 530 544 531 if (phys_enc->hw_intf->ops.bind_pingpong_blk) { 545 532 phys_enc->hw_intf->ops.bind_pingpong_blk( 546 533 phys_enc->hw_intf, 547 - false, 548 - phys_enc->hw_pp->idx); 534 + PINGPONG_NONE); 549 535 550 536 ctl = phys_enc->hw_ctl; 551 - ctl->ops.update_pending_flush_intf(ctl, phys_enc->intf_idx); 537 + ctl->ops.update_pending_flush_intf(ctl, phys_enc->hw_intf->idx); 552 538 } 553 539 554 540 phys_enc->enable_state = DPU_ENC_DISABLED; ··· 606 574 atomic_read(&phys_enc->pending_kickoff_cnt)); 607 575 } 608 576 609 - static bool dpu_encoder_phys_cmd_is_ongoing_pptx( 610 - struct dpu_encoder_phys *phys_enc) 611 - { 612 - struct dpu_hw_pp_vsync_info info; 613 - 614 - if (!phys_enc) 615 - return false; 616 - 617 - phys_enc->hw_pp->ops.get_vsync_info(phys_enc->hw_pp, &info); 618 - if (info.wr_ptr_line_count > 0 && 619 - info.wr_ptr_line_count < phys_enc->cached_mode.vdisplay) 620 - return true; 621 - 622 - return false; 623 - } 624 - 625 577 static void dpu_encoder_phys_cmd_enable_te(struct dpu_encoder_phys *phys_enc) 626 578 { 627 - struct dpu_encoder_phys_cmd *cmd_enc = 628 - to_dpu_encoder_phys_cmd(phys_enc); 629 - int trial = 0; 630 - 631 579 if (!phys_enc) 632 - return; 633 - if (!phys_enc->hw_pp) 634 580 return; 635 581 if (!dpu_encoder_phys_cmd_is_master(phys_enc)) 636 582 return; 637 583 638 - /* If autorefresh is already disabled, we have nothing to do */ 639 - if (!phys_enc->hw_pp->ops.get_autorefresh(phys_enc->hw_pp, NULL)) 640 - return; 584 + if (phys_enc->has_intf_te) { 585 + if (!phys_enc->hw_intf->ops.disable_autorefresh) 586 + return; 641 587 642 - /* 643 - * If autorefresh is enabled, disable it and make sure it is safe to 644 - * proceed with current frame commit/push. Sequence fallowed is, 645 - * 1. Disable TE 646 - * 2. Disable autorefresh config 647 - * 4. Poll for frame transfer ongoing to be false 648 - * 5. Enable TE back 649 - */ 650 - _dpu_encoder_phys_cmd_connect_te(phys_enc, false); 651 - phys_enc->hw_pp->ops.setup_autorefresh(phys_enc->hw_pp, 0, false); 588 + phys_enc->hw_intf->ops.disable_autorefresh( 589 + phys_enc->hw_intf, 590 + DRMID(phys_enc->parent), 591 + phys_enc->cached_mode.vdisplay); 592 + } else { 593 + if (!phys_enc->hw_pp || 594 + !phys_enc->hw_pp->ops.disable_autorefresh) 595 + return; 652 596 653 - do { 654 - udelay(DPU_ENC_MAX_POLL_TIMEOUT_US); 655 - if ((trial * DPU_ENC_MAX_POLL_TIMEOUT_US) 656 - > (KICKOFF_TIMEOUT_MS * USEC_PER_MSEC)) { 657 - DPU_ERROR_CMDENC(cmd_enc, 658 - "disable autorefresh failed\n"); 659 - break; 660 - } 661 - 662 - trial++; 663 - } while (dpu_encoder_phys_cmd_is_ongoing_pptx(phys_enc)); 664 - 665 - _dpu_encoder_phys_cmd_connect_te(phys_enc, true); 666 - 667 - DPU_DEBUG_CMDENC(to_dpu_encoder_phys_cmd(phys_enc), 668 - "disabled autorefresh\n"); 597 + phys_enc->hw_pp->ops.disable_autorefresh( 598 + phys_enc->hw_pp, 599 + DRMID(phys_enc->parent), 600 + phys_enc->cached_mode.vdisplay); 601 + } 669 602 } 670 603 671 604 static int _dpu_encoder_phys_cmd_wait_for_ctl_start( ··· 667 670 if (rc) { 668 671 DRM_ERROR("failed wait_for_idle: id:%u ret:%d intf:%d\n", 669 672 DRMID(phys_enc->parent), rc, 670 - phys_enc->intf_idx - INTF_0); 673 + phys_enc->hw_intf->idx - INTF_0); 671 674 } 672 675 673 676 return rc; ··· 707 710 708 711 rc = dpu_encoder_helper_wait_for_irq(phys_enc, 709 712 phys_enc->irq[INTR_IDX_RDPTR], 710 - dpu_encoder_phys_cmd_pp_rd_ptr_irq, 713 + dpu_encoder_phys_cmd_te_rd_ptr_irq, 711 714 &wait_info); 712 715 713 716 return rc; ··· 756 759 { 757 760 struct dpu_encoder_phys *phys_enc = NULL; 758 761 struct dpu_encoder_phys_cmd *cmd_enc = NULL; 759 - int i, ret = 0; 760 762 761 - DPU_DEBUG("intf %d\n", p->intf_idx - INTF_0); 763 + DPU_DEBUG("intf\n"); 762 764 763 765 cmd_enc = kzalloc(sizeof(*cmd_enc), GFP_KERNEL); 764 766 if (!cmd_enc) { 765 - ret = -ENOMEM; 766 767 DPU_ERROR("failed to allocate\n"); 767 - return ERR_PTR(ret); 768 + return ERR_PTR(-ENOMEM); 768 769 } 769 770 phys_enc = &cmd_enc->base; 770 - phys_enc->hw_mdptop = p->dpu_kms->hw_mdp; 771 - phys_enc->intf_idx = p->intf_idx; 771 + 772 + dpu_encoder_phys_init(phys_enc, p); 772 773 773 774 dpu_encoder_phys_cmd_init_ops(&phys_enc->ops); 774 - phys_enc->parent = p->parent; 775 - phys_enc->dpu_kms = p->dpu_kms; 776 - phys_enc->split_role = p->split_role; 777 775 phys_enc->intf_mode = INTF_MODE_CMD; 778 - phys_enc->enc_spinlock = p->enc_spinlock; 779 776 cmd_enc->stream_sel = 0; 780 - phys_enc->enable_state = DPU_ENC_DISABLED; 781 - for (i = 0; i < ARRAY_SIZE(phys_enc->irq); i++) 782 - phys_enc->irq[i] = -EINVAL; 783 777 784 - atomic_set(&phys_enc->vblank_refcount, 0); 785 - atomic_set(&phys_enc->pending_kickoff_cnt, 0); 786 - atomic_set(&phys_enc->pending_ctlstart_cnt, 0); 778 + phys_enc->has_intf_te = test_bit(DPU_INTF_TE, 779 + &phys_enc->hw_intf->cap->features); 780 + 787 781 atomic_set(&cmd_enc->pending_vblank_cnt, 0); 788 - init_waitqueue_head(&phys_enc->pending_kickoff_wq); 789 782 init_waitqueue_head(&cmd_enc->pending_vblank_wq); 790 783 791 784 DPU_DEBUG_CMDENC(cmd_enc, "created\n");
+3 -17
drivers/gpu/drm/msm/disp/dpu1/dpu_encoder_phys_vid.c
··· 287 287 if (phys_enc->hw_intf->ops.bind_pingpong_blk) 288 288 phys_enc->hw_intf->ops.bind_pingpong_blk( 289 289 phys_enc->hw_intf, 290 - true, 291 290 phys_enc->hw_pp->idx); 292 291 293 292 if (phys_enc->hw_pp->merge_3d) ··· 698 699 struct dpu_enc_phys_init_params *p) 699 700 { 700 701 struct dpu_encoder_phys *phys_enc = NULL; 701 - int i; 702 702 703 703 if (!p) { 704 704 DPU_ERROR("failed to create encoder due to invalid parameter\n"); ··· 710 712 return ERR_PTR(-ENOMEM); 711 713 } 712 714 713 - phys_enc->hw_mdptop = p->dpu_kms->hw_mdp; 714 - phys_enc->intf_idx = p->intf_idx; 715 - 716 715 DPU_DEBUG_VIDENC(phys_enc, "\n"); 717 716 717 + dpu_encoder_phys_init(phys_enc, p); 718 + 718 719 dpu_encoder_phys_vid_init_ops(&phys_enc->ops); 719 - phys_enc->parent = p->parent; 720 - phys_enc->dpu_kms = p->dpu_kms; 721 - phys_enc->split_role = p->split_role; 722 720 phys_enc->intf_mode = INTF_MODE_VIDEO; 723 - phys_enc->enc_spinlock = p->enc_spinlock; 724 - for (i = 0; i < ARRAY_SIZE(phys_enc->irq); i++) 725 - phys_enc->irq[i] = -EINVAL; 726 721 727 - atomic_set(&phys_enc->vblank_refcount, 0); 728 - atomic_set(&phys_enc->pending_kickoff_cnt, 0); 729 - init_waitqueue_head(&phys_enc->pending_kickoff_wq); 730 - phys_enc->enable_state = DPU_ENC_DISABLED; 731 - 732 - DPU_DEBUG_VIDENC(phys_enc, "created intf idx:%d\n", p->intf_idx); 722 + DPU_DEBUG_VIDENC(phys_enc, "created intf idx:%d\n", p->hw_intf->idx); 733 723 734 724 return phys_enc; 735 725 }
+13 -43
drivers/gpu/drm/msm/disp/dpu1/dpu_encoder_phys_wb.c
··· 102 102 static void dpu_encoder_phys_wb_set_qos(struct dpu_encoder_phys *phys_enc) 103 103 { 104 104 struct dpu_hw_wb *hw_wb; 105 - struct dpu_hw_wb_qos_cfg qos_cfg; 105 + struct dpu_hw_qos_cfg qos_cfg; 106 106 const struct dpu_mdss_cfg *catalog; 107 107 const struct dpu_qos_lut_tbl *qos_lut_tb; 108 108 ··· 115 115 116 116 hw_wb = phys_enc->hw_wb; 117 117 118 - memset(&qos_cfg, 0, sizeof(struct dpu_hw_wb_qos_cfg)); 118 + memset(&qos_cfg, 0, sizeof(struct dpu_hw_qos_cfg)); 119 119 qos_cfg.danger_safe_en = true; 120 120 qos_cfg.danger_lut = 121 121 catalog->perf->danger_lut_tbl[DPU_QOS_LUT_USAGE_NRT]; ··· 140 140 struct dpu_encoder_phys_wb *wb_enc = to_dpu_encoder_phys_wb(phys_enc); 141 141 struct dpu_hw_wb *hw_wb; 142 142 struct dpu_hw_wb_cfg *wb_cfg; 143 - struct dpu_hw_cdp_cfg cdp_cfg; 144 143 145 144 if (!phys_enc || !phys_enc->dpu_kms || !phys_enc->dpu_kms->catalog) { 146 145 DPU_ERROR("invalid encoder\n"); ··· 162 163 hw_wb->ops.setup_outformat(hw_wb, wb_cfg); 163 164 164 165 if (hw_wb->ops.setup_cdp) { 165 - memset(&cdp_cfg, 0, sizeof(struct dpu_hw_cdp_cfg)); 166 + const struct dpu_perf_cfg *perf = phys_enc->dpu_kms->catalog->perf; 166 167 167 - cdp_cfg.enable = phys_enc->dpu_kms->catalog->perf->cdp_cfg 168 - [DPU_PERF_CDP_USAGE_NRT].wr_enable; 169 - cdp_cfg.ubwc_meta_enable = 170 - DPU_FORMAT_IS_UBWC(wb_cfg->dest.format); 171 - cdp_cfg.tile_amortize_enable = 172 - DPU_FORMAT_IS_UBWC(wb_cfg->dest.format) || 173 - DPU_FORMAT_IS_TILE(wb_cfg->dest.format); 174 - cdp_cfg.preload_ahead = DPU_WB_CDP_PRELOAD_AHEAD_64; 175 - 176 - hw_wb->ops.setup_cdp(hw_wb, &cdp_cfg); 168 + hw_wb->ops.setup_cdp(hw_wb, wb_cfg->dest.format, 169 + perf->cdp_cfg[DPU_PERF_CDP_USAGE_NRT].wr_enable); 177 170 } 178 171 179 172 if (hw_wb->ops.setup_outaddress) ··· 210 219 211 220 /* setup which pp blk will connect to this wb */ 212 221 if (hw_pp && phys_enc->hw_wb->ops.bind_pingpong_blk) 213 - phys_enc->hw_wb->ops.bind_pingpong_blk(phys_enc->hw_wb, true, 222 + phys_enc->hw_wb->ops.bind_pingpong_blk(phys_enc->hw_wb, 214 223 phys_enc->hw_pp->idx); 215 224 216 225 phys_enc->hw_ctl->ops.setup_intf_cfg(phys_enc->hw_ctl, &intf_cfg); ··· 240 249 const struct drm_display_mode *mode = &crtc_state->mode; 241 250 242 251 DPU_DEBUG("[atomic_check:%d, \"%s\",%d,%d]\n", 243 - phys_enc->wb_idx, mode->name, mode->hdisplay, mode->vdisplay); 252 + phys_enc->hw_wb->idx, mode->name, mode->hdisplay, mode->vdisplay); 244 253 245 254 if (!conn_state || !conn_state->connector) { 246 255 DPU_ERROR("invalid connector state\n"); ··· 561 570 if (!phys_enc) 562 571 return; 563 572 564 - DPU_DEBUG("[wb:%d]\n", phys_enc->wb_idx - WB_0); 573 + DPU_DEBUG("[wb:%d]\n", phys_enc->hw_wb->idx - WB_0); 565 574 566 575 kfree(phys_enc); 567 576 } ··· 684 693 { 685 694 struct dpu_encoder_phys *phys_enc = NULL; 686 695 struct dpu_encoder_phys_wb *wb_enc = NULL; 687 - int ret = 0; 688 - int i; 689 696 690 697 DPU_DEBUG("\n"); 691 698 692 699 if (!p || !p->parent) { 693 700 DPU_ERROR("invalid params\n"); 694 - ret = -EINVAL; 695 - goto fail_alloc; 701 + return ERR_PTR(-EINVAL); 696 702 } 697 703 698 704 wb_enc = kzalloc(sizeof(*wb_enc), GFP_KERNEL); 699 705 if (!wb_enc) { 700 706 DPU_ERROR("failed to allocate wb phys_enc enc\n"); 701 - ret = -ENOMEM; 702 - goto fail_alloc; 707 + return ERR_PTR(-ENOMEM); 703 708 } 704 709 705 710 phys_enc = &wb_enc->base; 706 - phys_enc->hw_mdptop = p->dpu_kms->hw_mdp; 707 - phys_enc->wb_idx = p->wb_idx; 711 + 712 + dpu_encoder_phys_init(phys_enc, p); 708 713 709 714 dpu_encoder_phys_wb_init_ops(&phys_enc->ops); 710 - phys_enc->parent = p->parent; 711 - phys_enc->dpu_kms = p->dpu_kms; 712 - phys_enc->split_role = p->split_role; 713 715 phys_enc->intf_mode = INTF_MODE_WB_LINE; 714 - phys_enc->wb_idx = p->wb_idx; 715 - phys_enc->enc_spinlock = p->enc_spinlock; 716 716 717 717 atomic_set(&wb_enc->wbirq_refcount, 0); 718 718 719 - for (i = 0; i < ARRAY_SIZE(phys_enc->irq); i++) 720 - phys_enc->irq[i] = -EINVAL; 721 - 722 - atomic_set(&phys_enc->pending_kickoff_cnt, 0); 723 - atomic_set(&phys_enc->vblank_refcount, 0); 724 719 wb_enc->wb_done_timeout_cnt = 0; 725 720 726 - init_waitqueue_head(&phys_enc->pending_kickoff_wq); 727 - phys_enc->enable_state = DPU_ENC_DISABLED; 728 - 729 - DPU_DEBUG("Created dpu_encoder_phys for wb %d\n", 730 - phys_enc->wb_idx); 721 + DPU_DEBUG("Created dpu_encoder_phys for wb %d\n", phys_enc->hw_wb->idx); 731 722 732 723 return phys_enc; 733 - 734 - fail_alloc: 735 - return ERR_PTR(ret); 736 724 }
+60 -81
drivers/gpu/drm/msm/disp/dpu1/dpu_hw_catalog.c
··· 1 1 // SPDX-License-Identifier: GPL-2.0-only 2 2 /* Copyright (c) 2015-2018, The Linux Foundation. All rights reserved. 3 - * Copyright (c) 2022. Qualcomm Innovation Center, Inc. All rights reserved. 3 + * Copyright (c) 2022-2023, Qualcomm Innovation Center, Inc. All rights reserved. 4 4 */ 5 5 6 6 #define pr_fmt(fmt) "[drm:%s:%d] " fmt, __func__, __LINE__ ··· 13 13 #include "dpu_kms.h" 14 14 15 15 #define VIG_BASE_MASK \ 16 - (BIT(DPU_SSPP_SRC) | BIT(DPU_SSPP_QOS) |\ 16 + (BIT(DPU_SSPP_QOS) |\ 17 17 BIT(DPU_SSPP_CDP) |\ 18 18 BIT(DPU_SSPP_TS_PREFILL) | BIT(DPU_SSPP_EXCL_RECT)) 19 19 ··· 39 39 #define VIG_QCM2290_MASK (VIG_BASE_MASK | BIT(DPU_SSPP_QOS_8LVL)) 40 40 41 41 #define DMA_MSM8998_MASK \ 42 - (BIT(DPU_SSPP_SRC) | BIT(DPU_SSPP_QOS) |\ 42 + (BIT(DPU_SSPP_QOS) |\ 43 43 BIT(DPU_SSPP_TS_PREFILL) | BIT(DPU_SSPP_TS_PREFILL_REC1) |\ 44 44 BIT(DPU_SSPP_CDP) | BIT(DPU_SSPP_EXCL_RECT)) 45 45 ··· 50 50 (VIG_SC7280_MASK | BIT(DPU_SSPP_SMART_DMA_V2)) 51 51 52 52 #define DMA_SDM845_MASK \ 53 - (BIT(DPU_SSPP_SRC) | BIT(DPU_SSPP_QOS) | BIT(DPU_SSPP_QOS_8LVL) |\ 53 + (BIT(DPU_SSPP_QOS) | BIT(DPU_SSPP_QOS_8LVL) |\ 54 54 BIT(DPU_SSPP_TS_PREFILL) | BIT(DPU_SSPP_TS_PREFILL_REC1) |\ 55 55 BIT(DPU_SSPP_CDP) | BIT(DPU_SSPP_EXCL_RECT)) 56 56 ··· 75 75 #define MIXER_QCM2290_MASK \ 76 76 (BIT(DPU_DIM_LAYER) | BIT(DPU_MIXER_COMBINED_ALPHA)) 77 77 78 - #define PINGPONG_SDM845_MASK BIT(DPU_PINGPONG_DITHER) 78 + #define PINGPONG_SDM845_MASK \ 79 + (BIT(DPU_PINGPONG_DITHER) | BIT(DPU_PINGPONG_TE) | BIT(DPU_PINGPONG_DSC)) 79 80 80 - #define PINGPONG_SDM845_SPLIT_MASK \ 81 + #define PINGPONG_SDM845_TE2_MASK \ 81 82 (PINGPONG_SDM845_MASK | BIT(DPU_PINGPONG_TE2)) 83 + 84 + #define PINGPONG_SM8150_MASK \ 85 + (BIT(DPU_PINGPONG_DITHER) | BIT(DPU_PINGPONG_DSC)) 82 86 83 87 #define CTL_SC7280_MASK \ 84 88 (BIT(DPU_CTL_ACTIVE_CFG) | \ ··· 95 91 96 92 #define MERGE_3D_SM8150_MASK (0) 97 93 98 - #define DSPP_MSM8998_MASK BIT(DPU_DSPP_PCC) | BIT(DPU_DSPP_GC) 99 - 100 94 #define DSPP_SC7180_MASK BIT(DPU_DSPP_PCC) 101 95 102 96 #define INTF_SDM845_MASK (0) 103 97 104 98 #define INTF_SC7180_MASK \ 105 - (BIT(DPU_INTF_INPUT_CTRL) | BIT(DPU_INTF_TE) | BIT(DPU_INTF_STATUS_SUPPORTED)) 99 + (BIT(DPU_INTF_INPUT_CTRL) | \ 100 + BIT(DPU_INTF_TE) | \ 101 + BIT(DPU_INTF_STATUS_SUPPORTED) | \ 102 + BIT(DPU_DATA_HCTL_EN)) 106 103 107 - #define INTF_SC7280_MASK INTF_SC7180_MASK | BIT(DPU_DATA_HCTL_EN) 104 + #define INTF_SC7280_MASK (INTF_SC7180_MASK | BIT(DPU_INTF_DATA_COMPRESS)) 108 105 109 106 #define WB_SM8250_MASK (BIT(DPU_WB_LINE_MODE) | \ 110 107 BIT(DPU_WB_UBWC) | \ ··· 257 252 .maxdwnscale = MAX_DOWNSCALE_RATIO, \ 258 253 .maxupscale = MAX_UPSCALE_RATIO, \ 259 254 .smart_dma_priority = sdma_pri, \ 260 - .src_blk = {.name = STRCAT("sspp_src_", num), \ 261 - .id = DPU_SSPP_SRC, .base = 0x00, .len = 0x150,}, \ 262 255 .scaler_blk = {.name = STRCAT("sspp_scaler", num), \ 263 256 .id = qseed_ver, \ 264 257 .base = 0xa00, .len = 0xa0,}, \ ··· 275 272 .maxdwnscale = MAX_DOWNSCALE_RATIO, \ 276 273 .maxupscale = MAX_UPSCALE_RATIO, \ 277 274 .smart_dma_priority = sdma_pri, \ 278 - .src_blk = {.name = STRCAT("sspp_src_", num), \ 279 - .id = DPU_SSPP_SRC, .base = 0x00, .len = 0x150,}, \ 280 275 .scaler_blk = {.name = STRCAT("sspp_scaler", num), \ 281 276 .id = qseed_ver, \ 282 277 .base = 0xa00, .len = 0xa0,}, \ ··· 293 292 .maxdwnscale = SSPP_UNITY_SCALE, \ 294 293 .maxupscale = SSPP_UNITY_SCALE, \ 295 294 .smart_dma_priority = sdma_pri, \ 296 - .src_blk = {.name = STRCAT("sspp_src_", num), \ 297 - .id = DPU_SSPP_SRC, .base = 0x00, .len = 0x150,}, \ 298 295 .format_list = plane_formats, \ 299 296 .num_formats = ARRAY_SIZE(plane_formats), \ 300 297 .virt_format_list = plane_formats, \ ··· 374 375 .maxdwnscale = SSPP_UNITY_SCALE, \ 375 376 .maxupscale = SSPP_UNITY_SCALE, \ 376 377 .smart_dma_priority = sdma_pri, \ 377 - .src_blk = {.name = STRCAT("sspp_src_", num), \ 378 - .id = DPU_SSPP_SRC, .base = 0x00, .len = 0x150,}, \ 379 378 .format_list = plane_formats_yuv, \ 380 379 .num_formats = ARRAY_SIZE(plane_formats_yuv), \ 381 380 .virt_format_list = plane_formats, \ ··· 446 449 static const struct dpu_dspp_sub_blks msm8998_dspp_sblk = { 447 450 .pcc = {.id = DPU_DSPP_PCC, .base = 0x1700, 448 451 .len = 0x90, .version = 0x10007}, 449 - .gc = { .id = DPU_DSPP_GC, .base = 0x17c0, 450 - .len = 0x90, .version = 0x10007}, 451 - }; 452 - 453 - static const struct dpu_dspp_sub_blks sc7180_dspp_sblk = { 454 - .pcc = {.id = DPU_DSPP_PCC, .base = 0x1700, 455 - .len = 0x90, .version = 0x10000}, 456 452 }; 457 453 458 454 static const struct dpu_dspp_sub_blks sm8150_dspp_sblk = { ··· 491 501 .intr_done = _done, \ 492 502 .intr_rdptr = _rdptr, \ 493 503 } 494 - #define PP_BLK_TE(_name, _id, _base, _merge_3d, _sblk, _done, _rdptr) \ 504 + #define PP_BLK(_name, _id, _base, _features, _merge_3d, _sblk, _done, _rdptr) \ 495 505 {\ 496 506 .name = _name, .id = _id, \ 497 507 .base = _base, .len = 0xd4, \ 498 - .features = PINGPONG_SDM845_SPLIT_MASK, \ 499 - .merge_3d = _merge_3d, \ 500 - .sblk = &_sblk, \ 501 - .intr_done = _done, \ 502 - .intr_rdptr = _rdptr, \ 503 - } 504 - #define PP_BLK(_name, _id, _base, _merge_3d, _sblk, _done, _rdptr) \ 505 - {\ 506 - .name = _name, .id = _id, \ 507 - .base = _base, .len = 0xd4, \ 508 - .features = PINGPONG_SDM845_MASK, \ 508 + .features = _features, \ 509 509 .merge_3d = _merge_3d, \ 510 510 .sblk = &_sblk, \ 511 511 .intr_done = _done, \ ··· 508 528 #define MERGE_3D_BLK(_name, _id, _base) \ 509 529 {\ 510 530 .name = _name, .id = _id, \ 511 - .base = _base, .len = 0x100, \ 531 + .base = _base, .len = 0x8, \ 512 532 .features = MERGE_3D_SM8150_MASK, \ 513 533 .sblk = NULL \ 514 534 } ··· 516 536 /************************************************************* 517 537 * DSC sub blocks config 518 538 *************************************************************/ 539 + static const struct dpu_dsc_sub_blks dsc_sblk_0 = { 540 + .enc = {.base = 0x100, .len = 0x100}, 541 + .ctl = {.base = 0xF00, .len = 0x10}, 542 + }; 543 + 544 + static const struct dpu_dsc_sub_blks dsc_sblk_1 = { 545 + .enc = {.base = 0x200, .len = 0x100}, 546 + .ctl = {.base = 0xF80, .len = 0x10}, 547 + }; 548 + 519 549 #define DSC_BLK(_name, _id, _base, _features) \ 520 550 {\ 521 551 .name = _name, .id = _id, \ ··· 533 543 .features = _features, \ 534 544 } 535 545 546 + #define DSC_BLK_1_2(_name, _id, _base, _len, _features, _sblk) \ 547 + {\ 548 + .name = _name, .id = _id, \ 549 + .base = _base, .len = _len, \ 550 + .features = BIT(DPU_DSC_HW_REV_1_2) | _features, \ 551 + .sblk = &_sblk, \ 552 + } 553 + 536 554 /************************************************************* 537 555 * INTF sub blocks config 538 556 *************************************************************/ 539 - #define INTF_BLK(_name, _id, _base, _len, _type, _ctrl_id, _progfetch, _features, _reg, _underrun_bit, _vsync_bit) \ 557 + #define INTF_BLK(_name, _id, _base, _len, _type, _ctrl_id, _progfetch, _features, _underrun, _vsync) \ 540 558 {\ 541 559 .name = _name, .id = _id, \ 542 560 .base = _base, .len = _len, \ ··· 552 554 .type = _type, \ 553 555 .controller_id = _ctrl_id, \ 554 556 .prog_fetch_lines_worst_case = _progfetch, \ 555 - .intr_underrun = DPU_IRQ_IDX(_reg, _underrun_bit), \ 556 - .intr_vsync = DPU_IRQ_IDX(_reg, _vsync_bit), \ 557 + .intr_underrun = _underrun, \ 558 + .intr_vsync = _vsync, \ 559 + .intr_tear_rd_ptr = -1, \ 560 + } 561 + 562 + /* DSI Interface sub-block with TEAR registers (since DPU 5.0.0) */ 563 + #define INTF_BLK_DSI_TE(_name, _id, _base, _len, _type, _ctrl_id, _progfetch, _features, _underrun, _vsync, _tear_rd_ptr) \ 564 + {\ 565 + .name = _name, .id = _id, \ 566 + .base = _base, .len = _len, \ 567 + .features = _features, \ 568 + .type = _type, \ 569 + .controller_id = _ctrl_id, \ 570 + .prog_fetch_lines_worst_case = _progfetch, \ 571 + .intr_underrun = _underrun, \ 572 + .intr_vsync = _vsync, \ 573 + .intr_tear_rd_ptr = _tear_rd_ptr, \ 557 574 } 558 575 559 576 /************************************************************* ··· 663 650 }, 664 651 }; 665 652 666 - static const struct dpu_reg_dma_cfg sc8280xp_regdma = { 667 - .base = 0x0, 668 - .version = 0x00020000, 669 - .trigger_sel_off = 0x119c, 670 - .xin_id = 7, 671 - .clk_ctrl = DPU_CLK_CTRL_REG_DMA, 672 - }; 673 - 674 - static const struct dpu_reg_dma_cfg sdm845_regdma = { 675 - .base = 0x0, .version = 0x1, .trigger_sel_off = 0x119c 676 - }; 677 - 678 - static const struct dpu_reg_dma_cfg sm8150_regdma = { 679 - .base = 0x0, .version = 0x00010001, .trigger_sel_off = 0x119c 680 - }; 681 - 682 - static const struct dpu_reg_dma_cfg sm8250_regdma = { 683 - .base = 0x0, 684 - .version = 0x00010002, 685 - .trigger_sel_off = 0x119c, 686 - .xin_id = 7, 687 - .clk_ctrl = DPU_CLK_CTRL_REG_DMA, 688 - }; 689 - 690 - static const struct dpu_reg_dma_cfg sm8350_regdma = { 691 - .base = 0x400, 692 - .version = 0x00020000, 693 - .trigger_sel_off = 0x119c, 694 - .xin_id = 7, 695 - .clk_ctrl = DPU_CLK_CTRL_REG_DMA, 696 - }; 697 - 698 - static const struct dpu_reg_dma_cfg sm8450_regdma = { 699 - .base = 0x0, 700 - .version = 0x00020000, 701 - .trigger_sel_off = 0x119c, 702 - .xin_id = 7, 703 - .clk_ctrl = DPU_CLK_CTRL_REG_DMA, 704 - }; 705 - 706 653 /************************************************************* 707 654 * PERF data config 708 655 *************************************************************/ ··· 705 732 706 733 static const struct dpu_qos_lut_entry sc7180_qos_linear[] = { 707 734 {.fl = 0, .lut = 0x0011222222335777}, 735 + }; 736 + 737 + static const struct dpu_qos_lut_entry sm6350_qos_linear_macrotile[] = { 738 + {.fl = 0, .lut = 0x0011223445566777 }, 708 739 }; 709 740 710 741 static const struct dpu_qos_lut_entry sm8150_qos_linear[] = { ··· 766 789 #include "catalog/dpu_6_0_sm8250.h" 767 790 #include "catalog/dpu_6_2_sc7180.h" 768 791 #include "catalog/dpu_6_3_sm6115.h" 792 + #include "catalog/dpu_6_4_sm6350.h" 769 793 #include "catalog/dpu_6_5_qcm2290.h" 794 + #include "catalog/dpu_6_9_sm6375.h" 770 795 771 796 #include "catalog/dpu_7_0_sm8350.h" 772 797 #include "catalog/dpu_7_2_sc7280.h"
+43 -55
drivers/gpu/drm/msm/disp/dpu1/dpu_hw_catalog.h
··· 1 1 /* SPDX-License-Identifier: GPL-2.0-only */ 2 2 /* 3 - * Copyright (c) 2022. Qualcomm Innovation Center, Inc. All rights reserved. 3 + * Copyright (c) 2022-2023, Qualcomm Innovation Center, Inc. All rights reserved. 4 4 * Copyright (c) 2015-2018, 2020 The Linux Foundation. All rights reserved. 5 5 */ 6 6 ··· 48 48 * @DPU_MDP_UBWC_1_5, Universal Bandwidth compression version 1.5 49 49 * @DPU_MDP_PERIPH_0_REMOVED Indicates that access to periph top0 block results 50 50 * in a failure 51 + * @DPU_MDP_VSYNC_SEL Enables vsync source selection via MDP_VSYNC_SEL register 52 + * (moved into INTF block since DPU 5.0.0) 51 53 * @DPU_MDP_MAX Maximum value 52 54 53 55 */ ··· 61 59 DPU_MDP_UBWC_1_5, 62 60 DPU_MDP_AUDIO_SELECT, 63 61 DPU_MDP_PERIPH_0_REMOVED, 62 + DPU_MDP_VSYNC_SEL, 64 63 DPU_MDP_MAX 65 64 }; 66 65 67 66 /** 68 67 * SSPP sub-blocks/features 69 - * @DPU_SSPP_SRC Src and fetch part of the pipes, 70 68 * @DPU_SSPP_SCALER_QSEED2, QSEED2 algorithm support 71 69 * @DPU_SSPP_SCALER_QSEED3, QSEED3 alogorithm support 72 70 * @DPU_SSPP_SCALER_QSEED3LITE, QSEED3 Lite alogorithm support ··· 87 85 * @DPU_SSPP_MAX maximum value 88 86 */ 89 87 enum { 90 - DPU_SSPP_SRC = 0x1, 91 - DPU_SSPP_SCALER_QSEED2, 88 + DPU_SSPP_SCALER_QSEED2 = 0x1, 92 89 DPU_SSPP_SCALER_QSEED3, 93 90 DPU_SSPP_SCALER_QSEED3LITE, 94 91 DPU_SSPP_SCALER_QSEED4, ··· 128 127 /** 129 128 * DSPP sub-blocks 130 129 * @DPU_DSPP_PCC Panel color correction block 131 - * @DPU_DSPP_GC Gamma correction block 132 - * @DPU_DSPP_IGC Inverse gamma correction block 133 130 */ 134 131 enum { 135 132 DPU_DSPP_PCC = 0x1, 136 - DPU_DSPP_GC, 137 - DPU_DSPP_IGC, 138 133 DPU_DSPP_MAX 139 134 }; 140 135 ··· 140 143 * @DPU_PINGPONG_TE2 Additional tear check block for split pipes 141 144 * @DPU_PINGPONG_SPLIT PP block supports split fifo 142 145 * @DPU_PINGPONG_SLAVE PP block is a suitable slave for split fifo 143 - * @DPU_PINGPONG_DITHER, Dither blocks 146 + * @DPU_PINGPONG_DITHER Dither blocks 147 + * @DPU_PINGPONG_DSC PP block supports DSC 144 148 * @DPU_PINGPONG_MAX 145 149 */ 146 150 enum { ··· 150 152 DPU_PINGPONG_SPLIT, 151 153 DPU_PINGPONG_SLAVE, 152 154 DPU_PINGPONG_DITHER, 155 + DPU_PINGPONG_DSC, 153 156 DPU_PINGPONG_MAX 154 157 }; 155 158 ··· 181 182 * @DPU_DATA_HCTL_EN Allows data to be transferred at different rate 182 183 * than video timing 183 184 * @DPU_INTF_STATUS_SUPPORTED INTF block has INTF_STATUS register 185 + * @DPU_INTF_DATA_COMPRESS INTF block has DATA_COMPRESS register 184 186 * @DPU_INTF_MAX 185 187 */ 186 188 enum { ··· 189 189 DPU_INTF_TE, 190 190 DPU_DATA_HCTL_EN, 191 191 DPU_INTF_STATUS_SUPPORTED, 192 + DPU_INTF_DATA_COMPRESS, 192 193 DPU_INTF_MAX 193 194 }; 194 195 ··· 242 241 }; 243 242 244 243 /** 245 - * DSC features 244 + * DSC sub-blocks/features 246 245 * @DPU_DSC_OUTPUT_CTRL Configure which PINGPONG block gets 247 246 * the pixel output from this DSC. 247 + * @DPU_DSC_HW_REV_1_2 DSC block supports DSC 1.1 and 1.2 248 + * @DPU_DSC_NATIVE_42x_EN Supports NATIVE_422_EN and NATIVE_420_EN encoding 249 + * @DPU_DSC_MAX 248 250 */ 249 251 enum { 250 252 DPU_DSC_OUTPUT_CTRL = 0x1, 253 + DPU_DSC_HW_REV_1_2, 254 + DPU_DSC_NATIVE_42x_EN, 255 + DPU_DSC_MAX 251 256 }; 252 257 253 258 /** ··· 286 279 u32 len 287 280 288 281 /** 289 - * struct dpu_src_blk: SSPP part of the source pipes 290 - * @info: HW register and features supported by this sub-blk 291 - */ 292 - struct dpu_src_blk { 293 - DPU_HW_SUBBLK_INFO; 294 - }; 295 - 296 - /** 297 282 * struct dpu_scaler_blk: Scaler information 298 283 * @info: HW register and features supported by this sub-blk 299 284 * @version: qseed block revision ··· 307 308 struct dpu_pp_blk { 308 309 DPU_HW_SUBBLK_INFO; 309 310 u32 version; 311 + }; 312 + 313 + /** 314 + * struct dpu_dsc_blk - DSC Encoder sub-blk information 315 + * @info: HW register and features supported by this sub-blk 316 + */ 317 + struct dpu_dsc_blk { 318 + DPU_HW_SUBBLK_INFO; 310 319 }; 311 320 312 321 /** ··· 392 385 /** 393 386 * struct dpu_sspp_sub_blks : SSPP sub-blocks 394 387 * common: Pointer to common configurations shared by sub blocks 395 - * @creq_vblank: creq priority during vertical blanking 396 - * @danger_vblank: danger priority during vertical blanking 397 388 * @maxdwnscale: max downscale ratio supported(without DECIMATION) 398 389 * @maxupscale: maxupscale ratio supported 399 390 * @smart_dma_priority: hw priority of rect1 of multirect pipe 400 391 * @max_per_pipe_bw: maximum allowable bandwidth of this pipe in kBps 401 392 * @qseed_ver: qseed version 402 - * @src_blk: 403 393 * @scaler_blk: 404 394 * @csc_blk: 405 - * @hsic: 406 - * @memcolor: 407 - * @pcc_blk: 408 - * @igc_blk: 409 395 * @format_list: Pointer to list of supported formats 410 396 * @num_formats: Number of supported formats 411 397 * @virt_format_list: Pointer to list of supported formats for virtual planes ··· 406 406 * @dpu_rotation_cfg: inline rotation configuration 407 407 */ 408 408 struct dpu_sspp_sub_blks { 409 - u32 creq_vblank; 410 - u32 danger_vblank; 411 409 u32 maxdwnscale; 412 410 u32 maxupscale; 413 411 u32 smart_dma_priority; 414 412 u32 max_per_pipe_bw; 415 413 u32 qseed_ver; 416 - struct dpu_src_blk src_blk; 417 414 struct dpu_scaler_blk scaler_blk; 418 415 struct dpu_pp_blk csc_blk; 419 - struct dpu_pp_blk hsic_blk; 420 - struct dpu_pp_blk memcolor_blk; 421 - struct dpu_pp_blk pcc_blk; 422 - struct dpu_pp_blk igc_blk; 423 416 424 417 const u32 *format_list; 425 418 u32 num_formats; ··· 426 433 * @maxwidth: Max pixel width supported by this mixer 427 434 * @maxblendstages: Max number of blend-stages supported 428 435 * @blendstage_base: Blend-stage register base offset 429 - * @gc: gamma correction block 430 436 */ 431 437 struct dpu_lm_sub_blks { 432 438 u32 maxwidth; 433 439 u32 maxblendstages; 434 440 u32 blendstage_base[MAX_BLOCKS]; 435 - struct dpu_pp_blk gc; 436 441 }; 437 442 438 443 /** 439 444 * struct dpu_dspp_sub_blks: Information of DSPP block 440 - * @gc : gamma correction block 441 445 * @pcc: pixel color correction block 442 446 */ 443 447 struct dpu_dspp_sub_blks { 444 - struct dpu_pp_blk gc; 445 448 struct dpu_pp_blk pcc; 446 449 }; 447 450 ··· 445 456 struct dpu_pp_blk te; 446 457 struct dpu_pp_blk te2; 447 458 struct dpu_pp_blk dither; 459 + }; 460 + 461 + /** 462 + * struct dpu_dsc_sub_blks - DSC sub-blks 463 + * @enc: DSC encoder sub-block 464 + * @ctl: DSC controller sub-block 465 + */ 466 + struct dpu_dsc_sub_blks { 467 + struct dpu_dsc_blk enc; 468 + struct dpu_dsc_blk ctl; 448 469 }; 449 470 450 471 /** ··· 553 554 * @base register offset of this block 554 555 * @features bit mask identifying sub-blocks/features 555 556 * @sblk: LM Sub-blocks information 556 - * @pingpong: ID of connected PingPong, PINGPONG_MAX if unsupported 557 + * @pingpong: ID of connected PingPong, PINGPONG_NONE if unsupported 557 558 * @lm_pair_mask: Bitmask of LMs that can be controlled by same CTL 558 559 */ 559 560 struct dpu_lm_cfg { ··· 611 612 * struct dpu_dsc_cfg - information of DSC blocks 612 613 * @id enum identifying this block 613 614 * @base register offset of this block 615 + * @len: length of hardware block 614 616 * @features bit mask identifying sub-blocks/features 617 + * @sblk: sub-blocks information 615 618 */ 616 619 struct dpu_dsc_cfg { 617 620 DPU_HW_BLK_INFO; 621 + const struct dpu_dsc_sub_blks *sblk; 618 622 }; 619 623 620 624 /** ··· 630 628 * @prog_fetch_lines_worst_case Worst case latency num lines needed to prefetch 631 629 * @intr_underrun: index for INTF underrun interrupt 632 630 * @intr_vsync: index for INTF VSYNC interrupt 631 + * @intr_tear_rd_ptr: Index for INTF TEAR_RD_PTR interrupt 633 632 */ 634 633 struct dpu_intf_cfg { 635 634 DPU_HW_BLK_INFO; ··· 639 636 u32 prog_fetch_lines_worst_case; 640 637 s32 intr_underrun; 641 638 s32 intr_vsync; 639 + s32 intr_tear_rd_ptr; 642 640 }; 643 641 644 642 /** ··· 723 719 struct dpu_vbif_qos_tbl qos_nrt_tbl; 724 720 u32 memtype_count; 725 721 u32 memtype[MAX_XIN_COUNT]; 726 - }; 727 - /** 728 - * struct dpu_reg_dma_cfg - information of lut dma blocks 729 - * @id enum identifying this block 730 - * @base register offset of this block 731 - * @features bit mask identifying sub-blocks/features 732 - * @version version of lutdma hw block 733 - * @trigger_sel_off offset to trigger select registers of lutdma 734 - */ 735 - struct dpu_reg_dma_cfg { 736 - DPU_HW_BLK_INFO; 737 - u32 version; 738 - u32 trigger_sel_off; 739 - u32 xin_id; 740 - enum dpu_clk_ctrl_type clk_ctrl; 741 722 }; 742 723 743 724 /** ··· 839 850 u32 wb_count; 840 851 const struct dpu_wb_cfg *wb; 841 852 842 - u32 reg_dma_count; 843 - const struct dpu_reg_dma_cfg *dma_cfg; 844 - 845 853 u32 ad_count; 846 854 847 855 u32 dspp_count; ··· 861 875 extern const struct dpu_mdss_cfg dpu_sm8250_cfg; 862 876 extern const struct dpu_mdss_cfg dpu_sc7180_cfg; 863 877 extern const struct dpu_mdss_cfg dpu_sm6115_cfg; 878 + extern const struct dpu_mdss_cfg dpu_sm6350_cfg; 864 879 extern const struct dpu_mdss_cfg dpu_qcm2290_cfg; 880 + extern const struct dpu_mdss_cfg dpu_sm6375_cfg; 865 881 extern const struct dpu_mdss_cfg dpu_sm8350_cfg; 866 882 extern const struct dpu_mdss_cfg dpu_sc7280_cfg; 867 883 extern const struct dpu_mdss_cfg dpu_sc8280xp_cfg;
+35 -41
drivers/gpu/drm/msm/disp/dpu1/dpu_hw_ctl.c
··· 53 53 CTL_INVALID_BIT, CTL_INVALID_BIT, CTL_INVALID_BIT, CTL_INVALID_BIT, 0, 54 54 1, 2, 3, CTL_INVALID_BIT, CTL_INVALID_BIT}; 55 55 56 - static const struct dpu_ctl_cfg *_ctl_offset(enum dpu_ctl ctl, 57 - const struct dpu_mdss_cfg *m, 58 - void __iomem *addr, 59 - struct dpu_hw_blk_reg_map *b) 60 - { 61 - int i; 62 - 63 - for (i = 0; i < m->ctl_count; i++) { 64 - if (ctl == m->ctl[i].id) { 65 - b->blk_addr = addr + m->ctl[i].base; 66 - b->log_mask = DPU_DBG_MASK_CTL; 67 - return &m->ctl[i]; 68 - } 69 - } 70 - return ERR_PTR(-ENOMEM); 71 - } 72 - 73 56 static int _mixer_stages(const struct dpu_lm_cfg *mixer, int count, 74 57 enum dpu_lm lm) 75 58 { ··· 100 117 trace_dpu_hw_ctl_clear_pending_flush(ctx->pending_flush_mask, 101 118 dpu_hw_ctl_get_flush_register(ctx)); 102 119 ctx->pending_flush_mask = 0x0; 120 + ctx->pending_intf_flush_mask = 0; 121 + ctx->pending_wb_flush_mask = 0; 122 + ctx->pending_merge_3d_flush_mask = 0; 123 + ctx->pending_dsc_flush_mask = 0; 103 124 104 125 memset(ctx->pending_dspp_flush_mask, 0, 105 126 sizeof(ctx->pending_dspp_flush_mask)); ··· 143 156 CTL_DSPP_n_FLUSH(dspp - DSPP_0), 144 157 ctx->pending_dspp_flush_mask[dspp - DSPP_0]); 145 158 } 159 + 160 + if (ctx->pending_flush_mask & BIT(DSC_IDX)) 161 + DPU_REG_WRITE(&ctx->hw, CTL_DSC_FLUSH, 162 + ctx->pending_dsc_flush_mask); 163 + 146 164 DPU_REG_WRITE(&ctx->hw, CTL_FLUSH, ctx->pending_flush_mask); 147 165 } 148 166 ··· 294 302 ctx->pending_flush_mask |= BIT(MERGE_3D_IDX); 295 303 } 296 304 305 + static void dpu_hw_ctl_update_pending_flush_dsc_v1(struct dpu_hw_ctl *ctx, 306 + enum dpu_dsc dsc_num) 307 + { 308 + ctx->pending_dsc_flush_mask |= BIT(dsc_num - DSC_0); 309 + ctx->pending_flush_mask |= BIT(DSC_IDX); 310 + } 311 + 297 312 static void dpu_hw_ctl_update_pending_flush_dspp(struct dpu_hw_ctl *ctx, 298 313 enum dpu_dspp dspp, u32 dspp_sub_blk) 299 314 { ··· 329 330 return; 330 331 331 332 switch (dspp_sub_blk) { 332 - case DPU_DSPP_IGC: 333 - ctx->pending_dspp_flush_mask[dspp - DSPP_0] |= BIT(2); 334 - break; 335 333 case DPU_DSPP_PCC: 336 334 ctx->pending_dspp_flush_mask[dspp - DSPP_0] |= BIT(4); 337 - break; 338 - case DPU_DSPP_GC: 339 - ctx->pending_dspp_flush_mask[dspp - DSPP_0] |= BIT(5); 340 335 break; 341 336 default: 342 337 return; ··· 512 519 if ((test_bit(DPU_CTL_VM_CFG, &ctx->caps->features))) 513 520 mode_sel = CTL_DEFAULT_GROUP_ID << 28; 514 521 515 - if (cfg->dsc) 516 - DPU_REG_WRITE(&ctx->hw, CTL_DSC_FLUSH, cfg->dsc); 517 - 518 522 if (cfg->intf_mode_sel == DPU_CTL_MODE_SEL_CMD) 519 523 mode_sel |= BIT(17); 520 524 ··· 531 541 if (cfg->merge_3d) 532 542 DPU_REG_WRITE(c, CTL_MERGE_3D_ACTIVE, 533 543 BIT(cfg->merge_3d - MERGE_3D_0)); 534 - if (cfg->dsc) { 535 - DPU_REG_WRITE(&ctx->hw, CTL_FLUSH, DSC_IDX); 544 + 545 + if (cfg->dsc) 536 546 DPU_REG_WRITE(c, CTL_DSC_ACTIVE, cfg->dsc); 537 - } 538 547 } 539 548 540 549 static void dpu_hw_ctl_intf_cfg(struct dpu_hw_ctl *ctx, ··· 576 587 u32 intf_active = 0; 577 588 u32 wb_active = 0; 578 589 u32 merge3d_active = 0; 590 + u32 dsc_active; 579 591 580 592 /* 581 593 * This API resets each portion of the CTL path namely, ··· 605 615 wb_active = DPU_REG_READ(c, CTL_WB_ACTIVE); 606 616 wb_active &= ~BIT(cfg->wb - WB_0); 607 617 DPU_REG_WRITE(c, CTL_WB_ACTIVE, wb_active); 618 + } 619 + 620 + if (cfg->dsc) { 621 + dsc_active = DPU_REG_READ(c, CTL_DSC_ACTIVE); 622 + dsc_active &= ~cfg->dsc; 623 + DPU_REG_WRITE(c, CTL_DSC_ACTIVE, dsc_active); 608 624 } 609 625 } 610 626 ··· 643 647 ops->update_pending_flush_merge_3d = 644 648 dpu_hw_ctl_update_pending_flush_merge_3d_v1; 645 649 ops->update_pending_flush_wb = dpu_hw_ctl_update_pending_flush_wb_v1; 650 + ops->update_pending_flush_dsc = 651 + dpu_hw_ctl_update_pending_flush_dsc_v1; 646 652 } else { 647 653 ops->trigger_flush = dpu_hw_ctl_trigger_flush; 648 654 ops->setup_intf_cfg = dpu_hw_ctl_intf_cfg; ··· 674 676 ops->set_active_pipes = dpu_hw_ctl_set_fetch_pipe_active; 675 677 }; 676 678 677 - struct dpu_hw_ctl *dpu_hw_ctl_init(enum dpu_ctl idx, 679 + struct dpu_hw_ctl *dpu_hw_ctl_init(const struct dpu_ctl_cfg *cfg, 678 680 void __iomem *addr, 679 - const struct dpu_mdss_cfg *m) 681 + u32 mixer_count, 682 + const struct dpu_lm_cfg *mixer) 680 683 { 681 684 struct dpu_hw_ctl *c; 682 - const struct dpu_ctl_cfg *cfg; 683 685 684 686 c = kzalloc(sizeof(*c), GFP_KERNEL); 685 687 if (!c) 686 688 return ERR_PTR(-ENOMEM); 687 689 688 - cfg = _ctl_offset(idx, m, addr, &c->hw); 689 - if (IS_ERR_OR_NULL(cfg)) { 690 - kfree(c); 691 - pr_err("failed to create dpu_hw_ctl %d\n", idx); 692 - return ERR_PTR(-EINVAL); 693 - } 690 + c->hw.blk_addr = addr + cfg->base; 691 + c->hw.log_mask = DPU_DBG_MASK_CTL; 694 692 695 693 c->caps = cfg; 696 694 _setup_ctl_ops(&c->ops, c->caps->features); 697 - c->idx = idx; 698 - c->mixer_count = m->mixer_count; 699 - c->mixer_hw_caps = m->mixer; 695 + c->idx = cfg->id; 696 + c->mixer_count = mixer_count; 697 + c->mixer_hw_caps = mixer; 700 698 701 699 return c; 702 700 }
+19 -6
drivers/gpu/drm/msm/disp/dpu1/dpu_hw_ctl.h
··· 158 158 enum dpu_dspp blk, u32 dspp_sub_blk); 159 159 160 160 /** 161 + * OR in the given flushbits to the cached pending_(dsc_)flush_mask 162 + * No effect on hardware 163 + * @ctx: ctl path ctx pointer 164 + * @blk: interface block index 165 + */ 166 + void (*update_pending_flush_dsc)(struct dpu_hw_ctl *ctx, 167 + enum dpu_dsc blk); 168 + 169 + /** 161 170 * Write the value of the pending_flush_mask to hardware 162 171 * @ctx : ctl path ctx pointer 163 172 */ ··· 238 229 * @pending_flush_mask: storage for pending ctl_flush managed via ops 239 230 * @pending_intf_flush_mask: pending INTF flush 240 231 * @pending_wb_flush_mask: pending WB flush 232 + * @pending_dsc_flush_mask: pending DSC flush 241 233 * @ops: operation list 242 234 */ 243 235 struct dpu_hw_ctl { ··· 255 245 u32 pending_wb_flush_mask; 256 246 u32 pending_merge_3d_flush_mask; 257 247 u32 pending_dspp_flush_mask[DSPP_MAX - DSPP_0]; 248 + u32 pending_dsc_flush_mask; 258 249 259 250 /* ops */ 260 251 struct dpu_hw_ctl_ops ops; ··· 272 261 } 273 262 274 263 /** 275 - * dpu_hw_ctl_init(): Initializes the ctl_path hw driver object. 276 - * should be called before accessing every ctl path registers. 277 - * @idx: ctl_path index for which driver object is required 264 + * dpu_hw_ctl_init() - Initializes the ctl_path hw driver object. 265 + * Should be called before accessing any ctl_path register. 266 + * @cfg: ctl_path catalog entry for which driver object is required 278 267 * @addr: mapped register io address of MDP 279 - * @m : pointer to mdss catalog data 268 + * @mixer_count: Number of mixers in @mixer 269 + * @mixer: Pointer to an array of Layer Mixers defined in the catalog 280 270 */ 281 - struct dpu_hw_ctl *dpu_hw_ctl_init(enum dpu_ctl idx, 271 + struct dpu_hw_ctl *dpu_hw_ctl_init(const struct dpu_ctl_cfg *cfg, 282 272 void __iomem *addr, 283 - const struct dpu_mdss_cfg *m); 273 + u32 mixer_count, 274 + const struct dpu_lm_cfg *mixer); 284 275 285 276 /** 286 277 * dpu_hw_ctl_destroy(): Destroys ctl driver context
+18 -37
drivers/gpu/drm/msm/disp/dpu1/dpu_hw_dsc.c
··· 3 3 * Copyright (c) 2020-2022, Linaro Limited 4 4 */ 5 5 6 + #include <drm/display/drm_dsc_helper.h> 7 + 6 8 #include "dpu_kms.h" 7 9 #include "dpu_hw_catalog.h" 8 10 #include "dpu_hwio.h" ··· 56 54 if (is_cmd_mode) 57 55 initial_lines += 1; 58 56 59 - slice_last_group_size = 3 - (dsc->slice_width % 3); 57 + slice_last_group_size = (dsc->slice_width + 2) % 3; 58 + 60 59 data = (initial_lines << 20); 61 - data |= ((slice_last_group_size - 1) << 18); 60 + data |= (slice_last_group_size << 18); 62 61 /* bpp is 6.4 format, 4 LSBs bits are for fractional part */ 63 62 data |= (dsc->bits_per_pixel << 8); 64 63 data |= (dsc->block_pred_enable << 7); ··· 105 102 data |= dsc->final_offset; 106 103 DPU_REG_WRITE(c, DSC_DSC_OFFSET, data); 107 104 108 - det_thresh_flatness = 7 + 2 * (dsc->bits_per_component - 8); 105 + det_thresh_flatness = drm_dsc_flatness_det_thresh(dsc); 109 106 data = det_thresh_flatness << 10; 110 107 data |= dsc->flatness_max_qp << 5; 111 108 data |= dsc->flatness_min_qp; ··· 157 154 158 155 static void dpu_hw_dsc_bind_pingpong_blk( 159 156 struct dpu_hw_dsc *hw_dsc, 160 - bool enable, 161 157 const enum dpu_pingpong pp) 162 158 { 163 159 struct dpu_hw_blk_reg_map *c = &hw_dsc->hw; ··· 165 163 166 164 dsc_ctl_offset = DSC_CTL(hw_dsc->idx); 167 165 168 - if (enable) 166 + if (pp) 169 167 mux_cfg = (pp - PINGPONG_0) & 0x7; 170 168 171 - DRM_DEBUG_KMS("%s dsc:%d %s pp:%d\n", 172 - enable ? "Binding" : "Unbinding", 173 - hw_dsc->idx - DSC_0, 174 - enable ? "to" : "from", 175 - pp - PINGPONG_0); 169 + if (pp) 170 + DRM_DEBUG_KMS("Binding dsc:%d to pp:%d\n", 171 + hw_dsc->idx - DSC_0, pp - PINGPONG_0); 172 + else 173 + DRM_DEBUG_KMS("Unbinding dsc:%d from any pp\n", 174 + hw_dsc->idx - DSC_0); 176 175 177 176 DPU_REG_WRITE(c, dsc_ctl_offset, mux_cfg); 178 - } 179 - 180 - static const struct dpu_dsc_cfg *_dsc_offset(enum dpu_dsc dsc, 181 - const struct dpu_mdss_cfg *m, 182 - void __iomem *addr, 183 - struct dpu_hw_blk_reg_map *b) 184 - { 185 - int i; 186 - 187 - for (i = 0; i < m->dsc_count; i++) { 188 - if (dsc == m->dsc[i].id) { 189 - b->blk_addr = addr + m->dsc[i].base; 190 - b->log_mask = DPU_DBG_MASK_DSC; 191 - return &m->dsc[i]; 192 - } 193 - } 194 - 195 - return NULL; 196 177 } 197 178 198 179 static void _setup_dsc_ops(struct dpu_hw_dsc_ops *ops, ··· 188 203 ops->dsc_bind_pingpong_blk = dpu_hw_dsc_bind_pingpong_blk; 189 204 }; 190 205 191 - struct dpu_hw_dsc *dpu_hw_dsc_init(enum dpu_dsc idx, void __iomem *addr, 192 - const struct dpu_mdss_cfg *m) 206 + struct dpu_hw_dsc *dpu_hw_dsc_init(const struct dpu_dsc_cfg *cfg, 207 + void __iomem *addr) 193 208 { 194 209 struct dpu_hw_dsc *c; 195 - const struct dpu_dsc_cfg *cfg; 196 210 197 211 c = kzalloc(sizeof(*c), GFP_KERNEL); 198 212 if (!c) 199 213 return ERR_PTR(-ENOMEM); 200 214 201 - cfg = _dsc_offset(idx, m, addr, &c->hw); 202 - if (IS_ERR_OR_NULL(cfg)) { 203 - kfree(c); 204 - return ERR_PTR(-EINVAL); 205 - } 215 + c->hw.blk_addr = addr + cfg->base; 216 + c->hw.log_mask = DPU_DBG_MASK_DSC; 206 217 207 - c->idx = idx; 218 + c->idx = cfg->id; 208 219 c->caps = cfg; 209 220 _setup_dsc_ops(&c->ops, c->caps->features); 210 221
+17 -7
drivers/gpu/drm/msm/disp/dpu1/dpu_hw_dsc.h
··· 1 1 /* SPDX-License-Identifier: GPL-2.0-only */ 2 - /* Copyright (c) 2020-2022, Linaro Limited */ 2 + /* 3 + * Copyright (c) 2020-2022, Linaro Limited 4 + * Copyright (c) 2023 Qualcomm Innovation Center, Inc. All rights reserved 5 + */ 3 6 4 7 #ifndef _DPU_HW_DSC_H 5 8 #define _DPU_HW_DSC_H ··· 47 44 struct drm_dsc_config *dsc); 48 45 49 46 void (*dsc_bind_pingpong_blk)(struct dpu_hw_dsc *hw_dsc, 50 - bool enable, 51 47 enum dpu_pingpong pp); 52 48 }; 53 49 ··· 63 61 }; 64 62 65 63 /** 66 - * dpu_hw_dsc_init - initializes the dsc block for the passed dsc idx. 67 - * @idx: DSC index for which driver object is required 64 + * dpu_hw_dsc_init() - Initializes the DSC hw driver object. 65 + * @cfg: DSC catalog entry for which driver object is required 68 66 * @addr: Mapped register io address of MDP 69 - * @m: Pointer to mdss catalog data 67 + * Return: Error code or allocated dpu_hw_dsc context 68 + */ 69 + struct dpu_hw_dsc *dpu_hw_dsc_init(const struct dpu_dsc_cfg *cfg, 70 + void __iomem *addr); 71 + 72 + /** 73 + * dpu_hw_dsc_init_1_2() - initializes the v1.2 DSC hw driver object 74 + * @cfg: DSC catalog entry for which driver object is required 75 + * @addr: Mapped register io address of MDP 70 76 * Returns: Error code or allocated dpu_hw_dsc context 71 77 */ 72 - struct dpu_hw_dsc *dpu_hw_dsc_init(enum dpu_dsc idx, void __iomem *addr, 73 - const struct dpu_mdss_cfg *m); 78 + struct dpu_hw_dsc *dpu_hw_dsc_init_1_2(const struct dpu_dsc_cfg *cfg, 79 + void __iomem *addr); 74 80 75 81 /** 76 82 * dpu_hw_dsc_destroy - destroys dsc driver context
+387
drivers/gpu/drm/msm/disp/dpu1/dpu_hw_dsc_1_2.c
··· 1 + // SPDX-License-Identifier: GPL-2.0-only 2 + /* 3 + * Copyright (c) 2020-2021, The Linux Foundation. All rights reserved. 4 + * Copyright (c) 2023 Qualcomm Innovation Center, Inc. All rights reserved 5 + */ 6 + 7 + #include <drm/display/drm_dsc_helper.h> 8 + 9 + #include "dpu_kms.h" 10 + #include "dpu_hw_catalog.h" 11 + #include "dpu_hwio.h" 12 + #include "dpu_hw_mdss.h" 13 + #include "dpu_hw_dsc.h" 14 + 15 + #define DSC_CMN_MAIN_CNF 0x00 16 + 17 + /* DPU_DSC_ENC register offsets */ 18 + #define ENC_DF_CTRL 0x00 19 + #define ENC_GENERAL_STATUS 0x04 20 + #define ENC_HSLICE_STATUS 0x08 21 + #define ENC_OUT_STATUS 0x0C 22 + #define ENC_INT_STAT 0x10 23 + #define ENC_INT_CLR 0x14 24 + #define ENC_INT_MASK 0x18 25 + #define DSC_MAIN_CONF 0x30 26 + #define DSC_PICTURE_SIZE 0x34 27 + #define DSC_SLICE_SIZE 0x38 28 + #define DSC_MISC_SIZE 0x3C 29 + #define DSC_HRD_DELAYS 0x40 30 + #define DSC_RC_SCALE 0x44 31 + #define DSC_RC_SCALE_INC_DEC 0x48 32 + #define DSC_RC_OFFSETS_1 0x4C 33 + #define DSC_RC_OFFSETS_2 0x50 34 + #define DSC_RC_OFFSETS_3 0x54 35 + #define DSC_RC_OFFSETS_4 0x58 36 + #define DSC_FLATNESS_QP 0x5C 37 + #define DSC_RC_MODEL_SIZE 0x60 38 + #define DSC_RC_CONFIG 0x64 39 + #define DSC_RC_BUF_THRESH_0 0x68 40 + #define DSC_RC_BUF_THRESH_1 0x6C 41 + #define DSC_RC_BUF_THRESH_2 0x70 42 + #define DSC_RC_BUF_THRESH_3 0x74 43 + #define DSC_RC_MIN_QP_0 0x78 44 + #define DSC_RC_MIN_QP_1 0x7C 45 + #define DSC_RC_MIN_QP_2 0x80 46 + #define DSC_RC_MAX_QP_0 0x84 47 + #define DSC_RC_MAX_QP_1 0x88 48 + #define DSC_RC_MAX_QP_2 0x8C 49 + #define DSC_RC_RANGE_BPG_OFFSETS_0 0x90 50 + #define DSC_RC_RANGE_BPG_OFFSETS_1 0x94 51 + #define DSC_RC_RANGE_BPG_OFFSETS_2 0x98 52 + 53 + /* DPU_DSC_CTL register offsets */ 54 + #define DSC_CTL 0x00 55 + #define DSC_CFG 0x04 56 + #define DSC_DATA_IN_SWAP 0x08 57 + #define DSC_CLK_CTRL 0x0C 58 + 59 + static int _dsc_calc_output_buf_max_addr(struct dpu_hw_dsc *hw_dsc, int num_softslice) 60 + { 61 + int max_addr = 2400 / num_softslice; 62 + 63 + if (hw_dsc->caps->features & BIT(DPU_DSC_NATIVE_42x_EN)) 64 + max_addr /= 2; 65 + 66 + return max_addr - 1; 67 + }; 68 + 69 + static void dpu_hw_dsc_disable_1_2(struct dpu_hw_dsc *hw_dsc) 70 + { 71 + struct dpu_hw_blk_reg_map *hw; 72 + const struct dpu_dsc_sub_blks *sblk; 73 + 74 + if (!hw_dsc) 75 + return; 76 + 77 + hw = &hw_dsc->hw; 78 + sblk = hw_dsc->caps->sblk; 79 + DPU_REG_WRITE(hw, sblk->ctl.base + DSC_CFG, 0); 80 + 81 + DPU_REG_WRITE(hw, sblk->enc.base + ENC_DF_CTRL, 0); 82 + DPU_REG_WRITE(hw, sblk->enc.base + DSC_MAIN_CONF, 0); 83 + } 84 + 85 + static void dpu_hw_dsc_config_1_2(struct dpu_hw_dsc *hw_dsc, 86 + struct drm_dsc_config *dsc, 87 + u32 mode, 88 + u32 initial_lines) 89 + { 90 + struct dpu_hw_blk_reg_map *hw; 91 + const struct dpu_dsc_sub_blks *sblk; 92 + u32 data = 0; 93 + u32 det_thresh_flatness; 94 + u32 num_active_slice_per_enc; 95 + u32 bpp; 96 + 97 + if (!hw_dsc || !dsc) 98 + return; 99 + 100 + hw = &hw_dsc->hw; 101 + 102 + sblk = hw_dsc->caps->sblk; 103 + 104 + if (mode & DSC_MODE_SPLIT_PANEL) 105 + data |= BIT(0); 106 + 107 + if (mode & DSC_MODE_MULTIPLEX) 108 + data |= BIT(1); 109 + 110 + num_active_slice_per_enc = dsc->slice_count; 111 + if (mode & DSC_MODE_MULTIPLEX) 112 + num_active_slice_per_enc = dsc->slice_count / 2; 113 + 114 + data |= (num_active_slice_per_enc & 0x3) << 7; 115 + 116 + DPU_REG_WRITE(hw, DSC_CMN_MAIN_CNF, data); 117 + 118 + data = (initial_lines & 0xff); 119 + 120 + if (mode & DSC_MODE_VIDEO) 121 + data |= BIT(9); 122 + 123 + data |= (_dsc_calc_output_buf_max_addr(hw_dsc, num_active_slice_per_enc) << 18); 124 + 125 + DPU_REG_WRITE(hw, sblk->enc.base + ENC_DF_CTRL, data); 126 + 127 + data = (dsc->dsc_version_minor & 0xf) << 28; 128 + if (dsc->dsc_version_minor == 0x2) { 129 + if (dsc->native_422) 130 + data |= BIT(22); 131 + if (dsc->native_420) 132 + data |= BIT(21); 133 + } 134 + 135 + bpp = dsc->bits_per_pixel; 136 + /* as per hw requirement bpp should be programmed 137 + * twice the actual value in case of 420 or 422 encoding 138 + */ 139 + if (dsc->native_422 || dsc->native_420) 140 + bpp = 2 * bpp; 141 + 142 + data |= bpp << 10; 143 + 144 + if (dsc->block_pred_enable) 145 + data |= BIT(20); 146 + 147 + if (dsc->convert_rgb) 148 + data |= BIT(4); 149 + 150 + data |= (dsc->line_buf_depth & 0xf) << 6; 151 + data |= dsc->bits_per_component & 0xf; 152 + 153 + DPU_REG_WRITE(hw, sblk->enc.base + DSC_MAIN_CONF, data); 154 + 155 + data = (dsc->pic_width & 0xffff) | 156 + ((dsc->pic_height & 0xffff) << 16); 157 + 158 + DPU_REG_WRITE(hw, sblk->enc.base + DSC_PICTURE_SIZE, data); 159 + 160 + data = (dsc->slice_width & 0xffff) | 161 + ((dsc->slice_height & 0xffff) << 16); 162 + 163 + DPU_REG_WRITE(hw, sblk->enc.base + DSC_SLICE_SIZE, data); 164 + 165 + DPU_REG_WRITE(hw, sblk->enc.base + DSC_MISC_SIZE, 166 + (dsc->slice_chunk_size) & 0xffff); 167 + 168 + data = (dsc->initial_xmit_delay & 0xffff) | 169 + ((dsc->initial_dec_delay & 0xffff) << 16); 170 + 171 + DPU_REG_WRITE(hw, sblk->enc.base + DSC_HRD_DELAYS, data); 172 + 173 + DPU_REG_WRITE(hw, sblk->enc.base + DSC_RC_SCALE, 174 + dsc->initial_scale_value & 0x3f); 175 + 176 + data = (dsc->scale_increment_interval & 0xffff) | 177 + ((dsc->scale_decrement_interval & 0x7ff) << 16); 178 + 179 + DPU_REG_WRITE(hw, sblk->enc.base + DSC_RC_SCALE_INC_DEC, data); 180 + 181 + data = (dsc->first_line_bpg_offset & 0x1f) | 182 + ((dsc->second_line_bpg_offset & 0x1f) << 5); 183 + 184 + DPU_REG_WRITE(hw, sblk->enc.base + DSC_RC_OFFSETS_1, data); 185 + 186 + data = (dsc->nfl_bpg_offset & 0xffff) | 187 + ((dsc->slice_bpg_offset & 0xffff) << 16); 188 + 189 + DPU_REG_WRITE(hw, sblk->enc.base + DSC_RC_OFFSETS_2, data); 190 + 191 + data = (dsc->initial_offset & 0xffff) | 192 + ((dsc->final_offset & 0xffff) << 16); 193 + 194 + DPU_REG_WRITE(hw, sblk->enc.base + DSC_RC_OFFSETS_3, data); 195 + 196 + data = (dsc->nsl_bpg_offset & 0xffff) | 197 + ((dsc->second_line_offset_adj & 0xffff) << 16); 198 + 199 + DPU_REG_WRITE(hw, sblk->enc.base + DSC_RC_OFFSETS_4, data); 200 + 201 + det_thresh_flatness = drm_dsc_flatness_det_thresh(dsc); 202 + data = (dsc->flatness_min_qp & 0x1f) | 203 + ((dsc->flatness_max_qp & 0x1f) << 5) | 204 + ((det_thresh_flatness & 0xff) << 10); 205 + 206 + DPU_REG_WRITE(hw, sblk->enc.base + DSC_FLATNESS_QP, data); 207 + 208 + DPU_REG_WRITE(hw, sblk->enc.base + DSC_RC_MODEL_SIZE, 209 + (dsc->rc_model_size) & 0xffff); 210 + 211 + data = dsc->rc_edge_factor & 0xf; 212 + data |= (dsc->rc_quant_incr_limit0 & 0x1f) << 8; 213 + data |= (dsc->rc_quant_incr_limit1 & 0x1f) << 13; 214 + data |= (dsc->rc_tgt_offset_high & 0xf) << 20; 215 + data |= (dsc->rc_tgt_offset_low & 0xf) << 24; 216 + 217 + DPU_REG_WRITE(hw, sblk->enc.base + DSC_RC_CONFIG, data); 218 + 219 + /* program the dsc wrapper */ 220 + data = BIT(0); /* encoder enable */ 221 + if (dsc->native_422) 222 + data |= BIT(8); 223 + else if (dsc->native_420) 224 + data |= BIT(9); 225 + if (!dsc->convert_rgb) 226 + data |= BIT(10); 227 + if (dsc->bits_per_component == 8) 228 + data |= BIT(11); 229 + if (mode & DSC_MODE_SPLIT_PANEL) 230 + data |= BIT(12); 231 + if (mode & DSC_MODE_MULTIPLEX) 232 + data |= BIT(13); 233 + if (!(mode & DSC_MODE_VIDEO)) 234 + data |= BIT(17); 235 + 236 + DPU_REG_WRITE(hw, sblk->ctl.base + DSC_CFG, data); 237 + } 238 + 239 + static void dpu_hw_dsc_config_thresh_1_2(struct dpu_hw_dsc *hw_dsc, 240 + struct drm_dsc_config *dsc) 241 + { 242 + struct dpu_hw_blk_reg_map *hw; 243 + const struct dpu_dsc_sub_blks *sblk; 244 + struct drm_dsc_rc_range_parameters *rc; 245 + 246 + if (!hw_dsc || !dsc) 247 + return; 248 + 249 + hw = &hw_dsc->hw; 250 + 251 + sblk = hw_dsc->caps->sblk; 252 + 253 + rc = dsc->rc_range_params; 254 + 255 + /* 256 + * With BUF_THRESH -- 14 in total 257 + * each register contains 4 thresh values with the last register 258 + * containing only 2 thresh values 259 + */ 260 + DPU_REG_WRITE(hw, sblk->enc.base + DSC_RC_BUF_THRESH_0, 261 + (dsc->rc_buf_thresh[0] << 0) | 262 + (dsc->rc_buf_thresh[1] << 8) | 263 + (dsc->rc_buf_thresh[2] << 16) | 264 + (dsc->rc_buf_thresh[3] << 24)); 265 + DPU_REG_WRITE(hw, sblk->enc.base + DSC_RC_BUF_THRESH_1, 266 + (dsc->rc_buf_thresh[4] << 0) | 267 + (dsc->rc_buf_thresh[5] << 8) | 268 + (dsc->rc_buf_thresh[6] << 16) | 269 + (dsc->rc_buf_thresh[7] << 24)); 270 + DPU_REG_WRITE(hw, sblk->enc.base + DSC_RC_BUF_THRESH_2, 271 + (dsc->rc_buf_thresh[8] << 0) | 272 + (dsc->rc_buf_thresh[9] << 8) | 273 + (dsc->rc_buf_thresh[10] << 16) | 274 + (dsc->rc_buf_thresh[11] << 24)); 275 + DPU_REG_WRITE(hw, sblk->enc.base + DSC_RC_BUF_THRESH_3, 276 + (dsc->rc_buf_thresh[12] << 0) | 277 + (dsc->rc_buf_thresh[13] << 8)); 278 + 279 + /* 280 + * with min/max_QP -- 5 bits 281 + * each register contains 5 min_qp or max_qp for total of 15 282 + * 283 + * With BPG_OFFSET -- 6 bits 284 + * each register contains 5 BPG_offset for total of 15 285 + */ 286 + DPU_REG_WRITE(hw, sblk->enc.base + DSC_RC_MIN_QP_0, 287 + (rc[0].range_min_qp << 0) | 288 + (rc[1].range_min_qp << 5) | 289 + (rc[2].range_min_qp << 10) | 290 + (rc[3].range_min_qp << 15) | 291 + (rc[4].range_min_qp << 20)); 292 + DPU_REG_WRITE(hw, sblk->enc.base + DSC_RC_MAX_QP_0, 293 + (rc[0].range_max_qp << 0) | 294 + (rc[1].range_max_qp << 5) | 295 + (rc[2].range_max_qp << 10) | 296 + (rc[3].range_max_qp << 15) | 297 + (rc[4].range_max_qp << 20)); 298 + DPU_REG_WRITE(hw, sblk->enc.base + DSC_RC_RANGE_BPG_OFFSETS_0, 299 + (rc[0].range_bpg_offset << 0) | 300 + (rc[1].range_bpg_offset << 6) | 301 + (rc[2].range_bpg_offset << 12) | 302 + (rc[3].range_bpg_offset << 18) | 303 + (rc[4].range_bpg_offset << 24)); 304 + 305 + DPU_REG_WRITE(hw, sblk->enc.base + DSC_RC_MIN_QP_1, 306 + (rc[5].range_min_qp << 0) | 307 + (rc[6].range_min_qp << 5) | 308 + (rc[7].range_min_qp << 10) | 309 + (rc[8].range_min_qp << 15) | 310 + (rc[9].range_min_qp << 20)); 311 + DPU_REG_WRITE(hw, sblk->enc.base + DSC_RC_MAX_QP_1, 312 + (rc[5].range_max_qp << 0) | 313 + (rc[6].range_max_qp << 5) | 314 + (rc[7].range_max_qp << 10) | 315 + (rc[8].range_max_qp << 15) | 316 + (rc[9].range_max_qp << 20)); 317 + DPU_REG_WRITE(hw, sblk->enc.base + DSC_RC_RANGE_BPG_OFFSETS_1, 318 + (rc[5].range_bpg_offset << 0) | 319 + (rc[6].range_bpg_offset << 6) | 320 + (rc[7].range_bpg_offset << 12) | 321 + (rc[8].range_bpg_offset << 18) | 322 + (rc[9].range_bpg_offset << 24)); 323 + 324 + DPU_REG_WRITE(hw, sblk->enc.base + DSC_RC_MIN_QP_2, 325 + (rc[10].range_min_qp << 0) | 326 + (rc[11].range_min_qp << 5) | 327 + (rc[12].range_min_qp << 10) | 328 + (rc[13].range_min_qp << 15) | 329 + (rc[14].range_min_qp << 20)); 330 + DPU_REG_WRITE(hw, sblk->enc.base + DSC_RC_MAX_QP_2, 331 + (rc[10].range_max_qp << 0) | 332 + (rc[11].range_max_qp << 5) | 333 + (rc[12].range_max_qp << 10) | 334 + (rc[13].range_max_qp << 15) | 335 + (rc[14].range_max_qp << 20)); 336 + DPU_REG_WRITE(hw, sblk->enc.base + DSC_RC_RANGE_BPG_OFFSETS_2, 337 + (rc[10].range_bpg_offset << 0) | 338 + (rc[11].range_bpg_offset << 6) | 339 + (rc[12].range_bpg_offset << 12) | 340 + (rc[13].range_bpg_offset << 18) | 341 + (rc[14].range_bpg_offset << 24)); 342 + } 343 + 344 + static void dpu_hw_dsc_bind_pingpong_blk_1_2(struct dpu_hw_dsc *hw_dsc, 345 + const enum dpu_pingpong pp) 346 + { 347 + struct dpu_hw_blk_reg_map *hw; 348 + const struct dpu_dsc_sub_blks *sblk; 349 + int mux_cfg = 0xf; /* Disabled */ 350 + 351 + hw = &hw_dsc->hw; 352 + 353 + sblk = hw_dsc->caps->sblk; 354 + 355 + if (pp) 356 + mux_cfg = (pp - PINGPONG_0) & 0x7; 357 + 358 + DPU_REG_WRITE(hw, sblk->ctl.base + DSC_CTL, mux_cfg); 359 + } 360 + 361 + static void _setup_dcs_ops_1_2(struct dpu_hw_dsc_ops *ops, 362 + const unsigned long features) 363 + { 364 + ops->dsc_disable = dpu_hw_dsc_disable_1_2; 365 + ops->dsc_config = dpu_hw_dsc_config_1_2; 366 + ops->dsc_config_thresh = dpu_hw_dsc_config_thresh_1_2; 367 + ops->dsc_bind_pingpong_blk = dpu_hw_dsc_bind_pingpong_blk_1_2; 368 + } 369 + 370 + struct dpu_hw_dsc *dpu_hw_dsc_init_1_2(const struct dpu_dsc_cfg *cfg, 371 + void __iomem *addr) 372 + { 373 + struct dpu_hw_dsc *c; 374 + 375 + c = kzalloc(sizeof(*c), GFP_KERNEL); 376 + if (!c) 377 + return ERR_PTR(-ENOMEM); 378 + 379 + c->hw.blk_addr = addr + cfg->base; 380 + c->hw.log_mask = DPU_DBG_MASK_DSC; 381 + 382 + c->idx = cfg->id; 383 + c->caps = cfg; 384 + _setup_dcs_ops_1_2(&c->ops, c->caps->features); 385 + 386 + return c; 387 + }
+6 -32
drivers/gpu/drm/msm/disp/dpu1/dpu_hw_dspp.c
··· 68 68 c->ops.setup_pcc = dpu_setup_dspp_pcc; 69 69 } 70 70 71 - static const struct dpu_dspp_cfg *_dspp_offset(enum dpu_dspp dspp, 72 - const struct dpu_mdss_cfg *m, 73 - void __iomem *addr, 74 - struct dpu_hw_blk_reg_map *b) 75 - { 76 - int i; 77 - 78 - if (!m || !addr || !b) 79 - return ERR_PTR(-EINVAL); 80 - 81 - for (i = 0; i < m->dspp_count; i++) { 82 - if (dspp == m->dspp[i].id) { 83 - b->blk_addr = addr + m->dspp[i].base; 84 - b->log_mask = DPU_DBG_MASK_DSPP; 85 - return &m->dspp[i]; 86 - } 87 - } 88 - 89 - return ERR_PTR(-EINVAL); 90 - } 91 - 92 - struct dpu_hw_dspp *dpu_hw_dspp_init(enum dpu_dspp idx, 93 - void __iomem *addr, 94 - const struct dpu_mdss_cfg *m) 71 + struct dpu_hw_dspp *dpu_hw_dspp_init(const struct dpu_dspp_cfg *cfg, 72 + void __iomem *addr) 95 73 { 96 74 struct dpu_hw_dspp *c; 97 - const struct dpu_dspp_cfg *cfg; 98 75 99 - if (!addr || !m) 76 + if (!addr) 100 77 return ERR_PTR(-EINVAL); 101 78 102 79 c = kzalloc(sizeof(*c), GFP_KERNEL); 103 80 if (!c) 104 81 return ERR_PTR(-ENOMEM); 105 82 106 - cfg = _dspp_offset(idx, m, addr, &c->hw); 107 - if (IS_ERR_OR_NULL(cfg)) { 108 - kfree(c); 109 - return ERR_PTR(-EINVAL); 110 - } 83 + c->hw.blk_addr = addr + cfg->base; 84 + c->hw.log_mask = DPU_DBG_MASK_DSPP; 111 85 112 86 /* Assign ops */ 113 - c->idx = idx; 87 + c->idx = cfg->id; 114 88 c->cap = cfg; 115 89 _setup_dspp_ops(c, c->cap->features); 116 90
+6 -6
drivers/gpu/drm/msm/disp/dpu1/dpu_hw_dspp.h
··· 79 79 } 80 80 81 81 /** 82 - * dpu_hw_dspp_init - initializes the dspp hw driver object. 83 - * should be called once before accessing every dspp. 84 - * @idx: DSPP index for which driver object is required 82 + * dpu_hw_dspp_init() - Initializes the DSPP hw driver object. 83 + * should be called once before accessing every DSPP. 84 + * @cfg: DSPP catalog entry for which driver object is required 85 85 * @addr: Mapped register io address of MDP 86 - * @Return: pointer to structure or ERR_PTR 86 + * Return: pointer to structure or ERR_PTR 87 87 */ 88 - struct dpu_hw_dspp *dpu_hw_dspp_init(enum dpu_dspp idx, 89 - void __iomem *addr, const struct dpu_mdss_cfg *m); 88 + struct dpu_hw_dspp *dpu_hw_dspp_init(const struct dpu_dspp_cfg *cfg, 89 + void __iomem *addr); 90 90 91 91 /** 92 92 * dpu_hw_dspp_destroy(): Destroys DSPP driver context
+100 -84
drivers/gpu/drm/msm/disp/dpu1/dpu_hw_interrupts.c
··· 17 17 * Register offsets in MDSS register file for the interrupt registers 18 18 * w.r.t. the MDP base 19 19 */ 20 - #define MDP_SSPP_TOP0_OFF 0x0 21 - #define MDP_INTF_0_OFF 0x6A000 22 - #define MDP_INTF_1_OFF 0x6A800 23 - #define MDP_INTF_2_OFF 0x6B000 24 - #define MDP_INTF_3_OFF 0x6B800 25 - #define MDP_INTF_4_OFF 0x6C000 26 - #define MDP_INTF_5_OFF 0x6C800 27 - #define INTF_INTR_EN 0x1c0 28 - #define INTF_INTR_STATUS 0x1c4 29 - #define INTF_INTR_CLEAR 0x1c8 30 - #define MDP_AD4_0_OFF 0x7C000 31 - #define MDP_AD4_1_OFF 0x7D000 32 - #define MDP_AD4_INTR_EN_OFF 0x41c 33 - #define MDP_AD4_INTR_CLEAR_OFF 0x424 34 - #define MDP_AD4_INTR_STATUS_OFF 0x420 35 - #define MDP_INTF_0_OFF_REV_7xxx 0x34000 36 - #define MDP_INTF_1_OFF_REV_7xxx 0x35000 37 - #define MDP_INTF_2_OFF_REV_7xxx 0x36000 38 - #define MDP_INTF_3_OFF_REV_7xxx 0x37000 39 - #define MDP_INTF_4_OFF_REV_7xxx 0x38000 40 - #define MDP_INTF_5_OFF_REV_7xxx 0x39000 41 - #define MDP_INTF_6_OFF_REV_7xxx 0x3a000 42 - #define MDP_INTF_7_OFF_REV_7xxx 0x3b000 43 - #define MDP_INTF_8_OFF_REV_7xxx 0x3c000 20 + #define MDP_INTF_OFF(intf) (0x6A000 + 0x800 * (intf)) 21 + #define MDP_INTF_INTR_EN(intf) (MDP_INTF_OFF(intf) + 0x1c0) 22 + #define MDP_INTF_INTR_STATUS(intf) (MDP_INTF_OFF(intf) + 0x1c4) 23 + #define MDP_INTF_INTR_CLEAR(intf) (MDP_INTF_OFF(intf) + 0x1c8) 24 + #define MDP_INTF_TEAR_OFF(intf) (0x6D700 + 0x100 * (intf)) 25 + #define MDP_INTF_INTR_TEAR_EN(intf) (MDP_INTF_TEAR_OFF(intf) + 0x000) 26 + #define MDP_INTF_INTR_TEAR_STATUS(intf) (MDP_INTF_TEAR_OFF(intf) + 0x004) 27 + #define MDP_INTF_INTR_TEAR_CLEAR(intf) (MDP_INTF_TEAR_OFF(intf) + 0x008) 28 + #define MDP_AD4_OFF(ad4) (0x7C000 + 0x1000 * (ad4)) 29 + #define MDP_AD4_INTR_EN_OFF(ad4) (MDP_AD4_OFF(ad4) + 0x41c) 30 + #define MDP_AD4_INTR_CLEAR_OFF(ad4) (MDP_AD4_OFF(ad4) + 0x424) 31 + #define MDP_AD4_INTR_STATUS_OFF(ad4) (MDP_AD4_OFF(ad4) + 0x420) 32 + #define MDP_INTF_REV_7xxx_OFF(intf) (0x34000 + 0x1000 * (intf)) 33 + #define MDP_INTF_REV_7xxx_INTR_EN(intf) (MDP_INTF_REV_7xxx_OFF(intf) + 0x1c0) 34 + #define MDP_INTF_REV_7xxx_INTR_STATUS(intf) (MDP_INTF_REV_7xxx_OFF(intf) + 0x1c4) 35 + #define MDP_INTF_REV_7xxx_INTR_CLEAR(intf) (MDP_INTF_REV_7xxx_OFF(intf) + 0x1c8) 36 + #define MDP_INTF_REV_7xxx_TEAR_OFF(intf) (0x34800 + 0x1000 * (intf)) 37 + #define MDP_INTF_REV_7xxx_INTR_TEAR_EN(intf) (MDP_INTF_REV_7xxx_TEAR_OFF(intf) + 0x000) 38 + #define MDP_INTF_REV_7xxx_INTR_TEAR_STATUS(intf) (MDP_INTF_REV_7xxx_TEAR_OFF(intf) + 0x004) 39 + #define MDP_INTF_REV_7xxx_INTR_TEAR_CLEAR(intf) (MDP_INTF_REV_7xxx_TEAR_OFF(intf) + 0x008) 44 40 45 41 /** 46 42 * struct dpu_intr_reg - array of DPU register sets ··· 57 61 */ 58 62 static const struct dpu_intr_reg dpu_intr_set[] = { 59 63 [MDP_SSPP_TOP0_INTR] = { 60 - MDP_SSPP_TOP0_OFF+INTR_CLEAR, 61 - MDP_SSPP_TOP0_OFF+INTR_EN, 62 - MDP_SSPP_TOP0_OFF+INTR_STATUS 64 + INTR_CLEAR, 65 + INTR_EN, 66 + INTR_STATUS 63 67 }, 64 68 [MDP_SSPP_TOP0_INTR2] = { 65 - MDP_SSPP_TOP0_OFF+INTR2_CLEAR, 66 - MDP_SSPP_TOP0_OFF+INTR2_EN, 67 - MDP_SSPP_TOP0_OFF+INTR2_STATUS 69 + INTR2_CLEAR, 70 + INTR2_EN, 71 + INTR2_STATUS 68 72 }, 69 73 [MDP_SSPP_TOP0_HIST_INTR] = { 70 - MDP_SSPP_TOP0_OFF+HIST_INTR_CLEAR, 71 - MDP_SSPP_TOP0_OFF+HIST_INTR_EN, 72 - MDP_SSPP_TOP0_OFF+HIST_INTR_STATUS 74 + HIST_INTR_CLEAR, 75 + HIST_INTR_EN, 76 + HIST_INTR_STATUS 73 77 }, 74 78 [MDP_INTF0_INTR] = { 75 - MDP_INTF_0_OFF+INTF_INTR_CLEAR, 76 - MDP_INTF_0_OFF+INTF_INTR_EN, 77 - MDP_INTF_0_OFF+INTF_INTR_STATUS 79 + MDP_INTF_INTR_CLEAR(0), 80 + MDP_INTF_INTR_EN(0), 81 + MDP_INTF_INTR_STATUS(0) 78 82 }, 79 83 [MDP_INTF1_INTR] = { 80 - MDP_INTF_1_OFF+INTF_INTR_CLEAR, 81 - MDP_INTF_1_OFF+INTF_INTR_EN, 82 - MDP_INTF_1_OFF+INTF_INTR_STATUS 84 + MDP_INTF_INTR_CLEAR(1), 85 + MDP_INTF_INTR_EN(1), 86 + MDP_INTF_INTR_STATUS(1) 83 87 }, 84 88 [MDP_INTF2_INTR] = { 85 - MDP_INTF_2_OFF+INTF_INTR_CLEAR, 86 - MDP_INTF_2_OFF+INTF_INTR_EN, 87 - MDP_INTF_2_OFF+INTF_INTR_STATUS 89 + MDP_INTF_INTR_CLEAR(2), 90 + MDP_INTF_INTR_EN(2), 91 + MDP_INTF_INTR_STATUS(2) 88 92 }, 89 93 [MDP_INTF3_INTR] = { 90 - MDP_INTF_3_OFF+INTF_INTR_CLEAR, 91 - MDP_INTF_3_OFF+INTF_INTR_EN, 92 - MDP_INTF_3_OFF+INTF_INTR_STATUS 94 + MDP_INTF_INTR_CLEAR(3), 95 + MDP_INTF_INTR_EN(3), 96 + MDP_INTF_INTR_STATUS(3) 93 97 }, 94 98 [MDP_INTF4_INTR] = { 95 - MDP_INTF_4_OFF+INTF_INTR_CLEAR, 96 - MDP_INTF_4_OFF+INTF_INTR_EN, 97 - MDP_INTF_4_OFF+INTF_INTR_STATUS 99 + MDP_INTF_INTR_CLEAR(4), 100 + MDP_INTF_INTR_EN(4), 101 + MDP_INTF_INTR_STATUS(4) 98 102 }, 99 103 [MDP_INTF5_INTR] = { 100 - MDP_INTF_5_OFF+INTF_INTR_CLEAR, 101 - MDP_INTF_5_OFF+INTF_INTR_EN, 102 - MDP_INTF_5_OFF+INTF_INTR_STATUS 104 + MDP_INTF_INTR_CLEAR(5), 105 + MDP_INTF_INTR_EN(5), 106 + MDP_INTF_INTR_STATUS(5) 107 + }, 108 + [MDP_INTF1_TEAR_INTR] = { 109 + MDP_INTF_INTR_TEAR_CLEAR(1), 110 + MDP_INTF_INTR_TEAR_EN(1), 111 + MDP_INTF_INTR_TEAR_STATUS(1) 112 + }, 113 + [MDP_INTF2_TEAR_INTR] = { 114 + MDP_INTF_INTR_TEAR_CLEAR(2), 115 + MDP_INTF_INTR_TEAR_EN(2), 116 + MDP_INTF_INTR_TEAR_STATUS(2) 103 117 }, 104 118 [MDP_AD4_0_INTR] = { 105 - MDP_AD4_0_OFF + MDP_AD4_INTR_CLEAR_OFF, 106 - MDP_AD4_0_OFF + MDP_AD4_INTR_EN_OFF, 107 - MDP_AD4_0_OFF + MDP_AD4_INTR_STATUS_OFF, 119 + MDP_AD4_INTR_CLEAR_OFF(0), 120 + MDP_AD4_INTR_EN_OFF(0), 121 + MDP_AD4_INTR_STATUS_OFF(0), 108 122 }, 109 123 [MDP_AD4_1_INTR] = { 110 - MDP_AD4_1_OFF + MDP_AD4_INTR_CLEAR_OFF, 111 - MDP_AD4_1_OFF + MDP_AD4_INTR_EN_OFF, 112 - MDP_AD4_1_OFF + MDP_AD4_INTR_STATUS_OFF, 124 + MDP_AD4_INTR_CLEAR_OFF(1), 125 + MDP_AD4_INTR_EN_OFF(1), 126 + MDP_AD4_INTR_STATUS_OFF(1), 113 127 }, 114 128 [MDP_INTF0_7xxx_INTR] = { 115 - MDP_INTF_0_OFF_REV_7xxx+INTF_INTR_CLEAR, 116 - MDP_INTF_0_OFF_REV_7xxx+INTF_INTR_EN, 117 - MDP_INTF_0_OFF_REV_7xxx+INTF_INTR_STATUS 129 + MDP_INTF_REV_7xxx_INTR_CLEAR(0), 130 + MDP_INTF_REV_7xxx_INTR_EN(0), 131 + MDP_INTF_REV_7xxx_INTR_STATUS(0) 118 132 }, 119 133 [MDP_INTF1_7xxx_INTR] = { 120 - MDP_INTF_1_OFF_REV_7xxx+INTF_INTR_CLEAR, 121 - MDP_INTF_1_OFF_REV_7xxx+INTF_INTR_EN, 122 - MDP_INTF_1_OFF_REV_7xxx+INTF_INTR_STATUS 134 + MDP_INTF_REV_7xxx_INTR_CLEAR(1), 135 + MDP_INTF_REV_7xxx_INTR_EN(1), 136 + MDP_INTF_REV_7xxx_INTR_STATUS(1) 137 + }, 138 + [MDP_INTF1_7xxx_TEAR_INTR] = { 139 + MDP_INTF_REV_7xxx_INTR_TEAR_CLEAR(1), 140 + MDP_INTF_REV_7xxx_INTR_TEAR_EN(1), 141 + MDP_INTF_REV_7xxx_INTR_TEAR_STATUS(1) 123 142 }, 124 143 [MDP_INTF2_7xxx_INTR] = { 125 - MDP_INTF_2_OFF_REV_7xxx+INTF_INTR_CLEAR, 126 - MDP_INTF_2_OFF_REV_7xxx+INTF_INTR_EN, 127 - MDP_INTF_2_OFF_REV_7xxx+INTF_INTR_STATUS 144 + MDP_INTF_REV_7xxx_INTR_CLEAR(2), 145 + MDP_INTF_REV_7xxx_INTR_EN(2), 146 + MDP_INTF_REV_7xxx_INTR_STATUS(2) 147 + }, 148 + [MDP_INTF2_7xxx_TEAR_INTR] = { 149 + MDP_INTF_REV_7xxx_INTR_TEAR_CLEAR(2), 150 + MDP_INTF_REV_7xxx_INTR_TEAR_EN(2), 151 + MDP_INTF_REV_7xxx_INTR_TEAR_STATUS(2) 128 152 }, 129 153 [MDP_INTF3_7xxx_INTR] = { 130 - MDP_INTF_3_OFF_REV_7xxx+INTF_INTR_CLEAR, 131 - MDP_INTF_3_OFF_REV_7xxx+INTF_INTR_EN, 132 - MDP_INTF_3_OFF_REV_7xxx+INTF_INTR_STATUS 154 + MDP_INTF_REV_7xxx_INTR_CLEAR(3), 155 + MDP_INTF_REV_7xxx_INTR_EN(3), 156 + MDP_INTF_REV_7xxx_INTR_STATUS(3) 133 157 }, 134 158 [MDP_INTF4_7xxx_INTR] = { 135 - MDP_INTF_4_OFF_REV_7xxx+INTF_INTR_CLEAR, 136 - MDP_INTF_4_OFF_REV_7xxx+INTF_INTR_EN, 137 - MDP_INTF_4_OFF_REV_7xxx+INTF_INTR_STATUS 159 + MDP_INTF_REV_7xxx_INTR_CLEAR(4), 160 + MDP_INTF_REV_7xxx_INTR_EN(4), 161 + MDP_INTF_REV_7xxx_INTR_STATUS(4) 138 162 }, 139 163 [MDP_INTF5_7xxx_INTR] = { 140 - MDP_INTF_5_OFF_REV_7xxx+INTF_INTR_CLEAR, 141 - MDP_INTF_5_OFF_REV_7xxx+INTF_INTR_EN, 142 - MDP_INTF_5_OFF_REV_7xxx+INTF_INTR_STATUS 164 + MDP_INTF_REV_7xxx_INTR_CLEAR(5), 165 + MDP_INTF_REV_7xxx_INTR_EN(5), 166 + MDP_INTF_REV_7xxx_INTR_STATUS(5) 143 167 }, 144 168 [MDP_INTF6_7xxx_INTR] = { 145 - MDP_INTF_6_OFF_REV_7xxx+INTF_INTR_CLEAR, 146 - MDP_INTF_6_OFF_REV_7xxx+INTF_INTR_EN, 147 - MDP_INTF_6_OFF_REV_7xxx+INTF_INTR_STATUS 169 + MDP_INTF_REV_7xxx_INTR_CLEAR(6), 170 + MDP_INTF_REV_7xxx_INTR_EN(6), 171 + MDP_INTF_REV_7xxx_INTR_STATUS(6) 148 172 }, 149 173 [MDP_INTF7_7xxx_INTR] = { 150 - MDP_INTF_7_OFF_REV_7xxx+INTF_INTR_CLEAR, 151 - MDP_INTF_7_OFF_REV_7xxx+INTF_INTR_EN, 152 - MDP_INTF_7_OFF_REV_7xxx+INTF_INTR_STATUS 174 + MDP_INTF_REV_7xxx_INTR_CLEAR(7), 175 + MDP_INTF_REV_7xxx_INTR_EN(7), 176 + MDP_INTF_REV_7xxx_INTR_STATUS(7) 153 177 }, 154 178 [MDP_INTF8_7xxx_INTR] = { 155 - MDP_INTF_8_OFF_REV_7xxx+INTF_INTR_CLEAR, 156 - MDP_INTF_8_OFF_REV_7xxx+INTF_INTR_EN, 157 - MDP_INTF_8_OFF_REV_7xxx+INTF_INTR_STATUS 179 + MDP_INTF_REV_7xxx_INTR_CLEAR(8), 180 + MDP_INTF_REV_7xxx_INTR_EN(8), 181 + MDP_INTF_REV_7xxx_INTR_STATUS(8) 158 182 }, 159 183 }; 160 184
+5 -1
drivers/gpu/drm/msm/disp/dpu1/dpu_hw_interrupts.h
··· 23 23 MDP_INTF3_INTR, 24 24 MDP_INTF4_INTR, 25 25 MDP_INTF5_INTR, 26 + MDP_INTF1_TEAR_INTR, 27 + MDP_INTF2_TEAR_INTR, 26 28 MDP_AD4_0_INTR, 27 29 MDP_AD4_1_INTR, 28 30 MDP_INTF0_7xxx_INTR, 29 31 MDP_INTF1_7xxx_INTR, 32 + MDP_INTF1_7xxx_TEAR_INTR, 30 33 MDP_INTF2_7xxx_INTR, 34 + MDP_INTF2_7xxx_TEAR_INTR, 31 35 MDP_INTF3_7xxx_INTR, 32 36 MDP_INTF4_7xxx_INTR, 33 37 MDP_INTF5_7xxx_INTR, ··· 71 67 /** 72 68 * dpu_hw_intr_init(): Initializes the interrupts hw object 73 69 * @addr: mapped register io address of MDP 74 - * @m : pointer to mdss catalog data 70 + * @m: pointer to MDSS catalog data 75 71 */ 76 72 struct dpu_hw_intr *dpu_hw_intr_init(void __iomem *addr, 77 73 const struct dpu_mdss_cfg *m);
+265 -66
drivers/gpu/drm/msm/disp/dpu1/dpu_hw_intf.c
··· 8 8 #include "dpu_hw_catalog.h" 9 9 #include "dpu_hw_intf.h" 10 10 #include "dpu_kms.h" 11 + #include "dpu_trace.h" 12 + 13 + #include <linux/iopoll.h> 11 14 12 15 #define INTF_TIMING_ENGINE_EN 0x000 13 16 #define INTF_CONFIG 0x004 ··· 39 36 #define INTF_CONFIG2 0x060 40 37 #define INTF_DISPLAY_DATA_HCTL 0x064 41 38 #define INTF_ACTIVE_DATA_HCTL 0x068 39 + 40 + #define INTF_DSI_CMD_MODE_TRIGGER_EN 0x084 41 + #define INTF_PANEL_FORMAT 0x090 42 + 42 43 #define INTF_FRAME_LINE_COUNT_EN 0x0A8 43 44 #define INTF_FRAME_COUNT 0x0AC 44 - #define INTF_LINE_COUNT 0x0B0 45 + #define INTF_LINE_COUNT 0x0B0 45 46 46 - #define INTF_DEFLICKER_CONFIG 0x0F0 47 - #define INTF_DEFLICKER_STRNG_COEFF 0x0F4 48 - #define INTF_DEFLICKER_WEAK_COEFF 0x0F8 47 + #define INTF_DEFLICKER_CONFIG 0x0F0 48 + #define INTF_DEFLICKER_STRNG_COEFF 0x0F4 49 + #define INTF_DEFLICKER_WEAK_COEFF 0x0F8 49 50 50 - #define INTF_DSI_CMD_MODE_TRIGGER_EN 0x084 51 - #define INTF_PANEL_FORMAT 0x090 52 - #define INTF_TPG_ENABLE 0x100 53 - #define INTF_TPG_MAIN_CONTROL 0x104 54 - #define INTF_TPG_VIDEO_CONFIG 0x108 55 - #define INTF_TPG_COMPONENT_LIMITS 0x10C 56 - #define INTF_TPG_RECTANGLE 0x110 57 - #define INTF_TPG_INITIAL_VALUE 0x114 58 - #define INTF_TPG_BLK_WHITE_PATTERN_FRAMES 0x118 59 - #define INTF_TPG_RGB_MAPPING 0x11C 60 - #define INTF_PROG_FETCH_START 0x170 61 - #define INTF_PROG_ROT_START 0x174 62 - #define INTF_MUX 0x25C 63 - #define INTF_STATUS 0x26C 51 + #define INTF_TPG_ENABLE 0x100 52 + #define INTF_TPG_MAIN_CONTROL 0x104 53 + #define INTF_TPG_VIDEO_CONFIG 0x108 54 + #define INTF_TPG_COMPONENT_LIMITS 0x10C 55 + #define INTF_TPG_RECTANGLE 0x110 56 + #define INTF_TPG_INITIAL_VALUE 0x114 57 + #define INTF_TPG_BLK_WHITE_PATTERN_FRAMES 0x118 58 + #define INTF_TPG_RGB_MAPPING 0x11C 59 + #define INTF_PROG_FETCH_START 0x170 60 + #define INTF_PROG_ROT_START 0x174 61 + 62 + #define INTF_MISR_CTRL 0x180 63 + #define INTF_MISR_SIGNATURE 0x184 64 + 65 + #define INTF_MUX 0x25C 66 + #define INTF_STATUS 0x26C 67 + #define INTF_AVR_CONTROL 0x270 68 + #define INTF_AVR_MODE 0x274 69 + #define INTF_AVR_TRIGGER 0x278 70 + #define INTF_AVR_VTOTAL 0x27C 71 + #define INTF_TEAR_MDP_VSYNC_SEL 0x280 72 + #define INTF_TEAR_TEAR_CHECK_EN 0x284 73 + #define INTF_TEAR_SYNC_CONFIG_VSYNC 0x288 74 + #define INTF_TEAR_SYNC_CONFIG_HEIGHT 0x28C 75 + #define INTF_TEAR_SYNC_WRCOUNT 0x290 76 + #define INTF_TEAR_VSYNC_INIT_VAL 0x294 77 + #define INTF_TEAR_INT_COUNT_VAL 0x298 78 + #define INTF_TEAR_SYNC_THRESH 0x29C 79 + #define INTF_TEAR_START_POS 0x2A0 80 + #define INTF_TEAR_RD_PTR_IRQ 0x2A4 81 + #define INTF_TEAR_WR_PTR_IRQ 0x2A8 82 + #define INTF_TEAR_OUT_LINE_COUNT 0x2AC 83 + #define INTF_TEAR_LINE_COUNT 0x2B0 84 + #define INTF_TEAR_AUTOREFRESH_CONFIG 0x2B4 64 85 65 86 #define INTF_CFG_ACTIVE_H_EN BIT(29) 66 87 #define INTF_CFG_ACTIVE_V_EN BIT(30) 67 88 68 89 #define INTF_CFG2_DATABUS_WIDEN BIT(0) 69 90 #define INTF_CFG2_DATA_HCTL_EN BIT(4) 91 + #define INTF_CFG2_DCE_DATA_COMPRESS BIT(12) 70 92 71 - #define INTF_MISR_CTRL 0x180 72 - #define INTF_MISR_SIGNATURE 0x184 73 - 74 - static const struct dpu_intf_cfg *_intf_offset(enum dpu_intf intf, 75 - const struct dpu_mdss_cfg *m, 76 - void __iomem *addr, 77 - struct dpu_hw_blk_reg_map *b) 78 - { 79 - int i; 80 - 81 - for (i = 0; i < m->intf_count; i++) { 82 - if ((intf == m->intf[i].id) && 83 - (m->intf[i].type != INTF_NONE)) { 84 - b->blk_addr = addr + m->intf[i].base; 85 - b->log_mask = DPU_DBG_MASK_INTF; 86 - return &m->intf[i]; 87 - } 88 - } 89 - 90 - return ERR_PTR(-EINVAL); 91 - } 92 93 93 94 static void dpu_hw_intf_setup_timing_engine(struct dpu_hw_intf *ctx, 94 95 const struct intf_timing_params *p, ··· 106 99 u32 active_h_start, active_h_end; 107 100 u32 active_v_start, active_v_end; 108 101 u32 active_hctl, display_hctl, hsync_ctl; 109 - u32 polarity_ctl, den_polarity, hsync_polarity, vsync_polarity; 102 + u32 polarity_ctl, den_polarity; 110 103 u32 panel_format; 111 104 u32 intf_cfg, intf_cfg2 = 0; 112 105 u32 display_data_hctl = 0, active_data_hctl = 0; ··· 193 186 } 194 187 195 188 den_polarity = 0; 196 - if (ctx->cap->type == INTF_HDMI) { 197 - hsync_polarity = p->yres >= 720 ? 0 : 1; 198 - vsync_polarity = p->yres >= 720 ? 0 : 1; 199 - } else if (ctx->cap->type == INTF_DP) { 200 - hsync_polarity = p->hsync_polarity; 201 - vsync_polarity = p->vsync_polarity; 202 - } else { 203 - hsync_polarity = 0; 204 - vsync_polarity = 0; 205 - } 206 189 polarity_ctl = (den_polarity << 2) | /* DEN Polarity */ 207 - (vsync_polarity << 1) | /* VSYNC Polarity */ 208 - (hsync_polarity << 0); /* HSYNC Polarity */ 190 + (p->vsync_polarity << 1) | /* VSYNC Polarity */ 191 + (p->hsync_polarity << 0); /* HSYNC Polarity */ 209 192 210 193 if (!DPU_FORMAT_IS_YUV(fmt)) 211 194 panel_format = (fmt->bits[C0_G_Y] | ··· 268 271 269 272 static void dpu_hw_intf_bind_pingpong_blk( 270 273 struct dpu_hw_intf *intf, 271 - bool enable, 272 274 const enum dpu_pingpong pp) 273 275 { 274 276 struct dpu_hw_blk_reg_map *c = &intf->hw; ··· 276 280 mux_cfg = DPU_REG_READ(c, INTF_MUX); 277 281 mux_cfg &= ~0xf; 278 282 279 - if (enable) 283 + if (pp) 280 284 mux_cfg |= (pp - PINGPONG_0) & 0x7; 281 285 else 282 286 mux_cfg |= 0xf; ··· 328 332 return dpu_hw_collect_misr(&intf->hw, INTF_MISR_CTRL, INTF_MISR_SIGNATURE, misr_value); 329 333 } 330 334 335 + static int dpu_hw_intf_enable_te(struct dpu_hw_intf *intf, 336 + struct dpu_hw_tear_check *te) 337 + { 338 + struct dpu_hw_blk_reg_map *c; 339 + int cfg; 340 + 341 + if (!intf) 342 + return -EINVAL; 343 + 344 + c = &intf->hw; 345 + 346 + cfg = BIT(19); /* VSYNC_COUNTER_EN */ 347 + if (te->hw_vsync_mode) 348 + cfg |= BIT(20); 349 + 350 + cfg |= te->vsync_count; 351 + 352 + DPU_REG_WRITE(c, INTF_TEAR_SYNC_CONFIG_VSYNC, cfg); 353 + DPU_REG_WRITE(c, INTF_TEAR_SYNC_CONFIG_HEIGHT, te->sync_cfg_height); 354 + DPU_REG_WRITE(c, INTF_TEAR_VSYNC_INIT_VAL, te->vsync_init_val); 355 + DPU_REG_WRITE(c, INTF_TEAR_RD_PTR_IRQ, te->rd_ptr_irq); 356 + DPU_REG_WRITE(c, INTF_TEAR_START_POS, te->start_pos); 357 + DPU_REG_WRITE(c, INTF_TEAR_SYNC_THRESH, 358 + ((te->sync_threshold_continue << 16) | 359 + te->sync_threshold_start)); 360 + DPU_REG_WRITE(c, INTF_TEAR_SYNC_WRCOUNT, 361 + (te->start_pos + te->sync_threshold_start + 1)); 362 + 363 + DPU_REG_WRITE(c, INTF_TEAR_TEAR_CHECK_EN, 1); 364 + 365 + return 0; 366 + } 367 + 368 + static void dpu_hw_intf_setup_autorefresh_config(struct dpu_hw_intf *intf, 369 + u32 frame_count, bool enable) 370 + { 371 + struct dpu_hw_blk_reg_map *c; 372 + u32 refresh_cfg; 373 + 374 + c = &intf->hw; 375 + refresh_cfg = DPU_REG_READ(c, INTF_TEAR_AUTOREFRESH_CONFIG); 376 + if (enable) 377 + refresh_cfg = BIT(31) | frame_count; 378 + else 379 + refresh_cfg &= ~BIT(31); 380 + 381 + DPU_REG_WRITE(c, INTF_TEAR_AUTOREFRESH_CONFIG, refresh_cfg); 382 + } 383 + 384 + /* 385 + * dpu_hw_intf_get_autorefresh_config - Get autorefresh config from HW 386 + * @intf: DPU intf structure 387 + * @frame_count: Used to return the current frame count from hw 388 + * 389 + * Returns: True if autorefresh enabled, false if disabled. 390 + */ 391 + static bool dpu_hw_intf_get_autorefresh_config(struct dpu_hw_intf *intf, 392 + u32 *frame_count) 393 + { 394 + u32 val = DPU_REG_READ(&intf->hw, INTF_TEAR_AUTOREFRESH_CONFIG); 395 + 396 + if (frame_count != NULL) 397 + *frame_count = val & 0xffff; 398 + return !!((val & BIT(31)) >> 31); 399 + } 400 + 401 + static int dpu_hw_intf_disable_te(struct dpu_hw_intf *intf) 402 + { 403 + struct dpu_hw_blk_reg_map *c; 404 + 405 + if (!intf) 406 + return -EINVAL; 407 + 408 + c = &intf->hw; 409 + DPU_REG_WRITE(c, INTF_TEAR_TEAR_CHECK_EN, 0); 410 + return 0; 411 + } 412 + 413 + static int dpu_hw_intf_connect_external_te(struct dpu_hw_intf *intf, 414 + bool enable_external_te) 415 + { 416 + struct dpu_hw_blk_reg_map *c = &intf->hw; 417 + u32 cfg; 418 + int orig; 419 + 420 + if (!intf) 421 + return -EINVAL; 422 + 423 + c = &intf->hw; 424 + cfg = DPU_REG_READ(c, INTF_TEAR_SYNC_CONFIG_VSYNC); 425 + orig = (bool)(cfg & BIT(20)); 426 + if (enable_external_te) 427 + cfg |= BIT(20); 428 + else 429 + cfg &= ~BIT(20); 430 + DPU_REG_WRITE(c, INTF_TEAR_SYNC_CONFIG_VSYNC, cfg); 431 + trace_dpu_intf_connect_ext_te(intf->idx - INTF_0, cfg); 432 + 433 + return orig; 434 + } 435 + 436 + static int dpu_hw_intf_get_vsync_info(struct dpu_hw_intf *intf, 437 + struct dpu_hw_pp_vsync_info *info) 438 + { 439 + struct dpu_hw_blk_reg_map *c = &intf->hw; 440 + u32 val; 441 + 442 + if (!intf || !info) 443 + return -EINVAL; 444 + 445 + c = &intf->hw; 446 + 447 + val = DPU_REG_READ(c, INTF_TEAR_VSYNC_INIT_VAL); 448 + info->rd_ptr_init_val = val & 0xffff; 449 + 450 + val = DPU_REG_READ(c, INTF_TEAR_INT_COUNT_VAL); 451 + info->rd_ptr_frame_count = (val & 0xffff0000) >> 16; 452 + info->rd_ptr_line_count = val & 0xffff; 453 + 454 + val = DPU_REG_READ(c, INTF_TEAR_LINE_COUNT); 455 + info->wr_ptr_line_count = val & 0xffff; 456 + 457 + val = DPU_REG_READ(c, INTF_FRAME_COUNT); 458 + info->intf_frame_count = val; 459 + 460 + return 0; 461 + } 462 + 463 + static void dpu_hw_intf_vsync_sel(struct dpu_hw_intf *intf, 464 + u32 vsync_source) 465 + { 466 + struct dpu_hw_blk_reg_map *c; 467 + 468 + if (!intf) 469 + return; 470 + 471 + c = &intf->hw; 472 + 473 + DPU_REG_WRITE(c, INTF_TEAR_MDP_VSYNC_SEL, (vsync_source & 0xf)); 474 + } 475 + 476 + static void dpu_hw_intf_disable_autorefresh(struct dpu_hw_intf *intf, 477 + uint32_t encoder_id, u16 vdisplay) 478 + { 479 + struct dpu_hw_pp_vsync_info info; 480 + int trial = 0; 481 + 482 + /* If autorefresh is already disabled, we have nothing to do */ 483 + if (!dpu_hw_intf_get_autorefresh_config(intf, NULL)) 484 + return; 485 + 486 + /* 487 + * If autorefresh is enabled, disable it and make sure it is safe to 488 + * proceed with current frame commit/push. Sequence followed is, 489 + * 1. Disable TE 490 + * 2. Disable autorefresh config 491 + * 4. Poll for frame transfer ongoing to be false 492 + * 5. Enable TE back 493 + */ 494 + 495 + dpu_hw_intf_connect_external_te(intf, false); 496 + dpu_hw_intf_setup_autorefresh_config(intf, 0, false); 497 + 498 + do { 499 + udelay(DPU_ENC_MAX_POLL_TIMEOUT_US); 500 + if ((trial * DPU_ENC_MAX_POLL_TIMEOUT_US) 501 + > (KICKOFF_TIMEOUT_MS * USEC_PER_MSEC)) { 502 + DPU_ERROR("enc%d intf%d disable autorefresh failed\n", 503 + encoder_id, intf->idx - INTF_0); 504 + break; 505 + } 506 + 507 + trial++; 508 + 509 + dpu_hw_intf_get_vsync_info(intf, &info); 510 + } while (info.wr_ptr_line_count > 0 && 511 + info.wr_ptr_line_count < vdisplay); 512 + 513 + dpu_hw_intf_connect_external_te(intf, true); 514 + 515 + DPU_DEBUG("enc%d intf%d disabled autorefresh\n", 516 + encoder_id, intf->idx - INTF_0); 517 + 518 + } 519 + 520 + static void dpu_hw_intf_enable_compression(struct dpu_hw_intf *ctx) 521 + { 522 + u32 intf_cfg2 = DPU_REG_READ(&ctx->hw, INTF_CONFIG2); 523 + 524 + intf_cfg2 |= INTF_CFG2_DCE_DATA_COMPRESS; 525 + 526 + DPU_REG_WRITE(&ctx->hw, INTF_CONFIG2, intf_cfg2); 527 + } 528 + 331 529 static void _setup_intf_ops(struct dpu_hw_intf_ops *ops, 332 530 unsigned long cap) 333 531 { ··· 534 344 ops->bind_pingpong_blk = dpu_hw_intf_bind_pingpong_blk; 535 345 ops->setup_misr = dpu_hw_intf_setup_misr; 536 346 ops->collect_misr = dpu_hw_intf_collect_misr; 347 + 348 + if (cap & BIT(DPU_INTF_TE)) { 349 + ops->enable_tearcheck = dpu_hw_intf_enable_te; 350 + ops->disable_tearcheck = dpu_hw_intf_disable_te; 351 + ops->connect_external_te = dpu_hw_intf_connect_external_te; 352 + ops->vsync_sel = dpu_hw_intf_vsync_sel; 353 + ops->disable_autorefresh = dpu_hw_intf_disable_autorefresh; 354 + } 355 + 356 + if (cap & BIT(DPU_INTF_DATA_COMPRESS)) 357 + ops->enable_compression = dpu_hw_intf_enable_compression; 537 358 } 538 359 539 - struct dpu_hw_intf *dpu_hw_intf_init(enum dpu_intf idx, 540 - void __iomem *addr, 541 - const struct dpu_mdss_cfg *m) 360 + struct dpu_hw_intf *dpu_hw_intf_init(const struct dpu_intf_cfg *cfg, 361 + void __iomem *addr) 542 362 { 543 363 struct dpu_hw_intf *c; 544 - const struct dpu_intf_cfg *cfg; 364 + 365 + if (cfg->type == INTF_NONE) { 366 + DPU_DEBUG("Skip intf %d with type NONE\n", cfg->id - INTF_0); 367 + return NULL; 368 + } 545 369 546 370 c = kzalloc(sizeof(*c), GFP_KERNEL); 547 371 if (!c) 548 372 return ERR_PTR(-ENOMEM); 549 373 550 - cfg = _intf_offset(idx, m, addr, &c->hw); 551 - if (IS_ERR_OR_NULL(cfg)) { 552 - kfree(c); 553 - pr_err("failed to create dpu_hw_intf %d\n", idx); 554 - return ERR_PTR(-EINVAL); 555 - } 374 + c->hw.blk_addr = addr + cfg->base; 375 + c->hw.log_mask = DPU_DBG_MASK_INTF; 556 376 557 377 /* 558 378 * Assign ops 559 379 */ 560 - c->idx = idx; 380 + c->idx = cfg->id; 561 381 c->cap = cfg; 562 - c->mdss = m; 563 382 _setup_intf_ops(&c->ops, c->cap->features); 564 383 565 384 return c;
+33 -9
drivers/gpu/drm/msm/disp/dpu1/dpu_hw_intf.h
··· 60 60 * feed pixels to this interface 61 61 * @setup_misr: enable/disable MISR 62 62 * @collect_misr: read MISR signature 63 + * @enable_tearcheck: Enables vsync generation and sets up init value of read 64 + * pointer and programs the tear check configuration 65 + * @disable_tearcheck: Disables tearcheck block 66 + * @connect_external_te: Read, modify, write to either set or clear listening to external TE 67 + * Return: 1 if TE was originally connected, 0 if not, or -ERROR 68 + * @get_vsync_info: Provides the programmed and current line_count 69 + * @setup_autorefresh: Configure and enable the autorefresh config 70 + * @get_autorefresh: Retrieve autorefresh config from hardware 71 + * Return: 0 on success, -ETIMEDOUT on timeout 72 + * @vsync_sel: Select vsync signal for tear-effect configuration 73 + * @enable_compression: Enable data compression 63 74 */ 64 75 struct dpu_hw_intf_ops { 65 76 void (*setup_timing_gen)(struct dpu_hw_intf *intf, ··· 89 78 u32 (*get_line_count)(struct dpu_hw_intf *intf); 90 79 91 80 void (*bind_pingpong_blk)(struct dpu_hw_intf *intf, 92 - bool enable, 93 81 const enum dpu_pingpong pp); 94 82 void (*setup_misr)(struct dpu_hw_intf *intf, bool enable, u32 frame_count); 95 83 int (*collect_misr)(struct dpu_hw_intf *intf, u32 *misr_value); 84 + 85 + // Tearcheck on INTF since DPU 5.0.0 86 + 87 + int (*enable_tearcheck)(struct dpu_hw_intf *intf, struct dpu_hw_tear_check *cfg); 88 + 89 + int (*disable_tearcheck)(struct dpu_hw_intf *intf); 90 + 91 + int (*connect_external_te)(struct dpu_hw_intf *intf, bool enable_external_te); 92 + 93 + void (*vsync_sel)(struct dpu_hw_intf *intf, u32 vsync_source); 94 + 95 + /** 96 + * Disable autorefresh if enabled 97 + */ 98 + void (*disable_autorefresh)(struct dpu_hw_intf *intf, uint32_t encoder_id, u16 vdisplay); 99 + 100 + void (*enable_compression)(struct dpu_hw_intf *intf); 96 101 }; 97 102 98 103 struct dpu_hw_intf { ··· 117 90 /* intf */ 118 91 enum dpu_intf idx; 119 92 const struct dpu_intf_cfg *cap; 120 - const struct dpu_mdss_cfg *mdss; 121 93 122 94 /* ops */ 123 95 struct dpu_hw_intf_ops ops; 124 96 }; 125 97 126 98 /** 127 - * dpu_hw_intf_init(): Initializes the intf driver for the passed 128 - * interface idx. 129 - * @idx: interface index for which driver object is required 99 + * dpu_hw_intf_init() - Initializes the INTF driver for the passed 100 + * interface catalog entry. 101 + * @cfg: interface catalog entry for which driver object is required 130 102 * @addr: mapped register io address of MDP 131 - * @m : pointer to mdss catalog data 132 103 */ 133 - struct dpu_hw_intf *dpu_hw_intf_init(enum dpu_intf idx, 134 - void __iomem *addr, 135 - const struct dpu_mdss_cfg *m); 104 + struct dpu_hw_intf *dpu_hw_intf_init(const struct dpu_intf_cfg *cfg, 105 + void __iomem *addr); 136 106 137 107 /** 138 108 * dpu_hw_intf_destroy(): Destroys INTF driver context
+12 -31
drivers/gpu/drm/msm/disp/dpu1/dpu_hw_lm.c
··· 30 30 #define LM_MISR_SIGNATURE 0x314 31 31 32 32 33 - static const struct dpu_lm_cfg *_lm_offset(enum dpu_lm mixer, 34 - const struct dpu_mdss_cfg *m, 35 - void __iomem *addr, 36 - struct dpu_hw_blk_reg_map *b) 37 - { 38 - int i; 39 - 40 - for (i = 0; i < m->mixer_count; i++) { 41 - if (mixer == m->mixer[i].id) { 42 - b->blk_addr = addr + m->mixer[i].base; 43 - b->log_mask = DPU_DBG_MASK_LM; 44 - return &m->mixer[i]; 45 - } 46 - } 47 - 48 - return ERR_PTR(-ENOMEM); 49 - } 50 - 51 33 /** 52 34 * _stage_offset(): returns the relative offset of the blend registers 53 35 * for the stage to be setup ··· 142 160 DPU_REG_WRITE(c, LM_OP_MODE, op_mode); 143 161 } 144 162 145 - static void _setup_mixer_ops(const struct dpu_mdss_cfg *m, 146 - struct dpu_hw_lm_ops *ops, 163 + static void _setup_mixer_ops(struct dpu_hw_lm_ops *ops, 147 164 unsigned long features) 148 165 { 149 166 ops->setup_mixer_out = dpu_hw_lm_setup_out; ··· 156 175 ops->collect_misr = dpu_hw_lm_collect_misr; 157 176 } 158 177 159 - struct dpu_hw_mixer *dpu_hw_lm_init(enum dpu_lm idx, 160 - void __iomem *addr, 161 - const struct dpu_mdss_cfg *m) 178 + struct dpu_hw_mixer *dpu_hw_lm_init(const struct dpu_lm_cfg *cfg, 179 + void __iomem *addr) 162 180 { 163 181 struct dpu_hw_mixer *c; 164 - const struct dpu_lm_cfg *cfg; 182 + 183 + if (cfg->pingpong == PINGPONG_NONE) { 184 + DPU_DEBUG("skip mixer %d without pingpong\n", cfg->id); 185 + return NULL; 186 + } 165 187 166 188 c = kzalloc(sizeof(*c), GFP_KERNEL); 167 189 if (!c) 168 190 return ERR_PTR(-ENOMEM); 169 191 170 - cfg = _lm_offset(idx, m, addr, &c->hw); 171 - if (IS_ERR_OR_NULL(cfg)) { 172 - kfree(c); 173 - return ERR_PTR(-EINVAL); 174 - } 192 + c->hw.blk_addr = addr + cfg->base; 193 + c->hw.log_mask = DPU_DBG_MASK_LM; 175 194 176 195 /* Assign ops */ 177 - c->idx = idx; 196 + c->idx = cfg->id; 178 197 c->cap = cfg; 179 - _setup_mixer_ops(m, &c->ops, c->cap->features); 198 + _setup_mixer_ops(&c->ops, c->cap->features); 180 199 181 200 return c; 182 201 }
+4 -6
drivers/gpu/drm/msm/disp/dpu1/dpu_hw_lm.h
··· 93 93 } 94 94 95 95 /** 96 - * dpu_hw_lm_init(): Initializes the mixer hw driver object. 96 + * dpu_hw_lm_init() - Initializes the mixer hw driver object. 97 97 * should be called once before accessing every mixer. 98 - * @idx: mixer index for which driver object is required 98 + * @cfg: mixer catalog entry for which driver object is required 99 99 * @addr: mapped register io address of MDP 100 - * @m : pointer to mdss catalog data 101 100 */ 102 - struct dpu_hw_mixer *dpu_hw_lm_init(enum dpu_lm idx, 103 - void __iomem *addr, 104 - const struct dpu_mdss_cfg *m); 101 + struct dpu_hw_mixer *dpu_hw_lm_init(const struct dpu_lm_cfg *cfg, 102 + void __iomem *addr); 105 103 106 104 /** 107 105 * dpu_hw_lm_destroy(): Destroys layer mixer driver context
+50 -1
drivers/gpu/drm/msm/disp/dpu1/dpu_hw_mdss.h
··· 191 191 }; 192 192 193 193 enum dpu_pingpong { 194 - PINGPONG_0 = 1, 194 + PINGPONG_NONE, 195 + PINGPONG_0, 195 196 PINGPONG_1, 196 197 PINGPONG_2, 197 198 PINGPONG_3, ··· 463 462 #define DPU_DBG_MASK_ROT (1 << 9) 464 463 #define DPU_DBG_MASK_DSPP (1 << 10) 465 464 #define DPU_DBG_MASK_DSC (1 << 11) 465 + 466 + /** 467 + * struct dpu_hw_tear_check - Struct contains parameters to configure 468 + * tear-effect module. This structure is used to configure tear-check 469 + * logic present either in ping-pong or in interface module. 470 + * @vsync_count: Ratio of MDP VSYNC clk freq(Hz) to refresh rate divided 471 + * by no of lines 472 + * @sync_cfg_height: Total vertical lines (display height - 1) 473 + * @vsync_init_val: Init value to which the read pointer gets loaded at 474 + * vsync edge 475 + * @sync_threshold_start: Read pointer threshold start ROI for write operation 476 + * @sync_threshold_continue: The minimum number of lines the write pointer 477 + * needs to be above the read pointer 478 + * @start_pos: The position from which the start_threshold value is added 479 + * @rd_ptr_irq: The read pointer line at which interrupt has to be generated 480 + * @hw_vsync_mode: Sync with external frame sync input 481 + */ 482 + struct dpu_hw_tear_check { 483 + /* 484 + * This is ratio of MDP VSYNC clk freq(Hz) to 485 + * refresh rate divided by no of lines 486 + */ 487 + u32 vsync_count; 488 + u32 sync_cfg_height; 489 + u32 vsync_init_val; 490 + u32 sync_threshold_start; 491 + u32 sync_threshold_continue; 492 + u32 start_pos; 493 + u32 rd_ptr_irq; 494 + u8 hw_vsync_mode; 495 + }; 496 + 497 + /** 498 + * struct dpu_hw_pp_vsync_info - Struct contains parameters to configure 499 + * read and write pointers for command mode panels 500 + * @rd_ptr_init_val: Value of rd pointer at vsync edge 501 + * @rd_ptr_frame_count: Num frames sent since enabling interface 502 + * @rd_ptr_line_count: Current line on panel (rd ptr) 503 + * @wr_ptr_line_count: Current line within pp fifo (wr ptr) 504 + * @intf_frame_count: Frames read from intf 505 + */ 506 + struct dpu_hw_pp_vsync_info { 507 + u32 rd_ptr_init_val; 508 + u32 rd_ptr_frame_count; 509 + u32 rd_ptr_line_count; 510 + u32 wr_ptr_line_count; 511 + u32 intf_frame_count; 512 + }; 466 513 467 514 #endif /* _DPU_HW_MDSS_H */
+5 -28
drivers/gpu/drm/msm/disp/dpu1/dpu_hw_merge3d.c
··· 14 14 #define MERGE_3D_MUX 0x000 15 15 #define MERGE_3D_MODE 0x004 16 16 17 - static const struct dpu_merge_3d_cfg *_merge_3d_offset(enum dpu_merge_3d idx, 18 - const struct dpu_mdss_cfg *m, 19 - void __iomem *addr, 20 - struct dpu_hw_blk_reg_map *b) 21 - { 22 - int i; 23 - 24 - for (i = 0; i < m->merge_3d_count; i++) { 25 - if (idx == m->merge_3d[i].id) { 26 - b->blk_addr = addr + m->merge_3d[i].base; 27 - b->log_mask = DPU_DBG_MASK_PINGPONG; 28 - return &m->merge_3d[i]; 29 - } 30 - } 31 - 32 - return ERR_PTR(-EINVAL); 33 - } 34 - 35 17 static void dpu_hw_merge_3d_setup_3d_mode(struct dpu_hw_merge_3d *merge_3d, 36 18 enum dpu_3d_blend_mode mode_3d) 37 19 { ··· 37 55 c->ops.setup_3d_mode = dpu_hw_merge_3d_setup_3d_mode; 38 56 }; 39 57 40 - struct dpu_hw_merge_3d *dpu_hw_merge_3d_init(enum dpu_merge_3d idx, 41 - void __iomem *addr, 42 - const struct dpu_mdss_cfg *m) 58 + struct dpu_hw_merge_3d *dpu_hw_merge_3d_init(const struct dpu_merge_3d_cfg *cfg, 59 + void __iomem *addr) 43 60 { 44 61 struct dpu_hw_merge_3d *c; 45 - const struct dpu_merge_3d_cfg *cfg; 46 62 47 63 c = kzalloc(sizeof(*c), GFP_KERNEL); 48 64 if (!c) 49 65 return ERR_PTR(-ENOMEM); 50 66 51 - cfg = _merge_3d_offset(idx, m, addr, &c->hw); 52 - if (IS_ERR_OR_NULL(cfg)) { 53 - kfree(c); 54 - return ERR_PTR(-EINVAL); 55 - } 67 + c->hw.blk_addr = addr + cfg->base; 68 + c->hw.log_mask = DPU_DBG_MASK_PINGPONG; 56 69 57 - c->idx = idx; 70 + c->idx = cfg->id; 58 71 c->caps = cfg; 59 72 _setup_merge_3d_ops(c, c->caps->features); 60 73
+6 -8
drivers/gpu/drm/msm/disp/dpu1/dpu_hw_merge3d.h
··· 46 46 } 47 47 48 48 /** 49 - * dpu_hw_merge_3d_init - initializes the merge_3d driver for the passed 50 - * merge_3d idx. 51 - * @idx: Pingpong index for which driver object is required 49 + * dpu_hw_merge_3d_init() - Initializes the merge_3d driver for the passed 50 + * merge3d catalog entry. 51 + * @cfg: Pingpong catalog entry for which driver object is required 52 52 * @addr: Mapped register io address of MDP 53 - * @m: Pointer to mdss catalog data 54 - * Returns: Error code or allocated dpu_hw_merge_3d context 53 + * Return: Error code or allocated dpu_hw_merge_3d context 55 54 */ 56 - struct dpu_hw_merge_3d *dpu_hw_merge_3d_init(enum dpu_merge_3d idx, 57 - void __iomem *addr, 58 - const struct dpu_mdss_cfg *m); 55 + struct dpu_hw_merge_3d *dpu_hw_merge_3d_init(const struct dpu_merge_3d_cfg *cfg, 56 + void __iomem *addr); 59 57 60 58 /** 61 59 * dpu_hw_merge_3d_destroy - destroys merge_3d driver context
+66 -59
drivers/gpu/drm/msm/disp/dpu1/dpu_hw_pingpong.c
··· 42 42 0, 0, 0, 0, 0, 0, 0, 1, 2 43 43 }; 44 44 45 - static const struct dpu_pingpong_cfg *_pingpong_offset(enum dpu_pingpong pp, 46 - const struct dpu_mdss_cfg *m, 47 - void __iomem *addr, 48 - struct dpu_hw_blk_reg_map *b) 49 - { 50 - int i; 51 - 52 - for (i = 0; i < m->pingpong_count; i++) { 53 - if (pp == m->pingpong[i].id) { 54 - b->blk_addr = addr + m->pingpong[i].base; 55 - b->log_mask = DPU_DBG_MASK_PINGPONG; 56 - return &m->pingpong[i]; 57 - } 58 - } 59 - 60 - return ERR_PTR(-EINVAL); 61 - } 62 - 63 45 static void dpu_hw_pp_setup_dither(struct dpu_hw_pingpong *pp, 64 46 struct dpu_hw_dither_cfg *cfg) 65 47 { ··· 73 91 DPU_REG_WRITE(c, base + PP_DITHER_EN, 1); 74 92 } 75 93 76 - static int dpu_hw_pp_setup_te_config(struct dpu_hw_pingpong *pp, 94 + static int dpu_hw_pp_enable_te(struct dpu_hw_pingpong *pp, 77 95 struct dpu_hw_tear_check *te) 78 96 { 79 97 struct dpu_hw_blk_reg_map *c; ··· 99 117 te->sync_threshold_start)); 100 118 DPU_REG_WRITE(c, PP_SYNC_WRCOUNT, 101 119 (te->start_pos + te->sync_threshold_start + 1)); 120 + 121 + DPU_REG_WRITE(c, PP_TEAR_CHECK_EN, 1); 102 122 103 123 return 0; 104 124 } ··· 128 144 return !!((val & BIT(31)) >> 31); 129 145 } 130 146 131 - static int dpu_hw_pp_poll_timeout_wr_ptr(struct dpu_hw_pingpong *pp, 132 - u32 timeout_us) 133 - { 134 - struct dpu_hw_blk_reg_map *c; 135 - u32 val; 136 - int rc; 137 - 138 - if (!pp) 139 - return -EINVAL; 140 - 141 - c = &pp->hw; 142 - rc = readl_poll_timeout(c->blk_addr + PP_LINE_COUNT, 143 - val, (val & 0xffff) >= 1, 10, timeout_us); 144 - 145 - return rc; 146 - } 147 - 148 - static int dpu_hw_pp_enable_te(struct dpu_hw_pingpong *pp, bool enable) 147 + static int dpu_hw_pp_disable_te(struct dpu_hw_pingpong *pp) 149 148 { 150 149 struct dpu_hw_blk_reg_map *c; 151 150 ··· 136 169 return -EINVAL; 137 170 c = &pp->hw; 138 171 139 - DPU_REG_WRITE(c, PP_TEAR_CHECK_EN, enable); 172 + DPU_REG_WRITE(c, PP_TEAR_CHECK_EN, 0); 140 173 return 0; 141 174 } 142 175 ··· 212 245 return line; 213 246 } 214 247 248 + static void dpu_hw_pp_disable_autorefresh(struct dpu_hw_pingpong *pp, 249 + uint32_t encoder_id, u16 vdisplay) 250 + { 251 + struct dpu_hw_pp_vsync_info info; 252 + int trial = 0; 253 + 254 + /* If autorefresh is already disabled, we have nothing to do */ 255 + if (!dpu_hw_pp_get_autorefresh_config(pp, NULL)) 256 + return; 257 + 258 + /* 259 + * If autorefresh is enabled, disable it and make sure it is safe to 260 + * proceed with current frame commit/push. Sequence followed is, 261 + * 1. Disable TE 262 + * 2. Disable autorefresh config 263 + * 4. Poll for frame transfer ongoing to be false 264 + * 5. Enable TE back 265 + */ 266 + 267 + dpu_hw_pp_connect_external_te(pp, false); 268 + dpu_hw_pp_setup_autorefresh_config(pp, 0, false); 269 + 270 + do { 271 + udelay(DPU_ENC_MAX_POLL_TIMEOUT_US); 272 + if ((trial * DPU_ENC_MAX_POLL_TIMEOUT_US) 273 + > (KICKOFF_TIMEOUT_MS * USEC_PER_MSEC)) { 274 + DPU_ERROR("enc%d pp%d disable autorefresh failed\n", 275 + encoder_id, pp->idx - PINGPONG_0); 276 + break; 277 + } 278 + 279 + trial++; 280 + 281 + dpu_hw_pp_get_vsync_info(pp, &info); 282 + } while (info.wr_ptr_line_count > 0 && 283 + info.wr_ptr_line_count < vdisplay); 284 + 285 + dpu_hw_pp_connect_external_te(pp, true); 286 + 287 + DPU_DEBUG("enc%d pp%d disabled autorefresh\n", 288 + encoder_id, pp->idx - PINGPONG_0); 289 + } 290 + 215 291 static int dpu_hw_pp_dsc_enable(struct dpu_hw_pingpong *pp) 216 292 { 217 293 struct dpu_hw_blk_reg_map *c = &pp->hw; ··· 284 274 static void _setup_pingpong_ops(struct dpu_hw_pingpong *c, 285 275 unsigned long features) 286 276 { 287 - c->ops.setup_tearcheck = dpu_hw_pp_setup_te_config; 288 - c->ops.enable_tearcheck = dpu_hw_pp_enable_te; 289 - c->ops.connect_external_te = dpu_hw_pp_connect_external_te; 290 - c->ops.get_vsync_info = dpu_hw_pp_get_vsync_info; 291 - c->ops.setup_autorefresh = dpu_hw_pp_setup_autorefresh_config; 292 - c->ops.get_autorefresh = dpu_hw_pp_get_autorefresh_config; 293 - c->ops.poll_timeout_wr_ptr = dpu_hw_pp_poll_timeout_wr_ptr; 294 - c->ops.get_line_count = dpu_hw_pp_get_line_count; 295 - c->ops.setup_dsc = dpu_hw_pp_setup_dsc; 296 - c->ops.enable_dsc = dpu_hw_pp_dsc_enable; 297 - c->ops.disable_dsc = dpu_hw_pp_dsc_disable; 277 + if (test_bit(DPU_PINGPONG_TE, &features)) { 278 + c->ops.enable_tearcheck = dpu_hw_pp_enable_te; 279 + c->ops.disable_tearcheck = dpu_hw_pp_disable_te; 280 + c->ops.connect_external_te = dpu_hw_pp_connect_external_te; 281 + c->ops.get_line_count = dpu_hw_pp_get_line_count; 282 + c->ops.disable_autorefresh = dpu_hw_pp_disable_autorefresh; 283 + } 284 + 285 + if (test_bit(DPU_PINGPONG_DSC, &features)) { 286 + c->ops.setup_dsc = dpu_hw_pp_setup_dsc; 287 + c->ops.enable_dsc = dpu_hw_pp_dsc_enable; 288 + c->ops.disable_dsc = dpu_hw_pp_dsc_disable; 289 + } 298 290 299 291 if (test_bit(DPU_PINGPONG_DITHER, &features)) 300 292 c->ops.setup_dither = dpu_hw_pp_setup_dither; 301 293 }; 302 294 303 - struct dpu_hw_pingpong *dpu_hw_pingpong_init(enum dpu_pingpong idx, 304 - void __iomem *addr, 305 - const struct dpu_mdss_cfg *m) 295 + struct dpu_hw_pingpong *dpu_hw_pingpong_init(const struct dpu_pingpong_cfg *cfg, 296 + void __iomem *addr) 306 297 { 307 298 struct dpu_hw_pingpong *c; 308 - const struct dpu_pingpong_cfg *cfg; 309 299 310 300 c = kzalloc(sizeof(*c), GFP_KERNEL); 311 301 if (!c) 312 302 return ERR_PTR(-ENOMEM); 313 303 314 - cfg = _pingpong_offset(idx, m, addr, &c->hw); 315 - if (IS_ERR_OR_NULL(cfg)) { 316 - kfree(c); 317 - return ERR_PTR(-EINVAL); 318 - } 304 + c->hw.blk_addr = addr + cfg->base; 305 + c->hw.log_mask = DPU_DBG_MASK_PINGPONG; 319 306 320 - c->idx = idx; 307 + c->idx = cfg->id; 321 308 c->caps = cfg; 322 309 _setup_pingpong_ops(c, c->caps->features); 323 310
+16 -64
drivers/gpu/drm/msm/disp/dpu1/dpu_hw_pingpong.h
··· 13 13 14 14 struct dpu_hw_pingpong; 15 15 16 - struct dpu_hw_tear_check { 17 - /* 18 - * This is ratio of MDP VSYNC clk freq(Hz) to 19 - * refresh rate divided by no of lines 20 - */ 21 - u32 vsync_count; 22 - u32 sync_cfg_height; 23 - u32 vsync_init_val; 24 - u32 sync_threshold_start; 25 - u32 sync_threshold_continue; 26 - u32 start_pos; 27 - u32 rd_ptr_irq; 28 - u8 hw_vsync_mode; 29 - }; 30 - 31 - struct dpu_hw_pp_vsync_info { 32 - u32 rd_ptr_init_val; /* value of rd pointer at vsync edge */ 33 - u32 rd_ptr_frame_count; /* num frames sent since enabling interface */ 34 - u32 rd_ptr_line_count; /* current line on panel (rd ptr) */ 35 - u32 wr_ptr_line_count; /* current line within pp fifo (wr ptr) */ 36 - }; 37 - 38 16 /** 39 17 * struct dpu_hw_dither_cfg - dither feature structure 40 18 * @flags: for customizing operations ··· 37 59 * 38 60 * struct dpu_hw_pingpong_ops : Interface to the pingpong Hw driver functions 39 61 * Assumption is these functions will be called after clocks are enabled 40 - * @setup_tearcheck : program tear check values 41 - * @enable_tearcheck : enables tear check 42 - * @get_vsync_info : retries timing info of the panel 43 - * @setup_autorefresh : configure and enable the autorefresh config 44 - * @get_autorefresh : retrieve autorefresh config from hardware 62 + * @enable_tearcheck: program and enable tear check block 63 + * @disable_tearcheck: disable able tear check block 45 64 * @setup_dither : function to program the dither hw block 46 65 * @get_line_count: obtain current vertical line counter 47 66 */ ··· 47 72 * enables vysnc generation and sets up init value of 48 73 * read pointer and programs the tear check cofiguration 49 74 */ 50 - int (*setup_tearcheck)(struct dpu_hw_pingpong *pp, 75 + int (*enable_tearcheck)(struct dpu_hw_pingpong *pp, 51 76 struct dpu_hw_tear_check *cfg); 52 77 53 78 /** 54 - * enables tear check block 79 + * disables tear check block 55 80 */ 56 - int (*enable_tearcheck)(struct dpu_hw_pingpong *pp, 57 - bool enable); 81 + int (*disable_tearcheck)(struct dpu_hw_pingpong *pp); 58 82 59 83 /** 60 84 * read, modify, write to either set or clear listening to external TE ··· 63 89 bool enable_external_te); 64 90 65 91 /** 66 - * provides the programmed and current 67 - * line_count 68 - */ 69 - int (*get_vsync_info)(struct dpu_hw_pingpong *pp, 70 - struct dpu_hw_pp_vsync_info *info); 71 - 72 - /** 73 - * configure and enable the autorefresh config 74 - */ 75 - void (*setup_autorefresh)(struct dpu_hw_pingpong *pp, 76 - u32 frame_count, bool enable); 77 - 78 - /** 79 - * retrieve autorefresh config from hardware 80 - */ 81 - bool (*get_autorefresh)(struct dpu_hw_pingpong *pp, 82 - u32 *frame_count); 83 - 84 - /** 85 - * poll until write pointer transmission starts 86 - * @Return: 0 on success, -ETIMEDOUT on timeout 87 - */ 88 - int (*poll_timeout_wr_ptr)(struct dpu_hw_pingpong *pp, u32 timeout_us); 89 - 90 - /** 91 92 * Obtain current vertical line counter 92 93 */ 93 94 u32 (*get_line_count)(struct dpu_hw_pingpong *pp); 95 + 96 + /** 97 + * Disable autorefresh if enabled 98 + */ 99 + void (*disable_autorefresh)(struct dpu_hw_pingpong *pp, uint32_t encoder_id, u16 vdisplay); 94 100 95 101 /** 96 102 * Setup dither matix for pingpong block ··· 119 165 } 120 166 121 167 /** 122 - * dpu_hw_pingpong_init - initializes the pingpong driver for the passed 123 - * pingpong idx. 124 - * @idx: Pingpong index for which driver object is required 168 + * dpu_hw_pingpong_init() - initializes the pingpong driver for the passed 169 + * pingpong catalog entry. 170 + * @cfg: Pingpong catalog entry for which driver object is required 125 171 * @addr: Mapped register io address of MDP 126 - * @m: Pointer to mdss catalog data 127 - * Returns: Error code or allocated dpu_hw_pingpong context 172 + * Return: Error code or allocated dpu_hw_pingpong context 128 173 */ 129 - struct dpu_hw_pingpong *dpu_hw_pingpong_init(enum dpu_pingpong idx, 130 - void __iomem *addr, 131 - const struct dpu_mdss_cfg *m); 174 + struct dpu_hw_pingpong *dpu_hw_pingpong_init(const struct dpu_pingpong_cfg *cfg, 175 + void __iomem *addr); 132 176 133 177 /** 134 178 * dpu_hw_pingpong_destroy - destroys pingpong driver context
+129 -257
drivers/gpu/drm/msm/disp/dpu1/dpu_hw_sspp.c
··· 12 12 13 13 #define DPU_FETCH_CONFIG_RESET_VALUE 0x00000087 14 14 15 - /* DPU_SSPP_SRC */ 15 + /* SSPP registers */ 16 16 #define SSPP_SRC_SIZE 0x00 17 17 #define SSPP_SRC_XY 0x08 18 18 #define SSPP_OUT_SIZE 0x0c ··· 26 26 #define SSPP_SRC_FORMAT 0x30 27 27 #define SSPP_SRC_UNPACK_PATTERN 0x34 28 28 #define SSPP_SRC_OP_MODE 0x38 29 - 30 - /* SSPP_MULTIRECT*/ 31 - #define SSPP_SRC_SIZE_REC1 0x16C 32 - #define SSPP_SRC_XY_REC1 0x168 33 - #define SSPP_OUT_SIZE_REC1 0x160 34 - #define SSPP_OUT_XY_REC1 0x164 35 - #define SSPP_SRC_FORMAT_REC1 0x174 36 - #define SSPP_SRC_UNPACK_PATTERN_REC1 0x178 37 - #define SSPP_SRC_OP_MODE_REC1 0x17C 38 - #define SSPP_MULTIRECT_OPMODE 0x170 39 - #define SSPP_SRC_CONSTANT_COLOR_REC1 0x180 40 - #define SSPP_EXCL_REC_SIZE_REC1 0x184 41 - #define SSPP_EXCL_REC_XY_REC1 0x188 42 - 43 - #define MDSS_MDP_OP_DEINTERLACE BIT(22) 44 - #define MDSS_MDP_OP_DEINTERLACE_ODD BIT(23) 45 - #define MDSS_MDP_OP_IGC_ROM_1 BIT(18) 46 - #define MDSS_MDP_OP_IGC_ROM_0 BIT(17) 47 - #define MDSS_MDP_OP_IGC_EN BIT(16) 48 - #define MDSS_MDP_OP_FLIP_UD BIT(14) 49 - #define MDSS_MDP_OP_FLIP_LR BIT(13) 50 - #define MDSS_MDP_OP_BWC_EN BIT(0) 51 - #define MDSS_MDP_OP_PE_OVERRIDE BIT(31) 52 - #define MDSS_MDP_OP_BWC_LOSSLESS (0 << 1) 53 - #define MDSS_MDP_OP_BWC_Q_HIGH (1 << 1) 54 - #define MDSS_MDP_OP_BWC_Q_MED (2 << 1) 55 - 56 29 #define SSPP_SRC_CONSTANT_COLOR 0x3c 57 30 #define SSPP_EXCL_REC_CTL 0x40 58 31 #define SSPP_UBWC_STATIC_CTRL 0x44 59 - #define SSPP_FETCH_CONFIG 0x048 32 + #define SSPP_FETCH_CONFIG 0x48 60 33 #define SSPP_DANGER_LUT 0x60 61 34 #define SSPP_SAFE_LUT 0x64 62 35 #define SSPP_CREQ_LUT 0x68 63 36 #define SSPP_QOS_CTRL 0x6C 64 - #define SSPP_DECIMATION_CONFIG 0xB4 65 37 #define SSPP_SRC_ADDR_SW_STATUS 0x70 66 38 #define SSPP_CREQ_LUT_0 0x74 67 39 #define SSPP_CREQ_LUT_1 0x78 40 + #define SSPP_DECIMATION_CONFIG 0xB4 68 41 #define SSPP_SW_PIX_EXT_C0_LR 0x100 69 42 #define SSPP_SW_PIX_EXT_C0_TB 0x104 70 43 #define SSPP_SW_PIX_EXT_C0_REQ_PIXELS 0x108 ··· 54 81 #define SSPP_TRAFFIC_SHAPER_PREFILL 0x150 55 82 #define SSPP_TRAFFIC_SHAPER_REC1_PREFILL 0x154 56 83 #define SSPP_TRAFFIC_SHAPER_REC1 0x158 84 + #define SSPP_OUT_SIZE_REC1 0x160 85 + #define SSPP_OUT_XY_REC1 0x164 86 + #define SSPP_SRC_XY_REC1 0x168 87 + #define SSPP_SRC_SIZE_REC1 0x16C 88 + #define SSPP_MULTIRECT_OPMODE 0x170 89 + #define SSPP_SRC_FORMAT_REC1 0x174 90 + #define SSPP_SRC_UNPACK_PATTERN_REC1 0x178 91 + #define SSPP_SRC_OP_MODE_REC1 0x17C 92 + #define SSPP_SRC_CONSTANT_COLOR_REC1 0x180 93 + #define SSPP_EXCL_REC_SIZE_REC1 0x184 94 + #define SSPP_EXCL_REC_XY_REC1 0x188 57 95 #define SSPP_EXCL_REC_SIZE 0x1B4 58 96 #define SSPP_EXCL_REC_XY 0x1B8 59 - #define SSPP_VIG_OP_MODE 0x0 60 - #define SSPP_VIG_CSC_10_OP_MODE 0x0 61 - #define SSPP_TRAFFIC_SHAPER_BPC_MAX 0xFF 97 + 98 + /* SSPP_SRC_OP_MODE & OP_MODE_REC1 */ 99 + #define MDSS_MDP_OP_DEINTERLACE BIT(22) 100 + #define MDSS_MDP_OP_DEINTERLACE_ODD BIT(23) 101 + #define MDSS_MDP_OP_IGC_ROM_1 BIT(18) 102 + #define MDSS_MDP_OP_IGC_ROM_0 BIT(17) 103 + #define MDSS_MDP_OP_IGC_EN BIT(16) 104 + #define MDSS_MDP_OP_FLIP_UD BIT(14) 105 + #define MDSS_MDP_OP_FLIP_LR BIT(13) 106 + #define MDSS_MDP_OP_BWC_EN BIT(0) 107 + #define MDSS_MDP_OP_PE_OVERRIDE BIT(31) 108 + #define MDSS_MDP_OP_BWC_LOSSLESS (0 << 1) 109 + #define MDSS_MDP_OP_BWC_Q_HIGH (1 << 1) 110 + #define MDSS_MDP_OP_BWC_Q_MED (2 << 1) 62 111 63 112 /* SSPP_QOS_CTRL */ 64 113 #define SSPP_QOS_CTRL_VBLANK_EN BIT(16) ··· 91 96 #define SSPP_QOS_CTRL_CREQ_VBLANK_OFF 20 92 97 93 98 /* DPU_SSPP_SCALER_QSEED2 */ 99 + #define SSPP_VIG_OP_MODE 0x0 94 100 #define SCALE_CONFIG 0x04 95 101 #define COMP0_3_PHASE_STEP_X 0x10 96 102 #define COMP0_3_PHASE_STEP_Y 0x14 ··· 102 106 #define COMP1_2_INIT_PHASE_X 0x28 103 107 #define COMP1_2_INIT_PHASE_Y 0x2C 104 108 #define VIG_0_QSEED2_SHARP 0x30 109 + 110 + /* SSPP_TRAFFIC_SHAPER and _REC1 */ 111 + #define SSPP_TRAFFIC_SHAPER_BPC_MAX 0xFF 105 112 106 113 /* 107 114 * Definitions for ViG op modes ··· 127 128 /* 128 129 * Definitions for CSC 10 op modes 129 130 */ 131 + #define SSPP_VIG_CSC_10_OP_MODE 0x0 130 132 #define VIG_CSC_10_SRC_DATAFMT BIT(1) 131 133 #define VIG_CSC_10_EN BIT(0) 132 134 #define CSC_10BIT_OFFSET 4 ··· 136 136 #define TS_CLK 19200000 137 137 138 138 139 - static int _sspp_subblk_offset(struct dpu_hw_sspp *ctx, 140 - int s_id, 141 - u32 *idx) 142 - { 143 - int rc = 0; 144 - const struct dpu_sspp_sub_blks *sblk; 145 - 146 - if (!ctx || !ctx->cap || !ctx->cap->sblk) 147 - return -EINVAL; 148 - 149 - sblk = ctx->cap->sblk; 150 - 151 - switch (s_id) { 152 - case DPU_SSPP_SRC: 153 - *idx = sblk->src_blk.base; 154 - break; 155 - case DPU_SSPP_SCALER_QSEED2: 156 - case DPU_SSPP_SCALER_QSEED3: 157 - case DPU_SSPP_SCALER_RGB: 158 - *idx = sblk->scaler_blk.base; 159 - break; 160 - case DPU_SSPP_CSC: 161 - case DPU_SSPP_CSC_10BIT: 162 - *idx = sblk->csc_blk.base; 163 - break; 164 - default: 165 - rc = -EINVAL; 166 - } 167 - 168 - return rc; 169 - } 170 - 171 139 static void dpu_hw_sspp_setup_multirect(struct dpu_sw_pipe *pipe) 172 140 { 173 141 struct dpu_hw_sspp *ctx = pipe->sspp; 174 142 u32 mode_mask; 175 - u32 idx; 176 143 177 - if (_sspp_subblk_offset(ctx, DPU_SSPP_SRC, &idx)) 144 + if (!ctx) 178 145 return; 179 146 180 147 if (pipe->multirect_index == DPU_SSPP_RECT_SOLO) { ··· 152 185 */ 153 186 mode_mask = 0; 154 187 } else { 155 - mode_mask = DPU_REG_READ(&ctx->hw, SSPP_MULTIRECT_OPMODE + idx); 188 + mode_mask = DPU_REG_READ(&ctx->hw, SSPP_MULTIRECT_OPMODE); 156 189 mode_mask |= pipe->multirect_index; 157 190 if (pipe->multirect_mode == DPU_SSPP_MULTIRECT_TIME_MX) 158 191 mode_mask |= BIT(2); ··· 160 193 mode_mask &= ~BIT(2); 161 194 } 162 195 163 - DPU_REG_WRITE(&ctx->hw, SSPP_MULTIRECT_OPMODE + idx, mode_mask); 196 + DPU_REG_WRITE(&ctx->hw, SSPP_MULTIRECT_OPMODE, mode_mask); 164 197 } 165 198 166 199 static void _sspp_setup_opmode(struct dpu_hw_sspp *ctx, 167 200 u32 mask, u8 en) 168 201 { 169 - u32 idx; 202 + const struct dpu_sspp_sub_blks *sblk = ctx->cap->sblk; 170 203 u32 opmode; 171 204 172 205 if (!test_bit(DPU_SSPP_SCALER_QSEED2, &ctx->cap->features) || 173 - _sspp_subblk_offset(ctx, DPU_SSPP_SCALER_QSEED2, &idx) || 174 206 !test_bit(DPU_SSPP_CSC, &ctx->cap->features)) 175 207 return; 176 208 177 - opmode = DPU_REG_READ(&ctx->hw, SSPP_VIG_OP_MODE + idx); 209 + opmode = DPU_REG_READ(&ctx->hw, sblk->scaler_blk.base + SSPP_VIG_OP_MODE); 178 210 179 211 if (en) 180 212 opmode |= mask; 181 213 else 182 214 opmode &= ~mask; 183 215 184 - DPU_REG_WRITE(&ctx->hw, SSPP_VIG_OP_MODE + idx, opmode); 216 + DPU_REG_WRITE(&ctx->hw, sblk->scaler_blk.base + SSPP_VIG_OP_MODE, opmode); 185 217 } 186 218 187 219 static void _sspp_setup_csc10_opmode(struct dpu_hw_sspp *ctx, 188 220 u32 mask, u8 en) 189 221 { 190 - u32 idx; 222 + const struct dpu_sspp_sub_blks *sblk = ctx->cap->sblk; 191 223 u32 opmode; 192 224 193 - if (_sspp_subblk_offset(ctx, DPU_SSPP_CSC_10BIT, &idx)) 194 - return; 195 - 196 - opmode = DPU_REG_READ(&ctx->hw, SSPP_VIG_CSC_10_OP_MODE + idx); 225 + opmode = DPU_REG_READ(&ctx->hw, sblk->csc_blk.base + SSPP_VIG_CSC_10_OP_MODE); 197 226 if (en) 198 227 opmode |= mask; 199 228 else 200 229 opmode &= ~mask; 201 230 202 - DPU_REG_WRITE(&ctx->hw, SSPP_VIG_CSC_10_OP_MODE + idx, opmode); 231 + DPU_REG_WRITE(&ctx->hw, sblk->csc_blk.base + SSPP_VIG_CSC_10_OP_MODE, opmode); 203 232 } 204 233 205 234 /* ··· 210 247 u32 opmode = 0; 211 248 u32 fast_clear = 0; 212 249 u32 op_mode_off, unpack_pat_off, format_off; 213 - u32 idx; 214 250 215 - if (_sspp_subblk_offset(ctx, DPU_SSPP_SRC, &idx) || !fmt) 251 + if (!ctx || !fmt) 216 252 return; 217 253 218 254 if (pipe->multirect_index == DPU_SSPP_RECT_SOLO || ··· 226 264 } 227 265 228 266 c = &ctx->hw; 229 - opmode = DPU_REG_READ(c, op_mode_off + idx); 267 + opmode = DPU_REG_READ(c, op_mode_off); 230 268 opmode &= ~(MDSS_MDP_OP_FLIP_LR | MDSS_MDP_OP_FLIP_UD | 231 269 MDSS_MDP_OP_BWC_EN | MDSS_MDP_OP_PE_OVERRIDE); 232 270 ··· 314 352 VIG_CSC_10_EN | VIG_CSC_10_SRC_DATAFMT, 315 353 DPU_FORMAT_IS_YUV(fmt)); 316 354 317 - DPU_REG_WRITE(c, format_off + idx, src_format); 318 - DPU_REG_WRITE(c, unpack_pat_off + idx, unpack); 319 - DPU_REG_WRITE(c, op_mode_off + idx, opmode); 355 + DPU_REG_WRITE(c, format_off, src_format); 356 + DPU_REG_WRITE(c, unpack_pat_off, unpack); 357 + DPU_REG_WRITE(c, op_mode_off, opmode); 320 358 321 359 /* clear previous UBWC error */ 322 - DPU_REG_WRITE(c, SSPP_UBWC_ERROR_STATUS + idx, BIT(31)); 360 + DPU_REG_WRITE(c, SSPP_UBWC_ERROR_STATUS, BIT(31)); 323 361 } 324 362 325 363 static void dpu_hw_sspp_setup_pe_config(struct dpu_hw_sspp *ctx, ··· 330 368 u32 lr_pe[4], tb_pe[4], tot_req_pixels[4]; 331 369 const u32 bytemask = 0xff; 332 370 const u32 shortmask = 0xffff; 333 - u32 idx; 334 371 335 - if (_sspp_subblk_offset(ctx, DPU_SSPP_SRC, &idx) || !pe_ext) 372 + if (!ctx || !pe_ext) 336 373 return; 337 374 338 375 c = &ctx->hw; ··· 361 400 } 362 401 363 402 /* color 0 */ 364 - DPU_REG_WRITE(c, SSPP_SW_PIX_EXT_C0_LR + idx, lr_pe[0]); 365 - DPU_REG_WRITE(c, SSPP_SW_PIX_EXT_C0_TB + idx, tb_pe[0]); 366 - DPU_REG_WRITE(c, SSPP_SW_PIX_EXT_C0_REQ_PIXELS + idx, 403 + DPU_REG_WRITE(c, SSPP_SW_PIX_EXT_C0_LR, lr_pe[0]); 404 + DPU_REG_WRITE(c, SSPP_SW_PIX_EXT_C0_TB, tb_pe[0]); 405 + DPU_REG_WRITE(c, SSPP_SW_PIX_EXT_C0_REQ_PIXELS, 367 406 tot_req_pixels[0]); 368 407 369 408 /* color 1 and color 2 */ 370 - DPU_REG_WRITE(c, SSPP_SW_PIX_EXT_C1C2_LR + idx, lr_pe[1]); 371 - DPU_REG_WRITE(c, SSPP_SW_PIX_EXT_C1C2_TB + idx, tb_pe[1]); 372 - DPU_REG_WRITE(c, SSPP_SW_PIX_EXT_C1C2_REQ_PIXELS + idx, 409 + DPU_REG_WRITE(c, SSPP_SW_PIX_EXT_C1C2_LR, lr_pe[1]); 410 + DPU_REG_WRITE(c, SSPP_SW_PIX_EXT_C1C2_TB, tb_pe[1]); 411 + DPU_REG_WRITE(c, SSPP_SW_PIX_EXT_C1C2_REQ_PIXELS, 373 412 tot_req_pixels[1]); 374 413 375 414 /* color 3 */ 376 - DPU_REG_WRITE(c, SSPP_SW_PIX_EXT_C3_LR + idx, lr_pe[3]); 377 - DPU_REG_WRITE(c, SSPP_SW_PIX_EXT_C3_TB + idx, lr_pe[3]); 378 - DPU_REG_WRITE(c, SSPP_SW_PIX_EXT_C3_REQ_PIXELS + idx, 415 + DPU_REG_WRITE(c, SSPP_SW_PIX_EXT_C3_LR, lr_pe[3]); 416 + DPU_REG_WRITE(c, SSPP_SW_PIX_EXT_C3_TB, lr_pe[3]); 417 + DPU_REG_WRITE(c, SSPP_SW_PIX_EXT_C3_REQ_PIXELS, 379 418 tot_req_pixels[3]); 380 419 } 381 420 ··· 383 422 struct dpu_hw_scaler3_cfg *scaler3_cfg, 384 423 const struct dpu_format *format) 385 424 { 386 - u32 idx; 387 - 388 - if (_sspp_subblk_offset(ctx, DPU_SSPP_SCALER_QSEED3, &idx) 389 - || !scaler3_cfg) 425 + if (!ctx || !scaler3_cfg) 390 426 return; 391 427 392 - dpu_hw_setup_scaler3(&ctx->hw, scaler3_cfg, idx, 428 + dpu_hw_setup_scaler3(&ctx->hw, scaler3_cfg, 429 + ctx->cap->sblk->scaler_blk.base, 393 430 ctx->cap->sblk->scaler_blk.version, 394 431 format); 395 432 } 396 433 397 434 static u32 _dpu_hw_sspp_get_scaler3_ver(struct dpu_hw_sspp *ctx) 398 435 { 399 - u32 idx; 400 - 401 - if (!ctx || _sspp_subblk_offset(ctx, DPU_SSPP_SCALER_QSEED3, &idx)) 436 + if (!ctx) 402 437 return 0; 403 438 404 - return dpu_hw_get_scaler3_ver(&ctx->hw, idx); 439 + return dpu_hw_get_scaler3_ver(&ctx->hw, 440 + ctx->cap->sblk->scaler_blk.base); 405 441 } 406 442 407 443 /* ··· 411 453 struct dpu_hw_blk_reg_map *c; 412 454 u32 src_size, src_xy, dst_size, dst_xy; 413 455 u32 src_size_off, src_xy_off, out_size_off, out_xy_off; 414 - u32 idx; 415 456 416 - if (_sspp_subblk_offset(ctx, DPU_SSPP_SRC, &idx) || !cfg) 457 + if (!ctx || !cfg) 417 458 return; 418 459 419 460 c = &ctx->hw; ··· 440 483 drm_rect_width(&cfg->dst_rect); 441 484 442 485 /* rectangle register programming */ 443 - DPU_REG_WRITE(c, src_size_off + idx, src_size); 444 - DPU_REG_WRITE(c, src_xy_off + idx, src_xy); 445 - DPU_REG_WRITE(c, out_size_off + idx, dst_size); 446 - DPU_REG_WRITE(c, out_xy_off + idx, dst_xy); 486 + DPU_REG_WRITE(c, src_size_off, src_size); 487 + DPU_REG_WRITE(c, src_xy_off, src_xy); 488 + DPU_REG_WRITE(c, out_size_off, dst_size); 489 + DPU_REG_WRITE(c, out_xy_off, dst_xy); 447 490 } 448 491 449 492 static void dpu_hw_sspp_setup_sourceaddress(struct dpu_sw_pipe *pipe, ··· 452 495 struct dpu_hw_sspp *ctx = pipe->sspp; 453 496 u32 ystride0, ystride1; 454 497 int i; 455 - u32 idx; 456 498 457 - if (_sspp_subblk_offset(ctx, DPU_SSPP_SRC, &idx)) 499 + if (!ctx) 458 500 return; 459 501 460 502 if (pipe->multirect_index == DPU_SSPP_RECT_SOLO) { 461 503 for (i = 0; i < ARRAY_SIZE(layout->plane_addr); i++) 462 - DPU_REG_WRITE(&ctx->hw, SSPP_SRC0_ADDR + idx + i * 0x4, 504 + DPU_REG_WRITE(&ctx->hw, SSPP_SRC0_ADDR + i * 0x4, 463 505 layout->plane_addr[i]); 464 506 } else if (pipe->multirect_index == DPU_SSPP_RECT_0) { 465 - DPU_REG_WRITE(&ctx->hw, SSPP_SRC0_ADDR + idx, 507 + DPU_REG_WRITE(&ctx->hw, SSPP_SRC0_ADDR, 466 508 layout->plane_addr[0]); 467 - DPU_REG_WRITE(&ctx->hw, SSPP_SRC2_ADDR + idx, 509 + DPU_REG_WRITE(&ctx->hw, SSPP_SRC2_ADDR, 468 510 layout->plane_addr[2]); 469 511 } else { 470 - DPU_REG_WRITE(&ctx->hw, SSPP_SRC1_ADDR + idx, 512 + DPU_REG_WRITE(&ctx->hw, SSPP_SRC1_ADDR, 471 513 layout->plane_addr[0]); 472 - DPU_REG_WRITE(&ctx->hw, SSPP_SRC3_ADDR + idx, 514 + DPU_REG_WRITE(&ctx->hw, SSPP_SRC3_ADDR, 473 515 layout->plane_addr[2]); 474 516 } 475 517 ··· 478 522 ystride1 = (layout->plane_pitch[2]) | 479 523 (layout->plane_pitch[3] << 16); 480 524 } else { 481 - ystride0 = DPU_REG_READ(&ctx->hw, SSPP_SRC_YSTRIDE0 + idx); 482 - ystride1 = DPU_REG_READ(&ctx->hw, SSPP_SRC_YSTRIDE1 + idx); 525 + ystride0 = DPU_REG_READ(&ctx->hw, SSPP_SRC_YSTRIDE0); 526 + ystride1 = DPU_REG_READ(&ctx->hw, SSPP_SRC_YSTRIDE1); 483 527 484 528 if (pipe->multirect_index == DPU_SSPP_RECT_0) { 485 529 ystride0 = (ystride0 & 0xFFFF0000) | ··· 496 540 } 497 541 } 498 542 499 - DPU_REG_WRITE(&ctx->hw, SSPP_SRC_YSTRIDE0 + idx, ystride0); 500 - DPU_REG_WRITE(&ctx->hw, SSPP_SRC_YSTRIDE1 + idx, ystride1); 543 + DPU_REG_WRITE(&ctx->hw, SSPP_SRC_YSTRIDE0, ystride0); 544 + DPU_REG_WRITE(&ctx->hw, SSPP_SRC_YSTRIDE1, ystride1); 501 545 } 502 546 503 547 static void dpu_hw_sspp_setup_csc(struct dpu_hw_sspp *ctx, 504 548 const struct dpu_csc_cfg *data) 505 549 { 506 - u32 idx; 550 + u32 offset; 507 551 bool csc10 = false; 508 552 509 - if (_sspp_subblk_offset(ctx, DPU_SSPP_CSC, &idx) || !data) 553 + if (!ctx || !data) 510 554 return; 511 555 556 + offset = ctx->cap->sblk->csc_blk.base; 557 + 512 558 if (test_bit(DPU_SSPP_CSC_10BIT, &ctx->cap->features)) { 513 - idx += CSC_10BIT_OFFSET; 559 + offset += CSC_10BIT_OFFSET; 514 560 csc10 = true; 515 561 } 516 562 517 - dpu_hw_csc_setup(&ctx->hw, idx, data, csc10); 563 + dpu_hw_csc_setup(&ctx->hw, offset, data, csc10); 518 564 } 519 565 520 566 static void dpu_hw_sspp_setup_solidfill(struct dpu_sw_pipe *pipe, u32 color) 521 567 { 522 568 struct dpu_hw_sspp *ctx = pipe->sspp; 523 569 struct dpu_hw_fmt_layout cfg; 524 - u32 idx; 525 570 526 - if (_sspp_subblk_offset(ctx, DPU_SSPP_SRC, &idx)) 571 + if (!ctx) 527 572 return; 528 573 529 574 /* cleanup source addresses */ ··· 533 576 534 577 if (pipe->multirect_index == DPU_SSPP_RECT_SOLO || 535 578 pipe->multirect_index == DPU_SSPP_RECT_0) 536 - DPU_REG_WRITE(&ctx->hw, SSPP_SRC_CONSTANT_COLOR + idx, color); 579 + DPU_REG_WRITE(&ctx->hw, SSPP_SRC_CONSTANT_COLOR, color); 537 580 else 538 - DPU_REG_WRITE(&ctx->hw, SSPP_SRC_CONSTANT_COLOR_REC1 + idx, 581 + DPU_REG_WRITE(&ctx->hw, SSPP_SRC_CONSTANT_COLOR_REC1, 539 582 color); 540 583 } 541 584 542 - static void dpu_hw_sspp_setup_danger_safe_lut(struct dpu_hw_sspp *ctx, 543 - u32 danger_lut, 544 - u32 safe_lut) 585 + static void dpu_hw_sspp_setup_qos_lut(struct dpu_hw_sspp *ctx, 586 + struct dpu_hw_qos_cfg *cfg) 545 587 { 546 - u32 idx; 547 - 548 - if (_sspp_subblk_offset(ctx, DPU_SSPP_SRC, &idx)) 549 - return; 550 - 551 - DPU_REG_WRITE(&ctx->hw, SSPP_DANGER_LUT + idx, danger_lut); 552 - DPU_REG_WRITE(&ctx->hw, SSPP_SAFE_LUT + idx, safe_lut); 553 - } 554 - 555 - static void dpu_hw_sspp_setup_creq_lut(struct dpu_hw_sspp *ctx, 556 - u64 creq_lut) 557 - { 558 - u32 idx; 559 - 560 - if (_sspp_subblk_offset(ctx, DPU_SSPP_SRC, &idx)) 561 - return; 562 - 563 - if (ctx->cap && test_bit(DPU_SSPP_QOS_8LVL, &ctx->cap->features)) { 564 - DPU_REG_WRITE(&ctx->hw, SSPP_CREQ_LUT_0 + idx, creq_lut); 565 - DPU_REG_WRITE(&ctx->hw, SSPP_CREQ_LUT_1 + idx, 566 - creq_lut >> 32); 567 - } else { 568 - DPU_REG_WRITE(&ctx->hw, SSPP_CREQ_LUT + idx, creq_lut); 569 - } 570 - } 571 - 572 - static void dpu_hw_sspp_setup_qos_ctrl(struct dpu_hw_sspp *ctx, 573 - struct dpu_hw_pipe_qos_cfg *cfg) 574 - { 575 - u32 idx; 576 - u32 qos_ctrl = 0; 577 - 578 - if (_sspp_subblk_offset(ctx, DPU_SSPP_SRC, &idx)) 579 - return; 580 - 581 - if (cfg->vblank_en) { 582 - qos_ctrl |= ((cfg->creq_vblank & 583 - SSPP_QOS_CTRL_CREQ_VBLANK_MASK) << 584 - SSPP_QOS_CTRL_CREQ_VBLANK_OFF); 585 - qos_ctrl |= ((cfg->danger_vblank & 586 - SSPP_QOS_CTRL_DANGER_VBLANK_MASK) << 587 - SSPP_QOS_CTRL_DANGER_VBLANK_OFF); 588 - qos_ctrl |= SSPP_QOS_CTRL_VBLANK_EN; 589 - } 590 - 591 - if (cfg->danger_safe_en) 592 - qos_ctrl |= SSPP_QOS_CTRL_DANGER_SAFE_EN; 593 - 594 - DPU_REG_WRITE(&ctx->hw, SSPP_QOS_CTRL + idx, qos_ctrl); 595 - } 596 - 597 - static void dpu_hw_sspp_setup_cdp(struct dpu_sw_pipe *pipe, 598 - struct dpu_hw_cdp_cfg *cfg) 599 - { 600 - struct dpu_hw_sspp *ctx = pipe->sspp; 601 - u32 idx; 602 - u32 cdp_cntl = 0; 603 - u32 cdp_cntl_offset = 0; 604 - 605 588 if (!ctx || !cfg) 606 589 return; 607 590 608 - if (_sspp_subblk_offset(ctx, DPU_SSPP_SRC, &idx)) 591 + _dpu_hw_setup_qos_lut(&ctx->hw, SSPP_DANGER_LUT, 592 + test_bit(DPU_SSPP_QOS_8LVL, &ctx->cap->features), 593 + cfg); 594 + } 595 + 596 + static void dpu_hw_sspp_setup_qos_ctrl(struct dpu_hw_sspp *ctx, 597 + bool danger_safe_en) 598 + { 599 + if (!ctx) 600 + return; 601 + 602 + DPU_REG_WRITE(&ctx->hw, SSPP_QOS_CTRL, 603 + danger_safe_en ? SSPP_QOS_CTRL_DANGER_SAFE_EN : 0); 604 + } 605 + 606 + static void dpu_hw_sspp_setup_cdp(struct dpu_sw_pipe *pipe, 607 + const struct dpu_format *fmt, 608 + bool enable) 609 + { 610 + struct dpu_hw_sspp *ctx = pipe->sspp; 611 + u32 cdp_cntl_offset = 0; 612 + 613 + if (!ctx) 609 614 return; 610 615 611 616 if (pipe->multirect_index == DPU_SSPP_RECT_SOLO || ··· 576 657 else 577 658 cdp_cntl_offset = SSPP_CDP_CNTL_REC1; 578 659 579 - if (cfg->enable) 580 - cdp_cntl |= BIT(0); 581 - if (cfg->ubwc_meta_enable) 582 - cdp_cntl |= BIT(1); 583 - if (cfg->tile_amortize_enable) 584 - cdp_cntl |= BIT(2); 585 - if (cfg->preload_ahead == DPU_SSPP_CDP_PRELOAD_AHEAD_64) 586 - cdp_cntl |= BIT(3); 587 - 588 - DPU_REG_WRITE(&ctx->hw, cdp_cntl_offset, cdp_cntl); 660 + dpu_setup_cdp(&ctx->hw, cdp_cntl_offset, fmt, enable); 589 661 } 590 662 591 663 static void _setup_layer_ops(struct dpu_hw_sspp *c, 592 664 unsigned long features) 593 665 { 594 - if (test_bit(DPU_SSPP_SRC, &features)) { 595 - c->ops.setup_format = dpu_hw_sspp_setup_format; 596 - c->ops.setup_rects = dpu_hw_sspp_setup_rects; 597 - c->ops.setup_sourceaddress = dpu_hw_sspp_setup_sourceaddress; 598 - c->ops.setup_solidfill = dpu_hw_sspp_setup_solidfill; 599 - c->ops.setup_pe = dpu_hw_sspp_setup_pe_config; 600 - } 666 + c->ops.setup_format = dpu_hw_sspp_setup_format; 667 + c->ops.setup_rects = dpu_hw_sspp_setup_rects; 668 + c->ops.setup_sourceaddress = dpu_hw_sspp_setup_sourceaddress; 669 + c->ops.setup_solidfill = dpu_hw_sspp_setup_solidfill; 670 + c->ops.setup_pe = dpu_hw_sspp_setup_pe_config; 601 671 602 672 if (test_bit(DPU_SSPP_QOS, &features)) { 603 - c->ops.setup_danger_safe_lut = 604 - dpu_hw_sspp_setup_danger_safe_lut; 605 - c->ops.setup_creq_lut = dpu_hw_sspp_setup_creq_lut; 673 + c->ops.setup_qos_lut = dpu_hw_sspp_setup_qos_lut; 606 674 c->ops.setup_qos_ctrl = dpu_hw_sspp_setup_qos_ctrl; 607 675 } 608 676 ··· 634 728 /* add register dump support */ 635 729 dpu_debugfs_create_regset32("src_blk", 0400, 636 730 debugfs_root, 637 - sblk->src_blk.base + cfg->base, 638 - sblk->src_blk.len, 731 + cfg->base, 732 + cfg->len, 639 733 kms); 640 734 641 735 if (cfg->features & BIT(DPU_SSPP_SCALER_QSEED3) || ··· 664 758 0400, 665 759 debugfs_root, 666 760 (u32 *) &cfg->clk_ctrl); 667 - debugfs_create_x32("creq_vblank", 668 - 0600, 669 - debugfs_root, 670 - (u32 *) &sblk->creq_vblank); 671 - debugfs_create_x32("danger_vblank", 672 - 0600, 673 - debugfs_root, 674 - (u32 *) &sblk->danger_vblank); 675 761 676 762 return 0; 677 763 } 678 764 #endif 679 765 680 - 681 - static const struct dpu_sspp_cfg *_sspp_offset(enum dpu_sspp sspp, 682 - void __iomem *addr, 683 - const struct dpu_mdss_cfg *catalog, 684 - struct dpu_hw_blk_reg_map *b) 685 - { 686 - int i; 687 - 688 - if ((sspp < SSPP_MAX) && catalog && addr && b) { 689 - for (i = 0; i < catalog->sspp_count; i++) { 690 - if (sspp == catalog->sspp[i].id) { 691 - b->blk_addr = addr + catalog->sspp[i].base; 692 - b->log_mask = DPU_DBG_MASK_SSPP; 693 - return &catalog->sspp[i]; 694 - } 695 - } 696 - } 697 - 698 - return ERR_PTR(-ENOMEM); 699 - } 700 - 701 - struct dpu_hw_sspp *dpu_hw_sspp_init(enum dpu_sspp idx, 702 - void __iomem *addr, const struct dpu_mdss_cfg *catalog) 766 + struct dpu_hw_sspp *dpu_hw_sspp_init(const struct dpu_sspp_cfg *cfg, 767 + void __iomem *addr, const struct dpu_ubwc_cfg *ubwc) 703 768 { 704 769 struct dpu_hw_sspp *hw_pipe; 705 - const struct dpu_sspp_cfg *cfg; 706 770 707 - if (!addr || !catalog) 771 + if (!addr || !ubwc) 708 772 return ERR_PTR(-EINVAL); 709 773 710 774 hw_pipe = kzalloc(sizeof(*hw_pipe), GFP_KERNEL); 711 775 if (!hw_pipe) 712 776 return ERR_PTR(-ENOMEM); 713 777 714 - cfg = _sspp_offset(idx, addr, catalog, &hw_pipe->hw); 715 - if (IS_ERR_OR_NULL(cfg)) { 716 - kfree(hw_pipe); 717 - return ERR_PTR(-EINVAL); 718 - } 778 + hw_pipe->hw.blk_addr = addr + cfg->base; 779 + hw_pipe->hw.log_mask = DPU_DBG_MASK_SSPP; 719 780 720 781 /* Assign ops */ 721 - hw_pipe->catalog = catalog; 722 - hw_pipe->ubwc = catalog->ubwc; 723 - hw_pipe->idx = idx; 782 + hw_pipe->ubwc = ubwc; 783 + hw_pipe->idx = cfg->id; 724 784 hw_pipe->cap = cfg; 725 785 _setup_layer_ops(hw_pipe, hw_pipe->cap->features); 726 786
+16 -50
drivers/gpu/drm/msm/disp/dpu1/dpu_hw_sspp.h
··· 164 164 }; 165 165 166 166 /** 167 - * struct dpu_hw_pipe_qos_cfg : Source pipe QoS configuration 168 - * @creq_vblank: creq value generated to vbif during vertical blanking 169 - * @danger_vblank: danger value generated during vertical blanking 170 - * @vblank_en: enable creq_vblank and danger_vblank during vblank 171 - * @danger_safe_en: enable danger safe generation 172 - */ 173 - struct dpu_hw_pipe_qos_cfg { 174 - u32 creq_vblank; 175 - u32 danger_vblank; 176 - bool vblank_en; 177 - bool danger_safe_en; 178 - }; 179 - 180 - /** 181 - * enum CDP preload ahead address size 182 - */ 183 - enum { 184 - DPU_SSPP_CDP_PRELOAD_AHEAD_32, 185 - DPU_SSPP_CDP_PRELOAD_AHEAD_64 186 - }; 187 - 188 - /** 189 167 * struct dpu_hw_pipe_ts_cfg - traffic shaper configuration 190 168 * @size: size to prefill in bytes, or zero to disable 191 169 * @time: time to prefill in usec, or zero to disable ··· 254 276 void (*setup_sharpening)(struct dpu_hw_sspp *ctx, 255 277 struct dpu_hw_sharp_cfg *cfg); 256 278 257 - /** 258 - * setup_danger_safe_lut - setup danger safe LUTs 259 - * @ctx: Pointer to pipe context 260 - * @danger_lut: LUT for generate danger level based on fill level 261 - * @safe_lut: LUT for generate safe level based on fill level 262 - * 263 - */ 264 - void (*setup_danger_safe_lut)(struct dpu_hw_sspp *ctx, 265 - u32 danger_lut, 266 - u32 safe_lut); 267 279 268 280 /** 269 - * setup_creq_lut - setup CREQ LUT 281 + * setup_qos_lut - setup QoS LUTs 270 282 * @ctx: Pointer to pipe context 271 - * @creq_lut: LUT for generate creq level based on fill level 272 - * 283 + * @cfg: LUT configuration 273 284 */ 274 - void (*setup_creq_lut)(struct dpu_hw_sspp *ctx, 275 - u64 creq_lut); 285 + void (*setup_qos_lut)(struct dpu_hw_sspp *ctx, 286 + struct dpu_hw_qos_cfg *cfg); 276 287 277 288 /** 278 289 * setup_qos_ctrl - setup QoS control 279 290 * @ctx: Pointer to pipe context 280 - * @cfg: Pointer to pipe QoS configuration 281 - * 291 + * @danger_safe_en: flags controlling enabling of danger/safe QoS/LUT 282 292 */ 283 293 void (*setup_qos_ctrl)(struct dpu_hw_sspp *ctx, 284 - struct dpu_hw_pipe_qos_cfg *cfg); 294 + bool danger_safe_en); 285 295 286 296 /** 287 297 * setup_histogram - setup histograms ··· 297 331 /** 298 332 * setup_cdp - setup client driven prefetch 299 333 * @pipe: Pointer to software pipe context 300 - * @cfg: Pointer to cdp configuration 334 + * @fmt: format used by the sw pipe 335 + * @enable: whether the CDP should be enabled for this pipe 301 336 */ 302 337 void (*setup_cdp)(struct dpu_sw_pipe *pipe, 303 - struct dpu_hw_cdp_cfg *cfg); 338 + const struct dpu_format *fmt, 339 + bool enable); 304 340 }; 305 341 306 342 /** 307 343 * struct dpu_hw_sspp - pipe description 308 344 * @base: hardware block base structure 309 345 * @hw: block hardware details 310 - * @catalog: back pointer to catalog 311 - * @ubwc: ubwc configuration data 346 + * @ubwc: UBWC configuration data 312 347 * @idx: pipe index 313 348 * @cap: pointer to layer_cfg 314 349 * @ops: pointer to operations possible for this pipe ··· 317 350 struct dpu_hw_sspp { 318 351 struct dpu_hw_blk base; 319 352 struct dpu_hw_blk_reg_map hw; 320 - const struct dpu_mdss_cfg *catalog; 321 353 const struct dpu_ubwc_cfg *ubwc; 322 354 323 355 /* Pipe */ ··· 329 363 330 364 struct dpu_kms; 331 365 /** 332 - * dpu_hw_sspp_init - initializes the sspp hw driver object. 366 + * dpu_hw_sspp_init() - Initializes the sspp hw driver object. 333 367 * Should be called once before accessing every pipe. 334 - * @idx: Pipe index for which driver object is required 368 + * @cfg: Pipe catalog entry for which driver object is required 335 369 * @addr: Mapped register io address of MDP 336 - * @catalog : Pointer to mdss catalog data 370 + * @ubwc: UBWC configuration data 337 371 */ 338 - struct dpu_hw_sspp *dpu_hw_sspp_init(enum dpu_sspp idx, 339 - void __iomem *addr, const struct dpu_mdss_cfg *catalog); 372 + struct dpu_hw_sspp *dpu_hw_sspp_init(const struct dpu_sspp_cfg *cfg, 373 + void __iomem *addr, const struct dpu_ubwc_cfg *ubwc); 340 374 341 375 /** 342 376 * dpu_hw_sspp_destroy(): Destroys SSPP driver context
+35 -15
drivers/gpu/drm/msm/disp/dpu1/dpu_hw_top.c
··· 130 130 struct dpu_vsync_source_cfg *cfg) 131 131 { 132 132 struct dpu_hw_blk_reg_map *c; 133 - u32 reg, wd_load_value, wd_ctl, wd_ctl2, i; 134 - static const u32 pp_offset[PINGPONG_MAX] = {0xC, 0x8, 0x4, 0x13, 0x18}; 133 + u32 reg, wd_load_value, wd_ctl, wd_ctl2; 135 134 136 - if (!mdp || !cfg || (cfg->pp_count > ARRAY_SIZE(cfg->ppnumber))) 135 + if (!mdp || !cfg) 137 136 return; 138 137 139 138 c = &mdp->hw; 140 - reg = DPU_REG_READ(c, MDP_VSYNC_SEL); 141 - for (i = 0; i < cfg->pp_count; i++) { 142 - int pp_idx = cfg->ppnumber[i] - PINGPONG_0; 143 - 144 - if (pp_idx >= ARRAY_SIZE(pp_offset)) 145 - continue; 146 - 147 - reg &= ~(0xf << pp_offset[pp_idx]); 148 - reg |= (cfg->vsync_source & 0xf) << pp_offset[pp_idx]; 149 - } 150 - DPU_REG_WRITE(c, MDP_VSYNC_SEL, reg); 151 139 152 140 if (cfg->vsync_source >= DPU_VSYNC_SOURCE_WD_TIMER_4 && 153 141 cfg->vsync_source <= DPU_VSYNC_SOURCE_WD_TIMER_0) { ··· 180 192 /* make sure that timers are enabled/disabled for vsync state */ 181 193 wmb(); 182 194 } 195 + } 196 + 197 + static void dpu_hw_setup_vsync_source_and_vsync_sel(struct dpu_hw_mdp *mdp, 198 + struct dpu_vsync_source_cfg *cfg) 199 + { 200 + struct dpu_hw_blk_reg_map *c; 201 + u32 reg, i; 202 + static const u32 pp_offset[PINGPONG_MAX] = {0xC, 0x8, 0x4, 0x13, 0x18}; 203 + 204 + if (!mdp || !cfg || (cfg->pp_count > ARRAY_SIZE(cfg->ppnumber))) 205 + return; 206 + 207 + c = &mdp->hw; 208 + 209 + reg = DPU_REG_READ(c, MDP_VSYNC_SEL); 210 + for (i = 0; i < cfg->pp_count; i++) { 211 + int pp_idx = cfg->ppnumber[i] - PINGPONG_0; 212 + 213 + if (pp_idx >= ARRAY_SIZE(pp_offset)) 214 + continue; 215 + 216 + reg &= ~(0xf << pp_offset[pp_idx]); 217 + reg |= (cfg->vsync_source & 0xf) << pp_offset[pp_idx]; 218 + } 219 + DPU_REG_WRITE(c, MDP_VSYNC_SEL, reg); 220 + 221 + dpu_hw_setup_vsync_source(mdp, cfg); 183 222 } 184 223 185 224 static void dpu_hw_get_safe_status(struct dpu_hw_mdp *mdp, ··· 256 241 ops->setup_split_pipe = dpu_hw_setup_split_pipe; 257 242 ops->setup_clk_force_ctrl = dpu_hw_setup_clk_force_ctrl; 258 243 ops->get_danger_status = dpu_hw_get_danger_status; 259 - ops->setup_vsync_source = dpu_hw_setup_vsync_source; 244 + 245 + if (cap & BIT(DPU_MDP_VSYNC_SEL)) 246 + ops->setup_vsync_source = dpu_hw_setup_vsync_source_and_vsync_sel; 247 + else 248 + ops->setup_vsync_source = dpu_hw_setup_vsync_source; 249 + 260 250 ops->get_safe_status = dpu_hw_get_safe_status; 261 251 262 252 if (cap & BIT(DPU_MDP_AUDIO_SELECT))
+52
drivers/gpu/drm/msm/disp/dpu1/dpu_hw_util.c
··· 73 73 #define QSEED3LITE_SEP_LUT_SIZE \ 74 74 (QSEED3LITE_LUT_SIZE * QSEED3LITE_SEPARABLE_LUTS * sizeof(u32)) 75 75 76 + /* QOS_LUT */ 77 + #define QOS_DANGER_LUT 0x00 78 + #define QOS_SAFE_LUT 0x04 79 + #define QOS_CREQ_LUT 0x08 80 + #define QOS_QOS_CTRL 0x0C 81 + #define QOS_CREQ_LUT_0 0x14 82 + #define QOS_CREQ_LUT_1 0x18 83 + 84 + /* QOS_QOS_CTRL */ 85 + #define QOS_QOS_CTRL_DANGER_SAFE_EN BIT(0) 86 + #define QOS_QOS_CTRL_DANGER_VBLANK_MASK GENMASK(5, 4) 87 + #define QOS_QOS_CTRL_VBLANK_EN BIT(16) 88 + #define QOS_QOS_CTRL_CREQ_VBLANK_MASK GENMASK(21, 20) 76 89 77 90 void dpu_reg_write(struct dpu_hw_blk_reg_map *c, 78 91 u32 reg_off, ··· 463 450 return 0; 464 451 } 465 452 453 + void _dpu_hw_setup_qos_lut(struct dpu_hw_blk_reg_map *c, u32 offset, 454 + bool qos_8lvl, 455 + const struct dpu_hw_qos_cfg *cfg) 456 + { 457 + DPU_REG_WRITE(c, offset + QOS_DANGER_LUT, cfg->danger_lut); 458 + DPU_REG_WRITE(c, offset + QOS_SAFE_LUT, cfg->safe_lut); 459 + 460 + if (qos_8lvl) { 461 + DPU_REG_WRITE(c, offset + QOS_CREQ_LUT_0, cfg->creq_lut); 462 + DPU_REG_WRITE(c, offset + QOS_CREQ_LUT_1, cfg->creq_lut >> 32); 463 + } else { 464 + DPU_REG_WRITE(c, offset + QOS_CREQ_LUT, cfg->creq_lut); 465 + } 466 + 467 + DPU_REG_WRITE(c, offset + QOS_QOS_CTRL, 468 + cfg->danger_safe_en ? QOS_QOS_CTRL_DANGER_SAFE_EN : 0); 469 + } 470 + 466 471 void dpu_hw_setup_misr(struct dpu_hw_blk_reg_map *c, 467 472 u32 misr_ctrl_offset, 468 473 bool enable, u32 frame_count) ··· 524 493 *misr_value = DPU_REG_READ(c, misr_signature_offset); 525 494 526 495 return 0; 496 + } 497 + 498 + #define CDP_ENABLE BIT(0) 499 + #define CDP_UBWC_META_ENABLE BIT(1) 500 + #define CDP_TILE_AMORTIZE_ENABLE BIT(2) 501 + #define CDP_PRELOAD_AHEAD_64 BIT(3) 502 + 503 + void dpu_setup_cdp(struct dpu_hw_blk_reg_map *c, u32 offset, 504 + const struct dpu_format *fmt, bool enable) 505 + { 506 + u32 cdp_cntl = CDP_PRELOAD_AHEAD_64; 507 + 508 + if (enable) 509 + cdp_cntl |= CDP_ENABLE; 510 + if (DPU_FORMAT_IS_UBWC(fmt)) 511 + cdp_cntl |= CDP_UBWC_META_ENABLE; 512 + if (DPU_FORMAT_IS_UBWC(fmt) || 513 + DPU_FORMAT_IS_TILE(fmt)) 514 + cdp_cntl |= CDP_TILE_AMORTIZE_ENABLE; 515 + 516 + DPU_REG_WRITE(c, offset, cdp_cntl); 527 517 }
+20 -12
drivers/gpu/drm/msm/disp/dpu1/dpu_hw_util.h
··· 306 306 }; 307 307 308 308 /** 309 - * struct dpu_hw_cdp_cfg : CDP configuration 310 - * @enable: true to enable CDP 311 - * @ubwc_meta_enable: true to enable ubwc metadata preload 312 - * @tile_amortize_enable: true to enable amortization control for tile format 313 - * @preload_ahead: number of request to preload ahead 314 - * DPU_*_CDP_PRELOAD_AHEAD_32, 315 - * DPU_*_CDP_PRELOAD_AHEAD_64 309 + * struct dpu_hw_qos_cfg: pipe QoS configuration 310 + * @danger_lut: LUT for generate danger level based on fill level 311 + * @safe_lut: LUT for generate safe level based on fill level 312 + * @creq_lut: LUT for generate creq level based on fill level 313 + * @creq_vblank: creq value generated to vbif during vertical blanking 314 + * @danger_vblank: danger value generated during vertical blanking 315 + * @vblank_en: enable creq_vblank and danger_vblank during vblank 316 + * @danger_safe_en: enable danger safe generation 316 317 */ 317 - struct dpu_hw_cdp_cfg { 318 - bool enable; 319 - bool ubwc_meta_enable; 320 - bool tile_amortize_enable; 321 - u32 preload_ahead; 318 + struct dpu_hw_qos_cfg { 319 + u32 danger_lut; 320 + u32 safe_lut; 321 + u64 creq_lut; 322 + bool danger_safe_en; 322 323 }; 323 324 324 325 u32 *dpu_hw_util_get_log_mask_ptr(void); ··· 347 346 u32 csc_reg_off, 348 347 const struct dpu_csc_cfg *data, bool csc10); 349 348 349 + void dpu_setup_cdp(struct dpu_hw_blk_reg_map *c, u32 offset, 350 + const struct dpu_format *fmt, bool enable); 351 + 350 352 u64 _dpu_hw_get_qos_lut(const struct dpu_qos_lut_tbl *tbl, 351 353 u32 total_fl); 354 + 355 + void _dpu_hw_setup_qos_lut(struct dpu_hw_blk_reg_map *c, u32 offset, 356 + bool qos_8lvl, 357 + const struct dpu_hw_qos_cfg *cfg); 352 358 353 359 void dpu_hw_setup_misr(struct dpu_hw_blk_reg_map *c, 354 360 u32 misr_ctrl_offset,
+5 -28
drivers/gpu/drm/msm/disp/dpu1/dpu_hw_vbif.c
··· 211 211 ops->set_write_gather_en = dpu_hw_set_write_gather_en; 212 212 } 213 213 214 - static const struct dpu_vbif_cfg *_top_offset(enum dpu_vbif vbif, 215 - const struct dpu_mdss_cfg *m, 216 - void __iomem *addr, 217 - struct dpu_hw_blk_reg_map *b) 218 - { 219 - int i; 220 - 221 - for (i = 0; i < m->vbif_count; i++) { 222 - if (vbif == m->vbif[i].id) { 223 - b->blk_addr = addr + m->vbif[i].base; 224 - b->log_mask = DPU_DBG_MASK_VBIF; 225 - return &m->vbif[i]; 226 - } 227 - } 228 - 229 - return ERR_PTR(-EINVAL); 230 - } 231 - 232 - struct dpu_hw_vbif *dpu_hw_vbif_init(enum dpu_vbif idx, 233 - void __iomem *addr, 234 - const struct dpu_mdss_cfg *m) 214 + struct dpu_hw_vbif *dpu_hw_vbif_init(const struct dpu_vbif_cfg *cfg, 215 + void __iomem *addr) 235 216 { 236 217 struct dpu_hw_vbif *c; 237 - const struct dpu_vbif_cfg *cfg; 238 218 239 219 c = kzalloc(sizeof(*c), GFP_KERNEL); 240 220 if (!c) 241 221 return ERR_PTR(-ENOMEM); 242 222 243 - cfg = _top_offset(idx, m, addr, &c->hw); 244 - if (IS_ERR_OR_NULL(cfg)) { 245 - kfree(c); 246 - return ERR_PTR(-EINVAL); 247 - } 223 + c->hw.blk_addr = addr + cfg->base; 224 + c->hw.log_mask = DPU_DBG_MASK_VBIF; 248 225 249 226 /* 250 227 * Assign ops 251 228 */ 252 - c->idx = idx; 229 + c->idx = cfg->id; 253 230 c->cap = cfg; 254 231 _setup_vbif_ops(&c->ops, c->cap->features); 255 232
+5 -6
drivers/gpu/drm/msm/disp/dpu1/dpu_hw_vbif.h
··· 106 106 }; 107 107 108 108 /** 109 - * dpu_hw_vbif_init - initializes the vbif driver for the passed interface idx 110 - * @idx: Interface index for which driver object is required 109 + * dpu_hw_vbif_init() - Initializes the VBIF driver for the passed 110 + * VBIF catalog entry. 111 + * @cfg: VBIF catalog entry for which driver object is required 111 112 * @addr: Mapped register io address of MDSS 112 - * @m: Pointer to mdss catalog data 113 113 */ 114 - struct dpu_hw_vbif *dpu_hw_vbif_init(enum dpu_vbif idx, 115 - void __iomem *addr, 116 - const struct dpu_mdss_cfg *m); 114 + struct dpu_hw_vbif *dpu_hw_vbif_init(const struct dpu_vbif_cfg *cfg, 115 + void __iomem *addr); 117 116 118 117 void dpu_hw_vbif_destroy(struct dpu_hw_vbif *vbif); 119 118
+16 -70
drivers/gpu/drm/msm/disp/dpu1/dpu_hw_wb.c
··· 49 49 #define WB_OUT_IMAGE_SIZE 0x2C0 50 50 #define WB_OUT_XY 0x2C4 51 51 52 - /* WB_QOS_CTRL */ 53 - #define WB_QOS_CTRL_DANGER_SAFE_EN BIT(0) 54 - 55 - static const struct dpu_wb_cfg *_wb_offset(enum dpu_wb wb, 56 - const struct dpu_mdss_cfg *m, void __iomem *addr, 57 - struct dpu_hw_blk_reg_map *b) 58 - { 59 - int i; 60 - 61 - for (i = 0; i < m->wb_count; i++) { 62 - if (wb == m->wb[i].id) { 63 - b->blk_addr = addr + m->wb[i].base; 64 - b->log_mask = DPU_DBG_MASK_WB; 65 - return &m->wb[i]; 66 - } 67 - } 68 - return ERR_PTR(-EINVAL); 69 - } 70 - 71 52 static void dpu_hw_wb_setup_outaddress(struct dpu_hw_wb *ctx, 72 53 struct dpu_hw_wb_cfg *data) 73 54 { ··· 132 151 } 133 152 134 153 static void dpu_hw_wb_setup_qos_lut(struct dpu_hw_wb *ctx, 135 - struct dpu_hw_wb_qos_cfg *cfg) 154 + struct dpu_hw_qos_cfg *cfg) 136 155 { 137 - struct dpu_hw_blk_reg_map *c = &ctx->hw; 138 - u32 qos_ctrl = 0; 139 - 140 156 if (!ctx || !cfg) 141 157 return; 142 158 143 - DPU_REG_WRITE(c, WB_DANGER_LUT, cfg->danger_lut); 144 - DPU_REG_WRITE(c, WB_SAFE_LUT, cfg->safe_lut); 145 - 146 - /* 147 - * for chipsets not using DPU_WB_QOS_8LVL but still using DPU 148 - * driver such as msm8998, the reset value of WB_CREQ_LUT is 149 - * sufficient for writeback to work. SW doesn't need to explicitly 150 - * program a value. 151 - */ 152 - if (ctx->caps && test_bit(DPU_WB_QOS_8LVL, &ctx->caps->features)) { 153 - DPU_REG_WRITE(c, WB_CREQ_LUT_0, cfg->creq_lut); 154 - DPU_REG_WRITE(c, WB_CREQ_LUT_1, cfg->creq_lut >> 32); 155 - } 156 - 157 - if (cfg->danger_safe_en) 158 - qos_ctrl |= WB_QOS_CTRL_DANGER_SAFE_EN; 159 - 160 - DPU_REG_WRITE(c, WB_QOS_CTRL, qos_ctrl); 159 + _dpu_hw_setup_qos_lut(&ctx->hw, WB_DANGER_LUT, 160 + test_bit(DPU_WB_QOS_8LVL, &ctx->caps->features), 161 + cfg); 161 162 } 162 163 163 164 static void dpu_hw_wb_setup_cdp(struct dpu_hw_wb *ctx, 164 - struct dpu_hw_cdp_cfg *cfg) 165 + const struct dpu_format *fmt, 166 + bool enable) 165 167 { 166 - struct dpu_hw_blk_reg_map *c; 167 - u32 cdp_cntl = 0; 168 - 169 - if (!ctx || !cfg) 168 + if (!ctx) 170 169 return; 171 170 172 - c = &ctx->hw; 173 - 174 - if (cfg->enable) 175 - cdp_cntl |= BIT(0); 176 - if (cfg->ubwc_meta_enable) 177 - cdp_cntl |= BIT(1); 178 - if (cfg->preload_ahead == DPU_WB_CDP_PRELOAD_AHEAD_64) 179 - cdp_cntl |= BIT(3); 180 - 181 - DPU_REG_WRITE(c, WB_CDP_CNTL, cdp_cntl); 171 + dpu_setup_cdp(&ctx->hw, WB_CDP_CNTL, fmt, enable); 182 172 } 183 173 184 174 static void dpu_hw_wb_bind_pingpong_blk( 185 175 struct dpu_hw_wb *ctx, 186 - bool enable, const enum dpu_pingpong pp) 176 + const enum dpu_pingpong pp) 187 177 { 188 178 struct dpu_hw_blk_reg_map *c; 189 179 int mux_cfg; ··· 167 215 mux_cfg = DPU_REG_READ(c, WB_MUX); 168 216 mux_cfg &= ~0xf; 169 217 170 - if (enable) 218 + if (pp) 171 219 mux_cfg |= (pp - PINGPONG_0) & 0x7; 172 220 else 173 221 mux_cfg |= 0xf; ··· 194 242 ops->bind_pingpong_blk = dpu_hw_wb_bind_pingpong_blk; 195 243 } 196 244 197 - struct dpu_hw_wb *dpu_hw_wb_init(enum dpu_wb idx, 198 - void __iomem *addr, const struct dpu_mdss_cfg *m) 245 + struct dpu_hw_wb *dpu_hw_wb_init(const struct dpu_wb_cfg *cfg, 246 + void __iomem *addr) 199 247 { 200 248 struct dpu_hw_wb *c; 201 - const struct dpu_wb_cfg *cfg; 202 249 203 - if (!addr || !m) 250 + if (!addr) 204 251 return ERR_PTR(-EINVAL); 205 252 206 253 c = kzalloc(sizeof(*c), GFP_KERNEL); 207 254 if (!c) 208 255 return ERR_PTR(-ENOMEM); 209 256 210 - cfg = _wb_offset(idx, m, addr, &c->hw); 211 - if (IS_ERR(cfg)) { 212 - WARN(1, "Unable to find wb idx=%d\n", idx); 213 - kfree(c); 214 - return ERR_PTR(-EINVAL); 215 - } 257 + c->hw.blk_addr = addr + cfg->base; 258 + c->hw.log_mask = DPU_DBG_MASK_WB; 216 259 217 260 /* Assign ops */ 218 - c->mdp = &m->mdp[0]; 219 - c->idx = idx; 261 + c->idx = cfg->id; 220 262 c->caps = cfg; 221 263 _setup_wb_ops(&c->ops, c->caps->features); 222 264
+9 -36
drivers/gpu/drm/msm/disp/dpu1/dpu_hw_wb.h
··· 22 22 }; 23 23 24 24 /** 25 - * enum CDP preload ahead address size 26 - */ 27 - enum { 28 - DPU_WB_CDP_PRELOAD_AHEAD_32, 29 - DPU_WB_CDP_PRELOAD_AHEAD_64 30 - }; 31 - 32 - /** 33 - * struct dpu_hw_wb_qos_cfg : Writeback pipe QoS configuration 34 - * @danger_lut: LUT for generate danger level based on fill level 35 - * @safe_lut: LUT for generate safe level based on fill level 36 - * @creq_lut: LUT for generate creq level based on fill level 37 - * @danger_safe_en: enable danger safe generation 38 - */ 39 - struct dpu_hw_wb_qos_cfg { 40 - u32 danger_lut; 41 - u32 safe_lut; 42 - u64 creq_lut; 43 - bool danger_safe_en; 44 - }; 45 - 46 - /** 47 25 * 48 26 * struct dpu_hw_wb_ops : Interface to the wb hw driver functions 49 27 * Assumption is these functions will be called after clocks are enabled ··· 42 64 struct dpu_hw_wb_cfg *wb); 43 65 44 66 void (*setup_qos_lut)(struct dpu_hw_wb *ctx, 45 - struct dpu_hw_wb_qos_cfg *cfg); 67 + struct dpu_hw_qos_cfg *cfg); 46 68 47 69 void (*setup_cdp)(struct dpu_hw_wb *ctx, 48 - struct dpu_hw_cdp_cfg *cfg); 70 + const struct dpu_format *fmt, 71 + bool enable); 49 72 50 73 void (*bind_pingpong_blk)(struct dpu_hw_wb *ctx, 51 - bool enable, const enum dpu_pingpong pp); 74 + const enum dpu_pingpong pp); 52 75 }; 53 76 54 77 /** 55 78 * struct dpu_hw_wb : WB driver object 56 79 * @hw: block hardware details 57 - * @mdp: pointer to associated mdp portion of the catalog 58 80 * @idx: hardware index number within type 59 81 * @wb_hw_caps: hardware capabilities 60 82 * @ops: function pointers 61 - * @hw_mdp: MDP top level hardware block 62 83 */ 63 84 struct dpu_hw_wb { 64 85 struct dpu_hw_blk_reg_map hw; 65 - const struct dpu_mdp_cfg *mdp; 66 86 67 87 /* wb path */ 68 88 int idx; ··· 68 92 69 93 /* ops */ 70 94 struct dpu_hw_wb_ops ops; 71 - 72 - struct dpu_hw_mdp *hw_mdp; 73 95 }; 74 96 75 97 /** 76 - * dpu_hw_wb_init(): Initializes and return writeback hw driver object. 77 - * @idx: wb_path index for which driver object is required 98 + * dpu_hw_wb_init() - Initializes the writeback hw driver object. 99 + * @cfg: wb_path catalog entry for which driver object is required 78 100 * @addr: mapped register io address of MDP 79 - * @m : pointer to mdss catalog data 101 + * Return: Error code or allocated dpu_hw_wb context 80 102 */ 81 - struct dpu_hw_wb *dpu_hw_wb_init(enum dpu_wb idx, 82 - void __iomem *addr, 83 - const struct dpu_mdss_cfg *m); 103 + struct dpu_hw_wb *dpu_hw_wb_init(const struct dpu_wb_cfg *cfg, 104 + void __iomem *addr); 84 105 85 106 /** 86 107 * dpu_hw_wb_destroy(): Destroy writeback hw driver object.
+79 -58
drivers/gpu/drm/msm/disp/dpu1/dpu_kms.c
··· 57 57 static int _dpu_danger_signal_status(struct seq_file *s, 58 58 bool danger_status) 59 59 { 60 - struct dpu_kms *kms = (struct dpu_kms *)s->private; 61 60 struct dpu_danger_safe_status status; 61 + struct dpu_kms *kms = s->private; 62 62 int i; 63 63 64 64 if (!kms->hw_mdp) { ··· 535 535 !msm_dsi_is_master_dsi(priv->dsi[i])) 536 536 continue; 537 537 538 - encoder = dpu_encoder_init(dev, DRM_MODE_ENCODER_DSI); 538 + memset(&info, 0, sizeof(info)); 539 + info.intf_type = INTF_DSI; 540 + 541 + info.h_tile_instance[info.num_of_h_tiles++] = i; 542 + if (msm_dsi_is_bonded_dsi(priv->dsi[i])) 543 + info.h_tile_instance[info.num_of_h_tiles++] = other; 544 + 545 + info.is_cmd_mode = msm_dsi_is_cmd_mode(priv->dsi[i]); 546 + 547 + info.dsc = msm_dsi_get_dsc_config(priv->dsi[i]); 548 + 549 + encoder = dpu_encoder_init(dev, DRM_MODE_ENCODER_DSI, &info); 539 550 if (IS_ERR(encoder)) { 540 551 DPU_ERROR("encoder init failed for dsi display\n"); 541 552 return PTR_ERR(encoder); 542 553 } 543 - 544 - memset(&info, 0, sizeof(info)); 545 - info.intf_type = encoder->encoder_type; 546 554 547 555 rc = msm_dsi_modeset_init(priv->dsi[i], dev, encoder); 548 556 if (rc) { ··· 559 551 break; 560 552 } 561 553 562 - info.h_tile_instance[info.num_of_h_tiles++] = i; 563 - info.is_cmd_mode = msm_dsi_is_cmd_mode(priv->dsi[i]); 564 - 565 - info.dsc = msm_dsi_get_dsc_config(priv->dsi[i]); 566 - 567 554 if (msm_dsi_is_bonded_dsi(priv->dsi[i]) && priv->dsi[other]) { 568 555 rc = msm_dsi_modeset_init(priv->dsi[other], dev, encoder); 569 556 if (rc) { ··· 566 563 other, rc); 567 564 break; 568 565 } 569 - 570 - info.h_tile_instance[info.num_of_h_tiles++] = other; 571 566 } 572 - 573 - rc = dpu_encoder_setup(dev, encoder, &info); 574 - if (rc) 575 - DPU_ERROR("failed to setup DPU encoder %d: rc:%d\n", 576 - encoder->base.id, rc); 577 567 } 578 568 579 569 return rc; ··· 585 589 if (!priv->dp[i]) 586 590 continue; 587 591 588 - encoder = dpu_encoder_init(dev, DRM_MODE_ENCODER_TMDS); 592 + memset(&info, 0, sizeof(info)); 593 + info.num_of_h_tiles = 1; 594 + info.h_tile_instance[0] = i; 595 + info.intf_type = INTF_DP; 596 + 597 + encoder = dpu_encoder_init(dev, DRM_MODE_ENCODER_TMDS, &info); 589 598 if (IS_ERR(encoder)) { 590 599 DPU_ERROR("encoder init failed for dsi display\n"); 591 600 return PTR_ERR(encoder); 592 601 } 593 602 594 - memset(&info, 0, sizeof(info)); 595 603 rc = msm_dp_modeset_init(priv->dp[i], dev, encoder); 596 604 if (rc) { 597 605 DPU_ERROR("modeset_init failed for DP, rc = %d\n", rc); 598 606 drm_encoder_cleanup(encoder); 599 607 return rc; 600 608 } 609 + } 601 610 602 - info.num_of_h_tiles = 1; 603 - info.h_tile_instance[0] = i; 604 - info.intf_type = encoder->encoder_type; 605 - rc = dpu_encoder_setup(dev, encoder, &info); 606 - if (rc) { 607 - DPU_ERROR("failed to setup DPU encoder %d: rc:%d\n", 608 - encoder->base.id, rc); 609 - return rc; 610 - } 611 + return 0; 612 + } 613 + 614 + static int _dpu_kms_initialize_hdmi(struct drm_device *dev, 615 + struct msm_drm_private *priv, 616 + struct dpu_kms *dpu_kms) 617 + { 618 + struct drm_encoder *encoder = NULL; 619 + struct msm_display_info info; 620 + int rc; 621 + 622 + if (!priv->hdmi) 623 + return 0; 624 + 625 + memset(&info, 0, sizeof(info)); 626 + info.num_of_h_tiles = 1; 627 + info.h_tile_instance[0] = 0; 628 + info.intf_type = INTF_HDMI; 629 + 630 + encoder = dpu_encoder_init(dev, DRM_MODE_ENCODER_TMDS, &info); 631 + if (IS_ERR(encoder)) { 632 + DPU_ERROR("encoder init failed for HDMI display\n"); 633 + return PTR_ERR(encoder); 634 + } 635 + 636 + rc = msm_hdmi_modeset_init(priv->hdmi, dev, encoder); 637 + if (rc) { 638 + DPU_ERROR("modeset_init failed for DP, rc = %d\n", rc); 639 + drm_encoder_cleanup(encoder); 640 + return rc; 611 641 } 612 642 613 643 return 0; ··· 647 625 struct msm_display_info info; 648 626 int rc; 649 627 650 - encoder = dpu_encoder_init(dev, DRM_MODE_ENCODER_VIRTUAL); 628 + memset(&info, 0, sizeof(info)); 629 + 630 + info.num_of_h_tiles = 1; 631 + /* use only WB idx 2 instance for DPU */ 632 + info.h_tile_instance[0] = WB_2; 633 + info.intf_type = INTF_WB; 634 + 635 + encoder = dpu_encoder_init(dev, DRM_MODE_ENCODER_VIRTUAL, &info); 651 636 if (IS_ERR(encoder)) { 652 637 DPU_ERROR("encoder init failed for dsi display\n"); 653 638 return PTR_ERR(encoder); 654 639 } 655 - 656 - memset(&info, 0, sizeof(info)); 657 640 658 641 rc = dpu_writeback_init(dev, encoder, wb_formats, 659 642 n_formats); 660 643 if (rc) { 661 644 DPU_ERROR("dpu_writeback_init, rc = %d\n", rc); 662 645 drm_encoder_cleanup(encoder); 663 - return rc; 664 - } 665 - 666 - info.num_of_h_tiles = 1; 667 - /* use only WB idx 2 instance for DPU */ 668 - info.h_tile_instance[0] = WB_2; 669 - info.intf_type = encoder->encoder_type; 670 - 671 - rc = dpu_encoder_setup(dev, encoder, &info); 672 - if (rc) { 673 - DPU_ERROR("failed to setup DPU encoder %d: rc:%d\n", 674 - encoder->base.id, rc); 675 646 return rc; 676 647 } 677 648 ··· 695 680 rc = _dpu_kms_initialize_displayport(dev, priv, dpu_kms); 696 681 if (rc) { 697 682 DPU_ERROR("initialize_DP failed, rc = %d\n", rc); 683 + return rc; 684 + } 685 + 686 + rc = _dpu_kms_initialize_hdmi(dev, priv, dpu_kms); 687 + if (rc) { 688 + DPU_ERROR("initialize HDMI failed, rc = %d\n", rc); 698 689 return rc; 699 690 } 700 691 ··· 1000 979 return 0; 1001 980 } 1002 981 1003 - u64 dpu_kms_get_clk_rate(struct dpu_kms *dpu_kms, char *clock_name) 982 + unsigned long dpu_kms_get_clk_rate(struct dpu_kms *dpu_kms, char *clock_name) 1004 983 { 1005 984 struct clk *clk; 1006 985 1007 986 clk = msm_clk_bulk_get_clock(dpu_kms->clocks, dpu_kms->num_clocks, clock_name); 1008 987 if (!clk) 1009 - return -EINVAL; 988 + return 0; 1010 989 1011 990 return clk_get_rate(clk); 1012 991 } ··· 1025 1004 1026 1005 dpu_kms = to_dpu_kms(kms); 1027 1006 dev = dpu_kms->dev; 1007 + 1008 + dev->mode_config.cursor_width = 512; 1009 + dev->mode_config.cursor_height = 512; 1028 1010 1029 1011 rc = dpu_kms_global_obj_init(dpu_kms); 1030 1012 if (rc) ··· 1055 1031 if (IS_ERR(dpu_kms->vbif[VBIF_NRT])) { 1056 1032 dpu_kms->vbif[VBIF_NRT] = NULL; 1057 1033 DPU_DEBUG("VBIF NRT is not defined"); 1058 - } 1059 - 1060 - dpu_kms->reg_dma = msm_ioremap_quiet(dpu_kms->pdev, "regdma"); 1061 - if (IS_ERR(dpu_kms->reg_dma)) { 1062 - dpu_kms->reg_dma = NULL; 1063 - DPU_DEBUG("REG_DMA is not defined"); 1064 1034 } 1065 1035 1066 1036 dpu_kms_parse_data_bus_icc_path(dpu_kms); ··· 1102 1084 } 1103 1085 1104 1086 for (i = 0; i < dpu_kms->catalog->vbif_count; i++) { 1105 - u32 vbif_idx = dpu_kms->catalog->vbif[i].id; 1087 + struct dpu_hw_vbif *hw; 1088 + const struct dpu_vbif_cfg *vbif = &dpu_kms->catalog->vbif[i]; 1106 1089 1107 - dpu_kms->hw_vbif[vbif_idx] = dpu_hw_vbif_init(vbif_idx, 1108 - dpu_kms->vbif[vbif_idx], dpu_kms->catalog); 1109 - if (IS_ERR(dpu_kms->hw_vbif[vbif_idx])) { 1110 - rc = PTR_ERR(dpu_kms->hw_vbif[vbif_idx]); 1111 - DPU_ERROR("failed to init vbif %d: %d\n", vbif_idx, rc); 1112 - dpu_kms->hw_vbif[vbif_idx] = NULL; 1090 + hw = dpu_hw_vbif_init(vbif, dpu_kms->vbif[vbif->id]); 1091 + if (IS_ERR(hw)) { 1092 + rc = PTR_ERR(hw); 1093 + DPU_ERROR("failed to init vbif %d: %d\n", vbif->id, rc); 1113 1094 goto power_error; 1114 1095 } 1096 + 1097 + dpu_kms->hw_vbif[vbif->id] = hw; 1115 1098 } 1116 1099 1117 1100 rc = dpu_core_perf_init(&dpu_kms->perf, dev, dpu_kms->catalog, ··· 1305 1286 { .compatible = "qcom,sc8180x-dpu", .data = &dpu_sc8180x_cfg, }, 1306 1287 { .compatible = "qcom,sc8280xp-dpu", .data = &dpu_sc8280xp_cfg, }, 1307 1288 { .compatible = "qcom,sm6115-dpu", .data = &dpu_sm6115_cfg, }, 1289 + { .compatible = "qcom,sm6350-dpu", .data = &dpu_sm6350_cfg, }, 1290 + { .compatible = "qcom,sm6375-dpu", .data = &dpu_sm6375_cfg, }, 1308 1291 { .compatible = "qcom,sm8150-dpu", .data = &dpu_sm8150_cfg, }, 1309 1292 { .compatible = "qcom,sm8250-dpu", .data = &dpu_sm8250_cfg, }, 1310 1293 { .compatible = "qcom,sm8350-dpu", .data = &dpu_sm8350_cfg, },
+6 -4
drivers/gpu/drm/msm/disp/dpu1/dpu_kms.h
··· 63 63 #define ktime_compare_safe(A, B) \ 64 64 ktime_compare(ktime_sub((A), (B)), ktime_set(0, 0)) 65 65 66 - #define DPU_NAME_SIZE 12 67 - 68 66 struct dpu_kms { 69 67 struct msm_kms base; 70 68 struct drm_device *dev; 71 69 const struct dpu_mdss_cfg *catalog; 72 70 73 71 /* io/register spaces: */ 74 - void __iomem *mmio, *vbif[VBIF_MAX], *reg_dma; 72 + void __iomem *mmio, *vbif[VBIF_MAX]; 75 73 76 74 struct regulator *vdd; 77 75 struct regulator *mmagic; ··· 115 117 u32 frame_count; 116 118 u32 line_count; 117 119 }; 120 + 121 + #define DPU_ENC_WR_PTR_START_TIMEOUT_US 20000 122 + 123 + #define DPU_ENC_MAX_POLL_TIMEOUT_US 2000 118 124 119 125 #define to_dpu_kms(x) container_of(x, struct dpu_kms, base) 120 126 ··· 203 201 * 204 202 * Return: current clock rate 205 203 */ 206 - u64 dpu_kms_get_clk_rate(struct dpu_kms *dpu_kms, char *clock_name); 204 + unsigned long dpu_kms_get_clk_rate(struct dpu_kms *dpu_kms, char *clock_name); 207 205 208 206 #endif /* __dpu_kms_H__ */
+47 -120
drivers/gpu/drm/msm/disp/dpu1/dpu_plane.c
··· 42 42 #define SHARP_SMOOTH_THR_DEFAULT 8 43 43 #define SHARP_NOISE_THR_DEFAULT 2 44 44 45 - #define DPU_NAME_SIZE 12 46 - 47 45 #define DPU_PLANE_COLOR_FILL_FLAG BIT(31) 48 46 #define DPU_ZPOS_MAX 255 49 47 ··· 66 68 67 69 DRM_FORMAT_NV12, 68 70 DRM_FORMAT_P010, 69 - }; 70 - 71 - /** 72 - * enum dpu_plane_qos - Different qos configurations for each pipe 73 - * 74 - * @DPU_PLANE_QOS_VBLANK_CTRL: Setup VBLANK qos for the pipe. 75 - * @DPU_PLANE_QOS_VBLANK_AMORTIZE: Enables Amortization within pipe. 76 - * this configuration is mutually exclusive from VBLANK_CTRL. 77 - * @DPU_PLANE_QOS_PANIC_CTRL: Setup panic for the pipe. 78 - */ 79 - enum dpu_plane_qos { 80 - DPU_PLANE_QOS_VBLANK_CTRL = BIT(0), 81 - DPU_PLANE_QOS_VBLANK_AMORTIZE = BIT(1), 82 - DPU_PLANE_QOS_PANIC_CTRL = BIT(2), 83 71 }; 84 72 85 73 /* ··· 188 204 * _dpu_plane_calc_fill_level - calculate fill level of the given source format 189 205 * @plane: Pointer to drm plane 190 206 * @pipe: Pointer to software pipe 207 + * @lut_usage: LUT usecase 191 208 * @fmt: Pointer to source buffer format 192 209 * @src_width: width of source buffer 193 210 * Return: fill level corresponding to the source buffer/format or 0 if error 194 211 */ 195 212 static int _dpu_plane_calc_fill_level(struct drm_plane *plane, 196 213 struct dpu_sw_pipe *pipe, 214 + enum dpu_qos_lut_usage lut_usage, 197 215 const struct dpu_format *fmt, u32 src_width) 198 216 { 199 217 struct dpu_plane *pdpu; ··· 206 220 DPU_ERROR("invalid arguments\n"); 207 221 return 0; 208 222 } 223 + 224 + if (lut_usage == DPU_QOS_LUT_USAGE_NRT) 225 + return 0; 209 226 210 227 pdpu = to_dpu_plane(plane); 211 228 fixed_buff_size = pdpu->catalog->caps->pixel_ram_size; ··· 255 266 const struct dpu_format *fmt, struct dpu_sw_pipe_cfg *pipe_cfg) 256 267 { 257 268 struct dpu_plane *pdpu = to_dpu_plane(plane); 258 - u64 qos_lut; 259 - u32 total_fl = 0, lut_usage; 269 + struct dpu_hw_qos_cfg cfg; 270 + u32 total_fl, lut_usage; 260 271 261 272 if (!pdpu->is_rt_pipe) { 262 273 lut_usage = DPU_QOS_LUT_USAGE_NRT; 263 274 } else { 264 - total_fl = _dpu_plane_calc_fill_level(plane, pipe, fmt, 265 - drm_rect_width(&pipe_cfg->src_rect)); 266 - 267 275 if (fmt && DPU_FORMAT_IS_LINEAR(fmt)) 268 276 lut_usage = DPU_QOS_LUT_USAGE_LINEAR; 269 277 else 270 278 lut_usage = DPU_QOS_LUT_USAGE_MACROTILE; 271 279 } 272 280 273 - qos_lut = _dpu_hw_get_qos_lut( 274 - &pdpu->catalog->perf->qos_lut_tbl[lut_usage], total_fl); 281 + total_fl = _dpu_plane_calc_fill_level(plane, pipe, lut_usage, fmt, 282 + drm_rect_width(&pipe_cfg->src_rect)); 283 + 284 + cfg.creq_lut = _dpu_hw_get_qos_lut(&pdpu->catalog->perf->qos_lut_tbl[lut_usage], total_fl); 285 + cfg.danger_lut = pdpu->catalog->perf->danger_lut_tbl[lut_usage]; 286 + cfg.safe_lut = pdpu->catalog->perf->safe_lut_tbl[lut_usage]; 287 + 288 + if (pipe->sspp->idx != SSPP_CURSOR0 && 289 + pipe->sspp->idx != SSPP_CURSOR1 && 290 + pdpu->is_rt_pipe) 291 + cfg.danger_safe_en = true; 292 + 293 + DPU_DEBUG_PLANE(pdpu, "pnum:%d ds:%d is_rt:%d\n", 294 + pdpu->pipe - SSPP_VIG0, 295 + cfg.danger_safe_en, 296 + pdpu->is_rt_pipe); 275 297 276 298 trace_dpu_perf_set_qos_luts(pipe->sspp->idx - SSPP_VIG0, 277 299 (fmt) ? fmt->base.pixel_format : 0, 278 - pdpu->is_rt_pipe, total_fl, qos_lut, lut_usage); 300 + pdpu->is_rt_pipe, total_fl, cfg.creq_lut, lut_usage); 279 301 280 302 DPU_DEBUG_PLANE(pdpu, "pnum:%d fmt: %4.4s rt:%d fl:%u lut:0x%llx\n", 281 303 pdpu->pipe - SSPP_VIG0, 282 304 fmt ? (char *)&fmt->base.pixel_format : NULL, 283 - pdpu->is_rt_pipe, total_fl, qos_lut); 284 - 285 - pipe->sspp->ops.setup_creq_lut(pipe->sspp, qos_lut); 286 - } 287 - 288 - /** 289 - * _dpu_plane_set_danger_lut - set danger/safe LUT of the given plane 290 - * @plane: Pointer to drm plane 291 - * @pipe: Pointer to software pipe 292 - * @fmt: Pointer to source buffer format 293 - */ 294 - static void _dpu_plane_set_danger_lut(struct drm_plane *plane, 295 - struct dpu_sw_pipe *pipe, 296 - const struct dpu_format *fmt) 297 - { 298 - struct dpu_plane *pdpu = to_dpu_plane(plane); 299 - u32 danger_lut, safe_lut; 300 - 301 - if (!pdpu->is_rt_pipe) { 302 - danger_lut = pdpu->catalog->perf->danger_lut_tbl 303 - [DPU_QOS_LUT_USAGE_NRT]; 304 - safe_lut = pdpu->catalog->perf->safe_lut_tbl 305 - [DPU_QOS_LUT_USAGE_NRT]; 306 - } else { 307 - if (fmt && DPU_FORMAT_IS_LINEAR(fmt)) { 308 - danger_lut = pdpu->catalog->perf->danger_lut_tbl 309 - [DPU_QOS_LUT_USAGE_LINEAR]; 310 - safe_lut = pdpu->catalog->perf->safe_lut_tbl 311 - [DPU_QOS_LUT_USAGE_LINEAR]; 312 - } else { 313 - danger_lut = pdpu->catalog->perf->danger_lut_tbl 314 - [DPU_QOS_LUT_USAGE_MACROTILE]; 315 - safe_lut = pdpu->catalog->perf->safe_lut_tbl 316 - [DPU_QOS_LUT_USAGE_MACROTILE]; 317 - } 318 - } 305 + pdpu->is_rt_pipe, total_fl, cfg.creq_lut); 319 306 320 307 trace_dpu_perf_set_danger_luts(pdpu->pipe - SSPP_VIG0, 321 308 (fmt) ? fmt->base.pixel_format : 0, 322 309 (fmt) ? fmt->fetch_mode : 0, 323 - danger_lut, 324 - safe_lut); 310 + cfg.danger_lut, 311 + cfg.safe_lut); 325 312 326 313 DPU_DEBUG_PLANE(pdpu, "pnum:%d fmt: %4.4s mode:%d luts[0x%x, 0x%x]\n", 327 314 pdpu->pipe - SSPP_VIG0, 328 315 fmt ? (char *)&fmt->base.pixel_format : NULL, 329 316 fmt ? fmt->fetch_mode : -1, 330 - danger_lut, 331 - safe_lut); 317 + cfg.danger_lut, 318 + cfg.safe_lut); 332 319 333 - pipe->sspp->ops.setup_danger_safe_lut(pipe->sspp, 334 - danger_lut, safe_lut); 320 + pipe->sspp->ops.setup_qos_lut(pipe->sspp, &cfg); 335 321 } 336 322 337 323 /** ··· 314 350 * @plane: Pointer to drm plane 315 351 * @pipe: Pointer to software pipe 316 352 * @enable: true to enable QoS control 317 - * @flags: QoS control mode (enum dpu_plane_qos) 318 353 */ 319 354 static void _dpu_plane_set_qos_ctrl(struct drm_plane *plane, 320 355 struct dpu_sw_pipe *pipe, 321 - bool enable, u32 flags) 356 + bool enable) 322 357 { 323 358 struct dpu_plane *pdpu = to_dpu_plane(plane); 324 - struct dpu_hw_pipe_qos_cfg pipe_qos_cfg; 325 359 326 - memset(&pipe_qos_cfg, 0, sizeof(pipe_qos_cfg)); 360 + if (!pdpu->is_rt_pipe) 361 + enable = false; 327 362 328 - if (flags & DPU_PLANE_QOS_VBLANK_CTRL) { 329 - pipe_qos_cfg.creq_vblank = pipe->sspp->cap->sblk->creq_vblank; 330 - pipe_qos_cfg.danger_vblank = 331 - pipe->sspp->cap->sblk->danger_vblank; 332 - pipe_qos_cfg.vblank_en = enable; 333 - } 334 - 335 - if (flags & DPU_PLANE_QOS_VBLANK_AMORTIZE) { 336 - /* this feature overrules previous VBLANK_CTRL */ 337 - pipe_qos_cfg.vblank_en = false; 338 - pipe_qos_cfg.creq_vblank = 0; /* clear vblank bits */ 339 - } 340 - 341 - if (flags & DPU_PLANE_QOS_PANIC_CTRL) 342 - pipe_qos_cfg.danger_safe_en = enable; 343 - 344 - if (!pdpu->is_rt_pipe) { 345 - pipe_qos_cfg.vblank_en = false; 346 - pipe_qos_cfg.danger_safe_en = false; 347 - } 348 - 349 - DPU_DEBUG_PLANE(pdpu, "pnum:%d ds:%d vb:%d pri[0x%x, 0x%x] is_rt:%d\n", 363 + DPU_DEBUG_PLANE(pdpu, "pnum:%d ds:%d is_rt:%d\n", 350 364 pdpu->pipe - SSPP_VIG0, 351 - pipe_qos_cfg.danger_safe_en, 352 - pipe_qos_cfg.vblank_en, 353 - pipe_qos_cfg.creq_vblank, 354 - pipe_qos_cfg.danger_vblank, 365 + enable, 355 366 pdpu->is_rt_pipe); 356 367 357 368 pipe->sspp->ops.setup_qos_ctrl(pipe->sspp, 358 - &pipe_qos_cfg); 369 + enable); 359 370 } 360 371 361 372 /** ··· 1018 1079 pipe->sspp->ops.setup_sourceaddress(pipe, layout); 1019 1080 } 1020 1081 1021 - _dpu_plane_set_qos_ctrl(plane, pipe, false, DPU_PLANE_QOS_PANIC_CTRL); 1022 - 1023 1082 /* override for color fill */ 1024 1083 if (pdpu->color_fill & DPU_PLANE_COLOR_FILL_FLAG) { 1084 + _dpu_plane_set_qos_ctrl(plane, pipe, false); 1085 + 1025 1086 /* skip remaining processing on color fill */ 1026 1087 return; 1027 1088 } ··· 1055 1116 pipe->sspp->ops.setup_format(pipe, fmt, src_flags); 1056 1117 1057 1118 if (pipe->sspp->ops.setup_cdp) { 1058 - struct dpu_hw_cdp_cfg cdp_cfg; 1119 + const struct dpu_perf_cfg *perf = pdpu->catalog->perf; 1059 1120 1060 - memset(&cdp_cfg, 0, sizeof(struct dpu_hw_cdp_cfg)); 1061 - 1062 - cdp_cfg.enable = pdpu->catalog->perf->cdp_cfg 1063 - [DPU_PERF_CDP_USAGE_RT].rd_enable; 1064 - cdp_cfg.ubwc_meta_enable = 1065 - DPU_FORMAT_IS_UBWC(fmt); 1066 - cdp_cfg.tile_amortize_enable = 1067 - DPU_FORMAT_IS_UBWC(fmt) || 1068 - DPU_FORMAT_IS_TILE(fmt); 1069 - cdp_cfg.preload_ahead = DPU_SSPP_CDP_PRELOAD_AHEAD_64; 1070 - 1071 - pipe->sspp->ops.setup_cdp(pipe, &cdp_cfg); 1121 + pipe->sspp->ops.setup_cdp(pipe, fmt, 1122 + perf->cdp_cfg[DPU_PERF_CDP_USAGE_RT].rd_enable); 1072 1123 } 1073 1124 } 1074 1125 1075 1126 _dpu_plane_set_qos_lut(plane, pipe, fmt, pipe_cfg); 1076 - _dpu_plane_set_danger_lut(plane, pipe, fmt); 1077 1127 1078 - if (plane->type != DRM_PLANE_TYPE_CURSOR) { 1079 - _dpu_plane_set_qos_ctrl(plane, pipe, true, DPU_PLANE_QOS_PANIC_CTRL); 1128 + if (pipe->sspp->idx != SSPP_CURSOR0 && 1129 + pipe->sspp->idx != SSPP_CURSOR1) 1080 1130 _dpu_plane_set_ot_limit(plane, pipe, pipe_cfg, frame_rate); 1081 - } 1082 1131 1083 1132 if (pstate->needs_qos_remap) 1084 1133 _dpu_plane_set_qos_remap(plane, pipe); ··· 1181 1254 1182 1255 if (pdpu) { 1183 1256 pstate = to_dpu_plane_state(plane->state); 1184 - _dpu_plane_set_qos_ctrl(plane, &pstate->pipe, false, DPU_PLANE_QOS_PANIC_CTRL); 1257 + _dpu_plane_set_qos_ctrl(plane, &pstate->pipe, false); 1185 1258 1186 1259 if (pstate->r_pipe.sspp) 1187 - _dpu_plane_set_qos_ctrl(plane, &pstate->r_pipe, false, DPU_PLANE_QOS_PANIC_CTRL); 1260 + _dpu_plane_set_qos_ctrl(plane, &pstate->r_pipe, false); 1188 1261 1189 1262 mutex_destroy(&pdpu->lock); 1190 1263 ··· 1341 1414 return; 1342 1415 1343 1416 pm_runtime_get_sync(&dpu_kms->pdev->dev); 1344 - _dpu_plane_set_qos_ctrl(plane, &pstate->pipe, enable, DPU_PLANE_QOS_PANIC_CTRL); 1417 + _dpu_plane_set_qos_ctrl(plane, &pstate->pipe, enable); 1345 1418 if (pstate->r_pipe.sspp) 1346 - _dpu_plane_set_qos_ctrl(plane, &pstate->r_pipe, enable, DPU_PLANE_QOS_PANIC_CTRL); 1419 + _dpu_plane_set_qos_ctrl(plane, &pstate->r_pipe, enable); 1347 1420 pm_runtime_put_sync(&dpu_kms->pdev->dev); 1348 1421 } 1349 1422 #endif
+15 -53
drivers/gpu/drm/msm/disp/dpu1/dpu_rm.c
··· 1 1 // SPDX-License-Identifier: GPL-2.0-only 2 2 /* 3 3 * Copyright (c) 2016-2018, The Linux Foundation. All rights reserved. 4 + * Copyright (c) 2023 Qualcomm Innovation Center, Inc. All rights reserved. 4 5 */ 5 6 6 7 #define pr_fmt(fmt) "[drm:%s] " fmt, __func__ ··· 118 117 struct dpu_hw_mixer *hw; 119 118 const struct dpu_lm_cfg *lm = &cat->mixer[i]; 120 119 121 - if (lm->pingpong == PINGPONG_MAX) { 122 - DPU_DEBUG("skip mixer %d without pingpong\n", lm->id); 123 - continue; 124 - } 125 - 126 - if (lm->id < LM_0 || lm->id >= LM_MAX) { 127 - DPU_ERROR("skip mixer %d with invalid id\n", lm->id); 128 - continue; 129 - } 130 - hw = dpu_hw_lm_init(lm->id, mmio, cat); 120 + hw = dpu_hw_lm_init(lm, mmio); 131 121 if (IS_ERR(hw)) { 132 122 rc = PTR_ERR(hw); 133 123 DPU_ERROR("failed lm object creation: err %d\n", rc); ··· 131 139 struct dpu_hw_merge_3d *hw; 132 140 const struct dpu_merge_3d_cfg *merge_3d = &cat->merge_3d[i]; 133 141 134 - if (merge_3d->id < MERGE_3D_0 || merge_3d->id >= MERGE_3D_MAX) { 135 - DPU_ERROR("skip merge_3d %d with invalid id\n", merge_3d->id); 136 - continue; 137 - } 138 - hw = dpu_hw_merge_3d_init(merge_3d->id, mmio, cat); 142 + hw = dpu_hw_merge_3d_init(merge_3d, mmio); 139 143 if (IS_ERR(hw)) { 140 144 rc = PTR_ERR(hw); 141 145 DPU_ERROR("failed merge_3d object creation: err %d\n", ··· 145 157 struct dpu_hw_pingpong *hw; 146 158 const struct dpu_pingpong_cfg *pp = &cat->pingpong[i]; 147 159 148 - if (pp->id < PINGPONG_0 || pp->id >= PINGPONG_MAX) { 149 - DPU_ERROR("skip pingpong %d with invalid id\n", pp->id); 150 - continue; 151 - } 152 - hw = dpu_hw_pingpong_init(pp->id, mmio, cat); 160 + hw = dpu_hw_pingpong_init(pp, mmio); 153 161 if (IS_ERR(hw)) { 154 162 rc = PTR_ERR(hw); 155 163 DPU_ERROR("failed pingpong object creation: err %d\n", ··· 161 177 struct dpu_hw_intf *hw; 162 178 const struct dpu_intf_cfg *intf = &cat->intf[i]; 163 179 164 - if (intf->type == INTF_NONE) { 165 - DPU_DEBUG("skip intf %d with type none\n", i); 166 - continue; 167 - } 168 - if (intf->id < INTF_0 || intf->id >= INTF_MAX) { 169 - DPU_ERROR("skip intf %d with invalid id\n", intf->id); 170 - continue; 171 - } 172 - hw = dpu_hw_intf_init(intf->id, mmio, cat); 180 + hw = dpu_hw_intf_init(intf, mmio); 173 181 if (IS_ERR(hw)) { 174 182 rc = PTR_ERR(hw); 175 183 DPU_ERROR("failed intf object creation: err %d\n", rc); ··· 174 198 struct dpu_hw_wb *hw; 175 199 const struct dpu_wb_cfg *wb = &cat->wb[i]; 176 200 177 - if (wb->id < WB_0 || wb->id >= WB_MAX) { 178 - DPU_ERROR("skip intf %d with invalid id\n", wb->id); 179 - continue; 180 - } 181 - 182 - hw = dpu_hw_wb_init(wb->id, mmio, cat); 201 + hw = dpu_hw_wb_init(wb, mmio); 183 202 if (IS_ERR(hw)) { 184 203 rc = PTR_ERR(hw); 185 204 DPU_ERROR("failed wb object creation: err %d\n", rc); ··· 187 216 struct dpu_hw_ctl *hw; 188 217 const struct dpu_ctl_cfg *ctl = &cat->ctl[i]; 189 218 190 - if (ctl->id < CTL_0 || ctl->id >= CTL_MAX) { 191 - DPU_ERROR("skip ctl %d with invalid id\n", ctl->id); 192 - continue; 193 - } 194 - hw = dpu_hw_ctl_init(ctl->id, mmio, cat); 219 + hw = dpu_hw_ctl_init(ctl, mmio, cat->mixer_count, cat->mixer); 195 220 if (IS_ERR(hw)) { 196 221 rc = PTR_ERR(hw); 197 222 DPU_ERROR("failed ctl object creation: err %d\n", rc); ··· 200 233 struct dpu_hw_dspp *hw; 201 234 const struct dpu_dspp_cfg *dspp = &cat->dspp[i]; 202 235 203 - if (dspp->id < DSPP_0 || dspp->id >= DSPP_MAX) { 204 - DPU_ERROR("skip dspp %d with invalid id\n", dspp->id); 205 - continue; 206 - } 207 - hw = dpu_hw_dspp_init(dspp->id, mmio, cat); 236 + hw = dpu_hw_dspp_init(dspp, mmio); 208 237 if (IS_ERR(hw)) { 209 238 rc = PTR_ERR(hw); 210 239 DPU_ERROR("failed dspp object creation: err %d\n", rc); ··· 213 250 struct dpu_hw_dsc *hw; 214 251 const struct dpu_dsc_cfg *dsc = &cat->dsc[i]; 215 252 216 - hw = dpu_hw_dsc_init(dsc->id, mmio, cat); 217 - if (IS_ERR_OR_NULL(hw)) { 253 + if (test_bit(DPU_DSC_HW_REV_1_2, &dsc->features)) 254 + hw = dpu_hw_dsc_init_1_2(dsc, mmio); 255 + else 256 + hw = dpu_hw_dsc_init(dsc, mmio); 257 + 258 + if (IS_ERR(hw)) { 218 259 rc = PTR_ERR(hw); 219 260 DPU_ERROR("failed dsc object creation: err %d\n", rc); 220 261 goto fail; ··· 230 263 struct dpu_hw_sspp *hw; 231 264 const struct dpu_sspp_cfg *sspp = &cat->sspp[i]; 232 265 233 - if (sspp->id < SSPP_NONE || sspp->id >= SSPP_MAX) { 234 - DPU_ERROR("skip intf %d with invalid id\n", sspp->id); 235 - continue; 236 - } 237 - 238 - hw = dpu_hw_sspp_init(sspp->id, mmio, cat); 266 + hw = dpu_hw_sspp_init(sspp, mmio, cat->ubwc); 239 267 if (IS_ERR(hw)) { 240 268 rc = PTR_ERR(hw); 241 269 DPU_ERROR("failed sspp object creation: err %d\n", rc);
+14
drivers/gpu/drm/msm/disp/dpu1/dpu_trace.h
··· 871 871 TP_printk("pp:%d cfg:%u", __entry->pp, __entry->cfg) 872 872 ); 873 873 874 + TRACE_EVENT(dpu_intf_connect_ext_te, 875 + TP_PROTO(enum dpu_intf intf, u32 cfg), 876 + TP_ARGS(intf, cfg), 877 + TP_STRUCT__entry( 878 + __field( enum dpu_intf, intf ) 879 + __field( u32, cfg ) 880 + ), 881 + TP_fast_assign( 882 + __entry->intf = intf; 883 + __entry->cfg = cfg; 884 + ), 885 + TP_printk("intf:%d cfg:%u", __entry->intf, __entry->cfg) 886 + ); 887 + 874 888 TRACE_EVENT(dpu_core_irq_register_callback, 875 889 TP_PROTO(int irq_idx, void *callback), 876 890 TP_ARGS(irq_idx, callback),
+82
drivers/gpu/drm/msm/disp/mdp5/mdp5_cfg.c
··· 103 103 .max_clk = 200000000, 104 104 }; 105 105 106 + static const struct mdp5_cfg_hw msm8x26_config = { 107 + .name = "msm8x26", 108 + .mdp = { 109 + .count = 1, 110 + .caps = MDP_CAP_SMP | 111 + 0, 112 + }, 113 + .smp = { 114 + .mmb_count = 7, 115 + .mmb_size = 4096, 116 + .clients = { 117 + [SSPP_VIG0] = 1, 118 + [SSPP_DMA0] = 4, 119 + [SSPP_RGB0] = 7, 120 + }, 121 + }, 122 + .ctl = { 123 + .count = 2, 124 + .base = { 0x00500, 0x00600 }, 125 + .flush_hw_mask = 0x0003ffff, 126 + }, 127 + .pipe_vig = { 128 + .count = 1, 129 + .base = { 0x01100 }, 130 + .caps = MDP_PIPE_CAP_HFLIP | 131 + MDP_PIPE_CAP_VFLIP | 132 + MDP_PIPE_CAP_SCALE | 133 + MDP_PIPE_CAP_CSC | 134 + 0, 135 + }, 136 + .pipe_rgb = { 137 + .count = 1, 138 + .base = { 0x01d00 }, 139 + .caps = MDP_PIPE_CAP_HFLIP | 140 + MDP_PIPE_CAP_VFLIP | 141 + MDP_PIPE_CAP_SCALE | 142 + 0, 143 + }, 144 + .pipe_dma = { 145 + .count = 1, 146 + .base = { 0x02900 }, 147 + .caps = MDP_PIPE_CAP_HFLIP | 148 + MDP_PIPE_CAP_VFLIP | 149 + 0, 150 + }, 151 + .lm = { 152 + .count = 2, 153 + .base = { 0x03100, 0x03d00 }, 154 + .instances = { 155 + { .id = 0, .pp = 0, .dspp = 0, 156 + .caps = MDP_LM_CAP_DISPLAY, }, 157 + { .id = 1, .pp = -1, .dspp = -1, 158 + .caps = MDP_LM_CAP_WB }, 159 + }, 160 + .nb_stages = 2, 161 + .max_width = 2048, 162 + .max_height = 0xFFFF, 163 + }, 164 + .dspp = { 165 + .count = 1, 166 + .base = { 0x04500 }, 167 + }, 168 + .pp = { 169 + .count = 1, 170 + .base = { 0x21a00 }, 171 + }, 172 + .intf = { 173 + .base = { 0x00000, 0x21200 }, 174 + .connect = { 175 + [0] = INTF_DISABLED, 176 + [1] = INTF_DSI, 177 + }, 178 + }, 179 + .perf = { 180 + .ab_inefficiency = 100, 181 + .ib_inefficiency = 200, 182 + .clk_inefficiency = 125 183 + }, 184 + .max_clk = 200000000, 185 + }; 186 + 106 187 static const struct mdp5_cfg_hw msm8x74v2_config = { 107 188 .name = "msm8x74", 108 189 .mdp = { ··· 1317 1236 1318 1237 static const struct mdp5_cfg_handler cfg_handlers_v1[] = { 1319 1238 { .revision = 0, .config = { .hw = &msm8x74v1_config } }, 1239 + { .revision = 1, .config = { .hw = &msm8x26_config } }, 1320 1240 { .revision = 2, .config = { .hw = &msm8x74v2_config } }, 1321 1241 { .revision = 3, .config = { .hw = &apq8084_config } }, 1322 1242 { .revision = 6, .config = { .hw = &msm8x16_config } },
+1 -1
drivers/gpu/drm/msm/disp/mdp5/mdp5_kms.c
··· 229 229 #ifdef CONFIG_DEBUG_FS 230 230 static int smp_show(struct seq_file *m, void *arg) 231 231 { 232 - struct drm_info_node *node = (struct drm_info_node *) m->private; 232 + struct drm_info_node *node = m->private; 233 233 struct drm_device *dev = node->minor->dev; 234 234 struct msm_drm_private *priv = dev->dev_private; 235 235 struct mdp5_kms *mdp5_kms = to_mdp5_kms(to_mdp_kms(priv->kms));
-1
drivers/gpu/drm/msm/dp/dp_ctrl.h
··· 14 14 #include "dp_catalog.h" 15 15 16 16 struct dp_ctrl { 17 - bool orientation; 18 17 atomic_t aborted; 19 18 bool wide_bus_en; 20 19 };
+2 -4
drivers/gpu/drm/msm/dp/dp_debug.c
··· 21 21 struct dp_debug_private { 22 22 struct dentry *root; 23 23 24 - struct dp_usbpd *usbpd; 25 24 struct dp_link *link; 26 25 struct dp_panel *panel; 27 26 struct drm_connector *connector; ··· 231 232 } 232 233 233 234 struct dp_debug *dp_debug_get(struct device *dev, struct dp_panel *panel, 234 - struct dp_usbpd *usbpd, struct dp_link *link, 235 + struct dp_link *link, 235 236 struct drm_connector *connector, struct drm_minor *minor) 236 237 { 237 238 struct dp_debug_private *debug; 238 239 struct dp_debug *dp_debug; 239 240 int rc; 240 241 241 - if (!dev || !panel || !usbpd || !link) { 242 + if (!dev || !panel || !link) { 242 243 DRM_ERROR("invalid input\n"); 243 244 rc = -EINVAL; 244 245 goto error; ··· 251 252 } 252 253 253 254 debug->dp_debug.debug_en = false; 254 - debug->usbpd = usbpd; 255 255 debug->link = link; 256 256 debug->panel = panel; 257 257 debug->dev = dev;
+2 -3
drivers/gpu/drm/msm/dp/dp_debug.h
··· 32 32 * 33 33 * @dev: device instance of the caller 34 34 * @panel: instance of panel module 35 - * @usbpd: instance of usbpd module 36 35 * @link: instance of link module 37 36 * @connector: double pointer to display connector 38 37 * @minor: pointer to drm minor number after device registration ··· 41 42 * for debugfs input to be communicated with existing modules 42 43 */ 43 44 struct dp_debug *dp_debug_get(struct device *dev, struct dp_panel *panel, 44 - struct dp_usbpd *usbpd, struct dp_link *link, 45 + struct dp_link *link, 45 46 struct drm_connector *connector, 46 47 struct drm_minor *minor); 47 48 ··· 58 59 59 60 static inline 60 61 struct dp_debug *dp_debug_get(struct device *dev, struct dp_panel *panel, 61 - struct dp_usbpd *usbpd, struct dp_link *link, 62 + struct dp_link *link, 62 63 struct drm_connector *connector, struct drm_minor *minor) 63 64 { 64 65 return ERR_PTR(-EINVAL);
+6 -44
drivers/gpu/drm/msm/dp/dp_display.c
··· 14 14 15 15 #include "msm_drv.h" 16 16 #include "msm_kms.h" 17 - #include "dp_hpd.h" 18 17 #include "dp_parser.h" 19 18 #include "dp_power.h" 20 19 #include "dp_catalog.h" ··· 91 92 struct platform_device *pdev; 92 93 struct dentry *root; 93 94 94 - struct dp_usbpd *usbpd; 95 95 struct dp_parser *parser; 96 96 struct dp_power *power; 97 97 struct dp_catalog *catalog; ··· 100 102 struct dp_ctrl *ctrl; 101 103 struct dp_debug *debug; 102 104 103 - struct dp_usbpd_cb usbpd_cb; 104 105 struct dp_display_mode dp_mode; 105 106 struct msm_dp dp_display; 106 107 ··· 326 329 327 330 kthread_stop(dp->ev_tsk); 328 331 332 + of_dp_aux_depopulate_bus(dp->aux); 333 + 329 334 dp_power_client_deinit(dp->power); 330 335 dp_unregister_audio_driver(dev, dp->audio); 331 336 dp_aux_unregister(dp->aux); ··· 466 467 dp->dp_display.connector_type, dp->core_initialized, 467 468 dp->phy_initialized); 468 469 469 - dp_power_init(dp->power, false); 470 + dp_power_init(dp->power); 470 471 dp_ctrl_reset_irq_ctrl(dp->ctrl, true); 471 472 dp_aux_init(dp->aux); 472 473 dp->core_initialized = true; ··· 491 492 dp_display_host_phy_init(dp); 492 493 493 494 return dp_display_process_hpd_high(dp); 494 - } 495 - 496 - static int dp_display_usbpd_disconnect_cb(struct device *dev) 497 - { 498 - return 0; 499 495 } 500 496 501 497 static int dp_display_notify_disconnect(struct device *dev) ··· 577 583 578 584 static int dp_hpd_plug_handle(struct dp_display_private *dp, u32 data) 579 585 { 580 - struct dp_usbpd *hpd = dp->usbpd; 581 586 u32 state; 582 587 int ret; 583 - 584 - if (!hpd) 585 - return 0; 586 588 587 589 mutex_lock(&dp->event_mutex); 588 590 ··· 634 644 635 645 static int dp_hpd_unplug_handle(struct dp_display_private *dp, u32 data) 636 646 { 637 - struct dp_usbpd *hpd = dp->usbpd; 638 647 u32 state; 639 - 640 - if (!hpd) 641 - return 0; 642 648 643 649 mutex_lock(&dp->event_mutex); 644 650 ··· 734 748 { 735 749 int rc = 0; 736 750 struct device *dev = &dp->pdev->dev; 737 - struct dp_usbpd_cb *cb = &dp->usbpd_cb; 738 751 struct dp_panel_in panel_in = { 739 752 .dev = dev, 740 753 }; 741 - 742 - /* Callback APIs used for cable status change event */ 743 - cb->configure = dp_display_usbpd_configure_cb; 744 - cb->disconnect = dp_display_usbpd_disconnect_cb; 745 - cb->attention = dp_display_usbpd_attention_cb; 746 - 747 - dp->usbpd = dp_hpd_get(dev, cb); 748 - if (IS_ERR(dp->usbpd)) { 749 - rc = PTR_ERR(dp->usbpd); 750 - DRM_ERROR("failed to initialize hpd, rc = %d\n", rc); 751 - dp->usbpd = NULL; 752 - goto error; 753 - } 754 754 755 755 dp->parser = dp_parser_get(dp->pdev); 756 756 if (IS_ERR(dp->parser)) { ··· 1300 1328 { 1301 1329 struct dp_display_private *dp = dev_get_dp_display_private(&pdev->dev); 1302 1330 1331 + component_del(&pdev->dev, &dp_display_comp_ops); 1303 1332 dp_display_deinit_sub_modules(dp); 1304 1333 1305 - component_del(&pdev->dev, &dp_display_comp_ops); 1306 1334 platform_set_drvdata(pdev, NULL); 1307 1335 1308 1336 return 0; ··· 1471 1499 dp = container_of(dp_display, struct dp_display_private, dp_display); 1472 1500 dev = &dp->pdev->dev; 1473 1501 1474 - dp->debug = dp_debug_get(dev, dp->panel, dp->usbpd, 1502 + dp->debug = dp_debug_get(dev, dp->panel, 1475 1503 dp->link, dp->dp_display.connector, 1476 1504 minor); 1477 1505 if (IS_ERR(dp->debug)) { ··· 1479 1507 DRM_ERROR("failed to initialize debug, rc = %d\n", rc); 1480 1508 dp->debug = NULL; 1481 1509 } 1482 - } 1483 - 1484 - static void of_dp_aux_depopulate_bus_void(void *data) 1485 - { 1486 - of_dp_aux_depopulate_bus(data); 1487 1510 } 1488 1511 1489 1512 static int dp_display_get_next_bridge(struct msm_dp *dp) ··· 1508 1541 of_node_put(aux_bus); 1509 1542 if (rc) 1510 1543 goto error; 1511 - 1512 - rc = devm_add_action_or_reset(dp->drm_dev->dev, 1513 - of_dp_aux_depopulate_bus_void, 1514 - dp_priv->aux); 1515 - if (rc) 1516 - goto error; 1517 1544 } else if (dp->is_edp) { 1518 1545 DRM_ERROR("eDP aux_bus not found\n"); 1519 1546 return -ENODEV; ··· 1531 1570 1532 1571 error: 1533 1572 if (dp->is_edp) { 1573 + of_dp_aux_depopulate_bus(dp_priv->aux); 1534 1574 dp_display_host_phy_exit(dp_priv); 1535 1575 dp_display_host_deinit(dp_priv); 1536 1576 }
-67
drivers/gpu/drm/msm/dp/dp_hpd.c
··· 1 - // SPDX-License-Identifier: GPL-2.0-only 2 - /* 3 - * Copyright (c) 2012-2020, The Linux Foundation. All rights reserved. 4 - */ 5 - 6 - #define pr_fmt(fmt) "[drm-dp] %s: " fmt, __func__ 7 - 8 - #include <linux/slab.h> 9 - #include <linux/device.h> 10 - 11 - #include "dp_hpd.h" 12 - 13 - /* DP specific VDM commands */ 14 - #define DP_USBPD_VDM_STATUS 0x10 15 - #define DP_USBPD_VDM_CONFIGURE 0x11 16 - 17 - /* USBPD-TypeC specific Macros */ 18 - #define VDM_VERSION 0x0 19 - #define USB_C_DP_SID 0xFF01 20 - 21 - struct dp_hpd_private { 22 - struct device *dev; 23 - struct dp_usbpd_cb *dp_cb; 24 - struct dp_usbpd dp_usbpd; 25 - }; 26 - 27 - int dp_hpd_connect(struct dp_usbpd *dp_usbpd, bool hpd) 28 - { 29 - int rc = 0; 30 - struct dp_hpd_private *hpd_priv; 31 - 32 - hpd_priv = container_of(dp_usbpd, struct dp_hpd_private, 33 - dp_usbpd); 34 - 35 - if (!hpd_priv->dp_cb || !hpd_priv->dp_cb->configure 36 - || !hpd_priv->dp_cb->disconnect) { 37 - pr_err("hpd dp_cb not initialized\n"); 38 - return -EINVAL; 39 - } 40 - if (hpd) 41 - hpd_priv->dp_cb->configure(hpd_priv->dev); 42 - else 43 - hpd_priv->dp_cb->disconnect(hpd_priv->dev); 44 - 45 - return rc; 46 - } 47 - 48 - struct dp_usbpd *dp_hpd_get(struct device *dev, struct dp_usbpd_cb *cb) 49 - { 50 - struct dp_hpd_private *dp_hpd; 51 - 52 - if (!cb) { 53 - pr_err("invalid cb data\n"); 54 - return ERR_PTR(-EINVAL); 55 - } 56 - 57 - dp_hpd = devm_kzalloc(dev, sizeof(*dp_hpd), GFP_KERNEL); 58 - if (!dp_hpd) 59 - return ERR_PTR(-ENOMEM); 60 - 61 - dp_hpd->dev = dev; 62 - dp_hpd->dp_cb = cb; 63 - 64 - dp_hpd->dp_usbpd.connect = dp_hpd_connect; 65 - 66 - return &dp_hpd->dp_usbpd; 67 - }
-78
drivers/gpu/drm/msm/dp/dp_hpd.h
··· 1 - /* SPDX-License-Identifier: GPL-2.0-only */ 2 - /* 3 - * Copyright (c) 2012-2020, The Linux Foundation. All rights reserved. 4 - */ 5 - 6 - #ifndef _DP_HPD_H_ 7 - #define _DP_HPD_H_ 8 - 9 - //#include <linux/usb/usbpd.h> 10 - 11 - #include <linux/types.h> 12 - #include <linux/device.h> 13 - 14 - enum plug_orientation { 15 - ORIENTATION_NONE, 16 - ORIENTATION_CC1, 17 - ORIENTATION_CC2, 18 - }; 19 - 20 - /** 21 - * struct dp_usbpd - DisplayPort status 22 - * 23 - * @orientation: plug orientation configuration 24 - * @low_pow_st: low power state 25 - * @adaptor_dp_en: adaptor functionality enabled 26 - * @multi_func: multi-function preferred 27 - * @usb_config_req: request to switch to usb 28 - * @exit_dp_mode: request exit from displayport mode 29 - * @hpd_irq: Change in the status since last message 30 - * @alt_mode_cfg_done: bool to specify alt mode status 31 - * @debug_en: bool to specify debug mode 32 - * @connect: simulate disconnect or connect for debug mode 33 - */ 34 - struct dp_usbpd { 35 - enum plug_orientation orientation; 36 - bool low_pow_st; 37 - bool adaptor_dp_en; 38 - bool multi_func; 39 - bool usb_config_req; 40 - bool exit_dp_mode; 41 - bool hpd_irq; 42 - bool alt_mode_cfg_done; 43 - bool debug_en; 44 - 45 - int (*connect)(struct dp_usbpd *dp_usbpd, bool hpd); 46 - }; 47 - 48 - /** 49 - * struct dp_usbpd_cb - callback functions provided by the client 50 - * 51 - * @configure: called by usbpd module when PD communication has 52 - * been completed and the usb peripheral has been configured on 53 - * dp mode. 54 - * @disconnect: notify the cable disconnect issued by usb. 55 - * @attention: notify any attention message issued by usb. 56 - */ 57 - struct dp_usbpd_cb { 58 - int (*configure)(struct device *dev); 59 - int (*disconnect)(struct device *dev); 60 - int (*attention)(struct device *dev); 61 - }; 62 - 63 - /** 64 - * dp_hpd_get() - setup hpd module 65 - * 66 - * @dev: device instance of the caller 67 - * @cb: struct containing callback function pointers. 68 - * 69 - * This function allows the client to initialize the usbpd 70 - * module. The module will communicate with HPD module. 71 - */ 72 - struct dp_usbpd *dp_hpd_get(struct device *dev, struct dp_usbpd_cb *cb); 73 - 74 - int dp_hpd_register(struct dp_usbpd *dp_usbpd); 75 - void dp_hpd_unregister(struct dp_usbpd *dp_usbpd); 76 - int dp_hpd_connect(struct dp_usbpd *dp_usbpd, bool hpd); 77 - 78 - #endif /* _DP_HPD_H_ */
-1
drivers/gpu/drm/msm/dp/dp_panel.h
··· 10 10 11 11 #include "dp_aux.h" 12 12 #include "dp_link.h" 13 - #include "dp_hpd.h" 14 13 15 14 struct edid; 16 15
+16 -62
drivers/gpu/drm/msm/dp/dp_power.c
··· 14 14 15 15 struct dp_power_private { 16 16 struct dp_parser *parser; 17 - struct platform_device *pdev; 18 17 struct device *dev; 19 18 struct drm_device *drm_dev; 20 19 struct clk *link_clk_src; ··· 27 28 { 28 29 int rc = 0; 29 30 struct dss_module_power *core, *ctrl, *stream; 30 - struct device *dev = &power->pdev->dev; 31 + struct device *dev = power->dev; 31 32 32 33 core = &power->parser->mp[DP_CORE_PM]; 33 34 ctrl = &power->parser->mp[DP_CTRL_PM]; 34 35 stream = &power->parser->mp[DP_STREAM_PM]; 35 36 36 37 rc = devm_clk_bulk_get(dev, core->num_clk, core->clocks); 37 - if (rc) { 38 - DRM_ERROR("failed to get %s clk. err=%d\n", 39 - dp_parser_pm_name(DP_CORE_PM), rc); 38 + if (rc) 40 39 return rc; 41 - } 42 40 43 41 rc = devm_clk_bulk_get(dev, ctrl->num_clk, ctrl->clocks); 44 - if (rc) { 45 - DRM_ERROR("failed to get %s clk. err=%d\n", 46 - dp_parser_pm_name(DP_CTRL_PM), rc); 42 + if (rc) 47 43 return -ENODEV; 48 - } 49 44 50 45 rc = devm_clk_bulk_get(dev, stream->num_clk, stream->clocks); 51 - if (rc) { 52 - DRM_ERROR("failed to get %s clk. err=%d\n", 53 - dp_parser_pm_name(DP_CTRL_PM), rc); 46 + if (rc) 54 47 return -ENODEV; 55 - } 56 48 57 49 return 0; 58 50 } ··· 111 121 mp = &power->parser->mp[DP_CORE_PM]; 112 122 113 123 rc = clk_bulk_prepare_enable(mp->num_clk, mp->clocks); 114 - if (rc) { 115 - DRM_ERROR("fail to enable clks: %s. err=%d\n", 116 - dp_parser_pm_name(DP_CORE_PM), rc); 124 + if (rc) 117 125 return rc; 118 - } 126 + 119 127 dp_power->core_clks_on = true; 120 128 } 121 129 } ··· 121 133 mp = &power->parser->mp[pm_type]; 122 134 if (enable) { 123 135 rc = clk_bulk_prepare_enable(mp->num_clk, mp->clocks); 124 - if (rc) { 125 - DRM_ERROR("failed to enable clks, err: %d\n", rc); 136 + if (rc) 126 137 return rc; 127 - } 128 138 } else { 129 139 clk_bulk_disable_unprepare(mp->num_clk, mp->clocks); 130 140 } ··· 148 162 149 163 int dp_power_client_init(struct dp_power *dp_power) 150 164 { 151 - int rc = 0; 152 165 struct dp_power_private *power; 153 - 154 - if (!dp_power) { 155 - DRM_ERROR("invalid power data\n"); 156 - return -EINVAL; 157 - } 158 166 159 167 power = container_of(dp_power, struct dp_power_private, dp_power); 160 168 161 - pm_runtime_enable(&power->pdev->dev); 169 + pm_runtime_enable(power->dev); 162 170 163 - rc = dp_power_clk_init(power); 164 - if (rc) 165 - DRM_ERROR("failed to init clocks %d\n", rc); 166 - 167 - return rc; 171 + return dp_power_clk_init(power); 168 172 } 169 173 170 174 void dp_power_client_deinit(struct dp_power *dp_power) 171 175 { 172 176 struct dp_power_private *power; 173 177 174 - if (!dp_power) { 175 - DRM_ERROR("invalid power data\n"); 176 - return; 177 - } 178 - 179 178 power = container_of(dp_power, struct dp_power_private, dp_power); 180 179 181 - pm_runtime_disable(&power->pdev->dev); 180 + pm_runtime_disable(power->dev); 182 181 } 183 182 184 - int dp_power_init(struct dp_power *dp_power, bool flip) 183 + int dp_power_init(struct dp_power *dp_power) 185 184 { 186 185 int rc = 0; 187 186 struct dp_power_private *power = NULL; 188 187 189 - if (!dp_power) { 190 - DRM_ERROR("invalid power data\n"); 191 - return -EINVAL; 192 - } 193 - 194 188 power = container_of(dp_power, struct dp_power_private, dp_power); 195 189 196 - pm_runtime_get_sync(&power->pdev->dev); 190 + pm_runtime_get_sync(power->dev); 197 191 198 192 rc = dp_power_clk_enable(dp_power, DP_CORE_PM, true); 199 - if (rc) { 200 - DRM_ERROR("failed to enable DP core clocks, %d\n", rc); 201 - goto exit; 202 - } 193 + if (rc) 194 + pm_runtime_put_sync(power->dev); 203 195 204 - return 0; 205 - 206 - exit: 207 - pm_runtime_put_sync(&power->pdev->dev); 208 196 return rc; 209 197 } 210 198 ··· 189 229 power = container_of(dp_power, struct dp_power_private, dp_power); 190 230 191 231 dp_power_clk_enable(dp_power, DP_CORE_PM, false); 192 - pm_runtime_put_sync(&power->pdev->dev); 232 + pm_runtime_put_sync(power->dev); 193 233 return 0; 194 234 } 195 235 ··· 198 238 struct dp_power_private *power; 199 239 struct dp_power *dp_power; 200 240 201 - if (!parser) { 202 - DRM_ERROR("invalid input\n"); 203 - return ERR_PTR(-EINVAL); 204 - } 205 - 206 - power = devm_kzalloc(&parser->pdev->dev, sizeof(*power), GFP_KERNEL); 241 + power = devm_kzalloc(dev, sizeof(*power), GFP_KERNEL); 207 242 if (!power) 208 243 return ERR_PTR(-ENOMEM); 209 244 210 245 power->parser = parser; 211 - power->pdev = parser->pdev; 212 246 power->dev = dev; 213 247 214 248 dp_power = &power->dp_power;
+1 -2
drivers/gpu/drm/msm/dp/dp_power.h
··· 26 26 * dp_power_init() - enable power supplies for display controller 27 27 * 28 28 * @power: instance of power module 29 - * @flip: bool for flipping gpio direction 30 29 * return: 0 if success or error if failure. 31 30 * 32 31 * This API will turn on the regulators and configures gpio's 33 32 * aux/hpd. 34 33 */ 35 - int dp_power_init(struct dp_power *power, bool flip); 34 + int dp_power_init(struct dp_power *power); 36 35 37 36 /** 38 37 * dp_power_deinit() - turn off regulators and gpios.
+2
drivers/gpu/drm/msm/dsi/dsi_cfg.c
··· 245 245 &apq8064_dsi_cfg, &msm_dsi_v2_host_ops}, 246 246 {MSM_DSI_VER_MAJOR_6G, MSM_DSI_6G_VER_MINOR_V1_0, 247 247 &msm8974_apq8084_dsi_cfg, &msm_dsi_6g_host_ops}, 248 + {MSM_DSI_VER_MAJOR_6G, MSM_DSI_6G_VER_MINOR_V1_0_2, 249 + &msm8974_apq8084_dsi_cfg, &msm_dsi_6g_host_ops}, 248 250 {MSM_DSI_VER_MAJOR_6G, MSM_DSI_6G_VER_MINOR_V1_1, 249 251 &msm8974_apq8084_dsi_cfg, &msm_dsi_6g_host_ops}, 250 252 {MSM_DSI_VER_MAJOR_6G, MSM_DSI_6G_VER_MINOR_V1_1_1,
+1
drivers/gpu/drm/msm/dsi/dsi_cfg.h
··· 11 11 #define MSM_DSI_VER_MAJOR_V2 0x02 12 12 #define MSM_DSI_VER_MAJOR_6G 0x03 13 13 #define MSM_DSI_6G_VER_MINOR_V1_0 0x10000000 14 + #define MSM_DSI_6G_VER_MINOR_V1_0_2 0x10000002 14 15 #define MSM_DSI_6G_VER_MINOR_V1_1 0x10010000 15 16 #define MSM_DSI_6G_VER_MINOR_V1_1_1 0x10010001 16 17 #define MSM_DSI_6G_VER_MINOR_V1_2 0x10020000
+59 -118
drivers/gpu/drm/msm/dsi/dsi_host.c
··· 28 28 #include "dsi.xml.h" 29 29 #include "sfpb.xml.h" 30 30 #include "dsi_cfg.h" 31 + #include "msm_dsc_helper.h" 31 32 #include "msm_kms.h" 32 33 #include "msm_gem.h" 33 34 #include "phy/dsi_phy.h" ··· 118 117 struct clk *byte_clk; 119 118 struct clk *esc_clk; 120 119 struct clk *pixel_clk; 121 - struct clk *byte_clk_src; 122 - struct clk *pixel_clk_src; 123 120 struct clk *byte_intf_clk; 124 121 125 122 unsigned long byte_clk_rate; ··· 127 128 128 129 /* DSI v2 specific clocks */ 129 130 struct clk *src_clk; 130 - struct clk *esc_clk_src; 131 - struct clk *dsi_clk_src; 132 131 133 132 unsigned long src_clk_rate; 134 133 ··· 263 266 return ret; 264 267 } 265 268 266 - msm_host->esc_clk_src = clk_get_parent(msm_host->esc_clk); 267 - if (!msm_host->esc_clk_src) { 268 - ret = -ENODEV; 269 - pr_err("%s: can't get esc clock parent. ret=%d\n", 270 - __func__, ret); 271 - return ret; 272 - } 273 - 274 - msm_host->dsi_clk_src = clk_get_parent(msm_host->src_clk); 275 - if (!msm_host->dsi_clk_src) { 276 - ret = -ENODEV; 277 - pr_err("%s: can't get src clock parent. ret=%d\n", 278 - __func__, ret); 279 - } 280 - 281 269 return ret; 282 270 } 283 271 ··· 324 342 pr_err("%s: can't find dsi_esc clock. ret=%d\n", 325 343 __func__, ret); 326 344 msm_host->esc_clk = NULL; 327 - goto exit; 328 - } 329 - 330 - msm_host->byte_clk_src = clk_get_parent(msm_host->byte_clk); 331 - if (IS_ERR(msm_host->byte_clk_src)) { 332 - ret = PTR_ERR(msm_host->byte_clk_src); 333 - pr_err("%s: can't find byte_clk clock. ret=%d\n", __func__, ret); 334 - goto exit; 335 - } 336 - 337 - msm_host->pixel_clk_src = clk_get_parent(msm_host->pixel_clk); 338 - if (IS_ERR(msm_host->pixel_clk_src)) { 339 - ret = PTR_ERR(msm_host->pixel_clk_src); 340 - pr_err("%s: can't find pixel_clk clock. ret=%d\n", __func__, ret); 341 345 goto exit; 342 346 } 343 347 ··· 528 560 clk_disable_unprepare(msm_host->byte_clk); 529 561 } 530 562 531 - static unsigned long dsi_get_pclk_rate(const struct drm_display_mode *mode, bool is_bonded_dsi) 563 + static unsigned long dsi_adjust_pclk_for_compression(const struct drm_display_mode *mode, 564 + const struct drm_dsc_config *dsc) 565 + { 566 + int new_hdisplay = DIV_ROUND_UP(mode->hdisplay * drm_dsc_get_bpp_int(dsc), 567 + dsc->bits_per_component * 3); 568 + 569 + int new_htotal = mode->htotal - mode->hdisplay + new_hdisplay; 570 + 571 + return new_htotal * mode->vtotal * drm_mode_vrefresh(mode); 572 + } 573 + 574 + static unsigned long dsi_get_pclk_rate(const struct drm_display_mode *mode, 575 + const struct drm_dsc_config *dsc, bool is_bonded_dsi) 532 576 { 533 577 unsigned long pclk_rate; 534 578 535 579 pclk_rate = mode->clock * 1000; 580 + 581 + if (dsc) 582 + pclk_rate = dsi_adjust_pclk_for_compression(mode, dsc); 536 583 537 584 /* 538 585 * For bonded DSI mode, the current DRM mode has the complete width of the ··· 567 584 struct msm_dsi_host *msm_host = to_msm_dsi_host(host); 568 585 u8 lanes = msm_host->lanes; 569 586 u32 bpp = dsi_get_bpp(msm_host->format); 570 - unsigned long pclk_rate = dsi_get_pclk_rate(mode, is_bonded_dsi); 571 - u64 pclk_bpp = (u64)pclk_rate * bpp; 587 + unsigned long pclk_rate = dsi_get_pclk_rate(mode, msm_host->dsc, is_bonded_dsi); 588 + unsigned long pclk_bpp; 572 589 573 590 if (lanes == 0) { 574 591 pr_err("%s: forcing mdss_dsi lanes to 1\n", __func__); ··· 577 594 578 595 /* CPHY "byte_clk" is in units of 16 bits */ 579 596 if (msm_host->cphy_mode) 580 - do_div(pclk_bpp, (16 * lanes)); 597 + pclk_bpp = mult_frac(pclk_rate, bpp, 16 * lanes); 581 598 else 582 - do_div(pclk_bpp, (8 * lanes)); 599 + pclk_bpp = mult_frac(pclk_rate, bpp, 8 * lanes); 583 600 584 601 return pclk_bpp; 585 602 } 586 603 587 604 static void dsi_calc_pclk(struct msm_dsi_host *msm_host, bool is_bonded_dsi) 588 605 { 589 - msm_host->pixel_clk_rate = dsi_get_pclk_rate(msm_host->mode, is_bonded_dsi); 606 + msm_host->pixel_clk_rate = dsi_get_pclk_rate(msm_host->mode, msm_host->dsc, is_bonded_dsi); 590 607 msm_host->byte_clk_rate = dsi_byte_clk_get_rate(&msm_host->base, is_bonded_dsi, 591 608 msm_host->mode); 592 609 ··· 610 627 int dsi_calc_clk_rate_v2(struct msm_dsi_host *msm_host, bool is_bonded_dsi) 611 628 { 612 629 u32 bpp = dsi_get_bpp(msm_host->format); 613 - u64 pclk_bpp; 614 630 unsigned int esc_mhz, esc_div; 615 631 unsigned long byte_mhz; 616 632 617 633 dsi_calc_pclk(msm_host, is_bonded_dsi); 618 634 619 - pclk_bpp = (u64)dsi_get_pclk_rate(msm_host->mode, is_bonded_dsi) * bpp; 620 - do_div(pclk_bpp, 8); 621 - msm_host->src_clk_rate = pclk_bpp; 635 + msm_host->src_clk_rate = mult_frac(msm_host->pixel_clk_rate, bpp, 8); 622 636 623 637 /* 624 638 * esc clock is byte clock followed by a 4 bit divider, ··· 705 725 } 706 726 } 707 727 708 - static void dsi_ctrl_config(struct msm_dsi_host *msm_host, bool enable, 728 + static void dsi_ctrl_disable(struct msm_dsi_host *msm_host) 729 + { 730 + dsi_write(msm_host, REG_DSI_CTRL, 0); 731 + } 732 + 733 + static void dsi_ctrl_enable(struct msm_dsi_host *msm_host, 709 734 struct msm_dsi_phy_shared_timings *phy_shared_timings, struct msm_dsi_phy *phy) 710 735 { 711 736 u32 flags = msm_host->mode_flags; 712 737 enum mipi_dsi_pixel_format mipi_fmt = msm_host->format; 713 738 const struct msm_dsi_cfg_handler *cfg_hnd = msm_host->cfg_hnd; 714 739 u32 data = 0, lane_ctrl = 0; 715 - 716 - if (!enable) { 717 - dsi_write(msm_host, REG_DSI_CTRL, 0); 718 - return; 719 - } 720 740 721 741 if (flags & MIPI_DSI_MODE_VIDEO) { 722 742 if (flags & MIPI_DSI_MODE_VIDEO_HSE) ··· 802 822 if (!(flags & MIPI_DSI_CLOCK_NON_CONTINUOUS)) { 803 823 lane_ctrl = dsi_read(msm_host, REG_DSI_LANE_CTRL); 804 824 805 - if (msm_dsi_phy_set_continuous_clock(phy, enable)) 825 + if (msm_dsi_phy_set_continuous_clock(phy, true)) 806 826 lane_ctrl &= ~DSI_LANE_CTRL_HS_REQ_SEL_PHY; 807 827 808 828 dsi_write(msm_host, REG_DSI_LANE_CTRL, ··· 828 848 /* first calculate dsc parameters and then program 829 849 * compress mode registers 830 850 */ 831 - slice_per_intf = DIV_ROUND_UP(hdisplay, dsc->slice_width); 832 - 833 - /* 834 - * If slice_count is greater than slice_per_intf 835 - * then default to 1. This can happen during partial 836 - * update. 837 - */ 838 - if (dsc->slice_count > slice_per_intf) 839 - dsc->slice_count = 1; 851 + slice_per_intf = msm_dsc_get_slices_per_intf(dsc, hdisplay); 840 852 841 853 total_bytes_per_intf = dsc->slice_chunk_size * slice_per_intf; 842 854 843 855 eol_byte_num = total_bytes_per_intf % 3; 844 - pkt_per_line = slice_per_intf / dsc->slice_count; 856 + 857 + /* 858 + * Typically, pkt_per_line = slice_per_intf * slice_per_pkt. 859 + * 860 + * Since the current driver only supports slice_per_pkt = 1, 861 + * pkt_per_line will be equal to slice per intf for now. 862 + */ 863 + pkt_per_line = slice_per_intf; 845 864 846 865 if (is_cmd_mode) /* packet data type */ 847 866 reg = DSI_COMMAND_COMPRESSION_MODE_CTRL_STREAM0_DATATYPE(MIPI_DSI_DCS_LONG_WRITE); ··· 930 951 * pulse width same 931 952 */ 932 953 h_total -= hdisplay; 933 - hdisplay /= 3; 954 + hdisplay = DIV_ROUND_UP(msm_dsc_get_bytes_per_line(msm_host->dsc), 3); 934 955 h_total += hdisplay; 935 956 ha_end = ha_start + hdisplay; 936 957 } ··· 964 985 if (!msm_host->dsc) 965 986 wc = hdisplay * dsi_get_bpp(msm_host->format) / 8 + 1; 966 987 else 967 - wc = msm_host->dsc->slice_chunk_size * msm_host->dsc->slice_count + 1; 988 + /* 989 + * When DSC is enabled, WC = slice_chunk_size * slice_per_pkt + 1. 990 + * Currently, the driver only supports default value of slice_per_pkt = 1 991 + * 992 + * TODO: Expand mipi_dsi_device struct to hold slice_per_pkt info 993 + * and adjust DSC math to account for slice_per_pkt. 994 + */ 995 + wc = msm_host->dsc->slice_chunk_size + 1; 968 996 969 997 dsi_write(msm_host, REG_DSI_CMD_MDP_STREAM0_CTRL, 970 998 DSI_CMD_MDP_STREAM0_CTRL_WORD_COUNT(wc) | ··· 1717 1731 return -EINVAL; 1718 1732 } 1719 1733 1720 - static u32 dsi_dsc_rc_buf_thresh[DSC_NUM_BUF_RANGES - 1] = { 1721 - 0x0e, 0x1c, 0x2a, 0x38, 0x46, 0x54, 0x62, 1722 - 0x69, 0x70, 0x77, 0x79, 0x7b, 0x7d, 0x7e 1723 - }; 1724 - 1725 - /* only 8bpc, 8bpp added */ 1726 - static char min_qp[DSC_NUM_BUF_RANGES] = { 1727 - 0, 0, 1, 1, 3, 3, 3, 3, 3, 3, 5, 5, 5, 7, 13 1728 - }; 1729 - 1730 - static char max_qp[DSC_NUM_BUF_RANGES] = { 1731 - 4, 4, 5, 6, 7, 7, 7, 8, 9, 10, 11, 12, 13, 13, 15 1732 - }; 1733 - 1734 - static char bpg_offset[DSC_NUM_BUF_RANGES] = { 1735 - 2, 0, 0, -2, -4, -6, -8, -8, -8, -10, -10, -12, -12, -12, -12 1736 - }; 1737 - 1738 1734 static int dsi_populate_dsc_params(struct msm_dsi_host *msm_host, struct drm_dsc_config *dsc) 1739 1735 { 1740 - int i; 1741 - u16 bpp = dsc->bits_per_pixel >> 4; 1736 + int ret; 1742 1737 1743 1738 if (dsc->bits_per_pixel & 0xf) { 1744 1739 DRM_DEV_ERROR(&msm_host->pdev->dev, "DSI does not support fractional bits_per_pixel\n"); ··· 1731 1764 return -EOPNOTSUPP; 1732 1765 } 1733 1766 1734 - dsc->rc_model_size = 8192; 1735 - dsc->first_line_bpg_offset = 12; 1736 - dsc->rc_edge_factor = 6; 1737 - dsc->rc_tgt_offset_high = 3; 1738 - dsc->rc_tgt_offset_low = 3; 1739 1767 dsc->simple_422 = 0; 1740 1768 dsc->convert_rgb = 1; 1741 1769 dsc->vbr_enable = 0; 1742 1770 1743 - /* handle only bpp = bpc = 8 */ 1744 - for (i = 0; i < DSC_NUM_BUF_RANGES - 1 ; i++) 1745 - dsc->rc_buf_thresh[i] = dsi_dsc_rc_buf_thresh[i]; 1771 + drm_dsc_set_const_params(dsc); 1772 + drm_dsc_set_rc_buf_thresh(dsc); 1746 1773 1747 - for (i = 0; i < DSC_NUM_BUF_RANGES; i++) { 1748 - dsc->rc_range_params[i].range_min_qp = min_qp[i]; 1749 - dsc->rc_range_params[i].range_max_qp = max_qp[i]; 1750 - /* 1751 - * Range BPG Offset contains two's-complement signed values that fill 1752 - * 8 bits, yet the registers and DCS PPS field are only 6 bits wide. 1753 - */ 1754 - dsc->rc_range_params[i].range_bpg_offset = bpg_offset[i] & DSC_RANGE_BPG_OFFSET_MASK; 1774 + /* handle only bpp = bpc = 8, pre-SCR panels */ 1775 + ret = drm_dsc_setup_rc_params(dsc, DRM_DSC_1_1_PRE_SCR); 1776 + if (ret) { 1777 + DRM_DEV_ERROR(&msm_host->pdev->dev, "could not find DSC RC parameters\n"); 1778 + return ret; 1755 1779 } 1756 1780 1757 - dsc->initial_offset = 6144; /* Not bpp 12 */ 1758 - if (bpp != 8) 1759 - dsc->initial_offset = 2048; /* bpp = 12 */ 1760 - 1761 - if (dsc->bits_per_component <= 10) 1762 - dsc->mux_word_size = DSC_MUX_WORD_SIZE_8_10_BPC; 1763 - else 1764 - dsc->mux_word_size = DSC_MUX_WORD_SIZE_12_BPC; 1765 - 1766 - dsc->initial_xmit_delay = 512; 1767 - dsc->initial_scale_value = 32; 1768 - dsc->first_line_bpg_offset = 12; 1781 + dsc->initial_scale_value = drm_dsc_initial_scale_value(dsc); 1769 1782 dsc->line_buf_depth = dsc->bits_per_component + 1; 1770 - 1771 - /* bpc 8 */ 1772 - dsc->flatness_min_qp = 3; 1773 - dsc->flatness_max_qp = 12; 1774 - dsc->rc_quant_incr_limit0 = 11; 1775 - dsc->rc_quant_incr_limit1 = 11; 1776 1783 1777 1784 return drm_dsc_compute_rc_parameters(dsc); 1778 1785 } ··· 2358 2417 2359 2418 dsi_timing_setup(msm_host, is_bonded_dsi); 2360 2419 dsi_sw_reset(msm_host); 2361 - dsi_ctrl_config(msm_host, true, phy_shared_timings, phy); 2420 + dsi_ctrl_enable(msm_host, phy_shared_timings, phy); 2362 2421 2363 2422 if (msm_host->disp_en_gpio) 2364 2423 gpiod_set_value(msm_host->disp_en_gpio, 1); ··· 2390 2449 goto unlock_ret; 2391 2450 } 2392 2451 2393 - dsi_ctrl_config(msm_host, false, NULL, NULL); 2452 + dsi_ctrl_disable(msm_host); 2394 2453 2395 2454 if (msm_host->disp_en_gpio) 2396 2455 gpiod_set_value(msm_host->disp_en_gpio, 0);
+26 -42
drivers/gpu/drm/msm/dsi/dsi_manager.c
··· 34 34 #define IS_SYNC_NEEDED() (msm_dsim_glb.is_sync_needed) 35 35 #define IS_MASTER_DSI_LINK(id) (msm_dsim_glb.master_dsi_link_id == id) 36 36 37 - #ifdef CONFIG_OF 38 - static bool dsi_mgr_power_on_early(struct drm_bridge *bridge) 39 - { 40 - struct drm_bridge *next_bridge = drm_bridge_get_next_bridge(bridge); 41 - 42 - /* 43 - * If the next bridge in the chain is the Parade ps8640 bridge chip 44 - * then don't power on early since it seems to violate the expectations 45 - * of the firmware that the bridge chip is running. 46 - * 47 - * NOTE: this is expected to be a temporary special case. It's expected 48 - * that we'll eventually have a framework that allows the next level 49 - * bridge to indicate whether it needs us to power on before it or 50 - * after it. When that framework is in place then we'll use it and 51 - * remove this special case. 52 - */ 53 - return !(next_bridge && next_bridge->of_node && 54 - of_device_is_compatible(next_bridge->of_node, "parade,ps8640")); 55 - } 56 - #else 57 - static inline bool dsi_mgr_power_on_early(struct drm_bridge *bridge) 58 - { 59 - return true; 60 - } 61 - #endif 62 - 63 37 static inline struct msm_dsi *dsi_mgr_get_dsi(int id) 64 38 { 65 39 return msm_dsim_glb.dsi[id]; ··· 228 254 } 229 255 } 230 256 231 - static void dsi_mgr_bridge_power_on(struct drm_bridge *bridge) 257 + static int dsi_mgr_bridge_power_on(struct drm_bridge *bridge) 232 258 { 233 259 int id = dsi_mgr_bridge_get_id(bridge); 234 260 struct msm_dsi *msm_dsi = dsi_mgr_get_dsi(id); ··· 239 265 int ret; 240 266 241 267 DBG("id=%d", id); 242 - if (!msm_dsi_device_connected(msm_dsi)) 243 - return; 244 - 245 - /* Do nothing with the host if it is slave-DSI in case of bonded DSI */ 246 - if (is_bonded_dsi && !IS_MASTER_DSI_LINK(id)) 247 - return; 248 268 249 269 ret = dsi_mgr_phy_enable(id, phy_shared_timings); 250 270 if (ret) ··· 268 300 if (is_bonded_dsi && msm_dsi1) 269 301 msm_dsi_host_enable_irq(msm_dsi1->host); 270 302 271 - return; 303 + return 0; 272 304 273 305 host1_on_fail: 274 306 msm_dsi_host_power_off(host); 275 307 host_on_fail: 276 308 dsi_mgr_phy_disable(id); 277 309 phy_en_fail: 278 - return; 310 + return ret; 311 + } 312 + 313 + static void dsi_mgr_bridge_power_off(struct drm_bridge *bridge) 314 + { 315 + int id = dsi_mgr_bridge_get_id(bridge); 316 + struct msm_dsi *msm_dsi = dsi_mgr_get_dsi(id); 317 + struct msm_dsi *msm_dsi1 = dsi_mgr_get_dsi(DSI_1); 318 + struct mipi_dsi_host *host = msm_dsi->host; 319 + bool is_bonded_dsi = IS_BONDED_DSI(); 320 + 321 + msm_dsi_host_disable_irq(host); 322 + if (is_bonded_dsi && msm_dsi1) { 323 + msm_dsi_host_disable_irq(msm_dsi1->host); 324 + msm_dsi_host_power_off(msm_dsi1->host); 325 + } 326 + msm_dsi_host_power_off(host); 327 + dsi_mgr_phy_disable(id); 279 328 } 280 329 281 330 static void dsi_mgr_bridge_pre_enable(struct drm_bridge *bridge) ··· 312 327 if (is_bonded_dsi && !IS_MASTER_DSI_LINK(id)) 313 328 return; 314 329 315 - if (!dsi_mgr_power_on_early(bridge)) 316 - dsi_mgr_bridge_power_on(bridge); 330 + ret = dsi_mgr_bridge_power_on(bridge); 331 + if (ret) { 332 + dev_err(&msm_dsi->pdev->dev, "Power on failed: %d\n", ret); 333 + return; 334 + } 317 335 318 336 ret = msm_dsi_host_enable(host); 319 337 if (ret) { ··· 337 349 host1_en_fail: 338 350 msm_dsi_host_disable(host); 339 351 host_en_fail: 340 - 341 - return; 352 + dsi_mgr_bridge_power_off(bridge); 342 353 } 343 354 344 355 void msm_dsi_manager_tpg_enable(void) ··· 425 438 msm_dsi_host_set_display_mode(host, adjusted_mode); 426 439 if (is_bonded_dsi && other_dsi) 427 440 msm_dsi_host_set_display_mode(other_dsi->host, adjusted_mode); 428 - 429 - if (dsi_mgr_power_on_early(bridge)) 430 - dsi_mgr_bridge_power_on(bridge); 431 441 } 432 442 433 443 static enum drm_mode_status dsi_mgr_bridge_mode_valid(struct drm_bridge *bridge,
+2
drivers/gpu/drm/msm/dsi/phy/dsi_phy.c
··· 541 541 .data = &dsi_phy_28nm_hpm_famb_cfgs }, 542 542 { .compatible = "qcom,dsi-phy-28nm-lp", 543 543 .data = &dsi_phy_28nm_lp_cfgs }, 544 + { .compatible = "qcom,dsi-phy-28nm-8226", 545 + .data = &dsi_phy_28nm_8226_cfgs }, 544 546 #endif 545 547 #ifdef CONFIG_DRM_MSM_DSI_20NM_PHY 546 548 { .compatible = "qcom,dsi-phy-20nm",
+2 -1
drivers/gpu/drm/msm/dsi/phy/dsi_phy.h
··· 46 46 extern const struct msm_dsi_phy_cfg dsi_phy_28nm_hpm_cfgs; 47 47 extern const struct msm_dsi_phy_cfg dsi_phy_28nm_hpm_famb_cfgs; 48 48 extern const struct msm_dsi_phy_cfg dsi_phy_28nm_lp_cfgs; 49 - extern const struct msm_dsi_phy_cfg dsi_phy_20nm_cfgs; 49 + extern const struct msm_dsi_phy_cfg dsi_phy_28nm_8226_cfgs; 50 50 extern const struct msm_dsi_phy_cfg dsi_phy_28nm_8960_cfgs; 51 + extern const struct msm_dsi_phy_cfg dsi_phy_20nm_cfgs; 51 52 extern const struct msm_dsi_phy_cfg dsi_phy_14nm_cfgs; 52 53 extern const struct msm_dsi_phy_cfg dsi_phy_14nm_660_cfgs; 53 54 extern const struct msm_dsi_phy_cfg dsi_phy_14nm_2290_cfgs;
+3
drivers/gpu/drm/msm/dsi/phy/dsi_phy_14nm.c
··· 539 539 if (unlikely(pll_14nm->phy->pll_on)) 540 540 return 0; 541 541 542 + if (dsi_pll_14nm_vco_recalc_rate(hw, VCO_REF_CLK_RATE) == 0) 543 + dsi_pll_14nm_vco_set_rate(hw, pll_14nm->phy->cfg->min_pll_rate, VCO_REF_CLK_RATE); 544 + 542 545 dsi_phy_write(base + REG_DSI_14nm_PHY_PLL_VREF_CFG1, 0x10); 543 546 dsi_phy_write(cmn_base + REG_DSI_14nm_PHY_CMN_PLL_CNTRL, 1); 544 547
+97
drivers/gpu/drm/msm/dsi/phy/dsi_phy_28nm.c
··· 37 37 38 38 /* v2.0.0 28nm LP implementation */ 39 39 #define DSI_PHY_28NM_QUIRK_PHY_LP BIT(0) 40 + #define DSI_PHY_28NM_QUIRK_PHY_8226 BIT(1) 40 41 41 42 #define LPFR_LUT_SIZE 10 42 43 struct lpfr_cfg { ··· 378 377 return ret; 379 378 } 380 379 380 + static int dsi_pll_28nm_vco_prepare_8226(struct clk_hw *hw) 381 + { 382 + struct dsi_pll_28nm *pll_28nm = to_pll_28nm(hw); 383 + struct device *dev = &pll_28nm->phy->pdev->dev; 384 + void __iomem *base = pll_28nm->phy->pll_base; 385 + u32 max_reads = 5, timeout_us = 100; 386 + bool locked; 387 + u32 val; 388 + int i; 389 + 390 + DBG("id=%d", pll_28nm->phy->id); 391 + 392 + pll_28nm_software_reset(pll_28nm); 393 + 394 + /* 395 + * PLL power up sequence. 396 + * Add necessary delays recommended by hardware. 397 + */ 398 + dsi_phy_write(base + REG_DSI_28nm_PHY_PLL_CAL_CFG1, 0x34); 399 + 400 + val = DSI_28nm_PHY_PLL_GLB_CFG_PLL_PWRDN_B; 401 + dsi_phy_write_udelay(base + REG_DSI_28nm_PHY_PLL_GLB_CFG, val, 200); 402 + 403 + val |= DSI_28nm_PHY_PLL_GLB_CFG_PLL_PWRGEN_PWRDN_B; 404 + dsi_phy_write_udelay(base + REG_DSI_28nm_PHY_PLL_GLB_CFG, val, 200); 405 + 406 + val |= DSI_28nm_PHY_PLL_GLB_CFG_PLL_LDO_PWRDN_B; 407 + val |= DSI_28nm_PHY_PLL_GLB_CFG_PLL_ENABLE; 408 + dsi_phy_write_udelay(base + REG_DSI_28nm_PHY_PLL_GLB_CFG, val, 600); 409 + 410 + for (i = 0; i < 7; i++) { 411 + /* DSI Uniphy lock detect setting */ 412 + dsi_phy_write(base + REG_DSI_28nm_PHY_PLL_LKDET_CFG2, 0x0d); 413 + dsi_phy_write_udelay(base + REG_DSI_28nm_PHY_PLL_LKDET_CFG2, 414 + 0x0c, 100); 415 + dsi_phy_write(base + REG_DSI_28nm_PHY_PLL_LKDET_CFG2, 0x0d); 416 + 417 + /* poll for PLL ready status */ 418 + locked = pll_28nm_poll_for_ready(pll_28nm, 419 + max_reads, timeout_us); 420 + if (locked) 421 + break; 422 + 423 + pll_28nm_software_reset(pll_28nm); 424 + 425 + /* 426 + * PLL power up sequence. 427 + * Add necessary delays recommended by hardware. 428 + */ 429 + dsi_phy_write_udelay(base + REG_DSI_28nm_PHY_PLL_PWRGEN_CFG, 0x00, 50); 430 + 431 + val = DSI_28nm_PHY_PLL_GLB_CFG_PLL_PWRDN_B; 432 + val |= DSI_28nm_PHY_PLL_GLB_CFG_PLL_PWRGEN_PWRDN_B; 433 + dsi_phy_write_udelay(base + REG_DSI_28nm_PHY_PLL_GLB_CFG, val, 100); 434 + 435 + val |= DSI_28nm_PHY_PLL_GLB_CFG_PLL_LDO_PWRDN_B; 436 + val |= DSI_28nm_PHY_PLL_GLB_CFG_PLL_ENABLE; 437 + dsi_phy_write_udelay(base + REG_DSI_28nm_PHY_PLL_GLB_CFG, val, 600); 438 + } 439 + 440 + if (unlikely(!locked)) 441 + DRM_DEV_ERROR(dev, "DSI PLL lock failed\n"); 442 + else 443 + DBG("DSI PLL Lock success"); 444 + 445 + return locked ? 0 : -EINVAL; 446 + } 447 + 381 448 static int dsi_pll_28nm_vco_prepare_lp(struct clk_hw *hw) 382 449 { 383 450 struct dsi_pll_28nm *pll_28nm = to_pll_28nm(hw); ··· 540 471 .is_enabled = dsi_pll_28nm_clk_is_enabled, 541 472 }; 542 473 474 + static const struct clk_ops clk_ops_dsi_pll_28nm_vco_8226 = { 475 + .round_rate = dsi_pll_28nm_clk_round_rate, 476 + .set_rate = dsi_pll_28nm_clk_set_rate, 477 + .recalc_rate = dsi_pll_28nm_clk_recalc_rate, 478 + .prepare = dsi_pll_28nm_vco_prepare_8226, 479 + .unprepare = dsi_pll_28nm_vco_unprepare, 480 + .is_enabled = dsi_pll_28nm_clk_is_enabled, 481 + }; 482 + 543 483 /* 544 484 * PLL Callbacks 545 485 */ ··· 614 536 615 537 if (pll_28nm->phy->cfg->quirks & DSI_PHY_28NM_QUIRK_PHY_LP) 616 538 vco_init.ops = &clk_ops_dsi_pll_28nm_vco_lp; 539 + else if (pll_28nm->phy->cfg->quirks & DSI_PHY_28NM_QUIRK_PHY_8226) 540 + vco_init.ops = &clk_ops_dsi_pll_28nm_vco_8226; 617 541 else 618 542 vco_init.ops = &clk_ops_dsi_pll_28nm_vco_hpm; 619 543 ··· 900 820 .quirks = DSI_PHY_28NM_QUIRK_PHY_LP, 901 821 }; 902 822 823 + const struct msm_dsi_phy_cfg dsi_phy_28nm_8226_cfgs = { 824 + .has_phy_regulator = true, 825 + .regulator_data = dsi_phy_28nm_regulators, 826 + .num_regulators = ARRAY_SIZE(dsi_phy_28nm_regulators), 827 + .ops = { 828 + .enable = dsi_28nm_phy_enable, 829 + .disable = dsi_28nm_phy_disable, 830 + .pll_init = dsi_pll_28nm_init, 831 + .save_pll_state = dsi_28nm_pll_save_state, 832 + .restore_pll_state = dsi_28nm_pll_restore_state, 833 + }, 834 + .min_pll_rate = VCO_MIN_RATE, 835 + .max_pll_rate = VCO_MAX_RATE, 836 + .io_start = { 0xfd922b00 }, 837 + .num_dsi_phy = 1, 838 + .quirks = DSI_PHY_28NM_QUIRK_PHY_8226, 839 + };
+3 -3
drivers/gpu/drm/msm/msm_debugfs.c
··· 211 211 212 212 static int msm_gem_show(struct seq_file *m, void *arg) 213 213 { 214 - struct drm_info_node *node = (struct drm_info_node *) m->private; 214 + struct drm_info_node *node = m->private; 215 215 struct drm_device *dev = node->minor->dev; 216 216 struct msm_drm_private *priv = dev->dev_private; 217 217 int ret; ··· 229 229 230 230 static int msm_mm_show(struct seq_file *m, void *arg) 231 231 { 232 - struct drm_info_node *node = (struct drm_info_node *) m->private; 232 + struct drm_info_node *node = m->private; 233 233 struct drm_device *dev = node->minor->dev; 234 234 struct drm_printer p = drm_seq_file_printer(m); 235 235 ··· 240 240 241 241 static int msm_fb_show(struct seq_file *m, void *arg) 242 242 { 243 - struct drm_info_node *node = (struct drm_info_node *) m->private; 243 + struct drm_info_node *node = m->private; 244 244 struct drm_device *dev = node->minor->dev; 245 245 struct drm_framebuffer *fb, *fbdev_fb = NULL; 246 246
+38
drivers/gpu/drm/msm/msm_dsc_helper.h
··· 1 + /* SPDX-License-Identifier: GPL-2.0-only */ 2 + /* 3 + * Copyright (c) 2023 Qualcomm Innovation Center, Inc. All rights reserved 4 + * 5 + * Helper methods for MSM-specific DSC calculations that are common between timing engine, 6 + * DSI, and DP. 7 + */ 8 + 9 + #ifndef MSM_DSC_HELPER_H_ 10 + #define MSM_DSC_HELPER_H_ 11 + 12 + #include <linux/math.h> 13 + #include <drm/display/drm_dsc_helper.h> 14 + 15 + /** 16 + * msm_dsc_get_slices_per_intf() - calculate number of slices per interface 17 + * @dsc: Pointer to drm dsc config struct 18 + * @intf_width: interface width in pixels 19 + * Returns: Integer representing the number of slices for the given interface 20 + */ 21 + static inline u32 msm_dsc_get_slices_per_intf(const struct drm_dsc_config *dsc, u32 intf_width) 22 + { 23 + return DIV_ROUND_UP(intf_width, dsc->slice_width); 24 + } 25 + 26 + /** 27 + * msm_dsc_get_bytes_per_line() - calculate bytes per line 28 + * @dsc: Pointer to drm dsc config struct 29 + * Returns: Integer value representing bytes per line. DSI and DP need 30 + * to perform further calculations to turn this into pclk_per_intf, 31 + * such as dividing by different values depending on if widebus is enabled. 32 + */ 33 + static inline u32 msm_dsc_get_bytes_per_line(const struct drm_dsc_config *dsc) 34 + { 35 + return dsc->slice_count * dsc->slice_chunk_size; 36 + } 37 + 38 + #endif /* MSM_DSC_HELPER_H_ */
+20
drivers/gpu/drm/msm/msm_fbdev.c
··· 139 139 return ret; 140 140 } 141 141 142 + static int msm_fbdev_fb_dirty(struct drm_fb_helper *helper, 143 + struct drm_clip_rect *clip) 144 + { 145 + struct drm_device *dev = helper->dev; 146 + int ret; 147 + 148 + /* Call damage handlers only if necessary */ 149 + if (!(clip->x1 < clip->x2 && clip->y1 < clip->y2)) 150 + return 0; 151 + 152 + if (helper->fb->funcs->dirty) { 153 + ret = helper->fb->funcs->dirty(helper->fb, NULL, 0, 0, clip, 1); 154 + if (drm_WARN_ONCE(dev, ret, "Dirty helper failed: ret=%d\n", ret)) 155 + return ret; 156 + } 157 + 158 + return 0; 159 + } 160 + 142 161 static const struct drm_fb_helper_funcs msm_fb_helper_funcs = { 143 162 .fb_probe = msm_fbdev_create, 163 + .fb_dirty = msm_fbdev_fb_dirty, 144 164 }; 145 165 146 166 /*
+4 -3
drivers/gpu/drm/msm/msm_gem_submit.c
··· 558 558 struct drm_file *file, 559 559 uint64_t in_syncobjs_addr, 560 560 uint32_t nr_in_syncobjs, 561 - size_t syncobj_stride, 562 - struct msm_ringbuffer *ring) 561 + size_t syncobj_stride) 563 562 { 564 563 struct drm_syncobj **syncobjs = NULL; 565 564 struct drm_msm_gem_submit_syncobj syncobj_desc = {0}; ··· 807 808 syncobjs_to_reset = msm_parse_deps(submit, file, 808 809 args->in_syncobjs, 809 810 args->nr_in_syncobjs, 810 - args->syncobj_stride, ring); 811 + args->syncobj_stride); 811 812 if (IS_ERR(syncobjs_to_reset)) { 812 813 ret = PTR_ERR(syncobjs_to_reset); 813 814 goto out_unlock; ··· 947 948 948 949 /* The scheduler owns a ref now: */ 949 950 msm_gem_submit_get(submit); 951 + 952 + msm_rd_dump_submit(priv->rd, submit, NULL); 950 953 951 954 drm_sched_entity_push_job(&submit->base); 952 955
-4
drivers/gpu/drm/msm/msm_gpu.c
··· 746 746 /* add bo's to gpu's ring, and kick gpu: */ 747 747 void msm_gpu_submit(struct msm_gpu *gpu, struct msm_gem_submit *submit) 748 748 { 749 - struct drm_device *dev = gpu->dev; 750 - struct msm_drm_private *priv = dev->dev_private; 751 749 struct msm_ringbuffer *ring = submit->ring; 752 750 unsigned long flags; 753 751 ··· 756 758 msm_gpu_hw_init(gpu); 757 759 758 760 submit->seqno = submit->hw_fence->seqno; 759 - 760 - msm_rd_dump_submit(priv->rd, submit, NULL); 761 761 762 762 update_sw_cntrs(gpu); 763 763
+10
drivers/gpu/drm/msm/msm_mdss.c
··· 538 538 .highest_bank_bit = 2, 539 539 }; 540 540 541 + static const struct msm_mdss_data sm6350_data = { 542 + .ubwc_version = UBWC_2_0, 543 + .ubwc_dec_version = UBWC_2_0, 544 + .ubwc_swizzle = 6, 545 + .ubwc_static = 0x1e, 546 + .highest_bank_bit = 1, 547 + }; 548 + 541 549 static const struct msm_mdss_data sm8150_data = { 542 550 .ubwc_version = UBWC_3_0, 543 551 .ubwc_dec_version = UBWC_3_0, ··· 579 571 { .compatible = "qcom,sc8180x-mdss", .data = &sc8180x_data }, 580 572 { .compatible = "qcom,sc8280xp-mdss", .data = &sc8280xp_data }, 581 573 { .compatible = "qcom,sm6115-mdss", .data = &sm6115_data }, 574 + { .compatible = "qcom,sm6350-mdss", .data = &sm6350_data }, 575 + { .compatible = "qcom,sm6375-mdss", .data = &sm6350_data }, 582 576 { .compatible = "qcom,sm8150-mdss", .data = &sm8150_data }, 583 577 { .compatible = "qcom,sm8250-mdss", .data = &sm8250_data }, 584 578 { .compatible = "qcom,sm8350-mdss", .data = &sm8250_data },
+8 -16
drivers/gpu/drm/msm/msm_rd.c
··· 83 83 84 84 bool open; 85 85 86 - /* current submit to read out: */ 87 - struct msm_gem_submit *submit; 88 - 89 86 /* fifo access is synchronized on the producer side by 90 - * gpu->lock held by submit code (otherwise we could 91 - * end up w/ cmds logged in different order than they 92 - * were executed). And read_lock synchronizes the reads 87 + * write_lock. And read_lock synchronizes the reads 93 88 */ 94 - struct mutex read_lock; 89 + struct mutex read_lock, write_lock; 95 90 96 91 wait_queue_head_t fifo_event; 97 92 struct circ_buf fifo; ··· 238 243 return; 239 244 240 245 mutex_destroy(&rd->read_lock); 246 + mutex_destroy(&rd->write_lock); 241 247 kfree(rd); 242 248 } 243 249 ··· 254 258 rd->fifo.buf = rd->buf; 255 259 256 260 mutex_init(&rd->read_lock); 261 + mutex_init(&rd->write_lock); 257 262 258 263 init_waitqueue_head(&rd->fifo_event); 259 264 ··· 335 338 if (!(submit->bos[idx].flags & MSM_SUBMIT_BO_READ)) 336 339 return; 337 340 338 - msm_gem_lock(&obj->base); 339 341 buf = msm_gem_get_vaddr_active(&obj->base); 340 342 if (IS_ERR(buf)) 341 - goto out_unlock; 343 + return; 342 344 343 345 buf += offset; 344 346 345 347 rd_write_section(rd, RD_BUFFER_CONTENTS, buf, size); 346 348 347 349 msm_gem_put_vaddr_locked(&obj->base); 348 - 349 - out_unlock: 350 - msm_gem_unlock(&obj->base); 351 350 } 352 351 353 352 /* called under gpu->lock */ ··· 357 364 if (!rd->open) 358 365 return; 359 366 360 - /* writing into fifo is serialized by caller, and 361 - * rd->read_lock is used to serialize the reads 362 - */ 363 - WARN_ON(!mutex_is_locked(&submit->gpu->lock)); 367 + mutex_lock(&rd->write_lock); 364 368 365 369 if (fmt) { 366 370 va_list args; ··· 414 424 break; 415 425 } 416 426 } 427 + 428 + mutex_unlock(&rd->write_lock); 417 429 } 418 430 #endif
+4
include/drm/display/drm_dsc_helper.h
··· 21 21 int drm_dsc_dp_rc_buffer_size(u8 rc_buffer_block_size, u8 rc_buffer_size); 22 22 void drm_dsc_pps_payload_pack(struct drm_dsc_picture_parameter_set *pps_sdp, 23 23 const struct drm_dsc_config *dsc_cfg); 24 + void drm_dsc_set_const_params(struct drm_dsc_config *vdsc_cfg); 24 25 void drm_dsc_set_rc_buf_thresh(struct drm_dsc_config *vdsc_cfg); 25 26 int drm_dsc_setup_rc_params(struct drm_dsc_config *vdsc_cfg, enum drm_dsc_params_type type); 26 27 int drm_dsc_compute_rc_parameters(struct drm_dsc_config *vdsc_cfg); 28 + u8 drm_dsc_initial_scale_value(const struct drm_dsc_config *dsc); 29 + u32 drm_dsc_flatness_det_thresh(const struct drm_dsc_config *dsc); 30 + u32 drm_dsc_get_bpp_int(const struct drm_dsc_config *vdsc_cfg); 27 31 28 32 #endif /* _DRM_DSC_HELPER_H_ */ 29 33