Re: [PATCH/RFC v3 06/19] video: display: OF support

2013-09-11 Thread Laurent Pinchart
Hi Philipp,

On Wednesday 04 September 2013 16:21:38 Philipp Zabel wrote:
 Am Samstag, den 10.08.2013, 01:03 +0200 schrieb Laurent Pinchart:
  Extend the notifier with DT node matching support, and add helper
  functions to build the notifier and link entities based on a graph
  representation in DT.
  
  Signed-off-by: Laurent Pinchart
  laurent.pinchart+rene...@ideasonboard.com
  ---
  
   drivers/video/display/display-core.c | 334 ++
   drivers/video/display/display-notifier.c | 187 +
   include/video/display.h  |  45 +
   3 files changed, 566 insertions(+)
  
  diff --git a/drivers/video/display/display-core.c
  b/drivers/video/display/display-core.c index c3b47d3..328ead7 100644
  --- a/drivers/video/display/display-core.c
  +++ b/drivers/video/display/display-core.c
 
 [...]
 
  @@ -420,6 +599,161 @@ int display_entity_link_graph(struct device *dev,
  struct list_head *entities) 
   }
   EXPORT_SYMBOL_GPL(display_entity_link_graph);
  
  +#ifdef CONFIG_OF
  +
  +static int display_of_entity_link_entity(struct device *dev,
  +struct display_entity *entity,
  +struct list_head *entities,
  +struct display_entity *root)
  +{
  +   u32 link_flags = MEDIA_LNK_FL_IMMUTABLE | MEDIA_LNK_FL_ENABLED;
  +   const struct device_node *node = entity-dev-of_node;
 
 the current device tree matching implementation only allows one display
 entity per linux device. How about adding an of_node pointer to struct
 display_entity directly and allow multiple display entity nodes below in a
 single device node in the device tree?

That's a very good point. We had a similar issues in V4L2, with sensors that 
would create several entities. However, in those cases, the sensors would be 
connected to the rest of the pipeline through a single entity :

Sensor Entity 1 - ... - Sensor Entity N - V4L2 pipeline ...

The core code thus had to care about a single sensor entity when building the 
pipeline. We could solve the problem in a similar way for panels, but encoders 
need a more elaborate solution.

I see (at least) two possibilities here, either explicitly describing all 
entities that make the device in DT (as you have proposed below), or creating 
a hierarchy of entities, with parent entities that can contain several child 
entities. I've CC'ed Guennadi, Hans, Sylwester and Sakari to get their opinion 
on the matter.

 lvds-encoder {
   channel@0 {

If I understand this correctly, your LVDS encoder has two independent 
channels. In the general case a device made of multiple entities might have 
those entities chained, so channel might not be the best term. entity 
might be a better choice.

   port@0 {
   lvds0_input: endpoint {
   };
   };
   port@1 {
   lvds0_output: endpoint {
   };
   };
   };
   channel@1 {
   port@0 {
   lvds1_input: endpoint {
   };
   };
   lvds1: port@1 {
   lvds1_output: endpoint {
   };
   };
   };
 };
 
  +   struct media_entity *local = entity-entity;
  +   struct device_node *ep = NULL;
  +   int ret = 0;
  +
  +   dev_dbg(dev, creating links for entity %s\n, local-name);
  +
  +   while (1) {
  +   struct media_entity *remote = NULL;
  +   struct media_pad *remote_pad;
  +   struct media_pad *local_pad;
  +   struct display_of_link link;
  +   struct display_entity *ent;
  +   struct device_node *next;
  +
  +   /* Get the next endpoint and parse its link. */
  +   next = display_of_get_next_endpoint(node, ep);
  +   if (next == NULL)
  +   break;
  +
  +   of_node_put(ep);
  +   ep = next;
  +
  +   dev_dbg(dev, processing endpoint %s\n, ep-full_name);
  +
  +   ret = display_of_parse_link(ep, link);
  +   if (ret  0) {
  +   dev_err(dev, failed to parse link for %s\n,
  +   ep-full_name);
  +   continue;
  +   }
  +
  +   /* Skip source pads, they will be processed from the other end 
  of
  +* the link.
  +*/
  +   if (link.local_port = local-num_pads) {
  +   dev_err(dev, invalid port number %u on %s\n,
  +   link.local_port, link.local_node-full_name);
  +   display_of_put_link(link);
  +   ret = -EINVAL;
  +   break;
  +   }
  +
  +   local_pad = local-pads[link.local_port];
  +
  +   if (local_pad-flags  MEDIA_PAD_FL_SOURCE) {
  +   dev_dbg(dev, skipping source port %s:%u\n,
  +

Re: [PATCH/RFC v3 06/19] video: display: OF support

2013-09-11 Thread Philipp Zabel
Am Mittwoch, den 11.09.2013, 13:33 +0200 schrieb Laurent Pinchart:
 Hi Philipp,
 
 On Wednesday 04 September 2013 16:21:38 Philipp Zabel wrote:
  Am Samstag, den 10.08.2013, 01:03 +0200 schrieb Laurent Pinchart:
   Extend the notifier with DT node matching support, and add helper
   functions to build the notifier and link entities based on a graph
   representation in DT.
   
   Signed-off-by: Laurent Pinchart
   laurent.pinchart+rene...@ideasonboard.com
   ---
   
drivers/video/display/display-core.c | 334 ++
drivers/video/display/display-notifier.c | 187 +
include/video/display.h  |  45 +
3 files changed, 566 insertions(+)
   
   diff --git a/drivers/video/display/display-core.c
   b/drivers/video/display/display-core.c index c3b47d3..328ead7 100644
   --- a/drivers/video/display/display-core.c
   +++ b/drivers/video/display/display-core.c
  
  [...]
  
   @@ -420,6 +599,161 @@ int display_entity_link_graph(struct device *dev,
   struct list_head *entities) 
}
EXPORT_SYMBOL_GPL(display_entity_link_graph);
   
   +#ifdef CONFIG_OF
   +
   +static int display_of_entity_link_entity(struct device *dev,
   +  struct display_entity *entity,
   +  struct list_head *entities,
   +  struct display_entity *root)
   +{
   + u32 link_flags = MEDIA_LNK_FL_IMMUTABLE | MEDIA_LNK_FL_ENABLED;
   + const struct device_node *node = entity-dev-of_node;
  
  the current device tree matching implementation only allows one display
  entity per linux device. How about adding an of_node pointer to struct
  display_entity directly and allow multiple display entity nodes below in a
  single device node in the device tree?
 
 That's a very good point. We had a similar issues in V4L2, with sensors that 
 would create several entities. However, in those cases, the sensors would be 
 connected to the rest of the pipeline through a single entity :
 
 Sensor Entity 1 - ... - Sensor Entity N - V4L2 pipeline ...
 
 The core code thus had to care about a single sensor entity when building the 
 pipeline. We could solve the problem in a similar way for panels, but 
 encoders 
 need a more elaborate solution.
 
 I see (at least) two possibilities here, either explicitly describing all 
 entities that make the device in DT (as you have proposed below), or creating 
 a hierarchy of entities, with parent entities that can contain several child 
 entities. I've CC'ed Guennadi, Hans, Sylwester and Sakari to get their 
 opinion 
 on the matter.

When you say hierarchy of entities, I imagine something like GStreamer
bins? I suspect hierarchically encapsulated entities would complicate
the pipeline/graph traversal code quite a bit, although it would
probably help to organise the graph and reduce the amount of boilerplate
needed in the device tree.

  lvds-encoder {
  channel@0 {
 
 If I understand this correctly, your LVDS encoder has two independent 
 channels.

In this example, yes. In reality the i.MX LDB has a mux in each path, so
both inputs can be routed to both outputs. With an entity hierarchy this
could be described as a single entity with two inputs and two outputs,
containing two multiplexer entites and two encoder entities.

LDB entity with two input pads, four internal entities, and two output
pads:
  ,.
  |-.  LDB   ,--.  ,--.  ,-|
--| pad || mux0 |--| enc0 |--| pad |--
  |  0  |--.  ,--|  |  |  |  |  2  |
  |-´   \/   `--´  `--´  `-|
  |-.   /\   ,--.  ,--.  .-|
--| pad |--´  `--| mux1 |  | enc1 |--| pad |--
  |  1  ||  |--|  |  |  3  |
  |-´`--´  `--´  `-|
  `´
(In guess the mux and enc entities could each be combined into one)

 In the general case a device made of multiple entities might have 
 those entities chained, so channel might not be the best term.
 entity might be a better choice.

On the other hand, when describing subdevice entities in the device
tree, maybe the generic type of entity (sensor, scaler, encoder, mux,
etc.) would be useful information?

Another module where I'd like to describe the (outward facing) contained
entities in the device tree is the i.MX Image Processing Unit, which has
two capture interfaces and two display interfaces (all parallel). Those
can't be combined into a single entity because there are other internal
entities connected to them, and because the capture interfaces are v4l2
subdevices, whereas the display interfaces will be display entites.
Alternatively, this could also be described as a single entity
containing an internal structure.

IPU entity with two input pads, two internal capture entities (csi), two
display entities (di), and two output pads:
  ,.
  |-.  ,--.  IPU   

Re: [PATCH/RFC v3 06/19] video: display: OF support

2013-09-11 Thread Hans Verkuil


On 09/11/2013 01:33 PM, Laurent Pinchart wrote:
 Hi Philipp,
 
 On Wednesday 04 September 2013 16:21:38 Philipp Zabel wrote:
 Am Samstag, den 10.08.2013, 01:03 +0200 schrieb Laurent Pinchart:
 Extend the notifier with DT node matching support, and add helper
 functions to build the notifier and link entities based on a graph
 representation in DT.

 Signed-off-by: Laurent Pinchart
 laurent.pinchart+rene...@ideasonboard.com
 ---

  drivers/video/display/display-core.c | 334 ++
  drivers/video/display/display-notifier.c | 187 +
  include/video/display.h  |  45 +
  3 files changed, 566 insertions(+)

 diff --git a/drivers/video/display/display-core.c
 b/drivers/video/display/display-core.c index c3b47d3..328ead7 100644
 --- a/drivers/video/display/display-core.c
 +++ b/drivers/video/display/display-core.c

 [...]

 @@ -420,6 +599,161 @@ int display_entity_link_graph(struct device *dev,
 struct list_head *entities) 
  }
  EXPORT_SYMBOL_GPL(display_entity_link_graph);

 +#ifdef CONFIG_OF
 +
 +static int display_of_entity_link_entity(struct device *dev,
 +struct display_entity *entity,
 +struct list_head *entities,
 +struct display_entity *root)
 +{
 +   u32 link_flags = MEDIA_LNK_FL_IMMUTABLE | MEDIA_LNK_FL_ENABLED;
 +   const struct device_node *node = entity-dev-of_node;

 the current device tree matching implementation only allows one display
 entity per linux device. How about adding an of_node pointer to struct
 display_entity directly and allow multiple display entity nodes below in a
 single device node in the device tree?
 
 That's a very good point. We had a similar issues in V4L2, with sensors that 
 would create several entities. However, in those cases, the sensors would be 
 connected to the rest of the pipeline through a single entity :
 
 Sensor Entity 1 - ... - Sensor Entity N - V4L2 pipeline ...
 
 The core code thus had to care about a single sensor entity when building the 
 pipeline. We could solve the problem in a similar way for panels, but 
 encoders 
 need a more elaborate solution.

Why? Sorry, I don't see why an encoder is different in this respect than a 
panel.
I'm sure I'm missing something here.

 
 I see (at least) two possibilities here, either explicitly describing all 
 entities that make the device in DT (as you have proposed below), or creating 
 a hierarchy of entities, with parent entities that can contain several child 
 entities. I've CC'ed Guennadi, Hans, Sylwester and Sakari to get their 
 opinion 
 on the matter.

I think the way this is done today in complex devices is that the driver just
exposes itself as a single sub-device, but internally it has its own pipeline of
sub-devices. The only one that I know of (platform/s5p-tv/hdmi_drv) doesn't 
expose
them to a media controller, they are completely hidden inside the hdmi driver.

The ability to support hierarchies of entities would be very nice. However, I
don't know how much work that would be to implement and if it is worth the
effort.

Regards,

Hans

 
 lvds-encoder {
  channel@0 {
 
 If I understand this correctly, your LVDS encoder has two independent 
 channels. In the general case a device made of multiple entities might have 
 those entities chained, so channel might not be the best term. entity 
 might be a better choice.
 
  port@0 {
  lvds0_input: endpoint {
  };
  };
  port@1 {
  lvds0_output: endpoint {
  };
  };
  };
  channel@1 {
  port@0 {
  lvds1_input: endpoint {
  };
  };
  lvds1: port@1 {
  lvds1_output: endpoint {
  };
  };
  };
 };

 +   struct media_entity *local = entity-entity;
 +   struct device_node *ep = NULL;
 +   int ret = 0;
 +
 +   dev_dbg(dev, creating links for entity %s\n, local-name);
 +
 +   while (1) {
 +   struct media_entity *remote = NULL;
 +   struct media_pad *remote_pad;
 +   struct media_pad *local_pad;
 +   struct display_of_link link;
 +   struct display_entity *ent;
 +   struct device_node *next;
 +
 +   /* Get the next endpoint and parse its link. */
 +   next = display_of_get_next_endpoint(node, ep);
 +   if (next == NULL)
 +   break;
 +
 +   of_node_put(ep);
 +   ep = next;
 +
 +   dev_dbg(dev, processing endpoint %s\n, ep-full_name);
 +
 +   ret = display_of_parse_link(ep, link);
 +   if (ret  0) {
 +   dev_err(dev, failed to parse link for %s\n,
 +   ep-full_name);
 +   continue;
 +   }
 +
 +   /* Skip source pads, they 

Re: [PATCH/RFC v3 06/19] video: display: OF support

2013-09-04 Thread Philipp Zabel
Hi Laurent,

Am Samstag, den 10.08.2013, 01:03 +0200 schrieb Laurent Pinchart:
 Extend the notifier with DT node matching support, and add helper functions to
 build the notifier and link entities based on a graph representation in
 DT.
 
 Signed-off-by: Laurent Pinchart laurent.pinchart+rene...@ideasonboard.com
 ---
  drivers/video/display/display-core.c | 334 
 +++
  drivers/video/display/display-notifier.c | 187 +
  include/video/display.h  |  45 +
  3 files changed, 566 insertions(+)
 
 diff --git a/drivers/video/display/display-core.c 
 b/drivers/video/display/display-core.c
 index c3b47d3..328ead7 100644
 --- a/drivers/video/display/display-core.c
 +++ b/drivers/video/display/display-core.c
[...]
 @@ -420,6 +599,161 @@ int display_entity_link_graph(struct device *dev, 
 struct list_head *entities)
  }
  EXPORT_SYMBOL_GPL(display_entity_link_graph);
  
 +#ifdef CONFIG_OF
 +
 +static int display_of_entity_link_entity(struct device *dev,
 +  struct display_entity *entity,
 +  struct list_head *entities,
 +  struct display_entity *root)
 +{
 + u32 link_flags = MEDIA_LNK_FL_IMMUTABLE | MEDIA_LNK_FL_ENABLED;
 + const struct device_node *node = entity-dev-of_node;

the current device tree matching implementation only allows one display
entity per linux device. How about adding an of_node pointer to struct
display_entity directly and allow multiple display entity nodes below in
a single device node in the device tree?

lvds-encoder {
channel@0 {
port@0 {
lvds0_input: endpoint {
};
};
port@1 {
lvds0_output: endpoint {
};
};
};
channel@1 {
port@0 {
lvds1_input: endpoint {
};
};
lvds1: port@1 {
lvds1_output: endpoint {
};
};
};
};

 + struct media_entity *local = entity-entity;
 + struct device_node *ep = NULL;
 + int ret = 0;
 +
 + dev_dbg(dev, creating links for entity %s\n, local-name);
 +
 + while (1) {
 + struct media_entity *remote = NULL;
 + struct media_pad *remote_pad;
 + struct media_pad *local_pad;
 + struct display_of_link link;
 + struct display_entity *ent;
 + struct device_node *next;
 +
 + /* Get the next endpoint and parse its link. */
 + next = display_of_get_next_endpoint(node, ep);
 + if (next == NULL)
 + break;
 +
 + of_node_put(ep);
 + ep = next;
 +
 + dev_dbg(dev, processing endpoint %s\n, ep-full_name);
 +
 + ret = display_of_parse_link(ep, link);
 + if (ret  0) {
 + dev_err(dev, failed to parse link for %s\n,
 + ep-full_name);
 + continue;
 + }
 +
 + /* Skip source pads, they will be processed from the other end 
 of
 +  * the link.
 +  */
 + if (link.local_port = local-num_pads) {
 + dev_err(dev, invalid port number %u on %s\n,
 + link.local_port, link.local_node-full_name);
 + display_of_put_link(link);
 + ret = -EINVAL;
 + break;
 + }
 +
 + local_pad = local-pads[link.local_port];
 +
 + if (local_pad-flags  MEDIA_PAD_FL_SOURCE) {
 + dev_dbg(dev, skipping source port %s:%u\n,
 + link.local_node-full_name, link.local_port);
 + display_of_put_link(link);
 + continue;
 + }
 +
 + /* Find the remote entity. If not found, just skip the link as
 +  * it goes out of scope of the entities handled by the notifier.
 +  */
 + list_for_each_entry(ent, entities, list) {
 + if (ent-dev-of_node == link.remote_node) {
 + remote = ent-entity;
 + break;
 + }
 + }
 +
 + if (root-dev-of_node == link.remote_node)
 + remote = root-entity;
 +
 + if (remote == NULL) {
 + dev_dbg(dev, no entity found for %s\n,
 + link.remote_node-full_name);
 + display_of_put_link(link);
 + continue;
 + }
 +
 + if (link.remote_port = remote-num_pads) {
 + dev_err(dev, invalid port number %u on %s\n,
 + 

Re: [PATCH/RFC v3 06/19] video: display: OF support

2013-08-29 Thread Laurent Pinchart
Hi Philipp,

On Tuesday 27 August 2013 11:30:51 Philipp Zabel wrote:
 Hi Laurent,
 
 I have another small issue with the graph helpers below:
 
 Am Samstag, den 10.08.2013, 01:03 +0200 schrieb Laurent Pinchart:
 [...]
 
  +/*
  -
   
* Graph Helpers
*/
  
  @@ -420,6 +599,161 @@ int display_entity_link_graph(struct device *dev,
  struct list_head *entities) 
   }
   EXPORT_SYMBOL_GPL(display_entity_link_graph);
  
  +#ifdef CONFIG_OF
  +
  +static int display_of_entity_link_entity(struct device *dev,
  +struct display_entity *entity,
  +struct list_head *entities,
  +struct display_entity *root)
  +{
  +   u32 link_flags = MEDIA_LNK_FL_IMMUTABLE | MEDIA_LNK_FL_ENABLED;
  +   const struct device_node *node = entity-dev-of_node;
  +   struct media_entity *local = entity-entity;
  +   struct device_node *ep = NULL;
  +   int ret = 0;
  +
  +   dev_dbg(dev, creating links for entity %s\n, local-name);
  +
  +   while (1) {
  +   struct media_entity *remote = NULL;
  +   struct media_pad *remote_pad;
  +   struct media_pad *local_pad;
  +   struct display_of_link link;
  +   struct display_entity *ent;
  +   struct device_node *next;
  +
  +   /* Get the next endpoint and parse its link. */
  +   next = display_of_get_next_endpoint(node, ep);
  +   if (next == NULL)
  +   break;
  +
  +   of_node_put(ep);
  +   ep = next;
  +
  +   dev_dbg(dev, processing endpoint %s\n, ep-full_name);
  +
  +   ret = display_of_parse_link(ep, link);
  +   if (ret  0) {
  +   dev_err(dev, failed to parse link for %s\n,
  +   ep-full_name);
  +   continue;
  +   }
  +
  +   /* Skip source pads, they will be processed from the other end 
  of
  +* the link.
  +*/
  +   if (link.local_port = local-num_pads) {
  +   dev_err(dev, invalid port number %u on %s\n,
  +   link.local_port, link.local_node-full_name);
  +   display_of_put_link(link);
  +   ret = -EINVAL;
  +   break;
  +   }
  +
  +   local_pad = local-pads[link.local_port];
  +
  +   if (local_pad-flags  MEDIA_PAD_FL_SOURCE) {
  +   dev_dbg(dev, skipping source port %s:%u\n,
  +   link.local_node-full_name, link.local_port);
  +   display_of_put_link(link);
  +   continue;
  +   }
  +
  +   /* Find the remote entity. If not found, just skip the link as
  +* it goes out of scope of the entities handled by the notifier.
  +*/
  +   list_for_each_entry(ent, entities, list) {
  +   if (ent-dev-of_node == link.remote_node) {
  +   remote = ent-entity;
  +   break;
  +   }
  +   }
  +
  +   if (root-dev-of_node == link.remote_node)
  +   remote = root-entity;
  +
  +   if (remote == NULL) {
  +   dev_dbg(dev, no entity found for %s\n,
  +   link.remote_node-full_name);
  +   display_of_put_link(link);
  +   continue;
  +   }
  +
  +   if (link.remote_port = remote-num_pads) {
  +   dev_err(dev, invalid port number %u on %s\n,
  +   link.remote_port, link.remote_node-full_name);
  +   display_of_put_link(link);
  +   ret = -EINVAL;
  +   break;
  +   }
  +
  +   remote_pad = remote-pads[link.remote_port];
  +
  +   display_of_put_link(link);
  +
  +   /* Create the media link. */
  +   dev_dbg(dev, creating %s:%u - %s:%u link\n,
  +   remote-name, remote_pad-index,
  +   local-name, local_pad-index);
  +
  +   ret = media_entity_create_link(remote, remote_pad-index,
  +  local, local_pad-index,
  +  link_flags);
  +   if (ret  0) {
  +   dev_err(dev,
  +   failed to create %s:%u - %s:%u link\n,
  +   remote-name, remote_pad-index,
  +   local-name, local_pad-index);
  +   break;
  +   }
  +   }
  +
  +   of_node_put(ep);
  +   return ret;
  +}
  +
  +/**
  + * display_of_entity_link_graph - Link all entities in a graph
  + * @dev: device used to print debugging and error messages
  + * @root: optional root display entity
  + * @entities: list of display entities in the 

Re: [PATCH/RFC v3 06/19] video: display: OF support

2013-08-27 Thread Philipp Zabel
Hi Laurent,

I have another small issue with the graph helpers below:

Am Samstag, den 10.08.2013, 01:03 +0200 schrieb Laurent Pinchart:
[...]
 +/* 
 -
   * Graph Helpers
   */
  
 @@ -420,6 +599,161 @@ int display_entity_link_graph(struct device *dev, 
 struct list_head *entities)
  }
  EXPORT_SYMBOL_GPL(display_entity_link_graph);
  
 +#ifdef CONFIG_OF
 +
 +static int display_of_entity_link_entity(struct device *dev,
 +  struct display_entity *entity,
 +  struct list_head *entities,
 +  struct display_entity *root)
 +{
 + u32 link_flags = MEDIA_LNK_FL_IMMUTABLE | MEDIA_LNK_FL_ENABLED;
 + const struct device_node *node = entity-dev-of_node;
 + struct media_entity *local = entity-entity;
 + struct device_node *ep = NULL;
 + int ret = 0;
 +
 + dev_dbg(dev, creating links for entity %s\n, local-name);
 +
 + while (1) {
 + struct media_entity *remote = NULL;
 + struct media_pad *remote_pad;
 + struct media_pad *local_pad;
 + struct display_of_link link;
 + struct display_entity *ent;
 + struct device_node *next;
 +
 + /* Get the next endpoint and parse its link. */
 + next = display_of_get_next_endpoint(node, ep);
 + if (next == NULL)
 + break;
 +
 + of_node_put(ep);
 + ep = next;
 +
 + dev_dbg(dev, processing endpoint %s\n, ep-full_name);
 +
 + ret = display_of_parse_link(ep, link);
 + if (ret  0) {
 + dev_err(dev, failed to parse link for %s\n,
 + ep-full_name);
 + continue;
 + }
 +
 + /* Skip source pads, they will be processed from the other end 
 of
 +  * the link.
 +  */
 + if (link.local_port = local-num_pads) {
 + dev_err(dev, invalid port number %u on %s\n,
 + link.local_port, link.local_node-full_name);
 + display_of_put_link(link);
 + ret = -EINVAL;
 + break;
 + }
 +
 + local_pad = local-pads[link.local_port];
 +
 + if (local_pad-flags  MEDIA_PAD_FL_SOURCE) {
 + dev_dbg(dev, skipping source port %s:%u\n,
 + link.local_node-full_name, link.local_port);
 + display_of_put_link(link);
 + continue;
 + }
 +
 + /* Find the remote entity. If not found, just skip the link as
 +  * it goes out of scope of the entities handled by the notifier.
 +  */
 + list_for_each_entry(ent, entities, list) {
 + if (ent-dev-of_node == link.remote_node) {
 + remote = ent-entity;
 + break;
 + }
 + }
 +
 + if (root-dev-of_node == link.remote_node)
 + remote = root-entity;
 +
 + if (remote == NULL) {
 + dev_dbg(dev, no entity found for %s\n,
 + link.remote_node-full_name);
 + display_of_put_link(link);
 + continue;
 + }
 +
 + if (link.remote_port = remote-num_pads) {
 + dev_err(dev, invalid port number %u on %s\n,
 + link.remote_port, link.remote_node-full_name);
 + display_of_put_link(link);
 + ret = -EINVAL;
 + break;
 + }
 +
 + remote_pad = remote-pads[link.remote_port];
 +
 + display_of_put_link(link);
 +
 + /* Create the media link. */
 + dev_dbg(dev, creating %s:%u - %s:%u link\n,
 + remote-name, remote_pad-index,
 + local-name, local_pad-index);
 +
 + ret = media_entity_create_link(remote, remote_pad-index,
 +local, local_pad-index,
 +link_flags);
 + if (ret  0) {
 + dev_err(dev,
 + failed to create %s:%u - %s:%u link\n,
 + remote-name, remote_pad-index,
 + local-name, local_pad-index);
 + break;
 + }
 + }
 +
 + of_node_put(ep);
 + return ret;
 +}
 +
 +/**
 + * display_of_entity_link_graph - Link all entities in a graph
 + * @dev: device used to print debugging and error messages
 + * @root: optional root display entity
 + * @entities: list of display entities in the graph
 + *
 + * This function 

[PATCH/RFC v3 06/19] video: display: OF support

2013-08-09 Thread Laurent Pinchart
Extend the notifier with DT node matching support, and add helper functions to
build the notifier and link entities based on a graph representation in
DT.

Signed-off-by: Laurent Pinchart laurent.pinchart+rene...@ideasonboard.com
---
 drivers/video/display/display-core.c | 334 +++
 drivers/video/display/display-notifier.c | 187 +
 include/video/display.h  |  45 +
 3 files changed, 566 insertions(+)

diff --git a/drivers/video/display/display-core.c 
b/drivers/video/display/display-core.c
index c3b47d3..328ead7 100644
--- a/drivers/video/display/display-core.c
+++ b/drivers/video/display/display-core.c
@@ -14,6 +14,7 @@
 #include linux/export.h
 #include linux/kernel.h
 #include linux/module.h
+#include linux/of.h
 #include linux/slab.h
 
 #include media/media-device.h
@@ -315,6 +316,184 @@ void display_entity_unregister(struct display_entity 
*entity)
 EXPORT_SYMBOL_GPL(display_entity_unregister);
 
 /* 
-
+ * OF Helpers
+ */
+
+#ifdef CONFIG_OF
+
+/**
+ * display_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 *
+display_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;
+}
+
+/**
+ * display_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 *
+display_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;
+}
+
+/**
+ * struct display_of_link - a link between two endpoints
+ * @local_node: pointer to device_node of this endpoint
+ * @local_port: identifier of the port this endpoint belongs to
+ * @remote_node: pointer to device_node of the remote endpoint
+ * @remote_port: identifier of the port the remote endpoint belongs to
+ */
+struct display_of_link {
+   struct device_node *local_node;
+   unsigned int local_port;
+   struct device_node *remote_node;
+   unsigned int remote_port;
+};
+
+/**
+ * display_of_parse_link() - parse a