diff mbox

[1/1] drm/mgag200: Added resolution and bandwidth limits for various G200e products.

Message ID a7ba1d84d4fb762c7e4a4ee3c438d7eccf664d40.1371475033.git.jlemire@matrox.com (mailing list archive)
State New, archived
Headers show

Commit Message

Julia Lemire June 17, 2013, 1:19 p.m. UTC
This code was ported from the old xorg mga driver.  These limits were
implemented as a solution to a number of problems that were seen.  These
problems were linked to the bandwidth limitations of the g200e series.

Signed-off-by: Julia Lemire <jlemire@matrox.com>
---
 drivers/gpu/drm/mgag200/mgag200_drv.h  |    3 +-
 drivers/gpu/drm/mgag200/mgag200_main.c |    2 +-
 drivers/gpu/drm/mgag200/mgag200_mode.c |   55 ++++++++++++++++++++++++++++++--
 3 files changed, 56 insertions(+), 4 deletions(-)

Comments

Julia Lemire June 19, 2013, 2:56 p.m. UTC | #1
On 13-06-17 09:19 AM, Julia Lemire wrote:
> +static uint32_t mga_vga_calculate_mode_bandwidth(struct drm_display_mode * mode,
> +                                                       int bits_per_pixel)
> +{
> +       uint64_t active_area, total_area, pixels_per_second;
> +       uint64_t bytes_per_pixel = (bits_per_pixel + 7) / 8;
> +
> +       if(!mode->htotal || !mode->vtotal || !mode->clock)
> +               return 0;
> +
> +       active_area = mode->hdisplay * mode->vdisplay;
> +       total_area = mode->htotal * mode->vtotal;
> +       pixels_per_second = active_area * mode->clock * 1000 / total_area;
> +       return (uint32_t)(pixels_per_second * bytes_per_pixel * 100 / (1024));
> +}
I found a bug while testing this on a 32-bit machine linked to the 
64-bit division.  Sorry.
diff mbox

Patch

diff --git a/drivers/gpu/drm/mgag200/mgag200_drv.h b/drivers/gpu/drm/mgag200/mgag200_drv.h
index bf29b2f..988911a 100644
--- a/drivers/gpu/drm/mgag200/mgag200_drv.h
+++ b/drivers/gpu/drm/mgag200/mgag200_drv.h
@@ -198,7 +198,8 @@  struct mga_device {
 		struct ttm_bo_device bdev;
 	} ttm;
 
-	u32 reg_1e24; /* SE model number */
+	/* SE model number stored in reg 0x1e24 */
+	u32 unique_rev_id;
 };
 
 
