summaryrefslogtreecommitdiff
path: root/drivers
diff options
context:
space:
mode:
authorRicardo Perez Olivares <x0081762@ti.com>2010-08-26 03:04:26 -0500
committerRicardo Perez Olivares <x0081762@ti.com>2010-08-26 03:04:26 -0500
commit08c0945df44856fc8451011333174c1eb64a0169 (patch)
treeddd8eb5b4726d5f1060daf71c9f7746683156954 /drivers
parent2f49df977321beb50657a0a8a0a2698e61293330 (diff)
parent98f6e0d2b5be2afc87eb3954f01e1c6acf311849 (diff)
Merge branch 'display-next' of git://dev.omapzoom.org/pub/scm/axelcx/kernel-display into L24x9-p2
Diffstat (limited to 'drivers')
-rwxr-xr-xdrivers/video/omap2/dss/core.c3
-rw-r--r--drivers/video/omap2/dss/dispc.c7
-rw-r--r--drivers/video/omap2/dss/display.c55
-rw-r--r--drivers/video/omap2/dss/hdmi.c2
-rwxr-xr-xdrivers/video/omap2/omapfb/omapfb-main.c85
5 files changed, 120 insertions, 32 deletions
diff --git a/drivers/video/omap2/dss/core.c b/drivers/video/omap2/dss/core.c
index 00f68cb5f293..854be93f4c4a 100755
--- a/drivers/video/omap2/dss/core.c
+++ b/drivers/video/omap2/dss/core.c
@@ -1111,6 +1111,9 @@ int omap_dss_register_device(struct omap_dss_device *dssdev)
dssdev->dev.parent = &dss_bus;
dssdev->dev.release = omap_dss_dev_release;
dev_set_name(&dssdev->dev, "display%d", dev_num++);
+
+ BLOCKING_INIT_NOTIFIER_HEAD(&dssdev->notifier);
+
return device_register(&dssdev->dev);
}
diff --git a/drivers/video/omap2/dss/dispc.c b/drivers/video/omap2/dss/dispc.c
index 5591a04860f1..47816a96358c 100644
--- a/drivers/video/omap2/dss/dispc.c
+++ b/drivers/video/omap2/dss/dispc.c
@@ -4333,10 +4333,7 @@ static void dispc_error_worker(struct work_struct *work)
if (errors & DISPC_IRQ_SYNC_LOST_DIGIT) {
- DSSERR("SYNC_LOST_DIGIT\n");
-/*commenting below code as with 1080P Decode we see a sync lost digit for
-first frame as it takes long time to decode but it later recovers*/
-#if 0
+ DSSERR("SYNC_LOST_DIGIT\n");
struct omap_overlay_manager *manager = NULL;
bool enable = false;
@@ -4374,7 +4371,7 @@ first frame as it takes long time to decode but it later recovers*/
if (enable)
dssdev->driver->enable(dssdev);
}
-#endif
+
}
if (errors & DISPC_IRQ_OCP_ERR) {
diff --git a/drivers/video/omap2/dss/display.c b/drivers/video/omap2/dss/display.c
index 94e4ce0d7450..443cf1109d3b 100644
--- a/drivers/video/omap2/dss/display.c
+++ b/drivers/video/omap2/dss/display.c
@@ -709,44 +709,47 @@ EXPORT_SYMBOL(omap_dss_stop_device);
/* since omap_dss_update_size can be called in irq context, schedule work from
* work-queue to deliver notification to client..
*/
-struct update_size_work {
+struct notify_work {
struct work_struct work;
struct omap_dss_device *dssdev;
- int w, h;
+ enum omap_dss_event evt;
};
-static void update_size_worker(struct work_struct *work)
+static void notify_worker(struct work_struct *work)
{
- struct update_size_work *usw =
- container_of(work, struct update_size_work, work);
- if (usw->dssdev->size_notify) {
- usw->dssdev->size_notify(usw->dssdev->size_notify_arg, usw->w, usw->h);
- }
+ struct notify_work *nw =
+ container_of(work, struct notify_work, work);
+ struct omap_dss_device *dssdev = nw->dssdev;
+ blocking_notifier_call_chain(&dssdev->notifier, nw->evt, dssdev);
kfree(work);
}
/**
- * Called by lower level driver to notify about a change in resolution, for
- * example in response to a hot-plug event..
+ * Called by lower level driver to notify about a change in resolution, etc.
*/
-void omap_dss_update_size(struct omap_dss_device *dssdev, int w, int h)
-{
- struct update_size_work *usw =
- kmalloc(sizeof(struct update_size_work), GFP_KERNEL);
- if (usw) {
- INIT_WORK(&usw->work, update_size_worker);
- usw->dssdev = dssdev;
- usw->w = w;
- usw->h = h;
- schedule_work(&usw->work);
+void omap_dss_notify(struct omap_dss_device *dssdev, enum omap_dss_event evt)
+{
+ struct notify_work *nw =
+ kmalloc(sizeof(struct notify_work), GFP_KERNEL);
+ if (nw) {
+ INIT_WORK(&nw->work, notify_worker);
+ nw->dssdev = dssdev;
+ nw->evt = evt;
+ schedule_work(&nw->work);
}
}
-EXPORT_SYMBOL(omap_dss_update_size);
+EXPORT_SYMBOL(omap_dss_notify);
+
+void omap_dss_add_notify(struct omap_dss_device *dssdev,
+ struct notifier_block *nb)
+{
+ blocking_notifier_chain_register(&dssdev->notifier, nb);
+}
+EXPORT_SYMBOL(omap_dss_add_notify);
-void omap_dss_set_size_notify(struct omap_dss_device *dssdev,
- void (*notify)(void *arg, int w, int h), void *arg)
+void omap_dss_remove_notify(struct omap_dss_device *dssdev,
+ struct notifier_block *nb)
{
- dssdev->size_notify_arg = arg;
- dssdev->size_notify = notify;
+ blocking_notifier_chain_unregister(&dssdev->notifier, nb);
}
-EXPORT_SYMBOL(omap_dss_set_size_notify);
+EXPORT_SYMBOL(omap_dss_remove_notify);
diff --git a/drivers/video/omap2/dss/hdmi.c b/drivers/video/omap2/dss/hdmi.c
index 04e16033d175..b820f4d30eeb 100644
--- a/drivers/video/omap2/dss/hdmi.c
+++ b/drivers/video/omap2/dss/hdmi.c
@@ -705,7 +705,7 @@ static int hdmi_power_on(struct omap_dss_device *dssdev)
dispc_enable_digit_out(0);
if (dirty) {
- omap_dss_update_size(dssdev, p->x_res, p->y_res);
+ omap_dss_notify(dssdev, OMAP_DSS_SIZE_CHANGE);
}
/* config the PLL and PHY first */
diff --git a/drivers/video/omap2/omapfb/omapfb-main.c b/drivers/video/omap2/omapfb/omapfb-main.c
index 9144538092fa..0529bd29c7dd 100755
--- a/drivers/video/omap2/omapfb/omapfb-main.c
+++ b/drivers/video/omap2/omapfb/omapfb-main.c
@@ -29,6 +29,7 @@
#include <linux/device.h>
#include <linux/platform_device.h>
#include <linux/omapfb.h>
+#include <linux/console.h>
#include <plat/display.h>
#include <plat/vram.h>
@@ -2006,6 +2007,84 @@ static void omapfb_free_resources(struct omapfb2_device *fbdev)
kfree(fbdev);
}
+static void size_notify(struct fb_info *fbi, int w, int h)
+{
+ struct fb_var_screeninfo var = fbi->var;
+ struct fb_var_screeninfo saved_var = fbi->var;
+ int orig_flags;
+
+ DBG("size_notify: %dx%d\n", w, h);
+
+ var.activate |= FB_ACTIVATE_FORCE | FB_ACTIVATE_ALL | FB_ACTIVATE_NOW;
+ var.xres = w;
+ var.yres = h;
+ var.xres_virtual = w;
+ var.yres_virtual = h;
+
+ acquire_console_sem();
+
+ /* this ensures fbdev clients, like the console driver, get notified about
+ * the change:
+ */
+ orig_flags = fbi->flags;
+ fbi->flags |= FBINFO_MISC_USEREVENT;
+ fb_set_var(fbi, &var);
+ fbi->flags &= ~FBINFO_MISC_USEREVENT;
+
+ /* now delete old mode:
+ */
+ saved_var.activate |= FB_ACTIVATE_INV_MODE;
+ fbi->flags |= FBINFO_MISC_USEREVENT;
+ fb_set_var(fbi, &saved_var);
+ fbi->flags = orig_flags;
+
+ release_console_sem();
+}
+
+struct omapfb_notifier_block {
+ struct notifier_block notifier;
+ struct omapfb2_device *fbdev;
+};
+
+static int omapfb_notifier(struct notifier_block *nb,
+ unsigned long evt, void *arg)
+{
+ struct omapfb_notifier_block *notifier =
+ container_of(nb, struct omapfb_notifier_block, notifier);
+ struct omap_dss_device *dssdev = arg;
+ struct omapfb2_device *fbdev = notifier->fbdev;
+ int keep = false;
+ int i;
+
+ /* figure out if this event pertains to this omapfb device:
+ */
+ for (i = 0; i < fbdev->num_managers; i++) {
+ if (fbdev->managers[i]->device == dssdev) {
+ keep = true;
+ break;
+ }
+ }
+
+ if (!keep)
+ return NOTIFY_DONE;
+
+ /* the event pertains to us.. see if we care:
+ */
+ switch (evt) {
+ case OMAP_DSS_SIZE_CHANGE: {
+ u16 w, h;
+ dssdev->driver->get_resolution(dssdev, &w, &h);
+ for (i = 0; i < fbdev->num_fbs; i++)
+ size_notify(fbdev->fbs[i], w, h);
+ break;
+ }
+ default: /* don't care about other events for now */
+ break;
+ }
+
+ return NOTIFY_OK;
+}
+
static int omapfb_create_framebuffers(struct omapfb2_device *fbdev)
{
int r, i;
@@ -2324,6 +2403,7 @@ static int omapfb_probe(struct platform_device *pdev)
fbdev->num_displays = 0;
dssdev = NULL;
for_each_dss_dev(dssdev) {
+ struct omapfb_notifier_block *notifier;
omap_dss_get_device(dssdev);
if (!dssdev->driver) {
@@ -2332,6 +2412,11 @@ static int omapfb_probe(struct platform_device *pdev)
}
fbdev->displays[fbdev->num_displays++] = dssdev;
+
+ notifier = kzalloc(sizeof(struct omapfb_notifier_block), GFP_KERNEL);
+ notifier->notifier.notifier_call = omapfb_notifier;
+ notifier->fbdev = fbdev;
+ omap_dss_add_notify(dssdev, &notifier->notifier);
}
if (r)