drm/mgag200: Store maximum resolution and memory bandwidth in device info
authorThomas Zimmermann <tzimmermann@suse.de>
Wed, 1 Jun 2022 11:25:20 +0000 (13:25 +0200)
committerThomas Zimmermann <tzimmermann@suse.de>
Tue, 7 Jun 2022 07:40:04 +0000 (09:40 +0200)
The maximum resolution and memory bandwidth are model-specific limits.
Both are used during display-mode validation. Store the values in struct
mgag200_device_info and simplify the validation code.

v2:
* 'bandwith' -> 'bandwidth' in commit message

Signed-off-by: Thomas Zimmermann <tzimmermann@suse.de>
Reviewed-by: Jocelyn Falempe <jfalempe@redhat.com>
Tested-by: Jocelyn Falempe <jfalempe@redhat.com>
Link: https://patchwork.freedesktop.org/patch/msgid/20220601112522.5774-9-tzimmermann@suse.de
drivers/gpu/drm/mgag200/mgag200_drv.h
drivers/gpu/drm/mgag200/mgag200_g200.c
drivers/gpu/drm/mgag200/mgag200_g200eh.c
drivers/gpu/drm/mgag200/mgag200_g200eh3.c
drivers/gpu/drm/mgag200/mgag200_g200er.c
drivers/gpu/drm/mgag200/mgag200_g200ev.c
drivers/gpu/drm/mgag200/mgag200_g200ew3.c
drivers/gpu/drm/mgag200/mgag200_g200se.c
drivers/gpu/drm/mgag200/mgag200_g200wb.c
drivers/gpu/drm/mgag200/mgag200_mode.c

