brintos

brintos / linux-shallow public Read only

0
0
Text · 11.0 KiB · 1b644be Raw
517 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 "MANAGER"11 12#include <linux/kernel.h>13#include <linux/kstrtox.h>14#include <linux/slab.h>15#include <linux/module.h>16#include <linux/platform_device.h>17#include <linux/jiffies.h>18 19#include <video/omapfb_dss.h>20 21#include "dss.h"22#include "dss_features.h"23 24static ssize_t manager_name_show(struct omap_overlay_manager *mgr, char *buf)25{26	return sysfs_emit(buf, "%s\n", mgr->name);27}28 29static ssize_t manager_display_show(struct omap_overlay_manager *mgr, char *buf)30{31	struct omap_dss_device *dssdev = mgr->get_device(mgr);32 33	return sysfs_emit(buf, "%s\n", dssdev ?34			dssdev->name : "<none>");35}36 37static int manager_display_match(struct omap_dss_device *dssdev, void *data)38{39	const char *str = data;40 41	return sysfs_streq(dssdev->name, str);42}43 44static ssize_t manager_display_store(struct omap_overlay_manager *mgr,45		const char *buf, size_t size)46{47	int r = 0;48	size_t len = size;49	struct omap_dss_device *dssdev = NULL;50	struct omap_dss_device *old_dssdev;51 52	if (buf[size-1] == '\n')53		--len;54 55	if (len > 0)56		dssdev = omap_dss_find_device((void *)buf,57			manager_display_match);58 59	if (len > 0 && dssdev == NULL)60		return -EINVAL;61 62	if (dssdev) {63		DSSDBG("display %s found\n", dssdev->name);64 65		if (omapdss_device_is_connected(dssdev)) {66			DSSERR("new display is already connected\n");67			r = -EINVAL;68			goto put_device;69		}70 71		if (omapdss_device_is_enabled(dssdev)) {72			DSSERR("new display is not disabled\n");73			r = -EINVAL;74			goto put_device;75		}76	}77 78	old_dssdev = mgr->get_device(mgr);79	if (old_dssdev) {80		if (omapdss_device_is_enabled(old_dssdev)) {81			DSSERR("old display is not disabled\n");82			r = -EINVAL;83			goto put_device;84		}85 86		old_dssdev->driver->disconnect(old_dssdev);87	}88 89	if (dssdev) {90		r = dssdev->driver->connect(dssdev);91		if (r) {92			DSSERR("failed to connect new device\n");93			goto put_device;94		}95 96		old_dssdev = mgr->get_device(mgr);97		if (old_dssdev != dssdev) {98			DSSERR("failed to connect device to this manager\n");99			dssdev->driver->disconnect(dssdev);100			goto put_device;101		}102 103		r = mgr->apply(mgr);104		if (r) {105			DSSERR("failed to apply dispc config\n");106			goto put_device;107		}108	}109 110put_device:111	if (dssdev)112		omap_dss_put_device(dssdev);113 114	return r ? r : size;115}116 117static ssize_t manager_default_color_show(struct omap_overlay_manager *mgr,118					  char *buf)119{120	struct omap_overlay_manager_info info;121 122	mgr->get_manager_info(mgr, &info);123 124	return sysfs_emit(buf, "%#x\n", info.default_color);125}126 127static ssize_t manager_default_color_store(struct omap_overlay_manager *mgr,128					   const char *buf, size_t size)129{130	struct omap_overlay_manager_info info;131	u32 color;132	int r;133 134	r = kstrtouint(buf, 0, &color);135	if (r)136		return r;137 138	mgr->get_manager_info(mgr, &info);139 140	info.default_color = color;141 142	r = mgr->set_manager_info(mgr, &info);143	if (r)144		return r;145 146	r = mgr->apply(mgr);147	if (r)148		return r;149 150	return size;151}152 153static const char *trans_key_type_str[] = {154	"gfx-destination",155	"video-source",156};157 158static ssize_t manager_trans_key_type_show(struct omap_overlay_manager *mgr,159					   char *buf)160{161	enum omap_dss_trans_key_type key_type;162	struct omap_overlay_manager_info info;163 164	mgr->get_manager_info(mgr, &info);165 166	key_type = info.trans_key_type;167	BUG_ON(key_type >= ARRAY_SIZE(trans_key_type_str));168 169	return sysfs_emit(buf, "%s\n", trans_key_type_str[key_type]);170}171 172static ssize_t manager_trans_key_type_store(struct omap_overlay_manager *mgr,173					    const char *buf, size_t size)174{175	struct omap_overlay_manager_info info;176	int r;177 178	r = sysfs_match_string(trans_key_type_str, buf);179	if (r < 0)180		return r;181 182	mgr->get_manager_info(mgr, &info);183 184	info.trans_key_type = r;185 186	r = mgr->set_manager_info(mgr, &info);187	if (r)188		return r;189 190	r = mgr->apply(mgr);191	if (r)192		return r;193 194	return size;195}196 197static ssize_t manager_trans_key_value_show(struct omap_overlay_manager *mgr,198					    char *buf)199{200	struct omap_overlay_manager_info info;201 202	mgr->get_manager_info(mgr, &info);203 204	return sysfs_emit(buf, "%#x\n", info.trans_key);205}206 207static ssize_t manager_trans_key_value_store(struct omap_overlay_manager *mgr,208					     const char *buf, size_t size)209{210	struct omap_overlay_manager_info info;211	u32 key_value;212	int r;213 214	r = kstrtouint(buf, 0, &key_value);215	if (r)216		return r;217 218	mgr->get_manager_info(mgr, &info);219 220	info.trans_key = key_value;221 222	r = mgr->set_manager_info(mgr, &info);223	if (r)224		return r;225 226	r = mgr->apply(mgr);227	if (r)228		return r;229 230	return size;231}232 233static ssize_t manager_trans_key_enabled_show(struct omap_overlay_manager *mgr,234					      char *buf)235{236	struct omap_overlay_manager_info info;237 238	mgr->get_manager_info(mgr, &info);239 240	return sysfs_emit(buf, "%d\n", info.trans_enabled);241}242 243static ssize_t manager_trans_key_enabled_store(struct omap_overlay_manager *mgr,244					       const char *buf, size_t size)245{246	struct omap_overlay_manager_info info;247	bool enable;248	int r;249 250	r = kstrtobool(buf, &enable);251	if (r)252		return r;253 254	mgr->get_manager_info(mgr, &info);255 256	info.trans_enabled = enable;257 258	r = mgr->set_manager_info(mgr, &info);259	if (r)260		return r;261 262	r = mgr->apply(mgr);263	if (r)264		return r;265 266	return size;267}268 269static ssize_t manager_alpha_blending_enabled_show(270		struct omap_overlay_manager *mgr, char *buf)271{272	struct omap_overlay_manager_info info;273 274	if(!dss_has_feature(FEAT_ALPHA_FIXED_ZORDER))275		return -ENODEV;276 277	mgr->get_manager_info(mgr, &info);278 279	return sysfs_emit(buf, "%d\n",280		info.partial_alpha_enabled);281}282 283static ssize_t manager_alpha_blending_enabled_store(284		struct omap_overlay_manager *mgr,285		const char *buf, size_t size)286{287	struct omap_overlay_manager_info info;288	bool enable;289	int r;290 291	if(!dss_has_feature(FEAT_ALPHA_FIXED_ZORDER))292		return -ENODEV;293 294	r = kstrtobool(buf, &enable);295	if (r)296		return r;297 298	mgr->get_manager_info(mgr, &info);299 300	info.partial_alpha_enabled = enable;301 302	r = mgr->set_manager_info(mgr, &info);303	if (r)304		return r;305 306	r = mgr->apply(mgr);307	if (r)308		return r;309 310	return size;311}312 313static ssize_t manager_cpr_enable_show(struct omap_overlay_manager *mgr,314		char *buf)315{316	struct omap_overlay_manager_info info;317 318	mgr->get_manager_info(mgr, &info);319 320	return sysfs_emit(buf, "%d\n", info.cpr_enable);321}322 323static ssize_t manager_cpr_enable_store(struct omap_overlay_manager *mgr,324		const char *buf, size_t size)325{326	struct omap_overlay_manager_info info;327	int r;328	bool enable;329 330	if (!dss_has_feature(FEAT_CPR))331		return -ENODEV;332 333	r = kstrtobool(buf, &enable);334	if (r)335		return r;336 337	mgr->get_manager_info(mgr, &info);338 339	if (info.cpr_enable == enable)340		return size;341 342	info.cpr_enable = enable;343 344	r = mgr->set_manager_info(mgr, &info);345	if (r)346		return r;347 348	r = mgr->apply(mgr);349	if (r)350		return r;351 352	return size;353}354 355static ssize_t manager_cpr_coef_show(struct omap_overlay_manager *mgr,356		char *buf)357{358	struct omap_overlay_manager_info info;359 360	mgr->get_manager_info(mgr, &info);361 362	return sysfs_emit(buf,363			"%d %d %d %d %d %d %d %d %d\n",364			info.cpr_coefs.rr,365			info.cpr_coefs.rg,366			info.cpr_coefs.rb,367			info.cpr_coefs.gr,368			info.cpr_coefs.gg,369			info.cpr_coefs.gb,370			info.cpr_coefs.br,371			info.cpr_coefs.bg,372			info.cpr_coefs.bb);373}374 375static ssize_t manager_cpr_coef_store(struct omap_overlay_manager *mgr,376		const char *buf, size_t size)377{378	struct omap_overlay_manager_info info;379	struct omap_dss_cpr_coefs coefs;380	int r, i;381	s16 *arr;382 383	if (!dss_has_feature(FEAT_CPR))384		return -ENODEV;385 386	if (sscanf(buf, "%hd %hd %hd %hd %hd %hd %hd %hd %hd",387				&coefs.rr, &coefs.rg, &coefs.rb,388				&coefs.gr, &coefs.gg, &coefs.gb,389				&coefs.br, &coefs.bg, &coefs.bb) != 9)390		return -EINVAL;391 392	arr = (s16[]){ coefs.rr, coefs.rg, coefs.rb,393		coefs.gr, coefs.gg, coefs.gb,394		coefs.br, coefs.bg, coefs.bb };395 396	for (i = 0; i < 9; ++i) {397		if (arr[i] < -512 || arr[i] > 511)398			return -EINVAL;399	}400 401	mgr->get_manager_info(mgr, &info);402 403	info.cpr_coefs = coefs;404 405	r = mgr->set_manager_info(mgr, &info);406	if (r)407		return r;408 409	r = mgr->apply(mgr);410	if (r)411		return r;412 413	return size;414}415 416struct manager_attribute {417	struct attribute attr;418	ssize_t (*show)(struct omap_overlay_manager *, char *);419	ssize_t	(*store)(struct omap_overlay_manager *, const char *, size_t);420};421 422#define MANAGER_ATTR(_name, _mode, _show, _store) \423	struct manager_attribute manager_attr_##_name = \424	__ATTR(_name, _mode, _show, _store)425 426static MANAGER_ATTR(name, S_IRUGO, manager_name_show, NULL);427static MANAGER_ATTR(display, S_IRUGO|S_IWUSR,428		manager_display_show, manager_display_store);429static MANAGER_ATTR(default_color, S_IRUGO|S_IWUSR,430		manager_default_color_show, manager_default_color_store);431static MANAGER_ATTR(trans_key_type, S_IRUGO|S_IWUSR,432		manager_trans_key_type_show, manager_trans_key_type_store);433static MANAGER_ATTR(trans_key_value, S_IRUGO|S_IWUSR,434		manager_trans_key_value_show, manager_trans_key_value_store);435static MANAGER_ATTR(trans_key_enabled, S_IRUGO|S_IWUSR,436		manager_trans_key_enabled_show,437		manager_trans_key_enabled_store);438static MANAGER_ATTR(alpha_blending_enabled, S_IRUGO|S_IWUSR,439		manager_alpha_blending_enabled_show,440		manager_alpha_blending_enabled_store);441static MANAGER_ATTR(cpr_enable, S_IRUGO|S_IWUSR,442		manager_cpr_enable_show,443		manager_cpr_enable_store);444static MANAGER_ATTR(cpr_coef, S_IRUGO|S_IWUSR,445		manager_cpr_coef_show,446		manager_cpr_coef_store);447 448 449static struct attribute *manager_sysfs_attrs[] = {450	&manager_attr_name.attr,451	&manager_attr_display.attr,452	&manager_attr_default_color.attr,453	&manager_attr_trans_key_type.attr,454	&manager_attr_trans_key_value.attr,455	&manager_attr_trans_key_enabled.attr,456	&manager_attr_alpha_blending_enabled.attr,457	&manager_attr_cpr_enable.attr,458	&manager_attr_cpr_coef.attr,459	NULL460};461ATTRIBUTE_GROUPS(manager_sysfs);462 463static ssize_t manager_attr_show(struct kobject *kobj, struct attribute *attr,464		char *buf)465{466	struct omap_overlay_manager *manager;467	struct manager_attribute *manager_attr;468 469	manager = container_of(kobj, struct omap_overlay_manager, kobj);470	manager_attr = container_of(attr, struct manager_attribute, attr);471 472	if (!manager_attr->show)473		return -ENOENT;474 475	return manager_attr->show(manager, buf);476}477 478static ssize_t manager_attr_store(struct kobject *kobj, struct attribute *attr,479		const char *buf, size_t size)480{481	struct omap_overlay_manager *manager;482	struct manager_attribute *manager_attr;483 484	manager = container_of(kobj, struct omap_overlay_manager, kobj);485	manager_attr = container_of(attr, struct manager_attribute, attr);486 487	if (!manager_attr->store)488		return -ENOENT;489 490	return manager_attr->store(manager, buf, size);491}492 493static const struct sysfs_ops manager_sysfs_ops = {494	.show = manager_attr_show,495	.store = manager_attr_store,496};497 498static struct kobj_type manager_ktype = {499	.sysfs_ops = &manager_sysfs_ops,500	.default_groups = manager_sysfs_groups,501};502 503int dss_manager_kobj_init(struct omap_overlay_manager *mgr,504		struct platform_device *pdev)505{506	return kobject_init_and_add(&mgr->kobj, &manager_ktype,507			&pdev->dev.kobj, "manager%d", mgr->id);508}509 510void dss_manager_kobj_uninit(struct omap_overlay_manager *mgr)511{512	kobject_del(&mgr->kobj);513	kobject_put(&mgr->kobj);514 515	memset(&mgr->kobj, 0, sizeof(mgr->kobj));516}517