linux/drivers/gpu/drm/mediatek/mtk_drm_crtc.c
<<
>>
Prefs
   1/*
   2 * Copyright (c) 2015 MediaTek Inc.
   3 *
   4 * This program is free software; you can redistribute it and/or modify
   5 * it under the terms of the GNU General Public License version 2 as
   6 * published by the Free Software Foundation.
   7 *
   8 * This program is distributed in the hope that it will be useful,
   9 * but WITHOUT ANY WARRANTY; without even the implied warranty of
  10 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  11 * GNU General Public License for more details.
  12 */
  13
  14#include <asm/barrier.h>
  15#include <drm/drmP.h>
  16#include <drm/drm_atomic_helper.h>
  17#include <drm/drm_crtc_helper.h>
  18#include <drm/drm_plane_helper.h>
  19#include <linux/clk.h>
  20#include <linux/pm_runtime.h>
  21#include <soc/mediatek/smi.h>
  22
  23#include "mtk_drm_drv.h"
  24#include "mtk_drm_crtc.h"
  25#include "mtk_drm_ddp.h"
  26#include "mtk_drm_ddp_comp.h"
  27#include "mtk_drm_gem.h"
  28#include "mtk_drm_plane.h"
  29
  30/**
  31 * struct mtk_drm_crtc - MediaTek specific crtc structure.
  32 * @base: crtc object.
  33 * @enabled: records whether crtc_enable succeeded
  34 * @planes: array of 4 drm_plane structures, one for each overlay plane
  35 * @pending_planes: whether any plane has pending changes to be applied
  36 * @config_regs: memory mapped mmsys configuration register space
  37 * @mutex: handle to one of the ten disp_mutex streams
  38 * @ddp_comp_nr: number of components in ddp_comp
  39 * @ddp_comp: array of pointers the mtk_ddp_comp structures used by this crtc
  40 */
  41struct mtk_drm_crtc {
  42        struct drm_crtc                 base;
  43        bool                            enabled;
  44
  45        bool                            pending_needs_vblank;
  46        struct drm_pending_vblank_event *event;
  47
  48        struct drm_plane                planes[OVL_LAYER_NR];
  49        bool                            pending_planes;
  50
  51        void __iomem                    *config_regs;
  52        struct mtk_disp_mutex           *mutex;
  53        unsigned int                    ddp_comp_nr;
  54        struct mtk_ddp_comp             **ddp_comp;
  55};
  56
  57struct mtk_crtc_state {
  58        struct drm_crtc_state           base;
  59
  60        bool                            pending_config;
  61        unsigned int                    pending_width;
  62        unsigned int                    pending_height;
  63        unsigned int                    pending_vrefresh;
  64};
  65
  66static inline struct mtk_drm_crtc *to_mtk_crtc(struct drm_crtc *c)
  67{
  68        return container_of(c, struct mtk_drm_crtc, base);
  69}
  70
  71static inline struct mtk_crtc_state *to_mtk_crtc_state(struct drm_crtc_state *s)
  72{
  73        return container_of(s, struct mtk_crtc_state, base);
  74}
  75
  76static void mtk_drm_crtc_finish_page_flip(struct mtk_drm_crtc *mtk_crtc)
  77{
  78        struct drm_crtc *crtc = &mtk_crtc->base;
  79        unsigned long flags;
  80
  81        spin_lock_irqsave(&crtc->dev->event_lock, flags);
  82        drm_crtc_send_vblank_event(crtc, mtk_crtc->event);
  83        drm_crtc_vblank_put(crtc);
  84        mtk_crtc->event = NULL;
  85        spin_unlock_irqrestore(&crtc->dev->event_lock, flags);
  86}
  87
  88static void mtk_drm_finish_page_flip(struct mtk_drm_crtc *mtk_crtc)
  89{
  90        drm_crtc_handle_vblank(&mtk_crtc->base);
  91        if (mtk_crtc->pending_needs_vblank) {
  92                mtk_drm_crtc_finish_page_flip(mtk_crtc);
  93                mtk_crtc->pending_needs_vblank = false;
  94        }
  95}
  96
  97static void mtk_drm_crtc_destroy(struct drm_crtc *crtc)
  98{
  99        struct mtk_drm_crtc *mtk_crtc = to_mtk_crtc(crtc);
 100        int i;
 101
 102        for (i = 0; i < mtk_crtc->ddp_comp_nr; i++)
 103                clk_unprepare(mtk_crtc->ddp_comp[i]->clk);
 104
 105        mtk_disp_mutex_put(mtk_crtc->mutex);
 106
 107        drm_crtc_cleanup(crtc);
 108}
 109
 110static void mtk_drm_crtc_reset(struct drm_crtc *crtc)
 111{
 112        struct mtk_crtc_state *state;
 113
 114        if (crtc->state) {
 115                __drm_atomic_helper_crtc_destroy_state(crtc->state);
 116
 117                state = to_mtk_crtc_state(crtc->state);
 118                memset(state, 0, sizeof(*state));
 119        } else {
 120                state = kzalloc(sizeof(*state), GFP_KERNEL);
 121                if (!state)
 122                        return;
 123                crtc->state = &state->base;
 124        }
 125
 126        state->base.crtc = crtc;
 127}
 128
 129static struct drm_crtc_state *mtk_drm_crtc_duplicate_state(struct drm_crtc *crtc)
 130{
 131        struct mtk_crtc_state *state;
 132
 133        state = kzalloc(sizeof(*state), GFP_KERNEL);
 134        if (!state)
 135                return NULL;
 136
 137        __drm_atomic_helper_crtc_duplicate_state(crtc, &state->base);
 138
 139        WARN_ON(state->base.crtc != crtc);
 140        state->base.crtc = crtc;
 141
 142        return &state->base;
 143}
 144
 145static void mtk_drm_crtc_destroy_state(struct drm_crtc *crtc,
 146                                       struct drm_crtc_state *state)
 147{
 148        __drm_atomic_helper_crtc_destroy_state(state);
 149        kfree(to_mtk_crtc_state(state));
 150}
 151
 152static bool mtk_drm_crtc_mode_fixup(struct drm_crtc *crtc,
 153                                    const struct drm_display_mode *mode,
 154                                    struct drm_display_mode *adjusted_mode)
 155{
 156        /* Nothing to do here, but this callback is mandatory. */
 157        return true;
 158}
 159
 160static void mtk_drm_crtc_mode_set_nofb(struct drm_crtc *crtc)
 161{
 162        struct mtk_crtc_state *state = to_mtk_crtc_state(crtc->state);
 163
 164        state->pending_width = crtc->mode.hdisplay;
 165        state->pending_height = crtc->mode.vdisplay;
 166        state->pending_vrefresh = crtc->mode.vrefresh;
 167        wmb();  /* Make sure the above parameters are set before update */
 168        state->pending_config = true;
 169}
 170
 171static int mtk_drm_crtc_enable_vblank(struct drm_crtc *crtc)
 172{
 173        struct mtk_drm_crtc *mtk_crtc = to_mtk_crtc(crtc);
 174        struct mtk_ddp_comp *ovl = mtk_crtc->ddp_comp[0];
 175
 176        mtk_ddp_comp_enable_vblank(ovl, &mtk_crtc->base);
 177
 178        return 0;
 179}
 180
 181static void mtk_drm_crtc_disable_vblank(struct drm_crtc *crtc)
 182{
 183        struct mtk_drm_crtc *mtk_crtc = to_mtk_crtc(crtc);
 184        struct mtk_ddp_comp *ovl = mtk_crtc->ddp_comp[0];
 185
 186        mtk_ddp_comp_disable_vblank(ovl);
 187}
 188
 189static int mtk_crtc_ddp_clk_enable(struct mtk_drm_crtc *mtk_crtc)
 190{
 191        int ret;
 192        int i;
 193
 194        DRM_DEBUG_DRIVER("%s\n", __func__);
 195        for (i = 0; i < mtk_crtc->ddp_comp_nr; i++) {
 196                ret = clk_enable(mtk_crtc->ddp_comp[i]->clk);
 197                if (ret) {
 198                        DRM_ERROR("Failed to enable clock %d: %d\n", i, ret);
 199                        goto err;
 200                }
 201        }
 202
 203        return 0;
 204err:
 205        while (--i >= 0)
 206                clk_disable(mtk_crtc->ddp_comp[i]->clk);
 207        return ret;
 208}
 209
 210static void mtk_crtc_ddp_clk_disable(struct mtk_drm_crtc *mtk_crtc)
 211{
 212        int i;
 213
 214        DRM_DEBUG_DRIVER("%s\n", __func__);
 215        for (i = 0; i < mtk_crtc->ddp_comp_nr; i++)
 216                clk_disable(mtk_crtc->ddp_comp[i]->clk);
 217}
 218
 219static int mtk_crtc_ddp_hw_init(struct mtk_drm_crtc *mtk_crtc)
 220{
 221        struct drm_crtc *crtc = &mtk_crtc->base;
 222        struct drm_connector *connector;
 223        struct drm_encoder *encoder;
 224        struct drm_connector_list_iter conn_iter;
 225        unsigned int width, height, vrefresh, bpc = MTK_MAX_BPC;
 226        int ret;
 227        int i;
 228
 229        DRM_DEBUG_DRIVER("%s\n", __func__);
 230        if (WARN_ON(!crtc->state))
 231                return -EINVAL;
 232
 233        width = crtc->state->adjusted_mode.hdisplay;
 234        height = crtc->state->adjusted_mode.vdisplay;
 235        vrefresh = crtc->state->adjusted_mode.vrefresh;
 236
 237        drm_for_each_encoder(encoder, crtc->dev) {
 238                if (encoder->crtc != crtc)
 239                        continue;
 240
 241                drm_connector_list_iter_begin(crtc->dev, &conn_iter);
 242                drm_for_each_connector_iter(connector, &conn_iter) {
 243                        if (connector->encoder != encoder)
 244                                continue;
 245                        if (connector->display_info.bpc != 0 &&
 246                            bpc > connector->display_info.bpc)
 247                                bpc = connector->display_info.bpc;
 248                }
 249                drm_connector_list_iter_end(&conn_iter);
 250        }
 251
 252        ret = pm_runtime_get_sync(crtc->dev->dev);
 253        if (ret < 0) {
 254                DRM_ERROR("Failed to enable power domain: %d\n", ret);
 255                return ret;
 256        }
 257
 258        ret = mtk_disp_mutex_prepare(mtk_crtc->mutex);
 259        if (ret < 0) {
 260                DRM_ERROR("Failed to enable mutex clock: %d\n", ret);
 261                goto err_pm_runtime_put;
 262        }
 263
 264        ret = mtk_crtc_ddp_clk_enable(mtk_crtc);
 265        if (ret < 0) {
 266                DRM_ERROR("Failed to enable component clocks: %d\n", ret);
 267                goto err_mutex_unprepare;
 268        }
 269
 270        DRM_DEBUG_DRIVER("mediatek_ddp_ddp_path_setup\n");
 271        for (i = 0; i < mtk_crtc->ddp_comp_nr - 1; i++) {
 272                mtk_ddp_add_comp_to_path(mtk_crtc->config_regs,
 273                                         mtk_crtc->ddp_comp[i]->id,
 274                                         mtk_crtc->ddp_comp[i + 1]->id);
 275                mtk_disp_mutex_add_comp(mtk_crtc->mutex,
 276                                        mtk_crtc->ddp_comp[i]->id);
 277        }
 278        mtk_disp_mutex_add_comp(mtk_crtc->mutex, mtk_crtc->ddp_comp[i]->id);
 279        mtk_disp_mutex_enable(mtk_crtc->mutex);
 280
 281        for (i = 0; i < mtk_crtc->ddp_comp_nr; i++) {
 282                struct mtk_ddp_comp *comp = mtk_crtc->ddp_comp[i];
 283
 284                mtk_ddp_comp_config(comp, width, height, vrefresh, bpc);
 285                mtk_ddp_comp_start(comp);
 286        }
 287
 288        /* Initially configure all planes */
 289        for (i = 0; i < OVL_LAYER_NR; i++) {
 290                struct drm_plane *plane = &mtk_crtc->planes[i];
 291                struct mtk_plane_state *plane_state;
 292
 293                plane_state = to_mtk_plane_state(plane->state);
 294                mtk_ddp_comp_layer_config(mtk_crtc->ddp_comp[0], i,
 295                                          plane_state);
 296        }
 297
 298        return 0;
 299
 300err_mutex_unprepare:
 301        mtk_disp_mutex_unprepare(mtk_crtc->mutex);
 302err_pm_runtime_put:
 303        pm_runtime_put(crtc->dev->dev);
 304        return ret;
 305}
 306
 307static void mtk_crtc_ddp_hw_fini(struct mtk_drm_crtc *mtk_crtc)
 308{
 309        struct drm_device *drm = mtk_crtc->base.dev;
 310        int i;
 311
 312        DRM_DEBUG_DRIVER("%s\n", __func__);
 313        for (i = 0; i < mtk_crtc->ddp_comp_nr; i++)
 314                mtk_ddp_comp_stop(mtk_crtc->ddp_comp[i]);
 315        for (i = 0; i < mtk_crtc->ddp_comp_nr; i++)
 316                mtk_disp_mutex_remove_comp(mtk_crtc->mutex,
 317                                           mtk_crtc->ddp_comp[i]->id);
 318        mtk_disp_mutex_disable(mtk_crtc->mutex);
 319        for (i = 0; i < mtk_crtc->ddp_comp_nr - 1; i++) {
 320                mtk_ddp_remove_comp_from_path(mtk_crtc->config_regs,
 321                                              mtk_crtc->ddp_comp[i]->id,
 322                                              mtk_crtc->ddp_comp[i + 1]->id);
 323                mtk_disp_mutex_remove_comp(mtk_crtc->mutex,
 324                                           mtk_crtc->ddp_comp[i]->id);
 325        }
 326        mtk_disp_mutex_remove_comp(mtk_crtc->mutex, mtk_crtc->ddp_comp[i]->id);
 327        mtk_crtc_ddp_clk_disable(mtk_crtc);
 328        mtk_disp_mutex_unprepare(mtk_crtc->mutex);
 329
 330        pm_runtime_put(drm->dev);
 331}
 332
 333static void mtk_crtc_ddp_config(struct drm_crtc *crtc)
 334{
 335        struct mtk_drm_crtc *mtk_crtc = to_mtk_crtc(crtc);
 336        struct mtk_crtc_state *state = to_mtk_crtc_state(mtk_crtc->base.state);
 337        struct mtk_ddp_comp *ovl = mtk_crtc->ddp_comp[0];
 338        unsigned int i;
 339
 340        /*
 341         * TODO: instead of updating the registers here, we should prepare
 342         * working registers in atomic_commit and let the hardware command
 343         * queue update module registers on vblank.
 344         */
 345        if (state->pending_config) {
 346                mtk_ddp_comp_config(ovl, state->pending_width,
 347                                    state->pending_height,
 348                                    state->pending_vrefresh, 0);
 349
 350                state->pending_config = false;
 351        }
 352
 353        if (mtk_crtc->pending_planes) {
 354                for (i = 0; i < OVL_LAYER_NR; i++) {
 355                        struct drm_plane *plane = &mtk_crtc->planes[i];
 356                        struct mtk_plane_state *plane_state;
 357
 358                        plane_state = to_mtk_plane_state(plane->state);
 359
 360                        if (plane_state->pending.config) {
 361                                mtk_ddp_comp_layer_config(ovl, i, plane_state);
 362                                plane_state->pending.config = false;
 363                        }
 364                }
 365                mtk_crtc->pending_planes = false;
 366        }
 367}
 368
 369static void mtk_drm_crtc_atomic_enable(struct drm_crtc *crtc,
 370                                       struct drm_crtc_state *old_state)
 371{
 372        struct mtk_drm_crtc *mtk_crtc = to_mtk_crtc(crtc);
 373        struct mtk_ddp_comp *ovl = mtk_crtc->ddp_comp[0];
 374        int ret;
 375
 376        DRM_DEBUG_DRIVER("%s %d\n", __func__, crtc->base.id);
 377
 378        ret = mtk_smi_larb_get(ovl->larb_dev);
 379        if (ret) {
 380                DRM_ERROR("Failed to get larb: %d\n", ret);
 381                return;
 382        }
 383
 384        ret = mtk_crtc_ddp_hw_init(mtk_crtc);
 385        if (ret) {
 386                mtk_smi_larb_put(ovl->larb_dev);
 387                return;
 388        }
 389
 390        drm_crtc_vblank_on(crtc);
 391        mtk_crtc->enabled = true;
 392}
 393
 394static void mtk_drm_crtc_atomic_disable(struct drm_crtc *crtc,
 395                                        struct drm_crtc_state *old_state)
 396{
 397        struct mtk_drm_crtc *mtk_crtc = to_mtk_crtc(crtc);
 398        struct mtk_ddp_comp *ovl = mtk_crtc->ddp_comp[0];
 399        int i;
 400
 401        DRM_DEBUG_DRIVER("%s %d\n", __func__, crtc->base.id);
 402        if (!mtk_crtc->enabled)
 403                return;
 404
 405        /* Set all pending plane state to disabled */
 406        for (i = 0; i < OVL_LAYER_NR; i++) {
 407                struct drm_plane *plane = &mtk_crtc->planes[i];
 408                struct mtk_plane_state *plane_state;
 409
 410                plane_state = to_mtk_plane_state(plane->state);
 411                plane_state->pending.enable = false;
 412                plane_state->pending.config = true;
 413        }
 414        mtk_crtc->pending_planes = true;
 415
 416        /* Wait for planes to be disabled */
 417        drm_crtc_wait_one_vblank(crtc);
 418
 419        drm_crtc_vblank_off(crtc);
 420        mtk_crtc_ddp_hw_fini(mtk_crtc);
 421        mtk_smi_larb_put(ovl->larb_dev);
 422
 423        mtk_crtc->enabled = false;
 424}
 425
 426static void mtk_drm_crtc_atomic_begin(struct drm_crtc *crtc,
 427                                      struct drm_crtc_state *old_crtc_state)
 428{
 429        struct mtk_crtc_state *state = to_mtk_crtc_state(crtc->state);
 430        struct mtk_drm_crtc *mtk_crtc = to_mtk_crtc(crtc);
 431
 432        if (mtk_crtc->event && state->base.event)
 433                DRM_ERROR("new event while there is still a pending event\n");
 434
 435        if (state->base.event) {
 436                state->base.event->pipe = drm_crtc_index(crtc);
 437                WARN_ON(drm_crtc_vblank_get(crtc) != 0);
 438                mtk_crtc->event = state->base.event;
 439                state->base.event = NULL;
 440        }
 441}
 442
 443static void mtk_drm_crtc_atomic_flush(struct drm_crtc *crtc,
 444                                      struct drm_crtc_state *old_crtc_state)
 445{
 446        struct mtk_drm_crtc *mtk_crtc = to_mtk_crtc(crtc);
 447        struct mtk_drm_private *priv = crtc->dev->dev_private;
 448        unsigned int pending_planes = 0;
 449        int i;
 450
 451        if (mtk_crtc->event)
 452                mtk_crtc->pending_needs_vblank = true;
 453        for (i = 0; i < OVL_LAYER_NR; i++) {
 454                struct drm_plane *plane = &mtk_crtc->planes[i];
 455                struct mtk_plane_state *plane_state;
 456
 457                plane_state = to_mtk_plane_state(plane->state);
 458                if (plane_state->pending.dirty) {
 459                        plane_state->pending.config = true;
 460                        plane_state->pending.dirty = false;
 461                        pending_planes |= BIT(i);
 462                }
 463        }
 464        if (pending_planes)
 465                mtk_crtc->pending_planes = true;
 466        if (crtc->state->color_mgmt_changed)
 467                for (i = 0; i < mtk_crtc->ddp_comp_nr; i++)
 468                        mtk_ddp_gamma_set(mtk_crtc->ddp_comp[i], crtc->state);
 469
 470        if (priv->data->shadow_register) {
 471                mtk_disp_mutex_acquire(mtk_crtc->mutex);
 472                mtk_crtc_ddp_config(crtc);
 473                mtk_disp_mutex_release(mtk_crtc->mutex);
 474        }
 475}
 476
 477static const struct drm_crtc_funcs mtk_crtc_funcs = {
 478        .set_config             = drm_atomic_helper_set_config,
 479        .page_flip              = drm_atomic_helper_page_flip,
 480        .destroy                = mtk_drm_crtc_destroy,
 481        .reset                  = mtk_drm_crtc_reset,
 482        .atomic_duplicate_state = mtk_drm_crtc_duplicate_state,
 483        .atomic_destroy_state   = mtk_drm_crtc_destroy_state,
 484        .gamma_set              = drm_atomic_helper_legacy_gamma_set,
 485        .enable_vblank          = mtk_drm_crtc_enable_vblank,
 486        .disable_vblank         = mtk_drm_crtc_disable_vblank,
 487};
 488
 489static const struct drm_crtc_helper_funcs mtk_crtc_helper_funcs = {
 490        .mode_fixup     = mtk_drm_crtc_mode_fixup,
 491        .mode_set_nofb  = mtk_drm_crtc_mode_set_nofb,
 492        .atomic_begin   = mtk_drm_crtc_atomic_begin,
 493        .atomic_flush   = mtk_drm_crtc_atomic_flush,
 494        .atomic_enable  = mtk_drm_crtc_atomic_enable,
 495        .atomic_disable = mtk_drm_crtc_atomic_disable,
 496};
 497
 498static int mtk_drm_crtc_init(struct drm_device *drm,
 499                             struct mtk_drm_crtc *mtk_crtc,
 500                             struct drm_plane *primary,
 501                             struct drm_plane *cursor, unsigned int pipe)
 502{
 503        int ret;
 504
 505        ret = drm_crtc_init_with_planes(drm, &mtk_crtc->base, primary, cursor,
 506                                        &mtk_crtc_funcs, NULL);
 507        if (ret)
 508                goto err_cleanup_crtc;
 509
 510        drm_crtc_helper_add(&mtk_crtc->base, &mtk_crtc_helper_funcs);
 511
 512        return 0;
 513
 514err_cleanup_crtc:
 515        drm_crtc_cleanup(&mtk_crtc->base);
 516        return ret;
 517}
 518
 519void mtk_crtc_ddp_irq(struct drm_crtc *crtc, struct mtk_ddp_comp *ovl)
 520{
 521        struct mtk_drm_crtc *mtk_crtc = to_mtk_crtc(crtc);
 522        struct mtk_drm_private *priv = crtc->dev->dev_private;
 523
 524        if (!priv->data->shadow_register)
 525                mtk_crtc_ddp_config(crtc);
 526
 527        mtk_drm_finish_page_flip(mtk_crtc);
 528}
 529
 530int mtk_drm_crtc_create(struct drm_device *drm_dev,
 531                        const enum mtk_ddp_comp_id *path, unsigned int path_len)
 532{
 533        struct mtk_drm_private *priv = drm_dev->dev_private;
 534        struct device *dev = drm_dev->dev;
 535        struct mtk_drm_crtc *mtk_crtc;
 536        enum drm_plane_type type;
 537        unsigned int zpos;
 538        int pipe = priv->num_pipes;
 539        int ret;
 540        int i;
 541
 542        for (i = 0; i < path_len; i++) {
 543                enum mtk_ddp_comp_id comp_id = path[i];
 544                struct device_node *node;
 545
 546                node = priv->comp_node[comp_id];
 547                if (!node) {
 548                        dev_info(dev,
 549                                 "Not creating crtc %d because component %d is disabled or missing\n",
 550                                 pipe, comp_id);
 551                        return 0;
 552                }
 553        }
 554
 555        mtk_crtc = devm_kzalloc(dev, sizeof(*mtk_crtc), GFP_KERNEL);
 556        if (!mtk_crtc)
 557                return -ENOMEM;
 558
 559        mtk_crtc->config_regs = priv->config_regs;
 560        mtk_crtc->ddp_comp_nr = path_len;
 561        mtk_crtc->ddp_comp = devm_kmalloc_array(dev, mtk_crtc->ddp_comp_nr,
 562                                                sizeof(*mtk_crtc->ddp_comp),
 563                                                GFP_KERNEL);
 564        if (!mtk_crtc->ddp_comp)
 565                return -ENOMEM;
 566
 567        mtk_crtc->mutex = mtk_disp_mutex_get(priv->mutex_dev, pipe);
 568        if (IS_ERR(mtk_crtc->mutex)) {
 569                ret = PTR_ERR(mtk_crtc->mutex);
 570                dev_err(dev, "Failed to get mutex: %d\n", ret);
 571                return ret;
 572        }
 573
 574        for (i = 0; i < mtk_crtc->ddp_comp_nr; i++) {
 575                enum mtk_ddp_comp_id comp_id = path[i];
 576                struct mtk_ddp_comp *comp;
 577                struct device_node *node;
 578
 579                node = priv->comp_node[comp_id];
 580                comp = priv->ddp_comp[comp_id];
 581                if (!comp) {
 582                        dev_err(dev, "Component %pOF not initialized\n", node);
 583                        ret = -ENODEV;
 584                        goto unprepare;
 585                }
 586
 587                ret = clk_prepare(comp->clk);
 588                if (ret) {
 589                        dev_err(dev,
 590                                "Failed to prepare clock for component %pOF: %d\n",
 591                                node, ret);
 592                        goto unprepare;
 593                }
 594
 595                mtk_crtc->ddp_comp[i] = comp;
 596        }
 597
 598        for (zpos = 0; zpos < OVL_LAYER_NR; zpos++) {
 599                type = (zpos == 0) ? DRM_PLANE_TYPE_PRIMARY :
 600                                (zpos == 1) ? DRM_PLANE_TYPE_CURSOR :
 601                                                DRM_PLANE_TYPE_OVERLAY;
 602                ret = mtk_plane_init(drm_dev, &mtk_crtc->planes[zpos],
 603                                     BIT(pipe), type);
 604                if (ret)
 605                        goto unprepare;
 606        }
 607
 608        ret = mtk_drm_crtc_init(drm_dev, mtk_crtc, &mtk_crtc->planes[0],
 609                                &mtk_crtc->planes[1], pipe);
 610        if (ret < 0)
 611                goto unprepare;
 612        drm_mode_crtc_set_gamma_size(&mtk_crtc->base, MTK_LUT_SIZE);
 613        drm_crtc_enable_color_mgmt(&mtk_crtc->base, 0, false, MTK_LUT_SIZE);
 614        priv->num_pipes++;
 615
 616        return 0;
 617
 618unprepare:
 619        while (--i >= 0)
 620                clk_unprepare(mtk_crtc->ddp_comp[i]->clk);
 621
 622        return ret;
 623}
 624