Commit fd9fdb78 authored by Philipp Zabel's avatar Philipp Zabel

[media] of: move graph helpers from drivers/media/v4l2-core to drivers/of

This patch moves the parsing helpers used to parse connected graphs
in the device tree, like the video interface bindings documented in
Documentation/devicetree/bindings/media/video-interfaces.txt, from
drivers/media/v4l2-core/v4l2-of.c into drivers/of/base.c.

This allows to reuse the same parser code from outside the V4L2
framework, most importantly from display drivers.
The functions v4l2_of_get_next_endpoint, v4l2_of_get_remote_port,
and v4l2_of_get_remote_port_parent are moved. They are renamed to
of_graph_get_next_endpoint, of_graph_get_remote_port, and
of_graph_get_remote_port_parent, respectively.
Since there are not that many current users yet, switch all of
them to the new functions right away.
Signed-off-by: default avatarPhilipp Zabel <p.zabel@pengutronix.de>
Acked-by: default avatarTomi Valkeinen <tomi.valkeinen@ti.com>
Acked-by: default avatarMauro Carvalho Chehab <m.chehab@samsung.com>
Acked-by: default avatarSylwester Nawrocki <s.nawrocki@samsung.com>
parent 0414855f
...@@ -26,12 +26,12 @@ ...@@ -26,12 +26,12 @@
#include <linux/videodev2.h> #include <linux/videodev2.h>
#include <linux/uaccess.h> #include <linux/uaccess.h>
#include <linux/of.h> #include <linux/of.h>
#include <linux/of_graph.h>
#include <media/adv7343.h> #include <media/adv7343.h>
#include <media/v4l2-async.h> #include <media/v4l2-async.h>
#include <media/v4l2-device.h> #include <media/v4l2-device.h>
#include <media/v4l2-ctrls.h> #include <media/v4l2-ctrls.h>
#include <media/v4l2-of.h>
#include "adv7343_regs.h" #include "adv7343_regs.h"
...@@ -410,7 +410,7 @@ adv7343_get_pdata(struct i2c_client *client) ...@@ -410,7 +410,7 @@ adv7343_get_pdata(struct i2c_client *client)
if (!IS_ENABLED(CONFIG_OF) || !client->dev.of_node) if (!IS_ENABLED(CONFIG_OF) || !client->dev.of_node)
return client->dev.platform_data; return client->dev.platform_data;
np = v4l2_of_get_next_endpoint(client->dev.of_node, NULL); np = of_graph_get_next_endpoint(client->dev.of_node, NULL);
if (!np) if (!np)
return NULL; return NULL;
......
...@@ -21,6 +21,7 @@ ...@@ -21,6 +21,7 @@
#include <linux/module.h> #include <linux/module.h>
#include <linux/of.h> #include <linux/of.h>
#include <linux/of_gpio.h> #include <linux/of_gpio.h>
#include <linux/of_graph.h>
#include <linux/pm.h> #include <linux/pm.h>
#include <linux/regulator/consumer.h> #include <linux/regulator/consumer.h>
#include <linux/slab.h> #include <linux/slab.h>
...@@ -29,7 +30,6 @@ ...@@ -29,7 +30,6 @@
#include <media/mt9p031.h> #include <media/mt9p031.h>
#include <media/v4l2-ctrls.h> #include <media/v4l2-ctrls.h>
#include <media/v4l2-device.h> #include <media/v4l2-device.h>
#include <media/v4l2-of.h>
#include <media/v4l2-subdev.h> #include <media/v4l2-subdev.h>
#include "aptina-pll.h" #include "aptina-pll.h"
...@@ -943,7 +943,7 @@ mt9p031_get_pdata(struct i2c_client *client) ...@@ -943,7 +943,7 @@ mt9p031_get_pdata(struct i2c_client *client)
if (!IS_ENABLED(CONFIG_OF) || !client->dev.of_node) if (!IS_ENABLED(CONFIG_OF) || !client->dev.of_node)
return client->dev.platform_data; return client->dev.platform_data;
np = v4l2_of_get_next_endpoint(client->dev.of_node, NULL); np = of_graph_get_next_endpoint(client->dev.of_node, NULL);
if (!np) if (!np)
return NULL; return NULL;
......
...@@ -21,6 +21,7 @@ ...@@ -21,6 +21,7 @@
#include <linux/media.h> #include <linux/media.h>
#include <linux/module.h> #include <linux/module.h>
#include <linux/of_gpio.h> #include <linux/of_gpio.h>
#include <linux/of_graph.h>
#include <linux/regulator/consumer.h> #include <linux/regulator/consumer.h>
#include <linux/slab.h> #include <linux/slab.h>
...@@ -1855,7 +1856,7 @@ static int s5k5baf_parse_device_node(struct s5k5baf *state, struct device *dev) ...@@ -1855,7 +1856,7 @@ static int s5k5baf_parse_device_node(struct s5k5baf *state, struct device *dev)
if (ret < 0) if (ret < 0)
return ret; return ret;
node_ep = v4l2_of_get_next_endpoint(node, NULL); node_ep = of_graph_get_next_endpoint(node, NULL);
if (!node_ep) { if (!node_ep) {
dev_err(dev, "no endpoint defined at node %s\n", dev_err(dev, "no endpoint defined at node %s\n",
node->full_name); node->full_name);
......
...@@ -36,6 +36,7 @@ ...@@ -36,6 +36,7 @@
#include <linux/module.h> #include <linux/module.h>
#include <linux/v4l2-mediabus.h> #include <linux/v4l2-mediabus.h>
#include <linux/of.h> #include <linux/of.h>
#include <linux/of_graph.h>
#include <media/v4l2-async.h> #include <media/v4l2-async.h>
#include <media/v4l2-device.h> #include <media/v4l2-device.h>
...@@ -1068,7 +1069,7 @@ tvp514x_get_pdata(struct i2c_client *client) ...@@ -1068,7 +1069,7 @@ tvp514x_get_pdata(struct i2c_client *client)
if (!IS_ENABLED(CONFIG_OF) || !client->dev.of_node) if (!IS_ENABLED(CONFIG_OF) || !client->dev.of_node)
return client->dev.platform_data; return client->dev.platform_data;
endpoint = v4l2_of_get_next_endpoint(client->dev.of_node, NULL); endpoint = of_graph_get_next_endpoint(client->dev.of_node, NULL);
if (!endpoint) if (!endpoint)
return NULL; return NULL;
......
...@@ -30,6 +30,7 @@ ...@@ -30,6 +30,7 @@
#include <linux/videodev2.h> #include <linux/videodev2.h>
#include <linux/module.h> #include <linux/module.h>
#include <linux/of.h> #include <linux/of.h>
#include <linux/of_graph.h>
#include <linux/v4l2-dv-timings.h> #include <linux/v4l2-dv-timings.h>
#include <media/tvp7002.h> #include <media/tvp7002.h>
#include <media/v4l2-async.h> #include <media/v4l2-async.h>
...@@ -957,7 +958,7 @@ tvp7002_get_pdata(struct i2c_client *client) ...@@ -957,7 +958,7 @@ tvp7002_get_pdata(struct i2c_client *client)
if (!IS_ENABLED(CONFIG_OF) || !client->dev.of_node) if (!IS_ENABLED(CONFIG_OF) || !client->dev.of_node)
return client->dev.platform_data; return client->dev.platform_data;
endpoint = v4l2_of_get_next_endpoint(client->dev.of_node, NULL); endpoint = of_graph_get_next_endpoint(client->dev.of_node, NULL);
if (!endpoint) if (!endpoint)
return NULL; return NULL;
......
...@@ -24,13 +24,13 @@ ...@@ -24,13 +24,13 @@
#include <linux/i2c.h> #include <linux/i2c.h>
#include <linux/of_irq.h> #include <linux/of_irq.h>
#include <linux/of_address.h> #include <linux/of_address.h>
#include <linux/of_graph.h>
#include <linux/of_platform.h> #include <linux/of_platform.h>
#include <linux/platform_device.h> #include <linux/platform_device.h>
#include <linux/pm_runtime.h> #include <linux/pm_runtime.h>
#include <linux/slab.h> #include <linux/slab.h>
#include <linux/types.h> #include <linux/types.h>
#include <linux/videodev2.h> #include <linux/videodev2.h>
#include <media/v4l2-of.h>
#include <media/videobuf2-dma-contig.h> #include <media/videobuf2-dma-contig.h>
#include "media-dev.h" #include "media-dev.h"
...@@ -167,10 +167,10 @@ static int fimc_is_parse_sensor_config(struct fimc_is_sensor *sensor, ...@@ -167,10 +167,10 @@ static int fimc_is_parse_sensor_config(struct fimc_is_sensor *sensor,
u32 tmp = 0; u32 tmp = 0;
int ret; int ret;
np = v4l2_of_get_next_endpoint(np, NULL); np = of_graph_get_next_endpoint(np, NULL);
if (!np) if (!np)
return -ENXIO; return -ENXIO;
np = v4l2_of_get_remote_port(np); np = of_graph_get_remote_port(np);
if (!np) if (!np)
return -ENXIO; return -ENXIO;
......
...@@ -20,6 +20,7 @@ ...@@ -20,6 +20,7 @@
#include <linux/of.h> #include <linux/of.h>
#include <linux/of_platform.h> #include <linux/of_platform.h>
#include <linux/of_device.h> #include <linux/of_device.h>
#include <linux/of_graph.h>
#include <linux/platform_device.h> #include <linux/platform_device.h>
#include <linux/pm_runtime.h> #include <linux/pm_runtime.h>
#include <linux/types.h> #include <linux/types.h>
...@@ -473,7 +474,7 @@ static int fimc_md_parse_port_node(struct fimc_md *fmd, ...@@ -473,7 +474,7 @@ static int fimc_md_parse_port_node(struct fimc_md *fmd,
pd->mux_id = (endpoint.port - 1) & 0x1; pd->mux_id = (endpoint.port - 1) & 0x1;
rem = v4l2_of_get_remote_port_parent(ep); rem = of_graph_get_remote_port_parent(ep);
of_node_put(ep); of_node_put(ep);
if (rem == NULL) { if (rem == NULL) {
v4l2_info(&fmd->v4l2_dev, "Remote device at %s not found\n", v4l2_info(&fmd->v4l2_dev, "Remote device at %s not found\n",
......
...@@ -20,6 +20,7 @@ ...@@ -20,6 +20,7 @@
#include <linux/memory.h> #include <linux/memory.h>
#include <linux/module.h> #include <linux/module.h>
#include <linux/of.h> #include <linux/of.h>
#include <linux/of_graph.h>
#include <linux/phy/phy.h> #include <linux/phy/phy.h>
#include <linux/platform_data/mipi-csis.h> #include <linux/platform_data/mipi-csis.h>
#include <linux/platform_device.h> #include <linux/platform_device.h>
...@@ -762,7 +763,7 @@ static int s5pcsis_parse_dt(struct platform_device *pdev, ...@@ -762,7 +763,7 @@ static int s5pcsis_parse_dt(struct platform_device *pdev,
&state->max_num_lanes)) &state->max_num_lanes))
return -EINVAL; return -EINVAL;
node = v4l2_of_get_next_endpoint(node, NULL); node = of_graph_get_next_endpoint(node, NULL);
if (!node) { if (!node) {
dev_err(&pdev->dev, "No port node at %s\n", dev_err(&pdev->dev, "No port node at %s\n",
pdev->dev.of_node->full_name); pdev->dev.of_node->full_name);
......
...@@ -152,120 +152,3 @@ int v4l2_of_parse_endpoint(const struct device_node *node, ...@@ -152,120 +152,3 @@ int v4l2_of_parse_endpoint(const struct device_node *node,
return 0; return 0;
} }
EXPORT_SYMBOL(v4l2_of_parse_endpoint); EXPORT_SYMBOL(v4l2_of_parse_endpoint);
/**
* v4l2_of_get_next_endpoint() - get next endpoint node
* @parent: pointer to the parent device node
* @prev: previous endpoint node, or NULL to get first
*
* Return: An 'endpoint' node pointer with refcount incremented. Refcount
* of the passed @prev node is not decremented, the caller have to use
* of_node_put() on it when done.
*/
struct device_node *v4l2_of_get_next_endpoint(const struct device_node *parent,
struct device_node *prev)
{
struct device_node *endpoint;
struct device_node *port = NULL;
if (!parent)
return NULL;
if (!prev) {
struct device_node *node;
/*
* It's the first call, we have to find a port subnode
* within this node or within an optional 'ports' node.
*/
node = of_get_child_by_name(parent, "ports");
if (node)
parent = node;
port = of_get_child_by_name(parent, "port");
if (port) {
/* Found a port, get an endpoint. */
endpoint = of_get_next_child(port, NULL);
of_node_put(port);
} else {
endpoint = NULL;
}
if (!endpoint)
pr_err("%s(): no endpoint nodes specified for %s\n",
__func__, parent->full_name);
of_node_put(node);
} else {
port = of_get_parent(prev);
if (!port)
/* Hm, has someone given us the root node ?... */
return NULL;
/* Avoid dropping prev node refcount to 0. */
of_node_get(prev);
endpoint = of_get_next_child(port, prev);
if (endpoint) {
of_node_put(port);
return endpoint;
}
/* No more endpoints under this port, try the next one. */
do {
port = of_get_next_child(parent, port);
if (!port)
return NULL;
} while (of_node_cmp(port->name, "port"));
/* Pick up the first endpoint in this port. */
endpoint = of_get_next_child(port, NULL);
of_node_put(port);
}
return endpoint;
}
EXPORT_SYMBOL(v4l2_of_get_next_endpoint);
/**
* v4l2_of_get_remote_port_parent() - get remote port's parent node
* @node: pointer to a local endpoint device_node
*
* Return: Remote device node associated with remote endpoint node linked
* to @node. Use of_node_put() on it when done.
*/
struct device_node *v4l2_of_get_remote_port_parent(
const struct device_node *node)
{
struct device_node *np;
unsigned int depth;
/* Get remote endpoint node. */
np = of_parse_phandle(node, "remote-endpoint", 0);
/* Walk 3 levels up only if there is 'ports' node. */
for (depth = 3; depth && np; depth--) {
np = of_get_next_parent(np);
if (depth == 2 && of_node_cmp(np->name, "ports"))
break;
}
return np;
}
EXPORT_SYMBOL(v4l2_of_get_remote_port_parent);
/**
* v4l2_of_get_remote_port() - get remote port node
* @node: pointer to a local endpoint device_node
*
* Return: Remote port node associated with remote endpoint node linked
* to @node. Use of_node_put() on it when done.
*/
struct device_node *v4l2_of_get_remote_port(const struct device_node *node)
{
struct device_node *np;
/* Get remote endpoint node. */
np = of_parse_phandle(node, "remote-endpoint", 0);
if (!np)
return NULL;
return of_get_next_parent(np);
}
EXPORT_SYMBOL(v4l2_of_get_remote_port);
...@@ -21,6 +21,7 @@ ...@@ -21,6 +21,7 @@
#include <linux/cpu.h> #include <linux/cpu.h>
#include <linux/module.h> #include <linux/module.h>
#include <linux/of.h> #include <linux/of.h>
#include <linux/of_graph.h>
#include <linux/spinlock.h> #include <linux/spinlock.h>
#include <linux/slab.h> #include <linux/slab.h>
#include <linux/proc_fs.h> #include <linux/proc_fs.h>
...@@ -1982,3 +1983,120 @@ struct device_node *of_find_next_cache_node(const struct device_node *np) ...@@ -1982,3 +1983,120 @@ struct device_node *of_find_next_cache_node(const struct device_node *np)
return NULL; return NULL;
} }
/**
* of_graph_get_next_endpoint() - get next endpoint node
* @parent: pointer to the parent device node
* @prev: previous endpoint node, or NULL to get first
*
* Return: An 'endpoint' node pointer with refcount incremented. Refcount
* of the passed @prev node is not decremented, the caller have to use
* of_node_put() on it when done.
*/
struct device_node *of_graph_get_next_endpoint(const struct device_node *parent,
struct device_node *prev)
{
struct device_node *endpoint;
struct device_node *port = NULL;
if (!parent)
return NULL;
if (!prev) {
struct device_node *node;
/*
* It's the first call, we have to find a port subnode
* within this node or within an optional 'ports' node.
*/
node = of_get_child_by_name(parent, "ports");
if (node)
parent = node;
port = of_get_child_by_name(parent, "port");
if (port) {
/* Found a port, get an endpoint. */
endpoint = of_get_next_child(port, NULL);
of_node_put(port);
} else {
endpoint = NULL;
}
if (!endpoint)
pr_err("%s(): no endpoint nodes specified for %s\n",
__func__, parent->full_name);
of_node_put(node);
} else {
port = of_get_parent(prev);
if (!port)
/* Hm, has someone given us the root node ?... */
return NULL;
/* Avoid dropping prev node refcount to 0. */
of_node_get(prev);
endpoint = of_get_next_child(port, prev);
if (endpoint) {
of_node_put(port);
return endpoint;
}
/* No more endpoints under this port, try the next one. */
do {
port = of_get_next_child(parent, port);
if (!port)
return NULL;
} while (of_node_cmp(port->name, "port"));
/* Pick up the first endpoint in this port. */
endpoint = of_get_next_child(port, NULL);
of_node_put(port);
}
return endpoint;
}
EXPORT_SYMBOL(of_graph_get_next_endpoint);
/**
* of_graph_get_remote_port_parent() - get remote port's parent node
* @node: pointer to a local endpoint device_node
*
* Return: Remote device node associated with remote endpoint node linked
* to @node. Use of_node_put() on it when done.
*/
struct device_node *of_graph_get_remote_port_parent(
const struct device_node *node)
{
struct device_node *np;
unsigned int depth;
/* Get remote endpoint node. */
np = of_parse_phandle(node, "remote-endpoint", 0);
/* Walk 3 levels up only if there is 'ports' node. */
for (depth = 3; depth && np; depth--) {
np = of_get_next_parent(np);
if (depth == 2 && of_node_cmp(np->name, "ports"))
break;
}
return np;
}
EXPORT_SYMBOL(of_graph_get_remote_port_parent);
/**
* of_graph_get_remote_port() - get remote port node
* @node: pointer to a local endpoint device_node
*
* Return: Remote port node associated with remote endpoint node linked
* to @node. Use of_node_put() on it when done.
*/
struct device_node *of_graph_get_remote_port(const struct device_node *node)
{
struct device_node *np;
/* Get remote endpoint node. */
np = of_parse_phandle(node, "remote-endpoint", 0);
if (!np)
return NULL;
return of_get_next_parent(np);
}
EXPORT_SYMBOL(of_graph_get_remote_port);
/*
* OF graph binding parsing helpers
*
* Copyright (C) 2012 - 2013 Samsung Electronics Co., Ltd.
* Author: Sylwester Nawrocki <s.nawrocki@samsung.com>
*
* Copyright (C) 2012 Renesas Electronics Corp.
* Author: Guennadi Liakhovetski <g.liakhovetski@gmx.de>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of version 2 of the GNU General Public License as
* published by the Free Software Foundation.
*/
#ifndef __LINUX_OF_GRAPH_H
#define __LINUX_OF_GRAPH_H
#ifdef CONFIG_OF
struct device_node *of_graph_get_next_endpoint(const struct device_node *parent,
struct device_node *previous);
struct device_node *of_graph_get_remote_port_parent(
const struct device_node *node);
struct device_node *of_graph_get_remote_port(const struct device_node *node);
#else
static inline struct device_node *of_graph_get_next_endpoint(
const struct device_node *parent,
struct device_node *previous)
{
return NULL;
}
static inline struct device_node *of_graph_get_remote_port_parent(
const struct device_node *node)
{
return NULL;
}
static inline struct device_node *of_graph_get_remote_port(
const struct device_node *node)
{
return NULL;
}
#endif /* CONFIG_OF */
#endif /* __LINUX_OF_GRAPH_H */
...@@ -17,6 +17,7 @@ ...@@ -17,6 +17,7 @@
#include <linux/list.h> #include <linux/list.h>
#include <linux/types.h> #include <linux/types.h>
#include <linux/errno.h> #include <linux/errno.h>
#include <linux/of_graph.h>
#include <media/v4l2-mediabus.h> #include <media/v4l2-mediabus.h>
...@@ -72,11 +73,6 @@ struct v4l2_of_endpoint { ...@@ -72,11 +73,6 @@ struct v4l2_of_endpoint {
#ifdef CONFIG_OF #ifdef CONFIG_OF
int v4l2_of_parse_endpoint(const struct device_node *node, int v4l2_of_parse_endpoint(const struct device_node *node,
struct v4l2_of_endpoint *endpoint); struct v4l2_of_endpoint *endpoint);
struct device_node *v4l2_of_get_next_endpoint(const struct device_node *parent,
struct device_node *previous);
struct device_node *v4l2_of_get_remote_port_parent(
const struct device_node *node);
struct device_node *v4l2_of_get_remote_port(const struct device_node *node);
#else /* CONFIG_OF */ #else /* CONFIG_OF */
static inline int v4l2_of_parse_endpoint(const struct device_node *node, static inline int v4l2_of_parse_endpoint(const struct device_node *node,
...@@ -85,25 +81,6 @@ static inline int v4l2_of_parse_endpoint(const struct device_node *node, ...@@ -85,25 +81,6 @@ static inline int v4l2_of_parse_endpoint(const struct device_node *node,
return -ENOSYS; return -ENOSYS;
} }
static inline struct device_node *v4l2_of_get_next_endpoint(
const struct device_node *parent,
struct device_node *previous)
{
return NULL;
}
static inline struct device_node *v4l2_of_get_remote_port_parent(
const struct device_node *node)
{
return NULL;
}
static inline struct device_node *v4l2_of_get_remote_port(
const struct device_node *node)
{
return NULL;
}
#endif /* CONFIG_OF */ #endif /* CONFIG_OF */
#endif /* _V4L2_OF_H */ #endif /* _V4L2_OF_H */
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment