Re: further issues with MGA G200 graphics chipset
From: Thomas Zimmermann
Date: Mon Apr 27 2026 - 08:15:06 EST
Hi
Am 25.04.26 um 01:29 schrieb Jacob Keller:
[...]
I think this is the best solution. Keep it focused for now. I believe
So I suggest to pick Manufacturer, Product, Version as key. I'd be
surprised if we find more than a hand full of systems with the issue. If
we see a trend or common pattern, we can generalize later on.
Intel has two major platforms that we care about with respect to this
issue. I'll see if I can dig up the data. The systems install the MGA
G200 for BMC use but don't seem to expose the VGA connection.
For the specific system I have that was faulty, we have the following:
$ for t in system-manufacturer system-product-name system-version ; \
do dmidecode -s ${t}; \
done
Dell Inc.
PowerEdge XR8720t
Not Specified
I believe there was also some concern about HP systems which similarly
use this chipset, but I don't have the DMI data for that one off hand.
I've asked some colleagues to confirm the situation and obtain that
data. I'll get back early next week if we think there are any other
systems possibly affected.
In the mean time, I'm happy to have our team test any patch to confirm
that it behaves as expected and resolves the service interruptions.
For now, I've modified the two places that have BMC support in the driver. Could you please also tell me your system's exact Matrox chipset or its PCI id?
The patch is attached for your testing. It would work against drm-tip or v7.1-rc1.
I've also found the page at [1], which claims that there's a Mini-DP port at the front. If so, I'd assume that there's also an extra encoder chip to replace the VGA. If we ever get specs for that, we could implement real support in the driver.
In the meantime, the current fix should work. In the worst case, that Mini-DP port would give a lower default resolution.
[1] https://www.dell.com/en-us/shop/ipovw/poweredge-xr8720t?hve=shop+now#techspecs_section
Best regards
Thomas
Appreciate all the feedback on this thread.
Thanks,
Jake
--
--
Thomas Zimmermann
Graphics Driver Developer
SUSE Software Solutions Germany GmbH
Frankenstr. 146, 90461 Nürnberg, Germany, www.suse.com
GF: Jochen Jaser, Andrew McDonald, Werner Knoblich, (HRB 36809, AG Nürnberg)
From 95d72c2e4abef9fc45433076d3b130336c734e75 Mon Sep 17 00:00:00 2001
From: Thomas Zimmermann <tzimmermann@xxxxxxx>
Date: Fri, 24 Apr 2026 09:05:14 +0200
Subject: [PATCH] drm/mgag200: Add BMC-only connector
---
drivers/gpu/drm/mgag200/mgag200_bmc.c | 109 ++++++++++++++++++++++
drivers/gpu/drm/mgag200/mgag200_drv.h | 7 +-
drivers/gpu/drm/mgag200/mgag200_g200ew3.c | 17 +++-
drivers/gpu/drm/mgag200/mgag200_g200wb.c | 17 +++-
4 files changed, 147 insertions(+), 3 deletions(-)
diff --git a/drivers/gpu/drm/mgag200/mgag200_bmc.c b/drivers/gpu/drm/mgag200/mgag200_bmc.c
index bbdeb791c5b3..8d974e2c1810 100644
--- a/drivers/gpu/drm/mgag200/mgag200_bmc.c
+++ b/drivers/gpu/drm/mgag200/mgag200_bmc.c
@@ -6,6 +6,8 @@
#include <drm/drm_atomic_helper.h>
#include <drm/drm_edid.h>
#include <drm/drm_managed.h>
+#include <drm/drm_modeset_helper_vtables.h>
+#include <drm/drm_print.h>
#include <drm/drm_probe_helper.h>
#include "mgag200_drv.h"
@@ -90,3 +92,110 @@ void mgag200_bmc_start_scanout(struct mga_device *mdev)
tmp &= ~0x10;
WREG_DAC(MGA1064_GEN_IO_DATA, tmp);
}
+
+static void mgag200_bmc_encoder_atomic_disable(struct drm_encoder *encoder,
+ struct drm_atomic_state *state)
+{
+ struct mga_device *mdev = to_mga_device(encoder->dev);
+
+ if (mdev->info->sync_bmc)
+ mgag200_bmc_stop_scanout(mdev);
+}
+
+static void mgag200_bmc_encoder_atomic_enable(struct drm_encoder *encoder,
+ struct drm_atomic_state *state)
+{
+ struct mga_device *mdev = to_mga_device(encoder->dev);
+
+ if (mdev->info->sync_bmc)
+ mgag200_bmc_start_scanout(mdev);
+}
+
+static int mgag200_bmc_encoder_atomic_check(struct drm_encoder *encoder,
+ struct drm_crtc_state *new_crtc_state,
+ struct drm_connector_state *new_connector_state)
+{
+ struct mga_device *mdev = to_mga_device(encoder->dev);
+ struct mgag200_crtc_state *new_mgag200_crtc_state = to_mgag200_crtc_state(new_crtc_state);
+
+ new_mgag200_crtc_state->set_vidrst = mdev->info->sync_bmc;
+
+ return 0;
+}
+
+static const struct drm_encoder_helper_funcs mgag200_bmc_encoder_helper_funcs = {
+ .atomic_disable = mgag200_bmc_encoder_atomic_disable,
+ .atomic_enable = mgag200_bmc_encoder_atomic_enable,
+ .atomic_check = mgag200_bmc_encoder_atomic_check,
+};
+
+static const struct drm_encoder_funcs mgag200_bmc_encoder_funcs = {
+ .destroy = drm_encoder_cleanup
+};
+
+static int mgag200_bmc_connector_helper_get_modes(struct drm_connector *connector)
+{
+ struct mga_device *mdev = to_mga_device(connector->dev);
+ const struct mgag200_device_info *minfo = mdev->info;
+ int count;
+
+ /*
+ * There's no EDID data without a connected monitor. Set BMC-
+ * compatible modes in this case. The XGA default resolution
+ * should work well for all BMCs.
+ */
+ count = drm_add_modes_noedid(connector, minfo->max_hdisplay, minfo->max_vdisplay);
+ if (count)
+ drm_set_preferred_mode(connector, 1024, 768);
+
+ return count;
+}
+
+static const struct drm_connector_helper_funcs mgag200_bmc_connector_helper_funcs = {
+ .get_modes = mgag200_bmc_connector_helper_get_modes,
+};
+
+static const struct drm_connector_funcs mgag200_bmc_connector_funcs = {
+ .reset = drm_atomic_helper_connector_reset,
+ .fill_modes = drm_helper_probe_single_connector_modes,
+ .destroy = drm_connector_cleanup,
+ .atomic_duplicate_state = drm_atomic_helper_connector_duplicate_state,
+ .atomic_destroy_state = drm_atomic_helper_connector_destroy_state
+};
+
+int mgag200_bmc_output_init(struct mga_device *mdev)
+{
+ struct drm_device *dev = &mdev->base;
+ struct drm_crtc *crtc = &mdev->crtc;
+ struct drm_encoder *encoder;
+ struct drm_connector *connector;
+ int ret;
+
+ encoder = &mdev->output.bmc.encoder;
+ ret = drm_encoder_init(dev, encoder, &mgag200_bmc_encoder_funcs,
+ DRM_MODE_ENCODER_VIRTUAL, NULL);
+ if (ret) {
+ drm_err(dev, "drm_encoder_init() failed: %d\n", ret);
+ return ret;
+ }
+ drm_encoder_helper_add(encoder, &mgag200_bmc_encoder_helper_funcs);
+
+ encoder->possible_crtcs = drm_crtc_mask(crtc);
+
+ connector = &mdev->output.bmc.connector;
+ ret = drm_connector_init(dev, connector, &mgag200_bmc_connector_funcs,
+ DRM_MODE_CONNECTOR_VGA);
+ if (ret) {
+ drm_err(dev, "drm_connector_init() failed: %d\n", ret);
+ return ret;
+ }
+ drm_connector_helper_add(connector, &mgag200_bmc_connector_helper_funcs);
+
+ ret = drm_connector_attach_encoder(connector, encoder);
+ if (ret) {
+ drm_err(dev, "drm_connector_attach_encoder() failed: %d\n", ret);
+ return ret;
+ }
+
+ return 0;
+}
diff --git a/drivers/gpu/drm/mgag200/mgag200_drv.h b/drivers/gpu/drm/mgag200/mgag200_drv.h
index a875c4bf8cbe..f126f6d61ed0 100644
--- a/drivers/gpu/drm/mgag200/mgag200_drv.h
+++ b/drivers/gpu/drm/mgag200/mgag200_drv.h
@@ -279,7 +279,11 @@ struct mga_device {
struct drm_plane primary_plane;
struct drm_crtc crtc;
- struct {
+ union {
+ struct {
+ struct drm_encoder encoder;
+ struct drm_connector connector;
+ } bmc;
struct {
struct drm_encoder encoder;
struct drm_connector connector;
@@ -435,5 +439,6 @@ int mgag200_vga_output_init(struct mga_device *mdev);
/* mgag200_bmc.c */
void mgag200_bmc_stop_scanout(struct mga_device *mdev);
void mgag200_bmc_start_scanout(struct mga_device *mdev);
+int mgag200_bmc_output_init(struct mga_device *mdev);
#endif /* __MGAG200_DRV_H__ */
diff --git a/drivers/gpu/drm/mgag200/mgag200_g200ew3.c b/drivers/gpu/drm/mgag200/mgag200_g200ew3.c
index e387a455eae5..12047066b615 100644
--- a/drivers/gpu/drm/mgag200/mgag200_g200ew3.c
+++ b/drivers/gpu/drm/mgag200/mgag200_g200ew3.c
@@ -1,5 +1,6 @@
// SPDX-License-Identifier: GPL-2.0-only
+#include <linux/dmi.h>
#include <linux/pci.h>
#include <drm/drm_atomic.h>
@@ -11,6 +12,17 @@
#include "mgag200_drv.h"
+static const struct dmi_system_id mgag200_g200ew3_novga[] = {
+ {
+ .ident = "PowerEdge XR8720t",
+ .matches = {
+ DMI_MATCH(DMI_SYS_VENDOR, "Dell Inc."),
+ DMI_MATCH(DMI_PRODUCT_NAME, "PowerEdge XR8720t"),
+ },
+ },
+ {},
+};
+
static void mgag200_g200ew3_init_registers(struct mga_device *mdev)
{
mgag200_g200wb_init_registers(mdev); // same as G200WB
@@ -128,7 +140,10 @@ static int mgag200_g200ew3_pipeline_init(struct mga_device *mdev)
drm_mode_crtc_set_gamma_size(crtc, MGAG200_LUT_SIZE);
drm_crtc_enable_color_mgmt(crtc, 0, false, MGAG200_LUT_SIZE);
- ret = mgag200_vga_bmc_output_init(mdev);
+ if (dmi_check_system(mgag200_g200ew3_novga))
+ ret = mgag200_bmc_output_init(mdev);
+ else
+ ret = mgag200_vga_bmc_output_init(mdev);
if (ret)
return ret;
diff --git a/drivers/gpu/drm/mgag200/mgag200_g200wb.c b/drivers/gpu/drm/mgag200/mgag200_g200wb.c
index d847fa8ded8c..e6ce1130d5eb 100644
--- a/drivers/gpu/drm/mgag200/mgag200_g200wb.c
+++ b/drivers/gpu/drm/mgag200/mgag200_g200wb.c
@@ -1,6 +1,7 @@
// SPDX-License-Identifier: GPL-2.0-only
#include <linux/delay.h>
+#include <linux/dmi.h>
#include <linux/pci.h>
#include <drm/drm_atomic.h>
@@ -12,6 +13,17 @@
#include "mgag200_drv.h"
+static const struct dmi_system_id mgag200_g200wb_novga[] = {
+ {
+ .ident = "PowerEdge XR8720t",
+ .matches = {
+ DMI_MATCH(DMI_SYS_VENDOR, "Dell Inc."),
+ DMI_MATCH(DMI_PRODUCT_NAME, "PowerEdge XR8720t"),
+ },
+ },
+ {},
+};
+
void mgag200_g200wb_init_registers(struct mga_device *mdev)
{
static const u8 dacvalue[] = {
@@ -262,7 +274,10 @@ static int mgag200_g200wb_pipeline_init(struct mga_device *mdev)
drm_mode_crtc_set_gamma_size(crtc, MGAG200_LUT_SIZE);
drm_crtc_enable_color_mgmt(crtc, 0, false, MGAG200_LUT_SIZE);
- ret = mgag200_vga_bmc_output_init(mdev);
+ if (dmi_check_system(mgag200_g200wb_novga))
+ ret = mgag200_bmc_output_init(mdev);
+ else
+ ret = mgag200_vga_bmc_output_init(mdev);
if (ret)
return ret;
--
2.54.0