dri-devel.lists.freedesktop.org archive mirror
 help / color / mirror / Atom feed
* [PATCH v2 00/22] drm: mxsfb: Add i.MX7 support
@ 2020-05-30  3:09 Laurent Pinchart
  2020-05-30  3:09 ` [PATCH v2 01/22] drm: mxsfb: Remove fbdev leftovers Laurent Pinchart
                   ` (21 more replies)
  0 siblings, 22 replies; 40+ messages in thread
From: Laurent Pinchart @ 2020-05-30  3:09 UTC (permalink / raw)
  To: dri-devel; +Cc: Marek Vasut, linux-imx, kernel, robert.chiras, leonard.crestez

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 10 patches (01/22 to 10/22) contain miscellaneous cleanups and
refactoring to prepare for what is to come. Patch 11/22 starts the real
work with removal of the DRM simple display pipeline helper, as it
doesn't support multiple planes. The next patch (12/22) is an additional
cleanup.

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

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

The second plane suffers from an issue whose root cause hasn't been
found, which results in the first 64 bytes of the first line to contain
data of unknown origin. Help from NXP to diagnose this issue would be
useful and appreciated.

Compared to v1, the patches incorporate various review feedback, without
major modifications. See individual changelogs for details.

The code is based on v5.7-rc7 and has been tested on an i.MX7D platform
with a DPI panel. There is no conflict between v5.7-rc7 and
drm-misc-next for the mxsfb driver.

Laurent Pinchart (22):
  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: Rename mxsfb_crtc.c to mxsfb_kms.c
  drm: mxsfb: Stop using DRM simple display pipeline helper
  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 and i.MX8M 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: Remove unnecessary spaces after tab
  drm: mxsfb: Support the alpha plane

 drivers/gpu/drm/mxsfb/Kconfig      |   8 +-
 drivers/gpu/drm/mxsfb/Makefile     |   2 +-
 drivers/gpu/drm/mxsfb/mxsfb_crtc.c | 343 -----------------
 drivers/gpu/drm/mxsfb/mxsfb_drv.c  | 248 ++++---------
 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 | 103 +++---
 8 files changed, 732 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] 40+ messages in thread

* [PATCH v2 01/22] drm: mxsfb: Remove fbdev leftovers
  2020-05-30  3:09 [PATCH v2 00/22] drm: mxsfb: Add i.MX7 support Laurent Pinchart
@ 2020-05-30  3:09 ` Laurent Pinchart
  2020-05-30  3:09 ` [PATCH v2 02/22] drm: mxsfb: Use drm_panel_bridge Laurent Pinchart
                   ` (20 subsequent siblings)
  21 siblings, 0 replies; 40+ messages in thread
From: Laurent Pinchart @ 2020-05-30  3:09 UTC (permalink / raw)
  To: dri-devel; +Cc: Marek Vasut, linux-imx, kernel, robert.chiras, leonard.crestez

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>
---
 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] 40+ messages in thread

* [PATCH v2 02/22] drm: mxsfb: Use drm_panel_bridge
  2020-05-30  3:09 [PATCH v2 00/22] drm: mxsfb: Add i.MX7 support Laurent Pinchart
  2020-05-30  3:09 ` [PATCH v2 01/22] drm: mxsfb: Remove fbdev leftovers Laurent Pinchart
@ 2020-05-30  3:09 ` Laurent Pinchart
  2020-06-17 15:25   ` Stefan Agner
  2020-05-30  3:09 ` [PATCH v2 03/22] drm: mxsfb: Use BIT() macro to define register bitfields Laurent Pinchart
                   ` (19 subsequent siblings)
  21 siblings, 1 reply; 40+ messages in thread
From: Laurent Pinchart @ 2020-05-30  3:09 UTC (permalink / raw)
  To: dri-devel; +Cc: Marek Vasut, linux-imx, kernel, robert.chiras, leonard.crestez

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>
---
Changes since v1:

- Select DRM_PANEL_BRIDGE in Kconfig
---
 drivers/gpu/drm/mxsfb/Kconfig     |   1 +
 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 ----------------------------
 5 files changed, 54 insertions(+), 158 deletions(-)
 delete mode 100644 drivers/gpu/drm/mxsfb/mxsfb_out.c

diff --git a/drivers/gpu/drm/mxsfb/Kconfig b/drivers/gpu/drm/mxsfb/Kconfig
index 0dca8f27169e..e43b326e9147 100644
--- a/drivers/gpu/drm/mxsfb/Kconfig
+++ b/drivers/gpu/drm/mxsfb/Kconfig
@@ -13,6 +13,7 @@ config DRM_MXSFB
 	select DRM_KMS_FB_HELPER
 	select DRM_KMS_CMA_HELPER
 	select DRM_PANEL
+	select DRM_PANEL_BRIDGE
 	help
 	  Choose this option if you have an i.MX23/i.MX28/i.MX6SX MXSFB
 	  LCD controller.
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] 40+ messages in thread

* [PATCH v2 03/22] drm: mxsfb: Use BIT() macro to define register bitfields
  2020-05-30  3:09 [PATCH v2 00/22] drm: mxsfb: Add i.MX7 support Laurent Pinchart
  2020-05-30  3:09 ` [PATCH v2 01/22] drm: mxsfb: Remove fbdev leftovers Laurent Pinchart
  2020-05-30  3:09 ` [PATCH v2 02/22] drm: mxsfb: Use drm_panel_bridge Laurent Pinchart
@ 2020-05-30  3:09 ` Laurent Pinchart
  2020-05-30  3:09 ` [PATCH v2 04/22] drm: mxsfb: Remove unused macros from mxsfb_regs.h Laurent Pinchart
                   ` (18 subsequent siblings)
  21 siblings, 0 replies; 40+ messages in thread
From: Laurent Pinchart @ 2020-05-30  3:09 UTC (permalink / raw)
  To: dri-devel; +Cc: Marek Vasut, linux-imx, kernel, robert.chiras, leonard.crestez

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
-- 
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] 40+ messages in thread

* [PATCH v2 04/22] drm: mxsfb: Remove unused macros from mxsfb_regs.h
  2020-05-30  3:09 [PATCH v2 00/22] drm: mxsfb: Add i.MX7 support Laurent Pinchart
                   ` (2 preceding siblings ...)
  2020-05-30  3:09 ` [PATCH v2 03/22] drm: mxsfb: Use BIT() macro to define register bitfields Laurent Pinchart
@ 2020-05-30  3:09 ` Laurent Pinchart
  2020-05-30  3:09 ` [PATCH v2 05/22] drm: mxsfb: Clarify format and bus width configuration Laurent Pinchart
                   ` (17 subsequent siblings)
  21 siblings, 0 replies; 40+ messages in thread
From: Laurent Pinchart @ 2020-05-30  3:09 UTC (permalink / raw)
  To: dri-devel; +Cc: Marek Vasut, linux-imx, kernel, robert.chiras, leonard.crestez

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__ */
-- 
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] 40+ messages in thread

* [PATCH v2 05/22] drm: mxsfb: Clarify format and bus width configuration
  2020-05-30  3:09 [PATCH v2 00/22] drm: mxsfb: Add i.MX7 support Laurent Pinchart
                   ` (3 preceding siblings ...)
  2020-05-30  3:09 ` [PATCH v2 04/22] drm: mxsfb: Remove unused macros from mxsfb_regs.h Laurent Pinchart
@ 2020-05-30  3:09 ` Laurent Pinchart
  2020-05-30  3:09 ` [PATCH v2 06/22] drm: mxsfb: Pass mxsfb_drm_private pointer to mxsfb_reset_block() Laurent Pinchart
                   ` (16 subsequent siblings)
  21 siblings, 0 replies; 40+ messages in thread
From: Laurent Pinchart @ 2020-05-30  3:09 UTC (permalink / raw)
  To: dri-devel; +Cc: Marek Vasut, linux-imx, kernel, robert.chiras, leonard.crestez

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>
Reviewed-by: Stefan Agner <stefan@agner.ch>
---
 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] 40+ messages in thread

* [PATCH v2 06/22] drm: mxsfb: Pass mxsfb_drm_private pointer to mxsfb_reset_block()
  2020-05-30  3:09 [PATCH v2 00/22] drm: mxsfb: Add i.MX7 support Laurent Pinchart
                   ` (4 preceding siblings ...)
  2020-05-30  3:09 ` [PATCH v2 05/22] drm: mxsfb: Clarify format and bus width configuration Laurent Pinchart
@ 2020-05-30  3:09 ` Laurent Pinchart
  2020-05-30  3:10 ` [PATCH v2 07/22] drm: mxsfb: Use LCDC_CTRL register name explicitly Laurent Pinchart
                   ` (15 subsequent siblings)
  21 siblings, 0 replies; 40+ messages in thread
