mirror of https://gitee.com/openkylin/linux.git
omapdrm changes for 5.3
- Add support for DSI command mode displays -----BEGIN PGP SIGNATURE----- iQJKBAABCgA0FiEExDgMPpZe/YEHn/On+j2qjLyWHvUFAlz/X6kWHHRvbWkudmFs a2VpbmVuQHRpLmNvbQAKCRD6PaqMvJYe9SPCEACOABAZy0aOSxCfdIuQjJ4YFL0Q uC3grwklTPuGQPn7cEsibm6ZT3ag0GtQUwYmRcZ6OCeFuTq5dJsJqbjQ2tS3ZVzR JAYRJInXWuJV1zKel238flR0blyVIIJ7BTOxgDOXa5s9Q4L4hy1hI61VkZ7vfZkH g8hdqgAW+EyiwKR8Qv3tlFvJQD0WA5tooC1qx6A8fqM+7jxE61T+RBiKXFhCsH5K 9nxMDGZFlgl9DMzYWcIMPhrCUuHLMGr+RT3KjmStihpkA9eeImzvN1jc//v8Fw9g 8JnIWMLpfo0yIvXQQ3B8RNo6n/ifAf/m0RzTvWtfU0ja4AgA2+820YPg03OHvGg+ OuedPcHGQWIGw4qXHiD+u2+hF7/Loo+09OE5XTms2j5OFMJrCMqgwpy4AMtpTfWk ZsAVoSH0sSKzVjlnyCpZ9QBdlVmk56zR+iVtlK+arsy4zv/O2B2YY+qtUD34AqpY Mi81H9qhYG+G69trZepKUyGyj3WYfwctgBef0O0u6coWkJTWipz3ZO7P7QktDqzi aQg9gJJ+Buh589VgmEHRfjNBuonmy/MTi2QEgM0wtQ4Uh/zqaO1tfuBWFRjK0015 02qfODCl913I2JOqTdQYtav1oIoDv2P0ckMV0Its7IZtgPSXnbMZI28D4UFvf5NU YN/u9wV+2J7u77dRfg== =2i92 -----END PGP SIGNATURE----- Merge tag 'omapdrm-5.3' of git://git.kernel.org/pub/scm/linux/kernel/git/tomba/linux into drm-next omapdrm changes for 5.3 - Add support for DSI command mode displays Signed-off-by: Daniel Vetter <daniel.vetter@ffwll.ch> From: Tomi Valkeinen <tomi.valkeinen@ti.com> Link: https://patchwork.freedesktop.org/patch/msgid/a709f57d-6909-8550-3932-d84e0b5bc3ef@ti.com
This commit is contained in:
commit
561564bea3
|
@ -410,8 +410,7 @@ static const struct backlight_ops dsicm_bl_ops = {
|
|||
static ssize_t dsicm_num_errors_show(struct device *dev,
|
||||
struct device_attribute *attr, char *buf)
|
||||
{
|
||||
struct platform_device *pdev = to_platform_device(dev);
|
||||
struct panel_drv_data *ddata = platform_get_drvdata(pdev);
|
||||
struct panel_drv_data *ddata = dev_get_drvdata(dev);
|
||||
struct omap_dss_device *src = ddata->src;
|
||||
u8 errors = 0;
|
||||
int r;
|
||||
|
@ -442,8 +441,7 @@ static ssize_t dsicm_num_errors_show(struct device *dev,
|
|||
static ssize_t dsicm_hw_revision_show(struct device *dev,
|
||||
struct device_attribute *attr, char *buf)
|
||||
{
|
||||
struct platform_device *pdev = to_platform_device(dev);
|
||||
struct panel_drv_data *ddata = platform_get_drvdata(pdev);
|
||||
struct panel_drv_data *ddata = dev_get_drvdata(dev);
|
||||
struct omap_dss_device *src = ddata->src;
|
||||
u8 id1, id2, id3;
|
||||
int r;
|
||||
|
@ -474,8 +472,7 @@ static ssize_t dsicm_store_ulps(struct device *dev,
|
|||
struct device_attribute *attr,
|
||||
const char *buf, size_t count)
|
||||
{
|
||||
struct platform_device *pdev = to_platform_device(dev);
|
||||
struct panel_drv_data *ddata = platform_get_drvdata(pdev);
|
||||
struct panel_drv_data *ddata = dev_get_drvdata(dev);
|
||||
struct omap_dss_device *src = ddata->src;
|
||||
unsigned long t;
|
||||
int r;
|
||||
|
@ -509,8 +506,7 @@ static ssize_t dsicm_show_ulps(struct device *dev,
|
|||
struct device_attribute *attr,
|
||||
char *buf)
|
||||
{
|
||||
struct platform_device *pdev = to_platform_device(dev);
|
||||
struct panel_drv_data *ddata = platform_get_drvdata(pdev);
|
||||
struct panel_drv_data *ddata = dev_get_drvdata(dev);
|
||||
unsigned int t;
|
||||
|
||||
mutex_lock(&ddata->lock);
|
||||
|
@ -524,8 +520,7 @@ static ssize_t dsicm_store_ulps_timeout(struct device *dev,
|
|||
struct device_attribute *attr,
|
||||
const char *buf, size_t count)
|
||||
{
|
||||
struct platform_device *pdev = to_platform_device(dev);
|
||||
struct panel_drv_data *ddata = platform_get_drvdata(pdev);
|
||||
struct panel_drv_data *ddata = dev_get_drvdata(dev);
|
||||
struct omap_dss_device *src = ddata->src;
|
||||
unsigned long t;
|
||||
int r;
|
||||
|
@ -556,8 +551,7 @@ static ssize_t dsicm_show_ulps_timeout(struct device *dev,
|
|||
struct device_attribute *attr,
|
||||
char *buf)
|
||||
{
|
||||
struct platform_device *pdev = to_platform_device(dev);
|
||||
struct panel_drv_data *ddata = platform_get_drvdata(pdev);
|
||||
struct panel_drv_data *ddata = dev_get_drvdata(dev);
|
||||
unsigned int t;
|
||||
|
||||
mutex_lock(&ddata->lock);
|
||||
|
|
|
@ -198,6 +198,7 @@ static const struct of_device_id omapdss_of_fixups_whitelist[] __initconst = {
|
|||
{ .compatible = "toppoly,td028ttec1" },
|
||||
{ .compatible = "tpo,td028ttec1" },
|
||||
{ .compatible = "tpo,td043mtea1" },
|
||||
{},
|
||||
};
|
||||
|
||||
static int __init omapdss_boot_init(void)
|
||||
|
|
|
@ -32,6 +32,7 @@ struct omap_crtc_state {
|
|||
/* Shadow values for legacy userspace support. */
|
||||
unsigned int rotation;
|
||||
unsigned int zpos;
|
||||
bool manually_updated;
|
||||
};
|
||||
|
||||
#define to_omap_crtc(x) container_of(x, struct omap_crtc, base)
|
||||
|
@ -51,6 +52,10 @@ struct omap_crtc {
|
|||
bool pending;
|
||||
wait_queue_head_t pending_wait;
|
||||
struct drm_pending_vblank_event *event;
|
||||
struct delayed_work update_work;
|
||||
|
||||
void (*framedone_handler)(void *);
|
||||
void *framedone_handler_data;
|
||||
};
|
||||
|
||||
/* -----------------------------------------------------------------------------
|
||||
|
@ -102,21 +107,18 @@ int omap_crtc_wait_pending(struct drm_crtc *crtc)
|
|||
/*
|
||||
* Manager-ops, callbacks from output when they need to configure
|
||||
* the upstream part of the video pipe.
|
||||
*
|
||||
* Most of these we can ignore until we add support for command-mode
|
||||
* panels.. for video-mode the crtc-helpers already do an adequate
|
||||
* job of sequencing the setup of the video pipe in the proper order
|
||||
*/
|
||||
|
||||
/* we can probably ignore these until we support command-mode panels: */
|
||||
static void omap_crtc_dss_start_update(struct omap_drm_private *priv,
|
||||
enum omap_channel channel)
|
||||
{
|
||||
priv->dispc_ops->mgr_enable(priv->dispc, channel, true);
|
||||
}
|
||||
|
||||
/* Called only from the encoder enable/disable and suspend/resume handlers. */
|
||||
static void omap_crtc_set_enabled(struct drm_crtc *crtc, bool enable)
|
||||
{
|
||||
struct omap_crtc_state *omap_state = to_omap_crtc_state(crtc->state);
|
||||
struct drm_device *dev = crtc->dev;
|
||||
struct omap_drm_private *priv = dev->dev_private;
|
||||
struct omap_crtc *omap_crtc = to_omap_crtc(crtc);
|
||||
|
@ -128,6 +130,12 @@ static void omap_crtc_set_enabled(struct drm_crtc *crtc, bool enable)
|
|||
if (WARN_ON(omap_crtc->enabled == enable))
|
||||
return;
|
||||
|
||||
if (omap_state->manually_updated) {
|
||||
omap_irq_enable_framedone(crtc, enable);
|
||||
omap_crtc->enabled = enable;
|
||||
return;
|
||||
}
|
||||
|
||||
if (omap_crtc->pipe->output->type == OMAP_DISPLAY_TYPE_HDMI) {
|
||||
priv->dispc_ops->mgr_enable(priv->dispc, channel, enable);
|
||||
omap_crtc->enabled = enable;
|
||||
|
@ -230,6 +238,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 +257,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 +333,73 @@ 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);
|
||||
}
|
||||
|
||||
void omap_crtc_flush(struct drm_crtc *crtc)
|
||||
{
|
||||
struct omap_crtc *omap_crtc = to_omap_crtc(crtc);
|
||||
struct omap_crtc_state *omap_state = to_omap_crtc_state(crtc->state);
|
||||
|
||||
if (!omap_state->manually_updated)
|
||||
return;
|
||||
|
||||
if (!delayed_work_pending(&omap_crtc->update_work))
|
||||
schedule_delayed_work(&omap_crtc->update_work, 0);
|
||||
}
|
||||
|
||||
static void omap_crtc_manual_display_update(struct work_struct *data)
|
||||
{
|
||||
struct omap_crtc *omap_crtc =
|
||||
container_of(data, struct omap_crtc, update_work.work);
|
||||
struct drm_display_mode *mode = &omap_crtc->pipe->crtc->mode;
|
||||
struct omap_dss_device *dssdev = omap_crtc->pipe->output->next;
|
||||
struct drm_device *dev = omap_crtc->base.dev;
|
||||
const struct omap_dss_driver *dssdrv;
|
||||
int ret;
|
||||
|
||||
if (!dssdev) {
|
||||
dev_err_once(dev->dev, "missing display dssdev!");
|
||||
return;
|
||||
}
|
||||
|
||||
dssdrv = dssdev->driver;
|
||||
if (!dssdrv || !dssdrv->update) {
|
||||
dev_err_once(dev->dev, "missing or incorrect dssdrv!");
|
||||
return;
|
||||
}
|
||||
|
||||
if (dssdrv->sync)
|
||||
dssdrv->sync(dssdev);
|
||||
|
||||
ret = dssdrv->update(dssdev, 0, 0, mode->hdisplay, mode->vdisplay);
|
||||
if (ret < 0) {
|
||||
spin_lock_irq(&dev->event_lock);
|
||||
omap_crtc->pending = false;
|
||||
spin_unlock_irq(&dev->event_lock);
|
||||
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;
|
||||
|
@ -351,12 +449,17 @@ static void omap_crtc_atomic_enable(struct drm_crtc *crtc,
|
|||
{
|
||||
struct omap_drm_private *priv = crtc->dev->dev_private;
|
||||
struct omap_crtc *omap_crtc = to_omap_crtc(crtc);
|
||||
struct omap_crtc_state *omap_state = to_omap_crtc_state(crtc->state);
|
||||
int ret;
|
||||
|
||||
DBG("%s", omap_crtc->name);
|
||||
|
||||
priv->dispc_ops->runtime_get(priv->dispc);
|
||||
|
||||
/* manual updated display will not trigger vsync irq */
|
||||
if (omap_state->manually_updated)
|
||||
return;
|
||||
|
||||
spin_lock_irq(&crtc->dev->event_lock);
|
||||
drm_crtc_vblank_on(crtc);
|
||||
ret = drm_crtc_vblank_get(crtc);
|
||||
|
@ -371,6 +474,7 @@ static void omap_crtc_atomic_disable(struct drm_crtc *crtc,
|
|||
{
|
||||
struct omap_drm_private *priv = crtc->dev->dev_private;
|
||||
struct omap_crtc *omap_crtc = to_omap_crtc(crtc);
|
||||
struct drm_device *dev = crtc->dev;
|
||||
|
||||
DBG("%s", omap_crtc->name);
|
||||
|
||||
|
@ -381,6 +485,11 @@ static void omap_crtc_atomic_disable(struct drm_crtc *crtc,
|
|||
}
|
||||
spin_unlock_irq(&crtc->dev->event_lock);
|
||||
|
||||
cancel_delayed_work(&omap_crtc->update_work);
|
||||
|
||||
if (!omap_crtc_wait_pending(crtc))
|
||||
dev_warn(dev->dev, "manual display update did not finish!");
|
||||
|
||||
drm_crtc_vblank_off(crtc);
|
||||
|
||||
priv->dispc_ops->runtime_put(priv->dispc);
|
||||
|
@ -395,10 +504,20 @@ static enum drm_mode_status omap_crtc_mode_valid(struct drm_crtc *crtc,
|
|||
int r;
|
||||
|
||||
drm_display_mode_to_videomode(mode, &vm);
|
||||
r = priv->dispc_ops->mgr_check_timings(priv->dispc, omap_crtc->channel,
|
||||
|
||||
/*
|
||||
* DSI might not call this, since the supplied mode is not a
|
||||
* valid DISPC mode. DSI will calculate and configure the
|
||||
* proper DISPC mode later.
|
||||
*/
|
||||
if (omap_crtc->pipe->output->next == NULL ||
|
||||
omap_crtc->pipe->output->next->type != OMAP_DISPLAY_TYPE_DSI) {
|
||||
r = priv->dispc_ops->mgr_check_timings(priv->dispc,
|
||||
omap_crtc->channel,
|
||||
&vm);
|
||||
if (r)
|
||||
return r;
|
||||
}
|
||||
|
||||
/* Check for bandwidth limit */
|
||||
if (priv->max_bandwidth) {
|
||||
|
@ -441,6 +560,22 @@ static void omap_crtc_mode_set_nofb(struct drm_crtc *crtc)
|
|||
drm_display_mode_to_videomode(mode, &omap_crtc->vm);
|
||||
}
|
||||
|
||||
static bool omap_crtc_is_manually_updated(struct drm_crtc *crtc)
|
||||
{
|
||||
struct omap_crtc *omap_crtc = to_omap_crtc(crtc);
|
||||
struct omap_dss_device *display = omap_crtc->pipe->output->next;
|
||||
|
||||
if (!display)
|
||||
return false;
|
||||
|
||||
if (display->caps & OMAP_DSS_DISPLAY_CAP_MANUAL_UPDATE) {
|
||||
DBG("detected manually updated display!");
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
static int omap_crtc_atomic_check(struct drm_crtc *crtc,
|
||||
struct drm_crtc_state *state)
|
||||
{
|
||||
|
@ -462,6 +597,9 @@ static int omap_crtc_atomic_check(struct drm_crtc *crtc,
|
|||
/* Mirror new values for zpos and rotation in omap_crtc_state */
|
||||
omap_crtc_state->zpos = pri_state->zpos;
|
||||
omap_crtc_state->rotation = pri_state->rotation;
|
||||
|
||||
/* Check if this CRTC is for a manually updated display */
|
||||
omap_crtc_state->manually_updated = omap_crtc_is_manually_updated(crtc);
|
||||
}
|
||||
|
||||
return 0;
|
||||
|
@ -477,6 +615,7 @@ static void omap_crtc_atomic_flush(struct drm_crtc *crtc,
|
|||
{
|
||||
struct omap_drm_private *priv = crtc->dev->dev_private;
|
||||
struct omap_crtc *omap_crtc = to_omap_crtc(crtc);
|
||||
struct omap_crtc_state *omap_crtc_state = to_omap_crtc_state(crtc->state);
|
||||
int ret;
|
||||
|
||||
if (crtc->state->color_mgmt_changed) {
|
||||
|
@ -501,6 +640,15 @@ static void omap_crtc_atomic_flush(struct drm_crtc *crtc,
|
|||
|
||||
DBG("%s: GO", omap_crtc->name);
|
||||
|
||||
if (omap_crtc_state->manually_updated) {
|
||||
/* send new image for page flips and modeset changes */
|
||||
spin_lock_irq(&crtc->dev->event_lock);
|
||||
omap_crtc_flush(crtc);
|
||||
omap_crtc_arm_event(crtc);
|
||||
spin_unlock_irq(&crtc->dev->event_lock);
|
||||
return;
|
||||
}
|
||||
|
||||
ret = drm_crtc_vblank_get(crtc);
|
||||
WARN_ON(ret != 0);
|
||||
|
||||
|
@ -586,6 +734,7 @@ omap_crtc_duplicate_state(struct drm_crtc *crtc)
|
|||
|
||||
state->zpos = current_state->zpos;
|
||||
state->rotation = current_state->rotation;
|
||||
state->manually_updated = current_state->manually_updated;
|
||||
|
||||
return &state->base;
|
||||
}
|
||||
|
@ -662,6 +811,19 @@ struct drm_crtc *omap_crtc_init(struct drm_device *dev,
|
|||
omap_crtc->channel = channel;
|
||||
omap_crtc->name = channel_names[channel];
|
||||
|
||||
/*
|
||||
* We want to refresh manually updated displays from dirty callback,
|
||||
* which is called quite often (e.g. for each drawn line). This will
|
||||
* be used to do the display update asynchronously to avoid blocking
|
||||
* the rendering process and merges multiple dirty calls into one
|
||||
* update if they arrive very fast. We also call this function for
|
||||
* atomic display updates (e.g. for page flips), which means we do
|
||||
* not need extra locking. Atomic updates should be synchronous, but
|
||||
* need to wait for the framedone interrupt anyways.
|
||||
*/
|
||||
INIT_DELAYED_WORK(&omap_crtc->update_work,
|
||||
omap_crtc_manual_display_update);
|
||||
|
||||
ret = drm_crtc_init_with_planes(dev, crtc, plane, NULL,
|
||||
&omap_crtc_funcs, NULL);
|
||||
if (ret < 0) {
|
||||
|
|
|
@ -41,5 +41,7 @@ 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);
|
||||
void omap_crtc_flush(struct drm_crtc *crtc);
|
||||
|
||||
#endif /* __OMAPDRM_CRTC_H__ */
|
||||
|
|
|
@ -439,20 +439,6 @@ static int ioctl_get_param(struct drm_device *dev, void *data,
|
|||
return 0;
|
||||
}
|
||||
|
||||
static int ioctl_set_param(struct drm_device *dev, void *data,
|
||||
struct drm_file *file_priv)
|
||||
{
|
||||
struct drm_omap_param *args = data;
|
||||
|
||||
switch (args->param) {
|
||||
default:
|
||||
DBG("unknown parameter %lld", args->param);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
#define OMAP_BO_USER_MASK 0x00ffffff /* flags settable by userspace */
|
||||
|
||||
static int ioctl_gem_new(struct drm_device *dev, void *data,
|
||||
|
@ -492,7 +478,7 @@ static int ioctl_gem_info(struct drm_device *dev, void *data,
|
|||
static const struct drm_ioctl_desc ioctls[DRM_COMMAND_END - DRM_COMMAND_BASE] = {
|
||||
DRM_IOCTL_DEF_DRV(OMAP_GET_PARAM, ioctl_get_param,
|
||||
DRM_AUTH | DRM_RENDER_ALLOW),
|
||||
DRM_IOCTL_DEF_DRV(OMAP_SET_PARAM, ioctl_set_param,
|
||||
DRM_IOCTL_DEF_DRV(OMAP_SET_PARAM, drm_invalid_op,
|
||||
DRM_AUTH | DRM_MASTER | DRM_ROOT_ONLY),
|
||||
DRM_IOCTL_DEF_DRV(OMAP_GEM_NEW, ioctl_gem_new,
|
||||
DRM_AUTH | DRM_RENDER_ALLOW),
|
||||
|
|
|
@ -37,8 +37,8 @@
|
|||
#include "omap_irq.h"
|
||||
#include "omap_plane.h"
|
||||
|
||||
#define DBG(fmt, ...) DRM_DEBUG(fmt"\n", ##__VA_ARGS__)
|
||||
#define VERB(fmt, ...) if (0) DRM_DEBUG(fmt, ##__VA_ARGS__) /* verbose debug */
|
||||
#define DBG(fmt, ...) DRM_DEBUG_DRIVER(fmt"\n", ##__VA_ARGS__)
|
||||
#define VERB(fmt, ...) if (0) DRM_DEBUG_DRIVER(fmt, ##__VA_ARGS__) /* verbose debug */
|
||||
|
||||
#define MODULE_NAME "omapdrm"
|
||||
|
||||
|
|
|
@ -66,8 +66,27 @@ struct omap_framebuffer {
|
|||
struct mutex lock;
|
||||
};
|
||||
|
||||
static int omap_framebuffer_dirty(struct drm_framebuffer *fb,
|
||||
struct drm_file *file_priv,
|
||||
unsigned flags, unsigned color,
|
||||
struct drm_clip_rect *clips,
|
||||
unsigned num_clips)
|
||||
{
|
||||
struct drm_crtc *crtc;
|
||||
|
||||
drm_modeset_lock_all(fb->dev);
|
||||
|
||||
drm_for_each_crtc(crtc, fb->dev)
|
||||
omap_crtc_flush(crtc);
|
||||
|
||||
drm_modeset_unlock_all(fb->dev);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static const struct drm_framebuffer_funcs omap_framebuffer_funcs = {
|
||||
.create_handle = drm_gem_fb_create_handle,
|
||||
.dirty = omap_framebuffer_dirty,
|
||||
.destroy = drm_gem_fb_destroy,
|
||||
};
|
||||
|
||||
|
|
|
@ -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…
Reference in New Issue