diff --git a/drivers/gpu/drm/mgag200/mgag200_main.c b/drivers/gpu/drm/mgag200/mgag200_main.c
index 9905923..dafe049 100644
--- a/drivers/gpu/drm/mgag200/mgag200_main.c
+++ b/drivers/gpu/drm/mgag200/mgag200_main.c
@@ -176,7 +176,7 @@  static int mgag200_device_init(struct drm_device *dev,
 
 	/* stash G200 SE model number for later use */
 	if (IS_G200_SE(mdev))
-		mdev->reg_1e24 = RREG32(0x1e24);
+		mdev->unique_rev_id = RREG32(0x1e24);
 
 	ret = mga_vram_init(mdev);
 	if (ret)
diff --git a/drivers/gpu/drm/mgag200/mgag200_mode.c b/drivers/gpu/drm/mgag200/mgag200_mode.c
index ee66bad..3cdebe6 100644
--- a/drivers/gpu/drm/mgag200/mgag200_mode.c
+++ b/drivers/gpu/drm/mgag200/mgag200_mode.c
@@ -1008,7 +1008,7 @@  static int mga_crtc_mode_set(struct drm_crtc *crtc,
 
 
 	if (IS_G200_SE(mdev)) {
-		if (mdev->reg_1e24 >= 0x02) {
+		if (mdev->unique_rev_id >= 0x02) {
 			u8 hi_pri_lvl;
 			u32 bpp;
 			u32 mb;
@@ -1038,7 +1038,7 @@  static int mga_crtc_mode_set(struct drm_crtc *crtc,
 			WREG8(MGAREG_CRTCEXT_DATA, hi_pri_lvl);
 		} else {
 			WREG8(MGAREG_CRTCEXT_INDEX, 0x06);
-			if (mdev->reg_1e24 >= 0x01)
+			if (mdev->unique_rev_id >= 0x01)
 				WREG8(MGAREG_CRTCEXT_DATA, 0x03);
 			else
 				WREG8(MGAREG_CRTCEXT_DATA, 0x04);
@@ -1410,6 +1410,24 @@  static int mga_vga_get_modes(struct drm_connector *connector)
 	return ret;
 }
 
+static uint32_t mga_vga_calculate_mode_bandwidth(struct drm_display_mode * mode,
+                                                       int bits_per_pixel)
+{
+       uint64_t active_area, total_area, pixels_per_second;
+       uint64_t bytes_per_pixel = (bits_per_pixel + 7) / 8;
+
+       if(!mode->htotal || !mode->vtotal || !mode->clock)
+               return 0;
+
+       active_area = mode->hdisplay * mode->vdisplay;
+       total_area = mode->htotal * mode->vtotal;
+       pixels_per_second = active_area * mode->clock * 1000 / total_area;
+
+       return (uint32_t)(pixels_per_second * bytes_per_pixel * 100 / (1024));
+}
+
+#define MODE_BANDWIDTH	MODE_BAD
+
 static int mga_vga_mode_valid(struct drm_connector *connector,
 				 struct drm_display_mode *mode)
 {
@@ -1422,6 +1440,39 @@  static int mga_vga_mode_valid(struct drm_connector *connector,
 	int i = 0;
 
 	/* FIXME: Add bandwidth and g200se limitations */
+	if (IS_G200_SE(mdev)) {
+		if (mdev->unique_rev_id == 0x01) {
+			if (mode->hdisplay > 1600)
+				return MODE_VIRTUAL_X;
+			if (mode->vdisplay > 1200)
+				return MODE_VIRTUAL_Y;
+			if (mga_vga_calculate_mode_bandwidth(mode, bpp) > (24400 * 1024))
+				return MODE_BANDWIDTH;
+		} else if (mdev->unique_rev_id >= 0x02) {
+			if (mode->hdisplay > 1920)
+				return MODE_VIRTUAL_X;
+			if (mode->vdisplay > 1200)
+				return MODE_VIRTUAL_Y;
+			if (mga_vga_calculate_mode_bandwidth(mode, bpp) > (30100 * 1024))
+				return MODE_BANDWIDTH;
+		}
+	} else if (mdev->type == G200_WB) {
+		if (mode->hdisplay > 1280)
+			return MODE_VIRTUAL_X;
+		if (mode->vdisplay > 1024)
+			return MODE_VIRTUAL_Y;
+		if (mga_vga_calculate_mode_bandwidth(mode, bpp > (31877 * 1024)))
+			return MODE_BANDWIDTH;
+	} else if (mdev->type == G200_EV && 
+		(mga_vga_calculate_mode_bandwidth(mode, bpp) > (32700 * 1024))) {
+		return MODE_BANDWIDTH;
+	} else if (mode->type == G200_EH && 
+		(mga_vga_calculate_mode_bandwidth(mode, bpp) > (37500 * 1024))) {
+	 	return MODE_BANDWIDTH;
+	} else if (mode->type == G200_ER && 
+		(mga_vga_calculate_mode_bandwidth(mode, bpp) > (55000 * 1024))) {
+		return MODE_BANDWIDTH;
+	}
 
 	if (mode->crtc_hdisplay > 2048 || mode->crtc_hsync_start > 4096 ||
 	    mode->crtc_hsync_end > 4096 || mode->crtc_htotal > 4096 ||