LCOV - code coverage report
Current view: top level - drivers/video - of_display_timing.c (source / functions) Hit Total Coverage
Test: gcov_data_raspi2_qemu_modules_combined.info Lines: 0 104 0.0 %
Date: 2020-09-30 20:25:01 Functions: 0 4 0.0 %
Branches: 0 64 0.0 %

           Branch data     Line data    Source code
       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                 :          0 : 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                 :          0 :         prop = of_find_property(np, name, &length);
      32         [ #  # ]:          0 :         if (!prop) {
      33                 :          0 :                 pr_err("%pOF: could not find property %s\n", np, name);
      34                 :          0 :                 return -EINVAL;
      35                 :            :         }
      36                 :            : 
      37                 :          0 :         cells = length / sizeof(u32);
      38         [ #  # ]:          0 :         if (cells == 1) {
      39                 :          0 :                 ret = of_property_read_u32(np, name, &result->typ);
      40                 :          0 :                 result->min = result->typ;
      41                 :          0 :                 result->max = result->typ;
      42         [ #  # ]:          0 :         } else if (cells == 3) {
      43                 :          0 :                 ret = of_property_read_u32_array(np, name, &result->min, cells);
      44                 :            :         } else {
      45                 :          0 :                 pr_err("%pOF: illegal timing specification in %s\n", np, name);
      46                 :          0 :                 return -EINVAL;
      47                 :            :         }
      48                 :            : 
      49                 :          0 :         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                 :          0 : static int of_parse_display_timing(const struct device_node *np,
      57                 :            :                 struct display_timing *dt)
      58                 :            : {
      59                 :          0 :         u32 val = 0;
      60                 :            :         int ret = 0;
      61                 :            : 
      62                 :          0 :         memset(dt, 0, sizeof(*dt));
      63                 :            : 
      64                 :          0 :         ret |= parse_timing_property(np, "hback-porch", &dt->hback_porch);
      65                 :          0 :         ret |= parse_timing_property(np, "hfront-porch", &dt->hfront_porch);
      66                 :          0 :         ret |= parse_timing_property(np, "hactive", &dt->hactive);
      67                 :          0 :         ret |= parse_timing_property(np, "hsync-len", &dt->hsync_len);
      68                 :          0 :         ret |= parse_timing_property(np, "vback-porch", &dt->vback_porch);
      69                 :          0 :         ret |= parse_timing_property(np, "vfront-porch", &dt->vfront_porch);
      70                 :          0 :         ret |= parse_timing_property(np, "vactive", &dt->vactive);
      71                 :          0 :         ret |= parse_timing_property(np, "vsync-len", &dt->vsync_len);
      72                 :          0 :         ret |= parse_timing_property(np, "clock-frequency", &dt->pixelclock);
      73                 :            : 
      74                 :          0 :         dt->flags = 0;
      75         [ #  # ]:          0 :         if (!of_property_read_u32(np, "vsync-active", &val))
      76         [ #  # ]:          0 :                 dt->flags |= val ? DISPLAY_FLAGS_VSYNC_HIGH :
      77                 :            :                                 DISPLAY_FLAGS_VSYNC_LOW;
      78         [ #  # ]:          0 :         if (!of_property_read_u32(np, "hsync-active", &val))
      79         [ #  # ]:          0 :                 dt->flags |= val ? DISPLAY_FLAGS_HSYNC_HIGH :
      80                 :            :                                 DISPLAY_FLAGS_HSYNC_LOW;
      81         [ #  # ]:          0 :         if (!of_property_read_u32(np, "de-active", &val))
      82         [ #  # ]:          0 :                 dt->flags |= val ? DISPLAY_FLAGS_DE_HIGH :
      83                 :            :                                 DISPLAY_FLAGS_DE_LOW;
      84         [ #  # ]:          0 :         if (!of_property_read_u32(np, "pixelclk-active", &val))
      85         [ #  # ]:          0 :                 dt->flags |= val ? DISPLAY_FLAGS_PIXDATA_POSEDGE :
      86                 :            :                                 DISPLAY_FLAGS_PIXDATA_NEGEDGE;
      87                 :            : 
      88         [ #  # ]:          0 :         if (!of_property_read_u32(np, "syncclk-active", &val))
      89         [ #  # ]:          0 :                 dt->flags |= val ? DISPLAY_FLAGS_SYNC_POSEDGE :
      90                 :            :                                 DISPLAY_FLAGS_SYNC_NEGEDGE;
      91         [ #  # ]:          0 :         else if (dt->flags & (DISPLAY_FLAGS_PIXDATA_POSEDGE |
      92                 :            :                               DISPLAY_FLAGS_PIXDATA_NEGEDGE))
      93         [ #  # ]:          0 :                 dt->flags |= dt->flags & DISPLAY_FLAGS_PIXDATA_POSEDGE ?
      94                 :            :                                 DISPLAY_FLAGS_SYNC_POSEDGE :
      95                 :            :                                 DISPLAY_FLAGS_SYNC_NEGEDGE;
      96                 :            : 
      97         [ #  # ]:          0 :         if (of_property_read_bool(np, "interlaced"))
      98                 :          0 :                 dt->flags |= DISPLAY_FLAGS_INTERLACED;
      99         [ #  # ]:          0 :         if (of_property_read_bool(np, "doublescan"))
     100                 :          0 :                 dt->flags |= DISPLAY_FLAGS_DOUBLESCAN;
     101         [ #  # ]:          0 :         if (of_property_read_bool(np, "doubleclk"))
     102                 :          0 :                 dt->flags |= DISPLAY_FLAGS_DOUBLECLK;
     103                 :            : 
     104         [ #  # ]:          0 :         if (ret) {
     105                 :          0 :                 pr_err("%pOF: error reading timing properties\n", np);
     106                 :          0 :                 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                 :          0 : 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         [ #  # ]:          0 :         if (!np)
     125                 :            :                 return -EINVAL;
     126                 :            : 
     127                 :          0 :         timing_np = of_get_child_by_name(np, name);
     128         [ #  # ]:          0 :         if (!timing_np)
     129                 :            :                 return -ENOENT;
     130                 :            : 
     131                 :          0 :         ret = of_parse_display_timing(timing_np, dt);
     132                 :            : 
     133                 :          0 :         of_node_put(timing_np);
     134                 :            : 
     135                 :          0 :         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                 :          0 : 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         [ #  # ]:          0 :         if (!np)
     151                 :            :                 return NULL;
     152                 :            : 
     153                 :          0 :         timings_np = of_get_child_by_name(np, "display-timings");
     154         [ #  # ]:          0 :         if (!timings_np) {
     155                 :          0 :                 pr_err("%pOF: could not find display-timings node\n", np);
     156                 :          0 :                 return NULL;
     157                 :            :         }
     158                 :            : 
     159                 :          0 :         disp = kzalloc(sizeof(*disp), GFP_KERNEL);
     160         [ #  # ]:          0 :         if (!disp) {
     161                 :          0 :                 pr_err("%pOF: could not allocate struct disp'\n", np);
     162                 :          0 :                 goto dispfail;
     163                 :            :         }
     164                 :            : 
     165                 :          0 :         entry = of_parse_phandle(timings_np, "native-mode", 0);
     166                 :            :         /* assume first child as native mode if none provided */
     167         [ #  # ]:          0 :         if (!entry)
     168                 :          0 :                 entry = of_get_next_child(timings_np, NULL);
     169                 :            :         /* if there is no child, it is useless to go on */
     170         [ #  # ]:          0 :         if (!entry) {
     171                 :          0 :                 pr_err("%pOF: no timing specifications given\n", np);
     172                 :          0 :                 goto entryfail;
     173                 :            :         }
     174                 :            : 
     175                 :            :         pr_debug("%pOF: using %pOFn as default timing\n", np, entry);
     176                 :            : 
     177                 :            :         native_mode = entry;
     178                 :            : 
     179                 :          0 :         disp->num_timings = of_get_child_count(timings_np);
     180         [ #  # ]:          0 :         if (disp->num_timings == 0) {
     181                 :            :                 /* should never happen, as entry was already found above */
     182                 :          0 :                 pr_err("%pOF: no timings specified\n", np);
     183                 :          0 :                 goto entryfail;
     184                 :            :         }
     185                 :            : 
     186                 :          0 :         disp->timings = kcalloc(disp->num_timings,
     187                 :            :                                 sizeof(struct display_timing *),
     188                 :            :                                 GFP_KERNEL);
     189         [ #  # ]:          0 :         if (!disp->timings) {
     190                 :          0 :                 pr_err("%pOF: could not allocate timings array\n", np);
     191                 :          0 :                 goto entryfail;
     192                 :            :         }
     193                 :            : 
     194                 :          0 :         disp->num_timings = 0;
     195                 :          0 :         disp->native_mode = 0;
     196                 :            : 
     197         [ #  # ]:          0 :         for_each_child_of_node(timings_np, entry) {
     198                 :            :                 struct display_timing *dt;
     199                 :            :                 int r;
     200                 :            : 
     201                 :          0 :                 dt = kzalloc(sizeof(*dt), GFP_KERNEL);
     202         [ #  # ]:          0 :                 if (!dt) {
     203                 :          0 :                         pr_err("%pOF: could not allocate display_timing struct\n",
     204                 :            :                                 np);
     205                 :          0 :                         goto timingfail;
     206                 :            :                 }
     207                 :            : 
     208                 :          0 :                 r = of_parse_display_timing(entry, dt);
     209         [ #  # ]:          0 :                 if (r) {
     210                 :            :                         /*
     211                 :            :                          * to not encourage wrong devicetrees, fail in case of
     212                 :            :                          * an error
     213                 :            :                          */
     214                 :          0 :                         pr_err("%pOF: error in timing %d\n",
     215                 :            :                                 np, disp->num_timings + 1);
     216                 :          0 :                         kfree(dt);
     217                 :          0 :                         goto timingfail;
     218                 :            :                 }
     219                 :            : 
     220         [ #  # ]:          0 :                 if (native_mode == entry)
     221                 :          0 :                         disp->native_mode = disp->num_timings;
     222                 :            : 
     223                 :          0 :                 disp->timings[disp->num_timings] = dt;
     224                 :          0 :                 disp->num_timings++;
     225                 :            :         }
     226                 :          0 :         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                 :          0 :         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                 :          0 :         return disp;
     238                 :            : 
     239                 :            : timingfail:
     240                 :          0 :         of_node_put(native_mode);
     241                 :          0 :         display_timings_release(disp);
     242                 :            :         disp = NULL;
     243                 :            : entryfail:
     244                 :          0 :         kfree(disp);
     245                 :            : dispfail:
     246                 :          0 :         of_node_put(timings_np);
     247                 :          0 :         return NULL;
     248                 :            : }
     249                 :            : EXPORT_SYMBOL_GPL(of_get_display_timings);

Generated by: LCOV version 1.14