File Index
Files and directories
Sign in
FILE

display-sysfs.c

File preview with syntax highlighting.

linux-6.19.14/drivers/video/fbdev/omap2/omapfb/dss/display-sysfs.c 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 "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
 21static 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
 28static 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
 34static 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
 61static 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
 68static 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
 88static 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
103static 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
141static 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
150static 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
169static 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
178static 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
198static 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
210static 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
233struct 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
243static DISPLAY_ATTR(name, S_IRUGO, display_name_show, NULL);
244static DISPLAY_ATTR(display_name, S_IRUGO, display_name_show, NULL);
245static DISPLAY_ATTR(enabled, S_IRUGO|S_IWUSR,
246		display_enabled_show, display_enabled_store);
247static DISPLAY_ATTR(tear_elim, S_IRUGO|S_IWUSR,
248		display_tear_show, display_tear_store);
249static DISPLAY_ATTR(timings, S_IRUGO|S_IWUSR,
250		display_timings_show, display_timings_store);
251static DISPLAY_ATTR(rotate, S_IRUGO|S_IWUSR,
252		display_rotate_show, display_rotate_store);
253static DISPLAY_ATTR(mirror, S_IRUGO|S_IWUSR,
254		display_mirror_show, display_mirror_store);
255static DISPLAY_ATTR(wss, S_IRUGO|S_IWUSR,
256		display_wss_show, display_wss_store);
257
258static 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};
269ATTRIBUTE_GROUPS(display_sysfs);
270
271static 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
286static 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
301static const struct sysfs_ops display_sysfs_ops = {
302	.show = display_attr_show,
303	.store = display_attr_store,
304};
305
306static struct kobj_type display_ktype = {
307	.sysfs_ops = &display_sysfs_ops,
308	.default_groups = display_sysfs_groups,
309};
310
311int 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
328err:
329	display_uninit_sysfs(pdev);
330
331	return r;
332}
333
334void 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}
~/ Read-only file preview.