linux/drivers/gpu/drm/mediatek/mtk_drm_drv.c
<<
>>
Prefs
   1// SPDX-License-Identifier: GPL-2.0-only
   2/*
   3 * Copyright (c) 2015 MediaTek Inc.
   4 * Author: YT SHEN <yt.shen@mediatek.com>
   5 */
   6
   7#include <linux/component.h>
   8#include <linux/iommu.h>
   9#include <linux/module.h>
  10#include <linux/of_address.h>
  11#include <linux/of_platform.h>
  12#include <linux/pm_runtime.h>
  13#include <linux/dma-mapping.h>
  14
  15#include <drm/drm_atomic.h>
  16#include <drm/drm_atomic_helper.h>
  17#include <drm/drm_drv.h>
  18#include <drm/drm_fb_helper.h>
  19#include <drm/drm_fourcc.h>
  20#include <drm/drm_gem.h>
  21#include <drm/drm_gem_cma_helper.h>
  22#include <drm/drm_gem_framebuffer_helper.h>
  23#include <drm/drm_of.h>
  24#include <drm/drm_probe_helper.h>
  25#include <drm/drm_vblank.h>
  26
  27#include "mtk_drm_crtc.h"
  28#include "mtk_drm_ddp_comp.h"
  29#include "mtk_drm_drv.h"
  30#include "mtk_drm_gem.h"
  31
  32#define DRIVER_NAME "mediatek"
  33#define DRIVER_DESC "Mediatek SoC DRM"
  34#define DRIVER_DATE "20150513"
  35#define DRIVER_MAJOR 1
  36#define DRIVER_MINOR 0
  37
  38static const struct drm_mode_config_helper_funcs mtk_drm_mode_config_helpers = {
  39        .atomic_commit_tail = drm_atomic_helper_commit_tail_rpm,
  40};
  41
  42static struct drm_framebuffer *
  43mtk_drm_mode_fb_create(struct drm_device *dev,
  44                       struct drm_file *file,
  45                       const struct drm_mode_fb_cmd2 *cmd)
  46{
  47        const struct drm_format_info *info = drm_get_format_info(dev, cmd);
  48
  49        if (info->num_planes != 1)
  50                return ERR_PTR(-EINVAL);
  51
  52        return drm_gem_fb_create(dev, file, cmd);
  53}
  54
  55static const struct drm_mode_config_funcs mtk_drm_mode_config_funcs = {
  56        .fb_create = mtk_drm_mode_fb_create,
  57        .atomic_check = drm_atomic_helper_check,
  58        .atomic_commit = drm_atomic_helper_commit,
  59};
  60
  61static const enum mtk_ddp_comp_id mt2701_mtk_ddp_main[] = {
  62        DDP_COMPONENT_OVL0,
  63        DDP_COMPONENT_RDMA0,
  64        DDP_COMPONENT_COLOR0,
  65        DDP_COMPONENT_BLS,
  66        DDP_COMPONENT_DSI0,
  67};
  68
  69static const enum mtk_ddp_comp_id mt2701_mtk_ddp_ext[] = {
  70        DDP_COMPONENT_RDMA1,
  71        DDP_COMPONENT_DPI0,
  72};
  73
  74static const enum mtk_ddp_comp_id mt7623_mtk_ddp_main[] = {
  75        DDP_COMPONENT_OVL0,
  76        DDP_COMPONENT_RDMA0,
  77        DDP_COMPONENT_COLOR0,
  78        DDP_COMPONENT_BLS,
  79        DDP_COMPONENT_DPI0,
  80};
  81
  82static const enum mtk_ddp_comp_id mt7623_mtk_ddp_ext[] = {
  83        DDP_COMPONENT_RDMA1,
  84        DDP_COMPONENT_DSI0,
  85};
  86
  87static const enum mtk_ddp_comp_id mt2712_mtk_ddp_main[] = {
  88        DDP_COMPONENT_OVL0,
  89        DDP_COMPONENT_COLOR0,
  90        DDP_COMPONENT_AAL0,
  91        DDP_COMPONENT_OD0,
  92        DDP_COMPONENT_RDMA0,
  93        DDP_COMPONENT_DPI0,
  94        DDP_COMPONENT_PWM0,
  95};
  96
  97static const enum mtk_ddp_comp_id mt2712_mtk_ddp_ext[] = {
  98        DDP_COMPONENT_OVL1,
  99        DDP_COMPONENT_COLOR1,
 100        DDP_COMPONENT_AAL1,
 101        DDP_COMPONENT_OD1,
 102        DDP_COMPONENT_RDMA1,
 103        DDP_COMPONENT_DPI1,
 104        DDP_COMPONENT_PWM1,
 105};
 106
 107static const enum mtk_ddp_comp_id mt2712_mtk_ddp_third[] = {
 108        DDP_COMPONENT_RDMA2,
 109        DDP_COMPONENT_DSI3,
 110        DDP_COMPONENT_PWM2,
 111};
 112
 113static enum mtk_ddp_comp_id mt8167_mtk_ddp_main[] = {
 114        DDP_COMPONENT_OVL0,
 115        DDP_COMPONENT_COLOR0,
 116        DDP_COMPONENT_CCORR,
 117        DDP_COMPONENT_AAL0,
 118        DDP_COMPONENT_GAMMA,
 119        DDP_COMPONENT_DITHER,
 120        DDP_COMPONENT_RDMA0,
 121        DDP_COMPONENT_DSI0,
 122};
 123
 124static const enum mtk_ddp_comp_id mt8173_mtk_ddp_main[] = {
 125        DDP_COMPONENT_OVL0,
 126        DDP_COMPONENT_COLOR0,
 127        DDP_COMPONENT_AAL0,
 128        DDP_COMPONENT_OD0,
 129        DDP_COMPONENT_RDMA0,
 130        DDP_COMPONENT_UFOE,
 131        DDP_COMPONENT_DSI0,
 132        DDP_COMPONENT_PWM0,
 133};
 134
 135static const enum mtk_ddp_comp_id mt8173_mtk_ddp_ext[] = {
 136        DDP_COMPONENT_OVL1,
 137        DDP_COMPONENT_COLOR1,
 138        DDP_COMPONENT_GAMMA,
 139        DDP_COMPONENT_RDMA1,
 140        DDP_COMPONENT_DPI0,
 141};
 142
 143static const enum mtk_ddp_comp_id mt8183_mtk_ddp_main[] = {
 144        DDP_COMPONENT_OVL0,
 145        DDP_COMPONENT_OVL_2L0,
 146        DDP_COMPONENT_RDMA0,
 147        DDP_COMPONENT_COLOR0,
 148        DDP_COMPONENT_CCORR,
 149        DDP_COMPONENT_AAL0,
 150        DDP_COMPONENT_GAMMA,
 151        DDP_COMPONENT_DITHER,
 152        DDP_COMPONENT_DSI0,
 153};
 154
 155static const enum mtk_ddp_comp_id mt8183_mtk_ddp_ext[] = {
 156        DDP_COMPONENT_OVL_2L1,
 157        DDP_COMPONENT_RDMA1,
 158        DDP_COMPONENT_DPI0,
 159};
 160
 161static const enum mtk_ddp_comp_id mt8192_mtk_ddp_main[] = {
 162        DDP_COMPONENT_OVL0,
 163        DDP_COMPONENT_OVL_2L0,
 164        DDP_COMPONENT_RDMA0,
 165        DDP_COMPONENT_COLOR0,
 166        DDP_COMPONENT_CCORR,
 167        DDP_COMPONENT_AAL0,
 168        DDP_COMPONENT_GAMMA,
 169        DDP_COMPONENT_POSTMASK0,
 170        DDP_COMPONENT_DITHER,
 171        DDP_COMPONENT_DSI0,
 172};
 173
 174static const enum mtk_ddp_comp_id mt8192_mtk_ddp_ext[] = {
 175        DDP_COMPONENT_OVL_2L2,
 176        DDP_COMPONENT_RDMA4,
 177        DDP_COMPONENT_DPI0,
 178};
 179
 180static const struct mtk_mmsys_driver_data mt2701_mmsys_driver_data = {
 181        .main_path = mt2701_mtk_ddp_main,
 182        .main_len = ARRAY_SIZE(mt2701_mtk_ddp_main),
 183        .ext_path = mt2701_mtk_ddp_ext,
 184        .ext_len = ARRAY_SIZE(mt2701_mtk_ddp_ext),
 185        .shadow_register = true,
 186};
 187
 188static const struct mtk_mmsys_driver_data mt7623_mmsys_driver_data = {
 189        .main_path = mt7623_mtk_ddp_main,
 190        .main_len = ARRAY_SIZE(mt7623_mtk_ddp_main),
 191        .ext_path = mt7623_mtk_ddp_ext,
 192        .ext_len = ARRAY_SIZE(mt7623_mtk_ddp_ext),
 193        .shadow_register = true,
 194};
 195
 196static const struct mtk_mmsys_driver_data mt2712_mmsys_driver_data = {
 197        .main_path = mt2712_mtk_ddp_main,
 198        .main_len = ARRAY_SIZE(mt2712_mtk_ddp_main),
 199        .ext_path = mt2712_mtk_ddp_ext,
 200        .ext_len = ARRAY_SIZE(mt2712_mtk_ddp_ext),
 201        .third_path = mt2712_mtk_ddp_third,
 202        .third_len = ARRAY_SIZE(mt2712_mtk_ddp_third),
 203};
 204
 205static const struct mtk_mmsys_driver_data mt8167_mmsys_driver_data = {
 206        .main_path = mt8167_mtk_ddp_main,
 207        .main_len = ARRAY_SIZE(mt8167_mtk_ddp_main),
 208};
 209
 210static const struct mtk_mmsys_driver_data mt8173_mmsys_driver_data = {
 211        .main_path = mt8173_mtk_ddp_main,
 212        .main_len = ARRAY_SIZE(mt8173_mtk_ddp_main),
 213        .ext_path = mt8173_mtk_ddp_ext,
 214        .ext_len = ARRAY_SIZE(mt8173_mtk_ddp_ext),
 215};
 216
 217static const struct mtk_mmsys_driver_data mt8183_mmsys_driver_data = {
 218        .main_path = mt8183_mtk_ddp_main,
 219        .main_len = ARRAY_SIZE(mt8183_mtk_ddp_main),
 220        .ext_path = mt8183_mtk_ddp_ext,
 221        .ext_len = ARRAY_SIZE(mt8183_mtk_ddp_ext),
 222};
 223
 224static const struct mtk_mmsys_driver_data mt8192_mmsys_driver_data = {
 225        .main_path = mt8192_mtk_ddp_main,
 226        .main_len = ARRAY_SIZE(mt8192_mtk_ddp_main),
 227        .ext_path = mt8192_mtk_ddp_ext,
 228        .ext_len = ARRAY_SIZE(mt8192_mtk_ddp_ext),
 229};
 230
 231static int mtk_drm_kms_init(struct drm_device *drm)
 232{
 233        struct mtk_drm_private *private = drm->dev_private;
 234        struct platform_device *pdev;
 235        struct device_node *np;
 236        struct device *dma_dev;
 237        int ret;
 238
 239        if (drm_firmware_drivers_only())
 240                return -ENODEV;
 241
 242        if (!iommu_present(&platform_bus_type))
 243                return -EPROBE_DEFER;
 244
 245        pdev = of_find_device_by_node(private->mutex_node);
 246        if (!pdev) {
 247                dev_err(drm->dev, "Waiting for disp-mutex device %pOF\n",
 248                        private->mutex_node);
 249                of_node_put(private->mutex_node);
 250                return -EPROBE_DEFER;
 251        }
 252        private->mutex_dev = &pdev->dev;
 253
 254        ret = drmm_mode_config_init(drm);
 255        if (ret)
 256                goto put_mutex_dev;
 257
 258        drm->mode_config.min_width = 64;
 259        drm->mode_config.min_height = 64;
 260
 261        /*
 262         * set max width and height as default value(4096x4096).
 263         * this value would be used to check framebuffer size limitation
 264         * at drm_mode_addfb().
 265         */
 266        drm->mode_config.max_width = 4096;
 267        drm->mode_config.max_height = 4096;
 268        drm->mode_config.funcs = &mtk_drm_mode_config_funcs;
 269        drm->mode_config.helper_private = &mtk_drm_mode_config_helpers;
 270
 271        ret = component_bind_all(drm->dev, drm);
 272        if (ret)
 273                goto put_mutex_dev;
 274
 275        /*
 276         * We currently support two fixed data streams, each optional,
 277         * and each statically assigned to a crtc:
 278         * OVL0 -> COLOR0 -> AAL -> OD -> RDMA0 -> UFOE -> DSI0 ...
 279         */
 280        ret = mtk_drm_crtc_create(drm, private->data->main_path,
 281                                  private->data->main_len);
 282        if (ret < 0)
 283                goto err_component_unbind;
 284        /* ... and OVL1 -> COLOR1 -> GAMMA -> RDMA1 -> DPI0. */
 285        ret = mtk_drm_crtc_create(drm, private->data->ext_path,
 286                                  private->data->ext_len);
 287        if (ret < 0)
 288                goto err_component_unbind;
 289
 290        ret = mtk_drm_crtc_create(drm, private->data->third_path,
 291                                  private->data->third_len);
 292        if (ret < 0)
 293                goto err_component_unbind;
 294
 295        /* Use OVL device for all DMA memory allocations */
 296        np = private->comp_node[private->data->main_path[0]] ?:
 297             private->comp_node[private->data->ext_path[0]];
 298        pdev = of_find_device_by_node(np);
 299        if (!pdev) {
 300                ret = -ENODEV;
 301                dev_err(drm->dev, "Need at least one OVL device\n");
 302                goto err_component_unbind;
 303        }
 304
 305        dma_dev = &pdev->dev;
 306        private->dma_dev = dma_dev;
 307
 308        /*
 309         * Configure the DMA segment size to make sure we get contiguous IOVA
 310         * when importing PRIME buffers.
 311         */
 312        ret = dma_set_max_seg_size(dma_dev, UINT_MAX);
 313        if (ret) {
 314                dev_err(dma_dev, "Failed to set DMA segment size\n");
 315                goto err_component_unbind;
 316        }
 317
 318        ret = drm_vblank_init(drm, MAX_CRTC);
 319        if (ret < 0)
 320                goto err_component_unbind;
 321
 322        drm_kms_helper_poll_init(drm);
 323        drm_mode_config_reset(drm);
 324
 325        return 0;
 326
 327err_component_unbind:
 328        component_unbind_all(drm->dev, drm);
 329put_mutex_dev:
 330        put_device(private->mutex_dev);
 331        return ret;
 332}
 333
 334static void mtk_drm_kms_deinit(struct drm_device *drm)
 335{
 336        drm_kms_helper_poll_fini(drm);
 337        drm_atomic_helper_shutdown(drm);
 338
 339        component_unbind_all(drm->dev, drm);
 340}
 341
 342DEFINE_DRM_GEM_FOPS(mtk_drm_fops);
 343
 344/*
 345 * We need to override this because the device used to import the memory is
 346 * not dev->dev, as drm_gem_prime_import() expects.
 347 */
 348static struct drm_gem_object *mtk_drm_gem_prime_import(struct drm_device *dev,
 349                                                       struct dma_buf *dma_buf)
 350{
 351        struct mtk_drm_private *private = dev->dev_private;
 352
 353        return drm_gem_prime_import_dev(dev, dma_buf, private->dma_dev);
 354}
 355
 356static const struct drm_driver mtk_drm_driver = {
 357        .driver_features = DRIVER_MODESET | DRIVER_GEM | DRIVER_ATOMIC,
 358
 359        .dumb_create = mtk_drm_gem_dumb_create,
 360
 361        .prime_handle_to_fd = drm_gem_prime_handle_to_fd,
 362        .prime_fd_to_handle = drm_gem_prime_fd_to_handle,
 363        .gem_prime_import = mtk_drm_gem_prime_import,
 364        .gem_prime_import_sg_table = mtk_gem_prime_import_sg_table,
 365        .gem_prime_mmap = drm_gem_prime_mmap,
 366        .fops = &mtk_drm_fops,
 367
 368        .name = DRIVER_NAME,
 369        .desc = DRIVER_DESC,
 370        .date = DRIVER_DATE,
 371        .major = DRIVER_MAJOR,
 372        .minor = DRIVER_MINOR,
 373};
 374
 375static int mtk_drm_bind(struct device *dev)
 376{
 377        struct mtk_drm_private *private = dev_get_drvdata(dev);
 378        struct drm_device *drm;
 379        int ret;
 380
 381        drm = drm_dev_alloc(&mtk_drm_driver, dev);
 382        if (IS_ERR(drm))
 383                return PTR_ERR(drm);
 384
 385        drm->dev_private = private;
 386        private->drm = drm;
 387
 388        ret = mtk_drm_kms_init(drm);
 389        if (ret < 0)
 390                goto err_free;
 391
 392        ret = drm_dev_register(drm, 0);
 393        if (ret < 0)
 394                goto err_deinit;
 395
 396        drm_fbdev_generic_setup(drm, 32);
 397
 398        return 0;
 399
 400err_deinit:
 401        mtk_drm_kms_deinit(drm);
 402err_free:
 403        drm_dev_put(drm);
 404        return ret;
 405}
 406
 407static void mtk_drm_unbind(struct device *dev)
 408{
 409        struct mtk_drm_private *private = dev_get_drvdata(dev);
 410
 411        drm_dev_unregister(private->drm);
 412        mtk_drm_kms_deinit(private->drm);
 413        drm_dev_put(private->drm);
 414        private->num_pipes = 0;
 415        private->drm = NULL;
 416}
 417
 418static const struct component_master_ops mtk_drm_ops = {
 419        .bind           = mtk_drm_bind,
 420        .unbind         = mtk_drm_unbind,
 421};
 422
 423static const struct of_device_id mtk_ddp_comp_dt_ids[] = {
 424        { .compatible = "mediatek,mt8167-disp-aal",
 425          .data = (void *)MTK_DISP_AAL},
 426        { .compatible = "mediatek,mt8173-disp-aal",
 427          .data = (void *)MTK_DISP_AAL},
 428        { .compatible = "mediatek,mt8183-disp-aal",
 429          .data = (void *)MTK_DISP_AAL},
 430        { .compatible = "mediatek,mt8192-disp-aal",
 431          .data = (void *)MTK_DISP_AAL},
 432        { .compatible = "mediatek,mt8167-disp-ccorr",
 433          .data = (void *)MTK_DISP_CCORR },
 434        { .compatible = "mediatek,mt8183-disp-ccorr",
 435          .data = (void *)MTK_DISP_CCORR },
 436        { .compatible = "mediatek,mt8192-disp-ccorr",
 437          .data = (void *)MTK_DISP_CCORR },
 438        { .compatible = "mediatek,mt2701-disp-color",
 439          .data = (void *)MTK_DISP_COLOR },
 440        { .compatible = "mediatek,mt8167-disp-color",
 441          .data = (void *)MTK_DISP_COLOR },
 442        { .compatible = "mediatek,mt8173-disp-color",
 443          .data = (void *)MTK_DISP_COLOR },
 444        { .compatible = "mediatek,mt8167-disp-dither",
 445          .data = (void *)MTK_DISP_DITHER },
 446        { .compatible = "mediatek,mt8183-disp-dither",
 447          .data = (void *)MTK_DISP_DITHER },
 448        { .compatible = "mediatek,mt8167-disp-gamma",
 449          .data = (void *)MTK_DISP_GAMMA, },
 450        { .compatible = "mediatek,mt8173-disp-gamma",
 451          .data = (void *)MTK_DISP_GAMMA, },
 452        { .compatible = "mediatek,mt8183-disp-gamma",
 453          .data = (void *)MTK_DISP_GAMMA, },
 454        { .compatible = "mediatek,mt2701-disp-mutex",
 455          .data = (void *)MTK_DISP_MUTEX },
 456        { .compatible = "mediatek,mt2712-disp-mutex",
 457          .data = (void *)MTK_DISP_MUTEX },
 458        { .compatible = "mediatek,mt8167-disp-mutex",
 459          .data = (void *)MTK_DISP_MUTEX },
 460        { .compatible = "mediatek,mt8173-disp-mutex",
 461          .data = (void *)MTK_DISP_MUTEX },
 462        { .compatible = "mediatek,mt8183-disp-mutex",
 463          .data = (void *)MTK_DISP_MUTEX },
 464        { .compatible = "mediatek,mt8192-disp-mutex",
 465          .data = (void *)MTK_DISP_MUTEX },
 466        { .compatible = "mediatek,mt8173-disp-od",
 467          .data = (void *)MTK_DISP_OD },
 468        { .compatible = "mediatek,mt2701-disp-ovl",
 469          .data = (void *)MTK_DISP_OVL },
 470        { .compatible = "mediatek,mt8167-disp-ovl",
 471          .data = (void *)MTK_DISP_OVL },
 472        { .compatible = "mediatek,mt8173-disp-ovl",
 473          .data = (void *)MTK_DISP_OVL },
 474        { .compatible = "mediatek,mt8183-disp-ovl",
 475          .data = (void *)MTK_DISP_OVL },
 476        { .compatible = "mediatek,mt8192-disp-ovl",
 477          .data = (void *)MTK_DISP_OVL },
 478        { .compatible = "mediatek,mt8183-disp-ovl-2l",
 479          .data = (void *)MTK_DISP_OVL_2L },
 480        { .compatible = "mediatek,mt8192-disp-ovl-2l",
 481          .data = (void *)MTK_DISP_OVL_2L },
 482        { .compatible = "mediatek,mt8192-disp-postmask",
 483          .data = (void *)MTK_DISP_POSTMASK },
 484        { .compatible = "mediatek,mt2701-disp-pwm",
 485          .data = (void *)MTK_DISP_BLS },
 486        { .compatible = "mediatek,mt8167-disp-pwm",
 487          .data = (void *)MTK_DISP_PWM },
 488        { .compatible = "mediatek,mt8173-disp-pwm",
 489          .data = (void *)MTK_DISP_PWM },
 490        { .compatible = "mediatek,mt2701-disp-rdma",
 491          .data = (void *)MTK_DISP_RDMA },
 492        { .compatible = "mediatek,mt8167-disp-rdma",
 493          .data = (void *)MTK_DISP_RDMA },
 494        { .compatible = "mediatek,mt8173-disp-rdma",
 495          .data = (void *)MTK_DISP_RDMA },
 496        { .compatible = "mediatek,mt8183-disp-rdma",
 497          .data = (void *)MTK_DISP_RDMA },
 498        { .compatible = "mediatek,mt8192-disp-rdma",
 499          .data = (void *)MTK_DISP_RDMA },
 500        { .compatible = "mediatek,mt8173-disp-ufoe",
 501          .data = (void *)MTK_DISP_UFOE },
 502        { .compatible = "mediatek,mt8173-disp-wdma",
 503          .data = (void *)MTK_DISP_WDMA },
 504        { .compatible = "mediatek,mt2701-dpi",
 505          .data = (void *)MTK_DPI },
 506        { .compatible = "mediatek,mt8167-dsi",
 507          .data = (void *)MTK_DSI },
 508        { .compatible = "mediatek,mt8173-dpi",
 509          .data = (void *)MTK_DPI },
 510        { .compatible = "mediatek,mt8183-dpi",
 511          .data = (void *)MTK_DPI },
 512        { .compatible = "mediatek,mt2701-dsi",
 513          .data = (void *)MTK_DSI },
 514        { .compatible = "mediatek,mt8173-dsi",
 515          .data = (void *)MTK_DSI },
 516        { .compatible = "mediatek,mt8183-dsi",
 517          .data = (void *)MTK_DSI },
 518        { }
 519};
 520
 521static const struct of_device_id mtk_drm_of_ids[] = {
 522        { .compatible = "mediatek,mt2701-mmsys",
 523          .data = &mt2701_mmsys_driver_data},
 524        { .compatible = "mediatek,mt7623-mmsys",
 525          .data = &mt7623_mmsys_driver_data},
 526        { .compatible = "mediatek,mt2712-mmsys",
 527          .data = &mt2712_mmsys_driver_data},
 528        { .compatible = "mediatek,mt8167-mmsys",
 529          .data = &mt8167_mmsys_driver_data},
 530        { .compatible = "mediatek,mt8173-mmsys",
 531          .data = &mt8173_mmsys_driver_data},
 532        { .compatible = "mediatek,mt8183-mmsys",
 533          .data = &mt8183_mmsys_driver_data},
 534        { .compatible = "mediatek,mt8192-mmsys",
 535          .data = &mt8192_mmsys_driver_data},
 536        { }
 537};
 538MODULE_DEVICE_TABLE(of, mtk_drm_of_ids);
 539
 540static int mtk_drm_probe(struct platform_device *pdev)
 541{
 542        struct device *dev = &pdev->dev;
 543        struct device_node *phandle = dev->parent->of_node;
 544        const struct of_device_id *of_id;
 545        struct mtk_drm_private *private;
 546        struct device_node *node;
 547        struct component_match *match = NULL;
 548        int ret;
 549        int i;
 550
 551        private = devm_kzalloc(dev, sizeof(*private), GFP_KERNEL);
 552        if (!private)
 553                return -ENOMEM;
 554
 555        private->mmsys_dev = dev->parent;
 556        if (!private->mmsys_dev) {
 557                dev_err(dev, "Failed to get MMSYS device\n");
 558                return -ENODEV;
 559        }
 560
 561        of_id = of_match_node(mtk_drm_of_ids, phandle);
 562        if (!of_id)
 563                return -ENODEV;
 564
 565        private->data = of_id->data;
 566
 567        /* Iterate over sibling DISP function blocks */
 568        for_each_child_of_node(phandle->parent, node) {
 569                const struct of_device_id *of_id;
 570                enum mtk_ddp_comp_type comp_type;
 571                int comp_id;
 572
 573                of_id = of_match_node(mtk_ddp_comp_dt_ids, node);
 574                if (!of_id)
 575                        continue;
 576
 577                if (!of_device_is_available(node)) {
 578                        dev_dbg(dev, "Skipping disabled component %pOF\n",
 579                                node);
 580                        continue;
 581                }
 582
 583                comp_type = (enum mtk_ddp_comp_type)of_id->data;
 584
 585                if (comp_type == MTK_DISP_MUTEX) {
 586                        private->mutex_node = of_node_get(node);
 587                        continue;
 588                }
 589
 590                comp_id = mtk_ddp_comp_get_id(node, comp_type);
 591                if (comp_id < 0) {
 592                        dev_warn(dev, "Skipping unknown component %pOF\n",
 593                                 node);
 594                        continue;
 595                }
 596
 597                private->comp_node[comp_id] = of_node_get(node);
 598
 599                /*
 600                 * Currently only the AAL, CCORR, COLOR, GAMMA, OVL, RDMA, DSI, and DPI
 601                 * blocks have separate component platform drivers and initialize their own
 602                 * DDP component structure. The others are initialized here.
 603                 */
 604                if (comp_type == MTK_DISP_AAL ||
 605                    comp_type == MTK_DISP_CCORR ||
 606                    comp_type == MTK_DISP_COLOR ||
 607                    comp_type == MTK_DISP_GAMMA ||
 608                    comp_type == MTK_DISP_OVL ||
 609                    comp_type == MTK_DISP_OVL_2L ||
 610                    comp_type == MTK_DISP_RDMA ||
 611                    comp_type == MTK_DPI ||
 612                    comp_type == MTK_DSI) {
 613                        dev_info(dev, "Adding component match for %pOF\n",
 614                                 node);
 615                        drm_of_component_match_add(dev, &match, component_compare_of,
 616                                                   node);
 617                }
 618
 619                ret = mtk_ddp_comp_init(node, &private->ddp_comp[comp_id], comp_id);
 620                if (ret) {
 621                        of_node_put(node);
 622                        goto err_node;
 623                }
 624        }
 625
 626        if (!private->mutex_node) {
 627                dev_err(dev, "Failed to find disp-mutex node\n");
 628                ret = -ENODEV;
 629                goto err_node;
 630        }
 631
 632        pm_runtime_enable(dev);
 633
 634        platform_set_drvdata(pdev, private);
 635
 636        ret = component_master_add_with_match(dev, &mtk_drm_ops, match);
 637        if (ret)
 638                goto err_pm;
 639
 640        return 0;
 641
 642err_pm:
 643        pm_runtime_disable(dev);
 644err_node:
 645        of_node_put(private->mutex_node);
 646        for (i = 0; i < DDP_COMPONENT_ID_MAX; i++)
 647                of_node_put(private->comp_node[i]);
 648        return ret;
 649}
 650
 651static int mtk_drm_remove(struct platform_device *pdev)
 652{
 653        struct mtk_drm_private *private = platform_get_drvdata(pdev);
 654        int i;
 655
 656        component_master_del(&pdev->dev, &mtk_drm_ops);
 657        pm_runtime_disable(&pdev->dev);
 658        of_node_put(private->mutex_node);
 659        for (i = 0; i < DDP_COMPONENT_ID_MAX; i++)
 660                of_node_put(private->comp_node[i]);
 661
 662        return 0;
 663}
 664
 665#ifdef CONFIG_PM_SLEEP
 666static int mtk_drm_sys_suspend(struct device *dev)
 667{
 668        struct mtk_drm_private *private = dev_get_drvdata(dev);
 669        struct drm_device *drm = private->drm;
 670        int ret;
 671
 672        ret = drm_mode_config_helper_suspend(drm);
 673
 674        return ret;
 675}
 676
 677static int mtk_drm_sys_resume(struct device *dev)
 678{
 679        struct mtk_drm_private *private = dev_get_drvdata(dev);
 680        struct drm_device *drm = private->drm;
 681        int ret;
 682
 683        ret = drm_mode_config_helper_resume(drm);
 684
 685        return ret;
 686}
 687#endif
 688
 689static SIMPLE_DEV_PM_OPS(mtk_drm_pm_ops, mtk_drm_sys_suspend,
 690                         mtk_drm_sys_resume);
 691
 692static struct platform_driver mtk_drm_platform_driver = {
 693        .probe  = mtk_drm_probe,
 694        .remove = mtk_drm_remove,
 695        .driver = {
 696                .name   = "mediatek-drm",
 697                .pm     = &mtk_drm_pm_ops,
 698        },
 699};
 700
 701static struct platform_driver * const mtk_drm_drivers[] = {
 702        &mtk_disp_aal_driver,
 703        &mtk_disp_ccorr_driver,
 704        &mtk_disp_color_driver,
 705        &mtk_disp_gamma_driver,
 706        &mtk_disp_ovl_driver,
 707        &mtk_disp_rdma_driver,
 708        &mtk_dpi_driver,
 709        &mtk_drm_platform_driver,
 710        &mtk_dsi_driver,
 711};
 712
 713static int __init mtk_drm_init(void)
 714{
 715        return platform_register_drivers(mtk_drm_drivers,
 716                                         ARRAY_SIZE(mtk_drm_drivers));
 717}
 718
 719static void __exit mtk_drm_exit(void)
 720{
 721        platform_unregister_drivers(mtk_drm_drivers,
 722                                    ARRAY_SIZE(mtk_drm_drivers));
 723}
 724
 725module_init(mtk_drm_init);
 726module_exit(mtk_drm_exit);
 727
 728MODULE_AUTHOR("YT SHEN <yt.shen@mediatek.com>");
 729MODULE_DESCRIPTION("Mediatek SoC DRM driver");
 730MODULE_LICENSE("GPL v2");
 731