186 lines · c
1// SPDX-License-Identifier: GPL-2.0+2/*3 * Copyright (C) 2019-2022 Bootlin4 * 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}186