diff options
-rw-r--r-- | drivers/video/omap2/omapfb/omapfb-ioctl.c | 44 | ||||
-rw-r--r-- | drivers/video/omap2/omapfb/omapfb-main.c | 62 | ||||
-rw-r--r-- | drivers/video/omap2/omapfb/omapfb-sysfs.c | 37 | ||||
-rw-r--r-- | drivers/video/omap2/omapfb/omapfb.h | 18 |
4 files changed, 140 insertions, 21 deletions
diff --git a/drivers/video/omap2/omapfb/omapfb-ioctl.c b/drivers/video/omap2/omapfb/omapfb-ioctl.c index 6635bd75affa..69bcbfca47f6 100644 --- a/drivers/video/omap2/omapfb/omapfb-ioctl.c +++ b/drivers/video/omap2/omapfb/omapfb-ioctl.c | |||
@@ -55,7 +55,7 @@ static struct omapfb2_mem_region *get_mem_region(struct omapfb_info *ofbi, | |||
55 | if (mem_idx >= fbdev->num_fbs) | 55 | if (mem_idx >= fbdev->num_fbs) |
56 | return NULL; | 56 | return NULL; |
57 | 57 | ||
58 | return &fbdev->regions[mem_idx]; | 58 | return omapfb_get_mem_region(&fbdev->regions[mem_idx]); |
59 | } | 59 | } |
60 | 60 | ||
61 | static int omapfb_setup_plane(struct fb_info *fbi, struct omapfb_plane_info *pi) | 61 | static int omapfb_setup_plane(struct fb_info *fbi, struct omapfb_plane_info *pi) |
@@ -77,11 +77,11 @@ static int omapfb_setup_plane(struct fb_info *fbi, struct omapfb_plane_info *pi) | |||
77 | /* XXX uses only the first overlay */ | 77 | /* XXX uses only the first overlay */ |
78 | ovl = ofbi->overlays[0]; | 78 | ovl = ofbi->overlays[0]; |
79 | 79 | ||
80 | old_rg = ofbi->region; | 80 | old_rg = omapfb_get_mem_region(ofbi->region); |
81 | new_rg = get_mem_region(ofbi, pi->mem_idx); | 81 | new_rg = get_mem_region(ofbi, pi->mem_idx); |
82 | if (!new_rg) { | 82 | if (!new_rg) { |
83 | r = -EINVAL; | 83 | r = -EINVAL; |
84 | goto out; | 84 | goto put_old; |
85 | } | 85 | } |
86 | 86 | ||
87 | if (pi->enabled && !new_rg->size) { | 87 | if (pi->enabled && !new_rg->size) { |
@@ -90,7 +90,7 @@ static int omapfb_setup_plane(struct fb_info *fbi, struct omapfb_plane_info *pi) | |||
90 | * until it's reallocated. | 90 | * until it's reallocated. |
91 | */ | 91 | */ |
92 | r = -EINVAL; | 92 | r = -EINVAL; |
93 | goto out; | 93 | goto put_new; |
94 | } | 94 | } |
95 | 95 | ||
96 | ovl->get_overlay_info(ovl, &old_info); | 96 | ovl->get_overlay_info(ovl, &old_info); |
@@ -135,6 +135,9 @@ static int omapfb_setup_plane(struct fb_info *fbi, struct omapfb_plane_info *pi) | |||
135 | if (ovl->manager) | 135 | if (ovl->manager) |
136 | ovl->manager->apply(ovl->manager); | 136 | ovl->manager->apply(ovl->manager); |
137 | 137 | ||
138 | omapfb_put_mem_region(new_rg); | ||
139 | omapfb_put_mem_region(old_rg); | ||
140 | |||
138 | return 0; | 141 | return 0; |
139 | 142 | ||
140 | undo: | 143 | undo: |
@@ -144,6 +147,10 @@ static int omapfb_setup_plane(struct fb_info *fbi, struct omapfb_plane_info *pi) | |||
144 | } | 147 | } |
145 | 148 | ||
146 | ovl->set_overlay_info(ovl, &old_info); | 149 | ovl->set_overlay_info(ovl, &old_info); |
150 | put_new: | ||
151 | omapfb_put_mem_region(new_rg); | ||
152 | put_old: | ||
153 | omapfb_put_mem_region(old_rg); | ||
147 | out: | 154 | out: |
148 | dev_err(fbdev->dev, "setup_plane failed\n"); | 155 | dev_err(fbdev->dev, "setup_plane failed\n"); |
149 | 156 | ||
@@ -181,7 +188,7 @@ static int omapfb_setup_mem(struct fb_info *fbi, struct omapfb_mem_info *mi) | |||
181 | struct omapfb_info *ofbi = FB2OFB(fbi); | 188 | struct omapfb_info *ofbi = FB2OFB(fbi); |
182 | struct omapfb2_device *fbdev = ofbi->fbdev; | 189 | struct omapfb2_device *fbdev = ofbi->fbdev; |
183 | struct omapfb2_mem_region *rg; | 190 | struct omapfb2_mem_region *rg; |
184 | int r, i; | 191 | int r = 0, i; |
185 | size_t size; | 192 | size_t size; |
186 | 193 | ||
187 | if (mi->type > OMAPFB_MEMTYPE_MAX) | 194 | if (mi->type > OMAPFB_MEMTYPE_MAX) |
@@ -191,8 +198,18 @@ static int omapfb_setup_mem(struct fb_info *fbi, struct omapfb_mem_info *mi) | |||
191 | 198 | ||
192 | rg = ofbi->region; | 199 | rg = ofbi->region; |
193 | 200 | ||
194 | if (atomic_read(&rg->map_count)) | 201 | /* FIXME probably should be a rwsem ... */ |
195 | return -EBUSY; | 202 | mutex_lock(&rg->mtx); |
203 | while (rg->ref) { | ||
204 | mutex_unlock(&rg->mtx); | ||
205 | schedule(); | ||
206 | mutex_lock(&rg->mtx); | ||
207 | } | ||
208 | |||
209 | if (atomic_read(&rg->map_count)) { | ||
210 | r = -EBUSY; | ||
211 | goto out; | ||
212 | } | ||
196 | 213 | ||
197 | for (i = 0; i < fbdev->num_fbs; i++) { | 214 | for (i = 0; i < fbdev->num_fbs; i++) { |
198 | struct omapfb_info *ofbi2 = FB2OFB(fbdev->fbs[i]); | 215 | struct omapfb_info *ofbi2 = FB2OFB(fbdev->fbs[i]); |
@@ -204,7 +221,7 @@ static int omapfb_setup_mem(struct fb_info *fbi, struct omapfb_mem_info *mi) | |||
204 | for (j = 0; j < ofbi2->num_overlays; j++) { | 221 | for (j = 0; j < ofbi2->num_overlays; j++) { |
205 | if (ofbi2->overlays[j]->info.enabled) { | 222 | if (ofbi2->overlays[j]->info.enabled) { |
206 | r = -EBUSY; | 223 | r = -EBUSY; |
207 | return r; | 224 | goto out; |
208 | } | 225 | } |
209 | } | 226 | } |
210 | } | 227 | } |
@@ -213,11 +230,14 @@ static int omapfb_setup_mem(struct fb_info *fbi, struct omapfb_mem_info *mi) | |||
213 | r = omapfb_realloc_fbmem(fbi, size, mi->type); | 230 | r = omapfb_realloc_fbmem(fbi, size, mi->type); |
214 | if (r) { | 231 | if (r) { |
215 | dev_err(fbdev->dev, "realloc fbmem failed\n"); | 232 | dev_err(fbdev->dev, "realloc fbmem failed\n"); |
216 | return r; | 233 | goto out; |
217 | } | 234 | } |
218 | } | 235 | } |
219 | 236 | ||
220 | return 0; | 237 | out: |
238 | mutex_unlock(&rg->mtx); | ||
239 | |||
240 | return r; | ||
221 | } | 241 | } |
222 | 242 | ||
223 | static int omapfb_query_mem(struct fb_info *fbi, struct omapfb_mem_info *mi) | 243 | static int omapfb_query_mem(struct fb_info *fbi, struct omapfb_mem_info *mi) |
@@ -225,12 +245,14 @@ static int omapfb_query_mem(struct fb_info *fbi, struct omapfb_mem_info *mi) | |||
225 | struct omapfb_info *ofbi = FB2OFB(fbi); | 245 | struct omapfb_info *ofbi = FB2OFB(fbi); |
226 | struct omapfb2_mem_region *rg; | 246 | struct omapfb2_mem_region *rg; |
227 | 247 | ||
228 | rg = ofbi->region; | 248 | rg = omapfb_get_mem_region(ofbi->region); |
229 | memset(mi, 0, sizeof(*mi)); | 249 | memset(mi, 0, sizeof(*mi)); |
230 | 250 | ||
231 | mi->size = rg->size; | 251 | mi->size = rg->size; |
232 | mi->type = rg->type; | 252 | mi->type = rg->type; |
233 | 253 | ||
254 | omapfb_put_mem_region(rg); | ||
255 | |||
234 | return 0; | 256 | return 0; |
235 | } | 257 | } |
236 | 258 | ||
diff --git a/drivers/video/omap2/omapfb/omapfb-main.c b/drivers/video/omap2/omapfb/omapfb-main.c index 4a0588022b33..eb4338bbaa2b 100644 --- a/drivers/video/omap2/omapfb/omapfb-main.c +++ b/drivers/video/omap2/omapfb/omapfb-main.c | |||
@@ -1019,36 +1019,48 @@ err: | |||
1019 | * DO NOT MODIFY PAR */ | 1019 | * DO NOT MODIFY PAR */ |
1020 | static int omapfb_check_var(struct fb_var_screeninfo *var, struct fb_info *fbi) | 1020 | static int omapfb_check_var(struct fb_var_screeninfo *var, struct fb_info *fbi) |
1021 | { | 1021 | { |
1022 | struct omapfb_info *ofbi = FB2OFB(fbi); | ||
1022 | int r; | 1023 | int r; |
1023 | 1024 | ||
1024 | DBG("check_var(%d)\n", FB2OFB(fbi)->id); | 1025 | DBG("check_var(%d)\n", FB2OFB(fbi)->id); |
1025 | 1026 | ||
1027 | omapfb_get_mem_region(ofbi->region); | ||
1028 | |||
1026 | r = check_fb_var(fbi, var); | 1029 | r = check_fb_var(fbi, var); |
1027 | 1030 | ||
1031 | omapfb_put_mem_region(ofbi->region); | ||
1032 | |||
1028 | return r; | 1033 | return r; |
1029 | } | 1034 | } |
1030 | 1035 | ||
1031 | /* set the video mode according to info->var */ | 1036 | /* set the video mode according to info->var */ |
1032 | static int omapfb_set_par(struct fb_info *fbi) | 1037 | static int omapfb_set_par(struct fb_info *fbi) |
1033 | { | 1038 | { |
1039 | struct omapfb_info *ofbi = FB2OFB(fbi); | ||
1034 | int r; | 1040 | int r; |
1035 | 1041 | ||
1036 | DBG("set_par(%d)\n", FB2OFB(fbi)->id); | 1042 | DBG("set_par(%d)\n", FB2OFB(fbi)->id); |
1037 | 1043 | ||
1044 | omapfb_get_mem_region(ofbi->region); | ||
1045 | |||
1038 | set_fb_fix(fbi); | 1046 | set_fb_fix(fbi); |
1039 | 1047 | ||
1040 | r = setup_vrfb_rotation(fbi); | 1048 | r = setup_vrfb_rotation(fbi); |
1041 | if (r) | 1049 | if (r) |
1042 | return r; | 1050 | goto out; |
1043 | 1051 | ||
1044 | r = omapfb_apply_changes(fbi, 0); | 1052 | r = omapfb_apply_changes(fbi, 0); |
1045 | 1053 | ||
1054 | out: | ||
1055 | omapfb_put_mem_region(ofbi->region); | ||
1056 | |||
1046 | return r; | 1057 | return r; |
1047 | } | 1058 | } |
1048 | 1059 | ||
1049 | static int omapfb_pan_display(struct fb_var_screeninfo *var, | 1060 | static int omapfb_pan_display(struct fb_var_screeninfo *var, |
1050 | struct fb_info *fbi) | 1061 | struct fb_info *fbi) |
1051 | { | 1062 | { |
1063 | struct omapfb_info *ofbi = FB2OFB(fbi); | ||
1052 | struct fb_var_screeninfo new_var; | 1064 | struct fb_var_screeninfo new_var; |
1053 | int r; | 1065 | int r; |
1054 | 1066 | ||
@@ -1064,8 +1076,12 @@ static int omapfb_pan_display(struct fb_var_screeninfo *var, | |||
1064 | 1076 | ||
1065 | fbi->var = new_var; | 1077 | fbi->var = new_var; |
1066 | 1078 | ||
1079 | omapfb_get_mem_region(ofbi->region); | ||
1080 | |||
1067 | r = omapfb_apply_changes(fbi, 0); | 1081 | r = omapfb_apply_changes(fbi, 0); |
1068 | 1082 | ||
1083 | omapfb_put_mem_region(ofbi->region); | ||
1084 | |||
1069 | return r; | 1085 | return r; |
1070 | } | 1086 | } |
1071 | 1087 | ||
@@ -1073,14 +1089,18 @@ static void mmap_user_open(struct vm_area_struct *vma) | |||
1073 | { | 1089 | { |
1074 | struct omapfb2_mem_region *rg = vma->vm_private_data; | 1090 | struct omapfb2_mem_region *rg = vma->vm_private_data; |
1075 | 1091 | ||
1092 | omapfb_get_mem_region(rg); | ||
1076 | atomic_inc(&rg->map_count); | 1093 | atomic_inc(&rg->map_count); |
1094 | omapfb_put_mem_region(rg); | ||
1077 | } | 1095 | } |
1078 | 1096 | ||
1079 | static void mmap_user_close(struct vm_area_struct *vma) | 1097 | static void mmap_user_close(struct vm_area_struct *vma) |
1080 | { | 1098 | { |
1081 | struct omapfb2_mem_region *rg = vma->vm_private_data; | 1099 | struct omapfb2_mem_region *rg = vma->vm_private_data; |
1082 | 1100 | ||
1101 | omapfb_get_mem_region(rg); | ||
1083 | atomic_dec(&rg->map_count); | 1102 | atomic_dec(&rg->map_count); |
1103 | omapfb_put_mem_region(rg); | ||
1084 | } | 1104 | } |
1085 | 1105 | ||
1086 | static struct vm_operations_struct mmap_user_ops = { | 1106 | static struct vm_operations_struct mmap_user_ops = { |
@@ -1096,6 +1116,7 @@ static int omapfb_mmap(struct fb_info *fbi, struct vm_area_struct *vma) | |||
1096 | unsigned long off; | 1116 | unsigned long off; |
1097 | unsigned long start; | 1117 | unsigned long start; |
1098 | u32 len; | 1118 | u32 len; |
1119 | int r = -EINVAL; | ||
1099 | 1120 | ||
1100 | if (vma->vm_end - vma->vm_start == 0) | 1121 | if (vma->vm_end - vma->vm_start == 0) |
1101 | return 0; | 1122 | return 0; |
@@ -1103,14 +1124,14 @@ static int omapfb_mmap(struct fb_info *fbi, struct vm_area_struct *vma) | |||
1103 | return -EINVAL; | 1124 | return -EINVAL; |
1104 | off = vma->vm_pgoff << PAGE_SHIFT; | 1125 | off = vma->vm_pgoff << PAGE_SHIFT; |
1105 | 1126 | ||
1106 | rg = ofbi->region; | 1127 | rg = omapfb_get_mem_region(ofbi->region); |
1107 | 1128 | ||
1108 | start = omapfb_get_region_paddr(ofbi); | 1129 | start = omapfb_get_region_paddr(ofbi); |
1109 | len = fix->smem_len; | 1130 | len = fix->smem_len; |
1110 | if (off >= len) | 1131 | if (off >= len) |
1111 | return -EINVAL; | 1132 | goto error; |
1112 | if ((vma->vm_end - vma->vm_start + off) > len) | 1133 | if ((vma->vm_end - vma->vm_start + off) > len) |
1113 | return -EINVAL; | 1134 | goto error; |
1114 | 1135 | ||
1115 | off += start; | 1136 | off += start; |
1116 | 1137 | ||
@@ -1122,11 +1143,23 @@ static int omapfb_mmap(struct fb_info *fbi, struct vm_area_struct *vma) | |||
1122 | vma->vm_ops = &mmap_user_ops; | 1143 | vma->vm_ops = &mmap_user_ops; |
1123 | vma->vm_private_data = rg; | 1144 | vma->vm_private_data = rg; |
1124 | if (io_remap_pfn_range(vma, vma->vm_start, off >> PAGE_SHIFT, | 1145 | if (io_remap_pfn_range(vma, vma->vm_start, off >> PAGE_SHIFT, |
1125 | vma->vm_end - vma->vm_start, vma->vm_page_prot)) | 1146 | vma->vm_end - vma->vm_start, |
1126 | return -EAGAIN; | 1147 | vma->vm_page_prot)) { |
1148 | r = -EAGAIN; | ||
1149 | goto error; | ||
1150 | } | ||
1151 | |||
1127 | /* vm_ops.open won't be called for mmap itself. */ | 1152 | /* vm_ops.open won't be called for mmap itself. */ |
1128 | atomic_inc(&rg->map_count); | 1153 | atomic_inc(&rg->map_count); |
1154 | |||
1155 | omapfb_put_mem_region(rg); | ||
1156 | |||
1129 | return 0; | 1157 | return 0; |
1158 | |||
1159 | error: | ||
1160 | omapfb_put_mem_region(ofbi->region); | ||
1161 | |||
1162 | return r; | ||
1130 | } | 1163 | } |
1131 | 1164 | ||
1132 | /* Store a single color palette entry into a pseudo palette or the hardware | 1165 | /* Store a single color palette entry into a pseudo palette or the hardware |
@@ -1897,6 +1930,7 @@ static int omapfb_create_framebuffers(struct omapfb2_device *fbdev) | |||
1897 | 1930 | ||
1898 | ofbi->region = &fbdev->regions[i]; | 1931 | ofbi->region = &fbdev->regions[i]; |
1899 | ofbi->region->id = i; | 1932 | ofbi->region->id = i; |
1933 | mutex_init(&ofbi->region->mtx); | ||
1900 | 1934 | ||
1901 | /* assign these early, so that fb alloc can use them */ | 1935 | /* assign these early, so that fb alloc can use them */ |
1902 | ofbi->rotation_type = def_vrfb ? OMAP_DSS_ROT_VRFB : | 1936 | ofbi->rotation_type = def_vrfb ? OMAP_DSS_ROT_VRFB : |
@@ -1927,7 +1961,13 @@ static int omapfb_create_framebuffers(struct omapfb2_device *fbdev) | |||
1927 | 1961 | ||
1928 | /* setup fb_infos */ | 1962 | /* setup fb_infos */ |
1929 | for (i = 0; i < fbdev->num_fbs; i++) { | 1963 | for (i = 0; i < fbdev->num_fbs; i++) { |
1930 | r = omapfb_fb_init(fbdev, fbdev->fbs[i]); | 1964 | struct fb_info *fbi = fbdev->fbs[i]; |
1965 | struct omapfb_info *ofbi = FB2OFB(fbi); | ||
1966 | |||
1967 | omapfb_get_mem_region(ofbi->region); | ||
1968 | r = omapfb_fb_init(fbdev, fbi); | ||
1969 | omapfb_put_mem_region(ofbi->region); | ||
1970 | |||
1931 | if (r) { | 1971 | if (r) { |
1932 | dev_err(fbdev->dev, "failed to setup fb_info\n"); | 1972 | dev_err(fbdev->dev, "failed to setup fb_info\n"); |
1933 | return r; | 1973 | return r; |
@@ -1948,7 +1988,13 @@ static int omapfb_create_framebuffers(struct omapfb2_device *fbdev) | |||
1948 | DBG("framebuffers registered\n"); | 1988 | DBG("framebuffers registered\n"); |
1949 | 1989 | ||
1950 | for (i = 0; i < fbdev->num_fbs; i++) { | 1990 | for (i = 0; i < fbdev->num_fbs; i++) { |
1951 | r = omapfb_apply_changes(fbdev->fbs[i], 1); | 1991 | struct fb_info *fbi = fbdev->fbs[i]; |
1992 | struct omapfb_info *ofbi = FB2OFB(fbi); | ||
1993 | |||
1994 | omapfb_get_mem_region(ofbi->region); | ||
1995 | r = omapfb_apply_changes(fbi, 1); | ||
1996 | omapfb_put_mem_region(ofbi->region); | ||
1997 | |||
1952 | if (r) { | 1998 | if (r) { |
1953 | dev_err(fbdev->dev, "failed to change mode\n"); | 1999 | dev_err(fbdev->dev, "failed to change mode\n"); |
1954 | return r; | 2000 | return r; |
diff --git a/drivers/video/omap2/omapfb/omapfb-sysfs.c b/drivers/video/omap2/omapfb/omapfb-sysfs.c index dea1aa46a7db..74c11b243100 100644 --- a/drivers/video/omap2/omapfb/omapfb-sysfs.c +++ b/drivers/video/omap2/omapfb/omapfb-sysfs.c | |||
@@ -49,6 +49,7 @@ static ssize_t store_rotate_type(struct device *dev, | |||
49 | { | 49 | { |
50 | struct fb_info *fbi = dev_get_drvdata(dev); | 50 | struct fb_info *fbi = dev_get_drvdata(dev); |
51 | struct omapfb_info *ofbi = FB2OFB(fbi); | 51 | struct omapfb_info *ofbi = FB2OFB(fbi); |
52 | struct omapfb2_mem_region *rg; | ||
52 | enum omap_dss_rotation_type rot_type; | 53 | enum omap_dss_rotation_type rot_type; |
53 | int r; | 54 | int r; |
54 | 55 | ||
@@ -64,9 +65,11 @@ static ssize_t store_rotate_type(struct device *dev, | |||
64 | if (rot_type == ofbi->rotation_type) | 65 | if (rot_type == ofbi->rotation_type) |
65 | goto out; | 66 | goto out; |
66 | 67 | ||
67 | if (ofbi->region->size) { | 68 | rg = omapfb_get_mem_region(ofbi->region); |
69 | |||
70 | if (rg->size) { | ||
68 | r = -EBUSY; | 71 | r = -EBUSY; |
69 | goto out; | 72 | goto put_region; |
70 | } | 73 | } |
71 | 74 | ||
72 | ofbi->rotation_type = rot_type; | 75 | ofbi->rotation_type = rot_type; |
@@ -75,6 +78,8 @@ static ssize_t store_rotate_type(struct device *dev, | |||
75 | * Since the VRAM for this FB is not allocated at the moment we don't | 78 | * Since the VRAM for this FB is not allocated at the moment we don't |
76 | * need to do any further parameter checking at this point. | 79 | * need to do any further parameter checking at this point. |
77 | */ | 80 | */ |
81 | put_region: | ||
82 | omapfb_put_mem_region(rg); | ||
78 | out: | 83 | out: |
79 | unlock_fb_info(fbi); | 84 | unlock_fb_info(fbi); |
80 | 85 | ||
@@ -111,6 +116,8 @@ static ssize_t store_mirror(struct device *dev, | |||
111 | 116 | ||
112 | ofbi->mirror = mirror; | 117 | ofbi->mirror = mirror; |
113 | 118 | ||
119 | omapfb_get_mem_region(ofbi->region); | ||
120 | |||
114 | memcpy(&new_var, &fbi->var, sizeof(new_var)); | 121 | memcpy(&new_var, &fbi->var, sizeof(new_var)); |
115 | r = check_fb_var(fbi, &new_var); | 122 | r = check_fb_var(fbi, &new_var); |
116 | if (r) | 123 | if (r) |
@@ -125,6 +132,8 @@ static ssize_t store_mirror(struct device *dev, | |||
125 | 132 | ||
126 | r = count; | 133 | r = count; |
127 | out: | 134 | out: |
135 | omapfb_put_mem_region(ofbi->region); | ||
136 | |||
128 | unlock_fb_info(fbi); | 137 | unlock_fb_info(fbi); |
129 | 138 | ||
130 | return r; | 139 | return r; |
@@ -263,11 +272,15 @@ static ssize_t store_overlays(struct device *dev, struct device_attribute *attr, | |||
263 | 272 | ||
264 | DBG("detaching %d\n", ofbi->overlays[i]->id); | 273 | DBG("detaching %d\n", ofbi->overlays[i]->id); |
265 | 274 | ||
275 | omapfb_get_mem_region(ofbi->region); | ||
276 | |||
266 | omapfb_overlay_enable(ovl, 0); | 277 | omapfb_overlay_enable(ovl, 0); |
267 | 278 | ||
268 | if (ovl->manager) | 279 | if (ovl->manager) |
269 | ovl->manager->apply(ovl->manager); | 280 | ovl->manager->apply(ovl->manager); |
270 | 281 | ||
282 | omapfb_put_mem_region(ofbi->region); | ||
283 | |||
271 | for (t = i + 1; t < ofbi->num_overlays; t++) { | 284 | for (t = i + 1; t < ofbi->num_overlays; t++) { |
272 | ofbi->rotation[t-1] = ofbi->rotation[t]; | 285 | ofbi->rotation[t-1] = ofbi->rotation[t]; |
273 | ofbi->overlays[t-1] = ofbi->overlays[t]; | 286 | ofbi->overlays[t-1] = ofbi->overlays[t]; |
@@ -300,7 +313,12 @@ static ssize_t store_overlays(struct device *dev, struct device_attribute *attr, | |||
300 | } | 313 | } |
301 | 314 | ||
302 | if (added) { | 315 | if (added) { |
316 | omapfb_get_mem_region(ofbi->region); | ||
317 | |||
303 | r = omapfb_apply_changes(fbi, 0); | 318 | r = omapfb_apply_changes(fbi, 0); |
319 | |||
320 | omapfb_put_mem_region(ofbi->region); | ||
321 | |||
304 | if (r) | 322 | if (r) |
305 | goto out; | 323 | goto out; |
306 | } | 324 | } |
@@ -388,7 +406,12 @@ static ssize_t store_overlays_rotate(struct device *dev, | |||
388 | for (i = 0; i < num_ovls; ++i) | 406 | for (i = 0; i < num_ovls; ++i) |
389 | ofbi->rotation[i] = rotation[i]; | 407 | ofbi->rotation[i] = rotation[i]; |
390 | 408 | ||
409 | omapfb_get_mem_region(ofbi->region); | ||
410 | |||
391 | r = omapfb_apply_changes(fbi, 0); | 411 | r = omapfb_apply_changes(fbi, 0); |
412 | |||
413 | omapfb_put_mem_region(ofbi->region); | ||
414 | |||
392 | if (r) | 415 | if (r) |
393 | goto out; | 416 | goto out; |
394 | 417 | ||
@@ -429,6 +452,14 @@ static ssize_t store_size(struct device *dev, struct device_attribute *attr, | |||
429 | 452 | ||
430 | rg = ofbi->region; | 453 | rg = ofbi->region; |
431 | 454 | ||
455 | /* FIXME probably should be a rwsem ... */ | ||
456 | mutex_lock(&rg->mtx); | ||
457 | while (rg->ref) { | ||
458 | mutex_unlock(&rg->mtx); | ||
459 | schedule(); | ||
460 | mutex_lock(&rg->mtx); | ||
461 | } | ||
462 | |||
432 | if (atomic_read(&rg->map_count)) { | 463 | if (atomic_read(&rg->map_count)) { |
433 | r = -EBUSY; | 464 | r = -EBUSY; |
434 | goto out; | 465 | goto out; |
@@ -459,6 +490,8 @@ static ssize_t store_size(struct device *dev, struct device_attribute *attr, | |||
459 | 490 | ||
460 | r = count; | 491 | r = count; |
461 | out: | 492 | out: |
493 | mutex_unlock(&rg->mtx); | ||
494 | |||
462 | unlock_fb_info(fbi); | 495 | unlock_fb_info(fbi); |
463 | 496 | ||
464 | return r; | 497 | return r; |
diff --git a/drivers/video/omap2/omapfb/omapfb.h b/drivers/video/omap2/omapfb/omapfb.h index 02f1ba9b228c..db3aef5172c5 100644 --- a/drivers/video/omap2/omapfb/omapfb.h +++ b/drivers/video/omap2/omapfb/omapfb.h | |||
@@ -52,6 +52,8 @@ struct omapfb2_mem_region { | |||
52 | u8 type; /* OMAPFB_PLANE_MEM_* */ | 52 | u8 type; /* OMAPFB_PLANE_MEM_* */ |
53 | bool alloc; /* allocated by the driver */ | 53 | bool alloc; /* allocated by the driver */ |
54 | bool map; /* kernel mapped by the driver */ | 54 | bool map; /* kernel mapped by the driver */ |
55 | struct mutex mtx; | ||
56 | unsigned int ref; | ||
55 | atomic_t map_count; | 57 | atomic_t map_count; |
56 | }; | 58 | }; |
57 | 59 | ||
@@ -159,4 +161,20 @@ static inline int omapfb_overlay_enable(struct omap_overlay *ovl, | |||
159 | return ovl->set_overlay_info(ovl, &info); | 161 | return ovl->set_overlay_info(ovl, &info); |
160 | } | 162 | } |
161 | 163 | ||
164 | static inline struct omapfb2_mem_region * | ||
165 | omapfb_get_mem_region(struct omapfb2_mem_region *rg) | ||
166 | { | ||
167 | mutex_lock(&rg->mtx); | ||
168 | rg->ref++; | ||
169 | mutex_unlock(&rg->mtx); | ||
170 | return rg; | ||
171 | } | ||
172 | |||
173 | static inline void omapfb_put_mem_region(struct omapfb2_mem_region *rg) | ||
174 | { | ||
175 | mutex_lock(&rg->mtx); | ||
176 | rg->ref--; | ||
177 | mutex_unlock(&rg->mtx); | ||
178 | } | ||
179 | |||
162 | #endif | 180 | #endif |