History

Merge https://gitlab.freedesktop.org/drm/msm into drm-next-msm-5.8

* new gpu support: a405, a640, a650 * dpu: color processing support * mdp5: support for msm8x36 (the thing with a405) * some prep work for per-context pagetables (ie the part that does not depend on in-flight iommu patches) * last but not least, UABI update for submit ioctl to support syncobj (from Bas)

Dave Airlie committed 6 years ago

Commit efe792f2 parents 3d77e6a 1cb2c4a47 files · +1697 −382Browse files

Unified · Split

47 files
  1. drivers/gpu/drm/msm/Makefile +1 −0
  2. drivers/gpu/drm/msm/adreno/a2xx_gpu.c +16 −0
  3. drivers/gpu/drm/msm/adreno/a3xx_gpu.c +1 −0
  4. drivers/gpu/drm/msm/adreno/a4xx_gpu.c +68 −15
  5. drivers/gpu/drm/msm/adreno/a5xx_gpu.c +7 −0
  6. drivers/gpu/drm/msm/adreno/a6xx.xml.h +14 −0
  7. drivers/gpu/drm/msm/adreno/a6xx_gmu.c +321 −97
  8. drivers/gpu/drm/msm/adreno/a6xx_gmu.h +34 −3
  9. drivers/gpu/drm/msm/adreno/a6xx_gmu.xml.h +29 −19
  10. drivers/gpu/drm/msm/adreno/a6xx_gpu.c +59 −11
  11. drivers/gpu/drm/msm/adreno/a6xx_hfi.c +114 −9
  12. drivers/gpu/drm/msm/adreno/a6xx_hfi.h +48 −2
  13. drivers/gpu/drm/msm/adreno/adreno_device.c +35 −0
  14. drivers/gpu/drm/msm/adreno/adreno_gpu.c +19 −8
  15. drivers/gpu/drm/msm/adreno/adreno_gpu.h +23 −0
  16. drivers/gpu/drm/msm/disp/dpu1/dpu_core_perf.c +1 −22
  17. drivers/gpu/drm/msm/disp/dpu1/dpu_crtc.c +77 −18
  18. drivers/gpu/drm/msm/disp/dpu1/dpu_crtc.h +2 −0
  19. drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c +11 −1
  20. drivers/gpu/drm/msm/disp/dpu1/dpu_hw_catalog.c +36 −12
  21. drivers/gpu/drm/msm/disp/dpu1/dpu_hw_catalog.h +39 −0
  22. drivers/gpu/drm/msm/disp/dpu1/dpu_hw_ctl.c +26 −0
  23. drivers/gpu/drm/msm/disp/dpu1/dpu_hw_ctl.h +3 −0
  24. drivers/gpu/drm/msm/disp/dpu1/dpu_hw_dspp.c +129 −0
  25. drivers/gpu/drm/msm/disp/dpu1/dpu_hw_dspp.h +100 −0
  26. drivers/gpu/drm/msm/disp/dpu1/dpu_hw_mdss.h +2 −0
  27. drivers/gpu/drm/msm/disp/dpu1/dpu_kms.c +5 −13
  28. drivers/gpu/drm/msm/disp/dpu1/dpu_kms.h +1 −0
  29. drivers/gpu/drm/msm/disp/dpu1/dpu_rm.c +54 −4
  30. drivers/gpu/drm/msm/disp/dpu1/dpu_rm.h +2 −0
  31. drivers/gpu/drm/msm/disp/mdp4/mdp4_kms.c +8 −10
  32. drivers/gpu/drm/msm/disp/mdp5/mdp5_cfg.c +76 −4
  33. drivers/gpu/drm/msm/disp/mdp5/mdp5_crtc.c +2 −2
  34. drivers/gpu/drm/msm/disp/mdp5/mdp5_kms.c +11 −10
  35. drivers/gpu/drm/msm/msm_drv.c +4 −2
  36. drivers/gpu/drm/msm/msm_drv.h +8 −7
  37. drivers/gpu/drm/msm/msm_gem.c +24 −7
  38. drivers/gpu/drm/msm/msm_gem.h +1 −0
  39. drivers/gpu/drm/msm/msm_gem_submit.c +231 −1
  40. drivers/gpu/drm/msm/msm_gem_vma.c +10 −32
  41. drivers/gpu/drm/msm/msm_gpu.c +2 −47
  42. drivers/gpu/drm/msm/msm_gpu.h +2 −2
  43. drivers/gpu/drm/msm/msm_gpummu.c +2 −8
  44. drivers/gpu/drm/msm/msm_iommu.c +12 −10
  45. drivers/gpu/drm/msm/msm_mmu.h +2 −3
  46. drivers/gpu/drm/msm/msm_rd.c +2 −2
  47. include/uapi/drm/msm_drm.h +23 −1
