Commit abbee623 authored by Julia Lemire's avatar Julia Lemire Committed by Dave Airlie

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: default avatarJulia Lemire <jlemire@matrox.com>
Cc: stable@vger.kernel.org
Signed-off-by: default avatarDave Airlie <airlied@redhat.com>
parent 43355503
...@@ -214,7 +214,8 @@ struct mga_device { ...@@ -214,7 +214,8 @@ struct mga_device {
struct ttm_bo_device bdev; struct ttm_bo_device bdev;
} ttm; } ttm;
u32 reg_1e24; /* SE model number */ /* SE model number stored in reg 0x1e24 */
u32 unique_rev_id;
}; };
......
...@@ -176,7 +176,7 @@ static int mgag200_device_init(struct drm_device *dev, ...@@ -176,7 +176,7 @@ static int mgag200_device_init(struct drm_device *dev,
/* stash G200 SE model number for later use */ /* stash G200 SE model number for later use */
if (IS_G200_SE(mdev)) if (IS_G200_SE(mdev))
mdev->reg_1e24 = RREG32(0x1e24); mdev->unique_rev_id = RREG32(0x1e24);
ret = mga_vram_init(mdev); ret = mga_vram_init(mdev);
if (ret) if (ret)
......
...@@ -1008,7 +1008,7 @@ static int mga_crtc_mode_set(struct drm_crtc *crtc, ...@@ -1008,7 +1008,7 @@ static int mga_crtc_mode_set(struct drm_crtc *crtc,
if (IS_G200_SE(mdev)) { if (IS_G200_SE(mdev)) {
if (mdev->reg_1e24 >= 0x02) { if (mdev->unique_rev_id >= 0x02) {
u8 hi_pri_lvl; u8 hi_pri_lvl;
u32 bpp; u32 bpp;
u32 mb; u32 mb;
...@@ -1038,7 +1038,7 @@ static int mga_crtc_mode_set(struct drm_crtc *crtc, ...@@ -1038,7 +1038,7 @@ static int mga_crtc_mode_set(struct drm_crtc *crtc,
WREG8(MGAREG_CRTCEXT_DATA, hi_pri_lvl); WREG8(MGAREG_CRTCEXT_DATA, hi_pri_lvl);
} else { } else {
WREG8(MGAREG_CRTCEXT_INDEX, 0x06); WREG8(MGAREG_CRTCEXT_INDEX, 0x06);
if (mdev->reg_1e24 >= 0x01) if (mdev->unique_rev_id >= 0x01)
WREG8(MGAREG_CRTCEXT_DATA, 0x03); WREG8(MGAREG_CRTCEXT_DATA, 0x03);
else else
WREG8(MGAREG_CRTCEXT_DATA, 0x04); WREG8(MGAREG_CRTCEXT_DATA, 0x04);
...@@ -1412,6 +1412,32 @@ static int mga_vga_get_modes(struct drm_connector *connector) ...@@ -1412,6 +1412,32 @@ static int mga_vga_get_modes(struct drm_connector *connector)
return ret; return ret;
} }
static uint32_t mga_vga_calculate_mode_bandwidth(struct drm_display_mode *mode,
int bits_per_pixel)
{
uint32_t total_area, divisor;
int64_t active_area, pixels_per_second, bandwidth;
uint64_t bytes_per_pixel = (bits_per_pixel + 7) / 8;
divisor = 1024;
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;
do_div(pixels_per_second, total_area);
bandwidth = pixels_per_second * bytes_per_pixel * 100;
do_div(bandwidth, divisor);
return (uint32_t)(bandwidth);
}
#define MODE_BANDWIDTH MODE_BAD
static int mga_vga_mode_valid(struct drm_connector *connector, static int mga_vga_mode_valid(struct drm_connector *connector,
struct drm_display_mode *mode) struct drm_display_mode *mode)
{ {
...@@ -1423,7 +1449,45 @@ static int mga_vga_mode_valid(struct drm_connector *connector, ...@@ -1423,7 +1449,45 @@ static int mga_vga_mode_valid(struct drm_connector *connector,
int bpp = 32; int bpp = 32;
int i = 0; 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 || if (mode->crtc_hdisplay > 2048 || mode->crtc_hsync_start > 4096 ||
mode->crtc_hsync_end > 4096 || mode->crtc_htotal > 4096 || mode->crtc_hsync_end > 4096 || mode->crtc_htotal > 4096 ||
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment