]> Git Repo - J-linux.git/blob - drivers/video/fbdev/omap2/omapfb/dss/display-sysfs.c
Merge tag 'vfs-6.13-rc7.fixes' of git://git.kernel.org/pub/scm/linux/kernel/git/vfs/vfs
[J-linux.git] / drivers / video / fbdev / omap2 / omapfb / dss / display-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 "DISPLAY"
11
12 #include <linux/kernel.h>
13 #include <linux/kstrtox.h>
14 #include <linux/module.h>
15 #include <linux/platform_device.h>
16 #include <linux/sysfs.h>
17
18 #include <video/omapfb_dss.h>
19 #include "dss.h"
20
21 static ssize_t display_name_show(struct omap_dss_device *dssdev, char *buf)
22 {
23         return sysfs_emit(buf, "%s\n",
24                         dssdev->name ?
25                         dssdev->name : "");
26 }
27
28 static ssize_t display_enabled_show(struct omap_dss_device *dssdev, char *buf)
29 {
30         return sysfs_emit(buf, "%d\n",
31                         omapdss_device_is_enabled(dssdev));
32 }
33
34 static ssize_t display_enabled_store(struct omap_dss_device *dssdev,
35                 const char *buf, size_t size)
36 {
37         int r;
38         bool enable;
39
40         r = kstrtobool(buf, &enable);
41         if (r)
42                 return r;
43
44         if (enable == omapdss_device_is_enabled(dssdev))
45                 return size;
46
47         if (omapdss_device_is_connected(dssdev) == false)
48                 return -ENODEV;
49
50         if (enable) {
51                 r = dssdev->driver->enable(dssdev);
52                 if (r)
53                         return r;
54         } else {
55                 dssdev->driver->disable(dssdev);
56         }
57
58         return size;
59 }
60
61 static ssize_t display_tear_show(struct omap_dss_device *dssdev, char *buf)
62 {
63         return sysfs_emit(buf, "%d\n",
64                         dssdev->driver->get_te ?
65                         dssdev->driver->get_te(dssdev) : 0);
66 }
67
68 static ssize_t display_tear_store(struct omap_dss_device *dssdev,
69         const char *buf, size_t size)
70 {
71         int r;
72         bool te;
73
74         if (!dssdev->driver->enable_te || !dssdev->driver->get_te)
75                 return -ENOENT;
76
77         r = kstrtobool(buf, &te);
78         if (r)
79                 return r;
80
81         r = dssdev->driver->enable_te(dssdev, te);
82         if (r)
83                 return r;
84
85         return size;
86 }
87
88 static ssize_t display_timings_show(struct omap_dss_device *dssdev, char *buf)
89 {
90         struct omap_video_timings t;
91
92         if (!dssdev->driver->get_timings)
93                 return -ENOENT;
94
95         dssdev->driver->get_timings(dssdev, &t);
96
97         return sysfs_emit(buf, "%u,%u/%u/%u/%u,%u/%u/%u/%u\n",
98                         t.pixelclock,
99                         t.x_res, t.hfp, t.hbp, t.hsw,
100                         t.y_res, t.vfp, t.vbp, t.vsw);
101 }
102
103 static ssize_t display_timings_store(struct omap_dss_device *dssdev,
104         const char *buf, size_t size)
105 {
106         struct omap_video_timings t = dssdev->panel.timings;
107         int r, found;
108
109         if (!dssdev->driver->set_timings || !dssdev->driver->check_timings)
110                 return -ENOENT;
111
112         found = 0;
113 #ifdef CONFIG_FB_OMAP2_DSS_VENC
114         if (strncmp("pal", buf, 3) == 0) {
115                 t = omap_dss_pal_timings;
116                 found = 1;
117         } else if (strncmp("ntsc", buf, 4) == 0) {
118                 t = omap_dss_ntsc_timings;
119                 found = 1;
120         }
121 #endif
122         if (!found && sscanf(buf, "%u,%hu/%hu/%hu/%hu,%hu/%hu/%hu/%hu",
123                                 &t.pixelclock,
124                                 &t.x_res, &t.hfp, &t.hbp, &t.hsw,
125                                 &t.y_res, &t.vfp, &t.vbp, &t.vsw) != 9)
126                 return -EINVAL;
127
128         r = dssdev->driver->check_timings(dssdev, &t);
129         if (r)
130                 return r;
131
132         dssdev->driver->disable(dssdev);
133         dssdev->driver->set_timings(dssdev, &t);
134         r = dssdev->driver->enable(dssdev);
135         if (r)
136                 return r;
137
138         return size;
139 }
140
141 static ssize_t display_rotate_show(struct omap_dss_device *dssdev, char *buf)
142 {
143         int rotate;
144         if (!dssdev->driver->get_rotate)
145                 return -ENOENT;
146         rotate = dssdev->driver->get_rotate(dssdev);
147         return sysfs_emit(buf, "%u\n", rotate);
148 }
149
150 static ssize_t display_rotate_store(struct omap_dss_device *dssdev,
151         const char *buf, size_t size)
152 {
153         int rot, r;
154
155         if (!dssdev->driver->set_rotate || !dssdev->driver->get_rotate)
156                 return -ENOENT;
157
158         r = kstrtoint(buf, 0, &rot);
159         if (r)
160                 return r;
161
162         r = dssdev->driver->set_rotate(dssdev, rot);
163         if (r)
164                 return r;
165
166         return size;
167 }
168
169 static ssize_t display_mirror_show(struct omap_dss_device *dssdev, char *buf)
170 {
171         int mirror;
172         if (!dssdev->driver->get_mirror)
173                 return -ENOENT;
174         mirror = dssdev->driver->get_mirror(dssdev);
175         return sysfs_emit(buf, "%u\n", mirror);
176 }
177
178 static ssize_t display_mirror_store(struct omap_dss_device *dssdev,
179         const char *buf, size_t size)
180 {
181         int r;
182         bool mirror;
183
184         if (!dssdev->driver->set_mirror || !dssdev->driver->get_mirror)
185                 return -ENOENT;
186
187         r = kstrtobool(buf, &mirror);
188         if (r)
189                 return r;
190
191         r = dssdev->driver->set_mirror(dssdev, mirror);
192         if (r)
193                 return r;
194
195         return size;
196 }
197
198 static ssize_t display_wss_show(struct omap_dss_device *dssdev, char *buf)
199 {
200         unsigned int wss;
201
202         if (!dssdev->driver->get_wss)
203                 return -ENOENT;
204
205         wss = dssdev->driver->get_wss(dssdev);
206
207         return sysfs_emit(buf, "0x%05x\n", wss);
208 }
209
210 static ssize_t display_wss_store(struct omap_dss_device *dssdev,
211         const char *buf, size_t size)
212 {
213         u32 wss;
214         int r;
215
216         if (!dssdev->driver->get_wss || !dssdev->driver->set_wss)
217                 return -ENOENT;
218
219         r = kstrtou32(buf, 0, &wss);
220         if (r)
221                 return r;
222
223         if (wss > 0xfffff)
224                 return -EINVAL;
225
226         r = dssdev->driver->set_wss(dssdev, wss);
227         if (r)
228                 return r;
229
230         return size;
231 }
232
233 struct display_attribute {
234         struct attribute attr;
235         ssize_t (*show)(struct omap_dss_device *, char *);
236         ssize_t (*store)(struct omap_dss_device *, const char *, size_t);
237 };
238
239 #define DISPLAY_ATTR(_name, _mode, _show, _store) \
240         struct display_attribute display_attr_##_name = \
241         __ATTR(_name, _mode, _show, _store)
242
243 static DISPLAY_ATTR(name, S_IRUGO, display_name_show, NULL);
244 static DISPLAY_ATTR(display_name, S_IRUGO, display_name_show, NULL);
245 static DISPLAY_ATTR(enabled, S_IRUGO|S_IWUSR,
246                 display_enabled_show, display_enabled_store);
247 static DISPLAY_ATTR(tear_elim, S_IRUGO|S_IWUSR,
248                 display_tear_show, display_tear_store);
249 static DISPLAY_ATTR(timings, S_IRUGO|S_IWUSR,
250                 display_timings_show, display_timings_store);
251 static DISPLAY_ATTR(rotate, S_IRUGO|S_IWUSR,
252                 display_rotate_show, display_rotate_store);
253 static DISPLAY_ATTR(mirror, S_IRUGO|S_IWUSR,
254                 display_mirror_show, display_mirror_store);
255 static DISPLAY_ATTR(wss, S_IRUGO|S_IWUSR,
256                 display_wss_show, display_wss_store);
257
258 static struct attribute *display_sysfs_attrs[] = {
259         &display_attr_name.attr,
260         &display_attr_display_name.attr,
261         &display_attr_enabled.attr,
262         &display_attr_tear_elim.attr,
263         &display_attr_timings.attr,
264         &display_attr_rotate.attr,
265         &display_attr_mirror.attr,
266         &display_attr_wss.attr,
267         NULL
268 };
269 ATTRIBUTE_GROUPS(display_sysfs);
270
271 static ssize_t display_attr_show(struct kobject *kobj, struct attribute *attr,
272                 char *buf)
273 {
274         struct omap_dss_device *dssdev;
275         struct display_attribute *display_attr;
276
277         dssdev = container_of(kobj, struct omap_dss_device, kobj);
278         display_attr = container_of(attr, struct display_attribute, attr);
279
280         if (!display_attr->show)
281                 return -ENOENT;
282
283         return display_attr->show(dssdev, buf);
284 }
285
286 static ssize_t display_attr_store(struct kobject *kobj, struct attribute *attr,
287                 const char *buf, size_t size)
288 {
289         struct omap_dss_device *dssdev;
290         struct display_attribute *display_attr;
291
292         dssdev = container_of(kobj, struct omap_dss_device, kobj);
293         display_attr = container_of(attr, struct display_attribute, attr);
294
295         if (!display_attr->store)
296                 return -ENOENT;
297
298         return display_attr->store(dssdev, buf, size);
299 }
300
301 static const struct sysfs_ops display_sysfs_ops = {
302         .show = display_attr_show,
303         .store = display_attr_store,
304 };
305
306 static struct kobj_type display_ktype = {
307         .sysfs_ops = &display_sysfs_ops,
308         .default_groups = display_sysfs_groups,
309 };
310
311 int display_init_sysfs(struct platform_device *pdev)
312 {
313         struct omap_dss_device *dssdev = NULL;
314         int r;
315
316         for_each_dss_dev(dssdev) {
317                 r = kobject_init_and_add(&dssdev->kobj, &display_ktype,
318                         &pdev->dev.kobj, "%s", dssdev->alias);
319                 if (r) {
320                         DSSERR("failed to create sysfs files\n");
321                         omap_dss_put_device(dssdev);
322                         goto err;
323                 }
324         }
325
326         return 0;
327
328 err:
329         display_uninit_sysfs(pdev);
330
331         return r;
332 }
333
334 void display_uninit_sysfs(struct platform_device *pdev)
335 {
336         struct omap_dss_device *dssdev = NULL;
337
338         for_each_dss_dev(dssdev) {
339                 if (kobject_name(&dssdev->kobj) == NULL)
340                         continue;
341
342                 kobject_del(&dssdev->kobj);
343                 kobject_put(&dssdev->kobj);
344
345                 memset(&dssdev->kobj, 0, sizeof(dssdev->kobj));
346         }
347 }
This page took 0.046126 seconds and 4 git commands to generate.