Commit 1591fadf authored by Thomas Zimmermann's avatar Thomas Zimmermann

drm/mgag200: Add workaround for HW that does not support 'startadd'

There's at least one system that does not interpret the value of
the device's 'startadd' field correctly, which leads to incorrectly
displayed scanout buffers. Always placing the active scanout buffer
at offset 0 works around the problem.
Signed-off-by: default avatarThomas Zimmermann <tzimmermann@suse.de>
Reported-by: default avatarJohn Donnelly <john.p.donnelly@oracle.com>
Tested-by: default avatarJohn Donnelly <john.p.donnelly@oracle.com>
Reviewed-by: default avatarDaniel Vetter <daniel.vetter@ffwll.ch>
Fixes: 81da87f6 ("drm: Replace drm_gem_vram_push_to_system() with kunmap + unpin")
Cc: Gerd Hoffmann <kraxel@redhat.com>
Cc: Dave Airlie <airlied@redhat.com>
Cc: Maarten Lankhorst <maarten.lankhorst@linux.intel.com>
Cc: Maxime Ripard <mripard@kernel.org>
Cc: David Airlie <airlied@linux.ie>
Cc: Sam Ravnborg <sam@ravnborg.org>
Cc: "Y.C. Chen" <yc_chen@aspeedtech.com>
Cc: Neil Armstrong <narmstrong@baylibre.com>
Cc: Thomas Gleixner <tglx@linutronix.de>
Cc: "José Roberto de Souza" <jose.souza@intel.com>
Cc: Andrzej Pietrasiewicz <andrzej.p@collabora.com>
Cc: dri-devel@lists.freedesktop.org
Cc: <stable@vger.kernel.org> # v5.3+
Link: https://gitlab.freedesktop.org/drm/misc/issues/7
Link: https://patchwork.freedesktop.org/patch/msgid/20191126101529.20356-4-tzimmermann@suse.de
parent d6d437d9
...@@ -30,6 +30,8 @@ module_param_named(modeset, mgag200_modeset, int, 0400); ...@@ -30,6 +30,8 @@ module_param_named(modeset, mgag200_modeset, int, 0400);
static struct drm_driver driver; static struct drm_driver driver;
static const struct pci_device_id pciidlist[] = { static const struct pci_device_id pciidlist[] = {
{ PCI_VENDOR_ID_MATROX, 0x522, PCI_VENDOR_ID_SUN, 0x4852, 0, 0,
G200_SE_A | MGAG200_FLAG_HW_BUG_NO_STARTADD},
{ PCI_VENDOR_ID_MATROX, 0x522, PCI_ANY_ID, PCI_ANY_ID, 0, 0, G200_SE_A }, { PCI_VENDOR_ID_MATROX, 0x522, PCI_ANY_ID, PCI_ANY_ID, 0, 0, G200_SE_A },
{ PCI_VENDOR_ID_MATROX, 0x524, PCI_ANY_ID, PCI_ANY_ID, 0, 0, G200_SE_B }, { PCI_VENDOR_ID_MATROX, 0x524, PCI_ANY_ID, PCI_ANY_ID, 0, 0, G200_SE_B },
{ PCI_VENDOR_ID_MATROX, 0x530, PCI_ANY_ID, PCI_ANY_ID, 0, 0, G200_EV }, { PCI_VENDOR_ID_MATROX, 0x530, PCI_ANY_ID, PCI_ANY_ID, 0, 0, G200_EV },
...@@ -60,6 +62,35 @@ static void mga_pci_remove(struct pci_dev *pdev) ...@@ -60,6 +62,35 @@ static void mga_pci_remove(struct pci_dev *pdev)
DEFINE_DRM_GEM_FOPS(mgag200_driver_fops); DEFINE_DRM_GEM_FOPS(mgag200_driver_fops);
static bool mgag200_pin_bo_at_0(const struct mga_device *mdev)
{
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 = dev->dev_private;
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, &dev->vram_mm->bdev,
pg_align, false, args);
}
static struct drm_driver driver = { static struct drm_driver driver = {
.driver_features = DRIVER_GEM | DRIVER_MODESET, .driver_features = DRIVER_GEM | DRIVER_MODESET,
.load = mgag200_driver_load, .load = mgag200_driver_load,
...@@ -71,7 +102,10 @@ static struct drm_driver driver = { ...@@ -71,7 +102,10 @@ static struct drm_driver driver = {
.major = DRIVER_MAJOR, .major = DRIVER_MAJOR,
.minor = DRIVER_MINOR, .minor = DRIVER_MINOR,
.patchlevel = DRIVER_PATCHLEVEL, .patchlevel = DRIVER_PATCHLEVEL,
DRM_GEM_VRAM_DRIVER .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 = { static struct pci_driver mgag200_pci_driver = {
......
...@@ -150,6 +150,9 @@ enum mga_type { ...@@ -150,6 +150,9 @@ enum mga_type {
G200_EW3, G200_EW3,
}; };
/* HW does not handle 'startadd' field correct. */
#define MGAG200_FLAG_HW_BUG_NO_STARTADD (1ul << 8)
#define MGAG200_TYPE_MASK (0x000000ff) #define MGAG200_TYPE_MASK (0x000000ff)
#define MGAG200_FLAG_MASK (0x00ffff00) #define MGAG200_FLAG_MASK (0x00ffff00)
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment