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 | 47 | - qcom,sm8650-dsi-ctrl |
| 48 | 48 | - qcom,sm8750-dsi-ctrl |
| 49 | 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 | 54 | - items: |
| 51 | 55 | - enum: |
| 52 | 56 | - qcom,qcs8300-dsi-ctrl |
| @@ -262,6 +262,7 @@ allOf: · 261 unmodified lines | ||
| 262 | 262 | compatible: |
| 263 | 263 | contains: |
| 264 | 264 | enum: |
| 265 | + - qcom,adreno-gmu-722.0 | |
| 265 | 266 | - qcom,adreno-gmu-730.1 |
| 266 | 267 | - qcom,adreno-gmu-740.1 |
| 267 | 268 | - qcom,adreno-gmu-750.1 |
| @@ -353,6 +353,7 @@ allOf: · 352 unmodified lines | ||
| 353 | 353 | - qcom,adreno-610.0 |
| 354 | 354 | - qcom,adreno-619.1 |
| 355 | 355 | - qcom,adreno-07000200 |
| 356 | + - qcom,adreno-07000400 | |
| 356 | 357 | then: |
| 357 | 358 | properties: |
| 358 | 359 | clocks: |
| @@ -413,6 +414,7 @@ allOf: · 54 unmodified lines | ||
| 413 | 414 | contains: |
| 414 | 415 | enum: |
| 415 | 416 | - qcom,adreno-44010000 |
| 417 | + - qcom,adreno-44050a01 | |
| 416 | 418 | - qcom,adreno-44070001 |
| 417 | 419 | then: |
| 418 | 420 | properties: |
| @@ -443,11 +445,13 @@ allOf: · 24 unmodified lines | ||
| 443 | 445 | - qcom,adreno-680.1 |
| 444 | 446 | - qcom,adreno-690.0 |
| 445 | 447 | - qcom,adreno-730.1 |
| 448 | + - qcom,adreno-43020100 | |
| 446 | 449 | - qcom,adreno-43030c00 |
| 447 | 450 | - qcom,adreno-43050a01 |
| 448 | 451 | - qcom,adreno-43050c01 |
| 449 | 452 | - qcom,adreno-43051401 |
| 450 | 453 | - qcom,adreno-44010000 |
| 454 | + - qcom,adreno-44050a01 | |
| 451 | 455 | - qcom,adreno-44070001 |
| 452 | 456 | |
| 453 | 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 | 14 | properties: |
| 15 | 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 | 22 | reg: |
| 19 | 23 | items: |
| @@ -4,7 +4,7 @@ · 3 unmodified lines | ||
| 4 | 4 | $id: http://devicetree.org/schemas/display/msm/qcom,qcm2290-mdss.yaml# |
| 5 | 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 | 9 | maintainers: |
| 10 | 10 | - Loic Poulain <loic.poulain@linaro.org> |
| @@ -12,13 +12,18 @@ maintainers: · 1 unmodified line | ||
| 12 | 12 | description: |
| 13 | 13 | Device tree bindings for MSM Mobile Display Subsystem(MDSS) that encapsulates |
| 14 | 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 | 18 | $ref: /schemas/display/msm/mdss-common.yaml# |
| 18 | 19 | |
| 19 | 20 | properties: |
| 20 | 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 | 28 | clocks: |
| 24 | 29 | items: |
| @@ -52,7 +57,8 @@ patternProperties: · 27 unmodified lines | ||
| 52 | 57 | |
| 53 | 58 | properties: |
| 54 | 59 | compatible: |
| 55 | − const: qcom,qcm2290-dpu | |
| 60 | + contains: | |
| 61 | + const: qcom,qcm2290-dpu | |
| 56 | 62 | |
| 57 | 63 | "^dsi@[0-9a-f]+$": |
| 58 | 64 | type: object |
| @@ -60,9 +66,8 @@ patternProperties: · 1 unmodified line | ||
| 60 | 66 | |
| 61 | 67 | properties: |
| 62 | 68 | compatible: |
| 63 | − items: | |
| 64 | − - const: qcom,qcm2290-dsi-ctrl | |
| 65 | − - const: qcom,mdss-dsi-ctrl | |
| 69 | + contains: | |
| 70 | + const: qcom,qcm2290-dsi-ctrl | |
| 66 | 71 | |
| 67 | 72 | "^phy@[0-9a-f]+$": |
| 68 | 73 | type: object |
| @@ -95,6 +95,7 @@ properties: · 94 unmodified lines | ||
| 95 | 95 | - description: Qcom Adreno GPUs implementing "qcom,smmu-500" and "arm,mmu-500" |
| 96 | 96 | items: |
| 97 | 97 | - enum: |
| 98 | + - qcom,eliza-smmu-500 | |
| 98 | 99 | - qcom,glymur-smmu-500 |
| 99 | 100 | - qcom,hawi-smmu-500 |
| 100 | 101 | - qcom,kaanapali-smmu-500 |
| @@ -108,6 +109,7 @@ properties: · 7 unmodified lines | ||
| 108 | 109 | - qcom,sc7280-smmu-500 |
| 109 | 110 | - qcom,sc8180x-smmu-500 |
| 110 | 111 | - qcom,sc8280xp-smmu-500 |
| 112 | + - qcom,shikra-smmu-500 | |
| 111 | 113 | - qcom,sm6115-smmu-500 |
| 112 | 114 | - qcom,sm6125-smmu-500 |
| 113 | 115 | - qcom,sm8150-smmu-500 |
| @@ -543,6 +545,7 @@ allOf: · 429 unmodified lines | ||
| 543 | 545 | - enum: |
| 544 | 546 | - qcom,milos-smmu-500 |
| 545 | 547 | - qcom,sar2130p-smmu-500 |
| 548 | + - qcom,shikra-smmu-500 | |
| 546 | 549 | - qcom,sm8550-smmu-500 |
| 547 | 550 | - qcom,sm8650-smmu-500 |
| 548 | 551 | - qcom,x1e80100-smmu-500 |
| @@ -570,6 +573,7 @@ allOf: · 21 unmodified lines | ||
| 570 | 573 | compatible: |
| 571 | 574 | items: |
| 572 | 575 | - enum: |
| 576 | + - qcom,eliza-smmu-500 | |
| 573 | 577 | - qcom,glymur-smmu-500 |
| 574 | 578 | - qcom,hawi-smmu-500 |
| 575 | 579 | - qcom,kaanapali-smmu-500 |
| @@ -25,6 +25,8 @@ · 24 unmodified lines | ||
| 25 | 25 | |
| 26 | 26 | extern bool hang_debug; |
| 27 | 27 | |
| 28 | +#define A3XX_VBIF_XIN_HALT_CTRL0_MASK GENMASK(5, 0) | |
| 29 | + | |
| 28 | 30 | static void a3xx_dump(struct msm_gpu *gpu); |
| 29 | 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 | 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 | 533 | static u32 a3xx_get_rptr(struct msm_gpu *gpu, struct msm_ringbuffer *ring) |
| 500 | 534 | { |
| 501 | 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 | 615 | .get_param = adreno_get_param, |
| 582 | 616 | .set_param = adreno_set_param, |
| 583 | 617 | .hw_init = a3xx_hw_init, |
| 584 | − .pm_suspend = msm_gpu_pm_suspend, | |
| 618 | + .pm_suspend = a3xx_pm_suspend, | |
| 585 | 619 | .pm_resume = msm_gpu_pm_resume, |
| 586 | 620 | .recover = a3xx_recover, |
| 587 | 621 | .submit = a3xx_submit, |
| @@ -1275,6 +1275,11 @@ static irqreturn_t a5xx_irq(struct msm_gpu *gpu) · 1274 unmodified lines | ||
| 1275 | 1275 | status & ~A5XX_RBBM_INT_0_MASK_RBBM_AHB_ERROR); |
| 1276 | 1276 | |
| 1277 | 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 | 1283 | status &= A5XX_RBBM_INT_0_MASK_CP_CACHE_FLUSH_TS | |
| 1279 | 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 | 1199 | { REG_A6XX_RBBM_CLOCK_DELAY_SP0, 0x00000080 }, |
| 1200 | 1200 | { REG_A6XX_RBBM_CLOCK_CNTL_TP0, 0x22222220 }, |
| 1201 | 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 | 1203 | { REG_A6XX_RBBM_CLOCK_CNTL4_TP0, 0x00222222 }, |
| 1204 | 1204 | { REG_A6XX_RBBM_CLOCK_HYST_TP0, 0x77777777 }, |
| 1205 | 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 | 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 | 1458 | .family = ADRENO_6XX_GEN1, /* NOT a mistake! */ |
| 1459 | 1459 | .fw = { |
| 1460 | 1460 | [ADRENO_FW_SQE] = "a702_sqe.fw", |
| @@ -1500,6 +1500,40 @@ static const struct adreno_info a7xx_gpus[] = { · 39 unmodified lines | ||
| 1500 | 1500 | .gmu_cgc_mode = 0x00020000, |
| 1501 | 1501 | }, |
| 1502 | 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 | 1538 | .chip_ids = ADRENO_CHIP_IDS(0x43050a01), /* "C510v2" */ |
| 1505 | 1539 | .family = ADRENO_7XX_GEN2, |
| @@ -2180,7 +2214,7 @@ static const struct adreno_reglist a840_gbif[] = { · 674 unmodified lines | ||
| 2180 | 2214 | { REG_A6XX_GBIF_QSB_SIDE1, 0x00071e20 }, |
| 2181 | 2215 | { REG_A6XX_GBIF_QSB_SIDE2, 0x00071e20 }, |
| 2182 | 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 | 642 | int ret; |
| 643 | 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 | 646 | return; |
| 647 | 647 | |
| 648 | 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 | 710 | gmu_write_rscc(gmu, REG_A6XX_RSCC_HIDDEN_TCS_CMD0_DATA + 2, 0); |
| 711 | 711 | gmu_write_rscc(gmu, REG_A6XX_RSCC_HIDDEN_TCS_CMD0_ADDR + 2, 0); |
| 712 | 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 | 715 | gmu_write_rscc(gmu, REG_A6XX_RSCC_HIDDEN_TCS_CMD0_ADDR + 4, 0); |
| 715 | 716 | gmu_write_rscc(gmu, REG_A6XX_RSCC_OVERRIDE_START_ADDR, 0); |
| 716 | 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 | 719 | gmu_write_rscc(gmu, REG_A6XX_RSCC_PDC_MATCH_VALUE_HI, 0x4514); |
| 719 | 720 | |
| 720 | 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 | 723 | seqmem0_drv0_reg = REG_A7XX_RSCC_SEQ_MEM_0_DRV0_A740; |
| 723 | 724 | |
| 724 | 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 | 1033 | gpu_write(gpu, gbif_cx[i].offset, gbif_cx[i].value); |
| 1033 | 1034 | |
| 1034 | 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 | 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 | 1042 | /* Set up the lowest idle level on the GMU */ |
| 1040 | 1043 | a6xx_gmu_power_config(gmu); |
| @@ -1087,7 +1090,8 @@ static void a6xx_gmu_rpmh_off(struct a6xx_gmu *gmu) · 46 unmodified lines | ||
| 1087 | 1090 | u32 val, seqmem_off = 0; |
| 1088 | 1091 | |
| 1089 | 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 | 1095 | seqmem_off = 4; |
| 1092 | 1096 | |
| 1093 | 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 | 1104 | gmu_poll_timeout_rscc(gmu, REG_A6XX_RSCC_TCS3_DRV0_STATUS + seqmem_off, |
| 1101 | 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 | 1109 | return; |
| 1105 | 1110 | |
| 1106 | 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 | 1470 | /* Stop the interrupts and mask the hardware */ |
| 1466 | 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 | 1476 | /* Tell RPMh to power off the GPU */ |
| 1469 | 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 | 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 | 1558 | if (IS_ERR(bo->obj)) |
| 1551 | 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 | 230 | bool sysprof = msm_gpu_sysprof_no_perfcntr_zap(&a6xx_gpu->base.base); |
| 231 | 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 | 233 | struct adreno_gpu *adreno_gpu = &a6xx_gpu->base; |
| 234 | 234 | phys_addr_t ttbr; |
| 235 | 235 | u32 asid; |
| @@ -1273,7 +1273,8 @@ static int hw_init(struct msm_gpu *gpu) · 1037 unmodified lines | ||
| 1273 | 1273 | if (!(adreno_is_a650_family(adreno_gpu) || |
| 1274 | 1274 | adreno_is_a702(adreno_gpu) || |
| 1275 | 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 | 1279 | /* Set the GMEM VA range [0x100000:0x100000 + gpu->gmem - 1] */ |
| 1279 | 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 | 1340 | /* Enable fault detection */ |
| 1340 | 1341 | if (adreno_is_a612(adreno_gpu) || |
| 1342 | + adreno_is_a722(adreno_gpu) || | |
| 1341 | 1343 | adreno_is_a730(adreno_gpu) || |
| 1342 | 1344 | adreno_is_a740_family(adreno_gpu)) |
| 1343 | 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 | 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 | 1919 | status &= A6XX_RBBM_INT_0_MASK_CP_CACHE_FLUSH_TS; |
| 1920 | + } | |
| 1916 | 1921 | |
| 1917 | 1922 | if (status & A6XX_RBBM_INT_0_MASK_RBBM_HANG_DETECT) |
| 1918 | 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 | 2776 | adreno_gpu->ubwc_config = qcom_ubwc_config_get_data(); |
| 2772 | 2777 | if (IS_ERR(adreno_gpu->ubwc_config)) { |
| 2778 | + ret = PTR_ERR(adreno_gpu->ubwc_config); | |
| 2773 | 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 | 2783 | /* Set up the preemption specific bits and pieces for each ringbuffer */ |
| @@ -11,12 +11,14 @@ · 10 unmodified lines | ||
| 11 | 11 | static const unsigned int *gen7_0_0_external_core_regs[] __always_unused; |
| 12 | 12 | static const unsigned int *gen7_2_0_external_core_regs[] __always_unused; |
| 13 | 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 | 15 | static const struct gen7_sptp_cluster_registers gen7_9_0_sptp_clusters[] __always_unused; |
| 15 | 16 | static const u32 gen7_9_0_cx_debugbus_blocks[] __always_unused; |
| 16 | 17 | |
| 17 | 18 | #include "adreno_gen7_0_0_snapshot.h" |
| 18 | 19 | #include "adreno_gen7_2_0_snapshot.h" |
| 19 | 20 | #include "adreno_gen7_9_0_snapshot.h" |
| 21 | +#include "adreno_gen7_17_0_snapshot.h" | |
| 20 | 22 | |
| 21 | 23 | struct a6xx_gpu_state_obj { |
| 22 | 24 | const void *handle; |
| @@ -404,8 +406,13 @@ static void a7xx_get_debugbus_blocks(struct msm_gpu *gpu, · 381 unmodified lines | ||
| 404 | 406 | int i; |
| 405 | 407 | |
| 406 | 408 | if (adreno_gpu->info->family == ADRENO_7XX_GEN1) { |
| 407 | − debugbus_blocks = gen7_0_0_debugbus_blocks; | |
| 408 | − debugbus_blocks_count = ARRAY_SIZE(gen7_0_0_debugbus_blocks); | |
| 409 | + if (adreno_is_a722(adreno_gpu)) { | |
| 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 | 416 | gbif_debugbus_blocks = a7xx_gbif_debugbus_blocks; |
| 410 | 417 | gbif_debugbus_blocks_count = ARRAY_SIZE(a7xx_gbif_debugbus_blocks); |
| 411 | 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 | 685 | unsigned dbgahb_clusters_size; |
| 679 | 686 | |
| 680 | 687 | if (adreno_gpu->info->family == ADRENO_7XX_GEN1) { |
| 681 | − dbgahb_clusters = gen7_0_0_sptp_clusters; | |
| 682 | − dbgahb_clusters_size = ARRAY_SIZE(gen7_0_0_sptp_clusters); | |
| 688 | + if (adreno_is_a722(adreno_gpu)) { | |
| 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 | 695 | } else if (adreno_gpu->info->family == ADRENO_7XX_GEN2) { |
| 684 | 696 | dbgahb_clusters = gen7_2_0_sptp_clusters; |
| 685 | 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 | 851 | unsigned clusters_size; |
| 840 | 852 | |
| 841 | 853 | if (adreno_gpu->info->family == ADRENO_7XX_GEN1) { |
| 842 | − clusters = gen7_0_0_clusters; | |
| 843 | − clusters_size = ARRAY_SIZE(gen7_0_0_clusters); | |
| 854 | + if (adreno_is_a722(adreno_gpu)) { | |
| 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 | 861 | } else if (adreno_gpu->info->family == ADRENO_7XX_GEN2) { |
| 845 | 862 | clusters = gen7_2_0_clusters; |
| 846 | 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 | 994 | int i; |
| 978 | 995 | |
| 979 | 996 | if (adreno_gpu->info->family == ADRENO_7XX_GEN1) { |
| 980 | − shader_blocks = gen7_0_0_shader_blocks; | |
| 981 | − num_shader_blocks = ARRAY_SIZE(gen7_0_0_shader_blocks); | |
| 997 | + if (adreno_is_a722(adreno_gpu)) { | |
| 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 | 1004 | } else if (adreno_gpu->info->family == ADRENO_7XX_GEN2) { |
| 983 | 1005 | shader_blocks = gen7_2_0_shader_blocks; |
| 984 | 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 | 1266 | _a6xx_get_gmu_registers(gpu, a6xx_state, &a6xx_gmu_reglist[1], |
| 1245 | 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 | 1270 | _a6xx_get_gmu_registers(gpu, a6xx_state, &a621_gpucc_reg, |
| 1249 | 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 | 1275 | else |
| 1251 | 1276 | _a6xx_get_gmu_registers(gpu, a6xx_state, &a6xx_gpucc_reg, |
| 1252 | 1277 | &a6xx_state->gmu_registers[2], false); |
| @@ -1376,8 +1401,13 @@ static void a7xx_get_registers(struct msm_gpu *gpu, · 123 unmodified lines | ||
| 1376 | 1401 | const struct gen7_reg_list *reglist; |
| 1377 | 1402 | |
| 1378 | 1403 | if (adreno_gpu->info->family == ADRENO_7XX_GEN1) { |
| 1379 | − reglist = gen7_0_0_reg_list; | |
| 1380 | − pre_crashdumper_regs = gen7_0_0_pre_crashdumper_gpu_registers; | |
| 1404 | + if (adreno_is_a722(adreno_gpu)) { | |
| 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 | 1411 | } else if (adreno_gpu->info->family == ADRENO_7XX_GEN2) { |
| 1382 | 1412 | reglist = gen7_2_0_reg_list; |
| 1383 | 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 | 1463 | const u32 *regs; |
| 1434 | 1464 | |
| 1435 | 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 | 1470 | a7xx_get_ahb_gpu_registers(gpu, |
| 1439 | 1471 | a6xx_state, regs, |
| @@ -1540,19 +1572,35 @@ static void a7xx_get_indexed_registers(struct msm_gpu *gpu, · 100 unmodified lines | ||
| 1540 | 1572 | { |
| 1541 | 1573 | struct adreno_gpu *adreno_gpu = to_adreno_gpu(gpu); |
| 1542 | 1574 | const struct a6xx_indexed_registers *indexed_regs; |
| 1575 | + const struct a6xx_indexed_registers *mempool_regs; | |
| 1543 | 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 | 1590 | indexed_regs = a7xx_indexed_reglist; |
| 1547 | 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 | 1595 | } else { |
| 1549 | 1596 | BUG_ON(adreno_gpu->info->family != ADRENO_7XX_GEN3); |
| 1550 | 1597 | indexed_regs = gen7_9_0_cp_indexed_reg_list; |
| 1551 | 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 | 1604 | a6xx_state->indexed_regs = state_kcalloc(a6xx_state, |
| 1557 | 1605 | indexed_count + mempool_count, |
| 1558 | 1606 | sizeof(*a6xx_state->indexed_regs)); |
| @@ -1567,15 +1615,17 @@ static void a7xx_get_indexed_registers(struct msm_gpu *gpu, · 8 unmodified lines | ||
| 1567 | 1615 | &a6xx_state->indexed_regs[i]); |
| 1568 | 1616 | |
| 1569 | 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 | 1621 | /* Get the contents of the CP_BV mempool */ |
| 1573 | 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 | 1624 | &a6xx_state->indexed_regs[indexed_count + i]); |
| 1576 | 1625 | |
| 1577 | 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 | 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 | 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 | 391 | /* GPU CC */ |
| 381 | 392 | 0x24000, 0x2400e, 0x24400, 0x2440e, 0x25800, 0x25804, 0x25c00, 0x25c04, |
| 382 | 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 | 414 | static const struct a6xx_registers a6xx_gpucc_reg = REGS(a6xx_gmu_gpucc_registers, 0, 0); |
| 404 | 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 | 418 | static u32 a6xx_get_cp_roq_size(struct msm_gpu *gpu); |
| 407 | 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 | 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 | 482 | #define DEBUGBUS(_id, _count) { .id = _id, .name = #_id, .count = _count } |
| 466 | 483 | |
| 467 | 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 | 228 | * GMU enables clk gating in GBIF during boot up. So, |
| 229 | 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 | 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 | 1217 | status &= A6XX_RBBM_INT_0_MASK_CP_CACHE_FLUSH_TS; |
| 1218 | + } | |
| 1216 | 1219 | |
| 1217 | 1220 | if (status & A6XX_RBBM_INT_0_MASK_RBBM_HANG_DETECT) |
| 1218 | 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 | 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 | 365 | int adreno_get_param(struct msm_gpu *gpu, struct msm_context *ctx, |
| 360 | 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 | 420 | *value = gpu->suspend_count; |
| 415 | 421 | return 0; |
| 416 | 422 | case MSM_PARAM_VA_START: |
| 417 | − if (vm == gpu->vm) | |
| 423 | + if (!valid_per_process_vm(gpu, vm)) | |
| 418 | 424 | return UERR(EINVAL, drm, "requires per-process pgtables"); |
| 419 | 425 | *value = vm->mm_start; |
| 420 | 426 | return 0; |
| 421 | 427 | case MSM_PARAM_VA_SIZE: |
| 422 | − if (vm == gpu->vm) | |
| 428 | + if (!valid_per_process_vm(gpu, vm)) | |
| 423 | 429 | return UERR(EINVAL, drm, "requires per-process pgtables"); |
| 424 | 430 | *value = vm->mm_range; |
| 425 | 431 | return 0; |
| @@ -503,9 +509,11 @@ int adreno_set_param(struct msm_gpu *gpu, struct msm_context *ctx, · 77 unmodified lines | ||
| 503 | 509 | if (!perfmon_capable()) |
| 504 | 510 | return UERR(EPERM, drm, "invalid permissions"); |
| 505 | 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 | 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 | 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 | 526 | ctx->userspace_managed_vm = value; |
| 519 | 527 | |
| 520 | 528 | return 0; |
| 529 | + } | |
| 521 | 530 | default: |
| 522 | 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 | 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 | 570 | static inline int adreno_is_a740_family(struct adreno_gpu *gpu) |
| 566 | 571 | { |
| 567 | 572 | if (WARN_ON_ONCE(!gpu->info)) |
| @@ -86,42 +86,42 @@ static const struct dpu_sspp_cfg kaanapali_sspp[] = { · 85 unmodified lines | ||
| 86 | 86 | .name = "sspp_8", .id = SSPP_DMA0, |
| 87 | 87 | .base = 0x97000, .len = 0x84, |
| 88 | 88 | .features = DMA_SDM845_MASK_SDMA, |
| 89 | − .sblk = &dpu_dma_sblk, | |
| 89 | + .sblk = &dpu_dma_sblk_v13, | |
| 90 | 90 | .xin_id = 1, |
| 91 | 91 | .type = SSPP_TYPE_DMA, |
| 92 | 92 | }, { |
| 93 | 93 | .name = "sspp_9", .id = SSPP_DMA1, |
| 94 | 94 | .base = 0xa0000, .len = 0x84, |
| 95 | 95 | .features = DMA_SDM845_MASK_SDMA, |
| 96 | − .sblk = &dpu_dma_sblk, | |
| 96 | + .sblk = &dpu_dma_sblk_v13, | |
| 97 | 97 | .xin_id = 5, |
| 98 | 98 | .type = SSPP_TYPE_DMA, |
| 99 | 99 | }, { |
| 100 | 100 | .name = "sspp_10", .id = SSPP_DMA2, |
| 101 | 101 | .base = 0xa9000, .len = 0x84, |
| 102 | 102 | .features = DMA_SDM845_MASK_SDMA, |
| 103 | − .sblk = &dpu_dma_sblk, | |
| 103 | + .sblk = &dpu_dma_sblk_v13, | |
| 104 | 104 | .xin_id = 9, |
| 105 | 105 | .type = SSPP_TYPE_DMA, |
| 106 | 106 | }, { |
| 107 | 107 | .name = "sspp_11", .id = SSPP_DMA3, |
| 108 | 108 | .base = 0xb2000, .len = 0x84, |
| 109 | 109 | .features = DMA_SDM845_MASK_SDMA, |
| 110 | − .sblk = &dpu_dma_sblk, | |
| 110 | + .sblk = &dpu_dma_sblk_v13, | |
| 111 | 111 | .xin_id = 13, |
| 112 | 112 | .type = SSPP_TYPE_DMA, |
| 113 | 113 | }, { |
| 114 | 114 | .name = "sspp_12", .id = SSPP_DMA4, |
| 115 | 115 | .base = 0xbb000, .len = 0x84, |
| 116 | 116 | .features = DMA_CURSOR_SDM845_MASK_SDMA, |
| 117 | − .sblk = &dpu_dma_sblk, | |
| 117 | + .sblk = &dpu_dma_sblk_v13, | |
| 118 | 118 | .xin_id = 14, |
| 119 | 119 | .type = SSPP_TYPE_DMA, |
| 120 | 120 | }, { |
| 121 | 121 | .name = "sspp_13", .id = SSPP_DMA5, |
| 122 | 122 | .base = 0xc4000, .len = 0x84, |
| 123 | 123 | .features = DMA_CURSOR_SDM845_MASK_SDMA, |
| 124 | − .sblk = &dpu_dma_sblk, | |
| 124 | + .sblk = &dpu_dma_sblk_v13, | |
| 125 | 125 | .xin_id = 15, |
| 126 | 126 | .type = SSPP_TYPE_DMA, |
| 127 | 127 | }, |
| @@ -34,7 +34,7 @@ enum dpu_perf_mode { · 33 unmodified lines | ||
| 34 | 34 | /** |
| 35 | 35 | * dpu_core_perf_adjusted_mode_clk - Adjust given mode clock rate according to |
| 36 | 36 | * the perf clock factor. |
| 37 | − * @crtc_clk_rate - Unadjusted mode clock rate | |
| 37 | + * @mode_clk_rate: unadjusted mode clock rate | |
| 38 | 38 | * @perf_cfg: performance configuration |
| 39 | 39 | */ |
| 40 | 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 | 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 | 401 | clk_rate = min(clk_rate, kms->perf.max_core_clk_rate); |
| 398 | 402 | ret = dev_pm_opp_set_rate(&kms->pdev->dev, clk_rate); |
| 399 | 403 | if (ret) { |
| @@ -710,8 +710,7 @@ void dpu_encoder_update_topology(struct drm_encoder *drm_enc, · 709 unmodified lines | ||
| 710 | 710 | if (fb && MSM_FORMAT_IS_YUV(msm_framebuffer_format(fb))) |
| 711 | 711 | topology->num_cdm++; |
| 712 | 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]], | |
| 714 | − adj_mode)) | |
| 713 | + if (drm_mode_is_420_only(&connector->display_info, adj_mode)) | |
| 715 | 714 | topology->num_cdm++; |
| 716 | 715 | } |
| 717 | 716 | } |
| @@ -303,6 +303,16 @@ static const u32 wb2_formats_rgb_yuv[] = { · 302 unmodified lines | ||
| 303 | 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 | 316 | static const struct dpu_rotation_cfg dpu_rot_sc7280_cfg_v2 = { |
| 307 | 317 | .rot_maxheight = 1088, |
| 308 | 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 | 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 | 369 | * MIXER sub blocks config |
| 358 | 370 | *************************************************************/ |
| @@ -398,7 +398,7 @@ static int mdp4_kms_init(struct drm_device *dev) · 397 unmodified lines | ||
| 398 | 398 | ret = mdp_kms_init(&mdp4_kms->base, &kms_funcs); |
| 399 | 399 | if (ret) { |
| 400 | 400 | DRM_DEV_ERROR(dev->dev, "failed to init kms\n"); |
| 401 | − goto fail; | |
| 401 | + return ret; | |
| 402 | 402 | } |
| 403 | 403 | |
| 404 | 404 | kms = priv->kms; |
| @@ -409,7 +409,7 @@ static int mdp4_kms_init(struct drm_device *dev) · 4 unmodified lines | ||
| 409 | 409 | ret = regulator_enable(mdp4_kms->vdd); |
| 410 | 410 | if (ret) { |
| 411 | 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 | 421 | DRM_DEV_ERROR(dev->dev, "unexpected MDP version: v%d.%d\n", |
| 422 | 422 | major, minor); |
| 423 | 423 | ret = -ENXIO; |
| 424 | − goto fail; | |
| 424 | + return ret; | |
| 425 | 425 | } |
| 426 | 426 | |
| 427 | 427 | mdp4_kms->rev = minor; |
| @@ -430,7 +430,7 @@ static int mdp4_kms_init(struct drm_device *dev) · 2 unmodified lines | ||
| 430 | 430 | if (!mdp4_kms->lut_clk) { |
| 431 | 431 | DRM_DEV_ERROR(dev->dev, "failed to get lut_clk\n"); |
| 432 | 432 | ret = -ENODEV; |
| 433 | − goto fail; | |
| 433 | + return ret; | |
| 434 | 434 | } |
| 435 | 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 | 452 | vm = msm_kms_init_vm(mdp4_kms->dev, NULL); |
| 453 | 453 | if (IS_ERR(vm)) { |
| 454 | 454 | ret = PTR_ERR(vm); |
| 455 | − goto fail; | |
| 455 | + return ret; | |
| 456 | 456 | } |
| 457 | 457 | |
| 458 | 458 | kms->vm = vm; |
| @@ -460,22 +460,22 @@ static int mdp4_kms_init(struct drm_device *dev) · 1 unmodified line | ||
| 460 | 460 | ret = modeset_init(mdp4_kms); |
| 461 | 461 | if (ret) { |
| 462 | 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 | 467 | if (IS_ERR(mdp4_kms->blank_cursor_bo)) { |
| 468 | 468 | ret = PTR_ERR(mdp4_kms->blank_cursor_bo); |
| 469 | 469 | DRM_DEV_ERROR(dev->dev, "could not allocate blank-cursor bo: %d\n", ret); |
| 470 | 470 | mdp4_kms->blank_cursor_bo = NULL; |
| 471 | − goto fail; | |
| 471 | + return ret; | |
| 472 | 472 | } |
| 473 | 473 | |
| 474 | 474 | ret = msm_gem_get_and_pin_iova(mdp4_kms->blank_cursor_bo, kms->vm, |
| 475 | 475 | &mdp4_kms->blank_cursor_iova); |
| 476 | 476 | if (ret) { |
| 477 | 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 | 481 | dev->mode_config.min_width = 0; |
| @@ -484,12 +484,6 @@ static int mdp4_kms_init(struct drm_device *dev) · 2 unmodified lines | ||
| 484 | 484 | dev->mode_config.max_height = 2048; |
| 485 | 485 | |
| 486 | 486 | return 0; |
| 487 | − | |
| 488 | −fail: | |
| 489 | − if (kms) | |
| 490 | − mdp4_destroy(kms); | |
| 491 | − | |
| 492 | − return ret; | |
| 493 | 487 | } |
| 494 | 488 | |
| 495 | 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 | 517 | ret = mdp_kms_init(&mdp5_kms->base, &kms_funcs); |
| 518 | 518 | if (ret) { |
| 519 | 519 | DRM_DEV_ERROR(&pdev->dev, "failed to init kms\n"); |
| 520 | − goto fail; | |
| 520 | + return ret; | |
| 521 | 521 | } |
| 522 | 522 | |
| 523 | 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 | 540 | vm = msm_kms_init_vm(mdp5_kms->dev, pdev->dev.parent); |
| 541 | 541 | if (IS_ERR(vm)) { |
| 542 | 542 | ret = PTR_ERR(vm); |
| 543 | − goto fail; | |
| 543 | + return ret; | |
| 544 | 544 | } |
| 545 | 545 | |
| 546 | 546 | kms->vm = vm; |
| @@ -550,7 +550,7 @@ static int mdp5_kms_init(struct drm_device *dev) · 3 unmodified lines | ||
| 550 | 550 | ret = modeset_init(mdp5_kms); |
| 551 | 551 | if (ret) { |
| 552 | 552 | DRM_DEV_ERROR(&pdev->dev, "modeset_init failed: %d\n", ret); |
| 553 | − goto fail; | |
| 553 | + return ret; | |
| 554 | 554 | } |
| 555 | 555 | |
| 556 | 556 | dev->mode_config.min_width = 0; |
| @@ -562,11 +562,6 @@ static int mdp5_kms_init(struct drm_device *dev) · 5 unmodified lines | ||
| 562 | 562 | dev->vblank_disable_immediate = true; |
| 563 | 563 | |
| 564 | 564 | return 0; |
| 565 | −fail: | |
| 566 | − if (kms) | |
| 567 | − mdp5_kms_destroy(kms); | |
| 568 | − | |
| 569 | − return ret; | |
| 570 | 565 | } |
| 571 | 566 | |
| 572 | 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 | 284 | * such cases check for connection status and bail out if not |
| 285 | 285 | * connected. |
| 286 | 286 | */ |
| 287 | − if (!msm_dp_display->power_on) { | |
| 288 | − rc = -EINVAL; | |
| 287 | + if (!msm_dp_display->power_on) | |
| 289 | 288 | goto end; |
| 290 | − } | |
| 291 | 289 | |
| 292 | 290 | audio = msm_dp_audio_get_data(msm_dp_display); |
| 293 | 291 | if (IS_ERR(audio)) { |
| @@ -114,7 +114,6 @@ struct msm_dp_ctrl_private { · 113 unmodified lines | ||
| 114 | 114 | struct drm_device *drm_dev; |
| 115 | 115 | struct device *dev; |
| 116 | 116 | struct drm_dp_aux *aux; |
| 117 | − struct msm_dp_panel *panel; | |
| 118 | 117 | struct msm_dp_link *link; |
| 119 | 118 | void __iomem *ahb_base; |
| 120 | 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 | 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 | 207 | struct msm_dp_ctrl_private *ctrl = |
| 208 | 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 | 217 | sw_reset &= ~DP_SW_RESET; |
| 218 | 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 | 221 | ctrl->hw_revision = msm_dp_read_ahb(ctrl, REG_DP_HW_VERSION); |
| 222 | − ctrl->panel->hw_revision = ctrl->hw_revision; | |
| 223 | − } | |
| 222 | + panel->hw_revision = ctrl->hw_revision; | |
| 224 | 223 | } |
| 225 | 224 | |
| 226 | 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 | 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 | 393 | u32 config = 0, tbd; |
| 394 | − const u8 *dpcd = ctrl->panel->dpcd; | |
| 395 | 394 | |
| 396 | − /* Default-> LSCLK DIV: 1/4 LCLK */ | |
| 397 | − config |= (2 << DP_CONFIGURATION_CTRL_LSCLK_DIV_SHIFT); | |
| 395 | + /* | |
| 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 | 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 | 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 | 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 | 433 | /* Num of Lanes */ |
| 412 | 434 | config |= ((ctrl->link->link_params.num_lanes - 1) |
| 413 | 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 | 443 | config |= DP_CONFIGURATION_CTRL_STATIC_DYNAMIC_CN; |
| 422 | 444 | config |= DP_CONFIGURATION_CTRL_SYNC_ASYNC_CLK; |
| 423 | 445 | |
| 424 | − if (ctrl->panel->psr_cap.version) | |
| 425 | − config |= DP_CONFIGURATION_CTRL_SEND_VSC; | |
| 426 | − | |
| 427 | − drm_dbg_dp(ctrl->drm_dev, "DP_CONFIGURATION_CTRL=0x%x\n", config); | |
| 446 | + drm_dbg_dp(ctrl->drm_dev, "link DP_CONFIGURATION_CTRL=0x%x\n", config); | |
| 428 | 447 | |
| 429 | 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 | 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 | 468 | u32 colorimetry_cfg, test_bits_depth, misc_val; |
| 449 | 469 | |
| 450 | − msm_dp_ctrl_lane_mapping(ctrl); | |
| 451 | − msm_dp_setup_peripheral_flush(ctrl); | |
| 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); | |
| 470 | + test_bits_depth = msm_dp_link_get_test_bits_depth(ctrl->link, | |
| 471 | + msm_dp_panel->msm_dp_mode.bpp); | |
| 456 | 472 | colorimetry_cfg = msm_dp_link_get_colorimetry_config(ctrl->link); |
| 457 | 473 | |
| 458 | 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 | 483 | drm_dbg_dp(ctrl->drm_dev, "misc settings = 0x%x\n", misc_val); |
| 468 | 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 | 1263 | static void msm_dp_ctrl_calc_tu_parameters(struct msm_dp_ctrl_private *ctrl, |
| 1264 | + struct msm_dp_panel *panel, | |
| 1240 | 1265 | struct msm_dp_vc_tu_mapping_table *tu_table) |
| 1241 | 1266 | { |
| 1242 | 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 | 1272 | in.lclk = ctrl->link->link_params.rate / 1000; |
| 1248 | 1273 | in.pclk_khz = drm_mode->clock; |
| 1249 | 1274 | in.hactive = drm_mode->hdisplay; |
| 1250 | 1275 | in.hporch = drm_mode->htotal - drm_mode->hdisplay; |
| 1251 | 1276 | in.nlanes = ctrl->link->link_params.num_lanes; |
| 1252 | − in.bpp = ctrl->panel->msm_dp_mode.bpp; | |
| 1253 | − in.pixel_enc = ctrl->panel->msm_dp_mode.out_fmt_is_yuv_420 ? 420 : 444; | |
| 1277 | + in.bpp = panel->msm_dp_mode.bpp; | |
| 1278 | + in.pixel_enc = panel->msm_dp_mode.out_fmt_is_yuv_420 ? 420 : 444; | |
| 1254 | 1279 | in.dsc_en = 0; |
| 1255 | 1280 | in.async_en = 0; |
| 1256 | 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 | 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 | 1291 | u32 msm_dp_tu = 0x0; |
| 1266 | 1292 | u32 valid_boundary = 0x0; |
| 1267 | 1293 | u32 valid_boundary2 = 0x0; |
| 1268 | 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 | 1298 | msm_dp_tu |= tu_calc_table.tu_size_minus1; |
| 1273 | 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 | 1447 | static int msm_dp_ctrl_link_train_1(struct msm_dp_ctrl_private *ctrl, |
| 1448 | + struct msm_dp_panel *panel, | |
| 1422 | 1449 | int *training_step, enum drm_dp_phy dp_phy) |
| 1423 | 1450 | { |
| 1424 | 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 | 1454 | int const maximum_retries = 4; |
| 1428 | 1455 | |
| 1429 | 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 | 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 | 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 | 1547 | if (ctrl->link->link_params.num_lanes == 1) |
| 1520 | 1548 | return -1; |
| 1521 | 1549 | |
| 1522 | 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 | 1553 | ctrl->link->phy_params.p_level = 0; |
| 1526 | 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 | 1559 | static void msm_dp_ctrl_clear_training_pattern(struct msm_dp_ctrl_private *ctrl, |
| 1560 | + struct msm_dp_panel *panel, | |
| 1532 | 1561 | enum drm_dp_phy dp_phy) |
| 1533 | 1562 | { |
| 1534 | 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 | 1565 | msm_dp_ctrl_train_pattern_set(ctrl, DP_TRAINING_PATTERN_DISABLE, dp_phy); |
| 1537 | 1566 | |
| 1538 | 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 | 1569 | fsleep(delay_us); |
| 1541 | 1570 | } |
| 1542 | 1571 | |
| 1543 | 1572 | static int msm_dp_ctrl_link_train_2(struct msm_dp_ctrl_private *ctrl, |
| 1573 | + struct msm_dp_panel *panel, | |
| 1544 | 1574 | int *training_step, enum drm_dp_phy dp_phy) |
| 1545 | 1575 | { |
| 1546 | 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 | 1581 | u8 link_status[DP_LINK_STATUS_SIZE]; |
| 1552 | 1582 | |
| 1553 | 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 | 1586 | msm_dp_write_link(ctrl, REG_DP_STATE_CTRL, 0); |
| 1557 | 1587 | |
| 1558 | 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 | 1591 | pattern = DP_TRAINING_PATTERN_4; |
| 1562 | 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 | 1594 | pattern = DP_TRAINING_PATTERN_3; |
| 1565 | 1595 | state_ctrl_bit = 3; |
| 1566 | 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 | 1629 | static int msm_dp_ctrl_link_train_1_2(struct msm_dp_ctrl_private *ctrl, |
| 1630 | + struct msm_dp_panel *panel, | |
| 1600 | 1631 | int *training_step, enum drm_dp_phy dp_phy) |
| 1601 | 1632 | { |
| 1602 | 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 | 1636 | if (ret) { |
| 1606 | 1637 | DRM_ERROR("link training #1 on phy %d failed. ret=%d\n", dp_phy, ret); |
| 1607 | 1638 | return ret; |
| 1608 | 1639 | } |
| 1609 | 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 | 1643 | if (ret) { |
| 1613 | 1644 | DRM_ERROR("link training #2 on phy %d failed. ret=%d\n", dp_phy, ret); |
| 1614 | 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 | 1652 | static int msm_dp_ctrl_link_train(struct msm_dp_ctrl_private *ctrl, |
| 1653 | + struct msm_dp_panel *panel, | |
| 1622 | 1654 | int *training_step) |
| 1623 | 1655 | { |
| 1624 | 1656 | int i; |
| 1625 | 1657 | int ret = 0; |
| 1626 | − const u8 *dpcd = ctrl->panel->dpcd; | |
| 1658 | + const u8 *dpcd = panel->dpcd; | |
| 1627 | 1659 | u8 encoding[] = { 0, DP_SET_ANSI_8B10B }; |
| 1628 | 1660 | u8 assr; |
| 1629 | 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 | 1666 | link_info.num_lanes = ctrl->link->link_params.num_lanes; |
| 1634 | 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 | 1684 | for (i = ctrl->link->lttpr_count - 1; i >= 0; i--) { |
| 1652 | 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); | |
| 1655 | − msm_dp_ctrl_clear_training_pattern(ctrl, dp_phy); | |
| 1687 | + ret = msm_dp_ctrl_link_train_1_2(ctrl, panel, training_step, dp_phy); | |
| 1688 | + msm_dp_ctrl_clear_training_pattern(ctrl, panel, dp_phy); | |
| 1656 | 1689 | |
| 1657 | 1690 | if (ret) |
| 1658 | 1691 | break; |
| @@ -1663,7 +1696,7 @@ static int msm_dp_ctrl_link_train(struct msm_dp_ctrl_private *ctrl, · 4 unmodified lines | ||
| 1663 | 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 | 1700 | if (ret) { |
| 1668 | 1701 | DRM_ERROR("link training on sink failed. ret=%d\n", ret); |
| 1669 | 1702 | goto end; |
| @@ -1676,6 +1709,7 @@ end: · 6 unmodified lines | ||
| 1676 | 1709 | } |
| 1677 | 1710 | |
| 1678 | 1711 | static int msm_dp_ctrl_setup_main_link(struct msm_dp_ctrl_private *ctrl, |
| 1712 | + struct msm_dp_panel *panel, | |
| 1679 | 1713 | int *training_step) |
| 1680 | 1714 | { |
| 1681 | 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 | 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 | 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 | 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 | 1830 | int ret = 0; |
| 1796 | 1831 | struct phy *phy = ctrl->phy; |
| 1797 | − const u8 *dpcd = ctrl->panel->dpcd; | |
| 1832 | + const u8 *dpcd = panel->dpcd; | |
| 1798 | 1833 | |
| 1799 | 1834 | ctrl->phy_opts.dp.lanes = ctrl->link->link_params.num_lanes; |
| 1800 | 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 | 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 | 1887 | struct msm_dp_ctrl_private *ctrl = container_of(msm_dp_ctrl, |
| 1852 | 1888 | struct msm_dp_ctrl_private, msm_dp_ctrl); |
| 1853 | 1889 | u32 cfg; |
| 1854 | 1890 | |
| 1855 | − if (!ctrl->panel->psr_cap.version) | |
| 1891 | + if (!panel->psr_cap.version) | |
| 1856 | 1892 | return; |
| 1857 | 1893 | |
| 1858 | 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 | 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 | 1909 | struct msm_dp_ctrl_private *ctrl = container_of(msm_dp_ctrl, |
| 1873 | 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 | 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 | 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 | 1985 | struct phy *phy = ctrl->phy; |
| 1948 | 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 | 1988 | msm_dp_ctrl_mainlink_disable(ctrl); |
| 1951 | 1989 | ctrl->phy_opts.dp.lanes = ctrl->link->link_params.num_lanes; |
| 1952 | 1990 | phy_configure(phy, &ctrl->phy_opts); |
| 1991 | + | |
| 1953 | 1992 | /* |
| 1954 | 1993 | * Disable and re-enable the mainlink clock since the |
| 1955 | 1994 | * link clock might have been adjusted as part of the |
| 1956 | 1995 | * link maintenance. |
| 1957 | 1996 | */ |
| 1958 | − dev_pm_opp_set_rate(ctrl->dev, 0); | |
| 1959 | − | |
| 1960 | 1997 | msm_dp_ctrl_link_clk_disable(&ctrl->msm_dp_ctrl); |
| 1961 | 1998 | |
| 1962 | 1999 | phy_power_off(phy); |
| 1963 | 2000 | /* hw recommended delay before re-enabling clocks */ |
| 1964 | 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 | 2004 | if (ret) { |
| 1968 | 2005 | DRM_ERROR("Failed to enable mainlink clks. ret=%d\n", ret); |
| 1969 | 2006 | return ret; |
| @@ -1972,7 +2009,8 @@ static int msm_dp_ctrl_reinitialize_mainlink(struct msm_dp_ctrl_private *ctrl) · 2 unmodified lines | ||
| 1972 | 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 | 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 | 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 | 2023 | msm_dp_ctrl_link_clk_disable(&ctrl->msm_dp_ctrl); |
| 1987 | 2024 | |
| 1988 | 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 | 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 | 2037 | int ret = 0; |
| 2000 | 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 | 2042 | ctrl->link->phy_params.p_level = 0; |
| 2005 | 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 | 2046 | if (ret) |
| 2009 | 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 | 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 | 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 | 2231 | int ret; |
| 2158 | 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 | 2242 | * running. Add the global reset just before disabling the |
| 2169 | 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 | 2249 | if (ret) { |
| 2175 | 2250 | DRM_ERROR("failed to enable DP link controller\n"); |
| 2176 | 2251 | return ret; |
| 2177 | 2252 | } |
| 2178 | 2253 | |
| 2179 | − pixel_rate = ctrl->panel->msm_dp_mode.drm_mode.clock; | |
| 2180 | − ret = clk_set_rate(ctrl->pixel_clk, pixel_rate * 1000); | |
| 2181 | − if (ret) { | |
| 2182 | − DRM_ERROR("Failed to set pixel clock rate. ret=%d\n", ret); | |
| 2254 | + pixel_rate = panel->msm_dp_mode.drm_mode.clock; | |
| 2255 | + ret = msm_dp_ctrl_on_pixel_clk(ctrl, pixel_rate); | |
| 2256 | + if (ret) | |
| 2183 | 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 | 2259 | msm_dp_ctrl_send_phy_test_pattern(ctrl); |
| 2198 | 2260 | |
| 2199 | 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 | 2267 | struct msm_dp_ctrl_private *ctrl; |
| 2205 | 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 | 2278 | if (sink_request & DP_TEST_LINK_PHY_TEST_PATTERN) { |
| 2216 | 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 | 2281 | DRM_ERROR("process phy_test_req failed\n"); |
| 2219 | 2282 | return; |
| 2220 | 2283 | } |
| 2221 | 2284 | } |
| 2222 | 2285 | |
| 2223 | 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 | 2288 | DRM_ERROR("LM failed: TEST_LINK_TRAINING\n"); |
| 2226 | 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 | 2293 | if (sink_request & DP_TEST_LINK_TRAINING) { |
| 2231 | 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 | 2296 | DRM_ERROR("LM failed: TEST_LINK_TRAINING\n"); |
| 2234 | 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 | 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 | 2334 | int rc = 0; |
| 2271 | 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 | 2346 | ctrl = container_of(msm_dp_ctrl, struct msm_dp_ctrl_private, msm_dp_ctrl); |
| 2283 | 2347 | |
| 2284 | − rate = ctrl->panel->link_info.rate; | |
| 2285 | − pixel_rate = ctrl->panel->msm_dp_mode.drm_mode.clock; | |
| 2348 | + rate = panel->link_info.rate; | |
| 2349 | + pixel_rate = panel->msm_dp_mode.drm_mode.clock; | |
| 2286 | 2350 | |
| 2287 | 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 | 2358 | } else { |
| 2295 | 2359 | ctrl->link->link_params.rate = rate; |
| 2296 | 2360 | ctrl->link->link_params.num_lanes = |
| 2297 | − ctrl->panel->link_info.num_lanes; | |
| 2298 | − if (ctrl->panel->msm_dp_mode.out_fmt_is_yuv_420) | |
| 2361 | + panel->link_info.num_lanes; | |
| 2362 | + if (panel->msm_dp_mode.out_fmt_is_yuv_420) | |
| 2299 | 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 | 2367 | ctrl->link->link_params.rate, ctrl->link->link_params.num_lanes, |
| 2304 | 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 | 2371 | if (rc) |
| 2308 | 2372 | return rc; |
| 2309 | 2373 | |
| 2310 | 2374 | while (--link_train_max_retries) { |
| 2311 | 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 | 2377 | if (rc == 0) { |
| 2314 | 2378 | /* training completed successfully */ |
| 2315 | 2379 | break; |
| @@ -2328,7 +2392,7 @@ int msm_dp_ctrl_on_link(struct msm_dp_ctrl *msm_dp_ctrl) · 12 unmodified lines | ||
| 2328 | 2392 | * some lanes are ready, |
| 2329 | 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 | 2396 | if (rc < 0) { /* lane == 1 already */ |
| 2333 | 2397 | /* end with failure */ |
| 2334 | 2398 | break; |
| @@ -2349,7 +2413,7 @@ int msm_dp_ctrl_on_link(struct msm_dp_ctrl *msm_dp_ctrl) · 14 unmodified lines | ||
| 2349 | 2413 | ctrl->link->link_params.num_lanes)) |
| 2350 | 2414 | rc = msm_dp_ctrl_link_rate_down_shift(ctrl); |
| 2351 | 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 | 2418 | if (rc < 0) { |
| 2355 | 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 | 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 | 2428 | if (rc) { |
| 2365 | 2429 | DRM_ERROR("Failed to reinitialize mainlink. rc=%d\n", rc); |
| 2366 | 2430 | break; |
| @@ -2381,20 +2445,21 @@ int msm_dp_ctrl_on_link(struct msm_dp_ctrl *msm_dp_ctrl) · 14 unmodified lines | ||
| 2381 | 2445 | * link training failed |
| 2382 | 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 | 2451 | rc = -ECONNRESET; |
| 2388 | 2452 | } |
| 2389 | 2453 | |
| 2390 | 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 | 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 | 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 | 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 | 2537 | int ret = 0; |
| 2471 | − bool mainlink_ready = false; | |
| 2472 | 2538 | struct msm_dp_ctrl_private *ctrl; |
| 2473 | − unsigned long pixel_rate; | |
| 2474 | − unsigned long pixel_rate_orig; | |
| 2475 | 2539 | |
| 2476 | 2540 | if (!msm_dp_ctrl) |
| 2477 | 2541 | return -EINVAL; |
| 2478 | 2542 | |
| 2479 | 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; | |
| 2482 | − | |
| 2483 | − if (msm_dp_ctrl->wide_bus_en || ctrl->panel->msm_dp_mode.out_fmt_is_yuv_420) | |
| 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); | |
| 2545 | + drm_dbg_dp(ctrl->drm_dev, "rate=%d, num_lanes=%d\n", | |
| 2546 | + ctrl->link->link_params.rate, | |
| 2547 | + ctrl->link->link_params.num_lanes); | |
| 2489 | 2548 | |
| 2490 | 2549 | drm_dbg_dp(ctrl->drm_dev, |
| 2491 | 2550 | "core_clk_on=%d link_clk_on=%d stream_clk_on=%d\n", |
| 2492 | 2551 | ctrl->core_clks_on, ctrl->link_clks_on, ctrl->stream_clks_on); |
| 2493 | 2552 | |
| 2494 | 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 | 2555 | if (ret) { |
| 2497 | 2556 | DRM_ERROR("Failed to start link clocks. ret=%d\n", ret); |
| 2498 | − goto end; | |
| 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; | |
| 2557 | + return ret; | |
| 2515 | 2558 | } |
| 2516 | − ctrl->stream_clks_on = true; | |
| 2517 | 2559 | } |
| 2518 | 2560 | |
| 2519 | 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 | 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 | 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 | 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 | 2607 | msm_dp_ctrl_config_msa(ctrl, |
| 2534 | 2608 | ctrl->link->link_params.rate, |
| 2535 | 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 | 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 | 2623 | drm_dbg_dp(ctrl->drm_dev, |
| 2550 | 2624 | "mainlink %s\n", mainlink_ready ? "READY" : "NOT READY"); |
| 2551 | 2625 | |
| 2552 | −end: | |
| 2553 | 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 | 2631 | struct msm_dp_ctrl_private *ctrl; |
| 2559 | 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 | 2634 | ctrl = container_of(msm_dp_ctrl, struct msm_dp_ctrl_private, msm_dp_ctrl); |
| 2562 | 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 | 2637 | /* aux channel down, reinit phy */ |
| 2582 | 2638 | phy_exit(phy); |
| 2583 | 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 | 2645 | struct msm_dp_ctrl_private *ctrl; |
| 2589 | 2646 | struct phy *phy; |
| @@ -2591,24 +2648,19 @@ void msm_dp_ctrl_off(struct msm_dp_ctrl *msm_dp_ctrl) · 1 unmodified line | ||
| 2591 | 2648 | ctrl = container_of(msm_dp_ctrl, struct msm_dp_ctrl_private, msm_dp_ctrl); |
| 2592 | 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 | 2653 | msm_dp_ctrl_mainlink_disable(ctrl); |
| 2597 | 2654 | |
| 2598 | − msm_dp_ctrl_reset(&ctrl->msm_dp_ctrl); | |
| 2599 | − | |
| 2600 | − if (ctrl->stream_clks_on) { | |
| 2601 | − clk_disable_unprepare(ctrl->pixel_clk); | |
| 2602 | − ctrl->stream_clks_on = false; | |
| 2603 | − } | |
| 2655 | + msm_dp_ctrl_reset(&ctrl->msm_dp_ctrl, panel); | |
| 2604 | 2656 | |
| 2605 | − dev_pm_opp_set_rate(ctrl->dev, 0); | |
| 2606 | 2657 | msm_dp_ctrl_link_clk_disable(&ctrl->msm_dp_ctrl); |
| 2607 | 2658 | |
| 2608 | 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 | 2665 | struct msm_dp_ctrl_private *ctrl; |
| 2614 | 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 | 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 | 2675 | isr = msm_dp_ctrl_get_psr_interrupt(ctrl); |
| 2624 | 2676 | |
| 2625 | 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 | 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 | 2764 | struct phy *phy, |
| 2713 | 2765 | void __iomem *ahb_base, |
| 2714 | 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 | 2768 | struct msm_dp_ctrl_private *ctrl; |
| 2717 | 2769 | int ret; |
| 2718 | 2770 | |
| 2719 | − if (!dev || !panel || !aux || !link) { | |
| 2771 | + if (!dev || !aux || !link) { | |
| 2720 | 2772 | DRM_ERROR("invalid input\n"); |
| 2721 | 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 | 2796 | init_completion(&ctrl->video_comp); |
| 2745 | 2797 | |
| 2746 | 2798 | /* in parameters */ |
| 2747 | − ctrl->panel = panel; | |
| 2748 | 2799 | ctrl->aux = aux; |
| 2749 | 2800 | ctrl->link = link; |
| 2750 | 2801 | ctrl->dev = dev; |
| @@ -16,28 +16,37 @@ struct msm_dp_ctrl { · 15 unmodified lines | ||
| 16 | 16 | |
| 17 | 17 | struct phy; |
| 18 | 18 | |
| 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); | |
| 21 | −void msm_dp_ctrl_off_link_stream(struct msm_dp_ctrl *msm_dp_ctrl); | |
| 22 | −void msm_dp_ctrl_off(struct msm_dp_ctrl *msm_dp_ctrl); | |
| 19 | +int msm_dp_ctrl_on_link(struct msm_dp_ctrl *msm_dp_ctrl, | |
| 20 | + struct msm_dp_panel *panel); | |
| 21 | +int msm_dp_ctrl_on_stream(struct msm_dp_ctrl *msm_dp_ctrl, struct msm_dp_panel *panel); | |
| 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 | 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); | |
| 25 | −void msm_dp_ctrl_handle_sink_request(struct msm_dp_ctrl *msm_dp_ctrl); | |
| 29 | +irqreturn_t msm_dp_ctrl_isr(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 | 33 | struct msm_dp_ctrl *msm_dp_ctrl_get(struct device *dev, |
| 27 | 34 | struct msm_dp_link *link, |
| 28 | − struct msm_dp_panel *panel, | |
| 29 | 35 | struct drm_dp_aux *aux, |
| 30 | 36 | struct phy *phy, |
| 31 | 37 | void __iomem *ahb_base, |
| 32 | 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 | 42 | void msm_dp_ctrl_phy_init(struct msm_dp_ctrl *msm_dp_ctrl); |
| 36 | 43 | void msm_dp_ctrl_phy_exit(struct msm_dp_ctrl *msm_dp_ctrl); |
| 37 | 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); | |
| 40 | −void msm_dp_ctrl_config_psr(struct msm_dp_ctrl *msm_dp_ctrl); | |
| 46 | +void msm_dp_ctrl_set_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 | 51 | int msm_dp_ctrl_core_clk_enable(struct msm_dp_ctrl *msm_dp_ctrl); |
| 43 | 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 | 54 | void msm_dp_ctrl_enable_irq(struct msm_dp_ctrl *msm_dp_ctrl); |
| 46 | 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 | 58 | #endif /* _DP_CTRL_H_ */ |
| @@ -63,7 +63,6 @@ struct msm_dp_display_private { · 62 unmodified lines | ||
| 63 | 63 | struct msm_dp_panel *panel; |
| 64 | 64 | struct msm_dp_ctrl *ctrl; |
| 65 | 65 | |
| 66 | − struct msm_dp_display_mode msm_dp_mode; | |
| 67 | 66 | struct msm_dp msm_dp_display; |
| 68 | 67 | |
| 69 | 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 | 268 | const struct drm_display_info *info = &connector->display_info; |
| 270 | 269 | int rc = 0; |
| 271 | 270 | u8 dpcd[DP_RECEIVER_CAP_SIZE]; |
| 271 | + const struct drm_edid *drm_edid = NULL; | |
| 272 | 272 | |
| 273 | 273 | rc = drm_dp_read_dpcd_caps(dp->aux, dpcd); |
| 274 | 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 | 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 | 280 | if (rc) |
| 281 | 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 | 293 | msm_dp_link_process_request(dp->link); |
| 284 | 294 | |
| 285 | 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 | 301 | dp->msm_dp_display.psr_supported = dp->panel->psr_cap.version && psr_enabled; |
| 292 | 302 | |
| 293 | 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 | 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 | 312 | msm_dp_link_reset_phy_params_vx_px(dp->link); |
| 303 | 313 | |
| 304 | 314 | end: |
| 315 | + drm_edid_free(drm_edid); | |
| 305 | 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 | 359 | dp->phy_initialized); |
| 349 | 360 | |
| 350 | 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 | 363 | msm_dp_ctrl_enable_irq(dp->ctrl); |
| 353 | 364 | msm_dp_aux_init(dp->aux); |
| 354 | 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 | 371 | dp->msm_dp_display.connector_type, dp->core_initialized, |
| 361 | 372 | dp->phy_initialized); |
| 362 | 373 | |
| 363 | − msm_dp_ctrl_reset(dp->ctrl); | |
| 374 | + msm_dp_ctrl_reset(dp->ctrl, dp->panel); | |
| 364 | 375 | msm_dp_ctrl_disable_irq(dp->ctrl); |
| 365 | 376 | msm_dp_aux_deinit(dp->aux); |
| 366 | 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 | 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 | 397 | if (sink_request & DP_TEST_LINK_VIDEO_PATTERN) |
| 387 | 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 | 465 | /* Don't forget modes for eDP */ |
| 455 | 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 | 469 | /* triggered by irq_hdp with sink_count = 0 */ |
| 459 | 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 | 526 | static void msm_dp_display_deinit_sub_modules(struct msm_dp_display_private *dp) |
| 516 | 527 | { |
| 517 | 528 | msm_dp_audio_put(dp->audio); |
| 518 | − msm_dp_panel_put(dp->panel); | |
| 519 | 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 | 570 | goto error_link; |
| 561 | 571 | } |
| 562 | 572 | |
| 563 | − dp->ctrl = msm_dp_ctrl_get(dev, dp->link, dp->panel, dp->aux, | |
| 564 | − phy, dp->ahb_base, dp->link_base); | |
| 573 | + dp->ctrl = msm_dp_ctrl_get(dev, dp->link, dp->aux, | |
| 574 | + phy, dp->ahb_base, dp->link_base); | |
| 565 | 575 | if (IS_ERR(dp->ctrl)) { |
| 566 | 576 | rc = PTR_ERR(dp->ctrl); |
| 567 | 577 | DRM_ERROR("failed to initialize ctrl, rc = %d\n", rc); |
| 568 | 578 | dp->ctrl = NULL; |
| 569 | − goto error_ctrl; | |
| 579 | + goto error_link; | |
| 570 | 580 | } |
| 571 | 581 | |
| 572 | 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 | 584 | rc = PTR_ERR(dp->audio); |
| 575 | 585 | pr_err("failed to initialize audio, rc = %d\n", rc); |
| 576 | 586 | dp->audio = NULL; |
| 577 | − goto error_ctrl; | |
| 587 | + goto error_link; | |
| 578 | 588 | } |
| 579 | 589 | |
| 580 | 590 | return rc; |
| 581 | 591 | |
| 582 | −error_ctrl: | |
| 583 | − msm_dp_panel_put(dp->panel); | |
| 584 | 592 | error_link: |
| 585 | 593 | msm_dp_aux_put(dp->aux); |
| 586 | 594 | error: |
| @@ -588,20 +596,64 @@ error: · 1 unmodified line | ||
| 588 | 596 | } |
| 589 | 597 | |
| 590 | 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 | 602 | struct msm_dp_display_private *dp; |
| 603 | + u32 bpp; | |
| 594 | 604 | |
| 595 | 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); | |
| 598 | − dp->panel->msm_dp_mode.bpp = mode->bpp; | |
| 599 | − dp->panel->msm_dp_mode.out_fmt_is_yuv_420 = mode->out_fmt_is_yuv_420; | |
| 600 | − msm_dp_panel_init_panel_info(dp->panel); | |
| 607 | + if (msm_dp_display_check_video_test(msm_dp_display)) | |
| 608 | + bpp = msm_dp_display_get_test_bpp(msm_dp_display); | |
| 609 | + else | |
| 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 | 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 | 658 | int rc = 0; |
| 607 | 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 | 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 | 668 | if (!rc) |
| 617 | 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 | 689 | msm_dp_display_handle_plugged_change(msm_dp_display, true); |
| 638 | 690 | |
| 639 | 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 | 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 | 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 | 701 | /* wait only if audio was enabled */ |
| 653 | 702 | if (msm_dp_display->audio_enabled) { |
| 654 | 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 | 710 | msm_dp_display->audio_enabled = false; |
| 711 | +} | |
| 662 | 712 | |
| 663 | − if (dp->link->sink_count == 0) { | |
| 664 | − /* | |
| 665 | − * irq_hpd with sink_count = 0 | |
| 666 | − * hdmi unplugged out of dongle | |
| 667 | − */ | |
| 668 | − msm_dp_ctrl_off_link_stream(dp->ctrl); | |
| 669 | − } else { | |
| 670 | − /* | |
| 671 | − * unplugged interrupt | |
| 672 | − * dongle unplugged out of DUT | |
| 673 | − */ | |
| 674 | − msm_dp_ctrl_off(dp->ctrl); | |
| 713 | +static int msm_dp_display_disable(struct msm_dp_display_private *dp, | |
| 714 | + struct msm_dp_panel *msm_dp_panel) | |
| 715 | +{ | |
| 716 | + struct msm_dp *msm_dp_display = &dp->msm_dp_display; | |
| 717 | + | |
| 718 | + if (!msm_dp_display->power_on) | |
| 719 | + return 0; | |
| 720 | + | |
| 721 | + msm_dp_panel_disable_vsc_sdp(msm_dp_panel); | |
| 722 | + | |
| 723 | + msm_dp_ctrl_off_pixel_clk(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 | 735 | msm_dp_display_host_phy_exit(dp); |
| 676 | − } | |
| 677 | 736 | |
| 678 | 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 | |
| 686 | − * @bridge: Pointer to drm bridge structure | |
| 744 | + * msm_dp_display_mode_valid - callback to determine if specified mode is valid | |
| 745 | + * @dp: Pointer to dp display structure | |
| 687 | 746 | * @info: display info |
| 688 | 747 | * @mode: Pointer to drm mode structure |
| 689 | 748 | * Returns: Validity status for specified mode |
| 690 | 749 | */ |
| 691 | −enum drm_mode_status msm_dp_bridge_mode_valid(struct drm_bridge *bridge, | |
| 692 | − const struct drm_display_info *info, | |
| 693 | − const struct drm_display_mode *mode) | |
| 750 | +enum drm_mode_status msm_dp_display_mode_valid(struct msm_dp *dp, | |
| 751 | + const struct drm_display_info *info, | |
| 752 | + const struct drm_display_mode *mode) | |
| 694 | 753 | { |
| 695 | 754 | const u32 num_components = 3, default_bpp = 24; |
| 696 | 755 | struct msm_dp_display_private *msm_dp_display; |
| 697 | 756 | struct msm_dp_link_info *link_info; |
| 698 | 757 | u32 mode_rate_khz = 0, supported_rate_khz = 0, mode_bpp = 0; |
| 699 | − struct msm_dp *dp; | |
| 700 | 758 | int mode_pclk_khz = mode->clock; |
| 701 | − | |
| 702 | − dp = to_dp_bridge(bridge)->msm_dp_display; | |
| 759 | + bool is_yuv_420; | |
| 703 | 760 | |
| 704 | 761 | if (!dp || !mode_pclk_khz || !dp->connector) { |
| 705 | 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 | 766 | msm_dp_display = container_of(dp, struct msm_dp_display_private, msm_dp_display); |
| 710 | 767 | link_info = &msm_dp_display->panel->link_info; |
| 711 | 768 | |
| 712 | − if ((drm_mode_is_420_only(&dp->connector->display_info, mode) && | |
| 713 | − msm_dp_display->panel->vsc_sdp_supported) || | |
| 714 | − msm_dp_wide_bus_available(dp)) | |
| 769 | + is_yuv_420 = drm_mode_is_420_only(&dp->connector->display_info, mode); | |
| 770 | + | |
| 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 | 779 | mode_pclk_khz /= 2; |
| 716 | 780 | |
| 717 | 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 | 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, | |
| 748 | − dp->connector); | |
| 811 | + return drm_edid_connector_add_modes(msm_dp_display->panel->connector); | |
| 749 | 812 | } |
| 750 | 813 | |
| 751 | 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 | 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 | 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 | 986 | return ret; |
| 924 | 987 | } |
| @@ -1277,22 +1340,10 @@ void __exit msm_dp_unregister(void) · 352 unmodified lines | ||
| 1277 | 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 | 1343 | bool msm_dp_needs_periph_flush(const struct msm_dp *msm_dp_display, |
| 1293 | 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 | 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 | 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 | 1356 | return false; |
| 1306 | 1357 | |
| 1307 | 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 | 1403 | return 0; |
| 1353 | 1404 | } |
| 1354 | 1405 | |
| 1355 | −void msm_dp_bridge_atomic_enable(struct drm_bridge *drm_bridge, | |
| 1356 | − struct drm_atomic_commit *state) | |
| 1406 | +void msm_dp_display_atomic_pre_enable(struct msm_dp *msm_dp_display, | |
| 1407 | + struct drm_atomic_commit *state) | |
| 1357 | 1408 | { |
| 1358 | − struct msm_dp_bridge *msm_dp_bridge = to_dp_bridge(drm_bridge); | |
| 1359 | − struct msm_dp *dp = msm_dp_bridge->msm_dp_display; | |
| 1360 | − int rc = 0; | |
| 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 | − } | |
| 1409 | + struct msm_dp_display_private *dp; | |
| 1410 | + struct drm_crtc *crtc; | |
| 1411 | + struct drm_crtc_state *crtc_state; | |
| 1369 | 1412 | |
| 1370 | − if (dp->is_edp) | |
| 1371 | − msm_dp_hpd_plug_handle(msm_dp_display); | |
| 1413 | + dp = container_of(msm_dp_display, struct msm_dp_display_private, msm_dp_display); | |
| 1372 | 1414 | |
| 1373 | − if (pm_runtime_resume_and_get(&dp->pdev->dev)) { | |
| 1374 | − DRM_ERROR("failed to pm_runtime_resume\n"); | |
| 1415 | + crtc = drm_atomic_get_new_crtc_for_encoder(state, msm_dp_display->bridge->encoder); | |
| 1416 | + if (!crtc) | |
| 1375 | 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) | |
| 1379 | − return; | |
| 1420 | + /* | |
| 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); | |
| 1382 | − if (rc) { | |
| 1383 | − DRM_ERROR("Failed to perform a mode set, rc=%d\n", rc); | |
| 1384 | − return; | |
| 1385 | − } | |
| 1428 | +void msm_dp_display_atomic_enable(struct msm_dp *msm_dp_display, | |
| 1429 | + struct drm_atomic_commit *state) | |
| 1430 | +{ | |
| 1431 | + int rc = 0; | |
| 1432 | + struct msm_dp_display_private *dp; | |
| 1386 | 1433 | |
| 1387 | − if (!dp->power_on) { | |
| 1388 | − msm_dp_display_host_phy_init(msm_dp_display); | |
| 1389 | − force_link_train = true; | |
| 1390 | − } | |
| 1434 | + dp = container_of(msm_dp_display, struct msm_dp_display_private, msm_dp_display); | |
| 1391 | 1435 | |
| 1392 | − rc = msm_dp_ctrl_on_link(msm_dp_display->ctrl); | |
| 1436 | + rc = msm_dp_display_prepare_link(dp); | |
| 1393 | 1437 | if (rc) { |
| 1394 | − DRM_ERROR("Failed link training (rc=%d)\n", rc); | |
| 1395 | − // TODO: schedule drm_connector_set_link_status_property() | |
| 1438 | + DRM_ERROR("DP display prepare failed, rc=%d\n", rc); | |
| 1396 | 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 | 1447 | if (rc) { |
| 1403 | 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, | |
| 1411 | − struct drm_atomic_commit *state) | |
| 1455 | +void msm_dp_display_atomic_disable(struct msm_dp *dp) | |
| 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 | 1457 | struct msm_dp_display_private *msm_dp_display; |
| 1416 | 1458 | |
| 1417 | 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 | 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, | |
| 1423 | − struct drm_atomic_commit *state) | |
| 1464 | +static void msm_dp_display_unprepare(struct msm_dp_display_private *dp) | |
| 1424 | 1465 | { |
| 1425 | − struct msm_dp_bridge *msm_dp_bridge = to_dp_bridge(drm_bridge); | |
| 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); | |
| 1466 | + struct msm_dp *msm_dp_display = &dp->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, | |
| 1442 | − const struct drm_display_mode *mode, | |
| 1443 | − const struct drm_display_mode *adjusted_mode) | |
| 1473 | +void msm_dp_display_atomic_post_disable(struct msm_dp *dp) | |
| 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 | 1475 | struct msm_dp_display_private *msm_dp_display; |
| 1448 | − struct msm_dp_panel *msm_dp_panel; | |
| 1449 | 1476 | |
| 1450 | 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)); | |
| 1454 | − | |
| 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); | |
| 1479 | + if (dp->is_edp) | |
| 1480 | + msm_dp_hpd_unplug_handle(msm_dp_display); | |
| 1467 | 1481 | |
| 1468 | − msm_dp_display->msm_dp_mode.h_active_low = | |
| 1469 | − !!(msm_dp_display->msm_dp_mode.drm_mode.flags & DRM_MODE_FLAG_NHSYNC); | |
| 1482 | + msm_dp_display_audio_notify_disable(msm_dp_display); | |
| 1470 | 1483 | |
| 1471 | − msm_dp_display->msm_dp_mode.out_fmt_is_yuv_420 = | |
| 1472 | − drm_mode_is_420_only(&dp->connector->display_info, adjusted_mode) && | |
| 1473 | − msm_dp_panel->vsc_sdp_supported; | |
| 1484 | + msm_dp_display_disable(msm_dp_display, msm_dp_display->panel); | |
| 1474 | 1485 | |
| 1475 | − /* populate wide_bus_support to different layers */ | |
| 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; | |
| 1486 | + msm_dp_display_unprepare(msm_dp_display); | |
| 1478 | 1487 | } |
| 1479 | 1488 | |
| 1480 | 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 | 33 | void msm_dp_display_signal_audio_complete(struct msm_dp *msm_dp_display); |
| 34 | 34 | void msm_dp_display_set_psr(struct msm_dp *dp, bool enter); |
| 35 | 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 | 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 | 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 | 98 | static const struct drm_bridge_funcs msm_dp_bridge_ops = { |
| 53 | 99 | .atomic_duplicate_state = drm_atomic_helper_bridge_duplicate_state, |
| 54 | 100 | .atomic_destroy_state = drm_atomic_helper_bridge_destroy_state, |
| 55 | 101 | .atomic_create_state = drm_atomic_helper_bridge_create_state, |
| 102 | + .atomic_pre_enable = msm_dp_bridge_atomic_pre_enable, | |
| 56 | 103 | .atomic_enable = msm_dp_bridge_atomic_enable, |
| 57 | 104 | .atomic_disable = msm_dp_bridge_atomic_disable, |
| 58 | 105 | .atomic_post_disable = msm_dp_bridge_atomic_post_disable, |
| 59 | − .mode_set = msm_dp_bridge_mode_set, | |
| 60 | 106 | .mode_valid = msm_dp_bridge_mode_valid, |
| 61 | 107 | .get_modes = msm_dp_bridge_get_modes, |
| 62 | 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 | 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 | 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 | 278 | static const struct drm_bridge_funcs msm_edp_bridge_ops = { |
| 279 | + .atomic_pre_enable = msm_dp_bridge_atomic_pre_enable, | |
| 233 | 280 | .atomic_enable = msm_edp_bridge_atomic_enable, |
| 234 | 281 | .atomic_disable = msm_edp_bridge_atomic_disable, |
| 235 | 282 | .atomic_post_disable = msm_edp_bridge_atomic_post_disable, |
| 236 | − .mode_set = msm_dp_bridge_mode_set, | |
| 237 | 283 | .mode_valid = msm_edp_bridge_mode_valid, |
| 238 | 284 | .atomic_create_state = drm_atomic_helper_bridge_create_state, |
| 239 | 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 | 28 | enum drm_connector_status msm_dp_bridge_detect(struct drm_bridge *bridge, |
| 29 | 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 | 30 | void msm_dp_bridge_hpd_enable(struct drm_bridge *bridge); |
| 43 | 31 | void msm_dp_bridge_hpd_disable(struct drm_bridge *bridge); |
| 44 | 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 | 232 | return min_supported_bpp; |
| 233 | 233 | } |
| 234 | 234 | |
| 235 | −int msm_dp_panel_read_sink_caps(struct msm_dp_panel *msm_dp_panel, | |
| 236 | − struct drm_connector *connector) | |
| 235 | +int msm_dp_panel_read_link_caps(struct msm_dp_panel *msm_dp_panel, | |
| 236 | + struct drm_connector *connector) | |
| 237 | 237 | { |
| 238 | 238 | int rc, bw_code; |
| 239 | 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 | 272 | rc = drm_dp_read_downstream_info(panel->aux, msm_dp_panel->dpcd, |
| 273 | 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 | 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 | 277 | u32 msm_dp_panel_get_mode_bpp(struct msm_dp_panel *msm_dp_panel, |
| 305 | 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 | 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 | 300 | static u8 msm_dp_panel_get_edid_checksum(const struct edid *edid) |
| 342 | 301 | { |
| 343 | 302 | edid += edid->extensions; |
| @@ -345,7 +304,8 @@ static u8 msm_dp_panel_get_edid_checksum(const struct edid *edid) · 1 unmodified line | ||
| 345 | 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 | 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 | 319 | if (panel->link->sink_request & DP_TEST_LINK_EDID_READ) { |
| 360 | 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 | 322 | u8 checksum; |
| 363 | 323 | |
| 364 | 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 | 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 | 654 | struct drm_display_mode *drm_mode; |
| 693 | 655 | struct msm_dp_panel_private *panel; |
| 694 | 656 | |
| 695 | − drm_mode = &msm_dp_panel->msm_dp_mode.drm_mode; | |
| 696 | − | |
| 697 | 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 | 672 | * print resolution info as this is a result |
| 701 | 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 | 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 | 33 | u8 downstream_ports[DP_MAX_DOWNSTREAM_PORTS]; |
| 34 | 34 | |
| 35 | 35 | struct msm_dp_link_info link_info; |
| 36 | − const struct drm_edid *drm_edid; | |
| 37 | 36 | struct drm_connector *connector; |
| 38 | 37 | struct msm_dp_display_mode msm_dp_mode; |
| 39 | 38 | struct msm_dp_panel_psr psr_cap; |
| @@ -44,18 +43,17 @@ struct msm_dp_panel { · 4 unmodified lines | ||
| 44 | 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 | 49 | int msm_dp_panel_deinit(struct msm_dp_panel *msm_dp_panel); |
| 49 | 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 | − struct drm_connector *connector); | |
| 52 | −void msm_dp_panel_unplugged(struct msm_dp_panel *msm_dp_panel, | |
| 53 | − struct drm_connector *connector); | |
| 51 | +int msm_dp_panel_read_link_caps(struct msm_dp_panel *msm_dp_panel, | |
| 52 | + struct drm_connector *connector); | |
| 54 | 53 | u32 msm_dp_panel_get_mode_bpp(struct msm_dp_panel *msm_dp_panel, u32 mode_max_bpp, |
| 55 | 54 | u32 mode_pclk_khz); |
| 56 | −int msm_dp_panel_get_modes(struct msm_dp_panel *msm_dp_panel, | |
| 57 | − struct drm_connector *connector); | |
| 58 | −void msm_dp_panel_handle_sink_request(struct msm_dp_panel *msm_dp_panel); | |
| 55 | +void msm_dp_panel_handle_sink_request(struct msm_dp_panel *msm_dp_panel, | |
| 56 | + const struct drm_edid *drm_edid); | |
| 59 | 57 | void msm_dp_panel_tpg_config(struct msm_dp_panel *msm_dp_panel, bool enable); |
| 60 | 58 | |
| 61 | 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 | 92 | struct msm_dp_link *link, |
| 95 | 93 | void __iomem *link_base, |
| 96 | 94 | void __iomem *p0_base); |
| 97 | −void msm_dp_panel_put(struct msm_dp_panel *msm_dp_panel); | |
| 98 | 95 | #endif /* _DP_PANEL_H_ */ |
| @@ -149,8 +149,10 @@ · 148 unmodified lines | ||
| 149 | 149 | #define DP_CONFIGURATION_CTRL_ENHANCED_FRAMING (0x00000040) |
| 150 | 150 | #define DP_CONFIGURATION_CTRL_SEND_VSC (0x00000080) |
| 151 | 151 | #define DP_CONFIGURATION_CTRL_BPC (0x00000100) |
| 152 | +#define DP_CONFIGURATION_CTRL_BPC_MASK GENMASK(9, 8) | |
| 152 | 153 | #define DP_CONFIGURATION_CTRL_ASSR (0x00000400) |
| 153 | 154 | #define DP_CONFIGURATION_CTRL_RGB_YUV (0x00000800) |
| 155 | +#define DP_CONFIGURATION_CTRL_RGB_YUV_MASK GENMASK(12, 11) | |
| 154 | 156 | #define DP_CONFIGURATION_CTRL_LSCLK_DIV (0x00002000) |
| 155 | 157 | #define DP_CONFIGURATION_CTRL_NUM_OF_LANES_SHIFT (0x04) |
| 156 | 158 | #define DP_CONFIGURATION_CTRL_BPC_SHIFT (0x08) |
| @@ -550,8 +550,6 @@ error: · 549 unmodified lines | ||
| 550 | 550 | |
| 551 | 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 | 553 | clk_disable_unprepare(msm_host->esc_clk); |
| 556 | 554 | clk_disable_unprepare(msm_host->pixel_clk); |
| 557 | 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 | 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 | 674 | if (!msm_host->mode) { |
| 675 | 675 | pr_err("%s: mode not set\n", __func__); |
| 676 | 676 | return -EINVAL; |
| 677 | 677 | } |
| 678 | 678 | |
| 679 | 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 | 690 | msm_host->esc_clk_rate = clk_get_rate(msm_host->esc_clk); |
| 681 | 691 | return 0; |
| 682 | 692 | } |
| @@ -111,6 +111,7 @@ struct msm_dsi_phy { · 110 unmodified lines | ||
| 111 | 111 | struct msm_dsi_dphy_timing timing; |
| 112 | 112 | const struct msm_dsi_phy_cfg *cfg; |
| 113 | 113 | void *tuning_cfg; |
| 114 | + void *pll_data; | |
| 114 | 115 | |
| 115 | 116 | enum msm_dsi_phy_usecase usecase; |
| 116 | 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 | 426 | u32 data; |
| 427 | 427 | |
| 428 | 428 | spin_lock_irqsave(&pll->pll_enable_lock, flags); |
| 429 | − pll->pll_enable_cnt++; | |
| 430 | − WARN_ON(pll->pll_enable_cnt == INT_MAX); | |
| 429 | + if (pll->pll_enable_cnt++) { | |
| 430 | + spin_unlock_irqrestore(&pll->pll_enable_lock, flags); | |
| 431 | + WARN_ON(pll->pll_enable_cnt == INT_MAX); | |
| 432 | + return; | |
| 433 | + } | |
| 431 | 434 | |
| 432 | 435 | data = readl(pll->phy->base + REG_DSI_7nm_PHY_CMN_CTRL_0); |
| 433 | 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 | 876 | spin_lock_init(&pll_7nm->pll_enable_lock); |
| 874 | 877 | |
| 875 | 878 | pll_7nm->phy = phy; |
| 879 | + phy->pll_data = pll_7nm; | |
| 876 | 880 | |
| 877 | 881 | ret = pll_7nm_register(pll_7nm, phy->provided_clocks->hws); |
| 878 | 882 | if (ret) { |
| @@ -961,8 +965,10 @@ static int dsi_7nm_phy_enable(struct msm_dsi_phy *phy, · 82 unmodified lines | ||
| 961 | 965 | u32 const delay_us = 5; |
| 962 | 966 | u32 const timeout_us = 1000; |
| 963 | 967 | struct msm_dsi_dphy_timing *timing = &phy->timing; |
| 968 | + struct dsi_pll_7nm *pll = phy->pll_data; | |
| 964 | 969 | void __iomem *base = phy->base; |
| 965 | 970 | bool less_than_1500_mhz; |
| 971 | + unsigned long flags; | |
| 966 | 972 | u32 vreg_ctrl_0, vreg_ctrl_1, lane_ctrl0; |
| 967 | 973 | u32 glbl_pemph_ctrl_0; |
| 968 | 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 | 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 | 1095 | /* de-assert digital and pll power down */ |
| 1088 | 1096 | data = DSI_7nm_PHY_CMN_CTRL_0_DIGTOP_PWRDN_B | |
| 1089 | 1097 | DSI_7nm_PHY_CMN_CTRL_0_PLL_SHUTDOWNB; |
| 1090 | 1098 | writel(data, base + REG_DSI_7nm_PHY_CMN_CTRL_0); |
| 1099 | + spin_unlock_irqrestore(&pll->pll_enable_lock, flags); | |
| 1091 | 1100 | |
| 1092 | 1101 | /* Assert PLL core reset */ |
| 1093 | 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 | 1210 | static void dsi_7nm_phy_disable(struct msm_dsi_phy *phy) |
| 1202 | 1211 | { |
| 1212 | + struct dsi_pll_7nm *pll = phy->pll_data; | |
| 1203 | 1213 | void __iomem *base = phy->base; |
| 1214 | + unsigned long flags; | |
| 1204 | 1215 | u32 data; |
| 1205 | 1216 | |
| 1206 | 1217 | DBG(""); |
| @@ -1227,8 +1238,11 @@ static void dsi_7nm_phy_disable(struct msm_dsi_phy *phy) · 20 unmodified lines | ||
| 1227 | 1238 | writel(data, base + REG_DSI_7nm_PHY_CMN_CTRL_0); |
| 1228 | 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 | 1243 | /* Turn off all PHY blocks */ |
| 1231 | 1244 | writel(0x00, base + REG_DSI_7nm_PHY_CMN_CTRL_0); |
| 1245 | + spin_unlock_irqrestore(&pll->pll_enable_lock, flags); | |
| 1232 | 1246 | |
| 1233 | 1247 | /* make sure phy is turned off */ |
| 1234 | 1248 | wmb(); |
| @@ -112,6 +112,25 @@ static inline u32 hdmi_read(struct hdmi *hdmi, u32 reg) · 111 unmodified lines | ||
| 112 | 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 | 134 | static inline u32 hdmi_qfprom_read(struct hdmi *hdmi, u32 reg) |
| 116 | 135 | { |
| 117 | 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 | 59 | struct hdmi_bridge *hdmi_bridge = to_hdmi_bridge(bridge); |
| 60 | 60 | struct hdmi *hdmi = hdmi_bridge->hdmi; |
| 61 | − u32 val; | |
| 62 | 61 | |
| 63 | − val = hdmi_read(hdmi, REG_HDMI_INFOFRAME_CTRL0); | |
| 64 | − val &= ~(HDMI_INFOFRAME_CTRL0_AVI_SEND | | |
| 65 | − HDMI_INFOFRAME_CTRL0_AVI_CONT); | |
| 66 | − hdmi_write(hdmi, REG_HDMI_INFOFRAME_CTRL0, val); | |
| 62 | + hdmi_clear_bits(hdmi, REG_HDMI_INFOFRAME_CTRL0, | |
| 63 | + HDMI_INFOFRAME_CTRL0_AVI_SEND | | |
| 64 | + HDMI_INFOFRAME_CTRL0_AVI_CONT); | |
| 67 | 65 | |
| 68 | − val = hdmi_read(hdmi, REG_HDMI_INFOFRAME_CTRL1); | |
| 69 | − val &= ~HDMI_INFOFRAME_CTRL1_AVI_INFO_LINE__MASK; | |
| 70 | − hdmi_write(hdmi, REG_HDMI_INFOFRAME_CTRL1, val); | |
| 66 | + hdmi_clear_bits(hdmi, REG_HDMI_INFOFRAME_CTRL1, | |
| 67 | + HDMI_INFOFRAME_CTRL1_AVI_INFO_LINE__MASK); | |
| 71 | 68 | |
| 72 | 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 | 74 | struct hdmi_bridge *hdmi_bridge = to_hdmi_bridge(bridge); |
| 78 | 75 | struct hdmi *hdmi = hdmi_bridge->hdmi; |
| 79 | − u32 val; | |
| 80 | 76 | |
| 81 | − val = hdmi_read(hdmi, REG_HDMI_INFOFRAME_CTRL0); | |
| 82 | − val &= ~(HDMI_INFOFRAME_CTRL0_AUDIO_INFO_SEND | | |
| 83 | − HDMI_INFOFRAME_CTRL0_AUDIO_INFO_CONT | | |
| 84 | − HDMI_INFOFRAME_CTRL0_AUDIO_INFO_SOURCE | | |
| 85 | − HDMI_INFOFRAME_CTRL0_AUDIO_INFO_UPDATE); | |
| 86 | − hdmi_write(hdmi, REG_HDMI_INFOFRAME_CTRL0, val); | |
| 77 | + hdmi_clear_bits(hdmi, REG_HDMI_INFOFRAME_CTRL0, | |
| 78 | + HDMI_INFOFRAME_CTRL0_AUDIO_INFO_SEND | | |
| 79 | + HDMI_INFOFRAME_CTRL0_AUDIO_INFO_CONT | | |
| 80 | + HDMI_INFOFRAME_CTRL0_AUDIO_INFO_SOURCE | | |
| 81 | + HDMI_INFOFRAME_CTRL0_AUDIO_INFO_UPDATE); | |
| 87 | 82 | |
| 88 | − val = hdmi_read(hdmi, REG_HDMI_INFOFRAME_CTRL1); | |
| 89 | − val &= ~HDMI_INFOFRAME_CTRL1_AUDIO_INFO_LINE__MASK; | |
| 90 | − hdmi_write(hdmi, REG_HDMI_INFOFRAME_CTRL1, val); | |
| 83 | + hdmi_clear_bits(hdmi, REG_HDMI_INFOFRAME_CTRL1, | |
| 84 | + HDMI_INFOFRAME_CTRL1_AUDIO_INFO_LINE__MASK); | |
| 91 | 85 | |
| 92 | 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 | 91 | struct hdmi_bridge *hdmi_bridge = to_hdmi_bridge(bridge); |
| 98 | 92 | struct hdmi *hdmi = hdmi_bridge->hdmi; |
| 99 | − u32 val; | |
| 100 | 93 | |
| 101 | − val = hdmi_read(hdmi, REG_HDMI_GEN_PKT_CTRL); | |
| 102 | − val &= ~(HDMI_GEN_PKT_CTRL_GENERIC1_SEND | | |
| 103 | − HDMI_GEN_PKT_CTRL_GENERIC1_CONT | | |
| 104 | − HDMI_GEN_PKT_CTRL_GENERIC1_LINE__MASK); | |
| 105 | − hdmi_write(hdmi, REG_HDMI_GEN_PKT_CTRL, val); | |
| 94 | + hdmi_clear_bits(hdmi, REG_HDMI_GEN_PKT_CTRL, | |
| 95 | + HDMI_GEN_PKT_CTRL_GENERIC1_SEND | | |
| 96 | + HDMI_GEN_PKT_CTRL_GENERIC1_CONT | | |
| 97 | + HDMI_GEN_PKT_CTRL_GENERIC1_LINE__MASK); | |
| 106 | 98 | |
| 107 | 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 | 104 | struct hdmi_bridge *hdmi_bridge = to_hdmi_bridge(bridge); |
| 113 | 105 | struct hdmi *hdmi = hdmi_bridge->hdmi; |
| 114 | − u32 val; | |
| 115 | 106 | |
| 116 | − val = hdmi_read(hdmi, REG_HDMI_GEN_PKT_CTRL); | |
| 117 | − val &= ~(HDMI_GEN_PKT_CTRL_GENERIC0_SEND | | |
| 118 | − HDMI_GEN_PKT_CTRL_GENERIC0_CONT | | |
| 119 | − HDMI_GEN_PKT_CTRL_GENERIC0_UPDATE | | |
| 120 | − HDMI_GEN_PKT_CTRL_GENERIC0_LINE__MASK); | |
| 121 | − hdmi_write(hdmi, REG_HDMI_GEN_PKT_CTRL, val); | |
| 107 | + hdmi_clear_bits(hdmi, REG_HDMI_GEN_PKT_CTRL, | |
| 108 | + HDMI_GEN_PKT_CTRL_GENERIC0_SEND | | |
| 109 | + HDMI_GEN_PKT_CTRL_GENERIC0_CONT | | |
| 110 | + HDMI_GEN_PKT_CTRL_GENERIC0_UPDATE | | |
| 111 | + HDMI_GEN_PKT_CTRL_GENERIC0_LINE__MASK); | |
| 122 | 112 | |
| 123 | 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 | 119 | struct hdmi_bridge *hdmi_bridge = to_hdmi_bridge(bridge); |
| 130 | 120 | struct hdmi *hdmi = hdmi_bridge->hdmi; |
| 131 | 121 | u32 buf[4] = {}; |
| 132 | − u32 val; | |
| 133 | 122 | int i; |
| 134 | 123 | |
| 135 | 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 | 142 | for (i = 0; i < ARRAY_SIZE(buf); i++) |
| 154 | 143 | hdmi_write(hdmi, REG_HDMI_AVI_INFO(i), buf[i]); |
| 155 | 144 | |
| 156 | − val = hdmi_read(hdmi, REG_HDMI_INFOFRAME_CTRL0); | |
| 157 | − val |= HDMI_INFOFRAME_CTRL0_AVI_SEND | | |
| 158 | − HDMI_INFOFRAME_CTRL0_AVI_CONT; | |
| 159 | − hdmi_write(hdmi, REG_HDMI_INFOFRAME_CTRL0, val); | |
| 145 | + hdmi_update_bits(hdmi, REG_HDMI_INFOFRAME_CTRL0, | |
| 146 | + HDMI_INFOFRAME_CTRL0_AVI_SEND | HDMI_INFOFRAME_CTRL0_AVI_CONT, | |
| 147 | + HDMI_INFOFRAME_CTRL0_AVI_SEND | HDMI_INFOFRAME_CTRL0_AVI_CONT); | |
| 160 | 148 | |
| 161 | − val = hdmi_read(hdmi, REG_HDMI_INFOFRAME_CTRL1); | |
| 162 | − val &= ~HDMI_INFOFRAME_CTRL1_AVI_INFO_LINE__MASK; | |
| 163 | − val |= HDMI_INFOFRAME_CTRL1_AVI_INFO_LINE(AVI_IFRAME_LINE_NUMBER); | |
| 164 | − hdmi_write(hdmi, REG_HDMI_INFOFRAME_CTRL1, val); | |
| 149 | + hdmi_update_bits(hdmi, REG_HDMI_INFOFRAME_CTRL1, | |
| 150 | + HDMI_INFOFRAME_CTRL1_AVI_INFO_LINE__MASK, | |
| 151 | + HDMI_INFOFRAME_CTRL1_AVI_INFO_LINE(AVI_IFRAME_LINE_NUMBER)); | |
| 165 | 152 | |
| 166 | 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 | 180 | buffer[9] << 16 | |
| 194 | 181 | buffer[10] << 24); |
| 195 | 182 | |
| 196 | − val = hdmi_read(hdmi, REG_HDMI_INFOFRAME_CTRL0); | |
| 197 | − val |= HDMI_INFOFRAME_CTRL0_AUDIO_INFO_SEND | | |
| 198 | − HDMI_INFOFRAME_CTRL0_AUDIO_INFO_CONT | | |
| 199 | − HDMI_INFOFRAME_CTRL0_AUDIO_INFO_SOURCE | | |
| 200 | − HDMI_INFOFRAME_CTRL0_AUDIO_INFO_UPDATE; | |
| 201 | − hdmi_write(hdmi, REG_HDMI_INFOFRAME_CTRL0, val); | |
| 183 | + val = HDMI_INFOFRAME_CTRL0_AUDIO_INFO_SEND | | |
| 184 | + HDMI_INFOFRAME_CTRL0_AUDIO_INFO_CONT | | |
| 185 | + HDMI_INFOFRAME_CTRL0_AUDIO_INFO_SOURCE | | |
| 186 | + HDMI_INFOFRAME_CTRL0_AUDIO_INFO_UPDATE; | |
| 187 | + hdmi_update_bits(hdmi, REG_HDMI_INFOFRAME_CTRL0, val, val); | |
| 202 | 188 | |
| 203 | 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 | 217 | for (i = 0; i < ARRAY_SIZE(buf); i++) |
| 232 | 218 | hdmi_write(hdmi, REG_HDMI_GENERIC1(i), buf[i]); |
| 233 | 219 | |
| 234 | − val = hdmi_read(hdmi, REG_HDMI_GEN_PKT_CTRL); | |
| 235 | − val |= HDMI_GEN_PKT_CTRL_GENERIC1_SEND | | |
| 236 | − HDMI_GEN_PKT_CTRL_GENERIC1_CONT | | |
| 237 | − HDMI_GEN_PKT_CTRL_GENERIC1_LINE(SPD_IFRAME_LINE_NUMBER); | |
| 238 | − hdmi_write(hdmi, REG_HDMI_GEN_PKT_CTRL, val); | |
| 220 | + val = HDMI_GEN_PKT_CTRL_GENERIC1_SEND | | |
| 221 | + HDMI_GEN_PKT_CTRL_GENERIC1_CONT | | |
| 222 | + HDMI_GEN_PKT_CTRL_GENERIC1_LINE(SPD_IFRAME_LINE_NUMBER); | |
| 223 | + hdmi_update_bits(hdmi, REG_HDMI_GEN_PKT_CTRL, val, val); | |
| 239 | 224 | |
| 240 | 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 | 254 | for (i = 0; i < ARRAY_SIZE(buf); i++) |
| 270 | 255 | hdmi_write(hdmi, REG_HDMI_GENERIC0(i), buf[i]); |
| 271 | 256 | |
| 272 | − val = hdmi_read(hdmi, REG_HDMI_GEN_PKT_CTRL); | |
| 273 | − val |= HDMI_GEN_PKT_CTRL_GENERIC0_SEND | | |
| 274 | − HDMI_GEN_PKT_CTRL_GENERIC0_CONT | | |
| 275 | − HDMI_GEN_PKT_CTRL_GENERIC0_UPDATE | | |
| 276 | − HDMI_GEN_PKT_CTRL_GENERIC0_LINE(VENSPEC_IFRAME_LINE_NUMBER); | |
| 277 | − hdmi_write(hdmi, REG_HDMI_GEN_PKT_CTRL, val); | |
| 257 | + val = HDMI_GEN_PKT_CTRL_GENERIC0_SEND | | |
| 258 | + HDMI_GEN_PKT_CTRL_GENERIC0_CONT | | |
| 259 | + HDMI_GEN_PKT_CTRL_GENERIC0_UPDATE | | |
| 260 | + HDMI_GEN_PKT_CTRL_GENERIC0_LINE(VENSPEC_IFRAME_LINE_NUMBER); | |
| 261 | + hdmi_update_bits(hdmi, REG_HDMI_GEN_PKT_CTRL, val, val); | |
| 278 | 262 | |
| 279 | 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 | 306 | HDMI_HDCP_DDC_CTRL_0_DISABLE); |
| 307 | 307 | |
| 308 | 308 | /* ACK the Failure to Clear it */ |
| 309 | − reg_val = hdmi_read(hdmi, REG_HDMI_HDCP_DDC_CTRL_1); | |
| 310 | − reg_val |= HDMI_HDCP_DDC_CTRL_1_FAILED_ACK; | |
| 311 | − hdmi_write(hdmi, REG_HDMI_HDCP_DDC_CTRL_1, reg_val); | |
| 309 | + hdmi_update_bits(hdmi, REG_HDMI_HDCP_DDC_CTRL_1, | |
| 310 | + HDMI_HDCP_DDC_CTRL_1_FAILED_ACK, | |
| 311 | + HDMI_HDCP_DDC_CTRL_1_FAILED_ACK); | |
| 312 | 312 | |
| 313 | 313 | /* Check if the FAILURE got Cleared */ |
| 314 | 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 | 324 | DBG("Before: HDMI_DDC_SW_STATUS=0x%08x", |
| 325 | 325 | hdmi_read(hdmi, REG_HDMI_DDC_SW_STATUS)); |
| 326 | 326 | /* Reset HDMI DDC software status */ |
| 327 | − reg_val = hdmi_read(hdmi, REG_HDMI_DDC_CTRL); | |
| 328 | − reg_val |= HDMI_DDC_CTRL_SW_STATUS_RESET; | |
| 329 | − hdmi_write(hdmi, REG_HDMI_DDC_CTRL, reg_val); | |
| 327 | + hdmi_update_bits(hdmi, REG_HDMI_DDC_CTRL, HDMI_DDC_CTRL_SW_STATUS_RESET, | |
| 328 | + HDMI_DDC_CTRL_SW_STATUS_RESET); | |
| 330 | 329 | |
| 331 | 330 | rc = msm_hdmi_hdcp_msleep(hdcp_ctrl, 20, AUTH_ABORT_EV); |
| 332 | 331 | |
| 333 | − reg_val = hdmi_read(hdmi, REG_HDMI_DDC_CTRL); | |
| 334 | − reg_val &= ~HDMI_DDC_CTRL_SW_STATUS_RESET; | |
| 335 | − hdmi_write(hdmi, REG_HDMI_DDC_CTRL, reg_val); | |
| 332 | + hdmi_clear_bits(hdmi, REG_HDMI_DDC_CTRL, HDMI_DDC_CTRL_SW_STATUS_RESET); | |
| 336 | 333 | |
| 337 | 334 | /* Reset HDMI DDC Controller */ |
| 338 | − reg_val = hdmi_read(hdmi, REG_HDMI_DDC_CTRL); | |
| 339 | − reg_val |= HDMI_DDC_CTRL_SOFT_RESET; | |
| 340 | − hdmi_write(hdmi, REG_HDMI_DDC_CTRL, reg_val); | |
| 335 | + hdmi_update_bits(hdmi, REG_HDMI_DDC_CTRL, HDMI_DDC_CTRL_SOFT_RESET, | |
| 336 | + HDMI_DDC_CTRL_SOFT_RESET); | |
| 341 | 337 | |
| 342 | 338 | /* If previous msleep is aborted, skip this msleep */ |
| 343 | 339 | if (!rc) |
| 344 | 340 | rc = msm_hdmi_hdcp_msleep(hdcp_ctrl, 20, AUTH_ABORT_EV); |
| 345 | 341 | |
| 346 | − reg_val = hdmi_read(hdmi, REG_HDMI_DDC_CTRL); | |
| 347 | − reg_val &= ~HDMI_DDC_CTRL_SOFT_RESET; | |
| 348 | − hdmi_write(hdmi, REG_HDMI_DDC_CTRL, reg_val); | |
| 342 | + hdmi_clear_bits(hdmi, REG_HDMI_DDC_CTRL, HDMI_DDC_CTRL_SOFT_RESET); | |
| 349 | 343 | DBG("After: HDMI_DDC_SW_STATUS=0x%08x", |
| 350 | 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 | 393 | struct hdmi_hdcp_ctrl, hdcp_reauth_work); |
| 400 | 394 | struct hdmi *hdmi = hdcp_ctrl->hdmi; |
| 401 | 395 | unsigned long flags; |
| 402 | − u32 reg_val; | |
| 403 | 396 | |
| 404 | 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 | 402 | * AN1_READY bits in HDMI_HDCP_LINK0_STATUS register |
| 410 | 403 | */ |
| 411 | 404 | spin_lock_irqsave(&hdmi->reg_lock, flags); |
| 412 | − reg_val = hdmi_read(hdmi, REG_HDMI_HPD_CTRL); | |
| 413 | − reg_val &= ~HDMI_HPD_CTRL_ENABLE; | |
| 414 | − hdmi_write(hdmi, REG_HDMI_HPD_CTRL, reg_val); | |
| 405 | + hdmi_clear_bits(hdmi, REG_HDMI_HPD_CTRL, HDMI_HPD_CTRL_ENABLE); | |
| 415 | 406 | |
| 416 | 407 | /* Disable HDCP interrupts */ |
| 417 | 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 | 423 | /* Enable HPD circuitry */ |
| 433 | 424 | spin_lock_irqsave(&hdmi->reg_lock, flags); |
| 434 | − reg_val = hdmi_read(hdmi, REG_HDMI_HPD_CTRL); | |
| 435 | − reg_val |= HDMI_HPD_CTRL_ENABLE; | |
| 436 | − hdmi_write(hdmi, REG_HDMI_HPD_CTRL, reg_val); | |
| 425 | + hdmi_update_bits(hdmi, REG_HDMI_HPD_CTRL, HDMI_HPD_CTRL_ENABLE, | |
| 426 | + HDMI_HPD_CTRL_ENABLE); | |
| 437 | 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 | 447 | struct hdmi *hdmi = hdcp_ctrl->hdmi; |
| 458 | 448 | u32 link0_status; |
| 459 | − u32 reg_val; | |
| 460 | 449 | unsigned long flags; |
| 461 | 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 | 462 | spin_lock_irqsave(&hdmi->reg_lock, flags); |
| 474 | 463 | /* disable HDMI Encrypt */ |
| 475 | − reg_val = hdmi_read(hdmi, REG_HDMI_CTRL); | |
| 476 | − reg_val &= ~HDMI_CTRL_ENCRYPTED; | |
| 477 | − hdmi_write(hdmi, REG_HDMI_CTRL, reg_val); | |
| 464 | + hdmi_clear_bits(hdmi, REG_HDMI_CTRL, HDMI_CTRL_ENCRYPTED); | |
| 478 | 465 | |
| 479 | 466 | /* Enabling Software DDC */ |
| 480 | − reg_val = hdmi_read(hdmi, REG_HDMI_DDC_ARBITRATION); | |
| 481 | − reg_val &= ~HDMI_DDC_ARBITRATION_HW_ARBITRATION; | |
| 482 | − hdmi_write(hdmi, REG_HDMI_DDC_ARBITRATION, reg_val); | |
| 467 | + hdmi_clear_bits(hdmi, REG_HDMI_DDC_ARBITRATION, | |
| 468 | + HDMI_DDC_ARBITRATION_HW_ARBITRATION); | |
| 483 | 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 | 484 | hdmi_write(hdmi, REG_HDMI_HDCP_ENTROPY_CTRL1, 0xF00DFACE); |
| 499 | 485 | |
| 500 | 486 | /* Disable the RngCipher state */ |
| 501 | − reg_val = hdmi_read(hdmi, REG_HDMI_HDCP_DEBUG_CTRL); | |
| 502 | − reg_val &= ~HDMI_HDCP_DEBUG_CTRL_RNG_CIPHER; | |
| 503 | − hdmi_write(hdmi, REG_HDMI_HDCP_DEBUG_CTRL, reg_val); | |
| 487 | + hdmi_clear_bits(hdmi, REG_HDMI_HDCP_DEBUG_CTRL, | |
| 488 | + HDMI_HDCP_DEBUG_CTRL_RNG_CIPHER); | |
| 504 | 489 | DBG("HDCP_DEBUG_CTRL=0x%08x", |
| 505 | 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 | 522 | static void msm_hdmi_hdcp_auth_fail(struct hdmi_hdcp_ctrl *hdcp_ctrl) |
| 538 | 523 | { |
| 539 | 524 | struct hdmi *hdmi = hdcp_ctrl->hdmi; |
| 540 | − u32 reg_val; | |
| 541 | 525 | unsigned long flags; |
| 542 | 526 | |
| 543 | 527 | DBG("hdcp auth failed, queue reauth work"); |
| 544 | 528 | /* clear HDMI Encrypt */ |
| 545 | 529 | spin_lock_irqsave(&hdmi->reg_lock, flags); |
| 546 | − reg_val = hdmi_read(hdmi, REG_HDMI_CTRL); | |
| 547 | − reg_val &= ~HDMI_CTRL_ENCRYPTED; | |
| 548 | − hdmi_write(hdmi, REG_HDMI_CTRL, reg_val); | |
| 530 | + hdmi_clear_bits(hdmi, REG_HDMI_CTRL, HDMI_CTRL_ENCRYPTED); | |
| 549 | 531 | spin_unlock_irqrestore(&hdmi->reg_lock, flags); |
| 550 | 532 | |
| 551 | 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 | 537 | static void msm_hdmi_hdcp_auth_done(struct hdmi_hdcp_ctrl *hdcp_ctrl) |
| 556 | 538 | { |
| 557 | 539 | struct hdmi *hdmi = hdcp_ctrl->hdmi; |
| 558 | − u32 reg_val; | |
| 559 | 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 | 544 | * there is no Arbitration between software and hardware for DDC |
| 564 | 545 | */ |
| 565 | 546 | spin_lock_irqsave(&hdmi->reg_lock, flags); |
| 566 | − reg_val = hdmi_read(hdmi, REG_HDMI_DDC_ARBITRATION); | |
| 567 | − reg_val |= HDMI_DDC_ARBITRATION_HW_ARBITRATION; | |
| 568 | − hdmi_write(hdmi, REG_HDMI_DDC_ARBITRATION, reg_val); | |
| 547 | + hdmi_update_bits(hdmi, REG_HDMI_DDC_ARBITRATION, | |
| 548 | + HDMI_DDC_ARBITRATION_HW_ARBITRATION, | |
| 549 | + HDMI_DDC_ARBITRATION_HW_ARBITRATION); | |
| 569 | 550 | spin_unlock_irqrestore(&hdmi->reg_lock, flags); |
| 570 | 551 | |
| 571 | 552 | /* enable HDMI Encrypt */ |
| 572 | 553 | spin_lock_irqsave(&hdmi->reg_lock, flags); |
| 573 | − reg_val = hdmi_read(hdmi, REG_HDMI_CTRL); | |
| 574 | − reg_val |= HDMI_CTRL_ENCRYPTED; | |
| 575 | − hdmi_write(hdmi, REG_HDMI_CTRL, reg_val); | |
| 554 | + hdmi_update_bits(hdmi, REG_HDMI_CTRL, HDMI_CTRL_ENCRYPTED, | |
| 555 | + HDMI_CTRL_ENCRYPTED); | |
| 576 | 556 | spin_unlock_irqrestore(&hdmi->reg_lock, flags); |
| 577 | 557 | |
| 578 | 558 | hdcp_ctrl->hdcp_state = HDCP_STATE_AUTHENTICATED; |
| @@ -1304,7 +1284,6 @@ end: · 725 unmodified lines | ||
| 1304 | 1284 | void msm_hdmi_hdcp_on(struct hdmi_hdcp_ctrl *hdcp_ctrl) |
| 1305 | 1285 | { |
| 1306 | 1286 | struct hdmi *hdmi = hdcp_ctrl->hdmi; |
| 1307 | − u32 reg_val; | |
| 1308 | 1287 | unsigned long flags; |
| 1309 | 1288 | |
| 1310 | 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 | 1295 | /* clear HDMI Encrypt */ |
| 1317 | 1296 | spin_lock_irqsave(&hdmi->reg_lock, flags); |
| 1318 | − reg_val = hdmi_read(hdmi, REG_HDMI_CTRL); | |
| 1319 | − reg_val &= ~HDMI_CTRL_ENCRYPTED; | |
| 1320 | − hdmi_write(hdmi, REG_HDMI_CTRL, reg_val); | |
| 1297 | + hdmi_clear_bits(hdmi, REG_HDMI_CTRL, HDMI_CTRL_ENCRYPTED); | |
| 1321 | 1298 | spin_unlock_irqrestore(&hdmi->reg_lock, flags); |
| 1322 | 1299 | |
| 1323 | 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 | 1308 | struct hdmi *hdmi = hdcp_ctrl->hdmi; |
| 1332 | 1309 | unsigned long flags; |
| 1333 | − u32 reg_val; | |
| 1334 | 1310 | |
| 1335 | 1311 | if ((HDCP_STATE_INACTIVE == hdcp_ctrl->hdcp_state) || |
| 1336 | 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 | 1321 | * AN1_READY bits in HDMI_HDCP_LINK0_STATUS register |
| 1346 | 1322 | */ |
| 1347 | 1323 | spin_lock_irqsave(&hdmi->reg_lock, flags); |
| 1348 | − reg_val = hdmi_read(hdmi, REG_HDMI_HPD_CTRL); | |
| 1349 | − reg_val &= ~HDMI_HPD_CTRL_ENABLE; | |
| 1350 | − hdmi_write(hdmi, REG_HDMI_HPD_CTRL, reg_val); | |
| 1324 | + hdmi_clear_bits(hdmi, REG_HDMI_HPD_CTRL, HDMI_HPD_CTRL_ENABLE); | |
| 1351 | 1325 | |
| 1352 | 1326 | /* |
| 1353 | 1327 | * Disable HDCP interrupts. |
| @@ -1375,14 +1349,11 @@ void msm_hdmi_hdcp_off(struct hdmi_hdcp_ctrl *hdcp_ctrl) · 21 unmodified lines | ||
| 1375 | 1349 | hdmi_write(hdmi, REG_HDMI_HDCP_CTRL, 0); |
| 1376 | 1350 | |
| 1377 | 1351 | spin_lock_irqsave(&hdmi->reg_lock, flags); |
| 1378 | − reg_val = hdmi_read(hdmi, REG_HDMI_CTRL); | |
| 1379 | − reg_val &= ~HDMI_CTRL_ENCRYPTED; | |
| 1380 | − hdmi_write(hdmi, REG_HDMI_CTRL, reg_val); | |
| 1352 | + hdmi_clear_bits(hdmi, REG_HDMI_CTRL, HDMI_CTRL_ENCRYPTED); | |
| 1381 | 1353 | |
| 1382 | 1354 | /* Enable HPD circuitry */ |
| 1383 | − reg_val = hdmi_read(hdmi, REG_HDMI_HPD_CTRL); | |
| 1384 | − reg_val |= HDMI_HPD_CTRL_ENABLE; | |
| 1385 | − hdmi_write(hdmi, REG_HDMI_HPD_CTRL, reg_val); | |
| 1355 | + hdmi_update_bits(hdmi, REG_HDMI_HPD_CTRL, HDMI_HPD_CTRL_ENABLE, | |
| 1356 | + HDMI_HPD_CTRL_ENABLE); | |
| 1386 | 1357 | spin_unlock_irqrestore(&hdmi->reg_lock, flags); |
| 1387 | 1358 | |
| 1388 | 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 | 223 | struct drm_gpuvm *msm_context_vm(struct drm_device *dev, struct msm_context *ctx) |
| 224 | 224 | { |
| 225 | − static DEFINE_MUTEX(init_lock); | |
| 226 | 225 | struct msm_drm_private *priv = dev->dev_private; |
| 226 | + struct drm_gpuvm *vm = smp_load_acquire(&ctx->vm); | |
| 227 | 227 | |
| 228 | 228 | /* Once ctx->vm is created it is valid for the lifetime of the context: */ |
| 229 | − if (ctx->vm) | |
| 230 | − return ctx->vm; | |
| 229 | + if (vm) | |
| 230 | + return vm; | |
| 231 | + | |
| 232 | + guard(rwsem_write)(&ctx->ctxlock); | |
| 231 | 233 | |
| 232 | − mutex_lock(&init_lock); | |
| 233 | 234 | if (!ctx->vm) { |
| 234 | − ctx->vm = msm_gpu_create_private_vm( | |
| 235 | + vm = msm_gpu_create_private_vm( | |
| 235 | 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 | 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 | 251 | return -ENOMEM; |
| 251 | 252 | |
| 252 | 253 | INIT_LIST_HEAD(&ctx->submitqueues); |
| 253 | − rwlock_init(&ctx->queuelock); | |
| 254 | + init_rwsem(&ctx->ctxlock); | |
| 254 | 255 | |
| 255 | 256 | kref_init(&ctx->ref); |
| 256 | 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 | 424 | struct msm_drm_private *priv = dev->dev_private; |
| 424 | 425 | struct msm_context *ctx = file->driver_priv; |
| 426 | + struct drm_gpuvm *vm = msm_context_vm(dev, ctx); | |
| 425 | 427 | |
| 426 | 428 | if (!priv->gpu) |
| 427 | 429 | return -EINVAL; |
| 428 | 430 | |
| 431 | + if (!vm) | |
| 432 | + return UERR(ENOMEM, dev, "no VM"); | |
| 433 | + | |
| 429 | 434 | if (msm_context_is_vmbind(ctx)) |
| 430 | 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 | 441 | * Don't pin the memory here - just get an address so that userspace can |
| 437 | 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 | 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 | 455 | if (!priv->gpu) |
| 451 | 456 | return -EINVAL; |
| 452 | 457 | |
| 458 | + if (!vm) | |
| 459 | + return UERR(ENOMEM, dev, "no VM"); | |
| 460 | + | |
| 453 | 461 | if (msm_context_is_vmbind(ctx)) |
| 454 | 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 | 261 | struct drm_framebuffer *msm_framebuffer_create(struct drm_device *dev, |
| 262 | 262 | struct drm_file *file, const struct drm_format_info *info, |
| 263 | 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 | 265 | #ifdef CONFIG_DRM_MSM_KMS_FBDEV |
| 268 | 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 | 354 | int msm_dp_modeset_init(struct msm_dp *dp_display, struct drm_device *dev, |
| 357 | 355 | struct drm_encoder *encoder, bool yuv_supported); |
| 358 | 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 | 357 | bool msm_dp_needs_periph_flush(const struct msm_dp *dp_display, |
| 362 | 358 | const struct drm_display_mode *mode); |
| 363 | 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 | 381 | static inline bool msm_dp_needs_periph_flush(const struct msm_dp *dp_display, |
| 392 | 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 | 493 | #define DBG(fmt, ...) DRM_DEBUG_DRIVER(fmt"\n", ##__VA_ARGS__) |
| 504 | 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 | 496 | /* for the generated headers: */ |
| 514 | 497 | #define INVALID_IDX(idx) ({BUG(); 0;}) |
| 515 | 498 | #define fui(x) ({BUG(); 0;}) |
| @@ -6,7 +6,6 @@ · 5 unmodified lines | ||
| 6 | 6 | |
| 7 | 7 | #include <drm/drm_crtc.h> |
| 8 | 8 | #include <drm/drm_damage_helper.h> |
| 9 | −#include <drm/drm_file.h> | |
| 10 | 9 | #include <drm/drm_fourcc.h> |
| 11 | 10 | #include <drm/drm_framebuffer.h> |
| 12 | 11 | #include <drm/drm_gem_framebuffer_helper.h> |
| @@ -29,10 +28,6 @@ struct msm_framebuffer { · 16 unmodified lines | ||
| 29 | 28 | }; |
| 30 | 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 | 31 | static int msm_framebuffer_dirtyfb(struct drm_framebuffer *fb, |
| 37 | 32 | struct drm_file *file_priv, unsigned int flags, |
| 38 | 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 | 134 | return msm_fb->format; |
| 140 | 135 | } |
| 141 | 136 | |
| 142 | −struct drm_framebuffer *msm_framebuffer_create(struct drm_device *dev, | |
| 143 | − struct drm_file *file, const struct drm_format_info *info, | |
| 144 | − const struct drm_mode_fb_cmd2 *mode_cmd) | |
| 145 | −{ | |
| 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) | |
| 137 | +static struct drm_framebuffer * | |
| 138 | +msm_framebuffer_init(struct drm_device *dev, const struct drm_format_info *info, | |
| 139 | + const struct drm_mode_fb_cmd2 *mode_cmd, | |
| 140 | + struct drm_gem_object **bos) | |
| 175 | 141 | { |
| 176 | 142 | struct msm_drm_private *priv = dev->dev_private; |
| 177 | 143 | struct msm_kms *kms = priv->kms; |
| @@ -251,47 +217,33 @@ fail: · 73 unmodified lines | ||
| 251 | 217 | return ERR_PTR(ret); |
| 252 | 218 | } |
| 253 | 219 | |
| 254 | −struct drm_framebuffer * | |
| 255 | −msm_alloc_stolen_fb(struct drm_device *dev, int w, int h, int p, uint32_t format) | |
| 220 | +struct drm_framebuffer *msm_framebuffer_create(struct drm_device *dev, | |
| 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 = { | |
| 258 | − .pixel_format = format, | |
| 259 | − .width = w, | |
| 260 | − .height = h, | |
| 261 | − .pitches = { p }, | |
| 262 | − }; | |
| 263 | − struct drm_gem_object *bo; | |
| 225 | + struct drm_gem_object *bos[4] = {0}; | |
| 264 | 226 | struct drm_framebuffer *fb; |
| 265 | − int size; | |
| 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 | − } | |
| 227 | + int ret, i, n = info->num_planes; | |
| 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, | |
| 284 | − drm_get_format_info(dev, mode_cmd.pixel_format, | |
| 285 | − mode_cmd.modifier[0]), | |
| 286 | − &mode_cmd, &bo); | |
| 237 | + fb = msm_framebuffer_init(dev, info, mode_cmd, bos); | |
| 287 | 238 | if (IS_ERR(fb)) { |
| 288 | − DRM_DEV_ERROR(dev->dev, "failed to allocate fb\n"); | |
| 289 | − /* note: if fb creation failed, we can't rely on fb destroy | |
| 290 | − * to unref the bo: | |
| 291 | − */ | |
| 292 | − drm_gem_object_put(bo); | |
| 293 | − return ERR_CAST(fb); | |
| 239 | + ret = PTR_ERR(fb); | |
| 240 | + goto out_unref; | |
| 294 | 241 | } |
| 295 | 242 | |
| 296 | 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 | 9 | #include <drm/drm_drv.h> |
| 10 | 10 | #include <drm/drm_crtc_helper.h> |
| 11 | 11 | #include <drm/drm_fb_helper.h> |
| 12 | +#include <drm/drm_file.h> | |
| 12 | 13 | #include <drm/drm_fourcc.h> |
| 13 | 14 | #include <drm/drm_framebuffer.h> |
| 14 | 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 | 41 | static void msm_fbdev_fb_destroy(struct fb_info *info) |
| 41 | 42 | { |
| 42 | 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(fb, 0); | |
| 44 | + struct drm_gem_object *bo = msm_framebuffer_bo(helper->fb, 0); | |
| 45 | 45 | |
| 46 | 46 | DBG(); |
| 47 | 47 | |
| 48 | 48 | drm_fb_helper_fini(helper); |
| 49 | 49 | |
| 50 | − /* this will free the backing object */ | |
| 51 | 50 | msm_gem_put_vaddr(bo); |
| 52 | − drm_framebuffer_remove(fb); | |
| 53 | 51 | |
| 52 | + drm_client_buffer_delete(helper->buffer); | |
| 54 | 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 | 88 | int msm_fbdev_driver_fbdev_probe(struct drm_fb_helper *helper, |
| 90 | 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 | 94 | struct msm_drm_private *priv = dev->dev_private; |
| 94 | 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 | 99 | struct drm_gem_object *bo; |
| 100 | + struct drm_client_buffer *buffer; | |
| 97 | 101 | uint64_t paddr; |
| 98 | − uint32_t format; | |
| 99 | − int ret, pitch; | |
| 100 | − | |
| 101 | − format = drm_mode_legacy_fb_format(sizes->surface_bpp, sizes->surface_depth); | |
| 102 | + int ret; | |
| 102 | 103 | |
| 103 | 104 | DBG("create fbdev: %dx%d@%d (%dx%d)", sizes->surface_width, |
| 104 | 105 | sizes->surface_height, sizes->surface_bpp, |
| 105 | 106 | sizes->fb_width, sizes->fb_height); |
| 106 | 107 | |
| 107 | − pitch = align_pitch(sizes->surface_width, sizes->surface_bpp); | |
| 108 | − fb = msm_alloc_stolen_fb(dev, sizes->surface_width, | |
| 109 | − sizes->surface_height, pitch, format); | |
| 110 | − | |
| 111 | − if (IS_ERR(fb)) { | |
| 112 | − DRM_DEV_ERROR(dev->dev, "failed to allocate fb\n"); | |
| 113 | − return PTR_ERR(fb); | |
| 108 | + fourcc = drm_mode_legacy_fb_format(sizes->surface_bpp, sizes->surface_depth); | |
| 109 | + format = drm_get_format_info(dev, fourcc, DRM_FORMAT_MOD_LINEAR); | |
| 110 | + /* adreno needs pitch aligned to 32 pixels: */ | |
| 111 | + pitch = drm_format_info_min_pitch(format, 0, ALIGN(sizes->surface_width, 32)); | |
| 112 | + size = ALIGN(pitch * sizes->surface_height, PAGE_SIZE); | |
| 113 | + | |
| 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 | 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 | 145 | ret = msm_gem_get_and_pin_iova(bo, priv->kms->vm, &paddr); |
| 124 | 146 | if (ret) { |
| 125 | − DRM_DEV_ERROR(dev->dev, "failed to get buffer obj iova: %d\n", ret); | |
| 126 | − goto fail; | |
| 147 | + drm_err(dev, "failed to get buffer obj iova: %d\n", ret); | |
| 148 | + goto err_drm_client_buffer_delete; | |
| 127 | 149 | } |
| 128 | 150 | |
| 129 | 151 | DBG("fbi=%p, dev=%p", fbi, dev); |
| 130 | 152 | |
| 131 | 153 | helper->funcs = &msm_fbdev_helper_funcs; |
| 132 | − helper->fb = fb; | |
| 154 | + helper->buffer = buffer; | |
| 155 | + helper->fb = buffer->fb; | |
| 133 | 156 | |
| 134 | 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 | 161 | fbi->screen_buffer = msm_gem_get_vaddr(bo); |
| 139 | 162 | if (IS_ERR(fbi->screen_buffer)) { |
| 140 | 163 | ret = PTR_ERR(fbi->screen_buffer); |
| 141 | − goto fail; | |
| 164 | + goto err_msm_gem_unpin; | |
| 142 | 165 | } |
| 143 | 166 | fbi->screen_size = bo->size; |
| 144 | 167 | fbi->fix.smem_start = paddr; |
| 145 | 168 | fbi->fix.smem_len = bo->size; |
| 146 | 169 | |
| 147 | 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 | 179 | return 0; |
| 151 | 180 | |
| 152 | −fail: | |
| 153 | − drm_framebuffer_remove(fb); | |
| 181 | +err_msm_gem_unpin: | |
| 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 | 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 | 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 | 1099 | } else { |
| 1098 | 1100 | msm_gem_vunmap(obj); |
| 1099 | 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 | 1136 | size_t size, uint32_t flags, uint32_t *handle, |
| 1135 | 1137 | char *name) |
| 1136 | 1138 | { |
| 1137 | − struct drm_gem_object *obj; | |
| 1139 | + struct drm_gem_object *obj, *r_obj = NULL; | |
| 1138 | 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 | 1155 | if (IS_ERR(obj)) |
| 1143 | 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 | 1158 | if (name) |
| 1146 | 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 | 1161 | ret = drm_gem_handle_create(file, obj, handle); |
| 1158 | 1162 | |
| 1159 | 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 | 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 | 1260 | struct drm_gem_object *obj = NULL; |
| 1240 | 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 | 1272 | if (ret) |
| 1252 | 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 | 1280 | ret = drm_gem_object_init(dev, obj, size); |
| 1257 | 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 | 1289 | mapping_set_gfp_mask(obj->filp->f_mapping, GFP_HIGHUSER); |
| 1266 | 1290 | |
| 1267 | − drm_gem_lru_move_tail(&priv->lru.unbacked, 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); | |
| 1291 | + ret = msm_gem_init_bookkeeping(obj); | |
| 1274 | 1292 | if (ret) |
| 1275 | 1293 | goto fail; |
| 1276 | 1294 | |
| @@ -1282,11 +1300,12 @@ fail: · 5 unmodified lines | ||
| 1282 | 1300 | } |
| 1283 | 1301 | |
| 1284 | 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 | 1306 | struct msm_gem_object *msm_obj; |
| 1289 | 1307 | struct drm_gem_object *obj; |
| 1308 | + struct dma_buf *dmabuf = attach->dmabuf; | |
| 1290 | 1309 | size_t size, npages; |
| 1291 | 1310 | int ret; |
| 1292 | 1311 | |
| @@ -1296,38 +1315,35 @@ struct drm_gem_object *msm_gem_import(struct drm_device *dev, · 3 unmodified lines | ||
| 1296 | 1315 | if (ret) |
| 1297 | 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 | 1324 | drm_gem_private_object_init(dev, obj, size); |
| 1300 | 1325 | |
| 1301 | 1326 | npages = size / PAGE_SIZE; |
| 1302 | 1327 | |
| 1303 | 1328 | msm_obj = to_msm_bo(obj); |
| 1304 | − msm_gem_lock(obj); | |
| 1305 | − msm_obj->sgt = sgt; | |
| 1306 | 1329 | msm_obj->pages = kvmalloc_objs(struct page *, npages); |
| 1307 | 1330 | if (!msm_obj->pages) { |
| 1308 | − msm_gem_unlock(obj); | |
| 1309 | 1331 | ret = -ENOMEM; |
| 1310 | 1332 | goto fail; |
| 1311 | 1333 | } |
| 1312 | 1334 | |
| 1313 | 1335 | ret = drm_prime_sg_to_page_array(sgt, msm_obj->pages, npages); |
| 1314 | 1336 | if (ret) { |
| 1315 | − msm_gem_unlock(obj); | |
| 1316 | 1337 | goto fail; |
| 1317 | 1338 | } |
| 1318 | 1339 | |
| 1319 | − msm_gem_unlock(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); | |
| 1340 | + ret = msm_gem_init_bookkeeping(obj); | |
| 1328 | 1341 | if (ret) |
| 1329 | 1342 | goto fail; |
| 1330 | 1343 | |
| 1344 | + /* Now that we are past potential failure points, set sgt: */ | |
| 1345 | + msm_obj->sgt = sgt; | |
| 1346 | + | |
| 1331 | 1347 | return obj; |
| 1332 | 1348 | |
| 1333 | 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 | 1356 | uint64_t *iova) |
| 1341 | 1357 | { |
| 1342 | 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 | 1360 | int ret; |
| 1345 | 1361 | |
| 1346 | 1362 | if (IS_ERR(obj)) |
| @@ -296,13 +296,14 @@ int msm_gem_cpu_fini(struct drm_gem_object *obj); · 295 unmodified lines | ||
| 296 | 296 | int msm_gem_new_handle(struct drm_device *dev, struct drm_file *file, |
| 297 | 297 | size_t size, uint32_t flags, uint32_t *handle, char *name); |
| 298 | 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 | 300 | void *msm_gem_kernel_new(struct drm_device *dev, size_t size, uint32_t flags, |
| 301 | 301 | struct drm_gpuvm *vm, struct drm_gem_object **bo, |
| 302 | 302 | uint64_t *iova); |
| 303 | 303 | void msm_gem_kernel_put(struct drm_gem_object *bo, struct drm_gpuvm *vm); |
| 304 | 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 | 307 | __printf(2, 3) |
| 307 | 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 | 83 | struct drm_gem_object *msm_gem_prime_import_sg_table(struct drm_device *dev, |
| 84 | 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 | 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 | 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 | 34 | struct msm_gpu_submitqueue *queue, uint32_t nr_bos, |
| 35 | 35 | uint32_t nr_cmds, u64 drm_client_id) |
| 36 | 36 | { |
| 37 | 37 | static atomic_t ident = ATOMIC_INIT(0); |
| 38 | 38 | struct msm_gem_submit *submit; |
| 39 | − uint64_t sz; | |
| 39 | + size_t sz; | |
| 40 | 40 | int ret; |
| 41 | 41 | |
| 42 | − sz = struct_size(submit, bos, nr_bos) + | |
| 43 | − ((u64)nr_cmds * sizeof(submit->cmd[0])); | |
| 44 | − | |
| 45 | − if (sz > SIZE_MAX) | |
| 46 | − return ERR_PTR(-ENOMEM); | |
| 42 | + sz = size_add(struct_size(submit, bos, nr_bos), | |
| 43 | + array_size(sizeof(submit->cmd[0]), nr_cmds)); | |
| 47 | 44 | |
| 48 | 45 | submit = kzalloc(sz, GFP_KERNEL | __GFP_NOWARN); |
| 49 | 46 | if (!submit) |
| @@ -66,7 +63,7 @@ static struct msm_gem_submit *submit_create(struct drm_device *dev, · 16 unmodified lines | ||
| 66 | 63 | |
| 67 | 64 | kref_init(&submit->ref); |
| 68 | 65 | submit->dev = dev; |
| 69 | − submit->vm = msm_context_vm(dev, queue->ctx); | |
| 66 | + submit->vm = vm; | |
| 70 | 67 | submit->gpu = gpu; |
| 71 | 68 | submit->cmd = (void *)&submit->bos[nr_bos]; |
| 72 | 69 | submit->queue = queue; |
| @@ -250,16 +247,14 @@ static int submit_lookup_cmds(struct msm_gem_submit *submit, · 177 unmodified lines | ||
| 250 | 247 | |
| 251 | 248 | sz = array_size(submit_cmd.nr_relocs, |
| 252 | 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 | 250 | submit->cmd[i].relocs = kmalloc(sz, GFP_KERNEL | __GFP_NOWARN); |
| 259 | 251 | if (!submit->cmd[i].relocs) { |
| 260 | 252 | ret = -ENOMEM; |
| 261 | 253 | goto out; |
| 262 | 254 | } |
| 255 | + | |
| 256 | + submit->nr_cmds = i + 1; | |
| 257 | + | |
| 263 | 258 | ret = copy_from_user(submit->cmd[i].relocs, userptr, sz); |
| 264 | 259 | if (ret) { |
| 265 | 260 | ret = -EFAULT; |
| @@ -554,6 +549,7 @@ int msm_ioctl_gem_submit(struct drm_device *dev, void *data, · 288 unmodified lines | ||
| 554 | 549 | struct msm_drm_private *priv = dev->dev_private; |
| 555 | 550 | struct drm_msm_gem_submit *args = data; |
| 556 | 551 | struct msm_context *ctx = file->driver_priv; |
| 552 | + struct drm_gpuvm *vm = msm_context_vm(dev, ctx); | |
| 557 | 553 | struct msm_gem_submit *submit = NULL; |
| 558 | 554 | struct msm_gpu *gpu = priv->gpu; |
| 559 | 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 | 565 | if (!gpu) |
| 570 | 566 | return -ENXIO; |
| 571 | 567 | |
| 568 | + if (!vm) | |
| 569 | + return UERR(ENOMEM, dev, "no VM"); | |
| 570 | + | |
| 572 | 571 | if (args->pad) |
| 573 | 572 | return -EINVAL; |
| 574 | 573 | |
| 575 | − if (to_msm_vm(ctx->vm)->unusable) | |
| 574 | + if (to_msm_vm(vm)->unusable) | |
| 576 | 575 | return UERR(EPIPE, dev, "context is unusable"); |
| 577 | 576 | |
| 578 | 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 | 612 | file->client_id); |
| 614 | 613 | if (IS_ERR(submit)) { |
| 615 | 614 | ret = PTR_ERR(submit); |
| @@ -719,8 +718,6 @@ int msm_ioctl_gem_submit(struct drm_device *dev, void *data, · 103 unmodified lines | ||
| 719 | 718 | goto out; |
| 720 | 719 | } |
| 721 | 720 | |
| 722 | − submit->nr_cmds = args->nr_cmds; | |
| 723 | − | |
| 724 | 721 | idr_preload(GFP_KERNEL); |
| 725 | 722 | |
| 726 | 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 | 458 | return ret; |
| 459 | 459 | } |
| 460 | 460 | |
| 461 | + drm_gpuvm_bo_evict(vm_bo, false); | |
| 462 | + | |
| 461 | 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 | 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 | 961 | struct msm_gpu_submitqueue *queue, uint32_t nr_ops) |
| 960 | 962 | { |
| 961 | 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 | 974 | return ERR_PTR(ret); |
| 973 | 975 | } |
| 974 | 976 | |
| 975 | − job->vm = msm_context_vm(dev, queue->ctx); | |
| 977 | + job->vm = vm; | |
| 976 | 978 | job->queue = queue; |
| 977 | 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 | 1433 | struct msm_drm_private *priv = dev->dev_private; |
| 1432 | 1434 | struct drm_msm_vm_bind *args = data; |
| 1433 | 1435 | struct msm_context *ctx = file->driver_priv; |
| 1436 | + struct drm_gpuvm *vm = msm_context_vm(dev, ctx); | |
| 1434 | 1437 | struct msm_vm_bind_job *job = NULL; |
| 1435 | 1438 | struct msm_gpu *gpu = priv->gpu; |
| 1436 | 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 | 1448 | if (!gpu) |
| 1446 | 1449 | return -ENXIO; |
| 1447 | 1450 | |
| 1451 | + if (!vm) | |
| 1452 | + return UERR(ENOMEM, dev, "no VM"); | |
| 1453 | + | |
| 1448 | 1454 | /* |
| 1449 | 1455 | * Maybe we could allow just UNMAP ops? OTOH userspace should just |
| 1450 | 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 | 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 | 1490 | if (IS_ERR(job)) { |
| 1485 | 1491 | ret = PTR_ERR(job); |
| 1486 | 1492 | goto out_post_unlock; |
| @@ -505,6 +505,8 @@ static void recover_worker(struct kthread_work *work) · 504 unmodified lines | ||
| 505 | 505 | */ |
| 506 | 506 | if (!vm->managed) |
| 507 | 507 | msm_gem_vm_unusable(submit->vm); |
| 508 | + | |
| 509 | + put_task_struct(task); | |
| 508 | 510 | } |
| 509 | 511 | |
| 510 | 512 | noreclaim_flag = memalloc_noreclaim_save(); |
| @@ -552,11 +554,13 @@ static void recover_worker(struct kthread_work *work) · 41 unmodified lines | ||
| 552 | 554 | msm_update_fence(ring->fctx, fence); |
| 553 | 555 | } |
| 554 | 556 | |
| 555 | − /* retire completed submits, plus the one that hung: */ | |
| 556 | − retire_submits(gpu); | |
| 557 | + priv->disable_err_irq = false; | |
| 557 | 558 | |
| 558 | 559 | gpu->funcs->recover(gpu); |
| 559 | 560 | |
| 561 | + /* retire completed submits, plus the one that hung: */ | |
| 562 | + retire_submits(gpu); | |
| 563 | + | |
| 560 | 564 | /* |
| 561 | 565 | * Replay all remaining submits starting with highest priority |
| 562 | 566 | * ring |
| @@ -875,7 +879,7 @@ msm_gpu_create_private_vm(struct msm_gpu *gpu, struct task_struct *task, · 312 unmodified lines | ||
| 875 | 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 | 883 | vm = drm_gpuvm_get(gpu->vm); |
| 880 | 884 | |
| 881 | 885 | return vm; |
| @@ -392,8 +392,8 @@ msm_gpu_sysprof_no_ifpc(struct msm_gpu *gpu) · 391 unmodified lines | ||
| 392 | 392 | * struct msm_context - per-drm_file context |
| 393 | 393 | */ |
| 394 | 394 | struct msm_context { |
| 395 | − /** @queuelock: synchronizes access to submitqueues list */ | |
| 396 | − rwlock_t queuelock; | |
| 395 | + /** @ctxlock: synchronizes access to submitqueues list, etc */ | |
| 396 | + struct rw_semaphore ctxlock; | |
| 397 | 397 | /** @submitqueues: list of &msm_gpu_submitqueue created by userspace */ |
| 398 | 398 | struct list_head submitqueues; |
| 399 | 399 | /** |
| @@ -7,6 +7,15 @@ · 6 unmodified lines | ||
| 7 | 7 | #include <linux/adreno-smmu-priv.h> |
| 8 | 8 | #include <linux/io-pgtable.h> |
| 9 | 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 | 19 | #include "msm_drv.h" |
| 11 | 20 | #include "msm_gpu_trace.h" |
| 12 | 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 | 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 | 774 | ret = iommu_attach_device(iommu->domain, dev); |
| 753 | 775 | if (ret) { |
| 754 | 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 | 109 | ring->memptrs_iova = memptrs_iova; |
| 110 | 110 | |
| 111 | 111 | ret = drm_sched_init(&ring->sched, &args); |
| 112 | − if (ret) { | |
| 112 | + if (ret) | |
| 113 | 113 | goto fail; |
| 114 | − } | |
| 114 | + ring->sched_initialized = true; | |
| 115 | 115 | |
| 116 | 116 | INIT_LIST_HEAD(&ring->submits); |
| 117 | 117 | spin_lock_init(&ring->submit_lock); |
| @@ -133,7 +133,8 @@ void msm_ringbuffer_destroy(struct msm_ringbuffer *ring) · 15 unmodified lines | ||
| 133 | 133 | if (IS_ERR_OR_NULL(ring)) |
| 134 | 134 | return; |
| 135 | 135 | |
| 136 | − drm_sched_fini(&ring->sched); | |
| 136 | + if (ring->sched_initialized) | |
| 137 | + drm_sched_fini(&ring->sched); | |
| 137 | 138 | |
| 138 | 139 | msm_fence_context_free(ring->fctx); |
| 139 | 140 | |
| @@ -56,6 +56,7 @@ struct msm_ringbuffer { · 55 unmodified lines | ||
| 56 | 56 | * The job scheduler for this ring. |
| 57 | 57 | */ |
| 58 | 58 | struct drm_gpu_scheduler sched; |
| 59 | + bool sched_initialized; | |
| 59 | 60 | |
| 60 | 61 | /* |
| 61 | 62 | * List of in-flight submits on this ring. Protected by submit_lock. |
| @@ -9,6 +9,8 @@ · 8 unmodified lines | ||
| 9 | 9 | |
| 10 | 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 | 15 | * Since pm_runtime and sysprof_active are both refcounts, we |
| 14 | 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 | 95 | if (!ctx) |
| 94 | 96 | return NULL; |
| 95 | 97 | |
| 96 | − read_lock(&ctx->queuelock); | |
| 98 | + guard(rwsem_read)(&ctx->ctxlock); | |
| 97 | 99 | |
| 98 | 100 | list_for_each_entry(entry, &ctx->submitqueues, node) { |
| 99 | 101 | if (entry->id == id) { |
| 100 | 102 | kref_get(&entry->ref); |
| 101 | − read_unlock(&ctx->queuelock); | |
| 102 | − | |
| 103 | 103 | return entry; |
| 104 | 104 | } |
| 105 | 105 | } |
| 106 | 106 | |
| 107 | − read_unlock(&ctx->queuelock); | |
| 108 | 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 | 174 | struct msm_drm_private *priv = drm->dev_private; |
| 176 | 175 | struct msm_gpu_submitqueue *queue; |
| 177 | 176 | enum drm_sched_priority sched_prio; |
| 177 | + struct drm_gpuvm *vm = NULL; | |
| 178 | 178 | unsigned ring_nr; |
| 179 | 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 | 187 | if (flags & MSM_SUBMITQUEUE_VM_BIND) { |
| 188 | 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 | 195 | /* Not allowed for kernel managed VMs (ie. kernel allocs VA) */ |
| 191 | 196 | if (!msm_context_is_vmbind(ctx)) |
| 192 | 197 | return -EINVAL; |
| @@ -218,7 +223,7 @@ int msm_submitqueue_create(struct drm_device *drm, struct msm_context *ctx, · 25 unmodified lines | ||
| 218 | 223 | queue->flags = flags; |
| 219 | 224 | |
| 220 | 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 | 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 | 242 | return ret; |
| 238 | 243 | } |
| 239 | 244 | |
| 240 | − write_lock(&ctx->queuelock); | |
| 245 | + guard(rwsem_write)(&ctx->ctxlock); | |
| 241 | 246 | |
| 242 | 247 | queue->ctx = msm_context_get(ctx); |
| 243 | 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 | 257 | list_add_tail(&queue->node, &ctx->submitqueues); |
| 253 | 258 | |
| 254 | − write_unlock(&ctx->queuelock); | |
| 255 | − | |
| 256 | 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 | 338 | if (!id) |
| 336 | 339 | return -ENOENT; |
| 337 | 340 | |
| 338 | − write_lock(&ctx->queuelock); | |
| 341 | + guard(rwsem_write)(&ctx->ctxlock); | |
| 339 | 342 | |
| 340 | 343 | list_for_each_entry(entry, &ctx->submitqueues, node) { |
| 341 | 344 | if (entry->id == id) { |
| 342 | 345 | list_del(&entry->node); |
| 343 | − write_unlock(&ctx->queuelock); | |
| 344 | − | |
| 345 | 346 | msm_submitqueue_put(entry); |
| 346 | 347 | return 0; |
| 347 | 348 | } |
| 348 | 349 | } |
| 349 | 350 | |
| 350 | − write_unlock(&ctx->queuelock); | |
| 351 | 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 | 1495 | <reg32 offset="0x3058" name="VBIF_OUT_AXI_AMEMTYPE_CONF0"/> |
| 1496 | 1496 | <reg32 offset="0x305e" name="VBIF_OUT_AXI_AOOO_EN"/> |
| 1497 | 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 | 1501 | <bitset name="a3xx_vbif_perf_cnt" inline="yes"> |
| 1500 | 1502 | <bitfield name="CNT0" pos="0" type="boolean"/> |
| @@ -1268,7 +1268,7 @@ by a particular renderpass/blit. · 1267 unmodified lines | ||
| 1268 | 1268 | <reg32 offset="0x3119" name="VBIF_PERF_PWR_CNT_HIGH1" variants="A6XX"/> |
| 1269 | 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 | 1272 | <reg32 offset="0x3c01" name="GBIF_SCACHE_CNTL0"/> |
| 1273 | 1273 | <reg32 offset="0x3c02" name="GBIF_SCACHE_CNTL1"/> |
| 1274 | 1274 | <reg32 offset="0x3c03" name="GBIF_QSB_SIDE0"/> |
| @@ -228,7 +228,7 @@ struct drm_msm_gem_cpu_fini { · 227 unmodified lines | ||
| 228 | 228 | |
| 229 | 229 | struct drm_msm_syncobj { |
| 230 | 230 | __u32 handle; /* in, syncobj handle. */ |
| 231 | − __u32 flags; /* in, from MSM_SUBMIT_SYNCOBJ_FLAGS */ | |
| 231 | + __u32 flags; /* in, from MSM_SYNCOBJ_FLAGS */ | |
| 232 | 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 | 393 | __s32 fence_fd; |
| 394 | 394 | /** @queue_id: in, submitqueue id */ |
| 395 | 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 | 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 | 399 | __u64 out_syncobjs; |
| 400 | 400 | /** @nr_in_syncobjs: in, number of entries in in_syncobj */ |
| 401 | 401 | __u32 nr_in_syncobjs; |