From: Laurent Pinchart @ 2020-05-30  3:09 UTC (permalink / raw)
  To: dri-devel; +Cc: Marek Vasut, linux-imx, kernel, robert.chiras, leonard.crestez

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;
 
-- 
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] 40+ messages in thread

* [PATCH v2 07/22] drm: mxsfb: Use LCDC_CTRL register name explicitly
  2020-05-30  3:09 [PATCH v2 00/22] drm: mxsfb: Add i.MX7 support Laurent Pinchart
                   ` (5 preceding siblings ...)
  2020-05-30  3:09 ` [PATCH v2 06/22] drm: mxsfb: Pass mxsfb_drm_private pointer to mxsfb_reset_block() Laurent Pinchart
@ 2020-05-30  3:10 ` Laurent Pinchart
  2020-05-30  3:10 ` [PATCH v2 08/22] drm: mxsfb: Remove register definitions from mxsfb_crtc.c Laurent Pinchart
                   ` (14 subsequent siblings)
  21 siblings, 0 replies; 40+ messages in thread
From: Laurent Pinchart @ 2020-05-30  3:10 UTC (permalink / raw)
  To: dri-devel; +Cc: Marek Vasut, linux-imx, kernel, robert.chiras, leonard.crestez

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)
-- 
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] 40+ messages in thread

* [PATCH v2 08/22] drm: mxsfb: Remove register definitions from mxsfb_crtc.c
  2020-05-30  3:09 [PATCH v2 00/22] drm: mxsfb: Add i.MX7 support Laurent Pinchart
                   ` (6 preceding siblings ...)
  2020-05-30  3:10 ` [PATCH v2 07/22] drm: mxsfb: Use LCDC_CTRL register name explicitly Laurent Pinchart
@ 2020-05-30  3:10 ` Laurent Pinchart
  2020-05-30  3:10 ` [PATCH v2 09/22] drm: mxsfb: Remove unneeded includes Laurent Pinchart
                   ` (13 subsequent siblings)
  21 siblings, 0 replies; 40+ messages in thread
From: Laurent Pinchart @ 2020-05-30  3:10 UTC (permalink / raw)
  To: dri-devel; +Cc: Marek Vasut, linux-imx, kernel, robert.chiras, leonard.crestez

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)
-- 
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] 40+ messages in thread

* [PATCH v2 09/22] drm: mxsfb: Remove unneeded includes
  2020-05-30  3:09 [PATCH v2 00/22] drm: mxsfb: Add i.MX7 support Laurent Pinchart
                   ` (7 preceding siblings ...)
  2020-05-30  3:10 ` [PATCH v2 08/22] drm: mxsfb: Remove register definitions from mxsfb_crtc.c Laurent Pinchart
@ 2020-05-30  3:10 ` Laurent Pinchart
  2020-05-30  3:10 ` [PATCH v2 10/22] drm: mxsfb: Rename mxsfb_crtc.c to mxsfb_kms.c Laurent Pinchart
                   ` (12 subsequent siblings)
  21 siblings, 0 replies; 40+ messages in thread
From: Laurent Pinchart @ 2020-05-30  3:10 UTC (permalink / raw)
  To: dri-devel; +Cc: Marek Vasut, linux-imx, kernel, robert.chiras, leonard.crestez

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>
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 related	[flat|nested] 40+ messages in thread

* [PATCH v2 10/22] drm: mxsfb: Rename mxsfb_crtc.c to mxsfb_kms.c
  2020-05-30  3:09 [PATCH v2 00/22] drm: mxsfb: Add i.MX7 support Laurent Pinchart
                   ` (8 preceding siblings ...)
  2020-05-30  3:10 ` [PATCH v2 09/22] drm: mxsfb: Remove unneeded includes Laurent Pinchart
@ 2020-05-30  3:10 ` Laurent Pinchart
  2020-05-30  3:10 ` [PATCH v2 11/22] drm: mxsfb: Stop using DRM simple display pipeline helper Laurent Pinchart
                   ` (11 subsequent siblings)
  21 siblings, 0 replies; 40+ messages in thread
From: Laurent Pinchart @ 2020-05-30  3:10 UTC (permalink / raw)
  To: dri-devel; +Cc: Marek Vasut, linux-imx, kernel, robert.chiras, leonard.crestez

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
-- 
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] 40+ messages in thread

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

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>
---
Changes since v1:

- Move after mxsfb_crtc.c rename to mxsfb_kms.c
---
 drivers/gpu/drm/mxsfb/mxsfb_drv.c | 108 +++---------------
 drivers/gpu/drm/mxsfb/mxsfb_drv.h |  23 ++--
 drivers/gpu/drm/mxsfb/mxsfb_kms.c | 184 +++++++++++++++++++++++++++---
 3 files changed, 197 insertions(+), 118 deletions(-)

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__ */
diff --git a/drivers/gpu/drm/mxsfb/mxsfb_kms.c b/drivers/gpu/drm/mxsfb/mxsfb_kms.c
index c4f1575b4210..8f339adb8d04 100644
--- a/drivers/gpu/drm/mxsfb/mxsfb_kms.c
+++ b/drivers/gpu/drm/mxsfb/mxsfb_kms.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);
+}
-- 
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] 40+ messages in thread

* [PATCH v2 12/22] drm: mxsfb: Move vblank event arm to CRTC .atomic_flush()
  2020-05-30  3:09 [PATCH v2 00/22] drm: mxsfb: Add i.MX7 support Laurent Pinchart
                   ` (10 preceding siblings ...)
  2020-05-30  3:10 ` [PATCH v2 11/22] drm: mxsfb: Stop using DRM simple display pipeline helper Laurent Pinchart
@ 2020-05-30  3:10 ` Laurent Pinchart
  2020-05-30  3:10 ` [PATCH v2 13/22] drm: mxsfb: Don't touch AXI clock in IRQ context Laurent Pinchart
                   ` (9 subsequent siblings)
  21 siblings, 0 replies; 40+ messages in thread
From: Laurent Pinchart @ 2020-05-30  3:10 UTC (permalink / raw)
  To: dri-devel; +Cc: Marek Vasut, linux-imx, kernel, robert.chiras, leonard.crestez

The vblank event is armed in the plane .atomic_update(). This works fine
as we have a single plane, and was the only option when the driver was
using the drm_simple_kms_helper helper, but will break as soon as
multiple planes are supported. Move it to CRTC .atomic_flush().

Signed-off-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
Reviewed-by: Stefan Agner <stefan@agner.ch>
---
Changes since v1:

- Reword commit message
---
 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] 40+ messages in thread

* [PATCH v2 13/22] drm: mxsfb: Don't touch AXI clock in IRQ context
  2020-05-30  3:09 [PATCH v2 00/22] drm: mxsfb: Add i.MX7 support Laurent Pinchart
                   ` (11 preceding siblings ...)
  2020-05-30  3:10 ` [PATCH v2 12/22] drm: mxsfb: Move vblank event arm to CRTC .atomic_flush() Laurent Pinchart
@ 2020-05-30  3:10 ` Laurent Pinchart
  2020-05-30  3:10 ` [PATCH v2 14/22] drm: mxsfb: Enable vblank handling Laurent Pinchart
                   ` (8 subsequent siblings)
  21 siblings, 0 replies; 40+ messages in thread
From: Laurent Pinchart @ 2020-05-30  3:10 UTC (permalink / raw)
  To: dri-devel; +Cc: Marek Vasut, linux-imx, kernel, robert.chiras, leonard.crestez

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>
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 = {
-- 
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] 40+ messages in thread

