Blob Blame History Raw
From 4f638dedc0af068eaf545251b3551b51caa7a0b7 Mon Sep 17 00:00:00 2001
From: Thomas Zimmermann <tzimmermann@suse.de>
Date: Wed, 1 Jun 2022 13:25:14 +0200
Subject: drm/mgag200: Initialize each model in separate function
Git-commit: 85397f6bc4ff13a6bc5259facb8ebebb1986d666
Patch-mainline: v6.0-rc1
References: jsc#PED-1166 jsc#PED-1168 jsc#PED-1170 jsc#PED-1218 jsc#PED-1220 jsc#PED-1222 jsc#PED-1223 jsc#PED-1225 jsc#PED-2849

Add a separate initializer function for each model. Add separate
devic structures for G200 and G200SE, which require additional
information.

Also move G200's and G200SE's helpers for reading the BIOS and
version id into model-specific code.

Signed-off-by: Thomas Zimmermann <tzimmermann@suse.de>
Reviewed-by: Jocelyn Falempe <jfalempe@redhat.com>
Tested-by: Jocelyn Falempe <jfalempe@redhat.com>
Link: https://patchwork.freedesktop.org/patch/msgid/20220601112522.5774-3-tzimmermann@suse.de
Acked-by: Patrik Jakobsson <pjakobsson@suse.de>
---
 drivers/gpu/drm/mgag200/Makefile          |  15 +-
 drivers/gpu/drm/mgag200/mgag200_drv.c     | 206 ++++------------------
 drivers/gpu/drm/mgag200/mgag200_drv.h     |  59 +++++--
 drivers/gpu/drm/mgag200/mgag200_g200.c    | 170 ++++++++++++++++++
 drivers/gpu/drm/mgag200/mgag200_g200eh.c  |  43 +++++
 drivers/gpu/drm/mgag200/mgag200_g200eh3.c |  44 +++++
 drivers/gpu/drm/mgag200/mgag200_g200er.c  |  43 +++++
 drivers/gpu/drm/mgag200/mgag200_g200ev.c  |  43 +++++
 drivers/gpu/drm/mgag200/mgag200_g200ew3.c |  44 +++++
 drivers/gpu/drm/mgag200/mgag200_g200se.c  |  58 ++++++
 drivers/gpu/drm/mgag200/mgag200_g200wb.c  |  43 +++++
 drivers/gpu/drm/mgag200/mgag200_mode.c    |  25 +--
 drivers/gpu/drm/mgag200/mgag200_pll.c     |  12 +-
 13 files changed, 603 insertions(+), 202 deletions(-)
 create mode 100644 drivers/gpu/drm/mgag200/mgag200_g200.c
 create mode 100644 drivers/gpu/drm/mgag200/mgag200_g200eh.c
 create mode 100644 drivers/gpu/drm/mgag200/mgag200_g200eh3.c
 create mode 100644 drivers/gpu/drm/mgag200/mgag200_g200er.c
 create mode 100644 drivers/gpu/drm/mgag200/mgag200_g200ev.c
 create mode 100644 drivers/gpu/drm/mgag200/mgag200_g200ew3.c
 create mode 100644 drivers/gpu/drm/mgag200/mgag200_g200se.c
 create mode 100644 drivers/gpu/drm/mgag200/mgag200_g200wb.c

diff --git a/drivers/gpu/drm/mgag200/Makefile b/drivers/gpu/drm/mgag200/Makefile
index d4f766522483..0c515a3b073d 100644
--- a/drivers/gpu/drm/mgag200/Makefile
+++ b/drivers/gpu/drm/mgag200/Makefile
@@ -1,4 +1,17 @@
 # SPDX-License-Identifier: GPL-2.0-only
-mgag200-y   := mgag200_drv.o mgag200_i2c.o mgag200_mm.o mgag200_mode.o mgag200_pll.o
+mgag200-y := \
+	mgag200_drv.o \
+	mgag200_g200.o \
+	mgag200_g200eh.o \
+	mgag200_g200eh3.o \
+	mgag200_g200er.o \
+	mgag200_g200ev.o \
+	mgag200_g200ew3.o \
+	mgag200_g200se.o \
+	mgag200_g200wb.o \
+	mgag200_i2c.o \
+	mgag200_mm.o \
+	mgag200_mode.o \
+	mgag200_pll.o
 
 obj-$(CONFIG_DRM_MGAG200) += mgag200.o
diff --git a/drivers/gpu/drm/mgag200/mgag200_drv.c b/drivers/gpu/drm/mgag200/mgag200_drv.c
index 08839460606f..e5f06f44ec90 100644
--- a/drivers/gpu/drm/mgag200/mgag200_drv.c
+++ b/drivers/gpu/drm/mgag200/mgag200_drv.c
@@ -60,7 +60,7 @@ static bool mgag200_has_sgram(struct mga_device *mdev)
 	return !!(option & PCI_MGA_OPTION_HARDPWMSK);
 }
 
