drm/omap: add framedone interrupt support
This prepares framedone interrupt handling for manual display update support. Acked-by: Pavel Machek <pavel@ucw.cz> Tested-by: Tony Lindgren <tony@atomide.com> Tested-by: Pavel Machek <pavel@ucw.cz> Signed-off-by: Sebastian Reichel <sebastian.reichel@collabora.com> Signed-off-by: Tomi Valkeinen <tomi.valkeinen@ti.com>
This commit is contained in:
parent
ad9df7d91b
commit
47103a80f5
@ -51,6 +51,9 @@ struct omap_crtc {
|
||||
bool pending;
|
||||
wait_queue_head_t pending_wait;
|
||||
struct drm_pending_vblank_event *event;
|
||||
|
||||
void (*framedone_handler)(void *);
|
||||
void *framedone_handler_data;
|
||||
};
|
||||
|
||||
/* -----------------------------------------------------------------------------
|
||||
@ -230,6 +233,18 @@ static int omap_crtc_dss_register_framedone(
|
||||
struct omap_drm_private *priv, enum omap_channel channel,
|
||||
void (*handler)(void *), void *data)
|
||||
{
|
||||
struct drm_crtc *crtc = priv->channels[channel]->crtc;
|
||||
struct omap_crtc *omap_crtc = to_omap_crtc(crtc);
|
||||
struct drm_device *dev = omap_crtc->base.dev;
|
||||
|
||||
if (omap_crtc->framedone_handler)
|
||||
return -EBUSY;
|
||||
|
||||
dev_dbg(dev->dev, "register framedone %s", omap_crtc->name);
|
||||
|
||||
omap_crtc->framedone_handler = handler;
|
||||
omap_crtc->framedone_handler_data = data;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
@ -237,6 +252,17 @@ static void omap_crtc_dss_unregister_framedone(
|
||||
struct omap_drm_private *priv, enum omap_channel channel,
|
||||
void (*handler)(void *), void *data)
|
||||
{
|
||||
struct drm_crtc *crtc = priv->channels[channel]->crtc;
|
||||
struct omap_crtc *omap_crtc = to_omap_crtc(crtc);
|
||||
struct drm_device *dev = omap_crtc->base.dev;
|
||||
|
||||
dev_dbg(dev->dev, "unregister framedone %s", omap_crtc->name);
|
||||
|
||||
WARN_ON(omap_crtc->framedone_handler != handler);
|
||||
WARN_ON(omap_crtc->framedone_handler_data != data);
|
||||
|
||||
omap_crtc->framedone_handler = NULL;
|
||||
omap_crtc->framedone_handler_data = NULL;
|
||||
}
|
||||
|
||||
static const struct dss_mgr_ops mgr_ops = {
|
||||
@ -302,6 +328,28 @@ void omap_crtc_vblank_irq(struct drm_crtc *crtc)
|
||||
DBG("%s: apply done", omap_crtc->name);
|
||||
}
|
||||
|
||||
void omap_crtc_framedone_irq(struct drm_crtc *crtc, uint32_t irqstatus)
|
||||
{
|
||||
struct omap_crtc *omap_crtc = to_omap_crtc(crtc);
|
||||
|
||||
if (!omap_crtc->framedone_handler)
|
||||
return;
|
||||
|
||||
omap_crtc->framedone_handler(omap_crtc->framedone_handler_data);
|
||||
|
||||
spin_lock(&crtc->dev->event_lock);
|
||||
/* Send the vblank event if one has been requested. */
|
||||
if (omap_crtc->event) {
|
||||
drm_crtc_send_vblank_event(crtc, omap_crtc->event);
|
||||
omap_crtc->event = NULL;
|
||||
}
|
||||
omap_crtc->pending = false;
|
||||
spin_unlock(&crtc->dev->event_lock);
|
||||
|
||||
/* Wake up omap_atomic_complete. */
|
||||
wake_up(&omap_crtc->pending_wait);
|
||||
}
|
||||
|
||||
static void omap_crtc_write_crtc_properties(struct drm_crtc *crtc)
|
||||
{
|
||||
struct omap_drm_private *priv = crtc->dev->dev_private;
|
||||
|
@ -41,5 +41,6 @@ struct drm_crtc *omap_crtc_init(struct drm_device *dev,
|
||||
int omap_crtc_wait_pending(struct drm_crtc *crtc);
|
||||
void omap_crtc_error_irq(struct drm_crtc *crtc, u32 irqstatus);
|
||||
void omap_crtc_vblank_irq(struct drm_crtc *crtc);
|
||||
void omap_crtc_framedone_irq(struct drm_crtc *crtc, uint32_t irqstatus);
|
||||
|
||||
#endif /* __OMAPDRM_CRTC_H__ */
|
||||
|
@ -85,6 +85,28 @@ int omap_irq_wait(struct drm_device *dev, struct omap_irq_wait *wait,
|
||||
return ret == 0 ? -1 : 0;
|
||||
}
|
||||
|
||||
int omap_irq_enable_framedone(struct drm_crtc *crtc, bool enable)
|
||||
{
|
||||
struct drm_device *dev = crtc->dev;
|
||||
struct omap_drm_private *priv = dev->dev_private;
|
||||
unsigned long flags;
|
||||
enum omap_channel channel = omap_crtc_channel(crtc);
|
||||
int framedone_irq =
|
||||
priv->dispc_ops->mgr_get_framedone_irq(priv->dispc, channel);
|
||||
|
||||
DBG("dev=%p, crtc=%u, enable=%d", dev, channel, enable);
|
||||
|
||||
spin_lock_irqsave(&priv->wait_lock, flags);
|
||||
if (enable)
|
||||
priv->irq_mask |= framedone_irq;
|
||||
else
|
||||
priv->irq_mask &= ~framedone_irq;
|
||||
omap_irq_update(dev);
|
||||
spin_unlock_irqrestore(&priv->wait_lock, flags);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* enable_vblank - enable vblank interrupt events
|
||||
* @dev: DRM device
|
||||
@ -217,6 +239,9 @@ static irqreturn_t omap_irq_handler(int irq, void *arg)
|
||||
|
||||
if (irqstatus & priv->dispc_ops->mgr_get_sync_lost_irq(priv->dispc, channel))
|
||||
omap_crtc_error_irq(crtc, irqstatus);
|
||||
|
||||
if (irqstatus & priv->dispc_ops->mgr_get_framedone_irq(priv->dispc, channel))
|
||||
omap_crtc_framedone_irq(crtc, irqstatus);
|
||||
}
|
||||
|
||||
omap_irq_ocp_error_handler(dev, irqstatus);
|
||||
|
@ -27,6 +27,7 @@ struct drm_device;
|
||||
struct omap_irq_wait;
|
||||
|
||||
int omap_irq_enable_vblank(struct drm_crtc *crtc);
|
||||
int omap_irq_enable_framedone(struct drm_crtc *crtc, bool enable);
|
||||
void omap_irq_disable_vblank(struct drm_crtc *crtc);
|
||||
void omap_drm_irq_uninstall(struct drm_device *dev);
|
||||
int omap_drm_irq_install(struct drm_device *dev);
|
||||
|
Loading…
x
Reference in New Issue
Block a user