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->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 394 /* Check for bandwidth limit */ 395 if (priv->max_bandwidth) { 396 /* 397 * Estimation for the bandwidth need of a given mode with one 398 * full screen plane: 399 * bandwidth = resolution * 32bpp * (pclk / (vtotal * htotal)) 400 * ^^ Refresh rate ^^ 401 * 402 * The interlaced mode is taken into account by using the 403 * pixelclock in the calculation. 404 * 405 * The equation is rearranged for 64bit arithmetic. 406 */ 407 uint64_t bandwidth = mode->clock * 1000; 408 unsigned int bpp = 4; 409 410 bandwidth = bandwidth * mode->hdisplay * mode->vdisplay * bpp; 411 bandwidth = div_u64(bandwidth, mode->htotal * mode->vtotal); 412 413 /* 414 * Reject modes which would need more bandwidth if used with one 415 * full resolution plane (most common use case). 416 */ 417 if (priv->max_bandwidth < bandwidth) 418 return MODE_BAD; 419 } 420 421 return MODE_OK; 422 } 423 424 static void omap_crtc_mode_set_nofb(struct drm_crtc *crtc) 425 { 426 struct omap_crtc *omap_crtc = to_omap_crtc(crtc); 427 struct drm_display_mode *mode = &crtc->state->adjusted_mode; 428 429 DBG("%s: set mode: " DRM_MODE_FMT, 430 omap_crtc->name, DRM_MODE_ARG(mode)); 431 432 drm_display_mode_to_videomode(mode, &omap_crtc->vm); 433 } 434 435 static int omap_crtc_atomic_check(struct drm_crtc *crtc, 436 struct drm_crtc_state *state) 437 { 438 struct drm_plane_state *pri_state; 439 440 if (state->color_mgmt_changed && state->gamma_lut) { 441 unsigned int length = state->gamma_lut->length / 442 sizeof(struct drm_color_lut); 443 444 if (length < 2) 445 return -EINVAL; 446 } 447 448 pri_state = drm_atomic_get_new_plane_state(state->state, crtc->primary); 449 if (pri_state) { 450 struct omap_crtc_state *omap_crtc_state = 451 to_omap_crtc_state(state); 452 453 /* Mirror new values for zpos and rotation in omap_crtc_state */ 454 omap_crtc_state->zpos = pri_state->zpos; 455 omap_crtc_state->rotation = pri_state->rotation; 456 } 457 458 return 0; 459 } 460 461 static void omap_crtc_atomic_begin(struct drm_crtc *crtc, 462 struct drm_crtc_state *old_crtc_state) 463 { 464 } 465 466 static void omap_crtc_atomic_flush(struct drm_crtc *crtc, 467 struct drm_crtc_state *old_crtc_state) 468 { 469 struct omap_drm_private *priv = crtc->dev->dev_private; 470 struct omap_crtc *omap_crtc = to_omap_crtc(crtc); 471 int ret; 472 473 if (crtc->state->color_mgmt_changed) { 474 struct drm_color_lut *lut = NULL; 475 unsigned int length = 0; 476 477 if (crtc->state->gamma_lut) { 478 lut = (struct drm_color_lut *) 479 crtc->state->gamma_lut->data; 480 length = crtc->state->gamma_lut->length / 481 sizeof(*lut); 482 } 483 priv->dispc_ops->mgr_set_gamma(priv->dispc, omap_crtc->channel, 484 lut, length); 485 } 486 487 omap_crtc_write_crtc_properties(crtc); 488 489 /* Only flush the CRTC if it is currently enabled. */ 490 if (!omap_crtc->enabled) 491 return; 492 493 DBG("%s: GO", omap_crtc->name); 494 495 ret = drm_crtc_vblank_get(crtc); 496 WARN_ON(ret != 0); 497 498 spin_lock_irq(&crtc->dev->event_lock); 499 priv->dispc_ops->mgr_go(priv->dispc, omap_crtc->channel); 500 omap_crtc_arm_event(crtc); 501 spin_unlock_irq(&crtc->dev->event_lock); 502 } 503 504 static int omap_crtc_atomic_set_property(struct drm_crtc *crtc, 505 struct drm_crtc_state *state, 506 struct drm_property *property, 507 u64 val) 508 { 509 struct omap_drm_private *priv = crtc->dev->dev_private; 510 struct drm_plane_state *plane_state; 511 512 /* 513 * Delegate property set to the primary plane. Get the plane state and 514 * set the property directly, the shadow copy will be assigned in the 515 * omap_crtc_atomic_check callback. This way updates to plane state will 516 * always be mirrored in the crtc state correctly. 517 */ 518 plane_state = drm_atomic_get_plane_state(state->state, crtc->primary); 519 if (IS_ERR(plane_state)) 520 return PTR_ERR(plane_state); 521 522 if (property == crtc->primary->rotation_property) 523 plane_state->rotation = val; 524 else if (property == priv->zorder_prop) 525 plane_state->zpos = val; 526 else 527 return -EINVAL; 528 529 return 0; 530 } 531 532 static int omap_crtc_atomic_get_property(struct drm_crtc *crtc, 533 const struct drm_crtc_state *state, 534 struct drm_property *property, 535 u64 *val) 536 { 537 struct omap_drm_private *priv = crtc->dev->dev_private; 538 struct omap_crtc_state *omap_state = to_omap_crtc_state(state); 539 540 if (property == crtc->primary->rotation_property) 541 *val = omap_state->rotation; 542 else if (property == priv->zorder_prop) 543 *val = omap_state->zpos; 544 else 545 return -EINVAL; 546 547 return 0; 548 } 549 550 static void omap_crtc_reset(struct drm_crtc *crtc) 551 { 552 if (crtc->state) 553 __drm_atomic_helper_crtc_destroy_state(crtc->state); 554 555 kfree(crtc->state); 556 crtc->state = kzalloc(sizeof(struct omap_crtc_state), GFP_KERNEL); 557 558 if (crtc->state) 559 crtc->state->crtc = crtc; 560 } 561 562 static struct drm_crtc_state * 563 omap_crtc_duplicate_state(struct drm_crtc *crtc) 564 { 565 struct omap_crtc_state *state, *current_state; 566 567 if (WARN_ON(!crtc->state)) 568 return NULL; 569 570 current_state = to_omap_crtc_state(crtc->state); 571 572 state = kmalloc(sizeof(*state), GFP_KERNEL); 573 if (!state) 574 return NULL; 575 576 __drm_atomic_helper_crtc_duplicate_state(crtc, &state->base); 577 578 state->zpos = current_state->zpos; 579 state->rotation = current_state->rotation; 580 581 return &state->base; 582 } 583 584 static const struct drm_crtc_funcs omap_crtc_funcs = { 585 .reset = omap_crtc_reset, 586 .set_config = drm_atomic_helper_set_config, 587 .destroy = omap_crtc_destroy, 588 .page_flip = drm_atomic_helper_page_flip, 589 .gamma_set = drm_atomic_helper_legacy_gamma_set, 590 .atomic_duplicate_state = omap_crtc_duplicate_state, 591 .atomic_destroy_state = drm_atomic_helper_crtc_destroy_state, 592 .atomic_set_property = omap_crtc_atomic_set_property, 593 .atomic_get_property = omap_crtc_atomic_get_property, 594 .enable_vblank = omap_irq_enable_vblank, 595 .disable_vblank = omap_irq_disable_vblank, 596 }; 597 598 static const struct drm_crtc_helper_funcs omap_crtc_helper_funcs = { 599 .mode_set_nofb = omap_crtc_mode_set_nofb, 600 .atomic_check = omap_crtc_atomic_check, 601 .atomic_begin = omap_crtc_atomic_begin, 602 .atomic_flush = omap_crtc_atomic_flush, 603 .atomic_enable = omap_crtc_atomic_enable, 604 .atomic_disable = omap_crtc_atomic_disable, 605 .mode_valid = omap_crtc_mode_valid, 606 }; 607 608 /* ----------------------------------------------------------------------------- 609 * Init and Cleanup 610 */ 611 612 static const char *channel_names[] = { 613 [OMAP_DSS_CHANNEL_LCD] = "lcd", 614 [OMAP_DSS_CHANNEL_DIGIT] = "tv", 615 [OMAP_DSS_CHANNEL_LCD2] = "lcd2", 616 [OMAP_DSS_CHANNEL_LCD3] = "lcd3", 617 }; 618 619 void omap_crtc_pre_init(struct omap_drm_private *priv) 620 { 621 dss_install_mgr_ops(priv->dss, &mgr_ops, priv); 622 } 623 624 void omap_crtc_pre_uninit(struct omap_drm_private *priv) 625 { 626 dss_uninstall_mgr_ops(priv->dss); 627 } 628 629 /* initialize crtc */ 630 struct drm_crtc *omap_crtc_init(struct drm_device *dev, 631 struct omap_drm_pipeline *pipe, 632 struct drm_plane *plane) 633 { 634 struct omap_drm_private *priv = dev->dev_private; 635 struct drm_crtc *crtc = NULL; 636 struct omap_crtc *omap_crtc; 637 enum omap_channel channel; 638 int ret; 639 640 channel = pipe->output->dispc_channel; 641 642 DBG("%s", channel_names[channel]); 643 644 omap_crtc = kzalloc(sizeof(*omap_crtc), GFP_KERNEL); 645 if (!omap_crtc) 646 return ERR_PTR(-ENOMEM); 647 648 crtc = &omap_crtc->base; 649 650 init_waitqueue_head(&omap_crtc->pending_wait); 651 652 omap_crtc->pipe = pipe; 653 omap_crtc->channel = channel; 654 omap_crtc->name = channel_names[channel]; 655 656 ret = drm_crtc_init_with_planes(dev, crtc, plane, NULL, 657 &omap_crtc_funcs, NULL); 658 if (ret < 0) { 659 dev_err(dev->dev, "%s(): could not init crtc for: %s\n", 660 __func__, pipe->display->name); 661 kfree(omap_crtc); 662 return ERR_PTR(ret); 663 } 664 665 drm_crtc_helper_add(crtc, &omap_crtc_helper_funcs); 666 667 /* The dispc API adapts to what ever size, but the HW supports 668 * 256 element gamma table for LCDs and 1024 element table for 669 * OMAP_DSS_CHANNEL_DIGIT. X server assumes 256 element gamma 670 * tables so lets use that. Size of HW gamma table can be 671 * extracted with dispc_mgr_gamma_size(). If it returns 0 672 * gamma table is not supprted. 673 */ 674 if (priv->dispc_ops->mgr_gamma_size(priv->dispc, channel)) { 675 unsigned int gamma_lut_size = 256; 676 677 drm_crtc_enable_color_mgmt(crtc, 0, false, gamma_lut_size); 678 drm_mode_crtc_set_gamma_size(crtc, gamma_lut_size); 679 } 680 681 omap_plane_install_properties(crtc->primary, &crtc->base); 682 683 return crtc; 684 } 685