linux/drivers/gpu/drm/mediatek/mtk_drm_crtc.c
<<
>>
Prefs
   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/dma-mapping.h>
   8#include <linux/mailbox_controller.h>
   9#include <linux/pm_runtime.h>
  10#include <linux/soc/mediatek/mtk-cmdq.h>
  11#include <linux/soc/mediatek/mtk-mmsys.h>
  12#include <linux/soc/mediatek/mtk-mutex.h>
  13
  14#include <asm/barrier.h>
  15#include <soc/mediatek/smi.h>
  16
  17#include <drm/drm_atomic.h>
  18#include <drm/drm_atomic_helper.h>
  19#include <drm/drm_plane_helper.h>
  20#include <drm/drm_probe_helper.h>
  21#include <drm/drm_vblank.h>
  22
  23#include "mtk_drm_drv.h"
  24#include "mtk_drm_crtc.h"
  25#include "mtk_drm_ddp_comp.h"
  26#include "mtk_drm_gem.h"
  27#include "mtk_drm_plane.h"
  28
  29/*
  30 * struct mtk_drm_crtc - MediaTek specific crtc structure.
  31 * @base: crtc object.
  32 * @enabled: records whether crtc_enable succeeded
  33 * @planes: array of 4 drm_plane structures, one for each overlay plane
  34 * @pending_planes: whether any plane has pending changes to be applied
  35 * @mmsys_dev: pointer to the mmsys device for configuration registers
  36 * @mutex: handle to one of the ten disp_mutex streams
  37 * @ddp_comp_nr: number of components in ddp_comp
  38 * @ddp_comp: array of pointers the mtk_ddp_comp structures used by this crtc
  39 *
  40 * TODO: Needs update: this header is missing a bunch of member descriptions.
  41 */
  42struct mtk_drm_crtc {
  43        struct drm_crtc                 base;
  44        bool                            enabled;
  45
  46        bool                            pending_needs_vblank;
  47        struct drm_pending_vblank_event *event;
  48
  49        struct drm_plane                *planes;
  50        unsigned int                    layer_nr;
  51        bool                            pending_planes;
  52        bool                            pending_async_planes;
  53
  54#if IS_REACHABLE(CONFIG_MTK_CMDQ)
  55        struct cmdq_client              cmdq_client;
  56        struct cmdq_pkt                 cmdq_handle;
  57        u32                             cmdq_event;
  58        u32                             cmdq_vblank_cnt;
  59#endif
  60
  61        struct device                   *mmsys_dev;
  62        struct mtk_mutex                *mutex;
  63        unsigned int                    ddp_comp_nr;
  64        struct mtk_ddp_comp             **ddp_comp;
  65
  66        /* lock for display hardware access */
  67        struct mutex                    hw_lock;
  68        bool                            config_updating;
  69};
  70
  71struct mtk_crtc_state {
  72        struct drm_crtc_state           base;
  73
  74        bool                            pending_config;
  75        unsigned int                    pending_width;
  76        unsigned int                    pending_height;
  77        unsigned int                    pending_vrefresh;
  78};
  79
  80static inline struct mtk_drm_crtc *to_mtk_crtc(struct drm_crtc *c)
  81{
  82        return container_of(c, struct mtk_drm_crtc, base);
  83}
  84
  85static inline struct mtk_crtc_state *to_mtk_crtc_state(struct drm_crtc_state *s)
  86{
  87        return container_of(s, struct mtk_crtc_state, base);
  88}
  89
  90static void mtk_drm_crtc_finish_page_flip(struct mtk_drm_crtc *mtk_crtc)
  91{
  92        struct drm_crtc *crtc = &mtk_crtc->base;
  93        unsigned long flags;
  94
  95        spin_lock_irqsave(&crtc->dev->event_lock, flags);
  96        drm_crtc_send_vblank_event(crtc, mtk_crtc->event);
  97        drm_crtc_vblank_put(crtc);
  98        mtk_crtc->event = NULL;
  99        spin_unlock_irqrestore(&crtc->dev->event_lock, flags);
 100}
 101
 102static void mtk_drm_finish_page_flip(struct mtk_drm_crtc *mtk_crtc)
 103{
 104        drm_crtc_handle_vblank(&mtk_crtc->base);
 105        if (!mtk_crtc->config_updating && mtk_crtc->pending_needs_vblank) {
 106                mtk_drm_crtc_finish_page_flip(mtk_crtc);
 107                mtk_crtc->pending_needs_vblank = false;
 108        }
 109}
 110
 111#if IS_REACHABLE(CONFIG_MTK_CMDQ)
 112static int mtk_drm_cmdq_pkt_create(struct cmdq_client *client, struct cmdq_pkt *pkt,
 113                                   size_t size)
 114{
 115        struct device *dev;
 116        dma_addr_t dma_addr;
 117
 118        pkt->va_base = kzalloc(size, GFP_KERNEL);
 119        if (!pkt->va_base) {
 120                kfree(pkt);
 121                return -ENOMEM;
 122        }
 123        pkt->buf_size = size;
 124        pkt->cl = (void *)client;
 125
 126        dev = client->chan->mbox->dev;
 127        dma_addr = dma_map_single(dev, pkt->va_base, pkt->buf_size,
 128                                  DMA_TO_DEVICE);
 129        if (dma_mapping_error(dev, dma_addr)) {
 130                dev_err(dev, "dma map failed, size=%u\n", (u32)(u64)size);
 131                kfree(pkt->va_base);
 132                kfree(pkt);
 133                return -ENOMEM;
 134        }
 135
 136        pkt->pa_base = dma_addr;
 137
 138        return 0;
 139}
 140
 141static void mtk_drm_cmdq_pkt_destroy(struct cmdq_pkt *pkt)
 142{
 143        struct cmdq_client *client = (struct cmdq_client *)pkt->cl;
 144
 145        dma_unmap_single(client->chan->mbox->dev, pkt->pa_base, pkt->buf_size,
 146                         DMA_TO_DEVICE);
 147        kfree(pkt->va_base);
 148        kfree(pkt);
 149}
 150#endif
 151
 152static void mtk_drm_crtc_destroy(struct drm_crtc *crtc)
 153{
 154        struct mtk_drm_crtc *mtk_crtc = to_mtk_crtc(crtc);
 155
 156        mtk_mutex_put(mtk_crtc->mutex);
 157#if IS_REACHABLE(CONFIG_MTK_CMDQ)
 158        mtk_drm_cmdq_pkt_destroy(&mtk_crtc->cmdq_handle);
 159
 160        if (mtk_crtc->cmdq_client.chan) {
 161                mbox_free_channel(mtk_crtc->cmdq_client.chan);
 162                mtk_crtc->cmdq_client.chan = NULL;
 163        }
 164#endif
 165        drm_crtc_cleanup(crtc);
 166}
 167
 168static void mtk_drm_crtc_reset(struct drm_crtc *crtc)
 169{
 170        struct mtk_crtc_state *state;
 171
 172        if (crtc->state)
 173                __drm_atomic_helper_crtc_destroy_state(crtc->state);
 174
 175        kfree(to_mtk_crtc_state(crtc->state));
 176        crtc->state = NULL;
 177
 178        state = kzalloc(sizeof(*state), GFP_KERNEL);
 179        if (state)
 180                __drm_atomic_helper_crtc_reset(crtc, &state->base);
 181}
 182
 183static struct drm_crtc_state *mtk_drm_crtc_duplicate_state(struct drm_crtc *crtc)
 184{
 185        struct mtk_crtc_state *state;
 186
 187        state = kzalloc(sizeof(*state), GFP_KERNEL);
 188        if (!state)
 189                return NULL;
 190
 191        __drm_atomic_helper_crtc_duplicate_state(crtc, &state->base);
 192
 193        WARN_ON(state->base.crtc != crtc);
 194        state->base.crtc = crtc;
 195
 196        return &state->base;
 197}
 198
 199static void mtk_drm_crtc_destroy_state(struct drm_crtc *crtc,
 200                                       struct drm_crtc_state *state)
 201{
 202        __drm_atomic_helper_crtc_destroy_state(state);
 203        kfree(to_mtk_crtc_state(state));
 204}
 205
 206static bool mtk_drm_crtc_mode_fixup(struct drm_crtc *crtc,
 207                                    const struct drm_display_mode *mode,
 208                                    struct drm_display_mode *adjusted_mode)
 209{
 210        /* Nothing to do here, but this callback is mandatory. */
 211        return true;
 212}
 213
 214static void mtk_drm_crtc_mode_set_nofb(struct drm_crtc *crtc)
 215{
 216        struct mtk_crtc_state *state = to_mtk_crtc_state(crtc->state);
 217
 218        state->pending_width = crtc->mode.hdisplay;
 219        state->pending_height = crtc->mode.vdisplay;
 220        state->pending_vrefresh = drm_mode_vrefresh(&crtc->mode);
 221        wmb();  /* Make sure the above parameters are set before update */
 222        state->pending_config = true;
 223}
 224
 225static int mtk_crtc_ddp_clk_enable(struct mtk_drm_crtc *mtk_crtc)
 226{
 227        int ret;
 228        int i;
 229
 230        for (i = 0; i < mtk_crtc->ddp_comp_nr; i++) {
 231                ret = mtk_ddp_comp_clk_enable(mtk_crtc->ddp_comp[i]);
 232                if (ret) {
 233                        DRM_ERROR("Failed to enable clock %d: %d\n", i, ret);
 234                        goto err;
 235                }
 236        }
 237
 238        return 0;
 239err:
 240        while (--i >= 0)
 241                mtk_ddp_comp_clk_disable(mtk_crtc->ddp_comp[i]);
 242        return ret;
 243}
 244
 245static void mtk_crtc_ddp_clk_disable(struct mtk_drm_crtc *mtk_crtc)
 246{
 247        int i;
 248
 249        for (i = 0; i < mtk_crtc->ddp_comp_nr; i++)
 250                mtk_ddp_comp_clk_disable(mtk_crtc->ddp_comp[i]);
 251}
 252
 253static
 254struct mtk_ddp_comp *mtk_drm_ddp_comp_for_plane(struct drm_crtc *crtc,
 255                                                struct drm_plane *plane,
 256                                                unsigned int *local_layer)
 257{
 258        struct mtk_drm_crtc *mtk_crtc = to_mtk_crtc(crtc);
 259        struct mtk_ddp_comp *comp;
 260        int i, count = 0;
 261        unsigned int local_index = plane - mtk_crtc->planes;
 262
 263        for (i = 0; i < mtk_crtc->ddp_comp_nr; i++) {
 264                comp = mtk_crtc->ddp_comp[i];
 265                if (local_index < (count + mtk_ddp_comp_layer_nr(comp))) {
 266                        *local_layer = local_index - count;
 267                        return comp;
 268                }
 269                count += mtk_ddp_comp_layer_nr(comp);
 270        }
 271
 272        WARN(1, "Failed to find component for plane %d\n", plane->index);
 273        return NULL;
 274}
 275
 276#if IS_REACHABLE(CONFIG_MTK_CMDQ)
 277static void ddp_cmdq_cb(struct mbox_client *cl, void *mssg)
 278{
 279        struct cmdq_cb_data *data = mssg;
 280        struct cmdq_client *cmdq_cl = container_of(cl, struct cmdq_client, client);
 281        struct mtk_drm_crtc *mtk_crtc = container_of(cmdq_cl, struct mtk_drm_crtc, cmdq_client);
 282        struct mtk_crtc_state *state;
 283        unsigned int i;
 284
 285        if (data->sta < 0)
 286                return;
 287
 288        state = to_mtk_crtc_state(mtk_crtc->base.state);
 289
 290        state->pending_config = false;
 291
 292        if (mtk_crtc->pending_planes) {
 293                for (i = 0; i < mtk_crtc->layer_nr; i++) {
 294                        struct drm_plane *plane = &mtk_crtc->planes[i];
 295                        struct mtk_plane_state *plane_state;
 296
 297                        plane_state = to_mtk_plane_state(plane->state);
 298
 299                        plane_state->pending.config = false;
 300                }
 301                mtk_crtc->pending_planes = false;
 302        }
 303
 304        if (mtk_crtc->pending_async_planes) {
 305                for (i = 0; i < mtk_crtc->layer_nr; i++) {
 306                        struct drm_plane *plane = &mtk_crtc->planes[i];
 307                        struct mtk_plane_state *plane_state;
 308
 309                        plane_state = to_mtk_plane_state(plane->state);
 310
 311                        plane_state->pending.async_config = false;
 312                }
 313                mtk_crtc->pending_async_planes = false;
 314        }
 315
 316        mtk_crtc->cmdq_vblank_cnt = 0;
 317}
 318#endif
 319
 320static int mtk_crtc_ddp_hw_init(struct mtk_drm_crtc *mtk_crtc)
 321{
 322        struct drm_crtc *crtc = &mtk_crtc->base;
 323        struct drm_connector *connector;
 324        struct drm_encoder *encoder;
 325        struct drm_connector_list_iter conn_iter;
 326        unsigned int width, height, vrefresh, bpc = MTK_MAX_BPC;
 327        int ret;
 328        int i;
 329
 330        if (WARN_ON(!crtc->state))
 331                return -EINVAL;
 332
 333        width = crtc->state->adjusted_mode.hdisplay;
 334        height = crtc->state->adjusted_mode.vdisplay;
 335        vrefresh = drm_mode_vrefresh(&crtc->state->adjusted_mode);
 336
 337        drm_for_each_encoder(encoder, crtc->dev) {
 338                if (encoder->crtc != crtc)
 339                        continue;
 340
 341                drm_connector_list_iter_begin(crtc->dev, &conn_iter);
 342                drm_for_each_connector_iter(connector, &conn_iter) {
 343                        if (connector->encoder != encoder)
 344                                continue;
 345                        if (connector->display_info.bpc != 0 &&
 346                            bpc > connector->display_info.bpc)
 347                                bpc = connector->display_info.bpc;
 348                }
 349                drm_connector_list_iter_end(&conn_iter);
 350        }
 351
 352        ret = pm_runtime_resume_and_get(crtc->dev->dev);
 353        if (ret < 0) {
 354                DRM_ERROR("Failed to enable power domain: %d\n", ret);
 355                return ret;
 356        }
 357
 358        ret = mtk_mutex_prepare(mtk_crtc->mutex);
 359        if (ret < 0) {
 360                DRM_ERROR("Failed to enable mutex clock: %d\n", ret);
 361                goto err_pm_runtime_put;
 362        }
 363
 364        ret = mtk_crtc_ddp_clk_enable(mtk_crtc);
 365        if (ret < 0) {
 366                DRM_ERROR("Failed to enable component clocks: %d\n", ret);
 367                goto err_mutex_unprepare;
 368        }
 369
 370        for (i = 0; i < mtk_crtc->ddp_comp_nr - 1; i++) {
 371                mtk_mmsys_ddp_connect(mtk_crtc->mmsys_dev,
 372                                      mtk_crtc->ddp_comp[i]->id,
 373                                      mtk_crtc->ddp_comp[i + 1]->id);
 374                mtk_mutex_add_comp(mtk_crtc->mutex,
 375                                        mtk_crtc->ddp_comp[i]->id);
 376        }
 377        mtk_mutex_add_comp(mtk_crtc->mutex, mtk_crtc->ddp_comp[i]->id);
 378        mtk_mutex_enable(mtk_crtc->mutex);
 379
 380        for (i = 0; i < mtk_crtc->ddp_comp_nr; i++) {
 381                struct mtk_ddp_comp *comp = mtk_crtc->ddp_comp[i];
 382
 383                if (i == 1)
 384                        mtk_ddp_comp_bgclr_in_on(comp);
 385
 386                mtk_ddp_comp_config(comp, width, height, vrefresh, bpc, NULL);
 387                mtk_ddp_comp_start(comp);
 388        }
 389
 390        /* Initially configure all planes */
 391        for (i = 0; i < mtk_crtc->layer_nr; i++) {
 392                struct drm_plane *plane = &mtk_crtc->planes[i];
 393                struct mtk_plane_state *plane_state;
 394                struct mtk_ddp_comp *comp;
 395                unsigned int local_layer;
 396
 397                plane_state = to_mtk_plane_state(plane->state);
 398                comp = mtk_drm_ddp_comp_for_plane(crtc, plane, &local_layer);
 399                if (comp)
 400                        mtk_ddp_comp_layer_config(comp, local_layer,
 401                                                  plane_state, NULL);
 402        }
 403
 404        return 0;
 405
 406err_mutex_unprepare:
 407        mtk_mutex_unprepare(mtk_crtc->mutex);
 408err_pm_runtime_put:
 409        pm_runtime_put(crtc->dev->dev);
 410        return ret;
 411}
 412
 413static void mtk_crtc_ddp_hw_fini(struct mtk_drm_crtc *mtk_crtc)
 414{
 415        struct drm_device *drm = mtk_crtc->base.dev;
 416        struct drm_crtc *crtc = &mtk_crtc->base;
 417        int i;
 418
 419        for (i = 0; i < mtk_crtc->ddp_comp_nr; i++) {
 420                mtk_ddp_comp_stop(mtk_crtc->ddp_comp[i]);
 421                if (i == 1)
 422                        mtk_ddp_comp_bgclr_in_off(mtk_crtc->ddp_comp[i]);
 423        }
 424
 425        for (i = 0; i < mtk_crtc->ddp_comp_nr; i++)
 426                mtk_mutex_remove_comp(mtk_crtc->mutex,
 427                                           mtk_crtc->ddp_comp[i]->id);
 428        mtk_mutex_disable(mtk_crtc->mutex);
 429        for (i = 0; i < mtk_crtc->ddp_comp_nr - 1; i++) {
 430                mtk_mmsys_ddp_disconnect(mtk_crtc->mmsys_dev,
 431                                         mtk_crtc->ddp_comp[i]->id,
 432                                         mtk_crtc->ddp_comp[i + 1]->id);
 433                mtk_mutex_remove_comp(mtk_crtc->mutex,
 434                                           mtk_crtc->ddp_comp[i]->id);
 435        }
 436        mtk_mutex_remove_comp(mtk_crtc->mutex, mtk_crtc->ddp_comp[i]->id);
 437        mtk_crtc_ddp_clk_disable(mtk_crtc);
 438        mtk_mutex_unprepare(mtk_crtc->mutex);
 439
 440        pm_runtime_put(drm->dev);
 441
 442        if (crtc->state->event && !crtc->state->active) {
 443                spin_lock_irq(&crtc->dev->event_lock);
 444                drm_crtc_send_vblank_event(crtc, crtc->state->event);
 445                crtc->state->event = NULL;
 446                spin_unlock_irq(&crtc->dev->event_lock);
 447        }
 448}
 449
 450static void mtk_crtc_ddp_config(struct drm_crtc *crtc,
 451                                struct cmdq_pkt *cmdq_handle)
 452{
 453        struct mtk_drm_crtc *mtk_crtc = to_mtk_crtc(crtc);
 454        struct mtk_crtc_state *state = to_mtk_crtc_state(mtk_crtc->base.state);
 455        struct mtk_ddp_comp *comp = mtk_crtc->ddp_comp[0];
 456        unsigned int i;
 457        unsigned int local_layer;
 458
 459        /*
 460         * TODO: instead of updating the registers here, we should prepare
 461         * working registers in atomic_commit and let the hardware command
 462         * queue update module registers on vblank.
 463         */
 464        if (state->pending_config) {
 465                mtk_ddp_comp_config(comp, state->pending_width,
 466                                    state->pending_height,
 467                                    state->pending_vrefresh, 0,
 468                                    cmdq_handle);
 469
 470                if (!cmdq_handle)
 471                        state->pending_config = false;
 472        }
 473
 474        if (mtk_crtc->pending_planes) {
 475                for (i = 0; i < mtk_crtc->layer_nr; i++) {
 476                        struct drm_plane *plane = &mtk_crtc->planes[i];
 477                        struct mtk_plane_state *plane_state;
 478
 479                        plane_state = to_mtk_plane_state(plane->state);
 480
 481                        if (!plane_state->pending.config)
 482                                continue;
 483
 484                        comp = mtk_drm_ddp_comp_for_plane(crtc, plane,
 485                                                          &local_layer);
 486
 487                        if (comp)
 488                                mtk_ddp_comp_layer_config(comp, local_layer,
 489                                                          plane_state,
 490                                                          cmdq_handle);
 491                        if (!cmdq_handle)
 492                                plane_state->pending.config = false;
 493                }
 494
 495                if (!cmdq_handle)
 496                        mtk_crtc->pending_planes = false;
 497        }
 498
 499        if (mtk_crtc->pending_async_planes) {
 500                for (i = 0; i < mtk_crtc->layer_nr; i++) {
 501                        struct drm_plane *plane = &mtk_crtc->planes[i];
 502                        struct mtk_plane_state *plane_state;
 503
 504                        plane_state = to_mtk_plane_state(plane->state);
 505
 506                        if (!plane_state->pending.async_config)
 507                                continue;
 508
 509                        comp = mtk_drm_ddp_comp_for_plane(crtc, plane,
 510                                                          &local_layer);
 511
 512                        if (comp)
 513                                mtk_ddp_comp_layer_config(comp, local_layer,
 514                                                          plane_state,
 515                                                          cmdq_handle);
 516                        if (!cmdq_handle)
 517                                plane_state->pending.async_config = false;
 518                }
 519
 520                if (!cmdq_handle)
 521                        mtk_crtc->pending_async_planes = false;
 522        }
 523}
 524
 525static void mtk_drm_crtc_update_config(struct mtk_drm_crtc *mtk_crtc,
 526                                       bool needs_vblank)
 527{
 528#if IS_REACHABLE(CONFIG_MTK_CMDQ)
 529        struct cmdq_pkt *cmdq_handle = &mtk_crtc->cmdq_handle;
 530#endif
 531        struct drm_crtc *crtc = &mtk_crtc->base;
 532        struct mtk_drm_private *priv = crtc->dev->dev_private;
 533        unsigned int pending_planes = 0, pending_async_planes = 0;
 534        int i;
 535
 536        mutex_lock(&mtk_crtc->hw_lock);
 537        mtk_crtc->config_updating = true;
 538        if (needs_vblank)
 539                mtk_crtc->pending_needs_vblank = true;
 540
 541        for (i = 0; i < mtk_crtc->layer_nr; i++) {
 542                struct drm_plane *plane = &mtk_crtc->planes[i];
 543                struct mtk_plane_state *plane_state;
 544
 545                plane_state = to_mtk_plane_state(plane->state);
 546                if (plane_state->pending.dirty) {
 547                        plane_state->pending.config = true;
 548                        plane_state->pending.dirty = false;
 549                        pending_planes |= BIT(i);
 550                } else if (plane_state->pending.async_dirty) {
 551                        plane_state->pending.async_config = true;
 552                        plane_state->pending.async_dirty = false;
 553                        pending_async_planes |= BIT(i);
 554                }
 555        }
 556        if (pending_planes)
 557                mtk_crtc->pending_planes = true;
 558        if (pending_async_planes)
 559                mtk_crtc->pending_async_planes = true;
 560
 561        if (priv->data->shadow_register) {
 562                mtk_mutex_acquire(mtk_crtc->mutex);
 563                mtk_crtc_ddp_config(crtc, NULL);
 564                mtk_mutex_release(mtk_crtc->mutex);
 565        }
 566#if IS_REACHABLE(CONFIG_MTK_CMDQ)
 567        if (mtk_crtc->cmdq_client.chan) {
 568                mbox_flush(mtk_crtc->cmdq_client.chan, 2000);
 569                cmdq_handle->cmd_buf_size = 0;
 570                cmdq_pkt_clear_event(cmdq_handle, mtk_crtc->cmdq_event);
 571                cmdq_pkt_wfe(cmdq_handle, mtk_crtc->cmdq_event, false);
 572                mtk_crtc_ddp_config(crtc, cmdq_handle);
 573                cmdq_pkt_finalize(cmdq_handle);
 574                dma_sync_single_for_device(mtk_crtc->cmdq_client.chan->mbox->dev,
 575                                           cmdq_handle->pa_base,
 576                                           cmdq_handle->cmd_buf_size,
 577                                           DMA_TO_DEVICE);
 578                /*
 579                 * CMDQ command should execute in next 3 vblank.
 580                 * One vblank interrupt before send message (occasionally)
 581                 * and one vblank interrupt after cmdq done,
 582                 * so it's timeout after 3 vblank interrupt.
 583                 * If it fail to execute in next 3 vblank, timeout happen.
 584                 */
 585                mtk_crtc->cmdq_vblank_cnt = 3;
 586
 587                mbox_send_message(mtk_crtc->cmdq_client.chan, cmdq_handle);
 588                mbox_client_txdone(mtk_crtc->cmdq_client.chan, 0);
 589        }
 590#endif
 591        mtk_crtc->config_updating = false;
 592        mutex_unlock(&mtk_crtc->hw_lock);
 593}
 594
 595static void mtk_crtc_ddp_irq(void *data)
 596{
 597        struct drm_crtc *crtc = data;
 598        struct mtk_drm_crtc *mtk_crtc = to_mtk_crtc(crtc);
 599        struct mtk_drm_private *priv = crtc->dev->dev_private;
 600
 601#if IS_REACHABLE(CONFIG_MTK_CMDQ)
 602        if (!priv->data->shadow_register && !mtk_crtc->cmdq_client.chan)
 603                mtk_crtc_ddp_config(crtc, NULL);
 604        else if (mtk_crtc->cmdq_vblank_cnt > 0 && --mtk_crtc->cmdq_vblank_cnt == 0)
 605                DRM_ERROR("mtk_crtc %d CMDQ execute command timeout!\n",
 606                          drm_crtc_index(&mtk_crtc->base));
 607#else
 608        if (!priv->data->shadow_register)
 609                mtk_crtc_ddp_config(crtc, NULL);
 610#endif
 611        mtk_drm_finish_page_flip(mtk_crtc);
 612}
 613
 614static int mtk_drm_crtc_enable_vblank(struct drm_crtc *crtc)
 615{
 616        struct mtk_drm_crtc *mtk_crtc = to_mtk_crtc(crtc);
 617        struct mtk_ddp_comp *comp = mtk_crtc->ddp_comp[0];
 618
 619        mtk_ddp_comp_enable_vblank(comp, mtk_crtc_ddp_irq, &mtk_crtc->base);
 620
 621        return 0;
 622}
 623
 624static void mtk_drm_crtc_disable_vblank(struct drm_crtc *crtc)
 625{
 626        struct mtk_drm_crtc *mtk_crtc = to_mtk_crtc(crtc);
 627        struct mtk_ddp_comp *comp = mtk_crtc->ddp_comp[0];
 628
 629        mtk_ddp_comp_disable_vblank(comp);
 630}
 631
 632int mtk_drm_crtc_plane_check(struct drm_crtc *crtc, struct drm_plane *plane,
 633                             struct mtk_plane_state *state)
 634{
 635        unsigned int local_layer;
 636        struct mtk_ddp_comp *comp;
 637
 638        comp = mtk_drm_ddp_comp_for_plane(crtc, plane, &local_layer);
 639        if (comp)
 640                return mtk_ddp_comp_layer_check(comp, local_layer, state);
 641        return 0;
 642}
 643
 644void mtk_drm_crtc_async_update(struct drm_crtc *crtc, struct drm_plane *plane,
 645                               struct drm_atomic_state *state)
 646{
 647        struct mtk_drm_crtc *mtk_crtc = to_mtk_crtc(crtc);
 648
 649        if (!mtk_crtc->enabled)
 650                return;
 651
 652        mtk_drm_crtc_update_config(mtk_crtc, false);
 653}
 654
 655static void mtk_drm_crtc_atomic_enable(struct drm_crtc *crtc,
 656                                       struct drm_atomic_state *state)
 657{
 658        struct mtk_drm_crtc *mtk_crtc = to_mtk_crtc(crtc);
 659        struct mtk_ddp_comp *comp = mtk_crtc->ddp_comp[0];
 660        int ret;
 661
 662        DRM_DEBUG_DRIVER("%s %d\n", __func__, crtc->base.id);
 663
 664        ret = mtk_smi_larb_get(comp->larb_dev);
 665        if (ret) {
 666                DRM_ERROR("Failed to get larb: %d\n", ret);
 667                return;
 668        }
 669
 670        ret = mtk_crtc_ddp_hw_init(mtk_crtc);
 671        if (ret) {
 672                mtk_smi_larb_put(comp->larb_dev);
 673                return;
 674        }
 675
 676        drm_crtc_vblank_on(crtc);
 677        mtk_crtc->enabled = true;
 678}
 679
 680static void mtk_drm_crtc_atomic_disable(struct drm_crtc *crtc,
 681                                        struct drm_atomic_state *state)
 682{
 683        struct mtk_drm_crtc *mtk_crtc = to_mtk_crtc(crtc);
 684        struct mtk_ddp_comp *comp = mtk_crtc->ddp_comp[0];
 685        int i;
 686
 687        DRM_DEBUG_DRIVER("%s %d\n", __func__, crtc->base.id);
 688        if (!mtk_crtc->enabled)
 689                return;
 690
 691        /* Set all pending plane state to disabled */
 692        for (i = 0; i < mtk_crtc->layer_nr; i++) {
 693                struct drm_plane *plane = &mtk_crtc->planes[i];
 694                struct mtk_plane_state *plane_state;
 695
 696                plane_state = to_mtk_plane_state(plane->state);
 697                plane_state->pending.enable = false;
 698                plane_state->pending.config = true;
 699        }
 700        mtk_crtc->pending_planes = true;
 701
 702        mtk_drm_crtc_update_config(mtk_crtc, false);
 703        /* Wait for planes to be disabled */
 704        drm_crtc_wait_one_vblank(crtc);
 705
 706        drm_crtc_vblank_off(crtc);
 707        mtk_crtc_ddp_hw_fini(mtk_crtc);
 708        mtk_smi_larb_put(comp->larb_dev);
 709
 710        mtk_crtc->enabled = false;
 711}
 712
 713static void mtk_drm_crtc_atomic_begin(struct drm_crtc *crtc,
 714                                      struct drm_atomic_state *state)
 715{
 716        struct drm_crtc_state *crtc_state = drm_atomic_get_new_crtc_state(state,
 717                                                                          crtc);
 718        struct mtk_crtc_state *mtk_crtc_state = to_mtk_crtc_state(crtc_state);
 719        struct mtk_drm_crtc *mtk_crtc = to_mtk_crtc(crtc);
 720
 721        if (mtk_crtc->event && mtk_crtc_state->base.event)
 722                DRM_ERROR("new event while there is still a pending event\n");
 723
 724        if (mtk_crtc_state->base.event) {
 725                mtk_crtc_state->base.event->pipe = drm_crtc_index(crtc);
 726                WARN_ON(drm_crtc_vblank_get(crtc) != 0);
 727                mtk_crtc->event = mtk_crtc_state->base.event;
 728                mtk_crtc_state->base.event = NULL;
 729        }
 730}
 731
 732static void mtk_drm_crtc_atomic_flush(struct drm_crtc *crtc,
 733                                      struct drm_atomic_state *state)
 734{
 735        struct mtk_drm_crtc *mtk_crtc = to_mtk_crtc(crtc);
 736        int i;
 737
 738        if (crtc->state->color_mgmt_changed)
 739                for (i = 0; i < mtk_crtc->ddp_comp_nr; i++) {
 740                        mtk_ddp_gamma_set(mtk_crtc->ddp_comp[i], crtc->state);
 741                        mtk_ddp_ctm_set(mtk_crtc->ddp_comp[i], crtc->state);
 742                }
 743        mtk_drm_crtc_update_config(mtk_crtc, !!mtk_crtc->event);
 744}
 745
 746static const struct drm_crtc_funcs mtk_crtc_funcs = {
 747        .set_config             = drm_atomic_helper_set_config,
 748        .page_flip              = drm_atomic_helper_page_flip,
 749        .destroy                = mtk_drm_crtc_destroy,
 750        .reset                  = mtk_drm_crtc_reset,
 751        .atomic_duplicate_state = mtk_drm_crtc_duplicate_state,
 752        .atomic_destroy_state   = mtk_drm_crtc_destroy_state,
 753        .enable_vblank          = mtk_drm_crtc_enable_vblank,
 754        .disable_vblank         = mtk_drm_crtc_disable_vblank,
 755};
 756
 757static const struct drm_crtc_helper_funcs mtk_crtc_helper_funcs = {
 758        .mode_fixup     = mtk_drm_crtc_mode_fixup,
 759        .mode_set_nofb  = mtk_drm_crtc_mode_set_nofb,
 760        .atomic_begin   = mtk_drm_crtc_atomic_begin,
 761        .atomic_flush   = mtk_drm_crtc_atomic_flush,
 762        .atomic_enable  = mtk_drm_crtc_atomic_enable,
 763        .atomic_disable = mtk_drm_crtc_atomic_disable,
 764};
 765
 766static int mtk_drm_crtc_init(struct drm_device *drm,
 767                             struct mtk_drm_crtc *mtk_crtc,
 768                             unsigned int pipe)
 769{
 770        struct drm_plane *primary = NULL;
 771        struct drm_plane *cursor = NULL;
 772        int i, ret;
 773
 774        for (i = 0; i < mtk_crtc->layer_nr; i++) {
 775                if (mtk_crtc->planes[i].type == DRM_PLANE_TYPE_PRIMARY)
 776                        primary = &mtk_crtc->planes[i];
 777                else if (mtk_crtc->planes[i].type == DRM_PLANE_TYPE_CURSOR)
 778                        cursor = &mtk_crtc->planes[i];
 779        }
 780
 781        ret = drm_crtc_init_with_planes(drm, &mtk_crtc->base, primary, cursor,
 782                                        &mtk_crtc_funcs, NULL);
 783        if (ret)
 784                goto err_cleanup_crtc;
 785
 786        drm_crtc_helper_add(&mtk_crtc->base, &mtk_crtc_helper_funcs);
 787
 788        return 0;
 789
 790err_cleanup_crtc:
 791        drm_crtc_cleanup(&mtk_crtc->base);
 792        return ret;
 793}
 794
 795static int mtk_drm_crtc_num_comp_planes(struct mtk_drm_crtc *mtk_crtc,
 796                                        int comp_idx)
 797{
 798        struct mtk_ddp_comp *comp;
 799
 800        if (comp_idx > 1)
 801                return 0;
 802
 803        comp = mtk_crtc->ddp_comp[comp_idx];
 804        if (!comp->funcs)
 805                return 0;
 806
 807        if (comp_idx == 1 && !comp->funcs->bgclr_in_on)
 808                return 0;
 809
 810        return mtk_ddp_comp_layer_nr(comp);
 811}
 812
 813static inline
 814enum drm_plane_type mtk_drm_crtc_plane_type(unsigned int plane_idx,
 815                                            unsigned int num_planes)
 816{
 817        if (plane_idx == 0)
 818                return DRM_PLANE_TYPE_PRIMARY;
 819        else if (plane_idx == (num_planes - 1))
 820                return DRM_PLANE_TYPE_CURSOR;
 821        else
 822                return DRM_PLANE_TYPE_OVERLAY;
 823
 824}
 825
 826static int mtk_drm_crtc_init_comp_planes(struct drm_device *drm_dev,
 827                                         struct mtk_drm_crtc *mtk_crtc,
 828                                         int comp_idx, int pipe)
 829{
 830        int num_planes = mtk_drm_crtc_num_comp_planes(mtk_crtc, comp_idx);
 831        struct mtk_ddp_comp *comp = mtk_crtc->ddp_comp[comp_idx];
 832        int i, ret;
 833
 834        for (i = 0; i < num_planes; i++) {
 835                ret = mtk_plane_init(drm_dev,
 836                                &mtk_crtc->planes[mtk_crtc->layer_nr],
 837                                BIT(pipe),
 838                                mtk_drm_crtc_plane_type(mtk_crtc->layer_nr,
 839                                                        num_planes),
 840                                mtk_ddp_comp_supported_rotations(comp));
 841                if (ret)
 842                        return ret;
 843
 844                mtk_crtc->layer_nr++;
 845        }
 846        return 0;
 847}
 848
 849int mtk_drm_crtc_create(struct drm_device *drm_dev,
 850                        const enum mtk_ddp_comp_id *path, unsigned int path_len)
 851{
 852        struct mtk_drm_private *priv = drm_dev->dev_private;
 853        struct device *dev = drm_dev->dev;
 854        struct mtk_drm_crtc *mtk_crtc;
 855        unsigned int num_comp_planes = 0;
 856        int pipe = priv->num_pipes;
 857        int ret;
 858        int i;
 859        bool has_ctm = false;
 860        uint gamma_lut_size = 0;
 861
 862        if (!path)
 863                return 0;
 864
 865        for (i = 0; i < path_len; i++) {
 866                enum mtk_ddp_comp_id comp_id = path[i];
 867                struct device_node *node;
 868                struct mtk_ddp_comp *comp;
 869
 870                node = priv->comp_node[comp_id];
 871                comp = &priv->ddp_comp[comp_id];
 872
 873                if (!node) {
 874                        dev_info(dev,
 875                                 "Not creating crtc %d because component %d is disabled or missing\n",
 876                                 pipe, comp_id);
 877                        return 0;
 878                }
 879
 880                if (!comp->dev) {
 881                        dev_err(dev, "Component %pOF not initialized\n", node);
 882                        return -ENODEV;
 883                }
 884        }
 885
 886        mtk_crtc = devm_kzalloc(dev, sizeof(*mtk_crtc), GFP_KERNEL);
 887        if (!mtk_crtc)
 888                return -ENOMEM;
 889
 890        mtk_crtc->mmsys_dev = priv->mmsys_dev;
 891        mtk_crtc->ddp_comp_nr = path_len;
 892        mtk_crtc->ddp_comp = devm_kmalloc_array(dev, mtk_crtc->ddp_comp_nr,
 893                                                sizeof(*mtk_crtc->ddp_comp),
 894                                                GFP_KERNEL);
 895        if (!mtk_crtc->ddp_comp)
 896                return -ENOMEM;
 897
 898        mtk_crtc->mutex = mtk_mutex_get(priv->mutex_dev);
 899        if (IS_ERR(mtk_crtc->mutex)) {
 900                ret = PTR_ERR(mtk_crtc->mutex);
 901                dev_err(dev, "Failed to get mutex: %d\n", ret);
 902                return ret;
 903        }
 904
 905        for (i = 0; i < mtk_crtc->ddp_comp_nr; i++) {
 906                enum mtk_ddp_comp_id comp_id = path[i];
 907                struct mtk_ddp_comp *comp;
 908
 909                comp = &priv->ddp_comp[comp_id];
 910                mtk_crtc->ddp_comp[i] = comp;
 911
 912                if (comp->funcs) {
 913                        if (comp->funcs->gamma_set)
 914                                gamma_lut_size = MTK_LUT_SIZE;
 915
 916                        if (comp->funcs->ctm_set)
 917                                has_ctm = true;
 918                }
 919        }
 920
 921        for (i = 0; i < mtk_crtc->ddp_comp_nr; i++)
 922                num_comp_planes += mtk_drm_crtc_num_comp_planes(mtk_crtc, i);
 923
 924        mtk_crtc->planes = devm_kcalloc(dev, num_comp_planes,
 925                                        sizeof(struct drm_plane), GFP_KERNEL);
 926
 927        for (i = 0; i < mtk_crtc->ddp_comp_nr; i++) {
 928                ret = mtk_drm_crtc_init_comp_planes(drm_dev, mtk_crtc, i,
 929                                                    pipe);
 930                if (ret)
 931                        return ret;
 932        }
 933
 934        ret = mtk_drm_crtc_init(drm_dev, mtk_crtc, pipe);
 935        if (ret < 0)
 936                return ret;
 937
 938        if (gamma_lut_size)
 939                drm_mode_crtc_set_gamma_size(&mtk_crtc->base, gamma_lut_size);
 940        drm_crtc_enable_color_mgmt(&mtk_crtc->base, 0, has_ctm, gamma_lut_size);
 941        priv->num_pipes++;
 942        mutex_init(&mtk_crtc->hw_lock);
 943
 944#if IS_REACHABLE(CONFIG_MTK_CMDQ)
 945        mtk_crtc->cmdq_client.client.dev = mtk_crtc->mmsys_dev;
 946        mtk_crtc->cmdq_client.client.tx_block = false;
 947        mtk_crtc->cmdq_client.client.knows_txdone = true;
 948        mtk_crtc->cmdq_client.client.rx_callback = ddp_cmdq_cb;
 949        mtk_crtc->cmdq_client.chan =
 950                        mbox_request_channel(&mtk_crtc->cmdq_client.client,
 951                                             drm_crtc_index(&mtk_crtc->base));
 952        if (IS_ERR(mtk_crtc->cmdq_client.chan)) {
 953                dev_dbg(dev, "mtk_crtc %d failed to create mailbox client, writing register by CPU now\n",
 954                        drm_crtc_index(&mtk_crtc->base));
 955                mtk_crtc->cmdq_client.chan = NULL;
 956        }
 957
 958        if (mtk_crtc->cmdq_client.chan) {
 959                ret = of_property_read_u32_index(priv->mutex_node,
 960                                                 "mediatek,gce-events",
 961                                                 drm_crtc_index(&mtk_crtc->base),
 962                                                 &mtk_crtc->cmdq_event);
 963                if (ret) {
 964                        dev_dbg(dev, "mtk_crtc %d failed to get mediatek,gce-events property\n",
 965                                drm_crtc_index(&mtk_crtc->base));
 966                        mbox_free_channel(mtk_crtc->cmdq_client.chan);
 967                        mtk_crtc->cmdq_client.chan = NULL;
 968                } else {
 969                        ret = mtk_drm_cmdq_pkt_create(&mtk_crtc->cmdq_client,
 970                                                      &mtk_crtc->cmdq_handle,
 971                                                      PAGE_SIZE);
 972                        if (ret) {
 973                                dev_dbg(dev, "mtk_crtc %d failed to create cmdq packet\n",
 974                                        drm_crtc_index(&mtk_crtc->base));
 975                                mbox_free_channel(mtk_crtc->cmdq_client.chan);
 976                                mtk_crtc->cmdq_client.chan = NULL;
 977                        }
 978                }
 979        }
 980#endif
 981        return 0;
 982}
 983