Received: by 2002:a25:31c3:0:0:0:0:0 with SMTP id x186csp1412863ybx; Thu, 7 Nov 2019 11:31:50 -0800 (PST) X-Google-Smtp-Source: APXvYqzT5dXBvQ3qUInS1hyDEBTjmsh3oht98rBFdNk7FwZOd+w7cX0IujKfdiyWwylRtuhYQaQx X-Received: by 2002:aa7:d295:: with SMTP id w21mr5520059edq.13.1573155109943; Thu, 07 Nov 2019 11:31:49 -0800 (PST) ARC-Seal: i=1; a=rsa-sha256; t=1573155109; cv=none; d=google.com; s=arc-20160816; b=ruKT5ckXTCAOO4XvspTi/Eel+NcOwm0wSjAtY8kFZiYOFQNQ+73vaoZIXoFtdcGhUX suYgPawEzQcxUmsPvJDTwNUbviXmPdaN21knZoLZTNtH6Hm9cgQMomB01Duwc68UI3W6 T84O9H1hNyAnmYqKrPByS4ZwM2SjtIRxRcyPElGceB5lD3KCvynJOEZqXmiLkX9bJXIu rqFqVCIokgCOGDVe34m5BcrBxPAyz5Zun1ALGOtMdYD8V5B5CpzeUdngQggTuAF67fF4 2xascaFRK+Qfv9dv9qD94fRQ1ryz+XQXuozYdOeb40P+5ODg16g6POco2cYbr1l3GHIG 9McA== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20160816; h=list-id:precedence:sender:user-agent:in-reply-to :content-disposition:mime-version:references:mail-followup-to :message-id:subject:cc:to:from:date:dkim-signature; bh=lWB3JCiHIu1Ht/XhTBHFeS/poSCGsrp4WFT6q7+0Jf0=; b=heRiXaeXMdoQlYu4Mq1K7Hy7OVxeMboWeYqGAFPCoowtKwIkj9O+OYxUnFhVJO4rdE v2rMQSFXCTNNqHk0AVmB/cIGvjvXmdCn3iPnZIBxAJusmP8pnU1irvxoaFEkU5L2H7F/ S0PUEVkibCO4VmcyFfJ6F37f4+xopYs8lYZ3mqqHXN24MB3gVh5LX0wP6s7evN6Tf2El Lt/zLlIhNFzr/0yopXy/F2jqcEi13MLSvMZDvmz/n0xx5X1QYE81RybN/VwKMghpWqiB 5QTUNsMjadPOxjxQBGdX9ybH/WChi1LNNkIBECKJzI9q+vM98eBNmNiYNzQLnPvSq+ZX Zt7A== ARC-Authentication-Results: i=1; mx.google.com; dkim=fail header.i=@ffwll.ch header.s=google header.b=lHzIbaJ2; spf=pass (google.com: best guess record for domain of linux-kernel-owner@vger.kernel.org designates 209.132.180.67 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org Return-Path: Received: from vger.kernel.org (vger.kernel.org. [209.132.180.67]) by mx.google.com with ESMTP id be23si2016180edb.103.2019.11.07.11.31.26; Thu, 07 Nov 2019 11:31:49 -0800 (PST) Received-SPF: pass (google.com: best guess record for domain of linux-kernel-owner@vger.kernel.org designates 209.132.180.67 as permitted sender) client-ip=209.132.180.67; Authentication-Results: mx.google.com; dkim=fail header.i=@ffwll.ch header.s=google header.b=lHzIbaJ2; spf=pass (google.com: best guess record for domain of linux-kernel-owner@vger.kernel.org designates 209.132.180.67 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1726935AbfKGTaP (ORCPT + 99 others); Thu, 7 Nov 2019 14:30:15 -0500 Received: from mail-wr1-f68.google.com ([209.85.221.68]:37087 "EHLO mail-wr1-f68.google.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1726204AbfKGTaO (ORCPT ); Thu, 7 Nov 2019 14:30:14 -0500 Received: by mail-wr1-f68.google.com with SMTP id t1so4422565wrv.4 for ; Thu, 07 Nov 2019 11:30:11 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=ffwll.ch; s=google; h=sender:date:from:to:cc:subject:message-id:mail-followup-to :references:mime-version:content-disposition:in-reply-to:user-agent; bh=lWB3JCiHIu1Ht/XhTBHFeS/poSCGsrp4WFT6q7+0Jf0=; b=lHzIbaJ2W76dHIpyUK7JoFFY463Er56Gv5EsWD4mAO02FUn4i4S7y4ODQUOC/5Xod8 mm3FEkhLxNX3yM5SFbZxfcNuqNgGXO1fjpBIqXhvrcEPlbIR0Bg59PtbLsrjJxOZw/tz xXX0Lcga25xrKqzKaBSddbgAalVehOIws6T2Y= X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:sender:date:from:to:cc:subject:message-id :mail-followup-to:references:mime-version:content-disposition :in-reply-to:user-agent; bh=lWB3JCiHIu1Ht/XhTBHFeS/poSCGsrp4WFT6q7+0Jf0=; b=cHj2YsG9DF+ZsSMV97AvG1huToX5dyw1NEFaF3GTDHCE0Acav/j094rqtS1hUhyb8i QeEqompr7imYwqiRMeVSe1nYWrLVLD91Hbv4/DdmOZJokL88dFNBXIuDBaL7meJ3e8YI cjef7z53cR0zufw7nQXDaXj29spqz8kGVPiXW5e4SU0AtB75yp081NrQRSjL4Rg5bJZU R1e63rfhqKQDcfYc+qVjYy09x2izTmp8fiQy/bTMs5YzukB2mexjHTnYJk9D+hkKy23Q KDd3yHsLeK4a097gfuMC8itIbPNjD9O+IOzeY8SvUxNoYoCzqa0BraaOiHhUBUrgLwyA /PVQ== X-Gm-Message-State: APjAAAWSDbY0krABSBF1W5aYnUJF+0BcfMdFnmsGxb97gvabdAL4GUff kxDB9s/T8dmvhUYDkgnMu4uKaw== X-Received: by 2002:adf:8088:: with SMTP id 8mr4484023wrl.230.1573155010592; Thu, 07 Nov 2019 11:30:10 -0800 (PST) Received: from phenom.ffwll.local (212-51-149-96.fiber7.init7.net. [212.51.149.96]) by smtp.gmail.com with ESMTPSA id v8sm4548112wra.79.2019.11.07.11.30.09 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Thu, 07 Nov 2019 11:30:09 -0800 (PST) Date: Thu, 7 Nov 2019 20:30:07 +0100 From: Daniel Vetter To: Laurent Pinchart Cc: Fabrizio Castro , Maarten Lankhorst , Maxime Ripard , Sean Paul , David Airlie , Daniel Vetter , linux-kernel@vger.kernel.org, dri-devel@lists.freedesktop.org, Simon Horman , Geert Uytterhoeven , Chris Paterson , Biju Das , linux-renesas-soc@vger.kernel.org, Kieran Bingham , Jacopo Mondi , sam@ravnborg.org Subject: Re: [PATCH v3 3/8] drm: Add bus timings helper Message-ID: <20191107193007.GT23790@phenom.ffwll.local> Mail-Followup-To: Laurent Pinchart , Fabrizio Castro , Maarten Lankhorst , Maxime Ripard , Sean Paul , David Airlie , linux-kernel@vger.kernel.org, dri-devel@lists.freedesktop.org, Simon Horman , Geert Uytterhoeven , Chris Paterson , Biju Das , linux-renesas-soc@vger.kernel.org, Kieran Bingham , Jacopo Mondi , sam@ravnborg.org References: <1567017402-5895-1-git-send-email-fabrizio.castro@bp.renesas.com> <1567017402-5895-4-git-send-email-fabrizio.castro@bp.renesas.com> <20191107192621.GH24983@pendragon.ideasonboard.com> MIME-Version: 1.0 Content-Type: text/plain; charset=us-ascii Content-Disposition: inline In-Reply-To: <20191107192621.GH24983@pendragon.ideasonboard.com> X-Operating-System: Linux phenom 5.2.0-3-amd64 User-Agent: Mutt/1.12.2 (2019-09-21) Sender: linux-kernel-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-kernel@vger.kernel.org On Thu, Nov 07, 2019 at 09:26:21PM +0200, Laurent Pinchart wrote: > Hi Fabrizio, > > Thank you for the patch. > > On Wed, Aug 28, 2019 at 07:36:37PM +0100, Fabrizio Castro wrote: > > Helper to provide bus timing information. > > You may want to expand this a bit. And actually fix it too, as the > helper you introduce isn't related to timings (same for the subject > line). Also the kerneldoc needs to be pulled into the templates under Documentation/gpu. And since it's just one function, why not put this into drm_of.c? Gets rid of a pile of overhead. > > > Signed-off-by: Fabrizio Castro > > > > --- > > v2->v3: > > * new patch > > --- > > drivers/gpu/drm/Makefile | 3 +- > > drivers/gpu/drm/drm_bus_timings.c | 97 +++++++++++++++++++++++++++++++++++++++ > > include/drm/drm_bus_timings.h | 21 +++++++++ > > 3 files changed, 120 insertions(+), 1 deletion(-) > > create mode 100644 drivers/gpu/drm/drm_bus_timings.c > > create mode 100644 include/drm/drm_bus_timings.h > > > > diff --git a/drivers/gpu/drm/Makefile b/drivers/gpu/drm/Makefile > > index 9f0d2ee..a270063 100644 > > --- a/drivers/gpu/drm/Makefile > > +++ b/drivers/gpu/drm/Makefile > > @@ -17,7 +17,8 @@ drm-y := drm_auth.o drm_cache.o \ > > drm_plane.o drm_color_mgmt.o drm_print.o \ > > drm_dumb_buffers.o drm_mode_config.o drm_vblank.o \ > > drm_syncobj.o drm_lease.o drm_writeback.o drm_client.o \ > > - drm_client_modeset.o drm_atomic_uapi.o drm_hdcp.o > > + drm_client_modeset.o drm_atomic_uapi.o drm_hdcp.o \ > > + drm_bus_timings.o > > > > drm-$(CONFIG_DRM_LEGACY) += drm_legacy_misc.o drm_bufs.o drm_context.o drm_dma.o drm_scatter.o drm_lock.o > > drm-$(CONFIG_DRM_LIB_RANDOM) += lib/drm_random.o > > diff --git a/drivers/gpu/drm/drm_bus_timings.c b/drivers/gpu/drm/drm_bus_timings.c > > new file mode 100644 > > index 0000000..e2ecd22 > > --- /dev/null > > +++ b/drivers/gpu/drm/drm_bus_timings.c > > @@ -0,0 +1,97 @@ > > +// SPDX-License-Identifier: GPL-2.0 DRM core is supposed to be MIT. -Daniel > > +#include > > +#include > > +#include > > +#include > > +#include > > + > > +#define DRM_OF_LVDS_ODD 1 > > +#define DRM_OF_LVDS_EVEN 2 > > + > > +static int drm_of_lvds_get_port_pixels_type(struct device_node *port_node) > > +{ > > + bool even_pixels, odd_pixels; > > + > > + even_pixels = of_property_read_bool(port_node, "dual-lvds-even-pixels"); > > + odd_pixels = of_property_read_bool(port_node, "dual-lvds-odd-pixels"); > > + return even_pixels * DRM_OF_LVDS_EVEN + odd_pixels * DRM_OF_LVDS_ODD; > > s/ / / > > But I would make these bitflags. > > enum drm_of_lvds_pixels { > DRM_OF_LVDS_EVEN = BIT(0), > DRM_OF_LVDS_ODD = BIT(1), > }; > > static int drm_of_lvds_get_port_pixels_type(struct device_node *port) > { > bool even_pixels = of_property_read_bool(port, "dual-lvds-even-pixels"); > bool odd_pixels = of_property_read_bool(port, "dual-lvds-odd-pixels"); > > return (even_pixels ? DRM_OF_LVDS_EVEN : 0) | > (odd_pixels ? DRM_OF_LVDS_ODD : 0); > } > > > +} > > + > > +/** > > + * drm_of_lvds_get_dual_link_configuration - get the dual-LVDS configuration > > Should we name this drm_of_lvds_get_dual_link_pixel_order to better > reflect its purpose ? > > > + * @p1: device tree node corresponding to the first port of the source > > + * @p2: device tree node corresponding to the second port of the source > > Maybe port1 and port2 to make this more explicit ? > > > + * > > + * An LVDS dual-link bus is made of two connections, even pixels transit on one > > + * connection, and odd pixels transit on the other connection. > > To match the DT bindings documentation, I would recommand > > "An LVDS dual-link connection is made of two links, with even pixels > transitting on one link, and odd pixels on the other link." > > > + * This function walks the DT (from the source ports to the sink ports) looking > > + * for a dual-LVDS bus. A dual-LVDS bus is identfied by markers found on the DT > > + * ports of the sink device(s). If such a bus is found, this function returns > > + * its configuration (either p1 connected to the even pixels port and p2 > > + * connected to the odd pixels port, or p1 connected to the odd pixels port and > > + * p2 connected to the even pixels port). > > "walking the DT" sounds like the function goes through the whole graph. > How about the following ? > > /** > * drm_of_lvds_get_dual_link_pixel_order - Get LVDS dual-link pixel order > * @port1: First DT port node of the Dual-link LVDS source > * @port2: Second DT port node of the Dual-link LVDS source > * > * An LVDS dual-link connection is made of two links, with even pixels > * transitting on one link, and odd pixels on the other link. This function > * returns, for two ports of an LVDS dual-link source, which port shall transmit > * the even and off pixels, based on the requirements of the connected sink. > * > * The pixel order is determined from the dual-lvds-even-pixels and > * dual-lvds-odd-pixels properties in the sink's DT port nodes. If those > * properties are not present, or if their usage is not valid, this function > * returns -EINVAL. > * > * @port1 and @port2 are typically DT sibling nodes, but may have different > * parents when, for instance, two separate LVDS encoders carry the even and odd > * pixels. > * > * Return: > * * DRM_LVDS_DUAL_LINK_EVEN_ODD_PIXELS - @port1 carries even pixels and @port2 > * carries odd pixels > * * DRM_LVDS_DUAL_LINK_EVEN_ODD_PIXELS - @port1 carries odd pixels and @port1 > * carries even pixels > * * -EINVAL - @port1 and @port2 are not connected to a dual-link LVDS sink, or > * the sink configuration is invalid > */ > > We could also add -EPIPE as a return code for the case where port1 or > port2 are not connected. > > > + * > > + * Return: A code describing the bus configuration when a valid dual-LVDS bus is > > + * found, or an error code when no valid dual-LVDS bus is found > > + * > > + * Possible codes for the bus configuration are: > > + * > > + * - DRM_LVDS_DUAL_LINK_EVEN_ODD_PIXELS: when p1 is connected to the even pixels > > + * port and p2 is connected to the odd pixels port > > + * - DRM_LVDS_DUAL_LINK_ODD_EVEN_PIXELS: when p1 is connected to the odd pixels > > + * port and p2 is connected to the even pixels port > > + * > > + */ > > +int drm_of_lvds_get_dual_link_configuration(const struct device_node *p1, > > + const struct device_node *p2) > > +{ > > + struct device_node *remote_p1 = NULL, *remote_p2 = NULL; > > + struct device_node *parent_p1 = NULL, *parent_p2 = NULL; > > There's no need to initialize those two variables. > > > + struct device_node *ep1 = NULL, *ep2 = NULL; > > + u32 reg_p1, reg_p2; > > + int ret = -EINVAL, remote_p1_pt, remote_p2_pt; > > Please split this last line, as it otherwise hides the initialization of > ret in the middle. > > > + > > + if (!p1 || !p2) > > + return ret; > > You can return -EINVAL directly. > > > > + if (of_property_read_u32(p1, "reg", ®_p1) || > > + of_property_read_u32(p2, "reg", ®_p2)) > > + return ret; > > Same here. > > > + parent_p1 = of_get_parent(p1); > > + parent_p2 = of_get_parent(p2); > > + if (!parent_p1 || !parent_p2) > > + goto done; > > + ep1 = of_graph_get_endpoint_by_regs(parent_p1, reg_p1, 0); > > + ep2 = of_graph_get_endpoint_by_regs(parent_p2, reg_p2, 0); > > + if (!ep1 || !ep2) > > + goto done; > > If you only support the first endpoint, this should be mentioned in the > documentation. Alternatively you could pass the endpoint nodes instead > of the port nodes, or you could pass the endpoint number. > > It's also a bit inefficient to use of_graph_get_endpoint_by_regs() when > you already have the port nodes. How about adding the following helper > function ? > > struct device_node *of_graph_get_port_endpoint(struct device_node *port, int reg) > { > struct device_node *endpoint = NULL; > > for_each_child_of_node(port, endpoint) { > u32 id; > > if (!of_node_name_eq(endpoint, "endpoint") || > continue; > > if (reg == -1) > return endpoint; > > if (of_property_read_u32(node, "reg", &id) < 0) > continue; > > if (reg == id) > return endpoint; > } > > return NULL; > } > > If you're concerned that adding a core helper would delay this patch > series, you could add it as a local helper, and move it to of_graph.h in > a second step. > > > + remote_p1 = of_graph_get_remote_port(ep1); > > + remote_p2 = of_graph_get_remote_port(ep2); > > + if (!remote_p1 || !remote_p2) > > + goto done; > > + remote_p1_pt = drm_of_lvds_get_port_pixels_type(remote_p1); > > + remote_p2_pt = drm_of_lvds_get_port_pixels_type(remote_p2); > > + /* > > + * A valid dual-lVDS bus is found when one remote port is marked with > > + * "dual-lvds-even-pixels", and the other remote port is marked with > > + * "dual-lvds-odd-pixels", bail out if the markers are not right. > > + */ > > + if (!remote_p1_pt || !remote_p2_pt || > > + remote_p1_pt + remote_p2_pt != DRM_OF_LVDS_EVEN + DRM_OF_LVDS_ODD) > > + goto done; > > + if (remote_p1_pt == DRM_OF_LVDS_EVEN) > > + /* The sink expects even pixels through the first port */ > > + ret = DRM_LVDS_DUAL_LINK_EVEN_ODD_PIXELS; > > + else > > + /* The sink expects odd pixels through the first port */ > > + ret = DRM_LVDS_DUAL_LINK_ODD_EVEN_PIXELS; > > + > > +done: > > + of_node_put(ep1); > > + of_node_put(ep2); > > + of_node_put(parent_p1); > > + of_node_put(parent_p2); > > + of_node_put(remote_p1); > > + of_node_put(remote_p2); > > + return ret; > > This is heavy, I would add blank lines to make the code easier to read. > > > +} > > +EXPORT_SYMBOL_GPL(drm_of_lvds_get_dual_link_configuration); > > diff --git a/include/drm/drm_bus_timings.h b/include/drm/drm_bus_timings.h > > new file mode 100644 > > index 0000000..db8a385 > > --- /dev/null > > +++ b/include/drm/drm_bus_timings.h > > @@ -0,0 +1,21 @@ > > +/* SPDX-License-Identifier: GPL-2.0 */ > > +#ifndef __DRM_BUS_TIMINGS__ > > +#define __DRM_BUS_TIMINGS__ > > + > > +struct device_node; > > + > > +#define DRM_LVDS_DUAL_LINK_EVEN_ODD_PIXELS 0 > > +#define DRM_LVDS_DUAL_LINK_ODD_EVEN_PIXELS 1 > > These should be documented with kerneldoc. How about also turning them > into an enum ? > > > + > > +#ifdef CONFIG_OF > > +int drm_of_lvds_get_dual_link_configuration(const struct device_node *p1, > > + const struct device_node *p2); > > +#else > > +int drm_of_lvds_get_dual_link_configuration(const struct device_node *p1, > > + const struct device_node *p2) > > +{ > > + return -EINVAL; > > +} > > +#endif > > + > > +#endif /* __DRM_BUS_TIMINGS__ */ > > -- > Regards, > > Laurent Pinchart -- Daniel Vetter Software Engineer, Intel Corporation http://blog.ffwll.ch