All of lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH 00/14] drm/mgag200: Move model-specific code into separate functions
@ 2022-07-08  9:39 Thomas Zimmermann
  2022-07-08  9:39 ` [PATCH 01/14] drm/mgag200: Split mgag200_modeset_init() Thomas Zimmermann
                   ` (14 more replies)
  0 siblings, 15 replies; 28+ messages in thread
From: Thomas Zimmermann @ 2022-07-08  9:39 UTC (permalink / raw)
  To: airlied, airlied, jfalempe, daniel; +Cc: Thomas Zimmermann, dri-devel

Mgag200 still mixes model-specific code and generic code in the same
functions. Separate it into distinct helpers.

As part of this effort, convert the driver from simple-KMS helpers
to regular atomic helpers. The latter are way more flexible and can
be adapted easily for each hardware model.

Tested on Matrox G200 and G200EH hardware.

Thomas Zimmermann (14):
  drm/mgag200: Split mgag200_modeset_init()
  drm/mgag200: Move DAC-register setup into model-specific code
  dmr/mgag200: Move ER/EW3 register initializatino to per-model code
  drm/mgag200: Acquire I/O-register lock in atomic_commit_tail function
  drm/mgag200: Store primary plane's color format in CRTC state
  drm/mgag200: Reorganize before dropping simple-KMS helpers
  drm/mgag200: Replace simple-KMS with regular atomic helpers
  drm/mgag200: Set SCROFF in primary-plane code
  drm/mgag200: Add per-device callbacks
  drm/mgag200: Provide per-device callbacks for BMC synchronization
  drm/mgag200: Provide per-device callbacks for PIXPLLC
  drm/mgag200: Move mode-config to model-specific code
  drm/mgag200: Move CRTC atomic_enable to model-specfic code
  drm/mgag200: Remove type field from struct mga_device

 drivers/gpu/drm/mgag200/Makefile          |   4 +-
 drivers/gpu/drm/mgag200/mgag200_bmc.c     |  99 +++
 drivers/gpu/drm/mgag200/mgag200_drv.c     |  21 +-
 drivers/gpu/drm/mgag200/mgag200_drv.h     | 181 +++-
 drivers/gpu/drm/mgag200/mgag200_g200.c    | 266 +++++-
 drivers/gpu/drm/mgag200/mgag200_g200eh.c  | 287 ++++++-
 drivers/gpu/drm/mgag200/mgag200_g200eh3.c | 181 +++-
 drivers/gpu/drm/mgag200/mgag200_g200er.c  | 324 ++++++-
 drivers/gpu/drm/mgag200/mgag200_g200ev.c  | 329 ++++++-
 drivers/gpu/drm/mgag200/mgag200_g200ew3.c | 192 ++++-
 drivers/gpu/drm/mgag200/mgag200_g200se.c  | 446 +++++++++-
 drivers/gpu/drm/mgag200/mgag200_g200wb.c  | 336 +++++++-
 drivers/gpu/drm/mgag200/mgag200_mode.c    | 727 +++++-----------
 drivers/gpu/drm/mgag200/mgag200_pll.c     | 997 ----------------------
 14 files changed, 2804 insertions(+), 1586 deletions(-)
 create mode 100644 drivers/gpu/drm/mgag200/mgag200_bmc.c
 delete mode 100644 drivers/gpu/drm/mgag200/mgag200_pll.c


base-commit: 11d480026e922adacd274306728adb6df6dd262a
-- 
2.36.1


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

* [PATCH 01/14] drm/mgag200: Split mgag200_modeset_init()
  2022-07-08  9:39 [PATCH 00/14] drm/mgag200: Move model-specific code into separate functions Thomas Zimmermann
@ 2022-07-08  9:39 ` Thomas Zimmermann
  2022-07-08  9:39 ` [PATCH 02/14] drm/mgag200: Move DAC-register setup into model-specific code Thomas Zimmermann
                   ` (13 subsequent siblings)
  14 siblings, 0 replies; 28+ messages in thread
From: Thomas Zimmermann @ 2022-07-08  9:39 UTC (permalink / raw)
  To: airlied, airlied, jfalempe, daniel; +Cc: Thomas Zimmermann, dri-devel

Split mgag200_modeset_init() into smaller helpers to initialize
the mode_config structure and the pipeline. This will be helpful
for transforming this code into per-model functions. No functional
changes.

Signed-off-by: Thomas Zimmermann <tzimmermann@suse.de>
---
 drivers/gpu/drm/mgag200/mgag200_mode.c | 41 ++++++++++++++++++++------
 1 file changed, 32 insertions(+), 9 deletions(-)

diff --git a/drivers/gpu/drm/mgag200/mgag200_mode.c b/drivers/gpu/drm/mgag200/mgag200_mode.c
index 225cca2ed60e..e08852482fe2 100644
--- a/drivers/gpu/drm/mgag200/mgag200_mode.c
+++ b/drivers/gpu/drm/mgag200/mgag200_mode.c
@@ -1048,23 +1048,16 @@ static const struct drm_mode_config_funcs mgag200_mode_config_funcs = {
 	.atomic_commit = drm_atomic_helper_commit,
 };
 
-int mgag200_modeset_init(struct mga_device *mdev, resource_size_t vram_available)
+static int mgag200_mode_config_init(struct mga_device *mdev, resource_size_t vram_available)
 {
 	struct drm_device *dev = &mdev->base;
-	struct mga_i2c_chan *i2c = &mdev->i2c;
-	struct drm_connector *connector = &mdev->connector;
-	struct drm_simple_display_pipe *pipe = &mdev->display_pipe;
-	size_t format_count = ARRAY_SIZE(mgag200_simple_display_pipe_formats);
 	int ret;
 
-	mgag200_init_regs(mdev);
-
 	mdev->vram_available = vram_available;
 
 	ret = drmm_mode_config_init(dev);
 	if (ret) {
-		drm_err(dev, "drmm_mode_config_init() failed, error %d\n",
-			ret);
+		drm_err(dev, "drmm_mode_config_init() failed: %d\n", ret);
 		return ret;
 	}
 
@@ -1074,6 +1067,18 @@ int mgag200_modeset_init(struct mga_device *mdev, resource_size_t vram_available
 	dev->mode_config.fb_base = mdev->vram_res->start;
 	dev->mode_config.funcs = &mgag200_mode_config_funcs;
 
+	return 0;
+}
+
+static int mgag200_pipeline_init(struct mga_device *mdev)
+{
+	struct drm_device *dev = &mdev->base;
+	struct mga_i2c_chan *i2c = &mdev->i2c;
+	struct drm_connector *connector = &mdev->connector;
+	struct drm_simple_display_pipe *pipe = &mdev->display_pipe;
+	size_t format_count = ARRAY_SIZE(mgag200_simple_display_pipe_formats);
+	int ret;
+
 	ret = mgag200_i2c_init(mdev, i2c);
 	if (ret) {
 		drm_err(dev, "failed to add DDC bus: %d\n", ret);
@@ -1114,6 +1119,24 @@ int mgag200_modeset_init(struct mga_device *mdev, resource_size_t vram_available
 
 	drm_crtc_enable_color_mgmt(&pipe->crtc, 0, false, MGAG200_LUT_SIZE);
 
+	return 0;
+}
+
+int mgag200_modeset_init(struct mga_device *mdev, resource_size_t vram_available)
+{
+	struct drm_device *dev = &mdev->base;
+	int ret;
+
+	mgag200_init_regs(mdev);
+
+	ret = mgag200_mode_config_init(mdev, vram_available);
+	if (ret)
+		return ret;
+
+	ret = mgag200_pipeline_init(mdev);
+	if (ret)
+		return ret;
+
 	drm_mode_config_reset(dev);
 
 	return 0;
-- 
2.36.1


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

* [PATCH 02/14] drm/mgag200: Move DAC-register setup into model-specific code
  2022-07-08  9:39 [PATCH 00/14] drm/mgag200: Move model-specific code into separate functions Thomas Zimmermann
  2022-07-08  9:39 ` [PATCH 01/14] drm/mgag200: Split mgag200_modeset_init() Thomas Zimmermann
@ 2022-07-08  9:39 ` Thomas Zimmermann
  2022-07-08 15:54   ` Sam Ravnborg
  2022-07-08  9:39 ` [PATCH 03/14] dmr/mgag200: Move ER/EW3 register initializatino to per-model code Thomas Zimmermann
                   ` (12 subsequent siblings)
  14 siblings, 1 reply; 28+ messages in thread
From: Thomas Zimmermann @ 2022-07-08  9:39 UTC (permalink / raw)
  To: airlied, airlied, jfalempe, daniel; +Cc: Thomas Zimmermann, dri-devel

Provide an init function for each model's DAC registers. Remove
the shared helper.

The code for initializing the DAC registers consisted of a large
table of default value, plus many exceptions for the various G200
models. Providing a per-model implementation makes if more readable.
At some point, some of the initialization should probably move into
the modesetting code.

Signed-off-by: Thomas Zimmermann <tzimmermann@suse.de>
---
 drivers/gpu/drm/mgag200/mgag200_drv.h     |  3 +
 drivers/gpu/drm/mgag200/mgag200_g200.c    | 37 +++++++++++
 drivers/gpu/drm/mgag200/mgag200_g200eh.c  | 36 ++++++++++
 drivers/gpu/drm/mgag200/mgag200_g200eh3.c |  2 +
 drivers/gpu/drm/mgag200/mgag200_g200er.c  | 34 ++++++++++
 drivers/gpu/drm/mgag200/mgag200_g200ev.c  | 40 ++++++++++++
 drivers/gpu/drm/mgag200/mgag200_g200ew3.c |  2 +
 drivers/gpu/drm/mgag200/mgag200_g200se.c  | 45 +++++++++++++
 drivers/gpu/drm/mgag200/mgag200_g200wb.c  | 34 ++++++++++
 drivers/gpu/drm/mgag200/mgag200_mode.c    | 80 +----------------------
 10 files changed, 234 insertions(+), 79 deletions(-)

diff --git a/drivers/gpu/drm/mgag200/mgag200_drv.h b/drivers/gpu/drm/mgag200/mgag200_drv.h
index 301c4ab46539..6a2a1ad914c1 100644
--- a/drivers/gpu/drm/mgag200/mgag200_drv.h
+++ b/drivers/gpu/drm/mgag200/mgag200_drv.h
@@ -295,10 +295,12 @@ struct mga_device *mgag200_g200_device_create(struct pci_dev *pdev, const struct
 					      enum mga_type type);
 struct mga_device *mgag200_g200se_device_create(struct pci_dev *pdev, const struct drm_driver *drv,
 						enum mga_type type);
+void mgag200_g200wb_init_registers(struct mga_device *mdev);
 struct mga_device *mgag200_g200wb_device_create(struct pci_dev *pdev, const struct drm_driver *drv,
 						enum mga_type type);
 struct mga_device *mgag200_g200ev_device_create(struct pci_dev *pdev, const struct drm_driver *drv,
 						enum mga_type type);
+void mgag200_g200eh_init_registers(struct mga_device *mdev);
 struct mga_device *mgag200_g200eh_device_create(struct pci_dev *pdev, const struct drm_driver *drv,
 						enum mga_type type);
 struct mga_device *mgag200_g200eh3_device_create(struct pci_dev *pdev, const struct drm_driver *drv,
@@ -310,6 +312,7 @@ struct mga_device *mgag200_g200ew3_device_create(struct pci_dev *pdev, const str
 
 				/* mgag200_mode.c */
 resource_size_t mgag200_device_probe_vram(struct mga_device *mdev);
+void mgag200_init_registers(struct mga_device *mdev);
 int mgag200_modeset_init(struct mga_device *mdev, resource_size_t vram_fb_available);
 
 				/* mgag200_i2c.c */
diff --git a/drivers/gpu/drm/mgag200/mgag200_g200.c b/drivers/gpu/drm/mgag200/mgag200_g200.c
index 674385921b7f..c6303fcb8fe7 100644
--- a/drivers/gpu/drm/mgag200/mgag200_g200.c
+++ b/drivers/gpu/drm/mgag200/mgag200_g200.c
@@ -30,6 +30,41 @@ static int mgag200_g200_init_pci_options(struct pci_dev *pdev)
 	return mgag200_init_pci_options(pdev, option, 0x00008000);
 }
 
+static void mgag200_g200_init_registers(struct mgag200_g200_device *g200)
+{
+	static const u8 dacvalue[] = {
+		/* 0x00: */        0,    0,    0,    0,    0,    0,    0,    0,
+		/* 0x08: */        0,    0,    0,    0,    0,    0,    0,    0,
+		/* 0x10: */        0,    0,    0,    0,    0,    0,    0,    0,
+		/* 0x18: */     0x00,    0, 0xC9, 0xFF, 0xBF, 0x20, 0x1F, 0x20,
+		/* 0x20: */     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+		/* 0x28: */     0x00, 0x00, 0x00, 0x00,
+		/* 0x2c: */	0x04, /* G200 specific: MGA1064_SYS_PLL_M */
+		/* 0x2d: */     0x2d, /* G200 specific: MGA1064_SYS_PLL_N */
+		/* 0x2e: */     0x19, /* G200 specific: MGA1064_SYS_PLL_P */
+		/* 0x2f: */     0x40,
+		/* 0x30: */     0x00, 0xB0, 0x00, 0xC2, 0x34, 0x14, 0x02, 0x83,
+		/* 0x38: */     0x00, 0x93, 0x00, 0x77, 0x00, 0x00, 0x00, 0x3A,
+		/* 0x40: */        0,    0,    0,    0,    0,    0,    0,    0,
+		/* 0x48: */        0,    0,    0,    0,    0,    0,    0,    0
+	};
+
+	struct mga_device *mdev = &g200->base;
+	size_t i;
+
+	for (i = 0; i < ARRAY_SIZE(dacvalue); ++i) {
+		if ((i <= 0x17) ||
+		    (i == 0x1b) ||
+		    (i == 0x1c) ||
+		    ((i >= 0x1f) && (i <= 0x29)) ||
+		    ((i >= 0x30) && (i <= 0x37)))
+			continue;
+		WREG_DAC(i, dacvalue[i]);
+	}
+
+	mgag200_init_registers(mdev);
+}
+
 /*
  * DRM Device
  */
@@ -191,6 +226,8 @@ struct mga_device *mgag200_g200_device_create(struct pci_dev *pdev, const struct
 	if (ret)
 		return ERR_PTR(ret);
 
+	mgag200_g200_init_registers(g200);
+
 	vram_available = mgag200_device_probe_vram(mdev);
 
 	ret = mgag200_modeset_init(mdev, vram_available);
diff --git a/drivers/gpu/drm/mgag200/mgag200_g200eh.c b/drivers/gpu/drm/mgag200/mgag200_g200eh.c
index 1b9a22728744..365f486d3ce7 100644
--- a/drivers/gpu/drm/mgag200/mgag200_g200eh.c
+++ b/drivers/gpu/drm/mgag200/mgag200_g200eh.c
@@ -6,6 +6,40 @@
 
 #include "mgag200_drv.h"
 
+void mgag200_g200eh_init_registers(struct mga_device *mdev)
+{
+	static const u8 dacvalue[] = {
+		/* 0x00: */        0,    0,    0,    0,    0,    0,    0,    0,
+		/* 0x08: */        0,    0,    0,    0,    0,    0,    0,    0,
+		/* 0x10: */        0,    0,    0,    0,    0,    0,    0,    0,
+		/* 0x18: */     0x00,    0, 0xC9, 0xFF, 0xBF, 0x20,
+		/* 0x1e: */     MGA1064_MISC_CTL_VGA8 | /* G200EH specific: MGA1064_MISC_CTL */
+				MGA1064_MISC_CTL_DAC_RAM_CS,
+		/* 0x1f: */     0x20,
+		/* 0x20: */     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+		/* 0x28: */     0x00, 0x00, 0x00, 0x00,    0,    0,    0, 0x40,
+		/* 0x30: */     0x00, 0xB0, 0x00, 0xC2, 0x34, 0x14, 0x02, 0x83,
+		/* 0x38: */     0x00, 0x93, 0x00, 0x77, 0x00, 0x00, 0x00, 0x3A,
+		/* 0x40: */        0,    0,    0,    0,    0,    0,    0,    0,
+		/* 0x48: */        0,    0,    0,    0,    0,    0,    0,    0
+	};
+
+	size_t i;
+
+	for (i = 0; i < ARRAY_SIZE(dacvalue); i++) {
+		if ((i <= 0x17) ||
+		    (i == 0x1b) ||
+		    (i == 0x1c) ||
+		    ((i >= 0x1f) && (i <= 0x29)) ||
+		    ((i >= 0x30) && (i <= 0x37)) ||
+		    ((i >= 0x44) && (i <= 0x4e)))
+			continue;
+		WREG_DAC(i, dacvalue[i]);
+	}
+
+	mgag200_init_registers(mdev);
+}
+
 /*
  * DRM device
  */
@@ -40,6 +74,8 @@ struct mga_device *mgag200_g200eh_device_create(struct pci_dev *pdev, const stru
 	if (ret)
 		return ERR_PTR(ret);
 
+	mgag200_g200eh_init_registers(mdev);
+
 	vram_available = mgag200_device_probe_vram(mdev);
 
 	ret = mgag200_modeset_init(mdev, vram_available);
diff --git a/drivers/gpu/drm/mgag200/mgag200_g200eh3.c b/drivers/gpu/drm/mgag200/mgag200_g200eh3.c
index 438cda1b14c9..adb9190b62af 100644
--- a/drivers/gpu/drm/mgag200/mgag200_g200eh3.c
+++ b/drivers/gpu/drm/mgag200/mgag200_g200eh3.c
@@ -41,6 +41,8 @@ struct mga_device *mgag200_g200eh3_device_create(struct pci_dev *pdev,
 	if (ret)
 		return ERR_PTR(ret);
 
+	mgag200_g200eh_init_registers(mdev); // same as G200EH
+
 	vram_available = mgag200_device_probe_vram(mdev);
 
 	ret = mgag200_modeset_init(mdev, vram_available);
diff --git a/drivers/gpu/drm/mgag200/mgag200_g200er.c b/drivers/gpu/drm/mgag200/mgag200_g200er.c
index 0790d4e6463d..acdccc419944 100644
--- a/drivers/gpu/drm/mgag200/mgag200_g200er.c
+++ b/drivers/gpu/drm/mgag200/mgag200_g200er.c
@@ -6,6 +6,38 @@
 
 #include "mgag200_drv.h"
 
+static void mgag200_g200er_init_registers(struct mga_device *mdev)
+{
+	static const u8 dacvalue[] = {
+		/* 0x00: */        0,    0,    0,    0,    0,    0,    0,    0,
+		/* 0x08: */        0,    0,    0,    0,    0,    0,    0,    0,
+		/* 0x10: */        0,    0,    0,    0,    0,    0,    0,    0,
+		/* 0x18: */     0x00,    0, 0xC9, 0xFF, 0xBF, 0x20, 0x1F, 0x20,
+		/* 0x20: */     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+		/* 0x28: */     0x00, 0x00, 0x00, 0x00,    0,    0,    0, 0x40,
+		/* 0x30: */     0x00, 0xB0, 0x00, 0xC2, 0x34, 0x14, 0x02, 0x83,
+		/* 0x38: */     0x00, 0x93, 0x00, 0x77, 0x00, 0x00, 0x00, 0x3A,
+		/* 0x40: */        0,    0,    0,    0,    0,    0,    0,    0,
+		/* 0x48: */        0,    0,    0,    0,    0,    0,    0,    0
+	};
+
+	size_t i;
+
+	for (i = 0; i < ARRAY_SIZE(dacvalue); i++) {
+		if ((i <= 0x17) ||
+		    (i == 0x1b) ||
+		    (i == 0x1c) ||
+		    ((i >= 0x1f) && (i <= 0x29)) ||
+		    ((i >= 0x30) && (i <= 0x37)))
+			continue;
+		WREG_DAC(i, dacvalue[i]);
+	}
+
+	WREG_DAC(0x90, 0); /* G200ER specific */
+
+	mgag200_init_registers(mdev);
+}
+
 /*
  * DRM device
  */
@@ -36,6 +68,8 @@ struct mga_device *mgag200_g200er_device_create(struct pci_dev *pdev, const stru
 	if (ret)
 		return ERR_PTR(ret);
 
+	mgag200_g200er_init_registers(mdev);
+
 	vram_available = mgag200_device_probe_vram(mdev);
 
 	ret = mgag200_modeset_init(mdev, vram_available);
diff --git a/drivers/gpu/drm/mgag200/mgag200_g200ev.c b/drivers/gpu/drm/mgag200/mgag200_g200ev.c
index 5353422d0eef..ce26d48c9691 100644
--- a/drivers/gpu/drm/mgag200/mgag200_g200ev.c
+++ b/drivers/gpu/drm/mgag200/mgag200_g200ev.c
@@ -6,6 +6,44 @@
 
 #include "mgag200_drv.h"
 
+static void mgag200_g200ev_init_registers(struct mga_device *mdev)
+{
+	static const u8 dacvalue[] = {
+		/* 0x00: */        0,    0,    0,    0,    0,    0,    0,    0,
+		/* 0x08: */        0,    0,    0,    0,    0,    0,    0,    0,
+		/* 0x10: */        0,    0,    0,    0,    0,    0,    0,    0,
+		/* 0x18: */     0x00,    0,
+				/* G200EV specific: MGA1064_PIX_CLK_CTL */
+		/* 0x1a: */     MGA1064_PIX_CLK_CTL_SEL_PLL,
+		/* 0x1b: */     0xFF, 0xBF, 0x20,
+				/* G200EV specific: MGA1064_MISC_CTL */
+		/* 0x1e: */     MGA1064_MISC_CTL_VGA8 |
+				MGA1064_MISC_CTL_DAC_RAM_CS,
+		/* 0x1f: */     0x20,
+		/* 0x20: */     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+		/* 0x28: */     0x00, 0x00, 0x00, 0x00,    0,    0,    0, 0x40,
+		/* 0x30: */     0x00, 0xB0, 0x00, 0xC2, 0x34, 0x14, 0x02, 0x83,
+		/* 0x38: */     0x00, 0x93, 0x00, 0x77, 0x00, 0x00, 0x00, 0x3A,
+		/* 0x40: */        0,    0,    0,    0,    0,    0,    0,    0,
+		/* 0x48: */        0,    0,    0,    0,    0,    0,    0,    0
+	};
+
+	size_t i;
+
+	for (i = 0; i < ARRAY_SIZE(dacvalue); i++) {
+		if ((i <= 0x17) ||
+		    (i == 0x1b) ||
+		    (i == 0x1c) ||
+		    ((i >= 0x1f) && (i <= 0x29)) ||
+		    ((i >= 0x30) && (i <= 0x37)) ||
+		    ((i >= 0x44) && (i <= 0x4e)))
+			continue;
+		WREG_DAC(i, dacvalue[i]);
+	}
+
+	mgag200_init_registers(mdev);
+}
+
 /*
  * DRM device
  */
@@ -40,6 +78,8 @@ struct mga_device *mgag200_g200ev_device_create(struct pci_dev *pdev, const stru
 	if (ret)
 		return ERR_PTR(ret);
 
+	mgag200_g200ev_init_registers(mdev);
+
 	vram_available = mgag200_device_probe_vram(mdev);
 
 	ret = mgag200_modeset_init(mdev, vram_available);
diff --git a/drivers/gpu/drm/mgag200/mgag200_g200ew3.c b/drivers/gpu/drm/mgag200/mgag200_g200ew3.c
index 3bfc1324cf78..d86284c0eb4d 100644
--- a/drivers/gpu/drm/mgag200/mgag200_g200ew3.c
+++ b/drivers/gpu/drm/mgag200/mgag200_g200ew3.c
@@ -50,6 +50,8 @@ struct mga_device *mgag200_g200ew3_device_create(struct pci_dev *pdev,
 	if (ret)
 		return ERR_PTR(ret);
 
+	mgag200_g200wb_init_registers(mdev); // same as G200WB
+
 	vram_available = mgag200_g200ew3_device_probe_vram(mdev);
 
 	ret = mgag200_modeset_init(mdev, vram_available);
diff --git a/drivers/gpu/drm/mgag200/mgag200_g200se.c b/drivers/gpu/drm/mgag200/mgag200_g200se.c
index 0a3e66695e22..9f51be8ef731 100644
--- a/drivers/gpu/drm/mgag200/mgag200_g200se.c
+++ b/drivers/gpu/drm/mgag200/mgag200_g200se.c
@@ -28,6 +28,49 @@ static int mgag200_g200se_init_pci_options(struct pci_dev *pdev)
 	return mgag200_init_pci_options(pdev, option, 0x00008000);
 }
 
+static void mgag200_g200se_init_registers(struct mgag200_g200se_device *g200se)
+{
+	static const u8 dacvalue[] = {
+		/* 0x00: */        0,    0,    0,    0,    0,    0, 0x00,    0,
+		/* 0x08: */        0,    0,    0,    0,    0,    0,    0,    0,
+		/* 0x10: */        0,    0,    0,    0,    0,    0,    0,    0,
+				/* G200SE specific: MGA1064_VREF_CTL */
+		/* 0x18: */     0x03,
+		/* 0x19: */        0,
+				/* G200EV specific: MGA1064_PIX_CLK_CTL */
+		/* 0x1a: */     MGA1064_PIX_CLK_CTL_SEL_PLL,
+		/* 0x1b: */     0xFF, 0xBF, 0x20,
+				/* G200EV specific: MGA1064_MISC_CTL */
+		/* 0x1e: */     MGA1064_MISC_CTL_DAC_EN |
+				MGA1064_MISC_CTL_VGA8 |
+				MGA1064_MISC_CTL_DAC_RAM_CS,
+
+		/* 0x19: */        0, 0xC9, 0xFF, 0xBF, 0x20, 0x1F, 0x20,
+		/* 0x20: */     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+		/* 0x28: */     0x00, 0x00, 0x00, 0x00,    0,    0,    0, 0x40,
+		/* 0x30: */     0x00, 0xB0, 0x00, 0xC2, 0x34, 0x14, 0x02, 0x83,
+		/* 0x38: */     0x00, 0x93, 0x00, 0x77, 0x00, 0x00, 0x00, 0x3A,
+		/* 0x40: */        0,    0,    0,    0,    0,    0,    0,    0,
+		/* 0x48: */        0,    0,    0,    0,    0,    0,    0,    0
+	};
+
+	struct mga_device *mdev = &g200se->base;
+	size_t i;
+
+	for (i = 0; i < ARRAY_SIZE(dacvalue); i++) {
+		if ((i <= 0x17) ||
+		    (i == 0x1b) ||
+		    (i == 0x1c) ||
+		    ((i >= 0x1f) && (i <= 0x29)) ||
+		    ((i == 0x2c) || (i == 0x2d) || (i == 0x2e)) ||
+		    ((i >= 0x30) && (i <= 0x37)))
+			continue;
+		WREG_DAC(i, dacvalue[i]);
+	}
+
+	mgag200_init_registers(mdev);
+}
+
 /*
  * DRM device
  */
@@ -120,6 +163,8 @@ struct mga_device *mgag200_g200se_device_create(struct pci_dev *pdev, const stru
 	if (ret)
 		return ERR_PTR(ret);
 
+	mgag200_g200se_init_registers(g200se);
+
 	vram_available = mgag200_device_probe_vram(mdev);
 
 	ret = mgag200_modeset_init(mdev, vram_available);
diff --git a/drivers/gpu/drm/mgag200/mgag200_g200wb.c b/drivers/gpu/drm/mgag200/mgag200_g200wb.c
index c8450ac8eaec..e4de4b2dc2e2 100644
--- a/drivers/gpu/drm/mgag200/mgag200_g200wb.c
+++ b/drivers/gpu/drm/mgag200/mgag200_g200wb.c
@@ -6,6 +6,38 @@
 
 #include "mgag200_drv.h"
 
+void mgag200_g200wb_init_registers(struct mga_device *mdev)
+{
+	static const u8 dacvalue[] = {
+		/* 0x00: */        0,    0,    0,    0,    0,    0,    0,    0,
+		/* 0x08: */        0,    0,    0,    0,    0,    0,    0,    0,
+		/* 0x10: */        0,    0,    0,    0,    0,    0,    0,    0,
+		/* 0x18: */     0x07, /* G200WB specific: MGA1064_VREF_CTL */
+		/* 0x19: */        0, 0xC9, 0xFF, 0xBF, 0x20, 0x1F, 0x20,
+		/* 0x20: */     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+		/* 0x28: */     0x00, 0x00, 0x00, 0x00,    0,    0,    0, 0x40,
+		/* 0x30: */     0x00, 0xB0, 0x00, 0xC2, 0x34, 0x14, 0x02, 0x83,
+		/* 0x38: */     0x00, 0x93, 0x00, 0x77, 0x00, 0x00, 0x00, 0x3A,
+		/* 0x40: */        0,    0,    0,    0,    0,    0,    0,    0,
+		/* 0x48: */        0,    0,    0,    0,    0,    0,    0,    0
+	};
+
+	size_t i;
+
+	for (i = 0; i < ARRAY_SIZE(dacvalue); i++) {
+		if ((i <= 0x17) ||
+		    (i == 0x1b) ||
+		    (i == 0x1c) ||
+		    ((i >= 0x1f) && (i <= 0x29)) ||
+		    ((i >= 0x30) && (i <= 0x37)) ||
+		    ((i >= 0x44) && (i <= 0x4e)))
+			continue;
+		WREG_DAC(i, dacvalue[i]);
+	}
+
+	mgag200_init_registers(mdev);
+}
+
 /*
  * DRM device
  */
@@ -40,6 +72,8 @@ struct mga_device *mgag200_g200wb_device_create(struct pci_dev *pdev, const stru
 	if (ret)
 		return ERR_PTR(ret);
 
+	mgag200_g200wb_init_registers(mdev);
+
 	vram_available = mgag200_device_probe_vram(mdev);
 
 	ret = mgag200_modeset_init(mdev, vram_available);
diff --git a/drivers/gpu/drm/mgag200/mgag200_mode.c b/drivers/gpu/drm/mgag200/mgag200_mode.c
index e08852482fe2..f9868d728e6d 100644
--- a/drivers/gpu/drm/mgag200/mgag200_mode.c
+++ b/drivers/gpu/drm/mgag200/mgag200_mode.c
@@ -267,86 +267,10 @@ static void mgag200_set_startadd(struct mga_device *mdev,
 	WREG_ECRT(0x00, crtcext0);
 }
 
-static void mgag200_set_dac_regs(struct mga_device *mdev)
-{
-	size_t i;
-	u8 dacvalue[] = {
-		/* 0x00: */        0,    0,    0,    0,    0,    0, 0x00,    0,
-		/* 0x08: */        0,    0,    0,    0,    0,    0,    0,    0,
-		/* 0x10: */        0,    0,    0,    0,    0,    0,    0,    0,
-		/* 0x18: */     0x00,    0, 0xC9, 0xFF, 0xBF, 0x20, 0x1F, 0x20,
-		/* 0x20: */     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-		/* 0x28: */     0x00, 0x00, 0x00, 0x00,    0,    0,    0, 0x40,
-		/* 0x30: */     0x00, 0xB0, 0x00, 0xC2, 0x34, 0x14, 0x02, 0x83,
-		/* 0x38: */     0x00, 0x93, 0x00, 0x77, 0x00, 0x00, 0x00, 0x3A,
-		/* 0x40: */        0,    0,    0,    0,    0,    0,    0,    0,
-		/* 0x48: */        0,    0,    0,    0,    0,    0,    0,    0
-	};
-
-	switch (mdev->type) {
-	case G200_PCI:
-	case G200_AGP:
-		dacvalue[MGA1064_SYS_PLL_M] = 0x04;
-		dacvalue[MGA1064_SYS_PLL_N] = 0x2D;
-		dacvalue[MGA1064_SYS_PLL_P] = 0x19;
-		break;
-	case G200_SE_A:
-	case G200_SE_B:
-		dacvalue[MGA1064_VREF_CTL] = 0x03;
-		dacvalue[MGA1064_PIX_CLK_CTL] = MGA1064_PIX_CLK_CTL_SEL_PLL;
-		dacvalue[MGA1064_MISC_CTL] = MGA1064_MISC_CTL_DAC_EN |
-					     MGA1064_MISC_CTL_VGA8 |
-					     MGA1064_MISC_CTL_DAC_RAM_CS;
-		break;
-	case G200_WB:
-	case G200_EW3:
-		dacvalue[MGA1064_VREF_CTL] = 0x07;
-		break;
-	case G200_EV:
-		dacvalue[MGA1064_PIX_CLK_CTL] = MGA1064_PIX_CLK_CTL_SEL_PLL;
-		dacvalue[MGA1064_MISC_CTL] = MGA1064_MISC_CTL_VGA8 |
-					     MGA1064_MISC_CTL_DAC_RAM_CS;
-		break;
-	case G200_EH:
-	case G200_EH3:
-		dacvalue[MGA1064_MISC_CTL] = MGA1064_MISC_CTL_VGA8 |
-					     MGA1064_MISC_CTL_DAC_RAM_CS;
-		break;
-	case G200_ER:
-		break;
-	}
-
-	for (i = 0; i < ARRAY_SIZE(dacvalue); i++) {
-		if ((i <= 0x17) ||
-		    (i == 0x1b) ||
-		    (i == 0x1c) ||
-		    ((i >= 0x1f) && (i <= 0x29)) ||
-		    ((i >= 0x30) && (i <= 0x37)))
-			continue;
-		if (IS_G200_SE(mdev) &&
-		    ((i == 0x2c) || (i == 0x2d) || (i == 0x2e)))
-			continue;
-		if ((mdev->type == G200_EV ||
-		    mdev->type == G200_WB ||
-		    mdev->type == G200_EH ||
-		    mdev->type == G200_EW3 ||
-		    mdev->type == G200_EH3) &&
-		    (i >= 0x44) && (i <= 0x4e))
-			continue;
-
-		WREG_DAC(i, dacvalue[i]);
-	}
-
-	if (mdev->type == G200_ER)
-		WREG_DAC(0x90, 0);
-}
-
-static void mgag200_init_regs(struct mga_device *mdev)
+void mgag200_init_registers(struct mga_device *mdev)
 {
 	u8 crtc11, misc;
 
-	mgag200_set_dac_regs(mdev);
-
 	WREG_SEQ(2, 0x0f);
 	WREG_SEQ(3, 0x00);
 	WREG_SEQ(4, 0x0e);
@@ -1127,8 +1051,6 @@ int mgag200_modeset_init(struct mga_device *mdev, resource_size_t vram_available
 	struct drm_device *dev = &mdev->base;
 	int ret;
 
-	mgag200_init_regs(mdev);
-
 	ret = mgag200_mode_config_init(mdev, vram_available);
 	if (ret)
 		return ret;
-- 
2.36.1


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

* [PATCH 03/14] dmr/mgag200: Move ER/EW3 register initializatino to per-model code
  2022-07-08  9:39 [PATCH 00/14] drm/mgag200: Move model-specific code into separate functions Thomas Zimmermann
  2022-07-08  9:39 ` [PATCH 01/14] drm/mgag200: Split mgag200_modeset_init() Thomas Zimmermann
  2022-07-08  9:39 ` [PATCH 02/14] drm/mgag200: Move DAC-register setup into model-specific code Thomas Zimmermann
@ 2022-07-08  9:39 ` Thomas Zimmermann
  2022-07-08  9:39 ` [PATCH 04/14] drm/mgag200: Acquire I/O-register lock in atomic_commit_tail function Thomas Zimmermann
                   ` (11 subsequent siblings)
  14 siblings, 0 replies; 28+ messages in thread
From: Thomas Zimmermann @ 2022-07-08  9:39 UTC (permalink / raw)
  To: airlied, airlied, jfalempe, daniel; +Cc: Thomas Zimmermann, dri-devel

The register initialization code contains special cases for G200ER
and G200EW3 hardware. Move this to per-model code.

Signed-off-by: Thomas Zimmermann <tzimmermann@suse.de>
---
 drivers/gpu/drm/mgag200/mgag200_g200er.c  | 2 ++
 drivers/gpu/drm/mgag200/mgag200_g200ew3.c | 9 ++++++++-
 drivers/gpu/drm/mgag200/mgag200_mode.c    | 6 ------
 3 files changed, 10 insertions(+), 7 deletions(-)

diff --git a/drivers/gpu/drm/mgag200/mgag200_g200er.c b/drivers/gpu/drm/mgag200/mgag200_g200er.c
index acdccc419944..4489b382ebd0 100644
--- a/drivers/gpu/drm/mgag200/mgag200_g200er.c
+++ b/drivers/gpu/drm/mgag200/mgag200_g200er.c
@@ -36,6 +36,8 @@ static void mgag200_g200er_init_registers(struct mga_device *mdev)
 	WREG_DAC(0x90, 0); /* G200ER specific */
 
 	mgag200_init_registers(mdev);
+
+	WREG_ECRT(0x24, 0x5); /* G200ER specific */
 }
 
 /*
diff --git a/drivers/gpu/drm/mgag200/mgag200_g200ew3.c b/drivers/gpu/drm/mgag200/mgag200_g200ew3.c
index d86284c0eb4d..a4ecdd3784a3 100644
--- a/drivers/gpu/drm/mgag200/mgag200_g200ew3.c
+++ b/drivers/gpu/drm/mgag200/mgag200_g200ew3.c
@@ -6,6 +6,13 @@
 
 #include "mgag200_drv.h"
 
+static void mgag200_g200ew3_init_registers(struct mga_device *mdev)
+{
+	mgag200_g200wb_init_registers(mdev); // same as G200WB
+
+	WREG_ECRT(0x34, 0x5); // G200EW3 specific
+}
+
 /*
  * DRM device
  */
@@ -50,7 +57,7 @@ struct mga_device *mgag200_g200ew3_device_create(struct pci_dev *pdev,
 	if (ret)
 		return ERR_PTR(ret);
 
-	mgag200_g200wb_init_registers(mdev); // same as G200WB
+	mgag200_g200ew3_init_registers(mdev);
 
 	vram_available = mgag200_g200ew3_device_probe_vram(mdev);
 
diff --git a/drivers/gpu/drm/mgag200/mgag200_mode.c b/drivers/gpu/drm/mgag200/mgag200_mode.c
index f9868d728e6d..9bd5d743a87e 100644
--- a/drivers/gpu/drm/mgag200/mgag200_mode.c
+++ b/drivers/gpu/drm/mgag200/mgag200_mode.c
@@ -288,12 +288,6 @@ void mgag200_init_registers(struct mga_device *mdev)
 		    MGAREG_CRTC11_VINTCLR);
 	WREG_CRT(0x11, crtc11);
 
-	if (mdev->type == G200_ER)
-		WREG_ECRT(0x24, 0x5);
-
-	if (mdev->type == G200_EW3)
-		WREG_ECRT(0x34, 0x5);
-
 	misc = RREG8(MGA_MISC_IN);
 	misc |= MGAREG_MISC_IOADSEL;
 	WREG8(MGA_MISC_OUT, misc);
-- 
2.36.1


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

* [PATCH 04/14] drm/mgag200: Acquire I/O-register lock in atomic_commit_tail function
  2022-07-08  9:39 [PATCH 00/14] drm/mgag200: Move model-specific code into separate functions Thomas Zimmermann
                   ` (2 preceding siblings ...)
  2022-07-08  9:39 ` [PATCH 03/14] dmr/mgag200: Move ER/EW3 register initializatino to per-model code Thomas Zimmermann
@ 2022-07-08  9:39 ` Thomas Zimmermann
  2022-07-08  9:39 ` [PATCH 05/14] drm/mgag200: Store primary plane's color format in CRTC state Thomas Zimmermann
                   ` (10 subsequent siblings)
  14 siblings, 0 replies; 28+ messages in thread
From: Thomas Zimmermann @ 2022-07-08  9:39 UTC (permalink / raw)
  To: airlied, airlied, jfalempe, daniel; +Cc: Thomas Zimmermann, dri-devel

Hold I/O-register lock in atomic_commit_tail to protect all pipeline
updates at once. Protects against concurrent I/O access in get-modes
helper.

Complex modesetting operations involve mode changes, plane updates and
possibly BMC updates. Make all this atomic wrt to reading display modes
via EDID. It's not so much an issue with simple-KMS helpers, but will
become necessary for using regular atomic helpers.

Signed-off-by: Thomas Zimmermann <tzimmermann@suse.de>
---
 drivers/gpu/drm/mgag200/mgag200_mode.c | 36 ++++++++++++++++----------
 1 file changed, 22 insertions(+), 14 deletions(-)

diff --git a/drivers/gpu/drm/mgag200/mgag200_mode.c b/drivers/gpu/drm/mgag200/mgag200_mode.c
index 9bd5d743a87e..0c98742a1b65 100644
--- a/drivers/gpu/drm/mgag200/mgag200_mode.c
+++ b/drivers/gpu/drm/mgag200/mgag200_mode.c
@@ -11,6 +11,7 @@
 #include <linux/delay.h>
 #include <linux/iosys-map.h>
 
+#include <drm/drm_atomic.h>
 #include <drm/drm_atomic_helper.h>
 #include <drm/drm_atomic_state_helper.h>
 #include <drm/drm_crtc_helper.h>
@@ -703,14 +704,6 @@ mgag200_simple_display_pipe_enable(struct drm_simple_display_pipe *pipe,
 		.y2 = fb->height,
 	};
 
-	/*
-	 * Concurrent operations could possibly trigger a call to
-	 * drm_connector_helper_funcs.get_modes by trying to read the
-	 * display modes. Protect access to I/O registers by acquiring
-	 * the I/O-register lock.
-	 */
-	mutex_lock(&mdev->rmmio_lock);
-
 	if (mdev->type == G200_WB || mdev->type == G200_EW3)
 		mgag200_g200wb_hold_bmc(mdev);
 
@@ -742,8 +735,6 @@ mgag200_simple_display_pipe_enable(struct drm_simple_display_pipe *pipe,
 	/* Always scanout image at VRAM offset 0 */
 	mgag200_set_startadd(mdev, (u32)0);
 	mgag200_set_offset(mdev, fb);
-
-	mutex_unlock(&mdev->rmmio_lock);
 }
 
 static void
@@ -813,8 +804,6 @@ mgag200_simple_display_pipe_update(struct drm_simple_display_pipe *pipe,
 	if (!fb)
 		return;
 
-	mutex_lock(&mdev->rmmio_lock);
-
 	if (crtc->state->color_mgmt_changed && crtc->state->gamma_lut)
 		mgag200_crtc_set_gamma(mdev, fb->format, crtc->state->gamma_lut->data);
 
@@ -825,8 +814,6 @@ mgag200_simple_display_pipe_update(struct drm_simple_display_pipe *pipe,
 	/* Always scanout image at VRAM offset 0 */
 	mgag200_set_startadd(mdev, (u32)0);
 	mgag200_set_offset(mdev, fb);
-
-	mutex_unlock(&mdev->rmmio_lock);
 }
 
 static struct drm_crtc_state *
@@ -904,6 +891,26 @@ static const uint64_t mgag200_simple_display_pipe_fmtmods[] = {
  * Mode config
  */
 
+static void mgag200_mode_config_helper_atomic_commit_tail(struct drm_atomic_state *state)
+{
+	struct mga_device *mdev = to_mga_device(state->dev);
+
+	/*
+	 * Concurrent operations could possibly trigger a call to
+	 * drm_connector_helper_funcs.get_modes by trying to read the
+	 * display modes. Protect access to I/O registers by acquiring
+	 * the I/O-register lock.
+	 */
+	mutex_lock(&mdev->rmmio_lock);
+	drm_atomic_helper_commit_tail(state);
+	mutex_unlock(&mdev->rmmio_lock);
+}
+
+static const struct drm_mode_config_helper_funcs mgag200_mode_config_helper_funcs = {
+	.atomic_commit_tail = mgag200_mode_config_helper_atomic_commit_tail,
+};
+
+
 /* Calculates a mode's required memory bandwidth (in KiB/sec). */
 static uint32_t mgag200_calculate_mode_bandwidth(const struct drm_display_mode *mode,
 						 unsigned int bits_per_pixel)
@@ -984,6 +991,7 @@ static int mgag200_mode_config_init(struct mga_device *mdev, resource_size_t vra
 	dev->mode_config.preferred_depth = 24;
 	dev->mode_config.fb_base = mdev->vram_res->start;
 	dev->mode_config.funcs = &mgag200_mode_config_funcs;
+	dev->mode_config.helper_private = &mgag200_mode_config_helper_funcs;
 
 	return 0;
 }
-- 
2.36.1


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

* [PATCH 05/14] drm/mgag200: Store primary plane's color format in CRTC state
  2022-07-08  9:39 [PATCH 00/14] drm/mgag200: Move model-specific code into separate functions Thomas Zimmermann
                   ` (3 preceding siblings ...)
  2022-07-08  9:39 ` [PATCH 04/14] drm/mgag200: Acquire I/O-register lock in atomic_commit_tail function Thomas Zimmermann
@ 2022-07-08  9:39 ` Thomas Zimmermann
  2022-07-08  9:39 ` [PATCH 06/14] drm/mgag200: Reorganize before dropping simple-KMS helpers Thomas Zimmermann
                   ` (9 subsequent siblings)
  14 siblings, 0 replies; 28+ messages in thread
From: Thomas Zimmermann @ 2022-07-08  9:39 UTC (permalink / raw)
  To: airlied, airlied, jfalempe, daniel; +Cc: Thomas Zimmermann, dri-devel

Store the primary plane's color format in the CRTC state and use
it for programming the CRTC's gamma LUTs.

Gamma tables (i.e., color management) are provided by the CRTC, but
depend in the primary plane's color format. Store the format in the
CRTC state and use it. This has not been an issue with simple-KMS
helpers, which mix-up plane and CRTC state to some extent. For using
regular atomic helpers, it's necessary to distinguish between the two.

Signed-off-by: Thomas Zimmermann <tzimmermann@suse.de>
---
 drivers/gpu/drm/mgag200/mgag200_drv.h  |  3 +++
 drivers/gpu/drm/mgag200/mgag200_mode.c | 22 ++++++++++++----------
 2 files changed, 15 insertions(+), 10 deletions(-)

diff --git a/drivers/gpu/drm/mgag200/mgag200_drv.h b/drivers/gpu/drm/mgag200/mgag200_drv.h
index 6a2a1ad914c1..b5bccbc8820d 100644
--- a/drivers/gpu/drm/mgag200/mgag200_drv.h
+++ b/drivers/gpu/drm/mgag200/mgag200_drv.h
@@ -160,6 +160,9 @@ struct mgag200_pll {
 struct mgag200_crtc_state {
 	struct drm_crtc_state base;
 
+	/* Primary-plane format; required for modesetting and color mgmt. */
+	const struct drm_format_info *format;
+
 	struct mgag200_pll_values pixpllc;
 };
 
diff --git a/drivers/gpu/drm/mgag200/mgag200_mode.c b/drivers/gpu/drm/mgag200/mgag200_mode.c
index 0c98742a1b65..bbd1d97a926f 100644
--- a/drivers/gpu/drm/mgag200/mgag200_mode.c
+++ b/drivers/gpu/drm/mgag200/mgag200_mode.c
@@ -419,11 +419,9 @@ static void mgag200_set_offset(struct mga_device *mdev,
 	WREG_ECRT(0x00, crtcext0);
 }
 
-static void mgag200_set_format_regs(struct mga_device *mdev,
-				    const struct drm_framebuffer *fb)
+static void mgag200_set_format_regs(struct mga_device *mdev, const struct drm_format_info *format)
 {
 	struct drm_device *dev = &mdev->base;
-	const struct drm_format_info *format = fb->format;
 	unsigned int bpp, bppshift, scale;
 	u8 crtcext3, xmulctrl;
 
@@ -502,7 +500,7 @@ static void mgag200_g200er_reset_tagfifo(struct mga_device *mdev)
 
 static void mgag200_g200se_set_hiprilvl(struct mga_device *mdev,
 					const struct drm_display_mode *mode,
-					const struct drm_framebuffer *fb)
+					const struct drm_format_info *format)
 {
 	struct mgag200_g200se_device *g200se = to_mgag200_g200se_device(&mdev->base);
 	unsigned int hiprilvl;
@@ -514,9 +512,9 @@ static void mgag200_g200se_set_hiprilvl(struct mga_device *mdev,
 		unsigned int bpp;
 		unsigned long mb;
 
-		if (fb->format->cpp[0] * 8 > 16)
+		if (format->cpp[0] * 8 > 16)
 			bpp = 32;
-		else if (fb->format->cpp[0] * 8 > 8)
+		else if (format->cpp[0] * 8 > 8)
 			bpp = 16;
 		else
 			bpp = 8;
@@ -696,6 +694,7 @@ mgag200_simple_display_pipe_enable(struct drm_simple_display_pipe *pipe,
 	struct drm_display_mode *adjusted_mode = &crtc_state->adjusted_mode;
 	struct mgag200_crtc_state *mgag200_crtc_state = to_mgag200_crtc_state(crtc_state);
 	struct drm_framebuffer *fb = plane_state->fb;
+	const struct drm_format_info *format = mgag200_crtc_state->format;
 	struct drm_shadow_plane_state *shadow_plane_state = to_drm_shadow_plane_state(plane_state);
 	struct drm_rect fullscreen = {
 		.x1 = 0,
@@ -707,7 +706,7 @@ mgag200_simple_display_pipe_enable(struct drm_simple_display_pipe *pipe,
 	if (mdev->type == G200_WB || mdev->type == G200_EW3)
 		mgag200_g200wb_hold_bmc(mdev);
 
-	mgag200_set_format_regs(mdev, fb);
+	mgag200_set_format_regs(mdev, format);
 	mgag200_set_mode_regs(mdev, adjusted_mode);
 
 	pixpll->funcs->update(pixpll, &mgag200_crtc_state->pixpllc);
@@ -716,7 +715,7 @@ mgag200_simple_display_pipe_enable(struct drm_simple_display_pipe *pipe,
 		mgag200_g200er_reset_tagfifo(mdev);
 
 	if (IS_G200_SE(mdev))
-		mgag200_g200se_set_hiprilvl(mdev, adjusted_mode, fb);
+		mgag200_g200se_set_hiprilvl(mdev, adjusted_mode, format);
 	else if (mdev->type == G200_EV)
 		mgag200_g200ev_set_hiprilvl(mdev);
 
@@ -724,9 +723,9 @@ mgag200_simple_display_pipe_enable(struct drm_simple_display_pipe *pipe,
 		mgag200_g200wb_release_bmc(mdev);
 
 	if (crtc_state->gamma_lut)
-		mgag200_crtc_set_gamma(mdev, fb->format, crtc_state->gamma_lut->data);
+		mgag200_crtc_set_gamma(mdev, format, crtc_state->gamma_lut->data);
 	else
-		mgag200_crtc_set_gamma_linear(mdev, fb->format);
+		mgag200_crtc_set_gamma_linear(mdev, format);
 
 	mgag200_enable_display(mdev);
 
@@ -769,6 +768,8 @@ mgag200_simple_display_pipe_check(struct drm_simple_display_pipe *pipe,
 	if (!fb || (fb->format != new_fb->format))
 		crtc_state->mode_changed = true; /* update PLL settings */
 
+	mgag200_crtc_state->format = new_fb->format;
+
 	if (crtc_state->mode_changed) {
 		ret = pixpll->funcs->compute(pixpll, crtc_state->mode.clock,
 					     &mgag200_crtc_state->pixpllc);
@@ -832,6 +833,7 @@ mgag200_simple_display_pipe_duplicate_crtc_state(struct drm_simple_display_pipe
 		return NULL;
 	__drm_atomic_helper_crtc_duplicate_state(crtc, &new_mgag200_crtc_state->base);
 
+	new_mgag200_crtc_state->format = mgag200_crtc_state->format;
 	memcpy(&new_mgag200_crtc_state->pixpllc, &mgag200_crtc_state->pixpllc,
 	       sizeof(new_mgag200_crtc_state->pixpllc));
 
-- 
2.36.1


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

* [PATCH 06/14] drm/mgag200: Reorganize before dropping simple-KMS helpers
  2022-07-08  9:39 [PATCH 00/14] drm/mgag200: Move model-specific code into separate functions Thomas Zimmermann
                   ` (4 preceding siblings ...)
  2022-07-08  9:39 ` [PATCH 05/14] drm/mgag200: Store primary plane's color format in CRTC state Thomas Zimmermann
@ 2022-07-08  9:39 ` Thomas Zimmermann
  2022-07-08  9:39 ` [PATCH 07/14] drm/mgag200: Replace simple-KMS with regular atomic helpers Thomas Zimmermann
                   ` (8 subsequent siblings)
  14 siblings, 0 replies; 28+ messages in thread
From: Thomas Zimmermann @ 2022-07-08  9:39 UTC (permalink / raw)
  To: airlied, airlied, jfalempe, daniel; +Cc: Thomas Zimmermann, dri-devel

Move around some modesetting code before dropping simple-KMS helpers.
Makes the next patch more readable. No functional changes.

Signed-off-by: Thomas Zimmermann <tzimmermann@suse.de>
---
 drivers/gpu/drm/mgag200/mgag200_mode.c | 95 +++++++++++++-------------
 1 file changed, 47 insertions(+), 48 deletions(-)

diff --git a/drivers/gpu/drm/mgag200/mgag200_mode.c b/drivers/gpu/drm/mgag200/mgag200_mode.c
index bbd1d97a926f..fe11bb5d092e 100644
--- a/drivers/gpu/drm/mgag200/mgag200_mode.c
+++ b/drivers/gpu/drm/mgag200/mgag200_mode.c
@@ -604,42 +604,31 @@ static void mgag200_disable_display(struct mga_device *mdev)
 	WREG_ECRT(0x01, crtcext1);
 }
 
-/*
- * Connector
- */
-
-static int mgag200_vga_connector_helper_get_modes(struct drm_connector *connector)
+static void mgag200_handle_damage(struct mga_device *mdev, const struct iosys_map *vmap,
+				  struct drm_framebuffer *fb, const struct drm_rect *clip)
 {
-	struct mga_device *mdev = to_mga_device(connector->dev);
-	int ret;
-
-	/*
-	 * Protect access to I/O registers from concurrent modesetting
-	 * by acquiring the I/O-register lock.
-	 */
-	mutex_lock(&mdev->rmmio_lock);
-	ret = drm_connector_helper_get_modes_from_ddc(connector);
-	mutex_unlock(&mdev->rmmio_lock);
+	void __iomem *dst = mdev->vram;
+	void *vaddr = vmap[0].vaddr; /* TODO: Use mapping abstraction properly */
 
-	return ret;
+	dst += drm_fb_clip_offset(fb->pitches[0], fb->format, clip);
+	drm_fb_memcpy_toio(dst, fb->pitches[0], vaddr, fb, clip);
 }
 
-static const struct drm_connector_helper_funcs mga_vga_connector_helper_funcs = {
-	.get_modes  = mgag200_vga_connector_helper_get_modes,
-};
-
-static const struct drm_connector_funcs mga_vga_connector_funcs = {
-	.reset                  = drm_atomic_helper_connector_reset,
-	.fill_modes             = drm_helper_probe_single_connector_modes,
-	.destroy                = drm_connector_cleanup,
-	.atomic_duplicate_state = drm_atomic_helper_connector_duplicate_state,
-	.atomic_destroy_state   = drm_atomic_helper_connector_destroy_state,
-};
-
 /*
  * Simple Display Pipe
  */
 
+static const uint32_t mgag200_simple_display_pipe_formats[] = {
+	DRM_FORMAT_XRGB8888,
+	DRM_FORMAT_RGB565,
+	DRM_FORMAT_RGB888,
+};
+
+static const uint64_t mgag200_simple_display_pipe_fmtmods[] = {
+	DRM_FORMAT_MOD_LINEAR,
+	DRM_FORMAT_MOD_INVALID
+};
+
 static enum drm_mode_status
 mgag200_simple_display_pipe_mode_valid(struct drm_simple_display_pipe *pipe,
 				       const struct drm_display_mode *mode)
@@ -671,17 +660,6 @@ mgag200_simple_display_pipe_mode_valid(struct drm_simple_display_pipe *pipe,
 	return MODE_OK;
 }
 
-static void
-mgag200_handle_damage(struct mga_device *mdev, struct drm_framebuffer *fb,
-		      struct drm_rect *clip, const struct iosys_map *map)
-{
-	void __iomem *dst = mdev->vram;
-	void *vmap = map->vaddr; /* TODO: Use mapping abstraction properly */
-
-	dst += drm_fb_clip_offset(fb->pitches[0], fb->format, clip);
-	drm_fb_memcpy_toio(dst, fb->pitches[0], vmap, fb, clip);
-}
-
 static void
 mgag200_simple_display_pipe_enable(struct drm_simple_display_pipe *pipe,
 				   struct drm_crtc_state *crtc_state,
@@ -729,7 +707,7 @@ mgag200_simple_display_pipe_enable(struct drm_simple_display_pipe *pipe,
 
 	mgag200_enable_display(mdev);
 
-	mgag200_handle_damage(mdev, fb, &fullscreen, &shadow_plane_state->data[0]);
+	mgag200_handle_damage(mdev, shadow_plane_state->data, fb, &fullscreen);
 
 	/* Always scanout image at VRAM offset 0 */
 	mgag200_set_startadd(mdev, (u32)0);
@@ -810,7 +788,7 @@ mgag200_simple_display_pipe_update(struct drm_simple_display_pipe *pipe,
 
 	drm_atomic_helper_damage_iter_init(&iter, old_state, state);
 	drm_atomic_for_each_plane_damage(&iter, &damage) {
-		mgag200_handle_damage(mdev, fb, &damage, &shadow_plane_state->data[0]);
+		mgag200_handle_damage(mdev, shadow_plane_state->data, fb, &damage);
 	}
 	/* Always scanout image at VRAM offset 0 */
 	mgag200_set_startadd(mdev, (u32)0);
@@ -878,15 +856,36 @@ mgag200_simple_display_pipe_funcs = {
 	DRM_GEM_SIMPLE_DISPLAY_PIPE_SHADOW_PLANE_FUNCS,
 };
 
-static const uint32_t mgag200_simple_display_pipe_formats[] = {
-	DRM_FORMAT_XRGB8888,
-	DRM_FORMAT_RGB565,
-	DRM_FORMAT_RGB888,
+/*
+ * Connector
+ */
+
+static int mgag200_vga_connector_helper_get_modes(struct drm_connector *connector)
+{
+	struct mga_device *mdev = to_mga_device(connector->dev);
+	int ret;
+
+	/*
+	 * Protect access to I/O registers from concurrent modesetting
+	 * by acquiring the I/O-register lock.
+	 */
+	mutex_lock(&mdev->rmmio_lock);
+	ret = drm_connector_helper_get_modes_from_ddc(connector);
+	mutex_unlock(&mdev->rmmio_lock);
+
+	return ret;
+}
+
+static const struct drm_connector_helper_funcs mga_vga_connector_helper_funcs = {
+	.get_modes  = mgag200_vga_connector_helper_get_modes,
 };
 
-static const uint64_t mgag200_simple_display_pipe_fmtmods[] = {
-	DRM_FORMAT_MOD_LINEAR,
-	DRM_FORMAT_MOD_INVALID
+static const struct drm_connector_funcs mga_vga_connector_funcs = {
+	.reset                  = drm_atomic_helper_connector_reset,
+	.fill_modes             = drm_helper_probe_single_connector_modes,
+	.destroy                = drm_connector_cleanup,
+	.atomic_duplicate_state = drm_atomic_helper_connector_duplicate_state,
+	.atomic_destroy_state   = drm_atomic_helper_connector_destroy_state,
 };
 
 /*
-- 
2.36.1


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

* [PATCH 07/14] drm/mgag200: Replace simple-KMS with regular atomic helpers
  2022-07-08  9:39 [PATCH 00/14] drm/mgag200: Move model-specific code into separate functions Thomas Zimmermann
                   ` (5 preceding siblings ...)
  2022-07-08  9:39 ` [PATCH 06/14] drm/mgag200: Reorganize before dropping simple-KMS helpers Thomas Zimmermann
@ 2022-07-08  9:39 ` Thomas Zimmermann
       [not found]   ` <20230425142519.13201-1-kernel@linuxace.com>
  2022-07-08  9:39 ` [PATCH 08/14] drm/mgag200: Set SCROFF in primary-plane code Thomas Zimmermann
                   ` (7 subsequent siblings)
  14 siblings, 1 reply; 28+ messages in thread
From: Thomas Zimmermann @ 2022-07-08  9:39 UTC (permalink / raw)
  To: airlied, airlied, jfalempe, daniel; +Cc: Thomas Zimmermann, dri-devel

Drop simple-KMS in favor of regular atomic helpers. Makes the code
more modular and hence better to adapt to per-model requirements.

The simple-KMS helpers provide few extra features, so the patch is
mostly about open-coding what simple-KMS does. The simple-KMS helpers
do mix up plane and CRTC state. Changing to regular atomic helpers
requires to split some of the simple-pipe functions into per-plane
and per-CRTC code

No functional changes

Signed-off-by: Thomas Zimmermann <tzimmermann@suse.de>
---
 drivers/gpu/drm/mgag200/mgag200_drv.h  |   8 +-
 drivers/gpu/drm/mgag200/mgag200_mode.c | 385 +++++++++++++++----------
 2 files changed, 236 insertions(+), 157 deletions(-)

diff --git a/drivers/gpu/drm/mgag200/mgag200_drv.h b/drivers/gpu/drm/mgag200/mgag200_drv.h
index b5bccbc8820d..84579c2e1f3c 100644
--- a/drivers/gpu/drm/mgag200/mgag200_drv.h
+++ b/drivers/gpu/drm/mgag200/mgag200_drv.h
@@ -15,11 +15,13 @@
 
 #include <video/vga.h>
 
+#include <drm/drm_connector.h>
+#include <drm/drm_crtc.h>
 #include <drm/drm_encoder.h>
 #include <drm/drm_fb_helper.h>
 #include <drm/drm_gem.h>
 #include <drm/drm_gem_shmem_helper.h>
-#include <drm/drm_simple_kms_helper.h>
+#include <drm/drm_plane.h>
 
 #include "mgag200_reg.h"
 
@@ -249,9 +251,11 @@ struct mga_device {
 	enum mga_type			type;
 
 	struct mgag200_pll pixpll;
+	struct drm_plane primary_plane;
+	struct drm_crtc crtc;
+	struct drm_encoder encoder;
 	struct mga_i2c_chan i2c;
 	struct drm_connector connector;
-	struct drm_simple_display_pipe display_pipe;
 };
 
 static inline struct mga_device *to_mga_device(struct drm_device *dev)
diff --git a/drivers/gpu/drm/mgag200/mgag200_mode.c b/drivers/gpu/drm/mgag200/mgag200_mode.c
index fe11bb5d092e..39509dd84b23 100644
--- a/drivers/gpu/drm/mgag200/mgag200_mode.c
+++ b/drivers/gpu/drm/mgag200/mgag200_mode.c
@@ -24,7 +24,6 @@
 #include <drm/drm_plane_helper.h>
 #include <drm/drm_print.h>
 #include <drm/drm_probe_helper.h>
-#include <drm/drm_simple_kms_helper.h>
 
 #include "mgag200_drv.h"
 
@@ -615,25 +614,108 @@ static void mgag200_handle_damage(struct mga_device *mdev, const struct iosys_ma
 }
 
 /*
- * Simple Display Pipe
+ * Primary plane
  */
 
-static const uint32_t mgag200_simple_display_pipe_formats[] = {
+static const uint32_t mgag200_primary_plane_formats[] = {
 	DRM_FORMAT_XRGB8888,
 	DRM_FORMAT_RGB565,
 	DRM_FORMAT_RGB888,
 };
 
-static const uint64_t mgag200_simple_display_pipe_fmtmods[] = {
+static const uint64_t mgag200_primary_plane_fmtmods[] = {
 	DRM_FORMAT_MOD_LINEAR,
 	DRM_FORMAT_MOD_INVALID
 };
 
-static enum drm_mode_status
-mgag200_simple_display_pipe_mode_valid(struct drm_simple_display_pipe *pipe,
-				       const struct drm_display_mode *mode)
+static int mgag200_primary_plane_helper_atomic_check(struct drm_plane *plane,
+						     struct drm_atomic_state *state)
 {
-	struct mga_device *mdev = to_mga_device(pipe->crtc.dev);
+	struct drm_plane_state *new_plane_state = drm_atomic_get_new_plane_state(state, plane);
+	struct drm_framebuffer *new_fb = new_plane_state->fb;
+	struct drm_framebuffer *fb = NULL;
+	struct drm_crtc_state *new_crtc_state;
+	struct mgag200_crtc_state *new_mgag200_crtc_state;
+	int ret;
+
+	if (!new_fb)
+		return 0;
+
+	new_crtc_state = drm_atomic_get_new_crtc_state(state, new_plane_state->crtc);
+
+	ret = drm_atomic_helper_check_plane_state(new_plane_state, new_crtc_state,
+						  DRM_PLANE_HELPER_NO_SCALING,
+						  DRM_PLANE_HELPER_NO_SCALING,
+						  false, true);
+	if (ret)
+		return ret;
+
+	if (!new_plane_state->visible)
+		return 0;
+
+	if (plane->state)
+		fb = plane->state->fb;
+
+	if (!fb || (fb->format != new_fb->format))
+		new_crtc_state->mode_changed = true; /* update PLL settings */
+
+	new_mgag200_crtc_state = to_mgag200_crtc_state(new_crtc_state);
+	new_mgag200_crtc_state->format = new_fb->format;
+
+	return 0;
+}
+
+static void mgag200_primary_plane_helper_atomic_update(struct drm_plane *plane,
+						       struct drm_atomic_state *old_state)
+{
+	struct drm_device *dev = plane->dev;
+	struct mga_device *mdev = to_mga_device(dev);
+	struct drm_plane_state *plane_state = plane->state;
+	struct drm_plane_state *old_plane_state = drm_atomic_get_old_plane_state(old_state, plane);
+	struct drm_shadow_plane_state *shadow_plane_state = to_drm_shadow_plane_state(plane_state);
+	struct drm_framebuffer *fb = plane_state->fb;
+	struct drm_atomic_helper_damage_iter iter;
+	struct drm_rect damage;
+
+	if (!fb)
+		return;
+
+	drm_atomic_helper_damage_iter_init(&iter, old_plane_state, plane_state);
+	drm_atomic_for_each_plane_damage(&iter, &damage) {
+		mgag200_handle_damage(mdev, shadow_plane_state->data, fb, &damage);
+	}
+
+	/* Always scanout image at VRAM offset 0 */
+	mgag200_set_startadd(mdev, (u32)0);
+	mgag200_set_offset(mdev, fb);
+}
+
+static void mgag200_primary_plane_helper_atomic_disable(struct drm_plane *plane,
+							struct drm_atomic_state *old_state)
+{ }
+
+static const struct drm_plane_helper_funcs mgag200_primary_plane_helper_funcs = {
+	DRM_GEM_SHADOW_PLANE_HELPER_FUNCS,
+	.atomic_check = mgag200_primary_plane_helper_atomic_check,
+	.atomic_update = mgag200_primary_plane_helper_atomic_update,
+	.atomic_disable = mgag200_primary_plane_helper_atomic_disable,
+};
+
+static const struct drm_plane_funcs mgag200_primary_plane_funcs = {
+	.update_plane = drm_atomic_helper_update_plane,
+	.disable_plane = drm_atomic_helper_disable_plane,
+	.destroy = drm_plane_cleanup,
+	DRM_GEM_SHADOW_PLANE_FUNCS,
+};
+
+/*
+ * CRTC
+ */
+
+static enum drm_mode_status mgag200_crtc_helper_mode_valid(struct drm_crtc *crtc,
+							   const struct drm_display_mode *mode)
+{
+	struct mga_device *mdev = to_mga_device(crtc->dev);
 	const struct mgag200_device_info *info = mdev->info;
 
 	/*
@@ -660,26 +742,70 @@ mgag200_simple_display_pipe_mode_valid(struct drm_simple_display_pipe *pipe,
 	return MODE_OK;
 }
 
-static void
-mgag200_simple_display_pipe_enable(struct drm_simple_display_pipe *pipe,
-				   struct drm_crtc_state *crtc_state,
-				   struct drm_plane_state *plane_state)
+static int mgag200_crtc_helper_atomic_check(struct drm_crtc *crtc,
+					    struct drm_atomic_state *state)
 {
-	struct drm_crtc *crtc = &pipe->crtc;
 	struct drm_device *dev = crtc->dev;
 	struct mga_device *mdev = to_mga_device(dev);
+	struct drm_crtc_state *new_crtc_state = drm_atomic_get_new_crtc_state(state, crtc);
 	struct mgag200_pll *pixpll = &mdev->pixpll;
+	struct mgag200_crtc_state *mgag200_crtc_state = to_mgag200_crtc_state(new_crtc_state);
+	int ret;
+
+	ret = drm_atomic_helper_check_crtc_state(new_crtc_state, false);
+	if (ret)
+		return ret;
+
+	if (!new_crtc_state->enable)
+		return 0;
+
+	if (new_crtc_state->mode_changed) {
+		ret = pixpll->funcs->compute(pixpll, new_crtc_state->mode.clock,
+					     &mgag200_crtc_state->pixpllc);
+		if (ret)
+			return ret;
+	}
+
+	if (new_crtc_state->color_mgmt_changed && new_crtc_state->gamma_lut) {
+		if (new_crtc_state->gamma_lut->length !=
+		    MGAG200_LUT_SIZE * sizeof(struct drm_color_lut)) {
+			drm_err(dev, "Wrong size for gamma_lut %zu\n",
+				new_crtc_state->gamma_lut->length);
+			return -EINVAL;
+		}
+	}
+
+	return drm_atomic_add_affected_planes(state, crtc);
+}
+
+static void mgag200_crtc_helper_atomic_flush(struct drm_crtc *crtc,
+					     struct drm_atomic_state *old_state)
+{
+	struct drm_crtc_state *crtc_state = crtc->state;
+	struct mgag200_crtc_state *mgag200_crtc_state = to_mgag200_crtc_state(crtc_state);
+	struct drm_device *dev = crtc->dev;
+	struct mga_device *mdev = to_mga_device(dev);
+
+	if (crtc_state->enable && crtc_state->color_mgmt_changed) {
+		const struct drm_format_info *format = mgag200_crtc_state->format;
+
+		if (crtc_state->gamma_lut)
+			mgag200_crtc_set_gamma(mdev, format, crtc_state->gamma_lut->data);
+		else
+			mgag200_crtc_set_gamma_linear(mdev, format);
+	}
+}
+
+static void mgag200_crtc_helper_atomic_enable(struct drm_crtc *crtc,
+					      struct drm_atomic_state *old_state)
+{
+	struct drm_device *dev = crtc->dev;
+	struct mga_device *mdev = to_mga_device(dev);
+	struct drm_crtc_state *crtc_state = crtc->state;
 	struct drm_display_mode *adjusted_mode = &crtc_state->adjusted_mode;
 	struct mgag200_crtc_state *mgag200_crtc_state = to_mgag200_crtc_state(crtc_state);
-	struct drm_framebuffer *fb = plane_state->fb;
 	const struct drm_format_info *format = mgag200_crtc_state->format;
-	struct drm_shadow_plane_state *shadow_plane_state = to_drm_shadow_plane_state(plane_state);
-	struct drm_rect fullscreen = {
-		.x1 = 0,
-		.x2 = fb->width,
-		.y1 = 0,
-		.y2 = fb->height,
-	};
+	struct mgag200_pll *pixpll = &mdev->pixpll;
 
 	if (mdev->type == G200_WB || mdev->type == G200_EW3)
 		mgag200_g200wb_hold_bmc(mdev);
@@ -697,108 +823,50 @@ mgag200_simple_display_pipe_enable(struct drm_simple_display_pipe *pipe,
 	else if (mdev->type == G200_EV)
 		mgag200_g200ev_set_hiprilvl(mdev);
 
-	if (mdev->type == G200_WB || mdev->type == G200_EW3)
-		mgag200_g200wb_release_bmc(mdev);
-
-	if (crtc_state->gamma_lut)
-		mgag200_crtc_set_gamma(mdev, format, crtc_state->gamma_lut->data);
-	else
-		mgag200_crtc_set_gamma_linear(mdev, format);
-
 	mgag200_enable_display(mdev);
 
-	mgag200_handle_damage(mdev, shadow_plane_state->data, fb, &fullscreen);
-
-	/* Always scanout image at VRAM offset 0 */
-	mgag200_set_startadd(mdev, (u32)0);
-	mgag200_set_offset(mdev, fb);
+	if (mdev->type == G200_WB || mdev->type == G200_EW3)
+		mgag200_g200wb_release_bmc(mdev);
 }
 
-static void
-mgag200_simple_display_pipe_disable(struct drm_simple_display_pipe *pipe)
+static void mgag200_crtc_helper_atomic_disable(struct drm_crtc *crtc,
+					       struct drm_atomic_state *old_state)
 {
-	struct drm_crtc *crtc = &pipe->crtc;
 	struct mga_device *mdev = to_mga_device(crtc->dev);
 
-	mgag200_disable_display(mdev);
-}
-
-static int
-mgag200_simple_display_pipe_check(struct drm_simple_display_pipe *pipe,
-				  struct drm_plane_state *plane_state,
-				  struct drm_crtc_state *crtc_state)
-{
-	struct drm_plane *plane = plane_state->plane;
-	struct drm_device *dev = plane->dev;
-	struct mga_device *mdev = to_mga_device(dev);
-	struct mgag200_pll *pixpll = &mdev->pixpll;
-	struct mgag200_crtc_state *mgag200_crtc_state = to_mgag200_crtc_state(crtc_state);
-	struct drm_framebuffer *new_fb = plane_state->fb;
-	struct drm_framebuffer *fb = NULL;
-	int ret;
-
-	if (!new_fb)
-		return 0;
-
-	if (plane->state)
-		fb = plane->state->fb;
-
-	if (!fb || (fb->format != new_fb->format))
-		crtc_state->mode_changed = true; /* update PLL settings */
-
-	mgag200_crtc_state->format = new_fb->format;
+	if (mdev->type == G200_WB || mdev->type == G200_EW3)
+		mgag200_g200wb_hold_bmc(mdev);
 
-	if (crtc_state->mode_changed) {
-		ret = pixpll->funcs->compute(pixpll, crtc_state->mode.clock,
-					     &mgag200_crtc_state->pixpllc);
-		if (ret)
-			return ret;
-	}
+	mgag200_disable_display(mdev);
 
-	if (crtc_state->color_mgmt_changed && crtc_state->gamma_lut) {
-		if (crtc_state->gamma_lut->length !=
-		    MGAG200_LUT_SIZE * sizeof(struct drm_color_lut)) {
-			drm_err(dev, "Wrong size for gamma_lut %zu\n",
-				crtc_state->gamma_lut->length);
-			return -EINVAL;
-		}
-	}
-	return 0;
+	if (mdev->type == G200_WB || mdev->type == G200_EW3)
+		mgag200_g200wb_release_bmc(mdev);
 }
 
-static void
-mgag200_simple_display_pipe_update(struct drm_simple_display_pipe *pipe,
-				   struct drm_plane_state *old_state)
-{
-	struct drm_plane *plane = &pipe->plane;
-	struct drm_crtc *crtc = &pipe->crtc;
-	struct drm_device *dev = plane->dev;
-	struct mga_device *mdev = to_mga_device(dev);
-	struct drm_plane_state *state = plane->state;
-	struct drm_shadow_plane_state *shadow_plane_state = to_drm_shadow_plane_state(state);
-	struct drm_framebuffer *fb = state->fb;
-	struct drm_rect damage;
-	struct drm_atomic_helper_damage_iter iter;
+static const struct drm_crtc_helper_funcs mgag200_crtc_helper_funcs = {
+	.mode_valid = mgag200_crtc_helper_mode_valid,
+	.atomic_check = mgag200_crtc_helper_atomic_check,
+	.atomic_flush = mgag200_crtc_helper_atomic_flush,
+	.atomic_enable = mgag200_crtc_helper_atomic_enable,
+	.atomic_disable = mgag200_crtc_helper_atomic_disable,
+};
 
-	if (!fb)
-		return;
+static void mgag200_crtc_reset(struct drm_crtc *crtc)
+{
+	struct mgag200_crtc_state *mgag200_crtc_state;
 
-	if (crtc->state->color_mgmt_changed && crtc->state->gamma_lut)
-		mgag200_crtc_set_gamma(mdev, fb->format, crtc->state->gamma_lut->data);
+	if (crtc->state)
+		crtc->funcs->atomic_destroy_state(crtc, crtc->state);
 
-	drm_atomic_helper_damage_iter_init(&iter, old_state, state);
-	drm_atomic_for_each_plane_damage(&iter, &damage) {
-		mgag200_handle_damage(mdev, shadow_plane_state->data, fb, &damage);
-	}
-	/* Always scanout image at VRAM offset 0 */
-	mgag200_set_startadd(mdev, (u32)0);
-	mgag200_set_offset(mdev, fb);
+	mgag200_crtc_state = kzalloc(sizeof(*mgag200_crtc_state), GFP_KERNEL);
+	if (mgag200_crtc_state)
+		__drm_atomic_helper_crtc_reset(crtc, &mgag200_crtc_state->base);
+	else
+		__drm_atomic_helper_crtc_reset(crtc, NULL);
 }
 
-static struct drm_crtc_state *
-mgag200_simple_display_pipe_duplicate_crtc_state(struct drm_simple_display_pipe *pipe)
+static struct drm_crtc_state *mgag200_crtc_atomic_duplicate_state(struct drm_crtc *crtc)
 {
-	struct drm_crtc *crtc = &pipe->crtc;
 	struct drm_crtc_state *crtc_state = crtc->state;
 	struct mgag200_crtc_state *mgag200_crtc_state = to_mgag200_crtc_state(crtc_state);
 	struct mgag200_crtc_state *new_mgag200_crtc_state;
@@ -818,8 +886,8 @@ mgag200_simple_display_pipe_duplicate_crtc_state(struct drm_simple_display_pipe
 	return &new_mgag200_crtc_state->base;
 }
 
-static void mgag200_simple_display_pipe_destroy_crtc_state(struct drm_simple_display_pipe *pipe,
-							   struct drm_crtc_state *crtc_state)
+static void mgag200_crtc_atomic_destroy_state(struct drm_crtc *crtc,
+					      struct drm_crtc_state *crtc_state)
 {
 	struct mgag200_crtc_state *mgag200_crtc_state = to_mgag200_crtc_state(crtc_state);
 
@@ -827,33 +895,21 @@ static void mgag200_simple_display_pipe_destroy_crtc_state(struct drm_simple_dis
 	kfree(mgag200_crtc_state);
 }
 
-static void mgag200_simple_display_pipe_reset_crtc(struct drm_simple_display_pipe *pipe)
-{
-	struct drm_crtc *crtc = &pipe->crtc;
-	struct mgag200_crtc_state *mgag200_crtc_state;
-
-	if (crtc->state) {
-		mgag200_simple_display_pipe_destroy_crtc_state(pipe, crtc->state);
-		crtc->state = NULL; /* must be set to NULL here */
-	}
+static const struct drm_crtc_funcs mgag200_crtc_funcs = {
+	.reset = mgag200_crtc_reset,
+	.destroy = drm_crtc_cleanup,
+	.set_config = drm_atomic_helper_set_config,
+	.page_flip = drm_atomic_helper_page_flip,
+	.atomic_duplicate_state = mgag200_crtc_atomic_duplicate_state,
+	.atomic_destroy_state = mgag200_crtc_atomic_destroy_state,
+};
 
-	mgag200_crtc_state = kzalloc(sizeof(*mgag200_crtc_state), GFP_KERNEL);
-	if (!mgag200_crtc_state)
-		return;
-	__drm_atomic_helper_crtc_reset(crtc, &mgag200_crtc_state->base);
-}
+/*
+ * Encoder
+ */
 
-static const struct drm_simple_display_pipe_funcs
-mgag200_simple_display_pipe_funcs = {
-	.mode_valid = mgag200_simple_display_pipe_mode_valid,
-	.enable	    = mgag200_simple_display_pipe_enable,
-	.disable    = mgag200_simple_display_pipe_disable,
-	.check	    = mgag200_simple_display_pipe_check,
-	.update	    = mgag200_simple_display_pipe_update,
-	.reset_crtc = mgag200_simple_display_pipe_reset_crtc,
-	.duplicate_crtc_state = mgag200_simple_display_pipe_duplicate_crtc_state,
-	.destroy_crtc_state = mgag200_simple_display_pipe_destroy_crtc_state,
-	DRM_GEM_SIMPLE_DISPLAY_PIPE_SHADOW_PLANE_FUNCS,
+static const struct drm_encoder_funcs mgag200_dac_encoder_funcs = {
+	.destroy = drm_encoder_cleanup,
 };
 
 /*
@@ -1000,12 +1056,49 @@ static int mgag200_mode_config_init(struct mga_device *mdev, resource_size_t vra
 static int mgag200_pipeline_init(struct mga_device *mdev)
 {
 	struct drm_device *dev = &mdev->base;
+	struct drm_plane *primary_plane = &mdev->primary_plane;
+	struct drm_crtc *crtc = &mdev->crtc;
+	struct drm_encoder *encoder = &mdev->encoder;
 	struct mga_i2c_chan *i2c = &mdev->i2c;
 	struct drm_connector *connector = &mdev->connector;
-	struct drm_simple_display_pipe *pipe = &mdev->display_pipe;
-	size_t format_count = ARRAY_SIZE(mgag200_simple_display_pipe_formats);
 	int ret;
 
+	ret = mgag200_pixpll_init(&mdev->pixpll, mdev);
+	if (ret)
+		return ret;
+
+	ret = drm_universal_plane_init(dev, primary_plane, 0,
+				       &mgag200_primary_plane_funcs,
+				       mgag200_primary_plane_formats,
+				       ARRAY_SIZE(mgag200_primary_plane_formats),
+				       mgag200_primary_plane_fmtmods,
+				       DRM_PLANE_TYPE_PRIMARY, NULL);
+	if (ret) {
+		drm_err(dev, "drm_universal_plane_init() failed: %d\n", ret);
+		return ret;
+	}
+	drm_plane_helper_add(primary_plane, &mgag200_primary_plane_helper_funcs);
+	drm_plane_enable_fb_damage_clips(primary_plane);
+
+	ret = drm_crtc_init_with_planes(dev, crtc, primary_plane, NULL, &mgag200_crtc_funcs, NULL);
+	if (ret) {
+		drm_err(dev, "drm_crtc_init_with_planes() failed: %d\n", ret);
+		return ret;
+	}
+	drm_crtc_helper_add(crtc, &mgag200_crtc_helper_funcs);
+
+	/* FIXME: legacy gamma tables, but atomic gamma doesn't work without */
+	drm_mode_crtc_set_gamma_size(crtc, MGAG200_LUT_SIZE);
+	drm_crtc_enable_color_mgmt(crtc, 0, false, MGAG200_LUT_SIZE);
+
+	encoder->possible_crtcs = drm_crtc_mask(crtc);
+	ret = drm_encoder_init(dev, encoder, &mgag200_dac_encoder_funcs,
+			       DRM_MODE_ENCODER_DAC, NULL);
+	if (ret) {
+		drm_err(dev, "drm_encoder_init() failed: %d\n", ret);
+		return ret;
+	}
+
 	ret = mgag200_i2c_init(mdev, i2c);
 	if (ret) {
 		drm_err(dev, "failed to add DDC bus: %d\n", ret);
@@ -1022,30 +1115,12 @@ static int mgag200_pipeline_init(struct mga_device *mdev)
 	}
 	drm_connector_helper_add(connector, &mga_vga_connector_helper_funcs);
 
-	ret = mgag200_pixpll_init(&mdev->pixpll, mdev);
-	if (ret)
-		return ret;
-
-	ret = drm_simple_display_pipe_init(dev, pipe,
-					   &mgag200_simple_display_pipe_funcs,
-					   mgag200_simple_display_pipe_formats,
-					   format_count,
-					   mgag200_simple_display_pipe_fmtmods,
-					   connector);
+	ret = drm_connector_attach_encoder(connector, encoder);
 	if (ret) {
-		drm_err(dev,
-			"drm_simple_display_pipe_init() failed, error %d\n",
-			ret);
+		drm_err(dev, "drm_connector_attach_encoder() failed: %d\n", ret);
 		return ret;
 	}
 
-	drm_plane_enable_fb_damage_clips(&pipe->plane);
-
-	/* FIXME: legacy gamma tables, but atomic gamma doesn't work without */
-	drm_mode_crtc_set_gamma_size(&pipe->crtc, MGAG200_LUT_SIZE);
-
-	drm_crtc_enable_color_mgmt(&pipe->crtc, 0, false, MGAG200_LUT_SIZE);
-
 	return 0;
 }
 
-- 
2.36.1


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

* [PATCH 08/14] drm/mgag200: Set SCROFF in primary-plane code
  2022-07-08  9:39 [PATCH 00/14] drm/mgag200: Move model-specific code into separate functions Thomas Zimmermann
                   ` (6 preceding siblings ...)
  2022-07-08  9:39 ` [PATCH 07/14] drm/mgag200: Replace simple-KMS with regular atomic helpers Thomas Zimmermann
@ 2022-07-08  9:39 ` Thomas Zimmermann
  2022-07-08  9:39 ` [PATCH 09/14] drm/mgag200: Add per-device callbacks Thomas Zimmermann
                   ` (6 subsequent siblings)
  14 siblings, 0 replies; 28+ messages in thread
From: Thomas Zimmermann @ 2022-07-08  9:39 UTC (permalink / raw)
  To: airlied, airlied, jfalempe, daniel; +Cc: Thomas Zimmermann, dri-devel

The SCROFF bit controls reading the primary plane's scanout buffer
from video memory. Set it from primary-plane code, instead of CRTC
code.

Signed-off-by: Thomas Zimmermann <tzimmermann@suse.de>
---
 drivers/gpu/drm/mgag200/mgag200_mode.c | 33 ++++++++++++++------------
 1 file changed, 18 insertions(+), 15 deletions(-)

diff --git a/drivers/gpu/drm/mgag200/mgag200_mode.c b/drivers/gpu/drm/mgag200/mgag200_mode.c
index 39509dd84b23..789e02b8615f 100644
--- a/drivers/gpu/drm/mgag200/mgag200_mode.c
+++ b/drivers/gpu/drm/mgag200/mgag200_mode.c
@@ -550,7 +550,7 @@ static void mgag200_g200ev_set_hiprilvl(struct mga_device *mdev)
 
 static void mgag200_enable_display(struct mga_device *mdev)
 {
-	u8 seq0, seq1, crtcext1;
+	u8 seq0, crtcext1;
 
 	RREG_SEQ(0x00, seq0);
 	seq0 |= MGAREG_SEQ0_SYNCRST |
@@ -564,12 +564,6 @@ static void mgag200_enable_display(struct mga_device *mdev)
 	mga_wait_vsync(mdev);
 	mga_wait_busy(mdev);
 
-	RREG_SEQ(0x01, seq1);
-	seq1 &= ~MGAREG_SEQ1_SCROFF;
-	WREG_SEQ(0x01, seq1);
-
-	msleep(20);
-
 	RREG_ECRT(0x01, crtcext1);
 	crtcext1 &= ~MGAREG_CRTCEXT1_VSYNCOFF;
 	crtcext1 &= ~MGAREG_CRTCEXT1_HSYNCOFF;
@@ -578,7 +572,7 @@ static void mgag200_enable_display(struct mga_device *mdev)
 
 static void mgag200_disable_display(struct mga_device *mdev)
 {
-	u8 seq0, seq1, crtcext1;
+	u8 seq0, crtcext1;
 
 	RREG_SEQ(0x00, seq0);
 	seq0 &= ~MGAREG_SEQ0_SYNCRST;
@@ -591,12 +585,6 @@ static void mgag200_disable_display(struct mga_device *mdev)
 	mga_wait_vsync(mdev);
 	mga_wait_busy(mdev);
 
-	RREG_SEQ(0x01, seq1);
-	seq1 |= MGAREG_SEQ1_SCROFF;
-	WREG_SEQ(0x01, seq1);
-
-	msleep(20);
-
 	RREG_ECRT(0x01, crtcext1);
 	crtcext1 |= MGAREG_CRTCEXT1_VSYNCOFF |
 		    MGAREG_CRTCEXT1_HSYNCOFF;
@@ -676,6 +664,7 @@ static void mgag200_primary_plane_helper_atomic_update(struct drm_plane *plane,
 	struct drm_framebuffer *fb = plane_state->fb;
 	struct drm_atomic_helper_damage_iter iter;
 	struct drm_rect damage;
+	u8 seq1;
 
 	if (!fb)
 		return;
@@ -688,11 +677,25 @@ static void mgag200_primary_plane_helper_atomic_update(struct drm_plane *plane,
 	/* Always scanout image at VRAM offset 0 */
 	mgag200_set_startadd(mdev, (u32)0);
 	mgag200_set_offset(mdev, fb);
+
+	RREG_SEQ(0x01, seq1);
+	seq1 &= ~MGAREG_SEQ1_SCROFF;
+	WREG_SEQ(0x01, seq1);
+	msleep(20);
 }
 
 static void mgag200_primary_plane_helper_atomic_disable(struct drm_plane *plane,
 							struct drm_atomic_state *old_state)
-{ }
+{
+	struct drm_device *dev = plane->dev;
+	struct mga_device *mdev = to_mga_device(dev);
+	u8 seq1;
+
+	RREG_SEQ(0x01, seq1);
+	seq1 |= MGAREG_SEQ1_SCROFF;
+	WREG_SEQ(0x01, seq1);
+	msleep(20);
+}
 
 static const struct drm_plane_helper_funcs mgag200_primary_plane_helper_funcs = {
 	DRM_GEM_SHADOW_PLANE_HELPER_FUNCS,
-- 
2.36.1


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

* [PATCH 09/14] drm/mgag200: Add per-device callbacks
  2022-07-08  9:39 [PATCH 00/14] drm/mgag200: Move model-specific code into separate functions Thomas Zimmermann
                   ` (7 preceding siblings ...)
  2022-07-08  9:39 ` [PATCH 08/14] drm/mgag200: Set SCROFF in primary-plane code Thomas Zimmermann
@ 2022-07-08  9:39 ` Thomas Zimmermann
  2022-07-08  9:39 ` [PATCH 10/14] drm/mgag200: Provide per-device callbacks for BMC synchronization Thomas Zimmermann
                   ` (5 subsequent siblings)
  14 siblings, 0 replies; 28+ messages in thread
From: Thomas Zimmermann @ 2022-07-08  9:39 UTC (permalink / raw)
  To: airlied, airlied, jfalempe, daniel; +Cc: Thomas Zimmermann, dri-devel

While currently empty, the device callbacks will allow mgag200's
modesetting code to interact with the BMC and PIXPLLC.

Signed-off-by: Thomas Zimmermann <tzimmermann@suse.de>
---
 drivers/gpu/drm/mgag200/mgag200_drv.c     | 4 +++-
 drivers/gpu/drm/mgag200/mgag200_drv.h     | 7 ++++++-
 drivers/gpu/drm/mgag200/mgag200_g200.c    | 6 +++++-
 drivers/gpu/drm/mgag200/mgag200_g200eh.c  | 6 +++++-
 drivers/gpu/drm/mgag200/mgag200_g200eh3.c | 6 +++++-
 drivers/gpu/drm/mgag200/mgag200_g200er.c  | 6 +++++-
 drivers/gpu/drm/mgag200/mgag200_g200ev.c  | 6 +++++-
 drivers/gpu/drm/mgag200/mgag200_g200ew3.c | 6 +++++-
 drivers/gpu/drm/mgag200/mgag200_g200se.c  | 5 ++++-
 drivers/gpu/drm/mgag200/mgag200_g200wb.c  | 6 +++++-
 10 files changed, 48 insertions(+), 10 deletions(-)

diff --git a/drivers/gpu/drm/mgag200/mgag200_drv.c b/drivers/gpu/drm/mgag200/mgag200_drv.c
index 73e8e4e9e54b..c20a59a2cd91 100644
--- a/drivers/gpu/drm/mgag200/mgag200_drv.c
+++ b/drivers/gpu/drm/mgag200/mgag200_drv.c
@@ -162,13 +162,15 @@ int mgag200_device_preinit(struct mga_device *mdev)
 }
 
 int mgag200_device_init(struct mga_device *mdev, enum mga_type type,
-			const struct mgag200_device_info *info)
+			const struct mgag200_device_info *info,
+			const struct mgag200_device_funcs *funcs)
 {
 	struct drm_device *dev = &mdev->base;
 	u8 crtcext3, misc;
 	int ret;
 
 	mdev->info = info;
+	mdev->funcs = funcs;
 	mdev->type = type;
 
 	ret = drmm_mutex_init(dev, &mdev->rmmio_lock);
diff --git a/drivers/gpu/drm/mgag200/mgag200_drv.h b/drivers/gpu/drm/mgag200/mgag200_drv.h
index 84579c2e1f3c..68c0b72f7430 100644
--- a/drivers/gpu/drm/mgag200/mgag200_drv.h
+++ b/drivers/gpu/drm/mgag200/mgag200_drv.h
@@ -235,10 +235,14 @@ struct mgag200_device_info {
 		.bug_no_startadd = (_bug_no_startadd), \
 	}
 
+struct mgag200_device_funcs {
+};
+
 struct mga_device {
 	struct drm_device base;
 
 	const struct mgag200_device_info *info;
+	const struct mgag200_device_funcs *funcs;
 
 	struct resource			*rmmio_res;
 	void __iomem			*rmmio;
@@ -295,7 +299,8 @@ resource_size_t mgag200_probe_vram(void __iomem *mem, resource_size_t size);
 resource_size_t mgag200_device_probe_vram(struct mga_device *mdev);
 int mgag200_device_preinit(struct mga_device *mdev);
 int mgag200_device_init(struct mga_device *mdev, enum mga_type type,
-			const struct mgag200_device_info *info);
+			const struct mgag200_device_info *info,
+			const struct mgag200_device_funcs *funcs);
 
 				/* mgag200_<device type>.c */
 struct mga_device *mgag200_g200_device_create(struct pci_dev *pdev, const struct drm_driver *drv,
diff --git a/drivers/gpu/drm/mgag200/mgag200_g200.c b/drivers/gpu/drm/mgag200/mgag200_g200.c
index c6303fcb8fe7..5de77ef637f7 100644
--- a/drivers/gpu/drm/mgag200/mgag200_g200.c
+++ b/drivers/gpu/drm/mgag200/mgag200_g200.c
@@ -195,6 +195,9 @@ static void mgag200_g200_init_refclk(struct mgag200_g200_device *g200)
 	pci_unmap_rom(pdev, rom);
 }
 
+static const struct mgag200_device_funcs mgag200_g200_device_funcs = {
+};
+
 struct mga_device *mgag200_g200_device_create(struct pci_dev *pdev, const struct drm_driver *drv,
 					      enum mga_type type)
 {
@@ -222,7 +225,8 @@ struct mga_device *mgag200_g200_device_create(struct pci_dev *pdev, const struct
 
 	mgag200_g200_init_refclk(g200);
 
-	ret = mgag200_device_init(mdev, type, &mgag200_g200_device_info);
+	ret = mgag200_device_init(mdev, type, &mgag200_g200_device_info,
+				  &mgag200_g200_device_funcs);
 	if (ret)
 		return ERR_PTR(ret);
 
diff --git a/drivers/gpu/drm/mgag200/mgag200_g200eh.c b/drivers/gpu/drm/mgag200/mgag200_g200eh.c
index 365f486d3ce7..6acfc9eeeda9 100644
--- a/drivers/gpu/drm/mgag200/mgag200_g200eh.c
+++ b/drivers/gpu/drm/mgag200/mgag200_g200eh.c
@@ -47,6 +47,9 @@ void mgag200_g200eh_init_registers(struct mga_device *mdev)
 static const struct mgag200_device_info mgag200_g200eh_device_info =
 	MGAG200_DEVICE_INFO_INIT(2048, 2048, 37500, false, 1, 0, false);
 
+static const struct mgag200_device_funcs mgag200_g200eh_device_funcs = {
+};
+
 struct mga_device *mgag200_g200eh_device_create(struct pci_dev *pdev, const struct drm_driver *drv,
 						enum mga_type type)
 {
@@ -70,7 +73,8 @@ struct mga_device *mgag200_g200eh_device_create(struct pci_dev *pdev, const stru
 	if (ret)
 		return ERR_PTR(ret);
 
-	ret = mgag200_device_init(mdev, type, &mgag200_g200eh_device_info);
+	ret = mgag200_device_init(mdev, type, &mgag200_g200eh_device_info,
+				  &mgag200_g200eh_device_funcs);
 	if (ret)
 		return ERR_PTR(ret);
 
diff --git a/drivers/gpu/drm/mgag200/mgag200_g200eh3.c b/drivers/gpu/drm/mgag200/mgag200_g200eh3.c
index adb9190b62af..99e00aa848e1 100644
--- a/drivers/gpu/drm/mgag200/mgag200_g200eh3.c
+++ b/drivers/gpu/drm/mgag200/mgag200_g200eh3.c
@@ -13,6 +13,9 @@
 static const struct mgag200_device_info mgag200_g200eh3_device_info =
 	MGAG200_DEVICE_INFO_INIT(2048, 2048, 0, false, 1, 0, false);
 
+static const struct mgag200_device_funcs mgag200_g200eh3_device_funcs = {
+};
+
 struct mga_device *mgag200_g200eh3_device_create(struct pci_dev *pdev,
 						 const struct drm_driver *drv,
 						 enum mga_type type)
@@ -37,7 +40,8 @@ struct mga_device *mgag200_g200eh3_device_create(struct pci_dev *pdev,
 	if (ret)
 		return ERR_PTR(ret);
 
-	ret = mgag200_device_init(mdev, type, &mgag200_g200eh3_device_info);
+	ret = mgag200_device_init(mdev, type, &mgag200_g200eh3_device_info,
+				  &mgag200_g200eh3_device_funcs);
 	if (ret)
 		return ERR_PTR(ret);
 
diff --git a/drivers/gpu/drm/mgag200/mgag200_g200er.c b/drivers/gpu/drm/mgag200/mgag200_g200er.c
index 4489b382ebd0..76eb4776658a 100644
--- a/drivers/gpu/drm/mgag200/mgag200_g200er.c
+++ b/drivers/gpu/drm/mgag200/mgag200_g200er.c
@@ -47,6 +47,9 @@ static void mgag200_g200er_init_registers(struct mga_device *mdev)
 static const struct mgag200_device_info mgag200_g200er_device_info =
 	MGAG200_DEVICE_INFO_INIT(2048, 2048, 55000, false, 1, 0, false);
 
+static const struct mgag200_device_funcs mgag200_g200er_device_funcs = {
+};
+
 struct mga_device *mgag200_g200er_device_create(struct pci_dev *pdev, const struct drm_driver *drv,
 						enum mga_type type)
 {
@@ -66,7 +69,8 @@ struct mga_device *mgag200_g200er_device_create(struct pci_dev *pdev, const stru
 	if (ret)
 		return ERR_PTR(ret);
 
-	ret = mgag200_device_init(mdev, type, &mgag200_g200er_device_info);
+	ret = mgag200_device_init(mdev, type, &mgag200_g200er_device_info,
+				  &mgag200_g200er_device_funcs);
 	if (ret)
 		return ERR_PTR(ret);
 
diff --git a/drivers/gpu/drm/mgag200/mgag200_g200ev.c b/drivers/gpu/drm/mgag200/mgag200_g200ev.c
index ce26d48c9691..e9ea09195471 100644
--- a/drivers/gpu/drm/mgag200/mgag200_g200ev.c
+++ b/drivers/gpu/drm/mgag200/mgag200_g200ev.c
@@ -51,6 +51,9 @@ static void mgag200_g200ev_init_registers(struct mga_device *mdev)
 static const struct mgag200_device_info mgag200_g200ev_device_info =
 	MGAG200_DEVICE_INFO_INIT(2048, 2048, 32700, false, 0, 1, false);
 
+static const struct mgag200_device_funcs mgag200_g200ev_device_funcs = {
+};
+
 struct mga_device *mgag200_g200ev_device_create(struct pci_dev *pdev, const struct drm_driver *drv,
 						enum mga_type type)
 {
@@ -74,7 +77,8 @@ struct mga_device *mgag200_g200ev_device_create(struct pci_dev *pdev, const stru
 	if (ret)
 		return ERR_PTR(ret);
 
-	ret = mgag200_device_init(mdev, type, &mgag200_g200ev_device_info);
+	ret = mgag200_device_init(mdev, type, &mgag200_g200ev_device_info,
+				  &mgag200_g200ev_device_funcs);
 	if (ret)
 		return ERR_PTR(ret);
 
diff --git a/drivers/gpu/drm/mgag200/mgag200_g200ew3.c b/drivers/gpu/drm/mgag200/mgag200_g200ew3.c
index a4ecdd3784a3..202db00bb62e 100644
--- a/drivers/gpu/drm/mgag200/mgag200_g200ew3.c
+++ b/drivers/gpu/drm/mgag200/mgag200_g200ew3.c
@@ -20,6 +20,9 @@ static void mgag200_g200ew3_init_registers(struct mga_device *mdev)
 static const struct mgag200_device_info mgag200_g200ew3_device_info =
 	MGAG200_DEVICE_INFO_INIT(2048, 2048, 0, true, 0, 1, false);
 
+static const struct mgag200_device_funcs mgag200_g200ew3_device_funcs = {
+};
+
 static resource_size_t mgag200_g200ew3_device_probe_vram(struct mga_device *mdev)
 {
 	resource_size_t vram_size = resource_size(mdev->vram_res);
@@ -53,7 +56,8 @@ struct mga_device *mgag200_g200ew3_device_create(struct pci_dev *pdev,
 	if (ret)
 		return ERR_PTR(ret);
 
-	ret = mgag200_device_init(mdev, type, &mgag200_g200ew3_device_info);
+	ret = mgag200_device_init(mdev, type, &mgag200_g200ew3_device_info,
+				  &mgag200_g200ew3_device_funcs);
 	if (ret)
 		return ERR_PTR(ret);
 
diff --git a/drivers/gpu/drm/mgag200/mgag200_g200se.c b/drivers/gpu/drm/mgag200/mgag200_g200se.c
index 9f51be8ef731..5bdc20db3810 100644
--- a/drivers/gpu/drm/mgag200/mgag200_g200se.c
+++ b/drivers/gpu/drm/mgag200/mgag200_g200se.c
@@ -108,6 +108,9 @@ static int mgag200_g200se_init_unique_rev_id(struct mgag200_g200se_device *g200s
 	return 0;
 }
 
+static const struct mgag200_device_funcs mgag200_g200se_device_funcs = {
+};
+
 struct mga_device *mgag200_g200se_device_create(struct pci_dev *pdev, const struct drm_driver *drv,
 						enum mga_type type)
 {
@@ -159,7 +162,7 @@ struct mga_device *mgag200_g200se_device_create(struct pci_dev *pdev, const stru
 		return ERR_PTR(-EINVAL);
 	}
 
-	ret = mgag200_device_init(mdev, type, info);
+	ret = mgag200_device_init(mdev, type, info, &mgag200_g200se_device_funcs);
 	if (ret)
 		return ERR_PTR(ret);
 
diff --git a/drivers/gpu/drm/mgag200/mgag200_g200wb.c b/drivers/gpu/drm/mgag200/mgag200_g200wb.c
index e4de4b2dc2e2..3ca016b33e9a 100644
--- a/drivers/gpu/drm/mgag200/mgag200_g200wb.c
+++ b/drivers/gpu/drm/mgag200/mgag200_g200wb.c
@@ -45,6 +45,9 @@ void mgag200_g200wb_init_registers(struct mga_device *mdev)
 static const struct mgag200_device_info mgag200_g200wb_device_info =
 	MGAG200_DEVICE_INFO_INIT(1280, 1024, 31877, true, 0, 1, false);
 
+static const struct mgag200_device_funcs mgag200_g200wb_device_funcs = {
+};
+
 struct mga_device *mgag200_g200wb_device_create(struct pci_dev *pdev, const struct drm_driver *drv,
 						enum mga_type type)
 {
@@ -68,7 +71,8 @@ struct mga_device *mgag200_g200wb_device_create(struct pci_dev *pdev, const stru
 	if (ret)
 		return ERR_PTR(ret);
 
-	ret = mgag200_device_init(mdev, type, &mgag200_g200wb_device_info);
+	ret = mgag200_device_init(mdev, type, &mgag200_g200wb_device_info,
+				  &mgag200_g200wb_device_funcs);
 	if (ret)
 		return ERR_PTR(ret);
 
-- 
2.36.1


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

* [PATCH 10/14] drm/mgag200: Provide per-device callbacks for BMC synchronization
  2022-07-08  9:39 [PATCH 00/14] drm/mgag200: Move model-specific code into separate functions Thomas Zimmermann
                   ` (8 preceding siblings ...)
  2022-07-08  9:39 ` [PATCH 09/14] drm/mgag200: Add per-device callbacks Thomas Zimmermann
@ 2022-07-08  9:39 ` Thomas Zimmermann
  2022-07-08  9:39 ` [PATCH 11/14] drm/mgag200: Provide per-device callbacks for PIXPLLC Thomas Zimmermann
                   ` (4 subsequent siblings)
  14 siblings, 0 replies; 28+ messages in thread
From: Thomas Zimmermann @ 2022-07-08  9:39 UTC (permalink / raw)
  To: airlied, airlied, jfalempe, daniel; +Cc: Thomas Zimmermann, dri-devel

Move the BMC-related code into its own file and wire it up with device
callbacks.

While programming a new display mode, G200EW3 and G200WB have to de-
synchronize with the BMC. Synchronization is done via VIDRST pins
and controlled via VRSTEN and HRSTEN bits. Move the BMC code behind
a serviceable interface and call it from the CRTC's enable and
disable functions.

Signed-off-by: Thomas Zimmermann <tzimmermann@suse.de>
---
 drivers/gpu/drm/mgag200/Makefile          |   1 +
 drivers/gpu/drm/mgag200/mgag200_bmc.c     |  99 ++++++++++++++++++++
 drivers/gpu/drm/mgag200/mgag200_drv.h     |  15 +++
 drivers/gpu/drm/mgag200/mgag200_g200ew3.c |   2 +
 drivers/gpu/drm/mgag200/mgag200_g200wb.c  |   2 +
 drivers/gpu/drm/mgag200/mgag200_mode.c    | 107 ++--------------------
 6 files changed, 129 insertions(+), 97 deletions(-)
 create mode 100644 drivers/gpu/drm/mgag200/mgag200_bmc.c

diff --git a/drivers/gpu/drm/mgag200/Makefile b/drivers/gpu/drm/mgag200/Makefile
index 89558549c3af..94d465a2b753 100644
--- a/drivers/gpu/drm/mgag200/Makefile
+++ b/drivers/gpu/drm/mgag200/Makefile
@@ -1,5 +1,6 @@
 # SPDX-License-Identifier: GPL-2.0-only
 mgag200-y := \
+	mgag200_bmc.o \
 	mgag200_drv.o \
 	mgag200_g200.o \
 	mgag200_g200eh.o \
diff --git a/drivers/gpu/drm/mgag200/mgag200_bmc.c b/drivers/gpu/drm/mgag200/mgag200_bmc.c
new file mode 100644
index 000000000000..2ba2e3c5086a
--- /dev/null
+++ b/drivers/gpu/drm/mgag200/mgag200_bmc.c
@@ -0,0 +1,99 @@
+// SPDX-License-Identifier: GPL-2.0-only
+
+#include <linux/delay.h>
+
+#include "mgag200_drv.h"
+
+void mgag200_bmc_disable_vidrst(struct mga_device *mdev)
+{
+	u8 tmp;
+	int iter_max;
+
+	/*
+	 * 1 - The first step is to inform the BMC of an upcoming mode
+	 * change. We are putting the misc<0> to output.
+	 */
+
+	WREG8(DAC_INDEX, MGA1064_GEN_IO_CTL);
+	tmp = RREG8(DAC_DATA);
+	tmp |= 0x10;
+	WREG_DAC(MGA1064_GEN_IO_CTL, tmp);
+
+	/* we are putting a 1 on the misc<0> line */
+	WREG8(DAC_INDEX, MGA1064_GEN_IO_DATA);
+	tmp = RREG8(DAC_DATA);
+	tmp |= 0x10;
+	WREG_DAC(MGA1064_GEN_IO_DATA, tmp);
+
+	/*
+	 * 2- Second step to mask any further scan request. This is
+	 * done by asserting the remfreqmsk bit (XSPAREREG<7>)
+	 */
+
+	WREG8(DAC_INDEX, MGA1064_SPAREREG);
+	tmp = RREG8(DAC_DATA);
+	tmp |= 0x80;
+	WREG_DAC(MGA1064_SPAREREG, tmp);
+
+	/*
+	 * 3a- The third step is to verify if there is an active scan.
+	 * We are waiting for a 0 on remhsyncsts <XSPAREREG<0>).
+	 */
+	iter_max = 300;
+	while (!(tmp & 0x1) && iter_max) {
+		WREG8(DAC_INDEX, MGA1064_SPAREREG);
+		tmp = RREG8(DAC_DATA);
+		udelay(1000);
+		iter_max--;
+	}
+
+	/*
+	 * 3b- This step occurs only if the remove is actually
+	 * scanning. We are waiting for the end of the frame which is
+	 * a 1 on remvsyncsts (XSPAREREG<1>)
+	 */
+	if (iter_max) {
+		iter_max = 300;
+		while ((tmp & 0x2) && iter_max) {
+			WREG8(DAC_INDEX, MGA1064_SPAREREG);
+			tmp = RREG8(DAC_DATA);
+			udelay(1000);
+			iter_max--;
+		}
+	}
+}
+
+void mgag200_bmc_enable_vidrst(struct mga_device *mdev)
+{
+	u8 tmp;
+
+	/* Ensure that the vrsten and hrsten are set */
+	WREG8(MGAREG_CRTCEXT_INDEX, 1);
+	tmp = RREG8(MGAREG_CRTCEXT_DATA);
+	WREG8(MGAREG_CRTCEXT_DATA, tmp | 0x88);
+
+	/* Assert rstlvl2 */
+	WREG8(DAC_INDEX, MGA1064_REMHEADCTL2);
+	tmp = RREG8(DAC_DATA);
+	tmp |= 0x8;
+	WREG8(DAC_DATA, tmp);
+
+	udelay(10);
+
+	/* Deassert rstlvl2 */
+	tmp &= ~0x08;
+	WREG8(DAC_INDEX, MGA1064_REMHEADCTL2);
+	WREG8(DAC_DATA, tmp);
+
+	/* Remove mask of scan request */
+	WREG8(DAC_INDEX, MGA1064_SPAREREG);
+	tmp = RREG8(DAC_DATA);
+	tmp &= ~0x80;
+	WREG8(DAC_DATA, tmp);
+
+	/* Put back a 0 on the misc<0> line */
+	WREG8(DAC_INDEX, MGA1064_GEN_IO_DATA);
+	tmp = RREG8(DAC_DATA);
+	tmp &= ~0x10;
+	WREG_DAC(MGA1064_GEN_IO_DATA, tmp);
+}
diff --git a/drivers/gpu/drm/mgag200/mgag200_drv.h b/drivers/gpu/drm/mgag200/mgag200_drv.h
index 68c0b72f7430..e8b338198fdb 100644
--- a/drivers/gpu/drm/mgag200/mgag200_drv.h
+++ b/drivers/gpu/drm/mgag200/mgag200_drv.h
@@ -236,6 +236,17 @@ struct mgag200_device_info {
 	}
 
 struct mgag200_device_funcs {
+	/*
+	 * Disables an external reset source (i.e., BMC) before programming
+	 * a new display mode.
+	 */
+	void (*disable_vidrst)(struct mga_device *mdev);
+
+	/*
+	 * Enables an external reset source (i.e., BMC) after programming
+	 * a new display mode.
+	 */
+	void (*enable_vidrst)(struct mga_device *mdev);
 };
 
 struct mga_device {
@@ -327,6 +338,10 @@ resource_size_t mgag200_device_probe_vram(struct mga_device *mdev);
 void mgag200_init_registers(struct mga_device *mdev);
 int mgag200_modeset_init(struct mga_device *mdev, resource_size_t vram_fb_available);
 
+				/* mgag200_bmc.c */
+void mgag200_bmc_disable_vidrst(struct mga_device *mdev);
+void mgag200_bmc_enable_vidrst(struct mga_device *mdev);
+
 				/* mgag200_i2c.c */
 int mgag200_i2c_init(struct mga_device *mdev, struct mga_i2c_chan *i2c);
 
diff --git a/drivers/gpu/drm/mgag200/mgag200_g200ew3.c b/drivers/gpu/drm/mgag200/mgag200_g200ew3.c
index 202db00bb62e..19a870120ebc 100644
--- a/drivers/gpu/drm/mgag200/mgag200_g200ew3.c
+++ b/drivers/gpu/drm/mgag200/mgag200_g200ew3.c
@@ -21,6 +21,8 @@ static const struct mgag200_device_info mgag200_g200ew3_device_info =
 	MGAG200_DEVICE_INFO_INIT(2048, 2048, 0, true, 0, 1, false);
 
 static const struct mgag200_device_funcs mgag200_g200ew3_device_funcs = {
+	.disable_vidrst = mgag200_bmc_disable_vidrst,
+	.enable_vidrst = mgag200_bmc_enable_vidrst,
 };
 
 static resource_size_t mgag200_g200ew3_device_probe_vram(struct mga_device *mdev)
diff --git a/drivers/gpu/drm/mgag200/mgag200_g200wb.c b/drivers/gpu/drm/mgag200/mgag200_g200wb.c
index 3ca016b33e9a..92e174d63752 100644
--- a/drivers/gpu/drm/mgag200/mgag200_g200wb.c
+++ b/drivers/gpu/drm/mgag200/mgag200_g200wb.c
@@ -46,6 +46,8 @@ static const struct mgag200_device_info mgag200_g200wb_device_info =
 	MGAG200_DEVICE_INFO_INIT(1280, 1024, 31877, true, 0, 1, false);
 
 static const struct mgag200_device_funcs mgag200_g200wb_device_funcs = {
+	.disable_vidrst = mgag200_bmc_disable_vidrst,
+	.enable_vidrst = mgag200_bmc_enable_vidrst,
 };
 
 struct mga_device *mgag200_g200wb_device_create(struct pci_dev *pdev, const struct drm_driver *drv,
diff --git a/drivers/gpu/drm/mgag200/mgag200_mode.c b/drivers/gpu/drm/mgag200/mgag200_mode.c
index 789e02b8615f..7bcd3f6d891d 100644
--- a/drivers/gpu/drm/mgag200/mgag200_mode.c
+++ b/drivers/gpu/drm/mgag200/mgag200_mode.c
@@ -132,95 +132,6 @@ static inline void mga_wait_busy(struct mga_device *mdev)
 	} while ((status & 0x01) && time_before(jiffies, timeout));
 }
 
-static void mgag200_g200wb_hold_bmc(struct mga_device *mdev)
-{
-	u8 tmp;
-	int iter_max;
-
-	/* 1- The first step is to warn the BMC of an upcoming mode change.
-	 * We are putting the misc<0> to output.*/
-
-	WREG8(DAC_INDEX, MGA1064_GEN_IO_CTL);
-	tmp = RREG8(DAC_DATA);
-	tmp |= 0x10;
-	WREG_DAC(MGA1064_GEN_IO_CTL, tmp);
-
-	/* we are putting a 1 on the misc<0> line */
-	WREG8(DAC_INDEX, MGA1064_GEN_IO_DATA);
-	tmp = RREG8(DAC_DATA);
-	tmp |= 0x10;
-	WREG_DAC(MGA1064_GEN_IO_DATA, tmp);
-
-	/* 2- Second step to mask and further scan request
-	 * This will be done by asserting the remfreqmsk bit (XSPAREREG<7>)
-	 */
-	WREG8(DAC_INDEX, MGA1064_SPAREREG);
-	tmp = RREG8(DAC_DATA);
-	tmp |= 0x80;
-	WREG_DAC(MGA1064_SPAREREG, tmp);
-
-	/* 3a- the third step is to verifu if there is an active scan
-	 * We are searching for a 0 on remhsyncsts <XSPAREREG<0>)
-	 */
-	iter_max = 300;
-	while (!(tmp & 0x1) && iter_max) {
-		WREG8(DAC_INDEX, MGA1064_SPAREREG);
-		tmp = RREG8(DAC_DATA);
-		udelay(1000);
-		iter_max--;
-	}
-
-	/* 3b- this step occurs only if the remove is actually scanning
-	 * we are waiting for the end of the frame which is a 1 on
-	 * remvsyncsts (XSPAREREG<1>)
-	 */
-	if (iter_max) {
-		iter_max = 300;
-		while ((tmp & 0x2) && iter_max) {
-			WREG8(DAC_INDEX, MGA1064_SPAREREG);
-			tmp = RREG8(DAC_DATA);
-			udelay(1000);
-			iter_max--;
-		}
-	}
-}
-
-static void mgag200_g200wb_release_bmc(struct mga_device *mdev)
-{
-	u8 tmp;
-
-	/* 1- The first step is to ensure that the vrsten and hrsten are set */
-	WREG8(MGAREG_CRTCEXT_INDEX, 1);
-	tmp = RREG8(MGAREG_CRTCEXT_DATA);
-	WREG8(MGAREG_CRTCEXT_DATA, tmp | 0x88);
-
-	/* 2- second step is to assert the rstlvl2 */
-	WREG8(DAC_INDEX, MGA1064_REMHEADCTL2);
-	tmp = RREG8(DAC_DATA);
-	tmp |= 0x8;
-	WREG8(DAC_DATA, tmp);
-
-	/* wait 10 us */
-	udelay(10);
-
-	/* 3- deassert rstlvl2 */
-	tmp &= ~0x08;
-	WREG8(DAC_INDEX, MGA1064_REMHEADCTL2);
-	WREG8(DAC_DATA, tmp);
-
-	/* 4- remove mask of scan request */
-	WREG8(DAC_INDEX, MGA1064_SPAREREG);
-	tmp = RREG8(DAC_DATA);
-	tmp &= ~0x80;
-	WREG8(DAC_DATA, tmp);
-
-	/* 5- put back a 0 on the misc<0> line */
-	WREG8(DAC_INDEX, MGA1064_GEN_IO_DATA);
-	tmp = RREG8(DAC_DATA);
-	tmp &= ~0x10;
-	WREG_DAC(MGA1064_GEN_IO_DATA, tmp);
-}
-
 /*
  * This is how the framebuffer base address is stored in g200 cards:
  *   * Assume @offset is the gpu_addr variable of the framebuffer object
@@ -804,14 +715,15 @@ static void mgag200_crtc_helper_atomic_enable(struct drm_crtc *crtc,
 {
 	struct drm_device *dev = crtc->dev;
 	struct mga_device *mdev = to_mga_device(dev);
+	const struct mgag200_device_funcs *funcs = mdev->funcs;
 	struct drm_crtc_state *crtc_state = crtc->state;
 	struct drm_display_mode *adjusted_mode = &crtc_state->adjusted_mode;
 	struct mgag200_crtc_state *mgag200_crtc_state = to_mgag200_crtc_state(crtc_state);
 	const struct drm_format_info *format = mgag200_crtc_state->format;
 	struct mgag200_pll *pixpll = &mdev->pixpll;
 
-	if (mdev->type == G200_WB || mdev->type == G200_EW3)
-		mgag200_g200wb_hold_bmc(mdev);
+	if (funcs->disable_vidrst)
+		funcs->disable_vidrst(mdev);
 
 	mgag200_set_format_regs(mdev, format);
 	mgag200_set_mode_regs(mdev, adjusted_mode);
@@ -828,22 +740,23 @@ static void mgag200_crtc_helper_atomic_enable(struct drm_crtc *crtc,
 
 	mgag200_enable_display(mdev);
 
-	if (mdev->type == G200_WB || mdev->type == G200_EW3)
-		mgag200_g200wb_release_bmc(mdev);
+	if (funcs->enable_vidrst)
+		funcs->enable_vidrst(mdev);
 }
 
 static void mgag200_crtc_helper_atomic_disable(struct drm_crtc *crtc,
 					       struct drm_atomic_state *old_state)
 {
 	struct mga_device *mdev = to_mga_device(crtc->dev);
+	const struct mgag200_device_funcs *funcs = mdev->funcs;
 
-	if (mdev->type == G200_WB || mdev->type == G200_EW3)
-		mgag200_g200wb_hold_bmc(mdev);
+	if (funcs->disable_vidrst)
+		funcs->disable_vidrst(mdev);
 
 	mgag200_disable_display(mdev);
 
-	if (mdev->type == G200_WB || mdev->type == G200_EW3)
-		mgag200_g200wb_release_bmc(mdev);
+	if (funcs->enable_vidrst)
+		funcs->enable_vidrst(mdev);
 }
 
 static const struct drm_crtc_helper_funcs mgag200_crtc_helper_funcs = {
-- 
2.36.1


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

* [PATCH 11/14] drm/mgag200: Provide per-device callbacks for PIXPLLC
  2022-07-08  9:39 [PATCH 00/14] drm/mgag200: Move model-specific code into separate functions Thomas Zimmermann
                   ` (9 preceding siblings ...)
  2022-07-08  9:39 ` [PATCH 10/14] drm/mgag200: Provide per-device callbacks for BMC synchronization Thomas Zimmermann
@ 2022-07-08  9:39 ` Thomas Zimmermann
  2022-07-08  9:39 ` [PATCH 12/14] drm/mgag200: Move mode-config to model-specific code Thomas Zimmermann
                   ` (3 subsequent siblings)
  14 siblings, 0 replies; 28+ messages in thread
From: Thomas Zimmermann @ 2022-07-08  9:39 UTC (permalink / raw)
  To: airlied, airlied, jfalempe, daniel; +Cc: Thomas Zimmermann, dri-devel

Move the PIXPLLC code into per-model source files and wire it up
with per-model callbacks. No functional changes.

The PIXPLLC pixel-clock is part of the CRTC, but really separate
hardware that varies with each model of the G200. Move the PIXPLLC
code for each model into the per-model source file and call it from
CRTC helpers via device functions.

This allows to remove struct mgag200_pll and the related code. The
new callbacks behave like the CRTC's atomic_check and atomic_enable
functions.

Signed-off-by: Thomas Zimmermann <tzimmermann@suse.de>
---
 drivers/gpu/drm/mgag200/Makefile          |   3 +-
 drivers/gpu/drm/mgag200/mgag200_drv.h     |  32 +-
 drivers/gpu/drm/mgag200/mgag200_g200.c    | 109 +++
 drivers/gpu/drm/mgag200/mgag200_g200eh.c  | 131 +++
 drivers/gpu/drm/mgag200/mgag200_g200eh3.c |  59 ++
 drivers/gpu/drm/mgag200/mgag200_g200er.c  | 120 +++
 drivers/gpu/drm/mgag200/mgag200_g200ev.c  | 132 +++
 drivers/gpu/drm/mgag200/mgag200_g200ew3.c |  61 ++
 drivers/gpu/drm/mgag200/mgag200_g200se.c  | 211 ++++-
 drivers/gpu/drm/mgag200/mgag200_g200wb.c  | 180 ++++
 drivers/gpu/drm/mgag200/mgag200_mode.c    |  20 +-
 drivers/gpu/drm/mgag200/mgag200_pll.c     | 997 ----------------------
 12 files changed, 1026 insertions(+), 1029 deletions(-)
 delete mode 100644 drivers/gpu/drm/mgag200/mgag200_pll.c

diff --git a/drivers/gpu/drm/mgag200/Makefile b/drivers/gpu/drm/mgag200/Makefile
index 94d465a2b753..182e224c460d 100644
--- a/drivers/gpu/drm/mgag200/Makefile
+++ b/drivers/gpu/drm/mgag200/Makefile
@@ -11,7 +11,6 @@ mgag200-y := \
 	mgag200_g200se.o \
 	mgag200_g200wb.o \
 	mgag200_i2c.o \
-	mgag200_mode.o \
-	mgag200_pll.o
+	mgag200_mode.o
 
 obj-$(CONFIG_DRM_MGAG200) += mgag200.o
diff --git a/drivers/gpu/drm/mgag200/mgag200_drv.h b/drivers/gpu/drm/mgag200/mgag200_drv.h
index e8b338198fdb..8a7204e3ff96 100644
--- a/drivers/gpu/drm/mgag200/mgag200_drv.h
+++ b/drivers/gpu/drm/mgag200/mgag200_drv.h
@@ -129,7 +129,6 @@
 #define MGAG200_MAX_FB_WIDTH 4096
 
 struct mga_device;
-struct mgag200_pll;
 
 /*
  * Stores parameters for programming the PLLs
@@ -148,17 +147,6 @@ struct mgag200_pll_values {
 	unsigned int s;
 };
 
-struct mgag200_pll_funcs {
-	int (*compute)(struct mgag200_pll *pll, long clock, struct mgag200_pll_values *pllc);
-	void (*update)(struct mgag200_pll *pll, const struct mgag200_pll_values *pllc);
-};
-
-struct mgag200_pll {
-	struct mga_device *mdev;
-
-	const struct mgag200_pll_funcs *funcs;
-};
-
 struct mgag200_crtc_state {
 	struct drm_crtc_state base;
 
@@ -247,6 +235,20 @@ struct mgag200_device_funcs {
 	 * a new display mode.
 	 */
 	void (*enable_vidrst)(struct mga_device *mdev);
+
+	/*
+	 * Validate that the given state can be programmed into PIXPLLC. On
+	 * success, the calculated parameters should be stored in the CRTC's
+	 * state in struct @mgag200_crtc_state.pixpllc.
+	 */
+	int (*pixpllc_atomic_check)(struct drm_crtc *crtc, struct drm_atomic_state *state);
+
+	/*
+	 * Program PIXPLLC from the CRTC state. The parameters should have been
+	 * stored in struct @mgag200_crtc_state.pixpllc by the corresponding
+	 * implementation of @pixpllc_atomic_check.
+	 */
+	void (*pixpllc_atomic_update)(struct drm_crtc *crtc, struct drm_atomic_state *old_state);
 };
 
 struct mga_device {
@@ -265,7 +267,6 @@ struct mga_device {
 
 	enum mga_type			type;
 
-	struct mgag200_pll pixpll;
 	struct drm_plane primary_plane;
 	struct drm_crtc crtc;
 	struct drm_encoder encoder;
@@ -319,11 +320,13 @@ struct mga_device *mgag200_g200_device_create(struct pci_dev *pdev, const struct
 struct mga_device *mgag200_g200se_device_create(struct pci_dev *pdev, const struct drm_driver *drv,
 						enum mga_type type);
 void mgag200_g200wb_init_registers(struct mga_device *mdev);
+void mgag200_g200wb_pixpllc_atomic_update(struct drm_crtc *crtc, struct drm_atomic_state *state);
 struct mga_device *mgag200_g200wb_device_create(struct pci_dev *pdev, const struct drm_driver *drv,
 						enum mga_type type);
 struct mga_device *mgag200_g200ev_device_create(struct pci_dev *pdev, const struct drm_driver *drv,
 						enum mga_type type);
 void mgag200_g200eh_init_registers(struct mga_device *mdev);
+void mgag200_g200eh_pixpllc_atomic_update(struct drm_crtc *crtc, struct drm_atomic_state *state);
 struct mga_device *mgag200_g200eh_device_create(struct pci_dev *pdev, const struct drm_driver *drv,
 						enum mga_type type);
 struct mga_device *mgag200_g200eh3_device_create(struct pci_dev *pdev, const struct drm_driver *drv,
@@ -345,7 +348,4 @@ void mgag200_bmc_enable_vidrst(struct mga_device *mdev);
 				/* mgag200_i2c.c */
 int mgag200_i2c_init(struct mga_device *mdev, struct mga_i2c_chan *i2c);
 
-				/* mgag200_pll.c */
-int mgag200_pixpll_init(struct mgag200_pll *pixpll, struct mga_device *mdev);
-
 #endif				/* __MGAG200_DRV_H__ */
diff --git a/drivers/gpu/drm/mgag200/mgag200_g200.c b/drivers/gpu/drm/mgag200/mgag200_g200.c
index 5de77ef637f7..1f7dde2d7547 100644
--- a/drivers/gpu/drm/mgag200/mgag200_g200.c
+++ b/drivers/gpu/drm/mgag200/mgag200_g200.c
@@ -3,6 +3,7 @@
 #include <linux/pci.h>
 #include <linux/vmalloc.h>
 
+#include <drm/drm_atomic.h>
 #include <drm/drm_drv.h>
 
 #include "mgag200_drv.h"
@@ -65,6 +66,112 @@ static void mgag200_g200_init_registers(struct mgag200_g200_device *g200)
 	mgag200_init_registers(mdev);
 }
 
+/*
+ * PIXPLLC
+ */
+
+static int mgag200_g200_pixpllc_atomic_check(struct drm_crtc *crtc, struct drm_atomic_state *state)
+{
+	static const int post_div_max = 7;
+	static const int in_div_min = 1;
+	static const int in_div_max = 6;
+	static const int feed_div_min = 7;
+	static const int feed_div_max = 127;
+
+	struct drm_device *dev = crtc->dev;
+	struct mgag200_g200_device *g200 = to_mgag200_g200_device(dev);
+	struct drm_crtc_state *new_crtc_state = drm_atomic_get_new_crtc_state(state, crtc);
+	struct mgag200_crtc_state *new_mgag200_crtc_state = to_mgag200_crtc_state(new_crtc_state);
+	long clock = new_crtc_state->mode.clock;
+	struct mgag200_pll_values *pixpllc = &new_mgag200_crtc_state->pixpllc;
+	u8 testp, testm, testn;
+	u8 n = 0, m = 0, p, s;
+	long f_vco;
+	long computed;
+	long delta, tmp_delta;
+	long ref_clk = g200->ref_clk;
+	long p_clk_min = g200->pclk_min;
+	long p_clk_max = g200->pclk_max;
+
+	if (clock > p_clk_max) {
+		drm_err(dev, "Pixel Clock %ld too high\n", clock);
+		return -EINVAL;
+	}
+
+	if (clock < p_clk_min >> 3)
+		clock = p_clk_min >> 3;
+
+	f_vco = clock;
+	for (testp = 0;
+	     testp <= post_div_max && f_vco < p_clk_min;
+	     testp = (testp << 1) + 1, f_vco <<= 1)
+		;
+	p = testp + 1;
+
+	delta = clock;
+
+	for (testm = in_div_min; testm <= in_div_max; testm++) {
+		for (testn = feed_div_min; testn <= feed_div_max; testn++) {
+			computed = ref_clk * (testn + 1) / (testm + 1);
+			if (computed < f_vco)
+				tmp_delta = f_vco - computed;
+			else
+				tmp_delta = computed - f_vco;
+			if (tmp_delta < delta) {
+				delta = tmp_delta;
+				m = testm + 1;
+				n = testn + 1;
+			}
+		}
+	}
+	f_vco = ref_clk * n / m;
+	if (f_vco < 100000)
+		s = 0;
+	else if (f_vco < 140000)
+		s = 1;
+	else if (f_vco < 180000)
+		s = 2;
+	else
+		s = 3;
+
+	drm_dbg_kms(dev, "clock: %ld vco: %ld m: %d n: %d p: %d s: %d\n",
+		    clock, f_vco, m, n, p, s);
+
+	pixpllc->m = m;
+	pixpllc->n = n;
+	pixpllc->p = p;
+	pixpllc->s = s;
+
+	return 0;
+}
+
+static void mgag200_g200_pixpllc_atomic_update(struct drm_crtc *crtc,
+					       struct drm_atomic_state *old_state)
+{
+	struct drm_device *dev = crtc->dev;
+	struct mga_device *mdev = to_mga_device(dev);
+	struct drm_crtc_state *crtc_state = crtc->state;
+	struct mgag200_crtc_state *mgag200_crtc_state = to_mgag200_crtc_state(crtc_state);
+	struct mgag200_pll_values *pixpllc = &mgag200_crtc_state->pixpllc;
+	unsigned int pixpllcm, pixpllcn, pixpllcp, pixpllcs;
+	u8 xpixpllcm, xpixpllcn, xpixpllcp;
+
+	pixpllcm = pixpllc->m - 1;
+	pixpllcn = pixpllc->n - 1;
+	pixpllcp = pixpllc->p - 1;
+	pixpllcs = pixpllc->s;
+
+	xpixpllcm = pixpllcm;
+	xpixpllcn = pixpllcn;
+	xpixpllcp = (pixpllcs << 3) | pixpllcp;
+
+	WREG_MISC_MASKED(MGAREG_MISC_CLKSEL_MGA, MGAREG_MISC_CLKSEL_MASK);
+
+	WREG_DAC(MGA1064_PIX_PLLC_M, xpixpllcm);
+	WREG_DAC(MGA1064_PIX_PLLC_N, xpixpllcn);
+	WREG_DAC(MGA1064_PIX_PLLC_P, xpixpllcp);
+}
+
 /*
  * DRM Device
  */
@@ -196,6 +303,8 @@ static void mgag200_g200_init_refclk(struct mgag200_g200_device *g200)
 }
 
 static const struct mgag200_device_funcs mgag200_g200_device_funcs = {
+	.pixpllc_atomic_check = mgag200_g200_pixpllc_atomic_check,
+	.pixpllc_atomic_update = mgag200_g200_pixpllc_atomic_update,
 };
 
 struct mga_device *mgag200_g200_device_create(struct pci_dev *pdev, const struct drm_driver *drv,
diff --git a/drivers/gpu/drm/mgag200/mgag200_g200eh.c b/drivers/gpu/drm/mgag200/mgag200_g200eh.c
index 6acfc9eeeda9..b59ba115bda3 100644
--- a/drivers/gpu/drm/mgag200/mgag200_g200eh.c
+++ b/drivers/gpu/drm/mgag200/mgag200_g200eh.c
@@ -1,7 +1,9 @@
 // SPDX-License-Identifier: GPL-2.0-only
 
+#include <linux/delay.h>
 #include <linux/pci.h>
 
+#include <drm/drm_atomic.h>
 #include <drm/drm_drv.h>
 
 #include "mgag200_drv.h"
@@ -40,6 +42,133 @@ void mgag200_g200eh_init_registers(struct mga_device *mdev)
 	mgag200_init_registers(mdev);
 }
 
+/*
+ * PIXPLLC
+ */
+
+static int mgag200_g200eh_pixpllc_atomic_check(struct drm_crtc *crtc,
+					       struct drm_atomic_state *state)
+{
+	static const unsigned int vcomax = 800000;
+	static const unsigned int vcomin = 400000;
+	static const unsigned int pllreffreq = 33333;
+
+	struct drm_crtc_state *new_crtc_state = drm_atomic_get_new_crtc_state(state, crtc);
+	struct mgag200_crtc_state *new_mgag200_crtc_state = to_mgag200_crtc_state(new_crtc_state);
+	long clock = new_crtc_state->mode.clock;
+	struct mgag200_pll_values *pixpllc = &new_mgag200_crtc_state->pixpllc;
+	unsigned int delta, tmpdelta;
+	unsigned int testp, testm, testn;
+	unsigned int p, m, n, s;
+	unsigned int computed;
+
+	m = n = p = s = 0;
+	delta = 0xffffffff;
+
+	for (testp = 16; testp > 0; testp >>= 1) {
+		if (clock * testp > vcomax)
+			continue;
+		if (clock * testp < vcomin)
+			continue;
+
+		for (testm = 1; testm < 33; testm++) {
+			for (testn = 17; testn < 257; testn++) {
+				computed = (pllreffreq * testn) / (testm * testp);
+				if (computed > clock)
+					tmpdelta = computed - clock;
+				else
+					tmpdelta = clock - computed;
+				if (tmpdelta < delta) {
+					delta = tmpdelta;
+					n = testn;
+					m = testm;
+					p = testp;
+				}
+			}
+		}
+	}
+
+	pixpllc->m = m;
+	pixpllc->n = n;
+	pixpllc->p = p;
+	pixpllc->s = s;
+
+	return 0;
+}
+
+void mgag200_g200eh_pixpllc_atomic_update(struct drm_crtc *crtc,
+					  struct drm_atomic_state *old_state)
+{
+	struct drm_device *dev = crtc->dev;
+	struct mga_device *mdev = to_mga_device(dev);
+	struct drm_crtc_state *crtc_state = crtc->state;
+	struct mgag200_crtc_state *mgag200_crtc_state = to_mgag200_crtc_state(crtc_state);
+	struct mgag200_pll_values *pixpllc = &mgag200_crtc_state->pixpllc;
+	unsigned int pixpllcm, pixpllcn, pixpllcp, pixpllcs;
+	u8 xpixpllcm, xpixpllcn, xpixpllcp, tmp;
+	int i, j, tmpcount, vcount;
+	bool pll_locked = false;
+
+	pixpllcm = pixpllc->m - 1;
+	pixpllcn = pixpllc->n - 1;
+	pixpllcp = pixpllc->p - 1;
+	pixpllcs = pixpllc->s;
+
+	xpixpllcm = ((pixpllcn & BIT(8)) >> 1) | pixpllcm;
+	xpixpllcn = pixpllcn;
+	xpixpllcp = (pixpllcs << 3) | pixpllcp;
+
+	WREG_MISC_MASKED(MGAREG_MISC_CLKSEL_MGA, MGAREG_MISC_CLKSEL_MASK);
+
+	for (i = 0; i <= 32 && pll_locked == false; i++) {
+		WREG8(DAC_INDEX, MGA1064_PIX_CLK_CTL);
+		tmp = RREG8(DAC_DATA);
+		tmp |= MGA1064_PIX_CLK_CTL_CLK_DIS;
+		WREG8(DAC_DATA, tmp);
+
+		tmp = RREG8(MGAREG_MEM_MISC_READ);
+		tmp |= 0x3 << 2;
+		WREG8(MGAREG_MEM_MISC_WRITE, tmp);
+
+		WREG8(DAC_INDEX, MGA1064_PIX_CLK_CTL);
+		tmp = RREG8(DAC_DATA);
+		tmp |= MGA1064_PIX_CLK_CTL_CLK_POW_DOWN;
+		WREG8(DAC_DATA, tmp);
+
+		udelay(500);
+
+		WREG_DAC(MGA1064_EH_PIX_PLLC_M, xpixpllcm);
+		WREG_DAC(MGA1064_EH_PIX_PLLC_N, xpixpllcn);
+		WREG_DAC(MGA1064_EH_PIX_PLLC_P, xpixpllcp);
+
+		udelay(500);
+
+		WREG8(DAC_INDEX, MGA1064_PIX_CLK_CTL);
+		tmp = RREG8(DAC_DATA);
+		tmp &= ~MGA1064_PIX_CLK_CTL_SEL_MSK;
+		tmp |= MGA1064_PIX_CLK_CTL_SEL_PLL;
+		WREG8(DAC_DATA, tmp);
+
+		WREG8(DAC_INDEX, MGA1064_PIX_CLK_CTL);
+		tmp = RREG8(DAC_DATA);
+		tmp &= ~MGA1064_PIX_CLK_CTL_CLK_DIS;
+		tmp &= ~MGA1064_PIX_CLK_CTL_CLK_POW_DOWN;
+		WREG8(DAC_DATA, tmp);
+
+		vcount = RREG8(MGAREG_VCOUNT);
+
+		for (j = 0; j < 30 && pll_locked == false; j++) {
+			tmpcount = RREG8(MGAREG_VCOUNT);
+			if (tmpcount < vcount)
+				vcount = 0;
+			if ((tmpcount - vcount) > 2)
+				pll_locked = true;
+			else
+				udelay(5);
+		}
+	}
+}
+
 /*
  * DRM device
  */
@@ -48,6 +177,8 @@ static const struct mgag200_device_info mgag200_g200eh_device_info =
 	MGAG200_DEVICE_INFO_INIT(2048, 2048, 37500, false, 1, 0, false);
 
 static const struct mgag200_device_funcs mgag200_g200eh_device_funcs = {
+	.pixpllc_atomic_check = mgag200_g200eh_pixpllc_atomic_check,
+	.pixpllc_atomic_update = mgag200_g200eh_pixpllc_atomic_update,
 };
 
 struct mga_device *mgag200_g200eh_device_create(struct pci_dev *pdev, const struct drm_driver *drv,
diff --git a/drivers/gpu/drm/mgag200/mgag200_g200eh3.c b/drivers/gpu/drm/mgag200/mgag200_g200eh3.c
index 99e00aa848e1..9998197c6446 100644
--- a/drivers/gpu/drm/mgag200/mgag200_g200eh3.c
+++ b/drivers/gpu/drm/mgag200/mgag200_g200eh3.c
@@ -2,10 +2,67 @@
 
 #include <linux/pci.h>
 
+#include <drm/drm_atomic.h>
 #include <drm/drm_drv.h>
 
 #include "mgag200_drv.h"
 
+/*
+ * PIXPLLC
+ */
+
+static int mgag200_g200eh3_pixpllc_atomic_check(struct drm_crtc *crtc,
+						struct drm_atomic_state *state)
+{
+	static const unsigned int vcomax = 3000000;
+	static const unsigned int vcomin = 1500000;
+	static const unsigned int pllreffreq = 25000;
+
+	struct drm_crtc_state *new_crtc_state = drm_atomic_get_new_crtc_state(state, crtc);
+	struct mgag200_crtc_state *new_mgag200_crtc_state = to_mgag200_crtc_state(new_crtc_state);
+	long clock = new_crtc_state->mode.clock;
+	struct mgag200_pll_values *pixpllc = &new_mgag200_crtc_state->pixpllc;
+	unsigned int delta, tmpdelta;
+	unsigned int testp, testm, testn;
+	unsigned int p, m, n, s;
+	unsigned int computed;
+
+	m = n = p = s = 0;
+	delta = 0xffffffff;
+	testp = 0;
+
+	for (testm = 150; testm >= 6; testm--) {
+		if (clock * testm > vcomax)
+			continue;
+		if (clock * testm < vcomin)
+			continue;
+		for (testn = 120; testn >= 60; testn--) {
+			computed = (pllreffreq * testn) / testm;
+			if (computed > clock)
+				tmpdelta = computed - clock;
+			else
+				tmpdelta = clock - computed;
+			if (tmpdelta < delta) {
+				delta = tmpdelta;
+				n = testn + 1;
+				m = testm + 1;
+				p = testp + 1;
+			}
+			if (delta == 0)
+				break;
+		}
+		if (delta == 0)
+			break;
+	}
+
+	pixpllc->m = m;
+	pixpllc->n = n;
+	pixpllc->p = p;
+	pixpllc->s = s;
+
+	return 0;
+}
+
 /*
  * DRM device
  */
@@ -14,6 +71,8 @@ static const struct mgag200_device_info mgag200_g200eh3_device_info =
 	MGAG200_DEVICE_INFO_INIT(2048, 2048, 0, false, 1, 0, false);
 
 static const struct mgag200_device_funcs mgag200_g200eh3_device_funcs = {
+	.pixpllc_atomic_check = mgag200_g200eh3_pixpllc_atomic_check,
+	.pixpllc_atomic_update = mgag200_g200eh_pixpllc_atomic_update, // same as G200EH
 };
 
 struct mga_device *mgag200_g200eh3_device_create(struct pci_dev *pdev,
diff --git a/drivers/gpu/drm/mgag200/mgag200_g200er.c b/drivers/gpu/drm/mgag200/mgag200_g200er.c
index 76eb4776658a..b18fc5862b7c 100644
--- a/drivers/gpu/drm/mgag200/mgag200_g200er.c
+++ b/drivers/gpu/drm/mgag200/mgag200_g200er.c
@@ -1,7 +1,9 @@
 // SPDX-License-Identifier: GPL-2.0-only
 
+#include <linux/delay.h>
 #include <linux/pci.h>
 
+#include <drm/drm_atomic.h>
 #include <drm/drm_drv.h>
 
 #include "mgag200_drv.h"
@@ -40,6 +42,122 @@ static void mgag200_g200er_init_registers(struct mga_device *mdev)
 	WREG_ECRT(0x24, 0x5); /* G200ER specific */
 }
 
+/*
+ * PIXPLLC
+ */
+
+static int mgag200_g200er_pixpllc_atomic_check(struct drm_crtc *crtc,
+					       struct drm_atomic_state *state)
+{
+	static const unsigned int vcomax = 1488000;
+	static const unsigned int vcomin = 1056000;
+	static const unsigned int pllreffreq = 48000;
+	static const unsigned int m_div_val[] = { 1, 2, 4, 8 };
+
+	struct drm_crtc_state *new_crtc_state = drm_atomic_get_new_crtc_state(state, crtc);
+	struct mgag200_crtc_state *new_mgag200_crtc_state = to_mgag200_crtc_state(new_crtc_state);
+	long clock = new_crtc_state->mode.clock;
+	struct mgag200_pll_values *pixpllc = &new_mgag200_crtc_state->pixpllc;
+	unsigned int delta, tmpdelta;
+	int testr, testn, testm, testo;
+	unsigned int p, m, n, s;
+	unsigned int computed, vco;
+
+	m = n = p = s = 0;
+	delta = 0xffffffff;
+
+	for (testr = 0; testr < 4; testr++) {
+		if (delta == 0)
+			break;
+		for (testn = 5; testn < 129; testn++) {
+			if (delta == 0)
+				break;
+			for (testm = 3; testm >= 0; testm--) {
+				if (delta == 0)
+					break;
+				for (testo = 5; testo < 33; testo++) {
+					vco = pllreffreq * (testn + 1) /
+						(testr + 1);
+					if (vco < vcomin)
+						continue;
+					if (vco > vcomax)
+						continue;
+					computed = vco / (m_div_val[testm] * (testo + 1));
+					if (computed > clock)
+						tmpdelta = computed - clock;
+					else
+						tmpdelta = clock - computed;
+					if (tmpdelta < delta) {
+						delta = tmpdelta;
+						m = (testm | (testo << 3)) + 1;
+						n = testn + 1;
+						p = testr + 1;
+						s = testr;
+					}
+				}
+			}
+		}
+	}
+
+	pixpllc->m = m;
+	pixpllc->n = n;
+	pixpllc->p = p;
+	pixpllc->s = s;
+
+	return 0;
+}
+
+static void mgag200_g200er_pixpllc_atomic_update(struct drm_crtc *crtc,
+						 struct drm_atomic_state *old_state)
+{
+	struct drm_device *dev = crtc->dev;
+	struct mga_device *mdev = to_mga_device(dev);
+	struct drm_crtc_state *crtc_state = crtc->state;
+	struct mgag200_crtc_state *mgag200_crtc_state = to_mgag200_crtc_state(crtc_state);
+	struct mgag200_pll_values *pixpllc = &mgag200_crtc_state->pixpllc;
+	unsigned int pixpllcm, pixpllcn, pixpllcp, pixpllcs;
+	u8 xpixpllcm, xpixpllcn, xpixpllcp, tmp;
+
+	pixpllcm = pixpllc->m - 1;
+	pixpllcn = pixpllc->n - 1;
+	pixpllcp = pixpllc->p - 1;
+	pixpllcs = pixpllc->s;
+
+	xpixpllcm = pixpllcm;
+	xpixpllcn = pixpllcn;
+	xpixpllcp = (pixpllcs << 3) | pixpllcp;
+
+	WREG_MISC_MASKED(MGAREG_MISC_CLKSEL_MGA, MGAREG_MISC_CLKSEL_MASK);
+
+	WREG8(DAC_INDEX, MGA1064_PIX_CLK_CTL);
+	tmp = RREG8(DAC_DATA);
+	tmp |= MGA1064_PIX_CLK_CTL_CLK_DIS;
+	WREG8(DAC_DATA, tmp);
+
+	WREG8(DAC_INDEX, MGA1064_REMHEADCTL);
+	tmp = RREG8(DAC_DATA);
+	tmp |= MGA1064_REMHEADCTL_CLKDIS;
+	WREG8(DAC_DATA, tmp);
+
+	tmp = RREG8(MGAREG_MEM_MISC_READ);
+	tmp |= (0x3<<2) | 0xc0;
+	WREG8(MGAREG_MEM_MISC_WRITE, tmp);
+
+	WREG8(DAC_INDEX, MGA1064_PIX_CLK_CTL);
+	tmp = RREG8(DAC_DATA);
+	tmp &= ~MGA1064_PIX_CLK_CTL_CLK_DIS;
+	tmp |= MGA1064_PIX_CLK_CTL_CLK_POW_DOWN;
+	WREG8(DAC_DATA, tmp);
+
+	udelay(500);
+
+	WREG_DAC(MGA1064_ER_PIX_PLLC_N, xpixpllcn);
+	WREG_DAC(MGA1064_ER_PIX_PLLC_M, xpixpllcm);
+	WREG_DAC(MGA1064_ER_PIX_PLLC_P, xpixpllcp);
+
+	udelay(50);
+}
+
 /*
  * DRM device
  */
@@ -48,6 +166,8 @@ static const struct mgag200_device_info mgag200_g200er_device_info =
 	MGAG200_DEVICE_INFO_INIT(2048, 2048, 55000, false, 1, 0, false);
 
 static const struct mgag200_device_funcs mgag200_g200er_device_funcs = {
+	.pixpllc_atomic_check = mgag200_g200er_pixpllc_atomic_check,
+	.pixpllc_atomic_update = mgag200_g200er_pixpllc_atomic_update,
 };
 
 struct mga_device *mgag200_g200er_device_create(struct pci_dev *pdev, const struct drm_driver *drv,
diff --git a/drivers/gpu/drm/mgag200/mgag200_g200ev.c b/drivers/gpu/drm/mgag200/mgag200_g200ev.c
index e9ea09195471..95681796ccd6 100644
--- a/drivers/gpu/drm/mgag200/mgag200_g200ev.c
+++ b/drivers/gpu/drm/mgag200/mgag200_g200ev.c
@@ -1,7 +1,9 @@
 // SPDX-License-Identifier: GPL-2.0-only
 
+#include <linux/delay.h>
 #include <linux/pci.h>
 
+#include <drm/drm_atomic.h>
 #include <drm/drm_drv.h>
 
 #include "mgag200_drv.h"
@@ -44,6 +46,134 @@ static void mgag200_g200ev_init_registers(struct mga_device *mdev)
 	mgag200_init_registers(mdev);
 }
 
+/*
+ * PIXPLLC
+ */
+
+static int mgag200_g200ev_pixpllc_atomic_check(struct drm_crtc *crtc,
+					       struct drm_atomic_state *state)
+{
+	static const unsigned int vcomax = 550000;
+	static const unsigned int vcomin = 150000;
+	static const unsigned int pllreffreq = 50000;
+
+	struct drm_crtc_state *new_crtc_state = drm_atomic_get_new_crtc_state(state, crtc);
+	struct mgag200_crtc_state *new_mgag200_crtc_state = to_mgag200_crtc_state(new_crtc_state);
+	long clock = new_crtc_state->mode.clock;
+	struct mgag200_pll_values *pixpllc = &new_mgag200_crtc_state->pixpllc;
+	unsigned int delta, tmpdelta;
+	unsigned int testp, testm, testn;
+	unsigned int p, m, n, s;
+	unsigned int computed;
+
+	m = n = p = s = 0;
+	delta = 0xffffffff;
+
+	for (testp = 16; testp > 0; testp--) {
+		if (clock * testp > vcomax)
+			continue;
+		if (clock * testp < vcomin)
+			continue;
+
+		for (testn = 1; testn < 257; testn++) {
+			for (testm = 1; testm < 17; testm++) {
+				computed = (pllreffreq * testn) /
+					(testm * testp);
+				if (computed > clock)
+					tmpdelta = computed - clock;
+				else
+					tmpdelta = clock - computed;
+				if (tmpdelta < delta) {
+					delta = tmpdelta;
+					n = testn;
+					m = testm;
+					p = testp;
+				}
+			}
+		}
+	}
+
+	pixpllc->m = m;
+	pixpllc->n = n;
+	pixpllc->p = p;
+	pixpllc->s = s;
+
+	return 0;
+}
+
+static void mgag200_g200ev_pixpllc_atomic_update(struct drm_crtc *crtc,
+						 struct drm_atomic_state *old_state)
+{
+	struct drm_device *dev = crtc->dev;
+	struct mga_device *mdev = to_mga_device(dev);
+	struct drm_crtc_state *crtc_state = crtc->state;
+	struct mgag200_crtc_state *mgag200_crtc_state = to_mgag200_crtc_state(crtc_state);
+	struct mgag200_pll_values *pixpllc = &mgag200_crtc_state->pixpllc;
+	unsigned int pixpllcm, pixpllcn, pixpllcp, pixpllcs;
+	u8 xpixpllcm, xpixpllcn, xpixpllcp, tmp;
+
+	pixpllcm = pixpllc->m - 1;
+	pixpllcn = pixpllc->n - 1;
+	pixpllcp = pixpllc->p - 1;
+	pixpllcs = pixpllc->s;
+
+	xpixpllcm = pixpllcm;
+	xpixpllcn = pixpllcn;
+	xpixpllcp = (pixpllcs << 3) | pixpllcp;
+
+	WREG_MISC_MASKED(MGAREG_MISC_CLKSEL_MGA, MGAREG_MISC_CLKSEL_MASK);
+
+	WREG8(DAC_INDEX, MGA1064_PIX_CLK_CTL);
+	tmp = RREG8(DAC_DATA);
+	tmp |= MGA1064_PIX_CLK_CTL_CLK_DIS;
+	WREG8(DAC_DATA, tmp);
+
+	tmp = RREG8(MGAREG_MEM_MISC_READ);
+	tmp |= 0x3 << 2;
+	WREG8(MGAREG_MEM_MISC_WRITE, tmp);
+
+	WREG8(DAC_INDEX, MGA1064_PIX_PLL_STAT);
+	tmp = RREG8(DAC_DATA);
+	WREG8(DAC_DATA, tmp & ~0x40);
+
+	WREG8(DAC_INDEX, MGA1064_PIX_CLK_CTL);
+	tmp = RREG8(DAC_DATA);
+	tmp |= MGA1064_PIX_CLK_CTL_CLK_POW_DOWN;
+	WREG8(DAC_DATA, tmp);
+
+	WREG_DAC(MGA1064_EV_PIX_PLLC_M, xpixpllcm);
+	WREG_DAC(MGA1064_EV_PIX_PLLC_N, xpixpllcn);
+	WREG_DAC(MGA1064_EV_PIX_PLLC_P, xpixpllcp);
+
+	udelay(50);
+
+	WREG8(DAC_INDEX, MGA1064_PIX_CLK_CTL);
+	tmp = RREG8(DAC_DATA);
+	tmp &= ~MGA1064_PIX_CLK_CTL_CLK_POW_DOWN;
+	WREG8(DAC_DATA, tmp);
+
+	udelay(500);
+
+	WREG8(DAC_INDEX, MGA1064_PIX_CLK_CTL);
+	tmp = RREG8(DAC_DATA);
+	tmp &= ~MGA1064_PIX_CLK_CTL_SEL_MSK;
+	tmp |= MGA1064_PIX_CLK_CTL_SEL_PLL;
+	WREG8(DAC_DATA, tmp);
+
+	WREG8(DAC_INDEX, MGA1064_PIX_PLL_STAT);
+	tmp = RREG8(DAC_DATA);
+	WREG8(DAC_DATA, tmp | 0x40);
+
+	tmp = RREG8(MGAREG_MEM_MISC_READ);
+	tmp |= (0x3 << 2);
+	WREG8(MGAREG_MEM_MISC_WRITE, tmp);
+
+	WREG8(DAC_INDEX, MGA1064_PIX_CLK_CTL);
+	tmp = RREG8(DAC_DATA);
+	tmp &= ~MGA1064_PIX_CLK_CTL_CLK_DIS;
+	WREG8(DAC_DATA, tmp);
+}
+
 /*
  * DRM device
  */
@@ -52,6 +182,8 @@ static const struct mgag200_device_info mgag200_g200ev_device_info =
 	MGAG200_DEVICE_INFO_INIT(2048, 2048, 32700, false, 0, 1, false);
 
 static const struct mgag200_device_funcs mgag200_g200ev_device_funcs = {
+	.pixpllc_atomic_check = mgag200_g200ev_pixpllc_atomic_check,
+	.pixpllc_atomic_update = mgag200_g200ev_pixpllc_atomic_update,
 };
 
 struct mga_device *mgag200_g200ev_device_create(struct pci_dev *pdev, const struct drm_driver *drv,
diff --git a/drivers/gpu/drm/mgag200/mgag200_g200ew3.c b/drivers/gpu/drm/mgag200/mgag200_g200ew3.c
index 19a870120ebc..a7f5e8fe56d0 100644
--- a/drivers/gpu/drm/mgag200/mgag200_g200ew3.c
+++ b/drivers/gpu/drm/mgag200/mgag200_g200ew3.c
@@ -2,6 +2,7 @@
 
 #include <linux/pci.h>
 
+#include <drm/drm_atomic.h>
 #include <drm/drm_drv.h>
 
 #include "mgag200_drv.h"
@@ -13,6 +14,64 @@ static void mgag200_g200ew3_init_registers(struct mga_device *mdev)
 	WREG_ECRT(0x34, 0x5); // G200EW3 specific
 }
 
+/*
+ * PIXPLLC
+ */
+
+static int mgag200_g200ew3_pixpllc_atomic_check(struct drm_crtc *crtc,
+						struct drm_atomic_state *state)
+{
+	static const unsigned int vcomax = 800000;
+	static const unsigned int vcomin = 400000;
+	static const unsigned int pllreffreq = 25000;
+
+	struct drm_crtc_state *new_crtc_state = drm_atomic_get_new_crtc_state(state, crtc);
+	struct mgag200_crtc_state *new_mgag200_crtc_state = to_mgag200_crtc_state(new_crtc_state);
+	long clock = new_crtc_state->mode.clock;
+	struct mgag200_pll_values *pixpllc = &new_mgag200_crtc_state->pixpllc;
+	unsigned int delta, tmpdelta;
+	unsigned int testp, testm, testn, testp2;
+	unsigned int p, m, n, s;
+	unsigned int computed;
+
+	m = n = p = s = 0;
+	delta = 0xffffffff;
+
+	for (testp = 1; testp < 8; testp++) {
+		for (testp2 = 1; testp2 < 8; testp2++) {
+			if (testp < testp2)
+				continue;
+			if ((clock * testp * testp2) > vcomax)
+				continue;
+			if ((clock * testp * testp2) < vcomin)
+				continue;
+			for (testm = 1; testm < 26; testm++) {
+				for (testn = 32; testn < 2048 ; testn++) {
+					computed = (pllreffreq * testn) / (testm * testp * testp2);
+					if (computed > clock)
+						tmpdelta = computed - clock;
+					else
+						tmpdelta = clock - computed;
+					if (tmpdelta < delta) {
+						delta = tmpdelta;
+						m = testm + 1;
+						n = testn + 1;
+						p = testp + 1;
+						s = testp2;
+					}
+				}
+			}
+		}
+	}
+
+	pixpllc->m = m;
+	pixpllc->n = n;
+	pixpllc->p = p;
+	pixpllc->s = s;
+
+	return 0;
+}
+
 /*
  * DRM device
  */
@@ -23,6 +82,8 @@ static const struct mgag200_device_info mgag200_g200ew3_device_info =
 static const struct mgag200_device_funcs mgag200_g200ew3_device_funcs = {
 	.disable_vidrst = mgag200_bmc_disable_vidrst,
 	.enable_vidrst = mgag200_bmc_enable_vidrst,
+	.pixpllc_atomic_check = mgag200_g200ew3_pixpllc_atomic_check,
+	.pixpllc_atomic_update = mgag200_g200wb_pixpllc_atomic_update, // same as G200WB
 };
 
 static resource_size_t mgag200_g200ew3_device_probe_vram(struct mga_device *mdev)
diff --git a/drivers/gpu/drm/mgag200/mgag200_g200se.c b/drivers/gpu/drm/mgag200/mgag200_g200se.c
index 5bdc20db3810..04637b42af77 100644
--- a/drivers/gpu/drm/mgag200/mgag200_g200se.c
+++ b/drivers/gpu/drm/mgag200/mgag200_g200se.c
@@ -1,7 +1,9 @@
 // SPDX-License-Identifier: GPL-2.0-only
 
+#include <linux/delay.h>
 #include <linux/pci.h>
 
+#include <drm/drm_atomic.h>
 #include <drm/drm_drv.h>
 
 #include "mgag200_drv.h"
@@ -71,6 +73,198 @@ static void mgag200_g200se_init_registers(struct mgag200_g200se_device *g200se)
 	mgag200_init_registers(mdev);
 }
 
+/*
+ * PIXPLLC
+ */
+
+static int mgag200_g200se_00_pixpllc_atomic_check(struct drm_crtc *crtc,
+						  struct drm_atomic_state *state)
+{
+	static const unsigned int vcomax = 320000;
+	static const unsigned int vcomin = 160000;
+	static const unsigned int pllreffreq = 25000;
+
+	struct drm_crtc_state *new_crtc_state = drm_atomic_get_new_crtc_state(state, crtc);
+	struct mgag200_crtc_state *new_mgag200_crtc_state = to_mgag200_crtc_state(new_crtc_state);
+	long clock = new_crtc_state->mode.clock;
+	struct mgag200_pll_values *pixpllc = &new_mgag200_crtc_state->pixpllc;
+	unsigned int delta, tmpdelta, permitteddelta;
+	unsigned int testp, testm, testn;
+	unsigned int p, m, n, s;
+	unsigned int computed;
+
+	m = n = p = s = 0;
+	delta = 0xffffffff;
+	permitteddelta = clock * 5 / 1000;
+
+	for (testp = 8; testp > 0; testp /= 2) {
+		if (clock * testp > vcomax)
+			continue;
+		if (clock * testp < vcomin)
+			continue;
+
+		for (testn = 17; testn < 256; testn++) {
+			for (testm = 1; testm < 32; testm++) {
+				computed = (pllreffreq * testn) / (testm * testp);
+				if (computed > clock)
+					tmpdelta = computed - clock;
+				else
+					tmpdelta = clock - computed;
+				if (tmpdelta < delta) {
+					delta = tmpdelta;
+					m = testm;
+					n = testn;
+					p = testp;
+				}
+			}
+		}
+	}
+
+	if (delta > permitteddelta) {
+		pr_warn("PLL delta too large\n");
+		return -EINVAL;
+	}
+
+	pixpllc->m = m;
+	pixpllc->n = n;
+	pixpllc->p = p;
+	pixpllc->s = s;
+
+	return 0;
+}
+
+static void mgag200_g200se_00_pixpllc_atomic_update(struct drm_crtc *crtc,
+						    struct drm_atomic_state *old_state)
+{
+	struct drm_device *dev = crtc->dev;
+	struct mga_device *mdev = to_mga_device(dev);
+	struct drm_crtc_state *crtc_state = crtc->state;
+	struct mgag200_crtc_state *mgag200_crtc_state = to_mgag200_crtc_state(crtc_state);
+	struct mgag200_pll_values *pixpllc = &mgag200_crtc_state->pixpllc;
+	unsigned int pixpllcm, pixpllcn, pixpllcp, pixpllcs;
+	u8 xpixpllcm, xpixpllcn, xpixpllcp;
+
+	pixpllcm = pixpllc->m - 1;
+	pixpllcn = pixpllc->n - 1;
+	pixpllcp = pixpllc->p - 1;
+	pixpllcs = pixpllc->s;
+
+	xpixpllcm = pixpllcm | ((pixpllcn & BIT(8)) >> 1);
+	xpixpllcn = pixpllcn;
+	xpixpllcp = (pixpllcs << 3) | pixpllcp;
+
+	WREG_MISC_MASKED(MGAREG_MISC_CLKSEL_MGA, MGAREG_MISC_CLKSEL_MASK);
+
+	WREG_DAC(MGA1064_PIX_PLLC_M, xpixpllcm);
+	WREG_DAC(MGA1064_PIX_PLLC_N, xpixpllcn);
+	WREG_DAC(MGA1064_PIX_PLLC_P, xpixpllcp);
+}
+
+static int mgag200_g200se_04_pixpllc_atomic_check(struct drm_crtc *crtc,
+						  struct drm_atomic_state *state)
+{
+	static const unsigned int vcomax = 1600000;
+	static const unsigned int vcomin = 800000;
+	static const unsigned int pllreffreq = 25000;
+	static const unsigned int pvalues_e4[] = {16, 14, 12, 10, 8, 6, 4, 2, 1};
+
+	struct drm_crtc_state *new_crtc_state = drm_atomic_get_new_crtc_state(state, crtc);
+	struct mgag200_crtc_state *new_mgag200_crtc_state = to_mgag200_crtc_state(new_crtc_state);
+	long clock = new_crtc_state->mode.clock;
+	struct mgag200_pll_values *pixpllc = &new_mgag200_crtc_state->pixpllc;
+	unsigned int delta, tmpdelta, permitteddelta;
+	unsigned int testp, testm, testn;
+	unsigned int p, m, n, s;
+	unsigned int computed;
+	unsigned int fvv;
+	unsigned int i;
+
+	m = n = p = s = 0;
+	delta = 0xffffffff;
+
+	if (clock < 25000)
+		clock = 25000;
+	clock = clock * 2;
+
+	/* Permited delta is 0.5% as VESA Specification */
+	permitteddelta = clock * 5 / 1000;
+
+	for (i = 0 ; i < ARRAY_SIZE(pvalues_e4); i++) {
+		testp = pvalues_e4[i];
+
+		if ((clock * testp) > vcomax)
+			continue;
+		if ((clock * testp) < vcomin)
+			continue;
+
+		for (testn = 50; testn <= 256; testn++) {
+			for (testm = 1; testm <= 32; testm++) {
+				computed = (pllreffreq * testn) / (testm * testp);
+				if (computed > clock)
+					tmpdelta = computed - clock;
+				else
+					tmpdelta = clock - computed;
+
+				if (tmpdelta < delta) {
+					delta = tmpdelta;
+					m = testm;
+					n = testn;
+					p = testp;
+				}
+			}
+		}
+	}
+
+	fvv = pllreffreq * n / m;
+	fvv = (fvv - 800000) / 50000;
+	if (fvv > 15)
+		fvv = 15;
+	s = fvv << 1;
+
+	if (delta > permitteddelta) {
+		pr_warn("PLL delta too large\n");
+		return -EINVAL;
+	}
+
+	pixpllc->m = m;
+	pixpllc->n = n;
+	pixpllc->p = p;
+	pixpllc->s = s;
+
+	return 0;
+}
+
+static void mgag200_g200se_04_pixpllc_atomic_update(struct drm_crtc *crtc,
+						    struct drm_atomic_state *old_state)
+{
+	struct drm_device *dev = crtc->dev;
+	struct mga_device *mdev = to_mga_device(dev);
+	struct drm_crtc_state *crtc_state = crtc->state;
+	struct mgag200_crtc_state *mgag200_crtc_state = to_mgag200_crtc_state(crtc_state);
+	struct mgag200_pll_values *pixpllc = &mgag200_crtc_state->pixpllc;
+	unsigned int pixpllcm, pixpllcn, pixpllcp, pixpllcs;
+	u8 xpixpllcm, xpixpllcn, xpixpllcp;
+
+	pixpllcm = pixpllc->m - 1;
+	pixpllcn = pixpllc->n - 1;
+	pixpllcp = pixpllc->p - 1;
+	pixpllcs = pixpllc->s;
+
+	xpixpllcm = pixpllcm | ((pixpllcn & BIT(8)) >> 1);
+	xpixpllcn = pixpllcn;
+	xpixpllcp = (pixpllcs << 3) | pixpllcp;
+
+	WREG_MISC_MASKED(MGAREG_MISC_CLKSEL_MGA, MGAREG_MISC_CLKSEL_MASK);
+
+	WREG_DAC(MGA1064_PIX_PLLC_M, xpixpllcm);
+	WREG_DAC(MGA1064_PIX_PLLC_N, xpixpllcn);
+	WREG_DAC(MGA1064_PIX_PLLC_P, xpixpllcp);
+
+	WREG_DAC(0x1a, 0x09);
+	msleep(20);
+	WREG_DAC(0x1a, 0x01);
+}
+
 /*
  * DRM device
  */
@@ -108,7 +302,14 @@ static int mgag200_g200se_init_unique_rev_id(struct mgag200_g200se_device *g200s
 	return 0;
 }
 
-static const struct mgag200_device_funcs mgag200_g200se_device_funcs = {
+static const struct mgag200_device_funcs mgag200_g200se_00_device_funcs = {
+	.pixpllc_atomic_check = mgag200_g200se_00_pixpllc_atomic_check,
+	.pixpllc_atomic_update = mgag200_g200se_00_pixpllc_atomic_update,
+};
+
+static const struct mgag200_device_funcs mgag200_g200se_04_device_funcs = {
+	.pixpllc_atomic_check = mgag200_g200se_04_pixpllc_atomic_check,
+	.pixpllc_atomic_update = mgag200_g200se_04_pixpllc_atomic_update,
 };
 
 struct mga_device *mgag200_g200se_device_create(struct pci_dev *pdev, const struct drm_driver *drv,
@@ -116,6 +317,7 @@ struct mga_device *mgag200_g200se_device_create(struct pci_dev *pdev, const stru
 {
 	struct mgag200_g200se_device *g200se;
 	const struct mgag200_device_info *info;
+	const struct mgag200_device_funcs *funcs;
 	struct mga_device *mdev;
 	struct drm_device *dev;
 	resource_size_t vram_available;
@@ -162,7 +364,12 @@ struct mga_device *mgag200_g200se_device_create(struct pci_dev *pdev, const stru
 		return ERR_PTR(-EINVAL);
 	}
 
-	ret = mgag200_device_init(mdev, type, info, &mgag200_g200se_device_funcs);
+	if (g200se->unique_rev_id >= 0x04)
+		funcs = &mgag200_g200se_04_device_funcs;
+	else
+		funcs = &mgag200_g200se_00_device_funcs;
+
+	ret = mgag200_device_init(mdev, type, info, funcs);
 	if (ret)
 		return ERR_PTR(ret);
 
diff --git a/drivers/gpu/drm/mgag200/mgag200_g200wb.c b/drivers/gpu/drm/mgag200/mgag200_g200wb.c
index 92e174d63752..f71b786079fc 100644
--- a/drivers/gpu/drm/mgag200/mgag200_g200wb.c
+++ b/drivers/gpu/drm/mgag200/mgag200_g200wb.c
@@ -1,7 +1,9 @@
 // SPDX-License-Identifier: GPL-2.0-only
 
+#include <linux/delay.h>
 #include <linux/pci.h>
 
+#include <drm/drm_atomic.h>
 #include <drm/drm_drv.h>
 
 #include "mgag200_drv.h"
@@ -38,6 +40,182 @@ void mgag200_g200wb_init_registers(struct mga_device *mdev)
 	mgag200_init_registers(mdev);
 }
 
+/*
+ * PIXPLLC
+ */
+
+static int mgag200_g200wb_pixpllc_atomic_check(struct drm_crtc *crtc,
+					       struct drm_atomic_state *state)
+{
+	static const unsigned int vcomax = 550000;
+	static const unsigned int vcomin = 150000;
+	static const unsigned int pllreffreq = 48000;
+
+	struct drm_crtc_state *new_crtc_state = drm_atomic_get_new_crtc_state(state, crtc);
+	struct mgag200_crtc_state *new_mgag200_crtc_state = to_mgag200_crtc_state(new_crtc_state);
+	long clock = new_crtc_state->mode.clock;
+	struct mgag200_pll_values *pixpllc = &new_mgag200_crtc_state->pixpllc;
+	unsigned int delta, tmpdelta;
+	unsigned int testp, testm, testn;
+	unsigned int p, m, n, s;
+	unsigned int computed;
+
+	m = n = p = s = 0;
+	delta = 0xffffffff;
+
+	for (testp = 1; testp < 9; testp++) {
+		if (clock * testp > vcomax)
+			continue;
+		if (clock * testp < vcomin)
+			continue;
+
+		for (testm = 1; testm < 17; testm++) {
+			for (testn = 1; testn < 151; testn++) {
+				computed = (pllreffreq * testn) / (testm * testp);
+				if (computed > clock)
+					tmpdelta = computed - clock;
+				else
+					tmpdelta = clock - computed;
+				if (tmpdelta < delta) {
+					delta = tmpdelta;
+					n = testn;
+					m = testm;
+					p = testp;
+					s = 0;
+				}
+			}
+		}
+	}
+
+	pixpllc->m = m;
+	pixpllc->n = n;
+	pixpllc->p = p;
+	pixpllc->s = s;
+
+	return 0;
+}
+
+void mgag200_g200wb_pixpllc_atomic_update(struct drm_crtc *crtc,
+					  struct drm_atomic_state *old_state)
+{
+	struct drm_device *dev = crtc->dev;
+	struct mga_device *mdev = to_mga_device(dev);
+	struct drm_crtc_state *crtc_state = crtc->state;
+	struct mgag200_crtc_state *mgag200_crtc_state = to_mgag200_crtc_state(crtc_state);
+	struct mgag200_pll_values *pixpllc = &mgag200_crtc_state->pixpllc;
+	bool pll_locked = false;
+	unsigned int pixpllcm, pixpllcn, pixpllcp, pixpllcs;
+	u8 xpixpllcm, xpixpllcn, xpixpllcp, tmp;
+	int i, j, tmpcount, vcount;
+
+	pixpllcm = pixpllc->m - 1;
+	pixpllcn = pixpllc->n - 1;
+	pixpllcp = pixpllc->p - 1;
+	pixpllcs = pixpllc->s;
+
+	xpixpllcm = ((pixpllcn & BIT(8)) >> 1) | pixpllcm;
+	xpixpllcn = pixpllcn;
+	xpixpllcp = ((pixpllcn & GENMASK(10, 9)) >> 3) | (pixpllcs << 3) | pixpllcp;
+
+	WREG_MISC_MASKED(MGAREG_MISC_CLKSEL_MGA, MGAREG_MISC_CLKSEL_MASK);
+
+	for (i = 0; i <= 32 && pll_locked == false; i++) {
+		if (i > 0) {
+			WREG8(MGAREG_CRTC_INDEX, 0x1e);
+			tmp = RREG8(MGAREG_CRTC_DATA);
+			if (tmp < 0xff)
+				WREG8(MGAREG_CRTC_DATA, tmp+1);
+		}
+
+		/* set pixclkdis to 1 */
+		WREG8(DAC_INDEX, MGA1064_PIX_CLK_CTL);
+		tmp = RREG8(DAC_DATA);
+		tmp |= MGA1064_PIX_CLK_CTL_CLK_DIS;
+		WREG8(DAC_DATA, tmp);
+
+		WREG8(DAC_INDEX, MGA1064_REMHEADCTL);
+		tmp = RREG8(DAC_DATA);
+		tmp |= MGA1064_REMHEADCTL_CLKDIS;
+		WREG8(DAC_DATA, tmp);
+
+		/* select PLL Set C */
+		tmp = RREG8(MGAREG_MEM_MISC_READ);
+		tmp |= 0x3 << 2;
+		WREG8(MGAREG_MEM_MISC_WRITE, tmp);
+
+		WREG8(DAC_INDEX, MGA1064_PIX_CLK_CTL);
+		tmp = RREG8(DAC_DATA);
+		tmp |= MGA1064_PIX_CLK_CTL_CLK_POW_DOWN | 0x80;
+		WREG8(DAC_DATA, tmp);
+
+		udelay(500);
+
+		/* reset the PLL */
+		WREG8(DAC_INDEX, MGA1064_VREF_CTL);
+		tmp = RREG8(DAC_DATA);
+		tmp &= ~0x04;
+		WREG8(DAC_DATA, tmp);
+
+		udelay(50);
+
+		/* program pixel pll register */
+		WREG_DAC(MGA1064_WB_PIX_PLLC_N, xpixpllcn);
+		WREG_DAC(MGA1064_WB_PIX_PLLC_M, xpixpllcm);
+		WREG_DAC(MGA1064_WB_PIX_PLLC_P, xpixpllcp);
+
+		udelay(50);
+
+		/* turn pll on */
+		WREG8(DAC_INDEX, MGA1064_VREF_CTL);
+		tmp = RREG8(DAC_DATA);
+		tmp |= 0x04;
+		WREG_DAC(MGA1064_VREF_CTL, tmp);
+
+		udelay(500);
+
+		/* select the pixel pll */
+		WREG8(DAC_INDEX, MGA1064_PIX_CLK_CTL);
+		tmp = RREG8(DAC_DATA);
+		tmp &= ~MGA1064_PIX_CLK_CTL_SEL_MSK;
+		tmp |= MGA1064_PIX_CLK_CTL_SEL_PLL;
+		WREG8(DAC_DATA, tmp);
+
+		WREG8(DAC_INDEX, MGA1064_REMHEADCTL);
+		tmp = RREG8(DAC_DATA);
+		tmp &= ~MGA1064_REMHEADCTL_CLKSL_MSK;
+		tmp |= MGA1064_REMHEADCTL_CLKSL_PLL;
+		WREG8(DAC_DATA, tmp);
+
+		/* reset dotclock rate bit */
+		WREG8(MGAREG_SEQ_INDEX, 1);
+		tmp = RREG8(MGAREG_SEQ_DATA);
+		tmp &= ~0x8;
+		WREG8(MGAREG_SEQ_DATA, tmp);
+
+		WREG8(DAC_INDEX, MGA1064_PIX_CLK_CTL);
+		tmp = RREG8(DAC_DATA);
+		tmp &= ~MGA1064_PIX_CLK_CTL_CLK_DIS;
+		WREG8(DAC_DATA, tmp);
+
+		vcount = RREG8(MGAREG_VCOUNT);
+
+		for (j = 0; j < 30 && pll_locked == false; j++) {
+			tmpcount = RREG8(MGAREG_VCOUNT);
+			if (tmpcount < vcount)
+				vcount = 0;
+			if ((tmpcount - vcount) > 2)
+				pll_locked = true;
+			else
+				udelay(5);
+		}
+	}
+
+	WREG8(DAC_INDEX, MGA1064_REMHEADCTL);
+	tmp = RREG8(DAC_DATA);
+	tmp &= ~MGA1064_REMHEADCTL_CLKDIS;
+	WREG_DAC(MGA1064_REMHEADCTL, tmp);
+}
+
 /*
  * DRM device
  */
@@ -48,6 +226,8 @@ static const struct mgag200_device_info mgag200_g200wb_device_info =
 static const struct mgag200_device_funcs mgag200_g200wb_device_funcs = {
 	.disable_vidrst = mgag200_bmc_disable_vidrst,
 	.enable_vidrst = mgag200_bmc_enable_vidrst,
+	.pixpllc_atomic_check = mgag200_g200wb_pixpllc_atomic_check,
+	.pixpllc_atomic_update = mgag200_g200wb_pixpllc_atomic_update,
 };
 
 struct mga_device *mgag200_g200wb_device_create(struct pci_dev *pdev, const struct drm_driver *drv,
diff --git a/drivers/gpu/drm/mgag200/mgag200_mode.c b/drivers/gpu/drm/mgag200/mgag200_mode.c
index 7bcd3f6d891d..e3e40b25caa6 100644
--- a/drivers/gpu/drm/mgag200/mgag200_mode.c
+++ b/drivers/gpu/drm/mgag200/mgag200_mode.c
@@ -661,9 +661,8 @@ static int mgag200_crtc_helper_atomic_check(struct drm_crtc *crtc,
 {
 	struct drm_device *dev = crtc->dev;
 	struct mga_device *mdev = to_mga_device(dev);
+	const struct mgag200_device_funcs *funcs = mdev->funcs;
 	struct drm_crtc_state *new_crtc_state = drm_atomic_get_new_crtc_state(state, crtc);
-	struct mgag200_pll *pixpll = &mdev->pixpll;
-	struct mgag200_crtc_state *mgag200_crtc_state = to_mgag200_crtc_state(new_crtc_state);
 	int ret;
 
 	ret = drm_atomic_helper_check_crtc_state(new_crtc_state, false);
@@ -674,10 +673,11 @@ static int mgag200_crtc_helper_atomic_check(struct drm_crtc *crtc,
 		return 0;
 
 	if (new_crtc_state->mode_changed) {
-		ret = pixpll->funcs->compute(pixpll, new_crtc_state->mode.clock,
-					     &mgag200_crtc_state->pixpllc);
-		if (ret)
-			return ret;
+		if (funcs->pixpllc_atomic_check) {
+			ret = funcs->pixpllc_atomic_check(crtc, state);
+			if (ret)
+				return ret;
+		}
 	}
 
 	if (new_crtc_state->color_mgmt_changed && new_crtc_state->gamma_lut) {
@@ -720,7 +720,6 @@ static void mgag200_crtc_helper_atomic_enable(struct drm_crtc *crtc,
 	struct drm_display_mode *adjusted_mode = &crtc_state->adjusted_mode;
 	struct mgag200_crtc_state *mgag200_crtc_state = to_mgag200_crtc_state(crtc_state);
 	const struct drm_format_info *format = mgag200_crtc_state->format;
-	struct mgag200_pll *pixpll = &mdev->pixpll;
 
 	if (funcs->disable_vidrst)
 		funcs->disable_vidrst(mdev);
@@ -728,7 +727,8 @@ static void mgag200_crtc_helper_atomic_enable(struct drm_crtc *crtc,
 	mgag200_set_format_regs(mdev, format);
 	mgag200_set_mode_regs(mdev, adjusted_mode);
 
-	pixpll->funcs->update(pixpll, &mgag200_crtc_state->pixpllc);
+	if (funcs->pixpllc_atomic_update)
+		funcs->pixpllc_atomic_update(crtc, old_state);
 
 	if (mdev->type == G200_ER)
 		mgag200_g200er_reset_tagfifo(mdev);
@@ -979,10 +979,6 @@ static int mgag200_pipeline_init(struct mga_device *mdev)
 	struct drm_connector *connector = &mdev->connector;
 	int ret;
 
-	ret = mgag200_pixpll_init(&mdev->pixpll, mdev);
-	if (ret)
-		return ret;
-
 	ret = drm_universal_plane_init(dev, primary_plane, 0,
 				       &mgag200_primary_plane_funcs,
 				       mgag200_primary_plane_formats,
diff --git a/drivers/gpu/drm/mgag200/mgag200_pll.c b/drivers/gpu/drm/mgag200/mgag200_pll.c
deleted file mode 100644
index 8065ca5d8de9..000000000000
--- a/drivers/gpu/drm/mgag200/mgag200_pll.c
+++ /dev/null
@@ -1,997 +0,0 @@
-// SPDX-License-Identifier: GPL-2.0-only
-
-#include <linux/delay.h>
-
-#include "mgag200_drv.h"
-
-/*
- * G200
- */
-
-static int mgag200_pixpll_compute_g200(struct mgag200_pll *pixpll, long clock,
-				       struct mgag200_pll_values *pixpllc)
-{
-	struct mga_device *mdev = pixpll->mdev;
-	struct drm_device *dev = &mdev->base;
-	struct mgag200_g200_device *g200 = to_mgag200_g200_device(dev);
-	const int post_div_max = 7;
-	const int in_div_min = 1;
-	const int in_div_max = 6;
-	const int feed_div_min = 7;
-	const int feed_div_max = 127;
-	u8 testp, testm, testn;
-	u8 n = 0, m = 0, p, s;
-	long f_vco;
-	long computed;
-	long delta, tmp_delta;
-	long ref_clk = g200->ref_clk;
-	long p_clk_min = g200->pclk_min;
-	long p_clk_max = g200->pclk_max;
-
-	if (clock > p_clk_max) {
-		drm_err(dev, "Pixel Clock %ld too high\n", clock);
-		return -EINVAL;
-	}
-
-	if (clock < p_clk_min >> 3)
-		clock = p_clk_min >> 3;
-
-	f_vco = clock;
-	for (testp = 0;
-	     testp <= post_div_max && f_vco < p_clk_min;
-	     testp = (testp << 1) + 1, f_vco <<= 1)
-		;
-	p = testp + 1;
-
-	delta = clock;
-
-	for (testm = in_div_min; testm <= in_div_max; testm++) {
-		for (testn = feed_div_min; testn <= feed_div_max; testn++) {
-			computed = ref_clk * (testn + 1) / (testm + 1);
-			if (computed < f_vco)
-				tmp_delta = f_vco - computed;
-			else
-				tmp_delta = computed - f_vco;
-			if (tmp_delta < delta) {
-				delta = tmp_delta;
-				m = testm + 1;
-				n = testn + 1;
-			}
-		}
-	}
-	f_vco = ref_clk * n / m;
-	if (f_vco < 100000)
-		s = 0;
-	else if (f_vco < 140000)
-		s = 1;
-	else if (f_vco < 180000)
-		s = 2;
-	else
-		s = 3;
-
-	drm_dbg_kms(dev, "clock: %ld vco: %ld m: %d n: %d p: %d s: %d\n",
-		    clock, f_vco, m, n, p, s);
-
-	pixpllc->m = m;
-	pixpllc->n = n;
-	pixpllc->p = p;
-	pixpllc->s = s;
-
-	return 0;
-}
-
-static void
-mgag200_pixpll_update_g200(struct mgag200_pll *pixpll, const struct mgag200_pll_values *pixpllc)
-{
-	struct mga_device *mdev = pixpll->mdev;
-	unsigned int pixpllcm, pixpllcn, pixpllcp, pixpllcs;
-	u8 xpixpllcm, xpixpllcn, xpixpllcp;
-
-	pixpllcm = pixpllc->m - 1;
-	pixpllcn = pixpllc->n - 1;
-	pixpllcp = pixpllc->p - 1;
-	pixpllcs = pixpllc->s;
-
-	xpixpllcm = pixpllcm;
-	xpixpllcn = pixpllcn;
-	xpixpllcp = (pixpllcs << 3) | pixpllcp;
-
-	WREG_MISC_MASKED(MGAREG_MISC_CLKSEL_MGA, MGAREG_MISC_CLKSEL_MASK);
-
-	WREG_DAC(MGA1064_PIX_PLLC_M, xpixpllcm);
-	WREG_DAC(MGA1064_PIX_PLLC_N, xpixpllcn);
-	WREG_DAC(MGA1064_PIX_PLLC_P, xpixpllcp);
-}
-
-static const struct mgag200_pll_funcs mgag200_pixpll_funcs_g200 = {
-	.compute = mgag200_pixpll_compute_g200,
-	.update = mgag200_pixpll_update_g200,
-};
-
-/*
- * G200SE
- */
-
-static int mgag200_pixpll_compute_g200se_00(struct mgag200_pll *pixpll, long clock,
-					    struct mgag200_pll_values *pixpllc)
-{
-	static const unsigned int vcomax = 320000;
-	static const unsigned int vcomin = 160000;
-	static const unsigned int pllreffreq = 25000;
-
-	unsigned int delta, tmpdelta, permitteddelta;
-	unsigned int testp, testm, testn;
-	unsigned int p, m, n, s;
-	unsigned int computed;
-
-	m = n = p = s = 0;
-	delta = 0xffffffff;
-	permitteddelta = clock * 5 / 1000;
-
-	for (testp = 8; testp > 0; testp /= 2) {
-		if (clock * testp > vcomax)
-			continue;
-		if (clock * testp < vcomin)
-			continue;
-
-		for (testn = 17; testn < 256; testn++) {
-			for (testm = 1; testm < 32; testm++) {
-				computed = (pllreffreq * testn) / (testm * testp);
-				if (computed > clock)
-					tmpdelta = computed - clock;
-				else
-					tmpdelta = clock - computed;
-				if (tmpdelta < delta) {
-					delta = tmpdelta;
-					m = testm;
-					n = testn;
-					p = testp;
-				}
-			}
-		}
-	}
-
-	if (delta > permitteddelta) {
-		pr_warn("PLL delta too large\n");
-		return -EINVAL;
-	}
-
-	pixpllc->m = m;
-	pixpllc->n = n;
-	pixpllc->p = p;
-	pixpllc->s = s;
-
-	return 0;
-}
-
-static void mgag200_pixpll_update_g200se_00(struct mgag200_pll *pixpll,
-					    const struct mgag200_pll_values *pixpllc)
-{
-	unsigned int pixpllcm, pixpllcn, pixpllcp, pixpllcs;
-	u8 xpixpllcm, xpixpllcn, xpixpllcp;
-	struct mga_device *mdev = pixpll->mdev;
-
-	pixpllcm = pixpllc->m - 1;
-	pixpllcn = pixpllc->n - 1;
-	pixpllcp = pixpllc->p - 1;
-	pixpllcs = pixpllc->s;
-
-	xpixpllcm = pixpllcm | ((pixpllcn & BIT(8)) >> 1);
-	xpixpllcn = pixpllcn;
-	xpixpllcp = (pixpllcs << 3) | pixpllcp;
-
-	WREG_MISC_MASKED(MGAREG_MISC_CLKSEL_MGA, MGAREG_MISC_CLKSEL_MASK);
-
-	WREG_DAC(MGA1064_PIX_PLLC_M, xpixpllcm);
-	WREG_DAC(MGA1064_PIX_PLLC_N, xpixpllcn);
-	WREG_DAC(MGA1064_PIX_PLLC_P, xpixpllcp);
-}
-
-static int mgag200_pixpll_compute_g200se_04(struct mgag200_pll *pixpll, long clock,
-					    struct mgag200_pll_values *pixpllc)
-{
-	static const unsigned int vcomax = 1600000;
-	static const unsigned int vcomin = 800000;
-	static const unsigned int pllreffreq = 25000;
-	static const unsigned int pvalues_e4[] = {16, 14, 12, 10, 8, 6, 4, 2, 1};
-
-	unsigned int delta, tmpdelta, permitteddelta;
-	unsigned int testp, testm, testn;
-	unsigned int p, m, n, s;
-	unsigned int computed;
-	unsigned int fvv;
-	unsigned int i;
-
-	m = n = p = s = 0;
-	delta = 0xffffffff;
-
-	if (clock < 25000)
-		clock = 25000;
-	clock = clock * 2;
-
-	/* Permited delta is 0.5% as VESA Specification */
-	permitteddelta = clock * 5 / 1000;
-
-	for (i = 0 ; i < ARRAY_SIZE(pvalues_e4); i++) {
-		testp = pvalues_e4[i];
-
-		if ((clock * testp) > vcomax)
-			continue;
-		if ((clock * testp) < vcomin)
-			continue;
-
-		for (testn = 50; testn <= 256; testn++) {
-			for (testm = 1; testm <= 32; testm++) {
-				computed = (pllreffreq * testn) / (testm * testp);
-				if (computed > clock)
-					tmpdelta = computed - clock;
-				else
-					tmpdelta = clock - computed;
-
-				if (tmpdelta < delta) {
-					delta = tmpdelta;
-					m = testm;
-					n = testn;
-					p = testp;
-				}
-			}
-		}
-	}
-
-	fvv = pllreffreq * n / m;
-	fvv = (fvv - 800000) / 50000;
-	if (fvv > 15)
-		fvv = 15;
-	s = fvv << 1;
-
-	if (delta > permitteddelta) {
-		pr_warn("PLL delta too large\n");
-		return -EINVAL;
-	}
-
-	pixpllc->m = m;
-	pixpllc->n = n;
-	pixpllc->p = p;
-	pixpllc->s = s;
-
-	return 0;
-}
-
-static void mgag200_pixpll_update_g200se_04(struct mgag200_pll *pixpll,
-					    const struct mgag200_pll_values *pixpllc)
-{
-	unsigned int pixpllcm, pixpllcn, pixpllcp, pixpllcs;
-	u8 xpixpllcm, xpixpllcn, xpixpllcp;
-	struct mga_device *mdev = pixpll->mdev;
-
-	pixpllcm = pixpllc->m - 1;
-	pixpllcn = pixpllc->n - 1;
-	pixpllcp = pixpllc->p - 1;
-	pixpllcs = pixpllc->s;
-
-	xpixpllcm = pixpllcm | ((pixpllcn & BIT(8)) >> 1);
-	xpixpllcn = pixpllcn;
-	xpixpllcp = (pixpllcs << 3) | pixpllcp;
-
-	WREG_MISC_MASKED(MGAREG_MISC_CLKSEL_MGA, MGAREG_MISC_CLKSEL_MASK);
-
-	WREG_DAC(MGA1064_PIX_PLLC_M, xpixpllcm);
-	WREG_DAC(MGA1064_PIX_PLLC_N, xpixpllcn);
-	WREG_DAC(MGA1064_PIX_PLLC_P, xpixpllcp);
-
-	WREG_DAC(0x1a, 0x09);
-	msleep(20);
-	WREG_DAC(0x1a, 0x01);
-}
-
-static const struct mgag200_pll_funcs mgag200_pixpll_funcs_g200se_00 = {
-	.compute = mgag200_pixpll_compute_g200se_00,
-	.update = mgag200_pixpll_update_g200se_00,
-};
-
-static const struct mgag200_pll_funcs mgag200_pixpll_funcs_g200se_04 = {
-	.compute = mgag200_pixpll_compute_g200se_04,
-	.update = mgag200_pixpll_update_g200se_04,
-};
-
-/*
- * G200WB
- */
-
-static int mgag200_pixpll_compute_g200wb(struct mgag200_pll *pixpll, long clock,
-					 struct mgag200_pll_values *pixpllc)
-{
-	static const unsigned int vcomax = 550000;
-	static const unsigned int vcomin = 150000;
-	static const unsigned int pllreffreq = 48000;
-
-	unsigned int delta, tmpdelta;
-	unsigned int testp, testm, testn;
-	unsigned int p, m, n, s;
-	unsigned int computed;
-
-	m = n = p = s = 0;
-	delta = 0xffffffff;
-
-	for (testp = 1; testp < 9; testp++) {
-		if (clock * testp > vcomax)
-			continue;
-		if (clock * testp < vcomin)
-			continue;
-
-		for (testm = 1; testm < 17; testm++) {
-			for (testn = 1; testn < 151; testn++) {
-				computed = (pllreffreq * testn) / (testm * testp);
-				if (computed > clock)
-					tmpdelta = computed - clock;
-				else
-					tmpdelta = clock - computed;
-				if (tmpdelta < delta) {
-					delta = tmpdelta;
-					n = testn;
-					m = testm;
-					p = testp;
-					s = 0;
-				}
-			}
-		}
-	}
-
-	pixpllc->m = m;
-	pixpllc->n = n;
-	pixpllc->p = p;
-	pixpllc->s = s;
-
-	return 0;
-}
-
-static void
-mgag200_pixpll_update_g200wb(struct mgag200_pll *pixpll, const struct mgag200_pll_values *pixpllc)
-{
-	unsigned int pixpllcm, pixpllcn, pixpllcp, pixpllcs;
-	u8 xpixpllcm, xpixpllcn, xpixpllcp, tmp;
-	int i, j, tmpcount, vcount;
-	struct mga_device *mdev = pixpll->mdev;
-	bool pll_locked = false;
-
-	pixpllcm = pixpllc->m - 1;
-	pixpllcn = pixpllc->n - 1;
-	pixpllcp = pixpllc->p - 1;
-	pixpllcs = pixpllc->s;
-
-	xpixpllcm = ((pixpllcn & BIT(8)) >> 1) | pixpllcm;
-	xpixpllcn = pixpllcn;
-	xpixpllcp = ((pixpllcn & GENMASK(10, 9)) >> 3) | (pixpllcs << 3) | pixpllcp;
-
-	WREG_MISC_MASKED(MGAREG_MISC_CLKSEL_MGA, MGAREG_MISC_CLKSEL_MASK);
-
-	for (i = 0; i <= 32 && pll_locked == false; i++) {
-		if (i > 0) {
-			WREG8(MGAREG_CRTC_INDEX, 0x1e);
-			tmp = RREG8(MGAREG_CRTC_DATA);
-			if (tmp < 0xff)
-				WREG8(MGAREG_CRTC_DATA, tmp+1);
-		}
-
-		/* set pixclkdis to 1 */
-		WREG8(DAC_INDEX, MGA1064_PIX_CLK_CTL);
-		tmp = RREG8(DAC_DATA);
-		tmp |= MGA1064_PIX_CLK_CTL_CLK_DIS;
-		WREG8(DAC_DATA, tmp);
-
-		WREG8(DAC_INDEX, MGA1064_REMHEADCTL);
-		tmp = RREG8(DAC_DATA);
-		tmp |= MGA1064_REMHEADCTL_CLKDIS;
-		WREG8(DAC_DATA, tmp);
-
-		/* select PLL Set C */
-		tmp = RREG8(MGAREG_MEM_MISC_READ);
-		tmp |= 0x3 << 2;
-		WREG8(MGAREG_MEM_MISC_WRITE, tmp);
-
-		WREG8(DAC_INDEX, MGA1064_PIX_CLK_CTL);
-		tmp = RREG8(DAC_DATA);
-		tmp |= MGA1064_PIX_CLK_CTL_CLK_POW_DOWN | 0x80;
-		WREG8(DAC_DATA, tmp);
-
-		udelay(500);
-
-		/* reset the PLL */
-		WREG8(DAC_INDEX, MGA1064_VREF_CTL);
-		tmp = RREG8(DAC_DATA);
-		tmp &= ~0x04;
-		WREG8(DAC_DATA, tmp);
-
-		udelay(50);
-
-		/* program pixel pll register */
-		WREG_DAC(MGA1064_WB_PIX_PLLC_N, xpixpllcn);
-		WREG_DAC(MGA1064_WB_PIX_PLLC_M, xpixpllcm);
-		WREG_DAC(MGA1064_WB_PIX_PLLC_P, xpixpllcp);
-
-		udelay(50);
-
-		/* turn pll on */
-		WREG8(DAC_INDEX, MGA1064_VREF_CTL);
-		tmp = RREG8(DAC_DATA);
-		tmp |= 0x04;
-		WREG_DAC(MGA1064_VREF_CTL, tmp);
-
-		udelay(500);
-
-		/* select the pixel pll */
-		WREG8(DAC_INDEX, MGA1064_PIX_CLK_CTL);
-		tmp = RREG8(DAC_DATA);
-		tmp &= ~MGA1064_PIX_CLK_CTL_SEL_MSK;
-		tmp |= MGA1064_PIX_CLK_CTL_SEL_PLL;
-		WREG8(DAC_DATA, tmp);
-
-		WREG8(DAC_INDEX, MGA1064_REMHEADCTL);
-		tmp = RREG8(DAC_DATA);
-		tmp &= ~MGA1064_REMHEADCTL_CLKSL_MSK;
-		tmp |= MGA1064_REMHEADCTL_CLKSL_PLL;
-		WREG8(DAC_DATA, tmp);
-
-		/* reset dotclock rate bit */
-		WREG8(MGAREG_SEQ_INDEX, 1);
-		tmp = RREG8(MGAREG_SEQ_DATA);
-		tmp &= ~0x8;
-		WREG8(MGAREG_SEQ_DATA, tmp);
-
-		WREG8(DAC_INDEX, MGA1064_PIX_CLK_CTL);
-		tmp = RREG8(DAC_DATA);
-		tmp &= ~MGA1064_PIX_CLK_CTL_CLK_DIS;
-		WREG8(DAC_DATA, tmp);
-
-		vcount = RREG8(MGAREG_VCOUNT);
-
-		for (j = 0; j < 30 && pll_locked == false; j++) {
-			tmpcount = RREG8(MGAREG_VCOUNT);
-			if (tmpcount < vcount)
-				vcount = 0;
-			if ((tmpcount - vcount) > 2)
-				pll_locked = true;
-			else
-				udelay(5);
-		}
-	}
-
-	WREG8(DAC_INDEX, MGA1064_REMHEADCTL);
-	tmp = RREG8(DAC_DATA);
-	tmp &= ~MGA1064_REMHEADCTL_CLKDIS;
-	WREG_DAC(MGA1064_REMHEADCTL, tmp);
-}
-
-static const struct mgag200_pll_funcs mgag200_pixpll_funcs_g200wb = {
-	.compute = mgag200_pixpll_compute_g200wb,
-	.update = mgag200_pixpll_update_g200wb,
-};
-
-/*
- * G200EV
- */
-
-static int mgag200_pixpll_compute_g200ev(struct mgag200_pll *pixpll, long clock,
-					 struct mgag200_pll_values *pixpllc)
-{
-	static const unsigned int vcomax = 550000;
-	static const unsigned int vcomin = 150000;
-	static const unsigned int pllreffreq = 50000;
-
-	unsigned int delta, tmpdelta;
-	unsigned int testp, testm, testn;
-	unsigned int p, m, n, s;
-	unsigned int computed;
-
-	m = n = p = s = 0;
-	delta = 0xffffffff;
-
-	for (testp = 16; testp > 0; testp--) {
-		if (clock * testp > vcomax)
-			continue;
-		if (clock * testp < vcomin)
-			continue;
-
-		for (testn = 1; testn < 257; testn++) {
-			for (testm = 1; testm < 17; testm++) {
-				computed = (pllreffreq * testn) /
-					(testm * testp);
-				if (computed > clock)
-					tmpdelta = computed - clock;
-				else
-					tmpdelta = clock - computed;
-				if (tmpdelta < delta) {
-					delta = tmpdelta;
-					n = testn;
-					m = testm;
-					p = testp;
-				}
-			}
-		}
-	}
-
-	pixpllc->m = m;
-	pixpllc->n = n;
-	pixpllc->p = p;
-	pixpllc->s = s;
-
-	return 0;
-}
-
-static void
-mgag200_pixpll_update_g200ev(struct mgag200_pll *pixpll, const struct mgag200_pll_values *pixpllc)
-{
-	unsigned int pixpllcm, pixpllcn, pixpllcp, pixpllcs;
-	u8 xpixpllcm, xpixpllcn, xpixpllcp, tmp;
-	struct mga_device *mdev = pixpll->mdev;
-
-	pixpllcm = pixpllc->m - 1;
-	pixpllcn = pixpllc->n - 1;
-	pixpllcp = pixpllc->p - 1;
-	pixpllcs = pixpllc->s;
-
-	xpixpllcm = pixpllcm;
-	xpixpllcn = pixpllcn;
-	xpixpllcp = (pixpllcs << 3) | pixpllcp;
-
-	WREG_MISC_MASKED(MGAREG_MISC_CLKSEL_MGA, MGAREG_MISC_CLKSEL_MASK);
-
-	WREG8(DAC_INDEX, MGA1064_PIX_CLK_CTL);
-	tmp = RREG8(DAC_DATA);
-	tmp |= MGA1064_PIX_CLK_CTL_CLK_DIS;
-	WREG8(DAC_DATA, tmp);
-
-	tmp = RREG8(MGAREG_MEM_MISC_READ);
-	tmp |= 0x3 << 2;
-	WREG8(MGAREG_MEM_MISC_WRITE, tmp);
-
-	WREG8(DAC_INDEX, MGA1064_PIX_PLL_STAT);
-	tmp = RREG8(DAC_DATA);
-	WREG8(DAC_DATA, tmp & ~0x40);
-
-	WREG8(DAC_INDEX, MGA1064_PIX_CLK_CTL);
-	tmp = RREG8(DAC_DATA);
-	tmp |= MGA1064_PIX_CLK_CTL_CLK_POW_DOWN;
-	WREG8(DAC_DATA, tmp);
-
-	WREG_DAC(MGA1064_EV_PIX_PLLC_M, xpixpllcm);
-	WREG_DAC(MGA1064_EV_PIX_PLLC_N, xpixpllcn);
-	WREG_DAC(MGA1064_EV_PIX_PLLC_P, xpixpllcp);
-
-	udelay(50);
-
-	WREG8(DAC_INDEX, MGA1064_PIX_CLK_CTL);
-	tmp = RREG8(DAC_DATA);
-	tmp &= ~MGA1064_PIX_CLK_CTL_CLK_POW_DOWN;
-	WREG8(DAC_DATA, tmp);
-
-	udelay(500);
-
-	WREG8(DAC_INDEX, MGA1064_PIX_CLK_CTL);
-	tmp = RREG8(DAC_DATA);
-	tmp &= ~MGA1064_PIX_CLK_CTL_SEL_MSK;
-	tmp |= MGA1064_PIX_CLK_CTL_SEL_PLL;
-	WREG8(DAC_DATA, tmp);
-
-	WREG8(DAC_INDEX, MGA1064_PIX_PLL_STAT);
-	tmp = RREG8(DAC_DATA);
-	WREG8(DAC_DATA, tmp | 0x40);
-
-	tmp = RREG8(MGAREG_MEM_MISC_READ);
-	tmp |= (0x3 << 2);
-	WREG8(MGAREG_MEM_MISC_WRITE, tmp);
-
-	WREG8(DAC_INDEX, MGA1064_PIX_CLK_CTL);
-	tmp = RREG8(DAC_DATA);
-	tmp &= ~MGA1064_PIX_CLK_CTL_CLK_DIS;
-	WREG8(DAC_DATA, tmp);
-}
-
-static const struct mgag200_pll_funcs mgag200_pixpll_funcs_g200ev = {
-	.compute = mgag200_pixpll_compute_g200ev,
-	.update = mgag200_pixpll_update_g200ev,
-};
-
-/*
- * G200EH
- */
-
-static int mgag200_pixpll_compute_g200eh(struct mgag200_pll *pixpll, long clock,
-					 struct mgag200_pll_values *pixpllc)
-{
-	static const unsigned int vcomax = 800000;
-	static const unsigned int vcomin = 400000;
-	static const unsigned int pllreffreq = 33333;
-
-	unsigned int delta, tmpdelta;
-	unsigned int testp, testm, testn;
-	unsigned int p, m, n, s;
-	unsigned int computed;
-
-	m = n = p = s = 0;
-	delta = 0xffffffff;
-
-	for (testp = 16; testp > 0; testp >>= 1) {
-		if (clock * testp > vcomax)
-			continue;
-		if (clock * testp < vcomin)
-			continue;
-
-		for (testm = 1; testm < 33; testm++) {
-			for (testn = 17; testn < 257; testn++) {
-				computed = (pllreffreq * testn) / (testm * testp);
-				if (computed > clock)
-					tmpdelta = computed - clock;
-				else
-					tmpdelta = clock - computed;
-				if (tmpdelta < delta) {
-					delta = tmpdelta;
-					n = testn;
-					m = testm;
-					p = testp;
-				}
-			}
-		}
-	}
-
-	pixpllc->m = m;
-	pixpllc->n = n;
-	pixpllc->p = p;
-	pixpllc->s = s;
-
-	return 0;
-}
-
-static void
-mgag200_pixpll_update_g200eh(struct mgag200_pll *pixpll, const struct mgag200_pll_values *pixpllc)
-{
-	unsigned int pixpllcm, pixpllcn, pixpllcp, pixpllcs;
-	u8 xpixpllcm, xpixpllcn, xpixpllcp, tmp;
-	int i, j, tmpcount, vcount;
-	struct mga_device *mdev = pixpll->mdev;
-	bool pll_locked = false;
-
-	pixpllcm = pixpllc->m - 1;
-	pixpllcn = pixpllc->n - 1;
-	pixpllcp = pixpllc->p - 1;
-	pixpllcs = pixpllc->s;
-
-	xpixpllcm = ((pixpllcn & BIT(8)) >> 1) | pixpllcm;
-	xpixpllcn = pixpllcn;
-	xpixpllcp = (pixpllcs << 3) | pixpllcp;
-
-	WREG_MISC_MASKED(MGAREG_MISC_CLKSEL_MGA, MGAREG_MISC_CLKSEL_MASK);
-
-	for (i = 0; i <= 32 && pll_locked == false; i++) {
-		WREG8(DAC_INDEX, MGA1064_PIX_CLK_CTL);
-		tmp = RREG8(DAC_DATA);
-		tmp |= MGA1064_PIX_CLK_CTL_CLK_DIS;
-		WREG8(DAC_DATA, tmp);
-
-		tmp = RREG8(MGAREG_MEM_MISC_READ);
-		tmp |= 0x3 << 2;
-		WREG8(MGAREG_MEM_MISC_WRITE, tmp);
-
-		WREG8(DAC_INDEX, MGA1064_PIX_CLK_CTL);
-		tmp = RREG8(DAC_DATA);
-		tmp |= MGA1064_PIX_CLK_CTL_CLK_POW_DOWN;
-		WREG8(DAC_DATA, tmp);
-
-		udelay(500);
-
-		WREG_DAC(MGA1064_EH_PIX_PLLC_M, xpixpllcm);
-		WREG_DAC(MGA1064_EH_PIX_PLLC_N, xpixpllcn);
-		WREG_DAC(MGA1064_EH_PIX_PLLC_P, xpixpllcp);
-
-		udelay(500);
-
-		WREG8(DAC_INDEX, MGA1064_PIX_CLK_CTL);
-		tmp = RREG8(DAC_DATA);
-		tmp &= ~MGA1064_PIX_CLK_CTL_SEL_MSK;
-		tmp |= MGA1064_PIX_CLK_CTL_SEL_PLL;
-		WREG8(DAC_DATA, tmp);
-
-		WREG8(DAC_INDEX, MGA1064_PIX_CLK_CTL);
-		tmp = RREG8(DAC_DATA);
-		tmp &= ~MGA1064_PIX_CLK_CTL_CLK_DIS;
-		tmp &= ~MGA1064_PIX_CLK_CTL_CLK_POW_DOWN;
-		WREG8(DAC_DATA, tmp);
-
-		vcount = RREG8(MGAREG_VCOUNT);
-
-		for (j = 0; j < 30 && pll_locked == false; j++) {
-			tmpcount = RREG8(MGAREG_VCOUNT);
-			if (tmpcount < vcount)
-				vcount = 0;
-			if ((tmpcount - vcount) > 2)
-				pll_locked = true;
-			else
-				udelay(5);
-		}
-	}
-}
-
-static const struct mgag200_pll_funcs mgag200_pixpll_funcs_g200eh = {
-	.compute = mgag200_pixpll_compute_g200eh,
-	.update = mgag200_pixpll_update_g200eh,
-};
-
-/*
- * G200EH3
- */
-
-static int mgag200_pixpll_compute_g200eh3(struct mgag200_pll *pixpll, long clock,
-					  struct mgag200_pll_values *pixpllc)
-{
-	static const unsigned int vcomax = 3000000;
-	static const unsigned int vcomin = 1500000;
-	static const unsigned int pllreffreq = 25000;
-
-	unsigned int delta, tmpdelta;
-	unsigned int testp, testm, testn;
-	unsigned int p, m, n, s;
-	unsigned int computed;
-
-	m = n = p = s = 0;
-	delta = 0xffffffff;
-	testp = 0;
-
-	for (testm = 150; testm >= 6; testm--) {
-		if (clock * testm > vcomax)
-			continue;
-		if (clock * testm < vcomin)
-			continue;
-		for (testn = 120; testn >= 60; testn--) {
-			computed = (pllreffreq * testn) / testm;
-			if (computed > clock)
-				tmpdelta = computed - clock;
-			else
-				tmpdelta = clock - computed;
-			if (tmpdelta < delta) {
-				delta = tmpdelta;
-				n = testn + 1;
-				m = testm + 1;
-				p = testp + 1;
-			}
-			if (delta == 0)
-				break;
-		}
-		if (delta == 0)
-			break;
-	}
-
-	pixpllc->m = m;
-	pixpllc->n = n;
-	pixpllc->p = p;
-	pixpllc->s = s;
-
-	return 0;
-}
-
-static const struct mgag200_pll_funcs mgag200_pixpll_funcs_g200eh3 = {
-	.compute = mgag200_pixpll_compute_g200eh3,
-	.update = mgag200_pixpll_update_g200eh, // same as G200EH
-};
-
-/*
- * G200ER
- */
-
-static int mgag200_pixpll_compute_g200er(struct mgag200_pll *pixpll, long clock,
-					 struct mgag200_pll_values *pixpllc)
-{
-	static const unsigned int vcomax = 1488000;
-	static const unsigned int vcomin = 1056000;
-	static const unsigned int pllreffreq = 48000;
-	static const unsigned int m_div_val[] = { 1, 2, 4, 8 };
-
-	unsigned int delta, tmpdelta;
-	int testr, testn, testm, testo;
-	unsigned int p, m, n, s;
-	unsigned int computed, vco;
-
-	m = n = p = s = 0;
-	delta = 0xffffffff;
-
-	for (testr = 0; testr < 4; testr++) {
-		if (delta == 0)
-			break;
-		for (testn = 5; testn < 129; testn++) {
-			if (delta == 0)
-				break;
-			for (testm = 3; testm >= 0; testm--) {
-				if (delta == 0)
-					break;
-				for (testo = 5; testo < 33; testo++) {
-					vco = pllreffreq * (testn + 1) /
-						(testr + 1);
-					if (vco < vcomin)
-						continue;
-					if (vco > vcomax)
-						continue;
-					computed = vco / (m_div_val[testm] * (testo + 1));
-					if (computed > clock)
-						tmpdelta = computed - clock;
-					else
-						tmpdelta = clock - computed;
-					if (tmpdelta < delta) {
-						delta = tmpdelta;
-						m = (testm | (testo << 3)) + 1;
-						n = testn + 1;
-						p = testr + 1;
-						s = testr;
-					}
-				}
-			}
-		}
-	}
-
-	pixpllc->m = m;
-	pixpllc->n = n;
-	pixpllc->p = p;
-	pixpllc->s = s;
-
-	return 0;
-}
-
-static void
-mgag200_pixpll_update_g200er(struct mgag200_pll *pixpll, const struct mgag200_pll_values *pixpllc)
-{
-	unsigned int pixpllcm, pixpllcn, pixpllcp, pixpllcs;
-	u8 xpixpllcm, xpixpllcn, xpixpllcp, tmp;
-	struct mga_device *mdev = pixpll->mdev;
-
-	pixpllcm = pixpllc->m - 1;
-	pixpllcn = pixpllc->n - 1;
-	pixpllcp = pixpllc->p - 1;
-	pixpllcs = pixpllc->s;
-
-	xpixpllcm = pixpllcm;
-	xpixpllcn = pixpllcn;
-	xpixpllcp = (pixpllcs << 3) | pixpllcp;
-
-	WREG_MISC_MASKED(MGAREG_MISC_CLKSEL_MGA, MGAREG_MISC_CLKSEL_MASK);
-
-	WREG8(DAC_INDEX, MGA1064_PIX_CLK_CTL);
-	tmp = RREG8(DAC_DATA);
-	tmp |= MGA1064_PIX_CLK_CTL_CLK_DIS;
-	WREG8(DAC_DATA, tmp);
-
-	WREG8(DAC_INDEX, MGA1064_REMHEADCTL);
-	tmp = RREG8(DAC_DATA);
-	tmp |= MGA1064_REMHEADCTL_CLKDIS;
-	WREG8(DAC_DATA, tmp);
-
-	tmp = RREG8(MGAREG_MEM_MISC_READ);
-	tmp |= (0x3<<2) | 0xc0;
-	WREG8(MGAREG_MEM_MISC_WRITE, tmp);
-
-	WREG8(DAC_INDEX, MGA1064_PIX_CLK_CTL);
-	tmp = RREG8(DAC_DATA);
-	tmp &= ~MGA1064_PIX_CLK_CTL_CLK_DIS;
-	tmp |= MGA1064_PIX_CLK_CTL_CLK_POW_DOWN;
-	WREG8(DAC_DATA, tmp);
-
-	udelay(500);
-
-	WREG_DAC(MGA1064_ER_PIX_PLLC_N, xpixpllcn);
-	WREG_DAC(MGA1064_ER_PIX_PLLC_M, xpixpllcm);
-	WREG_DAC(MGA1064_ER_PIX_PLLC_P, xpixpllcp);
-
-	udelay(50);
-}
-
-static const struct mgag200_pll_funcs mgag200_pixpll_funcs_g200er = {
-	.compute = mgag200_pixpll_compute_g200er,
-	.update = mgag200_pixpll_update_g200er,
-};
-
-/*
- * G200EW3
- */
-
-static int mgag200_pixpll_compute_g200ew3(struct mgag200_pll *pixpll, long clock,
-					  struct mgag200_pll_values *pixpllc)
-{
-	static const unsigned int vcomax = 800000;
-	static const unsigned int vcomin = 400000;
-	static const unsigned int pllreffreq = 25000;
-
-	unsigned int delta, tmpdelta;
-	unsigned int testp, testm, testn, testp2;
-	unsigned int p, m, n, s;
-	unsigned int computed;
-
-	m = n = p = s = 0;
-	delta = 0xffffffff;
-
-	for (testp = 1; testp < 8; testp++) {
-		for (testp2 = 1; testp2 < 8; testp2++) {
-			if (testp < testp2)
-				continue;
-			if ((clock * testp * testp2) > vcomax)
-				continue;
-			if ((clock * testp * testp2) < vcomin)
-				continue;
-			for (testm = 1; testm < 26; testm++) {
-				for (testn = 32; testn < 2048 ; testn++) {
-					computed = (pllreffreq * testn) / (testm * testp * testp2);
-					if (computed > clock)
-						tmpdelta = computed - clock;
-					else
-						tmpdelta = clock - computed;
-					if (tmpdelta < delta) {
-						delta = tmpdelta;
-						m = testm + 1;
-						n = testn + 1;
-						p = testp + 1;
-						s = testp2;
-					}
-				}
-			}
-		}
-	}
-
-	pixpllc->m = m;
-	pixpllc->n = n;
-	pixpllc->p = p;
-	pixpllc->s = s;
-
-	return 0;
-}
-
-static const struct mgag200_pll_funcs mgag200_pixpll_funcs_g200ew3 = {
-	.compute = mgag200_pixpll_compute_g200ew3,
-	.update = mgag200_pixpll_update_g200wb, // same as G200WB
-};
-
-/*
- * PLL initialization
- */
-
-int mgag200_pixpll_init(struct mgag200_pll *pixpll, struct mga_device *mdev)
-{
-	struct drm_device *dev = &mdev->base;
-	struct mgag200_g200se_device *g200se;
-
-	pixpll->mdev = mdev;
-
-	switch (mdev->type) {
-	case G200_PCI:
-	case G200_AGP:
-		pixpll->funcs = &mgag200_pixpll_funcs_g200;
-		break;
-	case G200_SE_A:
-	case G200_SE_B:
-		g200se = to_mgag200_g200se_device(dev);
-
-		if (g200se->unique_rev_id >= 0x04)
-			pixpll->funcs = &mgag200_pixpll_funcs_g200se_04;
-		else
-			pixpll->funcs = &mgag200_pixpll_funcs_g200se_00;
-		break;
-	case G200_WB:
-		pixpll->funcs = &mgag200_pixpll_funcs_g200wb;
-		break;
-	case G200_EV:
-		pixpll->funcs = &mgag200_pixpll_funcs_g200ev;
-		break;
-	case G200_EH:
-		pixpll->funcs = &mgag200_pixpll_funcs_g200eh;
-		break;
-	case G200_EH3:
-		pixpll->funcs = &mgag200_pixpll_funcs_g200eh3;
-		break;
-	case G200_ER:
-		pixpll->funcs = &mgag200_pixpll_funcs_g200er;
-		break;
-	case G200_EW3:
-		pixpll->funcs = &mgag200_pixpll_funcs_g200ew3;
-		break;
-	default:
-		drm_err(dev, "unknown device type %d\n", mdev->type);
-		return -ENODEV;
-	}
-
-	return 0;
-}
-- 
2.36.1


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

* [PATCH 12/14] drm/mgag200: Move mode-config to model-specific code
  2022-07-08  9:39 [PATCH 00/14] drm/mgag200: Move model-specific code into separate functions Thomas Zimmermann
                   ` (10 preceding siblings ...)
  2022-07-08  9:39 ` [PATCH 11/14] drm/mgag200: Provide per-device callbacks for PIXPLLC Thomas Zimmermann
@ 2022-07-08  9:39 ` Thomas Zimmermann
  2022-07-08  9:39 ` [PATCH 13/14] drm/mgag200: Move CRTC atomic_enable to model-specfic code Thomas Zimmermann
                   ` (2 subsequent siblings)
  14 siblings, 0 replies; 28+ messages in thread
From: Thomas Zimmermann @ 2022-07-08  9:39 UTC (permalink / raw)
  To: airlied, airlied, jfalempe, daniel; +Cc: Thomas Zimmermann, dri-devel

Move the mode-config code into model-specific code and call the
plane/CRTC helpers as needed. This will help with providing per-
model implementations of individual helpers.

Duplication of the pipeline init function is accepted. Some macros
simplify this for shared helpers.

Signed-off-by: Thomas Zimmermann <tzimmermann@suse.de>
---
 drivers/gpu/drm/mgag200/mgag200_drv.h     |  78 ++++++++-
 drivers/gpu/drm/mgag200/mgag200_g200.c    | 111 ++++++++++++-
 drivers/gpu/drm/mgag200/mgag200_g200eh.c  | 111 ++++++++++++-
 drivers/gpu/drm/mgag200/mgag200_g200eh3.c | 111 ++++++++++++-
 drivers/gpu/drm/mgag200/mgag200_g200er.c  | 111 ++++++++++++-
 drivers/gpu/drm/mgag200/mgag200_g200ev.c  | 111 ++++++++++++-
 drivers/gpu/drm/mgag200/mgag200_g200ew3.c | 111 ++++++++++++-
 drivers/gpu/drm/mgag200/mgag200_g200se.c  | 111 ++++++++++++-
 drivers/gpu/drm/mgag200/mgag200_g200wb.c  | 111 ++++++++++++-
 drivers/gpu/drm/mgag200/mgag200_mode.c    | 186 +++-------------------
 10 files changed, 977 insertions(+), 175 deletions(-)

diff --git a/drivers/gpu/drm/mgag200/mgag200_drv.h b/drivers/gpu/drm/mgag200/mgag200_drv.h
index 8a7204e3ff96..69bdd61e9d82 100644
--- a/drivers/gpu/drm/mgag200/mgag200_drv.h
+++ b/drivers/gpu/drm/mgag200/mgag200_drv.h
@@ -125,6 +125,8 @@
 #define MGA_MISC_OUT 0x1fc2
 #define MGA_MISC_IN 0x1fcc
 
+#define MGAG200_LUT_SIZE 256
+
 #define MGAG200_MAX_FB_HEIGHT 4096
 #define MGAG200_MAX_FB_WIDTH 4096
 
@@ -336,10 +338,82 @@ struct mga_device *mgag200_g200er_device_create(struct pci_dev *pdev, const stru
 struct mga_device *mgag200_g200ew3_device_create(struct pci_dev *pdev, const struct drm_driver *drv,
 						 enum mga_type type);
 
-				/* mgag200_mode.c */
+/*
+ * mgag200_mode.c
+ */
+
+struct drm_crtc;
+struct drm_crtc_state;
+struct drm_display_mode;
+struct drm_plane;
+struct drm_atomic_state;
+
+extern const uint32_t mgag200_primary_plane_formats[];
+extern const size_t   mgag200_primary_plane_formats_size;
+extern const uint64_t mgag200_primary_plane_fmtmods[];
+
+int mgag200_primary_plane_helper_atomic_check(struct drm_plane *plane,
+					      struct drm_atomic_state *state);
+void mgag200_primary_plane_helper_atomic_update(struct drm_plane *plane,
+						struct drm_atomic_state *old_state);
+void mgag200_primary_plane_helper_atomic_disable(struct drm_plane *plane,
+						 struct drm_atomic_state *old_state);
+#define MGAG200_PRIMARY_PLANE_HELPER_FUNCS \
+	DRM_GEM_SHADOW_PLANE_HELPER_FUNCS, \
+	.atomic_check = mgag200_primary_plane_helper_atomic_check, \
+	.atomic_update = mgag200_primary_plane_helper_atomic_update, \
+	.atomic_disable = mgag200_primary_plane_helper_atomic_disable
+
+#define MGAG200_PRIMARY_PLANE_FUNCS \
+	.update_plane = drm_atomic_helper_update_plane, \
+	.disable_plane = drm_atomic_helper_disable_plane, \
+	.destroy = drm_plane_cleanup, \
+	DRM_GEM_SHADOW_PLANE_FUNCS
+
+enum drm_mode_status mgag200_crtc_helper_mode_valid(struct drm_crtc *crtc,
+						    const struct drm_display_mode *mode);
+int mgag200_crtc_helper_atomic_check(struct drm_crtc *crtc, struct drm_atomic_state *state);
+void mgag200_crtc_helper_atomic_flush(struct drm_crtc *crtc, struct drm_atomic_state *old_state);
+void mgag200_crtc_helper_atomic_enable(struct drm_crtc *crtc, struct drm_atomic_state *old_state);
+void mgag200_crtc_helper_atomic_disable(struct drm_crtc *crtc, struct drm_atomic_state *old_state);
+
+#define MGAG200_CRTC_HELPER_FUNCS \
+	.mode_valid = mgag200_crtc_helper_mode_valid, \
+	.atomic_check = mgag200_crtc_helper_atomic_check, \
+	.atomic_flush = mgag200_crtc_helper_atomic_flush, \
+	.atomic_enable = mgag200_crtc_helper_atomic_enable, \
+	.atomic_disable = mgag200_crtc_helper_atomic_disable
+
+void mgag200_crtc_reset(struct drm_crtc *crtc);
+struct drm_crtc_state *mgag200_crtc_atomic_duplicate_state(struct drm_crtc *crtc);
+void mgag200_crtc_atomic_destroy_state(struct drm_crtc *crtc, struct drm_crtc_state *crtc_state);
+
+#define MGAG200_CRTC_FUNCS \
+	.reset = mgag200_crtc_reset, \
+	.destroy = drm_crtc_cleanup, \
+	.set_config = drm_atomic_helper_set_config, \
+	.page_flip = drm_atomic_helper_page_flip, \
+	.atomic_duplicate_state = mgag200_crtc_atomic_duplicate_state, \
+	.atomic_destroy_state = mgag200_crtc_atomic_destroy_state
+
+#define MGAG200_DAC_ENCODER_FUNCS \
+	.destroy = drm_encoder_cleanup
+
+int mgag200_vga_connector_helper_get_modes(struct drm_connector *connector);
+
+#define MGAG200_VGA_CONNECTOR_HELPER_FUNCS \
+	.get_modes  = mgag200_vga_connector_helper_get_modes
+
+#define MGAG200_VGA_CONNECTOR_FUNCS \
+	.reset                  = drm_atomic_helper_connector_reset, \
+	.fill_modes             = drm_helper_probe_single_connector_modes, \
+	.destroy                = drm_connector_cleanup, \
+	.atomic_duplicate_state = drm_atomic_helper_connector_duplicate_state, \
+	.atomic_destroy_state   = drm_atomic_helper_connector_destroy_state
+
 resource_size_t mgag200_device_probe_vram(struct mga_device *mdev);
 void mgag200_init_registers(struct mga_device *mdev);
-int mgag200_modeset_init(struct mga_device *mdev, resource_size_t vram_fb_available);
+int mgag200_mode_config_init(struct mga_device *mdev, resource_size_t vram_available);
 
 				/* mgag200_bmc.c */
 void mgag200_bmc_disable_vidrst(struct mga_device *mdev);
diff --git a/drivers/gpu/drm/mgag200/mgag200_g200.c b/drivers/gpu/drm/mgag200/mgag200_g200.c
index 1f7dde2d7547..e0c0fd224c5e 100644
--- a/drivers/gpu/drm/mgag200/mgag200_g200.c
+++ b/drivers/gpu/drm/mgag200/mgag200_g200.c
@@ -4,7 +4,10 @@
 #include <linux/vmalloc.h>
 
 #include <drm/drm_atomic.h>
+#include <drm/drm_atomic_helper.h>
 #include <drm/drm_drv.h>
+#include <drm/drm_gem_atomic_helper.h>
+#include <drm/drm_probe_helper.h>
 
 #include "mgag200_drv.h"
 
@@ -172,6 +175,106 @@ static void mgag200_g200_pixpllc_atomic_update(struct drm_crtc *crtc,
 	WREG_DAC(MGA1064_PIX_PLLC_P, xpixpllcp);
 }
 
+/*
+ * Mode-setting pipeline
+ */
+
+static const struct drm_plane_helper_funcs mgag200_g200_primary_plane_helper_funcs = {
+	MGAG200_PRIMARY_PLANE_HELPER_FUNCS,
+};
+
+static const struct drm_plane_funcs mgag200_g200_primary_plane_funcs = {
+	MGAG200_PRIMARY_PLANE_FUNCS,
+};
+
+static const struct drm_crtc_helper_funcs mgag200_g200_crtc_helper_funcs = {
+	MGAG200_CRTC_HELPER_FUNCS,
+};
+
+static const struct drm_crtc_funcs mgag200_g200_crtc_funcs = {
+	MGAG200_CRTC_FUNCS,
+};
+
+static const struct drm_encoder_funcs mgag200_g200_dac_encoder_funcs = {
+	MGAG200_DAC_ENCODER_FUNCS,
+};
+
+static const struct drm_connector_helper_funcs mgag200_g200_vga_connector_helper_funcs = {
+	MGAG200_VGA_CONNECTOR_HELPER_FUNCS,
+};
+
+static const struct drm_connector_funcs mgag200_g200_vga_connector_funcs = {
+	MGAG200_VGA_CONNECTOR_FUNCS,
+};
+
+static int mgag200_g200_pipeline_init(struct mga_device *mdev)
+{
+	struct drm_device *dev = &mdev->base;
+	struct drm_plane *primary_plane = &mdev->primary_plane;
+	struct drm_crtc *crtc = &mdev->crtc;
+	struct drm_encoder *encoder = &mdev->encoder;
+	struct mga_i2c_chan *i2c = &mdev->i2c;
+	struct drm_connector *connector = &mdev->connector;
+	int ret;
+
+	ret = drm_universal_plane_init(dev, primary_plane, 0,
+				       &mgag200_g200_primary_plane_funcs,
+				       mgag200_primary_plane_formats,
+				       mgag200_primary_plane_formats_size,
+				       mgag200_primary_plane_fmtmods,
+				       DRM_PLANE_TYPE_PRIMARY, NULL);
+	if (ret) {
+		drm_err(dev, "drm_universal_plane_init() failed: %d\n", ret);
+		return ret;
+	}
+	drm_plane_helper_add(primary_plane, &mgag200_g200_primary_plane_helper_funcs);
+	drm_plane_enable_fb_damage_clips(primary_plane);
+
+	ret = drm_crtc_init_with_planes(dev, crtc, primary_plane, NULL,
+					&mgag200_g200_crtc_funcs, NULL);
+	if (ret) {
+		drm_err(dev, "drm_crtc_init_with_planes() failed: %d\n", ret);
+		return ret;
+	}
+	drm_crtc_helper_add(crtc, &mgag200_g200_crtc_helper_funcs);
+
+	/* FIXME: legacy gamma tables, but atomic gamma doesn't work without */
+	drm_mode_crtc_set_gamma_size(crtc, MGAG200_LUT_SIZE);
+	drm_crtc_enable_color_mgmt(crtc, 0, false, MGAG200_LUT_SIZE);
+
+	encoder->possible_crtcs = drm_crtc_mask(crtc);
+	ret = drm_encoder_init(dev, encoder, &mgag200_g200_dac_encoder_funcs,
+			       DRM_MODE_ENCODER_DAC, NULL);
+	if (ret) {
+		drm_err(dev, "drm_encoder_init() failed: %d\n", ret);
+		return ret;
+	}
+
+	ret = mgag200_i2c_init(mdev, i2c);
+	if (ret) {
+		drm_err(dev, "failed to add DDC bus: %d\n", ret);
+		return ret;
+	}
+
+	ret = drm_connector_init_with_ddc(dev, connector,
+					  &mgag200_g200_vga_connector_funcs,
+					  DRM_MODE_CONNECTOR_VGA,
+					  &i2c->adapter);
+	if (ret) {
+		drm_err(dev, "drm_connector_init_with_ddc() failed: %d\n", ret);
+		return ret;
+	}
+	drm_connector_helper_add(connector, &mgag200_g200_vga_connector_helper_funcs);
+
+	ret = drm_connector_attach_encoder(connector, encoder);
+	if (ret) {
+		drm_err(dev, "drm_connector_attach_encoder() failed: %d\n", ret);
+		return ret;
+	}
+
+	return 0;
+}
+
 /*
  * DRM Device
  */
@@ -343,9 +446,15 @@ struct mga_device *mgag200_g200_device_create(struct pci_dev *pdev, const struct
 
 	vram_available = mgag200_device_probe_vram(mdev);
 
-	ret = mgag200_modeset_init(mdev, vram_available);
+	ret = mgag200_mode_config_init(mdev, vram_available);
 	if (ret)
 		return ERR_PTR(ret);
 
+	ret = mgag200_g200_pipeline_init(mdev);
+	if (ret)
+		return ERR_PTR(ret);
+
+	drm_mode_config_reset(dev);
+
 	return mdev;
 }
diff --git a/drivers/gpu/drm/mgag200/mgag200_g200eh.c b/drivers/gpu/drm/mgag200/mgag200_g200eh.c
index b59ba115bda3..205540e33237 100644
--- a/drivers/gpu/drm/mgag200/mgag200_g200eh.c
+++ b/drivers/gpu/drm/mgag200/mgag200_g200eh.c
@@ -4,7 +4,10 @@
 #include <linux/pci.h>
 
 #include <drm/drm_atomic.h>
+#include <drm/drm_atomic_helper.h>
 #include <drm/drm_drv.h>
+#include <drm/drm_gem_atomic_helper.h>
+#include <drm/drm_probe_helper.h>
 
 #include "mgag200_drv.h"
 
@@ -169,6 +172,106 @@ void mgag200_g200eh_pixpllc_atomic_update(struct drm_crtc *crtc,
 	}
 }
 
+/*
+ * Mode-setting pipeline
+ */
+
+static const struct drm_plane_helper_funcs mgag200_g200eh_primary_plane_helper_funcs = {
+	MGAG200_PRIMARY_PLANE_HELPER_FUNCS,
+};
+
+static const struct drm_plane_funcs mgag200_g200eh_primary_plane_funcs = {
+	MGAG200_PRIMARY_PLANE_FUNCS,
+};
+
+static const struct drm_crtc_helper_funcs mgag200_g200eh_crtc_helper_funcs = {
+	MGAG200_CRTC_HELPER_FUNCS,
+};
+
+static const struct drm_crtc_funcs mgag200_g200eh_crtc_funcs = {
+	MGAG200_CRTC_FUNCS,
+};
+
+static const struct drm_encoder_funcs mgag200_g200eh_dac_encoder_funcs = {
+	MGAG200_DAC_ENCODER_FUNCS,
+};
+
+static const struct drm_connector_helper_funcs mgag200_g200eh_vga_connector_helper_funcs = {
+	MGAG200_VGA_CONNECTOR_HELPER_FUNCS,
+};
+
+static const struct drm_connector_funcs mgag200_g200eh_vga_connector_funcs = {
+	MGAG200_VGA_CONNECTOR_FUNCS,
+};
+
+static int mgag200_g200eh_pipeline_init(struct mga_device *mdev)
+{
+	struct drm_device *dev = &mdev->base;
+	struct drm_plane *primary_plane = &mdev->primary_plane;
+	struct drm_crtc *crtc = &mdev->crtc;
+	struct drm_encoder *encoder = &mdev->encoder;
+	struct mga_i2c_chan *i2c = &mdev->i2c;
+	struct drm_connector *connector = &mdev->connector;
+	int ret;
+
+	ret = drm_universal_plane_init(dev, primary_plane, 0,
+				       &mgag200_g200eh_primary_plane_funcs,
+				       mgag200_primary_plane_formats,
+				       mgag200_primary_plane_formats_size,
+				       mgag200_primary_plane_fmtmods,
+				       DRM_PLANE_TYPE_PRIMARY, NULL);
+	if (ret) {
+		drm_err(dev, "drm_universal_plane_init() failed: %d\n", ret);
+		return ret;
+	}
+	drm_plane_helper_add(primary_plane, &mgag200_g200eh_primary_plane_helper_funcs);
+	drm_plane_enable_fb_damage_clips(primary_plane);
+
+	ret = drm_crtc_init_with_planes(dev, crtc, primary_plane, NULL,
+					&mgag200_g200eh_crtc_funcs, NULL);
+	if (ret) {
+		drm_err(dev, "drm_crtc_init_with_planes() failed: %d\n", ret);
+		return ret;
+	}
+	drm_crtc_helper_add(crtc, &mgag200_g200eh_crtc_helper_funcs);
+
+	/* FIXME: legacy gamma tables, but atomic gamma doesn't work without */
+	drm_mode_crtc_set_gamma_size(crtc, MGAG200_LUT_SIZE);
+	drm_crtc_enable_color_mgmt(crtc, 0, false, MGAG200_LUT_SIZE);
+
+	encoder->possible_crtcs = drm_crtc_mask(crtc);
+	ret = drm_encoder_init(dev, encoder, &mgag200_g200eh_dac_encoder_funcs,
+			       DRM_MODE_ENCODER_DAC, NULL);
+	if (ret) {
+		drm_err(dev, "drm_encoder_init() failed: %d\n", ret);
+		return ret;
+	}
+
+	ret = mgag200_i2c_init(mdev, i2c);
+	if (ret) {
+		drm_err(dev, "failed to add DDC bus: %d\n", ret);
+		return ret;
+	}
+
+	ret = drm_connector_init_with_ddc(dev, connector,
+					  &mgag200_g200eh_vga_connector_funcs,
+					  DRM_MODE_CONNECTOR_VGA,
+					  &i2c->adapter);
+	if (ret) {
+		drm_err(dev, "drm_connector_init_with_ddc() failed: %d\n", ret);
+		return ret;
+	}
+	drm_connector_helper_add(connector, &mgag200_g200eh_vga_connector_helper_funcs);
+
+	ret = drm_connector_attach_encoder(connector, encoder);
+	if (ret) {
+		drm_err(dev, "drm_connector_attach_encoder() failed: %d\n", ret);
+		return ret;
+	}
+
+	return 0;
+}
+
 /*
  * DRM device
  */
@@ -213,9 +316,15 @@ struct mga_device *mgag200_g200eh_device_create(struct pci_dev *pdev, const stru
 
 	vram_available = mgag200_device_probe_vram(mdev);
 
-	ret = mgag200_modeset_init(mdev, vram_available);
+	ret = mgag200_mode_config_init(mdev, vram_available);
 	if (ret)
 		return ERR_PTR(ret);
 
+	ret = mgag200_g200eh_pipeline_init(mdev);
+	if (ret)
+		return ERR_PTR(ret);
+
+	drm_mode_config_reset(dev);
+
 	return mdev;
 }
diff --git a/drivers/gpu/drm/mgag200/mgag200_g200eh3.c b/drivers/gpu/drm/mgag200/mgag200_g200eh3.c
index 9998197c6446..69ce68efe16c 100644
--- a/drivers/gpu/drm/mgag200/mgag200_g200eh3.c
+++ b/drivers/gpu/drm/mgag200/mgag200_g200eh3.c
@@ -3,7 +3,10 @@
 #include <linux/pci.h>
 
 #include <drm/drm_atomic.h>
+#include <drm/drm_atomic_helper.h>
 #include <drm/drm_drv.h>
+#include <drm/drm_gem_atomic_helper.h>
+#include <drm/drm_probe_helper.h>
 
 #include "mgag200_drv.h"
 
@@ -63,6 +66,106 @@ static int mgag200_g200eh3_pixpllc_atomic_check(struct drm_crtc *crtc,
 	return 0;
 }
 
+/*
+ * Mode-setting pipeline
+ */
+
+static const struct drm_plane_helper_funcs mgag200_g200eh3_primary_plane_helper_funcs = {
+	MGAG200_PRIMARY_PLANE_HELPER_FUNCS,
+};
+
+static const struct drm_plane_funcs mgag200_g200eh3_primary_plane_funcs = {
+	MGAG200_PRIMARY_PLANE_FUNCS,
+};
+
+static const struct drm_crtc_helper_funcs mgag200_g200eh3_crtc_helper_funcs = {
+	MGAG200_CRTC_HELPER_FUNCS,
+};
+
+static const struct drm_crtc_funcs mgag200_g200eh3_crtc_funcs = {
+	MGAG200_CRTC_FUNCS,
+};
+
+static const struct drm_encoder_funcs mgag200_g200eh3_dac_encoder_funcs = {
+	MGAG200_DAC_ENCODER_FUNCS,
+};
+
+static const struct drm_connector_helper_funcs mgag200_g200eh3_vga_connector_helper_funcs = {
+	MGAG200_VGA_CONNECTOR_HELPER_FUNCS,
+};
+
+static const struct drm_connector_funcs mgag200_g200eh3_vga_connector_funcs = {
+	MGAG200_VGA_CONNECTOR_FUNCS,
+};
+
+static int mgag200_g200eh3_pipeline_init(struct mga_device *mdev)
+{
+	struct drm_device *dev = &mdev->base;
+	struct drm_plane *primary_plane = &mdev->primary_plane;
+	struct drm_crtc *crtc = &mdev->crtc;
+	struct drm_encoder *encoder = &mdev->encoder;
+	struct mga_i2c_chan *i2c = &mdev->i2c;
+	struct drm_connector *connector = &mdev->connector;
+	int ret;
+
+	ret = drm_universal_plane_init(dev, primary_plane, 0,
+				       &mgag200_g200eh3_primary_plane_funcs,
+				       mgag200_primary_plane_formats,
+				       mgag200_primary_plane_formats_size,
+				       mgag200_primary_plane_fmtmods,
+				       DRM_PLANE_TYPE_PRIMARY, NULL);
+	if (ret) {
+		drm_err(dev, "drm_universal_plane_init() failed: %d\n", ret);
+		return ret;
+	}
+	drm_plane_helper_add(primary_plane, &mgag200_g200eh3_primary_plane_helper_funcs);
+	drm_plane_enable_fb_damage_clips(primary_plane);
+
+	ret = drm_crtc_init_with_planes(dev, crtc, primary_plane, NULL,
+					&mgag200_g200eh3_crtc_funcs, NULL);
+	if (ret) {
+		drm_err(dev, "drm_crtc_init_with_planes() failed: %d\n", ret);
+		return ret;
+	}
+	drm_crtc_helper_add(crtc, &mgag200_g200eh3_crtc_helper_funcs);
+
+	/* FIXME: legacy gamma tables, but atomic gamma doesn't work without */
+	drm_mode_crtc_set_gamma_size(crtc, MGAG200_LUT_SIZE);
+	drm_crtc_enable_color_mgmt(crtc, 0, false, MGAG200_LUT_SIZE);
+
+	encoder->possible_crtcs = drm_crtc_mask(crtc);
+	ret = drm_encoder_init(dev, encoder, &mgag200_g200eh3_dac_encoder_funcs,
+			       DRM_MODE_ENCODER_DAC, NULL);
+	if (ret) {
+		drm_err(dev, "drm_encoder_init() failed: %d\n", ret);
+		return ret;
+	}
+
+	ret = mgag200_i2c_init(mdev, i2c);
+	if (ret) {
+		drm_err(dev, "failed to add DDC bus: %d\n", ret);
+		return ret;
+	}
+
+	ret = drm_connector_init_with_ddc(dev, connector,
+					  &mgag200_g200eh3_vga_connector_funcs,
+					  DRM_MODE_CONNECTOR_VGA,
+					  &i2c->adapter);
+	if (ret) {
+		drm_err(dev, "drm_connector_init_with_ddc() failed: %d\n", ret);
+		return ret;
+	}
+	drm_connector_helper_add(connector, &mgag200_g200eh3_vga_connector_helper_funcs);
+
+	ret = drm_connector_attach_encoder(connector, encoder);
+	if (ret) {
+		drm_err(dev, "drm_connector_attach_encoder() failed: %d\n", ret);
+		return ret;
+	}
+
+	return 0;
+}
+
 /*
  * DRM device
  */
@@ -108,9 +211,15 @@ struct mga_device *mgag200_g200eh3_device_create(struct pci_dev *pdev,
 
 	vram_available = mgag200_device_probe_vram(mdev);
 
-	ret = mgag200_modeset_init(mdev, vram_available);
+	ret = mgag200_mode_config_init(mdev, vram_available);
 	if (ret)
 		return ERR_PTR(ret);
 
+	ret = mgag200_g200eh3_pipeline_init(mdev);
+	if (ret)
+		return ERR_PTR(ret);
+
+	drm_mode_config_reset(dev);
+
 	return mdev;
 }
diff --git a/drivers/gpu/drm/mgag200/mgag200_g200er.c b/drivers/gpu/drm/mgag200/mgag200_g200er.c
index b18fc5862b7c..8dbb61c1a975 100644
--- a/drivers/gpu/drm/mgag200/mgag200_g200er.c
+++ b/drivers/gpu/drm/mgag200/mgag200_g200er.c
@@ -4,7 +4,10 @@
 #include <linux/pci.h>
 
 #include <drm/drm_atomic.h>
+#include <drm/drm_atomic_helper.h>
 #include <drm/drm_drv.h>
+#include <drm/drm_gem_atomic_helper.h>
+#include <drm/drm_probe_helper.h>
 
 #include "mgag200_drv.h"
 
@@ -158,6 +161,106 @@ static void mgag200_g200er_pixpllc_atomic_update(struct drm_crtc *crtc,
 	udelay(50);
 }
 
+/*
+ * Mode-setting pipeline
+ */
+
+static const struct drm_plane_helper_funcs mgag200_g200er_primary_plane_helper_funcs = {
+	MGAG200_PRIMARY_PLANE_HELPER_FUNCS,
+};
+
+static const struct drm_plane_funcs mgag200_g200er_primary_plane_funcs = {
+	MGAG200_PRIMARY_PLANE_FUNCS,
+};
+
+static const struct drm_crtc_helper_funcs mgag200_g200er_crtc_helper_funcs = {
+	MGAG200_CRTC_HELPER_FUNCS,
+};
+
+static const struct drm_crtc_funcs mgag200_g200er_crtc_funcs = {
+	MGAG200_CRTC_FUNCS,
+};
+
+static const struct drm_encoder_funcs mgag200_g200er_dac_encoder_funcs = {
+	MGAG200_DAC_ENCODER_FUNCS,
+};
+
+static const struct drm_connector_helper_funcs mgag200_g200er_vga_connector_helper_funcs = {
+	MGAG200_VGA_CONNECTOR_HELPER_FUNCS,
+};
+
+static const struct drm_connector_funcs mgag200_g200er_vga_connector_funcs = {
+	MGAG200_VGA_CONNECTOR_FUNCS,
+};
+
+static int mgag200_g200er_pipeline_init(struct mga_device *mdev)
+{
+	struct drm_device *dev = &mdev->base;
+	struct drm_plane *primary_plane = &mdev->primary_plane;
+	struct drm_crtc *crtc = &mdev->crtc;
+	struct drm_encoder *encoder = &mdev->encoder;
+	struct mga_i2c_chan *i2c = &mdev->i2c;
+	struct drm_connector *connector = &mdev->connector;
+	int ret;
+
+	ret = drm_universal_plane_init(dev, primary_plane, 0,
+				       &mgag200_g200er_primary_plane_funcs,
+				       mgag200_primary_plane_formats,
+				       mgag200_primary_plane_formats_size,
+				       mgag200_primary_plane_fmtmods,
+				       DRM_PLANE_TYPE_PRIMARY, NULL);
+	if (ret) {
+		drm_err(dev, "drm_universal_plane_init() failed: %d\n", ret);
+		return ret;
+	}
+	drm_plane_helper_add(primary_plane, &mgag200_g200er_primary_plane_helper_funcs);
+	drm_plane_enable_fb_damage_clips(primary_plane);
+
+	ret = drm_crtc_init_with_planes(dev, crtc, primary_plane, NULL,
+					&mgag200_g200er_crtc_funcs, NULL);
+	if (ret) {
+		drm_err(dev, "drm_crtc_init_with_planes() failed: %d\n", ret);
+		return ret;
+	}
+	drm_crtc_helper_add(crtc, &mgag200_g200er_crtc_helper_funcs);
+
+	/* FIXME: legacy gamma tables, but atomic gamma doesn't work without */
+	drm_mode_crtc_set_gamma_size(crtc, MGAG200_LUT_SIZE);
+	drm_crtc_enable_color_mgmt(crtc, 0, false, MGAG200_LUT_SIZE);
+
+	encoder->possible_crtcs = drm_crtc_mask(crtc);
+	ret = drm_encoder_init(dev, encoder, &mgag200_g200er_dac_encoder_funcs,
+			       DRM_MODE_ENCODER_DAC, NULL);
+	if (ret) {
+		drm_err(dev, "drm_encoder_init() failed: %d\n", ret);
+		return ret;
+	}
+
+	ret = mgag200_i2c_init(mdev, i2c);
+	if (ret) {
+		drm_err(dev, "failed to add DDC bus: %d\n", ret);
+		return ret;
+	}
+
+	ret = drm_connector_init_with_ddc(dev, connector,
+					  &mgag200_g200er_vga_connector_funcs,
+					  DRM_MODE_CONNECTOR_VGA,
+					  &i2c->adapter);
+	if (ret) {
+		drm_err(dev, "drm_connector_init_with_ddc() failed: %d\n", ret);
+		return ret;
+	}
+	drm_connector_helper_add(connector, &mgag200_g200er_vga_connector_helper_funcs);
+
+	ret = drm_connector_attach_encoder(connector, encoder);
+	if (ret) {
+		drm_err(dev, "drm_connector_attach_encoder() failed: %d\n", ret);
+		return ret;
+	}
+
+	return 0;
+}
+
 /*
  * DRM device
  */
@@ -198,9 +301,15 @@ struct mga_device *mgag200_g200er_device_create(struct pci_dev *pdev, const stru
 
 	vram_available = mgag200_device_probe_vram(mdev);
 
-	ret = mgag200_modeset_init(mdev, vram_available);
+	ret = mgag200_mode_config_init(mdev, vram_available);
 	if (ret)
 		return ERR_PTR(ret);
 
+	ret = mgag200_g200er_pipeline_init(mdev);
+	if (ret)
+		return ERR_PTR(ret);
+
+	drm_mode_config_reset(dev);
+
 	return mdev;
 }
diff --git a/drivers/gpu/drm/mgag200/mgag200_g200ev.c b/drivers/gpu/drm/mgag200/mgag200_g200ev.c
index 95681796ccd6..996e228de8bf 100644
--- a/drivers/gpu/drm/mgag200/mgag200_g200ev.c
+++ b/drivers/gpu/drm/mgag200/mgag200_g200ev.c
@@ -4,7 +4,10 @@
 #include <linux/pci.h>
 
 #include <drm/drm_atomic.h>
+#include <drm/drm_atomic_helper.h>
 #include <drm/drm_drv.h>
+#include <drm/drm_gem_atomic_helper.h>
+#include <drm/drm_probe_helper.h>
 
 #include "mgag200_drv.h"
 
@@ -174,6 +177,106 @@ static void mgag200_g200ev_pixpllc_atomic_update(struct drm_crtc *crtc,
 	WREG8(DAC_DATA, tmp);
 }
 
+/*
+ * Mode-setting pipeline
+ */
+
+static const struct drm_plane_helper_funcs mgag200_g200ev_primary_plane_helper_funcs = {
+	MGAG200_PRIMARY_PLANE_HELPER_FUNCS,
+};
+
+static const struct drm_plane_funcs mgag200_g200ev_primary_plane_funcs = {
+	MGAG200_PRIMARY_PLANE_FUNCS,
+};
+
+static const struct drm_crtc_helper_funcs mgag200_g200ev_crtc_helper_funcs = {
+	MGAG200_CRTC_HELPER_FUNCS,
+};
+
+static const struct drm_crtc_funcs mgag200_g200ev_crtc_funcs = {
+	MGAG200_CRTC_FUNCS,
+};
+
+static const struct drm_encoder_funcs mgag200_g200ev_dac_encoder_funcs = {
+	MGAG200_DAC_ENCODER_FUNCS,
+};
+
+static const struct drm_connector_helper_funcs mgag200_g200ev_vga_connector_helper_funcs = {
+	MGAG200_VGA_CONNECTOR_HELPER_FUNCS,
+};
+
+static const struct drm_connector_funcs mgag200_g200ev_vga_connector_funcs = {
+	MGAG200_VGA_CONNECTOR_FUNCS,
+};
+
+static int mgag200_g200ev_pipeline_init(struct mga_device *mdev)
+{
+	struct drm_device *dev = &mdev->base;
+	struct drm_plane *primary_plane = &mdev->primary_plane;
+	struct drm_crtc *crtc = &mdev->crtc;
+	struct drm_encoder *encoder = &mdev->encoder;
+	struct mga_i2c_chan *i2c = &mdev->i2c;
+	struct drm_connector *connector = &mdev->connector;
+	int ret;
+
+	ret = drm_universal_plane_init(dev, primary_plane, 0,
+				       &mgag200_g200ev_primary_plane_funcs,
+				       mgag200_primary_plane_formats,
+				       mgag200_primary_plane_formats_size,
+				       mgag200_primary_plane_fmtmods,
+				       DRM_PLANE_TYPE_PRIMARY, NULL);
+	if (ret) {
+		drm_err(dev, "drm_universal_plane_init() failed: %d\n", ret);
+		return ret;
+	}
+	drm_plane_helper_add(primary_plane, &mgag200_g200ev_primary_plane_helper_funcs);
+	drm_plane_enable_fb_damage_clips(primary_plane);
+
+	ret = drm_crtc_init_with_planes(dev, crtc, primary_plane, NULL,
+					&mgag200_g200ev_crtc_funcs, NULL);
+	if (ret) {
+		drm_err(dev, "drm_crtc_init_with_planes() failed: %d\n", ret);
+		return ret;
+	}
+	drm_crtc_helper_add(crtc, &mgag200_g200ev_crtc_helper_funcs);
+
+	/* FIXME: legacy gamma tables, but atomic gamma doesn't work without */
+	drm_mode_crtc_set_gamma_size(crtc, MGAG200_LUT_SIZE);
+	drm_crtc_enable_color_mgmt(crtc, 0, false, MGAG200_LUT_SIZE);
+
+	encoder->possible_crtcs = drm_crtc_mask(crtc);
+	ret = drm_encoder_init(dev, encoder, &mgag200_g200ev_dac_encoder_funcs,
+			       DRM_MODE_ENCODER_DAC, NULL);
+	if (ret) {
+		drm_err(dev, "drm_encoder_init() failed: %d\n", ret);
+		return ret;
+	}
+
+	ret = mgag200_i2c_init(mdev, i2c);
+	if (ret) {
+		drm_err(dev, "failed to add DDC bus: %d\n", ret);
+		return ret;
+	}
+
+	ret = drm_connector_init_with_ddc(dev, connector,
+					  &mgag200_g200ev_vga_connector_funcs,
+					  DRM_MODE_CONNECTOR_VGA,
+					  &i2c->adapter);
+	if (ret) {
+		drm_err(dev, "drm_connector_init_with_ddc() failed: %d\n", ret);
+		return ret;
+	}
+	drm_connector_helper_add(connector, &mgag200_g200ev_vga_connector_helper_funcs);
+
+	ret = drm_connector_attach_encoder(connector, encoder);
+	if (ret) {
+		drm_err(dev, "drm_connector_attach_encoder() failed: %d\n", ret);
+		return ret;
+	}
+
+	return 0;
+}
+
 /*
  * DRM device
  */
@@ -218,9 +321,15 @@ struct mga_device *mgag200_g200ev_device_create(struct pci_dev *pdev, const stru
 
 	vram_available = mgag200_device_probe_vram(mdev);
 
-	ret = mgag200_modeset_init(mdev, vram_available);
+	ret = mgag200_mode_config_init(mdev, vram_available);
 	if (ret)
 		return ERR_PTR(ret);
 
+	ret = mgag200_g200ev_pipeline_init(mdev);
+	if (ret)
+		return ERR_PTR(ret);
+
+	drm_mode_config_reset(dev);
+
 	return mdev;
 }
diff --git a/drivers/gpu/drm/mgag200/mgag200_g200ew3.c b/drivers/gpu/drm/mgag200/mgag200_g200ew3.c
index a7f5e8fe56d0..86ace6b861cd 100644
--- a/drivers/gpu/drm/mgag200/mgag200_g200ew3.c
+++ b/drivers/gpu/drm/mgag200/mgag200_g200ew3.c
@@ -3,7 +3,10 @@
 #include <linux/pci.h>
 
 #include <drm/drm_atomic.h>
+#include <drm/drm_atomic_helper.h>
 #include <drm/drm_drv.h>
+#include <drm/drm_gem_atomic_helper.h>
+#include <drm/drm_probe_helper.h>
 
 #include "mgag200_drv.h"
 
@@ -72,6 +75,106 @@ static int mgag200_g200ew3_pixpllc_atomic_check(struct drm_crtc *crtc,
 	return 0;
 }
 
+/*
+ * Mode-setting pipeline
+ */
+
+static const struct drm_plane_helper_funcs mgag200_g200ew3_primary_plane_helper_funcs = {
+	MGAG200_PRIMARY_PLANE_HELPER_FUNCS,
+};
+
+static const struct drm_plane_funcs mgag200_g200ew3_primary_plane_funcs = {
+	MGAG200_PRIMARY_PLANE_FUNCS,
+};
+
+static const struct drm_crtc_helper_funcs mgag200_g200ew3_crtc_helper_funcs = {
+	MGAG200_CRTC_HELPER_FUNCS,
+};
+
+static const struct drm_crtc_funcs mgag200_g200ew3_crtc_funcs = {
+	MGAG200_CRTC_FUNCS,
+};
+
+static const struct drm_encoder_funcs mgag200_g200ew3_dac_encoder_funcs = {
+	MGAG200_DAC_ENCODER_FUNCS,
+};
+
+static const struct drm_connector_helper_funcs mgag200_g200ew3_vga_connector_helper_funcs = {
+	MGAG200_VGA_CONNECTOR_HELPER_FUNCS,
+};
+
+static const struct drm_connector_funcs mgag200_g200ew3_vga_connector_funcs = {
+	MGAG200_VGA_CONNECTOR_FUNCS,
+};
+
+static int mgag200_g200ew3_pipeline_init(struct mga_device *mdev)
+{
+	struct drm_device *dev = &mdev->base;
+	struct drm_plane *primary_plane = &mdev->primary_plane;
+	struct drm_crtc *crtc = &mdev->crtc;
+	struct drm_encoder *encoder = &mdev->encoder;
+	struct mga_i2c_chan *i2c = &mdev->i2c;
+	struct drm_connector *connector = &mdev->connector;
+	int ret;
+
+	ret = drm_universal_plane_init(dev, primary_plane, 0,
+				       &mgag200_g200ew3_primary_plane_funcs,
+				       mgag200_primary_plane_formats,
+				       mgag200_primary_plane_formats_size,
+				       mgag200_primary_plane_fmtmods,
+				       DRM_PLANE_TYPE_PRIMARY, NULL);
+	if (ret) {
+		drm_err(dev, "drm_universal_plane_init() failed: %d\n", ret);
+		return ret;
+	}
+	drm_plane_helper_add(primary_plane, &mgag200_g200ew3_primary_plane_helper_funcs);
+	drm_plane_enable_fb_damage_clips(primary_plane);
+
+	ret = drm_crtc_init_with_planes(dev, crtc, primary_plane, NULL,
+					&mgag200_g200ew3_crtc_funcs, NULL);
+	if (ret) {
+		drm_err(dev, "drm_crtc_init_with_planes() failed: %d\n", ret);
+		return ret;
+	}
+	drm_crtc_helper_add(crtc, &mgag200_g200ew3_crtc_helper_funcs);
+
+	/* FIXME: legacy gamma tables, but atomic gamma doesn't work without */
+	drm_mode_crtc_set_gamma_size(crtc, MGAG200_LUT_SIZE);
+	drm_crtc_enable_color_mgmt(crtc, 0, false, MGAG200_LUT_SIZE);
+
+	encoder->possible_crtcs = drm_crtc_mask(crtc);
+	ret = drm_encoder_init(dev, encoder, &mgag200_g200ew3_dac_encoder_funcs,
+			       DRM_MODE_ENCODER_DAC, NULL);
+	if (ret) {
+		drm_err(dev, "drm_encoder_init() failed: %d\n", ret);
+		return ret;
+	}
+
+	ret = mgag200_i2c_init(mdev, i2c);
+	if (ret) {
+		drm_err(dev, "failed to add DDC bus: %d\n", ret);
+		return ret;
+	}
+
+	ret = drm_connector_init_with_ddc(dev, connector,
+					  &mgag200_g200ew3_vga_connector_funcs,
+					  DRM_MODE_CONNECTOR_VGA,
+					  &i2c->adapter);
+	if (ret) {
+		drm_err(dev, "drm_connector_init_with_ddc() failed: %d\n", ret);
+		return ret;
+	}
+	drm_connector_helper_add(connector, &mgag200_g200ew3_vga_connector_helper_funcs);
+
+	ret = drm_connector_attach_encoder(connector, encoder);
+	if (ret) {
+		drm_err(dev, "drm_connector_attach_encoder() failed: %d\n", ret);
+		return ret;
+	}
+
+	return 0;
+}
+
 /*
  * DRM device
  */
@@ -128,9 +231,15 @@ struct mga_device *mgag200_g200ew3_device_create(struct pci_dev *pdev,
 
 	vram_available = mgag200_g200ew3_device_probe_vram(mdev);
 
-	ret = mgag200_modeset_init(mdev, vram_available);
+	ret = mgag200_mode_config_init(mdev, vram_available);
 	if (ret)
 		return ERR_PTR(ret);
 
+	ret = mgag200_g200ew3_pipeline_init(mdev);
+	if (ret)
+		return ERR_PTR(ret);
+
+	drm_mode_config_reset(dev);
+
 	return mdev;
 }
diff --git a/drivers/gpu/drm/mgag200/mgag200_g200se.c b/drivers/gpu/drm/mgag200/mgag200_g200se.c
index 04637b42af77..59191b0c9f2e 100644
--- a/drivers/gpu/drm/mgag200/mgag200_g200se.c
+++ b/drivers/gpu/drm/mgag200/mgag200_g200se.c
@@ -4,7 +4,10 @@
 #include <linux/pci.h>
 
 #include <drm/drm_atomic.h>
+#include <drm/drm_atomic_helper.h>
 #include <drm/drm_drv.h>
+#include <drm/drm_gem_atomic_helper.h>
+#include <drm/drm_probe_helper.h>
 
 #include "mgag200_drv.h"
 
@@ -265,6 +268,106 @@ static void mgag200_g200se_04_pixpllc_atomic_update(struct drm_crtc *crtc,
 	WREG_DAC(0x1a, 0x01);
 }
 
+/*
+ * Mode-setting pipeline
+ */
+
+static const struct drm_plane_helper_funcs mgag200_g200se_primary_plane_helper_funcs = {
+	MGAG200_PRIMARY_PLANE_HELPER_FUNCS,
+};
+
+static const struct drm_plane_funcs mgag200_g200se_primary_plane_funcs = {
+	MGAG200_PRIMARY_PLANE_FUNCS,
+};
+
+static const struct drm_crtc_helper_funcs mgag200_g200se_crtc_helper_funcs = {
+	MGAG200_CRTC_HELPER_FUNCS,
+};
+
+static const struct drm_crtc_funcs mgag200_g200se_crtc_funcs = {
+	MGAG200_CRTC_FUNCS,
+};
+
+static const struct drm_encoder_funcs mgag200_g200se_dac_encoder_funcs = {
+	MGAG200_DAC_ENCODER_FUNCS,
+};
+
+static const struct drm_connector_helper_funcs mgag200_g200se_vga_connector_helper_funcs = {
+	MGAG200_VGA_CONNECTOR_HELPER_FUNCS,
+};
+
+static const struct drm_connector_funcs mgag200_g200se_vga_connector_funcs = {
+	MGAG200_VGA_CONNECTOR_FUNCS,
+};
+
+static int mgag200_g200se_pipeline_init(struct mga_device *mdev)
+{
+	struct drm_device *dev = &mdev->base;
+	struct drm_plane *primary_plane = &mdev->primary_plane;
+	struct drm_crtc *crtc = &mdev->crtc;
+	struct drm_encoder *encoder = &mdev->encoder;
+	struct mga_i2c_chan *i2c = &mdev->i2c;
+	struct drm_connector *connector = &mdev->connector;
+	int ret;
+
+	ret = drm_universal_plane_init(dev, primary_plane, 0,
+				       &mgag200_g200se_primary_plane_funcs,
+				       mgag200_primary_plane_formats,
+				       mgag200_primary_plane_formats_size,
+				       mgag200_primary_plane_fmtmods,
+				       DRM_PLANE_TYPE_PRIMARY, NULL);
+	if (ret) {
+		drm_err(dev, "drm_universal_plane_init() failed: %d\n", ret);
+		return ret;
+	}
+	drm_plane_helper_add(primary_plane, &mgag200_g200se_primary_plane_helper_funcs);
+	drm_plane_enable_fb_damage_clips(primary_plane);
+
+	ret = drm_crtc_init_with_planes(dev, crtc, primary_plane, NULL,
+					&mgag200_g200se_crtc_funcs, NULL);
+	if (ret) {
+		drm_err(dev, "drm_crtc_init_with_planes() failed: %d\n", ret);
+		return ret;
+	}
+	drm_crtc_helper_add(crtc, &mgag200_g200se_crtc_helper_funcs);
+
+	/* FIXME: legacy gamma tables, but atomic gamma doesn't work without */
+	drm_mode_crtc_set_gamma_size(crtc, MGAG200_LUT_SIZE);
+	drm_crtc_enable_color_mgmt(crtc, 0, false, MGAG200_LUT_SIZE);
+
+	encoder->possible_crtcs = drm_crtc_mask(crtc);
+	ret = drm_encoder_init(dev, encoder, &mgag200_g200se_dac_encoder_funcs,
+			       DRM_MODE_ENCODER_DAC, NULL);
+	if (ret) {
+		drm_err(dev, "drm_encoder_init() failed: %d\n", ret);
+		return ret;
+	}
+
+	ret = mgag200_i2c_init(mdev, i2c);
+	if (ret) {
+		drm_err(dev, "failed to add DDC bus: %d\n", ret);
+		return ret;
+	}
+
+	ret = drm_connector_init_with_ddc(dev, connector,
+					  &mgag200_g200se_vga_connector_funcs,
+					  DRM_MODE_CONNECTOR_VGA,
+					  &i2c->adapter);
+	if (ret) {
+		drm_err(dev, "drm_connector_init_with_ddc() failed: %d\n", ret);
+		return ret;
+	}
+	drm_connector_helper_add(connector, &mgag200_g200se_vga_connector_helper_funcs);
+
+	ret = drm_connector_attach_encoder(connector, encoder);
+	if (ret) {
+		drm_err(dev, "drm_connector_attach_encoder() failed: %d\n", ret);
+		return ret;
+	}
+
+	return 0;
+}
+
 /*
  * DRM device
  */
@@ -377,9 +480,15 @@ struct mga_device *mgag200_g200se_device_create(struct pci_dev *pdev, const stru
 
 	vram_available = mgag200_device_probe_vram(mdev);
 
-	ret = mgag200_modeset_init(mdev, vram_available);
+	ret = mgag200_mode_config_init(mdev, vram_available);
 	if (ret)
 		return ERR_PTR(ret);
 
+	ret = mgag200_g200se_pipeline_init(mdev);
+	if (ret)
+		return ERR_PTR(ret);
+
+	drm_mode_config_reset(dev);
+
 	return mdev;
 }
diff --git a/drivers/gpu/drm/mgag200/mgag200_g200wb.c b/drivers/gpu/drm/mgag200/mgag200_g200wb.c
index f71b786079fc..2a7812adf2cd 100644
--- a/drivers/gpu/drm/mgag200/mgag200_g200wb.c
+++ b/drivers/gpu/drm/mgag200/mgag200_g200wb.c
@@ -4,7 +4,10 @@
 #include <linux/pci.h>
 
 #include <drm/drm_atomic.h>
+#include <drm/drm_atomic_helper.h>
 #include <drm/drm_drv.h>
+#include <drm/drm_gem_atomic_helper.h>
+#include <drm/drm_probe_helper.h>
 
 #include "mgag200_drv.h"
 
@@ -216,6 +219,106 @@ void mgag200_g200wb_pixpllc_atomic_update(struct drm_crtc *crtc,
 	WREG_DAC(MGA1064_REMHEADCTL, tmp);
 }
 
+/*
+ * Mode-setting pipeline
+ */
+
+static const struct drm_plane_helper_funcs mgag200_g200wb_primary_plane_helper_funcs = {
+	MGAG200_PRIMARY_PLANE_HELPER_FUNCS,
+};
+
+static const struct drm_plane_funcs mgag200_g200wb_primary_plane_funcs = {
+	MGAG200_PRIMARY_PLANE_FUNCS,
+};
+
+static const struct drm_crtc_helper_funcs mgag200_g200wb_crtc_helper_funcs = {
+	MGAG200_CRTC_HELPER_FUNCS,
+};
+
+static const struct drm_crtc_funcs mgag200_g200wb_crtc_funcs = {
+	MGAG200_CRTC_FUNCS,
+};
+
+static const struct drm_encoder_funcs mgag200_g200wb_dac_encoder_funcs = {
+	MGAG200_DAC_ENCODER_FUNCS,
+};
+
+static const struct drm_connector_helper_funcs mgag200_g200wb_vga_connector_helper_funcs = {
+	MGAG200_VGA_CONNECTOR_HELPER_FUNCS,
+};
+
+static const struct drm_connector_funcs mgag200_g200wb_vga_connector_funcs = {
+	MGAG200_VGA_CONNECTOR_FUNCS,
+};
+
+static int mgag200_g200wb_pipeline_init(struct mga_device *mdev)
+{
+	struct drm_device *dev = &mdev->base;
+	struct drm_plane *primary_plane = &mdev->primary_plane;
+	struct drm_crtc *crtc = &mdev->crtc;
+	struct drm_encoder *encoder = &mdev->encoder;
+	struct mga_i2c_chan *i2c = &mdev->i2c;
+	struct drm_connector *connector = &mdev->connector;
+	int ret;
+
+	ret = drm_universal_plane_init(dev, primary_plane, 0,
+				       &mgag200_g200wb_primary_plane_funcs,
+				       mgag200_primary_plane_formats,
+				       mgag200_primary_plane_formats_size,
+				       mgag200_primary_plane_fmtmods,
+				       DRM_PLANE_TYPE_PRIMARY, NULL);
+	if (ret) {
+		drm_err(dev, "drm_universal_plane_init() failed: %d\n", ret);
+		return ret;
+	}
+	drm_plane_helper_add(primary_plane, &mgag200_g200wb_primary_plane_helper_funcs);
+	drm_plane_enable_fb_damage_clips(primary_plane);
+
+	ret = drm_crtc_init_with_planes(dev, crtc, primary_plane, NULL,
+					&mgag200_g200wb_crtc_funcs, NULL);
+	if (ret) {
+		drm_err(dev, "drm_crtc_init_with_planes() failed: %d\n", ret);
+		return ret;
+	}
+	drm_crtc_helper_add(crtc, &mgag200_g200wb_crtc_helper_funcs);
+
+	/* FIXME: legacy gamma tables, but atomic gamma doesn't work without */
+	drm_mode_crtc_set_gamma_size(crtc, MGAG200_LUT_SIZE);
+	drm_crtc_enable_color_mgmt(crtc, 0, false, MGAG200_LUT_SIZE);
+
+	encoder->possible_crtcs = drm_crtc_mask(crtc);
+	ret = drm_encoder_init(dev, encoder, &mgag200_g200wb_dac_encoder_funcs,
+			       DRM_MODE_ENCODER_DAC, NULL);
+	if (ret) {
+		drm_err(dev, "drm_encoder_init() failed: %d\n", ret);
+		return ret;
+	}
+
+	ret = mgag200_i2c_init(mdev, i2c);
+	if (ret) {
+		drm_err(dev, "failed to add DDC bus: %d\n", ret);
+		return ret;
+	}
+
+	ret = drm_connector_init_with_ddc(dev, connector,
+					  &mgag200_g200wb_vga_connector_funcs,
+					  DRM_MODE_CONNECTOR_VGA,
+					  &i2c->adapter);
+	if (ret) {
+		drm_err(dev, "drm_connector_init_with_ddc() failed: %d\n", ret);
+		return ret;
+	}
+	drm_connector_helper_add(connector, &mgag200_g200wb_vga_connector_helper_funcs);
+
+	ret = drm_connector_attach_encoder(connector, encoder);
+	if (ret) {
+		drm_err(dev, "drm_connector_attach_encoder() failed: %d\n", ret);
+		return ret;
+	}
+
+	return 0;
+}
+
 /*
  * DRM device
  */
@@ -262,9 +365,15 @@ struct mga_device *mgag200_g200wb_device_create(struct pci_dev *pdev, const stru
 
 	vram_available = mgag200_device_probe_vram(mdev);
 
-	ret = mgag200_modeset_init(mdev, vram_available);
+	ret = mgag200_mode_config_init(mdev, vram_available);
 	if (ret)
 		return ERR_PTR(ret);
 
+	ret = mgag200_g200wb_pipeline_init(mdev);
+	if (ret)
+		return ERR_PTR(ret);
+
+	drm_mode_config_reset(dev);
+
 	return mdev;
 }
diff --git a/drivers/gpu/drm/mgag200/mgag200_mode.c b/drivers/gpu/drm/mgag200/mgag200_mode.c
index e3e40b25caa6..639c33ce6090 100644
--- a/drivers/gpu/drm/mgag200/mgag200_mode.c
+++ b/drivers/gpu/drm/mgag200/mgag200_mode.c
@@ -13,8 +13,6 @@
 
 #include <drm/drm_atomic.h>
 #include <drm/drm_atomic_helper.h>
-#include <drm/drm_atomic_state_helper.h>
-#include <drm/drm_crtc_helper.h>
 #include <drm/drm_damage_helper.h>
 #include <drm/drm_format_helper.h>
 #include <drm/drm_fourcc.h>
@@ -22,13 +20,10 @@
 #include <drm/drm_gem_atomic_helper.h>
 #include <drm/drm_gem_framebuffer_helper.h>
 #include <drm/drm_plane_helper.h>
-#include <drm/drm_print.h>
 #include <drm/drm_probe_helper.h>
 
 #include "mgag200_drv.h"
 
-#define MGAG200_LUT_SIZE 256
-
 /*
  * This file contains setup code for the CRTC.
  */
@@ -516,19 +511,21 @@ static void mgag200_handle_damage(struct mga_device *mdev, const struct iosys_ma
  * Primary plane
  */
 
-static const uint32_t mgag200_primary_plane_formats[] = {
+const uint32_t mgag200_primary_plane_formats[] = {
 	DRM_FORMAT_XRGB8888,
 	DRM_FORMAT_RGB565,
 	DRM_FORMAT_RGB888,
 };
 
-static const uint64_t mgag200_primary_plane_fmtmods[] = {
+const size_t mgag200_primary_plane_formats_size = ARRAY_SIZE(mgag200_primary_plane_formats);
+
+const uint64_t mgag200_primary_plane_fmtmods[] = {
 	DRM_FORMAT_MOD_LINEAR,
 	DRM_FORMAT_MOD_INVALID
 };
 
-static int mgag200_primary_plane_helper_atomic_check(struct drm_plane *plane,
-						     struct drm_atomic_state *state)
+int mgag200_primary_plane_helper_atomic_check(struct drm_plane *plane,
+					      struct drm_atomic_state *state)
 {
 	struct drm_plane_state *new_plane_state = drm_atomic_get_new_plane_state(state, plane);
 	struct drm_framebuffer *new_fb = new_plane_state->fb;
@@ -564,8 +561,8 @@ static int mgag200_primary_plane_helper_atomic_check(struct drm_plane *plane,
 	return 0;
 }
 
-static void mgag200_primary_plane_helper_atomic_update(struct drm_plane *plane,
-						       struct drm_atomic_state *old_state)
+void mgag200_primary_plane_helper_atomic_update(struct drm_plane *plane,
+						struct drm_atomic_state *old_state)
 {
 	struct drm_device *dev = plane->dev;
 	struct mga_device *mdev = to_mga_device(dev);
@@ -595,8 +592,8 @@ static void mgag200_primary_plane_helper_atomic_update(struct drm_plane *plane,
 	msleep(20);
 }
 
-static void mgag200_primary_plane_helper_atomic_disable(struct drm_plane *plane,
-							struct drm_atomic_state *old_state)
+void mgag200_primary_plane_helper_atomic_disable(struct drm_plane *plane,
+						 struct drm_atomic_state *old_state)
 {
 	struct drm_device *dev = plane->dev;
 	struct mga_device *mdev = to_mga_device(dev);
@@ -608,26 +605,12 @@ static void mgag200_primary_plane_helper_atomic_disable(struct drm_plane *plane,
 	msleep(20);
 }
 
-static const struct drm_plane_helper_funcs mgag200_primary_plane_helper_funcs = {
-	DRM_GEM_SHADOW_PLANE_HELPER_FUNCS,
-	.atomic_check = mgag200_primary_plane_helper_atomic_check,
-	.atomic_update = mgag200_primary_plane_helper_atomic_update,
-	.atomic_disable = mgag200_primary_plane_helper_atomic_disable,
-};
-
-static const struct drm_plane_funcs mgag200_primary_plane_funcs = {
-	.update_plane = drm_atomic_helper_update_plane,
-	.disable_plane = drm_atomic_helper_disable_plane,
-	.destroy = drm_plane_cleanup,
-	DRM_GEM_SHADOW_PLANE_FUNCS,
-};
-
 /*
  * CRTC
  */
 
-static enum drm_mode_status mgag200_crtc_helper_mode_valid(struct drm_crtc *crtc,
-							   const struct drm_display_mode *mode)
+enum drm_mode_status mgag200_crtc_helper_mode_valid(struct drm_crtc *crtc,
+						    const struct drm_display_mode *mode)
 {
 	struct mga_device *mdev = to_mga_device(crtc->dev);
 	const struct mgag200_device_info *info = mdev->info;
@@ -656,8 +639,7 @@ static enum drm_mode_status mgag200_crtc_helper_mode_valid(struct drm_crtc *crtc
 	return MODE_OK;
 }
 
-static int mgag200_crtc_helper_atomic_check(struct drm_crtc *crtc,
-					    struct drm_atomic_state *state)
+int mgag200_crtc_helper_atomic_check(struct drm_crtc *crtc, struct drm_atomic_state *state)
 {
 	struct drm_device *dev = crtc->dev;
 	struct mga_device *mdev = to_mga_device(dev);
@@ -692,8 +674,7 @@ static int mgag200_crtc_helper_atomic_check(struct drm_crtc *crtc,
 	return drm_atomic_add_affected_planes(state, crtc);
 }
 
-static void mgag200_crtc_helper_atomic_flush(struct drm_crtc *crtc,
-					     struct drm_atomic_state *old_state)
+void mgag200_crtc_helper_atomic_flush(struct drm_crtc *crtc, struct drm_atomic_state *old_state)
 {
 	struct drm_crtc_state *crtc_state = crtc->state;
 	struct mgag200_crtc_state *mgag200_crtc_state = to_mgag200_crtc_state(crtc_state);
@@ -710,8 +691,7 @@ static void mgag200_crtc_helper_atomic_flush(struct drm_crtc *crtc,
 	}
 }
 
-static void mgag200_crtc_helper_atomic_enable(struct drm_crtc *crtc,
-					      struct drm_atomic_state *old_state)
+void mgag200_crtc_helper_atomic_enable(struct drm_crtc *crtc, struct drm_atomic_state *old_state)
 {
 	struct drm_device *dev = crtc->dev;
 	struct mga_device *mdev = to_mga_device(dev);
@@ -744,8 +724,7 @@ static void mgag200_crtc_helper_atomic_enable(struct drm_crtc *crtc,
 		funcs->enable_vidrst(mdev);
 }
 
-static void mgag200_crtc_helper_atomic_disable(struct drm_crtc *crtc,
-					       struct drm_atomic_state *old_state)
+void mgag200_crtc_helper_atomic_disable(struct drm_crtc *crtc, struct drm_atomic_state *old_state)
 {
 	struct mga_device *mdev = to_mga_device(crtc->dev);
 	const struct mgag200_device_funcs *funcs = mdev->funcs;
@@ -759,15 +738,7 @@ static void mgag200_crtc_helper_atomic_disable(struct drm_crtc *crtc,
 		funcs->enable_vidrst(mdev);
 }
 
-static const struct drm_crtc_helper_funcs mgag200_crtc_helper_funcs = {
-	.mode_valid = mgag200_crtc_helper_mode_valid,
-	.atomic_check = mgag200_crtc_helper_atomic_check,
-	.atomic_flush = mgag200_crtc_helper_atomic_flush,
-	.atomic_enable = mgag200_crtc_helper_atomic_enable,
-	.atomic_disable = mgag200_crtc_helper_atomic_disable,
-};
-
-static void mgag200_crtc_reset(struct drm_crtc *crtc)
+void mgag200_crtc_reset(struct drm_crtc *crtc)
 {
 	struct mgag200_crtc_state *mgag200_crtc_state;
 
@@ -781,7 +752,7 @@ static void mgag200_crtc_reset(struct drm_crtc *crtc)
 		__drm_atomic_helper_crtc_reset(crtc, NULL);
 }
 
-static struct drm_crtc_state *mgag200_crtc_atomic_duplicate_state(struct drm_crtc *crtc)
+struct drm_crtc_state *mgag200_crtc_atomic_duplicate_state(struct drm_crtc *crtc)
 {
 	struct drm_crtc_state *crtc_state = crtc->state;
 	struct mgag200_crtc_state *mgag200_crtc_state = to_mgag200_crtc_state(crtc_state);
@@ -802,8 +773,7 @@ static struct drm_crtc_state *mgag200_crtc_atomic_duplicate_state(struct drm_crt
 	return &new_mgag200_crtc_state->base;
 }
 
-static void mgag200_crtc_atomic_destroy_state(struct drm_crtc *crtc,
-					      struct drm_crtc_state *crtc_state)
+void mgag200_crtc_atomic_destroy_state(struct drm_crtc *crtc, struct drm_crtc_state *crtc_state)
 {
 	struct mgag200_crtc_state *mgag200_crtc_state = to_mgag200_crtc_state(crtc_state);
 
@@ -811,28 +781,11 @@ static void mgag200_crtc_atomic_destroy_state(struct drm_crtc *crtc,
 	kfree(mgag200_crtc_state);
 }
 
-static const struct drm_crtc_funcs mgag200_crtc_funcs = {
-	.reset = mgag200_crtc_reset,
-	.destroy = drm_crtc_cleanup,
-	.set_config = drm_atomic_helper_set_config,
-	.page_flip = drm_atomic_helper_page_flip,
-	.atomic_duplicate_state = mgag200_crtc_atomic_duplicate_state,
-	.atomic_destroy_state = mgag200_crtc_atomic_destroy_state,
-};
-
-/*
- * Encoder
- */
-
-static const struct drm_encoder_funcs mgag200_dac_encoder_funcs = {
-	.destroy = drm_encoder_cleanup,
-};
-
 /*
  * Connector
  */
 
-static int mgag200_vga_connector_helper_get_modes(struct drm_connector *connector)
+int mgag200_vga_connector_helper_get_modes(struct drm_connector *connector)
 {
 	struct mga_device *mdev = to_mga_device(connector->dev);
 	int ret;
@@ -848,18 +801,6 @@ static int mgag200_vga_connector_helper_get_modes(struct drm_connector *connecto
 	return ret;
 }
 
-static const struct drm_connector_helper_funcs mga_vga_connector_helper_funcs = {
-	.get_modes  = mgag200_vga_connector_helper_get_modes,
-};
-
-static const struct drm_connector_funcs mga_vga_connector_funcs = {
-	.reset                  = drm_atomic_helper_connector_reset,
-	.fill_modes             = drm_helper_probe_single_connector_modes,
-	.destroy                = drm_connector_cleanup,
-	.atomic_duplicate_state = drm_atomic_helper_connector_duplicate_state,
-	.atomic_destroy_state   = drm_atomic_helper_connector_destroy_state,
-};
-
 /*
  * Mode config
  */
@@ -946,7 +887,7 @@ static const struct drm_mode_config_funcs mgag200_mode_config_funcs = {
 	.atomic_commit = drm_atomic_helper_commit,
 };
 
-static int mgag200_mode_config_init(struct mga_device *mdev, resource_size_t vram_available)
+int mgag200_mode_config_init(struct mga_device *mdev, resource_size_t vram_available)
 {
 	struct drm_device *dev = &mdev->base;
 	int ret;
@@ -968,88 +909,3 @@ static int mgag200_mode_config_init(struct mga_device *mdev, resource_size_t vra
 
 	return 0;
 }
-
-static int mgag200_pipeline_init(struct mga_device *mdev)
-{
-	struct drm_device *dev = &mdev->base;
-	struct drm_plane *primary_plane = &mdev->primary_plane;
-	struct drm_crtc *crtc = &mdev->crtc;
-	struct drm_encoder *encoder = &mdev->encoder;
-	struct mga_i2c_chan *i2c = &mdev->i2c;
-	struct drm_connector *connector = &mdev->connector;
-	int ret;
-
-	ret = drm_universal_plane_init(dev, primary_plane, 0,
-				       &mgag200_primary_plane_funcs,
-				       mgag200_primary_plane_formats,
-				       ARRAY_SIZE(mgag200_primary_plane_formats),
-				       mgag200_primary_plane_fmtmods,
-				       DRM_PLANE_TYPE_PRIMARY, NULL);
-	if (ret) {
-		drm_err(dev, "drm_universal_plane_init() failed: %d\n", ret);
-		return ret;
-	}
-	drm_plane_helper_add(primary_plane, &mgag200_primary_plane_helper_funcs);
-	drm_plane_enable_fb_damage_clips(primary_plane);
-
-	ret = drm_crtc_init_with_planes(dev, crtc, primary_plane, NULL, &mgag200_crtc_funcs, NULL);
-	if (ret) {
-		drm_err(dev, "drm_crtc_init_with_planes() failed: %d\n", ret);
-		return ret;
-	}
-	drm_crtc_helper_add(crtc, &mgag200_crtc_helper_funcs);
-
-	/* FIXME: legacy gamma tables, but atomic gamma doesn't work without */
-	drm_mode_crtc_set_gamma_size(crtc, MGAG200_LUT_SIZE);
-	drm_crtc_enable_color_mgmt(crtc, 0, false, MGAG200_LUT_SIZE);
-
-	encoder->possible_crtcs = drm_crtc_mask(crtc);
-	ret = drm_encoder_init(dev, encoder, &mgag200_dac_encoder_funcs,
-			       DRM_MODE_ENCODER_DAC, NULL);
-	if (ret) {
-		drm_err(dev, "drm_encoder_init() failed: %d\n", ret);
-		return ret;
-	}
-
-	ret = mgag200_i2c_init(mdev, i2c);
-	if (ret) {
-		drm_err(dev, "failed to add DDC bus: %d\n", ret);
-		return ret;
-	}
-
-	ret = drm_connector_init_with_ddc(dev, connector,
-					  &mga_vga_connector_funcs,
-					  DRM_MODE_CONNECTOR_VGA,
-					  &i2c->adapter);
-	if (ret) {
-		drm_err(dev, "drm_connector_init_with_ddc() failed: %d\n", ret);
-		return ret;
-	}
-	drm_connector_helper_add(connector, &mga_vga_connector_helper_funcs);
-
-	ret = drm_connector_attach_encoder(connector, encoder);
-	if (ret) {
-		drm_err(dev, "drm_connector_attach_encoder() failed: %d\n", ret);
-		return ret;
-	}
-
-	return 0;
-}
-
-int mgag200_modeset_init(struct mga_device *mdev, resource_size_t vram_available)
-{
-	struct drm_device *dev = &mdev->base;
-	int ret;
-
-	ret = mgag200_mode_config_init(mdev, vram_available);
-	if (ret)
-		return ret;
-
-	ret = mgag200_pipeline_init(mdev);
-	if (ret)
-		return ret;
-
-	drm_mode_config_reset(dev);
-
-	return 0;
-}
-- 
2.36.1


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

* [PATCH 13/14] drm/mgag200: Move CRTC atomic_enable to model-specfic code
  2022-07-08  9:39 [PATCH 00/14] drm/mgag200: Move model-specific code into separate functions Thomas Zimmermann
                   ` (11 preceding siblings ...)
  2022-07-08  9:39 ` [PATCH 12/14] drm/mgag200: Move mode-config to model-specific code Thomas Zimmermann
@ 2022-07-08  9:39 ` Thomas Zimmermann
  2022-07-08  9:39 ` [PATCH 14/14] drm/mgag200: Remove type field from struct mga_device Thomas Zimmermann
  2022-07-08 17:22 ` [PATCH 00/14] drm/mgag200: Move model-specific code into separate functions Sam Ravnborg
  14 siblings, 0 replies; 28+ messages in thread
From: Thomas Zimmermann @ 2022-07-08  9:39 UTC (permalink / raw)
  To: airlied, airlied, jfalempe, daniel; +Cc: Thomas Zimmermann, dri-devel

The CRTC atomic_enable helper contains per-model branches for
G200ER, G200EV and G200SE devices. Implement a dedicated helper
for each of them and remove the branches from the shared helper.

Signed-off-by: Thomas Zimmermann <tzimmermann@suse.de>
---
 drivers/gpu/drm/mgag200/mgag200_drv.h    |  6 +-
 drivers/gpu/drm/mgag200/mgag200_g200er.c | 50 ++++++++++++++-
 drivers/gpu/drm/mgag200/mgag200_g200ev.c | 39 ++++++++++-
 drivers/gpu/drm/mgag200/mgag200_g200se.c | 80 ++++++++++++++++++++++-
 drivers/gpu/drm/mgag200/mgag200_mode.c   | 82 +-----------------------
 5 files changed, 172 insertions(+), 85 deletions(-)

diff --git a/drivers/gpu/drm/mgag200/mgag200_drv.h b/drivers/gpu/drm/mgag200/mgag200_drv.h
index 69bdd61e9d82..f3e114d462b2 100644
--- a/drivers/gpu/drm/mgag200/mgag200_drv.h
+++ b/drivers/gpu/drm/mgag200/mgag200_drv.h
@@ -183,8 +183,6 @@ enum mga_type {
 	G200_EW3,
 };
 
-#define IS_G200_SE(mdev) (mdev->type == G200_SE_A || mdev->type == G200_SE_B)
-
 struct mgag200_device_info {
 	u16 max_hdisplay;
 	u16 max_vdisplay;
@@ -411,7 +409,9 @@ int mgag200_vga_connector_helper_get_modes(struct drm_connector *connector);
 	.atomic_duplicate_state = drm_atomic_helper_connector_duplicate_state, \
 	.atomic_destroy_state   = drm_atomic_helper_connector_destroy_state
 
-resource_size_t mgag200_device_probe_vram(struct mga_device *mdev);
+void mgag200_set_mode_regs(struct mga_device *mdev, const struct drm_display_mode *mode);
+void mgag200_set_format_regs(struct mga_device *mdev, const struct drm_format_info *format);
+void mgag200_enable_display(struct mga_device *mdev);
 void mgag200_init_registers(struct mga_device *mdev);
 int mgag200_mode_config_init(struct mga_device *mdev, resource_size_t vram_available);
 
diff --git a/drivers/gpu/drm/mgag200/mgag200_g200er.c b/drivers/gpu/drm/mgag200/mgag200_g200er.c
index 8dbb61c1a975..42830b9ed5ac 100644
--- a/drivers/gpu/drm/mgag200/mgag200_g200er.c
+++ b/drivers/gpu/drm/mgag200/mgag200_g200er.c
@@ -45,6 +45,22 @@ static void mgag200_g200er_init_registers(struct mga_device *mdev)
 	WREG_ECRT(0x24, 0x5); /* G200ER specific */
 }
 
+static void mgag200_g200er_reset_tagfifo(struct mga_device *mdev)
+{
+	static const uint32_t RESET_FLAG = 0x00200000; /* undocumented magic value */
+	u32 memctl;
+
+	memctl = RREG32(MGAREG_MEMCTL);
+
+	memctl |= RESET_FLAG;
+	WREG32(MGAREG_MEMCTL, memctl);
+
+	udelay(1000);
+
+	memctl &= ~RESET_FLAG;
+	WREG32(MGAREG_MEMCTL, memctl);
+}
+
 /*
  * PIXPLLC
  */
@@ -173,8 +189,40 @@ static const struct drm_plane_funcs mgag200_g200er_primary_plane_funcs = {
 	MGAG200_PRIMARY_PLANE_FUNCS,
 };
 
+static void mgag200_g200er_crtc_helper_atomic_enable(struct drm_crtc *crtc,
+						     struct drm_atomic_state *old_state)
+{
+	struct drm_device *dev = crtc->dev;
+	struct mga_device *mdev = to_mga_device(dev);
+	const struct mgag200_device_funcs *funcs = mdev->funcs;
+	struct drm_crtc_state *crtc_state = crtc->state;
+	struct drm_display_mode *adjusted_mode = &crtc_state->adjusted_mode;
+	struct mgag200_crtc_state *mgag200_crtc_state = to_mgag200_crtc_state(crtc_state);
+	const struct drm_format_info *format = mgag200_crtc_state->format;
+
+	if (funcs->disable_vidrst)
+		funcs->disable_vidrst(mdev);
+
+	mgag200_set_format_regs(mdev, format);
+	mgag200_set_mode_regs(mdev, adjusted_mode);
+
+	if (funcs->pixpllc_atomic_update)
+		funcs->pixpllc_atomic_update(crtc, old_state);
+
+	mgag200_g200er_reset_tagfifo(mdev);
+
+	mgag200_enable_display(mdev);
+
+	if (funcs->enable_vidrst)
+		funcs->enable_vidrst(mdev);
+}
+
 static const struct drm_crtc_helper_funcs mgag200_g200er_crtc_helper_funcs = {
-	MGAG200_CRTC_HELPER_FUNCS,
+	.mode_valid = mgag200_crtc_helper_mode_valid,
+	.atomic_check = mgag200_crtc_helper_atomic_check,
+	.atomic_flush = mgag200_crtc_helper_atomic_flush,
+	.atomic_enable = mgag200_g200er_crtc_helper_atomic_enable,
+	.atomic_disable = mgag200_crtc_helper_atomic_disable
 };
 
 static const struct drm_crtc_funcs mgag200_g200er_crtc_funcs = {
diff --git a/drivers/gpu/drm/mgag200/mgag200_g200ev.c b/drivers/gpu/drm/mgag200/mgag200_g200ev.c
index 996e228de8bf..72ebea02a7ca 100644
--- a/drivers/gpu/drm/mgag200/mgag200_g200ev.c
+++ b/drivers/gpu/drm/mgag200/mgag200_g200ev.c
@@ -49,6 +49,11 @@ static void mgag200_g200ev_init_registers(struct mga_device *mdev)
 	mgag200_init_registers(mdev);
 }
 
+static void mgag200_g200ev_set_hiprilvl(struct mga_device *mdev)
+{
+	WREG_ECRT(0x06, 0x00);
+}
+
 /*
  * PIXPLLC
  */
@@ -189,8 +194,40 @@ static const struct drm_plane_funcs mgag200_g200ev_primary_plane_funcs = {
 	MGAG200_PRIMARY_PLANE_FUNCS,
 };
 
+static void mgag200_g200ev_crtc_helper_atomic_enable(struct drm_crtc *crtc,
+						     struct drm_atomic_state *old_state)
+{
+	struct drm_device *dev = crtc->dev;
+	struct mga_device *mdev = to_mga_device(dev);
+	const struct mgag200_device_funcs *funcs = mdev->funcs;
+	struct drm_crtc_state *crtc_state = crtc->state;
+	struct drm_display_mode *adjusted_mode = &crtc_state->adjusted_mode;
+	struct mgag200_crtc_state *mgag200_crtc_state = to_mgag200_crtc_state(crtc_state);
+	const struct drm_format_info *format = mgag200_crtc_state->format;
+
+	if (funcs->disable_vidrst)
+		funcs->disable_vidrst(mdev);
+
+	mgag200_set_format_regs(mdev, format);
+	mgag200_set_mode_regs(mdev, adjusted_mode);
+
+	if (funcs->pixpllc_atomic_update)
+		funcs->pixpllc_atomic_update(crtc, old_state);
+
+	mgag200_g200ev_set_hiprilvl(mdev);
+
+	mgag200_enable_display(mdev);
+
+	if (funcs->enable_vidrst)
+		funcs->enable_vidrst(mdev);
+}
+
 static const struct drm_crtc_helper_funcs mgag200_g200ev_crtc_helper_funcs = {
-	MGAG200_CRTC_HELPER_FUNCS,
+	.mode_valid = mgag200_crtc_helper_mode_valid,
+	.atomic_check = mgag200_crtc_helper_atomic_check,
+	.atomic_flush = mgag200_crtc_helper_atomic_flush,
+	.atomic_enable = mgag200_g200ev_crtc_helper_atomic_enable,
+	.atomic_disable = mgag200_crtc_helper_atomic_disable
 };
 
 static const struct drm_crtc_funcs mgag200_g200ev_crtc_funcs = {
diff --git a/drivers/gpu/drm/mgag200/mgag200_g200se.c b/drivers/gpu/drm/mgag200/mgag200_g200se.c
index 59191b0c9f2e..73511c51d0b4 100644
--- a/drivers/gpu/drm/mgag200/mgag200_g200se.c
+++ b/drivers/gpu/drm/mgag200/mgag200_g200se.c
@@ -76,6 +76,52 @@ static void mgag200_g200se_init_registers(struct mgag200_g200se_device *g200se)
 	mgag200_init_registers(mdev);
 }
 
+static void mgag200_g200se_set_hiprilvl(struct mga_device *mdev,
+					const struct drm_display_mode *mode,
+					const struct drm_format_info *format)
+{
+	struct mgag200_g200se_device *g200se = to_mgag200_g200se_device(&mdev->base);
+	unsigned int hiprilvl;
+	u8 crtcext6;
+
+	if  (g200se->unique_rev_id >= 0x04) {
+		hiprilvl = 0;
+	} else if (g200se->unique_rev_id >= 0x02) {
+		unsigned int bpp;
+		unsigned long mb;
+
+		if (format->cpp[0] * 8 > 16)
+			bpp = 32;
+		else if (format->cpp[0] * 8 > 8)
+			bpp = 16;
+		else
+			bpp = 8;
+
+		mb = (mode->clock * bpp) / 1000;
+		if (mb > 3100)
+			hiprilvl = 0;
+		else if (mb > 2600)
+			hiprilvl = 1;
+		else if (mb > 1900)
+			hiprilvl = 2;
+		else if (mb > 1160)
+			hiprilvl = 3;
+		else if (mb > 440)
+			hiprilvl = 4;
+		else
+			hiprilvl = 5;
+
+	} else if (g200se->unique_rev_id >= 0x01) {
+		hiprilvl = 3;
+	} else {
+		hiprilvl = 4;
+	}
+
+	crtcext6 = hiprilvl; /* implicitly sets maxhipri to 0 */
+
+	WREG_ECRT(0x06, crtcext6);
+}
+
 /*
  * PIXPLLC
  */
@@ -280,8 +326,40 @@ static const struct drm_plane_funcs mgag200_g200se_primary_plane_funcs = {
 	MGAG200_PRIMARY_PLANE_FUNCS,
 };
 
+static void mgag200_g200se_crtc_helper_atomic_enable(struct drm_crtc *crtc,
+						     struct drm_atomic_state *old_state)
+{
+	struct drm_device *dev = crtc->dev;
+	struct mga_device *mdev = to_mga_device(dev);
+	const struct mgag200_device_funcs *funcs = mdev->funcs;
+	struct drm_crtc_state *crtc_state = crtc->state;
+	struct drm_display_mode *adjusted_mode = &crtc_state->adjusted_mode;
+	struct mgag200_crtc_state *mgag200_crtc_state = to_mgag200_crtc_state(crtc_state);
+	const struct drm_format_info *format = mgag200_crtc_state->format;
+
+	if (funcs->disable_vidrst)
+		funcs->disable_vidrst(mdev);
+
+	mgag200_set_format_regs(mdev, format);
+	mgag200_set_mode_regs(mdev, adjusted_mode);
+
+	if (funcs->pixpllc_atomic_update)
+		funcs->pixpllc_atomic_update(crtc, old_state);
+
+	mgag200_g200se_set_hiprilvl(mdev, adjusted_mode, format);
+
+	mgag200_enable_display(mdev);
+
+	if (funcs->enable_vidrst)
+		funcs->enable_vidrst(mdev);
+}
+
 static const struct drm_crtc_helper_funcs mgag200_g200se_crtc_helper_funcs = {
-	MGAG200_CRTC_HELPER_FUNCS,
+	.mode_valid = mgag200_crtc_helper_mode_valid,
+	.atomic_check = mgag200_crtc_helper_atomic_check,
+	.atomic_flush = mgag200_crtc_helper_atomic_flush,
+	.atomic_enable = mgag200_g200se_crtc_helper_atomic_enable,
+	.atomic_disable = mgag200_crtc_helper_atomic_disable
 };
 
 static const struct drm_crtc_funcs mgag200_g200se_crtc_funcs = {
diff --git a/drivers/gpu/drm/mgag200/mgag200_mode.c b/drivers/gpu/drm/mgag200/mgag200_mode.c
index 639c33ce6090..1df1f3433418 100644
--- a/drivers/gpu/drm/mgag200/mgag200_mode.c
+++ b/drivers/gpu/drm/mgag200/mgag200_mode.c
@@ -199,8 +199,7 @@ void mgag200_init_registers(struct mga_device *mdev)
 	WREG8(MGA_MISC_OUT, misc);
 }
 
-static void mgag200_set_mode_regs(struct mga_device *mdev,
-				  const struct drm_display_mode *mode)
+void mgag200_set_mode_regs(struct mga_device *mdev, const struct drm_display_mode *mode)
 {
 	const struct mgag200_device_info *info = mdev->info;
 	unsigned int hdisplay, hsyncstart, hsyncend, htotal;
@@ -324,7 +323,7 @@ static void mgag200_set_offset(struct mga_device *mdev,
 	WREG_ECRT(0x00, crtcext0);
 }
 
-static void mgag200_set_format_regs(struct mga_device *mdev, const struct drm_format_info *format)
+void mgag200_set_format_regs(struct mga_device *mdev, const struct drm_format_info *format)
 {
 	struct drm_device *dev = &mdev->base;
 	unsigned int bpp, bppshift, scale;
@@ -387,74 +386,7 @@ static void mgag200_set_format_regs(struct mga_device *mdev, const struct drm_fo
 	WREG_ECRT(3, crtcext3);
 }
 
-static void mgag200_g200er_reset_tagfifo(struct mga_device *mdev)
-{
-	static uint32_t RESET_FLAG = 0x00200000; /* undocumented magic value */
-	u32 memctl;
-
-	memctl = RREG32(MGAREG_MEMCTL);
-
-	memctl |= RESET_FLAG;
-	WREG32(MGAREG_MEMCTL, memctl);
-
-	udelay(1000);
-
-	memctl &= ~RESET_FLAG;
-	WREG32(MGAREG_MEMCTL, memctl);
-}
-
-static void mgag200_g200se_set_hiprilvl(struct mga_device *mdev,
-					const struct drm_display_mode *mode,
-					const struct drm_format_info *format)
-{
-	struct mgag200_g200se_device *g200se = to_mgag200_g200se_device(&mdev->base);
-	unsigned int hiprilvl;
-	u8 crtcext6;
-
-	if  (g200se->unique_rev_id >= 0x04) {
-		hiprilvl = 0;
-	} else if (g200se->unique_rev_id >= 0x02) {
-		unsigned int bpp;
-		unsigned long mb;
-
-		if (format->cpp[0] * 8 > 16)
-			bpp = 32;
-		else if (format->cpp[0] * 8 > 8)
-			bpp = 16;
-		else
-			bpp = 8;
-
-		mb = (mode->clock * bpp) / 1000;
-		if (mb > 3100)
-			hiprilvl = 0;
-		else if (mb > 2600)
-			hiprilvl = 1;
-		else if (mb > 1900)
-			hiprilvl = 2;
-		else if (mb > 1160)
-			hiprilvl = 3;
-		else if (mb > 440)
-			hiprilvl = 4;
-		else
-			hiprilvl = 5;
-
-	} else if (g200se->unique_rev_id >= 0x01) {
-		hiprilvl = 3;
-	} else {
-		hiprilvl = 4;
-	}
-
-	crtcext6 = hiprilvl; /* implicitly sets maxhipri to 0 */
-
-	WREG_ECRT(0x06, crtcext6);
-}
-
-static void mgag200_g200ev_set_hiprilvl(struct mga_device *mdev)
-{
-	WREG_ECRT(0x06, 0x00);
-}
-
-static void mgag200_enable_display(struct mga_device *mdev)
+void mgag200_enable_display(struct mga_device *mdev)
 {
 	u8 seq0, crtcext1;
 
@@ -710,14 +642,6 @@ void mgag200_crtc_helper_atomic_enable(struct drm_crtc *crtc, struct drm_atomic_
 	if (funcs->pixpllc_atomic_update)
 		funcs->pixpllc_atomic_update(crtc, old_state);
 
-	if (mdev->type == G200_ER)
-		mgag200_g200er_reset_tagfifo(mdev);
-
-	if (IS_G200_SE(mdev))
-		mgag200_g200se_set_hiprilvl(mdev, adjusted_mode, format);
-	else if (mdev->type == G200_EV)
-		mgag200_g200ev_set_hiprilvl(mdev);
-
 	mgag200_enable_display(mdev);
 
 	if (funcs->enable_vidrst)
-- 
2.36.1


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

* [PATCH 14/14] drm/mgag200: Remove type field from struct mga_device
  2022-07-08  9:39 [PATCH 00/14] drm/mgag200: Move model-specific code into separate functions Thomas Zimmermann
                   ` (12 preceding siblings ...)
  2022-07-08  9:39 ` [PATCH 13/14] drm/mgag200: Move CRTC atomic_enable to model-specfic code Thomas Zimmermann
@ 2022-07-08  9:39 ` Thomas Zimmermann
  2022-07-08 17:18   ` Sam Ravnborg
  2022-07-08 17:22 ` [PATCH 00/14] drm/mgag200: Move model-specific code into separate functions Sam Ravnborg
  14 siblings, 1 reply; 28+ messages in thread
From: Thomas Zimmermann @ 2022-07-08  9:39 UTC (permalink / raw)
  To: airlied, airlied, jfalempe, daniel; +Cc: Thomas Zimmermann, dri-devel

Each model's specific code is located in a separate file. The type
field in struct mga_device is no unused. Remove it.

Signed-off-by: Thomas Zimmermann <tzimmermann@suse.de>
---
 drivers/gpu/drm/mgag200/mgag200_drv.c     | 17 +++++++------
 drivers/gpu/drm/mgag200/mgag200_drv.h     | 29 ++++++++++-------------
 drivers/gpu/drm/mgag200/mgag200_g200.c    |  5 ++--
 drivers/gpu/drm/mgag200/mgag200_g200eh.c  |  5 ++--
 drivers/gpu/drm/mgag200/mgag200_g200eh3.c |  5 ++--
 drivers/gpu/drm/mgag200/mgag200_g200er.c  |  5 ++--
 drivers/gpu/drm/mgag200/mgag200_g200ev.c  |  5 ++--
 drivers/gpu/drm/mgag200/mgag200_g200ew3.c |  5 ++--
 drivers/gpu/drm/mgag200/mgag200_g200se.c  |  2 +-
 drivers/gpu/drm/mgag200/mgag200_g200wb.c  |  5 ++--
 10 files changed, 35 insertions(+), 48 deletions(-)

diff --git a/drivers/gpu/drm/mgag200/mgag200_drv.c b/drivers/gpu/drm/mgag200/mgag200_drv.c
index c20a59a2cd91..d1e5933a6471 100644
--- a/drivers/gpu/drm/mgag200/mgag200_drv.c
+++ b/drivers/gpu/drm/mgag200/mgag200_drv.c
@@ -161,7 +161,7 @@ int mgag200_device_preinit(struct mga_device *mdev)
 	return 0;
 }
 
-int mgag200_device_init(struct mga_device *mdev, enum mga_type type,
+int mgag200_device_init(struct mga_device *mdev,
 			const struct mgag200_device_info *info,
 			const struct mgag200_device_funcs *funcs)
 {
@@ -171,7 +171,6 @@ int mgag200_device_init(struct mga_device *mdev, enum mga_type type,
 
 	mdev->info = info;
 	mdev->funcs = funcs;
-	mdev->type = type;
 
 	ret = drmm_mutex_init(dev, &mdev->rmmio_lock);
 	if (ret)
@@ -234,29 +233,29 @@ mgag200_pci_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
 	switch (type) {
 	case G200_PCI:
 	case G200_AGP:
-		mdev = mgag200_g200_device_create(pdev, &mgag200_driver, type);
+		mdev = mgag200_g200_device_create(pdev, &mgag200_driver);
 		break;
 	case G200_SE_A:
 	case G200_SE_B:
 		mdev = mgag200_g200se_device_create(pdev, &mgag200_driver, type);
 		break;
 	case G200_WB:
-		mdev = mgag200_g200wb_device_create(pdev, &mgag200_driver, type);
+		mdev = mgag200_g200wb_device_create(pdev, &mgag200_driver);
 		break;
 	case G200_EV:
-		mdev = mgag200_g200ev_device_create(pdev, &mgag200_driver, type);
+		mdev = mgag200_g200ev_device_create(pdev, &mgag200_driver);
 		break;
 	case G200_EH:
-		mdev = mgag200_g200eh_device_create(pdev, &mgag200_driver, type);
+		mdev = mgag200_g200eh_device_create(pdev, &mgag200_driver);
 		break;
 	case G200_EH3:
-		mdev = mgag200_g200eh3_device_create(pdev, &mgag200_driver, type);
+		mdev = mgag200_g200eh3_device_create(pdev, &mgag200_driver);
 		break;
 	case G200_ER:
-		mdev = mgag200_g200er_device_create(pdev, &mgag200_driver, type);
+		mdev = mgag200_g200er_device_create(pdev, &mgag200_driver);
 		break;
 	case G200_EW3:
-		mdev = mgag200_g200ew3_device_create(pdev, &mgag200_driver, type);
+		mdev = mgag200_g200ew3_device_create(pdev, &mgag200_driver);
 		break;
 	default:
 		dev_err(&pdev->dev, "Device type %d is unsupported\n", type);
diff --git a/drivers/gpu/drm/mgag200/mgag200_drv.h b/drivers/gpu/drm/mgag200/mgag200_drv.h
index f3e114d462b2..b57d27f66988 100644
--- a/drivers/gpu/drm/mgag200/mgag200_drv.h
+++ b/drivers/gpu/drm/mgag200/mgag200_drv.h
@@ -265,8 +265,6 @@ struct mga_device {
 	void __iomem			*vram;
 	resource_size_t			vram_available;
 
-	enum mga_type			type;
-
 	struct drm_plane primary_plane;
 	struct drm_crtc crtc;
 	struct drm_encoder encoder;
@@ -310,31 +308,28 @@ int mgag200_init_pci_options(struct pci_dev *pdev, u32 option, u32 option2);
 resource_size_t mgag200_probe_vram(void __iomem *mem, resource_size_t size);
 resource_size_t mgag200_device_probe_vram(struct mga_device *mdev);
 int mgag200_device_preinit(struct mga_device *mdev);
-int mgag200_device_init(struct mga_device *mdev, enum mga_type type,
+int mgag200_device_init(struct mga_device *mdev,
 			const struct mgag200_device_info *info,
 			const struct mgag200_device_funcs *funcs);
 
 				/* mgag200_<device type>.c */
-struct mga_device *mgag200_g200_device_create(struct pci_dev *pdev, const struct drm_driver *drv,
-					      enum mga_type type);
+struct mga_device *mgag200_g200_device_create(struct pci_dev *pdev, const struct drm_driver *drv);
 struct mga_device *mgag200_g200se_device_create(struct pci_dev *pdev, const struct drm_driver *drv,
 						enum mga_type type);
 void mgag200_g200wb_init_registers(struct mga_device *mdev);
 void mgag200_g200wb_pixpllc_atomic_update(struct drm_crtc *crtc, struct drm_atomic_state *state);
-struct mga_device *mgag200_g200wb_device_create(struct pci_dev *pdev, const struct drm_driver *drv,
-						enum mga_type type);
-struct mga_device *mgag200_g200ev_device_create(struct pci_dev *pdev, const struct drm_driver *drv,
-						enum mga_type type);
+struct mga_device *mgag200_g200wb_device_create(struct pci_dev *pdev, const struct drm_driver *drv);
+struct mga_device *mgag200_g200ev_device_create(struct pci_dev *pdev, const struct drm_driver *drv);
 void mgag200_g200eh_init_registers(struct mga_device *mdev);
 void mgag200_g200eh_pixpllc_atomic_update(struct drm_crtc *crtc, struct drm_atomic_state *state);
-struct mga_device *mgag200_g200eh_device_create(struct pci_dev *pdev, const struct drm_driver *drv,
-						enum mga_type type);
-struct mga_device *mgag200_g200eh3_device_create(struct pci_dev *pdev, const struct drm_driver *drv,
-						 enum mga_type type);
-struct mga_device *mgag200_g200er_device_create(struct pci_dev *pdev, const struct drm_driver *drv,
-						enum mga_type type);
-struct mga_device *mgag200_g200ew3_device_create(struct pci_dev *pdev, const struct drm_driver *drv,
-						 enum mga_type type);
+struct mga_device *mgag200_g200eh_device_create(struct pci_dev *pdev,
+						const struct drm_driver *drv);
+struct mga_device *mgag200_g200eh3_device_create(struct pci_dev *pdev,
+						 const struct drm_driver *drv);
+struct mga_device *mgag200_g200er_device_create(struct pci_dev *pdev,
+						const struct drm_driver *drv);
+struct mga_device *mgag200_g200ew3_device_create(struct pci_dev *pdev,
+						 const struct drm_driver *drv);
 
 /*
  * mgag200_mode.c
diff --git a/drivers/gpu/drm/mgag200/mgag200_g200.c b/drivers/gpu/drm/mgag200/mgag200_g200.c
index e0c0fd224c5e..17874a46639f 100644
--- a/drivers/gpu/drm/mgag200/mgag200_g200.c
+++ b/drivers/gpu/drm/mgag200/mgag200_g200.c
@@ -410,8 +410,7 @@ static const struct mgag200_device_funcs mgag200_g200_device_funcs = {
 	.pixpllc_atomic_update = mgag200_g200_pixpllc_atomic_update,
 };
 
-struct mga_device *mgag200_g200_device_create(struct pci_dev *pdev, const struct drm_driver *drv,
-					      enum mga_type type)
+struct mga_device *mgag200_g200_device_create(struct pci_dev *pdev, const struct drm_driver *drv)
 {
 	struct mgag200_g200_device *g200;
 	struct mga_device *mdev;
@@ -437,7 +436,7 @@ struct mga_device *mgag200_g200_device_create(struct pci_dev *pdev, const struct
 
 	mgag200_g200_init_refclk(g200);
 
-	ret = mgag200_device_init(mdev, type, &mgag200_g200_device_info,
+	ret = mgag200_device_init(mdev, &mgag200_g200_device_info,
 				  &mgag200_g200_device_funcs);
 	if (ret)
 		return ERR_PTR(ret);
diff --git a/drivers/gpu/drm/mgag200/mgag200_g200eh.c b/drivers/gpu/drm/mgag200/mgag200_g200eh.c
index 205540e33237..a4a644830a2c 100644
--- a/drivers/gpu/drm/mgag200/mgag200_g200eh.c
+++ b/drivers/gpu/drm/mgag200/mgag200_g200eh.c
@@ -284,8 +284,7 @@ static const struct mgag200_device_funcs mgag200_g200eh_device_funcs = {
 	.pixpllc_atomic_update = mgag200_g200eh_pixpllc_atomic_update,
 };
 
-struct mga_device *mgag200_g200eh_device_create(struct pci_dev *pdev, const struct drm_driver *drv,
-						enum mga_type type)
+struct mga_device *mgag200_g200eh_device_create(struct pci_dev *pdev, const struct drm_driver *drv)
 {
 	struct mga_device *mdev;
 	struct drm_device *dev;
@@ -307,7 +306,7 @@ struct mga_device *mgag200_g200eh_device_create(struct pci_dev *pdev, const stru
 	if (ret)
 		return ERR_PTR(ret);
 
-	ret = mgag200_device_init(mdev, type, &mgag200_g200eh_device_info,
+	ret = mgag200_device_init(mdev, &mgag200_g200eh_device_info,
 				  &mgag200_g200eh_device_funcs);
 	if (ret)
 		return ERR_PTR(ret);
diff --git a/drivers/gpu/drm/mgag200/mgag200_g200eh3.c b/drivers/gpu/drm/mgag200/mgag200_g200eh3.c
index 69ce68efe16c..5f4a550577b0 100644
--- a/drivers/gpu/drm/mgag200/mgag200_g200eh3.c
+++ b/drivers/gpu/drm/mgag200/mgag200_g200eh3.c
@@ -179,8 +179,7 @@ static const struct mgag200_device_funcs mgag200_g200eh3_device_funcs = {
 };
 
 struct mga_device *mgag200_g200eh3_device_create(struct pci_dev *pdev,
-						 const struct drm_driver *drv,
-						 enum mga_type type)
+						 const struct drm_driver *drv)
 {
 	struct mga_device *mdev;
 	struct drm_device *dev;
@@ -202,7 +201,7 @@ struct mga_device *mgag200_g200eh3_device_create(struct pci_dev *pdev,
 	if (ret)
 		return ERR_PTR(ret);
 
-	ret = mgag200_device_init(mdev, type, &mgag200_g200eh3_device_info,
+	ret = mgag200_device_init(mdev, &mgag200_g200eh3_device_info,
 				  &mgag200_g200eh3_device_funcs);
 	if (ret)
 		return ERR_PTR(ret);
diff --git a/drivers/gpu/drm/mgag200/mgag200_g200er.c b/drivers/gpu/drm/mgag200/mgag200_g200er.c
index 42830b9ed5ac..e29c2799e3ec 100644
--- a/drivers/gpu/drm/mgag200/mgag200_g200er.c
+++ b/drivers/gpu/drm/mgag200/mgag200_g200er.c
@@ -321,8 +321,7 @@ static const struct mgag200_device_funcs mgag200_g200er_device_funcs = {
 	.pixpllc_atomic_update = mgag200_g200er_pixpllc_atomic_update,
 };
 
-struct mga_device *mgag200_g200er_device_create(struct pci_dev *pdev, const struct drm_driver *drv,
-						enum mga_type type)
+struct mga_device *mgag200_g200er_device_create(struct pci_dev *pdev, const struct drm_driver *drv)
 {
 	struct mga_device *mdev;
 	struct drm_device *dev;
@@ -340,7 +339,7 @@ struct mga_device *mgag200_g200er_device_create(struct pci_dev *pdev, const stru
 	if (ret)
 		return ERR_PTR(ret);
 
-	ret = mgag200_device_init(mdev, type, &mgag200_g200er_device_info,
+	ret = mgag200_device_init(mdev, &mgag200_g200er_device_info,
 				  &mgag200_g200er_device_funcs);
 	if (ret)
 		return ERR_PTR(ret);
diff --git a/drivers/gpu/drm/mgag200/mgag200_g200ev.c b/drivers/gpu/drm/mgag200/mgag200_g200ev.c
index 72ebea02a7ca..b56473d8db3e 100644
--- a/drivers/gpu/drm/mgag200/mgag200_g200ev.c
+++ b/drivers/gpu/drm/mgag200/mgag200_g200ev.c
@@ -326,8 +326,7 @@ static const struct mgag200_device_funcs mgag200_g200ev_device_funcs = {
 	.pixpllc_atomic_update = mgag200_g200ev_pixpllc_atomic_update,
 };
 
-struct mga_device *mgag200_g200ev_device_create(struct pci_dev *pdev, const struct drm_driver *drv,
-						enum mga_type type)
+struct mga_device *mgag200_g200ev_device_create(struct pci_dev *pdev, const struct drm_driver *drv)
 {
 	struct mga_device *mdev;
 	struct drm_device *dev;
@@ -349,7 +348,7 @@ struct mga_device *mgag200_g200ev_device_create(struct pci_dev *pdev, const stru
 	if (ret)
 		return ERR_PTR(ret);
 
-	ret = mgag200_device_init(mdev, type, &mgag200_g200ev_device_info,
+	ret = mgag200_device_init(mdev, &mgag200_g200ev_device_info,
 				  &mgag200_g200ev_device_funcs);
 	if (ret)
 		return ERR_PTR(ret);
diff --git a/drivers/gpu/drm/mgag200/mgag200_g200ew3.c b/drivers/gpu/drm/mgag200/mgag200_g200ew3.c
index 86ace6b861cd..bab6535f91a9 100644
--- a/drivers/gpu/drm/mgag200/mgag200_g200ew3.c
+++ b/drivers/gpu/drm/mgag200/mgag200_g200ew3.c
@@ -199,8 +199,7 @@ static resource_size_t mgag200_g200ew3_device_probe_vram(struct mga_device *mdev
 }
 
 struct mga_device *mgag200_g200ew3_device_create(struct pci_dev *pdev,
-						 const struct drm_driver *drv,
-						 enum mga_type type)
+						 const struct drm_driver *drv)
 {
 	struct mga_device *mdev;
 	struct drm_device *dev;
@@ -222,7 +221,7 @@ struct mga_device *mgag200_g200ew3_device_create(struct pci_dev *pdev,
 	if (ret)
 		return ERR_PTR(ret);
 
-	ret = mgag200_device_init(mdev, type, &mgag200_g200ew3_device_info,
+	ret = mgag200_device_init(mdev, &mgag200_g200ew3_device_info,
 				  &mgag200_g200ew3_device_funcs);
 	if (ret)
 		return ERR_PTR(ret);
diff --git a/drivers/gpu/drm/mgag200/mgag200_g200se.c b/drivers/gpu/drm/mgag200/mgag200_g200se.c
index 73511c51d0b4..bf2941c0e645 100644
--- a/drivers/gpu/drm/mgag200/mgag200_g200se.c
+++ b/drivers/gpu/drm/mgag200/mgag200_g200se.c
@@ -550,7 +550,7 @@ struct mga_device *mgag200_g200se_device_create(struct pci_dev *pdev, const stru
 	else
 		funcs = &mgag200_g200se_00_device_funcs;
 
-	ret = mgag200_device_init(mdev, type, info, funcs);
+	ret = mgag200_device_init(mdev, info, funcs);
 	if (ret)
 		return ERR_PTR(ret);
 
diff --git a/drivers/gpu/drm/mgag200/mgag200_g200wb.c b/drivers/gpu/drm/mgag200/mgag200_g200wb.c
index 2a7812adf2cd..0e8f17c43a85 100644
--- a/drivers/gpu/drm/mgag200/mgag200_g200wb.c
+++ b/drivers/gpu/drm/mgag200/mgag200_g200wb.c
@@ -333,8 +333,7 @@ static const struct mgag200_device_funcs mgag200_g200wb_device_funcs = {
 	.pixpllc_atomic_update = mgag200_g200wb_pixpllc_atomic_update,
 };
 
-struct mga_device *mgag200_g200wb_device_create(struct pci_dev *pdev, const struct drm_driver *drv,
-						enum mga_type type)
+struct mga_device *mgag200_g200wb_device_create(struct pci_dev *pdev, const struct drm_driver *drv)
 {
 	struct mga_device *mdev;
 	struct drm_device *dev;
@@ -356,7 +355,7 @@ struct mga_device *mgag200_g200wb_device_create(struct pci_dev *pdev, const stru
 	if (ret)
 		return ERR_PTR(ret);
 
-	ret = mgag200_device_init(mdev, type, &mgag200_g200wb_device_info,
+	ret = mgag200_device_init(mdev, &mgag200_g200wb_device_info,
 				  &mgag200_g200wb_device_funcs);
 	if (ret)
 		return ERR_PTR(ret);
-- 
2.36.1


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

* Re: [PATCH 02/14] drm/mgag200: Move DAC-register setup into model-specific code
  2022-07-08  9:39 ` [PATCH 02/14] drm/mgag200: Move DAC-register setup into model-specific code Thomas Zimmermann
@ 2022-07-08 15:54   ` Sam Ravnborg
  2022-07-11  7:25     ` Thomas Zimmermann
  0 siblings, 1 reply; 28+ messages in thread
From: Sam Ravnborg @ 2022-07-08 15:54 UTC (permalink / raw)
  To: Thomas Zimmermann; +Cc: airlied, airlied, jfalempe, dri-devel

Hi Thomas,

On Fri, Jul 08, 2022 at 11:39:17AM +0200, Thomas Zimmermann wrote:
> Provide an init function for each model's DAC registers. Remove
> the shared helper.
> 
> The code for initializing the DAC registers consisted of a large
> table of default value, plus many exceptions for the various G200
> models. Providing a per-model implementation makes if more readable.
The suggested implementation introduces a lot of duplications which is
not nice and the increase in readability is low as it continues to use a
lot of direct value rather than referring to register index values.
In some places it replaces nice register index values with hardcoded
constants.

I typed up something that I see as easier to read - but it is also
much more verbose.

I noticed that for example index 0x1c has the value 0xBF - but the value
is never used. With the scheme below we would only assign values to
registers in use. This would be obvious in the scheme below.

I suggest to keep the current implementation as it is easier to read
what happens with the registers, or go for a more verbose version where
there is no hard coded index to registers like for example outlined below.

	Sam



struct dac_data {
	u8 data;
	bool use;	/* If 
};

All the registers that has the same values for all models:

static void mgag200_default_regs(struct dac_data *dac)
{
	memset(dac, 0, MGA200_REGS);	// New constat equal 0x50

	dac[MGA1064_VREF_CTL].use = true;
	dac[MGA1064_VREF_CTL].data = 0;

	dac[MGA1064_MUL_CTL].use = true;
	dac[MGA1064_MUL_CTL].data = 0;

	dac[MGA1064_PIX_CLK_CTL].use = true;
	dac[MGA1064_PIX_CLK_CTL] = 0xC9;

And so on.
Much more verbose than a table, but also more readable.

A generic write function:
void mgag200_write_dac(struct dac_data *dac)
{
	int i;

	for (i = 0; i < MGA200_REGS) {
		if (dac[i].use])
			WREG_DAC(i, dac[i]);
	}
}


Then for each model something like

void mgag200_g200eh_init_registers(struct mga_device *mdev)
{
	struct dac_data dac[MGA200_REGS];

	mgag200_default_regs(&dac];

	dac[MGA1064_MISC_CTL].use = true;
	dac[MGA1064_MISC_CTL].data = MGA1064_MISC_CTL_VGA8 | /* G200EH specific: MGA1064_MISC_CTL */
				     MGA1064_MISC_CTL_DAC_RAM_CS;

	/* No PIX_PLL setup */   -- The logic should be reversed I hink, so
       				    the ones that need PLL setup set to true.
				    But the idea is obvious so I did not
				    redo it
	dac[MGA1064_PIX_PLLA_M].use = false;
	dac[MGA1064_PIX_PLLA_N].use = false;
	dac[MGA1064_PIX_PLLA_P].use = false;
	dac[MGA1064_PIX_PLLB_M].use = false;
	dac[MGA1064_PIX_PLLB_N].use = false;
	dac[MGA1064_PIX_PLLB_P].use = false;
	dac[MGA1064_PIX_PLLC_M].use = false;
	dac[MGA1064_PIX_PLLC_N].use = false;
	dac[MGA1064_PIX_PLLC_P].use = false;

	mgag200_write_dac(&dac);
}


> At some point, some of the initialization should probably move into
> the modesetting code.
> 
> Signed-off-by: Thomas Zimmermann <tzimmermann@suse.de>
> ---
>  drivers/gpu/drm/mgag200/mgag200_drv.h     |  3 +
>  drivers/gpu/drm/mgag200/mgag200_g200.c    | 37 +++++++++++
>  drivers/gpu/drm/mgag200/mgag200_g200eh.c  | 36 ++++++++++
>  drivers/gpu/drm/mgag200/mgag200_g200eh3.c |  2 +
>  drivers/gpu/drm/mgag200/mgag200_g200er.c  | 34 ++++++++++
>  drivers/gpu/drm/mgag200/mgag200_g200ev.c  | 40 ++++++++++++
>  drivers/gpu/drm/mgag200/mgag200_g200ew3.c |  2 +
>  drivers/gpu/drm/mgag200/mgag200_g200se.c  | 45 +++++++++++++
>  drivers/gpu/drm/mgag200/mgag200_g200wb.c  | 34 ++++++++++
>  drivers/gpu/drm/mgag200/mgag200_mode.c    | 80 +----------------------
>  10 files changed, 234 insertions(+), 79 deletions(-)
> 
> diff --git a/drivers/gpu/drm/mgag200/mgag200_drv.h b/drivers/gpu/drm/mgag200/mgag200_drv.h
> index 301c4ab46539..6a2a1ad914c1 100644
> --- a/drivers/gpu/drm/mgag200/mgag200_drv.h
> +++ b/drivers/gpu/drm/mgag200/mgag200_drv.h
> @@ -295,10 +295,12 @@ struct mga_device *mgag200_g200_device_create(struct pci_dev *pdev, const struct
>  					      enum mga_type type);
>  struct mga_device *mgag200_g200se_device_create(struct pci_dev *pdev, const struct drm_driver *drv,
>  						enum mga_type type);
> +void mgag200_g200wb_init_registers(struct mga_device *mdev);
>  struct mga_device *mgag200_g200wb_device_create(struct pci_dev *pdev, const struct drm_driver *drv,
>  						enum mga_type type);
>  struct mga_device *mgag200_g200ev_device_create(struct pci_dev *pdev, const struct drm_driver *drv,
>  						enum mga_type type);
> +void mgag200_g200eh_init_registers(struct mga_device *mdev);
>  struct mga_device *mgag200_g200eh_device_create(struct pci_dev *pdev, const struct drm_driver *drv,
>  						enum mga_type type);
>  struct mga_device *mgag200_g200eh3_device_create(struct pci_dev *pdev, const struct drm_driver *drv,
> @@ -310,6 +312,7 @@ struct mga_device *mgag200_g200ew3_device_create(struct pci_dev *pdev, const str
>  
>  				/* mgag200_mode.c */
>  resource_size_t mgag200_device_probe_vram(struct mga_device *mdev);
> +void mgag200_init_registers(struct mga_device *mdev);
>  int mgag200_modeset_init(struct mga_device *mdev, resource_size_t vram_fb_available);
>  
>  				/* mgag200_i2c.c */
> diff --git a/drivers/gpu/drm/mgag200/mgag200_g200.c b/drivers/gpu/drm/mgag200/mgag200_g200.c
> index 674385921b7f..c6303fcb8fe7 100644
> --- a/drivers/gpu/drm/mgag200/mgag200_g200.c
> +++ b/drivers/gpu/drm/mgag200/mgag200_g200.c
> @@ -30,6 +30,41 @@ static int mgag200_g200_init_pci_options(struct pci_dev *pdev)
>  	return mgag200_init_pci_options(pdev, option, 0x00008000);
>  }
>  
> +static void mgag200_g200_init_registers(struct mgag200_g200_device *g200)
> +{
> +	static const u8 dacvalue[] = {
> +		/* 0x00: */        0,    0,    0,    0,    0,    0,    0,    0,
> +		/* 0x08: */        0,    0,    0,    0,    0,    0,    0,    0,
> +		/* 0x10: */        0,    0,    0,    0,    0,    0,    0,    0,
> +		/* 0x18: */     0x00,    0, 0xC9, 0xFF, 0xBF, 0x20, 0x1F, 0x20,
> +		/* 0x20: */     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
> +		/* 0x28: */     0x00, 0x00, 0x00, 0x00,
> +		/* 0x2c: */	0x04, /* G200 specific: MGA1064_SYS_PLL_M */
> +		/* 0x2d: */     0x2d, /* G200 specific: MGA1064_SYS_PLL_N */
> +		/* 0x2e: */     0x19, /* G200 specific: MGA1064_SYS_PLL_P */
> +		/* 0x2f: */     0x40,
> +		/* 0x30: */     0x00, 0xB0, 0x00, 0xC2, 0x34, 0x14, 0x02, 0x83,
> +		/* 0x38: */     0x00, 0x93, 0x00, 0x77, 0x00, 0x00, 0x00, 0x3A,
> +		/* 0x40: */        0,    0,    0,    0,    0,    0,    0,    0,
> +		/* 0x48: */        0,    0,    0,    0,    0,    0,    0,    0
> +	};
> +
> +	struct mga_device *mdev = &g200->base;
> +	size_t i;
> +
> +	for (i = 0; i < ARRAY_SIZE(dacvalue); ++i) {
> +		if ((i <= 0x17) ||
> +		    (i == 0x1b) ||
> +		    (i == 0x1c) ||
> +		    ((i >= 0x1f) && (i <= 0x29)) ||
> +		    ((i >= 0x30) && (i <= 0x37)))
> +			continue;
> +		WREG_DAC(i, dacvalue[i]);
> +	}
> +
> +	mgag200_init_registers(mdev);
> +}
> +
>  /*
>   * DRM Device
>   */
> @@ -191,6 +226,8 @@ struct mga_device *mgag200_g200_device_create(struct pci_dev *pdev, const struct
>  	if (ret)
>  		return ERR_PTR(ret);
>  
> +	mgag200_g200_init_registers(g200);
> +
>  	vram_available = mgag200_device_probe_vram(mdev);
>  
>  	ret = mgag200_modeset_init(mdev, vram_available);
> diff --git a/drivers/gpu/drm/mgag200/mgag200_g200eh.c b/drivers/gpu/drm/mgag200/mgag200_g200eh.c
> index 1b9a22728744..365f486d3ce7 100644
> --- a/drivers/gpu/drm/mgag200/mgag200_g200eh.c
> +++ b/drivers/gpu/drm/mgag200/mgag200_g200eh.c
> @@ -6,6 +6,40 @@
>  
>  #include "mgag200_drv.h"
>  
> +void mgag200_g200eh_init_registers(struct mga_device *mdev)
> +{
> +	static const u8 dacvalue[] = {
> +		/* 0x00: */        0,    0,    0,    0,    0,    0,    0,    0,
> +		/* 0x08: */        0,    0,    0,    0,    0,    0,    0,    0,
> +		/* 0x10: */        0,    0,    0,    0,    0,    0,    0,    0,
> +		/* 0x18: */     0x00,    0, 0xC9, 0xFF, 0xBF, 0x20,
> +		/* 0x1e: */     MGA1064_MISC_CTL_VGA8 | /* G200EH specific: MGA1064_MISC_CTL */
> +				MGA1064_MISC_CTL_DAC_RAM_CS,
> +		/* 0x1f: */     0x20,
> +		/* 0x20: */     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
> +		/* 0x28: */     0x00, 0x00, 0x00, 0x00,    0,    0,    0, 0x40,
> +		/* 0x30: */     0x00, 0xB0, 0x00, 0xC2, 0x34, 0x14, 0x02, 0x83,
> +		/* 0x38: */     0x00, 0x93, 0x00, 0x77, 0x00, 0x00, 0x00, 0x3A,
> +		/* 0x40: */        0,    0,    0,    0,    0,    0,    0,    0,
> +		/* 0x48: */        0,    0,    0,    0,    0,    0,    0,    0
> +	};
> +
> +	size_t i;
> +
> +	for (i = 0; i < ARRAY_SIZE(dacvalue); i++) {
> +		if ((i <= 0x17) ||
> +		    (i == 0x1b) ||
> +		    (i == 0x1c) ||
> +		    ((i >= 0x1f) && (i <= 0x29)) ||
> +		    ((i >= 0x30) && (i <= 0x37)) ||
> +		    ((i >= 0x44) && (i <= 0x4e)))
> +			continue;
> +		WREG_DAC(i, dacvalue[i]);
> +	}
> +
> +	mgag200_init_registers(mdev);
> +}
> +
>  /*
>   * DRM device
>   */
> @@ -40,6 +74,8 @@ struct mga_device *mgag200_g200eh_device_create(struct pci_dev *pdev, const stru
>  	if (ret)
>  		return ERR_PTR(ret);
>  
> +	mgag200_g200eh_init_registers(mdev);
> +
>  	vram_available = mgag200_device_probe_vram(mdev);
>  
>  	ret = mgag200_modeset_init(mdev, vram_available);
> diff --git a/drivers/gpu/drm/mgag200/mgag200_g200eh3.c b/drivers/gpu/drm/mgag200/mgag200_g200eh3.c
> index 438cda1b14c9..adb9190b62af 100644
> --- a/drivers/gpu/drm/mgag200/mgag200_g200eh3.c
> +++ b/drivers/gpu/drm/mgag200/mgag200_g200eh3.c
> @@ -41,6 +41,8 @@ struct mga_device *mgag200_g200eh3_device_create(struct pci_dev *pdev,
>  	if (ret)
>  		return ERR_PTR(ret);
>  
> +	mgag200_g200eh_init_registers(mdev); // same as G200EH
> +
>  	vram_available = mgag200_device_probe_vram(mdev);
>  
>  	ret = mgag200_modeset_init(mdev, vram_available);
> diff --git a/drivers/gpu/drm/mgag200/mgag200_g200er.c b/drivers/gpu/drm/mgag200/mgag200_g200er.c
> index 0790d4e6463d..acdccc419944 100644
> --- a/drivers/gpu/drm/mgag200/mgag200_g200er.c
> +++ b/drivers/gpu/drm/mgag200/mgag200_g200er.c
> @@ -6,6 +6,38 @@
>  
>  #include "mgag200_drv.h"
>  
> +static void mgag200_g200er_init_registers(struct mga_device *mdev)
> +{
> +	static const u8 dacvalue[] = {
> +		/* 0x00: */        0,    0,    0,    0,    0,    0,    0,    0,
> +		/* 0x08: */        0,    0,    0,    0,    0,    0,    0,    0,
> +		/* 0x10: */        0,    0,    0,    0,    0,    0,    0,    0,
> +		/* 0x18: */     0x00,    0, 0xC9, 0xFF, 0xBF, 0x20, 0x1F, 0x20,
> +		/* 0x20: */     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
> +		/* 0x28: */     0x00, 0x00, 0x00, 0x00,    0,    0,    0, 0x40,
> +		/* 0x30: */     0x00, 0xB0, 0x00, 0xC2, 0x34, 0x14, 0x02, 0x83,
> +		/* 0x38: */     0x00, 0x93, 0x00, 0x77, 0x00, 0x00, 0x00, 0x3A,
> +		/* 0x40: */        0,    0,    0,    0,    0,    0,    0,    0,
> +		/* 0x48: */        0,    0,    0,    0,    0,    0,    0,    0
> +	};
> +
> +	size_t i;
> +
> +	for (i = 0; i < ARRAY_SIZE(dacvalue); i++) {
> +		if ((i <= 0x17) ||
> +		    (i == 0x1b) ||
> +		    (i == 0x1c) ||
> +		    ((i >= 0x1f) && (i <= 0x29)) ||
> +		    ((i >= 0x30) && (i <= 0x37)))
> +			continue;
> +		WREG_DAC(i, dacvalue[i]);
> +	}
> +
> +	WREG_DAC(0x90, 0); /* G200ER specific */
> +
> +	mgag200_init_registers(mdev);
> +}
> +
>  /*
>   * DRM device
>   */
> @@ -36,6 +68,8 @@ struct mga_device *mgag200_g200er_device_create(struct pci_dev *pdev, const stru
>  	if (ret)
>  		return ERR_PTR(ret);
>  
> +	mgag200_g200er_init_registers(mdev);
> +
>  	vram_available = mgag200_device_probe_vram(mdev);
>  
>  	ret = mgag200_modeset_init(mdev, vram_available);
> diff --git a/drivers/gpu/drm/mgag200/mgag200_g200ev.c b/drivers/gpu/drm/mgag200/mgag200_g200ev.c
> index 5353422d0eef..ce26d48c9691 100644
> --- a/drivers/gpu/drm/mgag200/mgag200_g200ev.c
> +++ b/drivers/gpu/drm/mgag200/mgag200_g200ev.c
> @@ -6,6 +6,44 @@
>  
>  #include "mgag200_drv.h"
>  
> +static void mgag200_g200ev_init_registers(struct mga_device *mdev)
> +{
> +	static const u8 dacvalue[] = {
> +		/* 0x00: */        0,    0,    0,    0,    0,    0,    0,    0,
> +		/* 0x08: */        0,    0,    0,    0,    0,    0,    0,    0,
> +		/* 0x10: */        0,    0,    0,    0,    0,    0,    0,    0,
> +		/* 0x18: */     0x00,    0,
> +				/* G200EV specific: MGA1064_PIX_CLK_CTL */
> +		/* 0x1a: */     MGA1064_PIX_CLK_CTL_SEL_PLL,
> +		/* 0x1b: */     0xFF, 0xBF, 0x20,
> +				/* G200EV specific: MGA1064_MISC_CTL */
> +		/* 0x1e: */     MGA1064_MISC_CTL_VGA8 |
> +				MGA1064_MISC_CTL_DAC_RAM_CS,
> +		/* 0x1f: */     0x20,
> +		/* 0x20: */     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
> +		/* 0x28: */     0x00, 0x00, 0x00, 0x00,    0,    0,    0, 0x40,
> +		/* 0x30: */     0x00, 0xB0, 0x00, 0xC2, 0x34, 0x14, 0x02, 0x83,
> +		/* 0x38: */     0x00, 0x93, 0x00, 0x77, 0x00, 0x00, 0x00, 0x3A,
> +		/* 0x40: */        0,    0,    0,    0,    0,    0,    0,    0,
> +		/* 0x48: */        0,    0,    0,    0,    0,    0,    0,    0
> +	};
> +
> +	size_t i;
> +
> +	for (i = 0; i < ARRAY_SIZE(dacvalue); i++) {
> +		if ((i <= 0x17) ||
> +		    (i == 0x1b) ||
> +		    (i == 0x1c) ||
> +		    ((i >= 0x1f) && (i <= 0x29)) ||
> +		    ((i >= 0x30) && (i <= 0x37)) ||
> +		    ((i >= 0x44) && (i <= 0x4e)))
> +			continue;
> +		WREG_DAC(i, dacvalue[i]);
> +	}
> +
> +	mgag200_init_registers(mdev);
> +}
> +
>  /*
>   * DRM device
>   */
> @@ -40,6 +78,8 @@ struct mga_device *mgag200_g200ev_device_create(struct pci_dev *pdev, const stru
>  	if (ret)
>  		return ERR_PTR(ret);
>  
> +	mgag200_g200ev_init_registers(mdev);
> +
>  	vram_available = mgag200_device_probe_vram(mdev);
>  
>  	ret = mgag200_modeset_init(mdev, vram_available);
> diff --git a/drivers/gpu/drm/mgag200/mgag200_g200ew3.c b/drivers/gpu/drm/mgag200/mgag200_g200ew3.c
> index 3bfc1324cf78..d86284c0eb4d 100644
> --- a/drivers/gpu/drm/mgag200/mgag200_g200ew3.c
> +++ b/drivers/gpu/drm/mgag200/mgag200_g200ew3.c
> @@ -50,6 +50,8 @@ struct mga_device *mgag200_g200ew3_device_create(struct pci_dev *pdev,
>  	if (ret)
>  		return ERR_PTR(ret);
>  
> +	mgag200_g200wb_init_registers(mdev); // same as G200WB
> +
>  	vram_available = mgag200_g200ew3_device_probe_vram(mdev);
>  
>  	ret = mgag200_modeset_init(mdev, vram_available);
> diff --git a/drivers/gpu/drm/mgag200/mgag200_g200se.c b/drivers/gpu/drm/mgag200/mgag200_g200se.c
> index 0a3e66695e22..9f51be8ef731 100644
> --- a/drivers/gpu/drm/mgag200/mgag200_g200se.c
> +++ b/drivers/gpu/drm/mgag200/mgag200_g200se.c
> @@ -28,6 +28,49 @@ static int mgag200_g200se_init_pci_options(struct pci_dev *pdev)
>  	return mgag200_init_pci_options(pdev, option, 0x00008000);
>  }
>  
> +static void mgag200_g200se_init_registers(struct mgag200_g200se_device *g200se)
> +{
> +	static const u8 dacvalue[] = {
> +		/* 0x00: */        0,    0,    0,    0,    0,    0, 0x00,    0,
> +		/* 0x08: */        0,    0,    0,    0,    0,    0,    0,    0,
> +		/* 0x10: */        0,    0,    0,    0,    0,    0,    0,    0,
> +				/* G200SE specific: MGA1064_VREF_CTL */
> +		/* 0x18: */     0x03,
> +		/* 0x19: */        0,
> +				/* G200EV specific: MGA1064_PIX_CLK_CTL */
> +		/* 0x1a: */     MGA1064_PIX_CLK_CTL_SEL_PLL,
> +		/* 0x1b: */     0xFF, 0xBF, 0x20,
> +				/* G200EV specific: MGA1064_MISC_CTL */
> +		/* 0x1e: */     MGA1064_MISC_CTL_DAC_EN |
> +				MGA1064_MISC_CTL_VGA8 |
> +				MGA1064_MISC_CTL_DAC_RAM_CS,
> +
> +		/* 0x19: */        0, 0xC9, 0xFF, 0xBF, 0x20, 0x1F, 0x20,
> +		/* 0x20: */     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
> +		/* 0x28: */     0x00, 0x00, 0x00, 0x00,    0,    0,    0, 0x40,
> +		/* 0x30: */     0x00, 0xB0, 0x00, 0xC2, 0x34, 0x14, 0x02, 0x83,
> +		/* 0x38: */     0x00, 0x93, 0x00, 0x77, 0x00, 0x00, 0x00, 0x3A,
> +		/* 0x40: */        0,    0,    0,    0,    0,    0,    0,    0,
> +		/* 0x48: */        0,    0,    0,    0,    0,    0,    0,    0
> +	};
> +
> +	struct mga_device *mdev = &g200se->base;
> +	size_t i;
> +
> +	for (i = 0; i < ARRAY_SIZE(dacvalue); i++) {
> +		if ((i <= 0x17) ||
> +		    (i == 0x1b) ||
> +		    (i == 0x1c) ||
> +		    ((i >= 0x1f) && (i <= 0x29)) ||
> +		    ((i == 0x2c) || (i == 0x2d) || (i == 0x2e)) ||
> +		    ((i >= 0x30) && (i <= 0x37)))
> +			continue;
> +		WREG_DAC(i, dacvalue[i]);
> +	}
> +
> +	mgag200_init_registers(mdev);
> +}
> +
>  /*
>   * DRM device
>   */
> @@ -120,6 +163,8 @@ struct mga_device *mgag200_g200se_device_create(struct pci_dev *pdev, const stru
>  	if (ret)
>  		return ERR_PTR(ret);
>  
> +	mgag200_g200se_init_registers(g200se);
> +
>  	vram_available = mgag200_device_probe_vram(mdev);
>  
>  	ret = mgag200_modeset_init(mdev, vram_available);
> diff --git a/drivers/gpu/drm/mgag200/mgag200_g200wb.c b/drivers/gpu/drm/mgag200/mgag200_g200wb.c
> index c8450ac8eaec..e4de4b2dc2e2 100644
> --- a/drivers/gpu/drm/mgag200/mgag200_g200wb.c
> +++ b/drivers/gpu/drm/mgag200/mgag200_g200wb.c
> @@ -6,6 +6,38 @@
>  
>  #include "mgag200_drv.h"
>  
> +void mgag200_g200wb_init_registers(struct mga_device *mdev)
> +{
> +	static const u8 dacvalue[] = {
> +		/* 0x00: */        0,    0,    0,    0,    0,    0,    0,    0,
> +		/* 0x08: */        0,    0,    0,    0,    0,    0,    0,    0,
> +		/* 0x10: */        0,    0,    0,    0,    0,    0,    0,    0,
> +		/* 0x18: */     0x07, /* G200WB specific: MGA1064_VREF_CTL */
> +		/* 0x19: */        0, 0xC9, 0xFF, 0xBF, 0x20, 0x1F, 0x20,
> +		/* 0x20: */     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
> +		/* 0x28: */     0x00, 0x00, 0x00, 0x00,    0,    0,    0, 0x40,
> +		/* 0x30: */     0x00, 0xB0, 0x00, 0xC2, 0x34, 0x14, 0x02, 0x83,
> +		/* 0x38: */     0x00, 0x93, 0x00, 0x77, 0x00, 0x00, 0x00, 0x3A,
> +		/* 0x40: */        0,    0,    0,    0,    0,    0,    0,    0,
> +		/* 0x48: */        0,    0,    0,    0,    0,    0,    0,    0
> +	};
> +
> +	size_t i;
> +
> +	for (i = 0; i < ARRAY_SIZE(dacvalue); i++) {
> +		if ((i <= 0x17) ||
> +		    (i == 0x1b) ||
> +		    (i == 0x1c) ||
> +		    ((i >= 0x1f) && (i <= 0x29)) ||
> +		    ((i >= 0x30) && (i <= 0x37)) ||
> +		    ((i >= 0x44) && (i <= 0x4e)))
> +			continue;
> +		WREG_DAC(i, dacvalue[i]);
> +	}
> +
> +	mgag200_init_registers(mdev);
> +}
> +
>  /*
>   * DRM device
>   */
> @@ -40,6 +72,8 @@ struct mga_device *mgag200_g200wb_device_create(struct pci_dev *pdev, const stru
>  	if (ret)
>  		return ERR_PTR(ret);
>  
> +	mgag200_g200wb_init_registers(mdev);
> +
>  	vram_available = mgag200_device_probe_vram(mdev);
>  
>  	ret = mgag200_modeset_init(mdev, vram_available);
> diff --git a/drivers/gpu/drm/mgag200/mgag200_mode.c b/drivers/gpu/drm/mgag200/mgag200_mode.c
> index e08852482fe2..f9868d728e6d 100644
> --- a/drivers/gpu/drm/mgag200/mgag200_mode.c
> +++ b/drivers/gpu/drm/mgag200/mgag200_mode.c
> @@ -267,86 +267,10 @@ static void mgag200_set_startadd(struct mga_device *mdev,
>  	WREG_ECRT(0x00, crtcext0);
>  }
>  
> -static void mgag200_set_dac_regs(struct mga_device *mdev)
> -{
> -	size_t i;
> -	u8 dacvalue[] = {
> -		/* 0x00: */        0,    0,    0,    0,    0,    0, 0x00,    0,
> -		/* 0x08: */        0,    0,    0,    0,    0,    0,    0,    0,
> -		/* 0x10: */        0,    0,    0,    0,    0,    0,    0,    0,
> -		/* 0x18: */     0x00,    0, 0xC9, 0xFF, 0xBF, 0x20, 0x1F, 0x20,
> -		/* 0x20: */     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
> -		/* 0x28: */     0x00, 0x00, 0x00, 0x00,    0,    0,    0, 0x40,
> -		/* 0x30: */     0x00, 0xB0, 0x00, 0xC2, 0x34, 0x14, 0x02, 0x83,
> -		/* 0x38: */     0x00, 0x93, 0x00, 0x77, 0x00, 0x00, 0x00, 0x3A,
> -		/* 0x40: */        0,    0,    0,    0,    0,    0,    0,    0,
> -		/* 0x48: */        0,    0,    0,    0,    0,    0,    0,    0
> -	};
> -
> -	switch (mdev->type) {
> -	case G200_PCI:
> -	case G200_AGP:
> -		dacvalue[MGA1064_SYS_PLL_M] = 0x04;
> -		dacvalue[MGA1064_SYS_PLL_N] = 0x2D;
> -		dacvalue[MGA1064_SYS_PLL_P] = 0x19;
> -		break;
> -	case G200_SE_A:
> -	case G200_SE_B:
> -		dacvalue[MGA1064_VREF_CTL] = 0x03;
> -		dacvalue[MGA1064_PIX_CLK_CTL] = MGA1064_PIX_CLK_CTL_SEL_PLL;
> -		dacvalue[MGA1064_MISC_CTL] = MGA1064_MISC_CTL_DAC_EN |
> -					     MGA1064_MISC_CTL_VGA8 |
> -					     MGA1064_MISC_CTL_DAC_RAM_CS;
> -		break;
> -	case G200_WB:
> -	case G200_EW3:
> -		dacvalue[MGA1064_VREF_CTL] = 0x07;
> -		break;
> -	case G200_EV:
> -		dacvalue[MGA1064_PIX_CLK_CTL] = MGA1064_PIX_CLK_CTL_SEL_PLL;
> -		dacvalue[MGA1064_MISC_CTL] = MGA1064_MISC_CTL_VGA8 |
> -					     MGA1064_MISC_CTL_DAC_RAM_CS;
> -		break;
> -	case G200_EH:
> -	case G200_EH3:
> -		dacvalue[MGA1064_MISC_CTL] = MGA1064_MISC_CTL_VGA8 |
> -					     MGA1064_MISC_CTL_DAC_RAM_CS;
> -		break;
> -	case G200_ER:
> -		break;
> -	}
> -
> -	for (i = 0; i < ARRAY_SIZE(dacvalue); i++) {
> -		if ((i <= 0x17) ||
> -		    (i == 0x1b) ||
> -		    (i == 0x1c) ||
> -		    ((i >= 0x1f) && (i <= 0x29)) ||
> -		    ((i >= 0x30) && (i <= 0x37)))
> -			continue;
> -		if (IS_G200_SE(mdev) &&
> -		    ((i == 0x2c) || (i == 0x2d) || (i == 0x2e)))
> -			continue;
> -		if ((mdev->type == G200_EV ||
> -		    mdev->type == G200_WB ||
> -		    mdev->type == G200_EH ||
> -		    mdev->type == G200_EW3 ||
> -		    mdev->type == G200_EH3) &&
> -		    (i >= 0x44) && (i <= 0x4e))
> -			continue;
> -
> -		WREG_DAC(i, dacvalue[i]);
> -	}
> -
> -	if (mdev->type == G200_ER)
> -		WREG_DAC(0x90, 0);
> -}
> -
> -static void mgag200_init_regs(struct mga_device *mdev)
> +void mgag200_init_registers(struct mga_device *mdev)
>  {
>  	u8 crtc11, misc;
>  
> -	mgag200_set_dac_regs(mdev);
> -
>  	WREG_SEQ(2, 0x0f);
>  	WREG_SEQ(3, 0x00);
>  	WREG_SEQ(4, 0x0e);
> @@ -1127,8 +1051,6 @@ int mgag200_modeset_init(struct mga_device *mdev, resource_size_t vram_available
>  	struct drm_device *dev = &mdev->base;
>  	int ret;
>  
> -	mgag200_init_regs(mdev);
> -
>  	ret = mgag200_mode_config_init(mdev, vram_available);
>  	if (ret)
>  		return ret;
> -- 
> 2.36.1

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

* Re: [PATCH 14/14] drm/mgag200: Remove type field from struct mga_device
  2022-07-08  9:39 ` [PATCH 14/14] drm/mgag200: Remove type field from struct mga_device Thomas Zimmermann
@ 2022-07-08 17:18   ` Sam Ravnborg
  0 siblings, 0 replies; 28+ messages in thread
From: Sam Ravnborg @ 2022-07-08 17:18 UTC (permalink / raw)
  To: Thomas Zimmermann; +Cc: airlied, airlied, jfalempe, dri-devel

On Fri, Jul 08, 2022 at 11:39:29AM +0200, Thomas Zimmermann wrote:
> Each model's specific code is located in a separate file. The type
> field in struct mga_device is no unused. Remove it.
s/no/now/
> 
> Signed-off-by: Thomas Zimmermann <tzimmermann@suse.de>

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

* Re: [PATCH 00/14] drm/mgag200: Move model-specific code into separate functions
  2022-07-08  9:39 [PATCH 00/14] drm/mgag200: Move model-specific code into separate functions Thomas Zimmermann
                   ` (13 preceding siblings ...)
  2022-07-08  9:39 ` [PATCH 14/14] drm/mgag200: Remove type field from struct mga_device Thomas Zimmermann
@ 2022-07-08 17:22 ` Sam Ravnborg
  2022-07-11  7:29   ` Thomas Zimmermann
  14 siblings, 1 reply; 28+ messages in thread
From: Sam Ravnborg @ 2022-07-08 17:22 UTC (permalink / raw)
  To: Thomas Zimmermann; +Cc: airlied, airlied, jfalempe, dri-devel

Hi Thomas,

On Fri, Jul 08, 2022 at 11:39:15AM +0200, Thomas Zimmermann wrote:
> Mgag200 still mixes model-specific code and generic code in the same
> functions. Separate it into distinct helpers.
> 
> As part of this effort, convert the driver from simple-KMS helpers
> to regular atomic helpers. The latter are way more flexible and can
> be adapted easily for each hardware model.
> 
> Tested on Matrox G200 and G200EH hardware.
> 
> Thomas Zimmermann (14):
>   drm/mgag200: Split mgag200_modeset_init()
>   drm/mgag200: Move DAC-register setup into model-specific code
>   dmr/mgag200: Move ER/EW3 register initializatino to per-model code
>   drm/mgag200: Acquire I/O-register lock in atomic_commit_tail function
>   drm/mgag200: Store primary plane's color format in CRTC state
>   drm/mgag200: Reorganize before dropping simple-KMS helpers
>   drm/mgag200: Replace simple-KMS with regular atomic helpers
>   drm/mgag200: Set SCROFF in primary-plane code
>   drm/mgag200: Add per-device callbacks
>   drm/mgag200: Provide per-device callbacks for BMC synchronization
>   drm/mgag200: Provide per-device callbacks for PIXPLLC
>   drm/mgag200: Move mode-config to model-specific code
>   drm/mgag200: Move CRTC atomic_enable to model-specfic code
>   drm/mgag200: Remove type field from struct mga_device

I have browsed the patches and they looked good.
I was about to complain about several things, like bmc init, but then
later this is all nicely cleaned up.
Especially the pll setup stuff did not get much scrunity, as it like
most of the patch looked like code movements.

All patches except "Move DAC-register setup into model-specific code"
are:
Acked-by: Sam Ravnborg <sam@ravnborg.org>


>  14 files changed, 2804 insertions(+), 1586 deletions(-)
This is not a diffstat that makes one go - yyipeee.
But the improvements makes it worthwhile.

	Sam

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

* Re: [PATCH 02/14] drm/mgag200: Move DAC-register setup into model-specific code
  2022-07-08 15:54   ` Sam Ravnborg
@ 2022-07-11  7:25     ` Thomas Zimmermann
  0 siblings, 0 replies; 28+ messages in thread
From: Thomas Zimmermann @ 2022-07-11  7:25 UTC (permalink / raw)
  To: Sam Ravnborg; +Cc: airlied, airlied, jfalempe, dri-devel


[-- Attachment #1.1: Type: text/plain, Size: 24466 bytes --]

Hi Sam

Am 08.07.22 um 17:54 schrieb Sam Ravnborg:
> Hi Thomas,
> 
> On Fri, Jul 08, 2022 at 11:39:17AM +0200, Thomas Zimmermann wrote:
>> Provide an init function for each model's DAC registers. Remove
>> the shared helper.
>>
>> The code for initializing the DAC registers consisted of a large
>> table of default value, plus many exceptions for the various G200
>> models. Providing a per-model implementation makes if more readable.
> The suggested implementation introduces a lot of duplications which is
> not nice and the increase in readability is low as it continues to use a
> lot of direct value rather than referring to register index values.
> In some places it replaces nice register index values with hardcoded
> constants.
> 
> I typed up something that I see as easier to read - but it is also
> much more verbose.
> 
> I noticed that for example index 0x1c has the value 0xBF - but the value
> is never used. With the scheme below we would only assign values to
> registers in use. This would be obvious in the scheme below.
> 
> I suggest to keep the current implementation as it is easier to read
> what happens with the registers, or go for a more verbose version where
> there is no hard coded index to registers like for example outlined below.

The current code is not maintainable or even readable. That for loop 
with the branches isn't funny anymore.  It needs to be untangled into 
per-model code in some way.

> 
> 	Sam
> 
> 
> 
> struct dac_data {
> 	u8 data;
> 	bool use;	/* If
> };
> 
> All the registers that has the same values for all models:
> 
> static void mgag200_default_regs(struct dac_data *dac)
> {
> 	memset(dac, 0, MGA200_REGS);	// New constat equal 0x50
> 
> 	dac[MGA1064_VREF_CTL].use = true;
> 	dac[MGA1064_VREF_CTL].data = 0;
> 
> 	dac[MGA1064_MUL_CTL].use = true;
> 	dac[MGA1064_MUL_CTL].data = 0;
> 
> 	dac[MGA1064_PIX_CLK_CTL].use = true;
> 	dac[MGA1064_PIX_CLK_CTL] = 0xC9;
> 
> And so on.
> Much more verbose than a table, but also more readable.
> 
> A generic write function:
> void mgag200_write_dac(struct dac_data *dac)
> {
> 	int i;
> 
> 	for (i = 0; i < MGA200_REGS) {
> 		if (dac[i].use])
> 			WREG_DAC(i, dac[i]);
> 	}
> }
> 
> 
> Then for each model something like
> 
> void mgag200_g200eh_init_registers(struct mga_device *mdev)
> {
> 	struct dac_data dac[MGA200_REGS];
> 
> 	mgag200_default_regs(&dac];
> 
> 	dac[MGA1064_MISC_CTL].use = true;
> 	dac[MGA1064_MISC_CTL].data = MGA1064_MISC_CTL_VGA8 | /* G200EH specific: MGA1064_MISC_CTL */
> 				     MGA1064_MISC_CTL_DAC_RAM_CS;
> 
> 	/* No PIX_PLL setup */   -- The logic should be reversed I hink, so
>         				    the ones that need PLL setup set to true.
> 				    But the idea is obvious so I did not
> 				    redo it
> 	dac[MGA1064_PIX_PLLA_M].use = false;
> 	dac[MGA1064_PIX_PLLA_N].use = false;
> 	dac[MGA1064_PIX_PLLA_P].use = false;
> 	dac[MGA1064_PIX_PLLB_M].use = false;
> 	dac[MGA1064_PIX_PLLB_N].use = false;
> 	dac[MGA1064_PIX_PLLB_P].use = false;
> 	dac[MGA1064_PIX_PLLC_M].use = false;
> 	dac[MGA1064_PIX_PLLC_N].use = false;
> 	dac[MGA1064_PIX_PLLC_P].use = false;
> 
> 	mgag200_write_dac(&dac);
> }

IMHO that's not going to work well. Algorithms are much more error prone 
than data structures. Moving program expressions from a data structure 
into an algorithm is rarely useful. (Exceptions exist, of course.)

I think, the dupliction of DAC values can be solved by an intializer macro.

   MGAG200_DEFAULT_DAC_VALUES(...) =  \
     ...

and the macro parameter are those values that change among the different 
models. There aren't too many. It won't solve the for-loop for now, but 
it's a start.

In principle, these init_register() functions shouldn't exist at all. 
The initialization of these registers should be done in the CRTC's and 
plane's reset callbacks. [1] Most would then again be possible for share 
a good part if the register init among models. For the PLL, a per-model 
PLL-reset callback can be used.  All that is, however, enough change for 
another complete patchset.

Best regards
Thomas

[1] 
https://elixir.bootlin.com/linux/latest/source/include/drm/drm_crtc.h#L431

> 
> 
>> At some point, some of the initialization should probably move into
>> the modesetting code.
>>
>> Signed-off-by: Thomas Zimmermann <tzimmermann@suse.de>
>> ---
>>   drivers/gpu/drm/mgag200/mgag200_drv.h     |  3 +
>>   drivers/gpu/drm/mgag200/mgag200_g200.c    | 37 +++++++++++
>>   drivers/gpu/drm/mgag200/mgag200_g200eh.c  | 36 ++++++++++
>>   drivers/gpu/drm/mgag200/mgag200_g200eh3.c |  2 +
>>   drivers/gpu/drm/mgag200/mgag200_g200er.c  | 34 ++++++++++
>>   drivers/gpu/drm/mgag200/mgag200_g200ev.c  | 40 ++++++++++++
>>   drivers/gpu/drm/mgag200/mgag200_g200ew3.c |  2 +
>>   drivers/gpu/drm/mgag200/mgag200_g200se.c  | 45 +++++++++++++
>>   drivers/gpu/drm/mgag200/mgag200_g200wb.c  | 34 ++++++++++
>>   drivers/gpu/drm/mgag200/mgag200_mode.c    | 80 +----------------------
>>   10 files changed, 234 insertions(+), 79 deletions(-)
>>
>> diff --git a/drivers/gpu/drm/mgag200/mgag200_drv.h b/drivers/gpu/drm/mgag200/mgag200_drv.h
>> index 301c4ab46539..6a2a1ad914c1 100644
>> --- a/drivers/gpu/drm/mgag200/mgag200_drv.h
>> +++ b/drivers/gpu/drm/mgag200/mgag200_drv.h
>> @@ -295,10 +295,12 @@ struct mga_device *mgag200_g200_device_create(struct pci_dev *pdev, const struct
>>   					      enum mga_type type);
>>   struct mga_device *mgag200_g200se_device_create(struct pci_dev *pdev, const struct drm_driver *drv,
>>   						enum mga_type type);
>> +void mgag200_g200wb_init_registers(struct mga_device *mdev);
>>   struct mga_device *mgag200_g200wb_device_create(struct pci_dev *pdev, const struct drm_driver *drv,
>>   						enum mga_type type);
>>   struct mga_device *mgag200_g200ev_device_create(struct pci_dev *pdev, const struct drm_driver *drv,
>>   						enum mga_type type);
>> +void mgag200_g200eh_init_registers(struct mga_device *mdev);
>>   struct mga_device *mgag200_g200eh_device_create(struct pci_dev *pdev, const struct drm_driver *drv,
>>   						enum mga_type type);
>>   struct mga_device *mgag200_g200eh3_device_create(struct pci_dev *pdev, const struct drm_driver *drv,
>> @@ -310,6 +312,7 @@ struct mga_device *mgag200_g200ew3_device_create(struct pci_dev *pdev, const str
>>   
>>   				/* mgag200_mode.c */
>>   resource_size_t mgag200_device_probe_vram(struct mga_device *mdev);
>> +void mgag200_init_registers(struct mga_device *mdev);
>>   int mgag200_modeset_init(struct mga_device *mdev, resource_size_t vram_fb_available);
>>   
>>   				/* mgag200_i2c.c */
>> diff --git a/drivers/gpu/drm/mgag200/mgag200_g200.c b/drivers/gpu/drm/mgag200/mgag200_g200.c
>> index 674385921b7f..c6303fcb8fe7 100644
>> --- a/drivers/gpu/drm/mgag200/mgag200_g200.c
>> +++ b/drivers/gpu/drm/mgag200/mgag200_g200.c
>> @@ -30,6 +30,41 @@ static int mgag200_g200_init_pci_options(struct pci_dev *pdev)
>>   	return mgag200_init_pci_options(pdev, option, 0x00008000);
>>   }
>>   
>> +static void mgag200_g200_init_registers(struct mgag200_g200_device *g200)
>> +{
>> +	static const u8 dacvalue[] = {
>> +		/* 0x00: */        0,    0,    0,    0,    0,    0,    0,    0,
>> +		/* 0x08: */        0,    0,    0,    0,    0,    0,    0,    0,
>> +		/* 0x10: */        0,    0,    0,    0,    0,    0,    0,    0,
>> +		/* 0x18: */     0x00,    0, 0xC9, 0xFF, 0xBF, 0x20, 0x1F, 0x20,
>> +		/* 0x20: */     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
>> +		/* 0x28: */     0x00, 0x00, 0x00, 0x00,
>> +		/* 0x2c: */	0x04, /* G200 specific: MGA1064_SYS_PLL_M */
>> +		/* 0x2d: */     0x2d, /* G200 specific: MGA1064_SYS_PLL_N */
>> +		/* 0x2e: */     0x19, /* G200 specific: MGA1064_SYS_PLL_P */
>> +		/* 0x2f: */     0x40,
>> +		/* 0x30: */     0x00, 0xB0, 0x00, 0xC2, 0x34, 0x14, 0x02, 0x83,
>> +		/* 0x38: */     0x00, 0x93, 0x00, 0x77, 0x00, 0x00, 0x00, 0x3A,
>> +		/* 0x40: */        0,    0,    0,    0,    0,    0,    0,    0,
>> +		/* 0x48: */        0,    0,    0,    0,    0,    0,    0,    0
>> +	};
>> +
>> +	struct mga_device *mdev = &g200->base;
>> +	size_t i;
>> +
>> +	for (i = 0; i < ARRAY_SIZE(dacvalue); ++i) {
>> +		if ((i <= 0x17) ||
>> +		    (i == 0x1b) ||
>> +		    (i == 0x1c) ||
>> +		    ((i >= 0x1f) && (i <= 0x29)) ||
>> +		    ((i >= 0x30) && (i <= 0x37)))
>> +			continue;
>> +		WREG_DAC(i, dacvalue[i]);
>> +	}
>> +
>> +	mgag200_init_registers(mdev);
>> +}
>> +
>>   /*
>>    * DRM Device
>>    */
>> @@ -191,6 +226,8 @@ struct mga_device *mgag200_g200_device_create(struct pci_dev *pdev, const struct
>>   	if (ret)
>>   		return ERR_PTR(ret);
>>   
>> +	mgag200_g200_init_registers(g200);
>> +
>>   	vram_available = mgag200_device_probe_vram(mdev);
>>   
>>   	ret = mgag200_modeset_init(mdev, vram_available);
>> diff --git a/drivers/gpu/drm/mgag200/mgag200_g200eh.c b/drivers/gpu/drm/mgag200/mgag200_g200eh.c
>> index 1b9a22728744..365f486d3ce7 100644
>> --- a/drivers/gpu/drm/mgag200/mgag200_g200eh.c
>> +++ b/drivers/gpu/drm/mgag200/mgag200_g200eh.c
>> @@ -6,6 +6,40 @@
>>   
>>   #include "mgag200_drv.h"
>>   
>> +void mgag200_g200eh_init_registers(struct mga_device *mdev)
>> +{
>> +	static const u8 dacvalue[] = {
>> +		/* 0x00: */        0,    0,    0,    0,    0,    0,    0,    0,
>> +		/* 0x08: */        0,    0,    0,    0,    0,    0,    0,    0,
>> +		/* 0x10: */        0,    0,    0,    0,    0,    0,    0,    0,
>> +		/* 0x18: */     0x00,    0, 0xC9, 0xFF, 0xBF, 0x20,
>> +		/* 0x1e: */     MGA1064_MISC_CTL_VGA8 | /* G200EH specific: MGA1064_MISC_CTL */
>> +				MGA1064_MISC_CTL_DAC_RAM_CS,
>> +		/* 0x1f: */     0x20,
>> +		/* 0x20: */     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
>> +		/* 0x28: */     0x00, 0x00, 0x00, 0x00,    0,    0,    0, 0x40,
>> +		/* 0x30: */     0x00, 0xB0, 0x00, 0xC2, 0x34, 0x14, 0x02, 0x83,
>> +		/* 0x38: */     0x00, 0x93, 0x00, 0x77, 0x00, 0x00, 0x00, 0x3A,
>> +		/* 0x40: */        0,    0,    0,    0,    0,    0,    0,    0,
>> +		/* 0x48: */        0,    0,    0,    0,    0,    0,    0,    0
>> +	};
>> +
>> +	size_t i;
>> +
>> +	for (i = 0; i < ARRAY_SIZE(dacvalue); i++) {
>> +		if ((i <= 0x17) ||
>> +		    (i == 0x1b) ||
>> +		    (i == 0x1c) ||
>> +		    ((i >= 0x1f) && (i <= 0x29)) ||
>> +		    ((i >= 0x30) && (i <= 0x37)) ||
>> +		    ((i >= 0x44) && (i <= 0x4e)))
>> +			continue;
>> +		WREG_DAC(i, dacvalue[i]);
>> +	}
>> +
>> +	mgag200_init_registers(mdev);
>> +}
>> +
>>   /*
>>    * DRM device
>>    */
>> @@ -40,6 +74,8 @@ struct mga_device *mgag200_g200eh_device_create(struct pci_dev *pdev, const stru
>>   	if (ret)
>>   		return ERR_PTR(ret);
>>   
>> +	mgag200_g200eh_init_registers(mdev);
>> +
>>   	vram_available = mgag200_device_probe_vram(mdev);
>>   
>>   	ret = mgag200_modeset_init(mdev, vram_available);
>> diff --git a/drivers/gpu/drm/mgag200/mgag200_g200eh3.c b/drivers/gpu/drm/mgag200/mgag200_g200eh3.c
>> index 438cda1b14c9..adb9190b62af 100644
>> --- a/drivers/gpu/drm/mgag200/mgag200_g200eh3.c
>> +++ b/drivers/gpu/drm/mgag200/mgag200_g200eh3.c
>> @@ -41,6 +41,8 @@ struct mga_device *mgag200_g200eh3_device_create(struct pci_dev *pdev,
>>   	if (ret)
>>   		return ERR_PTR(ret);
>>   
>> +	mgag200_g200eh_init_registers(mdev); // same as G200EH
>> +
>>   	vram_available = mgag200_device_probe_vram(mdev);
>>   
>>   	ret = mgag200_modeset_init(mdev, vram_available);
>> diff --git a/drivers/gpu/drm/mgag200/mgag200_g200er.c b/drivers/gpu/drm/mgag200/mgag200_g200er.c
>> index 0790d4e6463d..acdccc419944 100644
>> --- a/drivers/gpu/drm/mgag200/mgag200_g200er.c
>> +++ b/drivers/gpu/drm/mgag200/mgag200_g200er.c
>> @@ -6,6 +6,38 @@
>>   
>>   #include "mgag200_drv.h"
>>   
>> +static void mgag200_g200er_init_registers(struct mga_device *mdev)
>> +{
>> +	static const u8 dacvalue[] = {
>> +		/* 0x00: */        0,    0,    0,    0,    0,    0,    0,    0,
>> +		/* 0x08: */        0,    0,    0,    0,    0,    0,    0,    0,
>> +		/* 0x10: */        0,    0,    0,    0,    0,    0,    0,    0,
>> +		/* 0x18: */     0x00,    0, 0xC9, 0xFF, 0xBF, 0x20, 0x1F, 0x20,
>> +		/* 0x20: */     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
>> +		/* 0x28: */     0x00, 0x00, 0x00, 0x00,    0,    0,    0, 0x40,
>> +		/* 0x30: */     0x00, 0xB0, 0x00, 0xC2, 0x34, 0x14, 0x02, 0x83,
>> +		/* 0x38: */     0x00, 0x93, 0x00, 0x77, 0x00, 0x00, 0x00, 0x3A,
>> +		/* 0x40: */        0,    0,    0,    0,    0,    0,    0,    0,
>> +		/* 0x48: */        0,    0,    0,    0,    0,    0,    0,    0
>> +	};
>> +
>> +	size_t i;
>> +
>> +	for (i = 0; i < ARRAY_SIZE(dacvalue); i++) {
>> +		if ((i <= 0x17) ||
>> +		    (i == 0x1b) ||
>> +		    (i == 0x1c) ||
>> +		    ((i >= 0x1f) && (i <= 0x29)) ||
>> +		    ((i >= 0x30) && (i <= 0x37)))
>> +			continue;
>> +		WREG_DAC(i, dacvalue[i]);
>> +	}
>> +
>> +	WREG_DAC(0x90, 0); /* G200ER specific */
>> +
>> +	mgag200_init_registers(mdev);
>> +}
>> +
>>   /*
>>    * DRM device
>>    */
>> @@ -36,6 +68,8 @@ struct mga_device *mgag200_g200er_device_create(struct pci_dev *pdev, const stru
>>   	if (ret)
>>   		return ERR_PTR(ret);
>>   
>> +	mgag200_g200er_init_registers(mdev);
>> +
>>   	vram_available = mgag200_device_probe_vram(mdev);
>>   
>>   	ret = mgag200_modeset_init(mdev, vram_available);
>> diff --git a/drivers/gpu/drm/mgag200/mgag200_g200ev.c b/drivers/gpu/drm/mgag200/mgag200_g200ev.c
>> index 5353422d0eef..ce26d48c9691 100644
>> --- a/drivers/gpu/drm/mgag200/mgag200_g200ev.c
>> +++ b/drivers/gpu/drm/mgag200/mgag200_g200ev.c
>> @@ -6,6 +6,44 @@
>>   
>>   #include "mgag200_drv.h"
>>   
>> +static void mgag200_g200ev_init_registers(struct mga_device *mdev)
>> +{
>> +	static const u8 dacvalue[] = {
>> +		/* 0x00: */        0,    0,    0,    0,    0,    0,    0,    0,
>> +		/* 0x08: */        0,    0,    0,    0,    0,    0,    0,    0,
>> +		/* 0x10: */        0,    0,    0,    0,    0,    0,    0,    0,
>> +		/* 0x18: */     0x00,    0,
>> +				/* G200EV specific: MGA1064_PIX_CLK_CTL */
>> +		/* 0x1a: */     MGA1064_PIX_CLK_CTL_SEL_PLL,
>> +		/* 0x1b: */     0xFF, 0xBF, 0x20,
>> +				/* G200EV specific: MGA1064_MISC_CTL */
>> +		/* 0x1e: */     MGA1064_MISC_CTL_VGA8 |
>> +				MGA1064_MISC_CTL_DAC_RAM_CS,
>> +		/* 0x1f: */     0x20,
>> +		/* 0x20: */     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
>> +		/* 0x28: */     0x00, 0x00, 0x00, 0x00,    0,    0,    0, 0x40,
>> +		/* 0x30: */     0x00, 0xB0, 0x00, 0xC2, 0x34, 0x14, 0x02, 0x83,
>> +		/* 0x38: */     0x00, 0x93, 0x00, 0x77, 0x00, 0x00, 0x00, 0x3A,
>> +		/* 0x40: */        0,    0,    0,    0,    0,    0,    0,    0,
>> +		/* 0x48: */        0,    0,    0,    0,    0,    0,    0,    0
>> +	};
>> +
>> +	size_t i;
>> +
>> +	for (i = 0; i < ARRAY_SIZE(dacvalue); i++) {
>> +		if ((i <= 0x17) ||
>> +		    (i == 0x1b) ||
>> +		    (i == 0x1c) ||
>> +		    ((i >= 0x1f) && (i <= 0x29)) ||
>> +		    ((i >= 0x30) && (i <= 0x37)) ||
>> +		    ((i >= 0x44) && (i <= 0x4e)))
>> +			continue;
>> +		WREG_DAC(i, dacvalue[i]);
>> +	}
>> +
>> +	mgag200_init_registers(mdev);
>> +}
>> +
>>   /*
>>    * DRM device
>>    */
>> @@ -40,6 +78,8 @@ struct mga_device *mgag200_g200ev_device_create(struct pci_dev *pdev, const stru
>>   	if (ret)
>>   		return ERR_PTR(ret);
>>   
>> +	mgag200_g200ev_init_registers(mdev);
>> +
>>   	vram_available = mgag200_device_probe_vram(mdev);
>>   
>>   	ret = mgag200_modeset_init(mdev, vram_available);
>> diff --git a/drivers/gpu/drm/mgag200/mgag200_g200ew3.c b/drivers/gpu/drm/mgag200/mgag200_g200ew3.c
>> index 3bfc1324cf78..d86284c0eb4d 100644
>> --- a/drivers/gpu/drm/mgag200/mgag200_g200ew3.c
>> +++ b/drivers/gpu/drm/mgag200/mgag200_g200ew3.c
>> @@ -50,6 +50,8 @@ struct mga_device *mgag200_g200ew3_device_create(struct pci_dev *pdev,
>>   	if (ret)
>>   		return ERR_PTR(ret);
>>   
>> +	mgag200_g200wb_init_registers(mdev); // same as G200WB
>> +
>>   	vram_available = mgag200_g200ew3_device_probe_vram(mdev);
>>   
>>   	ret = mgag200_modeset_init(mdev, vram_available);
>> diff --git a/drivers/gpu/drm/mgag200/mgag200_g200se.c b/drivers/gpu/drm/mgag200/mgag200_g200se.c
>> index 0a3e66695e22..9f51be8ef731 100644
>> --- a/drivers/gpu/drm/mgag200/mgag200_g200se.c
>> +++ b/drivers/gpu/drm/mgag200/mgag200_g200se.c
>> @@ -28,6 +28,49 @@ static int mgag200_g200se_init_pci_options(struct pci_dev *pdev)
>>   	return mgag200_init_pci_options(pdev, option, 0x00008000);
>>   }
>>   
>> +static void mgag200_g200se_init_registers(struct mgag200_g200se_device *g200se)
>> +{
>> +	static const u8 dacvalue[] = {
>> +		/* 0x00: */        0,    0,    0,    0,    0,    0, 0x00,    0,
>> +		/* 0x08: */        0,    0,    0,    0,    0,    0,    0,    0,
>> +		/* 0x10: */        0,    0,    0,    0,    0,    0,    0,    0,
>> +				/* G200SE specific: MGA1064_VREF_CTL */
>> +		/* 0x18: */     0x03,
>> +		/* 0x19: */        0,
>> +				/* G200EV specific: MGA1064_PIX_CLK_CTL */
>> +		/* 0x1a: */     MGA1064_PIX_CLK_CTL_SEL_PLL,
>> +		/* 0x1b: */     0xFF, 0xBF, 0x20,
>> +				/* G200EV specific: MGA1064_MISC_CTL */
>> +		/* 0x1e: */     MGA1064_MISC_CTL_DAC_EN |
>> +				MGA1064_MISC_CTL_VGA8 |
>> +				MGA1064_MISC_CTL_DAC_RAM_CS,
>> +
>> +		/* 0x19: */        0, 0xC9, 0xFF, 0xBF, 0x20, 0x1F, 0x20,
>> +		/* 0x20: */     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
>> +		/* 0x28: */     0x00, 0x00, 0x00, 0x00,    0,    0,    0, 0x40,
>> +		/* 0x30: */     0x00, 0xB0, 0x00, 0xC2, 0x34, 0x14, 0x02, 0x83,
>> +		/* 0x38: */     0x00, 0x93, 0x00, 0x77, 0x00, 0x00, 0x00, 0x3A,
>> +		/* 0x40: */        0,    0,    0,    0,    0,    0,    0,    0,
>> +		/* 0x48: */        0,    0,    0,    0,    0,    0,    0,    0
>> +	};
>> +
>> +	struct mga_device *mdev = &g200se->base;
>> +	size_t i;
>> +
>> +	for (i = 0; i < ARRAY_SIZE(dacvalue); i++) {
>> +		if ((i <= 0x17) ||
>> +		    (i == 0x1b) ||
>> +		    (i == 0x1c) ||
>> +		    ((i >= 0x1f) && (i <= 0x29)) ||
>> +		    ((i == 0x2c) || (i == 0x2d) || (i == 0x2e)) ||
>> +		    ((i >= 0x30) && (i <= 0x37)))
>> +			continue;
>> +		WREG_DAC(i, dacvalue[i]);
>> +	}
>> +
>> +	mgag200_init_registers(mdev);
>> +}
>> +
>>   /*
>>    * DRM device
>>    */
>> @@ -120,6 +163,8 @@ struct mga_device *mgag200_g200se_device_create(struct pci_dev *pdev, const stru
>>   	if (ret)
>>   		return ERR_PTR(ret);
>>   
>> +	mgag200_g200se_init_registers(g200se);
>> +
>>   	vram_available = mgag200_device_probe_vram(mdev);
>>   
>>   	ret = mgag200_modeset_init(mdev, vram_available);
>> diff --git a/drivers/gpu/drm/mgag200/mgag200_g200wb.c b/drivers/gpu/drm/mgag200/mgag200_g200wb.c
>> index c8450ac8eaec..e4de4b2dc2e2 100644
>> --- a/drivers/gpu/drm/mgag200/mgag200_g200wb.c
>> +++ b/drivers/gpu/drm/mgag200/mgag200_g200wb.c
>> @@ -6,6 +6,38 @@
>>   
>>   #include "mgag200_drv.h"
>>   
>> +void mgag200_g200wb_init_registers(struct mga_device *mdev)
>> +{
>> +	static const u8 dacvalue[] = {
>> +		/* 0x00: */        0,    0,    0,    0,    0,    0,    0,    0,
>> +		/* 0x08: */        0,    0,    0,    0,    0,    0,    0,    0,
>> +		/* 0x10: */        0,    0,    0,    0,    0,    0,    0,    0,
>> +		/* 0x18: */     0x07, /* G200WB specific: MGA1064_VREF_CTL */
>> +		/* 0x19: */        0, 0xC9, 0xFF, 0xBF, 0x20, 0x1F, 0x20,
>> +		/* 0x20: */     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
>> +		/* 0x28: */     0x00, 0x00, 0x00, 0x00,    0,    0,    0, 0x40,
>> +		/* 0x30: */     0x00, 0xB0, 0x00, 0xC2, 0x34, 0x14, 0x02, 0x83,
>> +		/* 0x38: */     0x00, 0x93, 0x00, 0x77, 0x00, 0x00, 0x00, 0x3A,
>> +		/* 0x40: */        0,    0,    0,    0,    0,    0,    0,    0,
>> +		/* 0x48: */        0,    0,    0,    0,    0,    0,    0,    0
>> +	};
>> +
>> +	size_t i;
>> +
>> +	for (i = 0; i < ARRAY_SIZE(dacvalue); i++) {
>> +		if ((i <= 0x17) ||
>> +		    (i == 0x1b) ||
>> +		    (i == 0x1c) ||
>> +		    ((i >= 0x1f) && (i <= 0x29)) ||
>> +		    ((i >= 0x30) && (i <= 0x37)) ||
>> +		    ((i >= 0x44) && (i <= 0x4e)))
>> +			continue;
>> +		WREG_DAC(i, dacvalue[i]);
>> +	}
>> +
>> +	mgag200_init_registers(mdev);
>> +}
>> +
>>   /*
>>    * DRM device
>>    */
>> @@ -40,6 +72,8 @@ struct mga_device *mgag200_g200wb_device_create(struct pci_dev *pdev, const stru
>>   	if (ret)
>>   		return ERR_PTR(ret);
>>   
>> +	mgag200_g200wb_init_registers(mdev);
>> +
>>   	vram_available = mgag200_device_probe_vram(mdev);
>>   
>>   	ret = mgag200_modeset_init(mdev, vram_available);
>> diff --git a/drivers/gpu/drm/mgag200/mgag200_mode.c b/drivers/gpu/drm/mgag200/mgag200_mode.c
>> index e08852482fe2..f9868d728e6d 100644
>> --- a/drivers/gpu/drm/mgag200/mgag200_mode.c
>> +++ b/drivers/gpu/drm/mgag200/mgag200_mode.c
>> @@ -267,86 +267,10 @@ static void mgag200_set_startadd(struct mga_device *mdev,
>>   	WREG_ECRT(0x00, crtcext0);
>>   }
>>   
>> -static void mgag200_set_dac_regs(struct mga_device *mdev)
>> -{
>> -	size_t i;
>> -	u8 dacvalue[] = {
>> -		/* 0x00: */        0,    0,    0,    0,    0,    0, 0x00,    0,
>> -		/* 0x08: */        0,    0,    0,    0,    0,    0,    0,    0,
>> -		/* 0x10: */        0,    0,    0,    0,    0,    0,    0,    0,
>> -		/* 0x18: */     0x00,    0, 0xC9, 0xFF, 0xBF, 0x20, 0x1F, 0x20,
>> -		/* 0x20: */     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
>> -		/* 0x28: */     0x00, 0x00, 0x00, 0x00,    0,    0,    0, 0x40,
>> -		/* 0x30: */     0x00, 0xB0, 0x00, 0xC2, 0x34, 0x14, 0x02, 0x83,
>> -		/* 0x38: */     0x00, 0x93, 0x00, 0x77, 0x00, 0x00, 0x00, 0x3A,
>> -		/* 0x40: */        0,    0,    0,    0,    0,    0,    0,    0,
>> -		/* 0x48: */        0,    0,    0,    0,    0,    0,    0,    0
>> -	};
>> -
>> -	switch (mdev->type) {
>> -	case G200_PCI:
>> -	case G200_AGP:
>> -		dacvalue[MGA1064_SYS_PLL_M] = 0x04;
>> -		dacvalue[MGA1064_SYS_PLL_N] = 0x2D;
>> -		dacvalue[MGA1064_SYS_PLL_P] = 0x19;
>> -		break;
>> -	case G200_SE_A:
>> -	case G200_SE_B:
>> -		dacvalue[MGA1064_VREF_CTL] = 0x03;
>> -		dacvalue[MGA1064_PIX_CLK_CTL] = MGA1064_PIX_CLK_CTL_SEL_PLL;
>> -		dacvalue[MGA1064_MISC_CTL] = MGA1064_MISC_CTL_DAC_EN |
>> -					     MGA1064_MISC_CTL_VGA8 |
>> -					     MGA1064_MISC_CTL_DAC_RAM_CS;
>> -		break;
>> -	case G200_WB:
>> -	case G200_EW3:
>> -		dacvalue[MGA1064_VREF_CTL] = 0x07;
>> -		break;
>> -	case G200_EV:
>> -		dacvalue[MGA1064_PIX_CLK_CTL] = MGA1064_PIX_CLK_CTL_SEL_PLL;
>> -		dacvalue[MGA1064_MISC_CTL] = MGA1064_MISC_CTL_VGA8 |
>> -					     MGA1064_MISC_CTL_DAC_RAM_CS;
>> -		break;
>> -	case G200_EH:
>> -	case G200_EH3:
>> -		dacvalue[MGA1064_MISC_CTL] = MGA1064_MISC_CTL_VGA8 |
>> -					     MGA1064_MISC_CTL_DAC_RAM_CS;
>> -		break;
>> -	case G200_ER:
>> -		break;
>> -	}
>> -
>> -	for (i = 0; i < ARRAY_SIZE(dacvalue); i++) {
>> -		if ((i <= 0x17) ||
>> -		    (i == 0x1b) ||
>> -		    (i == 0x1c) ||
>> -		    ((i >= 0x1f) && (i <= 0x29)) ||
>> -		    ((i >= 0x30) && (i <= 0x37)))
>> -			continue;
>> -		if (IS_G200_SE(mdev) &&
>> -		    ((i == 0x2c) || (i == 0x2d) || (i == 0x2e)))
>> -			continue;
>> -		if ((mdev->type == G200_EV ||
>> -		    mdev->type == G200_WB ||
>> -		    mdev->type == G200_EH ||
>> -		    mdev->type == G200_EW3 ||
>> -		    mdev->type == G200_EH3) &&
>> -		    (i >= 0x44) && (i <= 0x4e))
>> -			continue;
>> -
>> -		WREG_DAC(i, dacvalue[i]);
>> -	}
>> -
>> -	if (mdev->type == G200_ER)
>> -		WREG_DAC(0x90, 0);
>> -}
>> -
>> -static void mgag200_init_regs(struct mga_device *mdev)
>> +void mgag200_init_registers(struct mga_device *mdev)
>>   {
>>   	u8 crtc11, misc;
>>   
>> -	mgag200_set_dac_regs(mdev);
>> -
>>   	WREG_SEQ(2, 0x0f);
>>   	WREG_SEQ(3, 0x00);
>>   	WREG_SEQ(4, 0x0e);
>> @@ -1127,8 +1051,6 @@ int mgag200_modeset_init(struct mga_device *mdev, resource_size_t vram_available
>>   	struct drm_device *dev = &mdev->base;
>>   	int ret;
>>   
>> -	mgag200_init_regs(mdev);
>> -
>>   	ret = mgag200_mode_config_init(mdev, vram_available);
>>   	if (ret)
>>   		return ret;
>> -- 
>> 2.36.1

-- 
Thomas Zimmermann
Graphics Driver Developer
SUSE Software Solutions Germany GmbH
Maxfeldstr. 5, 90409 Nürnberg, Germany
(HRB 36809, AG Nürnberg)
Geschäftsführer: Ivo Totev

[-- Attachment #2: OpenPGP digital signature --]
[-- Type: application/pgp-signature, Size: 840 bytes --]

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

* Re: [PATCH 00/14] drm/mgag200: Move model-specific code into separate functions
  2022-07-08 17:22 ` [PATCH 00/14] drm/mgag200: Move model-specific code into separate functions Sam Ravnborg
@ 2022-07-11  7:29   ` Thomas Zimmermann
  2022-07-11 16:20     ` Jocelyn Falempe
  0 siblings, 1 reply; 28+ messages in thread
From: Thomas Zimmermann @ 2022-07-11  7:29 UTC (permalink / raw)
  To: Sam Ravnborg; +Cc: airlied, airlied, jfalempe, dri-devel


[-- Attachment #1.1: Type: text/plain, Size: 2597 bytes --]

Hi Sam,

thanks for reviewing.

Am 08.07.22 um 19:22 schrieb Sam Ravnborg:
> Hi Thomas,
> 
> On Fri, Jul 08, 2022 at 11:39:15AM +0200, Thomas Zimmermann wrote:
>> Mgag200 still mixes model-specific code and generic code in the same
>> functions. Separate it into distinct helpers.
>>
>> As part of this effort, convert the driver from simple-KMS helpers
>> to regular atomic helpers. The latter are way more flexible and can
>> be adapted easily for each hardware model.
>>
>> Tested on Matrox G200 and G200EH hardware.
>>
>> Thomas Zimmermann (14):
>>    drm/mgag200: Split mgag200_modeset_init()
>>    drm/mgag200: Move DAC-register setup into model-specific code
>>    dmr/mgag200: Move ER/EW3 register initializatino to per-model code
>>    drm/mgag200: Acquire I/O-register lock in atomic_commit_tail function
>>    drm/mgag200: Store primary plane's color format in CRTC state
>>    drm/mgag200: Reorganize before dropping simple-KMS helpers
>>    drm/mgag200: Replace simple-KMS with regular atomic helpers
>>    drm/mgag200: Set SCROFF in primary-plane code
>>    drm/mgag200: Add per-device callbacks
>>    drm/mgag200: Provide per-device callbacks for BMC synchronization
>>    drm/mgag200: Provide per-device callbacks for PIXPLLC
>>    drm/mgag200: Move mode-config to model-specific code
>>    drm/mgag200: Move CRTC atomic_enable to model-specfic code
>>    drm/mgag200: Remove type field from struct mga_device
> 
> I have browsed the patches and they looked good.
> I was about to complain about several things, like bmc init, but then
> later this is all nicely cleaned up.
> Especially the pll setup stuff did not get much scrunity, as it like
> most of the patch looked like code movements.

Indeed. The patch moves code and adapts the functions' interfaces to the 
new callbacks. But the implementation remains the same.

> 
> All patches except "Move DAC-register setup into model-specific code"
> are:
> Acked-by: Sam Ravnborg <sam@ravnborg.org>
> 
> 
>>   14 files changed, 2804 insertions(+), 1586 deletions(-)
> This is not a diffstat that makes one go - yyipeee.
> But the improvements makes it worthwhile.

Yeah. I accept a grow in driver size in exchange for the more cleanly 
structured code base. In my reply to the DAC review, I outline ways to 
re-share some of the duplicated code.

Best regards
Thomas

> 
> 	Sam

-- 
Thomas Zimmermann
Graphics Driver Developer
SUSE Software Solutions Germany GmbH
Maxfeldstr. 5, 90409 Nürnberg, Germany
(HRB 36809, AG Nürnberg)
Geschäftsführer: Ivo Totev

[-- Attachment #2: OpenPGP digital signature --]
[-- Type: application/pgp-signature, Size: 840 bytes --]

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

* Re: [PATCH 00/14] drm/mgag200: Move model-specific code into separate functions
  2022-07-11  7:29   ` Thomas Zimmermann
@ 2022-07-11 16:20     ` Jocelyn Falempe
  0 siblings, 0 replies; 28+ messages in thread
From: Jocelyn Falempe @ 2022-07-11 16:20 UTC (permalink / raw)
  To: Thomas Zimmermann, Sam Ravnborg; +Cc: airlied, airlied, dri-devel

On 11/07/2022 09:29, Thomas Zimmermann wrote:
> Hi Sam,
> 
> thanks for reviewing.
> 
> Am 08.07.22 um 19:22 schrieb Sam Ravnborg:
>> Hi Thomas,
>>
>> On Fri, Jul 08, 2022 at 11:39:15AM +0200, Thomas Zimmermann wrote:
>>> Mgag200 still mixes model-specific code and generic code in the same
>>> functions. Separate it into distinct helpers.
>>>
>>> As part of this effort, convert the driver from simple-KMS helpers
>>> to regular atomic helpers. The latter are way more flexible and can
>>> be adapted easily for each hardware model.
>>>
>>> Tested on Matrox G200 and G200EH hardware.
>>>
>>> Thomas Zimmermann (14):
>>>    drm/mgag200: Split mgag200_modeset_init()
>>>    drm/mgag200: Move DAC-register setup into model-specific code
>>>    dmr/mgag200: Move ER/EW3 register initializatino to per-model code
>>>    drm/mgag200: Acquire I/O-register lock in atomic_commit_tail function
>>>    drm/mgag200: Store primary plane's color format in CRTC state
>>>    drm/mgag200: Reorganize before dropping simple-KMS helpers
>>>    drm/mgag200: Replace simple-KMS with regular atomic helpers
>>>    drm/mgag200: Set SCROFF in primary-plane code
>>>    drm/mgag200: Add per-device callbacks
>>>    drm/mgag200: Provide per-device callbacks for BMC synchronization
>>>    drm/mgag200: Provide per-device callbacks for PIXPLLC
>>>    drm/mgag200: Move mode-config to model-specific code
>>>    drm/mgag200: Move CRTC atomic_enable to model-specfic code
>>>    drm/mgag200: Remove type field from struct mga_device
>>
>> I have browsed the patches and they looked good.
>> I was about to complain about several things, like bmc init, but then
>> later this is all nicely cleaned up.
>> Especially the pll setup stuff did not get much scrunity, as it like
>> most of the patch looked like code movements.
> 
> Indeed. The patch moves code and adapts the functions' interfaces to the 
> new callbacks. But the implementation remains the same.

I've read the whole serie, and it's good overall.
I agree with Sam about the duplication of the DAC-registers setup, but 
that can be solved later.

I have also tested this patchset on a G200eW, and have seen no regression.

Reviewed-by: Jocelyn Falempe <jfalempe@redhat.com>
Tested-by: Jocelyn Falempe <jfalempe@redhat.com>

> 
>>
>> All patches except "Move DAC-register setup into model-specific code"
>> are:
>> Acked-by: Sam Ravnborg <sam@ravnborg.org>
>>
>>
>>>   14 files changed, 2804 insertions(+), 1586 deletions(-)
>> This is not a diffstat that makes one go - yyipeee.
>> But the improvements makes it worthwhile.
> 
> Yeah. I accept a grow in driver size in exchange for the more cleanly 
> structured code base. In my reply to the DAC review, I outline ways to 
> re-share some of the duplicated code.
> 
> Best regards
> Thomas
> 
>>
>>     Sam
> 


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

* Re: [PATCH 07/14] drm/mgag200: Replace simple-KMS with regular atomic helpers
       [not found]   ` <20230425142519.13201-1-kernel@linuxace.com>
@ 2023-04-25 15:03     ` Thomas Zimmermann
  2023-04-25 15:48       ` Jocelyn Falempe
                         ` (2 more replies)
  0 siblings, 3 replies; 28+ messages in thread
From: Thomas Zimmermann @ 2023-04-25 15:03 UTC (permalink / raw)
  To: kernel; +Cc: Jocelyn Falempe, Sam Ravnborg, dri-devel


[-- Attachment #1.1: Type: text/plain, Size: 1682 bytes --]

(cc'ing dri-devel, Jocelyn and Sam)

Hi Phil,

I've put dri-devel into cc, which is the developer's mailing list. It's 
the first time I hear about this bug.

Am 25.04.23 um 16:25 schrieb kernel@linuxace.com:
> Hi Thomas,
> 
> I have been trying to track down why we lost console on our Dell servers since
> switching to kernel 6.1, and finally narrowed it down to the commit referenced
> in the subject (1baf9127c482).  If I boot kernel 1baf9127c482, I will have
> no console at all on my servers.  Booting the prior kernel (4f4dc37e374c) restores
> console.  The server I am testing on has a G200EH card.
> 
> There is a bug report about this (not opened by me) here:
> 
> https://bugzilla.redhat.com/show_bug.cgi?id=2171155
> 
> but I'm not sure if RedHat bugzilla is the best place to report this.  Any
> suggestions for a better place?  I'm available for any testing.  I've already
> tried simply reverting this commit from 6.1 but it does not reverse cleanly
> given all the other MGA changes made after this specific commit.  Any
> guidance you could provide is appreciated.

You cannot really revert it, as it's too old already. But could you 
please try the latest developer tree from

   git://anongit.freedesktop.org/drm/drm-tip

The branch is drm-tip. Maybe the bug has been fixed meanwhile. If this 
also doesn't work, we can take a closer look at the changes.

Best regards
Thomas

> 
> Thanks,
> Phil

-- 
Thomas Zimmermann
Graphics Driver Developer
SUSE Software Solutions Germany GmbH
Frankenstrasse 146, 90461 Nuernberg, Germany
GF: Ivo Totev, Andrew Myers, Andrew McDonald, Boudien Moerman
HRB 36809 (AG Nuernberg)

[-- Attachment #2: OpenPGP digital signature --]
[-- Type: application/pgp-signature, Size: 840 bytes --]

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

* Re: [PATCH 07/14] drm/mgag200: Replace simple-KMS with regular atomic helpers
  2023-04-25 15:03     ` Thomas Zimmermann
@ 2023-04-25 15:48       ` Jocelyn Falempe
  2023-04-25 19:56       ` kernel
  2023-04-25 23:39       ` kernel
  2 siblings, 0 replies; 28+ messages in thread
From: Jocelyn Falempe @ 2023-04-25 15:48 UTC (permalink / raw)
  To: Thomas Zimmermann, kernel; +Cc: Sam Ravnborg, dri-devel

On 25/04/2023 17:03, Thomas Zimmermann wrote:
> (cc'ing dri-devel, Jocelyn and Sam)
> 
> Hi Phil,
> 
> I've put dri-devel into cc, which is the developer's mailing list. It's 
> the first time I hear about this bug.

Thanks for pointing this to me, I will take a look at it.

-- 

Jocelyn
> 
> Am 25.04.23 um 16:25 schrieb kernel@linuxace.com:
>> Hi Thomas,
>>
>> I have been trying to track down why we lost console on our Dell 
>> servers since
>> switching to kernel 6.1, and finally narrowed it down to the commit 
>> referenced
>> in the subject (1baf9127c482).  If I boot kernel 1baf9127c482, I will 
>> have
>> no console at all on my servers.  Booting the prior kernel 
>> (4f4dc37e374c) restores
>> console.  The server I am testing on has a G200EH card.
>>
>> There is a bug report about this (not opened by me) here:
>>
>> https://bugzilla.redhat.com/show_bug.cgi?id=2171155
>>
>> but I'm not sure if RedHat bugzilla is the best place to report this.  
>> Any
>> suggestions for a better place?  I'm available for any testing.  I've 
>> already
>> tried simply reverting this commit from 6.1 but it does not reverse 
>> cleanly
>> given all the other MGA changes made after this specific commit.  Any
>> guidance you could provide is appreciated.
> 
> You cannot really revert it, as it's too old already. But could you 
> please try the latest developer tree from
> 
>    git://anongit.freedesktop.org/drm/drm-tip
> 
> The branch is drm-tip. Maybe the bug has been fixed meanwhile. If this 
> also doesn't work, we can take a closer look at the changes.
> 
> Best regards
> Thomas
> 
>>
>> Thanks,
>> Phil
> 


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

* RE: [PATCH 07/14] drm/mgag200: Replace simple-KMS with regular atomic helpers
  2023-04-25 15:03     ` Thomas Zimmermann
  2023-04-25 15:48       ` Jocelyn Falempe
@ 2023-04-25 19:56       ` kernel
  2023-04-25 23:39       ` kernel
  2 siblings, 0 replies; 28+ messages in thread
From: kernel @ 2023-04-25 19:56 UTC (permalink / raw)
  To: tzimmermann; +Cc: kernel, jfalempe, sam, dri-devel

On Tue, Apr 25, 2023 at 8:03 AM Thomas Zimmermann <tzimmermann@suse.de> wrote:
>  You cannot really revert it, as it's too old already. But could you
>  please try the latest developer tree from
>
>     git://anongit.freedesktop.org/drm/drm-tip
>
>  The branch is drm-tip. Maybe the bug has been fixed meanwhile. If this
>  also doesn't work, we can take a closer look at the changes.

I tried drm-tip, and it did not help.

Thanks,
Phil

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

* RE: [PATCH 07/14] drm/mgag200: Replace simple-KMS with regular atomic helpers
  2023-04-25 15:03     ` Thomas Zimmermann
  2023-04-25 15:48       ` Jocelyn Falempe
  2023-04-25 19:56       ` kernel
@ 2023-04-25 23:39       ` kernel
  2023-04-26  7:01         ` Thomas Zimmermann
  2 siblings, 1 reply; 28+ messages in thread
From: kernel @ 2023-04-25 23:39 UTC (permalink / raw)
  To: tzimmermann; +Cc: kernel, jfalempe, sam, dri-devel

I'm not sure if this information is useful, but we have found one system which
works with the 6.1 kernel.  I grabbed the lspci output from a working and
non-working system, pasted below.  Same kernel and same distro.  

BAD Dell R815 AMD
0a:03.0 VGA compatible controller: Matrox Electronics Systems Ltd. MGA G200eW
        WPCM450 (rev 0a) (prog-if 00 [VGA controller])
       DeviceName: Embedded Video                           
       Subsystem: Dell Device 0444
       Control: I/O+ Mem+ BusMaster+ SpecCycle- MemWINV- VGASnoop- ParErr- Stepping- SERR- FastB2B- DisINTx-
       Status: Cap+ 66MHz- UDF- FastB2B+ ParErr- DEVSEL=medium >TAbort- <TAbort- <MAbort- >SERR- <PERR- INTx-
       Latency: 32 (4000ns min, 8000ns max), Cache Line Size: 64 bytes
       Interrupt: pin A routed to IRQ 5
       NUMA node: 0
       IOMMU group: 10
       Region 0: Memory at ec800000 (32-bit, prefetchable) [size=8M]
       Region 1: Memory at ef7fc000 (32-bit, non-prefetchable) [size=16K]
       Region 2: Memory at ee800000 (32-bit, non-prefetchable) [size=8M]
       Expansion ROM at 000c0000 [virtual] [disabled] [size=128K]
       Capabilities: [dc] Power Management version 1
               Flags: PMEClk- DSI+ D1- D2- AuxCurrent=0mA PME(D0-,D1-,D2-,D3hot-,D3cold-)
               Status: D0 NoSoftRst- PME-Enable- DSel=0 DScale=0 PME-
00: 2b 10 32 05 07 00 90 02 0a 00 00 03 10 20 00 00
10: 08 00 80 ec 00 c0 7f ef 00 00 80 ee 00 00 00 00
20: 00 00 00 00 00 00 00 00 00 00 00 00 28 10 44 04
30: 00 00 00 00 dc 00 00 00 00 00 00 00 05 01 10 20

GOOD Dell R710 INTEL
0a:03.0 VGA compatible controller: Matrox Electronics Systems Ltd. MGA G200eW
        WPCM450 (rev 0a) (prog-if 00 [VGA controller])
       DeviceName: Embedded Video                           
       Subsystem: Dell PowerEdge R710 MGA G200eW WPCM450
       Control: I/O+ Mem+ BusMaster+ SpecCycle- MemWINV- VGASnoop- ParErr- Stepping- SERR- FastB2B- DisINTx-
       Status: Cap+ 66MHz- UDF- FastB2B+ ParErr- DEVSEL=medium >TAbort- <TAbort- <MAbort- >SERR- <PERR- INTx-
       Latency: 32 (4000ns min, 8000ns max), Cache Line Size: 64 bytes
       Interrupt: pin A routed to IRQ 10
       Region 0: Memory at d5000000 (32-bit, prefetchable) [size=8M]
       Region 1: Memory at deffc000 (32-bit, non-prefetchable) [size=16K]
       Region 2: Memory at df000000 (32-bit, non-prefetchable) [size=8M]
       Expansion ROM at 000c0000 [virtual] [disabled] [size=128K]
       Capabilities: [dc] Power Management version 1
               Flags: PMEClk- DSI+ D1- D2- AuxCurrent=0mA PME(D0-,D1-,D2-,D3hot-,D3cold-)
               Status: D0 NoSoftRst- PME-Enable- DSel=0 DScale=0 PME-
00: 2b 10 32 05 07 00 90 02 0a 00 00 03 10 20 00 00
10: 08 00 00 d5 00 c0 ff de 00 00 00 df 00 00 00 00
20: 00 00 00 00 00 00 00 00 00 00 00 00 28 10 35 02
30: 00 00 00 00 dc 00 00 00 00 00 00 00 0a 01 10 20

Phil

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

* Re: [PATCH 07/14] drm/mgag200: Replace simple-KMS with regular atomic helpers
  2023-04-25 23:39       ` kernel
@ 2023-04-26  7:01         ` Thomas Zimmermann
  2023-04-26 10:15           ` Thomas Zimmermann
  0 siblings, 1 reply; 28+ messages in thread
From: Thomas Zimmermann @ 2023-04-26  7:01 UTC (permalink / raw)
  To: kernel; +Cc: jfalempe, sam, dri-devel


[-- Attachment #1.1: Type: text/plain, Size: 3525 bytes --]

Hi

Am 26.04.23 um 01:39 schrieb kernel@linuxace.com:
> I'm not sure if this information is useful, but we have found one system which
> works with the 6.1 kernel.  I grabbed the lspci output from a working and
> non-working system, pasted below.  Same kernel and same distro.
> 
> BAD Dell R815 AMD
> 0a:03.0 VGA compatible controller: Matrox Electronics Systems Ltd. MGA G200eW

Thanks for this info. That's a G200eW, which uses slightly different 
code within the driver. From the testing we've done, we didn't see the 
bug either. So it's probably something very specific to your machine or 
the G200EH model.

Best regards
Thomas

>          WPCM450 (rev 0a) (prog-if 00 [VGA controller])
>         DeviceName: Embedded Video
>         Subsystem: Dell Device 0444
>         Control: I/O+ Mem+ BusMaster+ SpecCycle- MemWINV- VGASnoop- ParErr- Stepping- SERR- FastB2B- DisINTx-
>         Status: Cap+ 66MHz- UDF- FastB2B+ ParErr- DEVSEL=medium >TAbort- <TAbort- <MAbort- >SERR- <PERR- INTx-
>         Latency: 32 (4000ns min, 8000ns max), Cache Line Size: 64 bytes
>         Interrupt: pin A routed to IRQ 5
>         NUMA node: 0
>         IOMMU group: 10
>         Region 0: Memory at ec800000 (32-bit, prefetchable) [size=8M]
>         Region 1: Memory at ef7fc000 (32-bit, non-prefetchable) [size=16K]
>         Region 2: Memory at ee800000 (32-bit, non-prefetchable) [size=8M]
>         Expansion ROM at 000c0000 [virtual] [disabled] [size=128K]
>         Capabilities: [dc] Power Management version 1
>                 Flags: PMEClk- DSI+ D1- D2- AuxCurrent=0mA PME(D0-,D1-,D2-,D3hot-,D3cold-)
>                 Status: D0 NoSoftRst- PME-Enable- DSel=0 DScale=0 PME-
> 00: 2b 10 32 05 07 00 90 02 0a 00 00 03 10 20 00 00
> 10: 08 00 80 ec 00 c0 7f ef 00 00 80 ee 00 00 00 00
> 20: 00 00 00 00 00 00 00 00 00 00 00 00 28 10 44 04
> 30: 00 00 00 00 dc 00 00 00 00 00 00 00 05 01 10 20
> 
> GOOD Dell R710 INTEL
> 0a:03.0 VGA compatible controller: Matrox Electronics Systems Ltd. MGA G200eW
>          WPCM450 (rev 0a) (prog-if 00 [VGA controller])
>         DeviceName: Embedded Video
>         Subsystem: Dell PowerEdge R710 MGA G200eW WPCM450
>         Control: I/O+ Mem+ BusMaster+ SpecCycle- MemWINV- VGASnoop- ParErr- Stepping- SERR- FastB2B- DisINTx-
>         Status: Cap+ 66MHz- UDF- FastB2B+ ParErr- DEVSEL=medium >TAbort- <TAbort- <MAbort- >SERR- <PERR- INTx-
>         Latency: 32 (4000ns min, 8000ns max), Cache Line Size: 64 bytes
>         Interrupt: pin A routed to IRQ 10
>         Region 0: Memory at d5000000 (32-bit, prefetchable) [size=8M]
>         Region 1: Memory at deffc000 (32-bit, non-prefetchable) [size=16K]
>         Region 2: Memory at df000000 (32-bit, non-prefetchable) [size=8M]
>         Expansion ROM at 000c0000 [virtual] [disabled] [size=128K]
>         Capabilities: [dc] Power Management version 1
>                 Flags: PMEClk- DSI+ D1- D2- AuxCurrent=0mA PME(D0-,D1-,D2-,D3hot-,D3cold-)
>                 Status: D0 NoSoftRst- PME-Enable- DSel=0 DScale=0 PME-
> 00: 2b 10 32 05 07 00 90 02 0a 00 00 03 10 20 00 00
> 10: 08 00 00 d5 00 c0 ff de 00 00 00 df 00 00 00 00
> 20: 00 00 00 00 00 00 00 00 00 00 00 00 28 10 35 02
> 30: 00 00 00 00 dc 00 00 00 00 00 00 00 0a 01 10 20
> 
> Phil

-- 
Thomas Zimmermann
Graphics Driver Developer
SUSE Software Solutions Germany GmbH
Frankenstrasse 146, 90461 Nuernberg, Germany
GF: Ivo Totev, Andrew Myers, Andrew McDonald, Boudien Moerman
HRB 36809 (AG Nuernberg)

[-- Attachment #2: OpenPGP digital signature --]
[-- Type: application/pgp-signature, Size: 840 bytes --]

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

* Re: [PATCH 07/14] drm/mgag200: Replace simple-KMS with regular atomic helpers
  2023-04-26  7:01         ` Thomas Zimmermann
@ 2023-04-26 10:15           ` Thomas Zimmermann
  2023-04-27  0:47             ` kernel
  0 siblings, 1 reply; 28+ messages in thread
From: Thomas Zimmermann @ 2023-04-26 10:15 UTC (permalink / raw)
  To: kernel; +Cc: jfalempe, sam, dri-devel


[-- Attachment #1.1: Type: text/plain, Size: 4093 bytes --]



Am 26.04.23 um 09:01 schrieb Thomas Zimmermann:
> Hi
> 
> Am 26.04.23 um 01:39 schrieb kernel@linuxace.com:
>> I'm not sure if this information is useful, but we have found one 
>> system which
>> works with the 6.1 kernel.  I grabbed the lspci output from a working and
>> non-working system, pasted below.  Same kernel and same distro.
>>
>> BAD Dell R815 AMD
>> 0a:03.0 VGA compatible controller: Matrox Electronics Systems Ltd. MGA 
>> G200eW
> 
> Thanks for this info. That's a G200eW, which uses slightly different 
> code within the driver. From the testing we've done, we didn't see the 
> bug either. So it's probably something very specific to your machine or 
> the G200EH model.

Oh, now I got it. This G200eW is broken. The other one is good. And the 
kernel is also broken on the G200EH?

Best regards
Thomas

> 
> Best regards
> Thomas
> 
>>          WPCM450 (rev 0a) (prog-if 00 [VGA controller])
>>         DeviceName: Embedded Video
>>         Subsystem: Dell Device 0444
>>         Control: I/O+ Mem+ BusMaster+ SpecCycle- MemWINV- VGASnoop- 
>> ParErr- Stepping- SERR- FastB2B- DisINTx-
>>         Status: Cap+ 66MHz- UDF- FastB2B+ ParErr- DEVSEL=medium 
>> >TAbort- <TAbort- <MAbort- >SERR- <PERR- INTx-
>>         Latency: 32 (4000ns min, 8000ns max), Cache Line Size: 64 bytes
>>         Interrupt: pin A routed to IRQ 5
>>         NUMA node: 0
>>         IOMMU group: 10
>>         Region 0: Memory at ec800000 (32-bit, prefetchable) [size=8M]
>>         Region 1: Memory at ef7fc000 (32-bit, non-prefetchable) 
>> [size=16K]
>>         Region 2: Memory at ee800000 (32-bit, non-prefetchable) [size=8M]
>>         Expansion ROM at 000c0000 [virtual] [disabled] [size=128K]
>>         Capabilities: [dc] Power Management version 1
>>                 Flags: PMEClk- DSI+ D1- D2- AuxCurrent=0mA 
>> PME(D0-,D1-,D2-,D3hot-,D3cold-)
>>                 Status: D0 NoSoftRst- PME-Enable- DSel=0 DScale=0 PME-
>> 00: 2b 10 32 05 07 00 90 02 0a 00 00 03 10 20 00 00
>> 10: 08 00 80 ec 00 c0 7f ef 00 00 80 ee 00 00 00 00
>> 20: 00 00 00 00 00 00 00 00 00 00 00 00 28 10 44 04
>> 30: 00 00 00 00 dc 00 00 00 00 00 00 00 05 01 10 20
>>
>> GOOD Dell R710 INTEL
>> 0a:03.0 VGA compatible controller: Matrox Electronics Systems Ltd. MGA 
>> G200eW
>>          WPCM450 (rev 0a) (prog-if 00 [VGA controller])
>>         DeviceName: Embedded Video
>>         Subsystem: Dell PowerEdge R710 MGA G200eW WPCM450
>>         Control: I/O+ Mem+ BusMaster+ SpecCycle- MemWINV- VGASnoop- 
>> ParErr- Stepping- SERR- FastB2B- DisINTx-
>>         Status: Cap+ 66MHz- UDF- FastB2B+ ParErr- DEVSEL=medium 
>> >TAbort- <TAbort- <MAbort- >SERR- <PERR- INTx-
>>         Latency: 32 (4000ns min, 8000ns max), Cache Line Size: 64 bytes
>>         Interrupt: pin A routed to IRQ 10
>>         Region 0: Memory at d5000000 (32-bit, prefetchable) [size=8M]
>>         Region 1: Memory at deffc000 (32-bit, non-prefetchable) 
>> [size=16K]
>>         Region 2: Memory at df000000 (32-bit, non-prefetchable) [size=8M]
>>         Expansion ROM at 000c0000 [virtual] [disabled] [size=128K]
>>         Capabilities: [dc] Power Management version 1
>>                 Flags: PMEClk- DSI+ D1- D2- AuxCurrent=0mA 
>> PME(D0-,D1-,D2-,D3hot-,D3cold-)
>>                 Status: D0 NoSoftRst- PME-Enable- DSel=0 DScale=0 PME-
>> 00: 2b 10 32 05 07 00 90 02 0a 00 00 03 10 20 00 00
>> 10: 08 00 00 d5 00 c0 ff de 00 00 00 df 00 00 00 00
>> 20: 00 00 00 00 00 00 00 00 00 00 00 00 28 10 35 02
>> 30: 00 00 00 00 dc 00 00 00 00 00 00 00 0a 01 10 20
>>
>> Phil
> 

-- 
Thomas Zimmermann
Graphics Driver Developer
SUSE Software Solutions Germany GmbH
Frankenstrasse 146, 90461 Nuernberg, Germany
GF: Ivo Totev, Andrew Myers, Andrew McDonald, Boudien Moerman
HRB 36809 (AG Nuernberg)

[-- Attachment #2: OpenPGP digital signature --]
[-- Type: application/pgp-signature, Size: 840 bytes --]

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

* RE: [PATCH 07/14] drm/mgag200: Replace simple-KMS with regular atomic helpers
  2023-04-26 10:15           ` Thomas Zimmermann
@ 2023-04-27  0:47             ` kernel
  0 siblings, 0 replies; 28+ messages in thread
From: kernel @ 2023-04-27  0:47 UTC (permalink / raw)
  To: tzimmermann; +Cc: kernel, jfalempe, sam, dri-devel

On Wed, Apr 26, 2023 at 3:15 AM Thomas Zimmermann <tzimmermann@suse.de> wrote:

> Oh, now I got it. This G200eW is broken. The other one is good. And the
> kernel is also broken on the G200EH?

Correct, which doesn't make much sense.  I have two Dells, both of which
have 102b:0532, but only one has no video.  On your second point, I do have
a number of HP DL360p G8s with G200EH [102b:0533] which also have no video.

Phil

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

end of thread, other threads:[~2023-04-27  7:39 UTC | newest]

Thread overview: 28+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2022-07-08  9:39 [PATCH 00/14] drm/mgag200: Move model-specific code into separate functions Thomas Zimmermann
2022-07-08  9:39 ` [PATCH 01/14] drm/mgag200: Split mgag200_modeset_init() Thomas Zimmermann
2022-07-08  9:39 ` [PATCH 02/14] drm/mgag200: Move DAC-register setup into model-specific code Thomas Zimmermann
2022-07-08 15:54   ` Sam Ravnborg
2022-07-11  7:25     ` Thomas Zimmermann
2022-07-08  9:39 ` [PATCH 03/14] dmr/mgag200: Move ER/EW3 register initializatino to per-model code Thomas Zimmermann
2022-07-08  9:39 ` [PATCH 04/14] drm/mgag200: Acquire I/O-register lock in atomic_commit_tail function Thomas Zimmermann
2022-07-08  9:39 ` [PATCH 05/14] drm/mgag200: Store primary plane's color format in CRTC state Thomas Zimmermann
2022-07-08  9:39 ` [PATCH 06/14] drm/mgag200: Reorganize before dropping simple-KMS helpers Thomas Zimmermann
2022-07-08  9:39 ` [PATCH 07/14] drm/mgag200: Replace simple-KMS with regular atomic helpers Thomas Zimmermann
     [not found]   ` <20230425142519.13201-1-kernel@linuxace.com>
2023-04-25 15:03     ` Thomas Zimmermann
2023-04-25 15:48       ` Jocelyn Falempe
2023-04-25 19:56       ` kernel
2023-04-25 23:39       ` kernel
2023-04-26  7:01         ` Thomas Zimmermann
2023-04-26 10:15           ` Thomas Zimmermann
2023-04-27  0:47             ` kernel
2022-07-08  9:39 ` [PATCH 08/14] drm/mgag200: Set SCROFF in primary-plane code Thomas Zimmermann
2022-07-08  9:39 ` [PATCH 09/14] drm/mgag200: Add per-device callbacks Thomas Zimmermann
2022-07-08  9:39 ` [PATCH 10/14] drm/mgag200: Provide per-device callbacks for BMC synchronization Thomas Zimmermann
2022-07-08  9:39 ` [PATCH 11/14] drm/mgag200: Provide per-device callbacks for PIXPLLC Thomas Zimmermann
2022-07-08  9:39 ` [PATCH 12/14] drm/mgag200: Move mode-config to model-specific code Thomas Zimmermann
2022-07-08  9:39 ` [PATCH 13/14] drm/mgag200: Move CRTC atomic_enable to model-specfic code Thomas Zimmermann
2022-07-08  9:39 ` [PATCH 14/14] drm/mgag200: Remove type field from struct mga_device Thomas Zimmermann
2022-07-08 17:18   ` Sam Ravnborg
2022-07-08 17:22 ` [PATCH 00/14] drm/mgag200: Move model-specific code into separate functions Sam Ravnborg
2022-07-11  7:29   ` Thomas Zimmermann
2022-07-11 16:20     ` Jocelyn Falempe

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.