18c2ecf20Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0-only
28c2ecf20Sopenharmony_ci/*
38c2ecf20Sopenharmony_ci * Copyright (C) 2009 Nokia Corporation
48c2ecf20Sopenharmony_ci * Author: Tomi Valkeinen <tomi.valkeinen@nokia.com>
58c2ecf20Sopenharmony_ci *
68c2ecf20Sopenharmony_ci * Some code and ideas taken from drivers/video/omap/ driver
78c2ecf20Sopenharmony_ci * by Imre Deak.
88c2ecf20Sopenharmony_ci */
98c2ecf20Sopenharmony_ci
108c2ecf20Sopenharmony_ci#define DSS_SUBSYS_NAME "MANAGER"
118c2ecf20Sopenharmony_ci
128c2ecf20Sopenharmony_ci#include <linux/kernel.h>
138c2ecf20Sopenharmony_ci#include <linux/slab.h>
148c2ecf20Sopenharmony_ci#include <linux/module.h>
158c2ecf20Sopenharmony_ci#include <linux/platform_device.h>
168c2ecf20Sopenharmony_ci#include <linux/jiffies.h>
178c2ecf20Sopenharmony_ci
188c2ecf20Sopenharmony_ci#include <video/omapfb_dss.h>
198c2ecf20Sopenharmony_ci
208c2ecf20Sopenharmony_ci#include "dss.h"
218c2ecf20Sopenharmony_ci#include "dss_features.h"
228c2ecf20Sopenharmony_ci
238c2ecf20Sopenharmony_cistatic ssize_t manager_name_show(struct omap_overlay_manager *mgr, char *buf)
248c2ecf20Sopenharmony_ci{
258c2ecf20Sopenharmony_ci	return snprintf(buf, PAGE_SIZE, "%s\n", mgr->name);
268c2ecf20Sopenharmony_ci}
278c2ecf20Sopenharmony_ci
288c2ecf20Sopenharmony_cistatic ssize_t manager_display_show(struct omap_overlay_manager *mgr, char *buf)
298c2ecf20Sopenharmony_ci{
308c2ecf20Sopenharmony_ci	struct omap_dss_device *dssdev = mgr->get_device(mgr);
318c2ecf20Sopenharmony_ci
328c2ecf20Sopenharmony_ci	return snprintf(buf, PAGE_SIZE, "%s\n", dssdev ?
338c2ecf20Sopenharmony_ci			dssdev->name : "<none>");
348c2ecf20Sopenharmony_ci}
358c2ecf20Sopenharmony_ci
368c2ecf20Sopenharmony_cistatic int manager_display_match(struct omap_dss_device *dssdev, void *data)
378c2ecf20Sopenharmony_ci{
388c2ecf20Sopenharmony_ci	const char *str = data;
398c2ecf20Sopenharmony_ci
408c2ecf20Sopenharmony_ci	return sysfs_streq(dssdev->name, str);
418c2ecf20Sopenharmony_ci}
428c2ecf20Sopenharmony_ci
438c2ecf20Sopenharmony_cistatic ssize_t manager_display_store(struct omap_overlay_manager *mgr,
448c2ecf20Sopenharmony_ci		const char *buf, size_t size)
458c2ecf20Sopenharmony_ci{
468c2ecf20Sopenharmony_ci	int r = 0;
478c2ecf20Sopenharmony_ci	size_t len = size;
488c2ecf20Sopenharmony_ci	struct omap_dss_device *dssdev = NULL;
498c2ecf20Sopenharmony_ci	struct omap_dss_device *old_dssdev;
508c2ecf20Sopenharmony_ci
518c2ecf20Sopenharmony_ci	if (buf[size-1] == '\n')
528c2ecf20Sopenharmony_ci		--len;
538c2ecf20Sopenharmony_ci
548c2ecf20Sopenharmony_ci	if (len > 0)
558c2ecf20Sopenharmony_ci		dssdev = omap_dss_find_device((void *)buf,
568c2ecf20Sopenharmony_ci			manager_display_match);
578c2ecf20Sopenharmony_ci
588c2ecf20Sopenharmony_ci	if (len > 0 && dssdev == NULL)
598c2ecf20Sopenharmony_ci		return -EINVAL;
608c2ecf20Sopenharmony_ci
618c2ecf20Sopenharmony_ci	if (dssdev) {
628c2ecf20Sopenharmony_ci		DSSDBG("display %s found\n", dssdev->name);
638c2ecf20Sopenharmony_ci
648c2ecf20Sopenharmony_ci		if (omapdss_device_is_connected(dssdev)) {
658c2ecf20Sopenharmony_ci			DSSERR("new display is already connected\n");
668c2ecf20Sopenharmony_ci			r = -EINVAL;
678c2ecf20Sopenharmony_ci			goto put_device;
688c2ecf20Sopenharmony_ci		}
698c2ecf20Sopenharmony_ci
708c2ecf20Sopenharmony_ci		if (omapdss_device_is_enabled(dssdev)) {
718c2ecf20Sopenharmony_ci			DSSERR("new display is not disabled\n");
728c2ecf20Sopenharmony_ci			r = -EINVAL;
738c2ecf20Sopenharmony_ci			goto put_device;
748c2ecf20Sopenharmony_ci		}
758c2ecf20Sopenharmony_ci	}
768c2ecf20Sopenharmony_ci
778c2ecf20Sopenharmony_ci	old_dssdev = mgr->get_device(mgr);
788c2ecf20Sopenharmony_ci	if (old_dssdev) {
798c2ecf20Sopenharmony_ci		if (omapdss_device_is_enabled(old_dssdev)) {
808c2ecf20Sopenharmony_ci			DSSERR("old display is not disabled\n");
818c2ecf20Sopenharmony_ci			r = -EINVAL;
828c2ecf20Sopenharmony_ci			goto put_device;
838c2ecf20Sopenharmony_ci		}
848c2ecf20Sopenharmony_ci
858c2ecf20Sopenharmony_ci		old_dssdev->driver->disconnect(old_dssdev);
868c2ecf20Sopenharmony_ci	}
878c2ecf20Sopenharmony_ci
888c2ecf20Sopenharmony_ci	if (dssdev) {
898c2ecf20Sopenharmony_ci		r = dssdev->driver->connect(dssdev);
908c2ecf20Sopenharmony_ci		if (r) {
918c2ecf20Sopenharmony_ci			DSSERR("failed to connect new device\n");
928c2ecf20Sopenharmony_ci			goto put_device;
938c2ecf20Sopenharmony_ci		}
948c2ecf20Sopenharmony_ci
958c2ecf20Sopenharmony_ci		old_dssdev = mgr->get_device(mgr);
968c2ecf20Sopenharmony_ci		if (old_dssdev != dssdev) {
978c2ecf20Sopenharmony_ci			DSSERR("failed to connect device to this manager\n");
988c2ecf20Sopenharmony_ci			dssdev->driver->disconnect(dssdev);
998c2ecf20Sopenharmony_ci			goto put_device;
1008c2ecf20Sopenharmony_ci		}
1018c2ecf20Sopenharmony_ci
1028c2ecf20Sopenharmony_ci		r = mgr->apply(mgr);
1038c2ecf20Sopenharmony_ci		if (r) {
1048c2ecf20Sopenharmony_ci			DSSERR("failed to apply dispc config\n");
1058c2ecf20Sopenharmony_ci			goto put_device;
1068c2ecf20Sopenharmony_ci		}
1078c2ecf20Sopenharmony_ci	}
1088c2ecf20Sopenharmony_ci
1098c2ecf20Sopenharmony_ciput_device:
1108c2ecf20Sopenharmony_ci	if (dssdev)
1118c2ecf20Sopenharmony_ci		omap_dss_put_device(dssdev);
1128c2ecf20Sopenharmony_ci
1138c2ecf20Sopenharmony_ci	return r ? r : size;
1148c2ecf20Sopenharmony_ci}
1158c2ecf20Sopenharmony_ci
1168c2ecf20Sopenharmony_cistatic ssize_t manager_default_color_show(struct omap_overlay_manager *mgr,
1178c2ecf20Sopenharmony_ci					  char *buf)
1188c2ecf20Sopenharmony_ci{
1198c2ecf20Sopenharmony_ci	struct omap_overlay_manager_info info;
1208c2ecf20Sopenharmony_ci
1218c2ecf20Sopenharmony_ci	mgr->get_manager_info(mgr, &info);
1228c2ecf20Sopenharmony_ci
1238c2ecf20Sopenharmony_ci	return snprintf(buf, PAGE_SIZE, "%#x\n", info.default_color);
1248c2ecf20Sopenharmony_ci}
1258c2ecf20Sopenharmony_ci
1268c2ecf20Sopenharmony_cistatic ssize_t manager_default_color_store(struct omap_overlay_manager *mgr,
1278c2ecf20Sopenharmony_ci					   const char *buf, size_t size)
1288c2ecf20Sopenharmony_ci{
1298c2ecf20Sopenharmony_ci	struct omap_overlay_manager_info info;
1308c2ecf20Sopenharmony_ci	u32 color;
1318c2ecf20Sopenharmony_ci	int r;
1328c2ecf20Sopenharmony_ci
1338c2ecf20Sopenharmony_ci	r = kstrtouint(buf, 0, &color);
1348c2ecf20Sopenharmony_ci	if (r)
1358c2ecf20Sopenharmony_ci		return r;
1368c2ecf20Sopenharmony_ci
1378c2ecf20Sopenharmony_ci	mgr->get_manager_info(mgr, &info);
1388c2ecf20Sopenharmony_ci
1398c2ecf20Sopenharmony_ci	info.default_color = color;
1408c2ecf20Sopenharmony_ci
1418c2ecf20Sopenharmony_ci	r = mgr->set_manager_info(mgr, &info);
1428c2ecf20Sopenharmony_ci	if (r)
1438c2ecf20Sopenharmony_ci		return r;
1448c2ecf20Sopenharmony_ci
1458c2ecf20Sopenharmony_ci	r = mgr->apply(mgr);
1468c2ecf20Sopenharmony_ci	if (r)
1478c2ecf20Sopenharmony_ci		return r;
1488c2ecf20Sopenharmony_ci
1498c2ecf20Sopenharmony_ci	return size;
1508c2ecf20Sopenharmony_ci}
1518c2ecf20Sopenharmony_ci
1528c2ecf20Sopenharmony_cistatic const char *trans_key_type_str[] = {
1538c2ecf20Sopenharmony_ci	"gfx-destination",
1548c2ecf20Sopenharmony_ci	"video-source",
1558c2ecf20Sopenharmony_ci};
1568c2ecf20Sopenharmony_ci
1578c2ecf20Sopenharmony_cistatic ssize_t manager_trans_key_type_show(struct omap_overlay_manager *mgr,
1588c2ecf20Sopenharmony_ci					   char *buf)
1598c2ecf20Sopenharmony_ci{
1608c2ecf20Sopenharmony_ci	enum omap_dss_trans_key_type key_type;
1618c2ecf20Sopenharmony_ci	struct omap_overlay_manager_info info;
1628c2ecf20Sopenharmony_ci
1638c2ecf20Sopenharmony_ci	mgr->get_manager_info(mgr, &info);
1648c2ecf20Sopenharmony_ci
1658c2ecf20Sopenharmony_ci	key_type = info.trans_key_type;
1668c2ecf20Sopenharmony_ci	BUG_ON(key_type >= ARRAY_SIZE(trans_key_type_str));
1678c2ecf20Sopenharmony_ci
1688c2ecf20Sopenharmony_ci	return snprintf(buf, PAGE_SIZE, "%s\n", trans_key_type_str[key_type]);
1698c2ecf20Sopenharmony_ci}
1708c2ecf20Sopenharmony_ci
1718c2ecf20Sopenharmony_cistatic ssize_t manager_trans_key_type_store(struct omap_overlay_manager *mgr,
1728c2ecf20Sopenharmony_ci					    const char *buf, size_t size)
1738c2ecf20Sopenharmony_ci{
1748c2ecf20Sopenharmony_ci	struct omap_overlay_manager_info info;
1758c2ecf20Sopenharmony_ci	int r;
1768c2ecf20Sopenharmony_ci
1778c2ecf20Sopenharmony_ci	r = sysfs_match_string(trans_key_type_str, buf);
1788c2ecf20Sopenharmony_ci	if (r < 0)
1798c2ecf20Sopenharmony_ci		return r;
1808c2ecf20Sopenharmony_ci
1818c2ecf20Sopenharmony_ci	mgr->get_manager_info(mgr, &info);
1828c2ecf20Sopenharmony_ci
1838c2ecf20Sopenharmony_ci	info.trans_key_type = r;
1848c2ecf20Sopenharmony_ci
1858c2ecf20Sopenharmony_ci	r = mgr->set_manager_info(mgr, &info);
1868c2ecf20Sopenharmony_ci	if (r)
1878c2ecf20Sopenharmony_ci		return r;
1888c2ecf20Sopenharmony_ci
1898c2ecf20Sopenharmony_ci	r = mgr->apply(mgr);
1908c2ecf20Sopenharmony_ci	if (r)
1918c2ecf20Sopenharmony_ci		return r;
1928c2ecf20Sopenharmony_ci
1938c2ecf20Sopenharmony_ci	return size;
1948c2ecf20Sopenharmony_ci}
1958c2ecf20Sopenharmony_ci
1968c2ecf20Sopenharmony_cistatic ssize_t manager_trans_key_value_show(struct omap_overlay_manager *mgr,
1978c2ecf20Sopenharmony_ci					    char *buf)
1988c2ecf20Sopenharmony_ci{
1998c2ecf20Sopenharmony_ci	struct omap_overlay_manager_info info;
2008c2ecf20Sopenharmony_ci
2018c2ecf20Sopenharmony_ci	mgr->get_manager_info(mgr, &info);
2028c2ecf20Sopenharmony_ci
2038c2ecf20Sopenharmony_ci	return snprintf(buf, PAGE_SIZE, "%#x\n", info.trans_key);
2048c2ecf20Sopenharmony_ci}
2058c2ecf20Sopenharmony_ci
2068c2ecf20Sopenharmony_cistatic ssize_t manager_trans_key_value_store(struct omap_overlay_manager *mgr,
2078c2ecf20Sopenharmony_ci					     const char *buf, size_t size)
2088c2ecf20Sopenharmony_ci{
2098c2ecf20Sopenharmony_ci	struct omap_overlay_manager_info info;
2108c2ecf20Sopenharmony_ci	u32 key_value;
2118c2ecf20Sopenharmony_ci	int r;
2128c2ecf20Sopenharmony_ci
2138c2ecf20Sopenharmony_ci	r = kstrtouint(buf, 0, &key_value);
2148c2ecf20Sopenharmony_ci	if (r)
2158c2ecf20Sopenharmony_ci		return r;
2168c2ecf20Sopenharmony_ci
2178c2ecf20Sopenharmony_ci	mgr->get_manager_info(mgr, &info);
2188c2ecf20Sopenharmony_ci
2198c2ecf20Sopenharmony_ci	info.trans_key = key_value;
2208c2ecf20Sopenharmony_ci
2218c2ecf20Sopenharmony_ci	r = mgr->set_manager_info(mgr, &info);
2228c2ecf20Sopenharmony_ci	if (r)
2238c2ecf20Sopenharmony_ci		return r;
2248c2ecf20Sopenharmony_ci
2258c2ecf20Sopenharmony_ci	r = mgr->apply(mgr);
2268c2ecf20Sopenharmony_ci	if (r)
2278c2ecf20Sopenharmony_ci		return r;
2288c2ecf20Sopenharmony_ci
2298c2ecf20Sopenharmony_ci	return size;
2308c2ecf20Sopenharmony_ci}
2318c2ecf20Sopenharmony_ci
2328c2ecf20Sopenharmony_cistatic ssize_t manager_trans_key_enabled_show(struct omap_overlay_manager *mgr,
2338c2ecf20Sopenharmony_ci					      char *buf)
2348c2ecf20Sopenharmony_ci{
2358c2ecf20Sopenharmony_ci	struct omap_overlay_manager_info info;
2368c2ecf20Sopenharmony_ci
2378c2ecf20Sopenharmony_ci	mgr->get_manager_info(mgr, &info);
2388c2ecf20Sopenharmony_ci
2398c2ecf20Sopenharmony_ci	return snprintf(buf, PAGE_SIZE, "%d\n", info.trans_enabled);
2408c2ecf20Sopenharmony_ci}
2418c2ecf20Sopenharmony_ci
2428c2ecf20Sopenharmony_cistatic ssize_t manager_trans_key_enabled_store(struct omap_overlay_manager *mgr,
2438c2ecf20Sopenharmony_ci					       const char *buf, size_t size)
2448c2ecf20Sopenharmony_ci{
2458c2ecf20Sopenharmony_ci	struct omap_overlay_manager_info info;
2468c2ecf20Sopenharmony_ci	bool enable;
2478c2ecf20Sopenharmony_ci	int r;
2488c2ecf20Sopenharmony_ci
2498c2ecf20Sopenharmony_ci	r = strtobool(buf, &enable);
2508c2ecf20Sopenharmony_ci	if (r)
2518c2ecf20Sopenharmony_ci		return r;
2528c2ecf20Sopenharmony_ci
2538c2ecf20Sopenharmony_ci	mgr->get_manager_info(mgr, &info);
2548c2ecf20Sopenharmony_ci
2558c2ecf20Sopenharmony_ci	info.trans_enabled = enable;
2568c2ecf20Sopenharmony_ci
2578c2ecf20Sopenharmony_ci	r = mgr->set_manager_info(mgr, &info);
2588c2ecf20Sopenharmony_ci	if (r)
2598c2ecf20Sopenharmony_ci		return r;
2608c2ecf20Sopenharmony_ci
2618c2ecf20Sopenharmony_ci	r = mgr->apply(mgr);
2628c2ecf20Sopenharmony_ci	if (r)
2638c2ecf20Sopenharmony_ci		return r;
2648c2ecf20Sopenharmony_ci
2658c2ecf20Sopenharmony_ci	return size;
2668c2ecf20Sopenharmony_ci}
2678c2ecf20Sopenharmony_ci
2688c2ecf20Sopenharmony_cistatic ssize_t manager_alpha_blending_enabled_show(
2698c2ecf20Sopenharmony_ci		struct omap_overlay_manager *mgr, char *buf)
2708c2ecf20Sopenharmony_ci{
2718c2ecf20Sopenharmony_ci	struct omap_overlay_manager_info info;
2728c2ecf20Sopenharmony_ci
2738c2ecf20Sopenharmony_ci	if(!dss_has_feature(FEAT_ALPHA_FIXED_ZORDER))
2748c2ecf20Sopenharmony_ci		return -ENODEV;
2758c2ecf20Sopenharmony_ci
2768c2ecf20Sopenharmony_ci	mgr->get_manager_info(mgr, &info);
2778c2ecf20Sopenharmony_ci
2788c2ecf20Sopenharmony_ci	return snprintf(buf, PAGE_SIZE, "%d\n",
2798c2ecf20Sopenharmony_ci		info.partial_alpha_enabled);
2808c2ecf20Sopenharmony_ci}
2818c2ecf20Sopenharmony_ci
2828c2ecf20Sopenharmony_cistatic ssize_t manager_alpha_blending_enabled_store(
2838c2ecf20Sopenharmony_ci		struct omap_overlay_manager *mgr,
2848c2ecf20Sopenharmony_ci		const char *buf, size_t size)
2858c2ecf20Sopenharmony_ci{
2868c2ecf20Sopenharmony_ci	struct omap_overlay_manager_info info;
2878c2ecf20Sopenharmony_ci	bool enable;
2888c2ecf20Sopenharmony_ci	int r;
2898c2ecf20Sopenharmony_ci
2908c2ecf20Sopenharmony_ci	if(!dss_has_feature(FEAT_ALPHA_FIXED_ZORDER))
2918c2ecf20Sopenharmony_ci		return -ENODEV;
2928c2ecf20Sopenharmony_ci
2938c2ecf20Sopenharmony_ci	r = strtobool(buf, &enable);
2948c2ecf20Sopenharmony_ci	if (r)
2958c2ecf20Sopenharmony_ci		return r;
2968c2ecf20Sopenharmony_ci
2978c2ecf20Sopenharmony_ci	mgr->get_manager_info(mgr, &info);
2988c2ecf20Sopenharmony_ci
2998c2ecf20Sopenharmony_ci	info.partial_alpha_enabled = enable;
3008c2ecf20Sopenharmony_ci
3018c2ecf20Sopenharmony_ci	r = mgr->set_manager_info(mgr, &info);
3028c2ecf20Sopenharmony_ci	if (r)
3038c2ecf20Sopenharmony_ci		return r;
3048c2ecf20Sopenharmony_ci
3058c2ecf20Sopenharmony_ci	r = mgr->apply(mgr);
3068c2ecf20Sopenharmony_ci	if (r)
3078c2ecf20Sopenharmony_ci		return r;
3088c2ecf20Sopenharmony_ci
3098c2ecf20Sopenharmony_ci	return size;
3108c2ecf20Sopenharmony_ci}
3118c2ecf20Sopenharmony_ci
3128c2ecf20Sopenharmony_cistatic ssize_t manager_cpr_enable_show(struct omap_overlay_manager *mgr,
3138c2ecf20Sopenharmony_ci		char *buf)
3148c2ecf20Sopenharmony_ci{
3158c2ecf20Sopenharmony_ci	struct omap_overlay_manager_info info;
3168c2ecf20Sopenharmony_ci
3178c2ecf20Sopenharmony_ci	mgr->get_manager_info(mgr, &info);
3188c2ecf20Sopenharmony_ci
3198c2ecf20Sopenharmony_ci	return snprintf(buf, PAGE_SIZE, "%d\n", info.cpr_enable);
3208c2ecf20Sopenharmony_ci}
3218c2ecf20Sopenharmony_ci
3228c2ecf20Sopenharmony_cistatic ssize_t manager_cpr_enable_store(struct omap_overlay_manager *mgr,
3238c2ecf20Sopenharmony_ci		const char *buf, size_t size)
3248c2ecf20Sopenharmony_ci{
3258c2ecf20Sopenharmony_ci	struct omap_overlay_manager_info info;
3268c2ecf20Sopenharmony_ci	int r;
3278c2ecf20Sopenharmony_ci	bool enable;
3288c2ecf20Sopenharmony_ci
3298c2ecf20Sopenharmony_ci	if (!dss_has_feature(FEAT_CPR))
3308c2ecf20Sopenharmony_ci		return -ENODEV;
3318c2ecf20Sopenharmony_ci
3328c2ecf20Sopenharmony_ci	r = strtobool(buf, &enable);
3338c2ecf20Sopenharmony_ci	if (r)
3348c2ecf20Sopenharmony_ci		return r;
3358c2ecf20Sopenharmony_ci
3368c2ecf20Sopenharmony_ci	mgr->get_manager_info(mgr, &info);
3378c2ecf20Sopenharmony_ci
3388c2ecf20Sopenharmony_ci	if (info.cpr_enable == enable)
3398c2ecf20Sopenharmony_ci		return size;
3408c2ecf20Sopenharmony_ci
3418c2ecf20Sopenharmony_ci	info.cpr_enable = enable;
3428c2ecf20Sopenharmony_ci
3438c2ecf20Sopenharmony_ci	r = mgr->set_manager_info(mgr, &info);
3448c2ecf20Sopenharmony_ci	if (r)
3458c2ecf20Sopenharmony_ci		return r;
3468c2ecf20Sopenharmony_ci
3478c2ecf20Sopenharmony_ci	r = mgr->apply(mgr);
3488c2ecf20Sopenharmony_ci	if (r)
3498c2ecf20Sopenharmony_ci		return r;
3508c2ecf20Sopenharmony_ci
3518c2ecf20Sopenharmony_ci	return size;
3528c2ecf20Sopenharmony_ci}
3538c2ecf20Sopenharmony_ci
3548c2ecf20Sopenharmony_cistatic ssize_t manager_cpr_coef_show(struct omap_overlay_manager *mgr,
3558c2ecf20Sopenharmony_ci		char *buf)
3568c2ecf20Sopenharmony_ci{
3578c2ecf20Sopenharmony_ci	struct omap_overlay_manager_info info;
3588c2ecf20Sopenharmony_ci
3598c2ecf20Sopenharmony_ci	mgr->get_manager_info(mgr, &info);
3608c2ecf20Sopenharmony_ci
3618c2ecf20Sopenharmony_ci	return snprintf(buf, PAGE_SIZE,
3628c2ecf20Sopenharmony_ci			"%d %d %d %d %d %d %d %d %d\n",
3638c2ecf20Sopenharmony_ci			info.cpr_coefs.rr,
3648c2ecf20Sopenharmony_ci			info.cpr_coefs.rg,
3658c2ecf20Sopenharmony_ci			info.cpr_coefs.rb,
3668c2ecf20Sopenharmony_ci			info.cpr_coefs.gr,
3678c2ecf20Sopenharmony_ci			info.cpr_coefs.gg,
3688c2ecf20Sopenharmony_ci			info.cpr_coefs.gb,
3698c2ecf20Sopenharmony_ci			info.cpr_coefs.br,
3708c2ecf20Sopenharmony_ci			info.cpr_coefs.bg,
3718c2ecf20Sopenharmony_ci			info.cpr_coefs.bb);
3728c2ecf20Sopenharmony_ci}
3738c2ecf20Sopenharmony_ci
3748c2ecf20Sopenharmony_cistatic ssize_t manager_cpr_coef_store(struct omap_overlay_manager *mgr,
3758c2ecf20Sopenharmony_ci		const char *buf, size_t size)
3768c2ecf20Sopenharmony_ci{
3778c2ecf20Sopenharmony_ci	struct omap_overlay_manager_info info;
3788c2ecf20Sopenharmony_ci	struct omap_dss_cpr_coefs coefs;
3798c2ecf20Sopenharmony_ci	int r, i;
3808c2ecf20Sopenharmony_ci	s16 *arr;
3818c2ecf20Sopenharmony_ci
3828c2ecf20Sopenharmony_ci	if (!dss_has_feature(FEAT_CPR))
3838c2ecf20Sopenharmony_ci		return -ENODEV;
3848c2ecf20Sopenharmony_ci
3858c2ecf20Sopenharmony_ci	if (sscanf(buf, "%hd %hd %hd %hd %hd %hd %hd %hd %hd",
3868c2ecf20Sopenharmony_ci				&coefs.rr, &coefs.rg, &coefs.rb,
3878c2ecf20Sopenharmony_ci				&coefs.gr, &coefs.gg, &coefs.gb,
3888c2ecf20Sopenharmony_ci				&coefs.br, &coefs.bg, &coefs.bb) != 9)
3898c2ecf20Sopenharmony_ci		return -EINVAL;
3908c2ecf20Sopenharmony_ci
3918c2ecf20Sopenharmony_ci	arr = (s16[]){ coefs.rr, coefs.rg, coefs.rb,
3928c2ecf20Sopenharmony_ci		coefs.gr, coefs.gg, coefs.gb,
3938c2ecf20Sopenharmony_ci		coefs.br, coefs.bg, coefs.bb };
3948c2ecf20Sopenharmony_ci
3958c2ecf20Sopenharmony_ci	for (i = 0; i < 9; ++i) {
3968c2ecf20Sopenharmony_ci		if (arr[i] < -512 || arr[i] > 511)
3978c2ecf20Sopenharmony_ci			return -EINVAL;
3988c2ecf20Sopenharmony_ci	}
3998c2ecf20Sopenharmony_ci
4008c2ecf20Sopenharmony_ci	mgr->get_manager_info(mgr, &info);
4018c2ecf20Sopenharmony_ci
4028c2ecf20Sopenharmony_ci	info.cpr_coefs = coefs;
4038c2ecf20Sopenharmony_ci
4048c2ecf20Sopenharmony_ci	r = mgr->set_manager_info(mgr, &info);
4058c2ecf20Sopenharmony_ci	if (r)
4068c2ecf20Sopenharmony_ci		return r;
4078c2ecf20Sopenharmony_ci
4088c2ecf20Sopenharmony_ci	r = mgr->apply(mgr);
4098c2ecf20Sopenharmony_ci	if (r)
4108c2ecf20Sopenharmony_ci		return r;
4118c2ecf20Sopenharmony_ci
4128c2ecf20Sopenharmony_ci	return size;
4138c2ecf20Sopenharmony_ci}
4148c2ecf20Sopenharmony_ci
4158c2ecf20Sopenharmony_cistruct manager_attribute {
4168c2ecf20Sopenharmony_ci	struct attribute attr;
4178c2ecf20Sopenharmony_ci	ssize_t (*show)(struct omap_overlay_manager *, char *);
4188c2ecf20Sopenharmony_ci	ssize_t	(*store)(struct omap_overlay_manager *, const char *, size_t);
4198c2ecf20Sopenharmony_ci};
4208c2ecf20Sopenharmony_ci
4218c2ecf20Sopenharmony_ci#define MANAGER_ATTR(_name, _mode, _show, _store) \
4228c2ecf20Sopenharmony_ci	struct manager_attribute manager_attr_##_name = \
4238c2ecf20Sopenharmony_ci	__ATTR(_name, _mode, _show, _store)
4248c2ecf20Sopenharmony_ci
4258c2ecf20Sopenharmony_cistatic MANAGER_ATTR(name, S_IRUGO, manager_name_show, NULL);
4268c2ecf20Sopenharmony_cistatic MANAGER_ATTR(display, S_IRUGO|S_IWUSR,
4278c2ecf20Sopenharmony_ci		manager_display_show, manager_display_store);
4288c2ecf20Sopenharmony_cistatic MANAGER_ATTR(default_color, S_IRUGO|S_IWUSR,
4298c2ecf20Sopenharmony_ci		manager_default_color_show, manager_default_color_store);
4308c2ecf20Sopenharmony_cistatic MANAGER_ATTR(trans_key_type, S_IRUGO|S_IWUSR,
4318c2ecf20Sopenharmony_ci		manager_trans_key_type_show, manager_trans_key_type_store);
4328c2ecf20Sopenharmony_cistatic MANAGER_ATTR(trans_key_value, S_IRUGO|S_IWUSR,
4338c2ecf20Sopenharmony_ci		manager_trans_key_value_show, manager_trans_key_value_store);
4348c2ecf20Sopenharmony_cistatic MANAGER_ATTR(trans_key_enabled, S_IRUGO|S_IWUSR,
4358c2ecf20Sopenharmony_ci		manager_trans_key_enabled_show,
4368c2ecf20Sopenharmony_ci		manager_trans_key_enabled_store);
4378c2ecf20Sopenharmony_cistatic MANAGER_ATTR(alpha_blending_enabled, S_IRUGO|S_IWUSR,
4388c2ecf20Sopenharmony_ci		manager_alpha_blending_enabled_show,
4398c2ecf20Sopenharmony_ci		manager_alpha_blending_enabled_store);
4408c2ecf20Sopenharmony_cistatic MANAGER_ATTR(cpr_enable, S_IRUGO|S_IWUSR,
4418c2ecf20Sopenharmony_ci		manager_cpr_enable_show,
4428c2ecf20Sopenharmony_ci		manager_cpr_enable_store);
4438c2ecf20Sopenharmony_cistatic MANAGER_ATTR(cpr_coef, S_IRUGO|S_IWUSR,
4448c2ecf20Sopenharmony_ci		manager_cpr_coef_show,
4458c2ecf20Sopenharmony_ci		manager_cpr_coef_store);
4468c2ecf20Sopenharmony_ci
4478c2ecf20Sopenharmony_ci
4488c2ecf20Sopenharmony_cistatic struct attribute *manager_sysfs_attrs[] = {
4498c2ecf20Sopenharmony_ci	&manager_attr_name.attr,
4508c2ecf20Sopenharmony_ci	&manager_attr_display.attr,
4518c2ecf20Sopenharmony_ci	&manager_attr_default_color.attr,
4528c2ecf20Sopenharmony_ci	&manager_attr_trans_key_type.attr,
4538c2ecf20Sopenharmony_ci	&manager_attr_trans_key_value.attr,
4548c2ecf20Sopenharmony_ci	&manager_attr_trans_key_enabled.attr,
4558c2ecf20Sopenharmony_ci	&manager_attr_alpha_blending_enabled.attr,
4568c2ecf20Sopenharmony_ci	&manager_attr_cpr_enable.attr,
4578c2ecf20Sopenharmony_ci	&manager_attr_cpr_coef.attr,
4588c2ecf20Sopenharmony_ci	NULL
4598c2ecf20Sopenharmony_ci};
4608c2ecf20Sopenharmony_ci
4618c2ecf20Sopenharmony_cistatic ssize_t manager_attr_show(struct kobject *kobj, struct attribute *attr,
4628c2ecf20Sopenharmony_ci		char *buf)
4638c2ecf20Sopenharmony_ci{
4648c2ecf20Sopenharmony_ci	struct omap_overlay_manager *manager;
4658c2ecf20Sopenharmony_ci	struct manager_attribute *manager_attr;
4668c2ecf20Sopenharmony_ci
4678c2ecf20Sopenharmony_ci	manager = container_of(kobj, struct omap_overlay_manager, kobj);
4688c2ecf20Sopenharmony_ci	manager_attr = container_of(attr, struct manager_attribute, attr);
4698c2ecf20Sopenharmony_ci
4708c2ecf20Sopenharmony_ci	if (!manager_attr->show)
4718c2ecf20Sopenharmony_ci		return -ENOENT;
4728c2ecf20Sopenharmony_ci
4738c2ecf20Sopenharmony_ci	return manager_attr->show(manager, buf);
4748c2ecf20Sopenharmony_ci}
4758c2ecf20Sopenharmony_ci
4768c2ecf20Sopenharmony_cistatic ssize_t manager_attr_store(struct kobject *kobj, struct attribute *attr,
4778c2ecf20Sopenharmony_ci		const char *buf, size_t size)
4788c2ecf20Sopenharmony_ci{
4798c2ecf20Sopenharmony_ci	struct omap_overlay_manager *manager;
4808c2ecf20Sopenharmony_ci	struct manager_attribute *manager_attr;
4818c2ecf20Sopenharmony_ci
4828c2ecf20Sopenharmony_ci	manager = container_of(kobj, struct omap_overlay_manager, kobj);
4838c2ecf20Sopenharmony_ci	manager_attr = container_of(attr, struct manager_attribute, attr);
4848c2ecf20Sopenharmony_ci
4858c2ecf20Sopenharmony_ci	if (!manager_attr->store)
4868c2ecf20Sopenharmony_ci		return -ENOENT;
4878c2ecf20Sopenharmony_ci
4888c2ecf20Sopenharmony_ci	return manager_attr->store(manager, buf, size);
4898c2ecf20Sopenharmony_ci}
4908c2ecf20Sopenharmony_ci
4918c2ecf20Sopenharmony_cistatic const struct sysfs_ops manager_sysfs_ops = {
4928c2ecf20Sopenharmony_ci	.show = manager_attr_show,
4938c2ecf20Sopenharmony_ci	.store = manager_attr_store,
4948c2ecf20Sopenharmony_ci};
4958c2ecf20Sopenharmony_ci
4968c2ecf20Sopenharmony_cistatic struct kobj_type manager_ktype = {
4978c2ecf20Sopenharmony_ci	.sysfs_ops = &manager_sysfs_ops,
4988c2ecf20Sopenharmony_ci	.default_attrs = manager_sysfs_attrs,
4998c2ecf20Sopenharmony_ci};
5008c2ecf20Sopenharmony_ci
5018c2ecf20Sopenharmony_ciint dss_manager_kobj_init(struct omap_overlay_manager *mgr,
5028c2ecf20Sopenharmony_ci		struct platform_device *pdev)
5038c2ecf20Sopenharmony_ci{
5048c2ecf20Sopenharmony_ci	return kobject_init_and_add(&mgr->kobj, &manager_ktype,
5058c2ecf20Sopenharmony_ci			&pdev->dev.kobj, "manager%d", mgr->id);
5068c2ecf20Sopenharmony_ci}
5078c2ecf20Sopenharmony_ci
5088c2ecf20Sopenharmony_civoid dss_manager_kobj_uninit(struct omap_overlay_manager *mgr)
5098c2ecf20Sopenharmony_ci{
5108c2ecf20Sopenharmony_ci	kobject_del(&mgr->kobj);
5118c2ecf20Sopenharmony_ci	kobject_put(&mgr->kobj);
5128c2ecf20Sopenharmony_ci
5138c2ecf20Sopenharmony_ci	memset(&mgr->kobj, 0, sizeof(mgr->kobj));
5148c2ecf20Sopenharmony_ci}
515