aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJulia Lemire <jlemire@matrox.com>2013-06-27 13:38:59 -0400
committerDave Airlie <airlied@redhat.com>2013-06-27 18:45:09 -0400
commitabbee6238775c6633a3779962e9e5b5cb9823749 (patch)
tree7a48500ee97bf2f3518315b71a20631ded563ec1
parent433555031e5f4aeb893ea9fe9c3df9df9d566cd4 (diff)
drm/mgag200: Added resolution and bandwidth limits for various G200e products.
At the larger resolutions, the g200e series sometimes struggles with maintaining a proper output. Problems like flickering or black bands appearing on screen can occur. In order to avoid this, limitations regarding resolutions and bandwidth have been added for the different variations of the g200e series. This code was ported from the old xorg mga driver. Signed-off-by: Julia Lemire <jlemire@matrox.com> Cc: stable@vger.kernel.org Signed-off-by: Dave Airlie <airlied@redhat.com>
-rw-r--r--drivers/gpu/drm/mgag200/mgag200_drv.h3
-rw-r--r--drivers/gpu/drm/mgag200/mgag200_main.c2
-rw-r--r--drivers/gpu/drm/mgag200/mgag200_mode.c70
3 files changed, 70 insertions, 5 deletions
diff --git a/drivers/gpu/drm/mgag200/mgag200_drv.h b/drivers/gpu/drm/mgag200/mgag200_drv.h
index 364a05a15eb1..d9737ef2d9a2 100644
--- a/drivers/gpu/drm/mgag200/mgag200_drv.h
+++ b/drivers/gpu/drm/mgag200/mgag200_drv.h
@@ -214,7 +214,8 @@ struct mga_device {
214 struct ttm_bo_device bdev; 214 struct ttm_bo_device bdev;
215 } ttm; 215 } ttm;
216 216
217 u32 reg_1e24; /* SE model number */ 217 /* SE model number stored in reg 0x1e24 */
218 u32 unique_rev_id;
218}; 219};
219 220
220 221
diff --git a/drivers/gpu/drm/mgag200/mgag200_main.c b/drivers/gpu/drm/mgag200/mgag200_main.c
index 6d6b598ff791..9fa5685baee0 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,
176 176
177 /* stash G200 SE model number for later use */ 177 /* stash G200 SE model number for later use */
178 if (IS_G200_SE(mdev)) 178 if (IS_G200_SE(mdev))
179 mdev->reg_1e24 = RREG32(0x1e24); 179 mdev->unique_rev_id = RREG32(0x1e24);
180 180
181 ret = mga_vram_init(mdev); 181 ret = mga_vram_init(mdev);
182 if (ret) 182 if (ret)
diff --git a/drivers/gpu/drm/mgag200/mgag200_mode.c b/drivers/gpu/drm/mgag200/mgag200_mode.c
index 5b1a9e73fe58..251784aa2225 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,
1008 1008
1009 1009
1010 if (IS_G200_SE(mdev)) { 1010 if (IS_G200_SE(mdev)) {
1011 if (mdev->reg_1e24 >= 0x02) { 1011 if (mdev->unique_rev_id >= 0x02) {
1012 u8 hi_pri_lvl; 1012 u8 hi_pri_lvl;
1013 u32 bpp; 1013 u32 bpp;
1014 u32 mb; 1014 u32 mb;
@@ -1038,7 +1038,7 @@ static int mga_crtc_mode_set(struct drm_crtc *crtc,
1038 WREG8(MGAREG_CRTCEXT_DATA, hi_pri_lvl); 1038 WREG8(MGAREG_CRTCEXT_DATA, hi_pri_lvl);
1039 } else { 1039 } else {
1040 WREG8(MGAREG_CRTCEXT_INDEX, 0x06); 1040 WREG8(MGAREG_CRTCEXT_INDEX, 0x06);
1041 if (mdev->reg_1e24 >= 0x01) 1041 if (mdev->unique_rev_id >= 0x01)
1042 WREG8(MGAREG_CRTCEXT_DATA, 0x03); 1042 WREG8(MGAREG_CRTCEXT_DATA, 0x03);
1043 else 1043 else
1044 WREG8(MGAREG_CRTCEXT_DATA, 0x04); 1044 WREG8(MGAREG_CRTCEXT_DATA, 0x04);
@@ -1412,6 +1412,32 @@ static int mga_vga_get_modes(struct drm_connector *connector)
1412 return ret; 1412 return ret;
1413} 1413}
1414 1414
1415static uint32_t mga_vga_calculate_mode_bandwidth(struct drm_display_mode *mode,
1416 int bits_per_pixel)
1417{
1418 uint32_t total_area, divisor;
1419 int64_t active_area, pixels_per_second, bandwidth;
1420 uint64_t bytes_per_pixel = (bits_per_pixel + 7) / 8;
1421
1422 divisor = 1024;
1423
1424 if (!mode->htotal || !mode->vtotal || !mode->clock)
1425 return 0;
1426
1427 active_area = mode->hdisplay * mode->vdisplay;
1428 total_area = mode->htotal * mode->vtotal;
1429
1430 pixels_per_second = active_area * mode->clock * 1000;
1431 do_div(pixels_per_second, total_area);
1432
1433 bandwidth = pixels_per_second * bytes_per_pixel * 100;
1434 do_div(bandwidth, divisor);
1435
1436 return (uint32_t)(bandwidth);
1437}
1438
1439#define MODE_BANDWIDTH MODE_BAD
1440
1415static int mga_vga_mode_valid(struct drm_connector *connector, 1441static int mga_vga_mode_valid(struct drm_connector *connector,
1416 struct drm_display_mode *mode) 1442 struct drm_display_mode *mode)
1417{ 1443{
@@ -1423,7 +1449,45 @@ static int mga_vga_mode_valid(struct drm_connector *connector,
1423 int bpp = 32; 1449 int bpp = 32;
1424 int i = 0; 1450 int i = 0;
1425 1451
1426 /* FIXME: Add bandwidth and g200se limitations */ 1452 if (IS_G200_SE(mdev)) {
1453 if (mdev->unique_rev_id == 0x01) {
1454 if (mode->hdisplay > 1600)
1455 return MODE_VIRTUAL_X;
1456 if (mode->vdisplay > 1200)
1457 return MODE_VIRTUAL_Y;
1458 if (mga_vga_calculate_mode_bandwidth(mode, bpp)
1459 > (24400 * 1024))
1460 return MODE_BANDWIDTH;
1461 } else if (mdev->unique_rev_id >= 0x02) {
1462 if (mode->hdisplay > 1920)
1463 return MODE_VIRTUAL_X;
1464 if (mode->vdisplay > 1200)
1465 return MODE_VIRTUAL_Y;
1466 if (mga_vga_calculate_mode_bandwidth(mode, bpp)
1467 > (30100 * 1024))
1468 return MODE_BANDWIDTH;
1469 }
1470 } else if (mdev->type == G200_WB) {
1471 if (mode->hdisplay > 1280)
1472 return MODE_VIRTUAL_X;
1473 if (mode->vdisplay > 1024)
1474 return MODE_VIRTUAL_Y;
1475 if (mga_vga_calculate_mode_bandwidth(mode,
1476 bpp > (31877 * 1024)))
1477 return MODE_BANDWIDTH;
1478 } else if (mdev->type == G200_EV &&
1479 (mga_vga_calculate_mode_bandwidth(mode, bpp)
1480 > (32700 * 1024))) {
1481 return MODE_BANDWIDTH;
1482 } else if (mode->type == G200_EH &&
1483 (mga_vga_calculate_mode_bandwidth(mode, bpp)
1484 > (37500 * 1024))) {
1485 return MODE_BANDWIDTH;
1486 } else if (mode->type == G200_ER &&
1487 (mga_vga_calculate_mode_bandwidth(mode,
1488 bpp) > (55000 * 1024))) {
1489 return MODE_BANDWIDTH;
1490 }
1427 1491
1428 if (mode->crtc_hdisplay > 2048 || mode->crtc_hsync_start > 4096 || 1492 if (mode->crtc_hdisplay > 2048 || mode->crtc_hsync_start > 4096 ||
1429 mode->crtc_hsync_end > 4096 || mode->crtc_htotal > 4096 || 1493 mode->crtc_hsync_end > 4096 || mode->crtc_htotal > 4096 ||