diff mbox

[RFC,2/3] staging: imx-drm-core: Use graph to find connection between crtc and encoder

Message ID 1389019922-31992-3-git-send-email-p.zabel@pengutronix.de (mailing list archive)
State New, archived
Headers show

Commit Message

Philipp Zabel Jan. 6, 2014, 2:52 p.m. UTC
Signed-off-by: Philipp Zabel <p.zabel@pengutronix.de>
---
 drivers/staging/imx-drm/imx-drm-core.c | 44 ++++++++++++++++++++++++----------
 1 file changed, 32 insertions(+), 12 deletions(-)

Comments

Russell King - ARM Linux Feb. 10, 2014, 4:26 p.m. UTC | #1
On Mon, Jan 06, 2014 at 03:52:01PM +0100, Philipp Zabel wrote:
> @@ -438,24 +453,21 @@ int imx_drm_encoder_parse_of(struct drm_device *drm,
>  	struct drm_encoder *encoder, struct device_node *np)
>  {
>  	struct imx_drm_device *imxdrm = drm->dev_private;
> +	struct device_node *ep, *last_ep = NULL;
>  	uint32_t crtc_mask = 0;
>  	int i, ret = 0;
>  
>  	for (i = 0; !ret; i++) {
> -		struct of_phandle_args args;
>  		uint32_t mask;
> -		int id;
>  
> -		ret = of_parse_phandle_with_args(np, "crtcs", "#crtc-cells", i,
> -						 &args);
> -		if (ret == -ENOENT)
> +		ep = v4l2_of_get_next_endpoint(np, last_ep);
> +		if (last_ep)
> +			of_node_put(last_ep);
> +		if (!ep)
>  			break;
> -		if (ret < 0)
> -			return ret;
>  
> -		id = args.args_count > 0 ? args.args[0] : 0;
> -		mask = imx_drm_find_crtc_mask(imxdrm, args.np, id);
> -		of_node_put(args.np);
> +		/* CSI */
> +		mask = imx_drm_find_crtc_mask(imxdrm, ep);
>  
>  		/*
>  		 * If we failed to find the CRTC(s) which this encoder is
> @@ -463,12 +475,20 @@ int imx_drm_encoder_parse_of(struct drm_device *drm,
>  		 * not been registered yet.  Defer probing, and hope that
>  		 * the required CRTC is added later.
>  		 */
> -		if (mask == 0)
> +		if (mask == 0) {
> +			of_node_put(ep);
>  			return -EPROBE_DEFER;
> +		}
>  
>  		crtc_mask |= mask;
> +		last_ep = ep;
>  	}
>  
> +	if (ep)
> +		of_node_put(ep);

Why is this loop soo complicated?  Why do you need to mess around with
this "last_ep" stuff - you don't actually end up using it.

The loop reduces down to this without comments:

 	for (i = 0; !ret; i++) {
 		uint32_t mask;

		ep = v4l2_of_get_next_endpoint(np, last_ep);
		if (!ep)
			break;

		/* CSI */
		mask = imx_drm_find_crtc_mask(imxdrm, ep);
		of_node_put(ep);

		if (mask == 0)
			return -EPROBE_DEFER;

		crtc_mask |= mask;
	}

Now, here's the big question: why do we want to use v4l2_* here?  We
may want to use this functionality, but if this functionality is going
to be used outside of v4l2, it needs to become something generic, not
v4l2 specific.

Let's think about this for a moment... if we want to build imx-drm into
the kernel, can we do it with modular videodev, or with videodev
completely unconfigured.  We may wish to do this because we have no
videodev requirement on a platform.  Should the build fail because the
v4l2 function isn't there?

So, before we can change this, I think we first need to get agreement
from Mauro to move this function out of V4L2, so that it can be
available independently of V4L2.
Philipp Zabel Feb. 10, 2014, 8:45 p.m. UTC | #2
On Mon, Feb 10, 2014 at 04:26:31PM +0000, Russell King - ARM Linux wrote:
[...]
> Why is this loop soo complicated?  Why do you need to mess around with
> this "last_ep" stuff - you don't actually end up using it.

The last_ep dance is necessary because v4l2_of_get_next_endpoint(node,prev)
does not decrement the reference count of its prev argument.
To make the loop as simple as you propose, I'd either have to change
the get_next_endpoint library function or wrap it to release the prev
node:

static struct device_node *imx_drm_of_get_next_endpoint(
		struct device_node *node, struct device_node *prev)
{
	node = v4l2_of_get_next_endpoint(node, prev);
	of_node_put(prev);
	return node;
}
 
> The loop reduces down to this without comments:
> 
>  	for (i = 0; !ret; i++) {
>  		uint32_t mask;
> 
> 		ep = v4l2_of_get_next_endpoint(np, last_ep);
> 		if (!ep)
> 			break;
> 
> 		/* CSI */
> 		mask = imx_drm_find_crtc_mask(imxdrm, ep);
> 		of_node_put(ep);
> 
> 		if (mask == 0)
> 			return -EPROBE_DEFER;
> 
> 		crtc_mask |= mask;
> 	}

Yes, that is easier to read.

> Now, here's the big question: why do we want to use v4l2_* here?  We
> may want to use this functionality, but if this functionality is going
> to be used outside of v4l2, it needs to become something generic, not
> v4l2 specific.
> 
> Let's think about this for a moment... if we want to build imx-drm into
> the kernel, can we do it with modular videodev, or with videodev
> completely unconfigured.  We may wish to do this because we have no
> videodev requirement on a platform.  Should the build fail because the
> v4l2 function isn't there?
> 
> So, before we can change this, I think we first need to get agreement
> from Mauro to move this function out of V4L2, so that it can be
> available independently of V4L2.

Either that, or we add a temporary copy of the v4l2_of_get_next_endpoint
and v4l2_of_get_remote_port functions while doing the same.

regards
Philipp
Dan Carpenter Feb. 11, 2014, 8:38 a.m. UTC | #3
> Why is this loop soo complicated?  Why do you need to mess around with
> this "last_ep" stuff - you don't actually end up using it.
> 
> The loop reduces down to this without comments:
> 
>  	for (i = 0; !ret; i++) {
                    ^^^^
Philipp, "ret" isn't set anymore in the new loop.

>  		uint32_t mask;
> 
> 		ep = v4l2_of_get_next_endpoint(np, last_ep);
> 		if (!ep)
> 			break;
> 
> 		/* CSI */
> 		mask = imx_drm_find_crtc_mask(imxdrm, ep);
> 		of_node_put(ep);
> 
> 		if (mask == 0)
> 			return -EPROBE_DEFER;
> 
> 		crtc_mask |= mask;
> 	}

regards,
dan carpenter
Philipp Zabel Feb. 11, 2014, 9 a.m. UTC | #4
Hi Dan,

Am Dienstag, den 11.02.2014, 11:38 +0300 schrieb Dan Carpenter:
> > Why is this loop soo complicated?  Why do you need to mess around with
> > this "last_ep" stuff - you don't actually end up using it.
> > 
> > The loop reduces down to this without comments:
> > 
> >  	for (i = 0; !ret; i++) {
>                     ^^^^
> Philipp, "ret" isn't set anymore in the new loop.

thanks, I'll drop ret in the next version.

regards
Philipp
diff mbox

Patch

diff --git a/drivers/staging/imx-drm/imx-drm-core.c b/drivers/staging/imx-drm/imx-drm-core.c
index 2490dc3..2c20434 100644
--- a/drivers/staging/imx-drm/imx-drm-core.c
+++ b/drivers/staging/imx-drm/imx-drm-core.c
@@ -23,6 +23,7 @@ 
 #include <drm/drm_crtc_helper.h>
 #include <drm/drm_gem_cma_helper.h>
 #include <drm/drm_fb_cma_helper.h>
+#include <media/v4l2-of.h>
 
 #include "imx-drm.h"
 
@@ -420,9 +421,23 @@  EXPORT_SYMBOL_GPL(imx_drm_remove_crtc);
  * or removed once the DRM device has been fully initialised.
  */
 static uint32_t imx_drm_find_crtc_mask(struct imx_drm_device *imxdrm,
-	void *cookie, int id)
+	struct device_node *endpoint)
 {
+	struct device_node *remote_port;
+	void *cookie;
 	unsigned i;
+	int id = 0;
+
+	remote_port = v4l2_of_get_remote_port(endpoint);
+	if (remote_port)
+		of_property_read_u32(remote_port, "reg", &id);
+	else
+		return 0;
+	cookie = remote_port->parent;
+	of_node_put(remote_port);
+
+	/* IPU specific: CSI0/1 at 0/1, DI0/1 at 2/3 */
+	id -= 2;
 
 	for (i = 0; i < MAX_CRTC; i++) {
 		struct imx_drm_crtc *imx_drm_crtc = imxdrm->crtc[i];
@@ -438,24 +453,21 @@  int imx_drm_encoder_parse_of(struct drm_device *drm,
 	struct drm_encoder *encoder, struct device_node *np)
 {
 	struct imx_drm_device *imxdrm = drm->dev_private;
+	struct device_node *ep, *last_ep = NULL;
 	uint32_t crtc_mask = 0;
 	int i, ret = 0;
 
 	for (i = 0; !ret; i++) {
-		struct of_phandle_args args;
 		uint32_t mask;
-		int id;
 
-		ret = of_parse_phandle_with_args(np, "crtcs", "#crtc-cells", i,
-						 &args);
-		if (ret == -ENOENT)
+		ep = v4l2_of_get_next_endpoint(np, last_ep);
+		if (last_ep)
+			of_node_put(last_ep);
+		if (!ep)
 			break;
-		if (ret < 0)
-			return ret;
 
-		id = args.args_count > 0 ? args.args[0] : 0;
-		mask = imx_drm_find_crtc_mask(imxdrm, args.np, id);
-		of_node_put(args.np);
+		/* CSI */
+		mask = imx_drm_find_crtc_mask(imxdrm, ep);
 
 		/*
 		 * If we failed to find the CRTC(s) which this encoder is
@@ -463,12 +475,20 @@  int imx_drm_encoder_parse_of(struct drm_device *drm,
 		 * not been registered yet.  Defer probing, and hope that
 		 * the required CRTC is added later.
 		 */
-		if (mask == 0)
+		if (mask == 0) {
+			of_node_put(ep);
 			return -EPROBE_DEFER;
+		}
 
 		crtc_mask |= mask;
+		last_ep = ep;
 	}
 
+	if (ep)
+		of_node_put(ep);
+	if (i == 0)
+		return -ENOENT;
+
 	encoder->possible_crtcs = crtc_mask;
 
 	/* FIXME: this is the mask of outputs which can clone this output. */