diff options
Diffstat (limited to 'meta-amd-bsp/recipes-kernel/linux/linux-yocto-4.14.71/3763-drm-amd-display-Correct-the-plane-enumeration-order.patch')
-rw-r--r-- | meta-amd-bsp/recipes-kernel/linux/linux-yocto-4.14.71/3763-drm-amd-display-Correct-the-plane-enumeration-order.patch | 367 |
1 files changed, 367 insertions, 0 deletions
diff --git a/meta-amd-bsp/recipes-kernel/linux/linux-yocto-4.14.71/3763-drm-amd-display-Correct-the-plane-enumeration-order.patch b/meta-amd-bsp/recipes-kernel/linux/linux-yocto-4.14.71/3763-drm-amd-display-Correct-the-plane-enumeration-order.patch new file mode 100644 index 00000000..d57fb949 --- /dev/null +++ b/meta-amd-bsp/recipes-kernel/linux/linux-yocto-4.14.71/3763-drm-amd-display-Correct-the-plane-enumeration-order.patch @@ -0,0 +1,367 @@ +From 35563ed8153db3ad8e019571e7e80c215f9ec221 Mon Sep 17 00:00:00 2001 +From: Shirish S <shirish.s@amd.com> +Date: Tue, 27 Feb 2018 14:48:13 +0530 +Subject: [PATCH 3763/4131] drm/amd/display: Correct the plane enumeration + order + +The order of planes is given by the order they are enumerated +by kms. +Planes with a higher ID appears above planes with a lower ID. + +Currently the planes are enumerated in the wrong order, +putting the nv12 only plane after the two RGBA planes. + +This patch corrects the plane enumeration order such that all +the overlay planes are initialized first then the primary planes. + +Due to this change in order the dc_add_plane_to_context() shall +receive the planes in reverse order hence this patch reverses +the parsing of planes in DM side itself. + +Signed-off-by: Shirish S <shirish.s@amd.com> +Signed-off-by: Pratik Vishwakarma <Pratik.Vishwakarma@amd.com> +Reviewed-by: Harry Wentland <Harry.Wentland@amd.com> + +Conflicts: + drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c + +Change-Id: Id53a956b54f1f3afd89774da65e9fde12d4486dd +--- + drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c | 275 ++++++++++++---------- + drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.h | 23 ++ + 2 files changed, 175 insertions(+), 123 deletions(-) + +diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c +index 2a99523..6645c61 100644 +--- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c ++++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c +@@ -1367,6 +1367,43 @@ amdgpu_dm_register_backlight_device(struct amdgpu_display_manager *dm) + + #endif + ++static int initialize_plane(struct amdgpu_display_manager *dm, ++ struct amdgpu_mode_info *mode_info, ++ int plane_id) ++{ ++ struct amdgpu_plane *plane; ++ unsigned long possible_crtcs; ++ int ret = 0; ++ ++ plane = kzalloc(sizeof(struct amdgpu_plane), GFP_KERNEL); ++ mode_info->planes[plane_id] = plane; ++ ++ if (!plane) { ++ DRM_ERROR("KMS: Failed to allocate plane\n"); ++ return -ENOMEM; ++ } ++ plane->base.type = mode_info->plane_type[plane_id]; ++ ++ /* ++ * HACK: IGT tests expect that each plane can only have one ++ * one possible CRTC. For now, set one CRTC for each ++ * plane that is not an underlay, but still allow multiple ++ * CRTCs for underlay planes. ++ */ ++ possible_crtcs = 1 << plane_id; ++ if (plane_id >= dm->dc->caps.max_streams) ++ possible_crtcs = 0xff; ++ ++ ret = amdgpu_dm_plane_init(dm, mode_info->planes[plane_id], possible_crtcs); ++ ++ if (ret) { ++ DRM_ERROR("KMS: Failed to initialize plane\n"); ++ return ret; ++ } ++ ++ return ret; ++} ++ + /* In this architecture, the association + * connector -> encoder -> crtc + * id not really requried. The crtc and connector will hold the +@@ -1376,133 +1413,125 @@ amdgpu_dm_register_backlight_device(struct amdgpu_display_manager *dm) + */ + static int amdgpu_dm_initialize_drm_device(struct amdgpu_device *adev) + { +- struct amdgpu_display_manager *dm = &adev->dm; +- uint32_t i; +- struct amdgpu_dm_connector *aconnector = NULL; +- struct amdgpu_encoder *aencoder = NULL; +- struct amdgpu_mode_info *mode_info = &adev->mode_info; +- uint32_t link_cnt; +- unsigned long possible_crtcs; +- +- link_cnt = dm->dc->caps.max_links; +- if (amdgpu_dm_mode_config_init(dm->adev)) { +- DRM_ERROR("DM: Failed to initialize mode config\n"); +- return -1; +- } +- +- for (i = 0; i < dm->dc->caps.max_planes; i++) { +- struct amdgpu_plane *plane; +- +- plane = kzalloc(sizeof(struct amdgpu_plane), GFP_KERNEL); +- mode_info->planes[i] = plane; +- +- if (!plane) { +- DRM_ERROR("KMS: Failed to allocate plane\n"); +- goto fail; +- } +- plane->base.type = mode_info->plane_type[i]; +- +- /* +- * HACK: IGT tests expect that each plane can only have one +- * one possible CRTC. For now, set one CRTC for each +- * plane that is not an underlay, but still allow multiple +- * CRTCs for underlay planes. +- */ +- possible_crtcs = 1 << i; +- if (i >= dm->dc->caps.max_streams) +- possible_crtcs = 0xff; +- +- if (amdgpu_dm_plane_init(dm, mode_info->planes[i], possible_crtcs)) { +- DRM_ERROR("KMS: Failed to initialize plane\n"); +- goto fail; +- } +- } +- +- for (i = 0; i < dm->dc->caps.max_streams; i++) +- if (amdgpu_dm_crtc_init(dm, &mode_info->planes[i]->base, i)) { +- DRM_ERROR("KMS: Failed to initialize crtc\n"); +- goto fail; +- } +- +- dm->display_indexes_num = dm->dc->caps.max_streams; +- +- /* loops over all connectors on the board */ +- for (i = 0; i < link_cnt; i++) { +- +- if (i > AMDGPU_DM_MAX_DISPLAY_INDEX) { +- DRM_ERROR( +- "KMS: Cannot support more than %d display indexes\n", +- AMDGPU_DM_MAX_DISPLAY_INDEX); +- continue; +- } +- +- aconnector = kzalloc(sizeof(*aconnector), GFP_KERNEL); +- if (!aconnector) +- goto fail; +- +- aencoder = kzalloc(sizeof(*aencoder), GFP_KERNEL); +- if (!aencoder) +- goto fail; +- +- if (amdgpu_dm_encoder_init(dm->ddev, aencoder, i)) { +- DRM_ERROR("KMS: Failed to initialize encoder\n"); +- goto fail; +- } +- +- if (amdgpu_dm_connector_init(dm, aconnector, i, aencoder)) { +- DRM_ERROR("KMS: Failed to initialize connector\n"); +- goto fail; +- } +- +- if (dc_link_detect(dc_get_link_at_index(dm->dc, i), +- DETECT_REASON_BOOT)) +- amdgpu_dm_update_connector_after_detect(aconnector); +- } +- +- /* Software is initialized. Now we can register interrupt handlers. */ +- switch (adev->asic_type) { +- case CHIP_BONAIRE: +- case CHIP_HAWAII: +- case CHIP_KAVERI: +- case CHIP_KABINI: +- case CHIP_MULLINS: +- case CHIP_TONGA: +- case CHIP_FIJI: +- case CHIP_CARRIZO: +- case CHIP_STONEY: +- case CHIP_POLARIS11: +- case CHIP_POLARIS10: +- case CHIP_POLARIS12: +- case CHIP_VEGA10: +- if (dce110_register_irq_handlers(dm->adev)) { +- DRM_ERROR("DM: Failed to initialize IRQ\n"); +- goto fail; +- } +- break; ++ struct amdgpu_display_manager *dm = &adev->dm; ++ int32_t i; ++ struct amdgpu_dm_connector *aconnector = NULL; ++ struct amdgpu_encoder *aencoder = NULL; ++ struct amdgpu_mode_info *mode_info = &adev->mode_info; ++ uint32_t link_cnt; ++ int32_t total_overlay_planes, total_primary_planes; ++ ++ link_cnt = dm->dc->caps.max_links; ++ if (amdgpu_dm_mode_config_init(dm->adev)) { ++ DRM_ERROR("DM: Failed to initialize mode config\n"); ++ return -1; ++ } ++ ++ /* Identify the number of planes to be initialized */ ++ total_overlay_planes = dm->dc->caps.max_slave_planes; ++ total_primary_planes = dm->dc->caps.max_planes - dm->dc->caps.max_slave_planes; ++ ++ /* First initialize overlay planes, index starting after primary planes */ ++ for (i = (total_overlay_planes - 1); i >= 0; i--) { ++ if (initialize_plane(dm, mode_info, (total_primary_planes + i))) { ++ DRM_ERROR("KMS: Failed to initialize overlay plane\n"); ++ goto fail; ++ } ++ } ++ ++ /* Initialize primary planes */ ++ for (i = (total_primary_planes - 1); i >= 0; i--) { ++ if (initialize_plane(dm, mode_info, i)) { ++ DRM_ERROR("KMS: Failed to initialize primary plane\n"); ++ goto fail; ++ } ++ } ++ ++ for (i = 0; i < dm->dc->caps.max_streams; i++) ++ if (amdgpu_dm_crtc_init(dm, &mode_info->planes[i]->base, i)) { ++ DRM_ERROR("KMS: Failed to initialize crtc\n"); ++ goto fail; ++ } ++ ++ dm->display_indexes_num = dm->dc->caps.max_streams; ++ ++ /* loops over all connectors on the board */ ++ for (i = 0; i < link_cnt; i++) { ++ ++ if (i > AMDGPU_DM_MAX_DISPLAY_INDEX) { ++ DRM_ERROR( ++ "KMS: Cannot support more than %d display indexes\n", ++ AMDGPU_DM_MAX_DISPLAY_INDEX); ++ continue; ++ } ++ ++ aconnector = kzalloc(sizeof(*aconnector), GFP_KERNEL); ++ if (!aconnector) ++ goto fail; ++ ++ aencoder = kzalloc(sizeof(*aencoder), GFP_KERNEL); ++ if (!aencoder) ++ goto fail; ++ ++ if (amdgpu_dm_encoder_init(dm->ddev, aencoder, i)) { ++ DRM_ERROR("KMS: Failed to initialize encoder\n"); ++ goto fail; ++ } ++ ++ if (amdgpu_dm_connector_init(dm, aconnector, i, aencoder)) { ++ DRM_ERROR("KMS: Failed to initialize connector\n"); ++ goto fail; ++ } ++ ++ if (dc_link_detect(dc_get_link_at_index(dm->dc, i), ++ DETECT_REASON_BOOT)) ++ amdgpu_dm_update_connector_after_detect(aconnector); ++ } ++ ++ /* Software is initialized. Now we can register interrupt handlers. */ ++ switch (adev->asic_type) { ++ case CHIP_BONAIRE: ++ case CHIP_HAWAII: ++ case CHIP_KAVERI: ++ case CHIP_KABINI: ++ case CHIP_MULLINS: ++ case CHIP_TONGA: ++ case CHIP_FIJI: ++ case CHIP_CARRIZO: ++ case CHIP_STONEY: ++ case CHIP_POLARIS11: ++ case CHIP_POLARIS10: ++ case CHIP_POLARIS12: ++ case CHIP_VEGA10: ++ if (dce110_register_irq_handlers(dm->adev)) { ++ DRM_ERROR("DM: Failed to initialize IRQ\n"); ++ goto fail; ++ } ++ break; + #if defined(CONFIG_DRM_AMD_DC_DCN1_0) +- case CHIP_RAVEN: +- if (dcn10_register_irq_handlers(dm->adev)) { +- DRM_ERROR("DM: Failed to initialize IRQ\n"); +- goto fail; +- } +- /* +- * Temporary disable until pplib/smu interaction is implemented +- */ +- dm->dc->debug.disable_stutter = true; +- break; ++ case CHIP_RAVEN: ++ if (dcn10_register_irq_handlers(dm->adev)) { ++ DRM_ERROR("DM: Failed to initialize IRQ\n"); ++ goto fail; ++ } ++ /* ++ * Temporary disable until pplib/smu interaction is implemented ++ */ ++ dm->dc->debug.disable_stutter = true; ++ break; + #endif +- default: +- DRM_ERROR("Usupported ASIC type: 0x%X\n", adev->asic_type); +- goto fail; +- } ++ default: ++ DRM_ERROR("Usupported ASIC type: 0x%X\n", adev->asic_type); ++ goto fail; ++ } + +- return 0; ++ return 0; + fail: +- kfree(aencoder); +- kfree(aconnector); +- for (i = 0; i < dm->dc->caps.max_planes; i++) +- kfree(mode_info->planes[i]); +- return -1; ++ kfree(aencoder); ++ kfree(aconnector); ++ for (i = 0; i < dm->dc->caps.max_planes; i++) ++ kfree(mode_info->planes[i]); ++ return -1; + } + + static void amdgpu_dm_destroy_drm_device(struct amdgpu_display_manager *dm) +diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.h b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.h +index b4c48c5..c6d5785 100644 +--- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.h ++++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.h +@@ -80,6 +80,29 @@ struct dm_comressor_info { + }; + #endif + ++/** ++ * for_each_oldnew_plane_in_state_reverse - iterate over all planes in an atomic ++ * update in reverse order ++ * @__state: &struct drm_atomic_state pointer ++ * @plane: &struct drm_plane iteration cursor ++ * @old_plane_state: &struct drm_plane_state iteration cursor for the old state ++ * @new_plane_state: &struct drm_plane_state iteration cursor for the new state ++ * @__i: int iteration cursor, for macro-internal use ++ * ++ * This iterates over all planes in an atomic update in reverse order, ++ * tracking both old and new state. This is useful in places where the ++ * state delta needs to be considered, for example in atomic check functions. ++ */ ++#ifndef for_each_oldnew_plane_in_state_reverse ++#define for_each_oldnew_plane_in_state_reverse(__state, plane, old_plane_state, new_plane_state, __i) \ ++ for ((__i) = ((__state)->dev->mode_config.num_total_plane - 1); \ ++ (__i) >= 0; \ ++ (__i)--) \ ++ for_each_if ((__state)->planes[__i].ptr && \ ++ ((plane) = (__state)->planes[__i].ptr, \ ++ (old_plane_state) = (__state)->planes[__i].old_state,\ ++ (new_plane_state) = (__state)->planes[__i].new_state, 1)) ++#endif + + struct amdgpu_display_manager { + struct dal *dal; +-- +2.7.4 + |