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-2025-01-07' of gitlab.freedesktop.org:drm/msm into drm-next

Updates for v6.14

MDSS:
- properly described UBWC registers
- added SM6150 (aka QCS615) support

MDP4:
- several small fixes

DPU:
- added SM6150 (aka QCS615) support
- enabled wide planes if virtual planes are enabled (by using two SSPPs for a single plane)
- fixed modes filtering for platforms w/o 3DMux
- fixed DSPP DSPP_2 / _3 links on several platforms
- corrected DSPP definitions on SDM670
- added CWB hardware blocks support
- added VBIF to DPU snapshots
- dropped struct dpu_rm_requirements

DP:
- reworked DP audio support

DSI:
- added SM6150 (aka QCS615) support

GPU:
- Print GMU core fw version
- GMU bandwidth voting for a740 and a750
- Expose uche trap base via uapi
- UAPI error reporting

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

+2135 -702
+1
Documentation/devicetree/bindings/display/msm/dp-controller.yaml
··· 8 8 9 9 maintainers: 10 10 - Kuogee Hsieh <quic_khsieh@quicinc.com> 11 + - Abhinav Kumar <quic_abhinavk@quicinc.com> 11 12 12 13 description: | 13 14 Device tree bindings for DisplayPort host controller for MSM targets
+2
Documentation/devicetree/bindings/display/msm/dsi-controller-main.yaml
··· 30 30 - qcom,sdm845-dsi-ctrl 31 31 - qcom,sm6115-dsi-ctrl 32 32 - qcom,sm6125-dsi-ctrl 33 + - qcom,sm6150-dsi-ctrl 33 34 - qcom,sm6350-dsi-ctrl 34 35 - qcom,sm6375-dsi-ctrl 35 36 - qcom,sm7150-dsi-ctrl ··· 350 349 enum: 351 350 - qcom,sc7180-dsi-ctrl 352 351 - qcom,sc7280-dsi-ctrl 352 + - qcom,sm6150-dsi-ctrl 353 353 - qcom,sm7150-dsi-ctrl 354 354 - qcom,sm8150-dsi-ctrl 355 355 - qcom,sm8250-dsi-ctrl
+1
Documentation/devicetree/bindings/display/msm/dsi-phy-14nm.yaml
··· 20 20 - qcom,dsi-phy-14nm-660 21 21 - qcom,dsi-phy-14nm-8953 22 22 - qcom,sm6125-dsi-phy-14nm 23 + - qcom,sm6150-dsi-phy-14nm 23 24 24 25 reg: 25 26 items:
+2 -1
Documentation/devicetree/bindings/display/msm/qcom,sa8775p-mdss.yaml
··· 168 168 reg = <0xaf54000 0x104>, 169 169 <0xaf54200 0x0c0>, 170 170 <0xaf55000 0x770>, 171 - <0xaf56000 0x09c>; 171 + <0xaf56000 0x09c>, 172 + <0xaf57000 0x09c>; 172 173 173 174 interrupt-parent = <&mdss0>; 174 175 interrupts = <12>;
+108
Documentation/devicetree/bindings/display/msm/qcom,sm6150-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,sm6150-dpu.yaml# 5 + $schema: http://devicetree.org/meta-schemas/core.yaml# 6 + 7 + title: Qualcomm SM6150 Display DPU 8 + 9 + maintainers: 10 + - Abhinav Kumar <quic_abhinavk@quicinc.com> 11 + - Dmitry Baryshkov <dmitry.baryshkov@linaro.org> 12 + 13 + $ref: /schemas/display/msm/dpu-common.yaml# 14 + 15 + properties: 16 + compatible: 17 + const: qcom,sm6150-dpu 18 + 19 + reg: 20 + items: 21 + - description: Address offset and size for mdp register set 22 + - description: Address offset and size for vbif register set 23 + 24 + reg-names: 25 + items: 26 + - const: mdp 27 + - const: vbif 28 + 29 + clocks: 30 + items: 31 + - description: Display ahb clock 32 + - description: Display hf axi clock 33 + - description: Display core clock 34 + - description: Display vsync clock 35 + 36 + clock-names: 37 + items: 38 + - const: iface 39 + - const: bus 40 + - const: core 41 + - const: vsync 42 + 43 + unevaluatedProperties: false 44 + 45 + examples: 46 + - | 47 + #include <dt-bindings/interrupt-controller/arm-gic.h> 48 + #include <dt-bindings/power/qcom,rpmhpd.h> 49 + 50 + display-controller@ae01000 { 51 + compatible = "qcom,sm6150-dpu"; 52 + reg = <0x0ae01000 0x8f000>, 53 + <0x0aeb0000 0x2008>; 54 + reg-names = "mdp", "vbif"; 55 + 56 + clocks = <&dispcc_mdss_ahb_clk>, 57 + <&gcc_disp_hf_axi_clk>, 58 + <&dispcc_mdss_mdp_clk>, 59 + <&dispcc_mdss_vsync_clk>; 60 + clock-names = "iface", "bus", "core", "vsync"; 61 + 62 + assigned-clocks = <&dispcc_mdss_vsync_clk>; 63 + assigned-clock-rates = <19200000>; 64 + 65 + operating-points-v2 = <&mdp_opp_table>; 66 + power-domains = <&rpmhpd RPMHPD_CX>; 67 + 68 + interrupt-parent = <&mdss>; 69 + interrupts = <0>; 70 + 71 + ports { 72 + #address-cells = <1>; 73 + #size-cells = <0>; 74 + 75 + port@0 { 76 + reg = <0>; 77 + dpu_intf0_out: endpoint { 78 + }; 79 + }; 80 + 81 + port@1 { 82 + reg = <1>; 83 + dpu_intf1_out: endpoint { 84 + remote-endpoint = <&mdss_dsi0_in>; 85 + }; 86 + }; 87 + }; 88 + 89 + mdp_opp_table: opp-table { 90 + compatible = "operating-points-v2"; 91 + 92 + opp-19200000 { 93 + opp-hz = /bits/ 64 <19200000>; 94 + required-opps = <&rpmhpd_opp_low_svs>; 95 + }; 96 + 97 + opp-25600000 { 98 + opp-hz = /bits/ 64 <25600000>; 99 + required-opps = <&rpmhpd_opp_svs>; 100 + }; 101 + 102 + opp-307200000 { 103 + opp-hz = /bits/ 64 <307200000>; 104 + required-opps = <&rpmhpd_opp_nom>; 105 + }; 106 + }; 107 + }; 108 + ...
+245
Documentation/devicetree/bindings/display/msm/qcom,sm6150-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,sm6150-mdss.yaml# 5 + $schema: http://devicetree.org/meta-schemas/core.yaml# 6 + 7 + title: Qualcomm SM6150 Display MDSS 8 + 9 + maintainers: 10 + - Abhinav Kumar <quic_abhinavk@quicinc.com> 11 + - Dmitry Baryshkov <dmitry.baryshkov@linaro.org> 12 + 13 + description: 14 + Device tree bindings for MSM Mobile Display Subsystem(MDSS) that encapsulates 15 + sub-blocks like DPU display controller, DSI and DP interfaces etc. Device tree 16 + bindings of MDSS are mentioned for SM6150 target. 17 + 18 + $ref: /schemas/display/msm/mdss-common.yaml# 19 + 20 + properties: 21 + compatible: 22 + items: 23 + - const: qcom,sm6150-mdss 24 + 25 + clocks: 26 + items: 27 + - description: Display AHB clock from gcc 28 + - description: Display hf axi clock 29 + - description: Display core clock 30 + 31 + clock-names: 32 + items: 33 + - const: iface 34 + - const: bus 35 + - const: core 36 + 37 + iommus: 38 + maxItems: 1 39 + 40 + interconnects: 41 + maxItems: 2 42 + 43 + interconnect-names: 44 + maxItems: 2 45 + 46 + patternProperties: 47 + "^display-controller@[0-9a-f]+$": 48 + type: object 49 + additionalProperties: true 50 + properties: 51 + compatible: 52 + const: qcom,sm6150-dpu 53 + 54 + "^dsi@[0-9a-f]+$": 55 + type: object 56 + additionalProperties: true 57 + properties: 58 + compatible: 59 + items: 60 + - const: qcom,sm6150-dsi-ctrl 61 + - const: qcom,mdss-dsi-ctrl 62 + 63 + "^phy@[0-9a-f]+$": 64 + type: object 65 + additionalProperties: true 66 + properties: 67 + compatible: 68 + const: qcom,sm6150-dsi-phy-14nm 69 + 70 + unevaluatedProperties: false 71 + 72 + examples: 73 + - | 74 + #include <dt-bindings/clock/qcom,rpmh.h> 75 + #include <dt-bindings/interconnect/qcom,icc.h> 76 + #include <dt-bindings/interconnect/qcom,qcs615-rpmh.h> 77 + #include <dt-bindings/interrupt-controller/arm-gic.h> 78 + #include <dt-bindings/power/qcom,rpmhpd.h> 79 + 80 + display-subsystem@ae00000 { 81 + #address-cells = <1>; 82 + #size-cells = <1>; 83 + compatible = "qcom,sm6150-mdss"; 84 + reg = <0x0ae00000 0x1000>; 85 + reg-names = "mdss"; 86 + 87 + interconnects = <&mmss_noc MASTER_MDP0 QCOM_ICC_TAG_ALWAYS 88 + &mc_virt SLAVE_EBI1 QCOM_ICC_TAG_ALWAYS>, 89 + <&gem_noc MASTER_APPSS_PROC QCOM_ICC_TAG_ACTIVE_ONLY 90 + &config_noc SLAVE_DISPLAY_CFG QCOM_ICC_TAG_ACTIVE_ONLY>; 91 + interconnect-names = "mdp0-mem", "cpu-cfg"; 92 + 93 + power-domains = <&dispcc_mdss_gdsc>; 94 + 95 + clocks = <&dispcc_mdss_ahb_clk>, 96 + <&gcc_disp_hf_axi_clk>, 97 + <&dispcc_mdss_mdp_clk>; 98 + 99 + interrupts = <GIC_SPI 83 IRQ_TYPE_LEVEL_HIGH>; 100 + interrupt-controller; 101 + #interrupt-cells = <1>; 102 + 103 + iommus = <&apps_smmu 0x800 0x0>; 104 + 105 + ranges; 106 + 107 + display-controller@ae01000 { 108 + compatible = "qcom,sm6150-dpu"; 109 + reg = <0x0ae01000 0x8f000>, 110 + <0x0aeb0000 0x2008>; 111 + reg-names = "mdp", "vbif"; 112 + 113 + clocks = <&dispcc_mdss_ahb_clk>, 114 + <&gcc_disp_hf_axi_clk>, 115 + <&dispcc_mdss_mdp_clk>, 116 + <&dispcc_mdss_vsync_clk>; 117 + clock-names = "iface", "bus", "core", "vsync"; 118 + 119 + assigned-clocks = <&dispcc_mdss_vsync_clk>; 120 + assigned-clock-rates = <19200000>; 121 + 122 + operating-points-v2 = <&mdp_opp_table>; 123 + power-domains = <&rpmhpd RPMHPD_CX>; 124 + 125 + interrupt-parent = <&mdss>; 126 + interrupts = <0>; 127 + 128 + ports { 129 + #address-cells = <1>; 130 + #size-cells = <0>; 131 + 132 + port@0 { 133 + reg = <0>; 134 + dpu_intf0_out: endpoint { 135 + }; 136 + }; 137 + 138 + port@1 { 139 + reg = <1>; 140 + dpu_intf1_out: endpoint { 141 + remote-endpoint = <&mdss_dsi0_in>; 142 + }; 143 + }; 144 + }; 145 + 146 + mdp_opp_table: opp-table { 147 + compatible = "operating-points-v2"; 148 + 149 + opp-19200000 { 150 + opp-hz = /bits/ 64 <19200000>; 151 + required-opps = <&rpmhpd_opp_low_svs>; 152 + }; 153 + 154 + opp-25600000 { 155 + opp-hz = /bits/ 64 <25600000>; 156 + required-opps = <&rpmhpd_opp_svs>; 157 + }; 158 + 159 + opp-307200000 { 160 + opp-hz = /bits/ 64 <307200000>; 161 + required-opps = <&rpmhpd_opp_nom>; 162 + }; 163 + }; 164 + }; 165 + 166 + dsi@ae94000 { 167 + compatible = "qcom,sm6150-dsi-ctrl", 168 + "qcom,mdss-dsi-ctrl"; 169 + reg = <0x0ae94000 0x400>; 170 + reg-names = "dsi_ctrl"; 171 + 172 + interrupt-parent = <&mdss>; 173 + interrupts = <4>; 174 + 175 + clocks = <&dispcc_mdss_byte0_clk>, 176 + <&dispcc_mdss_byte0_intf_clk>, 177 + <&dispcc_mdss_pclk0_clk>, 178 + <&dispcc_mdss_esc0_clk>, 179 + <&dispcc_mdss_ahb_clk>, 180 + <&gcc_disp_hf_axi_clk>; 181 + clock-names = "byte", 182 + "byte_intf", 183 + "pixel", 184 + "core", 185 + "iface", 186 + "bus"; 187 + 188 + assigned-clocks = <&dispcc_mdss_byte0_clk_src>, 189 + <&dispcc_mdss_pclk0_clk_src>; 190 + assigned-clock-parents = <&mdss_dsi0_phy 0>, 191 + <&mdss_dsi0_phy 1>; 192 + 193 + operating-points-v2 = <&dsi0_opp_table>; 194 + 195 + phys = <&mdss_dsi0_phy>; 196 + 197 + #address-cells = <1>; 198 + #size-cells = <0>; 199 + 200 + ports { 201 + #address-cells = <1>; 202 + #size-cells = <0>; 203 + 204 + port@0 { 205 + reg = <0>; 206 + mdss_dsi0_in: endpoint { 207 + remote-endpoint = <&dpu_intf1_out>; 208 + }; 209 + }; 210 + 211 + port@1 { 212 + reg = <1>; 213 + mdss_dsi0_out: endpoint { 214 + }; 215 + }; 216 + }; 217 + 218 + dsi0_opp_table: opp-table { 219 + compatible = "operating-points-v2"; 220 + 221 + opp-164000000 { 222 + opp-hz = /bits/ 64 <164000000>; 223 + required-opps = <&rpmhpd_opp_low_svs>; 224 + }; 225 + }; 226 + }; 227 + 228 + mdss_dsi0_phy: phy@ae94400 { 229 + compatible = "qcom,sm6150-dsi-phy-14nm"; 230 + reg = <0x0ae94400 0x100>, 231 + <0x0ae94500 0x300>, 232 + <0x0ae94800 0x188>; 233 + reg-names = "dsi_phy", 234 + "dsi_phy_lane", 235 + "dsi_pll"; 236 + 237 + #clock-cells = <1>; 238 + #phy-cells = <0>; 239 + 240 + clocks = <&dispcc_mdss_ahb_clk>, 241 + <&rpmhcc RPMH_CXO_CLK>; 242 + clock-names = "iface", "ref"; 243 + }; 244 + }; 245 + ...
+1
drivers/gpu/drm/msm/Makefile
··· 78 78 disp/dpu1/dpu_hw_catalog.o \ 79 79 disp/dpu1/dpu_hw_cdm.o \ 80 80 disp/dpu1/dpu_hw_ctl.o \ 81 + disp/dpu1/dpu_hw_cwb.o \ 81 82 disp/dpu1/dpu_hw_dsc.o \ 82 83 disp/dpu1/dpu_hw_dsc_1_2.o \ 83 84 disp/dpu1/dpu_hw_interrupts.o \
+4 -2
drivers/gpu/drm/msm/adreno/a4xx_gpu.c
··· 251 251 gpu_write(gpu, REG_A4XX_UCHE_CACHE_WAYS_VFD, 0x07); 252 252 253 253 /* Disable L2 bypass to avoid UCHE out of bounds errors */ 254 - gpu_write(gpu, REG_A4XX_UCHE_TRAP_BASE_LO, 0xffff0000); 255 - gpu_write(gpu, REG_A4XX_UCHE_TRAP_BASE_HI, 0xffff0000); 254 + gpu_write(gpu, REG_A4XX_UCHE_TRAP_BASE_LO, lower_32_bits(adreno_gpu->uche_trap_base)); 255 + gpu_write(gpu, REG_A4XX_UCHE_TRAP_BASE_HI, upper_32_bits(adreno_gpu->uche_trap_base)); 256 256 257 257 gpu_write(gpu, REG_A4XX_CP_DEBUG, (1 << 25) | 258 258 (adreno_is_a420(adreno_gpu) ? (1 << 29) : 0)); ··· 692 692 &a4xx_gpu->ocmem); 693 693 if (ret) 694 694 goto fail; 695 + 696 + adreno_gpu->uche_trap_base = 0xffff0000ffff0000ull; 695 697 696 698 if (!gpu->aspace) { 697 699 /* TODO we think it is possible to configure the GPU to
+6 -9
drivers/gpu/drm/msm/adreno/a5xx_gpu.c
··· 750 750 gpu_write(gpu, REG_A5XX_UCHE_CACHE_WAYS, 0x02); 751 751 752 752 /* Disable L2 bypass in the UCHE */ 753 - gpu_write(gpu, REG_A5XX_UCHE_TRAP_BASE_LO, 0xFFFF0000); 754 - gpu_write(gpu, REG_A5XX_UCHE_TRAP_BASE_HI, 0x0001FFFF); 755 - gpu_write(gpu, REG_A5XX_UCHE_WRITE_THRU_BASE_LO, 0xFFFF0000); 756 - gpu_write(gpu, REG_A5XX_UCHE_WRITE_THRU_BASE_HI, 0x0001FFFF); 753 + gpu_write(gpu, REG_A5XX_UCHE_TRAP_BASE_LO, lower_32_bits(adreno_gpu->uche_trap_base)); 754 + gpu_write(gpu, REG_A5XX_UCHE_TRAP_BASE_HI, upper_32_bits(adreno_gpu->uche_trap_base)); 755 + gpu_write(gpu, REG_A5XX_UCHE_WRITE_THRU_BASE_LO, lower_32_bits(adreno_gpu->uche_trap_base)); 756 + gpu_write(gpu, REG_A5XX_UCHE_WRITE_THRU_BASE_HI, upper_32_bits(adreno_gpu->uche_trap_base)); 757 757 758 758 /* Set the GMEM VA range (0 to gpu->gmem) */ 759 759 gpu_write(gpu, REG_A5XX_UCHE_GMEM_RANGE_MIN_LO, 0x00100000); ··· 1760 1760 unsigned int nr_rings; 1761 1761 int ret; 1762 1762 1763 - if (!pdev) { 1764 - DRM_DEV_ERROR(dev->dev, "No A5XX device is defined\n"); 1765 - return ERR_PTR(-ENXIO); 1766 - } 1767 - 1768 1763 a5xx_gpu = kzalloc(sizeof(*a5xx_gpu), GFP_KERNEL); 1769 1764 if (!a5xx_gpu) 1770 1765 return ERR_PTR(-ENOMEM); ··· 1799 1804 /* a5xx only supports UBWC 1.0, these are not configurable */ 1800 1805 adreno_gpu->ubwc_config.macrotile_mode = 0; 1801 1806 adreno_gpu->ubwc_config.ubwc_swizzle = 0x7; 1807 + 1808 + adreno_gpu->uche_trap_base = 0x0001ffffffff0000ull; 1802 1809 1803 1810 return gpu; 1804 1811 }
+22
drivers/gpu/drm/msm/adreno/a6xx_catalog.c
··· 1388 1388 .pwrup_reglist = &a7xx_pwrup_reglist, 1389 1389 .gmu_chipid = 0x7020100, 1390 1390 .gmu_cgc_mode = 0x00020202, 1391 + .bcms = (const struct a6xx_bcm[]) { 1392 + { .name = "SH0", .buswidth = 16 }, 1393 + { .name = "MC0", .buswidth = 4 }, 1394 + { 1395 + .name = "ACV", 1396 + .fixed = true, 1397 + .perfmode = BIT(3), 1398 + .perfmode_bw = 16500000, 1399 + }, 1400 + { /* sentinel */ }, 1401 + }, 1391 1402 }, 1392 1403 .address_space_size = SZ_16G, 1393 1404 .preempt_record_size = 4192 * SZ_1K, ··· 1443 1432 .pwrup_reglist = &a7xx_pwrup_reglist, 1444 1433 .gmu_chipid = 0x7090100, 1445 1434 .gmu_cgc_mode = 0x00020202, 1435 + .bcms = (const struct a6xx_bcm[]) { 1436 + { .name = "SH0", .buswidth = 16 }, 1437 + { .name = "MC0", .buswidth = 4 }, 1438 + { 1439 + .name = "ACV", 1440 + .fixed = true, 1441 + .perfmode = BIT(2), 1442 + .perfmode_bw = 10687500, 1443 + }, 1444 + { /* sentinel */ }, 1445 + }, 1446 1446 }, 1447 1447 .address_space_size = SZ_16G, 1448 1448 .preempt_record_size = 3572 * SZ_1K,
+198 -5
drivers/gpu/drm/msm/adreno/a6xx_gmu.c
··· 9 9 #include <linux/pm_domain.h> 10 10 #include <linux/pm_opp.h> 11 11 #include <soc/qcom/cmd-db.h> 12 + #include <soc/qcom/tcs.h> 12 13 #include <drm/drm_gem.h> 13 14 14 15 #include "a6xx_gpu.h" ··· 110 109 bool suspended) 111 110 { 112 111 struct adreno_gpu *adreno_gpu = to_adreno_gpu(gpu); 112 + const struct a6xx_info *info = adreno_gpu->info->a6xx; 113 113 struct a6xx_gpu *a6xx_gpu = to_a6xx_gpu(adreno_gpu); 114 114 struct a6xx_gmu *gmu = &a6xx_gpu->gmu; 115 115 u32 perf_index; 116 + u32 bw_index = 0; 116 117 unsigned long gpu_freq; 117 118 int ret = 0; 118 119 ··· 126 123 for (perf_index = 0; perf_index < gmu->nr_gpu_freqs - 1; perf_index++) 127 124 if (gpu_freq == gmu->gpu_freqs[perf_index]) 128 125 break; 126 + 127 + /* If enabled, find the corresponding DDR bandwidth index */ 128 + if (info->bcms && gmu->nr_gpu_bws > 1) { 129 + unsigned int bw = dev_pm_opp_get_bw(opp, true, 0); 130 + 131 + for (bw_index = 0; bw_index < gmu->nr_gpu_bws - 1; bw_index++) { 132 + if (bw == gmu->gpu_bw_table[bw_index]) 133 + break; 134 + } 135 + 136 + /* Vote AB as a fraction of the max bandwidth, starting from A750 */ 137 + if (bw && adreno_is_a750_family(adreno_gpu)) { 138 + u64 tmp; 139 + 140 + /* For now, vote for 25% of the bandwidth */ 141 + tmp = bw * 25; 142 + do_div(tmp, 100); 143 + 144 + /* 145 + * The AB vote consists of a 16 bit wide quantized level 146 + * against the maximum supported bandwidth. 147 + * Quantization can be calculated as below: 148 + * vote = (bandwidth * 2^16) / max bandwidth 149 + */ 150 + tmp *= MAX_AB_VOTE; 151 + do_div(tmp, gmu->gpu_bw_table[gmu->nr_gpu_bws - 1]); 152 + 153 + bw_index |= AB_VOTE(clamp(tmp, 1, MAX_AB_VOTE)); 154 + bw_index |= AB_VOTE_ENABLE; 155 + } 156 + } 129 157 130 158 gmu->current_perf_index = perf_index; 131 159 gmu->freq = gmu->gpu_freqs[perf_index]; ··· 173 139 return; 174 140 175 141 if (!gmu->legacy) { 176 - a6xx_hfi_set_freq(gmu, perf_index); 177 - dev_pm_opp_set_opp(&gpu->pdev->dev, opp); 142 + a6xx_hfi_set_freq(gmu, perf_index, bw_index); 143 + /* With Bandwidth voting, we now vote for all resources, so skip OPP set */ 144 + if (!bw_index) 145 + dev_pm_opp_set_opp(&gpu->pdev->dev, opp); 178 146 return; 179 147 } 180 148 ··· 765 729 const struct firmware *fw_image = adreno_gpu->fw[ADRENO_FW_GMU]; 766 730 const struct block_header *blk; 767 731 u32 reg_offset; 732 + u32 ver; 768 733 769 734 u32 itcm_base = 0x00000000; 770 735 u32 dtcm_base = 0x00040000; ··· 811 774 blk->addr, blk->size, blk->data[0]); 812 775 } 813 776 } 777 + 778 + ver = gmu_read(gmu, REG_A6XX_GMU_CORE_FW_VERSION); 779 + DRM_INFO("Loaded GMU firmware v%u.%u.%u\n", 780 + FIELD_GET(A6XX_GMU_CORE_FW_VERSION_MAJOR__MASK, ver), 781 + FIELD_GET(A6XX_GMU_CORE_FW_VERSION_MINOR__MASK, ver), 782 + FIELD_GET(A6XX_GMU_CORE_FW_VERSION_STEP__MASK, ver)); 814 783 815 784 return 0; 816 785 } ··· 1308 1265 bo->virt = msm_gem_get_vaddr(bo->obj); 1309 1266 bo->size = size; 1310 1267 1311 - msm_gem_object_set_name(bo->obj, name); 1268 + msm_gem_object_set_name(bo->obj, "%s", name); 1312 1269 1313 1270 return 0; 1314 1271 } ··· 1326 1283 gmu->aspace = msm_gem_address_space_create(mmu, "gmu", 0x0, 0x80000000); 1327 1284 if (IS_ERR(gmu->aspace)) 1328 1285 return PTR_ERR(gmu->aspace); 1286 + 1287 + return 0; 1288 + } 1289 + 1290 + /** 1291 + * struct bcm_db - Auxiliary data pertaining to each Bus Clock Manager (BCM) 1292 + * @unit: divisor used to convert bytes/sec bw value to an RPMh msg 1293 + * @width: multiplier used to convert bytes/sec bw value to an RPMh msg 1294 + * @vcd: virtual clock domain that this bcm belongs to 1295 + * @reserved: reserved field 1296 + */ 1297 + struct bcm_db { 1298 + __le32 unit; 1299 + __le16 width; 1300 + u8 vcd; 1301 + u8 reserved; 1302 + }; 1303 + 1304 + static int a6xx_gmu_rpmh_bw_votes_init(struct adreno_gpu *adreno_gpu, 1305 + const struct a6xx_info *info, 1306 + struct a6xx_gmu *gmu) 1307 + { 1308 + const struct bcm_db *bcm_data[GMU_MAX_BCMS] = { 0 }; 1309 + unsigned int bcm_index, bw_index, bcm_count = 0; 1310 + 1311 + /* Retrieve BCM data from cmd-db */ 1312 + for (bcm_index = 0; bcm_index < GMU_MAX_BCMS; bcm_index++) { 1313 + const struct a6xx_bcm *bcm = &info->bcms[bcm_index]; 1314 + size_t count; 1315 + 1316 + /* Stop at NULL terminated bcm entry */ 1317 + if (!bcm->name) 1318 + break; 1319 + 1320 + bcm_data[bcm_index] = cmd_db_read_aux_data(bcm->name, &count); 1321 + if (IS_ERR(bcm_data[bcm_index])) 1322 + return PTR_ERR(bcm_data[bcm_index]); 1323 + 1324 + if (!count) { 1325 + dev_err(gmu->dev, "invalid BCM '%s' aux data size\n", 1326 + bcm->name); 1327 + return -EINVAL; 1328 + } 1329 + 1330 + bcm_count++; 1331 + } 1332 + 1333 + /* Generate BCM votes values for each bandwidth & BCM */ 1334 + for (bw_index = 0; bw_index < gmu->nr_gpu_bws; bw_index++) { 1335 + u32 *data = gmu->gpu_ib_votes[bw_index]; 1336 + u32 bw = gmu->gpu_bw_table[bw_index]; 1337 + 1338 + /* Calculations loosely copied from bcm_aggregate() & tcs_cmd_gen() */ 1339 + for (bcm_index = 0; bcm_index < bcm_count; bcm_index++) { 1340 + const struct a6xx_bcm *bcm = &info->bcms[bcm_index]; 1341 + bool commit = false; 1342 + u64 peak; 1343 + u32 vote; 1344 + 1345 + if (bcm_index == bcm_count - 1 || 1346 + (bcm_data[bcm_index + 1] && 1347 + bcm_data[bcm_index]->vcd != bcm_data[bcm_index + 1]->vcd)) 1348 + commit = true; 1349 + 1350 + if (!bw) { 1351 + data[bcm_index] = BCM_TCS_CMD(commit, false, 0, 0); 1352 + continue; 1353 + } 1354 + 1355 + if (bcm->fixed) { 1356 + u32 perfmode = 0; 1357 + 1358 + /* GMU on A6xx votes perfmode on all valid bandwidth */ 1359 + if (!adreno_is_a7xx(adreno_gpu) || 1360 + (bcm->perfmode_bw && bw >= bcm->perfmode_bw)) 1361 + perfmode = bcm->perfmode; 1362 + 1363 + data[bcm_index] = BCM_TCS_CMD(commit, true, 0, perfmode); 1364 + continue; 1365 + } 1366 + 1367 + /* Multiply the bandwidth by the width of the connection */ 1368 + peak = (u64)bw * le16_to_cpu(bcm_data[bcm_index]->width); 1369 + do_div(peak, bcm->buswidth); 1370 + 1371 + /* Input bandwidth value is in KBps, scale the value to BCM unit */ 1372 + peak *= 1000; 1373 + do_div(peak, le32_to_cpu(bcm_data[bcm_index]->unit)); 1374 + 1375 + vote = clamp(peak, 1, BCM_TCS_CMD_VOTE_MASK); 1376 + 1377 + /* GMUs on A7xx votes on both x & y */ 1378 + if (adreno_is_a7xx(adreno_gpu)) 1379 + data[bcm_index] = BCM_TCS_CMD(commit, true, vote, vote); 1380 + else 1381 + data[bcm_index] = BCM_TCS_CMD(commit, true, 0, vote); 1382 + } 1383 + } 1329 1384 1330 1385 return 0; 1331 1386 } ··· 1531 1390 * The GMU votes with the RPMh for itself and on behalf of the GPU but we need 1532 1391 * to construct the list of votes on the CPU and send it over. Query the RPMh 1533 1392 * voltage levels and build the votes 1393 + * The GMU can also vote for DDR interconnects, use the OPP bandwidth entries 1394 + * and BCM parameters to build the votes. 1534 1395 */ 1535 1396 1536 1397 static int a6xx_gmu_rpmh_votes_init(struct a6xx_gmu *gmu) 1537 1398 { 1538 1399 struct a6xx_gpu *a6xx_gpu = container_of(gmu, struct a6xx_gpu, gmu); 1539 1400 struct adreno_gpu *adreno_gpu = &a6xx_gpu->base; 1401 + const struct a6xx_info *info = adreno_gpu->info->a6xx; 1540 1402 struct msm_gpu *gpu = &adreno_gpu->base; 1541 1403 int ret; 1542 1404 ··· 1550 1406 /* Build the CX votes */ 1551 1407 ret |= a6xx_gmu_rpmh_arc_votes_init(gmu->dev, gmu->cx_arc_votes, 1552 1408 gmu->gmu_freqs, gmu->nr_gmu_freqs, "cx.lvl"); 1409 + 1410 + /* Build the interconnect votes */ 1411 + if (info->bcms && gmu->nr_gpu_bws > 1) 1412 + ret |= a6xx_gmu_rpmh_bw_votes_init(adreno_gpu, info, gmu); 1553 1413 1554 1414 return ret; 1555 1415 } ··· 1590 1442 return index; 1591 1443 } 1592 1444 1445 + static int a6xx_gmu_build_bw_table(struct device *dev, unsigned long *bandwidths, 1446 + u32 size) 1447 + { 1448 + int count = dev_pm_opp_get_opp_count(dev); 1449 + struct dev_pm_opp *opp; 1450 + int i, index = 0; 1451 + unsigned int bandwidth = 1; 1452 + 1453 + /* 1454 + * The OPP table doesn't contain the "off" bandwidth level so we need to 1455 + * add 1 to the table size to account for it 1456 + */ 1457 + 1458 + if (WARN(count + 1 > size, 1459 + "The GMU bandwidth table is being truncated\n")) 1460 + count = size - 1; 1461 + 1462 + /* Set the "off" bandwidth */ 1463 + bandwidths[index++] = 0; 1464 + 1465 + for (i = 0; i < count; i++) { 1466 + opp = dev_pm_opp_find_bw_ceil(dev, &bandwidth, 0); 1467 + if (IS_ERR(opp)) 1468 + break; 1469 + 1470 + dev_pm_opp_put(opp); 1471 + bandwidths[index++] = bandwidth++; 1472 + } 1473 + 1474 + return index; 1475 + } 1476 + 1593 1477 static int a6xx_gmu_pwrlevels_probe(struct a6xx_gmu *gmu) 1594 1478 { 1595 1479 struct a6xx_gpu *a6xx_gpu = container_of(gmu, struct a6xx_gpu, gmu); 1596 1480 struct adreno_gpu *adreno_gpu = &a6xx_gpu->base; 1481 + const struct a6xx_info *info = adreno_gpu->info->a6xx; 1597 1482 struct msm_gpu *gpu = &adreno_gpu->base; 1598 1483 1599 1484 int ret = 0; ··· 1652 1471 gmu->gpu_freqs, ARRAY_SIZE(gmu->gpu_freqs)); 1653 1472 1654 1473 gmu->current_perf_index = gmu->nr_gpu_freqs - 1; 1474 + 1475 + /* 1476 + * The GMU also handles GPU Interconnect Votes so build a list 1477 + * of DDR bandwidths from the GPU OPP table 1478 + */ 1479 + if (info->bcms) 1480 + gmu->nr_gpu_bws = a6xx_gmu_build_bw_table(&gpu->pdev->dev, 1481 + gmu->gpu_bw_table, ARRAY_SIZE(gmu->gpu_bw_table)); 1655 1482 1656 1483 /* Build the list of RPMh votes that we'll send to the GMU */ 1657 1484 return a6xx_gmu_rpmh_votes_init(gmu); ··· 1792 1603 1793 1604 gmu->dev = &pdev->dev; 1794 1605 1795 - of_dma_configure(gmu->dev, node, true); 1606 + ret = of_dma_configure(gmu->dev, node, true); 1607 + if (ret) 1608 + return ret; 1796 1609 1797 1610 pm_runtime_enable(gmu->dev); 1798 1611 ··· 1859 1668 1860 1669 gmu->dev = &pdev->dev; 1861 1670 1862 - of_dma_configure(gmu->dev, node, true); 1671 + ret = of_dma_configure(gmu->dev, node, true); 1672 + if (ret) 1673 + return ret; 1863 1674 1864 1675 /* Fow now, don't do anything fancy until we get our feet under us */ 1865 1676 gmu->idle_level = GMU_IDLE_STATE_ACTIVE;
+21 -5
drivers/gpu/drm/msm/adreno/a6xx_gmu.h
··· 19 19 u64 iova; 20 20 }; 21 21 22 + #define GMU_MAX_GX_FREQS 16 23 + #define GMU_MAX_CX_FREQS 4 24 + #define GMU_MAX_BCMS 3 25 + 26 + struct a6xx_bcm { 27 + char *name; 28 + unsigned int buswidth; 29 + bool fixed; 30 + unsigned int perfmode; 31 + unsigned int perfmode_bw; 32 + }; 33 + 22 34 /* 23 35 * These define the different GMU wake up options - these define how both the 24 36 * CPU and the GMU bring up the hardware ··· 91 79 int current_perf_index; 92 80 93 81 int nr_gpu_freqs; 94 - unsigned long gpu_freqs[16]; 95 - u32 gx_arc_votes[16]; 82 + unsigned long gpu_freqs[GMU_MAX_GX_FREQS]; 83 + u32 gx_arc_votes[GMU_MAX_GX_FREQS]; 84 + 85 + int nr_gpu_bws; 86 + unsigned long gpu_bw_table[GMU_MAX_GX_FREQS]; 87 + u32 gpu_ib_votes[GMU_MAX_GX_FREQS][GMU_MAX_BCMS]; 96 88 97 89 int nr_gmu_freqs; 98 - unsigned long gmu_freqs[4]; 99 - u32 cx_arc_votes[4]; 90 + unsigned long gmu_freqs[GMU_MAX_CX_FREQS]; 91 + u32 cx_arc_votes[GMU_MAX_CX_FREQS]; 100 92 101 93 unsigned long freq; 102 94 ··· 209 193 int a6xx_hfi_start(struct a6xx_gmu *gmu, int boot_state); 210 194 void a6xx_hfi_stop(struct a6xx_gmu *gmu); 211 195 int a6xx_hfi_send_prep_slumber(struct a6xx_gmu *gmu); 212 - int a6xx_hfi_set_freq(struct a6xx_gmu *gmu, int index); 196 + int a6xx_hfi_set_freq(struct a6xx_gmu *gmu, u32 perf_index, u32 bw_index); 213 197 214 198 bool a6xx_gmu_gx_is_on(struct a6xx_gmu *gmu); 215 199 bool a6xx_gmu_sptprac_is_on(struct a6xx_gmu *gmu);
+7 -5
drivers/gpu/drm/msm/adreno/a6xx_gpu.c
··· 1123 1123 1124 1124 /* Disable L2 bypass in the UCHE */ 1125 1125 if (adreno_is_a7xx(adreno_gpu)) { 1126 - gpu_write64(gpu, REG_A6XX_UCHE_TRAP_BASE, 0x0001fffffffff000llu); 1127 - gpu_write64(gpu, REG_A6XX_UCHE_WRITE_THRU_BASE, 0x0001fffffffff000llu); 1126 + gpu_write64(gpu, REG_A6XX_UCHE_TRAP_BASE, adreno_gpu->uche_trap_base); 1127 + gpu_write64(gpu, REG_A6XX_UCHE_WRITE_THRU_BASE, adreno_gpu->uche_trap_base); 1128 1128 } else { 1129 - gpu_write64(gpu, REG_A6XX_UCHE_WRITE_RANGE_MAX, 0x0001ffffffffffc0llu); 1130 - gpu_write64(gpu, REG_A6XX_UCHE_TRAP_BASE, 0x0001fffffffff000llu); 1131 - gpu_write64(gpu, REG_A6XX_UCHE_WRITE_THRU_BASE, 0x0001fffffffff000llu); 1129 + gpu_write64(gpu, REG_A6XX_UCHE_WRITE_RANGE_MAX, adreno_gpu->uche_trap_base + 0xfc0); 1130 + gpu_write64(gpu, REG_A6XX_UCHE_TRAP_BASE, adreno_gpu->uche_trap_base); 1131 + gpu_write64(gpu, REG_A6XX_UCHE_WRITE_THRU_BASE, adreno_gpu->uche_trap_base); 1132 1132 } 1133 1133 1134 1134 if (!(adreno_is_a650_family(adreno_gpu) || ··· 2532 2532 return ERR_PTR(ret); 2533 2533 } 2534 2534 } 2535 + 2536 + adreno_gpu->uche_trap_base = 0x1fffffffff000ull; 2535 2537 2536 2538 if (gpu->aspace) 2537 2539 msm_mmu_set_fault_handler(gpu->aspace->mmu, gpu,
+1
drivers/gpu/drm/msm/adreno/a6xx_gpu.h
··· 44 44 u32 gmu_chipid; 45 45 u32 gmu_cgc_mode; 46 46 u32 prim_fifo_threshold; 47 + const struct a6xx_bcm *bcms; 47 48 }; 48 49 49 50 struct a6xx_gpu {
+50 -4
drivers/gpu/drm/msm/adreno/a6xx_hfi.c
··· 6 6 #include <linux/list.h> 7 7 8 8 #include <soc/qcom/cmd-db.h> 9 + #include <soc/qcom/tcs.h> 9 10 10 11 #include "a6xx_gmu.h" 11 12 #include "a6xx_gmu.xml.h" ··· 258 257 259 258 return a6xx_hfi_send_msg(gmu, HFI_H2F_MSG_PERF_TABLE, &msg, sizeof(msg), 260 259 NULL, 0); 260 + } 261 + 262 + static void a6xx_generate_bw_table(const struct a6xx_info *info, struct a6xx_gmu *gmu, 263 + struct a6xx_hfi_msg_bw_table *msg) 264 + { 265 + unsigned int i, j; 266 + 267 + for (i = 0; i < GMU_MAX_BCMS; i++) { 268 + if (!info->bcms[i].name) 269 + break; 270 + msg->ddr_cmds_addrs[i] = cmd_db_read_addr(info->bcms[i].name); 271 + } 272 + msg->ddr_cmds_num = i; 273 + 274 + for (i = 0; i < gmu->nr_gpu_bws; ++i) 275 + for (j = 0; j < msg->ddr_cmds_num; j++) 276 + msg->ddr_cmds_data[i][j] = gmu->gpu_ib_votes[i][j]; 277 + msg->bw_level_num = gmu->nr_gpu_bws; 278 + 279 + /* Compute the wait bitmask with each BCM having the commit bit */ 280 + msg->ddr_wait_bitmask = 0; 281 + for (j = 0; j < msg->ddr_cmds_num; j++) 282 + if (msg->ddr_cmds_data[0][j] & BCM_TCS_CMD_COMMIT_MASK) 283 + msg->ddr_wait_bitmask |= BIT(j); 284 + 285 + /* 286 + * These are the CX (CNOC) votes - these are used by the GMU 287 + * The 'CN0' BCM is used on all targets, and votes are basically 288 + * 'off' and 'on' states with first bit to enable the path. 289 + */ 290 + 291 + msg->cnoc_cmds_addrs[0] = cmd_db_read_addr("CN0"); 292 + msg->cnoc_cmds_num = 1; 293 + 294 + msg->cnoc_cmds_data[0][0] = BCM_TCS_CMD(true, false, 0, 0); 295 + msg->cnoc_cmds_data[1][0] = BCM_TCS_CMD(true, true, 0, BIT(0)); 296 + 297 + /* Compute the wait bitmask with each BCM having the commit bit */ 298 + msg->cnoc_wait_bitmask = 0; 299 + for (j = 0; j < msg->cnoc_cmds_num; j++) 300 + if (msg->cnoc_cmds_data[0][j] & BCM_TCS_CMD_COMMIT_MASK) 301 + msg->cnoc_wait_bitmask |= BIT(j); 261 302 } 262 303 263 304 static void a618_build_bw_table(struct a6xx_hfi_msg_bw_table *msg) ··· 707 664 struct a6xx_hfi_msg_bw_table *msg; 708 665 struct a6xx_gpu *a6xx_gpu = container_of(gmu, struct a6xx_gpu, gmu); 709 666 struct adreno_gpu *adreno_gpu = &a6xx_gpu->base; 667 + const struct a6xx_info *info = adreno_gpu->info->a6xx; 710 668 711 669 if (gmu->bw_table) 712 670 goto send; ··· 716 672 if (!msg) 717 673 return -ENOMEM; 718 674 719 - if (adreno_is_a618(adreno_gpu)) 675 + if (info->bcms && gmu->nr_gpu_bws > 1) 676 + a6xx_generate_bw_table(info, gmu, msg); 677 + else if (adreno_is_a618(adreno_gpu)) 720 678 a618_build_bw_table(msg); 721 679 else if (adreno_is_a619(adreno_gpu)) 722 680 a619_build_bw_table(msg); ··· 772 726 sizeof(msg), NULL, 0); 773 727 } 774 728 775 - int a6xx_hfi_set_freq(struct a6xx_gmu *gmu, int index) 729 + int a6xx_hfi_set_freq(struct a6xx_gmu *gmu, u32 freq_index, u32 bw_index) 776 730 { 777 731 struct a6xx_hfi_gx_bw_perf_vote_cmd msg = { 0 }; 778 732 779 733 msg.ack_type = 1; /* blocking */ 780 - msg.freq = index; 781 - msg.bw = 0; /* TODO: bus scaling */ 734 + msg.freq = freq_index; 735 + msg.bw = bw_index; 782 736 783 737 return a6xx_hfi_send_msg(gmu, HFI_H2F_MSG_GX_BW_PERF_VOTE, &msg, 784 738 sizeof(msg), NULL, 0);
+5
drivers/gpu/drm/msm/adreno/a6xx_hfi.h
··· 173 173 u32 bw; 174 174 }; 175 175 176 + #define AB_VOTE_MASK GENMASK(31, 16) 177 + #define MAX_AB_VOTE (FIELD_MAX(AB_VOTE_MASK) - 1) 178 + #define AB_VOTE(vote) FIELD_PREP(AB_VOTE_MASK, (vote)) 179 + #define AB_VOTE_ENABLE BIT(8) 180 + 176 181 #define HFI_H2F_MSG_PREPARE_SLUMBER 33 177 182 178 183 struct a6xx_hfi_prep_slumber_cmd {
+14 -10
drivers/gpu/drm/msm/adreno/adreno_gpu.c
··· 310 310 uint32_t param, uint64_t *value, uint32_t *len) 311 311 { 312 312 struct adreno_gpu *adreno_gpu = to_adreno_gpu(gpu); 313 + struct drm_device *drm = gpu->dev; 313 314 314 315 /* No pointer params yet */ 315 316 if (*len != 0) 316 - return -EINVAL; 317 + return UERR(EINVAL, drm, "invalid len"); 317 318 318 319 switch (param) { 319 320 case MSM_PARAM_GPU_ID: ··· 366 365 return 0; 367 366 case MSM_PARAM_VA_START: 368 367 if (ctx->aspace == gpu->aspace) 369 - return -EINVAL; 368 + return UERR(EINVAL, drm, "requires per-process pgtables"); 370 369 *value = ctx->aspace->va_start; 371 370 return 0; 372 371 case MSM_PARAM_VA_SIZE: 373 372 if (ctx->aspace == gpu->aspace) 374 - return -EINVAL; 373 + return UERR(EINVAL, drm, "requires per-process pgtables"); 375 374 *value = ctx->aspace->va_size; 376 375 return 0; 377 376 case MSM_PARAM_HIGHEST_BANK_BIT: ··· 386 385 case MSM_PARAM_MACROTILE_MODE: 387 386 *value = adreno_gpu->ubwc_config.macrotile_mode; 388 387 return 0; 388 + case MSM_PARAM_UCHE_TRAP_BASE: 389 + *value = adreno_gpu->uche_trap_base; 390 + return 0; 389 391 default: 390 - DBG("%s: invalid param: %u", gpu->name, param); 391 - return -EINVAL; 392 + return UERR(EINVAL, drm, "%s: invalid param: %u", gpu->name, param); 392 393 } 393 394 } 394 395 395 396 int adreno_set_param(struct msm_gpu *gpu, struct msm_file_private *ctx, 396 397 uint32_t param, uint64_t value, uint32_t len) 397 398 { 399 + struct drm_device *drm = gpu->dev; 400 + 398 401 switch (param) { 399 402 case MSM_PARAM_COMM: 400 403 case MSM_PARAM_CMDLINE: ··· 406 401 * that should be a reasonable upper bound 407 402 */ 408 403 if (len > PAGE_SIZE) 409 - return -EINVAL; 404 + return UERR(EINVAL, drm, "invalid len"); 410 405 break; 411 406 default: 412 407 if (len != 0) 413 - return -EINVAL; 408 + return UERR(EINVAL, drm, "invalid len"); 414 409 } 415 410 416 411 switch (param) { ··· 439 434 } 440 435 case MSM_PARAM_SYSPROF: 441 436 if (!capable(CAP_SYS_ADMIN)) 442 - return -EPERM; 437 + return UERR(EPERM, drm, "invalid permissions"); 443 438 return msm_file_private_set_sysprof(ctx, gpu, value); 444 439 default: 445 - DBG("%s: invalid param: %u", gpu->name, param); 446 - return -EINVAL; 440 + return UERR(EINVAL, drm, "%s: invalid param: %u", gpu->name, param); 447 441 } 448 442 } 449 443
+7
drivers/gpu/drm/msm/adreno/adreno_gpu.h
··· 253 253 bool gmu_is_wrapper; 254 254 255 255 bool has_ray_tracing; 256 + 257 + u64 uche_trap_base; 256 258 }; 257 259 #define to_adreno_gpu(x) container_of(x, struct adreno_gpu, base) 258 260 ··· 559 557 return false; 560 558 return gpu->info->family == ADRENO_7XX_GEN2 || 561 559 gpu->info->family == ADRENO_7XX_GEN3; 560 + } 561 + 562 + static inline int adreno_is_a750_family(struct adreno_gpu *gpu) 563 + { 564 + return gpu->info->family == ADRENO_7XX_GEN3; 562 565 } 563 566 564 567 static inline int adreno_is_a7xx(struct adreno_gpu *gpu)
+27 -4
drivers/gpu/drm/msm/disp/dpu1/catalog/dpu_10_0_sm8650.h
··· 160 160 .sblk = &sdm845_lm_sblk, 161 161 .lm_pair = LM_3, 162 162 .pingpong = PINGPONG_2, 163 + .dspp = DSPP_2, 163 164 }, { 164 165 .name = "lm_3", .id = LM_3, 165 166 .base = 0x47000, .len = 0x400, ··· 168 167 .sblk = &sdm845_lm_sblk, 169 168 .lm_pair = LM_2, 170 169 .pingpong = PINGPONG_3, 170 + .dspp = DSPP_3, 171 171 }, { 172 172 .name = "lm_4", .id = LM_4, 173 173 .base = 0x48000, .len = 0x400, ··· 254 252 .merge_3d = MERGE_3D_2, 255 253 .intr_done = DPU_IRQ_IDX(MDP_SSPP_TOP0_INTR2, 31), 256 254 }, { 257 - .name = "pingpong_6", .id = PINGPONG_6, 255 + .name = "pingpong_cwb_0", .id = PINGPONG_CWB_0, 258 256 .base = 0x66000, .len = 0, 259 257 .features = BIT(DPU_PINGPONG_DITHER), 260 258 .sblk = &sc7280_pp_sblk, 261 259 .merge_3d = MERGE_3D_3, 262 260 }, { 263 - .name = "pingpong_7", .id = PINGPONG_7, 261 + .name = "pingpong_cwb_1", .id = PINGPONG_CWB_1, 264 262 .base = 0x66400, .len = 0, 265 263 .features = BIT(DPU_PINGPONG_DITHER), 266 264 .sblk = &sc7280_pp_sblk, 267 265 .merge_3d = MERGE_3D_3, 268 266 }, { 269 - .name = "pingpong_8", .id = PINGPONG_8, 267 + .name = "pingpong_cwb_2", .id = PINGPONG_CWB_2, 270 268 .base = 0x7e000, .len = 0, 271 269 .features = BIT(DPU_PINGPONG_DITHER), 272 270 .sblk = &sc7280_pp_sblk, 273 271 .merge_3d = MERGE_3D_4, 274 272 }, { 275 - .name = "pingpong_9", .id = PINGPONG_9, 273 + .name = "pingpong_cwb_3", .id = PINGPONG_CWB_3, 276 274 .base = 0x7e400, .len = 0, 277 275 .features = BIT(DPU_PINGPONG_DITHER), 278 276 .sblk = &sc7280_pp_sblk, ··· 349 347 .vbif_idx = VBIF_RT, 350 348 .maxlinewidth = 4096, 351 349 .intr_wb_done = DPU_IRQ_IDX(MDP_SSPP_TOP0_INTR, 4), 350 + }, 351 + }; 352 + 353 + static const struct dpu_cwb_cfg sm8650_cwb[] = { 354 + { 355 + .name = "cwb_0", .id = CWB_0, 356 + .base = 0x66200, .len = 0x8, 357 + }, 358 + { 359 + .name = "cwb_1", .id = CWB_1, 360 + .base = 0x66600, .len = 0x8, 361 + }, 362 + { 363 + .name = "cwb_2", .id = CWB_2, 364 + .base = 0x7E200, .len = 0x8, 365 + }, 366 + { 367 + .name = "cwb_3", .id = CWB_3, 368 + .base = 0x7E600, .len = 0x8, 352 369 }, 353 370 }; 354 371 ··· 468 447 .merge_3d = sm8650_merge_3d, 469 448 .wb_count = ARRAY_SIZE(sm8650_wb), 470 449 .wb = sm8650_wb, 450 + .cwb_count = ARRAY_SIZE(sm8650_cwb), 451 + .cwb = sm8650_cwb, 471 452 .intf_count = ARRAY_SIZE(sm8650_intf), 472 453 .intf = sm8650_intf, 473 454 .vbif_count = ARRAY_SIZE(sm8650_vbif),
+52 -2
drivers/gpu/drm/msm/disp/dpu1/catalog/dpu_4_1_sdm670.h
··· 65 65 }, 66 66 }; 67 67 68 + static const struct dpu_lm_cfg sdm670_lm[] = { 69 + { 70 + .name = "lm_0", .id = LM_0, 71 + .base = 0x44000, .len = 0x320, 72 + .features = MIXER_SDM845_MASK, 73 + .sblk = &sdm845_lm_sblk, 74 + .lm_pair = LM_1, 75 + .pingpong = PINGPONG_0, 76 + .dspp = DSPP_0, 77 + }, { 78 + .name = "lm_1", .id = LM_1, 79 + .base = 0x45000, .len = 0x320, 80 + .features = MIXER_SDM845_MASK, 81 + .sblk = &sdm845_lm_sblk, 82 + .lm_pair = LM_0, 83 + .pingpong = PINGPONG_1, 84 + .dspp = DSPP_1, 85 + }, { 86 + .name = "lm_2", .id = LM_2, 87 + .base = 0x46000, .len = 0x320, 88 + .features = MIXER_SDM845_MASK, 89 + .sblk = &sdm845_lm_sblk, 90 + .lm_pair = LM_5, 91 + .pingpong = PINGPONG_2, 92 + }, { 93 + .name = "lm_5", .id = LM_5, 94 + .base = 0x49000, .len = 0x320, 95 + .features = MIXER_SDM845_MASK, 96 + .sblk = &sdm845_lm_sblk, 97 + .lm_pair = LM_2, 98 + .pingpong = PINGPONG_3, 99 + }, 100 + }; 101 + 102 + static const struct dpu_dspp_cfg sdm670_dspp[] = { 103 + { 104 + .name = "dspp_0", .id = DSPP_0, 105 + .base = 0x54000, .len = 0x1800, 106 + .features = DSPP_SC7180_MASK, 107 + .sblk = &sdm845_dspp_sblk, 108 + }, { 109 + .name = "dspp_1", .id = DSPP_1, 110 + .base = 0x56000, .len = 0x1800, 111 + .features = DSPP_SC7180_MASK, 112 + .sblk = &sdm845_dspp_sblk, 113 + }, 114 + }; 115 + 68 116 static const struct dpu_dsc_cfg sdm670_dsc[] = { 69 117 { 70 118 .name = "dsc_0", .id = DSC_0, ··· 136 88 .ctl = sdm845_ctl, 137 89 .sspp_count = ARRAY_SIZE(sdm670_sspp), 138 90 .sspp = sdm670_sspp, 139 - .mixer_count = ARRAY_SIZE(sdm845_lm), 140 - .mixer = sdm845_lm, 91 + .mixer_count = ARRAY_SIZE(sdm670_lm), 92 + .mixer = sdm670_lm, 93 + .dspp_count = ARRAY_SIZE(sdm670_dspp), 94 + .dspp = sdm670_dspp, 141 95 .pingpong_count = ARRAY_SIZE(sdm845_pp), 142 96 .pingpong = sdm845_pp, 143 97 .dsc_count = ARRAY_SIZE(sdm670_dsc),
+2
drivers/gpu/drm/msm/disp/dpu1/catalog/dpu_5_0_sm8150.h
··· 164 164 .sblk = &sdm845_lm_sblk, 165 165 .lm_pair = LM_3, 166 166 .pingpong = PINGPONG_2, 167 + .dspp = DSPP_2, 167 168 }, { 168 169 .name = "lm_3", .id = LM_3, 169 170 .base = 0x47000, .len = 0x320, ··· 172 171 .sblk = &sdm845_lm_sblk, 173 172 .lm_pair = LM_2, 174 173 .pingpong = PINGPONG_3, 174 + .dspp = DSPP_3, 175 175 }, { 176 176 .name = "lm_4", .id = LM_4, 177 177 .base = 0x48000, .len = 0x320,
+2
drivers/gpu/drm/msm/disp/dpu1/catalog/dpu_5_1_sc8180x.h
··· 163 163 .sblk = &sdm845_lm_sblk, 164 164 .lm_pair = LM_3, 165 165 .pingpong = PINGPONG_2, 166 + .dspp = DSPP_2, 166 167 }, { 167 168 .name = "lm_3", .id = LM_3, 168 169 .base = 0x47000, .len = 0x320, ··· 171 170 .sblk = &sdm845_lm_sblk, 172 171 .lm_pair = LM_2, 173 172 .pingpong = PINGPONG_3, 173 + .dspp = DSPP_3, 174 174 }, { 175 175 .name = "lm_4", .id = LM_4, 176 176 .base = 0x48000, .len = 0x320,
+254
drivers/gpu/drm/msm/disp/dpu1/catalog/dpu_5_3_sm6150.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_5_3_SM6150_H 7 + #define _DPU_5_3_SM6150_H 8 + 9 + static const struct dpu_caps sm6150_dpu_caps = { 10 + .max_mixer_width = DEFAULT_DPU_OUTPUT_LINE_WIDTH, 11 + .max_mixer_blendstages = 0x9, 12 + .has_dim_layer = true, 13 + .has_idle_pc = true, 14 + .max_linewidth = 2160, 15 + .pixel_ram_size = DEFAULT_PIXEL_RAM_SIZE, 16 + .max_hdeci_exp = MAX_HORZ_DECIMATION, 17 + .max_vdeci_exp = MAX_VERT_DECIMATION, 18 + }; 19 + 20 + static const struct dpu_mdp_cfg sm6150_mdp = { 21 + .name = "top_0", 22 + .base = 0x0, .len = 0x45c, 23 + .features = 0, 24 + .clk_ctrls = { 25 + [DPU_CLK_CTRL_VIG0] = { .reg_off = 0x2ac, .bit_off = 0 }, 26 + [DPU_CLK_CTRL_DMA0] = { .reg_off = 0x2ac, .bit_off = 8 }, 27 + [DPU_CLK_CTRL_DMA1] = { .reg_off = 0x2b4, .bit_off = 8 }, 28 + [DPU_CLK_CTRL_DMA2] = { .reg_off = 0x2bc, .bit_off = 8 }, 29 + [DPU_CLK_CTRL_DMA3] = { .reg_off = 0x2c4, .bit_off = 8 }, 30 + }, 31 + }; 32 + 33 + static const struct dpu_ctl_cfg sm6150_ctl[] = { 34 + { 35 + .name = "ctl_0", .id = CTL_0, 36 + .base = 0x1000, .len = 0x1e0, 37 + .features = BIT(DPU_CTL_ACTIVE_CFG), 38 + .intr_start = DPU_IRQ_IDX(MDP_SSPP_TOP0_INTR2, 9), 39 + }, { 40 + .name = "ctl_1", .id = CTL_1, 41 + .base = 0x1200, .len = 0x1e0, 42 + .features = BIT(DPU_CTL_ACTIVE_CFG), 43 + .intr_start = DPU_IRQ_IDX(MDP_SSPP_TOP0_INTR2, 10), 44 + }, { 45 + .name = "ctl_2", .id = CTL_2, 46 + .base = 0x1400, .len = 0x1e0, 47 + .features = BIT(DPU_CTL_ACTIVE_CFG), 48 + .intr_start = DPU_IRQ_IDX(MDP_SSPP_TOP0_INTR2, 11), 49 + }, { 50 + .name = "ctl_3", .id = CTL_3, 51 + .base = 0x1600, .len = 0x1e0, 52 + .features = BIT(DPU_CTL_ACTIVE_CFG), 53 + .intr_start = DPU_IRQ_IDX(MDP_SSPP_TOP0_INTR2, 12), 54 + }, { 55 + .name = "ctl_4", .id = CTL_4, 56 + .base = 0x1800, .len = 0x1e0, 57 + .features = BIT(DPU_CTL_ACTIVE_CFG), 58 + .intr_start = DPU_IRQ_IDX(MDP_SSPP_TOP0_INTR2, 13), 59 + }, { 60 + .name = "ctl_5", .id = CTL_5, 61 + .base = 0x1a00, .len = 0x1e0, 62 + .features = BIT(DPU_CTL_ACTIVE_CFG), 63 + .intr_start = DPU_IRQ_IDX(MDP_SSPP_TOP0_INTR2, 23), 64 + }, 65 + }; 66 + 67 + static const struct dpu_sspp_cfg sm6150_sspp[] = { 68 + { 69 + .name = "sspp_0", .id = SSPP_VIG0, 70 + .base = 0x4000, .len = 0x1f0, 71 + .features = VIG_SDM845_MASK_SDMA, 72 + .sblk = &dpu_vig_sblk_qseed3_2_4, 73 + .xin_id = 0, 74 + .type = SSPP_TYPE_VIG, 75 + .clk_ctrl = DPU_CLK_CTRL_VIG0, 76 + }, { 77 + .name = "sspp_8", .id = SSPP_DMA0, 78 + .base = 0x24000, .len = 0x1f0, 79 + .features = DMA_SDM845_MASK_SDMA, 80 + .sblk = &dpu_dma_sblk, 81 + .xin_id = 1, 82 + .type = SSPP_TYPE_DMA, 83 + .clk_ctrl = DPU_CLK_CTRL_DMA0, 84 + }, { 85 + .name = "sspp_9", .id = SSPP_DMA1, 86 + .base = 0x26000, .len = 0x1f0, 87 + .features = DMA_SDM845_MASK_SDMA, 88 + .sblk = &dpu_dma_sblk, 89 + .xin_id = 5, 90 + .type = SSPP_TYPE_DMA, 91 + .clk_ctrl = DPU_CLK_CTRL_DMA1, 92 + }, { 93 + .name = "sspp_10", .id = SSPP_DMA2, 94 + .base = 0x28000, .len = 0x1f0, 95 + .features = DMA_CURSOR_SDM845_MASK_SDMA, 96 + .sblk = &dpu_dma_sblk, 97 + .xin_id = 9, 98 + .type = SSPP_TYPE_DMA, 99 + .clk_ctrl = DPU_CLK_CTRL_DMA2, 100 + }, { 101 + .name = "sspp_11", .id = SSPP_DMA3, 102 + .base = 0x2a000, .len = 0x1f0, 103 + .features = DMA_CURSOR_SDM845_MASK_SDMA, 104 + .sblk = &dpu_dma_sblk, 105 + .xin_id = 13, 106 + .type = SSPP_TYPE_DMA, 107 + .clk_ctrl = DPU_CLK_CTRL_DMA3, 108 + }, 109 + }; 110 + 111 + static const struct dpu_lm_cfg sm6150_lm[] = { 112 + { 113 + .name = "lm_0", .id = LM_0, 114 + .base = 0x44000, .len = 0x320, 115 + .features = MIXER_QCM2290_MASK, 116 + .sblk = &sdm845_lm_sblk, 117 + .pingpong = PINGPONG_0, 118 + .dspp = DSPP_0, 119 + .lm_pair = LM_1, 120 + }, { 121 + .name = "lm_1", .id = LM_1, 122 + .base = 0x45000, .len = 0x320, 123 + .features = MIXER_QCM2290_MASK, 124 + .sblk = &sdm845_lm_sblk, 125 + .pingpong = PINGPONG_1, 126 + .lm_pair = LM_0, 127 + }, { 128 + .name = "lm_2", .id = LM_2, 129 + .base = 0x46000, .len = 0x320, 130 + .features = MIXER_QCM2290_MASK, 131 + .sblk = &sdm845_lm_sblk, 132 + .pingpong = PINGPONG_2, 133 + }, 134 + }; 135 + 136 + static const struct dpu_dspp_cfg sm6150_dspp[] = { 137 + { 138 + .name = "dspp_0", .id = DSPP_0, 139 + .base = 0x54000, .len = 0x1800, 140 + .features = DSPP_SC7180_MASK, 141 + .sblk = &sdm845_dspp_sblk, 142 + }, 143 + }; 144 + 145 + static const struct dpu_pingpong_cfg sm6150_pp[] = { 146 + { 147 + .name = "pingpong_0", .id = PINGPONG_0, 148 + .base = 0x70000, .len = 0xd4, 149 + .features = PINGPONG_SM8150_MASK, 150 + .sblk = &sdm845_pp_sblk, 151 + .intr_done = DPU_IRQ_IDX(MDP_SSPP_TOP0_INTR, 8), 152 + }, { 153 + .name = "pingpong_1", .id = PINGPONG_1, 154 + .base = 0x70800, .len = 0xd4, 155 + .features = PINGPONG_SM8150_MASK, 156 + .sblk = &sdm845_pp_sblk, 157 + .intr_done = DPU_IRQ_IDX(MDP_SSPP_TOP0_INTR, 9), 158 + }, { 159 + .name = "pingpong_2", .id = PINGPONG_2, 160 + .base = 0x71000, .len = 0xd4, 161 + .features = PINGPONG_SM8150_MASK, 162 + .sblk = &sdm845_pp_sblk, 163 + .intr_done = DPU_IRQ_IDX(MDP_SSPP_TOP0_INTR, 10), 164 + }, 165 + }; 166 + 167 + static const struct dpu_intf_cfg sm6150_intf[] = { 168 + { 169 + .name = "intf_0", .id = INTF_0, 170 + .base = 0x6a000, .len = 0x280, 171 + .features = INTF_SC7180_MASK, 172 + .type = INTF_DP, 173 + .controller_id = MSM_DP_CONTROLLER_0, 174 + .prog_fetch_lines_worst_case = 24, 175 + .intr_underrun = DPU_IRQ_IDX(MDP_SSPP_TOP0_INTR, 24), 176 + .intr_vsync = DPU_IRQ_IDX(MDP_SSPP_TOP0_INTR, 25), 177 + }, { 178 + .name = "intf_1", .id = INTF_1, 179 + .base = 0x6a800, .len = 0x2c0, 180 + .features = INTF_SC7180_MASK, 181 + .type = INTF_DSI, 182 + .controller_id = MSM_DSI_CONTROLLER_0, 183 + .prog_fetch_lines_worst_case = 24, 184 + .intr_underrun = DPU_IRQ_IDX(MDP_SSPP_TOP0_INTR, 26), 185 + .intr_vsync = DPU_IRQ_IDX(MDP_SSPP_TOP0_INTR, 27), 186 + .intr_tear_rd_ptr = DPU_IRQ_IDX(MDP_INTF1_TEAR_INTR, 2), 187 + }, { 188 + .name = "intf_3", .id = INTF_3, 189 + .base = 0x6b800, .len = 0x280, 190 + .features = INTF_SC7180_MASK, 191 + .type = INTF_DP, 192 + .controller_id = MSM_DP_CONTROLLER_1, 193 + .prog_fetch_lines_worst_case = 24, 194 + .intr_underrun = DPU_IRQ_IDX(MDP_SSPP_TOP0_INTR, 30), 195 + .intr_vsync = DPU_IRQ_IDX(MDP_SSPP_TOP0_INTR, 31), 196 + }, 197 + }; 198 + 199 + static const struct dpu_perf_cfg sm6150_perf_data = { 200 + .max_bw_low = 4800000, 201 + .max_bw_high = 4800000, 202 + .min_core_ib = 2400000, 203 + .min_llcc_ib = 0, 204 + .min_dram_ib = 800000, 205 + .min_prefill_lines = 24, 206 + .danger_lut_tbl = {0xf, 0xffff, 0x0}, 207 + .safe_lut_tbl = {0xfff8, 0xf000, 0xffff}, 208 + .qos_lut_tbl = { 209 + {.nentry = ARRAY_SIZE(sm8150_qos_linear), 210 + .entries = sm8150_qos_linear 211 + }, 212 + {.nentry = ARRAY_SIZE(sc7180_qos_macrotile), 213 + .entries = sc7180_qos_macrotile 214 + }, 215 + {.nentry = ARRAY_SIZE(sc7180_qos_nrt), 216 + .entries = sc7180_qos_nrt 217 + }, 218 + /* TODO: macrotile-qseed is different from macrotile */ 219 + }, 220 + .cdp_cfg = { 221 + {.rd_enable = 1, .wr_enable = 1}, 222 + {.rd_enable = 1, .wr_enable = 0} 223 + }, 224 + .clk_inefficiency_factor = 105, 225 + .bw_inefficiency_factor = 120, 226 + }; 227 + 228 + static const struct dpu_mdss_version sm6150_mdss_ver = { 229 + .core_major_ver = 5, 230 + .core_minor_ver = 3, 231 + }; 232 + 233 + const struct dpu_mdss_cfg dpu_sm6150_cfg = { 234 + .mdss_ver = &sm6150_mdss_ver, 235 + .caps = &sm6150_dpu_caps, 236 + .mdp = &sm6150_mdp, 237 + .ctl_count = ARRAY_SIZE(sm6150_ctl), 238 + .ctl = sm6150_ctl, 239 + .sspp_count = ARRAY_SIZE(sm6150_sspp), 240 + .sspp = sm6150_sspp, 241 + .mixer_count = ARRAY_SIZE(sm6150_lm), 242 + .mixer = sm6150_lm, 243 + .dspp_count = ARRAY_SIZE(sm6150_dspp), 244 + .dspp = sm6150_dspp, 245 + .pingpong_count = ARRAY_SIZE(sm6150_pp), 246 + .pingpong = sm6150_pp, 247 + .intf_count = ARRAY_SIZE(sm6150_intf), 248 + .intf = sm6150_intf, 249 + .vbif_count = ARRAY_SIZE(sdm845_vbif), 250 + .vbif = sdm845_vbif, 251 + .perf = &sm6150_perf_data, 252 + }; 253 + 254 + #endif
+2
drivers/gpu/drm/msm/disp/dpu1/catalog/dpu_6_0_sm8250.h
··· 162 162 .sblk = &sdm845_lm_sblk, 163 163 .lm_pair = LM_3, 164 164 .pingpong = PINGPONG_2, 165 + .dspp = DSPP_2, 165 166 }, { 166 167 .name = "lm_3", .id = LM_3, 167 168 .base = 0x47000, .len = 0x320, ··· 170 169 .sblk = &sdm845_lm_sblk, 171 170 .lm_pair = LM_2, 172 171 .pingpong = PINGPONG_3, 172 + .dspp = DSPP_3, 173 173 }, { 174 174 .name = "lm_4", .id = LM_4, 175 175 .base = 0x48000, .len = 0x320,
+2
drivers/gpu/drm/msm/disp/dpu1/catalog/dpu_7_0_sm8350.h
··· 162 162 .sblk = &sdm845_lm_sblk, 163 163 .lm_pair = LM_3, 164 164 .pingpong = PINGPONG_2, 165 + .dspp = DSPP_2, 165 166 }, { 166 167 .name = "lm_3", .id = LM_3, 167 168 .base = 0x47000, .len = 0x320, ··· 170 169 .sblk = &sdm845_lm_sblk, 171 170 .lm_pair = LM_2, 172 171 .pingpong = PINGPONG_3, 172 + .dspp = DSPP_3, 173 173 }, { 174 174 .name = "lm_4", .id = LM_4, 175 175 .base = 0x48000, .len = 0x320,
+2 -2
drivers/gpu/drm/msm/disp/dpu1/catalog/dpu_8_1_sm8450.h
··· 257 257 .merge_3d = MERGE_3D_2, 258 258 .intr_done = DPU_IRQ_IDX(MDP_SSPP_TOP0_INTR2, 31), 259 259 }, { 260 - .name = "pingpong_6", .id = PINGPONG_6, 260 + .name = "pingpong_cwb_0", .id = PINGPONG_CWB_0, 261 261 .base = 0x65800, .len = 0, 262 262 .features = BIT(DPU_PINGPONG_DITHER), 263 263 .sblk = &sc7280_pp_sblk, 264 264 .merge_3d = MERGE_3D_3, 265 265 }, { 266 - .name = "pingpong_7", .id = PINGPONG_7, 266 + .name = "pingpong_cwb_1", .id = PINGPONG_CWB_1, 267 267 .base = 0x65c00, .len = 0, 268 268 .features = BIT(DPU_PINGPONG_DITHER), 269 269 .sblk = &sc7280_pp_sblk,
+2 -2
drivers/gpu/drm/msm/disp/dpu1/catalog/dpu_8_4_sa8775p.h
··· 256 256 .merge_3d = MERGE_3D_2, 257 257 .intr_done = DPU_IRQ_IDX(MDP_SSPP_TOP0_INTR2, 31), 258 258 }, { 259 - .name = "pingpong_6", .id = PINGPONG_6, 259 + .name = "pingpong_6", .id = PINGPONG_CWB_0, 260 260 .base = 0x65800, .len = 0, 261 261 .features = BIT(DPU_PINGPONG_DITHER), 262 262 .sblk = &sc7280_pp_sblk, 263 263 .merge_3d = MERGE_3D_3, 264 264 }, { 265 - .name = "pingpong_7", .id = PINGPONG_7, 265 + .name = "pingpong_7", .id = PINGPONG_CWB_1, 266 266 .base = 0x65c00, .len = 0, 267 267 .features = BIT(DPU_PINGPONG_DITHER), 268 268 .sblk = &sc7280_pp_sblk,
+4 -2
drivers/gpu/drm/msm/disp/dpu1/catalog/dpu_9_0_sm8550.h
··· 160 160 .sblk = &sdm845_lm_sblk, 161 161 .lm_pair = LM_3, 162 162 .pingpong = PINGPONG_2, 163 + .dspp = DSPP_2, 163 164 }, { 164 165 .name = "lm_3", .id = LM_3, 165 166 .base = 0x47000, .len = 0x320, ··· 168 167 .sblk = &sdm845_lm_sblk, 169 168 .lm_pair = LM_2, 170 169 .pingpong = PINGPONG_3, 170 + .dspp = DSPP_3, 171 171 }, { 172 172 .name = "lm_4", .id = LM_4, 173 173 .base = 0x48000, .len = 0x320, ··· 253 251 .merge_3d = MERGE_3D_2, 254 252 .intr_done = DPU_IRQ_IDX(MDP_SSPP_TOP0_INTR2, 31), 255 253 }, { 256 - .name = "pingpong_6", .id = PINGPONG_6, 254 + .name = "pingpong_cwb_0", .id = PINGPONG_CWB_0, 257 255 .base = 0x66000, .len = 0, 258 256 .features = BIT(DPU_PINGPONG_DITHER), 259 257 .sblk = &sc7280_pp_sblk, 260 258 .merge_3d = MERGE_3D_3, 261 259 }, { 262 - .name = "pingpong_7", .id = PINGPONG_7, 260 + .name = "pingpong_cwb_1", .id = PINGPONG_CWB_1, 263 261 .base = 0x66400, .len = 0, 264 262 .features = BIT(DPU_PINGPONG_DITHER), 265 263 .sblk = &sc7280_pp_sblk,
+6 -4
drivers/gpu/drm/msm/disp/dpu1/catalog/dpu_9_2_x1e80100.h
··· 159 159 .sblk = &sdm845_lm_sblk, 160 160 .lm_pair = LM_3, 161 161 .pingpong = PINGPONG_2, 162 + .dspp = DSPP_2, 162 163 }, { 163 164 .name = "lm_3", .id = LM_3, 164 165 .base = 0x47000, .len = 0x320, ··· 167 166 .sblk = &sdm845_lm_sblk, 168 167 .lm_pair = LM_2, 169 168 .pingpong = PINGPONG_3, 169 + .dspp = DSPP_3, 170 170 }, { 171 171 .name = "lm_4", .id = LM_4, 172 172 .base = 0x48000, .len = 0x320, ··· 253 251 .merge_3d = MERGE_3D_2, 254 252 .intr_done = DPU_IRQ_IDX(MDP_SSPP_TOP0_INTR2, 31), 255 253 }, { 256 - .name = "pingpong_6", .id = PINGPONG_6, 254 + .name = "pingpong_cwb_0", .id = PINGPONG_CWB_0, 257 255 .base = 0x66000, .len = 0, 258 256 .features = BIT(DPU_PINGPONG_DITHER), 259 257 .sblk = &sc7280_pp_sblk, 260 258 .merge_3d = MERGE_3D_3, 261 259 }, { 262 - .name = "pingpong_7", .id = PINGPONG_7, 260 + .name = "pingpong_cwb_1", .id = PINGPONG_CWB_1, 263 261 .base = 0x66400, .len = 0, 264 262 .features = BIT(DPU_PINGPONG_DITHER), 265 263 .sblk = &sc7280_pp_sblk, ··· 391 389 .type = INTF_DP, 392 390 .controller_id = MSM_DP_CONTROLLER_2, 393 391 .prog_fetch_lines_worst_case = 24, 394 - .intr_underrun = DPU_IRQ_IDX(MDP_SSPP_TOP0_INTR, 17), 395 - .intr_vsync = DPU_IRQ_IDX(MDP_SSPP_TOP0_INTR, 16), 392 + .intr_underrun = DPU_IRQ_IDX(MDP_SSPP_TOP0_INTR, 16), 393 + .intr_vsync = DPU_IRQ_IDX(MDP_SSPP_TOP0_INTR, 17), 396 394 }, { 397 395 .name = "intf_7", .id = INTF_7, 398 396 .base = 0x3b000, .len = 0x280,
+63
drivers/gpu/drm/msm/disp/dpu1/dpu_crtc.c
··· 732 732 struct dpu_kms *dpu_kms = _dpu_crtc_get_kms(crtc); 733 733 int i; 734 734 735 + /* if we cannot merge 2 LMs (no 3d mux) better to fail earlier 736 + * before even checking the width after the split 737 + */ 738 + if (!dpu_kms->catalog->caps->has_3d_merge && 739 + adj_mode->hdisplay > dpu_kms->catalog->caps->max_mixer_width) 740 + return -E2BIG; 741 + 735 742 for (i = 0; i < cstate->num_mixers; i++) { 736 743 struct drm_rect *r = &cstate->lm_bounds[i]; 737 744 r->x1 = crtc_split_width * i; ··· 1189 1182 return false; 1190 1183 } 1191 1184 1185 + static int dpu_crtc_reassign_planes(struct drm_crtc *crtc, struct drm_crtc_state *crtc_state) 1186 + { 1187 + int total_planes = crtc->dev->mode_config.num_total_plane; 1188 + struct drm_atomic_state *state = crtc_state->state; 1189 + struct dpu_global_state *global_state; 1190 + struct drm_plane_state **states; 1191 + struct drm_plane *plane; 1192 + int ret; 1193 + 1194 + global_state = dpu_kms_get_global_state(crtc_state->state); 1195 + if (IS_ERR(global_state)) 1196 + return PTR_ERR(global_state); 1197 + 1198 + dpu_rm_release_all_sspp(global_state, crtc); 1199 + 1200 + if (!crtc_state->enable) 1201 + return 0; 1202 + 1203 + states = kcalloc(total_planes, sizeof(*states), GFP_KERNEL); 1204 + if (!states) 1205 + return -ENOMEM; 1206 + 1207 + drm_atomic_crtc_state_for_each_plane(plane, crtc_state) { 1208 + struct drm_plane_state *plane_state = 1209 + drm_atomic_get_plane_state(state, plane); 1210 + 1211 + if (IS_ERR(plane_state)) { 1212 + ret = PTR_ERR(plane_state); 1213 + goto done; 1214 + } 1215 + 1216 + states[plane_state->normalized_zpos] = plane_state; 1217 + } 1218 + 1219 + ret = dpu_assign_plane_resources(global_state, state, crtc, states, total_planes); 1220 + 1221 + done: 1222 + kfree(states); 1223 + return ret; 1224 + 1225 + return 0; 1226 + } 1227 + 1192 1228 static int dpu_crtc_atomic_check(struct drm_crtc *crtc, 1193 1229 struct drm_atomic_state *state) 1194 1230 { ··· 1246 1196 int rc = 0; 1247 1197 1248 1198 bool needs_dirtyfb = dpu_crtc_needs_dirtyfb(crtc_state); 1199 + 1200 + if (dpu_use_virtual_planes && 1201 + (crtc_state->planes_changed || crtc_state->zpos_changed)) { 1202 + rc = dpu_crtc_reassign_planes(crtc, crtc_state); 1203 + if (rc < 0) 1204 + return rc; 1205 + } 1249 1206 1250 1207 if (!crtc_state->enable || !drm_atomic_crtc_effectively_active(crtc_state)) { 1251 1208 DRM_DEBUG_ATOMIC("crtc%d -> enable %d, active %d, skip atomic_check\n", ··· 1308 1251 { 1309 1252 struct dpu_kms *dpu_kms = _dpu_crtc_get_kms(crtc); 1310 1253 1254 + /* if there is no 3d_mux block we cannot merge LMs so we cannot 1255 + * split the large layer into 2 LMs, filter out such modes 1256 + */ 1257 + if (!dpu_kms->catalog->caps->has_3d_merge && 1258 + mode->hdisplay > dpu_kms->catalog->caps->max_mixer_width) 1259 + return MODE_BAD_HVALUE; 1311 1260 /* 1312 1261 * max crtc width is equal to the max mixer width * 2 and max height is 4K 1313 1262 */
+1 -1
drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c
··· 800 800 801 801 if (!crtc_state->active_changed || crtc_state->enable) 802 802 ret = dpu_rm_reserve(&dpu_kms->rm, global_state, 803 - drm_enc, crtc_state, topology); 803 + drm_enc, crtc_state, &topology); 804 804 if (!ret) 805 805 dpu_encoder_assign_crtc_resources(dpu_kms, drm_enc, 806 806 global_state, crtc_state);
+1
drivers/gpu/drm/msm/disp/dpu1/dpu_hw_catalog.c
··· 765 765 #include "catalog/dpu_5_0_sm8150.h" 766 766 #include "catalog/dpu_5_1_sc8180x.h" 767 767 #include "catalog/dpu_5_2_sm7150.h" 768 + #include "catalog/dpu_5_3_sm6150.h" 768 769 #include "catalog/dpu_5_4_sm6125.h" 769 770 770 771 #include "catalog/dpu_6_0_sm8250.h"
+14
drivers/gpu/drm/msm/disp/dpu1/dpu_hw_catalog.h
··· 613 613 enum dpu_clk_ctrl_type clk_ctrl; 614 614 }; 615 615 616 + /* 617 + * struct dpu_cwb_cfg : MDP CWB mux instance info 618 + * @id: enum identifying this block 619 + * @base: register base offset to mdss 620 + * @features bit mask identifying sub-blocks/features 621 + */ 622 + struct dpu_cwb_cfg { 623 + DPU_HW_BLK_INFO; 624 + }; 625 + 616 626 /** 617 627 * struct dpu_vbif_dynamic_ot_cfg - dynamic OT setting 618 628 * @pps pixel per seconds ··· 825 815 u32 dspp_count; 826 816 const struct dpu_dspp_cfg *dspp; 827 817 818 + u32 cwb_count; 819 + const struct dpu_cwb_cfg *cwb; 820 + 828 821 /* Add additional block data structures here */ 829 822 830 823 const struct dpu_perf_cfg *perf; ··· 852 839 extern const struct dpu_mdss_cfg dpu_sc7180_cfg; 853 840 extern const struct dpu_mdss_cfg dpu_sm6115_cfg; 854 841 extern const struct dpu_mdss_cfg dpu_sm6125_cfg; 842 + extern const struct dpu_mdss_cfg dpu_sm6150_cfg; 855 843 extern const struct dpu_mdss_cfg dpu_sm6350_cfg; 856 844 extern const struct dpu_mdss_cfg dpu_qcm2290_cfg; 857 845 extern const struct dpu_mdss_cfg dpu_sm6375_cfg;
+75
drivers/gpu/drm/msm/disp/dpu1/dpu_hw_cwb.c
··· 1 + // SPDX-License-Identifier: GPL-2.0-only 2 + /* 3 + * Copyright (c) 2024 Qualcomm Innovation Center, Inc. All rights reserved 4 + */ 5 + 6 + #include <drm/drm_managed.h> 7 + #include "dpu_hw_cwb.h" 8 + 9 + #include <linux/bitfield.h> 10 + 11 + #define CWB_MUX 0x000 12 + #define CWB_MODE 0x004 13 + 14 + /* CWB mux block bit definitions */ 15 + #define CWB_MUX_MASK GENMASK(3, 0) 16 + #define CWB_MODE_MASK GENMASK(2, 0) 17 + 18 + static void dpu_hw_cwb_config(struct dpu_hw_cwb *ctx, 19 + struct dpu_hw_cwb_setup_cfg *cwb_cfg) 20 + { 21 + struct dpu_hw_blk_reg_map *c = &ctx->hw; 22 + int cwb_mux_cfg = 0xF; 23 + enum dpu_pingpong pp; 24 + enum cwb_mode_input input; 25 + 26 + if (!cwb_cfg) 27 + return; 28 + 29 + input = cwb_cfg->input; 30 + pp = cwb_cfg->pp_idx; 31 + 32 + if (input >= INPUT_MODE_MAX) 33 + return; 34 + 35 + /* 36 + * The CWB_MUX register takes the pingpong index for the real-time 37 + * display 38 + */ 39 + if ((pp != PINGPONG_NONE) && (pp < PINGPONG_MAX)) 40 + cwb_mux_cfg = FIELD_PREP(CWB_MUX_MASK, pp - PINGPONG_0); 41 + 42 + input = FIELD_PREP(CWB_MODE_MASK, input); 43 + 44 + DPU_REG_WRITE(c, CWB_MUX, cwb_mux_cfg); 45 + DPU_REG_WRITE(c, CWB_MODE, input); 46 + } 47 + 48 + /** 49 + * dpu_hw_cwb_init() - Initializes the writeback hw driver object with cwb. 50 + * @dev: Corresponding device for devres management 51 + * @cfg: wb_path catalog entry for which driver object is required 52 + * @addr: mapped register io address of MDP 53 + * Return: Error code or allocated dpu_hw_wb context 54 + */ 55 + struct dpu_hw_cwb *dpu_hw_cwb_init(struct drm_device *dev, 56 + const struct dpu_cwb_cfg *cfg, 57 + void __iomem *addr) 58 + { 59 + struct dpu_hw_cwb *c; 60 + 61 + if (!addr) 62 + return ERR_PTR(-EINVAL); 63 + 64 + c = drmm_kzalloc(dev, sizeof(*c), GFP_KERNEL); 65 + if (!c) 66 + return ERR_PTR(-ENOMEM); 67 + 68 + c->hw.blk_addr = addr + cfg->base; 69 + c->hw.log_mask = DPU_DBG_MASK_CWB; 70 + 71 + c->idx = cfg->id; 72 + c->ops.config_cwb = dpu_hw_cwb_config; 73 + 74 + return c; 75 + }
+70
drivers/gpu/drm/msm/disp/dpu1/dpu_hw_cwb.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_HW_CWB_H 7 + #define _DPU_HW_CWB_H 8 + 9 + #include "dpu_hw_util.h" 10 + 11 + struct dpu_hw_cwb; 12 + 13 + enum cwb_mode_input { 14 + INPUT_MODE_LM_OUT, 15 + INPUT_MODE_DSPP_OUT, 16 + INPUT_MODE_MAX 17 + }; 18 + 19 + /** 20 + * struct dpu_hw_cwb_setup_cfg : Describes configuration for CWB mux 21 + * @pp_idx: Index of the real-time pinpong that the CWB mux will 22 + * feed the CWB mux 23 + * @input: Input tap point 24 + */ 25 + struct dpu_hw_cwb_setup_cfg { 26 + enum dpu_pingpong pp_idx; 27 + enum cwb_mode_input input; 28 + }; 29 + 30 + /** 31 + * 32 + * struct dpu_hw_cwb_ops : Interface to the cwb hw driver functions 33 + * @config_cwb: configure CWB mux 34 + */ 35 + struct dpu_hw_cwb_ops { 36 + void (*config_cwb)(struct dpu_hw_cwb *ctx, 37 + struct dpu_hw_cwb_setup_cfg *cwb_cfg); 38 + }; 39 + 40 + /** 41 + * struct dpu_hw_cwb : CWB mux driver object 42 + * @base: Hardware block base structure 43 + * @hw: Block hardware details 44 + * @idx: CWB index 45 + * @ops: handle to operations possible for this CWB 46 + */ 47 + struct dpu_hw_cwb { 48 + struct dpu_hw_blk base; 49 + struct dpu_hw_blk_reg_map hw; 50 + 51 + enum dpu_cwb idx; 52 + 53 + struct dpu_hw_cwb_ops ops; 54 + }; 55 + 56 + /** 57 + * dpu_hw_cwb - convert base object dpu_hw_base to container 58 + * @hw: Pointer to base hardware block 59 + * return: Pointer to hardware block container 60 + */ 61 + static inline struct dpu_hw_cwb *to_dpu_hw_cwb(struct dpu_hw_blk *hw) 62 + { 63 + return container_of(hw, struct dpu_hw_cwb, base); 64 + } 65 + 66 + struct dpu_hw_cwb *dpu_hw_cwb_init(struct drm_device *dev, 67 + const struct dpu_cwb_cfg *cfg, 68 + void __iomem *addr); 69 + 70 + #endif /*_DPU_HW_CWB_H */
+8 -5
drivers/gpu/drm/msm/disp/dpu1/dpu_hw_mdss.h
··· 1 1 /* SPDX-License-Identifier: GPL-2.0-only */ 2 - /* Copyright (c) 2015-2018, The Linux Foundation. All rights reserved. 2 + /* 3 + * Copyright (c) 2024 Qualcomm Innovation Center, Inc. All rights reserved. 4 + * Copyright (c) 2015-2018, The Linux Foundation. All rights reserved. 3 5 */ 4 6 5 7 #ifndef _DPU_HW_MDSS_H ··· 183 181 PINGPONG_3, 184 182 PINGPONG_4, 185 183 PINGPONG_5, 186 - PINGPONG_6, 187 - PINGPONG_7, 188 - PINGPONG_8, 189 - PINGPONG_9, 184 + PINGPONG_CWB_0, 185 + PINGPONG_CWB_1, 186 + PINGPONG_CWB_2, 187 + PINGPONG_CWB_3, 190 188 PINGPONG_S0, 191 189 PINGPONG_MAX 192 190 }; ··· 352 350 #define DPU_DBG_MASK_DSPP (1 << 10) 353 351 #define DPU_DBG_MASK_DSC (1 << 11) 354 352 #define DPU_DBG_MASK_CDM (1 << 12) 353 + #define DPU_DBG_MASK_CWB (1 << 13) 355 354 356 355 /** 357 356 * struct dpu_hw_tear_check - Struct contains parameters to configure
+3 -1
drivers/gpu/drm/msm/disp/dpu1/dpu_hw_wb.c
··· 173 173 mux_cfg = DPU_REG_READ(c, WB_MUX); 174 174 mux_cfg &= ~0xf; 175 175 176 - if (pp) 176 + if (pp >= PINGPONG_CWB_0) 177 + mux_cfg |= (pp < PINGPONG_CWB_2) ? 0xd : 0xb; 178 + else if (pp) 177 179 mux_cfg |= (pp - PINGPONG_0) & 0x7; 178 180 else 179 181 mux_cfg |= 0xf;
+39 -11
drivers/gpu/drm/msm/disp/dpu1/dpu_kms.c
··· 51 51 #define DPU_DEBUGFS_DIR "msm_dpu" 52 52 #define DPU_DEBUGFS_HWMASKNAME "hw_log_mask" 53 53 54 + bool dpu_use_virtual_planes; 55 + module_param(dpu_use_virtual_planes, bool, 0); 56 + 54 57 static int dpu_kms_hw_init(struct msm_kms *kms); 55 58 static void _dpu_kms_mmu_destroy(struct dpu_kms *dpu_kms); 56 59 ··· 832 829 type, catalog->sspp[i].features, 833 830 catalog->sspp[i].features & BIT(DPU_SSPP_CURSOR)); 834 831 835 - plane = dpu_plane_init(dev, catalog->sspp[i].id, type, 836 - (1UL << max_crtc_count) - 1); 832 + if (dpu_use_virtual_planes) 833 + plane = dpu_plane_init_virtual(dev, type, (1UL << max_crtc_count) - 1); 834 + else 835 + plane = dpu_plane_init(dev, catalog->sspp[i].id, type, 836 + (1UL << max_crtc_count) - 1); 837 837 if (IS_ERR(plane)) { 838 838 DPU_ERROR("dpu_plane_init failed\n"); 839 839 ret = PTR_ERR(plane); ··· 938 932 /* dump CTL sub-blocks HW regs info */ 939 933 for (i = 0; i < cat->ctl_count; i++) 940 934 msm_disp_snapshot_add_block(disp_state, cat->ctl[i].len, 941 - dpu_kms->mmio + cat->ctl[i].base, cat->ctl[i].name); 935 + dpu_kms->mmio + cat->ctl[i].base, "%s", 936 + cat->ctl[i].name); 942 937 943 938 /* dump DSPP sub-blocks HW regs info */ 944 939 for (i = 0; i < cat->dspp_count; i++) { 945 940 base = dpu_kms->mmio + cat->dspp[i].base; 946 - msm_disp_snapshot_add_block(disp_state, cat->dspp[i].len, base, cat->dspp[i].name); 941 + msm_disp_snapshot_add_block(disp_state, cat->dspp[i].len, base, 942 + "%s", cat->dspp[i].name); 947 943 948 944 if (cat->dspp[i].sblk && cat->dspp[i].sblk->pcc.len > 0) 949 945 msm_disp_snapshot_add_block(disp_state, cat->dspp[i].sblk->pcc.len, ··· 957 949 /* dump INTF sub-blocks HW regs info */ 958 950 for (i = 0; i < cat->intf_count; i++) 959 951 msm_disp_snapshot_add_block(disp_state, cat->intf[i].len, 960 - dpu_kms->mmio + cat->intf[i].base, cat->intf[i].name); 952 + dpu_kms->mmio + cat->intf[i].base, "%s", 953 + cat->intf[i].name); 961 954 962 955 /* dump PP sub-blocks HW regs info */ 963 956 for (i = 0; i < cat->pingpong_count; i++) { 964 957 base = dpu_kms->mmio + cat->pingpong[i].base; 965 958 msm_disp_snapshot_add_block(disp_state, cat->pingpong[i].len, base, 966 - cat->pingpong[i].name); 959 + "%s", cat->pingpong[i].name); 967 960 968 961 /* TE2 sub-block has length of 0, so will not print it */ 969 962 ··· 978 969 /* dump SSPP sub-blocks HW regs info */ 979 970 for (i = 0; i < cat->sspp_count; i++) { 980 971 base = dpu_kms->mmio + cat->sspp[i].base; 981 - msm_disp_snapshot_add_block(disp_state, cat->sspp[i].len, base, cat->sspp[i].name); 972 + msm_disp_snapshot_add_block(disp_state, cat->sspp[i].len, base, 973 + "%s", cat->sspp[i].name); 982 974 983 975 if (cat->sspp[i].sblk && cat->sspp[i].sblk->scaler_blk.len > 0) 984 976 msm_disp_snapshot_add_block(disp_state, cat->sspp[i].sblk->scaler_blk.len, ··· 997 987 /* dump LM sub-blocks HW regs info */ 998 988 for (i = 0; i < cat->mixer_count; i++) 999 989 msm_disp_snapshot_add_block(disp_state, cat->mixer[i].len, 1000 - dpu_kms->mmio + cat->mixer[i].base, cat->mixer[i].name); 990 + dpu_kms->mmio + cat->mixer[i].base, 991 + "%s", cat->mixer[i].name); 1001 992 1002 993 /* dump WB sub-blocks HW regs info */ 1003 994 for (i = 0; i < cat->wb_count; i++) 1004 995 msm_disp_snapshot_add_block(disp_state, cat->wb[i].len, 1005 - dpu_kms->mmio + cat->wb[i].base, cat->wb[i].name); 996 + dpu_kms->mmio + cat->wb[i].base, "%s", 997 + cat->wb[i].name); 1006 998 1007 999 if (cat->mdp[0].features & BIT(DPU_MDP_PERIPH_0_REMOVED)) { 1008 1000 msm_disp_snapshot_add_block(disp_state, MDP_PERIPH_TOP0, ··· 1016 1004 dpu_kms->mmio + cat->mdp[0].base, "top"); 1017 1005 } 1018 1006 1007 + /* dump CWB sub-blocks HW regs info */ 1008 + for (i = 0; i < cat->cwb_count; i++) 1009 + msm_disp_snapshot_add_block(disp_state, cat->cwb[i].len, 1010 + dpu_kms->mmio + cat->cwb[i].base, cat->cwb[i].name); 1011 + 1019 1012 /* dump DSC sub-blocks HW regs info */ 1020 1013 for (i = 0; i < cat->dsc_count; i++) { 1021 1014 base = dpu_kms->mmio + cat->dsc[i].base; 1022 - msm_disp_snapshot_add_block(disp_state, cat->dsc[i].len, base, cat->dsc[i].name); 1015 + msm_disp_snapshot_add_block(disp_state, cat->dsc[i].len, base, 1016 + "%s", cat->dsc[i].name); 1023 1017 1024 1018 if (cat->dsc[i].features & BIT(DPU_DSC_HW_REV_1_2)) { 1025 1019 struct dpu_dsc_blk enc = cat->dsc[i].sblk->enc; ··· 1040 1022 1041 1023 if (cat->cdm) 1042 1024 msm_disp_snapshot_add_block(disp_state, cat->cdm->len, 1043 - dpu_kms->mmio + cat->cdm->base, cat->cdm->name); 1025 + dpu_kms->mmio + cat->cdm->base, 1026 + "%s", cat->cdm->name); 1027 + 1028 + for (i = 0; i < dpu_kms->catalog->vbif_count; i++) { 1029 + const struct dpu_vbif_cfg *vbif = &dpu_kms->catalog->vbif[i]; 1030 + 1031 + msm_disp_snapshot_add_block(disp_state, vbif->len, 1032 + dpu_kms->vbif[vbif->id] + vbif->base, 1033 + "%s", vbif->name); 1034 + } 1044 1035 1045 1036 pm_runtime_put_sync(&dpu_kms->pdev->dev); 1046 1037 } ··· 1505 1478 { .compatible = "qcom,sc8280xp-dpu", .data = &dpu_sc8280xp_cfg, }, 1506 1479 { .compatible = "qcom,sm6115-dpu", .data = &dpu_sm6115_cfg, }, 1507 1480 { .compatible = "qcom,sm6125-dpu", .data = &dpu_sm6125_cfg, }, 1481 + { .compatible = "qcom,sm6150-dpu", .data = &dpu_sm6150_cfg, }, 1508 1482 { .compatible = "qcom,sm6350-dpu", .data = &dpu_sm6350_cfg, }, 1509 1483 { .compatible = "qcom,sm6375-dpu", .data = &dpu_sm6375_cfg, }, 1510 1484 { .compatible = "qcom,sm7150-dpu", .data = &dpu_sm7150_cfg, },
+4
drivers/gpu/drm/msm/disp/dpu1/dpu_kms.h
··· 54 54 #define ktime_compare_safe(A, B) \ 55 55 ktime_compare(ktime_sub((A), (B)), ktime_set(0, 0)) 56 56 57 + extern bool dpu_use_virtual_planes; 58 + 57 59 struct dpu_kms { 58 60 struct msm_kms base; 59 61 struct drm_device *dev; ··· 130 128 uint32_t dspp_to_enc_id[DSPP_MAX - DSPP_0]; 131 129 uint32_t dsc_to_enc_id[DSC_MAX - DSC_0]; 132 130 uint32_t cdm_to_enc_id; 131 + 132 + uint32_t sspp_to_crtc_id[SSPP_MAX - SSPP_NONE]; 133 133 }; 134 134 135 135 struct dpu_global_state
+322 -78
drivers/gpu/drm/msm/disp/dpu1/dpu_plane.c
··· 20 20 #include "msm_drv.h" 21 21 #include "msm_mdss.h" 22 22 #include "dpu_kms.h" 23 - #include "dpu_formats.h" 24 23 #include "dpu_hw_sspp.h" 25 24 #include "dpu_hw_util.h" 26 25 #include "dpu_trace.h" ··· 877 878 drm_rect_rotate_inv(&pipe_cfg->src_rect, 878 879 new_plane_state->fb->width, new_plane_state->fb->height, 879 880 new_plane_state->rotation); 880 - if (r_pipe_cfg->src_rect.x1 != 0) 881 + if (drm_rect_width(&r_pipe_cfg->src_rect) != 0) 881 882 drm_rect_rotate_inv(&r_pipe_cfg->src_rect, 882 883 new_plane_state->fb->width, new_plane_state->fb->height, 883 884 new_plane_state->rotation); ··· 885 886 pstate->needs_qos_remap = drm_atomic_crtc_needs_modeset(crtc_state); 886 887 887 888 return 0; 889 + } 890 + 891 + static int dpu_plane_is_multirect_parallel_capable(struct dpu_hw_sspp *sspp, 892 + struct dpu_sw_pipe_cfg *pipe_cfg, 893 + const struct msm_format *fmt, 894 + uint32_t max_linewidth) 895 + { 896 + if (drm_rect_width(&pipe_cfg->src_rect) != drm_rect_width(&pipe_cfg->dst_rect) || 897 + drm_rect_height(&pipe_cfg->src_rect) != drm_rect_height(&pipe_cfg->dst_rect)) 898 + return false; 899 + 900 + if (pipe_cfg->rotation & DRM_MODE_ROTATE_90) 901 + return false; 902 + 903 + if (MSM_FORMAT_IS_YUV(fmt)) 904 + return false; 905 + 906 + if (MSM_FORMAT_IS_UBWC(fmt) && 907 + drm_rect_width(&pipe_cfg->src_rect) > max_linewidth / 2) 908 + return false; 909 + 910 + if (!test_bit(DPU_SSPP_SMART_DMA_V1, &sspp->cap->features) && 911 + !test_bit(DPU_SSPP_SMART_DMA_V2, &sspp->cap->features)) 912 + return false; 913 + 914 + return true; 888 915 } 889 916 890 917 static int dpu_plane_atomic_check_sspp(struct drm_plane *plane, ··· 926 901 const struct msm_format *fmt; 927 902 struct dpu_sw_pipe_cfg *pipe_cfg = &pstate->pipe_cfg; 928 903 struct dpu_sw_pipe_cfg *r_pipe_cfg = &pstate->r_pipe_cfg; 929 - uint32_t max_linewidth; 930 904 uint32_t supported_rotations; 931 905 const struct dpu_sspp_cfg *pipe_hw_caps; 932 906 const struct dpu_sspp_sub_blks *sblk; ··· 947 923 948 924 fmt = msm_framebuffer_format(new_plane_state->fb); 949 925 950 - max_linewidth = pdpu->catalog->caps->max_linewidth; 951 - 952 926 supported_rotations = DRM_MODE_REFLECT_MASK | DRM_MODE_ROTATE_0; 953 927 954 928 if (pipe_hw_caps->features & BIT(DPU_SSPP_INLINE_ROTATION)) ··· 962 940 return ret; 963 941 964 942 if (drm_rect_width(&r_pipe_cfg->src_rect) != 0) { 965 - /* 966 - * In parallel multirect case only the half of the usual width 967 - * is supported for tiled formats. If we are here, we know that 968 - * full width is more than max_linewidth, thus each rect is 969 - * wider than allowed. 970 - */ 971 - if (MSM_FORMAT_IS_UBWC(fmt) && 972 - drm_rect_width(&pipe_cfg->src_rect) > max_linewidth) { 973 - DPU_DEBUG_PLANE(pdpu, "invalid src " DRM_RECT_FMT " line:%u, tiled format\n", 974 - DRM_RECT_ARG(&pipe_cfg->src_rect), max_linewidth); 975 - return -E2BIG; 976 - } 977 - 978 - if (drm_rect_width(&pipe_cfg->src_rect) != drm_rect_width(&pipe_cfg->dst_rect) || 979 - drm_rect_height(&pipe_cfg->src_rect) != drm_rect_height(&pipe_cfg->dst_rect) || 980 - (!test_bit(DPU_SSPP_SMART_DMA_V1, &pipe->sspp->cap->features) && 981 - !test_bit(DPU_SSPP_SMART_DMA_V2, &pipe->sspp->cap->features)) || 982 - pipe_cfg->rotation & DRM_MODE_ROTATE_90 || 983 - MSM_FORMAT_IS_YUV(fmt)) { 984 - DPU_DEBUG_PLANE(pdpu, "invalid src " DRM_RECT_FMT " line:%u, can't use split source\n", 985 - DRM_RECT_ARG(&pipe_cfg->src_rect), max_linewidth); 986 - return -E2BIG; 987 - } 988 - 989 - /* 990 - * Use multirect for wide plane. We do not support dynamic 991 - * assignment of SSPPs, so we know the configuration. 992 - */ 993 - pipe->multirect_index = DPU_SSPP_RECT_0; 994 - pipe->multirect_mode = DPU_SSPP_MULTIRECT_PARALLEL; 995 - 996 - r_pipe->sspp = pipe->sspp; 997 - r_pipe->multirect_index = DPU_SSPP_RECT_1; 998 - r_pipe->multirect_mode = DPU_SSPP_MULTIRECT_PARALLEL; 999 - 1000 943 ret = dpu_plane_atomic_check_pipe(pdpu, r_pipe, r_pipe_cfg, fmt, 1001 944 &crtc_state->adjusted_mode); 1002 945 if (ret) ··· 969 982 } 970 983 971 984 return 0; 985 + } 986 + 987 + static bool dpu_plane_try_multirect_parallel(struct dpu_sw_pipe *pipe, struct dpu_sw_pipe_cfg *pipe_cfg, 988 + struct dpu_sw_pipe *r_pipe, struct dpu_sw_pipe_cfg *r_pipe_cfg, 989 + struct dpu_hw_sspp *sspp, const struct msm_format *fmt, 990 + uint32_t max_linewidth) 991 + { 992 + r_pipe->sspp = NULL; 993 + 994 + pipe->multirect_index = DPU_SSPP_RECT_SOLO; 995 + pipe->multirect_mode = DPU_SSPP_MULTIRECT_NONE; 996 + 997 + r_pipe->multirect_index = DPU_SSPP_RECT_SOLO; 998 + r_pipe->multirect_mode = DPU_SSPP_MULTIRECT_NONE; 999 + 1000 + if (drm_rect_width(&r_pipe_cfg->src_rect) != 0) { 1001 + if (!dpu_plane_is_multirect_parallel_capable(pipe->sspp, pipe_cfg, fmt, max_linewidth) || 1002 + !dpu_plane_is_multirect_parallel_capable(pipe->sspp, r_pipe_cfg, fmt, max_linewidth)) 1003 + return false; 1004 + 1005 + r_pipe->sspp = pipe->sspp; 1006 + 1007 + pipe->multirect_index = DPU_SSPP_RECT_0; 1008 + pipe->multirect_mode = DPU_SSPP_MULTIRECT_PARALLEL; 1009 + 1010 + r_pipe->multirect_index = DPU_SSPP_RECT_1; 1011 + r_pipe->multirect_mode = DPU_SSPP_MULTIRECT_PARALLEL; 1012 + } 1013 + 1014 + return true; 972 1015 } 973 1016 974 1017 static int dpu_plane_atomic_check(struct drm_plane *plane, ··· 1012 995 struct dpu_kms *dpu_kms = _dpu_plane_get_kms(plane); 1013 996 struct dpu_sw_pipe *pipe = &pstate->pipe; 1014 997 struct dpu_sw_pipe *r_pipe = &pstate->r_pipe; 998 + struct dpu_sw_pipe_cfg *pipe_cfg = &pstate->pipe_cfg; 999 + struct dpu_sw_pipe_cfg *r_pipe_cfg = &pstate->r_pipe_cfg; 1015 1000 const struct drm_crtc_state *crtc_state = NULL; 1001 + uint32_t max_linewidth = dpu_kms->catalog->caps->max_linewidth; 1016 1002 1017 1003 if (new_plane_state->crtc) 1018 1004 crtc_state = drm_atomic_get_new_crtc_state(state, 1019 1005 new_plane_state->crtc); 1020 1006 1021 1007 pipe->sspp = dpu_rm_get_sspp(&dpu_kms->rm, pdpu->pipe); 1022 - r_pipe->sspp = NULL; 1008 + 1009 + if (!pipe->sspp) 1010 + return -EINVAL; 1023 1011 1024 1012 ret = dpu_plane_atomic_check_nosspp(plane, new_plane_state, crtc_state); 1025 1013 if (ret) ··· 1033 1011 if (!new_plane_state->visible) 1034 1012 return 0; 1035 1013 1036 - pipe->multirect_index = DPU_SSPP_RECT_SOLO; 1037 - pipe->multirect_mode = DPU_SSPP_MULTIRECT_NONE; 1038 - r_pipe->multirect_index = DPU_SSPP_RECT_SOLO; 1039 - r_pipe->multirect_mode = DPU_SSPP_MULTIRECT_NONE; 1014 + if (!dpu_plane_try_multirect_parallel(pipe, pipe_cfg, r_pipe, r_pipe_cfg, 1015 + pipe->sspp, 1016 + msm_framebuffer_format(new_plane_state->fb), 1017 + max_linewidth)) { 1018 + DPU_DEBUG_PLANE(pdpu, "invalid " DRM_RECT_FMT " /" DRM_RECT_FMT 1019 + " max_line:%u, can't use split source\n", 1020 + DRM_RECT_ARG(&pipe_cfg->src_rect), 1021 + DRM_RECT_ARG(&r_pipe_cfg->src_rect), 1022 + max_linewidth); 1023 + return -E2BIG; 1024 + } 1040 1025 1041 1026 return dpu_plane_atomic_check_sspp(plane, state, crtc_state); 1027 + } 1028 + 1029 + static int dpu_plane_virtual_atomic_check(struct drm_plane *plane, 1030 + struct drm_atomic_state *state) 1031 + { 1032 + struct drm_plane_state *plane_state = 1033 + drm_atomic_get_plane_state(state, plane); 1034 + struct drm_plane_state *old_plane_state = 1035 + drm_atomic_get_old_plane_state(state, plane); 1036 + struct dpu_plane_state *pstate = to_dpu_plane_state(plane_state); 1037 + struct drm_crtc_state *crtc_state; 1038 + int ret; 1039 + 1040 + if (plane_state->crtc) 1041 + crtc_state = drm_atomic_get_new_crtc_state(state, 1042 + plane_state->crtc); 1043 + 1044 + ret = dpu_plane_atomic_check_nosspp(plane, plane_state, crtc_state); 1045 + if (ret) 1046 + return ret; 1047 + 1048 + if (!plane_state->visible) { 1049 + /* 1050 + * resources are freed by dpu_crtc_assign_plane_resources(), 1051 + * but clean them here. 1052 + */ 1053 + pstate->pipe.sspp = NULL; 1054 + pstate->r_pipe.sspp = NULL; 1055 + 1056 + return 0; 1057 + } 1058 + 1059 + /* 1060 + * Force resource reallocation if the format of FB or src/dst have 1061 + * changed. We might need to allocate different SSPP or SSPPs for this 1062 + * plane than the one used previously. 1063 + */ 1064 + if (!old_plane_state || !old_plane_state->fb || 1065 + old_plane_state->src_w != plane_state->src_w || 1066 + old_plane_state->src_h != plane_state->src_h || 1067 + old_plane_state->src_w != plane_state->src_w || 1068 + old_plane_state->crtc_h != plane_state->crtc_h || 1069 + msm_framebuffer_format(old_plane_state->fb) != 1070 + msm_framebuffer_format(plane_state->fb)) 1071 + crtc_state->planes_changed = true; 1072 + 1073 + return 0; 1074 + } 1075 + 1076 + static int dpu_plane_virtual_assign_resources(struct drm_crtc *crtc, 1077 + struct dpu_global_state *global_state, 1078 + struct drm_atomic_state *state, 1079 + struct drm_plane_state *plane_state) 1080 + { 1081 + const struct drm_crtc_state *crtc_state = NULL; 1082 + struct drm_plane *plane = plane_state->plane; 1083 + struct dpu_kms *dpu_kms = _dpu_plane_get_kms(plane); 1084 + struct dpu_rm_sspp_requirements reqs; 1085 + struct dpu_plane_state *pstate; 1086 + struct dpu_sw_pipe *pipe; 1087 + struct dpu_sw_pipe *r_pipe; 1088 + struct dpu_sw_pipe_cfg *pipe_cfg; 1089 + struct dpu_sw_pipe_cfg *r_pipe_cfg; 1090 + const struct msm_format *fmt; 1091 + 1092 + if (plane_state->crtc) 1093 + crtc_state = drm_atomic_get_new_crtc_state(state, 1094 + plane_state->crtc); 1095 + 1096 + pstate = to_dpu_plane_state(plane_state); 1097 + pipe = &pstate->pipe; 1098 + r_pipe = &pstate->r_pipe; 1099 + pipe_cfg = &pstate->pipe_cfg; 1100 + r_pipe_cfg = &pstate->r_pipe_cfg; 1101 + 1102 + pipe->sspp = NULL; 1103 + r_pipe->sspp = NULL; 1104 + 1105 + if (!plane_state->fb) 1106 + return -EINVAL; 1107 + 1108 + fmt = msm_framebuffer_format(plane_state->fb); 1109 + reqs.yuv = MSM_FORMAT_IS_YUV(fmt); 1110 + reqs.scale = (plane_state->src_w >> 16 != plane_state->crtc_w) || 1111 + (plane_state->src_h >> 16 != plane_state->crtc_h); 1112 + 1113 + reqs.rot90 = drm_rotation_90_or_270(plane_state->rotation); 1114 + 1115 + pipe->sspp = dpu_rm_reserve_sspp(&dpu_kms->rm, global_state, crtc, &reqs); 1116 + if (!pipe->sspp) 1117 + return -ENODEV; 1118 + 1119 + if (!dpu_plane_try_multirect_parallel(pipe, pipe_cfg, r_pipe, r_pipe_cfg, 1120 + pipe->sspp, 1121 + msm_framebuffer_format(plane_state->fb), 1122 + dpu_kms->catalog->caps->max_linewidth)) { 1123 + /* multirect is not possible, use two SSPP blocks */ 1124 + r_pipe->sspp = dpu_rm_reserve_sspp(&dpu_kms->rm, global_state, crtc, &reqs); 1125 + if (!r_pipe->sspp) 1126 + return -ENODEV; 1127 + 1128 + pipe->multirect_index = DPU_SSPP_RECT_SOLO; 1129 + pipe->multirect_mode = DPU_SSPP_MULTIRECT_NONE; 1130 + 1131 + r_pipe->multirect_index = DPU_SSPP_RECT_SOLO; 1132 + r_pipe->multirect_mode = DPU_SSPP_MULTIRECT_NONE; 1133 + } 1134 + 1135 + return dpu_plane_atomic_check_sspp(plane, state, crtc_state); 1136 + } 1137 + 1138 + int dpu_assign_plane_resources(struct dpu_global_state *global_state, 1139 + struct drm_atomic_state *state, 1140 + struct drm_crtc *crtc, 1141 + struct drm_plane_state **states, 1142 + unsigned int num_planes) 1143 + { 1144 + unsigned int i; 1145 + int ret; 1146 + 1147 + for (i = 0; i < num_planes; i++) { 1148 + struct drm_plane_state *plane_state = states[i]; 1149 + 1150 + if (!plane_state || 1151 + !plane_state->visible) 1152 + continue; 1153 + 1154 + ret = dpu_plane_virtual_assign_resources(crtc, global_state, 1155 + state, plane_state); 1156 + if (ret) 1157 + break; 1158 + } 1159 + 1160 + return ret; 1042 1161 } 1043 1162 1044 1163 static void dpu_plane_flush_csc(struct dpu_plane *pdpu, struct dpu_sw_pipe *pipe) ··· 1498 1335 1499 1336 drm_printf(p, "\tstage=%d\n", pstate->stage); 1500 1337 1501 - drm_printf(p, "\tsspp[0]=%s\n", pipe->sspp->cap->name); 1502 - drm_printf(p, "\tmultirect_mode[0]=%s\n", dpu_get_multirect_mode(pipe->multirect_mode)); 1503 - drm_printf(p, "\tmultirect_index[0]=%s\n", 1504 - dpu_get_multirect_index(pipe->multirect_index)); 1505 - drm_printf(p, "\tsrc[0]=" DRM_RECT_FMT "\n", DRM_RECT_ARG(&pipe_cfg->src_rect)); 1506 - drm_printf(p, "\tdst[0]=" DRM_RECT_FMT "\n", DRM_RECT_ARG(&pipe_cfg->dst_rect)); 1338 + if (pipe->sspp) { 1339 + drm_printf(p, "\tsspp[0]=%s\n", pipe->sspp->cap->name); 1340 + drm_printf(p, "\tmultirect_mode[0]=%s\n", 1341 + dpu_get_multirect_mode(pipe->multirect_mode)); 1342 + drm_printf(p, "\tmultirect_index[0]=%s\n", 1343 + dpu_get_multirect_index(pipe->multirect_index)); 1344 + drm_printf(p, "\tsrc[0]=" DRM_RECT_FMT "\n", DRM_RECT_ARG(&pipe_cfg->src_rect)); 1345 + drm_printf(p, "\tdst[0]=" DRM_RECT_FMT "\n", DRM_RECT_ARG(&pipe_cfg->dst_rect)); 1346 + } 1507 1347 1508 1348 if (r_pipe->sspp) { 1509 1349 drm_printf(p, "\tsspp[1]=%s\n", r_pipe->sspp->cap->name); ··· 1599 1433 .atomic_update = dpu_plane_atomic_update, 1600 1434 }; 1601 1435 1602 - /** 1603 - * dpu_plane_init - create new dpu plane for the given pipe 1604 - * @dev: Pointer to DRM device 1605 - * @pipe: dpu hardware pipe identifier 1606 - * @type: Plane type - PRIMARY/OVERLAY/CURSOR 1607 - * @possible_crtcs: bitmask of crtc that can be attached to the given pipe 1608 - * 1609 - * Initialize the plane. 1610 - */ 1611 - struct drm_plane *dpu_plane_init(struct drm_device *dev, 1612 - uint32_t pipe, enum drm_plane_type type, 1613 - unsigned long possible_crtcs) 1436 + static const struct drm_plane_helper_funcs dpu_plane_virtual_helper_funcs = { 1437 + .prepare_fb = dpu_plane_prepare_fb, 1438 + .cleanup_fb = dpu_plane_cleanup_fb, 1439 + .atomic_check = dpu_plane_virtual_atomic_check, 1440 + .atomic_update = dpu_plane_atomic_update, 1441 + }; 1442 + 1443 + /* initialize plane */ 1444 + static struct drm_plane *dpu_plane_init_common(struct drm_device *dev, 1445 + enum drm_plane_type type, 1446 + unsigned long possible_crtcs, 1447 + bool inline_rotation, 1448 + const uint32_t *format_list, 1449 + uint32_t num_formats, 1450 + enum dpu_sspp pipe) 1614 1451 { 1615 1452 struct drm_plane *plane = NULL; 1616 - const uint32_t *format_list; 1617 1453 struct dpu_plane *pdpu; 1618 1454 struct msm_drm_private *priv = dev->dev_private; 1619 1455 struct dpu_kms *kms = to_dpu_kms(priv->kms); 1620 - struct dpu_hw_sspp *pipe_hw; 1621 - uint32_t num_formats; 1622 1456 uint32_t supported_rotations; 1623 1457 int ret; 1624 - 1625 - /* initialize underlying h/w driver */ 1626 - pipe_hw = dpu_rm_get_sspp(&kms->rm, pipe); 1627 - if (!pipe_hw || !pipe_hw->cap || !pipe_hw->cap->sblk) { 1628 - DPU_ERROR("[%u]SSPP is invalid\n", pipe); 1629 - return ERR_PTR(-EINVAL); 1630 - } 1631 - 1632 - format_list = pipe_hw->cap->sblk->format_list; 1633 - num_formats = pipe_hw->cap->sblk->num_formats; 1634 1458 1635 1459 pdpu = drmm_universal_plane_alloc(dev, struct dpu_plane, base, 1636 1460 0xff, &dpu_plane_funcs, ··· 1647 1491 1648 1492 supported_rotations = DRM_MODE_REFLECT_MASK | DRM_MODE_ROTATE_0 | DRM_MODE_ROTATE_180; 1649 1493 1650 - if (pipe_hw->cap->features & BIT(DPU_SSPP_INLINE_ROTATION)) 1494 + if (inline_rotation) 1651 1495 supported_rotations |= DRM_MODE_ROTATE_MASK; 1652 1496 1653 1497 drm_plane_create_rotation_property(plane, ··· 1655 1499 1656 1500 drm_plane_enable_fb_damage_clips(plane); 1657 1501 1658 - /* success! finalize initialization */ 1502 + DPU_DEBUG("%s created for pipe:%u id:%u\n", plane->name, 1503 + pipe, plane->base.id); 1504 + return plane; 1505 + } 1506 + 1507 + /** 1508 + * dpu_plane_init - create new dpu plane for the given pipe 1509 + * @dev: Pointer to DRM device 1510 + * @pipe: dpu hardware pipe identifier 1511 + * @type: Plane type - PRIMARY/OVERLAY/CURSOR 1512 + * @possible_crtcs: bitmask of crtc that can be attached to the given pipe 1513 + * 1514 + * Initialize the plane. 1515 + */ 1516 + struct drm_plane *dpu_plane_init(struct drm_device *dev, 1517 + uint32_t pipe, enum drm_plane_type type, 1518 + unsigned long possible_crtcs) 1519 + { 1520 + struct drm_plane *plane = NULL; 1521 + struct msm_drm_private *priv = dev->dev_private; 1522 + struct dpu_kms *kms = to_dpu_kms(priv->kms); 1523 + struct dpu_hw_sspp *pipe_hw; 1524 + 1525 + /* initialize underlying h/w driver */ 1526 + pipe_hw = dpu_rm_get_sspp(&kms->rm, pipe); 1527 + if (!pipe_hw || !pipe_hw->cap || !pipe_hw->cap->sblk) { 1528 + DPU_ERROR("[%u]SSPP is invalid\n", pipe); 1529 + return ERR_PTR(-EINVAL); 1530 + } 1531 + 1532 + 1533 + plane = dpu_plane_init_common(dev, type, possible_crtcs, 1534 + pipe_hw->cap->features & BIT(DPU_SSPP_INLINE_ROTATION), 1535 + pipe_hw->cap->sblk->format_list, 1536 + pipe_hw->cap->sblk->num_formats, 1537 + pipe); 1538 + if (IS_ERR(plane)) 1539 + return plane; 1540 + 1659 1541 drm_plane_helper_add(plane, &dpu_plane_helper_funcs); 1660 1542 1661 1543 DPU_DEBUG("%s created for pipe:%u id:%u\n", plane->name, 1662 1544 pipe, plane->base.id); 1545 + 1546 + return plane; 1547 + } 1548 + 1549 + /** 1550 + * dpu_plane_init_virtual - create new virtualized DPU plane 1551 + * @dev: Pointer to DRM device 1552 + * @type: Plane type - PRIMARY/OVERLAY/CURSOR 1553 + * @possible_crtcs: bitmask of crtc that can be attached to the given pipe 1554 + * 1555 + * Initialize the virtual plane with no backing SSPP / pipe. 1556 + */ 1557 + struct drm_plane *dpu_plane_init_virtual(struct drm_device *dev, 1558 + enum drm_plane_type type, 1559 + unsigned long possible_crtcs) 1560 + { 1561 + struct drm_plane *plane = NULL; 1562 + struct msm_drm_private *priv = dev->dev_private; 1563 + struct dpu_kms *kms = to_dpu_kms(priv->kms); 1564 + bool has_inline_rotation = false; 1565 + const u32 *format_list = NULL; 1566 + u32 num_formats = 0; 1567 + int i; 1568 + 1569 + /* Determine the largest configuration that we can implement */ 1570 + for (i = 0; i < kms->catalog->sspp_count; i++) { 1571 + const struct dpu_sspp_cfg *cfg = &kms->catalog->sspp[i]; 1572 + 1573 + if (test_bit(DPU_SSPP_INLINE_ROTATION, &cfg->features)) 1574 + has_inline_rotation = true; 1575 + 1576 + if (!format_list || 1577 + cfg->sblk->csc_blk.len) { 1578 + format_list = cfg->sblk->format_list; 1579 + num_formats = cfg->sblk->num_formats; 1580 + } 1581 + } 1582 + 1583 + plane = dpu_plane_init_common(dev, type, possible_crtcs, 1584 + has_inline_rotation, 1585 + format_list, 1586 + num_formats, 1587 + SSPP_NONE); 1588 + if (IS_ERR(plane)) 1589 + return plane; 1590 + 1591 + drm_plane_helper_add(plane, &dpu_plane_virtual_helper_funcs); 1592 + 1593 + DPU_DEBUG("%s created virtual id:%u\n", plane->name, plane->base.id); 1594 + 1663 1595 return plane; 1664 1596 }
+13
drivers/gpu/drm/msm/disp/dpu1/dpu_plane.h
··· 62 62 uint32_t pipe, enum drm_plane_type type, 63 63 unsigned long possible_crtcs); 64 64 65 + struct drm_plane *dpu_plane_init_virtual(struct drm_device *dev, 66 + enum drm_plane_type type, 67 + unsigned long possible_crtcs); 68 + 69 + int dpu_plane_color_fill(struct drm_plane *plane, 70 + uint32_t color, uint32_t alpha); 71 + 65 72 #ifdef CONFIG_DEBUG_FS 66 73 void dpu_plane_danger_signal_ctrl(struct drm_plane *plane, bool enable); 67 74 #else 68 75 static inline void dpu_plane_danger_signal_ctrl(struct drm_plane *plane, bool enable) {} 69 76 #endif 77 + 78 + int dpu_assign_plane_resources(struct dpu_global_state *global_state, 79 + struct drm_atomic_state *state, 80 + struct drm_crtc *crtc, 81 + struct drm_plane_state **states, 82 + unsigned int num_planes); 70 83 71 84 #endif /* _DPU_PLANE_H_ */
+126 -49
drivers/gpu/drm/msm/disp/dpu1/dpu_rm.c
··· 1 1 // SPDX-License-Identifier: GPL-2.0-only 2 2 /* 3 3 * Copyright (c) 2016-2018, The Linux Foundation. All rights reserved. 4 - * Copyright (c) 2023 Qualcomm Innovation Center, Inc. All rights reserved. 4 + * Copyright (c) 2023-2024 Qualcomm Innovation Center, Inc. All rights reserved. 5 5 */ 6 6 7 7 #define pr_fmt(fmt) "[drm:%s] " fmt, __func__ ··· 9 9 #include "dpu_hw_lm.h" 10 10 #include "dpu_hw_ctl.h" 11 11 #include "dpu_hw_cdm.h" 12 + #include "dpu_hw_cwb.h" 12 13 #include "dpu_hw_pingpong.h" 13 14 #include "dpu_hw_sspp.h" 14 15 #include "dpu_hw_intf.h" ··· 26 25 { 27 26 return res_map[idx] && res_map[idx] != enc_id; 28 27 } 29 - 30 - /** 31 - * struct dpu_rm_requirements - Reservation requirements parameter bundle 32 - * @topology: selected topology for the display 33 - */ 34 - struct dpu_rm_requirements { 35 - struct msm_display_topology topology; 36 - }; 37 28 38 29 /** 39 30 * dpu_rm_init - Read hardware catalog and create reservation tracking objects ··· 121 128 goto fail; 122 129 } 123 130 rm->hw_wb[wb->id - WB_0] = hw; 131 + } 132 + 133 + for (i = 0; i < cat->cwb_count; i++) { 134 + struct dpu_hw_cwb *hw; 135 + const struct dpu_cwb_cfg *cwb = &cat->cwb[i]; 136 + 137 + hw = dpu_hw_cwb_init(dev, cwb, mmio); 138 + if (IS_ERR(hw)) { 139 + rc = PTR_ERR(hw); 140 + DPU_ERROR("failed cwb object creation: err %d\n", rc); 141 + goto fail; 142 + } 143 + rm->cwb_blks[cwb->id - CWB_0] = &hw->base; 124 144 } 125 145 126 146 for (i = 0; i < cat->ctl_count; i++) { ··· 247 241 * mixer in rm->pingpong_blks[]. 248 242 * @dspp_idx: output parameter, index of dspp block attached to the layer 249 243 * mixer in rm->dspp_blks[]. 250 - * @reqs: input parameter, rm requirements for HW blocks needed in the 251 - * datapath. 244 + * @topology: selected topology for the display 252 245 * Return: true if lm matches all requirements, false otherwise 253 246 */ 254 247 static bool _dpu_rm_check_lm_and_get_connected_blks(struct dpu_rm *rm, 255 248 struct dpu_global_state *global_state, 256 249 uint32_t enc_id, int lm_idx, int *pp_idx, int *dspp_idx, 257 - struct dpu_rm_requirements *reqs) 250 + struct msm_display_topology *topology) 258 251 { 259 252 const struct dpu_lm_cfg *lm_cfg; 260 253 int idx; ··· 278 273 } 279 274 *pp_idx = idx; 280 275 281 - if (!reqs->topology.num_dspp) 276 + if (!topology->num_dspp) 282 277 return true; 283 278 284 279 idx = lm_cfg->dspp - DSPP_0; ··· 300 295 static int _dpu_rm_reserve_lms(struct dpu_rm *rm, 301 296 struct dpu_global_state *global_state, 302 297 uint32_t enc_id, 303 - struct dpu_rm_requirements *reqs) 298 + struct msm_display_topology *topology) 304 299 305 300 { 306 301 int lm_idx[MAX_BLOCKS]; ··· 308 303 int dspp_idx[MAX_BLOCKS] = {0}; 309 304 int i, lm_count = 0; 310 305 311 - if (!reqs->topology.num_lm) { 312 - DPU_ERROR("invalid number of lm: %d\n", reqs->topology.num_lm); 306 + if (!topology->num_lm) { 307 + DPU_ERROR("invalid number of lm: %d\n", topology->num_lm); 313 308 return -EINVAL; 314 309 } 315 310 316 311 /* Find a primary mixer */ 317 312 for (i = 0; i < ARRAY_SIZE(rm->mixer_blks) && 318 - lm_count < reqs->topology.num_lm; i++) { 313 + lm_count < topology->num_lm; i++) { 319 314 if (!rm->mixer_blks[i]) 320 315 continue; 321 316 ··· 324 319 325 320 if (!_dpu_rm_check_lm_and_get_connected_blks(rm, global_state, 326 321 enc_id, i, &pp_idx[lm_count], 327 - &dspp_idx[lm_count], reqs)) { 322 + &dspp_idx[lm_count], topology)) { 328 323 continue; 329 324 } 330 325 331 326 ++lm_count; 332 327 333 328 /* Valid primary mixer found, find matching peers */ 334 - if (lm_count < reqs->topology.num_lm) { 329 + if (lm_count < topology->num_lm) { 335 330 int j = _dpu_rm_get_lm_peer(rm, i); 336 331 337 332 /* ignore the peer if there is an error or if the peer was already processed */ ··· 344 339 if (!_dpu_rm_check_lm_and_get_connected_blks(rm, 345 340 global_state, enc_id, j, 346 341 &pp_idx[lm_count], &dspp_idx[lm_count], 347 - reqs)) { 342 + topology)) { 348 343 continue; 349 344 } 350 345 ··· 353 348 } 354 349 } 355 350 356 - if (lm_count != reqs->topology.num_lm) { 351 + if (lm_count != topology->num_lm) { 357 352 DPU_DEBUG("unable to find appropriate mixers\n"); 358 353 return -ENAVAIL; 359 354 } ··· 362 357 global_state->mixer_to_enc_id[lm_idx[i]] = enc_id; 363 358 global_state->pingpong_to_enc_id[pp_idx[i]] = enc_id; 364 359 global_state->dspp_to_enc_id[dspp_idx[i]] = 365 - reqs->topology.num_dspp ? enc_id : 0; 360 + topology->num_dspp ? enc_id : 0; 366 361 367 362 trace_dpu_rm_reserve_lms(lm_idx[i] + LM_0, enc_id, 368 363 pp_idx[i] + PINGPONG_0); ··· 599 594 struct dpu_rm *rm, 600 595 struct dpu_global_state *global_state, 601 596 struct drm_encoder *enc, 602 - struct dpu_rm_requirements *reqs) 597 + struct msm_display_topology *topology) 603 598 { 604 599 int ret; 605 600 606 - ret = _dpu_rm_reserve_lms(rm, global_state, enc->base.id, reqs); 601 + ret = _dpu_rm_reserve_lms(rm, global_state, enc->base.id, topology); 607 602 if (ret) { 608 603 DPU_ERROR("unable to find appropriate mixers\n"); 609 604 return ret; 610 605 } 611 606 612 607 ret = _dpu_rm_reserve_ctls(rm, global_state, enc->base.id, 613 - &reqs->topology); 608 + topology); 614 609 if (ret) { 615 610 DPU_ERROR("unable to find appropriate CTL\n"); 616 611 return ret; 617 612 } 618 613 619 - ret = _dpu_rm_reserve_dsc(rm, global_state, enc, &reqs->topology); 614 + ret = _dpu_rm_reserve_dsc(rm, global_state, enc, topology); 620 615 if (ret) 621 616 return ret; 622 617 623 - if (reqs->topology.needs_cdm) { 618 + if (topology->needs_cdm) { 624 619 ret = _dpu_rm_reserve_cdm(rm, global_state, enc); 625 620 if (ret) { 626 621 DPU_ERROR("unable to find CDM blk\n"); ··· 629 624 } 630 625 631 626 return ret; 632 - } 633 - 634 - static int _dpu_rm_populate_requirements( 635 - struct drm_encoder *enc, 636 - struct dpu_rm_requirements *reqs, 637 - struct msm_display_topology req_topology) 638 - { 639 - reqs->topology = req_topology; 640 - 641 - DRM_DEBUG_KMS("num_lm: %d num_dsc: %d num_intf: %d cdm: %d\n", 642 - reqs->topology.num_lm, reqs->topology.num_dsc, 643 - reqs->topology.num_intf, reqs->topology.needs_cdm); 644 - 645 - return 0; 646 627 } 647 628 648 629 static void _dpu_rm_clear_mapping(uint32_t *res_mapping, int cnt, ··· 684 693 struct dpu_global_state *global_state, 685 694 struct drm_encoder *enc, 686 695 struct drm_crtc_state *crtc_state, 687 - struct msm_display_topology topology) 696 + struct msm_display_topology *topology) 688 697 { 689 - struct dpu_rm_requirements reqs; 690 698 int ret; 691 699 692 700 /* Check if this is just a page-flip */ ··· 700 710 DRM_DEBUG_KMS("reserving hw for enc %d crtc %d\n", 701 711 enc->base.id, crtc_state->crtc->base.id); 702 712 703 - ret = _dpu_rm_populate_requirements(enc, &reqs, topology); 704 - if (ret) { 705 - DPU_ERROR("failed to populate hw requirements\n"); 706 - return ret; 707 - } 713 + DRM_DEBUG_KMS("num_lm: %d num_dsc: %d num_intf: %d\n", 714 + topology->num_lm, topology->num_dsc, 715 + topology->num_intf); 708 716 709 - ret = _dpu_rm_make_reservation(rm, global_state, enc, &reqs); 717 + ret = _dpu_rm_make_reservation(rm, global_state, enc, topology); 710 718 if (ret) 711 719 DPU_ERROR("failed to reserve hw resources: %d\n", ret); 712 720 713 721 714 722 715 723 return ret; 724 + } 725 + 726 + static struct dpu_hw_sspp *dpu_rm_try_sspp(struct dpu_rm *rm, 727 + struct dpu_global_state *global_state, 728 + struct drm_crtc *crtc, 729 + struct dpu_rm_sspp_requirements *reqs, 730 + unsigned int type) 731 + { 732 + uint32_t crtc_id = crtc->base.id; 733 + struct dpu_hw_sspp *hw_sspp; 734 + int i; 735 + 736 + for (i = 0; i < ARRAY_SIZE(rm->hw_sspp); i++) { 737 + if (!rm->hw_sspp[i]) 738 + continue; 739 + 740 + if (global_state->sspp_to_crtc_id[i]) 741 + continue; 742 + 743 + hw_sspp = rm->hw_sspp[i]; 744 + 745 + if (hw_sspp->cap->type != type) 746 + continue; 747 + 748 + if (reqs->scale && !hw_sspp->cap->sblk->scaler_blk.len) 749 + continue; 750 + 751 + // TODO: QSEED2 and RGB scalers are not yet supported 752 + if (reqs->scale && !hw_sspp->ops.setup_scaler) 753 + continue; 754 + 755 + if (reqs->yuv && !hw_sspp->cap->sblk->csc_blk.len) 756 + continue; 757 + 758 + if (reqs->rot90 && !(hw_sspp->cap->features & DPU_SSPP_INLINE_ROTATION)) 759 + continue; 760 + 761 + global_state->sspp_to_crtc_id[i] = crtc_id; 762 + 763 + return rm->hw_sspp[i]; 764 + } 765 + 766 + return NULL; 767 + } 768 + 769 + /** 770 + * dpu_rm_reserve_sspp - Reserve the required SSPP for the provided CRTC 771 + * @rm: DPU Resource Manager handle 772 + * @global_state: private global state 773 + * @crtc: DRM CRTC handle 774 + * @reqs: SSPP required features 775 + */ 776 + struct dpu_hw_sspp *dpu_rm_reserve_sspp(struct dpu_rm *rm, 777 + struct dpu_global_state *global_state, 778 + struct drm_crtc *crtc, 779 + struct dpu_rm_sspp_requirements *reqs) 780 + { 781 + struct dpu_hw_sspp *hw_sspp = NULL; 782 + 783 + if (!reqs->scale && !reqs->yuv) 784 + hw_sspp = dpu_rm_try_sspp(rm, global_state, crtc, reqs, SSPP_TYPE_DMA); 785 + if (!hw_sspp && reqs->scale) 786 + hw_sspp = dpu_rm_try_sspp(rm, global_state, crtc, reqs, SSPP_TYPE_RGB); 787 + if (!hw_sspp) 788 + hw_sspp = dpu_rm_try_sspp(rm, global_state, crtc, reqs, SSPP_TYPE_VIG); 789 + 790 + return hw_sspp; 791 + } 792 + 793 + /** 794 + * dpu_rm_release_all_sspp - Given the CRTC, release all SSPP 795 + * blocks previously reserved for that use case. 796 + * @global_state: resources shared across multiple kms objects 797 + * @crtc: DRM CRTC handle 798 + */ 799 + void dpu_rm_release_all_sspp(struct dpu_global_state *global_state, 800 + struct drm_crtc *crtc) 801 + { 802 + uint32_t crtc_id = crtc->base.id; 803 + 804 + _dpu_rm_clear_mapping(global_state->sspp_to_crtc_id, 805 + ARRAY_SIZE(global_state->sspp_to_crtc_id), crtc_id); 716 806 } 717 807 718 808 /** ··· 928 858 drm_puts(p, "\tcdm="); 929 859 dpu_rm_print_state_helper(p, rm->cdm_blk, 930 860 global_state->cdm_to_enc_id); 861 + drm_puts(p, "\n"); 862 + 863 + drm_puts(p, "\tsspp="); 864 + /* skip SSPP_NONE and start from the next index */ 865 + for (i = SSPP_NONE + 1; i < ARRAY_SIZE(global_state->sspp_to_crtc_id); i++) 866 + dpu_rm_print_state_helper(p, rm->hw_sspp[i] ? &rm->hw_sspp[i]->base : NULL, 867 + global_state->sspp_to_crtc_id[i]); 931 868 drm_puts(p, "\n"); 932 869 }
+17 -1
drivers/gpu/drm/msm/disp/dpu1/dpu_rm.h
··· 20 20 * @ctl_blks: array of ctl hardware resources 21 21 * @hw_intf: array of intf hardware resources 22 22 * @hw_wb: array of wb hardware resources 23 + * @hw_cwb: array of cwb hardware resources 23 24 * @dspp_blks: array of dspp hardware resources 24 25 * @hw_sspp: array of sspp hardware resources 25 26 * @cdm_blk: cdm hardware resource ··· 31 30 struct dpu_hw_blk *ctl_blks[CTL_MAX - CTL_0]; 32 31 struct dpu_hw_intf *hw_intf[INTF_MAX - INTF_0]; 33 32 struct dpu_hw_wb *hw_wb[WB_MAX - WB_0]; 33 + struct dpu_hw_blk *cwb_blks[CWB_MAX - CWB_0]; 34 34 struct dpu_hw_blk *dspp_blks[DSPP_MAX - DSPP_0]; 35 35 struct dpu_hw_blk *merge_3d_blks[MERGE_3D_MAX - MERGE_3D_0]; 36 36 struct dpu_hw_blk *dsc_blks[DSC_MAX - DSC_0]; 37 37 struct dpu_hw_sspp *hw_sspp[SSPP_MAX - SSPP_NONE]; 38 38 struct dpu_hw_blk *cdm_blk; 39 + }; 40 + 41 + struct dpu_rm_sspp_requirements { 42 + bool yuv; 43 + bool scale; 44 + bool rot90; 39 45 }; 40 46 41 47 /** ··· 71 63 struct dpu_global_state *global_state, 72 64 struct drm_encoder *drm_enc, 73 65 struct drm_crtc_state *crtc_state, 74 - struct msm_display_topology topology); 66 + struct msm_display_topology *topology); 75 67 76 68 void dpu_rm_release(struct dpu_global_state *global_state, 77 69 struct drm_encoder *enc); 70 + 71 + struct dpu_hw_sspp *dpu_rm_reserve_sspp(struct dpu_rm *rm, 72 + struct dpu_global_state *global_state, 73 + struct drm_crtc *crtc, 74 + struct dpu_rm_sspp_requirements *reqs); 75 + 76 + void dpu_rm_release_all_sspp(struct dpu_global_state *global_state, 77 + struct drm_crtc *crtc); 78 78 79 79 int dpu_rm_get_assigned_resources(struct dpu_rm *rm, 80 80 struct dpu_global_state *global_state, uint32_t enc_id,
-3
drivers/gpu/drm/msm/disp/dpu1/dpu_writeback.c
··· 42 42 if (!conn_state || !conn_state->connector) { 43 43 DPU_ERROR("invalid connector state\n"); 44 44 return -EINVAL; 45 - } else if (conn_state->connector->status != connector_status_connected) { 46 - DPU_ERROR("connector not connected %d\n", conn_state->connector->status); 47 - return -EINVAL; 48 45 } 49 46 50 47 crtc = conn_state->crtc;
+1 -1
drivers/gpu/drm/msm/disp/mdp4/mdp4_lcdc_encoder.c
··· 389 389 390 390 /* TODO: different regulators in other cases? */ 391 391 mdp4_lcdc_encoder->regs[0].supply = "lvds-vccs-3p3v"; 392 - mdp4_lcdc_encoder->regs[1].supply = "lvds-vccs-3p3v"; 392 + mdp4_lcdc_encoder->regs[1].supply = "lvds-pll-vdda"; 393 393 mdp4_lcdc_encoder->regs[2].supply = "lvds-vdda"; 394 394 395 395 ret = devm_regulator_bulk_get(dev->dev,
+38 -227
drivers/gpu/drm/msm/dp/dp_audio.c
··· 14 14 #include "dp_catalog.h" 15 15 #include "dp_audio.h" 16 16 #include "dp_panel.h" 17 + #include "dp_reg.h" 17 18 #include "dp_display.h" 18 19 #include "dp_utils.h" 19 20 ··· 29 28 struct msm_dp_audio msm_dp_audio; 30 29 }; 31 30 32 - static u32 msm_dp_audio_get_header(struct msm_dp_catalog *catalog, 33 - enum msm_dp_catalog_audio_sdp_type sdp, 34 - enum msm_dp_catalog_audio_header_type header) 35 - { 36 - return msm_dp_catalog_audio_get_header(catalog, sdp, header); 37 - } 38 - 39 - static void msm_dp_audio_set_header(struct msm_dp_catalog *catalog, 40 - u32 data, 41 - enum msm_dp_catalog_audio_sdp_type sdp, 42 - enum msm_dp_catalog_audio_header_type header) 43 - { 44 - msm_dp_catalog_audio_set_header(catalog, sdp, header, data); 45 - } 46 - 47 31 static void msm_dp_audio_stream_sdp(struct msm_dp_audio_private *audio) 48 32 { 49 - struct msm_dp_catalog *catalog = audio->catalog; 50 - u32 value, new_value; 51 - u8 parity_byte; 33 + struct dp_sdp_header sdp_hdr = { 34 + .HB0 = 0x00, 35 + .HB1 = 0x02, 36 + .HB2 = 0x00, 37 + .HB3 = audio->channels - 1, 38 + }; 52 39 53 - /* Config header and parity byte 1 */ 54 - value = msm_dp_audio_get_header(catalog, 55 - DP_AUDIO_SDP_STREAM, DP_AUDIO_SDP_HEADER_1); 56 - 57 - new_value = 0x02; 58 - parity_byte = msm_dp_utils_calculate_parity(new_value); 59 - value |= ((new_value << HEADER_BYTE_1_BIT) 60 - | (parity_byte << PARITY_BYTE_1_BIT)); 61 - drm_dbg_dp(audio->drm_dev, 62 - "Header Byte 1: value = 0x%x, parity_byte = 0x%x\n", 63 - value, parity_byte); 64 - msm_dp_audio_set_header(catalog, value, 65 - DP_AUDIO_SDP_STREAM, DP_AUDIO_SDP_HEADER_1); 66 - 67 - /* Config header and parity byte 2 */ 68 - value = msm_dp_audio_get_header(catalog, 69 - DP_AUDIO_SDP_STREAM, DP_AUDIO_SDP_HEADER_2); 70 - new_value = value; 71 - parity_byte = msm_dp_utils_calculate_parity(new_value); 72 - value |= ((new_value << HEADER_BYTE_2_BIT) 73 - | (parity_byte << PARITY_BYTE_2_BIT)); 74 - drm_dbg_dp(audio->drm_dev, 75 - "Header Byte 2: value = 0x%x, parity_byte = 0x%x\n", 76 - value, parity_byte); 77 - 78 - msm_dp_audio_set_header(catalog, value, 79 - DP_AUDIO_SDP_STREAM, DP_AUDIO_SDP_HEADER_2); 80 - 81 - /* Config header and parity byte 3 */ 82 - value = msm_dp_audio_get_header(catalog, 83 - DP_AUDIO_SDP_STREAM, DP_AUDIO_SDP_HEADER_3); 84 - 85 - new_value = audio->channels - 1; 86 - parity_byte = msm_dp_utils_calculate_parity(new_value); 87 - value |= ((new_value << HEADER_BYTE_3_BIT) 88 - | (parity_byte << PARITY_BYTE_3_BIT)); 89 - drm_dbg_dp(audio->drm_dev, 90 - "Header Byte 3: value = 0x%x, parity_byte = 0x%x\n", 91 - value, parity_byte); 92 - 93 - msm_dp_audio_set_header(catalog, value, 94 - DP_AUDIO_SDP_STREAM, DP_AUDIO_SDP_HEADER_3); 40 + msm_dp_catalog_write_audio_stream(audio->catalog, &sdp_hdr); 95 41 } 96 42 97 43 static void msm_dp_audio_timestamp_sdp(struct msm_dp_audio_private *audio) 98 44 { 99 - struct msm_dp_catalog *catalog = audio->catalog; 100 - u32 value, new_value; 101 - u8 parity_byte; 45 + struct dp_sdp_header sdp_hdr = { 46 + .HB0 = 0x00, 47 + .HB1 = 0x01, 48 + .HB2 = 0x17, 49 + .HB3 = 0x0 | (0x11 << 2), 50 + }; 102 51 103 - /* Config header and parity byte 1 */ 104 - value = msm_dp_audio_get_header(catalog, 105 - DP_AUDIO_SDP_TIMESTAMP, DP_AUDIO_SDP_HEADER_1); 106 - 107 - new_value = 0x1; 108 - parity_byte = msm_dp_utils_calculate_parity(new_value); 109 - value |= ((new_value << HEADER_BYTE_1_BIT) 110 - | (parity_byte << PARITY_BYTE_1_BIT)); 111 - drm_dbg_dp(audio->drm_dev, 112 - "Header Byte 1: value = 0x%x, parity_byte = 0x%x\n", 113 - value, parity_byte); 114 - msm_dp_audio_set_header(catalog, value, 115 - DP_AUDIO_SDP_TIMESTAMP, DP_AUDIO_SDP_HEADER_1); 116 - 117 - /* Config header and parity byte 2 */ 118 - value = msm_dp_audio_get_header(catalog, 119 - DP_AUDIO_SDP_TIMESTAMP, DP_AUDIO_SDP_HEADER_2); 120 - 121 - new_value = 0x17; 122 - parity_byte = msm_dp_utils_calculate_parity(new_value); 123 - value |= ((new_value << HEADER_BYTE_2_BIT) 124 - | (parity_byte << PARITY_BYTE_2_BIT)); 125 - drm_dbg_dp(audio->drm_dev, 126 - "Header Byte 2: value = 0x%x, parity_byte = 0x%x\n", 127 - value, parity_byte); 128 - msm_dp_audio_set_header(catalog, value, 129 - DP_AUDIO_SDP_TIMESTAMP, DP_AUDIO_SDP_HEADER_2); 130 - 131 - /* Config header and parity byte 3 */ 132 - value = msm_dp_audio_get_header(catalog, 133 - DP_AUDIO_SDP_TIMESTAMP, DP_AUDIO_SDP_HEADER_3); 134 - 135 - new_value = (0x0 | (0x11 << 2)); 136 - parity_byte = msm_dp_utils_calculate_parity(new_value); 137 - value |= ((new_value << HEADER_BYTE_3_BIT) 138 - | (parity_byte << PARITY_BYTE_3_BIT)); 139 - drm_dbg_dp(audio->drm_dev, 140 - "Header Byte 3: value = 0x%x, parity_byte = 0x%x\n", 141 - value, parity_byte); 142 - msm_dp_audio_set_header(catalog, value, 143 - DP_AUDIO_SDP_TIMESTAMP, DP_AUDIO_SDP_HEADER_3); 52 + msm_dp_catalog_write_audio_timestamp(audio->catalog, &sdp_hdr); 144 53 } 145 54 146 55 static void msm_dp_audio_infoframe_sdp(struct msm_dp_audio_private *audio) 147 56 { 148 - struct msm_dp_catalog *catalog = audio->catalog; 149 - u32 value, new_value; 150 - u8 parity_byte; 57 + struct dp_sdp_header sdp_hdr = { 58 + .HB0 = 0x00, 59 + .HB1 = 0x84, 60 + .HB2 = 0x1b, 61 + .HB3 = 0x0 | (0x11 << 2), 62 + }; 151 63 152 - /* Config header and parity byte 1 */ 153 - value = msm_dp_audio_get_header(catalog, 154 - DP_AUDIO_SDP_INFOFRAME, DP_AUDIO_SDP_HEADER_1); 155 - 156 - new_value = 0x84; 157 - parity_byte = msm_dp_utils_calculate_parity(new_value); 158 - value |= ((new_value << HEADER_BYTE_1_BIT) 159 - | (parity_byte << PARITY_BYTE_1_BIT)); 160 - drm_dbg_dp(audio->drm_dev, 161 - "Header Byte 1: value = 0x%x, parity_byte = 0x%x\n", 162 - value, parity_byte); 163 - msm_dp_audio_set_header(catalog, value, 164 - DP_AUDIO_SDP_INFOFRAME, DP_AUDIO_SDP_HEADER_1); 165 - 166 - /* Config header and parity byte 2 */ 167 - value = msm_dp_audio_get_header(catalog, 168 - DP_AUDIO_SDP_INFOFRAME, DP_AUDIO_SDP_HEADER_2); 169 - 170 - new_value = 0x1b; 171 - parity_byte = msm_dp_utils_calculate_parity(new_value); 172 - value |= ((new_value << HEADER_BYTE_2_BIT) 173 - | (parity_byte << PARITY_BYTE_2_BIT)); 174 - drm_dbg_dp(audio->drm_dev, 175 - "Header Byte 2: value = 0x%x, parity_byte = 0x%x\n", 176 - value, parity_byte); 177 - msm_dp_audio_set_header(catalog, value, 178 - DP_AUDIO_SDP_INFOFRAME, DP_AUDIO_SDP_HEADER_2); 179 - 180 - /* Config header and parity byte 3 */ 181 - value = msm_dp_audio_get_header(catalog, 182 - DP_AUDIO_SDP_INFOFRAME, DP_AUDIO_SDP_HEADER_3); 183 - 184 - new_value = (0x0 | (0x11 << 2)); 185 - parity_byte = msm_dp_utils_calculate_parity(new_value); 186 - value |= ((new_value << HEADER_BYTE_3_BIT) 187 - | (parity_byte << PARITY_BYTE_3_BIT)); 188 - drm_dbg_dp(audio->drm_dev, 189 - "Header Byte 3: value = 0x%x, parity_byte = 0x%x\n", 190 - new_value, parity_byte); 191 - msm_dp_audio_set_header(catalog, value, 192 - DP_AUDIO_SDP_INFOFRAME, DP_AUDIO_SDP_HEADER_3); 64 + msm_dp_catalog_write_audio_infoframe(audio->catalog, &sdp_hdr); 193 65 } 194 66 195 67 static void msm_dp_audio_copy_management_sdp(struct msm_dp_audio_private *audio) 196 68 { 197 - struct msm_dp_catalog *catalog = audio->catalog; 198 - u32 value, new_value; 199 - u8 parity_byte; 69 + struct dp_sdp_header sdp_hdr = { 70 + .HB0 = 0x00, 71 + .HB1 = 0x05, 72 + .HB2 = 0x0f, 73 + .HB3 = 0x00, 74 + }; 200 75 201 - /* Config header and parity byte 1 */ 202 - value = msm_dp_audio_get_header(catalog, 203 - DP_AUDIO_SDP_COPYMANAGEMENT, DP_AUDIO_SDP_HEADER_1); 204 - 205 - new_value = 0x05; 206 - parity_byte = msm_dp_utils_calculate_parity(new_value); 207 - value |= ((new_value << HEADER_BYTE_1_BIT) 208 - | (parity_byte << PARITY_BYTE_1_BIT)); 209 - drm_dbg_dp(audio->drm_dev, 210 - "Header Byte 1: value = 0x%x, parity_byte = 0x%x\n", 211 - value, parity_byte); 212 - msm_dp_audio_set_header(catalog, value, 213 - DP_AUDIO_SDP_COPYMANAGEMENT, DP_AUDIO_SDP_HEADER_1); 214 - 215 - /* Config header and parity byte 2 */ 216 - value = msm_dp_audio_get_header(catalog, 217 - DP_AUDIO_SDP_COPYMANAGEMENT, DP_AUDIO_SDP_HEADER_2); 218 - 219 - new_value = 0x0F; 220 - parity_byte = msm_dp_utils_calculate_parity(new_value); 221 - value |= ((new_value << HEADER_BYTE_2_BIT) 222 - | (parity_byte << PARITY_BYTE_2_BIT)); 223 - drm_dbg_dp(audio->drm_dev, 224 - "Header Byte 2: value = 0x%x, parity_byte = 0x%x\n", 225 - value, parity_byte); 226 - msm_dp_audio_set_header(catalog, value, 227 - DP_AUDIO_SDP_COPYMANAGEMENT, DP_AUDIO_SDP_HEADER_2); 228 - 229 - /* Config header and parity byte 3 */ 230 - value = msm_dp_audio_get_header(catalog, 231 - DP_AUDIO_SDP_COPYMANAGEMENT, DP_AUDIO_SDP_HEADER_3); 232 - 233 - new_value = 0x0; 234 - parity_byte = msm_dp_utils_calculate_parity(new_value); 235 - value |= ((new_value << HEADER_BYTE_3_BIT) 236 - | (parity_byte << PARITY_BYTE_3_BIT)); 237 - drm_dbg_dp(audio->drm_dev, 238 - "Header Byte 3: value = 0x%x, parity_byte = 0x%x\n", 239 - value, parity_byte); 240 - msm_dp_audio_set_header(catalog, value, 241 - DP_AUDIO_SDP_COPYMANAGEMENT, DP_AUDIO_SDP_HEADER_3); 76 + msm_dp_catalog_write_audio_copy_mgmt(audio->catalog, &sdp_hdr); 242 77 } 243 78 244 79 static void msm_dp_audio_isrc_sdp(struct msm_dp_audio_private *audio) 245 80 { 246 - struct msm_dp_catalog *catalog = audio->catalog; 247 - u32 value, new_value; 248 - u8 parity_byte; 81 + struct dp_sdp_header sdp_hdr = { 82 + .HB0 = 0x00, 83 + .HB1 = 0x06, 84 + .HB2 = 0x0f, 85 + .HB3 = 0x00, 86 + }; 249 87 250 - /* Config header and parity byte 1 */ 251 - value = msm_dp_audio_get_header(catalog, 252 - DP_AUDIO_SDP_ISRC, DP_AUDIO_SDP_HEADER_1); 253 - 254 - new_value = 0x06; 255 - parity_byte = msm_dp_utils_calculate_parity(new_value); 256 - value |= ((new_value << HEADER_BYTE_1_BIT) 257 - | (parity_byte << PARITY_BYTE_1_BIT)); 258 - drm_dbg_dp(audio->drm_dev, 259 - "Header Byte 1: value = 0x%x, parity_byte = 0x%x\n", 260 - value, parity_byte); 261 - msm_dp_audio_set_header(catalog, value, 262 - DP_AUDIO_SDP_ISRC, DP_AUDIO_SDP_HEADER_1); 263 - 264 - /* Config header and parity byte 2 */ 265 - value = msm_dp_audio_get_header(catalog, 266 - DP_AUDIO_SDP_ISRC, DP_AUDIO_SDP_HEADER_2); 267 - 268 - new_value = 0x0F; 269 - parity_byte = msm_dp_utils_calculate_parity(new_value); 270 - value |= ((new_value << HEADER_BYTE_2_BIT) 271 - | (parity_byte << PARITY_BYTE_2_BIT)); 272 - drm_dbg_dp(audio->drm_dev, 273 - "Header Byte 2: value = 0x%x, parity_byte = 0x%x\n", 274 - value, parity_byte); 275 - msm_dp_audio_set_header(catalog, value, 276 - DP_AUDIO_SDP_ISRC, DP_AUDIO_SDP_HEADER_2); 88 + msm_dp_catalog_write_audio_isrc(audio->catalog, &sdp_hdr); 277 89 } 278 90 279 91 static void msm_dp_audio_setup_sdp(struct msm_dp_audio_private *audio) ··· 143 329 safe_to_exit_level = 5; 144 330 break; 145 331 default: 332 + safe_to_exit_level = 14; 146 333 drm_dbg_dp(audio->drm_dev, 147 334 "setting the default safe_to_exit_level = %u\n", 148 335 safe_to_exit_level); 149 - safe_to_exit_level = 14; 150 336 break; 151 337 } 152 338 ··· 353 539 } 354 540 355 541 struct msm_dp_audio *msm_dp_audio_get(struct platform_device *pdev, 356 - struct msm_dp_panel *panel, 357 542 struct msm_dp_catalog *catalog) 358 543 { 359 544 int rc = 0; 360 545 struct msm_dp_audio_private *audio; 361 546 struct msm_dp_audio *msm_dp_audio; 362 547 363 - if (!pdev || !panel || !catalog) { 548 + if (!pdev || !catalog) { 364 549 DRM_ERROR("invalid input\n"); 365 550 rc = -EINVAL; 366 551 goto error; ··· 375 562 audio->catalog = catalog; 376 563 377 564 msm_dp_audio = &audio->msm_dp_audio; 378 - 379 - msm_dp_catalog_audio_init(catalog); 380 565 381 566 return msm_dp_audio; 382 567 error:
-3
drivers/gpu/drm/msm/dp/dp_audio.h
··· 8 8 9 9 #include <linux/platform_device.h> 10 10 11 - #include "dp_panel.h" 12 11 #include "dp_catalog.h" 13 12 #include <sound/hdmi-codec.h> 14 13 ··· 27 28 * Creates and instance of dp audio. 28 29 * 29 30 * @pdev: caller's platform device instance. 30 - * @panel: an instance of msm_dp_panel module. 31 31 * @catalog: an instance of msm_dp_catalog module. 32 32 * 33 33 * Returns the error code in case of failure, otherwize 34 34 * an instance of newly created msm_dp_module. 35 35 */ 36 36 struct msm_dp_audio *msm_dp_audio_get(struct platform_device *pdev, 37 - struct msm_dp_panel *panel, 38 37 struct msm_dp_catalog *catalog); 39 38 40 39 /**
+59 -102
drivers/gpu/drm/msm/dp/dp_catalog.c
··· 79 79 struct device *dev; 80 80 struct drm_device *drm_dev; 81 81 struct dss_io_data io; 82 - u32 (*audio_map)[DP_AUDIO_SDP_HEADER_MAX]; 83 82 struct msm_dp_catalog msm_dp_catalog; 84 83 }; 85 84 ··· 273 274 REG_DP_DP_HPD_INT_STATUS, 274 275 state, state & DP_DP_HPD_STATE_STATUS_CONNECTED, 275 276 min(wait_us, 2000), wait_us); 276 - } 277 - 278 - static void dump_regs(void __iomem *base, int len) 279 - { 280 - int i; 281 - u32 x0, x4, x8, xc; 282 - u32 addr_off = 0; 283 - 284 - len = DIV_ROUND_UP(len, 16); 285 - for (i = 0; i < len; i++) { 286 - x0 = readl_relaxed(base + addr_off); 287 - x4 = readl_relaxed(base + addr_off + 0x04); 288 - x8 = readl_relaxed(base + addr_off + 0x08); 289 - xc = readl_relaxed(base + addr_off + 0x0c); 290 - 291 - pr_info("%08x: %08x %08x %08x %08x", addr_off, x0, x4, x8, xc); 292 - addr_off += 16; 293 - } 294 - } 295 - 296 - void msm_dp_catalog_dump_regs(struct msm_dp_catalog *msm_dp_catalog) 297 - { 298 - struct msm_dp_catalog_private *catalog = container_of(msm_dp_catalog, 299 - struct msm_dp_catalog_private, msm_dp_catalog); 300 - struct dss_io_data *io = &catalog->io; 301 - 302 - pr_info("AHB regs\n"); 303 - dump_regs(io->ahb.base, io->ahb.len); 304 - 305 - pr_info("AUXCLK regs\n"); 306 - dump_regs(io->aux.base, io->aux.len); 307 - 308 - pr_info("LCLK regs\n"); 309 - dump_regs(io->link.base, io->link.len); 310 - 311 - pr_info("P0CLK regs\n"); 312 - dump_regs(io->p0.base, io->p0.len); 313 277 } 314 278 315 279 u32 msm_dp_catalog_aux_get_irq(struct msm_dp_catalog *msm_dp_catalog) ··· 998 1036 display_hctl = (hsync_end_x << 16) | hsync_start_x; 999 1037 1000 1038 1001 - msm_dp_write_p0(catalog, MMSS_DP_INTF_CONFIG, 0x0); 1002 1039 msm_dp_write_p0(catalog, MMSS_DP_INTF_HSYNC_CTL, hsync_ctl); 1003 1040 msm_dp_write_p0(catalog, MMSS_DP_INTF_VSYNC_PERIOD_F0, vsync_period * 1004 1041 hsync_period); ··· 1121 1160 return &catalog->msm_dp_catalog; 1122 1161 } 1123 1162 1124 - u32 msm_dp_catalog_audio_get_header(struct msm_dp_catalog *msm_dp_catalog, 1125 - enum msm_dp_catalog_audio_sdp_type sdp, 1126 - enum msm_dp_catalog_audio_header_type header) 1163 + void msm_dp_catalog_write_audio_stream(struct msm_dp_catalog *msm_dp_catalog, 1164 + struct dp_sdp_header *sdp_hdr) 1127 1165 { 1128 - struct msm_dp_catalog_private *catalog; 1129 - u32 (*sdp_map)[DP_AUDIO_SDP_HEADER_MAX]; 1166 + struct msm_dp_catalog_private *catalog = container_of(msm_dp_catalog, 1167 + struct msm_dp_catalog_private, msm_dp_catalog); 1168 + u32 header[2]; 1130 1169 1131 - catalog = container_of(msm_dp_catalog, 1132 - struct msm_dp_catalog_private, msm_dp_catalog); 1170 + msm_dp_utils_pack_sdp_header(sdp_hdr, header); 1133 1171 1134 - sdp_map = catalog->audio_map; 1135 - 1136 - return msm_dp_read_link(catalog, sdp_map[sdp][header]); 1172 + msm_dp_write_link(catalog, MMSS_DP_AUDIO_STREAM_0, header[0]); 1173 + msm_dp_write_link(catalog, MMSS_DP_AUDIO_STREAM_1, header[1]); 1137 1174 } 1138 1175 1139 - void msm_dp_catalog_audio_set_header(struct msm_dp_catalog *msm_dp_catalog, 1140 - enum msm_dp_catalog_audio_sdp_type sdp, 1141 - enum msm_dp_catalog_audio_header_type header, 1142 - u32 data) 1176 + void msm_dp_catalog_write_audio_timestamp(struct msm_dp_catalog *msm_dp_catalog, 1177 + struct dp_sdp_header *sdp_hdr) 1143 1178 { 1144 - struct msm_dp_catalog_private *catalog; 1145 - u32 (*sdp_map)[DP_AUDIO_SDP_HEADER_MAX]; 1179 + struct msm_dp_catalog_private *catalog = container_of(msm_dp_catalog, 1180 + struct msm_dp_catalog_private, msm_dp_catalog); 1181 + u32 header[2]; 1146 1182 1147 - if (!msm_dp_catalog) 1148 - return; 1183 + msm_dp_utils_pack_sdp_header(sdp_hdr, header); 1149 1184 1150 - catalog = container_of(msm_dp_catalog, 1151 - struct msm_dp_catalog_private, msm_dp_catalog); 1185 + msm_dp_write_link(catalog, MMSS_DP_AUDIO_TIMESTAMP_0, header[0]); 1186 + msm_dp_write_link(catalog, MMSS_DP_AUDIO_TIMESTAMP_1, header[1]); 1187 + } 1152 1188 1153 - sdp_map = catalog->audio_map; 1189 + void msm_dp_catalog_write_audio_infoframe(struct msm_dp_catalog *msm_dp_catalog, 1190 + struct dp_sdp_header *sdp_hdr) 1191 + { 1192 + struct msm_dp_catalog_private *catalog = container_of(msm_dp_catalog, 1193 + struct msm_dp_catalog_private, msm_dp_catalog); 1194 + u32 header[2]; 1154 1195 1155 - msm_dp_write_link(catalog, sdp_map[sdp][header], data); 1196 + msm_dp_utils_pack_sdp_header(sdp_hdr, header); 1197 + 1198 + msm_dp_write_link(catalog, MMSS_DP_AUDIO_INFOFRAME_0, header[0]); 1199 + msm_dp_write_link(catalog, MMSS_DP_AUDIO_INFOFRAME_1, header[1]); 1200 + } 1201 + 1202 + void msm_dp_catalog_write_audio_copy_mgmt(struct msm_dp_catalog *msm_dp_catalog, 1203 + struct dp_sdp_header *sdp_hdr) 1204 + { 1205 + struct msm_dp_catalog_private *catalog = container_of(msm_dp_catalog, 1206 + struct msm_dp_catalog_private, msm_dp_catalog); 1207 + u32 header[2]; 1208 + 1209 + msm_dp_utils_pack_sdp_header(sdp_hdr, header); 1210 + 1211 + msm_dp_write_link(catalog, MMSS_DP_AUDIO_COPYMANAGEMENT_0, header[0]); 1212 + msm_dp_write_link(catalog, MMSS_DP_AUDIO_COPYMANAGEMENT_1, header[1]); 1213 + } 1214 + 1215 + void msm_dp_catalog_write_audio_isrc(struct msm_dp_catalog *msm_dp_catalog, 1216 + struct dp_sdp_header *sdp_hdr) 1217 + { 1218 + struct msm_dp_catalog_private *catalog = container_of(msm_dp_catalog, 1219 + struct msm_dp_catalog_private, msm_dp_catalog); 1220 + struct dp_sdp_header tmp = *sdp_hdr; 1221 + u32 header[2]; 1222 + u32 reg; 1223 + 1224 + /* XXX: is it necessary to preserve this field? */ 1225 + reg = msm_dp_read_link(catalog, MMSS_DP_AUDIO_ISRC_1); 1226 + tmp.HB3 = FIELD_GET(HEADER_3_MASK, reg); 1227 + 1228 + msm_dp_utils_pack_sdp_header(&tmp, header); 1229 + 1230 + msm_dp_write_link(catalog, MMSS_DP_AUDIO_ISRC_0, header[0]); 1231 + msm_dp_write_link(catalog, MMSS_DP_AUDIO_ISRC_1, header[1]); 1156 1232 } 1157 1233 1158 1234 void msm_dp_catalog_audio_config_acr(struct msm_dp_catalog *msm_dp_catalog, u32 select) ··· 1273 1275 drm_dbg_dp(catalog->drm_dev, "sdp_cfg2 = 0x%x\n", sdp_cfg2); 1274 1276 1275 1277 msm_dp_write_link(catalog, MMSS_DP_SDP_CFG2, sdp_cfg2); 1276 - } 1277 - 1278 - void msm_dp_catalog_audio_init(struct msm_dp_catalog *msm_dp_catalog) 1279 - { 1280 - struct msm_dp_catalog_private *catalog; 1281 - 1282 - static u32 sdp_map[][DP_AUDIO_SDP_HEADER_MAX] = { 1283 - { 1284 - MMSS_DP_AUDIO_STREAM_0, 1285 - MMSS_DP_AUDIO_STREAM_1, 1286 - MMSS_DP_AUDIO_STREAM_1, 1287 - }, 1288 - { 1289 - MMSS_DP_AUDIO_TIMESTAMP_0, 1290 - MMSS_DP_AUDIO_TIMESTAMP_1, 1291 - MMSS_DP_AUDIO_TIMESTAMP_1, 1292 - }, 1293 - { 1294 - MMSS_DP_AUDIO_INFOFRAME_0, 1295 - MMSS_DP_AUDIO_INFOFRAME_1, 1296 - MMSS_DP_AUDIO_INFOFRAME_1, 1297 - }, 1298 - { 1299 - MMSS_DP_AUDIO_COPYMANAGEMENT_0, 1300 - MMSS_DP_AUDIO_COPYMANAGEMENT_1, 1301 - MMSS_DP_AUDIO_COPYMANAGEMENT_1, 1302 - }, 1303 - { 1304 - MMSS_DP_AUDIO_ISRC_0, 1305 - MMSS_DP_AUDIO_ISRC_1, 1306 - MMSS_DP_AUDIO_ISRC_1, 1307 - }, 1308 - }; 1309 - 1310 - if (!msm_dp_catalog) 1311 - return; 1312 - 1313 - catalog = container_of(msm_dp_catalog, 1314 - struct msm_dp_catalog_private, msm_dp_catalog); 1315 - 1316 - catalog->audio_map = sdp_map; 1317 1278 } 1318 1279 1319 1280 void msm_dp_catalog_audio_sfe_level(struct msm_dp_catalog *msm_dp_catalog, u32 safe_to_exit_level)
+10 -25
drivers/gpu/drm/msm/dp/dp_catalog.h
··· 31 31 #define DP_HW_VERSION_1_0 0x10000000 32 32 #define DP_HW_VERSION_1_2 0x10020000 33 33 34 - enum msm_dp_catalog_audio_sdp_type { 35 - DP_AUDIO_SDP_STREAM, 36 - DP_AUDIO_SDP_TIMESTAMP, 37 - DP_AUDIO_SDP_INFOFRAME, 38 - DP_AUDIO_SDP_COPYMANAGEMENT, 39 - DP_AUDIO_SDP_ISRC, 40 - DP_AUDIO_SDP_MAX, 41 - }; 42 - 43 - enum msm_dp_catalog_audio_header_type { 44 - DP_AUDIO_SDP_HEADER_1, 45 - DP_AUDIO_SDP_HEADER_2, 46 - DP_AUDIO_SDP_HEADER_3, 47 - DP_AUDIO_SDP_HEADER_MAX, 48 - }; 49 - 50 34 struct msm_dp_catalog { 51 35 bool wide_bus_en; 52 36 }; ··· 88 104 u32 sync_start, u32 width_blanking, u32 msm_dp_active); 89 105 void msm_dp_catalog_panel_enable_vsc_sdp(struct msm_dp_catalog *msm_dp_catalog, struct dp_sdp *vsc_sdp); 90 106 void msm_dp_catalog_panel_disable_vsc_sdp(struct msm_dp_catalog *msm_dp_catalog); 91 - void msm_dp_catalog_dump_regs(struct msm_dp_catalog *msm_dp_catalog); 92 107 void msm_dp_catalog_panel_tpg_enable(struct msm_dp_catalog *msm_dp_catalog, 93 108 struct drm_display_mode *drm_mode); 94 109 void msm_dp_catalog_panel_tpg_disable(struct msm_dp_catalog *msm_dp_catalog); ··· 95 112 struct msm_dp_catalog *msm_dp_catalog_get(struct device *dev); 96 113 97 114 /* DP Audio APIs */ 98 - u32 msm_dp_catalog_audio_get_header(struct msm_dp_catalog *msm_dp_catalog, 99 - enum msm_dp_catalog_audio_sdp_type sdp, 100 - enum msm_dp_catalog_audio_header_type header); 101 - void msm_dp_catalog_audio_set_header(struct msm_dp_catalog *msm_dp_catalog, 102 - enum msm_dp_catalog_audio_sdp_type sdp, 103 - enum msm_dp_catalog_audio_header_type header, 104 - u32 data); 115 + void msm_dp_catalog_write_audio_stream(struct msm_dp_catalog *msm_dp_catalog, 116 + struct dp_sdp_header *sdp_hdr); 117 + void msm_dp_catalog_write_audio_timestamp(struct msm_dp_catalog *msm_dp_catalog, 118 + struct dp_sdp_header *sdp_hdr); 119 + void msm_dp_catalog_write_audio_infoframe(struct msm_dp_catalog *msm_dp_catalog, 120 + struct dp_sdp_header *sdp_hdr); 121 + void msm_dp_catalog_write_audio_copy_mgmt(struct msm_dp_catalog *msm_dp_catalog, 122 + struct dp_sdp_header *sdp_hdr); 123 + void msm_dp_catalog_write_audio_isrc(struct msm_dp_catalog *msm_dp_catalog, 124 + struct dp_sdp_header *sdp_hdr); 105 125 void msm_dp_catalog_audio_config_acr(struct msm_dp_catalog *catalog, u32 select); 106 126 void msm_dp_catalog_audio_enable(struct msm_dp_catalog *catalog, bool enable); 107 127 void msm_dp_catalog_audio_config_sdp(struct msm_dp_catalog *catalog); 108 - void msm_dp_catalog_audio_init(struct msm_dp_catalog *catalog); 109 128 void msm_dp_catalog_audio_sfe_level(struct msm_dp_catalog *catalog, u32 safe_to_exit_level); 110 129 111 130 #endif /* _DP_CATALOG_H_ */
+1 -1
drivers/gpu/drm/msm/dp/dp_ctrl.c
··· 178 178 u32 cc, tb; 179 179 180 180 msm_dp_catalog_ctrl_lane_mapping(ctrl->catalog); 181 - msm_dp_catalog_ctrl_mainlink_ctrl(ctrl->catalog, true); 182 181 msm_dp_catalog_setup_peripheral_flush(ctrl->catalog); 183 182 184 183 msm_dp_ctrl_config_ctrl(ctrl); ··· 2070 2071 2071 2072 msm_dp_catalog_ctrl_mainlink_ctrl(ctrl->catalog, false); 2072 2073 2074 + dev_pm_opp_set_rate(ctrl->dev, 0); 2073 2075 msm_dp_ctrl_link_clk_disable(&ctrl->msm_dp_ctrl); 2074 2076 2075 2077 DRM_DEBUG_DP("Before, phy=%p init_count=%d power_on=%d\n",
+2 -9
drivers/gpu/drm/msm/dp/dp_display.c
··· 722 722 { 723 723 int rc = 0; 724 724 struct device *dev = &dp->msm_dp_display.pdev->dev; 725 - struct msm_dp_panel_in panel_in = { 726 - .dev = dev, 727 - }; 728 725 struct phy *phy; 729 726 730 727 phy = devm_phy_get(dev, "dp"); ··· 762 765 goto error_link; 763 766 } 764 767 765 - panel_in.aux = dp->aux; 766 - panel_in.catalog = dp->catalog; 767 - panel_in.link = dp->link; 768 - 769 - dp->panel = msm_dp_panel_get(&panel_in); 768 + dp->panel = msm_dp_panel_get(dev, dp->aux, dp->link, dp->catalog); 770 769 if (IS_ERR(dp->panel)) { 771 770 rc = PTR_ERR(dp->panel); 772 771 DRM_ERROR("failed to initialize panel, rc = %d\n", rc); ··· 780 787 goto error_ctrl; 781 788 } 782 789 783 - dp->audio = msm_dp_audio_get(dp->msm_dp_display.pdev, dp->panel, dp->catalog); 790 + dp->audio = msm_dp_audio_get(dp->msm_dp_display.pdev, dp->catalog); 784 791 if (IS_ERR(dp->audio)) { 785 792 rc = PTR_ERR(dp->audio); 786 793 pr_err("failed to initialize audio, rc = %d\n", rc);
+8 -18
drivers/gpu/drm/msm/dp/dp_panel.c
··· 317 317 return 0; 318 318 } 319 319 320 - void msm_dp_panel_dump_regs(struct msm_dp_panel *msm_dp_panel) 321 - { 322 - struct msm_dp_catalog *catalog; 323 - struct msm_dp_panel_private *panel; 324 - 325 - panel = container_of(msm_dp_panel, struct msm_dp_panel_private, msm_dp_panel); 326 - catalog = panel->catalog; 327 - 328 - msm_dp_catalog_dump_regs(catalog); 329 - } 330 - 331 320 int msm_dp_panel_timing_cfg(struct msm_dp_panel *msm_dp_panel) 332 321 { 333 322 u32 data, total_ver, total_hor; ··· 475 486 return 0; 476 487 } 477 488 478 - struct msm_dp_panel *msm_dp_panel_get(struct msm_dp_panel_in *in) 489 + struct msm_dp_panel *msm_dp_panel_get(struct device *dev, struct drm_dp_aux *aux, 490 + struct msm_dp_link *link, struct msm_dp_catalog *catalog) 479 491 { 480 492 struct msm_dp_panel_private *panel; 481 493 struct msm_dp_panel *msm_dp_panel; 482 494 int ret; 483 495 484 - if (!in->dev || !in->catalog || !in->aux || !in->link) { 496 + if (!dev || !catalog || !aux || !link) { 485 497 DRM_ERROR("invalid input\n"); 486 498 return ERR_PTR(-EINVAL); 487 499 } 488 500 489 - panel = devm_kzalloc(in->dev, sizeof(*panel), GFP_KERNEL); 501 + panel = devm_kzalloc(dev, sizeof(*panel), GFP_KERNEL); 490 502 if (!panel) 491 503 return ERR_PTR(-ENOMEM); 492 504 493 - panel->dev = in->dev; 494 - panel->aux = in->aux; 495 - panel->catalog = in->catalog; 496 - panel->link = in->link; 505 + panel->dev = dev; 506 + panel->aux = aux; 507 + panel->catalog = catalog; 508 + panel->link = link; 497 509 498 510 msm_dp_panel = &panel->msm_dp_panel; 499 511 msm_dp_panel->max_bw_code = DP_LINK_BW_8_1;
+2 -9
drivers/gpu/drm/msm/dp/dp_panel.h
··· 21 21 bool out_fmt_is_yuv_420; 22 22 }; 23 23 24 - struct msm_dp_panel_in { 25 - struct device *dev; 26 - struct drm_dp_aux *aux; 27 - struct msm_dp_link *link; 28 - struct msm_dp_catalog *catalog; 29 - }; 30 - 31 24 struct msm_dp_panel_psr { 32 25 u8 version; 33 26 u8 capabilities; ··· 48 55 int msm_dp_panel_init_panel_info(struct msm_dp_panel *msm_dp_panel); 49 56 int msm_dp_panel_deinit(struct msm_dp_panel *msm_dp_panel); 50 57 int msm_dp_panel_timing_cfg(struct msm_dp_panel *msm_dp_panel); 51 - void msm_dp_panel_dump_regs(struct msm_dp_panel *msm_dp_panel); 52 58 int msm_dp_panel_read_sink_caps(struct msm_dp_panel *msm_dp_panel, 53 59 struct drm_connector *connector); 54 60 u32 msm_dp_panel_get_mode_bpp(struct msm_dp_panel *msm_dp_panel, u32 mode_max_bpp, ··· 84 92 lane_count == 4); 85 93 } 86 94 87 - struct msm_dp_panel *msm_dp_panel_get(struct msm_dp_panel_in *in); 95 + struct msm_dp_panel *msm_dp_panel_get(struct device *dev, struct drm_dp_aux *aux, 96 + struct msm_dp_link *link, struct msm_dp_catalog *catalog); 88 97 void msm_dp_panel_put(struct msm_dp_panel *msm_dp_panel); 89 98 #endif /* _DP_PANEL_H_ */
+1 -9
drivers/gpu/drm/msm/dp/dp_utils.c
··· 74 74 return parity_byte; 75 75 } 76 76 77 - ssize_t msm_dp_utils_pack_sdp_header(struct dp_sdp_header *sdp_header, u32 *header_buff) 77 + void msm_dp_utils_pack_sdp_header(struct dp_sdp_header *sdp_header, u32 header_buff[2]) 78 78 { 79 - size_t length; 80 - 81 - length = sizeof(header_buff); 82 - if (length < DP_SDP_HEADER_SIZE) 83 - return -ENOSPC; 84 - 85 79 header_buff[0] = FIELD_PREP(HEADER_0_MASK, sdp_header->HB0) | 86 80 FIELD_PREP(PARITY_0_MASK, msm_dp_utils_calculate_parity(sdp_header->HB0)) | 87 81 FIELD_PREP(HEADER_1_MASK, sdp_header->HB1) | ··· 85 91 FIELD_PREP(PARITY_2_MASK, msm_dp_utils_calculate_parity(sdp_header->HB2)) | 86 92 FIELD_PREP(HEADER_3_MASK, sdp_header->HB3) | 87 93 FIELD_PREP(PARITY_3_MASK, msm_dp_utils_calculate_parity(sdp_header->HB3)); 88 - 89 - return length; 90 94 }
+1 -1
drivers/gpu/drm/msm/dp/dp_utils.h
··· 31 31 u8 msm_dp_utils_get_g0_value(u8 data); 32 32 u8 msm_dp_utils_get_g1_value(u8 data); 33 33 u8 msm_dp_utils_calculate_parity(u32 data); 34 - ssize_t msm_dp_utils_pack_sdp_header(struct dp_sdp_header *sdp_header, u32 *header_buff); 34 + void msm_dp_utils_pack_sdp_header(struct dp_sdp_header *sdp_header, u32 header_buff[2]); 35 35 36 36 #endif /* _DP_UTILS_H_ */
+2
drivers/gpu/drm/msm/dsi/dsi_cfg.c
··· 286 286 &sdm845_dsi_cfg, &msm_dsi_6g_v2_host_ops}, 287 287 {MSM_DSI_VER_MAJOR_6G, MSM_DSI_6G_VER_MINOR_V2_3_0, 288 288 &sdm845_dsi_cfg, &msm_dsi_6g_v2_host_ops}, 289 + {MSM_DSI_VER_MAJOR_6G, MSM_DSI_6G_VER_MINOR_V2_3_1, 290 + &sdm845_dsi_cfg, &msm_dsi_6g_v2_host_ops}, 289 291 {MSM_DSI_VER_MAJOR_6G, MSM_DSI_6G_VER_MINOR_V2_4_0, 290 292 &sdm845_dsi_cfg, &msm_dsi_6g_v2_host_ops}, 291 293 {MSM_DSI_VER_MAJOR_6G, MSM_DSI_6G_VER_MINOR_V2_4_1,
+1
drivers/gpu/drm/msm/dsi/dsi_cfg.h
··· 23 23 #define MSM_DSI_6G_VER_MINOR_V2_2_0 0x20000000 24 24 #define MSM_DSI_6G_VER_MINOR_V2_2_1 0x20020001 25 25 #define MSM_DSI_6G_VER_MINOR_V2_3_0 0x20030000 26 + #define MSM_DSI_6G_VER_MINOR_V2_3_1 0x20030001 26 27 #define MSM_DSI_6G_VER_MINOR_V2_4_0 0x20040000 27 28 #define MSM_DSI_6G_VER_MINOR_V2_4_1 0x20040001 28 29 #define MSM_DSI_6G_VER_MINOR_V2_5_0 0x20050000
+2
drivers/gpu/drm/msm/dsi/phy/dsi_phy.c
··· 567 567 .data = &dsi_phy_14nm_8953_cfgs }, 568 568 { .compatible = "qcom,sm6125-dsi-phy-14nm", 569 569 .data = &dsi_phy_14nm_2290_cfgs }, 570 + { .compatible = "qcom,sm6150-dsi-phy-14nm", 571 + .data = &dsi_phy_14nm_6150_cfgs }, 570 572 #endif 571 573 #ifdef CONFIG_DRM_MSM_DSI_10NM_PHY 572 574 { .compatible = "qcom,dsi-phy-10nm",
+1
drivers/gpu/drm/msm/dsi/phy/dsi_phy.h
··· 46 46 extern const struct msm_dsi_phy_cfg dsi_phy_28nm_8960_cfgs; 47 47 extern const struct msm_dsi_phy_cfg dsi_phy_20nm_cfgs; 48 48 extern const struct msm_dsi_phy_cfg dsi_phy_14nm_cfgs; 49 + extern const struct msm_dsi_phy_cfg dsi_phy_14nm_6150_cfgs; 49 50 extern const struct msm_dsi_phy_cfg dsi_phy_14nm_660_cfgs; 50 51 extern const struct msm_dsi_phy_cfg dsi_phy_14nm_2290_cfgs; 51 52 extern const struct msm_dsi_phy_cfg dsi_phy_14nm_8953_cfgs;
+21
drivers/gpu/drm/msm/dsi/phy/dsi_phy_14nm.c
··· 1032 1032 { .supply = "vcca", .init_load_uA = 73400 }, 1033 1033 }; 1034 1034 1035 + static const struct regulator_bulk_data dsi_phy_14nm_36mA_regulators[] = { 1036 + { .supply = "vdda", .init_load_uA = 36000 }, 1037 + }; 1038 + 1035 1039 const struct msm_dsi_phy_cfg dsi_phy_14nm_cfgs = { 1036 1040 .has_phy_lane = true, 1037 1041 .regulator_data = dsi_phy_14nm_17mA_regulators, ··· 1099 1095 .min_pll_rate = VCO_MIN_RATE, 1100 1096 .max_pll_rate = VCO_MAX_RATE, 1101 1097 .io_start = { 0x5e94400 }, 1098 + .num_dsi_phy = 1, 1099 + }; 1100 + 1101 + const struct msm_dsi_phy_cfg dsi_phy_14nm_6150_cfgs = { 1102 + .has_phy_lane = true, 1103 + .regulator_data = dsi_phy_14nm_36mA_regulators, 1104 + .num_regulators = ARRAY_SIZE(dsi_phy_14nm_36mA_regulators), 1105 + .ops = { 1106 + .enable = dsi_14nm_phy_enable, 1107 + .disable = dsi_14nm_phy_disable, 1108 + .pll_init = dsi_pll_14nm_init, 1109 + .save_pll_state = dsi_14nm_pll_save_state, 1110 + .restore_pll_state = dsi_14nm_pll_restore_state, 1111 + }, 1112 + .min_pll_rate = VCO_MIN_RATE, 1113 + .max_pll_rate = VCO_MAX_RATE, 1114 + .io_start = { 0xae94400 }, 1102 1115 .num_dsi_phy = 1, 1103 1116 };
+1 -1
drivers/gpu/drm/msm/hdmi/hdmi_phy_8998.c
··· 137 137 138 138 base <<= (digclk_divsel == 2 ? 1 : 0); 139 139 140 - return (base <= 2046 ? base : 2046); 140 + return base; 141 141 } 142 142 143 143 static inline u32 pll_get_pll_cmp(u64 fdata, unsigned long ref_clk)
+1 -1
drivers/gpu/drm/msm/msm_drv.c
··· 538 538 539 539 /* Only supported if per-process address space is supported: */ 540 540 if (priv->gpu->aspace == ctx->aspace) 541 - return -EOPNOTSUPP; 541 + return UERR(EOPNOTSUPP, dev, "requires per-process pgtables"); 542 542 543 543 if (should_fail(&fail_gem_iova, obj->size)) 544 544 return -ENOMEM;
+7
drivers/gpu/drm/msm/msm_drv.h
··· 28 28 29 29 #include <drm/drm_atomic.h> 30 30 #include <drm/drm_atomic_helper.h> 31 + #include <drm/drm_print.h> 31 32 #include <drm/drm_probe_helper.h> 32 33 #include <drm/display/drm_dsc.h> 33 34 #include <drm/msm_drm.h> ··· 506 505 kthread_work_func_t fn, 507 506 clockid_t clock_id, 508 507 enum hrtimer_mode mode); 508 + 509 + /* Helper for returning a UABI error with optional logging which can make 510 + * it easier for userspace to understand what it is doing wrong. 511 + */ 512 + #define UERR(err, drm, fmt, ...) \ 513 + ({ DRM_DEV_DEBUG_DRIVER((drm)->dev, fmt, ##__VA_ARGS__); -(err); }) 509 514 510 515 #define DBG(fmt, ...) DRM_DEBUG_DRIVER(fmt"\n", ##__VA_ARGS__) 511 516 #define VERB(fmt, ...) if (0) DRM_DEBUG_DRIVER(fmt"\n", ##__VA_ARGS__)
+28 -39
drivers/gpu/drm/msm/msm_gem_submit.c
··· 20 20 /* For userspace errors, use DRM_UT_DRIVER.. so that userspace can enable 21 21 * error msgs for debugging, but we don't spam dmesg by default 22 22 */ 23 - #define SUBMIT_ERROR(submit, fmt, ...) \ 24 - DRM_DEV_DEBUG_DRIVER((submit)->dev->dev, fmt, ##__VA_ARGS__) 23 + #define SUBMIT_ERROR(err, submit, fmt, ...) \ 24 + UERR(err, (submit)->dev, fmt, ##__VA_ARGS__) 25 25 26 26 /* 27 27 * Cmdstream submission: ··· 142 142 143 143 if ((submit_bo.flags & ~MSM_SUBMIT_BO_FLAGS) || 144 144 !(submit_bo.flags & MANDATORY_FLAGS)) { 145 - SUBMIT_ERROR(submit, "invalid flags: %x\n", submit_bo.flags); 146 - ret = -EINVAL; 145 + ret = SUBMIT_ERROR(EINVAL, submit, "invalid flags: %x\n", submit_bo.flags); 147 146 i = 0; 148 147 goto out; 149 148 } ··· 161 162 */ 162 163 obj = idr_find(&file->object_idr, submit->bos[i].handle); 163 164 if (!obj) { 164 - SUBMIT_ERROR(submit, "invalid handle %u at index %u\n", submit->bos[i].handle, i); 165 - ret = -EINVAL; 165 + ret = SUBMIT_ERROR(EINVAL, submit, "invalid handle %u at index %u\n", submit->bos[i].handle, i); 166 166 goto out_unlock; 167 167 } 168 168 ··· 204 206 case MSM_SUBMIT_CMD_CTX_RESTORE_BUF: 205 207 break; 206 208 default: 207 - SUBMIT_ERROR(submit, "invalid type: %08x\n", submit_cmd.type); 208 - return -EINVAL; 209 + return SUBMIT_ERROR(EINVAL, submit, "invalid type: %08x\n", submit_cmd.type); 209 210 } 210 211 211 212 if (submit_cmd.size % 4) { 212 - SUBMIT_ERROR(submit, "non-aligned cmdstream buffer size: %u\n", 213 - submit_cmd.size); 214 - ret = -EINVAL; 213 + ret = SUBMIT_ERROR(EINVAL, submit, "non-aligned cmdstream buffer size: %u\n", 214 + submit_cmd.size); 215 215 goto out; 216 216 } 217 217 ··· 367 371 struct drm_gem_object **obj, uint64_t *iova) 368 372 { 369 373 if (idx >= submit->nr_bos) { 370 - SUBMIT_ERROR(submit, "invalid buffer index: %u (out of %u)\n", 371 - idx, submit->nr_bos); 372 - return -EINVAL; 374 + return SUBMIT_ERROR(EINVAL, submit, "invalid buffer index: %u (out of %u)\n", 375 + idx, submit->nr_bos); 373 376 } 374 377 375 378 if (obj) ··· 387 392 uint32_t *ptr; 388 393 int ret = 0; 389 394 390 - if (offset % 4) { 391 - SUBMIT_ERROR(submit, "non-aligned cmdstream buffer: %u\n", offset); 392 - return -EINVAL; 393 - } 395 + if (offset % 4) 396 + return SUBMIT_ERROR(EINVAL, submit, "non-aligned cmdstream buffer: %u\n", offset); 394 397 395 398 /* For now, just map the entire thing. Eventually we probably 396 399 * to do it page-by-page, w/ kmap() if not vmap()d.. ··· 407 414 uint64_t iova; 408 415 409 416 if (submit_reloc.submit_offset % 4) { 410 - SUBMIT_ERROR(submit, "non-aligned reloc offset: %u\n", 411 - submit_reloc.submit_offset); 412 - ret = -EINVAL; 417 + ret = SUBMIT_ERROR(EINVAL, submit, "non-aligned reloc offset: %u\n", 418 + submit_reloc.submit_offset); 413 419 goto out; 414 420 } 415 421 ··· 417 425 418 426 if ((off >= (obj->size / 4)) || 419 427 (off < last_offset)) { 420 - SUBMIT_ERROR(submit, "invalid offset %u at reloc %u\n", off, i); 421 - ret = -EINVAL; 428 + ret = SUBMIT_ERROR(EINVAL, submit, "invalid offset %u at reloc %u\n", off, i); 422 429 goto out; 423 430 } 424 431 ··· 504 513 505 514 if (syncobj_desc.point && 506 515 !drm_core_check_feature(submit->dev, DRIVER_SYNCOBJ_TIMELINE)) { 507 - ret = -EOPNOTSUPP; 516 + ret = SUBMIT_ERROR(EOPNOTSUPP, submit, "syncobj timeline unsupported"); 508 517 break; 509 518 } 510 519 511 520 if (syncobj_desc.flags & ~MSM_SUBMIT_SYNCOBJ_FLAGS) { 512 - ret = -EINVAL; 521 + ret = -SUBMIT_ERROR(EINVAL, submit, "invalid syncobj flags: %x", syncobj_desc.flags); 513 522 break; 514 523 } 515 524 ··· 522 531 syncobjs[i] = 523 532 drm_syncobj_find(file, syncobj_desc.handle); 524 533 if (!syncobjs[i]) { 525 - ret = -EINVAL; 534 + ret = SUBMIT_ERROR(EINVAL, submit, "invalid syncobj handle: %u", i); 526 535 break; 527 536 } 528 537 } ··· 579 588 post_deps[i].point = syncobj_desc.point; 580 589 581 590 if (syncobj_desc.flags) { 582 - ret = -EINVAL; 591 + ret = UERR(EINVAL, dev, "invalid syncobj flags"); 583 592 break; 584 593 } 585 594 586 595 if (syncobj_desc.point) { 587 596 if (!drm_core_check_feature(dev, 588 597 DRIVER_SYNCOBJ_TIMELINE)) { 589 - ret = -EOPNOTSUPP; 598 + ret = UERR(EOPNOTSUPP, dev, "syncobj timeline unsupported"); 590 599 break; 591 600 } 592 601 ··· 600 609 post_deps[i].syncobj = 601 610 drm_syncobj_find(file, syncobj_desc.handle); 602 611 if (!post_deps[i].syncobj) { 603 - ret = -EINVAL; 612 + ret = UERR(EINVAL, dev, "invalid syncobj handle"); 604 613 break; 605 614 } 606 615 } ··· 668 677 * be more clever to dispatch to appropriate gpu module: 669 678 */ 670 679 if (MSM_PIPE_ID(args->flags) != MSM_PIPE_3D0) 671 - return -EINVAL; 680 + return UERR(EINVAL, dev, "invalid pipe"); 672 681 673 682 if (MSM_PIPE_FLAGS(args->flags) & ~MSM_SUBMIT_FLAGS) 674 - return -EINVAL; 683 + return UERR(EINVAL, dev, "invalid flags"); 675 684 676 685 if (args->flags & MSM_SUBMIT_SUDO) { 677 686 if (!IS_ENABLED(CONFIG_DRM_MSM_GPU_SUDO) || ··· 715 724 in_fence = sync_file_get_fence(args->fence_fd); 716 725 717 726 if (!in_fence) { 718 - ret = -EINVAL; 727 + ret = UERR(EINVAL, dev, "invalid in-fence"); 719 728 goto out_unlock; 720 729 } 721 730 ··· 778 787 goto out; 779 788 780 789 if (!submit->cmd[i].size || 781 - ((submit->cmd[i].size + submit->cmd[i].offset) > 782 - obj->size / 4)) { 783 - SUBMIT_ERROR(submit, "invalid cmdstream size: %u\n", submit->cmd[i].size * 4); 784 - ret = -EINVAL; 790 + (size_add(submit->cmd[i].size, submit->cmd[i].offset) > obj->size / 4)) { 791 + ret = UERR(EINVAL, dev, "invalid cmdstream size: %u\n", 792 + submit->cmd[i].size * 4); 785 793 goto out; 786 794 } 787 795 ··· 790 800 continue; 791 801 792 802 if (!gpu->allow_relocs) { 793 - SUBMIT_ERROR(submit, "relocs not allowed\n"); 794 - ret = -EINVAL; 803 + ret = UERR(EINVAL, dev, "relocs not allowed\n"); 795 804 goto out; 796 805 } 797 806 ··· 816 827 (!args->fence || idr_find(&queue->fence_idr, args->fence))) { 817 828 spin_unlock(&queue->idr_lock); 818 829 idr_preload_end(); 819 - ret = -EINVAL; 830 + ret = UERR(EINVAL, dev, "invalid in-fence-sn"); 820 831 goto out; 821 832 } 822 833
-1
drivers/gpu/drm/msm/msm_kms.c
··· 244 244 ret = priv->kms_init(ddev); 245 245 if (ret) { 246 246 DRM_DEV_ERROR(dev, "failed to load kms\n"); 247 - priv->kms = NULL; 248 247 return ret; 249 248 } 250 249
+51 -28
drivers/gpu/drm/msm/msm_mdss.c
··· 166 166 static void msm_mdss_setup_ubwc_dec_20(struct msm_mdss *msm_mdss) 167 167 { 168 168 const struct msm_mdss_data *data = msm_mdss->mdss_data; 169 + u32 value = MDSS_UBWC_STATIC_UBWC_SWIZZLE(data->ubwc_swizzle) | 170 + MDSS_UBWC_STATIC_HIGHEST_BANK_BIT(data->highest_bank_bit); 169 171 170 - writel_relaxed(data->ubwc_static, msm_mdss->mmio + REG_MDSS_UBWC_STATIC); 172 + if (data->ubwc_bank_spread) 173 + value |= MDSS_UBWC_STATIC_UBWC_BANK_SPREAD; 174 + 175 + if (data->ubwc_enc_version == UBWC_1_0) 176 + value |= MDSS_UBWC_STATIC_UBWC_MIN_ACC_LEN(1); 177 + 178 + writel_relaxed(value, msm_mdss->mmio + REG_MDSS_UBWC_STATIC); 171 179 } 172 180 173 181 static void msm_mdss_setup_ubwc_dec_30(struct msm_mdss *msm_mdss) 174 182 { 175 183 const struct msm_mdss_data *data = msm_mdss->mdss_data; 176 - u32 value = (data->ubwc_swizzle & 0x1) | 177 - (data->highest_bank_bit & 0x3) << 4 | 178 - (data->macrotile_mode & 0x1) << 12; 184 + u32 value = MDSS_UBWC_STATIC_UBWC_SWIZZLE(data->ubwc_swizzle & 0x1) | 185 + MDSS_UBWC_STATIC_HIGHEST_BANK_BIT(data->highest_bank_bit); 186 + 187 + if (data->macrotile_mode) 188 + value |= MDSS_UBWC_STATIC_MACROTILE_MODE; 179 189 180 190 if (data->ubwc_enc_version == UBWC_3_0) 181 - value |= BIT(10); 191 + value |= MDSS_UBWC_STATIC_UBWC_AMSBC; 182 192 183 193 if (data->ubwc_enc_version == UBWC_1_0) 184 - value |= BIT(8); 194 + value |= MDSS_UBWC_STATIC_UBWC_MIN_ACC_LEN(1); 185 195 186 196 writel_relaxed(value, msm_mdss->mmio + REG_MDSS_UBWC_STATIC); 187 197 } ··· 199 189 static void msm_mdss_setup_ubwc_dec_40(struct msm_mdss *msm_mdss) 200 190 { 201 191 const struct msm_mdss_data *data = msm_mdss->mdss_data; 202 - u32 value = (data->ubwc_swizzle & 0x7) | 203 - (data->ubwc_static & 0x1) << 3 | 204 - (data->highest_bank_bit & 0x7) << 4 | 205 - (data->macrotile_mode & 0x1) << 12; 192 + u32 value = MDSS_UBWC_STATIC_UBWC_SWIZZLE(data->ubwc_swizzle) | 193 + MDSS_UBWC_STATIC_HIGHEST_BANK_BIT(data->highest_bank_bit); 194 + 195 + if (data->ubwc_bank_spread) 196 + value |= MDSS_UBWC_STATIC_UBWC_BANK_SPREAD; 197 + 198 + if (data->macrotile_mode) 199 + value |= MDSS_UBWC_STATIC_MACROTILE_MODE; 206 200 207 201 writel_relaxed(value, msm_mdss->mmio + REG_MDSS_UBWC_STATIC); 208 202 ··· 586 572 .ubwc_enc_version = UBWC_4_0, 587 573 .ubwc_dec_version = UBWC_4_0, 588 574 .ubwc_swizzle = 4, 589 - .ubwc_static = 1, 575 + .ubwc_bank_spread = true, 590 576 .highest_bank_bit = 0, 591 - .macrotile_mode = 1, 577 + .macrotile_mode = true, 592 578 .reg_bus_bw = 74000, 593 579 }; 594 580 595 581 static const struct msm_mdss_data sc7180_data = { 596 582 .ubwc_enc_version = UBWC_2_0, 597 583 .ubwc_dec_version = UBWC_2_0, 598 - .ubwc_static = 0x1e, 584 + .ubwc_swizzle = 6, 585 + .ubwc_bank_spread = true, 599 586 .highest_bank_bit = 0x1, 600 587 .reg_bus_bw = 76800, 601 588 }; ··· 605 590 .ubwc_enc_version = UBWC_3_0, 606 591 .ubwc_dec_version = UBWC_4_0, 607 592 .ubwc_swizzle = 6, 608 - .ubwc_static = 1, 593 + .ubwc_bank_spread = true, 609 594 .highest_bank_bit = 1, 610 - .macrotile_mode = 1, 595 + .macrotile_mode = true, 611 596 .reg_bus_bw = 74000, 612 597 }; 613 598 ··· 615 600 .ubwc_enc_version = UBWC_3_0, 616 601 .ubwc_dec_version = UBWC_3_0, 617 602 .highest_bank_bit = 3, 618 - .macrotile_mode = 1, 603 + .macrotile_mode = true, 619 604 .reg_bus_bw = 76800, 620 605 }; 621 606 ··· 623 608 .ubwc_enc_version = UBWC_4_0, 624 609 .ubwc_dec_version = UBWC_4_0, 625 610 .ubwc_swizzle = 6, 626 - .ubwc_static = 1, 611 + .ubwc_bank_spread = true, 627 612 .highest_bank_bit = 3, 628 - .macrotile_mode = 1, 613 + .macrotile_mode = true, 629 614 .reg_bus_bw = 76800, 630 615 }; 631 616 ··· 647 632 .ubwc_enc_version = UBWC_2_0, 648 633 .ubwc_dec_version = UBWC_2_0, 649 634 .ubwc_swizzle = 6, 650 - .ubwc_static = 0x1e, 635 + .ubwc_bank_spread = true, 651 636 .highest_bank_bit = 1, 652 637 .reg_bus_bw = 76800, 653 638 }; ··· 670 655 .ubwc_enc_version = UBWC_1_0, 671 656 .ubwc_dec_version = UBWC_2_0, 672 657 .ubwc_swizzle = 7, 673 - .ubwc_static = 0x11f, 658 + .ubwc_bank_spread = true, 674 659 .highest_bank_bit = 0x1, 675 660 .reg_bus_bw = 76800, 676 661 }; ··· 682 667 .highest_bank_bit = 1, 683 668 }; 684 669 670 + static const struct msm_mdss_data sm6150_data = { 671 + .ubwc_enc_version = UBWC_2_0, 672 + .ubwc_dec_version = UBWC_2_0, 673 + .highest_bank_bit = 1, 674 + .reg_bus_bw = 76800, 675 + }; 676 + 685 677 static const struct msm_mdss_data sm8250_data = { 686 678 .ubwc_enc_version = UBWC_4_0, 687 679 .ubwc_dec_version = UBWC_4_0, 688 680 .ubwc_swizzle = 6, 689 - .ubwc_static = 1, 681 + .ubwc_bank_spread = true, 690 682 /* TODO: highest_bank_bit = 2 for LP_DDR4 */ 691 683 .highest_bank_bit = 3, 692 - .macrotile_mode = 1, 684 + .macrotile_mode = true, 693 685 .reg_bus_bw = 76800, 694 686 }; 695 687 ··· 704 682 .ubwc_enc_version = UBWC_4_0, 705 683 .ubwc_dec_version = UBWC_4_0, 706 684 .ubwc_swizzle = 6, 707 - .ubwc_static = 1, 685 + .ubwc_bank_spread = true, 708 686 /* TODO: highest_bank_bit = 2 for LP_DDR4 */ 709 687 .highest_bank_bit = 3, 710 - .macrotile_mode = 1, 688 + .macrotile_mode = true, 711 689 .reg_bus_bw = 74000, 712 690 }; 713 691 ··· 715 693 .ubwc_enc_version = UBWC_4_0, 716 694 .ubwc_dec_version = UBWC_4_3, 717 695 .ubwc_swizzle = 6, 718 - .ubwc_static = 1, 696 + .ubwc_bank_spread = true, 719 697 /* TODO: highest_bank_bit = 2 for LP_DDR4 */ 720 698 .highest_bank_bit = 3, 721 - .macrotile_mode = 1, 699 + .macrotile_mode = true, 722 700 .reg_bus_bw = 57000, 723 701 }; 724 702 ··· 726 704 .ubwc_enc_version = UBWC_4_0, 727 705 .ubwc_dec_version = UBWC_4_3, 728 706 .ubwc_swizzle = 6, 729 - .ubwc_static = 1, 707 + .ubwc_bank_spread = true, 730 708 /* TODO: highest_bank_bit = 2 for LP_DDR4 */ 731 709 .highest_bank_bit = 3, 732 - .macrotile_mode = 1, 710 + .macrotile_mode = true, 733 711 /* TODO: Add reg_bus_bw with real value */ 734 712 }; 735 713 ··· 746 724 { .compatible = "qcom,sc8280xp-mdss", .data = &sc8280xp_data }, 747 725 { .compatible = "qcom,sm6115-mdss", .data = &sm6115_data }, 748 726 { .compatible = "qcom,sm6125-mdss", .data = &sm6125_data }, 727 + { .compatible = "qcom,sm6150-mdss", .data = &sm6150_data }, 749 728 { .compatible = "qcom,sm6350-mdss", .data = &sm6350_data }, 750 729 { .compatible = "qcom,sm6375-mdss", .data = &sm6350_data }, 751 730 { .compatible = "qcom,sm7150-mdss", .data = &sm7150_data },
+2 -2
drivers/gpu/drm/msm/msm_mdss.h
··· 11 11 /* can be read from register 0x58 */ 12 12 u32 ubwc_dec_version; 13 13 u32 ubwc_swizzle; 14 - u32 ubwc_static; 15 14 u32 highest_bank_bit; 16 - u32 macrotile_mode; 15 + bool ubwc_bank_spread; 16 + bool macrotile_mode; 17 17 u32 reg_bus_bw; 18 18 }; 19 19
+1 -1
drivers/gpu/drm/msm/msm_submitqueue.c
··· 18 18 19 19 switch (sysprof) { 20 20 default: 21 - return -EINVAL; 21 + return UERR(EINVAL, gpu->dev, "Invalid sysprof: %d", sysprof); 22 22 case 2: 23 23 pm_runtime_get_sync(&gpu->pdev->dev); 24 24 fallthrough;
+5
drivers/gpu/drm/msm/registers/adreno/a6xx_gmu.xml
··· 52 52 <reg32 offset="0x23fd" name="GMU_DCVS_PERF_SETTING"/> 53 53 <reg32 offset="0x23fe" name="GMU_DCVS_BW_SETTING"/> 54 54 <reg32 offset="0x23ff" name="GMU_DCVS_RETURN"/> 55 + <reg32 offset="0x2bf8" name="GMU_CORE_FW_VERSION"> 56 + <bitfield name="MAJOR" low="28" high="31"/> 57 + <bitfield name="MINOR" low="16" high="27"/> 58 + <bitfield name="STEP" low="0" high="15"/> 59 + </reg32> 55 60 <reg32 offset="0x4c00" name="GMU_ICACHE_CONFIG"/> 56 61 <reg32 offset="0x4c01" name="GMU_DCACHE_CONFIG"/> 57 62 <reg32 offset="0x4c0f" name="GMU_SYS_BUS_CONFIG"/>
+10 -1
drivers/gpu/drm/msm/registers/display/mdss.xml
··· 21 21 22 22 <reg32 offset="0x00058" name="UBWC_DEC_HW_VERSION"/> 23 23 24 - <reg32 offset="0x00144" name="UBWC_STATIC"/> 24 + <reg32 offset="0x00144" name="UBWC_STATIC"> 25 + <bitfield name="UBWC_SWIZZLE" low="0" high="2"/> 26 + <bitfield name="UBWC_BANK_SPREAD" pos="3"/> 27 + <!-- high=5 for UBWC < 4.0 --> 28 + <bitfield name="HIGHEST_BANK_BIT" low="4" high="6"/> 29 + <bitfield name="UBWC_MIN_ACC_LEN" low="8" high="9"/> 30 + <bitfield name="UBWC_AMSBC" pos="10"/> 31 + <bitfield name="MACROTILE_MODE" pos="12"/> 32 + </reg32> 33 + 25 34 <reg32 offset="0x00150" name="UBWC_CTRL_2"/> 26 35 <reg32 offset="0x00154" name="UBWC_PREDICTION_MODE"/> 27 36 </domain>
+65 -17
drivers/opp/core.c
··· 101 101 * representation in the OPP table and manage the clock configuration themselves 102 102 * in an platform specific way. 103 103 */ 104 - static bool assert_single_clk(struct opp_table *opp_table) 104 + static bool assert_single_clk(struct opp_table *opp_table, 105 + unsigned int __always_unused index) 105 106 { 106 107 return !WARN_ON(opp_table->clk_count > 1); 107 108 } 109 + 110 + /* 111 + * Returns true if clock table is large enough to contain the clock index. 112 + */ 113 + static bool assert_clk_index(struct opp_table *opp_table, 114 + unsigned int index) 115 + { 116 + return opp_table->clk_count > index; 117 + } 118 + 119 + /* 120 + * Returns true if bandwidth table is large enough to contain the bandwidth index. 121 + */ 122 + static bool assert_bandwidth_index(struct opp_table *opp_table, 123 + unsigned int index) 124 + { 125 + return opp_table->path_count > index; 126 + } 127 + 128 + /** 129 + * dev_pm_opp_get_bw() - Gets the bandwidth corresponding to an opp 130 + * @opp: opp for which bandwidth has to be returned for 131 + * @peak: select peak or average bandwidth 132 + * @index: bandwidth index 133 + * 134 + * Return: bandwidth in kBps, else return 0 135 + */ 136 + unsigned long dev_pm_opp_get_bw(struct dev_pm_opp *opp, bool peak, int index) 137 + { 138 + if (IS_ERR_OR_NULL(opp)) { 139 + pr_err("%s: Invalid parameters\n", __func__); 140 + return 0; 141 + } 142 + 143 + if (index >= opp->opp_table->path_count) 144 + return 0; 145 + 146 + if (!opp->bandwidth) 147 + return 0; 148 + 149 + return peak ? opp->bandwidth[index].peak : opp->bandwidth[index].avg; 150 + } 151 + EXPORT_SYMBOL_GPL(dev_pm_opp_get_bw); 108 152 109 153 /** 110 154 * dev_pm_opp_get_voltage() - Gets the voltage corresponding to an opp ··· 543 499 unsigned long (*read)(struct dev_pm_opp *opp, int index), 544 500 bool (*compare)(struct dev_pm_opp **opp, struct dev_pm_opp *temp_opp, 545 501 unsigned long opp_key, unsigned long key), 546 - bool (*assert)(struct opp_table *opp_table)) 502 + bool (*assert)(struct opp_table *opp_table, unsigned int index)) 547 503 { 548 504 struct dev_pm_opp *temp_opp, *opp = ERR_PTR(-ERANGE); 549 505 550 506 /* Assert that the requirement is met */ 551 - if (assert && !assert(opp_table)) 507 + if (assert && !assert(opp_table, index)) 552 508 return ERR_PTR(-EINVAL); 553 509 554 510 mutex_lock(&opp_table->lock); ··· 576 532 unsigned long (*read)(struct dev_pm_opp *opp, int index), 577 533 bool (*compare)(struct dev_pm_opp **opp, struct dev_pm_opp *temp_opp, 578 534 unsigned long opp_key, unsigned long key), 579 - bool (*assert)(struct opp_table *opp_table)) 535 + bool (*assert)(struct opp_table *opp_table, unsigned int index)) 580 536 { 581 537 struct opp_table *opp_table; 582 538 struct dev_pm_opp *opp; ··· 599 555 static struct dev_pm_opp *_find_key_exact(struct device *dev, 600 556 unsigned long key, int index, bool available, 601 557 unsigned long (*read)(struct dev_pm_opp *opp, int index), 602 - bool (*assert)(struct opp_table *opp_table)) 558 + bool (*assert)(struct opp_table *opp_table, unsigned int index)) 603 559 { 604 560 /* 605 561 * The value of key will be updated here, but will be ignored as the ··· 612 568 static struct dev_pm_opp *_opp_table_find_key_ceil(struct opp_table *opp_table, 613 569 unsigned long *key, int index, bool available, 614 570 unsigned long (*read)(struct dev_pm_opp *opp, int index), 615 - bool (*assert)(struct opp_table *opp_table)) 571 + bool (*assert)(struct opp_table *opp_table, unsigned int index)) 616 572 { 617 573 return _opp_table_find_key(opp_table, key, index, available, read, 618 574 _compare_ceil, assert); ··· 621 577 static struct dev_pm_opp *_find_key_ceil(struct device *dev, unsigned long *key, 622 578 int index, bool available, 623 579 unsigned long (*read)(struct dev_pm_opp *opp, int index), 624 - bool (*assert)(struct opp_table *opp_table)) 580 + bool (*assert)(struct opp_table *opp_table, unsigned int index)) 625 581 { 626 582 return _find_key(dev, key, index, available, read, _compare_ceil, 627 583 assert); ··· 630 586 static struct dev_pm_opp *_find_key_floor(struct device *dev, 631 587 unsigned long *key, int index, bool available, 632 588 unsigned long (*read)(struct dev_pm_opp *opp, int index), 633 - bool (*assert)(struct opp_table *opp_table)) 589 + bool (*assert)(struct opp_table *opp_table, unsigned int index)) 634 590 { 635 591 return _find_key(dev, key, index, available, read, _compare_floor, 636 592 assert); ··· 691 647 dev_pm_opp_find_freq_exact_indexed(struct device *dev, unsigned long freq, 692 648 u32 index, bool available) 693 649 { 694 - return _find_key_exact(dev, freq, index, available, _read_freq, NULL); 650 + return _find_key_exact(dev, freq, index, available, _read_freq, 651 + assert_clk_index); 695 652 } 696 653 EXPORT_SYMBOL_GPL(dev_pm_opp_find_freq_exact_indexed); 697 654 ··· 752 707 dev_pm_opp_find_freq_ceil_indexed(struct device *dev, unsigned long *freq, 753 708 u32 index) 754 709 { 755 - return _find_key_ceil(dev, freq, index, true, _read_freq, NULL); 710 + return _find_key_ceil(dev, freq, index, true, _read_freq, 711 + assert_clk_index); 756 712 } 757 713 EXPORT_SYMBOL_GPL(dev_pm_opp_find_freq_ceil_indexed); 758 714 ··· 806 760 dev_pm_opp_find_freq_floor_indexed(struct device *dev, unsigned long *freq, 807 761 u32 index) 808 762 { 809 - return _find_key_floor(dev, freq, index, true, _read_freq, NULL); 763 + return _find_key_floor(dev, freq, index, true, _read_freq, assert_clk_index); 810 764 } 811 765 EXPORT_SYMBOL_GPL(dev_pm_opp_find_freq_floor_indexed); 812 766 ··· 924 878 unsigned long temp = *bw; 925 879 struct dev_pm_opp *opp; 926 880 927 - opp = _find_key_ceil(dev, &temp, index, true, _read_bw, NULL); 881 + opp = _find_key_ceil(dev, &temp, index, true, _read_bw, 882 + assert_bandwidth_index); 928 883 *bw = temp; 929 884 return opp; 930 885 } ··· 956 909 unsigned long temp = *bw; 957 910 struct dev_pm_opp *opp; 958 911 959 - opp = _find_key_floor(dev, &temp, index, true, _read_bw, NULL); 912 + opp = _find_key_floor(dev, &temp, index, true, _read_bw, 913 + assert_bandwidth_index); 960 914 *bw = temp; 961 915 return opp; 962 916 } ··· 1750 1702 if (IS_ERR(opp_table)) 1751 1703 return; 1752 1704 1753 - if (!assert_single_clk(opp_table)) 1705 + if (!assert_single_clk(opp_table, 0)) 1754 1706 goto put_table; 1755 1707 1756 1708 mutex_lock(&opp_table->lock); ··· 2102 2054 unsigned long tol, u_volt = data->u_volt; 2103 2055 int ret; 2104 2056 2105 - if (!assert_single_clk(opp_table)) 2057 + if (!assert_single_clk(opp_table, 0)) 2106 2058 return -EINVAL; 2107 2059 2108 2060 new_opp = _opp_allocate(opp_table); ··· 2858 2810 return r; 2859 2811 } 2860 2812 2861 - if (!assert_single_clk(opp_table)) { 2813 + if (!assert_single_clk(opp_table, 0)) { 2862 2814 r = -EINVAL; 2863 2815 goto put_table; 2864 2816 } ··· 2934 2886 return r; 2935 2887 } 2936 2888 2937 - if (!assert_single_clk(opp_table)) { 2889 + if (!assert_single_clk(opp_table, 0)) { 2938 2890 r = -EINVAL; 2939 2891 goto put_table; 2940 2892 }
+7
include/linux/pm_opp.h
··· 102 102 struct opp_table *dev_pm_opp_get_opp_table(struct device *dev); 103 103 void dev_pm_opp_put_opp_table(struct opp_table *opp_table); 104 104 105 + unsigned long dev_pm_opp_get_bw(struct dev_pm_opp *opp, bool peak, int index); 106 + 105 107 unsigned long dev_pm_opp_get_voltage(struct dev_pm_opp *opp); 106 108 107 109 int dev_pm_opp_get_supplies(struct dev_pm_opp *opp, struct dev_pm_opp_supply *supplies); ··· 206 204 } 207 205 208 206 static inline void dev_pm_opp_put_opp_table(struct opp_table *opp_table) {} 207 + 208 + static inline unsigned long dev_pm_opp_get_bw(struct dev_pm_opp *opp, bool peak, int index) 209 + { 210 + return 0; 211 + } 209 212 210 213 static inline unsigned long dev_pm_opp_get_voltage(struct dev_pm_opp *opp) 211 214 {
+1
include/uapi/drm/msm_drm.h
··· 90 90 #define MSM_PARAM_RAYTRACING 0x11 /* RO */ 91 91 #define MSM_PARAM_UBWC_SWIZZLE 0x12 /* RO */ 92 92 #define MSM_PARAM_MACROTILE_MODE 0x13 /* RO */ 93 + #define MSM_PARAM_UCHE_TRAP_BASE 0x14 /* RO */ 93 94 94 95 /* For backwards compat. The original support for preemption was based on 95 96 * a single ring per priority level so # of priority levels equals the #