drivers/gpu/drm/msm/Makefile+1−0
@@ -65,6 +65,7 @@ msm-y := \ · 64 unmodified lines
65 disp/dpu1/dpu_hw_lm.o \65 disp/dpu1/dpu_hw_lm.o \
66 disp/dpu1/dpu_hw_pingpong.o \66 disp/dpu1/dpu_hw_pingpong.o \
67 disp/dpu1/dpu_hw_sspp.o \67 disp/dpu1/dpu_hw_sspp.o \
68 disp/dpu1/dpu_hw_dspp.o \
68 disp/dpu1/dpu_hw_top.o \69 disp/dpu1/dpu_hw_top.o \
69 disp/dpu1/dpu_hw_util.o \70 disp/dpu1/dpu_hw_util.o \
70 disp/dpu1/dpu_hw_vbif.o \71 disp/dpu1/dpu_hw_vbif.o \
drivers/gpu/drm/msm/adreno/a2xx_gpu.c+16−0
@@ -401,6 +401,21 @@ static struct msm_gpu_state *a2xx_gpu_state_get(struct msm_gpu *gpu) · 400 unmodified lines
401 return state;401 return state;
402}402}
403 403
404static struct msm_gem_address_space *
405a2xx_create_address_space(struct msm_gpu *gpu, struct platform_device *pdev)
406{
407 struct msm_mmu *mmu = msm_gpummu_new(&pdev->dev, gpu);
408 struct msm_gem_address_space *aspace;
409
410 aspace = msm_gem_address_space_create(mmu, "gpu", SZ_16M,
411 SZ_16M + 0xfff * SZ_64K);
412
413 if (IS_ERR(aspace) && !IS_ERR(mmu))
414 mmu->funcs->destroy(mmu);
415
416 return aspace;
417}
418
404/* Register offset defines for A2XX - copy of A3XX */419/* Register offset defines for A2XX - copy of A3XX */
405static const unsigned int a2xx_register_offsets[REG_ADRENO_REGISTER_MAX] = {420static const unsigned int a2xx_register_offsets[REG_ADRENO_REGISTER_MAX] = {
406 REG_ADRENO_DEFINE(REG_ADRENO_CP_RB_BASE, REG_AXXX_CP_RB_BASE),421 REG_ADRENO_DEFINE(REG_ADRENO_CP_RB_BASE, REG_AXXX_CP_RB_BASE),
@@ -429,6 +444,7 @@ static const struct adreno_gpu_funcs funcs = { · 22 unmodified lines
429#endif444#endif
430 .gpu_state_get = a2xx_gpu_state_get,445 .gpu_state_get = a2xx_gpu_state_get,
431 .gpu_state_put = adreno_gpu_state_put,446 .gpu_state_put = adreno_gpu_state_put,
447 .create_address_space = a2xx_create_address_space,
432 },448 },
433};449};
434 450
drivers/gpu/drm/msm/adreno/a3xx_gpu.c+1−0
@@ -441,6 +441,7 @@ static const struct adreno_gpu_funcs funcs = { · 440 unmodified lines
441#endif441#endif
442 .gpu_state_get = a3xx_gpu_state_get,442 .gpu_state_get = a3xx_gpu_state_get,
443 .gpu_state_put = adreno_gpu_state_put,443 .gpu_state_put = adreno_gpu_state_put,
444 .create_address_space = adreno_iommu_create_address_space,
444 },445 },
445};446};
446 447
drivers/gpu/drm/msm/adreno/a4xx_gpu.c+68−15
@@ -66,19 +66,22 @@ static void a4xx_enable_hwcg(struct msm_gpu *gpu) · 65 unmodified lines
66 }66 }
67 }67 }
68 68
69 for (i = 0; i < 4; i++) {69 /* No CCU for A405 */
70 gpu_write(gpu, REG_A4XX_RBBM_CLOCK_CTL_MARB_CCU(i),70 if (!adreno_is_a405(adreno_gpu)) {
71 0x00000922);71 for (i = 0; i < 4; i++) {
72 }72 gpu_write(gpu, REG_A4XX_RBBM_CLOCK_CTL_MARB_CCU(i),
73 0x00000922);
74 }
73 75
74 for (i = 0; i < 4; i++) {76 for (i = 0; i < 4; i++) {
75 gpu_write(gpu, REG_A4XX_RBBM_CLOCK_HYST_RB_MARB_CCU(i),77 gpu_write(gpu, REG_A4XX_RBBM_CLOCK_HYST_RB_MARB_CCU(i),
76 0x00000000);78 0x00000000);
77 }79 }
78 80
79 for (i = 0; i < 4; i++) {81 for (i = 0; i < 4; i++) {
80 gpu_write(gpu, REG_A4XX_RBBM_CLOCK_DELAY_RB_MARB_CCU_L1(i),82 gpu_write(gpu, REG_A4XX_RBBM_CLOCK_DELAY_RB_MARB_CCU_L1(i),
81 0x00000001);83 0x00000001);
84 }
82 }85 }
83 86
84 gpu_write(gpu, REG_A4XX_RBBM_CLOCK_MODE_GPC, 0x02222222);87 gpu_write(gpu, REG_A4XX_RBBM_CLOCK_MODE_GPC, 0x02222222);
@@ -137,7 +140,9 @@ static int a4xx_hw_init(struct msm_gpu *gpu) · 52 unmodified lines
137 uint32_t *ptr, len;140 uint32_t *ptr, len;
138 int i, ret;141 int i, ret;
139 142
140 if (adreno_is_a420(adreno_gpu)) {143 if (adreno_is_a405(adreno_gpu)) {
144 gpu_write(gpu, REG_A4XX_VBIF_ROUND_ROBIN_QOS_ARB, 0x00000003);
145 } else if (adreno_is_a420(adreno_gpu)) {
141 gpu_write(gpu, REG_A4XX_VBIF_ABIT_SORT, 0x0001001F);146 gpu_write(gpu, REG_A4XX_VBIF_ABIT_SORT, 0x0001001F);
142 gpu_write(gpu, REG_A4XX_VBIF_ABIT_SORT_CONF, 0x000000A4);147 gpu_write(gpu, REG_A4XX_VBIF_ABIT_SORT_CONF, 0x000000A4);
143 gpu_write(gpu, REG_A4XX_VBIF_GATE_OFF_WRREQ_EN, 0x00000001);148 gpu_write(gpu, REG_A4XX_VBIF_GATE_OFF_WRREQ_EN, 0x00000001);
@@ -440,6 +445,52 @@ static const unsigned int a4xx_registers[] = { · 296 unmodified lines
440 ~0 /* sentinel */445 ~0 /* sentinel */
441};446};
442 447
448static const unsigned int a405_registers[] = {
449 /* RBBM */
450 0x0000, 0x0002, 0x0004, 0x0021, 0x0023, 0x0024, 0x0026, 0x0026,
451 0x0028, 0x002B, 0x002E, 0x0034, 0x0037, 0x0044, 0x0047, 0x0066,
452 0x0068, 0x0095, 0x009C, 0x0170, 0x0174, 0x01AF,
453 /* CP */
454 0x0200, 0x0233, 0x0240, 0x0250, 0x04C0, 0x04DD, 0x0500, 0x050B,
455 0x0578, 0x058F,
456 /* VSC */
457 0x0C00, 0x0C03, 0x0C08, 0x0C41, 0x0C50, 0x0C51,
458 /* GRAS */
459 0x0C80, 0x0C81, 0x0C88, 0x0C8F,
460 /* RB */
461 0x0CC0, 0x0CC0, 0x0CC4, 0x0CD2,
462 /* PC */
463 0x0D00, 0x0D0C, 0x0D10, 0x0D17, 0x0D20, 0x0D23,
464 /* VFD */
465 0x0E40, 0x0E4A,
466 /* VPC */
467 0x0E60, 0x0E61, 0x0E63, 0x0E68,
468 /* UCHE */
469 0x0E80, 0x0E84, 0x0E88, 0x0E95,
470 /* GRAS CTX 0 */
471 0x2000, 0x2004, 0x2008, 0x2067, 0x2070, 0x2078, 0x207B, 0x216E,
472 /* PC CTX 0 */
473 0x21C0, 0x21C6, 0x21D0, 0x21D0, 0x21D9, 0x21D9, 0x21E5, 0x21E7,
474 /* VFD CTX 0 */
475 0x2200, 0x2204, 0x2208, 0x22A9,
476 /* GRAS CTX 1 */
477 0x2400, 0x2404, 0x2408, 0x2467, 0x2470, 0x2478, 0x247B, 0x256E,
478 /* PC CTX 1 */
479 0x25C0, 0x25C6, 0x25D0, 0x25D0, 0x25D9, 0x25D9, 0x25E5, 0x25E7,
480 /* VFD CTX 1 */
481 0x2600, 0x2604, 0x2608, 0x26A9,
482 /* VBIF version 0x20050000*/
483 0x3000, 0x3007, 0x302C, 0x302C, 0x3030, 0x3030, 0x3034, 0x3036,
484 0x3038, 0x3038, 0x303C, 0x303D, 0x3040, 0x3040, 0x3049, 0x3049,
485 0x3058, 0x3058, 0x305B, 0x3061, 0x3064, 0x3068, 0x306C, 0x306D,
486 0x3080, 0x3088, 0x308B, 0x308C, 0x3090, 0x3094, 0x3098, 0x3098,
487 0x309C, 0x309C, 0x30C0, 0x30C0, 0x30C8, 0x30C8, 0x30D0, 0x30D0,
488 0x30D8, 0x30D8, 0x30E0, 0x30E0, 0x3100, 0x3100, 0x3108, 0x3108,
489 0x3110, 0x3110, 0x3118, 0x3118, 0x3120, 0x3120, 0x3124, 0x3125,
490 0x3129, 0x3129, 0x340C, 0x340C, 0x3410, 0x3410,
491 ~0 /* sentinel */
492};
493
443static struct msm_gpu_state *a4xx_gpu_state_get(struct msm_gpu *gpu)494static struct msm_gpu_state *a4xx_gpu_state_get(struct msm_gpu *gpu)
444{495{
445 struct msm_gpu_state *state = kzalloc(sizeof(*state), GFP_KERNEL);496 struct msm_gpu_state *state = kzalloc(sizeof(*state), GFP_KERNEL);
@@ -532,6 +583,7 @@ static const struct adreno_gpu_funcs funcs = { · 86 unmodified lines
532#endif583#endif
533 .gpu_state_get = a4xx_gpu_state_get,584 .gpu_state_get = a4xx_gpu_state_get,
534 .gpu_state_put = adreno_gpu_state_put,585 .gpu_state_put = adreno_gpu_state_put,
586 .create_address_space = adreno_iommu_create_address_space,
535 },587 },
536 .get_timestamp = a4xx_get_timestamp,588 .get_timestamp = a4xx_get_timestamp,
537};589};
@@ -563,13 +615,14 @@ struct msm_gpu *a4xx_gpu_init(struct drm_device *dev) · 25 unmodified lines
563 gpu->perfcntrs = NULL;615 gpu->perfcntrs = NULL;
564 gpu->num_perfcntrs = 0;616 gpu->num_perfcntrs = 0;
565 617
566 adreno_gpu->registers = a4xx_registers;
567 adreno_gpu->reg_offsets = a4xx_register_offsets;
568
569 ret = adreno_gpu_init(dev, pdev, adreno_gpu, &funcs, 1);618 ret = adreno_gpu_init(dev, pdev, adreno_gpu, &funcs, 1);
570 if (ret)619 if (ret)
571 goto fail;620 goto fail;
572 621
622 adreno_gpu->registers = adreno_is_a405(adreno_gpu) ? a405_registers :
623 a4xx_registers;
624 adreno_gpu->reg_offsets = a4xx_register_offsets;
625
573 /* if needed, allocate gmem: */626 /* if needed, allocate gmem: */
574 if (adreno_is_a4xx(adreno_gpu)) {627 if (adreno_is_a4xx(adreno_gpu)) {
575 ret = adreno_gpu_ocmem_init(dev->dev, adreno_gpu,628 ret = adreno_gpu_ocmem_init(dev->dev, adreno_gpu,
drivers/gpu/drm/msm/adreno/a5xx_gpu.c+7−0
@@ -1404,6 +1404,10 @@ static unsigned long a5xx_gpu_busy(struct msm_gpu *gpu) · 1403 unmodified lines
1404{1404{
1405 u64 busy_cycles, busy_time;1405 u64 busy_cycles, busy_time;
1406 1406
1407 /* Only read the gpu busy if the hardware is already active */
1408 if (pm_runtime_get_if_in_use(&gpu->pdev->dev) == 0)
1409 return 0;
1410
1407 busy_cycles = gpu_read64(gpu, REG_A5XX_RBBM_PERFCTR_RBBM_0_LO,1411 busy_cycles = gpu_read64(gpu, REG_A5XX_RBBM_PERFCTR_RBBM_0_LO,
1408 REG_A5XX_RBBM_PERFCTR_RBBM_0_HI);1412 REG_A5XX_RBBM_PERFCTR_RBBM_0_HI);
1409 1413
@@ -1412,6 +1416,8 @@ static unsigned long a5xx_gpu_busy(struct msm_gpu *gpu) · 2 unmodified lines
1412 1416
1413 gpu->devfreq.busy_cycles = busy_cycles;1417 gpu->devfreq.busy_cycles = busy_cycles;
1414 1418
1419 pm_runtime_put(&gpu->pdev->dev);
1420
1415 if (WARN_ON(busy_time > ~0LU))1421 if (WARN_ON(busy_time > ~0LU))
1416 return ~0LU;1422 return ~0LU;
1417 1423
@@ -1439,6 +1445,7 @@ static const struct adreno_gpu_funcs funcs = { · 21 unmodified lines
1439 .gpu_busy = a5xx_gpu_busy,1445 .gpu_busy = a5xx_gpu_busy,
1440 .gpu_state_get = a5xx_gpu_state_get,1446 .gpu_state_get = a5xx_gpu_state_get,
1441 .gpu_state_put = a5xx_gpu_state_put,1447 .gpu_state_put = a5xx_gpu_state_put,
1448 .create_address_space = adreno_iommu_create_address_space,
1442 },1449 },
1443 .get_timestamp = a5xx_get_timestamp,1450 .get_timestamp = a5xx_get_timestamp,
1444};1451};
drivers/gpu/drm/msm/adreno/a6xx.xml.h+14−0
@@ -1047,6 +1047,8 @@ enum a6xx_tex_type { · 1046 unmodified lines
1047 1047
1048#define REG_A6XX_CP_MISC_CNTL 0x000008401048#define REG_A6XX_CP_MISC_CNTL 0x00000840
1049 1049
1050#define REG_A6XX_CP_APRIV_CNTL 0x00000844
1051
1050#define REG_A6XX_CP_ROQ_THRESHOLDS_1 0x000008c11052#define REG_A6XX_CP_ROQ_THRESHOLDS_1 0x000008c1
1051 1053
1052#define REG_A6XX_CP_ROQ_THRESHOLDS_2 0x000008c21054#define REG_A6XX_CP_ROQ_THRESHOLDS_2 0x000008c2
@@ -1764,6 +1766,8 @@ static inline uint32_t A6XX_CP_PROTECT_REG_MASK_LEN(uint32_t val) · 711 unmodified lines
1764 1766
1765#define REG_A6XX_RBBM_VBIF_CLIENT_QOS_CNTL 0x000000101767#define REG_A6XX_RBBM_VBIF_CLIENT_QOS_CNTL 0x00000010
1766 1768
1769#define REG_A6XX_RBBM_GBIF_CLIENT_QOS_CNTL 0x00000011
1770
1767#define REG_A6XX_RBBM_INTERFACE_HANG_INT_CNTL 0x0000001f1771#define REG_A6XX_RBBM_INTERFACE_HANG_INT_CNTL 0x0000001f
1768 1772
1769#define REG_A6XX_RBBM_INT_CLEAR_CMD 0x000000371773#define REG_A6XX_RBBM_INT_CLEAR_CMD 0x00000037
@@ -2418,6 +2422,16 @@ static inline uint32_t A6XX_UCHE_CLIENT_PF_PERFSEL(uint32_t val) · 648 unmodified lines
2418 2422
2419#define REG_A6XX_TPL1_NC_MODE_CNTL 0x0000b6042423#define REG_A6XX_TPL1_NC_MODE_CNTL 0x0000b604
2420 2424
2425#define REG_A6XX_TPL1_BICUBIC_WEIGHTS_TABLE_0 0x0000b608
2426
2427#define REG_A6XX_TPL1_BICUBIC_WEIGHTS_TABLE_1 0x0000b609
2428
2429#define REG_A6XX_TPL1_BICUBIC_WEIGHTS_TABLE_2 0x0000b60a
2430
2431#define REG_A6XX_TPL1_BICUBIC_WEIGHTS_TABLE_3 0x0000b60b
2432
2433#define REG_A6XX_TPL1_BICUBIC_WEIGHTS_TABLE_4 0x0000b60c
2434
2421#define REG_A6XX_TPL1_PERFCTR_TP_SEL_0 0x0000b6102435#define REG_A6XX_TPL1_PERFCTR_TP_SEL_0 0x0000b610
2422 2436
2423#define REG_A6XX_TPL1_PERFCTR_TP_SEL_1 0x0000b6112437#define REG_A6XX_TPL1_PERFCTR_TP_SEL_1 0x0000b611
drivers/gpu/drm/msm/adreno/a6xx_gmu.c+321−97
@@ -2,14 +2,16 @@ · 1 unmodified line
2/* Copyright (c) 2017-2019 The Linux Foundation. All rights reserved. */2/* Copyright (c) 2017-2019 The Linux Foundation. All rights reserved. */
3 3
4#include <linux/clk.h>4#include <linux/clk.h>
5#include <linux/dma-mapping.h>
6#include <linux/interconnect.h>5#include <linux/interconnect.h>
7#include <linux/pm_domain.h>6#include <linux/pm_domain.h>
8#include <linux/pm_opp.h>7#include <linux/pm_opp.h>
9#include <soc/qcom/cmd-db.h>8#include <soc/qcom/cmd-db.h>
9#include <drm/drm_gem.h>
10 10
11#include "a6xx_gpu.h"11#include "a6xx_gpu.h"
12#include "a6xx_gmu.xml.h"12#include "a6xx_gmu.xml.h"
13#include "msm_gem.h"
14#include "msm_mmu.h"
13 15
14static void a6xx_gmu_fault(struct a6xx_gmu *gmu)16static void a6xx_gmu_fault(struct a6xx_gmu *gmu)
15{17{
@@ -127,8 +129,6 @@ static void __a6xx_gmu_set_freq(struct a6xx_gmu *gmu, int index) · 111 unmodified lines
127 if (ret)129 if (ret)
128 dev_err(gmu->dev, "GMU set GPU frequency error: %d\n", ret);130 dev_err(gmu->dev, "GMU set GPU frequency error: %d\n", ret);
129 131
130 gmu->freq = gmu->gpu_freqs[index];
131
132 /*132 /*
133 * Eventually we will want to scale the path vote with the frequency but133 * Eventually we will want to scale the path vote with the frequency but
134 * for now leave it at max so that the performance is nominal.134 * for now leave it at max so that the performance is nominal.
@@ -151,8 +151,21 @@ void a6xx_gmu_set_freq(struct msm_gpu *gpu, unsigned long freq) · 16 unmodified lines
151 break;151 break;
152 152
153 gmu->current_perf_index = perf_index;153 gmu->current_perf_index = perf_index;
154 gmu->freq = gmu->gpu_freqs[perf_index];
155
156 /*
157 * This can get called from devfreq while the hardware is idle. Don't
158 * bring up the power if it isn't already active
159 */
160 if (pm_runtime_get_if_in_use(gmu->dev) == 0)
161 return;
154 162
155 __a6xx_gmu_set_freq(gmu, perf_index);163 if (gmu->legacy)
164 __a6xx_gmu_set_freq(gmu, perf_index);
165 else
166 a6xx_hfi_set_freq(gmu, perf_index);
167
168 pm_runtime_put(gmu->dev);
156}169}
157 170
158unsigned long a6xx_gmu_get_freq(struct msm_gpu *gpu)171unsigned long a6xx_gmu_get_freq(struct msm_gpu *gpu)
@@ -196,6 +209,12 @@ static int a6xx_gmu_start(struct a6xx_gmu *gmu) · 37 unmodified lines
196 u32 val;209 u32 val;
197 210
198 gmu_write(gmu, REG_A6XX_GMU_CM3_SYSRESET, 1);211 gmu_write(gmu, REG_A6XX_GMU_CM3_SYSRESET, 1);
212
213 /* Set the log wptr index
214 * note: downstream saves the value in poweroff and restores it here
215 */
216 gmu_write(gmu, REG_A6XX_GPU_GMU_CX_GMU_PWR_COL_CP_RESP, 0);
217
199 gmu_write(gmu, REG_A6XX_GMU_CM3_SYSRESET, 0);218 gmu_write(gmu, REG_A6XX_GMU_CM3_SYSRESET, 0);
200 219
201 ret = gmu_poll_timeout(gmu, REG_A6XX_GMU_CM3_FW_INIT_RESULT, val,220 ret = gmu_poll_timeout(gmu, REG_A6XX_GMU_CM3_FW_INIT_RESULT, val,
@@ -232,8 +251,13 @@ int a6xx_gmu_set_oob(struct a6xx_gmu *gmu, enum a6xx_gmu_oob_state state) · 30 unmodified lines
232 251
233 switch (state) {252 switch (state) {
234 case GMU_OOB_GPU_SET:253 case GMU_OOB_GPU_SET:
235 request = GMU_OOB_GPU_SET_REQUEST;254 if (gmu->legacy) {
236 ack = GMU_OOB_GPU_SET_ACK;255 request = GMU_OOB_GPU_SET_REQUEST;
256 ack = GMU_OOB_GPU_SET_ACK;
257 } else {
258 request = GMU_OOB_GPU_SET_REQUEST_NEW;
259 ack = GMU_OOB_GPU_SET_ACK_NEW;
260 }
237 name = "GPU_SET";261 name = "GPU_SET";
238 break;262 break;
239 case GMU_OOB_BOOT_SLUMBER:263 case GMU_OOB_BOOT_SLUMBER:
@@ -272,6 +296,13 @@ int a6xx_gmu_set_oob(struct a6xx_gmu *gmu, enum a6xx_gmu_oob_state state) · 32 unmodified lines
272/* Clear a pending OOB state in the GMU */296/* Clear a pending OOB state in the GMU */
273void a6xx_gmu_clear_oob(struct a6xx_gmu *gmu, enum a6xx_gmu_oob_state state)297void a6xx_gmu_clear_oob(struct a6xx_gmu *gmu, enum a6xx_gmu_oob_state state)
274{298{
299 if (!gmu->legacy) {
300 WARN_ON(state != GMU_OOB_GPU_SET);
301 gmu_write(gmu, REG_A6XX_GMU_HOST2GMU_INTR_SET,
302 1 << GMU_OOB_GPU_SET_CLEAR_NEW);
303 return;
304 }
305
275 switch (state) {306 switch (state) {
276 case GMU_OOB_GPU_SET:307 case GMU_OOB_GPU_SET:
277 gmu_write(gmu, REG_A6XX_GMU_HOST2GMU_INTR_SET,308 gmu_write(gmu, REG_A6XX_GMU_HOST2GMU_INTR_SET,
@@ -294,6 +325,9 @@ static int a6xx_sptprac_enable(struct a6xx_gmu *gmu) · 16 unmodified lines
294 int ret;325 int ret;
295 u32 val;326 u32 val;
296 327
328 if (!gmu->legacy)
329 return 0;
330
297 gmu_write(gmu, REG_A6XX_GMU_GX_SPTPRAC_POWER_CONTROL, 0x778000);331 gmu_write(gmu, REG_A6XX_GMU_GX_SPTPRAC_POWER_CONTROL, 0x778000);
298 332
299 ret = gmu_poll_timeout(gmu, REG_A6XX_GMU_SPTPRAC_PWR_CLK_STATUS, val,333 ret = gmu_poll_timeout(gmu, REG_A6XX_GMU_SPTPRAC_PWR_CLK_STATUS, val,
@@ -313,6 +347,9 @@ static void a6xx_sptprac_disable(struct a6xx_gmu *gmu) · 13 unmodified lines
313 u32 val;347 u32 val;
314 int ret;348 int ret;
315 349
350 if (!gmu->legacy)
351 return;
352
316 /* Make sure retention is on */353 /* Make sure retention is on */
317 gmu_rmw(gmu, REG_A6XX_GPU_CC_GX_GDSCR, 0, (1 << 11));354 gmu_rmw(gmu, REG_A6XX_GPU_CC_GX_GDSCR, 0, (1 << 11));
318 355
@@ -356,6 +393,11 @@ static int a6xx_gmu_notify_slumber(struct a6xx_gmu *gmu) · 37 unmodified lines
356 if (gmu->idle_level < GMU_IDLE_STATE_SPTP)393 if (gmu->idle_level < GMU_IDLE_STATE_SPTP)
357 a6xx_sptprac_disable(gmu);394 a6xx_sptprac_disable(gmu);
358 395
396 if (!gmu->legacy) {
397 ret = a6xx_hfi_send_prep_slumber(gmu);
398 goto out;
399 }
400
359 /* Tell the GMU to get ready to slumber */401 /* Tell the GMU to get ready to slumber */
360 gmu_write(gmu, REG_A6XX_GMU_BOOT_SLUMBER_OPTION, 1);402 gmu_write(gmu, REG_A6XX_GMU_BOOT_SLUMBER_OPTION, 1);
361 403
@@ -371,6 +413,7 @@ static int a6xx_gmu_notify_slumber(struct a6xx_gmu *gmu) · 9 unmodified lines
371 }413 }
372 }414 }
373 415
416out:
374 /* Put fence into allow mode */417 /* Put fence into allow mode */
375 gmu_write(gmu, REG_A6XX_GMU_AO_AHB_FENCE_CTRL, 0);418 gmu_write(gmu, REG_A6XX_GMU_AO_AHB_FENCE_CTRL, 0);
376 return ret;419 return ret;
@@ -392,7 +435,7 @@ static int a6xx_rpmh_start(struct a6xx_gmu *gmu) · 15 unmodified lines
392 return ret;435 return ret;
393 }436 }
394 437
395 ret = gmu_poll_timeout(gmu, REG_A6XX_RSCC_SEQ_BUSY_DRV0, val,438 ret = gmu_poll_timeout_rscc(gmu, REG_A6XX_RSCC_SEQ_BUSY_DRV0, val,
396 !val, 100, 10000);439 !val, 100, 10000);
397 440
398 if (ret) {441 if (ret) {
@@ -418,7 +461,7 @@ static void a6xx_rpmh_stop(struct a6xx_gmu *gmu) · 19 unmodified lines
418 461
419 gmu_write(gmu, REG_A6XX_GMU_RSCC_CONTROL_REQ, 1);462 gmu_write(gmu, REG_A6XX_GMU_RSCC_CONTROL_REQ, 1);
420 463
421 ret = gmu_poll_timeout(gmu, REG_A6XX_GPU_RSCC_RSC_STATUS0_DRV0,464 ret = gmu_poll_timeout_rscc(gmu, REG_A6XX_GPU_RSCC_RSC_STATUS0_DRV0,
422 val, val & (1 << 16), 100, 10000);465 val, val & (1 << 16), 100, 10000);
423 if (ret)466 if (ret)
424 DRM_DEV_ERROR(gmu->dev, "Unable to power off the GPU RSC\n");467 DRM_DEV_ERROR(gmu->dev, "Unable to power off the GPU RSC\n");
@@ -441,32 +484,48 @@ static void a6xx_gmu_rpmh_init(struct a6xx_gmu *gmu) · 16 unmodified lines
441 struct platform_device *pdev = to_platform_device(gmu->dev);484 struct platform_device *pdev = to_platform_device(gmu->dev);
442 void __iomem *pdcptr = a6xx_gmu_get_mmio(pdev, "gmu_pdc");485 void __iomem *pdcptr = a6xx_gmu_get_mmio(pdev, "gmu_pdc");
443 void __iomem *seqptr = a6xx_gmu_get_mmio(pdev, "gmu_pdc_seq");486 void __iomem *seqptr = a6xx_gmu_get_mmio(pdev, "gmu_pdc_seq");
487 uint32_t pdc_address_offset;
444 488
445 if (!pdcptr || !seqptr)489 if (!pdcptr || !seqptr)
446 goto err;490 goto err;
447 491
492 if (adreno_is_a618(adreno_gpu) || adreno_is_a640(adreno_gpu))
493 pdc_address_offset = 0x30090;
494 else if (adreno_is_a650(adreno_gpu))
495 pdc_address_offset = 0x300a0;
496 else
497 pdc_address_offset = 0x30080;
498
448 /* Disable SDE clock gating */499 /* Disable SDE clock gating */
449 gmu_write(gmu, REG_A6XX_GPU_RSCC_RSC_STATUS0_DRV0, BIT(24));500 gmu_write_rscc(gmu, REG_A6XX_GPU_RSCC_RSC_STATUS0_DRV0, BIT(24));
450 501
451 /* Setup RSC PDC handshake for sleep and wakeup */502 /* Setup RSC PDC handshake for sleep and wakeup */
452 gmu_write(gmu, REG_A6XX_RSCC_PDC_SLAVE_ID_DRV0, 1);503 gmu_write_rscc(gmu, REG_A6XX_RSCC_PDC_SLAVE_ID_DRV0, 1);
453 gmu_write(gmu, REG_A6XX_RSCC_HIDDEN_TCS_CMD0_DATA, 0);504 gmu_write_rscc(gmu, REG_A6XX_RSCC_HIDDEN_TCS_CMD0_DATA, 0);
454 gmu_write(gmu, REG_A6XX_RSCC_HIDDEN_TCS_CMD0_ADDR, 0);505 gmu_write_rscc(gmu, REG_A6XX_RSCC_HIDDEN_TCS_CMD0_ADDR, 0);
455 gmu_write(gmu, REG_A6XX_RSCC_HIDDEN_TCS_CMD0_DATA + 2, 0);506 gmu_write_rscc(gmu, REG_A6XX_RSCC_HIDDEN_TCS_CMD0_DATA + 2, 0);
456 gmu_write(gmu, REG_A6XX_RSCC_HIDDEN_TCS_CMD0_ADDR + 2, 0);507 gmu_write_rscc(gmu, REG_A6XX_RSCC_HIDDEN_TCS_CMD0_ADDR + 2, 0);
457 gmu_write(gmu, REG_A6XX_RSCC_HIDDEN_TCS_CMD0_DATA + 4, 0x80000000);508 gmu_write_rscc(gmu, REG_A6XX_RSCC_HIDDEN_TCS_CMD0_DATA + 4, 0x80000000);
458 gmu_write(gmu, REG_A6XX_RSCC_HIDDEN_TCS_CMD0_ADDR + 4, 0);509 gmu_write_rscc(gmu, REG_A6XX_RSCC_HIDDEN_TCS_CMD0_ADDR + 4, 0);
459 gmu_write(gmu, REG_A6XX_RSCC_OVERRIDE_START_ADDR, 0);510 gmu_write_rscc(gmu, REG_A6XX_RSCC_OVERRIDE_START_ADDR, 0);
460 gmu_write(gmu, REG_A6XX_RSCC_PDC_SEQ_START_ADDR, 0x4520);511 gmu_write_rscc(gmu, REG_A6XX_RSCC_PDC_SEQ_START_ADDR, 0x4520);
461 gmu_write(gmu, REG_A6XX_RSCC_PDC_MATCH_VALUE_LO, 0x4510);512 gmu_write_rscc(gmu, REG_A6XX_RSCC_PDC_MATCH_VALUE_LO, 0x4510);
462 gmu_write(gmu, REG_A6XX_RSCC_PDC_MATCH_VALUE_HI, 0x4514);513 gmu_write_rscc(gmu, REG_A6XX_RSCC_PDC_MATCH_VALUE_HI, 0x4514);
463 514
464 /* Load RSC sequencer uCode for sleep and wakeup */515 /* Load RSC sequencer uCode for sleep and wakeup */
465 gmu_write(gmu, REG_A6XX_RSCC_SEQ_MEM_0_DRV0, 0xa7a506a0);516 if (adreno_is_a650(adreno_gpu)) {
466 gmu_write(gmu, REG_A6XX_RSCC_SEQ_MEM_0_DRV0 + 1, 0xa1e6a6e7);517 gmu_write_rscc(gmu, REG_A6XX_RSCC_SEQ_MEM_0_DRV0, 0xeaaae5a0);
467 gmu_write(gmu, REG_A6XX_RSCC_SEQ_MEM_0_DRV0 + 2, 0xa2e081e1);518 gmu_write_rscc(gmu, REG_A6XX_RSCC_SEQ_MEM_0_DRV0 + 1, 0xe1a1ebab);
468 gmu_write(gmu, REG_A6XX_RSCC_SEQ_MEM_0_DRV0 + 3, 0xe9a982e2);519 gmu_write_rscc(gmu, REG_A6XX_RSCC_SEQ_MEM_0_DRV0 + 2, 0xa2e0a581);
469 gmu_write(gmu, REG_A6XX_RSCC_SEQ_MEM_0_DRV0 + 4, 0x0020e8a8);520 gmu_write_rscc(gmu, REG_A6XX_RSCC_SEQ_MEM_0_DRV0 + 3, 0xecac82e2);
521 gmu_write_rscc(gmu, REG_A6XX_RSCC_SEQ_MEM_0_DRV0 + 4, 0x0020edad);
522 } else {
523 gmu_write_rscc(gmu, REG_A6XX_RSCC_SEQ_MEM_0_DRV0, 0xa7a506a0);
524 gmu_write_rscc(gmu, REG_A6XX_RSCC_SEQ_MEM_0_DRV0 + 1, 0xa1e6a6e7);
525 gmu_write_rscc(gmu, REG_A6XX_RSCC_SEQ_MEM_0_DRV0 + 2, 0xa2e081e1);
526 gmu_write_rscc(gmu, REG_A6XX_RSCC_SEQ_MEM_0_DRV0 + 3, 0xe9a982e2);
527 gmu_write_rscc(gmu, REG_A6XX_RSCC_SEQ_MEM_0_DRV0 + 4, 0x0020e8a8);
528 }
470 529
471 /* Load PDC sequencer uCode for power up and power down sequence */530 /* Load PDC sequencer uCode for power up and power down sequence */
472 pdc_write(seqptr, REG_A6XX_PDC_GPU_SEQ_MEM_0, 0xfebea1e1);531 pdc_write(seqptr, REG_A6XX_PDC_GPU_SEQ_MEM_0, 0xfebea1e1);
@@ -487,10 +546,7 @@ static void a6xx_gmu_rpmh_init(struct a6xx_gmu *gmu) · 14 unmodified lines
487 pdc_write(pdcptr, REG_A6XX_PDC_GPU_TCS1_CMD0_DATA + 4, 0x0);546 pdc_write(pdcptr, REG_A6XX_PDC_GPU_TCS1_CMD0_DATA + 4, 0x0);
488 547
489 pdc_write(pdcptr, REG_A6XX_PDC_GPU_TCS1_CMD0_MSGID + 8, 0x10108);548 pdc_write(pdcptr, REG_A6XX_PDC_GPU_TCS1_CMD0_MSGID + 8, 0x10108);
490 if (adreno_is_a618(adreno_gpu))549 pdc_write(pdcptr, REG_A6XX_PDC_GPU_TCS1_CMD0_ADDR + 8, pdc_address_offset);
491 pdc_write(pdcptr, REG_A6XX_PDC_GPU_TCS1_CMD0_ADDR + 8, 0x30090);
492 else
493 pdc_write(pdcptr, REG_A6XX_PDC_GPU_TCS1_CMD0_ADDR + 8, 0x30080);
494 pdc_write(pdcptr, REG_A6XX_PDC_GPU_TCS1_CMD0_DATA + 8, 0x0);550 pdc_write(pdcptr, REG_A6XX_PDC_GPU_TCS1_CMD0_DATA + 8, 0x0);
495 551
496 pdc_write(pdcptr, REG_A6XX_PDC_GPU_TCS3_CMD_ENABLE_BANK, 7);552 pdc_write(pdcptr, REG_A6XX_PDC_GPU_TCS3_CMD_ENABLE_BANK, 7);
@@ -502,17 +558,12 @@ static void a6xx_gmu_rpmh_init(struct a6xx_gmu *gmu) · 5 unmodified lines
502 558
503 pdc_write(pdcptr, REG_A6XX_PDC_GPU_TCS3_CMD0_MSGID + 4, 0x10108);559 pdc_write(pdcptr, REG_A6XX_PDC_GPU_TCS3_CMD0_MSGID + 4, 0x10108);
504 pdc_write(pdcptr, REG_A6XX_PDC_GPU_TCS3_CMD0_ADDR + 4, 0x30000);560 pdc_write(pdcptr, REG_A6XX_PDC_GPU_TCS3_CMD0_ADDR + 4, 0x30000);
505 if (adreno_is_a618(adreno_gpu))561 if (adreno_is_a618(adreno_gpu) || adreno_is_a650(adreno_gpu))
506 pdc_write(pdcptr, REG_A6XX_PDC_GPU_TCS3_CMD0_DATA + 4, 0x2);562 pdc_write(pdcptr, REG_A6XX_PDC_GPU_TCS3_CMD0_DATA + 4, 0x2);
507 else563 else
508 pdc_write(pdcptr, REG_A6XX_PDC_GPU_TCS3_CMD0_DATA + 4, 0x3);564 pdc_write(pdcptr, REG_A6XX_PDC_GPU_TCS3_CMD0_DATA + 4, 0x3);
509
510
511 pdc_write(pdcptr, REG_A6XX_PDC_GPU_TCS3_CMD0_MSGID + 8, 0x10108);565 pdc_write(pdcptr, REG_A6XX_PDC_GPU_TCS3_CMD0_MSGID + 8, 0x10108);
512 if (adreno_is_a618(adreno_gpu))566 pdc_write(pdcptr, REG_A6XX_PDC_GPU_TCS3_CMD0_ADDR + 8, pdc_address_offset);
513 pdc_write(pdcptr, REG_A6XX_PDC_GPU_TCS3_CMD0_ADDR + 8, 0x30090);
514 else
515 pdc_write(pdcptr, REG_A6XX_PDC_GPU_TCS3_CMD0_ADDR + 8, 0x30080);
516 pdc_write(pdcptr, REG_A6XX_PDC_GPU_TCS3_CMD0_DATA + 8, 0x3);567 pdc_write(pdcptr, REG_A6XX_PDC_GPU_TCS3_CMD0_DATA + 8, 0x3);
517 568
518 /* Setup GPU PDC */569 /* Setup GPU PDC */
@@ -542,6 +593,8 @@ static void a6xx_gmu_power_config(struct a6xx_gmu *gmu) · 23 unmodified lines
542{593{
543 /* Disable GMU WB/RB buffer */594 /* Disable GMU WB/RB buffer */
544 gmu_write(gmu, REG_A6XX_GMU_SYS_BUS_CONFIG, 0x1);595 gmu_write(gmu, REG_A6XX_GMU_SYS_BUS_CONFIG, 0x1);
596 gmu_write(gmu, REG_A6XX_GMU_ICACHE_CONFIG, 0x1);
597 gmu_write(gmu, REG_A6XX_GMU_DCACHE_CONFIG, 0x1);
545 598
546 gmu_write(gmu, REG_A6XX_GMU_PWR_COL_INTER_FRAME_CTRL, 0x9c40400);599 gmu_write(gmu, REG_A6XX_GMU_PWR_COL_INTER_FRAME_CTRL, 0x9c40400);
547 600
@@ -571,14 +624,95 @@ static void a6xx_gmu_power_config(struct a6xx_gmu *gmu) · 23 unmodified lines
571 A6XX_GMU_RPMH_CTRL_GFX_VOTE_ENABLE);624 A6XX_GMU_RPMH_CTRL_GFX_VOTE_ENABLE);
572}625}
573 626
627struct block_header {
628 u32 addr;
629 u32 size;
630 u32 type;
631 u32 value;
632 u32 data[];
633};
634
635/* this should be a general kernel helper */
636static int in_range(u32 addr, u32 start, u32 size)
637{
638 return addr >= start && addr < start + size;
639}
640
641static bool fw_block_mem(struct a6xx_gmu_bo *bo, const struct block_header *blk)
642{
643 if (!in_range(blk->addr, bo->iova, bo->size))
644 return false;
645
646 memcpy(bo->virt + blk->addr - bo->iova, blk->data, blk->size);
647 return true;
648}
649
650static int a6xx_gmu_fw_load(struct a6xx_gmu *gmu)
651{
652 struct a6xx_gpu *a6xx_gpu = container_of(gmu, struct a6xx_gpu, gmu);
653 struct adreno_gpu *adreno_gpu = &a6xx_gpu->base;
654 const struct firmware *fw_image = adreno_gpu->fw[ADRENO_FW_GMU];
655 const struct block_header *blk;
656 u32 reg_offset;
657
658 u32 itcm_base = 0x00000000;
659 u32 dtcm_base = 0x00040000;
660
661 if (adreno_is_a650(adreno_gpu))
662 dtcm_base = 0x10004000;
663
664 if (gmu->legacy) {
665 /* Sanity check the size of the firmware that was loaded */
666 if (fw_image->size > 0x8000) {
667 DRM_DEV_ERROR(gmu->dev,
668 "GMU firmware is bigger than the available region\n");
669 return -EINVAL;
670 }
671
672 gmu_write_bulk(gmu, REG_A6XX_GMU_CM3_ITCM_START,
673 (u32*) fw_image->data, fw_image->size);
674 return 0;
675 }
676
677
678 for (blk = (const struct block_header *) fw_image->data;
679 (const u8*) blk < fw_image->data + fw_image->size;
680 blk = (const struct block_header *) &blk->data[blk->size >> 2]) {
681 if (blk->size == 0)
682 continue;
683
684 if (in_range(blk->addr, itcm_base, SZ_16K)) {
685 reg_offset = (blk->addr - itcm_base) >> 2;
686 gmu_write_bulk(gmu,
687 REG_A6XX_GMU_CM3_ITCM_START + reg_offset,
688 blk->data, blk->size);
689 } else if (in_range(blk->addr, dtcm_base, SZ_16K)) {
690 reg_offset = (blk->addr - dtcm_base) >> 2;
691 gmu_write_bulk(gmu,
692 REG_A6XX_GMU_CM3_DTCM_START + reg_offset,
693 blk->data, blk->size);
694 } else if (!fw_block_mem(&gmu->icache, blk) &&
695 !fw_block_mem(&gmu->dcache, blk) &&
696 !fw_block_mem(&gmu->dummy, blk)) {
697 DRM_DEV_ERROR(gmu->dev,
698 "failed to match fw block (addr=%.8x size=%d data[0]=%.8x)\n",
699 blk->addr, blk->size, blk->data[0]);
700 }
701 }
702
703 return 0;
704}
705
574static int a6xx_gmu_fw_start(struct a6xx_gmu *gmu, unsigned int state)706static int a6xx_gmu_fw_start(struct a6xx_gmu *gmu, unsigned int state)
575{707{
576 static bool rpmh_init;708 static bool rpmh_init;
577 struct a6xx_gpu *a6xx_gpu = container_of(gmu, struct a6xx_gpu, gmu);709 struct a6xx_gpu *a6xx_gpu = container_of(gmu, struct a6xx_gpu, gmu);
578 struct adreno_gpu *adreno_gpu = &a6xx_gpu->base;710 struct adreno_gpu *adreno_gpu = &a6xx_gpu->base;
579 int i, ret;711 int ret;
580 u32 chipid;712 u32 chipid;
581 u32 *image;713
714 if (adreno_is_a650(adreno_gpu))
715 gmu_write(gmu, REG_A6XX_GPU_GMU_CX_GMU_CX_FAL_INTF, 1);
582 716
583 if (state == GMU_WARM_BOOT) {717 if (state == GMU_WARM_BOOT) {
584 ret = a6xx_rpmh_start(gmu);718 ret = a6xx_rpmh_start(gmu);
@@ -589,13 +723,6 @@ static int a6xx_gmu_fw_start(struct a6xx_gmu *gmu, unsigned int state) · 4 unmodified lines
589 "GMU firmware is not loaded\n"))723 "GMU firmware is not loaded\n"))
590 return -ENOENT;724 return -ENOENT;
591 725
592 /* Sanity check the size of the firmware that was loaded */
593 if (adreno_gpu->fw[ADRENO_FW_GMU]->size > 0x8000) {
594 DRM_DEV_ERROR(gmu->dev,
595 "GMU firmware is bigger than the available region\n");
596 return -EINVAL;
597 }
598
599 /* Turn on register retention */726 /* Turn on register retention */
600 gmu_write(gmu, REG_A6XX_GMU_GENERAL_7, 1);727 gmu_write(gmu, REG_A6XX_GMU_GENERAL_7, 1);
601 728
@@ -609,18 +736,16 @@ static int a6xx_gmu_fw_start(struct a6xx_gmu *gmu, unsigned int state) · 7 unmodified lines
609 return ret;736 return ret;
610 }737 }
611 738
612 image = (u32 *) adreno_gpu->fw[ADRENO_FW_GMU]->data;739 ret = a6xx_gmu_fw_load(gmu);
613 740 if (ret)
614 for (i = 0; i < adreno_gpu->fw[ADRENO_FW_GMU]->size >> 2; i++)741 return ret;
615 gmu_write(gmu, REG_A6XX_GMU_CM3_ITCM_START + i,
616 image[i]);
617 }742 }
618 743
619 gmu_write(gmu, REG_A6XX_GMU_CM3_FW_INIT_RESULT, 0);744 gmu_write(gmu, REG_A6XX_GMU_CM3_FW_INIT_RESULT, 0);
620 gmu_write(gmu, REG_A6XX_GMU_CM3_BOOT_CONFIG, 0x02);745 gmu_write(gmu, REG_A6XX_GMU_CM3_BOOT_CONFIG, 0x02);
621 746
622 /* Write the iova of the HFI table */747 /* Write the iova of the HFI table */
623 gmu_write(gmu, REG_A6XX_GMU_HFI_QTBL_ADDR, gmu->hfi->iova);748 gmu_write(gmu, REG_A6XX_GMU_HFI_QTBL_ADDR, gmu->hfi.iova);
624 gmu_write(gmu, REG_A6XX_GMU_HFI_QTBL_INFO, 1);749 gmu_write(gmu, REG_A6XX_GMU_HFI_QTBL_INFO, 1);
625 750
626 gmu_write(gmu, REG_A6XX_GMU_AHB_FENCE_RANGE_0,751 gmu_write(gmu, REG_A6XX_GMU_AHB_FENCE_RANGE_0,
@@ -633,6 +758,9 @@ static int a6xx_gmu_fw_start(struct a6xx_gmu *gmu, unsigned int state) · 6 unmodified lines
633 758
634 gmu_write(gmu, REG_A6XX_GMU_HFI_SFR_ADDR, chipid);759 gmu_write(gmu, REG_A6XX_GMU_HFI_SFR_ADDR, chipid);
635 760
761 gmu_write(gmu, REG_A6XX_GPU_GMU_CX_GMU_PWR_COL_CP_MSG,
762 gmu->log.iova | (gmu->log.size / SZ_4K - 1));
763
636 /* Set up the lowest idle level on the GMU */764 /* Set up the lowest idle level on the GMU */
637 a6xx_gmu_power_config(gmu);765 a6xx_gmu_power_config(gmu);
638 766
@@ -640,9 +768,11 @@ static int a6xx_gmu_fw_start(struct a6xx_gmu *gmu, unsigned int state) · 1 unmodified line
640 if (ret)768 if (ret)
641 return ret;769 return ret;
642 770
643 ret = a6xx_gmu_gfx_rail_on(gmu);771 if (gmu->legacy) {
644 if (ret)772 ret = a6xx_gmu_gfx_rail_on(gmu);
645 return ret;773 if (ret)
774 return ret;
775 }
646 776
647 /* Enable SPTP_PC if the CPU is responsible for it */777 /* Enable SPTP_PC if the CPU is responsible for it */
648 if (gmu->idle_level < GMU_IDLE_STATE_SPTP) {778 if (gmu->idle_level < GMU_IDLE_STATE_SPTP) {
@@ -683,13 +813,13 @@ static void a6xx_gmu_rpmh_off(struct a6xx_gmu *gmu) · 34 unmodified lines
683 u32 val;813 u32 val;
684 814
685 /* Make sure there are no outstanding RPMh votes */815 /* Make sure there are no outstanding RPMh votes */
686 gmu_poll_timeout(gmu, REG_A6XX_RSCC_TCS0_DRV0_STATUS, val,816 gmu_poll_timeout_rscc(gmu, REG_A6XX_RSCC_TCS0_DRV0_STATUS, val,
687 (val & 1), 100, 10000);817 (val & 1), 100, 10000);
688 gmu_poll_timeout(gmu, REG_A6XX_RSCC_TCS1_DRV0_STATUS, val,818 gmu_poll_timeout_rscc(gmu, REG_A6XX_RSCC_TCS1_DRV0_STATUS, val,
689 (val & 1), 100, 10000);819 (val & 1), 100, 10000);
690 gmu_poll_timeout(gmu, REG_A6XX_RSCC_TCS2_DRV0_STATUS, val,820 gmu_poll_timeout_rscc(gmu, REG_A6XX_RSCC_TCS2_DRV0_STATUS, val,
691 (val & 1), 100, 10000);821 (val & 1), 100, 10000);
692 gmu_poll_timeout(gmu, REG_A6XX_RSCC_TCS3_DRV0_STATUS, val,822 gmu_poll_timeout_rscc(gmu, REG_A6XX_RSCC_TCS3_DRV0_STATUS, val,
693 (val & 1), 100, 1000);823 (val & 1), 100, 1000);
694}824}
695 825
@@ -744,6 +874,13 @@ int a6xx_gmu_resume(struct a6xx_gpu *a6xx_gpu) · 48 unmodified lines
744 status = gmu_read(gmu, REG_A6XX_GMU_GENERAL_7) == 1 ?874 status = gmu_read(gmu, REG_A6XX_GMU_GENERAL_7) == 1 ?
745 GMU_WARM_BOOT : GMU_COLD_BOOT;875 GMU_WARM_BOOT : GMU_COLD_BOOT;
746 876
877 /*
878 * Warm boot path does not work on newer GPUs
879 * Presumably this is because icache/dcache regions must be restored
880 */
881 if (!gmu->legacy)
882 status = GMU_COLD_BOOT;
883
747 ret = a6xx_gmu_fw_start(gmu, status);884 ret = a6xx_gmu_fw_start(gmu, status);
748 if (ret)885 if (ret)
749 goto out;886 goto out;
@@ -761,7 +898,10 @@ int a6xx_gmu_resume(struct a6xx_gpu *a6xx_gpu) · 11 unmodified lines
761 enable_irq(gmu->hfi_irq);898 enable_irq(gmu->hfi_irq);
762 899
763 /* Set the GPU to the current freq */900 /* Set the GPU to the current freq */
764 __a6xx_gmu_set_freq(gmu, gmu->current_perf_index);901 if (gmu->legacy)
902 __a6xx_gmu_set_freq(gmu, gmu->current_perf_index);
903 else
904 a6xx_hfi_set_freq(gmu, gmu->current_perf_index);
765 905
766 /*906 /*
767 * "enable" the GX power domain which won't actually do anything but it907 * "enable" the GX power domain which won't actually do anything but it
@@ -919,34 +1059,75 @@ int a6xx_gmu_stop(struct a6xx_gpu *a6xx_gpu) · 151 unmodified lines
919 return 0;1059 return 0;
920}1060}
921 1061
922static void a6xx_gmu_memory_free(struct a6xx_gmu *gmu, struct a6xx_gmu_bo *bo)1062static void a6xx_gmu_memory_free(struct a6xx_gmu *gmu)
923{1063{
924 if (IS_ERR_OR_NULL(bo))1064 msm_gem_kernel_put(gmu->hfi.obj, gmu->aspace, false);
925 return;1065 msm_gem_kernel_put(gmu->debug.obj, gmu->aspace, false);
926 1066 msm_gem_kernel_put(gmu->icache.obj, gmu->aspace, false);
927 dma_free_wc(gmu->dev, bo->size, bo->virt, bo->iova);1067 msm_gem_kernel_put(gmu->dcache.obj, gmu->aspace, false);
928 kfree(bo);1068 msm_gem_kernel_put(gmu->dummy.obj, gmu->aspace, false);
1069 msm_gem_kernel_put(gmu->log.obj, gmu->aspace, false);
1070
1071 gmu->aspace->mmu->funcs->detach(gmu->aspace->mmu);
1072 msm_gem_address_space_put(gmu->aspace);
929}1073}
930 1074
931static struct a6xx_gmu_bo *a6xx_gmu_memory_alloc(struct a6xx_gmu *gmu,1075static int a6xx_gmu_memory_alloc(struct a6xx_gmu *gmu, struct a6xx_gmu_bo *bo,
932 size_t size)1076 size_t size, u64 iova)
933{1077{
934 struct a6xx_gmu_bo *bo;1078 struct a6xx_gpu *a6xx_gpu = container_of(gmu, struct a6xx_gpu, gmu);
1079 struct drm_device *dev = a6xx_gpu->base.base.dev;
1080 uint32_t flags = MSM_BO_WC;
1081 u64 range_start, range_end;
1082 int ret;
935 1083
936 bo = kzalloc(sizeof(*bo), GFP_KERNEL);1084 size = PAGE_ALIGN(size);
937 if (!bo)1085 if (!iova) {
938 return ERR_PTR(-ENOMEM);1086 /* no fixed address - use GMU's uncached range */
1087 range_start = 0x60000000 + PAGE_SIZE; /* skip dummy page */
1088 range_end = 0x80000000;
1089 } else {
1090 /* range for fixed address */
1091 range_start = iova;
1092 range_end = iova + size;
1093 /* use IOMMU_PRIV for icache/dcache */
1094 flags |= MSM_BO_MAP_PRIV;
1095 }
939 1096
940 bo->size = PAGE_ALIGN(size);1097 bo->obj = msm_gem_new(dev, size, flags);
1098 if (IS_ERR(bo->obj))
1099 return PTR_ERR(bo->obj);
941 1100
942 bo->virt = dma_alloc_wc(gmu->dev, bo->size, &bo->iova, GFP_KERNEL);1101 ret = msm_gem_get_and_pin_iova_range(bo->obj, gmu->aspace, &bo->iova,
1102 range_start >> PAGE_SHIFT, range_end >> PAGE_SHIFT);
1103 if (ret) {
1104 drm_gem_object_put(bo->obj);
1105 return ret;
1106 }
1107
1108 bo->virt = msm_gem_get_vaddr(bo->obj);
1109 bo->size = size;
1110
1111 return 0;
1112}
1113
1114static int a6xx_gmu_memory_probe(struct a6xx_gmu *gmu)
1115{
1116 struct iommu_domain *domain;
1117 struct msm_mmu *mmu;
943 1118
944 if (!bo->virt) {1119 domain = iommu_domain_alloc(&platform_bus_type);
945 kfree(bo);1120 if (!domain)
946 return ERR_PTR(-ENOMEM);1121 return -ENODEV;
1122
1123 mmu = msm_iommu_new(gmu->dev, domain);
1124 gmu->aspace = msm_gem_address_space_create(mmu, "gmu", 0x0, 0x7fffffff);
1125 if (IS_ERR(gmu->aspace)) {
1126 iommu_domain_free(domain);
1127 return PTR_ERR(gmu->aspace);
947 }1128 }
948 1129
949 return bo;1130 return 0;
950}1131}
951 1132
952/* Return the 'arc-level' for the given frequency */1133/* Return the 'arc-level' for the given frequency */
@@ -1011,8 +1192,8 @@ static int a6xx_gmu_rpmh_arc_votes_init(struct device *dev, u32 *votes, · 58 unmodified lines
1011 1192
1012 if (j == pri_count) {1193 if (j == pri_count) {
1013 DRM_DEV_ERROR(dev,1194 DRM_DEV_ERROR(dev,
1014 "Level %u not found in in the RPMh list\n",1195 "Level %u not found in the RPMh list\n",
1015 level);1196 level);
1016 DRM_DEV_ERROR(dev, "Available levels:\n");1197 DRM_DEV_ERROR(dev, "Available levels:\n");
1017 for (j = 0; j < pri_count; j++)1198 for (j = 0; j < pri_count; j++)
1018 DRM_DEV_ERROR(dev, " %u\n", pri[j]);1199 DRM_DEV_ERROR(dev, " %u\n", pri[j]);
@@ -1190,6 +1371,7 @@ static int a6xx_gmu_get_irq(struct a6xx_gmu *gmu, struct platform_device *pdev, · 171 unmodified lines
1190void a6xx_gmu_remove(struct a6xx_gpu *a6xx_gpu)1371void a6xx_gmu_remove(struct a6xx_gpu *a6xx_gpu)
1191{1372{
1192 struct a6xx_gmu *gmu = &a6xx_gpu->gmu;1373 struct a6xx_gmu *gmu = &a6xx_gpu->gmu;
1374 struct platform_device *pdev = to_platform_device(gmu->dev);
1193 1375
1194 if (!gmu->initialized)1376 if (!gmu->initialized)
1195 return;1377 return;
@@ -1202,9 +1384,12 @@ void a6xx_gmu_remove(struct a6xx_gpu *a6xx_gpu) · 6 unmodified lines
1202 }1384 }
1203 1385
1204 iounmap(gmu->mmio);1386 iounmap(gmu->mmio);
1387 if (platform_get_resource_byname(pdev, IORESOURCE_MEM, "rscc"))
1388 iounmap(gmu->rscc);
1205 gmu->mmio = NULL;1389 gmu->mmio = NULL;
1390 gmu->rscc = NULL;
1206 1391
1207 a6xx_gmu_memory_free(gmu, gmu->hfi);1392 a6xx_gmu_memory_free(gmu);
1208 1393
1209 free_irq(gmu->gmu_irq, gmu);1394 free_irq(gmu->gmu_irq, gmu);
1210 free_irq(gmu->hfi_irq, gmu);1395 free_irq(gmu->hfi_irq, gmu);
@@ -1217,6 +1402,7 @@ void a6xx_gmu_remove(struct a6xx_gpu *a6xx_gpu) · 6 unmodified lines
1217 1402
1218int a6xx_gmu_init(struct a6xx_gpu *a6xx_gpu, struct device_node *node)1403int a6xx_gmu_init(struct a6xx_gpu *a6xx_gpu, struct device_node *node)
1219{1404{
1405 struct adreno_gpu *adreno_gpu = &a6xx_gpu->base;
1220 struct a6xx_gmu *gmu = &a6xx_gpu->gmu;1406 struct a6xx_gmu *gmu = &a6xx_gpu->gmu;
1221 struct platform_device *pdev = of_find_device_by_node(node);1407 struct platform_device *pdev = of_find_device_by_node(node);
1222 int ret;1408 int ret;
@@ -1226,15 +1412,7 @@ int a6xx_gmu_init(struct a6xx_gpu *a6xx_gpu, struct device_node *node) · 3 unmodified lines
1226 1412
1227 gmu->dev = &pdev->dev;1413 gmu->dev = &pdev->dev;
1228 1414
1229 /* Pass force_dma false to require the DT to set the dma region */1415 of_dma_configure(gmu->dev, node, true);
1230 ret = of_dma_configure(gmu->dev, node, false);
1231 if (ret)
1232 return ret;
1233
1234 /* Set the mask after the of_dma_configure() */
1235 ret = dma_set_mask_and_coherent(&pdev->dev, DMA_BIT_MASK(31));
1236 if (ret)
1237 return ret;
1238 1416
1239 /* Fow now, don't do anything fancy until we get our feet under us */1417 /* Fow now, don't do anything fancy until we get our feet under us */
1240 gmu->idle_level = GMU_IDLE_STATE_ACTIVE;1418 gmu->idle_level = GMU_IDLE_STATE_ACTIVE;
@@ -1246,20 +1424,64 @@ int a6xx_gmu_init(struct a6xx_gpu *a6xx_gpu, struct device_node *node) · 5 unmodified lines
1246 if (ret)1424 if (ret)
1247 goto err_put_device;1425 goto err_put_device;
1248 1426
1427 ret = a6xx_gmu_memory_probe(gmu);
1428 if (ret)
1429 goto err_put_device;
1430
1431 /* Allocate memory for the GMU dummy page */
1432 ret = a6xx_gmu_memory_alloc(gmu, &gmu->dummy, SZ_4K, 0x60000000);
1433 if (ret)
1434 goto err_memory;
1435
1436 if (adreno_is_a650(adreno_gpu)) {
1437 ret = a6xx_gmu_memory_alloc(gmu, &gmu->icache,
1438 SZ_16M - SZ_16K, 0x04000);
1439 if (ret)
1440 goto err_memory;
1441 } else if (adreno_is_a640(adreno_gpu)) {
1442 ret = a6xx_gmu_memory_alloc(gmu, &gmu->icache,
1443 SZ_256K - SZ_16K, 0x04000);
1444 if (ret)
1445 goto err_memory;
1446
1447 ret = a6xx_gmu_memory_alloc(gmu, &gmu->dcache,
1448 SZ_256K - SZ_16K, 0x44000);
1449 if (ret)
1450 goto err_memory;
1451 } else {
1452 /* HFI v1, has sptprac */
1453 gmu->legacy = true;
1454
1455 /* Allocate memory for the GMU debug region */
1456 ret = a6xx_gmu_memory_alloc(gmu, &gmu->debug, SZ_16K, 0);
1457 if (ret)
1458 goto err_memory;
1459 }
1460
1249 /* Allocate memory for for the HFI queues */1461 /* Allocate memory for for the HFI queues */
1250 gmu->hfi = a6xx_gmu_memory_alloc(gmu, SZ_16K);1462 ret = a6xx_gmu_memory_alloc(gmu, &gmu->hfi, SZ_16K, 0);
1251 if (IS_ERR(gmu->hfi))1463 if (ret)
1252 goto err_memory;1464 goto err_memory;
1253 1465
1254 /* Allocate memory for the GMU debug region */1466 /* Allocate memory for the GMU log region */
1255 gmu->debug = a6xx_gmu_memory_alloc(gmu, SZ_16K);1467 ret = a6xx_gmu_memory_alloc(gmu, &gmu->log, SZ_4K, 0);
1256 if (IS_ERR(gmu->debug))1468 if (ret)
1257 goto err_memory;1469 goto err_memory;
1258 1470
1259 /* Map the GMU registers */1471 /* Map the GMU registers */
1260 gmu->mmio = a6xx_gmu_get_mmio(pdev, "gmu");1472 gmu->mmio = a6xx_gmu_get_mmio(pdev, "gmu");
1261 if (IS_ERR(gmu->mmio))1473 if (IS_ERR(gmu->mmio)) {
1474 ret = PTR_ERR(gmu->mmio);
1262 goto err_memory;1475 goto err_memory;
1476 }
1477
1478 if (adreno_is_a650(adreno_gpu)) {
1479 gmu->rscc = a6xx_gmu_get_mmio(pdev, "rscc");
1480 if (IS_ERR(gmu->rscc))
1481 goto err_mmio;
1482 } else {
1483 gmu->rscc = gmu->mmio + 0x23000;
1484 }
1263 1485
1264 /* Get the HFI and GMU interrupts */1486 /* Get the HFI and GMU interrupts */
1265 gmu->hfi_irq = a6xx_gmu_get_irq(gmu, pdev, "hfi", a6xx_hfi_irq);1487 gmu->hfi_irq = a6xx_gmu_get_irq(gmu, pdev, "hfi", a6xx_hfi_irq);
@@ -1286,13 +1508,15 @@ int a6xx_gmu_init(struct a6xx_gpu *a6xx_gpu, struct device_node *node) · 20 unmodified lines
1286 1508
1287err_mmio:1509err_mmio:
1288 iounmap(gmu->mmio);1510 iounmap(gmu->mmio);
1511 if (platform_get_resource_byname(pdev, IORESOURCE_MEM, "rscc"))
1512 iounmap(gmu->rscc);
1289 free_irq(gmu->gmu_irq, gmu);1513 free_irq(gmu->gmu_irq, gmu);
1290 free_irq(gmu->hfi_irq, gmu);1514 free_irq(gmu->hfi_irq, gmu);
1291err_memory:
1292 a6xx_gmu_memory_free(gmu, gmu->hfi);
1293 1515
1294 ret = -ENODEV;1516 ret = -ENODEV;
1295 1517
1518err_memory:
1519 a6xx_gmu_memory_free(gmu);
1296err_put_device:1520err_put_device:
1297 /* Drop reference taken in of_find_device_by_node */1521 /* Drop reference taken in of_find_device_by_node */
1298 put_device(gmu->dev);1522 put_device(gmu->dev);
drivers/gpu/drm/msm/adreno/a6xx_gmu.h+34−3
@@ -10,9 +10,10 @@ · 9 unmodified lines
10#include "a6xx_hfi.h"10#include "a6xx_hfi.h"
11 11
12struct a6xx_gmu_bo {12struct a6xx_gmu_bo {
13 struct drm_gem_object *obj;
13 void *virt;14 void *virt;
14 size_t size;15 size_t size;
15 dma_addr_t iova;16 u64 iova;
16};17};
17 18
18/*19/*
@@ -43,7 +44,10 @@ struct a6xx_gmu_bo { · 24 unmodified lines
43struct a6xx_gmu {44struct a6xx_gmu {
44 struct device *dev;45 struct device *dev;
45 46
47 struct msm_gem_address_space *aspace;
48
46 void * __iomem mmio;49 void * __iomem mmio;
50 void * __iomem rscc;
47 51
48 int hfi_irq;52 int hfi_irq;
49 int gmu_irq;53 int gmu_irq;
@@ -52,8 +56,12 @@ struct a6xx_gmu { · 2 unmodified lines
52 56
53 int idle_level;57 int idle_level;
54 58
55 struct a6xx_gmu_bo *hfi;59 struct a6xx_gmu_bo hfi;
56 struct a6xx_gmu_bo *debug;60 struct a6xx_gmu_bo debug;
61 struct a6xx_gmu_bo icache;
62 struct a6xx_gmu_bo dcache;
63 struct a6xx_gmu_bo dummy;
64 struct a6xx_gmu_bo log;
57 65
58 int nr_clocks;66 int nr_clocks;
59 struct clk_bulk_data *clocks;67 struct clk_bulk_data *clocks;
@@ -76,6 +84,7 @@ struct a6xx_gmu { · 16 unmodified lines
76 84
77 bool initialized;85 bool initialized;
78 bool hung;86 bool hung;
87 bool legacy; /* a618 or a630 */
79};88};
80 89
81static inline u32 gmu_read(struct a6xx_gmu *gmu, u32 offset)90static inline u32 gmu_read(struct a6xx_gmu *gmu, u32 offset)
@@ -88,6 +97,13 @@ static inline void gmu_write(struct a6xx_gmu *gmu, u32 offset, u32 value) · 6 unmodified lines
88 return msm_writel(value, gmu->mmio + (offset << 2));97 return msm_writel(value, gmu->mmio + (offset << 2));
89}98}
90 99
100static inline void
101gmu_write_bulk(struct a6xx_gmu *gmu, u32 offset, const u32 *data, u32 size)
102{
103 memcpy_toio(gmu->mmio + (offset << 2), data, size);
104 wmb();
105}
106
91static inline void gmu_rmw(struct a6xx_gmu *gmu, u32 reg, u32 mask, u32 or)107static inline void gmu_rmw(struct a6xx_gmu *gmu, u32 reg, u32 mask, u32 or)
92{108{
93 u32 val = gmu_read(gmu, reg);109 u32 val = gmu_read(gmu, reg);
@@ -111,6 +127,15 @@ static inline u64 gmu_read64(struct a6xx_gmu *gmu, u32 lo, u32 hi) · 17 unmodified lines
111 readl_poll_timeout((gmu)->mmio + ((addr) << 2), val, cond, \127 readl_poll_timeout((gmu)->mmio + ((addr) << 2), val, cond, \
112 interval, timeout)128 interval, timeout)
113 129
130static inline void gmu_write_rscc(struct a6xx_gmu *gmu, u32 offset, u32 value)
131{
132 return msm_writel(value, gmu->rscc + (offset << 2));
133}
134
135#define gmu_poll_timeout_rscc(gmu, addr, val, cond, interval, timeout) \
136 readl_poll_timeout((gmu)->rscc + ((addr) << 2), val, cond, \
137 interval, timeout)
138
114/*139/*
115 * These are the available OOB (out of band requests) to the GMU where "out of140 * These are the available OOB (out of band requests) to the GMU where "out of
116 * band" means that the CPU talks to the GMU directly and not through HFI.141 * band" means that the CPU talks to the GMU directly and not through HFI.
@@ -156,10 +181,16 @@ enum a6xx_gmu_oob_state { · 39 unmodified lines
156#define GMU_OOB_GPU_SET_ACK 24181#define GMU_OOB_GPU_SET_ACK 24
157#define GMU_OOB_GPU_SET_CLEAR 24182#define GMU_OOB_GPU_SET_CLEAR 24
158 183
184#define GMU_OOB_GPU_SET_REQUEST_NEW 30
185#define GMU_OOB_GPU_SET_ACK_NEW 31
186#define GMU_OOB_GPU_SET_CLEAR_NEW 31
187
159 188
160void a6xx_hfi_init(struct a6xx_gmu *gmu);189void a6xx_hfi_init(struct a6xx_gmu *gmu);
161int a6xx_hfi_start(struct a6xx_gmu *gmu, int boot_state);190int a6xx_hfi_start(struct a6xx_gmu *gmu, int boot_state);
162void a6xx_hfi_stop(struct a6xx_gmu *gmu);191void a6xx_hfi_stop(struct a6xx_gmu *gmu);
192int a6xx_hfi_send_prep_slumber(struct a6xx_gmu *gmu);
193int a6xx_hfi_set_freq(struct a6xx_gmu *gmu, int index);
163 194
164bool a6xx_gmu_gx_is_on(struct a6xx_gmu *gmu);195bool a6xx_gmu_gx_is_on(struct a6xx_gmu *gmu);
165bool a6xx_gmu_sptprac_is_on(struct a6xx_gmu *gmu);196bool a6xx_gmu_sptprac_is_on(struct a6xx_gmu *gmu);
drivers/gpu/drm/msm/adreno/a6xx_gmu.xml.h+29−19
@@ -101,6 +101,10 @@ static inline uint32_t A6XX_HFI_IRQ_OOB_MASK(uint32_t val) · 100 unmodified lines
101 101
102#define REG_A6XX_GMU_DCVS_RETURN 0x000023ff102#define REG_A6XX_GMU_DCVS_RETURN 0x000023ff
103 103
104#define REG_A6XX_GMU_ICACHE_CONFIG 0x00004c00
105
106#define REG_A6XX_GMU_DCACHE_CONFIG 0x00004c01
107
104#define REG_A6XX_GMU_SYS_BUS_CONFIG 0x00004c0f108#define REG_A6XX_GMU_SYS_BUS_CONFIG 0x00004c0f
105 109
106#define REG_A6XX_GMU_CM3_SYSRESET 0x00005000110#define REG_A6XX_GMU_CM3_SYSRESET 0x00005000
@@ -199,6 +203,12 @@ static inline uint32_t A6XX_GMU_GPU_NAP_CTRL_SID(uint32_t val) · 92 unmodified lines
199 203
200#define REG_A6XX_GPU_GMU_CX_GMU_RPMH_POWER_STATE 0x000050ec204#define REG_A6XX_GPU_GMU_CX_GMU_RPMH_POWER_STATE 0x000050ec
201 205
206#define REG_A6XX_GPU_GMU_CX_GMU_CX_FAL_INTF 0x000050f0
207
208#define REG_A6XX_GPU_GMU_CX_GMU_PWR_COL_CP_MSG 0x00005100
209
210#define REG_A6XX_GPU_GMU_CX_GMU_PWR_COL_CP_RESP 0x00005101
211
202#define REG_A6XX_GMU_BOOT_KMD_LM_HANDSHAKE 0x000051f0212#define REG_A6XX_GMU_BOOT_KMD_LM_HANDSHAKE 0x000051f0
203 213
204#define REG_A6XX_GMU_LLM_GLM_SLEEP_CTRL 0x00005157214#define REG_A6XX_GMU_LLM_GLM_SLEEP_CTRL 0x00005157
@@ -330,8 +340,6 @@ static inline uint32_t A6XX_GMU_GPU_NAP_CTRL_SID(uint32_t val) · 125 unmodified lines
330 340
331#define REG_A6XX_GMU_AO_SPARE_CNTL 0x00009316341#define REG_A6XX_GMU_AO_SPARE_CNTL 0x00009316
332 342
333#define REG_A6XX_GPU_RSCC_RSC_STATUS0_DRV0 0x00008c04
334
335#define REG_A6XX_GMU_RSCC_CONTROL_REQ 0x00009307343#define REG_A6XX_GMU_RSCC_CONTROL_REQ 0x00009307
336 344
337#define REG_A6XX_GMU_RSCC_CONTROL_ACK 0x00009308345#define REG_A6XX_GMU_RSCC_CONTROL_ACK 0x00009308
@@ -344,39 +352,41 @@ static inline uint32_t A6XX_GMU_GPU_NAP_CTRL_SID(uint32_t val) · 6 unmodified lines
344 352
345#define REG_A6XX_GPU_CC_GX_DOMAIN_MISC 0x00009d42353#define REG_A6XX_GPU_CC_GX_DOMAIN_MISC 0x00009d42
346 354
347#define REG_A6XX_RSCC_PDC_SEQ_START_ADDR 0x00008c08355#define REG_A6XX_GPU_RSCC_RSC_STATUS0_DRV0 0x00000004
356
357#define REG_A6XX_RSCC_PDC_SEQ_START_ADDR 0x00000008
348 358
349#define REG_A6XX_RSCC_PDC_MATCH_VALUE_LO 0x00008c09359#define REG_A6XX_RSCC_PDC_MATCH_VALUE_LO 0x00000009
350 360
351#define REG_A6XX_RSCC_PDC_MATCH_VALUE_HI 0x00008c0a361#define REG_A6XX_RSCC_PDC_MATCH_VALUE_HI 0x0000000a
352 362
353#define REG_A6XX_RSCC_PDC_SLAVE_ID_DRV0 0x00008c0b363#define REG_A6XX_RSCC_PDC_SLAVE_ID_DRV0 0x0000000b
354 364
355#define REG_A6XX_RSCC_HIDDEN_TCS_CMD0_ADDR 0x00008c0d365#define REG_A6XX_RSCC_HIDDEN_TCS_CMD0_ADDR 0x0000000d
356 366
357#define REG_A6XX_RSCC_HIDDEN_TCS_CMD0_DATA 0x00008c0e367#define REG_A6XX_RSCC_HIDDEN_TCS_CMD0_DATA 0x0000000e
358 368
359#define REG_A6XX_RSCC_TIMESTAMP_UNIT0_TIMESTAMP_L_DRV0 0x00008c82369#define REG_A6XX_RSCC_TIMESTAMP_UNIT0_TIMESTAMP_L_DRV0 0x00000082
360 370
361#define REG_A6XX_RSCC_TIMESTAMP_UNIT0_TIMESTAMP_H_DRV0 0x00008c83371#define REG_A6XX_RSCC_TIMESTAMP_UNIT0_TIMESTAMP_H_DRV0 0x00000083
362 372
363#define REG_A6XX_RSCC_TIMESTAMP_UNIT1_EN_DRV0 0x00008c89373#define REG_A6XX_RSCC_TIMESTAMP_UNIT1_EN_DRV0 0x00000089
364 374
365#define REG_A6XX_RSCC_TIMESTAMP_UNIT1_OUTPUT_DRV0 0x00008c8c375#define REG_A6XX_RSCC_TIMESTAMP_UNIT1_OUTPUT_DRV0 0x0000008c
366 376
367#define REG_A6XX_RSCC_OVERRIDE_START_ADDR 0x00008d00377#define REG_A6XX_RSCC_OVERRIDE_START_ADDR 0x00000100
368 378
369#define REG_A6XX_RSCC_SEQ_BUSY_DRV0 0x00008d01379#define REG_A6XX_RSCC_SEQ_BUSY_DRV0 0x00000101
370 380
371#define REG_A6XX_RSCC_SEQ_MEM_0_DRV0 0x00008d80381#define REG_A6XX_RSCC_SEQ_MEM_0_DRV0 0x00000180
372 382
373#define REG_A6XX_RSCC_TCS0_DRV0_STATUS 0x00008f46383#define REG_A6XX_RSCC_TCS0_DRV0_STATUS 0x00000346
374 384
375#define REG_A6XX_RSCC_TCS1_DRV0_STATUS 0x000090ae385#define REG_A6XX_RSCC_TCS1_DRV0_STATUS 0x000003ee
376 386
377#define REG_A6XX_RSCC_TCS2_DRV0_STATUS 0x00009216387#define REG_A6XX_RSCC_TCS2_DRV0_STATUS 0x00000496
378 388
379#define REG_A6XX_RSCC_TCS3_DRV0_STATUS 0x0000937e389#define REG_A6XX_RSCC_TCS3_DRV0_STATUS 0x0000053e
380 390
381 391
382#endif /* A6XX_GMU_XML */392#endif /* A6XX_GMU_XML */
drivers/gpu/drm/msm/adreno/a6xx_gpu.c+59−11
@@ -414,7 +414,17 @@ static int a6xx_hw_init(struct msm_gpu *gpu) · 413 unmodified lines
414 a6xx_set_hwcg(gpu, true);414 a6xx_set_hwcg(gpu, true);
415 415
416 /* VBIF/GBIF start*/416 /* VBIF/GBIF start*/
417 gpu_write(gpu, REG_A6XX_RBBM_VBIF_CLIENT_QOS_CNTL, 0x3);417 if (adreno_is_a640(adreno_gpu) || adreno_is_a650(adreno_gpu)) {
418 gpu_write(gpu, REG_A6XX_GBIF_QSB_SIDE0, 0x00071620);
419 gpu_write(gpu, REG_A6XX_GBIF_QSB_SIDE1, 0x00071620);
420 gpu_write(gpu, REG_A6XX_GBIF_QSB_SIDE2, 0x00071620);
421 gpu_write(gpu, REG_A6XX_GBIF_QSB_SIDE3, 0x00071620);
422 gpu_write(gpu, REG_A6XX_GBIF_QSB_SIDE3, 0x00071620);
423 gpu_write(gpu, REG_A6XX_RBBM_GBIF_CLIENT_QOS_CNTL, 0x3);
424 } else {
425 gpu_write(gpu, REG_A6XX_RBBM_VBIF_CLIENT_QOS_CNTL, 0x3);
426 }
427
418 if (adreno_is_a630(adreno_gpu))428 if (adreno_is_a630(adreno_gpu))
419 gpu_write(gpu, REG_A6XX_VBIF_GATE_OFF_WRREQ_EN, 0x00000009);429 gpu_write(gpu, REG_A6XX_VBIF_GATE_OFF_WRREQ_EN, 0x00000009);
420 430
@@ -429,25 +439,35 @@ static int a6xx_hw_init(struct msm_gpu *gpu) · 8 unmodified lines
429 gpu_write(gpu, REG_A6XX_UCHE_WRITE_THRU_BASE_LO, 0xfffff000);439 gpu_write(gpu, REG_A6XX_UCHE_WRITE_THRU_BASE_LO, 0xfffff000);
430 gpu_write(gpu, REG_A6XX_UCHE_WRITE_THRU_BASE_HI, 0x0001ffff);440 gpu_write(gpu, REG_A6XX_UCHE_WRITE_THRU_BASE_HI, 0x0001ffff);
431 441
432 /* Set the GMEM VA range [0x100000:0x100000 + gpu->gmem - 1] */442 if (!adreno_is_a650(adreno_gpu)) {
433 gpu_write64(gpu, REG_A6XX_UCHE_GMEM_RANGE_MIN_LO,443 /* Set the GMEM VA range [0x100000:0x100000 + gpu->gmem - 1] */
434 REG_A6XX_UCHE_GMEM_RANGE_MIN_HI, 0x00100000);444 gpu_write64(gpu, REG_A6XX_UCHE_GMEM_RANGE_MIN_LO,
445 REG_A6XX_UCHE_GMEM_RANGE_MIN_HI, 0x00100000);
435 446
436 gpu_write64(gpu, REG_A6XX_UCHE_GMEM_RANGE_MAX_LO,447 gpu_write64(gpu, REG_A6XX_UCHE_GMEM_RANGE_MAX_LO,
437 REG_A6XX_UCHE_GMEM_RANGE_MAX_HI,448 REG_A6XX_UCHE_GMEM_RANGE_MAX_HI,
438 0x00100000 + adreno_gpu->gmem - 1);449 0x00100000 + adreno_gpu->gmem - 1);
450 }
439 451
440 gpu_write(gpu, REG_A6XX_UCHE_FILTER_CNTL, 0x804);452 gpu_write(gpu, REG_A6XX_UCHE_FILTER_CNTL, 0x804);
441 gpu_write(gpu, REG_A6XX_UCHE_CACHE_WAYS, 0x4);453 gpu_write(gpu, REG_A6XX_UCHE_CACHE_WAYS, 0x4);
442 454
443 gpu_write(gpu, REG_A6XX_CP_ROQ_THRESHOLDS_2, 0x010000c0);455 if (adreno_is_a640(adreno_gpu) || adreno_is_a650(adreno_gpu))
456 gpu_write(gpu, REG_A6XX_CP_ROQ_THRESHOLDS_2, 0x02000140);
457 else
458 gpu_write(gpu, REG_A6XX_CP_ROQ_THRESHOLDS_2, 0x010000c0);
444 gpu_write(gpu, REG_A6XX_CP_ROQ_THRESHOLDS_1, 0x8040362c);459 gpu_write(gpu, REG_A6XX_CP_ROQ_THRESHOLDS_1, 0x8040362c);
445 460
446 /* Setting the mem pool size */461 /* Setting the mem pool size */
447 gpu_write(gpu, REG_A6XX_CP_MEM_POOL_SIZE, 128);462 gpu_write(gpu, REG_A6XX_CP_MEM_POOL_SIZE, 128);
448 463
449 /* Setting the primFifo thresholds default values */464 /* Setting the primFifo thresholds default values */
450 gpu_write(gpu, REG_A6XX_PC_DBG_ECO_CNTL, (0x300 << 11));465 if (adreno_is_a650(adreno_gpu))
466 gpu_write(gpu, REG_A6XX_PC_DBG_ECO_CNTL, 0x00300000);
467 else if (adreno_is_a640(adreno_gpu))
468 gpu_write(gpu, REG_A6XX_PC_DBG_ECO_CNTL, 0x00200000);
469 else
470 gpu_write(gpu, REG_A6XX_PC_DBG_ECO_CNTL, (0x300 << 11));
451 471
452 /* Set the AHB default slave response to "ERROR" */472 /* Set the AHB default slave response to "ERROR" */
453 gpu_write(gpu, REG_A6XX_CP_AHB_CNTL, 0x1);473 gpu_write(gpu, REG_A6XX_CP_AHB_CNTL, 0x1);
@@ -471,6 +491,19 @@ static int a6xx_hw_init(struct msm_gpu *gpu) · 17 unmodified lines
471 491
472 gpu_write(gpu, REG_A6XX_UCHE_CLIENT_PF, 1);492 gpu_write(gpu, REG_A6XX_UCHE_CLIENT_PF, 1);
473 493
494 /* Set weights for bicubic filtering */
495 if (adreno_is_a650(adreno_gpu)) {
496 gpu_write(gpu, REG_A6XX_TPL1_BICUBIC_WEIGHTS_TABLE_0, 0);
497 gpu_write(gpu, REG_A6XX_TPL1_BICUBIC_WEIGHTS_TABLE_1,
498 0x3fe05ff4);
499 gpu_write(gpu, REG_A6XX_TPL1_BICUBIC_WEIGHTS_TABLE_2,
500 0x3fa0ebee);
501 gpu_write(gpu, REG_A6XX_TPL1_BICUBIC_WEIGHTS_TABLE_3,
502 0x3f5193ed);
503 gpu_write(gpu, REG_A6XX_TPL1_BICUBIC_WEIGHTS_TABLE_4,
504 0x3f0243f0);
505 }
506
474 /* Protect registers from the CP */507 /* Protect registers from the CP */
475 gpu_write(gpu, REG_A6XX_CP_PROTECT_CNTL, 0x00000003);508 gpu_write(gpu, REG_A6XX_CP_PROTECT_CNTL, 0x00000003);
476 509
@@ -508,6 +541,11 @@ static int a6xx_hw_init(struct msm_gpu *gpu) · 31 unmodified lines
508 A6XX_PROTECT_RDONLY(0x980, 0x4));541 A6XX_PROTECT_RDONLY(0x980, 0x4));
509 gpu_write(gpu, REG_A6XX_CP_PROTECT(25), A6XX_PROTECT_RW(0xa630, 0x0));542 gpu_write(gpu, REG_A6XX_CP_PROTECT(25), A6XX_PROTECT_RW(0xa630, 0x0));
510 543
544 if (adreno_is_a650(adreno_gpu)) {
545 gpu_write(gpu, REG_A6XX_CP_APRIV_CNTL,
546 (1 << 6) | (1 << 5) | (1 << 3) | (1 << 2) | (1 << 1));
547 }
548
511 /* Enable interrupts */549 /* Enable interrupts */
512 gpu_write(gpu, REG_A6XX_RBBM_INT_0_MASK, A6XX_INT_MASK);550 gpu_write(gpu, REG_A6XX_RBBM_INT_0_MASK, A6XX_INT_MASK);
513 551
@@ -566,8 +604,10 @@ out: · 52 unmodified lines
566 */604 */
567 a6xx_gmu_clear_oob(&a6xx_gpu->gmu, GMU_OOB_GPU_SET);605 a6xx_gmu_clear_oob(&a6xx_gpu->gmu, GMU_OOB_GPU_SET);
568 606
569 /* Take the GMU out of its special boot mode */607 if (a6xx_gpu->gmu.legacy) {
570 a6xx_gmu_clear_oob(&a6xx_gpu->gmu, GMU_OOB_BOOT_SLUMBER);608 /* Take the GMU out of its special boot mode */
609 a6xx_gmu_clear_oob(&a6xx_gpu->gmu, GMU_OOB_BOOT_SLUMBER);
610 }
571 611
572 return ret;612 return ret;
573}613}
@@ -810,6 +850,11 @@ static unsigned long a6xx_gpu_busy(struct msm_gpu *gpu) · 236 unmodified lines
810 struct a6xx_gpu *a6xx_gpu = to_a6xx_gpu(adreno_gpu);850 struct a6xx_gpu *a6xx_gpu = to_a6xx_gpu(adreno_gpu);
811 u64 busy_cycles, busy_time;851 u64 busy_cycles, busy_time;
812 852
853
854 /* Only read the gpu busy if the hardware is already active */
855 if (pm_runtime_get_if_in_use(a6xx_gpu->gmu.dev) == 0)
856 return 0;
857
813 busy_cycles = gmu_read64(&a6xx_gpu->gmu,858 busy_cycles = gmu_read64(&a6xx_gpu->gmu,
814 REG_A6XX_GMU_CX_GMU_POWER_COUNTER_XOCLK_0_L,859 REG_A6XX_GMU_CX_GMU_POWER_COUNTER_XOCLK_0_L,
815 REG_A6XX_GMU_CX_GMU_POWER_COUNTER_XOCLK_0_H);860 REG_A6XX_GMU_CX_GMU_POWER_COUNTER_XOCLK_0_H);
@@ -819,6 +864,8 @@ static unsigned long a6xx_gpu_busy(struct msm_gpu *gpu) · 3 unmodified lines
819 864
820 gpu->devfreq.busy_cycles = busy_cycles;865 gpu->devfreq.busy_cycles = busy_cycles;
821 866
867 pm_runtime_put(a6xx_gpu->gmu.dev);
868
822 if (WARN_ON(busy_time > ~0LU))869 if (WARN_ON(busy_time > ~0LU))
823 return ~0LU;870 return ~0LU;
824 871
@@ -846,6 +893,7 @@ static const struct adreno_gpu_funcs funcs = { · 21 unmodified lines
846#if defined(CONFIG_DRM_MSM_GPU_STATE)893#if defined(CONFIG_DRM_MSM_GPU_STATE)
847 .gpu_state_get = a6xx_gpu_state_get,894 .gpu_state_get = a6xx_gpu_state_get,
848 .gpu_state_put = a6xx_gpu_state_put,895 .gpu_state_put = a6xx_gpu_state_put,
896 .create_address_space = adreno_iommu_create_address_space,
849#endif897#endif
850 },898 },
851 .get_timestamp = a6xx_get_timestamp,899 .get_timestamp = a6xx_get_timestamp,
drivers/gpu/drm/msm/adreno/a6xx_hfi.c+114−9
@@ -17,10 +17,14 @@ static const char * const a6xx_hfi_msg_id[] = { · 16 unmodified lines
17 HFI_MSG_ID(HFI_H2F_MSG_BW_TABLE),17 HFI_MSG_ID(HFI_H2F_MSG_BW_TABLE),
18 HFI_MSG_ID(HFI_H2F_MSG_PERF_TABLE),18 HFI_MSG_ID(HFI_H2F_MSG_PERF_TABLE),
19 HFI_MSG_ID(HFI_H2F_MSG_TEST),19 HFI_MSG_ID(HFI_H2F_MSG_TEST),
20 HFI_MSG_ID(HFI_H2F_MSG_START),
21 HFI_MSG_ID(HFI_H2F_MSG_CORE_FW_START),
22 HFI_MSG_ID(HFI_H2F_MSG_GX_BW_PERF_VOTE),
23 HFI_MSG_ID(HFI_H2F_MSG_PREPARE_SLUMBER),
20};24};
21 25
22static int a6xx_hfi_queue_read(struct a6xx_hfi_queue *queue, u32 *data,26static int a6xx_hfi_queue_read(struct a6xx_gmu *gmu,
23 u32 dwords)27 struct a6xx_hfi_queue *queue, u32 *data, u32 dwords)
24{28{
25 struct a6xx_hfi_queue_header *header = queue->header;29 struct a6xx_hfi_queue_header *header = queue->header;
26 u32 i, hdr, index = header->read_index;30 u32 i, hdr, index = header->read_index;
@@ -48,6 +52,9 @@ static int a6xx_hfi_queue_read(struct a6xx_hfi_queue *queue, u32 *data, · 21 unmodified lines
48 index = (index + 1) % header->size;52 index = (index + 1) % header->size;
49 }53 }
50 54
55 if (!gmu->legacy)
56 index = ALIGN(index, 4) % header->size;
57
51 header->read_index = index;58 header->read_index = index;
52 return HFI_HEADER_SIZE(hdr);59 return HFI_HEADER_SIZE(hdr);
53}60}
@@ -73,6 +80,12 @@ static int a6xx_hfi_queue_write(struct a6xx_gmu *gmu, · 19 unmodified lines
73 index = (index + 1) % header->size;80 index = (index + 1) % header->size;
74 }81 }
75 82
83 /* Cookify any non used data at the end of the write buffer */
84 if (!gmu->legacy) {
85 for (; index % 4; index = (index + 1) % header->size)
86 queue->data[index] = 0xfafafafa;
87 }
88
76 header->write_index = index;89 header->write_index = index;
77 spin_unlock(&queue->lock);90 spin_unlock(&queue->lock);
78 91
@@ -106,7 +119,7 @@ static int a6xx_hfi_wait_for_ack(struct a6xx_gmu *gmu, u32 id, u32 seqnum, · 27 unmodified lines
106 struct a6xx_hfi_msg_response resp;119 struct a6xx_hfi_msg_response resp;
107 120
108 /* Get the next packet */121 /* Get the next packet */
109 ret = a6xx_hfi_queue_read(queue, (u32 *) &resp,122 ret = a6xx_hfi_queue_read(gmu, queue, (u32 *) &resp,
110 sizeof(resp) >> 2);123 sizeof(resp) >> 2);
111 124
112 /* If the queue is empty our response never made it */125 /* If the queue is empty our response never made it */
@@ -176,8 +189,8 @@ static int a6xx_hfi_send_gmu_init(struct a6xx_gmu *gmu, int boot_state) · 63 unmodified lines
176{189{
177 struct a6xx_hfi_msg_gmu_init_cmd msg = { 0 };190 struct a6xx_hfi_msg_gmu_init_cmd msg = { 0 };
178 191
179 msg.dbg_buffer_addr = (u32) gmu->debug->iova;192 msg.dbg_buffer_addr = (u32) gmu->debug.iova;
180 msg.dbg_buffer_size = (u32) gmu->debug->size;193 msg.dbg_buffer_size = (u32) gmu->debug.size;
181 msg.boot_state = boot_state;194 msg.boot_state = boot_state;
182 195
183 return a6xx_hfi_send_msg(gmu, HFI_H2F_MSG_INIT, &msg, sizeof(msg),196 return a6xx_hfi_send_msg(gmu, HFI_H2F_MSG_INIT, &msg, sizeof(msg),
@@ -195,6 +208,28 @@ static int a6xx_hfi_get_fw_version(struct a6xx_gmu *gmu, u32 *version) · 11 unmodified lines
195 version, sizeof(*version));208 version, sizeof(*version));
196}209}
197 210
211static int a6xx_hfi_send_perf_table_v1(struct a6xx_gmu *gmu)
212{
213 struct a6xx_hfi_msg_perf_table_v1 msg = { 0 };
214 int i;
215
216 msg.num_gpu_levels = gmu->nr_gpu_freqs;
217 msg.num_gmu_levels = gmu->nr_gmu_freqs;
218
219 for (i = 0; i < gmu->nr_gpu_freqs; i++) {
220 msg.gx_votes[i].vote = gmu->gx_arc_votes[i];
221 msg.gx_votes[i].freq = gmu->gpu_freqs[i] / 1000;
222 }
223
224 for (i = 0; i < gmu->nr_gmu_freqs; i++) {
225 msg.cx_votes[i].vote = gmu->cx_arc_votes[i];
226 msg.cx_votes[i].freq = gmu->gmu_freqs[i] / 1000;
227 }
228
229 return a6xx_hfi_send_msg(gmu, HFI_H2F_MSG_PERF_TABLE, &msg, sizeof(msg),
230 NULL, 0);
231}
232
198static int a6xx_hfi_send_perf_table(struct a6xx_gmu *gmu)233static int a6xx_hfi_send_perf_table(struct a6xx_gmu *gmu)
199{234{
200 struct a6xx_hfi_msg_perf_table msg = { 0 };235 struct a6xx_hfi_msg_perf_table msg = { 0 };
@@ -205,6 +240,7 @@ static int a6xx_hfi_send_perf_table(struct a6xx_gmu *gmu) · 4 unmodified lines
205 240
206 for (i = 0; i < gmu->nr_gpu_freqs; i++) {241 for (i = 0; i < gmu->nr_gpu_freqs; i++) {
207 msg.gx_votes[i].vote = gmu->gx_arc_votes[i];242 msg.gx_votes[i].vote = gmu->gx_arc_votes[i];
243 msg.gx_votes[i].acd = 0xffffffff;
208 msg.gx_votes[i].freq = gmu->gpu_freqs[i] / 1000;244 msg.gx_votes[i].freq = gmu->gpu_freqs[i] / 1000;
209 }245 }
210 246
@@ -306,7 +342,45 @@ static int a6xx_hfi_send_test(struct a6xx_gmu *gmu) · 95 unmodified lines
306 NULL, 0);342 NULL, 0);
307}343}
308 344
309int a6xx_hfi_start(struct a6xx_gmu *gmu, int boot_state)345static int a6xx_hfi_send_start(struct a6xx_gmu *gmu)
346{
347 struct a6xx_hfi_msg_start msg = { 0 };
348
349 return a6xx_hfi_send_msg(gmu, HFI_H2F_MSG_START, &msg, sizeof(msg),
350 NULL, 0);
351}
352
353static int a6xx_hfi_send_core_fw_start(struct a6xx_gmu *gmu)
354{
355 struct a6xx_hfi_msg_core_fw_start msg = { 0 };
356
357 return a6xx_hfi_send_msg(gmu, HFI_H2F_MSG_CORE_FW_START, &msg,
358 sizeof(msg), NULL, 0);
359}
360
361int a6xx_hfi_set_freq(struct a6xx_gmu *gmu, int index)
362{
363 struct a6xx_hfi_gx_bw_perf_vote_cmd msg = { 0 };
364
365 msg.ack_type = 1; /* blocking */
366 msg.freq = index;
367 msg.bw = 0; /* TODO: bus scaling */
368
369 return a6xx_hfi_send_msg(gmu, HFI_H2F_MSG_GX_BW_PERF_VOTE, &msg,
370 sizeof(msg), NULL, 0);
371}
372
373int a6xx_hfi_send_prep_slumber(struct a6xx_gmu *gmu)
374{
375 struct a6xx_hfi_prep_slumber_cmd msg = { 0 };
376
377 /* TODO: should freq and bw fields be non-zero ? */
378
379 return a6xx_hfi_send_msg(gmu, HFI_H2F_MSG_PREPARE_SLUMBER, &msg,
380 sizeof(msg), NULL, 0);
381}
382
383static int a6xx_hfi_start_v1(struct a6xx_gmu *gmu, int boot_state)
310{384{
311 int ret;385 int ret;
312 386
@@ -324,7 +398,7 @@ int a6xx_hfi_start(struct a6xx_gmu *gmu, int boot_state) · 11 unmodified lines
324 * the GMU firmware398 * the GMU firmware
325 */399 */
326 400
327 ret = a6xx_hfi_send_perf_table(gmu);401 ret = a6xx_hfi_send_perf_table_v1(gmu);
328 if (ret)402 if (ret)
329 return ret;403 return ret;
330 404
@@ -341,6 +415,37 @@ int a6xx_hfi_start(struct a6xx_gmu *gmu, int boot_state) · 10 unmodified lines
341 return 0;415 return 0;
342}416}
343 417
418int a6xx_hfi_start(struct a6xx_gmu *gmu, int boot_state)
419{
420 int ret;
421
422 if (gmu->legacy)
423 return a6xx_hfi_start_v1(gmu, boot_state);
424
425
426 ret = a6xx_hfi_send_perf_table(gmu);
427 if (ret)
428 return ret;
429
430 ret = a6xx_hfi_send_bw_table(gmu);
431 if (ret)
432 return ret;
433
434 ret = a6xx_hfi_send_core_fw_start(gmu);
435 if (ret)
436 return ret;
437
438 /*
439 * Downstream driver sends this in its "a6xx_hw_init" equivalent,
440 * but seems to be no harm in sending it here
441 */
442 ret = a6xx_hfi_send_start(gmu);
443 if (ret)
444 return ret;
445
446 return 0;
447}
448
344void a6xx_hfi_stop(struct a6xx_gmu *gmu)449void a6xx_hfi_stop(struct a6xx_gmu *gmu)
345{450{
346 int i;451 int i;
@@ -385,7 +490,7 @@ static void a6xx_hfi_queue_init(struct a6xx_hfi_queue *queue, · 38 unmodified lines
385 490
386void a6xx_hfi_init(struct a6xx_gmu *gmu)491void a6xx_hfi_init(struct a6xx_gmu *gmu)
387{492{
388 struct a6xx_gmu_bo *hfi = gmu->hfi;493 struct a6xx_gmu_bo *hfi = &gmu->hfi;
389 struct a6xx_hfi_queue_table_header *table = hfi->virt;494 struct a6xx_hfi_queue_table_header *table = hfi->virt;
390 struct a6xx_hfi_queue_header *headers = hfi->virt + sizeof(*table);495 struct a6xx_hfi_queue_header *headers = hfi->virt + sizeof(*table);
391 u64 offset;496 u64 offset;
@@ -415,5 +520,5 @@ void a6xx_hfi_init(struct a6xx_gmu *gmu) · 23 unmodified lines
415 /* GMU response queue */520 /* GMU response queue */
416 offset += SZ_4K;521 offset += SZ_4K;
417 a6xx_hfi_queue_init(&gmu->queues[1], &headers[1], hfi->virt + offset,522 a6xx_hfi_queue_init(&gmu->queues[1], &headers[1], hfi->virt + offset,
418 hfi->iova + offset, 4);523 hfi->iova + offset, gmu->legacy ? 4 : 1);
419}524}
drivers/gpu/drm/msm/adreno/a6xx_hfi.h+48−2
@@ -51,7 +51,8 @@ struct a6xx_hfi_queue { · 50 unmodified lines
51/* HFI message types */51/* HFI message types */
52 52
53#define HFI_MSG_CMD 053#define HFI_MSG_CMD 0
54#define HFI_MSG_ACK 254#define HFI_MSG_ACK 1
55#define HFI_MSG_ACK_V1 2
55 56
56#define HFI_F2H_MSG_ACK 12657#define HFI_F2H_MSG_ACK 126
57 58
@@ -94,7 +95,13 @@ struct perf_level { · 36 unmodified lines
94 u32 freq;95 u32 freq;
95};96};
96 97
97struct a6xx_hfi_msg_perf_table {98struct perf_gx_level {
99 u32 vote;
100 u32 acd;
101 u32 freq;
102};
103
104struct a6xx_hfi_msg_perf_table_v1 {
98 u32 header;105 u32 header;
99 u32 num_gpu_levels;106 u32 num_gpu_levels;
100 u32 num_gmu_levels;107 u32 num_gmu_levels;
@@ -103,6 +110,15 @@ struct a6xx_hfi_msg_perf_table { · 2 unmodified lines
103 struct perf_level cx_votes[4];110 struct perf_level cx_votes[4];
104};111};
105 112
113struct a6xx_hfi_msg_perf_table {
114 u32 header;
115 u32 num_gpu_levels;
116 u32 num_gmu_levels;
117
118 struct perf_gx_level gx_votes[16];
119 struct perf_level cx_votes[4];
120};
121
106#define HFI_H2F_MSG_BW_TABLE 3122#define HFI_H2F_MSG_BW_TABLE 3
107 123
108struct a6xx_hfi_msg_bw_table {124struct a6xx_hfi_msg_bw_table {
@@ -124,4 +140,34 @@ struct a6xx_hfi_msg_test { · 15 unmodified lines
124 u32 header;140 u32 header;
125};141};
126 142
143#define HFI_H2F_MSG_START 10
144
145struct a6xx_hfi_msg_start {
146 u32 header;
147};
148
149#define HFI_H2F_MSG_CORE_FW_START 14
150
151struct a6xx_hfi_msg_core_fw_start {
152 u32 header;
153 u32 handle;
154};
155
156#define HFI_H2F_MSG_GX_BW_PERF_VOTE 30
157
158struct a6xx_hfi_gx_bw_perf_vote_cmd {
159 u32 header;
160 u32 ack_type;
161 u32 freq;
162 u32 bw;
163};
164
165#define HFI_H2F_MSG_PREPARE_SLUMBER 33
166
167struct a6xx_hfi_prep_slumber_cmd {
168 u32 header;
169 u32 bw;
170 u32 freq;
171};
172
127#endif173#endif
drivers/gpu/drm/msm/adreno/adreno_device.c+35−0
@@ -92,6 +92,17 @@ static const struct adreno_info gpulist[] = { · 91 unmodified lines
92 .gmem = SZ_1M,92 .gmem = SZ_1M,
93 .inactive_period = DRM_MSM_INACTIVE_PERIOD,93 .inactive_period = DRM_MSM_INACTIVE_PERIOD,
94 .init = a3xx_gpu_init,94 .init = a3xx_gpu_init,
95 }, {
96 .rev = ADRENO_REV(4, 0, 5, ANY_ID),
97 .revn = 405,
98 .name = "A405",
99 .fw = {
100 [ADRENO_FW_PM4] = "a420_pm4.fw",
101 [ADRENO_FW_PFP] = "a420_pfp.fw",
102 },
103 .gmem = SZ_256K,
104 .inactive_period = DRM_MSM_INACTIVE_PERIOD,
105 .init = a4xx_gpu_init,
95 }, {106 }, {
96 .rev = ADRENO_REV(4, 2, 0, ANY_ID),107 .rev = ADRENO_REV(4, 2, 0, ANY_ID),
97 .revn = 420,108 .revn = 420,
@@ -189,6 +200,30 @@ static const struct adreno_info gpulist[] = { · 91 unmodified lines
189 .inactive_period = DRM_MSM_INACTIVE_PERIOD,200 .inactive_period = DRM_MSM_INACTIVE_PERIOD,
190 .init = a6xx_gpu_init,201 .init = a6xx_gpu_init,
191 .zapfw = "a630_zap.mdt",202 .zapfw = "a630_zap.mdt",
203 }, {
204 .rev = ADRENO_REV(6, 4, 0, ANY_ID),
205 .revn = 640,
206 .name = "A640",
207 .fw = {
208 [ADRENO_FW_SQE] = "a630_sqe.fw",
209 [ADRENO_FW_GMU] = "a640_gmu.bin",
210 },
211 .gmem = SZ_1M,
212 .inactive_period = DRM_MSM_INACTIVE_PERIOD,
213 .init = a6xx_gpu_init,
214 .zapfw = "a640_zap.mdt",
215 }, {
216 .rev = ADRENO_REV(6, 5, 0, ANY_ID),
217 .revn = 650,
218 .name = "A650",
219 .fw = {
220 [ADRENO_FW_SQE] = "a650_sqe.fw",
221 [ADRENO_FW_GMU] = "a650_gmu.bin",
222 },
223 .gmem = SZ_1M + SZ_128K,
224 .inactive_period = DRM_MSM_INACTIVE_PERIOD,
225 .init = a6xx_gpu_init,
226 .zapfw = "a650_zap.mdt",
192 },227 },
193};228};
194 229
drivers/gpu/drm/msm/adreno/adreno_gpu.c+19−8
@@ -185,6 +185,23 @@ int adreno_zap_shader_load(struct msm_gpu *gpu, u32 pasid) · 184 unmodified lines
185 return zap_shader_load_mdt(gpu, adreno_gpu->info->zapfw, pasid);185 return zap_shader_load_mdt(gpu, adreno_gpu->info->zapfw, pasid);
186}186}
187 187
188struct msm_gem_address_space *
189adreno_iommu_create_address_space(struct msm_gpu *gpu,
190 struct platform_device *pdev)
191{
192 struct iommu_domain *iommu = iommu_domain_alloc(&platform_bus_type);
193 struct msm_mmu *mmu = msm_iommu_new(&pdev->dev, iommu);
194 struct msm_gem_address_space *aspace;
195
196 aspace = msm_gem_address_space_create(mmu, "gpu", SZ_16M,
197 0xfffffff);
198
199 if (IS_ERR(aspace) && !IS_ERR(mmu))
200 mmu->funcs->destroy(mmu);
201
202 return aspace;
203}
204
188int adreno_get_param(struct msm_gpu *gpu, uint32_t param, uint64_t *value)205int adreno_get_param(struct msm_gpu *gpu, uint32_t param, uint64_t *value)
189{206{
190 struct adreno_gpu *adreno_gpu = to_adreno_gpu(gpu);207 struct adreno_gpu *adreno_gpu = to_adreno_gpu(gpu);
@@ -197,7 +214,7 @@ int adreno_get_param(struct msm_gpu *gpu, uint32_t param, uint64_t *value) · 6 unmodified lines
197 *value = adreno_gpu->gmem;214 *value = adreno_gpu->gmem;
198 return 0;215 return 0;
199 case MSM_PARAM_GMEM_BASE:216 case MSM_PARAM_GMEM_BASE:
200 *value = 0x100000;217 *value = !adreno_is_a650(adreno_gpu) ? 0x100000 : 0;
201 return 0;218 return 0;
202 case MSM_PARAM_CHIP_ID:219 case MSM_PARAM_CHIP_ID:
203 *value = adreno_gpu->rev.patchid |220 *value = adreno_gpu->rev.patchid |
@@ -459,7 +476,7 @@ void adreno_submit(struct msm_gpu *gpu, struct msm_gem_submit *submit, · 255 unmodified lines
459 break;476 break;
460 /* fall-thru */477 /* fall-thru */
461 case MSM_SUBMIT_CMD_BUF:478 case MSM_SUBMIT_CMD_BUF:
462 OUT_PKT3(ring, adreno_is_a430(adreno_gpu) ?479 OUT_PKT3(ring, adreno_is_a4xx(adreno_gpu) ?
463 CP_INDIRECT_BUFFER_PFE : CP_INDIRECT_BUFFER_PFD, 2);480 CP_INDIRECT_BUFFER_PFE : CP_INDIRECT_BUFFER_PFD, 2);
464 OUT_RING(ring, lower_32_bits(submit->cmd[i].iova));481 OUT_RING(ring, lower_32_bits(submit->cmd[i].iova));
465 OUT_RING(ring, submit->cmd[i].size);482 OUT_RING(ring, submit->cmd[i].size);
@@ -988,12 +1005,6 @@ int adreno_gpu_init(struct drm_device *drm, struct platform_device *pdev, · 522 unmodified lines
988 1005
989 adreno_gpu_config.ioname = "kgsl_3d0_reg_memory";1006 adreno_gpu_config.ioname = "kgsl_3d0_reg_memory";
990 1007
991 adreno_gpu_config.va_start = SZ_16M;
992 adreno_gpu_config.va_end = 0xffffffff;
993 /* maximum range of a2xx mmu */
994 if (adreno_is_a2xx(adreno_gpu))
995 adreno_gpu_config.va_end = SZ_16M + 0xfff * SZ_64K;
996
997 adreno_gpu_config.nr_rings = nr_rings;1008 adreno_gpu_config.nr_rings = nr_rings;
998 1009
999 adreno_get_pwrlevels(&pdev->dev, gpu);1010 adreno_get_pwrlevels(&pdev->dev, gpu);
drivers/gpu/drm/msm/adreno/adreno_gpu.h+23−0
@@ -202,6 +202,11 @@ static inline bool adreno_is_a4xx(struct adreno_gpu *gpu) · 201 unmodified lines
202 return (gpu->revn >= 400) && (gpu->revn < 500);202 return (gpu->revn >= 400) && (gpu->revn < 500);
203}203}
204 204
205static inline int adreno_is_a405(struct adreno_gpu *gpu)
206{
207 return gpu->revn == 405;
208}
209
205static inline int adreno_is_a420(struct adreno_gpu *gpu)210static inline int adreno_is_a420(struct adreno_gpu *gpu)
206{211{
207 return gpu->revn == 420;212 return gpu->revn == 420;
@@ -237,6 +242,16 @@ static inline int adreno_is_a630(struct adreno_gpu *gpu) · 29 unmodified lines
237 return gpu->revn == 630;242 return gpu->revn == 630;
238}243}
239 244
245static inline int adreno_is_a640(struct adreno_gpu *gpu)
246{
247 return gpu->revn == 640;
248}
249
250static inline int adreno_is_a650(struct adreno_gpu *gpu)
251{
252 return gpu->revn == 650;
253}
254
240int adreno_get_param(struct msm_gpu *gpu, uint32_t param, uint64_t *value);255int adreno_get_param(struct msm_gpu *gpu, uint32_t param, uint64_t *value);
241const struct firmware *adreno_request_fw(struct adreno_gpu *adreno_gpu,256const struct firmware *adreno_request_fw(struct adreno_gpu *adreno_gpu,
242 const char *fwname);257 const char *fwname);
@@ -272,6 +287,14 @@ void adreno_gpu_state_destroy(struct msm_gpu_state *state); · 29 unmodified lines
272int adreno_gpu_state_get(struct msm_gpu *gpu, struct msm_gpu_state *state);287int adreno_gpu_state_get(struct msm_gpu *gpu, struct msm_gpu_state *state);
273int adreno_gpu_state_put(struct msm_gpu_state *state);288int adreno_gpu_state_put(struct msm_gpu_state *state);
274 289
290/*
291 * Common helper function to initialize the default address space for arm-smmu
292 * attached targets
293 */
294struct msm_gem_address_space *
295adreno_iommu_create_address_space(struct msm_gpu *gpu,
296 struct platform_device *pdev);
297
275/*298/*
276 * For a5xx and a6xx targets load the zap shader that is used to pull the GPU299 * For a5xx and a6xx targets load the zap shader that is used to pull the GPU
277 * out of secure mode300 * out of secure mode
drivers/gpu/drm/msm/disp/dpu1/dpu_core_perf.c+1−22
@@ -36,22 +36,6 @@ static struct dpu_kms *_dpu_crtc_get_kms(struct drm_crtc *crtc) · 35 unmodified lines
36 return to_dpu_kms(priv->kms);36 return to_dpu_kms(priv->kms);
37}37}
38 38
39static bool _dpu_core_video_mode_intf_connected(struct drm_crtc *crtc)
40{
41 struct drm_crtc *tmp_crtc;
42
43 drm_for_each_crtc(tmp_crtc, crtc->dev) {
44 if ((dpu_crtc_get_intf_mode(tmp_crtc) == INTF_MODE_VIDEO) &&
45 tmp_crtc->enabled) {
46 DPU_DEBUG("video interface connected crtc:%d\n",
47 tmp_crtc->base.id);
48 return true;
49 }
50 }
51
52 return false;
53}
54
55static void _dpu_core_perf_calc_crtc(struct dpu_kms *kms,39static void _dpu_core_perf_calc_crtc(struct dpu_kms *kms,
56 struct drm_crtc *crtc,40 struct drm_crtc *crtc,
57 struct drm_crtc_state *state,41 struct drm_crtc_state *state,
@@ -94,7 +78,6 @@ int dpu_core_perf_crtc_check(struct drm_crtc *crtc, · 36 unmodified lines
94 u32 bw, threshold;78 u32 bw, threshold;
95 u64 bw_sum_of_intfs = 0;79 u64 bw_sum_of_intfs = 0;
96 enum dpu_crtc_client_type curr_client_type;80 enum dpu_crtc_client_type curr_client_type;
97 bool is_video_mode;
98 struct dpu_crtc_state *dpu_cstate;81 struct dpu_crtc_state *dpu_cstate;
99 struct drm_crtc *tmp_crtc;82 struct drm_crtc *tmp_crtc;
100 struct dpu_kms *kms;83 struct dpu_kms *kms;
@@ -144,11 +127,7 @@ int dpu_core_perf_crtc_check(struct drm_crtc *crtc, · 43 unmodified lines
144 bw = DIV_ROUND_UP_ULL(bw_sum_of_intfs, 1000);127 bw = DIV_ROUND_UP_ULL(bw_sum_of_intfs, 1000);
145 DPU_DEBUG("calculated bandwidth=%uk\n", bw);128 DPU_DEBUG("calculated bandwidth=%uk\n", bw);
146 129
147 is_video_mode = dpu_crtc_get_intf_mode(crtc) == INTF_MODE_VIDEO;130 threshold = kms->catalog->perf.max_bw_high;
148 threshold = (is_video_mode ||
149 _dpu_core_video_mode_intf_connected(crtc)) ?
150 kms->catalog->perf.max_bw_low :
151 kms->catalog->perf.max_bw_high;
152 131
153 DPU_DEBUG("final threshold bw limit = %d\n", threshold);132 DPU_DEBUG("final threshold bw limit = %d\n", threshold);
154 133
drivers/gpu/drm/msm/disp/dpu1/dpu_crtc.c+77−18
@@ -9,6 +9,7 @@ · 8 unmodified lines
9#include <linux/sort.h>9#include <linux/sort.h>
10#include <linux/debugfs.h>10#include <linux/debugfs.h>
11#include <linux/ktime.h>11#include <linux/ktime.h>
12#include <linux/bits.h>
12 13
13#include <drm/drm_crtc.h>14#include <drm/drm_crtc.h>
14#include <drm/drm_flip_work.h>15#include <drm/drm_flip_work.h>
@@ -20,6 +21,7 @@ · 5 unmodified lines
20#include "dpu_kms.h"21#include "dpu_kms.h"
21#include "dpu_hw_lm.h"22#include "dpu_hw_lm.h"
22#include "dpu_hw_ctl.h"23#include "dpu_hw_ctl.h"
24#include "dpu_hw_dspp.h"
23#include "dpu_crtc.h"25#include "dpu_crtc.h"
24#include "dpu_plane.h"26#include "dpu_plane.h"
25#include "dpu_encoder.h"27#include "dpu_encoder.h"
@@ -40,6 +42,9 @@ · 14 unmodified lines
40/* timeout in ms waiting for frame done */42/* timeout in ms waiting for frame done */
41#define DPU_CRTC_FRAME_DONE_TIMEOUT_MS 6043#define DPU_CRTC_FRAME_DONE_TIMEOUT_MS 60
42 44
45#define CONVERT_S3_15(val) \
46 (((((u64)val) & ~BIT_ULL(63)) >> 17) & GENMASK_ULL(17, 0))
47
43static struct dpu_kms *_dpu_crtc_get_kms(struct drm_crtc *crtc)48static struct dpu_kms *_dpu_crtc_get_kms(struct drm_crtc *crtc)
44{49{
45 struct msm_drm_private *priv = crtc->dev->dev_private;50 struct msm_drm_private *priv = crtc->dev->dev_private;
@@ -88,11 +93,9 @@ static void _dpu_crtc_setup_blend_cfg(struct dpu_crtc_mixer *mixer, · 42 unmodified lines
88 93
89static void _dpu_crtc_program_lm_output_roi(struct drm_crtc *crtc)94static void _dpu_crtc_program_lm_output_roi(struct drm_crtc *crtc)
90{95{
91 struct dpu_crtc *dpu_crtc;
92 struct dpu_crtc_state *crtc_state;96 struct dpu_crtc_state *crtc_state;
93 int lm_idx, lm_horiz_position;97 int lm_idx, lm_horiz_position;
94 98
95 dpu_crtc = to_dpu_crtc(crtc);
96 crtc_state = to_dpu_crtc_state(crtc->state);99 crtc_state = to_dpu_crtc_state(crtc->state);
97 100
98 lm_horiz_position = 0;101 lm_horiz_position = 0;
@@ -422,6 +425,74 @@ static void _dpu_crtc_setup_lm_bounds(struct drm_crtc *crtc, · 323 unmodified lines
422 drm_mode_debug_printmodeline(adj_mode);425 drm_mode_debug_printmodeline(adj_mode);
423}426}
424 427
428static void _dpu_crtc_get_pcc_coeff(struct drm_crtc_state *state,
429 struct dpu_hw_pcc_cfg *cfg)
430{
431 struct drm_color_ctm *ctm;
432
433 memset(cfg, 0, sizeof(struct dpu_hw_pcc_cfg));
434
435 ctm = (struct drm_color_ctm *)state->ctm->data;
436
437 if (!ctm)
438 return;
439
440 cfg->r.r = CONVERT_S3_15(ctm->matrix[0]);
441 cfg->g.r = CONVERT_S3_15(ctm->matrix[1]);
442 cfg->b.r = CONVERT_S3_15(ctm->matrix[2]);
443
444 cfg->r.g = CONVERT_S3_15(ctm->matrix[3]);
445 cfg->g.g = CONVERT_S3_15(ctm->matrix[4]);
446 cfg->b.g = CONVERT_S3_15(ctm->matrix[5]);
447
448 cfg->r.b = CONVERT_S3_15(ctm->matrix[6]);
449 cfg->g.b = CONVERT_S3_15(ctm->matrix[7]);
450 cfg->b.b = CONVERT_S3_15(ctm->matrix[8]);
451}
452
453static void _dpu_crtc_setup_cp_blocks(struct drm_crtc *crtc)
454{
455 struct drm_crtc_state *state = crtc->state;
456 struct dpu_crtc_state *cstate = to_dpu_crtc_state(crtc->state);
457 struct dpu_crtc_mixer *mixer = cstate->mixers;
458 struct dpu_hw_pcc_cfg cfg;
459 struct dpu_hw_ctl *ctl;
460 struct dpu_hw_mixer *lm;
461 struct dpu_hw_dspp *dspp;
462 int i;
463
464
465 if (!state->color_mgmt_changed)
466 return;
467
468 for (i = 0; i < cstate->num_mixers; i++) {
469 ctl = mixer[i].lm_ctl;
470 lm = mixer[i].hw_lm;
471 dspp = mixer[i].hw_dspp;
472
473 if (!dspp || !dspp->ops.setup_pcc)
474 continue;
475
476 if (!state->ctm) {
477 dspp->ops.setup_pcc(dspp, NULL);
478 } else {
479 _dpu_crtc_get_pcc_coeff(state, &cfg);
480 dspp->ops.setup_pcc(dspp, &cfg);
481 }
482
483 mixer[i].flush_mask |= ctl->ops.get_bitmask_dspp(ctl,
484 mixer[i].hw_dspp->idx);
485
486 /* stage config flush mask */
487 ctl->ops.update_pending_flush(ctl, mixer[i].flush_mask);
488
489 DPU_DEBUG("lm %d, ctl %d, flush mask 0x%x\n",
490 mixer[i].hw_lm->idx - DSPP_0,
491 ctl->idx - CTL_0,
492 mixer[i].flush_mask);
493 }
494}
495
425static void dpu_crtc_atomic_begin(struct drm_crtc *crtc,496static void dpu_crtc_atomic_begin(struct drm_crtc *crtc,
426 struct drm_crtc_state *old_state)497 struct drm_crtc_state *old_state)
427{498{
@@ -430,7 +501,6 @@ static void dpu_crtc_atomic_begin(struct drm_crtc *crtc, · 2 unmodified lines
430 struct drm_encoder *encoder;501 struct drm_encoder *encoder;
431 struct drm_device *dev;502 struct drm_device *dev;
432 unsigned long flags;503 unsigned long flags;
433 struct dpu_crtc_smmu_state_data *smmu_state;
434 504
435 if (!crtc) {505 if (!crtc) {
436 DPU_ERROR("invalid crtc\n");506 DPU_ERROR("invalid crtc\n");
@@ -448,7 +518,6 @@ static void dpu_crtc_atomic_begin(struct drm_crtc *crtc, · 11 unmodified lines
448 dpu_crtc = to_dpu_crtc(crtc);518 dpu_crtc = to_dpu_crtc(crtc);
449 cstate = to_dpu_crtc_state(crtc->state);519 cstate = to_dpu_crtc_state(crtc->state);
450 dev = crtc->dev;520 dev = crtc->dev;
451 smmu_state = &dpu_crtc->smmu_state;
452 521
453 _dpu_crtc_setup_lm_bounds(crtc, crtc->state);522 _dpu_crtc_setup_lm_bounds(crtc, crtc->state);
454 523
@@ -475,6 +544,8 @@ static void dpu_crtc_atomic_begin(struct drm_crtc *crtc, · 20 unmodified lines
475 544
476 _dpu_crtc_blend_setup(crtc);545 _dpu_crtc_blend_setup(crtc);
477 546
547 _dpu_crtc_setup_cp_blocks(crtc);
548
478 /*549 /*
479 * PP_DONE irq is only used by command mode for now.550 * PP_DONE irq is only used by command mode for now.
480 * It is better to request pending before FLUSH and START trigger551 * It is better to request pending before FLUSH and START trigger
@@ -491,7 +562,6 @@ static void dpu_crtc_atomic_flush(struct drm_crtc *crtc, · 10 unmodified lines
491 struct drm_device *dev;562 struct drm_device *dev;
492 struct drm_plane *plane;563 struct drm_plane *plane;
493 struct msm_drm_private *priv;564 struct msm_drm_private *priv;
494 struct msm_drm_thread *event_thread;
495 unsigned long flags;565 unsigned long flags;
496 struct dpu_crtc_state *cstate;566 struct dpu_crtc_state *cstate;
497 567
@@ -513,8 +583,6 @@ static void dpu_crtc_atomic_flush(struct drm_crtc *crtc, · 15 unmodified lines
513 return;583 return;
514 }584 }
515 585
516 event_thread = &priv->event_thread[crtc->index];
517
518 if (dpu_crtc->event) {586 if (dpu_crtc->event) {
519 DPU_DEBUG("already received dpu_crtc->event\n");587 DPU_DEBUG("already received dpu_crtc->event\n");
520 } else {588 } else {
@@ -567,7 +635,6 @@ static void dpu_crtc_atomic_flush(struct drm_crtc *crtc, · 46 unmodified lines
567static void dpu_crtc_destroy_state(struct drm_crtc *crtc,635static void dpu_crtc_destroy_state(struct drm_crtc *crtc,
568 struct drm_crtc_state *state)636 struct drm_crtc_state *state)
569{637{
570 struct dpu_crtc *dpu_crtc;
571 struct dpu_crtc_state *cstate;638 struct dpu_crtc_state *cstate;
572 639
573 if (!crtc || !state) {640 if (!crtc || !state) {
@@ -575,7 +642,6 @@ static void dpu_crtc_destroy_state(struct drm_crtc *crtc, · 1 unmodified line
575 return;642 return;
576 }643 }
577 644
578 dpu_crtc = to_dpu_crtc(crtc);
579 cstate = to_dpu_crtc_state(state);645 cstate = to_dpu_crtc_state(state);
580 646
581 DPU_DEBUG("crtc%d\n", crtc->base.id);647 DPU_DEBUG("crtc%d\n", crtc->base.id);
@@ -662,11 +728,9 @@ static void dpu_crtc_reset(struct drm_crtc *crtc) · 80 unmodified lines
662/**728/**
663 * dpu_crtc_duplicate_state - state duplicate hook729 * dpu_crtc_duplicate_state - state duplicate hook
664 * @crtc: Pointer to drm crtc structure730 * @crtc: Pointer to drm crtc structure
665 * @Returns: Pointer to new drm_crtc_state structure
666 */731 */
667static struct drm_crtc_state *dpu_crtc_duplicate_state(struct drm_crtc *crtc)732static struct drm_crtc_state *dpu_crtc_duplicate_state(struct drm_crtc *crtc)
668{733{
669 struct dpu_crtc *dpu_crtc;
670 struct dpu_crtc_state *cstate, *old_cstate;734 struct dpu_crtc_state *cstate, *old_cstate;
671 735
672 if (!crtc || !crtc->state) {736 if (!crtc || !crtc->state) {
@@ -674,7 +738,6 @@ static struct drm_crtc_state *dpu_crtc_duplicate_state(struct drm_crtc *crtc) · 1 unmodified line
674 return NULL;738 return NULL;
675 }739 }
676 740
677 dpu_crtc = to_dpu_crtc(crtc);
678 old_cstate = to_dpu_crtc_state(crtc->state);741 old_cstate = to_dpu_crtc_state(crtc->state);
679 cstate = kmemdup(old_cstate, sizeof(*old_cstate), GFP_KERNEL);742 cstate = kmemdup(old_cstate, sizeof(*old_cstate), GFP_KERNEL);
680 if (!cstate) {743 if (!cstate) {
@@ -693,9 +756,7 @@ static void dpu_crtc_disable(struct drm_crtc *crtc, · 12 unmodified lines
693{756{
694 struct dpu_crtc *dpu_crtc;757 struct dpu_crtc *dpu_crtc;
695 struct dpu_crtc_state *cstate;758 struct dpu_crtc_state *cstate;
696 struct drm_display_mode *mode;
697 struct drm_encoder *encoder;759 struct drm_encoder *encoder;
698 struct msm_drm_private *priv;
699 unsigned long flags;760 unsigned long flags;
700 bool release_bandwidth = false;761 bool release_bandwidth = false;
701 762
@@ -705,8 +766,6 @@ static void dpu_crtc_disable(struct drm_crtc *crtc, · 3 unmodified lines
705 }766 }
706 dpu_crtc = to_dpu_crtc(crtc);767 dpu_crtc = to_dpu_crtc(crtc);
707 cstate = to_dpu_crtc_state(crtc->state);768 cstate = to_dpu_crtc_state(crtc->state);
708 mode = &cstate->base.adjusted_mode;
709 priv = crtc->dev->dev_private;
710 769
711 DRM_DEBUG_KMS("crtc%d\n", crtc->base.id);770 DRM_DEBUG_KMS("crtc%d\n", crtc->base.id);
712 771
@@ -768,14 +827,12 @@ static void dpu_crtc_enable(struct drm_crtc *crtc, · 55 unmodified lines
768{827{
769 struct dpu_crtc *dpu_crtc;828 struct dpu_crtc *dpu_crtc;
770 struct drm_encoder *encoder;829 struct drm_encoder *encoder;
771 struct msm_drm_private *priv;
772 bool request_bandwidth;830 bool request_bandwidth;
773 831
774 if (!crtc) {832 if (!crtc) {
775 DPU_ERROR("invalid crtc\n");833 DPU_ERROR("invalid crtc\n");
776 return;834 return;
777 }835 }
778 priv = crtc->dev->dev_private;
779 836
780 pm_runtime_get_sync(crtc->dev->dev);837 pm_runtime_get_sync(crtc->dev->dev);
781 838
@@ -1319,6 +1376,8 @@ struct drm_crtc *dpu_crtc_init(struct drm_device *dev, struct drm_plane *plane, · 537 unmodified lines
1319 1376
1320 drm_crtc_helper_add(crtc, &dpu_crtc_helper_funcs);1377 drm_crtc_helper_add(crtc, &dpu_crtc_helper_funcs);
1321 1378
1379 drm_crtc_enable_color_mgmt(crtc, 0, true, 0);
1380
1322 /* save user friendly CRTC name for later */1381 /* save user friendly CRTC name for later */
1323 snprintf(dpu_crtc->name, DPU_CRTC_NAME_SIZE, "crtc%u", crtc->base.id);1382 snprintf(dpu_crtc->name, DPU_CRTC_NAME_SIZE, "crtc%u", crtc->base.id);
1324 1383
drivers/gpu/drm/msm/disp/dpu1/dpu_crtc.h+2−0
@@ -73,12 +73,14 @@ struct dpu_crtc_smmu_state_data { · 72 unmodified lines
73 * struct dpu_crtc_mixer: stores the map for each virtual pipeline in the CRTC73 * struct dpu_crtc_mixer: stores the map for each virtual pipeline in the CRTC
74 * @hw_lm: LM HW Driver context74 * @hw_lm: LM HW Driver context
75 * @lm_ctl: CTL Path HW driver context75 * @lm_ctl: CTL Path HW driver context
76 * @lm_dspp: DSPP HW driver context
76 * @mixer_op_mode: mixer blending operation mode77 * @mixer_op_mode: mixer blending operation mode
77 * @flush_mask: mixer flush mask for ctl, mixer and pipe78 * @flush_mask: mixer flush mask for ctl, mixer and pipe
78 */79 */
79struct dpu_crtc_mixer {80struct dpu_crtc_mixer {
80 struct dpu_hw_mixer *hw_lm;81 struct dpu_hw_mixer *hw_lm;
81 struct dpu_hw_ctl *lm_ctl;82 struct dpu_hw_ctl *lm_ctl;
83 struct dpu_hw_dspp *hw_dspp;
82 u32 mixer_op_mode;84 u32 mixer_op_mode;
83 u32 flush_mask;85 u32 flush_mask;
84};86};
drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c+11−1
@@ -20,6 +20,7 @@ · 19 unmodified lines
20#include "dpu_hw_catalog.h"20#include "dpu_hw_catalog.h"
21#include "dpu_hw_intf.h"21#include "dpu_hw_intf.h"
22#include "dpu_hw_ctl.h"22#include "dpu_hw_ctl.h"
23#include "dpu_hw_dspp.h"
23#include "dpu_formats.h"24#include "dpu_formats.h"
24#include "dpu_encoder_phys.h"25#include "dpu_encoder_phys.h"
25#include "dpu_crtc.h"26#include "dpu_crtc.h"
@@ -536,6 +537,7 @@ static struct msm_display_topology dpu_encoder_get_topology( · 510 unmodified lines
536 * 1 LM, 1 INTF537 * 1 LM, 1 INTF
537 * 2 LM, 1 INTF (stream merge to support high resolution interfaces)538 * 2 LM, 1 INTF (stream merge to support high resolution interfaces)
538 *539 *
540 * Adding color blocks only to primary interface
539 */541 */
540 if (intf_count == 2)542 if (intf_count == 2)
541 topology.num_lm = 2;543 topology.num_lm = 2;
@@ -544,6 +546,9 @@ static struct msm_display_topology dpu_encoder_get_topology( · 2 unmodified lines
544 else546 else
545 topology.num_lm = (mode->hdisplay > MAX_HDISPLAY_SPLIT) ? 2 : 1;547 topology.num_lm = (mode->hdisplay > MAX_HDISPLAY_SPLIT) ? 2 : 1;
546 548
549 if (dpu_enc->disp_info.intf_type == DRM_MODE_ENCODER_DSI)
550 topology.num_dspp = topology.num_lm;
551
547 topology.num_enc = 0;552 topology.num_enc = 0;
548 topology.num_intf = intf_count;553 topology.num_intf = intf_count;
549 554
@@ -959,7 +964,8 @@ static void dpu_encoder_virt_mode_set(struct drm_encoder *drm_enc, · 409 unmodified lines
959 struct dpu_hw_blk *hw_pp[MAX_CHANNELS_PER_ENC];964 struct dpu_hw_blk *hw_pp[MAX_CHANNELS_PER_ENC];
960 struct dpu_hw_blk *hw_ctl[MAX_CHANNELS_PER_ENC];965 struct dpu_hw_blk *hw_ctl[MAX_CHANNELS_PER_ENC];
961 struct dpu_hw_blk *hw_lm[MAX_CHANNELS_PER_ENC];966 struct dpu_hw_blk *hw_lm[MAX_CHANNELS_PER_ENC];
962 int num_lm, num_ctl, num_pp;967 struct dpu_hw_blk *hw_dspp[MAX_CHANNELS_PER_ENC] = { NULL };
968 int num_lm, num_ctl, num_pp, num_dspp;
963 int i, j;969 int i, j;
964 970
965 if (!drm_enc) {971 if (!drm_enc) {
@@ -1008,6 +1014,9 @@ static void dpu_encoder_virt_mode_set(struct drm_encoder *drm_enc, · 42 unmodified lines
1008 drm_enc->base.id, DPU_HW_BLK_CTL, hw_ctl, ARRAY_SIZE(hw_ctl));1014 drm_enc->base.id, DPU_HW_BLK_CTL, hw_ctl, ARRAY_SIZE(hw_ctl));
1009 num_lm = dpu_rm_get_assigned_resources(&dpu_kms->rm, global_state,1015 num_lm = dpu_rm_get_assigned_resources(&dpu_kms->rm, global_state,
1010 drm_enc->base.id, DPU_HW_BLK_LM, hw_lm, ARRAY_SIZE(hw_lm));1016 drm_enc->base.id, DPU_HW_BLK_LM, hw_lm, ARRAY_SIZE(hw_lm));
1017 num_dspp = dpu_rm_get_assigned_resources(&dpu_kms->rm, global_state,
1018 drm_enc->base.id, DPU_HW_BLK_DSPP, hw_dspp,
1019 ARRAY_SIZE(hw_dspp));
1011 1020
1012 for (i = 0; i < MAX_CHANNELS_PER_ENC; i++)1021 for (i = 0; i < MAX_CHANNELS_PER_ENC; i++)
1013 dpu_enc->hw_pp[i] = i < num_pp ? to_dpu_hw_pingpong(hw_pp[i])1022 dpu_enc->hw_pp[i] = i < num_pp ? to_dpu_hw_pingpong(hw_pp[i])
@@ -1020,6 +1029,7 @@ static void dpu_encoder_virt_mode_set(struct drm_encoder *drm_enc, · 6 unmodified lines
1020 1029
1021 cstate->mixers[i].hw_lm = to_dpu_hw_mixer(hw_lm[i]);1030 cstate->mixers[i].hw_lm = to_dpu_hw_mixer(hw_lm[i]);
1022 cstate->mixers[i].lm_ctl = to_dpu_hw_ctl(hw_ctl[ctl_idx]);1031 cstate->mixers[i].lm_ctl = to_dpu_hw_ctl(hw_ctl[ctl_idx]);
1032 cstate->mixers[i].hw_dspp = to_dpu_hw_dspp(hw_dspp[i]);
1023 }1033 }
1024 1034
1025 cstate->num_mixers = num_lm;1035 cstate->num_mixers = num_lm;
drivers/gpu/drm/msm/disp/dpu1/dpu_hw_catalog.c+36−12
@@ -41,6 +41,8 @@ · 40 unmodified lines
41#define PINGPONG_SDM845_SPLIT_MASK \41#define PINGPONG_SDM845_SPLIT_MASK \
42 (PINGPONG_SDM845_MASK | BIT(DPU_PINGPONG_TE2))42 (PINGPONG_SDM845_MASK | BIT(DPU_PINGPONG_TE2))
43 43
44#define DSPP_SC7180_MASK BIT(DPU_DSPP_PCC)
45
44#define DEFAULT_PIXEL_RAM_SIZE (50 * 1024)46#define DEFAULT_PIXEL_RAM_SIZE (50 * 1024)
45#define DEFAULT_DPU_LINE_WIDTH 204847#define DEFAULT_DPU_LINE_WIDTH 2048
46#define DEFAULT_DPU_OUTPUT_LINE_WIDTH 256048#define DEFAULT_DPU_OUTPUT_LINE_WIDTH 2560
@@ -291,29 +293,30 @@ static const struct dpu_lm_sub_blks sdm845_lm_sblk = { · 244 unmodified lines
291 },293 },
292};294};
293 295
294#define LM_BLK(_name, _id, _base, _fmask, _sblk, _pp, _lmpair) \296#define LM_BLK(_name, _id, _base, _fmask, _sblk, _pp, _lmpair, _dspp) \
295 { \297 { \
296 .name = _name, .id = _id, \298 .name = _name, .id = _id, \
297 .base = _base, .len = 0x320, \299 .base = _base, .len = 0x320, \
298 .features = _fmask, \300 .features = _fmask, \
299 .sblk = _sblk, \301 .sblk = _sblk, \
300 .pingpong = _pp, \302 .pingpong = _pp, \
301 .lm_pair_mask = (1 << _lmpair) \303 .lm_pair_mask = (1 << _lmpair), \
304 .dspp = _dspp \
302 }305 }
303 306
304static const struct dpu_lm_cfg sdm845_lm[] = {307static const struct dpu_lm_cfg sdm845_lm[] = {
305 LM_BLK("lm_0", LM_0, 0x44000, MIXER_SDM845_MASK,308 LM_BLK("lm_0", LM_0, 0x44000, MIXER_SDM845_MASK,
306 &sdm845_lm_sblk, PINGPONG_0, LM_1),309 &sdm845_lm_sblk, PINGPONG_0, LM_1, 0),
307 LM_BLK("lm_1", LM_1, 0x45000, MIXER_SDM845_MASK,310 LM_BLK("lm_1", LM_1, 0x45000, MIXER_SDM845_MASK,
308 &sdm845_lm_sblk, PINGPONG_1, LM_0),311 &sdm845_lm_sblk, PINGPONG_1, LM_0, 0),
309 LM_BLK("lm_2", LM_2, 0x46000, MIXER_SDM845_MASK,312 LM_BLK("lm_2", LM_2, 0x46000, MIXER_SDM845_MASK,
310 &sdm845_lm_sblk, PINGPONG_2, LM_5),313 &sdm845_lm_sblk, PINGPONG_2, LM_5, 0),
311 LM_BLK("lm_3", LM_3, 0x0, MIXER_SDM845_MASK,314 LM_BLK("lm_3", LM_3, 0x0, MIXER_SDM845_MASK,
312 &sdm845_lm_sblk, PINGPONG_MAX, 0),315 &sdm845_lm_sblk, PINGPONG_MAX, 0, 0),
313 LM_BLK("lm_4", LM_4, 0x0, MIXER_SDM845_MASK,316 LM_BLK("lm_4", LM_4, 0x0, MIXER_SDM845_MASK,
314 &sdm845_lm_sblk, PINGPONG_MAX, 0),317 &sdm845_lm_sblk, PINGPONG_MAX, 0, 0),
315 LM_BLK("lm_5", LM_5, 0x49000, MIXER_SDM845_MASK,318 LM_BLK("lm_5", LM_5, 0x49000, MIXER_SDM845_MASK,
316 &sdm845_lm_sblk, PINGPONG_3, LM_2),319 &sdm845_lm_sblk, PINGPONG_3, LM_2, 0),
317};320};
318 321
319/* SC7180 */322/* SC7180 */
@@ -328,11 +331,30 @@ static const struct dpu_lm_sub_blks sc7180_lm_sblk = { · 8 unmodified lines
328 331
329static const struct dpu_lm_cfg sc7180_lm[] = {332static const struct dpu_lm_cfg sc7180_lm[] = {
330 LM_BLK("lm_0", LM_0, 0x44000, MIXER_SC7180_MASK,333 LM_BLK("lm_0", LM_0, 0x44000, MIXER_SC7180_MASK,
331 &sc7180_lm_sblk, PINGPONG_0, LM_1),334 &sc7180_lm_sblk, PINGPONG_0, LM_1, DSPP_0),
332 LM_BLK("lm_1", LM_1, 0x45000, MIXER_SC7180_MASK,335 LM_BLK("lm_1", LM_1, 0x45000, MIXER_SC7180_MASK,
333 &sc7180_lm_sblk, PINGPONG_1, LM_0),336 &sc7180_lm_sblk, PINGPONG_1, LM_0, 0),
337};
338
339/*************************************************************
340 * DSPP sub blocks config
341 *************************************************************/
342static const struct dpu_dspp_sub_blks sc7180_dspp_sblk = {
343 .pcc = {.id = DPU_DSPP_PCC, .base = 0x1700,
344 .len = 0x90, .version = 0x10000},
334};345};
335 346
347#define DSPP_BLK(_name, _id, _base) \
348 {\
349 .name = _name, .id = _id, \
350 .base = _base, .len = 0x1800, \
351 .features = DSPP_SC7180_MASK, \
352 .sblk = &sc7180_dspp_sblk \
353 }
354
355static const struct dpu_dspp_cfg sc7180_dspp[] = {
356 DSPP_BLK("dspp_0", DSPP_0, 0x54000),
357};
336/*************************************************************358/*************************************************************
337 * PINGPONG sub blocks config359 * PINGPONG sub blocks config
338 *************************************************************/360 *************************************************************/
@@ -515,8 +537,8 @@ static const struct dpu_perf_cfg sdm845_perf_data = { · 176 unmodified lines
515};537};
516 538
517static const struct dpu_perf_cfg sc7180_perf_data = {539static const struct dpu_perf_cfg sc7180_perf_data = {
518 .max_bw_low = 3900000,540 .max_bw_low = 6800000,
519 .max_bw_high = 5500000,541 .max_bw_high = 6800000,
520 .min_core_ib = 2400000,542 .min_core_ib = 2400000,
521 .min_llcc_ib = 800000,543 .min_llcc_ib = 800000,
522 .min_dram_ib = 800000,544 .min_dram_ib = 800000,
@@ -587,6 +609,8 @@ static void sc7180_cfg_init(struct dpu_mdss_cfg *dpu_cfg) · 64 unmodified lines
587 .sspp = sc7180_sspp,609 .sspp = sc7180_sspp,
588 .mixer_count = ARRAY_SIZE(sc7180_lm),610 .mixer_count = ARRAY_SIZE(sc7180_lm),
589 .mixer = sc7180_lm,611 .mixer = sc7180_lm,
612 .dspp_count = ARRAY_SIZE(sc7180_dspp),
613 .dspp = sc7180_dspp,
590 .pingpong_count = ARRAY_SIZE(sc7180_pp),614 .pingpong_count = ARRAY_SIZE(sc7180_pp),
591 .pingpong = sc7180_pp,615 .pingpong = sc7180_pp,
592 .intf_count = ARRAY_SIZE(sc7180_intf),616 .intf_count = ARRAY_SIZE(sc7180_intf),
drivers/gpu/drm/msm/disp/dpu1/dpu_hw_catalog.h+39−0
@@ -145,6 +145,17 @@ enum { · 144 unmodified lines
145 DPU_MIXER_MAX145 DPU_MIXER_MAX
146};146};
147 147
148/**
149 * DSPP sub-blocks
150 * @DPU_DSPP_PCC Panel color correction block
151 * @DPU_DSPP_GC Gamma correction block
152 */
153enum {
154 DPU_DSPP_PCC = 0x1,
155 DPU_DSPP_GC,
156 DPU_DSPP_MAX
157};
158
148/**159/**
149 * PINGPONG sub-blocks160 * PINGPONG sub-blocks
150 * @DPU_PINGPONG_TE Tear check block161 * @DPU_PINGPONG_TE Tear check block
@@ -377,6 +388,16 @@ struct dpu_lm_sub_blks { · 226 unmodified lines
377 struct dpu_pp_blk gc;388 struct dpu_pp_blk gc;
378};389};
379 390
391/**
392 * struct dpu_dspp_sub_blks: Information of DSPP block
393 * @gc : gamma correction block
394 * @pcc: pixel color correction block
395 */
396struct dpu_dspp_sub_blks {
397 struct dpu_pp_blk gc;
398 struct dpu_pp_blk pcc;
399};
400
380struct dpu_pingpong_sub_blks {401struct dpu_pingpong_sub_blks {
381 struct dpu_pp_blk te;402 struct dpu_pp_blk te;
382 struct dpu_pp_blk te2;403 struct dpu_pp_blk te2;
@@ -471,9 +492,23 @@ struct dpu_lm_cfg { · 88 unmodified lines
471 DPU_HW_BLK_INFO;492 DPU_HW_BLK_INFO;
472 const struct dpu_lm_sub_blks *sblk;493 const struct dpu_lm_sub_blks *sblk;
473 u32 pingpong;494 u32 pingpong;
495 u32 dspp;
474 unsigned long lm_pair_mask;496 unsigned long lm_pair_mask;
475};497};
476 498
499/**
500 * struct dpu_dspp_cfg - information of DSPP blocks
501 * @id enum identifying this block
502 * @base register offset of this block
503 * @features bit mask identifying sub-blocks/features
504 * supported by this block
505 * @sblk sub-blocks information
506 */
507struct dpu_dspp_cfg {
508 DPU_HW_BLK_INFO;
509 const struct dpu_dspp_sub_blks *sblk;
510};
511
477/**512/**
478 * struct dpu_pingpong_cfg - information of PING-PONG blocks513 * struct dpu_pingpong_cfg - information of PING-PONG blocks
479 * @id enum identifying this block514 * @id enum identifying this block
@@ -688,6 +723,9 @@ struct dpu_mdss_cfg { · 208 unmodified lines
688 723
689 u32 ad_count;724 u32 ad_count;
690 725
726 u32 dspp_count;
727 const struct dpu_dspp_cfg *dspp;
728
691 /* Add additional block data structures here */729 /* Add additional block data structures here */
692 730
693 struct dpu_perf_cfg perf;731 struct dpu_perf_cfg perf;
@@ -716,6 +754,7 @@ struct dpu_mdss_hw_cfg_handler { · 22 unmodified lines
716#define BLK_PINGPONG(s) ((s)->pingpong)754#define BLK_PINGPONG(s) ((s)->pingpong)
717#define BLK_INTF(s) ((s)->intf)755#define BLK_INTF(s) ((s)->intf)
718#define BLK_AD(s) ((s)->ad)756#define BLK_AD(s) ((s)->ad)
757#define BLK_DSPP(s) ((s)->dspp)
719 758
720/**759/**
721 * dpu_hw_catalog_init - dpu hardware catalog init API retrieves760 * dpu_hw_catalog_init - dpu hardware catalog init API retrieves
drivers/gpu/drm/msm/disp/dpu1/dpu_hw_ctl.c+26−0
@@ -272,6 +272,31 @@ static int dpu_hw_ctl_active_get_bitmask_intf(struct dpu_hw_ctl *ctx, · 271 unmodified lines
272 return 0;272 return 0;
273}273}
274 274
275static uint32_t dpu_hw_ctl_get_bitmask_dspp(struct dpu_hw_ctl *ctx,
276 enum dpu_dspp dspp)
277{
278 uint32_t flushbits = 0;
279
280 switch (dspp) {
281 case DSPP_0:
282 flushbits = BIT(13);
283 break;
284 case DSPP_1:
285 flushbits = BIT(14);
286 break;
287 case DSPP_2:
288 flushbits = BIT(15);
289 break;
290 case DSPP_3:
291 flushbits = BIT(21);
292 break;
293 default:
294 return 0;
295 }
296
297 return flushbits;
298}
299
275static u32 dpu_hw_ctl_poll_reset_status(struct dpu_hw_ctl *ctx, u32 timeout_us)300static u32 dpu_hw_ctl_poll_reset_status(struct dpu_hw_ctl *ctx, u32 timeout_us)
276{301{
277 struct dpu_hw_blk_reg_map *c = &ctx->hw;302 struct dpu_hw_blk_reg_map *c = &ctx->hw;
@@ -548,6 +573,7 @@ static void _setup_ctl_ops(struct dpu_hw_ctl_ops *ops, · 270 unmodified lines
548 ops->setup_blendstage = dpu_hw_ctl_setup_blendstage;573 ops->setup_blendstage = dpu_hw_ctl_setup_blendstage;
549 ops->get_bitmask_sspp = dpu_hw_ctl_get_bitmask_sspp;574 ops->get_bitmask_sspp = dpu_hw_ctl_get_bitmask_sspp;
550 ops->get_bitmask_mixer = dpu_hw_ctl_get_bitmask_mixer;575 ops->get_bitmask_mixer = dpu_hw_ctl_get_bitmask_mixer;
576 ops->get_bitmask_dspp = dpu_hw_ctl_get_bitmask_dspp;
551};577};
552 578
553static struct dpu_hw_blk_ops dpu_hw_ops;579static struct dpu_hw_blk_ops dpu_hw_ops;
drivers/gpu/drm/msm/disp/dpu1/dpu_hw_ctl.h+3−0
@@ -139,6 +139,9 @@ struct dpu_hw_ctl_ops { · 138 unmodified lines
139 uint32_t (*get_bitmask_mixer)(struct dpu_hw_ctl *ctx,139 uint32_t (*get_bitmask_mixer)(struct dpu_hw_ctl *ctx,
140 enum dpu_lm blk);140 enum dpu_lm blk);
141 141
142 uint32_t (*get_bitmask_dspp)(struct dpu_hw_ctl *ctx,
143 enum dpu_dspp blk);
144
142 /**145 /**
143 * Query the value of the intf flush mask146 * Query the value of the intf flush mask
144 * No effect on hardware147 * No effect on hardware
drivers/gpu/drm/msm/disp/dpu1/dpu_hw_dspp.c+129−0
@@ -0,0 +1,129 @@
1// SPDX-License-Identifier: GPL-2.0-only
2/* Copyright (c) 2015-2018, The Linux Foundation. All rights reserved.
3 */
4
5#include "dpu_hwio.h"
6#include "dpu_hw_catalog.h"
7#include "dpu_hw_lm.h"
8#include "dpu_hw_dspp.h"
9#include "dpu_kms.h"
10
11
12/* DSPP_PCC */
13#define PCC_EN BIT(0)
14#define PCC_DIS 0
15#define PCC_RED_R_OFF 0x10
16#define PCC_RED_G_OFF 0x1C
17#define PCC_RED_B_OFF 0x28
18#define PCC_GREEN_R_OFF 0x14
19#define PCC_GREEN_G_OFF 0x20
20#define PCC_GREEN_B_OFF 0x2C
21#define PCC_BLUE_R_OFF 0x18
22#define PCC_BLUE_G_OFF 0x24
23#define PCC_BLUE_B_OFF 0x30
24
25static void dpu_setup_dspp_pcc(struct dpu_hw_dspp *ctx,
26 struct dpu_hw_pcc_cfg *cfg)
27{
28
29 u32 base = ctx->cap->sblk->pcc.base;
30
31 if (!ctx || !base) {
32 DRM_ERROR("invalid ctx %pK pcc base 0x%x\n", ctx, base);
33 return;
34 }
35
36 if (!cfg) {
37 DRM_DEBUG_DRIVER("disable pcc feature\n");
38 DPU_REG_WRITE(&ctx->hw, base, PCC_DIS);
39 return;
40 }
41
42 DPU_REG_WRITE(&ctx->hw, base + PCC_RED_R_OFF, cfg->r.r);
43 DPU_REG_WRITE(&ctx->hw, base + PCC_RED_G_OFF, cfg->r.g);
44 DPU_REG_WRITE(&ctx->hw, base + PCC_RED_B_OFF, cfg->r.b);
45
46 DPU_REG_WRITE(&ctx->hw, base + PCC_GREEN_R_OFF, cfg->g.r);
47 DPU_REG_WRITE(&ctx->hw, base + PCC_GREEN_G_OFF, cfg->g.g);
48 DPU_REG_WRITE(&ctx->hw, base + PCC_GREEN_B_OFF, cfg->g.b);
49
50 DPU_REG_WRITE(&ctx->hw, base + PCC_BLUE_R_OFF, cfg->b.r);
51 DPU_REG_WRITE(&ctx->hw, base + PCC_BLUE_G_OFF, cfg->b.g);
52 DPU_REG_WRITE(&ctx->hw, base + PCC_BLUE_B_OFF, cfg->b.b);
53
54 DPU_REG_WRITE(&ctx->hw, base, PCC_EN);
55}
56
57static void _setup_dspp_ops(struct dpu_hw_dspp *c,
58 unsigned long features)
59{
60 if (test_bit(DPU_DSPP_PCC, &features) &&
61 IS_SC7180_TARGET(c->hw.hwversion))
62 c->ops.setup_pcc = dpu_setup_dspp_pcc;
63}
64
65static const struct dpu_dspp_cfg *_dspp_offset(enum dpu_dspp dspp,
66 const struct dpu_mdss_cfg *m,
67 void __iomem *addr,
68 struct dpu_hw_blk_reg_map *b)
69{
70 int i;
71
72 if (!m || !addr || !b)
73 return ERR_PTR(-EINVAL);
74
75 for (i = 0; i < m->dspp_count; i++) {
76 if (dspp == m->dspp[i].id) {
77 b->base_off = addr;
78 b->blk_off = m->dspp[i].base;
79 b->length = m->dspp[i].len;
80 b->hwversion = m->hwversion;
81 b->log_mask = DPU_DBG_MASK_DSPP;
82 return &m->dspp[i];
83 }
84 }
85
86 return ERR_PTR(-EINVAL);
87}
88
89static struct dpu_hw_blk_ops dpu_hw_ops;
90
91struct dpu_hw_dspp *dpu_hw_dspp_init(enum dpu_dspp idx,
92 void __iomem *addr,
93 const struct dpu_mdss_cfg *m)
94{
95 struct dpu_hw_dspp *c;
96 const struct dpu_dspp_cfg *cfg;
97
98 if (!addr || !m)
99 return ERR_PTR(-EINVAL);
100
101 c = kzalloc(sizeof(*c), GFP_KERNEL);
102 if (!c)
103 return ERR_PTR(-ENOMEM);
104
105 cfg = _dspp_offset(idx, m, addr, &c->hw);
106 if (IS_ERR_OR_NULL(cfg)) {
107 kfree(c);
108 return ERR_PTR(-EINVAL);
109 }
110
111 /* Assign ops */
112 c->idx = idx;
113 c->cap = cfg;
114 _setup_dspp_ops(c, c->cap->features);
115
116 dpu_hw_blk_init(&c->base, DPU_HW_BLK_DSPP, idx, &dpu_hw_ops);
117
118 return c;
119}
120
121void dpu_hw_dspp_destroy(struct dpu_hw_dspp *dspp)
122{
123 if (dspp)
124 dpu_hw_blk_destroy(&dspp->base);
125
126 kfree(dspp);
127}
128
129
drivers/gpu/drm/msm/disp/dpu1/dpu_hw_dspp.h+100−0
@@ -0,0 +1,100 @@
1/* SPDX-License-Identifier: GPL-2.0-only */
2/* Copyright (c) 2015-2018, The Linux Foundation. All rights reserved.
3 */
4
5#ifndef _DPU_HW_DSPP_H
6#define _DPU_HW_DSPP_H
7
8#include "dpu_hw_blk.h"
9
10struct dpu_hw_dspp;
11
12/**
13 * struct dpu_hw_pcc_coeff - PCC coefficient structure for each color
14 * component.
15 * @r: red coefficient.
16 * @g: green coefficient.
17 * @b: blue coefficient.
18 */
19
20struct dpu_hw_pcc_coeff {
21 __u32 r;
22 __u32 g;
23 __u32 b;
24};
25
26/**
27 * struct dpu_hw_pcc - pcc feature structure
28 * @r: red coefficients.
29 * @g: green coefficients.
30 * @b: blue coefficients.
31 */
32struct dpu_hw_pcc_cfg {
33 struct dpu_hw_pcc_coeff r;
34 struct dpu_hw_pcc_coeff g;
35 struct dpu_hw_pcc_coeff b;
36};
37
38/**
39 * struct dpu_hw_dspp_ops - interface to the dspp hardware driver functions
40 * Caller must call the init function to get the dspp context for each dspp
41 * Assumption is these functions will be called after clocks are enabled
42 */
43struct dpu_hw_dspp_ops {
44 /**
45 * setup_pcc - setup dspp pcc
46 * @ctx: Pointer to dspp context
47 * @cfg: Pointer to configuration
48 */
49 void (*setup_pcc)(struct dpu_hw_dspp *ctx, struct dpu_hw_pcc_cfg *cfg);
50
51};
52
53/**
54 * struct dpu_hw_dspp - dspp description
55 * @base: Hardware block base structure
56 * @hw: Block hardware details
57 * @idx: DSPP index
58 * @cap: Pointer to layer_cfg
59 * @ops: Pointer to operations possible for this DSPP
60 */
61struct dpu_hw_dspp {
62 struct dpu_hw_blk base;
63 struct dpu_hw_blk_reg_map hw;
64
65 /* dspp */
66 int idx;
67 const struct dpu_dspp_cfg *cap;
68
69 /* Ops */
70 struct dpu_hw_dspp_ops ops;
71};
72
73/**
74 * dpu_hw_dspp - convert base object dpu_hw_base to container
75 * @hw: Pointer to base hardware block
76 * return: Pointer to hardware block container
77 */
78static inline struct dpu_hw_dspp *to_dpu_hw_dspp(struct dpu_hw_blk *hw)
79{
80 return container_of(hw, struct dpu_hw_dspp, base);
81}
82
83/**
84 * dpu_hw_dspp_init - initializes the dspp hw driver object.
85 * should be called once before accessing every dspp.
86 * @idx: DSPP index for which driver object is required
87 * @addr: Mapped register io address of MDP
88 * @Return: pointer to structure or ERR_PTR
89 */
90struct dpu_hw_dspp *dpu_hw_dspp_init(enum dpu_dspp idx,
91 void __iomem *addr, const struct dpu_mdss_cfg *m);
92
93/**
94 * dpu_hw_dspp_destroy(): Destroys DSPP driver context
95 * @dspp: Pointer to DSPP driver context
96 */
97void dpu_hw_dspp_destroy(struct dpu_hw_dspp *dspp);
98
99#endif /*_DPU_HW_DSPP_H */
100
drivers/gpu/drm/msm/disp/dpu1/dpu_hw_mdss.h+2−0
@@ -95,6 +95,7 @@ enum dpu_hw_blk_type { · 94 unmodified lines
95 DPU_HW_BLK_PINGPONG,95 DPU_HW_BLK_PINGPONG,
96 DPU_HW_BLK_INTF,96 DPU_HW_BLK_INTF,
97 DPU_HW_BLK_WB,97 DPU_HW_BLK_WB,
98 DPU_HW_BLK_DSPP,
98 DPU_HW_BLK_MAX,99 DPU_HW_BLK_MAX,
99};100};
100 101
@@ -425,5 +426,6 @@ struct dpu_mdss_color { · 324 unmodified lines
425#define DPU_DBG_MASK_TOP (1 << 7)426#define DPU_DBG_MASK_TOP (1 << 7)
426#define DPU_DBG_MASK_VBIF (1 << 8)427#define DPU_DBG_MASK_VBIF (1 << 8)
427#define DPU_DBG_MASK_ROT (1 << 9)428#define DPU_DBG_MASK_ROT (1 << 9)
429#define DPU_DBG_MASK_DSPP (1 << 10)
428 430
429#endif /* _DPU_HW_MDSS_H */431#endif /* _DPU_HW_MDSS_H */
drivers/gpu/drm/msm/disp/dpu1/dpu_kms.c+5−13
@@ -772,29 +772,21 @@ static int _dpu_kms_mmu_init(struct dpu_kms *dpu_kms) · 771 unmodified lines
772{772{
773 struct iommu_domain *domain;773 struct iommu_domain *domain;
774 struct msm_gem_address_space *aspace;774 struct msm_gem_address_space *aspace;
775 int ret;775 struct msm_mmu *mmu;
776 776
777 domain = iommu_domain_alloc(&platform_bus_type);777 domain = iommu_domain_alloc(&platform_bus_type);
778 if (!domain)778 if (!domain)
779 return 0;779 return 0;
780 780
781 domain->geometry.aperture_start = 0x1000;781 mmu = msm_iommu_new(dpu_kms->dev->dev, domain);
782 domain->geometry.aperture_end = 0xffffffff;782 aspace = msm_gem_address_space_create(mmu, "dpu1",
783 0x1000, 0xfffffff);
783 784
784 aspace = msm_gem_address_space_create(dpu_kms->dev->dev,
785 domain, "dpu1");
786 if (IS_ERR(aspace)) {785 if (IS_ERR(aspace)) {
787 iommu_domain_free(domain);786 mmu->funcs->destroy(mmu);
788 return PTR_ERR(aspace);787 return PTR_ERR(aspace);
789 }788 }
790 789
791 ret = aspace->mmu->funcs->attach(aspace->mmu);
792 if (ret) {
793 DPU_ERROR("failed to attach iommu %d\n", ret);
794 msm_gem_address_space_put(aspace);
795 return ret;
796 }
797
798 dpu_kms->base.aspace = aspace;790 dpu_kms->base.aspace = aspace;
799 return 0;791 return 0;
800}792}
drivers/gpu/drm/msm/disp/dpu1/dpu_kms.h+1−0
@@ -158,6 +158,7 @@ struct dpu_global_state { · 157 unmodified lines
158 uint32_t mixer_to_enc_id[LM_MAX - LM_0];158 uint32_t mixer_to_enc_id[LM_MAX - LM_0];
159 uint32_t ctl_to_enc_id[CTL_MAX - CTL_0];159 uint32_t ctl_to_enc_id[CTL_MAX - CTL_0];
160 uint32_t intf_to_enc_id[INTF_MAX - INTF_0];160 uint32_t intf_to_enc_id[INTF_MAX - INTF_0];
161 uint32_t dspp_to_enc_id[DSPP_MAX - DSPP_0];
161};162};
162 163
163struct dpu_global_state164struct dpu_global_state
drivers/gpu/drm/msm/disp/dpu1/dpu_rm.c+54−4
@@ -9,6 +9,7 @@ · 8 unmodified lines
9#include "dpu_hw_ctl.h"9#include "dpu_hw_ctl.h"
10#include "dpu_hw_pingpong.h"10#include "dpu_hw_pingpong.h"
11#include "dpu_hw_intf.h"11#include "dpu_hw_intf.h"
12#include "dpu_hw_dspp.h"
12#include "dpu_encoder.h"13#include "dpu_encoder.h"
13#include "dpu_trace.h"14#include "dpu_trace.h"
14 15
@@ -174,6 +175,23 @@ int dpu_rm_init(struct dpu_rm *rm, · 159 unmodified lines
174 rm->ctl_blks[ctl->id - CTL_0] = &hw->base;175 rm->ctl_blks[ctl->id - CTL_0] = &hw->base;
175 }176 }
176 177
178 for (i = 0; i < cat->dspp_count; i++) {
179 struct dpu_hw_dspp *hw;
180 const struct dpu_dspp_cfg *dspp = &cat->dspp[i];
181
182 if (dspp->id < DSPP_0 || dspp->id >= DSPP_MAX) {
183 DPU_ERROR("skip dspp %d with invalid id\n", dspp->id);
184 continue;
185 }
186 hw = dpu_hw_dspp_init(dspp->id, mmio, cat);
187 if (IS_ERR_OR_NULL(hw)) {
188 rc = PTR_ERR(hw);
189 DPU_ERROR("failed dspp object creation: err %d\n", rc);
190 goto fail;
191 }
192 rm->dspp_blks[dspp->id - DSPP_0] = &hw->base;
193 }
194
177 return 0;195 return 0;
178 196
179fail:197fail:
@@ -222,12 +240,17 @@ static bool _dpu_rm_check_lm_peer(struct dpu_rm *rm, int primary_idx, · 42 unmodified lines
222 * if lm, and all other hardwired blocks connected to the lm (pp) is240 * if lm, and all other hardwired blocks connected to the lm (pp) is
223 * available and appropriate241 * available and appropriate
224 * @pp_idx: output parameter, index of pingpong block attached to the layer242 * @pp_idx: output parameter, index of pingpong block attached to the layer
225 * mixer in rm->pongpong_blks[].243 * mixer in rm->pingpong_blks[].
244 * @dspp_idx: output parameter, index of dspp block attached to the layer
245 * mixer in rm->dspp_blks[].
246 * @reqs: input parameter, rm requirements for HW blocks needed in the
247 * datapath.
226 * @Return: true if lm matches all requirements, false otherwise248 * @Return: true if lm matches all requirements, false otherwise
227 */249 */
228static bool _dpu_rm_check_lm_and_get_connected_blks(struct dpu_rm *rm,250static bool _dpu_rm_check_lm_and_get_connected_blks(struct dpu_rm *rm,
229 struct dpu_global_state *global_state,251 struct dpu_global_state *global_state,
230 uint32_t enc_id, int lm_idx, int *pp_idx)252 uint32_t enc_id, int lm_idx, int *pp_idx, int *dspp_idx,
253 struct dpu_rm_requirements *reqs)
231{254{
232 const struct dpu_lm_cfg *lm_cfg;255 const struct dpu_lm_cfg *lm_cfg;
233 int idx;256 int idx;
@@ -251,6 +274,23 @@ static bool _dpu_rm_check_lm_and_get_connected_blks(struct dpu_rm *rm, · 17 unmodified lines
251 return false;274 return false;
252 }275 }
253 *pp_idx = idx;276 *pp_idx = idx;
277
278 if (!reqs->topology.num_dspp)
279 return true;
280
281 idx = lm_cfg->dspp - DSPP_0;
282 if (idx < 0 || idx >= ARRAY_SIZE(rm->dspp_blks)) {
283 DPU_ERROR("failed to get dspp on lm %d\n", lm_cfg->dspp);
284 return false;
285 }
286
287 if (reserved_by_other(global_state->dspp_to_enc_id, idx, enc_id)) {
288 DPU_DEBUG("lm %d dspp %d already reserved\n", lm_cfg->id,
289 lm_cfg->dspp);
290 return false;
291 }
292 *dspp_idx = idx;
293
254 return true;294 return true;
255}295}
256 296
@@ -262,6 +302,7 @@ static int _dpu_rm_reserve_lms(struct dpu_rm *rm, · 5 unmodified lines
262{302{
263 int lm_idx[MAX_BLOCKS];303 int lm_idx[MAX_BLOCKS];
264 int pp_idx[MAX_BLOCKS];304 int pp_idx[MAX_BLOCKS];
305 int dspp_idx[MAX_BLOCKS] = {0};
265 int i, j, lm_count = 0;306 int i, j, lm_count = 0;
266 307
267 if (!reqs->topology.num_lm) {308 if (!reqs->topology.num_lm) {
@@ -279,7 +320,8 @@ static int _dpu_rm_reserve_lms(struct dpu_rm *rm, · 11 unmodified lines
279 lm_idx[lm_count] = i;320 lm_idx[lm_count] = i;
280 321
281 if (!_dpu_rm_check_lm_and_get_connected_blks(rm, global_state,322 if (!_dpu_rm_check_lm_and_get_connected_blks(rm, global_state,
282 enc_id, i, &pp_idx[lm_count])) {323 enc_id, i, &pp_idx[lm_count],
324 &dspp_idx[lm_count], reqs)) {
283 continue;325 continue;
284 }326 }
285 327
@@ -299,7 +341,8 @@ static int _dpu_rm_reserve_lms(struct dpu_rm *rm, · 13 unmodified lines
299 341
300 if (!_dpu_rm_check_lm_and_get_connected_blks(rm,342 if (!_dpu_rm_check_lm_and_get_connected_blks(rm,
301 global_state, enc_id, j,343 global_state, enc_id, j,
302 &pp_idx[lm_count])) {344 &pp_idx[lm_count], &dspp_idx[lm_count],
345 reqs)) {
303 continue;346 continue;
304 }347 }
305 348
@@ -316,6 +359,8 @@ static int _dpu_rm_reserve_lms(struct dpu_rm *rm, · 10 unmodified lines
316 for (i = 0; i < lm_count; i++) {359 for (i = 0; i < lm_count; i++) {
317 global_state->mixer_to_enc_id[lm_idx[i]] = enc_id;360 global_state->mixer_to_enc_id[lm_idx[i]] = enc_id;
318 global_state->pingpong_to_enc_id[pp_idx[i]] = enc_id;361 global_state->pingpong_to_enc_id[pp_idx[i]] = enc_id;
362 global_state->dspp_to_enc_id[dspp_idx[i]] =
363 reqs->topology.num_dspp ? enc_id : 0;
319 364
320 trace_dpu_rm_reserve_lms(lm_idx[i] + LM_0, enc_id,365 trace_dpu_rm_reserve_lms(lm_idx[i] + LM_0, enc_id,
321 pp_idx[i] + PINGPONG_0);366 pp_idx[i] + PINGPONG_0);
@@ -560,6 +605,11 @@ int dpu_rm_get_assigned_resources(struct dpu_rm *rm, · 238 unmodified lines
560 hw_to_enc_id = global_state->intf_to_enc_id;605 hw_to_enc_id = global_state->intf_to_enc_id;
561 max_blks = ARRAY_SIZE(rm->intf_blks);606 max_blks = ARRAY_SIZE(rm->intf_blks);
562 break;607 break;
608 case DPU_HW_BLK_DSPP:
609 hw_blks = rm->dspp_blks;
610 hw_to_enc_id = global_state->dspp_to_enc_id;
611 max_blks = ARRAY_SIZE(rm->dspp_blks);
612 break;
563 default:613 default:
564 DPU_ERROR("blk type %d not managed by rm\n", type);614 DPU_ERROR("blk type %d not managed by rm\n", type);
565 return 0;615 return 0;
drivers/gpu/drm/msm/disp/dpu1/dpu_rm.h+2−0
@@ -19,6 +19,7 @@ struct dpu_global_state; · 18 unmodified lines
19 * @mixer_blks: array of layer mixer hardware resources19 * @mixer_blks: array of layer mixer hardware resources
20 * @ctl_blks: array of ctl hardware resources20 * @ctl_blks: array of ctl hardware resources
21 * @intf_blks: array of intf hardware resources21 * @intf_blks: array of intf hardware resources
22 * @dspp_blks: array of dspp hardware resources
22 * @lm_max_width: cached layer mixer maximum width23 * @lm_max_width: cached layer mixer maximum width
23 * @rm_lock: resource manager mutex24 * @rm_lock: resource manager mutex
24 */25 */
@@ -27,6 +28,7 @@ struct dpu_rm { · 2 unmodified lines
27 struct dpu_hw_blk *mixer_blks[LM_MAX - LM_0];28 struct dpu_hw_blk *mixer_blks[LM_MAX - LM_0];
28 struct dpu_hw_blk *ctl_blks[CTL_MAX - CTL_0];29 struct dpu_hw_blk *ctl_blks[CTL_MAX - CTL_0];
29 struct dpu_hw_blk *intf_blks[INTF_MAX - INTF_0];30 struct dpu_hw_blk *intf_blks[INTF_MAX - INTF_0];
31 struct dpu_hw_blk *dspp_blks[DSPP_MAX - DSPP_0];
30 32
31 uint32_t lm_max_width;33 uint32_t lm_max_width;
32};34};
drivers/gpu/drm/msm/disp/mdp4/mdp4_kms.c+8−10
@@ -510,18 +510,20 @@ struct msm_kms *mdp4_kms_init(struct drm_device *dev) · 509 unmodified lines
510 mdelay(16);510 mdelay(16);
511 511
512 if (config->iommu) {512 if (config->iommu) {
513 aspace = msm_gem_address_space_create(&pdev->dev,513 struct msm_mmu *mmu = msm_iommu_new(&pdev->dev,
514 config->iommu, "mdp4");514 config->iommu);
515
516 aspace = msm_gem_address_space_create(mmu,
517 "mdp4", 0x1000, 0xffffffff);
518
515 if (IS_ERR(aspace)) {519 if (IS_ERR(aspace)) {
520 if (!IS_ERR(mmu))
521 mmu->funcs->destroy(mmu);
516 ret = PTR_ERR(aspace);522 ret = PTR_ERR(aspace);
517 goto fail;523 goto fail;
518 }524 }
519 525
520 kms->aspace = aspace;526 kms->aspace = aspace;
521
522 ret = aspace->mmu->funcs->attach(aspace->mmu);
523 if (ret)
524 goto fail;
525 } else {527 } else {
526 DRM_DEV_INFO(dev->dev, "no iommu, fallback to phys "528 DRM_DEV_INFO(dev->dev, "no iommu, fallback to phys "
527 "contig buffers for scanout\n");529 "contig buffers for scanout\n");
@@ -569,10 +571,6 @@ static struct mdp4_platform_config *mdp4_get_config(struct platform_device *dev) · 41 unmodified lines
569 /* TODO: Chips that aren't apq8064 have a 200 Mhz max_clk */571 /* TODO: Chips that aren't apq8064 have a 200 Mhz max_clk */
570 config.max_clk = 266667000;572 config.max_clk = 266667000;
571 config.iommu = iommu_domain_alloc(&platform_bus_type);573 config.iommu = iommu_domain_alloc(&platform_bus_type);
572 if (config.iommu) {
573 config.iommu->geometry.aperture_start = 0x1000;
574 config.iommu->geometry.aperture_end = 0xffffffff;
575 }
576 574
577 return &config;575 return &config;
578}576}
drivers/gpu/drm/msm/disp/mdp5/mdp5_cfg.c+76−4
@@ -342,6 +342,81 @@ static const struct mdp5_cfg_hw msm8x16_config = { · 341 unmodified lines
342 .max_clk = 320000000,342 .max_clk = 320000000,
343};343};
344 344
345static const struct mdp5_cfg_hw msm8x36_config = {
346 .name = "msm8x36",
347 .mdp = {
348 .count = 1,
349 .base = { 0x0 },
350 .caps = MDP_CAP_SMP |
351 0,
352 },
353 .smp = {
354 .mmb_count = 8,
355 .mmb_size = 10240,
356 .clients = {
357 [SSPP_VIG0] = 1, [SSPP_DMA0] = 4,
358 [SSPP_RGB0] = 7, [SSPP_RGB1] = 8,
359 },
360 },
361 .ctl = {
362 .count = 3,
363 .base = { 0x01000, 0x01200, 0x01400 },
364 .flush_hw_mask = 0x4003ffff,
365 },
366 .pipe_vig = {
367 .count = 1,
368 .base = { 0x04000 },
369 .caps = MDP_PIPE_CAP_HFLIP | MDP_PIPE_CAP_VFLIP |
370 MDP_PIPE_CAP_SCALE | MDP_PIPE_CAP_CSC |
371 MDP_PIPE_CAP_DECIMATION,
372 },
373 .pipe_rgb = {
374 .count = 2,
375 .base = { 0x14000, 0x16000 },
376 .caps = MDP_PIPE_CAP_HFLIP | MDP_PIPE_CAP_VFLIP |
377 MDP_PIPE_CAP_DECIMATION,
378 },
379 .pipe_dma = {
380 .count = 1,
381 .base = { 0x24000 },
382 .caps = MDP_PIPE_CAP_HFLIP | MDP_PIPE_CAP_VFLIP,
383 },
384 .lm = {
385 .count = 2,
386 .base = { 0x44000, 0x47000 },
387 .instances = {
388 { .id = 0, .pp = 0, .dspp = 0,
389 .caps = MDP_LM_CAP_DISPLAY, },
390 { .id = 1, .pp = -1, .dspp = -1,
391 .caps = MDP_LM_CAP_WB, },
392 },
393 .nb_stages = 8,
394 .max_width = 2560,
395 .max_height = 0xFFFF,
396 },
397 .pp = {
398 .count = 1,
399 .base = { 0x70000 },
400 },
401 .ad = {
402 .count = 1,
403 .base = { 0x78000 },
404 },
405 .dspp = {
406 .count = 1,
407 .base = { 0x54000 },
408 },
409 .intf = {
410 .base = { 0x00000, 0x6a800, 0x6b000 },
411 .connect = {
412 [0] = INTF_DISABLED,
413 [1] = INTF_DSI,
414 [2] = INTF_DSI,
415 },
416 },
417 .max_clk = 366670000,
418};
419
345static const struct mdp5_cfg_hw msm8x94_config = {420static const struct mdp5_cfg_hw msm8x94_config = {
346 .name = "msm8x94",421 .name = "msm8x94",
347 .mdp = {422 .mdp = {
@@ -840,6 +915,7 @@ static const struct mdp5_cfg_handler cfg_handlers_v1[] = { · 492 unmodified lines
840 { .revision = 2, .config = { .hw = &msm8x74v2_config } },915 { .revision = 2, .config = { .hw = &msm8x74v2_config } },
841 { .revision = 3, .config = { .hw = &apq8084_config } },916 { .revision = 3, .config = { .hw = &apq8084_config } },
842 { .revision = 6, .config = { .hw = &msm8x16_config } },917 { .revision = 6, .config = { .hw = &msm8x16_config } },
918 { .revision = 8, .config = { .hw = &msm8x36_config } },
843 { .revision = 9, .config = { .hw = &msm8x94_config } },919 { .revision = 9, .config = { .hw = &msm8x94_config } },
844 { .revision = 7, .config = { .hw = &msm8x96_config } },920 { .revision = 7, .config = { .hw = &msm8x96_config } },
845 { .revision = 11, .config = { .hw = &msm8x76_config } },921 { .revision = 11, .config = { .hw = &msm8x76_config } },
@@ -941,10 +1017,6 @@ static struct mdp5_cfg_platform *mdp5_get_config(struct platform_device *dev) · 95 unmodified lines
941 static struct mdp5_cfg_platform config = {};1017 static struct mdp5_cfg_platform config = {};
942 1018
943 config.iommu = iommu_domain_alloc(&platform_bus_type);1019 config.iommu = iommu_domain_alloc(&platform_bus_type);
944 if (config.iommu) {
945 config.iommu->geometry.aperture_start = 0x1000;
946 config.iommu->geometry.aperture_end = 0xffffffff;
947 }
948 1020
949 return &config;1021 return &config;
950}1022}
drivers/gpu/drm/msm/disp/mdp5/mdp5_crtc.c+2−2
@@ -959,7 +959,7 @@ static int mdp5_crtc_cursor_set(struct drm_crtc *crtc, · 958 unmodified lines
959 if (!ctl)959 if (!ctl)
960 return -EINVAL;960 return -EINVAL;
961 961
962 /* don't support LM cursors when we we have source split enabled */962 /* don't support LM cursors when we have source split enabled */
963 if (mdp5_cstate->pipeline.r_mixer)963 if (mdp5_cstate->pipeline.r_mixer)
964 return -EINVAL;964 return -EINVAL;
965 965
@@ -1030,7 +1030,7 @@ static int mdp5_crtc_cursor_move(struct drm_crtc *crtc, int x, int y) · 64 unmodified lines
1030 return -EINVAL;1030 return -EINVAL;
1031 }1031 }
1032 1032
1033 /* don't support LM cursors when we we have source split enabled */1033 /* don't support LM cursors when we have source split enabled */
1034 if (mdp5_cstate->pipeline.r_mixer)1034 if (mdp5_cstate->pipeline.r_mixer)
1035 return -EINVAL;1035 return -EINVAL;
1036 1036
drivers/gpu/drm/msm/disp/mdp5/mdp5_kms.c+11−10
@@ -632,25 +632,25 @@ struct msm_kms *mdp5_kms_init(struct drm_device *dev) · 631 unmodified lines
632 mdelay(16);632 mdelay(16);
633 633
634 if (config->platform.iommu) {634 if (config->platform.iommu) {
635 struct msm_mmu *mmu;
636
635 iommu_dev = &pdev->dev;637 iommu_dev = &pdev->dev;
636 if (!dev_iommu_fwspec_get(iommu_dev))638 if (!dev_iommu_fwspec_get(iommu_dev))
637 iommu_dev = iommu_dev->parent;639 iommu_dev = iommu_dev->parent;
638 640
639 aspace = msm_gem_address_space_create(iommu_dev,641 mmu = msm_iommu_new(iommu_dev, config->platform.iommu);
640 config->platform.iommu, "mdp5");642
643 aspace = msm_gem_address_space_create(mmu, "mdp5",
644 0x1000, 0xffffffff);
645
641 if (IS_ERR(aspace)) {646 if (IS_ERR(aspace)) {
647 if (!IS_ERR(mmu))
648 mmu->funcs->destroy(mmu);
642 ret = PTR_ERR(aspace);649 ret = PTR_ERR(aspace);
643 goto fail;650 goto fail;
644 }651 }
645 652
646 kms->aspace = aspace;653 kms->aspace = aspace;
647
648 ret = aspace->mmu->funcs->attach(aspace->mmu);
649 if (ret) {
650 DRM_DEV_ERROR(&pdev->dev, "failed to attach iommu: %d\n",
651 ret);
652 goto fail;
653 }
654 } else {654 } else {
655 DRM_DEV_INFO(&pdev->dev,655 DRM_DEV_INFO(&pdev->dev,
656 "no iommu, fallback to phys contig buffers for scanout\n");656 "no iommu, fallback to phys contig buffers for scanout\n");
@@ -943,7 +943,8 @@ static int mdp5_init(struct platform_device *pdev, struct drm_device *dev) · 286 unmodified lines
943 943
944 return 0;944 return 0;
945fail:945fail:
946 mdp5_destroy(pdev);946 if (mdp5_kms)
947 mdp5_destroy(pdev);
947 return ret;948 return ret;
948}949}
949 950
drivers/gpu/drm/msm/msm_drv.c+4−2
@@ -37,9 +37,10 @@ · 36 unmodified lines
37 * - 1.4.0 - softpin, MSM_RELOC_BO_DUMP, and GEM_INFO support to set/get37 * - 1.4.0 - softpin, MSM_RELOC_BO_DUMP, and GEM_INFO support to set/get
38 * GEM object's debug name38 * GEM object's debug name
39 * - 1.5.0 - Add SUBMITQUERY_QUERY ioctl39 * - 1.5.0 - Add SUBMITQUERY_QUERY ioctl
40 * - 1.6.0 - Syncobj support
40 */41 */
41#define MSM_VERSION_MAJOR 142#define MSM_VERSION_MAJOR 1
42#define MSM_VERSION_MINOR 543#define MSM_VERSION_MINOR 6
43#define MSM_VERSION_PATCHLEVEL 044#define MSM_VERSION_PATCHLEVEL 0
44 45
45static const struct drm_mode_config_funcs mode_config_funcs = {46static const struct drm_mode_config_funcs mode_config_funcs = {
@@ -1002,7 +1003,8 @@ static struct drm_driver msm_driver = { · 956 unmodified lines
1002 .driver_features = DRIVER_GEM |1003 .driver_features = DRIVER_GEM |
1003 DRIVER_RENDER |1004 DRIVER_RENDER |
1004 DRIVER_ATOMIC |1005 DRIVER_ATOMIC |
1005 DRIVER_MODESET,1006 DRIVER_MODESET |
1007 DRIVER_SYNCOBJ,
1006 .open = msm_open,1008 .open = msm_open,
1007 .postclose = msm_postclose,1009 .postclose = msm_postclose,
1008 .lastclose = drm_fb_helper_lastclose,1010 .lastclose = drm_fb_helper_lastclose,
drivers/gpu/drm/msm/msm_drv.h+8−7
@@ -105,6 +105,7 @@ struct msm_display_topology { · 104 unmodified lines
105 u32 num_lm;105 u32 num_lm;
106 u32 num_enc;106 u32 num_enc;
107 u32 num_intf;107 u32 num_intf;
108 u32 num_dspp;
108};109};
109 110
110/**111/**
@@ -236,7 +237,8 @@ int msm_crtc_enable_vblank(struct drm_crtc *crtc); · 125 unmodified lines
236void msm_crtc_disable_vblank(struct drm_crtc *crtc);237void msm_crtc_disable_vblank(struct drm_crtc *crtc);
237 238
238int msm_gem_init_vma(struct msm_gem_address_space *aspace,239int msm_gem_init_vma(struct msm_gem_address_space *aspace,
239 struct msm_gem_vma *vma, int npages);240 struct msm_gem_vma *vma, int npages,
241 u64 range_start, u64 range_end);
240void msm_gem_purge_vma(struct msm_gem_address_space *aspace,242void msm_gem_purge_vma(struct msm_gem_address_space *aspace,
241 struct msm_gem_vma *vma);243 struct msm_gem_vma *vma);
242void msm_gem_unmap_vma(struct msm_gem_address_space *aspace,244void msm_gem_unmap_vma(struct msm_gem_address_space *aspace,
@@ -250,12 +252,8 @@ void msm_gem_close_vma(struct msm_gem_address_space *aspace, · 7 unmodified lines
250void msm_gem_address_space_put(struct msm_gem_address_space *aspace);252void msm_gem_address_space_put(struct msm_gem_address_space *aspace);
251 253
252struct msm_gem_address_space *254struct msm_gem_address_space *
253msm_gem_address_space_create(struct device *dev, struct iommu_domain *domain,255msm_gem_address_space_create(struct msm_mmu *mmu, const char *name,
254 const char *name);256 u64 va_start, u64 size);
255
256struct msm_gem_address_space *
257msm_gem_address_space_create_a2xx(struct device *dev, struct msm_gpu *gpu,
258 const char *name, uint64_t va_start, uint64_t va_end);
259 257
260int msm_register_mmu(struct drm_device *dev, struct msm_mmu *mmu);258int msm_register_mmu(struct drm_device *dev, struct msm_mmu *mmu);
261void msm_unregister_mmu(struct drm_device *dev, struct msm_mmu *mmu);259void msm_unregister_mmu(struct drm_device *dev, struct msm_mmu *mmu);
@@ -276,6 +274,9 @@ vm_fault_t msm_gem_fault(struct vm_fault *vmf); · 14 unmodified lines
276uint64_t msm_gem_mmap_offset(struct drm_gem_object *obj);274uint64_t msm_gem_mmap_offset(struct drm_gem_object *obj);
277int msm_gem_get_iova(struct drm_gem_object *obj,275int msm_gem_get_iova(struct drm_gem_object *obj,
278 struct msm_gem_address_space *aspace, uint64_t *iova);276 struct msm_gem_address_space *aspace, uint64_t *iova);
277int msm_gem_get_and_pin_iova_range(struct drm_gem_object *obj,
278 struct msm_gem_address_space *aspace, uint64_t *iova,
279 u64 range_start, u64 range_end);
279int msm_gem_get_and_pin_iova(struct drm_gem_object *obj,280int msm_gem_get_and_pin_iova(struct drm_gem_object *obj,
280 struct msm_gem_address_space *aspace, uint64_t *iova);281 struct msm_gem_address_space *aspace, uint64_t *iova);
281uint64_t msm_gem_iova(struct drm_gem_object *obj,282uint64_t msm_gem_iova(struct drm_gem_object *obj,
drivers/gpu/drm/msm/msm_gem.c+24−7
@@ -389,7 +389,8 @@ put_iova(struct drm_gem_object *obj) · 388 unmodified lines
389}389}
390 390
391static int msm_gem_get_iova_locked(struct drm_gem_object *obj,391static int msm_gem_get_iova_locked(struct drm_gem_object *obj,
392 struct msm_gem_address_space *aspace, uint64_t *iova)392 struct msm_gem_address_space *aspace, uint64_t *iova,
393 u64 range_start, u64 range_end)
393{394{
394 struct msm_gem_object *msm_obj = to_msm_bo(obj);395 struct msm_gem_object *msm_obj = to_msm_bo(obj);
395 struct msm_gem_vma *vma;396 struct msm_gem_vma *vma;
@@ -404,7 +405,8 @@ static int msm_gem_get_iova_locked(struct drm_gem_object *obj, · 8 unmodified lines
404 if (IS_ERR(vma))405 if (IS_ERR(vma))
405 return PTR_ERR(vma);406 return PTR_ERR(vma);
406 407
407 ret = msm_gem_init_vma(aspace, vma, obj->size >> PAGE_SHIFT);408 ret = msm_gem_init_vma(aspace, vma, obj->size >> PAGE_SHIFT,
409 range_start, range_end);
408 if (ret) {410 if (ret) {
409 del_vma(vma);411 del_vma(vma);
410 return ret;412 return ret;
@@ -426,6 +428,9 @@ static int msm_gem_pin_iova(struct drm_gem_object *obj, · 15 unmodified lines
426 if (!(msm_obj->flags & MSM_BO_GPU_READONLY))428 if (!(msm_obj->flags & MSM_BO_GPU_READONLY))
427 prot |= IOMMU_WRITE;429 prot |= IOMMU_WRITE;
428 430
431 if (msm_obj->flags & MSM_BO_MAP_PRIV)
432 prot |= IOMMU_PRIV;
433
429 WARN_ON(!mutex_is_locked(&msm_obj->lock));434 WARN_ON(!mutex_is_locked(&msm_obj->lock));
430 435
431 if (WARN_ON(msm_obj->madv != MSM_MADV_WILLNEED))436 if (WARN_ON(msm_obj->madv != MSM_MADV_WILLNEED))
@@ -443,9 +448,13 @@ static int msm_gem_pin_iova(struct drm_gem_object *obj, · 11 unmodified lines
443 msm_obj->sgt, obj->size >> PAGE_SHIFT);448 msm_obj->sgt, obj->size >> PAGE_SHIFT);
444}449}
445 450
446/* get iova and pin it. Should have a matching put */451/*
447int msm_gem_get_and_pin_iova(struct drm_gem_object *obj,452 * get iova and pin it. Should have a matching put
448 struct msm_gem_address_space *aspace, uint64_t *iova)453 * limits iova to specified range (in pages)
454 */
455int msm_gem_get_and_pin_iova_range(struct drm_gem_object *obj,
456 struct msm_gem_address_space *aspace, uint64_t *iova,
457 u64 range_start, u64 range_end)
449{458{
450 struct msm_gem_object *msm_obj = to_msm_bo(obj);459 struct msm_gem_object *msm_obj = to_msm_bo(obj);
451 u64 local;460 u64 local;
@@ -453,7 +462,8 @@ int msm_gem_get_and_pin_iova(struct drm_gem_object *obj, · 1 unmodified line
453 462
454 mutex_lock(&msm_obj->lock);463 mutex_lock(&msm_obj->lock);
455 464
456 ret = msm_gem_get_iova_locked(obj, aspace, &local);465 ret = msm_gem_get_iova_locked(obj, aspace, &local,
466 range_start, range_end);
457 467
458 if (!ret)468 if (!ret)
459 ret = msm_gem_pin_iova(obj, aspace);469 ret = msm_gem_pin_iova(obj, aspace);
@@ -465,6 +475,13 @@ int msm_gem_get_and_pin_iova(struct drm_gem_object *obj, · 5 unmodified lines
465 return ret;475 return ret;
466}476}
467 477
478/* get iova and pin it. Should have a matching put */
479int msm_gem_get_and_pin_iova(struct drm_gem_object *obj,
480 struct msm_gem_address_space *aspace, uint64_t *iova)
481{
482 return msm_gem_get_and_pin_iova_range(obj, aspace, iova, 0, U64_MAX);
483}
484
468/*485/*
469 * Get an iova but don't pin it. Doesn't need a put because iovas are currently486 * Get an iova but don't pin it. Doesn't need a put because iovas are currently
470 * valid for the life of the object487 * valid for the life of the object
@@ -476,7 +493,7 @@ int msm_gem_get_iova(struct drm_gem_object *obj, · 5 unmodified lines
476 int ret;493 int ret;
477 494
478 mutex_lock(&msm_obj->lock);495 mutex_lock(&msm_obj->lock);
479 ret = msm_gem_get_iova_locked(obj, aspace, iova);496 ret = msm_gem_get_iova_locked(obj, aspace, iova, 0, U64_MAX);
480 mutex_unlock(&msm_obj->lock);497 mutex_unlock(&msm_obj->lock);
481 498
482 return ret;499 return ret;
drivers/gpu/drm/msm/msm_gem.h+1−0
@@ -13,6 +13,7 @@ · 12 unmodified lines
13 13
14/* Additional internal-use only BO flags: */14/* Additional internal-use only BO flags: */
15#define MSM_BO_STOLEN 0x10000000 /* try to use stolen/splash memory */15#define MSM_BO_STOLEN 0x10000000 /* try to use stolen/splash memory */
16#define MSM_BO_MAP_PRIV 0x20000000 /* use IOMMU_PRIV when mapping */
16 17
17struct msm_gem_address_space {18struct msm_gem_address_space {
18 const char *name;19 const char *name;
drivers/gpu/drm/msm/msm_gem_submit.c+231−1
@@ -8,7 +8,9 @@ · 7 unmodified lines
8#include <linux/sync_file.h>8#include <linux/sync_file.h>
9#include <linux/uaccess.h>9#include <linux/uaccess.h>
10 10
11#include <drm/drm_drv.h>
11#include <drm/drm_file.h>12#include <drm/drm_file.h>
13#include <drm/drm_syncobj.h>
12 14
13#include "msm_drv.h"15#include "msm_drv.h"
14#include "msm_gpu.h"16#include "msm_gpu.h"
@@ -391,6 +393,186 @@ static void submit_cleanup(struct msm_gem_submit *submit) · 376 unmodified lines
391 }393 }
392}394}
393 395
396
397struct msm_submit_post_dep {
398 struct drm_syncobj *syncobj;
399 uint64_t point;
400 struct dma_fence_chain *chain;
401};
402
403static struct drm_syncobj **msm_wait_deps(struct drm_device *dev,
404 struct drm_file *file,
405 uint64_t in_syncobjs_addr,
406 uint32_t nr_in_syncobjs,
407 size_t syncobj_stride,
408 struct msm_ringbuffer *ring)
409{
410 struct drm_syncobj **syncobjs = NULL;
411 struct drm_msm_gem_submit_syncobj syncobj_desc = {0};
412 int ret = 0;
413 uint32_t i, j;
414
415 syncobjs = kcalloc(nr_in_syncobjs, sizeof(*syncobjs),
416 GFP_KERNEL | __GFP_NOWARN | __GFP_NORETRY);
417 if (!syncobjs)
418 return ERR_PTR(-ENOMEM);
419
420 for (i = 0; i < nr_in_syncobjs; ++i) {
421 uint64_t address = in_syncobjs_addr + i * syncobj_stride;
422 struct dma_fence *fence;
423
424 if (copy_from_user(&syncobj_desc,
425 u64_to_user_ptr(address),
426 min(syncobj_stride, sizeof(syncobj_desc)))) {
427 ret = -EFAULT;
428 break;
429 }
430
431 if (syncobj_desc.point &&
432 !drm_core_check_feature(dev, DRIVER_SYNCOBJ_TIMELINE)) {
433 ret = -EOPNOTSUPP;
434 break;
435 }
436
437 if (syncobj_desc.flags & ~MSM_SUBMIT_SYNCOBJ_FLAGS) {
438 ret = -EINVAL;
439 break;
440 }
441
442 ret = drm_syncobj_find_fence(file, syncobj_desc.handle,
443 syncobj_desc.point, 0, &fence);
444 if (ret)
445 break;
446
447 if (!dma_fence_match_context(fence, ring->fctx->context))
448 ret = dma_fence_wait(fence, true);
449
450 dma_fence_put(fence);
451 if (ret)
452 break;
453
454 if (syncobj_desc.flags & MSM_SUBMIT_SYNCOBJ_RESET) {
455 syncobjs[i] =
456 drm_syncobj_find(file, syncobj_desc.handle);
457 if (!syncobjs[i]) {
458 ret = -EINVAL;
459 break;
460 }
461 }
462 }
463
464 if (ret) {
465 for (j = 0; j <= i; ++j) {
466 if (syncobjs[j])
467 drm_syncobj_put(syncobjs[j]);
468 }
469 kfree(syncobjs);
470 return ERR_PTR(ret);
471 }
472 return syncobjs;
473}
474
475static void msm_reset_syncobjs(struct drm_syncobj **syncobjs,
476 uint32_t nr_syncobjs)
477{
478 uint32_t i;
479
480 for (i = 0; syncobjs && i < nr_syncobjs; ++i) {
481 if (syncobjs[i])
482 drm_syncobj_replace_fence(syncobjs[i], NULL);
483 }
484}
485
486static struct msm_submit_post_dep *msm_parse_post_deps(struct drm_device *dev,
487 struct drm_file *file,
488 uint64_t syncobjs_addr,
489 uint32_t nr_syncobjs,
490 size_t syncobj_stride)
491{
492 struct msm_submit_post_dep *post_deps;
493 struct drm_msm_gem_submit_syncobj syncobj_desc = {0};
494 int ret = 0;
495 uint32_t i, j;
496
497 post_deps = kmalloc_array(nr_syncobjs, sizeof(*post_deps),
498 GFP_KERNEL | __GFP_NOWARN | __GFP_NORETRY);
499 if (!post_deps)
500 return ERR_PTR(-ENOMEM);
501
502 for (i = 0; i < nr_syncobjs; ++i) {
503 uint64_t address = syncobjs_addr + i * syncobj_stride;
504
505 if (copy_from_user(&syncobj_desc,
506 u64_to_user_ptr(address),
507 min(syncobj_stride, sizeof(syncobj_desc)))) {
508 ret = -EFAULT;
509 break;
510 }
511
512 post_deps[i].point = syncobj_desc.point;
513 post_deps[i].chain = NULL;
514
515 if (syncobj_desc.flags) {
516 ret = -EINVAL;
517 break;
518 }
519
520 if (syncobj_desc.point) {
521 if (!drm_core_check_feature(dev,
522 DRIVER_SYNCOBJ_TIMELINE)) {
523 ret = -EOPNOTSUPP;
524 break;
525 }
526
527 post_deps[i].chain =
528 kmalloc(sizeof(*post_deps[i].chain),
529 GFP_KERNEL);
530 if (!post_deps[i].chain) {
531 ret = -ENOMEM;
532 break;
533 }
534 }
535
536 post_deps[i].syncobj =
537 drm_syncobj_find(file, syncobj_desc.handle);
538 if (!post_deps[i].syncobj) {
539 ret = -EINVAL;
540 break;
541 }
542 }
543
544 if (ret) {
545 for (j = 0; j <= i; ++j) {
546 kfree(post_deps[j].chain);
547 if (post_deps[j].syncobj)
548 drm_syncobj_put(post_deps[j].syncobj);
549 }
550
551 kfree(post_deps);
552 return ERR_PTR(ret);
553 }
554
555 return post_deps;
556}
557
558static void msm_process_post_deps(struct msm_submit_post_dep *post_deps,
559 uint32_t count, struct dma_fence *fence)
560{
561 uint32_t i;
562
563 for (i = 0; post_deps && i < count; ++i) {
564 if (post_deps[i].chain) {
565 drm_syncobj_add_point(post_deps[i].syncobj,
566 post_deps[i].chain,
567 fence, post_deps[i].point);
568 post_deps[i].chain = NULL;
569 } else {
570 drm_syncobj_replace_fence(post_deps[i].syncobj,
571 fence);
572 }
573 }
574}
575
394int msm_ioctl_gem_submit(struct drm_device *dev, void *data,576int msm_ioctl_gem_submit(struct drm_device *dev, void *data,
395 struct drm_file *file)577 struct drm_file *file)
396{578{
@@ -403,6 +585,8 @@ int msm_ioctl_gem_submit(struct drm_device *dev, void *data, · 6 unmodified lines
403 struct sync_file *sync_file = NULL;585 struct sync_file *sync_file = NULL;
404 struct msm_gpu_submitqueue *queue;586 struct msm_gpu_submitqueue *queue;
405 struct msm_ringbuffer *ring;587 struct msm_ringbuffer *ring;
588 struct msm_submit_post_dep *post_deps = NULL;
589 struct drm_syncobj **syncobjs_to_reset = NULL;
406 int out_fence_fd = -1;590 int out_fence_fd = -1;
407 struct pid *pid = get_pid(task_pid(current));591 struct pid *pid = get_pid(task_pid(current));
408 bool has_ww_ticket = false;592 bool has_ww_ticket = false;
@@ -411,6 +595,9 @@ int msm_ioctl_gem_submit(struct drm_device *dev, void *data, · 2 unmodified lines
411 if (!gpu)595 if (!gpu)
412 return -ENXIO;596 return -ENXIO;
413 597
598 if (args->pad)
599 return -EINVAL;
600
414 /* for now, we just have 3d pipe.. eventually this would need to601 /* for now, we just have 3d pipe.. eventually this would need to
415 * be more clever to dispatch to appropriate gpu module:602 * be more clever to dispatch to appropriate gpu module:
416 */603 */
@@ -458,9 +645,29 @@ int msm_ioctl_gem_submit(struct drm_device *dev, void *data, · 41 unmodified lines
458 return ret;645 return ret;
459 }646 }
460 647
648 if (args->flags & MSM_SUBMIT_SYNCOBJ_IN) {
649 syncobjs_to_reset = msm_wait_deps(dev, file,
650 args->in_syncobjs,
651 args->nr_in_syncobjs,
652 args->syncobj_stride, ring);
653 if (IS_ERR(syncobjs_to_reset))
654 return PTR_ERR(syncobjs_to_reset);
655 }
656
657 if (args->flags & MSM_SUBMIT_SYNCOBJ_OUT) {
658 post_deps = msm_parse_post_deps(dev, file,
659 args->out_syncobjs,
660 args->nr_out_syncobjs,
661 args->syncobj_stride);
662 if (IS_ERR(post_deps)) {
663 ret = PTR_ERR(post_deps);
664 goto out_post_unlock;
665 }
666 }
667
461 ret = mutex_lock_interruptible(&dev->struct_mutex);668 ret = mutex_lock_interruptible(&dev->struct_mutex);
462 if (ret)669 if (ret)
463 return ret;670 goto out_post_unlock;
464 671
465 if (args->flags & MSM_SUBMIT_FENCE_FD_OUT) {672 if (args->flags & MSM_SUBMIT_FENCE_FD_OUT) {
466 out_fence_fd = get_unused_fd_flags(O_CLOEXEC);673 out_fence_fd = get_unused_fd_flags(O_CLOEXEC);
@@ -587,6 +794,11 @@ int msm_ioctl_gem_submit(struct drm_device *dev, void *data, · 120 unmodified lines
587 args->fence_fd = out_fence_fd;794 args->fence_fd = out_fence_fd;
588 }795 }
589 796
797 msm_reset_syncobjs(syncobjs_to_reset, args->nr_in_syncobjs);
798 msm_process_post_deps(post_deps, args->nr_out_syncobjs,
799 submit->fence);
800
801
590out:802out:
591 submit_cleanup(submit);803 submit_cleanup(submit);
592 if (has_ww_ticket)804 if (has_ww_ticket)
@@ -597,5 +809,23 @@ out_unlock: · 4 unmodified lines
597 if (ret && (out_fence_fd >= 0))809 if (ret && (out_fence_fd >= 0))
598 put_unused_fd(out_fence_fd);810 put_unused_fd(out_fence_fd);
599 mutex_unlock(&dev->struct_mutex);811 mutex_unlock(&dev->struct_mutex);
812
813out_post_unlock:
814 if (!IS_ERR_OR_NULL(post_deps)) {
815 for (i = 0; i < args->nr_out_syncobjs; ++i) {
816 kfree(post_deps[i].chain);
817 drm_syncobj_put(post_deps[i].syncobj);
818 }
819 kfree(post_deps);
820 }
821
822 if (!IS_ERR_OR_NULL(syncobjs_to_reset)) {
823 for (i = 0; i < args->nr_in_syncobjs; ++i) {
824 if (syncobjs_to_reset[i])
825 drm_syncobj_put(syncobjs_to_reset[i]);
826 }
827 kfree(syncobjs_to_reset);
828 }
829
600 return ret;830 return ret;
601}831}
drivers/gpu/drm/msm/msm_gem_vma.c+10−32
@@ -103,7 +103,8 @@ void msm_gem_close_vma(struct msm_gem_address_space *aspace, · 102 unmodified lines
103 103
104/* Initialize a new vma and allocate an iova for it */104/* Initialize a new vma and allocate an iova for it */
105int msm_gem_init_vma(struct msm_gem_address_space *aspace,105int msm_gem_init_vma(struct msm_gem_address_space *aspace,
106 struct msm_gem_vma *vma, int npages)106 struct msm_gem_vma *vma, int npages,
107 u64 range_start, u64 range_end)
107{108{
108 int ret;109 int ret;
109 110
@@ -111,7 +112,8 @@ int msm_gem_init_vma(struct msm_gem_address_space *aspace, · 1 unmodified line
111 return -EBUSY;112 return -EBUSY;
112 113
113 spin_lock(&aspace->lock);114 spin_lock(&aspace->lock);
114 ret = drm_mm_insert_node(&aspace->mm, &vma->node, npages);115 ret = drm_mm_insert_node_in_range(&aspace->mm, &vma->node, npages, 0,
116 0, range_start, range_end, 0);
115 spin_unlock(&aspace->lock);117 spin_unlock(&aspace->lock);
116 118
117 if (ret)119 if (ret)
@@ -125,37 +127,14 @@ int msm_gem_init_vma(struct msm_gem_address_space *aspace, · 7 unmodified lines
125 return 0;127 return 0;
126}128}
127 129
128
129struct msm_gem_address_space *130struct msm_gem_address_space *
130msm_gem_address_space_create(struct device *dev, struct iommu_domain *domain,131msm_gem_address_space_create(struct msm_mmu *mmu, const char *name,
131 const char *name)132 u64 va_start, u64 size)
132{133{
133 struct msm_gem_address_space *aspace;134 struct msm_gem_address_space *aspace;
134 u64 size = domain->geometry.aperture_end -
135 domain->geometry.aperture_start;
136
137 aspace = kzalloc(sizeof(*aspace), GFP_KERNEL);
138 if (!aspace)
139 return ERR_PTR(-ENOMEM);
140
141 spin_lock_init(&aspace->lock);
142 aspace->name = name;
143 aspace->mmu = msm_iommu_new(dev, domain);
144
145 drm_mm_init(&aspace->mm, (domain->geometry.aperture_start >> PAGE_SHIFT),
146 size >> PAGE_SHIFT);
147 135
148 kref_init(&aspace->kref);136 if (IS_ERR(mmu))
149 137 return ERR_CAST(mmu);
150 return aspace;
151}
152
153struct msm_gem_address_space *
154msm_gem_address_space_create_a2xx(struct device *dev, struct msm_gpu *gpu,
155 const char *name, uint64_t va_start, uint64_t va_end)
156{
157 struct msm_gem_address_space *aspace;
158 u64 size = va_end - va_start;
159 138
160 aspace = kzalloc(sizeof(*aspace), GFP_KERNEL);139 aspace = kzalloc(sizeof(*aspace), GFP_KERNEL);
161 if (!aspace)140 if (!aspace)
@@ -163,10 +142,9 @@ msm_gem_address_space_create_a2xx(struct device *dev, struct msm_gpu *gpu, · 1 unmodified line
163 142
164 spin_lock_init(&aspace->lock);143 spin_lock_init(&aspace->lock);
165 aspace->name = name;144 aspace->name = name;
166 aspace->mmu = msm_gpummu_new(dev, gpu);145 aspace->mmu = mmu;
167 146
168 drm_mm_init(&aspace->mm, (va_start >> PAGE_SHIFT),147 drm_mm_init(&aspace->mm, va_start >> PAGE_SHIFT, size >> PAGE_SHIFT);
169 size >> PAGE_SHIFT);
170 148
171 kref_init(&aspace->kref);149 kref_init(&aspace->kref);
172 150
drivers/gpu/drm/msm/msm_gpu.c+2−47
@@ -821,51 +821,6 @@ static int get_clocks(struct platform_device *pdev, struct msm_gpu *gpu) · 820 unmodified lines
821 return 0;821 return 0;
822}822}
823 823
824static struct msm_gem_address_space *
825msm_gpu_create_address_space(struct msm_gpu *gpu, struct platform_device *pdev,
826 uint64_t va_start, uint64_t va_end)
827{
828 struct msm_gem_address_space *aspace;
829 int ret;
830
831 /*
832 * Setup IOMMU.. eventually we will (I think) do this once per context
833 * and have separate page tables per context. For now, to keep things
834 * simple and to get something working, just use a single address space:
835 */
836 if (!adreno_is_a2xx(to_adreno_gpu(gpu))) {
837 struct iommu_domain *iommu = iommu_domain_alloc(&platform_bus_type);
838 if (!iommu)
839 return NULL;
840
841 iommu->geometry.aperture_start = va_start;
842 iommu->geometry.aperture_end = va_end;
843
844 DRM_DEV_INFO(gpu->dev->dev, "%s: using IOMMU\n", gpu->name);
845
846 aspace = msm_gem_address_space_create(&pdev->dev, iommu, "gpu");
847 if (IS_ERR(aspace))
848 iommu_domain_free(iommu);
849 } else {
850 aspace = msm_gem_address_space_create_a2xx(&pdev->dev, gpu, "gpu",
851 va_start, va_end);
852 }
853
854 if (IS_ERR(aspace)) {
855 DRM_DEV_ERROR(gpu->dev->dev, "failed to init mmu: %ld\n",
856 PTR_ERR(aspace));
857 return ERR_CAST(aspace);
858 }
859
860 ret = aspace->mmu->funcs->attach(aspace->mmu);
861 if (ret) {
862 msm_gem_address_space_put(aspace);
863 return ERR_PTR(ret);
864 }
865
866 return aspace;
867}
868
869int msm_gpu_init(struct drm_device *drm, struct platform_device *pdev,824int msm_gpu_init(struct drm_device *drm, struct platform_device *pdev,
870 struct msm_gpu *gpu, const struct msm_gpu_funcs *funcs,825 struct msm_gpu *gpu, const struct msm_gpu_funcs *funcs,
871 const char *name, struct msm_gpu_config *config)826 const char *name, struct msm_gpu_config *config)
@@ -938,8 +893,8 @@ int msm_gpu_init(struct drm_device *drm, struct platform_device *pdev, · 66 unmodified lines
938 893
939 msm_devfreq_init(gpu);894 msm_devfreq_init(gpu);
940 895
941 gpu->aspace = msm_gpu_create_address_space(gpu, pdev,896
942 config->va_start, config->va_end);897 gpu->aspace = gpu->funcs->create_address_space(gpu, pdev);
943 898
944 if (gpu->aspace == NULL)899 if (gpu->aspace == NULL)
945 DRM_DEV_INFO(drm->dev, "%s: no IOMMU, fallback to VRAM carveout!\n", name);900 DRM_DEV_INFO(drm->dev, "%s: no IOMMU, fallback to VRAM carveout!\n", name);
drivers/gpu/drm/msm/msm_gpu.h+2−2
@@ -21,8 +21,6 @@ struct msm_gpu_state; · 20 unmodified lines
21 21
22struct msm_gpu_config {22struct msm_gpu_config {
23 const char *ioname;23 const char *ioname;
24 uint64_t va_start;
25 uint64_t va_end;
26 unsigned int nr_rings;24 unsigned int nr_rings;
27};25};
28 26
@@ -64,6 +62,8 @@ struct msm_gpu_funcs { · 35 unmodified lines
64 int (*gpu_state_put)(struct msm_gpu_state *state);62 int (*gpu_state_put)(struct msm_gpu_state *state);
65 unsigned long (*gpu_get_freq)(struct msm_gpu *gpu);63 unsigned long (*gpu_get_freq)(struct msm_gpu *gpu);
66 void (*gpu_set_freq)(struct msm_gpu *gpu, unsigned long freq);64 void (*gpu_set_freq)(struct msm_gpu *gpu, unsigned long freq);
65 struct msm_gem_address_space *(*create_address_space)
66 (struct msm_gpu *gpu, struct platform_device *pdev);
67};67};
68 68
69struct msm_gpu {69struct msm_gpu {
drivers/gpu/drm/msm/msm_gpummu.c+2−8
@@ -21,17 +21,12 @@ struct msm_gpummu { · 20 unmodified lines
21#define GPUMMU_PAGE_SIZE SZ_4K21#define GPUMMU_PAGE_SIZE SZ_4K
22#define TABLE_SIZE (sizeof(uint32_t) * GPUMMU_VA_RANGE / GPUMMU_PAGE_SIZE)22#define TABLE_SIZE (sizeof(uint32_t) * GPUMMU_VA_RANGE / GPUMMU_PAGE_SIZE)
23 23
24static int msm_gpummu_attach(struct msm_mmu *mmu)
25{
26 return 0;
27}
28
29static void msm_gpummu_detach(struct msm_mmu *mmu)24static void msm_gpummu_detach(struct msm_mmu *mmu)
30{25{
31}26}
32 27
33static int msm_gpummu_map(struct msm_mmu *mmu, uint64_t iova,28static int msm_gpummu_map(struct msm_mmu *mmu, uint64_t iova,
34 struct sg_table *sgt, unsigned len, int prot)29 struct sg_table *sgt, size_t len, int prot)
35{30{
36 struct msm_gpummu *gpummu = to_msm_gpummu(mmu);31 struct msm_gpummu *gpummu = to_msm_gpummu(mmu);
37 unsigned idx = (iova - GPUMMU_VA_START) / GPUMMU_PAGE_SIZE;32 unsigned idx = (iova - GPUMMU_VA_START) / GPUMMU_PAGE_SIZE;
@@ -59,7 +54,7 @@ static int msm_gpummu_map(struct msm_mmu *mmu, uint64_t iova, · 21 unmodified lines
59 return 0;54 return 0;
60}55}
61 56
62static int msm_gpummu_unmap(struct msm_mmu *mmu, uint64_t iova, unsigned len)57static int msm_gpummu_unmap(struct msm_mmu *mmu, uint64_t iova, size_t len)
63{58{
64 struct msm_gpummu *gpummu = to_msm_gpummu(mmu);59 struct msm_gpummu *gpummu = to_msm_gpummu(mmu);
65 unsigned idx = (iova - GPUMMU_VA_START) / GPUMMU_PAGE_SIZE;60 unsigned idx = (iova - GPUMMU_VA_START) / GPUMMU_PAGE_SIZE;
@@ -85,7 +80,6 @@ static void msm_gpummu_destroy(struct msm_mmu *mmu) · 19 unmodified lines
85}80}
86 81
87static const struct msm_mmu_funcs funcs = {82static const struct msm_mmu_funcs funcs = {
88 .attach = msm_gpummu_attach,
89 .detach = msm_gpummu_detach,83 .detach = msm_gpummu_detach,
90 .map = msm_gpummu_map,84 .map = msm_gpummu_map,
91 .unmap = msm_gpummu_unmap,85 .unmap = msm_gpummu_unmap,
drivers/gpu/drm/msm/msm_iommu.c+12−10
@@ -23,13 +23,6 @@ static int msm_fault_handler(struct iommu_domain *domain, struct device *dev, · 22 unmodified lines
23 return 0;23 return 0;
24}24}
25 25
26static int msm_iommu_attach(struct msm_mmu *mmu)
27{
28 struct msm_iommu *iommu = to_msm_iommu(mmu);
29
30 return iommu_attach_device(iommu->domain, mmu->dev);
31}
32
33static void msm_iommu_detach(struct msm_mmu *mmu)26static void msm_iommu_detach(struct msm_mmu *mmu)
34{27{
35 struct msm_iommu *iommu = to_msm_iommu(mmu);28 struct msm_iommu *iommu = to_msm_iommu(mmu);
@@ -38,7 +31,7 @@ static void msm_iommu_detach(struct msm_mmu *mmu) · 2 unmodified lines
38}31}
39 32
40static int msm_iommu_map(struct msm_mmu *mmu, uint64_t iova,33static int msm_iommu_map(struct msm_mmu *mmu, uint64_t iova,
41 struct sg_table *sgt, unsigned len, int prot)34 struct sg_table *sgt, size_t len, int prot)
42{35{
43 struct msm_iommu *iommu = to_msm_iommu(mmu);36 struct msm_iommu *iommu = to_msm_iommu(mmu);
44 size_t ret;37 size_t ret;
@@ -49,7 +42,7 @@ static int msm_iommu_map(struct msm_mmu *mmu, uint64_t iova, · 4 unmodified lines
49 return (ret == len) ? 0 : -EINVAL;42 return (ret == len) ? 0 : -EINVAL;
50}43}
51 44
52static int msm_iommu_unmap(struct msm_mmu *mmu, uint64_t iova, unsigned len)45static int msm_iommu_unmap(struct msm_mmu *mmu, uint64_t iova, size_t len)
53{46{
54 struct msm_iommu *iommu = to_msm_iommu(mmu);47 struct msm_iommu *iommu = to_msm_iommu(mmu);
55 48
@@ -66,7 +59,6 @@ static void msm_iommu_destroy(struct msm_mmu *mmu) · 10 unmodified lines
66}59}
67 60
68static const struct msm_mmu_funcs funcs = {61static const struct msm_mmu_funcs funcs = {
69 .attach = msm_iommu_attach,
70 .detach = msm_iommu_detach,62 .detach = msm_iommu_detach,
71 .map = msm_iommu_map,63 .map = msm_iommu_map,
72 .unmap = msm_iommu_unmap,64 .unmap = msm_iommu_unmap,
@@ -76,6 +68,10 @@ static const struct msm_mmu_funcs funcs = { · 3 unmodified lines
76struct msm_mmu *msm_iommu_new(struct device *dev, struct iommu_domain *domain)68struct msm_mmu *msm_iommu_new(struct device *dev, struct iommu_domain *domain)
77{69{
78 struct msm_iommu *iommu;70 struct msm_iommu *iommu;
71 int ret;
72
73 if (!domain)
74 return ERR_PTR(-ENODEV);
79 75
80 iommu = kzalloc(sizeof(*iommu), GFP_KERNEL);76 iommu = kzalloc(sizeof(*iommu), GFP_KERNEL);
81 if (!iommu)77 if (!iommu)
@@ -85,5 +81,11 @@ struct msm_mmu *msm_iommu_new(struct device *dev, struct iommu_domain *domain) · 3 unmodified lines
85 msm_mmu_init(&iommu->base, dev, &funcs);81 msm_mmu_init(&iommu->base, dev, &funcs);
86 iommu_set_fault_handler(domain, msm_fault_handler, iommu);82 iommu_set_fault_handler(domain, msm_fault_handler, iommu);
87 83
84 ret = iommu_attach_device(iommu->domain, dev);
85 if (ret) {
86 kfree(iommu);
87 return ERR_PTR(ret);
88 }
89
88 return &iommu->base;90 return &iommu->base;
89}91}
drivers/gpu/drm/msm/msm_mmu.h+2−3
@@ -10,11 +10,10 @@ · 9 unmodified lines
10#include <linux/iommu.h>10#include <linux/iommu.h>
11 11
12struct msm_mmu_funcs {12struct msm_mmu_funcs {
13 int (*attach)(struct msm_mmu *mmu);
14 void (*detach)(struct msm_mmu *mmu);13 void (*detach)(struct msm_mmu *mmu);
15 int (*map)(struct msm_mmu *mmu, uint64_t iova, struct sg_table *sgt,14 int (*map)(struct msm_mmu *mmu, uint64_t iova, struct sg_table *sgt,
16 unsigned len, int prot);15 size_t len, int prot);
17 int (*unmap)(struct msm_mmu *mmu, uint64_t iova, unsigned len);16 int (*unmap)(struct msm_mmu *mmu, uint64_t iova, size_t len);
18 void (*destroy)(struct msm_mmu *mmu);17 void (*destroy)(struct msm_mmu *mmu);
19};18};
20 19
drivers/gpu/drm/msm/msm_rd.c+2−2
@@ -29,8 +29,6 @@ · 28 unmodified lines
29 * or shader programs (if not emitted inline in cmdstream).29 * or shader programs (if not emitted inline in cmdstream).
30 */30 */
31 31
32#ifdef CONFIG_DEBUG_FS
33
34#include <linux/circ_buf.h>32#include <linux/circ_buf.h>
35#include <linux/debugfs.h>33#include <linux/debugfs.h>
36#include <linux/kfifo.h>34#include <linux/kfifo.h>
@@ -47,6 +45,8 @@ bool rd_full = false; · 10 unmodified lines
47MODULE_PARM_DESC(rd_full, "If true, $debugfs/.../rd will snapshot all buffer contents");45MODULE_PARM_DESC(rd_full, "If true, $debugfs/.../rd will snapshot all buffer contents");
48module_param_named(rd_full, rd_full, bool, 0600);46module_param_named(rd_full, rd_full, bool, 0600);
49 47
48#ifdef CONFIG_DEBUG_FS
49
50enum rd_sect_type {50enum rd_sect_type {
51 RD_NONE,51 RD_NONE,
52 RD_TEST, /* ascii text */52 RD_TEST, /* ascii text */
include/uapi/drm/msm_drm.h+23−1
@@ -217,13 +217,28 @@ struct drm_msm_gem_submit_bo { · 216 unmodified lines
217#define MSM_SUBMIT_FENCE_FD_IN 0x40000000 /* enable input fence_fd */217#define MSM_SUBMIT_FENCE_FD_IN 0x40000000 /* enable input fence_fd */
218#define MSM_SUBMIT_FENCE_FD_OUT 0x20000000 /* enable output fence_fd */218#define MSM_SUBMIT_FENCE_FD_OUT 0x20000000 /* enable output fence_fd */
219#define MSM_SUBMIT_SUDO 0x10000000 /* run submitted cmds from RB */219#define MSM_SUBMIT_SUDO 0x10000000 /* run submitted cmds from RB */
220#define MSM_SUBMIT_SYNCOBJ_IN 0x08000000 /* enable input syncobj */
221#define MSM_SUBMIT_SYNCOBJ_OUT 0x04000000 /* enable output syncobj */
220#define MSM_SUBMIT_FLAGS ( \222#define MSM_SUBMIT_FLAGS ( \
221 MSM_SUBMIT_NO_IMPLICIT | \223 MSM_SUBMIT_NO_IMPLICIT | \
222 MSM_SUBMIT_FENCE_FD_IN | \224 MSM_SUBMIT_FENCE_FD_IN | \
223 MSM_SUBMIT_FENCE_FD_OUT | \225 MSM_SUBMIT_FENCE_FD_OUT | \
224 MSM_SUBMIT_SUDO | \226 MSM_SUBMIT_SUDO | \
227 MSM_SUBMIT_SYNCOBJ_IN | \
228 MSM_SUBMIT_SYNCOBJ_OUT | \
225 0)229 0)
226 230
231#define MSM_SUBMIT_SYNCOBJ_RESET 0x00000001 /* Reset syncobj after wait. */
232#define MSM_SUBMIT_SYNCOBJ_FLAGS ( \
233 MSM_SUBMIT_SYNCOBJ_RESET | \
234 0)
235
236struct drm_msm_gem_submit_syncobj {
237 __u32 handle; /* in, syncobj handle. */
238 __u32 flags; /* in, from MSM_SUBMIT_SYNCOBJ_FLAGS */
239 __u64 point; /* in, timepoint for timeline syncobjs. */
240};
241
227/* Each cmdstream submit consists of a table of buffers involved, and242/* Each cmdstream submit consists of a table of buffers involved, and
228 * one or more cmdstream buffers. This allows for conditional execution243 * one or more cmdstream buffers. This allows for conditional execution
229 * (context-restore), and IB buffers needed for per tile/bin draw cmds.244 * (context-restore), and IB buffers needed for per tile/bin draw cmds.
@@ -236,7 +251,14 @@ struct drm_msm_gem_submit { · 6 unmodified lines
236 __u64 bos; /* in, ptr to array of submit_bo's */251 __u64 bos; /* in, ptr to array of submit_bo's */
237 __u64 cmds; /* in, ptr to array of submit_cmd's */252 __u64 cmds; /* in, ptr to array of submit_cmd's */
238 __s32 fence_fd; /* in/out fence fd (see MSM_SUBMIT_FENCE_FD_IN/OUT) */253 __s32 fence_fd; /* in/out fence fd (see MSM_SUBMIT_FENCE_FD_IN/OUT) */
239 __u32 queueid; /* in, submitqueue id */254 __u32 queueid; /* in, submitqueue id */
255 __u64 in_syncobjs; /* in, ptr to to array of drm_msm_gem_submit_syncobj */
256 __u64 out_syncobjs; /* in, ptr to to array of drm_msm_gem_submit_syncobj */
257 __u32 nr_in_syncobjs; /* in, number of entries in in_syncobj */
258 __u32 nr_out_syncobjs; /* in, number of entries in out_syncobj. */
259 __u32 syncobj_stride; /* in, stride of syncobj arrays. */
260 __u32 pad; /*in, reserved for future use, always 0. */
261
240};262};
241 263
242/* The normal way to synchronize with the GPU is just to CPU_PREP on264/* The normal way to synchronize with the GPU is just to CPU_PREP on

Keyboard shortcuts

General

Show keyboard shortcuts
?
Focus the current search
/

Issues and pull requests

Open filters
f

Issues, pull requests and Inbox

Select next item
j↓
Select previous item
k↑
Open selected item
Enter
Dismiss filters or clear selection
Esc

Repository code

Go to file
t