aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJulia Lemire <jlemire@matrox.com>2013-06-27 13:38:59 -0400
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>2013-07-25 17:07:41 -0400
commitcd2c367cf10eab382c53bb9f39e01726c6f10253 (patch)
tree60a22507f6f4896eb0c1c40820f7f7752f141f67
parent657c9009705f8d22faefdecac258312c5621ea51 (diff)
drm/mgag200: Added resolution and bandwidth limits for various G200e products.
commit abbee6238775c6633a3779962e9e5b5cb9823749 upstream. 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> Signed-off-by: Dave Airlie <airlied@redhat.com> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
-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 bf29b2f4d68d..988911afcc8b 100644
--- a/drivers/gpu/drm/mgag200/mgag200_drv.h
+++ b/drivers/gpu/drm/mgag200/mgag200_drv.h
@@ -198,7 +198,8 @@ struct mga_device {
198 struct ttm_bo_device bdev; 198 struct ttm_bo_device bdev;
199 } ttm; 199 } ttm;
200 200
201 u32 reg_1e24; /* SE model number */ 201 /* SE model number stored in reg 0x1e24 */
202 u32 unique_rev_id;
202}; 203};
203 204
204 205
diff --git a/drivers/gpu/drm/mgag200/mgag200_main.c b/drivers/gpu/drm/mgag200/mgag200_main.c
index 99059237da38..dafe049fb1ae 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 ee66badc8bb6..99e07b688ea8 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);
@@ -1410,6 +1410,32 @@ static int mga_vga_get_modes(struct drm_connector *connector)
1410 return ret; 1410 return ret;
1411} 1411}
1412 1412
1413static uint32_t mga_vga_calculate_mode_bandwidth(struct drm_display_mode *mode,
1414 int bits_per_pixel)
1415{
1416 uint32_t total_area, divisor;
1417 int64_t active_area, pixels_per_second, bandwidth;
1418 uint64_t bytes_per_pixel = (bits_per_pixel + 7) / 8;
1419
1420 divisor = 1024;
1421
1422 if (!mode->htotal || !mode->vtotal || !mode->clock)
1423 return 0;
1424
1425 active_area = mode->hdisplay * mode->vdisplay;
1426 total_area = mode->htotal * mode->vtotal;
1427
1428 pixels_per_second = active_area * mode->clock * 1000;
1429 do_div(pixels_per_second, total_area);
1430
1431 bandwidth = pixels_per_second * bytes_per_pixel * 100;
1432 do_div(bandwidth, divisor);
1433
1434 return (uint32_t)(bandwidth);
1435}
1436
1437#define MODE_BANDWIDTH MODE_BAD
1438
1413static int mga_vga_mode_valid(struct drm_connector *connector, 1439static int mga_vga_mode_valid(struct drm_connector *connector,
1414 struct drm_display_mode *mode) 1440 struct drm_display_mode *mode)
1415{ 1441{
@@ -1421,7 +1447,45 @@ static int mga_vga_mode_valid(struct drm_connector *connector,
1421 int bpp = 32; 1447 int bpp = 32;
1422 int i = 0; 1448 int i = 0;
1423 1449
1424 /* FIXME: Add bandwidth and g200se limitations */ 1450 if (IS_G200_SE(mdev)) {
1451 if (mdev->unique_rev_id == 0x01) {
1452 if (mode->hdisplay > 1600)
1453 return MODE_VIRTUAL_X;
1454 if (mode->vdisplay > 1200)
1455 return MODE_VIRTUAL_Y;
1456 if (mga_vga_calculate_mode_bandwidth(mode, bpp)
1457 > (24400 * 1024))
1458 return MODE_BANDWIDTH;
1459 } else if (mdev->unique_rev_id >= 0x02) {
1460 if (mode->hdisplay > 1920)
1461 return MODE_VIRTUAL_X;
1462 if (mode->vdisplay > 1200)
1463 return MODE_VIRTUAL_Y;
1464 if (mga_vga_calculate_mode_bandwidth(mode, bpp)
1465 > (30100 * 1024))
1466 return MODE_BANDWIDTH;
1467 }
1468 } else if (mdev->type == G200_WB) {
1469 if (mode->hdisplay > 1280)
1470 return MODE_VIRTUAL_X;
1471 if (mode->vdisplay > 1024)
1472 return MODE_VIRTUAL_Y;
1473 if (mga_vga_calculate_mode_bandwidth(mode,
1474 bpp > (31877 * 1024)))
1475 return MODE_BANDWIDTH;
1476 } else if (mdev->type == G200_EV &&
1477 (mga_vga_calculate_mode_bandwidth(mode, bpp)
1478 > (32700 * 1024))) {
1479 return MODE_BANDWIDTH;
1480 } else if (mode->type == G200_EH &&
1481 (mga_vga_calculate_mode_bandwidth(mode, bpp)
1482 > (37500 * 1024))) {
1483 return MODE_BANDWIDTH;
1484 } else if (mode->type == G200_ER &&
1485 (mga_vga_calculate_mode_bandwidth(mode,
1486 bpp) > (55000 * 1024))) {
1487 return MODE_BANDWIDTH;
1488 }
1425 1489
1426 if (mode->crtc_hdisplay > 2048 || mode->crtc_hsync_start > 4096 || 1490 if (mode->crtc_hdisplay > 2048 || mode->crtc_hsync_start > 4096 ||
1427 mode->crtc_hsync_end > 4096 || mode->crtc_htotal > 4096 || 1491 mode->crtc_hsync_end > 4096 || mode->crtc_htotal > 4096 ||