2 * linux/drivers/video/omap2/omapfb-sysfs.c
4 * Copyright (C) 2008 Nokia Corporation
5 * Author: Tomi Valkeinen <tomi.valkeinen@nokia.com>
7 * Some code and ideas taken from drivers/video/omap/ driver
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.
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
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/>.
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>
30 #include <linux/omapfb.h>
32 #include <video/omapdss.h>
33 #include <plat/vrfb.h>
37 static ssize_t
show_rotate_type(struct device
*dev
,
38 struct device_attribute
*attr
, char *buf
)
40 struct fb_info
*fbi
= dev_get_drvdata(dev
);
41 struct omapfb_info
*ofbi
= FB2OFB(fbi
);
43 return snprintf(buf
, PAGE_SIZE
, "%d\n", ofbi
->rotation_type
);
46 static ssize_t
store_rotate_type(struct device
*dev
,
47 struct device_attribute
*attr
,
48 const char *buf
, size_t count
)
50 struct fb_info
*fbi
= dev_get_drvdata(dev
);
51 struct omapfb_info
*ofbi
= FB2OFB(fbi
);
52 struct omapfb2_mem_region
*rg
;
56 r
= kstrtoint(buf
, 0, &rot_type
);
60 if (rot_type
!= OMAP_DSS_ROT_DMA
&& rot_type
!= OMAP_DSS_ROT_VRFB
)
63 if (!lock_fb_info(fbi
))
67 if (rot_type
== ofbi
->rotation_type
)
70 rg
= omapfb_get_mem_region(ofbi
->region
);
77 ofbi
->rotation_type
= rot_type
;
80 * Since the VRAM for this FB is not allocated at the moment we don't
81 * need to do any further parameter checking at this point.
84 omapfb_put_mem_region(rg
);
92 static ssize_t
show_mirror(struct device
*dev
,
93 struct device_attribute
*attr
, char *buf
)
95 struct fb_info
*fbi
= dev_get_drvdata(dev
);
96 struct omapfb_info
*ofbi
= FB2OFB(fbi
);
98 return snprintf(buf
, PAGE_SIZE
, "%d\n", ofbi
->mirror
);
101 static ssize_t
store_mirror(struct device
*dev
,
102 struct device_attribute
*attr
,
103 const char *buf
, size_t count
)
105 struct fb_info
*fbi
= dev_get_drvdata(dev
);
106 struct omapfb_info
*ofbi
= FB2OFB(fbi
);
109 struct fb_var_screeninfo new_var
;
111 r
= kstrtoint(buf
, 0, &mirror
);
117 if (!lock_fb_info(fbi
))
120 ofbi
->mirror
= mirror
;
122 omapfb_get_mem_region(ofbi
->region
);
124 memcpy(&new_var
, &fbi
->var
, sizeof(new_var
));
125 r
= check_fb_var(fbi
, &new_var
);
128 memcpy(&fbi
->var
, &new_var
, sizeof(fbi
->var
));
132 r
= omapfb_apply_changes(fbi
, 0);
138 omapfb_put_mem_region(ofbi
->region
);
145 static ssize_t
show_overlays(struct device
*dev
,
146 struct device_attribute
*attr
, char *buf
)
148 struct fb_info
*fbi
= dev_get_drvdata(dev
);
149 struct omapfb_info
*ofbi
= FB2OFB(fbi
);
150 struct omapfb2_device
*fbdev
= ofbi
->fbdev
;
154 if (!lock_fb_info(fbi
))
158 for (t
= 0; t
< ofbi
->num_overlays
; t
++) {
159 struct omap_overlay
*ovl
= ofbi
->overlays
[t
];
162 for (ovlnum
= 0; ovlnum
< fbdev
->num_overlays
; ++ovlnum
)
163 if (ovl
== fbdev
->overlays
[ovlnum
])
166 l
+= snprintf(buf
+ l
, PAGE_SIZE
- l
, "%s%d",
167 t
== 0 ? "" : ",", ovlnum
);
170 l
+= snprintf(buf
+ l
, PAGE_SIZE
- l
, "\n");
172 omapfb_unlock(fbdev
);
178 static struct omapfb_info
*get_overlay_fb(struct omapfb2_device
*fbdev
,
179 struct omap_overlay
*ovl
)
183 for (i
= 0; i
< fbdev
->num_fbs
; i
++) {
184 struct omapfb_info
*ofbi
= FB2OFB(fbdev
->fbs
[i
]);
186 for (t
= 0; t
< ofbi
->num_overlays
; t
++) {
187 if (ofbi
->overlays
[t
] == ovl
)
195 static ssize_t
store_overlays(struct device
*dev
, struct device_attribute
*attr
,
196 const char *buf
, size_t count
)
198 struct fb_info
*fbi
= dev_get_drvdata(dev
);
199 struct omapfb_info
*ofbi
= FB2OFB(fbi
);
200 struct omapfb2_device
*fbdev
= ofbi
->fbdev
;
201 struct omap_overlay
*ovls
[OMAPFB_MAX_OVL_PER_FB
];
202 struct omap_overlay
*ovl
;
210 if (buf
[len
- 1] == '\n')
213 if (!lock_fb_info(fbi
))
218 char *p
= (char *)buf
;
221 while (p
< buf
+ len
) {
223 if (num_ovls
== OMAPFB_MAX_OVL_PER_FB
) {
228 ovlnum
= simple_strtoul(p
, &p
, 0);
229 if (ovlnum
> fbdev
->num_overlays
) {
235 for (i
= 0; i
< num_ovls
; ++i
) {
236 if (ovls
[i
] == fbdev
->overlays
[ovlnum
]) {
243 ovls
[num_ovls
++] = fbdev
->overlays
[ovlnum
];
249 for (i
= 0; i
< num_ovls
; ++i
) {
250 struct omapfb_info
*ofbi2
= get_overlay_fb(fbdev
, ovls
[i
]);
251 if (ofbi2
&& ofbi2
!= ofbi
) {
252 dev_err(fbdev
->dev
, "overlay already in use\n");
258 /* detach unused overlays */
259 for (i
= 0; i
< ofbi
->num_overlays
; ++i
) {
262 ovl
= ofbi
->overlays
[i
];
266 for (t
= 0; t
< num_ovls
; ++t
) {
267 if (ovl
== ovls
[t
]) {
276 DBG("detaching %d\n", ofbi
->overlays
[i
]->id
);
278 omapfb_get_mem_region(ofbi
->region
);
280 omapfb_overlay_enable(ovl
, 0);
283 ovl
->manager
->apply(ovl
->manager
);
285 omapfb_put_mem_region(ofbi
->region
);
287 for (t
= i
+ 1; t
< ofbi
->num_overlays
; t
++) {
288 ofbi
->rotation
[t
-1] = ofbi
->rotation
[t
];
289 ofbi
->overlays
[t
-1] = ofbi
->overlays
[t
];
292 ofbi
->num_overlays
--;
296 for (i
= 0; i
< num_ovls
; ++i
) {
303 for (t
= 0; t
< ofbi
->num_overlays
; ++t
) {
304 if (ovl
== ofbi
->overlays
[t
]) {
312 ofbi
->rotation
[ofbi
->num_overlays
] = 0;
313 ofbi
->overlays
[ofbi
->num_overlays
++] = ovl
;
319 omapfb_get_mem_region(ofbi
->region
);
321 r
= omapfb_apply_changes(fbi
, 0);
323 omapfb_put_mem_region(ofbi
->region
);
331 omapfb_unlock(fbdev
);
337 static ssize_t
show_overlays_rotate(struct device
*dev
,
338 struct device_attribute
*attr
, char *buf
)
340 struct fb_info
*fbi
= dev_get_drvdata(dev
);
341 struct omapfb_info
*ofbi
= FB2OFB(fbi
);
345 if (!lock_fb_info(fbi
))
348 for (t
= 0; t
< ofbi
->num_overlays
; t
++) {
349 l
+= snprintf(buf
+ l
, PAGE_SIZE
- l
, "%s%d",
350 t
== 0 ? "" : ",", ofbi
->rotation
[t
]);
353 l
+= snprintf(buf
+ l
, PAGE_SIZE
- l
, "\n");
360 static ssize_t
store_overlays_rotate(struct device
*dev
,
361 struct device_attribute
*attr
, const char *buf
, size_t count
)
363 struct fb_info
*fbi
= dev_get_drvdata(dev
);
364 struct omapfb_info
*ofbi
= FB2OFB(fbi
);
365 int num_ovls
= 0, r
, i
;
367 bool changed
= false;
368 u8 rotation
[OMAPFB_MAX_OVL_PER_FB
];
371 if (buf
[len
- 1] == '\n')
374 if (!lock_fb_info(fbi
))
378 char *p
= (char *)buf
;
380 while (p
< buf
+ len
) {
383 if (num_ovls
== ofbi
->num_overlays
) {
388 rot
= simple_strtoul(p
, &p
, 0);
389 if (rot
< 0 || rot
> 3) {
394 if (ofbi
->rotation
[num_ovls
] != rot
)
397 rotation
[num_ovls
++] = rot
;
403 if (num_ovls
!= ofbi
->num_overlays
) {
409 for (i
= 0; i
< num_ovls
; ++i
)
410 ofbi
->rotation
[i
] = rotation
[i
];
412 omapfb_get_mem_region(ofbi
->region
);
414 r
= omapfb_apply_changes(fbi
, 0);
416 omapfb_put_mem_region(ofbi
->region
);
421 /* FIXME error handling? */
431 static ssize_t
show_size(struct device
*dev
,
432 struct device_attribute
*attr
, char *buf
)
434 struct fb_info
*fbi
= dev_get_drvdata(dev
);
435 struct omapfb_info
*ofbi
= FB2OFB(fbi
);
437 return snprintf(buf
, PAGE_SIZE
, "%lu\n", ofbi
->region
->size
);
440 static ssize_t
store_size(struct device
*dev
, struct device_attribute
*attr
,
441 const char *buf
, size_t count
)
443 struct fb_info
*fbi
= dev_get_drvdata(dev
);
444 struct omapfb_info
*ofbi
= FB2OFB(fbi
);
445 struct omapfb2_device
*fbdev
= ofbi
->fbdev
;
446 struct omapfb2_mem_region
*rg
;
451 r
= kstrtoul(buf
, 0, &size
);
455 size
= PAGE_ALIGN(size
);
457 if (!lock_fb_info(fbi
))
462 down_write_nested(&rg
->lock
, rg
->id
);
463 atomic_inc(&rg
->lock_count
);
465 if (atomic_read(&rg
->map_count
)) {
470 for (i
= 0; i
< fbdev
->num_fbs
; i
++) {
471 struct omapfb_info
*ofbi2
= FB2OFB(fbdev
->fbs
[i
]);
474 if (ofbi2
->region
!= rg
)
477 for (j
= 0; j
< ofbi2
->num_overlays
; j
++) {
478 if (ofbi2
->overlays
[j
]->info
.enabled
) {
485 if (size
!= ofbi
->region
->size
) {
486 r
= omapfb_realloc_fbmem(fbi
, size
, ofbi
->region
->type
);
488 dev_err(dev
, "realloc fbmem failed\n");
495 atomic_dec(&rg
->lock_count
);
503 static ssize_t
show_phys(struct device
*dev
,
504 struct device_attribute
*attr
, char *buf
)
506 struct fb_info
*fbi
= dev_get_drvdata(dev
);
507 struct omapfb_info
*ofbi
= FB2OFB(fbi
);
509 return snprintf(buf
, PAGE_SIZE
, "%0x\n", ofbi
->region
->paddr
);
512 static ssize_t
show_virt(struct device
*dev
,
513 struct device_attribute
*attr
, char *buf
)
515 struct fb_info
*fbi
= dev_get_drvdata(dev
);
516 struct omapfb_info
*ofbi
= FB2OFB(fbi
);
518 return snprintf(buf
, PAGE_SIZE
, "%p\n", ofbi
->region
->vaddr
);
521 static struct device_attribute omapfb_attrs
[] = {
522 __ATTR(rotate_type
, S_IRUGO
| S_IWUSR
, show_rotate_type
,
524 __ATTR(mirror
, S_IRUGO
| S_IWUSR
, show_mirror
, store_mirror
),
525 __ATTR(size
, S_IRUGO
| S_IWUSR
, show_size
, store_size
),
526 __ATTR(overlays
, S_IRUGO
| S_IWUSR
, show_overlays
, store_overlays
),
527 __ATTR(overlays_rotate
, S_IRUGO
| S_IWUSR
, show_overlays_rotate
,
528 store_overlays_rotate
),
529 __ATTR(phys_addr
, S_IRUGO
, show_phys
, NULL
),
530 __ATTR(virt_addr
, S_IRUGO
, show_virt
, NULL
),
533 int omapfb_create_sysfs(struct omapfb2_device
*fbdev
)
538 DBG("create sysfs for fbs\n");
539 for (i
= 0; i
< fbdev
->num_fbs
; i
++) {
541 for (t
= 0; t
< ARRAY_SIZE(omapfb_attrs
); t
++) {
542 r
= device_create_file(fbdev
->fbs
[i
]->dev
,
546 dev_err(fbdev
->dev
, "failed to create sysfs "
556 void omapfb_remove_sysfs(struct omapfb2_device
*fbdev
)
560 DBG("remove sysfs for fbs\n");
561 for (i
= 0; i
< fbdev
->num_fbs
; i
++) {
562 for (t
= 0; t
< ARRAY_SIZE(omapfb_attrs
); t
++)
563 device_remove_file(fbdev
->fbs
[i
]->dev
,