dri-devel.lists.freedesktop.org archive mirror
 help / color / mirror / Atom feed
* [PATCH 00/21] drm: mxsfb: Add i.MX7 support
@ 2020-03-09 19:51 Laurent Pinchart
  2020-03-09 19:51 ` [PATCH 01/21] drm: mxsfb: Remove fbdev leftovers Laurent Pinchart
                   ` (23 more replies)
  0 siblings, 24 replies; 62+ messages in thread
From: Laurent Pinchart @ 2020-03-09 19:51 UTC (permalink / raw)
  To: dri-devel; +Cc: Marek Vasut, kernel, linux-imx

Hello,

This patch series adds i.MX7 support to the mxsfb driver. The eLCDIF
instance found in the i.MX7 is backward-compatible with the already
supported LCDC v4, but has extended features amongst which the most
notable one is a second plane.

The first 9 patches (01/21 to 09/21) contain miscellaneous cleanups and
refactoring to prepare for what is to come. Patch 10/21 starts the real
work with removal of the DRM simple display pipeline helper, as it
doesn't support multiple planes. The next patch (11/21) is an additional
cleanup.

Patches 12/21 to 14/21 fix vblank handling that I found to be broken
when testing on my device. Patch 15/21 then performs an additional small
cleanup, and patch 16/21 starts official support for i.MX7 by mentioning
it in Kconfig.

Patch 17/21 adds a new device model for the i.MX6SX and i.MX7 eLCDIF.
After three additional cleanups in patches 18/21 to 20/21, patch 21/21
finally adds support for the second plane.

The code is based on drm-misc-next and has been tested on an i.MX7D
platform with a DPI panel.

Laurent Pinchart (21):
  drm: mxsfb: Remove fbdev leftovers
  drm: mxsfb: Use drm_panel_bridge
  drm: mxsfb: Use BIT() macro to define register bitfields
  drm: mxsfb: Remove unused macros from mxsfb_regs.h
  drm: mxsfb: Clarify format and bus width configuration
  drm: mxsfb: Pass mxsfb_drm_private pointer to mxsfb_reset_block()
  drm: mxsfb: Use LCDC_CTRL register name explicitly
  drm: mxsfb: Remove register definitions from mxsfb_crtc.c
  drm: mxsfb: Remove unneeded includes
  drm: mxsfb: Stop using DRM simple display pipeline helper
  drm: mxsfb: Rename mxsfb_crtc.c to mxsfb_kms.c
  drm: mxsfb: Move vblank event arm to CRTC .atomic_flush()
  drm: mxsfb: Don't touch AXI clock in IRQ context
  drm: mxsfb: Enable vblank handling
  drm: mxsfb: Remove mxsfb_devdata unused fields
  drm: mxsfb: Add i.MX7 to the list of supported SoCs in Kconfig
  drm: mxsfb: Update internal IP version number for i.MX6SX
  drm: mxsfb: Drop non-OF support
  drm: mxsfb: Turn mxsfb_set_pixel_fmt() into a void function
  drm: mxsfb: Merge mxsfb_set_pixel_fmt() and mxsfb_set_bus_fmt()
  drm: mxsfb: Support the alpha plane

 drivers/gpu/drm/mxsfb/Kconfig      |   4 +-
 drivers/gpu/drm/mxsfb/Makefile     |   2 +-
 drivers/gpu/drm/mxsfb/mxsfb_crtc.c | 343 -----------------
 drivers/gpu/drm/mxsfb/mxsfb_drv.c  | 246 ++++---------
 drivers/gpu/drm/mxsfb/mxsfb_drv.h  |  42 ++-
 drivers/gpu/drm/mxsfb/mxsfb_kms.c  | 565 +++++++++++++++++++++++++++++
 drivers/gpu/drm/mxsfb/mxsfb_out.c  |  99 -----
 drivers/gpu/drm/mxsfb/mxsfb_regs.h | 107 +++---
 8 files changed, 730 insertions(+), 678 deletions(-)
 delete mode 100644 drivers/gpu/drm/mxsfb/mxsfb_crtc.c
 create mode 100644 drivers/gpu/drm/mxsfb/mxsfb_kms.c
 delete mode 100644 drivers/gpu/drm/mxsfb/mxsfb_out.c

-- 
Regards,

Laurent Pinchart

_______________________________________________
dri-devel mailing list
dri-devel@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/dri-devel

^ permalink raw reply	[flat|nested] 62+ messages in thread

* [PATCH 01/21] drm: mxsfb: Remove fbdev leftovers
  2020-03-09 19:51 [PATCH 00/21] drm: mxsfb: Add i.MX7 support Laurent Pinchart
@ 2020-03-09 19:51 ` Laurent Pinchart
  2020-03-23 20:23   ` Stefan Agner
  2020-03-09 19:51 ` [PATCH 02/21] drm: mxsfb: Use drm_panel_bridge Laurent Pinchart
                   ` (22 subsequent siblings)
  23 siblings, 1 reply; 62+ messages in thread
From: Laurent Pinchart @ 2020-03-09 19:51 UTC (permalink / raw)
  To: dri-devel; +Cc: Marek Vasut, kernel, linux-imx

Commit 8e93f1028d74 ("drm/mxsfb: Use drm_fbdev_generic_setup()")
replaced fbdev handling with drm_fbdev_generic_setup() but left
inclusion of the drm/drm_fb_cma_helper.h header. Remove it.

Fixes: 8e93f1028d74 ("drm/mxsfb: Use drm_fbdev_generic_setup()")
Signed-off-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
---
 drivers/gpu/drm/mxsfb/mxsfb_drv.c | 1 -
 1 file changed, 1 deletion(-)

diff --git a/drivers/gpu/drm/mxsfb/mxsfb_drv.c b/drivers/gpu/drm/mxsfb/mxsfb_drv.c
index 497cf443a9af..2e6068d96034 100644
--- a/drivers/gpu/drm/mxsfb/mxsfb_drv.c
+++ b/drivers/gpu/drm/mxsfb/mxsfb_drv.c
@@ -24,7 +24,6 @@
 #include <drm/drm_atomic_helper.h>
 #include <drm/drm_crtc.h>
 #include <drm/drm_drv.h>
-#include <drm/drm_fb_cma_helper.h>
 #include <drm/drm_fb_helper.h>
 #include <drm/drm_gem_cma_helper.h>
 #include <drm/drm_gem_framebuffer_helper.h>
-- 
Regards,

Laurent Pinchart

_______________________________________________
dri-devel mailing list
dri-devel@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/dri-devel

^ permalink raw reply related	[flat|nested] 62+ messages in thread

* [PATCH 02/21] drm: mxsfb: Use drm_panel_bridge
  2020-03-09 19:51 [PATCH 00/21] drm: mxsfb: Add i.MX7 support Laurent Pinchart
  2020-03-09 19:51 ` [PATCH 01/21] drm: mxsfb: Remove fbdev leftovers Laurent Pinchart
@ 2020-03-09 19:51 ` Laurent Pinchart
  2020-03-23 21:27   ` Stefan Agner
  2020-03-09 19:51 ` [PATCH 03/21] drm: mxsfb: Use BIT() macro to define register bitfields Laurent Pinchart
                   ` (21 subsequent siblings)
  23 siblings, 1 reply; 62+ messages in thread
From: Laurent Pinchart @ 2020-03-09 19:51 UTC (permalink / raw)
  To: dri-devel; +Cc: Marek Vasut, kernel, linux-imx

Replace the manual connector implementation based on drm_panel with the
drm_panel_bridge helper. This simplifies the mxsfb driver by removing
connector-related code, and standardizing all pipeline control
operations on bridges.

A hack is needed to get hold of the connector, as that's our only source
of bus flags and formats for now. As soon as the bridge API provides us
with that information this can be fixed.

Signed-off-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
---
 drivers/gpu/drm/mxsfb/Makefile    |   2 +-
 drivers/gpu/drm/mxsfb/mxsfb_drv.c | 105 ++++++++++++++----------------
 drivers/gpu/drm/mxsfb/mxsfb_drv.h |   5 +-
 drivers/gpu/drm/mxsfb/mxsfb_out.c |  99 ----------------------------
 4 files changed, 53 insertions(+), 158 deletions(-)
 delete mode 100644 drivers/gpu/drm/mxsfb/mxsfb_out.c

diff --git a/drivers/gpu/drm/mxsfb/Makefile b/drivers/gpu/drm/mxsfb/Makefile
index ff6e358088fa..811584e54ad1 100644
--- a/drivers/gpu/drm/mxsfb/Makefile
+++ b/drivers/gpu/drm/mxsfb/Makefile
@@ -1,3 +1,3 @@
 # SPDX-License-Identifier: GPL-2.0-only
-mxsfb-y := mxsfb_drv.o mxsfb_crtc.o mxsfb_out.o
+mxsfb-y := mxsfb_drv.o mxsfb_crtc.o
 obj-$(CONFIG_DRM_MXSFB)	+= mxsfb.o
diff --git a/drivers/gpu/drm/mxsfb/mxsfb_drv.c b/drivers/gpu/drm/mxsfb/mxsfb_drv.c
index 2e6068d96034..cffc70257bd3 100644
--- a/drivers/gpu/drm/mxsfb/mxsfb_drv.c
+++ b/drivers/gpu/drm/mxsfb/mxsfb_drv.c
@@ -29,7 +29,6 @@
 #include <drm/drm_gem_framebuffer_helper.h>
 #include <drm/drm_irq.h>
 #include <drm/drm_of.h>
-#include <drm/drm_panel.h>
 #include <drm/drm_probe_helper.h>
 #include <drm/drm_simple_kms_helper.h>
 #include <drm/drm_vblank.h>
@@ -100,29 +99,11 @@ static void mxsfb_pipe_enable(struct drm_simple_display_pipe *pipe,
 			      struct drm_crtc_state *crtc_state,
 			      struct drm_plane_state *plane_state)
 {
-	struct drm_connector *connector;
 	struct mxsfb_drm_private *mxsfb = drm_pipe_to_mxsfb_drm_private(pipe);
 	struct drm_device *drm = pipe->plane.dev;
 
-	if (!mxsfb->connector) {
-		list_for_each_entry(connector,
-				    &drm->mode_config.connector_list,
-				    head)
-			if (connector->encoder == &mxsfb->pipe.encoder) {
-				mxsfb->connector = connector;
-				break;
-			}
-	}
-
-	if (!mxsfb->connector) {
-		dev_warn(drm->dev, "No connector attached, using default\n");
-		mxsfb->connector = &mxsfb->panel_connector;
-	}
-
 	pm_runtime_get_sync(drm->dev);
-	drm_panel_prepare(mxsfb->panel);
 	mxsfb_crtc_enable(mxsfb);
-	drm_panel_enable(mxsfb->panel);
 }
 
 static void mxsfb_pipe_disable(struct drm_simple_display_pipe *pipe)
@@ -132,9 +113,7 @@ static void mxsfb_pipe_disable(struct drm_simple_display_pipe *pipe)
 	struct drm_crtc *crtc = &pipe->crtc;
 	struct drm_pending_vblank_event *event;
 
-	drm_panel_disable(mxsfb->panel);
 	mxsfb_crtc_disable(mxsfb);
-	drm_panel_unprepare(mxsfb->panel);
 	pm_runtime_put_sync(drm->dev);
 
 	spin_lock_irq(&drm->event_lock);
@@ -144,9 +123,6 @@ static void mxsfb_pipe_disable(struct drm_simple_display_pipe *pipe)
 		drm_crtc_send_vblank_event(crtc, event);
 	}
 	spin_unlock_irq(&drm->event_lock);
-
-	if (mxsfb->connector != &mxsfb->panel_connector)
-		mxsfb->connector = NULL;
 }
 
 static void mxsfb_pipe_update(struct drm_simple_display_pipe *pipe,
@@ -190,6 +166,48 @@ static struct drm_simple_display_pipe_funcs mxsfb_funcs = {
 	.disable_vblank	= mxsfb_pipe_disable_vblank,
 };
 
+static int mxsfb_attach_bridge(struct mxsfb_drm_private *mxsfb)
+{
+	struct drm_device *drm = mxsfb->drm;
+	struct drm_connector_list_iter iter;
+	struct drm_panel *panel;
+	struct drm_bridge *bridge;
+	int ret;
+
+	ret = drm_of_find_panel_or_bridge(drm->dev->of_node, 0, 0, &panel,
+					  &bridge);
+	if (ret)
+		return ret;
+
+	if (panel) {
+		bridge = devm_drm_panel_bridge_add(drm->dev, panel);
+		if (IS_ERR(bridge))
+			return PTR_ERR(bridge);
+	}
+
+	if (!bridge)
+		return -ENODEV;
+
+	ret = drm_simple_display_pipe_attach_bridge(&mxsfb->pipe, bridge);
+	if (ret) {
+		DRM_DEV_ERROR(drm->dev,
+			      "failed to attach bridge: %d\n", ret);
+		return ret;
+	}
+
+	mxsfb->bridge = bridge;
+
+	/*
+	 * Get hold of the connector. This is a bit of a hack, until the bridge
+	 * API gives us bus flags and formats.
+	 */
+	drm_connector_list_iter_begin(drm, &iter);
+	mxsfb->connector = drm_connector_list_iter_next(&iter);
+	drm_connector_list_iter_end(&iter);
+
+	return 0;
+}
+
 static int mxsfb_load(struct drm_device *drm, unsigned long flags)
 {
 	struct platform_device *pdev = to_platform_device(drm->dev);
@@ -201,6 +219,7 @@ static int mxsfb_load(struct drm_device *drm, unsigned long flags)
 	if (!mxsfb)
 		return -ENOMEM;
 
+	mxsfb->drm = drm;
 	drm->dev_private = mxsfb;
 	mxsfb->devdata = &mxsfb_devdata[pdev->id_entry->driver_data];
 
@@ -236,41 +255,17 @@ static int mxsfb_load(struct drm_device *drm, unsigned long flags)
 	/* Modeset init */
 	drm_mode_config_init(drm);
 
-	ret = mxsfb_create_output(drm);
-	if (ret < 0) {
-		dev_err(drm->dev, "Failed to create outputs\n");
-		goto err_vblank;
-	}
-
 	ret = drm_simple_display_pipe_init(drm, &mxsfb->pipe, &mxsfb_funcs,
-			mxsfb_formats, ARRAY_SIZE(mxsfb_formats), NULL,
-			mxsfb->connector);
+			mxsfb_formats, ARRAY_SIZE(mxsfb_formats), NULL, NULL);
 	if (ret < 0) {
 		dev_err(drm->dev, "Cannot setup simple display pipe\n");
 		goto err_vblank;
 	}
 
-	/*
-	 * Attach panel only if there is one.
-	 * If there is no panel attach, it must be a bridge. In this case, we
-	 * need a reference to its connector for a proper initialization.
-	 * We will do this check in pipe->enable(), since the connector won't
-	 * be attached to an encoder until then.
-	 */
-
-	if (mxsfb->panel) {
-		ret = drm_panel_attach(mxsfb->panel, mxsfb->connector);
-		if (ret) {
-			dev_err(drm->dev, "Cannot connect panel: %d\n", ret);
-			goto err_vblank;
-		}
-	} else if (mxsfb->bridge) {
-		ret = drm_simple_display_pipe_attach_bridge(&mxsfb->pipe,
-							    mxsfb->bridge);
-		if (ret) {
-			dev_err(drm->dev, "Cannot connect bridge: %d\n", ret);
-			goto err_vblank;
-		}
+	ret = mxsfb_attach_bridge(mxsfb);
+	if (ret) {
+		dev_err(drm->dev, "Cannot connect bridge: %d\n", ret);
+		goto err_vblank;
 	}
 
 	drm->mode_config.min_width	= MXSFB_MIN_XRES;
@@ -288,7 +283,7 @@ static int mxsfb_load(struct drm_device *drm, unsigned long flags)
 
 	if (ret < 0) {
 		dev_err(drm->dev, "Failed to install IRQ handler\n");
-		goto err_irq;
+		goto err_vblank;
 	}
 
 	drm_kms_helper_poll_init(drm);
@@ -299,8 +294,6 @@ static int mxsfb_load(struct drm_device *drm, unsigned long flags)
 
 	return 0;
 
-err_irq:
-	drm_panel_detach(mxsfb->panel);
 err_vblank:
 	pm_runtime_disable(drm->dev);
 
diff --git a/drivers/gpu/drm/mxsfb/mxsfb_drv.h b/drivers/gpu/drm/mxsfb/mxsfb_drv.h
index 0b65b5194a9c..0e3e5a63bbf9 100644
--- a/drivers/gpu/drm/mxsfb/mxsfb_drv.h
+++ b/drivers/gpu/drm/mxsfb/mxsfb_drv.h
@@ -8,6 +8,8 @@
 #ifndef __MXSFB_DRV_H__
 #define __MXSFB_DRV_H__
 
+struct drm_device;
+
 struct mxsfb_devdata {
 	unsigned int	 transfer_count;
 	unsigned int	 cur_buf;
@@ -26,10 +28,9 @@ struct mxsfb_drm_private {
 	struct clk			*clk_axi;
 	struct clk			*clk_disp_axi;
 
+	struct drm_device		*drm;
 	struct drm_simple_display_pipe	pipe;
-	struct drm_connector		panel_connector;
 	struct drm_connector		*connector;
-	struct drm_panel		*panel;
 	struct drm_bridge		*bridge;
 };
 
diff --git a/drivers/gpu/drm/mxsfb/mxsfb_out.c b/drivers/gpu/drm/mxsfb/mxsfb_out.c
deleted file mode 100644
index 9eca1605d11d..000000000000
--- a/drivers/gpu/drm/mxsfb/mxsfb_out.c
+++ /dev/null
@@ -1,99 +0,0 @@
-// SPDX-License-Identifier: GPL-2.0-or-later
-/*
- * Copyright (C) 2016 Marek Vasut <marex@denx.de>
- */
-
-#include <linux/of_graph.h>
-
-#include <drm/drm_atomic.h>
-#include <drm/drm_atomic_helper.h>
-#include <drm/drm_crtc.h>
-#include <drm/drm_fb_cma_helper.h>
-#include <drm/drm_gem_cma_helper.h>
-#include <drm/drm_of.h>
-#include <drm/drm_panel.h>
-#include <drm/drm_plane_helper.h>
-#include <drm/drm_probe_helper.h>
-#include <drm/drm_simple_kms_helper.h>
-
-#include "mxsfb_drv.h"
-
-static struct mxsfb_drm_private *
-drm_connector_to_mxsfb_drm_private(struct drm_connector *connector)
-{
-	return container_of(connector, struct mxsfb_drm_private,
-			    panel_connector);
-}
-
-static int mxsfb_panel_get_modes(struct drm_connector *connector)
-{
-	struct mxsfb_drm_private *mxsfb =
-			drm_connector_to_mxsfb_drm_private(connector);
-
-	if (mxsfb->panel)
-		return drm_panel_get_modes(mxsfb->panel, connector);
-
-	return 0;
-}
-
-static const struct
-drm_connector_helper_funcs mxsfb_panel_connector_helper_funcs = {
-	.get_modes = mxsfb_panel_get_modes,
-};
-
-static enum drm_connector_status
-mxsfb_panel_connector_detect(struct drm_connector *connector, bool force)
-{
-	struct mxsfb_drm_private *mxsfb =
-			drm_connector_to_mxsfb_drm_private(connector);
-
-	if (mxsfb->panel)
-		return connector_status_connected;
-
-	return connector_status_disconnected;
-}
-
-static void mxsfb_panel_connector_destroy(struct drm_connector *connector)
-{
-	struct mxsfb_drm_private *mxsfb =
-			drm_connector_to_mxsfb_drm_private(connector);
-
-	if (mxsfb->panel)
-		drm_panel_detach(mxsfb->panel);
-
-	drm_connector_unregister(connector);
-	drm_connector_cleanup(connector);
-}
-
-static const struct drm_connector_funcs mxsfb_panel_connector_funcs = {
-	.detect			= mxsfb_panel_connector_detect,
-	.fill_modes		= drm_helper_probe_single_connector_modes,
-	.destroy		= mxsfb_panel_connector_destroy,
-	.reset			= drm_atomic_helper_connector_reset,
-	.atomic_duplicate_state	= drm_atomic_helper_connector_duplicate_state,
-	.atomic_destroy_state	= drm_atomic_helper_connector_destroy_state,
-};
-
-int mxsfb_create_output(struct drm_device *drm)
-{
-	struct mxsfb_drm_private *mxsfb = drm->dev_private;
-	int ret;
-
-	ret = drm_of_find_panel_or_bridge(drm->dev->of_node, 0, 0,
-					  &mxsfb->panel, &mxsfb->bridge);
-	if (ret)
-		return ret;
-
-	if (mxsfb->panel) {
-		mxsfb->connector = &mxsfb->panel_connector;
-		mxsfb->connector->dpms = DRM_MODE_DPMS_OFF;
-		mxsfb->connector->polled = 0;
-		drm_connector_helper_add(mxsfb->connector,
-					 &mxsfb_panel_connector_helper_funcs);
-		ret = drm_connector_init(drm, mxsfb->connector,
-					 &mxsfb_panel_connector_funcs,
-					 DRM_MODE_CONNECTOR_Unknown);
-	}
-
-	return ret;
-}
-- 
Regards,

Laurent Pinchart

_______________________________________________
dri-devel mailing list
dri-devel@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/dri-devel

^ permalink raw reply related	[flat|nested] 62+ messages in thread

* [PATCH 03/21] drm: mxsfb: Use BIT() macro to define register bitfields
  2020-03-09 19:51 [PATCH 00/21] drm: mxsfb: Add i.MX7 support Laurent Pinchart
  2020-03-09 19:51 ` [PATCH 01/21] drm: mxsfb: Remove fbdev leftovers Laurent Pinchart
  2020-03-09 19:51 ` [PATCH 02/21] drm: mxsfb: Use drm_panel_bridge Laurent Pinchart
@ 2020-03-09 19:51 ` Laurent Pinchart
  2020-03-23 21:34   ` Stefan Agner
  2020-03-09 19:51 ` [PATCH 04/21] drm: mxsfb: Remove unused macros from mxsfb_regs.h Laurent Pinchart
                   ` (20 subsequent siblings)
  23 siblings, 1 reply; 62+ messages in thread
From: Laurent Pinchart @ 2020-03-09 19:51 UTC (permalink / raw)
  To: dri-devel; +Cc: Marek Vasut, kernel, linux-imx

Using BIT() is preferred over manual shifts as it's more readable,
handles the 1 << 31 case properly, and avoids other mistakes as shown by
the DEBUG0_HSYNC and DEBUG0_VSYNC bits (that are currently unused). Use
it.

Signed-off-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
---
 drivers/gpu/drm/mxsfb/mxsfb_regs.h | 56 +++++++++++++++---------------
 1 file changed, 28 insertions(+), 28 deletions(-)

diff --git a/drivers/gpu/drm/mxsfb/mxsfb_regs.h b/drivers/gpu/drm/mxsfb/mxsfb_regs.h
index 932d7ea08fd5..713d8f830135 100644
--- a/drivers/gpu/drm/mxsfb/mxsfb_regs.h
+++ b/drivers/gpu/drm/mxsfb/mxsfb_regs.h
@@ -28,51 +28,51 @@
 #define LCDC_V4_DEBUG0			0x1d0
 #define LCDC_V3_DEBUG0			0x1f0
 
-#define CTRL_SFTRST			(1 << 31)
-#define CTRL_CLKGATE			(1 << 30)
-#define CTRL_BYPASS_COUNT		(1 << 19)
-#define CTRL_VSYNC_MODE			(1 << 18)
-#define CTRL_DOTCLK_MODE		(1 << 17)
-#define CTRL_DATA_SELECT		(1 << 16)
+#define CTRL_SFTRST			BIT(31)
+#define CTRL_CLKGATE			BIT(30)
+#define CTRL_BYPASS_COUNT		BIT(19)
+#define CTRL_VSYNC_MODE			BIT(18)
+#define CTRL_DOTCLK_MODE		BIT(17)
+#define CTRL_DATA_SELECT		BIT(16)
 #define CTRL_SET_BUS_WIDTH(x)		(((x) & 0x3) << 10)
 #define CTRL_GET_BUS_WIDTH(x)		(((x) >> 10) & 0x3)
 #define CTRL_BUS_WIDTH_MASK		(0x3 << 10)
 #define CTRL_SET_WORD_LENGTH(x)		(((x) & 0x3) << 8)
 #define CTRL_GET_WORD_LENGTH(x)		(((x) >> 8) & 0x3)
-#define CTRL_MASTER			(1 << 5)
-#define CTRL_DF16			(1 << 3)
-#define CTRL_DF18			(1 << 2)
-#define CTRL_DF24			(1 << 1)
-#define CTRL_RUN			(1 << 0)
+#define CTRL_MASTER			BIT(5)
+#define CTRL_DF16			BIT(3)
+#define CTRL_DF18			BIT(2)
+#define CTRL_DF24			BIT(1)
+#define CTRL_RUN			BIT(0)
 
-#define CTRL1_FIFO_CLEAR		(1 << 21)
+#define CTRL1_FIFO_CLEAR		BIT(21)
 #define CTRL1_SET_BYTE_PACKAGING(x)	(((x) & 0xf) << 16)
 #define CTRL1_GET_BYTE_PACKAGING(x)	(((x) >> 16) & 0xf)
-#define CTRL1_CUR_FRAME_DONE_IRQ_EN	(1 << 13)
-#define CTRL1_CUR_FRAME_DONE_IRQ	(1 << 9)
+#define CTRL1_CUR_FRAME_DONE_IRQ_EN	BIT(13)
+#define CTRL1_CUR_FRAME_DONE_IRQ	BIT(9)
 
 #define TRANSFER_COUNT_SET_VCOUNT(x)	(((x) & 0xffff) << 16)
 #define TRANSFER_COUNT_GET_VCOUNT(x)	(((x) >> 16) & 0xffff)
 #define TRANSFER_COUNT_SET_HCOUNT(x)	((x) & 0xffff)
 #define TRANSFER_COUNT_GET_HCOUNT(x)	((x) & 0xffff)
 
-#define VDCTRL0_ENABLE_PRESENT		(1 << 28)
-#define VDCTRL0_VSYNC_ACT_HIGH		(1 << 27)
-#define VDCTRL0_HSYNC_ACT_HIGH		(1 << 26)
-#define VDCTRL0_DOTCLK_ACT_FALLING	(1 << 25)
-#define VDCTRL0_ENABLE_ACT_HIGH		(1 << 24)
-#define VDCTRL0_VSYNC_PERIOD_UNIT	(1 << 21)
-#define VDCTRL0_VSYNC_PULSE_WIDTH_UNIT	(1 << 20)
-#define VDCTRL0_HALF_LINE		(1 << 19)
-#define VDCTRL0_HALF_LINE_MODE		(1 << 18)
+#define VDCTRL0_ENABLE_PRESENT		BIT(28)
+#define VDCTRL0_VSYNC_ACT_HIGH		BIT(27)
+#define VDCTRL0_HSYNC_ACT_HIGH		BIT(26)
+#define VDCTRL0_DOTCLK_ACT_FALLING	BIT(25)
+#define VDCTRL0_ENABLE_ACT_HIGH		BIT(24)
+#define VDCTRL0_VSYNC_PERIOD_UNIT	BIT(21)
+#define VDCTRL0_VSYNC_PULSE_WIDTH_UNIT	BIT(20)
+#define VDCTRL0_HALF_LINE		BIT(19)
+#define VDCTRL0_HALF_LINE_MODE		BIT(18)
 #define VDCTRL0_SET_VSYNC_PULSE_WIDTH(x) ((x) & 0x3ffff)
 #define VDCTRL0_GET_VSYNC_PULSE_WIDTH(x) ((x) & 0x3ffff)
 
 #define VDCTRL2_SET_HSYNC_PERIOD(x)	((x) & 0x3ffff)
 #define VDCTRL2_GET_HSYNC_PERIOD(x)	((x) & 0x3ffff)
 
-#define VDCTRL3_MUX_SYNC_SIGNALS	(1 << 29)
-#define VDCTRL3_VSYNC_ONLY		(1 << 28)
+#define VDCTRL3_MUX_SYNC_SIGNALS	BIT(29)
+#define VDCTRL3_VSYNC_ONLY		BIT(28)
 #define SET_HOR_WAIT_CNT(x)		(((x) & 0xfff) << 16)
 #define GET_HOR_WAIT_CNT(x)		(((x) >> 16) & 0xfff)
 #define SET_VERT_WAIT_CNT(x)		((x) & 0xffff)
@@ -80,11 +80,11 @@
 
 #define VDCTRL4_SET_DOTCLK_DLY(x)	(((x) & 0x7) << 29) /* v4 only */
 #define VDCTRL4_GET_DOTCLK_DLY(x)	(((x) >> 29) & 0x7) /* v4 only */
-#define VDCTRL4_SYNC_SIGNALS_ON		(1 << 18)
+#define VDCTRL4_SYNC_SIGNALS_ON		BIT(18)
 #define SET_DOTCLK_H_VALID_DATA_CNT(x)	((x) & 0x3ffff)
 
-#define DEBUG0_HSYNC			(1 < 26)
-#define DEBUG0_VSYNC			(1 < 25)
+#define DEBUG0_HSYNC			BIT(26)
+#define DEBUG0_VSYNC			BIT(25)
 
 #define MXSFB_MIN_XRES			120
 #define MXSFB_MIN_YRES			120
-- 
Regards,

Laurent Pinchart

_______________________________________________
dri-devel mailing list
dri-devel@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/dri-devel

^ permalink raw reply related	[flat|nested] 62+ messages in thread

* [PATCH 04/21] drm: mxsfb: Remove unused macros from mxsfb_regs.h
  2020-03-09 19:51 [PATCH 00/21] drm: mxsfb: Add i.MX7 support Laurent Pinchart
                   ` (2 preceding siblings ...)
  2020-03-09 19:51 ` [PATCH 03/21] drm: mxsfb: Use BIT() macro to define register bitfields Laurent Pinchart
@ 2020-03-09 19:51 ` Laurent Pinchart
  2020-03-23 21:36   ` Stefan Agner
  2020-03-09 19:52 ` [PATCH 05/21] drm: mxsfb: Clarify format and bus width configuration Laurent Pinchart
                   ` (19 subsequent siblings)
  23 siblings, 1 reply; 62+ messages in thread
From: Laurent Pinchart @ 2020-03-09 19:51 UTC (permalink / raw)
  To: dri-devel; +Cc: Marek Vasut, kernel, linux-imx

mxsfb_regs.h defines macros related to register bits. Some of them are
not used and don't clearly map to any particular register, so their
purpose isn't known. Remove them.

Signed-off-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
---
 drivers/gpu/drm/mxsfb/mxsfb_regs.h | 8 --------
 1 file changed, 8 deletions(-)

diff --git a/drivers/gpu/drm/mxsfb/mxsfb_regs.h b/drivers/gpu/drm/mxsfb/mxsfb_regs.h
index 713d8f830135..78e6cb754712 100644
--- a/drivers/gpu/drm/mxsfb/mxsfb_regs.h
+++ b/drivers/gpu/drm/mxsfb/mxsfb_regs.h
@@ -91,17 +91,9 @@
 #define MXSFB_MAX_XRES			0xffff
 #define MXSFB_MAX_YRES			0xffff
 
-#define RED 0
-#define GREEN 1
-#define BLUE 2
-#define TRANSP 3
-
 #define STMLCDIF_8BIT  1 /* pixel data bus to the display is of 8 bit width */
 #define STMLCDIF_16BIT 0 /* pixel data bus to the display is of 16 bit width */
 #define STMLCDIF_18BIT 2 /* pixel data bus to the display is of 18 bit width */
 #define STMLCDIF_24BIT 3 /* pixel data bus to the display is of 24 bit width */
 
-#define MXSFB_SYNC_DATA_ENABLE_HIGH_ACT	(1 << 6)
-#define MXSFB_SYNC_DOTCLK_FALLING_ACT	(1 << 7) /* negative edge sampling */
-
 #endif /* __MXSFB_REGS_H__ */
-- 
Regards,

Laurent Pinchart

_______________________________________________
dri-devel mailing list
dri-devel@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/dri-devel

^ permalink raw reply related	[flat|nested] 62+ messages in thread

* [PATCH 05/21] drm: mxsfb: Clarify format and bus width configuration
  2020-03-09 19:51 [PATCH 00/21] drm: mxsfb: Add i.MX7 support Laurent Pinchart
                   ` (3 preceding siblings ...)
  2020-03-09 19:51 ` [PATCH 04/21] drm: mxsfb: Remove unused macros from mxsfb_regs.h Laurent Pinchart
@ 2020-03-09 19:52 ` Laurent Pinchart
  2020-03-23 21:42   ` Stefan Agner
  2020-03-09 19:52 ` [PATCH 06/21] drm: mxsfb: Pass mxsfb_drm_private pointer to mxsfb_reset_block() Laurent Pinchart
                   ` (18 subsequent siblings)
  23 siblings, 1 reply; 62+ messages in thread
From: Laurent Pinchart @ 2020-03-09 19:52 UTC (permalink / raw)
  To: dri-devel; +Cc: Marek Vasut, kernel, linux-imx

Replace the convoluted way to set the format and bus width through
difficult to read macros with more explicit ones. Also remove the
outdated comment related to the limitations on bus width setting as it
doesn't apply anymore (the bus width can be specified through the
display_info bus format).

Signed-off-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
---
 drivers/gpu/drm/mxsfb/mxsfb_crtc.c | 17 +++++------------
 drivers/gpu/drm/mxsfb/mxsfb_regs.h | 17 ++++++++---------
 2 files changed, 13 insertions(+), 21 deletions(-)

diff --git a/drivers/gpu/drm/mxsfb/mxsfb_crtc.c b/drivers/gpu/drm/mxsfb/mxsfb_crtc.c
index b69ace8bf526..8b6339316929 100644
--- a/drivers/gpu/drm/mxsfb/mxsfb_crtc.c
+++ b/drivers/gpu/drm/mxsfb/mxsfb_crtc.c
@@ -52,13 +52,6 @@ static int mxsfb_set_pixel_fmt(struct mxsfb_drm_private *mxsfb)
 
 	ctrl = CTRL_BYPASS_COUNT | CTRL_MASTER;
 
-	/*
-	 * WARNING: The bus width, CTRL_SET_BUS_WIDTH(), is configured to
-	 * match the selected mode here. This differs from the original
-	 * MXSFB driver, which had the option to configure the bus width
-	 * to arbitrary value. This limitation should not pose an issue.
-	 */
-
 	/* CTRL1 contains IRQ config and status bits, preserve those. */
 	ctrl1 = readl(mxsfb->base + LCDC_CTRL1);
 	ctrl1 &= CTRL1_CUR_FRAME_DONE_IRQ_EN | CTRL1_CUR_FRAME_DONE_IRQ;
@@ -66,12 +59,12 @@ static int mxsfb_set_pixel_fmt(struct mxsfb_drm_private *mxsfb)
 	switch (format) {
 	case DRM_FORMAT_RGB565:
 		dev_dbg(drm->dev, "Setting up RGB565 mode\n");
-		ctrl |= CTRL_SET_WORD_LENGTH(0);
+		ctrl |= CTRL_WORD_LENGTH_16;
 		ctrl1 |= CTRL1_SET_BYTE_PACKAGING(0xf);
 		break;
 	case DRM_FORMAT_XRGB8888:
 		dev_dbg(drm->dev, "Setting up XRGB8888 mode\n");
-		ctrl |= CTRL_SET_WORD_LENGTH(3);
+		ctrl |= CTRL_WORD_LENGTH_24;
 		/* Do not use packed pixels = one pixel per word instead. */
 		ctrl1 |= CTRL1_SET_BYTE_PACKAGING(0x7);
 		break;
@@ -104,13 +97,13 @@ static void mxsfb_set_bus_fmt(struct mxsfb_drm_private *mxsfb)
 	reg &= ~CTRL_BUS_WIDTH_MASK;
 	switch (bus_format) {
 	case MEDIA_BUS_FMT_RGB565_1X16:
-		reg |= CTRL_SET_BUS_WIDTH(STMLCDIF_16BIT);
+		reg |= CTRL_BUS_WIDTH_16;
 		break;
 	case MEDIA_BUS_FMT_RGB666_1X18:
-		reg |= CTRL_SET_BUS_WIDTH(STMLCDIF_18BIT);
+		reg |= CTRL_BUS_WIDTH_18;
 		break;
 	case MEDIA_BUS_FMT_RGB888_1X24:
-		reg |= CTRL_SET_BUS_WIDTH(STMLCDIF_24BIT);
+		reg |= CTRL_BUS_WIDTH_24;
 		break;
 	default:
 		dev_err(drm->dev, "Unknown media bus format %d\n", bus_format);
diff --git a/drivers/gpu/drm/mxsfb/mxsfb_regs.h b/drivers/gpu/drm/mxsfb/mxsfb_regs.h
index 78e6cb754712..8ebb52bb1b46 100644
--- a/drivers/gpu/drm/mxsfb/mxsfb_regs.h
+++ b/drivers/gpu/drm/mxsfb/mxsfb_regs.h
@@ -34,11 +34,15 @@
 #define CTRL_VSYNC_MODE			BIT(18)
 #define CTRL_DOTCLK_MODE		BIT(17)
 #define CTRL_DATA_SELECT		BIT(16)
-#define CTRL_SET_BUS_WIDTH(x)		(((x) & 0x3) << 10)
-#define CTRL_GET_BUS_WIDTH(x)		(((x) >> 10) & 0x3)
+#define CTRL_BUS_WIDTH_16		(0 << 10)
+#define CTRL_BUS_WIDTH_8		(1 << 10)
+#define CTRL_BUS_WIDTH_18		(2 << 10)
+#define CTRL_BUS_WIDTH_24		(3 << 10)
 #define CTRL_BUS_WIDTH_MASK		(0x3 << 10)
-#define CTRL_SET_WORD_LENGTH(x)		(((x) & 0x3) << 8)
-#define CTRL_GET_WORD_LENGTH(x)		(((x) >> 8) & 0x3)
+#define CTRL_WORD_LENGTH_16		(0 << 8)
+#define CTRL_WORD_LENGTH_8		(1 << 8)
+#define CTRL_WORD_LENGTH_18		(2 << 8)
+#define CTRL_WORD_LENGTH_24		(3 << 8)
 #define CTRL_MASTER			BIT(5)
 #define CTRL_DF16			BIT(3)
 #define CTRL_DF18			BIT(2)
@@ -91,9 +95,4 @@
 #define MXSFB_MAX_XRES			0xffff
 #define MXSFB_MAX_YRES			0xffff
 
-#define STMLCDIF_8BIT  1 /* pixel data bus to the display is of 8 bit width */
-#define STMLCDIF_16BIT 0 /* pixel data bus to the display is of 16 bit width */
-#define STMLCDIF_18BIT 2 /* pixel data bus to the display is of 18 bit width */
-#define STMLCDIF_24BIT 3 /* pixel data bus to the display is of 24 bit width */
-
 #endif /* __MXSFB_REGS_H__ */
-- 
Regards,

Laurent Pinchart

_______________________________________________
dri-devel mailing list
dri-devel@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/dri-devel

^ permalink raw reply related	[flat|nested] 62+ messages in thread

* [PATCH 06/21] drm: mxsfb: Pass mxsfb_drm_private pointer to mxsfb_reset_block()
  2020-03-09 19:51 [PATCH 00/21] drm: mxsfb: Add i.MX7 support Laurent Pinchart
                   ` (4 preceding siblings ...)
  2020-03-09 19:52 ` [PATCH 05/21] drm: mxsfb: Clarify format and bus width configuration Laurent Pinchart
@ 2020-03-09 19:52 ` Laurent Pinchart
  2020-03-23 21:43   ` Stefan Agner
  2020-03-09 19:52 ` [PATCH 07/21] drm: mxsfb: Use LCDC_CTRL register name explicitly Laurent Pinchart
                   ` (17 subsequent siblings)
  23 siblings, 1 reply; 62+ messages in thread
From: Laurent Pinchart @ 2020-03-09 19:52 UTC (permalink / raw)
  To: dri-devel; +Cc: Marek Vasut, kernel, linux-imx

The mxsfb_reset_block() function isn't special, pass it the
mxsfb_drm_private pointer instead of a pointer to the base address.

Signed-off-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
---
 drivers/gpu/drm/mxsfb/mxsfb_crtc.c | 12 ++++++------
 1 file changed, 6 insertions(+), 6 deletions(-)

diff --git a/drivers/gpu/drm/mxsfb/mxsfb_crtc.c b/drivers/gpu/drm/mxsfb/mxsfb_crtc.c
index 8b6339316929..be60c4021e2f 100644
--- a/drivers/gpu/drm/mxsfb/mxsfb_crtc.c
+++ b/drivers/gpu/drm/mxsfb/mxsfb_crtc.c
@@ -166,21 +166,21 @@ static int clear_poll_bit(void __iomem *addr, u32 mask)
 	return readl_poll_timeout(addr, reg, !(reg & mask), 0, RESET_TIMEOUT);
 }
 
-static int mxsfb_reset_block(void __iomem *reset_addr)
+static int mxsfb_reset_block(struct mxsfb_drm_private *mxsfb)
 {
 	int ret;
 
-	ret = clear_poll_bit(reset_addr, MODULE_SFTRST);
+	ret = clear_poll_bit(mxsfb->base, MODULE_SFTRST);
 	if (ret)
 		return ret;
 
-	writel(MODULE_CLKGATE, reset_addr + MXS_CLR_ADDR);
+	writel(MODULE_CLKGATE, mxsfb->base + MXS_CLR_ADDR);
 
-	ret = clear_poll_bit(reset_addr, MODULE_SFTRST);
+	ret = clear_poll_bit(mxsfb->base, MODULE_SFTRST);
 	if (ret)
 		return ret;
 
-	return clear_poll_bit(reset_addr, MODULE_CLKGATE);
+	return clear_poll_bit(mxsfb->base, MODULE_CLKGATE);
 }
 
 static dma_addr_t mxsfb_get_fb_paddr(struct mxsfb_drm_private *mxsfb)
@@ -213,7 +213,7 @@ static void mxsfb_crtc_mode_set_nofb(struct mxsfb_drm_private *mxsfb)
 	 */
 
 	/* Mandatory eLCDIF reset as per the Reference Manual */
-	err = mxsfb_reset_block(mxsfb->base);
+	err = mxsfb_reset_block(mxsfb);
 	if (err)
 		return;
 
-- 
Regards,

Laurent Pinchart

_______________________________________________
dri-devel mailing list
dri-devel@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/dri-devel

^ permalink raw reply related	[flat|nested] 62+ messages in thread

* [PATCH 07/21] drm: mxsfb: Use LCDC_CTRL register name explicitly
  2020-03-09 19:51 [PATCH 00/21] drm: mxsfb: Add i.MX7 support Laurent Pinchart
                   ` (5 preceding siblings ...)
  2020-03-09 19:52 ` [PATCH 06/21] drm: mxsfb: Pass mxsfb_drm_private pointer to mxsfb_reset_block() Laurent Pinchart
@ 2020-03-09 19:52 ` Laurent Pinchart
  2020-03-23 21:48   ` Stefan Agner
  2020-03-09 19:52 ` [PATCH 08/21] drm: mxsfb: Remove register definitions from mxsfb_crtc.c Laurent Pinchart
                   ` (16 subsequent siblings)
  23 siblings, 1 reply; 62+ messages in thread
From: Laurent Pinchart @ 2020-03-09 19:52 UTC (permalink / raw)
  To: dri-devel; +Cc: Marek Vasut, kernel, linux-imx

The LCDC_CTRL register is located at address 0x0000. Some of the
accesses to the register simply use the mxsfb->base address. Reference
the LCDC_CTRL register explicitly instead to clarify the code.

Signed-off-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
---
 drivers/gpu/drm/mxsfb/mxsfb_crtc.c | 8 ++++----
 1 file changed, 4 insertions(+), 4 deletions(-)

diff --git a/drivers/gpu/drm/mxsfb/mxsfb_crtc.c b/drivers/gpu/drm/mxsfb/mxsfb_crtc.c
index be60c4021e2f..722bd9b4f5f9 100644
--- a/drivers/gpu/drm/mxsfb/mxsfb_crtc.c
+++ b/drivers/gpu/drm/mxsfb/mxsfb_crtc.c
@@ -170,17 +170,17 @@ static int mxsfb_reset_block(struct mxsfb_drm_private *mxsfb)
 {
 	int ret;
 
-	ret = clear_poll_bit(mxsfb->base, MODULE_SFTRST);
+	ret = clear_poll_bit(mxsfb->base + LCDC_CTRL, MODULE_SFTRST);
 	if (ret)
 		return ret;
 
-	writel(MODULE_CLKGATE, mxsfb->base + MXS_CLR_ADDR);
+	writel(MODULE_CLKGATE, mxsfb->base + LCDC_CTRL + MXS_CLR_ADDR);
 
-	ret = clear_poll_bit(mxsfb->base, MODULE_SFTRST);
+	ret = clear_poll_bit(mxsfb->base + LCDC_CTRL, MODULE_SFTRST);
 	if (ret)
 		return ret;
 
-	return clear_poll_bit(mxsfb->base, MODULE_CLKGATE);
+	return clear_poll_bit(mxsfb->base + LCDC_CTRL, MODULE_CLKGATE);
 }
 
 static dma_addr_t mxsfb_get_fb_paddr(struct mxsfb_drm_private *mxsfb)
-- 
Regards,

Laurent Pinchart

_______________________________________________
dri-devel mailing list
dri-devel@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/dri-devel

^ permalink raw reply related	[flat|nested] 62+ messages in thread

* [PATCH 08/21] drm: mxsfb: Remove register definitions from mxsfb_crtc.c
  2020-03-09 19:51 [PATCH 00/21] drm: mxsfb: Add i.MX7 support Laurent Pinchart
                   ` (6 preceding siblings ...)
  2020-03-09 19:52 ` [PATCH 07/21] drm: mxsfb: Use LCDC_CTRL register name explicitly Laurent Pinchart
@ 2020-03-09 19:52 ` Laurent Pinchart
  2020-03-23 21:49   ` Stefan Agner
  2020-03-09 19:52 ` [PATCH 09/21] drm: mxsfb: Remove unneeded includes Laurent Pinchart
                   ` (15 subsequent siblings)
  23 siblings, 1 reply; 62+ messages in thread
From: Laurent Pinchart @ 2020-03-09 19:52 UTC (permalink / raw)
  To: dri-devel; +Cc: Marek Vasut, kernel, linux-imx

mxsfb_crtc.c defines several macros related to register addresses and
bit, which duplicates macros from mxsfb_regs.h. Use the macros from
mxsfb_regs.h instead and remove them.

Signed-off-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
---
 drivers/gpu/drm/mxsfb/mxsfb_crtc.c | 14 +++++---------
 1 file changed, 5 insertions(+), 9 deletions(-)

diff --git a/drivers/gpu/drm/mxsfb/mxsfb_crtc.c b/drivers/gpu/drm/mxsfb/mxsfb_crtc.c
index 722bd9b4f5f9..aef72adabf41 100644
--- a/drivers/gpu/drm/mxsfb/mxsfb_crtc.c
+++ b/drivers/gpu/drm/mxsfb/mxsfb_crtc.c
@@ -29,10 +29,6 @@
 #include "mxsfb_drv.h"
 #include "mxsfb_regs.h"
 
-#define MXS_SET_ADDR		0x4
-#define MXS_CLR_ADDR		0x8
-#define MODULE_CLKGATE		BIT(30)
-#define MODULE_SFTRST		BIT(31)
 /* 1 second delay should be plenty of time for block reset */
 #define RESET_TIMEOUT		1000000
 
@@ -162,7 +158,7 @@ static int clear_poll_bit(void __iomem *addr, u32 mask)
 {
 	u32 reg;
 
-	writel(mask, addr + MXS_CLR_ADDR);
+	writel(mask, addr + REG_CLR);
 	return readl_poll_timeout(addr, reg, !(reg & mask), 0, RESET_TIMEOUT);
 }
 
@@ -170,17 +166,17 @@ static int mxsfb_reset_block(struct mxsfb_drm_private *mxsfb)
 {
 	int ret;
 
-	ret = clear_poll_bit(mxsfb->base + LCDC_CTRL, MODULE_SFTRST);
+	ret = clear_poll_bit(mxsfb->base + LCDC_CTRL, CTRL_SFTRST);
 	if (ret)
 		return ret;
 
-	writel(MODULE_CLKGATE, mxsfb->base + LCDC_CTRL + MXS_CLR_ADDR);
+	writel(CTRL_CLKGATE, mxsfb->base + LCDC_CTRL + REG_CLR);
 
-	ret = clear_poll_bit(mxsfb->base + LCDC_CTRL, MODULE_SFTRST);
+	ret = clear_poll_bit(mxsfb->base + LCDC_CTRL, CTRL_SFTRST);
 	if (ret)
 		return ret;
 
-	return clear_poll_bit(mxsfb->base + LCDC_CTRL, MODULE_CLKGATE);
+	return clear_poll_bit(mxsfb->base + LCDC_CTRL, CTRL_CLKGATE);
 }
 
 static dma_addr_t mxsfb_get_fb_paddr(struct mxsfb_drm_private *mxsfb)
-- 
Regards,

Laurent Pinchart

_______________________________________________
dri-devel mailing list
dri-devel@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/dri-devel

^ permalink raw reply related	[flat|nested] 62+ messages in thread

* [PATCH 09/21] drm: mxsfb: Remove unneeded includes
  2020-03-09 19:51 [PATCH 00/21] drm: mxsfb: Add i.MX7 support Laurent Pinchart
                   ` (7 preceding siblings ...)
  2020-03-09 19:52 ` [PATCH 08/21] drm: mxsfb: Remove register definitions from mxsfb_crtc.c Laurent Pinchart
@ 2020-03-09 19:52 ` Laurent Pinchart
  2020-03-23 21:53   ` Stefan Agner
  2020-03-09 19:52 ` [PATCH 10/21] drm: mxsfb: Stop using DRM simple display pipeline helper Laurent Pinchart
                   ` (14 subsequent siblings)
  23 siblings, 1 reply; 62+ messages in thread
From: Laurent Pinchart @ 2020-03-09 19:52 UTC (permalink / raw)
  To: dri-devel; +Cc: Marek Vasut, kernel, linux-imx

A fair number of includes are not needed. Drop them, and add a couple of
required includes that were included indirectly.

Signed-off-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
---
 drivers/gpu/drm/mxsfb/mxsfb_crtc.c | 12 +++---------
 drivers/gpu/drm/mxsfb/mxsfb_drv.c  |  5 -----
 2 files changed, 3 insertions(+), 14 deletions(-)

diff --git a/drivers/gpu/drm/mxsfb/mxsfb_crtc.c b/drivers/gpu/drm/mxsfb/mxsfb_crtc.c
index aef72adabf41..c4f1575b4210 100644
--- a/drivers/gpu/drm/mxsfb/mxsfb_crtc.c
+++ b/drivers/gpu/drm/mxsfb/mxsfb_crtc.c
@@ -10,19 +10,13 @@
 
 #include <linux/clk.h>
 #include <linux/iopoll.h>
-#include <linux/of_graph.h>
-#include <linux/platform_data/simplefb.h>
+#include <linux/spinlock.h>
 
-#include <video/videomode.h>
-
-#include <drm/drm_atomic_helper.h>
+#include <drm/drm_bridge.h>
 #include <drm/drm_crtc.h>
 #include <drm/drm_fb_cma_helper.h>
-#include <drm/drm_fb_helper.h>
+#include <drm/drm_fourcc.h>
 #include <drm/drm_gem_cma_helper.h>
-#include <drm/drm_of.h>
-#include <drm/drm_plane_helper.h>
-#include <drm/drm_probe_helper.h>
 #include <drm/drm_simple_kms_helper.h>
 #include <drm/drm_vblank.h>
 
diff --git a/drivers/gpu/drm/mxsfb/mxsfb_drv.c b/drivers/gpu/drm/mxsfb/mxsfb_drv.c
index cffc70257bd3..204c1e52e9aa 100644
--- a/drivers/gpu/drm/mxsfb/mxsfb_drv.c
+++ b/drivers/gpu/drm/mxsfb/mxsfb_drv.c
@@ -9,15 +9,10 @@
  */
 
 #include <linux/clk.h>
-#include <linux/component.h>
 #include <linux/dma-mapping.h>
-#include <linux/list.h>
 #include <linux/module.h>
 #include <linux/of_device.h>
-#include <linux/of_graph.h>
-#include <linux/of_reserved_mem.h>
 #include <linux/pm_runtime.h>
-#include <linux/dma-resv.h>
 #include <linux/spinlock.h>
 
 #include <drm/drm_atomic.h>
-- 
Regards,

Laurent Pinchart

_______________________________________________
dri-devel mailing list
dri-devel@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/dri-devel

^ permalink raw reply related	[flat|nested] 62+ messages in thread

* [PATCH 10/21] drm: mxsfb: Stop using DRM simple display pipeline helper
  2020-03-09 19:51 [PATCH 00/21] drm: mxsfb: Add i.MX7 support Laurent Pinchart
                   ` (8 preceding siblings ...)
  2020-03-09 19:52 ` [PATCH 09/21] drm: mxsfb: Remove unneeded includes Laurent Pinchart
@ 2020-03-09 19:52 ` Laurent Pinchart
  2020-03-23 22:30   ` Stefan Agner
  2020-03-09 19:52 ` [PATCH 11/21] drm: mxsfb: Rename mxsfb_crtc.c to mxsfb_kms.c Laurent Pinchart
                   ` (13 subsequent siblings)
  23 siblings, 1 reply; 62+ messages in thread
From: Laurent Pinchart @ 2020-03-09 19:52 UTC (permalink / raw)
  To: dri-devel; +Cc: Marek Vasut, kernel, linux-imx

The DRM simple display pipeline helper only supports a single plane. In
order to prepare for support of the alpha plane on i.MX6SX and i.MX7,
move away from the helper. No new feature is added.

Signed-off-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
---
 drivers/gpu/drm/mxsfb/mxsfb_crtc.c | 184 ++++++++++++++++++++++++++---
 drivers/gpu/drm/mxsfb/mxsfb_drv.c  | 108 ++---------------
 drivers/gpu/drm/mxsfb/mxsfb_drv.h  |  23 ++--
 3 files changed, 197 insertions(+), 118 deletions(-)

diff --git a/drivers/gpu/drm/mxsfb/mxsfb_crtc.c b/drivers/gpu/drm/mxsfb/mxsfb_crtc.c
index c4f1575b4210..8f339adb8d04 100644
--- a/drivers/gpu/drm/mxsfb/mxsfb_crtc.c
+++ b/drivers/gpu/drm/mxsfb/mxsfb_crtc.c
@@ -9,15 +9,21 @@
  */
 
 #include <linux/clk.h>
+#include <linux/io.h>
 #include <linux/iopoll.h>
+#include <linux/pm_runtime.h>
 #include <linux/spinlock.h>
 
+#include <drm/drm_atomic.h>
+#include <drm/drm_atomic_helper.h>
 #include <drm/drm_bridge.h>
 #include <drm/drm_crtc.h>
+#include <drm/drm_encoder.h>
 #include <drm/drm_fb_cma_helper.h>
 #include <drm/drm_fourcc.h>
 #include <drm/drm_gem_cma_helper.h>
-#include <drm/drm_simple_kms_helper.h>
+#include <drm/drm_plane.h>
+#include <drm/drm_plane_helper.h>
 #include <drm/drm_vblank.h>
 
 #include "mxsfb_drv.h"
@@ -26,6 +32,10 @@
 /* 1 second delay should be plenty of time for block reset */
 #define RESET_TIMEOUT		1000000
 
+/* -----------------------------------------------------------------------------
+ * CRTC
+ */
+
 static u32 set_hsync_pulse_width(struct mxsfb_drm_private *mxsfb, u32 val)
 {
 	return (val & mxsfb->devdata->hs_wdth_mask) <<
@@ -35,9 +45,8 @@ static u32 set_hsync_pulse_width(struct mxsfb_drm_private *mxsfb, u32 val)
 /* Setup the MXSFB registers for decoding the pixels out of the framebuffer */
 static int mxsfb_set_pixel_fmt(struct mxsfb_drm_private *mxsfb)
 {
-	struct drm_crtc *crtc = &mxsfb->pipe.crtc;
-	struct drm_device *drm = crtc->dev;
-	const u32 format = crtc->primary->state->fb->format->format;
+	struct drm_device *drm = mxsfb->drm;
+	const u32 format = mxsfb->crtc.primary->state->fb->format->format;
 	u32 ctrl, ctrl1;
 
 	ctrl = CTRL_BYPASS_COUNT | CTRL_MASTER;
@@ -71,8 +80,7 @@ static int mxsfb_set_pixel_fmt(struct mxsfb_drm_private *mxsfb)
 
 static void mxsfb_set_bus_fmt(struct mxsfb_drm_private *mxsfb)
 {
-	struct drm_crtc *crtc = &mxsfb->pipe.crtc;
-	struct drm_device *drm = crtc->dev;
+	struct drm_device *drm = mxsfb->drm;
 	u32 bus_format = MEDIA_BUS_FMT_RGB888_1X24;
 	u32 reg;
 
@@ -175,7 +183,7 @@ static int mxsfb_reset_block(struct mxsfb_drm_private *mxsfb)
 
 static dma_addr_t mxsfb_get_fb_paddr(struct mxsfb_drm_private *mxsfb)
 {
-	struct drm_framebuffer *fb = mxsfb->pipe.plane.state->fb;
+	struct drm_framebuffer *fb = mxsfb->plane.state->fb;
 	struct drm_gem_cma_object *gem;
 
 	if (!fb)
@@ -190,8 +198,8 @@ static dma_addr_t mxsfb_get_fb_paddr(struct mxsfb_drm_private *mxsfb)
 
 static void mxsfb_crtc_mode_set_nofb(struct mxsfb_drm_private *mxsfb)
 {
-	struct drm_device *drm = mxsfb->pipe.crtc.dev;
-	struct drm_display_mode *m = &mxsfb->pipe.crtc.state->adjusted_mode;
+	struct drm_device *drm = mxsfb->crtc.dev;
+	struct drm_display_mode *m = &mxsfb->crtc.state->adjusted_mode;
 	u32 bus_flags = mxsfb->connector->display_info.bus_flags;
 	u32 vdctrl0, vsync_pulse_len, hsync_pulse_len;
 	int err;
@@ -273,10 +281,29 @@ static void mxsfb_crtc_mode_set_nofb(struct mxsfb_drm_private *mxsfb)
 	       mxsfb->base + LCDC_VDCTRL4);
 }
 
-void mxsfb_crtc_enable(struct mxsfb_drm_private *mxsfb)
+static int mxsfb_crtc_atomic_check(struct drm_crtc *crtc,
+				   struct drm_crtc_state *state)
 {
+	bool has_primary = state->plane_mask &
+			   drm_plane_mask(crtc->primary);
+
+	/* The primary plane has to be enabled when the CRTC is active. */
+	if (has_primary != state->active)
+		return -EINVAL;
+
+	/* TODO: Is this needed ? */
+	return drm_atomic_add_affected_planes(state->state, crtc);
+}
+
+static void mxsfb_crtc_atomic_enable(struct drm_crtc *crtc,
+				     struct drm_crtc_state *old_state)
+{
+	struct mxsfb_drm_private *mxsfb = to_mxsfb_drm_private(crtc->dev);
+	struct drm_device *drm = mxsfb->drm;
 	dma_addr_t paddr;
 
+	pm_runtime_get_sync(drm->dev);
+
 	mxsfb_enable_axi_clk(mxsfb);
 	mxsfb_crtc_mode_set_nofb(mxsfb);
 
@@ -290,17 +317,100 @@ void mxsfb_crtc_enable(struct mxsfb_drm_private *mxsfb)
 	mxsfb_enable_controller(mxsfb);
 }
 
-void mxsfb_crtc_disable(struct mxsfb_drm_private *mxsfb)
+static void mxsfb_crtc_atomic_disable(struct drm_crtc *crtc,
+				      struct drm_crtc_state *old_state)
 {
+	struct mxsfb_drm_private *mxsfb = to_mxsfb_drm_private(crtc->dev);
+	struct drm_device *drm = mxsfb->drm;
+	struct drm_pending_vblank_event *event;
+
 	mxsfb_disable_controller(mxsfb);
 	mxsfb_disable_axi_clk(mxsfb);
+
+	pm_runtime_put_sync(drm->dev);
+
+	spin_lock_irq(&drm->event_lock);
+	event = crtc->state->event;
+	if (event) {
+		crtc->state->event = NULL;
+		drm_crtc_send_vblank_event(crtc, event);
+	}
+	spin_unlock_irq(&drm->event_lock);
+}
+
+static int mxsfb_crtc_enable_vblank(struct drm_crtc *crtc)
+{
+	struct mxsfb_drm_private *mxsfb = to_mxsfb_drm_private(crtc->dev);
+
+	/* Clear and enable VBLANK IRQ */
+	mxsfb_enable_axi_clk(mxsfb);
+	writel(CTRL1_CUR_FRAME_DONE_IRQ, mxsfb->base + LCDC_CTRL1 + REG_CLR);
+	writel(CTRL1_CUR_FRAME_DONE_IRQ_EN, mxsfb->base + LCDC_CTRL1 + REG_SET);
+	mxsfb_disable_axi_clk(mxsfb);
+
+	return 0;
+}
+
+static void mxsfb_crtc_disable_vblank(struct drm_crtc *crtc)
+{
+	struct mxsfb_drm_private *mxsfb = to_mxsfb_drm_private(crtc->dev);
+
+	/* Disable and clear VBLANK IRQ */
+	mxsfb_enable_axi_clk(mxsfb);
+	writel(CTRL1_CUR_FRAME_DONE_IRQ_EN, mxsfb->base + LCDC_CTRL1 + REG_CLR);
+	writel(CTRL1_CUR_FRAME_DONE_IRQ, mxsfb->base + LCDC_CTRL1 + REG_CLR);
+	mxsfb_disable_axi_clk(mxsfb);
+}
+
+static const struct drm_crtc_helper_funcs mxsfb_crtc_helper_funcs = {
+	.atomic_check = mxsfb_crtc_atomic_check,
+	.atomic_enable = mxsfb_crtc_atomic_enable,
+	.atomic_disable = mxsfb_crtc_atomic_disable,
+};
+
+static const struct drm_crtc_funcs mxsfb_crtc_funcs = {
+	.reset = drm_atomic_helper_crtc_reset,
+	.destroy = drm_crtc_cleanup,
+	.set_config = drm_atomic_helper_set_config,
+	.page_flip = drm_atomic_helper_page_flip,
+	.atomic_duplicate_state = drm_atomic_helper_crtc_duplicate_state,
+	.atomic_destroy_state = drm_atomic_helper_crtc_destroy_state,
+	.enable_vblank = mxsfb_crtc_enable_vblank,
+	.disable_vblank = mxsfb_crtc_disable_vblank,
+};
+
+/* -----------------------------------------------------------------------------
+ * Encoder
+ */
+
+static const struct drm_encoder_funcs mxsfb_encoder_funcs = {
+	.destroy = drm_encoder_cleanup,
+};
+
+/* -----------------------------------------------------------------------------
+ * Planes
+ */
+
+static int mxsfb_plane_atomic_check(struct drm_plane *plane,
+				    struct drm_plane_state *plane_state)
+{
+	struct mxsfb_drm_private *mxsfb = to_mxsfb_drm_private(plane->dev);
+	struct drm_crtc_state *crtc_state;
+
+	crtc_state = drm_atomic_get_new_crtc_state(plane_state->state,
+						   &mxsfb->crtc);
+
+	return drm_atomic_helper_check_plane_state(plane_state, crtc_state,
+						   DRM_PLANE_HELPER_NO_SCALING,
+						   DRM_PLANE_HELPER_NO_SCALING,
+						   false, true);
 }
 
-void mxsfb_plane_atomic_update(struct mxsfb_drm_private *mxsfb,
-			       struct drm_plane_state *state)
+static void mxsfb_plane_atomic_update(struct drm_plane *plane,
+				      struct drm_plane_state *old_pstate)
 {
-	struct drm_simple_display_pipe *pipe = &mxsfb->pipe;
-	struct drm_crtc *crtc = &pipe->crtc;
+	struct mxsfb_drm_private *mxsfb = to_mxsfb_drm_private(plane->dev);
+	struct drm_crtc *crtc = &mxsfb->crtc;
 	struct drm_pending_vblank_event *event;
 	dma_addr_t paddr;
 
@@ -324,3 +434,47 @@ void mxsfb_plane_atomic_update(struct mxsfb_drm_private *mxsfb,
 		mxsfb_disable_axi_clk(mxsfb);
 	}
 }
+
+static const struct drm_plane_helper_funcs mxsfb_plane_helper_funcs = {
+	.atomic_check = mxsfb_plane_atomic_check,
+	.atomic_update = mxsfb_plane_atomic_update,
+};
+
+static const struct drm_plane_funcs mxsfb_plane_funcs = {
+	.update_plane		= drm_atomic_helper_update_plane,
+	.disable_plane		= drm_atomic_helper_disable_plane,
+	.destroy		= drm_plane_cleanup,
+	.reset			= drm_atomic_helper_plane_reset,
+	.atomic_duplicate_state	= drm_atomic_helper_plane_duplicate_state,
+	.atomic_destroy_state	= drm_atomic_helper_plane_destroy_state,
+};
+
+static const uint32_t mxsfb_formats[] = {
+	DRM_FORMAT_XRGB8888,
+	DRM_FORMAT_RGB565
+};
+
+int mxsfb_kms_init(struct mxsfb_drm_private *mxsfb)
+{
+	struct drm_encoder *encoder = &mxsfb->encoder;
+	struct drm_plane *plane = &mxsfb->plane;
+	struct drm_crtc *crtc = &mxsfb->crtc;
+	int ret;
+
+	drm_plane_helper_add(plane, &mxsfb_plane_helper_funcs);
+	ret = drm_universal_plane_init(mxsfb->drm, plane, 0, &mxsfb_plane_funcs,
+				       mxsfb_formats, ARRAY_SIZE(mxsfb_formats),
+				       NULL, DRM_PLANE_TYPE_PRIMARY, NULL);
+	if (ret)
+		return ret;
+
+	drm_crtc_helper_add(crtc, &mxsfb_crtc_helper_funcs);
+	ret = drm_crtc_init_with_planes(mxsfb->drm, crtc, plane, NULL,
+					&mxsfb_crtc_funcs, NULL);
+	if (ret)
+		return ret;
+
+	encoder->possible_crtcs = drm_crtc_mask(crtc);
+	return drm_encoder_init(mxsfb->drm, encoder, &mxsfb_encoder_funcs,
+				DRM_MODE_ENCODER_NONE, NULL);
+}
diff --git a/drivers/gpu/drm/mxsfb/mxsfb_drv.c b/drivers/gpu/drm/mxsfb/mxsfb_drv.c
index 204c1e52e9aa..a8da92976d13 100644
--- a/drivers/gpu/drm/mxsfb/mxsfb_drv.c
+++ b/drivers/gpu/drm/mxsfb/mxsfb_drv.c
@@ -10,22 +10,23 @@
 
 #include <linux/clk.h>
 #include <linux/dma-mapping.h>
+#include <linux/io.h>
 #include <linux/module.h>
 #include <linux/of_device.h>
+#include <linux/platform_device.h>
 #include <linux/pm_runtime.h>
-#include <linux/spinlock.h>
 
-#include <drm/drm_atomic.h>
 #include <drm/drm_atomic_helper.h>
-#include <drm/drm_crtc.h>
+#include <drm/drm_bridge.h>
+#include <drm/drm_connector.h>
 #include <drm/drm_drv.h>
 #include <drm/drm_fb_helper.h>
 #include <drm/drm_gem_cma_helper.h>
 #include <drm/drm_gem_framebuffer_helper.h>
 #include <drm/drm_irq.h>
+#include <drm/drm_mode_config.h>
 #include <drm/drm_of.h>
 #include <drm/drm_probe_helper.h>
-#include <drm/drm_simple_kms_helper.h>
 #include <drm/drm_vblank.h>
 
 #include "mxsfb_drv.h"
@@ -57,17 +58,6 @@ static const struct mxsfb_devdata mxsfb_devdata[] = {
 	},
 };
 
-static const uint32_t mxsfb_formats[] = {
-	DRM_FORMAT_XRGB8888,
-	DRM_FORMAT_RGB565
-};
-
-static struct mxsfb_drm_private *
-drm_pipe_to_mxsfb_drm_private(struct drm_simple_display_pipe *pipe)
-{
-	return container_of(pipe, struct mxsfb_drm_private, pipe);
-}
-
 void mxsfb_enable_axi_clk(struct mxsfb_drm_private *mxsfb)
 {
 	if (mxsfb->clk_axi)
@@ -90,77 +80,6 @@ static const struct drm_mode_config_helper_funcs mxsfb_mode_config_helpers = {
 	.atomic_commit_tail = drm_atomic_helper_commit_tail_rpm,
 };
 
-static void mxsfb_pipe_enable(struct drm_simple_display_pipe *pipe,
-			      struct drm_crtc_state *crtc_state,
-			      struct drm_plane_state *plane_state)
-{
-	struct mxsfb_drm_private *mxsfb = drm_pipe_to_mxsfb_drm_private(pipe);
-	struct drm_device *drm = pipe->plane.dev;
-
-	pm_runtime_get_sync(drm->dev);
-	mxsfb_crtc_enable(mxsfb);
-}
-
-static void mxsfb_pipe_disable(struct drm_simple_display_pipe *pipe)
-{
-	struct mxsfb_drm_private *mxsfb = drm_pipe_to_mxsfb_drm_private(pipe);
-	struct drm_device *drm = pipe->plane.dev;
-	struct drm_crtc *crtc = &pipe->crtc;
-	struct drm_pending_vblank_event *event;
-
-	mxsfb_crtc_disable(mxsfb);
-	pm_runtime_put_sync(drm->dev);
-
-	spin_lock_irq(&drm->event_lock);
-	event = crtc->state->event;
-	if (event) {
-		crtc->state->event = NULL;
-		drm_crtc_send_vblank_event(crtc, event);
-	}
-	spin_unlock_irq(&drm->event_lock);
-}
-
-static void mxsfb_pipe_update(struct drm_simple_display_pipe *pipe,
-			      struct drm_plane_state *plane_state)
-{
-	struct mxsfb_drm_private *mxsfb = drm_pipe_to_mxsfb_drm_private(pipe);
-
-	mxsfb_plane_atomic_update(mxsfb, plane_state);
-}
-
-static int mxsfb_pipe_enable_vblank(struct drm_simple_display_pipe *pipe)
-{
-	struct mxsfb_drm_private *mxsfb = drm_pipe_to_mxsfb_drm_private(pipe);
-
-	/* Clear and enable VBLANK IRQ */
-	mxsfb_enable_axi_clk(mxsfb);
-	writel(CTRL1_CUR_FRAME_DONE_IRQ, mxsfb->base + LCDC_CTRL1 + REG_CLR);
-	writel(CTRL1_CUR_FRAME_DONE_IRQ_EN, mxsfb->base + LCDC_CTRL1 + REG_SET);
-	mxsfb_disable_axi_clk(mxsfb);
-
-	return 0;
-}
-
-static void mxsfb_pipe_disable_vblank(struct drm_simple_display_pipe *pipe)
-{
-	struct mxsfb_drm_private *mxsfb = drm_pipe_to_mxsfb_drm_private(pipe);
-
-	/* Disable and clear VBLANK IRQ */
-	mxsfb_enable_axi_clk(mxsfb);
-	writel(CTRL1_CUR_FRAME_DONE_IRQ_EN, mxsfb->base + LCDC_CTRL1 + REG_CLR);
-	writel(CTRL1_CUR_FRAME_DONE_IRQ, mxsfb->base + LCDC_CTRL1 + REG_CLR);
-	mxsfb_disable_axi_clk(mxsfb);
-}
-
-static struct drm_simple_display_pipe_funcs mxsfb_funcs = {
-	.enable		= mxsfb_pipe_enable,
-	.disable	= mxsfb_pipe_disable,
-	.update		= mxsfb_pipe_update,
-	.prepare_fb	= drm_gem_fb_simple_display_pipe_prepare_fb,
-	.enable_vblank	= mxsfb_pipe_enable_vblank,
-	.disable_vblank	= mxsfb_pipe_disable_vblank,
-};
-
 static int mxsfb_attach_bridge(struct mxsfb_drm_private *mxsfb)
 {
 	struct drm_device *drm = mxsfb->drm;
@@ -183,7 +102,7 @@ static int mxsfb_attach_bridge(struct mxsfb_drm_private *mxsfb)
 	if (!bridge)
 		return -ENODEV;
 
-	ret = drm_simple_display_pipe_attach_bridge(&mxsfb->pipe, bridge);
+	ret = drm_bridge_attach(&mxsfb->encoder, bridge, NULL, 0);
 	if (ret) {
 		DRM_DEV_ERROR(drm->dev,
 			      "failed to attach bridge: %d\n", ret);
@@ -250,10 +169,9 @@ static int mxsfb_load(struct drm_device *drm, unsigned long flags)
 	/* Modeset init */
 	drm_mode_config_init(drm);
 
-	ret = drm_simple_display_pipe_init(drm, &mxsfb->pipe, &mxsfb_funcs,
-			mxsfb_formats, ARRAY_SIZE(mxsfb_formats), NULL, NULL);
+	ret = mxsfb_kms_init(mxsfb);
 	if (ret < 0) {
-		dev_err(drm->dev, "Cannot setup simple display pipe\n");
+		dev_err(drm->dev, "Failed to initialize KMS pipeline\n");
 		goto err_vblank;
 	}
 
@@ -309,11 +227,11 @@ static void mxsfb_unload(struct drm_device *drm)
 	pm_runtime_disable(drm->dev);
 }
 
-static void mxsfb_irq_preinstall(struct drm_device *drm)
+static void mxsfb_irq_disable(struct drm_device *drm)
 {
 	struct mxsfb_drm_private *mxsfb = drm->dev_private;
 
-	mxsfb_pipe_disable_vblank(&mxsfb->pipe);
+	mxsfb->crtc.funcs->disable_vblank(&mxsfb->crtc);
 }
 
 static irqreturn_t mxsfb_irq_handler(int irq, void *data)
@@ -327,7 +245,7 @@ static irqreturn_t mxsfb_irq_handler(int irq, void *data)
 	reg = readl(mxsfb->base + LCDC_CTRL1);
 
 	if (reg & CTRL1_CUR_FRAME_DONE_IRQ)
-		drm_crtc_handle_vblank(&mxsfb->pipe.crtc);
+		drm_crtc_handle_vblank(&mxsfb->crtc);
 
 	writel(CTRL1_CUR_FRAME_DONE_IRQ, mxsfb->base + LCDC_CTRL1 + REG_CLR);
 
@@ -341,8 +259,8 @@ DEFINE_DRM_GEM_CMA_FOPS(fops);
 static struct drm_driver mxsfb_driver = {
 	.driver_features	= DRIVER_GEM | DRIVER_MODESET | DRIVER_ATOMIC,
 	.irq_handler		= mxsfb_irq_handler,
-	.irq_preinstall		= mxsfb_irq_preinstall,
-	.irq_uninstall		= mxsfb_irq_preinstall,
+	.irq_preinstall		= mxsfb_irq_disable,
+	.irq_uninstall		= mxsfb_irq_disable,
 	.gem_free_object_unlocked = drm_gem_cma_free_object,
 	.gem_vm_ops		= &drm_gem_cma_vm_ops,
 	.dumb_create		= drm_gem_cma_dumb_create,
diff --git a/drivers/gpu/drm/mxsfb/mxsfb_drv.h b/drivers/gpu/drm/mxsfb/mxsfb_drv.h
index 0e3e5a63bbf9..edd766ad254f 100644
--- a/drivers/gpu/drm/mxsfb/mxsfb_drv.h
+++ b/drivers/gpu/drm/mxsfb/mxsfb_drv.h
@@ -8,7 +8,12 @@
 #ifndef __MXSFB_DRV_H__
 #define __MXSFB_DRV_H__
 
-struct drm_device;
+#include <drm/drm_crtc.h>
+#include <drm/drm_device.h>
+#include <drm/drm_encoder.h>
+#include <drm/drm_plane.h>
+
+struct clk;
 
 struct mxsfb_devdata {
 	unsigned int	 transfer_count;
@@ -29,20 +34,22 @@ struct mxsfb_drm_private {
 	struct clk			*clk_disp_axi;
 
 	struct drm_device		*drm;
-	struct drm_simple_display_pipe	pipe;
+	struct drm_plane		plane;
+	struct drm_crtc			crtc;
+	struct drm_encoder		encoder;
 	struct drm_connector		*connector;
 	struct drm_bridge		*bridge;
 };
 
-int mxsfb_setup_crtc(struct drm_device *dev);
-int mxsfb_create_output(struct drm_device *dev);
+static inline struct mxsfb_drm_private *
+to_mxsfb_drm_private(struct drm_device *drm)
+{
+	return drm->dev_private;
+}
 
 void mxsfb_enable_axi_clk(struct mxsfb_drm_private *mxsfb);
 void mxsfb_disable_axi_clk(struct mxsfb_drm_private *mxsfb);
 
-void mxsfb_crtc_enable(struct mxsfb_drm_private *mxsfb);
-void mxsfb_crtc_disable(struct mxsfb_drm_private *mxsfb);
-void mxsfb_plane_atomic_update(struct mxsfb_drm_private *mxsfb,
-			       struct drm_plane_state *state);
+int mxsfb_kms_init(struct mxsfb_drm_private *mxsfb);
 
 #endif /* __MXSFB_DRV_H__ */
-- 
Regards,

Laurent Pinchart

_______________________________________________
dri-devel mailing list
dri-devel@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/dri-devel

^ permalink raw reply related	[flat|nested] 62+ messages in thread

* [PATCH 11/21] drm: mxsfb: Rename mxsfb_crtc.c to mxsfb_kms.c
  2020-03-09 19:51 [PATCH 00/21] drm: mxsfb: Add i.MX7 support Laurent Pinchart
                   ` (9 preceding siblings ...)
  2020-03-09 19:52 ` [PATCH 10/21] drm: mxsfb: Stop using DRM simple display pipeline helper Laurent Pinchart
@ 2020-03-09 19:52 ` Laurent Pinchart
  2020-03-23 22:31   ` Stefan Agner
  2020-03-09 19:52 ` [PATCH 12/21] drm: mxsfb: Move vblank event arm to CRTC .atomic_flush() Laurent Pinchart
                   ` (12 subsequent siblings)
  23 siblings, 1 reply; 62+ messages in thread
From: Laurent Pinchart @ 2020-03-09 19:52 UTC (permalink / raw)
  To: dri-devel; +Cc: Marek Vasut, kernel, linux-imx

The mxsfb_crtc.c file doesn't handle just the CRTC, but also the other
KMS objects. Rename it accordingly.

Signed-off-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
---
 drivers/gpu/drm/mxsfb/Makefile                      | 2 +-
 drivers/gpu/drm/mxsfb/{mxsfb_crtc.c => mxsfb_kms.c} | 0
 2 files changed, 1 insertion(+), 1 deletion(-)
 rename drivers/gpu/drm/mxsfb/{mxsfb_crtc.c => mxsfb_kms.c} (100%)

diff --git a/drivers/gpu/drm/mxsfb/Makefile b/drivers/gpu/drm/mxsfb/Makefile
index 811584e54ad1..26d153896d72 100644
--- a/drivers/gpu/drm/mxsfb/Makefile
+++ b/drivers/gpu/drm/mxsfb/Makefile
@@ -1,3 +1,3 @@
 # SPDX-License-Identifier: GPL-2.0-only
-mxsfb-y := mxsfb_drv.o mxsfb_crtc.o
+mxsfb-y := mxsfb_drv.o mxsfb_kms.o
 obj-$(CONFIG_DRM_MXSFB)	+= mxsfb.o
diff --git a/drivers/gpu/drm/mxsfb/mxsfb_crtc.c b/drivers/gpu/drm/mxsfb/mxsfb_kms.c
similarity index 100%
rename from drivers/gpu/drm/mxsfb/mxsfb_crtc.c
rename to drivers/gpu/drm/mxsfb/mxsfb_kms.c
-- 
Regards,

Laurent Pinchart

_______________________________________________
dri-devel mailing list
dri-devel@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/dri-devel

^ permalink raw reply related	[flat|nested] 62+ messages in thread

* [PATCH 12/21] drm: mxsfb: Move vblank event arm to CRTC .atomic_flush()
  2020-03-09 19:51 [PATCH 00/21] drm: mxsfb: Add i.MX7 support Laurent Pinchart
                   ` (10 preceding siblings ...)
  2020-03-09 19:52 ` [PATCH 11/21] drm: mxsfb: Rename mxsfb_crtc.c to mxsfb_kms.c Laurent Pinchart
@ 2020-03-09 19:52 ` Laurent Pinchart
  2020-03-23 22:38   ` Stefan Agner
  2020-03-09 19:52 ` [PATCH 13/21] drm: mxsfb: Don't touch AXI clock in IRQ context Laurent Pinchart
                   ` (11 subsequent siblings)
  23 siblings, 1 reply; 62+ messages in thread
From: Laurent Pinchart @ 2020-03-09 19:52 UTC (permalink / raw)
  To: dri-devel; +Cc: Marek Vasut, kernel, linux-imx

The vblank event is armed in the plane .atomic_update(). This works fine
as we have a single plane, but will break as soon as multiple planes are
supported (not to mention it's logically the wrong place to perform the
operation). Move it to CRTC .atomic_flush().

Signed-off-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
---
 drivers/gpu/drm/mxsfb/mxsfb_kms.c | 35 ++++++++++++++++++-------------
 1 file changed, 20 insertions(+), 15 deletions(-)

diff --git a/drivers/gpu/drm/mxsfb/mxsfb_kms.c b/drivers/gpu/drm/mxsfb/mxsfb_kms.c
index 8f339adb8d04..ebe0785694cb 100644
--- a/drivers/gpu/drm/mxsfb/mxsfb_kms.c
+++ b/drivers/gpu/drm/mxsfb/mxsfb_kms.c
@@ -295,6 +295,25 @@ static int mxsfb_crtc_atomic_check(struct drm_crtc *crtc,
 	return drm_atomic_add_affected_planes(state->state, crtc);
 }
 
+static void mxsfb_crtc_atomic_flush(struct drm_crtc *crtc,
+				    struct drm_crtc_state *old_state)
+{
+	struct drm_pending_vblank_event *event;
+
+	event = crtc->state->event;
+	crtc->state->event = NULL;
+
+	if (!event)
+		return;
+
+	spin_lock_irq(&crtc->dev->event_lock);
+	if (drm_crtc_vblank_get(crtc) == 0)
+		drm_crtc_arm_vblank_event(crtc, event);
+	else
+		drm_crtc_send_vblank_event(crtc, event);
+	spin_unlock_irq(&crtc->dev->event_lock);
+}
+
 static void mxsfb_crtc_atomic_enable(struct drm_crtc *crtc,
 				     struct drm_crtc_state *old_state)
 {
@@ -364,6 +383,7 @@ static void mxsfb_crtc_disable_vblank(struct drm_crtc *crtc)
 
 static const struct drm_crtc_helper_funcs mxsfb_crtc_helper_funcs = {
 	.atomic_check = mxsfb_crtc_atomic_check,
+	.atomic_flush = mxsfb_crtc_atomic_flush,
 	.atomic_enable = mxsfb_crtc_atomic_enable,
 	.atomic_disable = mxsfb_crtc_atomic_disable,
 };
@@ -410,23 +430,8 @@ static void mxsfb_plane_atomic_update(struct drm_plane *plane,
 				      struct drm_plane_state *old_pstate)
 {
 	struct mxsfb_drm_private *mxsfb = to_mxsfb_drm_private(plane->dev);
-	struct drm_crtc *crtc = &mxsfb->crtc;
-	struct drm_pending_vblank_event *event;
 	dma_addr_t paddr;
 
-	spin_lock_irq(&crtc->dev->event_lock);
-	event = crtc->state->event;
-	if (event) {
-		crtc->state->event = NULL;
-
-		if (drm_crtc_vblank_get(crtc) == 0) {
-			drm_crtc_arm_vblank_event(crtc, event);
-		} else {
-			drm_crtc_send_vblank_event(crtc, event);
-		}
-	}
-	spin_unlock_irq(&crtc->dev->event_lock);
-
 	paddr = mxsfb_get_fb_paddr(mxsfb);
 	if (paddr) {
 		mxsfb_enable_axi_clk(mxsfb);
-- 
Regards,

Laurent Pinchart

_______________________________________________
dri-devel mailing list
dri-devel@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/dri-devel

^ permalink raw reply related	[flat|nested] 62+ messages in thread

* [PATCH 13/21] drm: mxsfb: Don't touch AXI clock in IRQ context
  2020-03-09 19:51 [PATCH 00/21] drm: mxsfb: Add i.MX7 support Laurent Pinchart
                   ` (11 preceding siblings ...)
  2020-03-09 19:52 ` [PATCH 12/21] drm: mxsfb: Move vblank event arm to CRTC .atomic_flush() Laurent Pinchart
@ 2020-03-09 19:52 ` Laurent Pinchart
  2020-03-23 22:50   ` Stefan Agner
  2020-03-09 19:52 ` [PATCH 14/21] drm: mxsfb: Enable vblank handling Laurent Pinchart
                   ` (10 subsequent siblings)
  23 siblings, 1 reply; 62+ messages in thread
From: Laurent Pinchart @ 2020-03-09 19:52 UTC (permalink / raw)
  To: dri-devel; +Cc: Marek Vasut, kernel, linux-imx

The driver attempts agressive power management by enabling and disabling
the AXI clock around register accesses. This results in attempts to
enable and disable the clock in the IRQ handler, which is a no-go as
preparing or unpreparing the clock may sleep.

On the other hand, the driver enables the AXI clock when enabling the
CRTC and keeps it enabled until the CRTC is disabled. This is correct,
and renders the power management attempt pointless, as interrupts are
not supposed to occur when the CRTC is off.

The same reasoning can be applied to the CRTC .enable_vblank() and
.disable_vblank() that are not supposed to be called when the CRTC off
and thus don't require manual handling of the AXI clock. Furthermore,
vblank handling is never enabled, which results in the vblank enable and
disable handlers never being called.

To fix this, remove the manual clock handling in the IRQ, the CRTC
.enable_vblank() and .disable_vblank() handlers and the plane
.atomic_update() handler. We however need to handle the clock manually
in mxsfb_irq_disable() as is calls .disable_vblank() manually and is
used both at probe and remove time.

The clock disabling is also moved to the last step of the
mxsfb_crtc_atomic_disable() function, to prepare for enabling vblank
handling.

Signed-off-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
---
 drivers/gpu/drm/mxsfb/mxsfb_drv.c |  6 ++----
 drivers/gpu/drm/mxsfb/mxsfb_kms.c | 15 ++++-----------
 2 files changed, 6 insertions(+), 15 deletions(-)

diff --git a/drivers/gpu/drm/mxsfb/mxsfb_drv.c b/drivers/gpu/drm/mxsfb/mxsfb_drv.c
index a8da92976d13..e324bd2a63a5 100644
--- a/drivers/gpu/drm/mxsfb/mxsfb_drv.c
+++ b/drivers/gpu/drm/mxsfb/mxsfb_drv.c
@@ -231,7 +231,9 @@ static void mxsfb_irq_disable(struct drm_device *drm)
 {
 	struct mxsfb_drm_private *mxsfb = drm->dev_private;
 
+	mxsfb_enable_axi_clk(mxsfb);
 	mxsfb->crtc.funcs->disable_vblank(&mxsfb->crtc);
+	mxsfb_disable_axi_clk(mxsfb);
 }
 
 static irqreturn_t mxsfb_irq_handler(int irq, void *data)
@@ -240,8 +242,6 @@ static irqreturn_t mxsfb_irq_handler(int irq, void *data)
 	struct mxsfb_drm_private *mxsfb = drm->dev_private;
 	u32 reg;
 
-	mxsfb_enable_axi_clk(mxsfb);
-
 	reg = readl(mxsfb->base + LCDC_CTRL1);
 
 	if (reg & CTRL1_CUR_FRAME_DONE_IRQ)
@@ -249,8 +249,6 @@ static irqreturn_t mxsfb_irq_handler(int irq, void *data)
 
 	writel(CTRL1_CUR_FRAME_DONE_IRQ, mxsfb->base + LCDC_CTRL1 + REG_CLR);
 
-	mxsfb_disable_axi_clk(mxsfb);
-
 	return IRQ_HANDLED;
 }
 
diff --git a/drivers/gpu/drm/mxsfb/mxsfb_kms.c b/drivers/gpu/drm/mxsfb/mxsfb_kms.c
index ebe0785694cb..ac2696c8483d 100644
--- a/drivers/gpu/drm/mxsfb/mxsfb_kms.c
+++ b/drivers/gpu/drm/mxsfb/mxsfb_kms.c
@@ -344,9 +344,6 @@ static void mxsfb_crtc_atomic_disable(struct drm_crtc *crtc,
 	struct drm_pending_vblank_event *event;
 
 	mxsfb_disable_controller(mxsfb);
-	mxsfb_disable_axi_clk(mxsfb);
-
-	pm_runtime_put_sync(drm->dev);
 
 	spin_lock_irq(&drm->event_lock);
 	event = crtc->state->event;
@@ -355,6 +352,9 @@ static void mxsfb_crtc_atomic_disable(struct drm_crtc *crtc,
 		drm_crtc_send_vblank_event(crtc, event);
 	}
 	spin_unlock_irq(&drm->event_lock);
+
+	mxsfb_disable_axi_clk(mxsfb);
+	pm_runtime_put_sync(drm->dev);
 }
 
 static int mxsfb_crtc_enable_vblank(struct drm_crtc *crtc)
@@ -362,10 +362,8 @@ static int mxsfb_crtc_enable_vblank(struct drm_crtc *crtc)
 	struct mxsfb_drm_private *mxsfb = to_mxsfb_drm_private(crtc->dev);
 
 	/* Clear and enable VBLANK IRQ */
-	mxsfb_enable_axi_clk(mxsfb);
 	writel(CTRL1_CUR_FRAME_DONE_IRQ, mxsfb->base + LCDC_CTRL1 + REG_CLR);
 	writel(CTRL1_CUR_FRAME_DONE_IRQ_EN, mxsfb->base + LCDC_CTRL1 + REG_SET);
-	mxsfb_disable_axi_clk(mxsfb);
 
 	return 0;
 }
@@ -375,10 +373,8 @@ static void mxsfb_crtc_disable_vblank(struct drm_crtc *crtc)
 	struct mxsfb_drm_private *mxsfb = to_mxsfb_drm_private(crtc->dev);
 
 	/* Disable and clear VBLANK IRQ */
-	mxsfb_enable_axi_clk(mxsfb);
 	writel(CTRL1_CUR_FRAME_DONE_IRQ_EN, mxsfb->base + LCDC_CTRL1 + REG_CLR);
 	writel(CTRL1_CUR_FRAME_DONE_IRQ, mxsfb->base + LCDC_CTRL1 + REG_CLR);
-	mxsfb_disable_axi_clk(mxsfb);
 }
 
 static const struct drm_crtc_helper_funcs mxsfb_crtc_helper_funcs = {
@@ -433,11 +429,8 @@ static void mxsfb_plane_atomic_update(struct drm_plane *plane,
 	dma_addr_t paddr;
 
 	paddr = mxsfb_get_fb_paddr(mxsfb);
-	if (paddr) {
-		mxsfb_enable_axi_clk(mxsfb);
+	if (paddr)
 		writel(paddr, mxsfb->base + mxsfb->devdata->next_buf);
-		mxsfb_disable_axi_clk(mxsfb);
-	}
 }
 
 static const struct drm_plane_helper_funcs mxsfb_plane_helper_funcs = {
-- 
Regards,

Laurent Pinchart

_______________________________________________
dri-devel mailing list
dri-devel@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/dri-devel

^ permalink raw reply related	[flat|nested] 62+ messages in thread

* [PATCH 14/21] drm: mxsfb: Enable vblank handling
  2020-03-09 19:51 [PATCH 00/21] drm: mxsfb: Add i.MX7 support Laurent Pinchart
                   ` (12 preceding siblings ...)
  2020-03-09 19:52 ` [PATCH 13/21] drm: mxsfb: Don't touch AXI clock in IRQ context Laurent Pinchart
@ 2020-03-09 19:52 ` Laurent Pinchart
  2020-03-23 23:08   ` Stefan Agner
  2020-03-09 19:52 ` [PATCH 15/21] drm: mxsfb: Remove mxsfb_devdata unused fields Laurent Pinchart
                   ` (9 subsequent siblings)
  23 siblings, 1 reply; 62+ messages in thread
From: Laurent Pinchart @ 2020-03-09 19:52 UTC (permalink / raw)
  To: dri-devel; +Cc: Marek Vasut, kernel, linux-imx

Enable vblank handling when the CRTC is turned on and disable it when it
is turned off. This requires moving vblank init after the KMS pipeline
initialisation, otherwise drm_vblank_init() gets called with 0 CRTCs.

Signed-off-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
---
 drivers/gpu/drm/mxsfb/mxsfb_drv.c | 15 +++++++++------
 drivers/gpu/drm/mxsfb/mxsfb_kms.c |  6 +++++-
 2 files changed, 14 insertions(+), 7 deletions(-)

diff --git a/drivers/gpu/drm/mxsfb/mxsfb_drv.c b/drivers/gpu/drm/mxsfb/mxsfb_drv.c
index e324bd2a63a5..72b4f6a947a4 100644
--- a/drivers/gpu/drm/mxsfb/mxsfb_drv.c
+++ b/drivers/gpu/drm/mxsfb/mxsfb_drv.c
@@ -160,12 +160,6 @@ static int mxsfb_load(struct drm_device *drm, unsigned long flags)
 
 	pm_runtime_enable(drm->dev);
 
-	ret = drm_vblank_init(drm, drm->mode_config.num_crtc);
-	if (ret < 0) {
-		dev_err(drm->dev, "Failed to initialise vblank\n");
-		goto err_vblank;
-	}
-
 	/* Modeset init */
 	drm_mode_config_init(drm);
 
@@ -175,6 +169,15 @@ static int mxsfb_load(struct drm_device *drm, unsigned long flags)
 		goto err_vblank;
 	}
 
+	ret = drm_vblank_init(drm, drm->mode_config.num_crtc);
+	if (ret < 0) {
+		dev_err(drm->dev, "Failed to initialise vblank\n");
+		goto err_vblank;
+	}
+
+	/* Start with vertical blanking interrupt reporting disabled. */
+	drm_crtc_vblank_off(&mxsfb->crtc);
+
 	ret = mxsfb_attach_bridge(mxsfb);
 	if (ret) {
 		dev_err(drm->dev, "Cannot connect bridge: %d\n", ret);
diff --git a/drivers/gpu/drm/mxsfb/mxsfb_kms.c b/drivers/gpu/drm/mxsfb/mxsfb_kms.c
index ac2696c8483d..640305fb1068 100644
--- a/drivers/gpu/drm/mxsfb/mxsfb_kms.c
+++ b/drivers/gpu/drm/mxsfb/mxsfb_kms.c
@@ -322,8 +322,10 @@ static void mxsfb_crtc_atomic_enable(struct drm_crtc *crtc,
 	dma_addr_t paddr;
 
 	pm_runtime_get_sync(drm->dev);
-
 	mxsfb_enable_axi_clk(mxsfb);
+
+	drm_crtc_vblank_on(crtc);
+
 	mxsfb_crtc_mode_set_nofb(mxsfb);
 
 	/* Write cur_buf as well to avoid an initial corrupt frame */
@@ -353,6 +355,8 @@ static void mxsfb_crtc_atomic_disable(struct drm_crtc *crtc,
 	}
 	spin_unlock_irq(&drm->event_lock);
 
+	drm_crtc_vblank_off(crtc);
+
 	mxsfb_disable_axi_clk(mxsfb);
 	pm_runtime_put_sync(drm->dev);
 }
-- 
Regards,

Laurent Pinchart

_______________________________________________
dri-devel mailing list
dri-devel@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/dri-devel

^ permalink raw reply related	[flat|nested] 62+ messages in thread

* [PATCH 15/21] drm: mxsfb: Remove mxsfb_devdata unused fields
  2020-03-09 19:51 [PATCH 00/21] drm: mxsfb: Add i.MX7 support Laurent Pinchart
                   ` (13 preceding siblings ...)
  2020-03-09 19:52 ` [PATCH 14/21] drm: mxsfb: Enable vblank handling Laurent Pinchart
@ 2020-03-09 19:52 ` Laurent Pinchart
  2020-03-23 23:15   ` Stefan Agner
  2020-03-09 19:52 ` [PATCH 16/21] drm: mxsfb: Add i.MX7 to the list of supported SoCs in Kconfig Laurent Pinchart
                   ` (8 subsequent siblings)
  23 siblings, 1 reply; 62+ messages in thread
From: Laurent Pinchart @ 2020-03-09 19:52 UTC (permalink / raw)
  To: dri-devel; +Cc: Marek Vasut, kernel, linux-imx

The debug0 and ipversion fields of the mxsfb_devdata structure are
unused. Remove them.

Signed-off-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
---
 drivers/gpu/drm/mxsfb/mxsfb_drv.c | 4 ----
 drivers/gpu/drm/mxsfb/mxsfb_drv.h | 2 --
 2 files changed, 6 deletions(-)

diff --git a/drivers/gpu/drm/mxsfb/mxsfb_drv.c b/drivers/gpu/drm/mxsfb/mxsfb_drv.c
index 72b4f6a947a4..7c9a041f5f6d 100644
--- a/drivers/gpu/drm/mxsfb/mxsfb_drv.c
+++ b/drivers/gpu/drm/mxsfb/mxsfb_drv.c
@@ -42,19 +42,15 @@ static const struct mxsfb_devdata mxsfb_devdata[] = {
 		.transfer_count	= LCDC_V3_TRANSFER_COUNT,
 		.cur_buf	= LCDC_V3_CUR_BUF,
 		.next_buf	= LCDC_V3_NEXT_BUF,
-		.debug0		= LCDC_V3_DEBUG0,
 		.hs_wdth_mask	= 0xff,
 		.hs_wdth_shift	= 24,
-		.ipversion	= 3,
 	},
 	[MXSFB_V4] = {
 		.transfer_count	= LCDC_V4_TRANSFER_COUNT,
 		.cur_buf	= LCDC_V4_CUR_BUF,
 		.next_buf	= LCDC_V4_NEXT_BUF,
-		.debug0		= LCDC_V4_DEBUG0,
 		.hs_wdth_mask	= 0x3fff,
 		.hs_wdth_shift	= 18,
-		.ipversion	= 4,
 	},
 };
 
diff --git a/drivers/gpu/drm/mxsfb/mxsfb_drv.h b/drivers/gpu/drm/mxsfb/mxsfb_drv.h
index edd766ad254f..607a6a5e6be3 100644
--- a/drivers/gpu/drm/mxsfb/mxsfb_drv.h
+++ b/drivers/gpu/drm/mxsfb/mxsfb_drv.h
@@ -19,10 +19,8 @@ struct mxsfb_devdata {
 	unsigned int	 transfer_count;
 	unsigned int	 cur_buf;
 	unsigned int	 next_buf;
-	unsigned int	 debug0;
 	unsigned int	 hs_wdth_mask;
 	unsigned int	 hs_wdth_shift;
-	unsigned int	 ipversion;
 };
 
 struct mxsfb_drm_private {
-- 
Regards,

Laurent Pinchart

_______________________________________________
dri-devel mailing list
dri-devel@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/dri-devel

^ permalink raw reply related	[flat|nested] 62+ messages in thread

* [PATCH 16/21] drm: mxsfb: Add i.MX7 to the list of supported SoCs in Kconfig
  2020-03-09 19:51 [PATCH 00/21] drm: mxsfb: Add i.MX7 support Laurent Pinchart
                   ` (14 preceding siblings ...)
  2020-03-09 19:52 ` [PATCH 15/21] drm: mxsfb: Remove mxsfb_devdata unused fields Laurent Pinchart
@ 2020-03-09 19:52 ` Laurent Pinchart
  2020-03-10 16:28   ` Fabio Estevam
  2020-03-23 23:18   ` [PATCH " Stefan Agner
  2020-03-09 19:52 ` [PATCH 17/21] drm: mxsfb: Update internal IP version number for i.MX6SX Laurent Pinchart
                   ` (7 subsequent siblings)
  23 siblings, 2 replies; 62+ messages in thread
From: Laurent Pinchart @ 2020-03-09 19:52 UTC (permalink / raw)
  To: dri-devel; +Cc: Marek Vasut, kernel, linux-imx

Extend the Kconfig option description by listing the i.MX7 SoCs, as they
are supported by the same driver.

Signed-off-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
---
 drivers/gpu/drm/mxsfb/Kconfig | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/drivers/gpu/drm/mxsfb/Kconfig b/drivers/gpu/drm/mxsfb/Kconfig
index 0dca8f27169e..e91841f8f8a2 100644
--- a/drivers/gpu/drm/mxsfb/Kconfig
+++ b/drivers/gpu/drm/mxsfb/Kconfig
@@ -5,7 +5,7 @@ config DRM_MXS
 	  Choose this option to select drivers for MXS FB devices
 
 config DRM_MXSFB
-	tristate "i.MX23/i.MX28/i.MX6SX MXSFB LCD controller"
+	tristate "i.MX23/i.MX28/i.MX6SX/i.MX7 MXSFB LCD controller"
 	depends on DRM && OF
 	depends on COMMON_CLK
 	select DRM_MXS
@@ -14,7 +14,7 @@ config DRM_MXSFB
 	select DRM_KMS_CMA_HELPER
 	select DRM_PANEL
 	help
-	  Choose this option if you have an i.MX23/i.MX28/i.MX6SX MXSFB
+	  Choose this option if you have an i.MX23/i.MX28/i.MX6SX/i.MX7 MXSFB
 	  LCD controller.
 
 	  If M is selected the module will be called mxsfb.
-- 
Regards,

Laurent Pinchart

_______________________________________________
dri-devel mailing list
dri-devel@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/dri-devel

^ permalink raw reply related	[flat|nested] 62+ messages in thread

* [PATCH 17/21] drm: mxsfb: Update internal IP version number for i.MX6SX
  2020-03-09 19:51 [PATCH 00/21] drm: mxsfb: Add i.MX7 support Laurent Pinchart
                   ` (15 preceding siblings ...)
  2020-03-09 19:52 ` [PATCH 16/21] drm: mxsfb: Add i.MX7 to the list of supported SoCs in Kconfig Laurent Pinchart
@ 2020-03-09 19:52 ` Laurent Pinchart
  2020-03-23 23:20   ` Stefan Agner
  2020-03-09 19:52 ` [PATCH 18/21] drm: mxsfb: Drop non-OF support Laurent Pinchart
                   ` (6 subsequent siblings)
  23 siblings, 1 reply; 62+ messages in thread
From: Laurent Pinchart @ 2020-03-09 19:52 UTC (permalink / raw)
  To: dri-devel; +Cc: Marek Vasut, kernel, linux-imx

The LCDIF present in the i.MX6SX has extra features compared to
the i.MX28. It has however lost its IP version register, so no official
version number is known. Bump the version to MXSFB_V6 following the i.MX
version, in preparation for support for the additional features.

Signed-off-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
---
 drivers/gpu/drm/mxsfb/mxsfb_drv.c | 14 +++++++++++++-
 1 file changed, 13 insertions(+), 1 deletion(-)

diff --git a/drivers/gpu/drm/mxsfb/mxsfb_drv.c b/drivers/gpu/drm/mxsfb/mxsfb_drv.c
index 7c9a041f5f6d..2316c12c5c42 100644
--- a/drivers/gpu/drm/mxsfb/mxsfb_drv.c
+++ b/drivers/gpu/drm/mxsfb/mxsfb_drv.c
@@ -35,6 +35,11 @@
 enum mxsfb_devtype {
 	MXSFB_V3,
 	MXSFB_V4,
+	/*
+	 * Starting at i.MX6 the hardware version register is gone, use the
+	 * i.MX family number as the version.
+	 */
+	MXSFB_V6,
 };
 
 static const struct mxsfb_devdata mxsfb_devdata[] = {
@@ -52,6 +57,13 @@ static const struct mxsfb_devdata mxsfb_devdata[] = {
 		.hs_wdth_mask	= 0x3fff,
 		.hs_wdth_shift	= 18,
 	},
+	[MXSFB_V6] = {
+		.transfer_count	= LCDC_V4_TRANSFER_COUNT,
+		.cur_buf	= LCDC_V4_CUR_BUF,
+		.next_buf	= LCDC_V4_NEXT_BUF,
+		.hs_wdth_mask	= 0x3fff,
+		.hs_wdth_shift	= 18,
+	},
 };
 
 void mxsfb_enable_axi_clk(struct mxsfb_drm_private *mxsfb)
@@ -279,7 +291,7 @@ static struct drm_driver mxsfb_driver = {
 static const struct platform_device_id mxsfb_devtype[] = {
 	{ .name = "imx23-fb", .driver_data = MXSFB_V3, },
 	{ .name = "imx28-fb", .driver_data = MXSFB_V4, },
-	{ .name = "imx6sx-fb", .driver_data = MXSFB_V4, },
+	{ .name = "imx6sx-fb", .driver_data = MXSFB_V6, },
 	{ /* sentinel */ }
 };
 MODULE_DEVICE_TABLE(platform, mxsfb_devtype);
-- 
Regards,

Laurent Pinchart

_______________________________________________
dri-devel mailing list
dri-devel@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/dri-devel

^ permalink raw reply related	[flat|nested] 62+ messages in thread

* [PATCH 18/21] drm: mxsfb: Drop non-OF support
  2020-03-09 19:51 [PATCH 00/21] drm: mxsfb: Add i.MX7 support Laurent Pinchart
                   ` (16 preceding siblings ...)
  2020-03-09 19:52 ` [PATCH 17/21] drm: mxsfb: Update internal IP version number for i.MX6SX Laurent Pinchart
@ 2020-03-09 19:52 ` Laurent Pinchart
  2020-03-23 23:23   ` Stefan Agner
  2020-03-09 19:52 ` [PATCH 19/21] drm: mxsfb: Turn mxsfb_set_pixel_fmt() into a void function Laurent Pinchart
                   ` (5 subsequent siblings)
  23 siblings, 1 reply; 62+ messages in thread
From: Laurent Pinchart @ 2020-03-09 19:52 UTC (permalink / raw)
  To: dri-devel; +Cc: Marek Vasut, kernel, linux-imx

The mxsfb driver is only used by OF platforms. Drop non-OF support.

Signed-off-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
---
 drivers/gpu/drm/mxsfb/mxsfb_drv.c | 25 +++++++------------------
 1 file changed, 7 insertions(+), 18 deletions(-)

diff --git a/drivers/gpu/drm/mxsfb/mxsfb_drv.c b/drivers/gpu/drm/mxsfb/mxsfb_drv.c
index 2316c12c5c42..ed8e3f7bc27c 100644
--- a/drivers/gpu/drm/mxsfb/mxsfb_drv.c
+++ b/drivers/gpu/drm/mxsfb/mxsfb_drv.c
@@ -130,7 +130,8 @@ static int mxsfb_attach_bridge(struct mxsfb_drm_private *mxsfb)
 	return 0;
 }
 
-static int mxsfb_load(struct drm_device *drm, unsigned long flags)
+static int mxsfb_load(struct drm_device *drm,
+		      const struct mxsfb_devdata *devdata)
 {
 	struct platform_device *pdev = to_platform_device(drm->dev);
 	struct mxsfb_drm_private *mxsfb;
@@ -143,7 +144,7 @@ static int mxsfb_load(struct drm_device *drm, unsigned long flags)
 
 	mxsfb->drm = drm;
 	drm->dev_private = mxsfb;
-	mxsfb->devdata = &mxsfb_devdata[pdev->id_entry->driver_data];
+	mxsfb->devdata = devdata;
 
 	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
 	mxsfb->base = devm_ioremap_resource(drm->dev, res);
@@ -288,18 +289,10 @@ static struct drm_driver mxsfb_driver = {
 	.minor	= 0,
 };
 
-static const struct platform_device_id mxsfb_devtype[] = {
-	{ .name = "imx23-fb", .driver_data = MXSFB_V3, },
-	{ .name = "imx28-fb", .driver_data = MXSFB_V4, },
-	{ .name = "imx6sx-fb", .driver_data = MXSFB_V6, },
-	{ /* sentinel */ }
-};
-MODULE_DEVICE_TABLE(platform, mxsfb_devtype);
-
 static const struct of_device_id mxsfb_dt_ids[] = {
-	{ .compatible = "fsl,imx23-lcdif", .data = &mxsfb_devtype[0], },
-	{ .compatible = "fsl,imx28-lcdif", .data = &mxsfb_devtype[1], },
-	{ .compatible = "fsl,imx6sx-lcdif", .data = &mxsfb_devtype[2], },
+	{ .compatible = "fsl,imx23-lcdif", .data = &mxsfb_devdata[MXSFB_V3], },
+	{ .compatible = "fsl,imx28-lcdif", .data = &mxsfb_devdata[MXSFB_V4], },
+	{ .compatible = "fsl,imx6sx-lcdif", .data = &mxsfb_devdata[MXSFB_V6], },
 	{ /* sentinel */ }
 };
 MODULE_DEVICE_TABLE(of, mxsfb_dt_ids);
@@ -314,14 +307,11 @@ static int mxsfb_probe(struct platform_device *pdev)
 	if (!pdev->dev.of_node)
 		return -ENODEV;
 
-	if (of_id)
-		pdev->id_entry = of_id->data;
-
 	drm = drm_dev_alloc(&mxsfb_driver, &pdev->dev);
 	if (IS_ERR(drm))
 		return PTR_ERR(drm);
 
-	ret = mxsfb_load(drm, 0);
+	ret = mxsfb_load(drm, of_id->data);
 	if (ret)
 		goto err_free;
 
@@ -375,7 +365,6 @@ static const struct dev_pm_ops mxsfb_pm_ops = {
 static struct platform_driver mxsfb_platform_driver = {
 	.probe		= mxsfb_probe,
 	.remove		= mxsfb_remove,
-	.id_table	= mxsfb_devtype,
 	.driver	= {
 		.name		= "mxsfb",
 		.of_match_table	= mxsfb_dt_ids,
-- 
Regards,

Laurent Pinchart

_______________________________________________
dri-devel mailing list
dri-devel@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/dri-devel

^ permalink raw reply related	[flat|nested] 62+ messages in thread

* [PATCH 19/21] drm: mxsfb: Turn mxsfb_set_pixel_fmt() into a void function
  2020-03-09 19:51 [PATCH 00/21] drm: mxsfb: Add i.MX7 support Laurent Pinchart
                   ` (17 preceding siblings ...)
  2020-03-09 19:52 ` [PATCH 18/21] drm: mxsfb: Drop non-OF support Laurent Pinchart
@ 2020-03-09 19:52 ` Laurent Pinchart
  2020-03-23 23:28   ` Stefan Agner
  2020-03-09 19:52 ` [PATCH 20/21] drm: mxsfb: Merge mxsfb_set_pixel_fmt() and mxsfb_set_bus_fmt() Laurent Pinchart
                   ` (4 subsequent siblings)
  23 siblings, 1 reply; 62+ messages in thread
From: Laurent Pinchart @ 2020-03-09 19:52 UTC (permalink / raw)
  To: dri-devel; +Cc: Marek Vasut, kernel, linux-imx

The mxsfb_set_pixel_fmt() function returns an error when the selected
pixel format is unsupported. This can never happen, as such errors are
caught by the DRM core. Remove the error check.

Signed-off-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
---
 drivers/gpu/drm/mxsfb/mxsfb_kms.c | 11 ++---------
 1 file changed, 2 insertions(+), 9 deletions(-)

diff --git a/drivers/gpu/drm/mxsfb/mxsfb_kms.c b/drivers/gpu/drm/mxsfb/mxsfb_kms.c
index 640305fb1068..19b937b383cf 100644
--- a/drivers/gpu/drm/mxsfb/mxsfb_kms.c
+++ b/drivers/gpu/drm/mxsfb/mxsfb_kms.c
@@ -43,7 +43,7 @@ static u32 set_hsync_pulse_width(struct mxsfb_drm_private *mxsfb, u32 val)
 }
 
 /* Setup the MXSFB registers for decoding the pixels out of the framebuffer */
-static int mxsfb_set_pixel_fmt(struct mxsfb_drm_private *mxsfb)
+static void mxsfb_set_pixel_fmt(struct mxsfb_drm_private *mxsfb)
 {
 	struct drm_device *drm = mxsfb->drm;
 	const u32 format = mxsfb->crtc.primary->state->fb->format->format;
@@ -67,15 +67,10 @@ static int mxsfb_set_pixel_fmt(struct mxsfb_drm_private *mxsfb)
 		/* Do not use packed pixels = one pixel per word instead. */
 		ctrl1 |= CTRL1_SET_BYTE_PACKAGING(0x7);
 		break;
-	default:
-		dev_err(drm->dev, "Unhandled pixel format %08x\n", format);
-		return -EINVAL;
 	}
 
 	writel(ctrl1, mxsfb->base + LCDC_CTRL1);
 	writel(ctrl, mxsfb->base + LCDC_CTRL);
-
-	return 0;
 }
 
 static void mxsfb_set_bus_fmt(struct mxsfb_drm_private *mxsfb)
@@ -218,9 +213,7 @@ static void mxsfb_crtc_mode_set_nofb(struct mxsfb_drm_private *mxsfb)
 	/* Clear the FIFOs */
 	writel(CTRL1_FIFO_CLEAR, mxsfb->base + LCDC_CTRL1 + REG_SET);
 
-	err = mxsfb_set_pixel_fmt(mxsfb);
-	if (err)
-		return;
+	mxsfb_set_pixel_fmt(mxsfb);
 
 	clk_set_rate(mxsfb->clk, m->crtc_clock * 1000);
 
-- 
Regards,

Laurent Pinchart

_______________________________________________
dri-devel mailing list
dri-devel@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/dri-devel

^ permalink raw reply related	[flat|nested] 62+ messages in thread

* [PATCH 20/21] drm: mxsfb: Merge mxsfb_set_pixel_fmt() and mxsfb_set_bus_fmt()
  2020-03-09 19:51 [PATCH 00/21] drm: mxsfb: Add i.MX7 support Laurent Pinchart
                   ` (18 preceding siblings ...)
  2020-03-09 19:52 ` [PATCH 19/21] drm: mxsfb: Turn mxsfb_set_pixel_fmt() into a void function Laurent Pinchart
@ 2020-03-09 19:52 ` Laurent Pinchart
  2020-03-23 23:34   ` Stefan Agner
  2020-03-09 19:52 ` [PATCH 21/21] drm: mxsfb: Support the alpha plane Laurent Pinchart
                   ` (3 subsequent siblings)
  23 siblings, 1 reply; 62+ messages in thread
From: Laurent Pinchart @ 2020-03-09 19:52 UTC (permalink / raw)
  To: dri-devel; +Cc: Marek Vasut, kernel, linux-imx

The mxsfb_set_pixel_fmt() and mxsfb_set_bus_fmt() functions both deal
with format configuration, are always called in a row from
mxsfb_crtc_mode_set_nofb(), and set fields from the LCDC_CTRL register.
This requires a read-modify-update cycle in mxsfb_set_bus_fmt(). Make
this more efficient by merging them together.

Signed-off-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
---
 drivers/gpu/drm/mxsfb/mxsfb_kms.c | 47 +++++++++++++------------------
 1 file changed, 19 insertions(+), 28 deletions(-)

diff --git a/drivers/gpu/drm/mxsfb/mxsfb_kms.c b/drivers/gpu/drm/mxsfb/mxsfb_kms.c
index 19b937b383cf..f81f8c222c13 100644
--- a/drivers/gpu/drm/mxsfb/mxsfb_kms.c
+++ b/drivers/gpu/drm/mxsfb/mxsfb_kms.c
@@ -42,13 +42,23 @@ static u32 set_hsync_pulse_width(struct mxsfb_drm_private *mxsfb, u32 val)
 		mxsfb->devdata->hs_wdth_shift;
 }
 
-/* Setup the MXSFB registers for decoding the pixels out of the framebuffer */
-static void mxsfb_set_pixel_fmt(struct mxsfb_drm_private *mxsfb)
+/*
+ * Setup the MXSFB registers for decoding the pixels out of the framebuffer and
+ * outputting them on the bus.
+ */
+static void mxsfb_set_formats(struct mxsfb_drm_private *mxsfb)
 {
 	struct drm_device *drm = mxsfb->drm;
 	const u32 format = mxsfb->crtc.primary->state->fb->format->format;
+	u32 bus_format = MEDIA_BUS_FMT_RGB888_1X24;
 	u32 ctrl, ctrl1;
 
+	if (mxsfb->connector->display_info.num_bus_formats)
+		bus_format = mxsfb->connector->display_info.bus_formats[0];
+
+	DRM_DEV_DEBUG_DRIVER(drm->dev, "Using bus_format: 0x%08X\n",
+			     bus_format);
+
 	ctrl = CTRL_BYPASS_COUNT | CTRL_MASTER;
 
 	/* CTRL1 contains IRQ config and status bits, preserve those. */
@@ -69,40 +79,23 @@ static void mxsfb_set_pixel_fmt(struct mxsfb_drm_private *mxsfb)
 		break;
 	}
 
-	writel(ctrl1, mxsfb->base + LCDC_CTRL1);
-	writel(ctrl, mxsfb->base + LCDC_CTRL);
-}
-
-static void mxsfb_set_bus_fmt(struct mxsfb_drm_private *mxsfb)
-{
-	struct drm_device *drm = mxsfb->drm;
-	u32 bus_format = MEDIA_BUS_FMT_RGB888_1X24;
-	u32 reg;
-
-	reg = readl(mxsfb->base + LCDC_CTRL);
-
-	if (mxsfb->connector->display_info.num_bus_formats)
-		bus_format = mxsfb->connector->display_info.bus_formats[0];
-
-	DRM_DEV_DEBUG_DRIVER(drm->dev, "Using bus_format: 0x%08X\n",
-			     bus_format);
-
-	reg &= ~CTRL_BUS_WIDTH_MASK;
 	switch (bus_format) {
 	case MEDIA_BUS_FMT_RGB565_1X16:
-		reg |= CTRL_BUS_WIDTH_16;
+		ctrl |= CTRL_BUS_WIDTH_16;
 		break;
 	case MEDIA_BUS_FMT_RGB666_1X18:
-		reg |= CTRL_BUS_WIDTH_18;
+		ctrl |= CTRL_BUS_WIDTH_18;
 		break;
 	case MEDIA_BUS_FMT_RGB888_1X24:
-		reg |= CTRL_BUS_WIDTH_24;
+		ctrl |= CTRL_BUS_WIDTH_24;
 		break;
 	default:
 		dev_err(drm->dev, "Unknown media bus format %d\n", bus_format);
 		break;
 	}
-	writel(reg, mxsfb->base + LCDC_CTRL);
+
+	writel(ctrl1, mxsfb->base + LCDC_CTRL1);
+	writel(ctrl, mxsfb->base + LCDC_CTRL);
 }
 
 static void mxsfb_enable_controller(struct mxsfb_drm_private *mxsfb)
@@ -213,7 +206,7 @@ static void mxsfb_crtc_mode_set_nofb(struct mxsfb_drm_private *mxsfb)
 	/* Clear the FIFOs */
 	writel(CTRL1_FIFO_CLEAR, mxsfb->base + LCDC_CTRL1 + REG_SET);
 
-	mxsfb_set_pixel_fmt(mxsfb);
+	mxsfb_set_formats(mxsfb);
 
 	clk_set_rate(mxsfb->clk, m->crtc_clock * 1000);
 
@@ -255,8 +248,6 @@ static void mxsfb_crtc_mode_set_nofb(struct mxsfb_drm_private *mxsfb)
 
 	writel(vdctrl0, mxsfb->base + LCDC_VDCTRL0);
 
-	mxsfb_set_bus_fmt(mxsfb);
-
 	/* Frame length in lines. */
 	writel(m->crtc_vtotal, mxsfb->base + LCDC_VDCTRL1);
 
-- 
Regards,

Laurent Pinchart

_______________________________________________
dri-devel mailing list
dri-devel@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/dri-devel

^ permalink raw reply related	[flat|nested] 62+ messages in thread

* [PATCH 21/21] drm: mxsfb: Support the alpha plane
  2020-03-09 19:51 [PATCH 00/21] drm: mxsfb: Add i.MX7 support Laurent Pinchart
                   ` (19 preceding siblings ...)
  2020-03-09 19:52 ` [PATCH 20/21] drm: mxsfb: Merge mxsfb_set_pixel_fmt() and mxsfb_set_bus_fmt() Laurent Pinchart
@ 2020-03-09 19:52 ` Laurent Pinchart
  2020-03-23 23:48   ` Stefan Agner
  2020-03-19  9:36 ` [PATCH 00/21] drm: mxsfb: Add i.MX7 support Laurent Pinchart
                   ` (2 subsequent siblings)
  23 siblings, 1 reply; 62+ messages in thread
From: Laurent Pinchart @ 2020-03-09 19:52 UTC (permalink / raw)
  To: dri-devel; +Cc: Marek Vasut, kernel, linux-imx

The LCDIF in the i.MX6SX and i.MX7 have a second plane called the alpha
plane. Support it.

Signed-off-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
---
 drivers/gpu/drm/mxsfb/mxsfb_drv.c  |   3 +
 drivers/gpu/drm/mxsfb/mxsfb_drv.h  |  16 ++--
 drivers/gpu/drm/mxsfb/mxsfb_kms.c  | 129 +++++++++++++++++++++++++----
 drivers/gpu/drm/mxsfb/mxsfb_regs.h |  22 +++++
 4 files changed, 149 insertions(+), 21 deletions(-)

diff --git a/drivers/gpu/drm/mxsfb/mxsfb_drv.c b/drivers/gpu/drm/mxsfb/mxsfb_drv.c
index ed8e3f7bc27c..ab3a212375f1 100644
--- a/drivers/gpu/drm/mxsfb/mxsfb_drv.c
+++ b/drivers/gpu/drm/mxsfb/mxsfb_drv.c
@@ -49,6 +49,7 @@ static const struct mxsfb_devdata mxsfb_devdata[] = {
 		.next_buf	= LCDC_V3_NEXT_BUF,
 		.hs_wdth_mask	= 0xff,
 		.hs_wdth_shift	= 24,
+		.has_overlay	= false,
 	},
 	[MXSFB_V4] = {
 		.transfer_count	= LCDC_V4_TRANSFER_COUNT,
@@ -56,6 +57,7 @@ static const struct mxsfb_devdata mxsfb_devdata[] = {
 		.next_buf	= LCDC_V4_NEXT_BUF,
 		.hs_wdth_mask	= 0x3fff,
 		.hs_wdth_shift	= 18,
+		.has_overlay	= false,
 	},
 	[MXSFB_V6] = {
 		.transfer_count	= LCDC_V4_TRANSFER_COUNT,
@@ -63,6 +65,7 @@ static const struct mxsfb_devdata mxsfb_devdata[] = {
 		.next_buf	= LCDC_V4_NEXT_BUF,
 		.hs_wdth_mask	= 0x3fff,
 		.hs_wdth_shift	= 18,
+		.has_overlay	= true,
 	},
 };
 
diff --git a/drivers/gpu/drm/mxsfb/mxsfb_drv.h b/drivers/gpu/drm/mxsfb/mxsfb_drv.h
index 607a6a5e6be3..399d23e91ed1 100644
--- a/drivers/gpu/drm/mxsfb/mxsfb_drv.h
+++ b/drivers/gpu/drm/mxsfb/mxsfb_drv.h
@@ -16,11 +16,12 @@
 struct clk;
 
 struct mxsfb_devdata {
-	unsigned int	 transfer_count;
-	unsigned int	 cur_buf;
-	unsigned int	 next_buf;
-	unsigned int	 hs_wdth_mask;
-	unsigned int	 hs_wdth_shift;
+	unsigned int	transfer_count;
+	unsigned int	cur_buf;
+	unsigned int	next_buf;
+	unsigned int	hs_wdth_mask;
+	unsigned int	hs_wdth_shift;
+	bool		has_overlay;
 };
 
 struct mxsfb_drm_private {
@@ -32,7 +33,10 @@ struct mxsfb_drm_private {
 	struct clk			*clk_disp_axi;
 
 	struct drm_device		*drm;
-	struct drm_plane		plane;
+	struct {
+		struct drm_plane	primary;
+		struct drm_plane	overlay;
+	} planes;
 	struct drm_crtc			crtc;
 	struct drm_encoder		encoder;
 	struct drm_connector		*connector;
diff --git a/drivers/gpu/drm/mxsfb/mxsfb_kms.c b/drivers/gpu/drm/mxsfb/mxsfb_kms.c
index f81f8c222c13..c9c394f7cbe2 100644
--- a/drivers/gpu/drm/mxsfb/mxsfb_kms.c
+++ b/drivers/gpu/drm/mxsfb/mxsfb_kms.c
@@ -169,9 +169,9 @@ static int mxsfb_reset_block(struct mxsfb_drm_private *mxsfb)
 	return clear_poll_bit(mxsfb->base + LCDC_CTRL, CTRL_CLKGATE);
 }
 
-static dma_addr_t mxsfb_get_fb_paddr(struct mxsfb_drm_private *mxsfb)
+static dma_addr_t mxsfb_get_fb_paddr(struct drm_plane *plane)
 {
-	struct drm_framebuffer *fb = mxsfb->plane.state->fb;
+	struct drm_framebuffer *fb = plane->state->fb;
 	struct drm_gem_cma_object *gem;
 
 	if (!fb)
@@ -206,6 +206,9 @@ static void mxsfb_crtc_mode_set_nofb(struct mxsfb_drm_private *mxsfb)
 	/* Clear the FIFOs */
 	writel(CTRL1_FIFO_CLEAR, mxsfb->base + LCDC_CTRL1 + REG_SET);
 
+	if (mxsfb->devdata->has_overlay)
+		writel(0, mxsfb->base + LCDC_AS_CTRL);
+
 	mxsfb_set_formats(mxsfb);
 
 	clk_set_rate(mxsfb->clk, m->crtc_clock * 1000);
@@ -313,7 +316,7 @@ static void mxsfb_crtc_atomic_enable(struct drm_crtc *crtc,
 	mxsfb_crtc_mode_set_nofb(mxsfb);
 
 	/* Write cur_buf as well to avoid an initial corrupt frame */
-	paddr = mxsfb_get_fb_paddr(mxsfb);
+	paddr = mxsfb_get_fb_paddr(crtc->primary);
 	if (paddr) {
 		writel(paddr, mxsfb->base + mxsfb->devdata->cur_buf);
 		writel(paddr, mxsfb->base + mxsfb->devdata->next_buf);
@@ -410,20 +413,85 @@ static int mxsfb_plane_atomic_check(struct drm_plane *plane,
 						   false, true);
 }
 
-static void mxsfb_plane_atomic_update(struct drm_plane *plane,
-				      struct drm_plane_state *old_pstate)
+static void mxsfb_plane_primary_atomic_update(struct drm_plane *plane,
+					      struct drm_plane_state *old_pstate)
 {
 	struct mxsfb_drm_private *mxsfb = to_mxsfb_drm_private(plane->dev);
 	dma_addr_t paddr;
 
-	paddr = mxsfb_get_fb_paddr(mxsfb);
+	paddr = mxsfb_get_fb_paddr(plane);
 	if (paddr)
 		writel(paddr, mxsfb->base + mxsfb->devdata->next_buf);
 }
 
-static const struct drm_plane_helper_funcs mxsfb_plane_helper_funcs = {
+static void mxsfb_plane_overlay_atomic_update(struct drm_plane *plane,
+					      struct drm_plane_state *old_pstate)
+{
+	struct mxsfb_drm_private *mxsfb = to_mxsfb_drm_private(plane->dev);
+	struct drm_plane_state *state = plane->state;
+	dma_addr_t paddr;
+	u32 ctrl;
+
+	paddr = mxsfb_get_fb_paddr(plane);
+	if (!paddr) {
+		writel(0, mxsfb->base + LCDC_AS_CTRL);
+		return;
+	}
+
+	/*
+	 * HACK: The hardware seems to output 64 bytes of data of unknown
+	 * origin, and then to proceed with the framebuffer. Until the reason
+	 * is understood, live with the 16 initial invalid pixels on the first
+	 * line and start 64 bytes within the framebuffer.
+	 */
+	paddr += 64;
+
+	writel(paddr, mxsfb->base + LCDC_AS_NEXT_BUF);
+
+	/*
+	 * If the plane was previously disabled, write LCDC_AS_BUF as well to
+	 * provide the first buffer.
+	 */
+	if (!old_pstate->fb)
+		writel(paddr, mxsfb->base + LCDC_AS_BUF);
+
+	ctrl = AS_CTRL_AS_ENABLE | AS_CTRL_ALPHA(255);
+
+	switch (state->fb->format->format) {
+	case DRM_FORMAT_XRGB4444:
+		ctrl |= AS_CTRL_FORMAT_RGB444 | AS_CTRL_ALPHA_CTRL_OVERRIDE;
+		break;
+	case DRM_FORMAT_ARGB4444:
+		ctrl |= AS_CTRL_FORMAT_ARGB4444 | AS_CTRL_ALPHA_CTRL_EMBEDDED;
+		break;
+	case DRM_FORMAT_XRGB1555:
+		ctrl |= AS_CTRL_FORMAT_RGB555 | AS_CTRL_ALPHA_CTRL_OVERRIDE;
+		break;
+	case DRM_FORMAT_ARGB1555:
+		ctrl |= AS_CTRL_FORMAT_ARGB1555 | AS_CTRL_ALPHA_CTRL_EMBEDDED;
+		break;
+	case DRM_FORMAT_RGB565:
+		ctrl |= AS_CTRL_FORMAT_RGB565 | AS_CTRL_ALPHA_CTRL_OVERRIDE;
+		break;
+	case DRM_FORMAT_XRGB8888:
+		ctrl |= AS_CTRL_FORMAT_RGB888 | AS_CTRL_ALPHA_CTRL_OVERRIDE;
+		break;
+	case DRM_FORMAT_ARGB8888:
+		ctrl |= AS_CTRL_FORMAT_ARGB8888 | AS_CTRL_ALPHA_CTRL_EMBEDDED;
+		break;
+	}
+
+	writel(ctrl, mxsfb->base + LCDC_AS_CTRL);
+}
+
+static const struct drm_plane_helper_funcs mxsfb_plane_primary_helper_funcs = {
+	.atomic_check = mxsfb_plane_atomic_check,
+	.atomic_update = mxsfb_plane_primary_atomic_update,
+};
+
+static const struct drm_plane_helper_funcs mxsfb_plane_overlay_helper_funcs = {
 	.atomic_check = mxsfb_plane_atomic_check,
-	.atomic_update = mxsfb_plane_atomic_update,
+	.atomic_update = mxsfb_plane_overlay_atomic_update,
 };
 
 static const struct drm_plane_funcs mxsfb_plane_funcs = {
@@ -435,27 +503,58 @@ static const struct drm_plane_funcs mxsfb_plane_funcs = {
 	.atomic_destroy_state	= drm_atomic_helper_plane_destroy_state,
 };
 
-static const uint32_t mxsfb_formats[] = {
+static const uint32_t mxsfb_primary_plane_formats[] = {
+	DRM_FORMAT_RGB565,
+	DRM_FORMAT_XRGB8888,
+};
+
+static const uint32_t mxsfb_overlay_plane_formats[] = {
+	DRM_FORMAT_XRGB4444,
+	DRM_FORMAT_ARGB4444,
+	DRM_FORMAT_XRGB1555,
+	DRM_FORMAT_ARGB1555,
+	DRM_FORMAT_RGB565,
 	DRM_FORMAT_XRGB8888,
-	DRM_FORMAT_RGB565
+	DRM_FORMAT_ARGB8888,
 };
 
+/* -----------------------------------------------------------------------------
+ * Initialization
+ */
+
 int mxsfb_kms_init(struct mxsfb_drm_private *mxsfb)
 {
 	struct drm_encoder *encoder = &mxsfb->encoder;
-	struct drm_plane *plane = &mxsfb->plane;
 	struct drm_crtc *crtc = &mxsfb->crtc;
 	int ret;
 
-	drm_plane_helper_add(plane, &mxsfb_plane_helper_funcs);
-	ret = drm_universal_plane_init(mxsfb->drm, plane, 0, &mxsfb_plane_funcs,
-				       mxsfb_formats, ARRAY_SIZE(mxsfb_formats),
+	drm_plane_helper_add(&mxsfb->planes.primary,
+			     &mxsfb_plane_primary_helper_funcs);
+	ret = drm_universal_plane_init(mxsfb->drm, &mxsfb->planes.primary, 1,
+				       &mxsfb_plane_funcs,
+				       mxsfb_primary_plane_formats,
+				       ARRAY_SIZE(mxsfb_primary_plane_formats),
 				       NULL, DRM_PLANE_TYPE_PRIMARY, NULL);
 	if (ret)
 		return ret;
 
+	if (mxsfb->devdata->has_overlay) {
+		drm_plane_helper_add(&mxsfb->planes.overlay,
+				     &mxsfb_plane_overlay_helper_funcs);
+		ret = drm_universal_plane_init(mxsfb->drm,
+					       &mxsfb->planes.overlay, 1,
+					       &mxsfb_plane_funcs,
+					       mxsfb_overlay_plane_formats,
+					       ARRAY_SIZE(mxsfb_overlay_plane_formats),
+					       NULL, DRM_PLANE_TYPE_OVERLAY,
+					       NULL);
+		if (ret)
+			return ret;
+	}
+
 	drm_crtc_helper_add(crtc, &mxsfb_crtc_helper_funcs);
-	ret = drm_crtc_init_with_planes(mxsfb->drm, crtc, plane, NULL,
+	ret = drm_crtc_init_with_planes(mxsfb->drm, crtc,
+					&mxsfb->planes.primary, NULL,
 					&mxsfb_crtc_funcs, NULL);
 	if (ret)
 		return ret;
diff --git a/drivers/gpu/drm/mxsfb/mxsfb_regs.h b/drivers/gpu/drm/mxsfb/mxsfb_regs.h
index 8ebb52bb1b46..55d28a27f912 100644
--- a/drivers/gpu/drm/mxsfb/mxsfb_regs.h
+++ b/drivers/gpu/drm/mxsfb/mxsfb_regs.h
@@ -27,6 +27,11 @@
 #define LCDC_VDCTRL4			0xb0
 #define LCDC_V4_DEBUG0			0x1d0
 #define LCDC_V3_DEBUG0			0x1f0
+#define LCDC_AS_CTRL			0x210
+#define LCDC_AS_BUF			0x220
+#define LCDC_AS_NEXT_BUF		0x230
+#define LCDC_AS_CLRKEYLOW		0x240
+#define LCDC_AS_CLRKEYHIGH		0x250
 
 #define CTRL_SFTRST			BIT(31)
 #define CTRL_CLKGATE			BIT(30)
@@ -90,6 +95,23 @@
 #define DEBUG0_HSYNC			BIT(26)
 #define DEBUG0_VSYNC			BIT(25)
 
+#define AS_CTRL_PS_DISABLE		BIT(23)
+#define AS_CTRL_ALPHA_INVERT		BIT(20)
+#define AS_CTRL_ALPHA(a)		(((a) & 0xff) << 8)
+#define AS_CTRL_FORMAT_RGB565		(0xe << 4)
+#define AS_CTRL_FORMAT_RGB444		(0xd << 4)
+#define AS_CTRL_FORMAT_RGB555		(0xc << 4)
+#define AS_CTRL_FORMAT_ARGB4444		(0x9 << 4)
+#define AS_CTRL_FORMAT_ARGB1555		(0x8 << 4)
+#define AS_CTRL_FORMAT_RGB888		(0x4 << 4)
+#define AS_CTRL_FORMAT_ARGB8888		(0x0 << 4)
+#define AS_CTRL_ENABLE_COLORKEY		BIT(3)
+#define AS_CTRL_ALPHA_CTRL_ROP		(3 << 1)
+#define AS_CTRL_ALPHA_CTRL_MULTIPLY	(2 << 1)
+#define AS_CTRL_ALPHA_CTRL_OVERRIDE	(1 << 1)
+#define AS_CTRL_ALPHA_CTRL_EMBEDDED	(0 << 1)
+#define AS_CTRL_AS_ENABLE		BIT(0)
+
 #define MXSFB_MIN_XRES			120
 #define MXSFB_MIN_YRES			120
 #define MXSFB_MAX_XRES			0xffff
-- 
Regards,

Laurent Pinchart

_______________________________________________
dri-devel mailing list
dri-devel@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/dri-devel

^ permalink raw reply related	[flat|nested] 62+ messages in thread

* Re: [PATCH 16/21] drm: mxsfb: Add i.MX7 to the list of supported SoCs in Kconfig
  2020-03-09 19:52 ` [PATCH 16/21] drm: mxsfb: Add i.MX7 to the list of supported SoCs in Kconfig Laurent Pinchart
@ 2020-03-10 16:28   ` Fabio Estevam
  2020-03-10 16:32     ` Laurent Pinchart
  2020-03-23 23:18   ` [PATCH " Stefan Agner
  1 sibling, 1 reply; 62+ messages in thread
From: Fabio Estevam @ 2020-03-10 16:28 UTC (permalink / raw)
  To: Laurent Pinchart
  Cc: Marek Vasut, Sascha Hauer, DRI mailing list, NXP Linux Team

Hi Laurent,

On Mon, Mar 9, 2020 at 4:53 PM Laurent Pinchart
<laurent.pinchart@ideasonboard.com> wrote:

>  config DRM_MXSFB
> -       tristate "i.MX23/i.MX28/i.MX6SX MXSFB LCD controller"
> +       tristate "i.MX23/i.MX28/i.MX6SX/i.MX7 MXSFB LCD controller"

Can't we just make it simpler and write: tristate "i.MX eLCDIF
controller" instead?

Otherwise this list will get longer each time a new SoC is supported:

tristate "i.MX23/i.MX28/i.MX6SX/i.MX6SL/i.MX7/i.MX7ULP/i.MX8M/i.MX8MM/i.MX8QXP/i.MX8M
MXSFB LCD controller"

and probably more :-)
_______________________________________________
dri-devel mailing list
dri-devel@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/dri-devel

^ permalink raw reply	[flat|nested] 62+ messages in thread

* Re: [PATCH 16/21] drm: mxsfb: Add i.MX7 to the list of supported SoCs in Kconfig
  2020-03-10 16:28   ` Fabio Estevam
@ 2020-03-10 16:32     ` Laurent Pinchart
  2020-03-10 16:37       ` [PATCH v1.1 " Laurent Pinchart
  0 siblings, 1 reply; 62+ messages in thread
From: Laurent Pinchart @ 2020-03-10 16:32 UTC (permalink / raw)
  To: Fabio Estevam; +Cc: Marek Vasut, Sascha Hauer, DRI mailing list, NXP Linux Team

Hi Fabio,

On Tue, Mar 10, 2020 at 01:28:35PM -0300, Fabio Estevam wrote:
> On Mon, Mar 9, 2020 at 4:53 PM Laurent Pinchart wrote:
> 
> >  config DRM_MXSFB
> > -       tristate "i.MX23/i.MX28/i.MX6SX MXSFB LCD controller"
> > +       tristate "i.MX23/i.MX28/i.MX6SX/i.MX7 MXSFB LCD controller"
> 
> Can't we just make it simpler and write: tristate "i.MX eLCDIF
> controller" instead?

It should then be "LCDIF and eLCDIF controllers" or "(e)LCDIF
controller", as the versions prior to i.MX6 were LCDIF and got later
extended to eLCDIF.

> Otherwise this list will get longer each time a new SoC is supported:
> 
> tristate "i.MX23/i.MX28/i.MX6SX/i.MX6SL/i.MX7/i.MX7ULP/i.MX8M/i.MX8MM/i.MX8QXP/i.MX8M
> MXSFB LCD controller"
> 
> and probably more :-)

It's a good point, and I agree. I'll fix this.

-- 
Regards,

Laurent Pinchart
_______________________________________________
dri-devel mailing list
dri-devel@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/dri-devel

^ permalink raw reply	[flat|nested] 62+ messages in thread

* [PATCH v1.1 16/21] drm: mxsfb: Add i.MX7 to the list of supported SoCs in Kconfig
  2020-03-10 16:32     ` Laurent Pinchart
@ 2020-03-10 16:37       ` Laurent Pinchart
  0 siblings, 0 replies; 62+ messages in thread
From: Laurent Pinchart @ 2020-03-10 16:37 UTC (permalink / raw)
  To: dri-devel; +Cc: Marek Vasut, linux-imx, Sascha Hauer

Extend the Kconfig option description by listing the i.MX7 SoCs, as they
are supported by the same driver. Replace the list of SoCs in the short
description with just "(e)LCDIF LCD controller" to avoid expanding it
further in the future as support for more SoCs is added.

Signed-off-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
---
 drivers/gpu/drm/mxsfb/Kconfig | 7 ++++---
 1 file changed, 4 insertions(+), 3 deletions(-)

diff --git a/drivers/gpu/drm/mxsfb/Kconfig b/drivers/gpu/drm/mxsfb/Kconfig
index 0dca8f27169e..0b407338dd46 100644
--- a/drivers/gpu/drm/mxsfb/Kconfig
+++ b/drivers/gpu/drm/mxsfb/Kconfig
@@ -5,7 +5,7 @@ config DRM_MXS
 	  Choose this option to select drivers for MXS FB devices
 
 config DRM_MXSFB
-	tristate "i.MX23/i.MX28/i.MX6SX MXSFB LCD controller"
+	tristate "i.MX (e)LCDIF LCD controller"
 	depends on DRM && OF
 	depends on COMMON_CLK
 	select DRM_MXS
@@ -14,7 +14,8 @@ config DRM_MXSFB
 	select DRM_KMS_CMA_HELPER
 	select DRM_PANEL
 	help
-	  Choose this option if you have an i.MX23/i.MX28/i.MX6SX MXSFB
-	  LCD controller.
+	  Choose this option if you have an LCDIF or eLCDIF LCD controller.
+	  Those devices are found in various i.MX SoC (including i.MX23,
+	  i.MX28, i.MX6SX and i.MX7).
 
 	  If M is selected the module will be called mxsfb.
-- 
Regards,

Laurent Pinchart

_______________________________________________
dri-devel mailing list
dri-devel@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/dri-devel

^ permalink raw reply related	[flat|nested] 62+ messages in thread

* Re: [PATCH 00/21] drm: mxsfb: Add i.MX7 support
  2020-03-09 19:51 [PATCH 00/21] drm: mxsfb: Add i.MX7 support Laurent Pinchart
                   ` (20 preceding siblings ...)
  2020-03-09 19:52 ` [PATCH 21/21] drm: mxsfb: Support the alpha plane Laurent Pinchart
@ 2020-03-19  9:36 ` Laurent Pinchart
  2020-04-12 16:37 ` Guido Günther
  2020-05-26 15:13 ` Stefan Agner
  23 siblings, 0 replies; 62+ messages in thread
From: Laurent Pinchart @ 2020-03-19  9:36 UTC (permalink / raw)
  To: dri-devel; +Cc: Marek Vasut, kernel, linux-imx

Hello,

Gentle ping.

On Mon, Mar 09, 2020 at 09:51:55PM +0200, Laurent Pinchart wrote:
> Hello,
> 
> This patch series adds i.MX7 support to the mxsfb driver. The eLCDIF
> instance found in the i.MX7 is backward-compatible with the already
> supported LCDC v4, but has extended features amongst which the most
> notable one is a second plane.
> 
> The first 9 patches (01/21 to 09/21) contain miscellaneous cleanups and
> refactoring to prepare for what is to come. Patch 10/21 starts the real
> work with removal of the DRM simple display pipeline helper, as it
> doesn't support multiple planes. The next patch (11/21) is an additional
> cleanup.
> 
> Patches 12/21 to 14/21 fix vblank handling that I found to be broken
> when testing on my device. Patch 15/21 then performs an additional small
> cleanup, and patch 16/21 starts official support for i.MX7 by mentioning
> it in Kconfig.
> 
> Patch 17/21 adds a new device model for the i.MX6SX and i.MX7 eLCDIF.
> After three additional cleanups in patches 18/21 to 20/21, patch 21/21
> finally adds support for the second plane.
> 
> The code is based on drm-misc-next and has been tested on an i.MX7D
> platform with a DPI panel.
> 
> Laurent Pinchart (21):
>   drm: mxsfb: Remove fbdev leftovers
>   drm: mxsfb: Use drm_panel_bridge
>   drm: mxsfb: Use BIT() macro to define register bitfields
>   drm: mxsfb: Remove unused macros from mxsfb_regs.h
>   drm: mxsfb: Clarify format and bus width configuration
>   drm: mxsfb: Pass mxsfb_drm_private pointer to mxsfb_reset_block()
>   drm: mxsfb: Use LCDC_CTRL register name explicitly
>   drm: mxsfb: Remove register definitions from mxsfb_crtc.c
>   drm: mxsfb: Remove unneeded includes
>   drm: mxsfb: Stop using DRM simple display pipeline helper
>   drm: mxsfb: Rename mxsfb_crtc.c to mxsfb_kms.c
>   drm: mxsfb: Move vblank event arm to CRTC .atomic_flush()
>   drm: mxsfb: Don't touch AXI clock in IRQ context
>   drm: mxsfb: Enable vblank handling
>   drm: mxsfb: Remove mxsfb_devdata unused fields
>   drm: mxsfb: Add i.MX7 to the list of supported SoCs in Kconfig
>   drm: mxsfb: Update internal IP version number for i.MX6SX
>   drm: mxsfb: Drop non-OF support
>   drm: mxsfb: Turn mxsfb_set_pixel_fmt() into a void function
>   drm: mxsfb: Merge mxsfb_set_pixel_fmt() and mxsfb_set_bus_fmt()
>   drm: mxsfb: Support the alpha plane
> 
>  drivers/gpu/drm/mxsfb/Kconfig      |   4 +-
>  drivers/gpu/drm/mxsfb/Makefile     |   2 +-
>  drivers/gpu/drm/mxsfb/mxsfb_crtc.c | 343 -----------------
>  drivers/gpu/drm/mxsfb/mxsfb_drv.c  | 246 ++++---------
>  drivers/gpu/drm/mxsfb/mxsfb_drv.h  |  42 ++-
>  drivers/gpu/drm/mxsfb/mxsfb_kms.c  | 565 +++++++++++++++++++++++++++++
>  drivers/gpu/drm/mxsfb/mxsfb_out.c  |  99 -----
>  drivers/gpu/drm/mxsfb/mxsfb_regs.h | 107 +++---
>  8 files changed, 730 insertions(+), 678 deletions(-)
>  delete mode 100644 drivers/gpu/drm/mxsfb/mxsfb_crtc.c
>  create mode 100644 drivers/gpu/drm/mxsfb/mxsfb_kms.c
>  delete mode 100644 drivers/gpu/drm/mxsfb/mxsfb_out.c

-- 
Regards,

Laurent Pinchart
_______________________________________________
dri-devel mailing list
dri-devel@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/dri-devel

^ permalink raw reply	[flat|nested] 62+ messages in thread

* Re: [PATCH 01/21] drm: mxsfb: Remove fbdev leftovers
  2020-03-09 19:51 ` [PATCH 01/21] drm: mxsfb: Remove fbdev leftovers Laurent Pinchart
@ 2020-03-23 20:23   ` Stefan Agner
  0 siblings, 0 replies; 62+ messages in thread
From: Stefan Agner @ 2020-03-23 20:23 UTC (permalink / raw)
  To: Laurent Pinchart; +Cc: Marek Vasut, kernel, dri-devel, linux-imx

On 2020-03-09 20:51, Laurent Pinchart wrote:
> Commit 8e93f1028d74 ("drm/mxsfb: Use drm_fbdev_generic_setup()")
> replaced fbdev handling with drm_fbdev_generic_setup() but left
> inclusion of the drm/drm_fb_cma_helper.h header. Remove it.
> 
> Fixes: 8e93f1028d74 ("drm/mxsfb: Use drm_fbdev_generic_setup()")
> Signed-off-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>

Reviewed-by: Stefan Agner <stefan@agner.ch>

I guess this could be merge independent of the rest already today.

--
Stefan

> ---
>  drivers/gpu/drm/mxsfb/mxsfb_drv.c | 1 -
>  1 file changed, 1 deletion(-)
> 
> diff --git a/drivers/gpu/drm/mxsfb/mxsfb_drv.c
> b/drivers/gpu/drm/mxsfb/mxsfb_drv.c
> index 497cf443a9af..2e6068d96034 100644
> --- a/drivers/gpu/drm/mxsfb/mxsfb_drv.c
> +++ b/drivers/gpu/drm/mxsfb/mxsfb_drv.c
> @@ -24,7 +24,6 @@
>  #include <drm/drm_atomic_helper.h>
>  #include <drm/drm_crtc.h>
>  #include <drm/drm_drv.h>
> -#include <drm/drm_fb_cma_helper.h>
>  #include <drm/drm_fb_helper.h>
>  #include <drm/drm_gem_cma_helper.h>
>  #include <drm/drm_gem_framebuffer_helper.h>
_______________________________________________
dri-devel mailing list
dri-devel@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/dri-devel

^ permalink raw reply	[flat|nested] 62+ messages in thread

* Re: [PATCH 02/21] drm: mxsfb: Use drm_panel_bridge
  2020-03-09 19:51 ` [PATCH 02/21] drm: mxsfb: Use drm_panel_bridge Laurent Pinchart
@ 2020-03-23 21:27   ` Stefan Agner
  2020-03-23 21:38     ` Sam Ravnborg
  2020-05-30  2:14     ` Laurent Pinchart
  0 siblings, 2 replies; 62+ messages in thread
From: Stefan Agner @ 2020-03-23 21:27 UTC (permalink / raw)
  To: Laurent Pinchart; +Cc: Marek Vasut, kernel, dri-devel, linux-imx

On 2020-03-09 20:51, Laurent Pinchart wrote:
> Replace the manual connector implementation based on drm_panel with the
> drm_panel_bridge helper. This simplifies the mxsfb driver by removing
> connector-related code, and standardizing all pipeline control
> operations on bridges.
> 
> A hack is needed to get hold of the connector, as that's our only source
> of bus flags and formats for now. As soon as the bridge API provides us
> with that information this can be fixed.

This seems like a nice simplification.

I gave this a go applied on today's drm-misc-next using a Colibri iMX7
(imx7d-colibri-emmc-eval-v3.dts device tree). This device makes use of
the simple panel driver. I get this when booting:

[    2.976698] [drm] Supports vblank timestamp caching Rev 2
(21.10.2013).
[    2.983526] ------------[ cut here ]------------
[    2.988180] WARNING: CPU: 0 PID: 1 at
drivers/gpu/drm/bridge/panel.c:267 devm_drm_panel_bridge_add+0x25/0x28
[    2.998059] Modules linked in:
[    3.001159] CPU: 0 PID: 1 Comm: swapper/0 Not tainted
5.6.0-rc5-yocto-standard-01250-ga4ce5db7c9f1 #29
[    3.010493] Hardware name: Freescale i.MX7 Dual (Device Tree)
[    3.016281] [<c010f089>] (unwind_backtrace) from [<c010a9bb>]
(show_stack+0xb/0xc)
[    3.023887] [<c010a9bb>] (show_stack) from [<c08b33cf>]
(dump_stack+0x63/0x70)
[    3.031144] [<c08b33cf>] (dump_stack) from [<c0124385>]
(__warn+0x9d/0xb0)
[    3.038047] [<c0124385>] (__warn) from [<c0124403>]
(warn_slowpath_fmt+0x6b/0x70)
[    3.045564] [<c0124403>] (warn_slowpath_fmt) from [<c04ebf65>]
(devm_drm_panel_bridge_add+0x25/0x28)
[    3.054736] [<c04ebf65>] (devm_drm_panel_bridge_add) from
[<c051fe7f>] (mxsfb_probe+0x197/0x2e0)
[    3.063559] [<c051fe7f>] (mxsfb_probe) from [<c0532e91>]
(platform_drv_probe+0x2d/0x60)
[    3.071598] [<c0532e91>] (platform_drv_probe) from [<c0531615>]
(really_probe+0x1dd/0x330)
[    3.079897] [<c0531615>] (really_probe) from [<c05318b3>]
(driver_probe_device+0x4f/0x154)
[    3.088195] [<c05318b3>] (driver_probe_device) from [<c0531b3f>]
(device_driver_attach+0x37/0x44)
[    3.097101] [<c0531b3f>] (device_driver_attach) from [<c0531bc7>]
(__driver_attach+0x7b/0xec)
[    3.105660] [<c0531bc7>] (__driver_attach) from [<c0530069>]
(bus_for_each_dev+0x3d/0x64)
[    3.113870] [<c0530069>] (bus_for_each_dev) from [<c0530b9b>]
(bus_add_driver+0xef/0x160)
[    3.122081] [<c0530b9b>] (bus_add_driver) from [<c053238d>]
(driver_register+0x35/0x9c)
[    3.130119] [<c053238d>] (driver_register) from [<c0102de9>]
(do_one_initcall+0x3d/0x1e4)
[    3.138333] [<c0102de9>] (do_one_initcall) from [<c1100d13>]
(kernel_init_freeable+0x1b3/0x1fc)
[    3.147069] [<c1100d13>] (kernel_init_freeable) from [<c08c3f7b>]
(kernel_init+0x7/0xd0)
[    3.155194] [<c08c3f7b>] (kernel_init) from [<c01010f9>]
(ret_from_fork+0x11/0x38)
[    3.162789] Exception stack(0xec0e3fb0 to 0xec0e3ff8)
[    3.167862] 3fa0:                                     00000000
00000000 00000000 00000000
[    3.176071] 3fc0: 00000000 00000000 00000000 00000000 00000000
00000000 00000000 00000000
[    3.184278] 3fe0: 00000000 00000000 00000000 00000000 00000013
00000000
[    3.191029] ---[ end trace b69e1f44de470959 ]---
[    3.195671] mxsfb 30730000.lcdif: Cannot connect bridge: -19

Should we maybe use devm_drm_panel_bridge_add_typed?

Two more comments below.

> 
> Signed-off-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
> ---
>  drivers/gpu/drm/mxsfb/Makefile    |   2 +-
>  drivers/gpu/drm/mxsfb/mxsfb_drv.c | 105 ++++++++++++++----------------
>  drivers/gpu/drm/mxsfb/mxsfb_drv.h |   5 +-
>  drivers/gpu/drm/mxsfb/mxsfb_out.c |  99 ----------------------------
>  4 files changed, 53 insertions(+), 158 deletions(-)
>  delete mode 100644 drivers/gpu/drm/mxsfb/mxsfb_out.c
> 
> diff --git a/drivers/gpu/drm/mxsfb/Makefile b/drivers/gpu/drm/mxsfb/Makefile
> index ff6e358088fa..811584e54ad1 100644
> --- a/drivers/gpu/drm/mxsfb/Makefile
> +++ b/drivers/gpu/drm/mxsfb/Makefile
> @@ -1,3 +1,3 @@
>  # SPDX-License-Identifier: GPL-2.0-only
> -mxsfb-y := mxsfb_drv.o mxsfb_crtc.o mxsfb_out.o
> +mxsfb-y := mxsfb_drv.o mxsfb_crtc.o
>  obj-$(CONFIG_DRM_MXSFB)	+= mxsfb.o
> diff --git a/drivers/gpu/drm/mxsfb/mxsfb_drv.c
> b/drivers/gpu/drm/mxsfb/mxsfb_drv.c
> index 2e6068d96034..cffc70257bd3 100644
> --- a/drivers/gpu/drm/mxsfb/mxsfb_drv.c
> +++ b/drivers/gpu/drm/mxsfb/mxsfb_drv.c
> @@ -29,7 +29,6 @@
>  #include <drm/drm_gem_framebuffer_helper.h>
>  #include <drm/drm_irq.h>
>  #include <drm/drm_of.h>
> -#include <drm/drm_panel.h>
>  #include <drm/drm_probe_helper.h>
>  #include <drm/drm_simple_kms_helper.h>
>  #include <drm/drm_vblank.h>
> @@ -100,29 +99,11 @@ static void mxsfb_pipe_enable(struct
> drm_simple_display_pipe *pipe,
>  			      struct drm_crtc_state *crtc_state,
>  			      struct drm_plane_state *plane_state)
>  {
> -	struct drm_connector *connector;
>  	struct mxsfb_drm_private *mxsfb = drm_pipe_to_mxsfb_drm_private(pipe);
>  	struct drm_device *drm = pipe->plane.dev;
>  
> -	if (!mxsfb->connector) {
> -		list_for_each_entry(connector,
> -				    &drm->mode_config.connector_list,
> -				    head)
> -			if (connector->encoder == &mxsfb->pipe.encoder) {
> -				mxsfb->connector = connector;
> -				break;
> -			}
> -	}
> -
> -	if (!mxsfb->connector) {
> -		dev_warn(drm->dev, "No connector attached, using default\n");
> -		mxsfb->connector = &mxsfb->panel_connector;
> -	}
> -
>  	pm_runtime_get_sync(drm->dev);
> -	drm_panel_prepare(mxsfb->panel);
>  	mxsfb_crtc_enable(mxsfb);
> -	drm_panel_enable(mxsfb->panel);
>  }
>  
>  static void mxsfb_pipe_disable(struct drm_simple_display_pipe *pipe)
> @@ -132,9 +113,7 @@ static void mxsfb_pipe_disable(struct
> drm_simple_display_pipe *pipe)
>  	struct drm_crtc *crtc = &pipe->crtc;
>  	struct drm_pending_vblank_event *event;
>  
> -	drm_panel_disable(mxsfb->panel);
>  	mxsfb_crtc_disable(mxsfb);
> -	drm_panel_unprepare(mxsfb->panel);
>  	pm_runtime_put_sync(drm->dev);
>  
>  	spin_lock_irq(&drm->event_lock);
> @@ -144,9 +123,6 @@ static void mxsfb_pipe_disable(struct
> drm_simple_display_pipe *pipe)
>  		drm_crtc_send_vblank_event(crtc, event);
>  	}
>  	spin_unlock_irq(&drm->event_lock);
> -
> -	if (mxsfb->connector != &mxsfb->panel_connector)
> -		mxsfb->connector = NULL;
>  }
>  
>  static void mxsfb_pipe_update(struct drm_simple_display_pipe *pipe,
> @@ -190,6 +166,48 @@ static struct drm_simple_display_pipe_funcs mxsfb_funcs = {
>  	.disable_vblank	= mxsfb_pipe_disable_vblank,
>  };
>  
> +static int mxsfb_attach_bridge(struct mxsfb_drm_private *mxsfb)
> +{
> +	struct drm_device *drm = mxsfb->drm;
> +	struct drm_connector_list_iter iter;
> +	struct drm_panel *panel;
> +	struct drm_bridge *bridge;
> +	int ret;
> +
> +	ret = drm_of_find_panel_or_bridge(drm->dev->of_node, 0, 0, &panel,
> +					  &bridge);
> +	if (ret)
> +		return ret;
> +
> +	if (panel) {
> +		bridge = devm_drm_panel_bridge_add(drm->dev, panel);

Do we need a select DRM_PANEL_BRIDGE in Kconfig maybe? From what I can
tell there is no devm_drm_panel_bridge_add() stub if DRM_PANEL_BRIDGE is
not selected.

> +		if (IS_ERR(bridge))
> +			return PTR_ERR(bridge);
> +	}
> +
> +	if (!bridge)
> +		return -ENODEV;
> +
> +	ret = drm_simple_display_pipe_attach_bridge(&mxsfb->pipe, bridge);
> +	if (ret) {
> +		DRM_DEV_ERROR(drm->dev,
> +			      "failed to attach bridge: %d\n", ret);
> +		return ret;
> +	}
> +
> +	mxsfb->bridge = bridge;
> +
> +	/*
> +	 * Get hold of the connector. This is a bit of a hack, until the bridge
> +	 * API gives us bus flags and formats.
> +	 */
> +	drm_connector_list_iter_begin(drm, &iter);
> +	mxsfb->connector = drm_connector_list_iter_next(&iter);
> +	drm_connector_list_iter_end(&iter);

Could we not just use drm_panel_bridge_connector() here?

--
Stefan

> +
> +	return 0;
> +}
> +
>  static int mxsfb_load(struct drm_device *drm, unsigned long flags)
>  {
>  	struct platform_device *pdev = to_platform_device(drm->dev);
> @@ -201,6 +219,7 @@ static int mxsfb_load(struct drm_device *drm,
> unsigned long flags)
>  	if (!mxsfb)
>  		return -ENOMEM;
>  
> +	mxsfb->drm = drm;
>  	drm->dev_private = mxsfb;
>  	mxsfb->devdata = &mxsfb_devdata[pdev->id_entry->driver_data];
>  
> @@ -236,41 +255,17 @@ static int mxsfb_load(struct drm_device *drm,
> unsigned long flags)
>  	/* Modeset init */
>  	drm_mode_config_init(drm);
>  
> -	ret = mxsfb_create_output(drm);
> -	if (ret < 0) {
> -		dev_err(drm->dev, "Failed to create outputs\n");
> -		goto err_vblank;
> -	}
> -
>  	ret = drm_simple_display_pipe_init(drm, &mxsfb->pipe, &mxsfb_funcs,
> -			mxsfb_formats, ARRAY_SIZE(mxsfb_formats), NULL,
> -			mxsfb->connector);
> +			mxsfb_formats, ARRAY_SIZE(mxsfb_formats), NULL, NULL);
>  	if (ret < 0) {
>  		dev_err(drm->dev, "Cannot setup simple display pipe\n");
>  		goto err_vblank;
>  	}
>  
> -	/*
> -	 * Attach panel only if there is one.
> -	 * If there is no panel attach, it must be a bridge. In this case, we
> -	 * need a reference to its connector for a proper initialization.
> -	 * We will do this check in pipe->enable(), since the connector won't
> -	 * be attached to an encoder until then.
> -	 */
> -
> -	if (mxsfb->panel) {
> -		ret = drm_panel_attach(mxsfb->panel, mxsfb->connector);
> -		if (ret) {
> -			dev_err(drm->dev, "Cannot connect panel: %d\n", ret);
> -			goto err_vblank;
> -		}
> -	} else if (mxsfb->bridge) {
> -		ret = drm_simple_display_pipe_attach_bridge(&mxsfb->pipe,
> -							    mxsfb->bridge);
> -		if (ret) {
> -			dev_err(drm->dev, "Cannot connect bridge: %d\n", ret);
> -			goto err_vblank;
> -		}
> +	ret = mxsfb_attach_bridge(mxsfb);
> +	if (ret) {
> +		dev_err(drm->dev, "Cannot connect bridge: %d\n", ret);
> +		goto err_vblank;
>  	}
>  
>  	drm->mode_config.min_width	= MXSFB_MIN_XRES;
> @@ -288,7 +283,7 @@ static int mxsfb_load(struct drm_device *drm,
> unsigned long flags)
>  
>  	if (ret < 0) {
>  		dev_err(drm->dev, "Failed to install IRQ handler\n");
> -		goto err_irq;
> +		goto err_vblank;
>  	}
>  
>  	drm_kms_helper_poll_init(drm);
> @@ -299,8 +294,6 @@ static int mxsfb_load(struct drm_device *drm,
> unsigned long flags)
>  
>  	return 0;
>  
> -err_irq:
> -	drm_panel_detach(mxsfb->panel);
>  err_vblank:
>  	pm_runtime_disable(drm->dev);
>  
> diff --git a/drivers/gpu/drm/mxsfb/mxsfb_drv.h
> b/drivers/gpu/drm/mxsfb/mxsfb_drv.h
> index 0b65b5194a9c..0e3e5a63bbf9 100644
> --- a/drivers/gpu/drm/mxsfb/mxsfb_drv.h
> +++ b/drivers/gpu/drm/mxsfb/mxsfb_drv.h
> @@ -8,6 +8,8 @@
>  #ifndef __MXSFB_DRV_H__
>  #define __MXSFB_DRV_H__
>  
> +struct drm_device;
> +
>  struct mxsfb_devdata {
>  	unsigned int	 transfer_count;
>  	unsigned int	 cur_buf;
> @@ -26,10 +28,9 @@ struct mxsfb_drm_private {
>  	struct clk			*clk_axi;
>  	struct clk			*clk_disp_axi;
>  
> +	struct drm_device		*drm;
>  	struct drm_simple_display_pipe	pipe;
> -	struct drm_connector		panel_connector;
>  	struct drm_connector		*connector;
> -	struct drm_panel		*panel;
>  	struct drm_bridge		*bridge;
>  };
>  
> diff --git a/drivers/gpu/drm/mxsfb/mxsfb_out.c
> b/drivers/gpu/drm/mxsfb/mxsfb_out.c
> deleted file mode 100644
> index 9eca1605d11d..000000000000
> --- a/drivers/gpu/drm/mxsfb/mxsfb_out.c
> +++ /dev/null
> @@ -1,99 +0,0 @@
> -// SPDX-License-Identifier: GPL-2.0-or-later
> -/*
> - * Copyright (C) 2016 Marek Vasut <marex@denx.de>
> - */
> -
> -#include <linux/of_graph.h>
> -
> -#include <drm/drm_atomic.h>
> -#include <drm/drm_atomic_helper.h>
> -#include <drm/drm_crtc.h>
> -#include <drm/drm_fb_cma_helper.h>
> -#include <drm/drm_gem_cma_helper.h>
> -#include <drm/drm_of.h>
> -#include <drm/drm_panel.h>
> -#include <drm/drm_plane_helper.h>
> -#include <drm/drm_probe_helper.h>
> -#include <drm/drm_simple_kms_helper.h>
> -
> -#include "mxsfb_drv.h"
> -
> -static struct mxsfb_drm_private *
> -drm_connector_to_mxsfb_drm_private(struct drm_connector *connector)
> -{
> -	return container_of(connector, struct mxsfb_drm_private,
> -			    panel_connector);
> -}
> -
> -static int mxsfb_panel_get_modes(struct drm_connector *connector)
> -{
> -	struct mxsfb_drm_private *mxsfb =
> -			drm_connector_to_mxsfb_drm_private(connector);
> -
> -	if (mxsfb->panel)
> -		return drm_panel_get_modes(mxsfb->panel, connector);
> -
> -	return 0;
> -}
> -
> -static const struct
> -drm_connector_helper_funcs mxsfb_panel_connector_helper_funcs = {
> -	.get_modes = mxsfb_panel_get_modes,
> -};
> -
> -static enum drm_connector_status
> -mxsfb_panel_connector_detect(struct drm_connector *connector, bool force)
> -{
> -	struct mxsfb_drm_private *mxsfb =
> -			drm_connector_to_mxsfb_drm_private(connector);
> -
> -	if (mxsfb->panel)
> -		return connector_status_connected;
> -
> -	return connector_status_disconnected;
> -}
> -
> -static void mxsfb_panel_connector_destroy(struct drm_connector *connector)
> -{
> -	struct mxsfb_drm_private *mxsfb =
> -			drm_connector_to_mxsfb_drm_private(connector);
> -
> -	if (mxsfb->panel)
> -		drm_panel_detach(mxsfb->panel);
> -
> -	drm_connector_unregister(connector);
> -	drm_connector_cleanup(connector);
> -}
> -
> -static const struct drm_connector_funcs mxsfb_panel_connector_funcs = {
> -	.detect			= mxsfb_panel_connector_detect,
> -	.fill_modes		= drm_helper_probe_single_connector_modes,
> -	.destroy		= mxsfb_panel_connector_destroy,
> -	.reset			= drm_atomic_helper_connector_reset,
> -	.atomic_duplicate_state	= drm_atomic_helper_connector_duplicate_state,
> -	.atomic_destroy_state	= drm_atomic_helper_connector_destroy_state,
> -};
> -
> -int mxsfb_create_output(struct drm_device *drm)
> -{
> -	struct mxsfb_drm_private *mxsfb = drm->dev_private;
> -	int ret;
> -
> -	ret = drm_of_find_panel_or_bridge(drm->dev->of_node, 0, 0,
> -					  &mxsfb->panel, &mxsfb->bridge);
> -	if (ret)
> -		return ret;
> -
> -	if (mxsfb->panel) {
> -		mxsfb->connector = &mxsfb->panel_connector;
> -		mxsfb->connector->dpms = DRM_MODE_DPMS_OFF;
> -		mxsfb->connector->polled = 0;
> -		drm_connector_helper_add(mxsfb->connector,
> -					 &mxsfb_panel_connector_helper_funcs);
> -		ret = drm_connector_init(drm, mxsfb->connector,
> -					 &mxsfb_panel_connector_funcs,
> -					 DRM_MODE_CONNECTOR_Unknown);
> -	}
> -
> -	return ret;
> -}
_______________________________________________
dri-devel mailing list
dri-devel@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/dri-devel

^ permalink raw reply	[flat|nested] 62+ messages in thread

* Re: [PATCH 03/21] drm: mxsfb: Use BIT() macro to define register bitfields
  2020-03-09 19:51 ` [PATCH 03/21] drm: mxsfb: Use BIT() macro to define register bitfields Laurent Pinchart
@ 2020-03-23 21:34   ` Stefan Agner
  0 siblings, 0 replies; 62+ messages in thread
From: Stefan Agner @ 2020-03-23 21:34 UTC (permalink / raw)
  To: Laurent Pinchart; +Cc: Marek Vasut, kernel, dri-devel, linux-imx

On 2020-03-09 20:51, Laurent Pinchart wrote:
> Using BIT() is preferred over manual shifts as it's more readable,
> handles the 1 << 31 case properly, and avoids other mistakes as shown by
> the DEBUG0_HSYNC and DEBUG0_VSYNC bits (that are currently unused). Use
> it.
> 
> Signed-off-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>

Reviewed-by: Stefan Agner <stefan@agner.ch>

> ---
>  drivers/gpu/drm/mxsfb/mxsfb_regs.h | 56 +++++++++++++++---------------
>  1 file changed, 28 insertions(+), 28 deletions(-)
> 
> diff --git a/drivers/gpu/drm/mxsfb/mxsfb_regs.h
> b/drivers/gpu/drm/mxsfb/mxsfb_regs.h
> index 932d7ea08fd5..713d8f830135 100644
> --- a/drivers/gpu/drm/mxsfb/mxsfb_regs.h
> +++ b/drivers/gpu/drm/mxsfb/mxsfb_regs.h
> @@ -28,51 +28,51 @@
>  #define LCDC_V4_DEBUG0			0x1d0
>  #define LCDC_V3_DEBUG0			0x1f0
>  
> -#define CTRL_SFTRST			(1 << 31)
> -#define CTRL_CLKGATE			(1 << 30)
> -#define CTRL_BYPASS_COUNT		(1 << 19)
> -#define CTRL_VSYNC_MODE			(1 << 18)
> -#define CTRL_DOTCLK_MODE		(1 << 17)
> -#define CTRL_DATA_SELECT		(1 << 16)
> +#define CTRL_SFTRST			BIT(31)
> +#define CTRL_CLKGATE			BIT(30)
> +#define CTRL_BYPASS_COUNT		BIT(19)
> +#define CTRL_VSYNC_MODE			BIT(18)
> +#define CTRL_DOTCLK_MODE		BIT(17)
> +#define CTRL_DATA_SELECT		BIT(16)
>  #define CTRL_SET_BUS_WIDTH(x)		(((x) & 0x3) << 10)
>  #define CTRL_GET_BUS_WIDTH(x)		(((x) >> 10) & 0x3)
>  #define CTRL_BUS_WIDTH_MASK		(0x3 << 10)
>  #define CTRL_SET_WORD_LENGTH(x)		(((x) & 0x3) << 8)
>  #define CTRL_GET_WORD_LENGTH(x)		(((x) >> 8) & 0x3)
> -#define CTRL_MASTER			(1 << 5)
> -#define CTRL_DF16			(1 << 3)
> -#define CTRL_DF18			(1 << 2)
> -#define CTRL_DF24			(1 << 1)
> -#define CTRL_RUN			(1 << 0)
> +#define CTRL_MASTER			BIT(5)
> +#define CTRL_DF16			BIT(3)
> +#define CTRL_DF18			BIT(2)
> +#define CTRL_DF24			BIT(1)
> +#define CTRL_RUN			BIT(0)
>  
> -#define CTRL1_FIFO_CLEAR		(1 << 21)
> +#define CTRL1_FIFO_CLEAR		BIT(21)
>  #define CTRL1_SET_BYTE_PACKAGING(x)	(((x) & 0xf) << 16)
>  #define CTRL1_GET_BYTE_PACKAGING(x)	(((x) >> 16) & 0xf)
> -#define CTRL1_CUR_FRAME_DONE_IRQ_EN	(1 << 13)
> -#define CTRL1_CUR_FRAME_DONE_IRQ	(1 << 9)
> +#define CTRL1_CUR_FRAME_DONE_IRQ_EN	BIT(13)
> +#define CTRL1_CUR_FRAME_DONE_IRQ	BIT(9)
>  
>  #define TRANSFER_COUNT_SET_VCOUNT(x)	(((x) & 0xffff) << 16)
>  #define TRANSFER_COUNT_GET_VCOUNT(x)	(((x) >> 16) & 0xffff)
>  #define TRANSFER_COUNT_SET_HCOUNT(x)	((x) & 0xffff)
>  #define TRANSFER_COUNT_GET_HCOUNT(x)	((x) & 0xffff)
>  
> -#define VDCTRL0_ENABLE_PRESENT		(1 << 28)
> -#define VDCTRL0_VSYNC_ACT_HIGH		(1 << 27)
> -#define VDCTRL0_HSYNC_ACT_HIGH		(1 << 26)
> -#define VDCTRL0_DOTCLK_ACT_FALLING	(1 << 25)
> -#define VDCTRL0_ENABLE_ACT_HIGH		(1 << 24)
> -#define VDCTRL0_VSYNC_PERIOD_UNIT	(1 << 21)
> -#define VDCTRL0_VSYNC_PULSE_WIDTH_UNIT	(1 << 20)
> -#define VDCTRL0_HALF_LINE		(1 << 19)
> -#define VDCTRL0_HALF_LINE_MODE		(1 << 18)
> +#define VDCTRL0_ENABLE_PRESENT		BIT(28)
> +#define VDCTRL0_VSYNC_ACT_HIGH		BIT(27)
> +#define VDCTRL0_HSYNC_ACT_HIGH		BIT(26)
> +#define VDCTRL0_DOTCLK_ACT_FALLING	BIT(25)
> +#define VDCTRL0_ENABLE_ACT_HIGH		BIT(24)
> +#define VDCTRL0_VSYNC_PERIOD_UNIT	BIT(21)
> +#define VDCTRL0_VSYNC_PULSE_WIDTH_UNIT	BIT(20)
> +#define VDCTRL0_HALF_LINE		BIT(19)
> +#define VDCTRL0_HALF_LINE_MODE		BIT(18)
>  #define VDCTRL0_SET_VSYNC_PULSE_WIDTH(x) ((x) & 0x3ffff)
>  #define VDCTRL0_GET_VSYNC_PULSE_WIDTH(x) ((x) & 0x3ffff)
>  
>  #define VDCTRL2_SET_HSYNC_PERIOD(x)	((x) & 0x3ffff)
>  #define VDCTRL2_GET_HSYNC_PERIOD(x)	((x) & 0x3ffff)
>  
> -#define VDCTRL3_MUX_SYNC_SIGNALS	(1 << 29)
> -#define VDCTRL3_VSYNC_ONLY		(1 << 28)
> +#define VDCTRL3_MUX_SYNC_SIGNALS	BIT(29)
> +#define VDCTRL3_VSYNC_ONLY		BIT(28)
>  #define SET_HOR_WAIT_CNT(x)		(((x) & 0xfff) << 16)
>  #define GET_HOR_WAIT_CNT(x)		(((x) >> 16) & 0xfff)
>  #define SET_VERT_WAIT_CNT(x)		((x) & 0xffff)
> @@ -80,11 +80,11 @@
>  
>  #define VDCTRL4_SET_DOTCLK_DLY(x)	(((x) & 0x7) << 29) /* v4 only */
>  #define VDCTRL4_GET_DOTCLK_DLY(x)	(((x) >> 29) & 0x7) /* v4 only */
> -#define VDCTRL4_SYNC_SIGNALS_ON		(1 << 18)
> +#define VDCTRL4_SYNC_SIGNALS_ON		BIT(18)
>  #define SET_DOTCLK_H_VALID_DATA_CNT(x)	((x) & 0x3ffff)
>  
> -#define DEBUG0_HSYNC			(1 < 26)
> -#define DEBUG0_VSYNC			(1 < 25)
> +#define DEBUG0_HSYNC			BIT(26)
> +#define DEBUG0_VSYNC			BIT(25)
>  
>  #define MXSFB_MIN_XRES			120
>  #define MXSFB_MIN_YRES			120
_______________________________________________
dri-devel mailing list
dri-devel@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/dri-devel

^ permalink raw reply	[flat|nested] 62+ messages in thread

* Re: [PATCH 04/21] drm: mxsfb: Remove unused macros from mxsfb_regs.h
  2020-03-09 19:51 ` [PATCH 04/21] drm: mxsfb: Remove unused macros from mxsfb_regs.h Laurent Pinchart
@ 2020-03-23 21:36   ` Stefan Agner
  0 siblings, 0 replies; 62+ messages in thread
From: Stefan Agner @ 2020-03-23 21:36 UTC (permalink / raw)
  To: Laurent Pinchart; +Cc: Marek Vasut, kernel, dri-devel, linux-imx

On 2020-03-09 20:51, Laurent Pinchart wrote:
> mxsfb_regs.h defines macros related to register bits. Some of them are
> not used and don't clearly map to any particular register, so their
> purpose isn't known. Remove them.
> 
> Signed-off-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>

Reviewed-by: Stefan Agner <stefan@agner.ch>

> ---
>  drivers/gpu/drm/mxsfb/mxsfb_regs.h | 8 --------
>  1 file changed, 8 deletions(-)
> 
> diff --git a/drivers/gpu/drm/mxsfb/mxsfb_regs.h
> b/drivers/gpu/drm/mxsfb/mxsfb_regs.h
> index 713d8f830135..78e6cb754712 100644
> --- a/drivers/gpu/drm/mxsfb/mxsfb_regs.h
> +++ b/drivers/gpu/drm/mxsfb/mxsfb_regs.h
> @@ -91,17 +91,9 @@
>  #define MXSFB_MAX_XRES			0xffff
>  #define MXSFB_MAX_YRES			0xffff
>  
> -#define RED 0
> -#define GREEN 1
> -#define BLUE 2
> -#define TRANSP 3
> -
>  #define STMLCDIF_8BIT  1 /* pixel data bus to the display is of 8 bit width */
>  #define STMLCDIF_16BIT 0 /* pixel data bus to the display is of 16 bit width */
>  #define STMLCDIF_18BIT 2 /* pixel data bus to the display is of 18 bit width */
>  #define STMLCDIF_24BIT 3 /* pixel data bus to the display is of 24 bit width */
>  
> -#define MXSFB_SYNC_DATA_ENABLE_HIGH_ACT	(1 << 6)
> -#define MXSFB_SYNC_DOTCLK_FALLING_ACT	(1 << 7) /* negative edge sampling */
> -
>  #endif /* __MXSFB_REGS_H__ */
_______________________________________________
dri-devel mailing list
dri-devel@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/dri-devel

^ permalink raw reply	[flat|nested] 62+ messages in thread

* Re: [PATCH 02/21] drm: mxsfb: Use drm_panel_bridge
  2020-03-23 21:27   ` Stefan Agner
@ 2020-03-23 21:38     ` Sam Ravnborg
  2020-03-23 23:50       ` Stefan Agner
  2020-05-30  2:14     ` Laurent Pinchart
  1 sibling, 1 reply; 62+ messages in thread
From: Sam Ravnborg @ 2020-03-23 21:38 UTC (permalink / raw)
  To: Stefan Agner; +Cc: Marek Vasut, dri-devel, Laurent Pinchart, kernel, linux-imx

Hi Stefan.

On Mon, Mar 23, 2020 at 10:27:21PM +0100, Stefan Agner wrote:
> On 2020-03-09 20:51, Laurent Pinchart wrote:
> > Replace the manual connector implementation based on drm_panel with the
> > drm_panel_bridge helper. This simplifies the mxsfb driver by removing
> > connector-related code, and standardizing all pipeline control
> > operations on bridges.
> > 
> > A hack is needed to get hold of the connector, as that's our only source
> > of bus flags and formats for now. As soon as the bridge API provides us
> > with that information this can be fixed.
> 
> This seems like a nice simplification.
> 
> I gave this a go applied on today's drm-misc-next using a Colibri iMX7
> (imx7d-colibri-emmc-eval-v3.dts device tree). This device makes use of
> the simple panel driver. I get this when booting:
> 
> [    2.976698] [drm] Supports vblank timestamp caching Rev 2
> (21.10.2013).
> [    2.983526] ------------[ cut here ]------------
> [    2.988180] WARNING: CPU: 0 PID: 1 at
> drivers/gpu/drm/bridge/panel.c:267 devm_drm_panel_bridge_add+0x25/0x28

...

I think you hit one of the panels that does not yet specify a
connector_type.

If this is the case, we should fix the definition in panel-simple.

	Sam
_______________________________________________
dri-devel mailing list
dri-devel@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/dri-devel

^ permalink raw reply	[flat|nested] 62+ messages in thread

* Re: [PATCH 05/21] drm: mxsfb: Clarify format and bus width configuration
  2020-03-09 19:52 ` [PATCH 05/21] drm: mxsfb: Clarify format and bus width configuration Laurent Pinchart
@ 2020-03-23 21:42   ` Stefan Agner
  0 siblings, 0 replies; 62+ messages in thread
From: Stefan Agner @ 2020-03-23 21:42 UTC (permalink / raw)
  To: Laurent Pinchart; +Cc: Marek Vasut, kernel, dri-devel, linux-imx

On 2020-03-09 20:52, Laurent Pinchart wrote:
> Replace the convoluted way to set the format and bus width through
> difficult to read macros with more explicit ones. Also remove the
> outdated comment related to the limitations on bus width setting as it

Nice catch.

> doesn't apply anymore (the bus width can be specified through the
> display_info bus format).

Reviewed-by: Stefan Agner <stefan@agner.ch>

> 
> Signed-off-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
> ---
>  drivers/gpu/drm/mxsfb/mxsfb_crtc.c | 17 +++++------------
>  drivers/gpu/drm/mxsfb/mxsfb_regs.h | 17 ++++++++---------
>  2 files changed, 13 insertions(+), 21 deletions(-)
> 
> diff --git a/drivers/gpu/drm/mxsfb/mxsfb_crtc.c
> b/drivers/gpu/drm/mxsfb/mxsfb_crtc.c
> index b69ace8bf526..8b6339316929 100644
> --- a/drivers/gpu/drm/mxsfb/mxsfb_crtc.c
> +++ b/drivers/gpu/drm/mxsfb/mxsfb_crtc.c
> @@ -52,13 +52,6 @@ static int mxsfb_set_pixel_fmt(struct
> mxsfb_drm_private *mxsfb)
>  
>  	ctrl = CTRL_BYPASS_COUNT | CTRL_MASTER;
>  
> -	/*
> -	 * WARNING: The bus width, CTRL_SET_BUS_WIDTH(), is configured to
> -	 * match the selected mode here. This differs from the original
> -	 * MXSFB driver, which had the option to configure the bus width
> -	 * to arbitrary value. This limitation should not pose an issue.
> -	 */
> -
>  	/* CTRL1 contains IRQ config and status bits, preserve those. */
>  	ctrl1 = readl(mxsfb->base + LCDC_CTRL1);
>  	ctrl1 &= CTRL1_CUR_FRAME_DONE_IRQ_EN | CTRL1_CUR_FRAME_DONE_IRQ;
> @@ -66,12 +59,12 @@ static int mxsfb_set_pixel_fmt(struct
> mxsfb_drm_private *mxsfb)
>  	switch (format) {
>  	case DRM_FORMAT_RGB565:
>  		dev_dbg(drm->dev, "Setting up RGB565 mode\n");
> -		ctrl |= CTRL_SET_WORD_LENGTH(0);
> +		ctrl |= CTRL_WORD_LENGTH_16;
>  		ctrl1 |= CTRL1_SET_BYTE_PACKAGING(0xf);
>  		break;
>  	case DRM_FORMAT_XRGB8888:
>  		dev_dbg(drm->dev, "Setting up XRGB8888 mode\n");
> -		ctrl |= CTRL_SET_WORD_LENGTH(3);
> +		ctrl |= CTRL_WORD_LENGTH_24;
>  		/* Do not use packed pixels = one pixel per word instead. */
>  		ctrl1 |= CTRL1_SET_BYTE_PACKAGING(0x7);
>  		break;
> @@ -104,13 +97,13 @@ static void mxsfb_set_bus_fmt(struct
> mxsfb_drm_private *mxsfb)
>  	reg &= ~CTRL_BUS_WIDTH_MASK;
>  	switch (bus_format) {
>  	case MEDIA_BUS_FMT_RGB565_1X16:
> -		reg |= CTRL_SET_BUS_WIDTH(STMLCDIF_16BIT);
> +		reg |= CTRL_BUS_WIDTH_16;
>  		break;
>  	case MEDIA_BUS_FMT_RGB666_1X18:
> -		reg |= CTRL_SET_BUS_WIDTH(STMLCDIF_18BIT);
> +		reg |= CTRL_BUS_WIDTH_18;
>  		break;
>  	case MEDIA_BUS_FMT_RGB888_1X24:
> -		reg |= CTRL_SET_BUS_WIDTH(STMLCDIF_24BIT);
> +		reg |= CTRL_BUS_WIDTH_24;
>  		break;
>  	default:
>  		dev_err(drm->dev, "Unknown media bus format %d\n", bus_format);
> diff --git a/drivers/gpu/drm/mxsfb/mxsfb_regs.h
> b/drivers/gpu/drm/mxsfb/mxsfb_regs.h
> index 78e6cb754712..8ebb52bb1b46 100644
> --- a/drivers/gpu/drm/mxsfb/mxsfb_regs.h
> +++ b/drivers/gpu/drm/mxsfb/mxsfb_regs.h
> @@ -34,11 +34,15 @@
>  #define CTRL_VSYNC_MODE			BIT(18)
>  #define CTRL_DOTCLK_MODE		BIT(17)
>  #define CTRL_DATA_SELECT		BIT(16)
> -#define CTRL_SET_BUS_WIDTH(x)		(((x) & 0x3) << 10)
> -#define CTRL_GET_BUS_WIDTH(x)		(((x) >> 10) & 0x3)
> +#define CTRL_BUS_WIDTH_16		(0 << 10)
> +#define CTRL_BUS_WIDTH_8		(1 << 10)
> +#define CTRL_BUS_WIDTH_18		(2 << 10)
> +#define CTRL_BUS_WIDTH_24		(3 << 10)
>  #define CTRL_BUS_WIDTH_MASK		(0x3 << 10)
> -#define CTRL_SET_WORD_LENGTH(x)		(((x) & 0x3) << 8)
> -#define CTRL_GET_WORD_LENGTH(x)		(((x) >> 8) & 0x3)
> +#define CTRL_WORD_LENGTH_16		(0 << 8)
> +#define CTRL_WORD_LENGTH_8		(1 << 8)
> +#define CTRL_WORD_LENGTH_18		(2 << 8)
> +#define CTRL_WORD_LENGTH_24		(3 << 8)
>  #define CTRL_MASTER			BIT(5)
>  #define CTRL_DF16			BIT(3)
>  #define CTRL_DF18			BIT(2)
> @@ -91,9 +95,4 @@
>  #define MXSFB_MAX_XRES			0xffff
>  #define MXSFB_MAX_YRES			0xffff
>  
> -#define STMLCDIF_8BIT  1 /* pixel data bus to the display is of 8 bit width */
> -#define STMLCDIF_16BIT 0 /* pixel data bus to the display is of 16 bit width */
> -#define STMLCDIF_18BIT 2 /* pixel data bus to the display is of 18 bit width */
> -#define STMLCDIF_24BIT 3 /* pixel data bus to the display is of 24 bit width */
> -
>  #endif /* __MXSFB_REGS_H__ */
_______________________________________________
dri-devel mailing list
dri-devel@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/dri-devel

^ permalink raw reply	[flat|nested] 62+ messages in thread

* Re: [PATCH 06/21] drm: mxsfb: Pass mxsfb_drm_private pointer to mxsfb_reset_block()
  2020-03-09 19:52 ` [PATCH 06/21] drm: mxsfb: Pass mxsfb_drm_private pointer to mxsfb_reset_block() Laurent Pinchart
@ 2020-03-23 21:43   ` Stefan Agner
  0 siblings, 0 replies; 62+ messages in thread
From: Stefan Agner @ 2020-03-23 21:43 UTC (permalink / raw)
  To: Laurent Pinchart; +Cc: Marek Vasut, kernel, dri-devel, linux-imx

On 2020-03-09 20:52, Laurent Pinchart wrote:
> The mxsfb_reset_block() function isn't special, pass it the
> mxsfb_drm_private pointer instead of a pointer to the base address.
> 
> Signed-off-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>

Reviewed-by: Stefan Agner <stefan@agner.ch>

> ---
>  drivers/gpu/drm/mxsfb/mxsfb_crtc.c | 12 ++++++------
>  1 file changed, 6 insertions(+), 6 deletions(-)
> 
> diff --git a/drivers/gpu/drm/mxsfb/mxsfb_crtc.c
> b/drivers/gpu/drm/mxsfb/mxsfb_crtc.c
> index 8b6339316929..be60c4021e2f 100644
> --- a/drivers/gpu/drm/mxsfb/mxsfb_crtc.c
> +++ b/drivers/gpu/drm/mxsfb/mxsfb_crtc.c
> @@ -166,21 +166,21 @@ static int clear_poll_bit(void __iomem *addr, u32 mask)
>  	return readl_poll_timeout(addr, reg, !(reg & mask), 0, RESET_TIMEOUT);
>  }
>  
> -static int mxsfb_reset_block(void __iomem *reset_addr)
> +static int mxsfb_reset_block(struct mxsfb_drm_private *mxsfb)
>  {
>  	int ret;
>  
> -	ret = clear_poll_bit(reset_addr, MODULE_SFTRST);
> +	ret = clear_poll_bit(mxsfb->base, MODULE_SFTRST);
>  	if (ret)
>  		return ret;
>  
> -	writel(MODULE_CLKGATE, reset_addr + MXS_CLR_ADDR);
> +	writel(MODULE_CLKGATE, mxsfb->base + MXS_CLR_ADDR);
>  
> -	ret = clear_poll_bit(reset_addr, MODULE_SFTRST);
> +	ret = clear_poll_bit(mxsfb->base, MODULE_SFTRST);
>  	if (ret)
>  		return ret;
>  
> -	return clear_poll_bit(reset_addr, MODULE_CLKGATE);
> +	return clear_poll_bit(mxsfb->base, MODULE_CLKGATE);
>  }
>  
>  static dma_addr_t mxsfb_get_fb_paddr(struct mxsfb_drm_private *mxsfb)
> @@ -213,7 +213,7 @@ static void mxsfb_crtc_mode_set_nofb(struct
> mxsfb_drm_private *mxsfb)
>  	 */
>  
>  	/* Mandatory eLCDIF reset as per the Reference Manual */
> -	err = mxsfb_reset_block(mxsfb->base);
> +	err = mxsfb_reset_block(mxsfb);
>  	if (err)
>  		return;
_______________________________________________
dri-devel mailing list
dri-devel@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/dri-devel

^ permalink raw reply	[flat|nested] 62+ messages in thread

* Re: [PATCH 07/21] drm: mxsfb: Use LCDC_CTRL register name explicitly
  2020-03-09 19:52 ` [PATCH 07/21] drm: mxsfb: Use LCDC_CTRL register name explicitly Laurent Pinchart
@ 2020-03-23 21:48   ` Stefan Agner
  0 siblings, 0 replies; 62+ messages in thread
From: Stefan Agner @ 2020-03-23 21:48 UTC (permalink / raw)
  To: Laurent Pinchart; +Cc: Marek Vasut, kernel, dri-devel, linux-imx

On 2020-03-09 20:52, Laurent Pinchart wrote:
> The LCDC_CTRL register is located at address 0x0000. Some of the
> accesses to the register simply use the mxsfb->base address. Reference
> the LCDC_CTRL register explicitly instead to clarify the code.
> 
> Signed-off-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>

Reviewed-by: Stefan Agner <stefan@agner.ch>

> ---
>  drivers/gpu/drm/mxsfb/mxsfb_crtc.c | 8 ++++----
>  1 file changed, 4 insertions(+), 4 deletions(-)
> 
> diff --git a/drivers/gpu/drm/mxsfb/mxsfb_crtc.c
> b/drivers/gpu/drm/mxsfb/mxsfb_crtc.c
> index be60c4021e2f..722bd9b4f5f9 100644
> --- a/drivers/gpu/drm/mxsfb/mxsfb_crtc.c
> +++ b/drivers/gpu/drm/mxsfb/mxsfb_crtc.c
> @@ -170,17 +170,17 @@ static int mxsfb_reset_block(struct
> mxsfb_drm_private *mxsfb)
>  {
>  	int ret;
>  
> -	ret = clear_poll_bit(mxsfb->base, MODULE_SFTRST);
> +	ret = clear_poll_bit(mxsfb->base + LCDC_CTRL, MODULE_SFTRST);
>  	if (ret)
>  		return ret;
>  
> -	writel(MODULE_CLKGATE, mxsfb->base + MXS_CLR_ADDR);
> +	writel(MODULE_CLKGATE, mxsfb->base + LCDC_CTRL + MXS_CLR_ADDR);
>  
> -	ret = clear_poll_bit(mxsfb->base, MODULE_SFTRST);
> +	ret = clear_poll_bit(mxsfb->base + LCDC_CTRL, MODULE_SFTRST);
>  	if (ret)
>  		return ret;
>  
> -	return clear_poll_bit(mxsfb->base, MODULE_CLKGATE);
> +	return clear_poll_bit(mxsfb->base + LCDC_CTRL, MODULE_CLKGATE);
>  }
>  
>  static dma_addr_t mxsfb_get_fb_paddr(struct mxsfb_drm_private *mxsfb)
_______________________________________________
dri-devel mailing list
dri-devel@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/dri-devel

^ permalink raw reply	[flat|nested] 62+ messages in thread

* Re: [PATCH 08/21] drm: mxsfb: Remove register definitions from mxsfb_crtc.c
  2020-03-09 19:52 ` [PATCH 08/21] drm: mxsfb: Remove register definitions from mxsfb_crtc.c Laurent Pinchart
@ 2020-03-23 21:49   ` Stefan Agner
  0 siblings, 0 replies; 62+ messages in thread
From: Stefan Agner @ 2020-03-23 21:49 UTC (permalink / raw)
  To: Laurent Pinchart; +Cc: Marek Vasut, kernel, dri-devel, linux-imx

On 2020-03-09 20:52, Laurent Pinchart wrote:
> mxsfb_crtc.c defines several macros related to register addresses and
> bit, which duplicates macros from mxsfb_regs.h. Use the macros from
> mxsfb_regs.h instead and remove them.
> 
> Signed-off-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>

Reviewed-by: Stefan Agner <stefan@agner.ch>

> ---
>  drivers/gpu/drm/mxsfb/mxsfb_crtc.c | 14 +++++---------
>  1 file changed, 5 insertions(+), 9 deletions(-)
> 
> diff --git a/drivers/gpu/drm/mxsfb/mxsfb_crtc.c
> b/drivers/gpu/drm/mxsfb/mxsfb_crtc.c
> index 722bd9b4f5f9..aef72adabf41 100644
> --- a/drivers/gpu/drm/mxsfb/mxsfb_crtc.c
> +++ b/drivers/gpu/drm/mxsfb/mxsfb_crtc.c
> @@ -29,10 +29,6 @@
>  #include "mxsfb_drv.h"
>  #include "mxsfb_regs.h"
>  
> -#define MXS_SET_ADDR		0x4
> -#define MXS_CLR_ADDR		0x8
> -#define MODULE_CLKGATE		BIT(30)
> -#define MODULE_SFTRST		BIT(31)
>  /* 1 second delay should be plenty of time for block reset */
>  #define RESET_TIMEOUT		1000000
>  
> @@ -162,7 +158,7 @@ static int clear_poll_bit(void __iomem *addr, u32 mask)
>  {
>  	u32 reg;
>  
> -	writel(mask, addr + MXS_CLR_ADDR);
> +	writel(mask, addr + REG_CLR);
>  	return readl_poll_timeout(addr, reg, !(reg & mask), 0, RESET_TIMEOUT);
>  }
>  
> @@ -170,17 +166,17 @@ static int mxsfb_reset_block(struct
> mxsfb_drm_private *mxsfb)
>  {
>  	int ret;
>  
> -	ret = clear_poll_bit(mxsfb->base + LCDC_CTRL, MODULE_SFTRST);
> +	ret = clear_poll_bit(mxsfb->base + LCDC_CTRL, CTRL_SFTRST);
>  	if (ret)
>  		return ret;
>  
> -	writel(MODULE_CLKGATE, mxsfb->base + LCDC_CTRL + MXS_CLR_ADDR);
> +	writel(CTRL_CLKGATE, mxsfb->base + LCDC_CTRL + REG_CLR);
>  
> -	ret = clear_poll_bit(mxsfb->base + LCDC_CTRL, MODULE_SFTRST);
> +	ret = clear_poll_bit(mxsfb->base + LCDC_CTRL, CTRL_SFTRST);
>  	if (ret)
>  		return ret;
>  
> -	return clear_poll_bit(mxsfb->base + LCDC_CTRL, MODULE_CLKGATE);
> +	return clear_poll_bit(mxsfb->base + LCDC_CTRL, CTRL_CLKGATE);
>  }
>  
>  static dma_addr_t mxsfb_get_fb_paddr(struct mxsfb_drm_private *mxsfb)
_______________________________________________
dri-devel mailing list
dri-devel@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/dri-devel

^ permalink raw reply	[flat|nested] 62+ messages in thread

* Re: [PATCH 09/21] drm: mxsfb: Remove unneeded includes
  2020-03-09 19:52 ` [PATCH 09/21] drm: mxsfb: Remove unneeded includes Laurent Pinchart
@ 2020-03-23 21:53   ` Stefan Agner
  2020-05-30  0:33     ` Laurent Pinchart
  0 siblings, 1 reply; 62+ messages in thread
From: Stefan Agner @ 2020-03-23 21:53 UTC (permalink / raw)
  To: Laurent Pinchart; +Cc: Marek Vasut, kernel, dri-devel, linux-imx

On 2020-03-09 20:52, Laurent Pinchart wrote:
> A fair number of includes are not needed. Drop them, and add a couple of
> required includes that were included indirectly.
> 
> Signed-off-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>

Out of curiosity, do you have some kind of tool helping with this?

Reviewed-by: Stefan Agner <stefan@agner.ch>

> ---
>  drivers/gpu/drm/mxsfb/mxsfb_crtc.c | 12 +++---------
>  drivers/gpu/drm/mxsfb/mxsfb_drv.c  |  5 -----
>  2 files changed, 3 insertions(+), 14 deletions(-)
> 
> diff --git a/drivers/gpu/drm/mxsfb/mxsfb_crtc.c
> b/drivers/gpu/drm/mxsfb/mxsfb_crtc.c
> index aef72adabf41..c4f1575b4210 100644
> --- a/drivers/gpu/drm/mxsfb/mxsfb_crtc.c
> +++ b/drivers/gpu/drm/mxsfb/mxsfb_crtc.c
> @@ -10,19 +10,13 @@
>  
>  #include <linux/clk.h>
>  #include <linux/iopoll.h>
> -#include <linux/of_graph.h>
> -#include <linux/platform_data/simplefb.h>
> +#include <linux/spinlock.h>
>  
> -#include <video/videomode.h>
> -
> -#include <drm/drm_atomic_helper.h>
> +#include <drm/drm_bridge.h>
>  #include <drm/drm_crtc.h>
>  #include <drm/drm_fb_cma_helper.h>
> -#include <drm/drm_fb_helper.h>
> +#include <drm/drm_fourcc.h>
>  #include <drm/drm_gem_cma_helper.h>
> -#include <drm/drm_of.h>
> -#include <drm/drm_plane_helper.h>
> -#include <drm/drm_probe_helper.h>
>  #include <drm/drm_simple_kms_helper.h>
>  #include <drm/drm_vblank.h>
>  
> diff --git a/drivers/gpu/drm/mxsfb/mxsfb_drv.c
> b/drivers/gpu/drm/mxsfb/mxsfb_drv.c
> index cffc70257bd3..204c1e52e9aa 100644
> --- a/drivers/gpu/drm/mxsfb/mxsfb_drv.c
> +++ b/drivers/gpu/drm/mxsfb/mxsfb_drv.c
> @@ -9,15 +9,10 @@
>   */
>  
>  #include <linux/clk.h>
> -#include <linux/component.h>
>  #include <linux/dma-mapping.h>
> -#include <linux/list.h>
>  #include <linux/module.h>
>  #include <linux/of_device.h>
> -#include <linux/of_graph.h>
> -#include <linux/of_reserved_mem.h>
>  #include <linux/pm_runtime.h>
> -#include <linux/dma-resv.h>
>  #include <linux/spinlock.h>
>  
>  #include <drm/drm_atomic.h>
_______________________________________________
dri-devel mailing list
dri-devel@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/dri-devel

^ permalink raw reply	[flat|nested] 62+ messages in thread

* Re: [PATCH 10/21] drm: mxsfb: Stop using DRM simple display pipeline helper
  2020-03-09 19:52 ` [PATCH 10/21] drm: mxsfb: Stop using DRM simple display pipeline helper Laurent Pinchart
@ 2020-03-23 22:30   ` Stefan Agner
  0 siblings, 0 replies; 62+ messages in thread
From: Stefan Agner @ 2020-03-23 22:30 UTC (permalink / raw)
  To: Laurent Pinchart; +Cc: Marek Vasut, kernel, dri-devel, linux-imx

On 2020-03-09 20:52, Laurent Pinchart wrote:
> The DRM simple display pipeline helper only supports a single plane. In
> order to prepare for support of the alpha plane on i.MX6SX and i.MX7,
> move away from the helper. No new feature is added.
> 
> Signed-off-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>

I actually would prefer if we order this patch a bit later, especially
after the mxsfb_crtc -> mxsfb_kms rename. It will make git log -p easier
later.

Looks quite straight forward otherwise. One small comment below.

> ---
>  drivers/gpu/drm/mxsfb/mxsfb_crtc.c | 184 ++++++++++++++++++++++++++---
>  drivers/gpu/drm/mxsfb/mxsfb_drv.c  | 108 ++---------------
>  drivers/gpu/drm/mxsfb/mxsfb_drv.h  |  23 ++--
>  3 files changed, 197 insertions(+), 118 deletions(-)
> 
> diff --git a/drivers/gpu/drm/mxsfb/mxsfb_crtc.c
> b/drivers/gpu/drm/mxsfb/mxsfb_crtc.c
> index c4f1575b4210..8f339adb8d04 100644
> --- a/drivers/gpu/drm/mxsfb/mxsfb_crtc.c
> +++ b/drivers/gpu/drm/mxsfb/mxsfb_crtc.c
> @@ -9,15 +9,21 @@
>   */
>  
>  #include <linux/clk.h>
> +#include <linux/io.h>
>  #include <linux/iopoll.h>
> +#include <linux/pm_runtime.h>
>  #include <linux/spinlock.h>
>  
> +#include <drm/drm_atomic.h>
> +#include <drm/drm_atomic_helper.h>
>  #include <drm/drm_bridge.h>
>  #include <drm/drm_crtc.h>
> +#include <drm/drm_encoder.h>
>  #include <drm/drm_fb_cma_helper.h>
>  #include <drm/drm_fourcc.h>
>  #include <drm/drm_gem_cma_helper.h>
> -#include <drm/drm_simple_kms_helper.h>
> +#include <drm/drm_plane.h>
> +#include <drm/drm_plane_helper.h>
>  #include <drm/drm_vblank.h>
>  
>  #include "mxsfb_drv.h"
> @@ -26,6 +32,10 @@
>  /* 1 second delay should be plenty of time for block reset */
>  #define RESET_TIMEOUT		1000000
>  
> +/*
> -----------------------------------------------------------------------------
> + * CRTC
> + */
> +
>  static u32 set_hsync_pulse_width(struct mxsfb_drm_private *mxsfb, u32 val)
>  {
>  	return (val & mxsfb->devdata->hs_wdth_mask) <<
> @@ -35,9 +45,8 @@ static u32 set_hsync_pulse_width(struct
> mxsfb_drm_private *mxsfb, u32 val)
>  /* Setup the MXSFB registers for decoding the pixels out of the framebuffer */
>  static int mxsfb_set_pixel_fmt(struct mxsfb_drm_private *mxsfb)
>  {
> -	struct drm_crtc *crtc = &mxsfb->pipe.crtc;
> -	struct drm_device *drm = crtc->dev;
> -	const u32 format = crtc->primary->state->fb->format->format;
> +	struct drm_device *drm = mxsfb->drm;
> +	const u32 format = mxsfb->crtc.primary->state->fb->format->format;
>  	u32 ctrl, ctrl1;
>  
>  	ctrl = CTRL_BYPASS_COUNT | CTRL_MASTER;
> @@ -71,8 +80,7 @@ static int mxsfb_set_pixel_fmt(struct
> mxsfb_drm_private *mxsfb)
>  
>  static void mxsfb_set_bus_fmt(struct mxsfb_drm_private *mxsfb)
>  {
> -	struct drm_crtc *crtc = &mxsfb->pipe.crtc;
> -	struct drm_device *drm = crtc->dev;
> +	struct drm_device *drm = mxsfb->drm;
>  	u32 bus_format = MEDIA_BUS_FMT_RGB888_1X24;
>  	u32 reg;
>  
> @@ -175,7 +183,7 @@ static int mxsfb_reset_block(struct
> mxsfb_drm_private *mxsfb)
>  
>  static dma_addr_t mxsfb_get_fb_paddr(struct mxsfb_drm_private *mxsfb)
>  {
> -	struct drm_framebuffer *fb = mxsfb->pipe.plane.state->fb;
> +	struct drm_framebuffer *fb = mxsfb->plane.state->fb;
>  	struct drm_gem_cma_object *gem;
>  
>  	if (!fb)
> @@ -190,8 +198,8 @@ static dma_addr_t mxsfb_get_fb_paddr(struct
> mxsfb_drm_private *mxsfb)
>  
>  static void mxsfb_crtc_mode_set_nofb(struct mxsfb_drm_private *mxsfb)
>  {
> -	struct drm_device *drm = mxsfb->pipe.crtc.dev;
> -	struct drm_display_mode *m = &mxsfb->pipe.crtc.state->adjusted_mode;
> +	struct drm_device *drm = mxsfb->crtc.dev;
> +	struct drm_display_mode *m = &mxsfb->crtc.state->adjusted_mode;
>  	u32 bus_flags = mxsfb->connector->display_info.bus_flags;
>  	u32 vdctrl0, vsync_pulse_len, hsync_pulse_len;
>  	int err;
> @@ -273,10 +281,29 @@ static void mxsfb_crtc_mode_set_nofb(struct
> mxsfb_drm_private *mxsfb)
>  	       mxsfb->base + LCDC_VDCTRL4);
>  }
>  
> -void mxsfb_crtc_enable(struct mxsfb_drm_private *mxsfb)
> +static int mxsfb_crtc_atomic_check(struct drm_crtc *crtc,
> +				   struct drm_crtc_state *state)
>  {
> +	bool has_primary = state->plane_mask &
> +			   drm_plane_mask(crtc->primary);
> +
> +	/* The primary plane has to be enabled when the CRTC is active. */
> +	if (has_primary != state->active)
> +		return -EINVAL;
> +
> +	/* TODO: Is this needed ? */

Did you come to a conclusion? I guess since drm_simple_kms_crtc_check()
is using it is the safe choice to keep it.

--
Stefan

> +	return drm_atomic_add_affected_planes(state->state, crtc);
> +}
> +
> +static void mxsfb_crtc_atomic_enable(struct drm_crtc *crtc,
> +				     struct drm_crtc_state *old_state)
> +{
> +	struct mxsfb_drm_private *mxsfb = to_mxsfb_drm_private(crtc->dev);
> +	struct drm_device *drm = mxsfb->drm;
>  	dma_addr_t paddr;
>  
> +	pm_runtime_get_sync(drm->dev);
> +
>  	mxsfb_enable_axi_clk(mxsfb);
>  	mxsfb_crtc_mode_set_nofb(mxsfb);
>  
> @@ -290,17 +317,100 @@ void mxsfb_crtc_enable(struct mxsfb_drm_private *mxsfb)
>  	mxsfb_enable_controller(mxsfb);
>  }
>  
> -void mxsfb_crtc_disable(struct mxsfb_drm_private *mxsfb)
> +static void mxsfb_crtc_atomic_disable(struct drm_crtc *crtc,
> +				      struct drm_crtc_state *old_state)
>  {
> +	struct mxsfb_drm_private *mxsfb = to_mxsfb_drm_private(crtc->dev);
> +	struct drm_device *drm = mxsfb->drm;
> +	struct drm_pending_vblank_event *event;
> +
>  	mxsfb_disable_controller(mxsfb);
>  	mxsfb_disable_axi_clk(mxsfb);
> +
> +	pm_runtime_put_sync(drm->dev);
> +
> +	spin_lock_irq(&drm->event_lock);
> +	event = crtc->state->event;
> +	if (event) {
> +		crtc->state->event = NULL;
> +		drm_crtc_send_vblank_event(crtc, event);
> +	}
> +	spin_unlock_irq(&drm->event_lock);
> +}
> +
> +static int mxsfb_crtc_enable_vblank(struct drm_crtc *crtc)
> +{
> +	struct mxsfb_drm_private *mxsfb = to_mxsfb_drm_private(crtc->dev);
> +
> +	/* Clear and enable VBLANK IRQ */
> +	mxsfb_enable_axi_clk(mxsfb);
> +	writel(CTRL1_CUR_FRAME_DONE_IRQ, mxsfb->base + LCDC_CTRL1 + REG_CLR);
> +	writel(CTRL1_CUR_FRAME_DONE_IRQ_EN, mxsfb->base + LCDC_CTRL1 + REG_SET);
> +	mxsfb_disable_axi_clk(mxsfb);
> +
> +	return 0;
> +}
> +
> +static void mxsfb_crtc_disable_vblank(struct drm_crtc *crtc)
> +{
> +	struct mxsfb_drm_private *mxsfb = to_mxsfb_drm_private(crtc->dev);
> +
> +	/* Disable and clear VBLANK IRQ */
> +	mxsfb_enable_axi_clk(mxsfb);
> +	writel(CTRL1_CUR_FRAME_DONE_IRQ_EN, mxsfb->base + LCDC_CTRL1 + REG_CLR);
> +	writel(CTRL1_CUR_FRAME_DONE_IRQ, mxsfb->base + LCDC_CTRL1 + REG_CLR);
> +	mxsfb_disable_axi_clk(mxsfb);
> +}
> +
> +static const struct drm_crtc_helper_funcs mxsfb_crtc_helper_funcs = {
> +	.atomic_check = mxsfb_crtc_atomic_check,
> +	.atomic_enable = mxsfb_crtc_atomic_enable,
> +	.atomic_disable = mxsfb_crtc_atomic_disable,
> +};
> +
> +static const struct drm_crtc_funcs mxsfb_crtc_funcs = {
> +	.reset = drm_atomic_helper_crtc_reset,
> +	.destroy = drm_crtc_cleanup,
> +	.set_config = drm_atomic_helper_set_config,
> +	.page_flip = drm_atomic_helper_page_flip,
> +	.atomic_duplicate_state = drm_atomic_helper_crtc_duplicate_state,
> +	.atomic_destroy_state = drm_atomic_helper_crtc_destroy_state,
> +	.enable_vblank = mxsfb_crtc_enable_vblank,
> +	.disable_vblank = mxsfb_crtc_disable_vblank,
> +};
> +
> +/*
> -----------------------------------------------------------------------------
> + * Encoder
> + */
> +
> +static const struct drm_encoder_funcs mxsfb_encoder_funcs = {
> +	.destroy = drm_encoder_cleanup,
> +};
> +
> +/*
> -----------------------------------------------------------------------------
> + * Planes
> + */
> +
> +static int mxsfb_plane_atomic_check(struct drm_plane *plane,
> +				    struct drm_plane_state *plane_state)
> +{
> +	struct mxsfb_drm_private *mxsfb = to_mxsfb_drm_private(plane->dev);
> +	struct drm_crtc_state *crtc_state;
> +
> +	crtc_state = drm_atomic_get_new_crtc_state(plane_state->state,
> +						   &mxsfb->crtc);
> +
> +	return drm_atomic_helper_check_plane_state(plane_state, crtc_state,
> +						   DRM_PLANE_HELPER_NO_SCALING,
> +						   DRM_PLANE_HELPER_NO_SCALING,
> +						   false, true);
>  }
>  
> -void mxsfb_plane_atomic_update(struct mxsfb_drm_private *mxsfb,
> -			       struct drm_plane_state *state)
> +static void mxsfb_plane_atomic_update(struct drm_plane *plane,
> +				      struct drm_plane_state *old_pstate)
>  {
> -	struct drm_simple_display_pipe *pipe = &mxsfb->pipe;
> -	struct drm_crtc *crtc = &pipe->crtc;
> +	struct mxsfb_drm_private *mxsfb = to_mxsfb_drm_private(plane->dev);
> +	struct drm_crtc *crtc = &mxsfb->crtc;
>  	struct drm_pending_vblank_event *event;
>  	dma_addr_t paddr;
>  
> @@ -324,3 +434,47 @@ void mxsfb_plane_atomic_update(struct
> mxsfb_drm_private *mxsfb,
>  		mxsfb_disable_axi_clk(mxsfb);
>  	}
>  }
> +
> +static const struct drm_plane_helper_funcs mxsfb_plane_helper_funcs = {
> +	.atomic_check = mxsfb_plane_atomic_check,
> +	.atomic_update = mxsfb_plane_atomic_update,
> +};
> +
> +static const struct drm_plane_funcs mxsfb_plane_funcs = {
> +	.update_plane		= drm_atomic_helper_update_plane,
> +	.disable_plane		= drm_atomic_helper_disable_plane,
> +	.destroy		= drm_plane_cleanup,
> +	.reset			= drm_atomic_helper_plane_reset,
> +	.atomic_duplicate_state	= drm_atomic_helper_plane_duplicate_state,
> +	.atomic_destroy_state	= drm_atomic_helper_plane_destroy_state,
> +};
> +
> +static const uint32_t mxsfb_formats[] = {
> +	DRM_FORMAT_XRGB8888,
> +	DRM_FORMAT_RGB565
> +};
> +
> +int mxsfb_kms_init(struct mxsfb_drm_private *mxsfb)
> +{
> +	struct drm_encoder *encoder = &mxsfb->encoder;
> +	struct drm_plane *plane = &mxsfb->plane;
> +	struct drm_crtc *crtc = &mxsfb->crtc;
> +	int ret;
> +
> +	drm_plane_helper_add(plane, &mxsfb_plane_helper_funcs);
> +	ret = drm_universal_plane_init(mxsfb->drm, plane, 0, &mxsfb_plane_funcs,
> +				       mxsfb_formats, ARRAY_SIZE(mxsfb_formats),
> +				       NULL, DRM_PLANE_TYPE_PRIMARY, NULL);
> +	if (ret)
> +		return ret;
> +
> +	drm_crtc_helper_add(crtc, &mxsfb_crtc_helper_funcs);
> +	ret = drm_crtc_init_with_planes(mxsfb->drm, crtc, plane, NULL,
> +					&mxsfb_crtc_funcs, NULL);
> +	if (ret)
> +		return ret;
> +
> +	encoder->possible_crtcs = drm_crtc_mask(crtc);
> +	return drm_encoder_init(mxsfb->drm, encoder, &mxsfb_encoder_funcs,
> +				DRM_MODE_ENCODER_NONE, NULL);
> +}
> diff --git a/drivers/gpu/drm/mxsfb/mxsfb_drv.c
> b/drivers/gpu/drm/mxsfb/mxsfb_drv.c
> index 204c1e52e9aa..a8da92976d13 100644
> --- a/drivers/gpu/drm/mxsfb/mxsfb_drv.c
> +++ b/drivers/gpu/drm/mxsfb/mxsfb_drv.c
> @@ -10,22 +10,23 @@
>  
>  #include <linux/clk.h>
>  #include <linux/dma-mapping.h>
> +#include <linux/io.h>
>  #include <linux/module.h>
>  #include <linux/of_device.h>
> +#include <linux/platform_device.h>
>  #include <linux/pm_runtime.h>
> -#include <linux/spinlock.h>
>  
> -#include <drm/drm_atomic.h>
>  #include <drm/drm_atomic_helper.h>
> -#include <drm/drm_crtc.h>
> +#include <drm/drm_bridge.h>
> +#include <drm/drm_connector.h>
>  #include <drm/drm_drv.h>
>  #include <drm/drm_fb_helper.h>
>  #include <drm/drm_gem_cma_helper.h>
>  #include <drm/drm_gem_framebuffer_helper.h>
>  #include <drm/drm_irq.h>
> +#include <drm/drm_mode_config.h>
>  #include <drm/drm_of.h>
>  #include <drm/drm_probe_helper.h>
> -#include <drm/drm_simple_kms_helper.h>
>  #include <drm/drm_vblank.h>
>  
>  #include "mxsfb_drv.h"
> @@ -57,17 +58,6 @@ static const struct mxsfb_devdata mxsfb_devdata[] = {
>  	},
>  };
>  
> -static const uint32_t mxsfb_formats[] = {
> -	DRM_FORMAT_XRGB8888,
> -	DRM_FORMAT_RGB565
> -};
> -
> -static struct mxsfb_drm_private *
> -drm_pipe_to_mxsfb_drm_private(struct drm_simple_display_pipe *pipe)
> -{
> -	return container_of(pipe, struct mxsfb_drm_private, pipe);
> -}
> -
>  void mxsfb_enable_axi_clk(struct mxsfb_drm_private *mxsfb)
>  {
>  	if (mxsfb->clk_axi)
> @@ -90,77 +80,6 @@ static const struct drm_mode_config_helper_funcs
> mxsfb_mode_config_helpers = {
>  	.atomic_commit_tail = drm_atomic_helper_commit_tail_rpm,
>  };
>  
> -static void mxsfb_pipe_enable(struct drm_simple_display_pipe *pipe,
> -			      struct drm_crtc_state *crtc_state,
> -			      struct drm_plane_state *plane_state)
> -{
> -	struct mxsfb_drm_private *mxsfb = drm_pipe_to_mxsfb_drm_private(pipe);
> -	struct drm_device *drm = pipe->plane.dev;
> -
> -	pm_runtime_get_sync(drm->dev);
> -	mxsfb_crtc_enable(mxsfb);
> -}
> -
> -static void mxsfb_pipe_disable(struct drm_simple_display_pipe *pipe)
> -{
> -	struct mxsfb_drm_private *mxsfb = drm_pipe_to_mxsfb_drm_private(pipe);
> -	struct drm_device *drm = pipe->plane.dev;
> -	struct drm_crtc *crtc = &pipe->crtc;
> -	struct drm_pending_vblank_event *event;
> -
> -	mxsfb_crtc_disable(mxsfb);
> -	pm_runtime_put_sync(drm->dev);
> -
> -	spin_lock_irq(&drm->event_lock);
> -	event = crtc->state->event;
> -	if (event) {
> -		crtc->state->event = NULL;
> -		drm_crtc_send_vblank_event(crtc, event);
> -	}
> -	spin_unlock_irq(&drm->event_lock);
> -}
> -
> -static void mxsfb_pipe_update(struct drm_simple_display_pipe *pipe,
> -			      struct drm_plane_state *plane_state)
> -{
> -	struct mxsfb_drm_private *mxsfb = drm_pipe_to_mxsfb_drm_private(pipe);
> -
> -	mxsfb_plane_atomic_update(mxsfb, plane_state);
> -}
> -
> -static int mxsfb_pipe_enable_vblank(struct drm_simple_display_pipe *pipe)
> -{
> -	struct mxsfb_drm_private *mxsfb = drm_pipe_to_mxsfb_drm_private(pipe);
> -
> -	/* Clear and enable VBLANK IRQ */
> -	mxsfb_enable_axi_clk(mxsfb);
> -	writel(CTRL1_CUR_FRAME_DONE_IRQ, mxsfb->base + LCDC_CTRL1 + REG_CLR);
> -	writel(CTRL1_CUR_FRAME_DONE_IRQ_EN, mxsfb->base + LCDC_CTRL1 + REG_SET);
> -	mxsfb_disable_axi_clk(mxsfb);
> -
> -	return 0;
> -}
> -
> -static void mxsfb_pipe_disable_vblank(struct drm_simple_display_pipe *pipe)
> -{
> -	struct mxsfb_drm_private *mxsfb = drm_pipe_to_mxsfb_drm_private(pipe);
> -
> -	/* Disable and clear VBLANK IRQ */
> -	mxsfb_enable_axi_clk(mxsfb);
> -	writel(CTRL1_CUR_FRAME_DONE_IRQ_EN, mxsfb->base + LCDC_CTRL1 + REG_CLR);
> -	writel(CTRL1_CUR_FRAME_DONE_IRQ, mxsfb->base + LCDC_CTRL1 + REG_CLR);
> -	mxsfb_disable_axi_clk(mxsfb);
> -}
> -
> -static struct drm_simple_display_pipe_funcs mxsfb_funcs = {
> -	.enable		= mxsfb_pipe_enable,
> -	.disable	= mxsfb_pipe_disable,
> -	.update		= mxsfb_pipe_update,
> -	.prepare_fb	= drm_gem_fb_simple_display_pipe_prepare_fb,
> -	.enable_vblank	= mxsfb_pipe_enable_vblank,
> -	.disable_vblank	= mxsfb_pipe_disable_vblank,
> -};
> -
>  static int mxsfb_attach_bridge(struct mxsfb_drm_private *mxsfb)
>  {
>  	struct drm_device *drm = mxsfb->drm;
> @@ -183,7 +102,7 @@ static int mxsfb_attach_bridge(struct
> mxsfb_drm_private *mxsfb)
>  	if (!bridge)
>  		return -ENODEV;
>  
> -	ret = drm_simple_display_pipe_attach_bridge(&mxsfb->pipe, bridge);
> +	ret = drm_bridge_attach(&mxsfb->encoder, bridge, NULL, 0);
>  	if (ret) {
>  		DRM_DEV_ERROR(drm->dev,
>  			      "failed to attach bridge: %d\n", ret);
> @@ -250,10 +169,9 @@ static int mxsfb_load(struct drm_device *drm,
> unsigned long flags)
>  	/* Modeset init */
>  	drm_mode_config_init(drm);
>  
> -	ret = drm_simple_display_pipe_init(drm, &mxsfb->pipe, &mxsfb_funcs,
> -			mxsfb_formats, ARRAY_SIZE(mxsfb_formats), NULL, NULL);
> +	ret = mxsfb_kms_init(mxsfb);
>  	if (ret < 0) {
> -		dev_err(drm->dev, "Cannot setup simple display pipe\n");
> +		dev_err(drm->dev, "Failed to initialize KMS pipeline\n");
>  		goto err_vblank;
>  	}
>  
> @@ -309,11 +227,11 @@ static void mxsfb_unload(struct drm_device *drm)
>  	pm_runtime_disable(drm->dev);
>  }
>  
> -static void mxsfb_irq_preinstall(struct drm_device *drm)
> +static void mxsfb_irq_disable(struct drm_device *drm)
>  {
>  	struct mxsfb_drm_private *mxsfb = drm->dev_private;
>  
> -	mxsfb_pipe_disable_vblank(&mxsfb->pipe);
> +	mxsfb->crtc.funcs->disable_vblank(&mxsfb->crtc);
>  }
>  
>  static irqreturn_t mxsfb_irq_handler(int irq, void *data)
> @@ -327,7 +245,7 @@ static irqreturn_t mxsfb_irq_handler(int irq, void *data)
>  	reg = readl(mxsfb->base + LCDC_CTRL1);
>  
>  	if (reg & CTRL1_CUR_FRAME_DONE_IRQ)
> -		drm_crtc_handle_vblank(&mxsfb->pipe.crtc);
> +		drm_crtc_handle_vblank(&mxsfb->crtc);
>  
>  	writel(CTRL1_CUR_FRAME_DONE_IRQ, mxsfb->base + LCDC_CTRL1 + REG_CLR);
>  
> @@ -341,8 +259,8 @@ DEFINE_DRM_GEM_CMA_FOPS(fops);
>  static struct drm_driver mxsfb_driver = {
>  	.driver_features	= DRIVER_GEM | DRIVER_MODESET | DRIVER_ATOMIC,
>  	.irq_handler		= mxsfb_irq_handler,
> -	.irq_preinstall		= mxsfb_irq_preinstall,
> -	.irq_uninstall		= mxsfb_irq_preinstall,
> +	.irq_preinstall		= mxsfb_irq_disable,
> +	.irq_uninstall		= mxsfb_irq_disable,
>  	.gem_free_object_unlocked = drm_gem_cma_free_object,
>  	.gem_vm_ops		= &drm_gem_cma_vm_ops,
>  	.dumb_create		= drm_gem_cma_dumb_create,
> diff --git a/drivers/gpu/drm/mxsfb/mxsfb_drv.h
> b/drivers/gpu/drm/mxsfb/mxsfb_drv.h
> index 0e3e5a63bbf9..edd766ad254f 100644
> --- a/drivers/gpu/drm/mxsfb/mxsfb_drv.h
> +++ b/drivers/gpu/drm/mxsfb/mxsfb_drv.h
> @@ -8,7 +8,12 @@
>  #ifndef __MXSFB_DRV_H__
>  #define __MXSFB_DRV_H__
>  
> -struct drm_device;
> +#include <drm/drm_crtc.h>
> +#include <drm/drm_device.h>
> +#include <drm/drm_encoder.h>
> +#include <drm/drm_plane.h>
> +
> +struct clk;
>  
>  struct mxsfb_devdata {
>  	unsigned int	 transfer_count;
> @@ -29,20 +34,22 @@ struct mxsfb_drm_private {
>  	struct clk			*clk_disp_axi;
>  
>  	struct drm_device		*drm;
> -	struct drm_simple_display_pipe	pipe;
> +	struct drm_plane		plane;
> +	struct drm_crtc			crtc;
> +	struct drm_encoder		encoder;
>  	struct drm_connector		*connector;
>  	struct drm_bridge		*bridge;
>  };
>  
> -int mxsfb_setup_crtc(struct drm_device *dev);
> -int mxsfb_create_output(struct drm_device *dev);
> +static inline struct mxsfb_drm_private *
> +to_mxsfb_drm_private(struct drm_device *drm)
> +{
> +	return drm->dev_private;
> +}
>  
>  void mxsfb_enable_axi_clk(struct mxsfb_drm_private *mxsfb);
>  void mxsfb_disable_axi_clk(struct mxsfb_drm_private *mxsfb);
>  
> -void mxsfb_crtc_enable(struct mxsfb_drm_private *mxsfb);
> -void mxsfb_crtc_disable(struct mxsfb_drm_private *mxsfb);
> -void mxsfb_plane_atomic_update(struct mxsfb_drm_private *mxsfb,
> -			       struct drm_plane_state *state);
> +int mxsfb_kms_init(struct mxsfb_drm_private *mxsfb);
>  
>  #endif /* __MXSFB_DRV_H__ */
_______________________________________________
dri-devel mailing list
dri-devel@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/dri-devel

^ permalink raw reply	[flat|nested] 62+ messages in thread

* Re: [PATCH 11/21] drm: mxsfb: Rename mxsfb_crtc.c to mxsfb_kms.c
  2020-03-09 19:52 ` [PATCH 11/21] drm: mxsfb: Rename mxsfb_crtc.c to mxsfb_kms.c Laurent Pinchart
@ 2020-03-23 22:31   ` Stefan Agner
  0 siblings, 0 replies; 62+ messages in thread
From: Stefan Agner @ 2020-03-23 22:31 UTC (permalink / raw)
  To: Laurent Pinchart; +Cc: Marek Vasut, kernel, dri-devel, linux-imx

On 2020-03-09 20:52, Laurent Pinchart wrote:
> The mxsfb_crtc.c file doesn't handle just the CRTC, but also the other
> KMS objects. Rename it accordingly.
> 
> Signed-off-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>

Reviewed-by: Stefan Agner <stefan@agner.ch>

> ---
>  drivers/gpu/drm/mxsfb/Makefile                      | 2 +-
>  drivers/gpu/drm/mxsfb/{mxsfb_crtc.c => mxsfb_kms.c} | 0
>  2 files changed, 1 insertion(+), 1 deletion(-)
>  rename drivers/gpu/drm/mxsfb/{mxsfb_crtc.c => mxsfb_kms.c} (100%)
> 
> diff --git a/drivers/gpu/drm/mxsfb/Makefile b/drivers/gpu/drm/mxsfb/Makefile
> index 811584e54ad1..26d153896d72 100644
> --- a/drivers/gpu/drm/mxsfb/Makefile
> +++ b/drivers/gpu/drm/mxsfb/Makefile
> @@ -1,3 +1,3 @@
>  # SPDX-License-Identifier: GPL-2.0-only
> -mxsfb-y := mxsfb_drv.o mxsfb_crtc.o
> +mxsfb-y := mxsfb_drv.o mxsfb_kms.o
>  obj-$(CONFIG_DRM_MXSFB)	+= mxsfb.o
> diff --git a/drivers/gpu/drm/mxsfb/mxsfb_crtc.c
> b/drivers/gpu/drm/mxsfb/mxsfb_kms.c
> similarity index 100%
> rename from drivers/gpu/drm/mxsfb/mxsfb_crtc.c
> rename to drivers/gpu/drm/mxsfb/mxsfb_kms.c
_______________________________________________
dri-devel mailing list
dri-devel@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/dri-devel

^ permalink raw reply	[flat|nested] 62+ messages in thread

* Re: [PATCH 12/21] drm: mxsfb: Move vblank event arm to CRTC .atomic_flush()
  2020-03-09 19:52 ` [PATCH 12/21] drm: mxsfb: Move vblank event arm to CRTC .atomic_flush() Laurent Pinchart
@ 2020-03-23 22:38   ` Stefan Agner
  0 siblings, 0 replies; 62+ messages in thread
From: Stefan Agner @ 2020-03-23 22:38 UTC (permalink / raw)
  To: Laurent Pinchart; +Cc: Marek Vasut, kernel, dri-devel, linux-imx

On 2020-03-09 20:52, Laurent Pinchart wrote:
> The vblank event is armed in the plane .atomic_update(). This works fine
> as we have a single plane, but will break as soon as multiple planes are
> supported (not to mention it's logically the wrong place to perform the
> operation). Move it to CRTC .atomic_flush().

The comment in the bracket make it sound as if there was something wrong
with the code before, but from what I understand that was just fine and
the only option we had with drm_simple_kms_helper, correct? Can you
maybe make that a bit clearer? (e.g. by stating that now that we no
longer use the simple display pipeline we can and should use the flush
callback).

Otherwise looks good.

Reviewed-by: Stefan Agner <stefan@agner.ch>

--
Stefan

> 
> Signed-off-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
> ---
>  drivers/gpu/drm/mxsfb/mxsfb_kms.c | 35 ++++++++++++++++++-------------
>  1 file changed, 20 insertions(+), 15 deletions(-)
> 
> diff --git a/drivers/gpu/drm/mxsfb/mxsfb_kms.c
> b/drivers/gpu/drm/mxsfb/mxsfb_kms.c
> index 8f339adb8d04..ebe0785694cb 100644
> --- a/drivers/gpu/drm/mxsfb/mxsfb_kms.c
> +++ b/drivers/gpu/drm/mxsfb/mxsfb_kms.c
> @@ -295,6 +295,25 @@ static int mxsfb_crtc_atomic_check(struct drm_crtc *crtc,
>  	return drm_atomic_add_affected_planes(state->state, crtc);
>  }
>  
> +static void mxsfb_crtc_atomic_flush(struct drm_crtc *crtc,
> +				    struct drm_crtc_state *old_state)
> +{
> +	struct drm_pending_vblank_event *event;
> +
> +	event = crtc->state->event;
> +	crtc->state->event = NULL;
> +
> +	if (!event)
> +		return;
> +
> +	spin_lock_irq(&crtc->dev->event_lock);
> +	if (drm_crtc_vblank_get(crtc) == 0)
> +		drm_crtc_arm_vblank_event(crtc, event);
> +	else
> +		drm_crtc_send_vblank_event(crtc, event);
> +	spin_unlock_irq(&crtc->dev->event_lock);
> +}
> +
>  static void mxsfb_crtc_atomic_enable(struct drm_crtc *crtc,
>  				     struct drm_crtc_state *old_state)
>  {
> @@ -364,6 +383,7 @@ static void mxsfb_crtc_disable_vblank(struct drm_crtc *crtc)
>  
>  static const struct drm_crtc_helper_funcs mxsfb_crtc_helper_funcs = {
>  	.atomic_check = mxsfb_crtc_atomic_check,
> +	.atomic_flush = mxsfb_crtc_atomic_flush,
>  	.atomic_enable = mxsfb_crtc_atomic_enable,
>  	.atomic_disable = mxsfb_crtc_atomic_disable,
>  };
> @@ -410,23 +430,8 @@ static void mxsfb_plane_atomic_update(struct
> drm_plane *plane,
>  				      struct drm_plane_state *old_pstate)
>  {
>  	struct mxsfb_drm_private *mxsfb = to_mxsfb_drm_private(plane->dev);
> -	struct drm_crtc *crtc = &mxsfb->crtc;
> -	struct drm_pending_vblank_event *event;
>  	dma_addr_t paddr;
>  
> -	spin_lock_irq(&crtc->dev->event_lock);
> -	event = crtc->state->event;
> -	if (event) {
> -		crtc->state->event = NULL;
> -
> -		if (drm_crtc_vblank_get(crtc) == 0) {
> -			drm_crtc_arm_vblank_event(crtc, event);
> -		} else {
> -			drm_crtc_send_vblank_event(crtc, event);
> -		}
> -	}
> -	spin_unlock_irq(&crtc->dev->event_lock);
> -
>  	paddr = mxsfb_get_fb_paddr(mxsfb);
>  	if (paddr) {
>  		mxsfb_enable_axi_clk(mxsfb);
_______________________________________________
dri-devel mailing list
dri-devel@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/dri-devel

^ permalink raw reply	[flat|nested] 62+ messages in thread

* Re: [PATCH 13/21] drm: mxsfb: Don't touch AXI clock in IRQ context
  2020-03-09 19:52 ` [PATCH 13/21] drm: mxsfb: Don't touch AXI clock in IRQ context Laurent Pinchart
@ 2020-03-23 22:50   ` Stefan Agner
  0 siblings, 0 replies; 62+ messages in thread
From: Stefan Agner @ 2020-03-23 22:50 UTC (permalink / raw)
  To: Laurent Pinchart; +Cc: Marek Vasut, kernel, dri-devel, linux-imx

On 2020-03-09 20:52, Laurent Pinchart wrote:
> The driver attempts agressive power management by enabling and disabling
> the AXI clock around register accesses. This results in attempts to
> enable and disable the clock in the IRQ handler, which is a no-go as
> preparing or unpreparing the clock may sleep.
> 
> On the other hand, the driver enables the AXI clock when enabling the
> CRTC and keeps it enabled until the CRTC is disabled. This is correct,
> and renders the power management attempt pointless, as interrupts are
> not supposed to occur when the CRTC is off.
> 
> The same reasoning can be applied to the CRTC .enable_vblank() and
> .disable_vblank() that are not supposed to be called when the CRTC off
> and thus don't require manual handling of the AXI clock. Furthermore,
> vblank handling is never enabled, which results in the vblank enable and
> disable handlers never being called.
> 
> To fix this, remove the manual clock handling in the IRQ, the CRTC
> .enable_vblank() and .disable_vblank() handlers and the plane
> .atomic_update() handler. We however need to handle the clock manually
> in mxsfb_irq_disable() as is calls .disable_vblank() manually and is
> used both at probe and remove time.
> 
> The clock disabling is also moved to the last step of the
> mxsfb_crtc_atomic_disable() function, to prepare for enabling vblank
> handling.
> 
> Signed-off-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>

Looks good to me!

Reviewed-by: Stefan Agner <stefan@agner.ch>

> ---
>  drivers/gpu/drm/mxsfb/mxsfb_drv.c |  6 ++----
>  drivers/gpu/drm/mxsfb/mxsfb_kms.c | 15 ++++-----------
>  2 files changed, 6 insertions(+), 15 deletions(-)
> 
> diff --git a/drivers/gpu/drm/mxsfb/mxsfb_drv.c
> b/drivers/gpu/drm/mxsfb/mxsfb_drv.c
> index a8da92976d13..e324bd2a63a5 100644
> --- a/drivers/gpu/drm/mxsfb/mxsfb_drv.c
> +++ b/drivers/gpu/drm/mxsfb/mxsfb_drv.c
> @@ -231,7 +231,9 @@ static void mxsfb_irq_disable(struct drm_device *drm)
>  {
>  	struct mxsfb_drm_private *mxsfb = drm->dev_private;
>  
> +	mxsfb_enable_axi_clk(mxsfb);
>  	mxsfb->crtc.funcs->disable_vblank(&mxsfb->crtc);
> +	mxsfb_disable_axi_clk(mxsfb);
>  }
>  
>  static irqreturn_t mxsfb_irq_handler(int irq, void *data)
> @@ -240,8 +242,6 @@ static irqreturn_t mxsfb_irq_handler(int irq, void *data)
>  	struct mxsfb_drm_private *mxsfb = drm->dev_private;
>  	u32 reg;
>  
> -	mxsfb_enable_axi_clk(mxsfb);
> -
>  	reg = readl(mxsfb->base + LCDC_CTRL1);
>  
>  	if (reg & CTRL1_CUR_FRAME_DONE_IRQ)
> @@ -249,8 +249,6 @@ static irqreturn_t mxsfb_irq_handler(int irq, void *data)
>  
>  	writel(CTRL1_CUR_FRAME_DONE_IRQ, mxsfb->base + LCDC_CTRL1 + REG_CLR);
>  
> -	mxsfb_disable_axi_clk(mxsfb);
> -
>  	return IRQ_HANDLED;
>  }
>  
> diff --git a/drivers/gpu/drm/mxsfb/mxsfb_kms.c
> b/drivers/gpu/drm/mxsfb/mxsfb_kms.c
> index ebe0785694cb..ac2696c8483d 100644
> --- a/drivers/gpu/drm/mxsfb/mxsfb_kms.c
> +++ b/drivers/gpu/drm/mxsfb/mxsfb_kms.c
> @@ -344,9 +344,6 @@ static void mxsfb_crtc_atomic_disable(struct drm_crtc *crtc,
>  	struct drm_pending_vblank_event *event;
>  
>  	mxsfb_disable_controller(mxsfb);
> -	mxsfb_disable_axi_clk(mxsfb);
> -
> -	pm_runtime_put_sync(drm->dev);
>  
>  	spin_lock_irq(&drm->event_lock);
>  	event = crtc->state->event;
> @@ -355,6 +352,9 @@ static void mxsfb_crtc_atomic_disable(struct drm_crtc *crtc,
>  		drm_crtc_send_vblank_event(crtc, event);
>  	}
>  	spin_unlock_irq(&drm->event_lock);
> +
> +	mxsfb_disable_axi_clk(mxsfb);
> +	pm_runtime_put_sync(drm->dev);
>  }
>  
>  static int mxsfb_crtc_enable_vblank(struct drm_crtc *crtc)
> @@ -362,10 +362,8 @@ static int mxsfb_crtc_enable_vblank(struct drm_crtc *crtc)
>  	struct mxsfb_drm_private *mxsfb = to_mxsfb_drm_private(crtc->dev);
>  
>  	/* Clear and enable VBLANK IRQ */
> -	mxsfb_enable_axi_clk(mxsfb);
>  	writel(CTRL1_CUR_FRAME_DONE_IRQ, mxsfb->base + LCDC_CTRL1 + REG_CLR);
>  	writel(CTRL1_CUR_FRAME_DONE_IRQ_EN, mxsfb->base + LCDC_CTRL1 + REG_SET);
> -	mxsfb_disable_axi_clk(mxsfb);
>  
>  	return 0;
>  }
> @@ -375,10 +373,8 @@ static void mxsfb_crtc_disable_vblank(struct
> drm_crtc *crtc)
>  	struct mxsfb_drm_private *mxsfb = to_mxsfb_drm_private(crtc->dev);
>  
>  	/* Disable and clear VBLANK IRQ */
> -	mxsfb_enable_axi_clk(mxsfb);
>  	writel(CTRL1_CUR_FRAME_DONE_IRQ_EN, mxsfb->base + LCDC_CTRL1 + REG_CLR);
>  	writel(CTRL1_CUR_FRAME_DONE_IRQ, mxsfb->base + LCDC_CTRL1 + REG_CLR);
> -	mxsfb_disable_axi_clk(mxsfb);
>  }
>  
>  static const struct drm_crtc_helper_funcs mxsfb_crtc_helper_funcs = {
> @@ -433,11 +429,8 @@ static void mxsfb_plane_atomic_update(struct
> drm_plane *plane,
>  	dma_addr_t paddr;
>  
>  	paddr = mxsfb_get_fb_paddr(mxsfb);
> -	if (paddr) {
> -		mxsfb_enable_axi_clk(mxsfb);
> +	if (paddr)
>  		writel(paddr, mxsfb->base + mxsfb->devdata->next_buf);
> -		mxsfb_disable_axi_clk(mxsfb);
> -	}
>  }
>  
>  static const struct drm_plane_helper_funcs mxsfb_plane_helper_funcs = {
_______________________________________________
dri-devel mailing list
dri-devel@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/dri-devel

^ permalink raw reply	[flat|nested] 62+ messages in thread

* Re: [PATCH 14/21] drm: mxsfb: Enable vblank handling
  2020-03-09 19:52 ` [PATCH 14/21] drm: mxsfb: Enable vblank handling Laurent Pinchart
@ 2020-03-23 23:08   ` Stefan Agner
  2020-03-24 10:37     ` Stefan Agner
  0 siblings, 1 reply; 62+ messages in thread
From: Stefan Agner @ 2020-03-23 23:08 UTC (permalink / raw)
  To: Laurent Pinchart; +Cc: Marek Vasut, kernel, dri-devel, linux-imx

On 2020-03-09 20:52, Laurent Pinchart wrote:
> Enable vblank handling when the CRTC is turned on and disable it when it
> is turned off. This requires moving vblank init after the KMS pipeline
> initialisation, otherwise drm_vblank_init() gets called with 0 CRTCs.
> 
> Signed-off-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>

With this patch applied I start to get system resets on my Colibri iMX7
test device during system boot shortly after initializing mxsfb. It
happens not on every boot, but rather often, I would say every second or
third. From what I can tell the interrupt handling should be safe, but
it seems that every now and then something races. Any idea what that
could be?

--
Stefan

> ---
>  drivers/gpu/drm/mxsfb/mxsfb_drv.c | 15 +++++++++------
>  drivers/gpu/drm/mxsfb/mxsfb_kms.c |  6 +++++-
>  2 files changed, 14 insertions(+), 7 deletions(-)
> 
> diff --git a/drivers/gpu/drm/mxsfb/mxsfb_drv.c
> b/drivers/gpu/drm/mxsfb/mxsfb_drv.c
> index e324bd2a63a5..72b4f6a947a4 100644
> --- a/drivers/gpu/drm/mxsfb/mxsfb_drv.c
> +++ b/drivers/gpu/drm/mxsfb/mxsfb_drv.c
> @@ -160,12 +160,6 @@ static int mxsfb_load(struct drm_device *drm,
> unsigned long flags)
>  
>  	pm_runtime_enable(drm->dev);
>  
> -	ret = drm_vblank_init(drm, drm->mode_config.num_crtc);
> -	if (ret < 0) {
> -		dev_err(drm->dev, "Failed to initialise vblank\n");
> -		goto err_vblank;
> -	}
> -
>  	/* Modeset init */
>  	drm_mode_config_init(drm);
>  
> @@ -175,6 +169,15 @@ static int mxsfb_load(struct drm_device *drm,
> unsigned long flags)
>  		goto err_vblank;
>  	}
>  
> +	ret = drm_vblank_init(drm, drm->mode_config.num_crtc);
> +	if (ret < 0) {
> +		dev_err(drm->dev, "Failed to initialise vblank\n");
> +		goto err_vblank;
> +	}
> +
> +	/* Start with vertical blanking interrupt reporting disabled. */
> +	drm_crtc_vblank_off(&mxsfb->crtc);
> +
>  	ret = mxsfb_attach_bridge(mxsfb);
>  	if (ret) {
>  		dev_err(drm->dev, "Cannot connect bridge: %d\n", ret);
> diff --git a/drivers/gpu/drm/mxsfb/mxsfb_kms.c
> b/drivers/gpu/drm/mxsfb/mxsfb_kms.c
> index ac2696c8483d..640305fb1068 100644
> --- a/drivers/gpu/drm/mxsfb/mxsfb_kms.c
> +++ b/drivers/gpu/drm/mxsfb/mxsfb_kms.c
> @@ -322,8 +322,10 @@ static void mxsfb_crtc_atomic_enable(struct drm_crtc *crtc,
>  	dma_addr_t paddr;
>  
>  	pm_runtime_get_sync(drm->dev);
> -
>  	mxsfb_enable_axi_clk(mxsfb);
> +
> +	drm_crtc_vblank_on(crtc);
> +
>  	mxsfb_crtc_mode_set_nofb(mxsfb);
>  
>  	/* Write cur_buf as well to avoid an initial corrupt frame */
> @@ -353,6 +355,8 @@ static void mxsfb_crtc_atomic_disable(struct drm_crtc *crtc,
>  	}
>  	spin_unlock_irq(&drm->event_lock);
>  
> +	drm_crtc_vblank_off(crtc);
> +
>  	mxsfb_disable_axi_clk(mxsfb);
>  	pm_runtime_put_sync(drm->dev);
>  }
_______________________________________________
dri-devel mailing list
dri-devel@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/dri-devel

^ permalink raw reply	[flat|nested] 62+ messages in thread

* Re: [PATCH 15/21] drm: mxsfb: Remove mxsfb_devdata unused fields
  2020-03-09 19:52 ` [PATCH 15/21] drm: mxsfb: Remove mxsfb_devdata unused fields Laurent Pinchart
@ 2020-03-23 23:15   ` Stefan Agner
  0 siblings, 0 replies; 62+ messages in thread
From: Stefan Agner @ 2020-03-23 23:15 UTC (permalink / raw)
  To: Laurent Pinchart; +Cc: Marek Vasut, kernel, dri-devel, linux-imx

On 2020-03-09 20:52, Laurent Pinchart wrote:
> The debug0 and ipversion fields of the mxsfb_devdata structure are
> unused. Remove them.
> 
> Signed-off-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>

Reviewed-by: Stefan Agner <stefan@agner.ch>

> ---
>  drivers/gpu/drm/mxsfb/mxsfb_drv.c | 4 ----
>  drivers/gpu/drm/mxsfb/mxsfb_drv.h | 2 --
>  2 files changed, 6 deletions(-)
> 
> diff --git a/drivers/gpu/drm/mxsfb/mxsfb_drv.c
> b/drivers/gpu/drm/mxsfb/mxsfb_drv.c
> index 72b4f6a947a4..7c9a041f5f6d 100644
> --- a/drivers/gpu/drm/mxsfb/mxsfb_drv.c
> +++ b/drivers/gpu/drm/mxsfb/mxsfb_drv.c
> @@ -42,19 +42,15 @@ static const struct mxsfb_devdata mxsfb_devdata[] = {
>  		.transfer_count	= LCDC_V3_TRANSFER_COUNT,
>  		.cur_buf	= LCDC_V3_CUR_BUF,
>  		.next_buf	= LCDC_V3_NEXT_BUF,
> -		.debug0		= LCDC_V3_DEBUG0,
>  		.hs_wdth_mask	= 0xff,
>  		.hs_wdth_shift	= 24,
> -		.ipversion	= 3,
>  	},
>  	[MXSFB_V4] = {
>  		.transfer_count	= LCDC_V4_TRANSFER_COUNT,
>  		.cur_buf	= LCDC_V4_CUR_BUF,
>  		.next_buf	= LCDC_V4_NEXT_BUF,
> -		.debug0		= LCDC_V4_DEBUG0,
>  		.hs_wdth_mask	= 0x3fff,
>  		.hs_wdth_shift	= 18,
> -		.ipversion	= 4,
>  	},
>  };
>  
> diff --git a/drivers/gpu/drm/mxsfb/mxsfb_drv.h
> b/drivers/gpu/drm/mxsfb/mxsfb_drv.h
> index edd766ad254f..607a6a5e6be3 100644
> --- a/drivers/gpu/drm/mxsfb/mxsfb_drv.h
> +++ b/drivers/gpu/drm/mxsfb/mxsfb_drv.h
> @@ -19,10 +19,8 @@ struct mxsfb_devdata {
>  	unsigned int	 transfer_count;
>  	unsigned int	 cur_buf;
>  	unsigned int	 next_buf;
> -	unsigned int	 debug0;
>  	unsigned int	 hs_wdth_mask;
>  	unsigned int	 hs_wdth_shift;
> -	unsigned int	 ipversion;
>  };
>  
>  struct mxsfb_drm_private {
_______________________________________________
dri-devel mailing list
dri-devel@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/dri-devel

^ permalink raw reply	[flat|nested] 62+ messages in thread

* Re: [PATCH 16/21] drm: mxsfb: Add i.MX7 to the list of supported SoCs in Kconfig
  2020-03-09 19:52 ` [PATCH 16/21] drm: mxsfb: Add i.MX7 to the list of supported SoCs in Kconfig Laurent Pinchart
  2020-03-10 16:28   ` Fabio Estevam
@ 2020-03-23 23:18   ` Stefan Agner
  1 sibling, 0 replies; 62+ messages in thread
From: Stefan Agner @ 2020-03-23 23:18 UTC (permalink / raw)
  To: Laurent Pinchart; +Cc: Marek Vasut, kernel, dri-devel, linux-imx

On 2020-03-09 20:52, Laurent Pinchart wrote:
> Extend the Kconfig option description by listing the i.MX7 SoCs, as they
> are supported by the same driver.

Can you also add "i.MX8M" to the list since the bindings for this driver
are also used in arch/arm64/boot/dts/freescale/imx8mq.dtsi.

--
Stefan

> 
> Signed-off-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
> ---
>  drivers/gpu/drm/mxsfb/Kconfig | 4 ++--
>  1 file changed, 2 insertions(+), 2 deletions(-)
> 
> diff --git a/drivers/gpu/drm/mxsfb/Kconfig b/drivers/gpu/drm/mxsfb/Kconfig
> index 0dca8f27169e..e91841f8f8a2 100644
> --- a/drivers/gpu/drm/mxsfb/Kconfig
> +++ b/drivers/gpu/drm/mxsfb/Kconfig
> @@ -5,7 +5,7 @@ config DRM_MXS
>  	  Choose this option to select drivers for MXS FB devices
>  
>  config DRM_MXSFB
> -	tristate "i.MX23/i.MX28/i.MX6SX MXSFB LCD controller"
> +	tristate "i.MX23/i.MX28/i.MX6SX/i.MX7 MXSFB LCD controller"
>  	depends on DRM && OF
>  	depends on COMMON_CLK
>  	select DRM_MXS
> @@ -14,7 +14,7 @@ config DRM_MXSFB
>  	select DRM_KMS_CMA_HELPER
>  	select DRM_PANEL
>  	help
> -	  Choose this option if you have an i.MX23/i.MX28/i.MX6SX MXSFB
> +	  Choose this option if you have an i.MX23/i.MX28/i.MX6SX/i.MX7 MXSFB
>  	  LCD controller.
>  
>  	  If M is selected the module will be called mxsfb.
_______________________________________________
dri-devel mailing list
dri-devel@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/dri-devel

^ permalink raw reply	[flat|nested] 62+ messages in thread

* Re: [PATCH 17/21] drm: mxsfb: Update internal IP version number for i.MX6SX
  2020-03-09 19:52 ` [PATCH 17/21] drm: mxsfb: Update internal IP version number for i.MX6SX Laurent Pinchart
@ 2020-03-23 23:20   ` Stefan Agner
  0 siblings, 0 replies; 62+ messages in thread
From: Stefan Agner @ 2020-03-23 23:20 UTC (permalink / raw)
  To: Laurent Pinchart; +Cc: Marek Vasut, kernel, dri-devel, linux-imx

On 2020-03-09 20:52, Laurent Pinchart wrote:
> The LCDIF present in the i.MX6SX has extra features compared to
> the i.MX28. It has however lost its IP version register, so no official
> version number is known. Bump the version to MXSFB_V6 following the i.MX
> version, in preparation for support for the additional features.
> 
> Signed-off-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>

Reviewed-by: Stefan Agner <stefan@agner.ch>

> ---
>  drivers/gpu/drm/mxsfb/mxsfb_drv.c | 14 +++++++++++++-
>  1 file changed, 13 insertions(+), 1 deletion(-)
> 
> diff --git a/drivers/gpu/drm/mxsfb/mxsfb_drv.c
> b/drivers/gpu/drm/mxsfb/mxsfb_drv.c
> index 7c9a041f5f6d..2316c12c5c42 100644
> --- a/drivers/gpu/drm/mxsfb/mxsfb_drv.c
> +++ b/drivers/gpu/drm/mxsfb/mxsfb_drv.c
> @@ -35,6 +35,11 @@
>  enum mxsfb_devtype {
>  	MXSFB_V3,
>  	MXSFB_V4,
> +	/*
> +	 * Starting at i.MX6 the hardware version register is gone, use the
> +	 * i.MX family number as the version.
> +	 */
> +	MXSFB_V6,
>  };
>  
>  static const struct mxsfb_devdata mxsfb_devdata[] = {
> @@ -52,6 +57,13 @@ static const struct mxsfb_devdata mxsfb_devdata[] = {
>  		.hs_wdth_mask	= 0x3fff,
>  		.hs_wdth_shift	= 18,
>  	},
> +	[MXSFB_V6] = {
> +		.transfer_count	= LCDC_V4_TRANSFER_COUNT,
> +		.cur_buf	= LCDC_V4_CUR_BUF,
> +		.next_buf	= LCDC_V4_NEXT_BUF,
> +		.hs_wdth_mask	= 0x3fff,
> +		.hs_wdth_shift	= 18,
> +	},
>  };
>  
>  void mxsfb_enable_axi_clk(struct mxsfb_drm_private *mxsfb)
> @@ -279,7 +291,7 @@ static struct drm_driver mxsfb_driver = {
>  static const struct platform_device_id mxsfb_devtype[] = {
>  	{ .name = "imx23-fb", .driver_data = MXSFB_V3, },
>  	{ .name = "imx28-fb", .driver_data = MXSFB_V4, },
> -	{ .name = "imx6sx-fb", .driver_data = MXSFB_V4, },
> +	{ .name = "imx6sx-fb", .driver_data = MXSFB_V6, },
>  	{ /* sentinel */ }
>  };
>  MODULE_DEVICE_TABLE(platform, mxsfb_devtype);
_______________________________________________
dri-devel mailing list
dri-devel@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/dri-devel

^ permalink raw reply	[flat|nested] 62+ messages in thread

* Re: [PATCH 18/21] drm: mxsfb: Drop non-OF support
  2020-03-09 19:52 ` [PATCH 18/21] drm: mxsfb: Drop non-OF support Laurent Pinchart
@ 2020-03-23 23:23   ` Stefan Agner
  0 siblings, 0 replies; 62+ messages in thread
From: Stefan Agner @ 2020-03-23 23:23 UTC (permalink / raw)
  To: Laurent Pinchart; +Cc: Marek Vasut, kernel, dri-devel, linux-imx

On 2020-03-09 20:52, Laurent Pinchart wrote:
> The mxsfb driver is only used by OF platforms. Drop non-OF support.

Nice cleanup. Actually only supported of anyways due to the
pdev->dev.of_node check.

Reviewed-by: Stefan Agner <stefan@agner.ch>

--
Stefan

> 
> Signed-off-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
> ---
>  drivers/gpu/drm/mxsfb/mxsfb_drv.c | 25 +++++++------------------
>  1 file changed, 7 insertions(+), 18 deletions(-)
> 
> diff --git a/drivers/gpu/drm/mxsfb/mxsfb_drv.c
> b/drivers/gpu/drm/mxsfb/mxsfb_drv.c
> index 2316c12c5c42..ed8e3f7bc27c 100644
> --- a/drivers/gpu/drm/mxsfb/mxsfb_drv.c
> +++ b/drivers/gpu/drm/mxsfb/mxsfb_drv.c
> @@ -130,7 +130,8 @@ static int mxsfb_attach_bridge(struct
> mxsfb_drm_private *mxsfb)
>  	return 0;
>  }
>  
> -static int mxsfb_load(struct drm_device *drm, unsigned long flags)
> +static int mxsfb_load(struct drm_device *drm,
> +		      const struct mxsfb_devdata *devdata)
>  {
>  	struct platform_device *pdev = to_platform_device(drm->dev);
>  	struct mxsfb_drm_private *mxsfb;
> @@ -143,7 +144,7 @@ static int mxsfb_load(struct drm_device *drm,
> unsigned long flags)
>  
>  	mxsfb->drm = drm;
>  	drm->dev_private = mxsfb;
> -	mxsfb->devdata = &mxsfb_devdata[pdev->id_entry->driver_data];
> +	mxsfb->devdata = devdata;
>  
>  	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
>  	mxsfb->base = devm_ioremap_resource(drm->dev, res);
> @@ -288,18 +289,10 @@ static struct drm_driver mxsfb_driver = {
>  	.minor	= 0,
>  };
>  
> -static const struct platform_device_id mxsfb_devtype[] = {
> -	{ .name = "imx23-fb", .driver_data = MXSFB_V3, },
> -	{ .name = "imx28-fb", .driver_data = MXSFB_V4, },
> -	{ .name = "imx6sx-fb", .driver_data = MXSFB_V6, },
> -	{ /* sentinel */ }
> -};
> -MODULE_DEVICE_TABLE(platform, mxsfb_devtype);
> -
>  static const struct of_device_id mxsfb_dt_ids[] = {
> -	{ .compatible = "fsl,imx23-lcdif", .data = &mxsfb_devtype[0], },
> -	{ .compatible = "fsl,imx28-lcdif", .data = &mxsfb_devtype[1], },
> -	{ .compatible = "fsl,imx6sx-lcdif", .data = &mxsfb_devtype[2], },
> +	{ .compatible = "fsl,imx23-lcdif", .data = &mxsfb_devdata[MXSFB_V3], },
> +	{ .compatible = "fsl,imx28-lcdif", .data = &mxsfb_devdata[MXSFB_V4], },
> +	{ .compatible = "fsl,imx6sx-lcdif", .data = &mxsfb_devdata[MXSFB_V6], },
>  	{ /* sentinel */ }
>  };
>  MODULE_DEVICE_TABLE(of, mxsfb_dt_ids);
> @@ -314,14 +307,11 @@ static int mxsfb_probe(struct platform_device *pdev)
>  	if (!pdev->dev.of_node)
>  		return -ENODEV;
>  
> -	if (of_id)
> -		pdev->id_entry = of_id->data;
> -
>  	drm = drm_dev_alloc(&mxsfb_driver, &pdev->dev);
>  	if (IS_ERR(drm))
>  		return PTR_ERR(drm);
>  
> -	ret = mxsfb_load(drm, 0);
> +	ret = mxsfb_load(drm, of_id->data);
>  	if (ret)
>  		goto err_free;
>  
> @@ -375,7 +365,6 @@ static const struct dev_pm_ops mxsfb_pm_ops = {
>  static struct platform_driver mxsfb_platform_driver = {
>  	.probe		= mxsfb_probe,
>  	.remove		= mxsfb_remove,
> -	.id_table	= mxsfb_devtype,
>  	.driver	= {
>  		.name		= "mxsfb",
>  		.of_match_table	= mxsfb_dt_ids,
_______________________________________________
dri-devel mailing list
dri-devel@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/dri-devel

^ permalink raw reply	[flat|nested] 62+ messages in thread

* Re: [PATCH 19/21] drm: mxsfb: Turn mxsfb_set_pixel_fmt() into a void function
  2020-03-09 19:52 ` [PATCH 19/21] drm: mxsfb: Turn mxsfb_set_pixel_fmt() into a void function Laurent Pinchart
@ 2020-03-23 23:28   ` Stefan Agner
  0 siblings, 0 replies; 62+ messages in thread
From: Stefan Agner @ 2020-03-23 23:28 UTC (permalink / raw)
  To: Laurent Pinchart; +Cc: Marek Vasut, kernel, dri-devel, linux-imx

On 2020-03-09 20:52, Laurent Pinchart wrote:
> The mxsfb_set_pixel_fmt() function returns an error when the selected
> pixel format is unsupported. This can never happen, as such errors are
> caught by the DRM core. Remove the error check.
> 
> Signed-off-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>

I see, we specify the supported plane formats when initializing the
primary/overlay plane.

Reviewed-by: Stefan Agner <stefan@agner.ch>

--
Stefan

> ---
>  drivers/gpu/drm/mxsfb/mxsfb_kms.c | 11 ++---------
>  1 file changed, 2 insertions(+), 9 deletions(-)
> 
> diff --git a/drivers/gpu/drm/mxsfb/mxsfb_kms.c
> b/drivers/gpu/drm/mxsfb/mxsfb_kms.c
> index 640305fb1068..19b937b383cf 100644
> --- a/drivers/gpu/drm/mxsfb/mxsfb_kms.c
> +++ b/drivers/gpu/drm/mxsfb/mxsfb_kms.c
> @@ -43,7 +43,7 @@ static u32 set_hsync_pulse_width(struct
> mxsfb_drm_private *mxsfb, u32 val)
>  }
>  
>  /* Setup the MXSFB registers for decoding the pixels out of the framebuffer */
> -static int mxsfb_set_pixel_fmt(struct mxsfb_drm_private *mxsfb)
> +static void mxsfb_set_pixel_fmt(struct mxsfb_drm_private *mxsfb)
>  {
>  	struct drm_device *drm = mxsfb->drm;
>  	const u32 format = mxsfb->crtc.primary->state->fb->format->format;
> @@ -67,15 +67,10 @@ static int mxsfb_set_pixel_fmt(struct
> mxsfb_drm_private *mxsfb)
>  		/* Do not use packed pixels = one pixel per word instead. */
>  		ctrl1 |= CTRL1_SET_BYTE_PACKAGING(0x7);
>  		break;
> -	default:
> -		dev_err(drm->dev, "Unhandled pixel format %08x\n", format);
> -		return -EINVAL;
>  	}
>  
>  	writel(ctrl1, mxsfb->base + LCDC_CTRL1);
>  	writel(ctrl, mxsfb->base + LCDC_CTRL);
> -
> -	return 0;
>  }
>  
>  static void mxsfb_set_bus_fmt(struct mxsfb_drm_private *mxsfb)
> @@ -218,9 +213,7 @@ static void mxsfb_crtc_mode_set_nofb(struct
> mxsfb_drm_private *mxsfb)
>  	/* Clear the FIFOs */
>  	writel(CTRL1_FIFO_CLEAR, mxsfb->base + LCDC_CTRL1 + REG_SET);
>  
> -	err = mxsfb_set_pixel_fmt(mxsfb);
> -	if (err)
> -		return;
> +	mxsfb_set_pixel_fmt(mxsfb);
>  
>  	clk_set_rate(mxsfb->clk, m->crtc_clock * 1000);
_______________________________________________
dri-devel mailing list
dri-devel@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/dri-devel

^ permalink raw reply	[flat|nested] 62+ messages in thread

* Re: [PATCH 20/21] drm: mxsfb: Merge mxsfb_set_pixel_fmt() and mxsfb_set_bus_fmt()
  2020-03-09 19:52 ` [PATCH 20/21] drm: mxsfb: Merge mxsfb_set_pixel_fmt() and mxsfb_set_bus_fmt() Laurent Pinchart
@ 2020-03-23 23:34   ` Stefan Agner
  0 siblings, 0 replies; 62+ messages in thread
From: Stefan Agner @ 2020-03-23 23:34 UTC (permalink / raw)
  To: Laurent Pinchart; +Cc: Marek Vasut, kernel, dri-devel, linux-imx

On 2020-03-09 20:52, Laurent Pinchart wrote:
> The mxsfb_set_pixel_fmt() and mxsfb_set_bus_fmt() functions both deal
> with format configuration, are always called in a row from
> mxsfb_crtc_mode_set_nofb(), and set fields from the LCDC_CTRL register.
> This requires a read-modify-update cycle in mxsfb_set_bus_fmt(). Make
> this more efficient by merging them together.
> 
> Signed-off-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>

Reviewed-by: Stefan Agner <stefan@agner.ch>

> ---
>  drivers/gpu/drm/mxsfb/mxsfb_kms.c | 47 +++++++++++++------------------
>  1 file changed, 19 insertions(+), 28 deletions(-)
> 
> diff --git a/drivers/gpu/drm/mxsfb/mxsfb_kms.c
> b/drivers/gpu/drm/mxsfb/mxsfb_kms.c
> index 19b937b383cf..f81f8c222c13 100644
> --- a/drivers/gpu/drm/mxsfb/mxsfb_kms.c
> +++ b/drivers/gpu/drm/mxsfb/mxsfb_kms.c
> @@ -42,13 +42,23 @@ static u32 set_hsync_pulse_width(struct
> mxsfb_drm_private *mxsfb, u32 val)
>  		mxsfb->devdata->hs_wdth_shift;
>  }
>  
> -/* Setup the MXSFB registers for decoding the pixels out of the framebuffer */
> -static void mxsfb_set_pixel_fmt(struct mxsfb_drm_private *mxsfb)
> +/*
> + * Setup the MXSFB registers for decoding the pixels out of the framebuffer and
> + * outputting them on the bus.
> + */
> +static void mxsfb_set_formats(struct mxsfb_drm_private *mxsfb)
>  {
>  	struct drm_device *drm = mxsfb->drm;
>  	const u32 format = mxsfb->crtc.primary->state->fb->format->format;
> +	u32 bus_format = MEDIA_BUS_FMT_RGB888_1X24;
>  	u32 ctrl, ctrl1;
>  
> +	if (mxsfb->connector->display_info.num_bus_formats)
> +		bus_format = mxsfb->connector->display_info.bus_formats[0];
> +
> +	DRM_DEV_DEBUG_DRIVER(drm->dev, "Using bus_format: 0x%08X\n",
> +			     bus_format);
> +
>  	ctrl = CTRL_BYPASS_COUNT | CTRL_MASTER;
>  
>  	/* CTRL1 contains IRQ config and status bits, preserve those. */
> @@ -69,40 +79,23 @@ static void mxsfb_set_pixel_fmt(struct
> mxsfb_drm_private *mxsfb)
>  		break;
>  	}
>  
> -	writel(ctrl1, mxsfb->base + LCDC_CTRL1);
> -	writel(ctrl, mxsfb->base + LCDC_CTRL);
> -}
> -
> -static void mxsfb_set_bus_fmt(struct mxsfb_drm_private *mxsfb)
> -{
> -	struct drm_device *drm = mxsfb->drm;
> -	u32 bus_format = MEDIA_BUS_FMT_RGB888_1X24;
> -	u32 reg;
> -
> -	reg = readl(mxsfb->base + LCDC_CTRL);
> -
> -	if (mxsfb->connector->display_info.num_bus_formats)
> -		bus_format = mxsfb->connector->display_info.bus_formats[0];
> -
> -	DRM_DEV_DEBUG_DRIVER(drm->dev, "Using bus_format: 0x%08X\n",
> -			     bus_format);
> -
> -	reg &= ~CTRL_BUS_WIDTH_MASK;
>  	switch (bus_format) {
>  	case MEDIA_BUS_FMT_RGB565_1X16:
> -		reg |= CTRL_BUS_WIDTH_16;
> +		ctrl |= CTRL_BUS_WIDTH_16;
>  		break;
>  	case MEDIA_BUS_FMT_RGB666_1X18:
> -		reg |= CTRL_BUS_WIDTH_18;
> +		ctrl |= CTRL_BUS_WIDTH_18;
>  		break;
>  	case MEDIA_BUS_FMT_RGB888_1X24:
> -		reg |= CTRL_BUS_WIDTH_24;
> +		ctrl |= CTRL_BUS_WIDTH_24;
>  		break;
>  	default:
>  		dev_err(drm->dev, "Unknown media bus format %d\n", bus_format);
>  		break;
>  	}
> -	writel(reg, mxsfb->base + LCDC_CTRL);
> +
> +	writel(ctrl1, mxsfb->base + LCDC_CTRL1);
> +	writel(ctrl, mxsfb->base + LCDC_CTRL);
>  }
>  
>  static void mxsfb_enable_controller(struct mxsfb_drm_private *mxsfb)
> @@ -213,7 +206,7 @@ static void mxsfb_crtc_mode_set_nofb(struct
> mxsfb_drm_private *mxsfb)
>  	/* Clear the FIFOs */
>  	writel(CTRL1_FIFO_CLEAR, mxsfb->base + LCDC_CTRL1 + REG_SET);
>  
> -	mxsfb_set_pixel_fmt(mxsfb);
> +	mxsfb_set_formats(mxsfb);
>  
>  	clk_set_rate(mxsfb->clk, m->crtc_clock * 1000);
>  
> @@ -255,8 +248,6 @@ static void mxsfb_crtc_mode_set_nofb(struct
> mxsfb_drm_private *mxsfb)
>  
>  	writel(vdctrl0, mxsfb->base + LCDC_VDCTRL0);
>  
> -	mxsfb_set_bus_fmt(mxsfb);
> -
>  	/* Frame length in lines. */
>  	writel(m->crtc_vtotal, mxsfb->base + LCDC_VDCTRL1);
_______________________________________________
dri-devel mailing list
dri-devel@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/dri-devel

^ permalink raw reply	[flat|nested] 62+ messages in thread

* Re: [PATCH 21/21] drm: mxsfb: Support the alpha plane
  2020-03-09 19:52 ` [PATCH 21/21] drm: mxsfb: Support the alpha plane Laurent Pinchart
@ 2020-03-23 23:48   ` Stefan Agner
  2020-05-30  2:44     ` Laurent Pinchart
  0 siblings, 1 reply; 62+ messages in thread
From: Stefan Agner @ 2020-03-23 23:48 UTC (permalink / raw)
  To: Laurent Pinchart, leonard.crestez, robert.chiras
  Cc: Marek Vasut, kernel, dri-devel, linux-imx

On 2020-03-09 20:52, Laurent Pinchart wrote:
> The LCDIF in the i.MX6SX and i.MX7 have a second plane called the alpha
> plane. Support it.
> 
> Signed-off-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
> ---
>  drivers/gpu/drm/mxsfb/mxsfb_drv.c  |   3 +
>  drivers/gpu/drm/mxsfb/mxsfb_drv.h  |  16 ++--
>  drivers/gpu/drm/mxsfb/mxsfb_kms.c  | 129 +++++++++++++++++++++++++----
>  drivers/gpu/drm/mxsfb/mxsfb_regs.h |  22 +++++
>  4 files changed, 149 insertions(+), 21 deletions(-)
> 
> diff --git a/drivers/gpu/drm/mxsfb/mxsfb_drv.c
> b/drivers/gpu/drm/mxsfb/mxsfb_drv.c
> index ed8e3f7bc27c..ab3a212375f1 100644
> --- a/drivers/gpu/drm/mxsfb/mxsfb_drv.c
> +++ b/drivers/gpu/drm/mxsfb/mxsfb_drv.c
> @@ -49,6 +49,7 @@ static const struct mxsfb_devdata mxsfb_devdata[] = {
>  		.next_buf	= LCDC_V3_NEXT_BUF,
>  		.hs_wdth_mask	= 0xff,
>  		.hs_wdth_shift	= 24,
> +		.has_overlay	= false,
>  	},
>  	[MXSFB_V4] = {
>  		.transfer_count	= LCDC_V4_TRANSFER_COUNT,
> @@ -56,6 +57,7 @@ static const struct mxsfb_devdata mxsfb_devdata[] = {
>  		.next_buf	= LCDC_V4_NEXT_BUF,
>  		.hs_wdth_mask	= 0x3fff,
>  		.hs_wdth_shift	= 18,
> +		.has_overlay	= false,
>  	},
>  	[MXSFB_V6] = {
>  		.transfer_count	= LCDC_V4_TRANSFER_COUNT,
> @@ -63,6 +65,7 @@ static const struct mxsfb_devdata mxsfb_devdata[] = {
>  		.next_buf	= LCDC_V4_NEXT_BUF,
>  		.hs_wdth_mask	= 0x3fff,
>  		.hs_wdth_shift	= 18,
> +		.has_overlay	= true,
>  	},
>  };
>  
> diff --git a/drivers/gpu/drm/mxsfb/mxsfb_drv.h
> b/drivers/gpu/drm/mxsfb/mxsfb_drv.h
> index 607a6a5e6be3..399d23e91ed1 100644
> --- a/drivers/gpu/drm/mxsfb/mxsfb_drv.h
> +++ b/drivers/gpu/drm/mxsfb/mxsfb_drv.h
> @@ -16,11 +16,12 @@
>  struct clk;
>  
>  struct mxsfb_devdata {
> -	unsigned int	 transfer_count;
> -	unsigned int	 cur_buf;
> -	unsigned int	 next_buf;
> -	unsigned int	 hs_wdth_mask;
> -	unsigned int	 hs_wdth_shift;
> +	unsigned int	transfer_count;
> +	unsigned int	cur_buf;
> +	unsigned int	next_buf;
> +	unsigned int	hs_wdth_mask;
> +	unsigned int	hs_wdth_shift;

This seems an unrelated change, can you split that out?

> +	bool		has_overlay;
>  };
>  
>  struct mxsfb_drm_private {
> @@ -32,7 +33,10 @@ struct mxsfb_drm_private {
>  	struct clk			*clk_disp_axi;
>  
>  	struct drm_device		*drm;
> -	struct drm_plane		plane;
> +	struct {
> +		struct drm_plane	primary;
> +		struct drm_plane	overlay;
> +	} planes;
>  	struct drm_crtc			crtc;
>  	struct drm_encoder		encoder;
>  	struct drm_connector		*connector;
> diff --git a/drivers/gpu/drm/mxsfb/mxsfb_kms.c
> b/drivers/gpu/drm/mxsfb/mxsfb_kms.c
> index f81f8c222c13..c9c394f7cbe2 100644
> --- a/drivers/gpu/drm/mxsfb/mxsfb_kms.c
> +++ b/drivers/gpu/drm/mxsfb/mxsfb_kms.c
> @@ -169,9 +169,9 @@ static int mxsfb_reset_block(struct
> mxsfb_drm_private *mxsfb)
>  	return clear_poll_bit(mxsfb->base + LCDC_CTRL, CTRL_CLKGATE);
>  }
>  
> -static dma_addr_t mxsfb_get_fb_paddr(struct mxsfb_drm_private *mxsfb)
> +static dma_addr_t mxsfb_get_fb_paddr(struct drm_plane *plane)
>  {
> -	struct drm_framebuffer *fb = mxsfb->plane.state->fb;
> +	struct drm_framebuffer *fb = plane->state->fb;
>  	struct drm_gem_cma_object *gem;
>  
>  	if (!fb)
> @@ -206,6 +206,9 @@ static void mxsfb_crtc_mode_set_nofb(struct
> mxsfb_drm_private *mxsfb)
>  	/* Clear the FIFOs */
>  	writel(CTRL1_FIFO_CLEAR, mxsfb->base + LCDC_CTRL1 + REG_SET);
>  
> +	if (mxsfb->devdata->has_overlay)
> +		writel(0, mxsfb->base + LCDC_AS_CTRL);
> +
>  	mxsfb_set_formats(mxsfb);
>  
>  	clk_set_rate(mxsfb->clk, m->crtc_clock * 1000);
> @@ -313,7 +316,7 @@ static void mxsfb_crtc_atomic_enable(struct drm_crtc *crtc,
>  	mxsfb_crtc_mode_set_nofb(mxsfb);
>  
>  	/* Write cur_buf as well to avoid an initial corrupt frame */
> -	paddr = mxsfb_get_fb_paddr(mxsfb);
> +	paddr = mxsfb_get_fb_paddr(crtc->primary);
>  	if (paddr) {
>  		writel(paddr, mxsfb->base + mxsfb->devdata->cur_buf);
>  		writel(paddr, mxsfb->base + mxsfb->devdata->next_buf);
> @@ -410,20 +413,85 @@ static int mxsfb_plane_atomic_check(struct
> drm_plane *plane,
>  						   false, true);
>  }
>  
> -static void mxsfb_plane_atomic_update(struct drm_plane *plane,
> -				      struct drm_plane_state *old_pstate)
> +static void mxsfb_plane_primary_atomic_update(struct drm_plane *plane,
> +					      struct drm_plane_state *old_pstate)
>  {
>  	struct mxsfb_drm_private *mxsfb = to_mxsfb_drm_private(plane->dev);
>  	dma_addr_t paddr;
>  
> -	paddr = mxsfb_get_fb_paddr(mxsfb);
> +	paddr = mxsfb_get_fb_paddr(plane);
>  	if (paddr)
>  		writel(paddr, mxsfb->base + mxsfb->devdata->next_buf);
>  }
>  
> -static const struct drm_plane_helper_funcs mxsfb_plane_helper_funcs = {
> +static void mxsfb_plane_overlay_atomic_update(struct drm_plane *plane,
> +					      struct drm_plane_state *old_pstate)
> +{
> +	struct mxsfb_drm_private *mxsfb = to_mxsfb_drm_private(plane->dev);
> +	struct drm_plane_state *state = plane->state;
> +	dma_addr_t paddr;
> +	u32 ctrl;
> +
> +	paddr = mxsfb_get_fb_paddr(plane);
> +	if (!paddr) {
> +		writel(0, mxsfb->base + LCDC_AS_CTRL);
> +		return;
> +	}
> +
> +	/*
> +	 * HACK: The hardware seems to output 64 bytes of data of unknown
> +	 * origin, and then to proceed with the framebuffer. Until the reason
> +	 * is understood, live with the 16 initial invalid pixels on the first
> +	 * line and start 64 bytes within the framebuffer.
> +	 */
> +	paddr += 64;

Wow, that is interesting. Did you check/find downstream drivers which
support this feature and have some kind of hint/work around?

Also adding NXP folks, maybe you have some idea?

Otherwise I guess we live with this.

--
Stefan

> +
> +	writel(paddr, mxsfb->base + LCDC_AS_NEXT_BUF);
> +
> +	/*
> +	 * If the plane was previously disabled, write LCDC_AS_BUF as well to
> +	 * provide the first buffer.
> +	 */
> +	if (!old_pstate->fb)
> +		writel(paddr, mxsfb->base + LCDC_AS_BUF);
> +
> +	ctrl = AS_CTRL_AS_ENABLE | AS_CTRL_ALPHA(255);
> +
> +	switch (state->fb->format->format) {
> +	case DRM_FORMAT_XRGB4444:
> +		ctrl |= AS_CTRL_FORMAT_RGB444 | AS_CTRL_ALPHA_CTRL_OVERRIDE;
> +		break;
> +	case DRM_FORMAT_ARGB4444:
> +		ctrl |= AS_CTRL_FORMAT_ARGB4444 | AS_CTRL_ALPHA_CTRL_EMBEDDED;
> +		break;
> +	case DRM_FORMAT_XRGB1555:
> +		ctrl |= AS_CTRL_FORMAT_RGB555 | AS_CTRL_ALPHA_CTRL_OVERRIDE;
> +		break;
> +	case DRM_FORMAT_ARGB1555:
> +		ctrl |= AS_CTRL_FORMAT_ARGB1555 | AS_CTRL_ALPHA_CTRL_EMBEDDED;
> +		break;
> +	case DRM_FORMAT_RGB565:
> +		ctrl |= AS_CTRL_FORMAT_RGB565 | AS_CTRL_ALPHA_CTRL_OVERRIDE;
> +		break;
> +	case DRM_FORMAT_XRGB8888:
> +		ctrl |= AS_CTRL_FORMAT_RGB888 | AS_CTRL_ALPHA_CTRL_OVERRIDE;
> +		break;
> +	case DRM_FORMAT_ARGB8888:
> +		ctrl |= AS_CTRL_FORMAT_ARGB8888 | AS_CTRL_ALPHA_CTRL_EMBEDDED;
> +		break;
> +	}
> +
> +	writel(ctrl, mxsfb->base + LCDC_AS_CTRL);
> +}
> +
> +static const struct drm_plane_helper_funcs mxsfb_plane_primary_helper_funcs = {
> +	.atomic_check = mxsfb_plane_atomic_check,
> +	.atomic_update = mxsfb_plane_primary_atomic_update,
> +};
> +
> +static const struct drm_plane_helper_funcs mxsfb_plane_overlay_helper_funcs = {
>  	.atomic_check = mxsfb_plane_atomic_check,
> -	.atomic_update = mxsfb_plane_atomic_update,
> +	.atomic_update = mxsfb_plane_overlay_atomic_update,
>  };
>  
>  static const struct drm_plane_funcs mxsfb_plane_funcs = {
> @@ -435,27 +503,58 @@ static const struct drm_plane_funcs mxsfb_plane_funcs = {
>  	.atomic_destroy_state	= drm_atomic_helper_plane_destroy_state,
>  };
>  
> -static const uint32_t mxsfb_formats[] = {
> +static const uint32_t mxsfb_primary_plane_formats[] = {
> +	DRM_FORMAT_RGB565,
> +	DRM_FORMAT_XRGB8888,
> +};
> +
> +static const uint32_t mxsfb_overlay_plane_formats[] = {
> +	DRM_FORMAT_XRGB4444,
> +	DRM_FORMAT_ARGB4444,
> +	DRM_FORMAT_XRGB1555,
> +	DRM_FORMAT_ARGB1555,
> +	DRM_FORMAT_RGB565,
>  	DRM_FORMAT_XRGB8888,
> -	DRM_FORMAT_RGB565
> +	DRM_FORMAT_ARGB8888,
>  };
>  
> +/*
> -----------------------------------------------------------------------------
> + * Initialization
> + */
> +
>  int mxsfb_kms_init(struct mxsfb_drm_private *mxsfb)
>  {
>  	struct drm_encoder *encoder = &mxsfb->encoder;
> -	struct drm_plane *plane = &mxsfb->plane;
>  	struct drm_crtc *crtc = &mxsfb->crtc;
>  	int ret;
>  
> -	drm_plane_helper_add(plane, &mxsfb_plane_helper_funcs);
> -	ret = drm_universal_plane_init(mxsfb->drm, plane, 0, &mxsfb_plane_funcs,
> -				       mxsfb_formats, ARRAY_SIZE(mxsfb_formats),
> +	drm_plane_helper_add(&mxsfb->planes.primary,
> +			     &mxsfb_plane_primary_helper_funcs);
> +	ret = drm_universal_plane_init(mxsfb->drm, &mxsfb->planes.primary, 1,
> +				       &mxsfb_plane_funcs,
> +				       mxsfb_primary_plane_formats,
> +				       ARRAY_SIZE(mxsfb_primary_plane_formats),
>  				       NULL, DRM_PLANE_TYPE_PRIMARY, NULL);
>  	if (ret)
>  		return ret;
>  
> +	if (mxsfb->devdata->has_overlay) {
> +		drm_plane_helper_add(&mxsfb->planes.overlay,
> +				     &mxsfb_plane_overlay_helper_funcs);
> +		ret = drm_universal_plane_init(mxsfb->drm,
> +					       &mxsfb->planes.overlay, 1,
> +					       &mxsfb_plane_funcs,
> +					       mxsfb_overlay_plane_formats,
> +					       ARRAY_SIZE(mxsfb_overlay_plane_formats),
> +					       NULL, DRM_PLANE_TYPE_OVERLAY,
> +					       NULL);
> +		if (ret)
> +			return ret;
> +	}
> +
>  	drm_crtc_helper_add(crtc, &mxsfb_crtc_helper_funcs);
> -	ret = drm_crtc_init_with_planes(mxsfb->drm, crtc, plane, NULL,
> +	ret = drm_crtc_init_with_planes(mxsfb->drm, crtc,
> +					&mxsfb->planes.primary, NULL,
>  					&mxsfb_crtc_funcs, NULL);
>  	if (ret)
>  		return ret;
> diff --git a/drivers/gpu/drm/mxsfb/mxsfb_regs.h
> b/drivers/gpu/drm/mxsfb/mxsfb_regs.h
> index 8ebb52bb1b46..55d28a27f912 100644
> --- a/drivers/gpu/drm/mxsfb/mxsfb_regs.h
> +++ b/drivers/gpu/drm/mxsfb/mxsfb_regs.h
> @@ -27,6 +27,11 @@
>  #define LCDC_VDCTRL4			0xb0
>  #define LCDC_V4_DEBUG0			0x1d0
>  #define LCDC_V3_DEBUG0			0x1f0
> +#define LCDC_AS_CTRL			0x210
> +#define LCDC_AS_BUF			0x220
> +#define LCDC_AS_NEXT_BUF		0x230
> +#define LCDC_AS_CLRKEYLOW		0x240
> +#define LCDC_AS_CLRKEYHIGH		0x250
>  
>  #define CTRL_SFTRST			BIT(31)
>  #define CTRL_CLKGATE			BIT(30)
> @@ -90,6 +95,23 @@
>  #define DEBUG0_HSYNC			BIT(26)
>  #define DEBUG0_VSYNC			BIT(25)
>  
> +#define AS_CTRL_PS_DISABLE		BIT(23)
> +#define AS_CTRL_ALPHA_INVERT		BIT(20)
> +#define AS_CTRL_ALPHA(a)		(((a) & 0xff) << 8)
> +#define AS_CTRL_FORMAT_RGB565		(0xe << 4)
> +#define AS_CTRL_FORMAT_RGB444		(0xd << 4)
> +#define AS_CTRL_FORMAT_RGB555		(0xc << 4)
> +#define AS_CTRL_FORMAT_ARGB4444		(0x9 << 4)
> +#define AS_CTRL_FORMAT_ARGB1555		(0x8 << 4)
> +#define AS_CTRL_FORMAT_RGB888		(0x4 << 4)
> +#define AS_CTRL_FORMAT_ARGB8888		(0x0 << 4)
> +#define AS_CTRL_ENABLE_COLORKEY		BIT(3)
> +#define AS_CTRL_ALPHA_CTRL_ROP		(3 << 1)
> +#define AS_CTRL_ALPHA_CTRL_MULTIPLY	(2 << 1)
> +#define AS_CTRL_ALPHA_CTRL_OVERRIDE	(1 << 1)
> +#define AS_CTRL_ALPHA_CTRL_EMBEDDED	(0 << 1)
> +#define AS_CTRL_AS_ENABLE		BIT(0)
> +
>  #define MXSFB_MIN_XRES			120
>  #define MXSFB_MIN_YRES			120
>  #define MXSFB_MAX_XRES			0xffff
_______________________________________________
dri-devel mailing list
dri-devel@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/dri-devel

^ permalink raw reply	[flat|nested] 62+ messages in thread

* Re: [PATCH 02/21] drm: mxsfb: Use drm_panel_bridge
  2020-03-23 21:38     ` Sam Ravnborg
@ 2020-03-23 23:50       ` Stefan Agner
  0 siblings, 0 replies; 62+ messages in thread
From: Stefan Agner @ 2020-03-23 23:50 UTC (permalink / raw)
  To: Sam Ravnborg; +Cc: Marek Vasut, dri-devel, Laurent Pinchart, kernel, linux-imx

On 2020-03-23 22:38, Sam Ravnborg wrote:
> Hi Stefan.
> 
> On Mon, Mar 23, 2020 at 10:27:21PM +0100, Stefan Agner wrote:
>> On 2020-03-09 20:51, Laurent Pinchart wrote:
>> > Replace the manual connector implementation based on drm_panel with the
>> > drm_panel_bridge helper. This simplifies the mxsfb driver by removing
>> > connector-related code, and standardizing all pipeline control
>> > operations on bridges.
>> >
>> > A hack is needed to get hold of the connector, as that's our only source
>> > of bus flags and formats for now. As soon as the bridge API provides us
>> > with that information this can be fixed.
>>
>> This seems like a nice simplification.
>>
>> I gave this a go applied on today's drm-misc-next using a Colibri iMX7
>> (imx7d-colibri-emmc-eval-v3.dts device tree). This device makes use of
>> the simple panel driver. I get this when booting:
>>
>> [    2.976698] [drm] Supports vblank timestamp caching Rev 2
>> (21.10.2013).
>> [    2.983526] ------------[ cut here ]------------
>> [    2.988180] WARNING: CPU: 0 PID: 1 at
>> drivers/gpu/drm/bridge/panel.c:267 devm_drm_panel_bridge_add+0x25/0x28
> 
> ...
> 
> I think you hit one of the panels that does not yet specify a
> connector_type.
> 
> If this is the case, we should fix the definition in panel-simple.

Yes, this indeed the case, I used the "logictechno,lt161010-2nhc"
compatible string. Will get this fixed!

But I think its still worth defining a default in the driver as DPI is
what this IP outputs...

--
Stefan
_______________________________________________
dri-devel mailing list
dri-devel@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/dri-devel

^ permalink raw reply	[flat|nested] 62+ messages in thread

* Re: [PATCH 14/21] drm: mxsfb: Enable vblank handling
  2020-03-23 23:08   ` Stefan Agner
@ 2020-03-24 10:37     ` Stefan Agner
  0 siblings, 0 replies; 62+ messages in thread
From: Stefan Agner @ 2020-03-24 10:37 UTC (permalink / raw)
  To: Laurent Pinchart; +Cc: Marek Vasut, kernel, dri-devel, linux-imx

On 2020-03-24 00:08, Stefan Agner wrote:
> On 2020-03-09 20:52, Laurent Pinchart wrote:
>> Enable vblank handling when the CRTC is turned on and disable it when it
>> is turned off. This requires moving vblank init after the KMS pipeline
>> initialisation, otherwise drm_vblank_init() gets called with 0 CRTCs.
>>
>> Signed-off-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
> 
> With this patch applied I start to get system resets on my Colibri iMX7
> test device during system boot shortly after initializing mxsfb. It
> happens not on every boot, but rather often, I would say every second or
> third. From what I can tell the interrupt handling should be safe, but
> it seems that every now and then something races. Any idea what that
> could be?

Disregard this: It seems that my power supply was a bit too weak which
lead to the system reset every now and then. With enough juice, I run
now quite some boots with the complete patchset applied without seeing
any issues.

Sorry about that.

--
Stefan

> 
> --
> Stefan
> 
>> ---
>>  drivers/gpu/drm/mxsfb/mxsfb_drv.c | 15 +++++++++------
>>  drivers/gpu/drm/mxsfb/mxsfb_kms.c |  6 +++++-
>>  2 files changed, 14 insertions(+), 7 deletions(-)
>>
>> diff --git a/drivers/gpu/drm/mxsfb/mxsfb_drv.c
>> b/drivers/gpu/drm/mxsfb/mxsfb_drv.c
>> index e324bd2a63a5..72b4f6a947a4 100644
>> --- a/drivers/gpu/drm/mxsfb/mxsfb_drv.c
>> +++ b/drivers/gpu/drm/mxsfb/mxsfb_drv.c
>> @@ -160,12 +160,6 @@ static int mxsfb_load(struct drm_device *drm,
>> unsigned long flags)
>>
>>  	pm_runtime_enable(drm->dev);
>>
>> -	ret = drm_vblank_init(drm, drm->mode_config.num_crtc);
>> -	if (ret < 0) {
>> -		dev_err(drm->dev, "Failed to initialise vblank\n");
>> -		goto err_vblank;
>> -	}
>> -
>>  	/* Modeset init */
>>  	drm_mode_config_init(drm);
>>
>> @@ -175,6 +169,15 @@ static int mxsfb_load(struct drm_device *drm,
>> unsigned long flags)
>>  		goto err_vblank;
>>  	}
>>
>> +	ret = drm_vblank_init(drm, drm->mode_config.num_crtc);
>> +	if (ret < 0) {
>> +		dev_err(drm->dev, "Failed to initialise vblank\n");
>> +		goto err_vblank;
>> +	}
>> +
>> +	/* Start with vertical blanking interrupt reporting disabled. */
>> +	drm_crtc_vblank_off(&mxsfb->crtc);
>> +
>>  	ret = mxsfb_attach_bridge(mxsfb);
>>  	if (ret) {
>>  		dev_err(drm->dev, "Cannot connect bridge: %d\n", ret);
>> diff --git a/drivers/gpu/drm/mxsfb/mxsfb_kms.c
>> b/drivers/gpu/drm/mxsfb/mxsfb_kms.c
>> index ac2696c8483d..640305fb1068 100644
>> --- a/drivers/gpu/drm/mxsfb/mxsfb_kms.c
>> +++ b/drivers/gpu/drm/mxsfb/mxsfb_kms.c
>> @@ -322,8 +322,10 @@ static void mxsfb_crtc_atomic_enable(struct drm_crtc *crtc,
>>  	dma_addr_t paddr;
>>
>>  	pm_runtime_get_sync(drm->dev);
>> -
>>  	mxsfb_enable_axi_clk(mxsfb);
>> +
>> +	drm_crtc_vblank_on(crtc);
>> +
>>  	mxsfb_crtc_mode_set_nofb(mxsfb);
>>
>>  	/* Write cur_buf as well to avoid an initial corrupt frame */
>> @@ -353,6 +355,8 @@ static void mxsfb_crtc_atomic_disable(struct drm_crtc *crtc,
>>  	}
>>  	spin_unlock_irq(&drm->event_lock);
>>
>> +	drm_crtc_vblank_off(crtc);
>> +
>>  	mxsfb_disable_axi_clk(mxsfb);
>>  	pm_runtime_put_sync(drm->dev);
>>  }
_______________________________________________
dri-devel mailing list
dri-devel@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/dri-devel

^ permalink raw reply	[flat|nested] 62+ messages in thread

* Re: [PATCH 00/21] drm: mxsfb: Add i.MX7 support
  2020-03-09 19:51 [PATCH 00/21] drm: mxsfb: Add i.MX7 support Laurent Pinchart
                   ` (21 preceding siblings ...)
  2020-03-19  9:36 ` [PATCH 00/21] drm: mxsfb: Add i.MX7 support Laurent Pinchart
@ 2020-04-12 16:37 ` Guido Günther
  2020-05-26 15:13 ` Stefan Agner
  23 siblings, 0 replies; 62+ messages in thread
From: Guido Günther @ 2020-04-12 16:37 UTC (permalink / raw)
  To: Laurent Pinchart; +Cc: Marek Vasut, kernel, dri-devel, linux-imx

Hi,
On Mon, Mar 09, 2020 at 09:51:55PM +0200, Laurent Pinchart wrote:
> Hello,
> 
> This patch series adds i.MX7 support to the mxsfb driver. The eLCDIF
> instance found in the i.MX7 is backward-compatible with the already
> supported LCDC v4, but has extended features amongst which the most
> notable one is a second plane.
> 
> The first 9 patches (01/21 to 09/21) contain miscellaneous cleanups and
> refactoring to prepare for what is to come. Patch 10/21 starts the real
> work with removal of the DRM simple display pipeline helper, as it
> doesn't support multiple planes. The next patch (11/21) is an additional
> cleanup.
> 
> Patches 12/21 to 14/21 fix vblank handling that I found to be broken
> when testing on my device. Patch 15/21 then performs an additional small
> cleanup, and patch 16/21 starts official support for i.MX7 by mentioning
> it in Kconfig.
> 
> Patch 17/21 adds a new device model for the i.MX6SX and i.MX7 eLCDIF.
> After three additional cleanups in patches 18/21 to 20/21, patch 21/21
> finally adds support for the second plane.
> 
> The code is based on drm-misc-next and has been tested on an i.MX7D
> platform with a DPI panel.

I've tested this with an imx8mq using both the current fsl,imx28-lcdif
and fsl,imx6sx-lcdif with the nwl DSI bridge and a dsi panel and both
worked well.
Cheers,
 -- Guido

> 
> Laurent Pinchart (21):
>   drm: mxsfb: Remove fbdev leftovers
>   drm: mxsfb: Use drm_panel_bridge
>   drm: mxsfb: Use BIT() macro to define register bitfields
>   drm: mxsfb: Remove unused macros from mxsfb_regs.h
>   drm: mxsfb: Clarify format and bus width configuration
>   drm: mxsfb: Pass mxsfb_drm_private pointer to mxsfb_reset_block()
>   drm: mxsfb: Use LCDC_CTRL register name explicitly
>   drm: mxsfb: Remove register definitions from mxsfb_crtc.c
>   drm: mxsfb: Remove unneeded includes
>   drm: mxsfb: Stop using DRM simple display pipeline helper
>   drm: mxsfb: Rename mxsfb_crtc.c to mxsfb_kms.c
>   drm: mxsfb: Move vblank event arm to CRTC .atomic_flush()
>   drm: mxsfb: Don't touch AXI clock in IRQ context
>   drm: mxsfb: Enable vblank handling
>   drm: mxsfb: Remove mxsfb_devdata unused fields
>   drm: mxsfb: Add i.MX7 to the list of supported SoCs in Kconfig
>   drm: mxsfb: Update internal IP version number for i.MX6SX
>   drm: mxsfb: Drop non-OF support
>   drm: mxsfb: Turn mxsfb_set_pixel_fmt() into a void function
>   drm: mxsfb: Merge mxsfb_set_pixel_fmt() and mxsfb_set_bus_fmt()
>   drm: mxsfb: Support the alpha plane
> 
>  drivers/gpu/drm/mxsfb/Kconfig      |   4 +-
>  drivers/gpu/drm/mxsfb/Makefile     |   2 +-
>  drivers/gpu/drm/mxsfb/mxsfb_crtc.c | 343 -----------------
>  drivers/gpu/drm/mxsfb/mxsfb_drv.c  | 246 ++++---------
>  drivers/gpu/drm/mxsfb/mxsfb_drv.h  |  42 ++-
>  drivers/gpu/drm/mxsfb/mxsfb_kms.c  | 565 +++++++++++++++++++++++++++++
>  drivers/gpu/drm/mxsfb/mxsfb_out.c  |  99 -----
>  drivers/gpu/drm/mxsfb/mxsfb_regs.h | 107 +++---
>  8 files changed, 730 insertions(+), 678 deletions(-)
>  delete mode 100644 drivers/gpu/drm/mxsfb/mxsfb_crtc.c
>  create mode 100644 drivers/gpu/drm/mxsfb/mxsfb_kms.c
>  delete mode 100644 drivers/gpu/drm/mxsfb/mxsfb_out.c
> 
> -- 
> Regards,
> 
> Laurent Pinchart
> 
> _______________________________________________
> dri-devel mailing list
> dri-devel@lists.freedesktop.org
> https://lists.freedesktop.org/mailman/listinfo/dri-devel
> 
_______________________________________________
dri-devel mailing list
dri-devel@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/dri-devel

^ permalink raw reply	[flat|nested] 62+ messages in thread

* Re: [PATCH 00/21] drm: mxsfb: Add i.MX7 support
  2020-03-09 19:51 [PATCH 00/21] drm: mxsfb: Add i.MX7 support Laurent Pinchart
                   ` (22 preceding siblings ...)
  2020-04-12 16:37 ` Guido Günther
@ 2020-05-26 15:13 ` Stefan Agner
  2020-05-30  0:29   ` Laurent Pinchart
  23 siblings, 1 reply; 62+ messages in thread
From: Stefan Agner @ 2020-05-26 15:13 UTC (permalink / raw)
  To: Laurent Pinchart; +Cc: Marek Vasut, kernel, dri-devel, linux-imx

Hi Laurent,

On 2020-03-09 20:51, Laurent Pinchart wrote:
> Hello,
> 
> This patch series adds i.MX7 support to the mxsfb driver. The eLCDIF
> instance found in the i.MX7 is backward-compatible with the already
> supported LCDC v4, but has extended features amongst which the most
> notable one is a second plane.
> 
> The first 9 patches (01/21 to 09/21) contain miscellaneous cleanups and
> refactoring to prepare for what is to come. Patch 10/21 starts the real
> work with removal of the DRM simple display pipeline helper, as it
> doesn't support multiple planes. The next patch (11/21) is an additional
> cleanup.
> 
> Patches 12/21 to 14/21 fix vblank handling that I found to be broken
> when testing on my device. Patch 15/21 then performs an additional small
> cleanup, and patch 16/21 starts official support for i.MX7 by mentioning
> it in Kconfig.
> 
> Patch 17/21 adds a new device model for the i.MX6SX and i.MX7 eLCDIF.
> After three additional cleanups in patches 18/21 to 20/21, patch 21/21
> finally adds support for the second plane.
> 
> The code is based on drm-misc-next and has been tested on an i.MX7D
> platform with a DPI panel.

Did you plan to update this series? I guess some of the changes I could
already merge now.

--
Stefan

> 
> Laurent Pinchart (21):
>   drm: mxsfb: Remove fbdev leftovers
>   drm: mxsfb: Use drm_panel_bridge
>   drm: mxsfb: Use BIT() macro to define register bitfields
>   drm: mxsfb: Remove unused macros from mxsfb_regs.h
>   drm: mxsfb: Clarify format and bus width configuration
>   drm: mxsfb: Pass mxsfb_drm_private pointer to mxsfb_reset_block()
>   drm: mxsfb: Use LCDC_CTRL register name explicitly
>   drm: mxsfb: Remove register definitions from mxsfb_crtc.c
>   drm: mxsfb: Remove unneeded includes
>   drm: mxsfb: Stop using DRM simple display pipeline helper
>   drm: mxsfb: Rename mxsfb_crtc.c to mxsfb_kms.c
>   drm: mxsfb: Move vblank event arm to CRTC .atomic_flush()
>   drm: mxsfb: Don't touch AXI clock in IRQ context
>   drm: mxsfb: Enable vblank handling
>   drm: mxsfb: Remove mxsfb_devdata unused fields
>   drm: mxsfb: Add i.MX7 to the list of supported SoCs in Kconfig
>   drm: mxsfb: Update internal IP version number for i.MX6SX
>   drm: mxsfb: Drop non-OF support
>   drm: mxsfb: Turn mxsfb_set_pixel_fmt() into a void function
>   drm: mxsfb: Merge mxsfb_set_pixel_fmt() and mxsfb_set_bus_fmt()
>   drm: mxsfb: Support the alpha plane
> 
>  drivers/gpu/drm/mxsfb/Kconfig      |   4 +-
>  drivers/gpu/drm/mxsfb/Makefile     |   2 +-
>  drivers/gpu/drm/mxsfb/mxsfb_crtc.c | 343 -----------------
>  drivers/gpu/drm/mxsfb/mxsfb_drv.c  | 246 ++++---------
>  drivers/gpu/drm/mxsfb/mxsfb_drv.h  |  42 ++-
>  drivers/gpu/drm/mxsfb/mxsfb_kms.c  | 565 +++++++++++++++++++++++++++++
>  drivers/gpu/drm/mxsfb/mxsfb_out.c  |  99 -----
>  drivers/gpu/drm/mxsfb/mxsfb_regs.h | 107 +++---
>  8 files changed, 730 insertions(+), 678 deletions(-)
>  delete mode 100644 drivers/gpu/drm/mxsfb/mxsfb_crtc.c
>  create mode 100644 drivers/gpu/drm/mxsfb/mxsfb_kms.c
>  delete mode 100644 drivers/gpu/drm/mxsfb/mxsfb_out.c
_______________________________________________
dri-devel mailing list
dri-devel@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/dri-devel

^ permalink raw reply	[flat|nested] 62+ messages in thread

* Re: [PATCH 00/21] drm: mxsfb: Add i.MX7 support
  2020-05-26 15:13 ` Stefan Agner
@ 2020-05-30  0:29   ` Laurent Pinchart
  0 siblings, 0 replies; 62+ messages in thread
From: Laurent Pinchart @ 2020-05-30  0:29 UTC (permalink / raw)
  To: Stefan Agner; +Cc: Marek Vasut, kernel, dri-devel, linux-imx

Hi Stefan,

On Tue, May 26, 2020 at 05:13:42PM +0200, Stefan Agner wrote:
> On 2020-03-09 20:51, Laurent Pinchart wrote:
> > Hello,
> > 
> > This patch series adds i.MX7 support to the mxsfb driver. The eLCDIF
> > instance found in the i.MX7 is backward-compatible with the already
> > supported LCDC v4, but has extended features amongst which the most
> > notable one is a second plane.
> > 
> > The first 9 patches (01/21 to 09/21) contain miscellaneous cleanups and
> > refactoring to prepare for what is to come. Patch 10/21 starts the real
> > work with removal of the DRM simple display pipeline helper, as it
> > doesn't support multiple planes. The next patch (11/21) is an additional
> > cleanup.
> > 
> > Patches 12/21 to 14/21 fix vblank handling that I found to be broken
> > when testing on my device. Patch 15/21 then performs an additional small
> > cleanup, and patch 16/21 starts official support for i.MX7 by mentioning
> > it in Kconfig.
> > 
> > Patch 17/21 adds a new device model for the i.MX6SX and i.MX7 eLCDIF.
> > After three additional cleanups in patches 18/21 to 20/21, patch 21/21
> > finally adds support for the second plane.
> > 
> > The code is based on drm-misc-next and has been tested on an i.MX7D
> > platform with a DPI panel.
> 
> Did you plan to update this series? I guess some of the changes I could
> already merge now.

I'm resuming work on it now, will incorporate your review comments and
send a v2. Feel free to apply some of the changes already if you want
to.

> > Laurent Pinchart (21):
> >   drm: mxsfb: Remove fbdev leftovers
> >   drm: mxsfb: Use drm_panel_bridge
> >   drm: mxsfb: Use BIT() macro to define register bitfields
> >   drm: mxsfb: Remove unused macros from mxsfb_regs.h
> >   drm: mxsfb: Clarify format and bus width configuration
> >   drm: mxsfb: Pass mxsfb_drm_private pointer to mxsfb_reset_block()
> >   drm: mxsfb: Use LCDC_CTRL register name explicitly
> >   drm: mxsfb: Remove register definitions from mxsfb_crtc.c
> >   drm: mxsfb: Remove unneeded includes
> >   drm: mxsfb: Stop using DRM simple display pipeline helper
> >   drm: mxsfb: Rename mxsfb_crtc.c to mxsfb_kms.c
> >   drm: mxsfb: Move vblank event arm to CRTC .atomic_flush()
> >   drm: mxsfb: Don't touch AXI clock in IRQ context
> >   drm: mxsfb: Enable vblank handling
> >   drm: mxsfb: Remove mxsfb_devdata unused fields
> >   drm: mxsfb: Add i.MX7 to the list of supported SoCs in Kconfig
> >   drm: mxsfb: Update internal IP version number for i.MX6SX
> >   drm: mxsfb: Drop non-OF support
> >   drm: mxsfb: Turn mxsfb_set_pixel_fmt() into a void function
> >   drm: mxsfb: Merge mxsfb_set_pixel_fmt() and mxsfb_set_bus_fmt()
> >   drm: mxsfb: Support the alpha plane
> > 
> >  drivers/gpu/drm/mxsfb/Kconfig      |   4 +-
> >  drivers/gpu/drm/mxsfb/Makefile     |   2 +-
> >  drivers/gpu/drm/mxsfb/mxsfb_crtc.c | 343 -----------------
> >  drivers/gpu/drm/mxsfb/mxsfb_drv.c  | 246 ++++---------
> >  drivers/gpu/drm/mxsfb/mxsfb_drv.h  |  42 ++-
> >  drivers/gpu/drm/mxsfb/mxsfb_kms.c  | 565 +++++++++++++++++++++++++++++
> >  drivers/gpu/drm/mxsfb/mxsfb_out.c  |  99 -----
> >  drivers/gpu/drm/mxsfb/mxsfb_regs.h | 107 +++---
> >  8 files changed, 730 insertions(+), 678 deletions(-)
> >  delete mode 100644 drivers/gpu/drm/mxsfb/mxsfb_crtc.c
> >  create mode 100644 drivers/gpu/drm/mxsfb/mxsfb_kms.c
> >  delete mode 100644 drivers/gpu/drm/mxsfb/mxsfb_out.c

-- 
Regards,

Laurent Pinchart
_______________________________________________
dri-devel mailing list
dri-devel@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/dri-devel

^ permalink raw reply	[flat|nested] 62+ messages in thread

* Re: [PATCH 09/21] drm: mxsfb: Remove unneeded includes
  2020-03-23 21:53   ` Stefan Agner
@ 2020-05-30  0:33     ` Laurent Pinchart
  0 siblings, 0 replies; 62+ messages in thread
From: Laurent Pinchart @ 2020-05-30  0:33 UTC (permalink / raw)
  To: Stefan Agner; +Cc: Marek Vasut, kernel, dri-devel, linux-imx

Hi Stefan,

On Mon, Mar 23, 2020 at 10:53:50PM +0100, Stefan Agner wrote:
> On 2020-03-09 20:52, Laurent Pinchart wrote:
> > A fair number of includes are not needed. Drop them, and add a couple of
> > required includes that were included indirectly.
> > 
> > Signed-off-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
> 
> Out of curiosity, do you have some kind of tool helping with this?

No, that was manual.

> Reviewed-by: Stefan Agner <stefan@agner.ch>
> 
> > ---
> >  drivers/gpu/drm/mxsfb/mxsfb_crtc.c | 12 +++---------
> >  drivers/gpu/drm/mxsfb/mxsfb_drv.c  |  5 -----
> >  2 files changed, 3 insertions(+), 14 deletions(-)
> > 
> > diff --git a/drivers/gpu/drm/mxsfb/mxsfb_crtc.c
> > b/drivers/gpu/drm/mxsfb/mxsfb_crtc.c
> > index aef72adabf41..c4f1575b4210 100644
> > --- a/drivers/gpu/drm/mxsfb/mxsfb_crtc.c
> > +++ b/drivers/gpu/drm/mxsfb/mxsfb_crtc.c
> > @@ -10,19 +10,13 @@
> >  
> >  #include <linux/clk.h>
> >  #include <linux/iopoll.h>
> > -#include <linux/of_graph.h>
> > -#include <linux/platform_data/simplefb.h>
> > +#include <linux/spinlock.h>
> >  
> > -#include <video/videomode.h>
> > -
> > -#include <drm/drm_atomic_helper.h>
> > +#include <drm/drm_bridge.h>
> >  #include <drm/drm_crtc.h>
> >  #include <drm/drm_fb_cma_helper.h>
> > -#include <drm/drm_fb_helper.h>
> > +#include <drm/drm_fourcc.h>
> >  #include <drm/drm_gem_cma_helper.h>
> > -#include <drm/drm_of.h>
> > -#include <drm/drm_plane_helper.h>
> > -#include <drm/drm_probe_helper.h>
> >  #include <drm/drm_simple_kms_helper.h>
> >  #include <drm/drm_vblank.h>
> >  
> > diff --git a/drivers/gpu/drm/mxsfb/mxsfb_drv.c
> > b/drivers/gpu/drm/mxsfb/mxsfb_drv.c
> > index cffc70257bd3..204c1e52e9aa 100644
> > --- a/drivers/gpu/drm/mxsfb/mxsfb_drv.c
> > +++ b/drivers/gpu/drm/mxsfb/mxsfb_drv.c
> > @@ -9,15 +9,10 @@
> >   */
> >  
> >  #include <linux/clk.h>
> > -#include <linux/component.h>
> >  #include <linux/dma-mapping.h>
> > -#include <linux/list.h>
> >  #include <linux/module.h>
> >  #include <linux/of_device.h>
> > -#include <linux/of_graph.h>
> > -#include <linux/of_reserved_mem.h>
> >  #include <linux/pm_runtime.h>
> > -#include <linux/dma-resv.h>
> >  #include <linux/spinlock.h>
> >  
> >  #include <drm/drm_atomic.h>

-- 
Regards,

Laurent Pinchart
_______________________________________________
dri-devel mailing list
dri-devel@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/dri-devel

^ permalink raw reply	[flat|nested] 62+ messages in thread

* Re: [PATCH 02/21] drm: mxsfb: Use drm_panel_bridge
  2020-03-23 21:27   ` Stefan Agner
  2020-03-23 21:38     ` Sam Ravnborg
@ 2020-05-30  2:14     ` Laurent Pinchart
  2020-06-02 13:12       ` Daniel Vetter
  1 sibling, 1 reply; 62+ messages in thread
From: Laurent Pinchart @ 2020-05-30  2:14 UTC (permalink / raw)
  To: Stefan Agner; +Cc: Marek Vasut, kernel, dri-devel, linux-imx

Hi Stefan,

On Mon, Mar 23, 2020 at 10:27:21PM +0100, Stefan Agner wrote:
> On 2020-03-09 20:51, Laurent Pinchart wrote:
> > Replace the manual connector implementation based on drm_panel with the
> > drm_panel_bridge helper. This simplifies the mxsfb driver by removing
> > connector-related code, and standardizing all pipeline control
> > operations on bridges.
> > 
> > A hack is needed to get hold of the connector, as that's our only source
> > of bus flags and formats for now. As soon as the bridge API provides us
> > with that information this can be fixed.
> 
> This seems like a nice simplification.
> 
> I gave this a go applied on today's drm-misc-next using a Colibri iMX7
> (imx7d-colibri-emmc-eval-v3.dts device tree). This device makes use of
> the simple panel driver. I get this when booting:
> 
> [    2.976698] [drm] Supports vblank timestamp caching Rev 2
> (21.10.2013).
> [    2.983526] ------------[ cut here ]------------
> [    2.988180] WARNING: CPU: 0 PID: 1 at
> drivers/gpu/drm/bridge/panel.c:267 devm_drm_panel_bridge_add+0x25/0x28
> [    2.998059] Modules linked in:
> [    3.001159] CPU: 0 PID: 1 Comm: swapper/0 Not tainted
> 5.6.0-rc5-yocto-standard-01250-ga4ce5db7c9f1 #29
> [    3.010493] Hardware name: Freescale i.MX7 Dual (Device Tree)
> [    3.016281] [<c010f089>] (unwind_backtrace) from [<c010a9bb>]
> (show_stack+0xb/0xc)
> [    3.023887] [<c010a9bb>] (show_stack) from [<c08b33cf>]
> (dump_stack+0x63/0x70)
> [    3.031144] [<c08b33cf>] (dump_stack) from [<c0124385>]
> (__warn+0x9d/0xb0)
> [    3.038047] [<c0124385>] (__warn) from [<c0124403>]
> (warn_slowpath_fmt+0x6b/0x70)
> [    3.045564] [<c0124403>] (warn_slowpath_fmt) from [<c04ebf65>]
> (devm_drm_panel_bridge_add+0x25/0x28)
> [    3.054736] [<c04ebf65>] (devm_drm_panel_bridge_add) from
> [<c051fe7f>] (mxsfb_probe+0x197/0x2e0)
> [    3.063559] [<c051fe7f>] (mxsfb_probe) from [<c0532e91>]
> (platform_drv_probe+0x2d/0x60)
> [    3.071598] [<c0532e91>] (platform_drv_probe) from [<c0531615>]
> (really_probe+0x1dd/0x330)
> [    3.079897] [<c0531615>] (really_probe) from [<c05318b3>]
> (driver_probe_device+0x4f/0x154)
> [    3.088195] [<c05318b3>] (driver_probe_device) from [<c0531b3f>]
> (device_driver_attach+0x37/0x44)
> [    3.097101] [<c0531b3f>] (device_driver_attach) from [<c0531bc7>]
> (__driver_attach+0x7b/0xec)
> [    3.105660] [<c0531bc7>] (__driver_attach) from [<c0530069>]
> (bus_for_each_dev+0x3d/0x64)
> [    3.113870] [<c0530069>] (bus_for_each_dev) from [<c0530b9b>]
> (bus_add_driver+0xef/0x160)
> [    3.122081] [<c0530b9b>] (bus_add_driver) from [<c053238d>]
> (driver_register+0x35/0x9c)
> [    3.130119] [<c053238d>] (driver_register) from [<c0102de9>]
> (do_one_initcall+0x3d/0x1e4)
> [    3.138333] [<c0102de9>] (do_one_initcall) from [<c1100d13>]
> (kernel_init_freeable+0x1b3/0x1fc)
> [    3.147069] [<c1100d13>] (kernel_init_freeable) from [<c08c3f7b>]
> (kernel_init+0x7/0xd0)
> [    3.155194] [<c08c3f7b>] (kernel_init) from [<c01010f9>]
> (ret_from_fork+0x11/0x38)
> [    3.162789] Exception stack(0xec0e3fb0 to 0xec0e3ff8)
> [    3.167862] 3fa0:                                     00000000
> 00000000 00000000 00000000
> [    3.176071] 3fc0: 00000000 00000000 00000000 00000000 00000000
> 00000000 00000000 00000000
> [    3.184278] 3fe0: 00000000 00000000 00000000 00000000 00000013
> 00000000
> [    3.191029] ---[ end trace b69e1f44de470959 ]---
> [    3.195671] mxsfb 30730000.lcdif: Cannot connect bridge: -19
> 
> Should we maybe use devm_drm_panel_bridge_add_typed?

As Sam reported, this is caused by the panel not setting connector_type.
We could use devm_drm_panel_bridge_add_typed(), even if I like the
warning as it uncovers the problematic panels and gets them fixed. What
would be your preference ?

> Two more comments below.
> 
> > Signed-off-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
> > ---
> >  drivers/gpu/drm/mxsfb/Makefile    |   2 +-
> >  drivers/gpu/drm/mxsfb/mxsfb_drv.c | 105 ++++++++++++++----------------
> >  drivers/gpu/drm/mxsfb/mxsfb_drv.h |   5 +-
> >  drivers/gpu/drm/mxsfb/mxsfb_out.c |  99 ----------------------------
> >  4 files changed, 53 insertions(+), 158 deletions(-)
> >  delete mode 100644 drivers/gpu/drm/mxsfb/mxsfb_out.c
> > 
> > diff --git a/drivers/gpu/drm/mxsfb/Makefile b/drivers/gpu/drm/mxsfb/Makefile
> > index ff6e358088fa..811584e54ad1 100644
> > --- a/drivers/gpu/drm/mxsfb/Makefile
> > +++ b/drivers/gpu/drm/mxsfb/Makefile
> > @@ -1,3 +1,3 @@
> >  # SPDX-License-Identifier: GPL-2.0-only
> > -mxsfb-y := mxsfb_drv.o mxsfb_crtc.o mxsfb_out.o
> > +mxsfb-y := mxsfb_drv.o mxsfb_crtc.o
> >  obj-$(CONFIG_DRM_MXSFB)	+= mxsfb.o
> > diff --git a/drivers/gpu/drm/mxsfb/mxsfb_drv.c
> > b/drivers/gpu/drm/mxsfb/mxsfb_drv.c
> > index 2e6068d96034..cffc70257bd3 100644
> > --- a/drivers/gpu/drm/mxsfb/mxsfb_drv.c
> > +++ b/drivers/gpu/drm/mxsfb/mxsfb_drv.c
> > @@ -29,7 +29,6 @@
> >  #include <drm/drm_gem_framebuffer_helper.h>
> >  #include <drm/drm_irq.h>
> >  #include <drm/drm_of.h>
> > -#include <drm/drm_panel.h>
> >  #include <drm/drm_probe_helper.h>
> >  #include <drm/drm_simple_kms_helper.h>
> >  #include <drm/drm_vblank.h>
> > @@ -100,29 +99,11 @@ static void mxsfb_pipe_enable(struct
> > drm_simple_display_pipe *pipe,
> >  			      struct drm_crtc_state *crtc_state,
> >  			      struct drm_plane_state *plane_state)
> >  {
> > -	struct drm_connector *connector;
> >  	struct mxsfb_drm_private *mxsfb = drm_pipe_to_mxsfb_drm_private(pipe);
> >  	struct drm_device *drm = pipe->plane.dev;
> >  
> > -	if (!mxsfb->connector) {
> > -		list_for_each_entry(connector,
> > -				    &drm->mode_config.connector_list,
> > -				    head)
> > -			if (connector->encoder == &mxsfb->pipe.encoder) {
> > -				mxsfb->connector = connector;
> > -				break;
> > -			}
> > -	}
> > -
> > -	if (!mxsfb->connector) {
> > -		dev_warn(drm->dev, "No connector attached, using default\n");
> > -		mxsfb->connector = &mxsfb->panel_connector;
> > -	}
> > -
> >  	pm_runtime_get_sync(drm->dev);
> > -	drm_panel_prepare(mxsfb->panel);
> >  	mxsfb_crtc_enable(mxsfb);
> > -	drm_panel_enable(mxsfb->panel);
> >  }
> >  
> >  static void mxsfb_pipe_disable(struct drm_simple_display_pipe *pipe)
> > @@ -132,9 +113,7 @@ static void mxsfb_pipe_disable(struct
> > drm_simple_display_pipe *pipe)
> >  	struct drm_crtc *crtc = &pipe->crtc;
> >  	struct drm_pending_vblank_event *event;
> >  
> > -	drm_panel_disable(mxsfb->panel);
> >  	mxsfb_crtc_disable(mxsfb);
> > -	drm_panel_unprepare(mxsfb->panel);
> >  	pm_runtime_put_sync(drm->dev);
> >  
> >  	spin_lock_irq(&drm->event_lock);
> > @@ -144,9 +123,6 @@ static void mxsfb_pipe_disable(struct
> > drm_simple_display_pipe *pipe)
> >  		drm_crtc_send_vblank_event(crtc, event);
> >  	}
> >  	spin_unlock_irq(&drm->event_lock);
> > -
> > -	if (mxsfb->connector != &mxsfb->panel_connector)
> > -		mxsfb->connector = NULL;
> >  }
> >  
> >  static void mxsfb_pipe_update(struct drm_simple_display_pipe *pipe,
> > @@ -190,6 +166,48 @@ static struct drm_simple_display_pipe_funcs mxsfb_funcs = {
> >  	.disable_vblank	= mxsfb_pipe_disable_vblank,
> >  };
> >  
> > +static int mxsfb_attach_bridge(struct mxsfb_drm_private *mxsfb)
> > +{
> > +	struct drm_device *drm = mxsfb->drm;
> > +	struct drm_connector_list_iter iter;
> > +	struct drm_panel *panel;
> > +	struct drm_bridge *bridge;
> > +	int ret;
> > +
> > +	ret = drm_of_find_panel_or_bridge(drm->dev->of_node, 0, 0, &panel,
> > +					  &bridge);
> > +	if (ret)
> > +		return ret;
> > +
> > +	if (panel) {
> > +		bridge = devm_drm_panel_bridge_add(drm->dev, panel);
> 
> Do we need a select DRM_PANEL_BRIDGE in Kconfig maybe? From what I can
> tell there is no devm_drm_panel_bridge_add() stub if DRM_PANEL_BRIDGE is
> not selected.

You're right, I'll add it.

> > +		if (IS_ERR(bridge))
> > +			return PTR_ERR(bridge);
> > +	}
> > +
> > +	if (!bridge)
> > +		return -ENODEV;
> > +
> > +	ret = drm_simple_display_pipe_attach_bridge(&mxsfb->pipe, bridge);
> > +	if (ret) {
> > +		DRM_DEV_ERROR(drm->dev,
> > +			      "failed to attach bridge: %d\n", ret);
> > +		return ret;
> > +	}
> > +
> > +	mxsfb->bridge = bridge;
> > +
> > +	/*
> > +	 * Get hold of the connector. This is a bit of a hack, until the bridge
> > +	 * API gives us bus flags and formats.
> > +	 */
> > +	drm_connector_list_iter_begin(drm, &iter);
> > +	mxsfb->connector = drm_connector_list_iter_next(&iter);
> > +	drm_connector_list_iter_end(&iter);
> 
> Could we not just use drm_panel_bridge_connector() here?

There's no guarantee that mxsfb->bridge is a panel bridge, the LCDIF
output could be connected to another bridge in which case
drm_of_find_panel_or_bridge() will set panel to NULL and bridge to a
non-NULL value).

> > +
> > +	return 0;
> > +}
> > +
> >  static int mxsfb_load(struct drm_device *drm, unsigned long flags)
> >  {
> >  	struct platform_device *pdev = to_platform_device(drm->dev);
> > @@ -201,6 +219,7 @@ static int mxsfb_load(struct drm_device *drm,
> > unsigned long flags)
> >  	if (!mxsfb)
> >  		return -ENOMEM;
> >  
> > +	mxsfb->drm = drm;
> >  	drm->dev_private = mxsfb;
> >  	mxsfb->devdata = &mxsfb_devdata[pdev->id_entry->driver_data];
> >  
> > @@ -236,41 +255,17 @@ static int mxsfb_load(struct drm_device *drm,
> > unsigned long flags)
> >  	/* Modeset init */
> >  	drm_mode_config_init(drm);
> >  
> > -	ret = mxsfb_create_output(drm);
> > -	if (ret < 0) {
> > -		dev_err(drm->dev, "Failed to create outputs\n");
> > -		goto err_vblank;
> > -	}
> > -
> >  	ret = drm_simple_display_pipe_init(drm, &mxsfb->pipe, &mxsfb_funcs,
> > -			mxsfb_formats, ARRAY_SIZE(mxsfb_formats), NULL,
> > -			mxsfb->connector);
> > +			mxsfb_formats, ARRAY_SIZE(mxsfb_formats), NULL, NULL);
> >  	if (ret < 0) {
> >  		dev_err(drm->dev, "Cannot setup simple display pipe\n");
> >  		goto err_vblank;
> >  	}
> >  
> > -	/*
> > -	 * Attach panel only if there is one.
> > -	 * If there is no panel attach, it must be a bridge. In this case, we
> > -	 * need a reference to its connector for a proper initialization.
> > -	 * We will do this check in pipe->enable(), since the connector won't
> > -	 * be attached to an encoder until then.
> > -	 */
> > -
> > -	if (mxsfb->panel) {
> > -		ret = drm_panel_attach(mxsfb->panel, mxsfb->connector);
> > -		if (ret) {
> > -			dev_err(drm->dev, "Cannot connect panel: %d\n", ret);
> > -			goto err_vblank;
> > -		}
> > -	} else if (mxsfb->bridge) {
> > -		ret = drm_simple_display_pipe_attach_bridge(&mxsfb->pipe,
> > -							    mxsfb->bridge);
> > -		if (ret) {
> > -			dev_err(drm->dev, "Cannot connect bridge: %d\n", ret);
> > -			goto err_vblank;
> > -		}
> > +	ret = mxsfb_attach_bridge(mxsfb);
> > +	if (ret) {
> > +		dev_err(drm->dev, "Cannot connect bridge: %d\n", ret);
> > +		goto err_vblank;
> >  	}
> >  
> >  	drm->mode_config.min_width	= MXSFB_MIN_XRES;
> > @@ -288,7 +283,7 @@ static int mxsfb_load(struct drm_device *drm,
> > unsigned long flags)
> >  
> >  	if (ret < 0) {
> >  		dev_err(drm->dev, "Failed to install IRQ handler\n");
> > -		goto err_irq;
> > +		goto err_vblank;
> >  	}
> >  
> >  	drm_kms_helper_poll_init(drm);
> > @@ -299,8 +294,6 @@ static int mxsfb_load(struct drm_device *drm,
> > unsigned long flags)
> >  
> >  	return 0;
> >  
> > -err_irq:
> > -	drm_panel_detach(mxsfb->panel);
> >  err_vblank:
> >  	pm_runtime_disable(drm->dev);
> >  
> > diff --git a/drivers/gpu/drm/mxsfb/mxsfb_drv.h
> > b/drivers/gpu/drm/mxsfb/mxsfb_drv.h
> > index 0b65b5194a9c..0e3e5a63bbf9 100644
> > --- a/drivers/gpu/drm/mxsfb/mxsfb_drv.h
> > +++ b/drivers/gpu/drm/mxsfb/mxsfb_drv.h
> > @@ -8,6 +8,8 @@
> >  #ifndef __MXSFB_DRV_H__
> >  #define __MXSFB_DRV_H__
> >  
> > +struct drm_device;
> > +
> >  struct mxsfb_devdata {
> >  	unsigned int	 transfer_count;
> >  	unsigned int	 cur_buf;
> > @@ -26,10 +28,9 @@ struct mxsfb_drm_private {
> >  	struct clk			*clk_axi;
> >  	struct clk			*clk_disp_axi;
> >  
> > +	struct drm_device		*drm;
> >  	struct drm_simple_display_pipe	pipe;
> > -	struct drm_connector		panel_connector;
> >  	struct drm_connector		*connector;
> > -	struct drm_panel		*panel;
> >  	struct drm_bridge		*bridge;
> >  };
> >  
> > diff --git a/drivers/gpu/drm/mxsfb/mxsfb_out.c
> > b/drivers/gpu/drm/mxsfb/mxsfb_out.c
> > deleted file mode 100644
> > index 9eca1605d11d..000000000000
> > --- a/drivers/gpu/drm/mxsfb/mxsfb_out.c
> > +++ /dev/null
> > @@ -1,99 +0,0 @@
> > -// SPDX-License-Identifier: GPL-2.0-or-later
> > -/*
> > - * Copyright (C) 2016 Marek Vasut <marex@denx.de>
> > - */
> > -
> > -#include <linux/of_graph.h>
> > -
> > -#include <drm/drm_atomic.h>
> > -#include <drm/drm_atomic_helper.h>
> > -#include <drm/drm_crtc.h>
> > -#include <drm/drm_fb_cma_helper.h>
> > -#include <drm/drm_gem_cma_helper.h>
> > -#include <drm/drm_of.h>
> > -#include <drm/drm_panel.h>
> > -#include <drm/drm_plane_helper.h>
> > -#include <drm/drm_probe_helper.h>
> > -#include <drm/drm_simple_kms_helper.h>
> > -
> > -#include "mxsfb_drv.h"
> > -
> > -static struct mxsfb_drm_private *
> > -drm_connector_to_mxsfb_drm_private(struct drm_connector *connector)
> > -{
> > -	return container_of(connector, struct mxsfb_drm_private,
> > -			    panel_connector);
> > -}
> > -
> > -static int mxsfb_panel_get_modes(struct drm_connector *connector)
> > -{
> > -	struct mxsfb_drm_private *mxsfb =
> > -			drm_connector_to_mxsfb_drm_private(connector);
> > -
> > -	if (mxsfb->panel)
> > -		return drm_panel_get_modes(mxsfb->panel, connector);
> > -
> > -	return 0;
> > -}
> > -
> > -static const struct
> > -drm_connector_helper_funcs mxsfb_panel_connector_helper_funcs = {
> > -	.get_modes = mxsfb_panel_get_modes,
> > -};
> > -
> > -static enum drm_connector_status
> > -mxsfb_panel_connector_detect(struct drm_connector *connector, bool force)
> > -{
> > -	struct mxsfb_drm_private *mxsfb =
> > -			drm_connector_to_mxsfb_drm_private(connector);
> > -
> > -	if (mxsfb->panel)
> > -		return connector_status_connected;
> > -
> > -	return connector_status_disconnected;
> > -}
> > -
> > -static void mxsfb_panel_connector_destroy(struct drm_connector *connector)
> > -{
> > -	struct mxsfb_drm_private *mxsfb =
> > -			drm_connector_to_mxsfb_drm_private(connector);
> > -
> > -	if (mxsfb->panel)
> > -		drm_panel_detach(mxsfb->panel);
> > -
> > -	drm_connector_unregister(connector);
> > -	drm_connector_cleanup(connector);
> > -}
> > -
> > -static const struct drm_connector_funcs mxsfb_panel_connector_funcs = {
> > -	.detect			= mxsfb_panel_connector_detect,
> > -	.fill_modes		= drm_helper_probe_single_connector_modes,
> > -	.destroy		= mxsfb_panel_connector_destroy,
> > -	.reset			= drm_atomic_helper_connector_reset,
> > -	.atomic_duplicate_state	= drm_atomic_helper_connector_duplicate_state,
> > -	.atomic_destroy_state	= drm_atomic_helper_connector_destroy_state,
> > -};
> > -
> > -int mxsfb_create_output(struct drm_device *drm)
> > -{
> > -	struct mxsfb_drm_private *mxsfb = drm->dev_private;
> > -	int ret;
> > -
> > -	ret = drm_of_find_panel_or_bridge(drm->dev->of_node, 0, 0,
> > -					  &mxsfb->panel, &mxsfb->bridge);
> > -	if (ret)
> > -		return ret;
> > -
> > -	if (mxsfb->panel) {
> > -		mxsfb->connector = &mxsfb->panel_connector;
> > -		mxsfb->connector->dpms = DRM_MODE_DPMS_OFF;
> > -		mxsfb->connector->polled = 0;
> > -		drm_connector_helper_add(mxsfb->connector,
> > -					 &mxsfb_panel_connector_helper_funcs);
> > -		ret = drm_connector_init(drm, mxsfb->connector,
> > -					 &mxsfb_panel_connector_funcs,
> > -					 DRM_MODE_CONNECTOR_Unknown);
> > -	}
> > -
> > -	return ret;
> > -}

-- 
Regards,

Laurent Pinchart
_______________________________________________
dri-devel mailing list
dri-devel@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/dri-devel

^ permalink raw reply	[flat|nested] 62+ messages in thread

* Re: [PATCH 21/21] drm: mxsfb: Support the alpha plane
  2020-03-23 23:48   ` Stefan Agner
@ 2020-05-30  2:44     ` Laurent Pinchart
  0 siblings, 0 replies; 62+ messages in thread
From: Laurent Pinchart @ 2020-05-30  2:44 UTC (permalink / raw)
  To: Stefan Agner
  Cc: Marek Vasut, dri-devel, linux-imx, kernel, robert.chiras,
	leonard.crestez

Hi Stefan,

On Tue, Mar 24, 2020 at 12:48:17AM +0100, Stefan Agner wrote:
> On 2020-03-09 20:52, Laurent Pinchart wrote:
> > The LCDIF in the i.MX6SX and i.MX7 have a second plane called the alpha
> > plane. Support it.
> > 
> > Signed-off-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
> > ---
> >  drivers/gpu/drm/mxsfb/mxsfb_drv.c  |   3 +
> >  drivers/gpu/drm/mxsfb/mxsfb_drv.h  |  16 ++--
> >  drivers/gpu/drm/mxsfb/mxsfb_kms.c  | 129 +++++++++++++++++++++++++----
> >  drivers/gpu/drm/mxsfb/mxsfb_regs.h |  22 +++++
> >  4 files changed, 149 insertions(+), 21 deletions(-)
> > 
> > diff --git a/drivers/gpu/drm/mxsfb/mxsfb_drv.c
> > b/drivers/gpu/drm/mxsfb/mxsfb_drv.c
> > index ed8e3f7bc27c..ab3a212375f1 100644
> > --- a/drivers/gpu/drm/mxsfb/mxsfb_drv.c
> > +++ b/drivers/gpu/drm/mxsfb/mxsfb_drv.c
> > @@ -49,6 +49,7 @@ static const struct mxsfb_devdata mxsfb_devdata[] = {
> >  		.next_buf	= LCDC_V3_NEXT_BUF,
> >  		.hs_wdth_mask	= 0xff,
> >  		.hs_wdth_shift	= 24,
> > +		.has_overlay	= false,
> >  	},
> >  	[MXSFB_V4] = {
> >  		.transfer_count	= LCDC_V4_TRANSFER_COUNT,
> > @@ -56,6 +57,7 @@ static const struct mxsfb_devdata mxsfb_devdata[] = {
> >  		.next_buf	= LCDC_V4_NEXT_BUF,
> >  		.hs_wdth_mask	= 0x3fff,
> >  		.hs_wdth_shift	= 18,
> > +		.has_overlay	= false,
> >  	},
> >  	[MXSFB_V6] = {
> >  		.transfer_count	= LCDC_V4_TRANSFER_COUNT,
> > @@ -63,6 +65,7 @@ static const struct mxsfb_devdata mxsfb_devdata[] = {
> >  		.next_buf	= LCDC_V4_NEXT_BUF,
> >  		.hs_wdth_mask	= 0x3fff,
> >  		.hs_wdth_shift	= 18,
> > +		.has_overlay	= true,
> >  	},
> >  };
> >  
> > diff --git a/drivers/gpu/drm/mxsfb/mxsfb_drv.h
> > b/drivers/gpu/drm/mxsfb/mxsfb_drv.h
> > index 607a6a5e6be3..399d23e91ed1 100644
> > --- a/drivers/gpu/drm/mxsfb/mxsfb_drv.h
> > +++ b/drivers/gpu/drm/mxsfb/mxsfb_drv.h
> > @@ -16,11 +16,12 @@
> >  struct clk;
> >  
> >  struct mxsfb_devdata {
> > -	unsigned int	 transfer_count;
> > -	unsigned int	 cur_buf;
> > -	unsigned int	 next_buf;
> > -	unsigned int	 hs_wdth_mask;
> > -	unsigned int	 hs_wdth_shift;
> > +	unsigned int	transfer_count;
> > +	unsigned int	cur_buf;
> > +	unsigned int	next_buf;
> > +	unsigned int	hs_wdth_mask;
> > +	unsigned int	hs_wdth_shift;
> 
> This seems an unrelated change, can you split that out?

OK.

> > +	bool		has_overlay;
> >  };
> >  
> >  struct mxsfb_drm_private {
> > @@ -32,7 +33,10 @@ struct mxsfb_drm_private {
> >  	struct clk			*clk_disp_axi;
> >  
> >  	struct drm_device		*drm;
> > -	struct drm_plane		plane;
> > +	struct {
> > +		struct drm_plane	primary;
> > +		struct drm_plane	overlay;
> > +	} planes;
> >  	struct drm_crtc			crtc;
> >  	struct drm_encoder		encoder;
> >  	struct drm_connector		*connector;
> > diff --git a/drivers/gpu/drm/mxsfb/mxsfb_kms.c
> > b/drivers/gpu/drm/mxsfb/mxsfb_kms.c
> > index f81f8c222c13..c9c394f7cbe2 100644
> > --- a/drivers/gpu/drm/mxsfb/mxsfb_kms.c
> > +++ b/drivers/gpu/drm/mxsfb/mxsfb_kms.c
> > @@ -169,9 +169,9 @@ static int mxsfb_reset_block(struct
> > mxsfb_drm_private *mxsfb)
> >  	return clear_poll_bit(mxsfb->base + LCDC_CTRL, CTRL_CLKGATE);
> >  }
> >  
> > -static dma_addr_t mxsfb_get_fb_paddr(struct mxsfb_drm_private *mxsfb)
> > +static dma_addr_t mxsfb_get_fb_paddr(struct drm_plane *plane)
> >  {
> > -	struct drm_framebuffer *fb = mxsfb->plane.state->fb;
> > +	struct drm_framebuffer *fb = plane->state->fb;
> >  	struct drm_gem_cma_object *gem;
> >  
> >  	if (!fb)
> > @@ -206,6 +206,9 @@ static void mxsfb_crtc_mode_set_nofb(struct
> > mxsfb_drm_private *mxsfb)
> >  	/* Clear the FIFOs */
> >  	writel(CTRL1_FIFO_CLEAR, mxsfb->base + LCDC_CTRL1 + REG_SET);
> >  
> > +	if (mxsfb->devdata->has_overlay)
> > +		writel(0, mxsfb->base + LCDC_AS_CTRL);
> > +
> >  	mxsfb_set_formats(mxsfb);
> >  
> >  	clk_set_rate(mxsfb->clk, m->crtc_clock * 1000);
> > @@ -313,7 +316,7 @@ static void mxsfb_crtc_atomic_enable(struct drm_crtc *crtc,
> >  	mxsfb_crtc_mode_set_nofb(mxsfb);
> >  
> >  	/* Write cur_buf as well to avoid an initial corrupt frame */
> > -	paddr = mxsfb_get_fb_paddr(mxsfb);
> > +	paddr = mxsfb_get_fb_paddr(crtc->primary);
> >  	if (paddr) {
> >  		writel(paddr, mxsfb->base + mxsfb->devdata->cur_buf);
> >  		writel(paddr, mxsfb->base + mxsfb->devdata->next_buf);
> > @@ -410,20 +413,85 @@ static int mxsfb_plane_atomic_check(struct
> > drm_plane *plane,
> >  						   false, true);
> >  }
> >  
> > -static void mxsfb_plane_atomic_update(struct drm_plane *plane,
> > -				      struct drm_plane_state *old_pstate)
> > +static void mxsfb_plane_primary_atomic_update(struct drm_plane *plane,
> > +					      struct drm_plane_state *old_pstate)
> >  {
> >  	struct mxsfb_drm_private *mxsfb = to_mxsfb_drm_private(plane->dev);
> >  	dma_addr_t paddr;
> >  
> > -	paddr = mxsfb_get_fb_paddr(mxsfb);
> > +	paddr = mxsfb_get_fb_paddr(plane);
> >  	if (paddr)
> >  		writel(paddr, mxsfb->base + mxsfb->devdata->next_buf);
> >  }
> >  
> > -static const struct drm_plane_helper_funcs mxsfb_plane_helper_funcs = {
> > +static void mxsfb_plane_overlay_atomic_update(struct drm_plane *plane,
> > +					      struct drm_plane_state *old_pstate)
> > +{
> > +	struct mxsfb_drm_private *mxsfb = to_mxsfb_drm_private(plane->dev);
> > +	struct drm_plane_state *state = plane->state;
> > +	dma_addr_t paddr;
> > +	u32 ctrl;
> > +
> > +	paddr = mxsfb_get_fb_paddr(plane);
> > +	if (!paddr) {
> > +		writel(0, mxsfb->base + LCDC_AS_CTRL);
> > +		return;
> > +	}
> > +
> > +	/*
> > +	 * HACK: The hardware seems to output 64 bytes of data of unknown
> > +	 * origin, and then to proceed with the framebuffer. Until the reason
> > +	 * is understood, live with the 16 initial invalid pixels on the first
> > +	 * line and start 64 bytes within the framebuffer.
> > +	 */
> > +	paddr += 64;
> 
> Wow, that is interesting. Did you check/find downstream drivers which
> support this feature and have some kind of hint/work around?
>
> Also adding NXP folks, maybe you have some idea?

I've had a look at the fbdev driver (drivers/video/fbdev/mxsfb.c) in the
4.14-2.3.x-imx branch of https://github.com/Freescale/linux-fslc.git.
When enabling the overlay, the driver first disables the LCDIF
completely, clears the FIFOs, then enable the overlay, clears the FIFOs
again, and reenables the LCDIF. I really hope that whole sequence isn't
needed, as that would reduce the usability of the LCDIF even more, but
it looks quite like a FIFO issue. Feedback from NXP would be helpful,
the i.MX7D reference manual doesn't decribe how to operate the overlay
plane, it only lists the related registers.

> Otherwise I guess we live with this.
> 
> > +
> > +	writel(paddr, mxsfb->base + LCDC_AS_NEXT_BUF);
> > +
> > +	/*
> > +	 * If the plane was previously disabled, write LCDC_AS_BUF as well to
> > +	 * provide the first buffer.
> > +	 */
> > +	if (!old_pstate->fb)
> > +		writel(paddr, mxsfb->base + LCDC_AS_BUF);
> > +
> > +	ctrl = AS_CTRL_AS_ENABLE | AS_CTRL_ALPHA(255);
> > +
> > +	switch (state->fb->format->format) {
> > +	case DRM_FORMAT_XRGB4444:
> > +		ctrl |= AS_CTRL_FORMAT_RGB444 | AS_CTRL_ALPHA_CTRL_OVERRIDE;
> > +		break;
> > +	case DRM_FORMAT_ARGB4444:
> > +		ctrl |= AS_CTRL_FORMAT_ARGB4444 | AS_CTRL_ALPHA_CTRL_EMBEDDED;
> > +		break;
> > +	case DRM_FORMAT_XRGB1555:
> > +		ctrl |= AS_CTRL_FORMAT_RGB555 | AS_CTRL_ALPHA_CTRL_OVERRIDE;
> > +		break;
> > +	case DRM_FORMAT_ARGB1555:
> > +		ctrl |= AS_CTRL_FORMAT_ARGB1555 | AS_CTRL_ALPHA_CTRL_EMBEDDED;
> > +		break;
> > +	case DRM_FORMAT_RGB565:
> > +		ctrl |= AS_CTRL_FORMAT_RGB565 | AS_CTRL_ALPHA_CTRL_OVERRIDE;
> > +		break;
> > +	case DRM_FORMAT_XRGB8888:
> > +		ctrl |= AS_CTRL_FORMAT_RGB888 | AS_CTRL_ALPHA_CTRL_OVERRIDE;
> > +		break;
> > +	case DRM_FORMAT_ARGB8888:
> > +		ctrl |= AS_CTRL_FORMAT_ARGB8888 | AS_CTRL_ALPHA_CTRL_EMBEDDED;
> > +		break;
> > +	}
> > +
> > +	writel(ctrl, mxsfb->base + LCDC_AS_CTRL);
> > +}
> > +
> > +static const struct drm_plane_helper_funcs mxsfb_plane_primary_helper_funcs = {
> > +	.atomic_check = mxsfb_plane_atomic_check,
> > +	.atomic_update = mxsfb_plane_primary_atomic_update,
> > +};
> > +
> > +static const struct drm_plane_helper_funcs mxsfb_plane_overlay_helper_funcs = {
> >  	.atomic_check = mxsfb_plane_atomic_check,
> > -	.atomic_update = mxsfb_plane_atomic_update,
> > +	.atomic_update = mxsfb_plane_overlay_atomic_update,
> >  };
> >  
> >  static const struct drm_plane_funcs mxsfb_plane_funcs = {
> > @@ -435,27 +503,58 @@ static const struct drm_plane_funcs mxsfb_plane_funcs = {
> >  	.atomic_destroy_state	= drm_atomic_helper_plane_destroy_state,
> >  };
> >  
> > -static const uint32_t mxsfb_formats[] = {
> > +static const uint32_t mxsfb_primary_plane_formats[] = {
> > +	DRM_FORMAT_RGB565,
> > +	DRM_FORMAT_XRGB8888,
> > +};
> > +
> > +static const uint32_t mxsfb_overlay_plane_formats[] = {
> > +	DRM_FORMAT_XRGB4444,
> > +	DRM_FORMAT_ARGB4444,
> > +	DRM_FORMAT_XRGB1555,
> > +	DRM_FORMAT_ARGB1555,
> > +	DRM_FORMAT_RGB565,
> >  	DRM_FORMAT_XRGB8888,
> > -	DRM_FORMAT_RGB565
> > +	DRM_FORMAT_ARGB8888,
> >  };
> >  
> > +/*
> > -----------------------------------------------------------------------------
> > + * Initialization
> > + */
> > +
> >  int mxsfb_kms_init(struct mxsfb_drm_private *mxsfb)
> >  {
> >  	struct drm_encoder *encoder = &mxsfb->encoder;
> > -	struct drm_plane *plane = &mxsfb->plane;
> >  	struct drm_crtc *crtc = &mxsfb->crtc;
> >  	int ret;
> >  
> > -	drm_plane_helper_add(plane, &mxsfb_plane_helper_funcs);
> > -	ret = drm_universal_plane_init(mxsfb->drm, plane, 0, &mxsfb_plane_funcs,
> > -				       mxsfb_formats, ARRAY_SIZE(mxsfb_formats),
> > +	drm_plane_helper_add(&mxsfb->planes.primary,
> > +			     &mxsfb_plane_primary_helper_funcs);
> > +	ret = drm_universal_plane_init(mxsfb->drm, &mxsfb->planes.primary, 1,
> > +				       &mxsfb_plane_funcs,
> > +				       mxsfb_primary_plane_formats,
> > +				       ARRAY_SIZE(mxsfb_primary_plane_formats),
> >  				       NULL, DRM_PLANE_TYPE_PRIMARY, NULL);
> >  	if (ret)
> >  		return ret;
> >  
> > +	if (mxsfb->devdata->has_overlay) {
> > +		drm_plane_helper_add(&mxsfb->planes.overlay,
> > +				     &mxsfb_plane_overlay_helper_funcs);
> > +		ret = drm_universal_plane_init(mxsfb->drm,
> > +					       &mxsfb->planes.overlay, 1,
> > +					       &mxsfb_plane_funcs,
> > +					       mxsfb_overlay_plane_formats,
> > +					       ARRAY_SIZE(mxsfb_overlay_plane_formats),
> > +					       NULL, DRM_PLANE_TYPE_OVERLAY,
> > +					       NULL);
> > +		if (ret)
> > +			return ret;
> > +	}
> > +
> >  	drm_crtc_helper_add(crtc, &mxsfb_crtc_helper_funcs);
> > -	ret = drm_crtc_init_with_planes(mxsfb->drm, crtc, plane, NULL,
> > +	ret = drm_crtc_init_with_planes(mxsfb->drm, crtc,
> > +					&mxsfb->planes.primary, NULL,
> >  					&mxsfb_crtc_funcs, NULL);
> >  	if (ret)
> >  		return ret;
> > diff --git a/drivers/gpu/drm/mxsfb/mxsfb_regs.h
> > b/drivers/gpu/drm/mxsfb/mxsfb_regs.h
> > index 8ebb52bb1b46..55d28a27f912 100644
> > --- a/drivers/gpu/drm/mxsfb/mxsfb_regs.h
> > +++ b/drivers/gpu/drm/mxsfb/mxsfb_regs.h
> > @@ -27,6 +27,11 @@
> >  #define LCDC_VDCTRL4			0xb0
> >  #define LCDC_V4_DEBUG0			0x1d0
> >  #define LCDC_V3_DEBUG0			0x1f0
> > +#define LCDC_AS_CTRL			0x210
> > +#define LCDC_AS_BUF			0x220
> > +#define LCDC_AS_NEXT_BUF		0x230
> > +#define LCDC_AS_CLRKEYLOW		0x240
> > +#define LCDC_AS_CLRKEYHIGH		0x250
> >  
> >  #define CTRL_SFTRST			BIT(31)
> >  #define CTRL_CLKGATE			BIT(30)
> > @@ -90,6 +95,23 @@
> >  #define DEBUG0_HSYNC			BIT(26)
> >  #define DEBUG0_VSYNC			BIT(25)
> >  
> > +#define AS_CTRL_PS_DISABLE		BIT(23)
> > +#define AS_CTRL_ALPHA_INVERT		BIT(20)
> > +#define AS_CTRL_ALPHA(a)		(((a) & 0xff) << 8)
> > +#define AS_CTRL_FORMAT_RGB565		(0xe << 4)
> > +#define AS_CTRL_FORMAT_RGB444		(0xd << 4)
> > +#define AS_CTRL_FORMAT_RGB555		(0xc << 4)
> > +#define AS_CTRL_FORMAT_ARGB4444		(0x9 << 4)
> > +#define AS_CTRL_FORMAT_ARGB1555		(0x8 << 4)
> > +#define AS_CTRL_FORMAT_RGB888		(0x4 << 4)
> > +#define AS_CTRL_FORMAT_ARGB8888		(0x0 << 4)
> > +#define AS_CTRL_ENABLE_COLORKEY		BIT(3)
> > +#define AS_CTRL_ALPHA_CTRL_ROP		(3 << 1)
> > +#define AS_CTRL_ALPHA_CTRL_MULTIPLY	(2 << 1)
> > +#define AS_CTRL_ALPHA_CTRL_OVERRIDE	(1 << 1)
> > +#define AS_CTRL_ALPHA_CTRL_EMBEDDED	(0 << 1)
> > +#define AS_CTRL_AS_ENABLE		BIT(0)
> > +
> >  #define MXSFB_MIN_XRES			120
> >  #define MXSFB_MIN_YRES			120
> >  #define MXSFB_MAX_XRES			0xffff

-- 
Regards,

Laurent Pinchart
_______________________________________________
dri-devel mailing list
dri-devel@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/dri-devel

^ permalink raw reply	[flat|nested] 62+ messages in thread

* Re: [PATCH 02/21] drm: mxsfb: Use drm_panel_bridge
  2020-05-30  2:14     ` Laurent Pinchart
@ 2020-06-02 13:12       ` Daniel Vetter
  2020-06-02 14:34         ` Stefan Agner
  2020-06-02 17:13         ` Laurent Pinchart
  0 siblings, 2 replies; 62+ messages in thread
From: Daniel Vetter @ 2020-06-02 13:12 UTC (permalink / raw)
  To: Laurent Pinchart; +Cc: Marek Vasut, dri-devel, kernel, linux-imx

On Sat, May 30, 2020 at 05:14:21AM +0300, Laurent Pinchart wrote:
> Hi Stefan,
> 
> On Mon, Mar 23, 2020 at 10:27:21PM +0100, Stefan Agner wrote:
> > On 2020-03-09 20:51, Laurent Pinchart wrote:
> > > Replace the manual connector implementation based on drm_panel with the
> > > drm_panel_bridge helper. This simplifies the mxsfb driver by removing
> > > connector-related code, and standardizing all pipeline control
> > > operations on bridges.
> > > 
> > > A hack is needed to get hold of the connector, as that's our only source
> > > of bus flags and formats for now. As soon as the bridge API provides us
> > > with that information this can be fixed.
> > 
> > This seems like a nice simplification.
> > 
> > I gave this a go applied on today's drm-misc-next using a Colibri iMX7
> > (imx7d-colibri-emmc-eval-v3.dts device tree). This device makes use of
> > the simple panel driver. I get this when booting:
> > 
> > [    2.976698] [drm] Supports vblank timestamp caching Rev 2
> > (21.10.2013).
> > [    2.983526] ------------[ cut here ]------------
> > [    2.988180] WARNING: CPU: 0 PID: 1 at
> > drivers/gpu/drm/bridge/panel.c:267 devm_drm_panel_bridge_add+0x25/0x28
> > [    2.998059] Modules linked in:
> > [    3.001159] CPU: 0 PID: 1 Comm: swapper/0 Not tainted
> > 5.6.0-rc5-yocto-standard-01250-ga4ce5db7c9f1 #29
> > [    3.010493] Hardware name: Freescale i.MX7 Dual (Device Tree)
> > [    3.016281] [<c010f089>] (unwind_backtrace) from [<c010a9bb>]
> > (show_stack+0xb/0xc)
> > [    3.023887] [<c010a9bb>] (show_stack) from [<c08b33cf>]
> > (dump_stack+0x63/0x70)
> > [    3.031144] [<c08b33cf>] (dump_stack) from [<c0124385>]
> > (__warn+0x9d/0xb0)
> > [    3.038047] [<c0124385>] (__warn) from [<c0124403>]
> > (warn_slowpath_fmt+0x6b/0x70)
> > [    3.045564] [<c0124403>] (warn_slowpath_fmt) from [<c04ebf65>]
> > (devm_drm_panel_bridge_add+0x25/0x28)
> > [    3.054736] [<c04ebf65>] (devm_drm_panel_bridge_add) from
> > [<c051fe7f>] (mxsfb_probe+0x197/0x2e0)
> > [    3.063559] [<c051fe7f>] (mxsfb_probe) from [<c0532e91>]
> > (platform_drv_probe+0x2d/0x60)
> > [    3.071598] [<c0532e91>] (platform_drv_probe) from [<c0531615>]
> > (really_probe+0x1dd/0x330)
> > [    3.079897] [<c0531615>] (really_probe) from [<c05318b3>]
> > (driver_probe_device+0x4f/0x154)
> > [    3.088195] [<c05318b3>] (driver_probe_device) from [<c0531b3f>]
> > (device_driver_attach+0x37/0x44)
> > [    3.097101] [<c0531b3f>] (device_driver_attach) from [<c0531bc7>]
> > (__driver_attach+0x7b/0xec)
> > [    3.105660] [<c0531bc7>] (__driver_attach) from [<c0530069>]
> > (bus_for_each_dev+0x3d/0x64)
> > [    3.113870] [<c0530069>] (bus_for_each_dev) from [<c0530b9b>]
> > (bus_add_driver+0xef/0x160)
> > [    3.122081] [<c0530b9b>] (bus_add_driver) from [<c053238d>]
> > (driver_register+0x35/0x9c)
> > [    3.130119] [<c053238d>] (driver_register) from [<c0102de9>]
> > (do_one_initcall+0x3d/0x1e4)
> > [    3.138333] [<c0102de9>] (do_one_initcall) from [<c1100d13>]
> > (kernel_init_freeable+0x1b3/0x1fc)
> > [    3.147069] [<c1100d13>] (kernel_init_freeable) from [<c08c3f7b>]
> > (kernel_init+0x7/0xd0)
> > [    3.155194] [<c08c3f7b>] (kernel_init) from [<c01010f9>]
> > (ret_from_fork+0x11/0x38)
> > [    3.162789] Exception stack(0xec0e3fb0 to 0xec0e3ff8)
> > [    3.167862] 3fa0:                                     00000000
> > 00000000 00000000 00000000
> > [    3.176071] 3fc0: 00000000 00000000 00000000 00000000 00000000
> > 00000000 00000000 00000000
> > [    3.184278] 3fe0: 00000000 00000000 00000000 00000000 00000013
> > 00000000
> > [    3.191029] ---[ end trace b69e1f44de470959 ]---
> > [    3.195671] mxsfb 30730000.lcdif: Cannot connect bridge: -19
> > 
> > Should we maybe use devm_drm_panel_bridge_add_typed?
> 
> As Sam reported, this is caused by the panel not setting connector_type.
> We could use devm_drm_panel_bridge_add_typed(), even if I like the
> warning as it uncovers the problematic panels and gets them fixed. What
> would be your preference ?

Adding warnings everywhere is kinda uncool, at least my experience is that
if there's too much you get warning overload and train people to ignore
them.

Imo either hide the wwarning for now, or if it's not too much work, review
all the panel drivers and make sure they set the connector type somewhere.
Warnings are kinda ok once you're pretty sure you got them all, and want
to make sure newly added drivers get this all right. But not before we've
reached that.

Cheers, Daniel

> 
> > Two more comments below.
> > 
> > > Signed-off-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
> > > ---
> > >  drivers/gpu/drm/mxsfb/Makefile    |   2 +-
> > >  drivers/gpu/drm/mxsfb/mxsfb_drv.c | 105 ++++++++++++++----------------
> > >  drivers/gpu/drm/mxsfb/mxsfb_drv.h |   5 +-
> > >  drivers/gpu/drm/mxsfb/mxsfb_out.c |  99 ----------------------------
> > >  4 files changed, 53 insertions(+), 158 deletions(-)
> > >  delete mode 100644 drivers/gpu/drm/mxsfb/mxsfb_out.c
> > > 
> > > diff --git a/drivers/gpu/drm/mxsfb/Makefile b/drivers/gpu/drm/mxsfb/Makefile
> > > index ff6e358088fa..811584e54ad1 100644
> > > --- a/drivers/gpu/drm/mxsfb/Makefile
> > > +++ b/drivers/gpu/drm/mxsfb/Makefile
> > > @@ -1,3 +1,3 @@
> > >  # SPDX-License-Identifier: GPL-2.0-only
> > > -mxsfb-y := mxsfb_drv.o mxsfb_crtc.o mxsfb_out.o
> > > +mxsfb-y := mxsfb_drv.o mxsfb_crtc.o
> > >  obj-$(CONFIG_DRM_MXSFB)	+= mxsfb.o
> > > diff --git a/drivers/gpu/drm/mxsfb/mxsfb_drv.c
> > > b/drivers/gpu/drm/mxsfb/mxsfb_drv.c
> > > index 2e6068d96034..cffc70257bd3 100644
> > > --- a/drivers/gpu/drm/mxsfb/mxsfb_drv.c
> > > +++ b/drivers/gpu/drm/mxsfb/mxsfb_drv.c
> > > @@ -29,7 +29,6 @@
> > >  #include <drm/drm_gem_framebuffer_helper.h>
> > >  #include <drm/drm_irq.h>
> > >  #include <drm/drm_of.h>
> > > -#include <drm/drm_panel.h>
> > >  #include <drm/drm_probe_helper.h>
> > >  #include <drm/drm_simple_kms_helper.h>
> > >  #include <drm/drm_vblank.h>
> > > @@ -100,29 +99,11 @@ static void mxsfb_pipe_enable(struct
> > > drm_simple_display_pipe *pipe,
> > >  			      struct drm_crtc_state *crtc_state,
> > >  			      struct drm_plane_state *plane_state)
> > >  {
> > > -	struct drm_connector *connector;
> > >  	struct mxsfb_drm_private *mxsfb = drm_pipe_to_mxsfb_drm_private(pipe);
> > >  	struct drm_device *drm = pipe->plane.dev;
> > >  
> > > -	if (!mxsfb->connector) {
> > > -		list_for_each_entry(connector,
> > > -				    &drm->mode_config.connector_list,
> > > -				    head)
> > > -			if (connector->encoder == &mxsfb->pipe.encoder) {
> > > -				mxsfb->connector = connector;
> > > -				break;
> > > -			}
> > > -	}
> > > -
> > > -	if (!mxsfb->connector) {
> > > -		dev_warn(drm->dev, "No connector attached, using default\n");
> > > -		mxsfb->connector = &mxsfb->panel_connector;
> > > -	}
> > > -
> > >  	pm_runtime_get_sync(drm->dev);
> > > -	drm_panel_prepare(mxsfb->panel);
> > >  	mxsfb_crtc_enable(mxsfb);
> > > -	drm_panel_enable(mxsfb->panel);
> > >  }
> > >  
> > >  static void mxsfb_pipe_disable(struct drm_simple_display_pipe *pipe)
> > > @@ -132,9 +113,7 @@ static void mxsfb_pipe_disable(struct
> > > drm_simple_display_pipe *pipe)
> > >  	struct drm_crtc *crtc = &pipe->crtc;
> > >  	struct drm_pending_vblank_event *event;
> > >  
> > > -	drm_panel_disable(mxsfb->panel);
> > >  	mxsfb_crtc_disable(mxsfb);
> > > -	drm_panel_unprepare(mxsfb->panel);
> > >  	pm_runtime_put_sync(drm->dev);
> > >  
> > >  	spin_lock_irq(&drm->event_lock);
> > > @@ -144,9 +123,6 @@ static void mxsfb_pipe_disable(struct
> > > drm_simple_display_pipe *pipe)
> > >  		drm_crtc_send_vblank_event(crtc, event);
> > >  	}
> > >  	spin_unlock_irq(&drm->event_lock);
> > > -
> > > -	if (mxsfb->connector != &mxsfb->panel_connector)
> > > -		mxsfb->connector = NULL;
> > >  }
> > >  
> > >  static void mxsfb_pipe_update(struct drm_simple_display_pipe *pipe,
> > > @@ -190,6 +166,48 @@ static struct drm_simple_display_pipe_funcs mxsfb_funcs = {
> > >  	.disable_vblank	= mxsfb_pipe_disable_vblank,
> > >  };
> > >  
> > > +static int mxsfb_attach_bridge(struct mxsfb_drm_private *mxsfb)
> > > +{
> > > +	struct drm_device *drm = mxsfb->drm;
> > > +	struct drm_connector_list_iter iter;
> > > +	struct drm_panel *panel;
> > > +	struct drm_bridge *bridge;
> > > +	int ret;
> > > +
> > > +	ret = drm_of_find_panel_or_bridge(drm->dev->of_node, 0, 0, &panel,
> > > +					  &bridge);
> > > +	if (ret)
> > > +		return ret;
> > > +
> > > +	if (panel) {
> > > +		bridge = devm_drm_panel_bridge_add(drm->dev, panel);
> > 
> > Do we need a select DRM_PANEL_BRIDGE in Kconfig maybe? From what I can
> > tell there is no devm_drm_panel_bridge_add() stub if DRM_PANEL_BRIDGE is
> > not selected.
> 
> You're right, I'll add it.
> 
> > > +		if (IS_ERR(bridge))
> > > +			return PTR_ERR(bridge);
> > > +	}
> > > +
> > > +	if (!bridge)
> > > +		return -ENODEV;
> > > +
> > > +	ret = drm_simple_display_pipe_attach_bridge(&mxsfb->pipe, bridge);
> > > +	if (ret) {
> > > +		DRM_DEV_ERROR(drm->dev,
> > > +			      "failed to attach bridge: %d\n", ret);
> > > +		return ret;
> > > +	}
> > > +
> > > +	mxsfb->bridge = bridge;
> > > +
> > > +	/*
> > > +	 * Get hold of the connector. This is a bit of a hack, until the bridge
> > > +	 * API gives us bus flags and formats.
> > > +	 */
> > > +	drm_connector_list_iter_begin(drm, &iter);
> > > +	mxsfb->connector = drm_connector_list_iter_next(&iter);
> > > +	drm_connector_list_iter_end(&iter);
> > 
> > Could we not just use drm_panel_bridge_connector() here?
> 
> There's no guarantee that mxsfb->bridge is a panel bridge, the LCDIF
> output could be connected to another bridge in which case
> drm_of_find_panel_or_bridge() will set panel to NULL and bridge to a
> non-NULL value).
> 
> > > +
> > > +	return 0;
> > > +}
> > > +
> > >  static int mxsfb_load(struct drm_device *drm, unsigned long flags)
> > >  {
> > >  	struct platform_device *pdev = to_platform_device(drm->dev);
> > > @@ -201,6 +219,7 @@ static int mxsfb_load(struct drm_device *drm,
> > > unsigned long flags)
> > >  	if (!mxsfb)
> > >  		return -ENOMEM;
> > >  
> > > +	mxsfb->drm = drm;
> > >  	drm->dev_private = mxsfb;
> > >  	mxsfb->devdata = &mxsfb_devdata[pdev->id_entry->driver_data];
> > >  
> > > @@ -236,41 +255,17 @@ static int mxsfb_load(struct drm_device *drm,
> > > unsigned long flags)
> > >  	/* Modeset init */
> > >  	drm_mode_config_init(drm);
> > >  
> > > -	ret = mxsfb_create_output(drm);
> > > -	if (ret < 0) {
> > > -		dev_err(drm->dev, "Failed to create outputs\n");
> > > -		goto err_vblank;
> > > -	}
> > > -
> > >  	ret = drm_simple_display_pipe_init(drm, &mxsfb->pipe, &mxsfb_funcs,
> > > -			mxsfb_formats, ARRAY_SIZE(mxsfb_formats), NULL,
> > > -			mxsfb->connector);
> > > +			mxsfb_formats, ARRAY_SIZE(mxsfb_formats), NULL, NULL);
> > >  	if (ret < 0) {
> > >  		dev_err(drm->dev, "Cannot setup simple display pipe\n");
> > >  		goto err_vblank;
> > >  	}
> > >  
> > > -	/*
> > > -	 * Attach panel only if there is one.
> > > -	 * If there is no panel attach, it must be a bridge. In this case, we
> > > -	 * need a reference to its connector for a proper initialization.
> > > -	 * We will do this check in pipe->enable(), since the connector won't
> > > -	 * be attached to an encoder until then.
> > > -	 */
> > > -
> > > -	if (mxsfb->panel) {
> > > -		ret = drm_panel_attach(mxsfb->panel, mxsfb->connector);
> > > -		if (ret) {
> > > -			dev_err(drm->dev, "Cannot connect panel: %d\n", ret);
> > > -			goto err_vblank;
> > > -		}
> > > -	} else if (mxsfb->bridge) {
> > > -		ret = drm_simple_display_pipe_attach_bridge(&mxsfb->pipe,
> > > -							    mxsfb->bridge);
> > > -		if (ret) {
> > > -			dev_err(drm->dev, "Cannot connect bridge: %d\n", ret);
> > > -			goto err_vblank;
> > > -		}
> > > +	ret = mxsfb_attach_bridge(mxsfb);
> > > +	if (ret) {
> > > +		dev_err(drm->dev, "Cannot connect bridge: %d\n", ret);
> > > +		goto err_vblank;
> > >  	}
> > >  
> > >  	drm->mode_config.min_width	= MXSFB_MIN_XRES;
> > > @@ -288,7 +283,7 @@ static int mxsfb_load(struct drm_device *drm,
> > > unsigned long flags)
> > >  
> > >  	if (ret < 0) {
> > >  		dev_err(drm->dev, "Failed to install IRQ handler\n");
> > > -		goto err_irq;
> > > +		goto err_vblank;
> > >  	}
> > >  
> > >  	drm_kms_helper_poll_init(drm);
> > > @@ -299,8 +294,6 @@ static int mxsfb_load(struct drm_device *drm,
> > > unsigned long flags)
> > >  
> > >  	return 0;
> > >  
> > > -err_irq:
> > > -	drm_panel_detach(mxsfb->panel);
> > >  err_vblank:
> > >  	pm_runtime_disable(drm->dev);
> > >  
> > > diff --git a/drivers/gpu/drm/mxsfb/mxsfb_drv.h
> > > b/drivers/gpu/drm/mxsfb/mxsfb_drv.h
> > > index 0b65b5194a9c..0e3e5a63bbf9 100644
> > > --- a/drivers/gpu/drm/mxsfb/mxsfb_drv.h
> > > +++ b/drivers/gpu/drm/mxsfb/mxsfb_drv.h
> > > @@ -8,6 +8,8 @@
> > >  #ifndef __MXSFB_DRV_H__
> > >  #define __MXSFB_DRV_H__
> > >  
> > > +struct drm_device;
> > > +
> > >  struct mxsfb_devdata {
> > >  	unsigned int	 transfer_count;
> > >  	unsigned int	 cur_buf;
> > > @@ -26,10 +28,9 @@ struct mxsfb_drm_private {
> > >  	struct clk			*clk_axi;
> > >  	struct clk			*clk_disp_axi;
> > >  
> > > +	struct drm_device		*drm;
> > >  	struct drm_simple_display_pipe	pipe;
> > > -	struct drm_connector		panel_connector;
> > >  	struct drm_connector		*connector;
> > > -	struct drm_panel		*panel;
> > >  	struct drm_bridge		*bridge;
> > >  };
> > >  
> > > diff --git a/drivers/gpu/drm/mxsfb/mxsfb_out.c
> > > b/drivers/gpu/drm/mxsfb/mxsfb_out.c
> > > deleted file mode 100644
> > > index 9eca1605d11d..000000000000
> > > --- a/drivers/gpu/drm/mxsfb/mxsfb_out.c
> > > +++ /dev/null
> > > @@ -1,99 +0,0 @@
> > > -// SPDX-License-Identifier: GPL-2.0-or-later
> > > -/*
> > > - * Copyright (C) 2016 Marek Vasut <marex@denx.de>
> > > - */
> > > -
> > > -#include <linux/of_graph.h>
> > > -
> > > -#include <drm/drm_atomic.h>
> > > -#include <drm/drm_atomic_helper.h>
> > > -#include <drm/drm_crtc.h>
> > > -#include <drm/drm_fb_cma_helper.h>
> > > -#include <drm/drm_gem_cma_helper.h>
> > > -#include <drm/drm_of.h>
> > > -#include <drm/drm_panel.h>
> > > -#include <drm/drm_plane_helper.h>
> > > -#include <drm/drm_probe_helper.h>
> > > -#include <drm/drm_simple_kms_helper.h>
> > > -
> > > -#include "mxsfb_drv.h"
> > > -
> > > -static struct mxsfb_drm_private *
> > > -drm_connector_to_mxsfb_drm_private(struct drm_connector *connector)
> > > -{
> > > -	return container_of(connector, struct mxsfb_drm_private,
> > > -			    panel_connector);
> > > -}
> > > -
> > > -static int mxsfb_panel_get_modes(struct drm_connector *connector)
> > > -{
> > > -	struct mxsfb_drm_private *mxsfb =
> > > -			drm_connector_to_mxsfb_drm_private(connector);
> > > -
> > > -	if (mxsfb->panel)
> > > -		return drm_panel_get_modes(mxsfb->panel, connector);
> > > -
> > > -	return 0;
> > > -}
> > > -
> > > -static const struct
> > > -drm_connector_helper_funcs mxsfb_panel_connector_helper_funcs = {
> > > -	.get_modes = mxsfb_panel_get_modes,
> > > -};
> > > -
> > > -static enum drm_connector_status
> > > -mxsfb_panel_connector_detect(struct drm_connector *connector, bool force)
> > > -{
> > > -	struct mxsfb_drm_private *mxsfb =
> > > -			drm_connector_to_mxsfb_drm_private(connector);
> > > -
> > > -	if (mxsfb->panel)
> > > -		return connector_status_connected;
> > > -
> > > -	return connector_status_disconnected;
> > > -}
> > > -
> > > -static void mxsfb_panel_connector_destroy(struct drm_connector *connector)
> > > -{
> > > -	struct mxsfb_drm_private *mxsfb =
> > > -			drm_connector_to_mxsfb_drm_private(connector);
> > > -
> > > -	if (mxsfb->panel)
> > > -		drm_panel_detach(mxsfb->panel);
> > > -
> > > -	drm_connector_unregister(connector);
> > > -	drm_connector_cleanup(connector);
> > > -}
> > > -
> > > -static const struct drm_connector_funcs mxsfb_panel_connector_funcs = {
> > > -	.detect			= mxsfb_panel_connector_detect,
> > > -	.fill_modes		= drm_helper_probe_single_connector_modes,
> > > -	.destroy		= mxsfb_panel_connector_destroy,
> > > -	.reset			= drm_atomic_helper_connector_reset,
> > > -	.atomic_duplicate_state	= drm_atomic_helper_connector_duplicate_state,
> > > -	.atomic_destroy_state	= drm_atomic_helper_connector_destroy_state,
> > > -};
> > > -
> > > -int mxsfb_create_output(struct drm_device *drm)
> > > -{
> > > -	struct mxsfb_drm_private *mxsfb = drm->dev_private;
> > > -	int ret;
> > > -
> > > -	ret = drm_of_find_panel_or_bridge(drm->dev->of_node, 0, 0,
> > > -					  &mxsfb->panel, &mxsfb->bridge);
> > > -	if (ret)
> > > -		return ret;
> > > -
> > > -	if (mxsfb->panel) {
> > > -		mxsfb->connector = &mxsfb->panel_connector;
> > > -		mxsfb->connector->dpms = DRM_MODE_DPMS_OFF;
> > > -		mxsfb->connector->polled = 0;
> > > -		drm_connector_helper_add(mxsfb->connector,
> > > -					 &mxsfb_panel_connector_helper_funcs);
> > > -		ret = drm_connector_init(drm, mxsfb->connector,
> > > -					 &mxsfb_panel_connector_funcs,
> > > -					 DRM_MODE_CONNECTOR_Unknown);
> > > -	}
> > > -
> > > -	return ret;
> > > -}
> 
> -- 
> Regards,
> 
> Laurent Pinchart
> _______________________________________________
> dri-devel mailing list
> dri-devel@lists.freedesktop.org
> https://lists.freedesktop.org/mailman/listinfo/dri-devel

-- 
Daniel Vetter
Software Engineer, Intel Corporation
http://blog.ffwll.ch
_______________________________________________
dri-devel mailing list
dri-devel@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/dri-devel

^ permalink raw reply	[flat|nested] 62+ messages in thread

* Re: [PATCH 02/21] drm: mxsfb: Use drm_panel_bridge
  2020-06-02 13:12       ` Daniel Vetter
@ 2020-06-02 14:34         ` Stefan Agner
  2020-06-02 17:18           ` Laurent Pinchart
  2020-06-02 17:13         ` Laurent Pinchart
  1 sibling, 1 reply; 62+ messages in thread
From: Stefan Agner @ 2020-06-02 14:34 UTC (permalink / raw)
  To: Daniel Vetter; +Cc: Marek Vasut, dri-devel, Laurent Pinchart, kernel, linux-imx

On 2020-06-02 15:12, Daniel Vetter wrote:
> On Sat, May 30, 2020 at 05:14:21AM +0300, Laurent Pinchart wrote:
>> Hi Stefan,
>>
>> On Mon, Mar 23, 2020 at 10:27:21PM +0100, Stefan Agner wrote:
>> > On 2020-03-09 20:51, Laurent Pinchart wrote:
>> > > Replace the manual connector implementation based on drm_panel with the
>> > > drm_panel_bridge helper. This simplifies the mxsfb driver by removing
>> > > connector-related code, and standardizing all pipeline control
>> > > operations on bridges.
>> > >
>> > > A hack is needed to get hold of the connector, as that's our only source
>> > > of bus flags and formats for now. As soon as the bridge API provides us
>> > > with that information this can be fixed.
>> >
>> > This seems like a nice simplification.
>> >
>> > I gave this a go applied on today's drm-misc-next using a Colibri iMX7
>> > (imx7d-colibri-emmc-eval-v3.dts device tree). This device makes use of
>> > the simple panel driver. I get this when booting:
>> >
>> > [    2.976698] [drm] Supports vblank timestamp caching Rev 2
>> > (21.10.2013).
>> > [    2.983526] ------------[ cut here ]------------
>> > [    2.988180] WARNING: CPU: 0 PID: 1 at
>> > drivers/gpu/drm/bridge/panel.c:267 devm_drm_panel_bridge_add+0x25/0x28
>> > [    2.998059] Modules linked in:
>> > [    3.001159] CPU: 0 PID: 1 Comm: swapper/0 Not tainted
>> > 5.6.0-rc5-yocto-standard-01250-ga4ce5db7c9f1 #29
>> > [    3.010493] Hardware name: Freescale i.MX7 Dual (Device Tree)
>> > [    3.016281] [<c010f089>] (unwind_backtrace) from [<c010a9bb>]
>> > (show_stack+0xb/0xc)
>> > [    3.023887] [<c010a9bb>] (show_stack) from [<c08b33cf>]
>> > (dump_stack+0x63/0x70)
>> > [    3.031144] [<c08b33cf>] (dump_stack) from [<c0124385>]
>> > (__warn+0x9d/0xb0)
>> > [    3.038047] [<c0124385>] (__warn) from [<c0124403>]
>> > (warn_slowpath_fmt+0x6b/0x70)
>> > [    3.045564] [<c0124403>] (warn_slowpath_fmt) from [<c04ebf65>]
>> > (devm_drm_panel_bridge_add+0x25/0x28)
>> > [    3.054736] [<c04ebf65>] (devm_drm_panel_bridge_add) from
>> > [<c051fe7f>] (mxsfb_probe+0x197/0x2e0)
>> > [    3.063559] [<c051fe7f>] (mxsfb_probe) from [<c0532e91>]
>> > (platform_drv_probe+0x2d/0x60)
>> > [    3.071598] [<c0532e91>] (platform_drv_probe) from [<c0531615>]
>> > (really_probe+0x1dd/0x330)
>> > [    3.079897] [<c0531615>] (really_probe) from [<c05318b3>]
>> > (driver_probe_device+0x4f/0x154)
>> > [    3.088195] [<c05318b3>] (driver_probe_device) from [<c0531b3f>]
>> > (device_driver_attach+0x37/0x44)
>> > [    3.097101] [<c0531b3f>] (device_driver_attach) from [<c0531bc7>]
>> > (__driver_attach+0x7b/0xec)
>> > [    3.105660] [<c0531bc7>] (__driver_attach) from [<c0530069>]
>> > (bus_for_each_dev+0x3d/0x64)
>> > [    3.113870] [<c0530069>] (bus_for_each_dev) from [<c0530b9b>]
>> > (bus_add_driver+0xef/0x160)
>> > [    3.122081] [<c0530b9b>] (bus_add_driver) from [<c053238d>]
>> > (driver_register+0x35/0x9c)
>> > [    3.130119] [<c053238d>] (driver_register) from [<c0102de9>]
>> > (do_one_initcall+0x3d/0x1e4)
>> > [    3.138333] [<c0102de9>] (do_one_initcall) from [<c1100d13>]
>> > (kernel_init_freeable+0x1b3/0x1fc)
>> > [    3.147069] [<c1100d13>] (kernel_init_freeable) from [<c08c3f7b>]
>> > (kernel_init+0x7/0xd0)
>> > [    3.155194] [<c08c3f7b>] (kernel_init) from [<c01010f9>]
>> > (ret_from_fork+0x11/0x38)
>> > [    3.162789] Exception stack(0xec0e3fb0 to 0xec0e3ff8)
>> > [    3.167862] 3fa0:                                     00000000
>> > 00000000 00000000 00000000
>> > [    3.176071] 3fc0: 00000000 00000000 00000000 00000000 00000000
>> > 00000000 00000000 00000000
>> > [    3.184278] 3fe0: 00000000 00000000 00000000 00000000 00000013
>> > 00000000
>> > [    3.191029] ---[ end trace b69e1f44de470959 ]---
>> > [    3.195671] mxsfb 30730000.lcdif: Cannot connect bridge: -19
>> >
>> > Should we maybe use devm_drm_panel_bridge_add_typed?
>>
>> As Sam reported, this is caused by the panel not setting connector_type.
>> We could use devm_drm_panel_bridge_add_typed(), even if I like the
>> warning as it uncovers the problematic panels and gets them fixed. What
>> would be your preference ?
> 
> Adding warnings everywhere is kinda uncool, at least my experience is that
> if there's too much you get warning overload and train people to ignore
> them.
> 
> Imo either hide the wwarning for now, or if it's not too much work, review
> all the panel drivers and make sure they set the connector type somewhere.
> Warnings are kinda ok once you're pretty sure you got them all, and want
> to make sure newly added drivers get this all right. But not before we've
> reached that.

I am with Daniel on this, too many warnings make users blind of them, so
we should save them when really attention is needed.

I guess the only question which connector type we should default to. I
think DRM_MODE_CONNECTOR_DPI make sense for this IP.

--
Stefan


> 
> Cheers, Daniel
> 
>>
>> > Two more comments below.
>> >
>> > > Signed-off-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
>> > > ---
>> > >  drivers/gpu/drm/mxsfb/Makefile    |   2 +-
>> > >  drivers/gpu/drm/mxsfb/mxsfb_drv.c | 105 ++++++++++++++----------------
>> > >  drivers/gpu/drm/mxsfb/mxsfb_drv.h |   5 +-
>> > >  drivers/gpu/drm/mxsfb/mxsfb_out.c |  99 ----------------------------
>> > >  4 files changed, 53 insertions(+), 158 deletions(-)
>> > >  delete mode 100644 drivers/gpu/drm/mxsfb/mxsfb_out.c
>> > >
>> > > diff --git a/drivers/gpu/drm/mxsfb/Makefile b/drivers/gpu/drm/mxsfb/Makefile
>> > > index ff6e358088fa..811584e54ad1 100644
>> > > --- a/drivers/gpu/drm/mxsfb/Makefile
>> > > +++ b/drivers/gpu/drm/mxsfb/Makefile
>> > > @@ -1,3 +1,3 @@
>> > >  # SPDX-License-Identifier: GPL-2.0-only
>> > > -mxsfb-y := mxsfb_drv.o mxsfb_crtc.o mxsfb_out.o
>> > > +mxsfb-y := mxsfb_drv.o mxsfb_crtc.o
>> > >  obj-$(CONFIG_DRM_MXSFB)	+= mxsfb.o
>> > > diff --git a/drivers/gpu/drm/mxsfb/mxsfb_drv.c
>> > > b/drivers/gpu/drm/mxsfb/mxsfb_drv.c
>> > > index 2e6068d96034..cffc70257bd3 100644
>> > > --- a/drivers/gpu/drm/mxsfb/mxsfb_drv.c
>> > > +++ b/drivers/gpu/drm/mxsfb/mxsfb_drv.c
>> > > @@ -29,7 +29,6 @@
>> > >  #include <drm/drm_gem_framebuffer_helper.h>
>> > >  #include <drm/drm_irq.h>
>> > >  #include <drm/drm_of.h>
>> > > -#include <drm/drm_panel.h>
>> > >  #include <drm/drm_probe_helper.h>
>> > >  #include <drm/drm_simple_kms_helper.h>
>> > >  #include <drm/drm_vblank.h>
>> > > @@ -100,29 +99,11 @@ static void mxsfb_pipe_enable(struct
>> > > drm_simple_display_pipe *pipe,
>> > >  			      struct drm_crtc_state *crtc_state,
>> > >  			      struct drm_plane_state *plane_state)
>> > >  {
>> > > -	struct drm_connector *connector;
>> > >  	struct mxsfb_drm_private *mxsfb = drm_pipe_to_mxsfb_drm_private(pipe);
>> > >  	struct drm_device *drm = pipe->plane.dev;
>> > >
>> > > -	if (!mxsfb->connector) {
>> > > -		list_for_each_entry(connector,
>> > > -				    &drm->mode_config.connector_list,
>> > > -				    head)
>> > > -			if (connector->encoder == &mxsfb->pipe.encoder) {
>> > > -				mxsfb->connector = connector;
>> > > -				break;
>> > > -			}
>> > > -	}
>> > > -
>> > > -	if (!mxsfb->connector) {
>> > > -		dev_warn(drm->dev, "No connector attached, using default\n");
>> > > -		mxsfb->connector = &mxsfb->panel_connector;
>> > > -	}
>> > > -
>> > >  	pm_runtime_get_sync(drm->dev);
>> > > -	drm_panel_prepare(mxsfb->panel);
>> > >  	mxsfb_crtc_enable(mxsfb);
>> > > -	drm_panel_enable(mxsfb->panel);
>> > >  }
>> > >
>> > >  static void mxsfb_pipe_disable(struct drm_simple_display_pipe *pipe)
>> > > @@ -132,9 +113,7 @@ static void mxsfb_pipe_disable(struct
>> > > drm_simple_display_pipe *pipe)
>> > >  	struct drm_crtc *crtc = &pipe->crtc;
>> > >  	struct drm_pending_vblank_event *event;
>> > >
>> > > -	drm_panel_disable(mxsfb->panel);
>> > >  	mxsfb_crtc_disable(mxsfb);
>> > > -	drm_panel_unprepare(mxsfb->panel);
>> > >  	pm_runtime_put_sync(drm->dev);
>> > >
>> > >  	spin_lock_irq(&drm->event_lock);
>> > > @@ -144,9 +123,6 @@ static void mxsfb_pipe_disable(struct
>> > > drm_simple_display_pipe *pipe)
>> > >  		drm_crtc_send_vblank_event(crtc, event);
>> > >  	}
>> > >  	spin_unlock_irq(&drm->event_lock);
>> > > -
>> > > -	if (mxsfb->connector != &mxsfb->panel_connector)
>> > > -		mxsfb->connector = NULL;
>> > >  }
>> > >
>> > >  static void mxsfb_pipe_update(struct drm_simple_display_pipe *pipe,
>> > > @@ -190,6 +166,48 @@ static struct drm_simple_display_pipe_funcs mxsfb_funcs = {
>> > >  	.disable_vblank	= mxsfb_pipe_disable_vblank,
>> > >  };
>> > >
>> > > +static int mxsfb_attach_bridge(struct mxsfb_drm_private *mxsfb)
>> > > +{
>> > > +	struct drm_device *drm = mxsfb->drm;
>> > > +	struct drm_connector_list_iter iter;
>> > > +	struct drm_panel *panel;
>> > > +	struct drm_bridge *bridge;
>> > > +	int ret;
>> > > +
>> > > +	ret = drm_of_find_panel_or_bridge(drm->dev->of_node, 0, 0, &panel,
>> > > +					  &bridge);
>> > > +	if (ret)
>> > > +		return ret;
>> > > +
>> > > +	if (panel) {
>> > > +		bridge = devm_drm_panel_bridge_add(drm->dev, panel);
>> >
>> > Do we need a select DRM_PANEL_BRIDGE in Kconfig maybe? From what I can
>> > tell there is no devm_drm_panel_bridge_add() stub if DRM_PANEL_BRIDGE is
>> > not selected.
>>
>> You're right, I'll add it.
>>
>> > > +		if (IS_ERR(bridge))
>> > > +			return PTR_ERR(bridge);
>> > > +	}
>> > > +
>> > > +	if (!bridge)
>> > > +		return -ENODEV;
>> > > +
>> > > +	ret = drm_simple_display_pipe_attach_bridge(&mxsfb->pipe, bridge);
>> > > +	if (ret) {
>> > > +		DRM_DEV_ERROR(drm->dev,
>> > > +			      "failed to attach bridge: %d\n", ret);
>> > > +		return ret;
>> > > +	}
>> > > +
>> > > +	mxsfb->bridge = bridge;
>> > > +
>> > > +	/*
>> > > +	 * Get hold of the connector. This is a bit of a hack, until the bridge
>> > > +	 * API gives us bus flags and formats.
>> > > +	 */
>> > > +	drm_connector_list_iter_begin(drm, &iter);
>> > > +	mxsfb->connector = drm_connector_list_iter_next(&iter);
>> > > +	drm_connector_list_iter_end(&iter);
>> >
>> > Could we not just use drm_panel_bridge_connector() here?
>>
>> There's no guarantee that mxsfb->bridge is a panel bridge, the LCDIF
>> output could be connected to another bridge in which case
>> drm_of_find_panel_or_bridge() will set panel to NULL and bridge to a
>> non-NULL value).
>>
>> > > +
>> > > +	return 0;
>> > > +}
>> > > +
>> > >  static int mxsfb_load(struct drm_device *drm, unsigned long flags)
>> > >  {
>> > >  	struct platform_device *pdev = to_platform_device(drm->dev);
>> > > @@ -201,6 +219,7 @@ static int mxsfb_load(struct drm_device *drm,
>> > > unsigned long flags)
>> > >  	if (!mxsfb)
>> > >  		return -ENOMEM;
>> > >
>> > > +	mxsfb->drm = drm;
>> > >  	drm->dev_private = mxsfb;
>> > >  	mxsfb->devdata = &mxsfb_devdata[pdev->id_entry->driver_data];
>> > >
>> > > @@ -236,41 +255,17 @@ static int mxsfb_load(struct drm_device *drm,
>> > > unsigned long flags)
>> > >  	/* Modeset init */
>> > >  	drm_mode_config_init(drm);
>> > >
>> > > -	ret = mxsfb_create_output(drm);
>> > > -	if (ret < 0) {
>> > > -		dev_err(drm->dev, "Failed to create outputs\n");
>> > > -		goto err_vblank;
>> > > -	}
>> > > -
>> > >  	ret = drm_simple_display_pipe_init(drm, &mxsfb->pipe, &mxsfb_funcs,
>> > > -			mxsfb_formats, ARRAY_SIZE(mxsfb_formats), NULL,
>> > > -			mxsfb->connector);
>> > > +			mxsfb_formats, ARRAY_SIZE(mxsfb_formats), NULL, NULL);
>> > >  	if (ret < 0) {
>> > >  		dev_err(drm->dev, "Cannot setup simple display pipe\n");
>> > >  		goto err_vblank;
>> > >  	}
>> > >
>> > > -	/*
>> > > -	 * Attach panel only if there is one.
>> > > -	 * If there is no panel attach, it must be a bridge. In this case, we
>> > > -	 * need a reference to its connector for a proper initialization.
>> > > -	 * We will do this check in pipe->enable(), since the connector won't
>> > > -	 * be attached to an encoder until then.
>> > > -	 */
>> > > -
>> > > -	if (mxsfb->panel) {
>> > > -		ret = drm_panel_attach(mxsfb->panel, mxsfb->connector);
>> > > -		if (ret) {
>> > > -			dev_err(drm->dev, "Cannot connect panel: %d\n", ret);
>> > > -			goto err_vblank;
>> > > -		}
>> > > -	} else if (mxsfb->bridge) {
>> > > -		ret = drm_simple_display_pipe_attach_bridge(&mxsfb->pipe,
>> > > -							    mxsfb->bridge);
>> > > -		if (ret) {
>> > > -			dev_err(drm->dev, "Cannot connect bridge: %d\n", ret);
>> > > -			goto err_vblank;
>> > > -		}
>> > > +	ret = mxsfb_attach_bridge(mxsfb);
>> > > +	if (ret) {
>> > > +		dev_err(drm->dev, "Cannot connect bridge: %d\n", ret);
>> > > +		goto err_vblank;
>> > >  	}
>> > >
>> > >  	drm->mode_config.min_width	= MXSFB_MIN_XRES;
>> > > @@ -288,7 +283,7 @@ static int mxsfb_load(struct drm_device *drm,
>> > > unsigned long flags)
>> > >
>> > >  	if (ret < 0) {
>> > >  		dev_err(drm->dev, "Failed to install IRQ handler\n");
>> > > -		goto err_irq;
>> > > +		goto err_vblank;
>> > >  	}
>> > >
>> > >  	drm_kms_helper_poll_init(drm);
>> > > @@ -299,8 +294,6 @@ static int mxsfb_load(struct drm_device *drm,
>> > > unsigned long flags)
>> > >
>> > >  	return 0;
>> > >
>> > > -err_irq:
>> > > -	drm_panel_detach(mxsfb->panel);
>> > >  err_vblank:
>> > >  	pm_runtime_disable(drm->dev);
>> > >
>> > > diff --git a/drivers/gpu/drm/mxsfb/mxsfb_drv.h
>> > > b/drivers/gpu/drm/mxsfb/mxsfb_drv.h
>> > > index 0b65b5194a9c..0e3e5a63bbf9 100644
>> > > --- a/drivers/gpu/drm/mxsfb/mxsfb_drv.h
>> > > +++ b/drivers/gpu/drm/mxsfb/mxsfb_drv.h
>> > > @@ -8,6 +8,8 @@
>> > >  #ifndef __MXSFB_DRV_H__
>> > >  #define __MXSFB_DRV_H__
>> > >
>> > > +struct drm_device;
>> > > +
>> > >  struct mxsfb_devdata {
>> > >  	unsigned int	 transfer_count;
>> > >  	unsigned int	 cur_buf;
>> > > @@ -26,10 +28,9 @@ struct mxsfb_drm_private {
>> > >  	struct clk			*clk_axi;
>> > >  	struct clk			*clk_disp_axi;
>> > >
>> > > +	struct drm_device		*drm;
>> > >  	struct drm_simple_display_pipe	pipe;
>> > > -	struct drm_connector		panel_connector;
>> > >  	struct drm_connector		*connector;
>> > > -	struct drm_panel		*panel;
>> > >  	struct drm_bridge		*bridge;
>> > >  };
>> > >
>> > > diff --git a/drivers/gpu/drm/mxsfb/mxsfb_out.c
>> > > b/drivers/gpu/drm/mxsfb/mxsfb_out.c
>> > > deleted file mode 100644
>> > > index 9eca1605d11d..000000000000
>> > > --- a/drivers/gpu/drm/mxsfb/mxsfb_out.c
>> > > +++ /dev/null
>> > > @@ -1,99 +0,0 @@
>> > > -// SPDX-License-Identifier: GPL-2.0-or-later
>> > > -/*
>> > > - * Copyright (C) 2016 Marek Vasut <marex@denx.de>
>> > > - */
>> > > -
>> > > -#include <linux/of_graph.h>
>> > > -
>> > > -#include <drm/drm_atomic.h>
>> > > -#include <drm/drm_atomic_helper.h>
>> > > -#include <drm/drm_crtc.h>
>> > > -#include <drm/drm_fb_cma_helper.h>
>> > > -#include <drm/drm_gem_cma_helper.h>
>> > > -#include <drm/drm_of.h>
>> > > -#include <drm/drm_panel.h>
>> > > -#include <drm/drm_plane_helper.h>
>> > > -#include <drm/drm_probe_helper.h>
>> > > -#include <drm/drm_simple_kms_helper.h>
>> > > -
>> > > -#include "mxsfb_drv.h"
>> > > -
>> > > -static struct mxsfb_drm_private *
>> > > -drm_connector_to_mxsfb_drm_private(struct drm_connector *connector)
>> > > -{
>> > > -	return container_of(connector, struct mxsfb_drm_private,
>> > > -			    panel_connector);
>> > > -}
>> > > -
>> > > -static int mxsfb_panel_get_modes(struct drm_connector *connector)
>> > > -{
>> > > -	struct mxsfb_drm_private *mxsfb =
>> > > -			drm_connector_to_mxsfb_drm_private(connector);
>> > > -
>> > > -	if (mxsfb->panel)
>> > > -		return drm_panel_get_modes(mxsfb->panel, connector);
>> > > -
>> > > -	return 0;
>> > > -}
>> > > -
>> > > -static const struct
>> > > -drm_connector_helper_funcs mxsfb_panel_connector_helper_funcs = {
>> > > -	.get_modes = mxsfb_panel_get_modes,
>> > > -};
>> > > -
>> > > -static enum drm_connector_status
>> > > -mxsfb_panel_connector_detect(struct drm_connector *connector, bool force)
>> > > -{
>> > > -	struct mxsfb_drm_private *mxsfb =
>> > > -			drm_connector_to_mxsfb_drm_private(connector);
>> > > -
>> > > -	if (mxsfb->panel)
>> > > -		return connector_status_connected;
>> > > -
>> > > -	return connector_status_disconnected;
>> > > -}
>> > > -
>> > > -static void mxsfb_panel_connector_destroy(struct drm_connector *connector)
>> > > -{
>> > > -	struct mxsfb_drm_private *mxsfb =
>> > > -			drm_connector_to_mxsfb_drm_private(connector);
>> > > -
>> > > -	if (mxsfb->panel)
>> > > -		drm_panel_detach(mxsfb->panel);
>> > > -
>> > > -	drm_connector_unregister(connector);
>> > > -	drm_connector_cleanup(connector);
>> > > -}
>> > > -
>> > > -static const struct drm_connector_funcs mxsfb_panel_connector_funcs = {
>> > > -	.detect			= mxsfb_panel_connector_detect,
>> > > -	.fill_modes		= drm_helper_probe_single_connector_modes,
>> > > -	.destroy		= mxsfb_panel_connector_destroy,
>> > > -	.reset			= drm_atomic_helper_connector_reset,
>> > > -	.atomic_duplicate_state	= drm_atomic_helper_connector_duplicate_state,
>> > > -	.atomic_destroy_state	= drm_atomic_helper_connector_destroy_state,
>> > > -};
>> > > -
>> > > -int mxsfb_create_output(struct drm_device *drm)
>> > > -{
>> > > -	struct mxsfb_drm_private *mxsfb = drm->dev_private;
>> > > -	int ret;
>> > > -
>> > > -	ret = drm_of_find_panel_or_bridge(drm->dev->of_node, 0, 0,
>> > > -					  &mxsfb->panel, &mxsfb->bridge);
>> > > -	if (ret)
>> > > -		return ret;
>> > > -
>> > > -	if (mxsfb->panel) {
>> > > -		mxsfb->connector = &mxsfb->panel_connector;
>> > > -		mxsfb->connector->dpms = DRM_MODE_DPMS_OFF;
>> > > -		mxsfb->connector->polled = 0;
>> > > -		drm_connector_helper_add(mxsfb->connector,
>> > > -					 &mxsfb_panel_connector_helper_funcs);
>> > > -		ret = drm_connector_init(drm, mxsfb->connector,
>> > > -					 &mxsfb_panel_connector_funcs,
>> > > -					 DRM_MODE_CONNECTOR_Unknown);
>> > > -	}
>> > > -
>> > > -	return ret;
>> > > -}
>>
>> --
>> Regards,
>>
>> Laurent Pinchart
>> _______________________________________________
>> dri-devel mailing list
>> dri-devel@lists.freedesktop.org
>> https://lists.freedesktop.org/mailman/listinfo/dri-devel
_______________________________________________
dri-devel mailing list
dri-devel@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/dri-devel

^ permalink raw reply	[flat|nested] 62+ messages in thread

* Re: [PATCH 02/21] drm: mxsfb: Use drm_panel_bridge
  2020-06-02 13:12       ` Daniel Vetter
  2020-06-02 14:34         ` Stefan Agner
@ 2020-06-02 17:13         ` Laurent Pinchart
  2020-06-03  8:16           ` Daniel Vetter
  1 sibling, 1 reply; 62+ messages in thread
From: Laurent Pinchart @ 2020-06-02 17:13 UTC (permalink / raw)
  To: Daniel Vetter; +Cc: Marek Vasut, dri-devel, kernel, linux-imx

Hi Daniel,

On Tue, Jun 02, 2020 at 03:12:37PM +0200, Daniel Vetter wrote:
> On Sat, May 30, 2020 at 05:14:21AM +0300, Laurent Pinchart wrote:
> > On Mon, Mar 23, 2020 at 10:27:21PM +0100, Stefan Agner wrote:
> > > On 2020-03-09 20:51, Laurent Pinchart wrote:
> > > > Replace the manual connector implementation based on drm_panel with the
> > > > drm_panel_bridge helper. This simplifies the mxsfb driver by removing
> > > > connector-related code, and standardizing all pipeline control
> > > > operations on bridges.
> > > > 
> > > > A hack is needed to get hold of the connector, as that's our only source
> > > > of bus flags and formats for now. As soon as the bridge API provides us
> > > > with that information this can be fixed.
> > > 
> > > This seems like a nice simplification.
> > > 
> > > I gave this a go applied on today's drm-misc-next using a Colibri iMX7
> > > (imx7d-colibri-emmc-eval-v3.dts device tree). This device makes use of
> > > the simple panel driver. I get this when booting:
> > > 
> > > [    2.976698] [drm] Supports vblank timestamp caching Rev 2
> > > (21.10.2013).
> > > [    2.983526] ------------[ cut here ]------------
> > > [    2.988180] WARNING: CPU: 0 PID: 1 at
> > > drivers/gpu/drm/bridge/panel.c:267 devm_drm_panel_bridge_add+0x25/0x28
> > > [    2.998059] Modules linked in:
> > > [    3.001159] CPU: 0 PID: 1 Comm: swapper/0 Not tainted
> > > 5.6.0-rc5-yocto-standard-01250-ga4ce5db7c9f1 #29
> > > [    3.010493] Hardware name: Freescale i.MX7 Dual (Device Tree)
> > > [    3.016281] [<c010f089>] (unwind_backtrace) from [<c010a9bb>]
> > > (show_stack+0xb/0xc)
> > > [    3.023887] [<c010a9bb>] (show_stack) from [<c08b33cf>]
> > > (dump_stack+0x63/0x70)
> > > [    3.031144] [<c08b33cf>] (dump_stack) from [<c0124385>]
> > > (__warn+0x9d/0xb0)
> > > [    3.038047] [<c0124385>] (__warn) from [<c0124403>]
> > > (warn_slowpath_fmt+0x6b/0x70)
> > > [    3.045564] [<c0124403>] (warn_slowpath_fmt) from [<c04ebf65>]
> > > (devm_drm_panel_bridge_add+0x25/0x28)
> > > [    3.054736] [<c04ebf65>] (devm_drm_panel_bridge_add) from
> > > [<c051fe7f>] (mxsfb_probe+0x197/0x2e0)
> > > [    3.063559] [<c051fe7f>] (mxsfb_probe) from [<c0532e91>]
> > > (platform_drv_probe+0x2d/0x60)
> > > [    3.071598] [<c0532e91>] (platform_drv_probe) from [<c0531615>]
> > > (really_probe+0x1dd/0x330)
> > > [    3.079897] [<c0531615>] (really_probe) from [<c05318b3>]
> > > (driver_probe_device+0x4f/0x154)
> > > [    3.088195] [<c05318b3>] (driver_probe_device) from [<c0531b3f>]
> > > (device_driver_attach+0x37/0x44)
> > > [    3.097101] [<c0531b3f>] (device_driver_attach) from [<c0531bc7>]
> > > (__driver_attach+0x7b/0xec)
> > > [    3.105660] [<c0531bc7>] (__driver_attach) from [<c0530069>]
> > > (bus_for_each_dev+0x3d/0x64)
> > > [    3.113870] [<c0530069>] (bus_for_each_dev) from [<c0530b9b>]
> > > (bus_add_driver+0xef/0x160)
> > > [    3.122081] [<c0530b9b>] (bus_add_driver) from [<c053238d>]
> > > (driver_register+0x35/0x9c)
> > > [    3.130119] [<c053238d>] (driver_register) from [<c0102de9>]
> > > (do_one_initcall+0x3d/0x1e4)
> > > [    3.138333] [<c0102de9>] (do_one_initcall) from [<c1100d13>]
> > > (kernel_init_freeable+0x1b3/0x1fc)
> > > [    3.147069] [<c1100d13>] (kernel_init_freeable) from [<c08c3f7b>]
> > > (kernel_init+0x7/0xd0)
> > > [    3.155194] [<c08c3f7b>] (kernel_init) from [<c01010f9>]
> > > (ret_from_fork+0x11/0x38)
> > > [    3.162789] Exception stack(0xec0e3fb0 to 0xec0e3ff8)
> > > [    3.167862] 3fa0:                                     00000000
> > > 00000000 00000000 00000000
> > > [    3.176071] 3fc0: 00000000 00000000 00000000 00000000 00000000
> > > 00000000 00000000 00000000
> > > [    3.184278] 3fe0: 00000000 00000000 00000000 00000000 00000013
> > > 00000000
> > > [    3.191029] ---[ end trace b69e1f44de470959 ]---
> > > [    3.195671] mxsfb 30730000.lcdif: Cannot connect bridge: -19
> > > 
> > > Should we maybe use devm_drm_panel_bridge_add_typed?
> > 
> > As Sam reported, this is caused by the panel not setting connector_type.
> > We could use devm_drm_panel_bridge_add_typed(), even if I like the
> > warning as it uncovers the problematic panels and gets them fixed. What
> > would be your preference ?
> 
> Adding warnings everywhere is kinda uncool, at least my experience is that
> if there's too much you get warning overload and train people to ignore
> them.
> 
> Imo either hide the wwarning for now, or if it's not too much work, review
> all the panel drivers and make sure they set the connector type somewhere.

All panel drivers but panel-simple set the connector type. For
panel-simple, the type is stored in the panel_desc panel description,
and out of the 123 supported panels, only 48 have a connector type. I've
just sent a patch to fix this for the 7 DSI panels, so only 68 panels to
go :-) This will require trying to find the corresponding datasheets, so
that's a large effort for a single developer. That's why I was hoping a
WARN_ON() could help distributing the work :-) I hear your concern
though, and I'll set a default in this driver for the time being.

> Warnings are kinda ok once you're pretty sure you got them all, and want
> to make sure newly added drivers get this all right. But not before we've
> reached that.
> 
> > > Two more comments below.
> > > 
> > > > Signed-off-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
> > > > ---
> > > >  drivers/gpu/drm/mxsfb/Makefile    |   2 +-
> > > >  drivers/gpu/drm/mxsfb/mxsfb_drv.c | 105 ++++++++++++++----------------
> > > >  drivers/gpu/drm/mxsfb/mxsfb_drv.h |   5 +-
> > > >  drivers/gpu/drm/mxsfb/mxsfb_out.c |  99 ----------------------------
> > > >  4 files changed, 53 insertions(+), 158 deletions(-)
> > > >  delete mode 100644 drivers/gpu/drm/mxsfb/mxsfb_out.c
> > > > 
> > > > diff --git a/drivers/gpu/drm/mxsfb/Makefile b/drivers/gpu/drm/mxsfb/Makefile
> > > > index ff6e358088fa..811584e54ad1 100644
> > > > --- a/drivers/gpu/drm/mxsfb/Makefile
> > > > +++ b/drivers/gpu/drm/mxsfb/Makefile
> > > > @@ -1,3 +1,3 @@
> > > >  # SPDX-License-Identifier: GPL-2.0-only
> > > > -mxsfb-y := mxsfb_drv.o mxsfb_crtc.o mxsfb_out.o
> > > > +mxsfb-y := mxsfb_drv.o mxsfb_crtc.o
> > > >  obj-$(CONFIG_DRM_MXSFB)	+= mxsfb.o
> > > > diff --git a/drivers/gpu/drm/mxsfb/mxsfb_drv.c
> > > > b/drivers/gpu/drm/mxsfb/mxsfb_drv.c
> > > > index 2e6068d96034..cffc70257bd3 100644
> > > > --- a/drivers/gpu/drm/mxsfb/mxsfb_drv.c
> > > > +++ b/drivers/gpu/drm/mxsfb/mxsfb_drv.c
> > > > @@ -29,7 +29,6 @@
> > > >  #include <drm/drm_gem_framebuffer_helper.h>
> > > >  #include <drm/drm_irq.h>
> > > >  #include <drm/drm_of.h>
> > > > -#include <drm/drm_panel.h>
> > > >  #include <drm/drm_probe_helper.h>
> > > >  #include <drm/drm_simple_kms_helper.h>
> > > >  #include <drm/drm_vblank.h>
> > > > @@ -100,29 +99,11 @@ static void mxsfb_pipe_enable(struct
> > > > drm_simple_display_pipe *pipe,
> > > >  			      struct drm_crtc_state *crtc_state,
> > > >  			      struct drm_plane_state *plane_state)
> > > >  {
> > > > -	struct drm_connector *connector;
> > > >  	struct mxsfb_drm_private *mxsfb = drm_pipe_to_mxsfb_drm_private(pipe);
> > > >  	struct drm_device *drm = pipe->plane.dev;
> > > >  
> > > > -	if (!mxsfb->connector) {
> > > > -		list_for_each_entry(connector,
> > > > -				    &drm->mode_config.connector_list,
> > > > -				    head)
> > > > -			if (connector->encoder == &mxsfb->pipe.encoder) {
> > > > -				mxsfb->connector = connector;
> > > > -				break;
> > > > -			}
> > > > -	}
> > > > -
> > > > -	if (!mxsfb->connector) {
> > > > -		dev_warn(drm->dev, "No connector attached, using default\n");
> > > > -		mxsfb->connector = &mxsfb->panel_connector;
> > > > -	}
> > > > -
> > > >  	pm_runtime_get_sync(drm->dev);
> > > > -	drm_panel_prepare(mxsfb->panel);
> > > >  	mxsfb_crtc_enable(mxsfb);
> > > > -	drm_panel_enable(mxsfb->panel);
> > > >  }
> > > >  
> > > >  static void mxsfb_pipe_disable(struct drm_simple_display_pipe *pipe)
> > > > @@ -132,9 +113,7 @@ static void mxsfb_pipe_disable(struct
> > > > drm_simple_display_pipe *pipe)
> > > >  	struct drm_crtc *crtc = &pipe->crtc;
> > > >  	struct drm_pending_vblank_event *event;
> > > >  
> > > > -	drm_panel_disable(mxsfb->panel);
> > > >  	mxsfb_crtc_disable(mxsfb);
> > > > -	drm_panel_unprepare(mxsfb->panel);
> > > >  	pm_runtime_put_sync(drm->dev);
> > > >  
> > > >  	spin_lock_irq(&drm->event_lock);
> > > > @@ -144,9 +123,6 @@ static void mxsfb_pipe_disable(struct
> > > > drm_simple_display_pipe *pipe)
> > > >  		drm_crtc_send_vblank_event(crtc, event);
> > > >  	}
> > > >  	spin_unlock_irq(&drm->event_lock);
> > > > -
> > > > -	if (mxsfb->connector != &mxsfb->panel_connector)
> > > > -		mxsfb->connector = NULL;
> > > >  }
> > > >  
> > > >  static void mxsfb_pipe_update(struct drm_simple_display_pipe *pipe,
> > > > @@ -190,6 +166,48 @@ static struct drm_simple_display_pipe_funcs mxsfb_funcs = {
> > > >  	.disable_vblank	= mxsfb_pipe_disable_vblank,
> > > >  };
> > > >  
> > > > +static int mxsfb_attach_bridge(struct mxsfb_drm_private *mxsfb)
> > > > +{
> > > > +	struct drm_device *drm = mxsfb->drm;
> > > > +	struct drm_connector_list_iter iter;
> > > > +	struct drm_panel *panel;
> > > > +	struct drm_bridge *bridge;
> > > > +	int ret;
> > > > +
> > > > +	ret = drm_of_find_panel_or_bridge(drm->dev->of_node, 0, 0, &panel,
> > > > +					  &bridge);
> > > > +	if (ret)
> > > > +		return ret;
> > > > +
> > > > +	if (panel) {
> > > > +		bridge = devm_drm_panel_bridge_add(drm->dev, panel);
> > > 
> > > Do we need a select DRM_PANEL_BRIDGE in Kconfig maybe? From what I can
> > > tell there is no devm_drm_panel_bridge_add() stub if DRM_PANEL_BRIDGE is
> > > not selected.
> > 
> > You're right, I'll add it.
> > 
> > > > +		if (IS_ERR(bridge))
> > > > +			return PTR_ERR(bridge);
> > > > +	}
> > > > +
> > > > +	if (!bridge)
> > > > +		return -ENODEV;
> > > > +
> > > > +	ret = drm_simple_display_pipe_attach_bridge(&mxsfb->pipe, bridge);
> > > > +	if (ret) {
> > > > +		DRM_DEV_ERROR(drm->dev,
> > > > +			      "failed to attach bridge: %d\n", ret);
> > > > +		return ret;
> > > > +	}
> > > > +
> > > > +	mxsfb->bridge = bridge;
> > > > +
> > > > +	/*
> > > > +	 * Get hold of the connector. This is a bit of a hack, until the bridge
> > > > +	 * API gives us bus flags and formats.
> > > > +	 */
> > > > +	drm_connector_list_iter_begin(drm, &iter);
> > > > +	mxsfb->connector = drm_connector_list_iter_next(&iter);
> > > > +	drm_connector_list_iter_end(&iter);
> > > 
> > > Could we not just use drm_panel_bridge_connector() here?
> > 
> > There's no guarantee that mxsfb->bridge is a panel bridge, the LCDIF
> > output could be connected to another bridge in which case
> > drm_of_find_panel_or_bridge() will set panel to NULL and bridge to a
> > non-NULL value).
> > 
> > > > +
> > > > +	return 0;
> > > > +}
> > > > +
> > > >  static int mxsfb_load(struct drm_device *drm, unsigned long flags)
> > > >  {
> > > >  	struct platform_device *pdev = to_platform_device(drm->dev);
> > > > @@ -201,6 +219,7 @@ static int mxsfb_load(struct drm_device *drm,
> > > > unsigned long flags)
> > > >  	if (!mxsfb)
> > > >  		return -ENOMEM;
> > > >  
> > > > +	mxsfb->drm = drm;
> > > >  	drm->dev_private = mxsfb;
> > > >  	mxsfb->devdata = &mxsfb_devdata[pdev->id_entry->driver_data];
> > > >  
> > > > @@ -236,41 +255,17 @@ static int mxsfb_load(struct drm_device *drm,
> > > > unsigned long flags)
> > > >  	/* Modeset init */
> > > >  	drm_mode_config_init(drm);
> > > >  
> > > > -	ret = mxsfb_create_output(drm);
> > > > -	if (ret < 0) {
> > > > -		dev_err(drm->dev, "Failed to create outputs\n");
> > > > -		goto err_vblank;
> > > > -	}
> > > > -
> > > >  	ret = drm_simple_display_pipe_init(drm, &mxsfb->pipe, &mxsfb_funcs,
> > > > -			mxsfb_formats, ARRAY_SIZE(mxsfb_formats), NULL,
> > > > -			mxsfb->connector);
> > > > +			mxsfb_formats, ARRAY_SIZE(mxsfb_formats), NULL, NULL);
> > > >  	if (ret < 0) {
> > > >  		dev_err(drm->dev, "Cannot setup simple display pipe\n");
> > > >  		goto err_vblank;
> > > >  	}
> > > >  
> > > > -	/*
> > > > -	 * Attach panel only if there is one.
> > > > -	 * If there is no panel attach, it must be a bridge. In this case, we
> > > > -	 * need a reference to its connector for a proper initialization.
> > > > -	 * We will do this check in pipe->enable(), since the connector won't
> > > > -	 * be attached to an encoder until then.
> > > > -	 */
> > > > -
> > > > -	if (mxsfb->panel) {
> > > > -		ret = drm_panel_attach(mxsfb->panel, mxsfb->connector);
> > > > -		if (ret) {
> > > > -			dev_err(drm->dev, "Cannot connect panel: %d\n", ret);
> > > > -			goto err_vblank;
> > > > -		}
> > > > -	} else if (mxsfb->bridge) {
> > > > -		ret = drm_simple_display_pipe_attach_bridge(&mxsfb->pipe,
> > > > -							    mxsfb->bridge);
> > > > -		if (ret) {
> > > > -			dev_err(drm->dev, "Cannot connect bridge: %d\n", ret);
> > > > -			goto err_vblank;
> > > > -		}
> > > > +	ret = mxsfb_attach_bridge(mxsfb);
> > > > +	if (ret) {
> > > > +		dev_err(drm->dev, "Cannot connect bridge: %d\n", ret);
> > > > +		goto err_vblank;
> > > >  	}
> > > >  
> > > >  	drm->mode_config.min_width	= MXSFB_MIN_XRES;
> > > > @@ -288,7 +283,7 @@ static int mxsfb_load(struct drm_device *drm,
> > > > unsigned long flags)
> > > >  
> > > >  	if (ret < 0) {
> > > >  		dev_err(drm->dev, "Failed to install IRQ handler\n");
> > > > -		goto err_irq;
> > > > +		goto err_vblank;
> > > >  	}
> > > >  
> > > >  	drm_kms_helper_poll_init(drm);
> > > > @@ -299,8 +294,6 @@ static int mxsfb_load(struct drm_device *drm,
> > > > unsigned long flags)
> > > >  
> > > >  	return 0;
> > > >  
> > > > -err_irq:
> > > > -	drm_panel_detach(mxsfb->panel);
> > > >  err_vblank:
> > > >  	pm_runtime_disable(drm->dev);
> > > >  
> > > > diff --git a/drivers/gpu/drm/mxsfb/mxsfb_drv.h
> > > > b/drivers/gpu/drm/mxsfb/mxsfb_drv.h
> > > > index 0b65b5194a9c..0e3e5a63bbf9 100644
> > > > --- a/drivers/gpu/drm/mxsfb/mxsfb_drv.h
> > > > +++ b/drivers/gpu/drm/mxsfb/mxsfb_drv.h
> > > > @@ -8,6 +8,8 @@
> > > >  #ifndef __MXSFB_DRV_H__
> > > >  #define __MXSFB_DRV_H__
> > > >  
> > > > +struct drm_device;
> > > > +
> > > >  struct mxsfb_devdata {
> > > >  	unsigned int	 transfer_count;
> > > >  	unsigned int	 cur_buf;
> > > > @@ -26,10 +28,9 @@ struct mxsfb_drm_private {
> > > >  	struct clk			*clk_axi;
> > > >  	struct clk			*clk_disp_axi;
> > > >  
> > > > +	struct drm_device		*drm;
> > > >  	struct drm_simple_display_pipe	pipe;
> > > > -	struct drm_connector		panel_connector;
> > > >  	struct drm_connector		*connector;
> > > > -	struct drm_panel		*panel;
> > > >  	struct drm_bridge		*bridge;
> > > >  };
> > > >  
> > > > diff --git a/drivers/gpu/drm/mxsfb/mxsfb_out.c
> > > > b/drivers/gpu/drm/mxsfb/mxsfb_out.c
> > > > deleted file mode 100644
> > > > index 9eca1605d11d..000000000000
> > > > --- a/drivers/gpu/drm/mxsfb/mxsfb_out.c
> > > > +++ /dev/null
> > > > @@ -1,99 +0,0 @@
> > > > -// SPDX-License-Identifier: GPL-2.0-or-later
> > > > -/*
> > > > - * Copyright (C) 2016 Marek Vasut <marex@denx.de>
> > > > - */
> > > > -
> > > > -#include <linux/of_graph.h>
> > > > -
> > > > -#include <drm/drm_atomic.h>
> > > > -#include <drm/drm_atomic_helper.h>
> > > > -#include <drm/drm_crtc.h>
> > > > -#include <drm/drm_fb_cma_helper.h>
> > > > -#include <drm/drm_gem_cma_helper.h>
> > > > -#include <drm/drm_of.h>
> > > > -#include <drm/drm_panel.h>
> > > > -#include <drm/drm_plane_helper.h>
> > > > -#include <drm/drm_probe_helper.h>
> > > > -#include <drm/drm_simple_kms_helper.h>
> > > > -
> > > > -#include "mxsfb_drv.h"
> > > > -
> > > > -static struct mxsfb_drm_private *
> > > > -drm_connector_to_mxsfb_drm_private(struct drm_connector *connector)
> > > > -{
> > > > -	return container_of(connector, struct mxsfb_drm_private,
> > > > -			    panel_connector);
> > > > -}
> > > > -
> > > > -static int mxsfb_panel_get_modes(struct drm_connector *connector)
> > > > -{
> > > > -	struct mxsfb_drm_private *mxsfb =
> > > > -			drm_connector_to_mxsfb_drm_private(connector);
> > > > -
> > > > -	if (mxsfb->panel)
> > > > -		return drm_panel_get_modes(mxsfb->panel, connector);
> > > > -
> > > > -	return 0;
> > > > -}
> > > > -
> > > > -static const struct
> > > > -drm_connector_helper_funcs mxsfb_panel_connector_helper_funcs = {
> > > > -	.get_modes = mxsfb_panel_get_modes,
> > > > -};
> > > > -
> > > > -static enum drm_connector_status
> > > > -mxsfb_panel_connector_detect(struct drm_connector *connector, bool force)
> > > > -{
> > > > -	struct mxsfb_drm_private *mxsfb =
> > > > -			drm_connector_to_mxsfb_drm_private(connector);
> > > > -
> > > > -	if (mxsfb->panel)
> > > > -		return connector_status_connected;
> > > > -
> > > > -	return connector_status_disconnected;
> > > > -}
> > > > -
> > > > -static void mxsfb_panel_connector_destroy(struct drm_connector *connector)
> > > > -{
> > > > -	struct mxsfb_drm_private *mxsfb =
> > > > -			drm_connector_to_mxsfb_drm_private(connector);
> > > > -
> > > > -	if (mxsfb->panel)
> > > > -		drm_panel_detach(mxsfb->panel);
> > > > -
> > > > -	drm_connector_unregister(connector);
> > > > -	drm_connector_cleanup(connector);
> > > > -}
> > > > -
> > > > -static const struct drm_connector_funcs mxsfb_panel_connector_funcs = {
> > > > -	.detect			= mxsfb_panel_connector_detect,
> > > > -	.fill_modes		= drm_helper_probe_single_connector_modes,
> > > > -	.destroy		= mxsfb_panel_connector_destroy,
> > > > -	.reset			= drm_atomic_helper_connector_reset,
> > > > -	.atomic_duplicate_state	= drm_atomic_helper_connector_duplicate_state,
> > > > -	.atomic_destroy_state	= drm_atomic_helper_connector_destroy_state,
> > > > -};
> > > > -
> > > > -int mxsfb_create_output(struct drm_device *drm)
> > > > -{
> > > > -	struct mxsfb_drm_private *mxsfb = drm->dev_private;
> > > > -	int ret;
> > > > -
> > > > -	ret = drm_of_find_panel_or_bridge(drm->dev->of_node, 0, 0,
> > > > -					  &mxsfb->panel, &mxsfb->bridge);
> > > > -	if (ret)
> > > > -		return ret;
> > > > -
> > > > -	if (mxsfb->panel) {
> > > > -		mxsfb->connector = &mxsfb->panel_connector;
> > > > -		mxsfb->connector->dpms = DRM_MODE_DPMS_OFF;
> > > > -		mxsfb->connector->polled = 0;
> > > > -		drm_connector_helper_add(mxsfb->connector,
> > > > -					 &mxsfb_panel_connector_helper_funcs);
> > > > -		ret = drm_connector_init(drm, mxsfb->connector,
> > > > -					 &mxsfb_panel_connector_funcs,
> > > > -					 DRM_MODE_CONNECTOR_Unknown);
> > > > -	}
> > > > -
> > > > -	return ret;
> > > > -}

-- 
Regards,

Laurent Pinchart
_______________________________________________
dri-devel mailing list
dri-devel@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/dri-devel

^ permalink raw reply	[flat|nested] 62+ messages in thread

* Re: [PATCH 02/21] drm: mxsfb: Use drm_panel_bridge
  2020-06-02 14:34         ` Stefan Agner
@ 2020-06-02 17:18           ` Laurent Pinchart
  0 siblings, 0 replies; 62+ messages in thread
From: Laurent Pinchart @ 2020-06-02 17:18 UTC (permalink / raw)
  To: Stefan Agner; +Cc: Marek Vasut, dri-devel, kernel, linux-imx

Hi Stefan,

On Tue, Jun 02, 2020 at 04:34:07PM +0200, Stefan Agner wrote:
> On 2020-06-02 15:12, Daniel Vetter wrote:
> > On Sat, May 30, 2020 at 05:14:21AM +0300, Laurent Pinchart wrote:
> >> On Mon, Mar 23, 2020 at 10:27:21PM +0100, Stefan Agner wrote:
> >>> On 2020-03-09 20:51, Laurent Pinchart wrote:
> >>>> Replace the manual connector implementation based on drm_panel with the
> >>>> drm_panel_bridge helper. This simplifies the mxsfb driver by removing
> >>>> connector-related code, and standardizing all pipeline control
> >>>> operations on bridges.
> >>>>
> >>>> A hack is needed to get hold of the connector, as that's our only source
> >>>> of bus flags and formats for now. As soon as the bridge API provides us
> >>>> with that information this can be fixed.
> >>>
> >>> This seems like a nice simplification.
> >>>
> >>> I gave this a go applied on today's drm-misc-next using a Colibri iMX7
> >>> (imx7d-colibri-emmc-eval-v3.dts device tree). This device makes use of
> >>> the simple panel driver. I get this when booting:
> >>>
> >>> [    2.976698] [drm] Supports vblank timestamp caching Rev 2
> >>> (21.10.2013).
> >>> [    2.983526] ------------[ cut here ]------------
> >>> [    2.988180] WARNING: CPU: 0 PID: 1 at
> >>> drivers/gpu/drm/bridge/panel.c:267 devm_drm_panel_bridge_add+0x25/0x28
> >>> [    2.998059] Modules linked in:
> >>> [    3.001159] CPU: 0 PID: 1 Comm: swapper/0 Not tainted
> >>> 5.6.0-rc5-yocto-standard-01250-ga4ce5db7c9f1 #29
> >>> [    3.010493] Hardware name: Freescale i.MX7 Dual (Device Tree)
> >>> [    3.016281] [<c010f089>] (unwind_backtrace) from [<c010a9bb>]
> >>> (show_stack+0xb/0xc)
> >>> [    3.023887] [<c010a9bb>] (show_stack) from [<c08b33cf>]
> >>> (dump_stack+0x63/0x70)
> >>> [    3.031144] [<c08b33cf>] (dump_stack) from [<c0124385>]
> >>> (__warn+0x9d/0xb0)
> >>> [    3.038047] [<c0124385>] (__warn) from [<c0124403>]
> >>> (warn_slowpath_fmt+0x6b/0x70)
> >>> [    3.045564] [<c0124403>] (warn_slowpath_fmt) from [<c04ebf65>]
> >>> (devm_drm_panel_bridge_add+0x25/0x28)
> >>> [    3.054736] [<c04ebf65>] (devm_drm_panel_bridge_add) from
> >>> [<c051fe7f>] (mxsfb_probe+0x197/0x2e0)
> >>> [    3.063559] [<c051fe7f>] (mxsfb_probe) from [<c0532e91>]
> >>> (platform_drv_probe+0x2d/0x60)
> >>> [    3.071598] [<c0532e91>] (platform_drv_probe) from [<c0531615>]
> >>> (really_probe+0x1dd/0x330)
> >>> [    3.079897] [<c0531615>] (really_probe) from [<c05318b3>]
> >>> (driver_probe_device+0x4f/0x154)
> >>> [    3.088195] [<c05318b3>] (driver_probe_device) from [<c0531b3f>]
> >>> (device_driver_attach+0x37/0x44)
> >>> [    3.097101] [<c0531b3f>] (device_driver_attach) from [<c0531bc7>]
> >>> (__driver_attach+0x7b/0xec)
> >>> [    3.105660] [<c0531bc7>] (__driver_attach) from [<c0530069>]
> >>> (bus_for_each_dev+0x3d/0x64)
> >>> [    3.113870] [<c0530069>] (bus_for_each_dev) from [<c0530b9b>]
> >>> (bus_add_driver+0xef/0x160)
> >>> [    3.122081] [<c0530b9b>] (bus_add_driver) from [<c053238d>]
> >>> (driver_register+0x35/0x9c)
> >>> [    3.130119] [<c053238d>] (driver_register) from [<c0102de9>]
> >>> (do_one_initcall+0x3d/0x1e4)
> >>> [    3.138333] [<c0102de9>] (do_one_initcall) from [<c1100d13>]
> >>> (kernel_init_freeable+0x1b3/0x1fc)
> >>> [    3.147069] [<c1100d13>] (kernel_init_freeable) from [<c08c3f7b>]
> >>> (kernel_init+0x7/0xd0)
> >>> [    3.155194] [<c08c3f7b>] (kernel_init) from [<c01010f9>]
> >>> (ret_from_fork+0x11/0x38)
> >>> [    3.162789] Exception stack(0xec0e3fb0 to 0xec0e3ff8)
> >>> [    3.167862] 3fa0:                                     00000000
> >>> 00000000 00000000 00000000
> >>> [    3.176071] 3fc0: 00000000 00000000 00000000 00000000 00000000
> >>> 00000000 00000000 00000000
> >>> [    3.184278] 3fe0: 00000000 00000000 00000000 00000000 00000013
> >>> 00000000
> >>> [    3.191029] ---[ end trace b69e1f44de470959 ]---
> >>> [    3.195671] mxsfb 30730000.lcdif: Cannot connect bridge: -19
> >>>
> >>> Should we maybe use devm_drm_panel_bridge_add_typed?
> >>
> >> As Sam reported, this is caused by the panel not setting connector_type.
> >> We could use devm_drm_panel_bridge_add_typed(), even if I like the
> >> warning as it uncovers the problematic panels and gets them fixed. What
> >> would be your preference ?
> > 
> > Adding warnings everywhere is kinda uncool, at least my experience is that
> > if there's too much you get warning overload and train people to ignore
> > them.
> > 
> > Imo either hide the wwarning for now, or if it's not too much work, review
> > all the panel drivers and make sure they set the connector type somewhere.
> > Warnings are kinda ok once you're pretty sure you got them all, and want
> > to make sure newly added drivers get this all right. But not before we've
> > reached that.
> 
> I am with Daniel on this, too many warnings make users blind of them, so
> we should save them when really attention is needed.
> 
> I guess the only question which connector type we should default to. I
> think DRM_MODE_CONNECTOR_DPI make sense for this IP.

Yes, that makes sense. I'll fix this in v3, but will wait until you
review the remaining patches from v2 before sending v3 out.

> >>> Two more comments below.
> >>>
> >>>> Signed-off-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
> >>>> ---
> >>>>  drivers/gpu/drm/mxsfb/Makefile    |   2 +-
> >>>>  drivers/gpu/drm/mxsfb/mxsfb_drv.c | 105 ++++++++++++++----------------
> >>>>  drivers/gpu/drm/mxsfb/mxsfb_drv.h |   5 +-
> >>>>  drivers/gpu/drm/mxsfb/mxsfb_out.c |  99 ----------------------------
> >>>>  4 files changed, 53 insertions(+), 158 deletions(-)
> >>>>  delete mode 100644 drivers/gpu/drm/mxsfb/mxsfb_out.c
> >>>>
> >>>> diff --git a/drivers/gpu/drm/mxsfb/Makefile b/drivers/gpu/drm/mxsfb/Makefile
> >>>> index ff6e358088fa..811584e54ad1 100644
> >>>> --- a/drivers/gpu/drm/mxsfb/Makefile
> >>>> +++ b/drivers/gpu/drm/mxsfb/Makefile
> >>>> @@ -1,3 +1,3 @@
> >>>>  # SPDX-License-Identifier: GPL-2.0-only
> >>>> -mxsfb-y := mxsfb_drv.o mxsfb_crtc.o mxsfb_out.o
> >>>> +mxsfb-y := mxsfb_drv.o mxsfb_crtc.o
> >>>>  obj-$(CONFIG_DRM_MXSFB)	+= mxsfb.o
> >>>> diff --git a/drivers/gpu/drm/mxsfb/mxsfb_drv.c
> >>>> b/drivers/gpu/drm/mxsfb/mxsfb_drv.c
> >>>> index 2e6068d96034..cffc70257bd3 100644
> >>>> --- a/drivers/gpu/drm/mxsfb/mxsfb_drv.c
> >>>> +++ b/drivers/gpu/drm/mxsfb/mxsfb_drv.c
> >>>> @@ -29,7 +29,6 @@
> >>>>  #include <drm/drm_gem_framebuffer_helper.h>
> >>>>  #include <drm/drm_irq.h>
> >>>>  #include <drm/drm_of.h>
> >>>> -#include <drm/drm_panel.h>
> >>>>  #include <drm/drm_probe_helper.h>
> >>>>  #include <drm/drm_simple_kms_helper.h>
> >>>>  #include <drm/drm_vblank.h>
> >>>> @@ -100,29 +99,11 @@ static void mxsfb_pipe_enable(struct
> >>>> drm_simple_display_pipe *pipe,
> >>>>  			      struct drm_crtc_state *crtc_state,
> >>>>  			      struct drm_plane_state *plane_state)
> >>>>  {
> >>>> -	struct drm_connector *connector;
> >>>>  	struct mxsfb_drm_private *mxsfb = drm_pipe_to_mxsfb_drm_private(pipe);
> >>>>  	struct drm_device *drm = pipe->plane.dev;
> >>>>
> >>>> -	if (!mxsfb->connector) {
> >>>> -		list_for_each_entry(connector,
> >>>> -				    &drm->mode_config.connector_list,
> >>>> -				    head)
> >>>> -			if (connector->encoder == &mxsfb->pipe.encoder) {
> >>>> -				mxsfb->connector = connector;
> >>>> -				break;
> >>>> -			}
> >>>> -	}
> >>>> -
> >>>> -	if (!mxsfb->connector) {
> >>>> -		dev_warn(drm->dev, "No connector attached, using default\n");
> >>>> -		mxsfb->connector = &mxsfb->panel_connector;
> >>>> -	}
> >>>> -
> >>>>  	pm_runtime_get_sync(drm->dev);
> >>>> -	drm_panel_prepare(mxsfb->panel);
> >>>>  	mxsfb_crtc_enable(mxsfb);
> >>>> -	drm_panel_enable(mxsfb->panel);
> >>>>  }
> >>>>
> >>>>  static void mxsfb_pipe_disable(struct drm_simple_display_pipe *pipe)
> >>>> @@ -132,9 +113,7 @@ static void mxsfb_pipe_disable(struct
> >>>> drm_simple_display_pipe *pipe)
> >>>>  	struct drm_crtc *crtc = &pipe->crtc;
> >>>>  	struct drm_pending_vblank_event *event;
> >>>>
> >>>> -	drm_panel_disable(mxsfb->panel);
> >>>>  	mxsfb_crtc_disable(mxsfb);
> >>>> -	drm_panel_unprepare(mxsfb->panel);
> >>>>  	pm_runtime_put_sync(drm->dev);
> >>>>
> >>>>  	spin_lock_irq(&drm->event_lock);
> >>>> @@ -144,9 +123,6 @@ static void mxsfb_pipe_disable(struct
> >>>> drm_simple_display_pipe *pipe)
> >>>>  		drm_crtc_send_vblank_event(crtc, event);
> >>>>  	}
> >>>>  	spin_unlock_irq(&drm->event_lock);
> >>>> -
> >>>> -	if (mxsfb->connector != &mxsfb->panel_connector)
> >>>> -		mxsfb->connector = NULL;
> >>>>  }
> >>>>
> >>>>  static void mxsfb_pipe_update(struct drm_simple_display_pipe *pipe,
> >>>> @@ -190,6 +166,48 @@ static struct drm_simple_display_pipe_funcs mxsfb_funcs = {
> >>>>  	.disable_vblank	= mxsfb_pipe_disable_vblank,
> >>>>  };
> >>>>
> >>>> +static int mxsfb_attach_bridge(struct mxsfb_drm_private *mxsfb)
> >>>> +{
> >>>> +	struct drm_device *drm = mxsfb->drm;
> >>>> +	struct drm_connector_list_iter iter;
> >>>> +	struct drm_panel *panel;
> >>>> +	struct drm_bridge *bridge;
> >>>> +	int ret;
> >>>> +
> >>>> +	ret = drm_of_find_panel_or_bridge(drm->dev->of_node, 0, 0, &panel,
> >>>> +					  &bridge);
> >>>> +	if (ret)
> >>>> +		return ret;
> >>>> +
> >>>> +	if (panel) {
> >>>> +		bridge = devm_drm_panel_bridge_add(drm->dev, panel);
> >>>
> >>> Do we need a select DRM_PANEL_BRIDGE in Kconfig maybe? From what I can
> >>> tell there is no devm_drm_panel_bridge_add() stub if DRM_PANEL_BRIDGE is
> >>> not selected.
> >>
> >> You're right, I'll add it.
> >>
> >>>> +		if (IS_ERR(bridge))
> >>>> +			return PTR_ERR(bridge);
> >>>> +	}
> >>>> +
> >>>> +	if (!bridge)
> >>>> +		return -ENODEV;
> >>>> +
> >>>> +	ret = drm_simple_display_pipe_attach_bridge(&mxsfb->pipe, bridge);
> >>>> +	if (ret) {
> >>>> +		DRM_DEV_ERROR(drm->dev,
> >>>> +			      "failed to attach bridge: %d\n", ret);
> >>>> +		return ret;
> >>>> +	}
> >>>> +
> >>>> +	mxsfb->bridge = bridge;
> >>>> +
> >>>> +	/*
> >>>> +	 * Get hold of the connector. This is a bit of a hack, until the bridge
> >>>> +	 * API gives us bus flags and formats.
> >>>> +	 */
> >>>> +	drm_connector_list_iter_begin(drm, &iter);
> >>>> +	mxsfb->connector = drm_connector_list_iter_next(&iter);
> >>>> +	drm_connector_list_iter_end(&iter);
> >>>
> >>> Could we not just use drm_panel_bridge_connector() here?
> >>
> >> There's no guarantee that mxsfb->bridge is a panel bridge, the LCDIF
> >> output could be connected to another bridge in which case
> >> drm_of_find_panel_or_bridge() will set panel to NULL and bridge to a
> >> non-NULL value).
> >>
> >>>> +
> >>>> +	return 0;
> >>>> +}
> >>>> +
> >>>>  static int mxsfb_load(struct drm_device *drm, unsigned long flags)
> >>>>  {
> >>>>  	struct platform_device *pdev = to_platform_device(drm->dev);
> >>>> @@ -201,6 +219,7 @@ static int mxsfb_load(struct drm_device *drm,
> >>>> unsigned long flags)
> >>>>  	if (!mxsfb)
> >>>>  		return -ENOMEM;
> >>>>
> >>>> +	mxsfb->drm = drm;
> >>>>  	drm->dev_private = mxsfb;
> >>>>  	mxsfb->devdata = &mxsfb_devdata[pdev->id_entry->driver_data];
> >>>>
> >>>> @@ -236,41 +255,17 @@ static int mxsfb_load(struct drm_device *drm,
> >>>> unsigned long flags)
> >>>>  	/* Modeset init */
> >>>>  	drm_mode_config_init(drm);
> >>>>
> >>>> -	ret = mxsfb_create_output(drm);
> >>>> -	if (ret < 0) {
> >>>> -		dev_err(drm->dev, "Failed to create outputs\n");
> >>>> -		goto err_vblank;
> >>>> -	}
> >>>> -
> >>>>  	ret = drm_simple_display_pipe_init(drm, &mxsfb->pipe, &mxsfb_funcs,
> >>>> -			mxsfb_formats, ARRAY_SIZE(mxsfb_formats), NULL,
> >>>> -			mxsfb->connector);
> >>>> +			mxsfb_formats, ARRAY_SIZE(mxsfb_formats), NULL, NULL);
> >>>>  	if (ret < 0) {
> >>>>  		dev_err(drm->dev, "Cannot setup simple display pipe\n");
> >>>>  		goto err_vblank;
> >>>>  	}
> >>>>
> >>>> -	/*
> >>>> -	 * Attach panel only if there is one.
> >>>> -	 * If there is no panel attach, it must be a bridge. In this case, we
> >>>> -	 * need a reference to its connector for a proper initialization.
> >>>> -	 * We will do this check in pipe->enable(), since the connector won't
> >>>> -	 * be attached to an encoder until then.
> >>>> -	 */
> >>>> -
> >>>> -	if (mxsfb->panel) {
> >>>> -		ret = drm_panel_attach(mxsfb->panel, mxsfb->connector);
> >>>> -		if (ret) {
> >>>> -			dev_err(drm->dev, "Cannot connect panel: %d\n", ret);
> >>>> -			goto err_vblank;
> >>>> -		}
> >>>> -	} else if (mxsfb->bridge) {
> >>>> -		ret = drm_simple_display_pipe_attach_bridge(&mxsfb->pipe,
> >>>> -							    mxsfb->bridge);
> >>>> -		if (ret) {
> >>>> -			dev_err(drm->dev, "Cannot connect bridge: %d\n", ret);
> >>>> -			goto err_vblank;
> >>>> -		}
> >>>> +	ret = mxsfb_attach_bridge(mxsfb);
> >>>> +	if (ret) {
> >>>> +		dev_err(drm->dev, "Cannot connect bridge: %d\n", ret);
> >>>> +		goto err_vblank;
> >>>>  	}
> >>>>
> >>>>  	drm->mode_config.min_width	= MXSFB_MIN_XRES;
> >>>> @@ -288,7 +283,7 @@ static int mxsfb_load(struct drm_device *drm,
> >>>> unsigned long flags)
> >>>>
> >>>>  	if (ret < 0) {
> >>>>  		dev_err(drm->dev, "Failed to install IRQ handler\n");
> >>>> -		goto err_irq;
> >>>> +		goto err_vblank;
> >>>>  	}
> >>>>
> >>>>  	drm_kms_helper_poll_init(drm);
> >>>> @@ -299,8 +294,6 @@ static int mxsfb_load(struct drm_device *drm,
> >>>> unsigned long flags)
> >>>>
> >>>>  	return 0;
> >>>>
> >>>> -err_irq:
> >>>> -	drm_panel_detach(mxsfb->panel);
> >>>>  err_vblank:
> >>>>  	pm_runtime_disable(drm->dev);
> >>>>
> >>>> diff --git a/drivers/gpu/drm/mxsfb/mxsfb_drv.h
> >>>> b/drivers/gpu/drm/mxsfb/mxsfb_drv.h
> >>>> index 0b65b5194a9c..0e3e5a63bbf9 100644
> >>>> --- a/drivers/gpu/drm/mxsfb/mxsfb_drv.h
> >>>> +++ b/drivers/gpu/drm/mxsfb/mxsfb_drv.h
> >>>> @@ -8,6 +8,8 @@
> >>>>  #ifndef __MXSFB_DRV_H__
> >>>>  #define __MXSFB_DRV_H__
> >>>>
> >>>> +struct drm_device;
> >>>> +
> >>>>  struct mxsfb_devdata {
> >>>>  	unsigned int	 transfer_count;
> >>>>  	unsigned int	 cur_buf;
> >>>> @@ -26,10 +28,9 @@ struct mxsfb_drm_private {
> >>>>  	struct clk			*clk_axi;
> >>>>  	struct clk			*clk_disp_axi;
> >>>>
> >>>> +	struct drm_device		*drm;
> >>>>  	struct drm_simple_display_pipe	pipe;
> >>>> -	struct drm_connector		panel_connector;
> >>>>  	struct drm_connector		*connector;
> >>>> -	struct drm_panel		*panel;
> >>>>  	struct drm_bridge		*bridge;
> >>>>  };
> >>>>
> >>>> diff --git a/drivers/gpu/drm/mxsfb/mxsfb_out.c
> >>>> b/drivers/gpu/drm/mxsfb/mxsfb_out.c
> >>>> deleted file mode 100644
> >>>> index 9eca1605d11d..000000000000
> >>>> --- a/drivers/gpu/drm/mxsfb/mxsfb_out.c
> >>>> +++ /dev/null
> >>>> @@ -1,99 +0,0 @@
> >>>> -// SPDX-License-Identifier: GPL-2.0-or-later
> >>>> -/*
> >>>> - * Copyright (C) 2016 Marek Vasut <marex@denx.de>
> >>>> - */
> >>>> -
> >>>> -#include <linux/of_graph.h>
> >>>> -
> >>>> -#include <drm/drm_atomic.h>
> >>>> -#include <drm/drm_atomic_helper.h>
> >>>> -#include <drm/drm_crtc.h>
> >>>> -#include <drm/drm_fb_cma_helper.h>
> >>>> -#include <drm/drm_gem_cma_helper.h>
> >>>> -#include <drm/drm_of.h>
> >>>> -#include <drm/drm_panel.h>
> >>>> -#include <drm/drm_plane_helper.h>
> >>>> -#include <drm/drm_probe_helper.h>
> >>>> -#include <drm/drm_simple_kms_helper.h>
> >>>> -
> >>>> -#include "mxsfb_drv.h"
> >>>> -
> >>>> -static struct mxsfb_drm_private *
> >>>> -drm_connector_to_mxsfb_drm_private(struct drm_connector *connector)
> >>>> -{
> >>>> -	return container_of(connector, struct mxsfb_drm_private,
> >>>> -			    panel_connector);
> >>>> -}
> >>>> -
> >>>> -static int mxsfb_panel_get_modes(struct drm_connector *connector)
> >>>> -{
> >>>> -	struct mxsfb_drm_private *mxsfb =
> >>>> -			drm_connector_to_mxsfb_drm_private(connector);
> >>>> -
> >>>> -	if (mxsfb->panel)
> >>>> -		return drm_panel_get_modes(mxsfb->panel, connector);
> >>>> -
> >>>> -	return 0;
> >>>> -}
> >>>> -
> >>>> -static const struct
> >>>> -drm_connector_helper_funcs mxsfb_panel_connector_helper_funcs = {
> >>>> -	.get_modes = mxsfb_panel_get_modes,
> >>>> -};
> >>>> -
> >>>> -static enum drm_connector_status
> >>>> -mxsfb_panel_connector_detect(struct drm_connector *connector, bool force)
> >>>> -{
> >>>> -	struct mxsfb_drm_private *mxsfb =
> >>>> -			drm_connector_to_mxsfb_drm_private(connector);
> >>>> -
> >>>> -	if (mxsfb->panel)
> >>>> -		return connector_status_connected;
> >>>> -
> >>>> -	return connector_status_disconnected;
> >>>> -}
> >>>> -
> >>>> -static void mxsfb_panel_connector_destroy(struct drm_connector *connector)
> >>>> -{
> >>>> -	struct mxsfb_drm_private *mxsfb =
> >>>> -			drm_connector_to_mxsfb_drm_private(connector);
> >>>> -
> >>>> -	if (mxsfb->panel)
> >>>> -		drm_panel_detach(mxsfb->panel);
> >>>> -
> >>>> -	drm_connector_unregister(connector);
> >>>> -	drm_connector_cleanup(connector);
> >>>> -}
> >>>> -
> >>>> -static const struct drm_connector_funcs mxsfb_panel_connector_funcs = {
> >>>> -	.detect			= mxsfb_panel_connector_detect,
> >>>> -	.fill_modes		= drm_helper_probe_single_connector_modes,
> >>>> -	.destroy		= mxsfb_panel_connector_destroy,
> >>>> -	.reset			= drm_atomic_helper_connector_reset,
> >>>> -	.atomic_duplicate_state	= drm_atomic_helper_connector_duplicate_state,
> >>>> -	.atomic_destroy_state	= drm_atomic_helper_connector_destroy_state,
> >>>> -};
> >>>> -
> >>>> -int mxsfb_create_output(struct drm_device *drm)
> >>>> -{
> >>>> -	struct mxsfb_drm_private *mxsfb = drm->dev_private;
> >>>> -	int ret;
> >>>> -
> >>>> -	ret = drm_of_find_panel_or_bridge(drm->dev->of_node, 0, 0,
> >>>> -					  &mxsfb->panel, &mxsfb->bridge);
> >>>> -	if (ret)
> >>>> -		return ret;
> >>>> -
> >>>> -	if (mxsfb->panel) {
> >>>> -		mxsfb->connector = &mxsfb->panel_connector;
> >>>> -		mxsfb->connector->dpms = DRM_MODE_DPMS_OFF;
> >>>> -		mxsfb->connector->polled = 0;
> >>>> -		drm_connector_helper_add(mxsfb->connector,
> >>>> -					 &mxsfb_panel_connector_helper_funcs);
> >>>> -		ret = drm_connector_init(drm, mxsfb->connector,
> >>>> -					 &mxsfb_panel_connector_funcs,
> >>>> -					 DRM_MODE_CONNECTOR_Unknown);
> >>>> -	}
> >>>> -
> >>>> -	return ret;
> >>>> -}

-- 
Regards,

Laurent Pinchart
_______________________________________________
dri-devel mailing list
dri-devel@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/dri-devel

^ permalink raw reply	[flat|nested] 62+ messages in thread

* Re: [PATCH 02/21] drm: mxsfb: Use drm_panel_bridge
  2020-06-02 17:13         ` Laurent Pinchart
@ 2020-06-03  8:16           ` Daniel Vetter
  2020-06-04 20:10             ` Sam Ravnborg
  0 siblings, 1 reply; 62+ messages in thread
From: Daniel Vetter @ 2020-06-03  8:16 UTC (permalink / raw)
  To: Laurent Pinchart; +Cc: Marek Vasut, dri-devel, kernel, linux-imx

On Tue, Jun 02, 2020 at 08:13:17PM +0300, Laurent Pinchart wrote:
> Hi Daniel,
> 
> On Tue, Jun 02, 2020 at 03:12:37PM +0200, Daniel Vetter wrote:
> > On Sat, May 30, 2020 at 05:14:21AM +0300, Laurent Pinchart wrote:
> > > On Mon, Mar 23, 2020 at 10:27:21PM +0100, Stefan Agner wrote:
> > > > On 2020-03-09 20:51, Laurent Pinchart wrote:
> > > > > Replace the manual connector implementation based on drm_panel with the
> > > > > drm_panel_bridge helper. This simplifies the mxsfb driver by removing
> > > > > connector-related code, and standardizing all pipeline control
> > > > > operations on bridges.
> > > > > 
> > > > > A hack is needed to get hold of the connector, as that's our only source
> > > > > of bus flags and formats for now. As soon as the bridge API provides us
> > > > > with that information this can be fixed.
> > > > 
> > > > This seems like a nice simplification.
> > > > 
> > > > I gave this a go applied on today's drm-misc-next using a Colibri iMX7
> > > > (imx7d-colibri-emmc-eval-v3.dts device tree). This device makes use of
> > > > the simple panel driver. I get this when booting:
> > > > 
> > > > [    2.976698] [drm] Supports vblank timestamp caching Rev 2
> > > > (21.10.2013).
> > > > [    2.983526] ------------[ cut here ]------------
> > > > [    2.988180] WARNING: CPU: 0 PID: 1 at
> > > > drivers/gpu/drm/bridge/panel.c:267 devm_drm_panel_bridge_add+0x25/0x28
> > > > [    2.998059] Modules linked in:
> > > > [    3.001159] CPU: 0 PID: 1 Comm: swapper/0 Not tainted
> > > > 5.6.0-rc5-yocto-standard-01250-ga4ce5db7c9f1 #29
> > > > [    3.010493] Hardware name: Freescale i.MX7 Dual (Device Tree)
> > > > [    3.016281] [<c010f089>] (unwind_backtrace) from [<c010a9bb>]
> > > > (show_stack+0xb/0xc)
> > > > [    3.023887] [<c010a9bb>] (show_stack) from [<c08b33cf>]
> > > > (dump_stack+0x63/0x70)
> > > > [    3.031144] [<c08b33cf>] (dump_stack) from [<c0124385>]
> > > > (__warn+0x9d/0xb0)
> > > > [    3.038047] [<c0124385>] (__warn) from [<c0124403>]
> > > > (warn_slowpath_fmt+0x6b/0x70)
> > > > [    3.045564] [<c0124403>] (warn_slowpath_fmt) from [<c04ebf65>]
> > > > (devm_drm_panel_bridge_add+0x25/0x28)
> > > > [    3.054736] [<c04ebf65>] (devm_drm_panel_bridge_add) from
> > > > [<c051fe7f>] (mxsfb_probe+0x197/0x2e0)
> > > > [    3.063559] [<c051fe7f>] (mxsfb_probe) from [<c0532e91>]
> > > > (platform_drv_probe+0x2d/0x60)
> > > > [    3.071598] [<c0532e91>] (platform_drv_probe) from [<c0531615>]
> > > > (really_probe+0x1dd/0x330)
> > > > [    3.079897] [<c0531615>] (really_probe) from [<c05318b3>]
> > > > (driver_probe_device+0x4f/0x154)
> > > > [    3.088195] [<c05318b3>] (driver_probe_device) from [<c0531b3f>]
> > > > (device_driver_attach+0x37/0x44)
> > > > [    3.097101] [<c0531b3f>] (device_driver_attach) from [<c0531bc7>]
> > > > (__driver_attach+0x7b/0xec)
> > > > [    3.105660] [<c0531bc7>] (__driver_attach) from [<c0530069>]
> > > > (bus_for_each_dev+0x3d/0x64)
> > > > [    3.113870] [<c0530069>] (bus_for_each_dev) from [<c0530b9b>]
> > > > (bus_add_driver+0xef/0x160)
> > > > [    3.122081] [<c0530b9b>] (bus_add_driver) from [<c053238d>]
> > > > (driver_register+0x35/0x9c)
> > > > [    3.130119] [<c053238d>] (driver_register) from [<c0102de9>]
> > > > (do_one_initcall+0x3d/0x1e4)
> > > > [    3.138333] [<c0102de9>] (do_one_initcall) from [<c1100d13>]
> > > > (kernel_init_freeable+0x1b3/0x1fc)
> > > > [    3.147069] [<c1100d13>] (kernel_init_freeable) from [<c08c3f7b>]
> > > > (kernel_init+0x7/0xd0)
> > > > [    3.155194] [<c08c3f7b>] (kernel_init) from [<c01010f9>]
> > > > (ret_from_fork+0x11/0x38)
> > > > [    3.162789] Exception stack(0xec0e3fb0 to 0xec0e3ff8)
> > > > [    3.167862] 3fa0:                                     00000000
> > > > 00000000 00000000 00000000
> > > > [    3.176071] 3fc0: 00000000 00000000 00000000 00000000 00000000
> > > > 00000000 00000000 00000000
> > > > [    3.184278] 3fe0: 00000000 00000000 00000000 00000000 00000013
> > > > 00000000
> > > > [    3.191029] ---[ end trace b69e1f44de470959 ]---
> > > > [    3.195671] mxsfb 30730000.lcdif: Cannot connect bridge: -19
> > > > 
> > > > Should we maybe use devm_drm_panel_bridge_add_typed?
> > > 
> > > As Sam reported, this is caused by the panel not setting connector_type.
> > > We could use devm_drm_panel_bridge_add_typed(), even if I like the
> > > warning as it uncovers the problematic panels and gets them fixed. What
> > > would be your preference ?
> > 
> > Adding warnings everywhere is kinda uncool, at least my experience is that
> > if there's too much you get warning overload and train people to ignore
> > them.
> > 
> > Imo either hide the wwarning for now, or if it's not too much work, review
> > all the panel drivers and make sure they set the connector type somewhere.
> 
> All panel drivers but panel-simple set the connector type. For
> panel-simple, the type is stored in the panel_desc panel description,
> and out of the 123 supported panels, only 48 have a connector type. I've
> just sent a patch to fix this for the 7 DSI panels, so only 68 panels to
> go :-) This will require trying to find the corresponding datasheets, so
> that's a large effort for a single developer. That's why I was hoping a
> WARN_ON() could help distributing the work :-) I hear your concern
> though, and I'll set a default in this driver for the time being.

I think some fallback in simple-panel.c with maybe a fixme would be ok for
this case. I don't think this has to be perfect, afaik userspace at best
just checks "is this a panel", not which specific type.
-Daniel

> 
> > Warnings are kinda ok once you're pretty sure you got them all, and want
> > to make sure newly added drivers get this all right. But not before we've
> > reached that.
> > 
> > > > Two more comments below.
> > > > 
> > > > > Signed-off-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
> > > > > ---
> > > > >  drivers/gpu/drm/mxsfb/Makefile    |   2 +-
> > > > >  drivers/gpu/drm/mxsfb/mxsfb_drv.c | 105 ++++++++++++++----------------
> > > > >  drivers/gpu/drm/mxsfb/mxsfb_drv.h |   5 +-
> > > > >  drivers/gpu/drm/mxsfb/mxsfb_out.c |  99 ----------------------------
> > > > >  4 files changed, 53 insertions(+), 158 deletions(-)
> > > > >  delete mode 100644 drivers/gpu/drm/mxsfb/mxsfb_out.c
> > > > > 
> > > > > diff --git a/drivers/gpu/drm/mxsfb/Makefile b/drivers/gpu/drm/mxsfb/Makefile
> > > > > index ff6e358088fa..811584e54ad1 100644
> > > > > --- a/drivers/gpu/drm/mxsfb/Makefile
> > > > > +++ b/drivers/gpu/drm/mxsfb/Makefile
> > > > > @@ -1,3 +1,3 @@
> > > > >  # SPDX-License-Identifier: GPL-2.0-only
> > > > > -mxsfb-y := mxsfb_drv.o mxsfb_crtc.o mxsfb_out.o
> > > > > +mxsfb-y := mxsfb_drv.o mxsfb_crtc.o
> > > > >  obj-$(CONFIG_DRM_MXSFB)	+= mxsfb.o
> > > > > diff --git a/drivers/gpu/drm/mxsfb/mxsfb_drv.c
> > > > > b/drivers/gpu/drm/mxsfb/mxsfb_drv.c
> > > > > index 2e6068d96034..cffc70257bd3 100644
> > > > > --- a/drivers/gpu/drm/mxsfb/mxsfb_drv.c
> > > > > +++ b/drivers/gpu/drm/mxsfb/mxsfb_drv.c
> > > > > @@ -29,7 +29,6 @@
> > > > >  #include <drm/drm_gem_framebuffer_helper.h>
> > > > >  #include <drm/drm_irq.h>
> > > > >  #include <drm/drm_of.h>
> > > > > -#include <drm/drm_panel.h>
> > > > >  #include <drm/drm_probe_helper.h>
> > > > >  #include <drm/drm_simple_kms_helper.h>
> > > > >  #include <drm/drm_vblank.h>
> > > > > @@ -100,29 +99,11 @@ static void mxsfb_pipe_enable(struct
> > > > > drm_simple_display_pipe *pipe,
> > > > >  			      struct drm_crtc_state *crtc_state,
> > > > >  			      struct drm_plane_state *plane_state)
> > > > >  {
> > > > > -	struct drm_connector *connector;
> > > > >  	struct mxsfb_drm_private *mxsfb = drm_pipe_to_mxsfb_drm_private(pipe);
> > > > >  	struct drm_device *drm = pipe->plane.dev;
> > > > >  
> > > > > -	if (!mxsfb->connector) {
> > > > > -		list_for_each_entry(connector,
> > > > > -				    &drm->mode_config.connector_list,
> > > > > -				    head)
> > > > > -			if (connector->encoder == &mxsfb->pipe.encoder) {
> > > > > -				mxsfb->connector = connector;
> > > > > -				break;
> > > > > -			}
> > > > > -	}
> > > > > -
> > > > > -	if (!mxsfb->connector) {
> > > > > -		dev_warn(drm->dev, "No connector attached, using default\n");
> > > > > -		mxsfb->connector = &mxsfb->panel_connector;
> > > > > -	}
> > > > > -
> > > > >  	pm_runtime_get_sync(drm->dev);
> > > > > -	drm_panel_prepare(mxsfb->panel);
> > > > >  	mxsfb_crtc_enable(mxsfb);
> > > > > -	drm_panel_enable(mxsfb->panel);
> > > > >  }
> > > > >  
> > > > >  static void mxsfb_pipe_disable(struct drm_simple_display_pipe *pipe)
> > > > > @@ -132,9 +113,7 @@ static void mxsfb_pipe_disable(struct
> > > > > drm_simple_display_pipe *pipe)
> > > > >  	struct drm_crtc *crtc = &pipe->crtc;
> > > > >  	struct drm_pending_vblank_event *event;
> > > > >  
> > > > > -	drm_panel_disable(mxsfb->panel);
> > > > >  	mxsfb_crtc_disable(mxsfb);
> > > > > -	drm_panel_unprepare(mxsfb->panel);
> > > > >  	pm_runtime_put_sync(drm->dev);
> > > > >  
> > > > >  	spin_lock_irq(&drm->event_lock);
> > > > > @@ -144,9 +123,6 @@ static void mxsfb_pipe_disable(struct
> > > > > drm_simple_display_pipe *pipe)
> > > > >  		drm_crtc_send_vblank_event(crtc, event);
> > > > >  	}
> > > > >  	spin_unlock_irq(&drm->event_lock);
> > > > > -
> > > > > -	if (mxsfb->connector != &mxsfb->panel_connector)
> > > > > -		mxsfb->connector = NULL;
> > > > >  }
> > > > >  
> > > > >  static void mxsfb_pipe_update(struct drm_simple_display_pipe *pipe,
> > > > > @@ -190,6 +166,48 @@ static struct drm_simple_display_pipe_funcs mxsfb_funcs = {
> > > > >  	.disable_vblank	= mxsfb_pipe_disable_vblank,
> > > > >  };
> > > > >  
> > > > > +static int mxsfb_attach_bridge(struct mxsfb_drm_private *mxsfb)
> > > > > +{
> > > > > +	struct drm_device *drm = mxsfb->drm;
> > > > > +	struct drm_connector_list_iter iter;
> > > > > +	struct drm_panel *panel;
> > > > > +	struct drm_bridge *bridge;
> > > > > +	int ret;
> > > > > +
> > > > > +	ret = drm_of_find_panel_or_bridge(drm->dev->of_node, 0, 0, &panel,
> > > > > +					  &bridge);
> > > > > +	if (ret)
> > > > > +		return ret;
> > > > > +
> > > > > +	if (panel) {
> > > > > +		bridge = devm_drm_panel_bridge_add(drm->dev, panel);
> > > > 
> > > > Do we need a select DRM_PANEL_BRIDGE in Kconfig maybe? From what I can
> > > > tell there is no devm_drm_panel_bridge_add() stub if DRM_PANEL_BRIDGE is
> > > > not selected.
> > > 
> > > You're right, I'll add it.
> > > 
> > > > > +		if (IS_ERR(bridge))
> > > > > +			return PTR_ERR(bridge);
> > > > > +	}
> > > > > +
> > > > > +	if (!bridge)
> > > > > +		return -ENODEV;
> > > > > +
> > > > > +	ret = drm_simple_display_pipe_attach_bridge(&mxsfb->pipe, bridge);
> > > > > +	if (ret) {
> > > > > +		DRM_DEV_ERROR(drm->dev,
> > > > > +			      "failed to attach bridge: %d\n", ret);
> > > > > +		return ret;
> > > > > +	}
> > > > > +
> > > > > +	mxsfb->bridge = bridge;
> > > > > +
> > > > > +	/*
> > > > > +	 * Get hold of the connector. This is a bit of a hack, until the bridge
> > > > > +	 * API gives us bus flags and formats.
> > > > > +	 */
> > > > > +	drm_connector_list_iter_begin(drm, &iter);
> > > > > +	mxsfb->connector = drm_connector_list_iter_next(&iter);
> > > > > +	drm_connector_list_iter_end(&iter);
> > > > 
> > > > Could we not just use drm_panel_bridge_connector() here?
> > > 
> > > There's no guarantee that mxsfb->bridge is a panel bridge, the LCDIF
> > > output could be connected to another bridge in which case
> > > drm_of_find_panel_or_bridge() will set panel to NULL and bridge to a
> > > non-NULL value).
> > > 
> > > > > +
> > > > > +	return 0;
> > > > > +}
> > > > > +
> > > > >  static int mxsfb_load(struct drm_device *drm, unsigned long flags)
> > > > >  {
> > > > >  	struct platform_device *pdev = to_platform_device(drm->dev);
> > > > > @@ -201,6 +219,7 @@ static int mxsfb_load(struct drm_device *drm,
> > > > > unsigned long flags)
> > > > >  	if (!mxsfb)
> > > > >  		return -ENOMEM;
> > > > >  
> > > > > +	mxsfb->drm = drm;
> > > > >  	drm->dev_private = mxsfb;
> > > > >  	mxsfb->devdata = &mxsfb_devdata[pdev->id_entry->driver_data];
> > > > >  
> > > > > @@ -236,41 +255,17 @@ static int mxsfb_load(struct drm_device *drm,
> > > > > unsigned long flags)
> > > > >  	/* Modeset init */
> > > > >  	drm_mode_config_init(drm);
> > > > >  
> > > > > -	ret = mxsfb_create_output(drm);
> > > > > -	if (ret < 0) {
> > > > > -		dev_err(drm->dev, "Failed to create outputs\n");
> > > > > -		goto err_vblank;
> > > > > -	}
> > > > > -
> > > > >  	ret = drm_simple_display_pipe_init(drm, &mxsfb->pipe, &mxsfb_funcs,
> > > > > -			mxsfb_formats, ARRAY_SIZE(mxsfb_formats), NULL,
> > > > > -			mxsfb->connector);
> > > > > +			mxsfb_formats, ARRAY_SIZE(mxsfb_formats), NULL, NULL);
> > > > >  	if (ret < 0) {
> > > > >  		dev_err(drm->dev, "Cannot setup simple display pipe\n");
> > > > >  		goto err_vblank;
> > > > >  	}
> > > > >  
> > > > > -	/*
> > > > > -	 * Attach panel only if there is one.
> > > > > -	 * If there is no panel attach, it must be a bridge. In this case, we
> > > > > -	 * need a reference to its connector for a proper initialization.
> > > > > -	 * We will do this check in pipe->enable(), since the connector won't
> > > > > -	 * be attached to an encoder until then.
> > > > > -	 */
> > > > > -
> > > > > -	if (mxsfb->panel) {
> > > > > -		ret = drm_panel_attach(mxsfb->panel, mxsfb->connector);
> > > > > -		if (ret) {
> > > > > -			dev_err(drm->dev, "Cannot connect panel: %d\n", ret);
> > > > > -			goto err_vblank;
> > > > > -		}
> > > > > -	} else if (mxsfb->bridge) {
> > > > > -		ret = drm_simple_display_pipe_attach_bridge(&mxsfb->pipe,
> > > > > -							    mxsfb->bridge);
> > > > > -		if (ret) {
> > > > > -			dev_err(drm->dev, "Cannot connect bridge: %d\n", ret);
> > > > > -			goto err_vblank;
> > > > > -		}
> > > > > +	ret = mxsfb_attach_bridge(mxsfb);
> > > > > +	if (ret) {
> > > > > +		dev_err(drm->dev, "Cannot connect bridge: %d\n", ret);
> > > > > +		goto err_vblank;
> > > > >  	}
> > > > >  
> > > > >  	drm->mode_config.min_width	= MXSFB_MIN_XRES;
> > > > > @@ -288,7 +283,7 @@ static int mxsfb_load(struct drm_device *drm,
> > > > > unsigned long flags)
> > > > >  
> > > > >  	if (ret < 0) {
> > > > >  		dev_err(drm->dev, "Failed to install IRQ handler\n");
> > > > > -		goto err_irq;
> > > > > +		goto err_vblank;
> > > > >  	}
> > > > >  
> > > > >  	drm_kms_helper_poll_init(drm);
> > > > > @@ -299,8 +294,6 @@ static int mxsfb_load(struct drm_device *drm,
> > > > > unsigned long flags)
> > > > >  
> > > > >  	return 0;
> > > > >  
> > > > > -err_irq:
> > > > > -	drm_panel_detach(mxsfb->panel);
> > > > >  err_vblank:
> > > > >  	pm_runtime_disable(drm->dev);
> > > > >  
> > > > > diff --git a/drivers/gpu/drm/mxsfb/mxsfb_drv.h
> > > > > b/drivers/gpu/drm/mxsfb/mxsfb_drv.h
> > > > > index 0b65b5194a9c..0e3e5a63bbf9 100644
> > > > > --- a/drivers/gpu/drm/mxsfb/mxsfb_drv.h
> > > > > +++ b/drivers/gpu/drm/mxsfb/mxsfb_drv.h
> > > > > @@ -8,6 +8,8 @@
> > > > >  #ifndef __MXSFB_DRV_H__
> > > > >  #define __MXSFB_DRV_H__
> > > > >  
> > > > > +struct drm_device;
> > > > > +
> > > > >  struct mxsfb_devdata {
> > > > >  	unsigned int	 transfer_count;
> > > > >  	unsigned int	 cur_buf;
> > > > > @@ -26,10 +28,9 @@ struct mxsfb_drm_private {
> > > > >  	struct clk			*clk_axi;
> > > > >  	struct clk			*clk_disp_axi;
> > > > >  
> > > > > +	struct drm_device		*drm;
> > > > >  	struct drm_simple_display_pipe	pipe;
> > > > > -	struct drm_connector		panel_connector;
> > > > >  	struct drm_connector		*connector;
> > > > > -	struct drm_panel		*panel;
> > > > >  	struct drm_bridge		*bridge;
> > > > >  };
> > > > >  
> > > > > diff --git a/drivers/gpu/drm/mxsfb/mxsfb_out.c
> > > > > b/drivers/gpu/drm/mxsfb/mxsfb_out.c
> > > > > deleted file mode 100644
> > > > > index 9eca1605d11d..000000000000
> > > > > --- a/drivers/gpu/drm/mxsfb/mxsfb_out.c
> > > > > +++ /dev/null
> > > > > @@ -1,99 +0,0 @@
> > > > > -// SPDX-License-Identifier: GPL-2.0-or-later
> > > > > -/*
> > > > > - * Copyright (C) 2016 Marek Vasut <marex@denx.de>
> > > > > - */
> > > > > -
> > > > > -#include <linux/of_graph.h>
> > > > > -
> > > > > -#include <drm/drm_atomic.h>
> > > > > -#include <drm/drm_atomic_helper.h>
> > > > > -#include <drm/drm_crtc.h>
> > > > > -#include <drm/drm_fb_cma_helper.h>
> > > > > -#include <drm/drm_gem_cma_helper.h>
> > > > > -#include <drm/drm_of.h>
> > > > > -#include <drm/drm_panel.h>
> > > > > -#include <drm/drm_plane_helper.h>
> > > > > -#include <drm/drm_probe_helper.h>
> > > > > -#include <drm/drm_simple_kms_helper.h>
> > > > > -
> > > > > -#include "mxsfb_drv.h"
> > > > > -
> > > > > -static struct mxsfb_drm_private *
> > > > > -drm_connector_to_mxsfb_drm_private(struct drm_connector *connector)
> > > > > -{
> > > > > -	return container_of(connector, struct mxsfb_drm_private,
> > > > > -			    panel_connector);
> > > > > -}
> > > > > -
> > > > > -static int mxsfb_panel_get_modes(struct drm_connector *connector)
> > > > > -{
> > > > > -	struct mxsfb_drm_private *mxsfb =
> > > > > -			drm_connector_to_mxsfb_drm_private(connector);
> > > > > -
> > > > > -	if (mxsfb->panel)
> > > > > -		return drm_panel_get_modes(mxsfb->panel, connector);
> > > > > -
> > > > > -	return 0;
> > > > > -}
> > > > > -
> > > > > -static const struct
> > > > > -drm_connector_helper_funcs mxsfb_panel_connector_helper_funcs = {
> > > > > -	.get_modes = mxsfb_panel_get_modes,
> > > > > -};
> > > > > -
> > > > > -static enum drm_connector_status
> > > > > -mxsfb_panel_connector_detect(struct drm_connector *connector, bool force)
> > > > > -{
> > > > > -	struct mxsfb_drm_private *mxsfb =
> > > > > -			drm_connector_to_mxsfb_drm_private(connector);
> > > > > -
> > > > > -	if (mxsfb->panel)
> > > > > -		return connector_status_connected;
> > > > > -
> > > > > -	return connector_status_disconnected;
> > > > > -}
> > > > > -
> > > > > -static void mxsfb_panel_connector_destroy(struct drm_connector *connector)
> > > > > -{
> > > > > -	struct mxsfb_drm_private *mxsfb =
> > > > > -			drm_connector_to_mxsfb_drm_private(connector);
> > > > > -
> > > > > -	if (mxsfb->panel)
> > > > > -		drm_panel_detach(mxsfb->panel);
> > > > > -
> > > > > -	drm_connector_unregister(connector);
> > > > > -	drm_connector_cleanup(connector);
> > > > > -}
> > > > > -
> > > > > -static const struct drm_connector_funcs mxsfb_panel_connector_funcs = {
> > > > > -	.detect			= mxsfb_panel_connector_detect,
> > > > > -	.fill_modes		= drm_helper_probe_single_connector_modes,
> > > > > -	.destroy		= mxsfb_panel_connector_destroy,
> > > > > -	.reset			= drm_atomic_helper_connector_reset,
> > > > > -	.atomic_duplicate_state	= drm_atomic_helper_connector_duplicate_state,
> > > > > -	.atomic_destroy_state	= drm_atomic_helper_connector_destroy_state,
> > > > > -};
> > > > > -
> > > > > -int mxsfb_create_output(struct drm_device *drm)
> > > > > -{
> > > > > -	struct mxsfb_drm_private *mxsfb = drm->dev_private;
> > > > > -	int ret;
> > > > > -
> > > > > -	ret = drm_of_find_panel_or_bridge(drm->dev->of_node, 0, 0,
> > > > > -					  &mxsfb->panel, &mxsfb->bridge);
> > > > > -	if (ret)
> > > > > -		return ret;
> > > > > -
> > > > > -	if (mxsfb->panel) {
> > > > > -		mxsfb->connector = &mxsfb->panel_connector;
> > > > > -		mxsfb->connector->dpms = DRM_MODE_DPMS_OFF;
> > > > > -		mxsfb->connector->polled = 0;
> > > > > -		drm_connector_helper_add(mxsfb->connector,
> > > > > -					 &mxsfb_panel_connector_helper_funcs);
> > > > > -		ret = drm_connector_init(drm, mxsfb->connector,
> > > > > -					 &mxsfb_panel_connector_funcs,
> > > > > -					 DRM_MODE_CONNECTOR_Unknown);
> > > > > -	}
> > > > > -
> > > > > -	return ret;
> > > > > -}
> 
> -- 
> Regards,
> 
> Laurent Pinchart

-- 
Daniel Vetter
Software Engineer, Intel Corporation
http://blog.ffwll.ch
_______________________________________________
dri-devel mailing list
dri-devel@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/dri-devel

^ permalink raw reply	[flat|nested] 62+ messages in thread

* Re: [PATCH 02/21] drm: mxsfb: Use drm_panel_bridge
  2020-06-03  8:16           ` Daniel Vetter
@ 2020-06-04 20:10             ` Sam Ravnborg
  0 siblings, 0 replies; 62+ messages in thread
From: Sam Ravnborg @ 2020-06-04 20:10 UTC (permalink / raw)
  To: Daniel Vetter; +Cc: Marek Vasut, kernel, Laurent Pinchart, dri-devel, linux-imx

On Wed, Jun 03, 2020 at 10:16:17AM +0200, Daniel Vetter wrote:
> On Tue, Jun 02, 2020 at 08:13:17PM +0300, Laurent Pinchart wrote:
> > Hi Daniel,
> > 
> > On Tue, Jun 02, 2020 at 03:12:37PM +0200, Daniel Vetter wrote:
> > > On Sat, May 30, 2020 at 05:14:21AM +0300, Laurent Pinchart wrote:
> > > > On Mon, Mar 23, 2020 at 10:27:21PM +0100, Stefan Agner wrote:
> > > > > On 2020-03-09 20:51, Laurent Pinchart wrote:
> > > > > > Replace the manual connector implementation based on drm_panel with the
> > > > > > drm_panel_bridge helper. This simplifies the mxsfb driver by removing
> > > > > > connector-related code, and standardizing all pipeline control
> > > > > > operations on bridges.
> > > > > > 
> > > > > > A hack is needed to get hold of the connector, as that's our only source
> > > > > > of bus flags and formats for now. As soon as the bridge API provides us
> > > > > > with that information this can be fixed.
> > > > > 
> > > > > This seems like a nice simplification.
> > > > > 
> > > > > I gave this a go applied on today's drm-misc-next using a Colibri iMX7
> > > > > (imx7d-colibri-emmc-eval-v3.dts device tree). This device makes use of
> > > > > the simple panel driver. I get this when booting:
> > > > > 
> > > > > [    2.976698] [drm] Supports vblank timestamp caching Rev 2
> > > > > (21.10.2013).
> > > > > [    2.983526] ------------[ cut here ]------------
> > > > > [    2.988180] WARNING: CPU: 0 PID: 1 at
> > > > > drivers/gpu/drm/bridge/panel.c:267 devm_drm_panel_bridge_add+0x25/0x28
> > > > > [    2.998059] Modules linked in:
> > > > > [    3.001159] CPU: 0 PID: 1 Comm: swapper/0 Not tainted
> > > > > 5.6.0-rc5-yocto-standard-01250-ga4ce5db7c9f1 #29
> > > > > [    3.010493] Hardware name: Freescale i.MX7 Dual (Device Tree)
> > > > > [    3.016281] [<c010f089>] (unwind_backtrace) from [<c010a9bb>]
> > > > > (show_stack+0xb/0xc)
> > > > > [    3.023887] [<c010a9bb>] (show_stack) from [<c08b33cf>]
> > > > > (dump_stack+0x63/0x70)
> > > > > [    3.031144] [<c08b33cf>] (dump_stack) from [<c0124385>]
> > > > > (__warn+0x9d/0xb0)
> > > > > [    3.038047] [<c0124385>] (__warn) from [<c0124403>]
> > > > > (warn_slowpath_fmt+0x6b/0x70)
> > > > > [    3.045564] [<c0124403>] (warn_slowpath_fmt) from [<c04ebf65>]
> > > > > (devm_drm_panel_bridge_add+0x25/0x28)
> > > > > [    3.054736] [<c04ebf65>] (devm_drm_panel_bridge_add) from
> > > > > [<c051fe7f>] (mxsfb_probe+0x197/0x2e0)
> > > > > [    3.063559] [<c051fe7f>] (mxsfb_probe) from [<c0532e91>]
> > > > > (platform_drv_probe+0x2d/0x60)
> > > > > [    3.071598] [<c0532e91>] (platform_drv_probe) from [<c0531615>]
> > > > > (really_probe+0x1dd/0x330)
> > > > > [    3.079897] [<c0531615>] (really_probe) from [<c05318b3>]
> > > > > (driver_probe_device+0x4f/0x154)
> > > > > [    3.088195] [<c05318b3>] (driver_probe_device) from [<c0531b3f>]
> > > > > (device_driver_attach+0x37/0x44)
> > > > > [    3.097101] [<c0531b3f>] (device_driver_attach) from [<c0531bc7>]
> > > > > (__driver_attach+0x7b/0xec)
> > > > > [    3.105660] [<c0531bc7>] (__driver_attach) from [<c0530069>]
> > > > > (bus_for_each_dev+0x3d/0x64)
> > > > > [    3.113870] [<c0530069>] (bus_for_each_dev) from [<c0530b9b>]
> > > > > (bus_add_driver+0xef/0x160)
> > > > > [    3.122081] [<c0530b9b>] (bus_add_driver) from [<c053238d>]
> > > > > (driver_register+0x35/0x9c)
> > > > > [    3.130119] [<c053238d>] (driver_register) from [<c0102de9>]
> > > > > (do_one_initcall+0x3d/0x1e4)
> > > > > [    3.138333] [<c0102de9>] (do_one_initcall) from [<c1100d13>]
> > > > > (kernel_init_freeable+0x1b3/0x1fc)
> > > > > [    3.147069] [<c1100d13>] (kernel_init_freeable) from [<c08c3f7b>]
> > > > > (kernel_init+0x7/0xd0)
> > > > > [    3.155194] [<c08c3f7b>] (kernel_init) from [<c01010f9>]
> > > > > (ret_from_fork+0x11/0x38)
> > > > > [    3.162789] Exception stack(0xec0e3fb0 to 0xec0e3ff8)
> > > > > [    3.167862] 3fa0:                                     00000000
> > > > > 00000000 00000000 00000000
> > > > > [    3.176071] 3fc0: 00000000 00000000 00000000 00000000 00000000
> > > > > 00000000 00000000 00000000
> > > > > [    3.184278] 3fe0: 00000000 00000000 00000000 00000000 00000013
> > > > > 00000000
> > > > > [    3.191029] ---[ end trace b69e1f44de470959 ]---
> > > > > [    3.195671] mxsfb 30730000.lcdif: Cannot connect bridge: -19
> > > > > 
> > > > > Should we maybe use devm_drm_panel_bridge_add_typed?
> > > > 
> > > > As Sam reported, this is caused by the panel not setting connector_type.
> > > > We could use devm_drm_panel_bridge_add_typed(), even if I like the
> > > > warning as it uncovers the problematic panels and gets them fixed. What
> > > > would be your preference ?
> > > 
> > > Adding warnings everywhere is kinda uncool, at least my experience is that
> > > if there's too much you get warning overload and train people to ignore
> > > them.
> > > 
> > > Imo either hide the wwarning for now, or if it's not too much work, review
> > > all the panel drivers and make sure they set the connector type somewhere.
> > 
> > All panel drivers but panel-simple set the connector type. For
> > panel-simple, the type is stored in the panel_desc panel description,
> > and out of the 123 supported panels, only 48 have a connector type. I've
> > just sent a patch to fix this for the 7 DSI panels, so only 68 panels to
> > go :-) This will require trying to find the corresponding datasheets, so
> > that's a large effort for a single developer. That's why I was hoping a
> > WARN_ON() could help distributing the work :-) I hear your concern
> > though, and I'll set a default in this driver for the time being.
> 
> I think some fallback in simple-panel.c with maybe a fixme would be ok for
> this case. I don't think this has to be perfect, afaik userspace at best
> just checks "is this a panel", not which specific type.

I just applied Laurent's patch for the DSI panels in panel-simple.
In another patch-set posted as part of a bridge update I used
DRM_MODE_CONNECTOR_DPI as the default for all panels in panel-simple
that did not have any connector type specified.
I think this matches what you suggest above.

I will re-post the patch series when time permits.

	Sam

> -Daniel
> 
> > 
> > > Warnings are kinda ok once you're pretty sure you got them all, and want
> > > to make sure newly added drivers get this all right. But not before we've
> > > reached that.
> > > 
> > > > > Two more comments below.
> > > > > 
> > > > > > Signed-off-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
> > > > > > ---
> > > > > >  drivers/gpu/drm/mxsfb/Makefile    |   2 +-
> > > > > >  drivers/gpu/drm/mxsfb/mxsfb_drv.c | 105 ++++++++++++++----------------
> > > > > >  drivers/gpu/drm/mxsfb/mxsfb_drv.h |   5 +-
> > > > > >  drivers/gpu/drm/mxsfb/mxsfb_out.c |  99 ----------------------------
> > > > > >  4 files changed, 53 insertions(+), 158 deletions(-)
> > > > > >  delete mode 100644 drivers/gpu/drm/mxsfb/mxsfb_out.c
> > > > > > 
> > > > > > diff --git a/drivers/gpu/drm/mxsfb/Makefile b/drivers/gpu/drm/mxsfb/Makefile
> > > > > > index ff6e358088fa..811584e54ad1 100644
> > > > > > --- a/drivers/gpu/drm/mxsfb/Makefile
> > > > > > +++ b/drivers/gpu/drm/mxsfb/Makefile
> > > > > > @@ -1,3 +1,3 @@
> > > > > >  # SPDX-License-Identifier: GPL-2.0-only
> > > > > > -mxsfb-y := mxsfb_drv.o mxsfb_crtc.o mxsfb_out.o
> > > > > > +mxsfb-y := mxsfb_drv.o mxsfb_crtc.o
> > > > > >  obj-$(CONFIG_DRM_MXSFB)	+= mxsfb.o
> > > > > > diff --git a/drivers/gpu/drm/mxsfb/mxsfb_drv.c
> > > > > > b/drivers/gpu/drm/mxsfb/mxsfb_drv.c
> > > > > > index 2e6068d96034..cffc70257bd3 100644
> > > > > > --- a/drivers/gpu/drm/mxsfb/mxsfb_drv.c
> > > > > > +++ b/drivers/gpu/drm/mxsfb/mxsfb_drv.c
> > > > > > @@ -29,7 +29,6 @@
> > > > > >  #include <drm/drm_gem_framebuffer_helper.h>
> > > > > >  #include <drm/drm_irq.h>
> > > > > >  #include <drm/drm_of.h>
> > > > > > -#include <drm/drm_panel.h>
> > > > > >  #include <drm/drm_probe_helper.h>
> > > > > >  #include <drm/drm_simple_kms_helper.h>
> > > > > >  #include <drm/drm_vblank.h>
> > > > > > @@ -100,29 +99,11 @@ static void mxsfb_pipe_enable(struct
> > > > > > drm_simple_display_pipe *pipe,
> > > > > >  			      struct drm_crtc_state *crtc_state,
> > > > > >  			      struct drm_plane_state *plane_state)
> > > > > >  {
> > > > > > -	struct drm_connector *connector;
> > > > > >  	struct mxsfb_drm_private *mxsfb = drm_pipe_to_mxsfb_drm_private(pipe);
> > > > > >  	struct drm_device *drm = pipe->plane.dev;
> > > > > >  
> > > > > > -	if (!mxsfb->connector) {
> > > > > > -		list_for_each_entry(connector,
> > > > > > -				    &drm->mode_config.connector_list,
> > > > > > -				    head)
> > > > > > -			if (connector->encoder == &mxsfb->pipe.encoder) {
> > > > > > -				mxsfb->connector = connector;
> > > > > > -				break;
> > > > > > -			}
> > > > > > -	}
> > > > > > -
> > > > > > -	if (!mxsfb->connector) {
> > > > > > -		dev_warn(drm->dev, "No connector attached, using default\n");
> > > > > > -		mxsfb->connector = &mxsfb->panel_connector;
> > > > > > -	}
> > > > > > -
> > > > > >  	pm_runtime_get_sync(drm->dev);
> > > > > > -	drm_panel_prepare(mxsfb->panel);
> > > > > >  	mxsfb_crtc_enable(mxsfb);
> > > > > > -	drm_panel_enable(mxsfb->panel);
> > > > > >  }
> > > > > >  
> > > > > >  static void mxsfb_pipe_disable(struct drm_simple_display_pipe *pipe)
> > > > > > @@ -132,9 +113,7 @@ static void mxsfb_pipe_disable(struct
> > > > > > drm_simple_display_pipe *pipe)
> > > > > >  	struct drm_crtc *crtc = &pipe->crtc;
> > > > > >  	struct drm_pending_vblank_event *event;
> > > > > >  
> > > > > > -	drm_panel_disable(mxsfb->panel);
> > > > > >  	mxsfb_crtc_disable(mxsfb);
> > > > > > -	drm_panel_unprepare(mxsfb->panel);
> > > > > >  	pm_runtime_put_sync(drm->dev);
> > > > > >  
> > > > > >  	spin_lock_irq(&drm->event_lock);
> > > > > > @@ -144,9 +123,6 @@ static void mxsfb_pipe_disable(struct
> > > > > > drm_simple_display_pipe *pipe)
> > > > > >  		drm_crtc_send_vblank_event(crtc, event);
> > > > > >  	}
> > > > > >  	spin_unlock_irq(&drm->event_lock);
> > > > > > -
> > > > > > -	if (mxsfb->connector != &mxsfb->panel_connector)
> > > > > > -		mxsfb->connector = NULL;
> > > > > >  }
> > > > > >  
> > > > > >  static void mxsfb_pipe_update(struct drm_simple_display_pipe *pipe,
> > > > > > @@ -190,6 +166,48 @@ static struct drm_simple_display_pipe_funcs mxsfb_funcs = {
> > > > > >  	.disable_vblank	= mxsfb_pipe_disable_vblank,
> > > > > >  };
> > > > > >  
> > > > > > +static int mxsfb_attach_bridge(struct mxsfb_drm_private *mxsfb)
> > > > > > +{
> > > > > > +	struct drm_device *drm = mxsfb->drm;
> > > > > > +	struct drm_connector_list_iter iter;
> > > > > > +	struct drm_panel *panel;
> > > > > > +	struct drm_bridge *bridge;
> > > > > > +	int ret;
> > > > > > +
> > > > > > +	ret = drm_of_find_panel_or_bridge(drm->dev->of_node, 0, 0, &panel,
> > > > > > +					  &bridge);
> > > > > > +	if (ret)
> > > > > > +		return ret;
> > > > > > +
> > > > > > +	if (panel) {
> > > > > > +		bridge = devm_drm_panel_bridge_add(drm->dev, panel);
> > > > > 
> > > > > Do we need a select DRM_PANEL_BRIDGE in Kconfig maybe? From what I can
> > > > > tell there is no devm_drm_panel_bridge_add() stub if DRM_PANEL_BRIDGE is
> > > > > not selected.
> > > > 
> > > > You're right, I'll add it.
> > > > 
> > > > > > +		if (IS_ERR(bridge))
> > > > > > +			return PTR_ERR(bridge);
> > > > > > +	}
> > > > > > +
> > > > > > +	if (!bridge)
> > > > > > +		return -ENODEV;
> > > > > > +
> > > > > > +	ret = drm_simple_display_pipe_attach_bridge(&mxsfb->pipe, bridge);
> > > > > > +	if (ret) {
> > > > > > +		DRM_DEV_ERROR(drm->dev,
> > > > > > +			      "failed to attach bridge: %d\n", ret);
> > > > > > +		return ret;
> > > > > > +	}
> > > > > > +
> > > > > > +	mxsfb->bridge = bridge;
> > > > > > +
> > > > > > +	/*
> > > > > > +	 * Get hold of the connector. This is a bit of a hack, until the bridge
> > > > > > +	 * API gives us bus flags and formats.
> > > > > > +	 */
> > > > > > +	drm_connector_list_iter_begin(drm, &iter);
> > > > > > +	mxsfb->connector = drm_connector_list_iter_next(&iter);
> > > > > > +	drm_connector_list_iter_end(&iter);
> > > > > 
> > > > > Could we not just use drm_panel_bridge_connector() here?
> > > > 
> > > > There's no guarantee that mxsfb->bridge is a panel bridge, the LCDIF
> > > > output could be connected to another bridge in which case
> > > > drm_of_find_panel_or_bridge() will set panel to NULL and bridge to a
> > > > non-NULL value).
> > > > 
> > > > > > +
> > > > > > +	return 0;
> > > > > > +}
> > > > > > +
> > > > > >  static int mxsfb_load(struct drm_device *drm, unsigned long flags)
> > > > > >  {
> > > > > >  	struct platform_device *pdev = to_platform_device(drm->dev);
> > > > > > @@ -201,6 +219,7 @@ static int mxsfb_load(struct drm_device *drm,
> > > > > > unsigned long flags)
> > > > > >  	if (!mxsfb)
> > > > > >  		return -ENOMEM;
> > > > > >  
> > > > > > +	mxsfb->drm = drm;
> > > > > >  	drm->dev_private = mxsfb;
> > > > > >  	mxsfb->devdata = &mxsfb_devdata[pdev->id_entry->driver_data];
> > > > > >  
> > > > > > @@ -236,41 +255,17 @@ static int mxsfb_load(struct drm_device *drm,
> > > > > > unsigned long flags)
> > > > > >  	/* Modeset init */
> > > > > >  	drm_mode_config_init(drm);
> > > > > >  
> > > > > > -	ret = mxsfb_create_output(drm);
> > > > > > -	if (ret < 0) {
> > > > > > -		dev_err(drm->dev, "Failed to create outputs\n");
> > > > > > -		goto err_vblank;
> > > > > > -	}
> > > > > > -
> > > > > >  	ret = drm_simple_display_pipe_init(drm, &mxsfb->pipe, &mxsfb_funcs,
> > > > > > -			mxsfb_formats, ARRAY_SIZE(mxsfb_formats), NULL,
> > > > > > -			mxsfb->connector);
> > > > > > +			mxsfb_formats, ARRAY_SIZE(mxsfb_formats), NULL, NULL);
> > > > > >  	if (ret < 0) {
> > > > > >  		dev_err(drm->dev, "Cannot setup simple display pipe\n");
> > > > > >  		goto err_vblank;
> > > > > >  	}
> > > > > >  
> > > > > > -	/*
> > > > > > -	 * Attach panel only if there is one.
> > > > > > -	 * If there is no panel attach, it must be a bridge. In this case, we
> > > > > > -	 * need a reference to its connector for a proper initialization.
> > > > > > -	 * We will do this check in pipe->enable(), since the connector won't
> > > > > > -	 * be attached to an encoder until then.
> > > > > > -	 */
> > > > > > -
> > > > > > -	if (mxsfb->panel) {
> > > > > > -		ret = drm_panel_attach(mxsfb->panel, mxsfb->connector);
> > > > > > -		if (ret) {
> > > > > > -			dev_err(drm->dev, "Cannot connect panel: %d\n", ret);
> > > > > > -			goto err_vblank;
> > > > > > -		}
> > > > > > -	} else if (mxsfb->bridge) {
> > > > > > -		ret = drm_simple_display_pipe_attach_bridge(&mxsfb->pipe,
> > > > > > -							    mxsfb->bridge);
> > > > > > -		if (ret) {
> > > > > > -			dev_err(drm->dev, "Cannot connect bridge: %d\n", ret);
> > > > > > -			goto err_vblank;
> > > > > > -		}
> > > > > > +	ret = mxsfb_attach_bridge(mxsfb);
> > > > > > +	if (ret) {
> > > > > > +		dev_err(drm->dev, "Cannot connect bridge: %d\n", ret);
> > > > > > +		goto err_vblank;
> > > > > >  	}
> > > > > >  
> > > > > >  	drm->mode_config.min_width	= MXSFB_MIN_XRES;
> > > > > > @@ -288,7 +283,7 @@ static int mxsfb_load(struct drm_device *drm,
> > > > > > unsigned long flags)
> > > > > >  
> > > > > >  	if (ret < 0) {
> > > > > >  		dev_err(drm->dev, "Failed to install IRQ handler\n");
> > > > > > -		goto err_irq;
> > > > > > +		goto err_vblank;
> > > > > >  	}
> > > > > >  
> > > > > >  	drm_kms_helper_poll_init(drm);
> > > > > > @@ -299,8 +294,6 @@ static int mxsfb_load(struct drm_device *drm,
> > > > > > unsigned long flags)
> > > > > >  
> > > > > >  	return 0;
> > > > > >  
> > > > > > -err_irq:
> > > > > > -	drm_panel_detach(mxsfb->panel);
> > > > > >  err_vblank:
> > > > > >  	pm_runtime_disable(drm->dev);
> > > > > >  
> > > > > > diff --git a/drivers/gpu/drm/mxsfb/mxsfb_drv.h
> > > > > > b/drivers/gpu/drm/mxsfb/mxsfb_drv.h
> > > > > > index 0b65b5194a9c..0e3e5a63bbf9 100644
> > > > > > --- a/drivers/gpu/drm/mxsfb/mxsfb_drv.h
> > > > > > +++ b/drivers/gpu/drm/mxsfb/mxsfb_drv.h
> > > > > > @@ -8,6 +8,8 @@
> > > > > >  #ifndef __MXSFB_DRV_H__
> > > > > >  #define __MXSFB_DRV_H__
> > > > > >  
> > > > > > +struct drm_device;
> > > > > > +
> > > > > >  struct mxsfb_devdata {
> > > > > >  	unsigned int	 transfer_count;
> > > > > >  	unsigned int	 cur_buf;
> > > > > > @@ -26,10 +28,9 @@ struct mxsfb_drm_private {
> > > > > >  	struct clk			*clk_axi;
> > > > > >  	struct clk			*clk_disp_axi;
> > > > > >  
> > > > > > +	struct drm_device		*drm;
> > > > > >  	struct drm_simple_display_pipe	pipe;
> > > > > > -	struct drm_connector		panel_connector;
> > > > > >  	struct drm_connector		*connector;
> > > > > > -	struct drm_panel		*panel;
> > > > > >  	struct drm_bridge		*bridge;
> > > > > >  };
> > > > > >  
> > > > > > diff --git a/drivers/gpu/drm/mxsfb/mxsfb_out.c
> > > > > > b/drivers/gpu/drm/mxsfb/mxsfb_out.c
> > > > > > deleted file mode 100644
> > > > > > index 9eca1605d11d..000000000000
> > > > > > --- a/drivers/gpu/drm/mxsfb/mxsfb_out.c
> > > > > > +++ /dev/null
> > > > > > @@ -1,99 +0,0 @@
> > > > > > -// SPDX-License-Identifier: GPL-2.0-or-later
> > > > > > -/*
> > > > > > - * Copyright (C) 2016 Marek Vasut <marex@denx.de>
> > > > > > - */
> > > > > > -
> > > > > > -#include <linux/of_graph.h>
> > > > > > -
> > > > > > -#include <drm/drm_atomic.h>
> > > > > > -#include <drm/drm_atomic_helper.h>
> > > > > > -#include <drm/drm_crtc.h>
> > > > > > -#include <drm/drm_fb_cma_helper.h>
> > > > > > -#include <drm/drm_gem_cma_helper.h>
> > > > > > -#include <drm/drm_of.h>
> > > > > > -#include <drm/drm_panel.h>
> > > > > > -#include <drm/drm_plane_helper.h>
> > > > > > -#include <drm/drm_probe_helper.h>
> > > > > > -#include <drm/drm_simple_kms_helper.h>
> > > > > > -
> > > > > > -#include "mxsfb_drv.h"
> > > > > > -
> > > > > > -static struct mxsfb_drm_private *
> > > > > > -drm_connector_to_mxsfb_drm_private(struct drm_connector *connector)
> > > > > > -{
> > > > > > -	return container_of(connector, struct mxsfb_drm_private,
> > > > > > -			    panel_connector);
> > > > > > -}
> > > > > > -
> > > > > > -static int mxsfb_panel_get_modes(struct drm_connector *connector)
> > > > > > -{
> > > > > > -	struct mxsfb_drm_private *mxsfb =
> > > > > > -			drm_connector_to_mxsfb_drm_private(connector);
> > > > > > -
> > > > > > -	if (mxsfb->panel)
> > > > > > -		return drm_panel_get_modes(mxsfb->panel, connector);
> > > > > > -
> > > > > > -	return 0;
> > > > > > -}
> > > > > > -
> > > > > > -static const struct
> > > > > > -drm_connector_helper_funcs mxsfb_panel_connector_helper_funcs = {
> > > > > > -	.get_modes = mxsfb_panel_get_modes,
> > > > > > -};
> > > > > > -
> > > > > > -static enum drm_connector_status
> > > > > > -mxsfb_panel_connector_detect(struct drm_connector *connector, bool force)
> > > > > > -{
> > > > > > -	struct mxsfb_drm_private *mxsfb =
> > > > > > -			drm_connector_to_mxsfb_drm_private(connector);
> > > > > > -
> > > > > > -	if (mxsfb->panel)
> > > > > > -		return connector_status_connected;
> > > > > > -
> > > > > > -	return connector_status_disconnected;
> > > > > > -}
> > > > > > -
> > > > > > -static void mxsfb_panel_connector_destroy(struct drm_connector *connector)
> > > > > > -{
> > > > > > -	struct mxsfb_drm_private *mxsfb =
> > > > > > -			drm_connector_to_mxsfb_drm_private(connector);
> > > > > > -
> > > > > > -	if (mxsfb->panel)
> > > > > > -		drm_panel_detach(mxsfb->panel);
> > > > > > -
> > > > > > -	drm_connector_unregister(connector);
> > > > > > -	drm_connector_cleanup(connector);
> > > > > > -}
> > > > > > -
> > > > > > -static const struct drm_connector_funcs mxsfb_panel_connector_funcs = {
> > > > > > -	.detect			= mxsfb_panel_connector_detect,
> > > > > > -	.fill_modes		= drm_helper_probe_single_connector_modes,
> > > > > > -	.destroy		= mxsfb_panel_connector_destroy,
> > > > > > -	.reset			= drm_atomic_helper_connector_reset,
> > > > > > -	.atomic_duplicate_state	= drm_atomic_helper_connector_duplicate_state,
> > > > > > -	.atomic_destroy_state	= drm_atomic_helper_connector_destroy_state,
> > > > > > -};
> > > > > > -
> > > > > > -int mxsfb_create_output(struct drm_device *drm)
> > > > > > -{
> > > > > > -	struct mxsfb_drm_private *mxsfb = drm->dev_private;
> > > > > > -	int ret;
> > > > > > -
> > > > > > -	ret = drm_of_find_panel_or_bridge(drm->dev->of_node, 0, 0,
> > > > > > -					  &mxsfb->panel, &mxsfb->bridge);
> > > > > > -	if (ret)
> > > > > > -		return ret;
> > > > > > -
> > > > > > -	if (mxsfb->panel) {
> > > > > > -		mxsfb->connector = &mxsfb->panel_connector;
> > > > > > -		mxsfb->connector->dpms = DRM_MODE_DPMS_OFF;
> > > > > > -		mxsfb->connector->polled = 0;
> > > > > > -		drm_connector_helper_add(mxsfb->connector,
> > > > > > -					 &mxsfb_panel_connector_helper_funcs);
> > > > > > -		ret = drm_connector_init(drm, mxsfb->connector,
> > > > > > -					 &mxsfb_panel_connector_funcs,
> > > > > > -					 DRM_MODE_CONNECTOR_Unknown);
> > > > > > -	}
> > > > > > -
> > > > > > -	return ret;
> > > > > > -}
> > 
> > -- 
> > Regards,
> > 
> > Laurent Pinchart
> 
> -- 
> Daniel Vetter
> Software Engineer, Intel Corporation
> http://blog.ffwll.ch
> _______________________________________________
> dri-devel mailing list
> dri-devel@lists.freedesktop.org
> https://lists.freedesktop.org/mailman/listinfo/dri-devel
_______________________________________________
dri-devel mailing list
dri-devel@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/dri-devel

^ permalink raw reply	[flat|nested] 62+ messages in thread

end of thread, other threads:[~2020-06-04 20:10 UTC | newest]

Thread overview: 62+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2020-03-09 19:51 [PATCH 00/21] drm: mxsfb: Add i.MX7 support Laurent Pinchart
2020-03-09 19:51 ` [PATCH 01/21] drm: mxsfb: Remove fbdev leftovers Laurent Pinchart
2020-03-23 20:23   ` Stefan Agner
2020-03-09 19:51 ` [PATCH 02/21] drm: mxsfb: Use drm_panel_bridge Laurent Pinchart
2020-03-23 21:27   ` Stefan Agner
2020-03-23 21:38     ` Sam Ravnborg
2020-03-23 23:50       ` Stefan Agner
2020-05-30  2:14     ` Laurent Pinchart
2020-06-02 13:12       ` Daniel Vetter
2020-06-02 14:34         ` Stefan Agner
2020-06-02 17:18           ` Laurent Pinchart
2020-06-02 17:13         ` Laurent Pinchart
2020-06-03  8:16           ` Daniel Vetter
2020-06-04 20:10             ` Sam Ravnborg
2020-03-09 19:51 ` [PATCH 03/21] drm: mxsfb: Use BIT() macro to define register bitfields Laurent Pinchart
2020-03-23 21:34   ` Stefan Agner
2020-03-09 19:51 ` [PATCH 04/21] drm: mxsfb: Remove unused macros from mxsfb_regs.h Laurent Pinchart
2020-03-23 21:36   ` Stefan Agner
2020-03-09 19:52 ` [PATCH 05/21] drm: mxsfb: Clarify format and bus width configuration Laurent Pinchart
2020-03-23 21:42   ` Stefan Agner
2020-03-09 19:52 ` [PATCH 06/21] drm: mxsfb: Pass mxsfb_drm_private pointer to mxsfb_reset_block() Laurent Pinchart
2020-03-23 21:43   ` Stefan Agner
2020-03-09 19:52 ` [PATCH 07/21] drm: mxsfb: Use LCDC_CTRL register name explicitly Laurent Pinchart
2020-03-23 21:48   ` Stefan Agner
2020-03-09 19:52 ` [PATCH 08/21] drm: mxsfb: Remove register definitions from mxsfb_crtc.c Laurent Pinchart
2020-03-23 21:49   ` Stefan Agner
2020-03-09 19:52 ` [PATCH 09/21] drm: mxsfb: Remove unneeded includes Laurent Pinchart
2020-03-23 21:53   ` Stefan Agner
2020-05-30  0:33     ` Laurent Pinchart
2020-03-09 19:52 ` [PATCH 10/21] drm: mxsfb: Stop using DRM simple display pipeline helper Laurent Pinchart
2020-03-23 22:30   ` Stefan Agner
2020-03-09 19:52 ` [PATCH 11/21] drm: mxsfb: Rename mxsfb_crtc.c to mxsfb_kms.c Laurent Pinchart
2020-03-23 22:31   ` Stefan Agner
2020-03-09 19:52 ` [PATCH 12/21] drm: mxsfb: Move vblank event arm to CRTC .atomic_flush() Laurent Pinchart
2020-03-23 22:38   ` Stefan Agner
2020-03-09 19:52 ` [PATCH 13/21] drm: mxsfb: Don't touch AXI clock in IRQ context Laurent Pinchart
2020-03-23 22:50   ` Stefan Agner
2020-03-09 19:52 ` [PATCH 14/21] drm: mxsfb: Enable vblank handling Laurent Pinchart
2020-03-23 23:08   ` Stefan Agner
2020-03-24 10:37     ` Stefan Agner
2020-03-09 19:52 ` [PATCH 15/21] drm: mxsfb: Remove mxsfb_devdata unused fields Laurent Pinchart
2020-03-23 23:15   ` Stefan Agner
2020-03-09 19:52 ` [PATCH 16/21] drm: mxsfb: Add i.MX7 to the list of supported SoCs in Kconfig Laurent Pinchart
2020-03-10 16:28   ` Fabio Estevam
2020-03-10 16:32     ` Laurent Pinchart
2020-03-10 16:37       ` [PATCH v1.1 " Laurent Pinchart
2020-03-23 23:18   ` [PATCH " Stefan Agner
2020-03-09 19:52 ` [PATCH 17/21] drm: mxsfb: Update internal IP version number for i.MX6SX Laurent Pinchart
2020-03-23 23:20   ` Stefan Agner
2020-03-09 19:52 ` [PATCH 18/21] drm: mxsfb: Drop non-OF support Laurent Pinchart
2020-03-23 23:23   ` Stefan Agner
2020-03-09 19:52 ` [PATCH 19/21] drm: mxsfb: Turn mxsfb_set_pixel_fmt() into a void function Laurent Pinchart
2020-03-23 23:28   ` Stefan Agner
2020-03-09 19:52 ` [PATCH 20/21] drm: mxsfb: Merge mxsfb_set_pixel_fmt() and mxsfb_set_bus_fmt() Laurent Pinchart
2020-03-23 23:34   ` Stefan Agner
2020-03-09 19:52 ` [PATCH 21/21] drm: mxsfb: Support the alpha plane Laurent Pinchart
2020-03-23 23:48   ` Stefan Agner
2020-05-30  2:44     ` Laurent Pinchart
2020-03-19  9:36 ` [PATCH 00/21] drm: mxsfb: Add i.MX7 support Laurent Pinchart
2020-04-12 16:37 ` Guido Günther
2020-05-26 15:13 ` Stefan Agner
2020-05-30  0:29   ` Laurent Pinchart

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).