summaryrefslogtreecommitdiff
path: root/drivers
diff options
context:
space:
mode:
authorSebastien Jan <s-jan@ti.com>2011-10-11 16:18:14 +0200
committerSebastien Jan <s-jan@ti.com>2011-10-14 10:42:59 +0200
commita67c0887d1873a3f518b796ddbe124fe633e69a2 (patch)
treec10d4be7a418bd55ba24613d022c77ff37775efd /drivers
parentb3ddef9e85972a09cd5b21828c1ec0109c3d590f (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.c114
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: