linux/drivers/gpu/drm/omapdrm/omap_crtc.c
<<
>>
Prefs
   1// SPDX-License-Identifier: GPL-2.0-only
   2/*
   3 * Copyright (C) 2011 Texas Instruments Incorporated - http://www.ti.com/
   4 * Author: Rob Clark <rob@ti.com>
   5 */
   6
   7#include <drm/drm_atomic.h>
   8#include <drm/drm_atomic_helper.h>
   9#include <drm/drm_crtc.h>
  10#include <drm/drm_mode.h>
  11#include <drm/drm_plane_helper.h>
  12#include <linux/math64.h>
  13
  14#include "omap_drv.h"
  15
  16#define to_omap_crtc_state(x) container_of(x, struct omap_crtc_state, base)
  17
  18struct omap_crtc_state {
  19        /* Must be first. */
  20        struct drm_crtc_state base;
  21        /* Shadow values for legacy userspace support. */
  22        unsigned int rotation;
  23        unsigned int zpos;
  24};
  25
  26#define to_omap_crtc(x) container_of(x, struct omap_crtc, base)
  27
  28struct omap_crtc {
  29        struct drm_crtc base;
  30
  31        const char *name;
  32        struct omap_drm_pipeline *pipe;
  33        enum omap_channel channel;
  34
  35        struct videomode vm;
  36
  37        bool ignore_digit_sync_lost;
  38
  39        bool enabled;
  40        bool pending;
  41        wait_queue_head_t pending_wait;
  42        struct drm_pending_vblank_event *event;
  43};
  44
  45/* -----------------------------------------------------------------------------
  46 * Helper Functions
  47 */
  48
  49struct videomode *omap_crtc_timings(struct drm_crtc *crtc)
  50{
  51        struct omap_crtc *omap_crtc = to_omap_crtc(crtc);
  52        return &omap_crtc->vm;
  53}
  54
  55enum omap_channel omap_crtc_channel(struct drm_crtc *crtc)
  56{
  57        struct omap_crtc *omap_crtc = to_omap_crtc(crtc);
  58        return omap_crtc->channel;
  59}
  60
  61static bool omap_crtc_is_pending(struct drm_crtc *crtc)
  62{
  63        struct omap_crtc *omap_crtc = to_omap_crtc(crtc);
  64        unsigned long flags;
  65        bool pending;
  66
  67        spin_lock_irqsave(&crtc->dev->event_lock, flags);
  68        pending = omap_crtc->pending;
  69        spin_unlock_irqrestore(&crtc->dev->event_lock, flags);
  70
  71        return pending;
  72}
  73
  74int omap_crtc_wait_pending(struct drm_crtc *crtc)
  75{
  76        struct omap_crtc *omap_crtc = to_omap_crtc(crtc);
  77
  78        /*
  79         * Timeout is set to a "sufficiently" high value, which should cover
  80         * a single frame refresh even on slower displays.
  81         */
  82        return wait_event_timeout(omap_crtc->pending_wait,
  83                                  !omap_crtc_is_pending(crtc),
  84                                  msecs_to_jiffies(250));
  85}
  86
  87/* -----------------------------------------------------------------------------
  88 * DSS Manager Functions
  89 */
  90
  91/*
  92 * Manager-ops, callbacks from output when they need to configure
  93 * the upstream part of the video pipe.
  94 *
  95 * Most of these we can ignore until we add support for command-mode
  96 * panels.. for video-mode the crtc-helpers already do an adequate
  97 * job of sequencing the setup of the video pipe in the proper order
  98 */
  99
 100/* we can probably ignore these until we support command-mode panels: */
 101static void omap_crtc_dss_start_update(struct omap_drm_private *priv,
 102                                       enum omap_channel channel)
 103{
 104}
 105
 106/* Called only from the encoder enable/disable and suspend/resume handlers. */
 107static void omap_crtc_set_enabled(struct drm_crtc *crtc, bool enable)
 108{
 109        struct drm_device *dev = crtc->dev;
 110        struct omap_drm_private *priv = dev->dev_private;
 111        struct omap_crtc *omap_crtc = to_omap_crtc(crtc);
 112        enum omap_channel channel = omap_crtc->channel;
 113        struct omap_irq_wait *wait;
 114        u32 framedone_irq, vsync_irq;
 115        int ret;
 116
 117        if (WARN_ON(omap_crtc->enabled == enable))
 118                return;
 119
 120        if (omap_crtc->pipe->output->type == OMAP_DISPLAY_TYPE_HDMI) {
 121                priv->dispc_ops->mgr_enable(priv->dispc, channel, enable);
 122                omap_crtc->enabled = enable;
 123                return;
 124        }
 125
 126        if (omap_crtc->channel == OMAP_DSS_CHANNEL_DIGIT) {
 127                /*
 128                 * Digit output produces some sync lost interrupts during the
 129                 * first frame when enabling, so we need to ignore those.
 130                 */
 131                omap_crtc->ignore_digit_sync_lost = true;
 132        }
 133
 134        framedone_irq = priv->dispc_ops->mgr_get_framedone_irq(priv->dispc,
 135                                                               channel);
 136        vsync_irq = priv->dispc_ops->mgr_get_vsync_irq(priv->dispc, channel);
 137
 138        if (enable) {
 139                wait = omap_irq_wait_init(dev, vsync_irq, 1);
 140        } else {
 141                /*
 142                 * When we disable the digit output, we need to wait for
 143                 * FRAMEDONE to know that DISPC has finished with the output.
 144                 *
 145                 * OMAP2/3 does not have FRAMEDONE irq for digit output, and in
 146                 * that case we need to use vsync interrupt, and wait for both
 147                 * even and odd frames.
 148                 */
 149
 150                if (framedone_irq)
 151                        wait = omap_irq_wait_init(dev, framedone_irq, 1);
 152                else
 153                        wait = omap_irq_wait_init(dev, vsync_irq, 2);
 154        }
 155
 156        priv->dispc_ops->mgr_enable(priv->dispc, channel, enable);
 157        omap_crtc->enabled = enable;
 158
 159        ret = omap_irq_wait(dev, wait, msecs_to_jiffies(100));
 160        if (ret) {
 161                dev_err(dev->dev, "%s: timeout waiting for %s\n",
 162                                omap_crtc->name, enable ? "enable" : "disable");
 163        }
 164
 165        if (omap_crtc->channel == OMAP_DSS_CHANNEL_DIGIT) {
 166                omap_crtc->ignore_digit_sync_lost = false;
 167                /* make sure the irq handler sees the value above */
 168                mb();
 169        }
 170}
 171
 172
 173static int omap_crtc_dss_enable(struct omap_drm_private *priv,
 174                                enum omap_channel channel)
 175{
 176        struct drm_crtc *crtc = priv->channels[channel]->crtc;
 177        struct omap_crtc *omap_crtc = to_omap_crtc(crtc);
 178
 179        priv->dispc_ops->mgr_set_timings(priv->dispc, omap_crtc->channel,
 180                                         &omap_crtc->vm);
 181        omap_crtc_set_enabled(&omap_crtc->base, true);
 182
 183        return 0;
 184}
 185
 186static void omap_crtc_dss_disable(struct omap_drm_private *priv,
 187                                  enum omap_channel channel)
 188{
 189        struct drm_crtc *crtc = priv->channels[channel]->crtc;
 190        struct omap_crtc *omap_crtc = to_omap_crtc(crtc);
 191
 192        omap_crtc_set_enabled(&omap_crtc->base, false);
 193}
 194
 195static void omap_crtc_dss_set_timings(struct omap_drm_private *priv,
 196                enum omap_channel channel,
 197                const struct videomode *vm)
 198{
 199        struct drm_crtc *crtc = priv->channels[channel]->crtc;
 200        struct omap_crtc *omap_crtc = to_omap_crtc(crtc);
 201
 202        DBG("%s", omap_crtc->name);
 203        omap_crtc->vm = *vm;
 204}
 205
 206static void omap_crtc_dss_set_lcd_config(struct omap_drm_private *priv,
 207                enum omap_channel channel,
 208                const struct dss_lcd_mgr_config *config)
 209{
 210        struct drm_crtc *crtc = priv->channels[channel]->crtc;
 211        struct omap_crtc *omap_crtc = to_omap_crtc(crtc);
 212
 213        DBG("%s", omap_crtc->name);
 214        priv->dispc_ops->mgr_set_lcd_config(priv->dispc, omap_crtc->channel,
 215                                            config);
 216}
 217
 218static int omap_crtc_dss_register_framedone(
 219                struct omap_drm_private *priv, enum omap_channel channel,
 220                void (*handler)(void *), void *data)
 221{
 222        return 0;
 223}
 224
 225static void omap_crtc_dss_unregister_framedone(
 226                struct omap_drm_private *priv, enum omap_channel channel,
 227                void (*handler)(void *), void *data)
 228{
 229}
 230
 231static const struct dss_mgr_ops mgr_ops = {
 232        .start_update = omap_crtc_dss_start_update,
 233        .enable = omap_crtc_dss_enable,
 234        .disable = omap_crtc_dss_disable,
 235        .set_timings = omap_crtc_dss_set_timings,
 236        .set_lcd_config = omap_crtc_dss_set_lcd_config,
 237        .register_framedone_handler = omap_crtc_dss_register_framedone,
 238        .unregister_framedone_handler = omap_crtc_dss_unregister_framedone,
 239};
 240
 241/* -----------------------------------------------------------------------------
 242 * Setup, Flush and Page Flip
 243 */
 244
 245void omap_crtc_error_irq(struct drm_crtc *crtc, u32 irqstatus)
 246{
 247        struct omap_crtc *omap_crtc = to_omap_crtc(crtc);
 248
 249        if (omap_crtc->ignore_digit_sync_lost) {
 250                irqstatus &= ~DISPC_IRQ_SYNC_LOST_DIGIT;
 251                if (!irqstatus)
 252                        return;
 253        }
 254
 255        DRM_ERROR_RATELIMITED("%s: errors: %08x\n", omap_crtc->name, irqstatus);
 256}
 257
 258void omap_crtc_vblank_irq(struct drm_crtc *crtc)
 259{
 260        struct omap_crtc *omap_crtc = to_omap_crtc(crtc);
 261        struct drm_device *dev = omap_crtc->base.dev;
 262        struct omap_drm_private *priv = dev->dev_private;
 263        bool pending;
 264
 265        spin_lock(&crtc->dev->event_lock);
 266        /*
 267         * If the dispc is busy we're racing the flush operation. Try again on
 268         * the next vblank interrupt.
 269         */
 270        if (priv->dispc_ops->mgr_go_busy(priv->dispc, omap_crtc->channel)) {
 271                spin_unlock(&crtc->dev->event_lock);
 272                return;
 273        }
 274
 275        /* Send the vblank event if one has been requested. */
 276        if (omap_crtc->event) {
 277                drm_crtc_send_vblank_event(crtc, omap_crtc->event);
 278                omap_crtc->event = NULL;
 279        }
 280
 281        pending = omap_crtc->pending;
 282        omap_crtc->pending = false;
 283        spin_unlock(&crtc->dev->event_lock);
 284
 285        if (pending)
 286                drm_crtc_vblank_put(crtc);
 287
 288        /* Wake up omap_atomic_complete. */
 289        wake_up(&omap_crtc->pending_wait);
 290
 291        DBG("%s: apply done", omap_crtc->name);
 292}
 293
 294static void omap_crtc_write_crtc_properties(struct drm_crtc *crtc)
 295{
 296        struct omap_drm_private *priv = crtc->dev->dev_private;
 297        struct omap_crtc *omap_crtc = to_omap_crtc(crtc);
 298        struct omap_overlay_manager_info info;
 299
 300        memset(&info, 0, sizeof(info));
 301
 302        info.default_color = 0x000000;
 303        info.trans_enabled = false;
 304        info.partial_alpha_enabled = false;
 305        info.cpr_enable = false;
 306
 307        priv->dispc_ops->mgr_setup(priv->dispc, omap_crtc->channel, &info);
 308}
 309
 310/* -----------------------------------------------------------------------------
 311 * CRTC Functions
 312 */
 313
 314static void omap_crtc_destroy(struct drm_crtc *crtc)
 315{
 316        struct omap_crtc *omap_crtc = to_omap_crtc(crtc);
 317
 318        DBG("%s", omap_crtc->name);
 319
 320        drm_crtc_cleanup(crtc);
 321
 322        kfree(omap_crtc);
 323}
 324
 325static void omap_crtc_arm_event(struct drm_crtc *crtc)
 326{
 327        struct omap_crtc *omap_crtc = to_omap_crtc(crtc);
 328
 329        WARN_ON(omap_crtc->pending);
 330        omap_crtc->pending = true;
 331
 332        if (crtc->state->event) {
 333                omap_crtc->event = crtc->state->event;
 334                crtc->state->event = NULL;
 335        }
 336}
 337
 338static void omap_crtc_atomic_enable(struct drm_crtc *crtc,
 339                                    struct drm_crtc_state *old_state)
 340{
 341        struct omap_drm_private *priv = crtc->dev->dev_private;
 342        struct omap_crtc *omap_crtc = to_omap_crtc(crtc);
 343        int ret;
 344
 345        DBG("%s", omap_crtc->name);
 346
 347        priv->dispc_ops->runtime_get(priv->dispc);
 348
 349        spin_lock_irq(&crtc->dev->event_lock);
 350        drm_crtc_vblank_on(crtc);
 351        ret = drm_crtc_vblank_get(crtc);
 352        WARN_ON(ret != 0);
 353
 354        omap_crtc_arm_event(crtc);
 355        spin_unlock_irq(&crtc->dev->event_lock);
 356}
 357
 358static void omap_crtc_atomic_disable(struct drm_crtc *crtc,
 359                                     struct drm_crtc_state *old_state)
 360{
 361        struct omap_drm_private *priv = crtc->dev->dev_private;
 362        struct omap_crtc *omap_crtc = to_omap_crtc(crtc);
 363
 364        DBG("%s", omap_crtc->name);
 365
 366        spin_lock_irq(&crtc->dev->event_lock);
 367        if (crtc->state->event) {
 368                drm_crtc_send_vblank_event(crtc, crtc->state->event);
 369                crtc->state->event = NULL;
 370        }
 371        spin_unlock_irq(&crtc->dev->event_lock);
 372
 373        drm_crtc_vblank_off(crtc);
 374
 375        priv->dispc_ops->runtime_put(priv->dispc);
 376}
 377
 378static enum drm_mode_status omap_crtc_mode_valid(struct drm_crtc *crtc,
 379                                        const struct drm_display_mode *mode)
 380{
 381        struct omap_drm_private *priv = crtc->dev->dev_private;
 382        struct omap_crtc *omap_crtc = to_omap_crtc(crtc);
 383        struct videomode vm = {0};
 384        int r;
 385
 386        drm_display_mode_to_videomode(mode, &vm);
 387        r = priv->dispc_ops->mgr_check_timings(priv->dispc, omap_crtc->channel,
 388                                               &vm);
 389        if (r)
 390                return r;
 391
 392        /* Check for bandwidth limit */
 393        if (priv->max_bandwidth) {
 394                /*
 395                 * Estimation for the bandwidth need of a given mode with one
 396                 * full screen plane:
 397                 * bandwidth = resolution * 32bpp * (pclk / (vtotal * htotal))
 398                 *                                      ^^ Refresh rate ^^
 399                 *
 400                 * The interlaced mode is taken into account by using the
 401                 * pixelclock in the calculation.
 402                 *
 403                 * The equation is rearranged for 64bit arithmetic.
 404                 */
 405                uint64_t bandwidth = mode->clock * 1000;
 406                unsigned int bpp = 4;
 407
 408                bandwidth = bandwidth * mode->hdisplay * mode->vdisplay * bpp;
 409                bandwidth = div_u64(bandwidth, mode->htotal * mode->vtotal);
 410
 411                /*
 412                 * Reject modes which would need more bandwidth if used with one
 413                 * full resolution plane (most common use case).
 414                 */
 415                if (priv->max_bandwidth < bandwidth)
 416                        return MODE_BAD;
 417        }
 418
 419        return MODE_OK;
 420}
 421
 422static void omap_crtc_mode_set_nofb(struct drm_crtc *crtc)
 423{
 424        struct omap_crtc *omap_crtc = to_omap_crtc(crtc);
 425        struct drm_display_mode *mode = &crtc->state->adjusted_mode;
 426
 427        DBG("%s: set mode: " DRM_MODE_FMT,
 428            omap_crtc->name, DRM_MODE_ARG(mode));
 429
 430        drm_display_mode_to_videomode(mode, &omap_crtc->vm);
 431}
 432
 433static int omap_crtc_atomic_check(struct drm_crtc *crtc,
 434                                struct drm_crtc_state *state)
 435{
 436        struct drm_plane_state *pri_state;
 437
 438        if (state->color_mgmt_changed && state->gamma_lut) {
 439                unsigned int length = state->gamma_lut->length /
 440                        sizeof(struct drm_color_lut);
 441
 442                if (length < 2)
 443                        return -EINVAL;
 444        }
 445
 446        pri_state = drm_atomic_get_new_plane_state(state->state, crtc->primary);
 447        if (pri_state) {
 448                struct omap_crtc_state *omap_crtc_state =
 449                        to_omap_crtc_state(state);
 450
 451                /* Mirror new values for zpos and rotation in omap_crtc_state */
 452                omap_crtc_state->zpos = pri_state->zpos;
 453                omap_crtc_state->rotation = pri_state->rotation;
 454        }
 455
 456        return 0;
 457}
 458
 459static void omap_crtc_atomic_begin(struct drm_crtc *crtc,
 460                                   struct drm_crtc_state *old_crtc_state)
 461{
 462}
 463
 464static void omap_crtc_atomic_flush(struct drm_crtc *crtc,
 465                                   struct drm_crtc_state *old_crtc_state)
 466{
 467        struct omap_drm_private *priv = crtc->dev->dev_private;
 468        struct omap_crtc *omap_crtc = to_omap_crtc(crtc);
 469        int ret;
 470
 471        if (crtc->state->color_mgmt_changed) {
 472                struct drm_color_lut *lut = NULL;
 473                unsigned int length = 0;
 474
 475                if (crtc->state->gamma_lut) {
 476                        lut = (struct drm_color_lut *)
 477                                crtc->state->gamma_lut->data;
 478                        length = crtc->state->gamma_lut->length /
 479                                sizeof(*lut);
 480                }
 481                priv->dispc_ops->mgr_set_gamma(priv->dispc, omap_crtc->channel,
 482                                               lut, length);
 483        }
 484
 485        omap_crtc_write_crtc_properties(crtc);
 486
 487        /* Only flush the CRTC if it is currently enabled. */
 488        if (!omap_crtc->enabled)
 489                return;
 490
 491        DBG("%s: GO", omap_crtc->name);
 492
 493        ret = drm_crtc_vblank_get(crtc);
 494        WARN_ON(ret != 0);
 495
 496        spin_lock_irq(&crtc->dev->event_lock);
 497        priv->dispc_ops->mgr_go(priv->dispc, omap_crtc->channel);
 498        omap_crtc_arm_event(crtc);
 499        spin_unlock_irq(&crtc->dev->event_lock);
 500}
 501
 502static int omap_crtc_atomic_set_property(struct drm_crtc *crtc,
 503                                         struct drm_crtc_state *state,
 504                                         struct drm_property *property,
 505                                         u64 val)
 506{
 507        struct omap_drm_private *priv = crtc->dev->dev_private;
 508        struct drm_plane_state *plane_state;
 509
 510        /*
 511         * Delegate property set to the primary plane. Get the plane state and
 512         * set the property directly, the shadow copy will be assigned in the
 513         * omap_crtc_atomic_check callback. This way updates to plane state will
 514         * always be mirrored in the crtc state correctly.
 515         */
 516        plane_state = drm_atomic_get_plane_state(state->state, crtc->primary);
 517        if (IS_ERR(plane_state))
 518                return PTR_ERR(plane_state);
 519
 520        if (property == crtc->primary->rotation_property)
 521                plane_state->rotation = val;
 522        else if (property == priv->zorder_prop)
 523                plane_state->zpos = val;
 524        else
 525                return -EINVAL;
 526
 527        return 0;
 528}
 529
 530static int omap_crtc_atomic_get_property(struct drm_crtc *crtc,
 531                                         const struct drm_crtc_state *state,
 532                                         struct drm_property *property,
 533                                         u64 *val)
 534{
 535        struct omap_drm_private *priv = crtc->dev->dev_private;
 536        struct omap_crtc_state *omap_state = to_omap_crtc_state(state);
 537
 538        if (property == crtc->primary->rotation_property)
 539                *val = omap_state->rotation;
 540        else if (property == priv->zorder_prop)
 541                *val = omap_state->zpos;
 542        else
 543                return -EINVAL;
 544
 545        return 0;
 546}
 547
 548static void omap_crtc_reset(struct drm_crtc *crtc)
 549{
 550        if (crtc->state)
 551                __drm_atomic_helper_crtc_destroy_state(crtc->state);
 552
 553        kfree(crtc->state);
 554        crtc->state = kzalloc(sizeof(struct omap_crtc_state), GFP_KERNEL);
 555
 556        if (crtc->state)
 557                crtc->state->crtc = crtc;
 558}
 559
 560static struct drm_crtc_state *
 561omap_crtc_duplicate_state(struct drm_crtc *crtc)
 562{
 563        struct omap_crtc_state *state, *current_state;
 564
 565        if (WARN_ON(!crtc->state))
 566                return NULL;
 567
 568        current_state = to_omap_crtc_state(crtc->state);
 569
 570        state = kmalloc(sizeof(*state), GFP_KERNEL);
 571        if (!state)
 572                return NULL;
 573
 574        __drm_atomic_helper_crtc_duplicate_state(crtc, &state->base);
 575
 576        state->zpos = current_state->zpos;
 577        state->rotation = current_state->rotation;
 578
 579        return &state->base;
 580}
 581
 582static const struct drm_crtc_funcs omap_crtc_funcs = {
 583        .reset = omap_crtc_reset,
 584        .set_config = drm_atomic_helper_set_config,
 585        .destroy = omap_crtc_destroy,
 586        .page_flip = drm_atomic_helper_page_flip,
 587        .gamma_set = drm_atomic_helper_legacy_gamma_set,
 588        .atomic_duplicate_state = omap_crtc_duplicate_state,
 589        .atomic_destroy_state = drm_atomic_helper_crtc_destroy_state,
 590        .atomic_set_property = omap_crtc_atomic_set_property,
 591        .atomic_get_property = omap_crtc_atomic_get_property,
 592        .enable_vblank = omap_irq_enable_vblank,
 593        .disable_vblank = omap_irq_disable_vblank,
 594};
 595
 596static const struct drm_crtc_helper_funcs omap_crtc_helper_funcs = {
 597        .mode_set_nofb = omap_crtc_mode_set_nofb,
 598        .atomic_check = omap_crtc_atomic_check,
 599        .atomic_begin = omap_crtc_atomic_begin,
 600        .atomic_flush = omap_crtc_atomic_flush,
 601        .atomic_enable = omap_crtc_atomic_enable,
 602        .atomic_disable = omap_crtc_atomic_disable,
 603        .mode_valid = omap_crtc_mode_valid,
 604};
 605
 606/* -----------------------------------------------------------------------------
 607 * Init and Cleanup
 608 */
 609
 610static const char *channel_names[] = {
 611        [OMAP_DSS_CHANNEL_LCD] = "lcd",
 612        [OMAP_DSS_CHANNEL_DIGIT] = "tv",
 613        [OMAP_DSS_CHANNEL_LCD2] = "lcd2",
 614        [OMAP_DSS_CHANNEL_LCD3] = "lcd3",
 615};
 616
 617void omap_crtc_pre_init(struct omap_drm_private *priv)
 618{
 619        dss_install_mgr_ops(priv->dss, &mgr_ops, priv);
 620}
 621
 622void omap_crtc_pre_uninit(struct omap_drm_private *priv)
 623{
 624        dss_uninstall_mgr_ops(priv->dss);
 625}
 626
 627/* initialize crtc */
 628struct drm_crtc *omap_crtc_init(struct drm_device *dev,
 629                                struct omap_drm_pipeline *pipe,
 630                                struct drm_plane *plane)
 631{
 632        struct omap_drm_private *priv = dev->dev_private;
 633        struct drm_crtc *crtc = NULL;
 634        struct omap_crtc *omap_crtc;
 635        enum omap_channel channel;
 636        int ret;
 637
 638        channel = pipe->output->dispc_channel;
 639
 640        DBG("%s", channel_names[channel]);
 641
 642        omap_crtc = kzalloc(sizeof(*omap_crtc), GFP_KERNEL);
 643        if (!omap_crtc)
 644                return ERR_PTR(-ENOMEM);
 645
 646        crtc = &omap_crtc->base;
 647
 648        init_waitqueue_head(&omap_crtc->pending_wait);
 649
 650        omap_crtc->pipe = pipe;
 651        omap_crtc->channel = channel;
 652        omap_crtc->name = channel_names[channel];
 653
 654        ret = drm_crtc_init_with_planes(dev, crtc, plane, NULL,
 655                                        &omap_crtc_funcs, NULL);
 656        if (ret < 0) {
 657                dev_err(dev->dev, "%s(): could not init crtc for: %s\n",
 658                        __func__, pipe->output->name);
 659                kfree(omap_crtc);
 660                return ERR_PTR(ret);
 661        }
 662
 663        drm_crtc_helper_add(crtc, &omap_crtc_helper_funcs);
 664
 665        /* The dispc API adapts to what ever size, but the HW supports
 666         * 256 element gamma table for LCDs and 1024 element table for
 667         * OMAP_DSS_CHANNEL_DIGIT. X server assumes 256 element gamma
 668         * tables so lets use that. Size of HW gamma table can be
 669         * extracted with dispc_mgr_gamma_size(). If it returns 0
 670         * gamma table is not supprted.
 671         */
 672        if (priv->dispc_ops->mgr_gamma_size(priv->dispc, channel)) {
 673                unsigned int gamma_lut_size = 256;
 674
 675                drm_crtc_enable_color_mgmt(crtc, 0, false, gamma_lut_size);
 676                drm_mode_crtc_set_gamma_size(crtc, gamma_lut_size);
 677        }
 678
 679        omap_plane_install_properties(crtc->primary, &crtc->base);
 680
 681        return crtc;
 682}
 683