diff options
author | Ricardo Perez Olivares <x0081762@ti.com> | 2010-08-26 03:04:26 -0500 |
---|---|---|
committer | Ricardo Perez Olivares <x0081762@ti.com> | 2010-08-26 03:04:26 -0500 |
commit | 08c0945df44856fc8451011333174c1eb64a0169 (patch) | |
tree | ddd8eb5b4726d5f1060daf71c9f7746683156954 /drivers | |
parent | 2f49df977321beb50657a0a8a0a2698e61293330 (diff) | |
parent | 98f6e0d2b5be2afc87eb3954f01e1c6acf311849 (diff) |
Merge branch 'display-next' of git://dev.omapzoom.org/pub/scm/axelcx/kernel-display into L24x9-p2
Diffstat (limited to 'drivers')
-rwxr-xr-x | drivers/video/omap2/dss/core.c | 3 | ||||
-rw-r--r-- | drivers/video/omap2/dss/dispc.c | 7 | ||||
-rw-r--r-- | drivers/video/omap2/dss/display.c | 55 | ||||
-rw-r--r-- | drivers/video/omap2/dss/hdmi.c | 2 | ||||
-rwxr-xr-x | drivers/video/omap2/omapfb/omapfb-main.c | 85 |
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, ¬ifier->notifier); } if (r) |