aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/gpu/drm/omapdrm/omap_crtc.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/gpu/drm/omapdrm/omap_crtc.c')
-rw-r--r--drivers/gpu/drm/omapdrm/omap_crtc.c114
1 files changed, 109 insertions, 5 deletions
diff --git a/drivers/gpu/drm/omapdrm/omap_crtc.c b/drivers/gpu/drm/omapdrm/omap_crtc.c
index 5b6a18a62bbb..d61215494617 100644
--- a/drivers/gpu/drm/omapdrm/omap_crtc.c
+++ b/drivers/gpu/drm/omapdrm/omap_crtc.c
@@ -32,6 +32,7 @@ struct omap_crtc_state {
32 /* Shadow values for legacy userspace support. */ 32 /* Shadow values for legacy userspace support. */
33 unsigned int rotation; 33 unsigned int rotation;
34 unsigned int zpos; 34 unsigned int zpos;
35 bool manually_updated;
35}; 36};
36 37
37#define to_omap_crtc(x) container_of(x, struct omap_crtc, base) 38#define to_omap_crtc(x) container_of(x, struct omap_crtc, base)
@@ -51,6 +52,7 @@ struct omap_crtc {
51 bool pending; 52 bool pending;
52 wait_queue_head_t pending_wait; 53 wait_queue_head_t pending_wait;
53 struct drm_pending_vblank_event *event; 54 struct drm_pending_vblank_event *event;
55 struct delayed_work update_work;
54 56
55 void (*framedone_handler)(void *); 57 void (*framedone_handler)(void *);
56 void *framedone_handler_data; 58 void *framedone_handler_data;
@@ -105,21 +107,18 @@ int omap_crtc_wait_pending(struct drm_crtc *crtc)
105/* 107/*
106 * Manager-ops, callbacks from output when they need to configure 108 * Manager-ops, callbacks from output when they need to configure
107 * the upstream part of the video pipe. 109 * the upstream part of the video pipe.
108 *
109 * Most of these we can ignore until we add support for command-mode
110 * panels.. for video-mode the crtc-helpers already do an adequate
111 * job of sequencing the setup of the video pipe in the proper order
112 */ 110 */
113 111
114/* we can probably ignore these until we support command-mode panels: */
115static void omap_crtc_dss_start_update(struct omap_drm_private *priv, 112static void omap_crtc_dss_start_update(struct omap_drm_private *priv,
116 enum omap_channel channel) 113 enum omap_channel channel)
117{ 114{
115 priv->dispc_ops->mgr_enable(priv->dispc, channel, true);
118} 116}
119 117
120/* Called only from the encoder enable/disable and suspend/resume handlers. */ 118/* Called only from the encoder enable/disable and suspend/resume handlers. */
121static void omap_crtc_set_enabled(struct drm_crtc *crtc, bool enable) 119static void omap_crtc_set_enabled(struct drm_crtc *crtc, bool enable)
122{ 120{
121 struct omap_crtc_state *omap_state = to_omap_crtc_state(crtc->state);
123 struct drm_device *dev = crtc->dev; 122 struct drm_device *dev = crtc->dev;
124 struct omap_drm_private *priv = dev->dev_private; 123 struct omap_drm_private *priv = dev->dev_private;
125 struct omap_crtc *omap_crtc = to_omap_crtc(crtc); 124 struct omap_crtc *omap_crtc = to_omap_crtc(crtc);
@@ -131,6 +130,12 @@ static void omap_crtc_set_enabled(struct drm_crtc *crtc, bool enable)
131 if (WARN_ON(omap_crtc->enabled == enable)) 130 if (WARN_ON(omap_crtc->enabled == enable))
132 return; 131 return;
133 132
133 if (omap_state->manually_updated) {
134 omap_irq_enable_framedone(crtc, enable);
135 omap_crtc->enabled = enable;
136 return;
137 }
138
134 if (omap_crtc->pipe->output->type == OMAP_DISPLAY_TYPE_HDMI) { 139 if (omap_crtc->pipe->output->type == OMAP_DISPLAY_TYPE_HDMI) {
135 priv->dispc_ops->mgr_enable(priv->dispc, channel, enable); 140 priv->dispc_ops->mgr_enable(priv->dispc, channel, enable);
136 omap_crtc->enabled = enable; 141 omap_crtc->enabled = enable;
@@ -350,6 +355,51 @@ void omap_crtc_framedone_irq(struct drm_crtc *crtc, uint32_t irqstatus)
350 wake_up(&omap_crtc->pending_wait); 355 wake_up(&omap_crtc->pending_wait);
351} 356}
352 357
358void omap_crtc_flush(struct drm_crtc *crtc)
359{
360 struct omap_crtc *omap_crtc = to_omap_crtc(crtc);
361 struct omap_crtc_state *omap_state = to_omap_crtc_state(crtc->state);
362
363 if (!omap_state->manually_updated)
364 return;
365
366 if (!delayed_work_pending(&omap_crtc->update_work))
367 schedule_delayed_work(&omap_crtc->update_work, 0);
368}
369
370static void omap_crtc_manual_display_update(struct work_struct *data)
371{
372 struct omap_crtc *omap_crtc =
373 container_of(data, struct omap_crtc, update_work.work);
374 struct drm_display_mode *mode = &omap_crtc->pipe->crtc->mode;
375 struct omap_dss_device *dssdev = omap_crtc->pipe->output->next;
376 struct drm_device *dev = omap_crtc->base.dev;
377 const struct omap_dss_driver *dssdrv;
378 int ret;
379
380 if (!dssdev) {
381 dev_err_once(dev->dev, "missing display dssdev!");
382 return;
383 }
384
385 dssdrv = dssdev->driver;
386 if (!dssdrv || !dssdrv->update) {
387 dev_err_once(dev->dev, "missing or incorrect dssdrv!");
388 return;
389 }
390
391 if (dssdrv->sync)
392 dssdrv->sync(dssdev);
393
394 ret = dssdrv->update(dssdev, 0, 0, mode->hdisplay, mode->vdisplay);
395 if (ret < 0) {
396 spin_lock_irq(&dev->event_lock);
397 omap_crtc->pending = false;
398 spin_unlock_irq(&dev->event_lock);
399 wake_up(&omap_crtc->pending_wait);
400 }
401}
402
353static void omap_crtc_write_crtc_properties(struct drm_crtc *crtc) 403static void omap_crtc_write_crtc_properties(struct drm_crtc *crtc)
354{ 404{
355 struct omap_drm_private *priv = crtc->dev->dev_private; 405 struct omap_drm_private *priv = crtc->dev->dev_private;
@@ -399,12 +449,17 @@ static void omap_crtc_atomic_enable(struct drm_crtc *crtc,
399{ 449{
400 struct omap_drm_private *priv = crtc->dev->dev_private; 450 struct omap_drm_private *priv = crtc->dev->dev_private;
401 struct omap_crtc *omap_crtc = to_omap_crtc(crtc); 451 struct omap_crtc *omap_crtc = to_omap_crtc(crtc);
452 struct omap_crtc_state *omap_state = to_omap_crtc_state(crtc->state);
402 int ret; 453 int ret;
403 454
404 DBG("%s", omap_crtc->name); 455 DBG("%s", omap_crtc->name);
405 456
406 priv->dispc_ops->runtime_get(priv->dispc); 457 priv->dispc_ops->runtime_get(priv->dispc);
407 458
459 /* manual updated display will not trigger vsync irq */
460 if (omap_state->manually_updated)
461 return;
462
408 spin_lock_irq(&crtc->dev->event_lock); 463 spin_lock_irq(&crtc->dev->event_lock);
409 drm_crtc_vblank_on(crtc); 464 drm_crtc_vblank_on(crtc);
410 ret = drm_crtc_vblank_get(crtc); 465 ret = drm_crtc_vblank_get(crtc);
@@ -419,6 +474,7 @@ static void omap_crtc_atomic_disable(struct drm_crtc *crtc,
419{ 474{
420 struct omap_drm_private *priv = crtc->dev->dev_private; 475 struct omap_drm_private *priv = crtc->dev->dev_private;
421 struct omap_crtc *omap_crtc = to_omap_crtc(crtc); 476 struct omap_crtc *omap_crtc = to_omap_crtc(crtc);
477 struct drm_device *dev = crtc->dev;
422 478
423 DBG("%s", omap_crtc->name); 479 DBG("%s", omap_crtc->name);
424 480
@@ -429,6 +485,11 @@ static void omap_crtc_atomic_disable(struct drm_crtc *crtc,
429 } 485 }
430 spin_unlock_irq(&crtc->dev->event_lock); 486 spin_unlock_irq(&crtc->dev->event_lock);
431 487
488 cancel_delayed_work(&omap_crtc->update_work);
489
490 if (!omap_crtc_wait_pending(crtc))
491 dev_warn(dev->dev, "manual display update did not finish!");
492
432 drm_crtc_vblank_off(crtc); 493 drm_crtc_vblank_off(crtc);
433 494
434 priv->dispc_ops->runtime_put(priv->dispc); 495 priv->dispc_ops->runtime_put(priv->dispc);
@@ -499,6 +560,22 @@ static void omap_crtc_mode_set_nofb(struct drm_crtc *crtc)
499 drm_display_mode_to_videomode(mode, &omap_crtc->vm); 560 drm_display_mode_to_videomode(mode, &omap_crtc->vm);
500} 561}
501 562
563static bool omap_crtc_is_manually_updated(struct drm_crtc *crtc)
564{
565 struct omap_crtc *omap_crtc = to_omap_crtc(crtc);
566 struct omap_dss_device *display = omap_crtc->pipe->output->next;
567
568 if (!display)
569 return false;
570
571 if (display->caps & OMAP_DSS_DISPLAY_CAP_MANUAL_UPDATE) {
572 DBG("detected manually updated display!");
573 return true;
574 }
575
576 return false;
577}
578
502static int omap_crtc_atomic_check(struct drm_crtc *crtc, 579static int omap_crtc_atomic_check(struct drm_crtc *crtc,
503 struct drm_crtc_state *state) 580 struct drm_crtc_state *state)
504{ 581{
@@ -520,6 +597,9 @@ static int omap_crtc_atomic_check(struct drm_crtc *crtc,
520 /* Mirror new values for zpos and rotation in omap_crtc_state */ 597 /* Mirror new values for zpos and rotation in omap_crtc_state */
521 omap_crtc_state->zpos = pri_state->zpos; 598 omap_crtc_state->zpos = pri_state->zpos;
522 omap_crtc_state->rotation = pri_state->rotation; 599 omap_crtc_state->rotation = pri_state->rotation;
600
601 /* Check if this CRTC is for a manually updated display */
602 omap_crtc_state->manually_updated = omap_crtc_is_manually_updated(crtc);
523 } 603 }
524 604
525 return 0; 605 return 0;
@@ -535,6 +615,7 @@ static void omap_crtc_atomic_flush(struct drm_crtc *crtc,
535{ 615{
536 struct omap_drm_private *priv = crtc->dev->dev_private; 616 struct omap_drm_private *priv = crtc->dev->dev_private;
537 struct omap_crtc *omap_crtc = to_omap_crtc(crtc); 617 struct omap_crtc *omap_crtc = to_omap_crtc(crtc);
618 struct omap_crtc_state *omap_crtc_state = to_omap_crtc_state(crtc->state);
538 int ret; 619 int ret;
539 620
540 if (crtc->state->color_mgmt_changed) { 621 if (crtc->state->color_mgmt_changed) {
@@ -559,6 +640,15 @@ static void omap_crtc_atomic_flush(struct drm_crtc *crtc,
559 640
560 DBG("%s: GO", omap_crtc->name); 641 DBG("%s: GO", omap_crtc->name);
561 642
643 if (omap_crtc_state->manually_updated) {
644 /* send new image for page flips and modeset changes */
645 spin_lock_irq(&crtc->dev->event_lock);
646 omap_crtc_flush(crtc);
647 omap_crtc_arm_event(crtc);
648 spin_unlock_irq(&crtc->dev->event_lock);
649 return;
650 }
651
562 ret = drm_crtc_vblank_get(crtc); 652 ret = drm_crtc_vblank_get(crtc);
563 WARN_ON(ret != 0); 653 WARN_ON(ret != 0);
564 654
@@ -644,6 +734,7 @@ omap_crtc_duplicate_state(struct drm_crtc *crtc)
644 734
645 state->zpos = current_state->zpos; 735 state->zpos = current_state->zpos;
646 state->rotation = current_state->rotation; 736 state->rotation = current_state->rotation;
737 state->manually_updated = current_state->manually_updated;
647 738
648 return &state->base; 739 return &state->base;
649} 740}
@@ -720,6 +811,19 @@ struct drm_crtc *omap_crtc_init(struct drm_device *dev,
720 omap_crtc->channel = channel; 811 omap_crtc->channel = channel;
721 omap_crtc->name = channel_names[channel]; 812 omap_crtc->name = channel_names[channel];
722 813
814 /*
815 * We want to refresh manually updated displays from dirty callback,
816 * which is called quite often (e.g. for each drawn line). This will
817 * be used to do the display update asynchronously to avoid blocking
818 * the rendering process and merges multiple dirty calls into one
819 * update if they arrive very fast. We also call this function for
820 * atomic display updates (e.g. for page flips), which means we do
821 * not need extra locking. Atomic updates should be synchronous, but
822 * need to wait for the framedone interrupt anyways.
823 */
824 INIT_DELAYED_WORK(&omap_crtc->update_work,
825 omap_crtc_manual_display_update);
826
723 ret = drm_crtc_init_with_planes(dev, crtc, plane, NULL, 827 ret = drm_crtc_init_with_planes(dev, crtc, plane, NULL,
724 &omap_crtc_funcs, NULL); 828 &omap_crtc_funcs, NULL);
725 if (ret < 0) { 829 if (ret < 0) {