root/drivers/video/of_display_timing.c

/* [<][>][^][v][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. parse_timing_property
  2. of_parse_display_timing
  3. of_get_display_timing
  4. of_get_display_timings

   1 // SPDX-License-Identifier: GPL-2.0-only
   2 /*
   3  * OF helpers for parsing display timings
   4  *
   5  * Copyright (c) 2012 Steffen Trumtrar <s.trumtrar@pengutronix.de>, Pengutronix
   6  *
   7  * based on of_videomode.c by Sascha Hauer <s.hauer@pengutronix.de>
   8  */
   9 #include <linux/export.h>
  10 #include <linux/of.h>
  11 #include <linux/slab.h>
  12 #include <video/display_timing.h>
  13 #include <video/of_display_timing.h>
  14 
  15 /**
  16  * parse_timing_property - parse timing_entry from device_node
  17  * @np: device_node with the property
  18  * @name: name of the property
  19  * @result: will be set to the return value
  20  *
  21  * DESCRIPTION:
  22  * Every display_timing can be specified with either just the typical value or
  23  * a range consisting of min/typ/max. This function helps handling this
  24  **/
  25 static int parse_timing_property(const struct device_node *np, const char *name,
  26                           struct timing_entry *result)
  27 {
  28         struct property *prop;
  29         int length, cells, ret;
  30 
  31         prop = of_find_property(np, name, &length);
  32         if (!prop) {
  33                 pr_err("%pOF: could not find property %s\n", np, name);
  34                 return -EINVAL;
  35         }
  36 
  37         cells = length / sizeof(u32);
  38         if (cells == 1) {
  39                 ret = of_property_read_u32(np, name, &result->typ);
  40                 result->min = result->typ;
  41                 result->max = result->typ;
  42         } else if (cells == 3) {
  43                 ret = of_property_read_u32_array(np, name, &result->min, cells);
  44         } else {
  45                 pr_err("%pOF: illegal timing specification in %s\n", np, name);
  46                 return -EINVAL;
  47         }
  48 
  49         return ret;
  50 }
  51 
  52 /**
  53  * of_parse_display_timing - parse display_timing entry from device_node
  54  * @np: device_node with the properties
  55  **/
  56 static int of_parse_display_timing(const struct device_node *np,
  57                 struct display_timing *dt)
  58 {
  59         u32 val = 0;
  60         int ret = 0;
  61 
  62         memset(dt, 0, sizeof(*dt));
  63 
  64         ret |= parse_timing_property(np, "hback-porch", &dt->hback_porch);
  65         ret |= parse_timing_property(np, "hfront-porch", &dt->hfront_porch);
  66         ret |= parse_timing_property(np, "hactive", &dt->hactive);
  67         ret |= parse_timing_property(np, "hsync-len", &dt->hsync_len);
  68         ret |= parse_timing_property(np, "vback-porch", &dt->vback_porch);
  69         ret |= parse_timing_property(np, "vfront-porch", &dt->vfront_porch);
  70         ret |= parse_timing_property(np, "vactive", &dt->vactive);
  71         ret |= parse_timing_property(np, "vsync-len", &dt->vsync_len);
  72         ret |= parse_timing_property(np, "clock-frequency", &dt->pixelclock);
  73 
  74         dt->flags = 0;
  75         if (!of_property_read_u32(np, "vsync-active", &val))
  76                 dt->flags |= val ? DISPLAY_FLAGS_VSYNC_HIGH :
  77                                 DISPLAY_FLAGS_VSYNC_LOW;
  78         if (!of_property_read_u32(np, "hsync-active", &val))
  79                 dt->flags |= val ? DISPLAY_FLAGS_HSYNC_HIGH :
  80                                 DISPLAY_FLAGS_HSYNC_LOW;
  81         if (!of_property_read_u32(np, "de-active", &val))
  82                 dt->flags |= val ? DISPLAY_FLAGS_DE_HIGH :
  83                                 DISPLAY_FLAGS_DE_LOW;
  84         if (!of_property_read_u32(np, "pixelclk-active", &val))
  85                 dt->flags |= val ? DISPLAY_FLAGS_PIXDATA_POSEDGE :
  86                                 DISPLAY_FLAGS_PIXDATA_NEGEDGE;
  87 
  88         if (!of_property_read_u32(np, "syncclk-active", &val))
  89                 dt->flags |= val ? DISPLAY_FLAGS_SYNC_POSEDGE :
  90                                 DISPLAY_FLAGS_SYNC_NEGEDGE;
  91         else if (dt->flags & (DISPLAY_FLAGS_PIXDATA_POSEDGE |
  92                               DISPLAY_FLAGS_PIXDATA_NEGEDGE))
  93                 dt->flags |= dt->flags & DISPLAY_FLAGS_PIXDATA_POSEDGE ?
  94                                 DISPLAY_FLAGS_SYNC_POSEDGE :
  95                                 DISPLAY_FLAGS_SYNC_NEGEDGE;
  96 
  97         if (of_property_read_bool(np, "interlaced"))
  98                 dt->flags |= DISPLAY_FLAGS_INTERLACED;
  99         if (of_property_read_bool(np, "doublescan"))
 100                 dt->flags |= DISPLAY_FLAGS_DOUBLESCAN;
 101         if (of_property_read_bool(np, "doubleclk"))
 102                 dt->flags |= DISPLAY_FLAGS_DOUBLECLK;
 103 
 104         if (ret) {
 105                 pr_err("%pOF: error reading timing properties\n", np);
 106                 return -EINVAL;
 107         }
 108 
 109         return 0;
 110 }
 111 
 112 /**
 113  * of_get_display_timing - parse a display_timing entry
 114  * @np: device_node with the timing subnode
 115  * @name: name of the timing node
 116  * @dt: display_timing struct to fill
 117  **/
 118 int of_get_display_timing(const struct device_node *np, const char *name,
 119                 struct display_timing *dt)
 120 {
 121         struct device_node *timing_np;
 122         int ret;
 123 
 124         if (!np)
 125                 return -EINVAL;
 126 
 127         timing_np = of_get_child_by_name(np, name);
 128         if (!timing_np)
 129                 return -ENOENT;
 130 
 131         ret = of_parse_display_timing(timing_np, dt);
 132 
 133         of_node_put(timing_np);
 134 
 135         return ret;
 136 }
 137 EXPORT_SYMBOL_GPL(of_get_display_timing);
 138 
 139 /**
 140  * of_get_display_timings - parse all display_timing entries from a device_node
 141  * @np: device_node with the subnodes
 142  **/
 143 struct display_timings *of_get_display_timings(const struct device_node *np)
 144 {
 145         struct device_node *timings_np;
 146         struct device_node *entry;
 147         struct device_node *native_mode;
 148         struct display_timings *disp;
 149 
 150         if (!np)
 151                 return NULL;
 152 
 153         timings_np = of_get_child_by_name(np, "display-timings");
 154         if (!timings_np) {
 155                 pr_err("%pOF: could not find display-timings node\n", np);
 156                 return NULL;
 157         }
 158 
 159         disp = kzalloc(sizeof(*disp), GFP_KERNEL);
 160         if (!disp) {
 161                 pr_err("%pOF: could not allocate struct disp'\n", np);
 162                 goto dispfail;
 163         }
 164 
 165         entry = of_parse_phandle(timings_np, "native-mode", 0);
 166         /* assume first child as native mode if none provided */
 167         if (!entry)
 168                 entry = of_get_next_child(timings_np, NULL);
 169         /* if there is no child, it is useless to go on */
 170         if (!entry) {
 171                 pr_err("%pOF: no timing specifications given\n", np);
 172                 goto entryfail;
 173         }
 174 
 175         pr_debug("%pOF: using %pOFn as default timing\n", np, entry);
 176 
 177         native_mode = entry;
 178 
 179         disp->num_timings = of_get_child_count(timings_np);
 180         if (disp->num_timings == 0) {
 181                 /* should never happen, as entry was already found above */
 182                 pr_err("%pOF: no timings specified\n", np);
 183                 goto entryfail;
 184         }
 185 
 186         disp->timings = kcalloc(disp->num_timings,
 187                                 sizeof(struct display_timing *),
 188                                 GFP_KERNEL);
 189         if (!disp->timings) {
 190                 pr_err("%pOF: could not allocate timings array\n", np);
 191                 goto entryfail;
 192         }
 193 
 194         disp->num_timings = 0;
 195         disp->native_mode = 0;
 196 
 197         for_each_child_of_node(timings_np, entry) {
 198                 struct display_timing *dt;
 199                 int r;
 200 
 201                 dt = kzalloc(sizeof(*dt), GFP_KERNEL);
 202                 if (!dt) {
 203                         pr_err("%pOF: could not allocate display_timing struct\n",
 204                                 np);
 205                         goto timingfail;
 206                 }
 207 
 208                 r = of_parse_display_timing(entry, dt);
 209                 if (r) {
 210                         /*
 211                          * to not encourage wrong devicetrees, fail in case of
 212                          * an error
 213                          */
 214                         pr_err("%pOF: error in timing %d\n",
 215                                 np, disp->num_timings + 1);
 216                         kfree(dt);
 217                         goto timingfail;
 218                 }
 219 
 220                 if (native_mode == entry)
 221                         disp->native_mode = disp->num_timings;
 222 
 223                 disp->timings[disp->num_timings] = dt;
 224                 disp->num_timings++;
 225         }
 226         of_node_put(timings_np);
 227         /*
 228          * native_mode points to the device_node returned by of_parse_phandle
 229          * therefore call of_node_put on it
 230          */
 231         of_node_put(native_mode);
 232 
 233         pr_debug("%pOF: got %d timings. Using timing #%d as default\n",
 234                 np, disp->num_timings,
 235                 disp->native_mode + 1);
 236 
 237         return disp;
 238 
 239 timingfail:
 240         of_node_put(native_mode);
 241         display_timings_release(disp);
 242         disp = NULL;
 243 entryfail:
 244         kfree(disp);
 245 dispfail:
 246         of_node_put(timings_np);
 247         return NULL;
 248 }
 249 EXPORT_SYMBOL_GPL(of_get_display_timings);

/* [<][>][^][v][top][bottom][index][help] */