2 * drivers/gpu/drm/omapdrm/omap_crtc.c
4 * Copyright (C) 2011 Texas Instruments
5 * Author: Rob Clark <rob@ti.com>
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.
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
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/>.
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>
29 #define to_omap_crtc_state(x) container_of(x, struct omap_crtc_state, base)
31 struct omap_crtc_state
{
33 struct drm_crtc_state base
;
34 /* Shadow values for legacy userspace support. */
35 unsigned int rotation
;
39 #define to_omap_crtc(x) container_of(x, struct omap_crtc, base)
45 enum omap_channel channel
;
49 bool ignore_digit_sync_lost
;
53 wait_queue_head_t pending_wait
;
54 struct drm_pending_vblank_event
*event
;
57 /* -----------------------------------------------------------------------------
61 struct videomode
*omap_crtc_timings(struct drm_crtc
*crtc
)
63 struct omap_crtc
*omap_crtc
= to_omap_crtc(crtc
);
64 return &omap_crtc
->vm
;
67 enum omap_channel
omap_crtc_channel(struct drm_crtc
*crtc
)
69 struct omap_crtc
*omap_crtc
= to_omap_crtc(crtc
);
70 return omap_crtc
->channel
;
73 static bool omap_crtc_is_pending(struct drm_crtc
*crtc
)
75 struct omap_crtc
*omap_crtc
= to_omap_crtc(crtc
);
79 spin_lock_irqsave(&crtc
->dev
->event_lock
, flags
);
80 pending
= omap_crtc
->pending
;
81 spin_unlock_irqrestore(&crtc
->dev
->event_lock
, flags
);
86 int omap_crtc_wait_pending(struct drm_crtc
*crtc
)
88 struct omap_crtc
*omap_crtc
= to_omap_crtc(crtc
);
91 * Timeout is set to a "sufficiently" high value, which should cover
92 * a single frame refresh even on slower displays.
94 return wait_event_timeout(omap_crtc
->pending_wait
,
95 !omap_crtc_is_pending(crtc
),
96 msecs_to_jiffies(250));
99 /* -----------------------------------------------------------------------------
100 * DSS Manager Functions
104 * Manager-ops, callbacks from output when they need to configure
105 * the upstream part of the video pipe.
107 * Most of these we can ignore until we add support for command-mode
108 * panels.. for video-mode the crtc-helpers already do an adequate
109 * job of sequencing the setup of the video pipe in the proper order
112 /* ovl-mgr-id -> crtc */
113 static struct omap_crtc
*omap_crtcs
[8];
114 static struct omap_dss_device
*omap_crtc_output
[8];
116 /* we can probably ignore these until we support command-mode panels: */
117 static int omap_crtc_dss_connect(enum omap_channel channel
,
118 struct omap_dss_device
*dst
)
120 const struct dispc_ops
*dispc_ops
= dispc_get_ops();
122 if (omap_crtc_output
[channel
])
125 if ((dispc_ops
->mgr_get_supported_outputs(channel
) & dst
->id
) == 0)
128 omap_crtc_output
[channel
] = dst
;
129 dst
->dispc_channel_connected
= true;
134 static void omap_crtc_dss_disconnect(enum omap_channel channel
,
135 struct omap_dss_device
*dst
)
137 omap_crtc_output
[channel
] = NULL
;
138 dst
->dispc_channel_connected
= false;
141 static void omap_crtc_dss_start_update(enum omap_channel channel
)
145 /* Called only from the encoder enable/disable and suspend/resume handlers. */
146 static void omap_crtc_set_enabled(struct drm_crtc
*crtc
, bool enable
)
148 struct drm_device
*dev
= crtc
->dev
;
149 struct omap_drm_private
*priv
= dev
->dev_private
;
150 struct omap_crtc
*omap_crtc
= to_omap_crtc(crtc
);
151 enum omap_channel channel
= omap_crtc
->channel
;
152 struct omap_irq_wait
*wait
;
153 u32 framedone_irq
, vsync_irq
;
156 if (WARN_ON(omap_crtc
->enabled
== enable
))
159 if (omap_crtc_output
[channel
]->output_type
== OMAP_DISPLAY_TYPE_HDMI
) {
160 priv
->dispc_ops
->mgr_enable(channel
, enable
);
161 omap_crtc
->enabled
= enable
;
165 if (omap_crtc
->channel
== OMAP_DSS_CHANNEL_DIGIT
) {
167 * Digit output produces some sync lost interrupts during the
168 * first frame when enabling, so we need to ignore those.
170 omap_crtc
->ignore_digit_sync_lost
= true;
173 framedone_irq
= priv
->dispc_ops
->mgr_get_framedone_irq(channel
);
174 vsync_irq
= priv
->dispc_ops
->mgr_get_vsync_irq(channel
);
177 wait
= omap_irq_wait_init(dev
, vsync_irq
, 1);
180 * When we disable the digit output, we need to wait for
181 * FRAMEDONE to know that DISPC has finished with the output.
183 * OMAP2/3 does not have FRAMEDONE irq for digit output, and in
184 * that case we need to use vsync interrupt, and wait for both
185 * even and odd frames.
189 wait
= omap_irq_wait_init(dev
, framedone_irq
, 1);
191 wait
= omap_irq_wait_init(dev
, vsync_irq
, 2);
194 priv
->dispc_ops
->mgr_enable(channel
, enable
);
195 omap_crtc
->enabled
= enable
;
197 ret
= omap_irq_wait(dev
, wait
, msecs_to_jiffies(100));
199 dev_err(dev
->dev
, "%s: timeout waiting for %s\n",
200 omap_crtc
->name
, enable
? "enable" : "disable");
203 if (omap_crtc
->channel
== OMAP_DSS_CHANNEL_DIGIT
) {
204 omap_crtc
->ignore_digit_sync_lost
= false;
205 /* make sure the irq handler sees the value above */
211 static int omap_crtc_dss_enable(enum omap_channel channel
)
213 struct omap_crtc
*omap_crtc
= omap_crtcs
[channel
];
214 struct omap_drm_private
*priv
= omap_crtc
->base
.dev
->dev_private
;
216 priv
->dispc_ops
->mgr_set_timings(omap_crtc
->channel
, &omap_crtc
->vm
);
217 omap_crtc_set_enabled(&omap_crtc
->base
, true);
222 static void omap_crtc_dss_disable(enum omap_channel channel
)
224 struct omap_crtc
*omap_crtc
= omap_crtcs
[channel
];
226 omap_crtc_set_enabled(&omap_crtc
->base
, false);
229 static void omap_crtc_dss_set_timings(enum omap_channel channel
,
230 const struct videomode
*vm
)
232 struct omap_crtc
*omap_crtc
= omap_crtcs
[channel
];
233 DBG("%s", omap_crtc
->name
);
237 static void omap_crtc_dss_set_lcd_config(enum omap_channel channel
,
238 const struct dss_lcd_mgr_config
*config
)
240 struct omap_crtc
*omap_crtc
= omap_crtcs
[channel
];
241 struct omap_drm_private
*priv
= omap_crtc
->base
.dev
->dev_private
;
243 DBG("%s", omap_crtc
->name
);
244 priv
->dispc_ops
->mgr_set_lcd_config(omap_crtc
->channel
, config
);
247 static int omap_crtc_dss_register_framedone(
248 enum omap_channel channel
,
249 void (*handler
)(void *), void *data
)
254 static void omap_crtc_dss_unregister_framedone(
255 enum omap_channel channel
,
256 void (*handler
)(void *), void *data
)
260 static const struct dss_mgr_ops mgr_ops
= {
261 .connect
= omap_crtc_dss_connect
,
262 .disconnect
= omap_crtc_dss_disconnect
,
263 .start_update
= omap_crtc_dss_start_update
,
264 .enable
= omap_crtc_dss_enable
,
265 .disable
= omap_crtc_dss_disable
,
266 .set_timings
= omap_crtc_dss_set_timings
,
267 .set_lcd_config
= omap_crtc_dss_set_lcd_config
,
268 .register_framedone_handler
= omap_crtc_dss_register_framedone
,
269 .unregister_framedone_handler
= omap_crtc_dss_unregister_framedone
,
272 /* -----------------------------------------------------------------------------
273 * Setup, Flush and Page Flip
276 void omap_crtc_error_irq(struct drm_crtc
*crtc
, uint32_t irqstatus
)
278 struct omap_crtc
*omap_crtc
= to_omap_crtc(crtc
);
280 if (omap_crtc
->ignore_digit_sync_lost
) {
281 irqstatus
&= ~DISPC_IRQ_SYNC_LOST_DIGIT
;
286 DRM_ERROR_RATELIMITED("%s: errors: %08x\n", omap_crtc
->name
, irqstatus
);
289 void omap_crtc_vblank_irq(struct drm_crtc
*crtc
)
291 struct omap_crtc
*omap_crtc
= to_omap_crtc(crtc
);
292 struct drm_device
*dev
= omap_crtc
->base
.dev
;
293 struct omap_drm_private
*priv
= dev
->dev_private
;
296 spin_lock(&crtc
->dev
->event_lock
);
298 * If the dispc is busy we're racing the flush operation. Try again on
299 * the next vblank interrupt.
301 if (priv
->dispc_ops
->mgr_go_busy(omap_crtc
->channel
)) {
302 spin_unlock(&crtc
->dev
->event_lock
);
306 /* Send the vblank event if one has been requested. */
307 if (omap_crtc
->event
) {
308 drm_crtc_send_vblank_event(crtc
, omap_crtc
->event
);
309 omap_crtc
->event
= NULL
;
312 pending
= omap_crtc
->pending
;
313 omap_crtc
->pending
= false;
314 spin_unlock(&crtc
->dev
->event_lock
);
317 drm_crtc_vblank_put(crtc
);
319 /* Wake up omap_atomic_complete. */
320 wake_up(&omap_crtc
->pending_wait
);
322 DBG("%s: apply done", omap_crtc
->name
);
325 static void omap_crtc_write_crtc_properties(struct drm_crtc
*crtc
)
327 struct omap_drm_private
*priv
= crtc
->dev
->dev_private
;
328 struct omap_crtc
*omap_crtc
= to_omap_crtc(crtc
);
329 struct omap_overlay_manager_info info
;
331 memset(&info
, 0, sizeof(info
));
333 info
.default_color
= 0x000000;
334 info
.trans_enabled
= false;
335 info
.partial_alpha_enabled
= false;
336 info
.cpr_enable
= false;
338 priv
->dispc_ops
->mgr_setup(omap_crtc
->channel
, &info
);
341 /* -----------------------------------------------------------------------------
345 static void omap_crtc_destroy(struct drm_crtc
*crtc
)
347 struct omap_crtc
*omap_crtc
= to_omap_crtc(crtc
);
349 DBG("%s", omap_crtc
->name
);
351 drm_crtc_cleanup(crtc
);
356 static void omap_crtc_arm_event(struct drm_crtc
*crtc
)
358 struct omap_crtc
*omap_crtc
= to_omap_crtc(crtc
);
360 WARN_ON(omap_crtc
->pending
);
361 omap_crtc
->pending
= true;
363 if (crtc
->state
->event
) {
364 omap_crtc
->event
= crtc
->state
->event
;
365 crtc
->state
->event
= NULL
;
369 static void omap_crtc_atomic_enable(struct drm_crtc
*crtc
,
370 struct drm_crtc_state
*old_state
)
372 struct omap_crtc
*omap_crtc
= to_omap_crtc(crtc
);
375 DBG("%s", omap_crtc
->name
);
377 spin_lock_irq(&crtc
->dev
->event_lock
);
378 drm_crtc_vblank_on(crtc
);
379 ret
= drm_crtc_vblank_get(crtc
);
382 omap_crtc_arm_event(crtc
);
383 spin_unlock_irq(&crtc
->dev
->event_lock
);
386 static void omap_crtc_atomic_disable(struct drm_crtc
*crtc
,
387 struct drm_crtc_state
*old_state
)
389 struct omap_crtc
*omap_crtc
= to_omap_crtc(crtc
);
391 DBG("%s", omap_crtc
->name
);
393 spin_lock_irq(&crtc
->dev
->event_lock
);
394 if (crtc
->state
->event
) {
395 drm_crtc_send_vblank_event(crtc
, crtc
->state
->event
);
396 crtc
->state
->event
= NULL
;
398 spin_unlock_irq(&crtc
->dev
->event_lock
);
400 drm_crtc_vblank_off(crtc
);
403 static void omap_crtc_mode_set_nofb(struct drm_crtc
*crtc
)
405 struct omap_crtc
*omap_crtc
= to_omap_crtc(crtc
);
406 struct drm_display_mode
*mode
= &crtc
->state
->adjusted_mode
;
407 struct omap_drm_private
*priv
= crtc
->dev
->dev_private
;
408 const u32 flags_mask
= DISPLAY_FLAGS_DE_HIGH
| DISPLAY_FLAGS_DE_LOW
|
409 DISPLAY_FLAGS_PIXDATA_POSEDGE
| DISPLAY_FLAGS_PIXDATA_NEGEDGE
|
410 DISPLAY_FLAGS_SYNC_POSEDGE
| DISPLAY_FLAGS_SYNC_NEGEDGE
;
413 DBG("%s: set mode: %d:\"%s\" %d %d %d %d %d %d %d %d %d %d 0x%x 0x%x",
414 omap_crtc
->name
, mode
->base
.id
, mode
->name
,
415 mode
->vrefresh
, mode
->clock
,
416 mode
->hdisplay
, mode
->hsync_start
, mode
->hsync_end
, mode
->htotal
,
417 mode
->vdisplay
, mode
->vsync_start
, mode
->vsync_end
, mode
->vtotal
,
418 mode
->type
, mode
->flags
);
420 drm_display_mode_to_videomode(mode
, &omap_crtc
->vm
);
423 * HACK: This fixes the vm flags.
424 * struct drm_display_mode does not contain the VSYNC/HSYNC/DE flags
425 * and they get lost when converting back and forth between
426 * struct drm_display_mode and struct videomode. The hack below
427 * goes and fetches the missing flags from the panel drivers.
429 * Correct solution would be to use DRM's bus-flags, but that's not
430 * easily possible before the omapdrm's panel/encoder driver model
431 * has been changed to the DRM model.
434 for (i
= 0; i
< priv
->num_encoders
; ++i
) {
435 struct drm_encoder
*encoder
= priv
->encoders
[i
];
437 if (encoder
->crtc
== crtc
) {
438 struct omap_dss_device
*dssdev
;
440 dssdev
= omap_encoder_get_dssdev(encoder
);
443 struct videomode vm
= {0};
445 dssdev
->driver
->get_timings(dssdev
, &vm
);
447 omap_crtc
->vm
.flags
|= vm
.flags
& flags_mask
;
455 static int omap_crtc_atomic_check(struct drm_crtc
*crtc
,
456 struct drm_crtc_state
*state
)
458 struct drm_plane_state
*pri_state
;
460 if (state
->color_mgmt_changed
&& state
->gamma_lut
) {
461 uint length
= state
->gamma_lut
->length
/
462 sizeof(struct drm_color_lut
);
468 pri_state
= drm_atomic_get_new_plane_state(state
->state
, crtc
->primary
);
470 struct omap_crtc_state
*omap_crtc_state
=
471 to_omap_crtc_state(state
);
473 /* Mirror new values for zpos and rotation in omap_crtc_state */
474 omap_crtc_state
->zpos
= pri_state
->zpos
;
475 omap_crtc_state
->rotation
= pri_state
->rotation
;
481 static void omap_crtc_atomic_begin(struct drm_crtc
*crtc
,
482 struct drm_crtc_state
*old_crtc_state
)
486 static void omap_crtc_atomic_flush(struct drm_crtc
*crtc
,
487 struct drm_crtc_state
*old_crtc_state
)
489 struct omap_drm_private
*priv
= crtc
->dev
->dev_private
;
490 struct omap_crtc
*omap_crtc
= to_omap_crtc(crtc
);
493 if (crtc
->state
->color_mgmt_changed
) {
494 struct drm_color_lut
*lut
= NULL
;
497 if (crtc
->state
->gamma_lut
) {
498 lut
= (struct drm_color_lut
*)
499 crtc
->state
->gamma_lut
->data
;
500 length
= crtc
->state
->gamma_lut
->length
/
503 priv
->dispc_ops
->mgr_set_gamma(omap_crtc
->channel
, lut
, length
);
506 omap_crtc_write_crtc_properties(crtc
);
508 /* Only flush the CRTC if it is currently enabled. */
509 if (!omap_crtc
->enabled
)
512 DBG("%s: GO", omap_crtc
->name
);
514 ret
= drm_crtc_vblank_get(crtc
);
517 spin_lock_irq(&crtc
->dev
->event_lock
);
518 priv
->dispc_ops
->mgr_go(omap_crtc
->channel
);
519 omap_crtc_arm_event(crtc
);
520 spin_unlock_irq(&crtc
->dev
->event_lock
);
523 static int omap_crtc_atomic_set_property(struct drm_crtc
*crtc
,
524 struct drm_crtc_state
*state
,
525 struct drm_property
*property
,
528 struct omap_drm_private
*priv
= crtc
->dev
->dev_private
;
529 struct drm_plane_state
*plane_state
;
532 * Delegate property set to the primary plane. Get the plane state and
533 * set the property directly, the shadow copy will be assigned in the
534 * omap_crtc_atomic_check callback. This way updates to plane state will
535 * always be mirrored in the crtc state correctly.
537 plane_state
= drm_atomic_get_plane_state(state
->state
, crtc
->primary
);
538 if (IS_ERR(plane_state
))
539 return PTR_ERR(plane_state
);
541 if (property
== crtc
->primary
->rotation_property
)
542 plane_state
->rotation
= val
;
543 else if (property
== priv
->zorder_prop
)
544 plane_state
->zpos
= val
;
551 static int omap_crtc_atomic_get_property(struct drm_crtc
*crtc
,
552 const struct drm_crtc_state
*state
,
553 struct drm_property
*property
,
556 struct omap_drm_private
*priv
= crtc
->dev
->dev_private
;
557 struct omap_crtc_state
*omap_state
= to_omap_crtc_state(state
);
559 if (property
== crtc
->primary
->rotation_property
)
560 *val
= omap_state
->rotation
;
561 else if (property
== priv
->zorder_prop
)
562 *val
= omap_state
->zpos
;
569 static void omap_crtc_reset(struct drm_crtc
*crtc
)
572 __drm_atomic_helper_crtc_destroy_state(crtc
->state
);
575 crtc
->state
= kzalloc(sizeof(struct omap_crtc_state
), GFP_KERNEL
);
578 crtc
->state
->crtc
= crtc
;
581 static struct drm_crtc_state
*
582 omap_crtc_duplicate_state(struct drm_crtc
*crtc
)
584 struct omap_crtc_state
*state
, *current_state
;
586 if (WARN_ON(!crtc
->state
))
589 current_state
= to_omap_crtc_state(crtc
->state
);
591 state
= kmalloc(sizeof(*state
), GFP_KERNEL
);
593 __drm_atomic_helper_crtc_duplicate_state(crtc
, &state
->base
);
595 state
->zpos
= current_state
->zpos
;
596 state
->rotation
= current_state
->rotation
;
601 static const struct drm_crtc_funcs omap_crtc_funcs
= {
602 .reset
= omap_crtc_reset
,
603 .set_config
= drm_atomic_helper_set_config
,
604 .destroy
= omap_crtc_destroy
,
605 .page_flip
= drm_atomic_helper_page_flip
,
606 .gamma_set
= drm_atomic_helper_legacy_gamma_set
,
607 .set_property
= drm_atomic_helper_crtc_set_property
,
608 .atomic_duplicate_state
= omap_crtc_duplicate_state
,
609 .atomic_destroy_state
= drm_atomic_helper_crtc_destroy_state
,
610 .atomic_set_property
= omap_crtc_atomic_set_property
,
611 .atomic_get_property
= omap_crtc_atomic_get_property
,
612 .enable_vblank
= omap_irq_enable_vblank
,
613 .disable_vblank
= omap_irq_disable_vblank
,
616 static const struct drm_crtc_helper_funcs omap_crtc_helper_funcs
= {
617 .mode_set_nofb
= omap_crtc_mode_set_nofb
,
618 .atomic_check
= omap_crtc_atomic_check
,
619 .atomic_begin
= omap_crtc_atomic_begin
,
620 .atomic_flush
= omap_crtc_atomic_flush
,
621 .atomic_enable
= omap_crtc_atomic_enable
,
622 .atomic_disable
= omap_crtc_atomic_disable
,
625 /* -----------------------------------------------------------------------------
629 static const char *channel_names
[] = {
630 [OMAP_DSS_CHANNEL_LCD
] = "lcd",
631 [OMAP_DSS_CHANNEL_DIGIT
] = "tv",
632 [OMAP_DSS_CHANNEL_LCD2
] = "lcd2",
633 [OMAP_DSS_CHANNEL_LCD3
] = "lcd3",
636 void omap_crtc_pre_init(void)
638 memset(omap_crtcs
, 0, sizeof(omap_crtcs
));
640 dss_install_mgr_ops(&mgr_ops
);
643 void omap_crtc_pre_uninit(void)
645 dss_uninstall_mgr_ops();
648 /* initialize crtc */
649 struct drm_crtc
*omap_crtc_init(struct drm_device
*dev
,
650 struct drm_plane
*plane
, struct omap_dss_device
*dssdev
)
652 struct omap_drm_private
*priv
= dev
->dev_private
;
653 struct drm_crtc
*crtc
= NULL
;
654 struct omap_crtc
*omap_crtc
;
655 enum omap_channel channel
;
656 struct omap_dss_device
*out
;
659 out
= omapdss_find_output_from_display(dssdev
);
660 channel
= out
->dispc_channel
;
661 omap_dss_put_device(out
);
663 DBG("%s", channel_names
[channel
]);
665 /* Multiple displays on same channel is not allowed */
666 if (WARN_ON(omap_crtcs
[channel
] != NULL
))
667 return ERR_PTR(-EINVAL
);
669 omap_crtc
= kzalloc(sizeof(*omap_crtc
), GFP_KERNEL
);
671 return ERR_PTR(-ENOMEM
);
673 crtc
= &omap_crtc
->base
;
675 init_waitqueue_head(&omap_crtc
->pending_wait
);
677 omap_crtc
->channel
= channel
;
678 omap_crtc
->name
= channel_names
[channel
];
680 ret
= drm_crtc_init_with_planes(dev
, crtc
, plane
, NULL
,
681 &omap_crtc_funcs
, NULL
);
683 dev_err(dev
->dev
, "%s(): could not init crtc for: %s\n",
684 __func__
, dssdev
->name
);
689 drm_crtc_helper_add(crtc
, &omap_crtc_helper_funcs
);
691 /* The dispc API adapts to what ever size, but the HW supports
692 * 256 element gamma table for LCDs and 1024 element table for
693 * OMAP_DSS_CHANNEL_DIGIT. X server assumes 256 element gamma
694 * tables so lets use that. Size of HW gamma table can be
695 * extracted with dispc_mgr_gamma_size(). If it returns 0
696 * gamma table is not supprted.
698 if (priv
->dispc_ops
->mgr_gamma_size(channel
)) {
699 uint gamma_lut_size
= 256;
701 drm_crtc_enable_color_mgmt(crtc
, 0, false, gamma_lut_size
);
702 drm_mode_crtc_set_gamma_size(crtc
, gamma_lut_size
);
705 omap_plane_install_properties(crtc
->primary
, &crtc
->base
);
707 omap_crtcs
[channel
] = omap_crtc
;