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