Skip to content

Commit

Permalink
OMAP: DSS2: OMAPFB: Add support for switching memory regions
Browse files Browse the repository at this point in the history
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>
  • Loading branch information
Ville Syrjälä authored and Tomi Valkeinen committed Aug 3, 2010
1 parent 2ad0c50 commit 078ff54
Show file tree
Hide file tree
Showing 5 changed files with 183 additions and 64 deletions.
125 changes: 102 additions & 23 deletions drivers/video/omap2/omapfb/omapfb-ioctl.c
Original file line number Diff line number Diff line change
Expand Up @@ -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");
Expand All @@ -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.
Expand All @@ -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;
}

Expand All @@ -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;
Expand All @@ -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;
}
Expand All @@ -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) {
Expand All @@ -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;
Expand Down
Loading

0 comments on commit 078ff54

Please sign in to comment.