* [PATCH v2 14/22] drm: mxsfb: Enable vblank handling
  2020-05-30  3:09 [PATCH v2 00/22] drm: mxsfb: Add i.MX7 support Laurent Pinchart
                   ` (12 preceding siblings ...)
  2020-05-30  3:10 ` [PATCH v2 13/22] drm: mxsfb: Don't touch AXI clock in IRQ context Laurent Pinchart
@ 2020-05-30  3:10 ` Laurent Pinchart
  2020-06-11 18:35   ` Stefan Agner
  2020-05-30  3:10 ` [PATCH v2 15/22] drm: mxsfb: Remove mxsfb_devdata unused fields Laurent Pinchart
                   ` (7 subsequent siblings)
  21 siblings, 1 reply; 40+ messages in thread
From: Laurent Pinchart @ 2020-05-30  3:10 UTC (permalink / raw)
  To: dri-devel; +Cc: Marek Vasut, linux-imx, kernel, robert.chiras, leonard.crestez

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] 40+ messages in thread

* [PATCH v2 15/22] drm: mxsfb: Remove mxsfb_devdata unused fields
  2020-05-30  3:09 [PATCH v2 00/22] drm: mxsfb: Add i.MX7 support Laurent Pinchart
                   ` (13 preceding siblings ...)
  2020-05-30  3:10 ` [PATCH v2 14/22] drm: mxsfb: Enable vblank handling Laurent Pinchart
@ 2020-05-30  3:10 ` Laurent Pinchart
  2020-05-30  3:10 ` [PATCH v2 16/22] drm: mxsfb: Add i.MX7 and i.MX8M to the list of supported SoCs in Kconfig Laurent Pinchart
                   ` (6 subsequent siblings)
  21 siblings, 0 replies; 40+ messages in thread
From: Laurent Pinchart @ 2020-05-30  3:10 UTC (permalink / raw)
  To: dri-devel; +Cc: Marek Vasut, linux-imx, kernel, robert.chiras, leonard.crestez

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 {
-- 
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] 40+ messages in thread

* [PATCH v2 16/22] drm: mxsfb: Add i.MX7 and i.MX8M to the list of supported SoCs in Kconfig
  2020-05-30  3:09 [PATCH v2 00/22] drm: mxsfb: Add i.MX7 support Laurent Pinchart
                   ` (14 preceding siblings ...)
  2020-05-30  3:10 ` [PATCH v2 15/22] drm: mxsfb: Remove mxsfb_devdata unused fields Laurent Pinchart
@ 2020-05-30  3:10 ` Laurent Pinchart
  2020-06-11 18:37   ` Stefan Agner
  2020-05-30  3:10 ` [PATCH v2 17/22] drm: mxsfb: Update internal IP version number for i.MX6SX Laurent Pinchart
                   ` (5 subsequent siblings)
  21 siblings, 1 reply; 40+ messages in thread
From: Laurent Pinchart @ 2020-05-30  3:10 UTC (permalink / raw)
  To: dri-devel; +Cc: Marek Vasut, linux-imx, kernel, robert.chiras, leonard.crestez

Extend the Kconfig option description by listing the i.MX7 and i.MX8M
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>
---
Changes since v1:

- Make description more explicit by mentioning LCDIF and eLCDIF
- Add i.MX8M
---
 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 e43b326e9147..0143d539f8f8 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
@@ -15,7 +15,8 @@ config DRM_MXSFB
 	select DRM_PANEL
 	select DRM_PANEL_BRIDGE
 	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, i.MX7 and i.MX8M).
 
 	  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] 40+ messages in thread

* [PATCH v2 17/22] drm: mxsfb: Update internal IP version number for i.MX6SX
  2020-05-30  3:09 [PATCH v2 00/22] drm: mxsfb: Add i.MX7 support Laurent Pinchart
                   ` (15 preceding siblings ...)
  2020-05-30  3:10 ` [PATCH v2 16/22] drm: mxsfb: Add i.MX7 and i.MX8M to the list of supported SoCs in Kconfig Laurent Pinchart
@ 2020-05-30  3:10 ` Laurent Pinchart
  2020-05-30  3:10 ` [PATCH v2 18/22] drm: mxsfb: Drop non-OF support Laurent Pinchart
                   ` (4 subsequent siblings)
  21 siblings, 0 replies; 40+ messages in thread
From: Laurent Pinchart @ 2020-05-30  3:10 UTC (permalink / raw)
  To: dri-devel; +Cc: Marek Vasut, linux-imx, kernel, robert.chiras, leonard.crestez

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);
-- 
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] 40+ messages in thread

* [PATCH v2 18/22] drm: mxsfb: Drop non-OF support
  2020-05-30  3:09 [PATCH v2 00/22] drm: mxsfb: Add i.MX7 support Laurent Pinchart
                   ` (16 preceding siblings ...)
  2020-05-30  3:10 ` [PATCH v2 17/22] drm: mxsfb: Update internal IP version number for i.MX6SX Laurent Pinchart
@ 2020-05-30  3:10 ` Laurent Pinchart
  2020-05-30  3:10 ` [PATCH v2 19/22] drm: mxsfb: Turn mxsfb_set_pixel_fmt() into a void function Laurent Pinchart
                   ` (3 subsequent siblings)
  21 siblings, 0 replies; 40+ messages in thread
From: Laurent Pinchart @ 2020-05-30  3:10 UTC (permalink / raw)
  To: dri-devel; +Cc: Marek Vasut, linux-imx, kernel, robert.chiras, leonard.crestez

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

Signed-off-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
Reviewed-by: Stefan Agner <stefan@agner.ch>
---
 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] 40+ messages in thread

* [PATCH v2 19/22] drm: mxsfb: Turn mxsfb_set_pixel_fmt() into a void function
  2020-05-30  3:09 [PATCH v2 00/22] drm: mxsfb: Add i.MX7 support Laurent Pinchart
                   ` (17 preceding siblings ...)
  2020-05-30  3:10 ` [PATCH v2 18/22] drm: mxsfb: Drop non-OF support Laurent Pinchart
@ 2020-05-30  3:10 ` Laurent Pinchart
  2020-05-30  3:10 ` [PATCH v2 20/22] drm: mxsfb: Merge mxsfb_set_pixel_fmt() and mxsfb_set_bus_fmt() Laurent Pinchart
                   ` (2 subsequent siblings)
  21 siblings, 0 replies; 40+ messages in thread
From: Laurent Pinchart @ 2020-05-30  3:10 UTC (permalink / raw)
  To: dri-devel; +Cc: Marek Vasut, linux-imx, kernel, robert.chiras, leonard.crestez

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>
Reviewed-by: Stefan Agner <stefan@agner.ch>
---
 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] 40+ messages in thread

* [PATCH v2 20/22] drm: mxsfb: Merge mxsfb_set_pixel_fmt() and mxsfb_set_bus_fmt()
  2020-05-30  3:09 [PATCH v2 00/22] drm: mxsfb: Add i.MX7 support Laurent Pinchart
                   ` (18 preceding siblings ...)
  2020-05-30  3:10 ` [PATCH v2 19/22] drm: mxsfb: Turn mxsfb_set_pixel_fmt() into a void function Laurent Pinchart
@ 2020-05-30  3:10 ` Laurent Pinchart
  2020-06-05 14:58   ` Emil Velikov
  2020-05-30  3:10 ` [PATCH v2 21/22] drm: mxsfb: Remove unnecessary spaces after tab Laurent Pinchart
  2020-05-30  3:10 ` [PATCH v2 22/22] drm: mxsfb: Support the alpha plane Laurent Pinchart
  21 siblings, 1 reply; 40+ messages in thread
From: Laurent Pinchart @ 2020-05-30  3:10 UTC (permalink / raw)
  To: dri-devel; +Cc: Marek Vasut, linux-imx, kernel, robert.chiras, leonard.crestez

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);
 
-- 
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] 40+ messages in thread

* [PATCH v2 21/22] drm: mxsfb: Remove unnecessary spaces after tab
  2020-05-30  3:09 [PATCH v2 00/22] drm: mxsfb: Add i.MX7 support Laurent Pinchart
                   ` (19 preceding siblings ...)
  2020-05-30  3:10 ` [PATCH v2 20/22] drm: mxsfb: Merge mxsfb_set_pixel_fmt() and mxsfb_set_bus_fmt() Laurent Pinchart
