summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--drivers/gpu/drm/mgag200/Makefile15
-rw-r--r--drivers/gpu/drm/mgag200/mgag200_drv.c206
-rw-r--r--drivers/gpu/drm/mgag200/mgag200_drv.h59
-rw-r--r--drivers/gpu/drm/mgag200/mgag200_g200.c170
-rw-r--r--drivers/gpu/drm/mgag200/mgag200_g200eh.c43
-rw-r--r--drivers/gpu/drm/mgag200/mgag200_g200eh3.c44
-rw-r--r--drivers/gpu/drm/mgag200/mgag200_g200er.c43
-rw-r--r--drivers/gpu/drm/mgag200/mgag200_g200ev.c43
-rw-r--r--drivers/gpu/drm/mgag200/mgag200_g200ew3.c44
-rw-r--r--drivers/gpu/drm/mgag200/mgag200_g200se.c58
-rw-r--r--drivers/gpu/drm/mgag200/mgag200_g200wb.c43
-rw-r--r--drivers/gpu/drm/mgag200/mgag200_mode.c25
-rw-r--r--drivers/gpu/drm/mgag200/mgag200_pll.c12
13 files changed, 603 insertions, 202 deletions
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;