-static int mgag200_regs_init(struct mga_device *mdev)
+int mgag200_regs_init(struct mga_device *mdev)
 {
 	struct drm_device *dev = &mdev->base;
 	struct pci_dev *pdev = to_pci_dev(dev->dev);
@@ -133,178 +133,6 @@ static int mgag200_regs_init(struct mga_device *mdev)
 	return 0;
 }
 
-static void mgag200_g200_interpret_bios(struct mga_device *mdev,
-					const unsigned char *bios,
-					size_t size)
-{
-	static const char matrox[] = {'M', 'A', 'T', 'R', 'O', 'X'};
-	static const unsigned int expected_length[6] = {
-		0, 64, 64, 64, 128, 128
-	};
-	struct drm_device *dev = &mdev->base;
-	const unsigned char *pins;
-	unsigned int pins_len, version;
-	int offset;
-	int tmp;
-
-	/* Test for MATROX string. */
-	if (size < 45 + sizeof(matrox))
-		return;
-	if (memcmp(&bios[45], matrox, sizeof(matrox)) != 0)
-		return;
-
-	/* Get the PInS offset. */
-	if (size < MGA_BIOS_OFFSET + 2)
-		return;
-	offset = (bios[MGA_BIOS_OFFSET + 1] << 8) | bios[MGA_BIOS_OFFSET];
-
-	/* Get PInS data structure. */
-
-	if (size < offset + 6)
-		return;
-	pins = bios + offset;
-	if (pins[0] == 0x2e && pins[1] == 0x41) {
-		version = pins[5];
-		pins_len = pins[2];
-	} else {
-		version = 1;
-		pins_len = pins[0] + (pins[1] << 8);
-	}
-
-	if (version < 1 || version > 5) {
-		drm_warn(dev, "Unknown BIOS PInS version: %d\n", version);
-		return;
-	}
-	if (pins_len != expected_length[version]) {
-		drm_warn(dev, "Unexpected BIOS PInS size: %d expected: %d\n",
-			 pins_len, expected_length[version]);
-		return;
-	}
-	if (size < offset + pins_len)
-		return;
-
-	drm_dbg_kms(dev, "MATROX BIOS PInS version %d size: %d found\n",
-		    version, pins_len);
-
-	/* Extract the clock values */
-
-	switch (version) {
-	case 1:
-		tmp = pins[24] + (pins[25] << 8);
-		if (tmp)
-			mdev->model.g200.pclk_max = tmp * 10;
-		break;
-	case 2:
-		if (pins[41] != 0xff)
-			mdev->model.g200.pclk_max = (pins[41] + 100) * 1000;
-		break;
-	case 3:
-		if (pins[36] != 0xff)
-			mdev->model.g200.pclk_max = (pins[36] + 100) * 1000;
-		if (pins[52] & 0x20)
-			mdev->model.g200.ref_clk = 14318;
-		break;
-	case 4:
-		if (pins[39] != 0xff)
-			mdev->model.g200.pclk_max = pins[39] * 4 * 1000;
-		if (pins[92] & 0x01)
-			mdev->model.g200.ref_clk = 14318;
-		break;
-	case 5:
-		tmp = pins[4] ? 8000 : 6000;
-		if (pins[123] != 0xff)
-			mdev->model.g200.pclk_min = pins[123] * tmp;
-		if (pins[38] != 0xff)
-			mdev->model.g200.pclk_max = pins[38] * tmp;
-		if (pins[110] & 0x01)
-			mdev->model.g200.ref_clk = 14318;
-		break;
-	default:
-		break;
-	}
-}
-
-static void mgag200_g200_init_refclk(struct mga_device *mdev)
-{
-	struct drm_device *dev = &mdev->base;
-	struct pci_dev *pdev = to_pci_dev(dev->dev);
-	unsigned char __iomem *rom;
-	unsigned char *bios;
-	size_t size;
-
-	mdev->model.g200.pclk_min = 50000;
-	mdev->model.g200.pclk_max = 230000;
-	mdev->model.g200.ref_clk = 27050;
-
-	rom = pci_map_rom(pdev, &size);
-	if (!rom)
-		return;
-
-	bios = vmalloc(size);
-	if (!bios)
-		goto out;
-	memcpy_fromio(bios, rom, size);
-
-	if (size != 0 && bios[0] == 0x55 && bios[1] == 0xaa)
-		mgag200_g200_interpret_bios(mdev, bios, size);
-
-	drm_dbg_kms(dev, "pclk_min: %ld pclk_max: %ld ref_clk: %ld\n",
-		    mdev->model.g200.pclk_min, mdev->model.g200.pclk_max,
-		    mdev->model.g200.ref_clk);
-
-	vfree(bios);
-out:
-	pci_unmap_rom(pdev, rom);
-}
-
-static void mgag200_g200se_init_unique_id(struct mga_device *mdev)
-{
-	struct drm_device *dev = &mdev->base;
-
-	/* stash G200 SE model number for later use */
-	mdev->model.g200se.unique_rev_id = RREG32(0x1e24);
-
-	drm_dbg(dev, "G200 SE unique revision id is 0x%x\n",
-		mdev->model.g200se.unique_rev_id);
-}
-
-static struct mga_device *
-mgag200_device_create(struct pci_dev *pdev, enum mga_type type, unsigned long flags)
-{
-	struct mga_device *mdev;
-	struct drm_device *dev;
-	int ret;
-
-	mdev = devm_drm_dev_alloc(&pdev->dev, &mgag200_driver, struct mga_device, base);
-	if (IS_ERR(mdev))
-		return mdev;
-	dev = &mdev->base;
-
-	pci_set_drvdata(pdev, dev);
-
-	mdev->flags = flags;
-	mdev->type = type;
-
-	ret = mgag200_regs_init(mdev);
-	if (ret)
-		return ERR_PTR(ret);
-
-	if (mdev->type == G200_PCI || mdev->type == G200_AGP)
-		mgag200_g200_init_refclk(mdev);
-	else if (IS_G200_SE(mdev))
-		mgag200_g200se_init_unique_id(mdev);
-
-	ret = mgag200_mm_init(mdev);
-	if (ret)
-		return ERR_PTR(ret);
-
-	ret = mgag200_modeset_init(mdev);
-	if (ret)
-		return ERR_PTR(ret);
-
-	return mdev;
-}
-
 /*
  * PCI driver
  */
