From patchwork Wed Mar 6 18:41:56 2019 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Laurent Pinchart X-Patchwork-Id: 10841591 X-Patchwork-Delegate: kieran@bingham.xyz Return-Path: Received: from mail.wl.linuxfoundation.org (pdx-wl-mail.web.codeaurora.org [172.30.200.125]) by pdx-korg-patchwork-2.web.codeaurora.org (Postfix) with ESMTP id 54ECE922 for ; Wed, 6 Mar 2019 18:42:10 +0000 (UTC) Received: from mail.wl.linuxfoundation.org (localhost [127.0.0.1]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id 404082EBA8 for ; Wed, 6 Mar 2019 18:42:10 +0000 (UTC) Received: by mail.wl.linuxfoundation.org (Postfix, from userid 486) id 31EC22EBBC; Wed, 6 Mar 2019 18:42:10 +0000 (UTC) X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on pdx-wl-mail.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-8.0 required=2.0 tests=BAYES_00,DKIM_SIGNED, DKIM_VALID,DKIM_VALID_AU,MAILING_LIST_MULTI,RCVD_IN_DNSWL_HI autolearn=ham version=3.3.1 Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id 90E662EBA8 for ; Wed, 6 Mar 2019 18:42:09 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1726903AbfCFSmJ (ORCPT ); Wed, 6 Mar 2019 13:42:09 -0500 Received: from perceval.ideasonboard.com ([213.167.242.64]:38938 "EHLO perceval.ideasonboard.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1727389AbfCFSmI (ORCPT ); Wed, 6 Mar 2019 13:42:08 -0500 Received: from pendragon.bb.dnainternet.fi (81-175-216-236.bb.dnainternet.fi [81.175.216.236]) by perceval.ideasonboard.com (Postfix) with ESMTPSA id 65678242; Wed, 6 Mar 2019 19:42:06 +0100 (CET) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=ideasonboard.com; s=mail; t=1551897726; bh=OauLMf75HrVVCqGzihomVcONa6Nab3dNUpN/NhSlBY0=; h=From:To:Cc:Subject:Date:From; b=cp2elqi9u8cJ5H74jXPqLZYSMQJ+a9G7OtrkgmM3B6Bjisdh/8kHVwFFOLkrfmFZj 4ex2PwRB5kEqIjjVmv2YVg7MtJcprLg2kym58lq1/AzCxfLlkdGKyjNv4XDDDlhYG4 RDxQjKmnYCXEp2qaeZHI85g/nVH+RCGMbGpXBils= From: Laurent Pinchart To: dri-devel@lists.freedesktop.org Cc: linux-renesas-soc@vger.kernel.org, Kevin Key , Kieran Bingham , Jacopo Mondi Subject: [PATCH v2] drm: rcar-du: Support panels connected directly to the DPAD outputs Date: Wed, 6 Mar 2019 20:41:56 +0200 Message-Id: <20190306184156.11764-1-laurent.pinchart+renesas@ideasonboard.com> X-Mailer: git-send-email 2.19.2 MIME-Version: 1.0 Sender: linux-renesas-soc-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-renesas-soc@vger.kernel.org X-Virus-Scanned: ClamAV using ClamSMTP The R-Car DU driver assumes that a bridge is always connected to the DU output. This is valid for the LVDS and HDMI outputs, but the DPAD outputs can be connected directly to a panel, in which case no bridge is available. To support this use case, detect whether the entities connected to the DU DPAD outputs are encoders or panels based on the number of ports of their DT node, and retrieve the corresponding type of DRM objects. For panels, additionally create panel bridge instances. Signed-off-by: Laurent Pinchart Tested-by: Kevin Key Reviewed-by: Kieran Bingham Reviewed-by: Jacopo Mondi --- drivers/gpu/drm/rcar-du/rcar_du_encoder.c | 54 ++++++++++++++++++++--- 1 file changed, 48 insertions(+), 6 deletions(-) Changes since v1: - Fix of_node_put() call in rcar_du_encoder_count_ports(), release the reference to ports, not to node diff --git a/drivers/gpu/drm/rcar-du/rcar_du_encoder.c b/drivers/gpu/drm/rcar-du/rcar_du_encoder.c index 8ee4e762f4e5..6c91753af7bc 100644 --- a/drivers/gpu/drm/rcar-du/rcar_du_encoder.c +++ b/drivers/gpu/drm/rcar-du/rcar_du_encoder.c @@ -28,13 +28,33 @@ static const struct drm_encoder_funcs encoder_funcs = { .destroy = drm_encoder_cleanup, }; +static unsigned int rcar_du_encoder_count_ports(struct device_node *node) +{ + struct device_node *ports; + struct device_node *port; + unsigned int num_ports = 0; + + ports = of_get_child_by_name(node, "ports"); + if (!ports) + ports = of_node_get(node); + + for_each_child_of_node(ports, port) { + if (of_node_name_eq(port, "port")) + num_ports++; + } + + of_node_put(ports); + + return num_ports; +} + int rcar_du_encoder_init(struct rcar_du_device *rcdu, enum rcar_du_output output, struct device_node *enc_node) { struct rcar_du_encoder *renc; struct drm_encoder *encoder; - struct drm_bridge *bridge = NULL; + struct drm_bridge *bridge; int ret; renc = devm_kzalloc(rcdu->dev, sizeof(*renc), GFP_KERNEL); @@ -48,11 +68,33 @@ int rcar_du_encoder_init(struct rcar_du_device *rcdu, dev_dbg(rcdu->dev, "initializing encoder %pOF for output %u\n", enc_node, output); - /* Locate the DRM bridge from the encoder DT node. */ - bridge = of_drm_find_bridge(enc_node); - if (!bridge) { - ret = -EPROBE_DEFER; - goto done; + /* + * Locate the DRM bridge from the DT node. For the DPAD outputs, if the + * DT node has a single port, assume that it describes a panel and + * create a panel bridge. + */ + if ((output == RCAR_DU_OUTPUT_DPAD0 || + output == RCAR_DU_OUTPUT_DPAD1) && + rcar_du_encoder_count_ports(enc_node) == 1) { + struct drm_panel *panel = of_drm_find_panel(enc_node); + + if (IS_ERR(panel)) { + ret = PTR_ERR(panel); + goto done; + } + + bridge = devm_drm_panel_bridge_add(rcdu->dev, panel, + DRM_MODE_CONNECTOR_DPI); + if (IS_ERR(bridge)) { + ret = PTR_ERR(bridge); + goto done; + } + } else { + bridge = of_drm_find_bridge(enc_node); + if (!bridge) { + ret = -EPROBE_DEFER; + goto done; + } } ret = drm_encoder_init(rcdu->ddev, encoder, &encoder_funcs,