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 <plat/display.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 enum omap_dss_rotation_type rot_type
;
55 rot_type
= simple_strtoul(buf
, NULL
, 0);
57 if (rot_type
!= OMAP_DSS_ROT_DMA
&& rot_type
!= OMAP_DSS_ROT_VRFB
)
63 if (rot_type
== ofbi
->rotation_type
)
66 if (ofbi
->region
.size
) {
71 ofbi
->rotation_type
= rot_type
;
74 * Since the VRAM for this FB is not allocated at the moment we don't
75 * need to do any further parameter checking at this point.
84 static ssize_t
show_mirror(struct device
*dev
,
85 struct device_attribute
*attr
, char *buf
)
87 struct fb_info
*fbi
= dev_get_drvdata(dev
);
88 struct omapfb_info
*ofbi
= FB2OFB(fbi
);
90 return snprintf(buf
, PAGE_SIZE
, "%d\n", ofbi
->mirror
);
93 static ssize_t
store_mirror(struct device
*dev
,
94 struct device_attribute
*attr
,
95 const char *buf
, size_t count
)
97 struct fb_info
*fbi
= dev_get_drvdata(dev
);
98 struct omapfb_info
*ofbi
= FB2OFB(fbi
);
101 struct fb_var_screeninfo new_var
;
103 mirror
= simple_strtoul(buf
, NULL
, 0);
105 if (mirror
!= 0 && mirror
!= 1)
110 ofbi
->mirror
= mirror
;
112 memcpy(&new_var
, &fbi
->var
, sizeof(new_var
));
113 r
= check_fb_var(fbi
, &new_var
);
116 memcpy(&fbi
->var
, &new_var
, sizeof(fbi
->var
));
120 r
= omapfb_apply_changes(fbi
, 0);
131 static ssize_t
show_overlays(struct device
*dev
,
132 struct device_attribute
*attr
, char *buf
)
134 struct fb_info
*fbi
= dev_get_drvdata(dev
);
135 struct omapfb_info
*ofbi
= FB2OFB(fbi
);
136 struct omapfb2_device
*fbdev
= ofbi
->fbdev
;
143 for (t
= 0; t
< ofbi
->num_overlays
; t
++) {
144 struct omap_overlay
*ovl
= ofbi
->overlays
[t
];
147 for (ovlnum
= 0; ovlnum
< fbdev
->num_overlays
; ++ovlnum
)
148 if (ovl
== fbdev
->overlays
[ovlnum
])
151 l
+= snprintf(buf
+ l
, PAGE_SIZE
- l
, "%s%d",
152 t
== 0 ? "" : ",", ovlnum
);
155 l
+= snprintf(buf
+ l
, PAGE_SIZE
- l
, "\n");
158 omapfb_unlock(fbdev
);
163 static struct omapfb_info
*get_overlay_fb(struct omapfb2_device
*fbdev
,
164 struct omap_overlay
*ovl
)
168 for (i
= 0; i
< fbdev
->num_fbs
; i
++) {
169 struct omapfb_info
*ofbi
= FB2OFB(fbdev
->fbs
[i
]);
171 for (t
= 0; t
< ofbi
->num_overlays
; t
++) {
172 if (ofbi
->overlays
[t
] == ovl
)
180 static ssize_t
store_overlays(struct device
*dev
, struct device_attribute
*attr
,
181 const char *buf
, size_t count
)
183 struct fb_info
*fbi
= dev_get_drvdata(dev
);
184 struct omapfb_info
*ofbi
= FB2OFB(fbi
);
185 struct omapfb2_device
*fbdev
= ofbi
->fbdev
;
186 struct omap_overlay
*ovls
[OMAPFB_MAX_OVL_PER_FB
];
187 struct omap_overlay
*ovl
;
195 if (buf
[len
- 1] == '\n')
202 char *p
= (char *)buf
;
205 while (p
< buf
+ len
) {
207 if (num_ovls
== OMAPFB_MAX_OVL_PER_FB
) {
212 ovlnum
= simple_strtoul(p
, &p
, 0);
213 if (ovlnum
> fbdev
->num_overlays
) {
219 for (i
= 0; i
< num_ovls
; ++i
) {
220 if (ovls
[i
] == fbdev
->overlays
[ovlnum
]) {
227 ovls
[num_ovls
++] = fbdev
->overlays
[ovlnum
];
233 for (i
= 0; i
< num_ovls
; ++i
) {
234 struct omapfb_info
*ofbi2
= get_overlay_fb(fbdev
, ovls
[i
]);
235 if (ofbi2
&& ofbi2
!= ofbi
) {
236 dev_err(fbdev
->dev
, "overlay already in use\n");
242 /* detach unused overlays */
243 for (i
= 0; i
< ofbi
->num_overlays
; ++i
) {
246 ovl
= ofbi
->overlays
[i
];
250 for (t
= 0; t
< num_ovls
; ++t
) {
251 if (ovl
== ovls
[t
]) {
260 DBG("detaching %d\n", ofbi
->overlays
[i
]->id
);
262 omapfb_overlay_enable(ovl
, 0);
265 ovl
->manager
->apply(ovl
->manager
);
267 for (t
= i
+ 1; t
< ofbi
->num_overlays
; t
++) {
268 ofbi
->rotation
[t
-1] = ofbi
->rotation
[t
];
269 ofbi
->overlays
[t
-1] = ofbi
->overlays
[t
];
272 ofbi
->num_overlays
--;
276 for (i
= 0; i
< num_ovls
; ++i
) {
283 for (t
= 0; t
< ofbi
->num_overlays
; ++t
) {
284 if (ovl
== ofbi
->overlays
[t
]) {
292 ofbi
->rotation
[ofbi
->num_overlays
] = 0;
293 ofbi
->overlays
[ofbi
->num_overlays
++] = ovl
;
299 r
= omapfb_apply_changes(fbi
, 0);
307 omapfb_unlock(fbdev
);
312 static ssize_t
show_overlays_rotate(struct device
*dev
,
313 struct device_attribute
*attr
, char *buf
)
315 struct fb_info
*fbi
= dev_get_drvdata(dev
);
316 struct omapfb_info
*ofbi
= FB2OFB(fbi
);
322 for (t
= 0; t
< ofbi
->num_overlays
; t
++) {
323 l
+= snprintf(buf
+ l
, PAGE_SIZE
- l
, "%s%d",
324 t
== 0 ? "" : ",", ofbi
->rotation
[t
]);
327 l
+= snprintf(buf
+ l
, PAGE_SIZE
- l
, "\n");
334 static ssize_t
store_overlays_rotate(struct device
*dev
,
335 struct device_attribute
*attr
, const char *buf
, size_t count
)
337 struct fb_info
*fbi
= dev_get_drvdata(dev
);
338 struct omapfb_info
*ofbi
= FB2OFB(fbi
);
339 int num_ovls
= 0, r
, i
;
341 bool changed
= false;
342 u8 rotation
[OMAPFB_MAX_OVL_PER_FB
];
345 if (buf
[len
- 1] == '\n')
351 char *p
= (char *)buf
;
353 while (p
< buf
+ len
) {
356 if (num_ovls
== ofbi
->num_overlays
) {
361 rot
= simple_strtoul(p
, &p
, 0);
362 if (rot
< 0 || rot
> 3) {
367 if (ofbi
->rotation
[num_ovls
] != rot
)
370 rotation
[num_ovls
++] = rot
;
376 if (num_ovls
!= ofbi
->num_overlays
) {
382 for (i
= 0; i
< num_ovls
; ++i
)
383 ofbi
->rotation
[i
] = rotation
[i
];
385 r
= omapfb_apply_changes(fbi
, 0);
389 /* FIXME error handling? */
399 static ssize_t
show_size(struct device
*dev
,
400 struct device_attribute
*attr
, char *buf
)
402 struct fb_info
*fbi
= dev_get_drvdata(dev
);
403 struct omapfb_info
*ofbi
= FB2OFB(fbi
);
405 return snprintf(buf
, PAGE_SIZE
, "%lu\n", ofbi
->region
.size
);
408 static ssize_t
store_size(struct device
*dev
, struct device_attribute
*attr
,
409 const char *buf
, size_t count
)
411 struct fb_info
*fbi
= dev_get_drvdata(dev
);
412 struct omapfb_info
*ofbi
= FB2OFB(fbi
);
417 size
= PAGE_ALIGN(simple_strtoul(buf
, NULL
, 0));
421 for (i
= 0; i
< ofbi
->num_overlays
; i
++) {
422 if (ofbi
->overlays
[i
]->info
.enabled
) {
428 if (size
!= ofbi
->region
.size
) {
429 r
= omapfb_realloc_fbmem(fbi
, size
, ofbi
->region
.type
);
431 dev_err(dev
, "realloc fbmem failed\n");
443 static ssize_t
show_phys(struct device
*dev
,
444 struct device_attribute
*attr
, char *buf
)
446 struct fb_info
*fbi
= dev_get_drvdata(dev
);
447 struct omapfb_info
*ofbi
= FB2OFB(fbi
);
449 return snprintf(buf
, PAGE_SIZE
, "%0x\n", ofbi
->region
.paddr
);
452 static ssize_t
show_virt(struct device
*dev
,
453 struct device_attribute
*attr
, char *buf
)
455 struct fb_info
*fbi
= dev_get_drvdata(dev
);
456 struct omapfb_info
*ofbi
= FB2OFB(fbi
);
458 return snprintf(buf
, PAGE_SIZE
, "%p\n", ofbi
->region
.vaddr
);
461 static struct device_attribute omapfb_attrs
[] = {
462 __ATTR(rotate_type
, S_IRUGO
| S_IWUSR
, show_rotate_type
,
464 __ATTR(mirror
, S_IRUGO
| S_IWUSR
, show_mirror
, store_mirror
),
465 __ATTR(size
, S_IRUGO
| S_IWUSR
, show_size
, store_size
),
466 __ATTR(overlays
, S_IRUGO
| S_IWUSR
, show_overlays
, store_overlays
),
467 __ATTR(overlays_rotate
, S_IRUGO
| S_IWUSR
, show_overlays_rotate
,
468 store_overlays_rotate
),
469 __ATTR(phys_addr
, S_IRUGO
, show_phys
, NULL
),
470 __ATTR(virt_addr
, S_IRUGO
, show_virt
, NULL
),
473 int omapfb_create_sysfs(struct omapfb2_device
*fbdev
)
478 DBG("create sysfs for fbs\n");
479 for (i
= 0; i
< fbdev
->num_fbs
; i
++) {
481 for (t
= 0; t
< ARRAY_SIZE(omapfb_attrs
); t
++) {
482 r
= device_create_file(fbdev
->fbs
[i
]->dev
,
486 dev_err(fbdev
->dev
, "failed to create sysfs "
496 void omapfb_remove_sysfs(struct omapfb2_device
*fbdev
)
500 DBG("remove sysfs for fbs\n");
501 for (i
= 0; i
< fbdev
->num_fbs
; i
++) {
502 for (t
= 0; t
< ARRAY_SIZE(omapfb_attrs
); t
++)
503 device_remove_file(fbdev
->fbs
[i
]->dev
,