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

drm/amdgpu/display: create fake mst encoders ahead of time (v4)

Prevents a warning in the MST create connector case.

v2: create global fake encoders rather per connector fake encoders
to avoid running out of encoder indices.

v3: use the actual number of crtcs on the asic rather than the max
to conserve encoders.

v4: v3 plus missing hunk I forgot to git add.

Bug: https://gitlab.freedesktop.org/drm/amd/-/issues/1108
Fixes: c6385e503aeaf9 ("drm/amdgpu: drop legacy drm load and unload callbacks")
Reviewed-by: Nicholas Kazlauskas <nicholas.kazlauskas@amd.com>
Signed-off-by: Alex Deucher <alexander.deucher@amd.com>
Cc: stable@vger.kernel.org # 5.7.x

+48 -28
+9
drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c
··· 974 974 /* Update the actual used number of crtc */ 975 975 adev->mode_info.num_crtc = adev->dm.display_indexes_num; 976 976 977 + /* create fake encoders for MST */ 978 + dm_dp_create_fake_mst_encoders(adev); 979 + 977 980 /* TODO: Add_display_info? */ 978 981 979 982 /* TODO use dynamic cursor width */ ··· 1000 997 1001 998 static void amdgpu_dm_fini(struct amdgpu_device *adev) 1002 999 { 1000 + int i; 1001 + 1002 + for (i = 0; i < adev->dm.display_indexes_num; i++) { 1003 + drm_encoder_cleanup(&adev->dm.mst_encoders[i].base); 1004 + } 1005 + 1003 1006 amdgpu_dm_audio_fini(adev); 1004 1007 1005 1008 amdgpu_dm_destroy_drm_device(&adev->dm);
+10 -1
drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.h
··· 43 43 */ 44 44 45 45 #define AMDGPU_DM_MAX_DISPLAY_INDEX 31 46 + 47 + #define AMDGPU_DM_MAX_CRTC 6 48 + 46 49 /* 47 50 #include "include/amdgpu_dal_power_if.h" 48 51 #include "amdgpu_dm_irq.h" ··· 331 328 * available in FW 332 329 */ 333 330 const struct gpu_info_soc_bounding_box_v1_0 *soc_bounding_box; 331 + 332 + /** 333 + * @mst_encoders: 334 + * 335 + * fake encoders used for DP MST. 336 + */ 337 + struct amdgpu_encoder mst_encoders[AMDGPU_DM_MAX_CRTC]; 334 338 }; 335 339 336 340 struct amdgpu_dm_connector { ··· 366 356 struct amdgpu_dm_dp_aux dm_dp_aux; 367 357 struct drm_dp_mst_port *port; 368 358 struct amdgpu_dm_connector *mst_port; 369 - struct amdgpu_encoder *mst_encoder; 370 359 struct drm_dp_aux *dsc_aux; 371 360 372 361 /* TODO see if we can merge with ddc_bus or make a dm_connector */
+26 -27
drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_mst_types.c
··· 95 95 { 96 96 struct amdgpu_dm_connector *aconnector = 97 97 to_amdgpu_dm_connector(connector); 98 - struct amdgpu_encoder *amdgpu_encoder = aconnector->mst_encoder; 99 98 100 99 if (aconnector->dc_sink) { 101 100 dc_link_remove_remote_sink(aconnector->dc_link, ··· 104 105 105 106 kfree(aconnector->edid); 106 107 107 - drm_encoder_cleanup(&amdgpu_encoder->base); 108 - kfree(amdgpu_encoder); 109 108 drm_connector_cleanup(connector); 110 109 drm_dp_mst_put_port_malloc(aconnector->port); 111 110 kfree(aconnector); ··· 240 243 dm_mst_atomic_best_encoder(struct drm_connector *connector, 241 244 struct drm_connector_state *connector_state) 242 245 { 243 - return &to_amdgpu_dm_connector(connector)->mst_encoder->base; 246 + struct drm_device *dev = connector->dev; 247 + struct amdgpu_device *adev = dev->dev_private; 248 + struct amdgpu_crtc *acrtc = to_amdgpu_crtc(connector_state->crtc); 249 + 250 + return &adev->dm.mst_encoders[acrtc->crtc_id].base; 244 251 } 245 252 246 253 static int ··· 307 306 .destroy = amdgpu_dm_encoder_destroy, 308 307 }; 309 308 310 - static struct amdgpu_encoder * 311 - dm_dp_create_fake_mst_encoder(struct amdgpu_dm_connector *connector) 309 + void 310 + dm_dp_create_fake_mst_encoders(struct amdgpu_device *adev) 312 311 { 313 - struct drm_device *dev = connector->base.dev; 314 - struct amdgpu_device *adev = dev->dev_private; 315 - struct amdgpu_encoder *amdgpu_encoder; 316 - struct drm_encoder *encoder; 312 + struct drm_device *dev = adev->ddev; 313 + int i; 317 314 318 - amdgpu_encoder = kzalloc(sizeof(*amdgpu_encoder), GFP_KERNEL); 319 - if (!amdgpu_encoder) 320 - return NULL; 315 + for (i = 0; i < adev->dm.display_indexes_num; i++) { 316 + struct amdgpu_encoder *amdgpu_encoder = &adev->dm.mst_encoders[i]; 317 + struct drm_encoder *encoder = &amdgpu_encoder->base; 321 318 322 - encoder = &amdgpu_encoder->base; 323 - encoder->possible_crtcs = amdgpu_dm_get_encoder_crtc_mask(adev); 319 + encoder->possible_crtcs = amdgpu_dm_get_encoder_crtc_mask(adev); 324 320 325 - drm_encoder_init( 326 - dev, 327 - &amdgpu_encoder->base, 328 - &amdgpu_dm_encoder_funcs, 329 - DRM_MODE_ENCODER_DPMST, 330 - NULL); 321 + drm_encoder_init( 322 + dev, 323 + &amdgpu_encoder->base, 324 + &amdgpu_dm_encoder_funcs, 325 + DRM_MODE_ENCODER_DPMST, 326 + NULL); 331 327 332 - drm_encoder_helper_add(encoder, &amdgpu_dm_encoder_helper_funcs); 333 - 334 - return amdgpu_encoder; 328 + drm_encoder_helper_add(encoder, &amdgpu_dm_encoder_helper_funcs); 329 + } 335 330 } 336 331 337 332 static struct drm_connector * ··· 340 343 struct amdgpu_device *adev = dev->dev_private; 341 344 struct amdgpu_dm_connector *aconnector; 342 345 struct drm_connector *connector; 346 + int i; 343 347 344 348 aconnector = kzalloc(sizeof(*aconnector), GFP_KERNEL); 345 349 if (!aconnector) ··· 367 369 master->dc_link, 368 370 master->connector_id); 369 371 370 - aconnector->mst_encoder = dm_dp_create_fake_mst_encoder(master); 371 - drm_connector_attach_encoder(&aconnector->base, 372 - &aconnector->mst_encoder->base); 372 + for (i = 0; i < adev->dm.display_indexes_num; i++) { 373 + drm_connector_attach_encoder(&aconnector->base, 374 + &adev->dm.mst_encoders[i].base); 375 + } 373 376 374 377 connector->max_bpc_property = master->base.max_bpc_property; 375 378 if (connector->max_bpc_property)
+3
drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_mst_types.h
··· 35 35 struct amdgpu_dm_connector *aconnector, 36 36 int link_index); 37 37 38 + void 39 + dm_dp_create_fake_mst_encoders(struct amdgpu_device *adev); 40 + 38 41 #if defined(CONFIG_DRM_AMD_DC_DCN) 39 42 bool compute_mst_dsc_configs_for_state(struct drm_atomic_state *state, 40 43 struct dc_state *dc_state);