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

Configure Feed

Select the types of activity you want to include in your feed.

drm/vmwgfx: Refactor drm connector probing for display modes

Implement drm_connector_helper_funcs.mode_valid and .get_modes,
replacing custom drm_connector_funcs.fill_modes code with
drm_helper_probe_single_connector_modes; for STDU, LDU & SOU
display units.

Signed-off-by: Martin Krastev <martin.krastev@broadcom.com>
Reviewed-by: Zack Rusin <zack.rusin@broadcom.com>
Signed-off-by: Zack Rusin <zack.rusin@broadcom.com>
Link: https://patchwork.freedesktop.org/patch/msgid/20240126200804.732454-2-zack.rusin@broadcom.com

authored by

Martin Krastev and committed by
Zack Rusin
935f7950 4db102dc

+101 -191
+89 -183
drivers/gpu/drm/vmwgfx/vmwgfx_kms.c
··· 35 35 #include <drm/drm_fourcc.h> 36 36 #include <drm/drm_rect.h> 37 37 #include <drm/drm_sysfs.h> 38 + #include <drm/drm_edid.h> 38 39 39 40 void vmw_du_cleanup(struct vmw_display_unit *du) 40 41 { ··· 2283 2282 connector_status_connected : connector_status_disconnected); 2284 2283 } 2285 2284 2286 - static struct drm_display_mode vmw_kms_connector_builtin[] = { 2287 - /* 640x480@60Hz */ 2288 - { DRM_MODE("640x480", DRM_MODE_TYPE_DRIVER, 25175, 640, 656, 2289 - 752, 800, 0, 480, 489, 492, 525, 0, 2290 - DRM_MODE_FLAG_NHSYNC | DRM_MODE_FLAG_NVSYNC) }, 2291 - /* 800x600@60Hz */ 2292 - { DRM_MODE("800x600", DRM_MODE_TYPE_DRIVER, 40000, 800, 840, 2293 - 968, 1056, 0, 600, 601, 605, 628, 0, 2294 - DRM_MODE_FLAG_PHSYNC | DRM_MODE_FLAG_PVSYNC) }, 2295 - /* 1024x768@60Hz */ 2296 - { DRM_MODE("1024x768", DRM_MODE_TYPE_DRIVER, 65000, 1024, 1048, 2297 - 1184, 1344, 0, 768, 771, 777, 806, 0, 2298 - DRM_MODE_FLAG_NHSYNC | DRM_MODE_FLAG_NVSYNC) }, 2299 - /* 1152x864@75Hz */ 2300 - { DRM_MODE("1152x864", DRM_MODE_TYPE_DRIVER, 108000, 1152, 1216, 2301 - 1344, 1600, 0, 864, 865, 868, 900, 0, 2302 - DRM_MODE_FLAG_PHSYNC | DRM_MODE_FLAG_PVSYNC) }, 2303 - /* 1280x720@60Hz */ 2304 - { DRM_MODE("1280x720", DRM_MODE_TYPE_DRIVER, 74500, 1280, 1344, 2305 - 1472, 1664, 0, 720, 723, 728, 748, 0, 2306 - DRM_MODE_FLAG_NHSYNC | DRM_MODE_FLAG_PVSYNC) }, 2307 - /* 1280x768@60Hz */ 2308 - { DRM_MODE("1280x768", DRM_MODE_TYPE_DRIVER, 79500, 1280, 1344, 2309 - 1472, 1664, 0, 768, 771, 778, 798, 0, 2310 - DRM_MODE_FLAG_NHSYNC | DRM_MODE_FLAG_PVSYNC) }, 2311 - /* 1280x800@60Hz */ 2312 - { DRM_MODE("1280x800", DRM_MODE_TYPE_DRIVER, 83500, 1280, 1352, 2313 - 1480, 1680, 0, 800, 803, 809, 831, 0, 2314 - DRM_MODE_FLAG_PHSYNC | DRM_MODE_FLAG_NVSYNC) }, 2315 - /* 1280x960@60Hz */ 2316 - { DRM_MODE("1280x960", DRM_MODE_TYPE_DRIVER, 108000, 1280, 1376, 2317 - 1488, 1800, 0, 960, 961, 964, 1000, 0, 2318 - DRM_MODE_FLAG_PHSYNC | DRM_MODE_FLAG_PVSYNC) }, 2319 - /* 1280x1024@60Hz */ 2320 - { DRM_MODE("1280x1024", DRM_MODE_TYPE_DRIVER, 108000, 1280, 1328, 2321 - 1440, 1688, 0, 1024, 1025, 1028, 1066, 0, 2322 - DRM_MODE_FLAG_PHSYNC | DRM_MODE_FLAG_PVSYNC) }, 2323 - /* 1360x768@60Hz */ 2324 - { DRM_MODE("1360x768", DRM_MODE_TYPE_DRIVER, 85500, 1360, 1424, 2325 - 1536, 1792, 0, 768, 771, 777, 795, 0, 2326 - DRM_MODE_FLAG_PHSYNC | DRM_MODE_FLAG_PVSYNC) }, 2327 - /* 1440x1050@60Hz */ 2328 - { DRM_MODE("1400x1050", DRM_MODE_TYPE_DRIVER, 121750, 1400, 1488, 2329 - 1632, 1864, 0, 1050, 1053, 1057, 1089, 0, 2330 - DRM_MODE_FLAG_NHSYNC | DRM_MODE_FLAG_PVSYNC) }, 2331 - /* 1440x900@60Hz */ 2332 - { DRM_MODE("1440x900", DRM_MODE_TYPE_DRIVER, 106500, 1440, 1520, 2333 - 1672, 1904, 0, 900, 903, 909, 934, 0, 2334 - DRM_MODE_FLAG_NHSYNC | DRM_MODE_FLAG_PVSYNC) }, 2335 - /* 1600x1200@60Hz */ 2336 - { DRM_MODE("1600x1200", DRM_MODE_TYPE_DRIVER, 162000, 1600, 1664, 2337 - 1856, 2160, 0, 1200, 1201, 1204, 1250, 0, 2338 - DRM_MODE_FLAG_PHSYNC | DRM_MODE_FLAG_PVSYNC) }, 2339 - /* 1680x1050@60Hz */ 2340 - { DRM_MODE("1680x1050", DRM_MODE_TYPE_DRIVER, 146250, 1680, 1784, 2341 - 1960, 2240, 0, 1050, 1053, 1059, 1089, 0, 2342 - DRM_MODE_FLAG_NHSYNC | DRM_MODE_FLAG_PVSYNC) }, 2343 - /* 1792x1344@60Hz */ 2344 - { DRM_MODE("1792x1344", DRM_MODE_TYPE_DRIVER, 204750, 1792, 1920, 2345 - 2120, 2448, 0, 1344, 1345, 1348, 1394, 0, 2346 - DRM_MODE_FLAG_NHSYNC | DRM_MODE_FLAG_PVSYNC) }, 2347 - /* 1853x1392@60Hz */ 2348 - { DRM_MODE("1856x1392", DRM_MODE_TYPE_DRIVER, 218250, 1856, 1952, 2349 - 2176, 2528, 0, 1392, 1393, 1396, 1439, 0, 2350 - DRM_MODE_FLAG_NHSYNC | DRM_MODE_FLAG_PVSYNC) }, 2351 - /* 1920x1080@60Hz */ 2352 - { DRM_MODE("1920x1080", DRM_MODE_TYPE_DRIVER, 173000, 1920, 2048, 2353 - 2248, 2576, 0, 1080, 1083, 1088, 1120, 0, 2354 - DRM_MODE_FLAG_NHSYNC | DRM_MODE_FLAG_PVSYNC) }, 2355 - /* 1920x1200@60Hz */ 2356 - { DRM_MODE("1920x1200", DRM_MODE_TYPE_DRIVER, 193250, 1920, 2056, 2357 - 2256, 2592, 0, 1200, 1203, 1209, 1245, 0, 2358 - DRM_MODE_FLAG_NHSYNC | DRM_MODE_FLAG_PVSYNC) }, 2359 - /* 1920x1440@60Hz */ 2360 - { DRM_MODE("1920x1440", DRM_MODE_TYPE_DRIVER, 234000, 1920, 2048, 2361 - 2256, 2600, 0, 1440, 1441, 1444, 1500, 0, 2362 - DRM_MODE_FLAG_NHSYNC | DRM_MODE_FLAG_PVSYNC) }, 2363 - /* 2560x1440@60Hz */ 2364 - { DRM_MODE("2560x1440", DRM_MODE_TYPE_DRIVER, 241500, 2560, 2608, 2365 - 2640, 2720, 0, 1440, 1443, 1448, 1481, 0, 2366 - DRM_MODE_FLAG_PHSYNC | DRM_MODE_FLAG_NVSYNC) }, 2367 - /* 2560x1600@60Hz */ 2368 - { DRM_MODE("2560x1600", DRM_MODE_TYPE_DRIVER, 348500, 2560, 2752, 2369 - 3032, 3504, 0, 1600, 1603, 1609, 1658, 0, 2370 - DRM_MODE_FLAG_NHSYNC | DRM_MODE_FLAG_PVSYNC) }, 2371 - /* 2880x1800@60Hz */ 2372 - { DRM_MODE("2880x1800", DRM_MODE_TYPE_DRIVER, 337500, 2880, 2928, 2373 - 2960, 3040, 0, 1800, 1803, 1809, 1852, 0, 2374 - DRM_MODE_FLAG_PHSYNC | DRM_MODE_FLAG_NVSYNC) }, 2375 - /* 3840x2160@60Hz */ 2376 - { DRM_MODE("3840x2160", DRM_MODE_TYPE_DRIVER, 533000, 3840, 3888, 2377 - 3920, 4000, 0, 2160, 2163, 2168, 2222, 0, 2378 - DRM_MODE_FLAG_PHSYNC | DRM_MODE_FLAG_NVSYNC) }, 2379 - /* 3840x2400@60Hz */ 2380 - { DRM_MODE("3840x2400", DRM_MODE_TYPE_DRIVER, 592250, 3840, 3888, 2381 - 3920, 4000, 0, 2400, 2403, 2409, 2469, 0, 2382 - DRM_MODE_FLAG_PHSYNC | DRM_MODE_FLAG_NVSYNC) }, 2383 - /* Terminate */ 2384 - { DRM_MODE("", 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0) }, 2385 - }; 2386 - 2387 2285 /** 2388 2286 * vmw_guess_mode_timing - Provide fake timings for a 2389 2287 * 60Hz vrefresh mode. ··· 2303 2403 mode->clock = (u32)mode->htotal * (u32)mode->vtotal / 100 * 6; 2304 2404 } 2305 2405 2306 - 2307 - int vmw_du_connector_fill_modes(struct drm_connector *connector, 2308 - uint32_t max_width, uint32_t max_height) 2309 - { 2310 - struct vmw_display_unit *du = vmw_connector_to_du(connector); 2311 - struct drm_device *dev = connector->dev; 2312 - struct vmw_private *dev_priv = vmw_priv(dev); 2313 - struct drm_display_mode *mode = NULL; 2314 - struct drm_display_mode *bmode; 2315 - struct drm_display_mode prefmode = { DRM_MODE("preferred", 2316 - DRM_MODE_TYPE_DRIVER | DRM_MODE_TYPE_PREFERRED, 2317 - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2318 - DRM_MODE_FLAG_NHSYNC | DRM_MODE_FLAG_PVSYNC) 2319 - }; 2320 - int i; 2321 - u32 assumed_bpp = 4; 2322 - 2323 - if (dev_priv->assume_16bpp) 2324 - assumed_bpp = 2; 2325 - 2326 - max_width = min(max_width, dev_priv->texture_max_width); 2327 - max_height = min(max_height, dev_priv->texture_max_height); 2328 - 2329 - /* 2330 - * For STDU extra limit for a mode on SVGA_REG_SCREENTARGET_MAX_WIDTH/ 2331 - * HEIGHT registers. 2332 - */ 2333 - if (dev_priv->active_display_unit == vmw_du_screen_target) { 2334 - max_width = min(max_width, dev_priv->stdu_max_width); 2335 - max_height = min(max_height, dev_priv->stdu_max_height); 2336 - } 2337 - 2338 - /* Add preferred mode */ 2339 - mode = drm_mode_duplicate(dev, &prefmode); 2340 - if (!mode) 2341 - return 0; 2342 - mode->hdisplay = du->pref_width; 2343 - mode->vdisplay = du->pref_height; 2344 - vmw_guess_mode_timing(mode); 2345 - drm_mode_set_name(mode); 2346 - 2347 - if (vmw_kms_validate_mode_vram(dev_priv, 2348 - mode->hdisplay * assumed_bpp, 2349 - mode->vdisplay)) { 2350 - drm_mode_probed_add(connector, mode); 2351 - } else { 2352 - drm_mode_destroy(dev, mode); 2353 - mode = NULL; 2354 - } 2355 - 2356 - if (du->pref_mode) { 2357 - list_del_init(&du->pref_mode->head); 2358 - drm_mode_destroy(dev, du->pref_mode); 2359 - } 2360 - 2361 - /* mode might be null here, this is intended */ 2362 - du->pref_mode = mode; 2363 - 2364 - for (i = 0; vmw_kms_connector_builtin[i].type != 0; i++) { 2365 - bmode = &vmw_kms_connector_builtin[i]; 2366 - if (bmode->hdisplay > max_width || 2367 - bmode->vdisplay > max_height) 2368 - continue; 2369 - 2370 - if (!vmw_kms_validate_mode_vram(dev_priv, 2371 - bmode->hdisplay * assumed_bpp, 2372 - bmode->vdisplay)) 2373 - continue; 2374 - 2375 - mode = drm_mode_duplicate(dev, bmode); 2376 - if (!mode) 2377 - return 0; 2378 - 2379 - drm_mode_probed_add(connector, mode); 2380 - } 2381 - 2382 - drm_connector_list_update(connector); 2383 - /* Move the prefered mode first, help apps pick the right mode. */ 2384 - drm_mode_sort(&connector->modes); 2385 - 2386 - return 1; 2387 - } 2388 2406 2389 2407 /** 2390 2408 * vmw_kms_update_layout_ioctl - Handler for DRM_VMW_UPDATE_LAYOUT ioctl ··· 2843 3025 out_unref: 2844 3026 vmw_validation_unref_lists(&val_ctx); 2845 3027 return ret; 3028 + } 3029 + 3030 + /** 3031 + * vmw_connector_mode_valid - implements drm_connector_helper_funcs.mode_valid callback 3032 + * 3033 + * @connector: the drm connector, part of a DU container 3034 + * @mode: drm mode to check 3035 + * 3036 + * Returns MODE_OK on success, or a drm_mode_status error code. 3037 + */ 3038 + enum drm_mode_status vmw_connector_mode_valid(struct drm_connector *connector, 3039 + struct drm_display_mode *mode) 3040 + { 3041 + struct drm_device *dev = connector->dev; 3042 + struct vmw_private *dev_priv = vmw_priv(dev); 3043 + u32 max_width = dev_priv->texture_max_width; 3044 + u32 max_height = dev_priv->texture_max_height; 3045 + u32 assumed_cpp = 4; 3046 + 3047 + if (dev_priv->assume_16bpp) 3048 + assumed_cpp = 2; 3049 + 3050 + if (dev_priv->active_display_unit == vmw_du_screen_target) { 3051 + max_width = min(dev_priv->stdu_max_width, max_width); 3052 + max_height = min(dev_priv->stdu_max_height, max_height); 3053 + } 3054 + 3055 + if (max_width < mode->hdisplay) 3056 + return MODE_BAD_HVALUE; 3057 + 3058 + if (max_height < mode->vdisplay) 3059 + return MODE_BAD_VVALUE; 3060 + 3061 + if (!vmw_kms_validate_mode_vram(dev_priv, 3062 + mode->hdisplay * assumed_cpp, 3063 + mode->vdisplay)) 3064 + return MODE_MEM; 3065 + 3066 + return MODE_OK; 3067 + } 3068 + 3069 + /** 3070 + * vmw_connector_get_modes - implements drm_connector_helper_funcs.get_modes callback 3071 + * 3072 + * @connector: the drm connector, part of a DU container 3073 + * 3074 + * Returns the number of added modes. 3075 + */ 3076 + int vmw_connector_get_modes(struct drm_connector *connector) 3077 + { 3078 + struct vmw_display_unit *du = vmw_connector_to_du(connector); 3079 + struct drm_device *dev = connector->dev; 3080 + struct vmw_private *dev_priv = vmw_priv(dev); 3081 + struct drm_display_mode *mode = NULL; 3082 + struct drm_display_mode prefmode = { DRM_MODE("preferred", 3083 + DRM_MODE_TYPE_DRIVER | DRM_MODE_TYPE_PREFERRED, 3084 + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3085 + DRM_MODE_FLAG_NHSYNC | DRM_MODE_FLAG_PVSYNC) 3086 + }; 3087 + u32 max_width; 3088 + u32 max_height; 3089 + u32 num_modes; 3090 + 3091 + /* Add preferred mode */ 3092 + mode = drm_mode_duplicate(dev, &prefmode); 3093 + if (!mode) 3094 + return 0; 3095 + 3096 + mode->hdisplay = du->pref_width; 3097 + mode->vdisplay = du->pref_height; 3098 + vmw_guess_mode_timing(mode); 3099 + drm_mode_set_name(mode); 3100 + 3101 + drm_mode_probed_add(connector, mode); 3102 + drm_dbg_kms(dev, "preferred mode " DRM_MODE_FMT "\n", DRM_MODE_ARG(mode)); 3103 + 3104 + /* Probe connector for all modes not exceeding our geom limits */ 3105 + max_width = dev_priv->texture_max_width; 3106 + max_height = dev_priv->texture_max_height; 3107 + 3108 + if (dev_priv->active_display_unit == vmw_du_screen_target) { 3109 + max_width = min(dev_priv->stdu_max_width, max_width); 3110 + max_height = min(dev_priv->stdu_max_height, max_height); 3111 + } 3112 + 3113 + num_modes = 1 + drm_add_modes_noedid(connector, max_width, max_height); 3114 + 3115 + return num_modes; 2846 3116 }
+3 -3
drivers/gpu/drm/vmwgfx/vmwgfx_kms.h
··· 378 378 unsigned pref_width; 379 379 unsigned pref_height; 380 380 bool pref_active; 381 - struct drm_display_mode *pref_mode; 382 381 383 382 /* 384 383 * Gui positioning ··· 427 428 void vmw_du_connector_restore(struct drm_connector *connector); 428 429 enum drm_connector_status 429 430 vmw_du_connector_detect(struct drm_connector *connector, bool force); 430 - int vmw_du_connector_fill_modes(struct drm_connector *connector, 431 - uint32_t max_width, uint32_t max_height); 432 431 int vmw_kms_helper_dirty(struct vmw_private *dev_priv, 433 432 struct vmw_framebuffer *framebuffer, 434 433 const struct drm_clip_rect *clips, ··· 435 438 int num_clips, 436 439 int increment, 437 440 struct vmw_kms_dirty *dirty); 441 + enum drm_mode_status vmw_connector_mode_valid(struct drm_connector *connector, 442 + struct drm_display_mode *mode); 443 + int vmw_connector_get_modes(struct drm_connector *connector); 438 444 439 445 void vmw_kms_helper_validation_finish(struct vmw_private *dev_priv, 440 446 struct drm_file *file_priv,
+3 -2
drivers/gpu/drm/vmwgfx/vmwgfx_ldu.c
··· 304 304 static const struct drm_connector_funcs vmw_legacy_connector_funcs = { 305 305 .dpms = vmw_du_connector_dpms, 306 306 .detect = vmw_du_connector_detect, 307 - .fill_modes = vmw_du_connector_fill_modes, 307 + .fill_modes = drm_helper_probe_single_connector_modes, 308 308 .destroy = vmw_ldu_connector_destroy, 309 309 .reset = vmw_du_connector_reset, 310 310 .atomic_duplicate_state = vmw_du_connector_duplicate_state, ··· 313 313 314 314 static const struct 315 315 drm_connector_helper_funcs vmw_ldu_connector_helper_funcs = { 316 + .get_modes = vmw_connector_get_modes, 317 + .mode_valid = vmw_connector_mode_valid 316 318 }; 317 319 318 320 static int vmw_kms_ldu_do_bo_dirty(struct vmw_private *dev_priv, ··· 451 449 ldu->base.pref_active = (unit == 0); 452 450 ldu->base.pref_width = dev_priv->initial_width; 453 451 ldu->base.pref_height = dev_priv->initial_height; 454 - ldu->base.pref_mode = NULL; 455 452 456 453 /* 457 454 * Remove this after enabling atomic because property values can
+3 -2
drivers/gpu/drm/vmwgfx/vmwgfx_scrn.c
··· 347 347 static const struct drm_connector_funcs vmw_sou_connector_funcs = { 348 348 .dpms = vmw_du_connector_dpms, 349 349 .detect = vmw_du_connector_detect, 350 - .fill_modes = vmw_du_connector_fill_modes, 350 + .fill_modes = drm_helper_probe_single_connector_modes, 351 351 .destroy = vmw_sou_connector_destroy, 352 352 .reset = vmw_du_connector_reset, 353 353 .atomic_duplicate_state = vmw_du_connector_duplicate_state, ··· 357 357 358 358 static const struct 359 359 drm_connector_helper_funcs vmw_sou_connector_helper_funcs = { 360 + .get_modes = vmw_connector_get_modes, 361 + .mode_valid = vmw_connector_mode_valid 360 362 }; 361 363 362 364 ··· 828 826 sou->base.pref_active = (unit == 0); 829 827 sou->base.pref_width = dev_priv->initial_width; 830 828 sou->base.pref_height = dev_priv->initial_height; 831 - sou->base.pref_mode = NULL; 832 829 833 830 /* 834 831 * Remove this after enabling atomic because property values can
+3 -1
drivers/gpu/drm/vmwgfx/vmwgfx_stdu.c
··· 835 835 static const struct drm_connector_funcs vmw_stdu_connector_funcs = { 836 836 .dpms = vmw_du_connector_dpms, 837 837 .detect = vmw_du_connector_detect, 838 - .fill_modes = vmw_du_connector_fill_modes, 838 + .fill_modes = drm_helper_probe_single_connector_modes, 839 839 .destroy = vmw_stdu_connector_destroy, 840 840 .reset = vmw_du_connector_reset, 841 841 .atomic_duplicate_state = vmw_du_connector_duplicate_state, ··· 845 845 846 846 static const struct 847 847 drm_connector_helper_funcs vmw_stdu_connector_helper_funcs = { 848 + .get_modes = vmw_connector_get_modes, 849 + .mode_valid = vmw_connector_mode_valid 848 850 }; 849 851 850 852