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 at matrox.com>
---
 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

Reply via email to