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

Updates for v6.15

GPU:
- Fix obscure GMU suspend failure
- Expose syncobj timeline support
- Extend GPU devcoredump with pagetable info
- a623 support
- Fix a6xx gen1/gen2 indexed-register blocks in gpu snapshot / devcoredump

Display:
- Add cpu-cfg interconnect paths on SM8560 and SM8650
- Introduce KMS OMMU fault handler, causing devcoredump snapshot
- Fixed error pointer dereference in msm_kms_init_aspace()

DPU:
- Fix mode_changing handling
- Add writeback support on SM6150 (QCS615)
- Fix DSC programming in 1:1:1 topology
- Reworked hardware resource allocation, moving it to the CRTC code
- Enabled support for Concurrent WriteBack (CWB) on SM8650
- Enabled CDM blocks on all relevant platforms
- Reworked debugfs interface for BW/clocks debugging
- Clear perf params before calculating bw
- Support YUV formats on writeback
- Fixed double inclusion
- Fixed writeback in YUV formats when using cloned output, Dropped
wb2_formats_rgb
- Corrected dpu_crtc_check_mode_changed and struct dpu_encoder_virt
kerneldocs
- Fixed uninitialized variable in dpu_crtc_kickoff_clone_mode()

DSI:
- DSC-related fixes
- Rework clock programming

DSI PHY:
- Fix 7nm (and lower) PHY programming
- Add proper DT schema definitions for DSI PHY clocks

HDMI:
- Rework the driver, enabling the use of the HDMI Connector framework

Bindings:
- Added eDP PHY on SA8775P

Misc:
- mailmap/MAINTAINERS: update Dmitry's email addr

Signed-off-by: Dave Airlie <airlied@redhat.com>
From: Rob Clark <robdclark@gmail.com>
Link: https://patchwork.freedesktop.org/patch/msgid/CAF6AEGu-rbEFzQQ-me6qRLgBOJ=Xro1PL=PhtKJ-K9=bCaiK0w@mail.gmail.com

