Changes for v7.3 Bindings: - Added Shikra support - Document a840, a704, a722 Core: - Use drm_client buffers for fbdev emulation - teardown fixes - ARM32 DMA fixup - Remove objects from evict list when re-validated - Bunch of corner case and error path fixes DPU: - Dropped dev_pm_opp_set_rate(0) preventing burnout - Fixed SSPP offsets of Kaanapali DP: - Dropped dev_pm_opp_set_rate(0) preventing burnout - Cleaned up core code in preparation for MST support - Fixed prepare() to let Pipewire continue in case of the unplugged cable GPU: - Add support for a704 - Add support for a722 HDMI: - Simplifed register access
Unified · Split
| @@ -47,6 +47,10 @@ properties: · 46 unmodified lines | |||
| 47 | - qcom,sm8650-dsi-ctrl | 47 | - qcom,sm8650-dsi-ctrl |
| 48 | - qcom,sm8750-dsi-ctrl | 48 | - qcom,sm8750-dsi-ctrl |
| 49 | - const: qcom,mdss-dsi-ctrl | 49 | - const: qcom,mdss-dsi-ctrl |
| 50 | - items: | ||
| 51 | - const: qcom,shikra-dsi-ctrl | ||
| 52 | - const: qcom,qcm2290-dsi-ctrl | ||
| 53 | - const: qcom,mdss-dsi-ctrl | ||
| 50 | - items: | 54 | - items: |
| 51 | - enum: | 55 | - enum: |
| 52 | - qcom,qcs8300-dsi-ctrl | 56 | - qcom,qcs8300-dsi-ctrl |
| @@ -262,6 +262,7 @@ allOf: · 261 unmodified lines | |||
| 262 | compatible: | 262 | compatible: |
| 263 | contains: | 263 | contains: |
| 264 | enum: | 264 | enum: |
| 265 | - qcom,adreno-gmu-722.0 | ||
| 265 | - qcom,adreno-gmu-730.1 | 266 | - qcom,adreno-gmu-730.1 |
| 266 | - qcom,adreno-gmu-740.1 | 267 | - qcom,adreno-gmu-740.1 |
| 267 | - qcom,adreno-gmu-750.1 | 268 | - qcom,adreno-gmu-750.1 |
| @@ -353,6 +353,7 @@ allOf: · 352 unmodified lines | |||
| 353 | - qcom,adreno-610.0 | 353 | - qcom,adreno-610.0 |
| 354 | - qcom,adreno-619.1 | 354 | - qcom,adreno-619.1 |
| 355 | - qcom,adreno-07000200 | 355 | - qcom,adreno-07000200 |
| 356 | - qcom,adreno-07000400 | ||
| 356 | then: | 357 | then: |
| 357 | properties: | 358 | properties: |
| 358 | clocks: | 359 | clocks: |
| @@ -413,6 +414,7 @@ allOf: · 54 unmodified lines | |||
| 413 | contains: | 414 | contains: |
| 414 | enum: | 415 | enum: |
| 415 | - qcom,adreno-44010000 | 416 | - qcom,adreno-44010000 |
| 417 | - qcom,adreno-44050a01 | ||
| 416 | - qcom,adreno-44070001 | 418 | - qcom,adreno-44070001 |
| 417 | then: | 419 | then: |
| 418 | properties: | 420 | properties: |
| @@ -443,11 +445,13 @@ allOf: · 24 unmodified lines | |||
| 443 | - qcom,adreno-680.1 | 445 | - qcom,adreno-680.1 |
| 444 | - qcom,adreno-690.0 | 446 | - qcom,adreno-690.0 |
| 445 | - qcom,adreno-730.1 | 447 | - qcom,adreno-730.1 |
| 448 | - qcom,adreno-43020100 | ||
| 446 | - qcom,adreno-43030c00 | 449 | - qcom,adreno-43030c00 |
| 447 | - qcom,adreno-43050a01 | 450 | - qcom,adreno-43050a01 |
| 448 | - qcom,adreno-43050c01 | 451 | - qcom,adreno-43050c01 |
| 449 | - qcom,adreno-43051401 | 452 | - qcom,adreno-43051401 |
| 450 | - qcom,adreno-44010000 | 453 | - qcom,adreno-44010000 |
| 454 | - qcom,adreno-44050a01 | ||
| 451 | - qcom,adreno-44070001 | 455 | - qcom,adreno-44070001 |
| 452 | 456 | ||
| 453 | then: # Starting with A6xx, the clocks are usually defined in the GMU node | 457 | then: # Starting with A6xx, the clocks are usually defined in the GMU node |
| @@ -13,7 +13,11 @@ $ref: /schemas/display/msm/dpu-common.yaml# · 12 unmodified lines | |||
| 13 | 13 | ||
| 14 | properties: | 14 | properties: |
| 15 | compatible: | 15 | compatible: |
| 16 | const: qcom,qcm2290-dpu | 16 | oneOf: |
| 17 | - const: qcom,qcm2290-dpu | ||
| 18 | - items: | ||
| 19 | - const: qcom,shikra-dpu | ||
| 20 | - const: qcom,qcm2290-dpu | ||
| 17 | 21 | ||
| 18 | reg: | 22 | reg: |
| 19 | items: | 23 | items: |
| @@ -4,7 +4,7 @@ · 3 unmodified lines | |||
| 4 | $id: http://devicetree.org/schemas/display/msm/qcom,qcm2290-mdss.yaml# | 4 | $id: http://devicetree.org/schemas/display/msm/qcom,qcm2290-mdss.yaml# |
| 5 | $schema: http://devicetree.org/meta-schemas/core.yaml# | 5 | $schema: http://devicetree.org/meta-schemas/core.yaml# |
| 6 | 6 | ||
| 7 | title: Qualcomm QCM220 Display MDSS | 7 | title: Qualcomm QCM2290 and Shikra Display MDSS |
| 8 | 8 | ||
| 9 | maintainers: | 9 | maintainers: |
| 10 | - Loic Poulain <loic.poulain@linaro.org> | 10 | - Loic Poulain <loic.poulain@linaro.org> |
| @@ -12,13 +12,18 @@ maintainers: · 1 unmodified line | |||
| 12 | description: | 12 | description: |
| 13 | Device tree bindings for MSM Mobile Display Subsystem(MDSS) that encapsulates | 13 | Device tree bindings for MSM Mobile Display Subsystem(MDSS) that encapsulates |
| 14 | sub-blocks like DPU display controller and DSI. Device tree bindings of MDSS | 14 | sub-blocks like DPU display controller and DSI. Device tree bindings of MDSS |
| 15 | are mentioned for QCM2290 target. | 15 | are mentioned for QCM2290 and Shikra targets. Shikra uses the same MDSS/DPU/DSI |
| 16 | hardware as QCM2290 (DPU 6.5) and shares the same register layout. | ||
| 16 | 17 | ||
| 17 | $ref: /schemas/display/msm/mdss-common.yaml# | 18 | $ref: /schemas/display/msm/mdss-common.yaml# |
| 18 | 19 | ||
| 19 | properties: | 20 | properties: |
| 20 | compatible: | 21 | compatible: |
| 21 | const: qcom,qcm2290-mdss | 22 | oneOf: |
| 23 | - const: qcom,qcm2290-mdss | ||
| 24 | - items: | ||
| 25 | - const: qcom,shikra-mdss | ||
| 26 | - const: qcom,qcm2290-mdss | ||
| 22 | 27 | ||
| 23 | clocks: | 28 | clocks: |
| 24 | items: | 29 | items: |
| @@ -52,7 +57,8 @@ patternProperties: · 27 unmodified lines | |||
| 52 | 57 | ||
| 53 | properties: | 58 | properties: |
| 54 | compatible: | 59 | compatible: |
| 55 | const: qcom,qcm2290-dpu | 60 | contains: |
| 61 | const: qcom,qcm2290-dpu | ||
| 56 | 62 | ||
| 57 | "^dsi@[0-9a-f]+$": | 63 | "^dsi@[0-9a-f]+$": |
| 58 | type: object | 64 | type: object |
| @@ -60,9 +66,8 @@ patternProperties: · 1 unmodified line | |||
| 60 | 66 | ||
| 61 | properties: | 67 | properties: |
| 62 | compatible: | 68 | compatible: |
| 63 | items: | 69 | contains: |
| 64 | - const: qcom,qcm2290-dsi-ctrl | 70 | const: qcom,qcm2290-dsi-ctrl |
| 65 | - const: qcom,mdss-dsi-ctrl | ||
| 66 | 71 | ||
| 67 | "^phy@[0-9a-f]+$": | 72 | "^phy@[0-9a-f]+$": |
| 68 | type: object | 73 | type: object |
| @@ -95,6 +95,7 @@ properties: · 94 unmodified lines | |||
| 95 | - description: Qcom Adreno GPUs implementing "qcom,smmu-500" and "arm,mmu-500" | 95 | - description: Qcom Adreno GPUs implementing "qcom,smmu-500" and "arm,mmu-500" |
| 96 | items: | 96 | items: |
| 97 | - enum: | 97 | - enum: |
| 98 | - qcom,eliza-smmu-500 | ||
| 98 | - qcom,glymur-smmu-500 | 99 | - qcom,glymur-smmu-500 |
| 99 | - qcom,hawi-smmu-500 | 100 | - qcom,hawi-smmu-500 |
| 100 | - qcom,kaanapali-smmu-500 | 101 | - qcom,kaanapali-smmu-500 |
| @@ -108,6 +109,7 @@ properties: · 7 unmodified lines | |||
| 108 | - qcom,sc7280-smmu-500 | 109 | - qcom,sc7280-smmu-500 |
| 109 | - qcom,sc8180x-smmu-500 | 110 | - qcom,sc8180x-smmu-500 |
| 110 | - qcom,sc8280xp-smmu-500 | 111 | - qcom,sc8280xp-smmu-500 |
| 112 | - qcom,shikra-smmu-500 | ||
| 111 | - qcom,sm6115-smmu-500 | 113 | - qcom,sm6115-smmu-500 |
| 112 | - qcom,sm6125-smmu-500 | 114 | - qcom,sm6125-smmu-500 |
| 113 | - qcom,sm8150-smmu-500 | 115 | - qcom,sm8150-smmu-500 |
| @@ -543,6 +545,7 @@ allOf: · 429 unmodified lines | |||
| 543 | - enum: | 545 | - enum: |
| 544 | - qcom,milos-smmu-500 | 546 | - qcom,milos-smmu-500 |
| 545 | - qcom,sar2130p-smmu-500 | 547 | - qcom,sar2130p-smmu-500 |
| 548 | - qcom,shikra-smmu-500 | ||
| 546 | - qcom,sm8550-smmu-500 | 549 | - qcom,sm8550-smmu-500 |
| 547 | - qcom,sm8650-smmu-500 | 550 | - qcom,sm8650-smmu-500 |
| 548 | - qcom,x1e80100-smmu-500 | 551 | - qcom,x1e80100-smmu-500 |
| @@ -570,6 +573,7 @@ allOf: · 21 unmodified lines | |||
| 570 | compatible: | 573 | compatible: |
| 571 | items: | 574 | items: |
| 572 | - enum: | 575 | - enum: |
| 576 | - qcom,eliza-smmu-500 | ||
| 573 | - qcom,glymur-smmu-500 | 577 | - qcom,glymur-smmu-500 |
| 574 | - qcom,hawi-smmu-500 | 578 | - qcom,hawi-smmu-500 |
| 575 | - qcom,kaanapali-smmu-500 | 579 | - qcom,kaanapali-smmu-500 |
| @@ -25,6 +25,8 @@ · 24 unmodified lines | |||
| 25 | 25 | ||
| 26 | extern bool hang_debug; | 26 | extern bool hang_debug; |
| 27 | 27 | ||
| 28 | #define A3XX_VBIF_XIN_HALT_CTRL0_MASK GENMASK(5, 0) | ||
| 29 | |||
| 28 | static void a3xx_dump(struct msm_gpu *gpu); | 30 | static void a3xx_dump(struct msm_gpu *gpu); |
| 29 | static bool a3xx_idle(struct msm_gpu *gpu); | 31 | static bool a3xx_idle(struct msm_gpu *gpu); |
| 30 | 32 | ||
| @@ -496,6 +498,38 @@ static u64 a3xx_gpu_busy(struct msm_gpu *gpu, unsigned long *out_sample_rate) · 465 unmodified lines | |||
| 496 | return busy_cycles; | 498 | return busy_cycles; |
| 497 | } | 499 | } |
| 498 | 500 | ||
| 501 | static int a3xx_vbif_halt(struct msm_gpu *gpu) | ||
| 502 | { | ||
| 503 | u32 ack; | ||
| 504 | int ret; | ||
| 505 | |||
| 506 | gpu_write(gpu, REG_A3XX_VBIF_XIN_HALT_CTRL0, | ||
| 507 | A3XX_VBIF_XIN_HALT_CTRL0_MASK); | ||
| 508 | ret = spin_until(((ack = gpu_read(gpu, REG_A3XX_VBIF_XIN_HALT_CTRL1)) & | ||
| 509 | A3XX_VBIF_XIN_HALT_CTRL0_MASK) == | ||
| 510 | A3XX_VBIF_XIN_HALT_CTRL0_MASK); | ||
| 511 | gpu_write(gpu, REG_A3XX_VBIF_XIN_HALT_CTRL0, 0); | ||
| 512 | |||
| 513 | if (ret) | ||
| 514 | return -EBUSY; | ||
| 515 | |||
| 516 | return 0; | ||
| 517 | } | ||
| 518 | |||
| 519 | static int a3xx_pm_suspend(struct msm_gpu *gpu) | ||
| 520 | { | ||
| 521 | int ret; | ||
| 522 | |||
| 523 | if (!a3xx_idle(gpu)) | ||
| 524 | return -EBUSY; | ||
| 525 | |||
| 526 | ret = a3xx_vbif_halt(gpu); | ||
| 527 | if (ret) | ||
| 528 | return ret; | ||
| 529 | |||
| 530 | return msm_gpu_pm_suspend(gpu); | ||
| 531 | } | ||
| 532 | |||
| 499 | static u32 a3xx_get_rptr(struct msm_gpu *gpu, struct msm_ringbuffer *ring) | 533 | static u32 a3xx_get_rptr(struct msm_gpu *gpu, struct msm_ringbuffer *ring) |
| 500 | { | 534 | { |
| 501 | ring->memptrs->rptr = gpu_read(gpu, REG_AXXX_CP_RB_RPTR); | 535 | ring->memptrs->rptr = gpu_read(gpu, REG_AXXX_CP_RB_RPTR); |
| @@ -581,7 +615,7 @@ const struct adreno_gpu_funcs a3xx_gpu_funcs = { · 79 unmodified lines | |||
| 581 | .get_param = adreno_get_param, | 615 | .get_param = adreno_get_param, |
| 582 | .set_param = adreno_set_param, | 616 | .set_param = adreno_set_param, |
| 583 | .hw_init = a3xx_hw_init, | 617 | .hw_init = a3xx_hw_init, |
| 584 | .pm_suspend = msm_gpu_pm_suspend, | 618 | .pm_suspend = a3xx_pm_suspend, |
| 585 | .pm_resume = msm_gpu_pm_resume, | 619 | .pm_resume = msm_gpu_pm_resume, |
| 586 | .recover = a3xx_recover, | 620 | .recover = a3xx_recover, |
| 587 | .submit = a3xx_submit, | 621 | .submit = a3xx_submit, |
| @@ -1275,6 +1275,11 @@ static irqreturn_t a5xx_irq(struct msm_gpu *gpu) · 1274 unmodified lines | |||
| 1275 | status & ~A5XX_RBBM_INT_0_MASK_RBBM_AHB_ERROR); | 1275 | status & ~A5XX_RBBM_INT_0_MASK_RBBM_AHB_ERROR); |
| 1276 | 1276 | ||
| 1277 | if (priv->disable_err_irq) { | 1277 | if (priv->disable_err_irq) { |
| 1278 | /* Turn off interrupts to avoid interrupt storm */ | ||
| 1279 | gpu_write(gpu, REG_A5XX_RBBM_INT_0_MASK, | ||
| 1280 | A5XX_RBBM_INT_0_MASK_CP_CACHE_FLUSH_TS | | ||
| 1281 | A5XX_RBBM_INT_0_MASK_CP_SW); | ||
| 1282 | |||
| 1278 | status &= A5XX_RBBM_INT_0_MASK_CP_CACHE_FLUSH_TS | | 1283 | status &= A5XX_RBBM_INT_0_MASK_CP_CACHE_FLUSH_TS | |
| 1279 | A5XX_RBBM_INT_0_MASK_CP_SW; | 1284 | A5XX_RBBM_INT_0_MASK_CP_SW; |
| 1280 | } | 1285 | } |
| @@ -1199,7 +1199,7 @@ static const struct adreno_reglist a730_hwcg[] = { · 1198 unmodified lines | |||
| 1199 | { REG_A6XX_RBBM_CLOCK_DELAY_SP0, 0x00000080 }, | 1199 | { REG_A6XX_RBBM_CLOCK_DELAY_SP0, 0x00000080 }, |
| 1200 | { REG_A6XX_RBBM_CLOCK_CNTL_TP0, 0x22222220 }, | 1200 | { REG_A6XX_RBBM_CLOCK_CNTL_TP0, 0x22222220 }, |
| 1201 | { REG_A6XX_RBBM_CLOCK_CNTL2_TP0, 0x22222222 }, | 1201 | { REG_A6XX_RBBM_CLOCK_CNTL2_TP0, 0x22222222 }, |
| 1202 | { REG_A6XX_RBBM_CLOCK_CNTL3_TP0, 0x22222222 }, | 1202 | { REG_A6XX_RBBM_CLOCK_CNTL3_TP0, 0x22220222 }, |
| 1203 | { REG_A6XX_RBBM_CLOCK_CNTL4_TP0, 0x00222222 }, | 1203 | { REG_A6XX_RBBM_CLOCK_CNTL4_TP0, 0x00222222 }, |
| 1204 | { REG_A6XX_RBBM_CLOCK_HYST_TP0, 0x77777777 }, | 1204 | { REG_A6XX_RBBM_CLOCK_HYST_TP0, 0x77777777 }, |
| 1205 | { REG_A6XX_RBBM_CLOCK_HYST2_TP0, 0x77777777 }, | 1205 | { REG_A6XX_RBBM_CLOCK_HYST2_TP0, 0x77777777 }, |
| @@ -1454,7 +1454,7 @@ DECLARE_ADRENO_REGLIST_PIPE_LIST(a7xx_dyn_pwrup_reglist); · 248 unmodified lines | |||
| 1454 | 1454 | ||
| 1455 | static const struct adreno_info a7xx_gpus[] = { | 1455 | static const struct adreno_info a7xx_gpus[] = { |
| 1456 | { | 1456 | { |
| 1457 | .chip_ids = ADRENO_CHIP_IDS(0x07000200), | 1457 | .chip_ids = ADRENO_CHIP_IDS(0x07000200, 0x07000400), |
| 1458 | .family = ADRENO_6XX_GEN1, /* NOT a mistake! */ | 1458 | .family = ADRENO_6XX_GEN1, /* NOT a mistake! */ |
| 1459 | .fw = { | 1459 | .fw = { |
| 1460 | [ADRENO_FW_SQE] = "a702_sqe.fw", | 1460 | [ADRENO_FW_SQE] = "a702_sqe.fw", |
| @@ -1500,6 +1500,40 @@ static const struct adreno_info a7xx_gpus[] = { · 39 unmodified lines | |||
| 1500 | .gmu_cgc_mode = 0x00020000, | 1500 | .gmu_cgc_mode = 0x00020000, |
| 1501 | }, | 1501 | }, |
| 1502 | .preempt_record_size = 2860 * SZ_1K, | 1502 | .preempt_record_size = 2860 * SZ_1K, |
| 1503 | }, { | ||
| 1504 | .chip_ids = ADRENO_CHIP_IDS(0x43020100), | ||
| 1505 | .family = ADRENO_7XX_GEN1, | ||
| 1506 | .fw = { | ||
| 1507 | [ADRENO_FW_SQE] = "qcom/gen71700_sqe.fw", | ||
| 1508 | [ADRENO_FW_GMU] = "qcom/gen71700_gmu.bin", | ||
| 1509 | }, | ||
| 1510 | .gmem = SZ_1M, | ||
| 1511 | .inactive_period = DRM_MSM_INACTIVE_PERIOD, | ||
| 1512 | .quirks = ADRENO_QUIRK_HAS_CACHED_COHERENT | | ||
| 1513 | ADRENO_QUIRK_HAS_HW_APRIV | | ||
| 1514 | ADRENO_QUIRK_PREEMPTION, | ||
| 1515 | .funcs = &a7xx_gpu_funcs, | ||
| 1516 | .a6xx = &(const struct a6xx_info) { | ||
| 1517 | .hwcg = a730_hwcg, | ||
| 1518 | .protect = &a730_protect, | ||
| 1519 | .pwrup_reglist = &a7xx_pwrup_reglist, | ||
| 1520 | .dyn_pwrup_reglist = &a7xx_dyn_pwrup_reglist, | ||
| 1521 | .gbif_cx = a640_gbif, | ||
| 1522 | .gmu_chipid = 0x07110000, | ||
| 1523 | .gmu_cgc_mode = 0x00020000, | ||
| 1524 | .bcms = (const struct a6xx_bcm[]) { | ||
| 1525 | { .name = "SH0", .buswidth = 16 }, | ||
| 1526 | { .name = "MC0", .buswidth = 4 }, | ||
| 1527 | { | ||
| 1528 | .name = "ACV", | ||
| 1529 | .fixed = true, | ||
| 1530 | .perfmode = BIT(3), | ||
| 1531 | .perfmode_bw = 16500000, | ||
| 1532 | }, | ||
| 1533 | { /* sentinel */ }, | ||
| 1534 | }, | ||
| 1535 | }, | ||
| 1536 | .preempt_record_size = 1536 * SZ_1K, | ||
| 1503 | }, { | 1537 | }, { |
| 1504 | .chip_ids = ADRENO_CHIP_IDS(0x43050a01), /* "C510v2" */ | 1538 | .chip_ids = ADRENO_CHIP_IDS(0x43050a01), /* "C510v2" */ |
| 1505 | .family = ADRENO_7XX_GEN2, | 1539 | .family = ADRENO_7XX_GEN2, |
| @@ -2180,7 +2214,7 @@ static const struct adreno_reglist a840_gbif[] = { · 674 unmodified lines | |||
| 2180 | { REG_A6XX_GBIF_QSB_SIDE1, 0x00071e20 }, | 2214 | { REG_A6XX_GBIF_QSB_SIDE1, 0x00071e20 }, |
| 2181 | { REG_A6XX_GBIF_QSB_SIDE2, 0x00071e20 }, | 2215 | { REG_A6XX_GBIF_QSB_SIDE2, 0x00071e20 }, |
| 2182 | { REG_A6XX_GBIF_QSB_SIDE3, 0x00071e20 }, | 2216 | { REG_A6XX_GBIF_QSB_SIDE3, 0x00071e20 }, |
| 2183 | { REG_A8XX_GBIF_CX_CONFIG, 0x20023000 }, | 2217 | { REG_A6XX_GBIF_CX_CONFIG, 0x20023000 }, |
| 2184 | { }, | 2218 | { }, |
| 2185 | }; | 2219 | }; |
| 2186 | 2220 | ||
| @@ -642,7 +642,7 @@ static void a6xx_rpmh_stop(struct a6xx_gmu *gmu) · 641 unmodified lines | |||
| 642 | int ret; | 642 | int ret; |
| 643 | u32 val; | 643 | u32 val; |
| 644 | 644 | ||
| 645 | if (test_and_clear_bit(GMU_STATUS_FW_START, &gmu->status)) | 645 | if (!test_and_clear_bit(GMU_STATUS_FW_START, &gmu->status)) |
| 646 | return; | 646 | return; |
| 647 | 647 | ||
| 648 | if (adreno_is_a840(adreno_gpu)) | 648 | if (adreno_is_a840(adreno_gpu)) |
| @@ -710,7 +710,8 @@ static void a6xx_gmu_rpmh_init(struct a6xx_gmu *gmu) · 61 unmodified lines | |||
| 710 | gmu_write_rscc(gmu, REG_A6XX_RSCC_HIDDEN_TCS_CMD0_DATA + 2, 0); | 710 | gmu_write_rscc(gmu, REG_A6XX_RSCC_HIDDEN_TCS_CMD0_DATA + 2, 0); |
| 711 | gmu_write_rscc(gmu, REG_A6XX_RSCC_HIDDEN_TCS_CMD0_ADDR + 2, 0); | 711 | gmu_write_rscc(gmu, REG_A6XX_RSCC_HIDDEN_TCS_CMD0_ADDR + 2, 0); |
| 712 | gmu_write_rscc(gmu, REG_A6XX_RSCC_HIDDEN_TCS_CMD0_DATA + 4, | 712 | gmu_write_rscc(gmu, REG_A6XX_RSCC_HIDDEN_TCS_CMD0_DATA + 4, |
| 713 | adreno_is_a740_family(adreno_gpu) ? 0x80000021 : 0x80000000); | 713 | (adreno_is_a740_family(adreno_gpu) || |
| 714 | adreno_is_a722(adreno_gpu)) ? 0x80000021 : 0x80000000); | ||
| 714 | gmu_write_rscc(gmu, REG_A6XX_RSCC_HIDDEN_TCS_CMD0_ADDR + 4, 0); | 715 | gmu_write_rscc(gmu, REG_A6XX_RSCC_HIDDEN_TCS_CMD0_ADDR + 4, 0); |
| 715 | gmu_write_rscc(gmu, REG_A6XX_RSCC_OVERRIDE_START_ADDR, 0); | 716 | gmu_write_rscc(gmu, REG_A6XX_RSCC_OVERRIDE_START_ADDR, 0); |
| 716 | gmu_write_rscc(gmu, REG_A6XX_RSCC_PDC_SEQ_START_ADDR, 0x4520); | 717 | gmu_write_rscc(gmu, REG_A6XX_RSCC_PDC_SEQ_START_ADDR, 0x4520); |
| @@ -718,7 +719,7 @@ static void a6xx_gmu_rpmh_init(struct a6xx_gmu *gmu) · 1 unmodified line | |||
| 718 | gmu_write_rscc(gmu, REG_A6XX_RSCC_PDC_MATCH_VALUE_HI, 0x4514); | 719 | gmu_write_rscc(gmu, REG_A6XX_RSCC_PDC_MATCH_VALUE_HI, 0x4514); |
| 719 | 720 | ||
| 720 | /* The second spin of A7xx GPUs messed with some register offsets.. */ | 721 | /* The second spin of A7xx GPUs messed with some register offsets.. */ |
| 721 | if (adreno_is_a740_family(adreno_gpu)) | 722 | if (adreno_is_a740_family(adreno_gpu) || adreno_is_a722(adreno_gpu)) |
| 722 | seqmem0_drv0_reg = REG_A7XX_RSCC_SEQ_MEM_0_DRV0_A740; | 723 | seqmem0_drv0_reg = REG_A7XX_RSCC_SEQ_MEM_0_DRV0_A740; |
| 723 | 724 | ||
| 724 | /* Load RSC sequencer uCode for sleep and wakeup */ | 725 | /* Load RSC sequencer uCode for sleep and wakeup */ |
| @@ -1032,9 +1033,11 @@ static int a6xx_gmu_fw_start(struct a6xx_gmu *gmu, unsigned int state) · 307 unmodified lines | |||
| 1032 | gpu_write(gpu, gbif_cx[i].offset, gbif_cx[i].value); | 1033 | gpu_write(gpu, gbif_cx[i].offset, gbif_cx[i].value); |
| 1033 | 1034 | ||
| 1034 | if (adreno_is_a8xx(adreno_gpu)) { | 1035 | if (adreno_is_a8xx(adreno_gpu)) { |
| 1035 | gpu_write(gpu, REG_A8XX_GBIF_CX_CONFIG, 0x20023000); | 1036 | gpu_write(gpu, REG_A6XX_GBIF_CX_CONFIG, 0x20023000); |
| 1036 | gmu_write(gmu, REG_A6XX_GMU_MRC_GBIF_QOS_CTRL, 0x33); | 1037 | gmu_write(gmu, REG_A6XX_GMU_MRC_GBIF_QOS_CTRL, 0x33); |
| 1037 | } | 1038 | } else if (adreno_is_a722(adreno_gpu)) |
| 1039 | gpu_rmw(gpu, REG_A6XX_GBIF_CX_CONFIG, GENMASK(31, 29), | ||
| 1040 | FIELD_PREP(GENMASK(31, 29), 2)); | ||
| 1038 | 1041 | ||
| 1039 | /* Set up the lowest idle level on the GMU */ | 1042 | /* Set up the lowest idle level on the GMU */ |
| 1040 | a6xx_gmu_power_config(gmu); | 1043 | a6xx_gmu_power_config(gmu); |
| @@ -1087,7 +1090,8 @@ static void a6xx_gmu_rpmh_off(struct a6xx_gmu *gmu) · 46 unmodified lines | |||
| 1087 | u32 val, seqmem_off = 0; | 1090 | u32 val, seqmem_off = 0; |
| 1088 | 1091 | ||
| 1089 | /* The second spin of A7xx GPUs messed with some register offsets.. */ | 1092 | /* The second spin of A7xx GPUs messed with some register offsets.. */ |
| 1090 | if (adreno_is_a740_family(adreno_gpu) || adreno_is_a8xx(adreno_gpu)) | 1093 | if (adreno_is_a740_family(adreno_gpu) || adreno_is_a722(adreno_gpu) || |
| 1094 | adreno_is_a8xx(adreno_gpu)) | ||
| 1091 | seqmem_off = 4; | 1095 | seqmem_off = 4; |
| 1092 | 1096 | ||
| 1093 | /* Make sure there are no outstanding RPMh votes */ | 1097 | /* Make sure there are no outstanding RPMh votes */ |
| @@ -1100,7 +1104,8 @@ static void a6xx_gmu_rpmh_off(struct a6xx_gmu *gmu) · 6 unmodified lines | |||
| 1100 | gmu_poll_timeout_rscc(gmu, REG_A6XX_RSCC_TCS3_DRV0_STATUS + seqmem_off, | 1104 | gmu_poll_timeout_rscc(gmu, REG_A6XX_RSCC_TCS3_DRV0_STATUS + seqmem_off, |
| 1101 | val, (val & 1), 100, 1000); | 1105 | val, (val & 1), 100, 1000); |
| 1102 | 1106 | ||
| 1103 | if (!adreno_is_a740_family(adreno_gpu) && !adreno_is_a8xx(adreno_gpu)) | 1107 | if (!adreno_is_a740_family(adreno_gpu) && !adreno_is_a722(adreno_gpu) && |
| 1108 | !adreno_is_a8xx(adreno_gpu)) | ||
| 1104 | return; | 1109 | return; |
| 1105 | 1110 | ||
| 1106 | gmu_poll_timeout_rscc(gmu, REG_A7XX_RSCC_TCS4_DRV0_STATUS + seqmem_off, | 1111 | gmu_poll_timeout_rscc(gmu, REG_A7XX_RSCC_TCS4_DRV0_STATUS + seqmem_off, |
| @@ -1465,6 +1470,9 @@ static void a6xx_gmu_shutdown(struct a6xx_gmu *gmu) · 358 unmodified lines | |||
| 1465 | /* Stop the interrupts and mask the hardware */ | 1470 | /* Stop the interrupts and mask the hardware */ |
| 1466 | a6xx_gmu_irq_disable(gmu); | 1471 | a6xx_gmu_irq_disable(gmu); |
| 1467 | 1472 | ||
| 1473 | /* Halt the gmu cm3 core */ | ||
| 1474 | gmu_write(gmu, REG_A6XX_GMU_CM3_SYSRESET, 1); | ||
| 1475 | |||
| 1468 | /* Tell RPMh to power off the GPU */ | 1476 | /* Tell RPMh to power off the GPU */ |
| 1469 | a6xx_rpmh_stop(gmu); | 1477 | a6xx_rpmh_stop(gmu); |
| 1470 | 1478 | ||
| @@ -1546,7 +1554,7 @@ static int a6xx_gmu_memory_alloc(struct a6xx_gmu *gmu, struct a6xx_gmu_bo *bo, · 75 unmodified lines | |||
| 1546 | flags |= MSM_BO_MAP_PRIV; | 1554 | flags |= MSM_BO_MAP_PRIV; |
| 1547 | } | 1555 | } |
| 1548 | 1556 | ||
| 1549 | bo->obj = msm_gem_new(dev, size, flags); | 1557 | bo->obj = msm_gem_new(dev, size, flags, NULL); |
| 1550 | if (IS_ERR(bo->obj)) | 1558 | if (IS_ERR(bo->obj)) |
| 1551 | return PTR_ERR(bo->obj); | 1559 | return PTR_ERR(bo->obj); |
| 1552 | 1560 | ||
| @@ -229,7 +229,7 @@ static void a6xx_set_pagetable(struct a6xx_gpu *a6xx_gpu, · 228 unmodified lines | |||
| 229 | { | 229 | { |
| 230 | bool sysprof = msm_gpu_sysprof_no_perfcntr_zap(&a6xx_gpu->base.base); | 230 | bool sysprof = msm_gpu_sysprof_no_perfcntr_zap(&a6xx_gpu->base.base); |
| 231 | struct msm_context *ctx = submit->queue->ctx; | 231 | struct msm_context *ctx = submit->queue->ctx; |
| 232 | struct drm_gpuvm *vm = msm_context_vm(submit->dev, ctx); | 232 | struct drm_gpuvm *vm = ctx->vm; |
| 233 | struct adreno_gpu *adreno_gpu = &a6xx_gpu->base; | 233 | struct adreno_gpu *adreno_gpu = &a6xx_gpu->base; |
| 234 | phys_addr_t ttbr; | 234 | phys_addr_t ttbr; |
| 235 | u32 asid; | 235 | u32 asid; |
| @@ -1273,7 +1273,8 @@ static int hw_init(struct msm_gpu *gpu) · 1037 unmodified lines | |||
| 1273 | if (!(adreno_is_a650_family(adreno_gpu) || | 1273 | if (!(adreno_is_a650_family(adreno_gpu) || |
| 1274 | adreno_is_a702(adreno_gpu) || | 1274 | adreno_is_a702(adreno_gpu) || |
| 1275 | adreno_is_a730(adreno_gpu))) { | 1275 | adreno_is_a730(adreno_gpu))) { |
| 1276 | gmem_range_min = adreno_is_a740_family(adreno_gpu) ? SZ_16M : SZ_1M; | 1276 | gmem_range_min = (adreno_is_a740_family(adreno_gpu) || |
| 1277 | adreno_is_a722(adreno_gpu)) ? SZ_16M : SZ_1M; | ||
| 1277 | 1278 | ||
| 1278 | /* Set the GMEM VA range [0x100000:0x100000 + gpu->gmem - 1] */ | 1279 | /* Set the GMEM VA range [0x100000:0x100000 + gpu->gmem - 1] */ |
| 1279 | gpu_write64(gpu, REG_A6XX_UCHE_GMEM_RANGE_MIN, gmem_range_min); | 1280 | gpu_write64(gpu, REG_A6XX_UCHE_GMEM_RANGE_MIN, gmem_range_min); |
| @@ -1338,6 +1339,7 @@ static int hw_init(struct msm_gpu *gpu) · 58 unmodified lines | |||
| 1338 | 1339 | ||
| 1339 | /* Enable fault detection */ | 1340 | /* Enable fault detection */ |
| 1340 | if (adreno_is_a612(adreno_gpu) || | 1341 | if (adreno_is_a612(adreno_gpu) || |
| 1342 | adreno_is_a722(adreno_gpu) || | ||
| 1341 | adreno_is_a730(adreno_gpu) || | 1343 | adreno_is_a730(adreno_gpu) || |
| 1342 | adreno_is_a740_family(adreno_gpu)) | 1344 | adreno_is_a740_family(adreno_gpu)) |
| 1343 | gpu_write(gpu, REG_A6XX_RBBM_INTERFACE_HANG_INT_CNTL, (1 << 30) | 0xcfffff); | 1345 | gpu_write(gpu, REG_A6XX_RBBM_INTERFACE_HANG_INT_CNTL, (1 << 30) | 0xcfffff); |
| @@ -1911,8 +1913,11 @@ static irqreturn_t a6xx_irq(struct msm_gpu *gpu) · 567 unmodified lines | |||
| 1911 | 1913 | ||
| 1912 | gpu_write(gpu, REG_A6XX_RBBM_INT_CLEAR_CMD, status); | 1914 | gpu_write(gpu, REG_A6XX_RBBM_INT_CLEAR_CMD, status); |
| 1913 | 1915 | ||
| 1914 | if (priv->disable_err_irq) | 1916 | if (priv->disable_err_irq) { |
| 1917 | /* Turn off interrupts to avoid interrupt storm */ | ||
| 1918 | gpu_write(gpu, REG_A6XX_RBBM_INT_0_MASK, A6XX_RBBM_INT_0_MASK_CP_CACHE_FLUSH_TS); | ||
| 1915 | status &= A6XX_RBBM_INT_0_MASK_CP_CACHE_FLUSH_TS; | 1919 | status &= A6XX_RBBM_INT_0_MASK_CP_CACHE_FLUSH_TS; |
| 1920 | } | ||
| 1916 | 1921 | ||
| 1917 | if (status & A6XX_RBBM_INT_0_MASK_RBBM_HANG_DETECT) | 1922 | if (status & A6XX_RBBM_INT_0_MASK_RBBM_HANG_DETECT) |
| 1918 | a6xx_fault_detect_irq(gpu); | 1923 | a6xx_fault_detect_irq(gpu); |
| @@ -2770,8 +2775,9 @@ static struct msm_gpu *a6xx_gpu_init(struct drm_device *dev) · 851 unmodified lines | |||
| 2770 | 2775 | ||
| 2771 | adreno_gpu->ubwc_config = qcom_ubwc_config_get_data(); | 2776 | adreno_gpu->ubwc_config = qcom_ubwc_config_get_data(); |
| 2772 | if (IS_ERR(adreno_gpu->ubwc_config)) { | 2777 | if (IS_ERR(adreno_gpu->ubwc_config)) { |
| 2778 | ret = PTR_ERR(adreno_gpu->ubwc_config); | ||
| 2773 | a6xx_destroy(&(a6xx_gpu->base.base)); | 2779 | a6xx_destroy(&(a6xx_gpu->base.base)); |
| 2774 | return ERR_CAST(adreno_gpu->ubwc_config); | 2780 | return ERR_PTR(ret); |
| 2775 | } | 2781 | } |
| 2776 | 2782 | ||
| 2777 | /* Set up the preemption specific bits and pieces for each ringbuffer */ | 2783 | /* Set up the preemption specific bits and pieces for each ringbuffer */ |
| @@ -11,12 +11,14 @@ · 10 unmodified lines | |||
| 11 | static const unsigned int *gen7_0_0_external_core_regs[] __always_unused; | 11 | static const unsigned int *gen7_0_0_external_core_regs[] __always_unused; |
| 12 | static const unsigned int *gen7_2_0_external_core_regs[] __always_unused; | 12 | static const unsigned int *gen7_2_0_external_core_regs[] __always_unused; |
| 13 | static const unsigned int *gen7_9_0_external_core_regs[] __always_unused; | 13 | static const unsigned int *gen7_9_0_external_core_regs[] __always_unused; |
| 14 | static const unsigned int *gen7_17_0_external_core_regs[] __always_unused; | ||
| 14 | static const struct gen7_sptp_cluster_registers gen7_9_0_sptp_clusters[] __always_unused; | 15 | static const struct gen7_sptp_cluster_registers gen7_9_0_sptp_clusters[] __always_unused; |
| 15 | static const u32 gen7_9_0_cx_debugbus_blocks[] __always_unused; | 16 | static const u32 gen7_9_0_cx_debugbus_blocks[] __always_unused; |
| 16 | 17 | ||
| 17 | #include "adreno_gen7_0_0_snapshot.h" | 18 | #include "adreno_gen7_0_0_snapshot.h" |
| 18 | #include "adreno_gen7_2_0_snapshot.h" | 19 | #include "adreno_gen7_2_0_snapshot.h" |
| 19 | #include "adreno_gen7_9_0_snapshot.h" | 20 | #include "adreno_gen7_9_0_snapshot.h" |
| 21 | #include "adreno_gen7_17_0_snapshot.h" | ||
| 20 | 22 | ||
| 21 | struct a6xx_gpu_state_obj { | 23 | struct a6xx_gpu_state_obj { |
| 22 | const void *handle; | 24 | const void *handle; |
| @@ -404,8 +406,13 @@ static void a7xx_get_debugbus_blocks(struct msm_gpu *gpu, · 381 unmodified lines | |||
| 404 | int i; | 406 | int i; |
| 405 | 407 | ||
| 406 | if (adreno_gpu->info->family == ADRENO_7XX_GEN1) { | 408 | if (adreno_gpu->info->family == ADRENO_7XX_GEN1) { |
| 407 | debugbus_blocks = gen7_0_0_debugbus_blocks; | 409 | if (adreno_is_a722(adreno_gpu)) { |
| 408 | debugbus_blocks_count = ARRAY_SIZE(gen7_0_0_debugbus_blocks); | 410 | debugbus_blocks = gen7_17_0_debugbus_blocks; |
| 411 | debugbus_blocks_count = ARRAY_SIZE(gen7_17_0_debugbus_blocks); | ||
| 412 | } else { | ||
| 413 | debugbus_blocks = gen7_0_0_debugbus_blocks; | ||
| 414 | debugbus_blocks_count = ARRAY_SIZE(gen7_0_0_debugbus_blocks); | ||
| 415 | } | ||
| 409 | gbif_debugbus_blocks = a7xx_gbif_debugbus_blocks; | 416 | gbif_debugbus_blocks = a7xx_gbif_debugbus_blocks; |
| 410 | gbif_debugbus_blocks_count = ARRAY_SIZE(a7xx_gbif_debugbus_blocks); | 417 | gbif_debugbus_blocks_count = ARRAY_SIZE(a7xx_gbif_debugbus_blocks); |
| 411 | } else if (adreno_gpu->info->family == ADRENO_7XX_GEN2) { | 418 | } else if (adreno_gpu->info->family == ADRENO_7XX_GEN2) { |
| @@ -678,8 +685,13 @@ static void a7xx_get_dbgahb_clusters(struct msm_gpu *gpu, · 266 unmodified lines | |||
| 678 | unsigned dbgahb_clusters_size; | 685 | unsigned dbgahb_clusters_size; |
| 679 | 686 | ||
| 680 | if (adreno_gpu->info->family == ADRENO_7XX_GEN1) { | 687 | if (adreno_gpu->info->family == ADRENO_7XX_GEN1) { |
| 681 | dbgahb_clusters = gen7_0_0_sptp_clusters; | 688 | if (adreno_is_a722(adreno_gpu)) { |
| 682 | dbgahb_clusters_size = ARRAY_SIZE(gen7_0_0_sptp_clusters); | 689 | dbgahb_clusters = gen7_17_0_sptp_clusters; |
| 690 | dbgahb_clusters_size = ARRAY_SIZE(gen7_17_0_sptp_clusters); | ||
| 691 | } else { | ||
| 692 | dbgahb_clusters = gen7_0_0_sptp_clusters; | ||
| 693 | dbgahb_clusters_size = ARRAY_SIZE(gen7_0_0_sptp_clusters); | ||
| 694 | } | ||
| 683 | } else if (adreno_gpu->info->family == ADRENO_7XX_GEN2) { | 695 | } else if (adreno_gpu->info->family == ADRENO_7XX_GEN2) { |
| 684 | dbgahb_clusters = gen7_2_0_sptp_clusters; | 696 | dbgahb_clusters = gen7_2_0_sptp_clusters; |
| 685 | dbgahb_clusters_size = ARRAY_SIZE(gen7_2_0_sptp_clusters); | 697 | dbgahb_clusters_size = ARRAY_SIZE(gen7_2_0_sptp_clusters); |
| @@ -839,8 +851,13 @@ static void a7xx_get_clusters(struct msm_gpu *gpu, · 153 unmodified lines | |||
| 839 | unsigned clusters_size; | 851 | unsigned clusters_size; |
| 840 | 852 | ||
| 841 | if (adreno_gpu->info->family == ADRENO_7XX_GEN1) { | 853 | if (adreno_gpu->info->family == ADRENO_7XX_GEN1) { |
| 842 | clusters = gen7_0_0_clusters; | 854 | if (adreno_is_a722(adreno_gpu)) { |
| 843 | clusters_size = ARRAY_SIZE(gen7_0_0_clusters); | 855 | clusters = gen7_17_0_clusters; |
| 856 | clusters_size = ARRAY_SIZE(gen7_17_0_clusters); | ||
| 857 | } else { | ||
| 858 | clusters = gen7_0_0_clusters; | ||
| 859 | clusters_size = ARRAY_SIZE(gen7_0_0_clusters); | ||
| 860 | } | ||
| 844 | } else if (adreno_gpu->info->family == ADRENO_7XX_GEN2) { | 861 | } else if (adreno_gpu->info->family == ADRENO_7XX_GEN2) { |
| 845 | clusters = gen7_2_0_clusters; | 862 | clusters = gen7_2_0_clusters; |
| 846 | clusters_size = ARRAY_SIZE(gen7_2_0_clusters); | 863 | clusters_size = ARRAY_SIZE(gen7_2_0_clusters); |
| @@ -977,8 +994,13 @@ static void a7xx_get_shaders(struct msm_gpu *gpu, · 130 unmodified lines | |||
| 977 | int i; | 994 | int i; |
| 978 | 995 | ||
| 979 | if (adreno_gpu->info->family == ADRENO_7XX_GEN1) { | 996 | if (adreno_gpu->info->family == ADRENO_7XX_GEN1) { |
| 980 | shader_blocks = gen7_0_0_shader_blocks; | 997 | if (adreno_is_a722(adreno_gpu)) { |
| 981 | num_shader_blocks = ARRAY_SIZE(gen7_0_0_shader_blocks); | 998 | shader_blocks = gen7_17_0_shader_blocks; |
| 999 | num_shader_blocks = ARRAY_SIZE(gen7_17_0_shader_blocks); | ||
| 1000 | } else { | ||
| 1001 | shader_blocks = gen7_0_0_shader_blocks; | ||
| 1002 | num_shader_blocks = ARRAY_SIZE(gen7_0_0_shader_blocks); | ||
| 1003 | } | ||
| 982 | } else if (adreno_gpu->info->family == ADRENO_7XX_GEN2) { | 1004 | } else if (adreno_gpu->info->family == ADRENO_7XX_GEN2) { |
| 983 | shader_blocks = gen7_2_0_shader_blocks; | 1005 | shader_blocks = gen7_2_0_shader_blocks; |
| 984 | num_shader_blocks = ARRAY_SIZE(gen7_2_0_shader_blocks); | 1006 | num_shader_blocks = ARRAY_SIZE(gen7_2_0_shader_blocks); |
| @@ -1244,9 +1266,12 @@ static void a6xx_get_gmu_registers(struct msm_gpu *gpu, · 259 unmodified lines | |||
| 1244 | _a6xx_get_gmu_registers(gpu, a6xx_state, &a6xx_gmu_reglist[1], | 1266 | _a6xx_get_gmu_registers(gpu, a6xx_state, &a6xx_gmu_reglist[1], |
| 1245 | &a6xx_state->gmu_registers[1], true); | 1267 | &a6xx_state->gmu_registers[1], true); |
| 1246 | 1268 | ||
| 1247 | if (adreno_is_a621(adreno_gpu) || adreno_is_a623(adreno_gpu)) | 1269 | if (adreno_is_a621(adreno_gpu)) |
| 1248 | _a6xx_get_gmu_registers(gpu, a6xx_state, &a621_gpucc_reg, | 1270 | _a6xx_get_gmu_registers(gpu, a6xx_state, &a621_gpucc_reg, |
| 1249 | &a6xx_state->gmu_registers[2], false); | 1271 | &a6xx_state->gmu_registers[2], false); |
| 1272 | else if (adreno_is_a623(adreno_gpu) || adreno_is_a663(adreno_gpu)) | ||
| 1273 | _a6xx_get_gmu_registers(gpu, a6xx_state, &a623_gpucc_reg, | ||
| 1274 | &a6xx_state->gmu_registers[2], false); | ||
| 1250 | else | 1275 | else |
| 1251 | _a6xx_get_gmu_registers(gpu, a6xx_state, &a6xx_gpucc_reg, | 1276 | _a6xx_get_gmu_registers(gpu, a6xx_state, &a6xx_gpucc_reg, |
| 1252 | &a6xx_state->gmu_registers[2], false); | 1277 | &a6xx_state->gmu_registers[2], false); |
| @@ -1376,8 +1401,13 @@ static void a7xx_get_registers(struct msm_gpu *gpu, · 123 unmodified lines | |||
| 1376 | const struct gen7_reg_list *reglist; | 1401 | const struct gen7_reg_list *reglist; |
| 1377 | 1402 | ||
| 1378 | if (adreno_gpu->info->family == ADRENO_7XX_GEN1) { | 1403 | if (adreno_gpu->info->family == ADRENO_7XX_GEN1) { |
| 1379 | reglist = gen7_0_0_reg_list; | 1404 | if (adreno_is_a722(adreno_gpu)) { |
| 1380 | pre_crashdumper_regs = gen7_0_0_pre_crashdumper_gpu_registers; | 1405 | reglist = gen7_17_0_reg_list; |
| 1406 | pre_crashdumper_regs = gen7_9_0_pre_crashdumper_gpu_registers; | ||
| 1407 | } else { | ||
| 1408 | reglist = gen7_0_0_reg_list; | ||
| 1409 | pre_crashdumper_regs = gen7_0_0_pre_crashdumper_gpu_registers; | ||
| 1410 | } | ||
| 1381 | } else if (adreno_gpu->info->family == ADRENO_7XX_GEN2) { | 1411 | } else if (adreno_gpu->info->family == ADRENO_7XX_GEN2) { |
| 1382 | reglist = gen7_2_0_reg_list; | 1412 | reglist = gen7_2_0_reg_list; |
| 1383 | pre_crashdumper_regs = gen7_0_0_pre_crashdumper_gpu_registers; | 1413 | pre_crashdumper_regs = gen7_0_0_pre_crashdumper_gpu_registers; |
| @@ -1433,7 +1463,9 @@ static void a7xx_get_post_crashdumper_registers(struct msm_gpu *gpu, · 49 unmodified lines | |||
| 1433 | const u32 *regs; | 1463 | const u32 *regs; |
| 1434 | 1464 | ||
| 1435 | BUG_ON(adreno_gpu->info->family > ADRENO_7XX_GEN3); | 1465 | BUG_ON(adreno_gpu->info->family > ADRENO_7XX_GEN3); |
| 1436 | regs = gen7_0_0_post_crashdumper_registers; | 1466 | regs = adreno_is_a722(adreno_gpu) ? |
| 1467 | gen7_17_0_post_crashdumper_registers : | ||
| 1468 | gen7_0_0_post_crashdumper_registers; | ||
| 1437 | 1469 | ||
| 1438 | a7xx_get_ahb_gpu_registers(gpu, | 1470 | a7xx_get_ahb_gpu_registers(gpu, |
| 1439 | a6xx_state, regs, | 1471 | a6xx_state, regs, |
| @@ -1540,19 +1572,35 @@ static void a7xx_get_indexed_registers(struct msm_gpu *gpu, · 100 unmodified lines | |||
| 1540 | { | 1572 | { |
| 1541 | struct adreno_gpu *adreno_gpu = to_adreno_gpu(gpu); | 1573 | struct adreno_gpu *adreno_gpu = to_adreno_gpu(gpu); |
| 1542 | const struct a6xx_indexed_registers *indexed_regs; | 1574 | const struct a6xx_indexed_registers *indexed_regs; |
| 1575 | const struct a6xx_indexed_registers *mempool_regs; | ||
| 1543 | int i, indexed_count, mempool_count; | 1576 | int i, indexed_count, mempool_count; |
| 1577 | bool concurrent_binning; | ||
| 1544 | 1578 | ||
| 1545 | if (adreno_gpu->info->family <= ADRENO_7XX_GEN2) { | 1579 | if (adreno_is_a722(adreno_gpu)) { |
| 1580 | /* | ||
| 1581 | * Eliza has no BV or LPAC SQE — skip the BV/LPAC indexed | ||
| 1582 | * registers and the BV mempool | ||
| 1583 | */ | ||
| 1584 | indexed_regs = gen7_17_0_cp_indexed_reglist; | ||
| 1585 | indexed_count = ARRAY_SIZE(gen7_17_0_cp_indexed_reglist); | ||
| 1586 | mempool_regs = a7xx_cp_mempool_indexed; | ||
| 1587 | mempool_count = ARRAY_SIZE(a7xx_cp_mempool_indexed); | ||
| 1588 | concurrent_binning = false; | ||
| 1589 | } else if (adreno_gpu->info->family <= ADRENO_7XX_GEN2) { | ||
| 1546 | indexed_regs = a7xx_indexed_reglist; | 1590 | indexed_regs = a7xx_indexed_reglist; |
| 1547 | indexed_count = ARRAY_SIZE(a7xx_indexed_reglist); | 1591 | indexed_count = ARRAY_SIZE(a7xx_indexed_reglist); |
| 1592 | mempool_regs = a7xx_cp_bv_mempool_indexed; | ||
| 1593 | mempool_count = ARRAY_SIZE(a7xx_cp_bv_mempool_indexed); | ||
| 1594 | concurrent_binning = true; | ||
| 1548 | } else { | 1595 | } else { |
| 1549 | BUG_ON(adreno_gpu->info->family != ADRENO_7XX_GEN3); | 1596 | BUG_ON(adreno_gpu->info->family != ADRENO_7XX_GEN3); |
| 1550 | indexed_regs = gen7_9_0_cp_indexed_reg_list; | 1597 | indexed_regs = gen7_9_0_cp_indexed_reg_list; |
| 1551 | indexed_count = ARRAY_SIZE(gen7_9_0_cp_indexed_reg_list); | 1598 | indexed_count = ARRAY_SIZE(gen7_9_0_cp_indexed_reg_list); |
| 1599 | mempool_regs = a7xx_cp_bv_mempool_indexed; | ||
| 1600 | mempool_count = ARRAY_SIZE(a7xx_cp_bv_mempool_indexed); | ||
| 1601 | concurrent_binning = true; | ||
| 1552 | } | 1602 | } |
| 1553 | 1603 | ||
| 1554 | mempool_count = ARRAY_SIZE(a7xx_cp_bv_mempool_indexed); | ||
| 1555 | |||
| 1556 | a6xx_state->indexed_regs = state_kcalloc(a6xx_state, | 1604 | a6xx_state->indexed_regs = state_kcalloc(a6xx_state, |
| 1557 | indexed_count + mempool_count, | 1605 | indexed_count + mempool_count, |
| 1558 | sizeof(*a6xx_state->indexed_regs)); | 1606 | sizeof(*a6xx_state->indexed_regs)); |
| @@ -1567,15 +1615,17 @@ static void a7xx_get_indexed_registers(struct msm_gpu *gpu, · 8 unmodified lines | |||
| 1567 | &a6xx_state->indexed_regs[i]); | 1615 | &a6xx_state->indexed_regs[i]); |
| 1568 | 1616 | ||
| 1569 | gpu_rmw(gpu, REG_A6XX_CP_CHICKEN_DBG, 0, BIT(2)); | 1617 | gpu_rmw(gpu, REG_A6XX_CP_CHICKEN_DBG, 0, BIT(2)); |
| 1570 | gpu_rmw(gpu, REG_A7XX_CP_BV_CHICKEN_DBG, 0, BIT(2)); | 1618 | if (concurrent_binning) |
| 1619 | gpu_rmw(gpu, REG_A7XX_CP_BV_CHICKEN_DBG, 0, BIT(2)); | ||
| 1571 | 1620 | ||
| 1572 | /* Get the contents of the CP_BV mempool */ | 1621 | /* Get the contents of the CP_BV mempool */ |
| 1573 | for (i = 0; i < mempool_count; i++) | 1622 | for (i = 0; i < mempool_count; i++) |
| 1574 | a6xx_get_indexed_regs(gpu, a6xx_state, &a7xx_cp_bv_mempool_indexed[i], | 1623 | a6xx_get_indexed_regs(gpu, a6xx_state, &mempool_regs[i], |
| 1575 | &a6xx_state->indexed_regs[indexed_count + i]); | 1624 | &a6xx_state->indexed_regs[indexed_count + i]); |
| 1576 | 1625 | ||
| 1577 | gpu_rmw(gpu, REG_A6XX_CP_CHICKEN_DBG, BIT(2), 0); | 1626 | gpu_rmw(gpu, REG_A6XX_CP_CHICKEN_DBG, BIT(2), 0); |
| 1578 | gpu_rmw(gpu, REG_A7XX_CP_BV_CHICKEN_DBG, BIT(2), 0); | 1627 | if (concurrent_binning) |
| 1628 | gpu_rmw(gpu, REG_A7XX_CP_BV_CHICKEN_DBG, BIT(2), 0); | ||
| 1579 | return; | 1629 | return; |
| 1580 | } | 1630 | } |
| 1581 | 1631 | ||
| @@ -377,6 +377,17 @@ static const u32 a6xx_gmu_gpucc_registers[] = { · 376 unmodified lines | |||
| 377 | }; | 377 | }; |
| 378 | 378 | ||
| 379 | static const u32 a621_gmu_gpucc_registers[] = { | 379 | static const u32 a621_gmu_gpucc_registers[] = { |
| 380 | /* GPU CC */ | ||
| 381 | 0x24000, 0x2400e, 0x24400, 0x2440e, 0x24800, 0x24805, 0x24c00, 0x24cff, | ||
| 382 | 0x25800, 0x25804, 0x25c00, 0x25c04, 0x26000, 0x26004, 0x26400, 0x26405, | ||
| 383 | 0x26414, 0x2641d, 0x2642a, 0x26430, 0x26432, 0x26432, 0x26441, 0x26455, | ||
| 384 | 0x26466, 0x26468, 0x26478, 0x2647a, 0x26489, 0x2648a, 0x2649c, 0x2649e, | ||
| 385 | 0x264a0, 0x264a3, 0x264b3, 0x264b5, 0x264c5, 0x264c7, 0x264d6, 0x264d8, | ||
| 386 | 0x264e8, 0x264e9, 0x264f9, 0x264fc, 0x2650b, 0x2650c, 0x2651c, 0x2651e, | ||
| 387 | 0x26540, 0x26570, 0x26600, 0x26616, 0x26620, 0x2662d, | ||
| 388 | }; | ||
| 389 | |||
| 390 | static const u32 a623_gmu_gpucc_registers[] = { | ||
| 380 | /* GPU CC */ | 391 | /* GPU CC */ |
| 381 | 0x24000, 0x2400e, 0x24400, 0x2440e, 0x25800, 0x25804, 0x25c00, 0x25c04, | 392 | 0x24000, 0x2400e, 0x24400, 0x2440e, 0x25800, 0x25804, 0x25c00, 0x25c04, |
| 382 | 0x26000, 0x26004, 0x26400, 0x26405, 0x26414, 0x2641d, 0x2642a, 0x26430, | 393 | 0x26000, 0x26004, 0x26400, 0x26405, 0x26414, 0x2641d, 0x2642a, 0x26430, |
| @@ -402,6 +413,7 @@ static const struct a6xx_registers a6xx_gmu_reglist[] = { · 19 unmodified lines | |||
| 402 | 413 | ||
| 403 | static const struct a6xx_registers a6xx_gpucc_reg = REGS(a6xx_gmu_gpucc_registers, 0, 0); | 414 | static const struct a6xx_registers a6xx_gpucc_reg = REGS(a6xx_gmu_gpucc_registers, 0, 0); |
| 404 | static const struct a6xx_registers a621_gpucc_reg = REGS(a621_gmu_gpucc_registers, 0, 0); | 415 | static const struct a6xx_registers a621_gpucc_reg = REGS(a621_gmu_gpucc_registers, 0, 0); |
| 416 | static const struct a6xx_registers a623_gpucc_reg = REGS(a623_gmu_gpucc_registers, 0, 0); | ||
| 405 | 417 | ||
| 406 | static u32 a6xx_get_cp_roq_size(struct msm_gpu *gpu); | 418 | static u32 a6xx_get_cp_roq_size(struct msm_gpu *gpu); |
| 407 | static u32 a7xx_get_cp_roq_size(struct msm_gpu *gpu); | 419 | static u32 a7xx_get_cp_roq_size(struct msm_gpu *gpu); |
| @@ -462,6 +474,11 @@ static const struct a6xx_indexed_registers a7xx_cp_bv_mempool_indexed[] = { · 54 unmodified lines | |||
| 462 | REG_A7XX_CP_BV_MEM_POOL_DBG_DATA, 0x2200, NULL }, | 474 | REG_A7XX_CP_BV_MEM_POOL_DBG_DATA, 0x2200, NULL }, |
| 463 | }; | 475 | }; |
| 464 | 476 | ||
| 477 | static const struct a6xx_indexed_registers a7xx_cp_mempool_indexed[] = { | ||
| 478 | { "CP_MEM_POOL_DBG", REG_A6XX_CP_MEM_POOL_DBG_ADDR, | ||
| 479 | REG_A6XX_CP_MEM_POOL_DBG_DATA, 0x2200, NULL }, | ||
| 480 | }; | ||
| 481 | |||
| 465 | #define DEBUGBUS(_id, _count) { .id = _id, .name = #_id, .count = _count } | 482 | #define DEBUGBUS(_id, _count) { .id = _id, .name = #_id, .count = _count } |
| 466 | 483 | ||
| 467 | static const struct a6xx_debugbus_block { | 484 | static const struct a6xx_debugbus_block { |
| @@ -228,7 +228,7 @@ static void a8xx_set_hwcg(struct msm_gpu *gpu, bool state) · 227 unmodified lines | |||
| 228 | * GMU enables clk gating in GBIF during boot up. So, | 228 | * GMU enables clk gating in GBIF during boot up. So, |
| 229 | * override that here when hwcg feature is disabled | 229 | * override that here when hwcg feature is disabled |
| 230 | */ | 230 | */ |
| 231 | gpu_rmw(gpu, REG_A8XX_GBIF_CX_CONFIG, BIT(0), 0); | 231 | gpu_rmw(gpu, REG_A6XX_GBIF_CX_CONFIG, BIT(0), 0); |
| 232 | } | 232 | } |
| 233 | } | 233 | } |
| 234 | 234 | ||
| @@ -1211,8 +1211,11 @@ irqreturn_t a8xx_irq(struct msm_gpu *gpu) · 976 unmodified lines | |||
| 1211 | 1211 | ||
| 1212 | gpu_write(gpu, REG_A8XX_RBBM_INT_CLEAR_CMD, status); | 1212 | gpu_write(gpu, REG_A8XX_RBBM_INT_CLEAR_CMD, status); |
| 1213 | 1213 | ||
| 1214 | if (priv->disable_err_irq) | 1214 | if (priv->disable_err_irq) { |
| 1215 | /* Turn off interrupts to avoid interrupt storm */ | ||
| 1216 | gpu_write(gpu, REG_A8XX_RBBM_INT_0_MASK, A6XX_RBBM_INT_0_MASK_CP_CACHE_FLUSH_TS); | ||
| 1215 | status &= A6XX_RBBM_INT_0_MASK_CP_CACHE_FLUSH_TS; | 1217 | status &= A6XX_RBBM_INT_0_MASK_CP_CACHE_FLUSH_TS; |
| 1218 | } | ||
| 1216 | 1219 | ||
| 1217 | if (status & A6XX_RBBM_INT_0_MASK_RBBM_HANG_DETECT) | 1220 | if (status & A6XX_RBBM_INT_0_MASK_RBBM_HANG_DETECT) |
| 1218 | a8xx_fault_detect_irq(gpu); | 1221 | a8xx_fault_detect_irq(gpu); |
| @@ -0,0 +1,428 @@ | |||
| 1 | /* SPDX-License-Identifier: GPL-2.0-only */ | ||
| 2 | /* | ||
| 3 | * Copyright (c) Qualcomm Innovation Center, Inc. All rights reserved. | ||
| 4 | */ | ||
| 5 | #ifndef __ADRENO_GEN7_17_0_SNAPSHOT_H | ||
| 6 | #define __ADRENO_GEN7_17_0_SNAPSHOT_H | ||
| 7 | |||
| 8 | #include "a6xx_gpu_state.h" | ||
| 9 | |||
| 10 | /* | ||
| 11 | * Snapshot tables for Adreno A722 (Eliza). | ||
| 12 | * Cluster sub-arrays that are identical to A730 reference gen7_0_0_* | ||
| 13 | * symbols; adreno_gen7_0_0_snapshot.h is included first in the TU. | ||
| 14 | */ | ||
| 15 | |||
| 16 | static const u32 gen7_17_0_rscc_registers[] = { | ||
| 17 | 0x14000, 0x14034, 0x14036, 0x14036, 0x14040, 0x14042, 0x14044, 0x14045, | ||
| 18 | 0x14047, 0x14047, 0x14080, 0x14084, 0x14089, 0x1408c, 0x14091, 0x14094, | ||
| 19 | 0x14099, 0x1409c, 0x140a1, 0x140a4, 0x140a9, 0x140ac, 0x140b1, 0x140b4, | ||
| 20 | 0x140b9, 0x140bc, 0x14100, 0x14104, 0x14114, 0x14119, 0x14124, 0x14132, | ||
| 21 | 0x14154, 0x1416b, 0x14340, 0x14341, 0x14344, 0x14344, 0x14346, 0x1437c, | ||
| 22 | 0x143f0, 0x143f8, 0x143fa, 0x143fe, 0x14400, 0x14404, 0x14406, 0x1440a, | ||
| 23 | 0x1440c, 0x14410, 0x14412, 0x14416, 0x14418, 0x1441c, 0x1441e, 0x14422, | ||
| 24 | 0x14424, 0x14424, 0x14498, 0x144a0, 0x144a2, 0x144a6, 0x144a8, 0x144ac, | ||
| 25 | 0x144ae, 0x144b2, 0x144b4, 0x144b8, 0x144ba, 0x144be, 0x144c0, 0x144c4, | ||
| 26 | 0x144c6, 0x144ca, 0x144cc, 0x144cc, 0x14540, 0x14548, 0x1454a, 0x1454e, | ||
| 27 | 0x14550, 0x14554, 0x14556, 0x1455a, 0x1455c, 0x14560, 0x14562, 0x14566, | ||
| 28 | 0x14568, 0x1456c, 0x1456e, 0x14572, 0x14574, 0x14574, 0x145e8, 0x145f0, | ||
| 29 | 0x145f2, 0x145f6, 0x145f8, 0x145fc, 0x145fe, 0x14602, 0x14604, 0x14608, | ||
| 30 | 0x1460a, 0x1460e, 0x14610, 0x14614, 0x14616, 0x1461a, 0x1461c, 0x1461c, | ||
| 31 | 0x14690, 0x14698, 0x1469a, 0x1469e, 0x146a0, 0x146a4, 0x146a6, 0x146aa, | ||
| 32 | 0x146ac, 0x146b0, 0x146b2, 0x146b6, 0x146b8, 0x146bc, 0x146be, 0x146c2, | ||
| 33 | 0x146c4, 0x146c4, 0x14738, 0x14740, 0x14742, 0x14746, 0x14748, 0x1474c, | ||
| 34 | 0x1474e, 0x14752, 0x14754, 0x14758, 0x1475a, 0x1475e, 0x14760, 0x14764, | ||
| 35 | 0x14766, 0x1476a, 0x1476c, 0x1476c, 0x147e0, 0x147e8, 0x147ea, 0x147ee, | ||
| 36 | 0x147f0, 0x147f4, 0x147f6, 0x147fa, 0x147fc, 0x14800, 0x14802, 0x14806, | ||
| 37 | 0x14808, 0x1480c, 0x1480e, 0x14812, 0x14814, 0x14814, 0x14888, 0x14890, | ||
| 38 | 0x14892, 0x14896, 0x14898, 0x1489c, 0x1489e, 0x148a2, 0x148a4, 0x148a8, | ||
| 39 | 0x148aa, 0x148ae, 0x148b0, 0x148b4, 0x148b6, 0x148ba, 0x148bc, 0x148bc, | ||
| 40 | 0x14930, 0x14938, 0x1493a, 0x1493e, 0x14940, 0x14944, 0x14946, 0x1494a, | ||
| 41 | 0x1494c, 0x14950, 0x14952, 0x14956, 0x14958, 0x1495c, 0x1495e, 0x14962, | ||
| 42 | 0x14964, 0x14964, | ||
| 43 | UINT_MAX, UINT_MAX, | ||
| 44 | }; | ||
| 45 | static_assert(IS_ALIGNED(sizeof(gen7_17_0_rscc_registers), 8)); | ||
| 46 | |||
| 47 | static const u32 gen7_17_0_cpr_registers[] = { | ||
| 48 | 0x26800, 0x26805, 0x26808, 0x2680c, 0x26814, 0x26814, 0x2681c, 0x2681c, | ||
| 49 | 0x26820, 0x26838, 0x26840, 0x26840, 0x26848, 0x26848, 0x26850, 0x26850, | ||
| 50 | 0x26880, 0x2688e, 0x26980, 0x269b0, 0x269c0, 0x269c2, 0x269c6, 0x269c8, | ||
| 51 | 0x269e0, 0x269ee, 0x269fb, 0x269ff, 0x26a02, 0x26a07, 0x26a09, 0x26a0b, | ||
| 52 | 0x26a10, 0x26b0f, 0x27440, 0x27441, 0x27444, 0x27444, 0x27480, 0x274a2, | ||
| 53 | 0x274ac, 0x274c4, 0x274c8, 0x274da, | ||
| 54 | UINT_MAX, UINT_MAX, | ||
| 55 | }; | ||
| 56 | static_assert(IS_ALIGNED(sizeof(gen7_17_0_cpr_registers), 8)); | ||
| 57 | |||
| 58 | static const u32 gen7_17_0_gpucc_registers[] = { | ||
| 59 | 0x24000, 0x2400f, 0x24400, 0x2440f, 0x24800, 0x24805, 0x24c00, 0x24cff, | ||
| 60 | 0x25400, 0x25404, 0x25800, 0x25804, 0x25c00, 0x25c04, 0x26000, 0x26004, | ||
| 61 | 0x26400, 0x26405, 0x26414, 0x2641d, 0x2642a, 0x2642c, 0x2642e, 0x26432, | ||
| 62 | 0x26434, 0x26434, 0x26443, 0x26457, 0x26459, 0x2645d, 0x2645f, 0x26464, | ||
| 63 | 0x26477, 0x26479, 0x26489, 0x2648b, 0x2649a, 0x2649b, 0x264ad, 0x264af, | ||
| 64 | 0x264b1, 0x264b5, 0x264d6, 0x264d8, 0x264e7, 0x264e9, 0x264f9, 0x264fa, | ||
| 65 | 0x2650a, 0x2650d, 0x2651f, 0x26520, 0x2652d, 0x2652f, 0x2653e, 0x2653e, | ||
| 66 | 0x26540, 0x2654e, 0x26554, 0x26573, 0x26576, 0x26576, 0x26593, 0x26593, | ||
| 67 | 0x26600, 0x26616, 0x26620, 0x2662d, 0x26630, 0x26631, 0x26635, 0x26635, | ||
| 68 | 0x26637, 0x26637, 0x2663a, 0x2663a, 0x26642, 0x26642, 0x26656, 0x26658, | ||
| 69 | 0x2665b, 0x2665d, 0x2665f, 0x26662, | ||
| 70 | UINT_MAX, UINT_MAX, | ||
| 71 | }; | ||
| 72 | static_assert(IS_ALIGNED(sizeof(gen7_17_0_gpucc_registers), 8)); | ||
| 73 | |||
| 74 | static const u32 *gen7_17_0_external_core_regs[] = { | ||
| 75 | gen7_17_0_gpucc_registers, | ||
| 76 | gen7_17_0_cpr_registers, | ||
| 77 | }; | ||
| 78 | |||
| 79 | static const u32 gen7_17_0_debugbus_blocks[] = { | ||
| 80 | A7XX_DBGBUS_CP_0_0, | ||
| 81 | A7XX_DBGBUS_CP_0_1, | ||
| 82 | A7XX_DBGBUS_RBBM, | ||
| 83 | A7XX_DBGBUS_HLSQ, | ||
| 84 | A7XX_DBGBUS_UCHE_0, | ||
| 85 | A7XX_DBGBUS_TESS_BR, | ||
| 86 | A7XX_DBGBUS_PC_BR, | ||
| 87 | A7XX_DBGBUS_VFDP_BR, | ||
| 88 | A7XX_DBGBUS_VPC_BR, | ||
| 89 | A7XX_DBGBUS_TSE_BR, | ||
| 90 | A7XX_DBGBUS_RAS_BR, | ||
| 91 | A7XX_DBGBUS_VSC, | ||
| 92 | A7XX_DBGBUS_COM_0, | ||
| 93 | A7XX_DBGBUS_LRZ_BR, | ||
| 94 | A7XX_DBGBUS_UFC_0, | ||
| 95 | A7XX_DBGBUS_UFC_1, | ||
| 96 | A7XX_DBGBUS_GMU_GX, | ||
| 97 | A7XX_DBGBUS_DBGC, | ||
| 98 | A7XX_DBGBUS_GPC_BR, | ||
| 99 | A7XX_DBGBUS_LARC, | ||
| 100 | A7XX_DBGBUS_HLSQ_SPTP, | ||
| 101 | A7XX_DBGBUS_RB_0, | ||
| 102 | A7XX_DBGBUS_RB_1, | ||
| 103 | A7XX_DBGBUS_UCHE_WRAPPER, | ||
| 104 | A7XX_DBGBUS_CCU_0, | ||
| 105 | A7XX_DBGBUS_CCU_1, | ||
| 106 | A7XX_DBGBUS_VFD_BR_0, | ||
| 107 | A7XX_DBGBUS_VFD_BR_1, | ||
| 108 | A7XX_DBGBUS_VFD_BR_2, | ||
| 109 | A7XX_DBGBUS_VFD_BR_3, | ||
| 110 | A7XX_DBGBUS_USP_0, | ||
| 111 | A7XX_DBGBUS_USP_1, | ||
| 112 | A7XX_DBGBUS_TP_0, | ||
| 113 | A7XX_DBGBUS_TP_1, | ||
| 114 | A7XX_DBGBUS_TP_2, | ||
| 115 | A7XX_DBGBUS_TP_3, | ||
| 116 | A7XX_DBGBUS_USPTP_0, | ||
| 117 | A7XX_DBGBUS_USPTP_1, | ||
| 118 | A7XX_DBGBUS_USPTP_2, | ||
| 119 | A7XX_DBGBUS_USPTP_3, | ||
| 120 | }; | ||
| 121 | |||
| 122 | static const struct gen7_sel_reg gen7_17_0_rb_rac_sel = { | ||
| 123 | .host_reg = REG_A6XX_RB_SUB_BLOCK_SEL_CNTL_HOST, | ||
| 124 | .cd_reg = REG_A6XX_RB_SUB_BLOCK_SEL_CNTL_CD, | ||
| 125 | .val = 0x0, | ||
| 126 | }; | ||
| 127 | |||
| 128 | static const struct gen7_sel_reg gen7_17_0_rb_rbp_sel = { | ||
| 129 | .host_reg = REG_A6XX_RB_SUB_BLOCK_SEL_CNTL_HOST, | ||
| 130 | .cd_reg = REG_A6XX_RB_SUB_BLOCK_SEL_CNTL_CD, | ||
| 131 | .val = 0x9, | ||
| 132 | }; | ||
| 133 | |||
| 134 | static const u32 gen7_17_0_post_crashdumper_registers[] = { | ||
| 135 | 0x00535, 0x00535, | ||
| 136 | UINT_MAX, UINT_MAX, | ||
| 137 | }; | ||
| 138 | static_assert(IS_ALIGNED(sizeof(gen7_17_0_post_crashdumper_registers), 8)); | ||
| 139 | |||
| 140 | static const u32 gen7_17_0_gpu_registers[] = { | ||
| 141 | 0x00000, 0x00000, 0x00002, 0x00002, 0x00011, 0x00012, 0x00016, 0x0001b, | ||
| 142 | 0x0001f, 0x00032, 0x00038, 0x0003c, 0x00042, 0x00042, 0x00044, 0x00044, | ||
| 143 | 0x00047, 0x00047, 0x00049, 0x0004a, 0x0004c, 0x0004c, 0x00050, 0x00050, | ||
| 144 | 0x00056, 0x00056, 0x00073, 0x00075, 0x000ad, 0x000ae, 0x000b0, 0x000b0, | ||
| 145 | 0x000b4, 0x000b4, 0x000b8, 0x000b8, 0x000bc, 0x000bc, 0x000c0, 0x000c0, | ||
| 146 | 0x000c4, 0x000c4, 0x000c8, 0x000c8, 0x000cc, 0x000cc, 0x000d0, 0x000d0, | ||
| 147 | 0x000d4, 0x000d4, 0x000d8, 0x000d8, 0x000dc, 0x000dc, 0x000e0, 0x000e0, | ||
| 148 | 0x000e4, 0x000e4, 0x000e8, 0x000e8, 0x000ec, 0x000ec, 0x000f0, 0x000f0, | ||
| 149 | 0x000f4, 0x000f4, 0x000f8, 0x000f8, 0x00100, 0x00100, 0x00104, 0x0010b, | ||
| 150 | 0x0010f, 0x0011d, 0x0012f, 0x0012f, 0x00200, 0x0020d, 0x00215, 0x00243, | ||
| 151 | 0x00260, 0x00268, 0x00272, 0x00274, 0x00286, 0x00286, 0x0028a, 0x0028a, | ||
| 152 | 0x0028c, 0x0028c, 0x00300, 0x00401, 0x00500, 0x00500, 0x00507, 0x0050b, | ||
| 153 | 0x0050f, 0x0050f, 0x00511, 0x00511, 0x00533, 0x00534, 0x00540, 0x00555, | ||
| 154 | 0x00564, 0x00567, 0x00800, 0x00808, 0x00810, 0x00813, 0x00820, 0x00821, | ||
| 155 | 0x00823, 0x00827, 0x00830, 0x00834, 0x00840, 0x00841, 0x00843, 0x00847, | ||
| 156 | 0x0084f, 0x00886, 0x008a0, 0x008ab, 0x008c0, 0x008c0, 0x008c4, 0x008c5, | ||
| 157 | 0x008d0, 0x008dd, 0x008f0, 0x008f3, 0x00900, 0x00903, 0x00908, 0x00911, | ||
| 158 | 0x00928, 0x0093e, 0x00942, 0x0094d, 0x00980, 0x00984, 0x0098d, 0x0098f, | ||
| 159 | 0x009b0, 0x009b4, 0x009c2, 0x009c9, 0x009ce, 0x009d7, 0x00a00, 0x00a00, | ||
| 160 | 0x00a02, 0x00a03, 0x00a10, 0x00a4f, 0x00a67, 0x00a6c, 0x00a9c, 0x00a9f, | ||
| 161 | 0x00c00, 0x00c00, 0x00c02, 0x00c04, 0x00c06, 0x00c06, 0x00c10, 0x00cd9, | ||
| 162 | 0x00ce0, 0x00d0c, 0x00df0, 0x00df4, 0x00e01, 0x00e02, 0x00e07, 0x00e0e, | ||
| 163 | 0x00e10, 0x00e12, 0x00e17, 0x00e17, 0x00e19, 0x00e19, 0x00e1b, 0x00e2b, | ||
| 164 | 0x00e30, 0x00e32, 0x00e38, 0x00e3c, | ||
| 165 | UINT_MAX, UINT_MAX, | ||
| 166 | }; | ||
| 167 | static_assert(IS_ALIGNED(sizeof(gen7_17_0_gpu_registers), 8)); | ||
| 168 | |||
| 169 | static const u32 gen7_17_0_dbgc_registers[] = { | ||
| 170 | 0x00600, 0x0061c, 0x0061e, 0x00634, 0x00640, 0x0065a, 0x00679, 0x0067a, | ||
| 171 | 0x00699, 0x00699, 0x0069b, 0x0069e, 0x18400, 0x1841c, 0x1841e, 0x18434, | ||
| 172 | 0x18440, 0x1845c, 0x18479, 0x1847c, 0x18580, 0x18581, | ||
| 173 | UINT_MAX, UINT_MAX, | ||
| 174 | }; | ||
| 175 | static_assert(IS_ALIGNED(sizeof(gen7_17_0_dbgc_registers), 8)); | ||
| 176 | |||
| 177 | static const u32 gen7_17_0_noncontext_pipe_br_registers[] = { | ||
| 178 | 0x00887, 0x0088c, 0x08600, 0x08600, 0x08602, 0x08602, 0x08610, 0x0861b, | ||
| 179 | 0x08620, 0x08620, 0x08630, 0x08630, 0x08637, 0x08639, 0x08640, 0x08640, | ||
| 180 | 0x09600, 0x09600, 0x09602, 0x09603, 0x0960a, 0x09616, 0x09624, 0x0963a, | ||
| 181 | 0x09640, 0x09640, 0x09e00, 0x09e00, 0x09e02, 0x09e07, 0x09e0a, 0x09e16, | ||
| 182 | 0x09e19, 0x09e19, 0x09e1c, 0x09e1c, 0x09e20, 0x09e25, 0x09e30, 0x09e31, | ||
| 183 | 0x09e40, 0x09e51, 0x09e64, 0x09e64, 0x09e70, 0x09e72, 0x09e78, 0x09e79, | ||
| 184 | 0x09e80, 0x09fff, 0x0a600, 0x0a600, 0x0a603, 0x0a603, 0x0a610, 0x0a61f, | ||
| 185 | 0x0a630, 0x0a631, 0x0a638, 0x0a638, | ||
| 186 | UINT_MAX, UINT_MAX, | ||
| 187 | }; | ||
| 188 | static_assert(IS_ALIGNED(sizeof(gen7_17_0_noncontext_pipe_br_registers), 8)); | ||
| 189 | |||
| 190 | static const u32 gen7_17_0_noncontext_rb_rac_pipe_br_registers[] = { | ||
| 191 | 0x08e10, 0x08e1c, 0x08e20, 0x08e25, 0x08e51, 0x08e54, | ||
| 192 | UINT_MAX, UINT_MAX, | ||
| 193 | }; | ||
| 194 | static_assert(IS_ALIGNED(sizeof(gen7_17_0_noncontext_rb_rac_pipe_br_registers), 8)); | ||
| 195 | |||
| 196 | static const u32 gen7_17_0_noncontext_rb_rbp_pipe_br_registers[] = { | ||
| 197 | 0x08e01, 0x08e01, 0x08e04, 0x08e04, 0x08e06, 0x08e09, 0x08e0c, 0x08e0c, | ||
| 198 | 0x08e28, 0x08e28, 0x08e2c, 0x08e35, 0x08e3b, 0x08e3f, 0x08e50, 0x08e50, | ||
| 199 | 0x08e5b, 0x08e5d, 0x08e5f, 0x08e5f, 0x08e61, 0x08e61, 0x08e63, 0x08e65, | ||
| 200 | 0x08e68, 0x08e68, 0x08e70, 0x08e79, 0x08e80, 0x08e8f, | ||
| 201 | UINT_MAX, UINT_MAX, | ||
| 202 | }; | ||
| 203 | static_assert(IS_ALIGNED(sizeof(gen7_17_0_noncontext_rb_rbp_pipe_br_registers), 8)); | ||
| 204 | |||
| 205 | static const u32 gen7_17_0_pc_cluster_fe_pipe_br_registers[] = { | ||
| 206 | 0x09800, 0x09804, 0x09806, 0x0980a, 0x09810, 0x09811, 0x09884, 0x09886, | ||
| 207 | 0x09970, 0x09972, 0x09b00, 0x09b08, | ||
| 208 | UINT_MAX, UINT_MAX, | ||
| 209 | }; | ||
| 210 | static_assert(IS_ALIGNED(sizeof(gen7_17_0_pc_cluster_fe_pipe_br_registers), 8)); | ||
| 211 | |||
| 212 | static const u32 gen7_17_0_sp_cluster_sp_ps_pipe_lpac_hlsq_state_registers[] = { | ||
| 213 | 0x0aa40, 0x0aabf, | ||
| 214 | UINT_MAX, UINT_MAX, | ||
| 215 | }; | ||
| 216 | static_assert(IS_ALIGNED(sizeof(gen7_17_0_sp_cluster_sp_ps_pipe_lpac_hlsq_state_registers), 8)); | ||
| 217 | |||
| 218 | static const u32 gen7_17_0_sp_cluster_sp_ps_pipe_lpac_usptp_registers[] = { | ||
| 219 | 0x0aa40, 0x0aabf, | ||
| 220 | UINT_MAX, UINT_MAX, | ||
| 221 | }; | ||
| 222 | static_assert(IS_ALIGNED(sizeof(gen7_17_0_sp_cluster_sp_ps_pipe_lpac_usptp_registers), 8)); | ||
| 223 | |||
| 224 | static const u32 gen7_17_0_non_context_tpl1_pipe_none_usptp_registers[] = { | ||
| 225 | 0x0b602, 0x0b602, 0x0b604, 0x0b604, 0x0b608, 0x0b60c, 0x0b60f, 0x0b621, | ||
| 226 | 0x0b630, 0x0b633, | ||
| 227 | UINT_MAX, UINT_MAX, | ||
| 228 | }; | ||
| 229 | static_assert(IS_ALIGNED(sizeof(gen7_17_0_non_context_tpl1_pipe_none_usptp_registers), 8)); | ||
| 230 | |||
| 231 | static const u32 gen7_17_0_non_context_tpl1_pipe_br_usptp_registers[] = { | ||
| 232 | 0x0b600, 0x0b600, | ||
| 233 | UINT_MAX, UINT_MAX, | ||
| 234 | }; | ||
| 235 | static_assert(IS_ALIGNED(sizeof(gen7_17_0_non_context_tpl1_pipe_br_usptp_registers), 8)); | ||
| 236 | |||
| 237 | static const u32 gen7_17_0_tpl1_cluster_sp_vs_pipe_br_usptp_registers[] = { | ||
| 238 | 0x0b300, 0x0b307, 0x0b309, 0x0b309, 0x0b310, 0x0b310, | ||
| 239 | UINT_MAX, UINT_MAX, | ||
| 240 | }; | ||
| 241 | static_assert(IS_ALIGNED(sizeof(gen7_17_0_tpl1_cluster_sp_vs_pipe_br_usptp_registers), 8)); | ||
| 242 | |||
| 243 | static const u32 gen7_17_0_tpl1_cluster_sp_ps_pipe_br_usptp_registers[] = { | ||
| 244 | 0x0b180, 0x0b183, 0x0b190, 0x0b195, 0x0b2c0, 0x0b2d5, 0x0b300, 0x0b307, | ||
| 245 | 0x0b309, 0x0b309, 0x0b310, 0x0b310, | ||
| 246 | UINT_MAX, UINT_MAX, | ||
| 247 | }; | ||
| 248 | static_assert(IS_ALIGNED(sizeof(gen7_17_0_tpl1_cluster_sp_ps_pipe_br_usptp_registers), 8)); | ||
| 249 | |||
| 250 | /* No BV pipe — gen7_0_0_* sub-arrays are shared from adreno_gen7_0_0_snapshot.h */ | ||
| 251 | static struct gen7_cluster_registers gen7_17_0_clusters[] = { | ||
| 252 | { A7XX_CLUSTER_NONE, PIPE_BR, STATE_NON_CONTEXT, | ||
| 253 | gen7_17_0_noncontext_pipe_br_registers, }, | ||
| 254 | { A7XX_CLUSTER_NONE, PIPE_BR, STATE_NON_CONTEXT, | ||
| 255 | gen7_17_0_noncontext_rb_rac_pipe_br_registers, &gen7_17_0_rb_rac_sel, }, | ||
| 256 | { A7XX_CLUSTER_NONE, PIPE_BR, STATE_NON_CONTEXT, | ||
| 257 | gen7_17_0_noncontext_rb_rbp_pipe_br_registers, &gen7_17_0_rb_rbp_sel, }, | ||
| 258 | { A7XX_CLUSTER_PS, PIPE_BR, STATE_FORCE_CTXT_0, | ||
| 259 | gen7_0_0_rb_rac_cluster_ps_pipe_br_registers, &gen7_17_0_rb_rac_sel, }, | ||
| 260 | { A7XX_CLUSTER_PS, PIPE_BR, STATE_FORCE_CTXT_1, | ||
| 261 | gen7_0_0_rb_rac_cluster_ps_pipe_br_registers, &gen7_17_0_rb_rac_sel, }, | ||
| 262 | { A7XX_CLUSTER_PS, PIPE_BR, STATE_FORCE_CTXT_0, | ||
| 263 | gen7_0_0_rb_rbp_cluster_ps_pipe_br_registers, &gen7_17_0_rb_rbp_sel, }, | ||
| 264 | { A7XX_CLUSTER_PS, PIPE_BR, STATE_FORCE_CTXT_1, | ||
| 265 | gen7_0_0_rb_rbp_cluster_ps_pipe_br_registers, &gen7_17_0_rb_rbp_sel, }, | ||
| 266 | { A7XX_CLUSTER_GRAS, PIPE_BR, STATE_FORCE_CTXT_0, | ||
| 267 | gen7_0_0_gras_cluster_gras_pipe_br_registers, }, | ||
| 268 | { A7XX_CLUSTER_GRAS, PIPE_BR, STATE_FORCE_CTXT_1, | ||
| 269 | gen7_0_0_gras_cluster_gras_pipe_br_registers, }, | ||
| 270 | { A7XX_CLUSTER_FE, PIPE_BR, STATE_FORCE_CTXT_0, | ||
| 271 | gen7_17_0_pc_cluster_fe_pipe_br_registers, }, | ||
| 272 | { A7XX_CLUSTER_FE, PIPE_BR, STATE_FORCE_CTXT_1, | ||
| 273 | gen7_17_0_pc_cluster_fe_pipe_br_registers, }, | ||
| 274 | { A7XX_CLUSTER_FE, PIPE_BR, STATE_FORCE_CTXT_0, | ||
| 275 | gen7_0_0_vfd_cluster_fe_pipe_bv_registers, }, | ||
| 276 | { A7XX_CLUSTER_FE, PIPE_BR, STATE_FORCE_CTXT_1, | ||
| 277 | gen7_0_0_vfd_cluster_fe_pipe_bv_registers, }, | ||
| 278 | { A7XX_CLUSTER_FE, PIPE_BR, STATE_FORCE_CTXT_0, | ||
| 279 | gen7_0_0_vpc_cluster_fe_pipe_br_registers, }, | ||
| 280 | { A7XX_CLUSTER_FE, PIPE_BR, STATE_FORCE_CTXT_1, | ||
| 281 | gen7_0_0_vpc_cluster_fe_pipe_br_registers, }, | ||
| 282 | { A7XX_CLUSTER_PC_VS, PIPE_BR, STATE_FORCE_CTXT_0, | ||
| 283 | gen7_0_0_vpc_cluster_pc_vs_pipe_br_registers, }, | ||
| 284 | { A7XX_CLUSTER_PC_VS, PIPE_BR, STATE_FORCE_CTXT_1, | ||
| 285 | gen7_0_0_vpc_cluster_pc_vs_pipe_br_registers, }, | ||
| 286 | { A7XX_CLUSTER_VPC_PS, PIPE_BR, STATE_FORCE_CTXT_0, | ||
| 287 | gen7_0_0_vpc_cluster_vpc_ps_pipe_br_registers, }, | ||
| 288 | { A7XX_CLUSTER_VPC_PS, PIPE_BR, STATE_FORCE_CTXT_1, | ||
| 289 | gen7_0_0_vpc_cluster_vpc_ps_pipe_br_registers, }, | ||
| 290 | }; | ||
| 291 | |||
| 292 | /* No BV pipe; 2 SPs, 2 USPTPs */ | ||
| 293 | static struct gen7_sptp_cluster_registers gen7_17_0_sptp_clusters[] = { | ||
| 294 | { A7XX_CLUSTER_NONE, A7XX_SP_NCTX_REG, PIPE_BR, 0, A7XX_HLSQ_STATE, | ||
| 295 | gen7_0_0_sp_noncontext_pipe_br_hlsq_state_registers, 0xae00 }, | ||
| 296 | { A7XX_CLUSTER_NONE, A7XX_SP_NCTX_REG, PIPE_BR, 0, A7XX_SP_TOP, | ||
| 297 | gen7_0_0_sp_noncontext_pipe_br_sp_top_registers, 0xae00 }, | ||
| 298 | { A7XX_CLUSTER_NONE, A7XX_SP_NCTX_REG, PIPE_BR, 0, A7XX_USPTP, | ||
| 299 | gen7_0_0_sp_noncontext_pipe_br_usptp_registers, 0xae00 }, | ||
| 300 | { A7XX_CLUSTER_SP_VS, A7XX_SP_CTX0_3D_CVS_REG, PIPE_BR, 0, A7XX_HLSQ_STATE, | ||
| 301 | gen7_0_0_sp_cluster_sp_vs_pipe_br_hlsq_state_registers, 0xa800 }, | ||
| 302 | { A7XX_CLUSTER_SP_VS, A7XX_SP_CTX0_3D_CVS_REG, PIPE_BR, 0, A7XX_SP_TOP, | ||
| 303 | gen7_0_0_sp_cluster_sp_vs_pipe_br_sp_top_registers, 0xa800 }, | ||
| 304 | { A7XX_CLUSTER_SP_VS, A7XX_SP_CTX0_3D_CVS_REG, PIPE_BR, 0, A7XX_USPTP, | ||
| 305 | gen7_0_0_sp_cluster_sp_vs_pipe_br_usptp_registers, 0xa800 }, | ||
| 306 | { A7XX_CLUSTER_SP_VS, A7XX_SP_CTX1_3D_CVS_REG, PIPE_BR, 1, A7XX_HLSQ_STATE, | ||
| 307 | gen7_0_0_sp_cluster_sp_vs_pipe_br_hlsq_state_registers, 0xa800 }, | ||
| 308 | { A7XX_CLUSTER_SP_VS, A7XX_SP_CTX1_3D_CVS_REG, PIPE_BR, 1, A7XX_SP_TOP, | ||
| 309 | gen7_0_0_sp_cluster_sp_vs_pipe_br_sp_top_registers, 0xa800 }, | ||
| 310 | { A7XX_CLUSTER_SP_VS, A7XX_SP_CTX1_3D_CVS_REG, PIPE_BR, 1, A7XX_USPTP, | ||
| 311 | gen7_0_0_sp_cluster_sp_vs_pipe_br_usptp_registers, 0xa800 }, | ||
| 312 | { A7XX_CLUSTER_SP_PS, A7XX_SP_CTX0_3D_CPS_REG, PIPE_BR, 0, A7XX_HLSQ_STATE, | ||
| 313 | gen7_0_0_sp_cluster_sp_ps_pipe_br_hlsq_state_registers, 0xa800 }, | ||
| 314 | { A7XX_CLUSTER_SP_PS, A7XX_SP_CTX0_3D_CPS_REG, PIPE_BR, 0, A7XX_HLSQ_DP, | ||
| 315 | gen7_0_0_sp_cluster_sp_ps_pipe_br_hlsq_dp_registers, 0xa800 }, | ||
| 316 | { A7XX_CLUSTER_SP_PS, A7XX_SP_CTX0_3D_CPS_REG, PIPE_BR, 0, A7XX_SP_TOP, | ||
| 317 | gen7_0_0_sp_cluster_sp_ps_pipe_br_sp_top_registers, 0xa800 }, | ||
| 318 | { A7XX_CLUSTER_SP_PS, A7XX_SP_CTX0_3D_CPS_REG, PIPE_BR, 0, A7XX_USPTP, | ||
| 319 | gen7_0_0_sp_cluster_sp_ps_pipe_br_usptp_registers, 0xa800 }, | ||
| 320 | { A7XX_CLUSTER_SP_PS, A7XX_SP_CTX0_3D_CPS_REG, PIPE_LPAC, 0, A7XX_HLSQ_STATE, | ||
| 321 | gen7_17_0_sp_cluster_sp_ps_pipe_lpac_hlsq_state_registers, 0xa800 }, | ||
| 322 | { A7XX_CLUSTER_SP_PS, A7XX_SP_CTX0_3D_CPS_REG, PIPE_LPAC, 0, A7XX_USPTP, | ||
| 323 | gen7_17_0_sp_cluster_sp_ps_pipe_lpac_usptp_registers, 0xa800 }, | ||
| 324 | { A7XX_CLUSTER_SP_PS, A7XX_SP_CTX1_3D_CPS_REG, PIPE_BR, 1, A7XX_HLSQ_STATE, | ||
| 325 | gen7_0_0_sp_cluster_sp_ps_pipe_br_hlsq_state_registers, 0xa800 }, | ||
| 326 | { A7XX_CLUSTER_SP_PS, A7XX_SP_CTX1_3D_CPS_REG, PIPE_BR, 1, A7XX_HLSQ_DP, | ||
| 327 | gen7_0_0_sp_cluster_sp_ps_pipe_br_hlsq_dp_registers, 0xa800 }, | ||
| 328 | { A7XX_CLUSTER_SP_PS, A7XX_SP_CTX1_3D_CPS_REG, PIPE_BR, 1, A7XX_SP_TOP, | ||
| 329 | gen7_0_0_sp_cluster_sp_ps_pipe_br_sp_top_registers, 0xa800 }, | ||
| 330 | { A7XX_CLUSTER_SP_PS, A7XX_SP_CTX1_3D_CPS_REG, PIPE_BR, 1, A7XX_USPTP, | ||
| 331 | gen7_0_0_sp_cluster_sp_ps_pipe_br_usptp_registers, 0xa800 }, | ||
| 332 | { A7XX_CLUSTER_SP_PS, A7XX_SP_CTX2_3D_CPS_REG, PIPE_BR, 2, A7XX_HLSQ_DP, | ||
| 333 | gen7_0_0_sp_cluster_sp_ps_pipe_br_hlsq_dp_registers, 0xa800 }, | ||
| 334 | { A7XX_CLUSTER_SP_PS, A7XX_SP_CTX2_3D_CPS_REG, PIPE_BR, 2, A7XX_SP_TOP, | ||
| 335 | gen7_0_0_sp_cluster_sp_ps_pipe_br_sp_top_registers, 0xa800 }, | ||
| 336 | { A7XX_CLUSTER_SP_PS, A7XX_SP_CTX2_3D_CPS_REG, PIPE_BR, 2, A7XX_USPTP, | ||
| 337 | gen7_0_0_sp_cluster_sp_ps_pipe_br_usptp_registers, 0xa800 }, | ||
| 338 | { A7XX_CLUSTER_SP_PS, A7XX_SP_CTX3_3D_CPS_REG, PIPE_BR, 3, A7XX_HLSQ_DP, | ||
| 339 | gen7_0_0_sp_cluster_sp_ps_pipe_br_hlsq_dp_registers, 0xa800 }, | ||
| 340 | { A7XX_CLUSTER_SP_PS, A7XX_SP_CTX3_3D_CPS_REG, PIPE_BR, 3, A7XX_SP_TOP, | ||
| 341 | gen7_0_0_sp_cluster_sp_ps_pipe_br_sp_top_registers, 0xa800 }, | ||
| 342 | { A7XX_CLUSTER_SP_PS, A7XX_SP_CTX3_3D_CPS_REG, PIPE_BR, 3, A7XX_USPTP, | ||
| 343 | gen7_0_0_sp_cluster_sp_ps_pipe_br_usptp_registers, 0xa800 }, | ||
| 344 | { A7XX_CLUSTER_NONE, A7XX_TP0_NCTX_REG, PIPE_NONE, 0, A7XX_USPTP, | ||
| 345 | gen7_17_0_non_context_tpl1_pipe_none_usptp_registers, 0xb600 }, | ||
| 346 | { A7XX_CLUSTER_NONE, A7XX_TP0_NCTX_REG, PIPE_BR, 0, A7XX_USPTP, | ||
| 347 | gen7_17_0_non_context_tpl1_pipe_br_usptp_registers, 0xb600 }, | ||
| 348 | { A7XX_CLUSTER_SP_VS, A7XX_TP0_CTX0_3D_CVS_REG, PIPE_BR, 0, A7XX_USPTP, | ||
| 349 | gen7_17_0_tpl1_cluster_sp_vs_pipe_br_usptp_registers, 0xb000 }, | ||
| 350 | { A7XX_CLUSTER_SP_VS, A7XX_TP0_CTX1_3D_CVS_REG, PIPE_BR, 1, A7XX_USPTP, | ||
| 351 | gen7_17_0_tpl1_cluster_sp_vs_pipe_br_usptp_registers, 0xb000 }, | ||
| 352 | { A7XX_CLUSTER_SP_PS, A7XX_TP0_CTX0_3D_CPS_REG, PIPE_BR, 0, A7XX_USPTP, | ||
| 353 | gen7_17_0_tpl1_cluster_sp_ps_pipe_br_usptp_registers, 0xb000 }, | ||
| 354 | { A7XX_CLUSTER_SP_PS, A7XX_TP0_CTX1_3D_CPS_REG, PIPE_BR, 1, A7XX_USPTP, | ||
| 355 | gen7_17_0_tpl1_cluster_sp_ps_pipe_br_usptp_registers, 0xb000 }, | ||
| 356 | { A7XX_CLUSTER_SP_PS, A7XX_TP0_CTX2_3D_CPS_REG, PIPE_BR, 2, A7XX_USPTP, | ||
| 357 | gen7_17_0_tpl1_cluster_sp_ps_pipe_br_usptp_registers, 0xb000 }, | ||
| 358 | { A7XX_CLUSTER_SP_PS, A7XX_TP0_CTX3_3D_CPS_REG, PIPE_BR, 3, A7XX_USPTP, | ||
| 359 | gen7_17_0_tpl1_cluster_sp_ps_pipe_br_usptp_registers, 0xb000 }, | ||
| 360 | }; | ||
| 361 | |||
| 362 | static struct gen7_shader_block gen7_17_0_shader_blocks[] = { | ||
| 363 | { A7XX_TP0_TMO_DATA, 0x0200, 2, 2, PIPE_BR, A7XX_USPTP }, | ||
| 364 | { A7XX_TP0_SMO_DATA, 0x0080, 2, 2, PIPE_BR, A7XX_USPTP }, | ||
| 365 | { A7XX_TP0_MIPMAP_BASE_DATA, 0x03c0, 2, 2, PIPE_BR, A7XX_USPTP }, | ||
| 366 | { A7XX_SP_INST_DATA, 0x0800, 2, 2, PIPE_BR, A7XX_USPTP }, | ||
| 367 | { A7XX_SP_INST_DATA_1, 0x0800, 2, 2, PIPE_BR, A7XX_USPTP }, | ||
| 368 | { A7XX_SP_LB_0_DATA, 0x0800, 2, 2, PIPE_BR, A7XX_USPTP }, | ||
| 369 | { A7XX_SP_LB_1_DATA, 0x0800, 2, 2, PIPE_BR, A7XX_USPTP }, | ||
| 370 | { A7XX_SP_LB_2_DATA, 0x0800, 2, 2, PIPE_BR, A7XX_USPTP }, | ||
| 371 | { A7XX_SP_LB_3_DATA, 0x0800, 2, 2, PIPE_BR, A7XX_USPTP }, | ||
| 372 | { A7XX_SP_LB_4_DATA, 0x0800, 2, 2, PIPE_BR, A7XX_USPTP }, | ||
| 373 | { A7XX_SP_LB_5_DATA, 0x0800, 2, 2, PIPE_BR, A7XX_USPTP }, | ||
| 374 | { A7XX_SP_CB_RAM, 0x0390, 2, 2, PIPE_BR, A7XX_USPTP }, | ||
| 375 | { A7XX_SP_INST_TAG, 0x0090, 2, 2, PIPE_BR, A7XX_USPTP }, | ||
| 376 | { A7XX_SP_TMO_TAG, 0x0080, 2, 2, PIPE_BR, A7XX_USPTP }, | ||
| 377 | { A7XX_SP_SMO_TAG, 0x0080, 2, 2, PIPE_BR, A7XX_USPTP }, | ||
| 378 | { A7XX_SP_STATE_DATA, 0x0040, 2, 2, PIPE_BR, A7XX_USPTP }, | ||
| 379 | { A7XX_SP_HWAVE_RAM, 0x0100, 2, 2, PIPE_BR, A7XX_USPTP }, | ||
| 380 | { A7XX_SP_L0_INST_BUF, 0x0050, 2, 2, PIPE_BR, A7XX_USPTP }, | ||
| 381 | { A7XX_HLSQ_CVS_BE_CTXT_BUF_RAM_TAG, 0x0010, 1, 1, PIPE_BR, A7XX_HLSQ_STATE }, | ||
| 382 | { A7XX_HLSQ_CPS_BE_CTXT_BUF_RAM_TAG, 0x0010, 1, 1, PIPE_BR, A7XX_HLSQ_STATE }, | ||
| 383 | { A7XX_HLSQ_GFX_CVS_BE_CTXT_BUF_RAM, 0x0300, 1, 1, PIPE_BR, A7XX_HLSQ_STATE }, | ||
| 384 | { A7XX_HLSQ_GFX_CPS_BE_CTXT_BUF_RAM, 0x0300, 1, 1, PIPE_BR, A7XX_HLSQ_STATE }, | ||
| 385 | { A7XX_HLSQ_CHUNK_CVS_RAM, 0x01c0, 1, 1, PIPE_BR, A7XX_HLSQ_STATE }, | ||
| 386 | { A7XX_HLSQ_CHUNK_CPS_RAM, 0x0300, 1, 1, PIPE_BR, A7XX_HLSQ_STATE }, | ||
| 387 | { A7XX_HLSQ_CHUNK_CVS_RAM_TAG, 0x0040, 1, 1, PIPE_BR, A7XX_HLSQ_STATE }, | ||
| 388 | { A7XX_HLSQ_CHUNK_CPS_RAM_TAG, 0x0040, 1, 1, PIPE_BR, A7XX_HLSQ_STATE }, | ||
| 389 | { A7XX_HLSQ_ICB_CVS_CB_BASE_TAG, 0x0010, 1, 1, PIPE_BR, A7XX_HLSQ_STATE }, | ||
| 390 | { A7XX_HLSQ_ICB_CPS_CB_BASE_TAG, 0x0010, 1, 1, PIPE_BR, A7XX_HLSQ_STATE }, | ||
| 391 | { A7XX_HLSQ_CVS_MISC_RAM, 0x0280, 1, 1, PIPE_BR, A7XX_HLSQ_STATE }, | ||
| 392 | { A7XX_HLSQ_CPS_MISC_RAM, 0x0800, 1, 1, PIPE_BR, A7XX_HLSQ_STATE }, | ||
| 393 | { A7XX_HLSQ_CPS_MISC_RAM_1, 0x0200, 1, 1, PIPE_BR, A7XX_HLSQ_STATE }, | ||
| 394 | { A7XX_HLSQ_INST_RAM, 0x0800, 1, 1, PIPE_BR, A7XX_HLSQ_STATE }, | ||
| 395 | { A7XX_HLSQ_GFX_CVS_CONST_RAM, 0x0800, 1, 1, PIPE_BR, A7XX_HLSQ_STATE }, | ||
| 396 | { A7XX_HLSQ_GFX_CPS_CONST_RAM, 0x0800, 1, 1, PIPE_BR, A7XX_HLSQ_STATE }, | ||
| 397 | { A7XX_HLSQ_CVS_MISC_RAM_TAG, 0x0010, 1, 1, PIPE_BR, A7XX_HLSQ_STATE }, | ||
| 398 | { A7XX_HLSQ_CPS_MISC_RAM_TAG, 0x0010, 1, 1, PIPE_BR, A7XX_HLSQ_STATE }, | ||
| 399 | { A7XX_HLSQ_INST_RAM_TAG, 0x0080, 1, 1, PIPE_BR, A7XX_HLSQ_STATE }, | ||
| 400 | { A7XX_HLSQ_GFX_CVS_CONST_RAM_TAG, 0x0064, 1, 1, PIPE_BR, A7XX_HLSQ_STATE }, | ||
| 401 | { A7XX_HLSQ_GFX_CPS_CONST_RAM_TAG, 0x0064, 1, 1, PIPE_BR, A7XX_HLSQ_STATE }, | ||
| 402 | { A7XX_HLSQ_INST_RAM_1, 0x0800, 1, 1, PIPE_BR, A7XX_HLSQ_STATE }, | ||
| 403 | { A7XX_HLSQ_STPROC_META, 0x0010, 1, 1, PIPE_BR, A7XX_HLSQ_STATE }, | ||
| 404 | { A7XX_HLSQ_BV_BE_META, 0x0010, 1, 1, PIPE_BR, A7XX_HLSQ_STATE }, | ||
| 405 | { A7XX_HLSQ_DATAPATH_META, 0x0020, 1, 1, PIPE_BR, A7XX_HLSQ_STATE }, | ||
| 406 | { A7XX_HLSQ_FRONTEND_META, 0x0040, 1, 1, PIPE_BR, A7XX_HLSQ_STATE }, | ||
| 407 | { A7XX_HLSQ_INDIRECT_META, 0x0010, 1, 1, PIPE_BR, A7XX_HLSQ_STATE }, | ||
| 408 | { A7XX_HLSQ_BACKEND_META, 0x0040, 1, 1, PIPE_BR, A7XX_HLSQ_STATE }, | ||
| 409 | }; | ||
| 410 | |||
| 411 | static struct gen7_reg_list gen7_17_0_reg_list[] = { | ||
| 412 | { gen7_17_0_gpu_registers, NULL }, | ||
| 413 | { gen7_17_0_dbgc_registers, NULL }, | ||
| 414 | { NULL, NULL }, | ||
| 415 | }; | ||
| 416 | |||
| 417 | static const struct a6xx_indexed_registers gen7_17_0_cp_indexed_reglist[] = { | ||
| 418 | { "CP_SQE_STAT", REG_A6XX_CP_SQE_STAT_ADDR, | ||
| 419 | REG_A6XX_CP_SQE_STAT_DATA, 0x40, NULL }, | ||
| 420 | { "CP_DRAW_STATE", REG_A6XX_CP_DRAW_STATE_ADDR, | ||
| 421 | REG_A6XX_CP_DRAW_STATE_DATA, 0x100, NULL }, | ||
| 422 | { "CP_SQE_UCODE_DBG", REG_A6XX_CP_SQE_UCODE_DBG_ADDR, | ||
| 423 | REG_A6XX_CP_SQE_UCODE_DBG_DATA, 0x8000, NULL }, | ||
| 424 | { "CP_ROQ_DBG", REG_A6XX_CP_ROQ_DBG_ADDR, | ||
| 425 | REG_A6XX_CP_ROQ_DBG_DATA, 0, a7xx_get_cp_roq_size }, | ||
| 426 | }; | ||
| 427 | |||
| 428 | #endif /* __ADRENO_GEN7_17_0_SNAPSHOT_H */ | ||
| @@ -356,6 +356,12 @@ int adreno_fault_handler(struct msm_gpu *gpu, unsigned long iova, int flags, · 355 unmodified lines | |||
| 356 | return 0; | 356 | return 0; |
| 357 | } | 357 | } |
| 358 | 358 | ||
| 359 | static bool | ||
| 360 | valid_per_process_vm(struct msm_gpu *gpu, struct drm_gpuvm *vm) | ||
| 361 | { | ||
| 362 | return vm && (vm != gpu->vm); | ||
| 363 | } | ||
| 364 | |||
| 359 | int adreno_get_param(struct msm_gpu *gpu, struct msm_context *ctx, | 365 | int adreno_get_param(struct msm_gpu *gpu, struct msm_context *ctx, |
| 360 | uint32_t param, uint64_t *value, uint32_t *len) | 366 | uint32_t param, uint64_t *value, uint32_t *len) |
| 361 | { | 367 | { |
| @@ -414,12 +420,12 @@ int adreno_get_param(struct msm_gpu *gpu, struct msm_context *ctx, · 52 unmodified lines | |||
| 414 | *value = gpu->suspend_count; | 420 | *value = gpu->suspend_count; |
| 415 | return 0; | 421 | return 0; |
| 416 | case MSM_PARAM_VA_START: | 422 | case MSM_PARAM_VA_START: |
| 417 | if (vm == gpu->vm) | 423 | if (!valid_per_process_vm(gpu, vm)) |
| 418 | return UERR(EINVAL, drm, "requires per-process pgtables"); | 424 | return UERR(EINVAL, drm, "requires per-process pgtables"); |
| 419 | *value = vm->mm_start; | 425 | *value = vm->mm_start; |
| 420 | return 0; | 426 | return 0; |
| 421 | case MSM_PARAM_VA_SIZE: | 427 | case MSM_PARAM_VA_SIZE: |
| 422 | if (vm == gpu->vm) | 428 | if (!valid_per_process_vm(gpu, vm)) |
| 423 | return UERR(EINVAL, drm, "requires per-process pgtables"); | 429 | return UERR(EINVAL, drm, "requires per-process pgtables"); |
| 424 | *value = vm->mm_range; | 430 | *value = vm->mm_range; |
| 425 | return 0; | 431 | return 0; |
| @@ -503,9 +509,11 @@ int adreno_set_param(struct msm_gpu *gpu, struct msm_context *ctx, · 77 unmodified lines | |||
| 503 | if (!perfmon_capable()) | 509 | if (!perfmon_capable()) |
| 504 | return UERR(EPERM, drm, "invalid permissions"); | 510 | return UERR(EPERM, drm, "invalid permissions"); |
| 505 | return msm_context_set_sysprof(ctx, gpu, value); | 511 | return msm_context_set_sysprof(ctx, gpu, value); |
| 506 | case MSM_PARAM_EN_VM_BIND: | 512 | case MSM_PARAM_EN_VM_BIND: { |
| 513 | guard(rwsem_read)(&ctx->ctxlock); | ||
| 514 | |||
| 507 | /* We can only support VM_BIND with per-process pgtables: */ | 515 | /* We can only support VM_BIND with per-process pgtables: */ |
| 508 | if (ctx->vm == gpu->vm) | 516 | if (!gpu->funcs->create_private_vm) |
| 509 | return UERR(EINVAL, drm, "requires per-process pgtables"); | 517 | return UERR(EINVAL, drm, "requires per-process pgtables"); |
| 510 | 518 | ||
| 511 | /* | 519 | /* |
| @@ -518,6 +526,7 @@ int adreno_set_param(struct msm_gpu *gpu, struct msm_context *ctx, · 6 unmodified lines | |||
| 518 | ctx->userspace_managed_vm = value; | 526 | ctx->userspace_managed_vm = value; |
| 519 | 527 | ||
| 520 | return 0; | 528 | return 0; |
| 529 | } | ||
| 521 | default: | 530 | default: |
| 522 | return UERR(EINVAL, drm, "%s: invalid param: %u", gpu->name, param); | 531 | return UERR(EINVAL, drm, "%s: invalid param: %u", gpu->name, param); |
| 523 | } | 532 | } |
| @@ -562,6 +562,11 @@ static inline int adreno_is_x185(struct adreno_gpu *gpu) · 561 unmodified lines | |||
| 562 | return gpu->info->chip_ids[0] == 0x43050c01; | 562 | return gpu->info->chip_ids[0] == 0x43050c01; |
| 563 | } | 563 | } |
| 564 | 564 | ||
| 565 | static inline int adreno_is_a722(struct adreno_gpu *gpu) | ||
| 566 | { | ||
| 567 | return gpu->info->chip_ids[0] == 0x43020100; | ||
| 568 | } | ||
| 569 | |||
| 565 | static inline int adreno_is_a740_family(struct adreno_gpu *gpu) | 570 | static inline int adreno_is_a740_family(struct adreno_gpu *gpu) |
| 566 | { | 571 | { |
| 567 | if (WARN_ON_ONCE(!gpu->info)) | 572 | if (WARN_ON_ONCE(!gpu->info)) |
| @@ -86,42 +86,42 @@ static const struct dpu_sspp_cfg kaanapali_sspp[] = { · 85 unmodified lines | |||
| 86 | .name = "sspp_8", .id = SSPP_DMA0, | 86 | .name = "sspp_8", .id = SSPP_DMA0, |
| 87 | .base = 0x97000, .len = 0x84, | 87 | .base = 0x97000, .len = 0x84, |
| 88 | .features = DMA_SDM845_MASK_SDMA, | 88 | .features = DMA_SDM845_MASK_SDMA, |
| 89 | .sblk = &dpu_dma_sblk, | 89 | .sblk = &dpu_dma_sblk_v13, |
| 90 | .xin_id = 1, | 90 | .xin_id = 1, |
| 91 | .type = SSPP_TYPE_DMA, | 91 | .type = SSPP_TYPE_DMA, |
| 92 | }, { | 92 | }, { |
| 93 | .name = "sspp_9", .id = SSPP_DMA1, | 93 | .name = "sspp_9", .id = SSPP_DMA1, |
| 94 | .base = 0xa0000, .len = 0x84, | 94 | .base = 0xa0000, .len = 0x84, |
| 95 | .features = DMA_SDM845_MASK_SDMA, | 95 | .features = DMA_SDM845_MASK_SDMA, |
| 96 | .sblk = &dpu_dma_sblk, | 96 | .sblk = &dpu_dma_sblk_v13, |
| 97 | .xin_id = 5, | 97 | .xin_id = 5, |
| 98 | .type = SSPP_TYPE_DMA, | 98 | .type = SSPP_TYPE_DMA, |
| 99 | }, { | 99 | }, { |
| 100 | .name = "sspp_10", .id = SSPP_DMA2, | 100 | .name = "sspp_10", .id = SSPP_DMA2, |
| 101 | .base = 0xa9000, .len = 0x84, | 101 | .base = 0xa9000, .len = 0x84, |
| 102 | .features = DMA_SDM845_MASK_SDMA, | 102 | .features = DMA_SDM845_MASK_SDMA, |
| 103 | .sblk = &dpu_dma_sblk, | 103 | .sblk = &dpu_dma_sblk_v13, |
| 104 | .xin_id = 9, | 104 | .xin_id = 9, |
| 105 | .type = SSPP_TYPE_DMA, | 105 | .type = SSPP_TYPE_DMA, |
| 106 | }, { | 106 | }, { |
| 107 | .name = "sspp_11", .id = SSPP_DMA3, | 107 | .name = "sspp_11", .id = SSPP_DMA3, |
| 108 | .base = 0xb2000, .len = 0x84, | 108 | .base = 0xb2000, .len = 0x84, |
| 109 | .features = DMA_SDM845_MASK_SDMA, | 109 | .features = DMA_SDM845_MASK_SDMA, |
| 110 | .sblk = &dpu_dma_sblk, | 110 | .sblk = &dpu_dma_sblk_v13, |
| 111 | .xin_id = 13, | 111 | .xin_id = 13, |
| 112 | .type = SSPP_TYPE_DMA, | 112 | .type = SSPP_TYPE_DMA, |
| 113 | }, { | 113 | }, { |
| 114 | .name = "sspp_12", .id = SSPP_DMA4, | 114 | .name = "sspp_12", .id = SSPP_DMA4, |
| 115 | .base = 0xbb000, .len = 0x84, | 115 | .base = 0xbb000, .len = 0x84, |
| 116 | .features = DMA_CURSOR_SDM845_MASK_SDMA, | 116 | .features = DMA_CURSOR_SDM845_MASK_SDMA, |
| 117 | .sblk = &dpu_dma_sblk, | 117 | .sblk = &dpu_dma_sblk_v13, |
| 118 | .xin_id = 14, | 118 | .xin_id = 14, |
| 119 | .type = SSPP_TYPE_DMA, | 119 | .type = SSPP_TYPE_DMA, |
| 120 | }, { | 120 | }, { |
| 121 | .name = "sspp_13", .id = SSPP_DMA5, | 121 | .name = "sspp_13", .id = SSPP_DMA5, |
| 122 | .base = 0xc4000, .len = 0x84, | 122 | .base = 0xc4000, .len = 0x84, |
| 123 | .features = DMA_CURSOR_SDM845_MASK_SDMA, | 123 | .features = DMA_CURSOR_SDM845_MASK_SDMA, |
| 124 | .sblk = &dpu_dma_sblk, | 124 | .sblk = &dpu_dma_sblk_v13, |
| 125 | .xin_id = 15, | 125 | .xin_id = 15, |
| 126 | .type = SSPP_TYPE_DMA, | 126 | .type = SSPP_TYPE_DMA, |
| 127 | }, | 127 | }, |
| @@ -34,7 +34,7 @@ enum dpu_perf_mode { · 33 unmodified lines | |||
| 34 | /** | 34 | /** |
| 35 | * dpu_core_perf_adjusted_mode_clk - Adjust given mode clock rate according to | 35 | * dpu_core_perf_adjusted_mode_clk - Adjust given mode clock rate according to |
| 36 | * the perf clock factor. | 36 | * the perf clock factor. |
| 37 | * @crtc_clk_rate - Unadjusted mode clock rate | 37 | * @mode_clk_rate: unadjusted mode clock rate |
| 38 | * @perf_cfg: performance configuration | 38 | * @perf_cfg: performance configuration |
| 39 | */ | 39 | */ |
| 40 | u64 dpu_core_perf_adjusted_mode_clk(u64 mode_clk_rate, | 40 | u64 dpu_core_perf_adjusted_mode_clk(u64 mode_clk_rate, |
| @@ -394,6 +394,10 @@ int dpu_core_perf_crtc_update(struct drm_crtc *crtc, · 353 unmodified lines | |||
| 394 | 394 | ||
| 395 | trace_dpu_core_perf_update_clk(kms->dev, !crtc->enabled, clk_rate); | 395 | trace_dpu_core_perf_update_clk(kms->dev, !crtc->enabled, clk_rate); |
| 396 | 396 | ||
| 397 | /* If we're going offline, PM callbacks will disable the clocks instead */ | ||
| 398 | if (!clk_rate) | ||
| 399 | return 0; | ||
| 400 | |||
| 397 | clk_rate = min(clk_rate, kms->perf.max_core_clk_rate); | 401 | clk_rate = min(clk_rate, kms->perf.max_core_clk_rate); |
| 398 | ret = dev_pm_opp_set_rate(&kms->pdev->dev, clk_rate); | 402 | ret = dev_pm_opp_set_rate(&kms->pdev->dev, clk_rate); |
| 399 | if (ret) { | 403 | if (ret) { |
| @@ -710,8 +710,7 @@ void dpu_encoder_update_topology(struct drm_encoder *drm_enc, · 709 unmodified lines | |||
| 710 | if (fb && MSM_FORMAT_IS_YUV(msm_framebuffer_format(fb))) | 710 | if (fb && MSM_FORMAT_IS_YUV(msm_framebuffer_format(fb))) |
| 711 | topology->num_cdm++; | 711 | topology->num_cdm++; |
| 712 | } else if (disp_info->intf_type == INTF_DP) { | 712 | } else if (disp_info->intf_type == INTF_DP) { |
| 713 | if (msm_dp_is_yuv_420_enabled(priv->kms->dp[disp_info->h_tile_instance[0]], | 713 | if (drm_mode_is_420_only(&connector->display_info, adj_mode)) |
| 714 | adj_mode)) | ||
| 715 | topology->num_cdm++; | 714 | topology->num_cdm++; |
| 716 | } | 715 | } |
| 717 | } | 716 | } |
| @@ -303,6 +303,16 @@ static const u32 wb2_formats_rgb_yuv[] = { · 302 unmodified lines | |||
| 303 | .num_formats = ARRAY_SIZE(plane_formats), \ | 303 | .num_formats = ARRAY_SIZE(plane_formats), \ |
| 304 | } | 304 | } |
| 305 | 305 | ||
| 306 | #define _DMA_SBLK_V13() \ | ||
| 307 | { \ | ||
| 308 | .sspp_rec0_blk = {.name = "sspp_rec0", \ | ||
| 309 | .base = 0x1000, .len = 0x180,}, \ | ||
| 310 | .sspp_rec1_blk = {.name = "sspp_rec1", \ | ||
| 311 | .base = 0x3000, .len = 0x180,}, \ | ||
| 312 | .format_list = plane_formats, \ | ||
| 313 | .num_formats = ARRAY_SIZE(plane_formats), \ | ||
| 314 | } | ||
| 315 | |||
| 306 | static const struct dpu_rotation_cfg dpu_rot_sc7280_cfg_v2 = { | 316 | static const struct dpu_rotation_cfg dpu_rot_sc7280_cfg_v2 = { |
| 307 | .rot_maxheight = 1088, | 317 | .rot_maxheight = 1088, |
| 308 | .rot_num_formats = ARRAY_SIZE(rotation_v2_formats), | 318 | .rot_num_formats = ARRAY_SIZE(rotation_v2_formats), |
| @@ -353,6 +363,8 @@ static const struct dpu_sspp_sub_blks dpu_rgb_sblk = _RGB_SBLK(); · 44 unmodified lines | |||
| 353 | 363 | ||
| 354 | static const struct dpu_sspp_sub_blks dpu_dma_sblk = _DMA_SBLK(); | 364 | static const struct dpu_sspp_sub_blks dpu_dma_sblk = _DMA_SBLK(); |
| 355 | 365 | ||
| 366 | static const struct dpu_sspp_sub_blks dpu_dma_sblk_v13 = _DMA_SBLK_V13(); | ||
| 367 | |||
| 356 | /************************************************************* | 368 | /************************************************************* |
| 357 | * MIXER sub blocks config | 369 | * MIXER sub blocks config |
| 358 | *************************************************************/ | 370 | *************************************************************/ |
| @@ -398,7 +398,7 @@ static int mdp4_kms_init(struct drm_device *dev) · 397 unmodified lines | |||
| 398 | ret = mdp_kms_init(&mdp4_kms->base, &kms_funcs); | 398 | ret = mdp_kms_init(&mdp4_kms->base, &kms_funcs); |
| 399 | if (ret) { | 399 | if (ret) { |
| 400 | DRM_DEV_ERROR(dev->dev, "failed to init kms\n"); | 400 | DRM_DEV_ERROR(dev->dev, "failed to init kms\n"); |
| 401 | goto fail; | 401 | return ret; |
| 402 | } | 402 | } |
| 403 | 403 | ||
| 404 | kms = priv->kms; | 404 | kms = priv->kms; |
| @@ -409,7 +409,7 @@ static int mdp4_kms_init(struct drm_device *dev) · 4 unmodified lines | |||
| 409 | ret = regulator_enable(mdp4_kms->vdd); | 409 | ret = regulator_enable(mdp4_kms->vdd); |
| 410 | if (ret) { | 410 | if (ret) { |
| 411 | DRM_DEV_ERROR(dev->dev, "failed to enable regulator vdd: %d\n", ret); | 411 | DRM_DEV_ERROR(dev->dev, "failed to enable regulator vdd: %d\n", ret); |
| 412 | goto fail; | 412 | return ret; |
| 413 | } | 413 | } |
| 414 | } | 414 | } |
| 415 | 415 | ||
| @@ -421,7 +421,7 @@ static int mdp4_kms_init(struct drm_device *dev) · 5 unmodified lines | |||
| 421 | DRM_DEV_ERROR(dev->dev, "unexpected MDP version: v%d.%d\n", | 421 | DRM_DEV_ERROR(dev->dev, "unexpected MDP version: v%d.%d\n", |
| 422 | major, minor); | 422 | major, minor); |
| 423 | ret = -ENXIO; | 423 | ret = -ENXIO; |
| 424 | goto fail; | 424 | return ret; |
| 425 | } | 425 | } |
| 426 | 426 | ||
| 427 | mdp4_kms->rev = minor; | 427 | mdp4_kms->rev = minor; |
| @@ -430,7 +430,7 @@ static int mdp4_kms_init(struct drm_device *dev) · 2 unmodified lines | |||
| 430 | if (!mdp4_kms->lut_clk) { | 430 | if (!mdp4_kms->lut_clk) { |
| 431 | DRM_DEV_ERROR(dev->dev, "failed to get lut_clk\n"); | 431 | DRM_DEV_ERROR(dev->dev, "failed to get lut_clk\n"); |
| 432 | ret = -ENODEV; | 432 | ret = -ENODEV; |
| 433 | goto fail; | 433 | return ret; |
| 434 | } | 434 | } |
| 435 | clk_set_rate(mdp4_kms->lut_clk, max_clk); | 435 | clk_set_rate(mdp4_kms->lut_clk, max_clk); |
| 436 | } | 436 | } |
| @@ -452,7 +452,7 @@ static int mdp4_kms_init(struct drm_device *dev) · 15 unmodified lines | |||
| 452 | vm = msm_kms_init_vm(mdp4_kms->dev, NULL); | 452 | vm = msm_kms_init_vm(mdp4_kms->dev, NULL); |
| 453 | if (IS_ERR(vm)) { | 453 | if (IS_ERR(vm)) { |
| 454 | ret = PTR_ERR(vm); | 454 | ret = PTR_ERR(vm); |
| 455 | goto fail; | 455 | return ret; |
| 456 | } | 456 | } |
| 457 | 457 | ||
| 458 | kms->vm = vm; | 458 | kms->vm = vm; |
| @@ -460,22 +460,22 @@ static int mdp4_kms_init(struct drm_device *dev) · 1 unmodified line | |||
| 460 | ret = modeset_init(mdp4_kms); | 460 | ret = modeset_init(mdp4_kms); |
| 461 | if (ret) { | 461 | if (ret) { |
| 462 | DRM_DEV_ERROR(dev->dev, "modeset_init failed: %d\n", ret); | 462 | DRM_DEV_ERROR(dev->dev, "modeset_init failed: %d\n", ret); |
| 463 | goto fail; | 463 | return ret; |
| 464 | } | 464 | } |
| 465 | 465 | ||
| 466 | mdp4_kms->blank_cursor_bo = msm_gem_new(dev, SZ_16K, MSM_BO_WC | MSM_BO_SCANOUT); | 466 | mdp4_kms->blank_cursor_bo = msm_gem_new(dev, SZ_16K, MSM_BO_WC | MSM_BO_SCANOUT, NULL); |
| 467 | if (IS_ERR(mdp4_kms->blank_cursor_bo)) { | 467 | if (IS_ERR(mdp4_kms->blank_cursor_bo)) { |
| 468 | ret = PTR_ERR(mdp4_kms->blank_cursor_bo); | 468 | ret = PTR_ERR(mdp4_kms->blank_cursor_bo); |
| 469 | DRM_DEV_ERROR(dev->dev, "could not allocate blank-cursor bo: %d\n", ret); | 469 | DRM_DEV_ERROR(dev->dev, "could not allocate blank-cursor bo: %d\n", ret); |
| 470 | mdp4_kms->blank_cursor_bo = NULL; | 470 | mdp4_kms->blank_cursor_bo = NULL; |
| 471 | goto fail; | 471 | return ret; |
| 472 | } | 472 | } |
| 473 | 473 | ||
| 474 | ret = msm_gem_get_and_pin_iova(mdp4_kms->blank_cursor_bo, kms->vm, | 474 | ret = msm_gem_get_and_pin_iova(mdp4_kms->blank_cursor_bo, kms->vm, |
| 475 | &mdp4_kms->blank_cursor_iova); | 475 | &mdp4_kms->blank_cursor_iova); |
| 476 | if (ret) { | 476 | if (ret) { |
| 477 | DRM_DEV_ERROR(dev->dev, "could not pin blank-cursor bo: %d\n", ret); | 477 | DRM_DEV_ERROR(dev->dev, "could not pin blank-cursor bo: %d\n", ret); |
| 478 | goto fail; | 478 | return ret; |
| 479 | } | 479 | } |
| 480 | 480 | ||
| 481 | dev->mode_config.min_width = 0; | 481 | dev->mode_config.min_width = 0; |
| @@ -484,12 +484,6 @@ static int mdp4_kms_init(struct drm_device *dev) · 2 unmodified lines | |||
| 484 | dev->mode_config.max_height = 2048; | 484 | dev->mode_config.max_height = 2048; |
| 485 | 485 | ||
| 486 | return 0; | 486 | return 0; |
| 487 | |||
| 488 | fail: | ||
| 489 | if (kms) | ||
| 490 | mdp4_destroy(kms); | ||
| 491 | |||
| 492 | return ret; | ||
| 493 | } | 487 | } |
| 494 | 488 | ||
| 495 | static const struct dev_pm_ops mdp4_pm_ops = { | 489 | static const struct dev_pm_ops mdp4_pm_ops = { |
| @@ -517,7 +517,7 @@ static int mdp5_kms_init(struct drm_device *dev) · 516 unmodified lines | |||
| 517 | ret = mdp_kms_init(&mdp5_kms->base, &kms_funcs); | 517 | ret = mdp_kms_init(&mdp5_kms->base, &kms_funcs); |
| 518 | if (ret) { | 518 | if (ret) { |
| 519 | DRM_DEV_ERROR(&pdev->dev, "failed to init kms\n"); | 519 | DRM_DEV_ERROR(&pdev->dev, "failed to init kms\n"); |
| 520 | goto fail; | 520 | return ret; |
| 521 | } | 521 | } |
| 522 | 522 | ||
| 523 | config = mdp5_cfg_get_config(mdp5_kms->cfg); | 523 | config = mdp5_cfg_get_config(mdp5_kms->cfg); |
| @@ -540,7 +540,7 @@ static int mdp5_kms_init(struct drm_device *dev) · 16 unmodified lines | |||
| 540 | vm = msm_kms_init_vm(mdp5_kms->dev, pdev->dev.parent); | 540 | vm = msm_kms_init_vm(mdp5_kms->dev, pdev->dev.parent); |
| 541 | if (IS_ERR(vm)) { | 541 | if (IS_ERR(vm)) { |
| 542 | ret = PTR_ERR(vm); | 542 | ret = PTR_ERR(vm); |
| 543 | goto fail; | 543 | return ret; |
| 544 | } | 544 | } |
| 545 | 545 | ||
| 546 | kms->vm = vm; | 546 | kms->vm = vm; |
| @@ -550,7 +550,7 @@ static int mdp5_kms_init(struct drm_device *dev) · 3 unmodified lines | |||
| 550 | ret = modeset_init(mdp5_kms); | 550 | ret = modeset_init(mdp5_kms); |
| 551 | if (ret) { | 551 | if (ret) { |
| 552 | DRM_DEV_ERROR(&pdev->dev, "modeset_init failed: %d\n", ret); | 552 | DRM_DEV_ERROR(&pdev->dev, "modeset_init failed: %d\n", ret); |
| 553 | goto fail; | 553 | return ret; |
| 554 | } | 554 | } |
| 555 | 555 | ||
| 556 | dev->mode_config.min_width = 0; | 556 | dev->mode_config.min_width = 0; |
| @@ -562,11 +562,6 @@ static int mdp5_kms_init(struct drm_device *dev) · 5 unmodified lines | |||
| 562 | dev->vblank_disable_immediate = true; | 562 | dev->vblank_disable_immediate = true; |
| 563 | 563 | ||
| 564 | return 0; | 564 | return 0; |
| 565 | fail: | ||
| 566 | if (kms) | ||
| 567 | mdp5_kms_destroy(kms); | ||
| 568 | |||
| 569 | return ret; | ||
| 570 | } | 565 | } |
| 571 | 566 | ||
| 572 | static void mdp5_destroy(struct mdp5_kms *mdp5_kms) | 567 | static void mdp5_destroy(struct mdp5_kms *mdp5_kms) |
| @@ -284,10 +284,8 @@ int msm_dp_audio_prepare(struct drm_bridge *bridge, · 283 unmodified lines | |||
| 284 | * such cases check for connection status and bail out if not | 284 | * such cases check for connection status and bail out if not |
| 285 | * connected. | 285 | * connected. |
| 286 | */ | 286 | */ |
| 287 | if (!msm_dp_display->power_on) { | 287 | if (!msm_dp_display->power_on) |
| 288 | rc = -EINVAL; | ||
| 289 | goto end; | 288 | goto end; |
| 290 | } | ||
| 291 | 289 | ||
| 292 | audio = msm_dp_audio_get_data(msm_dp_display); | 290 | audio = msm_dp_audio_get_data(msm_dp_display); |
| 293 | if (IS_ERR(audio)) { | 291 | if (IS_ERR(audio)) { |
| @@ -114,7 +114,6 @@ struct msm_dp_ctrl_private { · 113 unmodified lines | |||
| 114 | struct drm_device *drm_dev; | 114 | struct drm_device *drm_dev; |
| 115 | struct device *dev; | 115 | struct device *dev; |
| 116 | struct drm_dp_aux *aux; | 116 | struct drm_dp_aux *aux; |
| 117 | struct msm_dp_panel *panel; | ||
| 118 | struct msm_dp_link *link; | 117 | struct msm_dp_link *link; |
| 119 | void __iomem *ahb_base; | 118 | void __iomem *ahb_base; |
| 120 | void __iomem *link_base; | 119 | void __iomem *link_base; |
| @@ -202,7 +201,8 @@ static int msm_dp_aux_link_configure(struct drm_dp_aux *aux, · 81 unmodified lines | |||
| 202 | /* | 201 | /* |
| 203 | * NOTE: resetting DP controller will also clear any pending HPD related interrupts | 202 | * NOTE: resetting DP controller will also clear any pending HPD related interrupts |
| 204 | */ | 203 | */ |
| 205 | void msm_dp_ctrl_reset(struct msm_dp_ctrl *msm_dp_ctrl) | 204 | void msm_dp_ctrl_reset(struct msm_dp_ctrl *msm_dp_ctrl, |
| 205 | struct msm_dp_panel *panel) | ||
| 206 | { | 206 | { |
| 207 | struct msm_dp_ctrl_private *ctrl = | 207 | struct msm_dp_ctrl_private *ctrl = |
| 208 | container_of(msm_dp_ctrl, struct msm_dp_ctrl_private, msm_dp_ctrl); | 208 | container_of(msm_dp_ctrl, struct msm_dp_ctrl_private, msm_dp_ctrl); |
| @@ -217,10 +217,9 @@ void msm_dp_ctrl_reset(struct msm_dp_ctrl *msm_dp_ctrl) · 8 unmodified lines | |||
| 217 | sw_reset &= ~DP_SW_RESET; | 217 | sw_reset &= ~DP_SW_RESET; |
| 218 | msm_dp_write_ahb(ctrl, REG_DP_SW_RESET, sw_reset); | 218 | msm_dp_write_ahb(ctrl, REG_DP_SW_RESET, sw_reset); |
| 219 | 219 | ||
| 220 | if (!ctrl->hw_revision) { | 220 | if (!ctrl->hw_revision) |
| 221 | ctrl->hw_revision = msm_dp_read_ahb(ctrl, REG_DP_HW_VERSION); | 221 | ctrl->hw_revision = msm_dp_read_ahb(ctrl, REG_DP_HW_VERSION); |
| 222 | ctrl->panel->hw_revision = ctrl->hw_revision; | 222 | panel->hw_revision = ctrl->hw_revision; |
| 223 | } | ||
| 224 | } | 223 | } |
| 225 | 224 | ||
| 226 | static u32 msm_dp_ctrl_get_aux_interrupt(struct msm_dp_ctrl_private *ctrl) | 225 | static u32 msm_dp_ctrl_get_aux_interrupt(struct msm_dp_ctrl_private *ctrl) |
| @@ -388,26 +387,49 @@ void msm_dp_ctrl_push_idle(struct msm_dp_ctrl *msm_dp_ctrl) · 161 unmodified lines | |||
| 388 | drm_dbg_dp(ctrl->drm_dev, "mainlink off\n"); | 387 | drm_dbg_dp(ctrl->drm_dev, "mainlink off\n"); |
| 389 | } | 388 | } |
| 390 | 389 | ||
| 391 | static void msm_dp_ctrl_config_ctrl(struct msm_dp_ctrl_private *ctrl) | 390 | static void msm_dp_ctrl_config_ctrl_streams(struct msm_dp_ctrl_private *ctrl, |
| 391 | struct msm_dp_panel *msm_dp_panel) | ||
| 392 | { | 392 | { |
| 393 | u32 config = 0, tbd; | 393 | u32 config = 0, tbd; |
| 394 | const u8 *dpcd = ctrl->panel->dpcd; | ||
| 395 | 394 | ||
| 396 | /* Default-> LSCLK DIV: 1/4 LCLK */ | 395 | /* |
| 397 | config |= (2 << DP_CONFIGURATION_CTRL_LSCLK_DIV_SHIFT); | 396 | * RMW: called from atomic_enable(), serialized by the DRM atomic framework. |
| 397 | * Clear stream-specific fields before OR-ing to avoid bit accumulation. | ||
| 398 | */ | ||
| 399 | config = msm_dp_read_link(ctrl, REG_DP_CONFIGURATION_CTRL); | ||
| 400 | config &= ~(DP_CONFIGURATION_CTRL_RGB_YUV_MASK | | ||
| 401 | DP_CONFIGURATION_CTRL_BPC_MASK | | ||
| 402 | DP_CONFIGURATION_CTRL_SEND_VSC); | ||
| 398 | 403 | ||
| 399 | if (ctrl->panel->msm_dp_mode.out_fmt_is_yuv_420) | 404 | if (msm_dp_panel->msm_dp_mode.out_fmt_is_yuv_420) |
| 400 | config |= DP_CONFIGURATION_CTRL_RGB_YUV; /* YUV420 */ | 405 | config |= DP_CONFIGURATION_CTRL_RGB_YUV; /* YUV420 */ |
| 401 | 406 | ||
| 402 | /* Scrambler reset enable */ | ||
| 403 | if (drm_dp_alternate_scrambler_reset_cap(dpcd)) | ||
| 404 | config |= DP_CONFIGURATION_CTRL_ASSR; | ||
| 405 | |||
| 406 | tbd = msm_dp_link_get_test_bits_depth(ctrl->link, | 407 | tbd = msm_dp_link_get_test_bits_depth(ctrl->link, |
| 407 | ctrl->panel->msm_dp_mode.bpp); | 408 | msm_dp_panel->msm_dp_mode.bpp); |
| 408 | 409 | ||
| 409 | config |= tbd << DP_CONFIGURATION_CTRL_BPC_SHIFT; | 410 | config |= tbd << DP_CONFIGURATION_CTRL_BPC_SHIFT; |
| 410 | 411 | ||
| 412 | if (msm_dp_panel->psr_cap.version) | ||
| 413 | config |= DP_CONFIGURATION_CTRL_SEND_VSC; | ||
| 414 | |||
| 415 | drm_dbg_dp(ctrl->drm_dev, "stream DP_CONFIGURATION_CTRL=0x%x\n", config); | ||
| 416 | |||
| 417 | msm_dp_write_link(ctrl, REG_DP_CONFIGURATION_CTRL, config); | ||
| 418 | } | ||
| 419 | |||
| 420 | static void msm_dp_ctrl_config_ctrl_link(struct msm_dp_ctrl_private *ctrl, | ||
| 421 | struct msm_dp_panel *panel) | ||
| 422 | { | ||
| 423 | u32 config = 0; | ||
| 424 | const u8 *dpcd = panel->dpcd; | ||
| 425 | |||
| 426 | /* Default-> LSCLK DIV: 1/4 LCLK */ | ||
| 427 | config |= (2 << DP_CONFIGURATION_CTRL_LSCLK_DIV_SHIFT); | ||
| 428 | |||
| 429 | /* Scrambler reset enable */ | ||
| 430 | if (drm_dp_alternate_scrambler_reset_cap(dpcd)) | ||
| 431 | config |= DP_CONFIGURATION_CTRL_ASSR; | ||
| 432 | |||
| 411 | /* Num of Lanes */ | 433 | /* Num of Lanes */ |
| 412 | config |= ((ctrl->link->link_params.num_lanes - 1) | 434 | config |= ((ctrl->link->link_params.num_lanes - 1) |
| 413 | << DP_CONFIGURATION_CTRL_NUM_OF_LANES_SHIFT); | 435 | << DP_CONFIGURATION_CTRL_NUM_OF_LANES_SHIFT); |
| @@ -421,10 +443,7 @@ static void msm_dp_ctrl_config_ctrl(struct msm_dp_ctrl_private *ctrl) · 7 unmodified lines | |||
| 421 | config |= DP_CONFIGURATION_CTRL_STATIC_DYNAMIC_CN; | 443 | config |= DP_CONFIGURATION_CTRL_STATIC_DYNAMIC_CN; |
| 422 | config |= DP_CONFIGURATION_CTRL_SYNC_ASYNC_CLK; | 444 | config |= DP_CONFIGURATION_CTRL_SYNC_ASYNC_CLK; |
| 423 | 445 | ||
| 424 | if (ctrl->panel->psr_cap.version) | 446 | drm_dbg_dp(ctrl->drm_dev, "link DP_CONFIGURATION_CTRL=0x%x\n", config); |
| 425 | config |= DP_CONFIGURATION_CTRL_SEND_VSC; | ||
| 426 | |||
| 427 | drm_dbg_dp(ctrl->drm_dev, "DP_CONFIGURATION_CTRL=0x%x\n", config); | ||
| 428 | 447 | ||
| 429 | msm_dp_write_link(ctrl, REG_DP_CONFIGURATION_CTRL, config); | 448 | msm_dp_write_link(ctrl, REG_DP_CONFIGURATION_CTRL, config); |
| 430 | } | 449 | } |
| @@ -443,16 +462,13 @@ static void msm_dp_ctrl_lane_mapping(struct msm_dp_ctrl_private *ctrl) · 12 unmodified lines | |||
| 443 | ln_mapping); | 462 | ln_mapping); |
| 444 | } | 463 | } |
| 445 | 464 | ||
| 446 | static void msm_dp_ctrl_configure_source_params(struct msm_dp_ctrl_private *ctrl) | 465 | static void msm_dp_ctrl_config_misc1_misc0(struct msm_dp_ctrl_private *ctrl, |
| 466 | struct msm_dp_panel *msm_dp_panel) | ||
| 447 | { | 467 | { |
| 448 | u32 colorimetry_cfg, test_bits_depth, misc_val; | 468 | u32 colorimetry_cfg, test_bits_depth, misc_val; |
| 449 | 469 | ||
| 450 | msm_dp_ctrl_lane_mapping(ctrl); | 470 | test_bits_depth = msm_dp_link_get_test_bits_depth(ctrl->link, |
| 451 | msm_dp_setup_peripheral_flush(ctrl); | 471 | msm_dp_panel->msm_dp_mode.bpp); |
| 452 | |||
| 453 | msm_dp_ctrl_config_ctrl(ctrl); | ||
| 454 | |||
| 455 | test_bits_depth = msm_dp_link_get_test_bits_depth(ctrl->link, ctrl->panel->msm_dp_mode.bpp); | ||
| 456 | colorimetry_cfg = msm_dp_link_get_colorimetry_config(ctrl->link); | 472 | colorimetry_cfg = msm_dp_link_get_colorimetry_config(ctrl->link); |
| 457 | 473 | ||
| 458 | misc_val = msm_dp_read_link(ctrl, REG_DP_MISC1_MISC0); | 474 | misc_val = msm_dp_read_link(ctrl, REG_DP_MISC1_MISC0); |
| @@ -466,8 +482,16 @@ static void msm_dp_ctrl_configure_source_params(struct msm_dp_ctrl_private *ctrl · 7 unmodified lines | |||
| 466 | 482 | ||
| 467 | drm_dbg_dp(ctrl->drm_dev, "misc settings = 0x%x\n", misc_val); | 483 | drm_dbg_dp(ctrl->drm_dev, "misc settings = 0x%x\n", misc_val); |
| 468 | msm_dp_write_link(ctrl, REG_DP_MISC1_MISC0, misc_val); | 484 | msm_dp_write_link(ctrl, REG_DP_MISC1_MISC0, misc_val); |
| 485 | } | ||
| 469 | 486 | ||
| 470 | msm_dp_panel_timing_cfg(ctrl->panel, ctrl->msm_dp_ctrl.wide_bus_en); | 487 | static void msm_dp_ctrl_configure_source_params(struct msm_dp_ctrl_private *ctrl, |
| 488 | struct msm_dp_panel *panel) | ||
| 489 | { | ||
| 490 | msm_dp_ctrl_config_ctrl_streams(ctrl, panel); | ||
| 491 | |||
| 492 | msm_dp_ctrl_config_misc1_misc0(ctrl, panel); | ||
| 493 | |||
| 494 | msm_dp_panel_timing_cfg(panel, ctrl->msm_dp_ctrl.wide_bus_en); | ||
| 471 | } | 495 | } |
| 472 | 496 | ||
| 473 | /* | 497 | /* |
| @@ -1237,20 +1261,21 @@ tu_size_calc: · 763 unmodified lines | |||
| 1237 | } | 1261 | } |
| 1238 | 1262 | ||
| 1239 | static void msm_dp_ctrl_calc_tu_parameters(struct msm_dp_ctrl_private *ctrl, | 1263 | static void msm_dp_ctrl_calc_tu_parameters(struct msm_dp_ctrl_private *ctrl, |
| 1264 | struct msm_dp_panel *panel, | ||
| 1240 | struct msm_dp_vc_tu_mapping_table *tu_table) | 1265 | struct msm_dp_vc_tu_mapping_table *tu_table) |
| 1241 | { | 1266 | { |
| 1242 | struct msm_dp_tu_calc_input in; | 1267 | struct msm_dp_tu_calc_input in; |
| 1243 | struct drm_display_mode *drm_mode; | 1268 | const struct drm_display_mode *drm_mode; |
| 1244 | 1269 | ||
| 1245 | drm_mode = &ctrl->panel->msm_dp_mode.drm_mode; | 1270 | drm_mode = &panel->msm_dp_mode.drm_mode; |
| 1246 | 1271 | ||
| 1247 | in.lclk = ctrl->link->link_params.rate / 1000; | 1272 | in.lclk = ctrl->link->link_params.rate / 1000; |
| 1248 | in.pclk_khz = drm_mode->clock; | 1273 | in.pclk_khz = drm_mode->clock; |
| 1249 | in.hactive = drm_mode->hdisplay; | 1274 | in.hactive = drm_mode->hdisplay; |
| 1250 | in.hporch = drm_mode->htotal - drm_mode->hdisplay; | 1275 | in.hporch = drm_mode->htotal - drm_mode->hdisplay; |
| 1251 | in.nlanes = ctrl->link->link_params.num_lanes; | 1276 | in.nlanes = ctrl->link->link_params.num_lanes; |
| 1252 | in.bpp = ctrl->panel->msm_dp_mode.bpp; | 1277 | in.bpp = panel->msm_dp_mode.bpp; |
| 1253 | in.pixel_enc = ctrl->panel->msm_dp_mode.out_fmt_is_yuv_420 ? 420 : 444; | 1278 | in.pixel_enc = panel->msm_dp_mode.out_fmt_is_yuv_420 ? 420 : 444; |
| 1254 | in.dsc_en = 0; | 1279 | in.dsc_en = 0; |
| 1255 | in.async_en = 0; | 1280 | in.async_en = 0; |
| 1256 | in.fec_en = 0; | 1281 | in.fec_en = 0; |
| @@ -1260,14 +1285,15 @@ static void msm_dp_ctrl_calc_tu_parameters(struct msm_dp_ctrl_private *ctrl, · 3 unmodified lines | |||
| 1260 | _dp_ctrl_calc_tu(ctrl, &in, tu_table); | 1285 | _dp_ctrl_calc_tu(ctrl, &in, tu_table); |
| 1261 | } | 1286 | } |
| 1262 | 1287 | ||
| 1263 | static void msm_dp_ctrl_setup_tr_unit(struct msm_dp_ctrl_private *ctrl) | 1288 | static void msm_dp_ctrl_setup_tr_unit(struct msm_dp_ctrl_private *ctrl, |
| 1289 | struct msm_dp_panel *panel) | ||
| 1264 | { | 1290 | { |
| 1265 | u32 msm_dp_tu = 0x0; | 1291 | u32 msm_dp_tu = 0x0; |
| 1266 | u32 valid_boundary = 0x0; | 1292 | u32 valid_boundary = 0x0; |
| 1267 | u32 valid_boundary2 = 0x0; | 1293 | u32 valid_boundary2 = 0x0; |
| 1268 | struct msm_dp_vc_tu_mapping_table tu_calc_table; | 1294 | struct msm_dp_vc_tu_mapping_table tu_calc_table; |
| 1269 | 1295 | ||
| 1270 | msm_dp_ctrl_calc_tu_parameters(ctrl, &tu_calc_table); | 1296 | msm_dp_ctrl_calc_tu_parameters(ctrl, panel, &tu_calc_table); |
| 1271 | 1297 | ||
| 1272 | msm_dp_tu |= tu_calc_table.tu_size_minus1; | 1298 | msm_dp_tu |= tu_calc_table.tu_size_minus1; |
| 1273 | valid_boundary |= tu_calc_table.valid_boundary_link; | 1299 | valid_boundary |= tu_calc_table.valid_boundary_link; |
| @@ -1419,6 +1445,7 @@ static int msm_dp_ctrl_set_pattern_state_bit(struct msm_dp_ctrl_private *ctrl, · 145 unmodified lines | |||
| 1419 | } | 1445 | } |
| 1420 | 1446 | ||
| 1421 | static int msm_dp_ctrl_link_train_1(struct msm_dp_ctrl_private *ctrl, | 1447 | static int msm_dp_ctrl_link_train_1(struct msm_dp_ctrl_private *ctrl, |
| 1448 | struct msm_dp_panel *panel, | ||
| 1422 | int *training_step, enum drm_dp_phy dp_phy) | 1449 | int *training_step, enum drm_dp_phy dp_phy) |
| 1423 | { | 1450 | { |
| 1424 | int delay_us; | 1451 | int delay_us; |
| @@ -1427,7 +1454,7 @@ static int msm_dp_ctrl_link_train_1(struct msm_dp_ctrl_private *ctrl, · 2 unmodified lines | |||
| 1427 | int const maximum_retries = 4; | 1454 | int const maximum_retries = 4; |
| 1428 | 1455 | ||
| 1429 | delay_us = drm_dp_read_clock_recovery_delay(ctrl->aux, | 1456 | delay_us = drm_dp_read_clock_recovery_delay(ctrl->aux, |
| 1430 | ctrl->panel->dpcd, dp_phy, false); | 1457 | panel->dpcd, dp_phy, false); |
| 1431 | 1458 | ||
| 1432 | msm_dp_write_link(ctrl, REG_DP_STATE_CTRL, 0); | 1459 | msm_dp_write_link(ctrl, REG_DP_STATE_CTRL, 0); |
| 1433 | 1460 | ||
| @@ -1513,14 +1540,15 @@ static int msm_dp_ctrl_link_rate_down_shift(struct msm_dp_ctrl_private *ctrl) · 79 unmodified lines | |||
| 1513 | return ret; | 1540 | return ret; |
| 1514 | } | 1541 | } |
| 1515 | 1542 | ||
| 1516 | static int msm_dp_ctrl_link_lane_down_shift(struct msm_dp_ctrl_private *ctrl) | 1543 | static int msm_dp_ctrl_link_lane_down_shift(struct msm_dp_ctrl_private *ctrl, |
| 1544 | struct msm_dp_panel *panel) | ||
| 1517 | { | 1545 | { |
| 1518 | 1546 | ||
| 1519 | if (ctrl->link->link_params.num_lanes == 1) | 1547 | if (ctrl->link->link_params.num_lanes == 1) |
| 1520 | return -1; | 1548 | return -1; |
| 1521 | 1549 | ||
| 1522 | ctrl->link->link_params.num_lanes /= 2; | 1550 | ctrl->link->link_params.num_lanes /= 2; |
| 1523 | ctrl->link->link_params.rate = ctrl->panel->link_info.rate; | 1551 | ctrl->link->link_params.rate = panel->link_info.rate; |
| 1524 | 1552 | ||
| 1525 | ctrl->link->phy_params.p_level = 0; | 1553 | ctrl->link->phy_params.p_level = 0; |
| 1526 | ctrl->link->phy_params.v_level = 0; | 1554 | ctrl->link->phy_params.v_level = 0; |
| @@ -1529,6 +1557,7 @@ static int msm_dp_ctrl_link_lane_down_shift(struct msm_dp_ctrl_private *ctrl) · 2 unmodified lines | |||
| 1529 | } | 1557 | } |
| 1530 | 1558 | ||
| 1531 | static void msm_dp_ctrl_clear_training_pattern(struct msm_dp_ctrl_private *ctrl, | 1559 | static void msm_dp_ctrl_clear_training_pattern(struct msm_dp_ctrl_private *ctrl, |
| 1560 | struct msm_dp_panel *panel, | ||
| 1532 | enum drm_dp_phy dp_phy) | 1561 | enum drm_dp_phy dp_phy) |
| 1533 | { | 1562 | { |
| 1534 | int delay_us; | 1563 | int delay_us; |
| @@ -1536,11 +1565,12 @@ static void msm_dp_ctrl_clear_training_pattern(struct msm_dp_ctrl_private *ctrl, · 1 unmodified line | |||
| 1536 | msm_dp_ctrl_train_pattern_set(ctrl, DP_TRAINING_PATTERN_DISABLE, dp_phy); | 1565 | msm_dp_ctrl_train_pattern_set(ctrl, DP_TRAINING_PATTERN_DISABLE, dp_phy); |
| 1537 | 1566 | ||
| 1538 | delay_us = drm_dp_read_channel_eq_delay(ctrl->aux, | 1567 | delay_us = drm_dp_read_channel_eq_delay(ctrl->aux, |
| 1539 | ctrl->panel->dpcd, dp_phy, false); | 1568 | panel->dpcd, dp_phy, false); |
| 1540 | fsleep(delay_us); | 1569 | fsleep(delay_us); |
| 1541 | } | 1570 | } |
| 1542 | 1571 | ||
| 1543 | static int msm_dp_ctrl_link_train_2(struct msm_dp_ctrl_private *ctrl, | 1572 | static int msm_dp_ctrl_link_train_2(struct msm_dp_ctrl_private *ctrl, |
| 1573 | struct msm_dp_panel *panel, | ||
| 1544 | int *training_step, enum drm_dp_phy dp_phy) | 1574 | int *training_step, enum drm_dp_phy dp_phy) |
| 1545 | { | 1575 | { |
| 1546 | int delay_us; | 1576 | int delay_us; |
| @@ -1551,16 +1581,16 @@ static int msm_dp_ctrl_link_train_2(struct msm_dp_ctrl_private *ctrl, · 4 unmodified lines | |||
| 1551 | u8 link_status[DP_LINK_STATUS_SIZE]; | 1581 | u8 link_status[DP_LINK_STATUS_SIZE]; |
| 1552 | 1582 | ||
| 1553 | delay_us = drm_dp_read_channel_eq_delay(ctrl->aux, | 1583 | delay_us = drm_dp_read_channel_eq_delay(ctrl->aux, |
| 1554 | ctrl->panel->dpcd, dp_phy, false); | 1584 | panel->dpcd, dp_phy, false); |
| 1555 | 1585 | ||
| 1556 | msm_dp_write_link(ctrl, REG_DP_STATE_CTRL, 0); | 1586 | msm_dp_write_link(ctrl, REG_DP_STATE_CTRL, 0); |
| 1557 | 1587 | ||
| 1558 | *training_step = DP_TRAINING_2; | 1588 | *training_step = DP_TRAINING_2; |
| 1559 | 1589 | ||
| 1560 | if (drm_dp_tps4_supported(ctrl->panel->dpcd)) { | 1590 | if (drm_dp_tps4_supported(panel->dpcd)) { |
| 1561 | pattern = DP_TRAINING_PATTERN_4; | 1591 | pattern = DP_TRAINING_PATTERN_4; |
| 1562 | state_ctrl_bit = 4; | 1592 | state_ctrl_bit = 4; |
| 1563 | } else if (drm_dp_tps3_supported(ctrl->panel->dpcd)) { | 1593 | } else if (drm_dp_tps3_supported(panel->dpcd)) { |
| 1564 | pattern = DP_TRAINING_PATTERN_3; | 1594 | pattern = DP_TRAINING_PATTERN_3; |
| 1565 | state_ctrl_bit = 3; | 1595 | state_ctrl_bit = 3; |
| 1566 | } else { | 1596 | } else { |
| @@ -1597,18 +1627,19 @@ static int msm_dp_ctrl_link_train_2(struct msm_dp_ctrl_private *ctrl, · 30 unmodified lines | |||
| 1597 | } | 1627 | } |
| 1598 | 1628 | ||
| 1599 | static int msm_dp_ctrl_link_train_1_2(struct msm_dp_ctrl_private *ctrl, | 1629 | static int msm_dp_ctrl_link_train_1_2(struct msm_dp_ctrl_private *ctrl, |
| 1630 | struct msm_dp_panel *panel, | ||
| 1600 | int *training_step, enum drm_dp_phy dp_phy) | 1631 | int *training_step, enum drm_dp_phy dp_phy) |
| 1601 | { | 1632 | { |
| 1602 | int ret; | 1633 | int ret; |
| 1603 | 1634 | ||
| 1604 | ret = msm_dp_ctrl_link_train_1(ctrl, training_step, dp_phy); | 1635 | ret = msm_dp_ctrl_link_train_1(ctrl, panel, training_step, dp_phy); |
| 1605 | if (ret) { | 1636 | if (ret) { |
| 1606 | DRM_ERROR("link training #1 on phy %d failed. ret=%d\n", dp_phy, ret); | 1637 | DRM_ERROR("link training #1 on phy %d failed. ret=%d\n", dp_phy, ret); |
| 1607 | return ret; | 1638 | return ret; |
| 1608 | } | 1639 | } |
| 1609 | drm_dbg_dp(ctrl->drm_dev, "link training #1 on phy %d successful\n", dp_phy); | 1640 | drm_dbg_dp(ctrl->drm_dev, "link training #1 on phy %d successful\n", dp_phy); |
| 1610 | 1641 | ||
| 1611 | ret = msm_dp_ctrl_link_train_2(ctrl, training_step, dp_phy); | 1642 | ret = msm_dp_ctrl_link_train_2(ctrl, panel, training_step, dp_phy); |
| 1612 | if (ret) { | 1643 | if (ret) { |
| 1613 | DRM_ERROR("link training #2 on phy %d failed. ret=%d\n", dp_phy, ret); | 1644 | DRM_ERROR("link training #2 on phy %d failed. ret=%d\n", dp_phy, ret); |
| 1614 | return ret; | 1645 | return ret; |
| @@ -1619,16 +1650,18 @@ static int msm_dp_ctrl_link_train_1_2(struct msm_dp_ctrl_private *ctrl, · 4 unmodified lines | |||
| 1619 | } | 1650 | } |
| 1620 | 1651 | ||
| 1621 | static int msm_dp_ctrl_link_train(struct msm_dp_ctrl_private *ctrl, | 1652 | static int msm_dp_ctrl_link_train(struct msm_dp_ctrl_private *ctrl, |
| 1653 | struct msm_dp_panel *panel, | ||
| 1622 | int *training_step) | 1654 | int *training_step) |
| 1623 | { | 1655 | { |
| 1624 | int i; | 1656 | int i; |
| 1625 | int ret = 0; | 1657 | int ret = 0; |
| 1626 | const u8 *dpcd = ctrl->panel->dpcd; | 1658 | const u8 *dpcd = panel->dpcd; |
| 1627 | u8 encoding[] = { 0, DP_SET_ANSI_8B10B }; | 1659 | u8 encoding[] = { 0, DP_SET_ANSI_8B10B }; |
| 1628 | u8 assr; | 1660 | u8 assr; |
| 1629 | struct msm_dp_link_info link_info = {0}; | 1661 | struct msm_dp_link_info link_info = {0}; |
| 1630 | 1662 | ||
| 1631 | msm_dp_ctrl_config_ctrl(ctrl); | 1663 | msm_dp_ctrl_config_ctrl_link(ctrl, panel); |
| 1664 | msm_dp_ctrl_config_ctrl_streams(ctrl, panel); | ||
| 1632 | 1665 | ||
| 1633 | link_info.num_lanes = ctrl->link->link_params.num_lanes; | 1666 | link_info.num_lanes = ctrl->link->link_params.num_lanes; |
| 1634 | link_info.rate = ctrl->link->link_params.rate; | 1667 | link_info.rate = ctrl->link->link_params.rate; |
| @@ -1651,8 +1684,8 @@ static int msm_dp_ctrl_link_train(struct msm_dp_ctrl_private *ctrl, · 16 unmodified lines | |||
| 1651 | for (i = ctrl->link->lttpr_count - 1; i >= 0; i--) { | 1684 | for (i = ctrl->link->lttpr_count - 1; i >= 0; i--) { |
| 1652 | enum drm_dp_phy dp_phy = DP_PHY_LTTPR(i); | 1685 | enum drm_dp_phy dp_phy = DP_PHY_LTTPR(i); |
| 1653 | 1686 | ||
| 1654 | ret = msm_dp_ctrl_link_train_1_2(ctrl, training_step, dp_phy); | 1687 | ret = msm_dp_ctrl_link_train_1_2(ctrl, panel, training_step, dp_phy); |
| 1655 | msm_dp_ctrl_clear_training_pattern(ctrl, dp_phy); | 1688 | msm_dp_ctrl_clear_training_pattern(ctrl, panel, dp_phy); |
| 1656 | 1689 | ||
| 1657 | if (ret) | 1690 | if (ret) |
| 1658 | break; | 1691 | break; |
| @@ -1663,7 +1696,7 @@ static int msm_dp_ctrl_link_train(struct msm_dp_ctrl_private *ctrl, · 4 unmodified lines | |||
| 1663 | goto end; | 1696 | goto end; |
| 1664 | } | 1697 | } |
| 1665 | 1698 | ||
| 1666 | ret = msm_dp_ctrl_link_train_1_2(ctrl, training_step, DP_PHY_DPRX); | 1699 | ret = msm_dp_ctrl_link_train_1_2(ctrl, panel, training_step, DP_PHY_DPRX); |
| 1667 | if (ret) { | 1700 | if (ret) { |
| 1668 | DRM_ERROR("link training on sink failed. ret=%d\n", ret); | 1701 | DRM_ERROR("link training on sink failed. ret=%d\n", ret); |
| 1669 | goto end; | 1702 | goto end; |
| @@ -1676,6 +1709,7 @@ end: · 6 unmodified lines | |||
| 1676 | } | 1709 | } |
| 1677 | 1710 | ||
| 1678 | static int msm_dp_ctrl_setup_main_link(struct msm_dp_ctrl_private *ctrl, | 1711 | static int msm_dp_ctrl_setup_main_link(struct msm_dp_ctrl_private *ctrl, |
| 1712 | struct msm_dp_panel *panel, | ||
| 1679 | int *training_step) | 1713 | int *training_step) |
| 1680 | { | 1714 | { |
| 1681 | int ret = 0; | 1715 | int ret = 0; |
| @@ -1691,7 +1725,7 @@ static int msm_dp_ctrl_setup_main_link(struct msm_dp_ctrl_private *ctrl, · 9 unmodified lines | |||
| 1691 | * a link training pattern, we have to first do soft reset. | 1725 | * a link training pattern, we have to first do soft reset. |
| 1692 | */ | 1726 | */ |
| 1693 | 1727 | ||
| 1694 | ret = msm_dp_ctrl_link_train(ctrl, training_step); | 1728 | ret = msm_dp_ctrl_link_train(ctrl, panel, training_step); |
| 1695 | 1729 | ||
| 1696 | return ret; | 1730 | return ret; |
| 1697 | } | 1731 | } |
| @@ -1790,11 +1824,12 @@ static void msm_dp_ctrl_link_clk_disable(struct msm_dp_ctrl *msm_dp_ctrl) · 92 unmodified lines | |||
| 1790 | str_on_off(ctrl->core_clks_on)); | 1824 | str_on_off(ctrl->core_clks_on)); |
| 1791 | } | 1825 | } |
| 1792 | 1826 | ||
| 1793 | static int msm_dp_ctrl_enable_mainlink_clocks(struct msm_dp_ctrl_private *ctrl) | 1827 | static int msm_dp_ctrl_enable_mainlink_clocks(struct msm_dp_ctrl_private *ctrl, |
| 1828 | struct msm_dp_panel *panel) | ||
| 1794 | { | 1829 | { |
| 1795 | int ret = 0; | 1830 | int ret = 0; |
| 1796 | struct phy *phy = ctrl->phy; | 1831 | struct phy *phy = ctrl->phy; |
| 1797 | const u8 *dpcd = ctrl->panel->dpcd; | 1832 | const u8 *dpcd = panel->dpcd; |
| 1798 | 1833 | ||
| 1799 | ctrl->phy_opts.dp.lanes = ctrl->link->link_params.num_lanes; | 1834 | ctrl->phy_opts.dp.lanes = ctrl->link->link_params.num_lanes; |
| 1800 | ctrl->phy_opts.dp.link_rate = ctrl->link->link_params.rate / 100; | 1835 | ctrl->phy_opts.dp.link_rate = ctrl->link->link_params.rate / 100; |
| @@ -1846,13 +1881,14 @@ static void msm_dp_ctrl_psr_exit(struct msm_dp_ctrl_private *ctrl) · 45 unmodified lines | |||
| 1846 | msm_dp_write_link(ctrl, REG_PSR_CMD, cmd); | 1881 | msm_dp_write_link(ctrl, REG_PSR_CMD, cmd); |
| 1847 | } | 1882 | } |
| 1848 | 1883 | ||
| 1849 | void msm_dp_ctrl_config_psr(struct msm_dp_ctrl *msm_dp_ctrl) | 1884 | void msm_dp_ctrl_config_psr(struct msm_dp_ctrl *msm_dp_ctrl, |
| 1885 | struct msm_dp_panel *panel) | ||
| 1850 | { | 1886 | { |
| 1851 | struct msm_dp_ctrl_private *ctrl = container_of(msm_dp_ctrl, | 1887 | struct msm_dp_ctrl_private *ctrl = container_of(msm_dp_ctrl, |
| 1852 | struct msm_dp_ctrl_private, msm_dp_ctrl); | 1888 | struct msm_dp_ctrl_private, msm_dp_ctrl); |
| 1853 | u32 cfg; | 1889 | u32 cfg; |
| 1854 | 1890 | ||
| 1855 | if (!ctrl->panel->psr_cap.version) | 1891 | if (!panel->psr_cap.version) |
| 1856 | return; | 1892 | return; |
| 1857 | 1893 | ||
| 1858 | /* enable PSR1 function */ | 1894 | /* enable PSR1 function */ |
| @@ -1867,12 +1903,13 @@ void msm_dp_ctrl_config_psr(struct msm_dp_ctrl *msm_dp_ctrl) · 8 unmodified lines | |||
| 1867 | drm_dp_dpcd_write(ctrl->aux, DP_PSR_EN_CFG, &cfg, 1); | 1903 | drm_dp_dpcd_write(ctrl->aux, DP_PSR_EN_CFG, &cfg, 1); |
| 1868 | } | 1904 | } |
| 1869 | 1905 | ||
| 1870 | void msm_dp_ctrl_set_psr(struct msm_dp_ctrl *msm_dp_ctrl, bool enter) | 1906 | void msm_dp_ctrl_set_psr(struct msm_dp_ctrl *msm_dp_ctrl, |
| 1907 | struct msm_dp_panel *panel, bool enter) | ||
| 1871 | { | 1908 | { |
| 1872 | struct msm_dp_ctrl_private *ctrl = container_of(msm_dp_ctrl, | 1909 | struct msm_dp_ctrl_private *ctrl = container_of(msm_dp_ctrl, |
| 1873 | struct msm_dp_ctrl_private, msm_dp_ctrl); | 1910 | struct msm_dp_ctrl_private, msm_dp_ctrl); |
| 1874 | 1911 | ||
| 1875 | if (!ctrl->panel->psr_cap.version) | 1912 | if (!panel->psr_cap.version) |
| 1876 | return; | 1913 | return; |
| 1877 | 1914 | ||
| 1878 | /* | 1915 | /* |
| @@ -1942,7 +1979,8 @@ void msm_dp_ctrl_phy_exit(struct msm_dp_ctrl *msm_dp_ctrl) · 63 unmodified lines | |||
| 1942 | phy_exit(phy); | 1979 | phy_exit(phy); |
| 1943 | } | 1980 | } |
| 1944 | 1981 | ||
| 1945 | static int msm_dp_ctrl_reinitialize_mainlink(struct msm_dp_ctrl_private *ctrl) | 1982 | static int msm_dp_ctrl_reinitialize_mainlink(struct msm_dp_ctrl_private *ctrl, |
| 1983 | struct msm_dp_panel *panel) | ||
| 1946 | { | 1984 | { |
| 1947 | struct phy *phy = ctrl->phy; | 1985 | struct phy *phy = ctrl->phy; |
| 1948 | int ret = 0; | 1986 | int ret = 0; |
| @@ -1950,20 +1988,19 @@ static int msm_dp_ctrl_reinitialize_mainlink(struct msm_dp_ctrl_private *ctrl) · 1 unmodified line | |||
| 1950 | msm_dp_ctrl_mainlink_disable(ctrl); | 1988 | msm_dp_ctrl_mainlink_disable(ctrl); |
| 1951 | ctrl->phy_opts.dp.lanes = ctrl->link->link_params.num_lanes; | 1989 | ctrl->phy_opts.dp.lanes = ctrl->link->link_params.num_lanes; |
| 1952 | phy_configure(phy, &ctrl->phy_opts); | 1990 | phy_configure(phy, &ctrl->phy_opts); |
| 1991 | |||
| 1953 | /* | 1992 | /* |
| 1954 | * Disable and re-enable the mainlink clock since the | 1993 | * Disable and re-enable the mainlink clock since the |
| 1955 | * link clock might have been adjusted as part of the | 1994 | * link clock might have been adjusted as part of the |
| 1956 | * link maintenance. | 1995 | * link maintenance. |
| 1957 | */ | 1996 | */ |
| 1958 | dev_pm_opp_set_rate(ctrl->dev, 0); | ||
| 1959 | |||
| 1960 | msm_dp_ctrl_link_clk_disable(&ctrl->msm_dp_ctrl); | 1997 | msm_dp_ctrl_link_clk_disable(&ctrl->msm_dp_ctrl); |
| 1961 | 1998 | ||
| 1962 | phy_power_off(phy); | 1999 | phy_power_off(phy); |
| 1963 | /* hw recommended delay before re-enabling clocks */ | 2000 | /* hw recommended delay before re-enabling clocks */ |
| 1964 | msleep(20); | 2001 | msleep(20); |
| 1965 | 2002 | ||
| 1966 | ret = msm_dp_ctrl_enable_mainlink_clocks(ctrl); | 2003 | ret = msm_dp_ctrl_enable_mainlink_clocks(ctrl, panel); |
| 1967 | if (ret) { | 2004 | if (ret) { |
| 1968 | DRM_ERROR("Failed to enable mainlink clks. ret=%d\n", ret); | 2005 | DRM_ERROR("Failed to enable mainlink clks. ret=%d\n", ret); |
| 1969 | return ret; | 2006 | return ret; |
| @@ -1972,7 +2009,8 @@ static int msm_dp_ctrl_reinitialize_mainlink(struct msm_dp_ctrl_private *ctrl) · 2 unmodified lines | |||
| 1972 | return ret; | 2009 | return ret; |
| 1973 | } | 2010 | } |
| 1974 | 2011 | ||
| 1975 | static int msm_dp_ctrl_deinitialize_mainlink(struct msm_dp_ctrl_private *ctrl) | 2012 | static int msm_dp_ctrl_deinitialize_mainlink(struct msm_dp_ctrl_private *ctrl, |
| 2013 | struct msm_dp_panel *panel) | ||
| 1976 | { | 2014 | { |
| 1977 | struct phy *phy; | 2015 | struct phy *phy; |
| 1978 | 2016 | ||
| @@ -1980,9 +2018,8 @@ static int msm_dp_ctrl_deinitialize_mainlink(struct msm_dp_ctrl_private *ctrl) · 1 unmodified line | |||
| 1980 | 2018 | ||
| 1981 | msm_dp_ctrl_mainlink_disable(ctrl); | 2019 | msm_dp_ctrl_mainlink_disable(ctrl); |
| 1982 | 2020 | ||
| 1983 | msm_dp_ctrl_reset(&ctrl->msm_dp_ctrl); | 2021 | msm_dp_ctrl_reset(&ctrl->msm_dp_ctrl, panel); |
| 1984 | 2022 | ||
| 1985 | dev_pm_opp_set_rate(ctrl->dev, 0); | ||
| 1986 | msm_dp_ctrl_link_clk_disable(&ctrl->msm_dp_ctrl); | 2023 | msm_dp_ctrl_link_clk_disable(&ctrl->msm_dp_ctrl); |
| 1987 | 2024 | ||
| 1988 | phy_power_off(phy); | 2025 | phy_power_off(phy); |
| @@ -1994,7 +2031,8 @@ static int msm_dp_ctrl_deinitialize_mainlink(struct msm_dp_ctrl_private *ctrl) · 5 unmodified lines | |||
| 1994 | return 0; | 2031 | return 0; |
| 1995 | } | 2032 | } |
| 1996 | 2033 | ||
| 1997 | static int msm_dp_ctrl_link_maintenance(struct msm_dp_ctrl_private *ctrl) | 2034 | static int msm_dp_ctrl_link_maintenance(struct msm_dp_ctrl_private *ctrl, |
| 2035 | struct msm_dp_panel *panel) | ||
| 1998 | { | 2036 | { |
| 1999 | int ret = 0; | 2037 | int ret = 0; |
| 2000 | int training_step = DP_TRAINING_NONE; | 2038 | int training_step = DP_TRAINING_NONE; |
| @@ -2004,11 +2042,11 @@ static int msm_dp_ctrl_link_maintenance(struct msm_dp_ctrl_private *ctrl) · 3 unmodified lines | |||
| 2004 | ctrl->link->phy_params.p_level = 0; | 2042 | ctrl->link->phy_params.p_level = 0; |
| 2005 | ctrl->link->phy_params.v_level = 0; | 2043 | ctrl->link->phy_params.v_level = 0; |
| 2006 | 2044 | ||
| 2007 | ret = msm_dp_ctrl_setup_main_link(ctrl, &training_step); | 2045 | ret = msm_dp_ctrl_setup_main_link(ctrl, panel, &training_step); |
| 2008 | if (ret) | 2046 | if (ret) |
| 2009 | goto end; | 2047 | goto end; |
| 2010 | 2048 | ||
| 2011 | msm_dp_ctrl_clear_training_pattern(ctrl, DP_PHY_DPRX); | 2049 | msm_dp_ctrl_clear_training_pattern(ctrl, panel, DP_PHY_DPRX); |
| 2012 | 2050 | ||
| 2013 | msm_dp_write_link(ctrl, REG_DP_STATE_CTRL, DP_STATE_CTRL_SEND_VIDEO); | 2051 | msm_dp_write_link(ctrl, REG_DP_STATE_CTRL, DP_STATE_CTRL_SEND_VIDEO); |
| 2014 | 2052 | ||
| @@ -2152,7 +2190,43 @@ static bool msm_dp_ctrl_send_phy_test_pattern(struct msm_dp_ctrl_private *ctrl) · 137 unmodified lines | |||
| 2152 | return success; | 2190 | return success; |
| 2153 | } | 2191 | } |
| 2154 | 2192 | ||
| 2155 | static int msm_dp_ctrl_process_phy_test_request(struct msm_dp_ctrl_private *ctrl) | 2193 | static int msm_dp_ctrl_on_pixel_clk(struct msm_dp_ctrl_private *ctrl, unsigned long pixel_rate) |
| 2194 | { | ||
| 2195 | int ret; | ||
| 2196 | |||
| 2197 | ret = clk_set_rate(ctrl->pixel_clk, pixel_rate * 1000); | ||
| 2198 | if (ret) { | ||
| 2199 | DRM_ERROR("Failed to set pixel clock rate. ret=%d\n", ret); | ||
| 2200 | return ret; | ||
| 2201 | } | ||
| 2202 | |||
| 2203 | if (WARN_ON_ONCE(ctrl->stream_clks_on)) | ||
| 2204 | return 0; | ||
| 2205 | |||
| 2206 | ret = clk_prepare_enable(ctrl->pixel_clk); | ||
| 2207 | if (ret) { | ||
| 2208 | DRM_ERROR("Failed to start pixel clocks. ret=%d\n", ret); | ||
| 2209 | return ret; | ||
| 2210 | } | ||
| 2211 | ctrl->stream_clks_on = true; | ||
| 2212 | |||
| 2213 | return ret; | ||
| 2214 | } | ||
| 2215 | |||
| 2216 | void msm_dp_ctrl_off_pixel_clk(struct msm_dp_ctrl *msm_dp_ctrl) | ||
| 2217 | { | ||
| 2218 | struct msm_dp_ctrl_private *ctrl; | ||
| 2219 | |||
| 2220 | ctrl = container_of(msm_dp_ctrl, struct msm_dp_ctrl_private, msm_dp_ctrl); | ||
| 2221 | |||
| 2222 | if (ctrl->stream_clks_on) { | ||
| 2223 | clk_disable_unprepare(ctrl->pixel_clk); | ||
| 2224 | ctrl->stream_clks_on = false; | ||
| 2225 | } | ||
| 2226 | } | ||
| 2227 | |||
| 2228 | static int msm_dp_ctrl_process_phy_test_request(struct msm_dp_ctrl_private *ctrl, | ||
| 2229 | struct msm_dp_panel *panel) | ||
| 2156 | { | 2230 | { |
| 2157 | int ret; | 2231 | int ret; |
| 2158 | unsigned long pixel_rate; | 2232 | unsigned long pixel_rate; |
| @@ -2168,38 +2242,27 @@ static int msm_dp_ctrl_process_phy_test_request(struct msm_dp_ctrl_private *ctrl · 9 unmodified lines | |||
| 2168 | * running. Add the global reset just before disabling the | 2242 | * running. Add the global reset just before disabling the |
| 2169 | * link clocks and core clocks. | 2243 | * link clocks and core clocks. |
| 2170 | */ | 2244 | */ |
| 2171 | msm_dp_ctrl_off(&ctrl->msm_dp_ctrl); | 2245 | msm_dp_ctrl_off_pixel_clk(&ctrl->msm_dp_ctrl); |
| 2246 | msm_dp_ctrl_off_link(&ctrl->msm_dp_ctrl, panel); | ||
| 2172 | 2247 | ||
| 2173 | ret = msm_dp_ctrl_on_link(&ctrl->msm_dp_ctrl); | 2248 | ret = msm_dp_ctrl_on_link(&ctrl->msm_dp_ctrl, panel); |
| 2174 | if (ret) { | 2249 | if (ret) { |
| 2175 | DRM_ERROR("failed to enable DP link controller\n"); | 2250 | DRM_ERROR("failed to enable DP link controller\n"); |
| 2176 | return ret; | 2251 | return ret; |
| 2177 | } | 2252 | } |
| 2178 | 2253 | ||
| 2179 | pixel_rate = ctrl->panel->msm_dp_mode.drm_mode.clock; | 2254 | pixel_rate = panel->msm_dp_mode.drm_mode.clock; |
| 2180 | ret = clk_set_rate(ctrl->pixel_clk, pixel_rate * 1000); | 2255 | ret = msm_dp_ctrl_on_pixel_clk(ctrl, pixel_rate); |
| 2181 | if (ret) { | 2256 | if (ret) |
| 2182 | DRM_ERROR("Failed to set pixel clock rate. ret=%d\n", ret); | ||
| 2183 | return ret; | 2257 | return ret; |
| 2184 | } | ||
| 2185 | |||
| 2186 | if (ctrl->stream_clks_on) { | ||
| 2187 | drm_dbg_dp(ctrl->drm_dev, "pixel clks already enabled\n"); | ||
| 2188 | } else { | ||
| 2189 | ret = clk_prepare_enable(ctrl->pixel_clk); | ||
| 2190 | if (ret) { | ||
| 2191 | DRM_ERROR("Failed to start pixel clocks. ret=%d\n", ret); | ||
| 2192 | return ret; | ||
| 2193 | } | ||
| 2194 | ctrl->stream_clks_on = true; | ||
| 2195 | } | ||
| 2196 | 2258 | ||
| 2197 | msm_dp_ctrl_send_phy_test_pattern(ctrl); | 2259 | msm_dp_ctrl_send_phy_test_pattern(ctrl); |
| 2198 | 2260 | ||
| 2199 | return 0; | 2261 | return 0; |
| 2200 | } | 2262 | } |
| 2201 | 2263 | ||
| 2202 | void msm_dp_ctrl_handle_sink_request(struct msm_dp_ctrl *msm_dp_ctrl) | 2264 | void msm_dp_ctrl_handle_sink_request(struct msm_dp_ctrl *msm_dp_ctrl, |
| 2265 | struct msm_dp_panel *panel) | ||
| 2203 | { | 2266 | { |
| 2204 | struct msm_dp_ctrl_private *ctrl; | 2267 | struct msm_dp_ctrl_private *ctrl; |
| 2205 | u32 sink_request = 0x0; | 2268 | u32 sink_request = 0x0; |
| @@ -2214,14 +2277,14 @@ void msm_dp_ctrl_handle_sink_request(struct msm_dp_ctrl *msm_dp_ctrl) · 8 unmodified lines | |||
| 2214 | 2277 | ||
| 2215 | if (sink_request & DP_TEST_LINK_PHY_TEST_PATTERN) { | 2278 | if (sink_request & DP_TEST_LINK_PHY_TEST_PATTERN) { |
| 2216 | drm_dbg_dp(ctrl->drm_dev, "PHY_TEST_PATTERN request\n"); | 2279 | drm_dbg_dp(ctrl->drm_dev, "PHY_TEST_PATTERN request\n"); |
| 2217 | if (msm_dp_ctrl_process_phy_test_request(ctrl)) { | 2280 | if (msm_dp_ctrl_process_phy_test_request(ctrl, panel)) { |
| 2218 | DRM_ERROR("process phy_test_req failed\n"); | 2281 | DRM_ERROR("process phy_test_req failed\n"); |
| 2219 | return; | 2282 | return; |
| 2220 | } | 2283 | } |
| 2221 | } | 2284 | } |
| 2222 | 2285 | ||
| 2223 | if (sink_request & DP_LINK_STATUS_UPDATED) { | 2286 | if (sink_request & DP_LINK_STATUS_UPDATED) { |
| 2224 | if (msm_dp_ctrl_link_maintenance(ctrl)) { | 2287 | if (msm_dp_ctrl_link_maintenance(ctrl, panel)) { |
| 2225 | DRM_ERROR("LM failed: TEST_LINK_TRAINING\n"); | 2288 | DRM_ERROR("LM failed: TEST_LINK_TRAINING\n"); |
| 2226 | return; | 2289 | return; |
| 2227 | } | 2290 | } |
| @@ -2229,7 +2292,7 @@ void msm_dp_ctrl_handle_sink_request(struct msm_dp_ctrl *msm_dp_ctrl) · 1 unmodified line | |||
| 2229 | 2292 | ||
| 2230 | if (sink_request & DP_TEST_LINK_TRAINING) { | 2293 | if (sink_request & DP_TEST_LINK_TRAINING) { |
| 2231 | msm_dp_link_send_test_response(ctrl->link); | 2294 | msm_dp_link_send_test_response(ctrl->link); |
| 2232 | if (msm_dp_ctrl_link_maintenance(ctrl)) { | 2295 | if (msm_dp_ctrl_link_maintenance(ctrl, panel)) { |
| 2233 | DRM_ERROR("LM failed: TEST_LINK_TRAINING\n"); | 2296 | DRM_ERROR("LM failed: TEST_LINK_TRAINING\n"); |
| 2234 | return; | 2297 | return; |
| 2235 | } | 2298 | } |
| @@ -2265,7 +2328,8 @@ static bool msm_dp_ctrl_channel_eq_ok(struct msm_dp_ctrl_private *ctrl) · 29 unmodified lines | |||
| 2265 | return drm_dp_channel_eq_ok(link_status, num_lanes); | 2328 | return drm_dp_channel_eq_ok(link_status, num_lanes); |
| 2266 | } | 2329 | } |
| 2267 | 2330 | ||
| 2268 | int msm_dp_ctrl_on_link(struct msm_dp_ctrl *msm_dp_ctrl) | 2331 | int msm_dp_ctrl_on_link(struct msm_dp_ctrl *msm_dp_ctrl, |
| 2332 | struct msm_dp_panel *panel) | ||
| 2269 | { | 2333 | { |
| 2270 | int rc = 0; | 2334 | int rc = 0; |
| 2271 | struct msm_dp_ctrl_private *ctrl; | 2335 | struct msm_dp_ctrl_private *ctrl; |
| @@ -2281,8 +2345,8 @@ int msm_dp_ctrl_on_link(struct msm_dp_ctrl *msm_dp_ctrl) · 9 unmodified lines | |||
| 2281 | 2345 | ||
| 2282 | ctrl = container_of(msm_dp_ctrl, struct msm_dp_ctrl_private, msm_dp_ctrl); | 2346 | ctrl = container_of(msm_dp_ctrl, struct msm_dp_ctrl_private, msm_dp_ctrl); |
| 2283 | 2347 | ||
| 2284 | rate = ctrl->panel->link_info.rate; | 2348 | rate = panel->link_info.rate; |
| 2285 | pixel_rate = ctrl->panel->msm_dp_mode.drm_mode.clock; | 2349 | pixel_rate = panel->msm_dp_mode.drm_mode.clock; |
| 2286 | 2350 | ||
| 2287 | msm_dp_ctrl_core_clk_enable(&ctrl->msm_dp_ctrl); | 2351 | msm_dp_ctrl_core_clk_enable(&ctrl->msm_dp_ctrl); |
| 2288 | 2352 | ||
| @@ -2294,8 +2358,8 @@ int msm_dp_ctrl_on_link(struct msm_dp_ctrl *msm_dp_ctrl) · 5 unmodified lines | |||
| 2294 | } else { | 2358 | } else { |
| 2295 | ctrl->link->link_params.rate = rate; | 2359 | ctrl->link->link_params.rate = rate; |
| 2296 | ctrl->link->link_params.num_lanes = | 2360 | ctrl->link->link_params.num_lanes = |
| 2297 | ctrl->panel->link_info.num_lanes; | 2361 | panel->link_info.num_lanes; |
| 2298 | if (ctrl->panel->msm_dp_mode.out_fmt_is_yuv_420) | 2362 | if (panel->msm_dp_mode.out_fmt_is_yuv_420) |
| 2299 | pixel_rate >>= 1; | 2363 | pixel_rate >>= 1; |
| 2300 | } | 2364 | } |
| 2301 | 2365 | ||
| @@ -2303,13 +2367,13 @@ int msm_dp_ctrl_on_link(struct msm_dp_ctrl *msm_dp_ctrl) · 1 unmodified line | |||
| 2303 | ctrl->link->link_params.rate, ctrl->link->link_params.num_lanes, | 2367 | ctrl->link->link_params.rate, ctrl->link->link_params.num_lanes, |
| 2304 | pixel_rate); | 2368 | pixel_rate); |
| 2305 | 2369 | ||
| 2306 | rc = msm_dp_ctrl_enable_mainlink_clocks(ctrl); | 2370 | rc = msm_dp_ctrl_enable_mainlink_clocks(ctrl, panel); |
| 2307 | if (rc) | 2371 | if (rc) |
| 2308 | return rc; | 2372 | return rc; |
| 2309 | 2373 | ||
| 2310 | while (--link_train_max_retries) { | 2374 | while (--link_train_max_retries) { |
| 2311 | training_step = DP_TRAINING_NONE; | 2375 | training_step = DP_TRAINING_NONE; |
| 2312 | rc = msm_dp_ctrl_setup_main_link(ctrl, &training_step); | 2376 | rc = msm_dp_ctrl_setup_main_link(ctrl, panel, &training_step); |
| 2313 | if (rc == 0) { | 2377 | if (rc == 0) { |
| 2314 | /* training completed successfully */ | 2378 | /* training completed successfully */ |
| 2315 | break; | 2379 | break; |
| @@ -2328,7 +2392,7 @@ int msm_dp_ctrl_on_link(struct msm_dp_ctrl *msm_dp_ctrl) · 12 unmodified lines | |||
| 2328 | * some lanes are ready, | 2392 | * some lanes are ready, |
| 2329 | * reduce lane number | 2393 | * reduce lane number |
| 2330 | */ | 2394 | */ |
| 2331 | rc = msm_dp_ctrl_link_lane_down_shift(ctrl); | 2395 | rc = msm_dp_ctrl_link_lane_down_shift(ctrl, panel); |
| 2332 | if (rc < 0) { /* lane == 1 already */ | 2396 | if (rc < 0) { /* lane == 1 already */ |
| 2333 | /* end with failure */ | 2397 | /* end with failure */ |
| 2334 | break; | 2398 | break; |
| @@ -2349,7 +2413,7 @@ int msm_dp_ctrl_on_link(struct msm_dp_ctrl *msm_dp_ctrl) · 14 unmodified lines | |||
| 2349 | ctrl->link->link_params.num_lanes)) | 2413 | ctrl->link->link_params.num_lanes)) |
| 2350 | rc = msm_dp_ctrl_link_rate_down_shift(ctrl); | 2414 | rc = msm_dp_ctrl_link_rate_down_shift(ctrl); |
| 2351 | else | 2415 | else |
| 2352 | rc = msm_dp_ctrl_link_lane_down_shift(ctrl); | 2416 | rc = msm_dp_ctrl_link_lane_down_shift(ctrl, panel); |
| 2353 | 2417 | ||
| 2354 | if (rc < 0) { | 2418 | if (rc < 0) { |
| 2355 | /* end with failure */ | 2419 | /* end with failure */ |
| @@ -2357,10 +2421,10 @@ int msm_dp_ctrl_on_link(struct msm_dp_ctrl *msm_dp_ctrl) · 1 unmodified line | |||
| 2357 | } | 2421 | } |
| 2358 | 2422 | ||
| 2359 | /* stop link training before start re training */ | 2423 | /* stop link training before start re training */ |
| 2360 | msm_dp_ctrl_clear_training_pattern(ctrl, DP_PHY_DPRX); | 2424 | msm_dp_ctrl_clear_training_pattern(ctrl, panel, DP_PHY_DPRX); |
| 2361 | } | 2425 | } |
| 2362 | 2426 | ||
| 2363 | rc = msm_dp_ctrl_reinitialize_mainlink(ctrl); | 2427 | rc = msm_dp_ctrl_reinitialize_mainlink(ctrl, panel); |
| 2364 | if (rc) { | 2428 | if (rc) { |
| 2365 | DRM_ERROR("Failed to reinitialize mainlink. rc=%d\n", rc); | 2429 | DRM_ERROR("Failed to reinitialize mainlink. rc=%d\n", rc); |
| 2366 | break; | 2430 | break; |
| @@ -2381,20 +2445,21 @@ int msm_dp_ctrl_on_link(struct msm_dp_ctrl *msm_dp_ctrl) · 14 unmodified lines | |||
| 2381 | * link training failed | 2445 | * link training failed |
| 2382 | * end txing train pattern here | 2446 | * end txing train pattern here |
| 2383 | */ | 2447 | */ |
| 2384 | msm_dp_ctrl_clear_training_pattern(ctrl, DP_PHY_DPRX); | 2448 | msm_dp_ctrl_clear_training_pattern(ctrl, panel, DP_PHY_DPRX); |
| 2385 | 2449 | ||
| 2386 | msm_dp_ctrl_deinitialize_mainlink(ctrl); | 2450 | msm_dp_ctrl_deinitialize_mainlink(ctrl, panel); |
| 2387 | rc = -ECONNRESET; | 2451 | rc = -ECONNRESET; |
| 2388 | } | 2452 | } |
| 2389 | 2453 | ||
| 2390 | return rc; | 2454 | return rc; |
| 2391 | } | 2455 | } |
| 2392 | 2456 | ||
| 2393 | static int msm_dp_ctrl_link_retrain(struct msm_dp_ctrl_private *ctrl) | 2457 | static int msm_dp_ctrl_link_retrain(struct msm_dp_ctrl_private *ctrl, |
| 2458 | struct msm_dp_panel *panel) | ||
| 2394 | { | 2459 | { |
| 2395 | int training_step = DP_TRAINING_NONE; | 2460 | int training_step = DP_TRAINING_NONE; |
| 2396 | 2461 | ||
| 2397 | return msm_dp_ctrl_setup_main_link(ctrl, &training_step); | 2462 | return msm_dp_ctrl_setup_main_link(ctrl, panel, &training_step); |
| 2398 | } | 2463 | } |
| 2399 | 2464 | ||
| 2400 | static void msm_dp_ctrl_config_msa(struct msm_dp_ctrl_private *ctrl, | 2465 | static void msm_dp_ctrl_config_msa(struct msm_dp_ctrl_private *ctrl, |
| @@ -2465,62 +2530,67 @@ static void msm_dp_ctrl_config_msa(struct msm_dp_ctrl_private *ctrl, · 64 unmodified lines | |||
| 2465 | msm_dp_write_link(ctrl, REG_DP_SOFTWARE_NVID, nvid); | 2530 | msm_dp_write_link(ctrl, REG_DP_SOFTWARE_NVID, nvid); |
| 2466 | } | 2531 | } |
| 2467 | 2532 | ||
| 2468 | int msm_dp_ctrl_on_stream(struct msm_dp_ctrl *msm_dp_ctrl, bool force_link_train) | 2533 | int msm_dp_ctrl_prepare_stream_on(struct msm_dp_ctrl *msm_dp_ctrl, |
| 2534 | struct msm_dp_panel *panel, | ||
| 2535 | bool force_link_train) | ||
| 2469 | { | 2536 | { |
| 2470 | int ret = 0; | 2537 | int ret = 0; |
| 2471 | bool mainlink_ready = false; | ||
| 2472 | struct msm_dp_ctrl_private *ctrl; | 2538 | struct msm_dp_ctrl_private *ctrl; |
| 2473 | unsigned long pixel_rate; | ||
| 2474 | unsigned long pixel_rate_orig; | ||
| 2475 | 2539 | ||
| 2476 | if (!msm_dp_ctrl) | 2540 | if (!msm_dp_ctrl) |
| 2477 | return -EINVAL; | 2541 | return -EINVAL; |
| 2478 | 2542 | ||
| 2479 | ctrl = container_of(msm_dp_ctrl, struct msm_dp_ctrl_private, msm_dp_ctrl); | 2543 | ctrl = container_of(msm_dp_ctrl, struct msm_dp_ctrl_private, msm_dp_ctrl); |
| 2480 | 2544 | ||
| 2481 | pixel_rate = pixel_rate_orig = ctrl->panel->msm_dp_mode.drm_mode.clock; | 2545 | drm_dbg_dp(ctrl->drm_dev, "rate=%d, num_lanes=%d\n", |
| 2482 | 2546 | ctrl->link->link_params.rate, | |
| 2483 | if (msm_dp_ctrl->wide_bus_en || ctrl->panel->msm_dp_mode.out_fmt_is_yuv_420) | 2547 | ctrl->link->link_params.num_lanes); |
| 2484 | pixel_rate >>= 1; | ||
| 2485 | |||
| 2486 | drm_dbg_dp(ctrl->drm_dev, "rate=%d, num_lanes=%d, pixel_rate=%lu\n", | ||
| 2487 | ctrl->link->link_params.rate, | ||
| 2488 | ctrl->link->link_params.num_lanes, pixel_rate); | ||
| 2489 | 2548 | ||
| 2490 | drm_dbg_dp(ctrl->drm_dev, | 2549 | drm_dbg_dp(ctrl->drm_dev, |
| 2491 | "core_clk_on=%d link_clk_on=%d stream_clk_on=%d\n", | 2550 | "core_clk_on=%d link_clk_on=%d stream_clk_on=%d\n", |
| 2492 | ctrl->core_clks_on, ctrl->link_clks_on, ctrl->stream_clks_on); | 2551 | ctrl->core_clks_on, ctrl->link_clks_on, ctrl->stream_clks_on); |
| 2493 | 2552 | ||
| 2494 | if (!ctrl->link_clks_on) { /* link clk is off */ | 2553 | if (!ctrl->link_clks_on) { /* link clk is off */ |
| 2495 | ret = msm_dp_ctrl_enable_mainlink_clocks(ctrl); | 2554 | ret = msm_dp_ctrl_enable_mainlink_clocks(ctrl, panel); |
| 2496 | if (ret) { | 2555 | if (ret) { |
| 2497 | DRM_ERROR("Failed to start link clocks. ret=%d\n", ret); | 2556 | DRM_ERROR("Failed to start link clocks. ret=%d\n", ret); |
| 2498 | goto end; | 2557 | return ret; |
| 2499 | } | ||
| 2500 | } | ||
| 2501 | |||
| 2502 | ret = clk_set_rate(ctrl->pixel_clk, pixel_rate * 1000); | ||
| 2503 | if (ret) { | ||
| 2504 | DRM_ERROR("Failed to set pixel clock rate. ret=%d\n", ret); | ||
| 2505 | goto end; | ||
| 2506 | } | ||
| 2507 | |||
| 2508 | if (ctrl->stream_clks_on) { | ||
| 2509 | drm_dbg_dp(ctrl->drm_dev, "pixel clks already enabled\n"); | ||
| 2510 | } else { | ||
| 2511 | ret = clk_prepare_enable(ctrl->pixel_clk); | ||
| 2512 | if (ret) { | ||
| 2513 | DRM_ERROR("Failed to start pixel clocks. ret=%d\n", ret); | ||
| 2514 | goto end; | ||
| 2515 | } | 2558 | } |
| 2516 | ctrl->stream_clks_on = true; | ||
| 2517 | } | 2559 | } |
| 2518 | 2560 | ||
| 2519 | if (force_link_train || !msm_dp_ctrl_channel_eq_ok(ctrl)) | 2561 | if (force_link_train || !msm_dp_ctrl_channel_eq_ok(ctrl)) |
| 2520 | msm_dp_ctrl_link_retrain(ctrl); | 2562 | msm_dp_ctrl_link_retrain(ctrl, panel); |
| 2521 | 2563 | ||
| 2522 | /* stop txing train pattern to end link training */ | 2564 | /* stop txing train pattern to end link training */ |
| 2523 | msm_dp_ctrl_clear_training_pattern(ctrl, DP_PHY_DPRX); | 2565 | msm_dp_ctrl_clear_training_pattern(ctrl, panel, DP_PHY_DPRX); |
| 2566 | |||
| 2567 | return ret; | ||
| 2568 | } | ||
| 2569 | |||
| 2570 | int msm_dp_ctrl_on_stream(struct msm_dp_ctrl *msm_dp_ctrl, struct msm_dp_panel *panel) | ||
| 2571 | { | ||
| 2572 | int ret = 0; | ||
| 2573 | bool mainlink_ready = false; | ||
| 2574 | struct msm_dp_ctrl_private *ctrl; | ||
| 2575 | unsigned long pixel_rate; | ||
| 2576 | unsigned long pixel_rate_orig; | ||
| 2577 | |||
| 2578 | if (!msm_dp_ctrl) | ||
| 2579 | return -EINVAL; | ||
| 2580 | |||
| 2581 | ctrl = container_of(msm_dp_ctrl, struct msm_dp_ctrl_private, msm_dp_ctrl); | ||
| 2582 | |||
| 2583 | pixel_rate_orig = panel->msm_dp_mode.drm_mode.clock; | ||
| 2584 | pixel_rate = pixel_rate_orig; | ||
| 2585 | |||
| 2586 | if (msm_dp_ctrl->wide_bus_en || panel->msm_dp_mode.out_fmt_is_yuv_420) | ||
| 2587 | pixel_rate >>= 1; | ||
| 2588 | |||
| 2589 | drm_dbg_dp(ctrl->drm_dev, "pixel_rate=%lu\n", pixel_rate); | ||
| 2590 | |||
| 2591 | ret = msm_dp_ctrl_on_pixel_clk(ctrl, pixel_rate); | ||
| 2592 | if (ret) | ||
| 2593 | return ret; | ||
| 2524 | 2594 | ||
| 2525 | /* | 2595 | /* |
| 2526 | * Set up transfer unit values and set controller state to send | 2596 | * Set up transfer unit values and set controller state to send |
| @@ -2528,16 +2598,20 @@ int msm_dp_ctrl_on_stream(struct msm_dp_ctrl *msm_dp_ctrl, bool force_link_train · 1 unmodified line | |||
| 2528 | */ | 2598 | */ |
| 2529 | reinit_completion(&ctrl->video_comp); | 2599 | reinit_completion(&ctrl->video_comp); |
| 2530 | 2600 | ||
| 2531 | msm_dp_ctrl_configure_source_params(ctrl); | 2601 | msm_dp_ctrl_lane_mapping(ctrl); |
| 2602 | msm_dp_setup_peripheral_flush(ctrl); | ||
| 2603 | msm_dp_ctrl_config_ctrl_link(ctrl, panel); | ||
| 2604 | |||
| 2605 | msm_dp_ctrl_configure_source_params(ctrl, panel); | ||
| 2532 | 2606 | ||
| 2533 | msm_dp_ctrl_config_msa(ctrl, | 2607 | msm_dp_ctrl_config_msa(ctrl, |
| 2534 | ctrl->link->link_params.rate, | 2608 | ctrl->link->link_params.rate, |
| 2535 | pixel_rate_orig, | 2609 | pixel_rate_orig, |
| 2536 | ctrl->panel->msm_dp_mode.out_fmt_is_yuv_420); | 2610 | panel->msm_dp_mode.out_fmt_is_yuv_420); |
| 2537 | 2611 | ||
| 2538 | msm_dp_panel_clear_dsc_dto(ctrl->panel); | 2612 | msm_dp_panel_clear_dsc_dto(panel); |
| 2539 | 2613 | ||
| 2540 | msm_dp_ctrl_setup_tr_unit(ctrl); | 2614 | msm_dp_ctrl_setup_tr_unit(ctrl, panel); |
| 2541 | 2615 | ||
| 2542 | msm_dp_write_link(ctrl, REG_DP_STATE_CTRL, DP_STATE_CTRL_SEND_VIDEO); | 2616 | msm_dp_write_link(ctrl, REG_DP_STATE_CTRL, DP_STATE_CTRL_SEND_VIDEO); |
| 2543 | 2617 | ||
| @@ -2549,11 +2623,10 @@ int msm_dp_ctrl_on_stream(struct msm_dp_ctrl *msm_dp_ctrl, bool force_link_train · 5 unmodified lines | |||
| 2549 | drm_dbg_dp(ctrl->drm_dev, | 2623 | drm_dbg_dp(ctrl->drm_dev, |
| 2550 | "mainlink %s\n", mainlink_ready ? "READY" : "NOT READY"); | 2624 | "mainlink %s\n", mainlink_ready ? "READY" : "NOT READY"); |
| 2551 | 2625 | ||
| 2552 | end: | ||
| 2553 | return ret; | 2626 | return ret; |
| 2554 | } | 2627 | } |
| 2555 | 2628 | ||
| 2556 | void msm_dp_ctrl_off_link_stream(struct msm_dp_ctrl *msm_dp_ctrl) | 2629 | void msm_dp_ctrl_reinit_phy(struct msm_dp_ctrl *msm_dp_ctrl) |
| 2557 | { | 2630 | { |
| 2558 | struct msm_dp_ctrl_private *ctrl; | 2631 | struct msm_dp_ctrl_private *ctrl; |
| 2559 | struct phy *phy; | 2632 | struct phy *phy; |
| @@ -2561,29 +2634,13 @@ void msm_dp_ctrl_off_link_stream(struct msm_dp_ctrl *msm_dp_ctrl) · 1 unmodified line | |||
| 2561 | ctrl = container_of(msm_dp_ctrl, struct msm_dp_ctrl_private, msm_dp_ctrl); | 2634 | ctrl = container_of(msm_dp_ctrl, struct msm_dp_ctrl_private, msm_dp_ctrl); |
| 2562 | phy = ctrl->phy; | 2635 | phy = ctrl->phy; |
| 2563 | 2636 | ||
| 2564 | msm_dp_panel_disable_vsc_sdp(ctrl->panel); | ||
| 2565 | |||
| 2566 | /* set dongle to D3 (power off) mode */ | ||
| 2567 | msm_dp_link_psm_config(ctrl->link, &ctrl->panel->link_info, true); | ||
| 2568 | |||
| 2569 | msm_dp_ctrl_mainlink_disable(ctrl); | ||
| 2570 | |||
| 2571 | if (ctrl->stream_clks_on) { | ||
| 2572 | clk_disable_unprepare(ctrl->pixel_clk); | ||
| 2573 | ctrl->stream_clks_on = false; | ||
| 2574 | } | ||
| 2575 | |||
| 2576 | dev_pm_opp_set_rate(ctrl->dev, 0); | ||
| 2577 | msm_dp_ctrl_link_clk_disable(&ctrl->msm_dp_ctrl); | ||
| 2578 | |||
| 2579 | phy_power_off(phy); | ||
| 2580 | |||
| 2581 | /* aux channel down, reinit phy */ | 2637 | /* aux channel down, reinit phy */ |
| 2582 | phy_exit(phy); | 2638 | phy_exit(phy); |
| 2583 | phy_init(phy); | 2639 | phy_init(phy); |
| 2584 | } | 2640 | } |
| 2585 | 2641 | ||
| 2586 | void msm_dp_ctrl_off(struct msm_dp_ctrl *msm_dp_ctrl) | 2642 | void msm_dp_ctrl_off_link(struct msm_dp_ctrl *msm_dp_ctrl, |
| 2643 | struct msm_dp_panel *panel) | ||
| 2587 | { | 2644 | { |
| 2588 | struct msm_dp_ctrl_private *ctrl; | 2645 | struct msm_dp_ctrl_private *ctrl; |
| 2589 | struct phy *phy; | 2646 | struct phy *phy; |
| @@ -2591,24 +2648,19 @@ void msm_dp_ctrl_off(struct msm_dp_ctrl *msm_dp_ctrl) · 1 unmodified line | |||
| 2591 | ctrl = container_of(msm_dp_ctrl, struct msm_dp_ctrl_private, msm_dp_ctrl); | 2648 | ctrl = container_of(msm_dp_ctrl, struct msm_dp_ctrl_private, msm_dp_ctrl); |
| 2592 | phy = ctrl->phy; | 2649 | phy = ctrl->phy; |
| 2593 | 2650 | ||
| 2594 | msm_dp_panel_disable_vsc_sdp(ctrl->panel); | 2651 | msm_dp_panel_disable_vsc_sdp(panel); |
| 2595 | 2652 | ||
| 2596 | msm_dp_ctrl_mainlink_disable(ctrl); | 2653 | msm_dp_ctrl_mainlink_disable(ctrl); |
| 2597 | 2654 | ||
| 2598 | msm_dp_ctrl_reset(&ctrl->msm_dp_ctrl); | 2655 | msm_dp_ctrl_reset(&ctrl->msm_dp_ctrl, panel); |
| 2599 | |||
| 2600 | if (ctrl->stream_clks_on) { | ||
| 2601 | clk_disable_unprepare(ctrl->pixel_clk); | ||
| 2602 | ctrl->stream_clks_on = false; | ||
| 2603 | } | ||
| 2604 | 2656 | ||
| 2605 | dev_pm_opp_set_rate(ctrl->dev, 0); | ||
| 2606 | msm_dp_ctrl_link_clk_disable(&ctrl->msm_dp_ctrl); | 2657 | msm_dp_ctrl_link_clk_disable(&ctrl->msm_dp_ctrl); |
| 2607 | 2658 | ||
| 2608 | phy_power_off(phy); | 2659 | phy_power_off(phy); |
| 2609 | } | 2660 | } |
| 2610 | 2661 | ||
| 2611 | irqreturn_t msm_dp_ctrl_isr(struct msm_dp_ctrl *msm_dp_ctrl) | 2662 | irqreturn_t msm_dp_ctrl_isr(struct msm_dp_ctrl *msm_dp_ctrl, |
| 2663 | struct msm_dp_panel *panel) | ||
| 2612 | { | 2664 | { |
| 2613 | struct msm_dp_ctrl_private *ctrl; | 2665 | struct msm_dp_ctrl_private *ctrl; |
| 2614 | u32 isr; | 2666 | u32 isr; |
| @@ -2619,7 +2671,7 @@ irqreturn_t msm_dp_ctrl_isr(struct msm_dp_ctrl *msm_dp_ctrl) · 4 unmodified lines | |||
| 2619 | 2671 | ||
| 2620 | ctrl = container_of(msm_dp_ctrl, struct msm_dp_ctrl_private, msm_dp_ctrl); | 2672 | ctrl = container_of(msm_dp_ctrl, struct msm_dp_ctrl_private, msm_dp_ctrl); |
| 2621 | 2673 | ||
| 2622 | if (ctrl->panel->psr_cap.version) { | 2674 | if (panel->psr_cap.version) { |
| 2623 | isr = msm_dp_ctrl_get_psr_interrupt(ctrl); | 2675 | isr = msm_dp_ctrl_get_psr_interrupt(ctrl); |
| 2624 | 2676 | ||
| 2625 | if (isr) | 2677 | if (isr) |
| @@ -2708,7 +2760,7 @@ static int msm_dp_ctrl_clk_init(struct msm_dp_ctrl *msm_dp_ctrl) · 82 unmodified lines | |||
| 2708 | } | 2760 | } |
| 2709 | 2761 | ||
| 2710 | struct msm_dp_ctrl *msm_dp_ctrl_get(struct device *dev, struct msm_dp_link *link, | 2762 | struct msm_dp_ctrl *msm_dp_ctrl_get(struct device *dev, struct msm_dp_link *link, |
| 2711 | struct msm_dp_panel *panel, struct drm_dp_aux *aux, | 2763 | struct drm_dp_aux *aux, |
| 2712 | struct phy *phy, | 2764 | struct phy *phy, |
| 2713 | void __iomem *ahb_base, | 2765 | void __iomem *ahb_base, |
| 2714 | void __iomem *link_base) | 2766 | void __iomem *link_base) |
| @@ -2716,7 +2768,7 @@ struct msm_dp_ctrl *msm_dp_ctrl_get(struct device *dev, struct msm_dp_link *link · 1 unmodified line | |||
| 2716 | struct msm_dp_ctrl_private *ctrl; | 2768 | struct msm_dp_ctrl_private *ctrl; |
| 2717 | int ret; | 2769 | int ret; |
| 2718 | 2770 | ||
| 2719 | if (!dev || !panel || !aux || !link) { | 2771 | if (!dev || !aux || !link) { |
| 2720 | DRM_ERROR("invalid input\n"); | 2772 | DRM_ERROR("invalid input\n"); |
| 2721 | return ERR_PTR(-EINVAL); | 2773 | return ERR_PTR(-EINVAL); |
| 2722 | } | 2774 | } |
| @@ -2744,7 +2796,6 @@ struct msm_dp_ctrl *msm_dp_ctrl_get(struct device *dev, struct msm_dp_link *link · 21 unmodified lines | |||
| 2744 | init_completion(&ctrl->video_comp); | 2796 | init_completion(&ctrl->video_comp); |
| 2745 | 2797 | ||
| 2746 | /* in parameters */ | 2798 | /* in parameters */ |
| 2747 | ctrl->panel = panel; | ||
| 2748 | ctrl->aux = aux; | 2799 | ctrl->aux = aux; |
| 2749 | ctrl->link = link; | 2800 | ctrl->link = link; |
| 2750 | ctrl->dev = dev; | 2801 | ctrl->dev = dev; |
| @@ -16,28 +16,37 @@ struct msm_dp_ctrl { · 15 unmodified lines | |||
| 16 | 16 | ||
| 17 | struct phy; | 17 | struct phy; |
| 18 | 18 | ||
| 19 | int msm_dp_ctrl_on_link(struct msm_dp_ctrl *msm_dp_ctrl); | 19 | int msm_dp_ctrl_on_link(struct msm_dp_ctrl *msm_dp_ctrl, |
| 20 | int msm_dp_ctrl_on_stream(struct msm_dp_ctrl *msm_dp_ctrl, bool force_link_train); | 20 | struct msm_dp_panel *panel); |
| 21 | void msm_dp_ctrl_off_link_stream(struct msm_dp_ctrl *msm_dp_ctrl); | 21 | int msm_dp_ctrl_on_stream(struct msm_dp_ctrl *msm_dp_ctrl, struct msm_dp_panel *panel); |
| 22 | void msm_dp_ctrl_off(struct msm_dp_ctrl *msm_dp_ctrl); | 22 | int msm_dp_ctrl_prepare_stream_on(struct msm_dp_ctrl *msm_dp_ctrl, |
| 23 | struct msm_dp_panel *panel, | ||
| 24 | bool force_link_train); | ||
| 25 | void msm_dp_ctrl_off_link(struct msm_dp_ctrl *msm_dp_ctrl, | ||
| 26 | struct msm_dp_panel *panel); | ||
| 27 | void msm_dp_ctrl_off_pixel_clk(struct msm_dp_ctrl *msm_dp_ctrl); | ||
| 23 | void msm_dp_ctrl_push_idle(struct msm_dp_ctrl *msm_dp_ctrl); | 28 | void msm_dp_ctrl_push_idle(struct msm_dp_ctrl *msm_dp_ctrl); |
| 24 | irqreturn_t msm_dp_ctrl_isr(struct msm_dp_ctrl *msm_dp_ctrl); | 29 | irqreturn_t msm_dp_ctrl_isr(struct msm_dp_ctrl *msm_dp_ctrl, |
| 25 | void msm_dp_ctrl_handle_sink_request(struct msm_dp_ctrl *msm_dp_ctrl); | 30 | struct msm_dp_panel *panel); |
| 31 | void msm_dp_ctrl_handle_sink_request(struct msm_dp_ctrl *msm_dp_ctrl, | ||
| 32 | struct msm_dp_panel *panel); | ||
| 26 | struct msm_dp_ctrl *msm_dp_ctrl_get(struct device *dev, | 33 | struct msm_dp_ctrl *msm_dp_ctrl_get(struct device *dev, |
| 27 | struct msm_dp_link *link, | 34 | struct msm_dp_link *link, |
| 28 | struct msm_dp_panel *panel, | ||
| 29 | struct drm_dp_aux *aux, | 35 | struct drm_dp_aux *aux, |
| 30 | struct phy *phy, | 36 | struct phy *phy, |
| 31 | void __iomem *ahb_base, | 37 | void __iomem *ahb_base, |
| 32 | void __iomem *link_base); | 38 | void __iomem *link_base); |
| 33 | 39 | ||
| 34 | void msm_dp_ctrl_reset(struct msm_dp_ctrl *msm_dp_ctrl); | 40 | void msm_dp_ctrl_reset(struct msm_dp_ctrl *msm_dp_ctrl, |
| 41 | struct msm_dp_panel *panel); | ||
| 35 | void msm_dp_ctrl_phy_init(struct msm_dp_ctrl *msm_dp_ctrl); | 42 | void msm_dp_ctrl_phy_init(struct msm_dp_ctrl *msm_dp_ctrl); |
| 36 | void msm_dp_ctrl_phy_exit(struct msm_dp_ctrl *msm_dp_ctrl); | 43 | void msm_dp_ctrl_phy_exit(struct msm_dp_ctrl *msm_dp_ctrl); |
| 37 | void msm_dp_ctrl_irq_phy_exit(struct msm_dp_ctrl *msm_dp_ctrl); | 44 | void msm_dp_ctrl_irq_phy_exit(struct msm_dp_ctrl *msm_dp_ctrl); |
| 38 | 45 | ||
| 39 | void msm_dp_ctrl_set_psr(struct msm_dp_ctrl *msm_dp_ctrl, bool enable); | 46 | void msm_dp_ctrl_set_psr(struct msm_dp_ctrl *msm_dp_ctrl, |
| 40 | void msm_dp_ctrl_config_psr(struct msm_dp_ctrl *msm_dp_ctrl); | 47 | struct msm_dp_panel *panel, bool enable); |
| 48 | void msm_dp_ctrl_config_psr(struct msm_dp_ctrl *msm_dp_ctrl, | ||
| 49 | struct msm_dp_panel *panel); | ||
| 41 | 50 | ||
| 42 | int msm_dp_ctrl_core_clk_enable(struct msm_dp_ctrl *msm_dp_ctrl); | 51 | int msm_dp_ctrl_core_clk_enable(struct msm_dp_ctrl *msm_dp_ctrl); |
| 43 | void msm_dp_ctrl_core_clk_disable(struct msm_dp_ctrl *msm_dp_ctrl); | 52 | void msm_dp_ctrl_core_clk_disable(struct msm_dp_ctrl *msm_dp_ctrl); |
| @@ -45,4 +54,5 @@ void msm_dp_ctrl_core_clk_disable(struct msm_dp_ctrl *msm_dp_ctrl); · 1 unmodified line | |||
| 45 | void msm_dp_ctrl_enable_irq(struct msm_dp_ctrl *msm_dp_ctrl); | 54 | void msm_dp_ctrl_enable_irq(struct msm_dp_ctrl *msm_dp_ctrl); |
| 46 | void msm_dp_ctrl_disable_irq(struct msm_dp_ctrl *msm_dp_ctrl); | 55 | void msm_dp_ctrl_disable_irq(struct msm_dp_ctrl *msm_dp_ctrl); |
| 47 | 56 | ||
| 57 | void msm_dp_ctrl_reinit_phy(struct msm_dp_ctrl *msm_dp_ctrl); | ||
| 48 | #endif /* _DP_CTRL_H_ */ | 58 | #endif /* _DP_CTRL_H_ */ |
| @@ -63,7 +63,6 @@ struct msm_dp_display_private { · 62 unmodified lines | |||
| 63 | struct msm_dp_panel *panel; | 63 | struct msm_dp_panel *panel; |
| 64 | struct msm_dp_ctrl *ctrl; | 64 | struct msm_dp_ctrl *ctrl; |
| 65 | 65 | ||
| 66 | struct msm_dp_display_mode msm_dp_mode; | ||
| 67 | struct msm_dp msm_dp_display; | 66 | struct msm_dp msm_dp_display; |
| 68 | 67 | ||
| 69 | /* wait for audio signaling */ | 68 | /* wait for audio signaling */ |
| @@ -269,6 +268,7 @@ static int msm_dp_display_process_hpd_high(struct msm_dp_display_private *dp) · 199 unmodified lines | |||
| 269 | const struct drm_display_info *info = &connector->display_info; | 268 | const struct drm_display_info *info = &connector->display_info; |
| 270 | int rc = 0; | 269 | int rc = 0; |
| 271 | u8 dpcd[DP_RECEIVER_CAP_SIZE]; | 270 | u8 dpcd[DP_RECEIVER_CAP_SIZE]; |
| 271 | const struct drm_edid *drm_edid = NULL; | ||
| 272 | 272 | ||
| 273 | rc = drm_dp_read_dpcd_caps(dp->aux, dpcd); | 273 | rc = drm_dp_read_dpcd_caps(dp->aux, dpcd); |
| 274 | if (rc) | 274 | if (rc) |
| @@ -276,10 +276,20 @@ static int msm_dp_display_process_hpd_high(struct msm_dp_display_private *dp) · 1 unmodified line | |||
| 276 | 276 | ||
| 277 | dp->link->lttpr_count = msm_dp_display_lttpr_init(dp, dpcd); | 277 | dp->link->lttpr_count = msm_dp_display_lttpr_init(dp, dpcd); |
| 278 | 278 | ||
| 279 | rc = msm_dp_panel_read_sink_caps(dp->panel, connector); | 279 | rc = msm_dp_panel_read_link_caps(dp->panel, connector); |
| 280 | if (rc) | 280 | if (rc) |
| 281 | goto end; | 281 | goto end; |
| 282 | 282 | ||
| 283 | drm_edid = drm_edid_read_ddc(connector, &dp->aux->ddc); | ||
| 284 | drm_edid_connector_update(connector, drm_edid); | ||
| 285 | |||
| 286 | if (!drm_edid) { | ||
| 287 | DRM_ERROR("panel edid read failed\n"); | ||
| 288 | /* check edid read fail is due to unplug */ | ||
| 289 | if (!msm_dp_aux_is_link_connected(dp->aux)) | ||
| 290 | return -ETIMEDOUT; | ||
| 291 | } | ||
| 292 | |||
| 283 | msm_dp_link_process_request(dp->link); | 293 | msm_dp_link_process_request(dp->link); |
| 284 | 294 | ||
| 285 | if (!dp->msm_dp_display.is_edp) | 295 | if (!dp->msm_dp_display.is_edp) |
| @@ -291,7 +301,7 @@ static int msm_dp_display_process_hpd_high(struct msm_dp_display_private *dp) · 5 unmodified lines | |||
| 291 | dp->msm_dp_display.psr_supported = dp->panel->psr_cap.version && psr_enabled; | 301 | dp->msm_dp_display.psr_supported = dp->panel->psr_cap.version && psr_enabled; |
| 292 | 302 | ||
| 293 | dp->audio_supported = info->has_audio; | 303 | dp->audio_supported = info->has_audio; |
| 294 | msm_dp_panel_handle_sink_request(dp->panel); | 304 | msm_dp_panel_handle_sink_request(dp->panel, drm_edid); |
| 295 | 305 | ||
| 296 | /* | 306 | /* |
| 297 | * set sink to normal operation mode -- D0 | 307 | * set sink to normal operation mode -- D0 |
| @@ -302,6 +312,7 @@ static int msm_dp_display_process_hpd_high(struct msm_dp_display_private *dp) · 4 unmodified lines | |||
| 302 | msm_dp_link_reset_phy_params_vx_px(dp->link); | 312 | msm_dp_link_reset_phy_params_vx_px(dp->link); |
| 303 | 313 | ||
| 304 | end: | 314 | end: |
| 315 | drm_edid_free(drm_edid); | ||
| 305 | return rc; | 316 | return rc; |
| 306 | } | 317 | } |
| 307 | 318 | ||
| @@ -348,7 +359,7 @@ static void msm_dp_display_host_init(struct msm_dp_display_private *dp) · 40 unmodified lines | |||
| 348 | dp->phy_initialized); | 359 | dp->phy_initialized); |
| 349 | 360 | ||
| 350 | msm_dp_ctrl_core_clk_enable(dp->ctrl); | 361 | msm_dp_ctrl_core_clk_enable(dp->ctrl); |
| 351 | msm_dp_ctrl_reset(dp->ctrl); | 362 | msm_dp_ctrl_reset(dp->ctrl, dp->panel); |
| 352 | msm_dp_ctrl_enable_irq(dp->ctrl); | 363 | msm_dp_ctrl_enable_irq(dp->ctrl); |
| 353 | msm_dp_aux_init(dp->aux); | 364 | msm_dp_aux_init(dp->aux); |
| 354 | dp->core_initialized = true; | 365 | dp->core_initialized = true; |
| @@ -360,7 +371,7 @@ static void msm_dp_display_host_deinit(struct msm_dp_display_private *dp) · 5 unmodified lines | |||
| 360 | dp->msm_dp_display.connector_type, dp->core_initialized, | 371 | dp->msm_dp_display.connector_type, dp->core_initialized, |
| 361 | dp->phy_initialized); | 372 | dp->phy_initialized); |
| 362 | 373 | ||
| 363 | msm_dp_ctrl_reset(dp->ctrl); | 374 | msm_dp_ctrl_reset(dp->ctrl, dp->panel); |
| 364 | msm_dp_ctrl_disable_irq(dp->ctrl); | 375 | msm_dp_ctrl_disable_irq(dp->ctrl); |
| 365 | msm_dp_aux_deinit(dp->aux); | 376 | msm_dp_aux_deinit(dp->aux); |
| 366 | msm_dp_ctrl_core_clk_disable(dp->ctrl); | 377 | msm_dp_ctrl_core_clk_disable(dp->ctrl); |
| @@ -381,7 +392,7 @@ static int msm_dp_display_handle_irq_hpd(struct msm_dp_display_private *dp) · 14 unmodified lines | |||
| 381 | 392 | ||
| 382 | drm_dbg_dp(dp->drm_dev, "%d\n", sink_request); | 393 | drm_dbg_dp(dp->drm_dev, "%d\n", sink_request); |
| 383 | 394 | ||
| 384 | msm_dp_ctrl_handle_sink_request(dp->ctrl); | 395 | msm_dp_ctrl_handle_sink_request(dp->ctrl, dp->panel); |
| 385 | 396 | ||
| 386 | if (sink_request & DP_TEST_LINK_VIDEO_PATTERN) | 397 | if (sink_request & DP_TEST_LINK_VIDEO_PATTERN) |
| 387 | msm_dp_display_handle_video_request(dp); | 398 | msm_dp_display_handle_video_request(dp); |
| @@ -453,7 +464,7 @@ static int msm_dp_hpd_unplug_handle(struct msm_dp_display_private *dp) · 65 unmodified lines | |||
| 453 | 464 | ||
| 454 | /* Don't forget modes for eDP */ | 465 | /* Don't forget modes for eDP */ |
| 455 | if (!dp->msm_dp_display.is_edp) | 466 | if (!dp->msm_dp_display.is_edp) |
| 456 | msm_dp_panel_unplugged(dp->panel, dp->msm_dp_display.connector); | 467 | drm_edid_connector_update(dp->msm_dp_display.connector, NULL); |
| 457 | 468 | ||
| 458 | /* triggered by irq_hdp with sink_count = 0 */ | 469 | /* triggered by irq_hdp with sink_count = 0 */ |
| 459 | if (dp->link->sink_count == 0) | 470 | if (dp->link->sink_count == 0) |
| @@ -515,7 +526,6 @@ static int msm_dp_irq_hpd_handle(struct msm_dp_display_private *dp) · 55 unmodified lines | |||
| 515 | static void msm_dp_display_deinit_sub_modules(struct msm_dp_display_private *dp) | 526 | static void msm_dp_display_deinit_sub_modules(struct msm_dp_display_private *dp) |
| 516 | { | 527 | { |
| 517 | msm_dp_audio_put(dp->audio); | 528 | msm_dp_audio_put(dp->audio); |
| 518 | msm_dp_panel_put(dp->panel); | ||
| 519 | msm_dp_aux_put(dp->aux); | 529 | msm_dp_aux_put(dp->aux); |
| 520 | } | 530 | } |
| 521 | 531 | ||
| @@ -560,13 +570,13 @@ static int msm_dp_init_sub_modules(struct msm_dp_display_private *dp) · 38 unmodified lines | |||
| 560 | goto error_link; | 570 | goto error_link; |
| 561 | } | 571 | } |
| 562 | 572 | ||
| 563 | dp->ctrl = msm_dp_ctrl_get(dev, dp->link, dp->panel, dp->aux, | 573 | dp->ctrl = msm_dp_ctrl_get(dev, dp->link, dp->aux, |
| 564 | phy, dp->ahb_base, dp->link_base); | 574 | phy, dp->ahb_base, dp->link_base); |
| 565 | if (IS_ERR(dp->ctrl)) { | 575 | if (IS_ERR(dp->ctrl)) { |
| 566 | rc = PTR_ERR(dp->ctrl); | 576 | rc = PTR_ERR(dp->ctrl); |
| 567 | DRM_ERROR("failed to initialize ctrl, rc = %d\n", rc); | 577 | DRM_ERROR("failed to initialize ctrl, rc = %d\n", rc); |
| 568 | dp->ctrl = NULL; | 578 | dp->ctrl = NULL; |
| 569 | goto error_ctrl; | 579 | goto error_link; |
| 570 | } | 580 | } |
| 571 | 581 | ||
| 572 | dp->audio = msm_dp_audio_get(dp->msm_dp_display.pdev, dp->link_base); | 582 | dp->audio = msm_dp_audio_get(dp->msm_dp_display.pdev, dp->link_base); |
| @@ -574,13 +584,11 @@ static int msm_dp_init_sub_modules(struct msm_dp_display_private *dp) · 1 unmodified line | |||
| 574 | rc = PTR_ERR(dp->audio); | 584 | rc = PTR_ERR(dp->audio); |
| 575 | pr_err("failed to initialize audio, rc = %d\n", rc); | 585 | pr_err("failed to initialize audio, rc = %d\n", rc); |
| 576 | dp->audio = NULL; | 586 | dp->audio = NULL; |
| 577 | goto error_ctrl; | 587 | goto error_link; |
| 578 | } | 588 | } |
| 579 | 589 | ||
| 580 | return rc; | 590 | return rc; |
| 581 | 591 | ||
| 582 | error_ctrl: | ||
| 583 | msm_dp_panel_put(dp->panel); | ||
| 584 | error_link: | 592 | error_link: |
| 585 | msm_dp_aux_put(dp->aux); | 593 | msm_dp_aux_put(dp->aux); |
| 586 | error: | 594 | error: |
| @@ -588,20 +596,64 @@ error: · 1 unmodified line | |||
| 588 | } | 596 | } |
| 589 | 597 | ||
| 590 | static int msm_dp_display_set_mode(struct msm_dp *msm_dp_display, | 598 | static int msm_dp_display_set_mode(struct msm_dp *msm_dp_display, |
| 591 | struct msm_dp_display_mode *mode) | 599 | const struct drm_display_mode *adjusted_mode, |
| 600 | struct msm_dp_panel *msm_dp_panel) | ||
| 592 | { | 601 | { |
| 593 | struct msm_dp_display_private *dp; | 602 | struct msm_dp_display_private *dp; |
| 603 | u32 bpp; | ||
| 594 | 604 | ||
| 595 | dp = container_of(msm_dp_display, struct msm_dp_display_private, msm_dp_display); | 605 | dp = container_of(msm_dp_display, struct msm_dp_display_private, msm_dp_display); |
| 596 | 606 | ||
| 597 | drm_mode_copy(&dp->panel->msm_dp_mode.drm_mode, &mode->drm_mode); | 607 | if (msm_dp_display_check_video_test(msm_dp_display)) |
| 598 | dp->panel->msm_dp_mode.bpp = mode->bpp; | 608 | bpp = msm_dp_display_get_test_bpp(msm_dp_display); |
| 599 | dp->panel->msm_dp_mode.out_fmt_is_yuv_420 = mode->out_fmt_is_yuv_420; | 609 | else |
| 600 | msm_dp_panel_init_panel_info(dp->panel); | 610 | bpp = msm_dp_panel->connector->display_info.bpc * 3; |
| 611 | |||
| 612 | msm_dp_panel_init_panel_info(msm_dp_panel, adjusted_mode, bpp ? bpp : 24); | ||
| 613 | |||
| 614 | /* populate wide_bus_support to different layers */ | ||
| 615 | dp->ctrl->wide_bus_en = | ||
| 616 | msm_dp_panel->msm_dp_mode.out_fmt_is_yuv_420 ? false : dp->wide_bus_supported; | ||
| 601 | return 0; | 617 | return 0; |
| 602 | } | 618 | } |
| 603 | 619 | ||
| 604 | static int msm_dp_display_enable(struct msm_dp_display_private *dp, bool force_link_train) | 620 | static int msm_dp_display_prepare_link(struct msm_dp_display_private *dp) |
| 621 | { | ||
| 622 | struct msm_dp *msm_dp_display = &dp->msm_dp_display; | ||
| 623 | int rc = 0; | ||
| 624 | bool force_link_train = false; | ||
| 625 | |||
| 626 | drm_dbg_dp(dp->drm_dev, "sink_count=%d\n", dp->link->sink_count); | ||
| 627 | |||
| 628 | if (msm_dp_display->is_edp) | ||
| 629 | msm_dp_hpd_plug_handle(dp); | ||
| 630 | |||
| 631 | rc = pm_runtime_resume_and_get(&msm_dp_display->pdev->dev); | ||
| 632 | if (rc) { | ||
| 633 | DRM_ERROR("failed to pm_runtime_resume\n"); | ||
| 634 | return rc; | ||
| 635 | } | ||
| 636 | |||
| 637 | if (dp->link->sink_count == 0) | ||
| 638 | return -ENOTCONN; | ||
| 639 | |||
| 640 | if (!msm_dp_display->power_on) { | ||
| 641 | msm_dp_display_host_phy_init(dp); | ||
| 642 | force_link_train = true; | ||
| 643 | } | ||
| 644 | |||
| 645 | rc = msm_dp_ctrl_on_link(dp->ctrl, dp->panel); | ||
| 646 | if (rc) { | ||
| 647 | DRM_ERROR("Failed link training (rc=%d)\n", rc); | ||
| 648 | // TODO: schedule drm_connector_set_link_status_property() | ||
| 649 | return rc; | ||
| 650 | } | ||
| 651 | |||
| 652 | return msm_dp_ctrl_prepare_stream_on(dp->ctrl, dp->panel, force_link_train); | ||
| 653 | } | ||
| 654 | |||
| 655 | static int msm_dp_display_enable(struct msm_dp_display_private *dp, | ||
| 656 | struct msm_dp_panel *msm_dp_panel) | ||
| 605 | { | 657 | { |
| 606 | int rc = 0; | 658 | int rc = 0; |
| 607 | struct msm_dp *msm_dp_display = &dp->msm_dp_display; | 659 | struct msm_dp *msm_dp_display = &dp->msm_dp_display; |
| @@ -612,7 +664,7 @@ static int msm_dp_display_enable(struct msm_dp_display_private *dp, bool force_l · 4 unmodified lines | |||
| 612 | return 0; | 664 | return 0; |
| 613 | } | 665 | } |
| 614 | 666 | ||
| 615 | rc = msm_dp_ctrl_on_stream(dp->ctrl, force_link_train); | 667 | rc = msm_dp_ctrl_on_stream(dp->ctrl, msm_dp_panel); |
| 616 | if (!rc) | 668 | if (!rc) |
| 617 | msm_dp_display->power_on = true; | 669 | msm_dp_display->power_on = true; |
| 618 | 670 | ||
| @@ -637,18 +689,15 @@ static int msm_dp_display_post_enable(struct msm_dp *msm_dp_display) · 18 unmodified lines | |||
| 637 | msm_dp_display_handle_plugged_change(msm_dp_display, true); | 689 | msm_dp_display_handle_plugged_change(msm_dp_display, true); |
| 638 | 690 | ||
| 639 | if (msm_dp_display->psr_supported) | 691 | if (msm_dp_display->psr_supported) |
| 640 | msm_dp_ctrl_config_psr(dp->ctrl); | 692 | msm_dp_ctrl_config_psr(dp->ctrl, dp->panel); |
| 641 | 693 | ||
| 642 | return 0; | 694 | return 0; |
| 643 | } | 695 | } |
| 644 | 696 | ||
| 645 | static int msm_dp_display_disable(struct msm_dp_display_private *dp) | 697 | static void msm_dp_display_audio_notify_disable(struct msm_dp_display_private *dp) |
| 646 | { | 698 | { |
| 647 | struct msm_dp *msm_dp_display = &dp->msm_dp_display; | 699 | struct msm_dp *msm_dp_display = &dp->msm_dp_display; |
| 648 | 700 | ||
| 649 | if (!msm_dp_display->power_on) | ||
| 650 | return 0; | ||
| 651 | |||
| 652 | /* wait only if audio was enabled */ | 701 | /* wait only if audio was enabled */ |
| 653 | if (msm_dp_display->audio_enabled) { | 702 | if (msm_dp_display->audio_enabled) { |
| 654 | /* signal the disconnect event */ | 703 | /* signal the disconnect event */ |
| @@ -659,21 +708,31 @@ static int msm_dp_display_disable(struct msm_dp_display_private *dp) · 4 unmodified lines | |||
| 659 | } | 708 | } |
| 660 | 709 | ||
| 661 | msm_dp_display->audio_enabled = false; | 710 | msm_dp_display->audio_enabled = false; |
| 711 | } | ||
| 662 | 712 | ||
| 663 | if (dp->link->sink_count == 0) { | 713 | static int msm_dp_display_disable(struct msm_dp_display_private *dp, |
| 664 | /* | 714 | struct msm_dp_panel *msm_dp_panel) |
| 665 | * irq_hpd with sink_count = 0 | 715 | { |
| 666 | * hdmi unplugged out of dongle | 716 | struct msm_dp *msm_dp_display = &dp->msm_dp_display; |
| 667 | */ | 717 | |
| 668 | msm_dp_ctrl_off_link_stream(dp->ctrl); | 718 | if (!msm_dp_display->power_on) |
| 669 | } else { | 719 | return 0; |
| 670 | /* | 720 | |
| 671 | * unplugged interrupt | 721 | msm_dp_panel_disable_vsc_sdp(msm_dp_panel); |
| 672 | * dongle unplugged out of DUT | 722 | |
| 673 | */ | 723 | msm_dp_ctrl_off_pixel_clk(dp->ctrl); |
| 674 | msm_dp_ctrl_off(dp->ctrl); | 724 | |
| 725 | /* dongle is still connected but sinks are disconnected */ | ||
| 726 | if (dp->link->sink_count == 0) | ||
| 727 | msm_dp_link_psm_config(dp->link, &msm_dp_panel->link_info, true); | ||
| 728 | |||
| 729 | msm_dp_ctrl_off_link(dp->ctrl, msm_dp_panel); | ||
| 730 | |||
| 731 | if (dp->link->sink_count == 0) | ||
| 732 | /* re-init the PHY so that we can listen to Dongle disconnect */ | ||
| 733 | msm_dp_ctrl_reinit_phy(dp->ctrl); | ||
| 734 | else | ||
| 675 | msm_dp_display_host_phy_exit(dp); | 735 | msm_dp_display_host_phy_exit(dp); |
| 676 | } | ||
| 677 | 736 | ||
| 678 | msm_dp_display->power_on = false; | 737 | msm_dp_display->power_on = false; |
| 679 | 738 | ||
| @@ -682,24 +741,22 @@ static int msm_dp_display_disable(struct msm_dp_display_private *dp) · 2 unmodified lines | |||
| 682 | } | 741 | } |
| 683 | 742 | ||
| 684 | /** | 743 | /** |
| 685 | * msm_dp_bridge_mode_valid - callback to determine if specified mode is valid | 744 | * msm_dp_display_mode_valid - callback to determine if specified mode is valid |
| 686 | * @bridge: Pointer to drm bridge structure | 745 | * @dp: Pointer to dp display structure |
| 687 | * @info: display info | 746 | * @info: display info |
| 688 | * @mode: Pointer to drm mode structure | 747 | * @mode: Pointer to drm mode structure |
| 689 | * Returns: Validity status for specified mode | 748 | * Returns: Validity status for specified mode |
| 690 | */ | 749 | */ |
| 691 | enum drm_mode_status msm_dp_bridge_mode_valid(struct drm_bridge *bridge, | 750 | enum drm_mode_status msm_dp_display_mode_valid(struct msm_dp *dp, |
| 692 | const struct drm_display_info *info, | 751 | const struct drm_display_info *info, |
| 693 | const struct drm_display_mode *mode) | 752 | const struct drm_display_mode *mode) |
| 694 | { | 753 | { |
| 695 | const u32 num_components = 3, default_bpp = 24; | 754 | const u32 num_components = 3, default_bpp = 24; |
| 696 | struct msm_dp_display_private *msm_dp_display; | 755 | struct msm_dp_display_private *msm_dp_display; |
| 697 | struct msm_dp_link_info *link_info; | 756 | struct msm_dp_link_info *link_info; |
| 698 | u32 mode_rate_khz = 0, supported_rate_khz = 0, mode_bpp = 0; | 757 | u32 mode_rate_khz = 0, supported_rate_khz = 0, mode_bpp = 0; |
| 699 | struct msm_dp *dp; | ||
| 700 | int mode_pclk_khz = mode->clock; | 758 | int mode_pclk_khz = mode->clock; |
| 701 | 759 | bool is_yuv_420; | |
| 702 | dp = to_dp_bridge(bridge)->msm_dp_display; | ||
| 703 | 760 | ||
| 704 | if (!dp || !mode_pclk_khz || !dp->connector) { | 761 | if (!dp || !mode_pclk_khz || !dp->connector) { |
| 705 | DRM_ERROR("invalid params\n"); | 762 | DRM_ERROR("invalid params\n"); |
| @@ -709,9 +766,16 @@ enum drm_mode_status msm_dp_bridge_mode_valid(struct drm_bridge *bridge, · 3 unmodified lines | |||
| 709 | msm_dp_display = container_of(dp, struct msm_dp_display_private, msm_dp_display); | 766 | msm_dp_display = container_of(dp, struct msm_dp_display_private, msm_dp_display); |
| 710 | link_info = &msm_dp_display->panel->link_info; | 767 | link_info = &msm_dp_display->panel->link_info; |
| 711 | 768 | ||
| 712 | if ((drm_mode_is_420_only(&dp->connector->display_info, mode) && | 769 | is_yuv_420 = drm_mode_is_420_only(&dp->connector->display_info, mode); |
| 713 | msm_dp_display->panel->vsc_sdp_supported) || | 770 | |
| 714 | msm_dp_wide_bus_available(dp)) | 771 | /* |
| 772 | * YUV 420 is carried over DP by signalling the colorimetry through a | ||
| 773 | * VSC SDP, so a 420-only mode cannot be driven without VSC SDP support. | ||
| 774 | */ | ||
| 775 | if (is_yuv_420 && !msm_dp_display->panel->vsc_sdp_supported) | ||
| 776 | return MODE_NO_420; | ||
| 777 | |||
| 778 | if (is_yuv_420 || msm_dp_display->wide_bus_supported) | ||
| 715 | mode_pclk_khz /= 2; | 779 | mode_pclk_khz /= 2; |
| 716 | 780 | ||
| 717 | if (mode_pclk_khz > DP_MAX_PIXEL_CLK_KHZ) | 781 | if (mode_pclk_khz > DP_MAX_PIXEL_CLK_KHZ) |
| @@ -744,8 +808,7 @@ int msm_dp_display_get_modes(struct msm_dp *dp) · 26 unmodified lines | |||
| 744 | 808 | ||
| 745 | msm_dp_display = container_of(dp, struct msm_dp_display_private, msm_dp_display); | 809 | msm_dp_display = container_of(dp, struct msm_dp_display_private, msm_dp_display); |
| 746 | 810 | ||
| 747 | return msm_dp_panel_get_modes(msm_dp_display->panel, | 811 | return drm_edid_connector_add_modes(msm_dp_display->panel->connector); |
| 748 | dp->connector); | ||
| 749 | } | 812 | } |
| 750 | 813 | ||
| 751 | bool msm_dp_display_check_video_test(struct msm_dp *dp) | 814 | bool msm_dp_display_check_video_test(struct msm_dp *dp) |
| @@ -808,7 +871,7 @@ void msm_dp_display_set_psr(struct msm_dp *msm_dp_display, bool enter) · 56 unmodified lines | |||
| 808 | } | 871 | } |
| 809 | 872 | ||
| 810 | dp = container_of(msm_dp_display, struct msm_dp_display_private, msm_dp_display); | 873 | dp = container_of(msm_dp_display, struct msm_dp_display_private, msm_dp_display); |
| 811 | msm_dp_ctrl_set_psr(dp->ctrl, enter); | 874 | msm_dp_ctrl_set_psr(dp->ctrl, dp->panel, enter); |
| 812 | } | 875 | } |
| 813 | 876 | ||
| 814 | /** | 877 | /** |
| @@ -918,7 +981,7 @@ static irqreturn_t msm_dp_display_irq_handler(int irq, void *dev_id) · 103 unmodified lines | |||
| 918 | } | 981 | } |
| 919 | 982 | ||
| 920 | /* DP controller isr */ | 983 | /* DP controller isr */ |
| 921 | ret |= msm_dp_ctrl_isr(dp->ctrl); | 984 | ret |= msm_dp_ctrl_isr(dp->ctrl, dp->panel); |
| 922 | 985 | ||
| 923 | return ret; | 986 | return ret; |
| 924 | } | 987 | } |
| @@ -1277,22 +1340,10 @@ void __exit msm_dp_unregister(void) · 352 unmodified lines | |||
| 1277 | platform_driver_unregister(&msm_dp_display_driver); | 1340 | platform_driver_unregister(&msm_dp_display_driver); |
| 1278 | } | 1341 | } |
| 1279 | 1342 | ||
| 1280 | bool msm_dp_is_yuv_420_enabled(const struct msm_dp *msm_dp_display, | ||
| 1281 | const struct drm_display_mode *mode) | ||
| 1282 | { | ||
| 1283 | struct msm_dp_display_private *dp; | ||
| 1284 | const struct drm_display_info *info; | ||
| 1285 | |||
| 1286 | dp = container_of(msm_dp_display, struct msm_dp_display_private, msm_dp_display); | ||
| 1287 | info = &msm_dp_display->connector->display_info; | ||
| 1288 | |||
| 1289 | return dp->panel->vsc_sdp_supported && drm_mode_is_420_only(info, mode); | ||
| 1290 | } | ||
| 1291 | |||
| 1292 | bool msm_dp_needs_periph_flush(const struct msm_dp *msm_dp_display, | 1343 | bool msm_dp_needs_periph_flush(const struct msm_dp *msm_dp_display, |
| 1293 | const struct drm_display_mode *mode) | 1344 | const struct drm_display_mode *mode) |
| 1294 | { | 1345 | { |
| 1295 | return msm_dp_is_yuv_420_enabled(msm_dp_display, mode); | 1346 | return drm_mode_is_420_only(&msm_dp_display->connector->display_info, mode); |
| 1296 | } | 1347 | } |
| 1297 | 1348 | ||
| 1298 | bool msm_dp_wide_bus_available(const struct msm_dp *msm_dp_display) | 1349 | bool msm_dp_wide_bus_available(const struct msm_dp *msm_dp_display) |
| @@ -1301,7 +1352,7 @@ bool msm_dp_wide_bus_available(const struct msm_dp *msm_dp_display) · 2 unmodified lines | |||
| 1301 | 1352 | ||
| 1302 | dp = container_of(msm_dp_display, struct msm_dp_display_private, msm_dp_display); | 1353 | dp = container_of(msm_dp_display, struct msm_dp_display_private, msm_dp_display); |
| 1303 | 1354 | ||
| 1304 | if (dp->msm_dp_mode.out_fmt_is_yuv_420) | 1355 | if (dp->panel->msm_dp_mode.out_fmt_is_yuv_420) |
| 1305 | return false; | 1356 | return false; |
| 1306 | 1357 | ||
| 1307 | return dp->wide_bus_supported; | 1358 | return dp->wide_bus_supported; |
| @@ -1352,66 +1403,57 @@ int msm_dp_modeset_init(struct msm_dp *msm_dp_display, struct drm_device *dev, · 44 unmodified lines | |||
| 1352 | return 0; | 1403 | return 0; |
| 1353 | } | 1404 | } |
| 1354 | 1405 | ||
| 1355 | void msm_dp_bridge_atomic_enable(struct drm_bridge *drm_bridge, | 1406 | void msm_dp_display_atomic_pre_enable(struct msm_dp *msm_dp_display, |
| 1356 | struct drm_atomic_commit *state) | 1407 | struct drm_atomic_commit *state) |
| 1357 | { | 1408 | { |
| 1358 | struct msm_dp_bridge *msm_dp_bridge = to_dp_bridge(drm_bridge); | 1409 | struct msm_dp_display_private *dp; |
| 1359 | struct msm_dp *dp = msm_dp_bridge->msm_dp_display; | 1410 | struct drm_crtc *crtc; |
| 1360 | int rc = 0; | 1411 | struct drm_crtc_state *crtc_state; |
| 1361 | struct msm_dp_display_private *msm_dp_display; | ||
| 1362 | bool force_link_train = false; | ||
| 1363 | |||
| 1364 | msm_dp_display = container_of(dp, struct msm_dp_display_private, msm_dp_display); | ||
| 1365 | if (!msm_dp_display->msm_dp_mode.drm_mode.clock) { | ||
| 1366 | DRM_ERROR("invalid params\n"); | ||
| 1367 | return; | ||
| 1368 | } | ||
| 1369 | 1412 | ||
| 1370 | if (dp->is_edp) | 1413 | dp = container_of(msm_dp_display, struct msm_dp_display_private, msm_dp_display); |
| 1371 | msm_dp_hpd_plug_handle(msm_dp_display); | ||
| 1372 | 1414 | ||
| 1373 | if (pm_runtime_resume_and_get(&dp->pdev->dev)) { | 1415 | crtc = drm_atomic_get_new_crtc_for_encoder(state, msm_dp_display->bridge->encoder); |
| 1374 | DRM_ERROR("failed to pm_runtime_resume\n"); | 1416 | if (!crtc) |
| 1375 | return; | 1417 | return; |
| 1376 | } | 1418 | crtc_state = drm_atomic_get_new_crtc_state(state, crtc); |
| 1377 | 1419 | ||
| 1378 | if (msm_dp_display->link->sink_count == 0) | 1420 | /* |
| 1379 | return; | 1421 | * The DPU encoder's .atomic_enable() reads the mode's YUV420 / wide bus |
| 1422 | * state and runs before the bridge's .atomic_enable(), so the mode must | ||
| 1423 | * be programmed here, in .atomic_pre_enable(). | ||
| 1424 | */ | ||
| 1425 | msm_dp_display_set_mode(msm_dp_display, &crtc_state->adjusted_mode, dp->panel); | ||
| 1426 | } | ||
| 1380 | 1427 | ||
| 1381 | rc = msm_dp_display_set_mode(dp, &msm_dp_display->msm_dp_mode); | 1428 | void msm_dp_display_atomic_enable(struct msm_dp *msm_dp_display, |
| 1382 | if (rc) { | 1429 | struct drm_atomic_commit *state) |
| 1383 | DRM_ERROR("Failed to perform a mode set, rc=%d\n", rc); | 1430 | { |
| 1384 | return; | 1431 | int rc = 0; |
| 1385 | } | 1432 | struct msm_dp_display_private *dp; |
| 1386 | 1433 | ||
| 1387 | if (!dp->power_on) { | 1434 | dp = container_of(msm_dp_display, struct msm_dp_display_private, msm_dp_display); |
| 1388 | msm_dp_display_host_phy_init(msm_dp_display); | ||
| 1389 | force_link_train = true; | ||
| 1390 | } | ||
| 1391 | 1435 | ||
| 1392 | rc = msm_dp_ctrl_on_link(msm_dp_display->ctrl); | 1436 | rc = msm_dp_display_prepare_link(dp); |
| 1393 | if (rc) { | 1437 | if (rc) { |
| 1394 | DRM_ERROR("Failed link training (rc=%d)\n", rc); | 1438 | DRM_ERROR("DP display prepare failed, rc=%d\n", rc); |
| 1395 | // TODO: schedule drm_connector_set_link_status_property() | ||
| 1396 | return; | 1439 | return; |
| 1397 | } | 1440 | } |
| 1398 | 1441 | ||
| 1399 | msm_dp_display_enable(msm_dp_display, force_link_train); | 1442 | rc = msm_dp_display_enable(dp, dp->panel); |
| 1443 | if (rc) | ||
| 1444 | DRM_ERROR("DP display enable failed, rc=%d\n", rc); | ||
| 1400 | 1445 | ||
| 1401 | rc = msm_dp_display_post_enable(dp); | 1446 | rc = msm_dp_display_post_enable(msm_dp_display); |
| 1402 | if (rc) { | 1447 | if (rc) { |
| 1403 | DRM_ERROR("DP display post enable failed, rc=%d\n", rc); | 1448 | DRM_ERROR("DP display post enable failed, rc=%d\n", rc); |
| 1404 | msm_dp_display_disable(msm_dp_display); | 1449 | msm_dp_display_disable(dp, dp->panel); |
| 1405 | } | 1450 | } |
| 1406 | 1451 | ||
| 1407 | drm_dbg_dp(dp->drm_dev, "type=%d Done\n", dp->connector_type); | 1452 | drm_dbg_dp(msm_dp_display->drm_dev, "type=%d Done\n", msm_dp_display->connector_type); |
| 1408 | } | 1453 | } |
| 1409 | 1454 | ||
| 1410 | void msm_dp_bridge_atomic_disable(struct drm_bridge *drm_bridge, | 1455 | void msm_dp_display_atomic_disable(struct msm_dp *dp) |
| 1411 | struct drm_atomic_commit *state) | ||
| 1412 | { | 1456 | { |
| 1413 | struct msm_dp_bridge *msm_dp_bridge = to_dp_bridge(drm_bridge); | ||
| 1414 | struct msm_dp *dp = msm_dp_bridge->msm_dp_display; | ||
| 1415 | struct msm_dp_display_private *msm_dp_display; | 1457 | struct msm_dp_display_private *msm_dp_display; |
| 1416 | 1458 | ||
| 1417 | msm_dp_display = container_of(dp, struct msm_dp_display_private, msm_dp_display); | 1459 | msm_dp_display = container_of(dp, struct msm_dp_display_private, msm_dp_display); |
| @@ -1419,62 +1461,29 @@ void msm_dp_bridge_atomic_disable(struct drm_bridge *drm_bridge, · 1 unmodified line | |||
| 1419 | msm_dp_ctrl_push_idle(msm_dp_display->ctrl); | 1461 | msm_dp_ctrl_push_idle(msm_dp_display->ctrl); |
| 1420 | } | 1462 | } |
| 1421 | 1463 | ||
| 1422 | void msm_dp_bridge_atomic_post_disable(struct drm_bridge *drm_bridge, | 1464 | static void msm_dp_display_unprepare(struct msm_dp_display_private *dp) |
| 1423 | struct drm_atomic_commit *state) | ||
| 1424 | { | 1465 | { |
| 1425 | struct msm_dp_bridge *msm_dp_bridge = to_dp_bridge(drm_bridge); | 1466 | struct msm_dp *msm_dp_display = &dp->msm_dp_display; |
| 1426 | struct msm_dp *dp = msm_dp_bridge->msm_dp_display; | ||
| 1427 | struct msm_dp_display_private *msm_dp_display; | ||
| 1428 | |||
| 1429 | msm_dp_display = container_of(dp, struct msm_dp_display_private, msm_dp_display); | ||
| 1430 | |||
| 1431 | if (dp->is_edp) | ||
| 1432 | msm_dp_hpd_unplug_handle(msm_dp_display); | ||
| 1433 | |||
| 1434 | msm_dp_display_disable(msm_dp_display); | ||
| 1435 | 1467 | ||
| 1436 | drm_dbg_dp(dp->drm_dev, "type=%d Done\n", dp->connector_type); | 1468 | pm_runtime_put_sync(&msm_dp_display->pdev->dev); |
| 1437 | 1469 | ||
| 1438 | pm_runtime_put_sync(&dp->pdev->dev); | 1470 | drm_dbg_dp(dp->drm_dev, "type=%d Done\n", msm_dp_display->connector_type); |
| 1439 | } | 1471 | } |
| 1440 | 1472 | ||
| 1441 | void msm_dp_bridge_mode_set(struct drm_bridge *drm_bridge, | 1473 | void msm_dp_display_atomic_post_disable(struct msm_dp *dp) |
| 1442 | const struct drm_display_mode *mode, | ||
| 1443 | const struct drm_display_mode *adjusted_mode) | ||
| 1444 | { | 1474 | { |
| 1445 | struct msm_dp_bridge *msm_dp_bridge = to_dp_bridge(drm_bridge); | ||
| 1446 | struct msm_dp *dp = msm_dp_bridge->msm_dp_display; | ||
| 1447 | struct msm_dp_display_private *msm_dp_display; | 1475 | struct msm_dp_display_private *msm_dp_display; |
| 1448 | struct msm_dp_panel *msm_dp_panel; | ||
| 1449 | 1476 | ||
| 1450 | msm_dp_display = container_of(dp, struct msm_dp_display_private, msm_dp_display); | 1477 | msm_dp_display = container_of(dp, struct msm_dp_display_private, msm_dp_display); |
| 1451 | msm_dp_panel = msm_dp_display->panel; | ||
| 1452 | 1478 | ||
| 1453 | memset(&msm_dp_display->msm_dp_mode, 0x0, sizeof(struct msm_dp_display_mode)); | 1479 | if (dp->is_edp) |
| 1454 | 1480 | msm_dp_hpd_unplug_handle(msm_dp_display); | |
| 1455 | if (msm_dp_display_check_video_test(dp)) | ||
| 1456 | msm_dp_display->msm_dp_mode.bpp = msm_dp_display_get_test_bpp(dp); | ||
| 1457 | else /* Default num_components per pixel = 3 */ | ||
| 1458 | msm_dp_display->msm_dp_mode.bpp = dp->connector->display_info.bpc * 3; | ||
| 1459 | |||
| 1460 | if (!msm_dp_display->msm_dp_mode.bpp) | ||
| 1461 | msm_dp_display->msm_dp_mode.bpp = 24; /* Default bpp */ | ||
| 1462 | |||
| 1463 | drm_mode_copy(&msm_dp_display->msm_dp_mode.drm_mode, adjusted_mode); | ||
| 1464 | |||
| 1465 | msm_dp_display->msm_dp_mode.v_active_low = | ||
| 1466 | !!(msm_dp_display->msm_dp_mode.drm_mode.flags & DRM_MODE_FLAG_NVSYNC); | ||
| 1467 | 1481 | ||
| 1468 | msm_dp_display->msm_dp_mode.h_active_low = | 1482 | msm_dp_display_audio_notify_disable(msm_dp_display); |
| 1469 | !!(msm_dp_display->msm_dp_mode.drm_mode.flags & DRM_MODE_FLAG_NHSYNC); | ||
| 1470 | 1483 | ||
| 1471 | msm_dp_display->msm_dp_mode.out_fmt_is_yuv_420 = | 1484 | msm_dp_display_disable(msm_dp_display, msm_dp_display->panel); |
| 1472 | drm_mode_is_420_only(&dp->connector->display_info, adjusted_mode) && | ||
| 1473 | msm_dp_panel->vsc_sdp_supported; | ||
| 1474 | 1485 | ||
| 1475 | /* populate wide_bus_support to different layers */ | 1486 | msm_dp_display_unprepare(msm_dp_display); |
| 1476 | msm_dp_display->ctrl->wide_bus_en = | ||
| 1477 | msm_dp_display->msm_dp_mode.out_fmt_is_yuv_420 ? false : msm_dp_display->wide_bus_supported; | ||
| 1478 | } | 1487 | } |
| 1479 | 1488 | ||
| 1480 | void msm_dp_bridge_hpd_enable(struct drm_bridge *bridge) | 1489 | void msm_dp_bridge_hpd_enable(struct drm_bridge *bridge) |
| @@ -33,5 +33,14 @@ void msm_dp_display_signal_audio_start(struct msm_dp *msm_dp_display); · 32 unmodified lines | |||
| 33 | void msm_dp_display_signal_audio_complete(struct msm_dp *msm_dp_display); | 33 | void msm_dp_display_signal_audio_complete(struct msm_dp *msm_dp_display); |
| 34 | void msm_dp_display_set_psr(struct msm_dp *dp, bool enter); | 34 | void msm_dp_display_set_psr(struct msm_dp *dp, bool enter); |
| 35 | void msm_dp_display_debugfs_init(struct msm_dp *msm_dp_display, struct dentry *dentry, bool is_edp); | 35 | void msm_dp_display_debugfs_init(struct msm_dp *msm_dp_display, struct dentry *dentry, bool is_edp); |
| 36 | void msm_dp_display_atomic_post_disable(struct msm_dp *dp_display); | ||
| 37 | void msm_dp_display_atomic_disable(struct msm_dp *dp_display); | ||
| 38 | void msm_dp_display_atomic_pre_enable(struct msm_dp *dp_display, | ||
| 39 | struct drm_atomic_commit *state); | ||
| 40 | void msm_dp_display_atomic_enable(struct msm_dp *dp_display, | ||
| 41 | struct drm_atomic_commit *state); | ||
| 42 | enum drm_mode_status msm_dp_display_mode_valid(struct msm_dp *dp, | ||
| 43 | const struct drm_display_info *info, | ||
| 44 | const struct drm_display_mode *mode); | ||
| 36 | 45 | ||
| 37 | #endif /* _DP_DISPLAY_H_ */ | 46 | #endif /* _DP_DISPLAY_H_ */ |
| @@ -49,14 +49,60 @@ static void msm_dp_bridge_debugfs_init(struct drm_bridge *bridge, struct dentry · 48 unmodified lines | |||
| 49 | msm_dp_display_debugfs_init(dp, root, false); | 49 | msm_dp_display_debugfs_init(dp, root, false); |
| 50 | } | 50 | } |
| 51 | 51 | ||
| 52 | static void msm_dp_bridge_atomic_pre_enable(struct drm_bridge *drm_bridge, | ||
| 53 | struct drm_atomic_commit *state) | ||
| 54 | { | ||
| 55 | struct msm_dp_bridge *dp_bridge = to_dp_bridge(drm_bridge); | ||
| 56 | struct msm_dp *dp = dp_bridge->msm_dp_display; | ||
| 57 | |||
| 58 | msm_dp_display_atomic_pre_enable(dp, state); | ||
| 59 | } | ||
| 60 | |||
| 61 | static void msm_dp_bridge_atomic_enable(struct drm_bridge *drm_bridge, | ||
| 62 | struct drm_atomic_commit *state) | ||
| 63 | { | ||
| 64 | struct msm_dp_bridge *dp_bridge = to_dp_bridge(drm_bridge); | ||
| 65 | struct msm_dp *dp = dp_bridge->msm_dp_display; | ||
| 66 | |||
| 67 | msm_dp_display_atomic_enable(dp, state); | ||
| 68 | } | ||
| 69 | |||
| 70 | static void msm_dp_bridge_atomic_disable(struct drm_bridge *drm_bridge, | ||
| 71 | struct drm_atomic_commit *state) | ||
| 72 | { | ||
| 73 | struct msm_dp_bridge *dp_bridge = to_dp_bridge(drm_bridge); | ||
| 74 | struct msm_dp *dp = dp_bridge->msm_dp_display; | ||
| 75 | |||
| 76 | msm_dp_display_atomic_disable(dp); | ||
| 77 | } | ||
| 78 | |||
| 79 | static void msm_dp_bridge_atomic_post_disable(struct drm_bridge *drm_bridge, | ||
| 80 | struct drm_atomic_commit *state) | ||
| 81 | { | ||
| 82 | struct msm_dp_bridge *dp_bridge = to_dp_bridge(drm_bridge); | ||
| 83 | struct msm_dp *dp = dp_bridge->msm_dp_display; | ||
| 84 | |||
| 85 | msm_dp_display_atomic_post_disable(dp); | ||
| 86 | } | ||
| 87 | |||
| 88 | static enum drm_mode_status msm_dp_bridge_mode_valid(struct drm_bridge *drm_bridge, | ||
| 89 | const struct drm_display_info *info, | ||
| 90 | const struct drm_display_mode *mode) | ||
| 91 | { | ||
| 92 | struct msm_dp_bridge *dp_bridge = to_dp_bridge(drm_bridge); | ||
| 93 | struct msm_dp *dp = dp_bridge->msm_dp_display; | ||
| 94 | |||
| 95 | return msm_dp_display_mode_valid(dp, info, mode); | ||
| 96 | } | ||
| 97 | |||
| 52 | static const struct drm_bridge_funcs msm_dp_bridge_ops = { | 98 | static const struct drm_bridge_funcs msm_dp_bridge_ops = { |
| 53 | .atomic_duplicate_state = drm_atomic_helper_bridge_duplicate_state, | 99 | .atomic_duplicate_state = drm_atomic_helper_bridge_duplicate_state, |
| 54 | .atomic_destroy_state = drm_atomic_helper_bridge_destroy_state, | 100 | .atomic_destroy_state = drm_atomic_helper_bridge_destroy_state, |
| 55 | .atomic_create_state = drm_atomic_helper_bridge_create_state, | 101 | .atomic_create_state = drm_atomic_helper_bridge_create_state, |
| 102 | .atomic_pre_enable = msm_dp_bridge_atomic_pre_enable, | ||
| 56 | .atomic_enable = msm_dp_bridge_atomic_enable, | 103 | .atomic_enable = msm_dp_bridge_atomic_enable, |
| 57 | .atomic_disable = msm_dp_bridge_atomic_disable, | 104 | .atomic_disable = msm_dp_bridge_atomic_disable, |
| 58 | .atomic_post_disable = msm_dp_bridge_atomic_post_disable, | 105 | .atomic_post_disable = msm_dp_bridge_atomic_post_disable, |
| 59 | .mode_set = msm_dp_bridge_mode_set, | ||
| 60 | .mode_valid = msm_dp_bridge_mode_valid, | 106 | .mode_valid = msm_dp_bridge_mode_valid, |
| 61 | .get_modes = msm_dp_bridge_get_modes, | 107 | .get_modes = msm_dp_bridge_get_modes, |
| 62 | .detect = msm_dp_bridge_detect, | 108 | .detect = msm_dp_bridge_detect, |
| @@ -116,7 +162,7 @@ static void msm_edp_bridge_atomic_enable(struct drm_bridge *drm_bridge, · 53 unmodified lines | |||
| 116 | return; | 162 | return; |
| 117 | } | 163 | } |
| 118 | 164 | ||
| 119 | msm_dp_bridge_atomic_enable(drm_bridge, state); | 165 | msm_dp_display_atomic_enable(dp, state); |
| 120 | } | 166 | } |
| 121 | 167 | ||
| 122 | static void msm_edp_bridge_atomic_disable(struct drm_bridge *drm_bridge, | 168 | static void msm_edp_bridge_atomic_disable(struct drm_bridge *drm_bridge, |
| @@ -230,10 +276,10 @@ static void msm_edp_bridge_debugfs_init(struct drm_bridge *bridge, struct dentry · 107 unmodified lines | |||
| 230 | } | 276 | } |
| 231 | 277 | ||
| 232 | static const struct drm_bridge_funcs msm_edp_bridge_ops = { | 278 | static const struct drm_bridge_funcs msm_edp_bridge_ops = { |
| 279 | .atomic_pre_enable = msm_dp_bridge_atomic_pre_enable, | ||
| 233 | .atomic_enable = msm_edp_bridge_atomic_enable, | 280 | .atomic_enable = msm_edp_bridge_atomic_enable, |
| 234 | .atomic_disable = msm_edp_bridge_atomic_disable, | 281 | .atomic_disable = msm_edp_bridge_atomic_disable, |
| 235 | .atomic_post_disable = msm_edp_bridge_atomic_post_disable, | 282 | .atomic_post_disable = msm_edp_bridge_atomic_post_disable, |
| 236 | .mode_set = msm_dp_bridge_mode_set, | ||
| 237 | .mode_valid = msm_edp_bridge_mode_valid, | 283 | .mode_valid = msm_edp_bridge_mode_valid, |
| 238 | .atomic_create_state = drm_atomic_helper_bridge_create_state, | 284 | .atomic_create_state = drm_atomic_helper_bridge_create_state, |
| 239 | .atomic_duplicate_state = drm_atomic_helper_bridge_duplicate_state, | 285 | .atomic_duplicate_state = drm_atomic_helper_bridge_duplicate_state, |
| @@ -27,18 +27,6 @@ int msm_dp_bridge_init(struct msm_dp *msm_dp_display, struct drm_device *dev, · 26 unmodified lines | |||
| 27 | 27 | ||
| 28 | enum drm_connector_status msm_dp_bridge_detect(struct drm_bridge *bridge, | 28 | enum drm_connector_status msm_dp_bridge_detect(struct drm_bridge *bridge, |
| 29 | struct drm_connector *connector); | 29 | struct drm_connector *connector); |
| 30 | void msm_dp_bridge_atomic_enable(struct drm_bridge *drm_bridge, | ||
| 31 | struct drm_atomic_commit *state); | ||
| 32 | void msm_dp_bridge_atomic_disable(struct drm_bridge *drm_bridge, | ||
| 33 | struct drm_atomic_commit *state); | ||
| 34 | void msm_dp_bridge_atomic_post_disable(struct drm_bridge *drm_bridge, | ||
| 35 | struct drm_atomic_commit *state); | ||
| 36 | enum drm_mode_status msm_dp_bridge_mode_valid(struct drm_bridge *bridge, | ||
| 37 | const struct drm_display_info *info, | ||
| 38 | const struct drm_display_mode *mode); | ||
| 39 | void msm_dp_bridge_mode_set(struct drm_bridge *drm_bridge, | ||
| 40 | const struct drm_display_mode *mode, | ||
| 41 | const struct drm_display_mode *adjusted_mode); | ||
| 42 | void msm_dp_bridge_hpd_enable(struct drm_bridge *bridge); | 30 | void msm_dp_bridge_hpd_enable(struct drm_bridge *bridge); |
| 43 | void msm_dp_bridge_hpd_disable(struct drm_bridge *bridge); | 31 | void msm_dp_bridge_hpd_disable(struct drm_bridge *bridge); |
| 44 | void msm_dp_bridge_hpd_notify(struct drm_bridge *bridge, | 32 | void msm_dp_bridge_hpd_notify(struct drm_bridge *bridge, |
| @@ -232,8 +232,8 @@ static u32 msm_dp_panel_get_supported_bpp(struct msm_dp_panel *msm_dp_panel, · 231 unmodified lines | |||
| 232 | return min_supported_bpp; | 232 | return min_supported_bpp; |
| 233 | } | 233 | } |
| 234 | 234 | ||
| 235 | int msm_dp_panel_read_sink_caps(struct msm_dp_panel *msm_dp_panel, | 235 | int msm_dp_panel_read_link_caps(struct msm_dp_panel *msm_dp_panel, |
| 236 | struct drm_connector *connector) | 236 | struct drm_connector *connector) |
| 237 | { | 237 | { |
| 238 | int rc, bw_code; | 238 | int rc, bw_code; |
| 239 | int count; | 239 | int count; |
| @@ -271,36 +271,9 @@ int msm_dp_panel_read_sink_caps(struct msm_dp_panel *msm_dp_panel, · 31 unmodified lines | |||
| 271 | 271 | ||
| 272 | rc = drm_dp_read_downstream_info(panel->aux, msm_dp_panel->dpcd, | 272 | rc = drm_dp_read_downstream_info(panel->aux, msm_dp_panel->dpcd, |
| 273 | msm_dp_panel->downstream_ports); | 273 | msm_dp_panel->downstream_ports); |
| 274 | if (rc) | ||
| 275 | return rc; | ||
| 276 | |||
| 277 | drm_edid_free(msm_dp_panel->drm_edid); | ||
| 278 | |||
| 279 | msm_dp_panel->drm_edid = drm_edid_read_ddc(connector, &panel->aux->ddc); | ||
| 280 | |||
| 281 | drm_edid_connector_update(connector, msm_dp_panel->drm_edid); | ||
| 282 | |||
| 283 | if (!msm_dp_panel->drm_edid) { | ||
| 284 | DRM_ERROR("panel edid read failed\n"); | ||
| 285 | /* check edid read fail is due to unplug */ | ||
| 286 | if (!msm_dp_aux_is_link_connected(panel->aux)) { | ||
| 287 | rc = -ETIMEDOUT; | ||
| 288 | goto end; | ||
| 289 | } | ||
| 290 | } | ||
| 291 | |||
| 292 | end: | ||
| 293 | return rc; | 274 | return rc; |
| 294 | } | 275 | } |
| 295 | 276 | ||
| 296 | void msm_dp_panel_unplugged(struct msm_dp_panel *msm_dp_panel, | ||
| 297 | struct drm_connector *connector) | ||
| 298 | { | ||
| 299 | drm_edid_connector_update(connector, NULL); | ||
| 300 | drm_edid_free(msm_dp_panel->drm_edid); | ||
| 301 | msm_dp_panel->drm_edid = NULL; | ||
| 302 | } | ||
| 303 | |||
| 304 | u32 msm_dp_panel_get_mode_bpp(struct msm_dp_panel *msm_dp_panel, | 277 | u32 msm_dp_panel_get_mode_bpp(struct msm_dp_panel *msm_dp_panel, |
| 305 | u32 mode_edid_bpp, u32 mode_pclk_khz) | 278 | u32 mode_edid_bpp, u32 mode_pclk_khz) |
| 306 | { | 279 | { |
| @@ -324,20 +297,6 @@ u32 msm_dp_panel_get_mode_bpp(struct msm_dp_panel *msm_dp_panel, · 17 unmodified lines | |||
| 324 | return bpp; | 297 | return bpp; |
| 325 | } | 298 | } |
| 326 | 299 | ||
| 327 | int msm_dp_panel_get_modes(struct msm_dp_panel *msm_dp_panel, | ||
| 328 | struct drm_connector *connector) | ||
| 329 | { | ||
| 330 | if (!msm_dp_panel) { | ||
| 331 | DRM_ERROR("invalid input\n"); | ||
| 332 | return -EINVAL; | ||
| 333 | } | ||
| 334 | |||
| 335 | if (msm_dp_panel->drm_edid) | ||
| 336 | return drm_edid_connector_add_modes(connector); | ||
| 337 | |||
| 338 | return 0; | ||
| 339 | } | ||
| 340 | |||
| 341 | static u8 msm_dp_panel_get_edid_checksum(const struct edid *edid) | 300 | static u8 msm_dp_panel_get_edid_checksum(const struct edid *edid) |
| 342 | { | 301 | { |
| 343 | edid += edid->extensions; | 302 | edid += edid->extensions; |
| @@ -345,7 +304,8 @@ static u8 msm_dp_panel_get_edid_checksum(const struct edid *edid) · 1 unmodified line | |||
| 345 | return edid->checksum; | 304 | return edid->checksum; |
| 346 | } | 305 | } |
| 347 | 306 | ||
| 348 | void msm_dp_panel_handle_sink_request(struct msm_dp_panel *msm_dp_panel) | 307 | void msm_dp_panel_handle_sink_request(struct msm_dp_panel *msm_dp_panel, |
| 308 | const struct drm_edid *drm_edid) | ||
| 349 | { | 309 | { |
| 350 | struct msm_dp_panel_private *panel; | 310 | struct msm_dp_panel_private *panel; |
| 351 | 311 | ||
| @@ -358,7 +318,7 @@ void msm_dp_panel_handle_sink_request(struct msm_dp_panel *msm_dp_panel) · 6 unmodified lines | |||
| 358 | 318 | ||
| 359 | if (panel->link->sink_request & DP_TEST_LINK_EDID_READ) { | 319 | if (panel->link->sink_request & DP_TEST_LINK_EDID_READ) { |
| 360 | /* FIXME: get rid of drm_edid_raw() */ | 320 | /* FIXME: get rid of drm_edid_raw() */ |
| 361 | const struct edid *edid = drm_edid_raw(msm_dp_panel->drm_edid); | 321 | const struct edid *edid = drm_edid_raw(drm_edid); |
| 362 | u8 checksum; | 322 | u8 checksum; |
| 363 | 323 | ||
| 364 | if (edid) | 324 | if (edid) |
| @@ -687,15 +647,27 @@ int msm_dp_panel_timing_cfg(struct msm_dp_panel *msm_dp_panel, bool wide_bus_en) · 322 unmodified lines | |||
| 687 | return 0; | 647 | return 0; |
| 688 | } | 648 | } |
| 689 | 649 | ||
| 690 | int msm_dp_panel_init_panel_info(struct msm_dp_panel *msm_dp_panel) | 650 | int msm_dp_panel_init_panel_info(struct msm_dp_panel *msm_dp_panel, |
| 651 | const struct drm_display_mode *adjusted_mode, | ||
| 652 | u32 bpp) | ||
| 691 | { | 653 | { |
| 692 | struct drm_display_mode *drm_mode; | 654 | struct drm_display_mode *drm_mode; |
| 693 | struct msm_dp_panel_private *panel; | 655 | struct msm_dp_panel_private *panel; |
| 694 | 656 | ||
| 695 | drm_mode = &msm_dp_panel->msm_dp_mode.drm_mode; | ||
| 696 | |||
| 697 | panel = container_of(msm_dp_panel, struct msm_dp_panel_private, msm_dp_panel); | 657 | panel = container_of(msm_dp_panel, struct msm_dp_panel_private, msm_dp_panel); |
| 698 | 658 | ||
| 659 | drm_mode_copy(&msm_dp_panel->msm_dp_mode.drm_mode, adjusted_mode); | ||
| 660 | msm_dp_panel->msm_dp_mode.bpp = bpp; | ||
| 661 | msm_dp_panel->msm_dp_mode.v_active_low = | ||
| 662 | !!(adjusted_mode->flags & DRM_MODE_FLAG_NVSYNC); | ||
| 663 | msm_dp_panel->msm_dp_mode.h_active_low = | ||
| 664 | !!(adjusted_mode->flags & DRM_MODE_FLAG_NHSYNC); | ||
| 665 | msm_dp_panel->msm_dp_mode.out_fmt_is_yuv_420 = | ||
| 666 | drm_mode_is_420_only(&msm_dp_panel->connector->display_info, adjusted_mode) && | ||
| 667 | msm_dp_panel->vsc_sdp_supported; | ||
| 668 | |||
| 669 | drm_mode = &msm_dp_panel->msm_dp_mode.drm_mode; | ||
| 670 | |||
| 699 | /* | 671 | /* |
| 700 | * print resolution info as this is a result | 672 | * print resolution info as this is a result |
| 701 | * of user initiated action of cable connection | 673 | * of user initiated action of cable connection |
| @@ -755,10 +727,3 @@ struct msm_dp_panel *msm_dp_panel_get(struct device *dev, struct drm_dp_aux *aux · 53 unmodified lines | |||
| 755 | return msm_dp_panel; | 727 | return msm_dp_panel; |
| 756 | } | 728 | } |
| 757 | 729 | ||
| 758 | void msm_dp_panel_put(struct msm_dp_panel *msm_dp_panel) | ||
| 759 | { | ||
| 760 | if (!msm_dp_panel) | ||
| 761 | return; | ||
| 762 | |||
| 763 | drm_edid_free(msm_dp_panel->drm_edid); | ||
| 764 | } | ||
| @@ -33,7 +33,6 @@ struct msm_dp_panel { · 32 unmodified lines | |||
| 33 | u8 downstream_ports[DP_MAX_DOWNSTREAM_PORTS]; | 33 | u8 downstream_ports[DP_MAX_DOWNSTREAM_PORTS]; |
| 34 | 34 | ||
| 35 | struct msm_dp_link_info link_info; | 35 | struct msm_dp_link_info link_info; |
| 36 | const struct drm_edid *drm_edid; | ||
| 37 | struct drm_connector *connector; | 36 | struct drm_connector *connector; |
| 38 | struct msm_dp_display_mode msm_dp_mode; | 37 | struct msm_dp_display_mode msm_dp_mode; |
| 39 | struct msm_dp_panel_psr psr_cap; | 38 | struct msm_dp_panel_psr psr_cap; |
| @@ -44,18 +43,17 @@ struct msm_dp_panel { · 4 unmodified lines | |||
| 44 | u32 max_bw_code; | 43 | u32 max_bw_code; |
| 45 | }; | 44 | }; |
| 46 | 45 | ||
| 47 | int msm_dp_panel_init_panel_info(struct msm_dp_panel *msm_dp_panel); | 46 | int msm_dp_panel_init_panel_info(struct msm_dp_panel *msm_dp_panel, |
| 47 | const struct drm_display_mode *adjusted_mode, | ||
| 48 | u32 bpp); | ||
| 48 | int msm_dp_panel_deinit(struct msm_dp_panel *msm_dp_panel); | 49 | int msm_dp_panel_deinit(struct msm_dp_panel *msm_dp_panel); |
| 49 | int msm_dp_panel_timing_cfg(struct msm_dp_panel *msm_dp_panel, bool wide_bus_en); | 50 | int msm_dp_panel_timing_cfg(struct msm_dp_panel *msm_dp_panel, bool wide_bus_en); |
| 50 | int msm_dp_panel_read_sink_caps(struct msm_dp_panel *msm_dp_panel, | 51 | int msm_dp_panel_read_link_caps(struct msm_dp_panel *msm_dp_panel, |
| 51 | struct drm_connector *connector); | 52 | struct drm_connector *connector); |
| 52 | void msm_dp_panel_unplugged(struct msm_dp_panel *msm_dp_panel, | ||
| 53 | struct drm_connector *connector); | ||
| 54 | u32 msm_dp_panel_get_mode_bpp(struct msm_dp_panel *msm_dp_panel, u32 mode_max_bpp, | 53 | u32 msm_dp_panel_get_mode_bpp(struct msm_dp_panel *msm_dp_panel, u32 mode_max_bpp, |
| 55 | u32 mode_pclk_khz); | 54 | u32 mode_pclk_khz); |
| 56 | int msm_dp_panel_get_modes(struct msm_dp_panel *msm_dp_panel, | 55 | void msm_dp_panel_handle_sink_request(struct msm_dp_panel *msm_dp_panel, |
| 57 | struct drm_connector *connector); | 56 | const struct drm_edid *drm_edid); |
| 58 | void msm_dp_panel_handle_sink_request(struct msm_dp_panel *msm_dp_panel); | ||
| 59 | void msm_dp_panel_tpg_config(struct msm_dp_panel *msm_dp_panel, bool enable); | 57 | void msm_dp_panel_tpg_config(struct msm_dp_panel *msm_dp_panel, bool enable); |
| 60 | 58 | ||
| 61 | void msm_dp_panel_clear_dsc_dto(struct msm_dp_panel *msm_dp_panel); | 59 | void msm_dp_panel_clear_dsc_dto(struct msm_dp_panel *msm_dp_panel); |
| @@ -94,5 +92,4 @@ struct msm_dp_panel *msm_dp_panel_get(struct device *dev, struct drm_dp_aux *aux · 32 unmodified lines | |||
| 94 | struct msm_dp_link *link, | 92 | struct msm_dp_link *link, |
| 95 | void __iomem *link_base, | 93 | void __iomem *link_base, |
| 96 | void __iomem *p0_base); | 94 | void __iomem *p0_base); |
| 97 | void msm_dp_panel_put(struct msm_dp_panel *msm_dp_panel); | ||
| 98 | #endif /* _DP_PANEL_H_ */ | 95 | #endif /* _DP_PANEL_H_ */ |
| @@ -149,8 +149,10 @@ · 148 unmodified lines | |||
| 149 | #define DP_CONFIGURATION_CTRL_ENHANCED_FRAMING (0x00000040) | 149 | #define DP_CONFIGURATION_CTRL_ENHANCED_FRAMING (0x00000040) |
| 150 | #define DP_CONFIGURATION_CTRL_SEND_VSC (0x00000080) | 150 | #define DP_CONFIGURATION_CTRL_SEND_VSC (0x00000080) |
| 151 | #define DP_CONFIGURATION_CTRL_BPC (0x00000100) | 151 | #define DP_CONFIGURATION_CTRL_BPC (0x00000100) |
| 152 | #define DP_CONFIGURATION_CTRL_BPC_MASK GENMASK(9, 8) | ||
| 152 | #define DP_CONFIGURATION_CTRL_ASSR (0x00000400) | 153 | #define DP_CONFIGURATION_CTRL_ASSR (0x00000400) |
| 153 | #define DP_CONFIGURATION_CTRL_RGB_YUV (0x00000800) | 154 | #define DP_CONFIGURATION_CTRL_RGB_YUV (0x00000800) |
| 155 | #define DP_CONFIGURATION_CTRL_RGB_YUV_MASK GENMASK(12, 11) | ||
| 154 | #define DP_CONFIGURATION_CTRL_LSCLK_DIV (0x00002000) | 156 | #define DP_CONFIGURATION_CTRL_LSCLK_DIV (0x00002000) |
| 155 | #define DP_CONFIGURATION_CTRL_NUM_OF_LANES_SHIFT (0x04) | 157 | #define DP_CONFIGURATION_CTRL_NUM_OF_LANES_SHIFT (0x04) |
| 156 | #define DP_CONFIGURATION_CTRL_BPC_SHIFT (0x08) | 158 | #define DP_CONFIGURATION_CTRL_BPC_SHIFT (0x08) |
| @@ -550,8 +550,6 @@ error: · 549 unmodified lines | |||
| 550 | 550 | ||
| 551 | void dsi_link_clk_disable_6g(struct msm_dsi_host *msm_host) | 551 | void dsi_link_clk_disable_6g(struct msm_dsi_host *msm_host) |
| 552 | { | 552 | { |
| 553 | /* Drop the performance state vote */ | ||
| 554 | dev_pm_opp_set_rate(&msm_host->pdev->dev, 0); | ||
| 555 | clk_disable_unprepare(msm_host->esc_clk); | 553 | clk_disable_unprepare(msm_host->esc_clk); |
| 556 | clk_disable_unprepare(msm_host->pixel_clk); | 554 | clk_disable_unprepare(msm_host->pixel_clk); |
| 557 | clk_disable_unprepare(msm_host->byte_intf_clk); | 555 | clk_disable_unprepare(msm_host->byte_intf_clk); |
| @@ -671,12 +669,24 @@ static void dsi_calc_pclk(struct msm_dsi_host *msm_host, bool is_bonded_dsi) · 113 unmodified lines | |||
| 671 | 669 | ||
| 672 | int dsi_calc_clk_rate_6g(struct msm_dsi_host *msm_host, bool is_bonded_dsi) | 670 | int dsi_calc_clk_rate_6g(struct msm_dsi_host *msm_host, bool is_bonded_dsi) |
| 673 | { | 671 | { |
| 672 | long rounded_byte_clk_rate; | ||
| 673 | |||
| 674 | if (!msm_host->mode) { | 674 | if (!msm_host->mode) { |
| 675 | pr_err("%s: mode not set\n", __func__); | 675 | pr_err("%s: mode not set\n", __func__); |
| 676 | return -EINVAL; | 676 | return -EINVAL; |
| 677 | } | 677 | } |
| 678 | 678 | ||
| 679 | dsi_calc_pclk(msm_host, is_bonded_dsi); | 679 | dsi_calc_pclk(msm_host, is_bonded_dsi); |
| 680 | |||
| 681 | rounded_byte_clk_rate = clk_round_rate(msm_host->byte_clk, | ||
| 682 | msm_host->byte_clk_rate); | ||
| 683 | if (rounded_byte_clk_rate < 0) { | ||
| 684 | pr_err("%s: failed to round byte clock rate, %ld\n", | ||
| 685 | __func__, rounded_byte_clk_rate); | ||
| 686 | return rounded_byte_clk_rate; | ||
| 687 | } | ||
| 688 | |||
| 689 | msm_host->byte_clk_rate = rounded_byte_clk_rate; | ||
| 680 | msm_host->esc_clk_rate = clk_get_rate(msm_host->esc_clk); | 690 | msm_host->esc_clk_rate = clk_get_rate(msm_host->esc_clk); |
| 681 | return 0; | 691 | return 0; |
| 682 | } | 692 | } |
| @@ -111,6 +111,7 @@ struct msm_dsi_phy { · 110 unmodified lines | |||
| 111 | struct msm_dsi_dphy_timing timing; | 111 | struct msm_dsi_dphy_timing timing; |
| 112 | const struct msm_dsi_phy_cfg *cfg; | 112 | const struct msm_dsi_phy_cfg *cfg; |
| 113 | void *tuning_cfg; | 113 | void *tuning_cfg; |
| 114 | void *pll_data; | ||
| 114 | 115 | ||
| 115 | enum msm_dsi_phy_usecase usecase; | 116 | enum msm_dsi_phy_usecase usecase; |
| 116 | bool regulator_ldo_mode; | 117 | bool regulator_ldo_mode; |
| @@ -426,8 +426,11 @@ static void dsi_pll_enable_pll_bias(struct dsi_pll_7nm *pll) · 425 unmodified lines | |||
| 426 | u32 data; | 426 | u32 data; |
| 427 | 427 | ||
| 428 | spin_lock_irqsave(&pll->pll_enable_lock, flags); | 428 | spin_lock_irqsave(&pll->pll_enable_lock, flags); |
| 429 | pll->pll_enable_cnt++; | 429 | if (pll->pll_enable_cnt++) { |
| 430 | WARN_ON(pll->pll_enable_cnt == INT_MAX); | 430 | spin_unlock_irqrestore(&pll->pll_enable_lock, flags); |
| 431 | WARN_ON(pll->pll_enable_cnt == INT_MAX); | ||
| 432 | return; | ||
| 433 | } | ||
| 431 | 434 | ||
| 432 | data = readl(pll->phy->base + REG_DSI_7nm_PHY_CMN_CTRL_0); | 435 | data = readl(pll->phy->base + REG_DSI_7nm_PHY_CMN_CTRL_0); |
| 433 | data |= DSI_7nm_PHY_CMN_CTRL_0_PLL_SHUTDOWNB; | 436 | data |= DSI_7nm_PHY_CMN_CTRL_0_PLL_SHUTDOWNB; |
| @@ -873,6 +876,7 @@ static int dsi_pll_7nm_init(struct msm_dsi_phy *phy) · 439 unmodified lines | |||
| 873 | spin_lock_init(&pll_7nm->pll_enable_lock); | 876 | spin_lock_init(&pll_7nm->pll_enable_lock); |
| 874 | 877 | ||
| 875 | pll_7nm->phy = phy; | 878 | pll_7nm->phy = phy; |
| 879 | phy->pll_data = pll_7nm; | ||
| 876 | 880 | ||
| 877 | ret = pll_7nm_register(pll_7nm, phy->provided_clocks->hws); | 881 | ret = pll_7nm_register(pll_7nm, phy->provided_clocks->hws); |
| 878 | if (ret) { | 882 | if (ret) { |
| @@ -961,8 +965,10 @@ static int dsi_7nm_phy_enable(struct msm_dsi_phy *phy, · 82 unmodified lines | |||
| 961 | u32 const delay_us = 5; | 965 | u32 const delay_us = 5; |
| 962 | u32 const timeout_us = 1000; | 966 | u32 const timeout_us = 1000; |
| 963 | struct msm_dsi_dphy_timing *timing = &phy->timing; | 967 | struct msm_dsi_dphy_timing *timing = &phy->timing; |
| 968 | struct dsi_pll_7nm *pll = phy->pll_data; | ||
| 964 | void __iomem *base = phy->base; | 969 | void __iomem *base = phy->base; |
| 965 | bool less_than_1500_mhz; | 970 | bool less_than_1500_mhz; |
| 971 | unsigned long flags; | ||
| 966 | u32 vreg_ctrl_0, vreg_ctrl_1, lane_ctrl0; | 972 | u32 vreg_ctrl_0, vreg_ctrl_1, lane_ctrl0; |
| 967 | u32 glbl_pemph_ctrl_0; | 973 | u32 glbl_pemph_ctrl_0; |
| 968 | u32 glbl_str_swi_cal_sel_ctrl, glbl_hstx_str_ctrl_0; | 974 | u32 glbl_str_swi_cal_sel_ctrl, glbl_hstx_str_ctrl_0; |
| @@ -1084,10 +1090,13 @@ static int dsi_7nm_phy_enable(struct msm_dsi_phy *phy, · 115 unmodified lines | |||
| 1084 | glbl_rescode_bot_ctrl = 0x3c; | 1090 | glbl_rescode_bot_ctrl = 0x3c; |
| 1085 | } | 1091 | } |
| 1086 | 1092 | ||
| 1093 | spin_lock_irqsave(&pll->pll_enable_lock, flags); | ||
| 1094 | pll->pll_enable_cnt = 1; | ||
| 1087 | /* de-assert digital and pll power down */ | 1095 | /* de-assert digital and pll power down */ |
| 1088 | data = DSI_7nm_PHY_CMN_CTRL_0_DIGTOP_PWRDN_B | | 1096 | data = DSI_7nm_PHY_CMN_CTRL_0_DIGTOP_PWRDN_B | |
| 1089 | DSI_7nm_PHY_CMN_CTRL_0_PLL_SHUTDOWNB; | 1097 | DSI_7nm_PHY_CMN_CTRL_0_PLL_SHUTDOWNB; |
| 1090 | writel(data, base + REG_DSI_7nm_PHY_CMN_CTRL_0); | 1098 | writel(data, base + REG_DSI_7nm_PHY_CMN_CTRL_0); |
| 1099 | spin_unlock_irqrestore(&pll->pll_enable_lock, flags); | ||
| 1091 | 1100 | ||
| 1092 | /* Assert PLL core reset */ | 1101 | /* Assert PLL core reset */ |
| 1093 | writel(0x00, base + REG_DSI_7nm_PHY_CMN_PLL_CNTRL); | 1102 | writel(0x00, base + REG_DSI_7nm_PHY_CMN_PLL_CNTRL); |
| @@ -1200,7 +1209,9 @@ static bool dsi_7nm_set_continuous_clock(struct msm_dsi_phy *phy, bool enable) · 106 unmodified lines | |||
| 1200 | 1209 | ||
| 1201 | static void dsi_7nm_phy_disable(struct msm_dsi_phy *phy) | 1210 | static void dsi_7nm_phy_disable(struct msm_dsi_phy *phy) |
| 1202 | { | 1211 | { |
| 1212 | struct dsi_pll_7nm *pll = phy->pll_data; | ||
| 1203 | void __iomem *base = phy->base; | 1213 | void __iomem *base = phy->base; |
| 1214 | unsigned long flags; | ||
| 1204 | u32 data; | 1215 | u32 data; |
| 1205 | 1216 | ||
| 1206 | DBG(""); | 1217 | DBG(""); |
| @@ -1227,8 +1238,11 @@ static void dsi_7nm_phy_disable(struct msm_dsi_phy *phy) · 20 unmodified lines | |||
| 1227 | writel(data, base + REG_DSI_7nm_PHY_CMN_CTRL_0); | 1238 | writel(data, base + REG_DSI_7nm_PHY_CMN_CTRL_0); |
| 1228 | writel(0, base + REG_DSI_7nm_PHY_CMN_LANE_CTRL0); | 1239 | writel(0, base + REG_DSI_7nm_PHY_CMN_LANE_CTRL0); |
| 1229 | 1240 | ||
| 1241 | spin_lock_irqsave(&pll->pll_enable_lock, flags); | ||
| 1242 | pll->pll_enable_cnt = 0; | ||
| 1230 | /* Turn off all PHY blocks */ | 1243 | /* Turn off all PHY blocks */ |
| 1231 | writel(0x00, base + REG_DSI_7nm_PHY_CMN_CTRL_0); | 1244 | writel(0x00, base + REG_DSI_7nm_PHY_CMN_CTRL_0); |
| 1245 | spin_unlock_irqrestore(&pll->pll_enable_lock, flags); | ||
| 1232 | 1246 | ||
| 1233 | /* make sure phy is turned off */ | 1247 | /* make sure phy is turned off */ |
| 1234 | wmb(); | 1248 | wmb(); |
| @@ -112,6 +112,25 @@ static inline u32 hdmi_read(struct hdmi *hdmi, u32 reg) · 111 unmodified lines | |||
| 112 | return readl(hdmi->mmio + reg); | 112 | return readl(hdmi->mmio + reg); |
| 113 | } | 113 | } |
| 114 | 114 | ||
| 115 | static inline void hdmi_clear_bits(struct hdmi *hdmi, u32 reg, u32 mask) | ||
| 116 | { | ||
| 117 | u32 val; | ||
| 118 | |||
| 119 | val = hdmi_read(hdmi, reg); | ||
| 120 | val &= ~mask; | ||
| 121 | hdmi_write(hdmi, reg, val); | ||
| 122 | } | ||
| 123 | |||
| 124 | static inline void hdmi_update_bits(struct hdmi *hdmi, u32 reg, u32 mask, u32 data) | ||
| 125 | { | ||
| 126 | u32 val; | ||
| 127 | |||
| 128 | val = hdmi_read(hdmi, reg); | ||
| 129 | val &= ~mask; | ||
| 130 | val |= data & mask; | ||
| 131 | hdmi_write(hdmi, reg, val); | ||
| 132 | } | ||
| 133 | |||
| 115 | static inline u32 hdmi_qfprom_read(struct hdmi *hdmi, u32 reg) | 134 | static inline u32 hdmi_qfprom_read(struct hdmi *hdmi, u32 reg) |
| 116 | { | 135 | { |
| 117 | return readl(hdmi->qfprom_mmio + reg); | 136 | return readl(hdmi->qfprom_mmio + reg); |
| @@ -58,16 +58,13 @@ static int msm_hdmi_bridge_clear_avi_infoframe(struct drm_bridge *bridge) · 57 unmodified lines | |||
| 58 | { | 58 | { |
| 59 | struct hdmi_bridge *hdmi_bridge = to_hdmi_bridge(bridge); | 59 | struct hdmi_bridge *hdmi_bridge = to_hdmi_bridge(bridge); |
| 60 | struct hdmi *hdmi = hdmi_bridge->hdmi; | 60 | struct hdmi *hdmi = hdmi_bridge->hdmi; |
| 61 | u32 val; | ||
| 62 | 61 | ||
| 63 | val = hdmi_read(hdmi, REG_HDMI_INFOFRAME_CTRL0); | 62 | hdmi_clear_bits(hdmi, REG_HDMI_INFOFRAME_CTRL0, |
| 64 | val &= ~(HDMI_INFOFRAME_CTRL0_AVI_SEND | | 63 | HDMI_INFOFRAME_CTRL0_AVI_SEND | |
| 65 | HDMI_INFOFRAME_CTRL0_AVI_CONT); | 64 | HDMI_INFOFRAME_CTRL0_AVI_CONT); |
| 66 | hdmi_write(hdmi, REG_HDMI_INFOFRAME_CTRL0, val); | ||
| 67 | 65 | ||
| 68 | val = hdmi_read(hdmi, REG_HDMI_INFOFRAME_CTRL1); | 66 | hdmi_clear_bits(hdmi, REG_HDMI_INFOFRAME_CTRL1, |
| 69 | val &= ~HDMI_INFOFRAME_CTRL1_AVI_INFO_LINE__MASK; | 67 | HDMI_INFOFRAME_CTRL1_AVI_INFO_LINE__MASK); |
| 70 | hdmi_write(hdmi, REG_HDMI_INFOFRAME_CTRL1, val); | ||
| 71 | 68 | ||
| 72 | return 0; | 69 | return 0; |
| 73 | } | 70 | } |
| @@ -76,18 +73,15 @@ static int msm_hdmi_bridge_clear_audio_infoframe(struct drm_bridge *bridge) · 2 unmodified lines | |||
| 76 | { | 73 | { |
| 77 | struct hdmi_bridge *hdmi_bridge = to_hdmi_bridge(bridge); | 74 | struct hdmi_bridge *hdmi_bridge = to_hdmi_bridge(bridge); |
| 78 | struct hdmi *hdmi = hdmi_bridge->hdmi; | 75 | struct hdmi *hdmi = hdmi_bridge->hdmi; |
| 79 | u32 val; | ||
| 80 | 76 | ||
| 81 | val = hdmi_read(hdmi, REG_HDMI_INFOFRAME_CTRL0); | 77 | hdmi_clear_bits(hdmi, REG_HDMI_INFOFRAME_CTRL0, |
| 82 | val &= ~(HDMI_INFOFRAME_CTRL0_AUDIO_INFO_SEND | | 78 | HDMI_INFOFRAME_CTRL0_AUDIO_INFO_SEND | |
| 83 | HDMI_INFOFRAME_CTRL0_AUDIO_INFO_CONT | | 79 | HDMI_INFOFRAME_CTRL0_AUDIO_INFO_CONT | |
| 84 | HDMI_INFOFRAME_CTRL0_AUDIO_INFO_SOURCE | | 80 | HDMI_INFOFRAME_CTRL0_AUDIO_INFO_SOURCE | |
| 85 | HDMI_INFOFRAME_CTRL0_AUDIO_INFO_UPDATE); | 81 | HDMI_INFOFRAME_CTRL0_AUDIO_INFO_UPDATE); |
| 86 | hdmi_write(hdmi, REG_HDMI_INFOFRAME_CTRL0, val); | ||
| 87 | 82 | ||
| 88 | val = hdmi_read(hdmi, REG_HDMI_INFOFRAME_CTRL1); | 83 | hdmi_clear_bits(hdmi, REG_HDMI_INFOFRAME_CTRL1, |
| 89 | val &= ~HDMI_INFOFRAME_CTRL1_AUDIO_INFO_LINE__MASK; | 84 | HDMI_INFOFRAME_CTRL1_AUDIO_INFO_LINE__MASK); |
| 90 | hdmi_write(hdmi, REG_HDMI_INFOFRAME_CTRL1, val); | ||
| 91 | 85 | ||
| 92 | return 0; | 86 | return 0; |
| 93 | } | 87 | } |
| @@ -96,13 +90,11 @@ static int msm_hdmi_bridge_clear_spd_infoframe(struct drm_bridge *bridge) · 2 unmodified lines | |||
| 96 | { | 90 | { |
| 97 | struct hdmi_bridge *hdmi_bridge = to_hdmi_bridge(bridge); | 91 | struct hdmi_bridge *hdmi_bridge = to_hdmi_bridge(bridge); |
| 98 | struct hdmi *hdmi = hdmi_bridge->hdmi; | 92 | struct hdmi *hdmi = hdmi_bridge->hdmi; |
| 99 | u32 val; | ||
| 100 | 93 | ||
| 101 | val = hdmi_read(hdmi, REG_HDMI_GEN_PKT_CTRL); | 94 | hdmi_clear_bits(hdmi, REG_HDMI_GEN_PKT_CTRL, |
| 102 | val &= ~(HDMI_GEN_PKT_CTRL_GENERIC1_SEND | | 95 | HDMI_GEN_PKT_CTRL_GENERIC1_SEND | |
| 103 | HDMI_GEN_PKT_CTRL_GENERIC1_CONT | | 96 | HDMI_GEN_PKT_CTRL_GENERIC1_CONT | |
| 104 | HDMI_GEN_PKT_CTRL_GENERIC1_LINE__MASK); | 97 | HDMI_GEN_PKT_CTRL_GENERIC1_LINE__MASK); |
| 105 | hdmi_write(hdmi, REG_HDMI_GEN_PKT_CTRL, val); | ||
| 106 | 98 | ||
| 107 | return 0; | 99 | return 0; |
| 108 | } | 100 | } |
| @@ -111,14 +103,12 @@ static int msm_hdmi_bridge_clear_hdmi_infoframe(struct drm_bridge *bridge) · 2 unmodified lines | |||
| 111 | { | 103 | { |
| 112 | struct hdmi_bridge *hdmi_bridge = to_hdmi_bridge(bridge); | 104 | struct hdmi_bridge *hdmi_bridge = to_hdmi_bridge(bridge); |
| 113 | struct hdmi *hdmi = hdmi_bridge->hdmi; | 105 | struct hdmi *hdmi = hdmi_bridge->hdmi; |
| 114 | u32 val; | ||
| 115 | 106 | ||
| 116 | val = hdmi_read(hdmi, REG_HDMI_GEN_PKT_CTRL); | 107 | hdmi_clear_bits(hdmi, REG_HDMI_GEN_PKT_CTRL, |
| 117 | val &= ~(HDMI_GEN_PKT_CTRL_GENERIC0_SEND | | 108 | HDMI_GEN_PKT_CTRL_GENERIC0_SEND | |
| 118 | HDMI_GEN_PKT_CTRL_GENERIC0_CONT | | 109 | HDMI_GEN_PKT_CTRL_GENERIC0_CONT | |
| 119 | HDMI_GEN_PKT_CTRL_GENERIC0_UPDATE | | 110 | HDMI_GEN_PKT_CTRL_GENERIC0_UPDATE | |
| 120 | HDMI_GEN_PKT_CTRL_GENERIC0_LINE__MASK); | 111 | HDMI_GEN_PKT_CTRL_GENERIC0_LINE__MASK); |
| 121 | hdmi_write(hdmi, REG_HDMI_GEN_PKT_CTRL, val); | ||
| 122 | 112 | ||
| 123 | return 0; | 113 | return 0; |
| 124 | } | 114 | } |
| @@ -129,7 +119,6 @@ static int msm_hdmi_bridge_write_avi_infoframe(struct drm_bridge *bridge, · 4 unmodified lines | |||
| 129 | struct hdmi_bridge *hdmi_bridge = to_hdmi_bridge(bridge); | 119 | struct hdmi_bridge *hdmi_bridge = to_hdmi_bridge(bridge); |
| 130 | struct hdmi *hdmi = hdmi_bridge->hdmi; | 120 | struct hdmi *hdmi = hdmi_bridge->hdmi; |
| 131 | u32 buf[4] = {}; | 121 | u32 buf[4] = {}; |
| 132 | u32 val; | ||
| 133 | int i; | 122 | int i; |
| 134 | 123 | ||
| 135 | if (len != HDMI_INFOFRAME_SIZE(AVI) || len - 3 > sizeof(buf)) { | 124 | if (len != HDMI_INFOFRAME_SIZE(AVI) || len - 3 > sizeof(buf)) { |
| @@ -153,15 +142,13 @@ static int msm_hdmi_bridge_write_avi_infoframe(struct drm_bridge *bridge, · 17 unmodified lines | |||
| 153 | for (i = 0; i < ARRAY_SIZE(buf); i++) | 142 | for (i = 0; i < ARRAY_SIZE(buf); i++) |
| 154 | hdmi_write(hdmi, REG_HDMI_AVI_INFO(i), buf[i]); | 143 | hdmi_write(hdmi, REG_HDMI_AVI_INFO(i), buf[i]); |
| 155 | 144 | ||
| 156 | val = hdmi_read(hdmi, REG_HDMI_INFOFRAME_CTRL0); | 145 | hdmi_update_bits(hdmi, REG_HDMI_INFOFRAME_CTRL0, |
| 157 | val |= HDMI_INFOFRAME_CTRL0_AVI_SEND | | 146 | HDMI_INFOFRAME_CTRL0_AVI_SEND | HDMI_INFOFRAME_CTRL0_AVI_CONT, |
| 158 | HDMI_INFOFRAME_CTRL0_AVI_CONT; | 147 | HDMI_INFOFRAME_CTRL0_AVI_SEND | HDMI_INFOFRAME_CTRL0_AVI_CONT); |
| 159 | hdmi_write(hdmi, REG_HDMI_INFOFRAME_CTRL0, val); | ||
| 160 | 148 | ||
| 161 | val = hdmi_read(hdmi, REG_HDMI_INFOFRAME_CTRL1); | 149 | hdmi_update_bits(hdmi, REG_HDMI_INFOFRAME_CTRL1, |
| 162 | val &= ~HDMI_INFOFRAME_CTRL1_AVI_INFO_LINE__MASK; | 150 | HDMI_INFOFRAME_CTRL1_AVI_INFO_LINE__MASK, |
| 163 | val |= HDMI_INFOFRAME_CTRL1_AVI_INFO_LINE(AVI_IFRAME_LINE_NUMBER); | 151 | HDMI_INFOFRAME_CTRL1_AVI_INFO_LINE(AVI_IFRAME_LINE_NUMBER)); |
| 164 | hdmi_write(hdmi, REG_HDMI_INFOFRAME_CTRL1, val); | ||
| 165 | 152 | ||
| 166 | return 0; | 153 | return 0; |
| 167 | } | 154 | } |
| @@ -193,12 +180,11 @@ static int msm_hdmi_bridge_write_audio_infoframe(struct drm_bridge *bridge, · 25 unmodified lines | |||
| 193 | buffer[9] << 16 | | 180 | buffer[9] << 16 | |
| 194 | buffer[10] << 24); | 181 | buffer[10] << 24); |
| 195 | 182 | ||
| 196 | val = hdmi_read(hdmi, REG_HDMI_INFOFRAME_CTRL0); | 183 | val = HDMI_INFOFRAME_CTRL0_AUDIO_INFO_SEND | |
| 197 | val |= HDMI_INFOFRAME_CTRL0_AUDIO_INFO_SEND | | 184 | HDMI_INFOFRAME_CTRL0_AUDIO_INFO_CONT | |
| 198 | HDMI_INFOFRAME_CTRL0_AUDIO_INFO_CONT | | 185 | HDMI_INFOFRAME_CTRL0_AUDIO_INFO_SOURCE | |
| 199 | HDMI_INFOFRAME_CTRL0_AUDIO_INFO_SOURCE | | 186 | HDMI_INFOFRAME_CTRL0_AUDIO_INFO_UPDATE; |
| 200 | HDMI_INFOFRAME_CTRL0_AUDIO_INFO_UPDATE; | 187 | hdmi_update_bits(hdmi, REG_HDMI_INFOFRAME_CTRL0, val, val); |
| 201 | hdmi_write(hdmi, REG_HDMI_INFOFRAME_CTRL0, val); | ||
| 202 | 188 | ||
| 203 | return 0; | 189 | return 0; |
| 204 | } | 190 | } |
| @@ -231,11 +217,10 @@ static int msm_hdmi_bridge_write_spd_infoframe(struct drm_bridge *bridge, · 26 unmodified lines | |||
| 231 | for (i = 0; i < ARRAY_SIZE(buf); i++) | 217 | for (i = 0; i < ARRAY_SIZE(buf); i++) |
| 232 | hdmi_write(hdmi, REG_HDMI_GENERIC1(i), buf[i]); | 218 | hdmi_write(hdmi, REG_HDMI_GENERIC1(i), buf[i]); |
| 233 | 219 | ||
| 234 | val = hdmi_read(hdmi, REG_HDMI_GEN_PKT_CTRL); | 220 | val = HDMI_GEN_PKT_CTRL_GENERIC1_SEND | |
| 235 | val |= HDMI_GEN_PKT_CTRL_GENERIC1_SEND | | 221 | HDMI_GEN_PKT_CTRL_GENERIC1_CONT | |
| 236 | HDMI_GEN_PKT_CTRL_GENERIC1_CONT | | 222 | HDMI_GEN_PKT_CTRL_GENERIC1_LINE(SPD_IFRAME_LINE_NUMBER); |
| 237 | HDMI_GEN_PKT_CTRL_GENERIC1_LINE(SPD_IFRAME_LINE_NUMBER); | 223 | hdmi_update_bits(hdmi, REG_HDMI_GEN_PKT_CTRL, val, val); |
| 238 | hdmi_write(hdmi, REG_HDMI_GEN_PKT_CTRL, val); | ||
| 239 | 224 | ||
| 240 | return 0; | 225 | return 0; |
| 241 | } | 226 | } |
| @@ -269,12 +254,11 @@ static int msm_hdmi_bridge_write_hdmi_infoframe(struct drm_bridge *bridge, · 27 unmodified lines | |||
| 269 | for (i = 0; i < ARRAY_SIZE(buf); i++) | 254 | for (i = 0; i < ARRAY_SIZE(buf); i++) |
| 270 | hdmi_write(hdmi, REG_HDMI_GENERIC0(i), buf[i]); | 255 | hdmi_write(hdmi, REG_HDMI_GENERIC0(i), buf[i]); |
| 271 | 256 | ||
| 272 | val = hdmi_read(hdmi, REG_HDMI_GEN_PKT_CTRL); | 257 | val = HDMI_GEN_PKT_CTRL_GENERIC0_SEND | |
| 273 | val |= HDMI_GEN_PKT_CTRL_GENERIC0_SEND | | 258 | HDMI_GEN_PKT_CTRL_GENERIC0_CONT | |
| 274 | HDMI_GEN_PKT_CTRL_GENERIC0_CONT | | 259 | HDMI_GEN_PKT_CTRL_GENERIC0_UPDATE | |
| 275 | HDMI_GEN_PKT_CTRL_GENERIC0_UPDATE | | 260 | HDMI_GEN_PKT_CTRL_GENERIC0_LINE(VENSPEC_IFRAME_LINE_NUMBER); |
| 276 | HDMI_GEN_PKT_CTRL_GENERIC0_LINE(VENSPEC_IFRAME_LINE_NUMBER); | 261 | hdmi_update_bits(hdmi, REG_HDMI_GEN_PKT_CTRL, val, val); |
| 277 | hdmi_write(hdmi, REG_HDMI_GEN_PKT_CTRL, val); | ||
| 278 | 262 | ||
| 279 | return 0; | 263 | return 0; |
| 280 | } | 264 | } |
| @@ -306,9 +306,9 @@ static int msm_reset_hdcp_ddc_failures(struct hdmi_hdcp_ctrl *hdcp_ctrl) · 305 unmodified lines | |||
| 306 | HDMI_HDCP_DDC_CTRL_0_DISABLE); | 306 | HDMI_HDCP_DDC_CTRL_0_DISABLE); |
| 307 | 307 | ||
| 308 | /* ACK the Failure to Clear it */ | 308 | /* ACK the Failure to Clear it */ |
| 309 | reg_val = hdmi_read(hdmi, REG_HDMI_HDCP_DDC_CTRL_1); | 309 | hdmi_update_bits(hdmi, REG_HDMI_HDCP_DDC_CTRL_1, |
| 310 | reg_val |= HDMI_HDCP_DDC_CTRL_1_FAILED_ACK; | 310 | HDMI_HDCP_DDC_CTRL_1_FAILED_ACK, |
| 311 | hdmi_write(hdmi, REG_HDMI_HDCP_DDC_CTRL_1, reg_val); | 311 | HDMI_HDCP_DDC_CTRL_1_FAILED_ACK); |
| 312 | 312 | ||
| 313 | /* Check if the FAILURE got Cleared */ | 313 | /* Check if the FAILURE got Cleared */ |
| 314 | reg_val = hdmi_read(hdmi, REG_HDMI_HDCP_DDC_STATUS); | 314 | reg_val = hdmi_read(hdmi, REG_HDMI_HDCP_DDC_STATUS); |
| @@ -324,28 +324,22 @@ static int msm_reset_hdcp_ddc_failures(struct hdmi_hdcp_ctrl *hdcp_ctrl) · 9 unmodified lines | |||
| 324 | DBG("Before: HDMI_DDC_SW_STATUS=0x%08x", | 324 | DBG("Before: HDMI_DDC_SW_STATUS=0x%08x", |
| 325 | hdmi_read(hdmi, REG_HDMI_DDC_SW_STATUS)); | 325 | hdmi_read(hdmi, REG_HDMI_DDC_SW_STATUS)); |
| 326 | /* Reset HDMI DDC software status */ | 326 | /* Reset HDMI DDC software status */ |
| 327 | reg_val = hdmi_read(hdmi, REG_HDMI_DDC_CTRL); | 327 | hdmi_update_bits(hdmi, REG_HDMI_DDC_CTRL, HDMI_DDC_CTRL_SW_STATUS_RESET, |
| 328 | reg_val |= HDMI_DDC_CTRL_SW_STATUS_RESET; | 328 | HDMI_DDC_CTRL_SW_STATUS_RESET); |
| 329 | hdmi_write(hdmi, REG_HDMI_DDC_CTRL, reg_val); | ||
| 330 | 329 | ||
| 331 | rc = msm_hdmi_hdcp_msleep(hdcp_ctrl, 20, AUTH_ABORT_EV); | 330 | rc = msm_hdmi_hdcp_msleep(hdcp_ctrl, 20, AUTH_ABORT_EV); |
| 332 | 331 | ||
| 333 | reg_val = hdmi_read(hdmi, REG_HDMI_DDC_CTRL); | 332 | hdmi_clear_bits(hdmi, REG_HDMI_DDC_CTRL, HDMI_DDC_CTRL_SW_STATUS_RESET); |
| 334 | reg_val &= ~HDMI_DDC_CTRL_SW_STATUS_RESET; | ||
| 335 | hdmi_write(hdmi, REG_HDMI_DDC_CTRL, reg_val); | ||
| 336 | 333 | ||
| 337 | /* Reset HDMI DDC Controller */ | 334 | /* Reset HDMI DDC Controller */ |
| 338 | reg_val = hdmi_read(hdmi, REG_HDMI_DDC_CTRL); | 335 | hdmi_update_bits(hdmi, REG_HDMI_DDC_CTRL, HDMI_DDC_CTRL_SOFT_RESET, |
| 339 | reg_val |= HDMI_DDC_CTRL_SOFT_RESET; | 336 | HDMI_DDC_CTRL_SOFT_RESET); |
| 340 | hdmi_write(hdmi, REG_HDMI_DDC_CTRL, reg_val); | ||
| 341 | 337 | ||
| 342 | /* If previous msleep is aborted, skip this msleep */ | 338 | /* If previous msleep is aborted, skip this msleep */ |
| 343 | if (!rc) | 339 | if (!rc) |
| 344 | rc = msm_hdmi_hdcp_msleep(hdcp_ctrl, 20, AUTH_ABORT_EV); | 340 | rc = msm_hdmi_hdcp_msleep(hdcp_ctrl, 20, AUTH_ABORT_EV); |
| 345 | 341 | ||
| 346 | reg_val = hdmi_read(hdmi, REG_HDMI_DDC_CTRL); | 342 | hdmi_clear_bits(hdmi, REG_HDMI_DDC_CTRL, HDMI_DDC_CTRL_SOFT_RESET); |
| 347 | reg_val &= ~HDMI_DDC_CTRL_SOFT_RESET; | ||
| 348 | hdmi_write(hdmi, REG_HDMI_DDC_CTRL, reg_val); | ||
| 349 | DBG("After: HDMI_DDC_SW_STATUS=0x%08x", | 343 | DBG("After: HDMI_DDC_SW_STATUS=0x%08x", |
| 350 | hdmi_read(hdmi, REG_HDMI_DDC_SW_STATUS)); | 344 | hdmi_read(hdmi, REG_HDMI_DDC_SW_STATUS)); |
| 351 | } | 345 | } |
| @@ -399,7 +393,6 @@ static void msm_hdmi_hdcp_reauth_work(struct work_struct *work) · 47 unmodified lines | |||
| 399 | struct hdmi_hdcp_ctrl, hdcp_reauth_work); | 393 | struct hdmi_hdcp_ctrl, hdcp_reauth_work); |
| 400 | struct hdmi *hdmi = hdcp_ctrl->hdmi; | 394 | struct hdmi *hdmi = hdcp_ctrl->hdmi; |
| 401 | unsigned long flags; | 395 | unsigned long flags; |
| 402 | u32 reg_val; | ||
| 403 | 396 | ||
| 404 | DBG("HDCP REAUTH WORK"); | 397 | DBG("HDCP REAUTH WORK"); |
| 405 | /* | 398 | /* |
| @@ -409,9 +402,7 @@ static void msm_hdmi_hdcp_reauth_work(struct work_struct *work) · 3 unmodified lines | |||
| 409 | * AN1_READY bits in HDMI_HDCP_LINK0_STATUS register | 402 | * AN1_READY bits in HDMI_HDCP_LINK0_STATUS register |
| 410 | */ | 403 | */ |
| 411 | spin_lock_irqsave(&hdmi->reg_lock, flags); | 404 | spin_lock_irqsave(&hdmi->reg_lock, flags); |
| 412 | reg_val = hdmi_read(hdmi, REG_HDMI_HPD_CTRL); | 405 | hdmi_clear_bits(hdmi, REG_HDMI_HPD_CTRL, HDMI_HPD_CTRL_ENABLE); |
| 413 | reg_val &= ~HDMI_HPD_CTRL_ENABLE; | ||
| 414 | hdmi_write(hdmi, REG_HDMI_HPD_CTRL, reg_val); | ||
| 415 | 406 | ||
| 416 | /* Disable HDCP interrupts */ | 407 | /* Disable HDCP interrupts */ |
| 417 | hdmi_write(hdmi, REG_HDMI_HDCP_INT_CTRL, 0); | 408 | hdmi_write(hdmi, REG_HDMI_HDCP_INT_CTRL, 0); |
| @@ -431,9 +422,8 @@ static void msm_hdmi_hdcp_reauth_work(struct work_struct *work) · 13 unmodified lines | |||
| 431 | 422 | ||
| 432 | /* Enable HPD circuitry */ | 423 | /* Enable HPD circuitry */ |
| 433 | spin_lock_irqsave(&hdmi->reg_lock, flags); | 424 | spin_lock_irqsave(&hdmi->reg_lock, flags); |
| 434 | reg_val = hdmi_read(hdmi, REG_HDMI_HPD_CTRL); | 425 | hdmi_update_bits(hdmi, REG_HDMI_HPD_CTRL, HDMI_HPD_CTRL_ENABLE, |
| 435 | reg_val |= HDMI_HPD_CTRL_ENABLE; | 426 | HDMI_HPD_CTRL_ENABLE); |
| 436 | hdmi_write(hdmi, REG_HDMI_HPD_CTRL, reg_val); | ||
| 437 | spin_unlock_irqrestore(&hdmi->reg_lock, flags); | 427 | spin_unlock_irqrestore(&hdmi->reg_lock, flags); |
| 438 | 428 | ||
| 439 | /* | 429 | /* |
| @@ -456,7 +446,6 @@ static int msm_hdmi_hdcp_auth_prepare(struct hdmi_hdcp_ctrl *hdcp_ctrl) · 16 unmodified lines | |||
| 456 | { | 446 | { |
| 457 | struct hdmi *hdmi = hdcp_ctrl->hdmi; | 447 | struct hdmi *hdmi = hdcp_ctrl->hdmi; |
| 458 | u32 link0_status; | 448 | u32 link0_status; |
| 459 | u32 reg_val; | ||
| 460 | unsigned long flags; | 449 | unsigned long flags; |
| 461 | int rc; | 450 | int rc; |
| 462 | 451 | ||
| @@ -472,14 +461,11 @@ static int msm_hdmi_hdcp_auth_prepare(struct hdmi_hdcp_ctrl *hdcp_ctrl) · 9 unmodified lines | |||
| 472 | 461 | ||
| 473 | spin_lock_irqsave(&hdmi->reg_lock, flags); | 462 | spin_lock_irqsave(&hdmi->reg_lock, flags); |
| 474 | /* disable HDMI Encrypt */ | 463 | /* disable HDMI Encrypt */ |
| 475 | reg_val = hdmi_read(hdmi, REG_HDMI_CTRL); | 464 | hdmi_clear_bits(hdmi, REG_HDMI_CTRL, HDMI_CTRL_ENCRYPTED); |
| 476 | reg_val &= ~HDMI_CTRL_ENCRYPTED; | ||
| 477 | hdmi_write(hdmi, REG_HDMI_CTRL, reg_val); | ||
| 478 | 465 | ||
| 479 | /* Enabling Software DDC */ | 466 | /* Enabling Software DDC */ |
| 480 | reg_val = hdmi_read(hdmi, REG_HDMI_DDC_ARBITRATION); | 467 | hdmi_clear_bits(hdmi, REG_HDMI_DDC_ARBITRATION, |
| 481 | reg_val &= ~HDMI_DDC_ARBITRATION_HW_ARBITRATION; | 468 | HDMI_DDC_ARBITRATION_HW_ARBITRATION); |
| 482 | hdmi_write(hdmi, REG_HDMI_DDC_ARBITRATION, reg_val); | ||
| 483 | spin_unlock_irqrestore(&hdmi->reg_lock, flags); | 469 | spin_unlock_irqrestore(&hdmi->reg_lock, flags); |
| 484 | 470 | ||
| 485 | /* | 471 | /* |
| @@ -498,9 +484,8 @@ static int msm_hdmi_hdcp_auth_prepare(struct hdmi_hdcp_ctrl *hdcp_ctrl) · 12 unmodified lines | |||
| 498 | hdmi_write(hdmi, REG_HDMI_HDCP_ENTROPY_CTRL1, 0xF00DFACE); | 484 | hdmi_write(hdmi, REG_HDMI_HDCP_ENTROPY_CTRL1, 0xF00DFACE); |
| 499 | 485 | ||
| 500 | /* Disable the RngCipher state */ | 486 | /* Disable the RngCipher state */ |
| 501 | reg_val = hdmi_read(hdmi, REG_HDMI_HDCP_DEBUG_CTRL); | 487 | hdmi_clear_bits(hdmi, REG_HDMI_HDCP_DEBUG_CTRL, |
| 502 | reg_val &= ~HDMI_HDCP_DEBUG_CTRL_RNG_CIPHER; | 488 | HDMI_HDCP_DEBUG_CTRL_RNG_CIPHER); |
| 503 | hdmi_write(hdmi, REG_HDMI_HDCP_DEBUG_CTRL, reg_val); | ||
| 504 | DBG("HDCP_DEBUG_CTRL=0x%08x", | 489 | DBG("HDCP_DEBUG_CTRL=0x%08x", |
| 505 | hdmi_read(hdmi, REG_HDMI_HDCP_DEBUG_CTRL)); | 490 | hdmi_read(hdmi, REG_HDMI_HDCP_DEBUG_CTRL)); |
| 506 | 491 | ||
| @@ -537,15 +522,12 @@ static int msm_hdmi_hdcp_auth_prepare(struct hdmi_hdcp_ctrl *hdcp_ctrl) · 30 unmodified lines | |||
| 537 | static void msm_hdmi_hdcp_auth_fail(struct hdmi_hdcp_ctrl *hdcp_ctrl) | 522 | static void msm_hdmi_hdcp_auth_fail(struct hdmi_hdcp_ctrl *hdcp_ctrl) |
| 538 | { | 523 | { |
| 539 | struct hdmi *hdmi = hdcp_ctrl->hdmi; | 524 | struct hdmi *hdmi = hdcp_ctrl->hdmi; |
| 540 | u32 reg_val; | ||
| 541 | unsigned long flags; | 525 | unsigned long flags; |
| 542 | 526 | ||
| 543 | DBG("hdcp auth failed, queue reauth work"); | 527 | DBG("hdcp auth failed, queue reauth work"); |
| 544 | /* clear HDMI Encrypt */ | 528 | /* clear HDMI Encrypt */ |
| 545 | spin_lock_irqsave(&hdmi->reg_lock, flags); | 529 | spin_lock_irqsave(&hdmi->reg_lock, flags); |
| 546 | reg_val = hdmi_read(hdmi, REG_HDMI_CTRL); | 530 | hdmi_clear_bits(hdmi, REG_HDMI_CTRL, HDMI_CTRL_ENCRYPTED); |
| 547 | reg_val &= ~HDMI_CTRL_ENCRYPTED; | ||
| 548 | hdmi_write(hdmi, REG_HDMI_CTRL, reg_val); | ||
| 549 | spin_unlock_irqrestore(&hdmi->reg_lock, flags); | 531 | spin_unlock_irqrestore(&hdmi->reg_lock, flags); |
| 550 | 532 | ||
| 551 | hdcp_ctrl->hdcp_state = HDCP_STATE_AUTH_FAILED; | 533 | hdcp_ctrl->hdcp_state = HDCP_STATE_AUTH_FAILED; |
| @@ -555,7 +537,6 @@ static void msm_hdmi_hdcp_auth_fail(struct hdmi_hdcp_ctrl *hdcp_ctrl) · 3 unmodified lines | |||
| 555 | static void msm_hdmi_hdcp_auth_done(struct hdmi_hdcp_ctrl *hdcp_ctrl) | 537 | static void msm_hdmi_hdcp_auth_done(struct hdmi_hdcp_ctrl *hdcp_ctrl) |
| 556 | { | 538 | { |
| 557 | struct hdmi *hdmi = hdcp_ctrl->hdmi; | 539 | struct hdmi *hdmi = hdcp_ctrl->hdmi; |
| 558 | u32 reg_val; | ||
| 559 | unsigned long flags; | 540 | unsigned long flags; |
| 560 | 541 | ||
| 561 | /* | 542 | /* |
| @@ -563,16 +544,15 @@ static void msm_hdmi_hdcp_auth_done(struct hdmi_hdcp_ctrl *hdcp_ctrl) · 1 unmodified line | |||
| 563 | * there is no Arbitration between software and hardware for DDC | 544 | * there is no Arbitration between software and hardware for DDC |
| 564 | */ | 545 | */ |
| 565 | spin_lock_irqsave(&hdmi->reg_lock, flags); | 546 | spin_lock_irqsave(&hdmi->reg_lock, flags); |
| 566 | reg_val = hdmi_read(hdmi, REG_HDMI_DDC_ARBITRATION); | 547 | hdmi_update_bits(hdmi, REG_HDMI_DDC_ARBITRATION, |
| 567 | reg_val |= HDMI_DDC_ARBITRATION_HW_ARBITRATION; | 548 | HDMI_DDC_ARBITRATION_HW_ARBITRATION, |
| 568 | hdmi_write(hdmi, REG_HDMI_DDC_ARBITRATION, reg_val); | 549 | HDMI_DDC_ARBITRATION_HW_ARBITRATION); |
| 569 | spin_unlock_irqrestore(&hdmi->reg_lock, flags); | 550 | spin_unlock_irqrestore(&hdmi->reg_lock, flags); |
| 570 | 551 | ||
| 571 | /* enable HDMI Encrypt */ | 552 | /* enable HDMI Encrypt */ |
| 572 | spin_lock_irqsave(&hdmi->reg_lock, flags); | 553 | spin_lock_irqsave(&hdmi->reg_lock, flags); |
| 573 | reg_val = hdmi_read(hdmi, REG_HDMI_CTRL); | 554 | hdmi_update_bits(hdmi, REG_HDMI_CTRL, HDMI_CTRL_ENCRYPTED, |
| 574 | reg_val |= HDMI_CTRL_ENCRYPTED; | 555 | HDMI_CTRL_ENCRYPTED); |
| 575 | hdmi_write(hdmi, REG_HDMI_CTRL, reg_val); | ||
| 576 | spin_unlock_irqrestore(&hdmi->reg_lock, flags); | 556 | spin_unlock_irqrestore(&hdmi->reg_lock, flags); |
| 577 | 557 | ||
| 578 | hdcp_ctrl->hdcp_state = HDCP_STATE_AUTHENTICATED; | 558 | hdcp_ctrl->hdcp_state = HDCP_STATE_AUTHENTICATED; |
| @@ -1304,7 +1284,6 @@ end: · 725 unmodified lines | |||
| 1304 | void msm_hdmi_hdcp_on(struct hdmi_hdcp_ctrl *hdcp_ctrl) | 1284 | void msm_hdmi_hdcp_on(struct hdmi_hdcp_ctrl *hdcp_ctrl) |
| 1305 | { | 1285 | { |
| 1306 | struct hdmi *hdmi = hdcp_ctrl->hdmi; | 1286 | struct hdmi *hdmi = hdcp_ctrl->hdmi; |
| 1307 | u32 reg_val; | ||
| 1308 | unsigned long flags; | 1287 | unsigned long flags; |
| 1309 | 1288 | ||
| 1310 | if ((HDCP_STATE_INACTIVE != hdcp_ctrl->hdcp_state) || | 1289 | if ((HDCP_STATE_INACTIVE != hdcp_ctrl->hdcp_state) || |
| @@ -1315,9 +1294,7 @@ void msm_hdmi_hdcp_on(struct hdmi_hdcp_ctrl *hdcp_ctrl) · 4 unmodified lines | |||
| 1315 | 1294 | ||
| 1316 | /* clear HDMI Encrypt */ | 1295 | /* clear HDMI Encrypt */ |
| 1317 | spin_lock_irqsave(&hdmi->reg_lock, flags); | 1296 | spin_lock_irqsave(&hdmi->reg_lock, flags); |
| 1318 | reg_val = hdmi_read(hdmi, REG_HDMI_CTRL); | 1297 | hdmi_clear_bits(hdmi, REG_HDMI_CTRL, HDMI_CTRL_ENCRYPTED); |
| 1319 | reg_val &= ~HDMI_CTRL_ENCRYPTED; | ||
| 1320 | hdmi_write(hdmi, REG_HDMI_CTRL, reg_val); | ||
| 1321 | spin_unlock_irqrestore(&hdmi->reg_lock, flags); | 1298 | spin_unlock_irqrestore(&hdmi->reg_lock, flags); |
| 1322 | 1299 | ||
| 1323 | hdcp_ctrl->auth_event = 0; | 1300 | hdcp_ctrl->auth_event = 0; |
| @@ -1330,7 +1307,6 @@ void msm_hdmi_hdcp_off(struct hdmi_hdcp_ctrl *hdcp_ctrl) · 6 unmodified lines | |||
| 1330 | { | 1307 | { |
| 1331 | struct hdmi *hdmi = hdcp_ctrl->hdmi; | 1308 | struct hdmi *hdmi = hdcp_ctrl->hdmi; |
| 1332 | unsigned long flags; | 1309 | unsigned long flags; |
| 1333 | u32 reg_val; | ||
| 1334 | 1310 | ||
| 1335 | if ((HDCP_STATE_INACTIVE == hdcp_ctrl->hdcp_state) || | 1311 | if ((HDCP_STATE_INACTIVE == hdcp_ctrl->hdcp_state) || |
| 1336 | (HDCP_STATE_NO_AKSV == hdcp_ctrl->hdcp_state)) { | 1312 | (HDCP_STATE_NO_AKSV == hdcp_ctrl->hdcp_state)) { |
| @@ -1345,9 +1321,7 @@ void msm_hdmi_hdcp_off(struct hdmi_hdcp_ctrl *hdcp_ctrl) · 8 unmodified lines | |||
| 1345 | * AN1_READY bits in HDMI_HDCP_LINK0_STATUS register | 1321 | * AN1_READY bits in HDMI_HDCP_LINK0_STATUS register |
| 1346 | */ | 1322 | */ |
| 1347 | spin_lock_irqsave(&hdmi->reg_lock, flags); | 1323 | spin_lock_irqsave(&hdmi->reg_lock, flags); |
| 1348 | reg_val = hdmi_read(hdmi, REG_HDMI_HPD_CTRL); | 1324 | hdmi_clear_bits(hdmi, REG_HDMI_HPD_CTRL, HDMI_HPD_CTRL_ENABLE); |
| 1349 | reg_val &= ~HDMI_HPD_CTRL_ENABLE; | ||
| 1350 | hdmi_write(hdmi, REG_HDMI_HPD_CTRL, reg_val); | ||
| 1351 | 1325 | ||
| 1352 | /* | 1326 | /* |
| 1353 | * Disable HDCP interrupts. | 1327 | * Disable HDCP interrupts. |
| @@ -1375,14 +1349,11 @@ void msm_hdmi_hdcp_off(struct hdmi_hdcp_ctrl *hdcp_ctrl) · 21 unmodified lines | |||
| 1375 | hdmi_write(hdmi, REG_HDMI_HDCP_CTRL, 0); | 1349 | hdmi_write(hdmi, REG_HDMI_HDCP_CTRL, 0); |
| 1376 | 1350 | ||
| 1377 | spin_lock_irqsave(&hdmi->reg_lock, flags); | 1351 | spin_lock_irqsave(&hdmi->reg_lock, flags); |
| 1378 | reg_val = hdmi_read(hdmi, REG_HDMI_CTRL); | 1352 | hdmi_clear_bits(hdmi, REG_HDMI_CTRL, HDMI_CTRL_ENCRYPTED); |
| 1379 | reg_val &= ~HDMI_CTRL_ENCRYPTED; | ||
| 1380 | hdmi_write(hdmi, REG_HDMI_CTRL, reg_val); | ||
| 1381 | 1353 | ||
| 1382 | /* Enable HPD circuitry */ | 1354 | /* Enable HPD circuitry */ |
| 1383 | reg_val = hdmi_read(hdmi, REG_HDMI_HPD_CTRL); | 1355 | hdmi_update_bits(hdmi, REG_HDMI_HPD_CTRL, HDMI_HPD_CTRL_ENABLE, |
| 1384 | reg_val |= HDMI_HPD_CTRL_ENABLE; | 1356 | HDMI_HPD_CTRL_ENABLE); |
| 1385 | hdmi_write(hdmi, REG_HDMI_HPD_CTRL, reg_val); | ||
| 1386 | spin_unlock_irqrestore(&hdmi->reg_lock, flags); | 1357 | spin_unlock_irqrestore(&hdmi->reg_lock, flags); |
| 1387 | 1358 | ||
| 1388 | hdcp_ctrl->hdcp_state = HDCP_STATE_INACTIVE; | 1359 | hdcp_ctrl->hdcp_state = HDCP_STATE_INACTIVE; |
| @@ -222,20 +222,21 @@ static void load_gpu(struct drm_device *dev) · 221 unmodified lines | |||
| 222 | */ | 222 | */ |
| 223 | struct drm_gpuvm *msm_context_vm(struct drm_device *dev, struct msm_context *ctx) | 223 | struct drm_gpuvm *msm_context_vm(struct drm_device *dev, struct msm_context *ctx) |
| 224 | { | 224 | { |
| 225 | static DEFINE_MUTEX(init_lock); | ||
| 226 | struct msm_drm_private *priv = dev->dev_private; | 225 | struct msm_drm_private *priv = dev->dev_private; |
| 226 | struct drm_gpuvm *vm = smp_load_acquire(&ctx->vm); | ||
| 227 | 227 | ||
| 228 | /* Once ctx->vm is created it is valid for the lifetime of the context: */ | 228 | /* Once ctx->vm is created it is valid for the lifetime of the context: */ |
| 229 | if (ctx->vm) | 229 | if (vm) |
| 230 | return ctx->vm; | 230 | return vm; |
| 231 | |||
| 232 | guard(rwsem_write)(&ctx->ctxlock); | ||
| 231 | 233 | ||
| 232 | mutex_lock(&init_lock); | ||
| 233 | if (!ctx->vm) { | 234 | if (!ctx->vm) { |
| 234 | ctx->vm = msm_gpu_create_private_vm( | 235 | vm = msm_gpu_create_private_vm( |
| 235 | priv->gpu, current, !ctx->userspace_managed_vm); | 236 | priv->gpu, current, !ctx->userspace_managed_vm); |
| 236 | 237 | if (!IS_ERR_OR_NULL(vm)) | |
| 238 | smp_store_release(&ctx->vm, vm); | ||
| 237 | } | 239 | } |
| 238 | mutex_unlock(&init_lock); | ||
| 239 | 240 | ||
| 240 | return ctx->vm; | 241 | return ctx->vm; |
| 241 | } | 242 | } |
| @@ -250,7 +251,7 @@ static int context_init(struct drm_device *dev, struct drm_file *file) · 8 unmodified lines | |||
| 250 | return -ENOMEM; | 251 | return -ENOMEM; |
| 251 | 252 | ||
| 252 | INIT_LIST_HEAD(&ctx->submitqueues); | 253 | INIT_LIST_HEAD(&ctx->submitqueues); |
| 253 | rwlock_init(&ctx->queuelock); | 254 | init_rwsem(&ctx->ctxlock); |
| 254 | 255 | ||
| 255 | kref_init(&ctx->ref); | 256 | kref_init(&ctx->ref); |
| 256 | msm_submitqueue_init(dev, ctx); | 257 | msm_submitqueue_init(dev, ctx); |
| @@ -422,10 +423,14 @@ static int msm_ioctl_gem_info_iova(struct drm_device *dev, · 165 unmodified lines | |||
| 422 | { | 423 | { |
| 423 | struct msm_drm_private *priv = dev->dev_private; | 424 | struct msm_drm_private *priv = dev->dev_private; |
| 424 | struct msm_context *ctx = file->driver_priv; | 425 | struct msm_context *ctx = file->driver_priv; |
| 426 | struct drm_gpuvm *vm = msm_context_vm(dev, ctx); | ||
| 425 | 427 | ||
| 426 | if (!priv->gpu) | 428 | if (!priv->gpu) |
| 427 | return -EINVAL; | 429 | return -EINVAL; |
| 428 | 430 | ||
| 431 | if (!vm) | ||
| 432 | return UERR(ENOMEM, dev, "no VM"); | ||
| 433 | |||
| 429 | if (msm_context_is_vmbind(ctx)) | 434 | if (msm_context_is_vmbind(ctx)) |
| 430 | return UERR(EINVAL, dev, "VM_BIND is enabled"); | 435 | return UERR(EINVAL, dev, "VM_BIND is enabled"); |
| 431 | 436 | ||
| @@ -436,7 +441,7 @@ static int msm_ioctl_gem_info_iova(struct drm_device *dev, · 4 unmodified lines | |||
| 436 | * Don't pin the memory here - just get an address so that userspace can | 441 | * Don't pin the memory here - just get an address so that userspace can |
| 437 | * be productive | 442 | * be productive |
| 438 | */ | 443 | */ |
| 439 | return msm_gem_get_iova(obj, msm_context_vm(dev, ctx), iova); | 444 | return msm_gem_get_iova(obj, vm, iova); |
| 440 | } | 445 | } |
| 441 | 446 | ||
| 442 | static int msm_ioctl_gem_info_set_iova(struct drm_device *dev, | 447 | static int msm_ioctl_gem_info_set_iova(struct drm_device *dev, |
| @@ -450,6 +455,9 @@ static int msm_ioctl_gem_info_set_iova(struct drm_device *dev, · 7 unmodified lines | |||
| 450 | if (!priv->gpu) | 455 | if (!priv->gpu) |
| 451 | return -EINVAL; | 456 | return -EINVAL; |
| 452 | 457 | ||
| 458 | if (!vm) | ||
| 459 | return UERR(ENOMEM, dev, "no VM"); | ||
| 460 | |||
| 453 | if (msm_context_is_vmbind(ctx)) | 461 | if (msm_context_is_vmbind(ctx)) |
| 454 | return UERR(EINVAL, dev, "VM_BIND is enabled"); | 462 | return UERR(EINVAL, dev, "VM_BIND is enabled"); |
| 455 | 463 | ||
| @@ -261,8 +261,6 @@ const struct msm_format *msm_framebuffer_format(struct drm_framebuffer *fb); · 260 unmodified lines | |||
| 261 | struct drm_framebuffer *msm_framebuffer_create(struct drm_device *dev, | 261 | struct drm_framebuffer *msm_framebuffer_create(struct drm_device *dev, |
| 262 | struct drm_file *file, const struct drm_format_info *info, | 262 | struct drm_file *file, const struct drm_format_info *info, |
| 263 | const struct drm_mode_fb_cmd2 *mode_cmd); | 263 | const struct drm_mode_fb_cmd2 *mode_cmd); |
| 264 | struct drm_framebuffer * msm_alloc_stolen_fb(struct drm_device *dev, | ||
| 265 | int w, int h, int p, uint32_t format); | ||
| 266 | 264 | ||
| 267 | #ifdef CONFIG_DRM_MSM_KMS_FBDEV | 265 | #ifdef CONFIG_DRM_MSM_KMS_FBDEV |
| 268 | int msm_fbdev_driver_fbdev_probe(struct drm_fb_helper *helper, | 266 | int msm_fbdev_driver_fbdev_probe(struct drm_fb_helper *helper, |
| @@ -356,8 +354,6 @@ void __exit msm_dp_unregister(void); · 87 unmodified lines | |||
| 356 | int msm_dp_modeset_init(struct msm_dp *dp_display, struct drm_device *dev, | 354 | int msm_dp_modeset_init(struct msm_dp *dp_display, struct drm_device *dev, |
| 357 | struct drm_encoder *encoder, bool yuv_supported); | 355 | struct drm_encoder *encoder, bool yuv_supported); |
| 358 | void msm_dp_snapshot(struct msm_disp_state *disp_state, struct msm_dp *dp_display); | 356 | void msm_dp_snapshot(struct msm_disp_state *disp_state, struct msm_dp *dp_display); |
| 359 | bool msm_dp_is_yuv_420_enabled(const struct msm_dp *dp_display, | ||
| 360 | const struct drm_display_mode *mode); | ||
| 361 | bool msm_dp_needs_periph_flush(const struct msm_dp *dp_display, | 357 | bool msm_dp_needs_periph_flush(const struct msm_dp *dp_display, |
| 362 | const struct drm_display_mode *mode); | 358 | const struct drm_display_mode *mode); |
| 363 | bool msm_dp_wide_bus_available(const struct msm_dp *dp_display); | 359 | bool msm_dp_wide_bus_available(const struct msm_dp *dp_display); |
| @@ -382,12 +378,6 @@ static inline void msm_dp_snapshot(struct msm_disp_state *disp_state, struct msm · 18 unmodified lines | |||
| 382 | { | 378 | { |
| 383 | } | 379 | } |
| 384 | 380 | ||
| 385 | static inline bool msm_dp_is_yuv_420_enabled(const struct msm_dp *dp_display, | ||
| 386 | const struct drm_display_mode *mode) | ||
| 387 | { | ||
| 388 | return false; | ||
| 389 | } | ||
| 390 | |||
| 391 | static inline bool msm_dp_needs_periph_flush(const struct msm_dp *dp_display, | 381 | static inline bool msm_dp_needs_periph_flush(const struct msm_dp *dp_display, |
| 392 | const struct drm_display_mode *mode) | 382 | const struct drm_display_mode *mode) |
| 393 | { | 383 | { |
| @@ -503,13 +493,6 @@ void msm_hrtimer_work_init(struct msm_hrtimer_work *work, · 109 unmodified lines | |||
| 503 | #define DBG(fmt, ...) DRM_DEBUG_DRIVER(fmt"\n", ##__VA_ARGS__) | 493 | #define DBG(fmt, ...) DRM_DEBUG_DRIVER(fmt"\n", ##__VA_ARGS__) |
| 504 | #define VERB(fmt, ...) if (0) DRM_DEBUG_DRIVER(fmt"\n", ##__VA_ARGS__) | 494 | #define VERB(fmt, ...) if (0) DRM_DEBUG_DRIVER(fmt"\n", ##__VA_ARGS__) |
| 505 | 495 | ||
| 506 | static inline int align_pitch(int width, int bpp) | ||
| 507 | { | ||
| 508 | int bytespp = (bpp + 7) / 8; | ||
| 509 | /* adreno needs pitch aligned to 32 pixels: */ | ||
| 510 | return bytespp * ALIGN(width, 32); | ||
| 511 | } | ||
| 512 | |||
| 513 | /* for the generated headers: */ | 496 | /* for the generated headers: */ |
| 514 | #define INVALID_IDX(idx) ({BUG(); 0;}) | 497 | #define INVALID_IDX(idx) ({BUG(); 0;}) |
| 515 | #define fui(x) ({BUG(); 0;}) | 498 | #define fui(x) ({BUG(); 0;}) |
| @@ -6,7 +6,6 @@ · 5 unmodified lines | |||
| 6 | 6 | ||
| 7 | #include <drm/drm_crtc.h> | 7 | #include <drm/drm_crtc.h> |
| 8 | #include <drm/drm_damage_helper.h> | 8 | #include <drm/drm_damage_helper.h> |
| 9 | #include <drm/drm_file.h> | ||
| 10 | #include <drm/drm_fourcc.h> | 9 | #include <drm/drm_fourcc.h> |
| 11 | #include <drm/drm_framebuffer.h> | 10 | #include <drm/drm_framebuffer.h> |
| 12 | #include <drm/drm_gem_framebuffer_helper.h> | 11 | #include <drm/drm_gem_framebuffer_helper.h> |
| @@ -29,10 +28,6 @@ struct msm_framebuffer { · 16 unmodified lines | |||
| 29 | }; | 28 | }; |
| 30 | #define to_msm_framebuffer(x) container_of(x, struct msm_framebuffer, base) | 29 | #define to_msm_framebuffer(x) container_of(x, struct msm_framebuffer, base) |
| 31 | 30 | ||
| 32 | static struct drm_framebuffer *msm_framebuffer_init(struct drm_device *dev, | ||
| 33 | const struct drm_format_info *info, | ||
| 34 | const struct drm_mode_fb_cmd2 *mode_cmd, struct drm_gem_object **bos); | ||
| 35 | |||
| 36 | static int msm_framebuffer_dirtyfb(struct drm_framebuffer *fb, | 31 | static int msm_framebuffer_dirtyfb(struct drm_framebuffer *fb, |
| 37 | struct drm_file *file_priv, unsigned int flags, | 32 | struct drm_file *file_priv, unsigned int flags, |
| 38 | unsigned int color, struct drm_clip_rect *clips, | 33 | unsigned int color, struct drm_clip_rect *clips, |
| @@ -139,39 +134,10 @@ const struct msm_format *msm_framebuffer_format(struct drm_framebuffer *fb) · 100 unmodified lines | |||
| 139 | return msm_fb->format; | 134 | return msm_fb->format; |
| 140 | } | 135 | } |
| 141 | 136 | ||
| 142 | struct drm_framebuffer *msm_framebuffer_create(struct drm_device *dev, | 137 | static struct drm_framebuffer * |
| 143 | struct drm_file *file, const struct drm_format_info *info, | 138 | msm_framebuffer_init(struct drm_device *dev, const struct drm_format_info *info, |
| 144 | const struct drm_mode_fb_cmd2 *mode_cmd) | 139 | const struct drm_mode_fb_cmd2 *mode_cmd, |
| 145 | { | 140 | struct drm_gem_object **bos) |
| 146 | struct drm_gem_object *bos[4] = {0}; | ||
| 147 | struct drm_framebuffer *fb; | ||
| 148 | int ret, i, n = info->num_planes; | ||
| 149 | |||
| 150 | for (i = 0; i < n; i++) { | ||
| 151 | bos[i] = drm_gem_object_lookup(file, mode_cmd->handles[i]); | ||
| 152 | if (!bos[i]) { | ||
| 153 | ret = -ENXIO; | ||
| 154 | goto out_unref; | ||
| 155 | } | ||
| 156 | } | ||
| 157 | |||
| 158 | fb = msm_framebuffer_init(dev, info, mode_cmd, bos); | ||
| 159 | if (IS_ERR(fb)) { | ||
| 160 | ret = PTR_ERR(fb); | ||
| 161 | goto out_unref; | ||
| 162 | } | ||
| 163 | |||
| 164 | return fb; | ||
| 165 | |||
| 166 | out_unref: | ||
| 167 | for (i = 0; i < n; i++) | ||
| 168 | drm_gem_object_put(bos[i]); | ||
| 169 | return ERR_PTR(ret); | ||
| 170 | } | ||
| 171 | |||
| 172 | static struct drm_framebuffer *msm_framebuffer_init(struct drm_device *dev, | ||
| 173 | const struct drm_format_info *info, | ||
| 174 | const struct drm_mode_fb_cmd2 *mode_cmd, struct drm_gem_object **bos) | ||
| 175 | { | 141 | { |
| 176 | struct msm_drm_private *priv = dev->dev_private; | 142 | struct msm_drm_private *priv = dev->dev_private; |
| 177 | struct msm_kms *kms = priv->kms; | 143 | struct msm_kms *kms = priv->kms; |
| @@ -251,47 +217,33 @@ fail: · 73 unmodified lines | |||
| 251 | return ERR_PTR(ret); | 217 | return ERR_PTR(ret); |
| 252 | } | 218 | } |
| 253 | 219 | ||
| 254 | struct drm_framebuffer * | 220 | struct drm_framebuffer *msm_framebuffer_create(struct drm_device *dev, |
| 255 | msm_alloc_stolen_fb(struct drm_device *dev, int w, int h, int p, uint32_t format) | 221 | struct drm_file *file, |
| 222 | const struct drm_format_info *info, | ||
| 223 | const struct drm_mode_fb_cmd2 *mode_cmd) | ||
| 256 | { | 224 | { |
| 257 | struct drm_mode_fb_cmd2 mode_cmd = { | 225 | struct drm_gem_object *bos[4] = {0}; |
| 258 | .pixel_format = format, | ||
| 259 | .width = w, | ||
| 260 | .height = h, | ||
| 261 | .pitches = { p }, | ||
| 262 | }; | ||
| 263 | struct drm_gem_object *bo; | ||
| 264 | struct drm_framebuffer *fb; | 226 | struct drm_framebuffer *fb; |
| 265 | int size; | 227 | int ret, i, n = info->num_planes; |
| 266 | |||
| 267 | /* allocate backing bo */ | ||
| 268 | size = mode_cmd.pitches[0] * mode_cmd.height; | ||
| 269 | DBG("allocating %d bytes for fb %d", size, dev->primary->index); | ||
| 270 | bo = msm_gem_new(dev, size, MSM_BO_SCANOUT | MSM_BO_WC | MSM_BO_STOLEN); | ||
| 271 | if (IS_ERR(bo)) { | ||
| 272 | dev_warn(dev->dev, "could not allocate stolen bo\n"); | ||
| 273 | /* try regular bo: */ | ||
| 274 | bo = msm_gem_new(dev, size, MSM_BO_SCANOUT | MSM_BO_WC); | ||
| 275 | } | ||
| 276 | if (IS_ERR(bo)) { | ||
| 277 | DRM_DEV_ERROR(dev->dev, "failed to allocate buffer object\n"); | ||
| 278 | return ERR_CAST(bo); | ||
| 279 | } | ||
| 280 | 228 | ||
| 281 | msm_gem_object_set_name(bo, "stolenfb"); | 229 | for (i = 0; i < n; i++) { |
| 230 | bos[i] = drm_gem_object_lookup(file, mode_cmd->handles[i]); | ||
| 231 | if (!bos[i]) { | ||
| 232 | ret = -ENXIO; | ||
| 233 | goto out_unref; | ||
| 234 | } | ||
| 235 | } | ||
| 282 | 236 | ||
| 283 | fb = msm_framebuffer_init(dev, | 237 | fb = msm_framebuffer_init(dev, info, mode_cmd, bos); |
| 284 | drm_get_format_info(dev, mode_cmd.pixel_format, | ||
| 285 | mode_cmd.modifier[0]), | ||
| 286 | &mode_cmd, &bo); | ||
| 287 | if (IS_ERR(fb)) { | 238 | if (IS_ERR(fb)) { |
| 288 | DRM_DEV_ERROR(dev->dev, "failed to allocate fb\n"); | 239 | ret = PTR_ERR(fb); |
| 289 | /* note: if fb creation failed, we can't rely on fb destroy | 240 | goto out_unref; |
| 290 | * to unref the bo: | ||
| 291 | */ | ||
| 292 | drm_gem_object_put(bo); | ||
| 293 | return ERR_CAST(fb); | ||
| 294 | } | 241 | } |
| 295 | 242 | ||
| 296 | return fb; | 243 | return fb; |
| 244 | |||
| 245 | out_unref: | ||
| 246 | for (i = 0; i < n; i++) | ||
| 247 | drm_gem_object_put(bos[i]); | ||
| 248 | return ERR_PTR(ret); | ||
| 297 | } | 249 | } |
| @@ -9,6 +9,7 @@ · 8 unmodified lines | |||
| 9 | #include <drm/drm_drv.h> | 9 | #include <drm/drm_drv.h> |
| 10 | #include <drm/drm_crtc_helper.h> | 10 | #include <drm/drm_crtc_helper.h> |
| 11 | #include <drm/drm_fb_helper.h> | 11 | #include <drm/drm_fb_helper.h> |
| 12 | #include <drm/drm_file.h> | ||
| 12 | #include <drm/drm_fourcc.h> | 13 | #include <drm/drm_fourcc.h> |
| 13 | #include <drm/drm_framebuffer.h> | 14 | #include <drm/drm_framebuffer.h> |
| 14 | #include <drm/drm_prime.h> | 15 | #include <drm/drm_prime.h> |
| @@ -40,17 +41,15 @@ static int msm_fbdev_mmap(struct fb_info *info, struct vm_area_struct *vma) · 25 unmodified lines | |||
| 40 | static void msm_fbdev_fb_destroy(struct fb_info *info) | 41 | static void msm_fbdev_fb_destroy(struct fb_info *info) |
| 41 | { | 42 | { |
| 42 | struct drm_fb_helper *helper = (struct drm_fb_helper *)info->par; | 43 | struct drm_fb_helper *helper = (struct drm_fb_helper *)info->par; |
| 43 | struct drm_framebuffer *fb = helper->fb; | 44 | struct drm_gem_object *bo = msm_framebuffer_bo(helper->fb, 0); |
| 44 | struct drm_gem_object *bo = msm_framebuffer_bo(fb, 0); | ||
| 45 | 45 | ||
| 46 | DBG(); | 46 | DBG(); |
| 47 | 47 | ||
| 48 | drm_fb_helper_fini(helper); | 48 | drm_fb_helper_fini(helper); |
| 49 | 49 | ||
| 50 | /* this will free the backing object */ | ||
| 51 | msm_gem_put_vaddr(bo); | 50 | msm_gem_put_vaddr(bo); |
| 52 | drm_framebuffer_remove(fb); | ||
| 53 | 51 | ||
| 52 | drm_client_buffer_delete(helper->buffer); | ||
| 54 | drm_client_release(&helper->client); | 53 | drm_client_release(&helper->client); |
| 55 | } | 54 | } |
| 56 | 55 | ||
| @@ -89,31 +88,54 @@ static const struct drm_fb_helper_funcs msm_fbdev_helper_funcs = { · 32 unmodified lines | |||
| 89 | int msm_fbdev_driver_fbdev_probe(struct drm_fb_helper *helper, | 88 | int msm_fbdev_driver_fbdev_probe(struct drm_fb_helper *helper, |
| 90 | struct drm_fb_helper_surface_size *sizes) | 89 | struct drm_fb_helper_surface_size *sizes) |
| 91 | { | 90 | { |
| 92 | struct drm_device *dev = helper->dev; | 91 | struct drm_client_dev *client = &helper->client; |
| 92 | struct drm_device *dev = client->dev; | ||
| 93 | struct drm_file *file = client->file; | ||
| 93 | struct msm_drm_private *priv = dev->dev_private; | 94 | struct msm_drm_private *priv = dev->dev_private; |
| 94 | struct fb_info *fbi = helper->info; | 95 | struct fb_info *fbi = helper->info; |
| 95 | struct drm_framebuffer *fb = NULL; | 96 | const struct drm_format_info *format; |
| 97 | u32 fourcc, pitch, handle; | ||
| 98 | u64 size; | ||
| 96 | struct drm_gem_object *bo; | 99 | struct drm_gem_object *bo; |
| 100 | struct drm_client_buffer *buffer; | ||
| 97 | uint64_t paddr; | 101 | uint64_t paddr; |
| 98 | uint32_t format; | 102 | int ret; |
| 99 | int ret, pitch; | ||
| 100 | |||
| 101 | format = drm_mode_legacy_fb_format(sizes->surface_bpp, sizes->surface_depth); | ||
| 102 | 103 | ||
| 103 | DBG("create fbdev: %dx%d@%d (%dx%d)", sizes->surface_width, | 104 | DBG("create fbdev: %dx%d@%d (%dx%d)", sizes->surface_width, |
| 104 | sizes->surface_height, sizes->surface_bpp, | 105 | sizes->surface_height, sizes->surface_bpp, |
| 105 | sizes->fb_width, sizes->fb_height); | 106 | sizes->fb_width, sizes->fb_height); |
| 106 | 107 | ||
| 107 | pitch = align_pitch(sizes->surface_width, sizes->surface_bpp); | 108 | fourcc = drm_mode_legacy_fb_format(sizes->surface_bpp, sizes->surface_depth); |
| 108 | fb = msm_alloc_stolen_fb(dev, sizes->surface_width, | 109 | format = drm_get_format_info(dev, fourcc, DRM_FORMAT_MOD_LINEAR); |
| 109 | sizes->surface_height, pitch, format); | 110 | /* adreno needs pitch aligned to 32 pixels: */ |
| 110 | 111 | pitch = drm_format_info_min_pitch(format, 0, ALIGN(sizes->surface_width, 32)); | |
| 111 | if (IS_ERR(fb)) { | 112 | size = ALIGN(pitch * sizes->surface_height, PAGE_SIZE); |
| 112 | DRM_DEV_ERROR(dev->dev, "failed to allocate fb\n"); | 113 | |
| 113 | return PTR_ERR(fb); | 114 | /* allocate backing bo */ |
| 115 | DBG("allocating %llu bytes for fb %d", size, dev->primary->index); | ||
| 116 | bo = msm_gem_new(dev, size, MSM_BO_SCANOUT | MSM_BO_WC | MSM_BO_STOLEN, NULL); | ||
| 117 | if (IS_ERR(bo)) { | ||
| 118 | drm_warn(dev, "could not allocate stolen bo\n"); | ||
| 119 | /* try regular bo: */ | ||
| 120 | bo = msm_gem_new(dev, size, MSM_BO_SCANOUT | MSM_BO_WC, NULL); | ||
| 121 | if (IS_ERR(bo)) { | ||
| 122 | drm_err(dev, "failed to allocate buffer object\n"); | ||
| 123 | return PTR_ERR(bo); | ||
| 124 | } | ||
| 114 | } | 125 | } |
| 115 | 126 | ||
| 116 | bo = msm_framebuffer_bo(fb, 0); | 127 | msm_gem_object_set_name(bo, "stolenfb"); |
| 128 | |||
| 129 | ret = drm_gem_handle_create(file, bo, &handle); | ||
| 130 | if (ret) | ||
| 131 | goto err_drm_gem_object_put; | ||
| 132 | |||
| 133 | buffer = drm_client_buffer_create(client, sizes->surface_width, sizes->surface_height, | ||
| 134 | fourcc, handle, pitch); | ||
| 135 | if (IS_ERR(buffer)) { | ||
| 136 | ret = PTR_ERR(buffer); | ||
| 137 | goto err_drm_gem_handle_delete; | ||
| 138 | } | ||
| 117 | 139 | ||
| 118 | /* | 140 | /* |
| 119 | * NOTE: if we can be guaranteed to be able to map buffer | 141 | * NOTE: if we can be guaranteed to be able to map buffer |
| @@ -122,14 +144,15 @@ int msm_fbdev_driver_fbdev_probe(struct drm_fb_helper *helper, · 2 unmodified lines | |||
| 122 | */ | 144 | */ |
| 123 | ret = msm_gem_get_and_pin_iova(bo, priv->kms->vm, &paddr); | 145 | ret = msm_gem_get_and_pin_iova(bo, priv->kms->vm, &paddr); |
| 124 | if (ret) { | 146 | if (ret) { |
| 125 | DRM_DEV_ERROR(dev->dev, "failed to get buffer obj iova: %d\n", ret); | 147 | drm_err(dev, "failed to get buffer obj iova: %d\n", ret); |
| 126 | goto fail; | 148 | goto err_drm_client_buffer_delete; |
| 127 | } | 149 | } |
| 128 | 150 | ||
| 129 | DBG("fbi=%p, dev=%p", fbi, dev); | 151 | DBG("fbi=%p, dev=%p", fbi, dev); |
| 130 | 152 | ||
| 131 | helper->funcs = &msm_fbdev_helper_funcs; | 153 | helper->funcs = &msm_fbdev_helper_funcs; |
| 132 | helper->fb = fb; | 154 | helper->buffer = buffer; |
| 155 | helper->fb = buffer->fb; | ||
| 133 | 156 | ||
| 134 | fbi->fbops = &msm_fb_ops; | 157 | fbi->fbops = &msm_fb_ops; |
| 135 | 158 | ||
| @@ -138,18 +161,31 @@ int msm_fbdev_driver_fbdev_probe(struct drm_fb_helper *helper, · 2 unmodified lines | |||
| 138 | fbi->screen_buffer = msm_gem_get_vaddr(bo); | 161 | fbi->screen_buffer = msm_gem_get_vaddr(bo); |
| 139 | if (IS_ERR(fbi->screen_buffer)) { | 162 | if (IS_ERR(fbi->screen_buffer)) { |
| 140 | ret = PTR_ERR(fbi->screen_buffer); | 163 | ret = PTR_ERR(fbi->screen_buffer); |
| 141 | goto fail; | 164 | goto err_msm_gem_unpin; |
| 142 | } | 165 | } |
| 143 | fbi->screen_size = bo->size; | 166 | fbi->screen_size = bo->size; |
| 144 | fbi->fix.smem_start = paddr; | 167 | fbi->fix.smem_start = paddr; |
| 145 | fbi->fix.smem_len = bo->size; | 168 | fbi->fix.smem_len = bo->size; |
| 146 | 169 | ||
| 147 | DBG("par=%p, %dx%d", fbi->par, fbi->var.xres, fbi->var.yres); | 170 | DBG("par=%p, %dx%d", fbi->par, fbi->var.xres, fbi->var.yres); |
| 148 | DBG("allocated %dx%d fb", fb->width, fb->height); | 171 | DBG("allocated %dx%d fb", buffer->fb->width, buffer->fb->height); |
| 172 | |||
| 173 | /* The handle is only needed for creating the framebuffer. */ | ||
| 174 | drm_gem_handle_delete(file, handle); | ||
| 175 | |||
| 176 | /* The framebuffer still holds a reference on the GEM object. */ | ||
| 177 | drm_gem_object_put(bo); | ||
| 149 | 178 | ||
| 150 | return 0; | 179 | return 0; |
| 151 | 180 | ||
| 152 | fail: | 181 | err_msm_gem_unpin: |
| 153 | drm_framebuffer_remove(fb); | 182 | msm_gem_unpin_iova(bo, priv->kms->vm); |
| 183 | msm_gem_vma_put(bo); | ||
| 184 | err_drm_client_buffer_delete: | ||
| 185 | drm_client_buffer_delete(buffer); | ||
| 186 | err_drm_gem_handle_delete: | ||
| 187 | drm_gem_handle_delete(file, handle); | ||
| 188 | err_drm_gem_object_put: | ||
| 189 | drm_gem_object_put(bo); | ||
| 154 | return ret; | 190 | return ret; |
| 155 | } | 191 | } |
| @@ -1093,7 +1093,9 @@ static void msm_gem_free_object(struct drm_gem_object *obj) · 1092 unmodified lines | |||
| 1093 | */ | 1093 | */ |
| 1094 | kvfree(msm_obj->pages); | 1094 | kvfree(msm_obj->pages); |
| 1095 | 1095 | ||
| 1096 | drm_prime_gem_destroy(obj, msm_obj->sgt); | 1096 | /* In msm_gem_import() error path, sgt won't be set yet: */ |
| 1097 | if (msm_obj->sgt) | ||
| 1098 | drm_prime_gem_destroy(obj, msm_obj->sgt); | ||
| 1097 | } else { | 1099 | } else { |
| 1098 | msm_gem_vunmap(obj); | 1100 | msm_gem_vunmap(obj); |
| 1099 | put_pages(obj); | 1101 | put_pages(obj); |
| @@ -1134,10 +1136,21 @@ int msm_gem_new_handle(struct drm_device *dev, struct drm_file *file, · 34 unmodified lines | |||
| 1134 | size_t size, uint32_t flags, uint32_t *handle, | 1136 | size_t size, uint32_t flags, uint32_t *handle, |
| 1135 | char *name) | 1137 | char *name) |
| 1136 | { | 1138 | { |
| 1137 | struct drm_gem_object *obj; | 1139 | struct drm_gem_object *obj, *r_obj = NULL; |
| 1138 | int ret; | 1140 | int ret; |
| 1139 | 1141 | ||
| 1140 | obj = msm_gem_new(dev, size, flags); | 1142 | if (flags & MSM_BO_NO_SHARE) { |
| 1143 | struct msm_drm_private *priv = dev->dev_private; | ||
| 1144 | struct msm_context *ctx = file->driver_priv; | ||
| 1145 | struct drm_gpuvm *vm = msm_context_vm(dev, ctx); | ||
| 1146 | |||
| 1147 | if (!priv->gpu || !vm) | ||
| 1148 | return UERR(EINVAL, dev, "not supported with shared VM"); | ||
| 1149 | |||
| 1150 | r_obj = drm_gpuvm_resv_obj(vm); | ||
| 1151 | } | ||
| 1152 | |||
| 1153 | obj = msm_gem_new(dev, size, flags, r_obj); | ||
| 1141 | 1154 | ||
| 1142 | if (IS_ERR(obj)) | 1155 | if (IS_ERR(obj)) |
| 1143 | return PTR_ERR(obj); | 1156 | return PTR_ERR(obj); |
| @@ -1145,15 +1158,6 @@ int msm_gem_new_handle(struct drm_device *dev, struct drm_file *file, · 1 unmodified line | |||
| 1145 | if (name) | 1158 | if (name) |
| 1146 | msm_gem_object_set_name(obj, "%s", name); | 1159 | msm_gem_object_set_name(obj, "%s", name); |
| 1147 | 1160 | ||
| 1148 | if (flags & MSM_BO_NO_SHARE) { | ||
| 1149 | struct msm_context *ctx = file->driver_priv; | ||
| 1150 | struct drm_gem_object *r_obj = drm_gpuvm_resv_obj(ctx->vm); | ||
| 1151 | |||
| 1152 | drm_gem_object_get(r_obj); | ||
| 1153 | |||
| 1154 | obj->resv = r_obj->resv; | ||
| 1155 | } | ||
| 1156 | |||
| 1157 | ret = drm_gem_handle_create(file, obj, handle); | 1161 | ret = drm_gem_handle_create(file, obj, handle); |
| 1158 | 1162 | ||
| 1159 | /* drop reference from allocate - handle holds it now */ | 1163 | /* drop reference from allocate - handle holds it now */ |
| @@ -1232,10 +1236,27 @@ static int msm_gem_new_impl(struct drm_device *dev, uint32_t flags, · 72 unmodified lines | |||
| 1232 | return 0; | 1236 | return 0; |
| 1233 | } | 1237 | } |
| 1234 | 1238 | ||
| 1235 | struct drm_gem_object *msm_gem_new(struct drm_device *dev, size_t size, uint32_t flags) | 1239 | static int msm_gem_init_bookkeeping(struct drm_gem_object *obj) |
| 1240 | { | ||
| 1241 | struct msm_drm_private *priv = obj->dev->dev_private; | ||
| 1242 | |||
| 1243 | if (drm_gem_is_imported(obj)) { | ||
| 1244 | drm_gem_lru_move_tail(&priv->lru.pinned, obj); | ||
| 1245 | } else { | ||
| 1246 | drm_gem_lru_move_tail(&priv->lru.unbacked, obj); | ||
| 1247 | } | ||
| 1248 | |||
| 1249 | mutex_lock(&priv->obj_lock); | ||
| 1250 | list_add_tail(&to_msm_bo(obj)->node, &priv->objects); | ||
| 1251 | mutex_unlock(&priv->obj_lock); | ||
| 1252 | |||
| 1253 | return drm_gem_create_mmap_offset(obj); | ||
| 1254 | } | ||
| 1255 | |||
| 1256 | struct drm_gem_object * | ||
| 1257 | msm_gem_new(struct drm_device *dev, size_t size, uint32_t flags, | ||
| 1258 | struct drm_gem_object *r_obj) | ||
| 1236 | { | 1259 | { |
| 1237 | struct msm_drm_private *priv = dev->dev_private; | ||
| 1238 | struct msm_gem_object *msm_obj; | ||
| 1239 | struct drm_gem_object *obj = NULL; | 1260 | struct drm_gem_object *obj = NULL; |
| 1240 | int ret; | 1261 | int ret; |
| 1241 | 1262 | ||
| @@ -1251,7 +1272,10 @@ struct drm_gem_object *msm_gem_new(struct drm_device *dev, size_t size, uint32_t · 9 unmodified lines | |||
| 1251 | if (ret) | 1272 | if (ret) |
| 1252 | return ERR_PTR(ret); | 1273 | return ERR_PTR(ret); |
| 1253 | 1274 | ||
| 1254 | msm_obj = to_msm_bo(obj); | 1275 | if (flags & MSM_BO_NO_SHARE) { |
| 1276 | drm_gem_object_get(r_obj); | ||
| 1277 | obj->resv = r_obj->resv; | ||
| 1278 | } | ||
| 1255 | 1279 | ||
| 1256 | ret = drm_gem_object_init(dev, obj, size); | 1280 | ret = drm_gem_object_init(dev, obj, size); |
| 1257 | if (ret) | 1281 | if (ret) |
| @@ -1264,13 +1288,7 @@ struct drm_gem_object *msm_gem_new(struct drm_device *dev, size_t size, uint32_t · 6 unmodified lines | |||
| 1264 | */ | 1288 | */ |
| 1265 | mapping_set_gfp_mask(obj->filp->f_mapping, GFP_HIGHUSER); | 1289 | mapping_set_gfp_mask(obj->filp->f_mapping, GFP_HIGHUSER); |
| 1266 | 1290 | ||
| 1267 | drm_gem_lru_move_tail(&priv->lru.unbacked, obj); | 1291 | ret = msm_gem_init_bookkeeping(obj); |
| 1268 | |||
| 1269 | mutex_lock(&priv->obj_lock); | ||
| 1270 | list_add_tail(&msm_obj->node, &priv->objects); | ||
| 1271 | mutex_unlock(&priv->obj_lock); | ||
| 1272 | |||
| 1273 | ret = drm_gem_create_mmap_offset(obj); | ||
| 1274 | if (ret) | 1292 | if (ret) |
| 1275 | goto fail; | 1293 | goto fail; |
| 1276 | 1294 | ||
| @@ -1282,11 +1300,12 @@ fail: · 5 unmodified lines | |||
| 1282 | } | 1300 | } |
| 1283 | 1301 | ||
| 1284 | struct drm_gem_object *msm_gem_import(struct drm_device *dev, | 1302 | struct drm_gem_object *msm_gem_import(struct drm_device *dev, |
| 1285 | struct dma_buf *dmabuf, struct sg_table *sgt) | 1303 | struct dma_buf_attachment *attach, |
| 1304 | struct sg_table *sgt) | ||
| 1286 | { | 1305 | { |
| 1287 | struct msm_drm_private *priv = dev->dev_private; | ||
| 1288 | struct msm_gem_object *msm_obj; | 1306 | struct msm_gem_object *msm_obj; |
| 1289 | struct drm_gem_object *obj; | 1307 | struct drm_gem_object *obj; |
| 1308 | struct dma_buf *dmabuf = attach->dmabuf; | ||
| 1290 | size_t size, npages; | 1309 | size_t size, npages; |
| 1291 | int ret; | 1310 | int ret; |
| 1292 | 1311 | ||
| @@ -1296,38 +1315,35 @@ struct drm_gem_object *msm_gem_import(struct drm_device *dev, · 3 unmodified lines | |||
| 1296 | if (ret) | 1315 | if (ret) |
| 1297 | return ERR_PTR(ret); | 1316 | return ERR_PTR(ret); |
| 1298 | 1317 | ||
| 1318 | /* | ||
| 1319 | * Set import_attach here in case we hit an error path that ends | ||
| 1320 | * up in drm_gem_object_put() -> msm_gem_free_object() | ||
| 1321 | */ | ||
| 1322 | obj->import_attach = attach; | ||
| 1323 | obj->resv = dmabuf->resv; | ||
| 1299 | drm_gem_private_object_init(dev, obj, size); | 1324 | drm_gem_private_object_init(dev, obj, size); |
| 1300 | 1325 | ||
| 1301 | npages = size / PAGE_SIZE; | 1326 | npages = size / PAGE_SIZE; |
| 1302 | 1327 | ||
| 1303 | msm_obj = to_msm_bo(obj); | 1328 | msm_obj = to_msm_bo(obj); |
| 1304 | msm_gem_lock(obj); | ||
| 1305 | msm_obj->sgt = sgt; | ||
| 1306 | msm_obj->pages = kvmalloc_objs(struct page *, npages); | 1329 | msm_obj->pages = kvmalloc_objs(struct page *, npages); |
| 1307 | if (!msm_obj->pages) { | 1330 | if (!msm_obj->pages) { |
| 1308 | msm_gem_unlock(obj); | ||
| 1309 | ret = -ENOMEM; | 1331 | ret = -ENOMEM; |
| 1310 | goto fail; | 1332 | goto fail; |
| 1311 | } | 1333 | } |
| 1312 | 1334 | ||
| 1313 | ret = drm_prime_sg_to_page_array(sgt, msm_obj->pages, npages); | 1335 | ret = drm_prime_sg_to_page_array(sgt, msm_obj->pages, npages); |
| 1314 | if (ret) { | 1336 | if (ret) { |
| 1315 | msm_gem_unlock(obj); | ||
| 1316 | goto fail; | 1337 | goto fail; |
| 1317 | } | 1338 | } |
| 1318 | 1339 | ||
| 1319 | msm_gem_unlock(obj); | 1340 | ret = msm_gem_init_bookkeeping(obj); |
| 1320 | |||
| 1321 | drm_gem_lru_move_tail(&priv->lru.pinned, obj); | ||
| 1322 | |||
| 1323 | mutex_lock(&priv->obj_lock); | ||
| 1324 | list_add_tail(&msm_obj->node, &priv->objects); | ||
| 1325 | mutex_unlock(&priv->obj_lock); | ||
| 1326 | |||
| 1327 | ret = drm_gem_create_mmap_offset(obj); | ||
| 1328 | if (ret) | 1341 | if (ret) |
| 1329 | goto fail; | 1342 | goto fail; |
| 1330 | 1343 | ||
| 1344 | /* Now that we are past potential failure points, set sgt: */ | ||
| 1345 | msm_obj->sgt = sgt; | ||
| 1346 | |||
| 1331 | return obj; | 1347 | return obj; |
| 1332 | 1348 | ||
| 1333 | fail: | 1349 | fail: |
| @@ -1340,7 +1356,7 @@ void *msm_gem_kernel_new(struct drm_device *dev, size_t size, uint32_t flags, · 6 unmodified lines | |||
| 1340 | uint64_t *iova) | 1356 | uint64_t *iova) |
| 1341 | { | 1357 | { |
| 1342 | void *vaddr; | 1358 | void *vaddr; |
| 1343 | struct drm_gem_object *obj = msm_gem_new(dev, size, flags); | 1359 | struct drm_gem_object *obj = msm_gem_new(dev, size, flags, NULL); |
| 1344 | int ret; | 1360 | int ret; |
| 1345 | 1361 | ||
| 1346 | if (IS_ERR(obj)) | 1362 | if (IS_ERR(obj)) |
| @@ -296,13 +296,14 @@ int msm_gem_cpu_fini(struct drm_gem_object *obj); · 295 unmodified lines | |||
| 296 | int msm_gem_new_handle(struct drm_device *dev, struct drm_file *file, | 296 | int msm_gem_new_handle(struct drm_device *dev, struct drm_file *file, |
| 297 | size_t size, uint32_t flags, uint32_t *handle, char *name); | 297 | size_t size, uint32_t flags, uint32_t *handle, char *name); |
| 298 | struct drm_gem_object *msm_gem_new(struct drm_device *dev, | 298 | struct drm_gem_object *msm_gem_new(struct drm_device *dev, |
| 299 | size_t size, uint32_t flags); | 299 | size_t size, uint32_t flags, struct drm_gem_object *r_obj); |
| 300 | void *msm_gem_kernel_new(struct drm_device *dev, size_t size, uint32_t flags, | 300 | void *msm_gem_kernel_new(struct drm_device *dev, size_t size, uint32_t flags, |
| 301 | struct drm_gpuvm *vm, struct drm_gem_object **bo, | 301 | struct drm_gpuvm *vm, struct drm_gem_object **bo, |
| 302 | uint64_t *iova); | 302 | uint64_t *iova); |
| 303 | void msm_gem_kernel_put(struct drm_gem_object *bo, struct drm_gpuvm *vm); | 303 | void msm_gem_kernel_put(struct drm_gem_object *bo, struct drm_gpuvm *vm); |
| 304 | struct drm_gem_object *msm_gem_import(struct drm_device *dev, | 304 | struct drm_gem_object *msm_gem_import(struct drm_device *dev, |
| 305 | struct dma_buf *dmabuf, struct sg_table *sgt); | 305 | struct dma_buf_attachment *attach, |
| 306 | struct sg_table *sgt); | ||
| 306 | __printf(2, 3) | 307 | __printf(2, 3) |
| 307 | void msm_gem_object_set_name(struct drm_gem_object *bo, const char *fmt, ...); | 308 | void msm_gem_object_set_name(struct drm_gem_object *bo, const char *fmt, ...); |
| 308 | 309 | ||
| @@ -83,7 +83,7 @@ struct drm_gem_object *msm_gem_prime_import(struct drm_device *dev, · 82 unmodified lines | |||
| 83 | struct drm_gem_object *msm_gem_prime_import_sg_table(struct drm_device *dev, | 83 | struct drm_gem_object *msm_gem_prime_import_sg_table(struct drm_device *dev, |
| 84 | struct dma_buf_attachment *attach, struct sg_table *sg) | 84 | struct dma_buf_attachment *attach, struct sg_table *sg) |
| 85 | { | 85 | { |
| 86 | return msm_gem_import(dev, attach->dmabuf, sg); | 86 | return msm_gem_import(dev, attach, sg); |
| 87 | } | 87 | } |
| 88 | 88 | ||
| 89 | struct dma_buf *msm_gem_prime_export(struct drm_gem_object *obj, int flags) | 89 | struct dma_buf *msm_gem_prime_export(struct drm_gem_object *obj, int flags) |
| @@ -30,20 +30,17 @@ · 29 unmodified lines | |||
| 30 | */ | 30 | */ |
| 31 | 31 | ||
| 32 | static struct msm_gem_submit *submit_create(struct drm_device *dev, | 32 | static struct msm_gem_submit *submit_create(struct drm_device *dev, |
| 33 | struct msm_gpu *gpu, | 33 | struct msm_gpu *gpu, struct drm_gpuvm *vm, |
| 34 | struct msm_gpu_submitqueue *queue, uint32_t nr_bos, | 34 | struct msm_gpu_submitqueue *queue, uint32_t nr_bos, |
| 35 | uint32_t nr_cmds, u64 drm_client_id) | 35 | uint32_t nr_cmds, u64 drm_client_id) |
| 36 | { | 36 | { |
| 37 | static atomic_t ident = ATOMIC_INIT(0); | 37 | static atomic_t ident = ATOMIC_INIT(0); |
| 38 | struct msm_gem_submit *submit; | 38 | struct msm_gem_submit *submit; |
| 39 | uint64_t sz; | 39 | size_t sz; |
| 40 | int ret; | 40 | int ret; |
| 41 | 41 | ||
| 42 | sz = struct_size(submit, bos, nr_bos) + | 42 | sz = size_add(struct_size(submit, bos, nr_bos), |
| 43 | ((u64)nr_cmds * sizeof(submit->cmd[0])); | 43 | array_size(sizeof(submit->cmd[0]), nr_cmds)); |
| 44 | |||
| 45 | if (sz > SIZE_MAX) | ||
| 46 | return ERR_PTR(-ENOMEM); | ||
| 47 | 44 | ||
| 48 | submit = kzalloc(sz, GFP_KERNEL | __GFP_NOWARN); | 45 | submit = kzalloc(sz, GFP_KERNEL | __GFP_NOWARN); |
| 49 | if (!submit) | 46 | if (!submit) |
| @@ -66,7 +63,7 @@ static struct msm_gem_submit *submit_create(struct drm_device *dev, · 16 unmodified lines | |||
| 66 | 63 | ||
| 67 | kref_init(&submit->ref); | 64 | kref_init(&submit->ref); |
| 68 | submit->dev = dev; | 65 | submit->dev = dev; |
| 69 | submit->vm = msm_context_vm(dev, queue->ctx); | 66 | submit->vm = vm; |
| 70 | submit->gpu = gpu; | 67 | submit->gpu = gpu; |
| 71 | submit->cmd = (void *)&submit->bos[nr_bos]; | 68 | submit->cmd = (void *)&submit->bos[nr_bos]; |
| 72 | submit->queue = queue; | 69 | submit->queue = queue; |
| @@ -250,16 +247,14 @@ static int submit_lookup_cmds(struct msm_gem_submit *submit, · 177 unmodified lines | |||
| 250 | 247 | ||
| 251 | sz = array_size(submit_cmd.nr_relocs, | 248 | sz = array_size(submit_cmd.nr_relocs, |
| 252 | sizeof(struct drm_msm_gem_submit_reloc)); | 249 | sizeof(struct drm_msm_gem_submit_reloc)); |
| 253 | /* check for overflow: */ | ||
| 254 | if (sz == SIZE_MAX) { | ||
| 255 | ret = -ENOMEM; | ||
| 256 | goto out; | ||
| 257 | } | ||
| 258 | submit->cmd[i].relocs = kmalloc(sz, GFP_KERNEL | __GFP_NOWARN); | 250 | submit->cmd[i].relocs = kmalloc(sz, GFP_KERNEL | __GFP_NOWARN); |
| 259 | if (!submit->cmd[i].relocs) { | 251 | if (!submit->cmd[i].relocs) { |
| 260 | ret = -ENOMEM; | 252 | ret = -ENOMEM; |
| 261 | goto out; | 253 | goto out; |
| 262 | } | 254 | } |
| 255 | |||
| 256 | submit->nr_cmds = i + 1; | ||
| 257 | |||
| 263 | ret = copy_from_user(submit->cmd[i].relocs, userptr, sz); | 258 | ret = copy_from_user(submit->cmd[i].relocs, userptr, sz); |
| 264 | if (ret) { | 259 | if (ret) { |
| 265 | ret = -EFAULT; | 260 | ret = -EFAULT; |
| @@ -554,6 +549,7 @@ int msm_ioctl_gem_submit(struct drm_device *dev, void *data, · 288 unmodified lines | |||
| 554 | struct msm_drm_private *priv = dev->dev_private; | 549 | struct msm_drm_private *priv = dev->dev_private; |
| 555 | struct drm_msm_gem_submit *args = data; | 550 | struct drm_msm_gem_submit *args = data; |
| 556 | struct msm_context *ctx = file->driver_priv; | 551 | struct msm_context *ctx = file->driver_priv; |
| 552 | struct drm_gpuvm *vm = msm_context_vm(dev, ctx); | ||
| 557 | struct msm_gem_submit *submit = NULL; | 553 | struct msm_gem_submit *submit = NULL; |
| 558 | struct msm_gpu *gpu = priv->gpu; | 554 | struct msm_gpu *gpu = priv->gpu; |
| 559 | struct msm_gpu_submitqueue *queue; | 555 | struct msm_gpu_submitqueue *queue; |
| @@ -569,10 +565,13 @@ int msm_ioctl_gem_submit(struct drm_device *dev, void *data, · 9 unmodified lines | |||
| 569 | if (!gpu) | 565 | if (!gpu) |
| 570 | return -ENXIO; | 566 | return -ENXIO; |
| 571 | 567 | ||
| 568 | if (!vm) | ||
| 569 | return UERR(ENOMEM, dev, "no VM"); | ||
| 570 | |||
| 572 | if (args->pad) | 571 | if (args->pad) |
| 573 | return -EINVAL; | 572 | return -EINVAL; |
| 574 | 573 | ||
| 575 | if (to_msm_vm(ctx->vm)->unusable) | 574 | if (to_msm_vm(vm)->unusable) |
| 576 | return UERR(EPIPE, dev, "context is unusable"); | 575 | return UERR(EPIPE, dev, "context is unusable"); |
| 577 | 576 | ||
| 578 | /* for now, we just have 3d pipe.. eventually this would need to | 577 | /* for now, we just have 3d pipe.. eventually this would need to |
| @@ -609,7 +608,7 @@ int msm_ioctl_gem_submit(struct drm_device *dev, void *data, · 30 unmodified lines | |||
| 609 | } | 608 | } |
| 610 | } | 609 | } |
| 611 | 610 | ||
| 612 | submit = submit_create(dev, gpu, queue, args->nr_bos, args->nr_cmds, | 611 | submit = submit_create(dev, gpu, vm, queue, args->nr_bos, args->nr_cmds, |
| 613 | file->client_id); | 612 | file->client_id); |
| 614 | if (IS_ERR(submit)) { | 613 | if (IS_ERR(submit)) { |
| 615 | ret = PTR_ERR(submit); | 614 | ret = PTR_ERR(submit); |
| @@ -719,8 +718,6 @@ int msm_ioctl_gem_submit(struct drm_device *dev, void *data, · 103 unmodified lines | |||
| 719 | goto out; | 718 | goto out; |
| 720 | } | 719 | } |
| 721 | 720 | ||
| 722 | submit->nr_cmds = args->nr_cmds; | ||
| 723 | |||
| 724 | idr_preload(GFP_KERNEL); | 721 | idr_preload(GFP_KERNEL); |
| 725 | 722 | ||
| 726 | spin_lock(&queue->idr_lock); | 723 | spin_lock(&queue->idr_lock); |
| @@ -458,6 +458,8 @@ msm_gem_vm_bo_validate(struct drm_gpuvm_bo *vm_bo, struct drm_exec *exec) · 457 unmodified lines | |||
| 458 | return ret; | 458 | return ret; |
| 459 | } | 459 | } |
| 460 | 460 | ||
| 461 | drm_gpuvm_bo_evict(vm_bo, false); | ||
| 462 | |||
| 461 | return 0; | 463 | return 0; |
| 462 | } | 464 | } |
| 463 | 465 | ||
| @@ -955,7 +957,7 @@ msm_gem_vm_close(struct drm_gpuvm *gpuvm) · 491 unmodified lines | |||
| 955 | 957 | ||
| 956 | 958 | ||
| 957 | static struct msm_vm_bind_job * | 959 | static struct msm_vm_bind_job * |
| 958 | vm_bind_job_create(struct drm_device *dev, struct drm_file *file, | 960 | vm_bind_job_create(struct drm_device *dev, struct drm_file *file, struct drm_gpuvm *vm, |
| 959 | struct msm_gpu_submitqueue *queue, uint32_t nr_ops) | 961 | struct msm_gpu_submitqueue *queue, uint32_t nr_ops) |
| 960 | { | 962 | { |
| 961 | struct msm_vm_bind_job *job; | 963 | struct msm_vm_bind_job *job; |
| @@ -972,7 +974,7 @@ vm_bind_job_create(struct drm_device *dev, struct drm_file *file, · 10 unmodified lines | |||
| 972 | return ERR_PTR(ret); | 974 | return ERR_PTR(ret); |
| 973 | } | 975 | } |
| 974 | 976 | ||
| 975 | job->vm = msm_context_vm(dev, queue->ctx); | 977 | job->vm = vm; |
| 976 | job->queue = queue; | 978 | job->queue = queue; |
| 977 | INIT_LIST_HEAD(&job->vm_ops); | 979 | INIT_LIST_HEAD(&job->vm_ops); |
| 978 | 980 | ||
| @@ -1431,6 +1433,7 @@ msm_ioctl_vm_bind(struct drm_device *dev, void *data, struct drm_file *file) · 452 unmodified lines | |||
| 1431 | struct msm_drm_private *priv = dev->dev_private; | 1433 | struct msm_drm_private *priv = dev->dev_private; |
| 1432 | struct drm_msm_vm_bind *args = data; | 1434 | struct drm_msm_vm_bind *args = data; |
| 1433 | struct msm_context *ctx = file->driver_priv; | 1435 | struct msm_context *ctx = file->driver_priv; |
| 1436 | struct drm_gpuvm *vm = msm_context_vm(dev, ctx); | ||
| 1434 | struct msm_vm_bind_job *job = NULL; | 1437 | struct msm_vm_bind_job *job = NULL; |
| 1435 | struct msm_gpu *gpu = priv->gpu; | 1438 | struct msm_gpu *gpu = priv->gpu; |
| 1436 | struct msm_gpu_submitqueue *queue; | 1439 | struct msm_gpu_submitqueue *queue; |
| @@ -1445,11 +1448,14 @@ msm_ioctl_vm_bind(struct drm_device *dev, void *data, struct drm_file *file) · 8 unmodified lines | |||
| 1445 | if (!gpu) | 1448 | if (!gpu) |
| 1446 | return -ENXIO; | 1449 | return -ENXIO; |
| 1447 | 1450 | ||
| 1451 | if (!vm) | ||
| 1452 | return UERR(ENOMEM, dev, "no VM"); | ||
| 1453 | |||
| 1448 | /* | 1454 | /* |
| 1449 | * Maybe we could allow just UNMAP ops? OTOH userspace should just | 1455 | * Maybe we could allow just UNMAP ops? OTOH userspace should just |
| 1450 | * immediately close the device file and all will be torn down. | 1456 | * immediately close the device file and all will be torn down. |
| 1451 | */ | 1457 | */ |
| 1452 | if (to_msm_vm(msm_context_vm(dev, ctx))->unusable) | 1458 | if (to_msm_vm(vm)->unusable) |
| 1453 | return UERR(EPIPE, dev, "context is unusable"); | 1459 | return UERR(EPIPE, dev, "context is unusable"); |
| 1454 | 1460 | ||
| 1455 | /* | 1461 | /* |
| @@ -1480,7 +1486,7 @@ msm_ioctl_vm_bind(struct drm_device *dev, void *data, struct drm_file *file) · 24 unmodified lines | |||
| 1480 | } | 1486 | } |
| 1481 | } | 1487 | } |
| 1482 | 1488 | ||
| 1483 | job = vm_bind_job_create(dev, file, queue, args->nr_ops); | 1489 | job = vm_bind_job_create(dev, file, vm, queue, args->nr_ops); |
| 1484 | if (IS_ERR(job)) { | 1490 | if (IS_ERR(job)) { |
| 1485 | ret = PTR_ERR(job); | 1491 | ret = PTR_ERR(job); |
| 1486 | goto out_post_unlock; | 1492 | goto out_post_unlock; |
| @@ -505,6 +505,8 @@ static void recover_worker(struct kthread_work *work) · 504 unmodified lines | |||
| 505 | */ | 505 | */ |
| 506 | if (!vm->managed) | 506 | if (!vm->managed) |
| 507 | msm_gem_vm_unusable(submit->vm); | 507 | msm_gem_vm_unusable(submit->vm); |
| 508 | |||
| 509 | put_task_struct(task); | ||
| 508 | } | 510 | } |
| 509 | 511 | ||
| 510 | noreclaim_flag = memalloc_noreclaim_save(); | 512 | noreclaim_flag = memalloc_noreclaim_save(); |
| @@ -552,11 +554,13 @@ static void recover_worker(struct kthread_work *work) · 41 unmodified lines | |||
| 552 | msm_update_fence(ring->fctx, fence); | 554 | msm_update_fence(ring->fctx, fence); |
| 553 | } | 555 | } |
| 554 | 556 | ||
| 555 | /* retire completed submits, plus the one that hung: */ | 557 | priv->disable_err_irq = false; |
| 556 | retire_submits(gpu); | ||
| 557 | 558 | ||
| 558 | gpu->funcs->recover(gpu); | 559 | gpu->funcs->recover(gpu); |
| 559 | 560 | ||
| 561 | /* retire completed submits, plus the one that hung: */ | ||
| 562 | retire_submits(gpu); | ||
| 563 | |||
| 560 | /* | 564 | /* |
| 561 | * Replay all remaining submits starting with highest priority | 565 | * Replay all remaining submits starting with highest priority |
| 562 | * ring | 566 | * ring |
| @@ -875,7 +879,7 @@ msm_gpu_create_private_vm(struct msm_gpu *gpu, struct task_struct *task, · 312 unmodified lines | |||
| 875 | to_msm_vm(vm)->pid = get_pid(task_pid(task)); | 879 | to_msm_vm(vm)->pid = get_pid(task_pid(task)); |
| 876 | } | 880 | } |
| 877 | 881 | ||
| 878 | if (IS_ERR_OR_NULL(vm)) | 882 | if (IS_ERR_OR_NULL(vm) && kernel_managed) |
| 879 | vm = drm_gpuvm_get(gpu->vm); | 883 | vm = drm_gpuvm_get(gpu->vm); |
| 880 | 884 | ||
| 881 | return vm; | 885 | return vm; |
| @@ -392,8 +392,8 @@ msm_gpu_sysprof_no_ifpc(struct msm_gpu *gpu) · 391 unmodified lines | |||
| 392 | * struct msm_context - per-drm_file context | 392 | * struct msm_context - per-drm_file context |
| 393 | */ | 393 | */ |
| 394 | struct msm_context { | 394 | struct msm_context { |
| 395 | /** @queuelock: synchronizes access to submitqueues list */ | 395 | /** @ctxlock: synchronizes access to submitqueues list, etc */ |
| 396 | rwlock_t queuelock; | 396 | struct rw_semaphore ctxlock; |
| 397 | /** @submitqueues: list of &msm_gpu_submitqueue created by userspace */ | 397 | /** @submitqueues: list of &msm_gpu_submitqueue created by userspace */ |
| 398 | struct list_head submitqueues; | 398 | struct list_head submitqueues; |
| 399 | /** | 399 | /** |
| @@ -7,6 +7,15 @@ · 6 unmodified lines | |||
| 7 | #include <linux/adreno-smmu-priv.h> | 7 | #include <linux/adreno-smmu-priv.h> |
| 8 | #include <linux/io-pgtable.h> | 8 | #include <linux/io-pgtable.h> |
| 9 | #include <linux/kmemleak.h> | 9 | #include <linux/kmemleak.h> |
| 10 | |||
| 11 | #if defined(CONFIG_ARM_DMA_USE_IOMMU) | ||
| 12 | #include <asm/dma-iommu.h> | ||
| 13 | #else | ||
| 14 | #define arm_iommu_detach_device(...) ({ }) | ||
| 15 | #define arm_iommu_release_mapping(...) ({ }) | ||
| 16 | #define to_dma_iommu_mapping(dev) NULL | ||
| 17 | #endif | ||
| 18 | |||
| 10 | #include "msm_drv.h" | 19 | #include "msm_drv.h" |
| 11 | #include "msm_gpu_trace.h" | 20 | #include "msm_gpu_trace.h" |
| 12 | #include "msm_mmu.h" | 21 | #include "msm_mmu.h" |
| @@ -749,6 +758,19 @@ struct msm_mmu *msm_iommu_new(struct device *dev, unsigned long quirks) · 736 unmodified lines | |||
| 749 | 758 | ||
| 750 | mutex_init(&iommu->init_lock); | 759 | mutex_init(&iommu->init_lock); |
| 751 | 760 | ||
| 761 | /* | ||
| 762 | * ARM32 attaches a DMA mapping domain to every IOMMU-backed device, | ||
| 763 | * which would make attaching our own domain fail with -EBUSY. | ||
| 764 | */ | ||
| 765 | if (IS_ENABLED(CONFIG_ARM_DMA_USE_IOMMU)) { | ||
| 766 | struct dma_iommu_mapping *mapping = to_dma_iommu_mapping(dev); | ||
| 767 | |||
| 768 | if (mapping) { | ||
| 769 | arm_iommu_detach_device(dev); | ||
| 770 | arm_iommu_release_mapping(mapping); | ||
| 771 | } | ||
| 772 | } | ||
| 773 | |||
| 752 | ret = iommu_attach_device(iommu->domain, dev); | 774 | ret = iommu_attach_device(iommu->domain, dev); |
| 753 | if (ret) { | 775 | if (ret) { |
| 754 | iommu_domain_free(domain); | 776 | iommu_domain_free(domain); |
| @@ -109,9 +109,9 @@ struct msm_ringbuffer *msm_ringbuffer_new(struct msm_gpu *gpu, int id, · 108 unmodified lines | |||
| 109 | ring->memptrs_iova = memptrs_iova; | 109 | ring->memptrs_iova = memptrs_iova; |
| 110 | 110 | ||
| 111 | ret = drm_sched_init(&ring->sched, &args); | 111 | ret = drm_sched_init(&ring->sched, &args); |
| 112 | if (ret) { | 112 | if (ret) |
| 113 | goto fail; | 113 | goto fail; |
| 114 | } | 114 | ring->sched_initialized = true; |
| 115 | 115 | ||
| 116 | INIT_LIST_HEAD(&ring->submits); | 116 | INIT_LIST_HEAD(&ring->submits); |
| 117 | spin_lock_init(&ring->submit_lock); | 117 | spin_lock_init(&ring->submit_lock); |
| @@ -133,7 +133,8 @@ void msm_ringbuffer_destroy(struct msm_ringbuffer *ring) · 15 unmodified lines | |||
| 133 | if (IS_ERR_OR_NULL(ring)) | 133 | if (IS_ERR_OR_NULL(ring)) |
| 134 | return; | 134 | return; |
| 135 | 135 | ||
| 136 | drm_sched_fini(&ring->sched); | 136 | if (ring->sched_initialized) |
| 137 | drm_sched_fini(&ring->sched); | ||
| 137 | 138 | ||
| 138 | msm_fence_context_free(ring->fctx); | 139 | msm_fence_context_free(ring->fctx); |
| 139 | 140 | ||
| @@ -56,6 +56,7 @@ struct msm_ringbuffer { · 55 unmodified lines | |||
| 56 | * The job scheduler for this ring. | 56 | * The job scheduler for this ring. |
| 57 | */ | 57 | */ |
| 58 | struct drm_gpu_scheduler sched; | 58 | struct drm_gpu_scheduler sched; |
| 59 | bool sched_initialized; | ||
| 59 | 60 | ||
| 60 | /* | 61 | /* |
| 61 | * List of in-flight submits on this ring. Protected by submit_lock. | 62 | * List of in-flight submits on this ring. Protected by submit_lock. |
| @@ -9,6 +9,8 @@ · 8 unmodified lines | |||
| 9 | 9 | ||
| 10 | int msm_context_set_sysprof(struct msm_context *ctx, struct msm_gpu *gpu, int sysprof) | 10 | int msm_context_set_sysprof(struct msm_context *ctx, struct msm_gpu *gpu, int sysprof) |
| 11 | { | 11 | { |
| 12 | guard(rwsem_write)(&ctx->ctxlock); | ||
| 13 | |||
| 12 | /* | 14 | /* |
| 13 | * Since pm_runtime and sysprof_active are both refcounts, we | 15 | * Since pm_runtime and sysprof_active are both refcounts, we |
| 14 | * call apply the new value first, and then unwind the previous | 16 | * call apply the new value first, and then unwind the previous |
| @@ -93,18 +95,15 @@ struct msm_gpu_submitqueue *msm_submitqueue_get(struct msm_context *ctx, · 78 unmodified lines | |||
| 93 | if (!ctx) | 95 | if (!ctx) |
| 94 | return NULL; | 96 | return NULL; |
| 95 | 97 | ||
| 96 | read_lock(&ctx->queuelock); | 98 | guard(rwsem_read)(&ctx->ctxlock); |
| 97 | 99 | ||
| 98 | list_for_each_entry(entry, &ctx->submitqueues, node) { | 100 | list_for_each_entry(entry, &ctx->submitqueues, node) { |
| 99 | if (entry->id == id) { | 101 | if (entry->id == id) { |
| 100 | kref_get(&entry->ref); | 102 | kref_get(&entry->ref); |
| 101 | read_unlock(&ctx->queuelock); | ||
| 102 | |||
| 103 | return entry; | 103 | return entry; |
| 104 | } | 104 | } |
| 105 | } | 105 | } |
| 106 | 106 | ||
| 107 | read_unlock(&ctx->queuelock); | ||
| 108 | return NULL; | 107 | return NULL; |
| 109 | } | 108 | } |
| 110 | 109 | ||
| @@ -175,6 +174,7 @@ int msm_submitqueue_create(struct drm_device *drm, struct msm_context *ctx, · 64 unmodified lines | |||
| 175 | struct msm_drm_private *priv = drm->dev_private; | 174 | struct msm_drm_private *priv = drm->dev_private; |
| 176 | struct msm_gpu_submitqueue *queue; | 175 | struct msm_gpu_submitqueue *queue; |
| 177 | enum drm_sched_priority sched_prio; | 176 | enum drm_sched_priority sched_prio; |
| 177 | struct drm_gpuvm *vm = NULL; | ||
| 178 | unsigned ring_nr; | 178 | unsigned ring_nr; |
| 179 | int ret; | 179 | int ret; |
| 180 | 180 | ||
| @@ -187,6 +187,11 @@ int msm_submitqueue_create(struct drm_device *drm, struct msm_context *ctx, · 6 unmodified lines | |||
| 187 | if (flags & MSM_SUBMITQUEUE_VM_BIND) { | 187 | if (flags & MSM_SUBMITQUEUE_VM_BIND) { |
| 188 | unsigned sz; | 188 | unsigned sz; |
| 189 | 189 | ||
| 190 | vm = msm_context_vm(drm, ctx); | ||
| 191 | |||
| 192 | if (!vm) | ||
| 193 | return UERR(ENOMEM, drm, "no VM"); | ||
| 194 | |||
| 190 | /* Not allowed for kernel managed VMs (ie. kernel allocs VA) */ | 195 | /* Not allowed for kernel managed VMs (ie. kernel allocs VA) */ |
| 191 | if (!msm_context_is_vmbind(ctx)) | 196 | if (!msm_context_is_vmbind(ctx)) |
| 192 | return -EINVAL; | 197 | return -EINVAL; |
| @@ -218,7 +223,7 @@ int msm_submitqueue_create(struct drm_device *drm, struct msm_context *ctx, · 25 unmodified lines | |||
| 218 | queue->flags = flags; | 223 | queue->flags = flags; |
| 219 | 224 | ||
| 220 | if (flags & MSM_SUBMITQUEUE_VM_BIND) { | 225 | if (flags & MSM_SUBMITQUEUE_VM_BIND) { |
| 221 | struct drm_gpu_scheduler *sched = &to_msm_vm(msm_context_vm(drm, ctx))->sched; | 226 | struct drm_gpu_scheduler *sched = &to_msm_vm(vm)->sched; |
| 222 | 227 | ||
| 223 | queue->entity = &queue->_vm_bind_entity[0]; | 228 | queue->entity = &queue->_vm_bind_entity[0]; |
| 224 | 229 | ||
| @@ -237,7 +242,7 @@ int msm_submitqueue_create(struct drm_device *drm, struct msm_context *ctx, · 12 unmodified lines | |||
| 237 | return ret; | 242 | return ret; |
| 238 | } | 243 | } |
| 239 | 244 | ||
| 240 | write_lock(&ctx->queuelock); | 245 | guard(rwsem_write)(&ctx->ctxlock); |
| 241 | 246 | ||
| 242 | queue->ctx = msm_context_get(ctx); | 247 | queue->ctx = msm_context_get(ctx); |
| 243 | queue->id = ctx->queueid++; | 248 | queue->id = ctx->queueid++; |
| @@ -251,8 +256,6 @@ int msm_submitqueue_create(struct drm_device *drm, struct msm_context *ctx, · 7 unmodified lines | |||
| 251 | 256 | ||
| 252 | list_add_tail(&queue->node, &ctx->submitqueues); | 257 | list_add_tail(&queue->node, &ctx->submitqueues); |
| 253 | 258 | ||
| 254 | write_unlock(&ctx->queuelock); | ||
| 255 | |||
| 256 | return 0; | 259 | return 0; |
| 257 | } | 260 | } |
| 258 | 261 | ||
| @@ -335,19 +338,16 @@ int msm_submitqueue_remove(struct msm_context *ctx, u32 id) · 76 unmodified lines | |||
| 335 | if (!id) | 338 | if (!id) |
| 336 | return -ENOENT; | 339 | return -ENOENT; |
| 337 | 340 | ||
| 338 | write_lock(&ctx->queuelock); | 341 | guard(rwsem_write)(&ctx->ctxlock); |
| 339 | 342 | ||
| 340 | list_for_each_entry(entry, &ctx->submitqueues, node) { | 343 | list_for_each_entry(entry, &ctx->submitqueues, node) { |
| 341 | if (entry->id == id) { | 344 | if (entry->id == id) { |
| 342 | list_del(&entry->node); | 345 | list_del(&entry->node); |
| 343 | write_unlock(&ctx->queuelock); | ||
| 344 | |||
| 345 | msm_submitqueue_put(entry); | 346 | msm_submitqueue_put(entry); |
| 346 | return 0; | 347 | return 0; |
| 347 | } | 348 | } |
| 348 | } | 349 | } |
| 349 | 350 | ||
| 350 | write_unlock(&ctx->queuelock); | ||
| 351 | return -ENOENT; | 351 | return -ENOENT; |
| 352 | } | 352 | } |
| 353 | 353 | ||
| @@ -1495,6 +1495,8 @@ xsi:schemaLocation="https://gitlab.freedesktop.org/freedreno/ rules-fd.xsd"> · 1494 unmodified lines | |||
| 1495 | <reg32 offset="0x3058" name="VBIF_OUT_AXI_AMEMTYPE_CONF0"/> | 1495 | <reg32 offset="0x3058" name="VBIF_OUT_AXI_AMEMTYPE_CONF0"/> |
| 1496 | <reg32 offset="0x305e" name="VBIF_OUT_AXI_AOOO_EN"/> | 1496 | <reg32 offset="0x305e" name="VBIF_OUT_AXI_AOOO_EN"/> |
| 1497 | <reg32 offset="0x305f" name="VBIF_OUT_AXI_AOOO"/> | 1497 | <reg32 offset="0x305f" name="VBIF_OUT_AXI_AOOO"/> |
| 1498 | <reg32 offset="0x3080" name="VBIF_XIN_HALT_CTRL0"/> | ||
| 1499 | <reg32 offset="0x3081" name="VBIF_XIN_HALT_CTRL1"/> | ||
| 1498 | 1500 | ||
| 1499 | <bitset name="a3xx_vbif_perf_cnt" inline="yes"> | 1501 | <bitset name="a3xx_vbif_perf_cnt" inline="yes"> |
| 1500 | <bitfield name="CNT0" pos="0" type="boolean"/> | 1502 | <bitfield name="CNT0" pos="0" type="boolean"/> |
| @@ -1268,7 +1268,7 @@ by a particular renderpass/blit. · 1267 unmodified lines | |||
| 1268 | <reg32 offset="0x3119" name="VBIF_PERF_PWR_CNT_HIGH1" variants="A6XX"/> | 1268 | <reg32 offset="0x3119" name="VBIF_PERF_PWR_CNT_HIGH1" variants="A6XX"/> |
| 1269 | <reg32 offset="0x311a" name="VBIF_PERF_PWR_CNT_HIGH2" variants="A6XX"/> | 1269 | <reg32 offset="0x311a" name="VBIF_PERF_PWR_CNT_HIGH2" variants="A6XX"/> |
| 1270 | 1270 | ||
| 1271 | <reg32 offset="0x3c00" name="GBIF_CX_CONFIG" variants="A8XX-"/> | 1271 | <reg32 offset="0x3c00" name="GBIF_CX_CONFIG" variants="A6XX-"/> |
| 1272 | <reg32 offset="0x3c01" name="GBIF_SCACHE_CNTL0"/> | 1272 | <reg32 offset="0x3c01" name="GBIF_SCACHE_CNTL0"/> |
| 1273 | <reg32 offset="0x3c02" name="GBIF_SCACHE_CNTL1"/> | 1273 | <reg32 offset="0x3c02" name="GBIF_SCACHE_CNTL1"/> |
| 1274 | <reg32 offset="0x3c03" name="GBIF_QSB_SIDE0"/> | 1274 | <reg32 offset="0x3c03" name="GBIF_QSB_SIDE0"/> |
| @@ -228,7 +228,7 @@ struct drm_msm_gem_cpu_fini { · 227 unmodified lines | |||
| 228 | 228 | ||
| 229 | struct drm_msm_syncobj { | 229 | struct drm_msm_syncobj { |
| 230 | __u32 handle; /* in, syncobj handle. */ | 230 | __u32 handle; /* in, syncobj handle. */ |
| 231 | __u32 flags; /* in, from MSM_SUBMIT_SYNCOBJ_FLAGS */ | 231 | __u32 flags; /* in, from MSM_SYNCOBJ_FLAGS */ |
| 232 | __u64 point; /* in, timepoint for timeline syncobjs. */ | 232 | __u64 point; /* in, timepoint for timeline syncobjs. */ |
| 233 | }; | 233 | }; |
| 234 | 234 | ||
| @@ -393,9 +393,9 @@ struct drm_msm_vm_bind { · 158 unmodified lines | |||
| 393 | __s32 fence_fd; | 393 | __s32 fence_fd; |
| 394 | /** @queue_id: in, submitqueue id */ | 394 | /** @queue_id: in, submitqueue id */ |
| 395 | __u32 queue_id; | 395 | __u32 queue_id; |
| 396 | /** @in_syncobjs: in, ptr to array of drm_msm_gem_syncobj */ | 396 | /** @in_syncobjs: in, ptr to array of drm_msm_syncobj */ |
| 397 | __u64 in_syncobjs; | 397 | __u64 in_syncobjs; |
| 398 | /** @out_syncobjs: in, ptr to array of drm_msm_gem_syncobj */ | 398 | /** @out_syncobjs: in, ptr to array of drm_msm_syncobj */ |
| 399 | __u64 out_syncobjs; | 399 | __u64 out_syncobjs; |
| 400 | /** @nr_in_syncobjs: in, number of entries in in_syncobj */ | 400 | /** @nr_in_syncobjs: in, number of entries in in_syncobj */ |
| 401 | __u32 nr_in_syncobjs; | 401 | __u32 nr_in_syncobjs; |