@@ -354,7 +182,37 @@ mgag200_pci_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
 	if (ret)
 		return ret;
 
-	mdev = mgag200_device_create(pdev, type, flags);
+	switch (type) {
+	case G200_PCI:
+	case G200_AGP:
+		mdev = mgag200_g200_device_create(pdev, &mgag200_driver, type, flags);
+		break;
+	case G200_SE_A:
+	case G200_SE_B:
+		mdev = mgag200_g200se_device_create(pdev, &mgag200_driver, type, flags);
+		break;
+	case G200_WB:
+		mdev = mgag200_g200wb_device_create(pdev, &mgag200_driver, type, flags);
+		break;
+	case G200_EV:
+		mdev = mgag200_g200ev_device_create(pdev, &mgag200_driver, type, flags);
+		break;
+	case G200_EH:
+		mdev = mgag200_g200eh_device_create(pdev, &mgag200_driver, type, flags);
+		break;
+	case G200_EH3:
+		mdev = mgag200_g200eh3_device_create(pdev, &mgag200_driver, type, flags);
+		break;
+	case G200_ER:
+		mdev = mgag200_g200er_device_create(pdev, &mgag200_driver, type, flags);
+		break;
+	case G200_EW3:
+		mdev = mgag200_g200ew3_device_create(pdev, &mgag200_driver, type, flags);
+		break;
+	default:
+		dev_err(&pdev->dev, "Device type %d is unsupported\n", type);
+		return -ENODEV;
+	}
 	if (IS_ERR(mdev))
 		return PTR_ERR(mdev);
 	dev = &mdev->base;
diff --git a/drivers/gpu/drm/mgag200/mgag200_drv.h b/drivers/gpu/drm/mgag200/mgag200_drv.h
index 5634fc003ca4..99a9446b7df5 100644
--- a/drivers/gpu/drm/mgag200/mgag200_drv.h
+++ b/drivers/gpu/drm/mgag200/mgag200_drv.h
@@ -218,18 +218,6 @@ struct mga_device {
 
 	enum mga_type			type;
 
-	union {
-		struct {
-			long ref_clk;
-			long pclk_min;
-			long pclk_max;
-		} g200;
-		struct {
-			/* SE model number stored in reg 0x1e24 */
-			u32 unique_rev_id;
-		} g200se;
-	} model;
-
 	struct mgag200_pll pixpll;
 	struct mga_i2c_chan i2c;
 	struct drm_connector connector;
@@ -241,6 +229,53 @@ static inline struct mga_device *to_mga_device(struct drm_device *dev)
 	return container_of(dev, struct mga_device, base);
 }
 
