Back to home page

OSCL-LXR

 
 

    


0001 // SPDX-License-Identifier: GPL-2.0+
0002 /*
0003  * Copyright (C) 2019-2022 Bootlin
0004  * Author: Paul Kocialkowski <paul.kocialkowski@bootlin.com>
0005  */
0006 
0007 #include <drm/drm_print.h>
0008 
0009 #include "logicvc_drm.h"
0010 #include "logicvc_layer.h"
0011 #include "logicvc_of.h"
0012 
0013 static struct logicvc_of_property_sv logicvc_of_display_interface_sv[] = {
0014     { "lvds-4bits", LOGICVC_DISPLAY_INTERFACE_LVDS_4BITS },
0015     { "lvds-3bits", LOGICVC_DISPLAY_INTERFACE_LVDS_3BITS },
0016     { },
0017 };
0018 
0019 static struct logicvc_of_property_sv logicvc_of_display_colorspace_sv[] = {
0020     { "rgb",    LOGICVC_DISPLAY_COLORSPACE_RGB },
0021     { "yuv422", LOGICVC_DISPLAY_COLORSPACE_YUV422 },
0022     { "yuv444", LOGICVC_DISPLAY_COLORSPACE_YUV444 },
0023     { },
0024 };
0025 
0026 static struct logicvc_of_property_sv logicvc_of_layer_colorspace_sv[] = {
0027     { "rgb",    LOGICVC_LAYER_COLORSPACE_RGB },
0028     { "yuv",    LOGICVC_LAYER_COLORSPACE_YUV },
0029     { },
0030 };
0031 
0032 static struct logicvc_of_property_sv logicvc_of_layer_alpha_mode_sv[] = {
0033     { "layer",  LOGICVC_LAYER_ALPHA_LAYER },
0034     { "pixel",  LOGICVC_LAYER_ALPHA_PIXEL },
0035     { },
0036 };
0037 
0038 static struct logicvc_of_property logicvc_of_properties[] = {
0039     [LOGICVC_OF_PROPERTY_DISPLAY_INTERFACE] = {
0040         .name       = "xylon,display-interface",
0041         .sv     = logicvc_of_display_interface_sv,
0042         .range      = {
0043             LOGICVC_DISPLAY_INTERFACE_LVDS_4BITS,
0044             LOGICVC_DISPLAY_INTERFACE_LVDS_3BITS,
0045         },
0046     },
0047     [LOGICVC_OF_PROPERTY_DISPLAY_COLORSPACE] = {
0048         .name       = "xylon,display-colorspace",
0049         .sv     = logicvc_of_display_colorspace_sv,
0050         .range      = {
0051             LOGICVC_DISPLAY_COLORSPACE_RGB,
0052             LOGICVC_DISPLAY_COLORSPACE_YUV444,
0053         },
0054     },
0055     [LOGICVC_OF_PROPERTY_DISPLAY_DEPTH] = {
0056         .name       = "xylon,display-depth",
0057         .range      = { 8, 24 },
0058     },
0059     [LOGICVC_OF_PROPERTY_ROW_STRIDE] = {
0060         .name       = "xylon,row-stride",
0061     },
0062     [LOGICVC_OF_PROPERTY_DITHERING] = {
0063         .name       = "xylon,dithering",
0064         .optional   = true,
0065     },
0066     [LOGICVC_OF_PROPERTY_BACKGROUND_LAYER] = {
0067         .name       = "xylon,background-layer",
0068         .optional   = true,
0069     },
0070     [LOGICVC_OF_PROPERTY_LAYERS_CONFIGURABLE] = {
0071         .name       = "xylon,layers-configurable",
0072         .optional   = true,
0073     },
0074     [LOGICVC_OF_PROPERTY_LAYERS_COUNT] = {
0075         .name       = "xylon,layers-count",
0076     },
0077     [LOGICVC_OF_PROPERTY_LAYER_DEPTH] = {
0078         .name       = "xylon,layer-depth",
0079         .range      = { 8, 24 },
0080     },
0081     [LOGICVC_OF_PROPERTY_LAYER_COLORSPACE] = {
0082         .name       = "xylon,layer-colorspace",
0083         .sv     = logicvc_of_layer_colorspace_sv,
0084         .range      = {
0085             LOGICVC_LAYER_COLORSPACE_RGB,
0086             LOGICVC_LAYER_COLORSPACE_RGB,
0087         },
0088     },
0089     [LOGICVC_OF_PROPERTY_LAYER_ALPHA_MODE] = {
0090         .name       = "xylon,layer-alpha-mode",
0091         .sv     = logicvc_of_layer_alpha_mode_sv,
0092         .range      = {
0093             LOGICVC_LAYER_ALPHA_LAYER,
0094             LOGICVC_LAYER_ALPHA_PIXEL,
0095         },
0096     },
0097     [LOGICVC_OF_PROPERTY_LAYER_BASE_OFFSET] = {
0098         .name       = "xylon,layer-base-offset",
0099     },
0100     [LOGICVC_OF_PROPERTY_LAYER_BUFFER_OFFSET] = {
0101         .name       = "xylon,layer-buffer-offset",
0102     },
0103     [LOGICVC_OF_PROPERTY_LAYER_PRIMARY] = {
0104         .name       = "xylon,layer-primary",
0105         .optional   = true,
0106     },
0107 };
0108 
0109 static int logicvc_of_property_sv_value(struct logicvc_of_property_sv *sv,
0110                     const char *string, u32 *value)
0111 {
0112     unsigned int i = 0;
0113 
0114     while (sv[i].string) {
0115         if (!strcmp(sv[i].string, string)) {
0116             *value = sv[i].value;
0117             return 0;
0118         }
0119 
0120         i++;
0121     }
0122 
0123     return -EINVAL;
0124 }
0125 
0126 int logicvc_of_property_parse_u32(struct device_node *of_node,
0127                   unsigned int index, u32 *target)
0128 {
0129     struct logicvc_of_property *property;
0130     const char *string;
0131     u32 value;
0132     int ret;
0133 
0134     if (index >= LOGICVC_OF_PROPERTY_MAXIMUM)
0135         return -EINVAL;
0136 
0137     property = &logicvc_of_properties[index];
0138 
0139     if (!property->optional &&
0140         !of_property_read_bool(of_node, property->name))
0141         return -ENODEV;
0142 
0143     if (property->sv) {
0144         ret = of_property_read_string(of_node, property->name, &string);
0145         if (ret)
0146             return ret;
0147 
0148         ret = logicvc_of_property_sv_value(property->sv, string,
0149                            &value);
0150         if (ret)
0151             return ret;
0152     } else {
0153         ret = of_property_read_u32(of_node, property->name, &value);
0154         if (ret)
0155             return ret;
0156     }
0157 
0158     if (property->range[0] || property->range[1])
0159         if (value < property->range[0] || value > property->range[1])
0160             return -ERANGE;
0161 
0162     *target = value;
0163 
0164     return 0;
0165 }
0166 
0167 void logicvc_of_property_parse_bool(struct device_node *of_node,
0168                     unsigned int index, bool *target)
0169 {
0170     struct logicvc_of_property *property;
0171 
0172     if (index >= LOGICVC_OF_PROPERTY_MAXIMUM) {
0173         /* Fallback. */
0174         *target = false;
0175         return;
0176     }
0177 
0178     property = &logicvc_of_properties[index];
0179     *target = of_property_read_bool(of_node, property->name);
0180 }
0181 
0182 bool logicvc_of_node_is_layer(struct device_node *of_node)
0183 {
0184     return !of_node_cmp(of_node->name, "layer");
0185 }