1 // SPDX-License-Identifier: GPL-2.0-only
3 * linux/drivers/video/omap2/omapfb-sysfs.c
5 * Copyright (C) 2008 Nokia Corporation
6 * Author: Tomi Valkeinen <tomi.valkeinen@nokia.com>
8 * Some code and ideas taken from drivers/video/omap/ driver
13 #include <linux/sysfs.h>
14 #include <linux/device.h>
15 #include <linux/uaccess.h>
16 #include <linux/platform_device.h>
17 #include <linux/kernel.h>
18 #include <linux/kstrtox.h>
20 #include <linux/omapfb.h>
22 #include <video/omapfb_dss.h>
23 #include <video/omapvrfb.h>
27 static ssize_t
show_rotate_type(struct device
*dev
,
28 struct device_attribute
*attr
, char *buf
)
30 struct fb_info
*fbi
= dev_get_drvdata(dev
);
31 struct omapfb_info
*ofbi
= FB2OFB(fbi
);
33 return sysfs_emit(buf
, "%d\n", ofbi
->rotation_type
);
36 static ssize_t
store_rotate_type(struct device
*dev
,
37 struct device_attribute
*attr
,
38 const char *buf
, size_t count
)
40 struct fb_info
*fbi
= dev_get_drvdata(dev
);
41 struct omapfb_info
*ofbi
= FB2OFB(fbi
);
42 struct omapfb2_mem_region
*rg
;
46 r
= kstrtoint(buf
, 0, &rot_type
);
50 if (rot_type
!= OMAP_DSS_ROT_DMA
&& rot_type
!= OMAP_DSS_ROT_VRFB
)
56 if (rot_type
== ofbi
->rotation_type
)
59 rg
= omapfb_get_mem_region(ofbi
->region
);
66 ofbi
->rotation_type
= rot_type
;
69 * Since the VRAM for this FB is not allocated at the moment we don't
70 * need to do any further parameter checking at this point.
73 omapfb_put_mem_region(rg
);
81 static ssize_t
show_mirror(struct device
*dev
,
82 struct device_attribute
*attr
, char *buf
)
84 struct fb_info
*fbi
= dev_get_drvdata(dev
);
85 struct omapfb_info
*ofbi
= FB2OFB(fbi
);
87 return sysfs_emit(buf
, "%d\n", ofbi
->mirror
);
90 static ssize_t
store_mirror(struct device
*dev
,
91 struct device_attribute
*attr
,
92 const char *buf
, size_t count
)
94 struct fb_info
*fbi
= dev_get_drvdata(dev
);
95 struct omapfb_info
*ofbi
= FB2OFB(fbi
);
98 struct fb_var_screeninfo new_var
;
100 r
= kstrtobool(buf
, &mirror
);
106 ofbi
->mirror
= mirror
;
108 omapfb_get_mem_region(ofbi
->region
);
110 memcpy(&new_var
, &fbi
->var
, sizeof(new_var
));
111 r
= check_fb_var(fbi
, &new_var
);
114 memcpy(&fbi
->var
, &new_var
, sizeof(fbi
->var
));
118 r
= omapfb_apply_changes(fbi
, 0);
124 omapfb_put_mem_region(ofbi
->region
);
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
+= scnprintf(buf
+ l
, PAGE_SIZE
- l
, "%s%d",
152 t
== 0 ? "" : ",", ovlnum
);
155 l
+= scnprintf(buf
+ l
, PAGE_SIZE
- l
, "\n");
157 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_get_mem_region(ofbi
->region
);
264 omapfb_overlay_enable(ovl
, 0);
267 ovl
->manager
->apply(ovl
->manager
);
269 omapfb_put_mem_region(ofbi
->region
);
271 for (t
= i
+ 1; t
< ofbi
->num_overlays
; t
++) {
272 ofbi
->rotation
[t
-1] = ofbi
->rotation
[t
];
273 ofbi
->overlays
[t
-1] = ofbi
->overlays
[t
];
276 ofbi
->num_overlays
--;
280 for (i
= 0; i
< num_ovls
; ++i
) {
287 for (t
= 0; t
< ofbi
->num_overlays
; ++t
) {
288 if (ovl
== ofbi
->overlays
[t
]) {
296 ofbi
->rotation
[ofbi
->num_overlays
] = 0;
297 ofbi
->overlays
[ofbi
->num_overlays
++] = ovl
;
303 omapfb_get_mem_region(ofbi
->region
);
305 r
= omapfb_apply_changes(fbi
, 0);
307 omapfb_put_mem_region(ofbi
->region
);
315 omapfb_unlock(fbdev
);
321 static ssize_t
show_overlays_rotate(struct device
*dev
,
322 struct device_attribute
*attr
, char *buf
)
324 struct fb_info
*fbi
= dev_get_drvdata(dev
);
325 struct omapfb_info
*ofbi
= FB2OFB(fbi
);
331 for (t
= 0; t
< ofbi
->num_overlays
; t
++) {
332 l
+= scnprintf(buf
+ l
, PAGE_SIZE
- l
, "%s%d",
333 t
== 0 ? "" : ",", ofbi
->rotation
[t
]);
336 l
+= scnprintf(buf
+ l
, PAGE_SIZE
- l
, "\n");
343 static ssize_t
store_overlays_rotate(struct device
*dev
,
344 struct device_attribute
*attr
, const char *buf
, size_t count
)
346 struct fb_info
*fbi
= dev_get_drvdata(dev
);
347 struct omapfb_info
*ofbi
= FB2OFB(fbi
);
348 int num_ovls
= 0, r
, i
;
350 bool changed
= false;
351 u8 rotation
[OMAPFB_MAX_OVL_PER_FB
];
354 if (buf
[len
- 1] == '\n')
360 char *p
= (char *)buf
;
362 while (p
< buf
+ len
) {
365 if (num_ovls
== ofbi
->num_overlays
) {
370 rot
= simple_strtoul(p
, &p
, 0);
371 if (rot
< 0 || rot
> 3) {
376 if (ofbi
->rotation
[num_ovls
] != rot
)
379 rotation
[num_ovls
++] = rot
;
385 if (num_ovls
!= ofbi
->num_overlays
) {
391 for (i
= 0; i
< num_ovls
; ++i
)
392 ofbi
->rotation
[i
] = rotation
[i
];
394 omapfb_get_mem_region(ofbi
->region
);
396 r
= omapfb_apply_changes(fbi
, 0);
398 omapfb_put_mem_region(ofbi
->region
);
403 /* FIXME error handling? */
413 static ssize_t
show_size(struct device
*dev
,
414 struct device_attribute
*attr
, char *buf
)
416 struct fb_info
*fbi
= dev_get_drvdata(dev
);
417 struct omapfb_info
*ofbi
= FB2OFB(fbi
);
419 return sysfs_emit(buf
, "%lu\n", ofbi
->region
->size
);
422 static ssize_t
store_size(struct device
*dev
, struct device_attribute
*attr
,
423 const char *buf
, size_t count
)
425 struct fb_info
*fbi
= dev_get_drvdata(dev
);
426 struct omapfb_info
*ofbi
= FB2OFB(fbi
);
427 struct omapfb2_device
*fbdev
= ofbi
->fbdev
;
428 struct omap_dss_device
*display
= fb2display(fbi
);
429 struct omapfb2_mem_region
*rg
;
434 r
= kstrtoul(buf
, 0, &size
);
438 size
= PAGE_ALIGN(size
);
442 if (display
&& display
->driver
->sync
)
443 display
->driver
->sync(display
);
447 down_write_nested(&rg
->lock
, rg
->id
);
448 atomic_inc(&rg
->lock_count
);
450 if (atomic_read(&rg
->map_count
)) {
455 for (i
= 0; i
< fbdev
->num_fbs
; i
++) {
456 struct omapfb_info
*ofbi2
= FB2OFB(fbdev
->fbs
[i
]);
459 if (ofbi2
->region
!= rg
)
462 for (j
= 0; j
< ofbi2
->num_overlays
; j
++) {
463 struct omap_overlay
*ovl
;
464 ovl
= ofbi2
->overlays
[j
];
465 if (ovl
->is_enabled(ovl
)) {
472 if (size
!= ofbi
->region
->size
) {
473 r
= omapfb_realloc_fbmem(fbi
, size
, ofbi
->region
->type
);
475 dev_err(dev
, "realloc fbmem failed\n");
482 atomic_dec(&rg
->lock_count
);
490 static ssize_t
show_phys(struct device
*dev
,
491 struct device_attribute
*attr
, char *buf
)
493 struct fb_info
*fbi
= dev_get_drvdata(dev
);
494 struct omapfb_info
*ofbi
= FB2OFB(fbi
);
496 return sysfs_emit(buf
, "%0x\n", ofbi
->region
->paddr
);
499 static ssize_t
show_virt(struct device
*dev
,
500 struct device_attribute
*attr
, char *buf
)
502 struct fb_info
*fbi
= dev_get_drvdata(dev
);
503 struct omapfb_info
*ofbi
= FB2OFB(fbi
);
505 return sysfs_emit(buf
, "%p\n", ofbi
->region
->vaddr
);
508 static ssize_t
show_upd_mode(struct device
*dev
,
509 struct device_attribute
*attr
, char *buf
)
511 struct fb_info
*fbi
= dev_get_drvdata(dev
);
512 enum omapfb_update_mode mode
;
515 r
= omapfb_get_update_mode(fbi
, &mode
);
520 return sysfs_emit(buf
, "%u\n", (unsigned int)mode
);
523 static ssize_t
store_upd_mode(struct device
*dev
, struct device_attribute
*attr
,
524 const char *buf
, size_t count
)
526 struct fb_info
*fbi
= dev_get_drvdata(dev
);
530 r
= kstrtouint(buf
, 0, &mode
);
534 r
= omapfb_set_update_mode(fbi
, mode
);
541 static struct device_attribute omapfb_attrs
[] = {
542 __ATTR(rotate_type
, S_IRUGO
| S_IWUSR
, show_rotate_type
,
544 __ATTR(mirror
, S_IRUGO
| S_IWUSR
, show_mirror
, store_mirror
),
545 __ATTR(size
, S_IRUGO
| S_IWUSR
, show_size
, store_size
),
546 __ATTR(overlays
, S_IRUGO
| S_IWUSR
, show_overlays
, store_overlays
),
547 __ATTR(overlays_rotate
, S_IRUGO
| S_IWUSR
, show_overlays_rotate
,
548 store_overlays_rotate
),
549 __ATTR(phys_addr
, S_IRUGO
, show_phys
, NULL
),
550 __ATTR(virt_addr
, S_IRUGO
, show_virt
, NULL
),
551 __ATTR(update_mode
, S_IRUGO
| S_IWUSR
, show_upd_mode
, store_upd_mode
),
554 int omapfb_create_sysfs(struct omapfb2_device
*fbdev
)
559 DBG("create sysfs for fbs\n");
560 for (i
= 0; i
< fbdev
->num_fbs
; i
++) {
562 for (t
= 0; t
< ARRAY_SIZE(omapfb_attrs
); t
++) {
563 r
= device_create_file(fbdev
->fbs
[i
]->dev
,
567 dev_err(fbdev
->dev
, "failed to create sysfs "
577 void omapfb_remove_sysfs(struct omapfb2_device
*fbdev
)
581 DBG("remove sysfs for fbs\n");
582 for (i
= 0; i
< fbdev
->num_fbs
; i
++) {
583 for (t
= 0; t
< ARRAY_SIZE(omapfb_attrs
); t
++)
584 device_remove_file(fbdev
->fbs
[i
]->dev
,