+struct mgag200_g200_device {
+	struct mga_device base;
+
+	/* PLL constants */
+	long ref_clk;
+	long pclk_min;
+	long pclk_max;
+};
+
+static inline struct mgag200_g200_device *to_mgag200_g200_device(struct drm_device *dev)
+{
+	return container_of(to_mga_device(dev), struct mgag200_g200_device, base);
+}
+
+struct mgag200_g200se_device {
+	struct mga_device base;
+
+	/* SE model number stored in reg 0x1e24 */
+	u32 unique_rev_id;
+};
+
+static inline struct mgag200_g200se_device *to_mgag200_g200se_device(struct drm_device *dev)
+{
+	return container_of(to_mga_device(dev), struct mgag200_g200se_device, base);
+}
+
+				/* mgag200_drv.c */
+int mgag200_regs_init(struct mga_device *mdev);
+
+				/* mgag200_<device type>.c */
+struct mga_device *mgag200_g200_device_create(struct pci_dev *pdev, const struct drm_driver *drv,
+					      enum mga_type type, unsigned long flags);
+struct mga_device *mgag200_g200se_device_create(struct pci_dev *pdev, const struct drm_driver *drv,
+						enum mga_type type, unsigned long flags);
+struct mga_device *mgag200_g200wb_device_create(struct pci_dev *pdev, const struct drm_driver *drv,
+						enum mga_type type, unsigned long flags);
+struct mga_device *mgag200_g200ev_device_create(struct pci_dev *pdev, const struct drm_driver *drv,
+						enum mga_type type, unsigned long flags);
+struct mga_device *mgag200_g200eh_device_create(struct pci_dev *pdev, const struct drm_driver *drv,
+						enum mga_type type, unsigned long flags);
+struct mga_device *mgag200_g200eh3_device_create(struct pci_dev *pdev, const struct drm_driver *drv,
+						 enum mga_type type, unsigned long flags);
+struct mga_device *mgag200_g200er_device_create(struct pci_dev *pdev, const struct drm_driver *drv,
+						enum mga_type type, unsigned long flags);
+struct mga_device *mgag200_g200ew3_device_create(struct pci_dev *pdev, const struct drm_driver *drv,
+						 enum mga_type type, unsigned long flags);
+
 				/* mgag200_mode.c */
 int mgag200_modeset_init(struct mga_device *mdev);
 
