root/drivers/gpu/drm/mediatek/mtk_drm_crtc.c

/* [<][>][^][v][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. to_mtk_crtc
  2. to_mtk_crtc_state
  3. mtk_drm_crtc_finish_page_flip
  4. mtk_drm_finish_page_flip
  5. mtk_drm_crtc_destroy
  6. mtk_drm_crtc_reset
  7. mtk_drm_crtc_duplicate_state
  8. mtk_drm_crtc_destroy_state
  9. mtk_drm_crtc_mode_fixup
  10. mtk_drm_crtc_mode_set_nofb
  11. mtk_drm_crtc_enable_vblank
  12. mtk_drm_crtc_disable_vblank
  13. mtk_crtc_ddp_clk_enable
  14. mtk_crtc_ddp_clk_disable
  15. mtk_crtc_ddp_hw_init
  16. mtk_crtc_ddp_hw_fini
  17. mtk_crtc_ddp_config
  18. mtk_drm_crtc_atomic_enable
  19. mtk_drm_crtc_atomic_disable
  20. mtk_drm_crtc_atomic_begin
  21. mtk_drm_crtc_atomic_flush
  22. mtk_drm_crtc_init
  23. mtk_crtc_ddp_irq
  24. mtk_drm_crtc_create

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

/* [<][>][^][v][top][bottom][index][help] */