summaryrefslogtreecommitdiffstats
path: root/drivers/video/omap2/omapfb/omapfb-ioctl.c
diff options
context:
space:
mode:
authorVille Syrjälä <ville.syrjala@nokia.com>2010-03-17 20:36:51 +0200
committerTomi Valkeinen <tomi.valkeinen@nokia.com>2010-08-03 15:18:46 +0300
commit078ff546a806b2c2ab74c25c8edd4c6d4680656a (patch)
treefe988343f6b0038423b637c32e372202a8e5d05a /drivers/video/omap2/omapfb/omapfb-ioctl.c
parent2ad0c50b84ee984aa58b09b46aef5c9f1d95e469 (diff)
downloadblackbird-op-linux-078ff546a806b2c2ab74c25c8edd4c6d4680656a.tar.gz
blackbird-op-linux-078ff546a806b2c2ab74c25c8edd4c6d4680656a.zip
OMAP: DSS2: OMAPFB: Add support for switching memory regions
Separate the memory region from the framebuffer device a little bit. It's now possible to select the memory region used by the framebuffer device using the new mem_idx parameter of omapfb_plane_info. If the mem_idx is specified it will be interpreted as an index into the memory regions array, if it's not specified the framebuffer's index is used instead. So by default each framebuffer keeps using it's own memory region which preserves backwards compatibility. This allows cloning the same memory region to several overlays and yet each overlay can be controlled independently since they can be associated with separate framebuffer devices. Signed-off-by: Ville Syrjälä <ville.syrjala@nokia.com> Signed-off-by: Tomi Valkeinen <tomi.valkeinen@nokia.com>
Diffstat (limited to 'drivers/video/omap2/omapfb/omapfb-ioctl.c')
-rw-r--r--drivers/video/omap2/omapfb/omapfb-ioctl.c125
1 files changed, 102 insertions, 23 deletions
diff --git a/drivers/video/omap2/omapfb/omapfb-ioctl.c b/drivers/video/omap2/omapfb/omapfb-ioctl.c
index 9c7361871d78..6635bd75affa 100644
--- a/drivers/video/omap2/omapfb/omapfb-ioctl.c
+++ b/drivers/video/omap2/omapfb/omapfb-ioctl.c
@@ -34,12 +34,37 @@
#include "omapfb.h"
+static u8 get_mem_idx(struct omapfb_info *ofbi)
+{
+ if (ofbi->id == ofbi->region->id)
+ return 0;
+
+ return OMAPFB_MEM_IDX_ENABLED | ofbi->region->id;
+}
+
+static struct omapfb2_mem_region *get_mem_region(struct omapfb_info *ofbi,
+ u8 mem_idx)
+{
+ struct omapfb2_device *fbdev = ofbi->fbdev;
+
+ if (mem_idx & OMAPFB_MEM_IDX_ENABLED)
+ mem_idx &= OMAPFB_MEM_IDX_MASK;
+ else
+ mem_idx = ofbi->id;
+
+ if (mem_idx >= fbdev->num_fbs)
+ return NULL;
+
+ return &fbdev->regions[mem_idx];
+}
+
static int omapfb_setup_plane(struct fb_info *fbi, struct omapfb_plane_info *pi)
{
struct omapfb_info *ofbi = FB2OFB(fbi);
struct omapfb2_device *fbdev = ofbi->fbdev;
struct omap_overlay *ovl;
- struct omap_overlay_info info;
+ struct omap_overlay_info old_info;
+ struct omapfb2_mem_region *old_rg, *new_rg;
int r = 0;
DBG("omapfb_setup_plane\n");
@@ -52,7 +77,14 @@ static int omapfb_setup_plane(struct fb_info *fbi, struct omapfb_plane_info *pi)
/* XXX uses only the first overlay */
ovl = ofbi->overlays[0];
- if (pi->enabled && !ofbi->region.size) {
+ old_rg = ofbi->region;
+ new_rg = get_mem_region(ofbi, pi->mem_idx);
+ if (!new_rg) {
+ r = -EINVAL;
+ goto out;
+ }
+
+ if (pi->enabled && !new_rg->size) {
/*
* This plane's memory was freed, can't enable it
* until it's reallocated.
@@ -61,27 +93,60 @@ static int omapfb_setup_plane(struct fb_info *fbi, struct omapfb_plane_info *pi)
goto out;
}
- ovl->get_overlay_info(ovl, &info);
+ ovl->get_overlay_info(ovl, &old_info);
- info.pos_x = pi->pos_x;
- info.pos_y = pi->pos_y;
- info.out_width = pi->out_width;
- info.out_height = pi->out_height;
- info.enabled = pi->enabled;
+ if (old_rg != new_rg) {
+ ofbi->region = new_rg;
+ set_fb_fix(fbi);
+ }
- r = ovl->set_overlay_info(ovl, &info);
- if (r)
- goto out;
+ if (pi->enabled) {
+ struct omap_overlay_info info;
+
+ r = omapfb_setup_overlay(fbi, ovl, pi->pos_x, pi->pos_y,
+ pi->out_width, pi->out_height);
+ if (r)
+ goto undo;
- if (ovl->manager) {
- r = ovl->manager->apply(ovl->manager);
+ ovl->get_overlay_info(ovl, &info);
+
+ if (!info.enabled) {
+ info.enabled = pi->enabled;
+ r = ovl->set_overlay_info(ovl, &info);
+ if (r)
+ goto undo;
+ }
+ } else {
+ struct omap_overlay_info info;
+
+ ovl->get_overlay_info(ovl, &info);
+
+ info.enabled = pi->enabled;
+ info.pos_x = pi->pos_x;
+ info.pos_y = pi->pos_y;
+ info.out_width = pi->out_width;
+ info.out_height = pi->out_height;
+
+ r = ovl->set_overlay_info(ovl, &info);
if (r)
- goto out;
+ goto undo;
}
-out:
- if (r)
- dev_err(fbdev->dev, "setup_plane failed\n");
+ if (ovl->manager)
+ ovl->manager->apply(ovl->manager);
+
+ return 0;
+
+ undo:
+ if (old_rg != new_rg) {
+ ofbi->region = old_rg;
+ set_fb_fix(fbi);
+ }
+
+ ovl->set_overlay_info(ovl, &old_info);
+ out:
+ dev_err(fbdev->dev, "setup_plane failed\n");
+
return r;
}
@@ -92,8 +157,8 @@ static int omapfb_query_plane(struct fb_info *fbi, struct omapfb_plane_info *pi)
if (ofbi->num_overlays != 1) {
memset(pi, 0, sizeof(*pi));
} else {
- struct omap_overlay_info *ovli;
struct omap_overlay *ovl;
+ struct omap_overlay_info *ovli;
ovl = ofbi->overlays[0];
ovli = &ovl->info;
@@ -103,6 +168,7 @@ static int omapfb_query_plane(struct fb_info *fbi, struct omapfb_plane_info *pi)
pi->enabled = ovli->enabled;
pi->channel_out = 0; /* xxx */
pi->mirror = 0;
+ pi->mem_idx = get_mem_idx(ofbi);
pi->out_width = ovli->out_width;
pi->out_height = ovli->out_height;
}
@@ -123,11 +189,24 @@ static int omapfb_setup_mem(struct fb_info *fbi, struct omapfb_mem_info *mi)
size = PAGE_ALIGN(mi->size);
- rg = &ofbi->region;
+ rg = ofbi->region;
- for (i = 0; i < ofbi->num_overlays; i++) {
- if (ofbi->overlays[i]->info.enabled)
- return -EBUSY;
+ if (atomic_read(&rg->map_count))
+ return -EBUSY;
+
+ for (i = 0; i < fbdev->num_fbs; i++) {
+ struct omapfb_info *ofbi2 = FB2OFB(fbdev->fbs[i]);
+ int j;
+
+ if (ofbi2->region != rg)
+ continue;
+
+ for (j = 0; j < ofbi2->num_overlays; j++) {
+ if (ofbi2->overlays[j]->info.enabled) {
+ r = -EBUSY;
+ return r;
+ }
+ }
}
if (rg->size != size || rg->type != mi->type) {
@@ -146,7 +225,7 @@ static int omapfb_query_mem(struct fb_info *fbi, struct omapfb_mem_info *mi)
struct omapfb_info *ofbi = FB2OFB(fbi);
struct omapfb2_mem_region *rg;
- rg = &ofbi->region;
+ rg = ofbi->region;
memset(mi, 0, sizeof(*mi));
mi->size = rg->size;
OpenPOWER on IntegriCloud