@ 2020-05-30  3:10 ` Laurent Pinchart
  2020-06-11 19:11   ` Stefan Agner
  2020-05-30  3:10 ` [PATCH v2 22/22] drm: mxsfb: Support the alpha plane Laurent Pinchart
  21 siblings, 1 reply; 40+ messages in thread
From: Laurent Pinchart @ 2020-05-30  3:10 UTC (permalink / raw)
  To: dri-devel; +Cc: Marek Vasut, linux-imx, kernel, robert.chiras, leonard.crestez

This is a cosmetic change only, no code change is included.

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

diff --git a/drivers/gpu/drm/mxsfb/mxsfb_drv.h b/drivers/gpu/drm/mxsfb/mxsfb_drv.h
index 607a6a5e6be3..f883b56caed3 100644
--- a/drivers/gpu/drm/mxsfb/mxsfb_drv.h
+++ b/drivers/gpu/drm/mxsfb/mxsfb_drv.h
@@ -16,11 +16,11 @@
 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;
 };
 
 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] 40+ messages in thread

* [PATCH v2 22/22] drm: mxsfb: Support the alpha plane
  2020-05-30  3:09 [PATCH v2 00/22] drm: mxsfb: Add i.MX7 support Laurent Pinchart
                   ` (20 preceding siblings ...)
  2020-05-30  3:10 ` [PATCH v2 21/22] drm: mxsfb: Remove unnecessary spaces after tab Laurent Pinchart
@ 2020-05-30  3:10 ` Laurent Pinchart
  2020-05-31 16:54   ` Emil Velikov
  2020-06-17 16:08   ` Stefan Agner
  21 siblings, 2 replies; 40+ messages in thread
From: Laurent Pinchart @ 2020-05-30  3:10 UTC (permalink / raw)
  To: dri-devel; +Cc: Marek Vasut, linux-imx, kernel, robert.chiras, leonard.crestez

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>
---
Changes since v1:

- Split whitespace cleanup to a separate patch
---
 drivers/gpu/drm/mxsfb/mxsfb_drv.c  |   3 +
 drivers/gpu/drm/mxsfb/mxsfb_drv.h  |   6 +-
 drivers/gpu/drm/mxsfb/mxsfb_kms.c  | 129 +++++++++++++++++++++++++----
 drivers/gpu/drm/mxsfb/mxsfb_regs.h |  22 +++++
 4 files changed, 144 insertions(+), 16 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 f883b56caed3..399d23e91ed1 100644
--- a/drivers/gpu/drm/mxsfb/mxsfb_drv.h
+++ b/drivers/gpu/drm/mxsfb/mxsfb_drv.h
@@ -21,6 +21,7 @@ struct mxsfb_devdata {
 	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_atomic_update,
+	.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_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,
-	DRM_FORMAT_RGB565
 };
 
+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_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] 40+ messages in thread

* Re: [PATCH v2 22/22] drm: mxsfb: Support the alpha plane
  2020-05-30  3:10 ` [PATCH v2 22/22] drm: mxsfb: Support the alpha plane Laurent Pinchart
@ 2020-05-31 16:54   ` Emil Velikov
  2020-06-02 22:42     ` Laurent Pinchart
  2020-06-17 16:08   ` Stefan Agner
  1 sibling, 1 reply; 40+ messages in thread
From: Emil Velikov @ 2020-05-31 16:54 UTC (permalink / raw)
  To: Laurent Pinchart
  Cc: Marek Vasut, ML dri-devel, NXP Linux Team, Sascha Hauer,
	Robert Chiras, leonard.crestez

HI Laurent,

From a quick glance the series looks really good and neat. Then again,
I don't know much about the hardware to provide meaningful review.

A couple of small ideas below.

On Sat, 30 May 2020 at 04:11, Laurent Pinchart
<laurent.pinchart@ideasonboard.com> wrote:

> +#define LCDC_AS_BUF                    0x220
> +#define LCDC_AS_NEXT_BUF               0x230

s/LCDC_AS_BUF/LCDC_AS_CUR_BUF/ - to stay consistent with the primary
plane name scheme.

Would it make sense to store the above registers in mxsfb_devdata,
just like we do for the primary planes?

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

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

* Re: [PATCH v2 22/22] drm: mxsfb: Support the alpha plane
  2020-05-31 16:54   ` Emil Velikov
@ 2020-06-02 22:42     ` Laurent Pinchart
  2020-06-05 14:07       ` Emil Velikov
  0 siblings, 1 reply; 40+ messages in thread
From: Laurent Pinchart @ 2020-06-02 22:42 UTC (permalink / raw)
  To: Emil Velikov
  Cc: Marek Vasut, ML dri-devel, NXP Linux Team, Sascha Hauer,
	Robert Chiras, leonard.crestez

Hi Emil,

On Sun, May 31, 2020 at 05:54:04PM +0100, Emil Velikov wrote:
> HI Laurent,
> 
> From a quick glance the series looks really good and neat.

Thank you :-)

> Then again, I don't know much about the hardware to provide meaningful
> review.
>
> A couple of small ideas below.
> 
> On Sat, 30 May 2020 at 04:11, Laurent Pinchart wrote:
> 
> > +#define LCDC_AS_BUF                    0x220
> > +#define LCDC_AS_NEXT_BUF               0x230
> 
> s/LCDC_AS_BUF/LCDC_AS_CUR_BUF/ - to stay consistent with the primary
> plane name scheme.

The register names come directly from the datasheet (and yes, the
datasheet uses CUR_BUF and NEXT_BUF for the primary plane, and BUF and
NEXT_BUF for the overlay plane :-S). I'd thus rather keep them aligned
with the documentation.

> Would it make sense to store the above registers in mxsfb_devdata,
> just like we do for the primary planes?

The reason the register addresses are stored in mxsfb_devdata for the
primary plane is because they differ between hardware revisions (don't
they teach hardware engineers in school these days *not* to move
registers around ? :-)). The overlay plane is only supported in the
latest versions of the IP core, and are always located at the same
address as far as I can tell. I don't think we need an extra level of
indirection.

-- 
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] 40+ messages in thread

* Re: [PATCH v2 22/22] drm: mxsfb: Support the alpha plane
  2020-06-02 22:42     ` Laurent Pinchart
@ 2020-06-05 14:07       ` Emil Velikov
  0 siblings, 0 replies; 40+ messages in thread
From: Emil Velikov @ 2020-06-05 14:07 UTC (permalink / raw)
  To: Laurent Pinchart
  Cc: Marek Vasut, ML dri-devel, NXP Linux Team, Sascha Hauer,
	Robert Chiras, leonard.crestez

On Tue, 2 Jun 2020 at 23:43, Laurent Pinchart
<laurent.pinchart@ideasonboard.com> wrote:
>
> Hi Emil,
>
> On Sun, May 31, 2020 at 05:54:04PM +0100, Emil Velikov wrote:
> > HI Laurent,
> >
> > From a quick glance the series looks really good and neat.
>
> Thank you :-)
>
> > Then again, I don't know much about the hardware to provide meaningful
> > review.
> >
> > A couple of small ideas below.
> >
> > On Sat, 30 May 2020 at 04:11, Laurent Pinchart wrote:
> >
> > > +#define LCDC_AS_BUF                    0x220
> > > +#define LCDC_AS_NEXT_BUF               0x230
> >
> > s/LCDC_AS_BUF/LCDC_AS_CUR_BUF/ - to stay consistent with the primary
> > plane name scheme.
>
> The register names come directly from the datasheet (and yes, the
> datasheet uses CUR_BUF and NEXT_BUF for the primary plane, and BUF and
> NEXT_BUF for the overlay plane :-S). I'd thus rather keep them aligned
> with the documentation.
>
> > Would it make sense to store the above registers in mxsfb_devdata,
> > just like we do for the primary planes?
>
> The reason the register addresses are stored in mxsfb_devdata for the
> primary plane is because they differ between hardware revisions (don't
> they teach hardware engineers in school these days *not* to move
> registers around ? :-)). The overlay plane is only supported in the
> latest versions of the IP core, and are always located at the same
> address as far as I can tell. I don't think we need an extra level of
> indirection.
>
Right, makes sense. Thanks for the information.

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

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

* Re: [PATCH v2 20/22] drm: mxsfb: Merge mxsfb_set_pixel_fmt() and mxsfb_set_bus_fmt()
  2020-05-30  3:10 ` [PATCH v2 20/22] drm: mxsfb: Merge mxsfb_set_pixel_fmt() and mxsfb_set_bus_fmt() Laurent Pinchart
