]> git.baikalelectronics.ru Git - kernel.git/commitdiff
drm/mgag200: Initialize each model in separate function
authorThomas Zimmermann <tzimmermann@suse.de>
Wed, 1 Jun 2022 11:25:14 +0000 (13:25 +0200)
committerThomas Zimmermann <tzimmermann@suse.de>
Tue, 7 Jun 2022 07:39:44 +0000 (09:39 +0200)
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
13 files changed:
drivers/gpu/drm/mgag200/Makefile
drivers/gpu/drm/mgag200/mgag200_drv.c
drivers/gpu/drm/mgag200/mgag200_drv.h
drivers/gpu/drm/mgag200/mgag200_g200.c [new file with mode: 0644]
drivers/gpu/drm/mgag200/mgag200_g200eh.c [new file with mode: 0644]
drivers/gpu/drm/mgag200/mgag200_g200eh3.c [new file with mode: 0644]
drivers/gpu/drm/mgag200/mgag200_g200er.c [new file with mode: 0644]
drivers/gpu/drm/mgag200/mgag200_g200ev.c [new file with mode: 0644]
drivers/gpu/drm/mgag200/mgag200_g200ew3.c [new file with mode: 0644]
drivers/gpu/drm/mgag200/mgag200_g200se.c [new file with mode: 0644]
drivers/gpu/drm/mgag200/mgag200_g200wb.c [new file with mode: 0644]
drivers/gpu/drm/mgag200/mgag200_mode.c
drivers/gpu/drm/mgag200/mgag200_pll.c

index d4f7665224835e3f154cc183eeee8d9e2d0ed5a8..0c515a3b073d5a383b491d66abdfd81abcd1e8ee 100644 (file)
@@ -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
index 08839460606fee4acf7f5d17e50321d60e9f03a8..e5f06f44ec90996ceeaeb2fd688d530d3eca93ff 100644 (file)
@@ -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;
index 5634fc003ca49c8c568e0767ee3ce3ce7e5ec787..99a9446b7df5c8d985be1f87ac140d21d5bf0487 100644 (file)
@@ -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 (file)
index 0000000..ca9522d
--- /dev/null
@@ -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 (file)
index 0000000..67c7c75
--- /dev/null
@@ -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 (file)
index 0000000..b7a3f95
--- /dev/null
@@ -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 (file)
index 0000000..1c5e757
--- /dev/null
@@ -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 (file)
index 0000000..f8afd05
--- /dev/null
@@ -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 (file)
index 0000000..f65bb94
--- /dev/null
@@ -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 (file)
index 0000000..d809cc6
--- /dev/null
@@ -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 (file)
index 0000000..67b2864
--- /dev/null
@@ -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;
+}
index 8cb72e11a2ea02c70ff246118172e157210a51dc..2b034255a4affbc03adf49939fa5e1d89e8a2447 100644 (file)
@@ -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 {
index 52be08b744ade257cb51d71d5a3c7f9b7fcd3861..8065ca5d8de9a6944f854a0b28339742b5d978fb 100644 (file)
@@ -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;