Merge branches 'pm-cpuidle', 'pm-core' and 'pm-sleep'
[linux-block.git] / drivers / video / fbdev / omap2 / omapfb / omapfb-sysfs.c
1 // SPDX-License-Identifier: GPL-2.0-only
2 /*
3  * linux/drivers/video/omap2/omapfb-sysfs.c
4  *
5  * Copyright (C) 2008 Nokia Corporation
6  * Author: Tomi Valkeinen <tomi.valkeinen@nokia.com>
7  *
8  * Some code and ideas taken from drivers/video/omap/ driver
9  * by Imre Deak.
10  */
11
12 #include <linux/fb.h>
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>
19 #include <linux/mm.h>
20 #include <linux/omapfb.h>
21
22 #include <video/omapfb_dss.h>
23 #include <video/omapvrfb.h>
24
25 #include "omapfb.h"
26
27 static ssize_t show_rotate_type(struct device *dev,
28                 struct device_attribute *attr, char *buf)
29 {
30         struct fb_info *fbi = dev_get_drvdata(dev);
31         struct omapfb_info *ofbi = FB2OFB(fbi);
32
33         return sysfs_emit(buf, "%d\n", ofbi->rotation_type);
34 }
35
36 static ssize_t store_rotate_type(struct device *dev,
37                 struct device_attribute *attr,
38                 const char *buf, size_t count)
39 {
40         struct fb_info *fbi = dev_get_drvdata(dev);
41         struct omapfb_info *ofbi = FB2OFB(fbi);
42         struct omapfb2_mem_region *rg;
43         int rot_type;
44         int r;
45
46         r = kstrtoint(buf, 0, &rot_type);
47         if (r)
48                 return r;
49
50         if (rot_type != OMAP_DSS_ROT_DMA && rot_type != OMAP_DSS_ROT_VRFB)
51                 return -EINVAL;
52
53         lock_fb_info(fbi);
54
55         r = 0;
56         if (rot_type == ofbi->rotation_type)
57                 goto out;
58
59         rg = omapfb_get_mem_region(ofbi->region);
60
61         if (rg->size) {
62                 r = -EBUSY;
63                 goto put_region;
64         }
65
66         ofbi->rotation_type = rot_type;
67
68         /*
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.
71          */
72 put_region:
73         omapfb_put_mem_region(rg);
74 out:
75         unlock_fb_info(fbi);
76
77         return r ? r : count;
78 }
79
80
81 static ssize_t show_mirror(struct device *dev,
82                 struct device_attribute *attr, char *buf)
83 {
84         struct fb_info *fbi = dev_get_drvdata(dev);
85         struct omapfb_info *ofbi = FB2OFB(fbi);
86
87         return sysfs_emit(buf, "%d\n", ofbi->mirror);
88 }
89
90 static ssize_t store_mirror(struct device *dev,
91                 struct device_attribute *attr,
92                 const char *buf, size_t count)
93 {
94         struct fb_info *fbi = dev_get_drvdata(dev);
95         struct omapfb_info *ofbi = FB2OFB(fbi);
96         bool mirror;
97         int r;
98         struct fb_var_screeninfo new_var;
99
100         r = kstrtobool(buf, &mirror);
101         if (r)
102                 return r;
103
104         lock_fb_info(fbi);
105
106         ofbi->mirror = mirror;
107
108         omapfb_get_mem_region(ofbi->region);
109
110         memcpy(&new_var, &fbi->var, sizeof(new_var));
111         r = check_fb_var(fbi, &new_var);
112         if (r)
113                 goto out;
114         memcpy(&fbi->var, &new_var, sizeof(fbi->var));
115
116         set_fb_fix(fbi);
117
118         r = omapfb_apply_changes(fbi, 0);
119         if (r)
120                 goto out;
121
122         r = count;
123 out:
124         omapfb_put_mem_region(ofbi->region);
125
126         unlock_fb_info(fbi);
127
128         return r;
129 }
130
131 static ssize_t show_overlays(struct device *dev,
132                 struct device_attribute *attr, char *buf)
133 {
134         struct fb_info *fbi = dev_get_drvdata(dev);
135         struct omapfb_info *ofbi = FB2OFB(fbi);
136         struct omapfb2_device *fbdev = ofbi->fbdev;
137         ssize_t l = 0;
138         int t;
139
140         lock_fb_info(fbi);
141         omapfb_lock(fbdev);
142
143         for (t = 0; t < ofbi->num_overlays; t++) {
144                 struct omap_overlay *ovl = ofbi->overlays[t];
145                 int ovlnum;
146
147                 for (ovlnum = 0; ovlnum < fbdev->num_overlays; ++ovlnum)
148                         if (ovl == fbdev->overlays[ovlnum])
149                                 break;
150
151                 l += scnprintf(buf + l, PAGE_SIZE - l, "%s%d",
152                                 t == 0 ? "" : ",", ovlnum);
153         }
154
155         l += scnprintf(buf + l, PAGE_SIZE - l, "\n");
156
157         omapfb_unlock(fbdev);
158         unlock_fb_info(fbi);
159
160         return l;
161 }
162
163 static struct omapfb_info *get_overlay_fb(struct omapfb2_device *fbdev,
164                 struct omap_overlay *ovl)
165 {
166         int i, t;
167
168         for (i = 0; i < fbdev->num_fbs; i++) {
169                 struct omapfb_info *ofbi = FB2OFB(fbdev->fbs[i]);
170
171                 for (t = 0; t < ofbi->num_overlays; t++) {
172                         if (ofbi->overlays[t] == ovl)
173                                 return ofbi;
174                 }
175         }
176
177         return NULL;
178 }
179
180 static ssize_t store_overlays(struct device *dev, struct device_attribute *attr,
181                 const char *buf, size_t count)
182 {
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;
188         int num_ovls, r, i;
189         int len;
190         bool added = false;
191
192         num_ovls = 0;
193
194         len = strlen(buf);
195         if (buf[len - 1] == '\n')
196                 len = len - 1;
197
198         lock_fb_info(fbi);
199         omapfb_lock(fbdev);
200
201         if (len > 0) {
202                 char *p = (char *)buf;
203                 int ovlnum;
204
205                 while (p < buf + len) {
206                         int found;
207                         if (num_ovls == OMAPFB_MAX_OVL_PER_FB) {
208                                 r = -EINVAL;
209                                 goto out;
210                         }
211
212                         ovlnum = simple_strtoul(p, &p, 0);
213                         if (ovlnum > fbdev->num_overlays) {
214                                 r = -EINVAL;
215                                 goto out;
216                         }
217
218                         found = 0;
219                         for (i = 0; i < num_ovls; ++i) {
220                                 if (ovls[i] == fbdev->overlays[ovlnum]) {
221                                         found = 1;
222                                         break;
223                                 }
224                         }
225
226                         if (!found)
227                                 ovls[num_ovls++] = fbdev->overlays[ovlnum];
228
229                         p++;
230                 }
231         }
232
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");
237                         r = -EINVAL;
238                         goto out;
239                 }
240         }
241
242         /* detach unused overlays */
243         for (i = 0; i < ofbi->num_overlays; ++i) {
244                 int t, found;
245
246                 ovl = ofbi->overlays[i];
247
248                 found = 0;
249
250                 for (t = 0; t < num_ovls; ++t) {
251                         if (ovl == ovls[t]) {
252                                 found = 1;
253                                 break;
254                         }
255                 }
256
257                 if (found)
258                         continue;
259
260                 DBG("detaching %d\n", ofbi->overlays[i]->id);
261
262                 omapfb_get_mem_region(ofbi->region);
263
264                 omapfb_overlay_enable(ovl, 0);
265
266                 if (ovl->manager)
267                         ovl->manager->apply(ovl->manager);
268
269                 omapfb_put_mem_region(ofbi->region);
270
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];
274                 }
275
276                 ofbi->num_overlays--;
277                 i--;
278         }
279
280         for (i = 0; i < num_ovls; ++i) {
281                 int t, found;
282
283                 ovl = ovls[i];
284
285                 found = 0;
286
287                 for (t = 0; t < ofbi->num_overlays; ++t) {
288                         if (ovl == ofbi->overlays[t]) {
289                                 found = 1;
290                                 break;
291                         }
292                 }
293
294                 if (found)
295                         continue;
296                 ofbi->rotation[ofbi->num_overlays] = 0;
297                 ofbi->overlays[ofbi->num_overlays++] = ovl;
298
299                 added = true;
300         }
301
302         if (added) {
303                 omapfb_get_mem_region(ofbi->region);
304
305                 r = omapfb_apply_changes(fbi, 0);
306
307                 omapfb_put_mem_region(ofbi->region);
308
309                 if (r)
310                         goto out;
311         }
312
313         r = count;
314 out:
315         omapfb_unlock(fbdev);
316         unlock_fb_info(fbi);
317
318         return r;
319 }
320
321 static ssize_t show_overlays_rotate(struct device *dev,
322                 struct device_attribute *attr, char *buf)
323 {
324         struct fb_info *fbi = dev_get_drvdata(dev);
325         struct omapfb_info *ofbi = FB2OFB(fbi);
326         ssize_t l = 0;
327         int t;
328
329         lock_fb_info(fbi);
330
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]);
334         }
335
336         l += scnprintf(buf + l, PAGE_SIZE - l, "\n");
337
338         unlock_fb_info(fbi);
339
340         return l;
341 }
342
343 static ssize_t store_overlays_rotate(struct device *dev,
344                 struct device_attribute *attr, const char *buf, size_t count)
345 {
346         struct fb_info *fbi = dev_get_drvdata(dev);
347         struct omapfb_info *ofbi = FB2OFB(fbi);
348         int num_ovls = 0, r, i;
349         int len;
350         bool changed = false;
351         u8 rotation[OMAPFB_MAX_OVL_PER_FB];
352
353         len = strlen(buf);
354         if (buf[len - 1] == '\n')
355                 len = len - 1;
356
357         lock_fb_info(fbi);
358
359         if (len > 0) {
360                 char *p = (char *)buf;
361
362                 while (p < buf + len) {
363                         int rot;
364
365                         if (num_ovls == ofbi->num_overlays) {
366                                 r = -EINVAL;
367                                 goto out;
368                         }
369
370                         rot = simple_strtoul(p, &p, 0);
371                         if (rot < 0 || rot > 3) {
372                                 r = -EINVAL;
373                                 goto out;
374                         }
375
376                         if (ofbi->rotation[num_ovls] != rot)
377                                 changed = true;
378
379                         rotation[num_ovls++] = rot;
380
381                         p++;
382                 }
383         }
384
385         if (num_ovls != ofbi->num_overlays) {
386                 r = -EINVAL;
387                 goto out;
388         }
389
390         if (changed) {
391                 for (i = 0; i < num_ovls; ++i)
392                         ofbi->rotation[i] = rotation[i];
393
394                 omapfb_get_mem_region(ofbi->region);
395
396                 r = omapfb_apply_changes(fbi, 0);
397
398                 omapfb_put_mem_region(ofbi->region);
399
400                 if (r)
401                         goto out;
402
403                 /* FIXME error handling? */
404         }
405
406         r = count;
407 out:
408         unlock_fb_info(fbi);
409
410         return r;
411 }
412
413 static ssize_t show_size(struct device *dev,
414                 struct device_attribute *attr, char *buf)
415 {
416         struct fb_info *fbi = dev_get_drvdata(dev);
417         struct omapfb_info *ofbi = FB2OFB(fbi);
418
419         return sysfs_emit(buf, "%lu\n", ofbi->region->size);
420 }
421
422 static ssize_t store_size(struct device *dev, struct device_attribute *attr,
423                 const char *buf, size_t count)
424 {
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;
430         unsigned long size;
431         int r;
432         int i;
433
434         r = kstrtoul(buf, 0, &size);
435         if (r)
436                 return r;
437
438         size = PAGE_ALIGN(size);
439
440         lock_fb_info(fbi);
441
442         if (display && display->driver->sync)
443                 display->driver->sync(display);
444
445         rg = ofbi->region;
446
447         down_write_nested(&rg->lock, rg->id);
448         atomic_inc(&rg->lock_count);
449
450         if (atomic_read(&rg->map_count)) {
451                 r = -EBUSY;
452                 goto out;
453         }
454
455         for (i = 0; i < fbdev->num_fbs; i++) {
456                 struct omapfb_info *ofbi2 = FB2OFB(fbdev->fbs[i]);
457                 int j;
458
459                 if (ofbi2->region != rg)
460                         continue;
461
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)) {
466                                 r = -EBUSY;
467                                 goto out;
468                         }
469                 }
470         }
471
472         if (size != ofbi->region->size) {
473                 r = omapfb_realloc_fbmem(fbi, size, ofbi->region->type);
474                 if (r) {
475                         dev_err(dev, "realloc fbmem failed\n");
476                         goto out;
477                 }
478         }
479
480         r = count;
481 out:
482         atomic_dec(&rg->lock_count);
483         up_write(&rg->lock);
484
485         unlock_fb_info(fbi);
486
487         return r;
488 }
489
490 static ssize_t show_phys(struct device *dev,
491                 struct device_attribute *attr, char *buf)
492 {
493         struct fb_info *fbi = dev_get_drvdata(dev);
494         struct omapfb_info *ofbi = FB2OFB(fbi);
495
496         return sysfs_emit(buf, "%0x\n", ofbi->region->paddr);
497 }
498
499 static ssize_t show_virt(struct device *dev,
500                 struct device_attribute *attr, char *buf)
501 {
502         struct fb_info *fbi = dev_get_drvdata(dev);
503         struct omapfb_info *ofbi = FB2OFB(fbi);
504
505         return sysfs_emit(buf, "%p\n", ofbi->region->vaddr);
506 }
507
508 static ssize_t show_upd_mode(struct device *dev,
509                 struct device_attribute *attr, char *buf)
510 {
511         struct fb_info *fbi = dev_get_drvdata(dev);
512         enum omapfb_update_mode mode;
513         int r;
514
515         r = omapfb_get_update_mode(fbi, &mode);
516
517         if (r)
518                 return r;
519
520         return sysfs_emit(buf, "%u\n", (unsigned int)mode);
521 }
522
523 static ssize_t store_upd_mode(struct device *dev, struct device_attribute *attr,
524                 const char *buf, size_t count)
525 {
526         struct fb_info *fbi = dev_get_drvdata(dev);
527         unsigned mode;
528         int r;
529
530         r = kstrtouint(buf, 0, &mode);
531         if (r)
532                 return r;
533
534         r = omapfb_set_update_mode(fbi, mode);
535         if (r)
536                 return r;
537
538         return count;
539 }
540
541 static struct device_attribute omapfb_attrs[] = {
542         __ATTR(rotate_type, S_IRUGO | S_IWUSR, show_rotate_type,
543                         store_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),
552 };
553
554 int omapfb_create_sysfs(struct omapfb2_device *fbdev)
555 {
556         int i;
557         int r;
558
559         DBG("create sysfs for fbs\n");
560         for (i = 0; i < fbdev->num_fbs; i++) {
561                 int t;
562                 for (t = 0; t < ARRAY_SIZE(omapfb_attrs); t++) {
563                         r = device_create_file(fbdev->fbs[i]->dev,
564                                         &omapfb_attrs[t]);
565
566                         if (r) {
567                                 dev_err(fbdev->dev, "failed to create sysfs "
568                                                 "file\n");
569                                 return r;
570                         }
571                 }
572         }
573
574         return 0;
575 }
576
577 void omapfb_remove_sysfs(struct omapfb2_device *fbdev)
578 {
579         int i, t;
580
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,
585                                         &omapfb_attrs[t]);
586         }
587 }
588