index b05becb3d4b753e57f3c11ba3ec24356a3192841..f0fb13238f4f757c362d679464902db82f582e2a 100644 (file)
@@ -191,6 +191,15 @@ enum mga_type {
 #define IS_G200_SE(mdev) (mdev->type == G200_SE_A || mdev->type == G200_SE_B)
 
 struct mgag200_device_info {
+       u16 max_hdisplay;
+       u16 max_vdisplay;
+
+       /*
+        * Maximum memory bandwidth (MiB/sec). Setting this to zero disables
+        * the rsp test during mode validation.
+        */
+       unsigned long max_mem_bandwidth;
+
        /*
         * HW does not handle 'startadd' register correctly. Always set
         * it's value to 0.
@@ -198,8 +207,12 @@ struct mgag200_device_info {
        bool bug_no_startadd:1;
 };
 
-#define MGAG200_DEVICE_INFO_INIT(_bug_no_startadd) \
+#define MGAG200_DEVICE_INFO_INIT(_max_hdisplay, _max_vdisplay, _max_mem_bandwidth, \
+                                _bug_no_startadd) \
        { \
+               .max_hdisplay = (_max_hdisplay), \
+               .max_vdisplay = (_max_vdisplay), \
+               .max_mem_bandwidth = (_max_mem_bandwidth), \
                .bug_no_startadd = (_bug_no_startadd), \
        }
 
index 90b33a7352e5a6f4c85a87633fe750b5f75f4bbf..4ec1b18ab170df68a545d4b9e104a4481e3ac3ae 100644 (file)
@@ -34,7 +34,7 @@ static int mgag200_g200_init_pci_options(struct pci_dev *pdev)
  */
 
 static const struct mgag200_device_info mgag200_g200_device_info =
-       MGAG200_DEVICE_INFO_INIT(false);
+       MGAG200_DEVICE_INFO_INIT(2048, 2048, 0, false);
 
 static void mgag200_g200_interpret_bios(struct mgag200_g200_device *g200,
                                        const unsigned char *bios, size_t size)
index 14bec513e441523539222b005a2acaa1954d3dce..a35ba2fdfc0e1fcd4a5dde8fdb1577813973ab32 100644 (file)
@@ -11,7 +11,7 @@
  */
 
 static const struct mgag200_device_info mgag200_g200eh_device_info =
-       MGAG200_DEVICE_INFO_INIT(false);
+       MGAG200_DEVICE_INFO_INIT(2048, 2048, 37500, false);
 
 struct mga_device *mgag200_g200eh_device_create(struct pci_dev *pdev, const struct drm_driver *drv,
                                                enum mga_type type)
index c982533de9e735c46e7027a9adbd267c0d0209e8..649559be1482938404b5067376ad0b67307362c9 100644 (file)
@@ -11,7 +11,7 @@
  */
 
 static const struct mgag200_device_info mgag200_g200eh3_device_info =
-       MGAG200_DEVICE_INFO_INIT(false);
+       MGAG200_DEVICE_INFO_INIT(2048, 2048, 0, false);
 
 struct mga_device *mgag200_g200eh3_device_create(struct pci_dev *pdev,
                                                 const struct drm_driver *drv,
index d84039eef9828383ccbcc179e88c5ad05f87433e..e661fad2f8b2242df415ff0450878b89a13585af 100644 (file)
@@ -11,7 +11,7 @@
  */
 
 static const struct mgag200_device_info mgag200_g200er_device_info =
-       MGAG200_DEVICE_INFO_INIT(false);
+       MGAG200_DEVICE_INFO_INIT(2048, 2048, 55000, false);
 
 struct mga_device *mgag200_g200er_device_create(struct pci_dev *pdev, const struct drm_driver *drv,
                                                enum mga_type type)
index 14a891d4727010cdb09fc7e8389bd29347ff57fa..07a3862d69de23266cb840114d0462b2aabbd93d 100644 (file)
@@ -11,7 +11,7 @@
  */
 
 static const struct mgag200_device_info mgag200_g200ev_device_info =
-       MGAG200_DEVICE_INFO_INIT(false);
+       MGAG200_DEVICE_INFO_INIT(2048, 2048, 32700, false);
 
 struct mga_device *mgag200_g200ev_device_create(struct pci_dev *pdev, const struct drm_driver *drv,
                                                enum mga_type type)
index b09f345ba29b6f7eb29a35022280bc5ea093a446..7f39874350855086c1c941ec76ec9bff249f6f54 100644 (file)
@@ -11,7 +11,7 @@
  */
 
 static const struct mgag200_device_info mgag200_g200ew3_device_info =
-       MGAG200_DEVICE_INFO_INIT(false);
+       MGAG200_DEVICE_INFO_INIT(2048, 2048, 0, false);
 
 static resource_size_t mgag200_g200ew3_device_probe_vram(struct mga_device *mdev)
 {
index 9c0fc57366f2d03a600c755ecb65b5d2c18fdfc7..78120470b7be32dba90683f5fc2d0613d482dafe 100644 (file)
@@ -32,21 +32,37 @@ static int mgag200_g200se_init_pci_options(struct pci_dev *pdev)
  * DRM device
  */
 
-static const struct mgag200_device_info mgag200_g200se_a_device_info =
-       MGAG200_DEVICE_INFO_INIT(true);
+static const struct mgag200_device_info mgag200_g200se_a_01_device_info =
+       MGAG200_DEVICE_INFO_INIT(1600, 1200, 24400, true);
 
-static const struct mgag200_device_info mgag200_g200se_b_device_info =
-       MGAG200_DEVICE_INFO_INIT(false);
+static const struct mgag200_device_info mgag200_g200se_a_02_device_info =
+       MGAG200_DEVICE_INFO_INIT(1920, 1200, 30100, true);
 
-static void mgag200_g200se_init_unique_id(struct mgag200_g200se_device *g200se)
+static const struct mgag200_device_info mgag200_g200se_a_03_device_info =
+       MGAG200_DEVICE_INFO_INIT(2048, 2048, 55000, false);
+
+static const struct mgag200_device_info mgag200_g200se_b_01_device_info =
+       MGAG200_DEVICE_INFO_INIT(1600, 1200, 24400, false);
+
+static const struct mgag200_device_info mgag200_g200se_b_02_device_info =
+       MGAG200_DEVICE_INFO_INIT(1920, 1200, 30100, false);
+
+static const struct mgag200_device_info mgag200_g200se_b_03_device_info =
+       MGAG200_DEVICE_INFO_INIT(2048, 2048, 55000, false);
+
+static int mgag200_g200se_init_unique_rev_id(struct mgag200_g200se_device *g200se)
 {
        struct mga_device *mdev = &g200se->base;
        struct drm_device *dev = &mdev->base;
 
        /* stash G200 SE model number for later use */
        g200se->unique_rev_id = RREG32(0x1e24);
+       if (!g200se->unique_rev_id)
+               return -ENODEV;
 
        drm_dbg(dev, "G200 SE unique revision id is 0x%x\n", g200se->unique_rev_id);
+
+       return 0;
 }
 
 struct mga_device *mgag200_g200se_device_create(struct pci_dev *pdev, const struct drm_driver *drv,
@@ -75,14 +91,26 @@ struct mga_device *mgag200_g200se_device_create(struct pci_dev *pdev, const stru
        if (ret)
                return ERR_PTR(ret);
 
-       mgag200_g200se_init_unique_id(g200se);
+       ret = mgag200_g200se_init_unique_rev_id(g200se);
+       if (ret)
+               return ERR_PTR(ret);
 
        switch (type) {
        case G200_SE_A:
-               info = &mgag200_g200se_a_device_info;
+               if (g200se->unique_rev_id >= 0x03)
+                       info = &mgag200_g200se_a_03_device_info;
+               else if (g200se->unique_rev_id >= 0x02)
+                       info = &mgag200_g200se_a_02_device_info;
+               else
+                       info = &mgag200_g200se_a_01_device_info;
                break;
        case G200_SE_B:
-               info = &mgag200_g200se_b_device_info;
+               if (g200se->unique_rev_id >= 0x03)
+                       info = &mgag200_g200se_b_03_device_info;
+               else if (g200se->unique_rev_id >= 0x02)
+                       info = &mgag200_g200se_b_02_device_info;
+               else
+                       info = &mgag200_g200se_b_01_device_info;
                break;
        default:
                return ERR_PTR(-EINVAL);
index c9bf2176726ea89521da1b61c45c14bf8475b5b2..0943ad2a9999d7890320539de0b11a12a86450fe 100644 (file)
@@ -11,7 +11,7 @@
  */
 
 static const struct mgag200_device_info mgag200_g200wb_device_info =
-       MGAG200_DEVICE_INFO_INIT(false);
+       MGAG200_DEVICE_INFO_INIT(1280, 1024, 31877, false);
 
 struct mga_device *mgag200_g200wb_device_create(struct pci_dev *pdev, const struct drm_driver *drv,
                                                enum mga_type type)
index f5e1a89e0bfeb0924f5d557af3963ab7071d00d8..aa85558faa1ba22ef5f15fb065e59b71539dd65e 100644 (file)
@@ -725,30 +725,17 @@ static enum drm_mode_status
 mgag200_simple_display_pipe_mode_valid(struct drm_simple_display_pipe *pipe,
                                       const struct drm_display_mode *mode)
 {
-       struct drm_device *dev = pipe->crtc.dev;
-       struct mga_device *mdev = to_mga_device(dev);
-       struct mgag200_g200se_device *g200se;
-
-       if (IS_G200_SE(mdev)) {
-               g200se = to_mgag200_g200se_device(dev);
-
-               if (g200se->unique_rev_id == 0x01) {
-                       if (mode->hdisplay > 1600)
-                               return MODE_VIRTUAL_X;
-                       if (mode->vdisplay > 1200)
-                               return MODE_VIRTUAL_Y;
-               } else if (g200se->unique_rev_id == 0x02) {
-                       if (mode->hdisplay > 1920)
-                               return MODE_VIRTUAL_X;
-                       if (mode->vdisplay > 1200)
-                               return MODE_VIRTUAL_Y;
-               }
-       } else if (mdev->type == G200_WB) {
-               if (mode->hdisplay > 1280)
-                       return MODE_VIRTUAL_X;
-               if (mode->vdisplay > 1024)
-                       return MODE_VIRTUAL_Y;
-       }
+       struct mga_device *mdev = to_mga_device(pipe->crtc.dev);
+       const struct mgag200_device_info *info = mdev->info;
+
+       /*
+        * Some devices have additional limits on the size of the
+        * display mode.
+        */
+       if (mode->hdisplay > info->max_hdisplay)
+               return MODE_VIRTUAL_X;
+       if (mode->vdisplay > info->max_vdisplay)
+               return MODE_VIRTUAL_Y;
 
        if ((mode->hdisplay % 8) != 0 || (mode->hsync_start % 8) != 0 ||
            (mode->hsync_end % 8) != 0 || (mode->htotal % 8) != 0) {
@@ -1028,7 +1015,7 @@ static enum drm_mode_status mgag200_mode_config_mode_valid(struct drm_device *de
        static const unsigned int max_bpp = 4; // DRM_FORMAT_XRGB8888
        struct mga_device *mdev = to_mga_device(dev);
        unsigned long fbsize, fbpages, max_fbpages;
-       struct mgag200_g200se_device *g200se;
+       const struct mgag200_device_info *info = mdev->info;
 
        max_fbpages = mdev->vram_available >> PAGE_SHIFT;
 
@@ -1038,30 +1025,14 @@ static enum drm_mode_status mgag200_mode_config_mode_valid(struct drm_device *de
        if (fbpages > max_fbpages)
                return MODE_MEM;
 
-       if (IS_G200_SE(mdev)) {
-               g200se = to_mgag200_g200se_device(dev);
-
-               if (g200se->unique_rev_id == 0x01) {
-                       if (mgag200_calculate_mode_bandwidth(mode, max_bpp * 8) > (24400 * 1024))
-                               return MODE_BAD;
-               } else if (g200se->unique_rev_id == 0x02) {
-                       if (mgag200_calculate_mode_bandwidth(mode, max_bpp * 8) > (30100 * 1024))
-                               return MODE_BAD;
-               } else {
-                       if (mgag200_calculate_mode_bandwidth(mode, max_bpp * 8) > (55000 * 1024))
-                               return MODE_BAD;
-               }
-       } else if (mdev->type == G200_WB) {
-               if (mgag200_calculate_mode_bandwidth(mode, max_bpp * 8) > (31877 * 1024))
-                       return MODE_BAD;
-       } else if (mdev->type == G200_EV) {
-               if (mgag200_calculate_mode_bandwidth(mode, max_bpp * 8) > (32700 * 1024))
-                       return MODE_BAD;
-       } else if (mdev->type == G200_EH) {
-               if (mgag200_calculate_mode_bandwidth(mode, max_bpp * 8) > (37500 * 1024))
-                       return MODE_BAD;
-       } else if (mdev->type == G200_ER) {
-               if (mgag200_calculate_mode_bandwidth(mode, max_bpp * 8) > (55000 * 1024))
+       /*
+        * Test the mode's required memory bandwidth if the device
+        * specifies a maximum. Not all devices do though.
+        */
+       if (info->max_mem_bandwidth) {
+               uint32_t mode_bandwidth = mgag200_calculate_mode_bandwidth(mode, max_bpp * 8);
+
+               if (mode_bandwidth > (info->max_mem_bandwidth * 1024))
                        return MODE_BAD;
        }