Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

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>

authored by

Julia Lemire and committed by
Dave Airlie
abbee623 43355503

+70 -5
+2 -1
drivers/gpu/drm/mgag200/mgag200_drv.h
··· 214 214 struct ttm_bo_device bdev; 215 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
+1 -1
drivers/gpu/drm/mgag200/mgag200_main.c
··· 176 176 177 177 /* stash G200 SE model number for later use */ 178 178 if (IS_G200_SE(mdev)) 179 - mdev->reg_1e24 = RREG32(0x1e24); 179 + mdev->unique_rev_id = RREG32(0x1e24); 180 180 181 181 ret = mga_vram_init(mdev); 182 182 if (ret)
+67 -3
drivers/gpu/drm/mgag200/mgag200_mode.c
··· 1008 1008 1009 1009 1010 1010 if (IS_G200_SE(mdev)) { 1011 - if (mdev->reg_1e24 >= 0x02) { 1011 + if (mdev->unique_rev_id >= 0x02) { 1012 1012 u8 hi_pri_lvl; 1013 1013 u32 bpp; 1014 1014 u32 mb; ··· 1038 1038 WREG8(MGAREG_CRTCEXT_DATA, hi_pri_lvl); 1039 1039 } else { 1040 1040 WREG8(MGAREG_CRTCEXT_INDEX, 0x06); 1041 - if (mdev->reg_1e24 >= 0x01) 1041 + if (mdev->unique_rev_id >= 0x01) 1042 1042 WREG8(MGAREG_CRTCEXT_DATA, 0x03); 1043 1043 else 1044 1044 WREG8(MGAREG_CRTCEXT_DATA, 0x04); ··· 1412 1412 return ret; 1413 1413 } 1414 1414 1415 + static 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 + 1415 1441 static int mga_vga_mode_valid(struct drm_connector *connector, 1416 1442 struct drm_display_mode *mode) 1417 1443 { ··· 1449 1423 int bpp = 32; 1450 1424 int i = 0; 1451 1425 1452 - /* FIXME: Add bandwidth and g200se limitations */ 1426 + if (IS_G200_SE(mdev)) { 1427 + if (mdev->unique_rev_id == 0x01) { 1428 + if (mode->hdisplay > 1600) 1429 + return MODE_VIRTUAL_X; 1430 + if (mode->vdisplay > 1200) 1431 + return MODE_VIRTUAL_Y; 1432 + if (mga_vga_calculate_mode_bandwidth(mode, bpp) 1433 + > (24400 * 1024)) 1434 + return MODE_BANDWIDTH; 1435 + } else if (mdev->unique_rev_id >= 0x02) { 1436 + if (mode->hdisplay > 1920) 1437 + return MODE_VIRTUAL_X; 1438 + if (mode->vdisplay > 1200) 1439 + return MODE_VIRTUAL_Y; 1440 + if (mga_vga_calculate_mode_bandwidth(mode, bpp) 1441 + > (30100 * 1024)) 1442 + return MODE_BANDWIDTH; 1443 + } 1444 + } else if (mdev->type == G200_WB) { 1445 + if (mode->hdisplay > 1280) 1446 + return MODE_VIRTUAL_X; 1447 + if (mode->vdisplay > 1024) 1448 + return MODE_VIRTUAL_Y; 1449 + if (mga_vga_calculate_mode_bandwidth(mode, 1450 + bpp > (31877 * 1024))) 1451 + return MODE_BANDWIDTH; 1452 + } else if (mdev->type == G200_EV && 1453 + (mga_vga_calculate_mode_bandwidth(mode, bpp) 1454 + > (32700 * 1024))) { 1455 + return MODE_BANDWIDTH; 1456 + } else if (mode->type == G200_EH && 1457 + (mga_vga_calculate_mode_bandwidth(mode, bpp) 1458 + > (37500 * 1024))) { 1459 + return MODE_BANDWIDTH; 1460 + } else if (mode->type == G200_ER && 1461 + (mga_vga_calculate_mode_bandwidth(mode, 1462 + bpp) > (55000 * 1024))) { 1463 + return MODE_BANDWIDTH; 1464 + } 1453 1465 1454 1466 if (mode->crtc_hdisplay > 2048 || mode->crtc_hsync_start > 4096 || 1455 1467 mode->crtc_hsync_end > 4096 || mode->crtc_htotal > 4096 ||