From patchwork Fri Sep 1 09:36:33 2017 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Linus Walleij X-Patchwork-Id: 111469 Delivered-To: patch@linaro.org Received: by 10.140.95.112 with SMTP id h103csp785410qge; Fri, 1 Sep 2017 02:36:58 -0700 (PDT) X-Received: by 10.99.112.20 with SMTP id l20mr1712978pgc.146.1504258618612; Fri, 01 Sep 2017 02:36:58 -0700 (PDT) ARC-Seal: i=1; a=rsa-sha256; t=1504258618; cv=none; d=google.com; s=arc-20160816; b=ShWGe73szb1ukLY8tAFynPtd7I7A3+l6QUfEwqL8xaWipjKCYnS1aLMgBOaKCWx/Vy lO5MZLjNkyNSxGc+jzaleRkSuvoFy3DLX/bOfl/+AsGGzyWEYqDNjh17P9GAdOkgLw2v 3tdeK/j6a/FT1WeDFvPlIbCDvWsPjEBTN1eUGK5TRStKDvkgTXRZHBv3iXIdKbxt7iM+ dMYUGXRBEnjH4VQllzLoKJcMqJLaVF6CQCPZxKfBHc35PD0MpjYVf0krQb7qnETvFKGH vwjYxKvROOdQLPc6+XPHqoqMo7ElzN8tWZ2obnkWf/5XomAmz8vfqWtLELKhH9XIe10Z /S7w== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20160816; h=sender:errors-to:content-transfer-encoding:mime-version :list-subscribe:list-help:list-post:list-archive:list-unsubscribe :list-id:precedence:cc:references:in-reply-to:message-id:date :subject:to:from:dkim-signature:delivered-to :arc-authentication-results; bh=RFciHtGtbhp2utO2y8ZY+mTvjFHWH5dcE0nMjsmd9kU=; b=pf/0n5OO4iUKO2tzjbITP0hs9r8cIq7dGE0sUDeZ5mdaGdqG/Ce9UPowpqfvpOlHNS o1EU1xTUQ7oM7K9weA4C5hX4hTxmOswq5h8C558uZ9YQW5vF1gYwRE8u9OIlshyn+U8e ZUiJligLY2k2nVZog8adCAoQYUjaA+ToHzXhf/On+bH6mucmjxr+RuNG6kaqc9Ai092P K3wtVxbSUQdklUCDKQiZakqmZZ3bVFwMJmquQ9vKlJW5otiA9suWMcE0IlzoaCzXeu7T ORYOwRzoUAHHQAehtFsb5R5o9NS62nIoaDtrkDbok0DRdbmyWPh4B0kKXe9iVUNQPVB9 HtAw== ARC-Authentication-Results: i=1; mx.google.com; dkim=neutral (body hash did not verify) header.i=@linaro.org header.s=google header.b=GnhvN1lC; spf=pass (google.com: best guess record for domain of dri-devel-bounces@lists.freedesktop.org designates 131.252.210.177 as permitted sender) smtp.mailfrom=dri-devel-bounces@lists.freedesktop.org; dmarc=fail (p=NONE sp=NONE dis=NONE) header.from=linaro.org Return-Path: Received: from gabe.freedesktop.org (gabe.freedesktop.org. [131.252.210.177]) by mx.google.com with ESMTPS id b15si1353788plk.231.2017.09.01.02.36.58 (version=TLS1_2 cipher=ECDHE-RSA-AES128-GCM-SHA256 bits=128/128); Fri, 01 Sep 2017 02:36:58 -0700 (PDT) Received-SPF: pass (google.com: best guess record for domain of dri-devel-bounces@lists.freedesktop.org designates 131.252.210.177 as permitted sender) client-ip=131.252.210.177; Authentication-Results: mx.google.com; dkim=neutral (body hash did not verify) header.i=@linaro.org header.s=google header.b=GnhvN1lC; spf=pass (google.com: best guess record for domain of dri-devel-bounces@lists.freedesktop.org designates 131.252.210.177 as permitted sender) smtp.mailfrom=dri-devel-bounces@lists.freedesktop.org; dmarc=fail (p=NONE sp=NONE dis=NONE) header.from=linaro.org Received: from gabe.freedesktop.org (localhost [127.0.0.1]) by gabe.freedesktop.org (Postfix) with ESMTP id C30716E807; Fri, 1 Sep 2017 09:36:57 +0000 (UTC) X-Original-To: dri-devel@lists.freedesktop.org Delivered-To: dri-devel@lists.freedesktop.org Received: from mail-lf0-x233.google.com (mail-lf0-x233.google.com [IPv6:2a00:1450:4010:c07::233]) by gabe.freedesktop.org (Postfix) with ESMTPS id EC0556E807 for ; Fri, 1 Sep 2017 09:36:55 +0000 (UTC) Received: by mail-lf0-x233.google.com with SMTP id d17so7315624lfe.1 for ; Fri, 01 Sep 2017 02:36:55 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=linaro.org; s=google; h=from:to:cc:subject:date:message-id:in-reply-to:references; bh=6iPyxDqwcFfmHKeH+rNjrVtYWTxyy42+NYJO47DG1Is=; b=GnhvN1lC2T88trtKDNmiH3E9yCdtDB02B/AyuflVoUUxwpI3uS51fL1iUy7zokr3ZB nw7PV3uEJvRZG8JREVrjQyWRKE3D80ysNwgfCiUx0uRYWizX3hwVNbgkDgDKG+7vLUWG rLN74Twh8cQbqYfHkM16cwbt+nWWN0PQxLPUs= X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:from:to:cc:subject:date:message-id:in-reply-to :references; bh=6iPyxDqwcFfmHKeH+rNjrVtYWTxyy42+NYJO47DG1Is=; b=R9QUL+CkyNYJ458U6oUsSIG47LEq9zvab3zpOTJh3YWO1N/fZX308dy6JQ3q5yDw0v DsWrxukB+ksIZABsi7ktq/Ahyj/9Hwrzo/39mttgP/2NJDC6PT1FCYAJMXQLrk+JBzQj PVsWCdSSoGzymQVHgzMe+Qm7T4ILyNcIFp6aBbeGN1UFsMde8HUFpaM0lZj2Bhfd7Ath 2HHWU7eDPwNV/vmsg88tsZiejwiV8iIpDbuAOpPluTc1cW7iwVxOH0f75yS/HbB/Ge1b gV1OUH2bzO46PE5qHGEsfwzcDvDRlApphWlzVL7slc0+B3V+rK4Q0Ug5Y5V4rTLbtvGP 4oOQ== X-Gm-Message-State: AHPjjUjBI2KoxmHxBFu61uYKRZwPTxSDJ49ZCkXT95deuaBViAtxrVIr tY664yX5z3uWPWBy X-Google-Smtp-Source: ADKCNb5mHE7pPYwyN7bRlGSBHXo/uf5Ca/XAvkhO+J1BjJRBkgcoSnNzS6ZbGdmMjWfZALIkfXXH6g== X-Received: by 10.25.23.100 with SMTP id n97mr631907lfi.242.1504258614080; Fri, 01 Sep 2017 02:36:54 -0700 (PDT) Received: from genomnajs.ideon.se ([85.235.10.227]) by smtp.gmail.com with ESMTPSA id x18sm328588ljd.85.2017.09.01.02.36.52 (version=TLS1_2 cipher=ECDHE-RSA-CHACHA20-POLY1305 bits=256/256); Fri, 01 Sep 2017 02:36:53 -0700 (PDT) From: Linus Walleij To: Daniel Vetter , Jani Nikula , Sean Paul , Eric Anholt Subject: [PATCH 3/7 v2] drm/pl111: Replace custom connector with panel bridge Date: Fri, 1 Sep 2017 11:36:33 +0200 Message-Id: <20170901093637.4041-4-linus.walleij@linaro.org> X-Mailer: git-send-email 2.13.5 In-Reply-To: <20170901093637.4041-1-linus.walleij@linaro.org> References: <20170901093637.4041-1-linus.walleij@linaro.org> Cc: linux-arm-kernel@lists.infradead.org, dri-devel@lists.freedesktop.org X-BeenThere: dri-devel@lists.freedesktop.org X-Mailman-Version: 2.1.18 Precedence: list List-Id: Direct Rendering Infrastructure - Development List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , MIME-Version: 1.0 Errors-To: dri-devel-bounces@lists.freedesktop.org Sender: "dri-devel" This replaces the custom connector in the PL111 with the panel bridge helper. This works nicely for all standard panels, but since there are several PL11x-based systems that will need to use the dumb VGA connector bridge we use drm_of_find_panel_or_bridge() and make some headroom for dealing with bridges that are not panels as well, and drop a TODO in the code. Signed-off-by: Linus Walleij --- ChangeLog v1->v2: - Remove the panel [un]prepare() and [en|dis]able() calls from the display driver, since this is now handled by the bridge. --- drivers/gpu/drm/pl111/Kconfig | 3 +- drivers/gpu/drm/pl111/Makefile | 3 +- drivers/gpu/drm/pl111/pl111_connector.c | 127 -------------------------------- drivers/gpu/drm/pl111/pl111_display.c | 16 ++-- drivers/gpu/drm/pl111/pl111_drm.h | 18 ++--- drivers/gpu/drm/pl111/pl111_drv.c | 62 +++++++++++----- 6 files changed, 60 insertions(+), 169 deletions(-) delete mode 100644 drivers/gpu/drm/pl111/pl111_connector.c diff --git a/drivers/gpu/drm/pl111/Kconfig b/drivers/gpu/drm/pl111/Kconfig index bbfba87cd1a8..e5e2abd66491 100644 --- a/drivers/gpu/drm/pl111/Kconfig +++ b/drivers/gpu/drm/pl111/Kconfig @@ -6,7 +6,8 @@ config DRM_PL111 select DRM_KMS_HELPER select DRM_KMS_CMA_HELPER select DRM_GEM_CMA_HELPER - select DRM_PANEL + select DRM_BRIDGE + select DRM_PANEL_BRIDGE select VT_HW_CONSOLE_BINDING if FRAMEBUFFER_CONSOLE help Choose this option for DRM support for the PL111 CLCD controller. diff --git a/drivers/gpu/drm/pl111/Makefile b/drivers/gpu/drm/pl111/Makefile index 59483d610ef5..c5f8f9684848 100644 --- a/drivers/gpu/drm/pl111/Makefile +++ b/drivers/gpu/drm/pl111/Makefile @@ -1,5 +1,4 @@ -pl111_drm-y += pl111_connector.o \ - pl111_display.o \ +pl111_drm-y += pl111_display.o \ pl111_drv.o pl111_drm-$(CONFIG_DEBUG_FS) += pl111_debugfs.o diff --git a/drivers/gpu/drm/pl111/pl111_connector.c b/drivers/gpu/drm/pl111/pl111_connector.c deleted file mode 100644 index 3f213d7e7692..000000000000 --- a/drivers/gpu/drm/pl111/pl111_connector.c +++ /dev/null @@ -1,127 +0,0 @@ -/* - * (C) COPYRIGHT 2012-2013 ARM Limited. All rights reserved. - * - * Parts of this file were based on sources as follows: - * - * Copyright (c) 2006-2008 Intel Corporation - * Copyright (c) 2007 Dave Airlie - * Copyright (C) 2011 Texas Instruments - * - * This program is free software and is provided to you under the terms of the - * GNU General Public License version 2 as published by the Free Software - * Foundation, and any use by you of this program is subject to the terms of - * such GNU licence. - * - */ - -/** - * pl111_drm_connector.c - * Implementation of the connector functions for PL111 DRM - */ -#include -#include -#include -#include - -#include -#include -#include -#include -#include - -#include "pl111_drm.h" - -static void pl111_connector_destroy(struct drm_connector *connector) -{ - struct pl111_drm_connector *pl111_connector = - to_pl111_connector(connector); - - if (pl111_connector->panel) - drm_panel_detach(pl111_connector->panel); - - drm_connector_unregister(connector); - drm_connector_cleanup(connector); -} - -static enum drm_connector_status pl111_connector_detect(struct drm_connector - *connector, bool force) -{ - struct pl111_drm_connector *pl111_connector = - to_pl111_connector(connector); - - return (pl111_connector->panel ? - connector_status_connected : - connector_status_disconnected); -} - -static int pl111_connector_helper_get_modes(struct drm_connector *connector) -{ - struct pl111_drm_connector *pl111_connector = - to_pl111_connector(connector); - - if (!pl111_connector->panel) - return 0; - - return drm_panel_get_modes(pl111_connector->panel); -} - -const struct drm_connector_funcs connector_funcs = { - .fill_modes = drm_helper_probe_single_connector_modes, - .destroy = pl111_connector_destroy, - .detect = pl111_connector_detect, - .dpms = drm_atomic_helper_connector_dpms, - .reset = drm_atomic_helper_connector_reset, - .atomic_duplicate_state = drm_atomic_helper_connector_duplicate_state, - .atomic_destroy_state = drm_atomic_helper_connector_destroy_state, -}; - -const struct drm_connector_helper_funcs connector_helper_funcs = { - .get_modes = pl111_connector_helper_get_modes, -}; - -/* Walks the OF graph to find the panel node and then asks DRM to look - * up the panel. - */ -static struct drm_panel *pl111_get_panel(struct device *dev) -{ - struct device_node *endpoint, *panel_node; - struct device_node *np = dev->of_node; - struct drm_panel *panel; - - endpoint = of_graph_get_next_endpoint(np, NULL); - if (!endpoint) { - dev_err(dev, "no endpoint to fetch panel\n"); - return NULL; - } - - /* don't proceed if we have an endpoint but no panel_node tied to it */ - panel_node = of_graph_get_remote_port_parent(endpoint); - of_node_put(endpoint); - if (!panel_node) { - dev_err(dev, "no valid panel node\n"); - return NULL; - } - - panel = of_drm_find_panel(panel_node); - of_node_put(panel_node); - - return panel; -} - -int pl111_connector_init(struct drm_device *dev) -{ - struct pl111_drm_dev_private *priv = dev->dev_private; - struct pl111_drm_connector *pl111_connector = &priv->connector; - struct drm_connector *connector = &pl111_connector->connector; - - drm_connector_init(dev, connector, &connector_funcs, - DRM_MODE_CONNECTOR_DPI); - drm_connector_helper_add(connector, &connector_helper_funcs); - - pl111_connector->panel = pl111_get_panel(dev->dev); - if (pl111_connector->panel) - drm_panel_attach(pl111_connector->panel, connector); - - return 0; -} - diff --git a/drivers/gpu/drm/pl111/pl111_display.c b/drivers/gpu/drm/pl111/pl111_display.c index c6ca4f1bbd49..59cdb8f49bb1 100644 --- a/drivers/gpu/drm/pl111/pl111_display.c +++ b/drivers/gpu/drm/pl111/pl111_display.c @@ -21,7 +21,6 @@ #include #include -#include #include #include @@ -93,7 +92,7 @@ static void pl111_display_enable(struct drm_simple_display_pipe *pipe, struct pl111_drm_dev_private *priv = drm->dev_private; const struct drm_display_mode *mode = &cstate->mode; struct drm_framebuffer *fb = plane->state->fb; - struct drm_connector *connector = &priv->connector.connector; + struct drm_connector *connector = priv->connector; u32 cntl; u32 ppl, hsw, hfp, hbp; u32 lpp, vsw, vfp, vbp; @@ -155,8 +154,6 @@ static void pl111_display_enable(struct drm_simple_display_pipe *pipe, writel(0, priv->regs + CLCD_TIM3); - drm_panel_prepare(priv->connector.panel); - /* Enable and Power Up */ cntl = CNTL_LCDEN | CNTL_LCDTFT | CNTL_LCDPWR | CNTL_LCDVCOMP(1); @@ -203,8 +200,6 @@ static void pl111_display_enable(struct drm_simple_display_pipe *pipe, writel(cntl, priv->regs + CLCD_PL111_CNTL); - drm_panel_enable(priv->connector.panel); - drm_crtc_vblank_on(crtc); } @@ -216,13 +211,9 @@ void pl111_display_disable(struct drm_simple_display_pipe *pipe) drm_crtc_vblank_off(crtc); - drm_panel_disable(priv->connector.panel); - /* Disable and Power Down */ writel(0, priv->regs + CLCD_PL111_CNTL); - drm_panel_unprepare(priv->connector.panel); - clk_disable_unprepare(priv->clk); } @@ -457,9 +448,12 @@ int pl111_display_init(struct drm_device *drm) ret = drm_simple_display_pipe_init(drm, &priv->pipe, &pl111_display_funcs, formats, ARRAY_SIZE(formats), - &priv->connector.connector); + priv->connector); if (ret) return ret; + /* We need the encoder to attach the bridge */ + priv->encoder = &priv->pipe.encoder; + return 0; } diff --git a/drivers/gpu/drm/pl111/pl111_drm.h b/drivers/gpu/drm/pl111/pl111_drm.h index a97f303f6833..8804af0f8997 100644 --- a/drivers/gpu/drm/pl111/pl111_drm.h +++ b/drivers/gpu/drm/pl111/pl111_drm.h @@ -21,21 +21,23 @@ #include #include +#include +#include +#include +#include #include #define CLCD_IRQ_NEXTBASE_UPDATE BIT(2) struct drm_minor; -struct pl111_drm_connector { - struct drm_connector connector; - struct drm_panel *panel; -}; - struct pl111_drm_dev_private { struct drm_device *drm; - struct pl111_drm_connector connector; + struct drm_connector *connector; + struct drm_encoder *encoder; + struct drm_panel *panel; + struct drm_bridge *bridge; struct drm_simple_display_pipe pipe; struct drm_fbdev_cma *fbdev; @@ -50,14 +52,10 @@ struct pl111_drm_dev_private { spinlock_t tim2_lock; }; -#define to_pl111_connector(x) \ - container_of(x, struct pl111_drm_connector, connector) - int pl111_display_init(struct drm_device *dev); int pl111_enable_vblank(struct drm_device *drm, unsigned int crtc); void pl111_disable_vblank(struct drm_device *drm, unsigned int crtc); irqreturn_t pl111_irq(int irq, void *data); -int pl111_connector_init(struct drm_device *dev); int pl111_debugfs_init(struct drm_minor *minor); #endif /* _PL111_DRM_H_ */ diff --git a/drivers/gpu/drm/pl111/pl111_drv.c b/drivers/gpu/drm/pl111/pl111_drv.c index ac8771be70b0..e66cbf202e17 100644 --- a/drivers/gpu/drm/pl111/pl111_drv.c +++ b/drivers/gpu/drm/pl111/pl111_drv.c @@ -67,6 +67,9 @@ #include #include #include +#include +#include +#include #include "pl111_drm.h" @@ -82,6 +85,8 @@ static int pl111_modeset_init(struct drm_device *dev) { struct drm_mode_config *mode_config; struct pl111_drm_dev_private *priv = dev->dev_private; + struct drm_panel *panel; + struct drm_bridge *bridge; int ret = 0; drm_mode_config_init(dev); @@ -92,34 +97,46 @@ static int pl111_modeset_init(struct drm_device *dev) mode_config->min_height = 1; mode_config->max_height = 768; - ret = pl111_connector_init(dev); - if (ret) { - dev_err(dev->dev, "Failed to create pl111_drm_connector\n"); - goto out_config; - } - - /* Don't actually attach if we didn't find a drm_panel - * attached to us. This will allow a kernel to include both - * the fbdev pl111 driver and this one, and choose between - * them based on which subsystem has support for the panel. - */ - if (!priv->connector.panel) { - dev_info(dev->dev, - "Disabling due to lack of DRM panel device.\n"); - ret = -ENODEV; - goto out_config; + ret = drm_of_find_panel_or_bridge(dev->dev->of_node, + 0, 0, &panel, &bridge); + if (ret && ret != -ENODEV) + return ret; + if (panel) { + bridge = drm_panel_bridge_add(panel, + DRM_MODE_CONNECTOR_Unknown); + if (IS_ERR(bridge)) { + ret = PTR_ERR(bridge); + goto out_config; + } } ret = pl111_display_init(dev); if (ret != 0) { dev_err(dev->dev, "Failed to init display\n"); - goto out_config; + goto out_bridge; + } + + if (bridge) { + ret = drm_bridge_attach(priv->encoder, bridge, NULL); + if (ret) + goto out_bridge; + } + + /* + * TODO: when we are using a different bridge than a panel + * (such as a dumb VGA connector) we need to devise a different + * method to get the connector out of the bridge. + */ + if (panel) { + priv->panel = panel; + priv->connector = panel->connector; } + priv->bridge = bridge; ret = drm_vblank_init(dev, 1); if (ret != 0) { dev_err(dev->dev, "Failed to init vblank\n"); - goto out_config; + goto out_bridge; } drm_mode_config_reset(dev); @@ -131,6 +148,11 @@ static int pl111_modeset_init(struct drm_device *dev) goto finish; +out_bridge: + if (panel) + drm_panel_bridge_remove(bridge); + else + drm_bridge_remove(bridge); out_config: drm_mode_config_cleanup(dev); finish: @@ -237,6 +259,10 @@ static int pl111_amba_remove(struct amba_device *amba_dev) drm_dev_unregister(drm); if (priv->fbdev) drm_fbdev_cma_fini(priv->fbdev); + if (priv->panel) + drm_panel_bridge_remove(priv->bridge); + else + drm_bridge_remove(priv->bridge); drm_mode_config_cleanup(drm); drm_dev_unref(drm);