# 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
 
        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);
        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
  */
        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;
 
 
        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;
        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);
 
 
--- /dev/null
+// 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;
+}
 
--- /dev/null
+// 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;
+}
 
--- /dev/null
+// 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;
+}
 
--- /dev/null
+// 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;
+}
 
--- /dev/null
+// 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;
+}
 
--- /dev/null
+// 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;
+}
 
--- /dev/null
+// 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;
+}
 
--- /dev/null
+// 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;
+}
 
                                        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;
 
                else
                        hiprilvl = 5;
 
-       } else if (unique_rev_id >= 0x01) {
+       } else if (g200se->unique_rev_id >= 0x01) {
                hiprilvl = 3;
        } else {
                hiprilvl = 4;
 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)
        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;
 
                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 {
 
 {
        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;
        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);
 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;
 
                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;