Back to home page

OSCL-LXR

 
 

    


0001 // SPDX-License-Identifier: GPL-2.0-only
0002 /*
0003  * Copyright (C) 2011 Texas Instruments Incorporated - https://www.ti.com/
0004  * Author: Rob Clark <rob.clark@linaro.org>
0005  */
0006 
0007 #include <drm/drm_vblank.h>
0008 
0009 #include "omap_drv.h"
0010 
0011 struct omap_irq_wait {
0012     struct list_head node;
0013     wait_queue_head_t wq;
0014     u32 irqmask;
0015     int count;
0016 };
0017 
0018 /* call with wait_lock and dispc runtime held */
0019 static void omap_irq_update(struct drm_device *dev)
0020 {
0021     struct omap_drm_private *priv = dev->dev_private;
0022     struct omap_irq_wait *wait;
0023     u32 irqmask = priv->irq_mask;
0024 
0025     assert_spin_locked(&priv->wait_lock);
0026 
0027     list_for_each_entry(wait, &priv->wait_list, node)
0028         irqmask |= wait->irqmask;
0029 
0030     DBG("irqmask=%08x", irqmask);
0031 
0032     dispc_write_irqenable(priv->dispc, irqmask);
0033 }
0034 
0035 static void omap_irq_wait_handler(struct omap_irq_wait *wait)
0036 {
0037     wait->count--;
0038     wake_up(&wait->wq);
0039 }
0040 
0041 struct omap_irq_wait * omap_irq_wait_init(struct drm_device *dev,
0042         u32 irqmask, int count)
0043 {
0044     struct omap_drm_private *priv = dev->dev_private;
0045     struct omap_irq_wait *wait = kzalloc(sizeof(*wait), GFP_KERNEL);
0046     unsigned long flags;
0047 
0048     init_waitqueue_head(&wait->wq);
0049     wait->irqmask = irqmask;
0050     wait->count = count;
0051 
0052     spin_lock_irqsave(&priv->wait_lock, flags);
0053     list_add(&wait->node, &priv->wait_list);
0054     omap_irq_update(dev);
0055     spin_unlock_irqrestore(&priv->wait_lock, flags);
0056 
0057     return wait;
0058 }
0059 
0060 int omap_irq_wait(struct drm_device *dev, struct omap_irq_wait *wait,
0061         unsigned long timeout)
0062 {
0063     struct omap_drm_private *priv = dev->dev_private;
0064     unsigned long flags;
0065     int ret;
0066 
0067     ret = wait_event_timeout(wait->wq, (wait->count <= 0), timeout);
0068 
0069     spin_lock_irqsave(&priv->wait_lock, flags);
0070     list_del(&wait->node);
0071     omap_irq_update(dev);
0072     spin_unlock_irqrestore(&priv->wait_lock, flags);
0073 
0074     kfree(wait);
0075 
0076     return ret == 0 ? -1 : 0;
0077 }
0078 
0079 int omap_irq_enable_framedone(struct drm_crtc *crtc, bool enable)
0080 {
0081     struct drm_device *dev = crtc->dev;
0082     struct omap_drm_private *priv = dev->dev_private;
0083     unsigned long flags;
0084     enum omap_channel channel = omap_crtc_channel(crtc);
0085     int framedone_irq =
0086         dispc_mgr_get_framedone_irq(priv->dispc, channel);
0087 
0088     DBG("dev=%p, crtc=%u, enable=%d", dev, channel, enable);
0089 
0090     spin_lock_irqsave(&priv->wait_lock, flags);
0091     if (enable)
0092         priv->irq_mask |= framedone_irq;
0093     else
0094         priv->irq_mask &= ~framedone_irq;
0095     omap_irq_update(dev);
0096     spin_unlock_irqrestore(&priv->wait_lock, flags);
0097 
0098     return 0;
0099 }
0100 
0101 /**
0102  * enable_vblank - enable vblank interrupt events
0103  * @crtc: DRM CRTC
0104  *
0105  * Enable vblank interrupts for @crtc.  If the device doesn't have
0106  * a hardware vblank counter, this routine should be a no-op, since
0107  * interrupts will have to stay on to keep the count accurate.
0108  *
0109  * RETURNS
0110  * Zero on success, appropriate errno if the given @crtc's vblank
0111  * interrupt cannot be enabled.
0112  */
0113 int omap_irq_enable_vblank(struct drm_crtc *crtc)
0114 {
0115     struct drm_device *dev = crtc->dev;
0116     struct omap_drm_private *priv = dev->dev_private;
0117     unsigned long flags;
0118     enum omap_channel channel = omap_crtc_channel(crtc);
0119 
0120     DBG("dev=%p, crtc=%u", dev, channel);
0121 
0122     spin_lock_irqsave(&priv->wait_lock, flags);
0123     priv->irq_mask |= dispc_mgr_get_vsync_irq(priv->dispc,
0124                                  channel);
0125     omap_irq_update(dev);
0126     spin_unlock_irqrestore(&priv->wait_lock, flags);
0127 
0128     return 0;
0129 }
0130 
0131 /**
0132  * disable_vblank - disable vblank interrupt events
0133  * @crtc: DRM CRTC
0134  *
0135  * Disable vblank interrupts for @crtc.  If the device doesn't have
0136  * a hardware vblank counter, this routine should be a no-op, since
0137  * interrupts will have to stay on to keep the count accurate.
0138  */
0139 void omap_irq_disable_vblank(struct drm_crtc *crtc)
0140 {
0141     struct drm_device *dev = crtc->dev;
0142     struct omap_drm_private *priv = dev->dev_private;
0143     unsigned long flags;
0144     enum omap_channel channel = omap_crtc_channel(crtc);
0145 
0146     DBG("dev=%p, crtc=%u", dev, channel);
0147 
0148     spin_lock_irqsave(&priv->wait_lock, flags);
0149     priv->irq_mask &= ~dispc_mgr_get_vsync_irq(priv->dispc,
0150                                   channel);
0151     omap_irq_update(dev);
0152     spin_unlock_irqrestore(&priv->wait_lock, flags);
0153 }
0154 
0155 static void omap_irq_fifo_underflow(struct omap_drm_private *priv,
0156                     u32 irqstatus)
0157 {
0158     static DEFINE_RATELIMIT_STATE(_rs, DEFAULT_RATELIMIT_INTERVAL,
0159                       DEFAULT_RATELIMIT_BURST);
0160     static const struct {
0161         const char *name;
0162         u32 mask;
0163     } sources[] = {
0164         { "gfx", DISPC_IRQ_GFX_FIFO_UNDERFLOW },
0165         { "vid1", DISPC_IRQ_VID1_FIFO_UNDERFLOW },
0166         { "vid2", DISPC_IRQ_VID2_FIFO_UNDERFLOW },
0167         { "vid3", DISPC_IRQ_VID3_FIFO_UNDERFLOW },
0168     };
0169 
0170     const u32 mask = DISPC_IRQ_GFX_FIFO_UNDERFLOW
0171                | DISPC_IRQ_VID1_FIFO_UNDERFLOW
0172                | DISPC_IRQ_VID2_FIFO_UNDERFLOW
0173                | DISPC_IRQ_VID3_FIFO_UNDERFLOW;
0174     unsigned int i;
0175 
0176     spin_lock(&priv->wait_lock);
0177     irqstatus &= priv->irq_mask & mask;
0178     spin_unlock(&priv->wait_lock);
0179 
0180     if (!irqstatus)
0181         return;
0182 
0183     if (!__ratelimit(&_rs))
0184         return;
0185 
0186     DRM_ERROR("FIFO underflow on ");
0187 
0188     for (i = 0; i < ARRAY_SIZE(sources); ++i) {
0189         if (sources[i].mask & irqstatus)
0190             pr_cont("%s ", sources[i].name);
0191     }
0192 
0193     pr_cont("(0x%08x)\n", irqstatus);
0194 }
0195 
0196 static void omap_irq_ocp_error_handler(struct drm_device *dev,
0197     u32 irqstatus)
0198 {
0199     if (!(irqstatus & DISPC_IRQ_OCP_ERR))
0200         return;
0201 
0202     dev_err_ratelimited(dev->dev, "OCP error\n");
0203 }
0204 
0205 static irqreturn_t omap_irq_handler(int irq, void *arg)
0206 {
0207     struct drm_device *dev = (struct drm_device *) arg;
0208     struct omap_drm_private *priv = dev->dev_private;
0209     struct omap_irq_wait *wait, *n;
0210     unsigned long flags;
0211     unsigned int id;
0212     u32 irqstatus;
0213 
0214     irqstatus = dispc_read_irqstatus(priv->dispc);
0215     dispc_clear_irqstatus(priv->dispc, irqstatus);
0216     dispc_read_irqstatus(priv->dispc);  /* flush posted write */
0217 
0218     VERB("irqs: %08x", irqstatus);
0219 
0220     for (id = 0; id < priv->num_pipes; id++) {
0221         struct drm_crtc *crtc = priv->pipes[id].crtc;
0222         enum omap_channel channel = omap_crtc_channel(crtc);
0223 
0224         if (irqstatus & dispc_mgr_get_vsync_irq(priv->dispc, channel)) {
0225             drm_handle_vblank(dev, id);
0226             omap_crtc_vblank_irq(crtc);
0227         }
0228 
0229         if (irqstatus & dispc_mgr_get_sync_lost_irq(priv->dispc, channel))
0230             omap_crtc_error_irq(crtc, irqstatus);
0231 
0232         if (irqstatus & dispc_mgr_get_framedone_irq(priv->dispc, channel))
0233             omap_crtc_framedone_irq(crtc, irqstatus);
0234     }
0235 
0236     omap_irq_ocp_error_handler(dev, irqstatus);
0237     omap_irq_fifo_underflow(priv, irqstatus);
0238 
0239     spin_lock_irqsave(&priv->wait_lock, flags);
0240     list_for_each_entry_safe(wait, n, &priv->wait_list, node) {
0241         if (wait->irqmask & irqstatus)
0242             omap_irq_wait_handler(wait);
0243     }
0244     spin_unlock_irqrestore(&priv->wait_lock, flags);
0245 
0246     return IRQ_HANDLED;
0247 }
0248 
0249 static const u32 omap_underflow_irqs[] = {
0250     [OMAP_DSS_GFX] = DISPC_IRQ_GFX_FIFO_UNDERFLOW,
0251     [OMAP_DSS_VIDEO1] = DISPC_IRQ_VID1_FIFO_UNDERFLOW,
0252     [OMAP_DSS_VIDEO2] = DISPC_IRQ_VID2_FIFO_UNDERFLOW,
0253     [OMAP_DSS_VIDEO3] = DISPC_IRQ_VID3_FIFO_UNDERFLOW,
0254 };
0255 
0256 int omap_drm_irq_install(struct drm_device *dev)
0257 {
0258     struct omap_drm_private *priv = dev->dev_private;
0259     unsigned int num_mgrs = dispc_get_num_mgrs(priv->dispc);
0260     unsigned int max_planes;
0261     unsigned int i;
0262     int ret;
0263 
0264     spin_lock_init(&priv->wait_lock);
0265     INIT_LIST_HEAD(&priv->wait_list);
0266 
0267     priv->irq_mask = DISPC_IRQ_OCP_ERR;
0268 
0269     max_planes = min(ARRAY_SIZE(priv->planes),
0270              ARRAY_SIZE(omap_underflow_irqs));
0271     for (i = 0; i < max_planes; ++i) {
0272         if (priv->planes[i])
0273             priv->irq_mask |= omap_underflow_irqs[i];
0274     }
0275 
0276     for (i = 0; i < num_mgrs; ++i)
0277         priv->irq_mask |= dispc_mgr_get_sync_lost_irq(priv->dispc, i);
0278 
0279     dispc_runtime_get(priv->dispc);
0280     dispc_clear_irqstatus(priv->dispc, 0xffffffff);
0281     dispc_runtime_put(priv->dispc);
0282 
0283     ret = dispc_request_irq(priv->dispc, omap_irq_handler, dev);
0284     if (ret < 0)
0285         return ret;
0286 
0287     priv->irq_enabled = true;
0288 
0289     return 0;
0290 }
0291 
0292 void omap_drm_irq_uninstall(struct drm_device *dev)
0293 {
0294     struct omap_drm_private *priv = dev->dev_private;
0295 
0296     if (!priv->irq_enabled)
0297         return;
0298 
0299     priv->irq_enabled = false;
0300 
0301     dispc_free_irq(priv->dispc, dev);
0302 }