Linux Audio

Check our new training course

Loading...
Note: File does not exist in v3.1.
  1// SPDX-License-Identifier: GPL-2.0+
  2/*
  3 * Copyright (C) 2019-2022 Bootlin
  4 * Author: Paul Kocialkowski <paul.kocialkowski@bootlin.com>
  5 */
  6
  7#include <drm/drm_print.h>
  8
  9#include "logicvc_drm.h"
 10#include "logicvc_layer.h"
 11#include "logicvc_of.h"
 12
 13static struct logicvc_of_property_sv logicvc_of_display_interface_sv[] = {
 14	{ "lvds-4bits",	LOGICVC_DISPLAY_INTERFACE_LVDS_4BITS },
 15	{ "lvds-3bits",	LOGICVC_DISPLAY_INTERFACE_LVDS_3BITS },
 16	{ },
 17};
 18
 19static struct logicvc_of_property_sv logicvc_of_display_colorspace_sv[] = {
 20	{ "rgb",	LOGICVC_DISPLAY_COLORSPACE_RGB },
 21	{ "yuv422",	LOGICVC_DISPLAY_COLORSPACE_YUV422 },
 22	{ "yuv444",	LOGICVC_DISPLAY_COLORSPACE_YUV444 },
 23	{ },
 24};
 25
 26static struct logicvc_of_property_sv logicvc_of_layer_colorspace_sv[] = {
 27	{ "rgb",	LOGICVC_LAYER_COLORSPACE_RGB },
 28	{ "yuv",	LOGICVC_LAYER_COLORSPACE_YUV },
 29	{ },
 30};
 31
 32static struct logicvc_of_property_sv logicvc_of_layer_alpha_mode_sv[] = {
 33	{ "layer",	LOGICVC_LAYER_ALPHA_LAYER },
 34	{ "pixel",	LOGICVC_LAYER_ALPHA_PIXEL },
 35	{ },
 36};
 37
 38static struct logicvc_of_property logicvc_of_properties[] = {
 39	[LOGICVC_OF_PROPERTY_DISPLAY_INTERFACE] = {
 40		.name		= "xylon,display-interface",
 41		.sv		= logicvc_of_display_interface_sv,
 42		.range		= {
 43			LOGICVC_DISPLAY_INTERFACE_LVDS_4BITS,
 44			LOGICVC_DISPLAY_INTERFACE_LVDS_3BITS,
 45		},
 46	},
 47	[LOGICVC_OF_PROPERTY_DISPLAY_COLORSPACE] = {
 48		.name		= "xylon,display-colorspace",
 49		.sv		= logicvc_of_display_colorspace_sv,
 50		.range		= {
 51			LOGICVC_DISPLAY_COLORSPACE_RGB,
 52			LOGICVC_DISPLAY_COLORSPACE_YUV444,
 53		},
 54	},
 55	[LOGICVC_OF_PROPERTY_DISPLAY_DEPTH] = {
 56		.name		= "xylon,display-depth",
 57		.range		= { 8, 24 },
 58	},
 59	[LOGICVC_OF_PROPERTY_ROW_STRIDE] = {
 60		.name		= "xylon,row-stride",
 61	},
 62	[LOGICVC_OF_PROPERTY_DITHERING] = {
 63		.name		= "xylon,dithering",
 64		.optional	= true,
 65	},
 66	[LOGICVC_OF_PROPERTY_BACKGROUND_LAYER] = {
 67		.name		= "xylon,background-layer",
 68		.optional	= true,
 69	},
 70	[LOGICVC_OF_PROPERTY_LAYERS_CONFIGURABLE] = {
 71		.name		= "xylon,layers-configurable",
 72		.optional	= true,
 73	},
 74	[LOGICVC_OF_PROPERTY_LAYERS_COUNT] = {
 75		.name		= "xylon,layers-count",
 76	},
 77	[LOGICVC_OF_PROPERTY_LAYER_DEPTH] = {
 78		.name		= "xylon,layer-depth",
 79		.range		= { 8, 24 },
 80	},
 81	[LOGICVC_OF_PROPERTY_LAYER_COLORSPACE] = {
 82		.name		= "xylon,layer-colorspace",
 83		.sv		= logicvc_of_layer_colorspace_sv,
 84		.range		= {
 85			LOGICVC_LAYER_COLORSPACE_RGB,
 86			LOGICVC_LAYER_COLORSPACE_RGB,
 87		},
 88	},
 89	[LOGICVC_OF_PROPERTY_LAYER_ALPHA_MODE] = {
 90		.name		= "xylon,layer-alpha-mode",
 91		.sv		= logicvc_of_layer_alpha_mode_sv,
 92		.range		= {
 93			LOGICVC_LAYER_ALPHA_LAYER,
 94			LOGICVC_LAYER_ALPHA_PIXEL,
 95		},
 96	},
 97	[LOGICVC_OF_PROPERTY_LAYER_BASE_OFFSET] = {
 98		.name		= "xylon,layer-base-offset",
 99	},
100	[LOGICVC_OF_PROPERTY_LAYER_BUFFER_OFFSET] = {
101		.name		= "xylon,layer-buffer-offset",
102	},
103	[LOGICVC_OF_PROPERTY_LAYER_PRIMARY] = {
104		.name		= "xylon,layer-primary",
105		.optional	= true,
106	},
107};
108
109static int logicvc_of_property_sv_value(struct logicvc_of_property_sv *sv,
110					const char *string, u32 *value)
111{
112	unsigned int i = 0;
113
114	while (sv[i].string) {
115		if (!strcmp(sv[i].string, string)) {
116			*value = sv[i].value;
117			return 0;
118		}
119
120		i++;
121	}
122
123	return -EINVAL;
124}
125
126int logicvc_of_property_parse_u32(struct device_node *of_node,
127				  unsigned int index, u32 *target)
128{
129	struct logicvc_of_property *property;
130	const char *string;
131	u32 value;
132	int ret;
133
134	if (index >= LOGICVC_OF_PROPERTY_MAXIMUM)
135		return -EINVAL;
136
137	property = &logicvc_of_properties[index];
138
139	if (!property->optional &&
140	    !of_property_read_bool(of_node, property->name))
141		return -ENODEV;
142
143	if (property->sv) {
144		ret = of_property_read_string(of_node, property->name, &string);
145		if (ret)
146			return ret;
147
148		ret = logicvc_of_property_sv_value(property->sv, string,
149						   &value);
150		if (ret)
151			return ret;
152	} else {
153		ret = of_property_read_u32(of_node, property->name, &value);
154		if (ret)
155			return ret;
156	}
157
158	if (property->range[0] || property->range[1])
159		if (value < property->range[0] || value > property->range[1])
160			return -ERANGE;
161
162	*target = value;
163
164	return 0;
165}
166
167void logicvc_of_property_parse_bool(struct device_node *of_node,
168				    unsigned int index, bool *target)
169{
170	struct logicvc_of_property *property;
171
172	if (index >= LOGICVC_OF_PROPERTY_MAXIMUM) {
173		/* Fallback. */
174		*target = false;
175		return;
176	}
177
178	property = &logicvc_of_properties[index];
179	*target = of_property_read_bool(of_node, property->name);
180}
181
182bool logicvc_of_node_is_layer(struct device_node *of_node)
183{
184	return !of_node_cmp(of_node->name, "layer");
185}