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);