diff --git a/drivers/gpu/drm/mgag200/mgag200_g200.c b/drivers/gpu/drm/mgag200/mgag200_g200.c
new file mode 100644
index 000000000000..ca9522daf6e1
--- /dev/null
+++ b/drivers/gpu/drm/mgag200/mgag200_g200.c
@@ -0,0 +1,170 @@
+// SPDX-License-Identifier: GPL-2.0-only
+
+#include <linux/pci.h>
+
+#include <drm/drm_drv.h>
+
+#include "mgag200_drv.h"
+
+/*
+ * DRM Device
+ */
+
+static void mgag200_g200_interpret_bios(struct mgag200_g200_device *g200,
+					const unsigned char *bios, size_t size)
+{
+	static const char matrox[] = {'M', 'A', 'T', 'R', 'O', 'X'};
+	static const unsigned int expected_length[6] = {
+		0, 64, 64, 64, 128, 128
+	};
+	struct mga_device *mdev = &g200->base;
+	struct drm_device *dev = &mdev->base;
+	const unsigned char *pins;
+	unsigned int pins_len, version;
+	int offset;
+	int tmp;
+
+	/* Test for MATROX string. */
+	if (size < 45 + sizeof(matrox))
+		return;
+	if (memcmp(&bios[45], matrox, sizeof(matrox)) != 0)
+		return;
+
+	/* Get the PInS offset. */
+	if (size < MGA_BIOS_OFFSET + 2)
+		return;
+	offset = (bios[MGA_BIOS_OFFSET + 1] << 8) | bios[MGA_BIOS_OFFSET];
+
+	/* Get PInS data structure. */
+
+	if (size < offset + 6)
+		return;
+	pins = bios + offset;
+	if (pins[0] == 0x2e && pins[1] == 0x41) {
+		version = pins[5];
+		pins_len = pins[2];
+	} else {
+		version = 1;
+		pins_len = pins[0] + (pins[1] << 8);
+	}
+
+	if (version < 1 || version > 5) {
+		drm_warn(dev, "Unknown BIOS PInS version: %d\n", version);
+		return;
+	}
+	if (pins_len != expected_length[version]) {
+		drm_warn(dev, "Unexpected BIOS PInS size: %d expected: %d\n",
+			 pins_len, expected_length[version]);
+		return;
+	}
+	if (size < offset + pins_len)
+		return;
+
+	drm_dbg_kms(dev, "MATROX BIOS PInS version %d size: %d found\n", version, pins_len);
+
+	/* Extract the clock values */
+
+	switch (version) {
+	case 1:
+		tmp = pins[24] + (pins[25] << 8);
+		if (tmp)
+			g200->pclk_max = tmp * 10;
+		break;
+	case 2:
+		if (pins[41] != 0xff)
+			g200->pclk_max = (pins[41] + 100) * 1000;
+		break;
+	case 3:
+		if (pins[36] != 0xff)
+			g200->pclk_max = (pins[36] + 100) * 1000;
+		if (pins[52] & 0x20)
+			g200->ref_clk = 14318;
+		break;
+	case 4:
+		if (pins[39] != 0xff)
+			g200->pclk_max = pins[39] * 4 * 1000;
+		if (pins[92] & 0x01)
+			g200->ref_clk = 14318;
+		break;
+	case 5:
+		tmp = pins[4] ? 8000 : 6000;
+		if (pins[123] != 0xff)
+			g200->pclk_min = pins[123] * tmp;
+		if (pins[38] != 0xff)
+			g200->pclk_max = pins[38] * tmp;
+		if (pins[110] & 0x01)
+			g200->ref_clk = 14318;
+		break;
+	default:
+		break;
+	}
+}
+
+static void mgag200_g200_init_refclk(struct mgag200_g200_device *g200)
+{
+	struct mga_device *mdev = &g200->base;
+	struct drm_device *dev = &mdev->base;
+	struct pci_dev *pdev = to_pci_dev(dev->dev);
+	unsigned char __iomem *rom;
+	unsigned char *bios;
+	size_t size;
+
+	g200->pclk_min = 50000;
+	g200->pclk_max = 230000;
+	g200->ref_clk = 27050;
+
+	rom = pci_map_rom(pdev, &size);
+	if (!rom)
+		return;
+
+	bios = vmalloc(size);
+	if (!bios)
+		goto out;
+	memcpy_fromio(bios, rom, size);
+
+	if (size != 0 && bios[0] == 0x55 && bios[1] == 0xaa)
+		mgag200_g200_interpret_bios(g200, bios, size);
+
+	drm_dbg_kms(dev, "pclk_min: %ld pclk_max: %ld ref_clk: %ld\n",
+		    g200->pclk_min, g200->pclk_max, g200->ref_clk);
+
+	vfree(bios);
+out:
+	pci_unmap_rom(pdev, rom);
+}
+
+struct mga_device *mgag200_g200_device_create(struct pci_dev *pdev, const struct drm_driver *drv,
+					      enum mga_type type, unsigned long flags)
+{
+	struct mgag200_g200_device *g200;
+	struct mga_device *mdev;
+	struct drm_device *dev;
+	int ret;
+
+	g200 = devm_drm_dev_alloc(&pdev->dev, drv, struct mgag200_g200_device, base.base);
+	if (IS_ERR(g200))
+		return ERR_CAST(g200);
+	mdev = &g200->base;
+	dev = &mdev->base;
+
+	pci_set_drvdata(pdev, dev);
+
+	mdev->flags = flags;
+	mdev->type = type;
+
+	ret = mgag200_regs_init(mdev);
+	if (ret)
+		return ERR_PTR(ret);
+
+	mgag200_g200_init_refclk(g200);
+
+	ret = mgag200_mm_init(mdev);
+	if (ret)
+		return ERR_PTR(ret);
+
+	ret = mgag200_modeset_init(mdev);
+	if (ret)
+		return ERR_PTR(ret);
+
+	return mdev;
+}
diff --git a/drivers/gpu/drm/mgag200/mgag200_g200eh.c b/drivers/gpu/drm/mgag200/mgag200_g200eh.c
new file mode 100644
index 000000000000..67c7c75ea791
--- /dev/null
+++ b/drivers/gpu/drm/mgag200/mgag200_g200eh.c
@@ -0,0 +1,43 @@
+// SPDX-License-Identifier: GPL-2.0-only
+
+#include <linux/pci.h>
+
+#include <drm/drm_drv.h>
+
+#include "mgag200_drv.h"
+
+/*
+ * DRM device
+ */
+
+struct mga_device *mgag200_g200eh_device_create(struct pci_dev *pdev, const struct drm_driver *drv,
+						enum mga_type type, unsigned long flags)
+{
+	struct mga_device *mdev;
+	struct drm_device *dev;
+	int ret;
+
+	mdev = devm_drm_dev_alloc(&pdev->dev, drv, struct mga_device, base);
+	if (IS_ERR(mdev))
+		return mdev;
+	dev = &mdev->base;
+
+	pci_set_drvdata(pdev, dev);
+
+	mdev->flags = flags;
+	mdev->type = type;
+
+	ret = mgag200_regs_init(mdev);
+	if (ret)
+		return ERR_PTR(ret);
+
+	ret = mgag200_mm_init(mdev);
+	if (ret)
+		return ERR_PTR(ret);
+
+	ret = mgag200_modeset_init(mdev);
+	if (ret)
+		return ERR_PTR(ret);
+
+	return mdev;
+}
diff --git a/drivers/gpu/drm/mgag200/mgag200_g200eh3.c b/drivers/gpu/drm/mgag200/mgag200_g200eh3.c
new file mode 100644
index 000000000000..b7a3f9551bfd
--- /dev/null
+++ b/drivers/gpu/drm/mgag200/mgag200_g200eh3.c
@@ -0,0 +1,44 @@
+// SPDX-License-Identifier: GPL-2.0-only
+
+#include <linux/pci.h>
+
+#include <drm/drm_drv.h>
+
+#include "mgag200_drv.h"
+
+/*
+ * DRM device
+ */
+
+struct mga_device *mgag200_g200eh3_device_create(struct pci_dev *pdev,
+						 const struct drm_driver *drv,
+						 enum mga_type type, unsigned long flags)
+{
+	struct mga_device *mdev;
+	struct drm_device *dev;
+	int ret;
+
+	mdev = devm_drm_dev_alloc(&pdev->dev, drv, struct mga_device, base);
+	if (IS_ERR(mdev))
+		return mdev;
+	dev = &mdev->base;
+
+	pci_set_drvdata(pdev, dev);
+
+	mdev->flags = flags;
+	mdev->type = type;
+
+	ret = mgag200_regs_init(mdev);
+	if (ret)
+		return ERR_PTR(ret);
+
+	ret = mgag200_mm_init(mdev);
+	if (ret)
+		return ERR_PTR(ret);
+
+	ret = mgag200_modeset_init(mdev);
+	if (ret)
+		return ERR_PTR(ret);
+
+	return mdev;
+}
diff --git a/drivers/gpu/drm/mgag200/mgag200_g200er.c b/drivers/gpu/drm/mgag200/mgag200_g200er.c
new file mode 100644
index 000000000000..1c5e757ec016
--- /dev/null
+++ b/drivers/gpu/drm/mgag200/mgag200_g200er.c
@@ -0,0 +1,43 @@
+// SPDX-License-Identifier: GPL-2.0-only
+
+#include <linux/pci.h>
+
+#include <drm/drm_drv.h>
+
+#include "mgag200_drv.h"
+
+/*
+ * DRM device
+ */
+
+struct mga_device *mgag200_g200er_device_create(struct pci_dev *pdev, const struct drm_driver *drv,
+						enum mga_type type, unsigned long flags)
+{
+	struct mga_device *mdev;
+	struct drm_device *dev;
+	int ret;
+
+	mdev = devm_drm_dev_alloc(&pdev->dev, drv, struct mga_device, base);
+	if (IS_ERR(mdev))
+		return mdev;
+	dev = &mdev->base;
+
+	pci_set_drvdata(pdev, dev);
+
+	mdev->flags = flags;
+	mdev->type = type;
+
+	ret = mgag200_regs_init(mdev);
+	if (ret)
+		return ERR_PTR(ret);
+
+	ret = mgag200_mm_init(mdev);
+	if (ret)
+		return ERR_PTR(ret);
+
+	ret = mgag200_modeset_init(mdev);
+	if (ret)
+		return ERR_PTR(ret);
+
+	return mdev;
+}
diff --git a/drivers/gpu/drm/mgag200/mgag200_g200ev.c b/drivers/gpu/drm/mgag200/mgag200_g200ev.c
new file mode 100644
index 000000000000..f8afd05913fd
--- /dev/null
+++ b/drivers/gpu/drm/mgag200/mgag200_g200ev.c
@@ -0,0 +1,43 @@
+// SPDX-License-Identifier: GPL-2.0-only
+
+#include <linux/pci.h>
+
+#include <drm/drm_drv.h>
+
+#include "mgag200_drv.h"
+
+/*
+ * DRM device
+ */
+
+struct mga_device *mgag200_g200ev_device_create(struct pci_dev *pdev, const struct drm_driver *drv,
+						enum mga_type type, unsigned long flags)
+{
+	struct mga_device *mdev;
+	struct drm_device *dev;
+	int ret;
+
+	mdev = devm_drm_dev_alloc(&pdev->dev, drv, struct mga_device, base);
+	if (IS_ERR(mdev))
+		return mdev;
+	dev = &mdev->base;
+
+	pci_set_drvdata(pdev, dev);
+
+	mdev->flags = flags;
+	mdev->type = type;
+
+	ret = mgag200_regs_init(mdev);
+	if (ret)
+		return ERR_PTR(ret);
+
+	ret = mgag200_mm_init(mdev);
+	if (ret)
+		return ERR_PTR(ret);
+
+	ret = mgag200_modeset_init(mdev);
+	if (ret)
+		return ERR_PTR(ret);
+
+	return mdev;
+}
diff --git a/drivers/gpu/drm/mgag200/mgag200_g200ew3.c b/drivers/gpu/drm/mgag200/mgag200_g200ew3.c
new file mode 100644
index 000000000000..f65bb94e0b3d
--- /dev/null
+++ b/drivers/gpu/drm/mgag200/mgag200_g200ew3.c
@@ -0,0 +1,44 @@
+// SPDX-License-Identifier: GPL-2.0-only
+
+#include <linux/pci.h>
+
+#include <drm/drm_drv.h>
+
+#include "mgag200_drv.h"
+
+/*
+ * DRM device
+ */
+
+struct mga_device *mgag200_g200ew3_device_create(struct pci_dev *pdev,
+						 const struct drm_driver *drv,
+						 enum mga_type type, unsigned long flags)
+{
+	struct mga_device *mdev;
+	struct drm_device *dev;
+	int ret;
+
+	mdev = devm_drm_dev_alloc(&pdev->dev, drv, struct mga_device, base);
+	if (IS_ERR(mdev))
+		return mdev;
+	dev = &mdev->base;
+
+	pci_set_drvdata(pdev, dev);
+
+	mdev->flags = flags;
+	mdev->type = type;
+
+	ret = mgag200_regs_init(mdev);
+	if (ret)
+		return ERR_PTR(ret);
+
+	ret = mgag200_mm_init(mdev);
+	if (ret)
+		return ERR_PTR(ret);
+
+	ret = mgag200_modeset_init(mdev);
+	if (ret)
+		return ERR_PTR(ret);
+
+	return mdev;
+}
diff --git a/drivers/gpu/drm/mgag200/mgag200_g200se.c b/drivers/gpu/drm/mgag200/mgag200_g200se.c
new file mode 100644
index 000000000000..d809cc680024
--- /dev/null
+++ b/drivers/gpu/drm/mgag200/mgag200_g200se.c
@@ -0,0 +1,58 @@
+// SPDX-License-Identifier: GPL-2.0-only
+
+#include <linux/pci.h>
+
+#include <drm/drm_drv.h>
+
+#include "mgag200_drv.h"
+
+/*
+ * DRM device
+ */
+
+static void mgag200_g200se_init_unique_id(struct mgag200_g200se_device *g200se)
+{
+	struct mga_device *mdev = &g200se->base;
+	struct drm_device *dev = &mdev->base;
+
+	/* stash G200 SE model number for later use */
+	g200se->unique_rev_id = RREG32(0x1e24);
+
+	drm_dbg(dev, "G200 SE unique revision id is 0x%x\n", g200se->unique_rev_id);
+}
+
+struct mga_device *mgag200_g200se_device_create(struct pci_dev *pdev, const struct drm_driver *drv,
+						enum mga_type type, unsigned long flags)
+{
+	struct mgag200_g200se_device *g200se;
+	struct mga_device *mdev;
+	struct drm_device *dev;
+	int ret;
+
+	g200se = devm_drm_dev_alloc(&pdev->dev, drv, struct mgag200_g200se_device, base.base);
+	if (IS_ERR(g200se))
+		return ERR_CAST(g200se);
+	mdev = &g200se->base;
+	dev = &mdev->base;
+
+	pci_set_drvdata(pdev, dev);
+
+	mdev->flags = flags;
+	mdev->type = type;
+
+	ret = mgag200_regs_init(mdev);
+	if (ret)
+		return ERR_PTR(ret);
+
+	mgag200_g200se_init_unique_id(g200se);
+
+	ret = mgag200_mm_init(mdev);
+	if (ret)
+		return ERR_PTR(ret);
+
+	ret = mgag200_modeset_init(mdev);
+	if (ret)
+		return ERR_PTR(ret);
+
+	return mdev;
+}
diff --git a/drivers/gpu/drm/mgag200/mgag200_g200wb.c b/drivers/gpu/drm/mgag200/mgag200_g200wb.c
new file mode 100644
index 000000000000..67b28646386d
--- /dev/null
+++ b/drivers/gpu/drm/mgag200/mgag200_g200wb.c
@@ -0,0 +1,43 @@
+// SPDX-License-Identifier: GPL-2.0-only
+
+#include <linux/pci.h>
+
+#include <drm/drm_drv.h>
+
+#include "mgag200_drv.h"
+
+/*
+ * DRM device
+ */
+
+struct mga_device *mgag200_g200wb_device_create(struct pci_dev *pdev, const struct drm_driver *drv,
+						enum mga_type type, unsigned long flags)
+{
+	struct mga_device *mdev;
+	struct drm_device *dev;
+	int ret;
+
+	mdev = devm_drm_dev_alloc(&pdev->dev, drv, struct mga_device, base);
+	if (IS_ERR(mdev))
+		return mdev;
+	dev = &mdev->base;
+
+	pci_set_drvdata(pdev, dev);
+
+	mdev->flags = flags;
+	mdev->type = type;
+
+	ret = mgag200_regs_init(mdev);
+	if (ret)
+		return ERR_PTR(ret);
+
+	ret = mgag200_mm_init(mdev);
+	if (ret)
+		return ERR_PTR(ret);
+
+	ret = mgag200_modeset_init(mdev);
+	if (ret)
+		return ERR_PTR(ret);
+
+	return mdev;
+}
diff --git a/drivers/gpu/drm/mgag200/mgag200_mode.c b/drivers/gpu/drm/mgag200/mgag200_mode.c
index 8cb72e11a2ea..2b034255a4af 100644
--- a/drivers/gpu/drm/mgag200/mgag200_mode.c
+++ b/drivers/gpu/drm/mgag200/mgag200_mode.c
@@ -583,13 +583,13 @@ static void mgag200_g200se_set_hiprilvl(struct mga_device *mdev,
 					const struct drm_display_mode *mode,
 					const struct drm_framebuffer *fb)
 {
-	u32 unique_rev_id = mdev->model.g200se.unique_rev_id;
+	struct mgag200_g200se_device *g200se = to_mgag200_g200se_device(&mdev->base);
 	unsigned int hiprilvl;
 	u8 crtcext6;
 
-	if  (unique_rev_id >= 0x04) {
+	if  (g200se->unique_rev_id >= 0x04) {
 		hiprilvl = 0;
-	} else if (unique_rev_id >= 0x02) {
+	} else if (g200se->unique_rev_id >= 0x02) {
 		unsigned int bpp;
 		unsigned long mb;
 
@@ -614,7 +614,7 @@ static void mgag200_g200se_set_hiprilvl(struct mga_device *mdev,
 		else
 			hiprilvl = 5;
 
-	} else if (unique_rev_id >= 0x01) {
+	} else if (g200se->unique_rev_id >= 0x01) {
 		hiprilvl = 3;
 	} else {
 		hiprilvl = 4;
@@ -725,17 +725,19 @@ static enum drm_mode_status
 mgag200_simple_display_pipe_mode_valid(struct drm_simple_display_pipe *pipe,
 				       const struct drm_display_mode *mode)
 {
-	struct mga_device *mdev = to_mga_device(pipe->crtc.dev);
+	struct drm_device *dev = pipe->crtc.dev;
+	struct mga_device *mdev = to_mga_device(dev);
+	struct mgag200_g200se_device *g200se;
 
 	if (IS_G200_SE(mdev)) {
-		u32 unique_rev_id = mdev->model.g200se.unique_rev_id;
+		g200se = to_mgag200_g200se_device(dev);
 
-		if (unique_rev_id == 0x01) {
+		if (g200se->unique_rev_id == 0x01) {
 			if (mode->hdisplay > 1600)
 				return MODE_VIRTUAL_X;
 			if (mode->vdisplay > 1200)
 				return MODE_VIRTUAL_Y;
-		} else if (unique_rev_id == 0x02) {
+		} else if (g200se->unique_rev_id == 0x02) {
 			if (mode->hdisplay > 1920)
 				return MODE_VIRTUAL_X;
 			if (mode->vdisplay > 1200)
@@ -1026,6 +1028,7 @@ static enum drm_mode_status mgag200_mode_config_mode_valid(struct drm_device *de
 	static const unsigned int max_bpp = 4; // DRM_FORMAT_XRGB8888
 	struct mga_device *mdev = to_mga_device(dev);
 	unsigned long fbsize, fbpages, max_fbpages;
+	struct mgag200_g200se_device *g200se;
 
 	max_fbpages = mdev->vram_fb_available >> PAGE_SHIFT;
 
@@ -1036,12 +1039,12 @@ static enum drm_mode_status mgag200_mode_config_mode_valid(struct drm_device *de
 		return MODE_MEM;
 
 	if (IS_G200_SE(mdev)) {
-		u32 unique_rev_id = mdev->model.g200se.unique_rev_id;
+		g200se = to_mgag200_g200se_device(dev);
 
-		if (unique_rev_id == 0x01) {
+		if (g200se->unique_rev_id == 0x01) {
 			if (mgag200_calculate_mode_bandwidth(mode, max_bpp * 8) > (24400 * 1024))
 				return MODE_BAD;
-		} else if (unique_rev_id == 0x02) {
+		} else if (g200se->unique_rev_id == 0x02) {
 			if (mgag200_calculate_mode_bandwidth(mode, max_bpp * 8) > (30100 * 1024))
 				return MODE_BAD;
 		} else {
diff --git a/drivers/gpu/drm/mgag200/mgag200_pll.c b/drivers/gpu/drm/mgag200/mgag200_pll.c
index 52be08b744ad..8065ca5d8de9 100644
--- a/drivers/gpu/drm/mgag200/mgag200_pll.c
+++ b/drivers/gpu/drm/mgag200/mgag200_pll.c
@@ -13,6 +13,7 @@ static int mgag200_pixpll_compute_g200(struct mgag200_pll *pixpll, long clock,
 {
 	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;
@@ -23,9 +24,9 @@ static int mgag200_pixpll_compute_g200(struct mgag200_pll *pixpll, long clock,
 	long f_vco;
 	long computed;
 	long delta, tmp_delta;
-	long ref_clk = mdev->model.g200.ref_clk;
-	long p_clk_min = mdev->model.g200.pclk_min;
-	long p_clk_max =  mdev->model.g200.pclk_max;
+	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);
@@ -951,6 +952,7 @@ static const struct mgag200_pll_funcs mgag200_pixpll_funcs_g200ew3 = {
 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;
 
@@ -961,7 +963,9 @@ int mgag200_pixpll_init(struct mgag200_pll *pixpll, struct mga_device *mdev)
 		break;
 	case G200_SE_A:
 	case G200_SE_B:
-		if (mdev->model.g200se.unique_rev_id >= 0x04)
+		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;
-- 
2.38.1