summaryrefslogtreecommitdiff
path: root/drivers/gpu/drm/mgag200
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/gpu/drm/mgag200')
-rw-r--r--drivers/gpu/drm/mgag200/Kconfig4
-rw-r--r--drivers/gpu/drm/mgag200/Makefile3
-rw-r--r--drivers/gpu/drm/mgag200/mgag200_cursor.c319
-rw-r--r--drivers/gpu/drm/mgag200/mgag200_drv.c204
-rw-r--r--drivers/gpu/drm/mgag200/mgag200_drv.h56
-rw-r--r--drivers/gpu/drm/mgag200/mgag200_main.c160
-rw-r--r--drivers/gpu/drm/mgag200/mgag200_mm.c127
-rw-r--r--drivers/gpu/drm/mgag200/mgag200_mode.c875
-rw-r--r--drivers/gpu/drm/mgag200/mgag200_reg.h11
-rw-r--r--drivers/gpu/drm/mgag200/mgag200_ttm.c70
10 files changed, 749 insertions, 1080 deletions
diff --git a/drivers/gpu/drm/mgag200/Kconfig b/drivers/gpu/drm/mgag200/Kconfig
index d60aa4b9ccd4..93be766715c9 100644
--- a/drivers/gpu/drm/mgag200/Kconfig
+++ b/drivers/gpu/drm/mgag200/Kconfig
@@ -2,10 +2,8 @@
config DRM_MGAG200
tristate "Kernel modesetting driver for MGA G200 server engines"
depends on DRM && PCI && MMU
+ select DRM_GEM_SHMEM_HELPER
select DRM_KMS_HELPER
- select DRM_VRAM_HELPER
- select DRM_TTM
- select DRM_TTM_HELPER
help
This is a KMS driver for the MGA G200 server chips, it
does not support the original MGA G200 or any of the desktop
diff --git a/drivers/gpu/drm/mgag200/Makefile b/drivers/gpu/drm/mgag200/Makefile
index 04b281bcf655..42fedef53882 100644
--- a/drivers/gpu/drm/mgag200/Makefile
+++ b/drivers/gpu/drm/mgag200/Makefile
@@ -1,5 +1,4 @@
# SPDX-License-Identifier: GPL-2.0-only
-mgag200-y := mgag200_main.o mgag200_mode.o mgag200_cursor.o \
- mgag200_drv.o mgag200_i2c.o mgag200_ttm.o
+mgag200-y := mgag200_drv.o mgag200_i2c.o mgag200_mm.o mgag200_mode.o
obj-$(CONFIG_DRM_MGAG200) += mgag200.o
diff --git a/drivers/gpu/drm/mgag200/mgag200_cursor.c b/drivers/gpu/drm/mgag200/mgag200_cursor.c
deleted file mode 100644
index aebc9ce43d55..000000000000
--- a/drivers/gpu/drm/mgag200/mgag200_cursor.c
+++ /dev/null
@@ -1,319 +0,0 @@
-// SPDX-License-Identifier: GPL-2.0-only
-/*
- * Copyright 2013 Matrox Graphics
- *
- * Author: Christopher Harvey <charvey@matrox.com>
- */
-
-#include <linux/pci.h>
-
-#include "mgag200_drv.h"
-
-static bool warn_transparent = true;
-static bool warn_palette = true;
-
-static int mgag200_cursor_update(struct mga_device *mdev, void *dst, void *src,
- unsigned int width, unsigned int height)
-{
- struct drm_device *dev = mdev->dev;
- unsigned int i, row, col;
- uint32_t colour_set[16];
- uint32_t *next_space = &colour_set[0];
- uint32_t *palette_iter;
- uint32_t this_colour;
- bool found = false;
- int colour_count = 0;
- u8 reg_index;
- u8 this_row[48];
-
- memset(&colour_set[0], 0, sizeof(uint32_t)*16);
- /* width*height*4 = 16384 */
- for (i = 0; i < 16384; i += 4) {
- this_colour = ioread32(src + i);
- /* No transparency */
- if (this_colour>>24 != 0xff &&
- this_colour>>24 != 0x0) {
- if (warn_transparent) {
- dev_info(&dev->pdev->dev, "Video card doesn't support cursors with partial transparency.\n");
- dev_info(&dev->pdev->dev, "Not enabling hardware cursor.\n");
- warn_transparent = false; /* Only tell the user once. */
- }
- return -EINVAL;
- }
- /* Don't need to store transparent pixels as colours */
- if (this_colour>>24 == 0x0)
- continue;
- found = false;
- for (palette_iter = &colour_set[0]; palette_iter != next_space; palette_iter++) {
- if (*palette_iter == this_colour) {
- found = true;
- break;
- }
- }
- if (found)
- continue;
- /* We only support 4bit paletted cursors */
- if (colour_count >= 16) {
- if (warn_palette) {
- dev_info(&dev->pdev->dev, "Video card only supports cursors with up to 16 colours.\n");
- dev_info(&dev->pdev->dev, "Not enabling hardware cursor.\n");
- warn_palette = false; /* Only tell the user once. */
- }
- return -EINVAL;
- }
- *next_space = this_colour;
- next_space++;
- colour_count++;
- }
-
- /* Program colours from cursor icon into palette */
- for (i = 0; i < colour_count; i++) {
- if (i <= 2)
- reg_index = 0x8 + i*0x4;
- else
- reg_index = 0x60 + i*0x3;
- WREG_DAC(reg_index, colour_set[i] & 0xff);
- WREG_DAC(reg_index+1, colour_set[i]>>8 & 0xff);
- WREG_DAC(reg_index+2, colour_set[i]>>16 & 0xff);
- BUG_ON((colour_set[i]>>24 & 0xff) != 0xff);
- }
-
- /* now write colour indices into hardware cursor buffer */
- for (row = 0; row < 64; row++) {
- memset(&this_row[0], 0, 48);
- for (col = 0; col < 64; col++) {
- this_colour = ioread32(src + 4*(col + 64*row));
- /* write transparent pixels */
- if (this_colour>>24 == 0x0) {
- this_row[47 - col/8] |= 0x80>>(col%8);
- continue;
- }
-
- /* write colour index here */
- for (i = 0; i < colour_count; i++) {
- if (colour_set[i] == this_colour) {
- if (col % 2)
- this_row[col/2] |= i<<4;
- else
- this_row[col/2] |= i;
- break;
- }
- }
- }
- memcpy_toio(dst + row*48, &this_row[0], 48);
- }
-
- return 0;
-}
-
-static void mgag200_cursor_set_base(struct mga_device *mdev, u64 address)
-{
- u8 addrl = (address >> 10) & 0xff;
- u8 addrh = (address >> 18) & 0x3f;
-
- /* Program gpu address of cursor buffer */
- WREG_DAC(MGA1064_CURSOR_BASE_ADR_LOW, addrl);
- WREG_DAC(MGA1064_CURSOR_BASE_ADR_HI, addrh);
-}
-
-static int mgag200_show_cursor(struct mga_device *mdev, void *src,
- unsigned int width, unsigned int height)
-{
- struct drm_device *dev = mdev->dev;
- struct drm_gem_vram_object *gbo;
- void *dst;
- s64 off;
- int ret;
-
- gbo = mdev->cursor.gbo[mdev->cursor.next_index];
- if (!gbo) {
- WREG8(MGA_CURPOSXL, 0);
- WREG8(MGA_CURPOSXH, 0);
- return -ENOTSUPP; /* Didn't allocate space for cursors */
- }
- dst = drm_gem_vram_vmap(gbo);
- if (IS_ERR(dst)) {
- ret = PTR_ERR(dst);
- dev_err(&dev->pdev->dev,
- "failed to map cursor updates: %d\n", ret);
- return ret;
- }
- off = drm_gem_vram_offset(gbo);
- if (off < 0) {
- ret = (int)off;
- dev_err(&dev->pdev->dev,
- "failed to get cursor scanout address: %d\n", ret);
- goto err_drm_gem_vram_vunmap;
- }
-
- ret = mgag200_cursor_update(mdev, dst, src, width, height);
- if (ret)
- goto err_drm_gem_vram_vunmap;
- mgag200_cursor_set_base(mdev, off);
-
- /* Adjust cursor control register to turn on the cursor */
- WREG_DAC(MGA1064_CURSOR_CTL, 4); /* 16-colour palletized cursor mode */
-
- drm_gem_vram_vunmap(gbo, dst);
-
- ++mdev->cursor.next_index;
- mdev->cursor.next_index %= ARRAY_SIZE(mdev->cursor.gbo);
-
- return 0;
-
-err_drm_gem_vram_vunmap:
- drm_gem_vram_vunmap(gbo, dst);
- return ret;
-}
-
-/*
- * Hide the cursor off screen. We can't disable the cursor hardware because
- * it takes too long to re-activate and causes momentary corruption.
- */
-static void mgag200_hide_cursor(struct mga_device *mdev)
-{
- WREG8(MGA_CURPOSXL, 0);
- WREG8(MGA_CURPOSXH, 0);
-}
-
-static void mgag200_move_cursor(struct mga_device *mdev, int x, int y)
-{
- if (WARN_ON(x <= 0))
- return;
- if (WARN_ON(y <= 0))
- return;
- if (WARN_ON(x & ~0xffff))
- return;
- if (WARN_ON(y & ~0xffff))
- return;
-
- WREG8(MGA_CURPOSXL, x & 0xff);
- WREG8(MGA_CURPOSXH, (x>>8) & 0xff);
-
- WREG8(MGA_CURPOSYL, y & 0xff);
- WREG8(MGA_CURPOSYH, (y>>8) & 0xff);
-}
-
-int mgag200_cursor_init(struct mga_device *mdev)
-{
- struct drm_device *dev = mdev->dev;
- size_t ncursors = ARRAY_SIZE(mdev->cursor.gbo);
- size_t size;
- int ret;
- size_t i;
- struct drm_gem_vram_object *gbo;
-
- size = roundup(64 * 48, PAGE_SIZE);
- if (size * ncursors > mdev->vram_fb_available)
- return -ENOMEM;
-
- for (i = 0; i < ncursors; ++i) {
- gbo = drm_gem_vram_create(dev, size, 0);
- if (IS_ERR(gbo)) {
- ret = PTR_ERR(gbo);
- goto err_drm_gem_vram_put;
- }
- ret = drm_gem_vram_pin(gbo, DRM_GEM_VRAM_PL_FLAG_VRAM |
- DRM_GEM_VRAM_PL_FLAG_TOPDOWN);
- if (ret) {
- drm_gem_vram_put(gbo);
- goto err_drm_gem_vram_put;
- }
-
- mdev->cursor.gbo[i] = gbo;
- }
-
- /*
- * At the high end of video memory, we reserve space for
- * buffer objects. The cursor plane uses this memory to store
- * a double-buffered image of the current cursor. Hence, it's
- * not available for framebuffers.
- */
- mdev->vram_fb_available -= ncursors * size;
-
- return 0;
-
-err_drm_gem_vram_put:
- while (i) {
- --i;
- gbo = mdev->cursor.gbo[i];
- drm_gem_vram_unpin(gbo);
- drm_gem_vram_put(gbo);
- mdev->cursor.gbo[i] = NULL;
- }
- return ret;
-}
-
-void mgag200_cursor_fini(struct mga_device *mdev)
-{
- size_t i;
- struct drm_gem_vram_object *gbo;
-
- for (i = 0; i < ARRAY_SIZE(mdev->cursor.gbo); ++i) {
- gbo = mdev->cursor.gbo[i];
- drm_gem_vram_unpin(gbo);
- drm_gem_vram_put(gbo);
- }
-}
-
-int mgag200_crtc_cursor_set(struct drm_crtc *crtc, struct drm_file *file_priv,
- uint32_t handle, uint32_t width, uint32_t height)
-{
- struct drm_device *dev = crtc->dev;
- struct mga_device *mdev = to_mga_device(dev);
- struct drm_gem_object *obj;
- struct drm_gem_vram_object *gbo = NULL;
- int ret;
- u8 *src;
-
- if (!handle || !file_priv) {
- mgag200_hide_cursor(mdev);
- return 0;
- }
-
- if (width != 64 || height != 64) {
- WREG8(MGA_CURPOSXL, 0);
- WREG8(MGA_CURPOSXH, 0);
- return -EINVAL;
- }
-
- obj = drm_gem_object_lookup(file_priv, handle);
- if (!obj)
- return -ENOENT;
- gbo = drm_gem_vram_of_gem(obj);
- src = drm_gem_vram_vmap(gbo);
- if (IS_ERR(src)) {
- ret = PTR_ERR(src);
- dev_err(&dev->pdev->dev,
- "failed to map user buffer updates\n");
- goto err_drm_gem_object_put_unlocked;
- }
-
- ret = mgag200_show_cursor(mdev, src, width, height);
- if (ret)
- goto err_drm_gem_vram_vunmap;
-
- /* Now update internal buffer pointers */
- drm_gem_vram_vunmap(gbo, src);
- drm_gem_object_put_unlocked(obj);
-
- return 0;
-err_drm_gem_vram_vunmap:
- drm_gem_vram_vunmap(gbo, src);
-err_drm_gem_object_put_unlocked:
- drm_gem_object_put_unlocked(obj);
- return ret;
-}
-
-int mgag200_crtc_cursor_move(struct drm_crtc *crtc, int x, int y)
-{
- struct mga_device *mdev = to_mga_device(crtc->dev);
-
- /* Our origin is at (64,64) */
- x += 64;
- y += 64;
-
- mgag200_move_cursor(mdev, x, y);
-
- return 0;
-}
diff --git a/drivers/gpu/drm/mgag200/mgag200_drv.c b/drivers/gpu/drm/mgag200/mgag200_drv.c
index c2f0e4b40b05..e19660f4a637 100644
--- a/drivers/gpu/drm/mgag200/mgag200_drv.c
+++ b/drivers/gpu/drm/mgag200/mgag200_drv.c
@@ -17,23 +17,105 @@
#include "mgag200_drv.h"
-/*
- * This is the generic driver code. This binds the driver to the drm core,
- * which then performs further device association and calls our graphics init
- * functions
- */
int mgag200_modeset = -1;
-
MODULE_PARM_DESC(modeset, "Disable/Enable modesetting");
module_param_named(modeset, mgag200_modeset, int, 0400);
-int mgag200_hw_bug_no_startadd = -1;
-MODULE_PARM_DESC(modeset, "HW does not interpret scanout-buffer start address correctly");
-module_param_named(hw_bug_no_startadd, mgag200_hw_bug_no_startadd, int, 0400);
+/*
+ * DRM driver
+ */
+
+DEFINE_DRM_GEM_FOPS(mgag200_driver_fops);
+
+static struct drm_driver mgag200_driver = {
+ .driver_features = DRIVER_ATOMIC | DRIVER_GEM | DRIVER_MODESET,
+ .fops = &mgag200_driver_fops,
+ .name = DRIVER_NAME,
+ .desc = DRIVER_DESC,
+ .date = DRIVER_DATE,
+ .major = DRIVER_MAJOR,
+ .minor = DRIVER_MINOR,
+ .patchlevel = DRIVER_PATCHLEVEL,
+ DRM_GEM_SHMEM_DRIVER_OPS,
+};
+
+/*
+ * DRM device
+ */
+
+static int mgag200_device_init(struct mga_device *mdev, unsigned long flags)
+{
+ struct drm_device *dev = &mdev->base;
+ int ret, option;
+
+ mdev->flags = mgag200_flags_from_driver_data(flags);
+ mdev->type = mgag200_type_from_driver_data(flags);
+
+ pci_read_config_dword(dev->pdev, PCI_MGA_OPTION, &option);
+ mdev->has_sdram = !(option & (1 << 14));
+
+ /* BAR 0 is the framebuffer, BAR 1 contains registers */
+ mdev->rmmio_base = pci_resource_start(dev->pdev, 1);
+ mdev->rmmio_size = pci_resource_len(dev->pdev, 1);
+
+ if (!devm_request_mem_region(dev->dev, mdev->rmmio_base,
+ mdev->rmmio_size, "mgadrmfb_mmio")) {
+ drm_err(dev, "can't reserve mmio registers\n");
+ return -ENOMEM;
+ }
+
+ mdev->rmmio = pcim_iomap(dev->pdev, 1, 0);
+ if (mdev->rmmio == NULL)
+ return -ENOMEM;
+
+ /* stash G200 SE model number for later use */
+ if (IS_G200_SE(mdev)) {
+ mdev->unique_rev_id = RREG32(0x1e24);
+ drm_dbg(dev, "G200 SE unique revision id is 0x%x\n",
+ mdev->unique_rev_id);
+ }
+
+ ret = mgag200_mm_init(mdev);
+ if (ret)
+ return ret;
+
+ ret = mgag200_modeset_init(mdev);
+ if (ret) {
+ drm_err(dev, "Fatal error during modeset init: %d\n", ret);
+ return ret;
+ }
+
+ return 0;
+}
+
+static struct mga_device *
+mgag200_device_create(struct pci_dev *pdev, unsigned long flags)
+{
+ struct drm_device *dev;
+ struct mga_device *mdev;
+ int ret;
+
+ mdev = devm_drm_dev_alloc(&pdev->dev, &mgag200_driver,
+ struct mga_device, base);
+ if (IS_ERR(mdev))
+ return mdev;
+ dev = &mdev->base;
+
+ dev->pdev = pdev;
+ pci_set_drvdata(pdev, dev);
-static struct drm_driver driver;
+ ret = mgag200_device_init(mdev, flags);
+ if (ret)
+ return ERR_PTR(ret);
-static const struct pci_device_id pciidlist[] = {
+ return mdev;
+}
+
+/*
+ * PCI driver
+ */
+
+static const struct pci_device_id mgag200_pciidlist[] = {
{ PCI_VENDOR_ID_MATROX, 0x522, PCI_ANY_ID, PCI_ANY_ID, 0, 0,
G200_SE_A | MGAG200_FLAG_HW_BUG_NO_STARTADD},
{ PCI_VENDOR_ID_MATROX, 0x524, PCI_ANY_ID, PCI_ANY_ID, 0, 0, G200_SE_B },
@@ -46,119 +128,47 @@ static const struct pci_device_id pciidlist[] = {
{0,}
};
-MODULE_DEVICE_TABLE(pci, pciidlist);
-
+MODULE_DEVICE_TABLE(pci, mgag200_pciidlist);
-static int mga_pci_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
+static int
+mgag200_pci_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
{
+ struct mga_device *mdev;
struct drm_device *dev;
int ret;
drm_fb_helper_remove_conflicting_pci_framebuffers(pdev, "mgag200drmfb");
- ret = pci_enable_device(pdev);
+ ret = pcim_enable_device(pdev);
if (ret)
return ret;
- dev = drm_dev_alloc(&driver, &pdev->dev);
- if (IS_ERR(dev)) {
- ret = PTR_ERR(dev);
- goto err_pci_disable_device;
- }
-
- dev->pdev = pdev;
- pci_set_drvdata(pdev, dev);
-
- ret = mgag200_driver_load(dev, ent->driver_data);
- if (ret)
- goto err_drm_dev_put;
+ mdev = mgag200_device_create(pdev, ent->driver_data);
+ if (IS_ERR(mdev))
+ return PTR_ERR(mdev);
+ dev = &mdev->base;
ret = drm_dev_register(dev, ent->driver_data);
if (ret)
- goto err_mgag200_driver_unload;
+ return ret;
drm_fbdev_generic_setup(dev, 0);
return 0;
-
-err_mgag200_driver_unload:
- mgag200_driver_unload(dev);
-err_drm_dev_put:
- drm_dev_put(dev);
-err_pci_disable_device:
- pci_disable_device(pdev);
- return ret;
}
-static void mga_pci_remove(struct pci_dev *pdev)
+static void mgag200_pci_remove(struct pci_dev *pdev)
{
struct drm_device *dev = pci_get_drvdata(pdev);
drm_dev_unregister(dev);
- mgag200_driver_unload(dev);
- drm_dev_put(dev);
-}
-
-DEFINE_DRM_GEM_FOPS(mgag200_driver_fops);
-
-static bool mgag200_pin_bo_at_0(const struct mga_device *mdev)
-{
- if (mgag200_hw_bug_no_startadd > 0) {
- DRM_WARN_ONCE("Option hw_bug_no_startradd is enabled. Please "
- "report the output of 'lspci -vvnn' to "
- "<dri-devel@lists.freedesktop.org> if this "
- "option is required to make mgag200 work "
- "correctly on your system.\n");
- return true;
- } else if (!mgag200_hw_bug_no_startadd) {
- return false;
- }
- return mdev->flags & MGAG200_FLAG_HW_BUG_NO_STARTADD;
}
-int mgag200_driver_dumb_create(struct drm_file *file,
- struct drm_device *dev,
- struct drm_mode_create_dumb *args)
-{
- struct mga_device *mdev = to_mga_device(dev);
- unsigned long pg_align;
-
- if (WARN_ONCE(!dev->vram_mm, "VRAM MM not initialized"))
- return -EINVAL;
-
- pg_align = 0ul;
-
- /*
- * Aligning scanout buffers to the size of the video ram forces
- * placement at offset 0. Works around a bug where HW does not
- * respect 'startadd' field.
- */
- if (mgag200_pin_bo_at_0(mdev))
- pg_align = PFN_UP(mdev->mc.vram_size);
-
- return drm_gem_vram_fill_create_dumb(file, dev, pg_align, 0, args);
-}
-
-static struct drm_driver driver = {
- .driver_features = DRIVER_GEM | DRIVER_MODESET,
- .fops = &mgag200_driver_fops,
- .name = DRIVER_NAME,
- .desc = DRIVER_DESC,
- .date = DRIVER_DATE,
- .major = DRIVER_MAJOR,
- .minor = DRIVER_MINOR,
- .patchlevel = DRIVER_PATCHLEVEL,
- .debugfs_init = drm_vram_mm_debugfs_init,
- .dumb_create = mgag200_driver_dumb_create,
- .dumb_map_offset = drm_gem_vram_driver_dumb_mmap_offset,
- .gem_prime_mmap = drm_gem_prime_mmap,
-};
-
static struct pci_driver mgag200_pci_driver = {
.name = DRIVER_NAME,
- .id_table = pciidlist,
- .probe = mga_pci_probe,
- .remove = mga_pci_remove,
+ .id_table = mgag200_pciidlist,
+ .probe = mgag200_pci_probe,
+ .remove = mgag200_pci_remove,
};
static int __init mgag200_init(void)
diff --git a/drivers/gpu/drm/mgag200/mgag200_drv.h b/drivers/gpu/drm/mgag200/mgag200_drv.h
index d9b7e96b214f..270c2f9a6766 100644
--- a/drivers/gpu/drm/mgag200/mgag200_drv.h
+++ b/drivers/gpu/drm/mgag200/mgag200_drv.h
@@ -18,7 +18,8 @@
#include <drm/drm_encoder.h>
#include <drm/drm_fb_helper.h>
#include <drm/drm_gem.h>
-#include <drm/drm_gem_vram_helper.h>
+#include <drm/drm_gem_shmem_helper.h>
+#include <drm/drm_simple_kms_helper.h>
#include "mgag200_reg.h"
@@ -32,8 +33,6 @@
#define DRIVER_MINOR 0
#define DRIVER_PATCHLEVEL 0
-#define MGAG200FB_CONN_LIMIT 1
-
#define RREG8(reg) ioread8(((void __iomem *)mdev->rmmio) + (reg))
#define WREG8(reg, v) iowrite8(v, ((void __iomem *)mdev->rmmio) + (reg))
#define RREG32(reg) ioread32(((void __iomem *)mdev->rmmio) + (reg))
@@ -49,6 +48,12 @@
WREG8(ATTR_DATA, v); \
} while (0) \
+#define RREG_SEQ(reg, v) \
+ do { \
+ WREG8(MGAREG_SEQ_INDEX, reg); \
+ v = RREG8(MGAREG_SEQ_DATA); \
+ } while (0) \
+
#define WREG_SEQ(reg, v) \
do { \
WREG8(MGAREG_SEQ_INDEX, reg); \
@@ -61,6 +66,11 @@
WREG8(MGAREG_CRTC_DATA, v); \
} while (0) \
+#define RREG_ECRT(reg, v) \
+ do { \
+ WREG8(MGAREG_CRTCEXT_INDEX, reg); \
+ v = RREG8(MGAREG_CRTCEXT_DATA); \
+ } while (0) \
#define WREG_ECRT(reg, v) \
do { \
@@ -92,18 +102,8 @@
#define MGAG200_MAX_FB_HEIGHT 4096
#define MGAG200_MAX_FB_WIDTH 4096
-#define MATROX_DPMS_CLEARED (-1)
-
-#define to_mga_crtc(x) container_of(x, struct mga_crtc, base)
#define to_mga_connector(x) container_of(x, struct mga_connector, base)
-struct mga_crtc {
- struct drm_crtc base;
- u8 lut_r[256], lut_g[256], lut_b[256];
- int last_dpms;
- bool enabled;
-};
-
struct mga_i2c_chan {
struct i2c_adapter adapter;
struct drm_device *dev;
@@ -116,11 +116,6 @@ struct mga_connector {
struct mga_i2c_chan *i2c;
};
-struct mga_cursor {
- struct drm_gem_vram_object *gbo[2];
- unsigned int next_index;
-};
-
struct mga_mc {
resource_size_t vram_size;
resource_size_t vram_base;
@@ -147,7 +142,7 @@ enum mga_type {
#define IS_G200_SE(mdev) (mdev->type == G200_SE_A || mdev->type == G200_SE_B)
struct mga_device {
- struct drm_device *dev;
+ struct drm_device base;
unsigned long flags;
resource_size_t rmmio_base;
@@ -156,11 +151,9 @@ struct mga_device {
struct mga_mc mc;
- struct mga_cursor cursor;
-
- size_t vram_fb_available;
+ void __iomem *vram;
+ size_t vram_fb_available;
- bool suspended;
enum mga_type type;
int has_sdram;
@@ -172,12 +165,12 @@ struct mga_device {
u32 unique_rev_id;
struct mga_connector connector;
- struct drm_encoder encoder;
+ struct drm_simple_display_pipe display_pipe;
};
static inline struct mga_device *to_mga_device(struct drm_device *dev)
{
- return dev->dev_private;
+ return container_of(dev, struct mga_device, base);
}
static inline enum mga_type
@@ -195,22 +188,11 @@ mgag200_flags_from_driver_data(kernel_ulong_t driver_data)
/* mgag200_mode.c */
int mgag200_modeset_init(struct mga_device *mdev);
- /* mgag200_main.c */
-int mgag200_driver_load(struct drm_device *dev, unsigned long flags);
-void mgag200_driver_unload(struct drm_device *dev);
-
/* mgag200_i2c.c */
struct mga_i2c_chan *mgag200_i2c_create(struct drm_device *dev);
void mgag200_i2c_destroy(struct mga_i2c_chan *i2c);
+ /* mgag200_mm.c */
int mgag200_mm_init(struct mga_device *mdev);
-void mgag200_mm_fini(struct mga_device *mdev);
-int mgag200_mmap(struct file *filp, struct vm_area_struct *vma);
-
-int mgag200_cursor_init(struct mga_device *mdev);
-void mgag200_cursor_fini(struct mga_device *mdev);
-int mgag200_crtc_cursor_set(struct drm_crtc *crtc, struct drm_file *file_priv,
- uint32_t handle, uint32_t width, uint32_t height);
-int mgag200_crtc_cursor_move(struct drm_crtc *crtc, int x, int y);
#endif /* __MGAG200_DRV_H__ */
diff --git a/drivers/gpu/drm/mgag200/mgag200_main.c b/drivers/gpu/drm/mgag200/mgag200_main.c
deleted file mode 100644
index 86df799fd38c..000000000000
--- a/drivers/gpu/drm/mgag200/mgag200_main.c
+++ /dev/null
@@ -1,160 +0,0 @@
-// SPDX-License-Identifier: GPL-2.0-only
-/*
- * Copyright 2010 Matt Turner.
- * Copyright 2012 Red Hat
- *
- * Authors: Matthew Garrett
- * Matt Turner
- * Dave Airlie
- */
-
-#include <linux/pci.h>
-
-#include "mgag200_drv.h"
-
-static int mga_probe_vram(struct mga_device *mdev, void __iomem *mem)
-{
- int offset;
- int orig;
- int test1, test2;
- int orig1, orig2;
- unsigned int vram_size;
-
- /* Probe */
- orig = ioread16(mem);
- iowrite16(0, mem);
-
- vram_size = mdev->mc.vram_window;
-
- if ((mdev->type == G200_EW3) && (vram_size >= 0x1000000)) {
- vram_size = vram_size - 0x400000;
- }
-
- for (offset = 0x100000; offset < vram_size; offset += 0x4000) {
- orig1 = ioread8(mem + offset);
- orig2 = ioread8(mem + offset + 0x100);
-
- iowrite16(0xaa55, mem + offset);
- iowrite16(0xaa55, mem + offset + 0x100);
-
- test1 = ioread16(mem + offset);
- test2 = ioread16(mem);
-
- iowrite16(orig1, mem + offset);
- iowrite16(orig2, mem + offset + 0x100);
-
- if (test1 != 0xaa55) {
- break;
- }
-
- if (test2) {
- break;
- }
- }
-
- iowrite16(orig, mem);
- return offset - 65536;
-}
-
-/* Map the framebuffer from the card and configure the core */
-static int mga_vram_init(struct mga_device *mdev)
-{
- struct drm_device *dev = mdev->dev;
- void __iomem *mem;
-
- /* BAR 0 is VRAM */
- mdev->mc.vram_base = pci_resource_start(dev->pdev, 0);
- mdev->mc.vram_window = pci_resource_len(dev->pdev, 0);
-
- if (!devm_request_mem_region(dev->dev, mdev->mc.vram_base,
- mdev->mc.vram_window, "mgadrmfb_vram")) {
- DRM_ERROR("can't reserve VRAM\n");
- return -ENXIO;
- }
-
- mem = pci_iomap(dev->pdev, 0, 0);
- if (!mem)
- return -ENOMEM;
-
- mdev->mc.vram_size = mga_probe_vram(mdev, mem);
-
- pci_iounmap(dev->pdev, mem);
-
- return 0;
-}
-
-int mgag200_driver_load(struct drm_device *dev, unsigned long flags)
-{
- struct mga_device *mdev;
- int ret, option;
-
- mdev = devm_kzalloc(dev->dev, sizeof(struct mga_device), GFP_KERNEL);
- if (mdev == NULL)
- return -ENOMEM;
- dev->dev_private = (void *)mdev;
- mdev->dev = dev;
-
- mdev->flags = mgag200_flags_from_driver_data(flags);
- mdev->type = mgag200_type_from_driver_data(flags);
-
- pci_read_config_dword(dev->pdev, PCI_MGA_OPTION, &option);
- mdev->has_sdram = !(option & (1 << 14));
-
- /* BAR 0 is the framebuffer, BAR 1 contains registers */
- mdev->rmmio_base = pci_resource_start(dev->pdev, 1);
- mdev->rmmio_size = pci_resource_len(dev->pdev, 1);
-
- if (!devm_request_mem_region(dev->dev, mdev->rmmio_base,
- mdev->rmmio_size, "mgadrmfb_mmio")) {
- drm_err(dev, "can't reserve mmio registers\n");
- return -ENOMEM;
- }
-
- mdev->rmmio = pcim_iomap(dev->pdev, 1, 0);
- if (mdev->rmmio == NULL)
- return -ENOMEM;
-
- /* stash G200 SE model number for later use */
- if (IS_G200_SE(mdev)) {
- mdev->unique_rev_id = RREG32(0x1e24);
- drm_dbg(dev, "G200 SE unique revision id is 0x%x\n",
- mdev->unique_rev_id);
- }
-
- ret = mga_vram_init(mdev);
- if (ret)
- return ret;
-
- ret = mgag200_mm_init(mdev);
- if (ret)
- goto err_mm;
-
- ret = mgag200_modeset_init(mdev);
- if (ret) {
- drm_err(dev, "Fatal error during modeset init: %d\n", ret);
- goto err_mgag200_mm_fini;
- }
-
- ret = mgag200_cursor_init(mdev);
- if (ret)
- drm_err(dev, "Could not initialize cursors. Not doing hardware cursors.\n");
-
- return 0;
-
-err_mgag200_mm_fini:
- mgag200_mm_fini(mdev);
-err_mm:
- dev->dev_private = NULL;
- return ret;
-}
-
-void mgag200_driver_unload(struct drm_device *dev)
-{
- struct mga_device *mdev = to_mga_device(dev);
-
- if (mdev == NULL)
- return;
- mgag200_cursor_fini(mdev);
- mgag200_mm_fini(mdev);
- dev->dev_private = NULL;
-}
diff --git a/drivers/gpu/drm/mgag200/mgag200_mm.c b/drivers/gpu/drm/mgag200/mgag200_mm.c
new file mode 100644
index 000000000000..7b69392bcb89
--- /dev/null
+++ b/drivers/gpu/drm/mgag200/mgag200_mm.c
@@ -0,0 +1,127 @@
+/*
+ * Copyright 2012 Red Hat Inc.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the
+ * "Software"), to deal in the Software without restriction, including
+ * without limitation the rights to use, copy, modify, merge, publish,
+ * distribute, sub license, and/or sell copies of the Software, and to
+ * permit persons to whom the Software is furnished to do so, subject to
+ * the following conditions:
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL
+ * THE COPYRIGHT HOLDERS, AUTHORS AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM,
+ * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
+ * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
+ * USE OR OTHER DEALINGS IN THE SOFTWARE.
+ *
+ * The above copyright notice and this permission notice (including the
+ * next paragraph) shall be included in all copies or substantial portions
+ * of the Software.
+ *
+ */
+/*
+ * Authors: Dave Airlie <airlied@redhat.com>
+ */
+
+#include <linux/pci.h>
+
+#include <drm/drm_managed.h>
+
+#include "mgag200_drv.h"
+
+static size_t mgag200_probe_vram(struct mga_device *mdev, void __iomem *mem,
+ size_t size)
+{
+ int offset;
+ int orig;
+ int test1, test2;
+ int orig1, orig2;
+ size_t vram_size;
+
+ /* Probe */
+ orig = ioread16(mem);
+ iowrite16(0, mem);
+
+ vram_size = size;
+
+ if ((mdev->type == G200_EW3) && (vram_size >= 0x1000000))
+ vram_size = vram_size - 0x400000;
+
+ for (offset = 0x100000; offset < vram_size; offset += 0x4000) {
+ orig1 = ioread8(mem + offset);
+ orig2 = ioread8(mem + offset + 0x100);
+
+ iowrite16(0xaa55, mem + offset);
+ iowrite16(0xaa55, mem + offset + 0x100);
+
+ test1 = ioread16(mem + offset);
+ test2 = ioread16(mem);
+
+ iowrite16(orig1, mem + offset);
+ iowrite16(orig2, mem + offset + 0x100);
+
+ if (test1 != 0xaa55)
+ break;
+
+ if (test2)
+ break;
+ }
+
+ iowrite16(orig, mem);
+
+ return offset - 65536;
+}
+
+static void mgag200_mm_release(struct drm_device *dev, void *ptr)
+{
+ struct mga_device *mdev = to_mga_device(dev);
+
+ mdev->vram_fb_available = 0;
+ iounmap(mdev->vram);
+ arch_io_free_memtype_wc(pci_resource_start(dev->pdev, 0),
+ pci_resource_len(dev->pdev, 0));
+ arch_phys_wc_del(mdev->fb_mtrr);
+ mdev->fb_mtrr = 0;
+}
+
+int mgag200_mm_init(struct mga_device *mdev)
+{
+ struct drm_device *dev = &mdev->base;
+ resource_size_t start, len;
+ int ret;
+
+ /* BAR 0 is VRAM */
+ start = pci_resource_start(dev->pdev, 0);
+ len = pci_resource_len(dev->pdev, 0);
+
+ if (!devm_request_mem_region(dev->dev, start, len, "mgadrmfb_vram")) {
+ drm_err(dev, "can't reserve VRAM\n");
+ return -ENXIO;
+ }
+
+ arch_io_reserve_memtype_wc(start, len);
+
+ mdev->fb_mtrr = arch_phys_wc_add(start, len);
+
+ mdev->vram = ioremap(start, len);
+ if (!mdev->vram) {
+ ret = -ENOMEM;
+ goto err_arch_phys_wc_del;
+ }
+
+ mdev->mc.vram_size = mgag200_probe_vram(mdev, mdev->vram, len);
+ mdev->mc.vram_base = start;
+ mdev->mc.vram_window = len;
+
+ mdev->vram_fb_available = mdev->mc.vram_size;
+
+ return drmm_add_action_or_reset(dev, mgag200_mm_release, NULL);
+
+err_arch_phys_wc_del:
+ arch_phys_wc_del(mdev->fb_mtrr);
+ arch_io_free_memtype_wc(start, len);
+ return ret;
+}
diff --git a/drivers/gpu/drm/mgag200/mgag200_mode.c b/drivers/gpu/drm/mgag200/mgag200_mode.c
index 5f4ac36a9776..f16bd278ab7e 100644
--- a/drivers/gpu/drm/mgag200/mgag200_mode.c
+++ b/drivers/gpu/drm/mgag200/mgag200_mode.c
@@ -11,10 +11,15 @@
#include <linux/delay.h>
#include <linux/pci.h>
+#include <drm/drm_atomic_helper.h>
+#include <drm/drm_atomic_state_helper.h>
#include <drm/drm_crtc_helper.h>
+#include <drm/drm_damage_helper.h>
+#include <drm/drm_format_helper.h>
#include <drm/drm_fourcc.h>
#include <drm/drm_gem_framebuffer_helper.h>
#include <drm/drm_plane_helper.h>
+#include <drm/drm_print.h>
#include <drm/drm_probe_helper.h>
#include <drm/drm_simple_kms_helper.h>
@@ -30,13 +35,18 @@ static void mga_crtc_load_lut(struct drm_crtc *crtc)
{
struct drm_device *dev = crtc->dev;
struct mga_device *mdev = to_mga_device(dev);
- struct drm_framebuffer *fb = crtc->primary->fb;
+ struct drm_framebuffer *fb;
u16 *r_ptr, *g_ptr, *b_ptr;
int i