blob: be5eb074b7d31d091ab925cacc101eaaffb6579b [file] [log] [blame]
Tomi Valkeinenb39a982d2009-08-04 16:12:50 +03001/*
2 * linux/drivers/video/omap2/omapfb-sysfs.c
3 *
4 * Copyright (C) 2008 Nokia Corporation
5 * Author: Tomi Valkeinen <tomi.valkeinen@nokia.com>
6 *
7 * Some code and ideas taken from drivers/video/omap/ driver
8 * by Imre Deak.
9 *
10 * This program is free software; you can redistribute it and/or modify it
11 * under the terms of the GNU General Public License version 2 as published by
12 * the Free Software Foundation.
13 *
14 * This program is distributed in the hope that it will be useful, but WITHOUT
15 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
16 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
17 * more details.
18 *
19 * You should have received a copy of the GNU General Public License along with
20 * this program. If not, see <http://www.gnu.org/licenses/>.
21 */
22
23#include <linux/fb.h>
24#include <linux/sysfs.h>
25#include <linux/device.h>
26#include <linux/uaccess.h>
27#include <linux/platform_device.h>
28#include <linux/kernel.h>
29#include <linux/mm.h>
30#include <linux/omapfb.h>
31
Tomi Valkeinena0b38cc2011-05-11 14:05:07 +030032#include <video/omapdss.h>
Tomi Valkeinen6a1c9f62012-10-08 14:52:24 +030033#include <video/omapvrfb.h>
Tomi Valkeinenb39a982d2009-08-04 16:12:50 +030034
35#include "omapfb.h"
36
37static ssize_t show_rotate_type(struct device *dev,
38 struct device_attribute *attr, char *buf)
39{
40 struct fb_info *fbi = dev_get_drvdata(dev);
41 struct omapfb_info *ofbi = FB2OFB(fbi);
42
43 return snprintf(buf, PAGE_SIZE, "%d\n", ofbi->rotation_type);
44}
45
46static ssize_t store_rotate_type(struct device *dev,
47 struct device_attribute *attr,
48 const char *buf, size_t count)
49{
50 struct fb_info *fbi = dev_get_drvdata(dev);
51 struct omapfb_info *ofbi = FB2OFB(fbi);
Tomi Valkeinenb41deec2012-12-04 14:55:18 +020052 struct omapfb2_device *fbdev = ofbi->fbdev;
Ville Syrjälä430571d2010-03-17 20:43:23 +020053 struct omapfb2_mem_region *rg;
Tomi Valkeinene3502ce2011-04-04 15:40:23 +030054 int rot_type;
Tomi Valkeinenb39a982d2009-08-04 16:12:50 +030055 int r;
56
Tomi Valkeinene3502ce2011-04-04 15:40:23 +030057 r = kstrtoint(buf, 0, &rot_type);
58 if (r)
59 return r;
Tomi Valkeinenb39a982d2009-08-04 16:12:50 +030060
61 if (rot_type != OMAP_DSS_ROT_DMA && rot_type != OMAP_DSS_ROT_VRFB)
62 return -EINVAL;
63
Jani Nikula27b67c92010-03-18 10:32:06 +010064 if (!lock_fb_info(fbi))
65 return -ENODEV;
Tomi Valkeinenb41deec2012-12-04 14:55:18 +020066 omapfb_lock(fbdev);
Tomi Valkeinenb39a982d2009-08-04 16:12:50 +030067
68 r = 0;
69 if (rot_type == ofbi->rotation_type)
70 goto out;
71
Tomi Valkeinenb41deec2012-12-04 14:55:18 +020072 rg = ofbi->region;
Ville Syrjälä430571d2010-03-17 20:43:23 +020073
74 if (rg->size) {
Tomi Valkeinenb39a982d2009-08-04 16:12:50 +030075 r = -EBUSY;
Ville Syrjälä430571d2010-03-17 20:43:23 +020076 goto put_region;
Tomi Valkeinenb39a982d2009-08-04 16:12:50 +030077 }
78
79 ofbi->rotation_type = rot_type;
80
81 /*
82 * Since the VRAM for this FB is not allocated at the moment we don't
83 * need to do any further parameter checking at this point.
84 */
Ville Syrjälä430571d2010-03-17 20:43:23 +020085put_region:
Tomi Valkeinenb39a982d2009-08-04 16:12:50 +030086out:
Tomi Valkeinenb41deec2012-12-04 14:55:18 +020087 omapfb_unlock(fbdev);
Tomi Valkeinenb39a982d2009-08-04 16:12:50 +030088 unlock_fb_info(fbi);
89
90 return r ? r : count;
91}
92
93
94static ssize_t show_mirror(struct device *dev,
95 struct device_attribute *attr, char *buf)
96{
97 struct fb_info *fbi = dev_get_drvdata(dev);
98 struct omapfb_info *ofbi = FB2OFB(fbi);
99
100 return snprintf(buf, PAGE_SIZE, "%d\n", ofbi->mirror);
101}
102
103static ssize_t store_mirror(struct device *dev,
104 struct device_attribute *attr,
105 const char *buf, size_t count)
106{
107 struct fb_info *fbi = dev_get_drvdata(dev);
108 struct omapfb_info *ofbi = FB2OFB(fbi);
Tomi Valkeinenb41deec2012-12-04 14:55:18 +0200109 struct omapfb2_device *fbdev = ofbi->fbdev;
Tomi Valkeinen7fbf1bb2011-08-15 15:56:54 +0300110 bool mirror;
Tomi Valkeinenb39a982d2009-08-04 16:12:50 +0300111 int r;
112 struct fb_var_screeninfo new_var;
113
Tomi Valkeinen7fbf1bb2011-08-15 15:56:54 +0300114 r = strtobool(buf, &mirror);
Tomi Valkeinene3502ce2011-04-04 15:40:23 +0300115 if (r)
116 return r;
Tomi Valkeinenb39a982d2009-08-04 16:12:50 +0300117
Jani Nikula27b67c92010-03-18 10:32:06 +0100118 if (!lock_fb_info(fbi))
119 return -ENODEV;
Tomi Valkeinenb41deec2012-12-04 14:55:18 +0200120 omapfb_lock(fbdev);
Tomi Valkeinenb39a982d2009-08-04 16:12:50 +0300121
122 ofbi->mirror = mirror;
123
124 memcpy(&new_var, &fbi->var, sizeof(new_var));
125 r = check_fb_var(fbi, &new_var);
126 if (r)
127 goto out;
128 memcpy(&fbi->var, &new_var, sizeof(fbi->var));
129
130 set_fb_fix(fbi);
131
132 r = omapfb_apply_changes(fbi, 0);
133 if (r)
134 goto out;
135
136 r = count;
137out:
Tomi Valkeinenb41deec2012-12-04 14:55:18 +0200138 omapfb_unlock(fbdev);
Tomi Valkeinenb39a982d2009-08-04 16:12:50 +0300139 unlock_fb_info(fbi);
140
141 return r;
142}
143
144static ssize_t show_overlays(struct device *dev,
145 struct device_attribute *attr, char *buf)
146{
147 struct fb_info *fbi = dev_get_drvdata(dev);
148 struct omapfb_info *ofbi = FB2OFB(fbi);
149 struct omapfb2_device *fbdev = ofbi->fbdev;
150 ssize_t l = 0;
151 int t;
152
Jani Nikula27b67c92010-03-18 10:32:06 +0100153 if (!lock_fb_info(fbi))
154 return -ENODEV;
Jani Nikula238a4132010-03-18 10:32:05 +0100155 omapfb_lock(fbdev);
Tomi Valkeinenb39a982d2009-08-04 16:12:50 +0300156
157 for (t = 0; t < ofbi->num_overlays; t++) {
158 struct omap_overlay *ovl = ofbi->overlays[t];
159 int ovlnum;
160
161 for (ovlnum = 0; ovlnum < fbdev->num_overlays; ++ovlnum)
162 if (ovl == fbdev->overlays[ovlnum])
163 break;
164
165 l += snprintf(buf + l, PAGE_SIZE - l, "%s%d",
166 t == 0 ? "" : ",", ovlnum);
167 }
168
169 l += snprintf(buf + l, PAGE_SIZE - l, "\n");
170
Tomi Valkeinenb39a982d2009-08-04 16:12:50 +0300171 omapfb_unlock(fbdev);
Jani Nikula238a4132010-03-18 10:32:05 +0100172 unlock_fb_info(fbi);
Tomi Valkeinenb39a982d2009-08-04 16:12:50 +0300173
174 return l;
175}
176
177static struct omapfb_info *get_overlay_fb(struct omapfb2_device *fbdev,
178 struct omap_overlay *ovl)
179{
180 int i, t;
181
182 for (i = 0; i < fbdev->num_fbs; i++) {
183 struct omapfb_info *ofbi = FB2OFB(fbdev->fbs[i]);
184
185 for (t = 0; t < ofbi->num_overlays; t++) {
186 if (ofbi->overlays[t] == ovl)
187 return ofbi;
188 }
189 }
190
191 return NULL;
192}
193
194static ssize_t store_overlays(struct device *dev, struct device_attribute *attr,
195 const char *buf, size_t count)
196{
197 struct fb_info *fbi = dev_get_drvdata(dev);
198 struct omapfb_info *ofbi = FB2OFB(fbi);
199 struct omapfb2_device *fbdev = ofbi->fbdev;
200 struct omap_overlay *ovls[OMAPFB_MAX_OVL_PER_FB];
201 struct omap_overlay *ovl;
202 int num_ovls, r, i;
203 int len;
204 bool added = false;
205
206 num_ovls = 0;
207
208 len = strlen(buf);
209 if (buf[len - 1] == '\n')
210 len = len - 1;
211
Jani Nikula27b67c92010-03-18 10:32:06 +0100212 if (!lock_fb_info(fbi))
213 return -ENODEV;
Jani Nikula238a4132010-03-18 10:32:05 +0100214 omapfb_lock(fbdev);
Tomi Valkeinenb39a982d2009-08-04 16:12:50 +0300215
216 if (len > 0) {
217 char *p = (char *)buf;
218 int ovlnum;
219
220 while (p < buf + len) {
221 int found;
222 if (num_ovls == OMAPFB_MAX_OVL_PER_FB) {
223 r = -EINVAL;
224 goto out;
225 }
226
227 ovlnum = simple_strtoul(p, &p, 0);
228 if (ovlnum > fbdev->num_overlays) {
229 r = -EINVAL;
230 goto out;
231 }
232
233 found = 0;
234 for (i = 0; i < num_ovls; ++i) {
235 if (ovls[i] == fbdev->overlays[ovlnum]) {
236 found = 1;
237 break;
238 }
239 }
240
241 if (!found)
242 ovls[num_ovls++] = fbdev->overlays[ovlnum];
243
244 p++;
245 }
246 }
247
248 for (i = 0; i < num_ovls; ++i) {
249 struct omapfb_info *ofbi2 = get_overlay_fb(fbdev, ovls[i]);
250 if (ofbi2 && ofbi2 != ofbi) {
251 dev_err(fbdev->dev, "overlay already in use\n");
252 r = -EINVAL;
253 goto out;
254 }
255 }
256
257 /* detach unused overlays */
258 for (i = 0; i < ofbi->num_overlays; ++i) {
259 int t, found;
260
261 ovl = ofbi->overlays[i];
262
263 found = 0;
264
265 for (t = 0; t < num_ovls; ++t) {
266 if (ovl == ovls[t]) {
267 found = 1;
268 break;
269 }
270 }
271
272 if (found)
273 continue;
274
275 DBG("detaching %d\n", ofbi->overlays[i]->id);
276
277 omapfb_overlay_enable(ovl, 0);
278
279 if (ovl->manager)
280 ovl->manager->apply(ovl->manager);
281
282 for (t = i + 1; t < ofbi->num_overlays; t++) {
283 ofbi->rotation[t-1] = ofbi->rotation[t];
284 ofbi->overlays[t-1] = ofbi->overlays[t];
285 }
286
287 ofbi->num_overlays--;
288 i--;
289 }
290
291 for (i = 0; i < num_ovls; ++i) {
292 int t, found;
293
294 ovl = ovls[i];
295
296 found = 0;
297
298 for (t = 0; t < ofbi->num_overlays; ++t) {
299 if (ovl == ofbi->overlays[t]) {
300 found = 1;
301 break;
302 }
303 }
304
305 if (found)
306 continue;
307 ofbi->rotation[ofbi->num_overlays] = 0;
308 ofbi->overlays[ofbi->num_overlays++] = ovl;
309
310 added = true;
311 }
312
313 if (added) {
314 r = omapfb_apply_changes(fbi, 0);
Ville Syrjälä430571d2010-03-17 20:43:23 +0200315
Tomi Valkeinenb39a982d2009-08-04 16:12:50 +0300316 if (r)
317 goto out;
318 }
319
320 r = count;
321out:
Tomi Valkeinenb39a982d2009-08-04 16:12:50 +0300322 omapfb_unlock(fbdev);
Jani Nikula238a4132010-03-18 10:32:05 +0100323 unlock_fb_info(fbi);
Tomi Valkeinenb39a982d2009-08-04 16:12:50 +0300324
325 return r;
326}
327
328static ssize_t show_overlays_rotate(struct device *dev,
329 struct device_attribute *attr, char *buf)
330{
331 struct fb_info *fbi = dev_get_drvdata(dev);
332 struct omapfb_info *ofbi = FB2OFB(fbi);
Tomi Valkeinenb41deec2012-12-04 14:55:18 +0200333 struct omapfb2_device *fbdev = ofbi->fbdev;
Tomi Valkeinenb39a982d2009-08-04 16:12:50 +0300334 ssize_t l = 0;
335 int t;
336
Jani Nikula27b67c92010-03-18 10:32:06 +0100337 if (!lock_fb_info(fbi))
338 return -ENODEV;
Tomi Valkeinenb41deec2012-12-04 14:55:18 +0200339 omapfb_lock(fbdev);
Tomi Valkeinenb39a982d2009-08-04 16:12:50 +0300340
341 for (t = 0; t < ofbi->num_overlays; t++) {
342 l += snprintf(buf + l, PAGE_SIZE - l, "%s%d",
343 t == 0 ? "" : ",", ofbi->rotation[t]);
344 }
345
346 l += snprintf(buf + l, PAGE_SIZE - l, "\n");
347
Tomi Valkeinenb41deec2012-12-04 14:55:18 +0200348 omapfb_unlock(fbdev);
Tomi Valkeinenb39a982d2009-08-04 16:12:50 +0300349 unlock_fb_info(fbi);
350
351 return l;
352}
353
354static ssize_t store_overlays_rotate(struct device *dev,
355 struct device_attribute *attr, const char *buf, size_t count)
356{
357 struct fb_info *fbi = dev_get_drvdata(dev);
358 struct omapfb_info *ofbi = FB2OFB(fbi);
Tomi Valkeinenb41deec2012-12-04 14:55:18 +0200359 struct omapfb2_device *fbdev = ofbi->fbdev;
Tomi Valkeinenb39a982d2009-08-04 16:12:50 +0300360 int num_ovls = 0, r, i;
361 int len;
362 bool changed = false;
363 u8 rotation[OMAPFB_MAX_OVL_PER_FB];
364
365 len = strlen(buf);
366 if (buf[len - 1] == '\n')
367 len = len - 1;
368
Jani Nikula27b67c92010-03-18 10:32:06 +0100369 if (!lock_fb_info(fbi))
370 return -ENODEV;
Tomi Valkeinenb41deec2012-12-04 14:55:18 +0200371 omapfb_lock(fbdev);
Tomi Valkeinenb39a982d2009-08-04 16:12:50 +0300372
373 if (len > 0) {
374 char *p = (char *)buf;
375
376 while (p < buf + len) {
377 int rot;
378
379 if (num_ovls == ofbi->num_overlays) {
380 r = -EINVAL;
381 goto out;
382 }
383
384 rot = simple_strtoul(p, &p, 0);
385 if (rot < 0 || rot > 3) {
386 r = -EINVAL;
387 goto out;
388 }
389
390 if (ofbi->rotation[num_ovls] != rot)
391 changed = true;
392
393 rotation[num_ovls++] = rot;
394
395 p++;
396 }
397 }
398
399 if (num_ovls != ofbi->num_overlays) {
400 r = -EINVAL;
401 goto out;
402 }
403
404 if (changed) {
405 for (i = 0; i < num_ovls; ++i)
406 ofbi->rotation[i] = rotation[i];
407
408 r = omapfb_apply_changes(fbi, 0);
409 if (r)
410 goto out;
411
412 /* FIXME error handling? */
413 }
414
415 r = count;
416out:
Tomi Valkeinenb41deec2012-12-04 14:55:18 +0200417 omapfb_unlock(fbdev);
Tomi Valkeinenb39a982d2009-08-04 16:12:50 +0300418 unlock_fb_info(fbi);
419
420 return r;
421}
422
423static ssize_t show_size(struct device *dev,
424 struct device_attribute *attr, char *buf)
425{
426 struct fb_info *fbi = dev_get_drvdata(dev);
427 struct omapfb_info *ofbi = FB2OFB(fbi);
Tomi Valkeinenb41deec2012-12-04 14:55:18 +0200428 struct omapfb2_device *fbdev = ofbi->fbdev;
429 int r;
Tomi Valkeinenb39a982d2009-08-04 16:12:50 +0300430
Tomi Valkeinenb41deec2012-12-04 14:55:18 +0200431 if (!lock_fb_info(fbi))
432 return -ENODEV;
433 omapfb_lock(fbdev);
434
435 r = snprintf(buf, PAGE_SIZE, "%lu\n", ofbi->region->size);
436
437 omapfb_unlock(fbdev);
438 unlock_fb_info(fbi);
439
440 return r;
Tomi Valkeinenb39a982d2009-08-04 16:12:50 +0300441}
442
443static ssize_t store_size(struct device *dev, struct device_attribute *attr,
444 const char *buf, size_t count)
445{
446 struct fb_info *fbi = dev_get_drvdata(dev);
447 struct omapfb_info *ofbi = FB2OFB(fbi);
Ville Syrjälä078ff542010-03-17 20:36:51 +0200448 struct omapfb2_device *fbdev = ofbi->fbdev;
Tomi Valkeinen636f4e12012-12-07 16:47:28 +0200449 struct omap_dss_device *display = fb2display(fbi);
Ville Syrjälä078ff542010-03-17 20:36:51 +0200450 struct omapfb2_mem_region *rg;
Tomi Valkeinenb39a982d2009-08-04 16:12:50 +0300451 unsigned long size;
452 int r;
453 int i;
454
Tomi Valkeinene3502ce2011-04-04 15:40:23 +0300455 r = kstrtoul(buf, 0, &size);
456 if (r)
457 return r;
458
459 size = PAGE_ALIGN(size);
Tomi Valkeinenb39a982d2009-08-04 16:12:50 +0300460
Jani Nikula27b67c92010-03-18 10:32:06 +0100461 if (!lock_fb_info(fbi))
462 return -ENODEV;
Tomi Valkeinenb41deec2012-12-04 14:55:18 +0200463 omapfb_lock(fbdev);
Tomi Valkeinenb39a982d2009-08-04 16:12:50 +0300464
Tomi Valkeinen636f4e12012-12-07 16:47:28 +0200465 if (display && display->driver->sync)
466 display->driver->sync(display);
467
Tomi Valkeinenb41deec2012-12-04 14:55:18 +0200468 mutex_lock(&fbi->mm_lock);
Ville Syrjälä078ff542010-03-17 20:36:51 +0200469
Tomi Valkeinenb41deec2012-12-04 14:55:18 +0200470 rg = ofbi->region;
Ville Syrjälä430571d2010-03-17 20:43:23 +0200471
Ville Syrjälä078ff542010-03-17 20:36:51 +0200472 if (atomic_read(&rg->map_count)) {
473 r = -EBUSY;
474 goto out;
475 }
476
477 for (i = 0; i < fbdev->num_fbs; i++) {
478 struct omapfb_info *ofbi2 = FB2OFB(fbdev->fbs[i]);
479 int j;
480
481 if (ofbi2->region != rg)
482 continue;
483
484 for (j = 0; j < ofbi2->num_overlays; j++) {
Tomi Valkeinenaaa874a2011-11-15 16:37:53 +0200485 struct omap_overlay *ovl;
486 ovl = ofbi2->overlays[j];
487 if (ovl->is_enabled(ovl)) {
Ville Syrjälä078ff542010-03-17 20:36:51 +0200488 r = -EBUSY;
489 goto out;
490 }
Tomi Valkeinenb39a982d2009-08-04 16:12:50 +0300491 }
492 }
493
Ville Syrjälä078ff542010-03-17 20:36:51 +0200494 if (size != ofbi->region->size) {
495 r = omapfb_realloc_fbmem(fbi, size, ofbi->region->type);
Tomi Valkeinenb39a982d2009-08-04 16:12:50 +0300496 if (r) {
497 dev_err(dev, "realloc fbmem failed\n");
498 goto out;
499 }
500 }
501
502 r = count;
503out:
Tomi Valkeinenb41deec2012-12-04 14:55:18 +0200504 mutex_unlock(&fbi->mm_lock);
505 omapfb_unlock(fbdev);
Tomi Valkeinenb39a982d2009-08-04 16:12:50 +0300506 unlock_fb_info(fbi);
507
508 return r;
509}
510
511static ssize_t show_phys(struct device *dev,
512 struct device_attribute *attr, char *buf)
513{
514 struct fb_info *fbi = dev_get_drvdata(dev);
515 struct omapfb_info *ofbi = FB2OFB(fbi);
Tomi Valkeinenb41deec2012-12-04 14:55:18 +0200516 struct omapfb2_device *fbdev = ofbi->fbdev;
517 int r;
Tomi Valkeinenb39a982d2009-08-04 16:12:50 +0300518
Tomi Valkeinenb41deec2012-12-04 14:55:18 +0200519 if (!lock_fb_info(fbi))
520 return -ENODEV;
521 omapfb_lock(fbdev);
522
523 r = snprintf(buf, PAGE_SIZE, "%0x\n", ofbi->region->paddr);
524
525 omapfb_unlock(fbdev);
526 unlock_fb_info(fbi);
527
528 return r;
Tomi Valkeinenb39a982d2009-08-04 16:12:50 +0300529}
530
531static ssize_t show_virt(struct device *dev,
532 struct device_attribute *attr, char *buf)
533{
534 struct fb_info *fbi = dev_get_drvdata(dev);
535 struct omapfb_info *ofbi = FB2OFB(fbi);
536
Ville Syrjälä078ff542010-03-17 20:36:51 +0200537 return snprintf(buf, PAGE_SIZE, "%p\n", ofbi->region->vaddr);
Tomi Valkeinenb39a982d2009-08-04 16:12:50 +0300538}
539
Tomi Valkeinen27cc2132011-04-30 16:55:12 +0300540static ssize_t show_upd_mode(struct device *dev,
541 struct device_attribute *attr, char *buf)
542{
543 struct fb_info *fbi = dev_get_drvdata(dev);
Tomi Valkeinenb41deec2012-12-04 14:55:18 +0200544 struct omapfb_info *ofbi = FB2OFB(fbi);
545 struct omapfb2_device *fbdev = ofbi->fbdev;
Tomi Valkeinen27cc2132011-04-30 16:55:12 +0300546 enum omapfb_update_mode mode;
547 int r;
548
Tomi Valkeinenb41deec2012-12-04 14:55:18 +0200549 if (!lock_fb_info(fbi))
550 return -ENODEV;
551 omapfb_lock(fbdev);
552
Tomi Valkeinen27cc2132011-04-30 16:55:12 +0300553 r = omapfb_get_update_mode(fbi, &mode);
554
Tomi Valkeinenb41deec2012-12-04 14:55:18 +0200555 omapfb_unlock(fbdev);
556 unlock_fb_info(fbi);
557
Tomi Valkeinen27cc2132011-04-30 16:55:12 +0300558 if (r)
559 return r;
560
561 return snprintf(buf, PAGE_SIZE, "%u\n", (unsigned)mode);
562}
563
564static ssize_t store_upd_mode(struct device *dev, struct device_attribute *attr,
565 const char *buf, size_t count)
566{
567 struct fb_info *fbi = dev_get_drvdata(dev);
Tomi Valkeinenb41deec2012-12-04 14:55:18 +0200568 struct omapfb_info *ofbi = FB2OFB(fbi);
569 struct omapfb2_device *fbdev = ofbi->fbdev;
Tomi Valkeinen27cc2132011-04-30 16:55:12 +0300570 unsigned mode;
571 int r;
572
573 r = kstrtouint(buf, 0, &mode);
574 if (r)
575 return r;
576
Tomi Valkeinenb41deec2012-12-04 14:55:18 +0200577 if (!lock_fb_info(fbi))
578 return -ENODEV;
579 omapfb_lock(fbdev);
580
Tomi Valkeinen27cc2132011-04-30 16:55:12 +0300581 r = omapfb_set_update_mode(fbi, mode);
582 if (r)
583 return r;
584
Tomi Valkeinenb41deec2012-12-04 14:55:18 +0200585 omapfb_unlock(fbdev);
586 unlock_fb_info(fbi);
587
Tomi Valkeinen27cc2132011-04-30 16:55:12 +0300588 return count;
589}
590
Tomi Valkeinenb39a982d2009-08-04 16:12:50 +0300591static struct device_attribute omapfb_attrs[] = {
592 __ATTR(rotate_type, S_IRUGO | S_IWUSR, show_rotate_type,
593 store_rotate_type),
594 __ATTR(mirror, S_IRUGO | S_IWUSR, show_mirror, store_mirror),
595 __ATTR(size, S_IRUGO | S_IWUSR, show_size, store_size),
596 __ATTR(overlays, S_IRUGO | S_IWUSR, show_overlays, store_overlays),
597 __ATTR(overlays_rotate, S_IRUGO | S_IWUSR, show_overlays_rotate,
598 store_overlays_rotate),
599 __ATTR(phys_addr, S_IRUGO, show_phys, NULL),
600 __ATTR(virt_addr, S_IRUGO, show_virt, NULL),
Tomi Valkeinen27cc2132011-04-30 16:55:12 +0300601 __ATTR(update_mode, S_IRUGO | S_IWUSR, show_upd_mode, store_upd_mode),
Tomi Valkeinenb39a982d2009-08-04 16:12:50 +0300602};
603
604int omapfb_create_sysfs(struct omapfb2_device *fbdev)
605{
606 int i;
607 int r;
608
609 DBG("create sysfs for fbs\n");
610 for (i = 0; i < fbdev->num_fbs; i++) {
611 int t;
612 for (t = 0; t < ARRAY_SIZE(omapfb_attrs); t++) {
613 r = device_create_file(fbdev->fbs[i]->dev,
614 &omapfb_attrs[t]);
615
616 if (r) {
617 dev_err(fbdev->dev, "failed to create sysfs "
618 "file\n");
619 return r;
620 }
621 }
622 }
623
624 return 0;
625}
626
627void omapfb_remove_sysfs(struct omapfb2_device *fbdev)
628{
629 int i, t;
630
631 DBG("remove sysfs for fbs\n");
632 for (i = 0; i < fbdev->num_fbs; i++) {
633 for (t = 0; t < ARRAY_SIZE(omapfb_attrs); t++)
634 device_remove_file(fbdev->fbs[i]->dev,
635 &omapfb_attrs[t]);
636 }
637}
638