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

drm/mgag200: Store maximum resolution and memory bandwidth in device info

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

+75 -63
+14 -1
drivers/gpu/drm/mgag200/mgag200_drv.h
··· 191 191 #define IS_G200_SE(mdev) (mdev->type == G200_SE_A || mdev->type == G200_SE_B) 192 192 193 193 struct mgag200_device_info { 194 + u16 max_hdisplay; 195 + u16 max_vdisplay; 196 + 197 + /* 198 + * Maximum memory bandwidth (MiB/sec). Setting this to zero disables 199 + * the rsp test during mode validation. 200 + */ 201 + unsigned long max_mem_bandwidth; 202 + 194 203 /* 195 204 * HW does not handle 'startadd' register correctly. Always set 196 205 * it's value to 0. ··· 207 198 bool bug_no_startadd:1; 208 199 }; 209 200 210 - #define MGAG200_DEVICE_INFO_INIT(_bug_no_startadd) \ 201 + #define MGAG200_DEVICE_INFO_INIT(_max_hdisplay, _max_vdisplay, _max_mem_bandwidth, \ 202 + _bug_no_startadd) \ 211 203 { \ 204 + .max_hdisplay = (_max_hdisplay), \ 205 + .max_vdisplay = (_max_vdisplay), \ 206 + .max_mem_bandwidth = (_max_mem_bandwidth), \ 212 207 .bug_no_startadd = (_bug_no_startadd), \ 213 208 } 214 209
+1 -1
drivers/gpu/drm/mgag200/mgag200_g200.c
··· 34 34 */ 35 35 36 36 static const struct mgag200_device_info mgag200_g200_device_info = 37 - MGAG200_DEVICE_INFO_INIT(false); 37 + MGAG200_DEVICE_INFO_INIT(2048, 2048, 0, false); 38 38 39 39 static void mgag200_g200_interpret_bios(struct mgag200_g200_device *g200, 40 40 const unsigned char *bios, size_t size)
+1 -1
drivers/gpu/drm/mgag200/mgag200_g200eh.c
··· 11 11 */ 12 12 13 13 static const struct mgag200_device_info mgag200_g200eh_device_info = 14 - MGAG200_DEVICE_INFO_INIT(false); 14 + MGAG200_DEVICE_INFO_INIT(2048, 2048, 37500, false); 15 15 16 16 struct mga_device *mgag200_g200eh_device_create(struct pci_dev *pdev, const struct drm_driver *drv, 17 17 enum mga_type type)
+1 -1
drivers/gpu/drm/mgag200/mgag200_g200eh3.c
··· 11 11 */ 12 12 13 13 static const struct mgag200_device_info mgag200_g200eh3_device_info = 14 - MGAG200_DEVICE_INFO_INIT(false); 14 + MGAG200_DEVICE_INFO_INIT(2048, 2048, 0, false); 15 15 16 16 struct mga_device *mgag200_g200eh3_device_create(struct pci_dev *pdev, 17 17 const struct drm_driver *drv,
+1 -1
drivers/gpu/drm/mgag200/mgag200_g200er.c
··· 11 11 */ 12 12 13 13 static const struct mgag200_device_info mgag200_g200er_device_info = 14 - MGAG200_DEVICE_INFO_INIT(false); 14 + MGAG200_DEVICE_INFO_INIT(2048, 2048, 55000, false); 15 15 16 16 struct mga_device *mgag200_g200er_device_create(struct pci_dev *pdev, const struct drm_driver *drv, 17 17 enum mga_type type)
+1 -1
drivers/gpu/drm/mgag200/mgag200_g200ev.c
··· 11 11 */ 12 12 13 13 static const struct mgag200_device_info mgag200_g200ev_device_info = 14 - MGAG200_DEVICE_INFO_INIT(false); 14 + MGAG200_DEVICE_INFO_INIT(2048, 2048, 32700, false); 15 15 16 16 struct mga_device *mgag200_g200ev_device_create(struct pci_dev *pdev, const struct drm_driver *drv, 17 17 enum mga_type type)
+1 -1
drivers/gpu/drm/mgag200/mgag200_g200ew3.c
··· 11 11 */ 12 12 13 13 static const struct mgag200_device_info mgag200_g200ew3_device_info = 14 - MGAG200_DEVICE_INFO_INIT(false); 14 + MGAG200_DEVICE_INFO_INIT(2048, 2048, 0, false); 15 15 16 16 static resource_size_t mgag200_g200ew3_device_probe_vram(struct mga_device *mdev) 17 17 {
+36 -8
drivers/gpu/drm/mgag200/mgag200_g200se.c
··· 32 32 * DRM device 33 33 */ 34 34 35 - static const struct mgag200_device_info mgag200_g200se_a_device_info = 36 - MGAG200_DEVICE_INFO_INIT(true); 35 + static const struct mgag200_device_info mgag200_g200se_a_01_device_info = 36 + MGAG200_DEVICE_INFO_INIT(1600, 1200, 24400, true); 37 37 38 - static const struct mgag200_device_info mgag200_g200se_b_device_info = 39 - MGAG200_DEVICE_INFO_INIT(false); 38 + static const struct mgag200_device_info mgag200_g200se_a_02_device_info = 39 + MGAG200_DEVICE_INFO_INIT(1920, 1200, 30100, true); 40 40 41 - static void mgag200_g200se_init_unique_id(struct mgag200_g200se_device *g200se) 41 + static const struct mgag200_device_info mgag200_g200se_a_03_device_info = 42 + MGAG200_DEVICE_INFO_INIT(2048, 2048, 55000, false); 43 + 44 + static const struct mgag200_device_info mgag200_g200se_b_01_device_info = 45 + MGAG200_DEVICE_INFO_INIT(1600, 1200, 24400, false); 46 + 47 + static const struct mgag200_device_info mgag200_g200se_b_02_device_info = 48 + MGAG200_DEVICE_INFO_INIT(1920, 1200, 30100, false); 49 + 50 + static const struct mgag200_device_info mgag200_g200se_b_03_device_info = 51 + MGAG200_DEVICE_INFO_INIT(2048, 2048, 55000, false); 52 + 53 + static int mgag200_g200se_init_unique_rev_id(struct mgag200_g200se_device *g200se) 42 54 { 43 55 struct mga_device *mdev = &g200se->base; 44 56 struct drm_device *dev = &mdev->base; 45 57 46 58 /* stash G200 SE model number for later use */ 47 59 g200se->unique_rev_id = RREG32(0x1e24); 60 + if (!g200se->unique_rev_id) 61 + return -ENODEV; 48 62 49 63 drm_dbg(dev, "G200 SE unique revision id is 0x%x\n", g200se->unique_rev_id); 64 + 65 + return 0; 50 66 } 51 67 52 68 struct mga_device *mgag200_g200se_device_create(struct pci_dev *pdev, const struct drm_driver *drv, ··· 91 75 if (ret) 92 76 return ERR_PTR(ret); 93 77 94 - mgag200_g200se_init_unique_id(g200se); 78 + ret = mgag200_g200se_init_unique_rev_id(g200se); 79 + if (ret) 80 + return ERR_PTR(ret); 95 81 96 82 switch (type) { 97 83 case G200_SE_A: 98 - info = &mgag200_g200se_a_device_info; 84 + if (g200se->unique_rev_id >= 0x03) 85 + info = &mgag200_g200se_a_03_device_info; 86 + else if (g200se->unique_rev_id >= 0x02) 87 + info = &mgag200_g200se_a_02_device_info; 88 + else 89 + info = &mgag200_g200se_a_01_device_info; 99 90 break; 100 91 case G200_SE_B: 101 - info = &mgag200_g200se_b_device_info; 92 + if (g200se->unique_rev_id >= 0x03) 93 + info = &mgag200_g200se_b_03_device_info; 94 + else if (g200se->unique_rev_id >= 0x02) 95 + info = &mgag200_g200se_b_02_device_info; 96 + else 97 + info = &mgag200_g200se_b_01_device_info; 102 98 break; 103 99 default: 104 100 return ERR_PTR(-EINVAL);
+1 -1
drivers/gpu/drm/mgag200/mgag200_g200wb.c
··· 11 11 */ 12 12 13 13 static const struct mgag200_device_info mgag200_g200wb_device_info = 14 - MGAG200_DEVICE_INFO_INIT(false); 14 + MGAG200_DEVICE_INFO_INIT(1280, 1024, 31877, false); 15 15 16 16 struct mga_device *mgag200_g200wb_device_create(struct pci_dev *pdev, const struct drm_driver *drv, 17 17 enum mga_type type)
+18 -47
drivers/gpu/drm/mgag200/mgag200_mode.c
··· 725 725 mgag200_simple_display_pipe_mode_valid(struct drm_simple_display_pipe *pipe, 726 726 const struct drm_display_mode *mode) 727 727 { 728 - struct drm_device *dev = pipe->crtc.dev; 729 - struct mga_device *mdev = to_mga_device(dev); 730 - struct mgag200_g200se_device *g200se; 728 + struct mga_device *mdev = to_mga_device(pipe->crtc.dev); 729 + const struct mgag200_device_info *info = mdev->info; 731 730 732 - if (IS_G200_SE(mdev)) { 733 - g200se = to_mgag200_g200se_device(dev); 734 - 735 - if (g200se->unique_rev_id == 0x01) { 736 - if (mode->hdisplay > 1600) 737 - return MODE_VIRTUAL_X; 738 - if (mode->vdisplay > 1200) 739 - return MODE_VIRTUAL_Y; 740 - } else if (g200se->unique_rev_id == 0x02) { 741 - if (mode->hdisplay > 1920) 742 - return MODE_VIRTUAL_X; 743 - if (mode->vdisplay > 1200) 744 - return MODE_VIRTUAL_Y; 745 - } 746 - } else if (mdev->type == G200_WB) { 747 - if (mode->hdisplay > 1280) 748 - return MODE_VIRTUAL_X; 749 - if (mode->vdisplay > 1024) 750 - return MODE_VIRTUAL_Y; 751 - } 731 + /* 732 + * Some devices have additional limits on the size of the 733 + * display mode. 734 + */ 735 + if (mode->hdisplay > info->max_hdisplay) 736 + return MODE_VIRTUAL_X; 737 + if (mode->vdisplay > info->max_vdisplay) 738 + return MODE_VIRTUAL_Y; 752 739 753 740 if ((mode->hdisplay % 8) != 0 || (mode->hsync_start % 8) != 0 || 754 741 (mode->hsync_end % 8) != 0 || (mode->htotal % 8) != 0) { ··· 1015 1028 static const unsigned int max_bpp = 4; // DRM_FORMAT_XRGB8888 1016 1029 struct mga_device *mdev = to_mga_device(dev); 1017 1030 unsigned long fbsize, fbpages, max_fbpages; 1018 - struct mgag200_g200se_device *g200se; 1031 + const struct mgag200_device_info *info = mdev->info; 1019 1032 1020 1033 max_fbpages = mdev->vram_available >> PAGE_SHIFT; 1021 1034 ··· 1025 1038 if (fbpages > max_fbpages) 1026 1039 return MODE_MEM; 1027 1040 1028 - if (IS_G200_SE(mdev)) { 1029 - g200se = to_mgag200_g200se_device(dev); 1041 + /* 1042 + * Test the mode's required memory bandwidth if the device 1043 + * specifies a maximum. Not all devices do though. 1044 + */ 1045 + if (info->max_mem_bandwidth) { 1046 + uint32_t mode_bandwidth = mgag200_calculate_mode_bandwidth(mode, max_bpp * 8); 1030 1047 1031 - if (g200se->unique_rev_id == 0x01) { 1032 - if (mgag200_calculate_mode_bandwidth(mode, max_bpp * 8) > (24400 * 1024)) 1033 - return MODE_BAD; 1034 - } else if (g200se->unique_rev_id == 0x02) { 1035 - if (mgag200_calculate_mode_bandwidth(mode, max_bpp * 8) > (30100 * 1024)) 1036 - return MODE_BAD; 1037 - } else { 1038 - if (mgag200_calculate_mode_bandwidth(mode, max_bpp * 8) > (55000 * 1024)) 1039 - return MODE_BAD; 1040 - } 1041 - } else if (mdev->type == G200_WB) { 1042 - if (mgag200_calculate_mode_bandwidth(mode, max_bpp * 8) > (31877 * 1024)) 1043 - return MODE_BAD; 1044 - } else if (mdev->type == G200_EV) { 1045 - if (mgag200_calculate_mode_bandwidth(mode, max_bpp * 8) > (32700 * 1024)) 1046 - return MODE_BAD; 1047 - } else if (mdev->type == G200_EH) { 1048 - if (mgag200_calculate_mode_bandwidth(mode, max_bpp * 8) > (37500 * 1024)) 1049 - return MODE_BAD; 1050 - } else if (mdev->type == G200_ER) { 1051 - if (mgag200_calculate_mode_bandwidth(mode, max_bpp * 8) > (55000 * 1024)) 1048 + if (mode_bandwidth > (info->max_mem_bandwidth * 1024)) 1052 1049 return MODE_BAD; 1053 1050 } 1054 1051