Linux-libre 5.4.48-gnu
[librecmc/linux-libre.git] / drivers / video / fbdev / omap2 / omapfb / dss / overlay-sysfs.c
1 // SPDX-License-Identifier: GPL-2.0-only
2 /*
3  * Copyright (C) 2009 Nokia Corporation
4  * Author: Tomi Valkeinen <tomi.valkeinen@nokia.com>
5  *
6  * Some code and ideas taken from drivers/video/omap/ driver
7  * by Imre Deak.
8  */
9
10 #define DSS_SUBSYS_NAME "OVERLAY"
11
12 #include <linux/module.h>
13 #include <linux/err.h>
14 #include <linux/sysfs.h>
15 #include <linux/kobject.h>
16 #include <linux/platform_device.h>
17
18 #include <video/omapfb_dss.h>
19
20 #include "dss.h"
21 #include "dss_features.h"
22
23 static ssize_t overlay_name_show(struct omap_overlay *ovl, char *buf)
24 {
25         return snprintf(buf, PAGE_SIZE, "%s\n", ovl->name);
26 }
27
28 static ssize_t overlay_manager_show(struct omap_overlay *ovl, char *buf)
29 {
30         return snprintf(buf, PAGE_SIZE, "%s\n",
31                         ovl->manager ? ovl->manager->name : "<none>");
32 }
33
34 static ssize_t overlay_manager_store(struct omap_overlay *ovl, const char *buf,
35                 size_t size)
36 {
37         int i, r;
38         struct omap_overlay_manager *mgr = NULL;
39         struct omap_overlay_manager *old_mgr;
40         int len = size;
41
42         if (buf[size-1] == '\n')
43                 --len;
44
45         if (len > 0) {
46                 for (i = 0; i < omap_dss_get_num_overlay_managers(); ++i) {
47                         mgr = omap_dss_get_overlay_manager(i);
48
49                         if (sysfs_streq(buf, mgr->name))
50                                 break;
51
52                         mgr = NULL;
53                 }
54         }
55
56         if (len > 0 && mgr == NULL)
57                 return -EINVAL;
58
59         if (mgr)
60                 DSSDBG("manager %s found\n", mgr->name);
61
62         if (mgr == ovl->manager)
63                 return size;
64
65         old_mgr = ovl->manager;
66
67         r = dispc_runtime_get();
68         if (r)
69                 return r;
70
71         /* detach old manager */
72         if (old_mgr) {
73                 r = ovl->unset_manager(ovl);
74                 if (r) {
75                         DSSERR("detach failed\n");
76                         goto err;
77                 }
78
79                 r = old_mgr->apply(old_mgr);
80                 if (r)
81                         goto err;
82         }
83
84         if (mgr) {
85                 r = ovl->set_manager(ovl, mgr);
86                 if (r) {
87                         DSSERR("Failed to attach overlay\n");
88                         goto err;
89                 }
90
91                 r = mgr->apply(mgr);
92                 if (r)
93                         goto err;
94         }
95
96         dispc_runtime_put();
97
98         return size;
99
100 err:
101         dispc_runtime_put();
102         return r;
103 }
104
105 static ssize_t overlay_input_size_show(struct omap_overlay *ovl, char *buf)
106 {
107         struct omap_overlay_info info;
108
109         ovl->get_overlay_info(ovl, &info);
110
111         return snprintf(buf, PAGE_SIZE, "%d,%d\n",
112                         info.width, info.height);
113 }
114
115 static ssize_t overlay_screen_width_show(struct omap_overlay *ovl, char *buf)
116 {
117         struct omap_overlay_info info;
118
119         ovl->get_overlay_info(ovl, &info);
120
121         return snprintf(buf, PAGE_SIZE, "%d\n", info.screen_width);
122 }
123
124 static ssize_t overlay_position_show(struct omap_overlay *ovl, char *buf)
125 {
126         struct omap_overlay_info info;
127
128         ovl->get_overlay_info(ovl, &info);
129
130         return snprintf(buf, PAGE_SIZE, "%d,%d\n",
131                         info.pos_x, info.pos_y);
132 }
133
134 static ssize_t overlay_position_store(struct omap_overlay *ovl,
135                 const char *buf, size_t size)
136 {
137         int r;
138         char *last;
139         struct omap_overlay_info info;
140
141         ovl->get_overlay_info(ovl, &info);
142
143         info.pos_x = simple_strtoul(buf, &last, 10);
144         ++last;
145         if (last - buf >= size)
146                 return -EINVAL;
147
148         info.pos_y = simple_strtoul(last, &last, 10);
149
150         r = ovl->set_overlay_info(ovl, &info);
151         if (r)
152                 return r;
153
154         if (ovl->manager) {
155                 r = ovl->manager->apply(ovl->manager);
156                 if (r)
157                         return r;
158         }
159
160         return size;
161 }
162
163 static ssize_t overlay_output_size_show(struct omap_overlay *ovl, char *buf)
164 {
165         struct omap_overlay_info info;
166
167         ovl->get_overlay_info(ovl, &info);
168
169         return snprintf(buf, PAGE_SIZE, "%d,%d\n",
170                         info.out_width, info.out_height);
171 }
172
173 static ssize_t overlay_output_size_store(struct omap_overlay *ovl,
174                 const char *buf, size_t size)
175 {
176         int r;
177         char *last;
178         struct omap_overlay_info info;
179
180         ovl->get_overlay_info(ovl, &info);
181
182         info.out_width = simple_strtoul(buf, &last, 10);
183         ++last;
184         if (last - buf >= size)
185                 return -EINVAL;
186
187         info.out_height = simple_strtoul(last, &last, 10);
188
189         r = ovl->set_overlay_info(ovl, &info);
190         if (r)
191                 return r;
192
193         if (ovl->manager) {
194                 r = ovl->manager->apply(ovl->manager);
195                 if (r)
196                         return r;
197         }
198
199         return size;
200 }
201
202 static ssize_t overlay_enabled_show(struct omap_overlay *ovl, char *buf)
203 {
204         return snprintf(buf, PAGE_SIZE, "%d\n", ovl->is_enabled(ovl));
205 }
206
207 static ssize_t overlay_enabled_store(struct omap_overlay *ovl, const char *buf,
208                 size_t size)
209 {
210         int r;
211         bool enable;
212
213         r = strtobool(buf, &enable);
214         if (r)
215                 return r;
216
217         if (enable)
218                 r = ovl->enable(ovl);
219         else
220                 r = ovl->disable(ovl);
221
222         if (r)
223                 return r;
224
225         return size;
226 }
227
228 static ssize_t overlay_global_alpha_show(struct omap_overlay *ovl, char *buf)
229 {
230         struct omap_overlay_info info;
231
232         ovl->get_overlay_info(ovl, &info);
233
234         return snprintf(buf, PAGE_SIZE, "%d\n",
235                         info.global_alpha);
236 }
237
238 static ssize_t overlay_global_alpha_store(struct omap_overlay *ovl,
239                 const char *buf, size_t size)
240 {
241         int r;
242         u8 alpha;
243         struct omap_overlay_info info;
244
245         if ((ovl->caps & OMAP_DSS_OVL_CAP_GLOBAL_ALPHA) == 0)
246                 return -ENODEV;
247
248         r = kstrtou8(buf, 0, &alpha);
249         if (r)
250                 return r;
251
252         ovl->get_overlay_info(ovl, &info);
253
254         info.global_alpha = alpha;
255
256         r = ovl->set_overlay_info(ovl, &info);
257         if (r)
258                 return r;
259
260         if (ovl->manager) {
261                 r = ovl->manager->apply(ovl->manager);
262                 if (r)
263                         return r;
264         }
265
266         return size;
267 }
268
269 static ssize_t overlay_pre_mult_alpha_show(struct omap_overlay *ovl,
270                 char *buf)
271 {
272         struct omap_overlay_info info;
273
274         ovl->get_overlay_info(ovl, &info);
275
276         return snprintf(buf, PAGE_SIZE, "%d\n",
277                         info.pre_mult_alpha);
278 }
279
280 static ssize_t overlay_pre_mult_alpha_store(struct omap_overlay *ovl,
281                 const char *buf, size_t size)
282 {
283         int r;
284         u8 alpha;
285         struct omap_overlay_info info;
286
287         if ((ovl->caps & OMAP_DSS_OVL_CAP_PRE_MULT_ALPHA) == 0)
288                 return -ENODEV;
289
290         r = kstrtou8(buf, 0, &alpha);
291         if (r)
292                 return r;
293
294         ovl->get_overlay_info(ovl, &info);
295
296         info.pre_mult_alpha = alpha;
297
298         r = ovl->set_overlay_info(ovl, &info);
299         if (r)
300                 return r;
301
302         if (ovl->manager) {
303                 r = ovl->manager->apply(ovl->manager);
304                 if (r)
305                         return r;
306         }
307
308         return size;
309 }
310
311 static ssize_t overlay_zorder_show(struct omap_overlay *ovl, char *buf)
312 {
313         struct omap_overlay_info info;
314
315         ovl->get_overlay_info(ovl, &info);
316
317         return snprintf(buf, PAGE_SIZE, "%d\n", info.zorder);
318 }
319
320 static ssize_t overlay_zorder_store(struct omap_overlay *ovl,
321                 const char *buf, size_t size)
322 {
323         int r;
324         u8 zorder;
325         struct omap_overlay_info info;
326
327         if ((ovl->caps & OMAP_DSS_OVL_CAP_ZORDER) == 0)
328                 return -ENODEV;
329
330         r = kstrtou8(buf, 0, &zorder);
331         if (r)
332                 return r;
333
334         ovl->get_overlay_info(ovl, &info);
335
336         info.zorder = zorder;
337
338         r = ovl->set_overlay_info(ovl, &info);
339         if (r)
340                 return r;
341
342         if (ovl->manager) {
343                 r = ovl->manager->apply(ovl->manager);
344                 if (r)
345                         return r;
346         }
347
348         return size;
349 }
350
351 struct overlay_attribute {
352         struct attribute attr;
353         ssize_t (*show)(struct omap_overlay *, char *);
354         ssize_t (*store)(struct omap_overlay *, const char *, size_t);
355 };
356
357 #define OVERLAY_ATTR(_name, _mode, _show, _store) \
358         struct overlay_attribute overlay_attr_##_name = \
359         __ATTR(_name, _mode, _show, _store)
360
361 static OVERLAY_ATTR(name, S_IRUGO, overlay_name_show, NULL);
362 static OVERLAY_ATTR(manager, S_IRUGO|S_IWUSR,
363                 overlay_manager_show, overlay_manager_store);
364 static OVERLAY_ATTR(input_size, S_IRUGO, overlay_input_size_show, NULL);
365 static OVERLAY_ATTR(screen_width, S_IRUGO, overlay_screen_width_show, NULL);
366 static OVERLAY_ATTR(position, S_IRUGO|S_IWUSR,
367                 overlay_position_show, overlay_position_store);
368 static OVERLAY_ATTR(output_size, S_IRUGO|S_IWUSR,
369                 overlay_output_size_show, overlay_output_size_store);
370 static OVERLAY_ATTR(enabled, S_IRUGO|S_IWUSR,
371                 overlay_enabled_show, overlay_enabled_store);
372 static OVERLAY_ATTR(global_alpha, S_IRUGO|S_IWUSR,
373                 overlay_global_alpha_show, overlay_global_alpha_store);
374 static OVERLAY_ATTR(pre_mult_alpha, S_IRUGO|S_IWUSR,
375                 overlay_pre_mult_alpha_show,
376                 overlay_pre_mult_alpha_store);
377 static OVERLAY_ATTR(zorder, S_IRUGO|S_IWUSR,
378                 overlay_zorder_show, overlay_zorder_store);
379
380 static struct attribute *overlay_sysfs_attrs[] = {
381         &overlay_attr_name.attr,
382         &overlay_attr_manager.attr,
383         &overlay_attr_input_size.attr,
384         &overlay_attr_screen_width.attr,
385         &overlay_attr_position.attr,
386         &overlay_attr_output_size.attr,
387         &overlay_attr_enabled.attr,
388         &overlay_attr_global_alpha.attr,
389         &overlay_attr_pre_mult_alpha.attr,
390         &overlay_attr_zorder.attr,
391         NULL
392 };
393
394 static ssize_t overlay_attr_show(struct kobject *kobj, struct attribute *attr,
395                 char *buf)
396 {
397         struct omap_overlay *overlay;
398         struct overlay_attribute *overlay_attr;
399
400         overlay = container_of(kobj, struct omap_overlay, kobj);
401         overlay_attr = container_of(attr, struct overlay_attribute, attr);
402
403         if (!overlay_attr->show)
404                 return -ENOENT;
405
406         return overlay_attr->show(overlay, buf);
407 }
408
409 static ssize_t overlay_attr_store(struct kobject *kobj, struct attribute *attr,
410                 const char *buf, size_t size)
411 {
412         struct omap_overlay *overlay;
413         struct overlay_attribute *overlay_attr;
414
415         overlay = container_of(kobj, struct omap_overlay, kobj);
416         overlay_attr = container_of(attr, struct overlay_attribute, attr);
417
418         if (!overlay_attr->store)
419                 return -ENOENT;
420
421         return overlay_attr->store(overlay, buf, size);
422 }
423
424 static const struct sysfs_ops overlay_sysfs_ops = {
425         .show = overlay_attr_show,
426         .store = overlay_attr_store,
427 };
428
429 static struct kobj_type overlay_ktype = {
430         .sysfs_ops = &overlay_sysfs_ops,
431         .default_attrs = overlay_sysfs_attrs,
432 };
433
434 int dss_overlay_kobj_init(struct omap_overlay *ovl,
435                 struct platform_device *pdev)
436 {
437         return kobject_init_and_add(&ovl->kobj, &overlay_ktype,
438                         &pdev->dev.kobj, "overlay%d", ovl->id);
439 }
440
441 void dss_overlay_kobj_uninit(struct omap_overlay *ovl)
442 {
443         kobject_del(&ovl->kobj);
444         kobject_put(&ovl->kobj);
445 }