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(x) container_of(x, struct omap_crtc, base)
35 enum omap_channel channel
;
37 struct omap_video_timings timings
;
39 struct omap_drm_irq vblank_irq
;
40 struct omap_drm_irq error_irq
;
42 bool ignore_digit_sync_lost
;
45 wait_queue_head_t pending_wait
;
48 /* -----------------------------------------------------------------------------
52 uint32_t pipe2vbl(struct drm_crtc
*crtc
)
54 struct omap_crtc
*omap_crtc
= to_omap_crtc(crtc
);
56 return dispc_mgr_get_vsync_irq(omap_crtc
->channel
);
59 struct omap_video_timings
*omap_crtc_timings(struct drm_crtc
*crtc
)
61 struct omap_crtc
*omap_crtc
= to_omap_crtc(crtc
);
62 return &omap_crtc
->timings
;
65 enum omap_channel
omap_crtc_channel(struct drm_crtc
*crtc
)
67 struct omap_crtc
*omap_crtc
= to_omap_crtc(crtc
);
68 return omap_crtc
->channel
;
71 int omap_crtc_wait_pending(struct drm_crtc
*crtc
)
73 struct omap_crtc
*omap_crtc
= to_omap_crtc(crtc
);
76 * Timeout is set to a "sufficiently" high value, which should cover
77 * a single frame refresh even on slower displays.
79 return wait_event_timeout(omap_crtc
->pending_wait
,
81 msecs_to_jiffies(250));
84 /* -----------------------------------------------------------------------------
85 * DSS Manager Functions
89 * Manager-ops, callbacks from output when they need to configure
90 * the upstream part of the video pipe.
92 * Most of these we can ignore until we add support for command-mode
93 * panels.. for video-mode the crtc-helpers already do an adequate
94 * job of sequencing the setup of the video pipe in the proper order
97 /* ovl-mgr-id -> crtc */
98 static struct omap_crtc
*omap_crtcs
[8];
99 static struct omap_dss_device
*omap_crtc_output
[8];
101 /* we can probably ignore these until we support command-mode panels: */
102 static int omap_crtc_dss_connect(enum omap_channel channel
,
103 struct omap_dss_device
*dst
)
105 if (omap_crtc_output
[channel
])
108 if ((dispc_mgr_get_supported_outputs(channel
) & dst
->id
) == 0)
111 omap_crtc_output
[channel
] = dst
;
112 dst
->dispc_channel_connected
= true;
117 static void omap_crtc_dss_disconnect(enum omap_channel channel
,
118 struct omap_dss_device
*dst
)
120 omap_crtc_output
[channel
] = NULL
;
121 dst
->dispc_channel_connected
= false;
124 static void omap_crtc_dss_start_update(enum omap_channel channel
)
128 /* Called only from the encoder enable/disable and suspend/resume handlers. */
129 static void omap_crtc_set_enabled(struct drm_crtc
*crtc
, bool enable
)
131 struct drm_device
*dev
= crtc
->dev
;
132 struct omap_crtc
*omap_crtc
= to_omap_crtc(crtc
);
133 enum omap_channel channel
= omap_crtc
->channel
;
134 struct omap_irq_wait
*wait
;
135 u32 framedone_irq
, vsync_irq
;
138 if (omap_crtc_output
[channel
]->output_type
== OMAP_DISPLAY_TYPE_HDMI
) {
139 dispc_mgr_enable(channel
, enable
);
143 if (dispc_mgr_is_enabled(channel
) == enable
)
146 if (omap_crtc
->channel
== OMAP_DSS_CHANNEL_DIGIT
) {
148 * Digit output produces some sync lost interrupts during the
149 * first frame when enabling, so we need to ignore those.
151 omap_crtc
->ignore_digit_sync_lost
= true;
154 framedone_irq
= dispc_mgr_get_framedone_irq(channel
);
155 vsync_irq
= dispc_mgr_get_vsync_irq(channel
);
158 wait
= omap_irq_wait_init(dev
, vsync_irq
, 1);
161 * When we disable the digit output, we need to wait for
162 * FRAMEDONE to know that DISPC has finished with the output.
164 * OMAP2/3 does not have FRAMEDONE irq for digit output, and in
165 * that case we need to use vsync interrupt, and wait for both
166 * even and odd frames.
170 wait
= omap_irq_wait_init(dev
, framedone_irq
, 1);
172 wait
= omap_irq_wait_init(dev
, vsync_irq
, 2);
175 dispc_mgr_enable(channel
, enable
);
177 ret
= omap_irq_wait(dev
, wait
, msecs_to_jiffies(100));
179 dev_err(dev
->dev
, "%s: timeout waiting for %s\n",
180 omap_crtc
->name
, enable
? "enable" : "disable");
183 if (omap_crtc
->channel
== OMAP_DSS_CHANNEL_DIGIT
) {
184 omap_crtc
->ignore_digit_sync_lost
= false;
185 /* make sure the irq handler sees the value above */
191 static int omap_crtc_dss_enable(enum omap_channel channel
)
193 struct omap_crtc
*omap_crtc
= omap_crtcs
[channel
];
194 struct omap_overlay_manager_info info
;
196 memset(&info
, 0, sizeof(info
));
197 info
.default_color
= 0x00000000;
198 info
.trans_key
= 0x00000000;
199 info
.trans_key_type
= OMAP_DSS_COLOR_KEY_GFX_DST
;
200 info
.trans_enabled
= false;
202 dispc_mgr_setup(omap_crtc
->channel
, &info
);
203 dispc_mgr_set_timings(omap_crtc
->channel
,
204 &omap_crtc
->timings
);
205 omap_crtc_set_enabled(&omap_crtc
->base
, true);
210 static void omap_crtc_dss_disable(enum omap_channel channel
)
212 struct omap_crtc
*omap_crtc
= omap_crtcs
[channel
];
214 omap_crtc_set_enabled(&omap_crtc
->base
, false);
217 static void omap_crtc_dss_set_timings(enum omap_channel channel
,
218 const struct omap_video_timings
*timings
)
220 struct omap_crtc
*omap_crtc
= omap_crtcs
[channel
];
221 DBG("%s", omap_crtc
->name
);
222 omap_crtc
->timings
= *timings
;
225 static void omap_crtc_dss_set_lcd_config(enum omap_channel channel
,
226 const struct dss_lcd_mgr_config
*config
)
228 struct omap_crtc
*omap_crtc
= omap_crtcs
[channel
];
229 DBG("%s", omap_crtc
->name
);
230 dispc_mgr_set_lcd_config(omap_crtc
->channel
, config
);
233 static int omap_crtc_dss_register_framedone(
234 enum omap_channel channel
,
235 void (*handler
)(void *), void *data
)
240 static void omap_crtc_dss_unregister_framedone(
241 enum omap_channel channel
,
242 void (*handler
)(void *), void *data
)
246 static const struct dss_mgr_ops mgr_ops
= {
247 .connect
= omap_crtc_dss_connect
,
248 .disconnect
= omap_crtc_dss_disconnect
,
249 .start_update
= omap_crtc_dss_start_update
,
250 .enable
= omap_crtc_dss_enable
,
251 .disable
= omap_crtc_dss_disable
,
252 .set_timings
= omap_crtc_dss_set_timings
,
253 .set_lcd_config
= omap_crtc_dss_set_lcd_config
,
254 .register_framedone_handler
= omap_crtc_dss_register_framedone
,
255 .unregister_framedone_handler
= omap_crtc_dss_unregister_framedone
,
258 /* -----------------------------------------------------------------------------
259 * Setup, Flush and Page Flip
262 static void omap_crtc_complete_page_flip(struct drm_crtc
*crtc
)
264 struct drm_pending_vblank_event
*event
;
265 struct drm_device
*dev
= crtc
->dev
;
268 event
= crtc
->state
->event
;
273 spin_lock_irqsave(&dev
->event_lock
, flags
);
274 drm_crtc_send_vblank_event(crtc
, event
);
275 spin_unlock_irqrestore(&dev
->event_lock
, flags
);
278 static void omap_crtc_error_irq(struct omap_drm_irq
*irq
, uint32_t irqstatus
)
280 struct omap_crtc
*omap_crtc
=
281 container_of(irq
, struct omap_crtc
, error_irq
);
283 if (omap_crtc
->ignore_digit_sync_lost
) {
284 irqstatus
&= ~DISPC_IRQ_SYNC_LOST_DIGIT
;
289 DRM_ERROR_RATELIMITED("%s: errors: %08x\n", omap_crtc
->name
, irqstatus
);
292 static void omap_crtc_vblank_irq(struct omap_drm_irq
*irq
, uint32_t irqstatus
)
294 struct omap_crtc
*omap_crtc
=
295 container_of(irq
, struct omap_crtc
, vblank_irq
);
296 struct drm_device
*dev
= omap_crtc
->base
.dev
;
298 if (dispc_mgr_go_busy(omap_crtc
->channel
))
301 DBG("%s: apply done", omap_crtc
->name
);
303 __omap_irq_unregister(dev
, &omap_crtc
->vblank_irq
);
306 WARN_ON(!omap_crtc
->pending
);
307 omap_crtc
->pending
= false;
310 /* wake up userspace */
311 omap_crtc_complete_page_flip(&omap_crtc
->base
);
313 /* wake up omap_atomic_complete */
314 wake_up(&omap_crtc
->pending_wait
);
317 /* -----------------------------------------------------------------------------
321 static void omap_crtc_destroy(struct drm_crtc
*crtc
)
323 struct omap_crtc
*omap_crtc
= to_omap_crtc(crtc
);
325 DBG("%s", omap_crtc
->name
);
327 WARN_ON(omap_crtc
->vblank_irq
.registered
);
328 omap_irq_unregister(crtc
->dev
, &omap_crtc
->error_irq
);
330 drm_crtc_cleanup(crtc
);
335 static void omap_crtc_enable(struct drm_crtc
*crtc
)
337 struct omap_crtc
*omap_crtc
= to_omap_crtc(crtc
);
339 DBG("%s", omap_crtc
->name
);
342 WARN_ON(omap_crtc
->pending
);
343 omap_crtc
->pending
= true;
346 omap_irq_register(crtc
->dev
, &omap_crtc
->vblank_irq
);
348 drm_crtc_vblank_on(crtc
);
351 static void omap_crtc_disable(struct drm_crtc
*crtc
)
353 struct omap_crtc
*omap_crtc
= to_omap_crtc(crtc
);
355 DBG("%s", omap_crtc
->name
);
357 drm_crtc_vblank_off(crtc
);
360 static void omap_crtc_mode_set_nofb(struct drm_crtc
*crtc
)
362 struct omap_crtc
*omap_crtc
= to_omap_crtc(crtc
);
363 struct drm_display_mode
*mode
= &crtc
->state
->adjusted_mode
;
365 DBG("%s: set mode: %d:\"%s\" %d %d %d %d %d %d %d %d %d %d 0x%x 0x%x",
366 omap_crtc
->name
, mode
->base
.id
, mode
->name
,
367 mode
->vrefresh
, mode
->clock
,
368 mode
->hdisplay
, mode
->hsync_start
, mode
->hsync_end
, mode
->htotal
,
369 mode
->vdisplay
, mode
->vsync_start
, mode
->vsync_end
, mode
->vtotal
,
370 mode
->type
, mode
->flags
);
372 copy_timings_drm_to_omap(&omap_crtc
->timings
, mode
);
375 static void omap_crtc_atomic_begin(struct drm_crtc
*crtc
,
376 struct drm_crtc_state
*old_crtc_state
)
380 static void omap_crtc_atomic_flush(struct drm_crtc
*crtc
,
381 struct drm_crtc_state
*old_crtc_state
)
383 struct omap_crtc
*omap_crtc
= to_omap_crtc(crtc
);
385 WARN_ON(omap_crtc
->vblank_irq
.registered
);
387 if (dispc_mgr_is_enabled(omap_crtc
->channel
)) {
389 DBG("%s: GO", omap_crtc
->name
);
392 WARN_ON(omap_crtc
->pending
);
393 omap_crtc
->pending
= true;
396 dispc_mgr_go(omap_crtc
->channel
);
397 omap_irq_register(crtc
->dev
, &omap_crtc
->vblank_irq
);
401 static bool omap_crtc_is_plane_prop(struct drm_device
*dev
,
402 struct drm_property
*property
)
404 struct omap_drm_private
*priv
= dev
->dev_private
;
406 return property
== priv
->zorder_prop
||
407 property
== dev
->mode_config
.rotation_property
;
410 static int omap_crtc_atomic_set_property(struct drm_crtc
*crtc
,
411 struct drm_crtc_state
*state
,
412 struct drm_property
*property
,
415 struct drm_device
*dev
= crtc
->dev
;
417 if (omap_crtc_is_plane_prop(dev
, property
)) {
418 struct drm_plane_state
*plane_state
;
419 struct drm_plane
*plane
= crtc
->primary
;
422 * Delegate property set to the primary plane. Get the plane
423 * state and set the property directly.
426 plane_state
= drm_atomic_get_plane_state(state
->state
, plane
);
427 if (IS_ERR(plane_state
))
428 return PTR_ERR(plane_state
);
430 return drm_atomic_plane_set_property(plane
, plane_state
,
437 static int omap_crtc_atomic_get_property(struct drm_crtc
*crtc
,
438 const struct drm_crtc_state
*state
,
439 struct drm_property
*property
,
442 struct drm_device
*dev
= crtc
->dev
;
444 if (omap_crtc_is_plane_prop(dev
, property
)) {
446 * Delegate property get to the primary plane. The
447 * drm_atomic_plane_get_property() function isn't exported, but
448 * can be called through drm_object_property_get_value() as that
449 * will call drm_atomic_get_property() for atomic drivers.
451 return drm_object_property_get_value(&crtc
->primary
->base
,
458 static const struct drm_crtc_funcs omap_crtc_funcs
= {
459 .reset
= drm_atomic_helper_crtc_reset
,
460 .set_config
= drm_atomic_helper_set_config
,
461 .destroy
= omap_crtc_destroy
,
462 .page_flip
= drm_atomic_helper_page_flip
,
463 .set_property
= drm_atomic_helper_crtc_set_property
,
464 .atomic_duplicate_state
= drm_atomic_helper_crtc_duplicate_state
,
465 .atomic_destroy_state
= drm_atomic_helper_crtc_destroy_state
,
466 .atomic_set_property
= omap_crtc_atomic_set_property
,
467 .atomic_get_property
= omap_crtc_atomic_get_property
,
470 static const struct drm_crtc_helper_funcs omap_crtc_helper_funcs
= {
471 .mode_set_nofb
= omap_crtc_mode_set_nofb
,
472 .disable
= omap_crtc_disable
,
473 .enable
= omap_crtc_enable
,
474 .atomic_begin
= omap_crtc_atomic_begin
,
475 .atomic_flush
= omap_crtc_atomic_flush
,
478 /* -----------------------------------------------------------------------------
482 static const char *channel_names
[] = {
483 [OMAP_DSS_CHANNEL_LCD
] = "lcd",
484 [OMAP_DSS_CHANNEL_DIGIT
] = "tv",
485 [OMAP_DSS_CHANNEL_LCD2
] = "lcd2",
486 [OMAP_DSS_CHANNEL_LCD3
] = "lcd3",
489 void omap_crtc_pre_init(void)
491 dss_install_mgr_ops(&mgr_ops
);
494 void omap_crtc_pre_uninit(void)
496 dss_uninstall_mgr_ops();
499 /* initialize crtc */
500 struct drm_crtc
*omap_crtc_init(struct drm_device
*dev
,
501 struct drm_plane
*plane
, enum omap_channel channel
, int id
)
503 struct drm_crtc
*crtc
= NULL
;
504 struct omap_crtc
*omap_crtc
;
507 DBG("%s", channel_names
[channel
]);
509 omap_crtc
= kzalloc(sizeof(*omap_crtc
), GFP_KERNEL
);
513 crtc
= &omap_crtc
->base
;
515 init_waitqueue_head(&omap_crtc
->pending_wait
);
517 omap_crtc
->channel
= channel
;
518 omap_crtc
->name
= channel_names
[channel
];
520 omap_crtc
->vblank_irq
.irqmask
= pipe2vbl(crtc
);
521 omap_crtc
->vblank_irq
.irq
= omap_crtc_vblank_irq
;
523 omap_crtc
->error_irq
.irqmask
=
524 dispc_mgr_get_sync_lost_irq(channel
);
525 omap_crtc
->error_irq
.irq
= omap_crtc_error_irq
;
526 omap_irq_register(dev
, &omap_crtc
->error_irq
);
528 ret
= drm_crtc_init_with_planes(dev
, crtc
, plane
, NULL
,
529 &omap_crtc_funcs
, NULL
);
535 drm_crtc_helper_add(crtc
, &omap_crtc_helper_funcs
);
537 omap_plane_install_properties(crtc
->primary
, &crtc
->base
);
539 omap_crtcs
[channel
] = omap_crtc
;