From patchwork Fri Sep 8 12:47:05 2017 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Linus Walleij X-Patchwork-Id: 9943883 Return-Path: Received: from mail.wl.linuxfoundation.org (pdx-wl-mail.web.codeaurora.org [172.30.200.125]) by pdx-korg-patchwork.web.codeaurora.org (Postfix) with ESMTP id B7EE660224 for ; Fri, 8 Sep 2017 12:47:27 +0000 (UTC) Received: from mail.wl.linuxfoundation.org (localhost [127.0.0.1]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id AACD227E63 for ; Fri, 8 Sep 2017 12:47:27 +0000 (UTC) Received: by mail.wl.linuxfoundation.org (Postfix, from userid 486) id 9F47B280FC; Fri, 8 Sep 2017 12:47:27 +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=-4.1 required=2.0 tests=BAYES_00,DKIM_SIGNED, RCVD_IN_DNSWL_MED,T_DKIM_INVALID autolearn=ham version=3.3.1 Received: from gabe.freedesktop.org (gabe.freedesktop.org [131.252.210.177]) (using TLSv1.2 with cipher DHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by mail.wl.linuxfoundation.org (Postfix) with ESMTPS id C168727E63 for ; Fri, 8 Sep 2017 12:47:26 +0000 (UTC) Received: from gabe.freedesktop.org (localhost [127.0.0.1]) by gabe.freedesktop.org (Postfix) with ESMTP id C07146EB31; Fri, 8 Sep 2017 12:47:25 +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 DE0686E0C7 for ; Fri, 8 Sep 2017 12:47:23 +0000 (UTC) Received: by mail-lf0-x233.google.com with SMTP id l196so5451602lfl.1 for ; Fri, 08 Sep 2017 05:47:23 -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=ry/vNoGGhdM3JaUw3G0Buxodvt7AMMq6dTsSufB5GK0=; b=e77s/gAzbZJA5JQLBC85uhDlNCK+8b15p+C0vXQlI3EAmM3bh40i98HRnkR54u9cHj vt6bI/ZS4K2f8fefCmlENOpzGs5fJdcEb7zIwZzn6PF+01LybuvLljeUd5FPDAXK9f6/ Cfv9wNkhN43NZGmRwp+cFHZxF+4yauJTFlVug= 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=ry/vNoGGhdM3JaUw3G0Buxodvt7AMMq6dTsSufB5GK0=; b=WY1zNwNJ9fNCMays3EGMDP7dk0+HTGdcDm7uS7LTVk3/+8KBpXeV1jdygMLiLMBR8Z Yy1lXkmXM5Dkz86WgeiH3FNe9Z3m8hvYbOCf5kdtEDFPf+9vGJfCKejxpJSioAGdnWoL Bz4YrRky4A71WwI9mX9iXXY19X/FnpxYx61G9B2aJPHLW7Z8BAHVg80CeDDaosmi3vvo V7/+/xOrbnfOG1ZlIhdDTmFhGC8AwMX7NdrB38rXX9ttab0u0C277vMmjcfAOuEmkxUr bsVp6k0mMoF1yz7c9uRz8Bv+fDCox/ozVouc0bcXPyxyZtab5iGLhg5b6FCusa6d9ZrT gCEw== X-Gm-Message-State: AHPjjUhyZbuS5L3WhFEAaM8x1Z61+qXMhJJCXPcWK0OkY5FYU0WdwChU VUa5dP6ljRYDS5n0 X-Google-Smtp-Source: ADKCNb6EMYM+/gMAxpCl7qSJXd7JWVzQHRYbCVp5aEW2Wch94MjkV1bBhnxOAAOp7C9NlpHqLy4VAg== X-Received: by 10.46.85.205 with SMTP id g74mr655418lje.84.1504874841876; Fri, 08 Sep 2017 05:47:21 -0700 (PDT) Received: from genomnajs.ideon.se ([85.235.10.227]) by smtp.gmail.com with ESMTPSA id o28sm317427lfc.9.2017.09.08.05.47.20 (version=TLS1_2 cipher=ECDHE-RSA-CHACHA20-POLY1305 bits=256/256); Fri, 08 Sep 2017 05:47:21 -0700 (PDT) From: Linus Walleij To: Daniel Vetter , Jani Nikula , Sean Paul , Eric Anholt Subject: [PATCH 3/7 v4] drm/pl111: Replace custom connector with panel bridge Date: Fri, 8 Sep 2017 14:47:05 +0200 Message-Id: <20170908124709.4758-3-linus.walleij@linaro.org> X-Mailer: git-send-email 2.13.5 In-Reply-To: <20170908124709.4758-1-linus.walleij@linaro.org> References: <20170908124709.4758-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" X-Virus-Scanned: ClamAV using ClamSMTP 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. Reviewed-by: Eric Anholt Signed-off-by: Linus Walleij --- ChangeLog v3->v4: - Drop the surplus drm_bridge_remove(bridge) calls. - Collect Eric's review tag. ChangeLog v2->v3: - Rebase on DRM-TIP - Use drm_simple_display_pipe_attach_bridge() as suggested by Daniel Vetter. 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 | 126 -------------------------------- drivers/gpu/drm/pl111/pl111_display.c | 13 +--- drivers/gpu/drm/pl111/pl111_drm.h | 17 ++--- drivers/gpu/drm/pl111/pl111_drv.c | 55 +++++++++----- 6 files changed, 49 insertions(+), 168 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 d335f9a29ce4..000000000000 --- a/drivers/gpu/drm/pl111/pl111_connector.c +++ /dev/null @@ -1,126 +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, - .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 b58c988d9da0..9caf50d130f4 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 #include @@ -94,7 +93,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; @@ -156,8 +155,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); @@ -204,8 +201,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); } @@ -217,13 +212,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); } @@ -458,7 +449,7 @@ int pl111_display_init(struct drm_device *drm) ret = drm_simple_display_pipe_init(drm, &priv->pipe, &pl111_display_funcs, formats, ARRAY_SIZE(formats), - NULL, &priv->connector.connector); + NULL, priv->connector); if (ret) return ret; diff --git a/drivers/gpu/drm/pl111/pl111_drm.h b/drivers/gpu/drm/pl111/pl111_drm.h index a97f303f6833..000534d85b43 100644 --- a/drivers/gpu/drm/pl111/pl111_drm.h +++ b/drivers/gpu/drm/pl111/pl111_drm.h @@ -21,21 +21,22 @@ #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_panel *panel; + struct drm_bridge *bridge; struct drm_simple_display_pipe pipe; struct drm_fbdev_cma *fbdev; @@ -50,14 +51,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 581c452cede1..7dae687a8df4 100644 --- a/drivers/gpu/drm/pl111/pl111_drv.c +++ b/drivers/gpu/drm/pl111/pl111_drv.c @@ -68,6 +68,9 @@ #include #include #include +#include +#include +#include #include "pl111_drm.h" @@ -83,6 +86,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); @@ -93,34 +98,43 @@ 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; + } + /* + * 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. + */ } ret = pl111_display_init(dev); if (ret != 0) { dev_err(dev->dev, "Failed to init display\n"); - goto out_config; + goto out_bridge; } + ret = drm_simple_display_pipe_attach_bridge(&priv->pipe, + bridge); + if (ret) + return ret; + + priv->bridge = bridge; + priv->panel = panel; + priv->connector = panel->connector; + 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); @@ -132,6 +146,9 @@ static int pl111_modeset_init(struct drm_device *dev) goto finish; +out_bridge: + if (panel) + drm_panel_bridge_remove(bridge); out_config: drm_mode_config_cleanup(dev); finish: @@ -236,6 +253,8 @@ 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); drm_mode_config_cleanup(drm); drm_dev_unref(drm);