+1770 -1015
+5 -4
.mailmap
··· 200 200 Dengcheng Zhu <dzhu@wavecomp.com> <dengcheng.zhu@mips.com> 201 201 <dev.kurt@vandijck-laurijssen.be> <kurt.van.dijck@eia.be> 202 202 Dikshita Agarwal <quic_dikshita@quicinc.com> <dikshita@codeaurora.org> 203 - Dmitry Baryshkov <dbaryshkov@gmail.com> 204 - Dmitry Baryshkov <dbaryshkov@gmail.com> <[dbaryshkov@gmail.com]> 205 - Dmitry Baryshkov <dbaryshkov@gmail.com> <dmitry_baryshkov@mentor.com> 206 - Dmitry Baryshkov <dbaryshkov@gmail.com> <dmitry_eremin@mentor.com> 203 + Dmitry Baryshkov <lumag@kernel.org> <dbaryshkov@gmail.com> 204 + Dmitry Baryshkov <lumag@kernel.org> <[dbaryshkov@gmail.com]> 205 + Dmitry Baryshkov <lumag@kernel.org> <dmitry_baryshkov@mentor.com> 206 + Dmitry Baryshkov <lumag@kernel.org> <dmitry_eremin@mentor.com> 207 + Dmitry Baryshkov <lumag@kernel.org> <dmitry.baryshkov@linaro.org> 207 208 Dmitry Safonov <0x7f454c46@gmail.com> <dima@arista.com> 208 209 Dmitry Safonov <0x7f454c46@gmail.com> <d.safonov@partner.samsung.com> 209 210 Dmitry Safonov <0x7f454c46@gmail.com> <dsafonov@virtuozzo.com>
+11 -59
Documentation/devicetree/bindings/display/msm/dsi-controller-main.yaml
··· 231 231 then: 232 232 properties: 233 233 clocks: 234 + minItems: 7 234 235 maxItems: 7 235 236 clock-names: 236 237 items: ··· 249 248 contains: 250 249 enum: 251 250 - qcom,msm8916-dsi-ctrl 252 - then: 253 - properties: 254 - clocks: 255 - maxItems: 6 256 - clock-names: 257 - items: 258 - - const: mdp_core 259 - - const: iface 260 - - const: bus 261 - - const: byte 262 - - const: pixel 263 - - const: core 264 - 265 - - if: 266 - properties: 267 - compatible: 268 - contains: 269 - enum: 270 251 - qcom,msm8953-dsi-ctrl 271 252 - qcom,msm8976-dsi-ctrl 272 253 then: 273 254 properties: 274 255 clocks: 256 + minItems: 6 275 257 maxItems: 6 276 258 clock-names: 277 259 items: ··· 275 291 then: 276 292 properties: 277 293 clocks: 294 + minItems: 7 278 295 maxItems: 7 279 296 clock-names: 280 297 items: ··· 296 311 then: 297 312 properties: 298 313 clocks: 314 + minItems: 7 299 315 maxItems: 7 300 316 clock-names: 301 317 items: ··· 314 328 contains: 315 329 enum: 316 330 - qcom,msm8998-dsi-ctrl 317 - - qcom,sm6125-dsi-ctrl 318 - - qcom,sm6350-dsi-ctrl 319 - then: 320 - properties: 321 - clocks: 322 - maxItems: 6 323 - clock-names: 324 - items: 325 - - const: byte 326 - - const: byte_intf 327 - - const: pixel 328 - - const: core 329 - - const: iface 330 - - const: bus 331 - 332 - - if: 333 - properties: 334 - compatible: 335 - contains: 336 - enum: 337 331 - qcom,sc7180-dsi-ctrl 338 332 - qcom,sc7280-dsi-ctrl 333 + - qcom,sdm845-dsi-ctrl 334 + - qcom,sm6115-dsi-ctrl 335 + - qcom,sm6125-dsi-ctrl 336 + - qcom,sm6350-dsi-ctrl 337 + - qcom,sm6375-dsi-ctrl 339 338 - qcom,sm6150-dsi-ctrl 340 339 - qcom,sm7150-dsi-ctrl 341 340 - qcom,sm8150-dsi-ctrl ··· 332 361 then: 333 362 properties: 334 363 clocks: 364 + minItems: 6 335 365 maxItems: 6 336 366 clock-names: 337 367 items: ··· 352 380 then: 353 381 properties: 354 382 clocks: 383 + minItems: 9 355 384 maxItems: 9 356 385 clock-names: 357 386 items: ··· 365 392 - const: core_mmss 366 393 - const: pixel 367 394 - const: core 368 - 369 - - if: 370 - properties: 371 - compatible: 372 - contains: 373 - enum: 374 - - qcom,sdm845-dsi-ctrl 375 - - qcom,sm6115-dsi-ctrl 376 - - qcom,sm6375-dsi-ctrl 377 - then: 378 - properties: 379 - clocks: 380 - maxItems: 6 381 - clock-names: 382 - items: 383 - - const: byte 384 - - const: byte_intf 385 - - const: pixel 386 - - const: core 387 - - const: iface 388 - - const: bus 389 395 390 396 unevaluatedProperties: false 391 397
+2
Documentation/devicetree/bindings/display/msm/dsi-phy-common.yaml
··· 15 15 properties: 16 16 "#clock-cells": 17 17 const: 1 18 + description: 19 + See include/dt-bindings/clock/qcom,dsi-phy-28nm.h for clock IDs. 18 20 19 21 "#phy-cells": 20 22 const: 0
+1
Documentation/devicetree/bindings/display/msm/gmu.yaml
··· 123 123 compatible: 124 124 contains: 125 125 enum: 126 + - qcom,adreno-gmu-623.0 126 127 - qcom,adreno-gmu-635.0 127 128 - qcom,adreno-gmu-660.1 128 129 - qcom,adreno-gmu-663.0
+30 -2
Documentation/devicetree/bindings/display/msm/qcom,sa8775p-mdss.yaml
··· 52 52 items: 53 53 - const: qcom,sa8775p-dp 54 54 55 + "^phy@[0-9a-f]+$": 56 + type: object 57 + additionalProperties: true 58 + properties: 59 + compatible: 60 + const: qcom,sa8775p-edp-phy 61 + 55 62 required: 56 63 - compatible 57 64 ··· 68 61 - | 69 62 #include <dt-bindings/interconnect/qcom,icc.h> 70 63 #include <dt-bindings/interrupt-controller/arm-gic.h> 64 + #include <dt-bindings/clock/qcom,sa8775p-dispcc.h> 71 65 #include <dt-bindings/clock/qcom,sa8775p-gcc.h> 72 66 #include <dt-bindings/interconnect/qcom,sa8775p-rpmh.h> 73 67 #include <dt-bindings/power/qcom,rpmhpd.h> ··· 166 158 }; 167 159 }; 168 160 161 + mdss0_dp0_phy: phy@aec2a00 { 162 + compatible = "qcom,sa8775p-edp-phy"; 163 + 164 + reg = <0x0aec2a00 0x200>, 165 + <0x0aec2200 0xd0>, 166 + <0x0aec2600 0xd0>, 167 + <0x0aec2000 0x1c8>; 168 + 169 + clocks = <&dispcc0 MDSS_DISP_CC_MDSS_DPTX0_AUX_CLK>, 170 + <&dispcc0 MDSS_DISP_CC_MDSS_AHB_CLK>; 171 + clock-names = "aux", 172 + "cfg_ahb"; 173 + 174 + #clock-cells = <1>; 175 + #phy-cells = <0>; 176 + 177 + vdda-phy-supply = <&vreg_l1c>; 178 + vdda-pll-supply = <&vreg_l4a>; 179 + }; 180 + 169 181 displayport-controller@af54000 { 170 182 compatible = "qcom,sa8775p-dp"; 171 183 ··· 214 186 215 187 assigned-clocks = <&dispcc_mdss_dptx0_link_clk_src>, 216 188 <&dispcc_mdss_dptx0_pixel0_clk_src>; 217 - assigned-clock-parents = <&mdss0_edp_phy 0>, <&mdss0_edp_phy 1>; 189 + assigned-clock-parents = <&mdss0_dp0_phy 0>, <&mdss0_dp0_phy 1>; 218 190 219 - phys = <&mdss0_edp_phy>; 191 + phys = <&mdss0_dp0_phy>; 220 192 phy-names = "dp"; 221 193 222 194 operating-points-v2 = <&dp_opp_table>;
+9 -5
Documentation/devicetree/bindings/display/msm/qcom,sm8550-mdss.yaml
··· 30 30 maxItems: 1 31 31 32 32 interconnects: 33 - maxItems: 2 33 + items: 34 + - description: Interconnect path from mdp0 port to the data bus 35 + - description: Interconnect path from CPU to the reg bus 34 36 35 37 interconnect-names: 36 - maxItems: 2 38 + items: 39 + - const: mdp0-mem 40 + - const: cpu-cfg 37 41 38 42 patternProperties: 39 43 "^display-controller@[0-9a-f]+$": ··· 95 91 reg = <0x0ae00000 0x1000>; 96 92 reg-names = "mdss"; 97 93 98 - interconnects = <&mmss_noc MASTER_MDP 0 &gem_noc SLAVE_LLCC 0>, 99 - <&mc_virt MASTER_LLCC 0 &mc_virt SLAVE_EBI1 0>; 100 - interconnect-names = "mdp0-mem", "mdp1-mem"; 94 + interconnects = <&mmss_noc MASTER_MDP 0 &mc_virt SLAVE_EBI1 0>, 95 + <&gem_noc MASTER_APPSS_PROC 0 &config_noc SLAVE_DISPLAY_CFG 0>; 96 + interconnect-names = "mdp0-mem", "cpu-cfg"; 101 97 102 98 resets = <&dispcc DISP_CC_MDSS_CORE_BCR>; 103 99
+11 -2
Documentation/devicetree/bindings/display/msm/qcom,sm8650-mdss.yaml
··· 29 29 maxItems: 1 30 30 31 31 interconnects: 32 - maxItems: 2 32 + items: 33 + - description: Interconnect path from mdp0 port to the data bus 34 + - description: Interconnect path from CPU to the reg bus 33 35 34 36 interconnect-names: 35 - maxItems: 2 37 + items: 38 + - const: mdp0-mem 39 + - const: cpu-cfg 36 40 37 41 patternProperties: 38 42 "^display-controller@[0-9a-f]+$": ··· 79 75 #include <dt-bindings/clock/qcom,rpmh.h> 80 76 #include <dt-bindings/interrupt-controller/arm-gic.h> 81 77 #include <dt-bindings/power/qcom,rpmhpd.h> 78 + #include <dt-bindings/interconnect/qcom,sm8650-rpmh.h> 82 79 83 80 display-subsystem@ae00000 { 84 81 compatible = "qcom,sm8650-mdss"; 85 82 reg = <0x0ae00000 0x1000>; 86 83 reg-names = "mdss"; 84 + 85 + interconnects = <&mmss_noc MASTER_MDP 0 &mc_virt SLAVE_EBI1 0>, 86 + <&gem_noc MASTER_APPSS_PROC 0 &config_noc SLAVE_DISPLAY_CFG 0>; 87 + interconnect-names = "mdp0-mem", "cpu-cfg"; 87 88 88 89 resets = <&dispcc_core_bcr>; 89 90
+2 -1
MAINTAINERS
··· 7389 7389 DRM DRIVER for Qualcomm display hardware 7390 7390 M: Rob Clark <robdclark@gmail.com> 7391 7391 M: Abhinav Kumar <quic_abhinavk@quicinc.com> 7392 - M: Dmitry Baryshkov <dmitry.baryshkov@linaro.org> 7392 + M: Dmitry Baryshkov <lumag@kernel.org> 7393 7393 R: Sean Paul <sean@poorly.run> 7394 7394 R: Marijn Suijten <marijn.suijten@somainline.org> 7395 7395 L: linux-arm-msm@vger.kernel.org ··· 7401 7401 F: Documentation/devicetree/bindings/display/msm/ 7402 7402 F: drivers/gpu/drm/ci/xfails/msm* 7403 7403 F: drivers/gpu/drm/msm/ 7404 + F: include/dt-bindings/clock/qcom,dsi-phy-28nm.h 7404 7405 F: include/uapi/drm/msm_drm.h 7405 7406 7406 7407 DRM DRIVER FOR NOVATEK NT35510 PANELS
+2
drivers/gpu/drm/msm/Kconfig
··· 170 170 bool "Enable HDMI support in MSM DRM driver" 171 171 depends on DRM_MSM 172 172 default y 173 + select DRM_DISPLAY_HDMI_HELPER 174 + select DRM_DISPLAY_HDMI_STATE_HELPER 173 175 help 174 176 Compile in support for the HDMI output MSM DRM driver. It can 175 177 be a primary or a secondary display on device. Note that this is used
+29
drivers/gpu/drm/msm/adreno/a6xx_catalog.c
··· 880 880 { 137, 1 }, 881 881 ), 882 882 }, { 883 + .chip_ids = ADRENO_CHIP_IDS(0x06020300), 884 + .family = ADRENO_6XX_GEN3, 885 + .fw = { 886 + [ADRENO_FW_SQE] = "a650_sqe.fw", 887 + [ADRENO_FW_GMU] = "a623_gmu.bin", 888 + }, 889 + .gmem = SZ_512K, 890 + .inactive_period = DRM_MSM_INACTIVE_PERIOD, 891 + .quirks = ADRENO_QUIRK_HAS_CACHED_COHERENT | 892 + ADRENO_QUIRK_HAS_HW_APRIV, 893 + .init = a6xx_gpu_init, 894 + .a6xx = &(const struct a6xx_info) { 895 + .hwcg = a690_hwcg, 896 + .protect = &a650_protect, 897 + .gmu_cgc_mode = 0x00020200, 898 + .prim_fifo_threshold = 0x00010000, 899 + .bcms = (const struct a6xx_bcm[]) { 900 + { .name = "SH0", .buswidth = 16 }, 901 + { .name = "MC0", .buswidth = 4 }, 902 + { 903 + .name = "ACV", 904 + .fixed = true, 905 + .perfmode = BIT(3), 906 + }, 907 + { /* sentinel */ }, 908 + }, 909 + }, 910 + .address_space_size = SZ_16G, 911 + }, { 883 912 .chip_ids = ADRENO_CHIP_IDS( 884 913 0x06030001, 885 914 0x06030002
+44 -38
drivers/gpu/drm/msm/adreno/a6xx_gmu.c
··· 1169 1169 struct a6xx_gpu *a6xx_gpu = container_of(gmu, struct a6xx_gpu, gmu); 1170 1170 struct adreno_gpu *adreno_gpu = &a6xx_gpu->base; 1171 1171 u32 val; 1172 + int ret; 1172 1173 1173 1174 /* 1174 - * The GMU may still be in slumber unless the GPU started so check and 1175 - * skip putting it back into slumber if so 1175 + * GMU firmware's internal power state gets messed up if we send "prepare_slumber" hfi when 1176 + * oob_gpu handshake wasn't done after the last wake up. So do a dummy handshake here when 1177 + * required 1176 1178 */ 1177 - val = gmu_read(gmu, REG_A6XX_GPU_GMU_CX_GMU_RPMH_POWER_STATE); 1179 + if (adreno_gpu->base.needs_hw_init) { 1180 + if (a6xx_gmu_set_oob(&a6xx_gpu->gmu, GMU_OOB_GPU_SET)) 1181 + goto force_off; 1178 1182 1179 - if (val != 0xf) { 1180 - int ret = a6xx_gmu_wait_for_idle(gmu); 1181 - 1182 - /* If the GMU isn't responding assume it is hung */ 1183 - if (ret) { 1184 - a6xx_gmu_force_off(gmu); 1185 - return; 1186 - } 1187 - 1188 - a6xx_bus_clear_pending_transactions(adreno_gpu, a6xx_gpu->hung); 1189 - 1190 - /* tell the GMU we want to slumber */ 1191 - ret = a6xx_gmu_notify_slumber(gmu); 1192 - if (ret) { 1193 - a6xx_gmu_force_off(gmu); 1194 - return; 1195 - } 1196 - 1197 - ret = gmu_poll_timeout(gmu, 1198 - REG_A6XX_GPU_GMU_AO_GPU_CX_BUSY_STATUS, val, 1199 - !(val & A6XX_GPU_GMU_AO_GPU_CX_BUSY_STATUS_GPUBUSYIGNAHB), 1200 - 100, 10000); 1201 - 1202 - /* 1203 - * Let the user know we failed to slumber but don't worry too 1204 - * much because we are powering down anyway 1205 - */ 1206 - 1207 - if (ret) 1208 - DRM_DEV_ERROR(gmu->dev, 1209 - "Unable to slumber GMU: status = 0%x/0%x\n", 1210 - gmu_read(gmu, 1211 - REG_A6XX_GPU_GMU_AO_GPU_CX_BUSY_STATUS), 1212 - gmu_read(gmu, 1213 - REG_A6XX_GPU_GMU_AO_GPU_CX_BUSY_STATUS2)); 1183 + a6xx_gmu_clear_oob(&a6xx_gpu->gmu, GMU_OOB_GPU_SET); 1214 1184 } 1185 + 1186 + ret = a6xx_gmu_wait_for_idle(gmu); 1187 + 1188 + /* If the GMU isn't responding assume it is hung */ 1189 + if (ret) 1190 + goto force_off; 1191 + 1192 + a6xx_bus_clear_pending_transactions(adreno_gpu, a6xx_gpu->hung); 1193 + 1194 + /* tell the GMU we want to slumber */ 1195 + ret = a6xx_gmu_notify_slumber(gmu); 1196 + if (ret) 1197 + goto force_off; 1198 + 1199 + ret = gmu_poll_timeout(gmu, 1200 + REG_A6XX_GPU_GMU_AO_GPU_CX_BUSY_STATUS, val, 1201 + !(val & A6XX_GPU_GMU_AO_GPU_CX_BUSY_STATUS_GPUBUSYIGNAHB), 1202 + 100, 10000); 1203 + 1204 + /* 1205 + * Let the user know we failed to slumber but don't worry too 1206 + * much because we are powering down anyway 1207 + */ 1208 + 1209 + if (ret) 1210 + DRM_DEV_ERROR(gmu->dev, 1211 + "Unable to slumber GMU: status = 0%x/0%x\n", 1212 + gmu_read(gmu, 1213 + REG_A6XX_GPU_GMU_AO_GPU_CX_BUSY_STATUS), 1214 + gmu_read(gmu, 1215 + REG_A6XX_GPU_GMU_AO_GPU_CX_BUSY_STATUS2)); 1215 1216 1216 1217 /* Turn off HFI */ 1217 1218 a6xx_hfi_stop(gmu); ··· 1222 1221 1223 1222 /* Tell RPMh to power off the GPU */ 1224 1223 a6xx_rpmh_stop(gmu); 1224 + 1225 + return; 1226 + 1227 + force_off: 1228 + a6xx_gmu_force_off(gmu); 1225 1229 } 1226 1230 1227 1231
+8
drivers/gpu/drm/msm/adreno/a6xx_gpu.c
··· 616 616 gpu->ubwc_config.uavflagprd_inv = 2; 617 617 } 618 618 619 + if (adreno_is_a623(gpu)) { 620 + gpu->ubwc_config.highest_bank_bit = 16; 621 + gpu->ubwc_config.amsbc = 1; 622 + gpu->ubwc_config.rgb565_predicator = 1; 623 + gpu->ubwc_config.uavflagprd_inv = 2; 624 + gpu->ubwc_config.macrotile_mode = 1; 625 + } 626 + 619 627 if (adreno_is_a640_family(gpu)) 620 628 gpu->ubwc_config.amsbc = 1; 621 629
+12 -3
drivers/gpu/drm/msm/adreno/a6xx_gpu_state.c
··· 1214 1214 struct a6xx_gpu *a6xx_gpu = to_a6xx_gpu(adreno_gpu); 1215 1215 1216 1216 a6xx_state->gmu_registers = state_kcalloc(a6xx_state, 1217 - 3, sizeof(*a6xx_state->gmu_registers)); 1217 + 4, sizeof(*a6xx_state->gmu_registers)); 1218 1218 1219 1219 if (!a6xx_state->gmu_registers) 1220 1220 return; 1221 1221 1222 - a6xx_state->nr_gmu_registers = 3; 1222 + a6xx_state->nr_gmu_registers = 4; 1223 1223 1224 1224 /* Get the CX GMU registers from AHB */ 1225 1225 _a6xx_get_gmu_registers(gpu, a6xx_state, &a6xx_gmu_reglist[0], 1226 1226 &a6xx_state->gmu_registers[0], false); 1227 1227 _a6xx_get_gmu_registers(gpu, a6xx_state, &a6xx_gmu_reglist[1], 1228 1228 &a6xx_state->gmu_registers[1], true); 1229 + 1230 + if (adreno_is_a621(adreno_gpu) || adreno_is_a623(adreno_gpu)) 1231 + _a6xx_get_gmu_registers(gpu, a6xx_state, &a621_gpucc_reg, 1232 + &a6xx_state->gmu_registers[2], false); 1233 + else 1234 + _a6xx_get_gmu_registers(gpu, a6xx_state, &a6xx_gpucc_reg, 1235 + &a6xx_state->gmu_registers[2], false); 1229 1236 1230 1237 if (!a6xx_gmu_gx_is_on(&a6xx_gpu->gmu)) 1231 1238 return; ··· 1241 1234 gpu_write(gpu, REG_A6XX_GMU_AO_AHB_FENCE_CTRL, 0); 1242 1235 1243 1236 _a6xx_get_gmu_registers(gpu, a6xx_state, &a6xx_gmu_reglist[2], 1244 - &a6xx_state->gmu_registers[2], false); 1237 + &a6xx_state->gmu_registers[3], false); 1245 1238 } 1246 1239 1247 1240 static struct msm_gpu_state_bo *a6xx_snapshot_gmu_bo( ··· 1514 1507 1515 1508 /* Restore the size in the hardware */ 1516 1509 gpu_write(gpu, REG_A6XX_CP_MEM_POOL_SIZE, mempool_size); 1510 + 1511 + a6xx_state->nr_indexed_regs = count; 1517 1512 } 1518 1513 1519 1514 static void a7xx_get_indexed_registers(struct msm_gpu *gpu,
+17
drivers/gpu/drm/msm/adreno/a6xx_gpu_state.h
··· 363 363 0x51e0, 0x51e2, 0x51f0, 0x51f0, 0x5200, 0x5201, 364 364 /* GMU AO */ 365 365 0x9300, 0x9316, 0x9400, 0x9400, 366 + }; 367 + 368 + static const u32 a6xx_gmu_gpucc_registers[] = { 366 369 /* GPU CC */ 367 370 0x9800, 0x9812, 0x9840, 0x9852, 0x9c00, 0x9c04, 0x9c07, 0x9c0b, 368 371 0x9c15, 0x9c1c, 0x9c1e, 0x9c2d, 0x9c3c, 0x9c3d, 0x9c3f, 0x9c40, ··· 374 371 0xb800, 0xb802, 375 372 /* GPU CC ACD */ 376 373 0xbc00, 0xbc16, 0xbc20, 0xbc27, 374 + }; 375 + 376 + static const u32 a621_gmu_gpucc_registers[] = { 377 + /* GPU CC */ 378 + 0x9800, 0x980e, 0x9c00, 0x9c0e, 0xb000, 0xb004, 0xb400, 0xb404, 379 + 0xb800, 0xb804, 0xbc00, 0xbc05, 0xbc14, 0xbc1d, 0xbc2a, 0xbc30, 380 + 0xbc32, 0xbc32, 0xbc41, 0xbc55, 0xbc66, 0xbc68, 0xbc78, 0xbc7a, 381 + 0xbc89, 0xbc8a, 0xbc9c, 0xbc9e, 0xbca0, 0xbca3, 0xbcb3, 0xbcb5, 382 + 0xbcc5, 0xbcc7, 0xbcd6, 0xbcd8, 0xbce8, 0xbce9, 0xbcf9, 0xbcfc, 383 + 0xbd0b, 0xbd0c, 0xbd1c, 0xbd1e, 0xbd40, 0xbd70, 0xbe00, 0xbe16, 384 + 0xbe20, 0xbe2d, 377 385 }; 378 386 379 387 static const u32 a6xx_gmu_cx_rscc_registers[] = { ··· 399 385 REGS(a6xx_gmu_cx_rscc_registers, 0, 0), 400 386 REGS(a6xx_gmu_gx_registers, 0, 0), 401 387 }; 388 + 389 + static const struct a6xx_registers a6xx_gpucc_reg = REGS(a6xx_gmu_gpucc_registers, 0, 0); 390 + static const struct a6xx_registers a621_gpucc_reg = REGS(a621_gmu_gpucc_registers, 0, 0); 402 391 403 392 static u32 a6xx_get_cp_roq_size(struct msm_gpu *gpu); 404 393 static u32 a7xx_get_cp_roq_size(struct msm_gpu *gpu);
+10
drivers/gpu/drm/msm/adreno/adreno_gpu.c
··· 883 883 drm_printf(p, " - dir=%s\n", info->flags & IOMMU_FAULT_WRITE ? "WRITE" : "READ"); 884 884 drm_printf(p, " - type=%s\n", info->type); 885 885 drm_printf(p, " - source=%s\n", info->block); 886 + 887 + /* Information extracted from what we think are the current 888 + * pgtables. Hopefully the TTBR0 matches what we've extracted 889 + * from the SMMU registers in smmu_info! 890 + */ 891 + drm_puts(p, "pgtable-fault-info:\n"); 892 + drm_printf(p, " - ttbr0: %.16llx\n", (u64)info->pgtbl_ttbr0); 893 + drm_printf(p, " - asid: %d\n", info->asid); 894 + drm_printf(p, " - ptes: %.16llx %.16llx %.16llx %.16llx\n", 895 + info->ptes[0], info->ptes[1], info->ptes[2], info->ptes[3]); 886 896 } 887 897 888 898 drm_printf(p, "rbbm-status: 0x%08x\n", state->rbbm_status);
+5
drivers/gpu/drm/msm/adreno/adreno_gpu.h
··· 442 442 return gpu->info->chip_ids[0] == 0x06020100; 443 443 } 444 444 445 + static inline int adreno_is_a623(const struct adreno_gpu *gpu) 446 + { 447 + return gpu->info->chip_ids[0] == 0x06020300; 448 + } 449 + 445 450 static inline int adreno_is_a630(const struct adreno_gpu *gpu) 446 451 { 447 452 return adreno_is_revn(gpu, 630);
+3 -2
drivers/gpu/drm/msm/disp/dpu1/catalog/dpu_10_0_sm8650.h
··· 343 343 .name = "wb_2", .id = WB_2, 344 344 .base = 0x65000, .len = 0x2c8, 345 345 .features = WB_SM8250_MASK, 346 - .format_list = wb2_formats_rgb, 347 - .num_formats = ARRAY_SIZE(wb2_formats_rgb), 346 + .format_list = wb2_formats_rgb_yuv, 347 + .num_formats = ARRAY_SIZE(wb2_formats_rgb_yuv), 348 348 .xin_id = 6, 349 349 .vbif_idx = VBIF_RT, 350 350 .maxlinewidth = 4096, ··· 452 452 .mdss_ver = &sm8650_mdss_ver, 453 453 .caps = &sm8650_dpu_caps, 454 454 .mdp = &sm8650_mdp, 455 + .cdm = &dpu_cdm_5_x, 455 456 .ctl_count = ARRAY_SIZE(sm8650_ctl), 456 457 .ctl = sm8650_ctl, 457 458 .sspp_count = ARRAY_SIZE(sm8650_sspp),
+1
drivers/gpu/drm/msm/disp/dpu1/catalog/dpu_1_14_msm8937.h
··· 190 190 .mdss_ver = &msm8937_mdss_ver, 191 191 .caps = &msm8937_dpu_caps, 192 192 .mdp = msm8937_mdp, 193 + .cdm = &dpu_cdm_1_x_4_x, 193 194 .ctl_count = ARRAY_SIZE(msm8937_ctl), 194 195 .ctl = msm8937_ctl, 195 196 .sspp_count = ARRAY_SIZE(msm8937_sspp),
+1
drivers/gpu/drm/msm/disp/dpu1/catalog/dpu_1_15_msm8917.h
··· 167 167 .mdss_ver = &msm8917_mdss_ver, 168 168 .caps = &msm8917_dpu_caps, 169 169 .mdp = msm8917_mdp, 170 + .cdm = &dpu_cdm_1_x_4_x, 170 171 .ctl_count = ARRAY_SIZE(msm8917_ctl), 171 172 .ctl = msm8917_ctl, 172 173 .sspp_count = ARRAY_SIZE(msm8917_sspp),
+1
drivers/gpu/drm/msm/disp/dpu1/catalog/dpu_1_16_msm8953.h
··· 198 198 .mdss_ver = &msm8953_mdss_ver, 199 199 .caps = &msm8953_dpu_caps, 200 200 .mdp = msm8953_mdp, 201 + .cdm = &dpu_cdm_1_x_4_x, 201 202 .ctl_count = ARRAY_SIZE(msm8953_ctl), 202 203 .ctl = msm8953_ctl, 203 204 .sspp_count = ARRAY_SIZE(msm8953_sspp),
+1
drivers/gpu/drm/msm/disp/dpu1/catalog/dpu_1_7_msm8996.h
··· 316 316 .mdss_ver = &msm8996_mdss_ver, 317 317 .caps = &msm8996_dpu_caps, 318 318 .mdp = msm8996_mdp, 319 + .cdm = &dpu_cdm_1_x_4_x, 319 320 .ctl_count = ARRAY_SIZE(msm8996_ctl), 320 321 .ctl = msm8996_ctl, 321 322 .sspp_count = ARRAY_SIZE(msm8996_sspp),
+1
drivers/gpu/drm/msm/disp/dpu1/catalog/dpu_3_0_msm8998.h
··· 302 302 .mdss_ver = &msm8998_mdss_ver, 303 303 .caps = &msm8998_dpu_caps, 304 304 .mdp = &msm8998_mdp, 305 + .cdm = &dpu_cdm_1_x_4_x, 305 306 .ctl_count = ARRAY_SIZE(msm8998_ctl), 306 307 .ctl = msm8998_ctl, 307 308 .sspp_count = ARRAY_SIZE(msm8998_sspp),
+1
drivers/gpu/drm/msm/disp/dpu1/catalog/dpu_3_2_sdm660.h
··· 269 269 .mdss_ver = &sdm660_mdss_ver, 270 270 .caps = &sdm660_dpu_caps, 271 271 .mdp = &sdm660_mdp, 272 + .cdm = &dpu_cdm_1_x_4_x, 272 273 .ctl_count = ARRAY_SIZE(sdm660_ctl), 273 274 .ctl = sdm660_ctl, 274 275 .sspp_count = ARRAY_SIZE(sdm660_sspp),
+1
drivers/gpu/drm/msm/disp/dpu1/catalog/dpu_3_3_sdm630.h
··· 205 205 .mdss_ver = &sdm630_mdss_ver, 206 206 .caps = &sdm630_dpu_caps, 207 207 .mdp = &sdm630_mdp, 208 + .cdm = &dpu_cdm_1_x_4_x, 208 209 .ctl_count = ARRAY_SIZE(sdm630_ctl), 209 210 .ctl = sdm630_ctl, 210 211 .sspp_count = ARRAY_SIZE(sdm630_sspp),
+1
drivers/gpu/drm/msm/disp/dpu1/catalog/dpu_4_0_sdm845.h
··· 319 319 .mdss_ver = &sdm845_mdss_ver, 320 320 .caps = &sdm845_dpu_caps, 321 321 .mdp = &sdm845_mdp, 322 + .cdm = &dpu_cdm_1_x_4_x, 322 323 .ctl_count = ARRAY_SIZE(sdm845_ctl), 323 324 .ctl = sdm845_ctl, 324 325 .sspp_count = ARRAY_SIZE(sdm845_sspp),
+1
drivers/gpu/drm/msm/disp/dpu1/catalog/dpu_4_1_sdm670.h
··· 132 132 .mdss_ver = &sdm670_mdss_ver, 133 133 .caps = &sdm845_dpu_caps, 134 134 .mdp = &sdm670_mdp, 135 + .cdm = &dpu_cdm_1_x_4_x, 135 136 .ctl_count = ARRAY_SIZE(sdm845_ctl), 136 137 .ctl = sdm845_ctl, 137 138 .sspp_count = ARRAY_SIZE(sdm670_sspp),
+3 -2
drivers/gpu/drm/msm/disp/dpu1/catalog/dpu_5_0_sm8150.h
··· 298 298 .name = "wb_2", .id = WB_2, 299 299 .base = 0x65000, .len = 0x2c8, 300 300 .features = WB_SM8250_MASK, 301 - .format_list = wb2_formats_rgb, 302 - .num_formats = ARRAY_SIZE(wb2_formats_rgb), 301 + .format_list = wb2_formats_rgb_yuv, 302 + .num_formats = ARRAY_SIZE(wb2_formats_rgb_yuv), 303 303 .clk_ctrl = DPU_CLK_CTRL_WB2, 304 304 .xin_id = 6, 305 305 .vbif_idx = VBIF_RT, ··· 388 388 .mdss_ver = &sm8150_mdss_ver, 389 389 .caps = &sm8150_dpu_caps, 390 390 .mdp = &sm8150_mdp, 391 + .cdm = &dpu_cdm_5_x, 391 392 .ctl_count = ARRAY_SIZE(sm8150_ctl), 392 393 .ctl = sm8150_ctl, 393 394 .sspp_count = ARRAY_SIZE(sm8150_sspp),
+3 -2
drivers/gpu/drm/msm/disp/dpu1/catalog/dpu_5_1_sc8180x.h
··· 305 305 .name = "wb_2", .id = WB_2, 306 306 .base = 0x65000, .len = 0x2c8, 307 307 .features = WB_SM8250_MASK, 308 - .format_list = wb2_formats_rgb, 309 - .num_formats = ARRAY_SIZE(wb2_formats_rgb), 308 + .format_list = wb2_formats_rgb_yuv, 309 + .num_formats = ARRAY_SIZE(wb2_formats_rgb_yuv), 310 310 .clk_ctrl = DPU_CLK_CTRL_WB2, 311 311 .xin_id = 6, 312 312 .vbif_idx = VBIF_RT, ··· 414 414 .mdss_ver = &sc8180x_mdss_ver, 415 415 .caps = &sc8180x_dpu_caps, 416 416 .mdp = &sc8180x_mdp, 417 + .cdm = &dpu_cdm_5_x, 417 418 .ctl_count = ARRAY_SIZE(sc8180x_ctl), 418 419 .ctl = sc8180x_ctl, 419 420 .sspp_count = ARRAY_SIZE(sc8180x_sspp),
+3 -2
drivers/gpu/drm/msm/disp/dpu1/catalog/dpu_5_2_sm7150.h
··· 261 261 .name = "wb_2", .id = WB_2, 262 262 .base = 0x65000, .len = 0x2c8, 263 263 .features = WB_SM8250_MASK, 264 - .format_list = wb2_formats_rgb, 265 - .num_formats = ARRAY_SIZE(wb2_formats_rgb), 264 + .format_list = wb2_formats_rgb_yuv, 265 + .num_formats = ARRAY_SIZE(wb2_formats_rgb_yuv), 266 266 .clk_ctrl = DPU_CLK_CTRL_WB2, 267 267 .xin_id = 6, 268 268 .vbif_idx = VBIF_RT, ··· 309 309 .mdss_ver = &sm7150_mdss_ver, 310 310 .caps = &sm7150_dpu_caps, 311 311 .mdp = &sm7150_mdp, 312 + .cdm = &dpu_cdm_5_x, 312 313 .ctl_count = ARRAY_SIZE(sm7150_ctl), 313 314 .ctl = sm7150_ctl, 314 315 .sspp_count = ARRAY_SIZE(sm7150_sspp),
+19
drivers/gpu/drm/msm/disp/dpu1/catalog/dpu_5_3_sm6150.h
··· 27 27 [DPU_CLK_CTRL_DMA1] = { .reg_off = 0x2b4, .bit_off = 8 }, 28 28 [DPU_CLK_CTRL_DMA2] = { .reg_off = 0x2bc, .bit_off = 8 }, 29 29 [DPU_CLK_CTRL_DMA3] = { .reg_off = 0x2c4, .bit_off = 8 }, 30 + [DPU_CLK_CTRL_WB2] = { .reg_off = 0x2bc, .bit_off = 16 }, 30 31 }, 31 32 }; 32 33 ··· 163 162 }, 164 163 }; 165 164 165 + static const struct dpu_wb_cfg sm6150_wb[] = { 166 + { 167 + .name = "wb_2", .id = WB_2, 168 + .base = 0x65000, .len = 0x2c8, 169 + .features = WB_SM8250_MASK, 170 + .format_list = wb2_formats_rgb_yuv, 171 + .num_formats = ARRAY_SIZE(wb2_formats_rgb_yuv), 172 + .clk_ctrl = DPU_CLK_CTRL_WB2, 173 + .xin_id = 6, 174 + .vbif_idx = VBIF_RT, 175 + .maxlinewidth = 2160, 176 + .intr_wb_done = DPU_IRQ_IDX(MDP_SSPP_TOP0_INTR, 4), 177 + }, 178 + }; 179 + 166 180 static const struct dpu_intf_cfg sm6150_intf[] = { 167 181 { 168 182 .name = "intf_0", .id = INTF_0, ··· 248 232 .mdss_ver = &sm6150_mdss_ver, 249 233 .caps = &sm6150_dpu_caps, 250 234 .mdp = &sm6150_mdp, 235 + .cdm = &dpu_cdm_5_x, 251 236 .ctl_count = ARRAY_SIZE(sm6150_ctl), 252 237 .ctl = sm6150_ctl, 253 238 .sspp_count = ARRAY_SIZE(sm6150_sspp), ··· 259 242 .dspp = sm6150_dspp, 260 243 .pingpong_count = ARRAY_SIZE(sm6150_pp), 261 244 .pingpong = sm6150_pp, 245 + .wb_count = ARRAY_SIZE(sm6150_wb), 246 + .wb = sm6150_wb, 262 247 .intf_count = ARRAY_SIZE(sm6150_intf), 263 248 .intf = sm6150_intf, 264 249 .vbif_count = ARRAY_SIZE(sdm845_vbif),
+3 -2
drivers/gpu/drm/msm/disp/dpu1/catalog/dpu_5_4_sm6125.h
··· 145 145 .name = "wb_2", .id = WB_2, 146 146 .base = 0x65000, .len = 0x2c8, 147 147 .features = WB_SM8250_MASK, 148 - .format_list = wb2_formats_rgb, 149 - .num_formats = ARRAY_SIZE(wb2_formats_rgb), 148 + .format_list = wb2_formats_rgb_yuv, 149 + .num_formats = ARRAY_SIZE(wb2_formats_rgb_yuv), 150 150 .clk_ctrl = DPU_CLK_CTRL_WB2, 151 151 .xin_id = 6, 152 152 .vbif_idx = VBIF_RT, ··· 216 216 .mdss_ver = &sm6125_mdss_ver, 217 217 .caps = &sm6125_dpu_caps, 218 218 .mdp = &sm6125_mdp, 219 + .cdm = &dpu_cdm_5_x, 219 220 .ctl_count = ARRAY_SIZE(sm6125_ctl), 220 221 .ctl = sm6125_ctl, 221 222 .sspp_count = ARRAY_SIZE(sm6125_sspp),
+1 -1
drivers/gpu/drm/msm/disp/dpu1/catalog/dpu_6_0_sm8250.h
··· 386 386 .mdss_ver = &sm8250_mdss_ver, 387 387 .caps = &sm8250_dpu_caps, 388 388 .mdp = &sm8250_mdp, 389 - .cdm = &sc7280_cdm, 389 + .cdm = &dpu_cdm_5_x, 390 390 .ctl_count = ARRAY_SIZE(sm8250_ctl), 391 391 .ctl = sm8250_ctl, 392 392 .sspp_count = ARRAY_SIZE(sm8250_sspp),
+3 -2
drivers/gpu/drm/msm/disp/dpu1/catalog/dpu_6_2_sc7180.h
··· 157 157 .name = "wb_2", .id = WB_2, 158 158 .base = 0x65000, .len = 0x2c8, 159 159 .features = WB_SM8250_MASK, 160 - .format_list = wb2_formats_rgb, 161 - .num_formats = ARRAY_SIZE(wb2_formats_rgb), 160 + .format_list = wb2_formats_rgb_yuv, 161 + .num_formats = ARRAY_SIZE(wb2_formats_rgb_yuv), 162 162 .clk_ctrl = DPU_CLK_CTRL_WB2, 163 163 .xin_id = 6, 164 164 .vbif_idx = VBIF_RT, ··· 204 204 .mdss_ver = &sc7180_mdss_ver, 205 205 .caps = &sc7180_dpu_caps, 206 206 .mdp = &sc7180_mdp, 207 + .cdm = &dpu_cdm_5_x, 207 208 .ctl_count = ARRAY_SIZE(sc7180_ctl), 208 209 .ctl = sc7180_ctl, 209 210 .sspp_count = ARRAY_SIZE(sc7180_sspp),
+3 -2
drivers/gpu/drm/msm/disp/dpu1/catalog/dpu_6_4_sm6350.h
··· 151 151 .name = "wb_2", .id = WB_2, 152 152 .base = 0x65000, .len = 0x2c8, 153 153 .features = WB_SM8250_MASK, 154 - .format_list = wb2_formats_rgb, 155 - .num_formats = ARRAY_SIZE(wb2_formats_rgb), 154 + .format_list = wb2_formats_rgb_yuv, 155 + .num_formats = ARRAY_SIZE(wb2_formats_rgb_yuv), 156 156 .clk_ctrl = DPU_CLK_CTRL_WB2, 157 157 .xin_id = 6, 158 158 .vbif_idx = VBIF_RT, ··· 222 222 .mdss_ver = &sm6350_mdss_ver, 223 223 .caps = &sm6350_dpu_caps, 224 224 .mdp = &sm6350_mdp, 225 + .cdm = &dpu_cdm_5_x, 225 226 .ctl_count = ARRAY_SIZE(sm6350_ctl), 226 227 .ctl = sm6350_ctl, 227 228 .sspp_count = ARRAY_SIZE(sm6350_sspp),
+3 -2
drivers/gpu/drm/msm/disp/dpu1/catalog/dpu_7_0_sm8350.h
··· 305 305 .name = "wb_2", .id = WB_2, 306 306 .base = 0x65000, .len = 0x2c8, 307 307 .features = WB_SM8250_MASK, 308 - .format_list = wb2_formats_rgb, 309 - .num_formats = ARRAY_SIZE(wb2_formats_rgb), 308 + .format_list = wb2_formats_rgb_yuv, 309 + .num_formats = ARRAY_SIZE(wb2_formats_rgb_yuv), 310 310 .clk_ctrl = DPU_CLK_CTRL_WB2, 311 311 .xin_id = 6, 312 312 .vbif_idx = VBIF_RT, ··· 396 396 .mdss_ver = &sm8350_mdss_ver, 397 397 .caps = &sm8350_dpu_caps, 398 398 .mdp = &sm8350_mdp, 399 + .cdm = &dpu_cdm_5_x, 399 400 .ctl_count = ARRAY_SIZE(sm8350_ctl), 400 401 .ctl = sm8350_ctl, 401 402 .sspp_count = ARRAY_SIZE(sm8350_sspp),
+1 -1
drivers/gpu/drm/msm/disp/dpu1/catalog/dpu_7_2_sc7280.h
··· 248 248 .mdss_ver = &sc7280_mdss_ver, 249 249 .caps = &sc7280_dpu_caps, 250 250 .mdp = &sc7280_mdp, 251 - .cdm = &sc7280_cdm, 251 + .cdm = &dpu_cdm_5_x, 252 252 .ctl_count = ARRAY_SIZE(sc7280_ctl), 253 253 .ctl = sc7280_ctl, 254 254 .sspp_count = ARRAY_SIZE(sc7280_sspp),
+1
drivers/gpu/drm/msm/disp/dpu1/catalog/dpu_8_0_sc8280xp.h
··· 435 435 .mdss_ver = &sc8280xp_mdss_ver, 436 436 .caps = &sc8280xp_dpu_caps, 437 437 .mdp = &sc8280xp_mdp, 438 + .cdm = &dpu_cdm_5_x, 438 439 .ctl_count = ARRAY_SIZE(sc8280xp_ctl), 439 440 .ctl = sc8280xp_ctl, 440 441 .sspp_count = ARRAY_SIZE(sc8280xp_sspp),
+3 -2
drivers/gpu/drm/msm/disp/dpu1/catalog/dpu_8_1_sm8450.h
··· 321 321 .name = "wb_2", .id = WB_2, 322 322 .base = 0x65000, .len = 0x2c8, 323 323 .features = WB_SM8250_MASK, 324 - .format_list = wb2_formats_rgb, 325 - .num_formats = ARRAY_SIZE(wb2_formats_rgb), 324 + .format_list = wb2_formats_rgb_yuv, 325 + .num_formats = ARRAY_SIZE(wb2_formats_rgb_yuv), 326 326 .clk_ctrl = DPU_CLK_CTRL_WB2, 327 327 .xin_id = 6, 328 328 .vbif_idx = VBIF_RT, ··· 412 412 .mdss_ver = &sm8450_mdss_ver, 413 413 .caps = &sm8450_dpu_caps, 414 414 .mdp = &sm8450_mdp, 415 + .cdm = &dpu_cdm_5_x, 415 416 .ctl_count = ARRAY_SIZE(sm8450_ctl), 416 417 .ctl = sm8450_ctl, 417 418 .sspp_count = ARRAY_SIZE(sm8450_sspp),
+1 -1
drivers/gpu/drm/msm/disp/dpu1/catalog/dpu_8_4_sa8775p.h
··· 458 458 .mdss_ver = &sa8775p_mdss_ver, 459 459 .caps = &sa8775p_dpu_caps, 460 460 .mdp = &sa8775p_mdp, 461 - .cdm = &sc7280_cdm, 461 + .cdm = &dpu_cdm_5_x, 462 462 .ctl_count = ARRAY_SIZE(sa8775p_ctl), 463 463 .ctl = sa8775p_ctl, 464 464 .sspp_count = ARRAY_SIZE(sa8775p_sspp),
+3 -2
drivers/gpu/drm/msm/disp/dpu1/catalog/dpu_9_0_sm8550.h
··· 317 317 .name = "wb_2", .id = WB_2, 318 318 .base = 0x65000, .len = 0x2c8, 319 319 .features = WB_SM8250_MASK, 320 - .format_list = wb2_formats_rgb, 321 - .num_formats = ARRAY_SIZE(wb2_formats_rgb), 320 + .format_list = wb2_formats_rgb_yuv, 321 + .num_formats = ARRAY_SIZE(wb2_formats_rgb_yuv), 322 322 .xin_id = 6, 323 323 .vbif_idx = VBIF_RT, 324 324 .maxlinewidth = 4096, ··· 407 407 .mdss_ver = &sm8550_mdss_ver, 408 408 .caps = &sm8550_dpu_caps, 409 409 .mdp = &sm8550_mdp, 410 + .cdm = &dpu_cdm_5_x, 410 411 .ctl_count = ARRAY_SIZE(sm8550_ctl), 411 412 .ctl = sm8550_ctl, 412 413 .sspp_count = ARRAY_SIZE(sm8550_sspp),
+3 -2
drivers/gpu/drm/msm/disp/dpu1/catalog/dpu_9_2_x1e80100.h
··· 317 317 .name = "wb_2", .id = WB_2, 318 318 .base = 0x65000, .len = 0x2c8, 319 319 .features = WB_SM8250_MASK, 320 - .format_list = wb2_formats_rgb, 321 - .num_formats = ARRAY_SIZE(wb2_formats_rgb), 320 + .format_list = wb2_formats_rgb_yuv, 321 + .num_formats = ARRAY_SIZE(wb2_formats_rgb_yuv), 322 322 .xin_id = 6, 323 323 .vbif_idx = VBIF_RT, 324 324 .maxlinewidth = 4096, ··· 453 453 .mdss_ver = &x1e80100_mdss_ver, 454 454 .caps = &x1e80100_dpu_caps, 455 455 .mdp = &x1e80100_mdp, 456 + .cdm = &dpu_cdm_5_x, 456 457 .ctl_count = ARRAY_SIZE(x1e80100_ctl), 457 458 .ctl = x1e80100_ctl, 458 459 .sspp_count = ARRAY_SIZE(x1e80100_sspp),
+63 -77
drivers/gpu/drm/msm/disp/dpu1/dpu_core_perf.c
··· 118 118 return; 119 119 } 120 120 121 - memset(perf, 0, sizeof(struct dpu_core_perf_params)); 122 - 123 - if (core_perf->perf_tune.mode == DPU_PERF_MODE_MINIMUM) { 124 - perf->bw_ctl = 0; 125 - perf->max_per_pipe_ib = 0; 126 - perf->core_clk_rate = 0; 127 - } else if (core_perf->perf_tune.mode == DPU_PERF_MODE_FIXED) { 128 - perf->bw_ctl = core_perf->fix_core_ab_vote; 129 - perf->max_per_pipe_ib = core_perf->fix_core_ib_vote; 130 - perf->core_clk_rate = core_perf->fix_core_clk_rate; 131 - } else { 132 - perf->bw_ctl = _dpu_core_perf_calc_bw(perf_cfg, crtc); 133 - perf->max_per_pipe_ib = perf_cfg->min_dram_ib; 134 - perf->core_clk_rate = _dpu_core_perf_calc_clk(perf_cfg, crtc, state); 135 - } 136 - 121 + perf->bw_ctl = _dpu_core_perf_calc_bw(perf_cfg, crtc); 122 + perf->max_per_pipe_ib = perf_cfg->min_dram_ib; 123 + perf->core_clk_rate = _dpu_core_perf_calc_clk(perf_cfg, crtc, state); 137 124 DRM_DEBUG_ATOMIC( 138 - "crtc=%d clk_rate=%llu core_ib=%llu core_ab=%llu\n", 125 + "crtc=%d clk_rate=%llu core_ib=%u core_ab=%u\n", 139 126 crtc->base.id, perf->core_clk_rate, 140 - perf->max_per_pipe_ib, perf->bw_ctl); 127 + perf->max_per_pipe_ib, 128 + (u32)DIV_ROUND_UP_ULL(perf->bw_ctl, 1000)); 129 + } 130 + 131 + static void dpu_core_perf_aggregate(struct drm_device *ddev, 132 + enum dpu_crtc_client_type curr_client_type, 133 + struct dpu_core_perf_params *perf) 134 + { 135 + struct dpu_crtc_state *dpu_cstate; 136 + struct drm_crtc *tmp_crtc; 137 + 138 + drm_for_each_crtc(tmp_crtc, ddev) { 139 + if (tmp_crtc->enabled && 140 + curr_client_type == dpu_crtc_get_client_type(tmp_crtc)) { 141 + dpu_cstate = to_dpu_crtc_state(tmp_crtc->state); 142 + 143 + perf->max_per_pipe_ib = max(perf->max_per_pipe_ib, 144 + dpu_cstate->new_perf.max_per_pipe_ib); 145 + 146 + perf->bw_ctl += dpu_cstate->new_perf.bw_ctl; 147 + 148 + DRM_DEBUG_ATOMIC("crtc=%d bw=%llu\n", 149 + tmp_crtc->base.id, 150 + dpu_cstate->new_perf.bw_ctl); 151 + } 152 + } 141 153 } 142 154 143 155 /** ··· 162 150 struct drm_crtc_state *state) 163 151 { 164 152 u32 bw, threshold; 165 - u64 bw_sum_of_intfs = 0; 166 - enum dpu_crtc_client_type curr_client_type; 167 153 struct dpu_crtc_state *dpu_cstate; 168 - struct drm_crtc *tmp_crtc; 169 154 struct dpu_kms *kms; 155 + struct dpu_core_perf_params perf = { 0 }; 170 156 171 157 if (!crtc || !state) { 172 158 DPU_ERROR("invalid crtc\n"); ··· 182 172 /* obtain new values */ 183 173 _dpu_core_perf_calc_crtc(&kms->perf, crtc, state, &dpu_cstate->new_perf); 184 174 185 - bw_sum_of_intfs = dpu_cstate->new_perf.bw_ctl; 186 - curr_client_type = dpu_crtc_get_client_type(crtc); 175 + dpu_core_perf_aggregate(crtc->dev, dpu_crtc_get_client_type(crtc), &perf); 187 176 188 - drm_for_each_crtc(tmp_crtc, crtc->dev) { 189 - if (tmp_crtc->enabled && 190 - dpu_crtc_get_client_type(tmp_crtc) == curr_client_type && 191 - tmp_crtc != crtc) { 192 - struct dpu_crtc_state *tmp_cstate = 193 - to_dpu_crtc_state(tmp_crtc->state); 177 + /* convert bandwidth to kb */ 178 + bw = DIV_ROUND_UP_ULL(perf.bw_ctl, 1000); 179 + DRM_DEBUG_ATOMIC("calculated bandwidth=%uk\n", bw); 194 180 195 - DRM_DEBUG_ATOMIC("crtc:%d bw:%llu ctrl:%d\n", 196 - tmp_crtc->base.id, tmp_cstate->new_perf.bw_ctl, 197 - tmp_cstate->bw_control); 181 + threshold = kms->perf.perf_cfg->max_bw_high; 198 182 199 - bw_sum_of_intfs += tmp_cstate->new_perf.bw_ctl; 200 - } 183 + DRM_DEBUG_ATOMIC("final threshold bw limit = %d\n", threshold); 201 184 202 - /* convert bandwidth to kb */ 203 - bw = DIV_ROUND_UP_ULL(bw_sum_of_intfs, 1000); 204 - DRM_DEBUG_ATOMIC("calculated bandwidth=%uk\n", bw); 205 - 206 - threshold = kms->perf.perf_cfg->max_bw_high; 207 - 208 - DRM_DEBUG_ATOMIC("final threshold bw limit = %d\n", threshold); 209 - 210 - if (!threshold) { 211 - DPU_ERROR("no bandwidth limits specified\n"); 212 - return -E2BIG; 213 - } else if (bw > threshold) { 214 - DPU_ERROR("exceeds bandwidth: %ukb > %ukb\n", bw, 215 - threshold); 216 - return -E2BIG; 217 - } 185 + if (!threshold) { 186 + DPU_ERROR("no bandwidth limits specified\n"); 187 + return -E2BIG; 188 + } else if (bw > threshold) { 189 + DPU_ERROR("exceeds bandwidth: %ukb > %ukb\n", bw, 190 + threshold); 191 + return -E2BIG; 218 192 } 219 193 220 194 return 0; 221 195 } 222 196 223 197 static int _dpu_core_perf_crtc_update_bus(struct dpu_kms *kms, 224 - struct drm_crtc *crtc) 198 + struct drm_crtc *crtc) 225 199 { 226 200 struct dpu_core_perf_params perf = { 0 }; 227 - enum dpu_crtc_client_type curr_client_type 228 - = dpu_crtc_get_client_type(crtc); 229 - struct drm_crtc *tmp_crtc; 230 - struct dpu_crtc_state *dpu_cstate; 231 201 int i, ret = 0; 232 - u64 avg_bw; 202 + u32 avg_bw; 203 + u32 peak_bw; 233 204 234 205 if (!kms->num_paths) 235 206 return 0; 236 207 237 - drm_for_each_crtc(tmp_crtc, crtc->dev) { 238 - if (tmp_crtc->enabled && 239 - curr_client_type == 240 - dpu_crtc_get_client_type(tmp_crtc)) { 241 - dpu_cstate = to_dpu_crtc_state(tmp_crtc->state); 208 + if (kms->perf.perf_tune.mode == DPU_PERF_MODE_MINIMUM) { 209 + avg_bw = 0; 210 + peak_bw = 0; 211 + } else if (kms->perf.perf_tune.mode == DPU_PERF_MODE_FIXED) { 212 + avg_bw = kms->perf.fix_core_ab_vote; 213 + peak_bw = kms->perf.fix_core_ib_vote; 214 + } else { 215 + dpu_core_perf_aggregate(crtc->dev, dpu_crtc_get_client_type(crtc), &perf); 242 216 243 - perf.max_per_pipe_ib = max(perf.max_per_pipe_ib, 244 - dpu_cstate->new_perf.max_per_pipe_ib); 245 - 246 - perf.bw_ctl += dpu_cstate->new_perf.bw_ctl; 247 - 248 - DRM_DEBUG_ATOMIC("crtc=%d bw=%llu paths:%d\n", 249 - tmp_crtc->base.id, 250 - dpu_cstate->new_perf.bw_ctl, kms->num_paths); 251 - } 217 + avg_bw = div_u64(perf.bw_ctl, 1000); /*Bps_to_icc*/ 218 + peak_bw = perf.max_per_pipe_ib; 252 219 } 253 220 254 - avg_bw = perf.bw_ctl; 255 - do_div(avg_bw, (kms->num_paths * 1000)); /*Bps_to_icc*/ 221 + avg_bw /= kms->num_paths; 256 222 257 223 for (i = 0; i < kms->num_paths; i++) 258 - icc_set_bw(kms->path[i], avg_bw, perf.max_per_pipe_ib); 224 + icc_set_bw(kms->path[i], avg_bw, peak_bw); 259 225 260 226 return ret; 261 227 } ··· 462 476 &perf->core_clk_rate); 463 477 debugfs_create_u32("enable_bw_release", 0600, entry, 464 478 (u32 *)&perf->enable_bw_release); 465 - debugfs_create_u32("threshold_low", 0400, entry, 479 + debugfs_create_u32("low_core_ab", 0400, entry, 466 480 (u32 *)&perf->perf_cfg->max_bw_low); 467 - debugfs_create_u32("threshold_high", 0400, entry, 481 + debugfs_create_u32("max_core_ab", 0400, entry, 468 482 (u32 *)&perf->perf_cfg->max_bw_high); 469 483 debugfs_create_u32("min_core_ib", 0400, entry, 470 484 (u32 *)&perf->perf_cfg->min_core_ib); ··· 476 490 (u32 *)perf, &dpu_core_perf_mode_fops); 477 491 debugfs_create_u64("fix_core_clk_rate", 0600, entry, 478 492 &perf->fix_core_clk_rate); 479 - debugfs_create_u64("fix_core_ib_vote", 0600, entry, 493 + debugfs_create_u32("fix_core_ib_vote", 0600, entry, 480 494 &perf->fix_core_ib_vote); 481 - debugfs_create_u64("fix_core_ab_vote", 0600, entry, 495 + debugfs_create_u32("fix_core_ab_vote", 0600, entry, 482 496 &perf->fix_core_ab_vote); 483 497 484 498 return 0;
+5 -5
drivers/gpu/drm/msm/disp/dpu1/dpu_core_perf.h
··· 19 19 * @core_clk_rate: core clock rate request 20 20 */ 21 21 struct dpu_core_perf_params { 22 - u64 max_per_pipe_ib; 22 + u32 max_per_pipe_ib; 23 23 u64 bw_ctl; 24 24 u64 core_clk_rate; 25 25 }; ··· 40 40 * @perf_tune: debug control for performance tuning 41 41 * @enable_bw_release: debug control for bandwidth release 42 42 * @fix_core_clk_rate: fixed core clock request in Hz used in mode 2 43 - * @fix_core_ib_vote: fixed core ib vote in bps used in mode 2 44 - * @fix_core_ab_vote: fixed core ab vote in bps used in mode 2 43 + * @fix_core_ib_vote: fixed core ib vote in KBps used in mode 2 44 + * @fix_core_ab_vote: fixed core ab vote in KBps used in mode 2 45 45 */ 46 46 struct dpu_core_perf { 47 47 const struct dpu_perf_cfg *perf_cfg; ··· 50 50 struct dpu_core_perf_tune perf_tune; 51 51 u32 enable_bw_release; 52 52 u64 fix_core_clk_rate; 53 - u64 fix_core_ib_vote; 54 - u64 fix_core_ab_vote; 53 + u32 fix_core_ib_vote; 54 + u32 fix_core_ab_vote; 55 55 }; 56 56 57 57 int dpu_core_perf_crtc_check(struct drm_crtc *crtc,
+215 -18
drivers/gpu/drm/msm/disp/dpu1/dpu_crtc.c
··· 953 953 return rc; 954 954 } 955 955 956 + static int dpu_crtc_kickoff_clone_mode(struct drm_crtc *crtc) 957 + { 958 + struct drm_encoder *encoder; 959 + struct drm_encoder *rt_encoder = NULL, *wb_encoder = NULL; 960 + struct dpu_kms *dpu_kms = _dpu_crtc_get_kms(crtc); 961 + 962 + /* Find encoder for real time display */ 963 + drm_for_each_encoder_mask(encoder, crtc->dev, 964 + crtc->state->encoder_mask) { 965 + if (encoder->encoder_type == DRM_MODE_ENCODER_VIRTUAL) 966 + wb_encoder = encoder; 967 + else 968 + rt_encoder = encoder; 969 + } 970 + 971 + if (!rt_encoder || !wb_encoder) { 972 + DRM_DEBUG_ATOMIC("real time or wb encoder not found\n"); 973 + return -EINVAL; 974 + } 975 + 976 + dpu_encoder_prepare_for_kickoff(wb_encoder); 977 + dpu_encoder_prepare_for_kickoff(rt_encoder); 978 + 979 + dpu_vbif_clear_errors(dpu_kms); 980 + 981 + /* 982 + * Kickoff real time encoder last as it's the encoder that 983 + * will do the flush 984 + */ 985 + dpu_encoder_kickoff(wb_encoder); 986 + dpu_encoder_kickoff(rt_encoder); 987 + 988 + /* Don't start frame done timers until the kickoffs have finished */ 989 + dpu_encoder_start_frame_done_timer(wb_encoder); 990 + dpu_encoder_start_frame_done_timer(rt_encoder); 991 + 992 + return 0; 993 + } 994 + 956 995 /** 957 996 * dpu_crtc_commit_kickoff - trigger kickoff of the commit for this crtc 958 997 * @crtc: Pointer to drm crtc object ··· 1020 981 goto end; 1021 982 } 1022 983 } 1023 - /* 1024 - * Encoder will flush/start now, unless it has a tx pending. If so, it 1025 - * may delay and flush at an irq event (e.g. ppdone) 1026 - */ 1027 - drm_for_each_encoder_mask(encoder, crtc->dev, 1028 - crtc->state->encoder_mask) 1029 - dpu_encoder_prepare_for_kickoff(encoder); 984 + 985 + if (drm_crtc_in_clone_mode(crtc->state)) { 986 + if (dpu_crtc_kickoff_clone_mode(crtc)) 987 + goto end; 988 + } else { 989 + /* 990 + * Encoder will flush/start now, unless it has a tx pending. 991 + * If so, it may delay and flush at an irq event (e.g. ppdone) 992 + */ 993 + drm_for_each_encoder_mask(encoder, crtc->dev, 994 + crtc->state->encoder_mask) 995 + dpu_encoder_prepare_for_kickoff(encoder); 996 + 997 + dpu_vbif_clear_errors(dpu_kms); 998 + 999 + drm_for_each_encoder_mask(encoder, crtc->dev, 1000 + crtc->state->encoder_mask) { 1001 + dpu_encoder_kickoff(encoder); 1002 + dpu_encoder_start_frame_done_timer(encoder); 1003 + } 1004 + } 1030 1005 1031 1006 if (atomic_inc_return(&dpu_crtc->frame_pending) == 1) { 1032 1007 /* acquire bandwidth and other resources */ ··· 1049 996 DRM_DEBUG_ATOMIC("crtc%d commit\n", crtc->base.id); 1050 997 1051 998 dpu_crtc->play_count++; 1052 - 1053 - dpu_vbif_clear_errors(dpu_kms); 1054 - 1055 - drm_for_each_encoder_mask(encoder, crtc->dev, crtc->state->encoder_mask) 1056 - dpu_encoder_kickoff(encoder); 1057 999 1058 1000 reinit_completion(&dpu_crtc->frame_done_comp); 1059 1001 ··· 1278 1230 return ret; 1279 1231 } 1280 1232 1233 + #define MAX_CHANNELS_PER_CRTC 2 1234 + #define MAX_HDISPLAY_SPLIT 1080 1235 + 1236 + static struct msm_display_topology dpu_crtc_get_topology( 1237 + struct drm_crtc *crtc, 1238 + struct dpu_kms *dpu_kms, 1239 + struct drm_crtc_state *crtc_state) 1240 + { 1241 + struct drm_display_mode *mode = &crtc_state->adjusted_mode; 1242 + struct msm_display_topology topology = {0}; 1243 + struct drm_encoder *drm_enc; 1244 + 1245 + drm_for_each_encoder_mask(drm_enc, crtc->dev, crtc_state->encoder_mask) 1246 + dpu_encoder_update_topology(drm_enc, &topology, crtc_state->state, 1247 + &crtc_state->adjusted_mode); 1248 + 1249 + topology.cwb_enabled = drm_crtc_in_clone_mode(crtc_state); 1250 + 1251 + /* 1252 + * Datapath topology selection 1253 + * 1254 + * Dual display 1255 + * 2 LM, 2 INTF ( Split display using 2 interfaces) 1256 + * 1257 + * Single display 1258 + * 1 LM, 1 INTF 1259 + * 2 LM, 1 INTF (stream merge to support high resolution interfaces) 1260 + * 1261 + * If DSC is enabled, use 2 LMs for 2:2:1 topology 1262 + * 1263 + * Add dspps to the reservation requirements if ctm is requested 1264 + * 1265 + * Only hardcode num_lm to 2 for cases where num_intf == 2 and CWB is not 1266 + * enabled. This is because in cases where CWB is enabled, num_intf will 1267 + * count both the WB and real-time phys encoders. 1268 + * 1269 + * For non-DSC CWB usecases, have the num_lm be decided by the 1270 + * (mode->hdisplay > MAX_HDISPLAY_SPLIT) check. 1271 + */ 1272 + 1273 + if (topology.num_intf == 2 && !topology.cwb_enabled) 1274 + topology.num_lm = 2; 1275 + else if (topology.num_dsc == 2) 1276 + topology.num_lm = 2; 1277 + else if (dpu_kms->catalog->caps->has_3d_merge) 1278 + topology.num_lm = (mode->hdisplay > MAX_HDISPLAY_SPLIT) ? 2 : 1; 1279 + else 1280 + topology.num_lm = 1; 1281 + 1282 + if (crtc_state->ctm) 1283 + topology.num_dspp = topology.num_lm; 1284 + 1285 + return topology; 1286 + } 1287 + 1288 + static int dpu_crtc_assign_resources(struct drm_crtc *crtc, 1289 + struct drm_crtc_state *crtc_state) 1290 + { 1291 + struct dpu_hw_blk *hw_ctl[MAX_CHANNELS_PER_CRTC]; 1292 + struct dpu_hw_blk *hw_lm[MAX_CHANNELS_PER_CRTC]; 1293 + struct dpu_hw_blk *hw_dspp[MAX_CHANNELS_PER_CRTC]; 1294 + int i, num_lm, num_ctl, num_dspp; 1295 + struct dpu_kms *dpu_kms = _dpu_crtc_get_kms(crtc); 1296 + struct dpu_global_state *global_state; 1297 + struct dpu_crtc_state *cstate; 1298 + struct msm_display_topology topology; 1299 + int ret; 1300 + 1301 + /* 1302 + * Release and Allocate resources on every modeset 1303 + */ 1304 + global_state = dpu_kms_get_global_state(crtc_state->state); 1305 + if (IS_ERR(global_state)) 1306 + return PTR_ERR(global_state); 1307 + 1308 + dpu_rm_release(global_state, crtc); 1309 + 1310 + if (!crtc_state->enable) 1311 + return 0; 1312 + 1313 + topology = dpu_crtc_get_topology(crtc, dpu_kms, crtc_state); 1314 + ret = dpu_rm_reserve(&dpu_kms->rm, global_state, 1315 + crtc_state->crtc, &topology); 1316 + if (ret) 1317 + return ret; 1318 + 1319 + cstate = to_dpu_crtc_state(crtc_state); 1320 + 1321 + num_ctl = dpu_rm_get_assigned_resources(&dpu_kms->rm, global_state, 1322 + crtc_state->crtc, 1323 + DPU_HW_BLK_CTL, hw_ctl, 1324 + ARRAY_SIZE(hw_ctl)); 1325 + num_lm = dpu_rm_get_assigned_resources(&dpu_kms->rm, global_state, 1326 + crtc_state->crtc, 1327 + DPU_HW_BLK_LM, hw_lm, 1328 + ARRAY_SIZE(hw_lm)); 1329 + num_dspp = dpu_rm_get_assigned_resources(&dpu_kms->rm, global_state, 1330 + crtc_state->crtc, 1331 + DPU_HW_BLK_DSPP, hw_dspp, 1332 + ARRAY_SIZE(hw_dspp)); 1333 + 1334 + for (i = 0; i < num_lm; i++) { 1335 + int ctl_idx = (i < num_ctl) ? i : (num_ctl-1); 1336 + 1337 + cstate->mixers[i].hw_lm = to_dpu_hw_mixer(hw_lm[i]); 1338 + cstate->mixers[i].lm_ctl = to_dpu_hw_ctl(hw_ctl[ctl_idx]); 1339 + if (i < num_dspp) 1340 + cstate->mixers[i].hw_dspp = to_dpu_hw_dspp(hw_dspp[i]); 1341 + } 1342 + 1343 + cstate->num_mixers = num_lm; 1344 + 1345 + return 0; 1346 + } 1347 + 1348 + /** 1349 + * dpu_crtc_check_mode_changed: check if full modeset is required 1350 + * @old_crtc_state: Previous CRTC state 1351 + * @new_crtc_state: Corresponding CRTC state to be checked 1352 + * 1353 + * Check if the changes in the object properties demand full mode set. 1354 + */ 1355 + int dpu_crtc_check_mode_changed(struct drm_crtc_state *old_crtc_state, 1356 + struct drm_crtc_state *new_crtc_state) 1357 + { 1358 + struct drm_encoder *drm_enc; 1359 + struct drm_crtc *crtc = new_crtc_state->crtc; 1360 + bool clone_mode_enabled = drm_crtc_in_clone_mode(old_crtc_state); 1361 + bool clone_mode_requested = drm_crtc_in_clone_mode(new_crtc_state); 1362 + 1363 + DRM_DEBUG_ATOMIC("%d\n", crtc->base.id); 1364 + 1365 + /* there might be cases where encoder needs a modeset too */ 1366 + drm_for_each_encoder_mask(drm_enc, crtc->dev, new_crtc_state->encoder_mask) { 1367 + if (dpu_encoder_needs_modeset(drm_enc, new_crtc_state->state)) 1368 + new_crtc_state->mode_changed = true; 1369 + } 1370 + 1371 + if ((clone_mode_requested && !clone_mode_enabled) || 1372 + (!clone_mode_requested && clone_mode_enabled)) 1373 + new_crtc_state->mode_changed = true; 1374 + 1375 + return 0; 1376 + } 1377 + 1281 1378 static int dpu_crtc_atomic_check(struct drm_crtc *crtc, 1282 1379 struct drm_atomic_state *state) 1283 1380 { ··· 1437 1244 int rc = 0; 1438 1245 1439 1246 bool needs_dirtyfb = dpu_crtc_needs_dirtyfb(crtc_state); 1247 + 1248 + /* don't reallocate resources if only ACTIVE has beeen changed */ 1249 + if (crtc_state->mode_changed || crtc_state->connectors_changed) { 1250 + rc = dpu_crtc_assign_resources(crtc, crtc_state); 1251 + if (rc < 0) 1252 + return rc; 1253 + } 1440 1254 1441 1255 if (dpu_use_virtual_planes && 1442 1256 (crtc_state->planes_changed || crtc_state->zpos_changed)) { ··· 1461 1261 } 1462 1262 1463 1263 DRM_DEBUG_ATOMIC("%s: check\n", dpu_crtc->name); 1464 - 1465 - /* force a full mode set if active state changed */ 1466 - if (crtc_state->active_changed) 1467 - crtc_state->mode_changed = true; 1468 1264 1469 1265 if (cstate->num_mixers) { 1470 1266 rc = _dpu_crtc_check_and_setup_lm_bounds(crtc, crtc_state); ··· 1680 1484 seq_printf(s, "intf_mode: %d\n", dpu_crtc_get_intf_mode(crtc)); 1681 1485 seq_printf(s, "core_clk_rate: %llu\n", 1682 1486 dpu_crtc->cur_perf.core_clk_rate); 1683 - seq_printf(s, "bw_ctl: %llu\n", dpu_crtc->cur_perf.bw_ctl); 1684 - seq_printf(s, "max_per_pipe_ib: %llu\n", 1487 + seq_printf(s, "bw_ctl: %uk\n", 1488 + (u32)DIV_ROUND_UP_ULL(dpu_crtc->cur_perf.bw_ctl, 1000)); 1489 + seq_printf(s, "max_per_pipe_ib: %u\n", 1685 1490 dpu_crtc->cur_perf.max_per_pipe_ib); 1686 1491 1687 1492 return 0;
+3
drivers/gpu/drm/msm/disp/dpu1/dpu_crtc.h
··· 239 239 return crtc ? atomic_read(&to_dpu_crtc(crtc)->frame_pending) : -EINVAL; 240 240 } 241 241 242 + int dpu_crtc_check_mode_changed(struct drm_crtc_state *old_crtc_state, 243 + struct drm_crtc_state *new_crtc_state); 244 + 242 245 int dpu_crtc_vblank(struct drm_crtc *crtc, bool en); 243 246 244 247 void dpu_crtc_vblank_callback(struct drm_crtc *crtc);
+287 -189
drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c
··· 2 2 /* 3 3 * Copyright (C) 2013 Red Hat 4 4 * Copyright (c) 2014-2018, 2020-2021 The Linux Foundation. All rights reserved. 5 - * Copyright (c) 2022-2023 Qualcomm Innovation Center, Inc. All rights reserved. 5 + * Copyright (c) 2022-2024 Qualcomm Innovation Center, Inc. All rights reserved. 6 6 * 7 7 * Author: Rob Clark <robdclark@gmail.com> 8 8 */ ··· 24 24 #include "dpu_hw_catalog.h" 25 25 #include "dpu_hw_intf.h" 26 26 #include "dpu_hw_ctl.h" 27 + #include "dpu_hw_cwb.h" 27 28 #include "dpu_hw_dspp.h" 28 29 #include "dpu_hw_dsc.h" 29 30 #include "dpu_hw_merge3d.h" ··· 58 57 #define MAX_CHANNELS_PER_ENC 2 59 58 60 59 #define IDLE_SHORT_TIMEOUT 1 61 - 62 - #define MAX_HDISPLAY_SPLIT 1080 63 60 64 61 /* timeout in frames waiting for frame done */ 65 62 #define DPU_ENCODER_FRAME_DONE_TIMEOUT_FRAMES 5 ··· 134 135 * @cur_slave: As above but for the slave encoder. 135 136 * @hw_pp: Handle to the pingpong blocks used for the display. No. 136 137 * pingpong blocks can be different than num_phys_encs. 138 + * @hw_cwb: Handle to the CWB muxes used for concurrent writeback 139 + * display. Number of CWB muxes can be different than 140 + * num_phys_encs. 137 141 * @hw_dsc: Handle to the DSC blocks used for the display. 138 142 * @dsc_mask: Bitmask of used DSC blocks. 143 + * @cwb_mask: Bitmask of used CWB muxes 139 144 * @intfs_swapped: Whether or not the phys_enc interfaces have been swapped 140 145 * for partial update right-only cases, such as pingpong 141 146 * split where virtual pingpong does not generate IRQs ··· 182 179 struct dpu_encoder_phys *cur_master; 183 180 struct dpu_encoder_phys *cur_slave; 184 181 struct dpu_hw_pingpong *hw_pp[MAX_CHANNELS_PER_ENC]; 182 + struct dpu_hw_cwb *hw_cwb[MAX_CHANNELS_PER_ENC]; 185 183 struct dpu_hw_dsc *hw_dsc[MAX_CHANNELS_PER_ENC]; 186 184 187 185 unsigned int dsc_mask; 186 + unsigned int cwb_mask; 188 187 189 188 bool intfs_swapped; 190 189 ··· 627 622 if (dpu_enc->phys_encs[i]) 628 623 intf_count++; 629 624 630 - /* See dpu_encoder_get_topology, we only support 2:2:1 topology */ 631 - if (dpu_enc->dsc) 632 - num_dsc = 2; 625 + for (i = 0; i < MAX_CHANNELS_PER_ENC; i++) 626 + if (dpu_enc->hw_dsc[i]) 627 + num_dsc++; 633 628 634 629 return (num_dsc > 0) && (num_dsc > intf_count); 635 630 } ··· 652 647 return NULL; 653 648 } 654 649 655 - static struct msm_display_topology dpu_encoder_get_topology( 656 - struct dpu_encoder_virt *dpu_enc, 657 - struct dpu_kms *dpu_kms, 658 - struct drm_display_mode *mode, 659 - struct drm_crtc_state *crtc_state, 660 - struct drm_dsc_config *dsc) 650 + void dpu_encoder_update_topology(struct drm_encoder *drm_enc, 651 + struct msm_display_topology *topology, 652 + struct drm_atomic_state *state, 653 + const struct drm_display_mode *adj_mode) 661 654 { 662 - struct msm_display_topology topology = {0}; 663 - int i, intf_count = 0; 655 + struct dpu_encoder_virt *dpu_enc = to_dpu_encoder_virt(drm_enc); 656 + struct msm_drm_private *priv = dpu_enc->base.dev->dev_private; 657 + struct msm_display_info *disp_info = &dpu_enc->disp_info; 658 + struct dpu_kms *dpu_kms = to_dpu_kms(priv->kms); 659 + struct drm_connector *connector; 660 + struct drm_connector_state *conn_state; 661 + struct drm_framebuffer *fb; 662 + struct drm_dsc_config *dsc; 663 + 664 + int i; 664 665 665 666 for (i = 0; i < MAX_PHYS_ENCODERS_PER_VIRTUAL; i++) 666 667 if (dpu_enc->phys_encs[i]) 667 - intf_count++; 668 - 669 - /* Datapath topology selection 670 - * 671 - * Dual display 672 - * 2 LM, 2 INTF ( Split display using 2 interfaces) 673 - * 674 - * Single display 675 - * 1 LM, 1 INTF 676 - * 2 LM, 1 INTF (stream merge to support high resolution interfaces) 677 - * 678 - * Add dspps to the reservation requirements if ctm is requested 679 - */ 680 - if (intf_count == 2) 681 - topology.num_lm = 2; 682 - else if (!dpu_kms->catalog->caps->has_3d_merge) 683 - topology.num_lm = 1; 684 - else 685 - topology.num_lm = (mode->hdisplay > MAX_HDISPLAY_SPLIT) ? 2 : 1; 686 - 687 - if (crtc_state->ctm) 688 - topology.num_dspp = topology.num_lm; 689 - 690 - topology.num_intf = intf_count; 691 - 692 - if (dsc) { 693 - /* 694 - * In case of Display Stream Compression (DSC), we would use 695 - * 2 DSC encoders, 2 layer mixers and 1 interface 696 - * this is power optimal and can drive up to (including) 4k 697 - * screens 698 - */ 699 - topology.num_dsc = 2; 700 - topology.num_lm = 2; 701 - topology.num_intf = 1; 702 - } 703 - 704 - return topology; 705 - } 706 - 707 - static void dpu_encoder_assign_crtc_resources(struct dpu_kms *dpu_kms, 708 - struct drm_encoder *drm_enc, 709 - struct dpu_global_state *global_state, 710 - struct drm_crtc_state *crtc_state) 711 - { 712 - struct dpu_crtc_state *cstate; 713 - struct dpu_hw_blk *hw_ctl[MAX_CHANNELS_PER_ENC]; 714 - struct dpu_hw_blk *hw_lm[MAX_CHANNELS_PER_ENC]; 715 - struct dpu_hw_blk *hw_dspp[MAX_CHANNELS_PER_ENC]; 716 - int num_lm, num_ctl, num_dspp, i; 717 - 718 - cstate = to_dpu_crtc_state(crtc_state); 719 - 720 - memset(cstate->mixers, 0, sizeof(cstate->mixers)); 721 - 722 - num_ctl = dpu_rm_get_assigned_resources(&dpu_kms->rm, global_state, 723 - drm_enc->base.id, DPU_HW_BLK_CTL, hw_ctl, ARRAY_SIZE(hw_ctl)); 724 - num_lm = dpu_rm_get_assigned_resources(&dpu_kms->rm, global_state, 725 - drm_enc->base.id, DPU_HW_BLK_LM, hw_lm, ARRAY_SIZE(hw_lm)); 726 - num_dspp = dpu_rm_get_assigned_resources(&dpu_kms->rm, global_state, 727 - drm_enc->base.id, DPU_HW_BLK_DSPP, hw_dspp, 728 - ARRAY_SIZE(hw_dspp)); 729 - 730 - for (i = 0; i < num_lm; i++) { 731 - int ctl_idx = (i < num_ctl) ? i : (num_ctl-1); 732 - 733 - cstate->mixers[i].hw_lm = to_dpu_hw_mixer(hw_lm[i]); 734 - cstate->mixers[i].lm_ctl = to_dpu_hw_ctl(hw_ctl[ctl_idx]); 735 - cstate->mixers[i].hw_dspp = i < num_dspp ? to_dpu_hw_dspp(hw_dspp[i]) : NULL; 736 - } 737 - 738 - cstate->num_mixers = num_lm; 739 - } 740 - 741 - static int dpu_encoder_virt_atomic_check( 742 - struct drm_encoder *drm_enc, 743 - struct drm_crtc_state *crtc_state, 744 - struct drm_connector_state *conn_state) 745 - { 746 - struct dpu_encoder_virt *dpu_enc; 747 - struct msm_drm_private *priv; 748 - struct dpu_kms *dpu_kms; 749 - struct drm_display_mode *adj_mode; 750 - struct msm_display_topology topology; 751 - struct msm_display_info *disp_info; 752 - struct dpu_global_state *global_state; 753 - struct drm_framebuffer *fb; 754 - struct drm_dsc_config *dsc; 755 - int ret = 0; 756 - 757 - if (!drm_enc || !crtc_state || !conn_state) { 758 - DPU_ERROR("invalid arg(s), drm_enc %d, crtc/conn state %d/%d\n", 759 - drm_enc != NULL, crtc_state != NULL, conn_state != NULL); 760 - return -EINVAL; 761 - } 762 - 763 - dpu_enc = to_dpu_encoder_virt(drm_enc); 764 - DPU_DEBUG_ENC(dpu_enc, "\n"); 765 - 766 - priv = drm_enc->dev->dev_private; 767 - disp_info = &dpu_enc->disp_info; 768 - dpu_kms = to_dpu_kms(priv->kms); 769 - adj_mode = &crtc_state->adjusted_mode; 770 - global_state = dpu_kms_get_global_state(crtc_state->state); 771 - if (IS_ERR(global_state)) 772 - return PTR_ERR(global_state); 773 - 774 - trace_dpu_enc_atomic_check(DRMID(drm_enc)); 668 + topology->num_intf++; 775 669 776 670 dsc = dpu_encoder_get_dsc_config(drm_enc); 777 671 778 - topology = dpu_encoder_get_topology(dpu_enc, dpu_kms, adj_mode, crtc_state, dsc); 672 + /* We only support 2 DSC mode (with 2 LM and 1 INTF) */ 673 + if (dsc) { 674 + /* 675 + * Use 2 DSC encoders, 2 layer mixers and 1 or 2 interfaces 676 + * when Display Stream Compression (DSC) is enabled, 677 + * and when enough DSC blocks are available. 678 + * This is power-optimal and can drive up to (including) 4k 679 + * screens. 680 + */ 681 + WARN(topology->num_intf > 2, 682 + "DSC topology cannot support more than 2 interfaces\n"); 683 + if (topology->num_intf >= 2 || dpu_kms->catalog->dsc_count >= 2) 684 + topology->num_dsc = 2; 685 + else 686 + topology->num_dsc = 1; 687 + } 688 + 689 + connector = drm_atomic_get_new_connector_for_encoder(state, drm_enc); 690 + if (!connector) 691 + return; 692 + conn_state = drm_atomic_get_new_connector_state(state, connector); 693 + if (!conn_state) 694 + return; 779 695 780 696 /* 781 697 * Use CDM only for writeback or DP at the moment as other interfaces cannot handle it. ··· 707 781 fb = conn_state->writeback_job->fb; 708 782 709 783 if (fb && MSM_FORMAT_IS_YUV(msm_framebuffer_format(fb))) 710 - topology.needs_cdm = true; 784 + topology->num_cdm++; 711 785 } else if (disp_info->intf_type == INTF_DP) { 712 786 if (msm_dp_is_yuv_420_enabled(priv->dp[disp_info->h_tile_instance[0]], adj_mode)) 713 - topology.needs_cdm = true; 787 + topology->num_cdm++; 714 788 } 789 + } 715 790 716 - if (topology.needs_cdm && !dpu_enc->cur_master->hw_cdm) 717 - crtc_state->mode_changed = true; 718 - else if (!topology.needs_cdm && dpu_enc->cur_master->hw_cdm) 719 - crtc_state->mode_changed = true; 720 - /* 721 - * Release and Allocate resources on every modeset 722 - * Dont allocate when active is false. 791 + bool dpu_encoder_needs_modeset(struct drm_encoder *drm_enc, struct drm_atomic_state *state) 792 + { 793 + struct drm_connector *connector; 794 + struct drm_connector_state *conn_state; 795 + struct drm_framebuffer *fb; 796 + struct dpu_encoder_virt *dpu_enc = to_dpu_encoder_virt(drm_enc); 797 + 798 + if (!drm_enc || !state) 799 + return false; 800 + 801 + connector = drm_atomic_get_new_connector_for_encoder(state, drm_enc); 802 + if (!connector) 803 + return false; 804 + 805 + conn_state = drm_atomic_get_new_connector_state(state, connector); 806 + 807 + /** 808 + * These checks are duplicated from dpu_encoder_update_topology() since 809 + * CRTC and encoder don't hold topology information 723 810 */ 724 - if (drm_atomic_crtc_needs_modeset(crtc_state)) { 725 - dpu_rm_release(global_state, drm_enc); 726 - 727 - if (!crtc_state->active_changed || crtc_state->enable) 728 - ret = dpu_rm_reserve(&dpu_kms->rm, global_state, 729 - drm_enc, crtc_state, &topology); 730 - if (!ret) 731 - dpu_encoder_assign_crtc_resources(dpu_kms, drm_enc, 732 - global_state, crtc_state); 811 + if (dpu_enc->disp_info.intf_type == INTF_WB && conn_state->writeback_job) { 812 + fb = conn_state->writeback_job->fb; 813 + if (fb && MSM_FORMAT_IS_YUV(msm_framebuffer_format(fb))) { 814 + if (!dpu_enc->cur_master->hw_cdm) 815 + return true; 816 + } else { 817 + if (dpu_enc->cur_master->hw_cdm) 818 + return true; 819 + } 733 820 } 734 821 735 - trace_dpu_enc_atomic_check_flags(DRMID(drm_enc), adj_mode->flags); 736 - 737 - return ret; 822 + return false; 738 823 } 739 824 740 825 static void _dpu_encoder_update_vsync_source(struct dpu_encoder_virt *dpu_enc, ··· 1156 1219 struct dpu_hw_blk *hw_pp[MAX_CHANNELS_PER_ENC]; 1157 1220 struct dpu_hw_blk *hw_ctl[MAX_CHANNELS_PER_ENC]; 1158 1221 struct dpu_hw_blk *hw_dsc[MAX_CHANNELS_PER_ENC]; 1222 + struct dpu_hw_blk *hw_cwb[MAX_CHANNELS_PER_ENC]; 1159 1223 int num_ctl, num_pp, num_dsc; 1224 + int num_cwb = 0; 1225 + bool is_cwb_encoder; 1160 1226 unsigned int dsc_mask = 0; 1227 + unsigned int cwb_mask = 0; 1161 1228 int i; 1162 1229 1163 1230 if (!drm_enc) { ··· 1174 1233 1175 1234 priv = drm_enc->dev->dev_private; 1176 1235 dpu_kms = to_dpu_kms(priv->kms); 1236 + is_cwb_encoder = drm_crtc_in_clone_mode(crtc_state) && 1237 + dpu_enc->disp_info.intf_type == INTF_WB; 1177 1238 1178 1239 global_state = dpu_kms_get_existing_global_state(dpu_kms); 1179 1240 if (IS_ERR_OR_NULL(global_state)) { ··· 1186 1243 trace_dpu_enc_mode_set(DRMID(drm_enc)); 1187 1244 1188 1245 /* Query resource that have been reserved in atomic check step. */ 1189 - num_pp = dpu_rm_get_assigned_resources(&dpu_kms->rm, global_state, 1190 - drm_enc->base.id, DPU_HW_BLK_PINGPONG, hw_pp, 1191 - ARRAY_SIZE(hw_pp)); 1246 + if (is_cwb_encoder) { 1247 + num_pp = dpu_rm_get_assigned_resources(&dpu_kms->rm, global_state, 1248 + drm_enc->crtc, 1249 + DPU_HW_BLK_DCWB_PINGPONG, 1250 + hw_pp, ARRAY_SIZE(hw_pp)); 1251 + num_cwb = dpu_rm_get_assigned_resources(&dpu_kms->rm, global_state, 1252 + drm_enc->crtc, 1253 + DPU_HW_BLK_CWB, 1254 + hw_cwb, ARRAY_SIZE(hw_cwb)); 1255 + } else { 1256 + num_pp = dpu_rm_get_assigned_resources(&dpu_kms->rm, global_state, 1257 + drm_enc->crtc, 1258 + DPU_HW_BLK_PINGPONG, hw_pp, 1259 + ARRAY_SIZE(hw_pp)); 1260 + } 1261 + 1262 + for (i = 0; i < num_cwb; i++) { 1263 + dpu_enc->hw_cwb[i] = to_dpu_hw_cwb(hw_cwb[i]); 1264 + cwb_mask |= BIT(dpu_enc->hw_cwb[i]->idx - CWB_0); 1265 + } 1266 + 1267 + dpu_enc->cwb_mask = cwb_mask; 1268 + 1192 1269 num_ctl = dpu_rm_get_assigned_resources(&dpu_kms->rm, global_state, 1193 - drm_enc->base.id, DPU_HW_BLK_CTL, hw_ctl, ARRAY_SIZE(hw_ctl)); 1270 + drm_enc->crtc, DPU_HW_BLK_CTL, hw_ctl, ARRAY_SIZE(hw_ctl)); 1194 1271 1195 1272 for (i = 0; i < MAX_CHANNELS_PER_ENC; i++) 1196 1273 dpu_enc->hw_pp[i] = i < num_pp ? to_dpu_hw_pingpong(hw_pp[i]) 1197 1274 : NULL; 1198 1275 1199 1276 num_dsc = dpu_rm_get_assigned_resources(&dpu_kms->rm, global_state, 1200 - drm_enc->base.id, DPU_HW_BLK_DSC, 1277 + drm_enc->crtc, DPU_HW_BLK_DSC, 1201 1278 hw_dsc, ARRAY_SIZE(hw_dsc)); 1202 1279 for (i = 0; i < num_dsc; i++) { 1203 1280 dpu_enc->hw_dsc[i] = to_dpu_hw_dsc(hw_dsc[i]); ··· 1231 1268 struct dpu_hw_blk *hw_cdm = NULL; 1232 1269 1233 1270 dpu_rm_get_assigned_resources(&dpu_kms->rm, global_state, 1234 - drm_enc->base.id, DPU_HW_BLK_CDM, 1271 + drm_enc->crtc, DPU_HW_BLK_CDM, 1235 1272 &hw_cdm, 1); 1236 1273 dpu_enc->cur_master->hw_cdm = hw_cdm ? to_dpu_hw_cdm(hw_cdm) : NULL; 1237 1274 } ··· 1617 1654 static void _dpu_encoder_trigger_flush(struct drm_encoder *drm_enc, 1618 1655 struct dpu_encoder_phys *phys, uint32_t extra_flush_bits) 1619 1656 { 1657 + struct dpu_encoder_virt *dpu_enc = to_dpu_encoder_virt(drm_enc); 1620 1658 struct dpu_hw_ctl *ctl; 1621 1659 int pending_kickoff_cnt; 1622 1660 u32 ret = UINT_MAX; ··· 1634 1670 } 1635 1671 1636 1672 pending_kickoff_cnt = dpu_encoder_phys_inc_pending(phys); 1673 + 1674 + /* Return early if encoder is writeback and in clone mode */ 1675 + if (drm_enc->encoder_type == DRM_MODE_ENCODER_VIRTUAL && 1676 + dpu_enc->cwb_mask) { 1677 + DPU_DEBUG("encoder %d skip flush for concurrent writeback encoder\n", 1678 + DRMID(drm_enc)); 1679 + return; 1680 + } 1681 + 1637 1682 1638 1683 if (extra_flush_bits && ctl->ops.update_pending_flush) 1639 1684 ctl->ops.update_pending_flush(ctl, extra_flush_bits); ··· 1666 1693 */ 1667 1694 static void _dpu_encoder_trigger_start(struct dpu_encoder_phys *phys) 1668 1695 { 1696 + struct dpu_encoder_virt *dpu_enc = to_dpu_encoder_virt(phys->parent); 1697 + 1669 1698 if (!phys) { 1670 1699 DPU_ERROR("invalid argument(s)\n"); 1671 1700 return; ··· 1675 1700 1676 1701 if (!phys->hw_pp) { 1677 1702 DPU_ERROR("invalid pingpong hw\n"); 1703 + return; 1704 + } 1705 + 1706 + if (phys->parent->encoder_type == DRM_MODE_ENCODER_VIRTUAL && 1707 + dpu_enc->cwb_mask) { 1708 + DPU_DEBUG("encoder %d CWB enabled, skipping\n", DRMID(phys->parent)); 1678 1709 return; 1679 1710 } 1680 1711 ··· 2001 2020 static void dpu_encoder_prep_dsc(struct dpu_encoder_virt *dpu_enc, 2002 2021 struct drm_dsc_config *dsc) 2003 2022 { 2004 - /* coding only for 2LM, 2enc, 1 dsc config */ 2005 2023 struct dpu_encoder_phys *enc_master = dpu_enc->cur_master; 2006 2024 struct dpu_hw_ctl *ctl = enc_master->hw_ctl; 2007 2025 struct dpu_hw_dsc *hw_dsc[MAX_CHANNELS_PER_ENC]; ··· 2010 2030 int dsc_common_mode; 2011 2031 int pic_width; 2012 2032 u32 initial_lines; 2033 + int num_dsc = 0; 2013 2034 int i; 2014 2035 2015 2036 for (i = 0; i < MAX_CHANNELS_PER_ENC; i++) { 2016 2037 hw_pp[i] = dpu_enc->hw_pp[i]; 2017 2038 hw_dsc[i] = dpu_enc->hw_dsc[i]; 2018 2039 2019 - if (!hw_pp[i] || !hw_dsc[i]) { 2020 - DPU_ERROR_ENC(dpu_enc, "invalid params for DSC\n"); 2021 - return; 2022 - } 2040 + if (!hw_pp[i] || !hw_dsc[i]) 2041 + break; 2042 + 2043 + num_dsc++; 2023 2044 } 2024 2045 2025 - dsc_common_mode = 0; 2026 2046 pic_width = dsc->pic_width; 2027 2047 2028 - dsc_common_mode = DSC_MODE_SPLIT_PANEL; 2048 + dsc_common_mode = 0; 2049 + if (num_dsc > 1) 2050 + dsc_common_mode |= DSC_MODE_SPLIT_PANEL; 2029 2051 if (dpu_encoder_use_dsc_merge(enc_master->parent)) 2030 2052 dsc_common_mode |= DSC_MODE_MULTIPLEX; 2031 2053 if (enc_master->intf_mode == INTF_MODE_VIDEO) ··· 2036 2054 this_frame_slices = pic_width / dsc->slice_width; 2037 2055 intf_ip_w = this_frame_slices * dsc->slice_width; 2038 2056 2039 - /* 2040 - * dsc merge case: when using 2 encoders for the same stream, 2041 - * no. of slices need to be same on both the encoders. 2042 - */ 2043 - enc_ip_w = intf_ip_w / 2; 2057 + enc_ip_w = intf_ip_w / num_dsc; 2044 2058 initial_lines = dpu_encoder_dsc_initial_line_calc(dsc, enc_ip_w); 2045 2059 2046 - for (i = 0; i < MAX_CHANNELS_PER_ENC; i++) 2060 + for (i = 0; i < num_dsc; i++) 2047 2061 dpu_encoder_dsc_pipe_cfg(ctl, hw_dsc[i], hw_pp[i], 2048 2062 dsc, dsc_common_mode, initial_lines); 2049 2063 } ··· 2113 2135 } 2114 2136 2115 2137 /** 2138 + * dpu_encoder_start_frame_done_timer - Start the encoder frame done timer 2139 + * @drm_enc: Pointer to drm encoder structure 2140 + */ 2141 + void dpu_encoder_start_frame_done_timer(struct drm_encoder *drm_enc) 2142 + { 2143 + struct dpu_encoder_virt *dpu_enc; 2144 + unsigned long timeout_ms; 2145 + 2146 + dpu_enc = to_dpu_encoder_virt(drm_enc); 2147 + timeout_ms = DPU_ENCODER_FRAME_DONE_TIMEOUT_FRAMES * 1000 / 2148 + drm_mode_vrefresh(&drm_enc->crtc->state->adjusted_mode); 2149 + 2150 + atomic_set(&dpu_enc->frame_done_timeout_ms, timeout_ms); 2151 + mod_timer(&dpu_enc->frame_done_timer, 2152 + jiffies + msecs_to_jiffies(timeout_ms)); 2153 + 2154 + } 2155 + 2156 + /** 2116 2157 * dpu_encoder_kickoff - trigger a double buffer flip of the ctl path 2117 2158 * (i.e. ctl flush and start) immediately. 2118 2159 * @drm_enc: encoder pointer ··· 2140 2143 { 2141 2144 struct dpu_encoder_virt *dpu_enc; 2142 2145 struct dpu_encoder_phys *phys; 2143 - unsigned long timeout_ms; 2144 2146 unsigned int i; 2145 2147 2146 2148 DPU_ATRACE_BEGIN("encoder_kickoff"); 2147 2149 dpu_enc = to_dpu_encoder_virt(drm_enc); 2148 2150 2149 2151 trace_dpu_enc_kickoff(DRMID(drm_enc)); 2150 - 2151 - timeout_ms = DPU_ENCODER_FRAME_DONE_TIMEOUT_FRAMES * 1000 / 2152 - drm_mode_vrefresh(&drm_enc->crtc->state->adjusted_mode); 2153 - 2154 - atomic_set(&dpu_enc->frame_done_timeout_ms, timeout_ms); 2155 - mod_timer(&dpu_enc->frame_done_timer, 2156 - jiffies + msecs_to_jiffies(timeout_ms)); 2157 2152 2158 2153 /* All phys encs are ready to go, trigger the kickoff */ 2159 2154 _dpu_encoder_kickoff_phys(dpu_enc); ··· 2172 2183 memset(&mixer, 0, sizeof(mixer)); 2173 2184 2174 2185 /* reset all mixers for this encoder */ 2175 - if (phys_enc->hw_ctl->ops.clear_all_blendstages) 2176 - phys_enc->hw_ctl->ops.clear_all_blendstages(phys_enc->hw_ctl); 2186 + if (ctl->ops.clear_all_blendstages) 2187 + ctl->ops.clear_all_blendstages(ctl); 2177 2188 2178 2189 global_state = dpu_kms_get_existing_global_state(phys_enc->dpu_kms); 2179 2190 2180 2191 num_lm = dpu_rm_get_assigned_resources(&phys_enc->dpu_kms->rm, global_state, 2181 - phys_enc->parent->base.id, DPU_HW_BLK_LM, hw_lm, ARRAY_SIZE(hw_lm)); 2192 + phys_enc->parent->crtc, DPU_HW_BLK_LM, hw_lm, ARRAY_SIZE(hw_lm)); 2182 2193 2183 2194 for (i = 0; i < num_lm; i++) { 2184 2195 hw_mixer[i] = to_dpu_hw_mixer(hw_lm[i]); 2185 - if (phys_enc->hw_ctl->ops.update_pending_flush_mixer) 2186 - phys_enc->hw_ctl->ops.update_pending_flush_mixer(ctl, hw_mixer[i]->idx); 2196 + if (ctl->ops.update_pending_flush_mixer) 2197 + ctl->ops.update_pending_flush_mixer(ctl, hw_mixer[i]->idx); 2187 2198 2188 2199 /* clear all blendstages */ 2189 - if (phys_enc->hw_ctl->ops.setup_blendstage) 2190 - phys_enc->hw_ctl->ops.setup_blendstage(ctl, hw_mixer[i]->idx, NULL); 2200 + if (ctl->ops.setup_blendstage) 2201 + ctl->ops.setup_blendstage(ctl, hw_mixer[i]->idx, NULL); 2191 2202 } 2192 2203 } 2193 2204 ··· 2239 2250 2240 2251 dpu_enc = to_dpu_encoder_virt(phys_enc->parent); 2241 2252 2242 - phys_enc->hw_ctl->ops.reset(ctl); 2253 + ctl->ops.reset(ctl); 2243 2254 2244 2255 dpu_encoder_helper_reset_mixers(phys_enc); 2245 2256 ··· 2254 2265 phys_enc->hw_wb->ops.bind_pingpong_blk(phys_enc->hw_wb, PINGPONG_NONE); 2255 2266 2256 2267 /* mark WB flush as pending */ 2257 - if (phys_enc->hw_ctl->ops.update_pending_flush_wb) 2258 - phys_enc->hw_ctl->ops.update_pending_flush_wb(ctl, phys_enc->hw_wb->idx); 2268 + if (ctl->ops.update_pending_flush_wb) 2269 + ctl->ops.update_pending_flush_wb(ctl, phys_enc->hw_wb->idx); 2259 2270 } else { 2260 2271 for (i = 0; i < dpu_enc->num_phys_encs; i++) { 2261 2272 if (dpu_enc->phys_encs[i] && phys_enc->hw_intf->ops.bind_pingpong_blk) ··· 2264 2275 PINGPONG_NONE); 2265 2276 2266 2277 /* mark INTF flush as pending */ 2267 - if (phys_enc->hw_ctl->ops.update_pending_flush_intf) 2268 - phys_enc->hw_ctl->ops.update_pending_flush_intf(phys_enc->hw_ctl, 2278 + if (ctl->ops.update_pending_flush_intf) 2279 + ctl->ops.update_pending_flush_intf(ctl, 2269 2280 dpu_enc->phys_encs[i]->hw_intf->idx); 2270 2281 } 2271 2282 } ··· 2273 2284 if (phys_enc->hw_pp && phys_enc->hw_pp->ops.setup_dither) 2274 2285 phys_enc->hw_pp->ops.setup_dither(phys_enc->hw_pp, NULL); 2275 2286 2287 + if (dpu_enc->cwb_mask) 2288 + dpu_encoder_helper_phys_setup_cwb(phys_enc, false); 2289 + 2276 2290 /* reset the merge 3D HW block */ 2277 2291 if (phys_enc->hw_pp && phys_enc->hw_pp->merge_3d) { 2278 2292 phys_enc->hw_pp->merge_3d->ops.setup_3d_mode(phys_enc->hw_pp->merge_3d, 2279 2293 BLEND_3D_NONE); 2280 - if (phys_enc->hw_ctl->ops.update_pending_flush_merge_3d) 2281 - phys_enc->hw_ctl->ops.update_pending_flush_merge_3d(ctl, 2294 + if (ctl->ops.update_pending_flush_merge_3d) 2295 + ctl->ops.update_pending_flush_merge_3d(ctl, 2282 2296 phys_enc->hw_pp->merge_3d->idx); 2283 2297 } 2284 2298 ··· 2289 2297 if (phys_enc->hw_cdm->ops.bind_pingpong_blk && phys_enc->hw_pp) 2290 2298 phys_enc->hw_cdm->ops.bind_pingpong_blk(phys_enc->hw_cdm, 2291 2299 PINGPONG_NONE); 2292 - if (phys_enc->hw_ctl->ops.update_pending_flush_cdm) 2293 - phys_enc->hw_ctl->ops.update_pending_flush_cdm(phys_enc->hw_ctl, 2294 - phys_enc->hw_cdm->idx); 2300 + if (ctl->ops.update_pending_flush_cdm) 2301 + ctl->ops.update_pending_flush_cdm(ctl, 2302 + phys_enc->hw_cdm->idx); 2295 2303 } 2296 2304 2297 2305 if (dpu_enc->dsc) { ··· 2302 2310 intf_cfg.stream_sel = 0; /* Don't care value for video mode */ 2303 2311 intf_cfg.mode_3d = dpu_encoder_helper_get_3d_blend_mode(phys_enc); 2304 2312 intf_cfg.dsc = dpu_encoder_helper_get_dsc(phys_enc); 2313 + intf_cfg.cwb = dpu_enc->cwb_mask; 2305 2314 2306 2315 if (phys_enc->hw_intf) 2307 2316 intf_cfg.intf = phys_enc->hw_intf->idx; ··· 2318 2325 ctl->ops.trigger_flush(ctl); 2319 2326 ctl->ops.trigger_start(ctl); 2320 2327 ctl->ops.clear_pending_flush(ctl); 2328 + } 2329 + 2330 + void dpu_encoder_helper_phys_setup_cwb(struct dpu_encoder_phys *phys_enc, 2331 + bool enable) 2332 + { 2333 + struct dpu_encoder_virt *dpu_enc = to_dpu_encoder_virt(phys_enc->parent); 2334 + struct dpu_hw_cwb *hw_cwb; 2335 + struct dpu_hw_ctl *hw_ctl; 2336 + struct dpu_hw_cwb_setup_cfg cwb_cfg; 2337 + 2338 + struct dpu_kms *dpu_kms; 2339 + struct dpu_global_state *global_state; 2340 + struct dpu_hw_blk *rt_pp_list[MAX_CHANNELS_PER_ENC]; 2341 + int num_pp; 2342 + 2343 + if (!phys_enc->hw_wb) 2344 + return; 2345 + 2346 + hw_ctl = phys_enc->hw_ctl; 2347 + 2348 + if (!phys_enc->hw_ctl) { 2349 + DPU_DEBUG("[wb:%d] no ctl assigned\n", 2350 + phys_enc->hw_wb->idx - WB_0); 2351 + return; 2352 + } 2353 + 2354 + dpu_kms = phys_enc->dpu_kms; 2355 + global_state = dpu_kms_get_existing_global_state(dpu_kms); 2356 + num_pp = dpu_rm_get_assigned_resources(&dpu_kms->rm, global_state, 2357 + phys_enc->parent->crtc, 2358 + DPU_HW_BLK_PINGPONG, rt_pp_list, 2359 + ARRAY_SIZE(rt_pp_list)); 2360 + 2361 + if (num_pp == 0 || num_pp > MAX_CHANNELS_PER_ENC) { 2362 + DPU_DEBUG_ENC(dpu_enc, "invalid num_pp %d\n", num_pp); 2363 + return; 2364 + } 2365 + 2366 + /* 2367 + * The CWB mux supports using LM or DSPP as tap points. For now, 2368 + * always use LM tap point 2369 + */ 2370 + cwb_cfg.input = INPUT_MODE_LM_OUT; 2371 + 2372 + for (int i = 0; i < MAX_CHANNELS_PER_ENC; i++) { 2373 + hw_cwb = dpu_enc->hw_cwb[i]; 2374 + if (!hw_cwb) 2375 + continue; 2376 + 2377 + if (enable) { 2378 + struct dpu_hw_pingpong *hw_pp = 2379 + to_dpu_hw_pingpong(rt_pp_list[i]); 2380 + cwb_cfg.pp_idx = hw_pp->idx; 2381 + } else { 2382 + cwb_cfg.pp_idx = PINGPONG_NONE; 2383 + } 2384 + 2385 + hw_cwb->ops.config_cwb(hw_cwb, &cwb_cfg); 2386 + 2387 + if (hw_ctl->ops.update_pending_flush_cwb) 2388 + hw_ctl->ops.update_pending_flush_cwb(hw_ctl, hw_cwb->idx); 2389 + } 2321 2390 } 2322 2391 2323 2392 /** ··· 2568 2513 return 0; 2569 2514 } 2570 2515 2516 + /** 2517 + * dpu_encoder_get_clones - Calculate the possible_clones for DPU encoder 2518 + * @drm_enc: DRM encoder pointer 2519 + * Returns: possible_clones mask 2520 + */ 2521 + uint32_t dpu_encoder_get_clones(struct drm_encoder *drm_enc) 2522 + { 2523 + struct drm_encoder *curr; 2524 + int type = drm_enc->encoder_type; 2525 + uint32_t clone_mask = drm_encoder_mask(drm_enc); 2526 + 2527 + /* 2528 + * Set writeback as possible clones of real-time DSI encoders and vice 2529 + * versa 2530 + * 2531 + * Writeback encoders can't be clones of each other and DSI 2532 + * encoders can't be clones of each other. 2533 + * 2534 + * TODO: Add DP encoders as valid possible clones for writeback encoders 2535 + * (and vice versa) once concurrent writeback has been validated for DP 2536 + */ 2537 + drm_for_each_encoder(curr, drm_enc->dev) { 2538 + if ((type == DRM_MODE_ENCODER_VIRTUAL && 2539 + curr->encoder_type == DRM_MODE_ENCODER_DSI) || 2540 + (type == DRM_MODE_ENCODER_DSI && 2541 + curr->encoder_type == DRM_MODE_ENCODER_VIRTUAL)) 2542 + clone_mask |= drm_encoder_mask(curr); 2543 + } 2544 + 2545 + return clone_mask; 2546 + } 2547 + 2571 2548 static int dpu_encoder_setup_display(struct dpu_encoder_virt *dpu_enc, 2572 2549 struct dpu_kms *dpu_kms, 2573 2550 struct msm_display_info *disp_info) ··· 2717 2630 .atomic_mode_set = dpu_encoder_virt_atomic_mode_set, 2718 2631 .atomic_disable = dpu_encoder_virt_atomic_disable, 2719 2632 .atomic_enable = dpu_encoder_virt_atomic_enable, 2720 - .atomic_check = dpu_encoder_virt_atomic_check, 2721 2633 }; 2722 2634 2723 2635 static const struct drm_encoder_funcs dpu_encoder_funcs = { ··· 2872 2786 return dpu_enc->phys_encs[0]->intf_mode; 2873 2787 2874 2788 return INTF_MODE_NONE; 2789 + } 2790 + 2791 + /** 2792 + * dpu_encoder_helper_get_cwb_mask - get CWB blocks mask for the DPU encoder 2793 + * @phys_enc: Pointer to physical encoder structure 2794 + */ 2795 + unsigned int dpu_encoder_helper_get_cwb_mask(struct dpu_encoder_phys *phys_enc) 2796 + { 2797 + struct drm_encoder *encoder = phys_enc->parent; 2798 + struct dpu_encoder_virt *dpu_enc = to_dpu_encoder_virt(encoder); 2799 + 2800 + return dpu_enc->cwb_mask; 2875 2801 } 2876 2802 2877 2803 /**
+11 -1
drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.h
··· 1 1 /* SPDX-License-Identifier: GPL-2.0-only */ 2 2 /* 3 - * Copyright (c) 2022 Qualcomm Innovation Center, Inc. All rights reserved. 3 + * Copyright (c) 2022-2024 Qualcomm Innovation Center, Inc. All rights reserved. 4 4 * Copyright (c) 2015-2018, The Linux Foundation. All rights reserved. 5 5 * Copyright (C) 2013 Red Hat 6 6 * Author: Rob Clark <robdclark@gmail.com> ··· 60 60 61 61 void dpu_encoder_virt_runtime_resume(struct drm_encoder *encoder); 62 62 63 + uint32_t dpu_encoder_get_clones(struct drm_encoder *drm_enc); 64 + 63 65 struct drm_encoder *dpu_encoder_init(struct drm_device *dev, 64 66 int drm_enc_mode, 65 67 struct msm_display_info *disp_info); ··· 82 80 83 81 bool dpu_encoder_use_dsc_merge(struct drm_encoder *drm_enc); 84 82 83 + void dpu_encoder_update_topology(struct drm_encoder *drm_enc, 84 + struct msm_display_topology *topology, 85 + struct drm_atomic_state *state, 86 + const struct drm_display_mode *adj_mode); 87 + 88 + bool dpu_encoder_needs_modeset(struct drm_encoder *drm_enc, struct drm_atomic_state *state); 89 + 85 90 void dpu_encoder_prepare_wb_job(struct drm_encoder *drm_enc, 86 91 struct drm_writeback_job *job); 87 92 ··· 97 88 98 89 bool dpu_encoder_is_valid_for_commit(struct drm_encoder *drm_enc); 99 90 91 + void dpu_encoder_start_frame_done_timer(struct drm_encoder *drm_enc); 100 92 #endif /* __DPU_ENCODER_H__ */
+6 -1
drivers/gpu/drm/msm/disp/dpu1/dpu_encoder_phys.h
··· 1 1 /* SPDX-License-Identifier: GPL-2.0-only */ 2 2 /* 3 - * Copyright (c) 2022 Qualcomm Innovation Center, Inc. All rights reserved. 3 + * Copyright (c) 2022-2024 Qualcomm Innovation Center, Inc. All rights reserved. 4 4 * Copyright (c) 2015-2018 The Linux Foundation. All rights reserved. 5 5 */ 6 6 ··· 309 309 return BLEND_3D_NONE; 310 310 } 311 311 312 + unsigned int dpu_encoder_helper_get_cwb_mask(struct dpu_encoder_phys *phys_enc); 313 + 312 314 unsigned int dpu_encoder_helper_get_dsc(struct dpu_encoder_phys *phys_enc); 313 315 314 316 struct drm_dsc_config *dpu_encoder_get_dsc_config(struct drm_encoder *drm_enc); ··· 332 330 struct dpu_encoder_wait_info *wait_info); 333 331 334 332 void dpu_encoder_helper_phys_cleanup(struct dpu_encoder_phys *phys_enc); 333 + 334 + void dpu_encoder_helper_phys_setup_cwb(struct dpu_encoder_phys *phys_enc, 335 + bool enable); 335 336 336 337 void dpu_encoder_helper_phys_setup_cdm(struct dpu_encoder_phys *phys_enc, 337 338 const struct msm_format *dpu_fmt,
+3 -2
drivers/gpu/drm/msm/disp/dpu1/dpu_encoder_phys_cmd.c
··· 5 5 6 6 #define pr_fmt(fmt) "[drm:%s:%d] " fmt, __func__, __LINE__ 7 7 #include <linux/delay.h> 8 + #include <linux/string_choices.h> 8 9 #include "dpu_encoder_phys.h" 9 10 #include "dpu_hw_interrupts.h" 10 11 #include "dpu_hw_pingpong.h" ··· 262 261 263 262 DRM_DEBUG_KMS("id:%u pp:%d enable=%s/%d\n", DRMID(phys_enc->parent), 264 263 phys_enc->hw_pp->idx - PINGPONG_0, 265 - enable ? "true" : "false", refcount); 264 + str_true_false(enable), refcount); 266 265 267 266 if (enable) { 268 267 if (phys_enc->vblank_refcount == 0) ··· 286 285 DRM_ERROR("vblank irq err id:%u pp:%d ret:%d, enable %s/%d\n", 287 286 DRMID(phys_enc->parent), 288 287 phys_enc->hw_pp->idx - PINGPONG_0, ret, 289 - enable ? "true" : "false", refcount); 288 + str_true_false(enable), refcount); 290 289 } 291 290 292 291 return ret;
+12 -4
drivers/gpu/drm/msm/disp/dpu1/dpu_encoder_phys_wb.c
··· 1 1 // SPDX-License-Identifier: GPL-2.0-only 2 2 /* 3 - * Copyright (c) 2022 Qualcomm Innovation Center, Inc. All rights reserved. 3 + * Copyright (c) 2022-2024 Qualcomm Innovation Center, Inc. All rights reserved. 4 4 */ 5 5 6 6 #define pr_fmt(fmt) "[drm:%s:%d] " fmt, __func__, __LINE__ ··· 68 68 ot_params.num = hw_wb->idx - WB_0; 69 69 ot_params.width = phys_enc->cached_mode.hdisplay; 70 70 ot_params.height = phys_enc->cached_mode.vdisplay; 71 - ot_params.is_wfd = true; 71 + ot_params.is_wfd = !dpu_encoder_helper_get_cwb_mask(phys_enc); 72 72 ot_params.frame_rate = drm_mode_vrefresh(&phys_enc->cached_mode); 73 73 ot_params.vbif_idx = hw_wb->caps->vbif_idx; 74 74 ot_params.rd = false; ··· 111 111 qos_params.vbif_idx = hw_wb->caps->vbif_idx; 112 112 qos_params.xin_id = hw_wb->caps->xin_id; 113 113 qos_params.num = hw_wb->idx - WB_0; 114 - qos_params.is_rt = false; 114 + qos_params.is_rt = dpu_encoder_helper_get_cwb_mask(phys_enc); 115 115 116 116 DPU_DEBUG("[qos_remap] wb:%d vbif:%d xin:%d is_rt:%d\n", 117 117 qos_params.num, ··· 174 174 struct dpu_encoder_phys_wb *wb_enc = to_dpu_encoder_phys_wb(phys_enc); 175 175 struct dpu_hw_wb *hw_wb; 176 176 struct dpu_hw_wb_cfg *wb_cfg; 177 + u32 cdp_usage; 177 178 178 179 if (!phys_enc || !phys_enc->dpu_kms || !phys_enc->dpu_kms->catalog) { 179 180 DPU_ERROR("invalid encoder\n"); ··· 183 182 184 183 hw_wb = phys_enc->hw_wb; 185 184 wb_cfg = &wb_enc->wb_cfg; 185 + if (dpu_encoder_helper_get_cwb_mask(phys_enc)) 186 + cdp_usage = DPU_PERF_CDP_USAGE_RT; 187 + else 188 + cdp_usage = DPU_PERF_CDP_USAGE_NRT; 186 189 187 190 wb_cfg->intf_mode = phys_enc->intf_mode; 188 191 wb_cfg->roi.x1 = 0; ··· 204 199 const struct dpu_perf_cfg *perf = phys_enc->dpu_kms->catalog->perf; 205 200 206 201 hw_wb->ops.setup_cdp(hw_wb, format, 207 - perf->cdp_cfg[DPU_PERF_CDP_USAGE_NRT].wr_enable); 202 + perf->cdp_cfg[cdp_usage].wr_enable); 208 203 } 209 204 210 205 if (hw_wb->ops.setup_outaddress) ··· 241 236 242 237 intf_cfg.intf = DPU_NONE; 243 238 intf_cfg.wb = hw_wb->idx; 239 + intf_cfg.cwb = dpu_encoder_helper_get_cwb_mask(phys_enc); 244 240 245 241 if (mode_3d && hw_pp && hw_pp->merge_3d) 246 242 intf_cfg.merge_3d = hw_pp->merge_3d->idx; ··· 345 339 dpu_encoder_phys_wb_setup_fb(phys_enc, format); 346 340 347 341 dpu_encoder_helper_phys_setup_cdm(phys_enc, format, CDM_CDWN_OUTPUT_WB); 342 + 343 + dpu_encoder_helper_phys_setup_cwb(phys_enc, true); 348 344 349 345 dpu_encoder_phys_wb_setup_ctl(phys_enc); 350 346 }
+8 -32
drivers/gpu/drm/msm/disp/dpu1/dpu_hw_catalog.c
··· 232 232 /* TODO add formats after validation */ 233 233 }; 234 234 235 - static const u32 wb2_formats_rgb[] = { 236 - DRM_FORMAT_RGB565, 237 - DRM_FORMAT_BGR565, 238 - DRM_FORMAT_RGB888, 239 - DRM_FORMAT_ARGB8888, 240 - DRM_FORMAT_RGBA8888, 241 - DRM_FORMAT_ABGR8888, 242 - DRM_FORMAT_XRGB8888, 243 - DRM_FORMAT_RGBX8888, 244 - DRM_FORMAT_XBGR8888, 245 - DRM_FORMAT_ARGB1555, 246 - DRM_FORMAT_RGBA5551, 247 - DRM_FORMAT_XRGB1555, 248 - DRM_FORMAT_RGBX5551, 249 - DRM_FORMAT_ARGB4444, 250 - DRM_FORMAT_RGBA4444, 251 - DRM_FORMAT_RGBX4444, 252 - DRM_FORMAT_XRGB4444, 253 - DRM_FORMAT_BGR888, 254 - DRM_FORMAT_BGRA8888, 255 - DRM_FORMAT_BGRX8888, 256 - DRM_FORMAT_ABGR1555, 257 - DRM_FORMAT_BGRA5551, 258 - DRM_FORMAT_XBGR1555, 259 - DRM_FORMAT_BGRX5551, 260 - DRM_FORMAT_ABGR4444, 261 - DRM_FORMAT_BGRA4444, 262 - DRM_FORMAT_BGRX4444, 263 - DRM_FORMAT_XBGR4444, 264 - }; 265 - 266 235 static const u32 wb2_formats_rgb_yuv[] = { 267 236 DRM_FORMAT_RGB565, 268 237 DRM_FORMAT_BGR565, ··· 476 507 /************************************************************* 477 508 * CDM block config 478 509 *************************************************************/ 479 - static const struct dpu_cdm_cfg sc7280_cdm = { 510 + static const struct dpu_cdm_cfg dpu_cdm_1_x_4_x = { 511 + .name = "cdm_0", 512 + .id = CDM_0, 513 + .len = 0x224, 514 + .base = 0x79200, 515 + }; 516 + 517 + static const struct dpu_cdm_cfg dpu_cdm_5_x = { 480 518 .name = "cdm_0", 481 519 .id = CDM_0, 482 520 .len = 0x228,
+3 -1
drivers/gpu/drm/msm/disp/dpu1/dpu_hw_cdm.c
··· 214 214 mux_cfg = DPU_REG_READ(c, CDM_MUX); 215 215 mux_cfg &= ~0xf; 216 216 217 - if (pp) 217 + if (pp >= PINGPONG_CWB_0) 218 + mux_cfg |= 0xd; 219 + else if (pp) 218 220 mux_cfg |= (pp - PINGPONG_0) & 0x7; 219 221 else 220 222 mux_cfg |= 0xf;
+29 -1
drivers/gpu/drm/msm/disp/dpu1/dpu_hw_ctl.c
··· 1 1 // SPDX-License-Identifier: GPL-2.0-only 2 2 /* Copyright (c) 2015-2018, The Linux Foundation. All rights reserved. 3 - * Copyright (c) 2022 Qualcomm Innovation Center, Inc. All rights reserved. 3 + * Copyright (c) 2022-2024 Qualcomm Innovation Center, Inc. All rights reserved. 4 4 */ 5 5 6 6 #include <linux/delay.h> ··· 31 31 #define CTL_MERGE_3D_ACTIVE 0x0E4 32 32 #define CTL_DSC_ACTIVE 0x0E8 33 33 #define CTL_WB_ACTIVE 0x0EC 34 + #define CTL_CWB_ACTIVE 0x0F0 34 35 #define CTL_INTF_ACTIVE 0x0F4 35 36 #define CTL_CDM_ACTIVE 0x0F8 36 37 #define CTL_FETCH_PIPE_ACTIVE 0x0FC 37 38 #define CTL_MERGE_3D_FLUSH 0x100 38 39 #define CTL_DSC_FLUSH 0x104 39 40 #define CTL_WB_FLUSH 0x108 41 + #define CTL_CWB_FLUSH 0x10C 40 42 #define CTL_INTF_FLUSH 0x110 41 43 #define CTL_CDM_FLUSH 0x114 42 44 #define CTL_PERIPH_FLUSH 0x128 ··· 55 53 #define PERIPH_IDX 30 56 54 #define INTF_IDX 31 57 55 #define WB_IDX 16 56 + #define CWB_IDX 28 58 57 #define DSPP_IDX 29 /* From DPU hw rev 7.x.x */ 59 58 #define CTL_INVALID_BIT 0xffff 60 59 #define CTL_DEFAULT_GROUP_ID 0xf ··· 113 110 ctx->pending_flush_mask = 0x0; 114 111 ctx->pending_intf_flush_mask = 0; 115 112 ctx->pending_wb_flush_mask = 0; 113 + ctx->pending_cwb_flush_mask = 0; 116 114 ctx->pending_merge_3d_flush_mask = 0; 117 115 ctx->pending_dsc_flush_mask = 0; 118 116 ctx->pending_cdm_flush_mask = 0; ··· 148 144 if (ctx->pending_flush_mask & BIT(WB_IDX)) 149 145 DPU_REG_WRITE(&ctx->hw, CTL_WB_FLUSH, 150 146 ctx->pending_wb_flush_mask); 147 + if (ctx->pending_flush_mask & BIT(CWB_IDX)) 148 + DPU_REG_WRITE(&ctx->hw, CTL_CWB_FLUSH, 149 + ctx->pending_cwb_flush_mask); 151 150 152 151 if (ctx->pending_flush_mask & BIT(DSPP_IDX)) 153 152 for (dspp = DSPP_0; dspp < DSPP_MAX; dspp++) { ··· 315 308 { 316 309 ctx->pending_wb_flush_mask |= BIT(wb - WB_0); 317 310 ctx->pending_flush_mask |= BIT(WB_IDX); 311 + } 312 + 313 + static void dpu_hw_ctl_update_pending_flush_cwb_v1(struct dpu_hw_ctl *ctx, 314 + enum dpu_cwb cwb) 315 + { 316 + ctx->pending_cwb_flush_mask |= BIT(cwb - CWB_0); 317 + ctx->pending_flush_mask |= BIT(CWB_IDX); 318 318 } 319 319 320 320 static void dpu_hw_ctl_update_pending_flush_intf_v1(struct dpu_hw_ctl *ctx, ··· 561 547 u32 intf_active = 0; 562 548 u32 dsc_active = 0; 563 549 u32 wb_active = 0; 550 + u32 cwb_active = 0; 564 551 u32 mode_sel = 0; 565 552 566 553 /* CTL_TOP[31:28] carries group_id to collate CTL paths ··· 576 561 577 562 intf_active = DPU_REG_READ(c, CTL_INTF_ACTIVE); 578 563 wb_active = DPU_REG_READ(c, CTL_WB_ACTIVE); 564 + cwb_active = DPU_REG_READ(c, CTL_CWB_ACTIVE); 579 565 dsc_active = DPU_REG_READ(c, CTL_DSC_ACTIVE); 580 566 581 567 if (cfg->intf) ··· 585 569 if (cfg->wb) 586 570 wb_active |= BIT(cfg->wb - WB_0); 587 571 572 + if (cfg->cwb) 573 + cwb_active |= cfg->cwb; 574 + 588 575 if (cfg->dsc) 589 576 dsc_active |= cfg->dsc; 590 577 591 578 DPU_REG_WRITE(c, CTL_TOP, mode_sel); 592 579 DPU_REG_WRITE(c, CTL_INTF_ACTIVE, intf_active); 593 580 DPU_REG_WRITE(c, CTL_WB_ACTIVE, wb_active); 581 + DPU_REG_WRITE(c, CTL_CWB_ACTIVE, cwb_active); 594 582 DPU_REG_WRITE(c, CTL_DSC_ACTIVE, dsc_active); 595 583 596 584 if (cfg->merge_3d) ··· 644 624 struct dpu_hw_blk_reg_map *c = &ctx->hw; 645 625 u32 intf_active = 0; 646 626 u32 wb_active = 0; 627 + u32 cwb_active = 0; 647 628 u32 merge3d_active = 0; 648 629 u32 dsc_active; 649 630 u32 cdm_active; ··· 670 649 intf_active = DPU_REG_READ(c, CTL_INTF_ACTIVE); 671 650 intf_active &= ~BIT(cfg->intf - INTF_0); 672 651 DPU_REG_WRITE(c, CTL_INTF_ACTIVE, intf_active); 652 + } 653 + 654 + if (cfg->cwb) { 655 + cwb_active = DPU_REG_READ(c, CTL_CWB_ACTIVE); 656 + cwb_active &= ~cfg->cwb; 657 + DPU_REG_WRITE(c, CTL_CWB_ACTIVE, cwb_active); 673 658 } 674 659 675 660 if (cfg->wb) { ··· 730 703 ops->update_pending_flush_merge_3d = 731 704 dpu_hw_ctl_update_pending_flush_merge_3d_v1; 732 705 ops->update_pending_flush_wb = dpu_hw_ctl_update_pending_flush_wb_v1; 706 + ops->update_pending_flush_cwb = dpu_hw_ctl_update_pending_flush_cwb_v1; 733 707 ops->update_pending_flush_dsc = 734 708 dpu_hw_ctl_update_pending_flush_dsc_v1; 735 709 ops->update_pending_flush_cdm = dpu_hw_ctl_update_pending_flush_cdm_v1;
+14 -1
drivers/gpu/drm/msm/disp/dpu1/dpu_hw_ctl.h
··· 1 1 /* SPDX-License-Identifier: GPL-2.0-only */ 2 2 /* Copyright (c) 2015-2018, The Linux Foundation. All rights reserved. 3 - * Copyright (c) 2022 Qualcomm Innovation Center, Inc. All rights reserved. 3 + * Copyright (c) 2022-2024 Qualcomm Innovation Center, Inc. All rights reserved. 4 4 */ 5 5 6 6 #ifndef _DPU_HW_CTL_H ··· 42 42 * @cdm: CDM block used 43 43 * @stream_sel: Stream selection for multi-stream interfaces 44 44 * @dsc: DSC BIT masks used 45 + * @cwb: CWB BIT masks used 45 46 */ 46 47 struct dpu_hw_intf_cfg { 47 48 enum dpu_intf intf; ··· 52 51 enum dpu_ctl_mode_sel intf_mode_sel; 53 52 enum dpu_cdm cdm; 54 53 int stream_sel; 54 + unsigned int cwb; 55 55 unsigned int dsc; 56 56 }; 57 57 ··· 115 113 */ 116 114 void (*update_pending_flush_wb)(struct dpu_hw_ctl *ctx, 117 115 enum dpu_wb blk); 116 + 117 + /** 118 + * OR in the given flushbits to the cached pending_(cwb_)flush_mask 119 + * No effect on hardware 120 + * @ctx : ctl path ctx pointer 121 + * @blk : concurrent writeback block index 122 + */ 123 + void (*update_pending_flush_cwb)(struct dpu_hw_ctl *ctx, 124 + enum dpu_cwb blk); 118 125 119 126 /** 120 127 * OR in the given flushbits to the cached pending_(intf_)flush_mask ··· 269 258 * @pending_flush_mask: storage for pending ctl_flush managed via ops 270 259 * @pending_intf_flush_mask: pending INTF flush 271 260 * @pending_wb_flush_mask: pending WB flush 261 + * @pending_cwb_flush_mask: pending CWB flush 272 262 * @pending_dsc_flush_mask: pending DSC flush 273 263 * @pending_cdm_flush_mask: pending CDM flush 274 264 * @ops: operation list ··· 286 274 u32 pending_flush_mask; 287 275 u32 pending_intf_flush_mask; 288 276 u32 pending_wb_flush_mask; 277 + u32 pending_cwb_flush_mask; 289 278 u32 pending_periph_flush_mask; 290 279 u32 pending_merge_3d_flush_mask; 291 280 u32 pending_dspp_flush_mask[DSPP_MAX - DSPP_0];
+2
drivers/gpu/drm/msm/disp/dpu1/dpu_hw_mdss.h
··· 77 77 DPU_HW_BLK_LM, 78 78 DPU_HW_BLK_CTL, 79 79 DPU_HW_BLK_PINGPONG, 80 + DPU_HW_BLK_DCWB_PINGPONG, 80 81 DPU_HW_BLK_INTF, 81 82 DPU_HW_BLK_WB, 82 83 DPU_HW_BLK_DSPP, 83 84 DPU_HW_BLK_MERGE_3D, 84 85 DPU_HW_BLK_DSC, 85 86 DPU_HW_BLK_CDM, 87 + DPU_HW_BLK_CWB, 86 88 DPU_HW_BLK_MAX, 87 89 }; 88 90
+19 -2
drivers/gpu/drm/msm/disp/dpu1/dpu_kms.c
··· 2 2 /* 3 3 * Copyright (C) 2013 Red Hat 4 4 * Copyright (c) 2014-2018, The Linux Foundation. All rights reserved. 5 - * Copyright (c) 2022 Qualcomm Innovation Center, Inc. All rights reserved. 5 + * Copyright (c) 2022-2024 Qualcomm Innovation Center, Inc. All rights reserved. 6 6 * 7 7 * Author: Rob Clark <robdclark@gmail.com> 8 8 */ ··· 446 446 pm_runtime_put_sync(&dpu_kms->pdev->dev); 447 447 } 448 448 449 + static int dpu_kms_check_mode_changed(struct msm_kms *kms, struct drm_atomic_state *state) 450 + { 451 + struct drm_crtc_state *new_crtc_state; 452 + struct drm_crtc_state *old_crtc_state; 453 + struct drm_crtc *crtc; 454 + int i; 455 + 456 + for_each_oldnew_crtc_in_state(state, crtc, old_crtc_state, new_crtc_state, i) 457 + dpu_crtc_check_mode_changed(old_crtc_state, new_crtc_state); 458 + 459 + return 0; 460 + } 461 + 449 462 static void dpu_kms_flush_commit(struct msm_kms *kms, unsigned crtc_mask) 450 463 { 451 464 struct dpu_kms *dpu_kms = to_dpu_kms(kms); ··· 824 811 return ret; 825 812 826 813 num_encoders = 0; 827 - drm_for_each_encoder(encoder, dev) 814 + drm_for_each_encoder(encoder, dev) { 828 815 num_encoders++; 816 + if (catalog->cwb_count > 0) 817 + encoder->possible_clones = dpu_encoder_get_clones(encoder); 818 + } 829 819 830 820 max_crtc_count = min(catalog->mixer_count, num_encoders); 831 821 ··· 1078 1062 .irq = dpu_core_irq, 1079 1063 .enable_commit = dpu_kms_enable_commit, 1080 1064 .disable_commit = dpu_kms_disable_commit, 1065 + .check_mode_changed = dpu_kms_check_mode_changed, 1081 1066 .flush_commit = dpu_kms_flush_commit, 1082 1067 .wait_flush = dpu_kms_wait_flush, 1083 1068 .complete_commit = dpu_kms_complete_commit,
+7 -6
drivers/gpu/drm/msm/disp/dpu1/dpu_kms.h
··· 124 124 125 125 struct dpu_rm *rm; 126 126 127 - uint32_t pingpong_to_enc_id[PINGPONG_MAX - PINGPONG_0]; 128 - uint32_t mixer_to_enc_id[LM_MAX - LM_0]; 129 - uint32_t ctl_to_enc_id[CTL_MAX - CTL_0]; 130 - uint32_t dspp_to_enc_id[DSPP_MAX - DSPP_0]; 131 - uint32_t dsc_to_enc_id[DSC_MAX - DSC_0]; 132 - uint32_t cdm_to_enc_id; 127 + uint32_t pingpong_to_crtc_id[PINGPONG_MAX - PINGPONG_0]; 128 + uint32_t mixer_to_crtc_id[LM_MAX - LM_0]; 129 + uint32_t ctl_to_crtc_id[CTL_MAX - CTL_0]; 130 + uint32_t dspp_to_crtc_id[DSPP_MAX - DSPP_0]; 131 + uint32_t dsc_to_crtc_id[DSC_MAX - DSC_0]; 132 + uint32_t cdm_to_crtc_id; 133 133 134 134 uint32_t sspp_to_crtc_id[SSPP_MAX - SSPP_NONE]; 135 + uint32_t cwb_to_crtc_id[CWB_MAX - CWB_0]; 135 136 }; 136 137 137 138 struct dpu_global_state
+197 -101
drivers/gpu/drm/msm/disp/dpu1/dpu_rm.c
··· 22 22 23 23 24 24 static inline bool reserved_by_other(uint32_t *res_map, int idx, 25 - uint32_t enc_id) 25 + uint32_t crtc_id) 26 26 { 27 - return res_map[idx] && res_map[idx] != enc_id; 27 + return res_map[idx] && res_map[idx] != crtc_id; 28 28 } 29 29 30 30 /** ··· 233 233 return -EINVAL; 234 234 } 235 235 236 + static int _dpu_rm_reserve_cwb_mux_and_pingpongs(struct dpu_rm *rm, 237 + struct dpu_global_state *global_state, 238 + uint32_t crtc_id, 239 + struct msm_display_topology *topology) 240 + { 241 + int num_cwb_mux = topology->num_lm, cwb_mux_count = 0; 242 + int cwb_pp_start_idx = PINGPONG_CWB_0 - PINGPONG_0; 243 + int cwb_pp_idx[MAX_BLOCKS]; 244 + int cwb_mux_idx[MAX_BLOCKS]; 245 + 246 + /* 247 + * Reserve additional dedicated CWB PINGPONG blocks and muxes for each 248 + * mixer 249 + * 250 + * TODO: add support reserving resources for platforms with no 251 + * PINGPONG_CWB 252 + */ 253 + for (int i = 0; i < ARRAY_SIZE(rm->mixer_blks) && 254 + cwb_mux_count < num_cwb_mux; i++) { 255 + for (int j = 0; j < ARRAY_SIZE(rm->cwb_blks); j++) { 256 + /* 257 + * Odd LMs must be assigned to odd CWB muxes and even 258 + * LMs with even CWB muxes. 259 + * 260 + * Since the RM HW block array index is based on the HW 261 + * block ids, we can also use the array index to enforce 262 + * the odd/even rule. See dpu_rm_init() for more 263 + * information 264 + */ 265 + if (reserved_by_other(global_state->cwb_to_crtc_id, j, crtc_id) || 266 + i % 2 != j % 2) 267 + continue; 268 + 269 + cwb_mux_idx[cwb_mux_count] = j; 270 + cwb_pp_idx[cwb_mux_count] = j + cwb_pp_start_idx; 271 + cwb_mux_count++; 272 + break; 273 + } 274 + } 275 + 276 + if (cwb_mux_count != num_cwb_mux) { 277 + DPU_ERROR("Unable to reserve all CWB PINGPONGs\n"); 278 + return -ENAVAIL; 279 + } 280 + 281 + for (int i = 0; i < cwb_mux_count; i++) { 282 + global_state->pingpong_to_crtc_id[cwb_pp_idx[i]] = crtc_id; 283 + global_state->cwb_to_crtc_id[cwb_mux_idx[i]] = crtc_id; 284 + } 285 + 286 + return 0; 287 + } 288 + 236 289 /** 237 290 * _dpu_rm_check_lm_and_get_connected_blks - check if proposed layer mixer meets 238 291 * proposed use case requirements, incl. hardwired dependent blocks like 239 292 * pingpong 240 293 * @rm: dpu resource manager handle 241 294 * @global_state: resources shared across multiple kms objects 242 - * @enc_id: encoder id requesting for allocation 295 + * @crtc_id: crtc id requesting for allocation 243 296 * @lm_idx: index of proposed layer mixer in rm->mixer_blks[], function checks 244 297 * if lm, and all other hardwired blocks connected to the lm (pp) is 245 298 * available and appropriate ··· 305 252 */ 306 253 static bool _dpu_rm_check_lm_and_get_connected_blks(struct dpu_rm *rm, 307 254 struct dpu_global_state *global_state, 308 - uint32_t enc_id, int lm_idx, int *pp_idx, int *dspp_idx, 255 + uint32_t crtc_id, int lm_idx, int *pp_idx, int *dspp_idx, 309 256 struct msm_display_topology *topology) 310 257 { 311 258 const struct dpu_lm_cfg *lm_cfg; 312 259 int idx; 313 260 314 261 /* Already reserved? */ 315 - if (reserved_by_other(global_state->mixer_to_enc_id, lm_idx, enc_id)) { 262 + if (reserved_by_other(global_state->mixer_to_crtc_id, lm_idx, crtc_id)) { 316 263 DPU_DEBUG("lm %d already reserved\n", lm_idx + LM_0); 317 264 return false; 318 265 } ··· 324 271 return false; 325 272 } 326 273 327 - if (reserved_by_other(global_state->pingpong_to_enc_id, idx, enc_id)) { 274 + if (reserved_by_other(global_state->pingpong_to_crtc_id, idx, crtc_id)) { 328 275 DPU_DEBUG("lm %d pp %d already reserved\n", lm_cfg->id, 329 276 lm_cfg->pingpong); 330 277 return false; ··· 340 287 return false; 341 288 } 342 289 343 - if (reserved_by_other(global_state->dspp_to_enc_id, idx, enc_id)) { 290 + if (reserved_by_other(global_state->dspp_to_crtc_id, idx, crtc_id)) { 344 291 DPU_DEBUG("lm %d dspp %d already reserved\n", lm_cfg->id, 345 292 lm_cfg->dspp); 346 293 return false; ··· 352 299 353 300 static int _dpu_rm_reserve_lms(struct dpu_rm *rm, 354 301 struct dpu_global_state *global_state, 355 - uint32_t enc_id, 302 + uint32_t crtc_id, 356 303 struct msm_display_topology *topology) 357 304 358 305 { ··· 376 323 lm_idx[lm_count] = i; 377 324 378 325 if (!_dpu_rm_check_lm_and_get_connected_blks(rm, global_state, 379 - enc_id, i, &pp_idx[lm_count], 326 + crtc_id, i, &pp_idx[lm_count], 380 327 &dspp_idx[lm_count], topology)) { 381 328 continue; 382 329 } ··· 395 342 continue; 396 343 397 344 if (!_dpu_rm_check_lm_and_get_connected_blks(rm, 398 - global_state, enc_id, j, 345 + global_state, crtc_id, j, 399 346 &pp_idx[lm_count], &dspp_idx[lm_count], 400 347 topology)) { 401 348 continue; ··· 412 359 } 413 360 414 361 for (i = 0; i < lm_count; i++) { 415 - global_state->mixer_to_enc_id[lm_idx[i]] = enc_id; 416 - global_state->pingpong_to_enc_id[pp_idx[i]] = enc_id; 417 - global_state->dspp_to_enc_id[dspp_idx[i]] = 418 - topology->num_dspp ? enc_id : 0; 362 + global_state->mixer_to_crtc_id[lm_idx[i]] = crtc_id; 363 + global_state->pingpong_to_crtc_id[pp_idx[i]] = crtc_id; 364 + global_state->dspp_to_crtc_id[dspp_idx[i]] = 365 + topology->num_dspp ? crtc_id : 0; 419 366 420 - trace_dpu_rm_reserve_lms(lm_idx[i] + LM_0, enc_id, 367 + trace_dpu_rm_reserve_lms(lm_idx[i] + LM_0, crtc_id, 421 368 pp_idx[i] + PINGPONG_0); 422 369 } 423 370 ··· 427 374 static int _dpu_rm_reserve_ctls( 428 375 struct dpu_rm *rm, 429 376 struct dpu_global_state *global_state, 430 - uint32_t enc_id, 377 + uint32_t crtc_id, 431 378 const struct msm_display_topology *top) 432 379 { 433 380 int ctl_idx[MAX_BLOCKS]; 434 381 int i = 0, j, num_ctls; 435 382 bool needs_split_display; 436 383 437 - /* each hw_intf needs its own hw_ctrl to program its control path */ 438 - num_ctls = top->num_intf; 384 + /* 385 + * For non-CWB mode, each hw_intf needs its own hw_ctl to program its 386 + * control path. 387 + * 388 + * Hardcode num_ctls to 1 if CWB is enabled because in CWB, both the 389 + * writeback and real-time encoders must be driven by the same control 390 + * path 391 + */ 392 + if (top->cwb_enabled) 393 + num_ctls = 1; 394 + else 395 + num_ctls = top->num_intf; 439 396 440 397 needs_split_display = _dpu_rm_needs_split_display(top); 441 398 ··· 456 393 457 394 if (!rm->ctl_blks[j]) 458 395 continue; 459 - if (reserved_by_other(global_state->ctl_to_enc_id, j, enc_id)) 396 + if (reserved_by_other(global_state->ctl_to_crtc_id, j, crtc_id)) 460 397 continue; 461 398 462 399 ctl = to_dpu_hw_ctl(rm->ctl_blks[j]); ··· 480 417 return -ENAVAIL; 481 418 482 419 for (i = 0; i < ARRAY_SIZE(ctl_idx) && i < num_ctls; i++) { 483 - global_state->ctl_to_enc_id[ctl_idx[i]] = enc_id; 484 - trace_dpu_rm_reserve_ctls(i + CTL_0, enc_id); 420 + global_state->ctl_to_crtc_id[ctl_idx[i]] = crtc_id; 421 + trace_dpu_rm_reserve_ctls(i + CTL_0, crtc_id); 485 422 } 486 423 487 424 return 0; ··· 489 426 490 427 static int _dpu_rm_pingpong_next_index(struct dpu_global_state *global_state, 491 428 int start, 492 - uint32_t enc_id) 429 + uint32_t crtc_id) 493 430 { 494 431 int i; 495 432 496 433 for (i = start; i < (PINGPONG_MAX - PINGPONG_0); i++) { 497 - if (global_state->pingpong_to_enc_id[i] == enc_id) 434 + if (global_state->pingpong_to_crtc_id[i] == crtc_id) 498 435 return i; 499 436 } 500 437 ··· 515 452 516 453 static int _dpu_rm_dsc_alloc(struct dpu_rm *rm, 517 454 struct dpu_global_state *global_state, 518 - uint32_t enc_id, 455 + uint32_t crtc_id, 519 456 const struct msm_display_topology *top) 520 457 { 521 458 int num_dsc = 0; ··· 528 465 if (!rm->dsc_blks[dsc_idx]) 529 466 continue; 530 467 531 - if (reserved_by_other(global_state->dsc_to_enc_id, dsc_idx, enc_id)) 468 + if (reserved_by_other(global_state->dsc_to_crtc_id, dsc_idx, crtc_id)) 532 469 continue; 533 470 534 - pp_idx = _dpu_rm_pingpong_next_index(global_state, pp_idx, enc_id); 471 + pp_idx = _dpu_rm_pingpong_next_index(global_state, pp_idx, crtc_id); 535 472 if (pp_idx < 0) 536 473 return -ENAVAIL; 537 474 ··· 539 476 if (ret) 540 477 return -ENAVAIL; 541 478 542 - global_state->dsc_to_enc_id[dsc_idx] = enc_id; 479 + global_state->dsc_to_crtc_id[dsc_idx] = crtc_id; 543 480 num_dsc++; 544 481 pp_idx++; 545 482 } ··· 555 492 556 493 static int _dpu_rm_dsc_alloc_pair(struct dpu_rm *rm, 557 494 struct dpu_global_state *global_state, 558 - uint32_t enc_id, 495 + uint32_t crtc_id, 559 496 const struct msm_display_topology *top) 560 497 { 561 498 int num_dsc = 0; ··· 570 507 continue; 571 508 572 509 /* consective dsc index to be paired */ 573 - if (reserved_by_other(global_state->dsc_to_enc_id, dsc_idx, enc_id) || 574 - reserved_by_other(global_state->dsc_to_enc_id, dsc_idx + 1, enc_id)) 510 + if (reserved_by_other(global_state->dsc_to_crtc_id, dsc_idx, crtc_id) || 511 + reserved_by_other(global_state->dsc_to_crtc_id, dsc_idx + 1, crtc_id)) 575 512 continue; 576 513 577 - pp_idx = _dpu_rm_pingpong_next_index(global_state, pp_idx, enc_id); 514 + pp_idx = _dpu_rm_pingpong_next_index(global_state, pp_idx, crtc_id); 578 515 if (pp_idx < 0) 579 516 return -ENAVAIL; 580 517 ··· 584 521 continue; 585 522 } 586 523 587 - pp_idx = _dpu_rm_pingpong_next_index(global_state, pp_idx + 1, enc_id); 524 + pp_idx = _dpu_rm_pingpong_next_index(global_state, pp_idx + 1, crtc_id); 588 525 if (pp_idx < 0) 589 526 return -ENAVAIL; 590 527 ··· 594 531 continue; 595 532 } 596 533 597 - global_state->dsc_to_enc_id[dsc_idx] = enc_id; 598 - global_state->dsc_to_enc_id[dsc_idx + 1] = enc_id; 534 + global_state->dsc_to_crtc_id[dsc_idx] = crtc_id; 535 + global_state->dsc_to_crtc_id[dsc_idx + 1] = crtc_id; 599 536 num_dsc += 2; 600 537 pp_idx++; /* start for next pair */ 601 538 } ··· 611 548 612 549 static int _dpu_rm_reserve_dsc(struct dpu_rm *rm, 613 550 struct dpu_global_state *global_state, 614 - struct drm_encoder *enc, 551 + uint32_t crtc_id, 615 552 const struct msm_display_topology *top) 616 553 { 617 - uint32_t enc_id = enc->base.id; 618 - 619 554 if (!top->num_dsc || !top->num_intf) 620 555 return 0; 621 556 ··· 629 568 630 569 /* num_dsc should be either 1, 2 or 4 */ 631 570 if (top->num_dsc > top->num_intf) /* merge mode */ 632 - return _dpu_rm_dsc_alloc_pair(rm, global_state, enc_id, top); 571 + return _dpu_rm_dsc_alloc_pair(rm, global_state, crtc_id, top); 633 572 else 634 - return _dpu_rm_dsc_alloc(rm, global_state, enc_id, top); 573 + return _dpu_rm_dsc_alloc(rm, global_state, crtc_id, top); 635 574 636 575 return 0; 637 576 } 638 577 639 578 static int _dpu_rm_reserve_cdm(struct dpu_rm *rm, 640 579 struct dpu_global_state *global_state, 641 - struct drm_encoder *enc) 580 + uint32_t crtc_id, 581 + int num_cdm) 642 582 { 643 583 /* try allocating only one CDM block */ 644 584 if (!rm->cdm_blk) { ··· 647 585 return -EIO; 648 586 } 649 587 650 - if (global_state->cdm_to_enc_id) { 588 + if (num_cdm > 1) { 589 + DPU_ERROR("More than 1 INTF requesting CDM\n"); 590 + return -EINVAL; 591 + } 592 + 593 + if (global_state->cdm_to_crtc_id) { 651 594 DPU_ERROR("CDM_0 is already allocated\n"); 652 595 return -EIO; 653 596 } 654 597 655 - global_state->cdm_to_enc_id = enc->base.id; 598 + global_state->cdm_to_crtc_id = crtc_id; 656 599 657 600 return 0; 658 601 } ··· 665 598 static int _dpu_rm_make_reservation( 666 599 struct dpu_rm *rm, 667 600 struct dpu_global_state *global_state, 668 - struct drm_encoder *enc, 601 + uint32_t crtc_id, 669 602 struct msm_display_topology *topology) 670 603 { 671 604 int ret; 672 605 673 - ret = _dpu_rm_reserve_lms(rm, global_state, enc->base.id, topology); 606 + ret = _dpu_rm_reserve_lms(rm, global_state, crtc_id, topology); 674 607 if (ret) { 675 608 DPU_ERROR("unable to find appropriate mixers\n"); 676 609 return ret; 677 610 } 678 611 679 - ret = _dpu_rm_reserve_ctls(rm, global_state, enc->base.id, 612 + if (topology->cwb_enabled) { 613 + ret = _dpu_rm_reserve_cwb_mux_and_pingpongs(rm, global_state, 614 + crtc_id, topology); 615 + if (ret) 616 + return ret; 617 + } 618 + 619 + ret = _dpu_rm_reserve_ctls(rm, global_state, crtc_id, 680 620 topology); 681 621 if (ret) { 682 622 DPU_ERROR("unable to find appropriate CTL\n"); 683 623 return ret; 684 624 } 685 625 686 - ret = _dpu_rm_reserve_dsc(rm, global_state, enc, topology); 626 + ret = _dpu_rm_reserve_dsc(rm, global_state, crtc_id, topology); 687 627 if (ret) 688 628 return ret; 689 629 690 - if (topology->needs_cdm) { 691 - ret = _dpu_rm_reserve_cdm(rm, global_state, enc); 630 + if (topology->num_cdm > 0) { 631 + ret = _dpu_rm_reserve_cdm(rm, global_state, crtc_id, topology->num_cdm); 692 632 if (ret) { 693 633 DPU_ERROR("unable to find CDM blk\n"); 694 634 return ret; ··· 706 632 } 707 633 708 634 static void _dpu_rm_clear_mapping(uint32_t *res_mapping, int cnt, 709 - uint32_t enc_id) 635 + uint32_t crtc_id) 710 636 { 711 637 int i; 712 638 713 639 for (i = 0; i < cnt; i++) { 714 - if (res_mapping[i] == enc_id) 640 + if (res_mapping[i] == crtc_id) 715 641 res_mapping[i] = 0; 716 642 } 717 643 } ··· 720 646 * dpu_rm_release - Given the encoder for the display chain, release any 721 647 * HW blocks previously reserved for that use case. 722 648 * @global_state: resources shared across multiple kms objects 723 - * @enc: DRM Encoder handle 649 + * @crtc: DRM CRTC handle 724 650 * @return: 0 on Success otherwise -ERROR 725 651 */ 726 652 void dpu_rm_release(struct dpu_global_state *global_state, 727 - struct drm_encoder *enc) 653 + struct drm_crtc *crtc) 728 654 { 729 - _dpu_rm_clear_mapping(global_state->pingpong_to_enc_id, 730 - ARRAY_SIZE(global_state->pingpong_to_enc_id), enc->base.id); 731 - _dpu_rm_clear_mapping(global_state->mixer_to_enc_id, 732 - ARRAY_SIZE(global_state->mixer_to_enc_id), enc->base.id); 733 - _dpu_rm_clear_mapping(global_state->ctl_to_enc_id, 734 - ARRAY_SIZE(global_state->ctl_to_enc_id), enc->base.id); 735 - _dpu_rm_clear_mapping(global_state->dsc_to_enc_id, 736 - ARRAY_SIZE(global_state->dsc_to_enc_id), enc->base.id); 737 - _dpu_rm_clear_mapping(global_state->dspp_to_enc_id, 738 - ARRAY_SIZE(global_state->dspp_to_enc_id), enc->base.id); 739 - _dpu_rm_clear_mapping(&global_state->cdm_to_enc_id, 1, enc->base.id); 655 + uint32_t crtc_id = crtc->base.id; 656 + 657 + _dpu_rm_clear_mapping(global_state->pingpong_to_crtc_id, 658 + ARRAY_SIZE(global_state->pingpong_to_crtc_id), crtc_id); 659 + _dpu_rm_clear_mapping(global_state->mixer_to_crtc_id, 660 + ARRAY_SIZE(global_state->mixer_to_crtc_id), crtc_id); 661 + _dpu_rm_clear_mapping(global_state->ctl_to_crtc_id, 662 + ARRAY_SIZE(global_state->ctl_to_crtc_id), crtc_id); 663 + _dpu_rm_clear_mapping(global_state->dsc_to_crtc_id, 664 + ARRAY_SIZE(global_state->dsc_to_crtc_id), crtc_id); 665 + _dpu_rm_clear_mapping(global_state->dspp_to_crtc_id, 666 + ARRAY_SIZE(global_state->dspp_to_crtc_id), crtc_id); 667 + _dpu_rm_clear_mapping(&global_state->cdm_to_crtc_id, 1, crtc_id); 668 + _dpu_rm_clear_mapping(global_state->cwb_to_crtc_id, 669 + ARRAY_SIZE(global_state->cwb_to_crtc_id), crtc_id); 740 670 } 741 671 742 672 /** ··· 752 674 * HW Reservations should be released via dpu_rm_release_hw. 753 675 * @rm: DPU Resource Manager handle 754 676 * @global_state: resources shared across multiple kms objects 755 - * @enc: DRM Encoder handle 756 - * @crtc_state: Proposed Atomic DRM CRTC State handle 677 + * @crtc: DRM CRTC handle 757 678 * @topology: Pointer to topology info for the display 758 679 * @return: 0 on Success otherwise -ERROR 759 680 */ 760 681 int dpu_rm_reserve( 761 682 struct dpu_rm *rm, 762 683 struct dpu_global_state *global_state, 763 - struct drm_encoder *enc, 764 - struct drm_crtc_state *crtc_state, 684 + struct drm_crtc *crtc, 765 685 struct msm_display_topology *topology) 766 686 { 767 687 int ret; 768 - 769 - /* Check if this is just a page-flip */ 770 - if (!drm_atomic_crtc_needs_modeset(crtc_state)) 771 - return 0; 772 688 773 689 if (IS_ERR(global_state)) { 774 690 DPU_ERROR("failed to global state\n"); 775 691 return PTR_ERR(global_state); 776 692 } 777 693 778 - DRM_DEBUG_KMS("reserving hw for enc %d crtc %d\n", 779 - enc->base.id, crtc_state->crtc->base.id); 694 + DRM_DEBUG_KMS("reserving hw for crtc %d\n", crtc->base.id); 780 695 781 696 DRM_DEBUG_KMS("num_lm: %d num_dsc: %d num_intf: %d\n", 782 697 topology->num_lm, topology->num_dsc, 783 698 topology->num_intf); 784 699 785 - ret = _dpu_rm_make_reservation(rm, global_state, enc, topology); 700 + ret = _dpu_rm_make_reservation(rm, global_state, crtc->base.id, topology); 786 701 if (ret) 787 702 DPU_ERROR("failed to reserve hw resources: %d\n", ret); 788 - 789 - 790 703 791 704 return ret; 792 705 } ··· 869 800 * assigned to this encoder 870 801 * @rm: DPU Resource Manager handle 871 802 * @global_state: resources shared across multiple kms objects 872 - * @enc_id: encoder id requesting for allocation 803 + * @crtc: DRM CRTC handle 873 804 * @type: resource type to return data for 874 805 * @blks: pointer to the array to be filled by HW resources 875 806 * @blks_size: size of the @blks array 876 807 */ 877 808 int dpu_rm_get_assigned_resources(struct dpu_rm *rm, 878 - struct dpu_global_state *global_state, uint32_t enc_id, 809 + struct dpu_global_state *global_state, struct drm_crtc *crtc, 879 810 enum dpu_hw_blk_type type, struct dpu_hw_blk **blks, int blks_size) 880 811 { 812 + uint32_t crtc_id = crtc->base.id; 881 813 struct dpu_hw_blk **hw_blks; 882 - uint32_t *hw_to_enc_id; 814 + uint32_t *hw_to_crtc_id; 883 815 int i, num_blks, max_blks; 884 816 885 817 switch (type) { 886 818 case DPU_HW_BLK_PINGPONG: 819 + case DPU_HW_BLK_DCWB_PINGPONG: 887 820 hw_blks = rm->pingpong_blks; 888 - hw_to_enc_id = global_state->pingpong_to_enc_id; 821 + hw_to_crtc_id = global_state->pingpong_to_crtc_id; 889 822 max_blks = ARRAY_SIZE(rm->pingpong_blks); 890 823 break; 891 824 case DPU_HW_BLK_LM: 892 825 hw_blks = rm->mixer_blks; 893 - hw_to_enc_id = global_state->mixer_to_enc_id; 826 + hw_to_crtc_id = global_state->mixer_to_crtc_id; 894 827 max_blks = ARRAY_SIZE(rm->mixer_blks); 895 828 break; 896 829 case DPU_HW_BLK_CTL: 897 830 hw_blks = rm->ctl_blks; 898 - hw_to_enc_id = global_state->ctl_to_enc_id; 831 + hw_to_crtc_id = global_state->ctl_to_crtc_id; 899 832 max_blks = ARRAY_SIZE(rm->ctl_blks); 900 833 break; 901 834 case DPU_HW_BLK_DSPP: 902 835 hw_blks = rm->dspp_blks; 903 - hw_to_enc_id = global_state->dspp_to_enc_id; 836 + hw_to_crtc_id = global_state->dspp_to_crtc_id; 904 837 max_blks = ARRAY_SIZE(rm->dspp_blks); 905 838 break; 906 839 case DPU_HW_BLK_DSC: 907 840 hw_blks = rm->dsc_blks; 908 - hw_to_enc_id = global_state->dsc_to_enc_id; 841 + hw_to_crtc_id = global_state->dsc_to_crtc_id; 909 842 max_blks = ARRAY_SIZE(rm->dsc_blks); 910 843 break; 911 844 case DPU_HW_BLK_CDM: 912 845 hw_blks = &rm->cdm_blk; 913 - hw_to_enc_id = &global_state->cdm_to_enc_id; 846 + hw_to_crtc_id = &global_state->cdm_to_crtc_id; 914 847 max_blks = 1; 848 + break; 849 + case DPU_HW_BLK_CWB: 850 + hw_blks = rm->cwb_blks; 851 + hw_to_crtc_id = global_state->cwb_to_crtc_id; 852 + max_blks = ARRAY_SIZE(rm->cwb_blks); 915 853 break; 916 854 default: 917 855 DPU_ERROR("blk type %d not managed by rm\n", type); ··· 927 851 928 852 num_blks = 0; 929 853 for (i = 0; i < max_blks; i++) { 930 - if (hw_to_enc_id[i] != enc_id) 854 + if (hw_to_crtc_id[i] != crtc_id) 931 855 continue; 932 856 857 + if (type == DPU_HW_BLK_PINGPONG) { 858 + struct dpu_hw_pingpong *pp = to_dpu_hw_pingpong(hw_blks[i]); 859 + 860 + if (pp->idx >= PINGPONG_CWB_0) 861 + continue; 862 + } 863 + 864 + if (type == DPU_HW_BLK_DCWB_PINGPONG) { 865 + struct dpu_hw_pingpong *pp = to_dpu_hw_pingpong(hw_blks[i]); 866 + 867 + if (pp->idx < PINGPONG_CWB_0) 868 + continue; 869 + } 870 + 933 871 if (num_blks == blks_size) { 934 - DPU_ERROR("More than %d resources assigned to enc %d\n", 935 - blks_size, enc_id); 872 + DPU_ERROR("More than %d resources assigned to crtc %d\n", 873 + blks_size, crtc_id); 936 874 break; 937 875 } 938 876 if (!hw_blks[i]) { 939 - DPU_ERROR("Allocated resource %d unavailable to assign to enc %d\n", 940 - type, enc_id); 877 + DPU_ERROR("Allocated resource %d unavailable to assign to crtc %d\n", 878 + type, crtc_id); 941 879 break; 942 880 } 943 881 blks[num_blks++] = hw_blks[i]; ··· 986 896 987 897 drm_puts(p, "resource mapping:\n"); 988 898 drm_puts(p, "\tpingpong="); 989 - for (i = 0; i < ARRAY_SIZE(global_state->pingpong_to_enc_id); i++) 899 + for (i = 0; i < ARRAY_SIZE(global_state->pingpong_to_crtc_id); i++) 990 900 dpu_rm_print_state_helper(p, rm->pingpong_blks[i], 991 - global_state->pingpong_to_enc_id[i]); 901 + global_state->pingpong_to_crtc_id[i]); 992 902 drm_puts(p, "\n"); 993 903 994 904 drm_puts(p, "\tmixer="); 995 - for (i = 0; i < ARRAY_SIZE(global_state->mixer_to_enc_id); i++) 905 + for (i = 0; i < ARRAY_SIZE(global_state->mixer_to_crtc_id); i++) 996 906 dpu_rm_print_state_helper(p, rm->mixer_blks[i], 997 - global_state->mixer_to_enc_id[i]); 907 + global_state->mixer_to_crtc_id[i]); 998 908 drm_puts(p, "\n"); 999 909 1000 910 drm_puts(p, "\tctl="); 1001 - for (i = 0; i < ARRAY_SIZE(global_state->ctl_to_enc_id); i++) 911 + for (i = 0; i < ARRAY_SIZE(global_state->ctl_to_crtc_id); i++) 1002 912 dpu_rm_print_state_helper(p, rm->ctl_blks[i], 1003 - global_state->ctl_to_enc_id[i]); 913 + global_state->ctl_to_crtc_id[i]); 1004 914 drm_puts(p, "\n"); 1005 915 1006 916 drm_puts(p, "\tdspp="); 1007 - for (i = 0; i < ARRAY_SIZE(global_state->dspp_to_enc_id); i++) 917 + for (i = 0; i < ARRAY_SIZE(global_state->dspp_to_crtc_id); i++) 1008 918 dpu_rm_print_state_helper(p, rm->dspp_blks[i], 1009 - global_state->dspp_to_enc_id[i]); 919 + global_state->dspp_to_crtc_id[i]); 1010 920 drm_puts(p, "\n"); 1011 921 1012 922 drm_puts(p, "\tdsc="); 1013 - for (i = 0; i < ARRAY_SIZE(global_state->dsc_to_enc_id); i++) 923 + for (i = 0; i < ARRAY_SIZE(global_state->dsc_to_crtc_id); i++) 1014 924 dpu_rm_print_state_helper(p, rm->dsc_blks[i], 1015 - global_state->dsc_to_enc_id[i]); 925 + global_state->dsc_to_crtc_id[i]); 1016 926 drm_puts(p, "\n"); 1017 927 1018 928 drm_puts(p, "\tcdm="); 1019 929 dpu_rm_print_state_helper(p, rm->cdm_blk, 1020 - global_state->cdm_to_enc_id); 930 + global_state->cdm_to_crtc_id); 1021 931 drm_puts(p, "\n"); 1022 932 1023 933 drm_puts(p, "\tsspp="); ··· 1025 935 for (i = SSPP_NONE + 1; i < ARRAY_SIZE(global_state->sspp_to_crtc_id); i++) 1026 936 dpu_rm_print_state_helper(p, rm->hw_sspp[i] ? &rm->hw_sspp[i]->base : NULL, 1027 937 global_state->sspp_to_crtc_id[i]); 938 + drm_puts(p, "\n"); 939 + 940 + drm_puts(p, "\tcwb="); 941 + for (i = 0; i < ARRAY_SIZE(global_state->cwb_to_crtc_id); i++) 942 + dpu_rm_print_state_helper(p, rm->cwb_blks[i], 943 + global_state->cwb_to_crtc_id[i]); 1028 944 drm_puts(p, "\n"); 1029 945 }
+8 -6
drivers/gpu/drm/msm/disp/dpu1/dpu_rm.h
··· 51 51 * @num_intf: number of interfaces the panel is mounted on 52 52 * @num_dspp: number of dspp blocks used 53 53 * @num_dsc: number of Display Stream Compression (DSC) blocks used 54 - * @needs_cdm: indicates whether cdm block is needed for this display topology 54 + * @num_cdm: indicates how many outputs are requesting cdm block for 55 + * this display topology 56 + * @cwb_enabled: indicates whether CWB is enabled for this display topology 55 57 */ 56 58 struct msm_display_topology { 57 59 u32 num_lm; 58 60 u32 num_intf; 59 61 u32 num_dspp; 60 62 u32 num_dsc; 61 - bool needs_cdm; 63 + int num_cdm; 64 + bool cwb_enabled; 62 65 }; 63 66 64 67 int dpu_rm_init(struct drm_device *dev, ··· 72 69 73 70 int dpu_rm_reserve(struct dpu_rm *rm, 74 71 struct dpu_global_state *global_state, 75 - struct drm_encoder *drm_enc, 76 - struct drm_crtc_state *crtc_state, 72 + struct drm_crtc *crtc, 77 73 struct msm_display_topology *topology); 78 74 79 75 void dpu_rm_release(struct dpu_global_state *global_state, 80 - struct drm_encoder *enc); 76 + struct drm_crtc *crtc); 81 77 82 78 struct dpu_hw_sspp *dpu_rm_reserve_sspp(struct dpu_rm *rm, 83 79 struct dpu_global_state *global_state, ··· 87 85 struct drm_crtc *crtc); 88 86 89 87 int dpu_rm_get_assigned_resources(struct dpu_rm *rm, 90 - struct dpu_global_state *global_state, uint32_t enc_id, 88 + struct dpu_global_state *global_state, struct drm_crtc *crtc, 91 89 enum dpu_hw_blk_type type, struct dpu_hw_blk **blks, int blks_size); 92 90 93 91 void dpu_rm_print_state(struct drm_printer *p,
+2 -1
drivers/gpu/drm/msm/disp/mdp5/mdp5_ctl.c
··· 3 3 * Copyright (c) 2014-2015 The Linux Foundation. All rights reserved. 4 4 */ 5 5 6 + #include <linux/string_choices.h> 6 7 #include "mdp5_kms.h" 7 8 #include "mdp5_ctl.h" 8 9 ··· 234 233 return -EINVAL; 235 234 236 235 ctl->encoder_enabled = enabled; 237 - DBG("intf_%d: %s", intf->num, enabled ? "on" : "off"); 236 + DBG("intf_%d: %s", intf->num, str_on_off(enabled)); 238 237 239 238 if (start_signal_needed(ctl, pipeline)) { 240 239 send_start_signal(ctl);
+13 -12
drivers/gpu/drm/msm/dp/dp_ctrl.c
··· 11 11 #include <linux/phy/phy.h> 12 12 #include <linux/phy/phy-dp.h> 13 13 #include <linux/pm_opp.h> 14 + #include <linux/string_choices.h> 14 15 15 16 #include <drm/display/drm_dp_helper.h> 16 17 #include <drm/drm_fixed.h> ··· 1367 1366 1368 1367 drm_dbg_dp(ctrl->drm_dev, "enable core clocks \n"); 1369 1368 drm_dbg_dp(ctrl->drm_dev, "stream_clks:%s link_clks:%s core_clks:%s\n", 1370 - ctrl->stream_clks_on ? "on" : "off", 1371 - ctrl->link_clks_on ? "on" : "off", 1372 - ctrl->core_clks_on ? "on" : "off"); 1369 + str_on_off(ctrl->stream_clks_on), 1370 + str_on_off(ctrl->link_clks_on), 1371 + str_on_off(ctrl->core_clks_on)); 1373 1372 1374 1373 return 0; 1375 1374 } ··· 1386 1385 1387 1386 drm_dbg_dp(ctrl->drm_dev, "disable core clocks \n"); 1388 1387 drm_dbg_dp(ctrl->drm_dev, "stream_clks:%s link_clks:%s core_clks:%s\n", 1389 - ctrl->stream_clks_on ? "on" : "off", 1390 - ctrl->link_clks_on ? "on" : "off", 1391 - ctrl->core_clks_on ? "on" : "off"); 1388 + str_on_off(ctrl->stream_clks_on), 1389 + str_on_off(ctrl->link_clks_on), 1390 + str_on_off(ctrl->core_clks_on)); 1392 1391 } 1393 1392 1394 1393 static int msm_dp_ctrl_link_clk_enable(struct msm_dp_ctrl *msm_dp_ctrl) ··· 1417 1416 1418 1417 drm_dbg_dp(ctrl->drm_dev, "enable link clocks\n"); 1419 1418 drm_dbg_dp(ctrl->drm_dev, "stream_clks:%s link_clks:%s core_clks:%s\n", 1420 - ctrl->stream_clks_on ? "on" : "off", 1421 - ctrl->link_clks_on ? "on" : "off", 1422 - ctrl->core_clks_on ? "on" : "off"); 1419 + str_on_off(ctrl->stream_clks_on), 1420 + str_on_off(ctrl->link_clks_on), 1421 + str_on_off(ctrl->core_clks_on)); 1423 1422 1424 1423 return 0; 1425 1424 } ··· 1436 1435 1437 1436 drm_dbg_dp(ctrl->drm_dev, "disabled link clocks\n"); 1438 1437 drm_dbg_dp(ctrl->drm_dev, "stream_clks:%s link_clks:%s core_clks:%s\n", 1439 - ctrl->stream_clks_on ? "on" : "off", 1440 - ctrl->link_clks_on ? "on" : "off", 1441 - ctrl->core_clks_on ? "on" : "off"); 1438 + str_on_off(ctrl->stream_clks_on), 1439 + str_on_off(ctrl->link_clks_on), 1440 + str_on_off(ctrl->core_clks_on)); 1442 1441 } 1443 1442 1444 1443 static int msm_dp_ctrl_enable_mainlink_clocks(struct msm_dp_ctrl_private *ctrl)
+2 -2
drivers/gpu/drm/msm/dp/dp_display.c
··· 11 11 #include <linux/of_irq.h> 12 12 #include <linux/phy/phy.h> 13 13 #include <linux/delay.h> 14 + #include <linux/string_choices.h> 14 15 #include <drm/display/drm_dp_aux_bus.h> 15 16 #include <drm/drm_edid.h> 16 17 ··· 344 343 { 345 344 if ((hpd && dp->msm_dp_display.link_ready) || 346 345 (!hpd && !dp->msm_dp_display.link_ready)) { 347 - drm_dbg_dp(dp->drm_dev, "HPD already %s\n", 348 - (hpd ? "on" : "off")); 346 + drm_dbg_dp(dp->drm_dev, "HPD already %s\n", str_on_off(hpd)); 349 347 return 0; 350 348 } 351 349
+3 -2
drivers/gpu/drm/msm/dp/dp_drm.c
··· 3 3 * Copyright (c) 2017-2020, The Linux Foundation. All rights reserved. 4 4 */ 5 5 6 + #include <linux/string_choices.h> 6 7 #include <drm/drm_atomic_helper.h> 7 8 #include <drm/drm_atomic.h> 8 9 #include <drm/drm_bridge.h> ··· 26 25 dp = to_dp_bridge(bridge)->msm_dp_display; 27 26 28 27 drm_dbg_dp(dp->drm_dev, "link_ready = %s\n", 29 - (dp->link_ready) ? "true" : "false"); 28 + str_true_false(dp->link_ready)); 30 29 31 30 return (dp->link_ready) ? connector_status_connected : 32 31 connector_status_disconnected; ··· 42 41 dp = to_dp_bridge(bridge)->msm_dp_display; 43 42 44 43 drm_dbg_dp(dp->drm_dev, "link_ready = %s\n", 45 - (dp->link_ready) ? "true" : "false"); 44 + str_true_false(dp->link_ready)); 46 45 47 46 /* 48 47 * There is no protection in the DRM framework to check if the display
+95 -98
drivers/gpu/drm/msm/dsi/dsi_host.c
··· 179 179 int irq; 180 180 }; 181 181 182 - 183 182 static inline u32 dsi_read(struct msm_dsi_host *msm_host, u32 reg) 184 183 { 185 184 return readl(msm_host->ctrl_base + reg); 186 185 } 186 + 187 187 static inline void dsi_write(struct msm_dsi_host *msm_host, u32 reg, u32 data) 188 188 { 189 189 writel(data, msm_host->ctrl_base + reg); 190 190 } 191 191 192 - static const struct msm_dsi_cfg_handler *dsi_get_config( 193 - struct msm_dsi_host *msm_host) 192 + static const struct msm_dsi_cfg_handler * 193 + dsi_get_config(struct msm_dsi_host *msm_host) 194 194 { 195 195 const struct msm_dsi_cfg_handler *cfg_hnd = NULL; 196 196 struct device *dev = &msm_host->pdev->dev; ··· 200 200 201 201 ahb_clk = msm_clk_get(msm_host->pdev, "iface"); 202 202 if (IS_ERR(ahb_clk)) { 203 - pr_err("%s: cannot get interface clock\n", __func__); 203 + dev_err_probe(dev, PTR_ERR(ahb_clk), "%s: cannot get interface clock\n", 204 + __func__); 204 205 goto exit; 205 206 } 206 207 ··· 209 208 210 209 ret = clk_prepare_enable(ahb_clk); 211 210 if (ret) { 212 - pr_err("%s: unable to enable ahb_clk\n", __func__); 211 + dev_err_probe(dev, ret, "%s: unable to enable ahb_clk\n", __func__); 213 212 goto runtime_put; 214 213 } 215 214 216 215 ret = dsi_get_version(msm_host->ctrl_base, &major, &minor); 217 216 if (ret) { 218 - pr_err("%s: Invalid version\n", __func__); 217 + dev_err_probe(dev, ret, "%s: Invalid version\n", __func__); 219 218 goto disable_clks; 220 219 } 221 220 ··· 282 281 msm_host->num_bus_clks = cfg->num_bus_clks; 283 282 284 283 ret = devm_clk_bulk_get(&pdev->dev, msm_host->num_bus_clks, msm_host->bus_clks); 285 - if (ret < 0) { 286 - dev_err(&pdev->dev, "Unable to get clocks, ret = %d\n", ret); 287 - goto exit; 288 - } 284 + if (ret < 0) 285 + return dev_err_probe(&pdev->dev, ret, "Unable to get clocks\n"); 289 286 290 287 /* get link and source clocks */ 291 288 msm_host->byte_clk = msm_clk_get(pdev, "byte"); 292 - if (IS_ERR(msm_host->byte_clk)) { 293 - ret = PTR_ERR(msm_host->byte_clk); 294 - pr_err("%s: can't find dsi_byte clock. ret=%d\n", 295 - __func__, ret); 296 - msm_host->byte_clk = NULL; 297 - goto exit; 298 - } 289 + if (IS_ERR(msm_host->byte_clk)) 290 + return dev_err_probe(&pdev->dev, PTR_ERR(msm_host->byte_clk), 291 + "%s: can't find dsi_byte clock\n", 292 + __func__); 299 293 300 294 msm_host->pixel_clk = msm_clk_get(pdev, "pixel"); 301 - if (IS_ERR(msm_host->pixel_clk)) { 302 - ret = PTR_ERR(msm_host->pixel_clk); 303 - pr_err("%s: can't find dsi_pixel clock. ret=%d\n", 304 - __func__, ret); 305 - msm_host->pixel_clk = NULL; 306 - goto exit; 307 - } 295 + if (IS_ERR(msm_host->pixel_clk)) 296 + return dev_err_probe(&pdev->dev, PTR_ERR(msm_host->pixel_clk), 297 + "%s: can't find dsi_pixel clock\n", 298 + __func__); 308 299 309 300 msm_host->esc_clk = msm_clk_get(pdev, "core"); 310 - if (IS_ERR(msm_host->esc_clk)) { 311 - ret = PTR_ERR(msm_host->esc_clk); 312 - pr_err("%s: can't find dsi_esc clock. ret=%d\n", 313 - __func__, ret); 314 - msm_host->esc_clk = NULL; 315 - goto exit; 316 - } 301 + if (IS_ERR(msm_host->esc_clk)) 302 + return dev_err_probe(&pdev->dev, PTR_ERR(msm_host->esc_clk), 303 + "%s: can't find dsi_esc clock\n", 304 + __func__); 317 305 318 306 if (cfg_hnd->ops->clk_init_ver) 319 307 ret = cfg_hnd->ops->clk_init_ver(msm_host); 320 - exit: 308 + 321 309 return ret; 322 310 } 323 311 ··· 369 379 370 380 return 0; 371 381 } 372 - 373 382 374 383 int dsi_link_clk_enable_6g(struct msm_dsi_host *msm_host) 375 384 { ··· 587 598 588 599 DBG("pclk=%lu, bclk=%lu", msm_host->pixel_clk_rate, 589 600 msm_host->byte_clk_rate); 590 - 591 601 } 592 602 593 603 int dsi_calc_clk_rate_6g(struct msm_dsi_host *msm_host, bool is_bonded_dsi) ··· 675 687 return NON_BURST_SYNCH_EVENT; 676 688 } 677 689 678 - static inline enum dsi_vid_dst_format dsi_get_vid_fmt( 679 - const enum mipi_dsi_pixel_format mipi_fmt) 690 + static inline enum dsi_vid_dst_format 691 + dsi_get_vid_fmt(const enum mipi_dsi_pixel_format mipi_fmt) 680 692 { 681 693 switch (mipi_fmt) { 682 694 case MIPI_DSI_FMT_RGB888: return VID_DST_FORMAT_RGB888; ··· 687 699 } 688 700 } 689 701 690 - static inline enum dsi_cmd_dst_format dsi_get_cmd_fmt( 691 - const enum mipi_dsi_pixel_format mipi_fmt) 702 + static inline enum dsi_cmd_dst_format 703 + dsi_get_cmd_fmt(const enum mipi_dsi_pixel_format mipi_fmt) 692 704 { 693 705 switch (mipi_fmt) { 694 706 case MIPI_DSI_FMT_RGB888: return CMD_DST_FORMAT_RGB888; ··· 834 846 dsi_write(msm_host, REG_DSI_CPHY_MODE_CTRL, BIT(0)); 835 847 } 836 848 837 - static void dsi_update_dsc_timing(struct msm_dsi_host *msm_host, bool is_cmd_mode, u32 hdisplay) 849 + static void dsi_update_dsc_timing(struct msm_dsi_host *msm_host, bool is_cmd_mode) 838 850 { 839 851 struct drm_dsc_config *dsc = msm_host->dsc; 840 852 u32 reg, reg_ctrl, reg_ctrl2; ··· 846 858 /* first calculate dsc parameters and then program 847 859 * compress mode registers 848 860 */ 849 - slice_per_intf = msm_dsc_get_slices_per_intf(dsc, hdisplay); 861 + slice_per_intf = dsc->slice_count; 850 862 851 863 total_bytes_per_intf = dsc->slice_chunk_size * slice_per_intf; 852 864 bytes_per_pkt = dsc->slice_chunk_size; /* * slice_per_pkt; */ ··· 979 991 980 992 if (msm_host->mode_flags & MIPI_DSI_MODE_VIDEO) { 981 993 if (msm_host->dsc) 982 - dsi_update_dsc_timing(msm_host, false, mode->hdisplay); 994 + dsi_update_dsc_timing(msm_host, false); 983 995 984 996 dsi_write(msm_host, REG_DSI_ACTIVE_H, 985 997 DSI_ACTIVE_H_START(ha_start) | ··· 1000 1012 DSI_ACTIVE_VSYNC_VPOS_END(vs_end)); 1001 1013 } else { /* command mode */ 1002 1014 if (msm_host->dsc) 1003 - dsi_update_dsc_timing(msm_host, true, mode->hdisplay); 1015 + dsi_update_dsc_timing(msm_host, true); 1004 1016 1005 1017 /* image data and 1 byte write_memory_start cmd */ 1006 1018 if (!msm_host->dsc) ··· 1280 1292 static int dsi_short_read1_resp(u8 *buf, const struct mipi_dsi_msg *msg) 1281 1293 { 1282 1294 u8 *data = msg->rx_buf; 1295 + 1283 1296 if (data && (msg->rx_len >= 1)) { 1284 1297 *data = buf[1]; /* strip out dcs type */ 1285 1298 return 1; 1286 - } else { 1287 - pr_err("%s: read data does not match with rx_buf len %zu\n", 1288 - __func__, msg->rx_len); 1289 - return -EINVAL; 1290 1299 } 1300 + 1301 + pr_err("%s: read data does not match with rx_buf len %zu\n", 1302 + __func__, msg->rx_len); 1303 + return -EINVAL; 1291 1304 } 1292 1305 1293 1306 /* ··· 1297 1308 static int dsi_short_read2_resp(u8 *buf, const struct mipi_dsi_msg *msg) 1298 1309 { 1299 1310 u8 *data = msg->rx_buf; 1311 + 1300 1312 if (data && (msg->rx_len >= 2)) { 1301 1313 data[0] = buf[1]; /* strip out dcs type */ 1302 1314 data[1] = buf[2]; 1303 1315 return 2; 1304 - } else { 1305 - pr_err("%s: read data does not match with rx_buf len %zu\n", 1306 - __func__, msg->rx_len); 1307 - return -EINVAL; 1308 1316 } 1317 + 1318 + pr_err("%s: read data does not match with rx_buf len %zu\n", 1319 + __func__, msg->rx_len); 1320 + return -EINVAL; 1309 1321 } 1310 1322 1311 1323 static int dsi_long_read_resp(u8 *buf, const struct mipi_dsi_msg *msg) ··· 1366 1376 ret = -ETIMEDOUT; 1367 1377 else 1368 1378 ret = len; 1369 - } else 1379 + } else { 1370 1380 ret = len; 1381 + } 1371 1382 1372 1383 return ret; 1373 1384 } ··· 1436 1445 return len; 1437 1446 } 1438 1447 1439 - /* for video mode, do not send cmds more than 1440 - * one pixel line, since it only transmit it 1441 - * during BLLP. 1442 - */ 1443 - /* TODO: if the command is sent in LP mode, the bit rate is only 1448 + /* 1449 + * for video mode, do not send cmds more than 1450 + * one pixel line, since it only transmit it 1451 + * during BLLP. 1452 + * 1453 + * TODO: if the command is sent in LP mode, the bit rate is only 1444 1454 * half of esc clk rate. In this case, if the video is already 1445 1455 * actively streaming, we need to check more carefully if the 1446 1456 * command can be fit into one BLLP. ··· 1759 1767 return -EINVAL; 1760 1768 } 1761 1769 1762 - if (dsc->bits_per_component != 8) { 1763 - DRM_DEV_ERROR(&msm_host->pdev->dev, "DSI does not support bits_per_component != 8 yet\n"); 1770 + switch (dsc->bits_per_component) { 1771 + case 8: 1772 + case 10: 1773 + case 12: 1774 + /* 1775 + * Only 8, 10, and 12 bpc are supported for DSC 1.1 block. 1776 + * If additional bpc values need to be supported, update 1777 + * this quard with the appropriate DSC version verification. 1778 + */ 1779 + break; 1780 + default: 1781 + DRM_DEV_ERROR(&msm_host->pdev->dev, 1782 + "Unsupported bits_per_component value: %d\n", 1783 + dsc->bits_per_component); 1764 1784 return -EOPNOTSUPP; 1765 1785 } 1766 1786 ··· 1783 1779 drm_dsc_set_const_params(dsc); 1784 1780 drm_dsc_set_rc_buf_thresh(dsc); 1785 1781 1786 - /* handle only bpp = bpc = 8, pre-SCR panels */ 1782 + /* DPU supports only pre-SCR panels */ 1787 1783 ret = drm_dsc_setup_rc_params(dsc, DRM_DSC_1_1_PRE_SCR); 1788 1784 if (ret) { 1789 1785 DRM_DEV_ERROR(&msm_host->pdev->dev, "could not find DSC RC parameters\n"); ··· 1831 1827 __func__, ret); 1832 1828 goto err; 1833 1829 } 1834 - if (!ret) 1830 + if (!ret) { 1835 1831 msm_dsi->te_source = devm_kstrdup(dev, te_source, GFP_KERNEL); 1832 + if (!msm_dsi->te_source) { 1833 + DRM_DEV_ERROR(dev, "%s: failed to allocate te_source\n", 1834 + __func__); 1835 + ret = -ENOMEM; 1836 + goto err; 1837 + } 1838 + } 1836 1839 ret = 0; 1837 1840 1838 1841 if (of_property_present(np, "syscon-sfpb")) { ··· 1885 1874 int ret; 1886 1875 1887 1876 msm_host = devm_kzalloc(&pdev->dev, sizeof(*msm_host), GFP_KERNEL); 1888 - if (!msm_host) { 1877 + if (!msm_host) 1889 1878 return -ENOMEM; 1890 - } 1891 1879 1892 1880 msm_host->pdev = pdev; 1893 1881 msm_dsi->host = &msm_host->base; 1894 1882 1895 1883 ret = dsi_host_parse_dt(msm_host); 1896 - if (ret) { 1897 - pr_err("%s: failed to parse dt\n", __func__); 1898 - return ret; 1899 - } 1884 + if (ret) 1885 + return dev_err_probe(&pdev->dev, ret, "%s: failed to parse dt\n", 1886 + __func__); 1900 1887 1901 1888 msm_host->ctrl_base = msm_ioremap_size(pdev, "dsi_ctrl", &msm_host->ctrl_size); 1902 - if (IS_ERR(msm_host->ctrl_base)) { 1903 - pr_err("%s: unable to map Dsi ctrl base\n", __func__); 1904 - return PTR_ERR(msm_host->ctrl_base); 1905 - } 1889 + if (IS_ERR(msm_host->ctrl_base)) 1890 + return dev_err_probe(&pdev->dev, PTR_ERR(msm_host->ctrl_base), 1891 + "%s: unable to map Dsi ctrl base\n", __func__); 1906 1892 1907 1893 pm_runtime_enable(&pdev->dev); 1908 1894 1909 1895 msm_host->cfg_hnd = dsi_get_config(msm_host); 1910 - if (!msm_host->cfg_hnd) { 1911 - pr_err("%s: get config failed\n", __func__); 1912 - return -EINVAL; 1913 - } 1896 + if (!msm_host->cfg_hnd) 1897 + return dev_err_probe(&pdev->dev, -EINVAL, 1898 + "%s: get config failed\n", __func__); 1914 1899 cfg = msm_host->cfg_hnd->cfg; 1915 1900 1916 1901 msm_host->id = dsi_host_get_id(msm_host); 1917 - if (msm_host->id < 0) { 1918 - pr_err("%s: unable to identify DSI host index\n", __func__); 1919 - return msm_host->id; 1920 - } 1902 + if (msm_host->id < 0) 1903 + return dev_err_probe(&pdev->dev, msm_host->id, 1904 + "%s: unable to identify DSI host index\n", 1905 + __func__); 1921 1906 1922 1907 /* fixup base address by io offset */ 1923 1908 msm_host->ctrl_base += cfg->io_offset; ··· 1925 1918 return ret; 1926 1919 1927 1920 ret = dsi_clk_init(msm_host); 1928 - if (ret) { 1929 - pr_err("%s: unable to initialize dsi clks\n", __func__); 1930 - return ret; 1931 - } 1921 + if (ret) 1922 + return dev_err_probe(&pdev->dev, ret, "%s: unable to initialize dsi clks\n", __func__); 1932 1923 1933 1924 msm_host->rx_buf = devm_kzalloc(&pdev->dev, SZ_4K, GFP_KERNEL); 1934 - if (!msm_host->rx_buf) { 1935 - pr_err("%s: alloc rx temp buf failed\n", __func__); 1925 + if (!msm_host->rx_buf) 1936 1926 return -ENOMEM; 1937 - } 1938 1927 1939 1928 ret = devm_pm_opp_set_clkname(&pdev->dev, "byte"); 1940 1929 if (ret) 1941 1930 return ret; 1942 1931 /* OPP table is optional */ 1943 1932 ret = devm_pm_opp_of_add_table(&pdev->dev); 1944 - if (ret && ret != -ENODEV) { 1945 - dev_err(&pdev->dev, "invalid OPP table in device tree\n"); 1946 - return ret; 1947 - } 1933 + if (ret && ret != -ENODEV) 1934 + return dev_err_probe(&pdev->dev, ret, "invalid OPP table in device tree\n"); 1948 1935 1949 1936 msm_host->irq = irq_of_parse_and_map(pdev->dev.of_node, 0); 1950 - if (!msm_host->irq) { 1951 - dev_err(&pdev->dev, "failed to get irq\n"); 1952 - return -EINVAL; 1953 - } 1937 + if (!msm_host->irq) 1938 + return dev_err_probe(&pdev->dev, -EINVAL, "failed to get irq\n"); 1954 1939 1955 1940 /* do not autoenable, will be enabled later */ 1956 1941 ret = devm_request_irq(&pdev->dev, msm_host->irq, dsi_host_irq, 1957 1942 IRQF_TRIGGER_HIGH | IRQF_NO_AUTOEN, 1958 1943 "dsi_isr", msm_host); 1959 - if (ret < 0) { 1960 - dev_err(&pdev->dev, "failed to request IRQ%u: %d\n", 1961 - msm_host->irq, ret); 1962 - return ret; 1963 - } 1944 + if (ret < 0) 1945 + return dev_err_probe(&pdev->dev, ret, "failed to request IRQ%u\n", 1946 + msm_host->irq); 1964 1947 1965 1948 init_completion(&msm_host->dma_comp); 1966 1949 init_completion(&msm_host->video_comp);
+21 -11
drivers/gpu/drm/msm/dsi/dsi_manager.c
··· 74 74 int ret; 75 75 76 76 if (!IS_BONDED_DSI()) { 77 + /* 78 + * Set the usecase before calling msm_dsi_host_register(), which would 79 + * already program the PLL source mux based on a default usecase. 80 + */ 81 + msm_dsi_phy_set_usecase(msm_dsi->phy, MSM_DSI_PHY_STANDALONE); 82 + msm_dsi_host_set_phy_mode(msm_dsi->host, msm_dsi->phy); 83 + 77 84 ret = msm_dsi_host_register(msm_dsi->host); 78 85 if (ret) 79 86 return ret; 80 - 81 - msm_dsi_phy_set_usecase(msm_dsi->phy, MSM_DSI_PHY_STANDALONE); 82 - msm_dsi_host_set_phy_mode(msm_dsi->host, msm_dsi->phy); 83 87 } else if (other_dsi) { 84 88 struct msm_dsi *master_link_dsi = IS_MASTER_DSI_LINK(id) ? 85 89 msm_dsi : other_dsi; 86 90 struct msm_dsi *slave_link_dsi = IS_MASTER_DSI_LINK(id) ? 87 91 other_dsi : msm_dsi; 92 + 93 + /* 94 + * PLL0 is to drive both DSI link clocks in bonded DSI mode. 95 + * 96 + * Set the usecase before calling msm_dsi_host_register(), which would 97 + * already program the PLL source mux based on a default usecase. 98 + */ 99 + msm_dsi_phy_set_usecase(clk_master_dsi->phy, 100 + MSM_DSI_PHY_MASTER); 101 + msm_dsi_phy_set_usecase(clk_slave_dsi->phy, 102 + MSM_DSI_PHY_SLAVE); 103 + msm_dsi_host_set_phy_mode(msm_dsi->host, msm_dsi->phy); 104 + msm_dsi_host_set_phy_mode(other_dsi->host, other_dsi->phy); 105 + 88 106 /* Register slave host first, so that slave DSI device 89 107 * has a chance to probe, and do not block the master 90 108 * DSI device's probe. ··· 116 98 ret = msm_dsi_host_register(master_link_dsi->host); 117 99 if (ret) 118 100 return ret; 119 - 120 - /* PLL0 is to drive both 2 DSI link clocks in bonded DSI mode. */ 121 - msm_dsi_phy_set_usecase(clk_master_dsi->phy, 122 - MSM_DSI_PHY_MASTER); 123 - msm_dsi_phy_set_usecase(clk_slave_dsi->phy, 124 - MSM_DSI_PHY_SLAVE); 125 - msm_dsi_host_set_phy_mode(msm_dsi->host, msm_dsi->phy); 126 - msm_dsi_host_set_phy_mode(other_dsi->host, other_dsi->phy); 127 101 } 128 102 129 103 return 0;
+2 -3
drivers/gpu/drm/msm/dsi/phy/dsi_phy.h
··· 6 6 #ifndef __DSI_PHY_H__ 7 7 #define __DSI_PHY_H__ 8 8 9 + #include <dt-bindings/clock/qcom,dsi-phy-28nm.h> 9 10 #include <linux/clk-provider.h> 10 11 #include <linux/delay.h> 11 12 #include <linux/regulator/consumer.h> ··· 85 84 u8 hs_halfbyte_en_ckln; 86 85 }; 87 86 88 - #define DSI_BYTE_PLL_CLK 0 89 - #define DSI_PIXEL_PLL_CLK 1 90 - #define NUM_PROVIDED_CLKS 2 87 + #define NUM_PROVIDED_CLKS (DSI_PIXEL_PLL_CLK + 1) 91 88 92 89 #define DSI_LANE_MAX 5 93 90
+1
drivers/gpu/drm/msm/dsi/phy/dsi_phy_10nm.c
··· 3 3 * Copyright (c) 2018, The Linux Foundation 4 4 */ 5 5 6 + #include <dt-bindings/clock/qcom,dsi-phy-28nm.h> 6 7 #include <linux/clk.h> 7 8 #include <linux/clk-provider.h> 8 9 #include <linux/iopoll.h>
+1
drivers/gpu/drm/msm/dsi/phy/dsi_phy_14nm.c
··· 3 3 * Copyright (c) 2016, The Linux Foundation. All rights reserved. 4 4 */ 5 5 6 + #include <dt-bindings/clock/qcom,dsi-phy-28nm.h> 6 7 #include <linux/clk.h> 7 8 #include <linux/clk-provider.h> 8 9 #include <linux/delay.h>
+1
drivers/gpu/drm/msm/dsi/phy/dsi_phy_28nm.c
··· 3 3 * Copyright (c) 2015, The Linux Foundation. All rights reserved. 4 4 */ 5 5 6 + #include <dt-bindings/clock/qcom,dsi-phy-28nm.h> 6 7 #include <linux/clk.h> 7 8 #include <linux/clk-provider.h> 8 9
+1
drivers/gpu/drm/msm/dsi/phy/dsi_phy_28nm_8960.c
··· 3 3 * Copyright (c) 2012-2015, The Linux Foundation. All rights reserved. 4 4 */ 5 5 6 + #include <dt-bindings/clock/qcom,dsi-phy-28nm.h> 6 7 #include <linux/clk-provider.h> 7 8 #include <linux/delay.h> 8 9
+11 -10
drivers/gpu/drm/msm/dsi/phy/dsi_phy_7nm.c
··· 3 3 * Copyright (c) 2018, The Linux Foundation 4 4 */ 5 5 6 + #include <dt-bindings/clock/qcom,dsi-phy-28nm.h> 7 + #include <linux/bitfield.h> 6 8 #include <linux/clk.h> 7 9 #include <linux/clk-provider.h> 8 10 #include <linux/iopoll.h> ··· 307 305 writel(pll->phy->cphy_mode ? 0x00 : 0x10, 308 306 base + REG_DSI_7nm_PHY_PLL_CMODE_1); 309 307 writel(config->pll_clock_inverters, 310 - base + REG_DSI_7nm_PHY_PLL_CLOCK_INVERTERS); 308 + base + REG_DSI_7nm_PHY_PLL_CLOCK_INVERTERS_1); 311 309 } 312 310 313 311 static int dsi_pll_7nm_vco_set_rate(struct clk_hw *hw, unsigned long rate, ··· 574 572 cached->pll_out_div &= 0x3; 575 573 576 574 cmn_clk_cfg0 = readl(phy_base + REG_DSI_7nm_PHY_CMN_CLK_CFG0); 577 - cached->bit_clk_div = cmn_clk_cfg0 & 0xf; 578 - cached->pix_clk_div = (cmn_clk_cfg0 & 0xf0) >> 4; 575 + cached->bit_clk_div = FIELD_GET(DSI_7nm_PHY_CMN_CLK_CFG0_DIV_CTRL_3_0__MASK, cmn_clk_cfg0); 576 + cached->pix_clk_div = FIELD_GET(DSI_7nm_PHY_CMN_CLK_CFG0_DIV_CTRL_7_4__MASK, cmn_clk_cfg0); 579 577 580 578 cmn_clk_cfg1 = readl(phy_base + REG_DSI_7nm_PHY_CMN_CLK_CFG1); 581 - cached->pll_mux = cmn_clk_cfg1 & 0x3; 579 + cached->pll_mux = FIELD_GET(DSI_7nm_PHY_CMN_CLK_CFG1_DSICLK_SEL__MASK, cmn_clk_cfg1); 582 580 583 581 DBG("DSI PLL%d outdiv %x bit_clk_div %x pix_clk_div %x pll_mux %x", 584 582 pll_7nm->phy->id, cached->pll_out_div, cached->bit_clk_div, ··· 600 598 dsi_pll_cmn_clk_cfg0_write(pll_7nm, 601 599 DSI_7nm_PHY_CMN_CLK_CFG0_DIV_CTRL_3_0(cached->bit_clk_div) | 602 600 DSI_7nm_PHY_CMN_CLK_CFG0_DIV_CTRL_7_4(cached->pix_clk_div)); 603 - dsi_pll_cmn_clk_cfg1_update(pll_7nm, 0x3, cached->pll_mux); 601 + dsi_pll_cmn_clk_cfg1_update(pll_7nm, DSI_7nm_PHY_CMN_CLK_CFG1_DSICLK_SEL__MASK, 602 + cached->pll_mux); 604 603 605 604 ret = dsi_pll_7nm_vco_set_rate(phy->vco_hw, 606 605 pll_7nm->vco_current_rate, ··· 739 736 * don't register a pclk_mux clock and just use post_out_div instead 740 737 */ 741 738 if (pll_7nm->phy->cphy_mode) { 742 - u32 data; 743 - 744 - data = readl(pll_7nm->phy->base + REG_DSI_7nm_PHY_CMN_CLK_CFG1); 745 - writel(data | 3, pll_7nm->phy->base + REG_DSI_7nm_PHY_CMN_CLK_CFG1); 746 - 739 + dsi_pll_cmn_clk_cfg1_update(pll_7nm, 740 + DSI_7nm_PHY_CMN_CLK_CFG1_DSICLK_SEL__MASK, 741 + DSI_7nm_PHY_CMN_CLK_CFG1_DSICLK_SEL(3)); 747 742 phy_pll_out_dsi_parent = pll_post_out_div; 748 743 } else { 749 744 snprintf(clk_name, sizeof(clk_name), "dsi%d_pclk_mux", pll_7nm->phy->id);
+2 -118
drivers/gpu/drm/msm/hdmi/hdmi.c
··· 12 12 13 13 #include <drm/drm_bridge_connector.h> 14 14 #include <drm/drm_of.h> 15 + #include <drm/display/drm_hdmi_state_helper.h> 15 16 16 - #include <sound/hdmi-codec.h> 17 17 #include "hdmi.h" 18 18 19 19 void msm_hdmi_set_mode(struct hdmi *hdmi, bool power_on) ··· 24 24 spin_lock_irqsave(&hdmi->reg_lock, flags); 25 25 if (power_on) { 26 26 ctrl |= HDMI_CTRL_ENABLE; 27 - if (!hdmi->hdmi_mode) { 27 + if (!hdmi->connector->display_info.is_hdmi) { 28 28 ctrl |= HDMI_CTRL_HDMI; 29 29 hdmi_write(hdmi, REG_HDMI_CTRL, ctrl); 30 30 ctrl &= ~HDMI_CTRL_HDMI; ··· 165 165 hdmi->dev = dev; 166 166 hdmi->encoder = encoder; 167 167 168 - hdmi_audio_infoframe_init(&hdmi->audio.infoframe); 169 - 170 168 ret = msm_hdmi_bridge_init(hdmi); 171 169 if (ret) { 172 170 DRM_DEV_ERROR(dev->dev, "failed to create HDMI bridge: %d\n", ret); ··· 244 246 .hpd_freq = hpd_clk_freq_8x74, 245 247 }; 246 248 247 - /* 248 - * HDMI audio codec callbacks 249 - */ 250 - static int msm_hdmi_audio_hw_params(struct device *dev, void *data, 251 - struct hdmi_codec_daifmt *daifmt, 252 - struct hdmi_codec_params *params) 253 - { 254 - struct hdmi *hdmi = dev_get_drvdata(dev); 255 - unsigned int chan; 256 - unsigned int channel_allocation = 0; 257 - unsigned int rate; 258 - unsigned int level_shift = 0; /* 0dB */ 259 - bool down_mix = false; 260 - 261 - DRM_DEV_DEBUG(dev, "%u Hz, %d bit, %d channels\n", params->sample_rate, 262 - params->sample_width, params->cea.channels); 263 - 264 - switch (params->cea.channels) { 265 - case 2: 266 - /* FR and FL speakers */ 267 - channel_allocation = 0; 268 - chan = MSM_HDMI_AUDIO_CHANNEL_2; 269 - break; 270 - case 4: 271 - /* FC, LFE, FR and FL speakers */ 272 - channel_allocation = 0x3; 273 - chan = MSM_HDMI_AUDIO_CHANNEL_4; 274 - break; 275 - case 6: 276 - /* RR, RL, FC, LFE, FR and FL speakers */ 277 - channel_allocation = 0x0B; 278 - chan = MSM_HDMI_AUDIO_CHANNEL_6; 279 - break; 280 - case 8: 281 - /* FRC, FLC, RR, RL, FC, LFE, FR and FL speakers */ 282 - channel_allocation = 0x1F; 283 - chan = MSM_HDMI_AUDIO_CHANNEL_8; 284 - break; 285 - default: 286 - return -EINVAL; 287 - } 288 - 289 - switch (params->sample_rate) { 290 - case 32000: 291 - rate = HDMI_SAMPLE_RATE_32KHZ; 292 - break; 293 - case 44100: 294 - rate = HDMI_SAMPLE_RATE_44_1KHZ; 295 - break; 296 - case 48000: 297 - rate = HDMI_SAMPLE_RATE_48KHZ; 298 - break; 299 - case 88200: 300 - rate = HDMI_SAMPLE_RATE_88_2KHZ; 301 - break; 302 - case 96000: 303 - rate = HDMI_SAMPLE_RATE_96KHZ; 304 - break; 305 - case 176400: 306 - rate = HDMI_SAMPLE_RATE_176_4KHZ; 307 - break; 308 - case 192000: 309 - rate = HDMI_SAMPLE_RATE_192KHZ; 310 - break; 311 - default: 312 - DRM_DEV_ERROR(dev, "rate[%d] not supported!\n", 313 - params->sample_rate); 314 - return -EINVAL; 315 - } 316 - 317 - msm_hdmi_audio_set_sample_rate(hdmi, rate); 318 - msm_hdmi_audio_info_setup(hdmi, 1, chan, channel_allocation, 319 - level_shift, down_mix); 320 - 321 - return 0; 322 - } 323 - 324 - static void msm_hdmi_audio_shutdown(struct device *dev, void *data) 325 - { 326 - struct hdmi *hdmi = dev_get_drvdata(dev); 327 - 328 - msm_hdmi_audio_info_setup(hdmi, 0, 0, 0, 0, 0); 329 - } 330 - 331 - static const struct hdmi_codec_ops msm_hdmi_audio_codec_ops = { 332 - .hw_params = msm_hdmi_audio_hw_params, 333 - .audio_shutdown = msm_hdmi_audio_shutdown, 334 - }; 335 - 336 - static struct hdmi_codec_pdata codec_data = { 337 - .ops = &msm_hdmi_audio_codec_ops, 338 - .max_i2s_channels = 8, 339 - .i2s = 1, 340 - }; 341 - 342 - static int msm_hdmi_register_audio_driver(struct hdmi *hdmi, struct device *dev) 343 - { 344 - hdmi->audio_pdev = platform_device_register_data(dev, 345 - HDMI_CODEC_DRV_NAME, 346 - PLATFORM_DEVID_AUTO, 347 - &codec_data, 348 - sizeof(codec_data)); 349 - return PTR_ERR_OR_ZERO(hdmi->audio_pdev); 350 - } 351 - 352 249 static int msm_hdmi_bind(struct device *dev, struct device *master, void *data) 353 250 { 354 251 struct msm_drm_private *priv = dev_get_drvdata(master); ··· 255 362 return err; 256 363 priv->hdmi = hdmi; 257 364 258 - err = msm_hdmi_register_audio_driver(hdmi, dev); 259 - if (err) { 260 - DRM_ERROR("Failed to attach an audio codec %d\n", err); 261 - hdmi->audio_pdev = NULL; 262 - } 263 - 264 365 return 0; 265 366 } 266 367 ··· 264 377 struct msm_drm_private *priv = dev_get_drvdata(master); 265 378 266 379 if (priv->hdmi) { 267 - if (priv->hdmi->audio_pdev) 268 - platform_device_unregister(priv->hdmi->audio_pdev); 269 - 270 380 if (priv->hdmi->bridge) 271 381 msm_hdmi_hpd_disable(priv->hdmi); 272 382
+9 -22
drivers/gpu/drm/msm/hdmi/hdmi.h
··· 24 24 25 25 struct hdmi_audio { 26 26 bool enabled; 27 - struct hdmi_audio_infoframe infoframe; 28 27 int rate; 28 + int channels; 29 29 }; 30 30 31 31 struct hdmi_hdcp_ctrl; ··· 33 33 struct hdmi { 34 34 struct drm_device *dev; 35 35 struct platform_device *pdev; 36 - struct platform_device *audio_pdev; 37 36 38 37 const struct hdmi_platform_config *config; 39 38 ··· 65 66 66 67 /* the encoder we are hooked to (outside of hdmi block) */ 67 68 struct drm_encoder *encoder; 68 - 69 - bool hdmi_mode; /* are we in hdmi mode? */ 70 69 71 70 int irq; 72 71 struct workqueue_struct *workq; ··· 204 207 /* 205 208 * audio: 206 209 */ 207 - /* Supported HDMI Audio channels and rates */ 208 - #define MSM_HDMI_AUDIO_CHANNEL_2 0 209 - #define MSM_HDMI_AUDIO_CHANNEL_4 1 210 - #define MSM_HDMI_AUDIO_CHANNEL_6 2 211 - #define MSM_HDMI_AUDIO_CHANNEL_8 3 212 - 213 - #define HDMI_SAMPLE_RATE_32KHZ 0 214 - #define HDMI_SAMPLE_RATE_44_1KHZ 1 215 - #define HDMI_SAMPLE_RATE_48KHZ 2 216 - #define HDMI_SAMPLE_RATE_88_2KHZ 3 217 - #define HDMI_SAMPLE_RATE_96KHZ 4 218 - #define HDMI_SAMPLE_RATE_176_4KHZ 5 219 - #define HDMI_SAMPLE_RATE_192KHZ 6 210 + struct hdmi_codec_daifmt; 211 + struct hdmi_codec_params; 220 212 221 213 int msm_hdmi_audio_update(struct hdmi *hdmi); 222 - int msm_hdmi_audio_info_setup(struct hdmi *hdmi, bool enabled, 223 - uint32_t num_of_channels, uint32_t channel_allocation, 224 - uint32_t level_shift, bool down_mix); 225 - void msm_hdmi_audio_set_sample_rate(struct hdmi *hdmi, int rate); 226 - 214 + int msm_hdmi_bridge_audio_prepare(struct drm_connector *connector, 215 + struct drm_bridge *bridge, 216 + struct hdmi_codec_daifmt *daifmt, 217 + struct hdmi_codec_params *params); 218 + void msm_hdmi_bridge_audio_shutdown(struct drm_connector *connector, 219 + struct drm_bridge *bridge); 227 220 228 221 /* 229 222 * hdmi bridge:
+68 -54
drivers/gpu/drm/msm/hdmi/hdmi_audio.c
··· 4 4 * Author: Rob Clark <robdclark@gmail.com> 5 5 */ 6 6 7 - #include <linux/hdmi.h> 8 - #include "hdmi.h" 7 + #include <drm/display/drm_hdmi_state_helper.h> 9 8 10 - /* maps MSM_HDMI_AUDIO_CHANNEL_n consts used by audio driver to # of channels: */ 11 - static int nchannels[] = { 2, 4, 6, 8 }; 9 + #include <linux/hdmi.h> 10 + 11 + #include <sound/hdmi-codec.h> 12 + 13 + #include "hdmi.h" 12 14 13 15 /* Supported HDMI Audio sample rates */ 14 16 #define MSM_HDMI_SAMPLE_RATE_32KHZ 0 ··· 76 74 int msm_hdmi_audio_update(struct hdmi *hdmi) 77 75 { 78 76 struct hdmi_audio *audio = &hdmi->audio; 79 - struct hdmi_audio_infoframe *info = &audio->infoframe; 80 77 const struct hdmi_msm_audio_arcs *arcs = NULL; 81 78 bool enabled = audio->enabled; 82 79 uint32_t acr_pkt_ctrl, vbi_pkt_ctrl, aud_pkt_ctrl; 83 - uint32_t infofrm_ctrl, audio_config; 80 + uint32_t audio_config; 84 81 85 - DBG("audio: enabled=%d, channels=%d, channel_allocation=0x%x, " 86 - "level_shift_value=%d, downmix_inhibit=%d, rate=%d", 87 - audio->enabled, info->channels, info->channel_allocation, 88 - info->level_shift_value, info->downmix_inhibit, audio->rate); 82 + if (!hdmi->connector->display_info.is_hdmi) 83 + return -EINVAL; 84 + 85 + DBG("audio: enabled=%d, channels=%d, rate=%d", 86 + audio->enabled, audio->channels, audio->rate); 87 + 89 88 DBG("video: power_on=%d, pixclock=%lu", hdmi->power_on, hdmi->pixclock); 90 89 91 90 if (enabled && !(hdmi->power_on && hdmi->pixclock)) { ··· 107 104 acr_pkt_ctrl = hdmi_read(hdmi, REG_HDMI_ACR_PKT_CTRL); 108 105 vbi_pkt_ctrl = hdmi_read(hdmi, REG_HDMI_VBI_PKT_CTRL); 109 106 aud_pkt_ctrl = hdmi_read(hdmi, REG_HDMI_AUDIO_PKT_CTRL1); 110 - infofrm_ctrl = hdmi_read(hdmi, REG_HDMI_INFOFRAME_CTRL0); 111 107 audio_config = hdmi_read(hdmi, REG_HDMI_AUDIO_CFG); 112 108 113 109 /* Clear N/CTS selection bits */ ··· 115 113 if (enabled) { 116 114 uint32_t n, cts, multiplier; 117 115 enum hdmi_acr_cts select; 118 - uint8_t buf[14]; 119 116 120 117 n = arcs->lut[audio->rate].n; 121 118 cts = arcs->lut[audio->rate].cts; ··· 156 155 HDMI_ACR_1_N(n)); 157 156 158 157 hdmi_write(hdmi, REG_HDMI_AUDIO_PKT_CTRL2, 159 - COND(info->channels != 2, HDMI_AUDIO_PKT_CTRL2_LAYOUT) | 158 + COND(audio->channels != 2, HDMI_AUDIO_PKT_CTRL2_LAYOUT) | 160 159 HDMI_AUDIO_PKT_CTRL2_OVERRIDE); 161 160 162 161 acr_pkt_ctrl |= HDMI_ACR_PKT_CTRL_CONT; 163 162 acr_pkt_ctrl |= HDMI_ACR_PKT_CTRL_SEND; 164 - 165 - /* configure infoframe: */ 166 - hdmi_audio_infoframe_pack(info, buf, sizeof(buf)); 167 - hdmi_write(hdmi, REG_HDMI_AUDIO_INFO0, 168 - (buf[3] << 0) | (buf[4] << 8) | 169 - (buf[5] << 16) | (buf[6] << 24)); 170 - hdmi_write(hdmi, REG_HDMI_AUDIO_INFO1, 171 - (buf[7] << 0) | (buf[8] << 8)); 172 163 173 164 hdmi_write(hdmi, REG_HDMI_GC, 0); 174 165 ··· 168 175 vbi_pkt_ctrl |= HDMI_VBI_PKT_CTRL_GC_EVERY_FRAME; 169 176 170 177 aud_pkt_ctrl |= HDMI_AUDIO_PKT_CTRL1_AUDIO_SAMPLE_SEND; 171 - 172 - infofrm_ctrl |= HDMI_INFOFRAME_CTRL0_AUDIO_INFO_SEND; 173 - infofrm_ctrl |= HDMI_INFOFRAME_CTRL0_AUDIO_INFO_CONT; 174 - infofrm_ctrl |= HDMI_INFOFRAME_CTRL0_AUDIO_INFO_SOURCE; 175 - infofrm_ctrl |= HDMI_INFOFRAME_CTRL0_AUDIO_INFO_UPDATE; 176 178 177 179 audio_config &= ~HDMI_AUDIO_CFG_FIFO_WATERMARK__MASK; 178 180 audio_config |= HDMI_AUDIO_CFG_FIFO_WATERMARK(4); ··· 178 190 vbi_pkt_ctrl &= ~HDMI_VBI_PKT_CTRL_GC_ENABLE; 179 191 vbi_pkt_ctrl &= ~HDMI_VBI_PKT_CTRL_GC_EVERY_FRAME; 180 192 aud_pkt_ctrl &= ~HDMI_AUDIO_PKT_CTRL1_AUDIO_SAMPLE_SEND; 181 - infofrm_ctrl &= ~HDMI_INFOFRAME_CTRL0_AUDIO_INFO_SEND; 182 - infofrm_ctrl &= ~HDMI_INFOFRAME_CTRL0_AUDIO_INFO_CONT; 183 - infofrm_ctrl &= ~HDMI_INFOFRAME_CTRL0_AUDIO_INFO_SOURCE; 184 - infofrm_ctrl &= ~HDMI_INFOFRAME_CTRL0_AUDIO_INFO_UPDATE; 185 193 audio_config &= ~HDMI_AUDIO_CFG_ENGINE_ENABLE; 186 194 } 187 195 188 196 hdmi_write(hdmi, REG_HDMI_ACR_PKT_CTRL, acr_pkt_ctrl); 189 197 hdmi_write(hdmi, REG_HDMI_VBI_PKT_CTRL, vbi_pkt_ctrl); 190 198 hdmi_write(hdmi, REG_HDMI_AUDIO_PKT_CTRL1, aud_pkt_ctrl); 191 - hdmi_write(hdmi, REG_HDMI_INFOFRAME_CTRL0, infofrm_ctrl); 192 199 193 200 hdmi_write(hdmi, REG_HDMI_AUD_INT, 194 201 COND(enabled, HDMI_AUD_INT_AUD_FIFO_URUN_INT) | ··· 197 214 return 0; 198 215 } 199 216 200 - int msm_hdmi_audio_info_setup(struct hdmi *hdmi, bool enabled, 201 - uint32_t num_of_channels, uint32_t channel_allocation, 202 - uint32_t level_shift, bool down_mix) 217 + int msm_hdmi_bridge_audio_prepare(struct drm_connector *connector, 218 + struct drm_bridge *bridge, 219 + struct hdmi_codec_daifmt *daifmt, 220 + struct hdmi_codec_params *params) 203 221 { 204 - struct hdmi_audio *audio; 222 + struct hdmi_bridge *hdmi_bridge = to_hdmi_bridge(bridge); 223 + struct hdmi *hdmi = hdmi_bridge->hdmi; 224 + unsigned int rate; 225 + int ret; 205 226 206 - if (!hdmi) 207 - return -ENXIO; 227 + drm_dbg_driver(bridge->dev, "%u Hz, %d bit, %d channels\n", 228 + params->sample_rate, 229 + params->sample_width, 230 + params->cea.channels); 208 231 209 - audio = &hdmi->audio; 210 - 211 - if (num_of_channels >= ARRAY_SIZE(nchannels)) 232 + switch (params->sample_rate) { 233 + case 32000: 234 + rate = MSM_HDMI_SAMPLE_RATE_32KHZ; 235 + break; 236 + case 44100: 237 + rate = MSM_HDMI_SAMPLE_RATE_44_1KHZ; 238 + break; 239 + case 48000: 240 + rate = MSM_HDMI_SAMPLE_RATE_48KHZ; 241 + break; 242 + case 88200: 243 + rate = MSM_HDMI_SAMPLE_RATE_88_2KHZ; 244 + break; 245 + case 96000: 246 + rate = MSM_HDMI_SAMPLE_RATE_96KHZ; 247 + break; 248 + case 176400: 249 + rate = MSM_HDMI_SAMPLE_RATE_176_4KHZ; 250 + break; 251 + case 192000: 252 + rate = MSM_HDMI_SAMPLE_RATE_192KHZ; 253 + break; 254 + default: 255 + drm_err(bridge->dev, "rate[%d] not supported!\n", 256 + params->sample_rate); 212 257 return -EINVAL; 258 + } 213 259 214 - audio->enabled = enabled; 215 - audio->infoframe.channels = nchannels[num_of_channels]; 216 - audio->infoframe.channel_allocation = channel_allocation; 217 - audio->infoframe.level_shift_value = level_shift; 218 - audio->infoframe.downmix_inhibit = down_mix; 260 + ret = drm_atomic_helper_connector_hdmi_update_audio_infoframe(connector, 261 + &params->cea); 262 + if (ret) 263 + return ret; 264 + 265 + hdmi->audio.rate = rate; 266 + hdmi->audio.channels = params->cea.channels; 267 + hdmi->audio.enabled = true; 219 268 220 269 return msm_hdmi_audio_update(hdmi); 221 270 } 222 271 223 - void msm_hdmi_audio_set_sample_rate(struct hdmi *hdmi, int rate) 272 + void msm_hdmi_bridge_audio_shutdown(struct drm_connector *connector, 273 + struct drm_bridge *bridge) 224 274 { 225 - struct hdmi_audio *audio; 275 + struct hdmi_bridge *hdmi_bridge = to_hdmi_bridge(bridge); 276 + struct hdmi *hdmi = hdmi_bridge->hdmi; 226 277 227 - if (!hdmi) 228 - return; 278 + drm_atomic_helper_connector_hdmi_clear_audio_infoframe(connector); 229 279 230 - audio = &hdmi->audio; 280 + hdmi->audio.rate = 0; 281 + hdmi->audio.channels = 2; 282 + hdmi->audio.enabled = false; 231 283 232 - if ((rate < 0) || (rate >= MSM_HDMI_SAMPLE_RATE_MAX)) 233 - return; 234 - 235 - audio->rate = rate; 236 284 msm_hdmi_audio_update(hdmi); 237 285 }
+257 -77
drivers/gpu/drm/msm/hdmi/hdmi_bridge.c
··· 7 7 #include <linux/delay.h> 8 8 #include <drm/drm_bridge_connector.h> 9 9 #include <drm/drm_edid.h> 10 + #include <drm/display/drm_hdmi_helper.h> 11 + #include <drm/display/drm_hdmi_state_helper.h> 10 12 11 13 #include "msm_kms.h" 12 14 #include "hdmi.h" ··· 69 67 } 70 68 71 69 #define AVI_IFRAME_LINE_NUMBER 1 70 + #define SPD_IFRAME_LINE_NUMBER 1 71 + #define VENSPEC_IFRAME_LINE_NUMBER 3 72 72 73 - static void msm_hdmi_config_avi_infoframe(struct hdmi *hdmi) 73 + static int msm_hdmi_config_avi_infoframe(struct hdmi *hdmi, 74 + const u8 *buffer, size_t len) 74 75 { 75 - struct drm_crtc *crtc = hdmi->encoder->crtc; 76 - const struct drm_display_mode *mode = &crtc->state->adjusted_mode; 77 - union hdmi_infoframe frame; 78 - u8 buffer[HDMI_INFOFRAME_SIZE(AVI)]; 76 + u32 buf[4] = {}; 79 77 u32 val; 80 - int len; 78 + int i; 81 79 82 - drm_hdmi_avi_infoframe_from_display_mode(&frame.avi, 83 - hdmi->connector, mode); 84 - 85 - len = hdmi_infoframe_pack(&frame, buffer, sizeof(buffer)); 86 - if (len < 0) { 80 + if (len != HDMI_INFOFRAME_SIZE(AVI) || len - 3 > sizeof(buf)) { 87 81 DRM_DEV_ERROR(&hdmi->pdev->dev, 88 82 "failed to configure avi infoframe\n"); 89 - return; 83 + return -EINVAL; 90 84 } 91 85 92 86 /* ··· 91 93 * written to the LSB byte of AVI_INFO0 and the version is written to 92 94 * the third byte from the LSB of AVI_INFO3 93 95 */ 94 - hdmi_write(hdmi, REG_HDMI_AVI_INFO(0), 95 - buffer[3] | 96 - buffer[4] << 8 | 97 - buffer[5] << 16 | 98 - buffer[6] << 24); 96 + memcpy(buf, &buffer[3], len - 3); 99 97 100 - hdmi_write(hdmi, REG_HDMI_AVI_INFO(1), 101 - buffer[7] | 102 - buffer[8] << 8 | 103 - buffer[9] << 16 | 104 - buffer[10] << 24); 98 + buf[3] |= buffer[1] << 24; 105 99 106 - hdmi_write(hdmi, REG_HDMI_AVI_INFO(2), 107 - buffer[11] | 108 - buffer[12] << 8 | 109 - buffer[13] << 16 | 110 - buffer[14] << 24); 100 + for (i = 0; i < ARRAY_SIZE(buf); i++) 101 + hdmi_write(hdmi, REG_HDMI_AVI_INFO(i), buf[i]); 111 102 112 - hdmi_write(hdmi, REG_HDMI_AVI_INFO(3), 113 - buffer[15] | 114 - buffer[16] << 8 | 115 - buffer[1] << 24); 116 - 117 - hdmi_write(hdmi, REG_HDMI_INFOFRAME_CTRL0, 118 - HDMI_INFOFRAME_CTRL0_AVI_SEND | 119 - HDMI_INFOFRAME_CTRL0_AVI_CONT); 103 + val = hdmi_read(hdmi, REG_HDMI_INFOFRAME_CTRL1); 104 + val |= HDMI_INFOFRAME_CTRL0_AVI_SEND | 105 + HDMI_INFOFRAME_CTRL0_AVI_CONT; 106 + hdmi_write(hdmi, REG_HDMI_INFOFRAME_CTRL0, val); 120 107 121 108 val = hdmi_read(hdmi, REG_HDMI_INFOFRAME_CTRL1); 122 109 val &= ~HDMI_INFOFRAME_CTRL1_AVI_INFO_LINE__MASK; 123 110 val |= HDMI_INFOFRAME_CTRL1_AVI_INFO_LINE(AVI_IFRAME_LINE_NUMBER); 124 111 hdmi_write(hdmi, REG_HDMI_INFOFRAME_CTRL1, val); 112 + 113 + return 0; 125 114 } 126 115 127 - static void msm_hdmi_bridge_pre_enable(struct drm_bridge *bridge) 116 + static int msm_hdmi_config_audio_infoframe(struct hdmi *hdmi, 117 + const u8 *buffer, size_t len) 118 + { 119 + u32 val; 120 + 121 + if (len != HDMI_INFOFRAME_SIZE(AUDIO)) { 122 + DRM_DEV_ERROR(&hdmi->pdev->dev, 123 + "failed to configure audio infoframe\n"); 124 + return -EINVAL; 125 + } 126 + 127 + hdmi_write(hdmi, REG_HDMI_AUDIO_INFO0, 128 + buffer[3] | 129 + buffer[4] << 8 | 130 + buffer[5] << 16 | 131 + buffer[6] << 24); 132 + 133 + hdmi_write(hdmi, REG_HDMI_AUDIO_INFO1, 134 + buffer[7] | 135 + buffer[8] << 8 | 136 + buffer[9] << 16 | 137 + buffer[10] << 24); 138 + 139 + val = hdmi_read(hdmi, REG_HDMI_INFOFRAME_CTRL1); 140 + val |= HDMI_INFOFRAME_CTRL0_AUDIO_INFO_SEND | 141 + HDMI_INFOFRAME_CTRL0_AUDIO_INFO_CONT | 142 + HDMI_INFOFRAME_CTRL0_AUDIO_INFO_SOURCE | 143 + HDMI_INFOFRAME_CTRL0_AUDIO_INFO_UPDATE; 144 + hdmi_write(hdmi, REG_HDMI_INFOFRAME_CTRL0, val); 145 + 146 + return 0; 147 + } 148 + 149 + static int msm_hdmi_config_spd_infoframe(struct hdmi *hdmi, 150 + const u8 *buffer, size_t len) 151 + { 152 + u32 buf[7] = {}; 153 + u32 val; 154 + int i; 155 + 156 + if (len != HDMI_INFOFRAME_SIZE(SPD) || len - 3 > sizeof(buf)) { 157 + DRM_DEV_ERROR(&hdmi->pdev->dev, 158 + "failed to configure SPD infoframe\n"); 159 + return -EINVAL; 160 + } 161 + 162 + /* checksum gets written together with the body of the frame */ 163 + hdmi_write(hdmi, REG_HDMI_GENERIC1_HDR, 164 + buffer[0] | 165 + buffer[1] << 8 | 166 + buffer[2] << 16); 167 + 168 + memcpy(buf, &buffer[3], len - 3); 169 + 170 + for (i = 0; i < ARRAY_SIZE(buf); i++) 171 + hdmi_write(hdmi, REG_HDMI_GENERIC1(i), buf[i]); 172 + 173 + val = hdmi_read(hdmi, REG_HDMI_GEN_PKT_CTRL); 174 + val |= HDMI_GEN_PKT_CTRL_GENERIC1_SEND | 175 + HDMI_GEN_PKT_CTRL_GENERIC1_CONT | 176 + HDMI_GEN_PKT_CTRL_GENERIC1_LINE(SPD_IFRAME_LINE_NUMBER); 177 + hdmi_write(hdmi, REG_HDMI_GEN_PKT_CTRL, val); 178 + 179 + return 0; 180 + } 181 + 182 + static int msm_hdmi_config_hdmi_infoframe(struct hdmi *hdmi, 183 + const u8 *buffer, size_t len) 184 + { 185 + u32 buf[7] = {}; 186 + u32 val; 187 + int i; 188 + 189 + if (len < HDMI_INFOFRAME_HEADER_SIZE + HDMI_VENDOR_INFOFRAME_SIZE || 190 + len - 3 > sizeof(buf)) { 191 + DRM_DEV_ERROR(&hdmi->pdev->dev, 192 + "failed to configure HDMI infoframe\n"); 193 + return -EINVAL; 194 + } 195 + 196 + /* checksum gets written together with the body of the frame */ 197 + hdmi_write(hdmi, REG_HDMI_GENERIC0_HDR, 198 + buffer[0] | 199 + buffer[1] << 8 | 200 + buffer[2] << 16); 201 + 202 + memcpy(buf, &buffer[3], len - 3); 203 + 204 + for (i = 0; i < ARRAY_SIZE(buf); i++) 205 + hdmi_write(hdmi, REG_HDMI_GENERIC0(i), buf[i]); 206 + 207 + val = hdmi_read(hdmi, REG_HDMI_GEN_PKT_CTRL); 208 + val |= HDMI_GEN_PKT_CTRL_GENERIC0_SEND | 209 + HDMI_GEN_PKT_CTRL_GENERIC0_CONT | 210 + HDMI_GEN_PKT_CTRL_GENERIC0_UPDATE | 211 + HDMI_GEN_PKT_CTRL_GENERIC0_LINE(VENSPEC_IFRAME_LINE_NUMBER); 212 + hdmi_write(hdmi, REG_HDMI_GEN_PKT_CTRL, val); 213 + 214 + return 0; 215 + } 216 + 217 + static int msm_hdmi_bridge_clear_infoframe(struct drm_bridge *bridge, 218 + enum hdmi_infoframe_type type) 219 + { 220 + struct hdmi_bridge *hdmi_bridge = to_hdmi_bridge(bridge); 221 + struct hdmi *hdmi = hdmi_bridge->hdmi; 222 + u32 val; 223 + 224 + switch (type) { 225 + case HDMI_INFOFRAME_TYPE_AVI: 226 + val = hdmi_read(hdmi, REG_HDMI_INFOFRAME_CTRL0); 227 + val &= ~(HDMI_INFOFRAME_CTRL0_AVI_SEND | 228 + HDMI_INFOFRAME_CTRL0_AVI_CONT); 229 + hdmi_write(hdmi, REG_HDMI_INFOFRAME_CTRL0, val); 230 + 231 + val = hdmi_read(hdmi, REG_HDMI_INFOFRAME_CTRL1); 232 + val &= ~HDMI_INFOFRAME_CTRL1_AVI_INFO_LINE__MASK; 233 + hdmi_write(hdmi, REG_HDMI_INFOFRAME_CTRL1, val); 234 + 235 + break; 236 + 237 + case HDMI_INFOFRAME_TYPE_AUDIO: 238 + val = hdmi_read(hdmi, REG_HDMI_INFOFRAME_CTRL0); 239 + val &= ~(HDMI_INFOFRAME_CTRL0_AUDIO_INFO_SEND | 240 + HDMI_INFOFRAME_CTRL0_AUDIO_INFO_CONT | 241 + HDMI_INFOFRAME_CTRL0_AUDIO_INFO_SOURCE | 242 + HDMI_INFOFRAME_CTRL0_AUDIO_INFO_UPDATE); 243 + hdmi_write(hdmi, REG_HDMI_INFOFRAME_CTRL0, val); 244 + 245 + val = hdmi_read(hdmi, REG_HDMI_INFOFRAME_CTRL1); 246 + val &= ~HDMI_INFOFRAME_CTRL1_AUDIO_INFO_LINE__MASK; 247 + hdmi_write(hdmi, REG_HDMI_INFOFRAME_CTRL1, val); 248 + 249 + break; 250 + 251 + case HDMI_INFOFRAME_TYPE_SPD: 252 + val = hdmi_read(hdmi, REG_HDMI_GEN_PKT_CTRL); 253 + val &= ~(HDMI_GEN_PKT_CTRL_GENERIC1_SEND | 254 + HDMI_GEN_PKT_CTRL_GENERIC1_CONT | 255 + HDMI_GEN_PKT_CTRL_GENERIC1_LINE__MASK); 256 + hdmi_write(hdmi, REG_HDMI_GEN_PKT_CTRL, val); 257 + 258 + break; 259 + 260 + case HDMI_INFOFRAME_TYPE_VENDOR: 261 + val = hdmi_read(hdmi, REG_HDMI_GEN_PKT_CTRL); 262 + val &= ~(HDMI_GEN_PKT_CTRL_GENERIC0_SEND | 263 + HDMI_GEN_PKT_CTRL_GENERIC0_CONT | 264 + HDMI_GEN_PKT_CTRL_GENERIC0_UPDATE | 265 + HDMI_GEN_PKT_CTRL_GENERIC0_LINE__MASK); 266 + hdmi_write(hdmi, REG_HDMI_GEN_PKT_CTRL, val); 267 + 268 + break; 269 + 270 + default: 271 + drm_dbg_driver(hdmi_bridge->base.dev, "Unsupported infoframe type %x\n", type); 272 + } 273 + 274 + return 0; 275 + } 276 + 277 + static int msm_hdmi_bridge_write_infoframe(struct drm_bridge *bridge, 278 + enum hdmi_infoframe_type type, 279 + const u8 *buffer, size_t len) 280 + { 281 + struct hdmi_bridge *hdmi_bridge = to_hdmi_bridge(bridge); 282 + struct hdmi *hdmi = hdmi_bridge->hdmi; 283 + 284 + msm_hdmi_bridge_clear_infoframe(bridge, type); 285 + 286 + switch (type) { 287 + case HDMI_INFOFRAME_TYPE_AVI: 288 + return msm_hdmi_config_avi_infoframe(hdmi, buffer, len); 289 + case HDMI_INFOFRAME_TYPE_AUDIO: 290 + return msm_hdmi_config_audio_infoframe(hdmi, buffer, len); 291 + case HDMI_INFOFRAME_TYPE_SPD: 292 + return msm_hdmi_config_spd_infoframe(hdmi, buffer, len); 293 + case HDMI_INFOFRAME_TYPE_VENDOR: 294 + return msm_hdmi_config_hdmi_infoframe(hdmi, buffer, len); 295 + default: 296 + drm_dbg_driver(hdmi_bridge->base.dev, "Unsupported infoframe type %x\n", type); 297 + return 0; 298 + } 299 + } 300 + 301 + static void msm_hdmi_set_timings(struct hdmi *hdmi, 302 + const struct drm_display_mode *mode); 303 + 304 + static void msm_hdmi_bridge_atomic_pre_enable(struct drm_bridge *bridge, 305 + struct drm_atomic_state *state) 128 306 { 129 307 struct hdmi_bridge *hdmi_bridge = to_hdmi_bridge(bridge); 130 308 struct hdmi *hdmi = hdmi_bridge->hdmi; 131 309 struct hdmi_phy *phy = hdmi->phy; 310 + struct drm_encoder *encoder = bridge->encoder; 311 + struct drm_connector *connector; 312 + struct drm_connector_state *conn_state; 313 + struct drm_crtc_state *crtc_state; 132 314 133 315 DBG("power up"); 316 + 317 + connector = drm_atomic_get_new_connector_for_encoder(state, encoder); 318 + conn_state = drm_atomic_get_new_connector_state(state, connector); 319 + crtc_state = drm_atomic_get_new_crtc_state(state, conn_state->crtc); 320 + 321 + hdmi->pixclock = conn_state->hdmi.tmds_char_rate; 322 + 323 + msm_hdmi_set_timings(hdmi, &crtc_state->adjusted_mode); 134 324 135 325 if (!hdmi->power_on) { 136 326 msm_hdmi_phy_resource_enable(phy); 137 327 msm_hdmi_power_on(bridge); 138 328 hdmi->power_on = true; 139 - if (hdmi->hdmi_mode) { 140 - msm_hdmi_config_avi_infoframe(hdmi); 329 + if (connector->display_info.is_hdmi) 141 330 msm_hdmi_audio_update(hdmi); 142 - } 143 331 } 332 + 333 + drm_atomic_helper_connector_hdmi_update_infoframes(connector, state); 144 334 145 335 msm_hdmi_phy_powerup(phy, hdmi->pixclock); 146 336 ··· 338 152 msm_hdmi_hdcp_on(hdmi->hdcp_ctrl); 339 153 } 340 154 341 - static void msm_hdmi_bridge_post_disable(struct drm_bridge *bridge) 155 + static void msm_hdmi_bridge_atomic_post_disable(struct drm_bridge *bridge, 156 + struct drm_atomic_state *state) 342 157 { 343 158 struct hdmi_bridge *hdmi_bridge = to_hdmi_bridge(bridge); 344 159 struct hdmi *hdmi = hdmi_bridge->hdmi; ··· 356 169 if (hdmi->power_on) { 357 170 power_off(bridge); 358 171 hdmi->power_on = false; 359 - if (hdmi->hdmi_mode) 172 + if (hdmi->connector->display_info.is_hdmi) 360 173 msm_hdmi_audio_update(hdmi); 361 174 msm_hdmi_phy_resource_disable(phy); 362 175 } 363 176 } 364 177 365 - static void msm_hdmi_bridge_mode_set(struct drm_bridge *bridge, 366 - const struct drm_display_mode *mode, 367 - const struct drm_display_mode *adjusted_mode) 178 + static void msm_hdmi_set_timings(struct hdmi *hdmi, 179 + const struct drm_display_mode *mode) 368 180 { 369 - struct hdmi_bridge *hdmi_bridge = to_hdmi_bridge(bridge); 370 - struct hdmi *hdmi = hdmi_bridge->hdmi; 371 181 int hstart, hend, vstart, vend; 372 182 uint32_t frame_ctrl; 373 - 374 - mode = adjusted_mode; 375 - 376 - hdmi->pixclock = mode->clock * 1000; 377 183 378 184 hstart = mode->htotal - mode->hsync_start; 379 185 hend = mode->htotal - mode->hsync_start + mode->hdisplay; ··· 412 232 DBG("frame_ctrl=%08x", frame_ctrl); 413 233 hdmi_write(hdmi, REG_HDMI_FRAME_CTRL, frame_ctrl); 414 234 415 - if (hdmi->hdmi_mode) 235 + if (hdmi->connector->display_info.is_hdmi) 416 236 msm_hdmi_audio_update(hdmi); 417 237 } 418 238 ··· 431 251 432 252 hdmi_write(hdmi, REG_HDMI_CTRL, hdmi_ctrl); 433 253 434 - if (drm_edid) { 435 - /* 436 - * FIXME: This should use connector->display_info.is_hdmi from a 437 - * path that has read the EDID and called 438 - * drm_edid_connector_update(). 439 - */ 440 - const struct edid *edid = drm_edid_raw(drm_edid); 441 - 442 - hdmi->hdmi_mode = drm_detect_hdmi_monitor(edid); 443 - } 444 - 445 254 return drm_edid; 446 255 } 447 256 448 - static enum drm_mode_status msm_hdmi_bridge_mode_valid(struct drm_bridge *bridge, 449 - const struct drm_display_info *info, 450 - const struct drm_display_mode *mode) 257 + static enum drm_mode_status msm_hdmi_bridge_tmds_char_rate_valid(const struct drm_bridge *bridge, 258 + const struct drm_display_mode *mode, 259 + unsigned long long tmds_rate) 451 260 { 452 261 struct hdmi_bridge *hdmi_bridge = to_hdmi_bridge(bridge); 453 262 struct hdmi *hdmi = hdmi_bridge->hdmi; 454 263 const struct hdmi_platform_config *config = hdmi->config; 455 264 struct msm_drm_private *priv = bridge->dev->dev_private; 456 265 struct msm_kms *kms = priv->kms; 457 - long actual, requested; 458 - 459 - requested = 1000 * mode->clock; 266 + long actual; 460 267 461 268 /* for mdp5/apq8074, we manage our own pixel clk (as opposed to 462 269 * mdp4/dtv stuff where pixel clk is assigned to mdp/encoder ··· 451 284 */ 452 285 if (kms->funcs->round_pixclk) 453 286 actual = kms->funcs->round_pixclk(kms, 454 - requested, hdmi_bridge->hdmi->encoder); 287 + tmds_rate, 288 + hdmi_bridge->hdmi->encoder); 455 289 else if (config->pwr_clk_cnt > 0) 456 - actual = clk_round_rate(hdmi->pwr_clks[0], requested); 290 + actual = clk_round_rate(hdmi->pwr_clks[0], tmds_rate); 457 291 else 458 - actual = requested; 292 + actual = tmds_rate; 459 293 460 - DBG("requested=%ld, actual=%ld", requested, actual); 294 + DBG("requested=%lld, actual=%ld", tmds_rate, actual); 461 295 462 - if (actual != requested) 296 + if (actual != tmds_rate) 463 297 return MODE_CLOCK_RANGE; 464 298 465 299 return 0; 466 300 } 467 301 468 302 static const struct drm_bridge_funcs msm_hdmi_bridge_funcs = { 469 - .pre_enable = msm_hdmi_bridge_pre_enable, 470 - .post_disable = msm_hdmi_bridge_post_disable, 471 - .mode_set = msm_hdmi_bridge_mode_set, 472 - .mode_valid = msm_hdmi_bridge_mode_valid, 303 + .atomic_duplicate_state = drm_atomic_helper_bridge_duplicate_state, 304 + .atomic_destroy_state = drm_atomic_helper_bridge_destroy_state, 305 + .atomic_reset = drm_atomic_helper_bridge_reset, 306 + .atomic_pre_enable = msm_hdmi_bridge_atomic_pre_enable, 307 + .atomic_post_disable = msm_hdmi_bridge_atomic_post_disable, 473 308 .edid_read = msm_hdmi_bridge_edid_read, 474 309 .detect = msm_hdmi_bridge_detect, 310 + .hdmi_tmds_char_rate_valid = msm_hdmi_bridge_tmds_char_rate_valid, 311 + .hdmi_clear_infoframe = msm_hdmi_bridge_clear_infoframe, 312 + .hdmi_write_infoframe = msm_hdmi_bridge_write_infoframe, 313 + .hdmi_audio_prepare = msm_hdmi_bridge_audio_prepare, 314 + .hdmi_audio_shutdown = msm_hdmi_bridge_audio_shutdown, 475 315 }; 476 316 477 317 static void ··· 510 336 bridge->funcs = &msm_hdmi_bridge_funcs; 511 337 bridge->ddc = hdmi->i2c; 512 338 bridge->type = DRM_MODE_CONNECTOR_HDMIA; 339 + bridge->vendor = "Qualcomm"; 340 + bridge->product = "Snapdragon"; 513 341 bridge->ops = DRM_BRIDGE_OP_HPD | 514 342 DRM_BRIDGE_OP_DETECT | 343 + DRM_BRIDGE_OP_HDMI | 515 344 DRM_BRIDGE_OP_EDID; 345 + bridge->hdmi_audio_max_i2s_playback_channels = 8; 346 + bridge->hdmi_audio_dev = &hdmi->pdev->dev; 347 + bridge->hdmi_audio_dai_port = -1; 516 348 517 349 ret = devm_drm_bridge_add(hdmi->dev->dev, bridge); 518 350 if (ret)
+14 -1
drivers/gpu/drm/msm/msm_atomic.c
··· 183 183 184 184 int msm_atomic_check(struct drm_device *dev, struct drm_atomic_state *state) 185 185 { 186 + struct msm_drm_private *priv = dev->dev_private; 187 + struct msm_kms *kms = priv->kms; 186 188 struct drm_crtc_state *old_crtc_state, *new_crtc_state; 187 189 struct drm_crtc *crtc; 188 - int i; 190 + int i, ret = 0; 189 191 192 + /* 193 + * FIXME: stop setting allow_modeset and move this check to the DPU 194 + * driver. 195 + */ 190 196 for_each_oldnew_crtc_in_state(state, crtc, old_crtc_state, 191 197 new_crtc_state, i) { 192 198 if ((old_crtc_state->ctm && !new_crtc_state->ctm) || ··· 201 195 state->allow_modeset = true; 202 196 } 203 197 } 198 + 199 + if (kms && kms->funcs && kms->funcs->check_mode_changed) 200 + ret = kms->funcs->check_mode_changed(kms, state); 201 + if (ret) 202 + return ret; 204 203 205 204 return drm_atomic_helper_check(dev, state); 206 205 } ··· 231 220 trace_msm_atomic_wait_flush_start(crtc_mask); 232 221 kms->funcs->wait_flush(kms, crtc_mask); 233 222 trace_msm_atomic_wait_flush_finish(crtc_mask); 223 + 224 + atomic_set(&kms->fault_snapshot_capture, 0); 234 225 235 226 /* 236 227 * Now that there is no in-progress flush, prepare the
+1
drivers/gpu/drm/msm/msm_drv.c
··· 894 894 DRIVER_RENDER | 895 895 DRIVER_ATOMIC | 896 896 DRIVER_MODESET | 897 + DRIVER_SYNCOBJ_TIMELINE | 897 898 DRIVER_SYNCOBJ, 898 899 .open = msm_open, 899 900 .postclose = msm_postclose,
-11
drivers/gpu/drm/msm/msm_dsc_helper.h
··· 13 13 #include <drm/display/drm_dsc_helper.h> 14 14 15 15 /** 16 - * msm_dsc_get_slices_per_intf() - calculate number of slices per interface 17 - * @dsc: Pointer to drm dsc config struct 18 - * @intf_width: interface width in pixels 19 - * Returns: Integer representing the number of slices for the given interface 20 - */ 21 - static inline u32 msm_dsc_get_slices_per_intf(const struct drm_dsc_config *dsc, u32 intf_width) 22 - { 23 - return DIV_ROUND_UP(intf_width, dsc->slice_width); 24 - } 25 - 26 - /** 27 16 * msm_dsc_get_bytes_per_line() - calculate bytes per line 28 17 * @dsc: Pointer to drm dsc config struct 29 18 * Returns: Integer value representing bytes per line. DSI and DP need
+1 -1
drivers/gpu/drm/msm/msm_gem_submit.c
··· 509 509 } 510 510 511 511 if (syncobj_desc.flags & ~MSM_SUBMIT_SYNCOBJ_FLAGS) { 512 - ret = -SUBMIT_ERROR(EINVAL, submit, "invalid syncobj flags: %x", syncobj_desc.flags); 512 + ret = SUBMIT_ERROR(EINVAL, submit, "invalid syncobj flags: %x", syncobj_desc.flags); 513 513 break; 514 514 } 515 515
+9
drivers/gpu/drm/msm/msm_gpu.c
··· 281 281 if (submit) { 282 282 int i; 283 283 284 + if (state->fault_info.ttbr0) { 285 + struct msm_gpu_fault_info *info = &state->fault_info; 286 + struct msm_mmu *mmu = submit->aspace->mmu; 287 + 288 + msm_iommu_pagetable_params(mmu, &info->pgtbl_ttbr0, 289 + &info->asid); 290 + msm_iommu_pagetable_walk(mmu, info->iova, info->ptes); 291 + } 292 + 284 293 state->bos = kcalloc(submit->nr_bos, 285 294 sizeof(struct msm_gpu_state_bo), GFP_KERNEL); 286 295
+8
drivers/gpu/drm/msm/msm_gpu.h
··· 101 101 int flags; 102 102 const char *type; 103 103 const char *block; 104 + 105 + /* Information about what we think/expect is the current SMMU state, 106 + * for example expected_ttbr0 should match smmu_info.ttbr0 which 107 + * was read back from SMMU registers. 108 + */ 109 + phys_addr_t pgtbl_ttbr0; 110 + u64 ptes[4]; 111 + int asid; 104 112 }; 105 113 106 114 /**
+51 -3
drivers/gpu/drm/msm/msm_iommu.c
··· 195 195 return &iommu->domain->geometry; 196 196 } 197 197 198 + int 199 + msm_iommu_pagetable_walk(struct msm_mmu *mmu, unsigned long iova, uint64_t ptes[4]) 200 + { 201 + struct msm_iommu_pagetable *pagetable; 202 + struct arm_lpae_io_pgtable_walk_data wd = {}; 203 + 204 + if (mmu->type != MSM_MMU_IOMMU_PAGETABLE) 205 + return -EINVAL; 206 + 207 + pagetable = to_pagetable(mmu); 208 + 209 + if (!pagetable->pgtbl_ops->pgtable_walk) 210 + return -EINVAL; 211 + 212 + pagetable->pgtbl_ops->pgtable_walk(pagetable->pgtbl_ops, iova, &wd); 213 + 214 + for (int i = 0; i < ARRAY_SIZE(wd.ptes); i++) 215 + ptes[i] = wd.ptes[i]; 216 + 217 + return 0; 218 + } 219 + 198 220 static const struct msm_mmu_funcs pagetable_funcs = { 199 221 .map = msm_iommu_pagetable_map, 200 222 .unmap = msm_iommu_pagetable_unmap, ··· 265 243 .tlb_add_page = msm_iommu_tlb_add_page, 266 244 }; 267 245 268 - static int msm_fault_handler(struct iommu_domain *domain, struct device *dev, 246 + static int msm_gpu_fault_handler(struct iommu_domain *domain, struct device *dev, 269 247 unsigned long iova, int flags, void *arg); 270 248 271 249 struct msm_mmu *msm_iommu_pagetable_create(struct msm_mmu *parent) ··· 341 319 return &pagetable->base; 342 320 } 343 321 344 - static int msm_fault_handler(struct iommu_domain *domain, struct device *dev, 322 + static int msm_gpu_fault_handler(struct iommu_domain *domain, struct device *dev, 345 323 unsigned long iova, int flags, void *arg) 346 324 { 347 325 struct msm_iommu *iommu = arg; ··· 363 341 mmu->funcs->resume_translation(mmu); 364 342 365 343 return 0; 344 + } 345 + 346 + static int msm_disp_fault_handler(struct iommu_domain *domain, struct device *dev, 347 + unsigned long iova, int flags, void *arg) 348 + { 349 + struct msm_iommu *iommu = arg; 350 + 351 + if (iommu->base.handler) 352 + return iommu->base.handler(iommu->base.arg, iova, flags, NULL); 353 + 354 + return -ENOSYS; 366 355 } 367 356 368 357 static void msm_iommu_resume_translation(struct msm_mmu *mmu) ··· 470 437 return &iommu->base; 471 438 } 472 439 440 + struct msm_mmu *msm_iommu_disp_new(struct device *dev, unsigned long quirks) 441 + { 442 + struct msm_iommu *iommu; 443 + struct msm_mmu *mmu; 444 + 445 + mmu = msm_iommu_new(dev, quirks); 446 + if (IS_ERR_OR_NULL(mmu)) 447 + return mmu; 448 + 449 + iommu = to_msm_iommu(mmu); 450 + iommu_set_fault_handler(iommu->domain, msm_disp_fault_handler, iommu); 451 + 452 + return mmu; 453 + } 454 + 473 455 struct msm_mmu *msm_iommu_gpu_new(struct device *dev, struct msm_gpu *gpu, unsigned long quirks) 474 456 { 475 457 struct adreno_smmu_priv *adreno_smmu = dev_get_drvdata(dev); ··· 496 448 return mmu; 497 449 498 450 iommu = to_msm_iommu(mmu); 499 - iommu_set_fault_handler(iommu->domain, msm_fault_handler, iommu); 451 + iommu_set_fault_handler(iommu->domain, msm_gpu_fault_handler, iommu); 500 452 501 453 /* Enable stall on iommu fault: */ 502 454 if (adreno_smmu->set_stall)
+18 -1
drivers/gpu/drm/msm/msm_kms.c
··· 164 164 vblank_ctrl_queue_work(priv, crtc, false); 165 165 } 166 166 167 + static int msm_kms_fault_handler(void *arg, unsigned long iova, int flags, void *data) 168 + { 169 + struct msm_kms *kms = arg; 170 + 171 + if (atomic_read(&kms->fault_snapshot_capture) == 0) { 172 + msm_disp_snapshot_state(kms->dev); 173 + atomic_inc(&kms->fault_snapshot_capture); 174 + } 175 + 176 + return -ENOSYS; 177 + } 178 + 167 179 struct msm_gem_address_space *msm_kms_init_aspace(struct drm_device *dev) 168 180 { 169 181 struct msm_gem_address_space *aspace; 170 182 struct msm_mmu *mmu; 171 183 struct device *mdp_dev = dev->dev; 172 184 struct device *mdss_dev = mdp_dev->parent; 185 + struct msm_drm_private *priv = dev->dev_private; 186 + struct msm_kms *kms = priv->kms; 173 187 struct device *iommu_dev; 174 188 175 189 /* ··· 195 181 else 196 182 iommu_dev = mdss_dev; 197 183 198 - mmu = msm_iommu_new(iommu_dev, 0); 184 + mmu = msm_iommu_disp_new(iommu_dev, 0); 199 185 if (IS_ERR(mmu)) 200 186 return ERR_CAST(mmu); 201 187 ··· 209 195 if (IS_ERR(aspace)) { 210 196 dev_err(mdp_dev, "aspace create, error %pe\n", aspace); 211 197 mmu->funcs->destroy(mmu); 198 + return aspace; 212 199 } 200 + 201 + msm_mmu_set_fault_handler(aspace->mmu, kms, msm_kms_fault_handler); 213 202 214 203 return aspace; 215 204 }
+10
drivers/gpu/drm/msm/msm_kms.h
··· 60 60 void (*disable_commit)(struct msm_kms *kms); 61 61 62 62 /** 63 + * @check_mode_changed: 64 + * 65 + * Verify if the commit requires a full modeset on one of CRTCs. 66 + */ 67 + int (*check_mode_changed)(struct msm_kms *kms, struct drm_atomic_state *state); 68 + 69 + /** 63 70 * Prepare for atomic commit. This is called after any previous 64 71 * (async or otherwise) commit has completed. 65 72 */ ··· 134 127 /* irq number to be passed on to msm_irq_install */ 135 128 int irq; 136 129 bool irq_requested; 130 + 131 + /* rate limit the snapshot capture to once per attach */ 132 + atomic_t fault_snapshot_capture; 137 133 138 134 /* mapper-id used to request GEM buffer mapped for scanout: */ 139 135 struct msm_gem_address_space *aspace;
+3 -1
drivers/gpu/drm/msm/msm_mmu.h
··· 42 42 43 43 struct msm_mmu *msm_iommu_new(struct device *dev, unsigned long quirks); 44 44 struct msm_mmu *msm_iommu_gpu_new(struct device *dev, struct msm_gpu *gpu, unsigned long quirks); 45 + struct msm_mmu *msm_iommu_disp_new(struct device *dev, unsigned long quirks); 45 46 46 47 static inline void msm_mmu_set_fault_handler(struct msm_mmu *mmu, void *arg, 47 48 int (*handler)(void *arg, unsigned long iova, int flags, void *data)) ··· 54 53 struct msm_mmu *msm_iommu_pagetable_create(struct msm_mmu *parent); 55 54 56 55 int msm_iommu_pagetable_params(struct msm_mmu *mmu, phys_addr_t *ttbr, 57 - int *asid); 56 + int *asid); 57 + int msm_iommu_pagetable_walk(struct msm_mmu *mmu, unsigned long iova, uint64_t ptes[4]); 58 58 struct iommu_domain_geometry *msm_iommu_get_geometry(struct msm_mmu *mmu); 59 59 60 60 #endif /* __MSM_MMU_H__ */
+1
drivers/gpu/drm/msm/registers/display/dsi_phy_7nm.xml
··· 17 17 <bitfield name="CLK_EN" pos="5" type="boolean"/> 18 18 <bitfield name="CLK_EN_SEL" pos="4" type="boolean"/> 19 19 <bitfield name="BITCLK_SEL" low="2" high="3" type="uint"/> 20 + <bitfield name="DSICLK_SEL" low="0" high="1" type="uint"/> 20 21 </reg32> 21 22 <reg32 offset="0x00018" name="GLBL_CTRL"/> 22 23 <reg32 offset="0x0001c" name="RBUF_CTRL"/>
+1 -1
drivers/gpu/drm/msm/registers/display/hdmi.xml
··· 131 131 --> 132 132 <bitfield name="GENERIC0_SEND" pos="0" type="boolean"/> 133 133 <bitfield name="GENERIC0_CONT" pos="1" type="boolean"/> 134 - <bitfield name="GENERIC0_UPDATE" low="2" high="3" type="uint"/> <!-- ??? --> 134 + <bitfield name="GENERIC0_UPDATE" pos="2" type="boolean"/> 135 135 <bitfield name="GENERIC1_SEND" pos="4" type="boolean"/> 136 136 <bitfield name="GENERIC1_CONT" pos="5" type="boolean"/> 137 137 <bitfield name="GENERIC0_LINE" low="16" high="21" type="uint"/>
+9
include/dt-bindings/clock/qcom,dsi-phy-28nm.h
··· 1 + /* SPDX-License-Identifier: GPL-2.0-only OR BSD-2-Clause */ 2 + 3 + #ifndef _DT_BINDINGS_CLK_QCOM_DSI_PHY_28NM_H 4 + #define _DT_BINDINGS_CLK_QCOM_DSI_PHY_28NM_H 5 + 6 + #define DSI_BYTE_PLL_CLK 0 7 + #define DSI_PIXEL_PLL_CLK 1 8 + 9 + #endif