0004-drm-omap-add-framedone-interrupt-support.patch (5405B)
1 From 8af6ec6efc7607cc5af52af895ac7f8e63820f80 Mon Sep 17 00:00:00 2001 2 From: Sebastian Reichel <sebastian.reichel@collabora.co.uk> 3 Date: Mon, 24 Jul 2017 19:33:01 +0200 4 Subject: [PATCH 04/17] drm/omap: add framedone interrupt support 5 6 This prepares framedone interrupt handling for 7 manual display update support. 8 9 Signed-off-by: Sebastian Reichel <sebastian.reichel@collabora.co.uk> 10 --- 11 drivers/gpu/drm/omapdrm/omap_crtc.c | 48 +++++++++++++++++++++++++++++++++++++ 12 drivers/gpu/drm/omapdrm/omap_drv.h | 2 ++ 13 drivers/gpu/drm/omapdrm/omap_irq.c | 24 +++++++++++++++++++ 14 3 files changed, 74 insertions(+) 15 16 diff --git a/drivers/gpu/drm/omapdrm/omap_crtc.c b/drivers/gpu/drm/omapdrm/omap_crtc.c 17 index cc85c16..dee9b6e 100644 18 --- a/drivers/gpu/drm/omapdrm/omap_crtc.c 19 +++ b/drivers/gpu/drm/omapdrm/omap_crtc.c 20 @@ -52,6 +52,9 @@ struct omap_crtc { 21 bool pending; 22 wait_queue_head_t pending_wait; 23 struct drm_pending_vblank_event *event; 24 + 25 + void (*framedone_handler)(void *); 26 + void *framedone_handler_data; 27 }; 28 29 /* ----------------------------------------------------------------------------- 30 @@ -248,6 +251,17 @@ static int omap_crtc_dss_register_framedone( 31 enum omap_channel channel, 32 void (*handler)(void *), void *data) 33 { 34 + struct omap_crtc *omap_crtc = omap_crtcs[channel]; 35 + struct drm_device *dev = omap_crtc->base.dev; 36 + 37 + if (omap_crtc->framedone_handler) 38 + return -EBUSY; 39 + 40 + dev_dbg(dev->dev, "register framedone %s", omap_crtc->name); 41 + 42 + omap_crtc->framedone_handler = handler; 43 + omap_crtc->framedone_handler_data = data; 44 + 45 return 0; 46 } 47 48 @@ -255,6 +269,16 @@ static void omap_crtc_dss_unregister_framedone( 49 enum omap_channel channel, 50 void (*handler)(void *), void *data) 51 { 52 + struct omap_crtc *omap_crtc = omap_crtcs[channel]; 53 + struct drm_device *dev = omap_crtc->base.dev; 54 + 55 + dev_dbg(dev->dev, "unregister framedone %s", omap_crtc->name); 56 + 57 + WARN_ON(omap_crtc->framedone_handler != handler); 58 + WARN_ON(omap_crtc->framedone_handler_data != data); 59 + 60 + omap_crtc->framedone_handler = NULL; 61 + omap_crtc->framedone_handler_data = NULL; 62 } 63 64 static const struct dss_mgr_ops mgr_ops = { 65 @@ -322,6 +346,30 @@ void omap_crtc_vblank_irq(struct drm_crtc *crtc) 66 DBG("%s: apply done", omap_crtc->name); 67 } 68 69 +void omap_crtc_framedone_irq(struct drm_crtc *crtc, uint32_t irqstatus) 70 +{ 71 + struct omap_crtc *omap_crtc = to_omap_crtc(crtc); 72 + 73 + if (!omap_crtc->framedone_handler) { 74 + dev_warn(omap_crtc->base.dev->dev, "no framedone handler?"); 75 + return; 76 + } 77 + 78 + omap_crtc->framedone_handler(omap_crtc->framedone_handler_data); 79 + 80 + spin_lock(&crtc->dev->event_lock); 81 + /* Send the vblank event if one has been requested. */ 82 + if (omap_crtc->event) { 83 + drm_crtc_send_vblank_event(crtc, omap_crtc->event); 84 + omap_crtc->event = NULL; 85 + } 86 + omap_crtc->pending = false; 87 + spin_unlock(&crtc->dev->event_lock); 88 + 89 + /* Wake up omap_atomic_complete. */ 90 + wake_up(&omap_crtc->pending_wait); 91 +} 92 + 93 static void omap_crtc_write_crtc_properties(struct drm_crtc *crtc) 94 { 95 struct omap_drm_private *priv = crtc->dev->dev_private; 96 diff --git a/drivers/gpu/drm/omapdrm/omap_drv.h b/drivers/gpu/drm/omapdrm/omap_drv.h 97 index 4bd1e90..22f3d94 100644 98 --- a/drivers/gpu/drm/omapdrm/omap_drv.h 99 +++ b/drivers/gpu/drm/omapdrm/omap_drv.h 100 @@ -97,6 +97,7 @@ void omap_gem_describe_objects(struct list_head *list, struct seq_file *m); 101 int omap_gem_resume(struct device *dev); 102 #endif 103 104 +int omap_irq_enable_framedone(struct drm_crtc *crtc, bool enable); 105 int omap_irq_enable_vblank(struct drm_crtc *crtc); 106 void omap_irq_disable_vblank(struct drm_crtc *crtc); 107 void omap_drm_irq_uninstall(struct drm_device *dev); 108 @@ -124,6 +125,7 @@ struct drm_crtc *omap_crtc_init(struct drm_device *dev, 109 int omap_crtc_wait_pending(struct drm_crtc *crtc); 110 void omap_crtc_error_irq(struct drm_crtc *crtc, uint32_t irqstatus); 111 void omap_crtc_vblank_irq(struct drm_crtc *crtc); 112 +void omap_crtc_framedone_irq(struct drm_crtc *crtc, uint32_t irqstatus); 113 114 struct drm_plane *omap_plane_init(struct drm_device *dev, 115 int idx, enum drm_plane_type type, 116 diff --git a/drivers/gpu/drm/omapdrm/omap_irq.c b/drivers/gpu/drm/omapdrm/omap_irq.c 117 index 013b0bb..301c0e7 100644 118 --- a/drivers/gpu/drm/omapdrm/omap_irq.c 119 +++ b/drivers/gpu/drm/omapdrm/omap_irq.c 120 @@ -87,6 +87,27 @@ int omap_irq_wait(struct drm_device *dev, struct omap_irq_wait *wait, 121 return ret == 0 ? -1 : 0; 122 } 123 124 +int omap_irq_enable_framedone(struct drm_crtc *crtc, bool enable) 125 +{ 126 + struct drm_device *dev = crtc->dev; 127 + struct omap_drm_private *priv = dev->dev_private; 128 + unsigned long flags; 129 + enum omap_channel channel = omap_crtc_channel(crtc); 130 + int framedone_irq = priv->dispc_ops->mgr_get_framedone_irq(channel); 131 + 132 + DBG("dev=%p, crtc=%u, enable=%d", dev, channel, enable); 133 + 134 + spin_lock_irqsave(&priv->wait_lock, flags); 135 + if (enable) 136 + priv->irq_mask |= framedone_irq; 137 + else 138 + priv->irq_mask &= ~framedone_irq; 139 + omap_irq_update(dev); 140 + spin_unlock_irqrestore(&priv->wait_lock, flags); 141 + 142 + return 0; 143 +} 144 + 145 /** 146 * enable_vblank - enable vblank interrupt events 147 * @dev: DRM device 148 @@ -217,6 +238,9 @@ static irqreturn_t omap_irq_handler(int irq, void *arg) 149 150 if (irqstatus & priv->dispc_ops->mgr_get_sync_lost_irq(channel)) 151 omap_crtc_error_irq(crtc, irqstatus); 152 + 153 + if (irqstatus & priv->dispc_ops->mgr_get_framedone_irq(channel)) 154 + omap_crtc_framedone_irq(crtc, irqstatus); 155 } 156 157 omap_irq_ocp_error_handler(dev, irqstatus); 158 -- 159 2.1.4 160