0001
0002
0003
0004
0005
0006
0007
0008
0009 #include "adreno_gpu.h"
0010
0011 bool hang_debug = false;
0012 MODULE_PARM_DESC(hang_debug, "Dump registers when hang is detected (can be slow!)");
0013 module_param_named(hang_debug, hang_debug, bool, 0600);
0014
0015 bool snapshot_debugbus = false;
0016 MODULE_PARM_DESC(snapshot_debugbus, "Include debugbus sections in GPU devcoredump (if not fused off)");
0017 module_param_named(snapshot_debugbus, snapshot_debugbus, bool, 0600);
0018
0019 bool allow_vram_carveout = false;
0020 MODULE_PARM_DESC(allow_vram_carveout, "Allow using VRAM Carveout, in place of IOMMU");
0021 module_param_named(allow_vram_carveout, allow_vram_carveout, bool, 0600);
0022
0023 static const struct adreno_info gpulist[] = {
0024 {
0025 .rev = ADRENO_REV(2, 0, 0, 0),
0026 .revn = 200,
0027 .name = "A200",
0028 .fw = {
0029 [ADRENO_FW_PM4] = "yamato_pm4.fw",
0030 [ADRENO_FW_PFP] = "yamato_pfp.fw",
0031 },
0032 .gmem = SZ_256K,
0033 .inactive_period = DRM_MSM_INACTIVE_PERIOD,
0034 .init = a2xx_gpu_init,
0035 }, {
0036 .rev = ADRENO_REV(2, 0, 0, 1),
0037 .revn = 201,
0038 .name = "A200",
0039 .fw = {
0040 [ADRENO_FW_PM4] = "yamato_pm4.fw",
0041 [ADRENO_FW_PFP] = "yamato_pfp.fw",
0042 },
0043 .gmem = SZ_128K,
0044 .inactive_period = DRM_MSM_INACTIVE_PERIOD,
0045 .init = a2xx_gpu_init,
0046 }, {
0047 .rev = ADRENO_REV(2, 2, 0, ANY_ID),
0048 .revn = 220,
0049 .name = "A220",
0050 .fw = {
0051 [ADRENO_FW_PM4] = "leia_pm4_470.fw",
0052 [ADRENO_FW_PFP] = "leia_pfp_470.fw",
0053 },
0054 .gmem = SZ_512K,
0055 .inactive_period = DRM_MSM_INACTIVE_PERIOD,
0056 .init = a2xx_gpu_init,
0057 }, {
0058 .rev = ADRENO_REV(3, 0, 5, ANY_ID),
0059 .revn = 305,
0060 .name = "A305",
0061 .fw = {
0062 [ADRENO_FW_PM4] = "a300_pm4.fw",
0063 [ADRENO_FW_PFP] = "a300_pfp.fw",
0064 },
0065 .gmem = SZ_256K,
0066 .inactive_period = DRM_MSM_INACTIVE_PERIOD,
0067 .init = a3xx_gpu_init,
0068 }, {
0069 .rev = ADRENO_REV(3, 0, 6, 0),
0070 .revn = 307,
0071 .name = "A306",
0072 .fw = {
0073 [ADRENO_FW_PM4] = "a300_pm4.fw",
0074 [ADRENO_FW_PFP] = "a300_pfp.fw",
0075 },
0076 .gmem = SZ_128K,
0077 .inactive_period = DRM_MSM_INACTIVE_PERIOD,
0078 .init = a3xx_gpu_init,
0079 }, {
0080 .rev = ADRENO_REV(3, 2, ANY_ID, ANY_ID),
0081 .revn = 320,
0082 .name = "A320",
0083 .fw = {
0084 [ADRENO_FW_PM4] = "a300_pm4.fw",
0085 [ADRENO_FW_PFP] = "a300_pfp.fw",
0086 },
0087 .gmem = SZ_512K,
0088 .inactive_period = DRM_MSM_INACTIVE_PERIOD,
0089 .init = a3xx_gpu_init,
0090 }, {
0091 .rev = ADRENO_REV(3, 3, 0, ANY_ID),
0092 .revn = 330,
0093 .name = "A330",
0094 .fw = {
0095 [ADRENO_FW_PM4] = "a330_pm4.fw",
0096 [ADRENO_FW_PFP] = "a330_pfp.fw",
0097 },
0098 .gmem = SZ_1M,
0099 .inactive_period = DRM_MSM_INACTIVE_PERIOD,
0100 .init = a3xx_gpu_init,
0101 }, {
0102 .rev = ADRENO_REV(4, 0, 5, ANY_ID),
0103 .revn = 405,
0104 .name = "A405",
0105 .fw = {
0106 [ADRENO_FW_PM4] = "a420_pm4.fw",
0107 [ADRENO_FW_PFP] = "a420_pfp.fw",
0108 },
0109 .gmem = SZ_256K,
0110 .inactive_period = DRM_MSM_INACTIVE_PERIOD,
0111 .init = a4xx_gpu_init,
0112 }, {
0113 .rev = ADRENO_REV(4, 2, 0, ANY_ID),
0114 .revn = 420,
0115 .name = "A420",
0116 .fw = {
0117 [ADRENO_FW_PM4] = "a420_pm4.fw",
0118 [ADRENO_FW_PFP] = "a420_pfp.fw",
0119 },
0120 .gmem = (SZ_1M + SZ_512K),
0121 .inactive_period = DRM_MSM_INACTIVE_PERIOD,
0122 .init = a4xx_gpu_init,
0123 }, {
0124 .rev = ADRENO_REV(4, 3, 0, ANY_ID),
0125 .revn = 430,
0126 .name = "A430",
0127 .fw = {
0128 [ADRENO_FW_PM4] = "a420_pm4.fw",
0129 [ADRENO_FW_PFP] = "a420_pfp.fw",
0130 },
0131 .gmem = (SZ_1M + SZ_512K),
0132 .inactive_period = DRM_MSM_INACTIVE_PERIOD,
0133 .init = a4xx_gpu_init,
0134 }, {
0135 .rev = ADRENO_REV(5, 0, 6, ANY_ID),
0136 .revn = 506,
0137 .name = "A506",
0138 .fw = {
0139 [ADRENO_FW_PM4] = "a530_pm4.fw",
0140 [ADRENO_FW_PFP] = "a530_pfp.fw",
0141 },
0142 .gmem = (SZ_128K + SZ_8K),
0143
0144
0145
0146
0147 .inactive_period = 250,
0148 .quirks = ADRENO_QUIRK_TWO_PASS_USE_WFI |
0149 ADRENO_QUIRK_LMLOADKILL_DISABLE,
0150 .init = a5xx_gpu_init,
0151 .zapfw = "a506_zap.mdt",
0152 }, {
0153 .rev = ADRENO_REV(5, 0, 8, ANY_ID),
0154 .revn = 508,
0155 .name = "A508",
0156 .fw = {
0157 [ADRENO_FW_PM4] = "a530_pm4.fw",
0158 [ADRENO_FW_PFP] = "a530_pfp.fw",
0159 },
0160 .gmem = (SZ_128K + SZ_8K),
0161
0162
0163
0164
0165 .inactive_period = 250,
0166 .quirks = ADRENO_QUIRK_LMLOADKILL_DISABLE,
0167 .init = a5xx_gpu_init,
0168 .zapfw = "a508_zap.mdt",
0169 }, {
0170 .rev = ADRENO_REV(5, 0, 9, ANY_ID),
0171 .revn = 509,
0172 .name = "A509",
0173 .fw = {
0174 [ADRENO_FW_PM4] = "a530_pm4.fw",
0175 [ADRENO_FW_PFP] = "a530_pfp.fw",
0176 },
0177 .gmem = (SZ_256K + SZ_16K),
0178
0179
0180
0181
0182 .inactive_period = 250,
0183 .quirks = ADRENO_QUIRK_LMLOADKILL_DISABLE,
0184 .init = a5xx_gpu_init,
0185
0186 .zapfw = "a512_zap.mdt",
0187 }, {
0188 .rev = ADRENO_REV(5, 1, 0, ANY_ID),
0189 .revn = 510,
0190 .name = "A510",
0191 .fw = {
0192 [ADRENO_FW_PM4] = "a530_pm4.fw",
0193 [ADRENO_FW_PFP] = "a530_pfp.fw",
0194 },
0195 .gmem = SZ_256K,
0196
0197
0198
0199
0200 .inactive_period = 250,
0201 .init = a5xx_gpu_init,
0202 }, {
0203 .rev = ADRENO_REV(5, 1, 2, ANY_ID),
0204 .revn = 512,
0205 .name = "A512",
0206 .fw = {
0207 [ADRENO_FW_PM4] = "a530_pm4.fw",
0208 [ADRENO_FW_PFP] = "a530_pfp.fw",
0209 },
0210 .gmem = (SZ_256K + SZ_16K),
0211
0212
0213
0214
0215 .inactive_period = 250,
0216 .quirks = ADRENO_QUIRK_LMLOADKILL_DISABLE,
0217 .init = a5xx_gpu_init,
0218 .zapfw = "a512_zap.mdt",
0219 }, {
0220 .rev = ADRENO_REV(5, 3, 0, 2),
0221 .revn = 530,
0222 .name = "A530",
0223 .fw = {
0224 [ADRENO_FW_PM4] = "a530_pm4.fw",
0225 [ADRENO_FW_PFP] = "a530_pfp.fw",
0226 [ADRENO_FW_GPMU] = "a530v3_gpmu.fw2",
0227 },
0228 .gmem = SZ_1M,
0229
0230
0231
0232
0233 .inactive_period = 250,
0234 .quirks = ADRENO_QUIRK_TWO_PASS_USE_WFI |
0235 ADRENO_QUIRK_FAULT_DETECT_MASK,
0236 .init = a5xx_gpu_init,
0237 .zapfw = "a530_zap.mdt",
0238 }, {
0239 .rev = ADRENO_REV(5, 4, 0, ANY_ID),
0240 .revn = 540,
0241 .name = "A540",
0242 .fw = {
0243 [ADRENO_FW_PM4] = "a530_pm4.fw",
0244 [ADRENO_FW_PFP] = "a530_pfp.fw",
0245 [ADRENO_FW_GPMU] = "a540_gpmu.fw2",
0246 },
0247 .gmem = SZ_1M,
0248
0249
0250
0251
0252 .inactive_period = 250,
0253 .quirks = ADRENO_QUIRK_LMLOADKILL_DISABLE,
0254 .init = a5xx_gpu_init,
0255 .zapfw = "a540_zap.mdt",
0256 }, {
0257 .rev = ADRENO_REV(6, 1, 8, ANY_ID),
0258 .revn = 618,
0259 .name = "A618",
0260 .fw = {
0261 [ADRENO_FW_SQE] = "a630_sqe.fw",
0262 [ADRENO_FW_GMU] = "a630_gmu.bin",
0263 },
0264 .gmem = SZ_512K,
0265 .inactive_period = DRM_MSM_INACTIVE_PERIOD,
0266 .init = a6xx_gpu_init,
0267 }, {
0268 .rev = ADRENO_REV(6, 1, 9, ANY_ID),
0269 .revn = 619,
0270 .name = "A619",
0271 .fw = {
0272 [ADRENO_FW_SQE] = "a630_sqe.fw",
0273 [ADRENO_FW_GMU] = "a619_gmu.bin",
0274 },
0275 .gmem = SZ_512K,
0276 .inactive_period = DRM_MSM_INACTIVE_PERIOD,
0277 .init = a6xx_gpu_init,
0278 .zapfw = "a615_zap.mdt",
0279 .hwcg = a615_hwcg,
0280 }, {
0281 .rev = ADRENO_REV(6, 3, 0, ANY_ID),
0282 .revn = 630,
0283 .name = "A630",
0284 .fw = {
0285 [ADRENO_FW_SQE] = "a630_sqe.fw",
0286 [ADRENO_FW_GMU] = "a630_gmu.bin",
0287 },
0288 .gmem = SZ_1M,
0289 .inactive_period = DRM_MSM_INACTIVE_PERIOD,
0290 .init = a6xx_gpu_init,
0291 .zapfw = "a630_zap.mdt",
0292 .hwcg = a630_hwcg,
0293 }, {
0294 .rev = ADRENO_REV(6, 4, 0, ANY_ID),
0295 .revn = 640,
0296 .name = "A640",
0297 .fw = {
0298 [ADRENO_FW_SQE] = "a630_sqe.fw",
0299 [ADRENO_FW_GMU] = "a640_gmu.bin",
0300 },
0301 .gmem = SZ_1M,
0302 .inactive_period = DRM_MSM_INACTIVE_PERIOD,
0303 .init = a6xx_gpu_init,
0304 .zapfw = "a640_zap.mdt",
0305 .hwcg = a640_hwcg,
0306 }, {
0307 .rev = ADRENO_REV(6, 5, 0, ANY_ID),
0308 .revn = 650,
0309 .name = "A650",
0310 .fw = {
0311 [ADRENO_FW_SQE] = "a650_sqe.fw",
0312 [ADRENO_FW_GMU] = "a650_gmu.bin",
0313 },
0314 .gmem = SZ_1M + SZ_128K,
0315 .inactive_period = DRM_MSM_INACTIVE_PERIOD,
0316 .init = a6xx_gpu_init,
0317 .zapfw = "a650_zap.mdt",
0318 .hwcg = a650_hwcg,
0319 .address_space_size = SZ_16G,
0320 }, {
0321 .rev = ADRENO_REV(6, 6, 0, ANY_ID),
0322 .revn = 660,
0323 .name = "A660",
0324 .fw = {
0325 [ADRENO_FW_SQE] = "a660_sqe.fw",
0326 [ADRENO_FW_GMU] = "a660_gmu.bin",
0327 },
0328 .gmem = SZ_1M + SZ_512K,
0329 .inactive_period = DRM_MSM_INACTIVE_PERIOD,
0330 .init = a6xx_gpu_init,
0331 .zapfw = "a660_zap.mdt",
0332 .hwcg = a660_hwcg,
0333 .address_space_size = SZ_16G,
0334 }, {
0335 .rev = ADRENO_REV(6, 3, 5, ANY_ID),
0336 .fw = {
0337 [ADRENO_FW_SQE] = "a660_sqe.fw",
0338 [ADRENO_FW_GMU] = "a660_gmu.bin",
0339 },
0340 .gmem = SZ_512K,
0341 .inactive_period = DRM_MSM_INACTIVE_PERIOD,
0342 .init = a6xx_gpu_init,
0343 .hwcg = a660_hwcg,
0344 .address_space_size = SZ_16G,
0345 }, {
0346 .rev = ADRENO_REV(6, 8, 0, ANY_ID),
0347 .revn = 680,
0348 .name = "A680",
0349 .fw = {
0350 [ADRENO_FW_SQE] = "a630_sqe.fw",
0351 [ADRENO_FW_GMU] = "a640_gmu.bin",
0352 },
0353 .gmem = SZ_2M,
0354 .inactive_period = DRM_MSM_INACTIVE_PERIOD,
0355 .init = a6xx_gpu_init,
0356 .zapfw = "a640_zap.mdt",
0357 .hwcg = a640_hwcg,
0358 },
0359 };
0360
0361 MODULE_FIRMWARE("qcom/a300_pm4.fw");
0362 MODULE_FIRMWARE("qcom/a300_pfp.fw");
0363 MODULE_FIRMWARE("qcom/a330_pm4.fw");
0364 MODULE_FIRMWARE("qcom/a330_pfp.fw");
0365 MODULE_FIRMWARE("qcom/a420_pm4.fw");
0366 MODULE_FIRMWARE("qcom/a420_pfp.fw");
0367 MODULE_FIRMWARE("qcom/a530_pm4.fw");
0368 MODULE_FIRMWARE("qcom/a530_pfp.fw");
0369 MODULE_FIRMWARE("qcom/a530v3_gpmu.fw2");
0370 MODULE_FIRMWARE("qcom/a530_zap.mdt");
0371 MODULE_FIRMWARE("qcom/a530_zap.b00");
0372 MODULE_FIRMWARE("qcom/a530_zap.b01");
0373 MODULE_FIRMWARE("qcom/a530_zap.b02");
0374 MODULE_FIRMWARE("qcom/a619_gmu.bin");
0375 MODULE_FIRMWARE("qcom/a630_sqe.fw");
0376 MODULE_FIRMWARE("qcom/a630_gmu.bin");
0377 MODULE_FIRMWARE("qcom/a630_zap.mbn");
0378
0379 static inline bool _rev_match(uint8_t entry, uint8_t id)
0380 {
0381 return (entry == ANY_ID) || (entry == id);
0382 }
0383
0384 bool adreno_cmp_rev(struct adreno_rev rev1, struct adreno_rev rev2)
0385 {
0386
0387 return _rev_match(rev1.core, rev2.core) &&
0388 _rev_match(rev1.major, rev2.major) &&
0389 _rev_match(rev1.minor, rev2.minor) &&
0390 _rev_match(rev1.patchid, rev2.patchid);
0391 }
0392
0393 const struct adreno_info *adreno_info(struct adreno_rev rev)
0394 {
0395 int i;
0396
0397
0398 for (i = 0; i < ARRAY_SIZE(gpulist); i++) {
0399 const struct adreno_info *info = &gpulist[i];
0400 if (adreno_cmp_rev(info->rev, rev))
0401 return info;
0402 }
0403
0404 return NULL;
0405 }
0406
0407 struct msm_gpu *adreno_load_gpu(struct drm_device *dev)
0408 {
0409 struct msm_drm_private *priv = dev->dev_private;
0410 struct platform_device *pdev = priv->gpu_pdev;
0411 struct msm_gpu *gpu = NULL;
0412 struct adreno_gpu *adreno_gpu;
0413 int ret;
0414
0415 if (pdev)
0416 gpu = dev_to_gpu(&pdev->dev);
0417
0418 if (!gpu) {
0419 dev_err_once(dev->dev, "no GPU device was found\n");
0420 return NULL;
0421 }
0422
0423 adreno_gpu = to_adreno_gpu(gpu);
0424
0425
0426
0427
0428
0429
0430
0431 ret = adreno_load_fw(adreno_gpu);
0432 if (ret)
0433 return NULL;
0434
0435
0436
0437
0438
0439 pm_runtime_enable(&pdev->dev);
0440
0441
0442 pm_runtime_set_active(&pdev->dev);
0443
0444 ret = pm_runtime_get_sync(&pdev->dev);
0445 if (ret < 0) {
0446 pm_runtime_put_sync(&pdev->dev);
0447 DRM_DEV_ERROR(dev->dev, "Couldn't power up the GPU: %d\n", ret);
0448 return NULL;
0449 }
0450
0451 mutex_lock(&gpu->lock);
0452 ret = msm_gpu_hw_init(gpu);
0453 mutex_unlock(&gpu->lock);
0454 pm_runtime_put_autosuspend(&pdev->dev);
0455 if (ret) {
0456 DRM_DEV_ERROR(dev->dev, "gpu hw init failed: %d\n", ret);
0457 return NULL;
0458 }
0459
0460 #ifdef CONFIG_DEBUG_FS
0461 if (gpu->funcs->debugfs_init) {
0462 gpu->funcs->debugfs_init(gpu, dev->primary);
0463 gpu->funcs->debugfs_init(gpu, dev->render);
0464 }
0465 #endif
0466
0467 return gpu;
0468 }
0469
0470 static int find_chipid(struct device *dev, struct adreno_rev *rev)
0471 {
0472 struct device_node *node = dev->of_node;
0473 const char *compat;
0474 int ret;
0475 u32 chipid;
0476
0477
0478 ret = of_property_read_string_index(node, "compatible", 0, &compat);
0479 if (ret == 0) {
0480 unsigned int r, patch;
0481
0482 if (sscanf(compat, "qcom,adreno-%u.%u", &r, &patch) == 2 ||
0483 sscanf(compat, "amd,imageon-%u.%u", &r, &patch) == 2) {
0484 rev->core = r / 100;
0485 r %= 100;
0486 rev->major = r / 10;
0487 r %= 10;
0488 rev->minor = r;
0489 rev->patchid = patch;
0490
0491 return 0;
0492 }
0493 }
0494
0495
0496 ret = of_property_read_u32(node, "qcom,chipid", &chipid);
0497 if (ret) {
0498 DRM_DEV_ERROR(dev, "could not parse qcom,chipid: %d\n", ret);
0499 return ret;
0500 }
0501
0502 rev->core = (chipid >> 24) & 0xff;
0503 rev->major = (chipid >> 16) & 0xff;
0504 rev->minor = (chipid >> 8) & 0xff;
0505 rev->patchid = (chipid & 0xff);
0506
0507 dev_warn(dev, "Using legacy qcom,chipid binding!\n");
0508 dev_warn(dev, "Use compatible qcom,adreno-%u%u%u.%u instead.\n",
0509 rev->core, rev->major, rev->minor, rev->patchid);
0510
0511 return 0;
0512 }
0513
0514 static int adreno_bind(struct device *dev, struct device *master, void *data)
0515 {
0516 static struct adreno_platform_config config = {};
0517 const struct adreno_info *info;
0518 struct msm_drm_private *priv = dev_get_drvdata(master);
0519 struct drm_device *drm = priv->dev;
0520 struct msm_gpu *gpu;
0521 int ret;
0522
0523 ret = find_chipid(dev, &config.rev);
0524 if (ret)
0525 return ret;
0526
0527 dev->platform_data = &config;
0528 priv->gpu_pdev = to_platform_device(dev);
0529
0530 info = adreno_info(config.rev);
0531
0532 if (!info) {
0533 dev_warn(drm->dev, "Unknown GPU revision: %u.%u.%u.%u\n",
0534 config.rev.core, config.rev.major,
0535 config.rev.minor, config.rev.patchid);
0536 return -ENXIO;
0537 }
0538
0539 DBG("Found GPU: %u.%u.%u.%u", config.rev.core, config.rev.major,
0540 config.rev.minor, config.rev.patchid);
0541
0542 priv->is_a2xx = config.rev.core == 2;
0543 priv->has_cached_coherent = config.rev.core >= 6;
0544
0545 gpu = info->init(drm);
0546 if (IS_ERR(gpu)) {
0547 dev_warn(drm->dev, "failed to load adreno gpu\n");
0548 return PTR_ERR(gpu);
0549 }
0550
0551 return 0;
0552 }
0553
0554 static void adreno_unbind(struct device *dev, struct device *master,
0555 void *data)
0556 {
0557 struct msm_drm_private *priv = dev_get_drvdata(master);
0558 struct msm_gpu *gpu = dev_to_gpu(dev);
0559
0560 pm_runtime_force_suspend(dev);
0561 gpu->funcs->destroy(gpu);
0562
0563 priv->gpu_pdev = NULL;
0564 }
0565
0566 static const struct component_ops a3xx_ops = {
0567 .bind = adreno_bind,
0568 .unbind = adreno_unbind,
0569 };
0570
0571 static void adreno_device_register_headless(void)
0572 {
0573
0574
0575
0576 struct platform_device_info dummy_info = {
0577 .parent = NULL,
0578 .name = "msm",
0579 .id = -1,
0580 .res = NULL,
0581 .num_res = 0,
0582 .data = NULL,
0583 .size_data = 0,
0584 .dma_mask = ~0,
0585 };
0586 platform_device_register_full(&dummy_info);
0587 }
0588
0589 static int adreno_probe(struct platform_device *pdev)
0590 {
0591
0592 int ret;
0593
0594 ret = component_add(&pdev->dev, &a3xx_ops);
0595 if (ret)
0596 return ret;
0597
0598 if (of_device_is_compatible(pdev->dev.of_node, "amd,imageon"))
0599 adreno_device_register_headless();
0600
0601 return 0;
0602 }
0603
0604 static int adreno_remove(struct platform_device *pdev)
0605 {
0606 component_del(&pdev->dev, &a3xx_ops);
0607 return 0;
0608 }
0609
0610 static void adreno_shutdown(struct platform_device *pdev)
0611 {
0612 pm_runtime_force_suspend(&pdev->dev);
0613 }
0614
0615 static const struct of_device_id dt_match[] = {
0616 { .compatible = "qcom,adreno" },
0617 { .compatible = "qcom,adreno-3xx" },
0618
0619 { .compatible = "amd,imageon" },
0620
0621 { .compatible = "qcom,kgsl-3d0" },
0622 {}
0623 };
0624
0625 static int adreno_runtime_resume(struct device *dev)
0626 {
0627 struct msm_gpu *gpu = dev_to_gpu(dev);
0628
0629 return gpu->funcs->pm_resume(gpu);
0630 }
0631
0632 static int adreno_runtime_suspend(struct device *dev)
0633 {
0634 struct msm_gpu *gpu = dev_to_gpu(dev);
0635
0636
0637
0638
0639
0640
0641 WARN_ON_ONCE(gpu->active_submits);
0642
0643 return gpu->funcs->pm_suspend(gpu);
0644 }
0645
0646 static void suspend_scheduler(struct msm_gpu *gpu)
0647 {
0648 int i;
0649
0650
0651
0652
0653
0654
0655
0656
0657
0658
0659
0660
0661 for (i = 0; i < gpu->nr_rings; i++) {
0662 struct drm_gpu_scheduler *sched = &gpu->rb[i]->sched;
0663 kthread_park(sched->thread);
0664 }
0665 }
0666
0667 static void resume_scheduler(struct msm_gpu *gpu)
0668 {
0669 int i;
0670
0671 for (i = 0; i < gpu->nr_rings; i++) {
0672 struct drm_gpu_scheduler *sched = &gpu->rb[i]->sched;
0673 kthread_unpark(sched->thread);
0674 }
0675 }
0676
0677 static int adreno_system_suspend(struct device *dev)
0678 {
0679 struct msm_gpu *gpu = dev_to_gpu(dev);
0680 int remaining, ret;
0681
0682 suspend_scheduler(gpu);
0683
0684 remaining = wait_event_timeout(gpu->retire_event,
0685 gpu->active_submits == 0,
0686 msecs_to_jiffies(1000));
0687 if (remaining == 0) {
0688 dev_err(dev, "Timeout waiting for GPU to suspend\n");
0689 ret = -EBUSY;
0690 goto out;
0691 }
0692
0693 ret = pm_runtime_force_suspend(dev);
0694 out:
0695 if (ret)
0696 resume_scheduler(gpu);
0697
0698 return ret;
0699 }
0700
0701 static int adreno_system_resume(struct device *dev)
0702 {
0703 resume_scheduler(dev_to_gpu(dev));
0704 return pm_runtime_force_resume(dev);
0705 }
0706
0707 static const struct dev_pm_ops adreno_pm_ops = {
0708 SYSTEM_SLEEP_PM_OPS(adreno_system_suspend, adreno_system_resume)
0709 RUNTIME_PM_OPS(adreno_runtime_suspend, adreno_runtime_resume, NULL)
0710 };
0711
0712 static struct platform_driver adreno_driver = {
0713 .probe = adreno_probe,
0714 .remove = adreno_remove,
0715 .shutdown = adreno_shutdown,
0716 .driver = {
0717 .name = "adreno",
0718 .of_match_table = dt_match,
0719 .pm = &adreno_pm_ops,
0720 },
0721 };
0722
0723 void __init adreno_register(void)
0724 {
0725 platform_driver_register(&adreno_driver);
0726 }
0727
0728 void __exit adreno_unregister(void)
0729 {
0730 platform_driver_unregister(&adreno_driver);
0731 }