aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/video/omap2/omapfb/omapfb-ioctl.c
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 /drivers/video/omap2/omapfb/omapfb-ioctl.c
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>
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 @@
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;