@ 2020-06-05 14:58   ` Emil Velikov
  2020-06-06 23:01     ` Laurent Pinchart
  0 siblings, 1 reply; 40+ messages in thread
From: Emil Velikov @ 2020-06-05 14:58 UTC (permalink / raw)
  To: Laurent Pinchart
  Cc: Marek Vasut, ML dri-devel, NXP Linux Team, Sascha Hauer,
	Robert Chiras, leonard.crestez

Hi Laurent,

With the previous disclaimer in mind, the series is:
Reviewed-by: Emil Velikov <emil.l.velikov@gmail.com>

There's a small suggestion inline, for future work.

On Sat, 30 May 2020 at 04:11, Laurent Pinchart
<laurent.pinchart@ideasonboard.com> wrote:

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

Off the top of my head, the default case should be handled in the
atomic_check() hook.
That is, unless I'm missing something and one can change the bus
format in between atomic_check() and atomic_enable(). Which would
sound like a very odd thing to do.

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

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

* Re: [PATCH v2 20/22] drm: mxsfb: Merge mxsfb_set_pixel_fmt() and mxsfb_set_bus_fmt()
  2020-06-05 14:58   ` Emil Velikov
@ 2020-06-06 23:01     ` Laurent Pinchart
  2020-06-15 19:31       ` Emil Velikov
  0 siblings, 1 reply; 40+ messages in thread
From: Laurent Pinchart @ 2020-06-06 23:01 UTC (permalink / raw)
  To: Emil Velikov
  Cc: Marek Vasut, ML dri-devel, NXP Linux Team, Sascha Hauer,
	Robert Chiras, leonard.crestez

Hi Emil,

On Fri, Jun 05, 2020 at 03:58:53PM +0100, Emil Velikov wrote:
> Hi Laurent,
> 
> With the previous disclaimer in mind, the series is:
> Reviewed-by: Emil Velikov <emil.l.velikov@gmail.com>

Sorry, which disclaimer is that ?

> There's a small suggestion inline, for future work.
> 
> On Sat, 30 May 2020 at 04:11, Laurent Pinchart wrote:
> 
> >         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;
> 
> Off the top of my head, the default case should be handled in the
> atomic_check() hook.
> That is, unless I'm missing something and one can change the bus
> format in between atomic_check() and atomic_enable(). Which would
> sound like a very odd thing to do.

I agree, this should go to the atomic check. There are still quite a few
things to improve in this driver, one step at a time :-)

-- 
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] 40+ messages in thread

* Re: [PATCH v2 14/22] drm: mxsfb: Enable vblank handling
  2020-05-30  3:10 ` [PATCH v2 14/22] drm: mxsfb: Enable vblank handling Laurent Pinchart
@ 2020-06-11 18:35   ` Stefan Agner
  0 siblings, 0 replies; 40+ messages in thread
From: Stefan Agner @ 2020-06-11 18:35 UTC (permalink / raw)
  To: Laurent Pinchart
  Cc: Marek Vasut, dri-devel, linux-imx, kernel, robert.chiras,
	leonard.crestez

On 2020-05-30 05:10, 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>

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

> ---
>  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] 40+ messages in thread

* Re: [PATCH v2 16/22] drm: mxsfb: Add i.MX7 and i.MX8M to the list of supported SoCs in Kconfig
  2020-05-30  3:10 ` [PATCH v2 16/22] drm: mxsfb: Add i.MX7 and i.MX8M to the list of supported SoCs in Kconfig Laurent Pinchart
@ 2020-06-11 18:37   ` Stefan Agner
  0 siblings, 0 replies; 40+ messages in thread
From: Stefan Agner @ 2020-06-11 18:37 UTC (permalink / raw)
  To: Laurent Pinchart
  Cc: Marek Vasut, dri-devel, linux-imx, kernel, robert.chiras,
	leonard.crestez

On 2020-05-30 05:10, Laurent Pinchart wrote:
> Extend the Kconfig option description by listing the i.MX7 and i.MX8M
> 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>

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

> ---
> Changes since v1:
> 
> - Make description more explicit by mentioning LCDIF and eLCDIF
> - Add i.MX8M
> ---
>  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 e43b326e9147..0143d539f8f8 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
> @@ -15,7 +15,8 @@ config DRM_MXSFB
>  	select DRM_PANEL
>  	select DRM_PANEL_BRIDGE
>  	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, i.MX7 and i.MX8M).
>  
>  	  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] 40+ messages in thread

* Re: [PATCH v2 21/22] drm: mxsfb: Remove unnecessary spaces after tab
  2020-05-30  3:10 ` [PATCH v2 21/22] drm: mxsfb: Remove unnecessary spaces after tab Laurent Pinchart
@ 2020-06-11 19:11   ` Stefan Agner
  0 siblings, 0 replies; 40+ messages in thread
From: Stefan Agner @ 2020-06-11 19:11 UTC (permalink / raw)
  To: Laurent Pinchart
  Cc: Marek Vasut, dri-devel, linux-imx, kernel, robert.chiras,
	leonard.crestez

On 2020-05-30 05:10, Laurent Pinchart wrote:
> This is a cosmetic change only, no code change is included.
> 
> Signed-off-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>

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

> ---
>  drivers/gpu/drm/mxsfb/mxsfb_drv.h | 10 +++++-----
>  1 file changed, 5 insertions(+), 5 deletions(-)
> 
> diff --git a/drivers/gpu/drm/mxsfb/mxsfb_drv.h
> b/drivers/gpu/drm/mxsfb/mxsfb_drv.h
> index 607a6a5e6be3..f883b56caed3 100644
> --- a/drivers/gpu/drm/mxsfb/mxsfb_drv.h
> +++ b/drivers/gpu/drm/mxsfb/mxsfb_drv.h
> @@ -16,11 +16,11 @@
>  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;
>  };
>  
>  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] 40+ messages in thread

* Re: [PATCH v2 11/22] drm: mxsfb: Stop using DRM simple display pipeline helper
  2020-05-30  3:10 ` [PATCH v2 11/22] drm: mxsfb: Stop using DRM simple display pipeline helper Laurent Pinchart
@ 2020-06-11 19:33   ` Stefan Agner
  2020-06-16  1:50     ` Laurent Pinchart
  0 siblings, 1 reply; 40+ messages in thread
From: Stefan Agner @ 2020-06-11 19:33 UTC (permalink / raw)
  To: Laurent Pinchart
  Cc: Marek Vasut, dri-devel, linux-imx, kernel, robert.chiras,
	leonard.crestez

On 2020-05-30 05:10, 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>
> ---
> Changes since v1:
> 
> - Move after mxsfb_crtc.c rename to mxsfb_kms.c
> ---
>  drivers/gpu/drm/mxsfb/mxsfb_drv.c | 108 +++---------------
>  drivers/gpu/drm/mxsfb/mxsfb_drv.h |  23 ++--
>  drivers/gpu/drm/mxsfb/mxsfb_kms.c | 184 +++++++++++++++++++++++++++---
>  3 files changed, 197 insertions(+), 118 deletions(-)
> 
> 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__ */
> diff --git a/drivers/gpu/drm/mxsfb/mxsfb_kms.c
> b/drivers/gpu/drm/mxsfb/mxsfb_kms.c
> index c4f1575b4210..8f339adb8d04 100644
> --- a/drivers/gpu/drm/mxsfb/mxsfb_kms.c
> +++ b/drivers/gpu/drm/mxsfb/mxsfb_kms.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;

This actually fails some of the igt subtests of kms_vblank.

I think it has to be:
if (state->active && !has_primary)

With that, all kms_vblank tests succeed (or are skipped).

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

--
Stefan

