summaryrefslogtreecommitdiff
path: root/drivers/gpu/drm/amd/display
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/gpu/drm/amd/display')
-rw-r--r--drivers/gpu/drm/amd/display/Kconfig2
-rw-r--r--drivers/gpu/drm/amd/display/Makefile2
-rw-r--r--drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c191
-rw-r--r--drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.h4
-rw-r--r--drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_color.c92
-rw-r--r--drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_helpers.c14
-rw-r--r--drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_mst_types.c12
-rw-r--r--drivers/gpu/drm/amd/display/dc/basics/logger.c3
-rw-r--r--drivers/gpu/drm/amd/display/dc/bios/bios_parser.c6
-rw-r--r--drivers/gpu/drm/amd/display/dc/bios/bios_parser2.c6
-rw-r--r--drivers/gpu/drm/amd/display/dc/bios/command_table2.c16
-rw-r--r--drivers/gpu/drm/amd/display/dc/bios/command_table2.h2
-rw-r--r--drivers/gpu/drm/amd/display/dc/calcs/dce_calcs.c160
-rw-r--r--drivers/gpu/drm/amd/display/dc/calcs/dcn_calcs.c34
-rw-r--r--drivers/gpu/drm/amd/display/dc/core/dc.c37
-rw-r--r--drivers/gpu/drm/amd/display/dc/core/dc_debug.c35
-rw-r--r--drivers/gpu/drm/amd/display/dc/core/dc_link.c74
-rw-r--r--drivers/gpu/drm/amd/display/dc/core/dc_link_ddc.c7
-rw-r--r--drivers/gpu/drm/amd/display/dc/core/dc_link_dp.c151
-rw-r--r--drivers/gpu/drm/amd/display/dc/core/dc_link_hwss.c1
-rw-r--r--drivers/gpu/drm/amd/display/dc/core/dc_resource.c14
-rw-r--r--drivers/gpu/drm/amd/display/dc/core/dc_stream.c5
-rw-r--r--drivers/gpu/drm/amd/display/dc/dc.h16
-rw-r--r--drivers/gpu/drm/amd/display/dc/dc_hw_types.h12
-rw-r--r--drivers/gpu/drm/amd/display/dc/dc_link.h2
-rw-r--r--drivers/gpu/drm/amd/display/dc/dc_stream.h10
-rw-r--r--drivers/gpu/drm/amd/display/dc/dc_types.h18
-rw-r--r--drivers/gpu/drm/amd/display/dc/dce/dce_abm.c5
-rw-r--r--drivers/gpu/drm/amd/display/dc/dce/dce_audio.c17
-rw-r--r--drivers/gpu/drm/amd/display/dc/dce/dce_clock_source.c32
-rw-r--r--drivers/gpu/drm/amd/display/dc/dce/dce_clocks.c8
-rw-r--r--drivers/gpu/drm/amd/display/dc/dce/dce_dmcu.h35
-rw-r--r--drivers/gpu/drm/amd/display/dc/dce/dce_hwseq.c10
-rw-r--r--drivers/gpu/drm/amd/display/dc/dce/dce_hwseq.h24
-rw-r--r--drivers/gpu/drm/amd/display/dc/dce/dce_link_encoder.c37
-rw-r--r--drivers/gpu/drm/amd/display/dc/dce/dce_stream_encoder.c9
-rw-r--r--drivers/gpu/drm/amd/display/dc/dce/dce_transform.c11
-rw-r--r--drivers/gpu/drm/amd/display/dc/dce/dce_transform.h1
-rw-r--r--drivers/gpu/drm/amd/display/dc/dce100/dce100_resource.c50
-rw-r--r--drivers/gpu/drm/amd/display/dc/dce110/dce110_compressor.c14
-rw-r--r--drivers/gpu/drm/amd/display/dc/dce110/dce110_hw_sequencer.c77
-rw-r--r--drivers/gpu/drm/amd/display/dc/dce110/dce110_resource.c26
-rw-r--r--drivers/gpu/drm/amd/display/dc/dce110/dce110_timing_generator_v.c17
-rw-r--r--drivers/gpu/drm/amd/display/dc/dce110/dce110_transform_v.c5
-rw-r--r--drivers/gpu/drm/amd/display/dc/dce112/dce112_compressor.c27
-rw-r--r--drivers/gpu/drm/amd/display/dc/dce112/dce112_resource.c7
-rw-r--r--drivers/gpu/drm/amd/display/dc/dce80/dce80_resource.c87
-rw-r--r--drivers/gpu/drm/amd/display/dc/dcn10/dcn10_cm_common.c153
-rw-r--r--drivers/gpu/drm/amd/display/dc/dcn10/dcn10_cm_common.h5
-rw-r--r--drivers/gpu/drm/amd/display/dc/dcn10/dcn10_dpp.c7
-rw-r--r--drivers/gpu/drm/amd/display/dc/dcn10/dcn10_dpp.h16
-rw-r--r--drivers/gpu/drm/amd/display/dc/dcn10/dcn10_dpp_cm.c9
-rw-r--r--drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hubbub.c77
-rw-r--r--drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hubbub.h1
-rw-r--r--drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hw_sequencer.c329
-rw-r--r--drivers/gpu/drm/amd/display/dc/dcn10/dcn10_optc.h6
-rw-r--r--drivers/gpu/drm/amd/display/dc/dcn10/dcn10_resource.c7
-rw-r--r--drivers/gpu/drm/amd/display/dc/dm_helpers.h10
-rw-r--r--drivers/gpu/drm/amd/display/dc/dm_services_types.h21
-rw-r--r--drivers/gpu/drm/amd/display/dc/dml/display_rq_dlg_helpers.c1
-rw-r--r--drivers/gpu/drm/amd/display/dc/dml/dml_common_defs.h2
-rw-r--r--drivers/gpu/drm/amd/display/dc/dml/dml_inline_defs.h1
-rw-r--r--drivers/gpu/drm/amd/display/dc/dml/dml_logger.h38
-rw-r--r--drivers/gpu/drm/amd/display/dc/i2caux/aux_engine.c21
-rw-r--r--drivers/gpu/drm/amd/display/dc/i2caux/dce110/i2c_hw_engine_dce110.c6
-rw-r--r--drivers/gpu/drm/amd/display/dc/i2caux/i2caux.c1
-rw-r--r--drivers/gpu/drm/amd/display/dc/inc/core_types.h28
-rw-r--r--drivers/gpu/drm/amd/display/dc/inc/dc_link_ddc.h2
-rw-r--r--drivers/gpu/drm/amd/display/dc/inc/dce_calcs.h6
-rw-r--r--drivers/gpu/drm/amd/display/dc/inc/hw/dpp.h5
-rw-r--r--drivers/gpu/drm/amd/display/dc/irq/dce110/irq_service_dce110.c75
-rw-r--r--drivers/gpu/drm/amd/display/dc/irq/irq_service.c10
-rw-r--r--drivers/gpu/drm/amd/display/include/link_service_types.h5
-rw-r--r--drivers/gpu/drm/amd/display/include/logger_types.h34
-rw-r--r--drivers/gpu/drm/amd/display/modules/color/color_gamma.c149
-rw-r--r--drivers/gpu/drm/amd/display/modules/freesync/freesync.c155
-rw-r--r--drivers/gpu/drm/amd/display/modules/inc/mod_freesync.h9
-rw-r--r--drivers/gpu/drm/amd/display/modules/inc/mod_stats.h65
-rw-r--r--drivers/gpu/drm/amd/display/modules/stats/stats.c334
79 files changed, 2233 insertions, 780 deletions
diff --git a/drivers/gpu/drm/amd/display/Kconfig b/drivers/gpu/drm/amd/display/Kconfig
index ec3285f65517..5b124a67404c 100644
--- a/drivers/gpu/drm/amd/display/Kconfig
+++ b/drivers/gpu/drm/amd/display/Kconfig
@@ -11,7 +11,7 @@ config DRM_AMD_DC
config DRM_AMD_DC_PRE_VEGA
bool "DC support for Polaris and older ASICs"
- default n
+ default y
help
Choose this option to enable the new DC support for older asics
by default. This includes Polaris, Carrizo, Tonga, Bonaire,
diff --git a/drivers/gpu/drm/amd/display/Makefile b/drivers/gpu/drm/amd/display/Makefile
index 3d14478913de..a2c5be493555 100644
--- a/drivers/gpu/drm/amd/display/Makefile
+++ b/drivers/gpu/drm/amd/display/Makefile
@@ -26,8 +26,6 @@
AMDDALPATH = $(RELATIVE_AMD_DISPLAY_PATH)
-subdir-ccflags-y += -I$(AMDDALPATH)/ -I$(AMDDALPATH)/include
-
subdir-ccflags-y += -I$(FULL_AMD_DISPLAY_PATH)/dc/inc/
subdir-ccflags-y += -I$(FULL_AMD_DISPLAY_PATH)/dc/inc/hw
subdir-ccflags-y += -I$(FULL_AMD_DISPLAY_PATH)/modules/inc
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 246fff33c7bf..ae512ecb65ee 100644
--- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c
+++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c
@@ -374,7 +374,7 @@ static void amdgpu_dm_fbc_init(struct drm_connector *connector)
if (max_size) {
int r = amdgpu_bo_create_kernel(adev, max_size * 4, PAGE_SIZE,
- AMDGPU_GEM_DOMAIN_VRAM, &compressor->bo_ptr,
+ AMDGPU_GEM_DOMAIN_GTT, &compressor->bo_ptr,
&compressor->gpu_addr, &compressor->cpu_addr);
if (r)
@@ -1058,6 +1058,10 @@ static void handle_hpd_rx_irq(void *param)
!is_mst_root_connector) {
/* Downstream Port status changed. */
if (dc_link_detect(dc_link, DETECT_REASON_HPDRX)) {
+
+ if (aconnector->fake_enable)
+ aconnector->fake_enable = false;
+
amdgpu_dm_update_connector_after_detect(aconnector);
@@ -1127,7 +1131,7 @@ static int dce110_register_irq_handlers(struct amdgpu_device *adev)
if (adev->asic_type == CHIP_VEGA10 ||
adev->asic_type == CHIP_RAVEN)
- client_id = AMDGPU_IH_CLIENTID_DCE;
+ client_id = SOC15_IH_CLIENTID_DCE;
int_params.requested_polarity = INTERRUPT_POLARITY_DEFAULT;
int_params.current_polarity = INTERRUPT_POLARITY_DEFAULT;
@@ -1227,7 +1231,7 @@ static int dcn10_register_irq_handlers(struct amdgpu_device *adev)
for (i = DCN_1_0__SRCID__DC_D1_OTG_VSTARTUP;
i <= DCN_1_0__SRCID__DC_D1_OTG_VSTARTUP + adev->mode_info.num_crtc - 1;
i++) {
- r = amdgpu_irq_add_id(adev, AMDGPU_IH_CLIENTID_DCE, i, &adev->crtc_irq);
+ r = amdgpu_irq_add_id(adev, SOC15_IH_CLIENTID_DCE, i, &adev->crtc_irq);
if (r) {
DRM_ERROR("Failed to add crtc irq id!\n");
@@ -1251,7 +1255,7 @@ static int dcn10_register_irq_handlers(struct amdgpu_device *adev)
for (i = DCN_1_0__SRCID__HUBP0_FLIP_INTERRUPT;
i <= DCN_1_0__SRCID__HUBP0_FLIP_INTERRUPT + adev->mode_info.num_crtc - 1;
i++) {
- r = amdgpu_irq_add_id(adev, AMDGPU_IH_CLIENTID_DCE, i, &adev->pageflip_irq);
+ r = amdgpu_irq_add_id(adev, SOC15_IH_CLIENTID_DCE, i, &adev->pageflip_irq);
if (r) {
DRM_ERROR("Failed to add page flip irq id!\n");
return r;
@@ -1272,7 +1276,7 @@ static int dcn10_register_irq_handlers(struct amdgpu_device *adev)
}
/* HPD */
- r = amdgpu_irq_add_id(adev, AMDGPU_IH_CLIENTID_DCE, DCN_1_0__SRCID__DC_HPD1_INT,
+ r = amdgpu_irq_add_id(adev, SOC15_IH_CLIENTID_DCE, DCN_1_0__SRCID__DC_HPD1_INT,
&adev->hpd_irq);
if (r) {
DRM_ERROR("Failed to add hpd irq id!\n");
@@ -1361,6 +1365,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
@@ -1371,12 +1412,12 @@ 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;
+ 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;
- unsigned long possible_crtcs;
+ int32_t total_overlay_planes, total_primary_planes;
link_cnt = dm->dc->caps.max_links;
if (amdgpu_dm_mode_config_init(dm->adev)) {
@@ -1384,30 +1425,22 @@ static int amdgpu_dm_initialize_drm_device(struct amdgpu_device *adev)
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;
+ /* 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;
- if (!plane) {
- DRM_ERROR("KMS: Failed to allocate plane\n");
+ /* 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;
}
- 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");
+ /* 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;
}
}
@@ -1978,6 +2011,10 @@ static int fill_plane_attributes(struct amdgpu_device *adev,
* every time.
*/
ret = amdgpu_dm_set_degamma_lut(crtc_state, dc_plane_state);
+ if (ret) {
+ dc_transfer_func_release(dc_plane_state->in_transfer_func);
+ dc_plane_state->in_transfer_func = NULL;
+ }
return ret;
}
@@ -2486,6 +2523,27 @@ dm_crtc_duplicate_state(struct drm_crtc *crtc)
return &state->base;
}
+
+static inline int dm_set_vblank(struct drm_crtc *crtc, bool enable)
+{
+ enum dc_irq_source irq_source;
+ struct amdgpu_crtc *acrtc = to_amdgpu_crtc(crtc);
+ struct amdgpu_device *adev = crtc->dev->dev_private;
+
+ irq_source = IRQ_TYPE_VBLANK + acrtc->otg_inst;
+ return dc_interrupt_set(adev->dm.dc, irq_source, enable) ? 0 : -EBUSY;
+}
+
+static int dm_enable_vblank(struct drm_crtc *crtc)
+{
+ return dm_set_vblank(crtc, true);
+}
+
+static void dm_disable_vblank(struct drm_crtc *crtc)
+{
+ dm_set_vblank(crtc, false);
+}
+
/* Implemented only the options currently availible for the driver */
static const struct drm_crtc_funcs amdgpu_dm_crtc_funcs = {
.reset = dm_crtc_reset_state,
@@ -2496,6 +2554,8 @@ static const struct drm_crtc_funcs amdgpu_dm_crtc_funcs = {
.atomic_duplicate_state = dm_crtc_duplicate_state,
.atomic_destroy_state = dm_crtc_destroy_state,
.set_crc_source = amdgpu_dm_crtc_set_crc_source,
+ .enable_vblank = dm_enable_vblank,
+ .disable_vblank = dm_disable_vblank,
};
static enum drm_connector_status
@@ -3059,6 +3119,9 @@ static int dm_plane_atomic_check(struct drm_plane *plane,
if (!dm_plane_state->dc_state)
return 0;
+ if (!fill_rects_from_plane_state(state, dm_plane_state->dc_state))
+ return -EINVAL;
+
if (dc_validate_plane(dc, dm_plane_state->dc_state) == DC_OK)
return 0;
@@ -3193,7 +3256,7 @@ static int amdgpu_dm_crtc_init(struct amdgpu_display_manager *dm,
dm->adev->mode_info.crtcs[crtc_index] = acrtc;
drm_crtc_enable_color_mgmt(&acrtc->base, MAX_COLOR_LUT_ENTRIES,
true, MAX_COLOR_LUT_ENTRIES);
- drm_mode_crtc_set_gamma_size(&acrtc->base, MAX_COLOR_LUT_ENTRIES);
+ drm_mode_crtc_set_gamma_size(&acrtc->base, MAX_COLOR_LEGACY_LUT_ENTRIES);
return 0;
@@ -4660,11 +4723,9 @@ static int dm_update_planes_state(struct dc *dc,
bool pflip_needed = !state->allow_modeset;
int ret = 0;
- if (pflip_needed)
- return ret;
- /* Add new planes */
- for_each_oldnew_plane_in_state(state, plane, old_plane_state, new_plane_state, i) {
+ /* Add new planes, in reverse order as DC expectation */
+ for_each_oldnew_plane_in_state_reverse(state, plane, old_plane_state, new_plane_state, i) {
new_plane_crtc = new_plane_state->crtc;
old_plane_crtc = old_plane_state->crtc;
dm_new_plane_state = to_dm_plane_state(new_plane_state);
@@ -4676,6 +4737,8 @@ static int dm_update_planes_state(struct dc *dc,
/* Remove any changed/removed planes */
if (!enable) {
+ if (pflip_needed)
+ continue;
if (!old_plane_crtc)
continue;
@@ -4707,6 +4770,7 @@ static int dm_update_planes_state(struct dc *dc,
*lock_and_validation_needed = true;
} else { /* Add new planes */
+ struct dc_plane_state *dc_new_plane_state;
if (drm_atomic_plane_disabling(plane->state, new_plane_state))
continue;
@@ -4720,37 +4784,47 @@ static int dm_update_planes_state(struct dc *dc,
if (!dm_new_crtc_state->stream)
continue;
+ if (pflip_needed)
+ continue;
WARN_ON(dm_new_plane_state->dc_state);
- dm_new_plane_state->dc_state = dc_create_plane_state(dc);
+ dc_new_plane_state = dc_create_plane_state(dc);
+ if (!dc_new_plane_state)
+ return -ENOMEM;
DRM_DEBUG_DRIVER("Enabling DRM plane: %d on DRM crtc %d\n",
plane->base.id, new_plane_crtc->base.id);
- if (!dm_new_plane_state->dc_state) {
- ret = -EINVAL;
- return ret;
- }
-
ret = fill_plane_attributes(
new_plane_crtc->dev->dev_private,
- dm_new_plane_state->dc_state,
+ dc_new_plane_state,
new_plane_state,
new_crtc_state);
- if (ret)
+ if (ret) {
+ dc_plane_state_release(dc_new_plane_state);
return ret;
+ }
+ /*
+ * Any atomic check errors that occur after this will
+ * not need a release. The plane state will be attached
+ * to the stream, and therefore part of the atomic
+ * state. It'll be released when the atomic state is
+ * cleaned.
+ */
if (!dc_add_plane_to_context(
dc,
dm_new_crtc_state->stream,
- dm_new_plane_state->dc_state,
+ dc_new_plane_state,
dm_state->context)) {
- ret = -EINVAL;
- return ret;
+ dc_plane_state_release(dc_new_plane_state);
+ return -EINVAL;
}
+ dm_new_plane_state->dc_state = dc_new_plane_state;
+
/* Tell DC to do a full surface update every time there
* is a plane change. Inefficient, but works for now.
*/
@@ -4764,6 +4838,33 @@ static int dm_update_planes_state(struct dc *dc,
return ret;
}
+static int dm_atomic_check_plane_state_fb(struct drm_atomic_state *state,
+ struct drm_crtc *crtc)
+{
+ struct drm_plane *plane;
+ struct drm_crtc_state *crtc_state;
+
+ WARN_ON(!drm_atomic_get_new_crtc_state(state, crtc));
+
+ drm_for_each_plane_mask(plane, state->dev, crtc->state->plane_mask) {
+ struct drm_plane_state *plane_state =
+ drm_atomic_get_plane_state(state, plane);
+
+ if (IS_ERR(plane_state))
+ return -EDEADLK;
+
+ crtc_state = drm_atomic_get_crtc_state(plane_state->state, crtc);
+ if (IS_ERR(crtc_state))
+ return PTR_ERR(crtc_state);
+
+ if (crtc->primary == plane && crtc_state->active) {
+ if (!plane_state->fb)
+ return -EINVAL;
+ }
+ }
+ return 0;
+}
+
static int amdgpu_dm_atomic_check(struct drm_device *dev,
struct drm_atomic_state *state)
{
@@ -4787,6 +4888,10 @@ static int amdgpu_dm_atomic_check(struct drm_device *dev,
goto fail;
for_each_oldnew_crtc_in_state(state, crtc, old_crtc_state, new_crtc_state, i) {
+ ret = dm_atomic_check_plane_state_fb(state, crtc);
+ if (ret)
+ goto fail;
+
if (!drm_atomic_crtc_needs_modeset(new_crtc_state) &&
!new_crtc_state->color_mgmt_changed)
continue;
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 aa7df5775545..b68400c1154b 100644
--- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.h
+++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.h
@@ -268,7 +268,9 @@ void amdgpu_dm_crtc_handle_crc_irq(struct drm_crtc *crtc);
#define amdgpu_dm_crtc_handle_crc_irq(x)
#endif
-#define MAX_COLOR_LUT_ENTRIES 256
+#define MAX_COLOR_LUT_ENTRIES 4096
+/* Legacy gamm LUT users such as X doesn't like large LUT sizes */
+#define MAX_COLOR_LEGACY_LUT_ENTRIES 256
void amdgpu_dm_init_color_mod(void);
int amdgpu_dm_set_degamma_lut(struct drm_crtc_state *crtc_state,
diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_color.c b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_color.c
index 62bb72fe9aa5..f6cb502c303f 100644
--- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_color.c
+++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_color.c
@@ -27,6 +27,8 @@
#include "amdgpu_dm.h"
#include "modules/color/color_gamma.h"
+#define MAX_DRM_LUT_VALUE 0xFFFF
+
/*
* Initialize the color module.
*
@@ -47,19 +49,18 @@ void amdgpu_dm_init_color_mod(void)
* f(a) = (0xFF00/MAX_COLOR_LUT_ENTRIES-1)a; for integer a in
* [0, MAX_COLOR_LUT_ENTRIES)
*/
-static bool __is_lut_linear(struct drm_color_lut *lut)
+static bool __is_lut_linear(struct drm_color_lut *lut, uint32_t size)
{
int i;
- uint32_t max_os = 0xFF00;
uint32_t expected;
int delta;
- for (i = 0; i < MAX_COLOR_LUT_ENTRIES; i++) {
+ for (i = 0; i < size; i++) {
/* All color values should equal */
if ((lut[i].red != lut[i].green) || (lut[i].green != lut[i].blue))
return false;
- expected = i * max_os / (MAX_COLOR_LUT_ENTRIES-1);
+ expected = i * MAX_DRM_LUT_VALUE / (size-1);
/* Allow a +/-1 error. */
delta = lut[i].red - expected;
@@ -70,6 +71,42 @@ static bool __is_lut_linear(struct drm_color_lut *lut)
}
/**
+ * Convert the drm_color_lut to dc_gamma. The conversion depends on the size
+ * of the lut - whether or not it's legacy.
+ */
+static void __drm_lut_to_dc_gamma(struct drm_color_lut *lut,
+ struct dc_gamma *gamma,
+ bool is_legacy)
+{
+ uint32_t r, g, b;
+ int i;
+
+ if (is_legacy) {
+ for (i = 0; i < MAX_COLOR_LEGACY_LUT_ENTRIES; i++) {
+ r = drm_color_lut_extract(lut[i].red, 16);
+ g = drm_color_lut_extract(lut[i].green, 16);
+ b = drm_color_lut_extract(lut[i].blue, 16);
+
+ gamma->entries.red[i] = dal_fixed31_32_from_int(r);
+ gamma->entries.green[i] = dal_fixed31_32_from_int(g);
+ gamma->entries.blue[i] = dal_fixed31_32_from_int(b);
+ }
+ return;
+ }
+
+ /* else */
+ for (i = 0; i < MAX_COLOR_LUT_ENTRIES; i++) {
+ r = drm_color_lut_extract(lut[i].red, 16);
+ g = drm_color_lut_extract(lut[i].green, 16);
+ b = drm_color_lut_extract(lut[i].blue, 16);
+
+ gamma->entries.red[i] = dal_fixed31_32_from_fraction(r, MAX_DRM_LUT_VALUE);
+ gamma->entries.green[i] = dal_fixed31_32_from_fraction(g, MAX_DRM_LUT_VALUE);
+ gamma->entries.blue[i] = dal_fixed31_32_from_fraction(b, MAX_DRM_LUT_VALUE);
+ }
+}
+
+/**
* amdgpu_dm_set_regamma_lut: Set regamma lut for the given CRTC.
* @crtc: amdgpu_dm crtc state
*
@@ -85,11 +122,10 @@ int amdgpu_dm_set_regamma_lut(struct dm_crtc_state *crtc)
struct drm_property_blob *blob = crtc->base.gamma_lut;
struct dc_stream_state *stream = crtc->stream;
struct drm_color_lut *lut;
+ uint32_t lut_size;
struct dc_gamma *gamma;
enum dc_transfer_func_type old_type = stream->out_transfer_func->type;
- uint32_t r, g, b;
- int i;
bool ret;
if (!blob) {
@@ -100,8 +136,9 @@ int amdgpu_dm_set_regamma_lut(struct dm_crtc_state *crtc)
}
lut = (struct drm_color_lut *)blob->data;
+ lut_size = blob->length / sizeof(struct drm_color_lut);
- if (__is_lut_linear(lut)) {
+ if (__is_lut_linear(lut, lut_size)) {
/* Set to bypass if lut is set to linear */
stream->out_transfer_func->type = TF_TYPE_BYPASS;
stream->out_transfer_func->tf = TRANSFER_FUNCTION_LINEAR;
@@ -112,20 +149,20 @@ int amdgpu_dm_set_regamma_lut(struct dm_crtc_state *crtc)
if (!gamma)
return -ENOMEM;
- gamma->num_entries = MAX_COLOR_LUT_ENTRIES;
- gamma->type = GAMMA_RGB_256;
-
- /* Truncate, and store in dc_gamma for output tf calculation */
- for (i = 0; i < gamma->num_entries; i++) {
- r = drm_color_lut_extract(lut[i].red, 16);
- g = drm_color_lut_extract(lut[i].green, 16);
- b = drm_color_lut_extract(lut[i].blue, 16);
-
- gamma->entries.red[i] = dal_fixed31_32_from_int(r);
- gamma->entries.green[i] = dal_fixed31_32_from_int(g);
- gamma->entries.blue[i] = dal_fixed31_32_from_int(b);
+ gamma->num_entries = lut_size;
+ if (gamma->num_entries == MAX_COLOR_LEGACY_LUT_ENTRIES)
+ gamma->type = GAMMA_RGB_256;
+ else if (gamma->num_entries == MAX_COLOR_LUT_ENTRIES)
+ gamma->type = GAMMA_CS_TFM_1D;
+ else {
+ /* Invalid lut size */
+ dc_gamma_release(&gamma);
+ return -EINVAL;
}
+ /* Convert drm_lut into dc_gamma */
+ __drm_lut_to_dc_gamma(lut, gamma, gamma->type == GAMMA_RGB_256);
+
/* Call color module to translate into something DC understands. Namely
* a transfer function.
*/
@@ -156,6 +193,7 @@ void amdgpu_dm_set_ctm(struct dm_crtc_state *crtc)
struct drm_property_blob *blob = crtc->base.ctm;
struct dc_stream_state *stream = crtc->stream;
struct drm_color_ctm *ctm;
+ int64_t val;
int i;
if (!blob) {
@@ -169,7 +207,9 @@ void amdgpu_dm_set_ctm(struct dm_crtc_state *crtc)
* DRM gives a 3x3 matrix, but DC wants 3x4. Assuming we're operating
* with homogeneous coordinates, augment the matrix with 0's.
*
- * The format provided is S31.32, which is the same as our fixed31_32.
+ * The format provided is S31.32, using signed-magnitude representation.
+ * Our fixed31_32 is also S31.32, but is using 2's complement. We have
+ * to convert from signed-magnitude to 2's complement.
*/
for (i = 0; i < 12; i++) {
/* Skip 4th element */
@@ -177,8 +217,14 @@ void amdgpu_dm_set_ctm(struct dm_crtc_state *crtc)
stream->gamut_remap_matrix.matrix[i] = dal_fixed31_32_zero;
continue;
}
- /* csc[i] = ctm[i - floor(i/4)] */
- stream->gamut_remap_matrix.matrix[i].value = ctm->matrix[i - (i/4)];
+
+ /* gamut_remap_matrix[i] = ctm[i - floor(i/4)] */
+ val = ctm->matrix[i - (i/4)];
+ /* If negative, convert to 2's complement. */
+ if (val & (1ULL << 63))
+ val = -(val & ~(1ULL << 63));
+
+ stream->gamut_remap_matrix.matrix[i].value = val;
}
}
@@ -212,7 +258,7 @@ int amdgpu_dm_set_degamma_lut(struct drm_crtc_state *crtc_state,
}
lut = (struct drm_color_lut *)blob->data;
- if (__is_lut_linear(lut)) {
+ if (__is_lut_linear(lut, MAX_COLOR_LUT_ENTRIES)) {
dc_plane_state->in_transfer_func->type = TF_TYPE_BYPASS;
dc_plane_state->in_transfer_func->tf = TRANSFER_FUNCTION_LINEAR;
return 0;
diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_helpers.c b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_helpers.c
index 9bd142f65f9b..9ab69b22b989 100644
--- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_helpers.c
+++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_helpers.c
@@ -258,6 +258,15 @@ bool dm_helpers_dp_mst_write_payload_allocation_table(
return true;
}
+
+/*
+ * Clear payload allocation table before enable MST DP link.
+ */
+void dm_helpers_dp_mst_clear_payload_allocation_table(
+ struct dc_context *ctx,
+ const struct dc_link *link)
+{}
+
/*
* Polls for ACT (allocation change trigger) handled and sends
* ALLOCATE_PAYLOAD message.
@@ -496,3 +505,8 @@ enum dc_edid_status dm_helpers_read_local_edid(
return edid_status;
}
+
+void dm_set_dcn_clocks(struct dc_context *ctx, struct dc_clocks *clks)
+{
+ /* TODO: something */
+}
diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_mst_types.c b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_mst_types.c
index 1e8a21b67df7..8291d74f26bc 100644
--- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_mst_types.c
+++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_mst_types.c
@@ -83,17 +83,21 @@ static ssize_t dm_dp_aux_transfer(struct drm_dp_aux *aux,
enum i2c_mot_mode mot = (msg->request & DP_AUX_I2C_MOT) ?
I2C_MOT_TRUE : I2C_MOT_FALSE;
enum ddc_result res;
+ ssize_t read_bytes;
+
+ if (WARN_ON(msg->size > 16))
+ return -E2BIG;
switch (msg->request & ~DP_AUX_I2C_MOT) {
case DP_AUX_NATIVE_READ:
- res = dal_ddc_service_read_dpcd_data(
+ read_bytes = dal_ddc_service_read_dpcd_data(
TO_DM_AUX(aux)->ddc_service,
false,
I2C_MOT_UNDEF,
msg->address,
msg->buffer,
msg->size);
- break;
+ return read_bytes;
case DP_AUX_NATIVE_WRITE:
res = dal_ddc_service_write_dpcd_data(
TO_DM_AUX(aux)->ddc_service,
@@ -104,14 +108,14 @@ static ssize_t dm_dp_aux_transfer(struct drm_dp_aux *aux,
msg->size);
break;
case DP_AUX_I2C_READ:
- res = dal_ddc_service_read_dpcd_data(
+ read_bytes = dal_ddc_service_read_dpcd_data(
TO_DM_AUX(aux)->ddc_service,
true,
mot,
msg->address,
msg->buffer,
msg->size);
- break;
+ return read_bytes;
case DP_AUX_I2C_WRITE:
res = dal_ddc_service_write_dpcd_data(
TO_DM_AUX(aux)->ddc_service,
diff --git a/drivers/gpu/drm/amd/display/dc/basics/logger.c b/drivers/gpu/drm/amd/display/dc/basics/logger.c
index 180a9d69d351..31bee054f43a 100644
--- a/drivers/gpu/drm/amd/display/dc/basics/logger.c
+++ b/drivers/gpu/drm/amd/display/dc/basics/logger.c
@@ -60,7 +60,8 @@ static const struct dc_log_type_info log_type_info_tbl[] = {
{LOG_EVENT_LINK_LOSS, "LinkLoss"},
{LOG_EVENT_UNDERFLOW, "Underflow"},
{LOG_IF_TRACE, "InterfaceTrace"},
- {LOG_DTN, "DTN"}
+ {LOG_DTN, "DTN"},
+ {LOG_PROFILING, "Profiling"}
};
diff --git a/drivers/gpu/drm/amd/display/dc/bios/bios_parser.c b/drivers/gpu/drm/amd/display/dc/bios/bios_parser.c
index 69c59e050a96..c7f0b27e457e 100644
--- a/drivers/gpu/drm/amd/display/dc/bios/bios_parser.c
+++ b/drivers/gpu/drm/amd/display/dc/bios/bios_parser.c
@@ -49,6 +49,9 @@
#define LAST_RECORD_TYPE 0xff
+#define DC_LOGGER \
+ bp->base.ctx->logger
+
/* GUID to validate external display connection info table (aka OPM module) */
static const uint8_t ext_display_connection_guid[NUMBER_OF_UCHAR_FOR_GUID] = {
0x91, 0x6E, 0x57, 0x09,
@@ -3079,8 +3082,7 @@ static enum bp_result patch_bios_image_from_ext_display_connection_info(
opm_object,
&ext_display_connection_info_tbl) != BP_RESULT_OK) {
- dm_logger_write(bp->base.ctx->logger, LOG_WARNING,
- "%s: Failed to read Connection Info Table", __func__);
+ DC_LOG_WARNING("%s: Failed to read Connection Info Table", __func__);
return BP_RESULT_UNSUPPORTED;
}
diff --git a/drivers/gpu/drm/amd/display/dc/bios/bios_parser2.c b/drivers/gpu/drm/amd/display/dc/bios/bios_parser2.c
index 1689c670ca6f..e7680c41f117 100644
--- a/drivers/gpu/drm/amd/display/dc/bios/bios_parser2.c
+++ b/drivers/gpu/drm/amd/display/dc/bios/bios_parser2.c
@@ -44,7 +44,7 @@
#include "bios_parser_common.h"
#define LAST_RECORD_TYPE 0xff
-
+#define SMU9_SYSPLL0_ID 0
struct i2c_id_config_access {
uint8_t bfI2C_LineMux:4;
@@ -1220,7 +1220,7 @@ static unsigned int bios_parser_get_smu_clock_info(
if (!bp->cmd_tbl.get_smu_clock_info)
return BP_RESULT_FAILURE;
- return bp->cmd_tbl.get_smu_clock_info(bp);
+ return bp->cmd_tbl.get_smu_clock_info(bp, 0);
}
static enum bp_result bios_parser_program_crtc_timing(
@@ -1376,7 +1376,7 @@ static enum bp_result get_firmware_info_v3_1(
if (bp->cmd_tbl.get_smu_clock_info != NULL) {
/* VBIOS gives in 10KHz */
info->smu_gpu_pll_output_freq =
- bp->cmd_tbl.get_smu_clock_info(bp) * 10;
+ bp->cmd_tbl.get_smu_clock_info(bp, SMU9_SYSPLL0_ID) * 10;
}
return BP_RESULT_OK;
diff --git a/drivers/gpu/drm/amd/display/dc/bios/command_table2.c b/drivers/gpu/drm/amd/display/dc/bios/command_table2.c
index fea5e83736fd..3f63f712c8a4 100644
--- a/drivers/gpu/drm/amd/display/dc/bios/command_table2.c
+++ b/drivers/gpu/drm/amd/display/dc/bios/command_table2.c
@@ -34,6 +34,8 @@
#include "command_table_helper2.h"
#include "bios_parser_helper.h"
#include "bios_parser_types_internal2.h"
+#define DC_LOGGER \
+ bp->base.ctx->logger
#define GET_INDEX_INTO_MASTER_TABLE(MasterOrData, FieldName)\
(((char *)(&((\
@@ -239,8 +241,7 @@ static enum bp_result transmitter_control_v1_6(
if (cntl->action == TRANSMITTER_CONTROL_ENABLE ||
cntl->action == TRANSMITTER_CONTROL_ACTIAVATE ||
cntl->action == TRANSMITTER_CONTROL_DEACTIVATE) {
- dm_logger_write(bp->base.ctx->logger, LOG_BIOS,\
- "%s:ps.param.symclk_10khz = %d\n",\
+ DC_LOG_BIOS("%s:ps.param.symclk_10khz = %d\n",\
__func__, ps.param.symclk_10khz);
}
@@ -331,8 +332,7 @@ static enum bp_result set_pixel_clock_v7(
(uint8_t) bp->cmd_helper->
transmitter_color_depth_to_atom(
bp_params->color_depth);
- dm_logger_write(bp->base.ctx->logger, LOG_BIOS,\
- "%s:program display clock = %d"\
+ DC_LOG_BIOS("%s:program display clock = %d"\
"colorDepth = %d\n", __func__,\
bp_params->target_pixel_clock, bp_params->color_depth);
@@ -772,8 +772,7 @@ static enum bp_result set_dce_clock_v2_1(
*/
params.param.dceclk_10khz = cpu_to_le32(
bp_params->target_clock_frequency / 10);
- dm_logger_write(bp->base.ctx->logger, LOG_BIOS,
- "%s:target_clock_frequency = %d"\
+ DC_LOG_BIOS("%s:target_clock_frequency = %d"\
"clock_type = %d \n", __func__,\
bp_params->target_clock_frequency,\
bp_params->clock_type);
@@ -797,7 +796,7 @@ static enum bp_result set_dce_clock_v2_1(
******************************************************************************
*****************************************************************************/
-static unsigned int get_smu_clock_info_v3_1(struct bios_parser *bp);
+static unsigned int get_smu_clock_info_v3_1(struct bios_parser *bp, uint8_t id);
static void init_get_smu_clock_info(struct bios_parser *bp)
{
@@ -806,12 +805,13 @@ static void init_get_smu_clock_info(struct bios_parser *bp)
}
-static unsigned int get_smu_clock_info_v3_1(struct bios_parser *bp)
+static unsigned int get_smu_clock_info_v3_1(struct bios_parser *bp, uint8_t id)
{
struct atom_get_smu_clock_info_parameters_v3_1 smu_input = {0};
struct atom_get_smu_clock_info_output_parameters_v3_1 smu_output;
smu_input.command = GET_SMU_CLOCK_INFO_V3_1_GET_PLLVCO_FREQ;
+ smu_input.syspll_id = id;
/* Get Specific Clock */
if (EXEC_BIOS_CMD_TABLE(getsmuclockinfo, smu_input)) {
diff --git a/drivers/gpu/drm/amd/display/dc/bios/command_table2.h b/drivers/gpu/drm/amd/display/dc/bios/command_table2.h
index 59061b806df5..ec1c0c9f3f1d 100644
--- a/drivers/gpu/drm/amd/display/dc/bios/command_table2.h
+++ b/drivers/gpu/drm/amd/display/dc/bios/command_table2.h
@@ -96,7 +96,7 @@ struct cmd_tbl {
struct bios_parser *bp,
struct bp_set_dce_clock_parameters *bp_params);
unsigned int (*get_smu_clock_info)(
- struct bios_parser *bp);
+ struct bios_parser *bp, uint8_t id);
};
diff --git a/drivers/gpu/drm/amd/display/dc/calcs/dce_calcs.c b/drivers/gpu/drm/amd/display/dc/calcs/dce_calcs.c
index 6d38b8f43198..0cbab81ab304 100644
--- a/drivers/gpu/drm/amd/display/dc/calcs/dce_calcs.c
+++ b/drivers/gpu/drm/amd/display/dc/calcs/dce_calcs.c
@@ -85,7 +85,6 @@ static void calculate_bandwidth(
const uint32_t s_mid5 = 5;
const uint32_t s_mid6 = 6;
const uint32_t s_high = 7;
- const uint32_t bus_efficiency = 1;
const uint32_t dmif_chunk_buff_margin = 1;
uint32_t max_chunks_fbc_mode;
@@ -592,7 +591,12 @@ static void calculate_bandwidth(
/* 1 = use channel 0 and 1*/
/* 2 = use channel 0,1,2,3*/
if ((fbc_enabled == 1 && lpt_enabled == 1)) {
- data->dram_efficiency = bw_int_to_fixed(1);
+ if (vbios->memory_type == bw_def_hbm)
+ data->dram_efficiency = bw_frc_to_fixed(5, 10);
+ else
+ data->dram_efficiency = bw_int_to_fixed(1);
+
+
if (dceip->low_power_tiling_mode == 0) {
data->number_of_dram_channels = 1;
}
@@ -607,7 +611,10 @@ static void calculate_bandwidth(
}
}
else {
- data->dram_efficiency = bw_frc_to_fixed(8, 10);
+ if (vbios->memory_type == bw_def_hbm)
+ data->dram_efficiency = bw_frc_to_fixed(5, 10);
+ else
+ data->dram_efficiency = bw_frc_to_fixed(8, 10);
}
/*memory request size and latency hiding:*/
/*request size is normally 64 byte, 2-line interleaved, with full latency hiding*/
@@ -1171,9 +1178,9 @@ static void calculate_bandwidth(
}
for (i = 0; i <= 2; i++) {
for (j = 0; j <= 7; j++) {
- data->dmif_burst_time[i][j] = bw_max3(data->dmif_total_page_close_open_time, bw_div(data->total_display_reads_required_dram_access_data, (bw_mul(bw_div(bw_mul(bw_mul(data->dram_efficiency, yclk[i]), bw_int_to_fixed(vbios->dram_channel_width_in_bits)), bw_int_to_fixed(8)), bw_int_to_fixed(data->number_of_dram_channels)))), bw_div(data->total_display_reads_required_data, (bw_mul(bw_mul(sclk[j], vbios->data_return_bus_width), bw_int_to_fixed(bus_efficiency)))));
+ data->dmif_burst_time[i][j] = bw_max3(data->dmif_total_page_close_open_time, bw_div(data->total_display_reads_required_dram_access_data, (bw_mul(bw_div(bw_mul(bw_mul(data->dram_efficiency, yclk[i]), bw_int_to_fixed(vbios->dram_channel_width_in_bits)), bw_int_to_fixed(8)), bw_int_to_fixed(data->number_of_dram_channels)))), bw_div(data->total_display_reads_required_data, (bw_mul(bw_mul(sclk[j], vbios->data_return_bus_width), bw_frc_to_fixed(dceip->percent_of_ideal_port_bw_received_after_urgent_latency, 100)))));
if (data->d1_display_write_back_dwb_enable == 1) {
- data->mcifwr_burst_time[i][j] = bw_max3(data->mcifwr_total_page_close_open_time, bw_div(data->total_display_writes_required_dram_access_data, (bw_mul(bw_div(bw_mul(bw_mul(data->dram_efficiency, yclk[i]), bw_int_to_fixed(vbios->dram_channel_width_in_bits)), bw_int_to_fixed(8)), bw_int_to_fixed(data->number_of_dram_wrchannels)))), bw_div(data->total_display_writes_required_data, (bw_mul(bw_mul(sclk[j], vbios->data_return_bus_width), bw_int_to_fixed(bus_efficiency)))));
+ data->mcifwr_burst_time[i][j] = bw_max3(data->mcifwr_total_page_close_open_time, bw_div(data->total_display_writes_required_dram_access_data, (bw_mul(bw_div(bw_mul(bw_mul(data->dram_efficiency, yclk[i]), bw_int_to_fixed(vbios->dram_channel_width_in_bits)), bw_int_to_fixed(8)), bw_int_to_fixed(data->number_of_dram_wrchannels)))), bw_div(data->total_display_writes_required_data, (bw_mul(sclk[j], vbios->data_return_bus_width))));
}
}
}
@@ -1258,6 +1265,16 @@ static void calculate_bandwidth(
/* / (dispclk - display bw)*/
/*the minimum latency hiding is the minimum for all pipes of one screen line time, plus one more line time if doing lb prefetch, plus the dmif data buffer size equivalent in time, minus the urgent latency.*/
/*the minimum latency hiding is further limited by the cursor. the cursor latency hiding is the number of lines of the cursor buffer, minus one if the downscaling is less than two, or minus three if it is more*/
+
+ /*initialize variables*/
+ number_of_displays_enabled = 0;
+ number_of_displays_enabled_with_margin = 0;
+ for (k = 0; k <= maximum_number_of_surfaces - 1; k++) {
+ if (data->enable[k]) {
+ number_of_displays_enabled = number_of_displays_enabled + 1;
+ }
+ data->display_pstate_change_enable[k] = 0;
+ }
for (i = 0; i <= maximum_number_of_surfaces - 1; i++) {
if (data->enable[i]) {
if ((bw_equ(dceip->stutter_and_dram_clock_state_change_gated_before_cursor, bw_int_to_fixed(0)) && bw_mtn(data->cursor_width_pixels[i], bw_int_to_fixed(0)))) {
@@ -1276,7 +1293,10 @@ static void calculate_bandwidth(
for (i = 0; i <= maximum_number_of_surfaces - 1; i++) {
if (data->enable[i]) {
if (dceip->graphics_lb_nodownscaling_multi_line_prefetching == 1 && (bw_equ(data->vsr[i], bw_int_to_fixed(1)) || (bw_leq(data->vsr[i], bw_frc_to_fixed(8, 10)) && bw_leq(data->v_taps[i], bw_int_to_fixed(2)) && data->lb_bpc[i] == 8)) && surface_type[i] == bw_def_graphics) {
- data->minimum_latency_hiding[i] = bw_sub(bw_div(bw_mul((bw_div((bw_add(bw_sub(data->lb_partitions[i], bw_int_to_fixed(1)), bw_div(bw_div(data->data_buffer_size[i], bw_int_to_fixed(data->bytes_per_pixel[i])), data->source_width_pixels[i]))), data->vsr[i])), data->h_total[i]), data->pixel_rate[i]), data->total_dmifmc_urgent_latency);
+ if (number_of_displays_enabled > 2)
+ data->minimum_latency_hiding[i] = bw_sub(bw_div(bw_mul((bw_div((bw_add(bw_sub(data->lb_partitions[i], bw_int_to_fixed(2)), bw_div(bw_div(data->data_buffer_size[i], bw_int_to_fixed(data->bytes_per_pixel[i])), data->source_width_pixels[i]))), data->vsr[i])), data->h_total[i]), data->pixel_rate[i]), data->total_dmifmc_urgent_latency);
+ else
+ data->minimum_latency_hiding[i] = bw_sub(bw_div(bw_mul((bw_div((bw_add(bw_sub(data->lb_partitions[i], bw_int_to_fixed(1)), bw_div(bw_div(data->data_buffer_size[i], bw_int_to_fixed(data->bytes_per_pixel[i])), data->source_width_pixels[i]))), data->vsr[i])), data->h_total[i]), data->pixel_rate[i]), data->total_dmifmc_urgent_latency);
}
else {
data->minimum_latency_hiding[i] = bw_sub(bw_div(bw_mul((bw_div((bw_add(bw_int_to_fixed(1 + data->line_buffer_prefetch[i]), bw_div(bw_div(data->data_buffer_size[i], bw_int_to_fixed(data->bytes_per_pixel[i])), data->source_width_pixels[i]))), data->vsr[i])), data->h_total[i]), data->pixel_rate[i]), data->total_dmifmc_urgent_latency);
@@ -1338,24 +1358,15 @@ static void calculate_bandwidth(
for (i = 0; i <= maximum_number_of_surfaces - 1; i++) {
if (data->enable[i]) {
if (dceip->graphics_lb_nodownscaling_multi_line_prefetching == 1) {
- data->maximum_latency_hiding[i] = bw_add(data->minimum_latency_hiding[i], bw_mul(bw_frc_to_fixed(8, 10), data->total_dmifmc_urgent_latency));
+ data->maximum_latency_hiding[i] = bw_add(data->minimum_latency_hiding[i], bw_mul(bw_frc_to_fixed(5, 10), data->total_dmifmc_urgent_latency));
}
else {
/*maximum_latency_hiding(i) = minimum_latency_hiding(i) + 1 / vsr(i) * h_total(i) / pixel_rate(i) + 0.5 * total_dmifmc_urgent_latency*/
- data->maximum_latency_hiding[i] = bw_add(data->minimum_latency_hiding[i], bw_mul(bw_frc_to_fixed(8, 10), data->total_dmifmc_urgent_latency));
+ data->maximum_latency_hiding[i] = bw_add(data->minimum_latency_hiding[i], bw_mul(bw_frc_to_fixed(5, 10), data->total_dmifmc_urgent_latency));
}
data->maximum_latency_hiding_with_cursor[i] = bw_min2(data->maximum_latency_hiding[i], data->cursor_latency_hiding[i]);
}
}
- /*initialize variables*/
- number_of_displays_enabled = 0;
- number_of_displays_enabled_with_margin = 0;
- for (k = 0; k <= maximum_number_of_surfaces - 1; k++) {
- if (data->enable[k]) {
- number_of_displays_enabled = number_of_displays_enabled + 1;
- }
- data->display_pstate_change_enable[k] = 0;
- }
for (i = 0; i <= 2; i++) {
for (j = 0; j <= 7; j++) {
data->min_dram_speed_change_margin[i][j] = bw_int_to_fixed(9999);
@@ -1370,10 +1381,11 @@ static void calculate_bandwidth(
/*determine the minimum dram clock change margin for each set of clock frequencies*/
data->min_dram_speed_change_margin[i][j] = bw_min2(data->min_dram_speed_change_margin[i][j], data->dram_speed_change_margin);
/*compute the maximum clock frequuency required for the dram clock change at each set of clock frequencies*/
- data->dispclk_required_for_dram_speed_change[i][j] = bw_max3(data->dispclk_required_for_dram_speed_change[i][j], bw_div(bw_div(bw_mul(data->src_pixels_for_first_output_pixel[k], dceip->display_pipe_throughput_factor), dceip->lb_write_pixels_per_dispclk), (bw_sub(bw_sub(bw_sub(data->maximum_latency_hiding_with_cursor[k], vbios->nbp_state_change_latency), data->dmif_burst_time[i][j]), data->dram_speed_change_line_source_transfer_time[k][i][j]))), bw_div(bw_div(bw_mul(data->src_pixels_for_last_output_pixel[k], dceip->display_pipe_throughput_factor), dceip->lb_write_pixels_per_dispclk), (bw_add(bw_sub(bw_sub(bw_sub(data->maximum_latency_hiding_with_cursor[k], vbios->nbp_state_change_latency), data->dmif_burst_time[i][j]), data->dram_speed_change_line_source_transfer_time[k][i][j]), data->active_time[k]))));
- if ((bw_ltn(data->dispclk_required_for_dram_speed_change[i][j], vbios->high_voltage_max_dispclk))) {
+ data->dispclk_required_for_dram_speed_change_pipe[i][j] = bw_max2(bw_div(bw_div(bw_mul(data->src_pixels_for_first_output_pixel[k], dceip->display_pipe_throughput_factor), dceip->lb_write_pixels_per_dispclk), (bw_sub(bw_sub(bw_sub(data->maximum_latency_hiding_with_cursor[k], vbios->nbp_state_change_latency), data->dmif_burst_time[i][j]), data->dram_speed_change_line_source_transfer_time[k][i][j]))), bw_div(bw_div(bw_mul(data->src_pixels_for_last_output_pixel[k], dceip->display_pipe_throughput_factor), dceip->lb_write_pixels_per_dispclk), (bw_add(bw_sub(bw_sub(bw_sub(data->maximum_latency_hiding_with_cursor[k], vbios->nbp_state_change_latency), data->dmif_burst_time[i][j]), data->dram_speed_change_line_source_transfer_time[k][i][j]), data->active_time[k]))));
+ if ((bw_ltn(data->dispclk_required_for_dram_speed_change_pipe[i][j], vbios->high_voltage_max_dispclk))) {
data->display_pstate_change_enable[k] = 1;
data->num_displays_with_margin[i][j] = data->num_displays_with_margin[i][j] + 1;
+ data->dispclk_required_for_dram_speed_change[i][j] = bw_max2(data->dispclk_required_for_dram_speed_change[i][j], data->dispclk_required_for_dram_speed_change_pipe[i][j]);
}
}
}
@@ -1383,10 +1395,11 @@ static void calculate_bandwidth(
/*determine the minimum dram clock change margin for each display pipe*/
data->min_dram_speed_change_margin[i][j] = bw_min2(data->min_dram_speed_change_margin[i][j], data->dram_speed_change_margin);
/*compute the maximum clock frequuency required for the dram clock change at each set of clock frequencies*/
- data->dispclk_required_for_dram_speed_change[i][j] = bw_max3(data->dispclk_required_for_dram_speed_change[i][j], bw_div(bw_div(bw_mul(data->src_pixels_for_first_output_pixel[k], dceip->display_pipe_throughput_factor), dceip->lb_write_pixels_per_dispclk), (bw_sub(bw_sub(bw_sub(bw_sub(data->maximum_latency_hiding_with_cursor[k], vbios->nbp_state_change_latency), data->dmif_burst_time[i][j]), data->dram_speed_change_line_source_transfer_time[k][i][j]), data->mcifwr_burst_time[i][j]))), bw_div(bw_div(bw_mul(data->src_pixels_for_last_output_pixel[k], dceip->display_pipe_throughput_factor), dceip->lb_write_pixels_per_dispclk), (bw_add(bw_sub(bw_sub(bw_sub(bw_sub(data->maximum_latency_hiding_with_cursor[k], vbios->nbp_state_change_latency), data->dmif_burst_time[i][j]), data->dram_speed_change_line_source_transfer_time[k][i][j]), data->mcifwr_burst_time[i][j]), data->active_time[k]))));
- if ((bw_ltn(data->dispclk_required_for_dram_speed_change[i][j], vbios->high_voltage_max_dispclk))) {
+ data->dispclk_required_for_dram_speed_change_pipe[i][j] = bw_max2(bw_div(bw_div(bw_mul(data->src_pixels_for_first_output_pixel[k], dceip->display_pipe_throughput_factor), dceip->lb_write_pixels_per_dispclk), (bw_sub(bw_sub(bw_sub(bw_sub(data->maximum_latency_hiding_with_cursor[k], vbios->nbp_state_change_latency), data->dmif_burst_time[i][j]), data->dram_speed_change_line_source_transfer_time[k][i][j]), data->mcifwr_burst_time[i][j]))), bw_div(bw_div(bw_mul(data->src_pixels_for_last_output_pixel[k], dceip->display_pipe_throughput_factor), dceip->lb_write_pixels_per_dispclk), (bw_add(bw_sub(bw_sub(bw_sub(bw_sub(data->maximum_latency_hiding_with_cursor[k], vbios->nbp_state_change_latency), data->dmif_burst_time[i][j]), data->dram_speed_change_line_source_transfer_time[k][i][j]), data->mcifwr_burst_time[i][j]), data->active_time[k]))));
+ if ((bw_ltn(data->dispclk_required_for_dram_speed_change_pipe[i][j], vbios->high_voltage_max_dispclk))) {
data->display_pstate_change_enable[k] = 1;
data->num_displays_with_margin[i][j] = data->num_displays_with_margin[i][j] + 1;
+ data->dispclk_required_for_dram_speed_change[i][j] = bw_max2(data->dispclk_required_for_dram_speed_change[i][j], data->dispclk_required_for_dram_speed_change_pipe[i][j]);
}
}
}
@@ -1420,7 +1433,7 @@ static void calculate_bandwidth(
data->displays_with_same_mode[i] = bw_int_to_fixed(0);
if (data->enable[i] == 1 && data->display_pstate_change_enable[i] == 0 && bw_mtn(data->v_blank_dram_speed_change_margin[i], bw_int_to_fixed(0))) {
for (j = 0; j <= maximum_number_of_surfaces - 1; j++) {
- if ((data->enable[j] == 1 && bw_equ(data->source_width_rounded_up_to_chunks[i], data->source_width_rounded_up_to_chunks[j]) && bw_equ(data->source_height_rounded_up_to_chunks[i], data->source_height_rounded_up_to_chunks[j]) && bw_equ(data->vsr[i], data->vsr[j]) && bw_equ(data->hsr[i], data->hsr[j]) && bw_equ(data->pixel_rate[i], data->pixel_rate[j]))) {
+ if ((i == j || data->display_synchronization_enabled) && (data->enable[j] == 1 && bw_equ(data->source_width_rounded_up_to_chunks[i], data->source_width_rounded_up_to_chunks[j]) && bw_equ(data->source_height_rounded_up_to_chunks[i], data->source_height_rounded_up_to_chunks[j]) && bw_equ(data->vsr[i], data->vsr[j]) && bw_equ(data->hsr[i], data->hsr[j]) && bw_equ(data->pixel_rate[i], data->pixel_rate[j]))) {
data->displays_with_same_mode[i] = bw_add(data->displays_with_same_mode[i], bw_int_to_fixed(1));
}
}
@@ -1435,7 +1448,7 @@ static void calculate_bandwidth(
/*aligned displays with the same timing.*/
/*the display(s) with the negative margin can be switched in the v_blank region while the other*/
/*displays are in v_blank or v_active.*/
- if ((number_of_displays_enabled_with_margin + number_of_aligned_displays_with_no_margin == number_of_displays_enabled && bw_mtn(data->min_dram_speed_change_margin[high][s_high], bw_int_to_fixed(0)) && bw_ltn(data->min_dram_speed_change_margin[high][s_high], bw_int_to_fixed(9999)) && bw_ltn(data->dispclk_required_for_dram_speed_change[high][s_high], vbios->high_voltage_max_dispclk))) {
+ if (number_of_displays_enabled_with_margin > 0 && (number_of_displays_enabled_with_margin + number_of_aligned_displays_with_no_margin) == number_of_displays_enabled && bw_mtn(data->min_dram_speed_change_margin[high][s_high], bw_int_to_fixed(0)) && bw_ltn(data->min_dram_speed_change_margin[high][s_high], bw_int_to_fixed(9999)) && bw_ltn(data->dispclk_required_for_dram_speed_change[high][s_high], vbios->high_voltage_max_dispclk)) {
data->nbp_state_change_enable = bw_def_yes;
}
else {
@@ -1448,6 +1461,25 @@ static void calculate_bandwidth(
else {
nbp_state_change_enable_blank = bw_def_no;
}
+
+ /*average bandwidth*/
+ /*the average bandwidth with no compression is the vertical active time is the source width times the bytes per pixel divided by the line time, multiplied by the vertical scale ratio and the ratio of bytes per request divided by the useful bytes per request.*/
+ /*the average bandwidth with compression is the same, divided by the compression ratio*/
+ for (i = 0; i <= maximum_number_of_surfaces - 1; i++) {
+ if (data->enable[i]) {
+ data->average_bandwidth_no_compression[i] = bw_div(bw_mul(bw_mul(bw_div(bw_mul(data->source_width_rounded_up_to_chunks[i], bw_int_to_fixed(data->bytes_per_pixel[i])), (bw_div(data->h_total[i], data->pixel_rate[i]))), data->vsr[i]), data->bytes_per_request[i]), data->useful_bytes_per_request[i]);
+ data->average_bandwidth[i] = bw_div(data->average_bandwidth_no_compression[i], data->compression_rate[i]);
+ }
+ }
+ data->total_average_bandwidth_no_compression = bw_int_to_fixed(0);
+ data->total_average_bandwidth = bw_int_to_fixed(0);
+ for (i = 0; i <= maximum_number_of_surfaces - 1; i++) {
+ if (data->enable[i]) {
+ data->total_average_bandwidth_no_compression = bw_add(data->total_average_bandwidth_no_compression, data->average_bandwidth_no_compression[i]);
+ data->total_average_bandwidth = bw_add(data->total_average_bandwidth, data->average_bandwidth[i]);
+ }
+ }
+
/*required yclk(pclk)*/
/*yclk requirement only makes sense if the dmif and mcifwr data total page close-open time is less than the time for data transfer and the total pte requests fit in the scatter-gather saw queque size*/
/*if that is the case, the yclk requirement is the maximum of the ones required by dmif and mcifwr, and the high/low yclk(pclk) is chosen accordingly*/
@@ -1497,17 +1529,20 @@ static void calculate_bandwidth(
}
else {
data->required_dram_bandwidth_gbyte_per_second = bw_div(bw_max2(data->dmif_required_dram_bandwidth, data->mcifwr_required_dram_bandwidth), bw_int_to_fixed(1000));
- if (bw_ltn(bw_mul(data->required_dram_bandwidth_gbyte_per_second, bw_int_to_fixed(1000)), bw_mul(bw_div(bw_mul(bw_mul(data->dram_efficiency, yclk[low]), bw_int_to_fixed(vbios->dram_channel_width_in_bits)), bw_int_to_fixed(8)), bw_int_to_fixed(data->number_of_dram_channels))) && (data->cpup_state_change_enable == bw_def_no || (bw_mtn(data->blackout_duration_margin[low][s_high], bw_int_to_fixed(0)) && bw_ltn(data->dispclk_required_for_blackout_duration[low][s_high], vbios->high_voltage_max_dispclk))) && (data->cpuc_state_change_enable == bw_def_no || (bw_mtn(data->blackout_duration_margin[low][s_high], bw_int_to_fixed(0)) && bw_ltn(data->dispclk_required_for_blackout_duration[low][s_high], vbios->high_voltage_max_dispclk) && bw_ltn(data->dispclk_required_for_blackout_recovery[low][s_high], vbios->high_voltage_max_dispclk))) && (data->nbp_state_change_enable == bw_def_no || (bw_mtn(data->min_dram_speed_change_margin[low][s_high], bw_int_to_fixed(0)) && bw_ltn(data->min_dram_speed_change_margin[low][s_high], bw_int_to_fixed(9999)) && bw_leq(data->dispclk_required_for_dram_speed_change[low][s_high], vbios->high_voltage_max_dispclk) && data->num_displays_with_margin[low][s_high] == number_of_displays_enabled_with_margin))) {
+ if (bw_ltn(data->total_average_bandwidth_no_compression, bw_mul(bw_mul(bw_mul(bw_frc_to_fixed(dceip->max_average_percent_of_ideal_drambw_display_can_use_in_normal_system_operation, 100),yclk[low]),bw_div(bw_int_to_fixed(vbios->dram_channel_width_in_bits),bw_int_to_fixed(8))),bw_int_to_fixed(vbios->number_of_dram_channels)))
+ && bw_ltn(bw_mul(data->required_dram_bandwidth_gbyte_per_second, bw_int_to_fixed(1000)), bw_mul(bw_div(bw_mul(bw_mul(data->dram_efficiency, yclk[low]), bw_int_to_fixed(vbios->dram_channel_width_in_bits)), bw_int_to_fixed(8)), bw_int_to_fixed(data->number_of_dram_channels))) && (data->cpup_state_change_enable == bw_def_no || (bw_mtn(data->blackout_duration_margin[low][s_high], bw_int_to_fixed(0)) && bw_ltn(data->dispclk_required_for_blackout_duration[low][s_high], vbios->high_voltage_max_dispclk))) && (data->cpuc_state_change_enable == bw_def_no || (bw_mtn(data->blackout_duration_margin[low][s_high], bw_int_to_fixed(0)) && bw_ltn(data->dispclk_required_for_blackout_duration[low][s_high], vbios->high_voltage_max_dispclk) && bw_ltn(data->dispclk_required_for_blackout_recovery[low][s_high], vbios->high_voltage_max_dispclk))) && (!data->increase_voltage_to_support_mclk_switch || data->nbp_state_change_enable == bw_def_no || (bw_mtn(data->min_dram_speed_change_margin[low][s_high], bw_int_to_fixed(0)) && bw_ltn(data->min_dram_speed_change_margin[low][s_high], bw_int_to_fixed(9999)) && bw_leq(data->dispclk_required_for_dram_speed_change[low][s_high], vbios->high_voltage_max_dispclk) && data->num_displays_with_margin[low][s_high] == number_of_displays_enabled_with_margin))) {
yclk_message = bw_fixed_to_int(vbios->low_yclk);
data->y_clk_level = low;
data->dram_bandwidth = bw_mul(bw_div(bw_mul(bw_mul(data->dram_efficiency, yclk[low]), bw_int_to_fixed(vbios->dram_channel_width_in_bits)), bw_int_to_fixed(8)), bw_int_to_fixed(data->number_of_dram_channels));
}
- else if (bw_ltn(bw_mul(data->required_dram_bandwidth_gbyte_per_second, bw_int_to_fixed(1000)), bw_mul(bw_div(bw_mul(bw_mul(data->dram_efficiency, yclk[mid]), bw_int_to_fixed(vbios->dram_channel_width_in_bits)), bw_int_to_fixed(8)), bw_int_to_fixed(data->number_of_dram_channels))) && (data->cpup_state_change_enable == bw_def_no || (bw_mtn(data->blackout_duration_margin[mid][s_high], bw_int_to_fixed(0)) && bw_ltn(data->dispclk_required_for_blackout_duration[mid][s_high], vbios->high_voltage_max_dispclk))) && (data->cpuc_state_change_enable == bw_def_no || (bw_mtn(data->blackout_duration_margin[mid][s_high], bw_int_to_fixed(0)) && bw_ltn(data->dispclk_required_for_blackout_duration[mid][s_high], vbios->high_voltage_max_dispclk) && bw_ltn(data->dispclk_required_for_blackout_recovery[mid][s_high], vbios->high_voltage_max_dispclk))) && (data->nbp_state_change_enable == bw_def_no || (bw_mtn(data->min_dram_speed_change_margin[mid][s_high], bw_int_to_fixed(0)) && bw_ltn(data->min_dram_speed_change_margin[mid][s_high], bw_int_to_fixed(9999)) && bw_leq(data->dispclk_required_for_dram_speed_change[mid][s_high], vbios->high_voltage_max_dispclk) && data->num_displays_with_margin[mid][s_high] == number_of_displays_enabled_with_margin))) {
+ else if (bw_ltn(data->total_average_bandwidth_no_compression, bw_mul(bw_mul(bw_mul(bw_frc_to_fixed(dceip->max_average_percent_of_ideal_drambw_display_can_use_in_normal_system_operation, 100),yclk[mid]),bw_div(bw_int_to_fixed(vbios->dram_channel_width_in_bits),bw_int_to_fixed(8))),bw_int_to_fixed(vbios->number_of_dram_channels)))
+ && bw_ltn(bw_mul(data->required_dram_bandwidth_gbyte_per_second, bw_int_to_fixed(1000)), bw_mul(bw_div(bw_mul(bw_mul(data->dram_efficiency, yclk[mid]), bw_int_to_fixed(vbios->dram_channel_width_in_bits)), bw_int_to_fixed(8)), bw_int_to_fixed(data->number_of_dram_channels))) && (data->cpup_state_change_enable == bw_def_no || (bw_mtn(data->blackout_duration_margin[mid][s_high], bw_int_to_fixed(0)) && bw_ltn(data->dispclk_required_for_blackout_duration[mid][s_high], vbios->high_voltage_max_dispclk))) && (data->cpuc_state_change_enable == bw_def_no || (bw_mtn(data->blackout_duration_margin[mid][s_high], bw_int_to_fixed(0)) && bw_ltn(data->dispclk_required_for_blackout_duration[mid][s_high], vbios->high_voltage_max_dispclk) && bw_ltn(data->dispclk_required_for_blackout_recovery[mid][s_high], vbios->high_voltage_max_dispclk))) && (!data->increase_voltage_to_support_mclk_switch || data->nbp_state_change_enable == bw_def_no || (bw_mtn(data->min_dram_speed_change_margin[mid][s_high], bw_int_to_fixed(0)) && bw_ltn(data->min_dram_speed_change_margin[mid][s_high], bw_int_to_fixed(9999)) && bw_leq(data->dispclk_required_for_dram_speed_change[mid][s_high], vbios->high_voltage_max_dispclk) && data->num_displays_with_margin[mid][s_high] == number_of_displays_enabled_with_margin))) {
yclk_message = bw_fixed_to_int(vbios->mid_yclk);
data->y_clk_level = mid;
data->dram_bandwidth = bw_mul(bw_div(bw_mul(bw_mul(data->dram_efficiency, yclk[mid]), bw_int_to_fixed(vbios->dram_channel_width_in_bits)), bw_int_to_fixed(8)), bw_int_to_fixed(data->number_of_dram_channels));
}
- else if (bw_ltn(bw_mul(data->required_dram_bandwidth_gbyte_per_second, bw_int_to_fixed(1000)), bw_mul(bw_div(bw_mul(bw_mul(data->dram_efficiency, yclk[high]), bw_int_to_fixed(vbios->dram_channel_width_in_bits)), bw_int_to_fixed(8)), bw_int_to_fixed(data->number_of_dram_channels)))) {
+ else if (bw_ltn(data->total_average_bandwidth_no_compression, bw_mul(bw_mul(bw_mul(bw_frc_to_fixed(dceip->max_average_percent_of_ideal_drambw_display_can_use_in_normal_system_operation, 100),yclk[high]),bw_div(bw_int_to_fixed(vbios->dram_channel_width_in_bits),bw_int_to_fixed(8))),bw_int_to_fixed(vbios->number_of_dram_channels)))
+ && bw_ltn(bw_mul(data->required_dram_bandwidth_gbyte_per_second, bw_int_to_fixed(1000)), bw_mul(bw_div(bw_mul(bw_mul(data->dram_efficiency, yclk[high]), bw_int_to_fixed(vbios->dram_channel_width_in_bits)), bw_int_to_fixed(8)), bw_int_to_fixed(data->number_of_dram_channels)))) {
yclk_message = bw_fixed_to_int(vbios->high_yclk);
data->y_clk_level = high;
data->dram_bandwidth = bw_mul(bw_div(bw_mul(bw_mul(data->dram_efficiency, yclk[high]), bw_int_to_fixed(vbios->dram_channel_width_in_bits)), bw_int_to_fixed(8)), bw_int_to_fixed(data->number_of_dram_channels));
@@ -1523,8 +1558,8 @@ static void calculate_bandwidth(
/*if that is the case, the sclk requirement is the maximum of the ones required by dmif and mcifwr, and the high/mid/low sclk is chosen accordingly, unless that choice results in foresaking dram speed/nb p-state change.*/
/*the dmif and mcifwr sclk required is the one that allows the transfer of all pipe's data buffer size through the sclk bus in the time for data transfer*/
/*for dmif, pte and cursor requests have to be included.*/
- data->dmif_required_sclk = bw_div(bw_div(data->total_display_reads_required_data, data->display_reads_time_for_data_transfer), (bw_mul(vbios->data_return_bus_width, bw_int_to_fixed(bus_efficiency))));
- data->mcifwr_required_sclk = bw_div(bw_div(data->total_display_writes_required_data, data->display_writes_time_for_data_transfer), (bw_mul(vbios->data_return_bus_width, bw_int_to_fixed(bus_efficiency))));
+ data->dmif_required_sclk = bw_div(bw_div(data->total_display_reads_required_data, data->display_reads_time_for_data_transfer), (bw_mul(vbios->data_return_bus_width, bw_frc_to_fixed(dceip->percent_of_ideal_port_bw_received_after_urgent_latency, 100))));
+ data->mcifwr_required_sclk = bw_div(bw_div(data->total_display_writes_required_data, data->display_writes_time_for_data_transfer), vbios->data_return_bus_width);
if (bw_mtn(data->scatter_gather_total_pte_requests, dceip->maximum_total_outstanding_pte_requests_allowed_by_saw)) {
data->required_sclk = bw_int_to_fixed(9999);
sclk_message = bw_def_exceeded_allowed_outstanding_pte_req_queue_size;
@@ -1537,42 +1572,56 @@ static void calculate_bandwidth(
}
else {
data->required_sclk = bw_max2(data->dmif_required_sclk, data->mcifwr_required_sclk);
- if (bw_ltn(data->required_sclk, sclk[s_low]) && (data->cpup_state_change_enable == bw_def_no || (bw_mtn(data->blackout_duration_margin[data->y_clk_level][s_low], bw_int_to_fixed(0)) && bw_ltn(data->dispclk_required_for_blackout_duration[data->y_clk_level][s_low], vbios->high_voltage_max_dispclk))) && (data->cpuc_state_change_enable == bw_def_no || (bw_mtn(data->blackout_duration_margin[data->y_clk_level][s_low], bw_int_to_fixed(0)) && bw_ltn(data->dispclk_required_for_blackout_duration[data->y_clk_level][s_low], vbios->high_voltage_max_dispclk) && bw_ltn(data->dispclk_required_for_blackout_recovery[data->y_clk_level][s_low], vbios->high_voltage_max_dispclk))) && (data->nbp_state_change_enable == bw_def_no || (bw_mtn(data->min_dram_speed_change_margin[data->y_clk_level][s_low], bw_int_to_fixed(0)) && bw_ltn(data->min_dram_speed_change_margin[data->y_clk_level][s_low], bw_int_to_fixed(9999)) && bw_leq(data->dispclk_required_for_dram_speed_change[data->y_clk_level][s_low], vbios->low_voltage_max_dispclk) && data->num_displays_with_margin[data->y_clk_level][s_low] == number_of_displays_enabled_with_margin))) {
+ if (bw_ltn(data->total_average_bandwidth_no_compression, bw_mul(bw_mul(bw_frc_to_fixed(dceip->max_average_percent_of_ideal_port_bw_display_can_use_in_normal_system_operation, 100),sclk[low]),vbios->data_return_bus_width))
+ && bw_ltn(data->required_sclk, sclk[s_low]) && (data->cpup_state_change_enable == bw_def_no || (bw_mtn(data->blackout_duration_margin[data->y_clk_level][s_low], bw_int_to_fixed(0)) && bw_ltn(data->dispclk_required_for_blackout_duration[data->y_clk_level][s_low], vbios->high_voltage_max_dispclk))) && (data->cpuc_state_change_enable == bw_def_no || (bw_mtn(data->blackout_duration_margin[data->y_clk_level][s_low], bw_int_to_fixed(0)) && bw_ltn(data->dispclk_required_for_blackout_duration[data->y_clk_level][s_low], vbios->high_voltage_max_dispclk) && bw_ltn(data->dispclk_required_for_blackout_recovery[data->y_clk_level][s_low], vbios->high_voltage_max_dispclk))) && (!data->increase_voltage_to_support_mclk_switch || data->nbp_state_change_enable == bw_def_no || (bw_mtn(data->min_dram_speed_change_margin[data->y_clk_level][s_low], bw_int_to_fixed(0)) && bw_ltn(data->min_dram_speed_change_margin[data->y_clk_level][s_low], bw_int_to_fixed(9999)) && bw_leq(data->dispclk_required_for_dram_speed_change[data->y_clk_level][s_low], vbios->low_voltage_max_dispclk) && data->num_displays_with_margin[data->y_clk_level][s_low] == number_of_displays_enabled_with_margin))) {
sclk_message = bw_def_low;
data->sclk_level = s_low;
data->required_sclk = vbios->low_sclk;
}
- else if (bw_ltn(data->required_sclk, sclk[s_mid1]) && (data->cpup_state_change_enable == bw_def_no || (bw_mtn(data->blackout_duration_margin[data->y_clk_level][s_mid1], bw_int_to_fixed(0)) && bw_ltn(data->dispclk_required_for_blackout_duration[data->y_clk_level][s_mid1], vbios->high_voltage_max_dispclk))) && (data->cpuc_state_change_enable == bw_def_no || (bw_mtn(data->blackout_duration_margin[data->y_clk_level][s_mid1], bw_int_to_fixed(0)) && bw_ltn(data->dispclk_required_for_blackout_duration[data->y_clk_level][s_mid1], vbios->high_voltage_max_dispclk) && bw_ltn(data->dispclk_required_for_blackout_recovery[data->y_clk_level][s_mid1], vbios->high_voltage_max_dispclk))) && (data->nbp_state_change_enable == bw_def_no || (bw_mtn(data->min_dram_speed_change_margin[data->y_clk_level][s_mid1], bw_int_to_fixed(0)) && bw_ltn(data->min_dram_speed_change_margin[data->y_clk_level][s_mid1], bw_int_to_fixed(9999)) && bw_leq(data->dispclk_required_for_dram_speed_change[data->y_clk_level][s_mid1], vbios->mid_voltage_max_dispclk) && data->num_displays_with_margin[data->y_clk_level][s_mid1] == number_of_displays_enabled_with_margin))) {
+ else if (bw_ltn(data->total_average_bandwidth_no_compression, bw_mul(bw_mul(bw_frc_to_fixed(dceip->max_average_percent_of_ideal_port_bw_display_can_use_in_normal_system_operation, 100),sclk[mid]),vbios->data_return_bus_width))
+ && bw_ltn(data->required_sclk, sclk[s_mid1]) && (data->cpup_state_change_enable == bw_def_no || (bw_mtn(data->blackout_duration_margin[data->y_clk_level][s_mid1], bw_int_to_fixed(0)) && bw_ltn(data->dispclk_required_for_blackout_duration[data->y_clk_level][s_mid1], vbios->high_voltage_max_dispclk))) && (data->cpuc_state_change_enable == bw_def_no || (bw_mtn(data->blackout_duration_margin[data->y_clk_level][s_mid1], bw_int_to_fixed(0)) && bw_ltn(data->dispclk_required_for_blackout_duration[data->y_clk_level][s_mid1], vbios->high_voltage_max_dispclk) && bw_ltn(data->dispclk_required_for_blackout_recovery[data->y_clk_level][s_mid1], vbios->high_voltage_max_dispclk))) && (!data->increase_voltage_to_support_mclk_switch || data->nbp_state_change_enable == bw_def_no || (bw_mtn(data->min_dram_speed_change_margin[data->y_clk_level][s_mid1], bw_int_to_fixed(0)) && bw_ltn(data->min_dram_speed_change_margin[data->y_clk_level][s_mid1], bw_int_to_fixed(9999)) && bw_leq(data->dispclk_required_for_dram_speed_change[data->y_clk_level][s_mid1], vbios->mid_voltage_max_dispclk) && data->num_displays_with_margin[data->y_clk_level][s_mid1] == number_of_displays_enabled_with_margin))) {
sclk_message = bw_def_mid;
data->sclk_level = s_mid1;
data->required_sclk = vbios->mid1_sclk;
}
- else if (bw_ltn(data->required_sclk, sclk[s_mid2]) && (data->cpup_state_change_enable == bw_def_no || (bw_mtn(data->blackout_duration_margin[data->y_clk_level][s_mid2], bw_int_to_fixed(0)) && bw_ltn(data->dispclk_required_for_blackout_duration[data->y_clk_level][s_mid2], vbios->high_voltage_max_dispclk))) && (data->cpuc_state_change_enable == bw_def_no || (bw_mtn(data->blackout_duration_margin[data->y_clk_level][s_mid2], bw_int_to_fixed(0)) && bw_ltn(data->dispclk_required_for_blackout_duration[data->y_clk_level][s_mid2], vbios->high_voltage_max_dispclk) && bw_ltn(data->dispclk_required_for_blackout_recovery[data->y_clk_level][s_mid2], vbios->high_voltage_max_dispclk))) && (data->nbp_state_change_enable == bw_def_no || (bw_mtn(data->min_dram_speed_change_margin[data->y_clk_level][s_mid2], bw_int_to_fixed(0)) && bw_ltn(data->min_dram_speed_change_margin[data->y_clk_level][s_mid2], bw_int_to_fixed(9999)) && bw_leq(data->dispclk_required_for_dram_speed_change[data->y_clk_level][s_mid2], vbios->mid_voltage_max_dispclk) && data->num_displays_with_margin[data->y_clk_level][s_mid2] == number_of_displays_enabled_with_margin))) {
+ else if (bw_ltn(data->total_average_bandwidth_no_compression, bw_mul(bw_mul(bw_frc_to_fixed(dceip->max_average_percent_of_ideal_port_bw_display_can_use_in_normal_system_operation, 100),sclk[s_mid2]),vbios->data_return_bus_width))
+ && bw_ltn(data->required_sclk, sclk[s_mid2]) && (data->cpup_state_change_enable == bw_def_no || (bw_mtn(data->blackout_duration_margin[data->y_clk_level][s_mid2], bw_int_to_fixed(0)) && bw_ltn(data->dispclk_required_for_blackout_duration[data->y_clk_level][s_mid2], vbios->high_voltage_max_dispclk))) && (data->cpuc_state_change_enable == bw_def_no || (bw_mtn(data->blackout_duration_margin[data->y_clk_level][s_mid2], bw_int_to_fixed(0)) && bw_ltn(data->dispclk_required_for_blackout_duration[data->y_clk_level][s_mid2], vbios->high_voltage_max_dispclk) && bw_ltn(data->dispclk_required_for_blackout_recovery[data->y_clk_level][s_mid2], vbios->high_voltage_max_dispclk))) && (!data->increase_voltage_to_support_mclk_switch || data->nbp_state_change_enable == bw_def_no || (bw_mtn(data->min_dram_speed_change_margin[data->y_clk_level][s_mid2], bw_int_to_fixed(0)) && bw_ltn(data->min_dram_speed_change_margin[data->y_clk_level][s_mid2], bw_int_to_fixed(9999)) && bw_leq(data->dispclk_required_for_dram_speed_change[data->y_clk_level][s_mid2], vbios->mid_voltage_max_dispclk) && data->num_displays_with_margin[data->y_clk_level][s_mid2] == number_of_displays_enabled_with_margin))) {
sclk_message = bw_def_mid;
data->sclk_level = s_mid2;
data->required_sclk = vbios->mid2_sclk;
}
- else if (bw_ltn(data->required_sclk, sclk[s_mid3]) && (data->cpup_state_change_enable == bw_def_no || (bw_mtn(data->blackout_duration_margin[data->y_clk_level][s_mid3], bw_int_to_fixed(0)) && bw_ltn(data->dispclk_required_for_blackout_duration[data->y_clk_level][s_mid3], vbios->high_voltage_max_dispclk))) && (data->cpuc_state_change_enable == bw_def_no || (bw_mtn(data->blackout_duration_margin[data->y_clk_level][s_mid3], bw_int_to_fixed(0)) && bw_ltn(data->dispclk_required_for_blackout_duration[data->y_clk_level][s_mid3], vbios->high_voltage_max_dispclk) && bw_ltn(data->dispclk_required_for_blackout_recovery[data->y_clk_level][s_mid3], vbios->high_voltage_max_dispclk))) && (data->nbp_state_change_enable == bw_def_no || (bw_mtn(data->min_dram_speed_change_margin[data->y_clk_level][s_mid3], bw_int_to_fixed(0)) && bw_ltn(data->min_dram_speed_change_margin[data->y_clk_level][s_mid3], bw_int_to_fixed(9999)) && bw_leq(data->dispclk_required_for_dram_speed_change[data->y_clk_level][s_mid3], vbios->mid_voltage_max_dispclk) && data->num_displays_with_margin[data->y_clk_level][s_mid3] == number_of_displays_enabled_with_margin))) {
+ else if (bw_ltn(data->total_average_bandwidth_no_compression, bw_mul(bw_mul(bw_frc_to_fixed(dceip->max_average_percent_of_ideal_port_bw_display_can_use_in_normal_system_operation, 100),sclk[s_mid3]),vbios->data_return_bus_width))
+ && bw_ltn(data->required_sclk, sclk[s_mid3]) && (data->cpup_state_change_enable == bw_def_no || (bw_mtn(data->blackout_duration_margin[data->y_clk_level][s_mid3], bw_int_to_fixed(0)) && bw_ltn(data->dispclk_required_for_blackout_duration[data->y_clk_level][s_mid3], vbios->high_voltage_max_dispclk))) && (data->cpuc_state_change_enable == bw_def_no || (bw_mtn(data->blackout_duration_margin[data->y_clk_level][s_mid3], bw_int_to_fixed(0)) && bw_ltn(data->dispclk_required_for_blackout_duration[data->y_clk_level][s_mid3], vbios->high_voltage_max_dispclk) && bw_ltn(data->dispclk_required_for_blackout_recovery[data->y_clk_level][s_mid3], vbios->high_voltage_max_dispclk))) && (!data->increase_voltage_to_support_mclk_switch || data->nbp_state_change_enable == bw_def_no || (bw_mtn(data->min_dram_speed_change_margin[data->y_clk_level][s_mid3], bw_int_to_fixed(0)) && bw_ltn(data->min_dram_speed_change_margin[data->y_clk_level][s_mid3], bw_int_to_fixed(9999)) && bw_leq(data->dispclk_required_for_dram_speed_change[data->y_clk_level][s_mid3], vbios->mid_voltage_max_dispclk) && data->num_displays_with_margin[data->y_clk_level][s_mid3] == number_of_displays_enabled_with_margin))) {
sclk_message = bw_def_mid;
data->sclk_level = s_mid3;
data->required_sclk = vbios->mid3_sclk;
}
- else if (bw_ltn(data->required_sclk, sclk[s_mid4]) && (data->cpup_state_change_enable == bw_def_no || (bw_mtn(data->blackout_duration_margin[data->y_clk_level][s_mid4], bw_int_to_fixed(0)) && bw_ltn(data->dispclk_required_for_blackout_duration[data->y_clk_level][s_mid4], vbios->high_voltage_max_dispclk))) && (data->cpuc_state_change_enable == bw_def_no || (bw_mtn(data->blackout_duration_margin[data->y_clk_level][s_mid4], bw_int_to_fixed(0)) && bw_ltn(data->dispclk_required_for_blackout_duration[data->y_clk_level][s_mid4], vbios->high_voltage_max_dispclk) && bw_ltn(data->dispclk_required_for_blackout_recovery[data->y_clk_level][s_mid4], vbios->high_voltage_max_dispclk))) && (data->nbp_state_change_enable == bw_def_no || (bw_mtn(data->min_dram_speed_change_margin[data->y_clk_level][s_mid4], bw_int_to_fixed(0)) && bw_ltn(data->min_dram_speed_change_margin[data->y_clk_level][s_mid4], bw_int_to_fixed(9999)) && bw_leq(data->dispclk_required_for_dram_speed_change[data->y_clk_level][s_mid4], vbios->mid_voltage_max_dispclk) && data->num_displays_with_margin[data->y_clk_level][s_mid4] == number_of_displays_enabled_with_margin))) {
+ else if (bw_ltn(data->total_average_bandwidth_no_compression, bw_mul(bw_mul(bw_frc_to_fixed(dceip->max_average_percent_of_ideal_port_bw_display_can_use_in_normal_system_operation, 100),sclk[s_mid4]),vbios->data_return_bus_width))
+ && bw_ltn(data->required_sclk, sclk[s_mid4]) && (data->cpup_state_change_enable == bw_def_no || (bw_mtn(data->blackout_duration_margin[data->y_clk_level][s_mid4], bw_int_to_fixed(0)) && bw_ltn(data->dispclk_required_for_blackout_duration[data->y_clk_level][s_mid4], vbios->high_voltage_max_dispclk))) && (data->cpuc_state_change_enable == bw_def_no || (bw_mtn(data->blackout_duration_margin[data->y_clk_level][s_mid4], bw_int_to_fixed(0)) && bw_ltn(data->dispclk_required_for_blackout_duration[data->y_clk_level][s_mid4], vbios->high_voltage_max_dispclk) && bw_ltn(data->dispclk_required_for_blackout_recovery[data->y_clk_level][s_mid4], vbios->high_voltage_max_dispclk))) && (!data->increase_voltage_to_support_mclk_switch || data->nbp_state_change_enable == bw_def_no || (bw_mtn(data->min_dram_speed_change_margin[data->y_clk_level][s_mid4], bw_int_to_fixed(0)) && bw_ltn(data->min_dram_speed_change_margin[data->y_clk_level][s_mid4], bw_int_to_fixed(9999)) && bw_leq(data->dispclk_required_for_dram_speed_change[data->y_clk_level][s_mid4], vbios->mid_voltage_max_dispclk) && data->num_displays_with_margin[data->y_clk_level][s_mid4] == number_of_displays_enabled_with_margin))) {
sclk_message = bw_def_mid;
data->sclk_level = s_mid4;
data->required_sclk = vbios->mid4_sclk;
}
- else if (bw_ltn(data->required_sclk, sclk[s_mid5]) && (data->cpup_state_change_enable == bw_def_no || (bw_mtn(data->blackout_duration_margin[data->y_clk_level][s_mid5], bw_int_to_fixed(0)) && bw_ltn(data->dispclk_required_for_blackout_duration[data->y_clk_level][s_mid5], vbios->high_voltage_max_dispclk))) && (data->cpuc_state_change_enable == bw_def_no || (bw_mtn(data->blackout_duration_margin[data->y_clk_level][s_mid5], bw_int_to_fixed(0)) && bw_ltn(data->dispclk_required_for_blackout_duration[data->y_clk_level][s_mid5], vbios->high_voltage_max_dispclk) && bw_ltn(data->dispclk_required_for_blackout_recovery[data->y_clk_level][s_mid5], vbios->high_voltage_max_dispclk))) && (data->nbp_state_change_enable == bw_def_no || (bw_mtn(data->min_dram_speed_change_margin[data->y_clk_level][s_mid5], bw_int_to_fixed(0)) && bw_ltn(data->min_dram_speed_change_margin[data->y_clk_level][s_mid5], bw_int_to_fixed(9999)) && bw_leq(data->dispclk_required_for_dram_speed_change[data->y_clk_level][s_mid5], vbios->mid_voltage_max_dispclk) && data->num_displays_with_margin[data->y_clk_level][s_mid5] == number_of_displays_enabled_with_margin))) {
+ else if (bw_ltn(data->total_average_bandwidth_no_compression, bw_mul(bw_mul(bw_frc_to_fixed(dceip->max_average_percent_of_ideal_port_bw_display_can_use_in_normal_system_operation, 100),sclk[s_mid5]),vbios->data_return_bus_width))
+ && bw_ltn(data->required_sclk, sclk[s_mid5]) && (data->cpup_state_change_enable == bw_def_no || (bw_mtn(data->blackout_duration_margin[data->y_clk_level][s_mid5], bw_int_to_fixed(0)) && bw_ltn(data->dispclk_required_for_blackout_duration[data->y_clk_level][s_mid5], vbios->high_voltage_max_dispclk))) && (data->cpuc_state_change_enable == bw_def_no || (bw_mtn(data->blackout_duration_margin[data->y_clk_level][s_mid5], bw_int_to_fixed(0)) && bw_ltn(data->dispclk_required_for_blackout_duration[data->y_clk_level][s_mid5], vbios->high_voltage_max_dispclk) && bw_ltn(data->dispclk_required_for_blackout_recovery[data->y_clk_level][s_mid5], vbios->high_voltage_max_dispclk))) && (!data->increase_voltage_to_support_mclk_switch || data->nbp_state_change_enable == bw_def_no || (bw_mtn(data->min_dram_speed_change_margin[data->y_clk_level][s_mid5], bw_int_to_fixed(0)) && bw_ltn(data->min_dram_speed_change_margin[data->y_clk_level][s_mid5], bw_int_to_fixed(9999)) && bw_leq(data->dispclk_required_for_dram_speed_change[data->y_clk_level][s_mid5], vbios->mid_voltage_max_dispclk) && data->num_displays_with_margin[data->y_clk_level][s_mid5] == number_of_displays_enabled_with_margin))) {
sclk_message = bw_def_mid;
data->sclk_level = s_mid5;
data->required_sclk = vbios->mid5_sclk;
}
- else if (bw_ltn(data->required_sclk, sclk[s_mid6]) && (data->cpup_state_change_enable == bw_def_no || (bw_mtn(data->blackout_duration_margin[data->y_clk_level][s_mid6], bw_int_to_fixed(0)) && bw_ltn(data->dispclk_required_for_blackout_duration[data->y_clk_level][s_mid6], vbios->high_voltage_max_dispclk))) && (data->cpuc_state_change_enable == bw_def_no || (bw_mtn(data->blackout_duration_margin[data->y_clk_level][s_mid6], bw_int_to_fixed(0)) && bw_ltn(data->dispclk_required_for_blackout_duration[data->y_clk_level][s_mid6], vbios->high_voltage_max_dispclk) && bw_ltn(data->dispclk_required_for_blackout_recovery[data->y_clk_level][s_mid6], vbios->high_voltage_max_dispclk))) && (data->nbp_state_change_enable == bw_def_no || (bw_mtn(data->min_dram_speed_change_margin[data->y_clk_level][s_mid6], bw_int_to_fixed(0)) && bw_ltn(data->min_dram_speed_change_margin[data->y_clk_level][s_mid6], bw_int_to_fixed(9999)) && bw_leq(data->dispclk_required_for_dram_speed_change[data->y_clk_level][s_mid6], vbios->high_voltage_max_dispclk) && data->num_displays_with_margin[data->y_clk_level][s_mid6] == number_of_displays_enabled_with_margin))) {
+ else if (bw_ltn(data->total_average_bandwidth_no_compression, bw_mul(bw_mul(bw_frc_to_fixed(dceip->max_average_percent_of_ideal_port_bw_display_can_use_in_normal_system_operation, 100),sclk[s_mid6]),vbios->data_return_bus_width))
+ && bw_ltn(data->required_sclk, sclk[s_mid6]) && (data->cpup_state_change_enable == bw_def_no || (bw_mtn(data->blackout_duration_margin[data->y_clk_level][s_mid6], bw_int_to_fixed(0)) && bw_ltn(data->dispclk_required_for_blackout_duration[data->y_clk_level][s_mid6], vbios->high_voltage_max_dispclk))) && (data->cpuc_state_change_enable == bw_def_no || (bw_mtn(data->blackout_duration_margin[data->y_clk_level][s_mid6], bw_int_to_fixed(0)) && bw_ltn(data->dispclk_required_for_blackout_duration[data->y_clk_level][s_mid6], vbios->high_voltage_max_dispclk) && bw_ltn(data->dispclk_required_for_blackout_recovery[data->y_clk_level][s_mid6], vbios->high_voltage_max_dispclk))) && (!data->increase_voltage_to_support_mclk_switch || data->nbp_state_change_enable == bw_def_no || (bw_mtn(data->min_dram_speed_change_margin[data->y_clk_level][s_mid6], bw_int_to_fixed(0)) && bw_ltn(data->min_dram_speed_change_margin[data->y_clk_level][s_mid6], bw_int_to_fixed(9999)) && bw_leq(data->dispclk_required_for_dram_speed_change[data->y_clk_level][s_mid6], vbios->high_voltage_max_dispclk) && data->num_displays_with_margin[data->y_clk_level][s_mid6] == number_of_displays_enabled_with_margin))) {
sclk_message = bw_def_mid;
data->sclk_level = s_mid6;
data->required_sclk = vbios->mid6_sclk;
}
- else if (bw_ltn(data->required_sclk, sclk[s_high])) {
+ else if (bw_ltn(data->total_average_bandwidth_no_compression, bw_mul(bw_mul(bw_frc_to_fixed(dceip->max_average_percent_of_ideal_port_bw_display_can_use_in_normal_system_operation, 100),sclk[s_high]),vbios->data_return_bus_width))
+ && bw_ltn(data->required_sclk, sclk[s_high])) {
+ sclk_message = bw_def_high;
+ data->sclk_level = s_high;
+ data->required_sclk = vbios->high_sclk;
+ }
+ else if (bw_meq(data->total_average_bandwidth_no_compression, bw_mul(bw_mul(bw_frc_to_fixed(dceip->max_average_percent_of_ideal_port_bw_display_can_use_in_normal_system_operation, 100),sclk[s_high]),vbios->data_return_bus_width))
+ && bw_ltn(data->required_sclk, sclk[s_high])) {
sclk_message = bw_def_high;
data->sclk_level = s_high;
data->required_sclk = vbios->high_sclk;
@@ -1681,7 +1730,7 @@ static void calculate_bandwidth(
data->total_dispclk_required_with_ramping_with_request_bandwidth = bw_max2(data->total_dispclk_required_with_ramping_with_request_bandwidth, data->dispclk_required_for_blackout_duration[data->y_clk_level][data->sclk_level]);
data->total_dispclk_required_without_ramping_with_request_bandwidth = bw_max2(data->total_dispclk_required_without_ramping_with_request_bandwidth, data->dispclk_required_for_blackout_duration[data->y_clk_level][data->sclk_level]);
}
- if (data->nbp_state_change_enable == bw_def_yes) {
+ if (data->nbp_state_change_enable == bw_def_yes && data->increase_voltage_to_support_mclk_switch) {
data->total_dispclk_required_with_ramping_with_request_bandwidth = bw_max2(data->total_dispclk_required_with_ramping_with_request_bandwidth, data->dispclk_required_for_dram_speed_change[data->y_clk_level][data->sclk_level]);
data->total_dispclk_required_without_ramping_with_request_bandwidth = bw_max2(data->total_dispclk_required_without_ramping_with_request_bandwidth, data->dispclk_required_for_dram_speed_change[data->y_clk_level][data->sclk_level]);
}
@@ -1861,23 +1910,6 @@ static void calculate_bandwidth(
else {
data->mcifwrdram_access_efficiency = bw_int_to_fixed(0);
}
- /*average bandwidth*/
- /*the average bandwidth with no compression is the vertical active time is the source width times the bytes per pixel divided by the line time, multiplied by the vertical scale ratio and the ratio of bytes per request divided by the useful bytes per request.*/
- /*the average bandwidth with compression is the same, divided by the compression ratio*/
- for (i = 0; i <= maximum_number_of_surfaces - 1; i++) {
- if (data->enable[i]) {
- data->average_bandwidth_no_compression[i] = bw_div(bw_mul(bw_mul(bw_div(bw_mul(data->source_width_rounded_up_to_chunks[i], bw_int_to_fixed(data->bytes_per_pixel[i])), (bw_div(data->h_total[i], data->pixel_rate[i]))), data->vsr[i]), data->bytes_per_request[i]), data->useful_bytes_per_request[i]);
- data->average_bandwidth[i] = bw_div(data->average_bandwidth_no_compression[i], data->compression_rate[i]);
- }
- }
- data->total_average_bandwidth_no_compression = bw_int_to_fixed(0);
- data->total_average_bandwidth = bw_int_to_fixed(0);
- for (i = 0; i <= maximum_number_of_surfaces - 1; i++) {
- if (data->enable[i]) {
- data->total_average_bandwidth_no_compression = bw_add(data->total_average_bandwidth_no_compression, data->average_bandwidth_no_compression[i]);
- data->total_average_bandwidth = bw_add(data->total_average_bandwidth, data->average_bandwidth[i]);
- }
- }
/*stutter efficiency*/
/*the stutter efficiency is the frame-average time in self-refresh divided by the frame-average stutter cycle duration. only applies if the display write-back is not enabled.*/
/*the frame-average stutter cycle used is the minimum for all pipes of the frame-average data buffer size in time, times the compression rate*/
@@ -1905,7 +1937,7 @@ static void calculate_bandwidth(
data->total_stutter_dmif_buffer_size = bw_fixed_to_int(bw_add(data->stutter_dmif_buffer_size[i], bw_int_to_fixed(data->total_stutter_dmif_buffer_size)));
}
}
- data->stutter_burst_time = bw_div(bw_int_to_fixed(data->total_stutter_dmif_buffer_size), bw_min2(bw_mul(data->dram_bandwidth, data->dmifdram_access_efficiency), bw_mul(sclk[data->sclk_level], bw_int_to_fixed(32))));
+ data->stutter_burst_time = bw_div(bw_int_to_fixed(data->total_stutter_dmif_buffer_size), bw_mul(sclk[data->sclk_level], vbios->data_return_bus_width));
data->num_stutter_bursts = data->total_bytes_requested / data->min_stutter_dmif_buffer_size;
data->total_stutter_cycle_duration = bw_add(bw_add(data->min_stutter_refresh_duration, vbios->stutter_self_refresh_exit_latency), data->stutter_burst_time);
data->time_in_self_refresh = data->min_stutter_refresh_duration;
@@ -1957,7 +1989,7 @@ static void calculate_bandwidth(
for (i = 1; i <= 5; i++) {
data->display_reads_time_for_data_transfer_and_urgent_latency = bw_sub(data->min_read_buffer_size_in_time, bw_mul(data->total_dmifmc_urgent_trips, bw_int_to_fixed(i)));
if (pipe_check == bw_def_ok && (bw_mtn(data->display_reads_time_for_data_transfer_and_urgent_latency, data->dmif_total_page_close_open_time))) {
- data->dmif_required_sclk_for_urgent_latency[i] = bw_div(bw_div(data->total_display_reads_required_data, data->display_reads_time_for_data_transfer_and_urgent_latency), (bw_mul(vbios->data_return_bus_width, bw_int_to_fixed(bus_efficiency))));
+ data->dmif_required_sclk_for_urgent_latency[i] = bw_div(bw_div(data->total_display_reads_required_data, data->display_reads_time_for_data_transfer_and_urgent_latency), (bw_mul(vbios->data_return_bus_width, bw_frc_to_fixed(dceip->percent_of_ideal_port_bw_received_after_urgent_latency, 100))));
}
else {
data->dmif_required_sclk_for_urgent_latency[i] = bw_int_to_fixed(bw_def_na);
@@ -2036,6 +2068,9 @@ void bw_calcs_init(struct bw_calcs_dceip *bw_dceip,
vbios.blackout_duration = bw_int_to_fixed(0); /* us */
vbios.maximum_blackout_recovery_time = bw_int_to_fixed(0);
+ dceip.max_average_percent_of_ideal_port_bw_display_can_use_in_normal_system_operation = 100;
+ dceip.max_average_percent_of_ideal_drambw_display_can_use_in_normal_system_operation = 100;
+ dceip.percent_of_ideal_port_bw_received_after_urgent_latency = 100;
dceip.large_cursor = false;
dceip.dmif_request_buffer_size = bw_int_to_fixed(768);
dceip.dmif_pipe_en_fbc_chunk_tracker = false;
@@ -2146,6 +2181,9 @@ void bw_calcs_init(struct bw_calcs_dceip *bw_dceip,
vbios.blackout_duration = bw_int_to_fixed(0); /* us */
vbios.maximum_blackout_recovery_time = bw_int_to_fixed(0);
+ dceip.max_average_percent_of_ideal_port_bw_display_can_use_in_normal_system_operation = 100;
+ dceip.max_average_percent_of_ideal_drambw_display_can_use_in_normal_system_operation = 100;
+ dceip.percent_of_ideal_port_bw_received_after_urgent_latency = 100;
dceip.large_cursor = false;
dceip.dmif_request_buffer_size = bw_int_to_fixed(768);
dceip.dmif_pipe_en_fbc_chunk_tracker = false;
@@ -2259,6 +2297,9 @@ void bw_calcs_init(struct bw_calcs_dceip *bw_dceip,
vbios.blackout_duration = bw_int_to_fixed(0); /* us */
vbios.maximum_blackout_recovery_time = bw_int_to_fixed(0);
+ dceip.max_average_percent_of_ideal_port_bw_display_can_use_in_normal_system_operation = 100;
+ dceip.max_average_percent_of_ideal_drambw_display_can_use_in_normal_system_operation = 100;
+ dceip.percent_of_ideal_port_bw_received_after_urgent_latency = 100;
dceip.large_cursor = false;
dceip.dmif_request_buffer_size = bw_int_to_fixed(768);
dceip.dmif_pipe_en_fbc_chunk_tracker = false;
@@ -2369,6 +2410,9 @@ void bw_calcs_init(struct bw_calcs_dceip *bw_dceip,
vbios.blackout_duration = bw_int_to_fixed(0); /* us */
vbios.maximum_blackout_recovery_time = bw_int_to_fixed(0);
+ dceip.max_average_percent_of_ideal_port_bw_display_can_use_in_normal_system_operation = 100;
+ dceip.max_average_percent_of_ideal_drambw_display_can_use_in_normal_system_operation = 100;
+ dceip.percent_of_ideal_port_bw_received_after_urgent_latency = 100;
dceip.large_cursor = false;
dceip.dmif_request_buffer_size = bw_int_to_fixed(768);
dceip.dmif_pipe_en_fbc_chunk_tracker = false;
@@ -2479,6 +2523,9 @@ void bw_calcs_init(struct bw_calcs_dceip *bw_dceip,
vbios.blackout_duration = bw_int_to_fixed(0); /* us */
vbios.maximum_blackout_recovery_time = bw_int_to_fixed(0);
+ dceip.max_average_percent_of_ideal_port_bw_display_can_use_in_normal_system_operation = 100;
+ dceip.max_average_percent_of_ideal_drambw_display_can_use_in_normal_system_operation = 100;
+ dceip.percent_of_ideal_port_bw_received_after_urgent_latency = 100;
dceip.large_cursor = false;
dceip.dmif_request_buffer_size = bw_int_to_fixed(2304);
dceip.dmif_pipe_en_fbc_chunk_tracker = true;
@@ -2597,6 +2644,7 @@ static void populate_initial_data(
data->graphics_tiling_mode = bw_def_tiled;
data->underlay_micro_tile_mode = bw_def_display_micro_tiling;
data->graphics_micro_tile_mode = bw_def_display_micro_tiling;
+ data->increase_voltage_to_support_mclk_switch = true;
/* Pipes with underlay first */
for (i = 0; i < pipe_count; i++) {
diff --git a/drivers/gpu/drm/amd/display/dc/calcs/dcn_calcs.c b/drivers/gpu/drm/amd/display/dc/calcs/dcn_calcs.c
index c9aa686d16b9..4bb43a371292 100644
--- a/drivers/gpu/drm/amd/display/dc/calcs/dcn_calcs.c
+++ b/drivers/gpu/drm/amd/display/dc/calcs/dcn_calcs.c
@@ -33,6 +33,8 @@
#include "dcn10/dcn10_resource.h"
#include "dcn_calc_math.h"
+#define DC_LOGGER \
+ dc->ctx->logger
/*
* NOTE:
* This file is gcc-parseable HW gospel, coming straight from HW engineers.
@@ -981,8 +983,6 @@ bool dcn_validate_bandwidth(
context->bw.dcn.calc_clk.fclk_khz = (int)(bw_consumed * 1000000 / 32);
}
- context->bw.dcn.calc_clk.dram_ccm_us = (int)(v->dram_clock_change_margin);
- context->bw.dcn.calc_clk.min_active_dram_ccm_us = (int)(v->min_active_dram_clock_change_margin);
context->bw.dcn.calc_clk.dcfclk_deep_sleep_khz = (int)(v->dcf_clk_deep_sleep * 1000);
context->bw.dcn.calc_clk.dcfclk_khz = (int)(v->dcfclk * 1000);
@@ -996,7 +996,26 @@ bool dcn_validate_bandwidth(
dc->debug.min_disp_clk_khz;
}
- context->bw.dcn.calc_clk.dppclk_div = (int)(v->dispclk_dppclk_ratio) == 2;
+ context->bw.dcn.calc_clk.dppclk_khz = context->bw.dcn.calc_clk.dispclk_khz / v->dispclk_dppclk_ratio;
+
+ switch (v->voltage_level) {
+ case 0:
+ context->bw.dcn.calc_clk.max_supported_dppclk_khz =
+ (int)(dc->dcn_soc->max_dppclk_vmin0p65 * 1000);
+ break;
+ case 1:
+ context->bw.dcn.calc_clk.max_supported_dppclk_khz =
+ (int)(dc->dcn_soc->max_dppclk_vmid0p72 * 1000);
+ break;
+ case 2:
+ context->bw.dcn.calc_clk.max_supported_dppclk_khz =
+ (int)(dc->dcn_soc->max_dppclk_vnom0p8 * 1000);
+ break;
+ default:
+ context->bw.dcn.calc_clk.max_supported_dppclk_khz =
+ (int)(dc->dcn_soc->max_dppclk_vmax0p9 * 1000);
+ break;
+ }
for (i = 0, input_idx = 0; i < pool->pipe_count; i++) {
struct pipe_ctx *pipe = &context->res_ctx.pipe_ctx[i];
@@ -1242,8 +1261,7 @@ unsigned int dcn_find_dcfclk_suits_all(
else
dcf_clk = dc->dcn_soc->dcfclkv_min0p65*1000;
- dm_logger_write(dc->ctx->logger, LOG_BANDWIDTH_CALCS,
- "\tdcf_clk for voltage = %d\n", dcf_clk);
+ DC_LOG_BANDWIDTH_CALCS("\tdcf_clk for voltage = %d\n", dcf_clk);
return dcf_clk;
}
@@ -1441,8 +1459,7 @@ void dcn_bw_notify_pplib_of_wm_ranges(struct dc *dc)
void dcn_bw_sync_calcs_and_dml(struct dc *dc)
{
kernel_fpu_begin();
- dm_logger_write(dc->ctx->logger, LOG_BANDWIDTH_CALCS,
- "sr_exit_time: %d ns\n"
+ DC_LOG_BANDWIDTH_CALCS("sr_exit_time: %d ns\n"
"sr_enter_plus_exit_time: %d ns\n"
"urgent_latency: %d ns\n"
"write_back_latency: %d ns\n"
@@ -1510,8 +1527,7 @@ void dcn_bw_sync_calcs_and_dml(struct dc *dc)
dc->dcn_soc->vmm_page_size,
dc->dcn_soc->dram_clock_change_latency * 1000,
dc->dcn_soc->return_bus_width);
- dm_logger_write(dc->ctx->logger, LOG_BANDWIDTH_CALCS,
- "rob_buffer_size_in_kbyte: %d\n"
+ DC_LOG_BANDWIDTH_CALCS("rob_buffer_size_in_kbyte: %d\n"
"det_buffer_size_in_kbyte: %d\n"
"dpp_output_buffer_pixels: %d\n"
"opp_output_buffer_lines: %d\n"
diff --git a/drivers/gpu/drm/amd/display/dc/core/dc.c b/drivers/gpu/drm/amd/display/dc/core/dc.c
index 77a1bf233c3c..63a3d468939a 100644
--- a/drivers/gpu/drm/amd/display/dc/core/dc.c
+++ b/drivers/gpu/drm/amd/display/dc/core/dc.c
@@ -42,6 +42,7 @@
#include "dmcu.h"
#include "dpp.h"
#include "timing_generator.h"
+#include "abm.h"
#include "virtual/virtual_link_encoder.h"
#include "link_hwss.h"
@@ -51,6 +52,8 @@
#include "dm_helpers.h"
#include "mem_input.h"
#include "hubp.h"
+#define DC_LOGGER \
+ dc->ctx->logger
/*******************************************************************************
@@ -264,7 +267,7 @@ bool dc_stream_configure_crc(struct dc *dc, struct dc_stream_state *stream,
/* Only call if supported */
if (tg->funcs->configure_crc)
return tg->funcs->configure_crc(tg, &param);
- dm_logger_write(dc->ctx->logger, LOG_WARNING, "CRC capture not supported.");
+ DC_LOG_WARNING("CRC capture not supported.");
return false;
}
@@ -297,7 +300,7 @@ bool dc_stream_get_crc(struct dc *dc, struct dc_stream_state *stream,
if (tg->funcs->get_crc)
return tg->funcs->get_crc(tg, r_cr, g_y, b_cb);
- dm_logger_write(dc->ctx->logger, LOG_WARNING, "CRC capture not supported.");
+ DC_LOG_WARNING("CRC capture not supported.");
return false;
}
@@ -618,8 +621,7 @@ struct dc *dc_create(const struct dc_init_data *init_params)
dc->config = init_params->flags;
- dm_logger_write(dc->ctx->logger, LOG_DC,
- "Display Core initialized\n");
+ DC_LOG_DC("Display Core initialized\n");
/* TODO: missing feature to be enabled */
@@ -801,6 +803,8 @@ static enum dc_status dc_commit_state_no_check(struct dc *dc, struct dc_state *c
if (!dcb->funcs->is_accelerated_mode(dcb))
dc->hwss.enable_accelerated_mode(dc, context);
+ dc->hwss.set_bandwidth(dc, context, false);
+
/* re-program planes for existing stream, in case we need to
* free up plane resource for later use
*/
@@ -869,6 +873,9 @@ static enum dc_status dc_commit_state_no_check(struct dc *dc, struct dc_state *c
dc_enable_stereo(dc, context, dc_streams, context->stream_count);
+ /* pplib is notified if disp_num changed */
+ dc->hwss.set_bandwidth(dc, context, true);
+
dc_release_state(dc->current_state);
dc->current_state = context;
@@ -888,7 +895,7 @@ bool dc_commit_state(struct dc *dc, struct dc_state *context)
if (false == context_changed(dc, context))
return DC_OK;
- dm_logger_write(dc->ctx->logger, LOG_DC, "%s: %d streams\n",
+ DC_LOG_DC("%s: %d streams\n",
__func__, context->stream_count);
for (i = 0; i < context->stream_count; i++) {
@@ -1103,9 +1110,6 @@ static enum surface_update_type get_plane_info_update_type(const struct dc_surfa
if (u->plane_info->input_tf != u->surface->input_tf)
update_flags->bits.input_tf_change = 1;
- if (u->plane_info->sdr_white_level != u->surface->sdr_white_level)
- update_flags->bits.output_tf_change = 1;
-
if (u->plane_info->horizontal_mirror != u->surface->horizontal_mirror)
update_flags->bits.horizontal_mirror_change = 1;
@@ -1360,6 +1364,17 @@ static void commit_planes_for_stream(struct dc *dc,
dc->hwss.apply_ctx_for_surface(
dc, pipe_ctx->stream, stream_status->plane_count, context);
+
+ if (stream_update && stream_update->abm_level && pipe_ctx->stream_res.abm) {
+ if (pipe_ctx->stream_res.tg->funcs->is_blanked) {
+ // if otg funcs defined check if blanked before programming
+ if (!pipe_ctx->stream_res.tg->funcs->is_blanked(pipe_ctx->stream_res.tg))
+ pipe_ctx->stream_res.abm->funcs->set_abm_level(
+ pipe_ctx->stream_res.abm, stream->abm_level);
+ } else
+ pipe_ctx->stream_res.abm->funcs->set_abm_level(
+ pipe_ctx->stream_res.abm, stream->abm_level);
+ }
}
}
@@ -1515,13 +1530,13 @@ enum dc_irq_source dc_interrupt_to_irq_source(
return dal_irq_service_to_irq_source(dc->res_pool->irqs, src_id, ext_id);
}
-void dc_interrupt_set(struct dc *dc, enum dc_irq_source src, bool enable)
+bool dc_interrupt_set(struct dc *dc, enum dc_irq_source src, bool enable)
{
if (dc == NULL)
- return;
+ return false;
- dal_irq_service_set(dc->res_pool->irqs, src, enable);
+ return dal_irq_service_set(dc->res_pool->irqs, src, enable);
}
void dc_interrupt_ack(struct dc *dc, enum dc_irq_source src)
diff --git a/drivers/gpu/drm/amd/display/dc/core/dc_debug.c b/drivers/gpu/drm/amd/display/dc/core/dc_debug.c
index 1babac07bcc9..5a552cb3f8a7 100644
--- a/drivers/gpu/drm/amd/display/dc/core/dc_debug.c
+++ b/drivers/gpu/drm/amd/display/dc/core/dc_debug.c
@@ -36,26 +36,22 @@
#include "hw_sequencer.h"
#include "resource.h"
+#define DC_LOGGER \
+ logger
#define SURFACE_TRACE(...) do {\
if (dc->debug.surface_trace) \
- dm_logger_write(logger, \
- LOG_IF_TRACE, \
- ##__VA_ARGS__); \
+ DC_LOG_IF_TRACE(__VA_ARGS__); \
} while (0)
#define TIMING_TRACE(...) do {\
if (dc->debug.timing_trace) \
- dm_logger_write(logger, \
- LOG_SYNC, \
- ##__VA_ARGS__); \
+ DC_LOG_SYNC(__VA_ARGS__); \
} while (0)
#define CLOCK_TRACE(...) do {\
if (dc->debug.clock_trace) \
- dm_logger_write(logger, \
- LOG_BANDWIDTH_CALCS, \
- ##__VA_ARGS__); \
+ DC_LOG_BANDWIDTH_CALCS(__VA_ARGS__); \
} while (0)
void pre_surface_trace(
@@ -361,25 +357,20 @@ void context_clock_trace(
struct dc *core_dc = dc;
struct dal_logger *logger = core_dc->ctx->logger;
- CLOCK_TRACE("Current: dispclk_khz:%d dppclk_div:%d dcfclk_khz:%d\n"
- "dcfclk_deep_sleep_khz:%d fclk_khz:%d\n"
- "dram_ccm_us:%d min_active_dram_ccm_us:%d\n",
+ CLOCK_TRACE("Current: dispclk_khz:%d max_dppclk_khz:%d dcfclk_khz:%d\n"
+ "dcfclk_deep_sleep_khz:%d fclk_khz:%d socclk_khz:%d\n",
context->bw.dcn.calc_clk.dispclk_khz,
- context->bw.dcn.calc_clk.dppclk_div,
+ context->bw.dcn.calc_clk.dppclk_khz,
context->bw.dcn.calc_clk.dcfclk_khz,
context->bw.dcn.calc_clk.dcfclk_deep_sleep_khz,
context->bw.dcn.calc_clk.fclk_khz,
- context->bw.dcn.calc_clk.dram_ccm_us,
- context->bw.dcn.calc_clk.min_active_dram_ccm_us);
- CLOCK_TRACE("Calculated: dispclk_khz:%d dppclk_div:%d dcfclk_khz:%d\n"
- "dcfclk_deep_sleep_khz:%d fclk_khz:%d\n"
- "dram_ccm_us:%d min_active_dram_ccm_us:%d\n",
+ context->bw.dcn.calc_clk.socclk_khz);
+ CLOCK_TRACE("Calculated: dispclk_khz:%d max_dppclk_khz:%d dcfclk_khz:%d\n"
+ "dcfclk_deep_sleep_khz:%d fclk_khz:%d socclk_khz:%d\n",
context->bw.dcn.calc_clk.dispclk_khz,
- context->bw.dcn.calc_clk.dppclk_div,
+ context->bw.dcn.calc_clk.dppclk_khz,
context->bw.dcn.calc_clk.dcfclk_khz,
context->bw.dcn.calc_clk.dcfclk_deep_sleep_khz,
- context->bw.dcn.calc_clk.fclk_khz,
- context->bw.dcn.calc_clk.dram_ccm_us,
- context->bw.dcn.calc_clk.min_active_dram_ccm_us);
+ context->bw.dcn.calc_clk.fclk_khz);
#endif
}
diff --git a/drivers/gpu/drm/amd/display/dc/core/dc_link.c b/drivers/gpu/drm/amd/display/dc/core/dc_link.c
index 95955ade4012..eeb04471b2f5 100644
--- a/drivers/gpu/drm/amd/display/dc/core/dc_link.c
+++ b/drivers/gpu/drm/amd/display/dc/core/dc_link.c
@@ -45,9 +45,11 @@
#include "dce/dce_11_0_d.h"
#include "dce/dce_11_0_enum.h"
#include "dce/dce_11_0_sh_mask.h"
+#define DC_LOGGER \
+ dc_ctx->logger
#define LINK_INFO(...) \
- dm_logger_write(dc_ctx->logger, LOG_HW_HOTPLUG, \
+ DC_LOG_HW_HOTPLUG( \
__VA_ARGS__)
/*******************************************************************************
@@ -677,12 +679,10 @@ bool dc_link_detect(struct dc_link *link, enum dc_detect_reason reason)
switch (edid_status) {
case EDID_BAD_CHECKSUM:
- dm_logger_write(link->ctx->logger, LOG_ERROR,
- "EDID checksum invalid.\n");
+ DC_LOG_ERROR("EDID checksum invalid.\n");
break;
case EDID_NO_RESPONSE:
- dm_logger_write(link->ctx->logger, LOG_ERROR,
- "No EDID read.\n");
+ DC_LOG_ERROR("No EDID read.\n");
default:
break;
}
@@ -712,8 +712,7 @@ bool dc_link_detect(struct dc_link *link, enum dc_detect_reason reason)
"%s: [Block %d] ", sink->edid_caps.display_name, i);
}
- dm_logger_write(link->ctx->logger, LOG_DETECTION_EDID_PARSER,
- "%s: "
+ DC_LOG_DETECTION_EDID_PARSER("%s: "
"manufacturer_id = %X, "
"product_id = %X, "
"serial_number = %X, "
@@ -733,8 +732,7 @@ bool dc_link_detect(struct dc_link *link, enum dc_detect_reason reason)
sink->edid_caps.audio_mode_count);
for (i = 0; i < sink->edid_caps.audio_mode_count; i++) {
- dm_logger_write(link->ctx->logger, LOG_DETECTION_EDID_PARSER,
- "%s: mode number = %d, "
+ DC_LOG_DETECTION_EDID_PARSER("%s: mode number = %d, "
"format_code = %d, "
"channel_count = %d, "
"sample_rate = %d, "
@@ -984,8 +982,7 @@ static bool construct(
}
break;
default:
- dm_logger_write(dc_ctx->logger, LOG_WARNING,
- "Unsupported Connector type:%d!\n", link->link_id.id);
+ DC_LOG_WARNING("Unsupported Connector type:%d!\n", link->link_id.id);
goto create_fail;
}
@@ -1138,7 +1135,7 @@ static void dpcd_configure_panel_mode(
{
union dpcd_edp_config edp_config_set;
bool panel_mode_edp = false;
-
+ struct dc_context *dc_ctx = link->ctx;
memset(&edp_config_set, '\0', sizeof(union dpcd_edp_config));
if (DP_PANEL_MODE_DEFAULT != panel_mode) {
@@ -1175,8 +1172,7 @@ static void dpcd_configure_panel_mode(
ASSERT(result == DDC_RESULT_SUCESSFULL);
}
}
- dm_logger_write(link->ctx->logger, LOG_DETECTION_DP_CAPS,
- "Link: %d eDP panel mode supported: %d "
+ DC_LOG_DETECTION_DP_CAPS("Link: %d eDP panel mode supported: %d "
"eDP panel mode enabled: %d \n",
link->link_index,
link->dpcd_caps.panel_mode_edp,
@@ -1311,6 +1307,9 @@ static enum dc_status enable_link_dp_mst(
if (link->cur_link_settings.lane_count != LANE_COUNT_UNKNOWN)
return DC_OK;
+ /* clear payload table */
+ dm_helpers_dp_mst_clear_payload_allocation_table(link->ctx, link);
+
/* set the sink to MST mode before enabling the link */
dp_enable_mst_on_sink(link, true);
@@ -1951,6 +1950,7 @@ bool dc_link_set_backlight_level(const struct dc_link *link, uint32_t level,
struct dc *core_dc = link->ctx->dc;
struct abm *abm = core_dc->res_pool->abm;
struct dmcu *dmcu = core_dc->res_pool->dmcu;
+ struct dc_context *dc_ctx = link->ctx;
unsigned int controller_id = 0;
bool use_smooth_brightness = true;
int i;
@@ -1960,10 +1960,16 @@ bool dc_link_set_backlight_level(const struct dc_link *link, uint32_t level,
(abm->funcs->set_backlight_level == NULL))
return false;
+ if (stream) {
+ if (stream->bl_pwm_level == 0)
+ frame_ramp = 0;
+
+ ((struct dc_stream_state *)stream)->bl_pwm_level = level;
+ }
+
use_smooth_brightness = dmcu->funcs->is_dmcu_initialized(dmcu);
- dm_logger_write(link->ctx->logger, LOG_BACKLIGHT,
- "New Backlight level: %d (0x%X)\n", level, level);
+ DC_LOG_BACKLIGHT("New Backlight level: %d (0x%X)\n", level, level);
if (dc_is_embedded_signal(link->connector_signal)) {
if (stream != NULL) {
@@ -2130,6 +2136,7 @@ static enum dc_status allocate_mst_payload(struct pipe_ctx *pipe_ctx)
struct fixed31_32 avg_time_slots_per_mtp;
struct fixed31_32 pbn;
struct fixed31_32 pbn_per_slot;
+ struct dc_context *dc_ctx = link->ctx;
uint8_t i;
/* enable_link_dp_mst already check link->enabled_stream_count
@@ -2147,21 +2154,18 @@ static enum dc_status allocate_mst_payload(struct pipe_ctx *pipe_ctx)
link, pipe_ctx->stream_res.stream_enc, &proposed_table);
}
else
- dm_logger_write(link->ctx->logger, LOG_WARNING,
- "Failed to update"
+ DC_LOG_WARNING("Failed to update"
"MST allocation table for"
"pipe idx:%d\n",
pipe_ctx->pipe_idx);
- dm_logger_write(link->ctx->logger, LOG_MST,
- "%s "
+ DC_LOG_MST("%s "
"stream_count: %d: \n ",
__func__,
link->mst_stream_alloc_table.stream_count);
for (i = 0; i < MAX_CONTROLLER_NUM; i++) {
- dm_logger_write(link->ctx->logger, LOG_MST,
- "stream_enc[%d]: 0x%x "
+ DC_LOG_MST("stream_enc[%d]: 0x%x "
"stream[%d].vcp_id: %d "
"stream[%d].slot_count: %d\n",
i,
@@ -2212,6 +2216,7 @@ static enum dc_status deallocate_mst_payload(struct pipe_ctx *pipe_ctx)
struct fixed31_32 avg_time_slots_per_mtp = dal_fixed31_32_from_int(0);
uint8_t i;
bool mst_mode = (link->type == dc_connection_mst_branch);
+ struct dc_context *dc_ctx = link->ctx;
/* deallocate_mst_payload is called before disable link. When mode or
* disable/enable monitor, new stream is created which is not in link
@@ -2237,23 +2242,20 @@ static enum dc_status deallocate_mst_payload(struct pipe_ctx *pipe_ctx)
link, pipe_ctx->stream_res.stream_enc, &proposed_table);
}
else {
- dm_logger_write(link->ctx->logger, LOG_WARNING,
- "Failed to update"
+ DC_LOG_WARNING("Failed to update"
"MST allocation table for"
"pipe idx:%d\n",
pipe_ctx->pipe_idx);
}
}
- dm_logger_write(link->ctx->logger, LOG_MST,
- "%s"
+ DC_LOG_MST("%s"
"stream_count: %d: ",
__func__,
link->mst_stream_alloc_table.stream_count);
for (i = 0; i < MAX_CONTROLLER_NUM; i++) {
- dm_logger_write(link->ctx->logger, LOG_MST,
- "stream_enc[%d]: 0x%x "
+ DC_LOG_MST("stream_enc[%d]: 0x%x "
"stream[%d].vcp_id: %d "
"stream[%d].slot_count: %d\n",
i,
@@ -2287,21 +2289,24 @@ void core_link_enable_stream(
struct pipe_ctx *pipe_ctx)
{
struct dc *core_dc = pipe_ctx->stream->ctx->dc;
-
+ struct dc_context *dc_ctx = pipe_ctx->stream->ctx;
enum dc_status status;
/* eDP lit up by bios already, no need to enable again. */
if (pipe_ctx->stream->signal == SIGNAL_TYPE_EDP &&
core_dc->apply_edp_fast_boot_optimization) {
core_dc->apply_edp_fast_boot_optimization = false;
+ pipe_ctx->stream->dpms_off = false;
return;
}
+ if (pipe_ctx->stream->dpms_off)
+ return;
+
status = enable_link(state, pipe_ctx);
if (status != DC_OK) {
- dm_logger_write(pipe_ctx->stream->ctx->logger,
- LOG_WARNING, "enabling link %u failed: %d\n",
+ DC_LOG_WARNING("enabling link %u failed: %d\n",
pipe_ctx->stream->sink->link->link_index,
status);
@@ -2355,11 +2360,14 @@ void core_link_set_avmute(struct pipe_ctx *pipe_ctx, bool enable)
core_dc->hwss.set_avmute(pipe_ctx, enable);
}
-void dc_link_disable_hpd_filter(struct dc_link *link)
+void dc_link_enable_hpd_filter(struct dc_link *link, bool enable)
{
struct gpio *hpd;
- if (!link->is_hpd_filter_disabled) {
+ if (enable) {
+ link->is_hpd_filter_disabled = false;
+ program_hpd_filter(link);
+ } else {
link->is_hpd_filter_disabled = true;
/* Obtain HPD handle */
hpd = get_hpd_gpio(link->ctx->dc_bios, link->link_id, link->ctx->gpio_service);
diff --git a/drivers/gpu/drm/amd/display/dc/core/dc_link_ddc.c b/drivers/gpu/drm/amd/display/dc/core/dc_link_ddc.c
index d5294798b0a5..49c2face1e7a 100644
--- a/drivers/gpu/drm/amd/display/dc/core/dc_link_ddc.c
+++ b/drivers/gpu/drm/amd/display/dc/core/dc_link_ddc.c
@@ -629,7 +629,7 @@ bool dal_ddc_service_query_ddc_data(
return ret;
}
-enum ddc_result dal_ddc_service_read_dpcd_data(
+ssize_t dal_ddc_service_read_dpcd_data(
struct ddc_service *ddc,
bool i2c,
enum i2c_mot_mode mot,
@@ -660,8 +660,9 @@ enum ddc_result dal_ddc_service_read_dpcd_data(
if (dal_i2caux_submit_aux_command(
ddc->ctx->i2caux,
ddc->ddc_pin,
- &command))
- return DDC_RESULT_SUCESSFULL;
+ &command)) {
+ return (ssize_t)command.payloads->length;
+ }
return DDC_RESULT_FAILED_OPERATION;
}
diff --git a/drivers/gpu/drm/amd/display/dc/core/dc_link_dp.c b/drivers/gpu/drm/amd/display/dc/core/dc_link_dp.c
index 604fb0171ee3..3b5053570229 100644
--- a/drivers/gpu/drm/amd/display/dc/core/dc_link_dp.c
+++ b/drivers/gpu/drm/amd/display/dc/core/dc_link_dp.c
@@ -11,6 +11,8 @@
#include "dpcd_defs.h"
#include "resource.h"
+#define DC_LOGGER \
+ link->ctx->logger
/* maximum pre emphasis level allowed for each voltage swing level*/
static const enum dc_pre_emphasis voltage_swing_to_pre_emphasis[] = {
@@ -63,8 +65,7 @@ static void wait_for_training_aux_rd_interval(
udelay(default_wait_in_micro_secs);
- dm_logger_write(link->ctx->logger, LOG_HW_LINK_TRAINING,
- "%s:\n wait = %d\n",
+ DC_LOG_HW_LINK_TRAINING("%s:\n wait = %d\n",
__func__,
default_wait_in_micro_secs);
}
@@ -79,8 +80,7 @@ static void dpcd_set_training_pattern(
&dpcd_pattern.raw,
1);
- dm_logger_write(link->ctx->logger, LOG_HW_LINK_TRAINING,
- "%s\n %x pattern = %x\n",
+ DC_LOG_HW_LINK_TRAINING("%s\n %x pattern = %x\n",
__func__,
DP_TRAINING_PATTERN_SET,
dpcd_pattern.v1_4.TRAINING_PATTERN_SET);
@@ -116,8 +116,7 @@ static void dpcd_set_link_settings(
core_link_write_dpcd(link, DP_DOWNSPREAD_CTRL,
&downspread.raw, sizeof(downspread));
- dm_logger_write(link->ctx->logger, LOG_HW_LINK_TRAINING,
- "%s\n %x rate = %x\n %x lane = %x\n %x spread = %x\n",
+ DC_LOG_HW_LINK_TRAINING("%s\n %x rate = %x\n %x lane = %x\n %x spread = %x\n",
__func__,
DP_LINK_BW_SET,
lt_settings->link_settings.link_rate,
@@ -151,8 +150,7 @@ static enum dpcd_training_patterns
break;
default:
ASSERT(0);
- dm_logger_write(link->ctx->logger, LOG_HW_LINK_TRAINING,
- "%s: Invalid HW Training pattern: %d\n",
+ DC_LOG_HW_LINK_TRAINING("%s: Invalid HW Training pattern: %d\n",
__func__, pattern);
break;
}
@@ -184,8 +182,7 @@ static void dpcd_set_lt_pattern_and_lane_settings(
dpcd_lt_buffer[DP_TRAINING_PATTERN_SET - dpcd_base_lt_offset]
= dpcd_pattern.raw;
- dm_logger_write(link->ctx->logger, LOG_HW_LINK_TRAINING,
- "%s\n %x pattern = %x\n",
+ DC_LOG_HW_LINK_TRAINING("%s\n %x pattern = %x\n",
__func__,
DP_TRAINING_PATTERN_SET,
dpcd_pattern.v1_4.TRAINING_PATTERN_SET);
@@ -219,8 +216,7 @@ static void dpcd_set_lt_pattern_and_lane_settings(
dpcd_lane,
size_in_bytes);
- dm_logger_write(link->ctx->logger, LOG_HW_LINK_TRAINING,
- "%s:\n %x VS set = %x PE set = %x max VS Reached = %x max PE Reached = %x\n",
+ DC_LOG_HW_LINK_TRAINING("%s:\n %x VS set = %x PE set = %x max VS Reached = %x max PE Reached = %x\n",
__func__,
DP_TRAINING_LANE0_SET,
dpcd_lane[0].bits.VOLTAGE_SWING_SET,
@@ -456,14 +452,12 @@ static void get_lane_status_and_drive_settings(
ln_status_updated->raw = dpcd_buf[2];
- dm_logger_write(link->ctx->logger, LOG_HW_LINK_TRAINING,
- "%s:\n%x Lane01Status = %x\n %x Lane23Status = %x\n ",
+ DC_LOG_HW_LINK_TRAINING("%s:\n%x Lane01Status = %x\n %x Lane23Status = %x\n ",
__func__,
DP_LANE0_1_STATUS, dpcd_buf[0],
DP_LANE2_3_STATUS, dpcd_buf[1]);
- dm_logger_write(link->ctx->logger, LOG_HW_LINK_TRAINING,
- "%s:\n %x Lane01AdjustRequest = %x\n %x Lane23AdjustRequest = %x\n",
+ DC_LOG_HW_LINK_TRAINING("%s:\n %x Lane01AdjustRequest = %x\n %x Lane23AdjustRequest = %x\n",
__func__,
DP_ADJUST_REQUEST_LANE0_1,
dpcd_buf[4],
@@ -556,8 +550,7 @@ static void dpcd_set_lane_settings(
}
*/
- dm_logger_write(link->ctx->logger, LOG_HW_LINK_TRAINING,
- "%s\n %x VS set = %x PE set = %x max VS Reached = %x max PE Reached = %x\n",
+ DC_LOG_HW_LINK_TRAINING("%s\n %x VS set = %x PE set = %x max VS Reached = %x max PE Reached = %x\n",
__func__,
DP_TRAINING_LANE0_SET,
dpcd_lane[0].bits.VOLTAGE_SWING_SET,
@@ -669,16 +662,14 @@ static bool perform_post_lt_adj_req_sequence(
}
if (!req_drv_setting_changed) {
- dm_logger_write(link->ctx->logger, LOG_WARNING,
- "%s: Post Link Training Adjust Request Timed out\n",
+ DC_LOG_WARNING("%s: Post Link Training Adjust Request Timed out\n",
__func__);
ASSERT(0);
return true;
}
}
- dm_logger_write(link->ctx->logger, LOG_WARNING,
- "%s: Post Link Training Adjust Request limit reached\n",
+ DC_LOG_WARNING("%s: Post Link Training Adjust Request limit reached\n",
__func__);
ASSERT(0);
@@ -709,6 +700,22 @@ static enum hw_dp_training_pattern get_supported_tp(struct dc_link *link)
return HW_DP_TRAINING_PATTERN_2;
}
+static enum link_training_result get_cr_failure(enum dc_lane_count ln_count,
+ union lane_status *dpcd_lane_status)
+{
+ enum link_training_result result = LINK_TRAINING_SUCCESS;
+
+ if (ln_count >= LANE_COUNT_ONE && !dpcd_lane_status[0].bits.CR_DONE_0)
+ result = LINK_TRAINING_CR_FAIL_LANE0;
+ else if (ln_count >= LANE_COUNT_TWO && !dpcd_lane_status[1].bits.CR_DONE_0)
+ result = LINK_TRAINING_CR_FAIL_LANE1;
+ else if (ln_count >= LANE_COUNT_FOUR && !dpcd_lane_status[2].bits.CR_DONE_0)
+ result = LINK_TRAINING_CR_FAIL_LANE23;
+ else if (ln_count >= LANE_COUNT_FOUR && !dpcd_lane_status[3].bits.CR_DONE_0)
+ result = LINK_TRAINING_CR_FAIL_LANE23;
+ return result;
+}
+
static enum link_training_result perform_channel_equalization_sequence(
struct dc_link *link,
struct link_training_settings *lt_settings)
@@ -771,7 +778,7 @@ static enum link_training_result perform_channel_equalization_sequence(
}
-static bool perform_clock_recovery_sequence(
+static enum link_training_result perform_clock_recovery_sequence(
struct dc_link *link,
struct link_training_settings *lt_settings)
{
@@ -846,11 +853,11 @@ static bool perform_clock_recovery_sequence(
/* 5. check CR done*/
if (is_cr_done(lane_count, dpcd_lane_status))
- return true;
+ return LINK_TRAINING_SUCCESS;
/* 6. max VS reached*/
if (is_max_vs_reached(lt_settings))
- return false;
+ break;
/* 7. same voltage*/
/* Note: VS same for all lanes,
@@ -869,20 +876,19 @@ static bool perform_clock_recovery_sequence(
if (retry_count >= LINK_TRAINING_MAX_CR_RETRY) {
ASSERT(0);
- dm_logger_write(link->ctx->logger, LOG_ERROR,
- "%s: Link Training Error, could not get CR after %d tries. Possibly voltage swing issue",
+ DC_LOG_ERROR("%s: Link Training Error, could not get CR after %d tries. Possibly voltage swing issue",
__func__,
LINK_TRAINING_MAX_CR_RETRY);
}
- return false;
+ return get_cr_failure(lane_count, dpcd_lane_status);
}
-static inline bool perform_link_training_int(
+static inline enum link_training_result perform_link_training_int(
struct dc_link *link,
struct link_training_settings *lt_settings,
- bool status)
+ enum link_training_result status)
{
union lane_count_set lane_count_set = { {0} };
union dpcd_training_pattern dpcd_pattern = { {0} };
@@ -903,9 +909,9 @@ static inline bool perform_link_training_int(
get_supported_tp(link) == HW_DP_TRAINING_PATTERN_4)
return status;
- if (status &&
+ if (status == LINK_TRAINING_SUCCESS &&
perform_post_lt_adj_req_sequence(link, lt_settings) == false)
- status = false;
+ status = LINK_TRAINING_LQA_FAIL;
lane_count_set.bits.LANE_COUNT_SET = lt_settings->link_settings.lane_count;
lane_count_set.bits.ENHANCED_FRAMING = 1;
@@ -928,6 +934,8 @@ enum link_training_result dc_link_dp_perform_link_training(
enum link_training_result status = LINK_TRAINING_SUCCESS;
char *link_rate = "Unknown";
+ char *lt_result = "Unknown";
+
struct link_training_settings lt_settings;
memset(&lt_settings, '\0', sizeof(lt_settings));
@@ -951,22 +959,16 @@ enum link_training_result dc_link_dp_perform_link_training(
/* 2. perform link training (set link training done
* to false is done as well)*/
- if (!perform_clock_recovery_sequence(link, &lt_settings)) {
- status = LINK_TRAINING_CR_FAIL;
- } else {
+ status = perform_clock_recovery_sequence(link, &lt_settings);
+ if (status == LINK_TRAINING_SUCCESS) {
status = perform_channel_equalization_sequence(link,
&lt_settings);
}
if ((status == LINK_TRAINING_SUCCESS) || !skip_video_pattern) {
- if (!perform_link_training_int(link,
+ status = perform_link_training_int(link,
&lt_settings,
- status == LINK_TRAINING_SUCCESS)) {
- /* the next link training setting in this case
- * would be the same as CR failure case.
- */
- status = LINK_TRAINING_CR_FAIL;
- }
+ status);
}
/* 6. print status message*/
@@ -991,13 +993,37 @@ enum link_training_result dc_link_dp_perform_link_training(
break;
}
+ switch (status) {
+ case LINK_TRAINING_SUCCESS:
+ lt_result = "pass";
+ break;
+ case LINK_TRAINING_CR_FAIL_LANE0:
+ lt_result = "CR failed lane0";
+ break;
+ case LINK_TRAINING_CR_FAIL_LANE1:
+ lt_result = "CR failed lane1";
+ break;
+ case LINK_TRAINING_CR_FAIL_LANE23:
+ lt_result = "CR failed lane23";
+ break;
+ case LINK_TRAINING_EQ_FAIL_CR:
+ lt_result = "CR failed in EQ";
+ break;
+ case LINK_TRAINING_EQ_FAIL_EQ:
+ lt_result = "EQ failed";
+ break;
+ case LINK_TRAINING_LQA_FAIL:
+ lt_result = "LQA failed";
+ break;
+ default:
+ break;
+ }
+
/* Connectivity log: link training */
CONN_MSG_LT(link, "%sx%d %s VS=%d, PE=%d",
link_rate,
lt_settings.link_settings.lane_count,
- (status == LINK_TRAINING_SUCCESS) ? "pass" :
- ((status == LINK_TRAINING_CR_FAIL) ? "CR failed" :
- "EQ failed"),
+ lt_result,
lt_settings.lane_settings[0].VOLTAGE_SWING,
lt_settings.lane_settings[0].PRE_EMPHASIS);
@@ -1115,6 +1141,7 @@ bool dp_hbr_verify_link_cap(
dp_cs_id,
cur);
+
if (skip_link_training)
success = true;
else {
@@ -1279,7 +1306,10 @@ static bool decide_fallback_link_setting(
return false;
switch (training_result) {
- case LINK_TRAINING_CR_FAIL:
+ case LINK_TRAINING_CR_FAIL_LANE0:
+ case LINK_TRAINING_CR_FAIL_LANE1:
+ case LINK_TRAINING_CR_FAIL_LANE23:
+ case LINK_TRAINING_LQA_FAIL:
{
if (!reached_minimum_link_rate
(current_link_setting->link_rate)) {
@@ -1290,8 +1320,18 @@ static bool decide_fallback_link_setting(
(current_link_setting->lane_count)) {
current_link_setting->link_rate =
initial_link_settings.link_rate;
- current_link_setting->lane_count =
- reduce_lane_count(
+ if (training_result == LINK_TRAINING_CR_FAIL_LANE0)
+ return false;
+ else if (training_result == LINK_TRAINING_CR_FAIL_LANE1)
+ current_link_setting->lane_count =
+ LANE_COUNT_ONE;
+ else if (training_result ==
+ LINK_TRAINING_CR_FAIL_LANE23)
+ current_link_setting->lane_count =
+ LANE_COUNT_TWO;
+ else
+ current_link_setting->lane_count =
+ reduce_lane_count(
current_link_setting->lane_count);
} else {
return false;
@@ -1556,8 +1596,7 @@ static bool hpd_rx_irq_check_link_loss_status(
if (sink_status_changed ||
!hpd_irq_dpcd_data->bytes.lane_status_updated.bits.INTERLANE_ALIGN_DONE) {
- dm_logger_write(link->ctx->logger, LOG_HW_HPD_IRQ,
- "%s: Link Status changed.\n", __func__);
+ DC_LOG_HW_HPD_IRQ("%s: Link Status changed.\n", __func__);
return_code = true;
@@ -1570,8 +1609,7 @@ static bool hpd_rx_irq_check_link_loss_status(
sizeof(irq_reg_rx_power_state));
if (dpcd_result != DC_OK) {
- dm_logger_write(link->ctx->logger, LOG_HW_HPD_IRQ,
- "%s: DPCD read failed to obtain power state.\n",
+ DC_LOG_HW_HPD_IRQ("%s: DPCD read failed to obtain power state.\n",
__func__);
} else {
if (irq_reg_rx_power_state != DP_SET_POWER_D0)
@@ -1932,8 +1970,7 @@ bool dc_link_handle_hpd_rx_irq(struct dc_link *link, union hpd_irq_data *out_hpd
* PSR and device auto test, refer to function handle_sst_hpd_irq
* in DAL2.1*/
- dm_logger_write(link->ctx->logger, LOG_HW_HPD_IRQ,
- "%s: Got short pulse HPD on link %d\n",
+ DC_LOG_HW_HPD_IRQ("%s: Got short pulse HPD on link %d\n",
__func__, link->link_index);
@@ -1947,8 +1984,7 @@ bool dc_link_handle_hpd_rx_irq(struct dc_link *link, union hpd_irq_data *out_hpd
*out_hpd_irq_dpcd_data = hpd_irq_dpcd_data;
if (result != DC_OK) {
- dm_logger_write(link->ctx->logger, LOG_HW_HPD_IRQ,
- "%s: DPCD read failed to obtain irq data\n",
+ DC_LOG_HW_HPD_IRQ("%s: DPCD read failed to obtain irq data\n",
__func__);
return false;
}
@@ -1966,8 +2002,7 @@ bool dc_link_handle_hpd_rx_irq(struct dc_link *link, union hpd_irq_data *out_hpd
}
if (!allow_hpd_rx_irq(link)) {
- dm_logger_write(link->ctx->logger, LOG_HW_HPD_IRQ,
- "%s: skipping HPD handling on %d\n",
+ DC_LOG_HW_HPD_IRQ("%s: skipping HPD handling on %d\n",
__func__, link->link_index);
return false;
}
diff --git a/drivers/gpu/drm/amd/display/dc/core/dc_link_hwss.c b/drivers/gpu/drm/amd/display/dc/core/dc_link_hwss.c
index bae9b0587e12..7c866a7d5e77 100644
--- a/drivers/gpu/drm/amd/display/dc/core/dc_link_hwss.c
+++ b/drivers/gpu/drm/amd/display/dc/core/dc_link_hwss.c
@@ -279,6 +279,7 @@ void dp_retrain_link_dp_test(struct dc_link *link,
for (i = 0; i < MAX_PIPES; i++) {
if (pipes[i].stream != NULL &&
+ !pipes[i].top_pipe &&
pipes[i].stream->sink != NULL &&
pipes[i].stream->sink->link != NULL &&
pipes[i].stream_res.stream_enc != NULL &&
diff --git a/drivers/gpu/drm/amd/display/dc/core/dc_resource.c b/drivers/gpu/drm/amd/display/dc/core/dc_resource.c
index ce0e9e76eb35..ba3487e97361 100644
--- a/drivers/gpu/drm/amd/display/dc/core/dc_resource.c
+++ b/drivers/gpu/drm/amd/display/dc/core/dc_resource.c
@@ -45,7 +45,8 @@
#include "dcn10/dcn10_resource.h"
#endif
#include "dce120/dce120_resource.h"
-
+#define DC_LOGGER \
+ ctx->logger
enum dce_version resource_parse_asic_id(struct hw_asic_id asic_id)
{
enum dce_version dc_version = DCE_VERSION_UNKNOWN;
@@ -834,7 +835,7 @@ bool resource_build_scaling_params(struct pipe_ctx *pipe_ctx)
struct dc_crtc_timing *timing = &pipe_ctx->stream->timing;
struct view recout_skip = { 0 };
bool res = false;
-
+ struct dc_context *ctx = pipe_ctx->stream->ctx;
/* Important: scaling ratio calculation requires pixel format,
* lb depth calculation requires recout and taps require scaling ratios.
* Inits require viewport, taps, ratios and recout of split pipe
@@ -893,7 +894,7 @@ bool resource_build_scaling_params(struct pipe_ctx *pipe_ctx)
/* May need to re-check lb size after this in some obscure scenario */
calculate_inits_and_adj_vp(pipe_ctx, &recout_skip);
- dm_logger_write(pipe_ctx->stream->ctx->logger, LOG_SCALER,
+ DC_LOG_SCALER(
"%s: Viewport:\nheight:%d width:%d x:%d "
"y:%d\n dst_rect:\nheight:%d width:%d x:%d "
"y:%d\n",
@@ -1123,6 +1124,7 @@ bool dc_add_plane_to_context(
ASSERT(tail_pipe);
free_pipe->stream_res.tg = tail_pipe->stream_res.tg;
+ free_pipe->stream_res.abm = tail_pipe->stream_res.abm;
free_pipe->stream_res.opp = tail_pipe->stream_res.opp;
free_pipe->stream_res.stream_enc = tail_pipe->stream_res.stream_enc;
free_pipe->stream_res.audio = tail_pipe->stream_res.audio;
@@ -1735,6 +1737,10 @@ enum dc_status resource_map_pool_resources(
pipe_ctx->stream_res.audio, true);
}
+ /* Add ABM to the resource if on EDP */
+ if (pipe_ctx->stream && dc_is_embedded_signal(pipe_ctx->stream->signal))
+ pipe_ctx->stream_res.abm = pool->abm;
+
for (i = 0; i < context->stream_count; i++)
if (context->streams[i] == stream) {
context->stream_status[i].primary_otg_inst = pipe_ctx->stream_res.tg->inst;
@@ -2436,7 +2442,7 @@ static void set_vsc_info_packet(
unsigned int i;
/*VSC packet set to 2 when DP revision >= 1.2*/
- if (stream->sink->link->dpcd_caps.dpcd_rev.raw >= DPCD_REV_12) {
+ if (stream->psr_version != 0) {
vscPacketRevision = 2;
}
diff --git a/drivers/gpu/drm/amd/display/dc/core/dc_stream.c b/drivers/gpu/drm/amd/display/dc/core/dc_stream.c
index 87a193ac2883..ce0747ed0f00 100644
--- a/drivers/gpu/drm/amd/display/dc/core/dc_stream.c
+++ b/drivers/gpu/drm/amd/display/dc/core/dc_stream.c
@@ -198,7 +198,7 @@ bool dc_stream_set_cursor_attributes(
for (i = 0; i < MAX_PIPES; i++) {
struct pipe_ctx *pipe_ctx = &res_ctx->pipe_ctx[i];
- if (pipe_ctx->stream != stream || (!pipe_ctx->plane_res.xfm && !pipe_ctx->plane_res.dpp))
+ if (pipe_ctx->stream != stream)
continue;
if (pipe_ctx->top_pipe && pipe_ctx->plane_state != pipe_ctx->top_pipe->plane_state)
continue;
@@ -237,7 +237,8 @@ bool dc_stream_set_cursor_position(
if (pipe_ctx->stream != stream ||
(!pipe_ctx->plane_res.mi && !pipe_ctx->plane_res.hubp) ||
!pipe_ctx->plane_state ||
- (!pipe_ctx->plane_res.xfm && !pipe_ctx->plane_res.dpp))
+ (!pipe_ctx->plane_res.xfm && !pipe_ctx->plane_res.dpp) ||
+ !pipe_ctx->plane_res.ipp)
continue;
core_dc->hwss.set_cursor_position(pipe_ctx);
diff --git a/drivers/gpu/drm/amd/display/dc/dc.h b/drivers/gpu/drm/amd/display/dc/dc.h
index 5bb0e5defaf4..fa4b3c8b3bb7 100644
--- a/drivers/gpu/drm/amd/display/dc/dc.h
+++ b/drivers/gpu/drm/amd/display/dc/dc.h
@@ -38,7 +38,7 @@
#include "inc/compressor.h"
#include "dml/display_mode_lib.h"
-#define DC_VER "3.1.34"
+#define DC_VER "3.1.38"
#define MAX_SURFACES 3
#define MAX_STREAMS 6
@@ -184,6 +184,16 @@ enum wm_report_mode {
WM_REPORT_OVERRIDE = 1,
};
+struct dc_clocks {
+ int dispclk_khz;
+ int max_supported_dppclk_khz;
+ int dppclk_khz;
+ int dcfclk_khz;
+ int socclk_khz;
+ int dcfclk_deep_sleep_khz;
+ int fclk_khz;
+};
+
struct dc_debug {
bool surface_visual_confirm;
bool sanity_checks;
@@ -436,6 +446,7 @@ union surface_update_flags {
struct dc_plane_state {
struct dc_plane_address address;
+ struct dc_plane_flip_time time;
struct scaling_taps scaling_quality;
struct rect src_rect;
struct rect dst_rect;
@@ -546,6 +557,7 @@ struct dc_transfer_func *dc_create_transfer_func(void);
*/
struct dc_flip_addrs {
struct dc_plane_address address;
+ unsigned int flip_timestamp_in_us;
bool flip_immediate;
/* TODO: add flip duration for FreeSync */
};
@@ -694,7 +706,7 @@ enum dc_irq_source dc_interrupt_to_irq_source(
struct dc *dc,
uint32_t src_id,
uint32_t ext_id);
-void dc_interrupt_set(struct dc *dc, enum dc_irq_source src, bool enable);
+bool dc_interrupt_set(struct dc *dc, enum dc_irq_source src, bool enable);
void dc_interrupt_ack(struct dc *dc, enum dc_irq_source src);
enum dc_irq_source dc_get_hpd_irq_source_at_index(
struct dc *dc, uint32_t link_index);
diff --git a/drivers/gpu/drm/amd/display/dc/dc_hw_types.h b/drivers/gpu/drm/amd/display/dc/dc_hw_types.h
index e91ac6811990..b83a7dc2f5a9 100644
--- a/drivers/gpu/drm/amd/display/dc/dc_hw_types.h
+++ b/drivers/gpu/drm/amd/display/dc/dc_hw_types.h
@@ -692,8 +692,18 @@ struct crtc_trigger_info {
enum trigger_delay delay;
};
-struct dc_crtc_timing {
+enum vrr_state {
+ VRR_STATE_OFF = 0,
+ VRR_STATE_VARIABLE,
+ VRR_STATE_FIXED,
+};
+struct dc_crtc_timing_adjust {
+ uint32_t v_total_min;
+ uint32_t v_total_max;
+};
+
+struct dc_crtc_timing {
uint32_t h_total;
uint32_t h_border_left;
uint32_t h_addressable;
diff --git a/drivers/gpu/drm/amd/display/dc/dc_link.h b/drivers/gpu/drm/amd/display/dc/dc_link.h
index ac0f617b43c9..fb4d9eafdc6e 100644
--- a/drivers/gpu/drm/amd/display/dc/dc_link.h
+++ b/drivers/gpu/drm/amd/display/dc/dc_link.h
@@ -197,7 +197,7 @@ bool dc_link_dp_set_test_pattern(
const unsigned char *p_custom_pattern,
unsigned int cust_pattern_size);
-void dc_link_disable_hpd_filter(struct dc_link *link);
+void dc_link_enable_hpd_filter(struct dc_link *link, bool enable);
/*
* DPCD access interfaces
diff --git a/drivers/gpu/drm/amd/display/dc/dc_stream.h b/drivers/gpu/drm/amd/display/dc/dc_stream.h
index 78a2bbe0b272..d017df56b2ba 100644
--- a/drivers/gpu/drm/amd/display/dc/dc_stream.h
+++ b/drivers/gpu/drm/amd/display/dc/dc_stream.h
@@ -48,6 +48,8 @@ struct dc_stream_status {
struct dc_stream_state {
struct dc_sink *sink;
struct dc_crtc_timing timing;
+ struct dc_crtc_timing_adjust timing_adjust;
+ struct vrr_params vrr_params;
struct rect src; /* composition area */
struct rect dst; /* stream addressable area */
@@ -70,9 +72,14 @@ struct dc_stream_state {
bool ignore_msa_timing_param;
/* TODO: custom INFO packets */
/* TODO: ABM info (DMCU) */
- /* TODO: PSR info */
+ /* PSR info */
+ unsigned char psr_version;
/* TODO: CEA VIC */
+ /* DMCU info */
+ unsigned int abm_level;
+ unsigned int bl_pwm_level;
+
/* from core_stream struct */
struct dc_context *ctx;
@@ -105,6 +112,7 @@ struct dc_stream_update {
struct dc_transfer_func *out_transfer_func;
struct dc_hdr_static_metadata *hdr_static_metadata;
enum color_transfer_func color_output_tf;
+ unsigned int *abm_level;
};
bool dc_is_stream_unchanged(
diff --git a/drivers/gpu/drm/amd/display/dc/dc_types.h b/drivers/gpu/drm/amd/display/dc/dc_types.h
index 8811b6f86bff..9441305d3ab5 100644
--- a/drivers/gpu/drm/amd/display/dc/dc_types.h
+++ b/drivers/gpu/drm/amd/display/dc/dc_types.h
@@ -521,6 +521,24 @@ struct audio_info {
struct audio_mode modes[DC_MAX_AUDIO_DESC_COUNT];
};
+struct vrr_params {
+ enum vrr_state state;
+ uint32_t window_min;
+ uint32_t window_max;
+ uint32_t inserted_frame_duration_in_us;
+ uint32_t frames_to_insert;
+ uint32_t frame_counter;
+};
+
+#define DC_PLANE_UPDATE_TIMES_MAX 10
+
+struct dc_plane_flip_time {
+ unsigned int time_elapsed_in_us[DC_PLANE_UPDATE_TIMES_MAX];
+ unsigned int index;
+ unsigned int prev_update_time_in_us;
+};
+
+// Will combine with vrr_params at some point.
struct freesync_context {
bool supported;
bool enabled;
diff --git a/drivers/gpu/drm/amd/display/dc/dce/dce_abm.c b/drivers/gpu/drm/amd/display/dc/dce/dce_abm.c
index b231bd53613e..fe92a1222803 100644
--- a/drivers/gpu/drm/amd/display/dc/dce/dce_abm.c
+++ b/drivers/gpu/drm/amd/display/dc/dce/dce_abm.c
@@ -42,6 +42,8 @@
#define FN(reg_name, field_name) \
abm_dce->abm_shift->field_name, abm_dce->abm_mask->field_name
+#define DC_LOGGER \
+ abm->ctx->logger
#define CTX \
abm_dce->base.ctx
@@ -403,8 +405,7 @@ static bool dce_abm_set_backlight_level(
{
struct dce_abm *abm_dce = TO_DCE_ABM(abm);
- dm_logger_write(abm->ctx->logger, LOG_BACKLIGHT,
- "New Backlight level: %d (0x%X)\n",
+ DC_LOG_BACKLIGHT("New Backlight level: %d (0x%X)\n",
backlight_level, backlight_level);
/* If DMCU is in reset state, DMCU is uninitialized */
diff --git a/drivers/gpu/drm/amd/display/dc/dce/dce_audio.c b/drivers/gpu/drm/amd/display/dc/dce/dce_audio.c
index e366bfd7cf6f..6d5cdcdc8ec9 100644
--- a/drivers/gpu/drm/amd/display/dc/dce/dce_audio.c
+++ b/drivers/gpu/drm/amd/display/dc/dce/dce_audio.c
@@ -33,6 +33,8 @@
#define CTX \
aud->base.ctx
+#define DC_LOGGER \
+ aud->base.ctx->logger
#define REG(reg)\
(aud->regs->reg)
@@ -63,8 +65,7 @@ static void write_indirect_azalia_reg(struct audio *audio,
REG_SET(AZALIA_F0_CODEC_ENDPOINT_DATA, 0,
AZALIA_ENDPOINT_REG_DATA, reg_data);
- dm_logger_write(CTX->logger, LOG_HW_AUDIO,
- "AUDIO:write_indirect_azalia_reg: index: %u data: %u\n",
+ DC_LOG_HW_AUDIO("AUDIO:write_indirect_azalia_reg: index: %u data: %u\n",
reg_index, reg_data);
}
@@ -81,8 +82,7 @@ static uint32_t read_indirect_azalia_reg(struct audio *audio, uint32_t reg_index
/* AZALIA_F0_CODEC_ENDPOINT_DATA endpoint data */
value = REG_READ(AZALIA_F0_CODEC_ENDPOINT_DATA);
- dm_logger_write(CTX->logger, LOG_HW_AUDIO,
- "AUDIO:read_indirect_azalia_reg: index: %u data: %u\n",
+ DC_LOG_HW_AUDIO("AUDIO:read_indirect_azalia_reg: index: %u data: %u\n",
reg_index, value);
return value;
@@ -364,8 +364,7 @@ void dce_aud_az_enable(struct audio *audio)
CLOCK_GATING_DISABLE);
AZ_REG_WRITE(AZALIA_F0_CODEC_PIN_CONTROL_HOT_PLUG_CONTROL, value);
- dm_logger_write(CTX->logger, LOG_HW_AUDIO,
- "\n\t========= AUDIO:dce_aud_az_enable: index: %u data: 0x%x\n",
+ DC_LOG_HW_AUDIO("\n\t========= AUDIO:dce_aud_az_enable: index: %u data: 0x%x\n",
audio->inst, value);
}
@@ -390,8 +389,7 @@ void dce_aud_az_disable(struct audio *audio)
CLOCK_GATING_DISABLE);
AZ_REG_WRITE(AZALIA_F0_CODEC_PIN_CONTROL_HOT_PLUG_CONTROL, value);
value = AZ_REG_READ(AZALIA_F0_CODEC_PIN_CONTROL_HOT_PLUG_CONTROL);
- dm_logger_write(CTX->logger, LOG_HW_AUDIO,
- "\n\t========= AUDIO:dce_aud_az_disable: index: %u data: 0x%x\n",
+ DC_LOG_HW_AUDIO("\n\t========= AUDIO:dce_aud_az_disable: index: %u data: 0x%x\n",
audio->inst, value);
}
@@ -795,8 +793,7 @@ void dce_aud_wall_dto_setup(
crtc_info->calculated_pixel_clock,
&clock_info);
- dm_logger_write(audio->ctx->logger, LOG_HW_AUDIO,\
- "\n%s:Input::requested_pixel_clock = %d"\
+ DC_LOG_HW_AUDIO("\n%s:Input::requested_pixel_clock = %d"\
"calculated_pixel_clock =%d\n"\
"audio_dto_module = %d audio_dto_phase =%d \n\n", __func__,\
crtc_info->requested_pixel_clock,\
diff --git a/drivers/gpu/drm/amd/display/dc/dce/dce_clock_source.c b/drivers/gpu/drm/amd/display/dc/dce/dce_clock_source.c
index 5036b674f68b..0aa2cda60890 100644
--- a/drivers/gpu/drm/amd/display/dc/dce/dce_clock_source.c
+++ b/drivers/gpu/drm/amd/display/dc/dce/dce_clock_source.c
@@ -41,7 +41,8 @@
#define CTX \
clk_src->base.ctx
-
+#define DC_LOGGER \
+ calc_pll_cs->ctx->logger
#undef FN
#define FN(reg_name, field_name) \
clk_src->cs_shift->field_name, clk_src->cs_mask->field_name
@@ -288,7 +289,7 @@ static uint32_t calculate_pixel_clock_pll_dividers(
uint32_t max_ref_divider;
if (pll_settings->adjusted_pix_clk == 0) {
- dm_logger_write(calc_pll_cs->ctx->logger, LOG_ERROR,
+ DC_LOG_ERROR(
"%s Bad requested pixel clock", __func__);
return MAX_PLL_CALC_ERROR;
}
@@ -349,13 +350,13 @@ static uint32_t calculate_pixel_clock_pll_dividers(
* ## SVS Wed 15 Jul 2009 */
if (min_post_divider > max_post_divider) {
- dm_logger_write(calc_pll_cs->ctx->logger, LOG_ERROR,
+ DC_LOG_ERROR(
"%s Post divider range is invalid", __func__);
return MAX_PLL_CALC_ERROR;
}
if (min_ref_divider > max_ref_divider) {
- dm_logger_write(calc_pll_cs->ctx->logger, LOG_ERROR,
+ DC_LOG_ERROR(
"%s Reference divider range is invalid", __func__);
return MAX_PLL_CALC_ERROR;
}
@@ -466,7 +467,7 @@ static uint32_t dce110_get_pix_clk_dividers_helper (
{
uint32_t field = 0;
uint32_t pll_calc_error = MAX_PLL_CALC_ERROR;
-
+ struct calc_pll_clock_source *calc_pll_cs = &clk_src->calc_pll;
/* Check if reference clock is external (not pcie/xtalin)
* HW Dce80 spec:
* 00 - PCIE_REFCLK, 01 - XTALIN, 02 - GENERICA, 03 - GENERICB
@@ -493,7 +494,7 @@ static uint32_t dce110_get_pix_clk_dividers_helper (
if (!pll_adjust_pix_clk(clk_src, pix_clk_params, pll_settings)) {
/* Should never happen, ASSERT and fill up values to be able
* to continue. */
- dm_logger_write(clk_src->base.ctx->logger, LOG_ERROR,
+ DC_LOG_ERROR(
"%s: Failed to adjust pixel clock!!", __func__);
pll_settings->actual_pix_clk =
pix_clk_params->requested_pix_clk;
@@ -556,11 +557,12 @@ static uint32_t dce110_get_pix_clk_dividers(
struct pll_settings *pll_settings)
{
struct dce110_clk_src *clk_src = TO_DCE110_CLK_SRC(cs);
+ struct calc_pll_clock_source *calc_pll_cs = &clk_src->calc_pll;
uint32_t pll_calc_error = MAX_PLL_CALC_ERROR;
if (pix_clk_params == NULL || pll_settings == NULL
|| pix_clk_params->requested_pix_clk == 0) {
- dm_logger_write(clk_src->base.ctx->logger, LOG_ERROR,
+ DC_LOG_ERROR(
"%s: Invalid parameters!!\n", __func__);
return pll_calc_error;
}
@@ -1052,14 +1054,14 @@ static void get_ss_info_from_atombios(
struct spread_spectrum_info *ss_info_cur;
struct spread_spectrum_data *ss_data_cur;
uint32_t i;
-
+ struct calc_pll_clock_source *calc_pll_cs = &clk_src->calc_pll;
if (ss_entries_num == NULL) {
- dm_logger_write(clk_src->base.ctx->logger, LOG_SYNC,
+ DC_LOG_SYNC(
"Invalid entry !!!\n");
return;
}
if (spread_spectrum_data == NULL) {
- dm_logger_write(clk_src->base.ctx->logger, LOG_SYNC,
+ DC_LOG_SYNC(
"Invalid array pointer!!!\n");
return;
}
@@ -1104,7 +1106,7 @@ static void get_ss_info_from_atombios(
++i, ++ss_info_cur, ++ss_data_cur) {
if (ss_info_cur->type.STEP_AND_DELAY_INFO != false) {
- dm_logger_write(clk_src->base.ctx->logger, LOG_SYNC,
+ DC_LOG_SYNC(
"Invalid ATOMBIOS SS Table!!!\n");
goto out_free_data;
}
@@ -1114,9 +1116,9 @@ static void get_ss_info_from_atombios(
if (as_signal == AS_SIGNAL_TYPE_HDMI
&& ss_info_cur->spread_spectrum_percentage > 6){
/* invalid input, do nothing */
- dm_logger_write(clk_src->base.ctx->logger, LOG_SYNC,
+ DC_LOG_SYNC(
"Invalid SS percentage ");
- dm_logger_write(clk_src->base.ctx->logger, LOG_SYNC,
+ DC_LOG_SYNC(
"for HDMI in ATOMBIOS info Table!!!\n");
continue;
}
@@ -1228,12 +1230,12 @@ static bool calc_pll_max_vco_construct(
if (init_data->num_fract_fb_divider_decimal_point == 0 ||
init_data->num_fract_fb_divider_decimal_point_precision >
init_data->num_fract_fb_divider_decimal_point) {
- dm_logger_write(calc_pll_cs->ctx->logger, LOG_ERROR,
+ DC_LOG_ERROR(
"The dec point num or precision is incorrect!");
return false;
}
if (init_data->num_fract_fb_divider_decimal_point_precision == 0) {
- dm_logger_write(calc_pll_cs->ctx->logger, LOG_ERROR,
+ DC_LOG_ERROR(
"Incorrect fract feedback divider precision num!");
return false;
}
diff --git a/drivers/gpu/drm/amd/display/dc/dce/dce_clocks.c b/drivers/gpu/drm/amd/display/dc/dce/dce_clocks.c
index 046658c8498a..78e6beb6cf26 100644
--- a/drivers/gpu/drm/amd/display/dc/dce/dce_clocks.c
+++ b/drivers/gpu/drm/amd/display/dc/dce/dce_clocks.c
@@ -49,6 +49,8 @@
#define CTX \
clk_dce->base.ctx
+#define DC_LOGGER \
+ clk->ctx->logger
/* Max clock values for each state indexed by "enum clocks_state": */
static const struct state_dependent_clocks dce80_max_clks_by_state[] = {
@@ -292,8 +294,7 @@ static enum dm_pp_clocks_state dce_get_required_clocks_state(
low_req_clk = i + 1;
if (low_req_clk > clk->max_clks_state) {
- dm_logger_write(clk->ctx->logger, LOG_WARNING,
- "%s: clocks unsupported disp_clk %d pix_clk %d",
+ DC_LOG_WARNING("%s: clocks unsupported disp_clk %d pix_clk %d",
__func__,
req_clocks->display_clk_khz,
req_clocks->pixel_clk_khz);
@@ -312,8 +313,7 @@ static bool dce_clock_set_min_clocks_state(
if (clocks_state > clk->max_clks_state) {
/*Requested state exceeds max supported state.*/
- dm_logger_write(clk->ctx->logger, LOG_WARNING,
- "Requested state exceeds max supported state");
+ DC_LOG_WARNING("Requested state exceeds max supported state");
return false;
} else if (clocks_state == clk->cur_min_clks_state) {
/*if we're trying to set the same state, we can just return
diff --git a/drivers/gpu/drm/amd/display/dc/dce/dce_dmcu.h b/drivers/gpu/drm/amd/display/dc/dce/dce_dmcu.h
index 1d4546f23135..c24c0e5ea44e 100644
--- a/drivers/gpu/drm/amd/display/dc/dce/dce_dmcu.h
+++ b/drivers/gpu/drm/amd/display/dc/dce/dce_dmcu.h
@@ -46,6 +46,23 @@
SR(SMU_INTERRUPT_CONTROL), \
SR(DC_DMCU_SCRATCH)
+#define DMCU_DCE80_REG_LIST() \
+ SR(DMCU_CTRL), \
+ SR(DMCU_STATUS), \
+ SR(DMCU_RAM_ACCESS_CTRL), \
+ SR(DMCU_IRAM_WR_CTRL), \
+ SR(DMCU_IRAM_WR_DATA), \
+ SR(MASTER_COMM_DATA_REG1), \
+ SR(MASTER_COMM_DATA_REG2), \
+ SR(MASTER_COMM_DATA_REG3), \
+ SR(MASTER_COMM_CMD_REG), \
+ SR(MASTER_COMM_CNTL_REG), \
+ SR(DMCU_IRAM_RD_CTRL), \
+ SR(DMCU_IRAM_RD_DATA), \
+ SR(DMCU_INTERRUPT_TO_UC_EN_MASK), \
+ SR(SMU_INTERRUPT_CONTROL), \
+ SR(DC_DMCU_SCRATCH)
+
#define DMCU_DCE110_COMMON_REG_LIST() \
DMCU_COMMON_REG_LIST_DCE_BASE(), \
SR(DCI_MEM_PWR_STATUS)
@@ -83,6 +100,24 @@
STATIC_SCREEN4_INT_TO_UC_EN, mask_sh), \
DMCU_SF(SMU_INTERRUPT_CONTROL, DC_SMU_INT_ENABLE, mask_sh)
+#define DMCU_MASK_SH_LIST_DCE80(mask_sh) \
+ DMCU_SF(DMCU_CTRL, \
+ DMCU_ENABLE, mask_sh), \
+ DMCU_SF(DMCU_STATUS, \
+ UC_IN_STOP_MODE, mask_sh), \
+ DMCU_SF(DMCU_STATUS, \
+ UC_IN_RESET, mask_sh), \
+ DMCU_SF(DMCU_RAM_ACCESS_CTRL, \
+ IRAM_HOST_ACCESS_EN, mask_sh), \
+ DMCU_SF(DMCU_RAM_ACCESS_CTRL, \
+ IRAM_WR_ADDR_AUTO_INC, mask_sh), \
+ DMCU_SF(DMCU_RAM_ACCESS_CTRL, \
+ IRAM_RD_ADDR_AUTO_INC, mask_sh), \
+ DMCU_SF(MASTER_COMM_CMD_REG, \
+ MASTER_COMM_CMD_REG_BYTE0, mask_sh), \
+ DMCU_SF(MASTER_COMM_CNTL_REG, MASTER_COMM_INTERRUPT, mask_sh), \
+ DMCU_SF(SMU_INTERRUPT_CONTROL, DC_SMU_INT_ENABLE, mask_sh)
+
#define DMCU_MASK_SH_LIST_DCE110(mask_sh) \
DMCU_COMMON_MASK_SH_LIST_DCE_COMMON_BASE(mask_sh), \
DMCU_SF(DCI_MEM_PWR_STATUS, \
diff --git a/drivers/gpu/drm/amd/display/dc/dce/dce_hwseq.c b/drivers/gpu/drm/amd/display/dc/dce/dce_hwseq.c
index 4b8e7ce2de8c..487724345d9d 100644
--- a/drivers/gpu/drm/amd/display/dc/dce/dce_hwseq.c
+++ b/drivers/gpu/drm/amd/display/dc/dce/dce_hwseq.c
@@ -56,7 +56,7 @@ void dce_pipe_control_lock(struct dc *dc,
if (lock && pipe->stream_res.tg->funcs->is_blanked(pipe->stream_res.tg))
return;
- val = REG_GET_4(BLND_V_UPDATE_LOCK[pipe->pipe_idx],
+ val = REG_GET_4(BLND_V_UPDATE_LOCK[pipe->stream_res.tg->inst],
BLND_DCP_GRPH_V_UPDATE_LOCK, &dcp_grph,
BLND_SCL_V_UPDATE_LOCK, &scl,
BLND_BLND_V_UPDATE_LOCK, &blnd,
@@ -67,19 +67,19 @@ void dce_pipe_control_lock(struct dc *dc,
blnd = lock_val;
update_lock_mode = lock_val;
- REG_SET_2(BLND_V_UPDATE_LOCK[pipe->pipe_idx], val,
+ REG_SET_2(BLND_V_UPDATE_LOCK[pipe->stream_res.tg->inst], val,
BLND_DCP_GRPH_V_UPDATE_LOCK, dcp_grph,
BLND_SCL_V_UPDATE_LOCK, scl);
if (hws->masks->BLND_BLND_V_UPDATE_LOCK != 0)
- REG_SET_2(BLND_V_UPDATE_LOCK[pipe->pipe_idx], val,
+ REG_SET_2(BLND_V_UPDATE_LOCK[pipe->stream_res.tg->inst], val,
BLND_BLND_V_UPDATE_LOCK, blnd,
BLND_V_UPDATE_LOCK_MODE, update_lock_mode);
if (hws->wa.blnd_crtc_trigger) {
if (!lock) {
- uint32_t value = REG_READ(CRTC_H_BLANK_START_END[pipe->pipe_idx]);
- REG_WRITE(CRTC_H_BLANK_START_END[pipe->pipe_idx], value);
+ uint32_t value = REG_READ(CRTC_H_BLANK_START_END[pipe->stream_res.tg->inst]);
+ REG_WRITE(CRTC_H_BLANK_START_END[pipe->stream_res.tg->inst], value);
}
}
}
diff --git a/drivers/gpu/drm/amd/display/dc/dce/dce_hwseq.h b/drivers/gpu/drm/amd/display/dc/dce/dce_hwseq.h
index 3336428b1fed..057b8afd74bc 100644
--- a/drivers/gpu/drm/amd/display/dc/dce/dce_hwseq.h
+++ b/drivers/gpu/drm/amd/display/dc/dce/dce_hwseq.h
@@ -190,6 +190,7 @@
SR(D2VGA_CONTROL), \
SR(D3VGA_CONTROL), \
SR(D4VGA_CONTROL), \
+ SR(VGA_TEST_CONTROL), \
SR(DC_IP_REQUEST_CNTL), \
BL_REG_LIST()
@@ -261,6 +262,7 @@ struct dce_hwseq_registers {
uint32_t D2VGA_CONTROL;
uint32_t D3VGA_CONTROL;
uint32_t D4VGA_CONTROL;
+ uint32_t VGA_TEST_CONTROL;
/* MMHUB registers. read only. temporary hack */
uint32_t VM_CONTEXT0_PAGE_TABLE_BASE_ADDR_HI32;
uint32_t VM_CONTEXT0_PAGE_TABLE_BASE_ADDR_LO32;
@@ -327,6 +329,8 @@ struct dce_hwseq_registers {
HWSEQ_DCE10_MASK_SH_LIST(mask_sh),\
SF(DCFEV_CLOCK_CONTROL, DCFEV_CLOCK_ENABLE, mask_sh),\
HWS_SF(, LVTMA_PWRSEQ_CNTL, LVTMA_BLON, mask_sh),\
+ HWS_SF(, LVTMA_PWRSEQ_CNTL, LVTMA_DIGON, mask_sh),\
+ HWS_SF(, LVTMA_PWRSEQ_CNTL, LVTMA_DIGON_OVRD, mask_sh),\
HWS_SF(, LVTMA_PWRSEQ_STATE, LVTMA_PWRSEQ_TARGET_STATE_R, mask_sh),\
HWSEQ_PIXEL_RATE_MASK_SH_LIST(mask_sh, CRTC0_)
@@ -403,7 +407,15 @@ struct dce_hwseq_registers {
HWS_SF(, DOMAIN6_PG_STATUS, DOMAIN6_PGFSM_PWR_STATUS, mask_sh), \
HWS_SF(, DOMAIN7_PG_STATUS, DOMAIN7_PGFSM_PWR_STATUS, mask_sh), \
HWS_SF(, DC_IP_REQUEST_CNTL, IP_REQUEST_EN, mask_sh), \
+ HWS_SF(, D1VGA_CONTROL, D1VGA_MODE_ENABLE, mask_sh),\
+ HWS_SF(, D2VGA_CONTROL, D2VGA_MODE_ENABLE, mask_sh),\
+ HWS_SF(, D3VGA_CONTROL, D3VGA_MODE_ENABLE, mask_sh),\
+ HWS_SF(, D4VGA_CONTROL, D4VGA_MODE_ENABLE, mask_sh),\
+ HWS_SF(, VGA_TEST_CONTROL, VGA_TEST_ENABLE, mask_sh),\
+ HWS_SF(, VGA_TEST_CONTROL, VGA_TEST_RENDER_START, mask_sh),\
HWS_SF(, LVTMA_PWRSEQ_CNTL, LVTMA_BLON, mask_sh), \
+ HWS_SF(, LVTMA_PWRSEQ_CNTL, LVTMA_DIGON, mask_sh), \
+ HWS_SF(, LVTMA_PWRSEQ_CNTL, LVTMA_DIGON_OVRD, mask_sh), \
HWS_SF(, LVTMA_PWRSEQ_STATE, LVTMA_PWRSEQ_TARGET_STATE_R, mask_sh)
#define HWSEQ_REG_FIELD_LIST(type) \
@@ -436,7 +448,9 @@ struct dce_hwseq_registers {
type ENABLE_L1_TLB;\
type SYSTEM_ACCESS_MODE;\
type LVTMA_BLON;\
- type LVTMA_PWRSEQ_TARGET_STATE_R;
+ type LVTMA_PWRSEQ_TARGET_STATE_R;\
+ type LVTMA_DIGON;\
+ type LVTMA_DIGON_OVRD;
#define HWSEQ_DCN_REG_FIELD_LIST(type) \
type HUBP_VTG_SEL; \
@@ -483,7 +497,13 @@ struct dce_hwseq_registers {
type DCFCLK_GATE_DIS; \
type DCHUBBUB_GLOBAL_TIMER_REFDIV; \
type DENTIST_DPPCLK_WDIVIDER; \
- type DENTIST_DISPCLK_WDIVIDER;
+ type DENTIST_DISPCLK_WDIVIDER; \
+ type VGA_TEST_ENABLE; \
+ type VGA_TEST_RENDER_START; \
+ type D1VGA_MODE_ENABLE; \
+ type D2VGA_MODE_ENABLE; \
+ type D3VGA_MODE_ENABLE; \
+ type D4VGA_MODE_ENABLE;
struct dce_hwseq_shift {
HWSEQ_REG_FIELD_LIST(uint8_t)
diff --git a/drivers/gpu/drm/amd/display/dc/dce/dce_link_encoder.c b/drivers/gpu/drm/amd/display/dc/dce/dce_link_encoder.c
index 11f50588b3f4..8167cad7bcf7 100644
--- a/drivers/gpu/drm/amd/display/dc/dce/dce_link_encoder.c
+++ b/drivers/gpu/drm/amd/display/dc/dce/dce_link_encoder.c
@@ -56,6 +56,8 @@
#define CTX \
enc110->base.ctx
+#define DC_LOGGER \
+ enc110->base.ctx->logger
#define REG(reg)\
(enc110->link_regs->reg)
@@ -676,6 +678,7 @@ void dce110_link_encoder_construct(
{
struct bp_encoder_cap_info bp_cap_info = {0};
const struct dc_vbios_funcs *bp_funcs = init_data->ctx->dc_bios->funcs;
+ enum bp_result result = BP_RESULT_OK;
enc110->base.funcs = &dce110_lnk_enc_funcs;
enc110->base.ctx = init_data->ctx;
@@ -750,15 +753,23 @@ void dce110_link_encoder_construct(
enc110->base.preferred_engine = ENGINE_ID_UNKNOWN;
}
+ /* default to one to mirror Windows behavior */
+ enc110->base.features.flags.bits.HDMI_6GB_EN = 1;
+
+ result = bp_funcs->get_encoder_cap_info(enc110->base.ctx->dc_bios,
+ enc110->base.id, &bp_cap_info);
+
/* Override features with DCE-specific values */
- if (BP_RESULT_OK == bp_funcs->get_encoder_cap_info(
- enc110->base.ctx->dc_bios, enc110->base.id,
- &bp_cap_info)) {
+ if (BP_RESULT_OK == result) {
enc110->base.features.flags.bits.IS_HBR2_CAPABLE =
bp_cap_info.DP_HBR2_EN;
enc110->base.features.flags.bits.IS_HBR3_CAPABLE =
bp_cap_info.DP_HBR3_EN;
enc110->base.features.flags.bits.HDMI_6GB_EN = bp_cap_info.HDMI_6GB_EN;
+ } else {
+ DC_LOG_WARNING("%s: Failed to get encoder_cap_info from VBIOS with error code %d!\n",
+ __func__,
+ result);
}
}
@@ -809,7 +820,6 @@ void dce110_link_encoder_hw_init(
struct link_encoder *enc)
{
struct dce110_link_encoder *enc110 = TO_DCE110_LINK_ENC(enc);
- struct dc_context *ctx = enc110->base.ctx;
struct bp_transmitter_control cntl = { 0 };
enum bp_result result;
@@ -827,8 +837,7 @@ void dce110_link_encoder_hw_init(
result = link_transmitter_control(enc110, &cntl);
if (result != BP_RESULT_OK) {
- dm_logger_write(ctx->logger, LOG_ERROR,
- "%s: Failed to execute VBIOS command table!\n",
+ DC_LOG_ERROR("%s: Failed to execute VBIOS command table!\n",
__func__);
BREAK_TO_DEBUGGER();
return;
@@ -904,7 +913,6 @@ void dce110_link_encoder_enable_tmds_output(
uint32_t pixel_clock)
{
struct dce110_link_encoder *enc110 = TO_DCE110_LINK_ENC(enc);
- struct dc_context *ctx = enc110->base.ctx;
struct bp_transmitter_control cntl = { 0 };
enum bp_result result;
@@ -928,8 +936,7 @@ void dce110_link_encoder_enable_tmds_output(
result = link_transmitter_control(enc110, &cntl);
if (result != BP_RESULT_OK) {
- dm_logger_write(ctx->logger, LOG_ERROR,
- "%s: Failed to execute VBIOS command table!\n",
+ DC_LOG_ERROR("%s: Failed to execute VBIOS command table!\n",
__func__);
BREAK_TO_DEBUGGER();
}
@@ -942,7 +949,6 @@ void dce110_link_encoder_enable_dp_output(
enum clock_source_id clock_source)
{
struct dce110_link_encoder *enc110 = TO_DCE110_LINK_ENC(enc);
- struct dc_context *ctx = enc110->base.ctx;
struct bp_transmitter_control cntl = { 0 };
enum bp_result result;
@@ -969,8 +975,7 @@ void dce110_link_encoder_enable_dp_output(
result = link_transmitter_control(enc110, &cntl);
if (result != BP_RESULT_OK) {
- dm_logger_write(ctx->logger, LOG_ERROR,
- "%s: Failed to execute VBIOS command table!\n",
+ DC_LOG_ERROR("%s: Failed to execute VBIOS command table!\n",
__func__);
BREAK_TO_DEBUGGER();
}
@@ -983,7 +988,6 @@ void dce110_link_encoder_enable_dp_mst_output(
enum clock_source_id clock_source)
{
struct dce110_link_encoder *enc110 = TO_DCE110_LINK_ENC(enc);
- struct dc_context *ctx = enc110->base.ctx;
struct bp_transmitter_control cntl = { 0 };
enum bp_result result;
@@ -1010,8 +1014,7 @@ void dce110_link_encoder_enable_dp_mst_output(
result = link_transmitter_control(enc110, &cntl);
if (result != BP_RESULT_OK) {
- dm_logger_write(ctx->logger, LOG_ERROR,
- "%s: Failed to execute VBIOS command table!\n",
+ DC_LOG_ERROR("%s: Failed to execute VBIOS command table!\n",
__func__);
BREAK_TO_DEBUGGER();
}
@@ -1025,7 +1028,6 @@ void dce110_link_encoder_disable_output(
enum signal_type signal)
{
struct dce110_link_encoder *enc110 = TO_DCE110_LINK_ENC(enc);
- struct dc_context *ctx = enc110->base.ctx;
struct bp_transmitter_control cntl = { 0 };
enum bp_result result;
@@ -1053,8 +1055,7 @@ void dce110_link_encoder_disable_output(
result = link_transmitter_control(enc110, &cntl);
if (result != BP_RESULT_OK) {
- dm_logger_write(ctx->logger, LOG_ERROR,
- "%s: Failed to execute VBIOS command table!\n",
+ DC_LOG_ERROR("%s: Failed to execute VBIOS command table!\n",
__func__);
BREAK_TO_DEBUGGER();
return;
diff --git a/drivers/gpu/drm/amd/display/dc/dce/dce_stream_encoder.c b/drivers/gpu/drm/amd/display/dc/dce/dce_stream_encoder.c
index 8146b9079d51..444558ca6533 100644
--- a/drivers/gpu/drm/amd/display/dc/dce/dce_stream_encoder.c
+++ b/drivers/gpu/drm/amd/display/dc/dce/dce_stream_encoder.c
@@ -26,7 +26,8 @@
#include "dc_bios_types.h"
#include "dce_stream_encoder.h"
#include "reg_helper.h"
-
+#define DC_LOGGER \
+ enc110->base.ctx->logger
enum DP_PIXEL_ENCODING {
DP_PIXEL_ENCODING_RGB444 = 0x00000000,
DP_PIXEL_ENCODING_YCBCR422 = 0x00000001,
@@ -197,7 +198,6 @@ static void dce110_update_hdmi_info_packet(
uint32_t packet_index,
const struct encoder_info_packet *info_packet)
{
- struct dc_context *ctx = enc110->base.ctx;
uint32_t cont, send, line;
if (info_packet->valid) {
@@ -277,8 +277,7 @@ static void dce110_update_hdmi_info_packet(
#endif
default:
/* invalid HW packet index */
- dm_logger_write(
- ctx->logger, LOG_WARNING,
+ DC_LOG_WARNING(
"Invalid HW packet index: %s()\n",
__func__);
return;
@@ -1386,7 +1385,7 @@ static void dce110_se_setup_hdmi_audio(
crtc_info->requested_pixel_clock,
crtc_info->calculated_pixel_clock,
&audio_clock_info);
- dm_logger_write(enc->ctx->logger, LOG_HW_AUDIO,
+ DC_LOG_HW_AUDIO(
"\n%s:Input::requested_pixel_clock = %d" \
"calculated_pixel_clock = %d \n", __func__, \
crtc_info->requested_pixel_clock, \
diff --git a/drivers/gpu/drm/amd/display/dc/dce/dce_transform.c b/drivers/gpu/drm/amd/display/dc/dce/dce_transform.c
index ad411dac5639..832c5daada35 100644
--- a/drivers/gpu/drm/amd/display/dc/dce/dce_transform.c
+++ b/drivers/gpu/drm/amd/display/dc/dce/dce_transform.c
@@ -38,6 +38,8 @@
#define CTX \
xfm_dce->base.ctx
+#define DC_LOGGER \
+ xfm_dce->base.ctx->logger
#define IDENTITY_RATIO(ratio) (dal_fixed31_32_u2d19(ratio) == (1 << 19))
#define GAMUT_MATRIX_SIZE 12
@@ -693,8 +695,7 @@ static int dce_transform_get_max_num_of_supported_lines(
break;
default:
- dm_logger_write(xfm_dce->base.ctx->logger, LOG_WARNING,
- "%s: Invalid LB pixel depth",
+ DC_LOG_WARNING("%s: Invalid LB pixel depth",
__func__);
BREAK_TO_DEBUGGER();
break;
@@ -791,8 +792,7 @@ static void dce_transform_set_pixel_storage_depth(
if (!(xfm_dce->lb_pixel_depth_supported & depth)) {
/*we should use unsupported capabilities
* unless it is required by w/a*/
- dm_logger_write(xfm->ctx->logger, LOG_WARNING,
- "%s: Capability not supported",
+ DC_LOG_WARNING("%s: Capability not supported",
__func__);
}
}
@@ -1172,8 +1172,7 @@ static void program_pwl(struct dce_transform *xfm_dce,
}
if (counter == max_tries) {
- dm_logger_write(xfm_dce->base.ctx->logger, LOG_WARNING,
- "%s: regamma lut was not powered on "
+ DC_LOG_WARNING("%s: regamma lut was not powered on "
"in a timely manner,"
" programming still proceeds\n",
__func__);
diff --git a/drivers/gpu/drm/amd/display/dc/dce/dce_transform.h b/drivers/gpu/drm/amd/display/dc/dce/dce_transform.h
index bfc94b4927b9..948281d8b6af 100644
--- a/drivers/gpu/drm/amd/display/dc/dce/dce_transform.h
+++ b/drivers/gpu/drm/amd/display/dc/dce/dce_transform.h
@@ -248,6 +248,7 @@
XFM_SF(DCP0_REGAMMA_CNTLA_REGION_0_1, REGAMMA_CNTLA_EXP_REGION1_LUT_OFFSET, mask_sh),\
XFM_SF(DCP0_REGAMMA_CNTLA_REGION_0_1, REGAMMA_CNTLA_EXP_REGION1_NUM_SEGMENTS, mask_sh),\
XFM_SF(DCP0_REGAMMA_CONTROL, GRPH_REGAMMA_MODE, mask_sh),\
+ XFM_SF(DCP0_REGAMMA_LUT_WRITE_EN_MASK, REGAMMA_LUT_WRITE_EN_MASK, mask_sh),\
XFM_SF(SCL0_SCL_MODE, SCL_MODE, mask_sh), \
XFM_SF(SCL0_SCL_TAP_CONTROL, SCL_H_NUM_OF_TAPS, mask_sh), \
XFM_SF(SCL0_SCL_TAP_CONTROL, SCL_V_NUM_OF_TAPS, mask_sh), \
diff --git a/drivers/gpu/drm/amd/display/dc/dce100/dce100_resource.c b/drivers/gpu/drm/amd/display/dc/dce100/dce100_resource.c
index 3bdbed80f7f8..3092f76bdb75 100644
--- a/drivers/gpu/drm/amd/display/dc/dce100/dce100_resource.c
+++ b/drivers/gpu/drm/amd/display/dc/dce100/dce100_resource.c
@@ -51,6 +51,9 @@
#include "dce/dce_10_0_d.h"
#include "dce/dce_10_0_sh_mask.h"
+#include "dce/dce_dmcu.h"
+#include "dce/dce_abm.h"
+
#ifndef mmMC_HUB_RDREQ_DMIF_LIMIT
#include "gmc/gmc_8_2_d.h"
#include "gmc/gmc_8_2_sh_mask.h"
@@ -320,7 +323,29 @@ static const struct dce110_clk_src_mask cs_mask = {
CS_COMMON_MASK_SH_LIST_DCE_COMMON_BASE(_MASK)
};
+static const struct dce_dmcu_registers dmcu_regs = {
+ DMCU_DCE110_COMMON_REG_LIST()
+};
+
+static const struct dce_dmcu_shift dmcu_shift = {
+ DMCU_MASK_SH_LIST_DCE110(__SHIFT)
+};
+
+static const struct dce_dmcu_mask dmcu_mask = {
+ DMCU_MASK_SH_LIST_DCE110(_MASK)
+};
+
+static const struct dce_abm_registers abm_regs = {
+ ABM_DCE110_COMMON_REG_LIST()
+};
+
+static const struct dce_abm_shift abm_shift = {
+ ABM_MASK_SH_LIST_DCE110(__SHIFT)
+};
+static const struct dce_abm_mask abm_mask = {
+ ABM_MASK_SH_LIST_DCE110(_MASK)
+};
#define DCFE_MEM_PWR_CTRL_REG_BASE 0x1b03
@@ -622,6 +647,12 @@ static void destruct(struct dce110_resource_pool *pool)
if (pool->base.display_clock != NULL)
dce_disp_clk_destroy(&pool->base.display_clock);
+ if (pool->base.abm != NULL)
+ dce_abm_destroy(&pool->base.abm);
+
+ if (pool->base.dmcu != NULL)
+ dce_dmcu_destroy(&pool->base.dmcu);
+
if (pool->base.irqs != NULL)
dal_irq_service_destroy(&pool->base.irqs);
}
@@ -829,6 +860,25 @@ static bool construct(
goto res_create_fail;
}
+ pool->base.dmcu = dce_dmcu_create(ctx,
+ &dmcu_regs,
+ &dmcu_shift,
+ &dmcu_mask);
+ if (pool->base.dmcu == NULL) {
+ dm_error("DC: failed to create dmcu!\n");
+ BREAK_TO_DEBUGGER();
+ goto res_create_fail;
+ }
+
+ pool->base.abm = dce_abm_create(ctx,
+ &abm_regs,
+ &abm_shift,
+ &abm_mask);
+ if (pool->base.abm == NULL) {
+ dm_error("DC: failed to create abm!\n");
+ BREAK_TO_DEBUGGER();
+ goto res_create_fail;
+ }
/* get static clock information for PPLIB or firmware, save
* max_clock_state
diff --git a/drivers/gpu/drm/amd/display/dc/dce110/dce110_compressor.c b/drivers/gpu/drm/amd/display/dc/dce110/dce110_compressor.c
index 6923662413cd..775d3bf0bd39 100644
--- a/drivers/gpu/drm/amd/display/dc/dce110/dce110_compressor.c
+++ b/drivers/gpu/drm/amd/display/dc/dce110/dce110_compressor.c
@@ -34,6 +34,8 @@
#include "dce110_compressor.h"
+#define DC_LOGGER \
+ cp110->base.ctx->logger
#define DCP_REG(reg)\
(reg + cp110->offsets.dcp_offset)
#define DMIF_REG(reg)\
@@ -120,14 +122,10 @@ static void wait_for_fbc_state_changed(
}
if (counter == 10) {
- dm_logger_write(
- cp110->base.ctx->logger, LOG_WARNING,
- "%s: wait counter exceeded, changes to HW not applied",
+ DC_LOG_WARNING("%s: wait counter exceeded, changes to HW not applied",
__func__);
} else {
- dm_logger_write(
- cp110->base.ctx->logger, LOG_SYNC,
- "FBC status changed to %d", enabled);
+ DC_LOG_SYNC("FBC status changed to %d", enabled);
}
@@ -310,9 +308,7 @@ void dce110_compressor_program_compressed_surface_address_and_pitch(
if (compressor->min_compress_ratio == FBC_COMPRESS_RATIO_1TO1)
fbc_pitch = fbc_pitch / 8;
else
- dm_logger_write(
- compressor->ctx->logger, LOG_WARNING,
- "%s: Unexpected DCE11 compression ratio",
+ DC_LOG_WARNING("%s: Unexpected DCE11 compression ratio",
__func__);
/* Clear content first. */
diff --git a/drivers/gpu/drm/amd/display/dc/dce110/dce110_hw_sequencer.c b/drivers/gpu/drm/amd/display/dc/dce110/dce110_hw_sequencer.c
index 0422c72a7579..30dd62f0f5fa 100644
--- a/drivers/gpu/drm/amd/display/dc/dce110/dce110_hw_sequencer.c
+++ b/drivers/gpu/drm/amd/display/dc/dce110/dce110_hw_sequencer.c
@@ -70,6 +70,8 @@
#define CTX \
hws->ctx
+#define DC_LOGGER \
+ ctx->logger
#define REG(reg)\
hws->regs->reg
@@ -682,15 +684,22 @@ void dce110_enable_stream(struct pipe_ctx *pipe_ctx)
struct dc_crtc_timing *timing = &pipe_ctx->stream->timing;
struct dc_link *link = pipe_ctx->stream->sink->link;
- /* 1. update AVI info frame (HDMI, DP)
- * we always need to update info frame
- */
+
uint32_t active_total_with_borders;
uint32_t early_control = 0;
struct timing_generator *tg = pipe_ctx->stream_res.tg;
- /* TODOFPGA may change to hwss.update_info_frame */
+ /* For MST, there are multiply stream go to only one link.
+ * connect DIG back_end to front_end while enable_stream and
+ * disconnect them during disable_stream
+ * BY this, it is logic clean to separate stream and link */
+ link->link_enc->funcs->connect_dig_be_to_fe(link->link_enc,
+ pipe_ctx->stream_res.stream_enc->id, true);
+
+ /* update AVI info frame (HDMI, DP)*/
+ /* TODO: FPGA may change to hwss.update_info_frame */
dce110_update_info_frame(pipe_ctx);
+
/* enable early control to avoid corruption on DP monitor*/
active_total_with_borders =
timing->h_addressable
@@ -711,12 +720,8 @@ void dce110_enable_stream(struct pipe_ctx *pipe_ctx)
pipe_ctx->stream_res.stream_enc->funcs->dp_audio_enable(pipe_ctx->stream_res.stream_enc);
}
- /* For MST, there are multiply stream go to only one link.
- * connect DIG back_end to front_end while enable_stream and
- * disconnect them during disable_stream
- * BY this, it is logic clean to separate stream and link */
- link->link_enc->funcs->connect_dig_be_to_fe(link->link_enc,
- pipe_ctx->stream_res.stream_enc->id, true);
+
+
}
@@ -732,10 +737,14 @@ static bool is_panel_backlight_on(struct dce_hwseq *hws)
static bool is_panel_powered_on(struct dce_hwseq *hws)
{
- uint32_t value;
+ uint32_t pwr_seq_state, dig_on, dig_on_ovrd;
+
+
+ REG_GET(LVTMA_PWRSEQ_STATE, LVTMA_PWRSEQ_TARGET_STATE_R, &pwr_seq_state);
+
+ REG_GET_2(LVTMA_PWRSEQ_CNTL, LVTMA_DIGON, &dig_on, LVTMA_DIGON_OVRD, &dig_on_ovrd);
- REG_GET(LVTMA_PWRSEQ_STATE, LVTMA_PWRSEQ_TARGET_STATE_R, &value);
- return value == 1;
+ return (pwr_seq_state == 1) || (dig_on == 1 && dig_on_ovrd == 1);
}
static enum bp_result link_transmitter_control(
@@ -816,7 +825,7 @@ void hwss_edp_wait_for_hpd_ready(
dal_gpio_destroy_irq(&hpd);
if (false == edp_hpd_high) {
- dm_logger_write(ctx->logger, LOG_ERROR,
+ DC_LOG_ERROR(
"%s: wait timed out!\n", __func__);
}
}
@@ -840,7 +849,7 @@ void hwss_edp_power_control(
if (power_up != is_panel_powered_on(hwseq)) {
/* Send VBIOS command to prompt eDP panel power */
- dm_logger_write(ctx->logger, LOG_HW_RESUME_S3,
+ DC_LOG_HW_RESUME_S3(
"%s: Panel Power action: %s\n",
__func__, (power_up ? "On":"Off"));
@@ -856,11 +865,11 @@ void hwss_edp_power_control(
bp_result = link_transmitter_control(ctx->dc_bios, &cntl);
if (bp_result != BP_RESULT_OK)
- dm_logger_write(ctx->logger, LOG_ERROR,
+ DC_LOG_ERROR(
"%s: Panel Power bp_result: %d\n",
__func__, bp_result);
} else {
- dm_logger_write(ctx->logger, LOG_HW_RESUME_S3,
+ DC_LOG_HW_RESUME_S3(
"%s: Skipping Panel Power action: %s\n",
__func__, (power_up ? "On":"Off"));
}
@@ -886,7 +895,7 @@ void hwss_edp_backlight_control(
}
if (enable && is_panel_backlight_on(hws)) {
- dm_logger_write(ctx->logger, LOG_HW_RESUME_S3,
+ DC_LOG_HW_RESUME_S3(
"%s: panel already powered up. Do nothing.\n",
__func__);
return;
@@ -894,7 +903,7 @@ void hwss_edp_backlight_control(
/* Send VBIOS command to control eDP panel backlight */
- dm_logger_write(ctx->logger, LOG_HW_RESUME_S3,
+ DC_LOG_HW_RESUME_S3(
"%s: backlight action: %s\n",
__func__, (enable ? "On":"Off"));
@@ -997,8 +1006,10 @@ void dce110_unblank_stream(struct pipe_ctx *pipe_ctx,
if (dc_is_dp_signal(pipe_ctx->stream->signal))
pipe_ctx->stream_res.stream_enc->funcs->dp_unblank(pipe_ctx->stream_res.stream_enc, &params);
- if (link->local_sink && link->local_sink->sink_signal == SIGNAL_TYPE_EDP)
+ if (link->local_sink && link->local_sink->sink_signal == SIGNAL_TYPE_EDP) {
link->dc->hwss.edp_backlight_control(link, true);
+ stream->bl_pwm_level = 0;
+ }
}
void dce110_blank_stream(struct pipe_ctx *pipe_ctx)
{
@@ -1123,7 +1134,7 @@ static void build_audio_output(
static void get_surface_visual_confirm_color(const struct pipe_ctx *pipe_ctx,
struct tg_color *color)
{
- uint32_t color_value = MAX_TG_COLOR_VALUE * (4 - pipe_ctx->pipe_idx) / 4;
+ uint32_t color_value = MAX_TG_COLOR_VALUE * (4 - pipe_ctx->stream_res.tg->inst) / 4;
switch (pipe_ctx->plane_res.scl_data.format) {
case PIXEL_FORMAT_ARGB8888:
@@ -1320,10 +1331,8 @@ static enum dc_status apply_single_controller_ctx_to_hw(
resource_build_info_frame(pipe_ctx);
dce110_update_info_frame(pipe_ctx);
- if (!pipe_ctx_old->stream) {
- if (!pipe_ctx->stream->dpms_off)
- core_link_enable_stream(context, pipe_ctx);
- }
+ if (!pipe_ctx_old->stream)
+ core_link_enable_stream(context, pipe_ctx);
pipe_ctx->plane_res.scl_data.lb_params.alpha_en = pipe_ctx->bottom_pipe != 0;
@@ -2103,9 +2112,6 @@ enum dc_status dce110_apply_ctx_to_hw(
return status;
}
- /* pplib is notified if disp_num changed */
- dc->hwss.set_bandwidth(dc, context, true);
-
/* to save power */
apply_min_clocks(dc, context, &clocks_state, false);
@@ -2689,7 +2695,7 @@ static void dce110_program_front_end_for_pipe(
struct xfm_grph_csc_adjustment adjust;
struct out_csc_color_matrix tbl_entry;
unsigned int i;
-
+ struct dc_context *ctx = dc->ctx;
memset(&tbl_entry, 0, sizeof(tbl_entry));
if (dc->current_state)
@@ -2764,7 +2770,7 @@ static void dce110_program_front_end_for_pipe(
if (pipe_ctx->plane_state->update_flags.bits.full_update)
dc->hwss.set_output_transfer_func(pipe_ctx, pipe_ctx->stream);
- dm_logger_write(dc->ctx->logger, LOG_SURFACE,
+ DC_LOG_SURFACE(
"Pipe:%d 0x%x: addr hi:0x%x, "
"addr low:0x%x, "
"src: %d, %d, %d,"
@@ -2787,7 +2793,7 @@ static void dce110_program_front_end_for_pipe(
pipe_ctx->plane_state->clip_rect.width,
pipe_ctx->plane_state->clip_rect.height);
- dm_logger_write(dc->ctx->logger, LOG_SURFACE,
+ DC_LOG_SURFACE(
"Pipe %d: width, height, x, y\n"
"viewport:%d, %d, %d, %d\n"
"recout: %d, %d, %d, %d\n",
@@ -2933,15 +2939,18 @@ void dce110_set_cursor_attribute(struct pipe_ctx *pipe_ctx)
{
struct dc_cursor_attributes *attributes = &pipe_ctx->stream->cursor_attributes;
- if (pipe_ctx->plane_res.ipp->funcs->ipp_cursor_set_attributes)
+ if (pipe_ctx->plane_res.ipp &&
+ pipe_ctx->plane_res.ipp->funcs->ipp_cursor_set_attributes)
pipe_ctx->plane_res.ipp->funcs->ipp_cursor_set_attributes(
pipe_ctx->plane_res.ipp, attributes);
- if (pipe_ctx->plane_res.mi->funcs->set_cursor_attributes)
+ if (pipe_ctx->plane_res.mi &&
+ pipe_ctx->plane_res.mi->funcs->set_cursor_attributes)
pipe_ctx->plane_res.mi->funcs->set_cursor_attributes(
pipe_ctx->plane_res.mi, attributes);
- if (pipe_ctx->plane_res.xfm->funcs->set_cursor_attributes)
+ if (pipe_ctx->plane_res.xfm &&
+ pipe_ctx->plane_res.xfm->funcs->set_cursor_attributes)
pipe_ctx->plane_res.xfm->funcs->set_cursor_attributes(
pipe_ctx->plane_res.xfm, attributes);
}
diff --git a/drivers/gpu/drm/amd/display/dc/dce110/dce110_resource.c b/drivers/gpu/drm/amd/display/dc/dce110/dce110_resource.c
index c4e877ac95d3..b1f14be20fdf 100644
--- a/drivers/gpu/drm/amd/display/dc/dce110/dce110_resource.c
+++ b/drivers/gpu/drm/amd/display/dc/dce110/dce110_resource.c
@@ -52,6 +52,8 @@
#include "dce/dce_abm.h"
#include "dce/dce_dmcu.h"
+#define DC_LOGGER \
+ dc->ctx->logger
#if defined(CONFIG_DRM_AMD_DC_FBC)
#include "dce110/dce110_compressor.h"
#endif
@@ -771,8 +773,7 @@ static bool dce110_validate_bandwidth(
{
bool result = false;
- dm_logger_write(
- dc->ctx->logger, LOG_BANDWIDTH_CALCS,
+ DC_LOG_BANDWIDTH_CALCS(
"%s: start",
__func__);
@@ -786,8 +787,7 @@ static bool dce110_validate_bandwidth(
result = true;
if (!result)
- dm_logger_write(dc->ctx->logger, LOG_BANDWIDTH_VALIDATION,
- "%s: %dx%d@%d Bandwidth validation failed!\n",
+ DC_LOG_BANDWIDTH_VALIDATION("%s: %dx%d@%d Bandwidth validation failed!\n",
__func__,
context->streams[0]->timing.h_addressable,
context->streams[0]->timing.v_addressable,
@@ -846,6 +846,16 @@ static bool dce110_validate_bandwidth(
return result;
}
+enum dc_status dce110_validate_plane(const struct dc_plane_state *plane_state,
+ struct dc_caps *caps)
+{
+ if (((plane_state->dst_rect.width * 2) < plane_state->src_rect.width) ||
+ ((plane_state->dst_rect.height * 2) < plane_state->src_rect.height))
+ return DC_FAIL_SURFACE_VALIDATE;
+
+ return DC_OK;
+}
+
static bool dce110_validate_surface_sets(
struct dc_state *context)
{
@@ -869,6 +879,13 @@ static bool dce110_validate_surface_sets(
plane->src_rect.height > 1080))
return false;
+ /* we don't have the logic to support underlay
+ * only yet so block the use case where we get
+ * NV12 plane as top layer
+ */
+ if (j == 0)
+ return false;
+
/* irrespective of plane format,
* stream should be RGB encoded
*/
@@ -1021,6 +1038,7 @@ static const struct resource_funcs dce110_res_pool_funcs = {
.link_enc_create = dce110_link_encoder_create,
.validate_guaranteed = dce110_validate_guaranteed,
.validate_bandwidth = dce110_validate_bandwidth,
+ .validate_plane = dce110_validate_plane,
.acquire_idle_pipe_for_layer = dce110_acquire_underlay,
.add_stream_to_ctx = dce110_add_stream_to_ctx,
.validate_global = dce110_validate_global
diff --git a/drivers/gpu/drm/amd/display/dc/dce110/dce110_timing_generator_v.c b/drivers/gpu/drm/amd/display/dc/dce110/dce110_timing_generator_v.c
index 59b4cd329715..8ad04816e7d3 100644
--- a/drivers/gpu/drm/amd/display/dc/dce110/dce110_timing_generator_v.c
+++ b/drivers/gpu/drm/amd/display/dc/dce110/dce110_timing_generator_v.c
@@ -38,6 +38,8 @@
#include "timing_generator.h"
+#define DC_LOGGER \
+ tg->ctx->logger
/** ********************************************************************************
*
* DCE11 Timing Generator Implementation
@@ -606,8 +608,7 @@ static uint32_t dce110_timing_generator_v_get_vblank_counter(struct timing_gener
static bool dce110_timing_generator_v_did_triggered_reset_occur(
struct timing_generator *tg)
{
- dm_logger_write(tg->ctx->logger, LOG_ERROR,
- "Timing Sync not supported on underlay pipe\n");
+ DC_LOG_ERROR("Timing Sync not supported on underlay pipe\n");
return false;
}
@@ -615,8 +616,7 @@ static void dce110_timing_generator_v_setup_global_swap_lock(
struct timing_generator *tg,
const struct dcp_gsl_params *gsl_params)
{
- dm_logger_write(tg->ctx->logger, LOG_ERROR,
- "Timing Sync not supported on underlay pipe\n");
+ DC_LOG_ERROR("Timing Sync not supported on underlay pipe\n");
return;
}
@@ -624,24 +624,21 @@ static void dce110_timing_generator_v_enable_reset_trigger(
struct timing_generator *tg,
int source_tg_inst)
{
- dm_logger_write(tg->ctx->logger, LOG_ERROR,
- "Timing Sync not supported on underlay pipe\n");
+ DC_LOG_ERROR("Timing Sync not supported on underlay pipe\n");
return;
}
static void dce110_timing_generator_v_disable_reset_trigger(
struct timing_generator *tg)
{
- dm_logger_write(tg->ctx->logger, LOG_ERROR,
- "Timing Sync not supported on underlay pipe\n");
+ DC_LOG_ERROR("Timing Sync not supported on underlay pipe\n");
return;
}
static void dce110_timing_generator_v_tear_down_global_swap_lock(
struct timing_generator *tg)
{
- dm_logger_write(tg->ctx->logger, LOG_ERROR,
- "Timing Sync not supported on underlay pipe\n");
+ DC_LOG_ERROR("Timing Sync not supported on underlay pipe\n");
return;
}
diff --git a/drivers/gpu/drm/amd/display/dc/dce110/dce110_transform_v.c b/drivers/gpu/drm/amd/display/dc/dce110/dce110_transform_v.c
index 47390dc58306..8ba3c12fc608 100644
--- a/drivers/gpu/drm/amd/display/dc/dce110/dce110_transform_v.c
+++ b/drivers/gpu/drm/amd/display/dc/dce110/dce110_transform_v.c
@@ -30,6 +30,8 @@
#include "dce/dce_11_0_sh_mask.h"
#define SCLV_PHASES 64
+#define DC_LOGGER \
+ xfm->ctx->logger
struct sclv_ratios_inits {
uint32_t h_int_scale_ratio_luma;
@@ -670,8 +672,7 @@ static void dce110_xfmv_set_pixel_storage_depth(
if (!(xfm_dce->lb_pixel_depth_supported & depth)) {
/*we should use unsupported capabilities
* unless it is required by w/a*/
- dm_logger_write(xfm->ctx->logger, LOG_WARNING,
- "%s: Capability not supported",
+ DC_LOG_WARNING("%s: Capability not supported",
__func__);
}
}
diff --git a/drivers/gpu/drm/amd/display/dc/dce112/dce112_compressor.c b/drivers/gpu/drm/amd/display/dc/dce112/dce112_compressor.c
index 69649928768c..faae12cf7968 100644
--- a/drivers/gpu/drm/amd/display/dc/dce112/dce112_compressor.c
+++ b/drivers/gpu/drm/amd/display/dc/dce112/dce112_compressor.c
@@ -33,7 +33,8 @@
#include "include/logger_interface.h"
#include "dce112_compressor.h"
-
+#define DC_LOGGER \
+ cp110->base.ctx->logger
#define DCP_REG(reg)\
(reg + cp110->offsets.dcp_offset)
#define DMIF_REG(reg)\
@@ -129,8 +130,7 @@ static uint32_t lpt_memory_control_config(struct dce112_compressor *cp110,
LOW_POWER_TILING_NUM_PIPES);
break;
default:
- dm_logger_write(
- cp110->base.ctx->logger, LOG_WARNING,
+ DC_LOG_WARNING(
"%s: Invalid LPT NUM_PIPES!!!",
__func__);
break;
@@ -175,8 +175,7 @@ static uint32_t lpt_memory_control_config(struct dce112_compressor *cp110,
LOW_POWER_TILING_NUM_BANKS);
break;
default:
- dm_logger_write(
- cp110->base.ctx->logger, LOG_WARNING,
+ DC_LOG_WARNING(
"%s: Invalid LPT NUM_BANKS!!!",
__func__);
break;
@@ -209,8 +208,7 @@ static uint32_t lpt_memory_control_config(struct dce112_compressor *cp110,
LOW_POWER_TILING_PIPE_INTERLEAVE_SIZE);
break;
default:
- dm_logger_write(
- cp110->base.ctx->logger, LOG_WARNING,
+ DC_LOG_WARNING(
"%s: Invalid LPT INTERLEAVE_SIZE!!!",
__func__);
break;
@@ -253,15 +251,13 @@ static uint32_t lpt_memory_control_config(struct dce112_compressor *cp110,
LOW_POWER_TILING_ROW_SIZE);
break;
default:
- dm_logger_write(
- cp110->base.ctx->logger, LOG_WARNING,
+ DC_LOG_WARNING(
"%s: Invalid LPT ROW_SIZE!!!",
__func__);
break;
}
} else {
- dm_logger_write(
- cp110->base.ctx->logger, LOG_WARNING,
+ DC_LOG_WARNING(
"%s: LPT MC Configuration is not provided",
__func__);
}
@@ -311,8 +307,7 @@ static void wait_for_fbc_state_changed(
}
if (counter == 10) {
- dm_logger_write(
- cp110->base.ctx->logger, LOG_WARNING,
+ DC_LOG_WARNING(
"%s: wait counter exceeded, changes to HW not applied",
__func__);
}
@@ -525,8 +520,7 @@ void dce112_compressor_program_compressed_surface_address_and_pitch(
if (compressor->min_compress_ratio == FBC_COMPRESS_RATIO_1TO1)
fbc_pitch = fbc_pitch / 8;
else
- dm_logger_write(
- compressor->ctx->logger, LOG_WARNING,
+ DC_LOG_WARNING(
"%s: Unexpected DCE11 compression ratio",
__func__);
@@ -690,8 +684,7 @@ void dce112_compressor_program_lpt_control(
LOW_POWER_TILING_MODE);
break;
default:
- dm_logger_write(
- compressor->ctx->logger, LOG_WARNING,
+ DC_LOG_WARNING(
"%s: Invalid selected DRAM channels for LPT!!!",
__func__);
break;
diff --git a/drivers/gpu/drm/amd/display/dc/dce112/dce112_resource.c b/drivers/gpu/drm/amd/display/dc/dce112/dce112_resource.c
index c0757dd6c03c..cd1e3f72c44e 100644
--- a/drivers/gpu/drm/amd/display/dc/dce112/dce112_resource.c
+++ b/drivers/gpu/drm/amd/display/dc/dce112/dce112_resource.c
@@ -56,6 +56,8 @@
#include "dce/dce_11_2_sh_mask.h"
#include "dce100/dce100_resource.h"
+#define DC_LOGGER \
+ dc->ctx->logger
#ifndef mmDP_DPHY_INTERNAL_CTRL
#define mmDP_DPHY_INTERNAL_CTRL 0x4aa7
@@ -722,8 +724,7 @@ bool dce112_validate_bandwidth(
{
bool result = false;
- dm_logger_write(
- dc->ctx->logger, LOG_BANDWIDTH_CALCS,
+ DC_LOG_BANDWIDTH_CALCS(
"%s: start",
__func__);
@@ -737,7 +738,7 @@ bool dce112_validate_bandwidth(
result = true;
if (!result)
- dm_logger_write(dc->ctx->logger, LOG_BANDWIDTH_VALIDATION,
+ DC_LOG_BANDWIDTH_VALIDATION(
"%s: Bandwidth validation failed!",
__func__);
diff --git a/drivers/gpu/drm/amd/display/dc/dce80/dce80_resource.c b/drivers/gpu/drm/amd/display/dc/dce80/dce80_resource.c
index a36c14d3d9a8..5d854a37a978 100644
--- a/drivers/gpu/drm/amd/display/dc/dce80/dce80_resource.c
+++ b/drivers/gpu/drm/amd/display/dc/dce80/dce80_resource.c
@@ -53,6 +53,8 @@
#include "reg_helper.h"
+#include "dce/dce_dmcu.h"
+#include "dce/dce_abm.h"
/* TODO remove this include */
#ifndef mmMC_HUB_RDREQ_DMIF_LIMIT
@@ -364,6 +366,29 @@ static const struct resource_caps res_cap_83 = {
.num_pll = 2,
};
+static const struct dce_dmcu_registers dmcu_regs = {
+ DMCU_DCE80_REG_LIST()
+};
+
+static const struct dce_dmcu_shift dmcu_shift = {
+ DMCU_MASK_SH_LIST_DCE80(__SHIFT)
+};
+
+static const struct dce_dmcu_mask dmcu_mask = {
+ DMCU_MASK_SH_LIST_DCE80(_MASK)
+};
+static const struct dce_abm_registers abm_regs = {
+ ABM_DCE110_COMMON_REG_LIST()
+};
+
+static const struct dce_abm_shift abm_shift = {
+ ABM_MASK_SH_LIST_DCE110(__SHIFT)
+};
+
+static const struct dce_abm_mask abm_mask = {
+ ABM_MASK_SH_LIST_DCE110(_MASK)
+};
+
#define CTX ctx
#define REG(reg) mm ## reg
@@ -643,6 +668,12 @@ static void destruct(struct dce110_resource_pool *pool)
}
}
+ if (pool->base.abm != NULL)
+ dce_abm_destroy(&pool->base.abm);
+
+ if (pool->base.dmcu != NULL)
+ dce_dmcu_destroy(&pool->base.dmcu);
+
if (pool->base.dp_clock_source != NULL)
dce80_clock_source_destroy(&pool->base.dp_clock_source);
@@ -850,7 +881,25 @@ static bool dce80_construct(
goto res_create_fail;
}
+ pool->base.dmcu = dce_dmcu_create(ctx,
+ &dmcu_regs,
+ &dmcu_shift,
+ &dmcu_mask);
+ if (pool->base.dmcu == NULL) {
+ dm_error("DC: failed to create dmcu!\n");
+ BREAK_TO_DEBUGGER();
+ goto res_create_fail;
+ }
+ pool->base.abm = dce_abm_create(ctx,
+ &abm_regs,
+ &abm_shift,
+ &abm_mask);
+ if (pool->base.abm == NULL) {
+ dm_error("DC: failed to create abm!\n");
+ BREAK_TO_DEBUGGER();
+ goto res_create_fail;
+ }
if (dm_pp_get_static_clocks(ctx, &static_clk_info))
pool->base.display_clock->max_clks_state =
static_clk_info.max_clocks_state;
@@ -1016,6 +1065,25 @@ static bool dce81_construct(
goto res_create_fail;
}
+ pool->base.dmcu = dce_dmcu_create(ctx,
+ &dmcu_regs,
+ &dmcu_shift,
+ &dmcu_mask);
+ if (pool->base.dmcu == NULL) {
+ dm_error("DC: failed to create dmcu!\n");
+ BREAK_TO_DEBUGGER();
+ goto res_create_fail;
+ }
+
+ pool->base.abm = dce_abm_create(ctx,
+ &abm_regs,
+ &abm_shift,
+ &abm_mask);
+ if (pool->base.abm == NULL) {
+ dm_error("DC: failed to create abm!\n");
+ BREAK_TO_DEBUGGER();
+ goto res_create_fail;
+ }
if (dm_pp_get_static_clocks(ctx, &static_clk_info))
pool->base.display_clock->max_clks_state =
@@ -1178,6 +1246,25 @@ static bool dce83_construct(
goto res_create_fail;
}
+ pool->base.dmcu = dce_dmcu_create(ctx,
+ &dmcu_regs,
+ &dmcu_shift,
+ &dmcu_mask);
+ if (pool->base.dmcu == NULL) {
+ dm_error("DC: failed to create dmcu!\n");
+ BREAK_TO_DEBUGGER();
+ goto res_create_fail;
+ }
+
+ pool->base.abm = dce_abm_create(ctx,
+ &abm_regs,
+ &abm_shift,
+ &abm_mask);
+ if (pool->base.abm == NULL) {
+ dm_error("DC: failed to create abm!\n");
+ BREAK_TO_DEBUGGER();
+ goto res_create_fail;
+ }
if (dm_pp_get_static_clocks(ctx, &static_clk_info))
pool->base.display_clock->max_clks_state =
diff --git a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_cm_common.c b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_cm_common.c
index b3db6397d353..881a1bff94d2 100644
--- a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_cm_common.c
+++ b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_cm_common.c
@@ -416,3 +416,156 @@ bool cm_helper_translate_curve_to_hw_format(
return true;
}
+
+#define NUM_DEGAMMA_REGIONS 12
+
+
+bool cm_helper_translate_curve_to_degamma_hw_format(
+ const struct dc_transfer_func *output_tf,
+ struct pwl_params *lut_params)
+{
+ struct curve_points *arr_points;
+ struct pwl_result_data *rgb_resulted;
+ struct pwl_result_data *rgb;
+ struct pwl_result_data *rgb_plus_1;
+ struct fixed31_32 y_r;
+ struct fixed31_32 y_g;
+ struct fixed31_32 y_b;
+ struct fixed31_32 y1_min;
+ struct fixed31_32 y3_max;
+
+ int32_t region_start, region_end;
+ int32_t i;
+ uint32_t j, k, seg_distr[MAX_REGIONS_NUMBER], increment, start_index, hw_points;
+
+ if (output_tf == NULL || lut_params == NULL || output_tf->type == TF_TYPE_BYPASS)
+ return false;
+
+ PERF_TRACE();
+
+ arr_points = lut_params->arr_points;
+ rgb_resulted = lut_params->rgb_resulted;
+ hw_points = 0;
+
+ memset(lut_params, 0, sizeof(struct pwl_params));
+ memset(seg_distr, 0, sizeof(seg_distr));
+
+ region_start = -NUM_DEGAMMA_REGIONS;
+ region_end = 0;
+
+
+ for (i = region_end - region_start; i < MAX_REGIONS_NUMBER ; i++)
+ seg_distr[i] = -1;
+ /* 12 segments
+ * segments are from 2^-12 to 0
+ */
+ for (i = 0; i < NUM_DEGAMMA_REGIONS ; i++)
+ seg_distr[i] = 4;
+
+ for (k = 0; k < MAX_REGIONS_NUMBER; k++) {
+ if (seg_distr[k] != -1)
+ hw_points += (1 << seg_distr[k]);
+ }
+
+ j = 0;
+ for (k = 0; k < (region_end - region_start); k++) {
+ increment = NUMBER_SW_SEGMENTS / (1 << seg_distr[k]);
+ start_index = (region_start + k + MAX_LOW_POINT) *
+ NUMBER_SW_SEGMENTS;
+ for (i = start_index; i < start_index + NUMBER_SW_SEGMENTS;
+ i += increment) {
+ if (j == hw_points - 1)
+ break;
+ rgb_resulted[j].red = output_tf->tf_pts.red[i];
+ rgb_resulted[j].green = output_tf->tf_pts.green[i];
+ rgb_resulted[j].blue = output_tf->tf_pts.blue[i];
+ j++;
+ }
+ }
+
+ /* last point */
+ start_index = (region_end + MAX_LOW_POINT) * NUMBER_SW_SEGMENTS;
+ rgb_resulted[hw_points - 1].red = output_tf->tf_pts.red[start_index];
+ rgb_resulted[hw_points - 1].green = output_tf->tf_pts.green[start_index];
+ rgb_resulted[hw_points - 1].blue = output_tf->tf_pts.blue[start_index];
+
+ arr_points[0].x = dal_fixed31_32_pow(dal_fixed31_32_from_int(2),
+ dal_fixed31_32_from_int(region_start));
+ arr_points[1].x = dal_fixed31_32_pow(dal_fixed31_32_from_int(2),
+ dal_fixed31_32_from_int(region_end));
+
+ y_r = rgb_resulted[0].red;
+ y_g = rgb_resulted[0].green;
+ y_b = rgb_resulted[0].blue;
+
+ y1_min = dal_fixed31_32_min(y_r, dal_fixed31_32_min(y_g, y_b));
+
+ arr_points[0].y = y1_min;
+ arr_points[0].slope = dal_fixed31_32_div(arr_points[0].y, arr_points[0].x);
+ y_r = rgb_resulted[hw_points - 1].red;
+ y_g = rgb_resulted[hw_points - 1].green;
+ y_b = rgb_resulted[hw_points - 1].blue;
+
+ /* see comment above, m_arrPoints[1].y should be the Y value for the
+ * region end (m_numOfHwPoints), not last HW point(m_numOfHwPoints - 1)
+ */
+ y3_max = dal_fixed31_32_max(y_r, dal_fixed31_32_max(y_g, y_b));
+
+ arr_points[1].y = y3_max;
+
+ arr_points[1].slope = dal_fixed31_32_zero;
+
+ if (output_tf->tf == TRANSFER_FUNCTION_PQ) {
+ /* for PQ, we want to have a straight line from last HW X point,
+ * and the slope to be such that we hit 1.0 at 10000 nits.
+ */
+ const struct fixed31_32 end_value =
+ dal_fixed31_32_from_int(125);
+
+ arr_points[1].slope = dal_fixed31_32_div(
+ dal_fixed31_32_sub(dal_fixed31_32_one, arr_points[1].y),
+ dal_fixed31_32_sub(end_value, arr_points[1].x));
+ }
+
+ lut_params->hw_points_num = hw_points;
+
+ i = 1;
+ for (k = 0; k < MAX_REGIONS_NUMBER && i < MAX_REGIONS_NUMBER; k++) {
+ if (seg_distr[k] != -1) {
+ lut_params->arr_curve_points[k].segments_num =
+ seg_distr[k];
+ lut_params->arr_curve_points[i].offset =
+ lut_params->arr_curve_points[k].offset + (1 << seg_distr[k]);
+ }
+ i++;
+ }
+
+ if (seg_distr[k] != -1)
+ lut_params->arr_curve_points[k].segments_num = seg_distr[k];
+
+ rgb = rgb_resulted;
+ rgb_plus_1 = rgb_resulted + 1;
+
+ i = 1;
+ while (i != hw_points + 1) {
+ if (dal_fixed31_32_lt(rgb_plus_1->red, rgb->red))
+ rgb_plus_1->red = rgb->red;
+ if (dal_fixed31_32_lt(rgb_plus_1->green, rgb->green))
+ rgb_plus_1->green = rgb->green;
+ if (dal_fixed31_32_lt(rgb_plus_1->blue, rgb->blue))
+ rgb_plus_1->blue = rgb->blue;
+
+ rgb->delta_red = dal_fixed31_32_sub(rgb_plus_1->red, rgb->red);
+ rgb->delta_green = dal_fixed31_32_sub(rgb_plus_1->green, rgb->green);
+ rgb->delta_blue = dal_fixed31_32_sub(rgb_plus_1->blue, rgb->blue);
+
+ ++rgb_plus_1;
+ ++rgb;
+ ++i;
+ }
+ cm_helper_convert_to_custom_float(rgb_resulted,
+ lut_params->arr_points,
+ hw_points, false);
+
+ return true;
+}
diff --git a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_cm_common.h b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_cm_common.h
index 64e476b83bcb..7a531b02871f 100644
--- a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_cm_common.h
+++ b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_cm_common.h
@@ -106,4 +106,9 @@ bool cm_helper_translate_curve_to_hw_format(
const struct dc_transfer_func *output_tf,
struct pwl_params *lut_params, bool fixpoint);
+bool cm_helper_translate_curve_to_degamma_hw_format(
+ const struct dc_transfer_func *output_tf,
+ struct pwl_params *lut_params);
+
+
#endif
diff --git a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_dpp.c b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_dpp.c
index 8725cab9ec00..e305c28c98de 100644
--- a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_dpp.c
+++ b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_dpp.c
@@ -432,14 +432,12 @@ void dpp1_dppclk_control(
struct dcn10_dpp *dpp = TO_DCN10_DPP(dpp_base);
if (enable) {
- if (dpp->tf_mask->DPPCLK_RATE_CONTROL) {
+ if (dpp->tf_mask->DPPCLK_RATE_CONTROL)
REG_UPDATE_2(DPP_CONTROL,
DPPCLK_RATE_CONTROL, dppclk_div,
DPP_CLOCK_ENABLE, 1);
- } else {
- ASSERT(dppclk_div == false);
+ else
REG_UPDATE(DPP_CONTROL, DPP_CLOCK_ENABLE, 1);
- }
} else
REG_UPDATE(DPP_CONTROL, DPP_CLOCK_ENABLE, 0);
}
@@ -466,6 +464,7 @@ static const struct dpp_funcs dcn10_dpp_funcs = {
.set_cursor_attributes = dpp1_set_cursor_attributes,
.set_cursor_position = dpp1_set_cursor_position,
.dpp_dppclk_control = dpp1_dppclk_control,
+ .dpp_set_hdr_multiplier = dpp1_set_hdr_multiplier,
};
static struct dpp_caps dcn10_dpp_cap = {
diff --git a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_dpp.h b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_dpp.h
index 07003d9c6bba..17b062a8f88a 100644
--- a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_dpp.h
+++ b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_dpp.h
@@ -113,7 +113,8 @@
SRI(CURSOR0_CONTROL, CNVC_CUR, id), \
SRI(CURSOR0_COLOR0, CNVC_CUR, id), \
SRI(CURSOR0_COLOR1, CNVC_CUR, id), \
- SRI(DPP_CONTROL, DPP_TOP, id)
+ SRI(DPP_CONTROL, DPP_TOP, id), \
+ SRI(CM_HDR_MULT_COEF, CM, id)
@@ -308,7 +309,8 @@
TF_SF(CNVC_CUR0_CURSOR0_CONTROL, CUR0_ENABLE, mask_sh), \
TF_SF(CNVC_CUR0_CURSOR0_COLOR0, CUR0_COLOR0, mask_sh), \
TF_SF(CNVC_CUR0_CURSOR0_COLOR1, CUR0_COLOR1, mask_sh), \
- TF_SF(DPP_TOP0_DPP_CONTROL, DPP_CLOCK_ENABLE, mask_sh)
+ TF_SF(DPP_TOP0_DPP_CONTROL, DPP_CLOCK_ENABLE, mask_sh), \
+ TF_SF(CM0_CM_HDR_MULT_COEF, CM_HDR_MULT_COEF, mask_sh)
#define TF_REG_LIST_SH_MASK_DCN10(mask_sh)\
TF_REG_LIST_SH_MASK_DCN(mask_sh),\
@@ -1012,7 +1014,8 @@
type CUR0_COLOR0; \
type CUR0_COLOR1; \
type DPPCLK_RATE_CONTROL; \
- type DPP_CLOCK_ENABLE;
+ type DPP_CLOCK_ENABLE; \
+ type CM_HDR_MULT_COEF;
struct dcn_dpp_shift {
TF_REG_FIELD_LIST(uint8_t)
@@ -1258,7 +1261,8 @@ struct dcn_dpp_mask {
uint32_t CURSOR0_CONTROL; \
uint32_t CURSOR0_COLOR0; \
uint32_t CURSOR0_COLOR1; \
- uint32_t DPP_CONTROL;
+ uint32_t DPP_CONTROL; \
+ uint32_t CM_HDR_MULT_COEF;
struct dcn_dpp_registers {
DPP_COMMON_REG_VARIABLE_LIST
@@ -1414,6 +1418,10 @@ void dpp1_dppclk_control(
bool dppclk_div,
bool enable);
+void dpp1_set_hdr_multiplier(
+ struct dpp *dpp_base,
+ uint32_t multiplier);
+
void dpp1_construct(struct dcn10_dpp *dpp1,
struct dc_context *ctx,
uint32_t inst,
diff --git a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_dpp_cm.c b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_dpp_cm.c
index bd3fcdfb79c5..fb32975e4b67 100644
--- a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_dpp_cm.c
+++ b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_dpp_cm.c
@@ -804,3 +804,12 @@ void dpp1_program_input_lut(
REG_UPDATE(CM_IGAM_CONTROL, CM_IGAM_LUT_MODE, rama_occupied ? 3 : 2);
REG_GET(CM_IGAM_CONTROL, CM_IGAM_LUT_MODE, &ram_num);
}
+
+void dpp1_set_hdr_multiplier(
+ struct dpp *dpp_base,
+ uint32_t multiplier)
+{
+ struct dcn10_dpp *dpp = TO_DCN10_DPP(dpp_base);
+
+ REG_UPDATE(CM_HDR_MULT_COEF, CM_HDR_MULT_COEF, multiplier);
+}
diff --git a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hubbub.c b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hubbub.c
index eb8317187f30..738f67ffd1b4 100644
--- a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hubbub.c
+++ b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hubbub.c
@@ -30,6 +30,8 @@
#define CTX \
hubbub->ctx
+#define DC_LOGGER \
+ hubbub->ctx->logger
#define REG(reg)\
hubbub->regs->reg
@@ -100,7 +102,6 @@ bool hubbub1_verify_allow_pstate_change_high(
static unsigned int max_sampled_pstate_wait_us; /* data collection */
static bool forced_pstate_allow; /* help with revert wa */
- unsigned int debug_index = 0x7;
unsigned int debug_data;
unsigned int i;
@@ -115,7 +116,9 @@ bool hubbub1_verify_allow_pstate_change_high(
forced_pstate_allow = false;
}
- /* description "3-0: Pipe0 cursor0 QOS
+ /* RV1:
+ * dchubbubdebugind, at: 0x7
+ * description "3-0: Pipe0 cursor0 QOS
* 7-4: Pipe1 cursor0 QOS
* 11-8: Pipe2 cursor0 QOS
* 15-12: Pipe3 cursor0 QOS
@@ -137,7 +140,8 @@ bool hubbub1_verify_allow_pstate_change_high(
* 31: SOC pstate change request
*/
- REG_WRITE(DCHUBBUB_TEST_DEBUG_INDEX, debug_index);
+
+ REG_WRITE(DCHUBBUB_TEST_DEBUG_INDEX, hubbub->debug_test_index_pstate);
for (i = 0; i < pstate_wait_timeout_us; i++) {
debug_data = REG_READ(DCHUBBUB_TEST_DEBUG_DATA);
@@ -145,8 +149,7 @@ bool hubbub1_verify_allow_pstate_change_high(
if (debug_data & (1 << 30)) {
if (i > pstate_wait_expected_timeout_us)
- dm_logger_write(hubbub->ctx->logger, LOG_WARNING,
- "pstate took longer than expected ~%dus\n",
+ DC_LOG_WARNING("pstate took longer than expected ~%dus\n",
i);
return true;
@@ -165,8 +168,7 @@ bool hubbub1_verify_allow_pstate_change_high(
DCHUBBUB_ARB_ALLOW_PSTATE_CHANGE_FORCE_ENABLE, 1);
forced_pstate_allow = true;
- dm_logger_write(hubbub->ctx->logger, LOG_WARNING,
- "pstate TEST_DEBUG_DATA: 0x%X\n",
+ DC_LOG_WARNING("pstate TEST_DEBUG_DATA: 0x%X\n",
debug_data);
return false;
@@ -209,16 +211,14 @@ void hubbub1_program_watermarks(
refclk_mhz, 0x1fffff);
REG_WRITE(DCHUBBUB_ARB_DATA_URGENCY_WATERMARK_A, prog_wm_value);
- dm_logger_write(hubbub->ctx->logger, LOG_BANDWIDTH_CALCS,
- "URGENCY_WATERMARK_A calculated =%d\n"
+ DC_LOG_BANDWIDTH_CALCS("URGENCY_WATERMARK_A calculated =%d\n"
"HW register value = 0x%x\n",
watermarks->a.urgent_ns, prog_wm_value);
prog_wm_value = convert_and_clamp(watermarks->a.pte_meta_urgent_ns,
refclk_mhz, 0x1fffff);
REG_WRITE(DCHUBBUB_ARB_PTE_META_URGENCY_WATERMARK_A, prog_wm_value);
- dm_logger_write(hubbub->ctx->logger, LOG_BANDWIDTH_CALCS,
- "PTE_META_URGENCY_WATERMARK_A calculated =%d\n"
+ DC_LOG_BANDWIDTH_CALCS("PTE_META_URGENCY_WATERMARK_A calculated =%d\n"
"HW register value = 0x%x\n",
watermarks->a.pte_meta_urgent_ns, prog_wm_value);
@@ -227,8 +227,7 @@ void hubbub1_program_watermarks(
watermarks->a.cstate_pstate.cstate_enter_plus_exit_ns,
refclk_mhz, 0x1fffff);
REG_WRITE(DCHUBBUB_ARB_ALLOW_SR_ENTER_WATERMARK_A, prog_wm_value);
- dm_logger_write(hubbub->ctx->logger, LOG_BANDWIDTH_CALCS,
- "SR_ENTER_EXIT_WATERMARK_A calculated =%d\n"
+ DC_LOG_BANDWIDTH_CALCS("SR_ENTER_EXIT_WATERMARK_A calculated =%d\n"
"HW register value = 0x%x\n",
watermarks->a.cstate_pstate.cstate_enter_plus_exit_ns, prog_wm_value);
@@ -237,8 +236,7 @@ void hubbub1_program_watermarks(
watermarks->a.cstate_pstate.cstate_exit_ns,
refclk_mhz, 0x1fffff);
REG_WRITE(DCHUBBUB_ARB_ALLOW_SR_EXIT_WATERMARK_A, prog_wm_value);
- dm_logger_write(hubbub->ctx->logger, LOG_BANDWIDTH_CALCS,
- "SR_EXIT_WATERMARK_A calculated =%d\n"
+ DC_LOG_BANDWIDTH_CALCS("SR_EXIT_WATERMARK_A calculated =%d\n"
"HW register value = 0x%x\n",
watermarks->a.cstate_pstate.cstate_exit_ns, prog_wm_value);
}
@@ -247,8 +245,7 @@ void hubbub1_program_watermarks(
watermarks->a.cstate_pstate.pstate_change_ns,
refclk_mhz, 0x1fffff);
REG_WRITE(DCHUBBUB_ARB_ALLOW_DRAM_CLK_CHANGE_WATERMARK_A, prog_wm_value);
- dm_logger_write(hubbub->ctx->logger, LOG_BANDWIDTH_CALCS,
- "DRAM_CLK_CHANGE_WATERMARK_A calculated =%d\n"
+ DC_LOG_BANDWIDTH_CALCS("DRAM_CLK_CHANGE_WATERMARK_A calculated =%d\n"
"HW register value = 0x%x\n\n",
watermarks->a.cstate_pstate.pstate_change_ns, prog_wm_value);
@@ -257,8 +254,7 @@ void hubbub1_program_watermarks(
prog_wm_value = convert_and_clamp(
watermarks->b.urgent_ns, refclk_mhz, 0x1fffff);
REG_WRITE(DCHUBBUB_ARB_DATA_URGENCY_WATERMARK_B, prog_wm_value);
- dm_logger_write(hubbub->ctx->logger, LOG_BANDWIDTH_CALCS,
- "URGENCY_WATERMARK_B calculated =%d\n"
+ DC_LOG_BANDWIDTH_CALCS("URGENCY_WATERMARK_B calculated =%d\n"
"HW register value = 0x%x\n",
watermarks->b.urgent_ns, prog_wm_value);
@@ -267,8 +263,7 @@ void hubbub1_program_watermarks(
watermarks->b.pte_meta_urgent_ns,
refclk_mhz, 0x1fffff);
REG_WRITE(DCHUBBUB_ARB_PTE_META_URGENCY_WATERMARK_B, prog_wm_value);
- dm_logger_write(hubbub->ctx->logger, LOG_BANDWIDTH_CALCS,
- "PTE_META_URGENCY_WATERMARK_B calculated =%d\n"
+ DC_LOG_BANDWIDTH_CALCS("PTE_META_URGENCY_WATERMARK_B calculated =%d\n"
"HW register value = 0x%x\n",
watermarks->b.pte_meta_urgent_ns, prog_wm_value);
@@ -278,8 +273,7 @@ void hubbub1_program_watermarks(
watermarks->b.cstate_pstate.cstate_enter_plus_exit_ns,
refclk_mhz, 0x1fffff);
REG_WRITE(DCHUBBUB_ARB_ALLOW_SR_ENTER_WATERMARK_B, prog_wm_value);
- dm_logger_write(hubbub->ctx->logger, LOG_BANDWIDTH_CALCS,
- "SR_ENTER_WATERMARK_B calculated =%d\n"
+ DC_LOG_BANDWIDTH_CALCS("SR_ENTER_WATERMARK_B calculated =%d\n"
"HW register value = 0x%x\n",
watermarks->b.cstate_pstate.cstate_enter_plus_exit_ns, prog_wm_value);
@@ -288,8 +282,7 @@ void hubbub1_program_watermarks(
watermarks->b.cstate_pstate.cstate_exit_ns,
refclk_mhz, 0x1fffff);
REG_WRITE(DCHUBBUB_ARB_ALLOW_SR_EXIT_WATERMARK_B, prog_wm_value);
- dm_logger_write(hubbub->ctx->logger, LOG_BANDWIDTH_CALCS,
- "SR_EXIT_WATERMARK_B calculated =%d\n"
+ DC_LOG_BANDWIDTH_CALCS("SR_EXIT_WATERMARK_B calculated =%d\n"
"HW register value = 0x%x\n",
watermarks->b.cstate_pstate.cstate_exit_ns, prog_wm_value);
}
@@ -298,8 +291,7 @@ void hubbub1_program_watermarks(
watermarks->b.cstate_pstate.pstate_change_ns,
refclk_mhz, 0x1fffff);
REG_WRITE(DCHUBBUB_ARB_ALLOW_DRAM_CLK_CHANGE_WATERMARK_B, prog_wm_value);
- dm_logger_write(hubbub->ctx->logger, LOG_BANDWIDTH_CALCS,
- "DRAM_CLK_CHANGE_WATERMARK_B calculated =%d\n\n"
+ DC_LOG_BANDWIDTH_CALCS("DRAM_CLK_CHANGE_WATERMARK_B calculated =%d\n\n"
"HW register value = 0x%x\n",
watermarks->b.cstate_pstate.pstate_change_ns, prog_wm_value);
@@ -307,8 +299,7 @@ void hubbub1_program_watermarks(
prog_wm_value = convert_and_clamp(
watermarks->c.urgent_ns, refclk_mhz, 0x1fffff);
REG_WRITE(DCHUBBUB_ARB_DATA_URGENCY_WATERMARK_C, prog_wm_value);
- dm_logger_write(hubbub->ctx->logger, LOG_BANDWIDTH_CALCS,
- "URGENCY_WATERMARK_C calculated =%d\n"
+ DC_LOG_BANDWIDTH_CALCS("URGENCY_WATERMARK_C calculated =%d\n"
"HW register value = 0x%x\n",
watermarks->c.urgent_ns, prog_wm_value);
@@ -317,8 +308,7 @@ void hubbub1_program_watermarks(
watermarks->c.pte_meta_urgent_ns,
refclk_mhz, 0x1fffff);
REG_WRITE(DCHUBBUB_ARB_PTE_META_URGENCY_WATERMARK_C, prog_wm_value);
- dm_logger_write(hubbub->ctx->logger, LOG_BANDWIDTH_CALCS,
- "PTE_META_URGENCY_WATERMARK_C calculated =%d\n"
+ DC_LOG_BANDWIDTH_CALCS("PTE_META_URGENCY_WATERMARK_C calculated =%d\n"
"HW register value = 0x%x\n",
watermarks->c.pte_meta_urgent_ns, prog_wm_value);
@@ -328,8 +318,7 @@ void hubbub1_program_watermarks(
watermarks->c.cstate_pstate.cstate_enter_plus_exit_ns,
refclk_mhz, 0x1fffff);
REG_WRITE(DCHUBBUB_ARB_ALLOW_SR_ENTER_WATERMARK_C, prog_wm_value);
- dm_logger_write(hubbub->ctx->logger, LOG_BANDWIDTH_CALCS,
- "SR_ENTER_WATERMARK_C calculated =%d\n"
+ DC_LOG_BANDWIDTH_CALCS("SR_ENTER_WATERMARK_C calculated =%d\n"
"HW register value = 0x%x\n",
watermarks->c.cstate_pstate.cstate_enter_plus_exit_ns, prog_wm_value);
@@ -338,8 +327,7 @@ void hubbub1_program_watermarks(
watermarks->c.cstate_pstate.cstate_exit_ns,
refclk_mhz, 0x1fffff);
REG_WRITE(DCHUBBUB_ARB_ALLOW_SR_EXIT_WATERMARK_C, prog_wm_value);
- dm_logger_write(hubbub->ctx->logger, LOG_BANDWIDTH_CALCS,
- "SR_EXIT_WATERMARK_C calculated =%d\n"
+ DC_LOG_BANDWIDTH_CALCS("SR_EXIT_WATERMARK_C calculated =%d\n"
"HW register value = 0x%x\n",
watermarks->c.cstate_pstate.cstate_exit_ns, prog_wm_value);
}
@@ -348,8 +336,7 @@ void hubbub1_program_watermarks(
watermarks->c.cstate_pstate.pstate_change_ns,
refclk_mhz, 0x1fffff);
REG_WRITE(DCHUBBUB_ARB_ALLOW_DRAM_CLK_CHANGE_WATERMARK_C, prog_wm_value);
- dm_logger_write(hubbub->ctx->logger, LOG_BANDWIDTH_CALCS,
- "DRAM_CLK_CHANGE_WATERMARK_C calculated =%d\n\n"
+ DC_LOG_BANDWIDTH_CALCS("DRAM_CLK_CHANGE_WATERMARK_C calculated =%d\n\n"
"HW register value = 0x%x\n",
watermarks->c.cstate_pstate.pstate_change_ns, prog_wm_value);
@@ -357,8 +344,7 @@ void hubbub1_program_watermarks(
prog_wm_value = convert_and_clamp(
watermarks->d.urgent_ns, refclk_mhz, 0x1fffff);
REG_WRITE(DCHUBBUB_ARB_DATA_URGENCY_WATERMARK_D, prog_wm_value);
- dm_logger_write(hubbub->ctx->logger, LOG_BANDWIDTH_CALCS,
- "URGENCY_WATERMARK_D calculated =%d\n"
+ DC_LOG_BANDWIDTH_CALCS("URGENCY_WATERMARK_D calculated =%d\n"
"HW register value = 0x%x\n",
watermarks->d.urgent_ns, prog_wm_value);
@@ -366,8 +352,7 @@ void hubbub1_program_watermarks(
watermarks->d.pte_meta_urgent_ns,
refclk_mhz, 0x1fffff);
REG_WRITE(DCHUBBUB_ARB_PTE_META_URGENCY_WATERMARK_D, prog_wm_value);
- dm_logger_write(hubbub->ctx->logger, LOG_BANDWIDTH_CALCS,
- "PTE_META_URGENCY_WATERMARK_D calculated =%d\n"
+ DC_LOG_BANDWIDTH_CALCS("PTE_META_URGENCY_WATERMARK_D calculated =%d\n"
"HW register value = 0x%x\n",
watermarks->d.pte_meta_urgent_ns, prog_wm_value);
@@ -377,8 +362,7 @@ void hubbub1_program_watermarks(
watermarks->d.cstate_pstate.cstate_enter_plus_exit_ns,
refclk_mhz, 0x1fffff);
REG_WRITE(DCHUBBUB_ARB_ALLOW_SR_ENTER_WATERMARK_D, prog_wm_value);
- dm_logger_write(hubbub->ctx->logger, LOG_BANDWIDTH_CALCS,
- "SR_ENTER_WATERMARK_D calculated =%d\n"
+ DC_LOG_BANDWIDTH_CALCS("SR_ENTER_WATERMARK_D calculated =%d\n"
"HW register value = 0x%x\n",
watermarks->d.cstate_pstate.cstate_enter_plus_exit_ns, prog_wm_value);
@@ -387,8 +371,7 @@ void hubbub1_program_watermarks(
watermarks->d.cstate_pstate.cstate_exit_ns,
refclk_mhz, 0x1fffff);
REG_WRITE(DCHUBBUB_ARB_ALLOW_SR_EXIT_WATERMARK_D, prog_wm_value);
- dm_logger_write(hubbub->ctx->logger, LOG_BANDWIDTH_CALCS,
- "SR_EXIT_WATERMARK_D calculated =%d\n"
+ DC_LOG_BANDWIDTH_CALCS("SR_EXIT_WATERMARK_D calculated =%d\n"
"HW register value = 0x%x\n",
watermarks->d.cstate_pstate.cstate_exit_ns, prog_wm_value);
}
@@ -398,8 +381,7 @@ void hubbub1_program_watermarks(
watermarks->d.cstate_pstate.pstate_change_ns,
refclk_mhz, 0x1fffff);
REG_WRITE(DCHUBBUB_ARB_ALLOW_DRAM_CLK_CHANGE_WATERMARK_D, prog_wm_value);
- dm_logger_write(hubbub->ctx->logger, LOG_BANDWIDTH_CALCS,
- "DRAM_CLK_CHANGE_WATERMARK_D calculated =%d\n"
+ DC_LOG_BANDWIDTH_CALCS("DRAM_CLK_CHANGE_WATERMARK_D calculated =%d\n"
"HW register value = 0x%x\n\n",
watermarks->d.cstate_pstate.pstate_change_ns, prog_wm_value);
@@ -512,5 +494,6 @@ void hubbub1_construct(struct hubbub *hubbub,
hubbub->shifts = hubbub_shift;
hubbub->masks = hubbub_mask;
+ hubbub->debug_test_index_pstate = 0x7;
}
diff --git a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hubbub.h b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hubbub.h
index d5c97844312f..a16e908821a0 100644
--- a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hubbub.h
+++ b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hubbub.h
@@ -185,6 +185,7 @@ struct hubbub {
const struct dcn_hubbub_registers *regs;
const struct dcn_hubbub_shift *shifts;
const struct dcn_hubbub_mask *masks;
+ unsigned int debug_test_index_pstate;
};
void hubbub1_update_dchub(
diff --git a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hw_sequencer.c b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hw_sequencer.c
index 29dc37fbdb26..8b0f6b8a5627 100644
--- a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hw_sequencer.c
+++ b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hw_sequencer.c
@@ -45,6 +45,8 @@
#include "dcn10_hubbub.h"
#include "dcn10_cm_common.h"
+#define DC_LOGGER \
+ ctx->logger
#define CTX \
hws->ctx
#define REG(reg)\
@@ -218,10 +220,34 @@ static void enable_power_gating_plane(
static void disable_vga(
struct dce_hwseq *hws)
{
+ unsigned int in_vga1_mode = 0;
+ unsigned int in_vga2_mode = 0;
+ unsigned int in_vga3_mode = 0;
+ unsigned int in_vga4_mode = 0;
+
+ REG_GET(D1VGA_CONTROL, D1VGA_MODE_ENABLE, &in_vga1_mode);
+ REG_GET(D2VGA_CONTROL, D2VGA_MODE_ENABLE, &in_vga2_mode);
+ REG_GET(D3VGA_CONTROL, D3VGA_MODE_ENABLE, &in_vga3_mode);
+ REG_GET(D4VGA_CONTROL, D4VGA_MODE_ENABLE, &in_vga4_mode);
+
+ if (in_vga1_mode == 0 && in_vga2_mode == 0 &&
+ in_vga3_mode == 0 && in_vga4_mode == 0)
+ return;
+
REG_WRITE(D1VGA_CONTROL, 0);
REG_WRITE(D2VGA_CONTROL, 0);
REG_WRITE(D3VGA_CONTROL, 0);
REG_WRITE(D4VGA_CONTROL, 0);
+
+ /* HW Engineer's Notes:
+ * During switch from vga->extended, if we set the VGA_TEST_ENABLE and
+ * then hit the VGA_TEST_RENDER_START, then the DCHUBP timing gets updated correctly.
+ *
+ * Then vBIOS will have it poll for the VGA_TEST_RENDER_DONE and unset
+ * VGA_TEST_ENABLE, to leave it in the same state as before.
+ */
+ REG_UPDATE(VGA_TEST_CONTROL, VGA_TEST_ENABLE, 1);
+ REG_UPDATE(VGA_TEST_CONTROL, VGA_TEST_RENDER_START, 1);
}
static void dpp_pg_control(
@@ -328,6 +354,7 @@ static void power_on_plane(
struct dce_hwseq *hws,
int plane_id)
{
+ struct dc_context *ctx = hws->ctx;
if (REG(DC_IP_REQUEST_CNTL)) {
REG_SET(DC_IP_REQUEST_CNTL, 0,
IP_REQUEST_EN, 1);
@@ -335,7 +362,7 @@ static void power_on_plane(
hubp_pg_control(hws, plane_id, true);
REG_SET(DC_IP_REQUEST_CNTL, 0,
IP_REQUEST_EN, 0);
- dm_logger_write(hws->ctx->logger, LOG_DEBUG,
+ DC_LOG_DEBUG(
"Un-gated front end for pipe %d\n", plane_id);
}
}
@@ -526,7 +553,7 @@ static void reset_back_end_for_pipe(
struct dc_state *context)
{
int i;
-
+ struct dc_context *ctx = dc->ctx;
if (pipe_ctx->stream_res.stream_enc == NULL) {
pipe_ctx->stream = NULL;
return;
@@ -536,6 +563,22 @@ static void reset_back_end_for_pipe(
/* DPMS may already disable */
if (!pipe_ctx->stream->dpms_off)
core_link_disable_stream(pipe_ctx, FREE_ACQUIRED_RESOURCE);
+ else if (pipe_ctx->stream_res.audio) {
+ /*
+ * if stream is already disabled outside of commit streams path,
+ * audio disable was skipped. Need to do it here
+ */
+ pipe_ctx->stream_res.audio->funcs->az_disable(pipe_ctx->stream_res.audio);
+
+ if (dc->caps.dynamic_audio == true) {
+ /*we have to dynamic arbitrate the audio endpoints*/
+ pipe_ctx->stream_res.audio = NULL;
+ /*we free the resource, need reset is_audio_acquired*/
+ update_audio_usage(&dc->current_state->res_ctx, dc->res_pool, pipe_ctx->stream_res.audio, false);
+ }
+
+ }
+
}
/* by upper caller loop, parent pipe: pipe0, will be reset last.
@@ -556,8 +599,7 @@ static void reset_back_end_for_pipe(
return;
pipe_ctx->stream = NULL;
- dm_logger_write(dc->ctx->logger, LOG_DEBUG,
- "Reset back end for pipe %d, tg:%d\n",
+ DC_LOG_DEBUG("Reset back end for pipe %d, tg:%d\n",
pipe_ctx->pipe_idx, pipe_ctx->stream_res.tg->inst);
}
@@ -607,6 +649,7 @@ static void plane_atomic_power_down(struct dc *dc, struct pipe_ctx *pipe_ctx)
{
struct dce_hwseq *hws = dc->hwseq;
struct dpp *dpp = pipe_ctx->plane_res.dpp;
+ struct dc_context *ctx = dc->ctx;
if (REG(DC_IP_REQUEST_CNTL)) {
REG_SET(DC_IP_REQUEST_CNTL, 0,
@@ -616,7 +659,7 @@ static void plane_atomic_power_down(struct dc *dc, struct pipe_ctx *pipe_ctx)
dpp->funcs->dpp_reset(dpp);
REG_SET(DC_IP_REQUEST_CNTL, 0,
IP_REQUEST_EN, 0);
- dm_logger_write(dc->ctx->logger, LOG_DEBUG,
+ DC_LOG_DEBUG(
"Power gated front end %d\n", pipe_ctx->pipe_idx);
}
}
@@ -656,6 +699,8 @@ static void plane_atomic_disable(struct dc *dc, struct pipe_ctx *pipe_ctx)
static void dcn10_disable_plane(struct dc *dc, struct pipe_ctx *pipe_ctx)
{
+ struct dc_context *ctx = dc->ctx;
+
if (!pipe_ctx->plane_res.hubp || pipe_ctx->plane_res.hubp->power_gated)
return;
@@ -663,8 +708,7 @@ static void dcn10_disable_plane(struct dc *dc, struct pipe_ctx *pipe_ctx)
apply_DEGVIDCN10_253_wa(dc);
- dm_logger_write(dc->ctx->logger, LOG_DC,
- "Power down front end %d\n",
+ DC_LOG_DC("Power down front end %d\n",
pipe_ctx->pipe_idx);
}
@@ -1086,7 +1130,7 @@ static void dcn10_enable_per_frame_crtc_position_reset(
struct dc *core_dc,
struct pipe_ctx *pipe_ctx)
{
- dm_logger_write(core_dc->ctx->logger, LOG_BANDWIDTH_CALCS,
+ DC_LOG_BANDWIDTH_CALCS(core_dc->ctx->logger,
"\n============== DML TTU Output parameters [%d] ==============\n"
"qos_level_low_wm: %d, \n"
"qos_level_high_wm: %d, \n"
@@ -1116,7 +1160,7 @@ static void dcn10_enable_per_frame_crtc_position_reset(
pipe_ctx->ttu_regs.refcyc_per_req_delivery_pre_c
);
- dm_logger_write(core_dc->ctx->logger, LOG_BANDWIDTH_CALCS,
+ DC_LOG_BANDWIDTH_CALCS(core_dc->ctx->logger,
"\n============== DML DLG Output parameters [%d] ==============\n"
"refcyc_h_blank_end: %d, \n"
"dlg_vblank_end: %d, \n"
@@ -1151,7 +1195,7 @@ static void dcn10_enable_per_frame_crtc_position_reset(
pipe_ctx->dlg_regs.refcyc_per_pte_group_nom_l
);
- dm_logger_write(core_dc->ctx->logger, LOG_BANDWIDTH_CALCS,
+ DC_LOG_BANDWIDTH_CALCS(core_dc->ctx->logger,
"\ndst_y_per_meta_row_nom_l: %d, \n"
"refcyc_per_meta_chunk_nom_l: %d, \n"
"refcyc_per_line_delivery_pre_l: %d, \n"
@@ -1181,7 +1225,7 @@ static void dcn10_enable_per_frame_crtc_position_reset(
pipe_ctx->dlg_regs.refcyc_per_line_delivery_c
);
- dm_logger_write(core_dc->ctx->logger, LOG_BANDWIDTH_CALCS,
+ DC_LOG_BANDWIDTH_CALCS(core_dc->ctx->logger,
"\n============== DML RQ Output parameters [%d] ==============\n"
"chunk_size: %d \n"
"min_chunk_size: %d \n"
@@ -1314,7 +1358,7 @@ static void dcn10_enable_plane(
/* TODO: enable/disable in dm as per update type.
if (plane_state) {
- dm_logger_write(dc->ctx->logger, LOG_DC,
+ DC_LOG_DC(dc->ctx->logger,
"Pipe:%d 0x%x: addr hi:0x%x, "
"addr low:0x%x, "
"src: %d, %d, %d,"
@@ -1332,7 +1376,7 @@ static void dcn10_enable_plane(
plane_state->dst_rect.width,
plane_state->dst_rect.height);
- dm_logger_write(dc->ctx->logger, LOG_DC,
+ DC_LOG_DC(dc->ctx->logger,
"Pipe %d: width, height, x, y format:%d\n"
"viewport:%d, %d, %d, %d\n"
"recout: %d, %d, %d, %d\n",
@@ -1568,6 +1612,7 @@ static void update_dpp(struct dpp *dpp, struct dc_plane_state *plane_state)
dpp->funcs->dpp_program_bias_and_scale(dpp, &bns_params);
}
+
static void update_mpcc(struct dc *dc, struct pipe_ctx *pipe_ctx)
{
struct hubp *hubp = pipe_ctx->plane_res.hubp;
@@ -1664,15 +1709,22 @@ static void update_dchubp_dpp(
union plane_size size = plane_state->plane_size;
/* depends on DML calculation, DPP clock value may change dynamically */
+ /* If request max dpp clk is lower than current dispclk, no need to
+ * divided by 2
+ */
if (plane_state->update_flags.bits.full_update) {
+ bool should_divided_by_2 = context->bw.dcn.calc_clk.dppclk_khz <=
+ context->bw.dcn.cur_clk.dispclk_khz / 2;
+
dpp->funcs->dpp_dppclk_control(
dpp,
- context->bw.dcn.calc_clk.dppclk_div,
+ should_divided_by_2,
true);
- dc->current_state->bw.dcn.cur_clk.dppclk_div =
- context->bw.dcn.calc_clk.dppclk_div;
- context->bw.dcn.cur_clk.dppclk_div = context->bw.dcn.calc_clk.dppclk_div;
+ dc->current_state->bw.dcn.cur_clk.dppclk_khz =
+ should_divided_by_2 ?
+ context->bw.dcn.cur_clk.dispclk_khz / 2 :
+ context->bw.dcn.cur_clk.dispclk_khz;
}
/* TODO: Need input parameter to tell current DCHUB pipe tie to which OTG
@@ -1758,14 +1810,62 @@ static void update_dchubp_dpp(
hubp->funcs->set_blank(hubp, false);
}
+static void dcn10_otg_blank(
+ struct dc *dc,
+ struct stream_resource stream_res,
+ struct dc_stream_state *stream,
+ bool blank)
+{
+ enum dc_color_space color_space;
+ struct tg_color black_color = {0};
+
+ /* program otg blank color */
+ color_space = stream->output_color_space;
+ color_space_to_black_color(dc, color_space, &black_color);
+
+ if (stream_res.tg->funcs->set_blank_color)
+ stream_res.tg->funcs->set_blank_color(
+ stream_res.tg,
+ &black_color);
+
+ if (!blank) {
+ if (stream_res.tg->funcs->set_blank)
+ stream_res.tg->funcs->set_blank(stream_res.tg, blank);
+ if (stream_res.abm)
+ stream_res.abm->funcs->set_abm_level(stream_res.abm, stream->abm_level);
+ } else if (blank) {
+ if (stream_res.abm)
+ stream_res.abm->funcs->set_abm_immediate_disable(stream_res.abm);
+ if (stream_res.tg->funcs->set_blank)
+ stream_res.tg->funcs->set_blank(stream_res.tg, blank);
+ }
+}
+
+static void set_hdr_multiplier(struct pipe_ctx *pipe_ctx)
+{
+ struct fixed31_32 multiplier = dal_fixed31_32_from_fraction(
+ pipe_ctx->plane_state->sdr_white_level, 80);
+ uint32_t hw_mult = 0x1f000; // 1.0 default multiplier
+ struct custom_float_format fmt;
+
+ fmt.exponenta_bits = 6;
+ fmt.mantissa_bits = 12;
+ fmt.sign = true;
+
+ if (pipe_ctx->plane_state->sdr_white_level > 80)
+ convert_to_custom_float_format(multiplier, &fmt, &hw_mult);
+
+ pipe_ctx->plane_res.dpp->funcs->dpp_set_hdr_multiplier(
+ pipe_ctx->plane_res.dpp, hw_mult);
+}
static void program_all_pipe_in_tree(
struct dc *dc,
struct pipe_ctx *pipe_ctx,
struct dc_state *context)
{
-
if (pipe_ctx->top_pipe == NULL) {
+ bool blank = !is_pipe_tree_visible(pipe_ctx);
pipe_ctx->stream_res.tg->dlg_otg_param.vready_offset = pipe_ctx->pipe_dlg_param.vready_offset;
pipe_ctx->stream_res.tg->dlg_otg_param.vstartup_start = pipe_ctx->pipe_dlg_param.vstartup_start;
@@ -1776,10 +1876,8 @@ static void program_all_pipe_in_tree(
pipe_ctx->stream_res.tg->funcs->program_global_sync(
pipe_ctx->stream_res.tg);
- if (pipe_ctx->stream_res.tg->funcs->set_blank)
- pipe_ctx->stream_res.tg->funcs->set_blank(
- pipe_ctx->stream_res.tg,
- !is_pipe_tree_visible(pipe_ctx));
+ dcn10_otg_blank(dc, pipe_ctx->stream_res,
+ pipe_ctx->stream, blank);
}
if (pipe_ctx->plane_state != NULL) {
@@ -1788,6 +1886,8 @@ static void program_all_pipe_in_tree(
update_dchubp_dpp(dc, pipe_ctx, context);
+ set_hdr_multiplier(pipe_ctx);
+
if (pipe_ctx->plane_state->update_flags.bits.full_update ||
pipe_ctx->plane_state->update_flags.bits.in_transfer_func_change ||
pipe_ctx->plane_state->update_flags.bits.gamma_change)
@@ -1803,8 +1903,9 @@ static void program_all_pipe_in_tree(
dc->hwss.set_output_transfer_func(pipe_ctx, pipe_ctx->stream);
}
- if (pipe_ctx->bottom_pipe != NULL && pipe_ctx->bottom_pipe != pipe_ctx)
+ if (pipe_ctx->bottom_pipe != NULL && pipe_ctx->bottom_pipe != pipe_ctx) {
program_all_pipe_in_tree(dc, pipe_ctx->bottom_pipe, context);
+ }
}
static void dcn10_pplib_apply_display_requirements(
@@ -1813,16 +1914,10 @@ static void dcn10_pplib_apply_display_requirements(
{
struct dm_pp_display_configuration *pp_display_cfg = &context->pp_display_cfg;
- pp_display_cfg->all_displays_in_sync = false;/*todo*/
- pp_display_cfg->nb_pstate_switch_disable = false;
pp_display_cfg->min_engine_clock_khz = context->bw.dcn.cur_clk.dcfclk_khz;
pp_display_cfg->min_memory_clock_khz = context->bw.dcn.cur_clk.fclk_khz;
pp_display_cfg->min_engine_clock_deep_sleep_khz = context->bw.dcn.cur_clk.dcfclk_deep_sleep_khz;
pp_display_cfg->min_dcfc_deep_sleep_clock_khz = context->bw.dcn.cur_clk.dcfclk_deep_sleep_khz;
- pp_display_cfg->avail_mclk_switch_time_us =
- context->bw.dcn.cur_clk.dram_ccm_us > 0 ? context->bw.dcn.cur_clk.dram_ccm_us : 0;
- pp_display_cfg->avail_mclk_switch_time_in_disp_active_us =
- context->bw.dcn.cur_clk.min_active_dram_ccm_us > 0 ? context->bw.dcn.cur_clk.min_active_dram_ccm_us : 0;
pp_display_cfg->min_dcfclock_khz = context->bw.dcn.cur_clk.dcfclk_khz;
pp_display_cfg->disp_clk_khz = context->bw.dcn.cur_clk.dispclk_khz;
dce110_fill_display_configs(context, pp_display_cfg);
@@ -1885,28 +1980,23 @@ static void dcn10_apply_ctx_for_surface(
{
int i;
struct timing_generator *tg;
- struct output_pixel_processor *opp;
bool removed_pipe[4] = { false };
unsigned int ref_clk_mhz = dc->res_pool->ref_clock_inKhz/1000;
bool program_water_mark = false;
-
+ struct dc_context *ctx = dc->ctx;
struct pipe_ctx *top_pipe_to_program =
find_top_pipe_for_stream(dc, context, stream);
if (!top_pipe_to_program)
return;
- opp = top_pipe_to_program->stream_res.opp;
-
tg = top_pipe_to_program->stream_res.tg;
dcn10_pipe_control_lock(dc, top_pipe_to_program, true);
if (num_planes == 0) {
-
/* OTG blank before remove all front end */
- if (tg->funcs->set_blank)
- tg->funcs->set_blank(tg, true);
+ dcn10_otg_blank(dc, top_pipe_to_program->stream_res, top_pipe_to_program->stream, true);
}
/* Disconnect unused mpcc */
@@ -1924,7 +2014,7 @@ static void dcn10_apply_ctx_for_surface(
if (old_pipe_ctx->stream_res.tg == tg &&
old_pipe_ctx->plane_res.hubp &&
old_pipe_ctx->plane_res.hubp->opp_id != 0xf) {
- dcn10_disable_plane(dc, pipe_ctx);
+ dcn10_disable_plane(dc, old_pipe_ctx);
/*
* power down fe will unlock when calling reset, need
* to lock it back here. Messy, need rework.
@@ -1940,7 +2030,7 @@ static void dcn10_apply_ctx_for_surface(
plane_atomic_disconnect(dc, old_pipe_ctx);
removed_pipe[i] = true;
- dm_logger_write(dc->ctx->logger, LOG_DC,
+ DC_LOG_DC(
"Reset mpcc for pipe %d\n",
old_pipe_ctx->pipe_idx);
}
@@ -1983,7 +2073,7 @@ static void dcn10_apply_ctx_for_surface(
dcn10_verify_allow_pstate_change_high(dc);
}
}
-/* dm_logger_write(dc->ctx->logger, LOG_BANDWIDTH_CALCS,
+/* DC_LOG_BANDWIDTH_CALCS(dc->ctx->logger,
"\n============== Watermark parameters ==============\n"
"a.urgent_ns: %d \n"
"a.cstate_enter_plus_exit: %d \n"
@@ -2006,7 +2096,7 @@ static void dcn10_apply_ctx_for_surface(
context->bw.dcn.watermarks.b.cstate_pstate.pstate_change_ns,
context->bw.dcn.watermarks.b.pte_meta_urgent_ns
);
- dm_logger_write(dc->ctx->logger, LOG_BANDWIDTH_CALCS,
+ DC_LOG_BANDWIDTH_CALCS(dc->ctx->logger,
"\nc.urgent_ns: %d \n"
"c.cstate_enter_plus_exit: %d \n"
"c.cstate_exit: %d \n"
@@ -2032,6 +2122,101 @@ static void dcn10_apply_ctx_for_surface(
*/
}
+static inline bool should_set_clock(bool decrease_allowed, int calc_clk, int cur_clk)
+{
+ return ((decrease_allowed && calc_clk < cur_clk) || calc_clk > cur_clk);
+}
+
+static int determine_dppclk_threshold(struct dc *dc, struct dc_state *context)
+{
+ bool request_dpp_div = context->bw.dcn.calc_clk.dispclk_khz >
+ context->bw.dcn.calc_clk.dppclk_khz;
+ bool dispclk_increase = context->bw.dcn.calc_clk.dispclk_khz >
+ context->bw.dcn.cur_clk.dispclk_khz;
+ int disp_clk_threshold = context->bw.dcn.calc_clk.max_supported_dppclk_khz;
+ bool cur_dpp_div = context->bw.dcn.cur_clk.dispclk_khz >
+ context->bw.dcn.cur_clk.dppclk_khz;
+
+ /* increase clock, looking for div is 0 for current, request div is 1*/
+ if (dispclk_increase) {
+ /* already divided by 2, no need to reach target clk with 2 steps*/
+ if (cur_dpp_div)
+ return context->bw.dcn.calc_clk.dispclk_khz;
+
+ /* request disp clk is lower than maximum supported dpp clk,
+ * no need to reach target clk with two steps.
+ */
+ if (context->bw.dcn.calc_clk.dispclk_khz <= disp_clk_threshold)
+ return context->bw.dcn.calc_clk.dispclk_khz;
+
+ /* target dpp clk not request divided by 2, still within threshold */
+ if (!request_dpp_div)
+ return context->bw.dcn.calc_clk.dispclk_khz;
+
+ } else {
+ /* decrease clock, looking for current dppclk divided by 2,
+ * request dppclk not divided by 2.
+ */
+
+ /* current dpp clk not divided by 2, no need to ramp*/
+ if (!cur_dpp_div)
+ return context->bw.dcn.calc_clk.dispclk_khz;
+
+ /* current disp clk is lower than current maximum dpp clk,
+ * no need to ramp
+ */
+ if (context->bw.dcn.cur_clk.dispclk_khz <= disp_clk_threshold)
+ return context->bw.dcn.calc_clk.dispclk_khz;
+
+ /* request dpp clk need to be divided by 2 */
+ if (request_dpp_div)
+ return context->bw.dcn.calc_clk.dispclk_khz;
+ }
+
+ return disp_clk_threshold;
+}
+
+static void ramp_up_dispclk_with_dpp(struct dc *dc, struct dc_state *context)
+{
+ int i;
+ bool request_dpp_div = context->bw.dcn.calc_clk.dispclk_khz >
+ context->bw.dcn.calc_clk.dppclk_khz;
+
+ int dispclk_to_dpp_threshold = determine_dppclk_threshold(dc, context);
+
+ /* set disp clk to dpp clk threshold */
+ dc->res_pool->display_clock->funcs->set_clock(
+ dc->res_pool->display_clock,
+ dispclk_to_dpp_threshold);
+
+ /* update request dpp clk division option */
+ for (i = 0; i < dc->res_pool->pipe_count; i++) {
+ struct pipe_ctx *pipe_ctx = &dc->current_state->res_ctx.pipe_ctx[i];
+
+ if (!pipe_ctx->plane_state)
+ continue;
+
+ pipe_ctx->plane_res.dpp->funcs->dpp_dppclk_control(
+ pipe_ctx->plane_res.dpp,
+ request_dpp_div,
+ true);
+ }
+
+ /* If target clk not same as dppclk threshold, set to target clock */
+ if (dispclk_to_dpp_threshold != context->bw.dcn.calc_clk.dispclk_khz) {
+ dc->res_pool->display_clock->funcs->set_clock(
+ dc->res_pool->display_clock,
+ context->bw.dcn.calc_clk.dispclk_khz);
+ }
+
+ context->bw.dcn.cur_clk.dispclk_khz =
+ context->bw.dcn.calc_clk.dispclk_khz;
+ context->bw.dcn.cur_clk.dppclk_khz =
+ context->bw.dcn.calc_clk.dppclk_khz;
+ context->bw.dcn.cur_clk.max_supported_dppclk_khz =
+ context->bw.dcn.calc_clk.max_supported_dppclk_khz;
+}
+
static void dcn10_set_bandwidth(
struct dc *dc,
struct dc_state *context,
@@ -2049,31 +2234,33 @@ static void dcn10_set_bandwidth(
if (IS_FPGA_MAXIMUS_DC(dc->ctx->dce_environment))
return;
- if (decrease_allowed || context->bw.dcn.calc_clk.dispclk_khz
- > dc->current_state->bw.dcn.cur_clk.dispclk_khz) {
- dc->res_pool->display_clock->funcs->set_clock(
- dc->res_pool->display_clock,
- context->bw.dcn.calc_clk.dispclk_khz);
- dc->current_state->bw.dcn.cur_clk.dispclk_khz =
- context->bw.dcn.calc_clk.dispclk_khz;
- }
- if (decrease_allowed || context->bw.dcn.calc_clk.dcfclk_khz
- > dc->current_state->bw.dcn.cur_clk.dcfclk_khz) {
+ if (should_set_clock(
+ decrease_allowed,
+ context->bw.dcn.calc_clk.dcfclk_khz,
+ dc->current_state->bw.dcn.cur_clk.dcfclk_khz)) {
+ context->bw.dcn.cur_clk.dcfclk_khz =
+ context->bw.dcn.calc_clk.dcfclk_khz;
smu_req.hard_min_dcefclk_khz =
context->bw.dcn.calc_clk.dcfclk_khz;
}
- if (decrease_allowed || context->bw.dcn.calc_clk.fclk_khz
- > dc->current_state->bw.dcn.cur_clk.fclk_khz) {
- smu_req.hard_min_fclk_khz = context->bw.dcn.calc_clk.fclk_khz;
- }
- if (decrease_allowed || context->bw.dcn.calc_clk.dcfclk_deep_sleep_khz
- > dc->current_state->bw.dcn.cur_clk.dcfclk_deep_sleep_khz) {
- dc->current_state->bw.dcn.calc_clk.dcfclk_deep_sleep_khz =
- context->bw.dcn.calc_clk.dcfclk_deep_sleep_khz;
+
+ if (should_set_clock(
+ decrease_allowed,
+ context->bw.dcn.calc_clk.dcfclk_deep_sleep_khz,
+ dc->current_state->bw.dcn.cur_clk.dcfclk_deep_sleep_khz)) {
context->bw.dcn.cur_clk.dcfclk_deep_sleep_khz =
context->bw.dcn.calc_clk.dcfclk_deep_sleep_khz;
}
+ if (should_set_clock(
+ decrease_allowed,
+ context->bw.dcn.calc_clk.fclk_khz,
+ dc->current_state->bw.dcn.cur_clk.fclk_khz)) {
+ context->bw.dcn.cur_clk.fclk_khz =
+ context->bw.dcn.calc_clk.fclk_khz;
+ smu_req.hard_min_fclk_khz = context->bw.dcn.calc_clk.fclk_khz;
+ }
+
smu_req.display_count = context->stream_count;
if (pp_smu->set_display_requirement)
@@ -2081,21 +2268,17 @@ static void dcn10_set_bandwidth(
*smu_req_cur = smu_req;
- /* Decrease in freq is increase in period so opposite comparison for dram_ccm */
- if (decrease_allowed || context->bw.dcn.calc_clk.dram_ccm_us
- < dc->current_state->bw.dcn.cur_clk.dram_ccm_us) {
- dc->current_state->bw.dcn.calc_clk.dram_ccm_us =
- context->bw.dcn.calc_clk.dram_ccm_us;
- context->bw.dcn.cur_clk.dram_ccm_us =
- context->bw.dcn.calc_clk.dram_ccm_us;
- }
- if (decrease_allowed || context->bw.dcn.calc_clk.min_active_dram_ccm_us
- < dc->current_state->bw.dcn.cur_clk.min_active_dram_ccm_us) {
- dc->current_state->bw.dcn.calc_clk.min_active_dram_ccm_us =
- context->bw.dcn.calc_clk.min_active_dram_ccm_us;
- context->bw.dcn.cur_clk.min_active_dram_ccm_us =
- context->bw.dcn.calc_clk.min_active_dram_ccm_us;
+ /* make sure dcf clk is before dpp clk to
+ * make sure we have enough voltage to run dpp clk
+ */
+ if (should_set_clock(
+ decrease_allowed,
+ context->bw.dcn.calc_clk.dispclk_khz,
+ dc->current_state->bw.dcn.cur_clk.dispclk_khz)) {
+
+ ramp_up_dispclk_with_dpp(dc, context);
}
+
dcn10_pplib_apply_display_requirements(dc, context);
if (dc->debug.sanity_checks) {
@@ -2251,7 +2434,7 @@ static void dcn10_wait_for_mpcc_disconnect(
res_pool->mpc->funcs->wait_for_idle(res_pool->mpc, mpcc_inst);
pipe_ctx->stream_res.opp->mpcc_disconnect_pending[mpcc_inst] = false;
hubp->funcs->set_blank(hubp, true);
- /*dm_logger_write(dc->ctx->logger, LOG_ERROR,
+ /*DC_LOG_ERROR(dc->ctx->logger,
"[debug_mpo: wait_for_mpcc finished waiting on mpcc %d]\n",
i);*/
}
diff --git a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_optc.h b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_optc.h
index 014543235df8..d25e7bf0d0d7 100644
--- a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_optc.h
+++ b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_optc.h
@@ -83,6 +83,8 @@
struct dcn_optc_registers {
+ uint32_t OTG_GLOBAL_CONTROL1;
+ uint32_t OTG_GLOBAL_CONTROL2;
uint32_t OTG_VERT_SYNC_CONTROL;
uint32_t OTG_MASTER_UPDATE_MODE;
uint32_t OTG_GSL_CONTROL;
@@ -126,6 +128,7 @@ struct dcn_optc_registers {
uint32_t OTG_VERTICAL_INTERRUPT2_POSITION;
uint32_t OPTC_INPUT_CLOCK_CONTROL;
uint32_t OPTC_DATA_SOURCE_SELECT;
+ uint32_t OPTC_MEMORY_CONFIG;
uint32_t OPTC_INPUT_GLOBAL_CONTROL;
uint32_t CONTROL;
uint32_t OTG_GSL_WINDOW_X;
@@ -325,10 +328,9 @@ struct dcn_optc_registers {
type OPTC_INPUT_CLK_EN;\
type OPTC_INPUT_CLK_ON;\
type OPTC_INPUT_CLK_GATE_DIS;\
- type OPTC_SRC_SEL;\
- type OPTC_SEG0_SRC_SEL;\
type OPTC_UNDERFLOW_OCCURRED_STATUS;\
type OPTC_UNDERFLOW_CLEAR;\
+ type OPTC_SRC_SEL;\
type VTG0_ENABLE;\
type VTG0_FP2;\
type VTG0_VCOUNT_INIT;\
diff --git a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_resource.c b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_resource.c
index c4a564cb56b9..02bd664aed3e 100644
--- a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_resource.c
+++ b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_resource.c
@@ -440,7 +440,11 @@ static const struct dc_debug debug_defaults_drv = {
.timing_trace = false,
.clock_trace = true,
- .min_disp_clk_khz = 300000,
+ /* raven smu dones't allow 0 disp clk,
+ * smu min disp clk limit is 50Mhz
+ * keep min disp clk 100Mhz avoid smu hang
+ */
+ .min_disp_clk_khz = 100000,
.disable_pplib_clock_request = true,
.disable_pplib_wm_range = false,
@@ -963,6 +967,7 @@ static struct pipe_ctx *dcn10_acquire_idle_pipe_for_layer(
idle_pipe->stream = head_pipe->stream;
idle_pipe->stream_res.tg = head_pipe->stream_res.tg;
+ idle_pipe->stream_res.abm = head_pipe->stream_res.abm;
idle_pipe->stream_res.opp = head_pipe->stream_res.opp;
idle_pipe->plane_res.hubp = pool->hubps[idle_pipe->pipe_idx];
diff --git a/drivers/gpu/drm/amd/display/dc/dm_helpers.h b/drivers/gpu/drm/amd/display/dc/dm_helpers.h
index ab88f07772a3..034369fbb9e2 100644
--- a/drivers/gpu/drm/amd/display/dc/dm_helpers.h
+++ b/drivers/gpu/drm/amd/display/dc/dm_helpers.h
@@ -50,6 +50,13 @@ bool dm_helpers_dp_mst_write_payload_allocation_table(
bool enable);
/*
+ * Clear payload allocation table before enable MST DP link.
+ */
+void dm_helpers_dp_mst_clear_payload_allocation_table(
+ struct dc_context *ctx,
+ const struct dc_link *link);
+
+/*
* Polls for ACT (allocation change trigger) handled and
*/
bool dm_helpers_dp_mst_poll_for_allocation_change_trigger(
@@ -101,5 +108,8 @@ enum dc_edid_status dm_helpers_read_local_edid(
struct dc_link *link,
struct dc_sink *sink);
+void dm_set_dcn_clocks(
+ struct dc_context *ctx,
+ struct dc_clocks *clks);
#endif /* __DM_HELPERS__ */
diff --git a/drivers/gpu/drm/amd/display/dc/dm_services_types.h b/drivers/gpu/drm/amd/display/dc/dm_services_types.h
index fa26cf488b3c..ab8c77d4e6df 100644
--- a/drivers/gpu/drm/amd/display/dc/dm_services_types.h
+++ b/drivers/gpu/drm/amd/display/dc/dm_services_types.h
@@ -29,7 +29,7 @@
#include "os_types.h"
#include "dc_types.h"
-#include "dm_pp_smu.h"
+struct pp_smu_funcs_rv;
struct dm_pp_clock_range {
int min_khz;
@@ -239,25 +239,8 @@ enum dm_acpi_display_type {
AcpiDisplayType_DFP6 = 12
};
-enum dm_pp_power_level {
- DM_PP_POWER_LEVEL_INVALID,
- DM_PP_POWER_LEVEL_ULTRA_LOW,
- DM_PP_POWER_LEVEL_LOW,
- DM_PP_POWER_LEVEL_NOMINAL,
- DM_PP_POWER_LEVEL_PERFORMANCE,
-
- DM_PP_POWER_LEVEL_0 = DM_PP_POWER_LEVEL_ULTRA_LOW,
- DM_PP_POWER_LEVEL_1 = DM_PP_POWER_LEVEL_LOW,
- DM_PP_POWER_LEVEL_2 = DM_PP_POWER_LEVEL_NOMINAL,
- DM_PP_POWER_LEVEL_3 = DM_PP_POWER_LEVEL_PERFORMANCE,
- DM_PP_POWER_LEVEL_4 = DM_PP_CLOCKS_DPM_STATE_LEVEL_3 + 1,
- DM_PP_POWER_LEVEL_5 = DM_PP_CLOCKS_DPM_STATE_LEVEL_4 + 1,
- DM_PP_POWER_LEVEL_6 = DM_PP_CLOCKS_DPM_STATE_LEVEL_5 + 1,
- DM_PP_POWER_LEVEL_7 = DM_PP_CLOCKS_DPM_STATE_LEVEL_6 + 1,
-};
-
struct dm_pp_power_level_change_request {
- enum dm_pp_power_level power_level;
+ enum dm_pp_clocks_state power_level;
};
struct dm_pp_clock_for_voltage_req {
diff --git a/drivers/gpu/drm/amd/display/dc/dml/display_rq_dlg_helpers.c b/drivers/gpu/drm/amd/display/dc/dml/display_rq_dlg_helpers.c
index 189052e911fc..48400d642610 100644
--- a/drivers/gpu/drm/amd/display/dc/dml/display_rq_dlg_helpers.c
+++ b/drivers/gpu/drm/amd/display/dc/dml/display_rq_dlg_helpers.c
@@ -24,6 +24,7 @@
*/
#include "display_rq_dlg_helpers.h"
+#include "dml_logger.h"
void print__rq_params_st(struct display_mode_lib *mode_lib, display_rq_params_st rq_param)
{
diff --git a/drivers/gpu/drm/amd/display/dc/dml/dml_common_defs.h b/drivers/gpu/drm/amd/display/dc/dml/dml_common_defs.h
index b2847bc469fe..f78cbae9db88 100644
--- a/drivers/gpu/drm/amd/display/dc/dml/dml_common_defs.h
+++ b/drivers/gpu/drm/amd/display/dc/dml/dml_common_defs.h
@@ -31,8 +31,6 @@
#include "display_mode_structs.h"
#include "display_mode_enums.h"
-#define dml_print(str, ...) {dm_logger_write(mode_lib->logger, LOG_DML, str, ##__VA_ARGS__); }
-#define DTRACE(str, ...) {dm_logger_write(mode_lib->logger, LOG_DML, str, ##__VA_ARGS__); }
double dml_round(double a);
diff --git a/drivers/gpu/drm/amd/display/dc/dml/dml_inline_defs.h b/drivers/gpu/drm/amd/display/dc/dml/dml_inline_defs.h
index e68086b8a22f..f9cf08357989 100644
--- a/drivers/gpu/drm/amd/display/dc/dml/dml_inline_defs.h
+++ b/drivers/gpu/drm/amd/display/dc/dml/dml_inline_defs.h
@@ -28,6 +28,7 @@
#include "dml_common_defs.h"
#include "../calcs/dcn_calc_math.h"
+#include "dml_logger.h"
static inline double dml_min(double a, double b)
{
diff --git a/drivers/gpu/drm/amd/display/dc/dml/dml_logger.h b/drivers/gpu/drm/amd/display/dc/dml/dml_logger.h
new file mode 100644
index 000000000000..465859b77248
--- /dev/null
+++ b/drivers/gpu/drm/amd/display/dc/dml/dml_logger.h
@@ -0,0 +1,38 @@
+/*
+ * Copyright 2018 Advanced Micro Devices, Inc.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ *
+ * Authors: AMD
+ *
+ */
+
+
+#ifndef __DML_LOGGER_H_
+#define __DML_LOGGER_H_
+
+#define DC_LOGGER \
+ mode_lib->logger
+
+#define dml_print(str, ...) {DC_LOG_DML(str, ##__VA_ARGS__); }
+#define DTRACE(str, ...) {DC_LOG_DML(str, ##__VA_ARGS__); }
+
+#endif
+
+
diff --git a/drivers/gpu/drm/amd/display/dc/i2caux/aux_engine.c b/drivers/gpu/drm/amd/display/dc/i2caux/aux_engine.c
index 0b1db48fef36..bb526ad326e5 100644
--- a/drivers/gpu/drm/amd/display/dc/i2caux/aux_engine.c
+++ b/drivers/gpu/drm/amd/display/dc/i2caux/aux_engine.c
@@ -55,6 +55,8 @@ enum {
#define FROM_ENGINE(ptr) \
container_of((ptr), struct aux_engine, base)
+#define DC_LOGGER \
+ engine->base.ctx->logger
enum i2caux_engine_type dal_aux_engine_get_engine_type(
const struct engine *engine)
@@ -126,20 +128,8 @@ static void process_read_reply(
ctx->status =
I2CAUX_TRANSACTION_STATUS_FAILED_PROTOCOL_ERROR;
ctx->operation_succeeded = false;
- } else if (ctx->returned_byte < ctx->current_read_length) {
- ctx->current_read_length -= ctx->returned_byte;
-
- ctx->offset += ctx->returned_byte;
-
- ++ctx->invalid_reply_retry_aux_on_ack;
-
- if (ctx->invalid_reply_retry_aux_on_ack >
- AUX_INVALID_REPLY_RETRY_COUNTER) {
- ctx->status =
- I2CAUX_TRANSACTION_STATUS_FAILED_PROTOCOL_ERROR;
- ctx->operation_succeeded = false;
- }
} else {
+ ctx->current_read_length = ctx->returned_byte;
ctx->status = I2CAUX_TRANSACTION_STATUS_SUCCEEDED;
ctx->transaction_complete = true;
ctx->operation_succeeded = true;
@@ -286,12 +276,13 @@ static bool read_command(
if (request->payload.address_space ==
I2CAUX_TRANSACTION_ADDRESS_SPACE_DPCD) {
- dm_logger_write(engine->base.ctx->logger, LOG_I2C_AUX, "READ: addr:0x%x value:0x%x Result:%d",
+ DC_LOG_I2C_AUX("READ: addr:0x%x value:0x%x Result:%d",
request->payload.address,
request->payload.data[0],
ctx.operation_succeeded);
}
+ request->payload.length = ctx.reply.length;
return ctx.operation_succeeded;
}
@@ -494,7 +485,7 @@ static bool write_command(
if (request->payload.address_space ==
I2CAUX_TRANSACTION_ADDRESS_SPACE_DPCD) {
- dm_logger_write(engine->base.ctx->logger, LOG_I2C_AUX, "WRITE: addr:0x%x value:0x%x Result:%d",
+ DC_LOG_I2C_AUX("WRITE: addr:0x%x value:0x%x Result:%d",
request->payload.address,
request->payload.data[0],
ctx.operation_succeeded);
diff --git a/drivers/gpu/drm/amd/display/dc/i2caux/dce110/i2c_hw_engine_dce110.c b/drivers/gpu/drm/amd/display/dc/i2caux/dce110/i2c_hw_engine_dce110.c
index 56e25b3d65fd..abd0095ced30 100644
--- a/drivers/gpu/drm/amd/display/dc/i2caux/dce110/i2c_hw_engine_dce110.c
+++ b/drivers/gpu/drm/amd/display/dc/i2caux/dce110/i2c_hw_engine_dce110.c
@@ -48,6 +48,8 @@
/*
* This unit
*/
+#define DC_LOGGER \
+ hw_engine->base.base.base.ctx->logger
enum dc_i2c_status {
DC_I2C_STATUS__DC_I2C_STATUS_IDLE,
@@ -525,9 +527,7 @@ static void construct(
REG_GET(MICROSECOND_TIME_BASE_DIV, XTAL_REF_DIV, &xtal_ref_div);
if (xtal_ref_div == 0) {
- dm_logger_write(
- hw_engine->base.base.base.ctx->logger, LOG_WARNING,
- "Invalid base timer divider\n",
+ DC_LOG_WARNING("Invalid base timer divider\n",
__func__);
xtal_ref_div = 2;
}
diff --git a/drivers/gpu/drm/amd/display/dc/i2caux/i2caux.c b/drivers/gpu/drm/amd/display/dc/i2caux/i2caux.c
index e1593ffe5a2b..5cbf6626b8d4 100644
--- a/drivers/gpu/drm/amd/display/dc/i2caux/i2caux.c
+++ b/drivers/gpu/drm/amd/display/dc/i2caux/i2caux.c
@@ -253,6 +253,7 @@ bool dal_i2caux_submit_aux_command(
break;
}
+ cmd->payloads->length = request.payload.length;
++index_of_payload;
}
diff --git a/drivers/gpu/drm/amd/display/dc/inc/core_types.h b/drivers/gpu/drm/amd/display/dc/inc/core_types.h
index 5509e13e7edf..8c51ad70cace 100644
--- a/drivers/gpu/drm/amd/display/dc/inc/core_types.h
+++ b/drivers/gpu/drm/amd/display/dc/inc/core_types.h
@@ -177,6 +177,15 @@ struct resource_pool {
const struct resource_caps *res_cap;
};
+struct dcn_fe_clocks {
+ int dppclk_khz;
+};
+
+struct dcn_fe_bandwidth {
+ struct dcn_fe_clocks calc;
+ struct dcn_fe_clocks cur;
+};
+
struct stream_resource {
struct output_pixel_processor *opp;
struct timing_generator *tg;
@@ -185,6 +194,8 @@ struct stream_resource {
struct pixel_clk_params pix_clk_params;
struct encoder_info_frame encoder_info_frame;
+
+ struct abm *abm;
};
struct plane_resource {
@@ -195,6 +206,8 @@ struct plane_resource {
struct transform *xfm;
struct dpp *dpp;
uint8_t mpcc_inst;
+
+ struct dcn_fe_bandwidth bw;
};
struct pipe_ctx {
@@ -245,20 +258,9 @@ struct dce_bw_output {
int blackout_recovery_time_us;
};
-struct dcn_bw_clocks {
- int dispclk_khz;
- int dppclk_khz;
- bool dppclk_div;
- int dcfclk_khz;
- int dcfclk_deep_sleep_khz;
- int fclk_khz;
- int dram_ccm_us;
- int min_active_dram_ccm_us;
-};
-
struct dcn_bw_output {
- struct dcn_bw_clocks cur_clk;
- struct dcn_bw_clocks calc_clk;
+ struct dc_clocks cur_clk;
+ struct dc_clocks calc_clk;
struct dcn_watermark_set watermarks;
};
diff --git a/drivers/gpu/drm/amd/display/dc/inc/dc_link_ddc.h b/drivers/gpu/drm/amd/display/dc/inc/dc_link_ddc.h
index 0bf73b742f1f..090b7a8dd67b 100644
--- a/drivers/gpu/drm/amd/display/dc/inc/dc_link_ddc.h
+++ b/drivers/gpu/drm/amd/display/dc/inc/dc_link_ddc.h
@@ -102,7 +102,7 @@ bool dal_ddc_service_query_ddc_data(
uint8_t *read_buf,
uint32_t read_size);
-enum ddc_result dal_ddc_service_read_dpcd_data(
+ssize_t dal_ddc_service_read_dpcd_data(
struct ddc_service *ddc,
bool i2c,
enum i2c_mot_mode mot,
diff --git a/drivers/gpu/drm/amd/display/dc/inc/dce_calcs.h b/drivers/gpu/drm/amd/display/dc/inc/dce_calcs.h
index ae2399f16d1c..a9bfe9ff8ce6 100644
--- a/drivers/gpu/drm/amd/display/dc/inc/dce_calcs.h
+++ b/drivers/gpu/drm/amd/display/dc/inc/dce_calcs.h
@@ -130,6 +130,9 @@ enum bw_defines {
struct bw_calcs_dceip {
enum bw_calcs_version version;
+ uint32_t percent_of_ideal_port_bw_received_after_urgent_latency;
+ uint32_t max_average_percent_of_ideal_port_bw_display_can_use_in_normal_system_operation;
+ uint32_t max_average_percent_of_ideal_drambw_display_can_use_in_normal_system_operation;
bool large_cursor;
uint32_t cursor_max_outstanding_group_num;
bool dmif_pipe_en_fbc_chunk_tracker;
@@ -230,6 +233,7 @@ struct bw_calcs_vbios {
struct bw_calcs_data {
/* data for all displays */
+ bool display_synchronization_enabled;
uint32_t number_of_displays;
enum bw_defines underlay_surface_type;
enum bw_defines panning_and_bezel_adjustment;
@@ -241,6 +245,7 @@ struct bw_calcs_data {
bool d1_display_write_back_dwb_enable;
enum bw_defines d1_underlay_mode;
+ bool increase_voltage_to_support_mclk_switch;
bool cpup_state_change_enable;
bool cpuc_state_change_enable;
bool nbp_state_change_enable;
@@ -449,6 +454,7 @@ struct bw_calcs_data {
struct bw_fixed dram_speed_change_line_source_transfer_time[maximum_number_of_surfaces][3][8];
struct bw_fixed min_dram_speed_change_margin[3][8];
struct bw_fixed dispclk_required_for_dram_speed_change[3][8];
+ struct bw_fixed dispclk_required_for_dram_speed_change_pipe[3][8];
struct bw_fixed blackout_duration_margin[3][8];
struct bw_fixed dispclk_required_for_blackout_duration[3][8];
struct bw_fixed dispclk_required_for_blackout_recovery[3][8];
diff --git a/drivers/gpu/drm/amd/display/dc/inc/hw/dpp.h b/drivers/gpu/drm/amd/display/dc/inc/hw/dpp.h
index 78abc16ec4dc..99995608b620 100644
--- a/drivers/gpu/drm/amd/display/dc/inc/hw/dpp.h
+++ b/drivers/gpu/drm/amd/display/dc/inc/hw/dpp.h
@@ -35,6 +35,8 @@ struct dpp {
int inst;
struct dpp_caps *caps;
struct pwl_params regamma_params;
+ struct pwl_params degamma_params;
+
};
struct dpp_grph_csc_adjustment {
@@ -130,6 +132,9 @@ struct dpp_funcs {
const struct dc_cursor_mi_param *param,
uint32_t width
);
+ void (*dpp_set_hdr_multiplier)(
+ struct dpp *dpp_base,
+ uint32_t multiplier);
void (*dpp_dppclk_control)(
struct dpp *dpp_base,
diff --git a/drivers/gpu/drm/amd/display/dc/irq/dce110/irq_service_dce110.c b/drivers/gpu/drm/amd/display/dc/irq/dce110/irq_service_dce110.c
index f7e40b292dfb..afe0876fe6f8 100644
--- a/drivers/gpu/drm/amd/display/dc/irq/dce110/irq_service_dce110.c
+++ b/drivers/gpu/drm/amd/display/dc/irq/dce110/irq_service_dce110.c
@@ -36,27 +36,25 @@
#include "dc.h"
#include "core_types.h"
-static bool hpd_ack(
- struct irq_service *irq_service,
- const struct irq_source_info *info)
+#define DC_LOGGER \
+ irq_service->ctx->logger
+
+static bool hpd_ack(struct irq_service *irq_service,
+ const struct irq_source_info *info)
{
uint32_t addr = info->status_reg;
uint32_t value = dm_read_reg(irq_service->ctx, addr);
- uint32_t current_status =
- get_reg_field_value(
- value,
- DC_HPD_INT_STATUS,
- DC_HPD_SENSE_DELAYED);
+ uint32_t current_status = get_reg_field_value(value,
+ DC_HPD_INT_STATUS,
+ DC_HPD_SENSE_DELAYED);
dal_irq_service_ack_generic(irq_service, info);
value = dm_read_reg(irq_service->ctx, info->enable_reg);
- set_reg_field_value(
- value,
- current_status ? 0 : 1,
- DC_HPD_INT_CONTROL,
- DC_HPD_INT_POLARITY);
+ set_reg_field_value(value, current_status ? 0 : 1,
+ DC_HPD_INT_CONTROL,
+ DC_HPD_INT_POLARITY);
dm_write_reg(irq_service->ctx, info->enable_reg, value);
@@ -176,48 +174,41 @@ static const struct irq_source_info_funcs vblank_irq_info_funcs = {
#define dc_underflow_int_entry(reg_num) \
[DC_IRQ_SOURCE_DC ## reg_num ## UNDERFLOW] = dummy_irq_entry()
-bool dal_irq_service_dummy_set(
- struct irq_service *irq_service,
- const struct irq_source_info *info,
- bool enable)
+bool dal_irq_service_dummy_set(struct irq_service *irq_service,
+ const struct irq_source_info *info,
+ bool enable)
{
- dm_logger_write(
- irq_service->ctx->logger, LOG_ERROR,
- "%s: called for non-implemented irq source\n",
- __func__);
+ DC_LOG_ERROR("%s: called for non-implemented irq source\n",
+ __func__);
return false;
}
-bool dal_irq_service_dummy_ack(
- struct irq_service *irq_service,
- const struct irq_source_info *info)
+bool dal_irq_service_dummy_ack(struct irq_service *irq_service,
+ const struct irq_source_info *info)
{
- dm_logger_write(
- irq_service->ctx->logger, LOG_ERROR,
- "%s: called for non-implemented irq source\n",
- __func__);
+ DC_LOG_ERROR("%s: called for non-implemented irq source\n",
+ __func__);
return false;
}
-bool dce110_vblank_set(
- struct irq_service *irq_service,
- const struct irq_source_info *info,
- bool enable)
+bool dce110_vblank_set(struct irq_service *irq_service,
+ const struct irq_source_info *info,
+ bool enable)
{
struct dc_context *dc_ctx = irq_service->ctx;
struct dc *core_dc = irq_service->ctx->dc;
- enum dc_irq_source dal_irq_src = dc_interrupt_to_irq_source(
- irq_service->ctx->dc,
- info->src_id,
- info->ext_id);
+ enum dc_irq_source dal_irq_src =
+ dc_interrupt_to_irq_source(irq_service->ctx->dc,
+ info->src_id,
+ info->ext_id);
uint8_t pipe_offset = dal_irq_src - IRQ_TYPE_VBLANK;
struct timing_generator *tg =
core_dc->current_state->res_ctx.pipe_ctx[pipe_offset].stream_res.tg;
if (enable) {
- if (!tg->funcs->arm_vert_intr(tg, 2)) {
+ if (!tg || !tg->funcs->arm_vert_intr(tg, 2)) {
DC_ERROR("Failed to get VBLANK!\n");
return false;
}
@@ -225,7 +216,6 @@ bool dce110_vblank_set(
dal_irq_service_set_generic(irq_service, info, enable);
return true;
-
}
static const struct irq_source_info_funcs dummy_irq_info_funcs = {
@@ -406,9 +396,8 @@ static const struct irq_service_funcs irq_service_funcs_dce110 = {
.to_dal_irq_source = to_dal_irq_source_dce110
};
-static void construct(
- struct irq_service *irq_service,
- struct irq_service_init_data *init_data)
+static void construct(struct irq_service *irq_service,
+ struct irq_service_init_data *init_data)
{
dal_irq_service_construct(irq_service, init_data);
@@ -416,8 +405,8 @@ static void construct(
irq_service->funcs = &irq_service_funcs_dce110;
}
-struct irq_service *dal_irq_service_dce110_create(
- struct irq_service_init_data *init_data)
+struct irq_service *
+dal_irq_service_dce110_create(struct irq_service_init_data *init_data)
{
struct irq_service *irq_service = kzalloc(sizeof(*irq_service),
GFP_KERNEL);
diff --git a/drivers/gpu/drm/amd/display/dc/irq/irq_service.c b/drivers/gpu/drm/amd/display/dc/irq/irq_service.c
index b106513fc2dc..dcdfa0f01551 100644
--- a/drivers/gpu/drm/amd/display/dc/irq/irq_service.c
+++ b/drivers/gpu/drm/amd/display/dc/irq/irq_service.c
@@ -47,6 +47,8 @@
#define CTX \
irq_service->ctx
+#define DC_LOGGER \
+ irq_service->ctx->logger
void dal_irq_service_construct(
struct irq_service *irq_service,
@@ -104,9 +106,7 @@ bool dal_irq_service_set(
find_irq_source_info(irq_service, source);
if (!info) {
- dm_logger_write(
- irq_service->ctx->logger, LOG_ERROR,
- "%s: cannot find irq info table entry for %d\n",
+ DC_LOG_ERROR("%s: cannot find irq info table entry for %d\n",
__func__,
source);
return false;
@@ -142,9 +142,7 @@ bool dal_irq_service_ack(
find_irq_source_info(irq_service, source);
if (!info) {
- dm_logger_write(
- irq_service->ctx->logger, LOG_ERROR,
- "%s: cannot find irq info table entry for %d\n",
+ DC_LOG_ERROR("%s: cannot find irq info table entry for %d\n",
__func__,
source);
return false;
diff --git a/drivers/gpu/drm/amd/display/include/link_service_types.h b/drivers/gpu/drm/amd/display/include/link_service_types.h
index adea1a59f620..80f0d93cfd94 100644
--- a/drivers/gpu/drm/amd/display/include/link_service_types.h
+++ b/drivers/gpu/drm/amd/display/include/link_service_types.h
@@ -58,11 +58,14 @@ enum {
enum link_training_result {
LINK_TRAINING_SUCCESS,
- LINK_TRAINING_CR_FAIL,
+ LINK_TRAINING_CR_FAIL_LANE0,
+ LINK_TRAINING_CR_FAIL_LANE1,
+ LINK_TRAINING_CR_FAIL_LANE23,
/* CR DONE bit is cleared during EQ step */
LINK_TRAINING_EQ_FAIL_CR,
/* other failure during EQ step */
LINK_TRAINING_EQ_FAIL_EQ,
+ LINK_TRAINING_LQA_FAIL,
};
struct link_training_settings {
diff --git a/drivers/gpu/drm/amd/display/include/logger_types.h b/drivers/gpu/drm/amd/display/include/logger_types.h
index e2ff8cd423d6..427796bdc14a 100644
--- a/drivers/gpu/drm/amd/display/include/logger_types.h
+++ b/drivers/gpu/drm/amd/display/include/logger_types.h
@@ -29,6 +29,39 @@
#include "os_types.h"
#define MAX_NAME_LEN 32
+#define DC_LOG_ERROR(a, ...) dm_logger_write(DC_LOGGER, LOG_ERROR, a, ## __VA_ARGS__)
+#define DC_LOG_WARNING(a, ...) dm_logger_write(DC_LOGGER, LOG_WARNING, a, ## __VA_ARGS__)
+#define DC_LOG_DEBUG(a, ...) dm_logger_write(DC_LOGGER, LOG_DEBUG, a, ## __VA_ARGS__)
+#define DC_LOG_DC(a, ...) dm_logger_write(DC_LOGGER, LOG_DC, a, ## __VA_ARGS__)
+#define DC_LOG_DTN(a, ...) dm_logger_write(DC_LOGGER, LOG_DTN, a, ## __VA_ARGS__)
+#define DC_LOG_SURFACE(a, ...) dm_logger_write(DC_LOGGER, LOG_SURFACE, a, ## __VA_ARGS__)
+#define DC_LOG_HW_HOTPLUG(a, ...) dm_logger_write(DC_LOGGER, LOG_HW_HOTPLUG, a, ## __VA_ARGS__)
+#define DC_LOG_HW_LINK_TRAINING(a, ...) dm_logger_write(DC_LOGGER, LOG_HW_LINK_TRAINING, a, ## __VA_ARGS__)
+#define DC_LOG_HW_SET_MODE(a, ...) dm_logger_write(DC_LOGGER, LOG_HW_SET_MODE, a, ## __VA_ARGS__)
+#define DC_LOG_HW_RESUME_S3(a, ...) dm_logger_write(DC_LOGGER, LOG_HW_RESUME_S3, a, ## __VA_ARGS__)
+#define DC_LOG_HW_AUDIO(a, ...) dm_logger_write(DC_LOGGER, LOG_HW_AUDIO, a, ## __VA_ARGS__)
+#define DC_LOG_HW_HPD_IRQ(a, ...) dm_logger_write(DC_LOGGER, LOG_HW_HPD_IRQ, a, ## __VA_ARGS__)
+#define DC_LOG_MST(a, ...) dm_logger_write(DC_LOGGER, LOG_MST, a, ## __VA_ARGS__)
+#define DC_LOG_SCALER(a, ...) dm_logger_write(DC_LOGGER, LOG_SCALER, a, ## __VA_ARGS__)
+#define DC_LOG_BIOS(a, ...) dm_logger_write(DC_LOGGER, LOG_BIOS, a, ## __VA_ARGS__)
+#define DC_LOG_BANDWIDTH_CALCS(a, ...) dm_logger_write(DC_LOGGER, LOG_BANDWIDTH_CALCS, a, ## __VA_ARGS__)
+#define DC_LOG_BANDWIDTH_VALIDATION(a, ...) dm_logger_write(DC_LOGGER, LOG_BANDWIDTH_VALIDATION, a, ## __VA_ARGS__)
+#define DC_LOG_I2C_AUX(a, ...) dm_logger_write(DC_LOGGER, LOG_I2C_AUX, a, ## __VA_ARGS__)
+#define DC_LOG_SYNC(a, ...) dm_logger_write(DC_LOGGER, LOG_SYNC, a, ## __VA_ARGS__)
+#define DC_LOG_BACKLIGHT(a, ...) dm_logger_write(DC_LOGGER, LOG_BACKLIGHT, a, ## __VA_ARGS__)
+#define DC_LOG_FEATURE_OVERRIDE(a, ...) dm_logger_write(DC_LOGGER, LOG_FEATURE_OVERRIDE, a, ## __VA_ARGS__)
+#define DC_LOG_DETECTION_EDID_PARSER(a, ...) dm_logger_write(DC_LOGGER, LOG_DETECTION_EDID_PARSER, a, ## __VA_ARGS__)
+#define DC_LOG_DETECTION_DP_CAPS(a, ...) dm_logger_write(DC_LOGGER, LOG_DETECTION_DP_CAPS, a, ## __VA_ARGS__)
+#define DC_LOG_RESOURCE(a, ...) dm_logger_write(DC_LOGGER, LOG_RESOURCE, a, ## __VA_ARGS__)
+#define DC_LOG_DML(a, ...) dm_logger_write(DC_LOGGER, LOG_DML, a, ## __VA_ARGS__)
+#define DC_LOG_EVENT_MODE_SET(a, ...) dm_logger_write(DC_LOGGER, LOG_EVENT_MODE_SET, a, ## __VA_ARGS__)
+#define DC_LOG_EVENT_DETECTION(a, ...) dm_logger_write(DC_LOGGER, LOG_EVENT_DETECTION, a, ## __VA_ARGS__)
+#define DC_LOG_EVENT_LINK_TRAINING(a, ...) dm_logger_write(DC_LOGGER, LOG_EVENT_LINK_TRAINING, a, ## __VA_ARGS__)
+#define DC_LOG_EVENT_LINK_LOSS(a, ...) dm_logger_write(DC_LOGGER, LOG_EVENT_LINK_LOSS, a, ## __VA_ARGS__)
+#define DC_LOG_EVENT_UNDERFLOW(a, ...) dm_logger_write(DC_LOGGER, LOG_EVENT_UNDERFLOW, a, ## __VA_ARGS__)
+#define DC_LOG_IF_TRACE(a, ...) dm_logger_write(DC_LOGGER, LOG_IF_TRACE, a, ## __VA_ARGS__)
+#define DC_LOG_PERF_TRACE(a, ...) dm_logger_write(DC_LOGGER, LOG_PERF_TRACE, a, ## __VA_ARGS__)
+
struct dal_logger;
@@ -65,6 +98,7 @@ enum dc_log_type {
LOG_EVENT_UNDERFLOW,
LOG_IF_TRACE,
LOG_PERF_TRACE,
+ LOG_PROFILING,
LOG_SECTION_TOTAL_COUNT
};
diff --git a/drivers/gpu/drm/amd/display/modules/color/color_gamma.c b/drivers/gpu/drm/amd/display/modules/color/color_gamma.c
index a5fd14a4016f..e7e374f56864 100644
--- a/drivers/gpu/drm/amd/display/modules/color/color_gamma.c
+++ b/drivers/gpu/drm/amd/display/modules/color/color_gamma.c
@@ -30,15 +30,12 @@
#define NUM_PTS_IN_REGION 16
#define NUM_REGIONS 32
-#define NUM_DEGAMMA_REGIONS 12
#define MAX_HW_POINTS (NUM_PTS_IN_REGION*NUM_REGIONS)
-#define MAX_HW_DEGAMMA_POINTS (NUM_PTS_IN_REGION*NUM_DEGAMMA_REGIONS)
static struct hw_x_point coordinates_x[MAX_HW_POINTS + 2];
-static struct hw_x_point degamma_coordinates_x[MAX_HW_DEGAMMA_POINTS + 2];
static struct fixed31_32 pq_table[MAX_HW_POINTS + 2];
-static struct fixed31_32 de_pq_table[MAX_HW_DEGAMMA_POINTS + 2];
+static struct fixed31_32 de_pq_table[MAX_HW_POINTS + 2];
static bool pq_initialized; /* = false; */
static bool de_pq_initialized; /* = false; */
@@ -69,26 +66,6 @@ void setup_x_points_distribution(void)
(coordinates_x[index-1].x, increment);
}
}
-
- region_size = dal_fixed31_32_from_int(1);
- degamma_coordinates_x[MAX_HW_DEGAMMA_POINTS].x = region_size;
- degamma_coordinates_x[MAX_HW_DEGAMMA_POINTS + 1].x = region_size;
-
- for (segment = -1; segment > -(NUM_DEGAMMA_REGIONS + 1); segment--) {
- region_size = dal_fixed31_32_div_int(region_size, 2);
- increment = dal_fixed31_32_div_int(region_size,
- NUM_PTS_IN_REGION);
- seg_offset = (segment + NUM_DEGAMMA_REGIONS) * NUM_PTS_IN_REGION;
- degamma_coordinates_x[seg_offset].x = region_size;
-
- for (index = seg_offset + 1;
- index < seg_offset + NUM_PTS_IN_REGION;
- index++) {
- degamma_coordinates_x[index].x = dal_fixed31_32_add
- (degamma_coordinates_x[index-1].x, increment);
- }
- }
-
}
static void compute_pq(struct fixed31_32 in_x, struct fixed31_32 *out_y)
@@ -179,15 +156,26 @@ void precompute_de_pq(void)
{
int i;
struct fixed31_32 y;
- const struct hw_x_point *coord_x = degamma_coordinates_x;
+ uint32_t begin_index, end_index;
+
struct fixed31_32 scaling_factor = dal_fixed31_32_from_int(125);
+ /* X points is 2^-25 to 2^7
+ * De-gamma X is 2^-12 to 2^0 – we are skipping first -12-(-25) = 13 regions
+ */
+ begin_index = 13 * NUM_PTS_IN_REGION;
+ end_index = begin_index + 12 * NUM_PTS_IN_REGION;
- for (i = 0; i <= MAX_HW_DEGAMMA_POINTS; i++) {
- compute_de_pq(coord_x->x, &y);
+ for (i = 0; i <= begin_index; i++)
+ de_pq_table[i] = dal_fixed31_32_zero;
+
+ for (; i <= end_index; i++) {
+ compute_de_pq(coordinates_x[i].x, &y);
de_pq_table[i] = dal_fixed31_32_mul(y, scaling_factor);
- ++coord_x;
}
+
+ for (; i <= MAX_HW_POINTS; i++)
+ de_pq_table[i] = de_pq_table[i-1];
}
struct dividers {
struct fixed31_32 divider1;
@@ -617,8 +605,6 @@ static void build_de_pq(struct pwl_float_data_ex *de_pq,
uint32_t i;
struct fixed31_32 output;
- struct pwl_float_data_ex *rgb = de_pq;
- const struct hw_x_point *coord_x = degamma_coordinates_x;
struct fixed31_32 scaling_factor = dal_fixed31_32_from_int(125);
if (!de_pq_initialized) {
@@ -634,13 +620,9 @@ static void build_de_pq(struct pwl_float_data_ex *de_pq,
output = dal_fixed31_32_zero;
else if (dal_fixed31_32_lt(scaling_factor, output))
output = scaling_factor;
-
- rgb->r = output;
- rgb->g = output;
- rgb->b = output;
-
- ++coord_x;
- ++rgb;
+ de_pq[i].r = output;
+ de_pq[i].g = output;
+ de_pq[i].b = output;
}
}
@@ -675,24 +657,37 @@ static void build_degamma(struct pwl_float_data_ex *curve,
const struct hw_x_point *coordinate_x, bool is_2_4)
{
uint32_t i;
-
struct gamma_coefficients coeff;
- struct pwl_float_data_ex *rgb = curve;
- const struct hw_x_point *coord_x = degamma_coordinates_x;
+ uint32_t begin_index, end_index;
build_coefficients(&coeff, is_2_4);
-
i = 0;
+ /* X points is 2^-25 to 2^7
+ * De-gamma X is 2^-12 to 2^0 – we are skipping first -12-(-25) = 13 regions
+ */
+ begin_index = 13 * NUM_PTS_IN_REGION;
+ end_index = begin_index + 12 * NUM_PTS_IN_REGION;
+
+ while (i != begin_index) {
+ curve[i].r = dal_fixed31_32_zero;
+ curve[i].g = dal_fixed31_32_zero;
+ curve[i].b = dal_fixed31_32_zero;
+ i++;
+ }
+
+ while (i != end_index) {
+ curve[i].r = translate_to_linear_space_ex(
+ coordinate_x[i].x, &coeff, 0);
+ curve[i].g = curve[i].r;
+ curve[i].b = curve[i].r;
+ i++;
+ }
while (i != hw_points_num + 1) {
- /*TODO use y vs r,g,b*/
- rgb->r = translate_to_linear_space_ex(
- coord_x->x, &coeff, 0);
- rgb->g = rgb->r;
- rgb->b = rgb->r;
- ++coord_x;
- ++rgb;
- ++i;
+ curve[i].r = dal_fixed31_32_one;
+ curve[i].g = dal_fixed31_32_one;
+ curve[i].b = dal_fixed31_32_one;
+ i++;
}
}
@@ -1173,10 +1168,6 @@ rgb_user_alloc_fail:
return ret;
}
-
-/*TODO fix me should be 2*/
-#define _EXTRA_POINTS 3
-
bool mod_color_calculate_degamma_params(struct dc_transfer_func *input_tf,
const struct dc_gamma *ramp, bool mapUserRamp)
{
@@ -1205,7 +1196,7 @@ bool mod_color_calculate_degamma_params(struct dc_transfer_func *input_tf,
GFP_KERNEL);
if (!rgb_user)
goto rgb_user_alloc_fail;
- curve = kzalloc(sizeof(*curve) * (MAX_HW_DEGAMMA_POINTS + _EXTRA_POINTS),
+ curve = kzalloc(sizeof(*curve) * (MAX_HW_POINTS + _EXTRA_POINTS),
GFP_KERNEL);
if (!curve)
goto curve_alloc_fail;
@@ -1213,7 +1204,7 @@ bool mod_color_calculate_degamma_params(struct dc_transfer_func *input_tf,
GFP_KERNEL);
if (!axix_x)
goto axix_x_alloc_fail;
- coeff = kzalloc(sizeof(*coeff) * (MAX_HW_DEGAMMA_POINTS + _EXTRA_POINTS), GFP_KERNEL);
+ coeff = kzalloc(sizeof(*coeff) * (MAX_HW_POINTS + _EXTRA_POINTS), GFP_KERNEL);
if (!coeff)
goto coeff_alloc_fail;
@@ -1235,12 +1226,12 @@ bool mod_color_calculate_degamma_params(struct dc_transfer_func *input_tf,
if (tf == TRANSFER_FUNCTION_PQ)
build_de_pq(curve,
- MAX_HW_DEGAMMA_POINTS,
- degamma_coordinates_x);
+ MAX_HW_POINTS,
+ coordinates_x);
else
build_degamma(curve,
- MAX_HW_DEGAMMA_POINTS,
- degamma_coordinates_x,
+ MAX_HW_POINTS,
+ coordinates_x,
tf == TRANSFER_FUNCTION_SRGB ? true:false);
tf_pts->end_exponent = 0;
@@ -1249,8 +1240,8 @@ bool mod_color_calculate_degamma_params(struct dc_transfer_func *input_tf,
tf_pts->x_point_at_y1_blue = 1;
map_regamma_hw_to_x_user(ramp, coeff, rgb_user,
- degamma_coordinates_x, axix_x, curve,
- MAX_HW_DEGAMMA_POINTS, tf_pts,
+ coordinates_x, axix_x, curve,
+ MAX_HW_POINTS, tf_pts,
mapUserRamp);
ret = true;
@@ -1276,13 +1267,14 @@ bool mod_color_calculate_curve(enum dc_transfer_func_predefined trans,
bool ret = false;
struct pwl_float_data_ex *rgb_regamma = NULL;
- if (trans == TRANSFER_FUNCTION_UNITY) {
+ if (trans == TRANSFER_FUNCTION_UNITY ||
+ trans == TRANSFER_FUNCTION_LINEAR) {
points->end_exponent = 0;
points->x_point_at_y1_red = 1;
points->x_point_at_y1_green = 1;
points->x_point_at_y1_blue = 1;
- for (i = 0; i < MAX_HW_POINTS ; i++) {
+ for (i = 0; i <= MAX_HW_POINTS ; i++) {
points->red[i] = coordinates_x[i].x;
points->green[i] = coordinates_x[i].x;
points->blue[i] = coordinates_x[i].x;
@@ -1303,7 +1295,7 @@ bool mod_color_calculate_curve(enum dc_transfer_func_predefined trans,
MAX_HW_POINTS,
coordinates_x,
80);
- for (i = 0; i < MAX_HW_POINTS ; i++) {
+ for (i = 0; i <= MAX_HW_POINTS ; i++) {
points->red[i] = rgb_regamma[i].r;
points->green[i] = rgb_regamma[i].g;
points->blue[i] = rgb_regamma[i].b;
@@ -1325,7 +1317,7 @@ bool mod_color_calculate_curve(enum dc_transfer_func_predefined trans,
build_regamma(rgb_regamma,
MAX_HW_POINTS,
coordinates_x, trans == TRANSFER_FUNCTION_SRGB ? true:false);
- for (i = 0; i < MAX_HW_POINTS ; i++) {
+ for (i = 0; i <= MAX_HW_POINTS ; i++) {
points->red[i] = rgb_regamma[i].r;
points->green[i] = rgb_regamma[i].g;
points->blue[i] = rgb_regamma[i].b;
@@ -1346,25 +1338,26 @@ bool mod_color_calculate_degamma_curve(enum dc_transfer_func_predefined trans,
bool ret = false;
struct pwl_float_data_ex *rgb_degamma = NULL;
- if (trans == TRANSFER_FUNCTION_UNITY) {
+ if (trans == TRANSFER_FUNCTION_UNITY ||
+ trans == TRANSFER_FUNCTION_LINEAR) {
- for (i = 0; i < MAX_HW_DEGAMMA_POINTS ; i++) {
- points->red[i] = degamma_coordinates_x[i].x;
- points->green[i] = degamma_coordinates_x[i].x;
- points->blue[i] = degamma_coordinates_x[i].x;
+ for (i = 0; i <= MAX_HW_POINTS ; i++) {
+ points->red[i] = coordinates_x[i].x;
+ points->green[i] = coordinates_x[i].x;
+ points->blue[i] = coordinates_x[i].x;
}
ret = true;
} else if (trans == TRANSFER_FUNCTION_PQ) {
- rgb_degamma = kzalloc(sizeof(*rgb_degamma) * (MAX_HW_DEGAMMA_POINTS +
+ rgb_degamma = kzalloc(sizeof(*rgb_degamma) * (MAX_HW_POINTS +
_EXTRA_POINTS), GFP_KERNEL);
if (!rgb_degamma)
goto rgb_degamma_alloc_fail;
build_de_pq(rgb_degamma,
- MAX_HW_DEGAMMA_POINTS,
- degamma_coordinates_x);
- for (i = 0; i < MAX_HW_DEGAMMA_POINTS ; i++) {
+ MAX_HW_POINTS,
+ coordinates_x);
+ for (i = 0; i <= MAX_HW_POINTS ; i++) {
points->red[i] = rgb_degamma[i].r;
points->green[i] = rgb_degamma[i].g;
points->blue[i] = rgb_degamma[i].b;
@@ -1374,15 +1367,15 @@ bool mod_color_calculate_degamma_curve(enum dc_transfer_func_predefined trans,
kfree(rgb_degamma);
} else if (trans == TRANSFER_FUNCTION_SRGB ||
trans == TRANSFER_FUNCTION_BT709) {
- rgb_degamma = kzalloc(sizeof(*rgb_degamma) * (MAX_HW_DEGAMMA_POINTS +
+ rgb_degamma = kzalloc(sizeof(*rgb_degamma) * (MAX_HW_POINTS +
_EXTRA_POINTS), GFP_KERNEL);
if (!rgb_degamma)
goto rgb_degamma_alloc_fail;
build_degamma(rgb_degamma,
- MAX_HW_DEGAMMA_POINTS,
- degamma_coordinates_x, trans == TRANSFER_FUNCTION_SRGB ? true:false);
- for (i = 0; i < MAX_HW_DEGAMMA_POINTS ; i++) {
+ MAX_HW_POINTS,
+ coordinates_x, trans == TRANSFER_FUNCTION_SRGB ? true:false);
+ for (i = 0; i <= MAX_HW_POINTS ; i++) {
points->red[i] = rgb_degamma[i].r;
points->green[i] = rgb_degamma[i].g;
points->blue[i] = rgb_degamma[i].b;
diff --git a/drivers/gpu/drm/amd/display/modules/freesync/freesync.c b/drivers/gpu/drm/amd/display/modules/freesync/freesync.c
index b4723af368a5..27d4003aa2c7 100644
--- a/drivers/gpu/drm/amd/display/modules/freesync/freesync.c
+++ b/drivers/gpu/drm/amd/display/modules/freesync/freesync.c
@@ -33,7 +33,7 @@
/* Refresh rate ramp at a fixed rate of 65 Hz/second */
#define STATIC_SCREEN_RAMP_DELTA_REFRESH_RATE_PER_FRAME ((1000 / 60) * 65)
/* Number of elements in the render times cache array */
-#define RENDER_TIMES_MAX_COUNT 20
+#define RENDER_TIMES_MAX_COUNT 10
/* Threshold to exit BTR (to avoid frequent enter-exits at the lower limit) */
#define BTR_EXIT_MARGIN 2000
/* Number of consecutive frames to check before entering/exiting fixed refresh*/
@@ -46,13 +46,15 @@
#define FREESYNC_NO_STATIC_FOR_INTERNAL_REGKEY "DalFreeSyncNoStaticForInternal"
+#define FREESYNC_DEFAULT_REGKEY "LCDFreeSyncDefault"
+
struct gradual_static_ramp {
bool ramp_is_active;
bool ramp_direction_is_up;
unsigned int ramp_current_frame_duration_in_ns;
};
-struct time_cache {
+struct freesync_time {
/* video (48Hz feature) related */
unsigned int update_duration_in_ns;
@@ -64,6 +66,9 @@ struct time_cache {
unsigned int render_times_index;
unsigned int render_times[RENDER_TIMES_MAX_COUNT];
+
+ unsigned int min_window;
+ unsigned int max_window;
};
struct below_the_range {
@@ -98,11 +103,14 @@ struct freesync_state {
bool static_screen;
bool video;
+ unsigned int vmin;
+ unsigned int vmax;
+
+ struct freesync_time time;
+
unsigned int nominal_refresh_rate_in_micro_hz;
bool windowed_fullscreen;
- struct time_cache time;
-
struct gradual_static_ramp static_ramp;
struct below_the_range btr;
struct fixed_refresh fixed_refresh;
@@ -119,14 +127,16 @@ struct freesync_entity {
struct freesync_registry_options {
bool drr_external_supported;
bool drr_internal_supported;
+ bool lcd_freesync_default_set;
+ int lcd_freesync_default_value;
};
struct core_freesync {
struct mod_freesync public;
struct dc *dc;
+ struct freesync_registry_options opts;
struct freesync_entity *map;
int num_entities;
- struct freesync_registry_options opts;
};
#define MOD_FREESYNC_TO_CORE(mod_freesync)\
@@ -146,7 +156,7 @@ struct mod_freesync *mod_freesync_create(struct dc *dc)
goto fail_alloc_context;
core_freesync->map = kzalloc(sizeof(struct freesync_entity) * MOD_FREESYNC_MAX_CONCURRENT_STREAMS,
- GFP_KERNEL);
+ GFP_KERNEL);
if (core_freesync->map == NULL)
goto fail_alloc_map;
@@ -183,6 +193,16 @@ struct mod_freesync *mod_freesync_create(struct dc *dc)
(data & 1) ? false : true;
}
+ if (dm_read_persistent_data(dc->ctx, NULL, NULL,
+ FREESYNC_DEFAULT_REGKEY,
+ &data, sizeof(data), &flag)) {
+ core_freesync->opts.lcd_freesync_default_set = true;
+ core_freesync->opts.lcd_freesync_default_value = data;
+ } else {
+ core_freesync->opts.lcd_freesync_default_set = false;
+ core_freesync->opts.lcd_freesync_default_value = 0;
+ }
+
return &core_freesync->public;
fail_construct:
@@ -288,6 +308,18 @@ bool mod_freesync_add_stream(struct mod_freesync *mod_freesync,
core_freesync->map[core_freesync->num_entities].user_enable.
enable_for_video =
(persistent_freesync_enable & 4) ? true : false;
+ /* If FreeSync display and LCDFreeSyncDefault is set, use as default values write back to userenable */
+ } else if (caps->supported && (core_freesync->opts.lcd_freesync_default_set)) {
+ core_freesync->map[core_freesync->num_entities].user_enable.enable_for_gaming =
+ (core_freesync->opts.lcd_freesync_default_value & 1) ? true : false;
+ core_freesync->map[core_freesync->num_entities].user_enable.enable_for_static =
+ (core_freesync->opts.lcd_freesync_default_value & 2) ? true : false;
+ core_freesync->map[core_freesync->num_entities].user_enable.enable_for_video =
+ (core_freesync->opts.lcd_freesync_default_value & 4) ? true : false;
+ dm_write_persistent_data(dc->ctx, stream->sink,
+ FREESYNC_REGISTRY_NAME,
+ "userenable", &core_freesync->opts.lcd_freesync_default_value,
+ sizeof(int), &flag);
} else {
core_freesync->map[core_freesync->num_entities].user_enable.
enable_for_gaming = false;
@@ -330,6 +362,25 @@ bool mod_freesync_remove_stream(struct mod_freesync *mod_freesync,
return true;
}
+static void adjust_vmin_vmax(struct core_freesync *core_freesync,
+ struct dc_stream_state **streams,
+ int num_streams,
+ int map_index,
+ unsigned int v_total_min,
+ unsigned int v_total_max)
+{
+ if (num_streams == 0 || streams == NULL || num_streams > 1)
+ return;
+
+ core_freesync->map[map_index].state.vmin = v_total_min;
+ core_freesync->map[map_index].state.vmax = v_total_max;
+
+ dc_stream_adjust_vmin_vmax(core_freesync->dc, streams,
+ num_streams, v_total_min,
+ v_total_max);
+}
+
+
static void update_stream_freesync_context(struct core_freesync *core_freesync,
struct dc_stream_state *stream)
{
@@ -588,9 +639,10 @@ static bool set_freesync_on_streams(struct core_freesync *core_freesync,
update_stream_freesync_context(core_freesync,
streams[stream_idx]);
- dc_stream_adjust_vmin_vmax(core_freesync->dc, streams,
- num_streams, v_total_min,
- v_total_max);
+ adjust_vmin_vmax(core_freesync, streams,
+ num_streams, map_index,
+ v_total_min,
+ v_total_max);
return true;
@@ -613,9 +665,10 @@ static bool set_freesync_on_streams(struct core_freesync *core_freesync,
core_freesync,
streams[stream_idx]);
- dc_stream_adjust_vmin_vmax(
- core_freesync->dc, streams,
- num_streams, v_total_nominal,
+ adjust_vmin_vmax(
+ core_freesync, streams,
+ num_streams, map_index,
+ v_total_nominal,
v_total_nominal);
}
return true;
@@ -632,9 +685,10 @@ static bool set_freesync_on_streams(struct core_freesync *core_freesync,
core_freesync,
streams[stream_idx]);
- dc_stream_adjust_vmin_vmax(core_freesync->dc, streams,
- num_streams, v_total_nominal,
- v_total_nominal);
+ adjust_vmin_vmax(core_freesync, streams,
+ num_streams, map_index,
+ v_total_nominal,
+ v_total_nominal);
/* Reset the cached variables */
reset_freesync_state_variables(state);
@@ -650,9 +704,10 @@ static bool set_freesync_on_streams(struct core_freesync *core_freesync,
* not support freesync because a former stream has
* be programmed
*/
- dc_stream_adjust_vmin_vmax(core_freesync->dc, streams,
- num_streams, v_total_nominal,
- v_total_nominal);
+ adjust_vmin_vmax(core_freesync, streams,
+ num_streams, map_index,
+ v_total_nominal,
+ v_total_nominal);
/* Reset the cached variables */
reset_freesync_state_variables(state);
}
@@ -769,8 +824,9 @@ void mod_freesync_handle_v_update(struct mod_freesync *mod_freesync,
vmin = inserted_frame_v_total;
/* Program V_TOTAL */
- dc_stream_adjust_vmin_vmax(core_freesync->dc, streams,
- num_streams, vmin, vmax);
+ adjust_vmin_vmax(core_freesync, streams,
+ num_streams, index,
+ vmin, vmax);
}
if (state->btr.frame_counter > 0)
@@ -804,9 +860,10 @@ void mod_freesync_handle_v_update(struct mod_freesync *mod_freesync,
update_stream_freesync_context(core_freesync, streams[0]);
/* Program static screen ramp values */
- dc_stream_adjust_vmin_vmax(core_freesync->dc, streams,
- num_streams, v_total,
- v_total);
+ adjust_vmin_vmax(core_freesync, streams,
+ num_streams, index,
+ v_total,
+ v_total);
triggers.overlay_update = true;
triggers.surface_update = true;
@@ -1063,9 +1120,9 @@ bool mod_freesync_override_min_max(struct mod_freesync *mod_freesync,
max_refresh);
/* Program vtotal min/max */
- dc_stream_adjust_vmin_vmax(core_freesync->dc, &streams, 1,
- state->freesync_range.vmin,
- state->freesync_range.vmax);
+ adjust_vmin_vmax(core_freesync, &streams, 1, index,
+ state->freesync_range.vmin,
+ state->freesync_range.vmax);
}
if (min_refresh != 0 &&
@@ -1399,11 +1456,9 @@ static void apply_fixed_refresh(struct core_freesync *core_freesync,
} else {
vmin = state->freesync_range.vmin;
-
vmax = vmin;
-
- dc_stream_adjust_vmin_vmax(core_freesync->dc, &stream,
- 1, vmin, vmax);
+ adjust_vmin_vmax(core_freesync, &stream, map_index,
+ 1, vmin, vmax);
}
}
@@ -1457,3 +1512,43 @@ void mod_freesync_pre_update_plane_addresses(struct mod_freesync *mod_freesync,
}
}
+
+void mod_freesync_get_settings(struct mod_freesync *mod_freesync,
+ struct dc_stream_state **streams, int num_streams,
+ unsigned int *v_total_min, unsigned int *v_total_max,
+ unsigned int *event_triggers,
+ unsigned int *window_min, unsigned int *window_max,
+ unsigned int *lfc_mid_point_in_us,
+ unsigned int *inserted_frames,
+ unsigned int *inserted_duration_in_us)
+{
+ unsigned int stream_index, map_index;
+ struct core_freesync *core_freesync = NULL;
+
+ if (mod_freesync == NULL)
+ return;
+
+ core_freesync = MOD_FREESYNC_TO_CORE(mod_freesync);
+
+ for (stream_index = 0; stream_index < num_streams; stream_index++) {
+
+ map_index = map_index_from_stream(core_freesync,
+ streams[stream_index]);
+
+ if (core_freesync->map[map_index].caps->supported) {
+ struct freesync_state state =
+ core_freesync->map[map_index].state;
+ *v_total_min = state.vmin;
+ *v_total_max = state.vmax;
+ *event_triggers = 0;
+ *window_min = state.time.min_window;
+ *window_max = state.time.max_window;
+ *lfc_mid_point_in_us = state.btr.mid_point_in_us;
+ *inserted_frames = state.btr.frames_to_insert;
+ *inserted_duration_in_us =
+ state.btr.inserted_frame_duration_in_us;
+ }
+
+ }
+}
+
diff --git a/drivers/gpu/drm/amd/display/modules/inc/mod_freesync.h b/drivers/gpu/drm/amd/display/modules/inc/mod_freesync.h
index 84b53425f2c8..f083e1619dbe 100644
--- a/drivers/gpu/drm/amd/display/modules/inc/mod_freesync.h
+++ b/drivers/gpu/drm/amd/display/modules/inc/mod_freesync.h
@@ -164,4 +164,13 @@ void mod_freesync_pre_update_plane_addresses(struct mod_freesync *mod_freesync,
struct dc_stream_state **streams, int num_streams,
unsigned int curr_time_stamp);
+void mod_freesync_get_settings(struct mod_freesync *mod_freesync,
+ struct dc_stream_state **streams, int num_streams,
+ unsigned int *v_total_min, unsigned int *v_total_max,
+ unsigned int *event_triggers,
+ unsigned int *window_min, unsigned int *window_max,
+ unsigned int *lfc_mid_point_in_us,
+ unsigned int *inserted_frames,
+ unsigned int *inserted_duration_in_us);
+
#endif
diff --git a/drivers/gpu/drm/amd/display/modules/inc/mod_stats.h b/drivers/gpu/drm/amd/display/modules/inc/mod_stats.h
new file mode 100644
index 000000000000..3230e2adb870
--- /dev/null
+++ b/drivers/gpu/drm/amd/display/modules/inc/mod_stats.h
@@ -0,0 +1,65 @@
+/*
+ * Copyright 2016 Advanced Micro Devices, Inc.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ *
+ * Authors: AMD
+ *
+ */
+
+#ifndef MODULES_INC_MOD_STATS_H_
+#define MODULES_INC_MOD_STATS_H_
+
+#include "dm_services.h"
+
+struct mod_stats {
+ int dummy;
+};
+
+struct mod_stats_caps {
+ bool dummy;
+};
+
+struct mod_stats *mod_stats_create(struct dc *dc);
+
+void mod_stats_destroy(struct mod_stats *mod_stats);
+
+bool mod_stats_init(struct mod_stats *mod_stats);
+
+void mod_stats_dump(struct mod_stats *mod_stats);
+
+void mod_stats_reset_data(struct mod_stats *mod_stats);
+
+void mod_stats_update_flip(struct mod_stats *mod_stats,
+ unsigned long timestamp_in_ns);
+
+void mod_stats_update_vupdate(struct mod_stats *mod_stats,
+ unsigned long timestamp_in_ns);
+
+void mod_stats_update_freesync(struct mod_stats *mod_stats,
+ unsigned int v_total_min,
+ unsigned int v_total_max,
+ unsigned int event_triggers,
+ unsigned int window_min,
+ unsigned int window_max,
+ unsigned int lfc_mid_point_in_us,
+ unsigned int inserted_frames,
+ unsigned int inserted_frame_duration_in_us);
+
+#endif /* MODULES_INC_MOD_STATS_H_ */
diff --git a/drivers/gpu/drm/amd/display/modules/stats/stats.c b/drivers/gpu/drm/amd/display/modules/stats/stats.c
new file mode 100644
index 000000000000..041f87b73d5f
--- /dev/null
+++ b/drivers/gpu/drm/amd/display/modules/stats/stats.c
@@ -0,0 +1,334 @@
+/*
+ * Copyright 2016 Advanced Micro Devices, Inc.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ *
+ * Authors: AMD
+ *
+ */
+
+#include "mod_stats.h"
+#include "dm_services.h"
+#include "dc.h"
+#include "core_types.h"
+
+#define DAL_STATS_ENABLE_REGKEY "DalStatsEnable"
+#define DAL_STATS_ENABLE_REGKEY_DEFAULT 0x00000001
+#define DAL_STATS_ENABLE_REGKEY_ENABLED 0x00000001
+
+#define DAL_STATS_ENTRIES_REGKEY "DalStatsEntries"
+#define DAL_STATS_ENTRIES_REGKEY_DEFAULT 0x00350000
+#define DAL_STATS_ENTRIES_REGKEY_MAX 0x01000000
+
+#define MOD_STATS_NUM_VSYNCS 5
+
+struct stats_time_cache {
+ unsigned long flip_timestamp_in_ns;
+ unsigned long vupdate_timestamp_in_ns;
+
+ unsigned int render_time_in_us;
+ unsigned int avg_render_time_in_us_last_ten;
+ unsigned int v_sync_time_in_us[MOD_STATS_NUM_VSYNCS];
+ unsigned int num_vsync_between_flips;
+
+ unsigned int flip_to_vsync_time_in_us;
+ unsigned int vsync_to_flip_time_in_us;
+
+ unsigned int min_window;
+ unsigned int max_window;
+ unsigned int v_total_min;
+ unsigned int v_total_max;
+ unsigned int event_triggers;
+
+ unsigned int lfc_mid_point_in_us;
+ unsigned int num_frames_inserted;
+ unsigned int inserted_duration_in_us;
+
+ unsigned int flags;
+};
+
+struct core_stats {
+ struct mod_stats public;
+ struct dc *dc;
+
+ struct stats_time_cache *time;
+ unsigned int index;
+
+ bool enabled;
+ unsigned int entries;
+};
+
+#define MOD_STATS_TO_CORE(mod_stats)\
+ container_of(mod_stats, struct core_stats, public)
+
+bool mod_stats_init(struct mod_stats *mod_stats)
+{
+ bool result = false;
+ struct core_stats *core_stats = NULL;
+ struct dc *dc = NULL;
+
+ if (mod_stats == NULL)
+ return false;
+
+ core_stats = MOD_STATS_TO_CORE(mod_stats);
+ dc = core_stats->dc;
+
+ return result;
+}
+
+struct mod_stats *mod_stats_create(struct dc *dc)
+{
+ struct core_stats *core_stats = NULL;
+ struct persistent_data_flag flag;
+ unsigned int reg_data;
+ int i = 0;
+
+ core_stats = kzalloc(sizeof(struct core_stats), GFP_KERNEL);
+
+ if (core_stats == NULL)
+ goto fail_alloc_context;
+
+ if (dc == NULL)
+ goto fail_construct;
+
+ core_stats->dc = dc;
+
+ core_stats->enabled = DAL_STATS_ENABLE_REGKEY_DEFAULT;
+ if (dm_read_persistent_data(dc->ctx, NULL, NULL,
+ DAL_STATS_ENABLE_REGKEY,
+ &reg_data, sizeof(unsigned int), &flag))
+ core_stats->enabled = reg_data;
+
+ core_stats->entries = DAL_STATS_ENTRIES_REGKEY_DEFAULT;
+ if (dm_read_persistent_data(dc->ctx, NULL, NULL,
+ DAL_STATS_ENTRIES_REGKEY,
+ &reg_data, sizeof(unsigned int), &flag)) {
+ if (reg_data > DAL_STATS_ENTRIES_REGKEY_MAX)
+ core_stats->entries = DAL_STATS_ENTRIES_REGKEY_MAX;
+ else
+ core_stats->entries = reg_data;
+ }
+
+ core_stats->time = kzalloc(sizeof(struct stats_time_cache) * core_stats->entries,
+ GFP_KERNEL);
+
+ if (core_stats->time == NULL)
+ goto fail_construct;
+
+ /* Purposely leave index 0 unused so we don't need special logic to
+ * handle calculation cases that depend on previous flip data.
+ */
+ core_stats->index = 1;
+
+ return &core_stats->public;
+
+fail_construct:
+ kfree(core_stats);
+
+fail_alloc_context:
+ return NULL;
+}
+
+void mod_stats_destroy(struct mod_stats *mod_stats)
+{
+ if (mod_stats != NULL) {
+ struct core_stats *core_stats = MOD_STATS_TO_CORE(mod_stats);
+
+ if (core_stats->time != NULL)
+ kfree(core_stats->time);
+
+ kfree(core_stats);
+ }
+}
+
+void mod_stats_dump(struct mod_stats *mod_stats)
+{
+ struct dc *dc = NULL;
+ struct dal_logger *logger = NULL;
+ struct core_stats *core_stats = NULL;
+ struct stats_time_cache *time = NULL;
+ unsigned int index = 0;
+
+ if (mod_stats == NULL)
+ return;
+
+ core_stats = MOD_STATS_TO_CORE(mod_stats);
+ dc = core_stats->dc;
+ logger = dc->ctx->logger;
+ time = core_stats->time;
+
+ //LogEntry* pLog = GetLog()->Open(LogMajor_ISR, LogMinor_ISR_FreeSyncSW);
+
+ //if (!pLog->IsDummyEntry())
+ {
+ dm_logger_write(logger, LOG_PROFILING, "==Display Caps==\n");
+ dm_logger_write(logger, LOG_PROFILING, "\n");
+ dm_logger_write(logger, LOG_PROFILING, "\n");
+
+ dm_logger_write(logger, LOG_PROFILING, "==Stats==\n");
+ dm_logger_write(logger, LOG_PROFILING,
+ "render avgRender minWindow midPoint maxWindow vsyncToFlip flipToVsync #vsyncBetweenFlip #frame insertDuration vTotalMin vTotalMax eventTrigs vSyncTime1 vSyncTime2 vSyncTime3 vSyncTime4 vSyncTime5 flags\n");
+
+ for (int i = 0; i < core_stats->index && i < core_stats->entries; i++) {
+ dm_logger_write(logger, LOG_PROFILING,
+ "%u %u %u %u %u %u %u %u %u %u %u %u %u %u %u %u %u %u %u\n",
+ time[i].render_time_in_us,
+ time[i].avg_render_time_in_us_last_ten,
+ time[i].min_window,
+ time[i].lfc_mid_point_in_us,
+ time[i].max_window,
+ time[i].vsync_to_flip_time_in_us,
+ time[i].flip_to_vsync_time_in_us,
+ time[i].num_vsync_between_flips,
+ time[i].num_frames_inserted,
+ time[i].inserted_duration_in_us,
+ time[i].v_total_min,
+ time[i].v_total_max,
+ time[i].event_triggers,
+ time[i].v_sync_time_in_us[0],
+ time[i].v_sync_time_in_us[1],
+ time[i].v_sync_time_in_us[2],
+ time[i].v_sync_time_in_us[3],
+ time[i].v_sync_time_in_us[4],
+ time[i].flags);
+ }
+ }
+ //GetLog()->Close(pLog);
+ //GetLog()->UnSetLogMask(LogMajor_ISR, LogMinor_ISR_FreeSyncSW);
+}
+
+void mod_stats_reset_data(struct mod_stats *mod_stats)
+{
+ struct core_stats *core_stats = NULL;
+ struct stats_time_cache *time = NULL;
+ unsigned int index = 0;
+
+ if (mod_stats == NULL)
+ return;
+
+ core_stats = MOD_STATS_TO_CORE(mod_stats);
+
+ memset(core_stats->time, 0,
+ sizeof(struct stats_time_cache) * core_stats->entries);
+
+ core_stats->index = 0;
+}
+
+void mod_stats_update_flip(struct mod_stats *mod_stats,
+ unsigned long timestamp_in_ns)
+{
+ struct core_stats *core_stats = NULL;
+ struct stats_time_cache *time = NULL;
+ unsigned int index = 0;
+
+ if (mod_stats == NULL)
+ return;
+
+ core_stats = MOD_STATS_TO_CORE(mod_stats);
+
+ if (core_stats->index >= core_stats->entries)
+ return;
+
+ time = core_stats->time;
+ index = core_stats->index;
+
+ time[index].flip_timestamp_in_ns = timestamp_in_ns;
+ time[index].render_time_in_us =
+ timestamp_in_ns - time[index - 1].flip_timestamp_in_ns;
+
+ if (index >= 10) {
+ for (unsigned int i = 0; i < 10; i++)
+ time[index].avg_render_time_in_us_last_ten +=
+ time[index - i].render_time_in_us;
+ time[index].avg_render_time_in_us_last_ten /= 10;
+ }
+
+ if (time[index].num_vsync_between_flips > 0)
+ time[index].vsync_to_flip_time_in_us =
+ timestamp_in_ns - time[index].vupdate_timestamp_in_ns;
+ else
+ time[index].vsync_to_flip_time_in_us =
+ timestamp_in_ns - time[index - 1].vupdate_timestamp_in_ns;
+
+ core_stats->index++;
+}
+
+void mod_stats_update_vupdate(struct mod_stats *mod_stats,
+ unsigned long timestamp_in_ns)
+{
+ struct core_stats *core_stats = NULL;
+ struct stats_time_cache *time = NULL;
+ unsigned int index = 0;
+
+ if (mod_stats == NULL)
+ return;
+
+ core_stats = MOD_STATS_TO_CORE(mod_stats);
+
+ if (core_stats->index >= core_stats->entries)
+ return;
+
+ time = core_stats->time;
+ index = core_stats->index;
+
+ time[index].vupdate_timestamp_in_ns = timestamp_in_ns;
+ if (time[index].num_vsync_between_flips < MOD_STATS_NUM_VSYNCS)
+ time[index].v_sync_time_in_us[time[index].num_vsync_between_flips] =
+ timestamp_in_ns - time[index - 1].vupdate_timestamp_in_ns;
+ time[index].flip_to_vsync_time_in_us =
+ timestamp_in_ns - time[index - 1].flip_timestamp_in_ns;
+
+ time[index].num_vsync_between_flips++;
+}
+
+void mod_stats_update_freesync(struct mod_stats *mod_stats,
+ unsigned int v_total_min,
+ unsigned int v_total_max,
+ unsigned int event_triggers,
+ unsigned int window_min,
+ unsigned int window_max,
+ unsigned int lfc_mid_point_in_us,
+ unsigned int inserted_frames,
+ unsigned int inserted_duration_in_us)
+{
+ struct core_stats *core_stats = NULL;
+ struct stats_time_cache *time = NULL;
+ unsigned int index = 0;
+
+ if (mod_stats == NULL)
+ return;
+
+ core_stats = MOD_STATS_TO_CORE(mod_stats);
+
+ if (core_stats->index >= core_stats->entries)
+ return;
+
+ time = core_stats->time;
+ index = core_stats->index;
+
+ time[index].v_total_min = v_total_min;
+ time[index].v_total_max = v_total_max;
+ time[index].event_triggers = event_triggers;
+ time[index].min_window = window_min;
+ time[index].max_window = window_max;
+ time[index].lfc_mid_point_in_us = lfc_mid_point_in_us;
+ time[index].num_frames_inserted = inserted_frames;
+ time[index].inserted_duration_in_us = inserted_duration_in_us;
+}
+