brintos

brintos / linux-shallow public Read only

0
0
Text · 7.6 KiB · ae93785 Raw
348 lines · c
1// SPDX-License-Identifier: GPL-2.0-only2/*3 * Copyright (C) 2009 Nokia Corporation4 * Author: Tomi Valkeinen <tomi.valkeinen@nokia.com>5 *6 * Some code and ideas taken from drivers/video/omap/ driver7 * 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_VENC114	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#endif122	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	NULL268};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}348