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 struct omapfb2_mem_region
*rg
;
53 enum omap_dss_rotation_type rot_type
;
56 rot_type
= simple_strtoul(buf
, NULL
, 0);
58 if (rot_type
!= OMAP_DSS_ROT_DMA
&& rot_type
!= OMAP_DSS_ROT_VRFB
)
61 if (!lock_fb_info(fbi
))
65 if (rot_type
== ofbi
->rotation_type
)
68 rg
= omapfb_get_mem_region(ofbi
->region
);
75 ofbi
->rotation_type
= rot_type
;
78 * Since the VRAM for this FB is not allocated at the moment we don't
79 * need to do any further parameter checking at this point.
82 omapfb_put_mem_region(rg
);
90 static ssize_t
show_mirror(struct device
*dev
,
91 struct device_attribute
*attr
, char *buf
)
93 struct fb_info
*fbi
= dev_get_drvdata(dev
);
94 struct omapfb_info
*ofbi
= FB2OFB(fbi
);
96 return snprintf(buf
, PAGE_SIZE
, "%d\n", ofbi
->mirror
);
99 static ssize_t
store_mirror(struct device
*dev
,
100 struct device_attribute
*attr
,
101 const char *buf
, size_t count
)
103 struct fb_info
*fbi
= dev_get_drvdata(dev
);
104 struct omapfb_info
*ofbi
= FB2OFB(fbi
);
105 unsigned long mirror
;
107 struct fb_var_screeninfo new_var
;
109 mirror
= simple_strtoul(buf
, NULL
, 0);
111 if (mirror
!= 0 && mirror
!= 1)
114 if (!lock_fb_info(fbi
))
117 ofbi
->mirror
= mirror
;
119 omapfb_get_mem_region(ofbi
->region
);
121 memcpy(&new_var
, &fbi
->var
, sizeof(new_var
));
122 r
= check_fb_var(fbi
, &new_var
);
125 memcpy(&fbi
->var
, &new_var
, sizeof(fbi
->var
));
129 r
= omapfb_apply_changes(fbi
, 0);
135 omapfb_put_mem_region(ofbi
->region
);
142 static ssize_t
show_overlays(struct device
*dev
,
143 struct device_attribute
*attr
, char *buf
)
145 struct fb_info
*fbi
= dev_get_drvdata(dev
);
146 struct omapfb_info
*ofbi
= FB2OFB(fbi
);
147 struct omapfb2_device
*fbdev
= ofbi
->fbdev
;
151 if (!lock_fb_info(fbi
))
155 for (t
= 0; t
< ofbi
->num_overlays
; t
++) {
156 struct omap_overlay
*ovl
= ofbi
->overlays
[t
];
159 for (ovlnum
= 0; ovlnum
< fbdev
->num_overlays
; ++ovlnum
)
160 if (ovl
== fbdev
->overlays
[ovlnum
])
163 l
+= snprintf(buf
+ l
, PAGE_SIZE
- l
, "%s%d",
164 t
== 0 ? "" : ",", ovlnum
);
167 l
+= snprintf(buf
+ l
, PAGE_SIZE
- l
, "\n");
169 omapfb_unlock(fbdev
);
175 static struct omapfb_info
*get_overlay_fb(struct omapfb2_device
*fbdev
,
176 struct omap_overlay
*ovl
)
180 for (i
= 0; i
< fbdev
->num_fbs
; i
++) {
181 struct omapfb_info
*ofbi
= FB2OFB(fbdev
->fbs
[i
]);
183 for (t
= 0; t
< ofbi
->num_overlays
; t
++) {
184 if (ofbi
->overlays
[t
] == ovl
)
192 static ssize_t
store_overlays(struct device
*dev
, struct device_attribute
*attr
,
193 const char *buf
, size_t count
)
195 struct fb_info
*fbi
= dev_get_drvdata(dev
);
196 struct omapfb_info
*ofbi
= FB2OFB(fbi
);
197 struct omapfb2_device
*fbdev
= ofbi
->fbdev
;
198 struct omap_overlay
*ovls
[OMAPFB_MAX_OVL_PER_FB
];
199 struct omap_overlay
*ovl
;
207 if (buf
[len
- 1] == '\n')
210 if (!lock_fb_info(fbi
))
215 char *p
= (char *)buf
;
218 while (p
< buf
+ len
) {
220 if (num_ovls
== OMAPFB_MAX_OVL_PER_FB
) {
225 ovlnum
= simple_strtoul(p
, &p
, 0);
226 if (ovlnum
> fbdev
->num_overlays
) {
232 for (i
= 0; i
< num_ovls
; ++i
) {
233 if (ovls
[i
] == fbdev
->overlays
[ovlnum
]) {
240 ovls
[num_ovls
++] = fbdev
->overlays
[ovlnum
];
246 for (i
= 0; i
< num_ovls
; ++i
) {
247 struct omapfb_info
*ofbi2
= get_overlay_fb(fbdev
, ovls
[i
]);
248 if (ofbi2
&& ofbi2
!= ofbi
) {
249 dev_err(fbdev
->dev
, "overlay already in use\n");
255 /* detach unused overlays */
256 for (i
= 0; i
< ofbi
->num_overlays
; ++i
) {
259 ovl
= ofbi
->overlays
[i
];
263 for (t
= 0; t
< num_ovls
; ++t
) {
264 if (ovl
== ovls
[t
]) {
273 DBG("detaching %d\n", ofbi
->overlays
[i
]->id
);
275 omapfb_get_mem_region(ofbi
->region
);
277 omapfb_overlay_enable(ovl
, 0);
280 ovl
->manager
->apply(ovl
->manager
);
282 omapfb_put_mem_region(ofbi
->region
);
284 for (t
= i
+ 1; t
< ofbi
->num_overlays
; t
++) {
285 ofbi
->rotation
[t
-1] = ofbi
->rotation
[t
];
286 ofbi
->overlays
[t
-1] = ofbi
->overlays
[t
];
289 ofbi
->num_overlays
--;
293 for (i
= 0; i
< num_ovls
; ++i
) {
300 for (t
= 0; t
< ofbi
->num_overlays
; ++t
) {
301 if (ovl
== ofbi
->overlays
[t
]) {
309 ofbi
->rotation
[ofbi
->num_overlays
] = 0;
310 ofbi
->overlays
[ofbi
->num_overlays
++] = ovl
;
316 omapfb_get_mem_region(ofbi
->region
);
318 r
= omapfb_apply_changes(fbi
, 0);
320 omapfb_put_mem_region(ofbi
->region
);
328 omapfb_unlock(fbdev
);
334 static ssize_t
show_overlays_rotate(struct device
*dev
,
335 struct device_attribute
*attr
, char *buf
)
337 struct fb_info
*fbi
= dev_get_drvdata(dev
);
338 struct omapfb_info
*ofbi
= FB2OFB(fbi
);
342 if (!lock_fb_info(fbi
))
345 for (t
= 0; t
< ofbi
->num_overlays
; t
++) {
346 l
+= snprintf(buf
+ l
, PAGE_SIZE
- l
, "%s%d",
347 t
== 0 ? "" : ",", ofbi
->rotation
[t
]);
350 l
+= snprintf(buf
+ l
, PAGE_SIZE
- l
, "\n");
357 static ssize_t
store_overlays_rotate(struct device
*dev
,
358 struct device_attribute
*attr
, const char *buf
, size_t count
)
360 struct fb_info
*fbi
= dev_get_drvdata(dev
);
361 struct omapfb_info
*ofbi
= FB2OFB(fbi
);
362 int num_ovls
= 0, r
, i
;
364 bool changed
= false;
365 u8 rotation
[OMAPFB_MAX_OVL_PER_FB
];
368 if (buf
[len
- 1] == '\n')
371 if (!lock_fb_info(fbi
))
375 char *p
= (char *)buf
;
377 while (p
< buf
+ len
) {
380 if (num_ovls
== ofbi
->num_overlays
) {
385 rot
= simple_strtoul(p
, &p
, 0);
386 if (rot
< 0 || rot
> 3) {
391 if (ofbi
->rotation
[num_ovls
] != rot
)
394 rotation
[num_ovls
++] = rot
;
400 if (num_ovls
!= ofbi
->num_overlays
) {
406 for (i
= 0; i
< num_ovls
; ++i
)
407 ofbi
->rotation
[i
] = rotation
[i
];
409 omapfb_get_mem_region(ofbi
->region
);
411 r
= omapfb_apply_changes(fbi
, 0);
413 omapfb_put_mem_region(ofbi
->region
);
427 static ssize_t
show_size(struct device
*dev
,
428 struct device_attribute
*attr
, char *buf
)
430 struct fb_info
*fbi
= dev_get_drvdata(dev
);
431 struct omapfb_info
*ofbi
= FB2OFB(fbi
);
433 return snprintf(buf
, PAGE_SIZE
, "%lu\n", ofbi
->region
->size
);
436 static ssize_t
store_size(struct device
*dev
, struct device_attribute
*attr
,
437 const char *buf
, size_t count
)
439 struct fb_info
*fbi
= dev_get_drvdata(dev
);
440 struct omapfb_info
*ofbi
= FB2OFB(fbi
);
441 struct omapfb2_device
*fbdev
= ofbi
->fbdev
;
442 struct omapfb2_mem_region
*rg
;
447 size
= PAGE_ALIGN(simple_strtoul(buf
, NULL
, 0));
449 if (!lock_fb_info(fbi
))
454 down_write_nested(&rg
->lock
, rg
->id
);
455 atomic_inc(&rg
->lock_count
);
457 if (atomic_read(&rg
->map_count
)) {
462 for (i
= 0; i
< fbdev
->num_fbs
; i
++) {
463 struct omapfb_info
*ofbi2
= FB2OFB(fbdev
->fbs
[i
]);
466 if (ofbi2
->region
!= rg
)
469 for (j
= 0; j
< ofbi2
->num_overlays
; j
++) {
470 if (ofbi2
->overlays
[j
]->info
.enabled
) {
477 if (size
!= ofbi
->region
->size
) {
478 r
= omapfb_realloc_fbmem(fbi
, size
, ofbi
->region
->type
);
480 dev_err(dev
, "realloc fbmem failed\n");
487 atomic_dec(&rg
->lock_count
);
495 static ssize_t
show_phys(struct device
*dev
,
496 struct device_attribute
*attr
, char *buf
)
498 struct fb_info
*fbi
= dev_get_drvdata(dev
);
499 struct omapfb_info
*ofbi
= FB2OFB(fbi
);
501 return snprintf(buf
, PAGE_SIZE
, "%0x\n", ofbi
->region
->paddr
);
504 static ssize_t
show_virt(struct device
*dev
,
505 struct device_attribute
*attr
, char *buf
)
507 struct fb_info
*fbi
= dev_get_drvdata(dev
);
508 struct omapfb_info
*ofbi
= FB2OFB(fbi
);
510 return snprintf(buf
, PAGE_SIZE
, "%p\n", ofbi
->region
->vaddr
);
513 static struct device_attribute omapfb_attrs
[] = {
514 __ATTR(rotate_type
, S_IRUGO
| S_IWUSR
, show_rotate_type
,
516 __ATTR(mirror
, S_IRUGO
| S_IWUSR
, show_mirror
, store_mirror
),
517 __ATTR(size
, S_IRUGO
| S_IWUSR
, show_size
, store_size
),
518 __ATTR(overlays
, S_IRUGO
| S_IWUSR
, show_overlays
, store_overlays
),
519 __ATTR(overlays_rotate
, S_IRUGO
| S_IWUSR
, show_overlays_rotate
,
520 store_overlays_rotate
),
521 __ATTR(phys_addr
, S_IRUGO
, show_phys
, NULL
),
522 __ATTR(virt_addr
, S_IRUGO
, show_virt
, NULL
),
525 int omapfb_create_sysfs(struct omapfb2_device
*fbdev
)
530 DBG("create sysfs for fbs\n");
531 for (i
= 0; i
< fbdev
->num_fbs
; i
++) {
533 for (t
= 0; t
< ARRAY_SIZE(omapfb_attrs
); t
++) {
534 r
= device_create_file(fbdev
->fbs
[i
]->dev
,
538 dev_err(fbdev
->dev
, "failed to create sysfs "
548 void omapfb_remove_sysfs(struct omapfb2_device
*fbdev
)
552 DBG("remove sysfs for fbs\n");
553 for (i
= 0; i
< fbdev
->num_fbs
; i
++) {
554 for (t
= 0; t
< ARRAY_SIZE(omapfb_attrs
); t
++)
555 device_remove_file(fbdev
->fbs
[i
]->dev
,