linux/drivers/video/fbdev/omap2/omapfb/dss/dss-of.c
<<
>>
Prefs
   1// SPDX-License-Identifier: GPL-2.0-only
   2/*
   3 * Copyright (C) 2013 Texas Instruments
   4 * Author: Tomi Valkeinen <tomi.valkeinen@ti.com>
   5 */
   6
   7#include <linux/device.h>
   8#include <linux/err.h>
   9#include <linux/module.h>
  10#include <linux/of.h>
  11#include <linux/of_graph.h>
  12#include <linux/seq_file.h>
  13
  14#include <video/omapfb_dss.h>
  15
  16#include "dss.h"
  17
  18struct device_node *
  19omapdss_of_get_next_port(const struct device_node *parent,
  20                         struct device_node *prev)
  21{
  22        struct device_node *port = NULL;
  23
  24        if (!parent)
  25                return NULL;
  26
  27        if (!prev) {
  28                struct device_node *ports;
  29                /*
  30                 * It's the first call, we have to find a port subnode
  31                 * within this node or within an optional 'ports' node.
  32                 */
  33                ports = of_get_child_by_name(parent, "ports");
  34                if (ports)
  35                        parent = ports;
  36
  37                port = of_get_child_by_name(parent, "port");
  38
  39                /* release the 'ports' node */
  40                of_node_put(ports);
  41        } else {
  42                struct device_node *ports;
  43
  44                ports = of_get_parent(prev);
  45                if (!ports)
  46                        return NULL;
  47
  48                do {
  49                        port = of_get_next_child(ports, prev);
  50                        if (!port) {
  51                                of_node_put(ports);
  52                                return NULL;
  53                        }
  54                        prev = port;
  55                } while (!of_node_name_eq(port, "port"));
  56
  57                of_node_put(ports);
  58        }
  59
  60        return port;
  61}
  62EXPORT_SYMBOL_GPL(omapdss_of_get_next_port);
  63
  64struct device_node *
  65omapdss_of_get_next_endpoint(const struct device_node *parent,
  66                             struct device_node *prev)
  67{
  68        struct device_node *ep = NULL;
  69
  70        if (!parent)
  71                return NULL;
  72
  73        do {
  74                ep = of_get_next_child(parent, prev);
  75                if (!ep)
  76                        return NULL;
  77                prev = ep;
  78        } while (!of_node_name_eq(ep, "endpoint"));
  79
  80        return ep;
  81}
  82EXPORT_SYMBOL_GPL(omapdss_of_get_next_endpoint);
  83
  84struct device_node *dss_of_port_get_parent_device(struct device_node *port)
  85{
  86        struct device_node *np;
  87        int i;
  88
  89        if (!port)
  90                return NULL;
  91
  92        np = of_get_parent(port);
  93
  94        for (i = 0; i < 2 && np; ++i) {
  95                struct property *prop;
  96
  97                prop = of_find_property(np, "compatible", NULL);
  98
  99                if (prop)
 100                        return np;
 101
 102                np = of_get_next_parent(np);
 103        }
 104
 105        return NULL;
 106}
 107
 108u32 dss_of_port_get_port_number(struct device_node *port)
 109{
 110        int r;
 111        u32 reg;
 112
 113        r = of_property_read_u32(port, "reg", &reg);
 114        if (r)
 115                reg = 0;
 116
 117        return reg;
 118}
 119
 120static struct device_node *omapdss_of_get_remote_port(const struct device_node *node)
 121{
 122        struct device_node *np;
 123
 124        np = of_graph_get_remote_endpoint(node);
 125        if (!np)
 126                return NULL;
 127
 128        np = of_get_next_parent(np);
 129
 130        return np;
 131}
 132
 133struct device_node *
 134omapdss_of_get_first_endpoint(const struct device_node *parent)
 135{
 136        struct device_node *port, *ep;
 137
 138        port = omapdss_of_get_next_port(parent, NULL);
 139
 140        if (!port)
 141                return NULL;
 142
 143        ep = omapdss_of_get_next_endpoint(port, NULL);
 144
 145        of_node_put(port);
 146
 147        return ep;
 148}
 149EXPORT_SYMBOL_GPL(omapdss_of_get_first_endpoint);
 150
 151struct omap_dss_device *
 152omapdss_of_find_source_for_first_ep(struct device_node *node)
 153{
 154        struct device_node *ep;
 155        struct device_node *src_port;
 156        struct omap_dss_device *src;
 157
 158        ep = omapdss_of_get_first_endpoint(node);
 159        if (!ep)
 160                return ERR_PTR(-EINVAL);
 161
 162        src_port = omapdss_of_get_remote_port(ep);
 163        if (!src_port) {
 164                of_node_put(ep);
 165                return ERR_PTR(-EINVAL);
 166        }
 167
 168        of_node_put(ep);
 169
 170        src = omap_dss_find_output_by_port_node(src_port);
 171
 172        of_node_put(src_port);
 173
 174        return src ? src : ERR_PTR(-EPROBE_DEFER);
 175}
 176EXPORT_SYMBOL_GPL(omapdss_of_find_source_for_first_ep);
 177