From b0febde779fd5d2e3e6f83843a828726117fe0a7 Mon Sep 17 00:00:00 2001 From: Jose Abreu Date: Thu, 25 May 2017 15:19:19 +0100 Subject: drm/bridge/synopsys: dw-hdmi: Use bridge->mode_valid() callback Now that we have a callback to check if bridge supports a given mode we can use it in Synopsys Designware HDMI bridge so that we restrict the number of probbed modes to the ones we can actually display. Also, there is no need to use mode_fixup() callback as mode_valid() will handle the mode validation. NOTE: I also had to change the pdata declaration of mode_valid custom callback so that the passed modes are const. I also changed in the platforms I found. Not even compiled it though. Signed-off-by: Jose Abreu Acked-by: Neil Armstrong Acked-by: Philipp Zabel Cc: Carlos Palminha Cc: Daniel Vetter Cc: Archit Taneja Cc: Andrzej Hajda Cc: Laurent Pinchart Cc: David Airlie Cc: Philipp Zabel Cc: Carlo Caione Cc: Kevin Hilman Cc: Mark Yao Cc: Heiko Stuebner Signed-off-by: Archit Taneja Link: http://patchwork.freedesktop.org/patch/msgid/3d8d449e4d13d2535fa292c75f5fa931de4a4fa8.1495720737.git.joabreu@synopsys.com --- include/drm/bridge/dw_hdmi.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'include/drm') diff --git a/include/drm/bridge/dw_hdmi.h b/include/drm/bridge/dw_hdmi.h index ed599bea3f6c..4c8d4c81a0e8 100644 --- a/include/drm/bridge/dw_hdmi.h +++ b/include/drm/bridge/dw_hdmi.h @@ -125,7 +125,7 @@ struct dw_hdmi_phy_ops { struct dw_hdmi_plat_data { struct regmap *regm; enum drm_mode_status (*mode_valid)(struct drm_connector *connector, - struct drm_display_mode *mode); + const struct drm_display_mode *mode); unsigned long input_bus_format; unsigned long input_bus_encoding; -- cgit v1.2.3 From 13dfc0540a575b47b2d640b093ac16e9e09474f6 Mon Sep 17 00:00:00 2001 From: Eric Anholt Date: Fri, 2 Jun 2017 13:25:14 -0700 Subject: drm/bridge: Refactor out the panel wrapper from the lvds-encoder bridge. Many DRM drivers have common code to make a stub connector implementation that wraps a drm_panel. By wrapping the panel in a DRM bridge, all of the connector code (including calls during encoder enable/disable) goes away. v2: Fix build with CONFIG_DRM=m, drop "dev" argument that should just be the panel's dev, move kerneldoc up a level and document _remove(). v3: Fix another breakage with CONFIG_DRM=m, fix breakage with CONFIG_OF=n, move protos under CONFIG_DRM_PANEL_BRIDGE, wrap a line. Signed-off-by: Eric Anholt Acked-by: Daniel Vetter (v1) Reviewed-by: Boris Brezillon (v2) Acked-by: Archit Taneja (v2) Signed-off-by: Archit Taneja Link: http://patchwork.freedesktop.org/patch/msgid/20170602202514.11900-1-eric@anholt.net --- Documentation/gpu/drm-kms-helpers.rst | 6 + drivers/gpu/drm/Makefile | 1 + drivers/gpu/drm/bridge/Kconfig | 11 +- drivers/gpu/drm/bridge/lvds-encoder.c | 157 +++----------------------- drivers/gpu/drm/bridge/panel.c | 200 ++++++++++++++++++++++++++++++++++ include/drm/drm_bridge.h | 7 ++ 6 files changed, 241 insertions(+), 141 deletions(-) create mode 100644 drivers/gpu/drm/bridge/panel.c (limited to 'include/drm') diff --git a/Documentation/gpu/drm-kms-helpers.rst b/Documentation/gpu/drm-kms-helpers.rst index c075aadd7078..7c5e2549a58a 100644 --- a/Documentation/gpu/drm-kms-helpers.rst +++ b/Documentation/gpu/drm-kms-helpers.rst @@ -143,6 +143,12 @@ Bridge Helper Reference .. kernel-doc:: drivers/gpu/drm/drm_bridge.c :export: +Panel-Bridge Helper Reference +----------------------------- + +.. kernel-doc:: drivers/gpu/drm/bridge/panel.c + :export: + .. _drm_panel_helper: Panel Helper Reference diff --git a/drivers/gpu/drm/Makefile b/drivers/gpu/drm/Makefile index acc88942c2e5..dc69175255b1 100644 --- a/drivers/gpu/drm/Makefile +++ b/drivers/gpu/drm/Makefile @@ -24,6 +24,7 @@ drm-$(CONFIG_COMPAT) += drm_ioc32.o drm-$(CONFIG_DRM_GEM_CMA_HELPER) += drm_gem_cma_helper.o drm-$(CONFIG_PCI) += ati_pcigart.o drm-$(CONFIG_DRM_PANEL) += drm_panel.o +drm-$(CONFIG_DRM_PANEL_BRIDGE) += bridge/panel.o drm-$(CONFIG_OF) += drm_of.o drm-$(CONFIG_AGP) += drm_agpsupport.o drm-$(CONFIG_DEBUG_FS) += drm_debugfs.o drm_debugfs_crc.o diff --git a/drivers/gpu/drm/bridge/Kconfig b/drivers/gpu/drm/bridge/Kconfig index f6968d3b4b41..adf9ae0e0b7c 100644 --- a/drivers/gpu/drm/bridge/Kconfig +++ b/drivers/gpu/drm/bridge/Kconfig @@ -4,6 +4,14 @@ config DRM_BRIDGE help Bridge registration and lookup framework. +config DRM_PANEL_BRIDGE + def_bool y + depends on DRM_BRIDGE + depends on DRM_KMS_HELPER + select DRM_PANEL + help + DRM bridge wrapper of DRM panels + menu "Display Interface Bridges" depends on DRM && DRM_BRIDGE @@ -27,8 +35,7 @@ config DRM_DUMB_VGA_DAC config DRM_LVDS_ENCODER tristate "Transparent parallel to LVDS encoder support" depends on OF - select DRM_KMS_HELPER - select DRM_PANEL + select DRM_PANEL_BRIDGE help Support for transparent parallel to LVDS encoders that don't require any configuration. diff --git a/drivers/gpu/drm/bridge/lvds-encoder.c b/drivers/gpu/drm/bridge/lvds-encoder.c index f1f67a279426..0903ba574f61 100644 --- a/drivers/gpu/drm/bridge/lvds-encoder.c +++ b/drivers/gpu/drm/bridge/lvds-encoder.c @@ -8,144 +8,18 @@ */ #include -#include -#include -#include -#include -#include +#include #include #include -struct lvds_encoder { - struct device *dev; - - struct drm_bridge bridge; - struct drm_connector connector; - struct drm_panel *panel; -}; - -static inline struct lvds_encoder * -drm_bridge_to_lvds_encoder(struct drm_bridge *bridge) -{ - return container_of(bridge, struct lvds_encoder, bridge); -} - -static inline struct lvds_encoder * -drm_connector_to_lvds_encoder(struct drm_connector *connector) -{ - return container_of(connector, struct lvds_encoder, connector); -} - -static int lvds_connector_get_modes(struct drm_connector *connector) -{ - struct lvds_encoder *lvds = drm_connector_to_lvds_encoder(connector); - - return drm_panel_get_modes(lvds->panel); -} - -static const struct drm_connector_helper_funcs lvds_connector_helper_funcs = { - .get_modes = lvds_connector_get_modes, -}; - -static const struct drm_connector_funcs lvds_connector_funcs = { - .dpms = drm_atomic_helper_connector_dpms, - .reset = drm_atomic_helper_connector_reset, - .fill_modes = drm_helper_probe_single_connector_modes, - .destroy = drm_connector_cleanup, - .atomic_duplicate_state = drm_atomic_helper_connector_duplicate_state, - .atomic_destroy_state = drm_atomic_helper_connector_destroy_state, -}; - -static int lvds_encoder_attach(struct drm_bridge *bridge) -{ - struct lvds_encoder *lvds = drm_bridge_to_lvds_encoder(bridge); - struct drm_connector *connector = &lvds->connector; - int ret; - - if (!bridge->encoder) { - DRM_ERROR("Missing encoder\n"); - return -ENODEV; - } - - drm_connector_helper_add(connector, &lvds_connector_helper_funcs); - - ret = drm_connector_init(bridge->dev, connector, &lvds_connector_funcs, - DRM_MODE_CONNECTOR_LVDS); - if (ret) { - DRM_ERROR("Failed to initialize connector\n"); - return ret; - } - - drm_mode_connector_attach_encoder(&lvds->connector, bridge->encoder); - - ret = drm_panel_attach(lvds->panel, &lvds->connector); - if (ret < 0) - return ret; - - return 0; -} - -static void lvds_encoder_detach(struct drm_bridge *bridge) -{ - struct lvds_encoder *lvds = drm_bridge_to_lvds_encoder(bridge); - - drm_panel_detach(lvds->panel); -} - -static void lvds_encoder_pre_enable(struct drm_bridge *bridge) -{ - struct lvds_encoder *lvds = drm_bridge_to_lvds_encoder(bridge); - - drm_panel_prepare(lvds->panel); -} - -static void lvds_encoder_enable(struct drm_bridge *bridge) -{ - struct lvds_encoder *lvds = drm_bridge_to_lvds_encoder(bridge); - - drm_panel_enable(lvds->panel); -} - -static void lvds_encoder_disable(struct drm_bridge *bridge) -{ - struct lvds_encoder *lvds = drm_bridge_to_lvds_encoder(bridge); - - drm_panel_disable(lvds->panel); -} - -static void lvds_encoder_post_disable(struct drm_bridge *bridge) -{ - struct lvds_encoder *lvds = drm_bridge_to_lvds_encoder(bridge); - - drm_panel_unprepare(lvds->panel); -} - -static const struct drm_bridge_funcs lvds_encoder_bridge_funcs = { - .attach = lvds_encoder_attach, - .detach = lvds_encoder_detach, - .pre_enable = lvds_encoder_pre_enable, - .enable = lvds_encoder_enable, - .disable = lvds_encoder_disable, - .post_disable = lvds_encoder_post_disable, -}; - static int lvds_encoder_probe(struct platform_device *pdev) { - struct lvds_encoder *lvds; struct device_node *port; struct device_node *endpoint; - struct device_node *panel; - - lvds = devm_kzalloc(&pdev->dev, sizeof(*lvds), GFP_KERNEL); - if (!lvds) - return -ENOMEM; - - lvds->dev = &pdev->dev; - platform_set_drvdata(pdev, lvds); - - lvds->bridge.funcs = &lvds_encoder_bridge_funcs; - lvds->bridge.of_node = pdev->dev.of_node; + struct device_node *panel_node; + struct drm_panel *panel; + struct drm_bridge *bridge; /* Locate the panel DT node. */ port = of_graph_get_port_by_id(pdev->dev.of_node, 1); @@ -161,29 +35,34 @@ static int lvds_encoder_probe(struct platform_device *pdev) return -ENXIO; } - panel = of_graph_get_remote_port_parent(endpoint); + panel_node = of_graph_get_remote_port_parent(endpoint); of_node_put(endpoint); - if (!panel) { + if (!panel_node) { dev_dbg(&pdev->dev, "no remote endpoint for port 1\n"); return -ENXIO; } - lvds->panel = of_drm_find_panel(panel); - of_node_put(panel); - if (!lvds->panel) { + panel = of_drm_find_panel(panel_node); + of_node_put(panel_node); + if (!panel) { dev_dbg(&pdev->dev, "panel not found, deferring probe\n"); return -EPROBE_DEFER; } - /* Register the bridge. */ - return drm_bridge_add(&lvds->bridge); + bridge = drm_panel_bridge_add(panel, DRM_MODE_CONNECTOR_LVDS); + if (IS_ERR(bridge)) + return PTR_ERR(bridge); + + platform_set_drvdata(pdev, bridge); + + return 0; } static int lvds_encoder_remove(struct platform_device *pdev) { - struct lvds_encoder *encoder = platform_get_drvdata(pdev); + struct drm_bridge *bridge = platform_get_drvdata(pdev); - drm_bridge_remove(&encoder->bridge); + drm_bridge_remove(bridge); return 0; } diff --git a/drivers/gpu/drm/bridge/panel.c b/drivers/gpu/drm/bridge/panel.c new file mode 100644 index 000000000000..99f9a4beb859 --- /dev/null +++ b/drivers/gpu/drm/bridge/panel.c @@ -0,0 +1,200 @@ +/* + * Copyright (C) 2016 Laurent Pinchart + * Copyright (C) 2017 Broadcom + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation; either version 2 of + * the License, or (at your option) any later version. + */ + +#include +#include +#include +#include +#include +#include +#include +#include + +struct panel_bridge { + struct drm_bridge bridge; + struct drm_connector connector; + struct drm_panel *panel; + u32 connector_type; +}; + +static inline struct panel_bridge * +drm_bridge_to_panel_bridge(struct drm_bridge *bridge) +{ + return container_of(bridge, struct panel_bridge, bridge); +} + +static inline struct panel_bridge * +drm_connector_to_panel_bridge(struct drm_connector *connector) +{ + return container_of(connector, struct panel_bridge, connector); +} + +static int panel_bridge_connector_get_modes(struct drm_connector *connector) +{ + struct panel_bridge *panel_bridge = + drm_connector_to_panel_bridge(connector); + + return drm_panel_get_modes(panel_bridge->panel); +} + +static const struct drm_connector_helper_funcs +panel_bridge_connector_helper_funcs = { + .get_modes = panel_bridge_connector_get_modes, +}; + +static const struct drm_connector_funcs panel_bridge_connector_funcs = { + .dpms = drm_atomic_helper_connector_dpms, + .reset = drm_atomic_helper_connector_reset, + .fill_modes = drm_helper_probe_single_connector_modes, + .destroy = drm_connector_cleanup, + .atomic_duplicate_state = drm_atomic_helper_connector_duplicate_state, + .atomic_destroy_state = drm_atomic_helper_connector_destroy_state, +}; + +static int panel_bridge_attach(struct drm_bridge *bridge) +{ + struct panel_bridge *panel_bridge = drm_bridge_to_panel_bridge(bridge); + struct drm_connector *connector = &panel_bridge->connector; + int ret; + + if (!bridge->encoder) { + DRM_ERROR("Missing encoder\n"); + return -ENODEV; + } + + drm_connector_helper_add(connector, + &panel_bridge_connector_helper_funcs); + + ret = drm_connector_init(bridge->dev, connector, + &panel_bridge_connector_funcs, + panel_bridge->connector_type); + if (ret) { + DRM_ERROR("Failed to initialize connector\n"); + return ret; + } + + drm_mode_connector_attach_encoder(&panel_bridge->connector, + bridge->encoder); + + ret = drm_panel_attach(panel_bridge->panel, &panel_bridge->connector); + if (ret < 0) + return ret; + + return 0; +} + +static void panel_bridge_detach(struct drm_bridge *bridge) +{ + struct panel_bridge *panel_bridge = drm_bridge_to_panel_bridge(bridge); + + drm_panel_detach(panel_bridge->panel); +} + +static void panel_bridge_pre_enable(struct drm_bridge *bridge) +{ + struct panel_bridge *panel_bridge = drm_bridge_to_panel_bridge(bridge); + + drm_panel_prepare(panel_bridge->panel); +} + +static void panel_bridge_enable(struct drm_bridge *bridge) +{ + struct panel_bridge *panel_bridge = drm_bridge_to_panel_bridge(bridge); + + drm_panel_enable(panel_bridge->panel); +} + +static void panel_bridge_disable(struct drm_bridge *bridge) +{ + struct panel_bridge *panel_bridge = drm_bridge_to_panel_bridge(bridge); + + drm_panel_disable(panel_bridge->panel); +} + +static void panel_bridge_post_disable(struct drm_bridge *bridge) +{ + struct panel_bridge *panel_bridge = drm_bridge_to_panel_bridge(bridge); + + drm_panel_unprepare(panel_bridge->panel); +} + +static const struct drm_bridge_funcs panel_bridge_bridge_funcs = { + .attach = panel_bridge_attach, + .detach = panel_bridge_detach, + .pre_enable = panel_bridge_pre_enable, + .enable = panel_bridge_enable, + .disable = panel_bridge_disable, + .post_disable = panel_bridge_post_disable, +}; + +/** + * drm_panel_bridge_add - Creates a drm_bridge and drm_connector that + * just calls the appropriate functions from drm_panel. + * + * @panel: The drm_panel being wrapped. Must be non-NULL. + * @connector_type: The DRM_MODE_CONNECTOR_* for the connector to be + * created. + * + * For drivers converting from directly using drm_panel: The expected + * usage pattern is that during either encoder module probe or DSI + * host attach, a drm_panel will be looked up through + * drm_of_find_panel_or_bridge(). drm_panel_bridge_add() is used to + * wrap that panel in the new bridge, and the result can then be + * passed to drm_bridge_attach(). The drm_panel_prepare() and related + * functions can be dropped from the encoder driver (they're now + * called by the KMS helpers before calling into the encoder), along + * with connector creation. When done with the bridge, + * drm_bridge_detach() should be called as normal, then + * drm_panel_bridge_remove() to free it. + */ +struct drm_bridge *drm_panel_bridge_add(struct drm_panel *panel, + u32 connector_type) +{ + struct panel_bridge *panel_bridge; + int ret; + + if (!panel) + return ERR_PTR(EINVAL); + + panel_bridge = devm_kzalloc(panel->dev, sizeof(*panel_bridge), + GFP_KERNEL); + if (!panel_bridge) + return ERR_PTR(-ENOMEM); + + panel_bridge->connector_type = connector_type; + panel_bridge->panel = panel; + + panel_bridge->bridge.funcs = &panel_bridge_bridge_funcs; +#ifdef CONFIG_OF + panel_bridge->bridge.of_node = panel->dev->of_node; +#endif + + ret = drm_bridge_add(&panel_bridge->bridge); + if (ret) + return ERR_PTR(ret); + + return &panel_bridge->bridge; +} +EXPORT_SYMBOL(drm_panel_bridge_add); + +/** + * drm_panel_bridge_remove - Unregisters and frees a drm_bridge + * created by drm_panel_bridge_add(). + * + * @bridge: The drm_bridge being freed. + */ +void drm_panel_bridge_remove(struct drm_bridge *bridge) +{ + struct panel_bridge *panel_bridge = drm_bridge_to_panel_bridge(bridge); + + drm_bridge_remove(bridge); + devm_kfree(panel_bridge->panel->dev, bridge); +} +EXPORT_SYMBOL(drm_panel_bridge_remove); diff --git a/include/drm/drm_bridge.h b/include/drm/drm_bridge.h index 5b106eca6d57..1dc94d5392e2 100644 --- a/include/drm/drm_bridge.h +++ b/include/drm/drm_bridge.h @@ -29,6 +29,7 @@ #include struct drm_bridge; +struct drm_panel; /** * struct drm_bridge_funcs - drm_bridge control functions @@ -263,4 +264,10 @@ void drm_bridge_mode_set(struct drm_bridge *bridge, void drm_bridge_pre_enable(struct drm_bridge *bridge); void drm_bridge_enable(struct drm_bridge *bridge); +#ifdef CONFIG_DRM_PANEL_BRIDGE +struct drm_bridge *drm_panel_bridge_add(struct drm_panel *panel, + u32 connector_type); +void drm_panel_bridge_remove(struct drm_bridge *bridge); +#endif + #endif -- cgit v1.2.3 From dc629141c3336ae4b03c5fef5fb7bf1058752aed Mon Sep 17 00:00:00 2001 From: Jyri Sarha Date: Tue, 30 May 2017 19:29:55 +0300 Subject: drm: Add const to name field declaration in struct drm_prop_enum_list MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit There is no reason why the name field should not be const, but several why it should. The struct should only be used by drm_property_create_enum() and there the name-field from the struct is passed to drm_property_add_enum(), which takes a const char * as a parameter. Signed-off-by: Jyri Sarha Signed-off-by: Ville Syrjälä Link: http://patchwork.freedesktop.org/patch/msgid/5dd3b6a1e20452bd8abdcbc55d1e8d7f56262266.1496161066.git.jsarha@ti.com --- include/drm/drm_property.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'include/drm') diff --git a/include/drm/drm_property.h b/include/drm/drm_property.h index 13e8c17d1c79..619868dc08d8 100644 --- a/include/drm/drm_property.h +++ b/include/drm/drm_property.h @@ -214,7 +214,7 @@ struct drm_property_blob { struct drm_prop_enum_list { int type; - char *name; + const char *name; }; #define obj_to_property(x) container_of(x, struct drm_property, base) -- cgit v1.2.3 From d35fb61759688093fab863318edbbcea0f4644bd Mon Sep 17 00:00:00 2001 From: Dawid Kurek Date: Wed, 14 Jun 2017 23:35:18 +0200 Subject: drm: Remove duplicate forward declaration Forward declarations in C are great but I'm pretty sure one is enough. Signed-off-by: Dawid Kurek Signed-off-by: Sean Paul Link: http://patchwork.freedesktop.org/patch/msgid/20170614213518.GA3554@gmail.com --- include/drm/drm_connector.h | 2 -- 1 file changed, 2 deletions(-) (limited to 'include/drm') diff --git a/include/drm/drm_connector.h b/include/drm/drm_connector.h index d8bb25f38eba..ae5b7dc316c8 100644 --- a/include/drm/drm_connector.h +++ b/include/drm/drm_connector.h @@ -30,8 +30,6 @@ #include -struct drm_device; - struct drm_connector_helper_funcs; struct drm_modeset_acquire_ctx; struct drm_device; -- cgit v1.2.3