aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorVille Syrjälä <ville.syrjala@nokia.com>2010-03-17 14:36:51 -0400
committerTomi Valkeinen <tomi.valkeinen@nokia.com>2010-08-03 08:18:46 -0400
commit078ff546a806b2c2ab74c25c8edd4c6d4680656a (patch)
treefe988343f6b0038423b637c32e372202a8e5d05a
parent2ad0c50b84ee984aa58b09b46aef5c9f1d95e469 (diff)
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>
-rw-r--r--drivers/video/omap2/omapfb/omapfb-ioctl.c125
-rw-r--r--drivers/video/omap2/omapfb/omapfb-main.c71
-rw-r--r--drivers/video/omap2/omapfb/omapfb-sysfs.c37
-rw-r--r--drivers/video/omap2/omapfb/omapfb.h9
-rw-r--r--include/linux/omapfb.h5
5 files changed, 183 insertions, 64 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 @@
34 34
35#include "omapfb.h" 35#include "omapfb.h"
36 36
37static u8 get_mem_idx(struct omapfb_info *ofbi)
38{
39 if (ofbi->id == ofbi->region->id)
40 return 0;
41
42 return OMAPFB_MEM_IDX_ENABLED | ofbi->region->id;
43}
44
45static struct omapfb2_mem_region *get_mem_region(struct omapfb_info *ofbi,
46 u8 mem_idx)
47{
48 struct omapfb2_device *fbdev = ofbi->fbdev;
49
50 if (mem_idx & OMAPFB_MEM_IDX_ENABLED)
51 mem_idx &= OMAPFB_MEM_IDX_MASK;
52 else
53 mem_idx = ofbi->id;
54
55 if (mem_idx >= fbdev->num_fbs)
56 return NULL;
57
58 return &fbdev->regions[mem_idx];
59}
60
37static int omapfb_setup_plane(struct fb_info *fbi, struct omapfb_plane_info *pi) 61static int omapfb_setup_plane(struct fb_info *fbi, struct omapfb_plane_info *pi)
38{ 62{
39 struct omapfb_info *ofbi = FB2OFB(fbi); 63 struct omapfb_info *ofbi = FB2OFB(fbi);
40 struct omapfb2_device *fbdev = ofbi->fbdev; 64 struct omapfb2_device *fbdev = ofbi->fbdev;
41 struct omap_overlay *ovl; 65 struct omap_overlay *ovl;
42 struct omap_overlay_info info; 66 struct omap_overlay_info old_info;
67 struct omapfb2_mem_region *old_rg, *new_rg;
43 int r = 0; 68 int r = 0;
44 69
45 DBG("omapfb_setup_plane\n"); 70 DBG("omapfb_setup_plane\n");
@@ -52,7 +77,14 @@ static int omapfb_setup_plane(struct fb_info *fbi, struct omapfb_plane_info *pi)
52 /* XXX uses only the first overlay */ 77 /* XXX uses only the first overlay */
53 ovl = ofbi->overlays[0]; 78 ovl = ofbi->overlays[0];
54 79
55 if (pi->enabled && !ofbi->region.size) { 80 old_rg = ofbi->region;
81 new_rg = get_mem_region(ofbi, pi->mem_idx);
82 if (!new_rg) {
83 r = -EINVAL;
84 goto out;
85 }
86
87 if (pi->enabled && !new_rg->size) {
56 /* 88 /*
57 * This plane's memory was freed, can't enable it 89 * This plane's memory was freed, can't enable it
58 * until it's reallocated. 90 * until it's reallocated.
@@ -61,27 +93,60 @@ static int omapfb_setup_plane(struct fb_info *fbi, struct omapfb_plane_info *pi)
61 goto out; 93 goto out;
62 } 94 }
63 95
64 ovl->get_overlay_info(ovl, &info); 96 ovl->get_overlay_info(ovl, &old_info);
65 97
66 info.pos_x = pi->pos_x; 98 if (old_rg != new_rg) {
67 info.pos_y = pi->pos_y; 99 ofbi->region = new_rg;
68 info.out_width = pi->out_width; 100 set_fb_fix(fbi);
69 info.out_height = pi->out_height; 101 }
70 info.enabled = pi->enabled;
71 102
72 r = ovl->set_overlay_info(ovl, &info); 103 if (pi->enabled) {
73 if (r) 104 struct omap_overlay_info info;
74 goto out; 105
106 r = omapfb_setup_overlay(fbi, ovl, pi->pos_x, pi->pos_y,
107 pi->out_width, pi->out_height);
108 if (r)
109 goto undo;
75 110
76 if (ovl->manager) { 111 ovl->get_overlay_info(ovl, &info);
77 r = ovl->manager->apply(ovl->manager); 112
113 if (!info.enabled) {
114 info.enabled = pi->enabled;
115 r = ovl->set_overlay_info(ovl, &info);
116 if (r)
117 goto undo;
118 }
119 } else {
120 struct omap_overlay_info info;
121
122 ovl->get_overlay_info(ovl, &info);
123
124 info.enabled = pi->enabled;
125 info.pos_x = pi->pos_x;
126 info.pos_y = pi->pos_y;
127 info.out_width = pi->out_width;
128 info.out_height = pi->out_height;
129
130 r = ovl->set_overlay_info(ovl, &info);
78 if (r) 131 if (r)
79 goto out; 132 goto undo;
80 } 133 }
81 134
82out: 135 if (ovl->manager)
83 if (r) 136 ovl->manager->apply(ovl->manager);
84 dev_err(fbdev->dev, "setup_plane failed\n"); 137
138 return 0;
139
140 undo:
141 if (old_rg != new_rg) {
142 ofbi->region = old_rg;
143 set_fb_fix(fbi);
144 }
145
146 ovl->set_overlay_info(ovl, &old_info);
147 out:
148 dev_err(fbdev->dev, "setup_plane failed\n");
149
85 return r; 150 return r;
86} 151}
87 152
@@ -92,8 +157,8 @@ static int omapfb_query_plane(struct fb_info *fbi, struct omapfb_plane_info *pi)
92 if (ofbi->num_overlays != 1) { 157 if (ofbi->num_overlays != 1) {
93 memset(pi, 0, sizeof(*pi)); 158 memset(pi, 0, sizeof(*pi));
94 } else { 159 } else {
95 struct omap_overlay_info *ovli;
96 struct omap_overlay *ovl; 160 struct omap_overlay *ovl;
161 struct omap_overlay_info *ovli;
97 162
98 ovl = ofbi->overlays[0]; 163 ovl = ofbi->overlays[0];
99 ovli = &ovl->info; 164 ovli = &ovl->info;
@@ -103,6 +168,7 @@ static int omapfb_query_plane(struct fb_info *fbi, struct omapfb_plane_info *pi)
103 pi->enabled = ovli->enabled; 168 pi->enabled = ovli->enabled;
104 pi->channel_out = 0; /* xxx */ 169 pi->channel_out = 0; /* xxx */
105 pi->mirror = 0; 170 pi->mirror = 0;
171 pi->mem_idx = get_mem_idx(ofbi);
106 pi->out_width = ovli->out_width; 172 pi->out_width = ovli->out_width;
107 pi->out_height = ovli->out_height; 173 pi->out_height = ovli->out_height;
108 } 174 }
@@ -123,11 +189,24 @@ static int omapfb_setup_mem(struct fb_info *fbi, struct omapfb_mem_info *mi)
123 189
124 size = PAGE_ALIGN(mi->size); 190 size = PAGE_ALIGN(mi->size);
125 191
126 rg = &ofbi->region; 192 rg = ofbi->region;
127 193
128 for (i = 0; i < ofbi->num_overlays; i++) { 194 if (atomic_read(&rg->map_count))
129 if (ofbi->overlays[i]->info.enabled) 195 return -EBUSY;
130 return -EBUSY; 196
197 for (i = 0; i < fbdev->num_fbs; i++) {
198 struct omapfb_info *ofbi2 = FB2OFB(fbdev->fbs[i]);
199 int j;
200
201 if (ofbi2->region != rg)
202 continue;
203
204 for (j = 0; j < ofbi2->num_overlays; j++) {
205 if (ofbi2->overlays[j]->info.enabled) {
206 r = -EBUSY;
207 return r;
208 }
209 }
131 } 210 }
132 211
133 if (rg->size != size || rg->type != mi->type) { 212 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)
146 struct omapfb_info *ofbi = FB2OFB(fbi); 225 struct omapfb_info *ofbi = FB2OFB(fbi);
147 struct omapfb2_mem_region *rg; 226 struct omapfb2_mem_region *rg;
148 227
149 rg = &ofbi->region; 228 rg = ofbi->region;
150 memset(mi, 0, sizeof(*mi)); 229 memset(mi, 0, sizeof(*mi));
151 230
152 mi->size = rg->size; 231 mi->size = rg->size;
diff --git a/drivers/video/omap2/omapfb/omapfb-main.c b/drivers/video/omap2/omapfb/omapfb-main.c
index ccccf3d71a39..4a0588022b33 100644
--- a/drivers/video/omap2/omapfb/omapfb-main.c
+++ b/drivers/video/omap2/omapfb/omapfb-main.c
@@ -157,7 +157,7 @@ static void fill_fb(struct fb_info *fbi)
157 157
158static unsigned omapfb_get_vrfb_offset(const struct omapfb_info *ofbi, int rot) 158static unsigned omapfb_get_vrfb_offset(const struct omapfb_info *ofbi, int rot)
159{ 159{
160 const struct vrfb *vrfb = &ofbi->region.vrfb; 160 const struct vrfb *vrfb = &ofbi->region->vrfb;
161 unsigned offset; 161 unsigned offset;
162 162
163 switch (rot) { 163 switch (rot) {
@@ -185,27 +185,27 @@ static unsigned omapfb_get_vrfb_offset(const struct omapfb_info *ofbi, int rot)
185static u32 omapfb_get_region_rot_paddr(const struct omapfb_info *ofbi, int rot) 185static u32 omapfb_get_region_rot_paddr(const struct omapfb_info *ofbi, int rot)
186{ 186{
187 if (ofbi->rotation_type == OMAP_DSS_ROT_VRFB) { 187 if (ofbi->rotation_type == OMAP_DSS_ROT_VRFB) {
188 return ofbi->region.vrfb.paddr[rot] 188 return ofbi->region->vrfb.paddr[rot]
189 + omapfb_get_vrfb_offset(ofbi, rot); 189 + omapfb_get_vrfb_offset(ofbi, rot);
190 } else { 190 } else {
191 return ofbi->region.paddr; 191 return ofbi->region->paddr;
192 } 192 }
193} 193}
194 194
195static u32 omapfb_get_region_paddr(const struct omapfb_info *ofbi) 195static u32 omapfb_get_region_paddr(const struct omapfb_info *ofbi)
196{ 196{
197 if (ofbi->rotation_type == OMAP_DSS_ROT_VRFB) 197 if (ofbi->rotation_type == OMAP_DSS_ROT_VRFB)
198 return ofbi->region.vrfb.paddr[0]; 198 return ofbi->region->vrfb.paddr[0];
199 else 199 else
200 return ofbi->region.paddr; 200 return ofbi->region->paddr;
201} 201}
202 202
203static void __iomem *omapfb_get_region_vaddr(const struct omapfb_info *ofbi) 203static void __iomem *omapfb_get_region_vaddr(const struct omapfb_info *ofbi)
204{ 204{
205 if (ofbi->rotation_type == OMAP_DSS_ROT_VRFB) 205 if (ofbi->rotation_type == OMAP_DSS_ROT_VRFB)
206 return ofbi->region.vrfb.vaddr[0]; 206 return ofbi->region->vrfb.vaddr[0];
207 else 207 else
208 return ofbi->region.vaddr; 208 return ofbi->region->vaddr;
209} 209}
210 210
211static struct omapfb_colormode omapfb_colormodes[] = { 211static struct omapfb_colormode omapfb_colormodes[] = {
@@ -450,7 +450,7 @@ static int check_vrfb_fb_size(unsigned long region_size,
450static int check_fb_size(const struct omapfb_info *ofbi, 450static int check_fb_size(const struct omapfb_info *ofbi,
451 struct fb_var_screeninfo *var) 451 struct fb_var_screeninfo *var)
452{ 452{
453 unsigned long max_frame_size = ofbi->region.size; 453 unsigned long max_frame_size = ofbi->region->size;
454 int bytespp = var->bits_per_pixel >> 3; 454 int bytespp = var->bits_per_pixel >> 3;
455 unsigned long line_size = var->xres_virtual * bytespp; 455 unsigned long line_size = var->xres_virtual * bytespp;
456 456
@@ -497,7 +497,7 @@ static int check_fb_size(const struct omapfb_info *ofbi,
497static int setup_vrfb_rotation(struct fb_info *fbi) 497static int setup_vrfb_rotation(struct fb_info *fbi)
498{ 498{
499 struct omapfb_info *ofbi = FB2OFB(fbi); 499 struct omapfb_info *ofbi = FB2OFB(fbi);
500 struct omapfb2_mem_region *rg = &ofbi->region; 500 struct omapfb2_mem_region *rg = ofbi->region;
501 struct vrfb *vrfb = &rg->vrfb; 501 struct vrfb *vrfb = &rg->vrfb;
502 struct fb_var_screeninfo *var = &fbi->var; 502 struct fb_var_screeninfo *var = &fbi->var;
503 struct fb_fix_screeninfo *fix = &fbi->fix; 503 struct fb_fix_screeninfo *fix = &fbi->fix;
@@ -558,9 +558,9 @@ static int setup_vrfb_rotation(struct fb_info *fbi)
558 return r; 558 return r;
559 559
560 /* used by open/write in fbmem.c */ 560 /* used by open/write in fbmem.c */
561 fbi->screen_base = ofbi->region.vrfb.vaddr[0]; 561 fbi->screen_base = ofbi->region->vrfb.vaddr[0];
562 562
563 fix->smem_start = ofbi->region.vrfb.paddr[0]; 563 fix->smem_start = ofbi->region->vrfb.paddr[0];
564 564
565 switch (var->nonstd) { 565 switch (var->nonstd) {
566 case OMAPFB_COLOR_YUV422: 566 case OMAPFB_COLOR_YUV422:
@@ -599,7 +599,7 @@ void set_fb_fix(struct fb_info *fbi)
599 struct fb_fix_screeninfo *fix = &fbi->fix; 599 struct fb_fix_screeninfo *fix = &fbi->fix;
600 struct fb_var_screeninfo *var = &fbi->var; 600 struct fb_var_screeninfo *var = &fbi->var;
601 struct omapfb_info *ofbi = FB2OFB(fbi); 601 struct omapfb_info *ofbi = FB2OFB(fbi);
602 struct omapfb2_mem_region *rg = &ofbi->region; 602 struct omapfb2_mem_region *rg = ofbi->region;
603 603
604 DBG("set_fb_fix\n"); 604 DBG("set_fb_fix\n");
605 605
@@ -688,7 +688,7 @@ int check_fb_var(struct fb_info *fbi, struct fb_var_screeninfo *var)
688 return -EINVAL; 688 return -EINVAL;
689 689
690 /* When no memory is allocated ignore the size check */ 690 /* When no memory is allocated ignore the size check */
691 if (ofbi->region.size != 0 && check_fb_size(ofbi, var)) 691 if (ofbi->region->size != 0 && check_fb_size(ofbi, var))
692 return -EINVAL; 692 return -EINVAL;
693 693
694 if (var->xres + var->xoffset > var->xres_virtual) 694 if (var->xres + var->xoffset > var->xres_virtual)
@@ -856,7 +856,7 @@ static void omapfb_calc_addr(const struct omapfb_info *ofbi,
856} 856}
857 857
858/* setup overlay according to the fb */ 858/* setup overlay according to the fb */
859static int omapfb_setup_overlay(struct fb_info *fbi, struct omap_overlay *ovl, 859int omapfb_setup_overlay(struct fb_info *fbi, struct omap_overlay *ovl,
860 u16 posx, u16 posy, u16 outw, u16 outh) 860 u16 posx, u16 posy, u16 outw, u16 outh)
861{ 861{
862 int r = 0; 862 int r = 0;
@@ -892,7 +892,7 @@ static int omapfb_setup_overlay(struct fb_info *fbi, struct omap_overlay *ovl,
892 yres = var->yres; 892 yres = var->yres;
893 } 893 }
894 894
895 if (ofbi->region.size) 895 if (ofbi->region->size)
896 omapfb_calc_addr(ofbi, var, fix, rotation, 896 omapfb_calc_addr(ofbi, var, fix, rotation,
897 &data_start_p, &data_start_v); 897 &data_start_p, &data_start_v);
898 898
@@ -971,7 +971,7 @@ int omapfb_apply_changes(struct fb_info *fbi, int init)
971 971
972 DBG("apply_changes, fb %d, ovl %d\n", ofbi->id, ovl->id); 972 DBG("apply_changes, fb %d, ovl %d\n", ofbi->id, ovl->id);
973 973
974 if (ofbi->region.size == 0) { 974 if (ofbi->region->size == 0) {
975 /* the fb is not available. disable the overlay */ 975 /* the fb is not available. disable the overlay */
976 omapfb_overlay_enable(ovl, 0); 976 omapfb_overlay_enable(ovl, 0);
977 if (!init && ovl->manager) 977 if (!init && ovl->manager)
@@ -1071,16 +1071,16 @@ static int omapfb_pan_display(struct fb_var_screeninfo *var,
1071 1071
1072static void mmap_user_open(struct vm_area_struct *vma) 1072static void mmap_user_open(struct vm_area_struct *vma)
1073{ 1073{
1074 struct omapfb_info *ofbi = (struct omapfb_info *)vma->vm_private_data; 1074 struct omapfb2_mem_region *rg = vma->vm_private_data;
1075 1075
1076 atomic_inc(&ofbi->map_count); 1076 atomic_inc(&rg->map_count);
1077} 1077}
1078 1078
1079static void mmap_user_close(struct vm_area_struct *vma) 1079static void mmap_user_close(struct vm_area_struct *vma)
1080{ 1080{
1081 struct omapfb_info *ofbi = (struct omapfb_info *)vma->vm_private_data; 1081 struct omapfb2_mem_region *rg = vma->vm_private_data;
1082 1082
1083 atomic_dec(&ofbi->map_count); 1083 atomic_dec(&rg->map_count);
1084} 1084}
1085 1085
1086static struct vm_operations_struct mmap_user_ops = { 1086static struct vm_operations_struct mmap_user_ops = {
@@ -1092,6 +1092,7 @@ static int omapfb_mmap(struct fb_info *fbi, struct vm_area_struct *vma)
1092{ 1092{
1093 struct omapfb_info *ofbi = FB2OFB(fbi); 1093 struct omapfb_info *ofbi = FB2OFB(fbi);
1094 struct fb_fix_screeninfo *fix = &fbi->fix; 1094 struct fb_fix_screeninfo *fix = &fbi->fix;
1095 struct omapfb2_mem_region *rg;
1095 unsigned long off; 1096 unsigned long off;
1096 unsigned long start; 1097 unsigned long start;
1097 u32 len; 1098 u32 len;
@@ -1102,6 +1103,8 @@ static int omapfb_mmap(struct fb_info *fbi, struct vm_area_struct *vma)
1102 return -EINVAL; 1103 return -EINVAL;
1103 off = vma->vm_pgoff << PAGE_SHIFT; 1104 off = vma->vm_pgoff << PAGE_SHIFT;
1104 1105
1106 rg = ofbi->region;
1107
1105 start = omapfb_get_region_paddr(ofbi); 1108 start = omapfb_get_region_paddr(ofbi);
1106 len = fix->smem_len; 1109 len = fix->smem_len;
1107 if (off >= len) 1110 if (off >= len)
@@ -1117,12 +1120,12 @@ static int omapfb_mmap(struct fb_info *fbi, struct vm_area_struct *vma)
1117 vma->vm_flags |= VM_IO | VM_RESERVED; 1120 vma->vm_flags |= VM_IO | VM_RESERVED;
1118 vma->vm_page_prot = pgprot_writecombine(vma->vm_page_prot); 1121 vma->vm_page_prot = pgprot_writecombine(vma->vm_page_prot);
1119 vma->vm_ops = &mmap_user_ops; 1122 vma->vm_ops = &mmap_user_ops;
1120 vma->vm_private_data = ofbi; 1123 vma->vm_private_data = rg;
1121 if (io_remap_pfn_range(vma, vma->vm_start, off >> PAGE_SHIFT, 1124 if (io_remap_pfn_range(vma, vma->vm_start, off >> PAGE_SHIFT,
1122 vma->vm_end - vma->vm_start, vma->vm_page_prot)) 1125 vma->vm_end - vma->vm_start, vma->vm_page_prot))
1123 return -EAGAIN; 1126 return -EAGAIN;
1124 /* vm_ops.open won't be called for mmap itself. */ 1127 /* vm_ops.open won't be called for mmap itself. */
1125 atomic_inc(&ofbi->map_count); 1128 atomic_inc(&rg->map_count);
1126 return 0; 1129 return 0;
1127} 1130}
1128 1131
@@ -1312,7 +1315,9 @@ static void omapfb_free_fbmem(struct fb_info *fbi)
1312 struct omapfb2_device *fbdev = ofbi->fbdev; 1315 struct omapfb2_device *fbdev = ofbi->fbdev;
1313 struct omapfb2_mem_region *rg; 1316 struct omapfb2_mem_region *rg;
1314 1317
1315 rg = &ofbi->region; 1318 rg = ofbi->region;
1319
1320 WARN_ON(atomic_read(&rg->map_count));
1316 1321
1317 if (rg->paddr) 1322 if (rg->paddr)
1318 if (omap_vram_free(rg->paddr, rg->size)) 1323 if (omap_vram_free(rg->paddr, rg->size))
@@ -1367,8 +1372,15 @@ static int omapfb_alloc_fbmem(struct fb_info *fbi, unsigned long size,
1367 void __iomem *vaddr; 1372 void __iomem *vaddr;
1368 int r; 1373 int r;
1369 1374
1370 rg = &ofbi->region; 1375 rg = ofbi->region;
1371 memset(rg, 0, sizeof(*rg)); 1376
1377 rg->paddr = 0;
1378 rg->vaddr = NULL;
1379 memset(&rg->vrfb, 0, sizeof rg->vrfb);
1380 rg->size = 0;
1381 rg->type = 0;
1382 rg->alloc = false;
1383 rg->map = false;
1372 1384
1373 size = PAGE_ALIGN(size); 1385 size = PAGE_ALIGN(size);
1374 1386
@@ -1621,7 +1633,7 @@ static int omapfb_allocate_all_fbs(struct omapfb2_device *fbdev)
1621 for (i = 0; i < fbdev->num_fbs; i++) { 1633 for (i = 0; i < fbdev->num_fbs; i++) {
1622 struct omapfb_info *ofbi = FB2OFB(fbdev->fbs[i]); 1634 struct omapfb_info *ofbi = FB2OFB(fbdev->fbs[i]);
1623 struct omapfb2_mem_region *rg; 1635 struct omapfb2_mem_region *rg;
1624 rg = &ofbi->region; 1636 rg = ofbi->region;
1625 1637
1626 DBG("region%d phys %08x virt %p size=%lu\n", 1638 DBG("region%d phys %08x virt %p size=%lu\n",
1627 i, 1639 i,
@@ -1638,7 +1650,7 @@ int omapfb_realloc_fbmem(struct fb_info *fbi, unsigned long size, int type)
1638 struct omapfb_info *ofbi = FB2OFB(fbi); 1650 struct omapfb_info *ofbi = FB2OFB(fbi);
1639 struct omapfb2_device *fbdev = ofbi->fbdev; 1651 struct omapfb2_device *fbdev = ofbi->fbdev;
1640 struct omap_dss_device *display = fb2display(fbi); 1652 struct omap_dss_device *display = fb2display(fbi);
1641 struct omapfb2_mem_region *rg = &ofbi->region; 1653 struct omapfb2_mem_region *rg = ofbi->region;
1642 unsigned long old_size = rg->size; 1654 unsigned long old_size = rg->size;
1643 unsigned long old_paddr = rg->paddr; 1655 unsigned long old_paddr = rg->paddr;
1644 int old_type = rg->type; 1656 int old_type = rg->type;
@@ -1721,7 +1733,7 @@ static int omapfb_fb_init(struct omapfb2_device *fbdev, struct fb_info *fbi)
1721 fbi->flags = FBINFO_FLAG_DEFAULT; 1733 fbi->flags = FBINFO_FLAG_DEFAULT;
1722 fbi->pseudo_palette = fbdev->pseudo_palette; 1734 fbi->pseudo_palette = fbdev->pseudo_palette;
1723 1735
1724 if (ofbi->region.size == 0) { 1736 if (ofbi->region->size == 0) {
1725 clear_fb_info(fbi); 1737 clear_fb_info(fbi);
1726 return 0; 1738 return 0;
1727 } 1739 }
@@ -1883,6 +1895,9 @@ static int omapfb_create_framebuffers(struct omapfb2_device *fbdev)
1883 ofbi->fbdev = fbdev; 1895 ofbi->fbdev = fbdev;
1884 ofbi->id = i; 1896 ofbi->id = i;
1885 1897
1898 ofbi->region = &fbdev->regions[i];
1899 ofbi->region->id = i;
1900
1886 /* assign these early, so that fb alloc can use them */ 1901 /* assign these early, so that fb alloc can use them */
1887 ofbi->rotation_type = def_vrfb ? OMAP_DSS_ROT_VRFB : 1902 ofbi->rotation_type = def_vrfb ? OMAP_DSS_ROT_VRFB :
1888 OMAP_DSS_ROT_DMA; 1903 OMAP_DSS_ROT_DMA;
diff --git a/drivers/video/omap2/omapfb/omapfb-sysfs.c b/drivers/video/omap2/omapfb/omapfb-sysfs.c
index 5179219128bd..dea1aa46a7db 100644
--- a/drivers/video/omap2/omapfb/omapfb-sysfs.c
+++ b/drivers/video/omap2/omapfb/omapfb-sysfs.c
@@ -64,7 +64,7 @@ static ssize_t store_rotate_type(struct device *dev,
64 if (rot_type == ofbi->rotation_type) 64 if (rot_type == ofbi->rotation_type)
65 goto out; 65 goto out;
66 66
67 if (ofbi->region.size) { 67 if (ofbi->region->size) {
68 r = -EBUSY; 68 r = -EBUSY;
69 goto out; 69 goto out;
70 } 70 }
@@ -408,7 +408,7 @@ static ssize_t show_size(struct device *dev,
408 struct fb_info *fbi = dev_get_drvdata(dev); 408 struct fb_info *fbi = dev_get_drvdata(dev);
409 struct omapfb_info *ofbi = FB2OFB(fbi); 409 struct omapfb_info *ofbi = FB2OFB(fbi);
410 410
411 return snprintf(buf, PAGE_SIZE, "%lu\n", ofbi->region.size); 411 return snprintf(buf, PAGE_SIZE, "%lu\n", ofbi->region->size);
412} 412}
413 413
414static ssize_t store_size(struct device *dev, struct device_attribute *attr, 414static ssize_t store_size(struct device *dev, struct device_attribute *attr,
@@ -416,6 +416,8 @@ static ssize_t store_size(struct device *dev, struct device_attribute *attr,
416{ 416{
417 struct fb_info *fbi = dev_get_drvdata(dev); 417 struct fb_info *fbi = dev_get_drvdata(dev);
418 struct omapfb_info *ofbi = FB2OFB(fbi); 418 struct omapfb_info *ofbi = FB2OFB(fbi);
419 struct omapfb2_device *fbdev = ofbi->fbdev;
420 struct omapfb2_mem_region *rg;
419 unsigned long size; 421 unsigned long size;
420 int r; 422 int r;
421 int i; 423 int i;
@@ -425,15 +427,30 @@ static ssize_t store_size(struct device *dev, struct device_attribute *attr,
425 if (!lock_fb_info(fbi)) 427 if (!lock_fb_info(fbi))
426 return -ENODEV; 428 return -ENODEV;
427 429
428 for (i = 0; i < ofbi->num_overlays; i++) { 430 rg = ofbi->region;
429 if (ofbi->overlays[i]->info.enabled) { 431
430 r = -EBUSY; 432 if (atomic_read(&rg->map_count)) {
431 goto out; 433 r = -EBUSY;
434 goto out;
435 }
436
437 for (i = 0; i < fbdev->num_fbs; i++) {
438 struct omapfb_info *ofbi2 = FB2OFB(fbdev->fbs[i]);
439 int j;
440
441 if (ofbi2->region != rg)
442 continue;
443
444 for (j = 0; j < ofbi2->num_overlays; j++) {
445 if (ofbi2->overlays[j]->info.enabled) {
446 r = -EBUSY;
447 goto out;
448 }
432 } 449 }
433 } 450 }
434 451
435 if (size != ofbi->region.size) { 452 if (size != ofbi->region->size) {
436 r = omapfb_realloc_fbmem(fbi, size, ofbi->region.type); 453 r = omapfb_realloc_fbmem(fbi, size, ofbi->region->type);
437 if (r) { 454 if (r) {
438 dev_err(dev, "realloc fbmem failed\n"); 455 dev_err(dev, "realloc fbmem failed\n");
439 goto out; 456 goto out;
@@ -453,7 +470,7 @@ static ssize_t show_phys(struct device *dev,
453 struct fb_info *fbi = dev_get_drvdata(dev); 470 struct fb_info *fbi = dev_get_drvdata(dev);
454 struct omapfb_info *ofbi = FB2OFB(fbi); 471 struct omapfb_info *ofbi = FB2OFB(fbi);
455 472
456 return snprintf(buf, PAGE_SIZE, "%0x\n", ofbi->region.paddr); 473 return snprintf(buf, PAGE_SIZE, "%0x\n", ofbi->region->paddr);
457} 474}
458 475
459static ssize_t show_virt(struct device *dev, 476static ssize_t show_virt(struct device *dev,
@@ -462,7 +479,7 @@ static ssize_t show_virt(struct device *dev,
462 struct fb_info *fbi = dev_get_drvdata(dev); 479 struct fb_info *fbi = dev_get_drvdata(dev);
463 struct omapfb_info *ofbi = FB2OFB(fbi); 480 struct omapfb_info *ofbi = FB2OFB(fbi);
464 481
465 return snprintf(buf, PAGE_SIZE, "%p\n", ofbi->region.vaddr); 482 return snprintf(buf, PAGE_SIZE, "%p\n", ofbi->region->vaddr);
466} 483}
467 484
468static struct device_attribute omapfb_attrs[] = { 485static struct device_attribute omapfb_attrs[] = {
diff --git a/drivers/video/omap2/omapfb/omapfb.h b/drivers/video/omap2/omapfb/omapfb.h
index c9866be0460a..02f1ba9b228c 100644
--- a/drivers/video/omap2/omapfb/omapfb.h
+++ b/drivers/video/omap2/omapfb/omapfb.h
@@ -44,6 +44,7 @@ extern unsigned int omapfb_debug;
44#define OMAPFB_MAX_OVL_PER_FB 3 44#define OMAPFB_MAX_OVL_PER_FB 3
45 45
46struct omapfb2_mem_region { 46struct omapfb2_mem_region {
47 int id;
47 u32 paddr; 48 u32 paddr;
48 void __iomem *vaddr; 49 void __iomem *vaddr;
49 struct vrfb vrfb; 50 struct vrfb vrfb;
@@ -51,13 +52,13 @@ struct omapfb2_mem_region {
51 u8 type; /* OMAPFB_PLANE_MEM_* */ 52 u8 type; /* OMAPFB_PLANE_MEM_* */
52 bool alloc; /* allocated by the driver */ 53 bool alloc; /* allocated by the driver */
53 bool map; /* kernel mapped by the driver */ 54 bool map; /* kernel mapped by the driver */
55 atomic_t map_count;
54}; 56};
55 57
56/* appended to fb_info */ 58/* appended to fb_info */
57struct omapfb_info { 59struct omapfb_info {
58 int id; 60 int id;
59 struct omapfb2_mem_region region; 61 struct omapfb2_mem_region *region;
60 atomic_t map_count;
61 int num_overlays; 62 int num_overlays;
62 struct omap_overlay *overlays[OMAPFB_MAX_OVL_PER_FB]; 63 struct omap_overlay *overlays[OMAPFB_MAX_OVL_PER_FB];
63 struct omapfb2_device *fbdev; 64 struct omapfb2_device *fbdev;
@@ -76,6 +77,7 @@ struct omapfb2_device {
76 77
77 unsigned num_fbs; 78 unsigned num_fbs;
78 struct fb_info *fbs[10]; 79 struct fb_info *fbs[10];
80 struct omapfb2_mem_region regions[10];
79 81
80 unsigned num_displays; 82 unsigned num_displays;
81 struct omap_dss_device *displays[10]; 83 struct omap_dss_device *displays[10];
@@ -117,6 +119,9 @@ int omapfb_update_window(struct fb_info *fbi,
117int dss_mode_to_fb_mode(enum omap_color_mode dssmode, 119int dss_mode_to_fb_mode(enum omap_color_mode dssmode,
118 struct fb_var_screeninfo *var); 120 struct fb_var_screeninfo *var);
119 121
122int omapfb_setup_overlay(struct fb_info *fbi, struct omap_overlay *ovl,
123 u16 posx, u16 posy, u16 outw, u16 outh);
124
120/* find the display connected to this fb, if any */ 125/* find the display connected to this fb, if any */
121static inline struct omap_dss_device *fb2display(struct fb_info *fbi) 126static inline struct omap_dss_device *fb2display(struct fb_info *fbi)
122{ 127{
diff --git a/include/linux/omapfb.h b/include/linux/omapfb.h
index 9bdd91486b49..0ecf7311c1ae 100644
--- a/include/linux/omapfb.h
+++ b/include/linux/omapfb.h
@@ -85,6 +85,9 @@
85#define OMAPFB_MEMTYPE_SRAM 1 85#define OMAPFB_MEMTYPE_SRAM 1
86#define OMAPFB_MEMTYPE_MAX 1 86#define OMAPFB_MEMTYPE_MAX 1
87 87
88#define OMAPFB_MEM_IDX_ENABLED 0x80
89#define OMAPFB_MEM_IDX_MASK 0x7f
90
88enum omapfb_color_format { 91enum omapfb_color_format {
89 OMAPFB_COLOR_RGB565 = 0, 92 OMAPFB_COLOR_RGB565 = 0,
90 OMAPFB_COLOR_YUV422, 93 OMAPFB_COLOR_YUV422,
@@ -136,7 +139,7 @@ struct omapfb_plane_info {
136 __u8 enabled; 139 __u8 enabled;
137 __u8 channel_out; 140 __u8 channel_out;
138 __u8 mirror; 141 __u8 mirror;
139 __u8 reserved1; 142 __u8 mem_idx;
140 __u32 out_width; 143 __u32 out_width;
141 __u32 out_height; 144 __u32 out_height;
142 __u32 reserved2[12]; 145 __u32 reserved2[12];