1 /* 2 * drivers/gpu/drm/omapdrm/omap_crtc.c 3 * 4 * Copyright (C) 2011 Texas Instruments 5 * Author: Rob Clark <rob@ti.com> 6 * 7 * This program is free software; you can redistribute it and/or modify it 8 * under the terms of the GNU General Public License version 2 as published by 9 * the Free Software Foundation. 10 * 11 * This program is distributed in the hope that it will be useful, but WITHOUT 12 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 13 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for 14 * more details. 15 * 16 * You should have received a copy of the GNU General Public License along with 17 * this program. If not, see <http://www.gnu.org/licenses/>. 18 */ 19 20 #include <drm/drm_atomic.h> 21 #include <drm/drm_atomic_helper.h> 22 #include <drm/drm_crtc.h> 23 #include <drm/drm_crtc_helper.h> 24 #include <drm/drm_mode.h> 25 #include <drm/drm_plane_helper.h> 26 27 #include "omap_drv.h" 28 29 #define to_omap_crtc(x) container_of(x, struct omap_crtc, base) 30 31 struct omap_crtc { 32 struct drm_crtc base; 33 34 const char *name; 35 enum omap_channel channel; 36 37 struct videomode vm; 38 39 bool ignore_digit_sync_lost; 40 41 bool enabled; 42 bool pending; 43 wait_queue_head_t pending_wait; 44 struct drm_pending_vblank_event *event; 45 }; 46 47 /* ----------------------------------------------------------------------------- 48 * Helper Functions 49 */ 50 51 struct videomode *omap_crtc_timings(struct drm_crtc *crtc) 52 { 53 struct omap_crtc *omap_crtc = to_omap_crtc(crtc); 54 return &omap_crtc->vm; 55 } 56 57 enum omap_channel omap_crtc_channel(struct drm_crtc *crtc) 58 { 59 struct omap_crtc *omap_crtc = to_omap_crtc(crtc); 60 return omap_crtc->channel; 61 } 62 63 static bool omap_crtc_is_pending(struct drm_crtc *crtc) 64 { 65 struct omap_crtc *omap_crtc = to_omap_crtc(crtc); 66 unsigned long flags; 67 bool pending; 68 69 spin_lock_irqsave(&crtc->dev->event_lock, flags); 70 pending = omap_crtc->pending; 71 spin_unlock_irqrestore(&crtc->dev->event_lock, flags); 72 73 return pending; 74 } 75 76 int omap_crtc_wait_pending(struct drm_crtc *crtc) 77 { 78 struct omap_crtc *omap_crtc = to_omap_crtc(crtc); 79 80 /* 81 * Timeout is set to a "sufficiently" high value, which should cover 82 * a single frame refresh even on slower displays. 83 */ 84 return wait_event_timeout(omap_crtc->pending_wait, 85 !omap_crtc_is_pending(crtc), 86 msecs_to_jiffies(250)); 87 } 88 89 /* ----------------------------------------------------------------------------- 90 * DSS Manager Functions 91 */ 92 93 /* 94 * Manager-ops, callbacks from output when they need to configure 95 * the upstream part of the video pipe. 96 * 97 * Most of these we can ignore until we add support for command-mode 98 * panels.. for video-mode the crtc-helpers already do an adequate 99 * job of sequencing the setup of the video pipe in the proper order 100 */ 101 102 /* ovl-mgr-id -> crtc */ 103 static struct omap_crtc *omap_crtcs[8]; 104 static struct omap_dss_device *omap_crtc_output[8]; 105 106 /* we can probably ignore these until we support command-mode panels: */ 107 static int omap_crtc_dss_connect(enum omap_channel channel, 108 struct omap_dss_device *dst) 109 { 110 if (omap_crtc_output[channel]) 111 return -EINVAL; 112 113 if ((dispc_mgr_get_supported_outputs(channel) & dst->id) == 0) 114 return -EINVAL; 115 116 omap_crtc_output[channel] = dst; 117 dst->dispc_channel_connected = true; 118 119 return 0; 120 } 121 122 static void omap_crtc_dss_disconnect(enum omap_channel channel, 123 struct omap_dss_device *dst) 124 { 125 omap_crtc_output[channel] = NULL; 126 dst->dispc_channel_connected = false; 127 } 128 129 static void omap_crtc_dss_start_update(enum omap_channel channel) 130 { 131 } 132 133 /* Called only from the encoder enable/disable and suspend/resume handlers. */ 134 static void omap_crtc_set_enabled(struct drm_crtc *crtc, bool enable) 135 { 136 struct drm_device *dev = crtc->dev; 137 struct omap_crtc *omap_crtc = to_omap_crtc(crtc); 138 enum omap_channel channel = omap_crtc->channel; 139 struct omap_irq_wait *wait; 140 u32 framedone_irq, vsync_irq; 141 int ret; 142 143 if (WARN_ON(omap_crtc->enabled == enable)) 144 return; 145 146 if (omap_crtc_output[channel]->output_type == OMAP_DISPLAY_TYPE_HDMI) { 147 dispc_mgr_enable(channel, enable); 148 omap_crtc->enabled = enable; 149 return; 150 } 151 152 if (omap_crtc->channel == OMAP_DSS_CHANNEL_DIGIT) { 153 /* 154 * Digit output produces some sync lost interrupts during the 155 * first frame when enabling, so we need to ignore those. 156 */ 157 omap_crtc->ignore_digit_sync_lost = true; 158 } 159 160 framedone_irq = dispc_mgr_get_framedone_irq(channel); 161 vsync_irq = dispc_mgr_get_vsync_irq(channel); 162 163 if (enable) { 164 wait = omap_irq_wait_init(dev, vsync_irq, 1); 165 } else { 166 /* 167 * When we disable the digit output, we need to wait for 168 * FRAMEDONE to know that DISPC has finished with the output. 169 * 170 * OMAP2/3 does not have FRAMEDONE irq for digit output, and in 171 * that case we need to use vsync interrupt, and wait for both 172 * even and odd frames. 173 */ 174 175 if (framedone_irq) 176 wait = omap_irq_wait_init(dev, framedone_irq, 1); 177 else 178 wait = omap_irq_wait_init(dev, vsync_irq, 2); 179 } 180 181 dispc_mgr_enable(channel, enable); 182 omap_crtc->enabled = enable; 183 184 ret = omap_irq_wait(dev, wait, msecs_to_jiffies(100)); 185 if (ret) { 186 dev_err(dev->dev, "%s: timeout waiting for %s\n", 187 omap_crtc->name, enable ? "enable" : "disable"); 188 } 189 190 if (omap_crtc->channel == OMAP_DSS_CHANNEL_DIGIT) { 191 omap_crtc->ignore_digit_sync_lost = false; 192 /* make sure the irq handler sees the value above */ 193 mb(); 194 } 195 } 196 197 198 static int omap_crtc_dss_enable(enum omap_channel channel) 199 { 200 struct omap_crtc *omap_crtc = omap_crtcs[channel]; 201 struct omap_overlay_manager_info info; 202 203 memset(&info, 0, sizeof(info)); 204 info.default_color = 0x00000000; 205 info.trans_key = 0x00000000; 206 info.trans_key_type = OMAP_DSS_COLOR_KEY_GFX_DST; 207 info.trans_enabled = false; 208 209 dispc_mgr_setup(omap_crtc->channel, &info); 210 dispc_mgr_set_timings(omap_crtc->channel, 211 &omap_crtc->vm); 212 omap_crtc_set_enabled(&omap_crtc->base, true); 213 214 return 0; 215 } 216 217 static void omap_crtc_dss_disable(enum omap_channel channel) 218 { 219 struct omap_crtc *omap_crtc = omap_crtcs[channel]; 220 221 omap_crtc_set_enabled(&omap_crtc->base, false); 222 } 223 224 static void omap_crtc_dss_set_timings(enum omap_channel channel, 225 const struct videomode *vm) 226 { 227 struct omap_crtc *omap_crtc = omap_crtcs[channel]; 228 DBG("%s", omap_crtc->name); 229 omap_crtc->vm = *vm; 230 } 231 232 static void omap_crtc_dss_set_lcd_config(enum omap_channel channel, 233 const struct dss_lcd_mgr_config *config) 234 { 235 struct omap_crtc *omap_crtc = omap_crtcs[channel]; 236 DBG("%s", omap_crtc->name); 237 dispc_mgr_set_lcd_config(omap_crtc->channel, config); 238 } 239 240 static int omap_crtc_dss_register_framedone( 241 enum omap_channel channel, 242 void (*handler)(void *), void *data) 243 { 244 return 0; 245 } 246 247 static void omap_crtc_dss_unregister_framedone( 248 enum omap_channel channel, 249 void (*handler)(void *), void *data) 250 { 251 } 252 253 static const struct dss_mgr_ops mgr_ops = { 254 .connect = omap_crtc_dss_connect, 255 .disconnect = omap_crtc_dss_disconnect, 256 .start_update = omap_crtc_dss_start_update, 257 .enable = omap_crtc_dss_enable, 258 .disable = omap_crtc_dss_disable, 259 .set_timings = omap_crtc_dss_set_timings, 260 .set_lcd_config = omap_crtc_dss_set_lcd_config, 261 .register_framedone_handler = omap_crtc_dss_register_framedone, 262 .unregister_framedone_handler = omap_crtc_dss_unregister_framedone, 263 }; 264 265 /* ----------------------------------------------------------------------------- 266 * Setup, Flush and Page Flip 267 */ 268 269 void omap_crtc_error_irq(struct drm_crtc *crtc, uint32_t irqstatus) 270 { 271 struct omap_crtc *omap_crtc = to_omap_crtc(crtc); 272 273 if (omap_crtc->ignore_digit_sync_lost) { 274 irqstatus &= ~DISPC_IRQ_SYNC_LOST_DIGIT; 275 if (!irqstatus) 276 return; 277 } 278 279 DRM_ERROR_RATELIMITED("%s: errors: %08x\n", omap_crtc->name, irqstatus); 280 } 281 282 void omap_crtc_vblank_irq(struct drm_crtc *crtc) 283 { 284 struct omap_crtc *omap_crtc = to_omap_crtc(crtc); 285 bool pending; 286 287 spin_lock(&crtc->dev->event_lock); 288 /* 289 * If the dispc is busy we're racing the flush operation. Try again on 290 * the next vblank interrupt. 291 */ 292 if (dispc_mgr_go_busy(omap_crtc->channel)) { 293 spin_unlock(&crtc->dev->event_lock); 294 return; 295 } 296 297 /* Send the vblank event if one has been requested. */ 298 if (omap_crtc->event) { 299 drm_crtc_send_vblank_event(crtc, omap_crtc->event); 300 omap_crtc->event = NULL; 301 } 302 303 pending = omap_crtc->pending; 304 omap_crtc->pending = false; 305 spin_unlock(&crtc->dev->event_lock); 306 307 if (pending) 308 drm_crtc_vblank_put(crtc); 309 310 /* Wake up omap_atomic_complete. */ 311 wake_up(&omap_crtc->pending_wait); 312 313 DBG("%s: apply done", omap_crtc->name); 314 } 315 316 /* ----------------------------------------------------------------------------- 317 * CRTC Functions 318 */ 319 320 static void omap_crtc_destroy(struct drm_crtc *crtc) 321 { 322 struct omap_crtc *omap_crtc = to_omap_crtc(crtc); 323 324 DBG("%s", omap_crtc->name); 325 326 drm_crtc_cleanup(crtc); 327 328 kfree(omap_crtc); 329 } 330 331 static void omap_crtc_enable(struct drm_crtc *crtc) 332 { 333 struct omap_crtc *omap_crtc = to_omap_crtc(crtc); 334 int ret; 335 336 DBG("%s", omap_crtc->name); 337 338 spin_lock_irq(&crtc->dev->event_lock); 339 drm_crtc_vblank_on(crtc); 340 ret = drm_crtc_vblank_get(crtc); 341 WARN_ON(ret != 0); 342 343 WARN_ON(omap_crtc->pending); 344 omap_crtc->pending = true; 345 spin_unlock_irq(&crtc->dev->event_lock); 346 } 347 348 static void omap_crtc_disable(struct drm_crtc *crtc) 349 { 350 struct omap_crtc *omap_crtc = to_omap_crtc(crtc); 351 352 DBG("%s", omap_crtc->name); 353 354 drm_crtc_vblank_off(crtc); 355 } 356 357 static void omap_crtc_mode_set_nofb(struct drm_crtc *crtc) 358 { 359 struct omap_crtc *omap_crtc = to_omap_crtc(crtc); 360 struct drm_display_mode *mode = &crtc->state->adjusted_mode; 361 362 DBG("%s: set mode: %d:\"%s\" %d %d %d %d %d %d %d %d %d %d 0x%x 0x%x", 363 omap_crtc->name, mode->base.id, mode->name, 364 mode->vrefresh, mode->clock, 365 mode->hdisplay, mode->hsync_start, mode->hsync_end, mode->htotal, 366 mode->vdisplay, mode->vsync_start, mode->vsync_end, mode->vtotal, 367 mode->type, mode->flags); 368 369 drm_display_mode_to_videomode(mode, &omap_crtc->vm); 370 omap_crtc->vm.flags |= DISPLAY_FLAGS_DE_HIGH | 371 DISPLAY_FLAGS_PIXDATA_POSEDGE | 372 DISPLAY_FLAGS_SYNC_NEGEDGE; 373 } 374 375 static int omap_crtc_atomic_check(struct drm_crtc *crtc, 376 struct drm_crtc_state *state) 377 { 378 if (state->color_mgmt_changed && state->gamma_lut) { 379 uint length = state->gamma_lut->length / 380 sizeof(struct drm_color_lut); 381 382 if (length < 2) 383 return -EINVAL; 384 } 385 386 return 0; 387 } 388 389 static void omap_crtc_atomic_begin(struct drm_crtc *crtc, 390 struct drm_crtc_state *old_crtc_state) 391 { 392 } 393 394 static void omap_crtc_atomic_flush(struct drm_crtc *crtc, 395 struct drm_crtc_state *old_crtc_state) 396 { 397 struct omap_crtc *omap_crtc = to_omap_crtc(crtc); 398 int ret; 399 400 if (crtc->state->color_mgmt_changed) { 401 struct drm_color_lut *lut = NULL; 402 uint length = 0; 403 404 if (crtc->state->gamma_lut) { 405 lut = (struct drm_color_lut *) 406 crtc->state->gamma_lut->data; 407 length = crtc->state->gamma_lut->length / 408 sizeof(*lut); 409 } 410 dispc_mgr_set_gamma(omap_crtc->channel, lut, length); 411 } 412 413 /* Only flush the CRTC if it is currently enabled. */ 414 if (!omap_crtc->enabled) 415 return; 416 417 DBG("%s: GO", omap_crtc->name); 418 419 ret = drm_crtc_vblank_get(crtc); 420 WARN_ON(ret != 0); 421 422 spin_lock_irq(&crtc->dev->event_lock); 423 dispc_mgr_go(omap_crtc->channel); 424 425 WARN_ON(omap_crtc->pending); 426 omap_crtc->pending = true; 427 428 if (crtc->state->event) 429 omap_crtc->event = crtc->state->event; 430 spin_unlock_irq(&crtc->dev->event_lock); 431 } 432 433 static bool omap_crtc_is_plane_prop(struct drm_crtc *crtc, 434 struct drm_property *property) 435 { 436 struct drm_device *dev = crtc->dev; 437 struct omap_drm_private *priv = dev->dev_private; 438 439 return property == priv->zorder_prop || 440 property == crtc->primary->rotation_property; 441 } 442 443 static int omap_crtc_atomic_set_property(struct drm_crtc *crtc, 444 struct drm_crtc_state *state, 445 struct drm_property *property, 446 uint64_t val) 447 { 448 if (omap_crtc_is_plane_prop(crtc, property)) { 449 struct drm_plane_state *plane_state; 450 struct drm_plane *plane = crtc->primary; 451 452 /* 453 * Delegate property set to the primary plane. Get the plane 454 * state and set the property directly. 455 */ 456 457 plane_state = drm_atomic_get_plane_state(state->state, plane); 458 if (IS_ERR(plane_state)) 459 return PTR_ERR(plane_state); 460 461 return drm_atomic_plane_set_property(plane, plane_state, 462 property, val); 463 } 464 465 return -EINVAL; 466 } 467 468 static int omap_crtc_atomic_get_property(struct drm_crtc *crtc, 469 const struct drm_crtc_state *state, 470 struct drm_property *property, 471 uint64_t *val) 472 { 473 if (omap_crtc_is_plane_prop(crtc, property)) { 474 /* 475 * Delegate property get to the primary plane. The 476 * drm_atomic_plane_get_property() function isn't exported, but 477 * can be called through drm_object_property_get_value() as that 478 * will call drm_atomic_get_property() for atomic drivers. 479 */ 480 return drm_object_property_get_value(&crtc->primary->base, 481 property, val); 482 } 483 484 return -EINVAL; 485 } 486 487 static const struct drm_crtc_funcs omap_crtc_funcs = { 488 .reset = drm_atomic_helper_crtc_reset, 489 .set_config = drm_atomic_helper_set_config, 490 .destroy = omap_crtc_destroy, 491 .page_flip = drm_atomic_helper_page_flip, 492 .gamma_set = drm_atomic_helper_legacy_gamma_set, 493 .set_property = drm_atomic_helper_crtc_set_property, 494 .atomic_duplicate_state = drm_atomic_helper_crtc_duplicate_state, 495 .atomic_destroy_state = drm_atomic_helper_crtc_destroy_state, 496 .atomic_set_property = omap_crtc_atomic_set_property, 497 .atomic_get_property = omap_crtc_atomic_get_property, 498 }; 499 500 static const struct drm_crtc_helper_funcs omap_crtc_helper_funcs = { 501 .mode_set_nofb = omap_crtc_mode_set_nofb, 502 .disable = omap_crtc_disable, 503 .enable = omap_crtc_enable, 504 .atomic_check = omap_crtc_atomic_check, 505 .atomic_begin = omap_crtc_atomic_begin, 506 .atomic_flush = omap_crtc_atomic_flush, 507 }; 508 509 /* ----------------------------------------------------------------------------- 510 * Init and Cleanup 511 */ 512 513 static const char *channel_names[] = { 514 [OMAP_DSS_CHANNEL_LCD] = "lcd", 515 [OMAP_DSS_CHANNEL_DIGIT] = "tv", 516 [OMAP_DSS_CHANNEL_LCD2] = "lcd2", 517 [OMAP_DSS_CHANNEL_LCD3] = "lcd3", 518 }; 519 520 void omap_crtc_pre_init(void) 521 { 522 dss_install_mgr_ops(&mgr_ops); 523 } 524 525 void omap_crtc_pre_uninit(void) 526 { 527 dss_uninstall_mgr_ops(); 528 } 529 530 /* initialize crtc */ 531 struct drm_crtc *omap_crtc_init(struct drm_device *dev, 532 struct drm_plane *plane, enum omap_channel channel, int id) 533 { 534 struct drm_crtc *crtc = NULL; 535 struct omap_crtc *omap_crtc; 536 int ret; 537 538 DBG("%s", channel_names[channel]); 539 540 omap_crtc = kzalloc(sizeof(*omap_crtc), GFP_KERNEL); 541 if (!omap_crtc) 542 return NULL; 543 544 crtc = &omap_crtc->base; 545 546 init_waitqueue_head(&omap_crtc->pending_wait); 547 548 omap_crtc->channel = channel; 549 omap_crtc->name = channel_names[channel]; 550 551 ret = drm_crtc_init_with_planes(dev, crtc, plane, NULL, 552 &omap_crtc_funcs, NULL); 553 if (ret < 0) { 554 kfree(omap_crtc); 555 return NULL; 556 } 557 558 drm_crtc_helper_add(crtc, &omap_crtc_helper_funcs); 559 560 /* The dispc API adapts to what ever size, but the HW supports 561 * 256 element gamma table for LCDs and 1024 element table for 562 * OMAP_DSS_CHANNEL_DIGIT. X server assumes 256 element gamma 563 * tables so lets use that. Size of HW gamma table can be 564 * extracted with dispc_mgr_gamma_size(). If it returns 0 565 * gamma table is not supprted. 566 */ 567 if (dispc_mgr_gamma_size(channel)) { 568 uint gamma_lut_size = 256; 569 570 drm_crtc_enable_color_mgmt(crtc, 0, false, gamma_lut_size); 571 drm_mode_crtc_set_gamma_size(crtc, gamma_lut_size); 572 } 573 574 omap_plane_install_properties(crtc->primary, &crtc->base); 575 576 omap_crtcs[channel] = omap_crtc; 577 578 return crtc; 579 } 580