linux/drivers/gpu/drm/msm/adreno/adreno_device.c
<<
>>
Prefs
   1// SPDX-License-Identifier: GPL-2.0-only
   2/*
   3 * Copyright (C) 2013-2014 Red Hat
   4 * Author: Rob Clark <robdclark@gmail.com>
   5 *
   6 * Copyright (c) 2014,2017 The Linux Foundation. All rights reserved.
   7 */
   8
   9#include "adreno_gpu.h"
  10
  11bool hang_debug = false;
  12MODULE_PARM_DESC(hang_debug, "Dump registers when hang is detected (can be slow!)");
  13module_param_named(hang_debug, hang_debug, bool, 0600);
  14
  15bool snapshot_debugbus = false;
  16MODULE_PARM_DESC(snapshot_debugbus, "Include debugbus sections in GPU devcoredump (if not fused off)");
  17module_param_named(snapshot_debugbus, snapshot_debugbus, bool, 0600);
  18
  19bool allow_vram_carveout = false;
  20MODULE_PARM_DESC(allow_vram_carveout, "Allow using VRAM Carveout, in place of IOMMU");
  21module_param_named(allow_vram_carveout, allow_vram_carveout, bool, 0600);
  22
  23static const struct adreno_info gpulist[] = {
  24        {
  25                .rev   = ADRENO_REV(2, 0, 0, 0),
  26                .revn  = 200,
  27                .name  = "A200",
  28                .fw = {
  29                        [ADRENO_FW_PM4] = "yamato_pm4.fw",
  30                        [ADRENO_FW_PFP] = "yamato_pfp.fw",
  31                },
  32                .gmem  = SZ_256K,
  33                .inactive_period = DRM_MSM_INACTIVE_PERIOD,
  34                .init  = a2xx_gpu_init,
  35        }, { /* a200 on i.mx51 has only 128kib gmem */
  36                .rev   = ADRENO_REV(2, 0, 0, 1),
  37                .revn  = 201,
  38                .name  = "A200",
  39                .fw = {
  40                        [ADRENO_FW_PM4] = "yamato_pm4.fw",
  41                        [ADRENO_FW_PFP] = "yamato_pfp.fw",
  42                },
  43                .gmem  = SZ_128K,
  44                .inactive_period = DRM_MSM_INACTIVE_PERIOD,
  45                .init  = a2xx_gpu_init,
  46        }, {
  47                .rev   = ADRENO_REV(2, 2, 0, ANY_ID),
  48                .revn  = 220,
  49                .name  = "A220",
  50                .fw = {
  51                        [ADRENO_FW_PM4] = "leia_pm4_470.fw",
  52                        [ADRENO_FW_PFP] = "leia_pfp_470.fw",
  53                },
  54                .gmem  = SZ_512K,
  55                .inactive_period = DRM_MSM_INACTIVE_PERIOD,
  56                .init  = a2xx_gpu_init,
  57        }, {
  58                .rev   = ADRENO_REV(3, 0, 5, ANY_ID),
  59                .revn  = 305,
  60                .name  = "A305",
  61                .fw = {
  62                        [ADRENO_FW_PM4] = "a300_pm4.fw",
  63                        [ADRENO_FW_PFP] = "a300_pfp.fw",
  64                },
  65                .gmem  = SZ_256K,
  66                .inactive_period = DRM_MSM_INACTIVE_PERIOD,
  67                .init  = a3xx_gpu_init,
  68        }, {
  69                .rev   = ADRENO_REV(3, 0, 6, 0),
  70                .revn  = 307,        /* because a305c is revn==306 */
  71                .name  = "A306",
  72                .fw = {
  73                        [ADRENO_FW_PM4] = "a300_pm4.fw",
  74                        [ADRENO_FW_PFP] = "a300_pfp.fw",
  75                },
  76                .gmem  = SZ_128K,
  77                .inactive_period = DRM_MSM_INACTIVE_PERIOD,
  78                .init  = a3xx_gpu_init,
  79        }, {
  80                .rev   = ADRENO_REV(3, 2, ANY_ID, ANY_ID),
  81                .revn  = 320,
  82                .name  = "A320",
  83                .fw = {
  84                        [ADRENO_FW_PM4] = "a300_pm4.fw",
  85                        [ADRENO_FW_PFP] = "a300_pfp.fw",
  86                },
  87                .gmem  = SZ_512K,
  88                .inactive_period = DRM_MSM_INACTIVE_PERIOD,
  89                .init  = a3xx_gpu_init,
  90        }, {
  91                .rev   = ADRENO_REV(3, 3, 0, ANY_ID),
  92                .revn  = 330,
  93                .name  = "A330",
  94                .fw = {
  95                        [ADRENO_FW_PM4] = "a330_pm4.fw",
  96                        [ADRENO_FW_PFP] = "a330_pfp.fw",
  97                },
  98                .gmem  = SZ_1M,
  99                .inactive_period = DRM_MSM_INACTIVE_PERIOD,
 100                .init  = a3xx_gpu_init,
 101        }, {
 102                .rev   = ADRENO_REV(4, 0, 5, ANY_ID),
 103                .revn  = 405,
 104                .name  = "A405",
 105                .fw = {
 106                        [ADRENO_FW_PM4] = "a420_pm4.fw",
 107                        [ADRENO_FW_PFP] = "a420_pfp.fw",
 108                },
 109                .gmem  = SZ_256K,
 110                .inactive_period = DRM_MSM_INACTIVE_PERIOD,
 111                .init  = a4xx_gpu_init,
 112        }, {
 113                .rev   = ADRENO_REV(4, 2, 0, ANY_ID),
 114                .revn  = 420,
 115                .name  = "A420",
 116                .fw = {
 117                        [ADRENO_FW_PM4] = "a420_pm4.fw",
 118                        [ADRENO_FW_PFP] = "a420_pfp.fw",
 119                },
 120                .gmem  = (SZ_1M + SZ_512K),
 121                .inactive_period = DRM_MSM_INACTIVE_PERIOD,
 122                .init  = a4xx_gpu_init,
 123        }, {
 124                .rev   = ADRENO_REV(4, 3, 0, ANY_ID),
 125                .revn  = 430,
 126                .name  = "A430",
 127                .fw = {
 128                        [ADRENO_FW_PM4] = "a420_pm4.fw",
 129                        [ADRENO_FW_PFP] = "a420_pfp.fw",
 130                },
 131                .gmem  = (SZ_1M + SZ_512K),
 132                .inactive_period = DRM_MSM_INACTIVE_PERIOD,
 133                .init  = a4xx_gpu_init,
 134        }, {
 135                .rev   = ADRENO_REV(5, 0, 8, ANY_ID),
 136                .revn = 508,
 137                .name = "A508",
 138                .fw = {
 139                        [ADRENO_FW_PM4] = "a530_pm4.fw",
 140                        [ADRENO_FW_PFP] = "a530_pfp.fw",
 141                },
 142                .gmem = (SZ_128K + SZ_8K),
 143                /*
 144                 * Increase inactive period to 250 to avoid bouncing
 145                 * the GDSC which appears to make it grumpy
 146                 */
 147                .inactive_period = 250,
 148                .quirks = ADRENO_QUIRK_LMLOADKILL_DISABLE,
 149                .init = a5xx_gpu_init,
 150                .zapfw = "a508_zap.mdt",
 151        }, {
 152                .rev   = ADRENO_REV(5, 0, 9, ANY_ID),
 153                .revn = 509,
 154                .name = "A509",
 155                .fw = {
 156                        [ADRENO_FW_PM4] = "a530_pm4.fw",
 157                        [ADRENO_FW_PFP] = "a530_pfp.fw",
 158                },
 159                .gmem = (SZ_256K + SZ_16K),
 160                /*
 161                 * Increase inactive period to 250 to avoid bouncing
 162                 * the GDSC which appears to make it grumpy
 163                 */
 164                .inactive_period = 250,
 165                .quirks = ADRENO_QUIRK_LMLOADKILL_DISABLE,
 166                .init = a5xx_gpu_init,
 167                /* Adreno 509 uses the same ZAP as 512 */
 168                .zapfw = "a512_zap.mdt",
 169        }, {
 170                .rev   = ADRENO_REV(5, 1, 0, ANY_ID),
 171                .revn = 510,
 172                .name = "A510",
 173                .fw = {
 174                        [ADRENO_FW_PM4] = "a530_pm4.fw",
 175                        [ADRENO_FW_PFP] = "a530_pfp.fw",
 176                },
 177                .gmem = SZ_256K,
 178                /*
 179                 * Increase inactive period to 250 to avoid bouncing
 180                 * the GDSC which appears to make it grumpy
 181                 */
 182                .inactive_period = 250,
 183                .init = a5xx_gpu_init,
 184        }, {
 185                .rev   = ADRENO_REV(5, 1, 2, ANY_ID),
 186                .revn = 512,
 187                .name = "A512",
 188                .fw = {
 189                        [ADRENO_FW_PM4] = "a530_pm4.fw",
 190                        [ADRENO_FW_PFP] = "a530_pfp.fw",
 191                },
 192                .gmem = (SZ_256K + SZ_16K),
 193                /*
 194                 * Increase inactive period to 250 to avoid bouncing
 195                 * the GDSC which appears to make it grumpy
 196                 */
 197                .inactive_period = 250,
 198                .quirks = ADRENO_QUIRK_LMLOADKILL_DISABLE,
 199                .init = a5xx_gpu_init,
 200                .zapfw = "a512_zap.mdt",
 201        }, {
 202                .rev = ADRENO_REV(5, 3, 0, 2),
 203                .revn = 530,
 204                .name = "A530",
 205                .fw = {
 206                        [ADRENO_FW_PM4] = "a530_pm4.fw",
 207                        [ADRENO_FW_PFP] = "a530_pfp.fw",
 208                        [ADRENO_FW_GPMU] = "a530v3_gpmu.fw2",
 209                },
 210                .gmem = SZ_1M,
 211                /*
 212                 * Increase inactive period to 250 to avoid bouncing
 213                 * the GDSC which appears to make it grumpy
 214                 */
 215                .inactive_period = 250,
 216                .quirks = ADRENO_QUIRK_TWO_PASS_USE_WFI |
 217                        ADRENO_QUIRK_FAULT_DETECT_MASK,
 218                .init = a5xx_gpu_init,
 219                .zapfw = "a530_zap.mdt",
 220        }, {
 221                .rev = ADRENO_REV(5, 4, 0, ANY_ID),
 222                .revn = 540,
 223                .name = "A540",
 224                .fw = {
 225                        [ADRENO_FW_PM4] = "a530_pm4.fw",
 226                        [ADRENO_FW_PFP] = "a530_pfp.fw",
 227                        [ADRENO_FW_GPMU] = "a540_gpmu.fw2",
 228                },
 229                .gmem = SZ_1M,
 230                /*
 231                 * Increase inactive period to 250 to avoid bouncing
 232                 * the GDSC which appears to make it grumpy
 233                 */
 234                .inactive_period = 250,
 235                .quirks = ADRENO_QUIRK_LMLOADKILL_DISABLE,
 236                .init = a5xx_gpu_init,
 237                .zapfw = "a540_zap.mdt",
 238        }, {
 239                .rev = ADRENO_REV(6, 1, 8, ANY_ID),
 240                .revn = 618,
 241                .name = "A618",
 242                .fw = {
 243                        [ADRENO_FW_SQE] = "a630_sqe.fw",
 244                        [ADRENO_FW_GMU] = "a630_gmu.bin",
 245                },
 246                .gmem = SZ_512K,
 247                .inactive_period = DRM_MSM_INACTIVE_PERIOD,
 248                .init = a6xx_gpu_init,
 249        }, {
 250                .rev = ADRENO_REV(6, 3, 0, ANY_ID),
 251                .revn = 630,
 252                .name = "A630",
 253                .fw = {
 254                        [ADRENO_FW_SQE] = "a630_sqe.fw",
 255                        [ADRENO_FW_GMU] = "a630_gmu.bin",
 256                },
 257                .gmem = SZ_1M,
 258                .inactive_period = DRM_MSM_INACTIVE_PERIOD,
 259                .init = a6xx_gpu_init,
 260                .zapfw = "a630_zap.mdt",
 261                .hwcg = a630_hwcg,
 262        }, {
 263                .rev = ADRENO_REV(6, 4, 0, ANY_ID),
 264                .revn = 640,
 265                .name = "A640",
 266                .fw = {
 267                        [ADRENO_FW_SQE] = "a630_sqe.fw",
 268                        [ADRENO_FW_GMU] = "a640_gmu.bin",
 269                },
 270                .gmem = SZ_1M,
 271                .inactive_period = DRM_MSM_INACTIVE_PERIOD,
 272                .init = a6xx_gpu_init,
 273                .zapfw = "a640_zap.mdt",
 274                .hwcg = a640_hwcg,
 275        }, {
 276                .rev = ADRENO_REV(6, 5, 0, ANY_ID),
 277                .revn = 650,
 278                .name = "A650",
 279                .fw = {
 280                        [ADRENO_FW_SQE] = "a650_sqe.fw",
 281                        [ADRENO_FW_GMU] = "a650_gmu.bin",
 282                },
 283                .gmem = SZ_1M + SZ_128K,
 284                .inactive_period = DRM_MSM_INACTIVE_PERIOD,
 285                .init = a6xx_gpu_init,
 286                .zapfw = "a650_zap.mdt",
 287                .hwcg = a650_hwcg,
 288        }, {
 289                .rev = ADRENO_REV(6, 6, 0, ANY_ID),
 290                .revn = 660,
 291                .name = "A660",
 292                .fw = {
 293                        [ADRENO_FW_SQE] = "a660_sqe.fw",
 294                        [ADRENO_FW_GMU] = "a660_gmu.bin",
 295                },
 296                .gmem = SZ_1M + SZ_512K,
 297                .inactive_period = DRM_MSM_INACTIVE_PERIOD,
 298                .init = a6xx_gpu_init,
 299                .zapfw = "a660_zap.mdt",
 300                .hwcg = a660_hwcg,
 301        }, {
 302                .rev = ADRENO_REV(6, 3, 5, ANY_ID),
 303                .name = "Adreno 7c Gen 3",
 304                .fw = {
 305                        [ADRENO_FW_SQE] = "a660_sqe.fw",
 306                        [ADRENO_FW_GMU] = "a660_gmu.bin",
 307                },
 308                .gmem = SZ_512K,
 309                .inactive_period = DRM_MSM_INACTIVE_PERIOD,
 310                .init = a6xx_gpu_init,
 311                .hwcg = a660_hwcg,
 312        }, {
 313                .rev = ADRENO_REV(6, 8, 0, ANY_ID),
 314                .revn = 680,
 315                .name = "A680",
 316                .fw = {
 317                        [ADRENO_FW_SQE] = "a630_sqe.fw",
 318                        [ADRENO_FW_GMU] = "a640_gmu.bin",
 319                },
 320                .gmem = SZ_2M,
 321                .inactive_period = DRM_MSM_INACTIVE_PERIOD,
 322                .init = a6xx_gpu_init,
 323                .zapfw = "a640_zap.mdt",
 324                .hwcg = a640_hwcg,
 325        },
 326};
 327
 328MODULE_FIRMWARE("qcom/a300_pm4.fw");
 329MODULE_FIRMWARE("qcom/a300_pfp.fw");
 330MODULE_FIRMWARE("qcom/a330_pm4.fw");
 331MODULE_FIRMWARE("qcom/a330_pfp.fw");
 332MODULE_FIRMWARE("qcom/a420_pm4.fw");
 333MODULE_FIRMWARE("qcom/a420_pfp.fw");
 334MODULE_FIRMWARE("qcom/a530_pm4.fw");
 335MODULE_FIRMWARE("qcom/a530_pfp.fw");
 336MODULE_FIRMWARE("qcom/a530v3_gpmu.fw2");
 337MODULE_FIRMWARE("qcom/a530_zap.mdt");
 338MODULE_FIRMWARE("qcom/a530_zap.b00");
 339MODULE_FIRMWARE("qcom/a530_zap.b01");
 340MODULE_FIRMWARE("qcom/a530_zap.b02");
 341MODULE_FIRMWARE("qcom/a630_sqe.fw");
 342MODULE_FIRMWARE("qcom/a630_gmu.bin");
 343MODULE_FIRMWARE("qcom/a630_zap.mbn");
 344
 345static inline bool _rev_match(uint8_t entry, uint8_t id)
 346{
 347        return (entry == ANY_ID) || (entry == id);
 348}
 349
 350bool adreno_cmp_rev(struct adreno_rev rev1, struct adreno_rev rev2)
 351{
 352
 353        return _rev_match(rev1.core, rev2.core) &&
 354                _rev_match(rev1.major, rev2.major) &&
 355                _rev_match(rev1.minor, rev2.minor) &&
 356                _rev_match(rev1.patchid, rev2.patchid);
 357}
 358
 359const struct adreno_info *adreno_info(struct adreno_rev rev)
 360{
 361        int i;
 362
 363        /* identify gpu: */
 364        for (i = 0; i < ARRAY_SIZE(gpulist); i++) {
 365                const struct adreno_info *info = &gpulist[i];
 366                if (adreno_cmp_rev(info->rev, rev))
 367                        return info;
 368        }
 369
 370        return NULL;
 371}
 372
 373struct msm_gpu *adreno_load_gpu(struct drm_device *dev)
 374{
 375        struct msm_drm_private *priv = dev->dev_private;
 376        struct platform_device *pdev = priv->gpu_pdev;
 377        struct msm_gpu *gpu = NULL;
 378        struct adreno_gpu *adreno_gpu;
 379        int ret;
 380
 381        if (pdev)
 382                gpu = dev_to_gpu(&pdev->dev);
 383
 384        if (!gpu) {
 385                dev_err_once(dev->dev, "no GPU device was found\n");
 386                return NULL;
 387        }
 388
 389        adreno_gpu = to_adreno_gpu(gpu);
 390
 391        /*
 392         * The number one reason for HW init to fail is if the firmware isn't
 393         * loaded yet. Try that first and don't bother continuing on
 394         * otherwise
 395         */
 396
 397        ret = adreno_load_fw(adreno_gpu);
 398        if (ret)
 399                return NULL;
 400
 401        /* Make sure pm runtime is active and reset any previous errors */
 402        pm_runtime_set_active(&pdev->dev);
 403
 404        ret = pm_runtime_get_sync(&pdev->dev);
 405        if (ret < 0) {
 406                pm_runtime_put_sync(&pdev->dev);
 407                DRM_DEV_ERROR(dev->dev, "Couldn't power up the GPU: %d\n", ret);
 408                return NULL;
 409        }
 410
 411        mutex_lock(&dev->struct_mutex);
 412        ret = msm_gpu_hw_init(gpu);
 413        mutex_unlock(&dev->struct_mutex);
 414        pm_runtime_put_autosuspend(&pdev->dev);
 415        if (ret) {
 416                DRM_DEV_ERROR(dev->dev, "gpu hw init failed: %d\n", ret);
 417                return NULL;
 418        }
 419
 420#ifdef CONFIG_DEBUG_FS
 421        if (gpu->funcs->debugfs_init) {
 422                gpu->funcs->debugfs_init(gpu, dev->primary);
 423                gpu->funcs->debugfs_init(gpu, dev->render);
 424        }
 425#endif
 426
 427        return gpu;
 428}
 429
 430static void set_gpu_pdev(struct drm_device *dev,
 431                struct platform_device *pdev)
 432{
 433        struct msm_drm_private *priv = dev->dev_private;
 434        priv->gpu_pdev = pdev;
 435}
 436
 437static int find_chipid(struct device *dev, struct adreno_rev *rev)
 438{
 439        struct device_node *node = dev->of_node;
 440        const char *compat;
 441        int ret;
 442        u32 chipid;
 443
 444        /* first search the compat strings for qcom,adreno-XYZ.W: */
 445        ret = of_property_read_string_index(node, "compatible", 0, &compat);
 446        if (ret == 0) {
 447                unsigned int r, patch;
 448
 449                if (sscanf(compat, "qcom,adreno-%u.%u", &r, &patch) == 2 ||
 450                    sscanf(compat, "amd,imageon-%u.%u", &r, &patch) == 2) {
 451                        rev->core = r / 100;
 452                        r %= 100;
 453                        rev->major = r / 10;
 454                        r %= 10;
 455                        rev->minor = r;
 456                        rev->patchid = patch;
 457
 458                        return 0;
 459                }
 460        }
 461
 462        /* and if that fails, fall back to legacy "qcom,chipid" property: */
 463        ret = of_property_read_u32(node, "qcom,chipid", &chipid);
 464        if (ret) {
 465                DRM_DEV_ERROR(dev, "could not parse qcom,chipid: %d\n", ret);
 466                return ret;
 467        }
 468
 469        rev->core = (chipid >> 24) & 0xff;
 470        rev->major = (chipid >> 16) & 0xff;
 471        rev->minor = (chipid >> 8) & 0xff;
 472        rev->patchid = (chipid & 0xff);
 473
 474        dev_warn(dev, "Using legacy qcom,chipid binding!\n");
 475        dev_warn(dev, "Use compatible qcom,adreno-%u%u%u.%u instead.\n",
 476                rev->core, rev->major, rev->minor, rev->patchid);
 477
 478        return 0;
 479}
 480
 481static int adreno_bind(struct device *dev, struct device *master, void *data)
 482{
 483        static struct adreno_platform_config config = {};
 484        const struct adreno_info *info;
 485        struct drm_device *drm = dev_get_drvdata(master);
 486        struct msm_drm_private *priv = drm->dev_private;
 487        struct msm_gpu *gpu;
 488        int ret;
 489
 490        ret = find_chipid(dev, &config.rev);
 491        if (ret)
 492                return ret;
 493
 494        dev->platform_data = &config;
 495        set_gpu_pdev(drm, to_platform_device(dev));
 496
 497        info = adreno_info(config.rev);
 498
 499        if (!info) {
 500                dev_warn(drm->dev, "Unknown GPU revision: %u.%u.%u.%u\n",
 501                        config.rev.core, config.rev.major,
 502                        config.rev.minor, config.rev.patchid);
 503                return -ENXIO;
 504        }
 505
 506        DBG("Found GPU: %u.%u.%u.%u", config.rev.core, config.rev.major,
 507                config.rev.minor, config.rev.patchid);
 508
 509        priv->is_a2xx = config.rev.core == 2;
 510        priv->has_cached_coherent = config.rev.core >= 6;
 511
 512        gpu = info->init(drm);
 513        if (IS_ERR(gpu)) {
 514                dev_warn(drm->dev, "failed to load adreno gpu\n");
 515                return PTR_ERR(gpu);
 516        }
 517
 518        return 0;
 519}
 520
 521static void adreno_unbind(struct device *dev, struct device *master,
 522                void *data)
 523{
 524        struct msm_gpu *gpu = dev_to_gpu(dev);
 525
 526        pm_runtime_force_suspend(dev);
 527        gpu->funcs->destroy(gpu);
 528
 529        set_gpu_pdev(dev_get_drvdata(master), NULL);
 530}
 531
 532static const struct component_ops a3xx_ops = {
 533                .bind   = adreno_bind,
 534                .unbind = adreno_unbind,
 535};
 536
 537static void adreno_device_register_headless(void)
 538{
 539        /* on imx5, we don't have a top-level mdp/dpu node
 540         * this creates a dummy node for the driver for that case
 541         */
 542        struct platform_device_info dummy_info = {
 543                .parent = NULL,
 544                .name = "msm",
 545                .id = -1,
 546                .res = NULL,
 547                .num_res = 0,
 548                .data = NULL,
 549                .size_data = 0,
 550                .dma_mask = ~0,
 551        };
 552        platform_device_register_full(&dummy_info);
 553}
 554
 555static int adreno_probe(struct platform_device *pdev)
 556{
 557
 558        int ret;
 559
 560        ret = component_add(&pdev->dev, &a3xx_ops);
 561        if (ret)
 562                return ret;
 563
 564        if (of_device_is_compatible(pdev->dev.of_node, "amd,imageon"))
 565                adreno_device_register_headless();
 566
 567        return 0;
 568}
 569
 570static int adreno_remove(struct platform_device *pdev)
 571{
 572        component_del(&pdev->dev, &a3xx_ops);
 573        return 0;
 574}
 575
 576static void adreno_shutdown(struct platform_device *pdev)
 577{
 578        pm_runtime_force_suspend(&pdev->dev);
 579}
 580
 581static const struct of_device_id dt_match[] = {
 582        { .compatible = "qcom,adreno" },
 583        { .compatible = "qcom,adreno-3xx" },
 584        /* for compatibility with imx5 gpu: */
 585        { .compatible = "amd,imageon" },
 586        /* for backwards compat w/ downstream kgsl DT files: */
 587        { .compatible = "qcom,kgsl-3d0" },
 588        {}
 589};
 590
 591#ifdef CONFIG_PM
 592static int adreno_resume(struct device *dev)
 593{
 594        struct msm_gpu *gpu = dev_to_gpu(dev);
 595
 596        return gpu->funcs->pm_resume(gpu);
 597}
 598
 599static int adreno_suspend(struct device *dev)
 600{
 601        struct msm_gpu *gpu = dev_to_gpu(dev);
 602
 603        return gpu->funcs->pm_suspend(gpu);
 604}
 605#endif
 606
 607static const struct dev_pm_ops adreno_pm_ops = {
 608        SET_SYSTEM_SLEEP_PM_OPS(pm_runtime_force_suspend, pm_runtime_force_resume)
 609        SET_RUNTIME_PM_OPS(adreno_suspend, adreno_resume, NULL)
 610};
 611
 612static struct platform_driver adreno_driver = {
 613        .probe = adreno_probe,
 614        .remove = adreno_remove,
 615        .shutdown = adreno_shutdown,
 616        .driver = {
 617                .name = "adreno",
 618                .of_match_table = dt_match,
 619                .pm = &adreno_pm_ops,
 620        },
 621};
 622
 623void __init adreno_register(void)
 624{
 625        platform_driver_register(&adreno_driver);
 626}
 627
 628void __exit adreno_unregister(void)
 629{
 630        platform_driver_unregister(&adreno_driver);
 631}
 632