> +
> +	/* 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);
> +}
_______________________________________________
dri-devel mailing list
dri-devel@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/dri-devel

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

* Re: [PATCH v2 20/22] drm: mxsfb: Merge mxsfb_set_pixel_fmt() and mxsfb_set_bus_fmt()
  2020-06-06 23:01     ` Laurent Pinchart
@ 2020-06-15 19:31       ` Emil Velikov
  0 siblings, 0 replies; 40+ messages in thread
From: Emil Velikov @ 2020-06-15 19:31 UTC (permalink / raw)
  To: Laurent Pinchart
  Cc: Marek Vasut, ML dri-devel, NXP Linux Team, Sascha Hauer,
	Robert Chiras, leonard.crestez

i Laurent,

On Sun, 7 Jun 2020 at 00:02, Laurent Pinchart
<laurent.pinchart@ideasonboard.com> wrote:
>
> Hi Emil,
>
> On Fri, Jun 05, 2020 at 03:58:53PM +0100, Emil Velikov wrote:
> > Hi Laurent,
> >
> > With the previous disclaimer in mind, the series is:
> > Reviewed-by: Emil Velikov <emil.l.velikov@gmail.com>
>
> Sorry, which disclaimer is that ?
>
"I don't know much about the hardware" from earlier. Even then, the
refactor that is 1-21 is spot on.


> > There's a small suggestion inline, for future work.
> >
> > On Sat, 30 May 2020 at 04:11, Laurent Pinchart wrote:
> >
> > >         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;
> >
> > Off the top of my head, the default case should be handled in the
> > atomic_check() hook.
> > That is, unless I'm missing something and one can change the bus
> > format in between atomic_check() and atomic_enable(). Which would
> > sound like a very odd thing to do.
>
> I agree, this should go to the atomic check. There are still quite a few
> things to improve in this driver, one step at a time :-)
>
Agreed - simply mentioning for completeness-sake. Doing that at misc
later point is perfectly fine.

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

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

* Re: [PATCH v2 11/22] drm: mxsfb: Stop using DRM simple display pipeline helper
  2020-06-11 19:33   ` Stefan Agner
@ 2020-06-16  1:50     ` Laurent Pinchart
  2020-07-09 10:25       ` Stefan Agner
  0 siblings, 1 reply; 40+ messages in thread
From: Laurent Pinchart @ 2020-06-16  1:50 UTC (permalink / raw)
  To: Stefan Agner
  Cc: Marek Vasut, dri-devel, linux-imx, kernel, robert.chiras,
	leonard.crestez

Hi Stefan,

On Thu, Jun 11, 2020 at 09:33:11PM +0200, Stefan Agner wrote:
> On 2020-05-30 05:10, 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>
> > ---
> > Changes since v1:
> > 
> > - Move after mxsfb_crtc.c rename to mxsfb_kms.c
> > ---
> >  drivers/gpu/drm/mxsfb/mxsfb_drv.c | 108 +++---------------
> >  drivers/gpu/drm/mxsfb/mxsfb_drv.h |  23 ++--
> >  drivers/gpu/drm/mxsfb/mxsfb_kms.c | 184 +++++++++++++++++++++++++++---
> >  3 files changed, 197 insertions(+), 118 deletions(-)
> > 
> > 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__ */
> > diff --git a/drivers/gpu/drm/mxsfb/mxsfb_kms.c
> > b/drivers/gpu/drm/mxsfb/mxsfb_kms.c
> > index c4f1575b4210..8f339adb8d04 100644
> > --- a/drivers/gpu/drm/mxsfb/mxsfb_kms.c
> > +++ b/drivers/gpu/drm/mxsfb/mxsfb_kms.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;
> 
> This actually fails some of the igt subtests of kms_vblank.
> 
> I think it has to be:
> if (state->active && !has_primary)
> 
> With that, all kms_vblank tests succeed (or are skipped).
> 
> With that fixed:
> Reviewed-by: Stefan Agner <stefan@agner.ch>

Good catch, this will be fixed in v3. Speaking of which, I'm still
missing your review on 02/22 and 22/22. Do you plan to have a look at
them ?

> > +
> > +	/* 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);
> > +}

-- 
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] 40+ messages in thread

* Re: [PATCH v2 02/22] drm: mxsfb: Use drm_panel_bridge
  2020-05-30  3:09 ` [PATCH v2 02/22] drm: mxsfb: Use drm_panel_bridge Laurent Pinchart
@ 2020-06-17 15:25   ` Stefan Agner
  0 siblings, 0 replies; 40+ messages in thread
From: Stefan Agner @ 2020-06-17 15:25 UTC (permalink / raw)
  To: Laurent Pinchart
  Cc: Marek Vasut, dri-devel, linux-imx, kernel, robert.chiras,
	leonard.crestez

On 2020-05-30 05:09, 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.
> 
> Signed-off-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>

As discussed in the late discussion on the v1 thread, we should add a
default type to avoid warnings for some panels.

Other than that, looks good to me:

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

> ---
> Changes since v1:
> 
> - Select DRM_PANEL_BRIDGE in Kconfig
> ---
>  drivers/gpu/drm/mxsfb/Kconfig     |   1 +
>  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 ----------------------------
>  5 files changed, 54 insertions(+), 158 deletions(-)
>  delete mode 100644 drivers/gpu/drm/mxsfb/mxsfb_out.c
> 
> diff --git a/drivers/gpu/drm/mxsfb/Kconfig b/drivers/gpu/drm/mxsfb/Kconfig
> index 0dca8f27169e..e43b326e9147 100644
> --- a/drivers/gpu/drm/mxsfb/Kconfig
> +++ b/drivers/gpu/drm/mxsfb/Kconfig
> @@ -13,6 +13,7 @@ config DRM_MXSFB
>  	select DRM_KMS_FB_HELPER
>  	select DRM_KMS_CMA_HELPER
>  	select DRM_PANEL
> +	select DRM_PANEL_BRIDGE
>  	help
>  	  Choose this option if you have an i.MX23/i.MX28/i.MX6SX MXSFB
>  	  LCD controller.
> 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;
> -}
_______________________________________________
dri-devel mailing list
dri-devel@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/dri-devel

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

* Re: [PATCH v2 22/22] drm: mxsfb: Support the alpha plane
  2020-05-30  3:10 ` [PATCH v2 22/22] drm: mxsfb: Support the alpha plane Laurent Pinchart
  2020-05-31 16:54   ` Emil Velikov
@ 2020-06-17 16:08   ` Stefan Agner
  1 sibling, 0 replies; 40+ messages in thread
From: Stefan Agner @ 2020-06-17 16:08 UTC (permalink / raw)
  To: Laurent Pinchart
  Cc: Marek Vasut, dri-devel, linux-imx, kernel, robert.chiras,
	leonard.crestez

On 2020-05-30 05:10, 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>

Looks good to me.

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

--
Stefan

> ---
> Changes since v1:
> 
> - Split whitespace cleanup to a separate patch
> ---
>  drivers/gpu/drm/mxsfb/mxsfb_drv.c  |   3 +
>  drivers/gpu/drm/mxsfb/mxsfb_drv.h  |   6 +-
>  drivers/gpu/drm/mxsfb/mxsfb_kms.c  | 129 +++++++++++++++++++++++++----
>  drivers/gpu/drm/mxsfb/mxsfb_regs.h |  22 +++++
>  4 files changed, 144 insertions(+), 16 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 f883b56caed3..399d23e91ed1 100644
> --- a/drivers/gpu/drm/mxsfb/mxsfb_drv.h
> +++ b/drivers/gpu/drm/mxsfb/mxsfb_drv.h
> @@ -21,6 +21,7 @@ struct mxsfb_devdata {
>  	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_atomic_update,
> +	.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_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,
> -	DRM_FORMAT_RGB565
>  };
>  
> +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_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] 40+ messages in thread

* Re: [PATCH v2 11/22] drm: mxsfb: Stop using DRM simple display pipeline helper
  2020-06-16  1:50     ` Laurent Pinchart
@ 2020-07-09 10:25       ` Stefan Agner
  2020-07-17  2:06         ` Laurent Pinchart
  0 siblings, 1 reply; 40+ messages in thread
From: Stefan Agner @ 2020-07-09 10:25 UTC (permalink / raw)
  To: Laurent Pinchart
  Cc: Marek Vasut, dri-devel, linux-imx, kernel, robert.chiras,
	leonard.crestez

Hi Laurent,

On 2020-06-16 03:50, Laurent Pinchart wrote:
> Hi Stefan,
> 
> On Thu, Jun 11, 2020 at 09:33:11PM +0200, Stefan Agner wrote:
>> On 2020-05-30 05:10, 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>
>> > ---
>> > Changes since v1:
>> >
>> > - Move after mxsfb_crtc.c rename to mxsfb_kms.c
>> > ---
>> >  drivers/gpu/drm/mxsfb/mxsfb_drv.c | 108 +++---------------
>> >  drivers/gpu/drm/mxsfb/mxsfb_drv.h |  23 ++--
>> >  drivers/gpu/drm/mxsfb/mxsfb_kms.c | 184 +++++++++++++++++++++++++++---
>> >  3 files changed, 197 insertions(+), 118 deletions(-)
>> >
>> > 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__ */
>> > diff --git a/drivers/gpu/drm/mxsfb/mxsfb_kms.c
>> > b/drivers/gpu/drm/mxsfb/mxsfb_kms.c
>> > index c4f1575b4210..8f339adb8d04 100644
>> > --- a/drivers/gpu/drm/mxsfb/mxsfb_kms.c
>> > +++ b/drivers/gpu/drm/mxsfb/mxsfb_kms.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;
>>
>> This actually fails some of the igt subtests of kms_vblank.
>>
>> I think it has to be:
>> if (state->active && !has_primary)
>>
>> With that, all kms_vblank tests succeed (or are skipped).
>>
>> With that fixed:
>> Reviewed-by: Stefan Agner <stefan@agner.ch>
> 
> Good catch, this will be fixed in v3. Speaking of which, I'm still
> missing your review on 02/22 and 22/22. Do you plan to have a look at
> them ?

