diff options
author | Sebastien Jan <s-jan@ti.com> | 2011-10-11 16:18:14 +0200 |
---|---|---|
committer | Sebastien Jan <s-jan@ti.com> | 2011-10-14 10:42:59 +0200 |
commit | a67c0887d1873a3f518b796ddbe124fe633e69a2 (patch) | |
tree | c10d4be7a418bd55ba24613d022c77ff37775efd /drivers | |
parent | b3ddef9e85972a09cd5b21828c1ec0109c3d590f (diff) |
OMAP: DRM: auto-update mode
Basic auto update mode ported from omapfb implementation.
Signed-off-by: Sebastien Jan <s-jan@ti.com>
Diffstat (limited to 'drivers')
-rw-r--r-- | drivers/staging/omapdrm/omap_connector.c | 114 |
1 files changed, 114 insertions, 0 deletions
diff --git a/drivers/staging/omapdrm/omap_connector.c b/drivers/staging/omapdrm/omap_connector.c index ee067520ca13..7bd23ada44c2 100644 --- a/drivers/staging/omapdrm/omap_connector.c +++ b/drivers/staging/omapdrm/omap_connector.c @@ -33,8 +33,16 @@ struct omap_connector { struct drm_connector base; struct omap_dss_device *dssdev; struct drm_display_mode *native_mode; + bool auto_update_work_enabled; + struct delayed_work auto_update_work; + struct workqueue_struct *auto_update_wq; }; +static bool auto_update = 1; +static unsigned int auto_update_freq; +module_param(auto_update, bool, 0); +module_param(auto_update_freq, uint, 0644); + static inline void copy_timings_omap_to_drm(struct drm_display_mode *mode, struct omap_video_timings *timings) { @@ -104,11 +112,16 @@ enum drm_connector_status omap_connector_detect( return ret; } +void omap_connector_stop_auto_update(struct omap_connector *oconnect); + static void omap_connector_destroy(struct drm_connector *connector) { struct omap_connector *omap_connector = to_omap_connector(connector); struct omap_dss_device *dssdev = omap_connector->dssdev; + if (omap_connector->auto_update_work_enabled) + omap_connector_stop_auto_update(omap_connector); + dssdev->driver->disable(dssdev); DBG("%s", omap_connector->dssdev->name); @@ -387,6 +400,76 @@ void omap_connector_mode_set(struct drm_connector *connector, dssdrv->set_timings(dssdev, &timings); } +static void omap_connector_auto_update_work(struct work_struct *work) +{ + struct omap_dss_device *dssdev; + struct omap_dss_driver *dssdrv; + struct omap_connector *d; + u16 w, h; + unsigned int freq; + + d = container_of(work, struct omap_connector, + auto_update_work.work); + + dssdev = d->dssdev; + dssdrv = dssdev->driver; + + if (!dssdrv || !dssdrv->update) + return; + + if (dssdrv->sync) + dssdrv->sync(dssdev); + + dssdrv->get_resolution(dssdev, &w, &h); + dssdrv->update(dssdev, 0, 0, w, h); + + DBG("%s", dssdev->name); + freq = auto_update_freq; + if (freq == 0) + freq = 20; + queue_delayed_work(d->auto_update_wq, + &d->auto_update_work, HZ / freq); +} + +void omap_connector_start_auto_update(struct omap_connector *oconnect, + struct omap_dss_device *display) +{ + DBG("%s", oconnect->dssdev->name); + if (oconnect->auto_update_wq == NULL) { + struct workqueue_struct *wq; + + wq = create_singlethread_workqueue("omapfb_auto_update"); + + if (wq == NULL) { + dev_err(&oconnect->dssdev->dev, "Failed to create workqueue for " + "auto-update\n"); + return; + } + + oconnect->auto_update_wq = wq; + } + + INIT_DELAYED_WORK(&oconnect->auto_update_work, omap_connector_auto_update_work); + + oconnect->auto_update_work_enabled = true; + + omap_connector_auto_update_work(&oconnect->auto_update_work.work); +} + +void omap_connector_stop_auto_update(struct omap_connector *oconnect) +{ + DBG(""); + cancel_delayed_work_sync(&oconnect->auto_update_work); + + oconnect->auto_update_work_enabled = false; + + if (oconnect->auto_update_wq != NULL) { + flush_workqueue(oconnect->auto_update_wq); + destroy_workqueue(oconnect->auto_update_wq); + oconnect->auto_update_wq = NULL; + } +} + enum omap_dss_update_mode omap_connector_get_update_mode( struct drm_connector *connector) { @@ -421,6 +504,30 @@ int omap_connector_set_update_mode(struct drm_connector *connector, } EXPORT_SYMBOL(omap_connector_set_update_mode); +/*static struct device_attribute omap_connector_attrs[] = { + __ATTR(auto_update, S_IRUGO | S_IWUSR, show_auto_update, store_auto_update), + __ATTR(auto_update_freq, S_IRUGO | S_IWUSR, show_upd_freq, store_upd_freq), +}; + +int omap_connector_create_sysfs(struct omap_connector *oconnect) +{ + int i; + int r, t; + + DBG("%s\n", oconnect->dssdev->name); + for (t = 0; t < ARRAY_SIZE(omap_connector_attrs); t++) { + r = device_create_file(oconnect->dssdev->dev, omap_connector_attrs); + if (r) { + dev_err(oconnect->dev, "failed to create sysfs " + "files\n"); + return r; + } + } + + return 0; +} +*/ + int omap_connector_sync(struct drm_connector *connector) { struct omap_connector *omap_connector = to_omap_connector(connector); @@ -506,6 +613,13 @@ struct drm_connector * omap_connector_init(struct drm_device *dev, break; } + if (auto_update) { + if (dssdev->caps & OMAP_DSS_DISPLAY_CAP_MANUAL_UPDATE) + omap_connector_start_auto_update(omap_connector, dssdev); + else + DBG("non-manual update device: %s", dssdev->name); + } + return connector; fail: |