From patchwork Wed Mar 29 13:16:07 2023 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Jagan Teki X-Patchwork-Id: 2826 Return-Path: X-Original-To: linux-amarula@patchwork.amarulasolutions.com Delivered-To: linux-amarula@patchwork.amarulasolutions.com Received: from mail-pj1-f72.google.com (mail-pj1-f72.google.com [209.85.216.72]) by ganimede.amarulasolutions.com (Postfix) with ESMTPS id 12D98414BB for ; Wed, 29 Mar 2023 15:17:55 +0200 (CEST) Received: by mail-pj1-f72.google.com with SMTP id ie21-20020a17090b401500b0023b4ba1e433sf4596129pjb.0 for ; Wed, 29 Mar 2023 06:17:54 -0700 (PDT) ARC-Seal: i=2; a=rsa-sha256; t=1680095873; cv=pass; d=google.com; s=arc-20160816; b=YR4QW7YCEco0RoNouD4ogDQmO0xVjZJVIVByy6nLm28tWnK4XPfhaUNx2D9NikEs81 MsgNeDaIArcqLiTxhBiQr11gexW+apsk+/JnoAZ5GGz99lkobcGW2luQniQQ9A92HvYw qf9biqmp64dEgvNzasv6QoqzYgrOMsTPDJSdsXp66UWz2W13BKkca/0HUHumfG+6o8O9 XAs6QzDglyyHhIPyoNtSuifgooNqfyCApJe4OZyHMMxkMx3gCYY2LfcQCfUQYaAsIybl bKFu8z8moxwXGaE1Nw7V2QQ1tHGLw+5ug6cAb/jXPsKPW3kv+3w3Y6KRuFj97hB3fcpp Yv4w== ARC-Message-Signature: i=2; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20160816; h=list-unsubscribe:list-archive:list-help:list-post:list-id :mailing-list:precedence:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:dkim-signature; bh=x22X+Fsg30ivCiu1NZUzY1vs90PHG+XI6R6mjyjXpjk=; b=uUnlvaUSBgcA8qlvjWML7aW3lhlEhgSOHV69XzmthRUFh6eWA5QTW83LOFYjCQxV34 1oBGLxZ9qQ2Bn3ey/UR0uQ2IQAunMS6y4E7RUfpPutvJusGHOE1yu5RFmFyJNivF/c85 Gv7kBplq7pWLxjI3FPjcDstN17D0Rwgp/TxbSIO8jcpREe1q+BW7WRafFnRvw6/cllJ7 RFloa0jk2Pbh/ALHVTinvYP44D4TXkLaUIMrg4DgZgBsgWZSuJkn9sYBBjPLyQED7gZ+ cNyB9D1ECfG6QLW3DjBjqFBdoQeA9xlL0nZfta3koOhBp1MQcCkzxCquH2qlLQhOVwnN 7uGg== ARC-Authentication-Results: i=2; mx.google.com; dkim=pass header.i=@amarulasolutions.com header.s=google header.b="lCODPpW/"; spf=pass (google.com: domain of jagan@amarulasolutions.com designates 209.85.220.41 as permitted sender) smtp.mailfrom=jagan@amarulasolutions.com; dmarc=pass (p=NONE sp=NONE dis=NONE) header.from=amarulasolutions.com DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=amarulasolutions.com; s=google; t=1680095873; h=list-unsubscribe:list-archive:list-help:list-post:list-id :mailing-list:precedence:x-original-authentication-results :x-original-sender:mime-version:references:in-reply-to:message-id :date:subject:cc:to:from:from:to:cc:subject:date:message-id:reply-to; bh=x22X+Fsg30ivCiu1NZUzY1vs90PHG+XI6R6mjyjXpjk=; b=V701ekRkanH/NS73qbnBu23nqCqDVI1RrfRzv+mgtRsZSoXznillAFeLxOsN1GtBmf lPOwKOLg1+rAMgld/iOPyIUgzUN8aQZp9Qoj0FUszi6N9sDwe1/VcbMVfp0N0bpbKqBd Zb5wwbZSXx+H/+ncLGezx+9IbC4PH6BD37rqg= X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20210112; t=1680095873; h=list-unsubscribe:list-archive:list-help:list-post :x-spam-checked-in-group:list-id:mailing-list:precedence :x-original-authentication-results:x-original-sender:mime-version :references:in-reply-to:message-id:date:subject:cc:to:from :x-gm-message-state:from:to:cc:subject:date:message-id:reply-to; bh=x22X+Fsg30ivCiu1NZUzY1vs90PHG+XI6R6mjyjXpjk=; b=N+ernY695l5VlouETK3lPxhyZY43ZgfD2mQAj06EgsAiOXDBfGJezw2TEKZYJ7G9Md P2PsyXYJHGVZbYwcwkf3Jamwjs4RtRiRtDBUqVYU5sjMZ4RkbMPMkd/H0hwfw5jkevSO ux68VyxPGxJ+6axfLV9vIUwGtNUEzfy+In489qS63UeHd398ISA6KHgBm2btGcIrWt/o z9SgVnPDh3sJCrHvmp+G1ys26lajdV8wtQic5Ss4GJkrdRDp3XA+nLlJMfVxWXOqVe44 mOlyT2mjJkk0dvsgpvO2tVF2MpgQ21BMsShBfOXSUk4wd79BxFAWpC/BSvPE0h71pGIm Q13A== X-Gm-Message-State: AAQBX9evCjczswPXMPcc+qTG5M1MPjJFh2EESPkFvjXpnC4B+1Hzsasl NvXQcisdr+ycNnK7MKOujsR829QL X-Google-Smtp-Source: AKy350Y4lWnwPhVlcLIyGpxCleUnE5JVAN0FFd8zdBqufYYWXw/83he2rPWkcmDTWcUsSD9yns8iyA== X-Received: by 2002:a17:902:f693:b0:1a0:5058:f629 with SMTP id l19-20020a170902f69300b001a05058f629mr7769482plg.13.1680095873588; Wed, 29 Mar 2023 06:17:53 -0700 (PDT) X-BeenThere: linux-amarula@amarulasolutions.com Received: by 2002:a17:90b:4d8f:b0:234:2ef4:2e9 with SMTP id oj15-20020a17090b4d8f00b002342ef402e9ls2221505pjb.0.-pod-control-gmail; Wed, 29 Mar 2023 06:17:52 -0700 (PDT) X-Received: by 2002:a17:90b:3b4f:b0:234:2485:6743 with SMTP id ot15-20020a17090b3b4f00b0023424856743mr21070772pjb.3.1680095872348; Wed, 29 Mar 2023 06:17:52 -0700 (PDT) ARC-Seal: i=1; a=rsa-sha256; t=1680095872; cv=none; d=google.com; s=arc-20160816; b=ohsKHJPXdpk7zFssp069OKUlVrf62O8x4uoWbkhJkbgTKdsYQxqxxYVIUjffuqHwYz so78bT2eXMqAmQSKYWqqykl8MuAxYmlGOwGo0wiLXC3Reuz2hA83C4HP+Hkgi3J08vE0 hgWa3HYwHpYRZdQxZAsHsggoQJGRlVGREL4818capXom4Qmqyn0YSaBuygUdvmcKYm9l mhhtFwVVZCk3DE7glxwitijmyfLzjVp1VGUAZq7W7JoTf6VJ9HSNRzwXjILffnj3KahL YIl/8EJJH8wobKCe0EWS5YJGzlOIAxm1lP2/ateDyCbUDqi0DMw0A5z9V+ZpgPz6OStJ 4FFg== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20160816; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:dkim-signature; bh=X83RR+xeESh5armnw5mGiS+y5yBuHI5QecAlLL/Hrnk=; b=Rox8BXxtowTjzigS0+OKzfa/wm+kTtXbLrUlX6DZRihrkaRBKCamZHzuANiAa7nSXr qjNndDGJJK7xE5B9SbgJrt5YKNRKXLoM89qfq+bv2g2yirmSvNCYrjMmXyhDdtUvOn8u fzi5/Ywry0ON4gQG3mPcmGkHZQLTGGziJwGJxhL/7uSQgrSU12dH8GikYbnrsvwZI46B ES9cIXBhKUJMVTMX9S6+Sb3pKWVzMNRv9YzAxj3ZK0aSldNP2va0LX7JLAS/dpCb7Esc PQ1ygQKTNUD9oGKnQy0aWRIJZjaeY9GDtdkvjx46PPTSAgACRnSONYigR1gn4BfRvjri mQXQ== ARC-Authentication-Results: i=1; mx.google.com; dkim=pass header.i=@amarulasolutions.com header.s=google header.b="lCODPpW/"; spf=pass (google.com: domain of jagan@amarulasolutions.com designates 209.85.220.41 as permitted sender) smtp.mailfrom=jagan@amarulasolutions.com; dmarc=pass (p=NONE sp=NONE dis=NONE) header.from=amarulasolutions.com Received: from mail-sor-f41.google.com (mail-sor-f41.google.com. [209.85.220.41]) by mx.google.com with SMTPS id ay6-20020a17090b030600b0023f8962e98asor850074pjb.13.2023.03.29.06.17.52 for (Google Transport Security); Wed, 29 Mar 2023 06:17:52 -0700 (PDT) Received-SPF: pass (google.com: domain of jagan@amarulasolutions.com designates 209.85.220.41 as permitted sender) client-ip=209.85.220.41; X-Received: by 2002:a17:90b:1e43:b0:23d:1b50:1ebe with SMTP id pi3-20020a17090b1e4300b0023d1b501ebemr22546115pjb.27.1680095871927; Wed, 29 Mar 2023 06:17:51 -0700 (PDT) Received: from localhost.localdomain ([2405:201:c00a:a047:206d:4722:c4fa:e845]) by smtp.gmail.com with ESMTPSA id s16-20020a17090b071000b0023f5c867f82sm1400192pjz.41.2023.03.29.06.17.44 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Wed, 29 Mar 2023 06:17:51 -0700 (PDT) From: Jagan Teki To: Dave Stevenson , Maxime Ripard , Maarten Lankhorst , Thomas Zimmermann , David Airlie , Daniel Vetter , Andrzej Hajda , Neil Armstrong , Robert Foss , Chen-Yu Tsai , Jernej Skrabec , Samuel Holland , Sam Ravnborg , Rob Herring , Krzysztof Kozlowski Cc: linux-arm-kernel@lists.infradead.org, linux-sunxi@lists.linux.dev, devicetree@vger.kernel.org, dri-devel@lists.freedesktop.org, Marek Vasut , linux-amarula , Jagan Teki Subject: [PATCH v7 01/12] drm: of: Lookup if child node has DSI panel or bridge Date: Wed, 29 Mar 2023 18:46:07 +0530 Message-Id: <20230329131615.1328366-2-jagan@amarulasolutions.com> X-Mailer: git-send-email 2.25.1 In-Reply-To: <20230329131615.1328366-1-jagan@amarulasolutions.com> References: <20230329131615.1328366-1-jagan@amarulasolutions.com> MIME-Version: 1.0 X-Original-Sender: jagan@amarulasolutions.com X-Original-Authentication-Results: mx.google.com; dkim=pass header.i=@amarulasolutions.com header.s=google header.b="lCODPpW/"; spf=pass (google.com: domain of jagan@amarulasolutions.com designates 209.85.220.41 as permitted sender) smtp.mailfrom=jagan@amarulasolutions.com; dmarc=pass (p=NONE sp=NONE dis=NONE) header.from=amarulasolutions.com Content-Type: text/plain; charset="UTF-8" Precedence: list Mailing-list: list linux-amarula@amarulasolutions.com; contact linux-amarula+owners@amarulasolutions.com List-ID: X-Spam-Checked-In-Group: linux-amarula@amarulasolutions.com X-Google-Group-Id: 476853432473 List-Post: , List-Help: , List-Archive: List-Unsubscribe: , Devices can also be child nodes when we also control that device through the upstream device (ie, MIPI-DCS for a MIPI-DSI device). Unlike the drm_of_find_panel_or_bridge helper it requires a special case to lookup a child node of the given parent that isn't either port or ports. Lookup for a child DSI node of the given parent that isn't either port or ports. If it is found then it will directly find the panel or bridge otherwise lookup for the child node with a given port and endpoint number as drm_of_find_panel_or_bridge does. Supporting this feature via existing drm_of_find_panel_or_bridge found several issues while handling usecases. Here is the previously failed attempt of similar and the same has been reverted later. commit <80253168dbfd> ("drm: of: Lookup if child node has panel or bridge") So, add a separate helper to handle this DSI use case. An example of the downstream panel represented as a child node: dsi { compatible = "allwinner,sun6i-a31-mipi-dsi"; port { dsi_in_tcon0: endpoint { remote-endpoint = ; }; }; panel@0 { compatible = "feixin,k101-im2ba02"; reg = <0>; }; }; An example of the downstream bridge represented as a port node: dsi { compatible = "allwinner,sun6i-a31-mipi-dsi"; port { dsi_in_tcon0: endpoint@0 { reg = <0>; remote-endpoint = ; }; dsi_out_bridge: endpoint@1 { reg = <1>; remote-endpoint = <&bridge_in_dsi>; }; }; bridge: bridge@0 { compatible = "chipone,icn6211"; reg = <0>; ports { bridge_in: port@0 { reg = <0>; bridge_in_dsi: endpoint { remote-endpoint = <&dsi_out_bridge>; }; }; bridge_out: port@1 { reg = <1>; bridge_out_panel: endpoint { remote-endpoint = <&panel_out_bridge>; }; }; }; }; }; An example of the downstream bridge represented as a ports node: i2c4 { bridge@2c { compatible = "ti,sn65dsi84"; ports { port@0 { reg = <0>; bridge_in_dsi: endpoint { remote-endpoint = <&dsi_out_bridge>; data-lanes = <1 2>; }; }; port@2 { reg = <2>; bridge_out_panel: endpoint { remote-endpoint = <&panel_out_bridge>; }; }; }; }; }; dsi { compatible = "fsl,imx8mm-mipi-dsim"; ports { port@0 { reg = <0>; dsi_in_lcdif: endpoint@0 { reg = <0>; remote-endpoint = <&lcdif_out_dsi>; }; }; port@1 { reg = <1>; dsi_out_bridge: endpoint { remote-endpoint = <&bridge_in_dsi>; }; }; }; }; An example of the downstream bridge represented as a child node, but whose host neither a port nor a ports: dsi0 { compatible = "ste,mcde-dsi"; panel@0 { reg = <0>; }; }; In, summary the DSI downstream devices are likely to be Panel, Bridge and I2C-Configured Bridge. It is possible to connect all three devices using upstream OF-graph port or ports node however only Panel and Bridge are possible to connect via child node but not possible to connect I2C-Configured Bridge via child node since I2C-Configure bridges are child of I2C not upstream DSI hosts and it must represent them via port or ports with endpoint linking. This indeed means, the OF-graph port or ports representation is mandatory for I2C-Configured DSI bridges. This patch tries to add an OF-graph port or ports representation detection code on top of existing child node detection. Overall, this patch makes use of a single standardized DRM helper for a given DSI pipeline representing downstream devices as child or OF-graph port or OF-graph ports node. Signed-off-by: Jagan Teki --- Changes for v7: - new patch drivers/gpu/drm/drm_of.c | 112 ++++++++++++++++++++++++++++++++------- include/drm/drm_of.h | 12 +++++ 2 files changed, 104 insertions(+), 20 deletions(-) diff --git a/drivers/gpu/drm/drm_of.c b/drivers/gpu/drm/drm_of.c index 177b600895d3..87cfd685318a 100644 --- a/drivers/gpu/drm/drm_of.c +++ b/drivers/gpu/drm/drm_of.c @@ -217,6 +217,35 @@ int drm_of_encoder_active_endpoint(struct device_node *node, } EXPORT_SYMBOL_GPL(drm_of_encoder_active_endpoint); +static int of_drm_find_panel_or_bridge(struct device_node *remote, + struct drm_panel **panel, + struct drm_bridge **bridge) +{ + int ret = -EPROBE_DEFER; + + if (panel) { + *panel = of_drm_find_panel(remote); + if (!IS_ERR(*panel)) + ret = 0; + else + *panel = NULL; + } + + /* No panel found yet, check for a bridge next. */ + if (bridge) { + if (ret) { + *bridge = of_drm_find_bridge(remote); + if (*bridge) + ret = 0; + } else { + *bridge = NULL; + } + } + + of_node_put(remote); + return ret; +} + /** * drm_of_find_panel_or_bridge - return connected panel or bridge device * @np: device tree node containing encoder output ports @@ -239,7 +268,6 @@ int drm_of_find_panel_or_bridge(const struct device_node *np, struct drm_panel **panel, struct drm_bridge **bridge) { - int ret = -EPROBE_DEFER; struct device_node *remote; if (!panel && !bridge) @@ -260,30 +288,74 @@ int drm_of_find_panel_or_bridge(const struct device_node *np, if (!remote) return -ENODEV; - if (panel) { - *panel = of_drm_find_panel(remote); - if (!IS_ERR(*panel)) - ret = 0; - else - *panel = NULL; - } + return of_drm_find_panel_or_bridge(remote, panel, bridge); +} +EXPORT_SYMBOL_GPL(drm_of_find_panel_or_bridge); - /* No panel found yet, check for a bridge next. */ - if (bridge) { - if (ret) { - *bridge = of_drm_find_bridge(remote); - if (*bridge) - ret = 0; - } else { - *bridge = NULL; - } +/** + * drm_of_dsi_find_panel_or_bridge - return connected DSI panel or bridge device + * @np: device tree node containing encoder output ports + * @port: port in the device tree node + * @endpoint: endpoint in the device tree node + * @panel: pointer to hold returned drm_panel + * @bridge: pointer to hold returned drm_bridge + * + * Lookup for a child DSI node of the given parent that isn't either port + * or ports. If it is found then it will directly find the panel or bridge + * otherwise lookup for the child node with a given port and endpoint number + * as drm_of_find_panel_or_bridge does. + * + * Lookup a given child DSI node or a DT node's port and endpoint number, + * find the connected node and return either the associated struct drm_panel + * or drm_bridge device. Either @panel or @bridge must not be NULL. + * + * Returns zero if successful, or one of the standard error codes if it fails. + */ +int drm_of_dsi_find_panel_or_bridge(const struct device_node *np, + int port, int endpoint, + struct drm_panel **panel, + struct drm_bridge **bridge) +{ + struct device_node *remote; + + if (!panel && !bridge) + return -EINVAL; + if (panel) + *panel = NULL; + /** + * Devices can also be child nodes when we also control that device + * through the upstream device (ie, MIPI-DCS for a MIPI-DSI device). + * + * Lookup for a child node of the given parent that isn't either port + * or ports. + */ + for_each_available_child_of_node(np, remote) { + if (of_node_name_eq(remote, "port") || + of_node_name_eq(remote, "ports")) + continue; + + goto of_find_panel_or_bridge; } - of_node_put(remote); - return ret; + /* + * of_graph_get_remote_node() produces a noisy error message if port + * node isn't found and the absence of the port is a legit case here, + * so at first we silently check whether graph presents in the + * device-tree node. + */ + if (!of_graph_is_present(np)) + return -ENODEV; + + remote = of_graph_get_remote_node(np, port, endpoint); + +of_find_panel_or_bridge: + if (!remote) + return -ENODEV; + + return of_drm_find_panel_or_bridge(remote, panel, bridge); } -EXPORT_SYMBOL_GPL(drm_of_find_panel_or_bridge); +EXPORT_SYMBOL_GPL(drm_of_dsi_find_panel_or_bridge); enum drm_of_lvds_pixels { DRM_OF_LVDS_EVEN = BIT(0), diff --git a/include/drm/drm_of.h b/include/drm/drm_of.h index 082a6e980d01..5e0d958121ce 100644 --- a/include/drm/drm_of.h +++ b/include/drm/drm_of.h @@ -49,6 +49,10 @@ int drm_of_find_panel_or_bridge(const struct device_node *np, int port, int endpoint, struct drm_panel **panel, struct drm_bridge **bridge); +int drm_of_dsi_find_panel_or_bridge(const struct device_node *np, + int port, int endpoint, + struct drm_panel **panel, + struct drm_bridge **bridge); int drm_of_lvds_get_dual_link_pixel_order(const struct device_node *port1, const struct device_node *port2); int drm_of_lvds_get_data_mapping(const struct device_node *port); @@ -101,6 +105,14 @@ static inline int drm_of_find_panel_or_bridge(const struct device_node *np, return -EINVAL; } +static inline int drm_of_dsi_find_panel_or_bridge(const struct device_node *np, + int port, int endpoint, + struct drm_panel **panel, + struct drm_bridge **bridge) +{ + return -EINVAL; +} + static inline int drm_of_lvds_get_dual_link_pixel_order(const struct device_node *port1, const struct device_node *port2)