Yeah sorry, I did initially miss them and sent a review a couple of
weeks ago.

Would be good if you can send a v3 soon, I think it should still be
early enough to make it into the next merge window.

--
Stefan

> 
>> > +
>> > +	/* 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);
>> > +}
_______________________________________________
dri-devel mailing list
dri-devel@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/dri-devel

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

* Re: [PATCH v2 11/22] drm: mxsfb: Stop using DRM simple display pipeline helper
  2020-07-09 10:25       ` Stefan Agner
@ 2020-07-17  2:06         ` Laurent Pinchart
  2020-07-26 18:28           ` Laurent Pinchart
  0 siblings, 1 reply; 40+ messages in thread
From: Laurent Pinchart @ 2020-07-17  2:06 UTC (permalink / raw)
  To: Stefan Agner
  Cc: Marek Vasut, dri-devel, linux-imx, kernel, robert.chiras,
	leonard.crestez

Hi Stefan,

On Thu, Jul 09, 2020 at 12:25:42PM +0200, Stefan Agner wrote:
> On 2020-06-16 03:50, Laurent Pinchart wrote:
> > On Thu, Jun 11, 2020 at 09:33:11PM +0200, Stefan Agner wrote:
> >> On 2020-05-30 05:10, 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>
> >> > ---
> >> > Changes since v1:
> >> >
> >> > - Move after mxsfb_crtc.c rename to mxsfb_kms.c
> >> > ---
> >> >  drivers/gpu/drm/mxsfb/mxsfb_drv.c | 108 +++---------------
> >> >  drivers/gpu/drm/mxsfb/mxsfb_drv.h |  23 ++--
> >> >  drivers/gpu/drm/mxsfb/mxsfb_kms.c | 184 +++++++++++++++++++++++++++---
> >> >  3 files changed, 197 insertions(+), 118 deletions(-)
> >> >
> >> > 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__ */
> >> > diff --git a/drivers/gpu/drm/mxsfb/mxsfb_kms.c
> >> > b/drivers/gpu/drm/mxsfb/mxsfb_kms.c
> >> > index c4f1575b4210..8f339adb8d04 100644
> >> > --- a/drivers/gpu/drm/mxsfb/mxsfb_kms.c
> >> > +++ b/drivers/gpu/drm/mxsfb/mxsfb_kms.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;
> >>
> >> This actually fails some of the igt subtests of kms_vblank.
> >>
> >> I think it has to be:
> >> if (state->active && !has_primary)
> >>
> >> With that, all kms_vblank tests succeed (or are skipped).
> >>
> >> With that fixed:
> >> Reviewed-by: Stefan Agner <stefan@agner.ch>
> > 
> > Good catch, this will be fixed in v3. Speaking of which, I'm still
> > missing your review on 02/22 and 22/22. Do you plan to have a look at
> > them ?
> 
> Yeah sorry, I did initially miss them and sent a review a couple of
> weeks ago.
> 
> Would be good if you can send a v3 soon, I think it should still be
> early enough to make it into the next merge window.

