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