From 06c4a9c2ae606a8c9fab303613234804b9c45a64 Mon Sep 17 00:00:00 2001 From: Sam Ravnborg Date: Sat, 7 Dec 2019 15:03:34 +0100 Subject: drm/panel: decouple connector from drm_panel MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit To facilitate moving connector creation to display drivers, decouple the drm_connector from drm_panel. This patch adds a connector argument to drm_panel_get_modes(). All users of drm_panel_get_modes() already had the connector available, so updating users was trivial. With this patch drm_panel no longer keeps a reference to the drm_connector. Signed-off-by: Sam Ravnborg Reviewed-by: Laurent Pinchart Reviewed-by: Linus Walleij Acked-by: Jeffrey Hugo Cc: Thierry Reding Cc: Laurent Pinchart Cc: Sam Ravnborg Cc: Andrzej Hajda Cc: Neil Armstrong Cc: Jonas Karlman Cc: Jernej Skrabec Cc: Maarten Lankhorst Cc: Maxime Ripard Cc: David Airlie Cc: Daniel Vetter Cc: Inki Dae Cc: Joonyoung Shim Cc: Seung-Woo Kim Cc: Kyungmin Park Cc: Kukjin Kim Cc: Krzysztof Kozlowski Cc: Stefan Agner Cc: Alison Wang Cc: Philipp Zabel Cc: Shawn Guo Cc: Sascha Hauer Cc: Pengutronix Kernel Team Cc: Fabio Estevam Cc: NXP Linux Team Cc: CK Hu Cc: Matthias Brugger Cc: Marek Vasut Cc: Tomi Valkeinen Cc: Kieran Bingham Cc: Sandy Huang Cc: "Heiko Stübner" Cc: Benjamin Gaignard Cc: Vincent Abriou Cc: Chen-Yu Tsai Cc: Jonathan Hunter Cc: Torsten Duwe Cc: Vasily Khoruzhick Cc: Icenowy Zheng Cc: Sean Paul Cc: Linus Walleij Cc: Boris Brezillon Cc: Hariprasad Kelam Cc: Alexios Zavras Cc: Brian Masney Cc: Rob Clark Cc: Thomas Gleixner Cc: Allison Randal Cc: Shayenne Moura Cc: Abhinav Kumar Cc: linux-arm-kernel@lists.infradead.org Cc: linux-samsung-soc@vger.kernel.org Cc: linux-mediatek@lists.infradead.org Cc: linux-renesas-soc@vger.kernel.org Cc: linux-rockchip@lists.infradead.org Cc: linux-tegra@vger.kernel.org Link: https://patchwork.freedesktop.org/patch/msgid/20191207140353.23967-7-sam@ravnborg.org --- drivers/gpu/drm/msm/dsi/dsi_manager.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers/gpu/drm/msm/dsi/dsi_manager.c') diff --git a/drivers/gpu/drm/msm/dsi/dsi_manager.c b/drivers/gpu/drm/msm/dsi/dsi_manager.c index 271aa7bbca92..0fc29f1be8cc 100644 --- a/drivers/gpu/drm/msm/dsi/dsi_manager.c +++ b/drivers/gpu/drm/msm/dsi/dsi_manager.c @@ -329,7 +329,7 @@ static int dsi_mgr_connector_get_modes(struct drm_connector *connector) * attached to the drm_panel. */ drm_panel_attach(panel, connector); - num = drm_panel_get_modes(panel); + num = drm_panel_get_modes(panel, connector); if (!num) return 0; -- cgit From e5400750fafdaeee136e9fc3d1dde83d9251ee63 Mon Sep 17 00:00:00 2001 From: Stephan Gerhold Date: Fri, 8 Nov 2019 22:28:40 +0100 Subject: drm/msm/dsi: Delay drm_panel_enable() until dsi_mgr_bridge_enable() At the moment, the MSM DSI driver calls drm_panel_enable() rather early from the DSI bridge pre_enable() function. At this point, the encoder (e.g. MDP5) is not enabled, so we have not started transmitting video data. However, the drm_panel_funcs documentation states that enable() should be called on the panel *after* video data is being transmitted: The .prepare() function is typically called before the display controller starts to transmit video data. [...] After the display controller has started transmitting video data, it's safe to call the .enable() function. This will typically enable the backlight to make the image on screen visible. Calling drm_panel_enable() too early causes problems for some panels: The TFT LCD panel used in the Samsung Galaxy Tab A 9.7 (2015) (APQ8016) uses the MIPI_DCS_SET_DISPLAY_BRIGHTNESS command to control backlight/brightness of the screen. The enable sequence is therefore: drm_panel_enable() drm_panel_funcs.enable(): backlight_enable() backlight_ops.update_status(): mipi_dsi_dcs_set_display_brightness(dsi, bl->props.brightness); The panel seems to silently ignore the MIPI_DCS_SET_DISPLAY_BRIGHTNESS command if it is sent too early. This prevents setting the initial brightness, causing the display to be enabled with minimum brightness instead. Adding various delays in the panel initialization code does not result in any difference. On the other hand, moving drm_panel_enable() to dsi_mgr_bridge_enable() fixes the problem, indicating that the panel requires the video stream to be active before the brightness command is accepted. Therefore: Move drm_panel_enable() to dsi_mgr_bridge_enable() to delay calling it until video data is being transmitted. Move drm_panel_disable() to dsi_mgr_bridge_disable() for similar reasons. (This is not strictly required for the panel affected above...) Tested-by: Jasper Korten Signed-off-by: Stephan Gerhold Tested-by: Jeffrey Hugo Reviewed-by: Jeffrey Hugo Signed-off-by: Rob Clark --- drivers/gpu/drm/msm/dsi/dsi_manager.c | 62 +++++++++++++++++++++++------------ 1 file changed, 41 insertions(+), 21 deletions(-) (limited to 'drivers/gpu/drm/msm/dsi/dsi_manager.c') diff --git a/drivers/gpu/drm/msm/dsi/dsi_manager.c b/drivers/gpu/drm/msm/dsi/dsi_manager.c index 271aa7bbca92..eea108865cd3 100644 --- a/drivers/gpu/drm/msm/dsi/dsi_manager.c +++ b/drivers/gpu/drm/msm/dsi/dsi_manager.c @@ -432,20 +432,8 @@ static void dsi_mgr_bridge_pre_enable(struct drm_bridge *bridge) } } - if (panel) { - ret = drm_panel_enable(panel); - if (ret) { - pr_err("%s: enable panel %d failed, %d\n", __func__, id, - ret); - goto panel_en_fail; - } - } - return; -panel_en_fail: - if (is_dual_dsi && msm_dsi1) - msm_dsi_host_disable(msm_dsi1->host); host1_en_fail: msm_dsi_host_disable(host); host_en_fail: @@ -464,12 +452,51 @@ phy_en_fail: static void dsi_mgr_bridge_enable(struct drm_bridge *bridge) { - DBG(""); + int id = dsi_mgr_bridge_get_id(bridge); + struct msm_dsi *msm_dsi = dsi_mgr_get_dsi(id); + struct drm_panel *panel = msm_dsi->panel; + bool is_dual_dsi = IS_DUAL_DSI(); + int ret; + + DBG("id=%d", id); + if (!msm_dsi_device_connected(msm_dsi)) + return; + + /* Do nothing with the host if it is slave-DSI in case of dual DSI */ + if (is_dual_dsi && !IS_MASTER_DSI_LINK(id)) + return; + + if (panel) { + ret = drm_panel_enable(panel); + if (ret) { + pr_err("%s: enable panel %d failed, %d\n", __func__, id, + ret); + } + } } static void dsi_mgr_bridge_disable(struct drm_bridge *bridge) { - DBG(""); + int id = dsi_mgr_bridge_get_id(bridge); + struct msm_dsi *msm_dsi = dsi_mgr_get_dsi(id); + struct drm_panel *panel = msm_dsi->panel; + bool is_dual_dsi = IS_DUAL_DSI(); + int ret; + + DBG("id=%d", id); + if (!msm_dsi_device_connected(msm_dsi)) + return; + + /* Do nothing with the host if it is slave-DSI in case of dual DSI */ + if (is_dual_dsi && !IS_MASTER_DSI_LINK(id)) + return; + + if (panel) { + ret = drm_panel_disable(panel); + if (ret) + pr_err("%s: Panel %d OFF failed, %d\n", __func__, id, + ret); + } } static void dsi_mgr_bridge_post_disable(struct drm_bridge *bridge) @@ -495,13 +522,6 @@ static void dsi_mgr_bridge_post_disable(struct drm_bridge *bridge) if (is_dual_dsi && !IS_MASTER_DSI_LINK(id)) goto disable_phy; - if (panel) { - ret = drm_panel_disable(panel); - if (ret) - pr_err("%s: Panel %d OFF failed, %d\n", __func__, id, - ret); - } - ret = msm_dsi_host_disable(host); if (ret) pr_err("%s: host %d disable failed, %d\n", __func__, id, ret); -- cgit