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