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>
19 #include <linux/omapfb.h>
21 #include <video/omapfb_dss.h>
22 #include <video/omapvrfb.h>
26 static ssize_t
show_rotate_type(struct device
*dev
,
27 struct device_attribute
*attr
, char *buf
)
29 struct fb_info
*fbi
= dev_get_drvdata(dev
);
30 struct omapfb_info
*ofbi
= FB2OFB(fbi
);
32 return snprintf(buf
, PAGE_SIZE
, "%d\n", ofbi
->rotation_type
);
35 static ssize_t
store_rotate_type(struct device
*dev
,
36 struct device_attribute
*attr
,
37 const char *buf
, size_t count
)
39 struct fb_info
*fbi
= dev_get_drvdata(dev
);
40 struct omapfb_info
*ofbi
= FB2OFB(fbi
);
41 struct omapfb2_mem_region
*rg
;
45 r
= kstrtoint(buf
, 0, &rot_type
);
49 if (rot_type
!= OMAP_DSS_ROT_DMA
&& rot_type
!= OMAP_DSS_ROT_VRFB
)
55 if (rot_type
== ofbi
->rotation_type
)
58 rg
= omapfb_get_mem_region(ofbi
->region
);
65 ofbi
->rotation_type
= rot_type
;
68 * Since the VRAM for this FB is not allocated at the moment we don't
69 * need to do any further parameter checking at this point.
72 omapfb_put_mem_region(rg
);
80 static ssize_t
show_mirror(struct device
*dev
,
81 struct device_attribute
*attr
, char *buf
)
83 struct fb_info
*fbi
= dev_get_drvdata(dev
);
84 struct omapfb_info
*ofbi
= FB2OFB(fbi
);
86 return snprintf(buf
, PAGE_SIZE
, "%d\n", ofbi
->mirror
);
89 static ssize_t
store_mirror(struct device
*dev
,
90 struct device_attribute
*attr
,
91 const char *buf
, size_t count
)
93 struct fb_info
*fbi
= dev_get_drvdata(dev
);
94 struct omapfb_info
*ofbi
= FB2OFB(fbi
);
97 struct fb_var_screeninfo new_var
;
99 r
= strtobool(buf
, &mirror
);
105 ofbi
->mirror
= mirror
;
107 omapfb_get_mem_region(ofbi
->region
);
109 memcpy(&new_var
, &fbi
->var
, sizeof(new_var
));
110 r
= check_fb_var(fbi
, &new_var
);
113 memcpy(&fbi
->var
, &new_var
, sizeof(fbi
->var
));
117 r
= omapfb_apply_changes(fbi
, 0);
123 omapfb_put_mem_region(ofbi
->region
);
130 static ssize_t
show_overlays(struct device
*dev
,
131 struct device_attribute
*attr
, char *buf
)
133 struct fb_info
*fbi
= dev_get_drvdata(dev
);
134 struct omapfb_info
*ofbi
= FB2OFB(fbi
);
135 struct omapfb2_device
*fbdev
= ofbi
->fbdev
;
142 for (t
= 0; t
< ofbi
->num_overlays
; t
++) {
143 struct omap_overlay
*ovl
= ofbi
->overlays
[t
];
146 for (ovlnum
= 0; ovlnum
< fbdev
->num_overlays
; ++ovlnum
)
147 if (ovl
== fbdev
->overlays
[ovlnum
])
150 l
+= scnprintf(buf
+ l
, PAGE_SIZE
- l
, "%s%d",
151 t
== 0 ? "" : ",", ovlnum
);
154 l
+= scnprintf(buf
+ l
, PAGE_SIZE
- l
, "\n");
156 omapfb_unlock(fbdev
);
162 static struct omapfb_info
*get_overlay_fb(struct omapfb2_device
*fbdev
,
163 struct omap_overlay
*ovl
)
167 for (i
= 0; i
< fbdev
->num_fbs
; i
++) {
168 struct omapfb_info
*ofbi
= FB2OFB(fbdev
->fbs
[i
]);
170 for (t
= 0; t
< ofbi
->num_overlays
; t
++) {
171 if (ofbi
->overlays
[t
] == ovl
)
179 static ssize_t
store_overlays(struct device
*dev
, struct device_attribute
*attr
,
180 const char *buf
, size_t count
)
182 struct fb_info
*fbi
= dev_get_drvdata(dev
);
183 struct omapfb_info
*ofbi
= FB2OFB(fbi
);
184 struct omapfb2_device
*fbdev
= ofbi
->fbdev
;
185 struct omap_overlay
*ovls
[OMAPFB_MAX_OVL_PER_FB
];
186 struct omap_overlay
*ovl
;
194 if (buf
[len
- 1] == '\n')
201 char *p
= (char *)buf
;
204 while (p
< buf
+ len
) {
206 if (num_ovls
== OMAPFB_MAX_OVL_PER_FB
) {
211 ovlnum
= simple_strtoul(p
, &p
, 0);
212 if (ovlnum
> fbdev
->num_overlays
) {
218 for (i
= 0; i
< num_ovls
; ++i
) {
219 if (ovls
[i
] == fbdev
->overlays
[ovlnum
]) {
226 ovls
[num_ovls
++] = fbdev
->overlays
[ovlnum
];
232 for (i
= 0; i
< num_ovls
; ++i
) {
233 struct omapfb_info
*ofbi2
= get_overlay_fb(fbdev
, ovls
[i
]);
234 if (ofbi2
&& ofbi2
!= ofbi
) {
235 dev_err(fbdev
->dev
, "overlay already in use\n");
241 /* detach unused overlays */
242 for (i
= 0; i
< ofbi
->num_overlays
; ++i
) {
245 ovl
= ofbi
->overlays
[i
];
249 for (t
= 0; t
< num_ovls
; ++t
) {
250 if (ovl
== ovls
[t
]) {
259 DBG("detaching %d\n", ofbi
->overlays
[i
]->id
);
261 omapfb_get_mem_region(ofbi
->region
);
263 omapfb_overlay_enable(ovl
, 0);
266 ovl
->manager
->apply(ovl
->manager
);
268 omapfb_put_mem_region(ofbi
->region
);
270 for (t
= i
+ 1; t
< ofbi
->num_overlays
; t
++) {
271 ofbi
->rotation
[t
-1] = ofbi
->rotation
[t
];
272 ofbi
->overlays
[t
-1] = ofbi
->overlays
[t
];
275 ofbi
->num_overlays
--;
279 for (i
= 0; i
< num_ovls
; ++i
) {
286 for (t
= 0; t
< ofbi
->num_overlays
; ++t
) {
287 if (ovl
== ofbi
->overlays
[t
]) {
295 ofbi
->rotation
[ofbi
->num_overlays
] = 0;
296 ofbi
->overlays
[ofbi
->num_overlays
++] = ovl
;
302 omapfb_get_mem_region(ofbi
->region
);
304 r
= omapfb_apply_changes(fbi
, 0);
306 omapfb_put_mem_region(ofbi
->region
);
314 omapfb_unlock(fbdev
);
320 static ssize_t
show_overlays_rotate(struct device
*dev
,
321 struct device_attribute
*attr
, char *buf
)
323 struct fb_info
*fbi
= dev_get_drvdata(dev
);
324 struct omapfb_info
*ofbi
= FB2OFB(fbi
);
330 for (t
= 0; t
< ofbi
->num_overlays
; t
++) {
331 l
+= scnprintf(buf
+ l
, PAGE_SIZE
- l
, "%s%d",
332 t
== 0 ? "" : ",", ofbi
->rotation
[t
]);
335 l
+= scnprintf(buf
+ l
, PAGE_SIZE
- l
, "\n");
342 static ssize_t
store_overlays_rotate(struct device
*dev
,
343 struct device_attribute
*attr
, const char *buf
, size_t count
)
345 struct fb_info
*fbi
= dev_get_drvdata(dev
);
346 struct omapfb_info
*ofbi
= FB2OFB(fbi
);
347 int num_ovls
= 0, r
, i
;
349 bool changed
= false;
350 u8 rotation
[OMAPFB_MAX_OVL_PER_FB
];
353 if (buf
[len
- 1] == '\n')
359 char *p
= (char *)buf
;
361 while (p
< buf
+ len
) {
364 if (num_ovls
== ofbi
->num_overlays
) {
369 rot
= simple_strtoul(p
, &p
, 0);
370 if (rot
< 0 || rot
> 3) {
375 if (ofbi
->rotation
[num_ovls
] != rot
)
378 rotation
[num_ovls
++] = rot
;
384 if (num_ovls
!= ofbi
->num_overlays
) {
390 for (i
= 0; i
< num_ovls
; ++i
)
391 ofbi
->rotation
[i
] = rotation
[i
];
393 omapfb_get_mem_region(ofbi
->region
);
395 r
= omapfb_apply_changes(fbi
, 0);
397 omapfb_put_mem_region(ofbi
->region
);
402 /* FIXME error handling? */
412 static ssize_t
show_size(struct device
*dev
,
413 struct device_attribute
*attr
, char *buf
)
415 struct fb_info
*fbi
= dev_get_drvdata(dev
);
416 struct omapfb_info
*ofbi
= FB2OFB(fbi
);
418 return snprintf(buf
, PAGE_SIZE
, "%lu\n", ofbi
->region
->size
);
421 static ssize_t
store_size(struct device
*dev
, struct device_attribute
*attr
,
422 const char *buf
, size_t count
)
424 struct fb_info
*fbi
= dev_get_drvdata(dev
);
425 struct omapfb_info
*ofbi
= FB2OFB(fbi
);
426 struct omapfb2_device
*fbdev
= ofbi
->fbdev
;
427 struct omap_dss_device
*display
= fb2display(fbi
);
428 struct omapfb2_mem_region
*rg
;
433 r
= kstrtoul(buf
, 0, &size
);
437 size
= PAGE_ALIGN(size
);
441 if (display
&& display
->driver
->sync
)
442 display
->driver
->sync(display
);
446 down_write_nested(&rg
->lock
, rg
->id
);
447 atomic_inc(&rg
->lock_count
);
449 if (atomic_read(&rg
->map_count
)) {
454 for (i
= 0; i
< fbdev
->num_fbs
; i
++) {
455 struct omapfb_info
*ofbi2
= FB2OFB(fbdev
->fbs
[i
]);
458 if (ofbi2
->region
!= rg
)
461 for (j
= 0; j
< ofbi2
->num_overlays
; j
++) {
462 struct omap_overlay
*ovl
;
463 ovl
= ofbi2
->overlays
[j
];
464 if (ovl
->is_enabled(ovl
)) {
471 if (size
!= ofbi
->region
->size
) {
472 r
= omapfb_realloc_fbmem(fbi
, size
, ofbi
->region
->type
);
474 dev_err(dev
, "realloc fbmem failed\n");
481 atomic_dec(&rg
->lock_count
);
489 static ssize_t
show_phys(struct device
*dev
,
490 struct device_attribute
*attr
, char *buf
)
492 struct fb_info
*fbi
= dev_get_drvdata(dev
);
493 struct omapfb_info
*ofbi
= FB2OFB(fbi
);
495 return snprintf(buf
, PAGE_SIZE
, "%0x\n", ofbi
->region
->paddr
);
498 static ssize_t
show_virt(struct device
*dev
,
499 struct device_attribute
*attr
, char *buf
)
501 struct fb_info
*fbi
= dev_get_drvdata(dev
);
502 struct omapfb_info
*ofbi
= FB2OFB(fbi
);
504 return snprintf(buf
, PAGE_SIZE
, "%p\n", ofbi
->region
->vaddr
);
507 static ssize_t
show_upd_mode(struct device
*dev
,
508 struct device_attribute
*attr
, char *buf
)
510 struct fb_info
*fbi
= dev_get_drvdata(dev
);
511 enum omapfb_update_mode mode
;
514 r
= omapfb_get_update_mode(fbi
, &mode
);
519 return snprintf(buf
, PAGE_SIZE
, "%u\n", (unsigned)mode
);
522 static ssize_t
store_upd_mode(struct device
*dev
, struct device_attribute
*attr
,
523 const char *buf
, size_t count
)
525 struct fb_info
*fbi
= dev_get_drvdata(dev
);
529 r
= kstrtouint(buf
, 0, &mode
);
533 r
= omapfb_set_update_mode(fbi
, mode
);
540 static struct device_attribute omapfb_attrs
[] = {
541 __ATTR(rotate_type
, S_IRUGO
| S_IWUSR
, show_rotate_type
,
543 __ATTR(mirror
, S_IRUGO
| S_IWUSR
, show_mirror
, store_mirror
),
544 __ATTR(size
, S_IRUGO
| S_IWUSR
, show_size
, store_size
),
545 __ATTR(overlays
, S_IRUGO
| S_IWUSR
, show_overlays
, store_overlays
),
546 __ATTR(overlays_rotate
, S_IRUGO
| S_IWUSR
, show_overlays_rotate
,
547 store_overlays_rotate
),
548 __ATTR(phys_addr
, S_IRUGO
, show_phys
, NULL
),
549 __ATTR(virt_addr
, S_IRUGO
, show_virt
, NULL
),
550 __ATTR(update_mode
, S_IRUGO
| S_IWUSR
, show_upd_mode
, store_upd_mode
),
553 int omapfb_create_sysfs(struct omapfb2_device
*fbdev
)
558 DBG("create sysfs for fbs\n");
559 for (i
= 0; i
< fbdev
->num_fbs
; i
++) {
561 for (t
= 0; t
< ARRAY_SIZE(omapfb_attrs
); t
++) {
562 r
= device_create_file(fbdev
->fbs
[i
]->dev
,
566 dev_err(fbdev
->dev
, "failed to create sysfs "
576 void omapfb_remove_sysfs(struct omapfb2_device
*fbdev
)
580 DBG("remove sysfs for fbs\n");
581 for (i
= 0; i
< fbdev
->num_fbs
; i
++) {
582 for (t
= 0; t
< ARRAY_SIZE(omapfb_attrs
); t
++)
583 device_remove_file(fbdev
->fbs
[i
]->dev
,