I'm afraid I'm fairly busy at the moment :-( I'll try to give it a go
next week, but it will be too late for v5.9.

> >> > +
> >> > +	/* 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);
> >> > +}

-- 
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] 40+ messages in thread

* Re: [PATCH v2 11/22] drm: mxsfb: Stop using DRM simple display pipeline helper
  2020-07-17  2:06         ` Laurent Pinchart
@ 2020-07-26 18:28           ` Laurent Pinchart
  2020-07-27  7:57             ` Stefan Agner
  0 siblings, 1 reply; 40+ messages in thread
From: Laurent Pinchart @ 2020-07-26 18:28 UTC (permalink / raw)
  To: Stefan Agner
  Cc: Marek Vasut, dri-devel, linux-imx, kernel, robert.chiras,
	leonard.crestez

Hi Stefan,

On Fri, Jul 17, 2020 at 05:06:55AM +0300, Laurent Pinchart wrote:
> On Thu, Jul 09, 2020 at 12:25:42PM +0200, Stefan Agner wrote:
> > On 2020-06-16 03:50, Laurent Pinchart wrote:
> >> On Thu, Jun 11, 2020 at 09:33:11PM +0200, Stefan Agner wrote:
> >>> On 2020-05-30 05:10, 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>
> >>>> ---
> >>>> Changes since v1:
> >>>>
> >>>> - Move after mxsfb_crtc.c rename to mxsfb_kms.c
> >>>> ---
> >>>>  drivers/gpu/drm/mxsfb/mxsfb_drv.c | 108 +++---------------
> >>>>  drivers/gpu/drm/mxsfb/mxsfb_drv.h |  23 ++--
> >>>>  drivers/gpu/drm/mxsfb/mxsfb_kms.c | 184 +++++++++++++++++++++++++++---
> >>>>  3 files changed, 197 insertions(+), 118 deletions(-)
> >>>>
> >>>> 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__ */
> >>>> diff --git a/drivers/gpu/drm/mxsfb/mxsfb_kms.c
> >>>> b/drivers/gpu/drm/mxsfb/mxsfb_kms.c
> >>>> index c4f1575b4210..8f339adb8d04 100644
> >>>> --- a/drivers/gpu/drm/mxsfb/mxsfb_kms.c
> >>>> +++ b/drivers/gpu/drm/mxsfb/mxsfb_kms.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;
> >>>
> >>> This actually fails some of the igt subtests of kms_vblank.
> >>>
> >>> I think it has to be:
> >>> if (state->active && !has_primary)
> >>>
> >>> With that, all kms_vblank tests succeed (or are skipped).
> >>>
> >>> With that fixed:
> >>> Reviewed-by: Stefan Agner <stefan@agner.ch>
> >> 
> >> Good catch, this will be fixed in v3. Speaking of which, I'm still
> >> missing your review on 02/22 and 22/22. Do you plan to have a look at
> >> them ?
> > 
> > Yeah sorry, I did initially miss them and sent a review a couple of
> > weeks ago.
> > 
> > Would be good if you can send a v3 soon, I think it should still be
> > early enough to make it into the next merge window.
> 
> I'm afraid I'm fairly busy at the moment :-( I'll try to give it a go
> next week, but it will be too late for v5.9.

Turns out I had already sent a v3 a month ago :-) I'll send a rebased v4
shortly.

> >>>> +
> >>>> +	/* 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);
> >>>> +}

-- 
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] 40+ messages in thread

* Re: [PATCH v2 11/22] drm: mxsfb: Stop using DRM simple display pipeline helper
  2020-07-26 18:28           ` Laurent Pinchart
@ 2020-07-27  7:57             ` Stefan Agner
  0 siblings, 0 replies; 40+ messages in thread
From: Stefan Agner @ 2020-07-27  7:57 UTC (permalink / raw)
  To: Laurent Pinchart
  Cc: Marek Vasut, dri-devel, linux-imx, kernel, robert.chiras,
	leonard.crestez

On 2020-07-26 20:28, Laurent Pinchart wrote:
> Hi Stefan,
> 
> On Fri, Jul 17, 2020 at 05:06:55AM +0300, Laurent Pinchart wrote:
>> On Thu, Jul 09, 2020 at 12:25:42PM +0200, Stefan Agner wrote:
>> > On 2020-06-16 03:50, Laurent Pinchart wrote:
>> >> On Thu, Jun 11, 2020 at 09:33:11PM +0200, Stefan Agner wrote:
>> >>> On 2020-05-30 05:10, 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>
>> >>>> ---
>> >>>> Changes since v1:
>> >>>>
>> >>>> - Move after mxsfb_crtc.c rename to mxsfb_kms.c
>> >>>> ---
>> >>>>  drivers/gpu/drm/mxsfb/mxsfb_drv.c | 108 +++---------------
>> >>>>  drivers/gpu/drm/mxsfb/mxsfb_drv.h |  23 ++--
>> >>>>  drivers/gpu/drm/mxsfb/mxsfb_kms.c | 184 +++++++++++++++++++++++++++---
>> >>>>  3 files changed, 197 insertions(+), 118 deletions(-)
>> >>>>
>> >>>> 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__ */
>> >>>> diff --git a/drivers/gpu/drm/mxsfb/mxsfb_kms.c
>> >>>> b/drivers/gpu/drm/mxsfb/mxsfb_kms.c
>> >>>> index c4f1575b4210..8f339adb8d04 100644
>> >>>> --- a/drivers/gpu/drm/mxsfb/mxsfb_kms.c
>> >>>> +++ b/drivers/gpu/drm/mxsfb/mxsfb_kms.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;
>> >>>
>> >>> This actually fails some of the igt subtests of kms_vblank.
>> >>>
>> >>> I think it has to be:
>> >>> if (state->active && !has_primary)
>> >>>
>> >>> With that, all kms_vblank tests succeed (or are skipped).
>> >>>
>> >>> With that fixed:
>> >>> Reviewed-by: Stefan Agner <stefan@agner.ch>
>> >>
>> >> Good catch, this will be fixed in v3. Speaking of which, I'm still
>> >> missing your review on 02/22 and 22/22. Do you plan to have a look at
>> >> them ?
>> >
>> > Yeah sorry, I did initially miss them and sent a review a couple of
>> > weeks ago.
>> >
>> > Would be good if you can send a v3 soon, I think it should still be
>> > early enough to make it into the next merge window.
>>
>> I'm afraid I'm fairly busy at the moment :-( I'll try to give it a go
>> next week, but it will be too late for v5.9.
> 
> Turns out I had already sent a v3 a month ago :-) I'll send a rebased v4
> shortly.
> 

Oh sorry, missed that one. I just checked my inbox and spam folder, but
wasn't able to find it. I think you missed my email?
https://lwn.net/Articles/823498/

Thanks for v4! Will take care of it today or tomorrow.

--
Stefan

>> >>>> +
>> >>>> +	/* 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);
>> >>>> +}
_______________________________________________
dri-devel mailing list
dri-devel@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/dri-devel

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

end of thread, other threads:[~2020-07-27  7:57 UTC | newest]

Thread overview: 40+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2020-05-30  3:09 [PATCH v2 00/22] drm: mxsfb: Add i.MX7 support Laurent Pinchart
2020-05-30  3:09 ` [PATCH v2 01/22] drm: mxsfb: Remove fbdev leftovers Laurent Pinchart
2020-05-30  3:09 ` [PATCH v2 02/22] drm: mxsfb: Use drm_panel_bridge Laurent Pinchart
2020-06-17 15:25   ` Stefan Agner
2020-05-30  3:09 ` [PATCH v2 03/22] drm: mxsfb: Use BIT() macro to define register bitfields Laurent Pinchart
2020-05-30  3:09 ` [PATCH v2 04/22] drm: mxsfb: Remove unused macros from mxsfb_regs.h Laurent Pinchart
2020-05-30  3:09 ` [PATCH v2 05/22] drm: mxsfb: Clarify format and bus width configuration Laurent Pinchart
2020-05-30  3:09 ` [PATCH v2 06/22] drm: mxsfb: Pass mxsfb_drm_private pointer to mxsfb_reset_block() Laurent Pinchart
2020-05-30  3:10 ` [PATCH v2 07/22] drm: mxsfb: Use LCDC_CTRL register name explicitly Laurent Pinchart
2020-05-30  3:10 ` [PATCH v2 08/22] drm: mxsfb: Remove register definitions from mxsfb_crtc.c Laurent Pinchart
2020-05-30  3:10 ` [PATCH v2 09/22] drm: mxsfb: Remove unneeded includes Laurent Pinchart
2020-05-30  3:10 ` [PATCH v2 10/22] drm: mxsfb: Rename mxsfb_crtc.c to mxsfb_kms.c Laurent Pinchart
2020-05-30  3:10 ` [PATCH v2 11/22] drm: mxsfb: Stop using DRM simple display pipeline helper Laurent Pinchart
2020-06-11 19:33   ` Stefan Agner
2020-06-16  1:50     ` Laurent Pinchart
2020-07-09 10:25       ` Stefan Agner
2020-07-17  2:06         ` Laurent Pinchart
2020-07-26 18:28           ` Laurent Pinchart
2020-07-27  7:57             ` Stefan Agner
2020-05-30  3:10 ` [PATCH v2 12/22] drm: mxsfb: Move vblank event arm to CRTC .atomic_flush() Laurent Pinchart
2020-05-30  3:10 ` [PATCH v2 13/22] drm: mxsfb: Don't touch AXI clock in IRQ context Laurent Pinchart
2020-05-30  3:10 ` [PATCH v2 14/22] drm: mxsfb: Enable vblank handling Laurent Pinchart
2020-06-11 18:35   ` Stefan Agner
2020-05-30  3:10 ` [PATCH v2 15/22] drm: mxsfb: Remove mxsfb_devdata unused fields Laurent Pinchart
2020-05-30  3:10 ` [PATCH v2 16/22] drm: mxsfb: Add i.MX7 and i.MX8M to the list of supported SoCs in Kconfig Laurent Pinchart
2020-06-11 18:37   ` Stefan Agner
2020-05-30  3:10 ` [PATCH v2 17/22] drm: mxsfb: Update internal IP version number for i.MX6SX Laurent Pinchart
2020-05-30  3:10 ` [PATCH v2 18/22] drm: mxsfb: Drop non-OF support Laurent Pinchart
2020-05-30  3:10 ` [PATCH v2 19/22] drm: mxsfb: Turn mxsfb_set_pixel_fmt() into a void function Laurent Pinchart
2020-05-30  3:10 ` [PATCH v2 20/22] drm: mxsfb: Merge mxsfb_set_pixel_fmt() and mxsfb_set_bus_fmt() Laurent Pinchart
2020-06-05 14:58   ` Emil Velikov
2020-06-06 23:01     ` Laurent Pinchart
2020-06-15 19:31       ` Emil Velikov
2020-05-30  3:10 ` [PATCH v2 21/22] drm: mxsfb: Remove unnecessary spaces after tab Laurent Pinchart
2020-06-11 19:11   ` Stefan Agner
2020-05-30  3:10 ` [PATCH v2 22/22] drm: mxsfb: Support the alpha plane Laurent Pinchart
2020-05-31 16:54   ` Emil Velikov
2020-06-02 22:42     ` Laurent Pinchart
2020-06-05 14:07       ` Emil Velikov
2020-06-17 16:08   ` Stefan Agner

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