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