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@xxxxxxxxxx> --- drivers/gpu/drm/mgag200/mgag200_drv.h | 41 ++++++++++++------------ drivers/gpu/drm/mgag200/mgag200_main.c | 2 +- drivers/gpu/drm/mgag200/mgag200_mode.c | 55 ++++++++++++++++++++++++++++++-- 3 files changed, 75 insertions(+), 23 deletions(-) diff --git a/drivers/gpu/drm/mgag200/mgag200_drv.h b/drivers/gpu/drm/mgag200/mgag200_drv.h index bf29b2f..710aa29 100644 --- a/drivers/gpu/drm/mgag200/mgag200_drv.h +++ b/drivers/gpu/drm/mgag200/mgag200_drv.h @@ -168,37 +168,38 @@ enum mga_type { #define IS_G200_SE(mdev) (mdev->type == G200_SE_A || mdev->type == G200_SE_B) struct mga_device { - struct drm_device *dev; - unsigned long flags; + struct drm_device *dev; + unsigned long flags; - resource_size_t rmmio_base; - resource_size_t rmmio_size; - void __iomem *rmmio; + resource_size_t rmmio_base; + resource_size_t rmmio_size; + void __iomem *rmmio; - drm_local_map_t *framebuffer; + drm_local_map_t *framebuffer; - struct mga_mc mc; - struct mga_mode_info mode_info; + struct mga_mc mc; + struct mga_mode_info mode_info; - struct mga_fbdev *mfbdev; + struct mga_fbdev *mfbdev; - bool suspended; - int num_crtc; - enum mga_type type; - int has_sdram; - struct drm_display_mode mode; + bool suspended; + int num_crtc; + enum mga_type type; + int has_sdram; + struct drm_display_mode mode; - int bpp_shifts[4]; + int bpp_shifts[4]; - int fb_mtrr; + int fb_mtrr; struct { - struct drm_global_reference mem_global_ref; - struct ttm_bo_global_ref bo_global_ref; - struct ttm_bo_device bdev; + struct drm_global_reference mem_global_ref; + struct ttm_bo_global_ref bo_global_ref; + 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 || -- 1.7.10.4 _______________________________________________ dri-devel mailing list dri-devel@xxxxxxxxxxxxxxxxxxxxx http://lists.freedesktop.org/mailman/listinfo/dri-devel