static unsigned omapfb_get_vrfb_offset(const struct omapfb_info *ofbi, int rot)
{
- const struct vrfb *vrfb = &ofbi->region.vrfb;
+ const struct vrfb *vrfb = &ofbi->region->vrfb;
unsigned offset;
switch (rot) {
static u32 omapfb_get_region_rot_paddr(const struct omapfb_info *ofbi, int rot)
{
if (ofbi->rotation_type == OMAP_DSS_ROT_VRFB) {
- return ofbi->region.vrfb.paddr[rot]
+ return ofbi->region->vrfb.paddr[rot]
+ omapfb_get_vrfb_offset(ofbi, rot);
} else {
- return ofbi->region.paddr;
+ return ofbi->region->paddr;
}
}
static u32 omapfb_get_region_paddr(const struct omapfb_info *ofbi)
{
if (ofbi->rotation_type == OMAP_DSS_ROT_VRFB)
- return ofbi->region.vrfb.paddr[0];
+ return ofbi->region->vrfb.paddr[0];
else
- return ofbi->region.paddr;
+ return ofbi->region->paddr;
}
static void __iomem *omapfb_get_region_vaddr(const struct omapfb_info *ofbi)
{
if (ofbi->rotation_type == OMAP_DSS_ROT_VRFB)
- return ofbi->region.vrfb.vaddr[0];
+ return ofbi->region->vrfb.vaddr[0];
else
- return ofbi->region.vaddr;
+ return ofbi->region->vaddr;
}
static struct omapfb_colormode omapfb_colormodes[] = {
static int check_fb_size(const struct omapfb_info *ofbi,
struct fb_var_screeninfo *var)
{
- unsigned long max_frame_size = ofbi->region.size;
+ unsigned long max_frame_size = ofbi->region->size;
int bytespp = var->bits_per_pixel >> 3;
unsigned long line_size = var->xres_virtual * bytespp;
static int setup_vrfb_rotation(struct fb_info *fbi)
{
struct omapfb_info *ofbi = FB2OFB(fbi);
- struct omapfb2_mem_region *rg = &ofbi->region;
+ struct omapfb2_mem_region *rg = ofbi->region;
struct vrfb *vrfb = &rg->vrfb;
struct fb_var_screeninfo *var = &fbi->var;
struct fb_fix_screeninfo *fix = &fbi->fix;
return r;
/* used by open/write in fbmem.c */
- fbi->screen_base = ofbi->region.vrfb.vaddr[0];
+ fbi->screen_base = ofbi->region->vrfb.vaddr[0];
- fix->smem_start = ofbi->region.vrfb.paddr[0];
+ fix->smem_start = ofbi->region->vrfb.paddr[0];
switch (var->nonstd) {
case OMAPFB_COLOR_YUV422:
struct fb_fix_screeninfo *fix = &fbi->fix;
struct fb_var_screeninfo *var = &fbi->var;
struct omapfb_info *ofbi = FB2OFB(fbi);
- struct omapfb2_mem_region *rg = &ofbi->region;
+ struct omapfb2_mem_region *rg = ofbi->region;
DBG("set_fb_fix\n");
DBG("check_fb_var %d\n", ofbi->id);
- if (ofbi->region.size == 0)
- return 0;
+ WARN_ON(!atomic_read(&ofbi->region->lock_count));
r = fb_mode_to_dss_mode(var, &mode);
if (r) {
}
}
- if (var->rotate < 0 || var->rotate > 3)
+ if (var->rotate > 3)
return -EINVAL;
if (check_fb_res_bounds(var))
return -EINVAL;
- if (check_fb_size(ofbi, var))
+ /* When no memory is allocated ignore the size check */
+ if (ofbi->region->size != 0 && check_fb_size(ofbi, var))
return -EINVAL;
if (var->xres + var->xoffset > var->xres_virtual)
return offset;
}
+static void omapfb_calc_addr(const struct omapfb_info *ofbi,
+ const struct fb_var_screeninfo *var,
+ const struct fb_fix_screeninfo *fix,
+ int rotation, u32 *paddr, void __iomem **vaddr)
+{
+ u32 data_start_p;
+ void __iomem *data_start_v;
+ int offset;
+
+ if (ofbi->rotation_type == OMAP_DSS_ROT_VRFB) {
+ data_start_p = omapfb_get_region_rot_paddr(ofbi, rotation);
+ data_start_v = NULL;
+ } else {
+ data_start_p = omapfb_get_region_paddr(ofbi);
+ data_start_v = omapfb_get_region_vaddr(ofbi);
+ }
+
+ if (ofbi->rotation_type == OMAP_DSS_ROT_VRFB)
+ offset = calc_rotation_offset_vrfb(var, fix, rotation);
+ else
+ offset = calc_rotation_offset_dma(var, fix, rotation);
+
+ data_start_p += offset;
+ data_start_v += offset;
+
+ if (offset)
+ DBG("offset %d, %d = %d\n",
+ var->xoffset, var->yoffset, offset);
+
+ DBG("paddr %x, vaddr %p\n", data_start_p, data_start_v);
+
+ *paddr = data_start_p;
+ *vaddr = data_start_v;
+}
/* setup overlay according to the fb */
-static int omapfb_setup_overlay(struct fb_info *fbi, struct omap_overlay *ovl,
+int omapfb_setup_overlay(struct fb_info *fbi, struct omap_overlay *ovl,
u16 posx, u16 posy, u16 outw, u16 outh)
{
int r = 0;
struct fb_var_screeninfo *var = &fbi->var;
struct fb_fix_screeninfo *fix = &fbi->fix;
enum omap_color_mode mode = 0;
- int offset;
- u32 data_start_p;
- void __iomem *data_start_v;
+ u32 data_start_p = 0;
+ void __iomem *data_start_v = NULL;
struct omap_overlay_info info;
int xres, yres;
int screen_width;
int rotation = var->rotate;
int i;
+ WARN_ON(!atomic_read(&ofbi->region->lock_count));
+
for (i = 0; i < ofbi->num_overlays; i++) {
if (ovl != ofbi->overlays[i])
continue;
yres = var->yres;
}
-
- if (ofbi->rotation_type == OMAP_DSS_ROT_VRFB) {
- data_start_p = omapfb_get_region_rot_paddr(ofbi, rotation);
- data_start_v = NULL;
- } else {
- data_start_p = omapfb_get_region_paddr(ofbi);
- data_start_v = omapfb_get_region_vaddr(ofbi);
- }
-
- if (ofbi->rotation_type == OMAP_DSS_ROT_VRFB)
- offset = calc_rotation_offset_vrfb(var, fix, rotation);
- else
- offset = calc_rotation_offset_dma(var, fix, rotation);
-
- data_start_p += offset;
- data_start_v += offset;
-
- if (offset)
- DBG("offset %d, %d = %d\n",
- var->xoffset, var->yoffset, offset);
-
- DBG("paddr %x, vaddr %p\n", data_start_p, data_start_v);
+ if (ofbi->region->size)
+ omapfb_calc_addr(ofbi, var, fix, rotation,
+ &data_start_p, &data_start_v);
r = fb_mode_to_dss_mode(var, &mode);
if (r) {
fill_fb(fbi);
#endif
+ WARN_ON(!atomic_read(&ofbi->region->lock_count));
+
for (i = 0; i < ofbi->num_overlays; i++) {
ovl = ofbi->overlays[i];
DBG("apply_changes, fb %d, ovl %d\n", ofbi->id, ovl->id);
- if (ofbi->region.size == 0) {
+ if (ofbi->region->size == 0) {
/* the fb is not available. disable the overlay */
omapfb_overlay_enable(ovl, 0);
if (!init && ovl->manager)
* DO NOT MODIFY PAR */
static int omapfb_check_var(struct fb_var_screeninfo *var, struct fb_info *fbi)
{
+ struct omapfb_info *ofbi = FB2OFB(fbi);
int r;
DBG("check_var(%d)\n", FB2OFB(fbi)->id);
+ omapfb_get_mem_region(ofbi->region);
+
r = check_fb_var(fbi, var);
+ omapfb_put_mem_region(ofbi->region);
+
return r;
}
/* set the video mode according to info->var */
static int omapfb_set_par(struct fb_info *fbi)
{
+ struct omapfb_info *ofbi = FB2OFB(fbi);
int r;
DBG("set_par(%d)\n", FB2OFB(fbi)->id);
+ omapfb_get_mem_region(ofbi->region);
+
set_fb_fix(fbi);
r = setup_vrfb_rotation(fbi);
if (r)
- return r;
+ goto out;
r = omapfb_apply_changes(fbi, 0);
+ out:
+ omapfb_put_mem_region(ofbi->region);
+
return r;
}
static int omapfb_pan_display(struct fb_var_screeninfo *var,
struct fb_info *fbi)
{
+ struct omapfb_info *ofbi = FB2OFB(fbi);
struct fb_var_screeninfo new_var;
int r;
fbi->var = new_var;
+ omapfb_get_mem_region(ofbi->region);
+
r = omapfb_apply_changes(fbi, 0);
+ omapfb_put_mem_region(ofbi->region);
+
return r;
}
static void mmap_user_open(struct vm_area_struct *vma)
{
- struct omapfb_info *ofbi = (struct omapfb_info *)vma->vm_private_data;
+ struct omapfb2_mem_region *rg = vma->vm_private_data;
- atomic_inc(&ofbi->map_count);
+ omapfb_get_mem_region(rg);
+ atomic_inc(&rg->map_count);
+ omapfb_put_mem_region(rg);
}
static void mmap_user_close(struct vm_area_struct *vma)
{
- struct omapfb_info *ofbi = (struct omapfb_info *)vma->vm_private_data;
+ struct omapfb2_mem_region *rg = vma->vm_private_data;
- atomic_dec(&ofbi->map_count);
+ omapfb_get_mem_region(rg);
+ atomic_dec(&rg->map_count);
+ omapfb_put_mem_region(rg);
}
static struct vm_operations_struct mmap_user_ops = {
{
struct omapfb_info *ofbi = FB2OFB(fbi);
struct fb_fix_screeninfo *fix = &fbi->fix;
+ struct omapfb2_mem_region *rg;
unsigned long off;
unsigned long start;
u32 len;
+ int r = -EINVAL;
if (vma->vm_end - vma->vm_start == 0)
return 0;
return -EINVAL;
off = vma->vm_pgoff << PAGE_SHIFT;
+ rg = omapfb_get_mem_region(ofbi->region);
+
start = omapfb_get_region_paddr(ofbi);
len = fix->smem_len;
if (off >= len)
- return -EINVAL;
+ goto error;
if ((vma->vm_end - vma->vm_start + off) > len)
- return -EINVAL;
+ goto error;
off += start;
vma->vm_flags |= VM_IO | VM_RESERVED;
vma->vm_page_prot = pgprot_writecombine(vma->vm_page_prot);
vma->vm_ops = &mmap_user_ops;
- vma->vm_private_data = ofbi;
+ vma->vm_private_data = rg;
if (io_remap_pfn_range(vma, vma->vm_start, off >> PAGE_SHIFT,
- vma->vm_end - vma->vm_start, vma->vm_page_prot))
- return -EAGAIN;
+ vma->vm_end - vma->vm_start,
+ vma->vm_page_prot)) {
+ r = -EAGAIN;
+ goto error;
+ }
+
/* vm_ops.open won't be called for mmap itself. */
- atomic_inc(&ofbi->map_count);
+ atomic_inc(&rg->map_count);
+
+ omapfb_put_mem_region(rg);
+
return 0;
+
+ error:
+ omapfb_put_mem_region(ofbi->region);
+
+ return r;
}
/* Store a single color palette entry into a pseudo palette or the hardware
if (r != 0)
break;
- if (regno < 0) {
- r = -EINVAL;
- break;
- }
-
if (regno < 16) {
u16 pal;
pal = ((red >> (16 - var->red.length)) <<
int do_update = 0;
int r = 0;
+ if (!display)
+ return -EINVAL;
+
omapfb_lock(fbdev);
switch (blank) {
struct omapfb2_device *fbdev = ofbi->fbdev;
struct omapfb2_mem_region *rg;
- rg = &ofbi->region;
+ rg = ofbi->region;
+
+ WARN_ON(atomic_read(&rg->map_count));
if (rg->paddr)
if (omap_vram_free(rg->paddr, rg->size))
void __iomem *vaddr;
int r;
- rg = &ofbi->region;
- memset(rg, 0, sizeof(*rg));
+ rg = ofbi->region;
+
+ rg->paddr = 0;
+ rg->vaddr = NULL;
+ memset(&rg->vrfb, 0, sizeof rg->vrfb);
+ rg->size = 0;
+ rg->type = 0;
+ rg->alloc = false;
+ rg->map = false;
size = PAGE_ALIGN(size);
for (i = 0; i < fbdev->num_fbs; i++) {
struct omapfb_info *ofbi = FB2OFB(fbdev->fbs[i]);
struct omapfb2_mem_region *rg;
- rg = &ofbi->region;
+ rg = ofbi->region;
DBG("region%d phys %08x virt %p size=%lu\n",
i,
struct omapfb_info *ofbi = FB2OFB(fbi);
struct omapfb2_device *fbdev = ofbi->fbdev;
struct omap_dss_device *display = fb2display(fbi);
- struct omapfb2_mem_region *rg = &ofbi->region;
+ struct omapfb2_mem_region *rg = ofbi->region;
unsigned long old_size = rg->size;
unsigned long old_paddr = rg->paddr;
int old_type = rg->type;
fbi->flags = FBINFO_FLAG_DEFAULT;
fbi->pseudo_palette = fbdev->pseudo_palette;
- if (ofbi->region.size == 0) {
+ if (ofbi->region->size == 0) {
clear_fb_info(fbi);
return 0;
}
ofbi->fbdev = fbdev;
ofbi->id = i;
+ ofbi->region = &fbdev->regions[i];
+ ofbi->region->id = i;
+ init_rwsem(&ofbi->region->lock);
+
/* assign these early, so that fb alloc can use them */
ofbi->rotation_type = def_vrfb ? OMAP_DSS_ROT_VRFB :
OMAP_DSS_ROT_DMA;
/* setup fb_infos */
for (i = 0; i < fbdev->num_fbs; i++) {
- r = omapfb_fb_init(fbdev, fbdev->fbs[i]);
+ struct fb_info *fbi = fbdev->fbs[i];
+ struct omapfb_info *ofbi = FB2OFB(fbi);
+
+ omapfb_get_mem_region(ofbi->region);
+ r = omapfb_fb_init(fbdev, fbi);
+ omapfb_put_mem_region(ofbi->region);
+
if (r) {
dev_err(fbdev->dev, "failed to setup fb_info\n");
return r;
DBG("framebuffers registered\n");
for (i = 0; i < fbdev->num_fbs; i++) {
- r = omapfb_apply_changes(fbdev->fbs[i], 1);
+ struct fb_info *fbi = fbdev->fbs[i];
+ struct omapfb_info *ofbi = FB2OFB(fbi);
+
+ omapfb_get_mem_region(ofbi->region);
+ r = omapfb_apply_changes(fbi, 1);
+ omapfb_put_mem_region(ofbi->region);
+
if (r) {
dev_err(fbdev->dev, "failed to change mode\n");
return r;