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-2024-10-28' of https://gitlab.freedesktop.org/drm/msm into drm-next

Updates for v6.13

Core:
- Switch to aperture_remove_all_conflicting_devices()
- Simplify msm_disp_state_dump_regs()

DPU:
- Add SA8775P support
- Add (disabled by default) MSM8917, MSM8937, MSM8953 and MSM8996
support
- Enable support for larger framebuffers (required for X.Org working
with several outputs)
- Dropped LM_3, LM_4 (MSM8998, SDM845)
- Fixed DSPP_3 routing on SDM845

DP:
- Add SA8775P support

HDMI:
- Mark two arrays as const in MSM8998 HDMI PHY driver

GPU:
- a7xx preemption support
- Adreno A663 support
- Typos fixes, etc
- Fix excessive stack usage in a6xx GMU

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

+3196 -1018
+1
Documentation/devicetree/bindings/display/msm/dp-controller.yaml
··· 17 17 compatible: 18 18 oneOf: 19 19 - enum: 20 + - qcom,sa8775p-dp 20 21 - qcom,sc7180-dp 21 22 - qcom,sc7280-dp 22 23 - qcom,sc7280-edp
+1
Documentation/devicetree/bindings/display/msm/gmu.yaml
··· 125 125 enum: 126 126 - qcom,adreno-gmu-635.0 127 127 - qcom,adreno-gmu-660.1 128 + - qcom,adreno-gmu-663.0 128 129 then: 129 130 properties: 130 131 reg:
+241
Documentation/devicetree/bindings/display/msm/qcom,sa8775p-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,sa8775p-mdss.yaml# 5 + $schema: http://devicetree.org/meta-schemas/core.yaml# 6 + 7 + title: Qualcomm Technologies, Inc. SA87755P Display MDSS 8 + 9 + maintainers: 10 + - Mahadevan <quic_mahap@quicinc.com> 11 + 12 + description: 13 + SA8775P MSM Mobile Display Subsystem(MDSS), which encapsulates sub-blocks like 14 + DPU display controller, DP interfaces and EDP etc. 15 + 16 + $ref: /schemas/display/msm/mdss-common.yaml# 17 + 18 + properties: 19 + compatible: 20 + const: qcom,sa8775p-mdss 21 + 22 + clocks: 23 + items: 24 + - description: Display AHB 25 + - description: Display hf AXI 26 + - description: Display core 27 + 28 + iommus: 29 + maxItems: 1 30 + 31 + interconnects: 32 + maxItems: 3 33 + 34 + interconnect-names: 35 + maxItems: 3 36 + 37 + patternProperties: 38 + "^display-controller@[0-9a-f]+$": 39 + type: object 40 + additionalProperties: true 41 + 42 + properties: 43 + compatible: 44 + const: qcom,sa8775p-dpu 45 + 46 + "^displayport-controller@[0-9a-f]+$": 47 + type: object 48 + additionalProperties: true 49 + 50 + properties: 51 + compatible: 52 + items: 53 + - const: qcom,sa8775p-dp 54 + 55 + required: 56 + - compatible 57 + 58 + unevaluatedProperties: false 59 + 60 + examples: 61 + - | 62 + #include <dt-bindings/interconnect/qcom,icc.h> 63 + #include <dt-bindings/interrupt-controller/arm-gic.h> 64 + #include <dt-bindings/clock/qcom,sa8775p-gcc.h> 65 + #include <dt-bindings/interconnect/qcom,sa8775p-rpmh.h> 66 + #include <dt-bindings/power/qcom,rpmhpd.h> 67 + #include <dt-bindings/power/qcom-rpmpd.h> 68 + 69 + display-subsystem@ae00000 { 70 + compatible = "qcom,sa8775p-mdss"; 71 + reg = <0x0ae00000 0x1000>; 72 + reg-names = "mdss"; 73 + 74 + interconnects = <&mmss_noc MASTER_MDP0 &mc_virt SLAVE_EBI1>, 75 + <&mmss_noc MASTER_MDP1 &mc_virt SLAVE_EBI1>, 76 + <&gem_noc MASTER_APPSS_PROC &config_noc SLAVE_DISPLAY_CFG>; 77 + interconnect-names = "mdp0-mem", 78 + "mdp1-mem", 79 + "cpu-cfg"; 80 + 81 + 82 + resets = <&dispcc_core_bcr>; 83 + power-domains = <&dispcc_gdsc>; 84 + 85 + clocks = <&dispcc_ahb_clk>, 86 + <&gcc GCC_DISP_HF_AXI_CLK>, 87 + <&dispcc_mdp_clk>; 88 + 89 + interrupts = <GIC_SPI 92 IRQ_TYPE_LEVEL_HIGH>; 90 + interrupt-controller; 91 + #interrupt-cells = <1>; 92 + 93 + iommus = <&apps_smmu 0x1000 0x402>; 94 + 95 + #address-cells = <1>; 96 + #size-cells = <1>; 97 + ranges; 98 + 99 + display-controller@ae01000 { 100 + compatible = "qcom,sa8775p-dpu"; 101 + reg = <0x0ae01000 0x8f000>, 102 + <0x0aeb0000 0x2008>; 103 + reg-names = "mdp", "vbif"; 104 + 105 + clocks = <&gcc GCC_DISP_HF_AXI_CLK>, 106 + <&dispcc_ahb_clk>, 107 + <&dispcc_mdp_lut_clk>, 108 + <&dispcc_mdp_clk>, 109 + <&dispcc_mdp_vsync_clk>; 110 + clock-names = "nrt_bus", 111 + "iface", 112 + "lut", 113 + "core", 114 + "vsync"; 115 + 116 + assigned-clocks = <&dispcc_mdp_vsync_clk>; 117 + assigned-clock-rates = <19200000>; 118 + 119 + operating-points-v2 = <&mdss0_mdp_opp_table>; 120 + power-domains = <&rpmhpd RPMHPD_MMCX>; 121 + 122 + interrupt-parent = <&mdss0>; 123 + interrupts = <0>; 124 + 125 + ports { 126 + #address-cells = <1>; 127 + #size-cells = <0>; 128 + 129 + port@0 { 130 + reg = <0>; 131 + dpu_intf0_out: endpoint { 132 + remote-endpoint = <&mdss0_dp0_in>; 133 + }; 134 + }; 135 + }; 136 + 137 + mdss0_mdp_opp_table: opp-table { 138 + compatible = "operating-points-v2"; 139 + 140 + opp-375000000 { 141 + opp-hz = /bits/ 64 <375000000>; 142 + required-opps = <&rpmhpd_opp_svs_l1>; 143 + }; 144 + 145 + opp-500000000 { 146 + opp-hz = /bits/ 64 <500000000>; 147 + required-opps = <&rpmhpd_opp_nom>; 148 + }; 149 + 150 + opp-575000000 { 151 + opp-hz = /bits/ 64 <575000000>; 152 + required-opps = <&rpmhpd_opp_turbo>; 153 + }; 154 + 155 + opp-650000000 { 156 + opp-hz = /bits/ 64 <650000000>; 157 + required-opps = <&rpmhpd_opp_turbo_l1>; 158 + }; 159 + }; 160 + }; 161 + 162 + displayport-controller@af54000 { 163 + compatible = "qcom,sa8775p-dp"; 164 + 165 + pinctrl-0 = <&dp_hot_plug_det>; 166 + pinctrl-names = "default"; 167 + 168 + reg = <0xaf54000 0x104>, 169 + <0xaf54200 0x0c0>, 170 + <0xaf55000 0x770>, 171 + <0xaf56000 0x09c>; 172 + 173 + interrupt-parent = <&mdss0>; 174 + interrupts = <12>; 175 + 176 + clocks = <&dispcc_mdss_ahb_clk>, 177 + <&dispcc_dptx0_aux_clk>, 178 + <&dispcc_dptx0_link_clk>, 179 + <&dispcc_dptx0_link_intf_clk>, 180 + <&dispcc_dptx0_pixel0_clk>; 181 + clock-names = "core_iface", 182 + "core_aux", 183 + "ctrl_link", 184 + "ctrl_link_iface", 185 + "stream_pixel"; 186 + 187 + assigned-clocks = <&dispcc_mdss_dptx0_link_clk_src>, 188 + <&dispcc_mdss_dptx0_pixel0_clk_src>; 189 + assigned-clock-parents = <&mdss0_edp_phy 0>, <&mdss0_edp_phy 1>; 190 + 191 + phys = <&mdss0_edp_phy>; 192 + phy-names = "dp"; 193 + 194 + operating-points-v2 = <&dp_opp_table>; 195 + power-domains = <&rpmhpd SA8775P_MMCX>; 196 + 197 + #sound-dai-cells = <0>; 198 + 199 + ports { 200 + #address-cells = <1>; 201 + #size-cells = <0>; 202 + 203 + port@0 { 204 + reg = <0>; 205 + mdss0_dp0_in: endpoint { 206 + remote-endpoint = <&dpu_intf0_out>; 207 + }; 208 + }; 209 + 210 + port@1 { 211 + reg = <1>; 212 + mdss0_dp_out: endpoint { }; 213 + }; 214 + }; 215 + 216 + dp_opp_table: opp-table { 217 + compatible = "operating-points-v2"; 218 + 219 + opp-160000000 { 220 + opp-hz = /bits/ 64 <160000000>; 221 + required-opps = <&rpmhpd_opp_low_svs>; 222 + }; 223 + 224 + opp-270000000 { 225 + opp-hz = /bits/ 64 <270000000>; 226 + required-opps = <&rpmhpd_opp_svs>; 227 + }; 228 + 229 + opp-540000000 { 230 + opp-hz = /bits/ 64 <540000000>; 231 + required-opps = <&rpmhpd_opp_svs_l1>; 232 + }; 233 + 234 + opp-810000000 { 235 + opp-hz = /bits/ 64 <810000000>; 236 + required-opps = <&rpmhpd_opp_nom>; 237 + }; 238 + }; 239 + }; 240 + }; 241 + ...
+9 -1
Documentation/devicetree/bindings/display/msm/qcom,sc7280-dpu.yaml
··· 7 7 title: Qualcomm Display DPU on SC7280 8 8 9 9 maintainers: 10 + - Bjorn Andersson <andersson@kernel.org> 11 + - Neil Armstrong <neil.armstrong@linaro.org> 12 + - Dmitry Baryshkov <dmitry.baryshkov@linaro.org> 10 13 - Krishna Manikandan <quic_mkrishn@quicinc.com> 11 14 12 15 $ref: /schemas/display/msm/dpu-common.yaml# 13 16 14 17 properties: 15 18 compatible: 16 - const: qcom,sc7280-dpu 19 + enum: 20 + - qcom,sc7280-dpu 21 + - qcom,sc8280xp-dpu 22 + - qcom,sm8350-dpu 23 + - qcom,sm8450-dpu 24 + - qcom,sm8550-dpu 17 25 18 26 reg: 19 27 items:
-122
Documentation/devicetree/bindings/display/msm/qcom,sc8280xp-dpu.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,sc8280xp-dpu.yaml# 5 - $schema: http://devicetree.org/meta-schemas/core.yaml# 6 - 7 - title: Qualcomm SC8280XP Display Processing Unit 8 - 9 - maintainers: 10 - - Bjorn Andersson <andersson@kernel.org> 11 - 12 - description: 13 - Device tree bindings for SC8280XP Display Processing Unit. 14 - 15 - $ref: /schemas/display/msm/dpu-common.yaml# 16 - 17 - properties: 18 - compatible: 19 - const: qcom,sc8280xp-dpu 20 - 21 - reg: 22 - items: 23 - - description: Address offset and size for mdp register set 24 - - description: Address offset and size for vbif register set 25 - 26 - reg-names: 27 - items: 28 - - const: mdp 29 - - const: vbif 30 - 31 - clocks: 32 - items: 33 - - description: Display hf axi clock 34 - - description: Display sf axi clock 35 - - description: Display ahb clock 36 - - description: Display lut clock 37 - - description: Display core clock 38 - - description: Display vsync clock 39 - 40 - clock-names: 41 - items: 42 - - const: bus 43 - - const: nrt_bus 44 - - const: iface 45 - - const: lut 46 - - const: core 47 - - const: vsync 48 - 49 - unevaluatedProperties: false 50 - 51 - examples: 52 - - | 53 - #include <dt-bindings/clock/qcom,dispcc-sc8280xp.h> 54 - #include <dt-bindings/clock/qcom,gcc-sc8280xp.h> 55 - #include <dt-bindings/interrupt-controller/arm-gic.h> 56 - #include <dt-bindings/interconnect/qcom,sc8280xp.h> 57 - #include <dt-bindings/power/qcom-rpmpd.h> 58 - 59 - display-controller@ae01000 { 60 - compatible = "qcom,sc8280xp-dpu"; 61 - reg = <0x0ae01000 0x8f000>, 62 - <0x0aeb0000 0x2008>; 63 - reg-names = "mdp", "vbif"; 64 - 65 - clocks = <&gcc GCC_DISP_HF_AXI_CLK>, 66 - <&gcc GCC_DISP_SF_AXI_CLK>, 67 - <&dispcc0 DISP_CC_MDSS_AHB_CLK>, 68 - <&dispcc0 DISP_CC_MDSS_MDP_LUT_CLK>, 69 - <&dispcc0 DISP_CC_MDSS_MDP_CLK>, 70 - <&dispcc0 DISP_CC_MDSS_VSYNC_CLK>; 71 - clock-names = "bus", 72 - "nrt_bus", 73 - "iface", 74 - "lut", 75 - "core", 76 - "vsync"; 77 - 78 - assigned-clocks = <&dispcc0 DISP_CC_MDSS_MDP_CLK>, 79 - <&dispcc0 DISP_CC_MDSS_VSYNC_CLK>; 80 - assigned-clock-rates = <460000000>, 81 - <19200000>; 82 - 83 - operating-points-v2 = <&mdp_opp_table>; 84 - power-domains = <&rpmhpd SC8280XP_MMCX>; 85 - 86 - interrupt-parent = <&mdss0>; 87 - interrupts = <0>; 88 - 89 - ports { 90 - #address-cells = <1>; 91 - #size-cells = <0>; 92 - 93 - port@0 { 94 - reg = <0>; 95 - endpoint { 96 - remote-endpoint = <&mdss0_dp0_in>; 97 - }; 98 - }; 99 - 100 - port@4 { 101 - reg = <4>; 102 - endpoint { 103 - remote-endpoint = <&mdss0_dp1_in>; 104 - }; 105 - }; 106 - 107 - port@5 { 108 - reg = <5>; 109 - endpoint { 110 - remote-endpoint = <&mdss0_dp3_in>; 111 - }; 112 - }; 113 - 114 - port@6 { 115 - reg = <6>; 116 - endpoint { 117 - remote-endpoint = <&mdss0_dp2_in>; 118 - }; 119 - }; 120 - }; 121 - }; 122 - ...
+3 -1
Documentation/devicetree/bindings/display/msm/qcom,sm8150-dpu.yaml
··· 13 13 14 14 properties: 15 15 compatible: 16 - const: qcom,sm8150-dpu 16 + enum: 17 + - qcom,sm8150-dpu 18 + - qcom,sm8250-dpu 17 19 18 20 reg: 19 21 items:
-99
Documentation/devicetree/bindings/display/msm/qcom,sm8250-dpu.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,sm8250-dpu.yaml# 5 - $schema: http://devicetree.org/meta-schemas/core.yaml# 6 - 7 - title: Qualcomm SM8250 Display DPU 8 - 9 - maintainers: 10 - - Dmitry Baryshkov <dmitry.baryshkov@linaro.org> 11 - 12 - $ref: /schemas/display/msm/dpu-common.yaml# 13 - 14 - properties: 15 - compatible: 16 - const: qcom,sm8250-dpu 17 - 18 - reg: 19 - items: 20 - - description: Address offset and size for mdp register set 21 - - description: Address offset and size for vbif register set 22 - 23 - reg-names: 24 - items: 25 - - const: mdp 26 - - const: vbif 27 - 28 - clocks: 29 - items: 30 - - description: Display ahb clock 31 - - description: Display hf axi clock 32 - - description: Display core clock 33 - - description: Display vsync clock 34 - 35 - clock-names: 36 - items: 37 - - const: iface 38 - - const: bus 39 - - const: core 40 - - const: vsync 41 - 42 - required: 43 - - compatible 44 - - reg 45 - - reg-names 46 - - clocks 47 - - clock-names 48 - 49 - unevaluatedProperties: false 50 - 51 - examples: 52 - - | 53 - #include <dt-bindings/clock/qcom,dispcc-sm8250.h> 54 - #include <dt-bindings/clock/qcom,gcc-sm8250.h> 55 - #include <dt-bindings/interrupt-controller/arm-gic.h> 56 - #include <dt-bindings/interconnect/qcom,sm8250.h> 57 - #include <dt-bindings/power/qcom,rpmhpd.h> 58 - 59 - display-controller@ae01000 { 60 - compatible = "qcom,sm8250-dpu"; 61 - reg = <0x0ae01000 0x8f000>, 62 - <0x0aeb0000 0x2008>; 63 - reg-names = "mdp", "vbif"; 64 - 65 - clocks = <&dispcc DISP_CC_MDSS_AHB_CLK>, 66 - <&gcc GCC_DISP_HF_AXI_CLK>, 67 - <&dispcc DISP_CC_MDSS_MDP_CLK>, 68 - <&dispcc DISP_CC_MDSS_VSYNC_CLK>; 69 - clock-names = "iface", "bus", "core", "vsync"; 70 - 71 - assigned-clocks = <&dispcc DISP_CC_MDSS_VSYNC_CLK>; 72 - assigned-clock-rates = <19200000>; 73 - 74 - operating-points-v2 = <&mdp_opp_table>; 75 - power-domains = <&rpmhpd RPMHPD_MMCX>; 76 - 77 - interrupt-parent = <&mdss>; 78 - interrupts = <0>; 79 - 80 - ports { 81 - #address-cells = <1>; 82 - #size-cells = <0>; 83 - 84 - port@0 { 85 - reg = <0>; 86 - endpoint { 87 - remote-endpoint = <&dsi0_in>; 88 - }; 89 - }; 90 - 91 - port@1 { 92 - reg = <1>; 93 - endpoint { 94 - remote-endpoint = <&dsi1_in>; 95 - }; 96 - }; 97 - }; 98 - }; 99 - ...
-120
Documentation/devicetree/bindings/display/msm/qcom,sm8350-dpu.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,sm8350-dpu.yaml# 5 - $schema: http://devicetree.org/meta-schemas/core.yaml# 6 - 7 - title: Qualcomm SM8350 Display DPU 8 - 9 - maintainers: 10 - - Robert Foss <robert.foss@linaro.org> 11 - 12 - $ref: /schemas/display/msm/dpu-common.yaml# 13 - 14 - properties: 15 - compatible: 16 - const: qcom,sm8350-dpu 17 - 18 - reg: 19 - items: 20 - - description: Address offset and size for mdp register set 21 - - description: Address offset and size for vbif register set 22 - 23 - reg-names: 24 - items: 25 - - const: mdp 26 - - const: vbif 27 - 28 - clocks: 29 - items: 30 - - description: Display hf axi clock 31 - - description: Display sf axi clock 32 - - description: Display ahb clock 33 - - description: Display lut clock 34 - - description: Display core clock 35 - - description: Display vsync clock 36 - 37 - clock-names: 38 - items: 39 - - const: bus 40 - - const: nrt_bus 41 - - const: iface 42 - - const: lut 43 - - const: core 44 - - const: vsync 45 - 46 - unevaluatedProperties: false 47 - 48 - examples: 49 - - | 50 - #include <dt-bindings/clock/qcom,dispcc-sm8350.h> 51 - #include <dt-bindings/clock/qcom,gcc-sm8350.h> 52 - #include <dt-bindings/interrupt-controller/arm-gic.h> 53 - #include <dt-bindings/interconnect/qcom,sm8350.h> 54 - #include <dt-bindings/power/qcom,rpmhpd.h> 55 - 56 - display-controller@ae01000 { 57 - compatible = "qcom,sm8350-dpu"; 58 - reg = <0x0ae01000 0x8f000>, 59 - <0x0aeb0000 0x2008>; 60 - reg-names = "mdp", "vbif"; 61 - 62 - clocks = <&gcc GCC_DISP_HF_AXI_CLK>, 63 - <&gcc GCC_DISP_SF_AXI_CLK>, 64 - <&dispcc DISP_CC_MDSS_AHB_CLK>, 65 - <&dispcc DISP_CC_MDSS_MDP_LUT_CLK>, 66 - <&dispcc DISP_CC_MDSS_MDP_CLK>, 67 - <&dispcc DISP_CC_MDSS_VSYNC_CLK>; 68 - clock-names = "bus", 69 - "nrt_bus", 70 - "iface", 71 - "lut", 72 - "core", 73 - "vsync"; 74 - 75 - assigned-clocks = <&dispcc DISP_CC_MDSS_VSYNC_CLK>; 76 - assigned-clock-rates = <19200000>; 77 - 78 - operating-points-v2 = <&mdp_opp_table>; 79 - power-domains = <&rpmhpd RPMHPD_MMCX>; 80 - 81 - interrupt-parent = <&mdss>; 82 - interrupts = <0>; 83 - 84 - ports { 85 - #address-cells = <1>; 86 - #size-cells = <0>; 87 - 88 - port@0 { 89 - reg = <0>; 90 - dpu_intf1_out: endpoint { 91 - remote-endpoint = <&dsi0_in>; 92 - }; 93 - }; 94 - }; 95 - 96 - mdp_opp_table: opp-table { 97 - compatible = "operating-points-v2"; 98 - 99 - opp-200000000 { 100 - opp-hz = /bits/ 64 <200000000>; 101 - required-opps = <&rpmhpd_opp_low_svs>; 102 - }; 103 - 104 - opp-300000000 { 105 - opp-hz = /bits/ 64 <300000000>; 106 - required-opps = <&rpmhpd_opp_svs>; 107 - }; 108 - 109 - opp-345000000 { 110 - opp-hz = /bits/ 64 <345000000>; 111 - required-opps = <&rpmhpd_opp_svs_l1>; 112 - }; 113 - 114 - opp-460000000 { 115 - opp-hz = /bits/ 64 <460000000>; 116 - required-opps = <&rpmhpd_opp_nom>; 117 - }; 118 - }; 119 - }; 120 - ...
-139
Documentation/devicetree/bindings/display/msm/qcom,sm8450-dpu.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,sm8450-dpu.yaml# 5 - $schema: http://devicetree.org/meta-schemas/core.yaml# 6 - 7 - title: Qualcomm SM8450 Display DPU 8 - 9 - maintainers: 10 - - Dmitry Baryshkov <dmitry.baryshkov@linaro.org> 11 - 12 - $ref: /schemas/display/msm/dpu-common.yaml# 13 - 14 - properties: 15 - compatible: 16 - const: qcom,sm8450-dpu 17 - 18 - reg: 19 - items: 20 - - description: Address offset and size for mdp register set 21 - - description: Address offset and size for vbif register set 22 - 23 - reg-names: 24 - items: 25 - - const: mdp 26 - - const: vbif 27 - 28 - clocks: 29 - items: 30 - - description: Display hf axi 31 - - description: Display sf axi 32 - - description: Display ahb 33 - - description: Display lut 34 - - description: Display core 35 - - description: Display vsync 36 - 37 - clock-names: 38 - items: 39 - - const: bus 40 - - const: nrt_bus 41 - - const: iface 42 - - const: lut 43 - - const: core 44 - - const: vsync 45 - 46 - required: 47 - - compatible 48 - - reg 49 - - reg-names 50 - - clocks 51 - - clock-names 52 - 53 - unevaluatedProperties: false 54 - 55 - examples: 56 - - | 57 - #include <dt-bindings/clock/qcom,sm8450-dispcc.h> 58 - #include <dt-bindings/clock/qcom,gcc-sm8450.h> 59 - #include <dt-bindings/interrupt-controller/arm-gic.h> 60 - #include <dt-bindings/interconnect/qcom,sm8450.h> 61 - #include <dt-bindings/power/qcom,rpmhpd.h> 62 - 63 - display-controller@ae01000 { 64 - compatible = "qcom,sm8450-dpu"; 65 - reg = <0x0ae01000 0x8f000>, 66 - <0x0aeb0000 0x2008>; 67 - reg-names = "mdp", "vbif"; 68 - 69 - clocks = <&gcc GCC_DISP_HF_AXI_CLK>, 70 - <&gcc GCC_DISP_SF_AXI_CLK>, 71 - <&dispcc DISP_CC_MDSS_AHB_CLK>, 72 - <&dispcc DISP_CC_MDSS_MDP_LUT_CLK>, 73 - <&dispcc DISP_CC_MDSS_MDP_CLK>, 74 - <&dispcc DISP_CC_MDSS_VSYNC_CLK>; 75 - clock-names = "bus", 76 - "nrt_bus", 77 - "iface", 78 - "lut", 79 - "core", 80 - "vsync"; 81 - 82 - assigned-clocks = <&dispcc DISP_CC_MDSS_VSYNC_CLK>; 83 - assigned-clock-rates = <19200000>; 84 - 85 - operating-points-v2 = <&mdp_opp_table>; 86 - power-domains = <&rpmhpd RPMHPD_MMCX>; 87 - 88 - interrupt-parent = <&mdss>; 89 - interrupts = <0>; 90 - 91 - ports { 92 - #address-cells = <1>; 93 - #size-cells = <0>; 94 - 95 - port@0 { 96 - reg = <0>; 97 - dpu_intf1_out: endpoint { 98 - remote-endpoint = <&dsi0_in>; 99 - }; 100 - }; 101 - 102 - port@1 { 103 - reg = <1>; 104 - dpu_intf2_out: endpoint { 105 - remote-endpoint = <&dsi1_in>; 106 - }; 107 - }; 108 - }; 109 - 110 - mdp_opp_table: opp-table { 111 - compatible = "operating-points-v2"; 112 - 113 - opp-172000000{ 114 - opp-hz = /bits/ 64 <172000000>; 115 - required-opps = <&rpmhpd_opp_low_svs_d1>; 116 - }; 117 - 118 - opp-200000000 { 119 - opp-hz = /bits/ 64 <200000000>; 120 - required-opps = <&rpmhpd_opp_low_svs>; 121 - }; 122 - 123 - opp-325000000 { 124 - opp-hz = /bits/ 64 <325000000>; 125 - required-opps = <&rpmhpd_opp_svs>; 126 - }; 127 - 128 - opp-375000000 { 129 - opp-hz = /bits/ 64 <375000000>; 130 - required-opps = <&rpmhpd_opp_svs_l1>; 131 - }; 132 - 133 - opp-500000000 { 134 - opp-hz = /bits/ 64 <500000000>; 135 - required-opps = <&rpmhpd_opp_nom>; 136 - }; 137 - }; 138 - }; 139 - ...
-133
Documentation/devicetree/bindings/display/msm/qcom,sm8550-dpu.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,sm8550-dpu.yaml# 5 - $schema: http://devicetree.org/meta-schemas/core.yaml# 6 - 7 - title: Qualcomm SM8550 Display DPU 8 - 9 - maintainers: 10 - - Neil Armstrong <neil.armstrong@linaro.org> 11 - 12 - $ref: /schemas/display/msm/dpu-common.yaml# 13 - 14 - properties: 15 - compatible: 16 - const: qcom,sm8550-dpu 17 - 18 - reg: 19 - items: 20 - - description: Address offset and size for mdp register set 21 - - description: Address offset and size for vbif register set 22 - 23 - reg-names: 24 - items: 25 - - const: mdp 26 - - const: vbif 27 - 28 - clocks: 29 - items: 30 - - description: Display AHB 31 - - description: Display hf axi 32 - - description: Display MDSS ahb 33 - - description: Display lut 34 - - description: Display core 35 - - description: Display vsync 36 - 37 - clock-names: 38 - items: 39 - - const: bus 40 - - const: nrt_bus 41 - - const: iface 42 - - const: lut 43 - - const: core 44 - - const: vsync 45 - 46 - required: 47 - - compatible 48 - - reg 49 - - reg-names 50 - - clocks 51 - - clock-names 52 - 53 - unevaluatedProperties: false 54 - 55 - examples: 56 - - | 57 - #include <dt-bindings/clock/qcom,sm8550-dispcc.h> 58 - #include <dt-bindings/clock/qcom,sm8550-gcc.h> 59 - #include <dt-bindings/interrupt-controller/arm-gic.h> 60 - #include <dt-bindings/power/qcom,rpmhpd.h> 61 - 62 - display-controller@ae01000 { 63 - compatible = "qcom,sm8550-dpu"; 64 - reg = <0x0ae01000 0x8f000>, 65 - <0x0aeb0000 0x2008>; 66 - reg-names = "mdp", "vbif"; 67 - 68 - clocks = <&gcc GCC_DISP_AHB_CLK>, 69 - <&gcc GCC_DISP_HF_AXI_CLK>, 70 - <&dispcc DISP_CC_MDSS_AHB_CLK>, 71 - <&dispcc DISP_CC_MDSS_MDP_LUT_CLK>, 72 - <&dispcc DISP_CC_MDSS_MDP_CLK>, 73 - <&dispcc DISP_CC_MDSS_VSYNC_CLK>; 74 - clock-names = "bus", 75 - "nrt_bus", 76 - "iface", 77 - "lut", 78 - "core", 79 - "vsync"; 80 - 81 - assigned-clocks = <&dispcc DISP_CC_MDSS_VSYNC_CLK>; 82 - assigned-clock-rates = <19200000>; 83 - 84 - operating-points-v2 = <&mdp_opp_table>; 85 - power-domains = <&rpmhpd RPMHPD_MMCX>; 86 - 87 - interrupt-parent = <&mdss>; 88 - interrupts = <0>; 89 - 90 - ports { 91 - #address-cells = <1>; 92 - #size-cells = <0>; 93 - 94 - port@0 { 95 - reg = <0>; 96 - dpu_intf1_out: endpoint { 97 - remote-endpoint = <&dsi0_in>; 98 - }; 99 - }; 100 - 101 - port@1 { 102 - reg = <1>; 103 - dpu_intf2_out: endpoint { 104 - remote-endpoint = <&dsi1_in>; 105 - }; 106 - }; 107 - }; 108 - 109 - mdp_opp_table: opp-table { 110 - compatible = "operating-points-v2"; 111 - 112 - opp-200000000 { 113 - opp-hz = /bits/ 64 <200000000>; 114 - required-opps = <&rpmhpd_opp_low_svs>; 115 - }; 116 - 117 - opp-325000000 { 118 - opp-hz = /bits/ 64 <325000000>; 119 - required-opps = <&rpmhpd_opp_svs>; 120 - }; 121 - 122 - opp-375000000 { 123 - opp-hz = /bits/ 64 <375000000>; 124 - required-opps = <&rpmhpd_opp_svs_l1>; 125 - }; 126 - 127 - opp-514000000 { 128 - opp-hz = /bits/ 64 <514000000>; 129 - required-opps = <&rpmhpd_opp_nom>; 130 - }; 131 - }; 132 - }; 133 - ...
+1
Documentation/devicetree/bindings/display/msm/qcom,sm8650-dpu.yaml
··· 14 14 properties: 15 15 compatible: 16 16 enum: 17 + - qcom,sa8775p-dpu 17 18 - qcom,sm8650-dpu 18 19 - qcom,x1e80100-dpu 19 20
+99
Documentation/gpu/msm-preemption.rst
··· 1 + .. SPDX-License-Identifier: GPL-2.0 2 + 3 + :orphan: 4 + 5 + ============== 6 + MSM Preemption 7 + ============== 8 + 9 + Preemption allows Adreno GPUs to switch to a higher priority ring when work is 10 + pushed to it, reducing latency for high priority submissions. 11 + 12 + When preemption is enabled 4 rings are initialized, corresponding to different 13 + priority levels. Having multiple rings is purely a software concept as the GPU 14 + only has registers to keep track of one graphics ring. 15 + The kernel is able to switch which ring is currently being processed by 16 + requesting preemption. When certain conditions are met, depending on the 17 + priority level, the GPU will save its current state in a series of buffers, 18 + then restores state from a similar set of buffers specified by the kernel. It 19 + then resumes execution and fires an IRQ to let the kernel know the context 20 + switch has completed. 21 + 22 + This mechanism can be used by the kernel to switch between rings. Whenever a 23 + submission occurs the kernel finds the highest priority ring which isn't empty 24 + and preempts to it if said ring is not the one being currently executed. This is 25 + also done whenever a submission completes to make sure execution resumes on a 26 + lower priority ring when a higher priority ring is done. 27 + 28 + Preemption levels 29 + ----------------- 30 + 31 + Preemption can only occur at certain boundaries. The exact conditions can be 32 + configured by changing the preemption level, this allows to compromise between 33 + latency (ie. the time that passes between when the kernel requests preemption 34 + and when the SQE begins saving state) and overhead (the amount of state that 35 + needs to be saved). 36 + 37 + The GPU offers 3 levels: 38 + 39 + Level 0 40 + Preemption only occurs at the submission level. This requires the least amount 41 + of state to be saved as the execution of userspace submitted IBs is never 42 + interrupted, however it offers very little benefit compared to not enabling 43 + preemption of any kind. 44 + 45 + Level 1 46 + Preemption occurs at either bin level, if using GMEM rendering, or draw level 47 + in the sysmem rendering case. 48 + 49 + Level 2 50 + Preemption occurs at draw level. 51 + 52 + Level 1 is the mode that is used by the msm driver. 53 + 54 + Additionally the GPU allows to specify a `skip_save_restore` option. This 55 + disables the saving and restoring of all registers except those relating to the 56 + operation of the SQE itself, reducing overhead. Saving and restoring is only 57 + skipped when using GMEM with Level 1 preemption. When enabling this userspace is 58 + expected to set the state that isn't preserved whenever preemption occurs which 59 + is done by specifying preamble and postambles. Those are IBs that are executed 60 + before and after preemption. 61 + 62 + Preemption buffers 63 + ------------------ 64 + 65 + A series of buffers are necessary to store the state of rings while they are not 66 + being executed. There are different kinds of preemption records and most of 67 + those require one buffer per ring. This is because preemption never occurs 68 + between submissions on the same ring, which always run in sequence when the ring 69 + is active. This means that only one context per ring is effectively active. 70 + 71 + SMMU_INFO 72 + This buffer contains info about the current SMMU configuration such as the 73 + ttbr0 register. The SQE firmware isn't actually able to save this record. 74 + As a result SMMU info must be saved manually from the CP to a buffer and the 75 + SMMU record updated with info from said buffer before triggering 76 + preemption. 77 + 78 + NON_SECURE 79 + This is the main preemption record where most state is saved. It is mostly 80 + opaque to the kernel except for the first few words that must be initialized 81 + by the kernel. 82 + 83 + SECURE 84 + This saves state related to the GPU's secure mode. 85 + 86 + NON_PRIV 87 + The intended purpose of this record is unknown. The SQE firmware actually 88 + ignores it and therefore msm doesn't handle it. 89 + 90 + COUNTER 91 + This record is used to save and restore performance counters. 92 + 93 + Handling the permissions of those buffers is critical for security. All but the 94 + NON_PRIV records need to be inaccessible from userspace, so they must be mapped 95 + in the kernel address space with the MSM_BO_MAP_PRIV flag. 96 + For example, making the NON_SECURE record accessible from userspace would allow 97 + any process to manipulate a saved ring's RPTR which can be used to skip the 98 + execution of some packets in a ring and execute user commands with higher 99 + privileges.
+1
drivers/gpu/drm/msm/Makefile
··· 23 23 adreno/a6xx_gpu.o \ 24 24 adreno/a6xx_gmu.o \ 25 25 adreno/a6xx_hfi.o \ 26 + adreno/a6xx_preempt.o \ 26 27 27 28 adreno-$(CONFIG_DEBUG_FS) += adreno/a5xx_debugfs.o \ 28 29
+1 -1
drivers/gpu/drm/msm/adreno/a2xx_gpu.c
··· 22 22 break; 23 23 case MSM_SUBMIT_CMD_CTX_RESTORE_BUF: 24 24 /* ignore if there has not been a ctx switch: */ 25 - if (gpu->cur_ctx_seqno == submit->queue->ctx->seqno) 25 + if (ring->cur_ctx_seqno == submit->queue->ctx->seqno) 26 26 break; 27 27 fallthrough; 28 28 case MSM_SUBMIT_CMD_BUF:
+1 -1
drivers/gpu/drm/msm/adreno/a3xx_gpu.c
··· 40 40 break; 41 41 case MSM_SUBMIT_CMD_CTX_RESTORE_BUF: 42 42 /* ignore if there has not been a ctx switch: */ 43 - if (gpu->cur_ctx_seqno == submit->queue->ctx->seqno) 43 + if (ring->cur_ctx_seqno == submit->queue->ctx->seqno) 44 44 break; 45 45 fallthrough; 46 46 case MSM_SUBMIT_CMD_BUF:
+1 -1
drivers/gpu/drm/msm/adreno/a4xx_gpu.c
··· 34 34 break; 35 35 case MSM_SUBMIT_CMD_CTX_RESTORE_BUF: 36 36 /* ignore if there has not been a ctx switch: */ 37 - if (gpu->cur_ctx_seqno == submit->queue->ctx->seqno) 37 + if (ring->cur_ctx_seqno == submit->queue->ctx->seqno) 38 38 break; 39 39 fallthrough; 40 40 case MSM_SUBMIT_CMD_BUF:
+3 -3
drivers/gpu/drm/msm/adreno/a5xx_gpu.c
··· 77 77 case MSM_SUBMIT_CMD_IB_TARGET_BUF: 78 78 break; 79 79 case MSM_SUBMIT_CMD_CTX_RESTORE_BUF: 80 - if (gpu->cur_ctx_seqno == submit->queue->ctx->seqno) 80 + if (ring->cur_ctx_seqno == submit->queue->ctx->seqno) 81 81 break; 82 82 fallthrough; 83 83 case MSM_SUBMIT_CMD_BUF: ··· 132 132 unsigned int i, ibs = 0; 133 133 134 134 if (IS_ENABLED(CONFIG_DRM_MSM_GPU_SUDO) && submit->in_rb) { 135 - gpu->cur_ctx_seqno = 0; 135 + ring->cur_ctx_seqno = 0; 136 136 a5xx_submit_in_rb(gpu, submit); 137 137 return; 138 138 } ··· 171 171 case MSM_SUBMIT_CMD_IB_TARGET_BUF: 172 172 break; 173 173 case MSM_SUBMIT_CMD_CTX_RESTORE_BUF: 174 - if (gpu->cur_ctx_seqno == submit->queue->ctx->seqno) 174 + if (ring->cur_ctx_seqno == submit->queue->ctx->seqno) 175 175 break; 176 176 fallthrough; 177 177 case MSM_SUBMIT_CMD_BUF:
+1 -1
drivers/gpu/drm/msm/adreno/a5xx_power.c
··· 307 307 else if (adreno_is_a540(adreno_gpu)) 308 308 a540_lm_setup(gpu); 309 309 310 - /* Set up SP/TP power collpase */ 310 + /* Set up SP/TP power collapse */ 311 311 a5xx_pc_init(gpu); 312 312 313 313 /* Start the GPMU */
+57 -4
drivers/gpu/drm/msm/adreno/a6xx_catalog.c
··· 973 973 }, 974 974 .address_space_size = SZ_16G, 975 975 }, { 976 + .chip_ids = ADRENO_CHIP_IDS(0x06060300), 977 + .family = ADRENO_6XX_GEN4, 978 + .fw = { 979 + [ADRENO_FW_SQE] = "a660_sqe.fw", 980 + [ADRENO_FW_GMU] = "a663_gmu.bin", 981 + }, 982 + .gmem = SZ_1M + SZ_512K, 983 + .inactive_period = DRM_MSM_INACTIVE_PERIOD, 984 + .quirks = ADRENO_QUIRK_HAS_CACHED_COHERENT | 985 + ADRENO_QUIRK_HAS_HW_APRIV, 986 + .init = a6xx_gpu_init, 987 + .a6xx = &(const struct a6xx_info) { 988 + .hwcg = a690_hwcg, 989 + .protect = &a660_protect, 990 + .gmu_cgc_mode = 0x00020200, 991 + .prim_fifo_threshold = 0x00300200, 992 + }, 993 + .address_space_size = SZ_16G, 994 + }, { 976 995 .chip_ids = ADRENO_CHIP_IDS(0x06030500), 977 996 .family = ADRENO_6XX_GEN4, 978 997 .fw = { ··· 1300 1281 }; 1301 1282 DECLARE_ADRENO_PROTECT(a730_protect, 48); 1302 1283 1284 + static const uint32_t a7xx_pwrup_reglist_regs[] = { 1285 + REG_A6XX_UCHE_TRAP_BASE, 1286 + REG_A6XX_UCHE_TRAP_BASE + 1, 1287 + REG_A6XX_UCHE_WRITE_THRU_BASE, 1288 + REG_A6XX_UCHE_WRITE_THRU_BASE + 1, 1289 + REG_A6XX_UCHE_GMEM_RANGE_MIN, 1290 + REG_A6XX_UCHE_GMEM_RANGE_MIN + 1, 1291 + REG_A6XX_UCHE_GMEM_RANGE_MAX, 1292 + REG_A6XX_UCHE_GMEM_RANGE_MAX + 1, 1293 + REG_A6XX_UCHE_CACHE_WAYS, 1294 + REG_A6XX_UCHE_MODE_CNTL, 1295 + REG_A6XX_RB_NC_MODE_CNTL, 1296 + REG_A6XX_RB_CMP_DBG_ECO_CNTL, 1297 + REG_A7XX_GRAS_NC_MODE_CNTL, 1298 + REG_A6XX_RB_CONTEXT_SWITCH_GMEM_SAVE_RESTORE, 1299 + REG_A6XX_UCHE_GBIF_GX_CONFIG, 1300 + REG_A6XX_UCHE_CLIENT_PF, 1301 + REG_A6XX_TPL1_DBG_ECO_CNTL1, 1302 + }; 1303 + 1304 + DECLARE_ADRENO_REGLIST_LIST(a7xx_pwrup_reglist); 1305 + 1303 1306 static const struct adreno_info a7xx_gpus[] = { 1304 1307 { 1305 1308 .chip_ids = ADRENO_CHIP_IDS(0x07000200), ··· 1356 1315 .gmem = SZ_2M, 1357 1316 .inactive_period = DRM_MSM_INACTIVE_PERIOD, 1358 1317 .quirks = ADRENO_QUIRK_HAS_CACHED_COHERENT | 1359 - ADRENO_QUIRK_HAS_HW_APRIV, 1318 + ADRENO_QUIRK_HAS_HW_APRIV | 1319 + ADRENO_QUIRK_PREEMPTION, 1360 1320 .init = a6xx_gpu_init, 1361 1321 .zapfw = "a730_zap.mdt", 1362 1322 .a6xx = &(const struct a6xx_info) { 1363 1323 .hwcg = a730_hwcg, 1364 1324 .protect = &a730_protect, 1325 + .pwrup_reglist = &a7xx_pwrup_reglist, 1365 1326 .gmu_cgc_mode = 0x00020000, 1366 1327 }, 1367 1328 .address_space_size = SZ_16G, 1329 + .preempt_record_size = 2860 * SZ_1K, 1368 1330 }, { 1369 1331 .chip_ids = ADRENO_CHIP_IDS(0x43050a01), /* "C510v2" */ 1370 1332 .family = ADRENO_7XX_GEN2, ··· 1378 1334 .gmem = 3 * SZ_1M, 1379 1335 .inactive_period = DRM_MSM_INACTIVE_PERIOD, 1380 1336 .quirks = ADRENO_QUIRK_HAS_CACHED_COHERENT | 1381 - ADRENO_QUIRK_HAS_HW_APRIV, 1337 + ADRENO_QUIRK_HAS_HW_APRIV | 1338 + ADRENO_QUIRK_PREEMPTION, 1382 1339 .init = a6xx_gpu_init, 1383 1340 .zapfw = "a740_zap.mdt", 1384 1341 .a6xx = &(const struct a6xx_info) { 1385 1342 .hwcg = a740_hwcg, 1386 1343 .protect = &a730_protect, 1344 + .pwrup_reglist = &a7xx_pwrup_reglist, 1387 1345 .gmu_chipid = 0x7020100, 1388 1346 .gmu_cgc_mode = 0x00020202, 1389 1347 }, 1390 1348 .address_space_size = SZ_16G, 1349 + .preempt_record_size = 4192 * SZ_1K, 1391 1350 }, { 1392 1351 .chip_ids = ADRENO_CHIP_IDS(0x43050c01), /* "C512v2" */ 1393 1352 .family = ADRENO_7XX_GEN2, ··· 1401 1354 .gmem = 3 * SZ_1M, 1402 1355 .inactive_period = DRM_MSM_INACTIVE_PERIOD, 1403 1356 .quirks = ADRENO_QUIRK_HAS_CACHED_COHERENT | 1404 - ADRENO_QUIRK_HAS_HW_APRIV, 1357 + ADRENO_QUIRK_HAS_HW_APRIV | 1358 + ADRENO_QUIRK_PREEMPTION, 1405 1359 .init = a6xx_gpu_init, 1406 1360 .a6xx = &(const struct a6xx_info) { 1407 1361 .hwcg = a740_hwcg, 1408 1362 .protect = &a730_protect, 1363 + .pwrup_reglist = &a7xx_pwrup_reglist, 1409 1364 .gmu_chipid = 0x7050001, 1410 1365 .gmu_cgc_mode = 0x00020202, 1411 1366 }, 1412 1367 .address_space_size = SZ_256G, 1368 + .preempt_record_size = 4192 * SZ_1K, 1413 1369 }, { 1414 1370 .chip_ids = ADRENO_CHIP_IDS(0x43051401), /* "C520v2" */ 1415 1371 .family = ADRENO_7XX_GEN3, ··· 1423 1373 .gmem = 3 * SZ_1M, 1424 1374 .inactive_period = DRM_MSM_INACTIVE_PERIOD, 1425 1375 .quirks = ADRENO_QUIRK_HAS_CACHED_COHERENT | 1426 - ADRENO_QUIRK_HAS_HW_APRIV, 1376 + ADRENO_QUIRK_HAS_HW_APRIV | 1377 + ADRENO_QUIRK_PREEMPTION, 1427 1378 .init = a6xx_gpu_init, 1428 1379 .zapfw = "gen70900_zap.mbn", 1429 1380 .a6xx = &(const struct a6xx_info) { 1430 1381 .protect = &a730_protect, 1382 + .pwrup_reglist = &a7xx_pwrup_reglist, 1431 1383 .gmu_chipid = 0x7090100, 1432 1384 .gmu_cgc_mode = 0x00020202, 1433 1385 }, 1434 1386 .address_space_size = SZ_16G, 1387 + .preempt_record_size = 3572 * SZ_1K, 1435 1388 } 1436 1389 }; 1437 1390 DECLARE_ADRENO_GPULIST(a7xx);
+1 -3
drivers/gpu/drm/msm/adreno/a6xx_gmu.c
··· 1522 1522 1523 1523 irq = platform_get_irq_byname(pdev, name); 1524 1524 1525 - ret = request_irq(irq, handler, IRQF_TRIGGER_HIGH, name, gmu); 1525 + ret = request_irq(irq, handler, IRQF_TRIGGER_HIGH | IRQF_NO_AUTOEN, name, gmu); 1526 1526 if (ret) { 1527 1527 DRM_DEV_ERROR(&pdev->dev, "Unable to get interrupt %s %d\n", 1528 1528 name, ret); 1529 1529 return ret; 1530 1530 } 1531 - 1532 - disable_irq(irq); 1533 1531 1534 1532 return irq; 1535 1533 }
+1
drivers/gpu/drm/msm/adreno/a6xx_gmu.h
··· 99 99 struct completion pd_gate; 100 100 101 101 struct qmp *qmp; 102 + struct a6xx_hfi_msg_bw_table *bw_table; 102 103 }; 103 104 104 105 static inline u32 gmu_read(struct a6xx_gmu *gmu, u32 offset)
+224 -22
drivers/gpu/drm/msm/adreno/a6xx_gpu.c
··· 68 68 69 69 static void a6xx_flush(struct msm_gpu *gpu, struct msm_ringbuffer *ring) 70 70 { 71 + struct adreno_gpu *adreno_gpu = to_adreno_gpu(gpu); 72 + struct a6xx_gpu *a6xx_gpu = to_a6xx_gpu(adreno_gpu); 71 73 uint32_t wptr; 72 74 unsigned long flags; 73 75 ··· 83 81 /* Make sure to wrap wptr if we need to */ 84 82 wptr = get_wptr(ring); 85 83 84 + /* Update HW if this is the current ring and we are not in preempt*/ 85 + if (!a6xx_in_preempt(a6xx_gpu)) { 86 + if (a6xx_gpu->cur_ring == ring) 87 + gpu_write(gpu, REG_A6XX_CP_RB_WPTR, wptr); 88 + else 89 + ring->restore_wptr = true; 90 + } else { 91 + ring->restore_wptr = true; 92 + } 93 + 86 94 spin_unlock_irqrestore(&ring->preempt_lock, flags); 87 - 88 - /* Make sure everything is posted before making a decision */ 89 - mb(); 90 - 91 - gpu_write(gpu, REG_A6XX_CP_RB_WPTR, wptr); 92 95 } 93 96 94 97 static void get_stats_counter(struct msm_ringbuffer *ring, u32 counter, ··· 117 110 u32 asid; 118 111 u64 memptr = rbmemptr(ring, ttbr0); 119 112 120 - if (ctx->seqno == a6xx_gpu->base.base.cur_ctx_seqno) 113 + if (ctx->seqno == ring->cur_ctx_seqno) 121 114 return; 122 115 123 116 if (msm_iommu_pagetable_params(ctx->aspace->mmu, &ttbr, &asid)) ··· 155 148 156 149 /* 157 150 * Write the new TTBR0 to the memstore. This is good for debugging. 151 + * Needed for preemption 158 152 */ 159 - OUT_PKT7(ring, CP_MEM_WRITE, 4); 153 + OUT_PKT7(ring, CP_MEM_WRITE, 5); 160 154 OUT_RING(ring, CP_MEM_WRITE_0_ADDR_LO(lower_32_bits(memptr))); 161 155 OUT_RING(ring, CP_MEM_WRITE_1_ADDR_HI(upper_32_bits(memptr))); 162 156 OUT_RING(ring, lower_32_bits(ttbr)); 163 - OUT_RING(ring, (asid << 16) | upper_32_bits(ttbr)); 157 + OUT_RING(ring, upper_32_bits(ttbr)); 158 + OUT_RING(ring, ctx->seqno); 164 159 165 160 /* 166 161 * Sync both threads after switching pagetables and enable BR only ··· 238 229 case MSM_SUBMIT_CMD_IB_TARGET_BUF: 239 230 break; 240 231 case MSM_SUBMIT_CMD_CTX_RESTORE_BUF: 241 - if (gpu->cur_ctx_seqno == submit->queue->ctx->seqno) 232 + if (ring->cur_ctx_seqno == submit->queue->ctx->seqno) 242 233 break; 243 234 fallthrough; 244 235 case MSM_SUBMIT_CMD_BUF: ··· 287 278 a6xx_flush(gpu, ring); 288 279 } 289 280 281 + static void a6xx_emit_set_pseudo_reg(struct msm_ringbuffer *ring, 282 + struct a6xx_gpu *a6xx_gpu, struct msm_gpu_submitqueue *queue) 283 + { 284 + u64 preempt_postamble; 285 + 286 + OUT_PKT7(ring, CP_SET_PSEUDO_REG, 12); 287 + 288 + OUT_RING(ring, SMMU_INFO); 289 + /* don't save SMMU, we write the record from the kernel instead */ 290 + OUT_RING(ring, 0); 291 + OUT_RING(ring, 0); 292 + 293 + /* privileged and non secure buffer save */ 294 + OUT_RING(ring, NON_SECURE_SAVE_ADDR); 295 + OUT_RING(ring, lower_32_bits( 296 + a6xx_gpu->preempt_iova[ring->id])); 297 + OUT_RING(ring, upper_32_bits( 298 + a6xx_gpu->preempt_iova[ring->id])); 299 + 300 + /* user context buffer save, seems to be unnused by fw */ 301 + OUT_RING(ring, NON_PRIV_SAVE_ADDR); 302 + OUT_RING(ring, 0); 303 + OUT_RING(ring, 0); 304 + 305 + OUT_RING(ring, COUNTER); 306 + /* seems OK to set to 0 to disable it */ 307 + OUT_RING(ring, 0); 308 + OUT_RING(ring, 0); 309 + 310 + /* Emit postamble to clear perfcounters */ 311 + preempt_postamble = a6xx_gpu->preempt_postamble_iova; 312 + 313 + OUT_PKT7(ring, CP_SET_AMBLE, 3); 314 + OUT_RING(ring, lower_32_bits(preempt_postamble)); 315 + OUT_RING(ring, upper_32_bits(preempt_postamble)); 316 + OUT_RING(ring, CP_SET_AMBLE_2_DWORDS( 317 + a6xx_gpu->preempt_postamble_len) | 318 + CP_SET_AMBLE_2_TYPE(KMD_AMBLE_TYPE)); 319 + } 320 + 290 321 static void a7xx_submit(struct msm_gpu *gpu, struct msm_gem_submit *submit) 291 322 { 292 323 unsigned int index = submit->seqno % MSM_GPU_SUBMIT_STATS_COUNT; ··· 344 295 345 296 a6xx_set_pagetable(a6xx_gpu, ring, submit); 346 297 298 + /* 299 + * If preemption is enabled, then set the pseudo register for the save 300 + * sequence 301 + */ 302 + if (gpu->nr_rings > 1) 303 + a6xx_emit_set_pseudo_reg(ring, a6xx_gpu, submit->queue); 304 + 347 305 get_stats_counter(ring, REG_A7XX_RBBM_PERFCTR_CP(0), 348 306 rbmemptr_stats(ring, index, cpcycles_start)); 349 307 get_stats_counter(ring, REG_A6XX_CP_ALWAYS_ON_COUNTER, ··· 362 306 OUT_PKT7(ring, CP_SET_MARKER, 1); 363 307 OUT_RING(ring, 0x101); /* IFPC disable */ 364 308 365 - OUT_PKT7(ring, CP_SET_MARKER, 1); 366 - OUT_RING(ring, 0x00d); /* IB1LIST start */ 309 + if (submit->queue->flags & MSM_SUBMITQUEUE_ALLOW_PREEMPT) { 310 + OUT_PKT7(ring, CP_SET_MARKER, 1); 311 + OUT_RING(ring, 0x00d); /* IB1LIST start */ 312 + } 367 313 368 314 /* Submit the commands */ 369 315 for (i = 0; i < submit->nr_cmds; i++) { ··· 373 315 case MSM_SUBMIT_CMD_IB_TARGET_BUF: 374 316 break; 375 317 case MSM_SUBMIT_CMD_CTX_RESTORE_BUF: 376 - if (gpu->cur_ctx_seqno == submit->queue->ctx->seqno) 318 + if (ring->cur_ctx_seqno == submit->queue->ctx->seqno) 377 319 break; 378 320 fallthrough; 379 321 case MSM_SUBMIT_CMD_BUF: ··· 396 338 update_shadow_rptr(gpu, ring); 397 339 } 398 340 399 - OUT_PKT7(ring, CP_SET_MARKER, 1); 400 - OUT_RING(ring, 0x00e); /* IB1LIST end */ 341 + if (submit->queue->flags & MSM_SUBMITQUEUE_ALLOW_PREEMPT) { 342 + OUT_PKT7(ring, CP_SET_MARKER, 1); 343 + OUT_RING(ring, 0x00e); /* IB1LIST end */ 344 + } 401 345 402 346 get_stats_counter(ring, REG_A7XX_RBBM_PERFCTR_CP(0), 403 347 rbmemptr_stats(ring, index, cpcycles_end)); ··· 446 386 OUT_RING(ring, upper_32_bits(rbmemptr(ring, bv_fence))); 447 387 OUT_RING(ring, submit->seqno); 448 388 389 + a6xx_gpu->last_seqno[ring->id] = submit->seqno; 390 + 449 391 /* write the ringbuffer timestamp */ 450 392 OUT_PKT7(ring, CP_EVENT_WRITE, 4); 451 393 OUT_RING(ring, CACHE_CLEAN | CP_EVENT_WRITE_0_IRQ | BIT(27)); ··· 461 399 OUT_PKT7(ring, CP_SET_MARKER, 1); 462 400 OUT_RING(ring, 0x100); /* IFPC enable */ 463 401 402 + /* If preemption is enabled */ 403 + if (gpu->nr_rings > 1) { 404 + /* Yield the floor on command completion */ 405 + OUT_PKT7(ring, CP_CONTEXT_SWITCH_YIELD, 4); 406 + 407 + /* 408 + * If dword[2:1] are non zero, they specify an address for 409 + * the CP to write the value of dword[3] to on preemption 410 + * complete. Write 0 to skip the write 411 + */ 412 + OUT_RING(ring, 0x00); 413 + OUT_RING(ring, 0x00); 414 + /* Data value - not used if the address above is 0 */ 415 + OUT_RING(ring, 0x01); 416 + /* generate interrupt on preemption completion */ 417 + OUT_RING(ring, 0x00); 418 + } 419 + 420 + 464 421 trace_msm_gpu_submit_flush(submit, 465 422 gpu_read64(gpu, REG_A6XX_CP_ALWAYS_ON_COUNTER)); 466 423 467 424 a6xx_flush(gpu, ring); 425 + 426 + /* Check to see if we need to start preemption */ 427 + a6xx_preempt_trigger(gpu); 468 428 } 469 429 470 430 static void a6xx_set_hwcg(struct msm_gpu *gpu, bool state) ··· 635 551 gpu->ubwc_config.macrotile_mode = 1; 636 552 } 637 553 554 + if (adreno_is_a663(gpu)) { 555 + gpu->ubwc_config.highest_bank_bit = 13; 556 + gpu->ubwc_config.amsbc = 1; 557 + gpu->ubwc_config.rgb565_predicator = 1; 558 + gpu->ubwc_config.uavflagprd_inv = 2; 559 + gpu->ubwc_config.macrotile_mode = 1; 560 + gpu->ubwc_config.ubwc_swizzle = 0x4; 561 + } 562 + 638 563 if (adreno_is_7c3(gpu)) { 639 564 gpu->ubwc_config.highest_bank_bit = 14; 640 565 gpu->ubwc_config.amsbc = 1; ··· 702 609 adreno_gpu->ubwc_config.macrotile_mode); 703 610 } 704 611 612 + static void a7xx_patch_pwrup_reglist(struct msm_gpu *gpu) 613 + { 614 + struct adreno_gpu *adreno_gpu = to_adreno_gpu(gpu); 615 + struct a6xx_gpu *a6xx_gpu = to_a6xx_gpu(adreno_gpu); 616 + const struct adreno_reglist_list *reglist; 617 + void *ptr = a6xx_gpu->pwrup_reglist_ptr; 618 + struct cpu_gpu_lock *lock = ptr; 619 + u32 *dest = (u32 *)&lock->regs[0]; 620 + int i; 621 + 622 + reglist = adreno_gpu->info->a6xx->pwrup_reglist; 623 + 624 + lock->gpu_req = lock->cpu_req = lock->turn = 0; 625 + lock->ifpc_list_len = 0; 626 + lock->preemption_list_len = reglist->count; 627 + 628 + /* 629 + * For each entry in each of the lists, write the offset and the current 630 + * register value into the GPU buffer 631 + */ 632 + for (i = 0; i < reglist->count; i++) { 633 + *dest++ = reglist->regs[i]; 634 + *dest++ = gpu_read(gpu, reglist->regs[i]); 635 + } 636 + 637 + /* 638 + * The overall register list is composed of 639 + * 1. Static IFPC-only registers 640 + * 2. Static IFPC + preemption registers 641 + * 3. Dynamic IFPC + preemption registers (ex: perfcounter selects) 642 + * 643 + * The first two lists are static. Size of these lists are stored as 644 + * number of pairs in ifpc_list_len and preemption_list_len 645 + * respectively. With concurrent binning, Some of the perfcounter 646 + * registers being virtualized, CP needs to know the pipe id to program 647 + * the aperture inorder to restore the same. Thus, third list is a 648 + * dynamic list with triplets as 649 + * (<aperture, shifted 12 bits> <address> <data>), and the length is 650 + * stored as number for triplets in dynamic_list_len. 651 + */ 652 + lock->dynamic_list_len = 0; 653 + } 654 + 655 + static int a7xx_preempt_start(struct msm_gpu *gpu) 656 + { 657 + struct adreno_gpu *adreno_gpu = to_adreno_gpu(gpu); 658 + struct a6xx_gpu *a6xx_gpu = to_a6xx_gpu(adreno_gpu); 659 + struct msm_ringbuffer *ring = gpu->rb[0]; 660 + 661 + if (gpu->nr_rings <= 1) 662 + return 0; 663 + 664 + /* Turn CP protection off */ 665 + OUT_PKT7(ring, CP_SET_PROTECTED_MODE, 1); 666 + OUT_RING(ring, 0); 667 + 668 + a6xx_emit_set_pseudo_reg(ring, a6xx_gpu, NULL); 669 + 670 + /* Yield the floor on command completion */ 671 + OUT_PKT7(ring, CP_CONTEXT_SWITCH_YIELD, 4); 672 + OUT_RING(ring, 0x00); 673 + OUT_RING(ring, 0x00); 674 + OUT_RING(ring, 0x00); 675 + /* Generate interrupt on preemption completion */ 676 + OUT_RING(ring, 0x00); 677 + 678 + a6xx_flush(gpu, ring); 679 + 680 + return a6xx_idle(gpu, ring) ? 0 : -EINVAL; 681 + } 682 + 705 683 static int a6xx_cp_init(struct msm_gpu *gpu) 706 684 { 707 685 struct msm_ringbuffer *ring = gpu->rb[0]; ··· 804 640 805 641 static int a7xx_cp_init(struct msm_gpu *gpu) 806 642 { 643 + struct adreno_gpu *adreno_gpu = to_adreno_gpu(gpu); 644 + struct a6xx_gpu *a6xx_gpu = to_a6xx_gpu(adreno_gpu); 807 645 struct msm_ringbuffer *ring = gpu->rb[0]; 808 646 u32 mask; 809 647 ··· 843 677 844 678 /* *Don't* send a power up reg list for concurrent binning (TODO) */ 845 679 /* Lo address */ 846 - OUT_RING(ring, 0x00000000); 680 + OUT_RING(ring, lower_32_bits(a6xx_gpu->pwrup_reglist_iova)); 847 681 /* Hi address */ 848 - OUT_RING(ring, 0x00000000); 682 + OUT_RING(ring, upper_32_bits(a6xx_gpu->pwrup_reglist_iova)); 849 683 /* BIT(31) set => read the regs from the list */ 850 - OUT_RING(ring, 0x00000000); 684 + OUT_RING(ring, BIT(31)); 851 685 852 686 a6xx_flush(gpu, ring); 853 687 return a6xx_idle(gpu, ring) ? 0 : -EINVAL; ··· 971 805 msm_gem_object_set_name(a6xx_gpu->shadow_bo, "shadow"); 972 806 } 973 807 808 + a6xx_gpu->pwrup_reglist_ptr = msm_gem_kernel_new(gpu->dev, PAGE_SIZE, 809 + MSM_BO_WC | MSM_BO_MAP_PRIV, 810 + gpu->aspace, &a6xx_gpu->pwrup_reglist_bo, 811 + &a6xx_gpu->pwrup_reglist_iova); 812 + 813 + if (IS_ERR(a6xx_gpu->pwrup_reglist_ptr)) 814 + return PTR_ERR(a6xx_gpu->pwrup_reglist_ptr); 815 + 816 + msm_gem_object_set_name(a6xx_gpu->pwrup_reglist_bo, "pwrup_reglist"); 817 + 974 818 return 0; 975 819 } 976 820 ··· 1040 864 struct a6xx_gpu *a6xx_gpu = to_a6xx_gpu(adreno_gpu); 1041 865 struct a6xx_gmu *gmu = &a6xx_gpu->gmu; 1042 866 u64 gmem_range_min; 867 + unsigned int i; 1043 868 int ret; 1044 869 1045 870 if (!adreno_has_gmu_wrapper(adreno_gpu)) { ··· 1249 1072 if (adreno_is_a690(adreno_gpu)) 1250 1073 gpu_write(gpu, REG_A6XX_UCHE_CMDQ_CONFIG, 0x90); 1251 1074 /* Set dualQ + disable afull for A660 GPU */ 1252 - else if (adreno_is_a660(adreno_gpu)) 1075 + else if (adreno_is_a660(adreno_gpu) || adreno_is_a663(adreno_gpu)) 1253 1076 gpu_write(gpu, REG_A6XX_UCHE_CMDQ_CONFIG, 0x66906); 1254 1077 else if (adreno_is_a7xx(adreno_gpu)) 1255 1078 gpu_write(gpu, REG_A6XX_UCHE_CMDQ_CONFIG, ··· 1311 1134 if (a6xx_gpu->shadow_bo) { 1312 1135 gpu_write64(gpu, REG_A6XX_CP_RB_RPTR_ADDR, 1313 1136 shadowptr(a6xx_gpu, gpu->rb[0])); 1137 + for (unsigned int i = 0; i < gpu->nr_rings; i++) 1138 + a6xx_gpu->shadow[i] = 0; 1314 1139 } 1315 1140 1316 1141 /* ..which means "always" on A7xx, also for BV shadow */ 1317 1142 if (adreno_is_a7xx(adreno_gpu)) { 1318 1143 gpu_write64(gpu, REG_A7XX_CP_BV_RB_RPTR_ADDR, 1319 - rbmemptr(gpu->rb[0], bv_fence)); 1144 + rbmemptr(gpu->rb[0], bv_rptr)); 1320 1145 } 1146 + 1147 + a6xx_preempt_hw_init(gpu); 1321 1148 1322 1149 /* Always come up on rb 0 */ 1323 1150 a6xx_gpu->cur_ring = gpu->rb[0]; 1324 1151 1325 - gpu->cur_ctx_seqno = 0; 1152 + for (i = 0; i < gpu->nr_rings; i++) 1153 + gpu->rb[i]->cur_ctx_seqno = 0; 1326 1154 1327 1155 /* Enable the SQE_to start the CP engine */ 1328 1156 gpu_write(gpu, REG_A6XX_CP_SQE_CNTL, 1); 1157 + 1158 + if (adreno_is_a7xx(adreno_gpu) && !a6xx_gpu->pwrup_reglist_emitted) { 1159 + a7xx_patch_pwrup_reglist(gpu); 1160 + a6xx_gpu->pwrup_reglist_emitted = true; 1161 + } 1329 1162 1330 1163 ret = adreno_is_a7xx(adreno_gpu) ? a7xx_cp_init(gpu) : a6xx_cp_init(gpu); 1331 1164 if (ret) ··· 1374 1187 out: 1375 1188 if (adreno_has_gmu_wrapper(adreno_gpu)) 1376 1189 return ret; 1190 + 1191 + /* Last step - yield the ringbuffer */ 1192 + a7xx_preempt_start(gpu); 1193 + 1377 1194 /* 1378 1195 * Tell the GMU that we are done touching the GPU and it can start power 1379 1196 * management ··· 1755 1564 if (status & A6XX_RBBM_INT_0_MASK_SWFUSEVIOLATION) 1756 1565 a7xx_sw_fuse_violation_irq(gpu); 1757 1566 1758 - if (status & A6XX_RBBM_INT_0_MASK_CP_CACHE_FLUSH_TS) 1567 + if (status & A6XX_RBBM_INT_0_MASK_CP_CACHE_FLUSH_TS) { 1759 1568 msm_gpu_retire(gpu); 1569 + a6xx_preempt_trigger(gpu); 1570 + } 1571 + 1572 + if (status & A6XX_RBBM_INT_0_MASK_CP_SW) 1573 + a6xx_preempt_irq(gpu); 1760 1574 1761 1575 return IRQ_HANDLED; 1762 1576 } ··· 2455 2259 struct a6xx_gpu *a6xx_gpu; 2456 2260 struct adreno_gpu *adreno_gpu; 2457 2261 struct msm_gpu *gpu; 2262 + extern int enable_preemption; 2458 2263 bool is_a7xx; 2459 2264 int ret; 2460 2265 ··· 2494 2297 return ERR_PTR(ret); 2495 2298 } 2496 2299 2497 - if (is_a7xx) 2300 + if ((enable_preemption == 1) || (enable_preemption == -1 && 2301 + (config->info->quirks & ADRENO_QUIRK_PREEMPTION))) 2302 + ret = adreno_gpu_init(dev, pdev, adreno_gpu, &funcs_a7xx, 4); 2303 + else if (is_a7xx) 2498 2304 ret = adreno_gpu_init(dev, pdev, adreno_gpu, &funcs_a7xx, 1); 2499 2305 else if (adreno_has_gmu_wrapper(adreno_gpu)) 2500 2306 ret = adreno_gpu_init(dev, pdev, adreno_gpu, &funcs_gmuwrapper, 1); ··· 2538 2338 a6xx_fault_handler); 2539 2339 2540 2340 a6xx_calc_ubwc_config(adreno_gpu); 2341 + /* Set up the preemption specific bits and pieces for each ringbuffer */ 2342 + a6xx_preempt_init(gpu); 2541 2343 2542 2344 return gpu; 2543 2345 }
+170
drivers/gpu/drm/msm/adreno/a6xx_gpu.h
··· 12 12 13 13 extern bool hang_debug; 14 14 15 + struct cpu_gpu_lock { 16 + uint32_t gpu_req; 17 + uint32_t cpu_req; 18 + uint32_t turn; 19 + union { 20 + struct { 21 + uint16_t list_length; 22 + uint16_t list_offset; 23 + }; 24 + struct { 25 + uint8_t ifpc_list_len; 26 + uint8_t preemption_list_len; 27 + uint16_t dynamic_list_len; 28 + }; 29 + }; 30 + uint64_t regs[62]; 31 + }; 32 + 15 33 /** 16 34 * struct a6xx_info - a6xx specific information from device table 17 35 * 18 36 * @hwcg: hw clock gating register sequence 19 37 * @protect: CP_PROTECT settings 38 + * @pwrup_reglist pwrup reglist for preemption 20 39 */ 21 40 struct a6xx_info { 22 41 const struct adreno_reglist *hwcg; 23 42 const struct adreno_protect *protect; 43 + const struct adreno_reglist_list *pwrup_reglist; 24 44 u32 gmu_chipid; 25 45 u32 gmu_cgc_mode; 26 46 u32 prim_fifo_threshold; ··· 53 33 uint64_t sqe_iova; 54 34 55 35 struct msm_ringbuffer *cur_ring; 36 + struct msm_ringbuffer *next_ring; 37 + 38 + struct drm_gem_object *preempt_bo[MSM_GPU_MAX_RINGS]; 39 + void *preempt[MSM_GPU_MAX_RINGS]; 40 + uint64_t preempt_iova[MSM_GPU_MAX_RINGS]; 41 + struct drm_gem_object *preempt_smmu_bo[MSM_GPU_MAX_RINGS]; 42 + void *preempt_smmu[MSM_GPU_MAX_RINGS]; 43 + uint64_t preempt_smmu_iova[MSM_GPU_MAX_RINGS]; 44 + uint32_t last_seqno[MSM_GPU_MAX_RINGS]; 45 + 46 + atomic_t preempt_state; 47 + spinlock_t eval_lock; 48 + struct timer_list preempt_timer; 49 + 50 + unsigned int preempt_level; 51 + bool uses_gmem; 52 + bool skip_save_restore; 53 + 54 + struct drm_gem_object *preempt_postamble_bo; 55 + void *preempt_postamble_ptr; 56 + uint64_t preempt_postamble_iova; 57 + uint64_t preempt_postamble_len; 58 + bool postamble_enabled; 56 59 57 60 struct a6xx_gmu gmu; 58 61 59 62 struct drm_gem_object *shadow_bo; 60 63 uint64_t shadow_iova; 61 64 uint32_t *shadow; 65 + 66 + struct drm_gem_object *pwrup_reglist_bo; 67 + void *pwrup_reglist_ptr; 68 + uint64_t pwrup_reglist_iova; 69 + bool pwrup_reglist_emitted; 62 70 63 71 bool has_whereami; 64 72 ··· 98 50 }; 99 51 100 52 #define to_a6xx_gpu(x) container_of(x, struct a6xx_gpu, base) 53 + 54 + /* 55 + * In order to do lockless preemption we use a simple state machine to progress 56 + * through the process. 57 + * 58 + * PREEMPT_NONE - no preemption in progress. Next state START. 59 + * PREEMPT_START - The trigger is evaluating if preemption is possible. Next 60 + * states: TRIGGERED, NONE 61 + * PREEMPT_FINISH - An intermediate state before moving back to NONE. Next 62 + * state: NONE. 63 + * PREEMPT_TRIGGERED: A preemption has been executed on the hardware. Next 64 + * states: FAULTED, PENDING 65 + * PREEMPT_FAULTED: A preemption timed out (never completed). This will trigger 66 + * recovery. Next state: N/A 67 + * PREEMPT_PENDING: Preemption complete interrupt fired - the callback is 68 + * checking the success of the operation. Next state: FAULTED, NONE. 69 + */ 70 + 71 + enum a6xx_preempt_state { 72 + PREEMPT_NONE = 0, 73 + PREEMPT_START, 74 + PREEMPT_FINISH, 75 + PREEMPT_TRIGGERED, 76 + PREEMPT_FAULTED, 77 + PREEMPT_PENDING, 78 + }; 79 + 80 + /* 81 + * struct a6xx_preempt_record is a shared buffer between the microcode and the 82 + * CPU to store the state for preemption. The record itself is much larger 83 + * (2112k) but most of that is used by the CP for storage. 84 + * 85 + * There is a preemption record assigned per ringbuffer. When the CPU triggers a 86 + * preemption, it fills out the record with the useful information (wptr, ring 87 + * base, etc) and the microcode uses that information to set up the CP following 88 + * the preemption. When a ring is switched out, the CP will save the ringbuffer 89 + * state back to the record. In this way, once the records are properly set up 90 + * the CPU can quickly switch back and forth between ringbuffers by only 91 + * updating a few registers (often only the wptr). 92 + * 93 + * These are the CPU aware registers in the record: 94 + * @magic: Must always be 0xAE399D6EUL 95 + * @info: Type of the record - written 0 by the CPU, updated by the CP 96 + * @errno: preemption error record 97 + * @data: Data field in YIELD and SET_MARKER packets, Written and used by CP 98 + * @cntl: Value of RB_CNTL written by CPU, save/restored by CP 99 + * @rptr: Value of RB_RPTR written by CPU, save/restored by CP 100 + * @wptr: Value of RB_WPTR written by CPU, save/restored by CP 101 + * @_pad: Reserved/padding 102 + * @rptr_addr: Value of RB_RPTR_ADDR_LO|HI written by CPU, save/restored by CP 103 + * @rbase: Value of RB_BASE written by CPU, save/restored by CP 104 + * @counter: GPU address of the storage area for the preemption counters 105 + * @bv_rptr_addr: Value of BV_RB_RPTR_ADDR_LO|HI written by CPU, save/restored by CP 106 + */ 107 + struct a6xx_preempt_record { 108 + u32 magic; 109 + u32 info; 110 + u32 errno; 111 + u32 data; 112 + u32 cntl; 113 + u32 rptr; 114 + u32 wptr; 115 + u32 _pad; 116 + u64 rptr_addr; 117 + u64 rbase; 118 + u64 counter; 119 + u64 bv_rptr_addr; 120 + }; 121 + 122 + #define A6XX_PREEMPT_RECORD_MAGIC 0xAE399D6EUL 123 + 124 + #define PREEMPT_SMMU_INFO_SIZE 4096 125 + 126 + #define PREEMPT_RECORD_SIZE(adreno_gpu) \ 127 + ((adreno_gpu->info->preempt_record_size) == 0 ? \ 128 + 4192 * SZ_1K : (adreno_gpu->info->preempt_record_size)) 129 + 130 + /* 131 + * The preemption counter block is a storage area for the value of the 132 + * preemption counters that are saved immediately before context switch. We 133 + * append it on to the end of the allocation for the preemption record. 134 + */ 135 + #define A6XX_PREEMPT_COUNTER_SIZE (16 * 4) 136 + 137 + struct a7xx_cp_smmu_info { 138 + u32 magic; 139 + u32 _pad4; 140 + u64 ttbr0; 141 + u32 asid; 142 + u32 context_idr; 143 + u32 context_bank; 144 + }; 145 + 146 + #define GEN7_CP_SMMU_INFO_MAGIC 0x241350d5UL 101 147 102 148 /* 103 149 * Given a register and a count, return a value to program into ··· 249 107 int a6xx_gmu_init(struct a6xx_gpu *a6xx_gpu, struct device_node *node); 250 108 int a6xx_gmu_wrapper_init(struct a6xx_gpu *a6xx_gpu, struct device_node *node); 251 109 void a6xx_gmu_remove(struct a6xx_gpu *a6xx_gpu); 110 + 111 + void a6xx_preempt_init(struct msm_gpu *gpu); 112 + void a6xx_preempt_hw_init(struct msm_gpu *gpu); 113 + void a6xx_preempt_trigger(struct msm_gpu *gpu); 114 + void a6xx_preempt_irq(struct msm_gpu *gpu); 115 + void a6xx_preempt_fini(struct msm_gpu *gpu); 116 + int a6xx_preempt_submitqueue_setup(struct msm_gpu *gpu, 117 + struct msm_gpu_submitqueue *queue); 118 + void a6xx_preempt_submitqueue_close(struct msm_gpu *gpu, 119 + struct msm_gpu_submitqueue *queue); 120 + 121 + /* Return true if we are in a preempt state */ 122 + static inline bool a6xx_in_preempt(struct a6xx_gpu *a6xx_gpu) 123 + { 124 + /* 125 + * Make sure the read to preempt_state is ordered with respect to reads 126 + * of other variables before ... 127 + */ 128 + smp_rmb(); 129 + 130 + int preempt_state = atomic_read(&a6xx_gpu->preempt_state); 131 + 132 + /* ... and after. */ 133 + smp_rmb(); 134 + 135 + return !(preempt_state == PREEMPT_NONE || 136 + preempt_state == PREEMPT_FINISH); 137 + } 252 138 253 139 void a6xx_gmu_set_freq(struct msm_gpu *gpu, struct dev_pm_opp *opp, 254 140 bool suspended);
+65 -22
drivers/gpu/drm/msm/adreno/a6xx_hfi.c
··· 478 478 msg->cnoc_cmds_data[1][0] = 0x60000001; 479 479 } 480 480 481 + static void a663_build_bw_table(struct a6xx_hfi_msg_bw_table *msg) 482 + { 483 + /* 484 + * Send a single "off" entry just to get things running 485 + * TODO: bus scaling 486 + */ 487 + msg->bw_level_num = 1; 488 + 489 + msg->ddr_cmds_num = 3; 490 + msg->ddr_wait_bitmask = 0x07; 491 + 492 + msg->ddr_cmds_addrs[0] = 0x50004; 493 + msg->ddr_cmds_addrs[1] = 0x50000; 494 + msg->ddr_cmds_addrs[2] = 0x500b4; 495 + 496 + msg->ddr_cmds_data[0][0] = 0x40000000; 497 + msg->ddr_cmds_data[0][1] = 0x40000000; 498 + msg->ddr_cmds_data[0][2] = 0x40000000; 499 + 500 + /* 501 + * These are the CX (CNOC) votes - these are used by the GMU but the 502 + * votes are known and fixed for the target 503 + */ 504 + msg->cnoc_cmds_num = 1; 505 + msg->cnoc_wait_bitmask = 0x01; 506 + 507 + msg->cnoc_cmds_addrs[0] = 0x50058; 508 + msg->cnoc_cmds_data[0][0] = 0x40000000; 509 + msg->cnoc_cmds_data[1][0] = 0x60000001; 510 + } 511 + 481 512 static void adreno_7c3_build_bw_table(struct a6xx_hfi_msg_bw_table *msg) 482 513 { 483 514 /* ··· 661 630 662 631 static int a6xx_hfi_send_bw_table(struct a6xx_gmu *gmu) 663 632 { 664 - struct a6xx_hfi_msg_bw_table msg = { 0 }; 633 + struct a6xx_hfi_msg_bw_table *msg; 665 634 struct a6xx_gpu *a6xx_gpu = container_of(gmu, struct a6xx_gpu, gmu); 666 635 struct adreno_gpu *adreno_gpu = &a6xx_gpu->base; 667 636 668 - if (adreno_is_a618(adreno_gpu)) 669 - a618_build_bw_table(&msg); 670 - else if (adreno_is_a619(adreno_gpu)) 671 - a619_build_bw_table(&msg); 672 - else if (adreno_is_a640_family(adreno_gpu)) 673 - a640_build_bw_table(&msg); 674 - else if (adreno_is_a650(adreno_gpu)) 675 - a650_build_bw_table(&msg); 676 - else if (adreno_is_7c3(adreno_gpu)) 677 - adreno_7c3_build_bw_table(&msg); 678 - else if (adreno_is_a660(adreno_gpu)) 679 - a660_build_bw_table(&msg); 680 - else if (adreno_is_a690(adreno_gpu)) 681 - a690_build_bw_table(&msg); 682 - else if (adreno_is_a730(adreno_gpu)) 683 - a730_build_bw_table(&msg); 684 - else if (adreno_is_a740_family(adreno_gpu)) 685 - a740_build_bw_table(&msg); 686 - else 687 - a6xx_build_bw_table(&msg); 637 + if (gmu->bw_table) 638 + goto send; 688 639 689 - return a6xx_hfi_send_msg(gmu, HFI_H2F_MSG_BW_TABLE, &msg, sizeof(msg), 640 + msg = devm_kzalloc(gmu->dev, sizeof(*msg), GFP_KERNEL); 641 + if (!msg) 642 + return -ENOMEM; 643 + 644 + if (adreno_is_a618(adreno_gpu)) 645 + a618_build_bw_table(msg); 646 + else if (adreno_is_a619(adreno_gpu)) 647 + a619_build_bw_table(msg); 648 + else if (adreno_is_a640_family(adreno_gpu)) 649 + a640_build_bw_table(msg); 650 + else if (adreno_is_a650(adreno_gpu)) 651 + a650_build_bw_table(msg); 652 + else if (adreno_is_7c3(adreno_gpu)) 653 + adreno_7c3_build_bw_table(msg); 654 + else if (adreno_is_a660(adreno_gpu)) 655 + a660_build_bw_table(msg); 656 + else if (adreno_is_a663(adreno_gpu)) 657 + a663_build_bw_table(msg); 658 + else if (adreno_is_a690(adreno_gpu)) 659 + a690_build_bw_table(msg); 660 + else if (adreno_is_a730(adreno_gpu)) 661 + a730_build_bw_table(msg); 662 + else if (adreno_is_a740_family(adreno_gpu)) 663 + a740_build_bw_table(msg); 664 + else 665 + a6xx_build_bw_table(msg); 666 + 667 + gmu->bw_table = msg; 668 + 669 + send: 670 + return a6xx_hfi_send_msg(gmu, HFI_H2F_MSG_BW_TABLE, gmu->bw_table, sizeof(*(gmu->bw_table)), 690 671 NULL, 0); 691 672 } 692 673
+456
drivers/gpu/drm/msm/adreno/a6xx_preempt.c
··· 1 + // SPDX-License-Identifier: GPL-2.0 2 + /* Copyright (c) 2018, The Linux Foundation. All rights reserved. */ 3 + /* Copyright (c) 2023 Collabora, Ltd. */ 4 + /* Copyright (c) 2024 Valve Corporation */ 5 + 6 + #include "msm_gem.h" 7 + #include "a6xx_gpu.h" 8 + #include "a6xx_gmu.xml.h" 9 + #include "msm_mmu.h" 10 + #include "msm_gpu_trace.h" 11 + 12 + /* 13 + * Try to transition the preemption state from old to new. Return 14 + * true on success or false if the original state wasn't 'old' 15 + */ 16 + static inline bool try_preempt_state(struct a6xx_gpu *a6xx_gpu, 17 + enum a6xx_preempt_state old, enum a6xx_preempt_state new) 18 + { 19 + enum a6xx_preempt_state cur = atomic_cmpxchg(&a6xx_gpu->preempt_state, 20 + old, new); 21 + 22 + return (cur == old); 23 + } 24 + 25 + /* 26 + * Force the preemption state to the specified state. This is used in cases 27 + * where the current state is known and won't change 28 + */ 29 + static inline void set_preempt_state(struct a6xx_gpu *gpu, 30 + enum a6xx_preempt_state new) 31 + { 32 + /* 33 + * preempt_state may be read by other cores trying to trigger a 34 + * preemption or in the interrupt handler so barriers are needed 35 + * before... 36 + */ 37 + smp_mb__before_atomic(); 38 + atomic_set(&gpu->preempt_state, new); 39 + /* ... and after*/ 40 + smp_mb__after_atomic(); 41 + } 42 + 43 + /* Write the most recent wptr for the given ring into the hardware */ 44 + static inline void update_wptr(struct msm_gpu *gpu, struct msm_ringbuffer *ring) 45 + { 46 + unsigned long flags; 47 + uint32_t wptr; 48 + 49 + spin_lock_irqsave(&ring->preempt_lock, flags); 50 + 51 + if (ring->restore_wptr) { 52 + wptr = get_wptr(ring); 53 + 54 + gpu_write(gpu, REG_A6XX_CP_RB_WPTR, wptr); 55 + 56 + ring->restore_wptr = false; 57 + } 58 + 59 + spin_unlock_irqrestore(&ring->preempt_lock, flags); 60 + } 61 + 62 + /* Return the highest priority ringbuffer with something in it */ 63 + static struct msm_ringbuffer *get_next_ring(struct msm_gpu *gpu) 64 + { 65 + struct adreno_gpu *adreno_gpu = to_adreno_gpu(gpu); 66 + struct a6xx_gpu *a6xx_gpu = to_a6xx_gpu(adreno_gpu); 67 + 68 + unsigned long flags; 69 + int i; 70 + 71 + for (i = 0; i < gpu->nr_rings; i++) { 72 + bool empty; 73 + struct msm_ringbuffer *ring = gpu->rb[i]; 74 + 75 + spin_lock_irqsave(&ring->preempt_lock, flags); 76 + empty = (get_wptr(ring) == gpu->funcs->get_rptr(gpu, ring)); 77 + if (!empty && ring == a6xx_gpu->cur_ring) 78 + empty = ring->memptrs->fence == a6xx_gpu->last_seqno[i]; 79 + spin_unlock_irqrestore(&ring->preempt_lock, flags); 80 + 81 + if (!empty) 82 + return ring; 83 + } 84 + 85 + return NULL; 86 + } 87 + 88 + static void a6xx_preempt_timer(struct timer_list *t) 89 + { 90 + struct a6xx_gpu *a6xx_gpu = from_timer(a6xx_gpu, t, preempt_timer); 91 + struct msm_gpu *gpu = &a6xx_gpu->base.base; 92 + struct drm_device *dev = gpu->dev; 93 + 94 + if (!try_preempt_state(a6xx_gpu, PREEMPT_TRIGGERED, PREEMPT_FAULTED)) 95 + return; 96 + 97 + dev_err(dev->dev, "%s: preemption timed out\n", gpu->name); 98 + kthread_queue_work(gpu->worker, &gpu->recover_work); 99 + } 100 + 101 + static void preempt_prepare_postamble(struct a6xx_gpu *a6xx_gpu) 102 + { 103 + u32 *postamble = a6xx_gpu->preempt_postamble_ptr; 104 + u32 count = 0; 105 + 106 + postamble[count++] = PKT7(CP_REG_RMW, 3); 107 + postamble[count++] = REG_A6XX_RBBM_PERFCTR_SRAM_INIT_CMD; 108 + postamble[count++] = 0; 109 + postamble[count++] = 1; 110 + 111 + postamble[count++] = PKT7(CP_WAIT_REG_MEM, 6); 112 + postamble[count++] = CP_WAIT_REG_MEM_0_FUNCTION(WRITE_EQ); 113 + postamble[count++] = CP_WAIT_REG_MEM_1_POLL_ADDR_LO( 114 + REG_A6XX_RBBM_PERFCTR_SRAM_INIT_STATUS); 115 + postamble[count++] = CP_WAIT_REG_MEM_2_POLL_ADDR_HI(0); 116 + postamble[count++] = CP_WAIT_REG_MEM_3_REF(0x1); 117 + postamble[count++] = CP_WAIT_REG_MEM_4_MASK(0x1); 118 + postamble[count++] = CP_WAIT_REG_MEM_5_DELAY_LOOP_CYCLES(0); 119 + 120 + a6xx_gpu->preempt_postamble_len = count; 121 + 122 + a6xx_gpu->postamble_enabled = true; 123 + } 124 + 125 + static void preempt_disable_postamble(struct a6xx_gpu *a6xx_gpu) 126 + { 127 + u32 *postamble = a6xx_gpu->preempt_postamble_ptr; 128 + 129 + /* 130 + * Disable the postamble by replacing the first packet header with a NOP 131 + * that covers the whole buffer. 132 + */ 133 + *postamble = PKT7(CP_NOP, (a6xx_gpu->preempt_postamble_len - 1)); 134 + 135 + a6xx_gpu->postamble_enabled = false; 136 + } 137 + 138 + void a6xx_preempt_irq(struct msm_gpu *gpu) 139 + { 140 + uint32_t status; 141 + struct adreno_gpu *adreno_gpu = to_adreno_gpu(gpu); 142 + struct a6xx_gpu *a6xx_gpu = to_a6xx_gpu(adreno_gpu); 143 + struct drm_device *dev = gpu->dev; 144 + 145 + if (!try_preempt_state(a6xx_gpu, PREEMPT_TRIGGERED, PREEMPT_PENDING)) 146 + return; 147 + 148 + /* Delete the preemption watchdog timer */ 149 + del_timer(&a6xx_gpu->preempt_timer); 150 + 151 + /* 152 + * The hardware should be setting the stop bit of CP_CONTEXT_SWITCH_CNTL 153 + * to zero before firing the interrupt, but there is a non zero chance 154 + * of a hardware condition or a software race that could set it again 155 + * before we have a chance to finish. If that happens, log and go for 156 + * recovery 157 + */ 158 + status = gpu_read(gpu, REG_A6XX_CP_CONTEXT_SWITCH_CNTL); 159 + if (unlikely(status & A6XX_CP_CONTEXT_SWITCH_CNTL_STOP)) { 160 + DRM_DEV_ERROR(&gpu->pdev->dev, 161 + "!!!!!!!!!!!!!!!! preemption faulted !!!!!!!!!!!!!! irq\n"); 162 + set_preempt_state(a6xx_gpu, PREEMPT_FAULTED); 163 + dev_err(dev->dev, "%s: Preemption failed to complete\n", 164 + gpu->name); 165 + kthread_queue_work(gpu->worker, &gpu->recover_work); 166 + return; 167 + } 168 + 169 + a6xx_gpu->cur_ring = a6xx_gpu->next_ring; 170 + a6xx_gpu->next_ring = NULL; 171 + 172 + set_preempt_state(a6xx_gpu, PREEMPT_FINISH); 173 + 174 + update_wptr(gpu, a6xx_gpu->cur_ring); 175 + 176 + set_preempt_state(a6xx_gpu, PREEMPT_NONE); 177 + 178 + trace_msm_gpu_preemption_irq(a6xx_gpu->cur_ring->id); 179 + 180 + /* 181 + * Retrigger preemption to avoid a deadlock that might occur when preemption 182 + * is skipped due to it being already in flight when requested. 183 + */ 184 + a6xx_preempt_trigger(gpu); 185 + } 186 + 187 + void a6xx_preempt_hw_init(struct msm_gpu *gpu) 188 + { 189 + struct adreno_gpu *adreno_gpu = to_adreno_gpu(gpu); 190 + struct a6xx_gpu *a6xx_gpu = to_a6xx_gpu(adreno_gpu); 191 + int i; 192 + 193 + /* No preemption if we only have one ring */ 194 + if (gpu->nr_rings == 1) 195 + return; 196 + 197 + for (i = 0; i < gpu->nr_rings; i++) { 198 + struct a6xx_preempt_record *record_ptr = a6xx_gpu->preempt[i]; 199 + 200 + record_ptr->wptr = 0; 201 + record_ptr->rptr = 0; 202 + record_ptr->rptr_addr = shadowptr(a6xx_gpu, gpu->rb[i]); 203 + record_ptr->info = 0; 204 + record_ptr->data = 0; 205 + record_ptr->rbase = gpu->rb[i]->iova; 206 + } 207 + 208 + /* Write a 0 to signal that we aren't switching pagetables */ 209 + gpu_write64(gpu, REG_A6XX_CP_CONTEXT_SWITCH_SMMU_INFO, 0); 210 + 211 + /* Enable the GMEM save/restore feature for preemption */ 212 + gpu_write(gpu, REG_A6XX_RB_CONTEXT_SWITCH_GMEM_SAVE_RESTORE, 0x1); 213 + 214 + /* Reset the preemption state */ 215 + set_preempt_state(a6xx_gpu, PREEMPT_NONE); 216 + 217 + spin_lock_init(&a6xx_gpu->eval_lock); 218 + 219 + /* Always come up on rb 0 */ 220 + a6xx_gpu->cur_ring = gpu->rb[0]; 221 + } 222 + 223 + void a6xx_preempt_trigger(struct msm_gpu *gpu) 224 + { 225 + struct adreno_gpu *adreno_gpu = to_adreno_gpu(gpu); 226 + struct a6xx_gpu *a6xx_gpu = to_a6xx_gpu(adreno_gpu); 227 + unsigned long flags; 228 + struct msm_ringbuffer *ring; 229 + unsigned int cntl; 230 + bool sysprof; 231 + 232 + if (gpu->nr_rings == 1) 233 + return; 234 + 235 + /* 236 + * Lock to make sure another thread attempting preemption doesn't skip it 237 + * while we are still evaluating the next ring. This makes sure the other 238 + * thread does start preemption if we abort it and avoids a soft lock. 239 + */ 240 + spin_lock_irqsave(&a6xx_gpu->eval_lock, flags); 241 + 242 + /* 243 + * Try to start preemption by moving from NONE to START. If 244 + * unsuccessful, a preemption is already in flight 245 + */ 246 + if (!try_preempt_state(a6xx_gpu, PREEMPT_NONE, PREEMPT_START)) { 247 + spin_unlock_irqrestore(&a6xx_gpu->eval_lock, flags); 248 + return; 249 + } 250 + 251 + cntl = A6XX_CP_CONTEXT_SWITCH_CNTL_LEVEL(a6xx_gpu->preempt_level); 252 + 253 + if (a6xx_gpu->skip_save_restore) 254 + cntl |= A6XX_CP_CONTEXT_SWITCH_CNTL_SKIP_SAVE_RESTORE; 255 + 256 + if (a6xx_gpu->uses_gmem) 257 + cntl |= A6XX_CP_CONTEXT_SWITCH_CNTL_USES_GMEM; 258 + 259 + cntl |= A6XX_CP_CONTEXT_SWITCH_CNTL_STOP; 260 + 261 + /* Get the next ring to preempt to */ 262 + ring = get_next_ring(gpu); 263 + 264 + /* 265 + * If no ring is populated or the highest priority ring is the current 266 + * one do nothing except to update the wptr to the latest and greatest 267 + */ 268 + if (!ring || (a6xx_gpu->cur_ring == ring)) { 269 + set_preempt_state(a6xx_gpu, PREEMPT_FINISH); 270 + update_wptr(gpu, a6xx_gpu->cur_ring); 271 + set_preempt_state(a6xx_gpu, PREEMPT_NONE); 272 + spin_unlock_irqrestore(&a6xx_gpu->eval_lock, flags); 273 + return; 274 + } 275 + 276 + spin_unlock_irqrestore(&a6xx_gpu->eval_lock, flags); 277 + 278 + spin_lock_irqsave(&ring->preempt_lock, flags); 279 + 280 + struct a7xx_cp_smmu_info *smmu_info_ptr = 281 + a6xx_gpu->preempt_smmu[ring->id]; 282 + struct a6xx_preempt_record *record_ptr = a6xx_gpu->preempt[ring->id]; 283 + u64 ttbr0 = ring->memptrs->ttbr0; 284 + u32 context_idr = ring->memptrs->context_idr; 285 + 286 + smmu_info_ptr->ttbr0 = ttbr0; 287 + smmu_info_ptr->context_idr = context_idr; 288 + record_ptr->wptr = get_wptr(ring); 289 + 290 + /* 291 + * The GPU will write the wptr we set above when we preempt. Reset 292 + * restore_wptr to make sure that we don't write WPTR to the same 293 + * thing twice. It's still possible subsequent submissions will update 294 + * wptr again, in which case they will set the flag to true. This has 295 + * to be protected by the lock for setting the flag and updating wptr 296 + * to be atomic. 297 + */ 298 + ring->restore_wptr = false; 299 + 300 + trace_msm_gpu_preemption_trigger(a6xx_gpu->cur_ring->id, ring->id); 301 + 302 + spin_unlock_irqrestore(&ring->preempt_lock, flags); 303 + 304 + gpu_write64(gpu, 305 + REG_A6XX_CP_CONTEXT_SWITCH_SMMU_INFO, 306 + a6xx_gpu->preempt_smmu_iova[ring->id]); 307 + 308 + gpu_write64(gpu, 309 + REG_A6XX_CP_CONTEXT_SWITCH_PRIV_NON_SECURE_RESTORE_ADDR, 310 + a6xx_gpu->preempt_iova[ring->id]); 311 + 312 + a6xx_gpu->next_ring = ring; 313 + 314 + /* Start a timer to catch a stuck preemption */ 315 + mod_timer(&a6xx_gpu->preempt_timer, jiffies + msecs_to_jiffies(10000)); 316 + 317 + /* Enable or disable postamble as needed */ 318 + sysprof = refcount_read(&a6xx_gpu->base.base.sysprof_active) > 1; 319 + 320 + if (!sysprof && !a6xx_gpu->postamble_enabled) 321 + preempt_prepare_postamble(a6xx_gpu); 322 + 323 + if (sysprof && a6xx_gpu->postamble_enabled) 324 + preempt_disable_postamble(a6xx_gpu); 325 + 326 + /* Set the preemption state to triggered */ 327 + set_preempt_state(a6xx_gpu, PREEMPT_TRIGGERED); 328 + 329 + /* Trigger the preemption */ 330 + gpu_write(gpu, REG_A6XX_CP_CONTEXT_SWITCH_CNTL, cntl); 331 + } 332 + 333 + static int preempt_init_ring(struct a6xx_gpu *a6xx_gpu, 334 + struct msm_ringbuffer *ring) 335 + { 336 + struct adreno_gpu *adreno_gpu = &a6xx_gpu->base; 337 + struct msm_gpu *gpu = &adreno_gpu->base; 338 + struct drm_gem_object *bo = NULL; 339 + phys_addr_t ttbr; 340 + u64 iova = 0; 341 + void *ptr; 342 + int asid; 343 + 344 + ptr = msm_gem_kernel_new(gpu->dev, 345 + PREEMPT_RECORD_SIZE(adreno_gpu), 346 + MSM_BO_WC | MSM_BO_MAP_PRIV, gpu->aspace, &bo, &iova); 347 + 348 + if (IS_ERR(ptr)) 349 + return PTR_ERR(ptr); 350 + 351 + memset(ptr, 0, PREEMPT_RECORD_SIZE(adreno_gpu)); 352 + 353 + msm_gem_object_set_name(bo, "preempt_record ring%d", ring->id); 354 + 355 + a6xx_gpu->preempt_bo[ring->id] = bo; 356 + a6xx_gpu->preempt_iova[ring->id] = iova; 357 + a6xx_gpu->preempt[ring->id] = ptr; 358 + 359 + struct a6xx_preempt_record *record_ptr = ptr; 360 + 361 + ptr = msm_gem_kernel_new(gpu->dev, 362 + PREEMPT_SMMU_INFO_SIZE, 363 + MSM_BO_WC | MSM_BO_MAP_PRIV | MSM_BO_GPU_READONLY, 364 + gpu->aspace, &bo, &iova); 365 + 366 + if (IS_ERR(ptr)) 367 + return PTR_ERR(ptr); 368 + 369 + memset(ptr, 0, PREEMPT_SMMU_INFO_SIZE); 370 + 371 + msm_gem_object_set_name(bo, "preempt_smmu_info ring%d", ring->id); 372 + 373 + a6xx_gpu->preempt_smmu_bo[ring->id] = bo; 374 + a6xx_gpu->preempt_smmu_iova[ring->id] = iova; 375 + a6xx_gpu->preempt_smmu[ring->id] = ptr; 376 + 377 + struct a7xx_cp_smmu_info *smmu_info_ptr = ptr; 378 + 379 + msm_iommu_pagetable_params(gpu->aspace->mmu, &ttbr, &asid); 380 + 381 + smmu_info_ptr->magic = GEN7_CP_SMMU_INFO_MAGIC; 382 + smmu_info_ptr->ttbr0 = ttbr; 383 + smmu_info_ptr->asid = 0xdecafbad; 384 + smmu_info_ptr->context_idr = 0; 385 + 386 + /* Set up the defaults on the preemption record */ 387 + record_ptr->magic = A6XX_PREEMPT_RECORD_MAGIC; 388 + record_ptr->info = 0; 389 + record_ptr->data = 0; 390 + record_ptr->rptr = 0; 391 + record_ptr->wptr = 0; 392 + record_ptr->cntl = MSM_GPU_RB_CNTL_DEFAULT; 393 + record_ptr->rbase = ring->iova; 394 + record_ptr->counter = 0; 395 + record_ptr->bv_rptr_addr = rbmemptr(ring, bv_rptr); 396 + 397 + return 0; 398 + } 399 + 400 + void a6xx_preempt_fini(struct msm_gpu *gpu) 401 + { 402 + struct adreno_gpu *adreno_gpu = to_adreno_gpu(gpu); 403 + struct a6xx_gpu *a6xx_gpu = to_a6xx_gpu(adreno_gpu); 404 + int i; 405 + 406 + for (i = 0; i < gpu->nr_rings; i++) 407 + msm_gem_kernel_put(a6xx_gpu->preempt_bo[i], gpu->aspace); 408 + } 409 + 410 + void a6xx_preempt_init(struct msm_gpu *gpu) 411 + { 412 + struct adreno_gpu *adreno_gpu = to_adreno_gpu(gpu); 413 + struct a6xx_gpu *a6xx_gpu = to_a6xx_gpu(adreno_gpu); 414 + int i; 415 + 416 + /* No preemption if we only have one ring */ 417 + if (gpu->nr_rings <= 1) 418 + return; 419 + 420 + for (i = 0; i < gpu->nr_rings; i++) { 421 + if (preempt_init_ring(a6xx_gpu, gpu->rb[i])) 422 + goto fail; 423 + } 424 + 425 + /* TODO: make this configurable? */ 426 + a6xx_gpu->preempt_level = 1; 427 + a6xx_gpu->uses_gmem = 1; 428 + a6xx_gpu->skip_save_restore = 1; 429 + 430 + a6xx_gpu->preempt_postamble_ptr = msm_gem_kernel_new(gpu->dev, 431 + PAGE_SIZE, 432 + MSM_BO_WC | MSM_BO_MAP_PRIV | MSM_BO_GPU_READONLY, 433 + gpu->aspace, &a6xx_gpu->preempt_postamble_bo, 434 + &a6xx_gpu->preempt_postamble_iova); 435 + 436 + preempt_prepare_postamble(a6xx_gpu); 437 + 438 + if (IS_ERR(a6xx_gpu->preempt_postamble_ptr)) 439 + goto fail; 440 + 441 + timer_setup(&a6xx_gpu->preempt_timer, a6xx_preempt_timer, 0); 442 + 443 + return; 444 + fail: 445 + /* 446 + * On any failure our adventure is over. Clean up and 447 + * set nr_rings to 1 to force preemption off 448 + */ 449 + a6xx_preempt_fini(gpu); 450 + gpu->nr_rings = 1; 451 + 452 + DRM_DEV_ERROR(&gpu->pdev->dev, 453 + "preemption init failed, disabling preemption\n"); 454 + 455 + return; 456 + }
+4
drivers/gpu/drm/msm/adreno/adreno_device.c
··· 20 20 MODULE_PARM_DESC(allow_vram_carveout, "Allow using VRAM Carveout, in place of IOMMU"); 21 21 module_param_named(allow_vram_carveout, allow_vram_carveout, bool, 0600); 22 22 23 + int enable_preemption = -1; 24 + MODULE_PARM_DESC(enable_preemption, "Enable preemption (A7xx only) (1=on , 0=disable, -1=auto (default))"); 25 + module_param(enable_preemption, int, 0600); 26 + 23 27 extern const struct adreno_gpulist a2xx_gpulist; 24 28 extern const struct adreno_gpulist a3xx_gpulist; 25 29 extern const struct adreno_gpulist a4xx_gpulist;
+1 -1
drivers/gpu/drm/msm/adreno/adreno_gpu.c
··· 533 533 if (!adreno_gpu->info->fw[i]) 534 534 continue; 535 535 536 - /* Skip loading GMU firwmare with GMU Wrapper */ 536 + /* Skip loading GMU firmware with GMU Wrapper */ 537 537 if (adreno_has_gmu_wrapper(adreno_gpu) && i == ADRENO_FW_GMU) 538 538 continue; 539 539
+25 -2
drivers/gpu/drm/msm/adreno/adreno_gpu.h
··· 56 56 #define ADRENO_QUIRK_LMLOADKILL_DISABLE BIT(2) 57 57 #define ADRENO_QUIRK_HAS_HW_APRIV BIT(3) 58 58 #define ADRENO_QUIRK_HAS_CACHED_COHERENT BIT(4) 59 + #define ADRENO_QUIRK_PREEMPTION BIT(5) 59 60 60 61 /* Helper for formating the chip_id in the way that userspace tools like 61 62 * crashdec expect. ··· 112 111 * {SHRT_MAX, 0} sentinal. 113 112 */ 114 113 struct adreno_speedbin *speedbins; 114 + u64 preempt_record_size; 115 115 }; 116 116 117 117 #define ADRENO_CHIP_IDS(tbl...) (uint32_t[]) { tbl, 0 } ··· 156 154 .regs = name ## _regs, \ 157 155 .count = ARRAY_SIZE(name ## _regs), \ 158 156 .count_max = __count_max, \ 157 + }; 158 + 159 + struct adreno_reglist_list { 160 + /** @reg: List of register **/ 161 + const u32 *regs; 162 + /** @count: Number of registers in the list **/ 163 + u32 count; 164 + }; 165 + 166 + #define DECLARE_ADRENO_REGLIST_LIST(name) \ 167 + static const struct adreno_reglist_list name = { \ 168 + .regs = name ## _regs, \ 169 + .count = ARRAY_SIZE(name ## _regs), \ 159 170 }; 160 171 161 172 struct adreno_gpu { ··· 470 455 return adreno_is_revn(gpu, 680); 471 456 } 472 457 458 + static inline int adreno_is_a663(const struct adreno_gpu *gpu) 459 + { 460 + return gpu->info->chip_ids[0] == 0x06060300; 461 + } 462 + 473 463 static inline int adreno_is_a690(const struct adreno_gpu *gpu) 474 464 { 475 465 return gpu->info->chip_ids[0] == 0x06090000; ··· 676 656 OUT_RING(ring, PKT4(regindx, cnt)); 677 657 } 678 658 659 + #define PKT7(opcode, cnt) \ 660 + (CP_TYPE7_PKT | (cnt << 0) | (PM4_PARITY(cnt) << 15) | \ 661 + ((opcode & 0x7F) << 16) | (PM4_PARITY(opcode) << 23)) 662 + 679 663 static inline void 680 664 OUT_PKT7(struct msm_ringbuffer *ring, uint8_t opcode, uint16_t cnt) 681 665 { 682 666 adreno_wait_ring(ring, cnt + 1); 683 - OUT_RING(ring, CP_TYPE7_PKT | (cnt << 0) | (PM4_PARITY(cnt) << 15) | 684 - ((opcode & 0x7F) << 16) | (PM4_PARITY(opcode) << 23)); 667 + OUT_RING(ring, PKT7(opcode, cnt)); 685 668 } 686 669 687 670 struct msm_gpu *a2xx_gpu_init(struct drm_device *dev);
+210
drivers/gpu/drm/msm/disp/dpu1/catalog/dpu_1_14_msm8937.h
··· 1 + /* SPDX-License-Identifier: GPL-2.0-only */ 2 + /* 3 + * Copyright (c) 2023, Linaro Limited 4 + */ 5 + 6 + #ifndef _DPU_1_14_MSM8937_H 7 + #define _DPU_1_14_MSM8937_H 8 + 9 + static const struct dpu_caps msm8937_dpu_caps = { 10 + .max_mixer_width = DEFAULT_DPU_LINE_WIDTH, 11 + .max_mixer_blendstages = 0x4, 12 + .max_linewidth = DEFAULT_DPU_LINE_WIDTH, 13 + .pixel_ram_size = 40 * 1024, 14 + .max_hdeci_exp = MAX_HORZ_DECIMATION, 15 + .max_vdeci_exp = MAX_VERT_DECIMATION, 16 + }; 17 + 18 + static const struct dpu_mdp_cfg msm8937_mdp[] = { 19 + { 20 + .name = "top_0", 21 + .base = 0x0, .len = 0x454, 22 + .features = BIT(DPU_MDP_VSYNC_SEL), 23 + .clk_ctrls = { 24 + [DPU_CLK_CTRL_VIG0] = { .reg_off = 0x2ac, .bit_off = 0 }, 25 + [DPU_CLK_CTRL_RGB0] = { .reg_off = 0x2ac, .bit_off = 4 }, 26 + [DPU_CLK_CTRL_RGB1] = { .reg_off = 0x2b4, .bit_off = 4 }, 27 + [DPU_CLK_CTRL_DMA0] = { .reg_off = 0x2ac, .bit_off = 8 }, 28 + [DPU_CLK_CTRL_CURSOR0] = { .reg_off = 0x3a8, .bit_off = 16 }, 29 + }, 30 + }, 31 + }; 32 + 33 + static const struct dpu_ctl_cfg msm8937_ctl[] = { 34 + { 35 + .name = "ctl_0", .id = CTL_0, 36 + .base = 0x1000, .len = 0x64, 37 + }, { 38 + .name = "ctl_1", .id = CTL_1, 39 + .base = 0x1200, .len = 0x64, 40 + }, { 41 + .name = "ctl_2", .id = CTL_2, 42 + .base = 0x1400, .len = 0x64, 43 + }, 44 + }; 45 + 46 + static const struct dpu_sspp_cfg msm8937_sspp[] = { 47 + { 48 + .name = "sspp_0", .id = SSPP_VIG0, 49 + .base = 0x4000, .len = 0x150, 50 + .features = VIG_MSM8953_MASK, 51 + .sblk = &dpu_vig_sblk_qseed2, 52 + .xin_id = 0, 53 + .type = SSPP_TYPE_VIG, 54 + .clk_ctrl = DPU_CLK_CTRL_VIG0, 55 + }, { 56 + .name = "sspp_4", .id = SSPP_RGB0, 57 + .base = 0x14000, .len = 0x150, 58 + .features = RGB_MSM8953_MASK, 59 + .sblk = &dpu_rgb_sblk, 60 + .xin_id = 1, 61 + .type = SSPP_TYPE_RGB, 62 + .clk_ctrl = DPU_CLK_CTRL_RGB0, 63 + }, { 64 + .name = "sspp_5", .id = SSPP_RGB1, 65 + .base = 0x16000, .len = 0x150, 66 + .features = RGB_MSM8953_MASK, 67 + .sblk = &dpu_rgb_sblk, 68 + .xin_id = 5, 69 + .type = SSPP_TYPE_RGB, 70 + .clk_ctrl = DPU_CLK_CTRL_RGB1, 71 + }, { 72 + .name = "sspp_8", .id = SSPP_DMA0, 73 + .base = 0x24000, .len = 0x150, 74 + .features = DMA_MSM8953_MASK | BIT(DPU_SSPP_CURSOR), 75 + .sblk = &dpu_dma_sblk, 76 + .xin_id = 2, 77 + .type = SSPP_TYPE_DMA, 78 + .clk_ctrl = DPU_CLK_CTRL_DMA0, 79 + }, 80 + }; 81 + 82 + static const struct dpu_lm_cfg msm8937_lm[] = { 83 + { 84 + .name = "lm_0", .id = LM_0, 85 + .base = 0x44000, .len = 0x320, 86 + .sblk = &msm8998_lm_sblk, 87 + .lm_pair = LM_1, 88 + .pingpong = PINGPONG_0, 89 + .dspp = DSPP_0, 90 + }, { 91 + .name = "lm_1", .id = LM_1, 92 + .base = 0x45000, .len = 0x320, 93 + .sblk = &msm8998_lm_sblk, 94 + .lm_pair = LM_0, 95 + .pingpong = PINGPONG_1, 96 + }, 97 + }; 98 + 99 + static const struct dpu_pingpong_cfg msm8937_pp[] = { 100 + { 101 + .name = "pingpong_0", .id = PINGPONG_0, 102 + .base = 0x70000, .len = 0xd4, 103 + .features = PINGPONG_MSM8996_MASK, 104 + .sblk = &msm8996_pp_sblk, 105 + .intr_done = DPU_IRQ_IDX(MDP_SSPP_TOP0_INTR, 8), 106 + .intr_rdptr = DPU_IRQ_IDX(MDP_SSPP_TOP0_INTR, 12), 107 + }, { 108 + .name = "pingpong_1", .id = PINGPONG_1, 109 + .base = 0x70800, .len = 0xd4, 110 + .features = PINGPONG_MSM8996_MASK, 111 + .sblk = &msm8996_pp_sblk, 112 + .intr_done = DPU_IRQ_IDX(MDP_SSPP_TOP0_INTR, 9), 113 + .intr_rdptr = DPU_IRQ_IDX(MDP_SSPP_TOP0_INTR, 13), 114 + }, 115 + }; 116 + 117 + static const struct dpu_dspp_cfg msm8937_dspp[] = { 118 + { 119 + .name = "dspp_0", .id = DSPP_0, 120 + .base = 0x54000, .len = 0x1800, 121 + .features = DSPP_SC7180_MASK, 122 + .sblk = &msm8998_dspp_sblk, 123 + }, 124 + }; 125 + 126 + static const struct dpu_intf_cfg msm8937_intf[] = { 127 + { 128 + .name = "intf_1", .id = INTF_1, 129 + .base = 0x6a800, .len = 0x268, 130 + .type = INTF_DSI, 131 + .controller_id = MSM_DSI_CONTROLLER_0, 132 + .prog_fetch_lines_worst_case = 14, 133 + .intr_underrun = DPU_IRQ_IDX(MDP_SSPP_TOP0_INTR, 26), 134 + .intr_vsync = DPU_IRQ_IDX(MDP_SSPP_TOP0_INTR, 27), 135 + .intr_tear_rd_ptr = -1, 136 + }, { 137 + .name = "intf_2", .id = INTF_2, 138 + .base = 0x6b000, .len = 0x268, 139 + .type = INTF_DSI, 140 + .controller_id = MSM_DSI_CONTROLLER_1, 141 + .prog_fetch_lines_worst_case = 14, 142 + .intr_underrun = DPU_IRQ_IDX(MDP_SSPP_TOP0_INTR, 28), 143 + .intr_vsync = DPU_IRQ_IDX(MDP_SSPP_TOP0_INTR, 29), 144 + .intr_tear_rd_ptr = -1, 145 + }, 146 + }; 147 + 148 + static const struct dpu_perf_cfg msm8937_perf_data = { 149 + .max_bw_low = 3100000, 150 + .max_bw_high = 3100000, 151 + .min_core_ib = 2400000, 152 + .min_llcc_ib = 0, /* No LLCC on this SoC */ 153 + .min_dram_ib = 800000, 154 + .undersized_prefill_lines = 2, 155 + .xtra_prefill_lines = 2, 156 + .dest_scale_prefill_lines = 3, 157 + .macrotile_prefill_lines = 4, 158 + .yuv_nv12_prefill_lines = 8, 159 + .linear_prefill_lines = 1, 160 + .downscaling_prefill_lines = 1, 161 + .amortizable_threshold = 25, 162 + .min_prefill_lines = 14, 163 + .danger_lut_tbl = {0xf, 0xffff, 0x0}, 164 + .safe_lut_tbl = {0xfffc, 0xff00, 0xffff}, 165 + .qos_lut_tbl = { 166 + {.nentry = ARRAY_SIZE(msm8998_qos_linear), 167 + .entries = msm8998_qos_linear 168 + }, 169 + {.nentry = ARRAY_SIZE(msm8998_qos_macrotile), 170 + .entries = msm8998_qos_macrotile 171 + }, 172 + {.nentry = ARRAY_SIZE(msm8998_qos_nrt), 173 + .entries = msm8998_qos_nrt 174 + }, 175 + }, 176 + .cdp_cfg = { 177 + {.rd_enable = 1, .wr_enable = 1}, 178 + {.rd_enable = 1, .wr_enable = 0} 179 + }, 180 + .clk_inefficiency_factor = 105, 181 + .bw_inefficiency_factor = 120, 182 + }; 183 + 184 + static const struct dpu_mdss_version msm8937_mdss_ver = { 185 + .core_major_ver = 1, 186 + .core_minor_ver = 14, 187 + }; 188 + 189 + const struct dpu_mdss_cfg dpu_msm8937_cfg = { 190 + .mdss_ver = &msm8937_mdss_ver, 191 + .caps = &msm8937_dpu_caps, 192 + .mdp = msm8937_mdp, 193 + .ctl_count = ARRAY_SIZE(msm8937_ctl), 194 + .ctl = msm8937_ctl, 195 + .sspp_count = ARRAY_SIZE(msm8937_sspp), 196 + .sspp = msm8937_sspp, 197 + .mixer_count = ARRAY_SIZE(msm8937_lm), 198 + .mixer = msm8937_lm, 199 + .dspp_count = ARRAY_SIZE(msm8937_dspp), 200 + .dspp = msm8937_dspp, 201 + .pingpong_count = ARRAY_SIZE(msm8937_pp), 202 + .pingpong = msm8937_pp, 203 + .intf_count = ARRAY_SIZE(msm8937_intf), 204 + .intf = msm8937_intf, 205 + .vbif_count = ARRAY_SIZE(msm8996_vbif), 206 + .vbif = msm8996_vbif, 207 + .perf = &msm8937_perf_data, 208 + }; 209 + 210 + #endif
+187
drivers/gpu/drm/msm/disp/dpu1/catalog/dpu_1_15_msm8917.h
··· 1 + /* SPDX-License-Identifier: GPL-2.0-only */ 2 + /* 3 + * Copyright (c) 2023, Linaro Limited 4 + */ 5 + 6 + #ifndef _DPU_1_14_MSM8917_H 7 + #define _DPU_1_14_MSM8917_H 8 + 9 + static const struct dpu_caps msm8917_dpu_caps = { 10 + .max_mixer_width = DEFAULT_DPU_LINE_WIDTH, 11 + .max_mixer_blendstages = 0x4, 12 + .max_linewidth = DEFAULT_DPU_LINE_WIDTH, 13 + .pixel_ram_size = 16 * 1024, 14 + .max_hdeci_exp = MAX_HORZ_DECIMATION, 15 + .max_vdeci_exp = MAX_VERT_DECIMATION, 16 + }; 17 + 18 + static const struct dpu_mdp_cfg msm8917_mdp[] = { 19 + { 20 + .name = "top_0", 21 + .base = 0x0, .len = 0x454, 22 + .features = BIT(DPU_MDP_VSYNC_SEL), 23 + .clk_ctrls = { 24 + [DPU_CLK_CTRL_VIG0] = { .reg_off = 0x2ac, .bit_off = 0 }, 25 + [DPU_CLK_CTRL_RGB0] = { .reg_off = 0x2ac, .bit_off = 4 }, 26 + [DPU_CLK_CTRL_RGB1] = { .reg_off = 0x2b4, .bit_off = 4 }, 27 + [DPU_CLK_CTRL_DMA0] = { .reg_off = 0x2ac, .bit_off = 8 }, 28 + [DPU_CLK_CTRL_CURSOR0] = { .reg_off = 0x3a8, .bit_off = 16 }, 29 + }, 30 + }, 31 + }; 32 + 33 + static const struct dpu_ctl_cfg msm8917_ctl[] = { 34 + { 35 + .name = "ctl_0", .id = CTL_0, 36 + .base = 0x1000, .len = 0x64, 37 + }, { 38 + .name = "ctl_1", .id = CTL_1, 39 + .base = 0x1200, .len = 0x64, 40 + }, { 41 + .name = "ctl_2", .id = CTL_2, 42 + .base = 0x1400, .len = 0x64, 43 + }, 44 + }; 45 + 46 + static const struct dpu_sspp_cfg msm8917_sspp[] = { 47 + { 48 + .name = "sspp_0", .id = SSPP_VIG0, 49 + .base = 0x4000, .len = 0x150, 50 + .features = VIG_MSM8953_MASK, 51 + .sblk = &dpu_vig_sblk_qseed2, 52 + .xin_id = 0, 53 + .type = SSPP_TYPE_VIG, 54 + .clk_ctrl = DPU_CLK_CTRL_VIG0, 55 + }, { 56 + .name = "sspp_4", .id = SSPP_RGB0, 57 + .base = 0x14000, .len = 0x150, 58 + .features = RGB_MSM8953_MASK, 59 + .sblk = &dpu_rgb_sblk, 60 + .xin_id = 1, 61 + .type = SSPP_TYPE_RGB, 62 + .clk_ctrl = DPU_CLK_CTRL_RGB0, 63 + }, { 64 + .name = "sspp_5", .id = SSPP_RGB1, 65 + .base = 0x16000, .len = 0x150, 66 + .features = RGB_MSM8953_MASK, 67 + .sblk = &dpu_rgb_sblk, 68 + .xin_id = 5, 69 + .type = SSPP_TYPE_RGB, 70 + .clk_ctrl = DPU_CLK_CTRL_RGB1, 71 + }, { 72 + .name = "sspp_8", .id = SSPP_DMA0, 73 + .base = 0x24000, .len = 0x150, 74 + .features = DMA_MSM8953_MASK | BIT(DPU_SSPP_CURSOR), 75 + .sblk = &dpu_dma_sblk, 76 + .xin_id = 2, 77 + .type = SSPP_TYPE_DMA, 78 + .clk_ctrl = DPU_CLK_CTRL_DMA0, 79 + }, 80 + }; 81 + 82 + static const struct dpu_lm_cfg msm8917_lm[] = { 83 + { 84 + .name = "lm_0", .id = LM_0, 85 + .base = 0x44000, .len = 0x320, 86 + .sblk = &msm8998_lm_sblk, 87 + .pingpong = PINGPONG_0, 88 + .dspp = DSPP_0, 89 + }, 90 + }; 91 + 92 + static const struct dpu_pingpong_cfg msm8917_pp[] = { 93 + { 94 + .name = "pingpong_0", .id = PINGPONG_0, 95 + .base = 0x70000, .len = 0xd4, 96 + .features = PINGPONG_MSM8996_MASK, 97 + .sblk = &msm8996_pp_sblk, 98 + .intr_done = DPU_IRQ_IDX(MDP_SSPP_TOP0_INTR, 8), 99 + .intr_rdptr = DPU_IRQ_IDX(MDP_SSPP_TOP0_INTR, 12), 100 + }, 101 + }; 102 + 103 + static const struct dpu_dspp_cfg msm8917_dspp[] = { 104 + { 105 + .name = "dspp_0", .id = DSPP_0, 106 + .base = 0x54000, .len = 0x1800, 107 + .features = DSPP_SC7180_MASK, 108 + .sblk = &msm8998_dspp_sblk, 109 + }, 110 + }; 111 + 112 + static const struct dpu_intf_cfg msm8917_intf[] = { 113 + { 114 + .name = "intf_1", .id = INTF_1, 115 + .base = 0x6a800, .len = 0x268, 116 + .type = INTF_DSI, 117 + .controller_id = MSM_DSI_CONTROLLER_0, 118 + .prog_fetch_lines_worst_case = 14, 119 + .intr_underrun = DPU_IRQ_IDX(MDP_SSPP_TOP0_INTR, 26), 120 + .intr_vsync = DPU_IRQ_IDX(MDP_SSPP_TOP0_INTR, 27), 121 + .intr_tear_rd_ptr = -1, 122 + }, 123 + }; 124 + 125 + static const struct dpu_perf_cfg msm8917_perf_data = { 126 + .max_bw_low = 1800000, 127 + .max_bw_high = 1800000, 128 + .min_core_ib = 2400000, 129 + .min_llcc_ib = 0, /* No LLCC on this SoC */ 130 + .min_dram_ib = 800000, 131 + .undersized_prefill_lines = 2, 132 + .xtra_prefill_lines = 2, 133 + .dest_scale_prefill_lines = 3, 134 + .macrotile_prefill_lines = 4, 135 + .yuv_nv12_prefill_lines = 8, 136 + .linear_prefill_lines = 1, 137 + .downscaling_prefill_lines = 1, 138 + .amortizable_threshold = 25, 139 + .min_prefill_lines = 21, 140 + .danger_lut_tbl = {0xf, 0xffff, 0x0}, 141 + .safe_lut_tbl = {0xfffc, 0xff00, 0xffff}, 142 + .qos_lut_tbl = { 143 + {.nentry = ARRAY_SIZE(msm8998_qos_linear), 144 + .entries = msm8998_qos_linear 145 + }, 146 + {.nentry = ARRAY_SIZE(msm8998_qos_macrotile), 147 + .entries = msm8998_qos_macrotile 148 + }, 149 + {.nentry = ARRAY_SIZE(msm8998_qos_nrt), 150 + .entries = msm8998_qos_nrt 151 + }, 152 + }, 153 + .cdp_cfg = { 154 + {.rd_enable = 1, .wr_enable = 1}, 155 + {.rd_enable = 1, .wr_enable = 0} 156 + }, 157 + .clk_inefficiency_factor = 105, 158 + .bw_inefficiency_factor = 120, 159 + }; 160 + 161 + static const struct dpu_mdss_version msm8917_mdss_ver = { 162 + .core_major_ver = 1, 163 + .core_minor_ver = 15, 164 + }; 165 + 166 + const struct dpu_mdss_cfg dpu_msm8917_cfg = { 167 + .mdss_ver = &msm8917_mdss_ver, 168 + .caps = &msm8917_dpu_caps, 169 + .mdp = msm8917_mdp, 170 + .ctl_count = ARRAY_SIZE(msm8917_ctl), 171 + .ctl = msm8917_ctl, 172 + .sspp_count = ARRAY_SIZE(msm8917_sspp), 173 + .sspp = msm8917_sspp, 174 + .mixer_count = ARRAY_SIZE(msm8917_lm), 175 + .mixer = msm8917_lm, 176 + .dspp_count = ARRAY_SIZE(msm8917_dspp), 177 + .dspp = msm8917_dspp, 178 + .pingpong_count = ARRAY_SIZE(msm8917_pp), 179 + .pingpong = msm8917_pp, 180 + .intf_count = ARRAY_SIZE(msm8917_intf), 181 + .intf = msm8917_intf, 182 + .vbif_count = ARRAY_SIZE(msm8996_vbif), 183 + .vbif = msm8996_vbif, 184 + .perf = &msm8917_perf_data, 185 + }; 186 + 187 + #endif
+218
drivers/gpu/drm/msm/disp/dpu1/catalog/dpu_1_16_msm8953.h
··· 1 + /* SPDX-License-Identifier: GPL-2.0-only */ 2 + /* 3 + * Copyright (c) 2023, Linaro Limited 4 + */ 5 + 6 + #ifndef _DPU_1_16_MSM8953_H 7 + #define _DPU_1_16_MSM8953_H 8 + 9 + static const struct dpu_caps msm8953_dpu_caps = { 10 + .max_mixer_width = DEFAULT_DPU_LINE_WIDTH, 11 + .max_mixer_blendstages = 0x4, 12 + .max_linewidth = DEFAULT_DPU_LINE_WIDTH, 13 + .pixel_ram_size = 40 * 1024, 14 + .max_hdeci_exp = MAX_HORZ_DECIMATION, 15 + .max_vdeci_exp = MAX_VERT_DECIMATION, 16 + }; 17 + 18 + static const struct dpu_mdp_cfg msm8953_mdp[] = { 19 + { 20 + .name = "top_0", 21 + .base = 0x0, .len = 0x454, 22 + .features = BIT(DPU_MDP_VSYNC_SEL), 23 + .clk_ctrls = { 24 + [DPU_CLK_CTRL_VIG0] = { .reg_off = 0x2ac, .bit_off = 0 }, 25 + [DPU_CLK_CTRL_RGB0] = { .reg_off = 0x2ac, .bit_off = 4 }, 26 + [DPU_CLK_CTRL_RGB1] = { .reg_off = 0x2b4, .bit_off = 4 }, 27 + [DPU_CLK_CTRL_DMA0] = { .reg_off = 0x2ac, .bit_off = 8 }, 28 + [DPU_CLK_CTRL_CURSOR0] = { .reg_off = 0x3a8, .bit_off = 16 }, 29 + }, 30 + }, 31 + }; 32 + 33 + static const struct dpu_ctl_cfg msm8953_ctl[] = { 34 + { 35 + .name = "ctl_0", .id = CTL_0, 36 + .base = 0x1000, .len = 0x64, 37 + }, { 38 + .name = "ctl_1", .id = CTL_1, 39 + .base = 0x1200, .len = 0x64, 40 + }, { 41 + .name = "ctl_2", .id = CTL_2, 42 + .base = 0x1400, .len = 0x64, 43 + }, 44 + }; 45 + 46 + static const struct dpu_sspp_cfg msm8953_sspp[] = { 47 + { 48 + .name = "sspp_0", .id = SSPP_VIG0, 49 + .base = 0x4000, .len = 0x150, 50 + .features = VIG_MSM8953_MASK, 51 + .sblk = &dpu_vig_sblk_qseed2, 52 + .xin_id = 0, 53 + .type = SSPP_TYPE_VIG, 54 + .clk_ctrl = DPU_CLK_CTRL_VIG0, 55 + }, { 56 + .name = "sspp_4", .id = SSPP_RGB0, 57 + .base = 0x14000, .len = 0x150, 58 + .features = RGB_MSM8953_MASK, 59 + .sblk = &dpu_rgb_sblk, 60 + .xin_id = 1, 61 + .type = SSPP_TYPE_RGB, 62 + .clk_ctrl = DPU_CLK_CTRL_RGB0, 63 + }, { 64 + .name = "sspp_5", .id = SSPP_RGB1, 65 + .base = 0x16000, .len = 0x150, 66 + .features = RGB_MSM8953_MASK, 67 + .sblk = &dpu_rgb_sblk, 68 + .xin_id = 5, 69 + .type = SSPP_TYPE_RGB, 70 + .clk_ctrl = DPU_CLK_CTRL_RGB1, 71 + }, { 72 + .name = "sspp_8", .id = SSPP_DMA0, 73 + .base = 0x24000, .len = 0x150, 74 + .features = DMA_MSM8953_MASK | BIT(DPU_SSPP_CURSOR), 75 + .sblk = &dpu_dma_sblk, 76 + .xin_id = 2, 77 + .type = SSPP_TYPE_DMA, 78 + .clk_ctrl = DPU_CLK_CTRL_DMA0, 79 + }, 80 + }; 81 + 82 + static const struct dpu_lm_cfg msm8953_lm[] = { 83 + { 84 + .name = "lm_0", .id = LM_0, 85 + .base = 0x44000, .len = 0x320, 86 + .sblk = &msm8998_lm_sblk, 87 + .lm_pair = LM_1, 88 + .pingpong = PINGPONG_0, 89 + .dspp = DSPP_0, 90 + }, { 91 + .name = "lm_1", .id = LM_1, 92 + .base = 0x45000, .len = 0x320, 93 + .sblk = &msm8998_lm_sblk, 94 + .lm_pair = LM_0, 95 + .pingpong = PINGPONG_1, 96 + }, 97 + }; 98 + 99 + static const struct dpu_pingpong_cfg msm8953_pp[] = { 100 + { 101 + .name = "pingpong_0", .id = PINGPONG_0, 102 + .base = 0x70000, .len = 0xd4, 103 + .features = PINGPONG_MSM8996_MASK, 104 + .sblk = &msm8996_pp_sblk, 105 + .intr_done = DPU_IRQ_IDX(MDP_SSPP_TOP0_INTR, 8), 106 + .intr_rdptr = DPU_IRQ_IDX(MDP_SSPP_TOP0_INTR, 12), 107 + }, { 108 + .name = "pingpong_1", .id = PINGPONG_1, 109 + .base = 0x70800, .len = 0xd4, 110 + .features = PINGPONG_MSM8996_MASK, 111 + .sblk = &msm8996_pp_sblk, 112 + .intr_done = DPU_IRQ_IDX(MDP_SSPP_TOP0_INTR, 9), 113 + .intr_rdptr = DPU_IRQ_IDX(MDP_SSPP_TOP0_INTR, 13), 114 + }, 115 + }; 116 + 117 + static const struct dpu_dspp_cfg msm8953_dspp[] = { 118 + { 119 + .name = "dspp_0", .id = DSPP_0, 120 + .base = 0x54000, .len = 0x1800, 121 + .features = DSPP_SC7180_MASK, 122 + .sblk = &msm8998_dspp_sblk, 123 + }, 124 + }; 125 + 126 + static const struct dpu_intf_cfg msm8953_intf[] = { 127 + { 128 + .name = "intf_0", .id = INTF_0, 129 + .base = 0x6a000, .len = 0x268, 130 + .type = INTF_NONE, 131 + .prog_fetch_lines_worst_case = 14, 132 + .intr_underrun = DPU_IRQ_IDX(MDP_SSPP_TOP0_INTR, 24), 133 + .intr_vsync = DPU_IRQ_IDX(MDP_SSPP_TOP0_INTR, 25), 134 + .intr_tear_rd_ptr = -1, 135 + }, { 136 + .name = "intf_1", .id = INTF_1, 137 + .base = 0x6a800, .len = 0x268, 138 + .type = INTF_DSI, 139 + .controller_id = MSM_DSI_CONTROLLER_0, 140 + .prog_fetch_lines_worst_case = 14, 141 + .intr_underrun = DPU_IRQ_IDX(MDP_SSPP_TOP0_INTR, 26), 142 + .intr_vsync = DPU_IRQ_IDX(MDP_SSPP_TOP0_INTR, 27), 143 + .intr_tear_rd_ptr = -1, 144 + }, { 145 + .name = "intf_2", .id = INTF_2, 146 + .base = 0x6b000, .len = 0x268, 147 + .type = INTF_DSI, 148 + .controller_id = MSM_DSI_CONTROLLER_1, 149 + .prog_fetch_lines_worst_case = 14, 150 + .intr_underrun = DPU_IRQ_IDX(MDP_SSPP_TOP0_INTR, 28), 151 + .intr_vsync = DPU_IRQ_IDX(MDP_SSPP_TOP0_INTR, 29), 152 + .intr_tear_rd_ptr = -1, 153 + }, 154 + }; 155 + 156 + static const struct dpu_perf_cfg msm8953_perf_data = { 157 + .max_bw_low = 3400000, 158 + .max_bw_high = 3400000, 159 + .min_core_ib = 2400000, 160 + .min_llcc_ib = 0, /* No LLCC on this SoC */ 161 + .min_dram_ib = 800000, 162 + .undersized_prefill_lines = 2, 163 + .xtra_prefill_lines = 2, 164 + .dest_scale_prefill_lines = 3, 165 + .macrotile_prefill_lines = 4, 166 + .yuv_nv12_prefill_lines = 8, 167 + .linear_prefill_lines = 1, 168 + .downscaling_prefill_lines = 1, 169 + .amortizable_threshold = 25, 170 + .min_prefill_lines = 14, 171 + .danger_lut_tbl = {0xf, 0xffff, 0x0}, 172 + .safe_lut_tbl = {0xfffc, 0xff00, 0xffff}, 173 + .qos_lut_tbl = { 174 + {.nentry = ARRAY_SIZE(msm8998_qos_linear), 175 + .entries = msm8998_qos_linear 176 + }, 177 + {.nentry = ARRAY_SIZE(msm8998_qos_macrotile), 178 + .entries = msm8998_qos_macrotile 179 + }, 180 + {.nentry = ARRAY_SIZE(msm8998_qos_nrt), 181 + .entries = msm8998_qos_nrt 182 + }, 183 + }, 184 + .cdp_cfg = { 185 + {.rd_enable = 1, .wr_enable = 1}, 186 + {.rd_enable = 1, .wr_enable = 0} 187 + }, 188 + .clk_inefficiency_factor = 105, 189 + .bw_inefficiency_factor = 120, 190 + }; 191 + 192 + static const struct dpu_mdss_version msm8953_mdss_ver = { 193 + .core_major_ver = 1, 194 + .core_minor_ver = 16, 195 + }; 196 + 197 + const struct dpu_mdss_cfg dpu_msm8953_cfg = { 198 + .mdss_ver = &msm8953_mdss_ver, 199 + .caps = &msm8953_dpu_caps, 200 + .mdp = msm8953_mdp, 201 + .ctl_count = ARRAY_SIZE(msm8953_ctl), 202 + .ctl = msm8953_ctl, 203 + .sspp_count = ARRAY_SIZE(msm8953_sspp), 204 + .sspp = msm8953_sspp, 205 + .mixer_count = ARRAY_SIZE(msm8953_lm), 206 + .mixer = msm8953_lm, 207 + .dspp_count = ARRAY_SIZE(msm8953_dspp), 208 + .dspp = msm8953_dspp, 209 + .pingpong_count = ARRAY_SIZE(msm8953_pp), 210 + .pingpong = msm8953_pp, 211 + .intf_count = ARRAY_SIZE(msm8953_intf), 212 + .intf = msm8953_intf, 213 + .vbif_count = ARRAY_SIZE(msm8996_vbif), 214 + .vbif = msm8996_vbif, 215 + .perf = &msm8953_perf_data, 216 + }; 217 + 218 + #endif
+338
drivers/gpu/drm/msm/disp/dpu1/catalog/dpu_1_7_msm8996.h
··· 1 + /* SPDX-License-Identifier: GPL-2.0-only */ 2 + /* 3 + * Copyright (c) 2023, Linaro Limited 4 + * Copyright (c) 2022. Qualcomm Innovation Center, Inc. All rights reserved. 5 + * Copyright (c) 2015-2018, 2020 The Linux Foundation. All rights reserved. 6 + */ 7 + 8 + #ifndef _DPU_1_7_MSM8996_H 9 + #define _DPU_1_7_MSM8996_H 10 + 11 + static const struct dpu_caps msm8996_dpu_caps = { 12 + .max_mixer_width = DEFAULT_DPU_OUTPUT_LINE_WIDTH, 13 + .max_mixer_blendstages = 0x7, 14 + .has_src_split = true, 15 + .max_linewidth = DEFAULT_DPU_OUTPUT_LINE_WIDTH, 16 + .pixel_ram_size = DEFAULT_PIXEL_RAM_SIZE, 17 + .max_hdeci_exp = MAX_HORZ_DECIMATION, 18 + .max_vdeci_exp = MAX_VERT_DECIMATION, 19 + }; 20 + 21 + static const struct dpu_mdp_cfg msm8996_mdp[] = { 22 + { 23 + .name = "top_0", 24 + .base = 0x0, .len = 0x454, 25 + .features = BIT(DPU_MDP_VSYNC_SEL), 26 + .clk_ctrls = { 27 + [DPU_CLK_CTRL_VIG0] = { .reg_off = 0x2ac, .bit_off = 0 }, 28 + [DPU_CLK_CTRL_VIG1] = { .reg_off = 0x2b4, .bit_off = 0 }, 29 + [DPU_CLK_CTRL_VIG2] = { .reg_off = 0x2bc, .bit_off = 0 }, 30 + [DPU_CLK_CTRL_VIG3] = { .reg_off = 0x2c4, .bit_off = 0 }, 31 + [DPU_CLK_CTRL_RGB0] = { .reg_off = 0x2ac, .bit_off = 4 }, 32 + [DPU_CLK_CTRL_RGB1] = { .reg_off = 0x2b4, .bit_off = 4 }, 33 + [DPU_CLK_CTRL_RGB2] = { .reg_off = 0x2bc, .bit_off = 4 }, 34 + [DPU_CLK_CTRL_RGB3] = { .reg_off = 0x2c4, .bit_off = 4 }, 35 + [DPU_CLK_CTRL_DMA0] = { .reg_off = 0x2ac, .bit_off = 8 }, 36 + [DPU_CLK_CTRL_DMA1] = { .reg_off = 0x2b4, .bit_off = 8 }, 37 + [DPU_CLK_CTRL_CURSOR0] = { .reg_off = 0x3a8, .bit_off = 16 }, 38 + [DPU_CLK_CTRL_CURSOR1] = { .reg_off = 0x3b0, .bit_off = 16 }, 39 + }, 40 + }, 41 + }; 42 + 43 + static const struct dpu_ctl_cfg msm8996_ctl[] = { 44 + { 45 + .name = "ctl_0", .id = CTL_0, 46 + .base = 0x1000, .len = 0x64, 47 + }, { 48 + .name = "ctl_1", .id = CTL_1, 49 + .base = 0x1200, .len = 0x64, 50 + }, { 51 + .name = "ctl_2", .id = CTL_2, 52 + .base = 0x1400, .len = 0x64, 53 + }, { 54 + .name = "ctl_3", .id = CTL_3, 55 + .base = 0x1600, .len = 0x64, 56 + }, { 57 + .name = "ctl_4", .id = CTL_4, 58 + .base = 0x1800, .len = 0x64, 59 + }, 60 + }; 61 + 62 + static const struct dpu_sspp_cfg msm8996_sspp[] = { 63 + { 64 + .name = "sspp_0", .id = SSPP_VIG0, 65 + .base = 0x4000, .len = 0x150, 66 + .features = VIG_MSM8996_MASK, 67 + .sblk = &dpu_vig_sblk_qseed2, 68 + .xin_id = 0, 69 + .type = SSPP_TYPE_VIG, 70 + .clk_ctrl = DPU_CLK_CTRL_VIG0, 71 + }, { 72 + .name = "sspp_1", .id = SSPP_VIG1, 73 + .base = 0x6000, .len = 0x150, 74 + .features = VIG_MSM8996_MASK, 75 + .sblk = &dpu_vig_sblk_qseed2, 76 + .xin_id = 4, 77 + .type = SSPP_TYPE_VIG, 78 + .clk_ctrl = DPU_CLK_CTRL_VIG1, 79 + }, { 80 + .name = "sspp_2", .id = SSPP_VIG2, 81 + .base = 0x8000, .len = 0x150, 82 + .features = VIG_MSM8996_MASK, 83 + .sblk = &dpu_vig_sblk_qseed2, 84 + .xin_id = 8, 85 + .type = SSPP_TYPE_VIG, 86 + .clk_ctrl = DPU_CLK_CTRL_VIG2, 87 + }, { 88 + .name = "sspp_3", .id = SSPP_VIG3, 89 + .base = 0xa000, .len = 0x150, 90 + .features = VIG_MSM8996_MASK, 91 + .sblk = &dpu_vig_sblk_qseed2, 92 + .xin_id = 12, 93 + .type = SSPP_TYPE_VIG, 94 + .clk_ctrl = DPU_CLK_CTRL_VIG3, 95 + }, { 96 + .name = "sspp_4", .id = SSPP_RGB0, 97 + .base = 0x14000, .len = 0x150, 98 + .features = RGB_MSM8996_MASK, 99 + .sblk = &dpu_rgb_sblk, 100 + .xin_id = 1, 101 + .type = SSPP_TYPE_RGB, 102 + .clk_ctrl = DPU_CLK_CTRL_RGB0, 103 + }, { 104 + .name = "sspp_5", .id = SSPP_RGB1, 105 + .base = 0x16000, .len = 0x150, 106 + .features = RGB_MSM8996_MASK, 107 + .sblk = &dpu_rgb_sblk, 108 + .xin_id = 5, 109 + .type = SSPP_TYPE_RGB, 110 + .clk_ctrl = DPU_CLK_CTRL_RGB1, 111 + }, { 112 + .name = "sspp_6", .id = SSPP_RGB2, 113 + .base = 0x18000, .len = 0x150, 114 + .features = RGB_MSM8996_MASK, 115 + .sblk = &dpu_rgb_sblk, 116 + .xin_id = 9, 117 + .type = SSPP_TYPE_RGB, 118 + .clk_ctrl = DPU_CLK_CTRL_RGB2, 119 + }, { 120 + .name = "sspp_7", .id = SSPP_RGB3, 121 + .base = 0x1a000, .len = 0x150, 122 + .features = RGB_MSM8996_MASK, 123 + .sblk = &dpu_rgb_sblk, 124 + .xin_id = 13, 125 + .type = SSPP_TYPE_RGB, 126 + .clk_ctrl = DPU_CLK_CTRL_RGB3, 127 + }, { 128 + .name = "sspp_8", .id = SSPP_DMA0, 129 + .base = 0x24000, .len = 0x150, 130 + .features = DMA_MSM8996_MASK, 131 + .sblk = &dpu_dma_sblk, 132 + .xin_id = 2, 133 + .type = SSPP_TYPE_DMA, 134 + .clk_ctrl = DPU_CLK_CTRL_DMA0, 135 + }, { 136 + .name = "sspp_9", .id = SSPP_DMA1, 137 + .base = 0x26000, .len = 0x150, 138 + .features = DMA_MSM8996_MASK, 139 + .sblk = &dpu_dma_sblk, 140 + .xin_id = 10, 141 + .type = SSPP_TYPE_DMA, 142 + .clk_ctrl = DPU_CLK_CTRL_DMA1, 143 + }, 144 + }; 145 + 146 + static const struct dpu_lm_cfg msm8996_lm[] = { 147 + { 148 + .name = "lm_0", .id = LM_0, 149 + .base = 0x44000, .len = 0x320, 150 + .features = MIXER_MSM8998_MASK, 151 + .sblk = &msm8998_lm_sblk, 152 + .lm_pair = LM_1, 153 + .pingpong = PINGPONG_0, 154 + .dspp = DSPP_0, 155 + }, { 156 + .name = "lm_1", .id = LM_1, 157 + .base = 0x45000, .len = 0x320, 158 + .features = MIXER_MSM8998_MASK, 159 + .sblk = &msm8998_lm_sblk, 160 + .lm_pair = LM_0, 161 + .pingpong = PINGPONG_1, 162 + .dspp = DSPP_1, 163 + }, { 164 + .name = "lm_2", .id = LM_2, 165 + .base = 0x46000, .len = 0x320, 166 + .features = MIXER_MSM8998_MASK, 167 + .sblk = &msm8998_lm_sblk, 168 + .lm_pair = LM_5, 169 + .pingpong = PINGPONG_2, 170 + }, { 171 + .name = "lm_5", .id = LM_5, 172 + .base = 0x49000, .len = 0x320, 173 + .features = MIXER_MSM8998_MASK, 174 + .sblk = &msm8998_lm_sblk, 175 + .lm_pair = LM_2, 176 + .pingpong = PINGPONG_3, 177 + }, 178 + }; 179 + 180 + static const struct dpu_pingpong_cfg msm8996_pp[] = { 181 + { 182 + .name = "pingpong_0", .id = PINGPONG_0, 183 + .base = 0x70000, .len = 0xd4, 184 + .features = PINGPONG_MSM8996_TE2_MASK, 185 + .sblk = &msm8996_pp_sblk_te, 186 + .intr_done = DPU_IRQ_IDX(MDP_SSPP_TOP0_INTR, 8), 187 + .intr_rdptr = DPU_IRQ_IDX(MDP_SSPP_TOP0_INTR, 12), 188 + }, { 189 + .name = "pingpong_1", .id = PINGPONG_1, 190 + .base = 0x70800, .len = 0xd4, 191 + .features = PINGPONG_MSM8996_TE2_MASK, 192 + .sblk = &msm8996_pp_sblk_te, 193 + .intr_done = DPU_IRQ_IDX(MDP_SSPP_TOP0_INTR, 9), 194 + .intr_rdptr = DPU_IRQ_IDX(MDP_SSPP_TOP0_INTR, 13), 195 + }, { 196 + .name = "pingpong_2", .id = PINGPONG_2, 197 + .base = 0x71000, .len = 0xd4, 198 + .features = PINGPONG_MSM8996_MASK, 199 + .sblk = &msm8996_pp_sblk, 200 + .intr_done = DPU_IRQ_IDX(MDP_SSPP_TOP0_INTR, 10), 201 + .intr_rdptr = DPU_IRQ_IDX(MDP_SSPP_TOP0_INTR, 14), 202 + }, { 203 + .name = "pingpong_3", .id = PINGPONG_3, 204 + .base = 0x71800, .len = 0xd4, 205 + .features = PINGPONG_MSM8996_MASK, 206 + .sblk = &msm8996_pp_sblk, 207 + .intr_done = DPU_IRQ_IDX(MDP_SSPP_TOP0_INTR, 11), 208 + .intr_rdptr = DPU_IRQ_IDX(MDP_SSPP_TOP0_INTR, 15), 209 + }, 210 + }; 211 + 212 + static const struct dpu_dsc_cfg msm8996_dsc[] = { 213 + { 214 + .name = "dsc_0", .id = DSC_0, 215 + .base = 0x80000, .len = 0x140, 216 + }, { 217 + .name = "dsc_1", .id = DSC_1, 218 + .base = 0x80400, .len = 0x140, 219 + }, 220 + }; 221 + 222 + static const struct dpu_dspp_cfg msm8996_dspp[] = { 223 + { 224 + .name = "dspp_0", .id = DSPP_0, 225 + .base = 0x54000, .len = 0x1800, 226 + .features = DSPP_SC7180_MASK, 227 + .sblk = &msm8998_dspp_sblk, 228 + }, { 229 + .name = "dspp_1", .id = DSPP_1, 230 + .base = 0x56000, .len = 0x1800, 231 + .features = DSPP_SC7180_MASK, 232 + .sblk = &msm8998_dspp_sblk, 233 + }, 234 + }; 235 + 236 + static const struct dpu_intf_cfg msm8996_intf[] = { 237 + { 238 + .name = "intf_0", .id = INTF_0, 239 + .base = 0x6a000, .len = 0x268, 240 + .type = INTF_NONE, 241 + .prog_fetch_lines_worst_case = 25, 242 + .intr_underrun = DPU_IRQ_IDX(MDP_SSPP_TOP0_INTR, 24), 243 + .intr_vsync = DPU_IRQ_IDX(MDP_SSPP_TOP0_INTR, 25), 244 + .intr_tear_rd_ptr = -1, 245 + }, { 246 + .name = "intf_1", .id = INTF_1, 247 + .base = 0x6a800, .len = 0x268, 248 + .type = INTF_DSI, 249 + .controller_id = MSM_DSI_CONTROLLER_0, 250 + .prog_fetch_lines_worst_case = 25, 251 + .intr_underrun = DPU_IRQ_IDX(MDP_SSPP_TOP0_INTR, 26), 252 + .intr_vsync = DPU_IRQ_IDX(MDP_SSPP_TOP0_INTR, 27), 253 + .intr_tear_rd_ptr = -1, 254 + }, { 255 + .name = "intf_2", .id = INTF_2, 256 + .base = 0x6b000, .len = 0x268, 257 + .type = INTF_DSI, 258 + .controller_id = MSM_DSI_CONTROLLER_1, 259 + .prog_fetch_lines_worst_case = 25, 260 + .intr_underrun = DPU_IRQ_IDX(MDP_SSPP_TOP0_INTR, 28), 261 + .intr_vsync = DPU_IRQ_IDX(MDP_SSPP_TOP0_INTR, 29), 262 + .intr_tear_rd_ptr = -1, 263 + }, { 264 + .name = "intf_3", .id = INTF_3, 265 + .base = 0x6b800, .len = 0x268, 266 + .type = INTF_HDMI, 267 + .prog_fetch_lines_worst_case = 25, 268 + .intr_underrun = DPU_IRQ_IDX(MDP_SSPP_TOP0_INTR, 30), 269 + .intr_vsync = DPU_IRQ_IDX(MDP_SSPP_TOP0_INTR, 31), 270 + .intr_tear_rd_ptr = -1, 271 + }, 272 + }; 273 + 274 + static const struct dpu_perf_cfg msm8996_perf_data = { 275 + .max_bw_low = 9600000, 276 + .max_bw_high = 9600000, 277 + .min_core_ib = 2400000, 278 + .min_llcc_ib = 0, /* No LLCC on this SoC */ 279 + .min_dram_ib = 800000, 280 + .undersized_prefill_lines = 2, 281 + .xtra_prefill_lines = 2, 282 + .dest_scale_prefill_lines = 3, 283 + .macrotile_prefill_lines = 4, 284 + .yuv_nv12_prefill_lines = 8, 285 + .linear_prefill_lines = 1, 286 + .downscaling_prefill_lines = 1, 287 + .amortizable_threshold = 25, 288 + .min_prefill_lines = 21, 289 + .danger_lut_tbl = {0xf, 0xffff, 0x0}, 290 + .safe_lut_tbl = {0xfffc, 0xff00, 0xffff}, 291 + .qos_lut_tbl = { 292 + {.nentry = ARRAY_SIZE(msm8998_qos_linear), 293 + .entries = msm8998_qos_linear 294 + }, 295 + {.nentry = ARRAY_SIZE(msm8998_qos_macrotile), 296 + .entries = msm8998_qos_macrotile 297 + }, 298 + {.nentry = ARRAY_SIZE(msm8998_qos_nrt), 299 + .entries = msm8998_qos_nrt 300 + }, 301 + }, 302 + .cdp_cfg = { 303 + {.rd_enable = 1, .wr_enable = 1}, 304 + {.rd_enable = 1, .wr_enable = 0} 305 + }, 306 + .clk_inefficiency_factor = 105, 307 + .bw_inefficiency_factor = 120, 308 + }; 309 + 310 + static const struct dpu_mdss_version msm8996_mdss_ver = { 311 + .core_major_ver = 1, 312 + .core_minor_ver = 7, 313 + }; 314 + 315 + const struct dpu_mdss_cfg dpu_msm8996_cfg = { 316 + .mdss_ver = &msm8996_mdss_ver, 317 + .caps = &msm8996_dpu_caps, 318 + .mdp = msm8996_mdp, 319 + .ctl_count = ARRAY_SIZE(msm8996_ctl), 320 + .ctl = msm8996_ctl, 321 + .sspp_count = ARRAY_SIZE(msm8996_sspp), 322 + .sspp = msm8996_sspp, 323 + .mixer_count = ARRAY_SIZE(msm8996_lm), 324 + .mixer = msm8996_lm, 325 + .dspp_count = ARRAY_SIZE(msm8996_dspp), 326 + .dspp = msm8996_dspp, 327 + .pingpong_count = ARRAY_SIZE(msm8996_pp), 328 + .pingpong = msm8996_pp, 329 + .dsc_count = ARRAY_SIZE(msm8996_dsc), 330 + .dsc = msm8996_dsc, 331 + .intf_count = ARRAY_SIZE(msm8996_intf), 332 + .intf = msm8996_intf, 333 + .vbif_count = ARRAY_SIZE(msm8996_vbif), 334 + .vbif = msm8996_vbif, 335 + .perf = &msm8996_perf_data, 336 + }; 337 + 338 + #endif
-12
drivers/gpu/drm/msm/disp/dpu1/catalog/dpu_3_0_msm8998.h
··· 157 157 .lm_pair = LM_5, 158 158 .pingpong = PINGPONG_2, 159 159 }, { 160 - .name = "lm_3", .id = LM_3, 161 - .base = 0x47000, .len = 0x320, 162 - .features = MIXER_MSM8998_MASK, 163 - .sblk = &msm8998_lm_sblk, 164 - .pingpong = PINGPONG_NONE, 165 - }, { 166 - .name = "lm_4", .id = LM_4, 167 - .base = 0x48000, .len = 0x320, 168 - .features = MIXER_MSM8998_MASK, 169 - .sblk = &msm8998_lm_sblk, 170 - .pingpong = PINGPONG_NONE, 171 - }, { 172 160 .name = "lm_5", .id = LM_5, 173 161 .base = 0x49000, .len = 0x320, 174 162 .features = MIXER_MSM8998_MASK,
+1 -13
drivers/gpu/drm/msm/disp/dpu1/catalog/dpu_4_0_sdm845.h
··· 156 156 .pingpong = PINGPONG_2, 157 157 .dspp = DSPP_2, 158 158 }, { 159 - .name = "lm_3", .id = LM_3, 160 - .base = 0x0, .len = 0x320, 161 - .features = MIXER_SDM845_MASK, 162 - .sblk = &sdm845_lm_sblk, 163 - .pingpong = PINGPONG_NONE, 164 - .dspp = DSPP_3, 165 - }, { 166 - .name = "lm_4", .id = LM_4, 167 - .base = 0x0, .len = 0x320, 168 - .features = MIXER_SDM845_MASK, 169 - .sblk = &sdm845_lm_sblk, 170 - .pingpong = PINGPONG_NONE, 171 - }, { 172 159 .name = "lm_5", .id = LM_5, 173 160 .base = 0x49000, .len = 0x320, 174 161 .features = MIXER_SDM845_MASK, 175 162 .sblk = &sdm845_lm_sblk, 176 163 .lm_pair = LM_2, 177 164 .pingpong = PINGPONG_3, 165 + .dspp = DSPP_3, 178 166 }, 179 167 }; 180 168
+485
drivers/gpu/drm/msm/disp/dpu1/catalog/dpu_8_4_sa8775p.h
··· 1 + /* SPDX-License-Identifier: GPL-2.0-only */ 2 + /* 3 + * Copyright (c) 2024 Qualcomm Innovation Center, Inc. All rights reserved. 4 + */ 5 + 6 + #ifndef _DPU_8_4_SA8775P_H 7 + #define _DPU_8_4_SA8775P_H 8 + 9 + static const struct dpu_caps sa8775p_dpu_caps = { 10 + .max_mixer_width = DEFAULT_DPU_OUTPUT_LINE_WIDTH, 11 + .max_mixer_blendstages = 0xb, 12 + .has_src_split = true, 13 + .has_dim_layer = true, 14 + .has_idle_pc = true, 15 + .has_3d_merge = true, 16 + .max_linewidth = 5120, 17 + .pixel_ram_size = DEFAULT_PIXEL_RAM_SIZE, 18 + }; 19 + 20 + static const struct dpu_mdp_cfg sa8775p_mdp = { 21 + .name = "top_0", 22 + .base = 0x0, .len = 0x494, 23 + .features = BIT(DPU_MDP_PERIPH_0_REMOVED), 24 + .clk_ctrls = { 25 + [DPU_CLK_CTRL_VIG0] = { .reg_off = 0x2ac, .bit_off = 0 }, 26 + [DPU_CLK_CTRL_VIG1] = { .reg_off = 0x2b4, .bit_off = 0 }, 27 + [DPU_CLK_CTRL_VIG2] = { .reg_off = 0x2bc, .bit_off = 0 }, 28 + [DPU_CLK_CTRL_VIG3] = { .reg_off = 0x2c4, .bit_off = 0 }, 29 + [DPU_CLK_CTRL_DMA0] = { .reg_off = 0x2ac, .bit_off = 8 }, 30 + [DPU_CLK_CTRL_DMA1] = { .reg_off = 0x2b4, .bit_off = 8 }, 31 + [DPU_CLK_CTRL_DMA2] = { .reg_off = 0x2bc, .bit_off = 8 }, 32 + [DPU_CLK_CTRL_DMA3] = { .reg_off = 0x2c4, .bit_off = 8 }, 33 + [DPU_CLK_CTRL_WB2] = { .reg_off = 0x2bc, .bit_off = 16 }, 34 + [DPU_CLK_CTRL_REG_DMA] = { .reg_off = 0x2bc, .bit_off = 20 }, 35 + }, 36 + }; 37 + 38 + /* FIXME: get rid of DPU_CTL_SPLIT_DISPLAY in favour of proper ACTIVE_CTL support */ 39 + static const struct dpu_ctl_cfg sa8775p_ctl[] = { 40 + { 41 + .name = "ctl_0", .id = CTL_0, 42 + .base = 0x15000, .len = 0x204, 43 + .features = BIT(DPU_CTL_SPLIT_DISPLAY) | CTL_SC7280_MASK, 44 + .intr_start = DPU_IRQ_IDX(MDP_SSPP_TOP0_INTR2, 9), 45 + }, { 46 + .name = "ctl_1", .id = CTL_1, 47 + .base = 0x16000, .len = 0x204, 48 + .features = BIT(DPU_CTL_SPLIT_DISPLAY) | CTL_SC7280_MASK, 49 + .intr_start = DPU_IRQ_IDX(MDP_SSPP_TOP0_INTR2, 10), 50 + }, { 51 + .name = "ctl_2", .id = CTL_2, 52 + .base = 0x17000, .len = 0x204, 53 + .features = CTL_SC7280_MASK, 54 + .intr_start = DPU_IRQ_IDX(MDP_SSPP_TOP0_INTR2, 11), 55 + }, { 56 + .name = "ctl_3", .id = CTL_3, 57 + .base = 0x18000, .len = 0x204, 58 + .features = CTL_SC7280_MASK, 59 + .intr_start = DPU_IRQ_IDX(MDP_SSPP_TOP0_INTR2, 12), 60 + }, { 61 + .name = "ctl_4", .id = CTL_4, 62 + .base = 0x19000, .len = 0x204, 63 + .features = CTL_SC7280_MASK, 64 + .intr_start = DPU_IRQ_IDX(MDP_SSPP_TOP0_INTR2, 13), 65 + }, { 66 + .name = "ctl_5", .id = CTL_5, 67 + .base = 0x1a000, .len = 0x204, 68 + .features = CTL_SC7280_MASK, 69 + .intr_start = DPU_IRQ_IDX(MDP_SSPP_TOP0_INTR2, 23), 70 + }, 71 + }; 72 + 73 + static const struct dpu_sspp_cfg sa8775p_sspp[] = { 74 + { 75 + .name = "sspp_0", .id = SSPP_VIG0, 76 + .base = 0x4000, .len = 0x32c, 77 + .features = VIG_SDM845_MASK_SDMA, 78 + .sblk = &dpu_vig_sblk_qseed3_3_1, 79 + .xin_id = 0, 80 + .type = SSPP_TYPE_VIG, 81 + .clk_ctrl = DPU_CLK_CTRL_VIG0, 82 + }, { 83 + .name = "sspp_1", .id = SSPP_VIG1, 84 + .base = 0x6000, .len = 0x32c, 85 + .features = VIG_SDM845_MASK_SDMA, 86 + .sblk = &dpu_vig_sblk_qseed3_3_1, 87 + .xin_id = 4, 88 + .type = SSPP_TYPE_VIG, 89 + .clk_ctrl = DPU_CLK_CTRL_VIG1, 90 + }, { 91 + .name = "sspp_2", .id = SSPP_VIG2, 92 + .base = 0x8000, .len = 0x32c, 93 + .features = VIG_SDM845_MASK_SDMA, 94 + .sblk = &dpu_vig_sblk_qseed3_3_1, 95 + .xin_id = 8, 96 + .type = SSPP_TYPE_VIG, 97 + .clk_ctrl = DPU_CLK_CTRL_VIG2, 98 + }, { 99 + .name = "sspp_3", .id = SSPP_VIG3, 100 + .base = 0xa000, .len = 0x32c, 101 + .features = VIG_SDM845_MASK_SDMA, 102 + .sblk = &dpu_vig_sblk_qseed3_3_1, 103 + .xin_id = 12, 104 + .type = SSPP_TYPE_VIG, 105 + .clk_ctrl = DPU_CLK_CTRL_VIG3, 106 + }, { 107 + .name = "sspp_8", .id = SSPP_DMA0, 108 + .base = 0x24000, .len = 0x32c, 109 + .features = DMA_SDM845_MASK_SDMA, 110 + .sblk = &dpu_dma_sblk, 111 + .xin_id = 1, 112 + .type = SSPP_TYPE_DMA, 113 + .clk_ctrl = DPU_CLK_CTRL_DMA0, 114 + }, { 115 + .name = "sspp_9", .id = SSPP_DMA1, 116 + .base = 0x26000, .len = 0x32c, 117 + .features = DMA_SDM845_MASK_SDMA, 118 + .sblk = &dpu_dma_sblk, 119 + .xin_id = 5, 120 + .type = SSPP_TYPE_DMA, 121 + .clk_ctrl = DPU_CLK_CTRL_DMA1, 122 + }, { 123 + .name = "sspp_10", .id = SSPP_DMA2, 124 + .base = 0x28000, .len = 0x32c, 125 + .features = DMA_CURSOR_SDM845_MASK_SDMA, 126 + .sblk = &dpu_dma_sblk, 127 + .xin_id = 9, 128 + .type = SSPP_TYPE_DMA, 129 + .clk_ctrl = DPU_CLK_CTRL_DMA2, 130 + }, { 131 + .name = "sspp_11", .id = SSPP_DMA3, 132 + .base = 0x2a000, .len = 0x32c, 133 + .features = DMA_CURSOR_SDM845_MASK_SDMA, 134 + .sblk = &dpu_dma_sblk, 135 + .xin_id = 13, 136 + .type = SSPP_TYPE_DMA, 137 + .clk_ctrl = DPU_CLK_CTRL_DMA3, 138 + }, 139 + }; 140 + 141 + static const struct dpu_lm_cfg sa8775p_lm[] = { 142 + { 143 + .name = "lm_0", .id = LM_0, 144 + .base = 0x44000, .len = 0x400, 145 + .features = MIXER_SDM845_MASK, 146 + .sblk = &sdm845_lm_sblk, 147 + .lm_pair = LM_1, 148 + .pingpong = PINGPONG_0, 149 + .dspp = DSPP_0, 150 + }, { 151 + .name = "lm_1", .id = LM_1, 152 + .base = 0x45000, .len = 0x400, 153 + .features = MIXER_SDM845_MASK, 154 + .sblk = &sdm845_lm_sblk, 155 + .lm_pair = LM_0, 156 + .pingpong = PINGPONG_1, 157 + .dspp = DSPP_1, 158 + }, { 159 + .name = "lm_2", .id = LM_2, 160 + .base = 0x46000, .len = 0x400, 161 + .features = MIXER_SDM845_MASK, 162 + .sblk = &sdm845_lm_sblk, 163 + .lm_pair = LM_3, 164 + .pingpong = PINGPONG_2, 165 + .dspp = DSPP_2, 166 + }, { 167 + .name = "lm_3", .id = LM_3, 168 + .base = 0x47000, .len = 0x400, 169 + .features = MIXER_SDM845_MASK, 170 + .sblk = &sdm845_lm_sblk, 171 + .lm_pair = LM_2, 172 + .pingpong = PINGPONG_3, 173 + .dspp = DSPP_3, 174 + }, { 175 + .name = "lm_4", .id = LM_4, 176 + .base = 0x48000, .len = 0x400, 177 + .features = MIXER_SDM845_MASK, 178 + .sblk = &sdm845_lm_sblk, 179 + .lm_pair = LM_5, 180 + .pingpong = PINGPONG_4, 181 + }, { 182 + .name = "lm_5", .id = LM_5, 183 + .base = 0x49000, .len = 0x400, 184 + .features = MIXER_SDM845_MASK, 185 + .sblk = &sdm845_lm_sblk, 186 + .lm_pair = LM_4, 187 + .pingpong = PINGPONG_5, 188 + }, 189 + }; 190 + 191 + static const struct dpu_dspp_cfg sa8775p_dspp[] = { 192 + { 193 + .name = "dspp_0", .id = DSPP_0, 194 + .base = 0x54000, .len = 0x1800, 195 + .features = DSPP_SC7180_MASK, 196 + .sblk = &sdm845_dspp_sblk, 197 + }, { 198 + .name = "dspp_1", .id = DSPP_1, 199 + .base = 0x56000, .len = 0x1800, 200 + .features = DSPP_SC7180_MASK, 201 + .sblk = &sdm845_dspp_sblk, 202 + }, { 203 + .name = "dspp_2", .id = DSPP_2, 204 + .base = 0x58000, .len = 0x1800, 205 + .features = DSPP_SC7180_MASK, 206 + .sblk = &sdm845_dspp_sblk, 207 + }, { 208 + .name = "dspp_3", .id = DSPP_3, 209 + .base = 0x5a000, .len = 0x1800, 210 + .features = DSPP_SC7180_MASK, 211 + .sblk = &sdm845_dspp_sblk, 212 + }, 213 + }; 214 + 215 + static const struct dpu_pingpong_cfg sa8775p_pp[] = { 216 + { 217 + .name = "pingpong_0", .id = PINGPONG_0, 218 + .base = 0x69000, .len = 0, 219 + .features = BIT(DPU_PINGPONG_DITHER), 220 + .sblk = &sc7280_pp_sblk, 221 + .merge_3d = MERGE_3D_0, 222 + .intr_done = DPU_IRQ_IDX(MDP_SSPP_TOP0_INTR, 8), 223 + }, { 224 + .name = "pingpong_1", .id = PINGPONG_1, 225 + .base = 0x6a000, .len = 0, 226 + .features = BIT(DPU_PINGPONG_DITHER), 227 + .sblk = &sc7280_pp_sblk, 228 + .merge_3d = MERGE_3D_0, 229 + .intr_done = DPU_IRQ_IDX(MDP_SSPP_TOP0_INTR, 9), 230 + }, { 231 + .name = "pingpong_2", .id = PINGPONG_2, 232 + .base = 0x6b000, .len = 0, 233 + .features = BIT(DPU_PINGPONG_DITHER), 234 + .sblk = &sc7280_pp_sblk, 235 + .merge_3d = MERGE_3D_1, 236 + .intr_done = DPU_IRQ_IDX(MDP_SSPP_TOP0_INTR, 10), 237 + }, { 238 + .name = "pingpong_3", .id = PINGPONG_3, 239 + .base = 0x6c000, .len = 0, 240 + .features = BIT(DPU_PINGPONG_DITHER), 241 + .sblk = &sc7280_pp_sblk, 242 + .merge_3d = MERGE_3D_1, 243 + .intr_done = DPU_IRQ_IDX(MDP_SSPP_TOP0_INTR, 11), 244 + }, { 245 + .name = "pingpong_4", .id = PINGPONG_4, 246 + .base = 0x6d000, .len = 0, 247 + .features = BIT(DPU_PINGPONG_DITHER), 248 + .sblk = &sc7280_pp_sblk, 249 + .merge_3d = MERGE_3D_2, 250 + .intr_done = DPU_IRQ_IDX(MDP_SSPP_TOP0_INTR2, 30), 251 + }, { 252 + .name = "pingpong_5", .id = PINGPONG_5, 253 + .base = 0x6e000, .len = 0, 254 + .features = BIT(DPU_PINGPONG_DITHER), 255 + .sblk = &sc7280_pp_sblk, 256 + .merge_3d = MERGE_3D_2, 257 + .intr_done = DPU_IRQ_IDX(MDP_SSPP_TOP0_INTR2, 31), 258 + }, { 259 + .name = "pingpong_6", .id = PINGPONG_6, 260 + .base = 0x65800, .len = 0, 261 + .features = BIT(DPU_PINGPONG_DITHER), 262 + .sblk = &sc7280_pp_sblk, 263 + .merge_3d = MERGE_3D_3, 264 + }, { 265 + .name = "pingpong_7", .id = PINGPONG_7, 266 + .base = 0x65c00, .len = 0, 267 + .features = BIT(DPU_PINGPONG_DITHER), 268 + .sblk = &sc7280_pp_sblk, 269 + .merge_3d = MERGE_3D_3, 270 + }, 271 + }; 272 + 273 + static const struct dpu_merge_3d_cfg sa8775p_merge_3d[] = { 274 + { 275 + .name = "merge_3d_0", .id = MERGE_3D_0, 276 + .base = 0x4e000, .len = 0x8, 277 + }, { 278 + .name = "merge_3d_1", .id = MERGE_3D_1, 279 + .base = 0x4f000, .len = 0x8, 280 + }, { 281 + .name = "merge_3d_2", .id = MERGE_3D_2, 282 + .base = 0x50000, .len = 0x8, 283 + }, { 284 + .name = "merge_3d_3", .id = MERGE_3D_3, 285 + .base = 0x65f00, .len = 0x8, 286 + }, 287 + }; 288 + 289 + /* 290 + * NOTE: Each display compression engine (DCE) contains dual hard 291 + * slice DSC encoders so both share same base address but with 292 + * its own different sub block address. 293 + */ 294 + static const struct dpu_dsc_cfg sa8775p_dsc[] = { 295 + { 296 + .name = "dce_0_0", .id = DSC_0, 297 + .base = 0x80000, .len = 0x4, 298 + .features = BIT(DPU_DSC_HW_REV_1_2), 299 + .sblk = &dsc_sblk_0, 300 + }, { 301 + .name = "dce_0_1", .id = DSC_1, 302 + .base = 0x80000, .len = 0x4, 303 + .features = BIT(DPU_DSC_HW_REV_1_2), 304 + .sblk = &dsc_sblk_1, 305 + }, { 306 + .name = "dce_1_0", .id = DSC_2, 307 + .base = 0x81000, .len = 0x4, 308 + .features = BIT(DPU_DSC_HW_REV_1_2) | BIT(DPU_DSC_NATIVE_42x_EN), 309 + .sblk = &dsc_sblk_0, 310 + }, { 311 + .name = "dce_1_1", .id = DSC_3, 312 + .base = 0x81000, .len = 0x4, 313 + .features = BIT(DPU_DSC_HW_REV_1_2) | BIT(DPU_DSC_NATIVE_42x_EN), 314 + .sblk = &dsc_sblk_1, 315 + }, { 316 + .name = "dce_2_0", .id = DSC_4, 317 + .base = 0x82000, .len = 0x4, 318 + .features = BIT(DPU_DSC_HW_REV_1_2), 319 + .sblk = &dsc_sblk_0, 320 + }, { 321 + .name = "dce_2_1", .id = DSC_5, 322 + .base = 0x82000, .len = 0x4, 323 + .features = BIT(DPU_DSC_HW_REV_1_2), 324 + .sblk = &dsc_sblk_1, 325 + }, 326 + }; 327 + 328 + static const struct dpu_wb_cfg sa8775p_wb[] = { 329 + { 330 + .name = "wb_2", .id = WB_2, 331 + .base = 0x65000, .len = 0x2c8, 332 + .features = WB_SM8250_MASK, 333 + .format_list = wb2_formats_rgb_yuv, 334 + .num_formats = ARRAY_SIZE(wb2_formats_rgb_yuv), 335 + .clk_ctrl = DPU_CLK_CTRL_WB2, 336 + .xin_id = 6, 337 + .vbif_idx = VBIF_RT, 338 + .maxlinewidth = 4096, 339 + .intr_wb_done = DPU_IRQ_IDX(MDP_SSPP_TOP0_INTR, 4), 340 + }, 341 + }; 342 + 343 + /* TODO: INTF 3, 6, 7 and 8 are used for MST, marked as INTF_NONE for now */ 344 + static const struct dpu_intf_cfg sa8775p_intf[] = { 345 + { 346 + .name = "intf_0", .id = INTF_0, 347 + .base = 0x34000, .len = 0x280, 348 + .features = INTF_SC7280_MASK, 349 + .type = INTF_DP, 350 + .controller_id = MSM_DP_CONTROLLER_0, 351 + .prog_fetch_lines_worst_case = 24, 352 + .intr_underrun = DPU_IRQ_IDX(MDP_SSPP_TOP0_INTR, 24), 353 + .intr_vsync = DPU_IRQ_IDX(MDP_SSPP_TOP0_INTR, 25), 354 + }, { 355 + .name = "intf_1", .id = INTF_1, 356 + .base = 0x35000, .len = 0x300, 357 + .features = INTF_SC7280_MASK, 358 + .type = INTF_DSI, 359 + .controller_id = MSM_DSI_CONTROLLER_0, 360 + .prog_fetch_lines_worst_case = 24, 361 + .intr_underrun = DPU_IRQ_IDX(MDP_SSPP_TOP0_INTR, 26), 362 + .intr_vsync = DPU_IRQ_IDX(MDP_SSPP_TOP0_INTR, 27), 363 + .intr_tear_rd_ptr = DPU_IRQ_IDX(MDP_INTF1_TEAR_INTR, 2), 364 + }, { 365 + .name = "intf_2", .id = INTF_2, 366 + .base = 0x36000, .len = 0x300, 367 + .features = INTF_SC7280_MASK, 368 + .type = INTF_DSI, 369 + .controller_id = MSM_DSI_CONTROLLER_1, 370 + .prog_fetch_lines_worst_case = 24, 371 + .intr_underrun = DPU_IRQ_IDX(MDP_SSPP_TOP0_INTR, 28), 372 + .intr_vsync = DPU_IRQ_IDX(MDP_SSPP_TOP0_INTR, 29), 373 + .intr_tear_rd_ptr = DPU_IRQ_IDX(MDP_INTF2_TEAR_INTR, 2), 374 + }, { 375 + .name = "intf_3", .id = INTF_3, 376 + .base = 0x37000, .len = 0x280, 377 + .features = INTF_SC7280_MASK, 378 + .type = INTF_NONE, 379 + .controller_id = MSM_DP_CONTROLLER_0, /* pair with intf_0 for DP MST */ 380 + .prog_fetch_lines_worst_case = 24, 381 + .intr_underrun = DPU_IRQ_IDX(MDP_SSPP_TOP0_INTR, 30), 382 + .intr_vsync = DPU_IRQ_IDX(MDP_SSPP_TOP0_INTR, 31), 383 + }, { 384 + .name = "intf_4", .id = INTF_4, 385 + .base = 0x38000, .len = 0x280, 386 + .features = INTF_SC7280_MASK, 387 + .type = INTF_DP, 388 + .controller_id = MSM_DP_CONTROLLER_1, 389 + .prog_fetch_lines_worst_case = 24, 390 + .intr_underrun = DPU_IRQ_IDX(MDP_SSPP_TOP0_INTR, 20), 391 + .intr_vsync = DPU_IRQ_IDX(MDP_SSPP_TOP0_INTR, 21), 392 + }, { 393 + .name = "intf_6", .id = INTF_6, 394 + .base = 0x3A000, .len = 0x280, 395 + .features = INTF_SC7280_MASK, 396 + .type = INTF_NONE, 397 + .controller_id = MSM_DP_CONTROLLER_0, /* pair with intf_0 for DP MST */ 398 + .prog_fetch_lines_worst_case = 24, 399 + .intr_underrun = DPU_IRQ_IDX(MDP_SSPP_TOP0_INTR, 17), 400 + .intr_vsync = DPU_IRQ_IDX(MDP_SSPP_TOP0_INTR, 16), 401 + }, { 402 + .name = "intf_7", .id = INTF_7, 403 + .base = 0x3b000, .len = 0x280, 404 + .features = INTF_SC7280_MASK, 405 + .type = INTF_NONE, 406 + .controller_id = MSM_DP_CONTROLLER_0, /* pair with intf_0 for DP MST */ 407 + .prog_fetch_lines_worst_case = 24, 408 + .intr_underrun = DPU_IRQ_IDX(MDP_SSPP_TOP0_INTR, 18), 409 + .intr_vsync = DPU_IRQ_IDX(MDP_SSPP_TOP0_INTR, 19), 410 + }, { 411 + .name = "intf_8", .id = INTF_8, 412 + .base = 0x3c000, .len = 0x280, 413 + .features = INTF_SC7280_MASK, 414 + .type = INTF_NONE, 415 + .controller_id = MSM_DP_CONTROLLER_1, /* pair with intf_4 for DP MST */ 416 + .prog_fetch_lines_worst_case = 24, 417 + .intr_underrun = DPU_IRQ_IDX(MDP_SSPP_TOP0_INTR, 12), 418 + .intr_vsync = DPU_IRQ_IDX(MDP_SSPP_TOP0_INTR, 13), 419 + }, 420 + }; 421 + 422 + static const struct dpu_perf_cfg sa8775p_perf_data = { 423 + .max_bw_low = 13600000, 424 + .max_bw_high = 18200000, 425 + .min_core_ib = 2500000, 426 + .min_llcc_ib = 0, 427 + .min_dram_ib = 800000, 428 + .min_prefill_lines = 35, 429 + /* FIXME: lut tables */ 430 + .danger_lut_tbl = {0x3ffff, 0x3ffff, 0x0}, 431 + .safe_lut_tbl = {0xfff0, 0xfff0, 0x1}, 432 + .qos_lut_tbl = { 433 + {.nentry = ARRAY_SIZE(sm6350_qos_linear_macrotile), 434 + .entries = sm6350_qos_linear_macrotile 435 + }, 436 + {.nentry = ARRAY_SIZE(sm6350_qos_linear_macrotile), 437 + .entries = sm6350_qos_linear_macrotile 438 + }, 439 + {.nentry = ARRAY_SIZE(sc7180_qos_nrt), 440 + .entries = sc7180_qos_nrt 441 + }, 442 + /* TODO: macrotile-qseed is different from macrotile */ 443 + }, 444 + .cdp_cfg = { 445 + {.rd_enable = 1, .wr_enable = 1}, 446 + {.rd_enable = 1, .wr_enable = 0} 447 + }, 448 + .clk_inefficiency_factor = 105, 449 + .bw_inefficiency_factor = 120, 450 + }; 451 + 452 + static const struct dpu_mdss_version sa8775p_mdss_ver = { 453 + .core_major_ver = 8, 454 + .core_minor_ver = 4, 455 + }; 456 + 457 + const struct dpu_mdss_cfg dpu_sa8775p_cfg = { 458 + .mdss_ver = &sa8775p_mdss_ver, 459 + .caps = &sa8775p_dpu_caps, 460 + .mdp = &sa8775p_mdp, 461 + .cdm = &sc7280_cdm, 462 + .ctl_count = ARRAY_SIZE(sa8775p_ctl), 463 + .ctl = sa8775p_ctl, 464 + .sspp_count = ARRAY_SIZE(sa8775p_sspp), 465 + .sspp = sa8775p_sspp, 466 + .mixer_count = ARRAY_SIZE(sa8775p_lm), 467 + .mixer = sa8775p_lm, 468 + .dspp_count = ARRAY_SIZE(sa8775p_dspp), 469 + .dspp = sa8775p_dspp, 470 + .pingpong_count = ARRAY_SIZE(sa8775p_pp), 471 + .pingpong = sa8775p_pp, 472 + .dsc_count = ARRAY_SIZE(sa8775p_dsc), 473 + .dsc = sa8775p_dsc, 474 + .merge_3d_count = ARRAY_SIZE(sa8775p_merge_3d), 475 + .merge_3d = sa8775p_merge_3d, 476 + .wb_count = ARRAY_SIZE(sa8775p_wb), 477 + .wb = sa8775p_wb, 478 + .intf_count = ARRAY_SIZE(sa8775p_intf), 479 + .intf = sa8775p_intf, 480 + .vbif_count = ARRAY_SIZE(sdm845_vbif), 481 + .vbif = sdm845_vbif, 482 + .perf = &sa8775p_perf_data, 483 + }; 484 + 485 + #endif
+14
drivers/gpu/drm/msm/disp/dpu1/dpu_crtc.c
··· 1230 1230 return 0; 1231 1231 } 1232 1232 1233 + static enum drm_mode_status dpu_crtc_mode_valid(struct drm_crtc *crtc, 1234 + const struct drm_display_mode *mode) 1235 + { 1236 + struct dpu_kms *dpu_kms = _dpu_crtc_get_kms(crtc); 1237 + 1238 + /* 1239 + * max crtc width is equal to the max mixer width * 2 and max height is 4K 1240 + */ 1241 + return drm_mode_validate_size(mode, 1242 + 2 * dpu_kms->catalog->caps->max_mixer_width, 1243 + 4096); 1244 + } 1245 + 1233 1246 int dpu_crtc_vblank(struct drm_crtc *crtc, bool en) 1234 1247 { 1235 1248 struct dpu_crtc *dpu_crtc = to_dpu_crtc(crtc); ··· 1458 1445 .atomic_check = dpu_crtc_atomic_check, 1459 1446 .atomic_begin = dpu_crtc_atomic_begin, 1460 1447 .atomic_flush = dpu_crtc_atomic_flush, 1448 + .mode_valid = dpu_crtc_mode_valid, 1461 1449 .get_scanout_position = dpu_crtc_get_scanout_position, 1462 1450 }; 1463 1451
+13 -24
drivers/gpu/drm/msm/disp/dpu1/dpu_encoder_phys_wb.c
··· 166 166 /** 167 167 * dpu_encoder_phys_wb_setup_fb - setup output framebuffer 168 168 * @phys_enc: Pointer to physical encoder 169 - * @fb: Pointer to output framebuffer 169 + * @format: Format of the framebuffer 170 170 */ 171 171 static void dpu_encoder_phys_wb_setup_fb(struct dpu_encoder_phys *phys_enc, 172 - struct drm_framebuffer *fb) 172 + const struct msm_format *format) 173 173 { 174 174 struct dpu_encoder_phys_wb *wb_enc = to_dpu_encoder_phys_wb(phys_enc); 175 175 struct dpu_hw_wb *hw_wb; ··· 193 193 hw_wb->ops.setup_roi(hw_wb, wb_cfg); 194 194 195 195 if (hw_wb->ops.setup_outformat) 196 - hw_wb->ops.setup_outformat(hw_wb, wb_cfg); 196 + hw_wb->ops.setup_outformat(hw_wb, wb_cfg, format); 197 197 198 198 if (hw_wb->ops.setup_cdp) { 199 199 const struct dpu_perf_cfg *perf = phys_enc->dpu_kms->catalog->perf; 200 200 201 - hw_wb->ops.setup_cdp(hw_wb, wb_cfg->dest.format, 201 + hw_wb->ops.setup_cdp(hw_wb, format, 202 202 perf->cdp_cfg[DPU_PERF_CDP_USAGE_NRT].wr_enable); 203 203 } 204 204 ··· 321 321 { 322 322 struct dpu_hw_wb *hw_wb = phys_enc->hw_wb; 323 323 struct drm_display_mode mode = phys_enc->cached_mode; 324 - struct drm_framebuffer *fb = NULL; 325 324 struct dpu_encoder_phys_wb *wb_enc = to_dpu_encoder_phys_wb(phys_enc); 326 - struct drm_writeback_job *wb_job; 327 325 const struct msm_format *format; 328 - const struct msm_format *dpu_fmt; 329 326 330 - wb_job = wb_enc->wb_job; 331 327 format = msm_framebuffer_format(wb_enc->wb_job->fb); 332 - dpu_fmt = mdp_get_format(&phys_enc->dpu_kms->base, format->pixel_format, wb_job->fb->modifier); 333 328 334 329 DPU_DEBUG("[mode_set:%d, \"%s\",%d,%d]\n", 335 330 hw_wb->idx - WB_0, mode.name, ··· 336 341 337 342 dpu_encoder_phys_wb_set_qos(phys_enc); 338 343 339 - dpu_encoder_phys_wb_setup_fb(phys_enc, fb); 344 + dpu_encoder_phys_wb_setup_fb(phys_enc, format); 340 345 341 - dpu_encoder_helper_phys_setup_cdm(phys_enc, dpu_fmt, CDM_CDWN_OUTPUT_WB); 346 + dpu_encoder_helper_phys_setup_cdm(phys_enc, format, CDM_CDWN_OUTPUT_WB); 342 347 343 348 dpu_encoder_phys_wb_setup_ctl(phys_enc); 344 349 } ··· 582 587 583 588 format = msm_framebuffer_format(job->fb); 584 589 585 - wb_cfg->dest.format = mdp_get_format(&phys_enc->dpu_kms->base, 586 - format->pixel_format, job->fb->modifier); 587 - if (!wb_cfg->dest.format) { 588 - /* this error should be detected during atomic_check */ 589 - DPU_ERROR("failed to get format %p4cc\n", &format->pixel_format); 590 + ret = dpu_format_populate_plane_sizes(job->fb, &wb_cfg->dest); 591 + if (ret) { 592 + DPU_DEBUG("failed to populate plane sizes%d\n", ret); 590 593 return; 591 594 } 592 595 593 - ret = dpu_format_populate_layout(aspace, job->fb, &wb_cfg->dest); 594 - if (ret) { 595 - DPU_DEBUG("failed to populate layout %d\n", ret); 596 - return; 597 - } 596 + dpu_format_populate_addrs(aspace, job->fb, &wb_cfg->dest); 598 597 599 598 wb_cfg->dest.width = job->fb->width; 600 599 wb_cfg->dest.height = job->fb->height; 601 - wb_cfg->dest.num_planes = wb_cfg->dest.format->num_planes; 600 + wb_cfg->dest.num_planes = format->num_planes; 602 601 603 - if ((wb_cfg->dest.format->fetch_type == MDP_PLANE_PLANAR) && 604 - (wb_cfg->dest.format->element[0] == C1_B_Cb)) 602 + if ((format->fetch_type == MDP_PLANE_PLANAR) && 603 + (format->element[0] == C1_B_Cb)) 605 604 swap(wb_cfg->dest.plane_addr[1], wb_cfg->dest.plane_addr[2]); 606 605 607 606 DPU_DEBUG("[fb_offset:%8.8x,%8.8x,%8.8x,%8.8x]\n",
+80 -165
drivers/gpu/drm/msm/disp/dpu1/dpu_formats.c
··· 13 13 14 14 #define DPU_UBWC_PLANE_SIZE_ALIGNMENT 4096 15 15 16 - #define DPU_MAX_IMG_WIDTH 0x3FFF 17 - #define DPU_MAX_IMG_HEIGHT 0x3FFF 18 - 19 16 /* 20 17 * struct dpu_media_color_map - maps drm format to media format 21 18 * @format: DRM base pixel format ··· 90 93 return color_fmt; 91 94 } 92 95 93 - static int _dpu_format_get_plane_sizes_ubwc( 96 + static int _dpu_format_populate_plane_sizes_ubwc( 94 97 const struct msm_format *fmt, 95 - const uint32_t width, 96 - const uint32_t height, 98 + struct drm_framebuffer *fb, 97 99 struct dpu_hw_fmt_layout *layout) 98 100 { 99 101 int i; ··· 100 104 bool meta = MSM_FORMAT_IS_UBWC(fmt); 101 105 102 106 memset(layout, 0, sizeof(struct dpu_hw_fmt_layout)); 103 - layout->format = fmt; 104 - layout->width = width; 105 - layout->height = height; 107 + layout->width = fb->width; 108 + layout->height = fb->height; 106 109 layout->num_planes = fmt->num_planes; 107 110 108 111 color = _dpu_format_get_media_color_ubwc(fmt); ··· 111 116 return -EINVAL; 112 117 } 113 118 114 - if (MSM_FORMAT_IS_YUV(layout->format)) { 119 + if (MSM_FORMAT_IS_YUV(fmt)) { 115 120 uint32_t y_sclines, uv_sclines; 116 121 uint32_t y_meta_scanlines = 0; 117 122 uint32_t uv_meta_scanlines = 0; 118 123 119 124 layout->num_planes = 2; 120 - layout->plane_pitch[0] = VENUS_Y_STRIDE(color, width); 121 - y_sclines = VENUS_Y_SCANLINES(color, height); 125 + layout->plane_pitch[0] = VENUS_Y_STRIDE(color, fb->width); 126 + y_sclines = VENUS_Y_SCANLINES(color, fb->height); 122 127 layout->plane_size[0] = MSM_MEDIA_ALIGN(layout->plane_pitch[0] * 123 128 y_sclines, DPU_UBWC_PLANE_SIZE_ALIGNMENT); 124 129 125 - layout->plane_pitch[1] = VENUS_UV_STRIDE(color, width); 126 - uv_sclines = VENUS_UV_SCANLINES(color, height); 130 + layout->plane_pitch[1] = VENUS_UV_STRIDE(color, fb->width); 131 + uv_sclines = VENUS_UV_SCANLINES(color, fb->height); 127 132 layout->plane_size[1] = MSM_MEDIA_ALIGN(layout->plane_pitch[1] * 128 133 uv_sclines, DPU_UBWC_PLANE_SIZE_ALIGNMENT); 129 134 ··· 131 136 goto done; 132 137 133 138 layout->num_planes += 2; 134 - layout->plane_pitch[2] = VENUS_Y_META_STRIDE(color, width); 135 - y_meta_scanlines = VENUS_Y_META_SCANLINES(color, height); 139 + layout->plane_pitch[2] = VENUS_Y_META_STRIDE(color, fb->width); 140 + y_meta_scanlines = VENUS_Y_META_SCANLINES(color, fb->height); 136 141 layout->plane_size[2] = MSM_MEDIA_ALIGN(layout->plane_pitch[2] * 137 142 y_meta_scanlines, DPU_UBWC_PLANE_SIZE_ALIGNMENT); 138 143 139 - layout->plane_pitch[3] = VENUS_UV_META_STRIDE(color, width); 140 - uv_meta_scanlines = VENUS_UV_META_SCANLINES(color, height); 144 + layout->plane_pitch[3] = VENUS_UV_META_STRIDE(color, fb->width); 145 + uv_meta_scanlines = VENUS_UV_META_SCANLINES(color, fb->height); 141 146 layout->plane_size[3] = MSM_MEDIA_ALIGN(layout->plane_pitch[3] * 142 147 uv_meta_scanlines, DPU_UBWC_PLANE_SIZE_ALIGNMENT); 143 148 ··· 146 151 147 152 layout->num_planes = 1; 148 153 149 - layout->plane_pitch[0] = VENUS_RGB_STRIDE(color, width); 150 - rgb_scanlines = VENUS_RGB_SCANLINES(color, height); 154 + layout->plane_pitch[0] = VENUS_RGB_STRIDE(color, fb->width); 155 + rgb_scanlines = VENUS_RGB_SCANLINES(color, fb->height); 151 156 layout->plane_size[0] = MSM_MEDIA_ALIGN(layout->plane_pitch[0] * 152 157 rgb_scanlines, DPU_UBWC_PLANE_SIZE_ALIGNMENT); 153 158 154 159 if (!meta) 155 160 goto done; 156 161 layout->num_planes += 2; 157 - layout->plane_pitch[2] = VENUS_RGB_META_STRIDE(color, width); 158 - rgb_meta_scanlines = VENUS_RGB_META_SCANLINES(color, height); 162 + layout->plane_pitch[2] = VENUS_RGB_META_STRIDE(color, fb->width); 163 + rgb_meta_scanlines = VENUS_RGB_META_SCANLINES(color, fb->height); 159 164 layout->plane_size[2] = MSM_MEDIA_ALIGN(layout->plane_pitch[2] * 160 165 rgb_meta_scanlines, DPU_UBWC_PLANE_SIZE_ALIGNMENT); 161 166 } ··· 167 172 return 0; 168 173 } 169 174 170 - static int _dpu_format_get_plane_sizes_linear( 175 + static int _dpu_format_populate_plane_sizes_linear( 171 176 const struct msm_format *fmt, 172 - const uint32_t width, 173 - const uint32_t height, 174 - struct dpu_hw_fmt_layout *layout, 175 - const uint32_t *pitches) 177 + struct drm_framebuffer *fb, 178 + struct dpu_hw_fmt_layout *layout) 176 179 { 177 180 int i; 178 181 179 182 memset(layout, 0, sizeof(struct dpu_hw_fmt_layout)); 180 - layout->format = fmt; 181 - layout->width = width; 182 - layout->height = height; 183 + layout->width = fb->width; 184 + layout->height = fb->height; 183 185 layout->num_planes = fmt->num_planes; 184 186 185 187 /* Due to memset above, only need to set planes of interest */ 186 188 if (fmt->fetch_type == MDP_PLANE_INTERLEAVED) { 187 189 layout->num_planes = 1; 188 - layout->plane_size[0] = width * height * layout->format->bpp; 189 - layout->plane_pitch[0] = width * layout->format->bpp; 190 + layout->plane_size[0] = fb->width * fb->height * fmt->bpp; 191 + layout->plane_pitch[0] = fb->width * fmt->bpp; 190 192 } else { 191 193 uint32_t v_subsample, h_subsample; 192 194 uint32_t chroma_samp; ··· 193 201 _dpu_get_v_h_subsample_rate(chroma_samp, &v_subsample, 194 202 &h_subsample); 195 203 196 - if (width % h_subsample || height % v_subsample) { 204 + if (fb->width % h_subsample || fb->height % v_subsample) { 197 205 DRM_ERROR("mismatch in subsample vs dimensions\n"); 198 206 return -EINVAL; 199 207 } ··· 201 209 if ((fmt->pixel_format == DRM_FORMAT_NV12) && 202 210 (MSM_FORMAT_IS_DX(fmt))) 203 211 bpp = 2; 204 - layout->plane_pitch[0] = width * bpp; 212 + layout->plane_pitch[0] = fb->width * bpp; 205 213 layout->plane_pitch[1] = layout->plane_pitch[0] / h_subsample; 206 - layout->plane_size[0] = layout->plane_pitch[0] * height; 214 + layout->plane_size[0] = layout->plane_pitch[0] * fb->height; 207 215 layout->plane_size[1] = layout->plane_pitch[1] * 208 - (height / v_subsample); 216 + (fb->height / v_subsample); 209 217 210 218 if (fmt->fetch_type == MDP_PLANE_PSEUDO_PLANAR) { 211 219 layout->num_planes = 2; ··· 226 234 * all the components based on ubwc specifications. 227 235 */ 228 236 for (i = 0; i < layout->num_planes && i < DPU_MAX_PLANES; ++i) { 229 - if (pitches && layout->plane_pitch[i] < pitches[i]) 230 - layout->plane_pitch[i] = pitches[i]; 237 + if (layout->plane_pitch[i] <= fb->pitches[i]) { 238 + layout->plane_pitch[i] = fb->pitches[i]; 239 + } else { 240 + DRM_DEBUG("plane %u expected pitch %u, fb %u\n", 241 + i, layout->plane_pitch[i], fb->pitches[i]); 242 + return -EINVAL; 243 + } 231 244 } 232 245 233 246 for (i = 0; i < DPU_MAX_PLANES; i++) ··· 241 244 return 0; 242 245 } 243 246 244 - static int dpu_format_get_plane_sizes( 245 - const struct msm_format *fmt, 246 - const uint32_t w, 247 - const uint32_t h, 248 - struct dpu_hw_fmt_layout *layout, 249 - const uint32_t *pitches) 247 + /* 248 + * dpu_format_populate_addrs - populate non-address part of the layout based on 249 + * fb, and format found in the fb 250 + * @fb: framebuffer pointer 251 + * @layout: format layout structure to populate 252 + * 253 + * Return: error code on failure or 0 if new addresses were populated 254 + */ 255 + int dpu_format_populate_plane_sizes( 256 + struct drm_framebuffer *fb, 257 + struct dpu_hw_fmt_layout *layout) 250 258 { 251 - if (!layout || !fmt) { 259 + const struct msm_format *fmt; 260 + 261 + if (!layout || !fb) { 252 262 DRM_ERROR("invalid pointer\n"); 253 263 return -EINVAL; 254 264 } 255 265 256 - if ((w > DPU_MAX_IMG_WIDTH) || (h > DPU_MAX_IMG_HEIGHT)) { 266 + if (fb->width > DPU_MAX_IMG_WIDTH || 267 + fb->height > DPU_MAX_IMG_HEIGHT) { 257 268 DRM_ERROR("image dimensions outside max range\n"); 258 269 return -ERANGE; 259 270 } 260 271 261 - if (MSM_FORMAT_IS_UBWC(fmt) || MSM_FORMAT_IS_TILE(fmt)) 262 - return _dpu_format_get_plane_sizes_ubwc(fmt, w, h, layout); 272 + fmt = msm_framebuffer_format(fb); 263 273 264 - return _dpu_format_get_plane_sizes_linear(fmt, w, h, layout, pitches); 274 + if (MSM_FORMAT_IS_UBWC(fmt) || MSM_FORMAT_IS_TILE(fmt)) 275 + return _dpu_format_populate_plane_sizes_ubwc(fmt, fb, layout); 276 + 277 + return _dpu_format_populate_plane_sizes_linear(fmt, fb, layout); 265 278 } 266 279 267 - static int _dpu_format_populate_addrs_ubwc( 268 - struct msm_gem_address_space *aspace, 269 - struct drm_framebuffer *fb, 270 - struct dpu_hw_fmt_layout *layout) 280 + static void _dpu_format_populate_addrs_ubwc(struct msm_gem_address_space *aspace, 281 + struct drm_framebuffer *fb, 282 + struct dpu_hw_fmt_layout *layout) 271 283 { 284 + const struct msm_format *fmt; 272 285 uint32_t base_addr = 0; 273 286 bool meta; 274 287 275 - if (!fb || !layout) { 276 - DRM_ERROR("invalid pointers\n"); 277 - return -EINVAL; 278 - } 288 + base_addr = msm_framebuffer_iova(fb, aspace, 0); 279 289 280 - if (aspace) 281 - base_addr = msm_framebuffer_iova(fb, aspace, 0); 282 - if (!base_addr) { 283 - DRM_ERROR("failed to retrieve base addr\n"); 284 - return -EFAULT; 285 - } 286 - 287 - meta = MSM_FORMAT_IS_UBWC(layout->format); 290 + fmt = msm_framebuffer_format(fb); 291 + meta = MSM_FORMAT_IS_UBWC(fmt); 288 292 289 293 /* Per-format logic for verifying active planes */ 290 - if (MSM_FORMAT_IS_YUV(layout->format)) { 294 + if (MSM_FORMAT_IS_YUV(fmt)) { 291 295 /************************************************/ 292 296 /* UBWC ** */ 293 297 /* buffer ** DPU PLANE */ ··· 317 319 + layout->plane_size[2] + layout->plane_size[3]; 318 320 319 321 if (!meta) 320 - return 0; 322 + return; 321 323 322 324 /* configure Y metadata plane */ 323 325 layout->plane_addr[2] = base_addr; ··· 348 350 layout->plane_addr[1] = 0; 349 351 350 352 if (!meta) 351 - return 0; 353 + return; 352 354 353 355 layout->plane_addr[2] = base_addr; 354 356 layout->plane_addr[3] = 0; 355 357 } 356 - return 0; 357 358 } 358 359 359 - static int _dpu_format_populate_addrs_linear( 360 - struct msm_gem_address_space *aspace, 361 - struct drm_framebuffer *fb, 362 - struct dpu_hw_fmt_layout *layout) 360 + static void _dpu_format_populate_addrs_linear(struct msm_gem_address_space *aspace, 361 + struct drm_framebuffer *fb, 362 + struct dpu_hw_fmt_layout *layout) 363 363 { 364 364 unsigned int i; 365 365 366 - /* Can now check the pitches given vs pitches expected */ 367 - for (i = 0; i < layout->num_planes; ++i) { 368 - if (layout->plane_pitch[i] > fb->pitches[i]) { 369 - DRM_ERROR("plane %u expected pitch %u, fb %u\n", 370 - i, layout->plane_pitch[i], fb->pitches[i]); 371 - return -EINVAL; 372 - } 373 - } 374 - 375 366 /* Populate addresses for simple formats here */ 376 - for (i = 0; i < layout->num_planes; ++i) { 377 - if (aspace) 378 - layout->plane_addr[i] = 379 - msm_framebuffer_iova(fb, aspace, i); 380 - if (!layout->plane_addr[i]) { 381 - DRM_ERROR("failed to retrieve base addr\n"); 382 - return -EFAULT; 383 - } 384 - } 385 - 386 - return 0; 367 + for (i = 0; i < layout->num_planes; ++i) 368 + layout->plane_addr[i] = msm_framebuffer_iova(fb, aspace, i); 387 369 } 388 370 389 - int dpu_format_populate_layout( 390 - struct msm_gem_address_space *aspace, 391 - struct drm_framebuffer *fb, 392 - struct dpu_hw_fmt_layout *layout) 371 + void dpu_format_populate_addrs(struct msm_gem_address_space *aspace, 372 + struct drm_framebuffer *fb, 373 + struct dpu_hw_fmt_layout *layout) 393 374 { 394 - int ret; 375 + const struct msm_format *fmt; 395 376 396 - if (!fb || !layout) { 397 - DRM_ERROR("invalid arguments\n"); 398 - return -EINVAL; 399 - } 400 - 401 - if ((fb->width > DPU_MAX_IMG_WIDTH) || 402 - (fb->height > DPU_MAX_IMG_HEIGHT)) { 403 - DRM_ERROR("image dimensions outside max range\n"); 404 - return -ERANGE; 405 - } 406 - 407 - layout->format = msm_framebuffer_format(fb); 408 - 409 - /* Populate the plane sizes etc via get_format */ 410 - ret = dpu_format_get_plane_sizes(layout->format, fb->width, fb->height, 411 - layout, fb->pitches); 412 - if (ret) 413 - return ret; 377 + fmt = msm_framebuffer_format(fb); 414 378 415 379 /* Populate the addresses given the fb */ 416 - if (MSM_FORMAT_IS_UBWC(layout->format) || 417 - MSM_FORMAT_IS_TILE(layout->format)) 418 - ret = _dpu_format_populate_addrs_ubwc(aspace, fb, layout); 380 + if (MSM_FORMAT_IS_UBWC(fmt) || 381 + MSM_FORMAT_IS_TILE(fmt)) 382 + _dpu_format_populate_addrs_ubwc(aspace, fb, layout); 419 383 else 420 - ret = _dpu_format_populate_addrs_linear(aspace, fb, layout); 421 - 422 - return ret; 423 - } 424 - 425 - int dpu_format_check_modified_format( 426 - const struct msm_kms *kms, 427 - const struct msm_format *fmt, 428 - const struct drm_mode_fb_cmd2 *cmd, 429 - struct drm_gem_object **bos) 430 - { 431 - const struct drm_format_info *info; 432 - struct dpu_hw_fmt_layout layout; 433 - uint32_t bos_total_size = 0; 434 - int ret, i; 435 - 436 - if (!fmt || !cmd || !bos) { 437 - DRM_ERROR("invalid arguments\n"); 438 - return -EINVAL; 439 - } 440 - 441 - info = drm_format_info(fmt->pixel_format); 442 - if (!info) 443 - return -EINVAL; 444 - 445 - ret = dpu_format_get_plane_sizes(fmt, cmd->width, cmd->height, 446 - &layout, cmd->pitches); 447 - if (ret) 448 - return ret; 449 - 450 - for (i = 0; i < info->num_planes; i++) { 451 - if (!bos[i]) { 452 - DRM_ERROR("invalid handle for plane %d\n", i); 453 - return -EINVAL; 454 - } 455 - if ((i == 0) || (bos[i] != bos[0])) 456 - bos_total_size += bos[i]->size; 457 - } 458 - 459 - if (bos_total_size < layout.total_size) { 460 - DRM_ERROR("buffers total size too small %u expected %u\n", 461 - bos_total_size, layout.total_size); 462 - return -EINVAL; 463 - } 464 - 465 - return 0; 384 + _dpu_format_populate_addrs_linear(aspace, fb, layout); 466 385 }
+7 -23
drivers/gpu/drm/msm/disp/dpu1/dpu_formats.h
··· 32 32 } 33 33 34 34 /** 35 - * dpu_format_check_modified_format - validate format and buffers for 36 - * dpu non-standard, i.e. modified format 37 - * @kms: kms driver 38 - * @msm_fmt: pointer to the msm_fmt base pointer of an msm_format 39 - * @cmd: fb_cmd2 structure user request 40 - * @bos: gem buffer object list 41 - * 42 - * Return: error code on failure, 0 on success 43 - */ 44 - int dpu_format_check_modified_format( 45 - const struct msm_kms *kms, 46 - const struct msm_format *msm_fmt, 47 - const struct drm_mode_fb_cmd2 *cmd, 48 - struct drm_gem_object **bos); 49 - 50 - /** 51 - * dpu_format_populate_layout - populate the given format layout based on 35 + * dpu_format_populate_addrs - populate buffer addresses based on 52 36 * mmu, fb, and format found in the fb 53 37 * @aspace: address space pointer 54 38 * @fb: framebuffer pointer 55 39 * @fmtl: format layout structure to populate 56 - * 57 - * Return: error code on failure, -EAGAIN if success but the addresses 58 - * are the same as before or 0 if new addresses were populated 59 40 */ 60 - int dpu_format_populate_layout( 61 - struct msm_gem_address_space *aspace, 41 + void dpu_format_populate_addrs(struct msm_gem_address_space *aspace, 42 + struct drm_framebuffer *fb, 43 + struct dpu_hw_fmt_layout *layout); 44 + 45 + int dpu_format_populate_plane_sizes( 62 46 struct drm_framebuffer *fb, 63 - struct dpu_hw_fmt_layout *fmtl); 47 + struct dpu_hw_fmt_layout *layout); 64 48 65 49 #endif /*_DPU_FORMATS_H */
+109
drivers/gpu/drm/msm/disp/dpu1/dpu_hw_catalog.c
··· 21 21 (VIG_BASE_MASK | \ 22 22 BIT(DPU_SSPP_CSC_10BIT)) 23 23 24 + #define VIG_MSM8953_MASK \ 25 + (BIT(DPU_SSPP_QOS) |\ 26 + BIT(DPU_SSPP_SCALER_QSEED2) |\ 27 + BIT(DPU_SSPP_CSC)) 28 + 29 + #define VIG_MSM8996_MASK \ 30 + (BIT(DPU_SSPP_QOS) | BIT(DPU_SSPP_CDP) |\ 31 + BIT(DPU_SSPP_TS_PREFILL) | BIT(DPU_SSPP_SCALER_QSEED2) |\ 32 + BIT(DPU_SSPP_CSC)) 33 + 24 34 #define VIG_MSM8998_MASK \ 25 35 (VIG_MASK | BIT(DPU_SSPP_SCALER_QSEED3_COMPATIBLE)) 26 36 ··· 41 31 (VIG_SDM845_MASK | BIT(DPU_SSPP_SMART_DMA_V2)) 42 32 43 33 #define VIG_QCM2290_MASK (VIG_BASE_MASK | BIT(DPU_SSPP_QOS_8LVL)) 34 + 35 + #define DMA_MSM8953_MASK \ 36 + (BIT(DPU_SSPP_QOS)) 37 + 38 + #define DMA_MSM8996_MASK \ 39 + (BIT(DPU_SSPP_QOS) | BIT(DPU_SSPP_TS_PREFILL) | BIT(DPU_SSPP_CDP)) 44 40 45 41 #define DMA_MSM8998_MASK \ 46 42 (BIT(DPU_SSPP_QOS) |\ ··· 73 57 #define DMA_CURSOR_SDM845_MASK_SDMA \ 74 58 (DMA_CURSOR_SDM845_MASK | BIT(DPU_SSPP_SMART_DMA_V2)) 75 59 60 + #define DMA_CURSOR_MSM8996_MASK \ 61 + (DMA_MSM8996_MASK | BIT(DPU_SSPP_CURSOR)) 62 + 76 63 #define DMA_CURSOR_MSM8998_MASK \ 77 64 (DMA_MSM8998_MASK | BIT(DPU_SSPP_CURSOR)) 65 + 66 + #define RGB_MSM8953_MASK \ 67 + (BIT(DPU_SSPP_QOS)) 68 + 69 + #define RGB_MSM8996_MASK \ 70 + (BIT(DPU_SSPP_QOS) | BIT(DPU_SSPP_CDP) |\ 71 + BIT(DPU_SSPP_TS_PREFILL) | BIT(DPU_SSPP_SCALER_RGB)) 78 72 79 73 #define MIXER_MSM8998_MASK \ 80 74 (BIT(DPU_MIXER_SOURCESPLIT)) ··· 94 68 95 69 #define MIXER_QCM2290_MASK \ 96 70 (BIT(DPU_DIM_LAYER) | BIT(DPU_MIXER_COMBINED_ALPHA)) 71 + 72 + #define PINGPONG_MSM8996_MASK \ 73 + (BIT(DPU_PINGPONG_DSC)) 74 + 75 + #define PINGPONG_MSM8996_TE2_MASK \ 76 + (PINGPONG_MSM8996_MASK | BIT(DPU_PINGPONG_TE2)) 97 77 98 78 #define PINGPONG_SDM845_MASK \ 99 79 (BIT(DPU_PINGPONG_DITHER) | BIT(DPU_PINGPONG_DSC)) ··· 348 316 .virt_num_formats = ARRAY_SIZE(plane_formats), \ 349 317 } 350 318 319 + /* qseed2 is not supported, so disabled scaling */ 320 + #define _VIG_SBLK_QSEED2() \ 321 + { \ 322 + .maxdwnscale = SSPP_UNITY_SCALE, \ 323 + .maxupscale = SSPP_UNITY_SCALE, \ 324 + .scaler_blk = {.name = "scaler", \ 325 + /* no version for qseed2 */ \ 326 + .base = 0x200, .len = 0xa0,}, \ 327 + .csc_blk = {.name = "csc", \ 328 + .base = 0x320, .len = 0x100,}, \ 329 + .format_list = plane_formats_yuv, \ 330 + .num_formats = ARRAY_SIZE(plane_formats_yuv), \ 331 + .virt_format_list = plane_formats, \ 332 + .virt_num_formats = ARRAY_SIZE(plane_formats), \ 333 + .rotation_cfg = NULL, \ 334 + } 335 + 336 + #define _RGB_SBLK() \ 337 + { \ 338 + .maxdwnscale = SSPP_UNITY_SCALE, \ 339 + .maxupscale = SSPP_UNITY_SCALE, \ 340 + .scaler_blk = {.name = "scaler", \ 341 + .base = 0x200, .len = 0x28,}, \ 342 + .format_list = plane_formats, \ 343 + .num_formats = ARRAY_SIZE(plane_formats), \ 344 + .virt_format_list = plane_formats, \ 345 + .virt_num_formats = ARRAY_SIZE(plane_formats), \ 346 + } 347 + 351 348 #define _DMA_SBLK() \ 352 349 { \ 353 350 .maxdwnscale = SSPP_UNITY_SCALE, \ ··· 392 331 .rot_num_formats = ARRAY_SIZE(rotation_v2_formats), 393 332 .rot_format_list = rotation_v2_formats, 394 333 }; 334 + 335 + static const struct dpu_sspp_sub_blks dpu_vig_sblk_qseed2 = 336 + _VIG_SBLK_QSEED2(); 395 337 396 338 static const struct dpu_sspp_sub_blks dpu_vig_sblk_noscale = 397 339 _VIG_SBLK_NOSCALE(); ··· 426 362 427 363 static const struct dpu_sspp_sub_blks dpu_vig_sblk_qseed3_3_3 = 428 364 _VIG_SBLK(SSPP_SCALER_VER(3, 3)); 365 + 366 + static const struct dpu_sspp_sub_blks dpu_rgb_sblk = _RGB_SBLK(); 429 367 430 368 static const struct dpu_sspp_sub_blks dpu_dma_sblk = _DMA_SBLK(); 431 369 ··· 493 427 /************************************************************* 494 428 * PINGPONG sub blocks config 495 429 *************************************************************/ 430 + static const struct dpu_pingpong_sub_blks msm8996_pp_sblk_te = { 431 + .te2 = {.name = "te2", .base = 0x2000, .len = 0x0, 432 + .version = 0x1}, 433 + }; 434 + 435 + static const struct dpu_pingpong_sub_blks msm8996_pp_sblk = { 436 + /* No dither block */ 437 + }; 438 + 496 439 static const struct dpu_pingpong_sub_blks sdm845_pp_sblk_te = { 497 440 .te2 = {.name = "te2", .base = 0x2000, .len = 0x0, 498 441 .version = 0x1}, ··· 564 489 { 565 490 .pps = 3840 * 2160 * 30, 566 491 .ot_limit = 16, 492 + }, 493 + }; 494 + 495 + static const struct dpu_vbif_cfg msm8996_vbif[] = { 496 + { 497 + .name = "vbif_rt", .id = VBIF_RT, 498 + .base = 0, .len = 0x1040, 499 + .default_ot_rd_limit = 32, 500 + .default_ot_wr_limit = 16, 501 + .features = BIT(DPU_VBIF_QOS_REMAP) | BIT(DPU_VBIF_QOS_OTLIM), 502 + .xin_halt_timeout = 0x4000, 503 + .qos_rp_remap_size = 0x20, 504 + .dynamic_ot_rd_tbl = { 505 + .count = ARRAY_SIZE(msm8998_ot_rdwr_cfg), 506 + .cfg = msm8998_ot_rdwr_cfg, 507 + }, 508 + .dynamic_ot_wr_tbl = { 509 + .count = ARRAY_SIZE(msm8998_ot_rdwr_cfg), 510 + .cfg = msm8998_ot_rdwr_cfg, 511 + }, 512 + .qos_rt_tbl = { 513 + .npriority_lvl = ARRAY_SIZE(msm8998_rt_pri_lvl), 514 + .priority_lvl = msm8998_rt_pri_lvl, 515 + }, 516 + .qos_nrt_tbl = { 517 + .npriority_lvl = ARRAY_SIZE(msm8998_nrt_pri_lvl), 518 + .priority_lvl = msm8998_nrt_pri_lvl, 519 + }, 567 520 }, 568 521 }; 569 522 ··· 778 675 * Hardware catalog 779 676 *************************************************************/ 780 677 678 + #include "catalog/dpu_1_7_msm8996.h" 679 + #include "catalog/dpu_1_14_msm8937.h" 680 + #include "catalog/dpu_1_15_msm8917.h" 681 + #include "catalog/dpu_1_16_msm8953.h" 682 + 781 683 #include "catalog/dpu_3_0_msm8998.h" 782 684 #include "catalog/dpu_3_2_sdm660.h" 783 685 #include "catalog/dpu_3_3_sdm630.h" ··· 807 699 808 700 #include "catalog/dpu_8_0_sc8280xp.h" 809 701 #include "catalog/dpu_8_1_sm8450.h" 702 + #include "catalog/dpu_8_4_sa8775p.h" 810 703 811 704 #include "catalog/dpu_9_0_sm8550.h" 812 705
+7 -2
drivers/gpu/drm/msm/disp/dpu1/dpu_hw_catalog.h
··· 21 21 22 22 #define DPU_HW_BLK_NAME_LEN 16 23 23 24 - #define MAX_IMG_WIDTH 0x3fff 25 - #define MAX_IMG_HEIGHT 0x3fff 24 + #define DPU_MAX_IMG_WIDTH 0x3fff 25 + #define DPU_MAX_IMG_HEIGHT 0x3fff 26 26 27 27 #define CRTC_DUAL_MIXERS 2 28 28 ··· 831 831 const struct dpu_format_extended *vig_formats; 832 832 }; 833 833 834 + extern const struct dpu_mdss_cfg dpu_msm8917_cfg; 835 + extern const struct dpu_mdss_cfg dpu_msm8937_cfg; 836 + extern const struct dpu_mdss_cfg dpu_msm8953_cfg; 837 + extern const struct dpu_mdss_cfg dpu_msm8996_cfg; 834 838 extern const struct dpu_mdss_cfg dpu_msm8998_cfg; 835 839 extern const struct dpu_mdss_cfg dpu_sdm630_cfg; 836 840 extern const struct dpu_mdss_cfg dpu_sdm660_cfg; ··· 854 850 extern const struct dpu_mdss_cfg dpu_sc7280_cfg; 855 851 extern const struct dpu_mdss_cfg dpu_sc8280xp_cfg; 856 852 extern const struct dpu_mdss_cfg dpu_sm8450_cfg; 853 + extern const struct dpu_mdss_cfg dpu_sa8775p_cfg; 857 854 extern const struct dpu_mdss_cfg dpu_sm8550_cfg; 858 855 extern const struct dpu_mdss_cfg dpu_sm8650_cfg; 859 856 extern const struct dpu_mdss_cfg dpu_x1e80100_cfg;
-2
drivers/gpu/drm/msm/disp/dpu1/dpu_hw_mdss.h
··· 293 293 294 294 /** 295 295 * struct dpu_hw_fmt_layout - format information of the source pixel data 296 - * @format: pixel format parameters 297 296 * @num_planes: number of planes (including meta data planes) 298 297 * @width: image width 299 298 * @height: image height ··· 302 303 * @plane_pitch: pitch of each plane 303 304 */ 304 305 struct dpu_hw_fmt_layout { 305 - const struct msm_format *format; 306 306 uint32_t num_planes; 307 307 uint32_t width; 308 308 uint32_t height;
+2
drivers/gpu/drm/msm/disp/dpu1/dpu_hw_sspp.h
··· 12 12 13 13 struct dpu_hw_sspp; 14 14 15 + #define DPU_SSPP_MAX_PITCH_SIZE 0xffff 16 + 15 17 /** 16 18 * Flags 17 19 */
+2 -2
drivers/gpu/drm/msm/disp/dpu1/dpu_hw_wb.c
··· 64 64 } 65 65 66 66 static void dpu_hw_wb_setup_format(struct dpu_hw_wb *ctx, 67 - struct dpu_hw_wb_cfg *data) 67 + struct dpu_hw_wb_cfg *data, 68 + const struct msm_format *fmt) 68 69 { 69 70 struct dpu_hw_blk_reg_map *c = &ctx->hw; 70 - const struct msm_format *fmt = data->dest.format; 71 71 u32 dst_format, pattern, ystride0, ystride1, outsize, chroma_samp; 72 72 u32 write_config = 0; 73 73 u32 opmode = 0;
+2 -1
drivers/gpu/drm/msm/disp/dpu1/dpu_hw_wb.h
··· 37 37 struct dpu_hw_wb_cfg *wb); 38 38 39 39 void (*setup_outformat)(struct dpu_hw_wb *ctx, 40 - struct dpu_hw_wb_cfg *wb); 40 + struct dpu_hw_wb_cfg *wb, 41 + const struct msm_format *fmt); 41 42 42 43 void (*setup_roi)(struct dpu_hw_wb *ctx, 43 44 struct dpu_hw_wb_cfg *wb);
+7 -8
drivers/gpu/drm/msm/disp/dpu1/dpu_kms.c
··· 1025 1025 .complete_commit = dpu_kms_complete_commit, 1026 1026 .enable_vblank = dpu_kms_enable_vblank, 1027 1027 .disable_vblank = dpu_kms_disable_vblank, 1028 - .check_modified_format = dpu_format_check_modified_format, 1029 1028 .destroy = dpu_kms_destroy, 1030 1029 .snapshot = dpu_kms_mdp_snapshot, 1031 1030 #ifdef CONFIG_DEBUG_FS ··· 1201 1202 dev->mode_config.min_width = 0; 1202 1203 dev->mode_config.min_height = 0; 1203 1204 1204 - /* 1205 - * max crtc width is equal to the max mixer width * 2 and max height is 1206 - * is 4K 1207 - */ 1208 - dev->mode_config.max_width = 1209 - dpu_kms->catalog->caps->max_mixer_width * 2; 1210 - dev->mode_config.max_height = 4096; 1205 + dev->mode_config.max_width = DPU_MAX_IMG_WIDTH; 1206 + dev->mode_config.max_height = DPU_MAX_IMG_HEIGHT; 1211 1207 1212 1208 dev->max_vblank_count = 0xffffffff; 1213 1209 /* Disable vblank irqs aggressively for power-saving */ ··· 1439 1445 }; 1440 1446 1441 1447 static const struct of_device_id dpu_dt_match[] = { 1448 + { .compatible = "qcom,msm8917-mdp5", .data = &dpu_msm8917_cfg, }, 1449 + { .compatible = "qcom,msm8937-mdp5", .data = &dpu_msm8937_cfg, }, 1450 + { .compatible = "qcom,msm8953-mdp5", .data = &dpu_msm8953_cfg, }, 1451 + { .compatible = "qcom,msm8996-mdp5", .data = &dpu_msm8996_cfg, }, 1442 1452 { .compatible = "qcom,msm8998-dpu", .data = &dpu_msm8998_cfg, }, 1443 1453 { .compatible = "qcom,qcm2290-dpu", .data = &dpu_qcm2290_cfg, }, 1454 + { .compatible = "qcom,sa8775p-dpu", .data = &dpu_sa8775p_cfg, }, 1444 1455 { .compatible = "qcom,sdm630-mdp5", .data = &dpu_sdm630_cfg, }, 1445 1456 { .compatible = "qcom,sdm660-mdp5", .data = &dpu_sdm660_cfg, }, 1446 1457 { .compatible = "qcom,sdm670-dpu", .data = &dpu_sdm670_cfg, },
+20 -30
drivers/gpu/drm/msm/disp/dpu1/dpu_plane.c
··· 648 648 struct drm_framebuffer *fb = new_state->fb; 649 649 struct dpu_plane *pdpu = to_dpu_plane(plane); 650 650 struct dpu_plane_state *pstate = to_dpu_plane_state(new_state); 651 - struct dpu_hw_fmt_layout layout; 652 651 struct dpu_kms *kms = _dpu_plane_get_kms(&pdpu->base); 653 652 int ret; 654 653 ··· 673 674 DPU_ERROR("failed to prepare framebuffer\n"); 674 675 return ret; 675 676 } 676 - } 677 - 678 - /* validate framebuffer layout before commit */ 679 - ret = dpu_format_populate_layout(pstate->aspace, 680 - new_state->fb, &layout); 681 - if (ret) { 682 - DPU_ERROR_PLANE(pdpu, "failed to get format layout, %d\n", ret); 683 - if (pstate->aspace) 684 - msm_framebuffer_cleanup(new_state->fb, pstate->aspace, 685 - pstate->needs_dirtyfb); 686 - return ret; 687 677 } 688 678 689 679 return 0; ··· 782 794 { 783 795 struct drm_plane_state *new_plane_state = drm_atomic_get_new_plane_state(state, 784 796 plane); 785 - int ret = 0, min_scale; 797 + int i, ret = 0, min_scale; 786 798 struct dpu_plane *pdpu = to_dpu_plane(plane); 787 799 struct dpu_kms *kms = _dpu_plane_get_kms(&pdpu->base); 788 800 u64 max_mdp_clk_rate = kms->perf.max_core_clk_rate; ··· 843 855 fb_rect.y2 = new_plane_state->fb->height; 844 856 845 857 /* Ensure fb size is supported */ 846 - if (drm_rect_width(&fb_rect) > MAX_IMG_WIDTH || 847 - drm_rect_height(&fb_rect) > MAX_IMG_HEIGHT) { 858 + if (drm_rect_width(&fb_rect) > DPU_MAX_IMG_WIDTH || 859 + drm_rect_height(&fb_rect) > DPU_MAX_IMG_HEIGHT) { 848 860 DPU_DEBUG_PLANE(pdpu, "invalid framebuffer " DRM_RECT_FMT "\n", 849 861 DRM_RECT_ARG(&fb_rect)); 850 862 return -E2BIG; 851 863 } 864 + 865 + ret = dpu_format_populate_plane_sizes(new_plane_state->fb, &pstate->layout); 866 + if (ret) { 867 + DPU_ERROR_PLANE(pdpu, "failed to get format plane sizes, %d\n", ret); 868 + return ret; 869 + } 870 + 871 + for (i = 0; i < pstate->layout.num_planes; i++) 872 + if (pstate->layout.plane_pitch[i] > DPU_SSPP_MAX_PITCH_SIZE) 873 + return -E2BIG; 852 874 853 875 fmt = msm_framebuffer_format(new_plane_state->fb); 854 876 ··· 1099 1101 _dpu_plane_set_qos_remap(plane, pipe); 1100 1102 } 1101 1103 1102 - static void dpu_plane_sspp_atomic_update(struct drm_plane *plane) 1104 + static void dpu_plane_sspp_atomic_update(struct drm_plane *plane, 1105 + struct drm_plane_state *new_state) 1103 1106 { 1104 1107 struct dpu_plane *pdpu = to_dpu_plane(plane); 1105 1108 struct drm_plane_state *state = plane->state; ··· 1114 1115 msm_framebuffer_format(fb); 1115 1116 struct dpu_sw_pipe_cfg *pipe_cfg = &pstate->pipe_cfg; 1116 1117 struct dpu_sw_pipe_cfg *r_pipe_cfg = &pstate->r_pipe_cfg; 1117 - struct dpu_kms *kms = _dpu_plane_get_kms(&pdpu->base); 1118 - struct msm_gem_address_space *aspace = kms->base.aspace; 1119 - struct dpu_hw_fmt_layout layout; 1120 - bool layout_valid = false; 1121 - int ret; 1122 - 1123 - ret = dpu_format_populate_layout(aspace, fb, &layout); 1124 - if (ret) 1125 - DPU_ERROR_PLANE(pdpu, "failed to get format layout, %d\n", ret); 1126 - else 1127 - layout_valid = true; 1128 1118 1129 1119 pstate->pending = true; 1130 1120 1131 1121 is_rt_pipe = (dpu_crtc_get_client_type(crtc) != NRT_CLIENT); 1132 1122 pstate->needs_qos_remap |= (is_rt_pipe != pdpu->is_rt_pipe); 1133 1123 pdpu->is_rt_pipe = is_rt_pipe; 1124 + 1125 + dpu_format_populate_addrs(pstate->aspace, new_state->fb, &pstate->layout); 1134 1126 1135 1127 DPU_DEBUG_PLANE(pdpu, "FB[%u] " DRM_RECT_FP_FMT "->crtc%u " DRM_RECT_FMT 1136 1128 ", %p4cc ubwc %d\n", fb->base.id, DRM_RECT_FP_ARG(&state->src), ··· 1130 1140 1131 1141 dpu_plane_sspp_update_pipe(plane, pipe, pipe_cfg, fmt, 1132 1142 drm_mode_vrefresh(&crtc->mode), 1133 - layout_valid ? &layout : NULL); 1143 + &pstate->layout); 1134 1144 1135 1145 if (r_pipe->sspp) { 1136 1146 dpu_plane_sspp_update_pipe(plane, r_pipe, r_pipe_cfg, fmt, 1137 1147 drm_mode_vrefresh(&crtc->mode), 1138 - layout_valid ? &layout : NULL); 1148 + &pstate->layout); 1139 1149 } 1140 1150 1141 1151 if (pstate->needs_qos_remap) ··· 1187 1197 if (!new_state->visible) { 1188 1198 _dpu_plane_atomic_disable(plane); 1189 1199 } else { 1190 - dpu_plane_sspp_atomic_update(plane); 1200 + dpu_plane_sspp_atomic_update(plane, new_state); 1191 1201 } 1192 1202 } 1193 1203
+3
drivers/gpu/drm/msm/disp/dpu1/dpu_plane.h
··· 31 31 * @plane_clk: calculated clk per plane 32 32 * @needs_dirtyfb: whether attached CRTC needs pixel data explicitly flushed 33 33 * @rotation: simplified drm rotation hint 34 + * @layout: framebuffer memory layout 34 35 */ 35 36 struct dpu_plane_state { 36 37 struct drm_plane_state base; ··· 49 48 50 49 bool needs_dirtyfb; 51 50 unsigned int rotation; 51 + 52 + struct dpu_hw_fmt_layout layout; 52 53 }; 53 54 54 55 #define to_dpu_plane_state(x) \
+8 -11
drivers/gpu/drm/msm/disp/msm_disp_snapshot_util.c
··· 25 25 addr = base_addr; 26 26 end_addr = base_addr + aligned_len; 27 27 28 - if (!(*reg)) 29 - *reg = kvzalloc(len_padded, GFP_KERNEL); 28 + *reg = kvzalloc(len_padded, GFP_KERNEL); 29 + if (!*reg) 30 + return; 30 31 31 - if (*reg) 32 - dump_addr = *reg; 33 - 32 + dump_addr = *reg; 34 33 for (i = 0; i < num_rows; i++) { 35 34 x0 = (addr < end_addr) ? readl_relaxed(addr + 0x0) : 0; 36 35 x4 = (addr + 0x4 < end_addr) ? readl_relaxed(addr + 0x4) : 0; 37 36 x8 = (addr + 0x8 < end_addr) ? readl_relaxed(addr + 0x8) : 0; 38 37 xc = (addr + 0xc < end_addr) ? readl_relaxed(addr + 0xc) : 0; 39 38 40 - if (dump_addr) { 41 - dump_addr[i * 4] = x0; 42 - dump_addr[i * 4 + 1] = x4; 43 - dump_addr[i * 4 + 2] = x8; 44 - dump_addr[i * 4 + 3] = xc; 45 - } 39 + dump_addr[i * 4] = x0; 40 + dump_addr[i * 4 + 1] = x4; 41 + dump_addr[i * 4 + 2] = x8; 42 + dump_addr[i * 4 + 3] = xc; 46 43 47 44 addr += REG_DUMP_ALIGN; 48 45 }
+9
drivers/gpu/drm/msm/dp/dp_display.c
··· 118 118 bool wide_bus_supported; 119 119 }; 120 120 121 + static const struct msm_dp_desc sa8775p_dp_descs[] = { 122 + { .io_start = 0x0af54000, .id = MSM_DP_CONTROLLER_0, .wide_bus_supported = true }, 123 + { .io_start = 0x0af5c000, .id = MSM_DP_CONTROLLER_1, .wide_bus_supported = true }, 124 + { .io_start = 0x22154000, .id = MSM_DP_CONTROLLER_2, .wide_bus_supported = true }, 125 + { .io_start = 0x2215c000, .id = MSM_DP_CONTROLLER_3, .wide_bus_supported = true }, 126 + {} 127 + }; 128 + 121 129 static const struct msm_dp_desc sc7180_dp_descs[] = { 122 130 { .io_start = 0x0ae90000, .id = MSM_DP_CONTROLLER_0, .wide_bus_supported = true }, 123 131 {} ··· 170 162 }; 171 163 172 164 static const struct of_device_id dp_dt_match[] = { 165 + { .compatible = "qcom,sa8775p-dp", .data = &sa8775p_dp_descs }, 173 166 { .compatible = "qcom,sc7180-dp", .data = &sc7180_dp_descs }, 174 167 { .compatible = "qcom,sc7280-dp", .data = &sc7280_dp_descs }, 175 168 { .compatible = "qcom,sc7280-edp", .data = &sc7280_dp_descs },
+3 -4
drivers/gpu/drm/msm/hdmi/hdmi_phy_8998.c
··· 157 157 #define HDMI_MHZ_TO_HZ ((u64)1000000) 158 158 static int pll_get_post_div(struct hdmi_8998_post_divider *pd, u64 bclk) 159 159 { 160 - u32 const ratio_list[] = {1, 2, 3, 4, 5, 6, 161 - 9, 10, 12, 15, 25}; 162 - u32 const band_list[] = {0, 1, 2, 3}; 160 + static const u32 ratio_list[] = {1, 2, 3, 4, 5, 6, 9, 10, 12, 15, 25}; 161 + static const u32 band_list[] = {0, 1, 2, 3}; 163 162 u32 const sz_ratio = ARRAY_SIZE(ratio_list); 164 163 u32 const sz_band = ARRAY_SIZE(band_list); 165 164 u32 const cmp_cnt = 1024; ··· 269 270 case 25: 270 271 found_hsclk_divsel = 14; 271 272 break; 272 - }; 273 + } 273 274 274 275 pd->vco_freq = found_vco_freq; 275 276 pd->tx_band_sel = found_tx_band_sel;
+4
drivers/gpu/drm/msm/msm_drv.c
··· 985 985 986 986 /* list all platforms supported by both mdp5 and dpu drivers */ 987 987 static const char *const msm_mdp5_dpu_migration[] = { 988 + "qcom,msm8917-mdp5", 989 + "qcom,msm8937-mdp5", 990 + "qcom,msm8953-mdp5", 991 + "qcom,msm8996-mdp5", 988 992 "qcom,sdm630-mdp5", 989 993 "qcom,sdm660-mdp5", 990 994 NULL,
+1 -1
drivers/gpu/drm/msm/msm_gpu.c
··· 783 783 mutex_unlock(&gpu->active_lock); 784 784 785 785 gpu->funcs->submit(gpu, submit); 786 - gpu->cur_ctx_seqno = submit->queue->ctx->seqno; 786 + submit->ring->cur_ctx_seqno = submit->queue->ctx->seqno; 787 787 788 788 pm_runtime_put(&gpu->pdev->dev); 789 789 hangcheck_timer_reset(gpu);
-11
drivers/gpu/drm/msm/msm_gpu.h
··· 194 194 refcount_t sysprof_active; 195 195 196 196 /** 197 - * cur_ctx_seqno: 198 - * 199 - * The ctx->seqno value of the last context to submit rendering, 200 - * and the one with current pgtables installed (for generations 201 - * that support per-context pgtables). Tracked by seqno rather 202 - * than pointer value to avoid dangling pointers, and cases where 203 - * a ctx can be freed and a new one created with the same address. 204 - */ 205 - int cur_ctx_seqno; 206 - 207 - /** 208 197 * lock: 209 198 * 210 199 * General lock for serializing all the gpu things.
+7 -2
drivers/gpu/drm/msm/msm_gpu_devfreq.c
··· 140 140 { 141 141 struct msm_gpu_devfreq *df = &gpu->devfreq; 142 142 struct msm_drm_private *priv = gpu->dev->dev_private; 143 + int ret; 143 144 144 145 /* We need target support to do devfreq */ 145 146 if (!gpu->funcs->gpu_busy) ··· 157 156 158 157 mutex_init(&df->lock); 159 158 160 - dev_pm_qos_add_request(&gpu->pdev->dev, &df->boost_freq, 161 - DEV_PM_QOS_MIN_FREQUENCY, 0); 159 + ret = dev_pm_qos_add_request(&gpu->pdev->dev, &df->boost_freq, 160 + DEV_PM_QOS_MIN_FREQUENCY, 0); 161 + if (ret < 0) { 162 + DRM_DEV_ERROR(&gpu->pdev->dev, "Couldn't initialize QoS\n"); 163 + return; 164 + } 162 165 163 166 msm_devfreq_profile.initial_freq = gpu->fast_rate; 164 167
+28
drivers/gpu/drm/msm/msm_gpu_trace.h
··· 177 177 TP_printk("%u", __entry->dummy) 178 178 ); 179 179 180 + TRACE_EVENT(msm_gpu_preemption_trigger, 181 + TP_PROTO(int ring_id_from, int ring_id_to), 182 + TP_ARGS(ring_id_from, ring_id_to), 183 + TP_STRUCT__entry( 184 + __field(int, ring_id_from) 185 + __field(int, ring_id_to) 186 + ), 187 + TP_fast_assign( 188 + __entry->ring_id_from = ring_id_from; 189 + __entry->ring_id_to = ring_id_to; 190 + ), 191 + TP_printk("preempting %u -> %u", 192 + __entry->ring_id_from, 193 + __entry->ring_id_to) 194 + ); 195 + 196 + TRACE_EVENT(msm_gpu_preemption_irq, 197 + TP_PROTO(u32 ring_id), 198 + TP_ARGS(ring_id), 199 + TP_STRUCT__entry( 200 + __field(u32, ring_id) 201 + ), 202 + TP_fast_assign( 203 + __entry->ring_id = ring_id; 204 + ), 205 + TP_printk("preempted to %u", __entry->ring_id) 206 + ); 207 + 180 208 #endif 181 209 182 210 #undef TRACE_INCLUDE_PATH
-6
drivers/gpu/drm/msm/msm_kms.h
··· 92 92 * Format handling: 93 93 */ 94 94 95 - /* do format checking on format modified through fb_cmd2 modifiers */ 96 - int (*check_modified_format)(const struct msm_kms *kms, 97 - const struct msm_format *msm_fmt, 98 - const struct drm_mode_fb_cmd2 *cmd, 99 - struct drm_gem_object **bos); 100 - 101 95 /* misc: */ 102 96 long (*round_pixclk)(struct msm_kms *kms, unsigned long rate, 103 97 struct drm_encoder *encoder);
+11
drivers/gpu/drm/msm/msm_mdss.c
··· 573 573 .reg_bus_bw = 76800, 574 574 }; 575 575 576 + static const struct msm_mdss_data sa8775p_data = { 577 + .ubwc_enc_version = UBWC_4_0, 578 + .ubwc_dec_version = UBWC_4_0, 579 + .ubwc_swizzle = 4, 580 + .ubwc_static = 1, 581 + .highest_bank_bit = 0, 582 + .macrotile_mode = 1, 583 + .reg_bus_bw = 74000, 584 + }; 585 + 576 586 static const struct msm_mdss_data sc7180_data = { 577 587 .ubwc_enc_version = UBWC_2_0, 578 588 .ubwc_dec_version = UBWC_2_0, ··· 720 710 { .compatible = "qcom,mdss" }, 721 711 { .compatible = "qcom,msm8998-mdss", .data = &msm8998_data }, 722 712 { .compatible = "qcom,qcm2290-mdss", .data = &qcm2290_data }, 713 + { .compatible = "qcom,sa8775p-mdss", .data = &sa8775p_data }, 723 714 { .compatible = "qcom,sdm670-mdss", .data = &sdm670_data }, 724 715 { .compatible = "qcom,sdm845-mdss", .data = &sdm845_data }, 725 716 { .compatible = "qcom,sc7180-mdss", .data = &sc7180_data },
+1 -1
drivers/gpu/drm/msm/msm_ringbuffer.c
··· 64 64 char name[32]; 65 65 int ret; 66 66 67 - /* We assume everwhere that MSM_GPU_RINGBUFFER_SZ is a power of 2 */ 67 + /* We assume everywhere that MSM_GPU_RINGBUFFER_SZ is a power of 2 */ 68 68 BUILD_BUG_ON(!is_power_of_2(MSM_GPU_RINGBUFFER_SZ)); 69 69 70 70 ring = kzalloc(sizeof(*ring), GFP_KERNEL);
+18
drivers/gpu/drm/msm/msm_ringbuffer.h
··· 31 31 volatile uint32_t rptr; 32 32 volatile uint32_t fence; 33 33 /* Introduced on A7xx */ 34 + volatile uint32_t bv_rptr; 34 35 volatile uint32_t bv_fence; 35 36 36 37 volatile struct msm_gpu_submit_stats stats[MSM_GPU_SUBMIT_STATS_COUNT]; 37 38 volatile u64 ttbr0; 39 + volatile u32 context_idr; 38 40 }; 39 41 40 42 struct msm_cp_state { ··· 101 99 * preemption. Can be aquired from irq context. 102 100 */ 103 101 spinlock_t preempt_lock; 102 + 103 + /* 104 + * Whether we skipped writing wptr and it needs to be updated in the 105 + * future when the ring becomes current. 106 + */ 107 + bool restore_wptr; 108 + 109 + /** 110 + * cur_ctx_seqno: 111 + * 112 + * The ctx->seqno value of the last context to submit to this ring 113 + * Tracked by seqno rather than pointer value to avoid dangling 114 + * pointers, and cases where a ctx can be freed and a new one created 115 + * with the same address. 116 + */ 117 + int cur_ctx_seqno; 104 118 }; 105 119 106 120 struct msm_ringbuffer *msm_ringbuffer_new(struct msm_gpu *gpu, int id,
+7
drivers/gpu/drm/msm/msm_submitqueue.c
··· 161 161 struct msm_drm_private *priv = drm->dev_private; 162 162 struct msm_gpu_submitqueue *queue; 163 163 enum drm_sched_priority sched_prio; 164 + extern int enable_preemption; 165 + bool preemption_supported; 164 166 unsigned ring_nr; 165 167 int ret; 166 168 ··· 171 169 172 170 if (!priv->gpu) 173 171 return -ENODEV; 172 + 173 + preemption_supported = priv->gpu->nr_rings == 1 && enable_preemption != 0; 174 + 175 + if (flags & MSM_SUBMITQUEUE_ALLOW_PREEMPT && preemption_supported) 176 + return -EINVAL; 174 177 175 178 ret = msm_gpu_convert_priority(priv->gpu, prio, &ring_nr, &sched_prio); 176 179 if (ret)
+6 -1
drivers/gpu/drm/msm/registers/adreno/a6xx.xml
··· 2358 2358 <reg32 offset="0x0" name="REG" type="a6x_cp_protect"/> 2359 2359 </array> 2360 2360 2361 - <reg32 offset="0x08A0" name="CP_CONTEXT_SWITCH_CNTL"/> 2361 + <reg32 offset="0x08A0" name="CP_CONTEXT_SWITCH_CNTL"> 2362 + <bitfield name="STOP" pos="0" type="boolean"/> 2363 + <bitfield name="LEVEL" low="6" high="7"/> 2364 + <bitfield name="USES_GMEM" pos="8" type="boolean"/> 2365 + <bitfield name="SKIP_SAVE_RESTORE" pos="9" type="boolean"/> 2366 + </reg32> 2362 2367 <reg64 offset="0x08A1" name="CP_CONTEXT_SWITCH_SMMU_INFO"/> 2363 2368 <reg64 offset="0x08A3" name="CP_CONTEXT_SWITCH_PRIV_NON_SECURE_RESTORE_ADDR"/> 2364 2369 <reg64 offset="0x08A5" name="CP_CONTEXT_SWITCH_PRIV_SECURE_RESTORE_ADDR"/>
+17 -22
drivers/gpu/drm/msm/registers/adreno/adreno_pm4.xml
··· 581 581 and forcibly switch to the indicated context. 582 582 </doc> 583 583 <value name="CP_CONTEXT_SWITCH" value="0x54" variants="A6XX"/> 584 - <!-- Note, kgsl calls this CP_SET_AMBLE: --> 585 - <value name="CP_SET_CTXSWITCH_IB" value="0x55" variants="A6XX-"/> 584 + <value name="CP_SET_AMBLE" value="0x55" variants="A6XX-"/> 586 585 587 586 <!-- 588 587 Seems to always have the payload: ··· 2012 2013 </reg32> 2013 2014 </domain> 2014 2015 2015 - <domain name="CP_SET_CTXSWITCH_IB" width="32"> 2016 + <domain name="CP_SET_AMBLE" width="32"> 2016 2017 <doc> 2017 - Used by the userspace driver to set various IB's which are 2018 - executed during context save/restore for handling 2019 - state that isn't restored by the 2020 - context switch routine itself. 2021 - </doc> 2022 - <enum name="ctxswitch_ib"> 2023 - <value name="RESTORE_IB" value="0"> 2018 + Used by the userspace and kernel drivers to set various IB's 2019 + which are executed during context save/restore for handling 2020 + state that isn't restored by the context switch routine itself. 2021 + </doc> 2022 + <enum name="amble_type"> 2023 + <value name="PREAMBLE_AMBLE_TYPE" value="0"> 2024 2024 <doc>Executed unconditionally when switching back to the context.</doc> 2025 2025 </value> 2026 - <value name="YIELD_RESTORE_IB" value="1"> 2026 + <value name="BIN_PREAMBLE_AMBLE_TYPE" value="1"> 2027 2027 <doc> 2028 2028 Executed when switching back after switching 2029 2029 away during execution of 2030 - a CP_SET_MARKER packet with RM6_YIELD as the 2031 - payload *and* the normal save routine was 2032 - bypassed for a shorter one. I think this is 2033 - connected to the "skipsaverestore" bit set by 2034 - the kernel when preempting. 2030 + a CP_SET_MARKER packet with RM6_BIN_RENDER_END as the 2031 + payload *and* skipsaverestore is set. This is 2032 + expected to restore static register values not 2033 + saved when skipsaverestore is set. 2035 2034 </doc> 2036 2035 </value> 2037 - <value name="SAVE_IB" value="2"> 2036 + <value name="POSTAMBLE_AMBLE_TYPE" value="2"> 2038 2037 <doc> 2039 2038 Executed when switching away from the context, 2040 2039 except for context switches initiated via 2041 2040 CP_YIELD. 2042 2041 </doc> 2043 2042 </value> 2044 - <value name="RB_SAVE_IB" value="3"> 2043 + <value name="KMD_AMBLE_TYPE" value="3"> 2045 2044 <doc> 2046 2045 This can only be set by the RB (i.e. the kernel) 2047 2046 and executes with protected mode off, but 2048 - is otherwise similar to SAVE_IB. 2049 - 2050 - Note, kgsl calls this CP_KMD_AMBLE_TYPE 2047 + is otherwise similar to POSTAMBLE_AMBLE_TYPE. 2051 2048 </doc> 2052 2049 </value> 2053 2050 </enum> ··· 2055 2060 </reg32> 2056 2061 <reg32 offset="2" name="2"> 2057 2062 <bitfield name="DWORDS" low="0" high="19" type="uint"/> 2058 - <bitfield name="TYPE" low="20" high="21" type="ctxswitch_ib"/> 2063 + <bitfield name="TYPE" low="20" high="21" type="amble_type"/> 2059 2064 </reg32> 2060 2065 </domain> 2061 2066
+4 -1
include/uapi/drm/msm_drm.h
··· 347 347 * backwards compatibility as a "default" submitqueue 348 348 */ 349 349 350 - #define MSM_SUBMITQUEUE_FLAGS (0) 350 + #define MSM_SUBMITQUEUE_ALLOW_PREEMPT 0x00000001 351 + #define MSM_SUBMITQUEUE_FLAGS ( \ 352 + MSM_SUBMITQUEUE_ALLOW_PREEMPT | \ 353 + 0) 351 354 352 355 /* 353 356 * The submitqueue priority should be between 0 and MSM_PARAM_PRIORITIES-1,