diff options
Diffstat (limited to 'common/recipes-kernel/linux/files/0956-drm-amd-dal-add-core-support-for-Polaris-family-v2.patch')
-rw-r--r-- | common/recipes-kernel/linux/files/0956-drm-amd-dal-add-core-support-for-Polaris-family-v2.patch | 9820 |
1 files changed, 0 insertions, 9820 deletions
diff --git a/common/recipes-kernel/linux/files/0956-drm-amd-dal-add-core-support-for-Polaris-family-v2.patch b/common/recipes-kernel/linux/files/0956-drm-amd-dal-add-core-support-for-Polaris-family-v2.patch deleted file mode 100644 index 6143ca86..00000000 --- a/common/recipes-kernel/linux/files/0956-drm-amd-dal-add-core-support-for-Polaris-family-v2.patch +++ /dev/null @@ -1,9820 +0,0 @@ -From bc3e400b9b554d0e8448d89c7a721f887b612dfc Mon Sep 17 00:00:00 2001 -From: Alex Deucher <alexander.deucher@amd.com> -Date: Tue, 15 Mar 2016 10:53:48 -0400 -Subject: [PATCH 0956/1110] drm/amd/dal: add core support for Polaris family - (v2) - -This adds core dc support for polaris 10 and 11. - -v2: add missing files - -Signed-off-by: Alex Deucher <alexander.deucher@amd.com> ---- - drivers/gpu/drm/amd/dal/dc/Makefile | 4 + - drivers/gpu/drm/amd/dal/dc/adapter/Makefile | 4 + - .../gpu/drm/amd/dal/dc/adapter/adapter_service.c | 12 + - .../adapter/dce112/hw_ctx_adapter_service_dce112.c | 302 +++ - .../adapter/dce112/hw_ctx_adapter_service_dce112.h | 39 + - .../gpu/drm/amd/dal/dc/asic_capability/Makefile | 9 + - .../amd/dal/dc/asic_capability/asic_capability.c | 15 +- - .../dc/asic_capability/polaris10_asic_capability.c | 146 ++ - .../dc/asic_capability/polaris10_asic_capability.h | 36 + - drivers/gpu/drm/amd/dal/dc/audio/Makefile | 8 + - drivers/gpu/drm/amd/dal/dc/audio/audio_base.c | 9 + - .../gpu/drm/amd/dal/dc/audio/dce112/audio_dce112.c | 451 +++++ - .../gpu/drm/amd/dal/dc/audio/dce112/audio_dce112.h | 40 + - .../amd/dal/dc/audio/dce112/hw_ctx_audio_dce112.c | 1923 ++++++++++++++++++++ - .../amd/dal/dc/audio/dce112/hw_ctx_audio_dce112.h | 47 + - drivers/gpu/drm/amd/dal/dc/bios/Makefile | 9 + - .../gpu/drm/amd/dal/dc/bios/bios_parser_helper.c | 6 + - .../gpu/drm/amd/dal/dc/bios/bios_parser_helper.h | 4 + - drivers/gpu/drm/amd/dal/dc/bios/command_table.c | 78 +- - .../gpu/drm/amd/dal/dc/bios/command_table_helper.c | 6 + - .../gpu/drm/amd/dal/dc/bios/command_table_helper.h | 3 + - .../dal/dc/bios/dce112/bios_parser_helper_dce112.c | 480 +++++ - .../dal/dc/bios/dce112/bios_parser_helper_dce112.h | 34 + - .../dc/bios/dce112/command_table_helper_dce112.c | 417 +++++ - .../dc/bios/dce112/command_table_helper_dce112.h | 34 + - drivers/gpu/drm/amd/dal/dc/calcs/bandwidth_calcs.c | 206 +++ - drivers/gpu/drm/amd/dal/dc/core/dc_hw_sequencer.c | 7 + - drivers/gpu/drm/amd/dal/dc/core/dc_resource.c | 22 +- - .../drm/amd/dal/dc/dce110/dce110_hw_sequencer.c | 1 + - .../amd/dal/dc/dce110/dce110_timing_generator.c | 2 +- - drivers/gpu/drm/amd/dal/dc/dce112/Makefile | 10 + - .../drm/amd/dal/dc/dce112/dce112_clock_source.c | 266 +++ - .../drm/amd/dal/dc/dce112/dce112_clock_source.h | 52 + - .../gpu/drm/amd/dal/dc/dce112/dce112_compressor.c | 883 +++++++++ - .../gpu/drm/amd/dal/dc/dce112/dce112_compressor.h | 84 + - .../drm/amd/dal/dc/dce112/dce112_hw_sequencer.c | 178 ++ - .../drm/amd/dal/dc/dce112/dce112_hw_sequencer.h | 36 + - .../drm/amd/dal/dc/dce112/dce112_link_encoder.c | 116 ++ - .../drm/amd/dal/dc/dce112/dce112_link_encoder.h | 41 + - .../gpu/drm/amd/dal/dc/dce112/dce112_mem_input.c | 455 +++++ - .../gpu/drm/amd/dal/dc/dce112/dce112_mem_input.h | 38 + - .../gpu/drm/amd/dal/dc/dce112/dce112_resource.c | 1404 ++++++++++++++ - .../gpu/drm/amd/dal/dc/dce112/dce112_resource.h | 42 + - drivers/gpu/drm/amd/dal/dc/dm_services_types.h | 5 + - drivers/gpu/drm/amd/dal/dc/gpio/hw_factory.c | 3 + - drivers/gpu/drm/amd/dal/dc/gpio/hw_translate.c | 3 + - drivers/gpu/drm/amd/dal/dc/gpu/Makefile | 8 + - .../amd/dal/dc/gpu/dce112/dc_clock_gating_dce112.c | 89 + - .../amd/dal/dc/gpu/dce112/dc_clock_gating_dce112.h | 33 + - .../amd/dal/dc/gpu/dce112/display_clock_dce112.c | 964 ++++++++++ - .../amd/dal/dc/gpu/dce112/display_clock_dce112.h | 54 + - drivers/gpu/drm/amd/dal/dc/i2caux/i2caux.c | 5 +- - drivers/gpu/drm/amd/dal/dc/inc/bandwidth_calcs.h | 4 +- - drivers/gpu/drm/amd/dal/dc/irq/irq_service.c | 4 + - drivers/gpu/drm/amd/dal/include/dal_asic_id.h | 14 + - drivers/gpu/drm/amd/dal/include/dal_types.h | 3 + - .../drm/amd/dal/include/display_clock_interface.h | 6 + - 57 files changed, 9146 insertions(+), 8 deletions(-) - create mode 100644 drivers/gpu/drm/amd/dal/dc/adapter/dce112/hw_ctx_adapter_service_dce112.c - create mode 100644 drivers/gpu/drm/amd/dal/dc/adapter/dce112/hw_ctx_adapter_service_dce112.h - create mode 100644 drivers/gpu/drm/amd/dal/dc/asic_capability/polaris10_asic_capability.c - create mode 100644 drivers/gpu/drm/amd/dal/dc/asic_capability/polaris10_asic_capability.h - create mode 100644 drivers/gpu/drm/amd/dal/dc/audio/dce112/audio_dce112.c - create mode 100644 drivers/gpu/drm/amd/dal/dc/audio/dce112/audio_dce112.h - create mode 100644 drivers/gpu/drm/amd/dal/dc/audio/dce112/hw_ctx_audio_dce112.c - create mode 100644 drivers/gpu/drm/amd/dal/dc/audio/dce112/hw_ctx_audio_dce112.h - create mode 100644 drivers/gpu/drm/amd/dal/dc/bios/dce112/bios_parser_helper_dce112.c - create mode 100644 drivers/gpu/drm/amd/dal/dc/bios/dce112/bios_parser_helper_dce112.h - create mode 100644 drivers/gpu/drm/amd/dal/dc/bios/dce112/command_table_helper_dce112.c - create mode 100644 drivers/gpu/drm/amd/dal/dc/bios/dce112/command_table_helper_dce112.h - create mode 100644 drivers/gpu/drm/amd/dal/dc/dce112/Makefile - create mode 100644 drivers/gpu/drm/amd/dal/dc/dce112/dce112_clock_source.c - create mode 100644 drivers/gpu/drm/amd/dal/dc/dce112/dce112_clock_source.h - create mode 100644 drivers/gpu/drm/amd/dal/dc/dce112/dce112_compressor.c - create mode 100644 drivers/gpu/drm/amd/dal/dc/dce112/dce112_compressor.h - create mode 100644 drivers/gpu/drm/amd/dal/dc/dce112/dce112_hw_sequencer.c - create mode 100644 drivers/gpu/drm/amd/dal/dc/dce112/dce112_hw_sequencer.h - create mode 100644 drivers/gpu/drm/amd/dal/dc/dce112/dce112_link_encoder.c - create mode 100644 drivers/gpu/drm/amd/dal/dc/dce112/dce112_link_encoder.h - create mode 100644 drivers/gpu/drm/amd/dal/dc/dce112/dce112_mem_input.c - create mode 100644 drivers/gpu/drm/amd/dal/dc/dce112/dce112_mem_input.h - create mode 100644 drivers/gpu/drm/amd/dal/dc/dce112/dce112_resource.c - create mode 100644 drivers/gpu/drm/amd/dal/dc/dce112/dce112_resource.h - create mode 100644 drivers/gpu/drm/amd/dal/dc/gpu/dce112/dc_clock_gating_dce112.c - create mode 100644 drivers/gpu/drm/amd/dal/dc/gpu/dce112/dc_clock_gating_dce112.h - create mode 100644 drivers/gpu/drm/amd/dal/dc/gpu/dce112/display_clock_dce112.c - create mode 100644 drivers/gpu/drm/amd/dal/dc/gpu/dce112/display_clock_dce112.h - -diff --git a/drivers/gpu/drm/amd/dal/dc/Makefile b/drivers/gpu/drm/amd/dal/dc/Makefile -index 5112ec9..a718674 100644 ---- a/drivers/gpu/drm/amd/dal/dc/Makefile -+++ b/drivers/gpu/drm/amd/dal/dc/Makefile -@@ -5,6 +5,10 @@ - DC_LIBS = adapter asic_capability audio basics bios calcs \ - gpio gpu i2caux irq virtual - -+ifdef CONFIG_DRM_AMD_DAL_DCE11_2 -+DC_LIBS += dce112 -+endif -+ - ifdef CONFIG_DRM_AMD_DAL_DCE11_0 - DC_LIBS += dce110 - endif -diff --git a/drivers/gpu/drm/amd/dal/dc/adapter/Makefile b/drivers/gpu/drm/amd/dal/dc/adapter/Makefile -index db1f0e8..370323e 100644 ---- a/drivers/gpu/drm/amd/dal/dc/adapter/Makefile -+++ b/drivers/gpu/drm/amd/dal/dc/adapter/Makefile -@@ -25,6 +25,10 @@ ifdef CONFIG_DRM_AMD_DAL_DCE11_0 - AMD_DAL_FILES += $(AMDDALPATH)/dc/adapter/dce110/hw_ctx_adapter_service_dce110.o - endif - -+ifdef CONFIG_DRM_AMD_DAL_DCE11_2 -+AMD_DAL_FILES += $(AMDDALPATH)/dc/adapter/dce112/hw_ctx_adapter_service_dce112.o -+endif -+ - ############################################################################### - # FPGA Diagnositcs - ############################################################################### -diff --git a/drivers/gpu/drm/amd/dal/dc/adapter/adapter_service.c b/drivers/gpu/drm/amd/dal/dc/adapter/adapter_service.c -index f7aea01..308d456 100644 ---- a/drivers/gpu/drm/amd/dal/dc/adapter/adapter_service.c -+++ b/drivers/gpu/drm/amd/dal/dc/adapter/adapter_service.c -@@ -49,6 +49,10 @@ - #include "dce110/hw_ctx_adapter_service_dce110.h" - #endif - -+#if defined(CONFIG_DRM_AMD_DAL_DCE11_2) -+#include "dce112/hw_ctx_adapter_service_dce112.h" -+#endif -+ - #include "diagnostics/hw_ctx_adapter_service_diag.h" - - /* -@@ -664,6 +668,10 @@ static struct hw_ctx_adapter_service *create_hw_ctx( - case DCE_VERSION_11_0: - return dal_adapter_service_create_hw_ctx_dce110(ctx); - #endif -+#if defined(CONFIG_DRM_AMD_DAL_DCE11_2) -+ case DCE_VERSION_11_2: -+ return dal_adapter_service_create_hw_ctx_dce112(ctx); -+#endif - default: - ASSERT_CRITICAL(false); - return NULL; -@@ -907,6 +915,10 @@ enum dce_version dal_adapter_service_get_dce_version( - case 0x110: - return DCE_VERSION_11_0; - #endif -+#if defined(CONFIG_DRM_AMD_DAL_DCE11_2) -+ case 0x112: -+ return DCE_VERSION_11_2; -+#endif - default: - ASSERT_CRITICAL(false); - return DCE_VERSION_UNKNOWN; -diff --git a/drivers/gpu/drm/amd/dal/dc/adapter/dce112/hw_ctx_adapter_service_dce112.c b/drivers/gpu/drm/amd/dal/dc/adapter/dce112/hw_ctx_adapter_service_dce112.c -new file mode 100644 -index 0000000..f438998 ---- /dev/null -+++ b/drivers/gpu/drm/amd/dal/dc/adapter/dce112/hw_ctx_adapter_service_dce112.c -@@ -0,0 +1,302 @@ -+/* -+ * Copyright 2012-15 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 "dm_services.h" -+ -+#include "../hw_ctx_adapter_service.h" -+ -+#include "hw_ctx_adapter_service_dce112.h" -+ -+#include "include/logger_interface.h" -+#include "include/grph_object_id.h" -+ -+#include "dce/dce_11_2_d.h" -+#include "dce/dce_11_2_sh_mask.h" -+ -+#ifndef mmCC_DC_HDMI_STRAPS -+#define mmCC_DC_HDMI_STRAPS 0x4819 -+#define CC_DC_HDMI_STRAPS__HDMI_DISABLE_MASK 0x40 -+#define CC_DC_HDMI_STRAPS__HDMI_DISABLE__SHIFT 0x6 -+#define CC_DC_HDMI_STRAPS__AUDIO_STREAM_NUMBER_MASK 0x700 -+#define CC_DC_HDMI_STRAPS__AUDIO_STREAM_NUMBER__SHIFT 0x8 -+#endif -+ -+static const struct graphics_object_id invalid_go = { -+ 0, ENUM_ID_UNKNOWN, OBJECT_TYPE_UNKNOWN, 0 -+}; -+ -+/* Macro */ -+#define AUDIO_STRAPS_HDMI_ENABLE 0x2 -+ -+#define FROM_HW_CTX(ptr) \ -+ container_of((ptr), struct hw_ctx_adapter_service_dce112, base) -+ -+static const uint32_t audio_index_reg_offset[] = { -+ /*CZ has 3 DIGs but 4 audio endpoints*/ -+ mmAZF0ENDPOINT0_AZALIA_F0_CODEC_ENDPOINT_INDEX, -+ mmAZF0ENDPOINT1_AZALIA_F0_CODEC_ENDPOINT_INDEX, -+ mmAZF0ENDPOINT2_AZALIA_F0_CODEC_ENDPOINT_INDEX, -+ mmAZF0ENDPOINT3_AZALIA_F0_CODEC_ENDPOINT_INDEX -+}; -+ -+static const uint32_t audio_data_reg_offset[] = { -+ mmAZF0ENDPOINT0_AZALIA_F0_CODEC_ENDPOINT_DATA, -+ mmAZF0ENDPOINT1_AZALIA_F0_CODEC_ENDPOINT_DATA, -+ mmAZF0ENDPOINT2_AZALIA_F0_CODEC_ENDPOINT_DATA, -+ mmAZF0ENDPOINT3_AZALIA_F0_CODEC_ENDPOINT_DATA, -+}; -+ -+enum { -+ MAX_NUMBER_OF_AUDIO_PINS = 4 -+}; -+ -+static void destruct( -+ struct hw_ctx_adapter_service_dce112 *hw_ctx) -+{ -+ /* There is nothing to destruct at the moment */ -+ dal_adapter_service_destruct_hw_ctx(&hw_ctx->base); -+} -+ -+static void destroy( -+ struct hw_ctx_adapter_service *ptr) -+{ -+ struct hw_ctx_adapter_service_dce112 *hw_ctx = -+ FROM_HW_CTX(ptr); -+ -+ destruct(hw_ctx); -+ -+ dm_free(hw_ctx); -+} -+ -+/* -+ * enum_audio_object -+ * -+ * @brief enumerate audio object -+ * -+ * @param -+ * const struct hw_ctx_adapter_service *hw_ctx - [in] provides num of endpoints -+ * uint32_t index - [in] audio index -+ * -+ * @return -+ * grphic object id -+ */ -+static struct graphics_object_id enum_audio_object( -+ const struct hw_ctx_adapter_service *hw_ctx, -+ uint32_t index) -+{ -+ uint32_t number_of_connected_audio_endpoints = -+ FROM_HW_CTX(hw_ctx)->number_of_connected_audio_endpoints; -+ -+ if (index >= number_of_connected_audio_endpoints || -+ number_of_connected_audio_endpoints == 0) -+ return invalid_go; -+ else -+ return dal_graphics_object_id_init( -+ AUDIO_ID_INTERNAL_AZALIA, -+ (enum object_enum_id)(index + 1), -+ OBJECT_TYPE_AUDIO); -+} -+ -+static uint32_t get_number_of_connected_audio_endpoints_multistream( -+ struct dc_context *ctx) -+{ -+ uint32_t num_connected_audio_endpoints = 0; -+ uint32_t i; -+ uint32_t default_config = -+ ixAZALIA_F0_CODEC_PIN_CONTROL_RESPONSE_CONFIGURATION_DEFAULT; -+ -+ /* find the total number of streams available via the -+ * AZALIA_F0_CODEC_PIN_CONTROL_RESPONSE_CONFIGURATION_DEFAULT -+ * registers (one for each pin) starting from pin 1 -+ * up to the max number of audio pins. -+ * We stop on the first pin where -+ * PORT_CONNECTIVITY == 1 (as instructed by HW team). -+ */ -+ for (i = 0; i < MAX_NUMBER_OF_AUDIO_PINS; i++) { -+ uint32_t value = 0; -+ -+ set_reg_field_value(value, -+ default_config, -+ AZALIA_F0_CODEC_ENDPOINT_INDEX, -+ AZALIA_ENDPOINT_REG_INDEX); -+ -+ dm_write_reg(ctx, audio_index_reg_offset[i], value); -+ -+ value = 0; -+ value = dm_read_reg(ctx, audio_data_reg_offset[i]); -+ -+ /* 1 means not supported*/ -+ if (get_reg_field_value(value, -+ AZALIA_F0_CODEC_PIN_CONTROL_RESPONSE_CONFIGURATION_DEFAULT, -+ PORT_CONNECTIVITY) == 1) -+ break; -+ -+ num_connected_audio_endpoints++; -+ } -+ -+ return num_connected_audio_endpoints; -+ -+} -+ -+/* -+ * get_number_of_connected_audio_endpoints -+ */ -+static uint32_t get_number_of_connected_audio_endpoints( -+ struct hw_ctx_adapter_service *hw_ctx) -+{ -+ uint32_t addr = mmCC_DC_HDMI_STRAPS; -+ uint32_t value = 0; -+ uint32_t field = 0; -+ -+ if (hw_ctx->cached_audio_straps == AUDIO_STRAPS_NOT_ALLOWED) -+ /* audio straps indicate no audio supported */ -+ return 0; -+ -+ value = dm_read_reg(hw_ctx->ctx, addr); -+ -+ field = get_reg_field_value( -+ value, CC_DC_HDMI_STRAPS, AUDIO_STREAM_NUMBER); -+ if (field == 1) -+ /* multi streams not supported */ -+ return 1; -+ else if (field == 0) -+ /* multi streams supported */ -+ return get_number_of_connected_audio_endpoints_multistream( -+ hw_ctx->ctx); -+ -+ /* unexpected value */ -+ ASSERT_CRITICAL(false); -+ return field; -+} -+ -+/* -+ * power_up -+ * -+ * @brief -+ * Determine and cache audio support from register. -+ * -+ * @param -+ * struct hw_ctx_adapter_service *hw_ctx - [in] adapter service hw context -+ * -+ * @return -+ * true if succeed, false otherwise -+ */ -+static bool power_up( -+ struct hw_ctx_adapter_service *hw_ctx) -+{ -+ struct hw_ctx_adapter_service_dce112 *hw_ctx_dce11 = -+ FROM_HW_CTX(hw_ctx); -+ /* Allow DP audio all the time -+ * without additional pinstrap check on Fusion */ -+ -+ { -+ uint32_t value = 0; -+ uint32_t field = 0; -+ -+ value = dm_read_reg(hw_ctx->ctx, mmCC_DC_HDMI_STRAPS); -+ field = get_reg_field_value( -+ value, CC_DC_HDMI_STRAPS, HDMI_DISABLE); -+ -+ if (field == 0) { -+ hw_ctx->cached_audio_straps = AUDIO_STRAPS_DP_HDMI_AUDIO; -+ } else { -+ value = dm_read_reg( -+ hw_ctx->ctx, mmDC_PINSTRAPS); -+ field = get_reg_field_value( -+ value, -+ DC_PINSTRAPS, -+ DC_PINSTRAPS_AUDIO); -+ -+ if (field & AUDIO_STRAPS_HDMI_ENABLE) -+ hw_ctx->cached_audio_straps = -+ AUDIO_STRAPS_DP_HDMI_AUDIO_ON_DONGLE; -+ else -+ hw_ctx->cached_audio_straps = -+ AUDIO_STRAPS_DP_AUDIO_ALLOWED; -+ } -+ -+ } -+ -+ /* get the number of connected audio endpoints */ -+ hw_ctx_dce11->number_of_connected_audio_endpoints = -+ get_number_of_connected_audio_endpoints(hw_ctx); -+ -+ return true; -+} -+ -+static void update_audio_connectivity( -+ struct hw_ctx_adapter_service *hw_ctx, -+ uint32_t number_of_audio_capable_display_path, -+ uint32_t number_of_controllers) -+{ -+ /* this one should be empty on DCE112 */ -+} -+ -+static const struct hw_ctx_adapter_service_funcs funcs = { -+ .destroy = destroy, -+ .power_up = power_up, -+ .enum_fake_path_resource = NULL, -+ .enum_stereo_sync_object = NULL, -+ .enum_sync_output_object = NULL, -+ .enum_audio_object = enum_audio_object, -+ .update_audio_connectivity = update_audio_connectivity -+}; -+ -+static bool construct( -+ struct hw_ctx_adapter_service_dce112 *hw_ctx, -+ struct dc_context *ctx) -+{ -+ if (!dal_adapter_service_construct_hw_ctx(&hw_ctx->base, ctx)) { -+ ASSERT_CRITICAL(false); -+ return false; -+ } -+ -+ hw_ctx->base.funcs = &funcs; -+ hw_ctx->number_of_connected_audio_endpoints = 0; -+ -+ return true; -+} -+ -+struct hw_ctx_adapter_service * -+ dal_adapter_service_create_hw_ctx_dce112( -+ struct dc_context *ctx) -+{ -+ struct hw_ctx_adapter_service_dce112 *hw_ctx = -+ dm_alloc(sizeof(struct hw_ctx_adapter_service_dce112)); -+ -+ if (!hw_ctx) { -+ ASSERT_CRITICAL(false); -+ return NULL; -+ } -+ -+ if (construct(hw_ctx, ctx)) -+ return &hw_ctx->base; -+ -+ ASSERT_CRITICAL(false); -+ -+ dm_free(hw_ctx); -+ -+ return NULL; -+} -diff --git a/drivers/gpu/drm/amd/dal/dc/adapter/dce112/hw_ctx_adapter_service_dce112.h b/drivers/gpu/drm/amd/dal/dc/adapter/dce112/hw_ctx_adapter_service_dce112.h -new file mode 100644 -index 0000000..bc60030 ---- /dev/null -+++ b/drivers/gpu/drm/amd/dal/dc/adapter/dce112/hw_ctx_adapter_service_dce112.h -@@ -0,0 +1,39 @@ -+/* -+ * Copyright 2012-15 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 __DAL_HW_CTX_ADAPTER_SERVICE_DCE112_H__ -+#define __DAL_HW_CTX_ADAPTER_SERVICE_DCE112_H__ -+ -+struct hw_ctx_adapter_service_dce112 { -+ struct hw_ctx_adapter_service base; -+ uint32_t number_of_connected_audio_endpoints; -+}; -+ -+struct hw_ctx_adapter_service * -+ dal_adapter_service_create_hw_ctx_dce112( -+ struct dc_context *ctx); -+ -+#endif /* __DAL_HW_CTX_ADAPTER_SERVICE_DCE112_H__ */ -+ -diff --git a/drivers/gpu/drm/amd/dal/dc/asic_capability/Makefile b/drivers/gpu/drm/amd/dal/dc/asic_capability/Makefile -index b243542..e80de2a 100644 ---- a/drivers/gpu/drm/amd/dal/dc/asic_capability/Makefile -+++ b/drivers/gpu/drm/amd/dal/dc/asic_capability/Makefile -@@ -46,3 +46,12 @@ AMD_DAL_ASIC_CAPABILITY_DCE11 = \ - - AMD_DAL_FILES += $(AMD_DAL_ASIC_CAPABILITY_DCE11) - endif -+ -+ifdef CONFIG_DRM_AMD_DAL_DCE11_2 -+ASIC_CAPABILITY_DCE112 = polaris10_asic_capability.o -+ -+AMD_DAL_ASIC_CAPABILITY_DCE112 = \ -+ $(addprefix $(AMDDALPATH)/dc/asic_capability/,$(ASIC_CAPABILITY_DCE112)) -+ -+AMD_DAL_FILES += $(AMD_DAL_ASIC_CAPABILITY_DCE112) -+endif -diff --git a/drivers/gpu/drm/amd/dal/dc/asic_capability/asic_capability.c b/drivers/gpu/drm/amd/dal/dc/asic_capability/asic_capability.c -index 75e0e27..aeabfc6 100644 ---- a/drivers/gpu/drm/amd/dal/dc/asic_capability/asic_capability.c -+++ b/drivers/gpu/drm/amd/dal/dc/asic_capability/asic_capability.c -@@ -44,6 +44,10 @@ - #include "carrizo_asic_capability.h" - #endif - -+#if defined(CONFIG_DRM_AMD_DAL_DCE11_2) -+#include "polaris10_asic_capability.h" -+#endif -+ - /* - * Initializes asic_capability instance. - */ -@@ -108,7 +112,8 @@ static bool construct( - asic_supported = true; - #endif - break; -- case FAMILY_VI: -+ -+ case FAMILY_VI: - #if defined(CONFIG_DRM_AMD_DAL_DCE10_0) - if (ASIC_REV_IS_TONGA_P(init->hw_internal_rev) || - ASIC_REV_IS_FIJI_P(init->hw_internal_rev)) { -@@ -117,7 +122,15 @@ static bool construct( - break; - } - #endif -+#if defined(CONFIG_DRM_AMD_DAL_DCE11_2) -+ if (ASIC_REV_IS_POLARIS10_P(init->hw_internal_rev) || -+ ASIC_REV_IS_POLARIS11_M(init->hw_internal_rev)) { -+ polaris10_asic_capability_create(cap, init); -+ asic_supported = true; -+ } -+#endif - break; -+ - default: - /* unsupported "chip_family" */ - break; -diff --git a/drivers/gpu/drm/amd/dal/dc/asic_capability/polaris10_asic_capability.c b/drivers/gpu/drm/amd/dal/dc/asic_capability/polaris10_asic_capability.c -new file mode 100644 -index 0000000..9e4fdfa ---- /dev/null -+++ b/drivers/gpu/drm/amd/dal/dc/asic_capability/polaris10_asic_capability.c -@@ -0,0 +1,146 @@ -+/* -+ * Copyright 2012-15 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 "dm_services.h" -+ -+#include "include/asic_capability_interface.h" -+#include "include/asic_capability_types.h" -+ -+#include "polaris10_asic_capability.h" -+ -+#include "atom.h" -+#include "dce/dce_11_2_d.h" -+#include "dce/dce_11_2_sh_mask.h" -+#include "dal_asic_id.h" -+ -+#define ixVCE_HARVEST_FUSE_MACRO__ADDRESS 0xC0014074 -+ -+/* -+ * carrizo_asic_capability_create -+ * -+ * Create and initiate Carrizo capability. -+ */ -+void polaris10_asic_capability_create(struct asic_capability *cap, -+ struct hw_asic_id *init) -+{ -+ uint32_t e_fuse_setting; -+ /* ASIC data */ -+ if (ASIC_REV_IS_POLARIS11_M(init->hw_internal_rev)) { -+ cap->data[ASIC_DATA_CONTROLLERS_NUM] = 5; -+ cap->data[ASIC_DATA_FUNCTIONAL_CONTROLLERS_NUM] = 5; -+ cap->data[ASIC_DATA_LINEBUFFER_NUM] = 5; -+ cap->data[ASIC_DATA_DIGFE_NUM] = 5; -+ cap->data[ASIC_DATA_CLOCKSOURCES_NUM] = 7; -+ cap->data[ASIC_DATA_MAX_COFUNC_NONDP_DISPLAYS] = 5; -+ cap->data[ASIC_DATA_SUPPORTED_HDMI_CONNECTION_NUM] = 5; -+ } else { -+ cap->data[ASIC_DATA_CONTROLLERS_NUM] = 6; -+ cap->data[ASIC_DATA_FUNCTIONAL_CONTROLLERS_NUM] = 6; -+ cap->data[ASIC_DATA_LINEBUFFER_NUM] = 6; -+ cap->data[ASIC_DATA_DIGFE_NUM] = 6; -+ cap->data[ASIC_DATA_CLOCKSOURCES_NUM] = 8; -+ cap->data[ASIC_DATA_MAX_COFUNC_NONDP_DISPLAYS] = 6; -+ cap->data[ASIC_DATA_SUPPORTED_HDMI_CONNECTION_NUM] = 6; -+ } -+ -+ cap->data[ASIC_DATA_PATH_NUM_PER_DPMST_CONNECTOR] = 4; -+ cap->data[ASIC_DATA_DCE_VERSION] = 0x112; /* DCE 11 */ -+ cap->data[ASIC_DATA_LINEBUFFER_SIZE] = 5124 * 144; -+ cap->data[ASIC_DATA_DRAM_BANDWIDTH_EFFICIENCY] = 70; -+ -+ cap->data[ASIC_DATA_MC_LATENCY] = 3000; -+ cap->data[ASIC_DATA_STUTTERMODE] = 0x200A; -+ cap->data[ASIC_DATA_VIEWPORT_PIXEL_GRANULARITY] = 2; -+ -+ cap->data[ASIC_DATA_MEMORYTYPE_MULTIPLIER] = 4; -+ cap->data[ASIC_DATA_DEFAULT_I2C_SPEED_IN_KHZ] = 100; -+ cap->data[ASIC_DATA_NUM_OF_VIDEO_PLANES] = 0; -+ -+ cap->data[ASIC_DATA_MIN_DISPCLK_FOR_UNDERSCAN] = 300000; -+ -+ /* ASIC basic capability */ -+ cap->caps.IS_FUSION = true; -+ cap->caps.DP_MST_SUPPORTED = true; -+ cap->caps.PANEL_SELF_REFRESH_SUPPORTED = true; -+ cap->caps.MIRABILIS_SUPPORTED = true; -+ cap->caps.NO_VCC_OFF_HPD_POLLING = true; -+ cap->caps.VCE_SUPPORTED = true; -+ cap->caps.HPD_CHECK_FOR_EDID = true; -+ cap->caps.DFSBYPASS_DYNAMIC_SUPPORT = true; -+ cap->caps.SUPPORT_8BPP = false; -+ -+ /* ASIC stereo 3d capability */ -+ cap->stereo_3d_caps.DISPLAY_BASED_ON_WS = true; -+ cap->stereo_3d_caps.HDMI_FRAME_PACK = true; -+ cap->stereo_3d_caps.INTERLACE_FRAME_PACK = true; -+ cap->stereo_3d_caps.DISPLAYPORT_FRAME_PACK = true; -+ cap->stereo_3d_caps.DISPLAYPORT_FRAME_ALT = true; -+ cap->stereo_3d_caps.INTERLEAVE = true; -+ -+ e_fuse_setting = dm_read_index_reg(cap->ctx,CGS_IND_REG__SMC, ixVCE_HARVEST_FUSE_MACRO__ADDRESS); -+ -+ /* Bits [28:27]*/ -+ switch ((e_fuse_setting >> 27) & 0x3) { -+ case 0: -+ /*both VCE engine are working*/ -+ cap->caps.VCE_SUPPORTED = true; -+ cap->caps.WIRELESS_TIMING_ADJUSTMENT = false; -+ /*TODO: -+ cap->caps.wirelessLowVCEPerformance = false; -+ m_AsicCaps.vceInstance0Enabled = true; -+ m_AsicCaps.vceInstance1Enabled = true;*/ -+ cap->caps.NEED_MC_TUNING = true; -+ break; -+ -+ case 1: -+ cap->caps.VCE_SUPPORTED = true; -+ cap->caps.WIRELESS_TIMING_ADJUSTMENT = true; -+ /*TODO: -+ m_AsicCaps.wirelessLowVCEPerformance = false; -+ m_AsicCaps.vceInstance1Enabled = true;*/ -+ cap->caps.NEED_MC_TUNING = true; -+ break; -+ -+ case 2: -+ cap->caps.VCE_SUPPORTED = true; -+ cap->caps.WIRELESS_TIMING_ADJUSTMENT = true; -+ /*TODO: -+ m_AsicCaps.wirelessLowVCEPerformance = false; -+ m_AsicCaps.vceInstance0Enabled = true;*/ -+ cap->caps.NEED_MC_TUNING = true; -+ break; -+ -+ case 3: -+ /* VCE_DISABLE = 0x3 - both VCE -+ * instances are in harvesting, -+ * no VCE supported any more. -+ */ -+ cap->caps.VCE_SUPPORTED = false; -+ break; -+ -+ default: -+ break; -+ } -+} -diff --git a/drivers/gpu/drm/amd/dal/dc/asic_capability/polaris10_asic_capability.h b/drivers/gpu/drm/amd/dal/dc/asic_capability/polaris10_asic_capability.h -new file mode 100644 -index 0000000..c8aebe1 ---- /dev/null -+++ b/drivers/gpu/drm/amd/dal/dc/asic_capability/polaris10_asic_capability.h -@@ -0,0 +1,36 @@ -+/* -+ * Copyright 2012-15 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 __DAL_POLARIS10_ASIC_CAPABILITY_H__ -+#define __DAL_POLARIS10_ASIC_CAPABILITY_H__ -+ -+/* Forward declaration */ -+struct asic_capability; -+ -+/* Create and initialize Polaris10 data */ -+void polaris10_asic_capability_create(struct asic_capability *cap, -+ struct hw_asic_id *init); -+ -+#endif /* __DAL_POLARIS10_ASIC_CAPABILITY_H__ */ -diff --git a/drivers/gpu/drm/amd/dal/dc/audio/Makefile b/drivers/gpu/drm/amd/dal/dc/audio/Makefile -index 2433d90..9a9a64c 100644 ---- a/drivers/gpu/drm/amd/dal/dc/audio/Makefile -+++ b/drivers/gpu/drm/amd/dal/dc/audio/Makefile -@@ -32,3 +32,11 @@ AMD_DAL_AUDIO_DCE11 = $(addprefix $(AMDDALPATH)/dc/audio/dce110/,$(AUDIO_DCE11)) - - AMD_DAL_FILES += $(AMD_DAL_AUDIO_DCE11) - endif -+ -+ifdef CONFIG_DRM_AMD_DAL_DCE11_2 -+AUDIO_DCE112 = audio_dce112.o hw_ctx_audio_dce112.o -+ -+AMD_DAL_AUDIO_DCE112 = $(addprefix $(AMDDALPATH)/dc/audio/dce112/,$(AUDIO_DCE112)) -+ -+AMD_DAL_FILES += $(AMD_DAL_AUDIO_DCE112) -+endif -diff --git a/drivers/gpu/drm/amd/dal/dc/audio/audio_base.c b/drivers/gpu/drm/amd/dal/dc/audio/audio_base.c -index c297d95..a8137e0 100644 ---- a/drivers/gpu/drm/amd/dal/dc/audio/audio_base.c -+++ b/drivers/gpu/drm/amd/dal/dc/audio/audio_base.c -@@ -40,6 +40,11 @@ - #include "dce110/hw_ctx_audio_dce110.h" - #endif - -+#if defined(CONFIG_DRM_AMD_DAL_DCE11_2) -+#include "dce112/audio_dce112.h" -+#include "dce112/hw_ctx_audio_dce112.h" -+#endif -+ - /***** static function : only used within audio.c *****/ - - /* stub for hook functions */ -@@ -281,6 +286,10 @@ struct audio *dal_audio_create( - case DCE_VERSION_11_0: - return dal_audio_create_dce110(init_data); - #endif -+#if defined(CONFIG_DRM_AMD_DAL_DCE11_2) -+ case DCE_VERSION_11_2: -+ return dal_audio_create_dce112(init_data); -+#endif - default: - BREAK_TO_DEBUGGER(); - return NULL; -diff --git a/drivers/gpu/drm/amd/dal/dc/audio/dce112/audio_dce112.c b/drivers/gpu/drm/amd/dal/dc/audio/dce112/audio_dce112.c -new file mode 100644 -index 0000000..66c32b0 ---- /dev/null -+++ b/drivers/gpu/drm/amd/dal/dc/audio/dce112/audio_dce112.c -@@ -0,0 +1,451 @@ -+/* -+ * Copyright 2012-15 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 "dm_services.h" -+ -+#include "include/logger_interface.h" -+ -+#include "audio_dce112.h" -+ -+/***** static functions *****/ -+ -+static void destruct(struct audio_dce112 *audio) -+{ -+ /*release memory allocated for hw_ctx -- allocated is initiated -+ *by audio_dce112 power_up -+ *audio->base->hw_ctx = NULL is done within hw-ctx->destroy -+ */ -+ if (audio->base.hw_ctx) -+ audio->base.hw_ctx->funcs->destroy(&(audio->base.hw_ctx)); -+ -+ /* reset base_audio_block */ -+ dal_audio_destruct_base(&audio->base); -+} -+ -+static void destroy(struct audio **ptr) -+{ -+ struct audio_dce112 *audio = NULL; -+ -+ audio = container_of(*ptr, struct audio_dce112, base); -+ -+ destruct(audio); -+ -+ /* release memory allocated for audio_dce112*/ -+ dm_free(audio); -+ *ptr = NULL; -+} -+ -+/* The inital call of hook function comes from audio object level. -+ *The passing object handle "struct audio *audio" point to base object -+ *already.There is not need to get base object from audio_dce112. -+ */ -+ -+/** -+* setup -+* -+* @brief -+* setup Audio HW block, to be called by dal_audio_setup -+* -+*/ -+static enum audio_result setup( -+ struct audio *audio, -+ struct audio_output *output, -+ struct audio_info *info) -+{ -+ switch (output->signal) { -+ case SIGNAL_TYPE_HDMI_TYPE_A: -+ /*setup HDMI audio engine*/ -+ audio->hw_ctx->funcs->enable_afmt_clock( -+ audio->hw_ctx, -+ output->engine_id, -+ true); -+ audio->hw_ctx->funcs->setup_hdmi_audio( -+ audio->hw_ctx, output->engine_id, &output->crtc_info); -+ -+ audio->hw_ctx->funcs->setup_azalia( -+ audio->hw_ctx, -+ output->engine_id, -+ output->signal, -+ &output->crtc_info, -+ &output->pll_info, -+ info); -+ break; -+ -+ case SIGNAL_TYPE_WIRELESS: -+ /* setup Azalia block for Wireless Display - This -+ is different than for wired -+ displays because there is no -+ DIG to program.*/ -+ /*TODO: -+ audio->hw_ctx->funcs->setup_azalia_for_vce( -+ audio->hw_ctx, -+ audio->signal, -+ audio->crtc_info, -+ info); -+ */ -+ break; -+ case SIGNAL_TYPE_DISPLAY_PORT: -+ case SIGNAL_TYPE_DISPLAY_PORT_MST: -+ case SIGNAL_TYPE_EDP: -+ /* setup DP audio engine will be done at enable output */ -+ -+ /* setup Azalia block*/ -+ audio->hw_ctx->funcs->setup_azalia( -+ audio->hw_ctx, -+ output->engine_id, -+ output->signal, -+ &output->crtc_info, -+ &output->pll_info, -+ info); -+ -+ break; -+ default: -+ return AUDIO_RESULT_ERROR; -+ } -+ -+ return AUDIO_RESULT_OK; -+} -+ -+/** -+* enable_output -+* -+* @brief -+* enable Audio HW block, to be called by dal_audio_enable_output -+*/ -+static enum audio_result enable_output( -+ struct audio *audio, -+ enum engine_id engine_id, -+ enum signal_type signal) -+{ -+ /* enable audio output */ -+ switch (signal) { -+ case SIGNAL_TYPE_HDMI_TYPE_A: -+ break; -+ case SIGNAL_TYPE_DISPLAY_PORT: -+ case SIGNAL_TYPE_DISPLAY_PORT_MST: -+ case SIGNAL_TYPE_EDP: { -+ /* enable AFMT clock before enable audio*/ -+ audio->hw_ctx->funcs->enable_afmt_clock( -+ audio->hw_ctx, engine_id, true); -+ /* setup DP audio engine */ -+ audio->hw_ctx->funcs->setup_dp_audio( -+ audio->hw_ctx, engine_id); -+ /* enabl DP audio packets will be done at unblank */ -+ audio->hw_ctx->funcs->enable_dp_audio( -+ audio->hw_ctx, engine_id); -+ } -+ break; -+ case SIGNAL_TYPE_WIRELESS: -+ /* route audio to VCE block */ -+ audio->hw_ctx->funcs->setup_vce_audio(audio->hw_ctx); -+ break; -+ default: -+ return AUDIO_RESULT_ERROR; -+ } -+ return AUDIO_RESULT_OK; -+} -+ -+/** -+* disable_output -+* -+* @brief -+* disable Audio HW block, to be called by dal_audio_disable_output -+* -+*/ -+static enum audio_result disable_output( -+ struct audio *audio, -+ enum engine_id engine_id, -+ enum signal_type signal) -+{ -+ switch (signal) { -+ case SIGNAL_TYPE_HDMI_TYPE_A: -+ case SIGNAL_TYPE_WIRELESS: -+ /* disable HDMI audio */ -+ audio->hw_ctx-> -+ funcs->disable_azalia_audio( -+ audio->hw_ctx, engine_id); -+ audio->hw_ctx-> -+ funcs->enable_afmt_clock( -+ audio->hw_ctx, engine_id, -+ false); -+ -+ break; -+ case SIGNAL_TYPE_DISPLAY_PORT: -+ case SIGNAL_TYPE_DISPLAY_PORT_MST: -+ case SIGNAL_TYPE_EDP: { -+ /* disable DP audio */ -+ audio->hw_ctx->funcs->disable_dp_audio( -+ audio->hw_ctx, engine_id); -+ audio->hw_ctx->funcs->disable_azalia_audio( -+ audio->hw_ctx, engine_id); -+ audio->hw_ctx->funcs->enable_afmt_clock( -+ audio->hw_ctx, engine_id, false); -+ } -+ break; -+ default: -+ return AUDIO_RESULT_ERROR; -+ } -+ -+ return AUDIO_RESULT_OK; -+} -+ -+/** -+* unmute -+* -+* @brief -+* unmute audio, to be called by dal_audio_unmute -+* -+*/ -+static enum audio_result unmute( -+ struct audio *audio, -+ enum engine_id engine_id, -+ enum signal_type signal) -+{ -+ switch (signal) { -+ case SIGNAL_TYPE_HDMI_TYPE_A: -+ case SIGNAL_TYPE_DISPLAY_PORT: -+ case SIGNAL_TYPE_DISPLAY_PORT_MST: -+ case SIGNAL_TYPE_EDP: -+ /* unmute Azalia audio */ -+ audio->hw_ctx->funcs->unmute_azalia_audio( -+ audio->hw_ctx, engine_id); -+ break; -+ case SIGNAL_TYPE_WIRELESS: -+ /*Do nothing for wireless display*/ -+ break; -+ default: -+ return AUDIO_RESULT_ERROR; -+ } -+ return AUDIO_RESULT_OK; -+} -+ -+/** -+* mute -+* -+* @brief -+* mute audio, to be called by dal_audio_nmute -+* -+*/ -+static enum audio_result mute( -+ struct audio *audio, -+ enum engine_id engine_id, -+ enum signal_type signal) -+{ -+ switch (signal) { -+ case SIGNAL_TYPE_HDMI_TYPE_A: -+ case SIGNAL_TYPE_DISPLAY_PORT: -+ case SIGNAL_TYPE_DISPLAY_PORT_MST: -+ case SIGNAL_TYPE_EDP: -+ /* mute Azalia audio */ -+ audio->hw_ctx->funcs->mute_azalia_audio( -+ audio->hw_ctx, engine_id); -+ break; -+ case SIGNAL_TYPE_WIRELESS: -+ /*Do nothing for wireless display*/ -+ break; -+ default: -+ return AUDIO_RESULT_ERROR; -+ } -+ return AUDIO_RESULT_OK; -+} -+ -+/** -+* initialize -+* -+* @brief -+* Perform SW initialization - create audio hw context. Then do HW -+* initialization. this function is called at dal_audio_power_up. -+* -+*/ -+static enum audio_result initialize( -+ struct audio *audio) -+{ -+ uint8_t audio_endpoint_enum_id = 0; -+ -+ audio_endpoint_enum_id = audio->id.enum_id; -+ -+ /* HW CTX already create*/ -+ if (audio->hw_ctx != NULL) -+ return AUDIO_RESULT_OK; -+ -+ audio->hw_ctx = dal_hw_ctx_audio_dce112_create( -+ audio->ctx, -+ audio_endpoint_enum_id); -+ -+ if (audio->hw_ctx == NULL) -+ return AUDIO_RESULT_ERROR; -+ -+ /* override HW default settings */ -+ audio->hw_ctx->funcs->hw_initialize(audio->hw_ctx); -+ -+ return AUDIO_RESULT_OK; -+} -+ -+/* enable multi channel split */ -+static void enable_channel_splitting_mapping( -+ struct audio *audio, -+ enum engine_id engine_id, -+ enum signal_type signal, -+ const struct audio_channel_associate_info *audio_mapping, -+ bool enable) -+{ -+ audio->hw_ctx->funcs->setup_channel_splitting_mapping( -+ audio->hw_ctx, -+ engine_id, -+ signal, -+ audio_mapping, enable); -+} -+ -+/* get current multi channel split. */ -+static enum audio_result get_channel_splitting_mapping( -+ struct audio *audio, -+ enum engine_id engine_id, -+ struct audio_channel_associate_info *audio_mapping) -+{ -+ if (audio->hw_ctx->funcs->get_channel_splitting_mapping( -+ audio->hw_ctx, engine_id, audio_mapping)) { -+ return AUDIO_RESULT_OK; -+ } else { -+ return AUDIO_RESULT_ERROR; -+ } -+} -+ -+/** -+* set_unsolicited_response_payload -+* -+* @brief -+* Set payload value for the unsolicited response -+*/ -+static void set_unsolicited_response_payload( -+ struct audio *audio, -+ enum audio_payload payload) -+{ -+ audio->hw_ctx->funcs->set_unsolicited_response_payload( -+ audio->hw_ctx, payload); -+} -+ -+/** -+* setup_audio_wall_dto -+* -+* @brief -+* Update audio source clock from hardware context. -+* -+*/ -+static void setup_audio_wall_dto( -+ struct audio *audio, -+ enum signal_type signal, -+ const struct audio_crtc_info *crtc_info, -+ const struct audio_pll_info *pll_info) -+{ -+ audio->hw_ctx->funcs->setup_audio_wall_dto( -+ audio->hw_ctx, signal, crtc_info, pll_info); -+} -+ -+/** -+* get_supported_features -+* -+* @brief -+* options and features supported by Audio -+* returns supported engines, signals. -+* features are reported for HW audio/Azalia block rather then Audio object -+* itself the difference for DCE6.x is that MultiStream Audio is now supported -+* -+*/ -+static struct audio_feature_support get_supported_features(struct audio *audio) -+{ -+ struct audio_feature_support afs = {0}; -+ -+ afs.ENGINE_DIGA = 1; -+ afs.ENGINE_DIGB = 1; -+ afs.ENGINE_DIGC = 1; -+ afs.MULTISTREAM_AUDIO = 1; -+ -+ return afs; -+} -+ -+static const struct audio_funcs funcs = { -+ .destroy = destroy, -+ .setup = setup, -+ .enable_output = enable_output, -+ .disable_output = disable_output, -+ .unmute = unmute, -+ .mute = mute, -+ .initialize = initialize, -+ .enable_channel_splitting_mapping = -+ enable_channel_splitting_mapping, -+ .get_channel_splitting_mapping = -+ get_channel_splitting_mapping, -+ .set_unsolicited_response_payload = -+ set_unsolicited_response_payload, -+ .setup_audio_wall_dto = setup_audio_wall_dto, -+ .get_supported_features = get_supported_features, -+}; -+ -+static bool construct( -+ struct audio_dce112 *audio, -+ const struct audio_init_data *init_data) -+{ -+ struct audio *base = &audio->base; -+ -+ /* base audio construct*/ -+ if (!dal_audio_construct_base(base, init_data)) -+ return false; -+ -+ /*vtable methods*/ -+ base->funcs = &funcs; -+ return true; -+} -+ -+/* --- audio scope functions --- */ -+ -+struct audio *dal_audio_create_dce112( -+ const struct audio_init_data *init_data) -+{ -+ /*allocate memory for audio_dce112 */ -+ struct audio_dce112 *audio = dm_alloc(sizeof(*audio)); -+ -+ if (audio == NULL) { -+ ASSERT_CRITICAL(audio); -+ return NULL; -+ } -+ /*pointer to base_audio_block of audio_dce112 ==> audio base object */ -+ if (construct(audio, init_data)) -+ return &audio->base; -+ -+ dal_logger_write( -+ init_data->ctx->logger, -+ LOG_MAJOR_ERROR, -+ LOG_MINOR_COMPONENT_AUDIO, -+ "Failed to create audio object for DCE11\n"); -+ -+ /*release memory allocated if fail */ -+ dm_free(audio); -+ return NULL; -+} -+ -+/* Do not need expose construct_dce112 and destruct_dce112 becuase there is -+ *derived object after dce112 -+ */ -+ -diff --git a/drivers/gpu/drm/amd/dal/dc/audio/dce112/audio_dce112.h b/drivers/gpu/drm/amd/dal/dc/audio/dce112/audio_dce112.h -new file mode 100644 -index 0000000..7c8d71c ---- /dev/null -+++ b/drivers/gpu/drm/amd/dal/dc/audio/dce112/audio_dce112.h -@@ -0,0 +1,40 @@ -+/* -+ * Copyright 2012-15 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 __DAL_AUDIO_DCE_112_H__ -+#define __DAL_AUDIO_DCE_112_H__ -+ -+#include "audio/audio.h" -+#include "audio/hw_ctx_audio.h" -+#include "audio/dce112/hw_ctx_audio_dce112.h" -+ -+struct audio_dce112 { -+ struct audio base; -+ /* dce-specific members are following */ -+ /* none */ -+}; -+ -+struct audio *dal_audio_create_dce112(const struct audio_init_data *init_data); -+ -+#endif /*__DAL_AUDIO_DCE_112_H__*/ -diff --git a/drivers/gpu/drm/amd/dal/dc/audio/dce112/hw_ctx_audio_dce112.c b/drivers/gpu/drm/amd/dal/dc/audio/dce112/hw_ctx_audio_dce112.c -new file mode 100644 -index 0000000..95cb86f ---- /dev/null -+++ b/drivers/gpu/drm/amd/dal/dc/audio/dce112/hw_ctx_audio_dce112.c -@@ -0,0 +1,1923 @@ -+/* -+ * Copyright 2012-15 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 "dm_services.h" -+ -+#include "include/logger_interface.h" -+#include "../hw_ctx_audio.h" -+#include "hw_ctx_audio_dce112.h" -+ -+#include "dce/dce_11_2_d.h" -+#include "dce/dce_11_2_sh_mask.h" -+ -+#define FROM_BASE(ptr) \ -+ container_of((ptr), struct hw_ctx_audio_dce112, base) -+ -+#define DP_SEC_AUD_N__DP_SEC_AUD_N__DEFAULT 0x8000 -+#define DP_AUDIO_DTO_MODULE_WITHOUT_SS 360 -+#define DP_AUDIO_DTO_PHASE_WITHOUT_SS 24 -+ -+#define DP_SEC_TIMESTAMP__DP_SEC_TIMESTAMP_MODE__AUDIO_FRONT_END 0 -+#define DP_SEC_TIMESTAMP__DP_SEC_TIMESTAMP_MODE__AUTO_CALC 1 -+#define DP_SEC_TIMESTAMP__DP_SEC_TIMESTAMP_MODE__REGISTER_PROGRAMMABLE 2 -+ -+#define FIRST_AUDIO_STREAM_ID 1 -+ -+#define NOT_IMPLEMENTED() DAL_LOGGER_NOT_IMPL(LOG_MINOR_COMPONENT_AUDIO, \ -+ "Audio:%s()\n", __func__) -+ -+static const uint32_t engine_offset[] = { -+ 0, -+ mmDIG1_DIG_FE_CNTL - mmDIG0_DIG_FE_CNTL, -+ mmDIG2_DIG_FE_CNTL - mmDIG0_DIG_FE_CNTL, -+ mmDIG3_DIG_FE_CNTL - mmDIG0_DIG_FE_CNTL, -+ mmDIG4_DIG_FE_CNTL - mmDIG0_DIG_FE_CNTL, -+ mmDIG5_DIG_FE_CNTL - mmDIG0_DIG_FE_CNTL -+}; -+ -+static void destruct( -+ struct hw_ctx_audio_dce112 *hw_ctx_dce112) -+{ -+ dal_audio_destruct_hw_ctx_audio(&hw_ctx_dce112->base); -+} -+ -+static void destroy( -+ struct hw_ctx_audio **ptr) -+{ -+ struct hw_ctx_audio_dce112 *hw_ctx_dce112; -+ -+ hw_ctx_dce112 = container_of( -+ *ptr, struct hw_ctx_audio_dce112, base); -+ -+ destruct(hw_ctx_dce112); -+ /* release memory allocated for struct hw_ctx_audio_dce112 */ -+ dm_free(hw_ctx_dce112); -+ -+ *ptr = NULL; -+} -+ -+/* --- helpers --- */ -+static void write_indirect_azalia_reg( -+ const struct hw_ctx_audio *hw_ctx, -+ uint32_t reg_index, -+ uint32_t reg_data) -+{ -+ uint32_t addr = 0; -+ uint32_t value = 0; -+ /* AZALIA_F0_CODEC_ENDPOINT_INDEX endpoint index */ -+ { -+ addr = -+ FROM_BASE(hw_ctx)->az_mm_reg_offsets. -+ azf0endpointx_azalia_f0_codec_endpoint_index; -+ -+ set_reg_field_value(value, reg_index, -+ AZALIA_F0_CODEC_ENDPOINT_INDEX, -+ AZALIA_ENDPOINT_REG_INDEX); -+ -+ dm_write_reg(hw_ctx->ctx, addr, value); -+ } -+ -+ /* AZALIA_F0_CODEC_ENDPOINT_DATA endpoint data */ -+ { -+ addr = -+ FROM_BASE(hw_ctx)->az_mm_reg_offsets. -+ azf0endpointx_azalia_f0_codec_endpoint_data; -+ -+ value = 0; -+ set_reg_field_value(value, reg_data, -+ AZALIA_F0_CODEC_ENDPOINT_DATA, -+ AZALIA_ENDPOINT_REG_DATA); -+ dm_write_reg(hw_ctx->ctx, addr, value); -+ } -+ -+ dal_logger_write( -+ hw_ctx->ctx->logger, -+ LOG_MAJOR_HW_TRACE, -+ LOG_MINOR_HW_TRACE_AUDIO, -+ "AUDIO:write_indirect_azalia_reg: index: %u data: %u\n", -+ reg_index, reg_data); -+} -+ -+static uint32_t read_indirect_azalia_reg( -+ const struct hw_ctx_audio *hw_ctx, -+ uint32_t reg_index) -+{ -+ uint32_t ret_val = 0; -+ uint32_t addr = 0; -+ uint32_t value = 0; -+ -+ /* AZALIA_F0_CODEC_ENDPOINT_INDEX endpoint index */ -+ { -+ addr = -+ FROM_BASE(hw_ctx)->az_mm_reg_offsets. -+ azf0endpointx_azalia_f0_codec_endpoint_index; -+ -+ set_reg_field_value(value, reg_index, -+ AZALIA_F0_CODEC_ENDPOINT_INDEX, -+ AZALIA_ENDPOINT_REG_INDEX); -+ -+ dm_write_reg(hw_ctx->ctx, addr, value); -+ } -+ -+ /* AZALIA_F0_CODEC_ENDPOINT_DATA endpoint data */ -+ { -+ addr = -+ FROM_BASE(hw_ctx)->az_mm_reg_offsets. -+ azf0endpointx_azalia_f0_codec_endpoint_data; -+ -+ value = dm_read_reg(hw_ctx->ctx, addr); -+ ret_val = value; -+ } -+ -+ dal_logger_write( -+ hw_ctx->ctx->logger, -+ LOG_MAJOR_HW_TRACE, -+ LOG_MINOR_HW_TRACE_AUDIO, -+ "AUDIO:read_indirect_azalia_reg: index: %u data: %u\n", -+ reg_index, ret_val); -+ -+ return ret_val; -+} -+ -+/* expose/not expose HBR capability to Audio driver */ -+static void set_high_bit_rate_capable( -+ const struct hw_ctx_audio *hw_ctx, -+ bool capable) -+{ -+ uint32_t value = 0; -+ -+ /* set high bit rate audio capable*/ -+ value = read_indirect_azalia_reg( -+ hw_ctx, -+ ixAZALIA_F0_CODEC_PIN_CONTROL_RESPONSE_HBR); -+ -+ set_reg_field_value(value, capable, -+ AZALIA_F0_CODEC_PIN_CONTROL_RESPONSE_HBR, -+ HBR_CAPABLE); -+ -+ write_indirect_azalia_reg( -+ hw_ctx, -+ ixAZALIA_F0_CODEC_PIN_CONTROL_RESPONSE_HBR, -+ value); -+} -+ -+/* set HBR channnel count * -+static void set_hbr_channel_count( -+ const struct hw_ctx_audio *hw_ctx, -+ uint32_t hbr_channel_count) -+{ -+ uint32_t value = 0; -+ -+ if (hbr_channel_count > 7) -+ return; -+ -+ value = dal_read_reg(hw_ctx->ctx, -+ mmAZALIA_F0_CODEC_CHANNEL_COUNT_CONTROL); -+ -+ set_reg_field_value(value, hbr_channel_count, -+ AZALIA_F0_CODEC_CHANNEL_COUNT_CONTROL, -+ HBR_CHANNEL_COUNT); -+ -+ dal_write_reg(hw_ctx->ctx, -+ mmAZALIA_F0_CODEC_CHANNEL_COUNT_CONTROL, value); -+ -+} -+ -+*set compressed audio channel count * -+static void set_compressed_audio_channel_count( -+ const struct hw_ctx_audio *hw_ctx, -+ uint32_t compressed_audio_ch_count) -+{ -+ uint32_t value = 0; -+ if (compressed_audio_ch_count > 7) -+ return; -+ -+ value = dal_read_reg(hw_ctx->ctx, -+ mmAZALIA_F0_CODEC_CHANNEL_COUNT_CONTROL); -+ -+ set_reg_field_value(value, compressed_audio_ch_count, -+ AZALIA_F0_CODEC_CHANNEL_COUNT_CONTROL, -+ COMPRESSED_CHANNEL_COUNT); -+ -+ dal_write_reg(hw_ctx->ctx, -+ mmAZALIA_F0_CODEC_CHANNEL_COUNT_CONTROL, -+ value); -+ -+} -+*/ -+/* set video latency in in ms/2+1 */ -+static void set_video_latency( -+ const struct hw_ctx_audio *hw_ctx, -+ int latency_in_ms) -+{ -+ uint32_t value = 0; -+ -+ if ((latency_in_ms < 0) || (latency_in_ms > 255)) -+ return; -+ -+ value = read_indirect_azalia_reg( -+ hw_ctx, -+ ixAZALIA_F0_CODEC_PIN_CONTROL_RESPONSE_LIPSYNC); -+ -+ set_reg_field_value(value, latency_in_ms, -+ AZALIA_F0_CODEC_PIN_CONTROL_RESPONSE_LIPSYNC, -+ VIDEO_LIPSYNC); -+ -+ write_indirect_azalia_reg( -+ hw_ctx, -+ ixAZALIA_F0_CODEC_PIN_CONTROL_RESPONSE_LIPSYNC, -+ value); -+ -+} -+ -+/* set audio latency in in ms/2+1 */ -+static void set_audio_latency( -+ const struct hw_ctx_audio *hw_ctx, -+ int latency_in_ms) -+{ -+ uint32_t value = 0; -+ -+ if (latency_in_ms < 0) -+ latency_in_ms = 0; -+ -+ if (latency_in_ms > 255) -+ latency_in_ms = 255; -+ -+ value = read_indirect_azalia_reg( -+ hw_ctx, -+ ixAZALIA_F0_CODEC_PIN_CONTROL_RESPONSE_LIPSYNC); -+ -+ set_reg_field_value(value, latency_in_ms, -+ AZALIA_F0_CODEC_PIN_CONTROL_RESPONSE_LIPSYNC, -+ AUDIO_LIPSYNC); -+ -+ write_indirect_azalia_reg( -+ hw_ctx, -+ ixAZALIA_F0_CODEC_PIN_CONTROL_RESPONSE_LIPSYNC, -+ value); -+ -+} -+ -+/* enable HW/SW Sync */ -+/*static void enable_hw_sw_sync( -+ const struct hw_ctx_audio *hw_ctx) -+{ -+ union AZALIA_CYCLIC_BUFFER_SYNC value; -+ -+ value = dal_read_reg(mmAZALIA_CYCLIC_BUFFER_SYNC); -+ value.bits.CYCLIC_BUFFER_SYNC_ENABLE = 1; -+ dal_write_reg(mmAZALIA_CYCLIC_BUFFER_SYNC, value); -+}*/ -+ -+/* disable HW/SW Sync */ -+/*static void disable_hw_sw_sync( -+ const struct hw_ctx_audio *hw_ctx) -+{ -+ union AZALIA_CYCLIC_BUFFER_SYNC value; -+ -+ value = dal_read_reg( -+ mmAZALIA_CYCLIC_BUFFER_SYNC); -+ value.bits.CYCLIC_BUFFER_SYNC_ENABLE = 0; -+ dal_write_reg( -+ mmAZALIA_CYCLIC_BUFFER_SYNC, value); -+}*/ -+ -+/* update hardware with software's current position in cyclic buffer */ -+/*static void update_sw_write_ptr( -+ const struct hw_ctx_audio *hw_ctx, -+ uint32_t offset) -+{ -+ union AZALIA_APPLICATION_POSITION_IN_CYCLIC_BUFFER value; -+ -+ value = dal_read_reg( -+ mmAZALIA_APPLICATION_POSITION_IN_CYCLIC_BUFFER); -+ value.bits.APPLICATION_POSITION_IN_CYCLIC_BUFFER = offset; -+ dal_write_reg( -+ mmAZALIA_APPLICATION_POSITION_IN_CYCLIC_BUFFER, -+ value); -+}*/ -+ -+/* update Audio/Video association */ -+/*static void update_av_association( -+ const struct hw_ctx_audio *hw_ctx, -+ enum engine_id engine_id, -+ enum signal_type signal, -+ uint32_t displayId) -+{ -+ -+}*/ -+ -+/* --- hook functions --- */ -+static bool get_azalia_clock_info_hdmi( -+ const struct hw_ctx_audio *hw_ctx, -+ uint32_t crtc_pixel_clock_in_khz, -+ uint32_t actual_pixel_clock_in_khz, -+ struct azalia_clock_info *azalia_clock_info); -+ -+static bool get_azalia_clock_info_dp( -+ const struct hw_ctx_audio *hw_ctx, -+ uint32_t requested_pixel_clock_in_khz, -+ const struct audio_pll_info *pll_info, -+ struct azalia_clock_info *azalia_clock_info); -+ -+static void setup_audio_wall_dto( -+ const struct hw_ctx_audio *hw_ctx, -+ enum signal_type signal, -+ const struct audio_crtc_info *crtc_info, -+ const struct audio_pll_info *pll_info) -+{ -+ struct azalia_clock_info clock_info = { 0 }; -+ -+ uint32_t value = dm_read_reg(hw_ctx->ctx, mmDCCG_AUDIO_DTO_SOURCE); -+ -+ /* TODO: GraphicsObject\inc\GraphicsObjectDefs.hpp(131): -+ *inline bool isHdmiSignal(SignalType signal) -+ *if (Signals::isHdmiSignal(signal)) -+ */ -+ if (dc_is_hdmi_signal(signal)) { -+ /*DTO0 Programming goal: -+ -generate 24MHz, 128*Fs from 24MHz -+ -use DTO0 when an active HDMI port is connected -+ (optionally a DP is connected) */ -+ -+ /* calculate DTO settings */ -+ get_azalia_clock_info_hdmi( -+ hw_ctx, -+ crtc_info->requested_pixel_clock, -+ crtc_info->calculated_pixel_clock, -+ &clock_info); -+ -+ /* On TN/SI, Program DTO source select and DTO select before -+ programming DTO modulo and DTO phase. These bits must be -+ programmed first, otherwise there will be no HDMI audio at boot -+ up. This is a HW sequence change (different from old ASICs). -+ Caution when changing this programming sequence. -+ -+ HDMI enabled, using DTO0 -+ program master CRTC for DTO0 */ -+ { -+ set_reg_field_value(value, -+ pll_info->dto_source - DTO_SOURCE_ID0, -+ DCCG_AUDIO_DTO_SOURCE, -+ DCCG_AUDIO_DTO0_SOURCE_SEL); -+ -+ set_reg_field_value(value, -+ 0, -+ DCCG_AUDIO_DTO_SOURCE, -+ DCCG_AUDIO_DTO_SEL); -+ -+ dm_write_reg(hw_ctx->ctx, -+ mmDCCG_AUDIO_DTO_SOURCE, value); -+ } -+ -+ /* module */ -+ { -+ value = dm_read_reg(hw_ctx->ctx, -+ mmDCCG_AUDIO_DTO0_MODULE); -+ set_reg_field_value(value, -+ clock_info.audio_dto_module, -+ DCCG_AUDIO_DTO0_MODULE, -+ DCCG_AUDIO_DTO0_MODULE); -+ dm_write_reg(hw_ctx->ctx, -+ mmDCCG_AUDIO_DTO0_MODULE, value); -+ } -+ -+ /* phase */ -+ { -+ value = 0; -+ -+ value = dm_read_reg(hw_ctx->ctx, -+ mmDCCG_AUDIO_DTO0_PHASE); -+ set_reg_field_value(value, -+ clock_info.audio_dto_phase, -+ DCCG_AUDIO_DTO0_PHASE, -+ DCCG_AUDIO_DTO0_PHASE); -+ -+ dm_write_reg(hw_ctx->ctx, -+ mmDCCG_AUDIO_DTO0_PHASE, value); -+ } -+ -+ } else { -+ /*DTO1 Programming goal: -+ -generate 24MHz, 512*Fs, 128*Fs from 24MHz -+ -default is to used DTO1, and switch to DTO0 when an audio -+ master HDMI port is connected -+ -use as default for DP -+ -+ calculate DTO settings */ -+ get_azalia_clock_info_dp( -+ hw_ctx, -+ crtc_info->requested_pixel_clock, -+ pll_info, -+ &clock_info); -+ -+ /* Program DTO select before programming DTO modulo and DTO -+ phase. default to use DTO1 */ -+ -+ { -+ set_reg_field_value(value, 1, -+ DCCG_AUDIO_DTO_SOURCE, -+ DCCG_AUDIO_DTO_SEL); -+ /*dal_write_reg(mmDCCG_AUDIO_DTO_SOURCE, value)*/ -+ -+ /* Select 512fs for DP TODO: web register definition -+ does not match register header file -+ set_reg_field_value(value, 1, -+ DCCG_AUDIO_DTO_SOURCE, -+ DCCG_AUDIO_DTO2_USE_512FBR_DTO); -+ */ -+ -+ dm_write_reg(hw_ctx->ctx, -+ mmDCCG_AUDIO_DTO_SOURCE, value); -+ } -+ -+ /* module */ -+ { -+ value = 0; -+ -+ value = dm_read_reg(hw_ctx->ctx, -+ mmDCCG_AUDIO_DTO1_MODULE); -+ -+ set_reg_field_value(value, -+ clock_info.audio_dto_module, -+ DCCG_AUDIO_DTO1_MODULE, -+ DCCG_AUDIO_DTO1_MODULE); -+ -+ dm_write_reg(hw_ctx->ctx, -+ mmDCCG_AUDIO_DTO1_MODULE, value); -+ } -+ -+ /* phase */ -+ { -+ value = 0; -+ -+ value = dm_read_reg(hw_ctx->ctx, -+ mmDCCG_AUDIO_DTO1_PHASE); -+ -+ set_reg_field_value(value, -+ clock_info.audio_dto_phase, -+ DCCG_AUDIO_DTO1_PHASE, -+ DCCG_AUDIO_DTO1_PHASE); -+ -+ dm_write_reg(hw_ctx->ctx, -+ mmDCCG_AUDIO_DTO1_PHASE, value); -+ } -+ -+ /* DAL2 code separate DCCG_AUDIO_DTO_SEL and -+ DCCG_AUDIO_DTO2_USE_512FBR_DTO programming into two different -+ location. merge together should not hurt */ -+ /*value.bits.DCCG_AUDIO_DTO2_USE_512FBR_DTO = 1; -+ dal_write_reg(mmDCCG_AUDIO_DTO_SOURCE, value);*/ -+ } -+} -+ -+/* setup HDMI audio */ -+static void setup_hdmi_audio( -+ const struct hw_ctx_audio *hw_ctx, -+ enum engine_id engine_id, -+ const struct audio_crtc_info *crtc_info) -+{ -+ struct audio_clock_info audio_clock_info = {0}; -+ uint32_t max_packets_per_line; -+ uint32_t addr = 0; -+ uint32_t value = 0; -+ -+ /* For now still do calculation, although this field is ignored when -+ above HDMI_PACKET_GEN_VERSION set to 1 */ -+ max_packets_per_line = -+ dal_audio_hw_ctx_calc_max_audio_packets_per_line( -+ hw_ctx, -+ crtc_info); -+ -+ /* HDMI_AUDIO_PACKET_CONTROL */ -+ { -+ addr = -+ mmHDMI_AUDIO_PACKET_CONTROL + engine_offset[engine_id]; -+ -+ value = dm_read_reg(hw_ctx->ctx, addr); -+ -+ set_reg_field_value(value, max_packets_per_line, -+ HDMI_AUDIO_PACKET_CONTROL, -+ HDMI_AUDIO_PACKETS_PER_LINE); -+ /* still apply RS600's default setting which is 1. */ -+ set_reg_field_value(value, 1, -+ HDMI_AUDIO_PACKET_CONTROL, -+ HDMI_AUDIO_DELAY_EN); -+ -+ dm_write_reg(hw_ctx->ctx, addr, value); -+ } -+ -+ /* AFMT_AUDIO_PACKET_CONTROL */ -+ { -+ addr = mmAFMT_AUDIO_PACKET_CONTROL + engine_offset[engine_id]; -+ -+ value = dm_read_reg(hw_ctx->ctx, addr); -+ -+ set_reg_field_value(value, 1, -+ AFMT_AUDIO_PACKET_CONTROL, -+ AFMT_60958_CS_UPDATE); -+ -+ dm_write_reg(hw_ctx->ctx, addr, value); -+ } -+ -+ /* AFMT_AUDIO_PACKET_CONTROL2 */ -+ { -+ addr = mmAFMT_AUDIO_PACKET_CONTROL2 + engine_offset[engine_id]; -+ -+ value = dm_read_reg(hw_ctx->ctx, addr); -+ -+ set_reg_field_value(value, 0, -+ AFMT_AUDIO_PACKET_CONTROL2, -+ AFMT_AUDIO_LAYOUT_OVRD); -+ -+ /*Register field changed.*/ -+ set_reg_field_value(value, 0, -+ AFMT_AUDIO_PACKET_CONTROL2, -+ AFMT_60958_OSF_OVRD); -+ -+ dm_write_reg(hw_ctx->ctx, addr, value); -+ } -+ -+ /* HDMI_ACR_PACKET_CONTROL */ -+ { -+ addr = mmHDMI_ACR_PACKET_CONTROL + engine_offset[engine_id]; -+ -+ value = dm_read_reg(hw_ctx->ctx, addr); -+ set_reg_field_value(value, 1, -+ HDMI_ACR_PACKET_CONTROL, -+ HDMI_ACR_AUTO_SEND); -+ -+ /* Set HDMI_ACR_SOURCE to 0, to use hardwre -+ * computed CTS values.*/ -+ set_reg_field_value(value, 0, -+ HDMI_ACR_PACKET_CONTROL, -+ HDMI_ACR_SOURCE); -+ -+ /* For now clear HDMI_ACR_AUDIO_PRIORITY =>ACR packet has -+ higher priority over Audio Sample */ -+ set_reg_field_value(value, 0, -+ HDMI_ACR_PACKET_CONTROL, -+ HDMI_ACR_AUDIO_PRIORITY); -+ -+ dm_write_reg(hw_ctx->ctx, addr, value); -+ } -+ -+ /* Program audio clock sample/regeneration parameters */ -+ if (dal_audio_hw_ctx_get_audio_clock_info( -+ hw_ctx, -+ crtc_info->color_depth, -+ crtc_info->requested_pixel_clock, -+ crtc_info->calculated_pixel_clock, -+ &audio_clock_info)) { -+ -+ /* HDMI_ACR_32_0__HDMI_ACR_CTS_32_MASK */ -+ { -+ addr = mmHDMI_ACR_32_0 + engine_offset[engine_id]; -+ -+ value = dm_read_reg(hw_ctx->ctx, addr); -+ -+ set_reg_field_value(value, audio_clock_info.cts_32khz, -+ HDMI_ACR_32_0, -+ HDMI_ACR_CTS_32); -+ -+ dm_write_reg(hw_ctx->ctx, addr, value); -+ } -+ -+ /* HDMI_ACR_32_1__HDMI_ACR_N_32_MASK */ -+ { -+ addr = mmHDMI_ACR_32_1 + engine_offset[engine_id]; -+ -+ value = dm_read_reg(hw_ctx->ctx, addr); -+ set_reg_field_value(value, audio_clock_info.n_32khz, -+ HDMI_ACR_32_1, -+ HDMI_ACR_N_32); -+ -+ dm_write_reg(hw_ctx->ctx, addr, value); -+ } -+ -+ /* HDMI_ACR_44_0__HDMI_ACR_CTS_44_MASK */ -+ { -+ addr = mmHDMI_ACR_44_0 + engine_offset[engine_id]; -+ -+ value = dm_read_reg(hw_ctx->ctx, addr); -+ set_reg_field_value(value, audio_clock_info.cts_44khz, -+ HDMI_ACR_44_0, -+ HDMI_ACR_CTS_44); -+ -+ dm_write_reg(hw_ctx->ctx, addr, value); -+ } -+ -+ /* HDMI_ACR_44_1__HDMI_ACR_N_44_MASK */ -+ { -+ addr = mmHDMI_ACR_44_1 + engine_offset[engine_id]; -+ -+ value = dm_read_reg(hw_ctx->ctx, addr); -+ set_reg_field_value(value, audio_clock_info.n_44khz, -+ HDMI_ACR_44_1, -+ HDMI_ACR_N_44); -+ -+ dm_write_reg(hw_ctx->ctx, addr, value); -+ } -+ -+ /* HDMI_ACR_48_0__HDMI_ACR_CTS_48_MASK */ -+ { -+ addr = mmHDMI_ACR_48_0 + engine_offset[engine_id]; -+ -+ value = dm_read_reg(hw_ctx->ctx, addr); -+ set_reg_field_value(value, audio_clock_info.cts_48khz, -+ HDMI_ACR_48_0, -+ HDMI_ACR_CTS_48); -+ -+ dm_write_reg(hw_ctx->ctx, addr, value); -+ } -+ -+ /* HDMI_ACR_48_1__HDMI_ACR_N_48_MASK */ -+ { -+ addr = mmHDMI_ACR_48_1 + engine_offset[engine_id]; -+ -+ value = dm_read_reg(hw_ctx->ctx, addr); -+ set_reg_field_value(value, audio_clock_info.n_48khz, -+ HDMI_ACR_48_1, -+ HDMI_ACR_N_48); -+ -+ dm_write_reg(hw_ctx->ctx, addr, value); -+ } -+ -+ /* Video driver cannot know in advance which sample rate will -+ be used by HD Audio driver -+ HDMI_ACR_PACKET_CONTROL__HDMI_ACR_N_MULTIPLE field is -+ programmed below in interruppt callback */ -+ } /* if */ -+ -+ /* AFMT_60958_0__AFMT_60958_CS_CHANNEL_NUMBER_L_MASK & -+ AFMT_60958_0__AFMT_60958_CS_CLOCK_ACCURACY_MASK */ -+ { -+ addr = mmAFMT_60958_0 + engine_offset[engine_id]; -+ -+ value = dm_read_reg(hw_ctx->ctx, addr); -+ set_reg_field_value(value, 1, -+ AFMT_60958_0, -+ AFMT_60958_CS_CHANNEL_NUMBER_L); -+ -+ /*HW default */ -+ set_reg_field_value(value, 0, -+ AFMT_60958_0, -+ AFMT_60958_CS_CLOCK_ACCURACY); -+ -+ dm_write_reg(hw_ctx->ctx, addr, value); -+ } -+ -+ /* AFMT_60958_1 AFMT_60958_CS_CHALNNEL_NUMBER_R */ -+ { -+ addr = mmAFMT_60958_1 + engine_offset[engine_id]; -+ -+ value = dm_read_reg(hw_ctx->ctx, addr); -+ set_reg_field_value(value, 2, -+ AFMT_60958_1, -+ AFMT_60958_CS_CHANNEL_NUMBER_R); -+ -+ dm_write_reg(hw_ctx->ctx, addr, value); -+ } -+ -+ /*AFMT_60958_2 now keep this settings until -+ * Programming guide comes out*/ -+ { -+ addr = mmAFMT_60958_2 + engine_offset[engine_id]; -+ -+ value = dm_read_reg(hw_ctx->ctx, addr); -+ set_reg_field_value(value, 3, -+ AFMT_60958_2, -+ AFMT_60958_CS_CHANNEL_NUMBER_2); -+ -+ set_reg_field_value(value, 4, -+ AFMT_60958_2, -+ AFMT_60958_CS_CHANNEL_NUMBER_3); -+ -+ set_reg_field_value(value, 5, -+ AFMT_60958_2, -+ AFMT_60958_CS_CHANNEL_NUMBER_4); -+ -+ set_reg_field_value(value, 6, -+ AFMT_60958_2, -+ AFMT_60958_CS_CHANNEL_NUMBER_5); -+ -+ set_reg_field_value(value, 7, -+ AFMT_60958_2, -+ AFMT_60958_CS_CHANNEL_NUMBER_6); -+ -+ set_reg_field_value(value, 8, -+ AFMT_60958_2, -+ AFMT_60958_CS_CHANNEL_NUMBER_7); -+ -+ dm_write_reg(hw_ctx->ctx, addr, value); -+ } -+} -+ -+ /* setup DP audio */ -+static void setup_dp_audio( -+ const struct hw_ctx_audio *hw_ctx, -+ enum engine_id engine_id) -+{ -+ /* --- DP Audio packet configurations --- */ -+ uint32_t addr = 0; -+ uint32_t value = 0; -+ -+ /* ATP Configuration */ -+ { -+ addr = mmDP_SEC_AUD_N + engine_offset[engine_id]; -+ -+ set_reg_field_value(value, -+ DP_SEC_AUD_N__DP_SEC_AUD_N__DEFAULT, -+ DP_SEC_AUD_N, -+ DP_SEC_AUD_N); -+ dm_write_reg(hw_ctx->ctx, addr, value); -+ } -+ -+ /* Async/auto-calc timestamp mode */ -+ { -+ addr = mmDP_SEC_TIMESTAMP + -+ engine_offset[engine_id]; -+ -+ value = 0; -+ -+ set_reg_field_value(value, -+ DP_SEC_TIMESTAMP__DP_SEC_TIMESTAMP_MODE__AUTO_CALC, -+ DP_SEC_TIMESTAMP, -+ DP_SEC_TIMESTAMP_MODE); -+ -+ dm_write_reg(hw_ctx->ctx, addr, value); -+ } -+ -+ /* --- The following are the registers -+ * copied from the SetupHDMI --- */ -+ -+ /* AFMT_AUDIO_PACKET_CONTROL */ -+ { -+ addr = mmAFMT_AUDIO_PACKET_CONTROL + -+ engine_offset[engine_id]; -+ -+ value = 0; -+ -+ value = dm_read_reg(hw_ctx->ctx, addr); -+ set_reg_field_value(value, -+ 1, -+ AFMT_AUDIO_PACKET_CONTROL, -+ AFMT_60958_CS_UPDATE); -+ -+ dm_write_reg(hw_ctx->ctx, addr, value); -+ } -+ -+ /* AFMT_AUDIO_PACKET_CONTROL2 */ -+ { -+ addr = -+ mmAFMT_AUDIO_PACKET_CONTROL2 + engine_offset[engine_id]; -+ -+ value = 0; -+ -+ value = dm_read_reg(hw_ctx->ctx, addr); -+ set_reg_field_value(value, -+ 0, -+ AFMT_AUDIO_PACKET_CONTROL2, -+ AFMT_AUDIO_LAYOUT_OVRD); -+ -+ set_reg_field_value(value, -+ 0, -+ AFMT_AUDIO_PACKET_CONTROL2, -+ AFMT_60958_OSF_OVRD); -+ -+ dm_write_reg(hw_ctx->ctx, addr, value); -+ } -+ -+ /* AFMT_INFOFRAME_CONTROL0 */ -+ { -+ addr = -+ mmAFMT_INFOFRAME_CONTROL0 + engine_offset[engine_id]; -+ -+ value = 0; -+ -+ value = dm_read_reg(hw_ctx->ctx, addr); -+ -+ set_reg_field_value(value, -+ 1, -+ AFMT_INFOFRAME_CONTROL0, -+ AFMT_AUDIO_INFO_UPDATE); -+ -+ dm_write_reg(hw_ctx->ctx, addr, value); -+ } -+ -+ /* AFMT_60958_0__AFMT_60958_CS_CLOCK_ACCURACY_MASK */ -+ { -+ addr = mmAFMT_60958_0 + engine_offset[engine_id]; -+ -+ value = 0; -+ -+ value = dm_read_reg(hw_ctx->ctx, addr); -+ set_reg_field_value(value, -+ 0, -+ AFMT_60958_0, -+ AFMT_60958_CS_CLOCK_ACCURACY); -+ -+ dm_write_reg(hw_ctx->ctx, addr, value); -+ } -+} -+ -+ /* setup VCE audio */ -+static void setup_vce_audio( -+ const struct hw_ctx_audio *hw_ctx) -+{ -+ struct dc_context *ctx = hw_ctx->ctx; -+ -+ NOT_IMPLEMENTED(); -+ -+ /*TODO: -+ const uint32_t addr = mmDOUT_DCE_VCE_CONTROL; -+ uint32_t value = 0; -+ -+ value = dal_read_reg(hw_ctx->ctx, -+ addr); -+ -+ set_reg_field_value(value, -+ FROM_BASE(hw_ctx)->azalia_stream_id - 1, -+ DOUT_DCE_VCE_CONTROL, -+ DC_VCE_AUDIO_STREAM_SELECT); -+ -+ dal_write_reg(hw_ctx->ctx, -+ addr, value);*/ -+} -+ -+static void enable_afmt_clock( -+ const struct hw_ctx_audio *hw_ctx, -+ enum engine_id engine_id, -+ bool enable_flag) -+{ -+ uint32_t engine_offs = engine_offset[engine_id]; -+ uint32_t value; -+ uint32_t count = 0; -+ uint32_t enable = enable_flag ? 1:0; -+ -+ /* Enable Audio packets*/ -+ value = dm_read_reg(hw_ctx->ctx, mmAFMT_CNTL + engine_offs); -+ -+ /*enable AFMT clock*/ -+ set_reg_field_value(value, enable, -+ AFMT_CNTL, AFMT_AUDIO_CLOCK_EN); -+ dm_write_reg(hw_ctx->ctx, mmAFMT_CNTL + engine_offs, value); -+ -+ /*wait for AFMT clock to turn on, -+ * the expectation is that this -+ * should complete in 1-2 reads) -+ */ -+ do { -+ /* Wait for 1us between subsequent register reads.*/ -+ udelay(1); -+ value = dm_read_reg(hw_ctx->ctx, -+ mmAFMT_CNTL + engine_offs); -+ } while (get_reg_field_value(value, -+ AFMT_CNTL, AFMT_AUDIO_CLOCK_ON) != -+ enable && count++ < 10); -+} -+ -+/* enable Azalia audio */ -+static void enable_azalia_audio( -+ const struct hw_ctx_audio *hw_ctx, -+ enum engine_id engine_id) -+{ -+ uint32_t value; -+ -+ value = read_indirect_azalia_reg( -+ hw_ctx, -+ ixAZALIA_F0_CODEC_PIN_CONTROL_HOT_PLUG_CONTROL); -+ -+ if (get_reg_field_value(value, -+ AZALIA_F0_CODEC_PIN_CONTROL_HOT_PLUG_CONTROL, -+ AUDIO_ENABLED) != 1) -+ set_reg_field_value(value, 1, -+ AZALIA_F0_CODEC_PIN_CONTROL_HOT_PLUG_CONTROL, -+ AUDIO_ENABLED); -+ -+ write_indirect_azalia_reg( -+ hw_ctx, -+ ixAZALIA_F0_CODEC_PIN_CONTROL_HOT_PLUG_CONTROL, -+ value); -+} -+ -+/* disable Azalia audio */ -+static void disable_azalia_audio( -+ const struct hw_ctx_audio *hw_ctx, -+ enum engine_id engine_id) -+{ -+ uint32_t value; -+ -+ value = read_indirect_azalia_reg( -+ hw_ctx, -+ ixAZALIA_F0_CODEC_PIN_CONTROL_HOT_PLUG_CONTROL); -+ -+ set_reg_field_value(value, 0, -+ AZALIA_F0_CODEC_PIN_CONTROL_HOT_PLUG_CONTROL, -+ AUDIO_ENABLED); -+ -+ write_indirect_azalia_reg( -+ hw_ctx, -+ ixAZALIA_F0_CODEC_PIN_CONTROL_HOT_PLUG_CONTROL, -+ value); -+} -+ -+/* enable DP audio */ -+static void enable_dp_audio( -+ const struct hw_ctx_audio *hw_ctx, -+ enum engine_id engine_id) -+{ -+ const uint32_t addr = mmDP_SEC_CNTL + engine_offset[engine_id]; -+ -+ uint32_t value; -+ -+ /* Enable Audio packets */ -+ value = dm_read_reg(hw_ctx->ctx, addr); -+ set_reg_field_value(value, 1, -+ DP_SEC_CNTL, -+ DP_SEC_ASP_ENABLE); -+ -+ dm_write_reg(hw_ctx->ctx, addr, value); -+ -+ /* Program the ATP and AIP next */ -+ set_reg_field_value(value, 1, -+ DP_SEC_CNTL, -+ DP_SEC_ATP_ENABLE); -+ -+ set_reg_field_value(value, 1, -+ DP_SEC_CNTL, -+ DP_SEC_AIP_ENABLE); -+ -+ dm_write_reg(hw_ctx->ctx, addr, value); -+ -+ /* Program STREAM_ENABLE after all the other enables. */ -+ set_reg_field_value(value, 1, -+ DP_SEC_CNTL, -+ DP_SEC_STREAM_ENABLE); -+ -+ dm_write_reg(hw_ctx->ctx, addr, value); -+} -+ -+/* disable DP audio */ -+static void disable_dp_audio( -+ const struct hw_ctx_audio *hw_ctx, -+ enum engine_id engine_id) -+{ -+ const uint32_t addr = mmDP_SEC_CNTL + engine_offset[engine_id]; -+ -+ uint32_t value; -+ -+ /* Disable Audio packets */ -+ value = dm_read_reg(hw_ctx->ctx, addr); -+ -+ set_reg_field_value(value, 0, -+ DP_SEC_CNTL, -+ DP_SEC_ASP_ENABLE); -+ -+ set_reg_field_value(value, 0, -+ DP_SEC_CNTL, -+ DP_SEC_ATP_ENABLE); -+ -+ set_reg_field_value(value, 0, -+ DP_SEC_CNTL, -+ DP_SEC_AIP_ENABLE); -+ -+ set_reg_field_value(value, 0, -+ DP_SEC_CNTL, -+ DP_SEC_ACM_ENABLE); -+ -+ set_reg_field_value(value, 0, -+ DP_SEC_CNTL, -+ DP_SEC_STREAM_ENABLE); -+ -+ /* This register shared with encoder info frame. Therefore we need to -+ keep master enabled if at least on of the fields is not 0 */ -+ if (value != 0) -+ set_reg_field_value(value, 1, -+ DP_SEC_CNTL, -+ DP_SEC_STREAM_ENABLE); -+ -+ dm_write_reg(hw_ctx->ctx, addr, value); -+} -+ -+static void configure_azalia( -+ const struct hw_ctx_audio *hw_ctx, -+ enum signal_type signal, -+ const struct audio_crtc_info *crtc_info, -+ const struct audio_info *audio_info) -+{ -+ uint32_t speakers = audio_info->flags.info.ALLSPEAKERS; -+ uint32_t value; -+ uint32_t field = 0; -+ enum audio_format_code audio_format_code; -+ uint32_t format_index; -+ uint32_t index; -+ bool is_ac3_supported = false; -+ bool is_audio_format_supported = false; -+ union audio_sample_rates sample_rate; -+ uint32_t strlen = 0; -+ -+ /* Speaker Allocation */ -+ /* -+ uint32_t value; -+ uint32_t field = 0;*/ -+ value = read_indirect_azalia_reg( -+ hw_ctx, -+ ixAZALIA_F0_CODEC_PIN_CONTROL_CHANNEL_SPEAKER); -+ -+ set_reg_field_value(value, -+ speakers, -+ AZALIA_F0_CODEC_PIN_CONTROL_CHANNEL_SPEAKER, -+ SPEAKER_ALLOCATION); -+ -+ /* LFE_PLAYBACK_LEVEL = LFEPBL -+ * LFEPBL = 0 : Unknown or refer to other information -+ * LFEPBL = 1 : 0dB playback -+ * LFEPBL = 2 : +10dB playback -+ * LFE_BL = 3 : Reserved -+ */ -+ set_reg_field_value(value, -+ 0, -+ AZALIA_F0_CODEC_PIN_CONTROL_CHANNEL_SPEAKER, -+ LFE_PLAYBACK_LEVEL); -+ -+ set_reg_field_value(value, -+ 0, -+ AZALIA_F0_CODEC_PIN_CONTROL_CHANNEL_SPEAKER, -+ HDMI_CONNECTION); -+ -+ set_reg_field_value(value, -+ 0, -+ AZALIA_F0_CODEC_PIN_CONTROL_CHANNEL_SPEAKER, -+ DP_CONNECTION); -+ -+ field = get_reg_field_value(value, -+ AZALIA_F0_CODEC_PIN_CONTROL_CHANNEL_SPEAKER, -+ EXTRA_CONNECTION_INFO); -+ -+ field &= ~0x1; -+ -+ set_reg_field_value(value, -+ field, -+ AZALIA_F0_CODEC_PIN_CONTROL_CHANNEL_SPEAKER, -+ EXTRA_CONNECTION_INFO); -+ -+ /* set audio for output signal */ -+ switch (signal) { -+ case SIGNAL_TYPE_HDMI_TYPE_A: -+ set_reg_field_value(value, -+ 1, -+ AZALIA_F0_CODEC_PIN_CONTROL_CHANNEL_SPEAKER, -+ HDMI_CONNECTION); -+ -+ break; -+ case SIGNAL_TYPE_WIRELESS: { -+ /*LSB used for "is wireless" flag */ -+ field = 0; -+ field = get_reg_field_value(value, -+ AZALIA_F0_CODEC_PIN_CONTROL_CHANNEL_SPEAKER, -+ EXTRA_CONNECTION_INFO); -+ field |= 0x1; -+ set_reg_field_value(value, -+ field, -+ AZALIA_F0_CODEC_PIN_CONTROL_CHANNEL_SPEAKER, -+ EXTRA_CONNECTION_INFO); -+ -+ set_reg_field_value(value, -+ 1, -+ AZALIA_F0_CODEC_PIN_CONTROL_CHANNEL_SPEAKER, -+ HDMI_CONNECTION); -+ -+ } -+ break; -+ case SIGNAL_TYPE_EDP: -+ case SIGNAL_TYPE_DISPLAY_PORT: -+ case SIGNAL_TYPE_DISPLAY_PORT_MST: -+ set_reg_field_value(value, -+ 1, -+ AZALIA_F0_CODEC_PIN_CONTROL_CHANNEL_SPEAKER, -+ DP_CONNECTION); -+ -+ break; -+ default: -+ break; -+ } -+ -+ write_indirect_azalia_reg( -+ hw_ctx, -+ ixAZALIA_F0_CODEC_PIN_CONTROL_CHANNEL_SPEAKER, -+ value); -+ -+ /* Wireless Display identification */ -+ value = read_indirect_azalia_reg( -+ hw_ctx, -+ ixAZALIA_F0_CODEC_PIN_CONTROL_WIRELESS_DISPLAY_IDENTIFICATION); -+ -+ set_reg_field_value(value, -+ signal == SIGNAL_TYPE_WIRELESS ? 1 : 0, -+ AZALIA_F0_CODEC_PIN_CONTROL_WIRELESS_DISPLAY_IDENTIFICATION, -+ WIRELESS_DISPLAY_IDENTIFICATION); -+ -+ write_indirect_azalia_reg( -+ hw_ctx, -+ ixAZALIA_F0_CODEC_PIN_CONTROL_WIRELESS_DISPLAY_IDENTIFICATION, -+ value); -+ -+ /* Audio Descriptors */ -+ /* pass through all formats */ -+ for (format_index = 0; format_index < AUDIO_FORMAT_CODE_COUNT; -+ format_index++) { -+ audio_format_code = -+ (AUDIO_FORMAT_CODE_FIRST + format_index); -+ -+ /* those are unsupported, skip programming */ -+ if (audio_format_code == AUDIO_FORMAT_CODE_1BITAUDIO || -+ audio_format_code == AUDIO_FORMAT_CODE_DST) -+ continue; -+ -+ value = 0; -+ -+ /* check if supported */ -+ is_audio_format_supported = -+ dal_audio_hw_ctx_is_audio_format_supported( -+ hw_ctx, -+ audio_info, -+ audio_format_code, &index); -+ -+ if (is_audio_format_supported) { -+ const struct audio_mode *audio_mode = -+ &audio_info->modes[index]; -+ union audio_sample_rates sample_rates = -+ audio_mode->sample_rates; -+ uint8_t byte2 = audio_mode->max_bit_rate; -+ -+ /* adjust specific properties */ -+ switch (audio_format_code) { -+ case AUDIO_FORMAT_CODE_LINEARPCM: { -+ dal_hw_ctx_audio_check_audio_bandwidth( -+ hw_ctx, -+ crtc_info, -+ audio_mode->channel_count, -+ signal, -+ &sample_rates); -+ -+ byte2 = audio_mode->sample_size; -+ -+ set_reg_field_value(value, -+ sample_rates.all, -+ AZALIA_F0_CODEC_PIN_CONTROL_AUDIO_DESCRIPTOR0, -+ SUPPORTED_FREQUENCIES_STEREO); -+ -+ } -+ break; -+ case AUDIO_FORMAT_CODE_AC3: -+ is_ac3_supported = true; -+ break; -+ case AUDIO_FORMAT_CODE_DOLBYDIGITALPLUS: -+ case AUDIO_FORMAT_CODE_DTS_HD: -+ case AUDIO_FORMAT_CODE_MAT_MLP: -+ case AUDIO_FORMAT_CODE_DST: -+ case AUDIO_FORMAT_CODE_WMAPRO: -+ byte2 = audio_mode->vendor_specific; -+ break; -+ default: -+ break; -+ } -+ -+ /* fill audio format data */ -+ set_reg_field_value(value, -+ audio_mode->channel_count - 1, -+ AZALIA_F0_CODEC_PIN_CONTROL_AUDIO_DESCRIPTOR0, -+ MAX_CHANNELS); -+ -+ set_reg_field_value(value, -+ sample_rates.all, -+ AZALIA_F0_CODEC_PIN_CONTROL_AUDIO_DESCRIPTOR0, -+ SUPPORTED_FREQUENCIES); -+ -+ set_reg_field_value(value, -+ byte2, -+ AZALIA_F0_CODEC_PIN_CONTROL_AUDIO_DESCRIPTOR0, -+ DESCRIPTOR_BYTE_2); -+ -+ } /* if */ -+ -+ write_indirect_azalia_reg( -+ hw_ctx, -+ ixAZALIA_F0_CODEC_PIN_CONTROL_AUDIO_DESCRIPTOR0 + -+ format_index, -+ value); -+ } /* for */ -+ -+ if (is_ac3_supported) -+ dm_write_reg(hw_ctx->ctx, -+ mmAZALIA_F0_CODEC_FUNCTION_PARAMETER_STREAM_FORMATS, -+ 0x05); -+ -+ /* check for 192khz/8-Ch support for HBR requirements */ -+ sample_rate.all = 0; -+ sample_rate.rate.RATE_192 = 1; -+ dal_hw_ctx_audio_check_audio_bandwidth( -+ hw_ctx, -+ crtc_info, -+ 8, -+ signal, -+ &sample_rate); -+ -+ set_high_bit_rate_capable(hw_ctx, sample_rate.rate.RATE_192); -+ -+ /* Audio and Video Lipsync */ -+ set_video_latency(hw_ctx, audio_info->video_latency); -+ set_audio_latency(hw_ctx, audio_info->audio_latency); -+ -+ value = 0; -+ set_reg_field_value(value, audio_info->manufacture_id, -+ AZALIA_F0_CODEC_PIN_CONTROL_SINK_INFO0, -+ MANUFACTURER_ID); -+ -+ set_reg_field_value(value, audio_info->product_id, -+ AZALIA_F0_CODEC_PIN_CONTROL_SINK_INFO0, -+ PRODUCT_ID); -+ -+ write_indirect_azalia_reg( -+ hw_ctx, -+ ixAZALIA_F0_CODEC_PIN_CONTROL_SINK_INFO0, -+ value); -+ -+ value = 0; -+ -+ /*get display name string length */ -+ while (audio_info->display_name[strlen++] != '\0') { -+ if (strlen >= -+ MAX_HW_AUDIO_INFO_DISPLAY_NAME_SIZE_IN_CHARS) -+ break; -+ } -+ set_reg_field_value(value, strlen, -+ AZALIA_F0_CODEC_PIN_CONTROL_SINK_INFO1, -+ SINK_DESCRIPTION_LEN); -+ -+ write_indirect_azalia_reg( -+ hw_ctx, -+ ixAZALIA_F0_CODEC_PIN_CONTROL_SINK_INFO1, -+ value); -+ -+ /* -+ *write the port ID: -+ *PORT_ID0 = display index -+ *PORT_ID1 = 16bit BDF -+ *(format MSB->LSB: 8bit Bus, 5bit Device, 3bit Function) -+ */ -+ -+ value = 0; -+ -+ set_reg_field_value(value, audio_info->port_id[0], -+ AZALIA_F0_CODEC_PIN_CONTROL_SINK_INFO2, -+ PORT_ID0); -+ -+ write_indirect_azalia_reg( -+ hw_ctx, -+ ixAZALIA_F0_CODEC_PIN_CONTROL_SINK_INFO2, -+ value); -+ -+ value = 0; -+ set_reg_field_value(value, audio_info->port_id[1], -+ AZALIA_F0_CODEC_PIN_CONTROL_SINK_INFO3, -+ PORT_ID1); -+ -+ write_indirect_azalia_reg( -+ hw_ctx, -+ ixAZALIA_F0_CODEC_PIN_CONTROL_SINK_INFO3, -+ value); -+ -+ /*write the 18 char monitor string */ -+ -+ value = 0; -+ set_reg_field_value(value, audio_info->display_name[0], -+ AZALIA_F0_CODEC_PIN_CONTROL_SINK_INFO4, -+ DESCRIPTION0); -+ -+ set_reg_field_value(value, audio_info->display_name[1], -+ AZALIA_F0_CODEC_PIN_CONTROL_SINK_INFO4, -+ DESCRIPTION1); -+ -+ set_reg_field_value(value, audio_info->display_name[2], -+ AZALIA_F0_CODEC_PIN_CONTROL_SINK_INFO4, -+ DESCRIPTION2); -+ -+ set_reg_field_value(value, audio_info->display_name[3], -+ AZALIA_F0_CODEC_PIN_CONTROL_SINK_INFO4, -+ DESCRIPTION3); -+ -+ write_indirect_azalia_reg( -+ hw_ctx, -+ ixAZALIA_F0_CODEC_PIN_CONTROL_SINK_INFO4, -+ value); -+ -+ value = 0; -+ set_reg_field_value(value, audio_info->display_name[4], -+ AZALIA_F0_CODEC_PIN_CONTROL_SINK_INFO5, -+ DESCRIPTION4); -+ -+ set_reg_field_value(value, audio_info->display_name[5], -+ AZALIA_F0_CODEC_PIN_CONTROL_SINK_INFO5, -+ DESCRIPTION5); -+ -+ set_reg_field_value(value, audio_info->display_name[6], -+ AZALIA_F0_CODEC_PIN_CONTROL_SINK_INFO5, -+ DESCRIPTION6); -+ -+ set_reg_field_value(value, audio_info->display_name[7], -+ AZALIA_F0_CODEC_PIN_CONTROL_SINK_INFO5, -+ DESCRIPTION7); -+ -+ write_indirect_azalia_reg( -+ hw_ctx, -+ ixAZALIA_F0_CODEC_PIN_CONTROL_SINK_INFO5, -+ value); -+ -+ value = 0; -+ set_reg_field_value(value, audio_info->display_name[8], -+ AZALIA_F0_CODEC_PIN_CONTROL_SINK_INFO6, -+ DESCRIPTION8); -+ -+ set_reg_field_value(value, audio_info->display_name[9], -+ AZALIA_F0_CODEC_PIN_CONTROL_SINK_INFO6, -+ DESCRIPTION9); -+ -+ set_reg_field_value(value, audio_info->display_name[10], -+ AZALIA_F0_CODEC_PIN_CONTROL_SINK_INFO6, -+ DESCRIPTION10); -+ -+ set_reg_field_value(value, audio_info->display_name[11], -+ AZALIA_F0_CODEC_PIN_CONTROL_SINK_INFO6, -+ DESCRIPTION11); -+ -+ write_indirect_azalia_reg( -+ hw_ctx, -+ ixAZALIA_F0_CODEC_PIN_CONTROL_SINK_INFO6, -+ value); -+ -+ value = 0; -+ set_reg_field_value(value, audio_info->display_name[12], -+ AZALIA_F0_CODEC_PIN_CONTROL_SINK_INFO7, -+ DESCRIPTION12); -+ -+ set_reg_field_value(value, audio_info->display_name[13], -+ AZALIA_F0_CODEC_PIN_CONTROL_SINK_INFO7, -+ DESCRIPTION13); -+ -+ set_reg_field_value(value, audio_info->display_name[14], -+ AZALIA_F0_CODEC_PIN_CONTROL_SINK_INFO7, -+ DESCRIPTION14); -+ -+ set_reg_field_value(value, audio_info->display_name[15], -+ AZALIA_F0_CODEC_PIN_CONTROL_SINK_INFO7, -+ DESCRIPTION15); -+ -+ write_indirect_azalia_reg( -+ hw_ctx, -+ ixAZALIA_F0_CODEC_PIN_CONTROL_SINK_INFO7, -+ value); -+ -+ value = 0; -+ set_reg_field_value(value, audio_info->display_name[16], -+ AZALIA_F0_CODEC_PIN_CONTROL_SINK_INFO8, -+ DESCRIPTION16); -+ -+ set_reg_field_value(value, audio_info->display_name[17], -+ AZALIA_F0_CODEC_PIN_CONTROL_SINK_INFO8, -+ DESCRIPTION17); -+ -+ write_indirect_azalia_reg( -+ hw_ctx, -+ ixAZALIA_F0_CODEC_PIN_CONTROL_SINK_INFO8, -+ value); -+ -+} -+ -+/* setup Azalia HW block */ -+static void setup_azalia( -+ const struct hw_ctx_audio *hw_ctx, -+ enum engine_id engine_id, -+ enum signal_type signal, -+ const struct audio_crtc_info *crtc_info, -+ const struct audio_pll_info *pll_info, -+ const struct audio_info *audio_info) -+{ -+ uint32_t speakers = 0; -+ uint32_t channels = 0; -+ -+ if (audio_info == NULL) -+ /* This should not happen.it does so we don't get BSOD*/ -+ return; -+ -+ speakers = audio_info->flags.info.ALLSPEAKERS; -+ channels = dal_audio_hw_ctx_speakers_to_channels( -+ hw_ctx, -+ audio_info->flags.speaker_flags).all; -+ -+ /* setup the audio stream source select (audio -> dig mapping) */ -+ { -+ const uint32_t addr = -+ mmAFMT_AUDIO_SRC_CONTROL + engine_offset[engine_id]; -+ -+ uint32_t value = 0; -+ /*convert one-based index to zero-based */ -+ set_reg_field_value(value, -+ FROM_BASE(hw_ctx)->azalia_stream_id - 1, -+ AFMT_AUDIO_SRC_CONTROL, -+ AFMT_AUDIO_SRC_SELECT); -+ -+ dm_write_reg(hw_ctx->ctx, addr, value); -+ } -+ -+ /* Channel allocation */ -+ { -+ const uint32_t addr = -+ mmAFMT_AUDIO_PACKET_CONTROL2 + engine_offset[engine_id]; -+ uint32_t value = dm_read_reg(hw_ctx->ctx, addr); -+ -+ set_reg_field_value(value, -+ channels, -+ AFMT_AUDIO_PACKET_CONTROL2, -+ AFMT_AUDIO_CHANNEL_ENABLE); -+ -+ dm_write_reg(hw_ctx->ctx, addr, value); -+ } -+ -+ configure_azalia(hw_ctx, signal, crtc_info, audio_info); -+} -+ -+/* unmute audio */ -+static void unmute_azalia_audio( -+ const struct hw_ctx_audio *hw_ctx, -+ enum engine_id engine_id) -+{ -+ const uint32_t addr = mmAFMT_AUDIO_PACKET_CONTROL + -+ engine_offset[engine_id]; -+ -+ uint32_t value = 0; -+ -+ value = dm_read_reg(hw_ctx->ctx, addr); -+ -+ set_reg_field_value(value, 1, -+ AFMT_AUDIO_PACKET_CONTROL, AFMT_AUDIO_SAMPLE_SEND); -+ -+ dm_write_reg(hw_ctx->ctx, addr, value); -+} -+ -+/* mute audio */ -+static void mute_azalia_audio( -+ const struct hw_ctx_audio *hw_ctx, -+ enum engine_id engine_id) -+{ -+ const uint32_t addr = mmAFMT_AUDIO_PACKET_CONTROL + -+ engine_offset[engine_id]; -+ -+ uint32_t value = 0; -+ -+ value = dm_read_reg(hw_ctx->ctx, addr); -+ -+ set_reg_field_value(value, 0, -+ AFMT_AUDIO_PACKET_CONTROL, AFMT_AUDIO_SAMPLE_SEND); -+ -+ dm_write_reg(hw_ctx->ctx, addr, value); -+} -+ -+/* enable channel splitting mapping */ -+static void setup_channel_splitting_mapping( -+ const struct hw_ctx_audio *hw_ctx, -+ enum engine_id engine_id, -+ enum signal_type signal, -+ const struct audio_channel_associate_info *audio_mapping, -+ bool enable) -+{ -+ uint32_t value = 0; -+ -+ if ((audio_mapping == NULL || audio_mapping->u32all == 0) && enable) -+ return; -+ -+ value = audio_mapping->u32all; -+ -+ if (enable == false) -+ /*0xFFFFFFFF;*/ -+ value = MULTI_CHANNEL_SPLIT_NO_ASSO_INFO; -+ -+ write_indirect_azalia_reg( -+ hw_ctx, -+ ixAZALIA_F0_CODEC_PIN_ASSOCIATION_INFO, -+ value); -+} -+ -+/* get current channel spliting */ -+static bool get_channel_splitting_mapping( -+ const struct hw_ctx_audio *hw_ctx, -+ enum engine_id engine_id, -+ struct audio_channel_associate_info *audio_mapping) -+{ -+ uint32_t value = 0; -+ -+ if (audio_mapping == NULL) -+ return false; -+ -+ value = read_indirect_azalia_reg( -+ hw_ctx, -+ ixAZALIA_F0_CODEC_PIN_ASSOCIATION_INFO); -+ -+ /*0xFFFFFFFF*/ -+ if (get_reg_field_value(value, -+ AZALIA_F0_CODEC_PIN_ASSOCIATION_INFO, -+ ASSOCIATION_INFO) != -+ MULTI_CHANNEL_SPLIT_NO_ASSO_INFO) { -+ uint32_t multi_channel01_enable = 0; -+ uint32_t multi_channel23_enable = 0; -+ uint32_t multi_channel45_enable = 0; -+ uint32_t multi_channel67_enable = 0; -+ /* get the one we set.*/ -+ audio_mapping->u32all = value; -+ -+ /* check each enable status*/ -+ value = read_indirect_azalia_reg( -+ hw_ctx, -+ ixAZALIA_F0_CODEC_PIN_CONTROL_MULTICHANNEL_ENABLE); -+ -+ multi_channel01_enable = get_reg_field_value(value, -+ AZALIA_F0_CODEC_PIN_CONTROL_MULTICHANNEL_ENABLE, -+ MULTICHANNEL01_ENABLE); -+ -+ multi_channel23_enable = get_reg_field_value(value, -+ AZALIA_F0_CODEC_PIN_CONTROL_MULTICHANNEL_ENABLE, -+ MULTICHANNEL23_ENABLE); -+ -+ multi_channel45_enable = get_reg_field_value(value, -+ AZALIA_F0_CODEC_PIN_CONTROL_MULTICHANNEL_ENABLE, -+ MULTICHANNEL45_ENABLE); -+ -+ multi_channel67_enable = get_reg_field_value(value, -+ AZALIA_F0_CODEC_PIN_CONTROL_MULTICHANNEL_ENABLE, -+ MULTICHANNEL67_ENABLE); -+ -+ if (multi_channel01_enable == 0 && -+ multi_channel23_enable == 0 && -+ multi_channel45_enable == 0 && -+ multi_channel67_enable == 0) -+ dal_logger_write(hw_ctx->ctx->logger, -+ LOG_MAJOR_HW_TRACE, -+ LOG_MINOR_COMPONENT_AUDIO, -+ "Audio driver did not enable multi-channel\n"); -+ -+ return true; -+ } -+ -+ return false; -+} -+ -+/* set the payload value for the unsolicited response */ -+static void set_unsolicited_response_payload( -+ const struct hw_ctx_audio *hw_ctx, -+ enum audio_payload payload) -+{ -+ /* set the payload value for the unsolicited response -+ Jack presence is not required to be enabled */ -+ uint32_t value = 0; -+ -+ value = read_indirect_azalia_reg( -+ hw_ctx, -+ ixAZALIA_F0_CODEC_PIN_CONTROL_UNSOLICITED_RESPONSE_FORCE); -+ -+ set_reg_field_value(value, payload, -+ AZALIA_F0_CODEC_PIN_CONTROL_UNSOLICITED_RESPONSE_FORCE, -+ UNSOLICITED_RESPONSE_PAYLOAD); -+ -+ set_reg_field_value(value, 1, -+ AZALIA_F0_CODEC_PIN_CONTROL_UNSOLICITED_RESPONSE_FORCE, -+ UNSOLICITED_RESPONSE_FORCE); -+ -+ write_indirect_azalia_reg( -+ hw_ctx, -+ ixAZALIA_F0_CODEC_PIN_CONTROL_UNSOLICITED_RESPONSE_FORCE, -+ value); -+} -+ -+/* initialize HW state */ -+static void hw_initialize( -+ const struct hw_ctx_audio *hw_ctx) -+{ -+ uint32_t stream_id = FROM_BASE(hw_ctx)->azalia_stream_id; -+ uint32_t addr; -+ -+ /* we only need to program the following registers once, so we only do -+ it for the first audio stream.*/ -+ if (stream_id != FIRST_AUDIO_STREAM_ID) -+ return; -+ -+ /* Suport R5 - 32khz -+ * Suport R6 - 44.1khz -+ * Suport R7 - 48khz -+ */ -+ addr = mmAZALIA_F0_CODEC_FUNCTION_PARAMETER_SUPPORTED_SIZE_RATES; -+ { -+ uint32_t value; -+ -+ value = dm_read_reg(hw_ctx->ctx, addr); -+ -+ set_reg_field_value(value, 0x70, -+ AZALIA_F0_CODEC_FUNCTION_PARAMETER_SUPPORTED_SIZE_RATES, -+ AUDIO_RATE_CAPABILITIES); -+ -+ dm_write_reg(hw_ctx->ctx, addr, value); -+ } -+ -+ /*Keep alive bit to verify HW block in BU. */ -+ addr = mmAZALIA_F0_CODEC_FUNCTION_PARAMETER_POWER_STATES; -+ { -+ uint32_t value; -+ -+ value = dm_read_reg(hw_ctx->ctx, addr); -+ -+ set_reg_field_value(value, 1, -+ AZALIA_F0_CODEC_FUNCTION_PARAMETER_POWER_STATES, -+ CLKSTOP); -+ -+ set_reg_field_value(value, 1, -+ AZALIA_F0_CODEC_FUNCTION_PARAMETER_POWER_STATES, -+ EPSS); -+ dm_write_reg(hw_ctx->ctx, addr, value); -+ } -+} -+ -+/* Assign GTC group and enable GTC value embedding */ -+static void enable_gtc_embedding_with_group( -+ const struct hw_ctx_audio *hw_ctx, -+ uint32_t group_num, -+ uint32_t audio_latency) -+{ -+ /*need to replace the static number with variable */ -+ if (group_num <= 6) { -+ uint32_t value = read_indirect_azalia_reg( -+ hw_ctx, -+ ixAZALIA_F0_CODEC_CONVERTER_CONTROL_GTC_EMBEDDING); -+ -+ set_reg_field_value( -+ value, -+ group_num, -+ AZALIA_F0_CODEC_CONVERTER_CONTROL_GTC_EMBEDDING, -+ PRESENTATION_TIME_EMBEDDING_GROUP); -+ -+ set_reg_field_value( -+ value, -+ 1, -+ AZALIA_F0_CODEC_CONVERTER_CONTROL_GTC_EMBEDDING, -+ PRESENTATION_TIME_EMBEDDING_ENABLE); -+ -+ write_indirect_azalia_reg( -+ hw_ctx, -+ ixAZALIA_F0_CODEC_CONVERTER_CONTROL_GTC_EMBEDDING, -+ value); -+ -+ /*update audio latency to LIPSYNC*/ -+ set_audio_latency(hw_ctx, audio_latency); -+ } else { -+ dal_logger_write( -+ hw_ctx->ctx->logger, -+ LOG_MAJOR_HW_TRACE, -+ LOG_MINOR_COMPONENT_AUDIO, -+ "GTC group number %d is too big", -+ group_num); -+ } -+} -+ -+ /* Disable GTC value embedding */ -+static void disable_gtc_embedding( -+ const struct hw_ctx_audio *hw_ctx) -+{ -+ uint32_t value = 0; -+ -+ value = read_indirect_azalia_reg( -+ hw_ctx, -+ ixAZALIA_F0_CODEC_CONVERTER_CONTROL_GTC_EMBEDDING); -+ -+ set_reg_field_value(value, 0, -+ AZALIA_F0_CODEC_CONVERTER_CONTROL_GTC_EMBEDDING, -+ PRESENTATION_TIME_EMBEDDING_ENABLE); -+ -+ set_reg_field_value(value, 0, -+ AZALIA_F0_CODEC_CONVERTER_CONTROL_GTC_EMBEDDING, -+ PRESENTATION_TIME_EMBEDDING_GROUP); -+ -+ write_indirect_azalia_reg( -+ hw_ctx, -+ ixAZALIA_F0_CODEC_CONVERTER_CONTROL_GTC_EMBEDDING, -+ value); -+} -+ -+/* search pixel clock value for Azalia HDMI Audio */ -+static bool get_azalia_clock_info_hdmi( -+ const struct hw_ctx_audio *hw_ctx, -+ uint32_t crtc_pixel_clock_in_khz, -+ uint32_t actual_pixel_clock_in_khz, -+ struct azalia_clock_info *azalia_clock_info) -+{ -+ if (azalia_clock_info == NULL) -+ return false; -+ -+ /* audio_dto_phase= 24 * 10,000; -+ * 24MHz in [100Hz] units */ -+ azalia_clock_info->audio_dto_phase = -+ 24 * 10000; -+ -+ /* audio_dto_module = PCLKFrequency * 10,000; -+ * [khz] -> [100Hz] */ -+ azalia_clock_info->audio_dto_module = -+ actual_pixel_clock_in_khz * 10; -+ -+ return true; -+} -+ -+/* search pixel clock value for Azalia DP Audio */ -+static bool get_azalia_clock_info_dp( -+ const struct hw_ctx_audio *hw_ctx, -+ uint32_t requested_pixel_clock_in_khz, -+ const struct audio_pll_info *pll_info, -+ struct azalia_clock_info *azalia_clock_info) -+{ -+ if (pll_info == NULL || azalia_clock_info == NULL) -+ return false; -+ -+ /* Reported dpDtoSourceClockInkhz value for -+ * DCE8 already adjusted for SS, do not need any -+ * adjustment here anymore -+ */ -+ -+ /*audio_dto_phase = 24 * 10,000; -+ * 24MHz in [100Hz] units */ -+ azalia_clock_info->audio_dto_phase = 24 * 10000; -+ -+ /*audio_dto_module = dpDtoSourceClockInkhz * 10,000; -+ * [khz] ->[100Hz] */ -+ azalia_clock_info->audio_dto_module = -+ pll_info->dp_dto_source_clock_in_khz * 10; -+ -+ return true; -+} -+ -+static const struct hw_ctx_audio_funcs funcs = { -+ .destroy = destroy, -+ .setup_audio_wall_dto = -+ setup_audio_wall_dto, -+ .setup_hdmi_audio = -+ setup_hdmi_audio, -+ .setup_dp_audio = setup_dp_audio, -+ .setup_vce_audio = setup_vce_audio, -+ .enable_azalia_audio = -+ enable_azalia_audio, -+ .disable_azalia_audio = -+ disable_azalia_audio, -+ .enable_dp_audio = -+ enable_dp_audio, -+ .disable_dp_audio = -+ disable_dp_audio, -+ .setup_azalia = -+ setup_azalia, -+ .disable_az_clock_gating = NULL, -+ .unmute_azalia_audio = -+ unmute_azalia_audio, -+ .mute_azalia_audio = -+ mute_azalia_audio, -+ .setup_channel_splitting_mapping = -+ setup_channel_splitting_mapping, -+ .get_channel_splitting_mapping = -+ get_channel_splitting_mapping, -+ .set_unsolicited_response_payload = -+ set_unsolicited_response_payload, -+ .hw_initialize = -+ hw_initialize, -+ .enable_gtc_embedding_with_group = -+ enable_gtc_embedding_with_group, -+ .disable_gtc_embedding = -+ disable_gtc_embedding, -+ .get_azalia_clock_info_hdmi = -+ get_azalia_clock_info_hdmi, -+ .get_azalia_clock_info_dp = -+ get_azalia_clock_info_dp, -+ .enable_afmt_clock = enable_afmt_clock -+}; -+ -+static bool construct( -+ struct hw_ctx_audio_dce112 *hw_ctx, -+ uint8_t azalia_stream_id, -+ struct dc_context *ctx) -+{ -+ struct hw_ctx_audio *base = &hw_ctx->base; -+ -+ if (!dal_audio_construct_hw_ctx_audio(base)) -+ return false; -+ -+ base->funcs = &funcs; -+ -+ /* save audio endpoint or dig front for current dce112 audio object */ -+ hw_ctx->azalia_stream_id = azalia_stream_id; -+ hw_ctx->base.ctx = ctx; -+ -+ /* azalia audio endpoints register offsets. azalia is associated with -+ DIG front. save AUDIO register offset */ -+ switch (azalia_stream_id) { -+ case 1: { -+ hw_ctx->az_mm_reg_offsets. -+ azf0endpointx_azalia_f0_codec_endpoint_index = -+ mmAZF0ENDPOINT0_AZALIA_F0_CODEC_ENDPOINT_INDEX; -+ hw_ctx->az_mm_reg_offsets. -+ azf0endpointx_azalia_f0_codec_endpoint_data = -+ mmAZF0ENDPOINT0_AZALIA_F0_CODEC_ENDPOINT_DATA; -+ } -+ break; -+ case 2: { -+ hw_ctx->az_mm_reg_offsets. -+ azf0endpointx_azalia_f0_codec_endpoint_index = -+ mmAZF0ENDPOINT1_AZALIA_F0_CODEC_ENDPOINT_INDEX; -+ hw_ctx->az_mm_reg_offsets. -+ azf0endpointx_azalia_f0_codec_endpoint_data = -+ mmAZF0ENDPOINT1_AZALIA_F0_CODEC_ENDPOINT_DATA; -+ } -+ break; -+ case 3: { -+ hw_ctx->az_mm_reg_offsets. -+ azf0endpointx_azalia_f0_codec_endpoint_index = -+ mmAZF0ENDPOINT2_AZALIA_F0_CODEC_ENDPOINT_INDEX; -+ hw_ctx->az_mm_reg_offsets. -+ azf0endpointx_azalia_f0_codec_endpoint_data = -+ mmAZF0ENDPOINT2_AZALIA_F0_CODEC_ENDPOINT_DATA; -+ } -+ break; -+ case 4: { -+ hw_ctx->az_mm_reg_offsets. -+ azf0endpointx_azalia_f0_codec_endpoint_index = -+ mmAZF0ENDPOINT3_AZALIA_F0_CODEC_ENDPOINT_INDEX; -+ hw_ctx->az_mm_reg_offsets. -+ azf0endpointx_azalia_f0_codec_endpoint_data = -+ mmAZF0ENDPOINT3_AZALIA_F0_CODEC_ENDPOINT_DATA; -+ } -+ break; -+ default: -+ dal_logger_write( -+ hw_ctx->base.ctx->logger, -+ LOG_MAJOR_WARNING, -+ LOG_MINOR_COMPONENT_AUDIO, -+ "Invalid Azalia stream ID!"); -+ break; -+ } -+ -+ return true; -+} -+ -+/* audio_dce112 is derived from audio directly, not via dce80 */ -+struct hw_ctx_audio *dal_hw_ctx_audio_dce112_create( -+ struct dc_context *ctx, -+ uint32_t azalia_stream_id) -+{ -+ /* allocate memory for struc hw_ctx_audio_dce112 */ -+ struct hw_ctx_audio_dce112 *hw_ctx_dce112 = -+ dm_alloc(sizeof(struct hw_ctx_audio_dce112)); -+ -+ if (!hw_ctx_dce112) { -+ ASSERT_CRITICAL(hw_ctx_dce112); -+ return NULL; -+ } -+ -+ /*return pointer to hw_ctx_audio back to caller -- audio object */ -+ if (construct( -+ hw_ctx_dce112, azalia_stream_id, ctx)) -+ return &hw_ctx_dce112->base; -+ -+ dal_logger_write( -+ ctx->logger, -+ LOG_MAJOR_ERROR, -+ LOG_MINOR_COMPONENT_AUDIO, -+ "Failed to create hw_ctx_audio for DCE11\n"); -+ -+ dm_free(hw_ctx_dce112); -+ -+ return NULL; -+} -diff --git a/drivers/gpu/drm/amd/dal/dc/audio/dce112/hw_ctx_audio_dce112.h b/drivers/gpu/drm/amd/dal/dc/audio/dce112/hw_ctx_audio_dce112.h -new file mode 100644 -index 0000000..af61aad ---- /dev/null -+++ b/drivers/gpu/drm/amd/dal/dc/audio/dce112/hw_ctx_audio_dce112.h -@@ -0,0 +1,47 @@ -+/* -+ * Copyright 2012-15 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 __DAL_HW_CTX_AUDIO_DCE112_H__ -+#define __DAL_HW_CTX_AUDIO_DCE112_H__ -+ -+#include "audio/hw_ctx_audio.h" -+ -+struct hw_ctx_audio_dce112 { -+ struct hw_ctx_audio base; -+ -+ /* azalia stream id 1 based indexing, corresponding to audio GO enumId*/ -+ uint32_t azalia_stream_id; -+ -+ /* azalia stream endpoint register offsets */ -+ struct azalia_reg_offsets az_mm_reg_offsets; -+ -+ /* audio encoder block MM register offset -- associate with DIG FRONT */ -+}; -+ -+struct hw_ctx_audio *dal_hw_ctx_audio_dce112_create( -+ struct dc_context *ctx, -+ uint32_t azalia_stream_id); -+ -+#endif /* __DAL_HW_CTX_AUDIO_DCE110_H__ */ -diff --git a/drivers/gpu/drm/amd/dal/dc/bios/Makefile b/drivers/gpu/drm/amd/dal/dc/bios/Makefile -index e5c8876..9c90230 100644 ---- a/drivers/gpu/drm/amd/dal/dc/bios/Makefile -+++ b/drivers/gpu/drm/amd/dal/dc/bios/Makefile -@@ -37,3 +37,12 @@ endif - - AMD_DAL_FILES += $(AMDDALPATH)/dc/bios/dce110/command_table_helper_dce110.o - endif -+ -+ifdef CONFIG_DRM_AMD_DAL_DCE11_2 -+ccflags-y += -DLATEST_ATOM_BIOS_SUPPORT -+ifdef CONFIG_DRM_AMD_DAL_VBIOS_PRESENT -+AMD_DAL_FILES += $(AMDDALPATH)/dc/bios/dce112/bios_parser_helper_dce112.o -+endif -+ -+AMD_DAL_FILES += $(AMDDALPATH)/dc/bios/dce112/command_table_helper_dce112.o -+endif -diff --git a/drivers/gpu/drm/amd/dal/dc/bios/bios_parser_helper.c b/drivers/gpu/drm/amd/dal/dc/bios/bios_parser_helper.c -index 4e2bc90..4204798 100644 ---- a/drivers/gpu/drm/amd/dal/dc/bios/bios_parser_helper.c -+++ b/drivers/gpu/drm/amd/dal/dc/bios/bios_parser_helper.c -@@ -55,6 +55,12 @@ bool dal_bios_parser_init_bios_helper( - return true; - - #endif -+#if defined(CONFIG_DRM_AMD_DAL_DCE11_2) -+ case DCE_VERSION_11_2: -+ bp->bios_helper = dal_bios_parser_helper_dce112_get_table(); -+ return true; -+ -+#endif - default: - BREAK_TO_DEBUGGER(); - return false; -diff --git a/drivers/gpu/drm/amd/dal/dc/bios/bios_parser_helper.h b/drivers/gpu/drm/amd/dal/dc/bios/bios_parser_helper.h -index c58b9bb..b93b046 100644 ---- a/drivers/gpu/drm/amd/dal/dc/bios/bios_parser_helper.h -+++ b/drivers/gpu/drm/amd/dal/dc/bios/bios_parser_helper.h -@@ -34,6 +34,10 @@ - #include "dce110/bios_parser_helper_dce110.h" - #endif - -+#if defined(CONFIG_DRM_AMD_DAL_DCE11_2) -+#include "dce112/bios_parser_helper_dce112.h" -+#endif -+ - struct bios_parser; - - struct vbios_helper_data { -diff --git a/drivers/gpu/drm/amd/dal/dc/bios/command_table.c b/drivers/gpu/drm/amd/dal/dc/bios/command_table.c -index ccd1c7e..22524b3 100644 ---- a/drivers/gpu/drm/amd/dal/dc/bios/command_table.c -+++ b/drivers/gpu/drm/amd/dal/dc/bios/command_table.c -@@ -104,6 +104,13 @@ static enum bp_result encoder_control_digx_v3( - static enum bp_result encoder_control_digx_v4( - struct bios_parser *bp, - struct bp_encoder_control *cntl); -+ -+#ifdef LATEST_ATOM_BIOS_SUPPORT -+static enum bp_result encoder_control_digx_v5( -+ struct bios_parser *bp, -+ struct bp_encoder_control *cntl); -+#endif -+ - static void init_encoder_control_dig_v1(struct bios_parser *bp); - - static void init_dig_encoder_control(struct bios_parser *bp) -@@ -112,12 +119,19 @@ static void init_dig_encoder_control(struct bios_parser *bp) - BIOS_CMD_TABLE_PARA_REVISION(DIGxEncoderControl); - - switch (version) { -+ case 2: -+ bp->cmd_tbl.dig_encoder_control = encoder_control_digx_v3; -+ break; - case 4: - bp->cmd_tbl.dig_encoder_control = encoder_control_digx_v4; - break; -- case 2: -- bp->cmd_tbl.dig_encoder_control = encoder_control_digx_v3; -+ -+#ifdef LATEST_ATOM_BIOS_SUPPORT -+ case 5: -+ bp->cmd_tbl.dig_encoder_control = encoder_control_digx_v5; - break; -+#endif -+ - default: - init_encoder_control_dig_v1(bp); - break; -@@ -302,6 +316,66 @@ static enum bp_result encoder_control_digx_v4( - return result; - } - -+#ifdef LATEST_ATOM_BIOS_SUPPORT -+static enum bp_result encoder_control_digx_v5( -+ struct bios_parser *bp, -+ struct bp_encoder_control *cntl) -+{ -+ enum bp_result result = BP_RESULT_FAILURE; -+ ENCODER_STREAM_SETUP_PARAMETERS_V5 params = {0}; -+ -+ params.ucDigId = (uint8_t)(cntl->engine_id); -+ params.ucAction = bp->cmd_helper->encoder_action_to_atom(cntl->action); -+ -+ params.ulPixelClock = cntl->pixel_clock / 10; -+ params.ucDigMode = -+ (uint8_t)(bp->cmd_helper->encoder_mode_bp_to_atom( -+ cntl->signal, -+ cntl->enable_dp_audio)); -+ params.ucLaneNum = (uint8_t)(cntl->lanes_number); -+ -+ switch (cntl->color_depth) { -+ case COLOR_DEPTH_888: -+ params.ucBitPerColor = PANEL_8BIT_PER_COLOR; -+ break; -+ case COLOR_DEPTH_101010: -+ params.ucBitPerColor = PANEL_10BIT_PER_COLOR; -+ break; -+ case COLOR_DEPTH_121212: -+ params.ucBitPerColor = PANEL_12BIT_PER_COLOR; -+ break; -+ case COLOR_DEPTH_161616: -+ params.ucBitPerColor = PANEL_16BIT_PER_COLOR; -+ break; -+ default: -+ break; -+ } -+ -+ if (cntl->signal == SIGNAL_TYPE_HDMI_TYPE_A) -+ switch (cntl->color_depth) { -+ case COLOR_DEPTH_101010: -+ params.ulPixelClock = -+ (params.ulPixelClock * 30) / 24; -+ break; -+ case COLOR_DEPTH_121212: -+ params.ulPixelClock = -+ (params.ulPixelClock * 36) / 24; -+ break; -+ case COLOR_DEPTH_161616: -+ params.ulPixelClock = -+ (params.ulPixelClock * 48) / 24; -+ break; -+ default: -+ break; -+ } -+ -+ if (EXEC_BIOS_CMD_TABLE(DIGxEncoderControl, params)) -+ result = BP_RESULT_OK; -+ -+ return result; -+} -+#endif -+ - /******************************************************************************* - ******************************************************************************** - ** -diff --git a/drivers/gpu/drm/amd/dal/dc/bios/command_table_helper.c b/drivers/gpu/drm/amd/dal/dc/bios/command_table_helper.c -index 85a5924..a27db8c 100644 ---- a/drivers/gpu/drm/amd/dal/dc/bios/command_table_helper.c -+++ b/drivers/gpu/drm/amd/dal/dc/bios/command_table_helper.c -@@ -55,6 +55,12 @@ bool dal_bios_parser_init_cmd_tbl_helper( - return true; - #endif - -+#if defined(CONFIG_DRM_AMD_DAL_DCE11_2) -+ case DCE_VERSION_11_2: -+ *h = dal_cmd_tbl_helper_dce112_get_table(); -+ return true; -+#endif -+ - default: - /* Unsupported DCE */ - BREAK_TO_DEBUGGER(); -diff --git a/drivers/gpu/drm/amd/dal/dc/bios/command_table_helper.h b/drivers/gpu/drm/amd/dal/dc/bios/command_table_helper.h -index a462917..e6a0d19 100644 ---- a/drivers/gpu/drm/amd/dal/dc/bios/command_table_helper.h -+++ b/drivers/gpu/drm/amd/dal/dc/bios/command_table_helper.h -@@ -32,6 +32,9 @@ - #if defined(CONFIG_DRM_AMD_DAL_DCE11_0) || defined(CONFIG_DRM_AMD_DAL_DCE10_0) - #include "dce110/command_table_helper_dce110.h" - #endif -+#if defined(CONFIG_DRM_AMD_DAL_DCE11_2) -+#include "dce112/command_table_helper_dce112.h" -+#endif - - struct command_table_helper { - bool (*controller_id_to_atom)(enum controller_id id, uint8_t *atom_id); -diff --git a/drivers/gpu/drm/amd/dal/dc/bios/dce112/bios_parser_helper_dce112.c b/drivers/gpu/drm/amd/dal/dc/bios/dce112/bios_parser_helper_dce112.c -new file mode 100644 -index 0000000..1b0f816 ---- /dev/null -+++ b/drivers/gpu/drm/amd/dal/dc/bios/dce112/bios_parser_helper_dce112.c -@@ -0,0 +1,480 @@ -+/* -+ * Copyright 2012-15 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, sub license, -+ * 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 "dm_services.h" -+ -+#include "atom.h" -+ -+#include "include/bios_parser_types.h" -+#include "include/adapter_service_types.h" -+#include "include/logger_interface.h" -+ -+#include "../bios_parser_helper.h" -+ -+#include "dce/dce_11_0_d.h" -+#include "bif/bif_5_1_d.h" -+ -+/** -+ * set_scratch_acc_mode_change -+ * -+ * @brief -+ * set Accelerated Mode in VBIOS scratch register, VBIOS will clean it when -+ * VGA/non-Accelerated mode is set -+ * -+ * @param -+ * struct dc_context *ctx - [in] DAL context -+ */ -+static void set_scratch_acc_mode_change( -+ struct dc_context *ctx) -+{ -+ uint32_t addr = mmBIOS_SCRATCH_6; -+ uint32_t value = 0; -+ -+ value = dm_read_reg(ctx, addr); -+ -+ value |= ATOM_S6_ACC_MODE; -+ -+ dm_write_reg(ctx, addr, value); -+} -+ -+/* -+ * set_scratch_active_and_requested -+ * -+ * @brief -+ * Set VBIOS scratch pad registers about active and requested displays -+ * -+ * @param -+ * struct dc_context *ctx - [in] DAL context for register accessing -+ * struct vbios_helper_data *d - [in] values to write -+ */ -+static void set_scratch_active_and_requested( -+ struct dc_context *ctx, -+ struct vbios_helper_data *d) -+{ -+ uint32_t addr = 0; -+ uint32_t value = 0; -+ -+ /* mmBIOS_SCRATCH_3 = mmBIOS_SCRATCH_0 + ATOM_ACTIVE_INFO_DEF */ -+ addr = mmBIOS_SCRATCH_3; -+ -+ value = dm_read_reg(ctx, addr); -+ -+ value &= ~ATOM_S3_DEVICE_ACTIVE_MASK; -+ value |= (d->active & ATOM_S3_DEVICE_ACTIVE_MASK); -+ -+ dm_write_reg(ctx, addr, value); -+ -+ /* mmBIOS_SCRATCH_6 = mmBIOS_SCRATCH_0 + ATOM_ACC_CHANGE_INFO_DEF */ -+ addr = mmBIOS_SCRATCH_6; -+ -+ value = dm_read_reg(ctx, addr); -+ -+ value &= ~ATOM_S6_ACC_REQ_MASK; -+ value |= (d->requested & ATOM_S6_ACC_REQ_MASK); -+ -+ dm_write_reg(ctx, addr, value); -+ -+ /* mmBIOS_SCRATCH_5 = mmBIOS_SCRATCH_0 + ATOM_DOS_REQ_INFO_DEF */ -+ addr = mmBIOS_SCRATCH_5; -+ -+ value = dm_read_reg(ctx, addr); -+ -+ value &= ~ATOM_S5_DOS_REQ_DEVICEw0; -+ value |= (d->active & ATOM_S5_DOS_REQ_DEVICEw0); -+ -+ dm_write_reg(ctx, addr, value); -+ -+ d->active = 0; -+ d->requested = 0; -+} -+ -+/** -+ * get LCD Scale Mode from VBIOS scratch register -+ */ -+static enum lcd_scale get_scratch_lcd_scale( -+ struct dc_context *ctx) -+{ -+ uint32_t addr = mmBIOS_SCRATCH_6; -+ uint32_t value = 0; -+ -+ value = dm_read_reg(ctx, addr); -+ -+ if (value & ATOM_S6_REQ_LCD_EXPANSION_FULL) -+ return LCD_SCALE_FULLPANEL; -+ else if (value & ATOM_S6_REQ_LCD_EXPANSION_ASPEC_RATIO) -+ return LCD_SCALE_ASPECTRATIO; -+ else -+ return LCD_SCALE_NONE; -+} -+ -+/** -+ * prepare_scratch_active_and_requested -+ * -+ * @brief -+ * prepare and update VBIOS scratch pad registers about active and requested -+ * displays -+ * -+ * @param -+ * data - helper's shared data -+ * enum controller_ild - controller Id -+ * enum signal_type - signal type used on display -+ * const struct connector_device_tag_info* - pointer to display type and enum id -+ */ -+static void prepare_scratch_active_and_requested( -+ struct dc_context *ctx, -+ struct vbios_helper_data *data, -+ enum controller_id id, -+ enum signal_type s, -+ const struct connector_device_tag_info *dev_tag) -+{ -+ switch (s) { -+ case SIGNAL_TYPE_DVI_SINGLE_LINK: -+ case SIGNAL_TYPE_DVI_DUAL_LINK: -+ case SIGNAL_TYPE_HDMI_TYPE_A: -+ case SIGNAL_TYPE_DISPLAY_PORT: -+ case SIGNAL_TYPE_DISPLAY_PORT_MST: -+ if (dev_tag->dev_id.device_type == DEVICE_TYPE_DFP) -+ switch (dev_tag->dev_id.enum_id) { -+ case 1: -+ data->requested |= ATOM_S6_ACC_REQ_DFP1; -+ data->active |= ATOM_S3_DFP1_ACTIVE; -+ break; -+ case 2: -+ data->requested |= ATOM_S6_ACC_REQ_DFP2; -+ data->active |= ATOM_S3_DFP2_ACTIVE; -+ break; -+ case 3: -+ data->requested |= ATOM_S6_ACC_REQ_DFP3; -+ data->active |= ATOM_S3_DFP3_ACTIVE; -+ break; -+ case 4: -+ data->requested |= ATOM_S6_ACC_REQ_DFP4; -+ data->active |= ATOM_S3_DFP4_ACTIVE; -+ break; -+ case 5: -+ data->requested |= ATOM_S6_ACC_REQ_DFP5; -+ data->active |= ATOM_S3_DFP5_ACTIVE; -+ break; -+ case 6: -+ data->requested |= ATOM_S6_ACC_REQ_DFP6; -+ data->active |= ATOM_S3_DFP6_ACTIVE; -+ break; -+ default: -+ break; -+ } -+ break; -+ case SIGNAL_TYPE_LVDS: -+ case SIGNAL_TYPE_EDP: -+ data->requested |= ATOM_S6_ACC_REQ_LCD1; -+ data->active |= ATOM_S3_LCD1_ACTIVE; -+ break; -+ case SIGNAL_TYPE_RGB: -+ if (dev_tag->dev_id.device_type == DEVICE_TYPE_CRT) -+ switch (dev_tag->dev_id.enum_id) { -+ case 1: -+ data->requested |= ATOM_S6_ACC_REQ_CRT1; -+ data->active |= ATOM_S3_CRT1_ACTIVE; -+ break; -+ case 2: -+ dal_logger_write(ctx->logger, -+ LOG_MAJOR_BIOS, -+ LOG_MINOR_COMPONENT_BIOS, -+ "%s: DAL does not support DAC2!\n", -+ __func__); -+ break; -+ default: -+ break; -+ } -+ break; -+ default: -+ dal_logger_write(ctx->logger, -+ LOG_MAJOR_BIOS, -+ LOG_MINOR_COMPONENT_BIOS, -+ "%s: No such signal!\n", -+ __func__); -+ break; -+ } -+} -+ -+/* -+ * is_accelerated_mode -+ * -+ * @brief -+ * set Accelerated Mode in VBIOS scratch register, VBIOS will clean it when -+ * VGA/non-Accelerated mode is set -+ * -+ * @param -+ * struct dc_context *ctx -+ * -+ * @return -+ * true if in acceleration mode, false otherwise. -+ */ -+static bool is_accelerated_mode( -+ struct dc_context *ctx) -+{ -+ uint32_t addr = mmBIOS_SCRATCH_6; -+ uint32_t value = dm_read_reg(ctx, addr); -+ -+ return (value & ATOM_S6_ACC_MODE) ? true : false; -+} -+ -+#define BIOS_SCRATCH0_DAC_B_SHIFT 8 -+ -+/** -+ * detect_sink -+ * -+ * @brief -+ * read VBIOS scratch register to determine whether display for the specified -+ * signal is present and return the actual sink signal type -+ * For analog signals VBIOS load detection has to be called prior reading the -+ * register -+ * -+ * @param -+ * encoder - encoder id (to specify DAC) -+ * connector - connector id (to check CV on DIN) -+ * signal - signal (as display type) to check -+ * -+ * @return -+ * signal_type - actual (on the sink) signal type detected -+ */ -+static enum signal_type detect_sink( -+ struct dc_context *ctx, -+ struct graphics_object_id encoder, -+ struct graphics_object_id connector, -+ enum signal_type signal) -+{ -+ uint32_t bios_scratch0; -+ uint32_t encoder_id = encoder.id; -+ /* after DCE 10.x does not support DAC2, so assert and return SIGNAL_TYPE_NONE */ -+ if (encoder_id == ENCODER_ID_INTERNAL_DAC2 -+ || encoder_id == ENCODER_ID_INTERNAL_KLDSCP_DAC2) { -+ ASSERT(false); -+ return SIGNAL_TYPE_NONE; -+ } -+ -+ bios_scratch0 = dm_read_reg(ctx, -+ mmBIOS_SCRATCH_0 + ATOM_DEVICE_CONNECT_INFO_DEF); -+ -+ /* In further processing we use DACB masks. If we want detect load on -+ * DACA, we need to shift the register so DACA bits will be in place of -+ * DACB bits -+ */ -+ if (encoder_id == ENCODER_ID_INTERNAL_DAC1 -+ || encoder_id == ENCODER_ID_INTERNAL_KLDSCP_DAC1 -+ || encoder_id == ENCODER_ID_EXTERNAL_NUTMEG -+ || encoder_id == ENCODER_ID_EXTERNAL_TRAVIS) { -+ bios_scratch0 <<= BIOS_SCRATCH0_DAC_B_SHIFT; -+ } -+ -+ switch (signal) { -+ case SIGNAL_TYPE_RGB: { -+ if (bios_scratch0 & ATOM_S0_CRT2_MASK) -+ return SIGNAL_TYPE_RGB; -+ break; -+ } -+ case SIGNAL_TYPE_LVDS: { -+ if (bios_scratch0 & ATOM_S0_LCD1) -+ return SIGNAL_TYPE_LVDS; -+ break; -+ } -+ case SIGNAL_TYPE_EDP: { -+ if (bios_scratch0 & ATOM_S0_LCD1) -+ return SIGNAL_TYPE_EDP; -+ break; -+ } -+ default: -+ break; -+ } -+ -+ return SIGNAL_TYPE_NONE; -+} -+ -+/** -+ * set_scratch_connected -+ * -+ * @brief -+ * update BIOS_SCRATCH_0 register about connected displays -+ * -+ * @param -+ * bool - update scratch register or just prepare info to be updated -+ * bool - connection state -+ * const struct connector_device_tag_info * - pointer to device type and enum ID -+ */ -+static void set_scratch_connected( -+ struct dc_context *ctx, -+ struct graphics_object_id id, -+ bool connected, -+ const struct connector_device_tag_info *device_tag) -+{ -+ uint32_t addr = 0; -+ uint32_t value = 0; -+ uint32_t update = 0; -+ -+ switch (device_tag->dev_id.device_type) { -+ case DEVICE_TYPE_LCD: -+ /* For LCD VBIOS will update LCD Panel connected bit always and -+ * Lid state bit based on SBIOS info do not do anything here -+ * for LCD -+ */ -+ break; -+ case DEVICE_TYPE_CRT: -+ /* CRT is not supported in DCE11 */ -+ break; -+ case DEVICE_TYPE_DFP: -+ switch (device_tag->dev_id.enum_id) { -+ case 1: -+ update |= ATOM_S0_DFP1; -+ break; -+ case 2: -+ update |= ATOM_S0_DFP2; -+ break; -+ case 3: -+ update |= ATOM_S0_DFP3; -+ break; -+ case 4: -+ update |= ATOM_S0_DFP4; -+ break; -+ case 5: -+ update |= ATOM_S0_DFP5; -+ break; -+ case 6: -+ update |= ATOM_S0_DFP6; -+ break; -+ default: -+ break; -+ } -+ break; -+ case DEVICE_TYPE_CV: -+ /* DCE 8.0 does not support CV, so don't do anything */ -+ break; -+ -+ case DEVICE_TYPE_TV: -+ /* For TV VBIOS will update S-Video or -+ * Composite scratch bits on DAL_LoadDetect -+ * when called by driver, do not do anything -+ * here for TV -+ */ -+ break; -+ -+ default: -+ break; -+ -+ } -+ -+ /* update scratch register */ -+ addr = mmBIOS_SCRATCH_0 + ATOM_DEVICE_CONNECT_INFO_DEF; -+ -+ value = dm_read_reg(ctx, addr); -+ -+ if (connected) -+ value |= update; -+ else -+ value &= ~update; -+ -+ dm_write_reg(ctx, addr, value); -+} -+ -+static void set_scratch_critical_state( -+ struct dc_context *ctx, -+ bool state) -+{ -+ uint32_t addr = mmBIOS_SCRATCH_6; -+ uint32_t value = dm_read_reg(ctx, addr); -+ -+ if (state) -+ value |= ATOM_S6_CRITICAL_STATE; -+ else -+ value &= ~ATOM_S6_CRITICAL_STATE; -+ -+ dm_write_reg(ctx, addr, value); -+} -+ -+static void set_scratch_lcd_scale( -+ struct dc_context *ctx, -+ enum lcd_scale lcd_scale_request) -+{ -+ DAL_LOGGER_NOT_IMPL( -+ LOG_MINOR_COMPONENT_BIOS, -+ "Bios Parser:%s\n", -+ __func__); -+} -+ -+static bool is_lid_open(struct dc_context *ctx) -+{ -+ uint32_t bios_scratch6; -+ -+ bios_scratch6 = -+ dm_read_reg( -+ ctx, -+ mmBIOS_SCRATCH_0 + ATOM_ACC_CHANGE_INFO_DEF); -+ -+ /* lid is open if the bit is not set */ -+ if (!(bios_scratch6 & ATOM_S6_LID_STATE)) -+ return true; -+ -+ return false; -+} -+ -+/* function table */ -+static const struct bios_parser_helper bios_parser_helper_funcs = { -+ .detect_sink = detect_sink, -+ .fmt_bit_depth_control = NULL, -+ .fmt_control = NULL, -+ .get_bios_event_info = NULL, -+ .get_embedded_display_controller_id = NULL, -+ .get_embedded_display_refresh_rate = NULL, -+ .get_requested_backlight_level = NULL, -+ .get_scratch_lcd_scale = get_scratch_lcd_scale, -+ .is_accelerated_mode = is_accelerated_mode, -+ .is_active_display = NULL, -+ .is_display_config_changed = NULL, -+ .is_lid_open = is_lid_open, -+ .is_lid_status_changed = NULL, -+ .prepare_scratch_active_and_requested = -+ prepare_scratch_active_and_requested, -+ .set_scratch_acc_mode_change = set_scratch_acc_mode_change, -+ .set_scratch_active_and_requested = set_scratch_active_and_requested, -+ .set_scratch_connected = set_scratch_connected, -+ .set_scratch_critical_state = set_scratch_critical_state, -+ .set_scratch_lcd_scale = set_scratch_lcd_scale, -+ .take_backlight_control = NULL, -+ .update_requested_backlight_level = NULL, -+}; -+ -+/* -+ * dal_bios_parser_dce112_init_bios_helper -+ * -+ * @brief -+ * Initialize BIOS helper functions -+ * -+ * @param -+ * const struct command_table_helper **h - [out] struct of functions -+ * -+ */ -+ -+const struct bios_parser_helper *dal_bios_parser_helper_dce112_get_table() -+{ -+ return &bios_parser_helper_funcs; -+} -diff --git a/drivers/gpu/drm/amd/dal/dc/bios/dce112/bios_parser_helper_dce112.h b/drivers/gpu/drm/amd/dal/dc/bios/dce112/bios_parser_helper_dce112.h -new file mode 100644 -index 0000000..044327e ---- /dev/null -+++ b/drivers/gpu/drm/amd/dal/dc/bios/dce112/bios_parser_helper_dce112.h -@@ -0,0 +1,34 @@ -+/* -+ * Copyright 2012-15 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, sub license, -+ * 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 __DAL_BIOS_PARSER_HELPER_DCE112_H__ -+#define __DAL_BIOS_PARSER_HELPER_DCE112_H__ -+ -+struct bios_parser_helper; -+ -+/* Initialize BIOS helper functions */ -+const struct bios_parser_helper *dal_bios_parser_helper_dce112_get_table(void); -+ -+#endif /* __DAL_BIOS_PARSER_HELPER_DCE110_H__ */ -diff --git a/drivers/gpu/drm/amd/dal/dc/bios/dce112/command_table_helper_dce112.c b/drivers/gpu/drm/amd/dal/dc/bios/dce112/command_table_helper_dce112.c -new file mode 100644 -index 0000000..32ec228 ---- /dev/null -+++ b/drivers/gpu/drm/amd/dal/dc/bios/dce112/command_table_helper_dce112.c -@@ -0,0 +1,417 @@ -+/* -+ * Copyright 2012-15 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 "dm_services.h" -+ -+#include "atom.h" -+ -+#include "include/bios_parser_types.h" -+#include "include/adapter_service_types.h" -+ -+#include "../command_table_helper.h" -+ -+static uint8_t phy_id_to_atom(enum transmitter t) -+{ -+ uint8_t atom_phy_id; -+ -+ switch (t) { -+ case TRANSMITTER_UNIPHY_A: -+ atom_phy_id = ATOM_PHY_ID_UNIPHYA; -+ break; -+ case TRANSMITTER_UNIPHY_B: -+ atom_phy_id = ATOM_PHY_ID_UNIPHYB; -+ break; -+ case TRANSMITTER_UNIPHY_C: -+ atom_phy_id = ATOM_PHY_ID_UNIPHYC; -+ break; -+ case TRANSMITTER_UNIPHY_D: -+ atom_phy_id = ATOM_PHY_ID_UNIPHYD; -+ break; -+ case TRANSMITTER_UNIPHY_E: -+ atom_phy_id = ATOM_PHY_ID_UNIPHYE; -+ break; -+ case TRANSMITTER_UNIPHY_F: -+ atom_phy_id = ATOM_PHY_ID_UNIPHYF; -+ break; -+ case TRANSMITTER_UNIPHY_G: -+ atom_phy_id = ATOM_PHY_ID_UNIPHYG; -+ break; -+ default: -+ atom_phy_id = ATOM_PHY_ID_UNIPHYA; -+ break; -+ } -+ return atom_phy_id; -+} -+ -+static uint8_t signal_type_to_atom_dig_mode(enum signal_type s) -+{ -+ uint8_t atom_dig_mode = ATOM_TRANSMITTER_DIGMODE_V6_DP; -+ -+ switch (s) { -+ case SIGNAL_TYPE_DISPLAY_PORT: -+ case SIGNAL_TYPE_EDP: -+ atom_dig_mode = ATOM_TRANSMITTER_DIGMODE_V6_DP; -+ break; -+ case SIGNAL_TYPE_DVI_SINGLE_LINK: -+ case SIGNAL_TYPE_DVI_DUAL_LINK: -+ atom_dig_mode = ATOM_TRANSMITTER_DIGMODE_V6_DVI; -+ break; -+ case SIGNAL_TYPE_HDMI_TYPE_A: -+ atom_dig_mode = ATOM_TRANSMITTER_DIGMODE_V6_HDMI; -+ break; -+ case SIGNAL_TYPE_DISPLAY_PORT_MST: -+ atom_dig_mode = ATOM_TRANSMITTER_DIGMODE_V6_DP_MST; -+ break; -+ default: -+ atom_dig_mode = ATOM_TRANSMITTER_DIGMODE_V6_DVI; -+ break; -+ } -+ -+ return atom_dig_mode; -+} -+ -+static uint8_t clock_source_id_to_atom_phy_clk_src_id( -+ enum clock_source_id id) -+{ -+ uint8_t atom_phy_clk_src_id = 0; -+ -+ switch (id) { -+ case CLOCK_SOURCE_ID_PLL0: -+ atom_phy_clk_src_id = ATOM_TRANSMITTER_CONFIG_V5_P0PLL; -+ break; -+ case CLOCK_SOURCE_ID_PLL1: -+ atom_phy_clk_src_id = ATOM_TRANSMITTER_CONFIG_V5_P1PLL; -+ break; -+ case CLOCK_SOURCE_ID_PLL2: -+ atom_phy_clk_src_id = ATOM_TRANSMITTER_CONFIG_V5_P2PLL; -+ break; -+ case CLOCK_SOURCE_ID_EXTERNAL: -+ atom_phy_clk_src_id = ATOM_TRANSMITTER_CONFIG_V5_REFCLK_SRC_EXT; -+ break; -+ default: -+ atom_phy_clk_src_id = ATOM_TRANSMITTER_CONFIG_V5_P1PLL; -+ break; -+ } -+ -+ return atom_phy_clk_src_id >> 2; -+} -+ -+static uint8_t hpd_sel_to_atom(enum hpd_source_id id) -+{ -+ uint8_t atom_hpd_sel = 0; -+ -+ switch (id) { -+ case HPD_SOURCEID1: -+ atom_hpd_sel = ATOM_TRANSMITTER_V6_HPD1_SEL; -+ break; -+ case HPD_SOURCEID2: -+ atom_hpd_sel = ATOM_TRANSMITTER_V6_HPD2_SEL; -+ break; -+ case HPD_SOURCEID3: -+ atom_hpd_sel = ATOM_TRANSMITTER_V6_HPD3_SEL; -+ break; -+ case HPD_SOURCEID4: -+ atom_hpd_sel = ATOM_TRANSMITTER_V6_HPD4_SEL; -+ break; -+ case HPD_SOURCEID5: -+ atom_hpd_sel = ATOM_TRANSMITTER_V6_HPD5_SEL; -+ break; -+ case HPD_SOURCEID6: -+ atom_hpd_sel = ATOM_TRANSMITTER_V6_HPD6_SEL; -+ break; -+ case HPD_SOURCEID_UNKNOWN: -+ default: -+ atom_hpd_sel = 0; -+ break; -+ } -+ return atom_hpd_sel; -+} -+ -+static uint8_t dig_encoder_sel_to_atom(enum engine_id id) -+{ -+ uint8_t atom_dig_encoder_sel = 0; -+ -+ switch (id) { -+ case ENGINE_ID_DIGA: -+ atom_dig_encoder_sel = ATOM_TRANMSITTER_V6__DIGA_SEL; -+ break; -+ case ENGINE_ID_DIGB: -+ atom_dig_encoder_sel = ATOM_TRANMSITTER_V6__DIGB_SEL; -+ break; -+ case ENGINE_ID_DIGC: -+ atom_dig_encoder_sel = ATOM_TRANMSITTER_V6__DIGC_SEL; -+ break; -+ case ENGINE_ID_DIGD: -+ atom_dig_encoder_sel = ATOM_TRANMSITTER_V6__DIGD_SEL; -+ break; -+ case ENGINE_ID_DIGE: -+ atom_dig_encoder_sel = ATOM_TRANMSITTER_V6__DIGE_SEL; -+ break; -+ case ENGINE_ID_DIGF: -+ atom_dig_encoder_sel = ATOM_TRANMSITTER_V6__DIGF_SEL; -+ break; -+ case ENGINE_ID_DIGG: -+ atom_dig_encoder_sel = ATOM_TRANMSITTER_V6__DIGG_SEL; -+ break; -+ case ENGINE_ID_UNKNOWN: -+ /* No DIG_FRONT is associated to DIG_BACKEND */ -+ atom_dig_encoder_sel = 0; -+ break; -+ default: -+ atom_dig_encoder_sel = ATOM_TRANMSITTER_V6__DIGA_SEL; -+ break; -+ } -+ -+ return atom_dig_encoder_sel; -+} -+ -+static bool clock_source_id_to_atom( -+ enum clock_source_id id, -+ uint32_t *atom_pll_id) -+{ -+ bool result = true; -+ -+ if (atom_pll_id != NULL) -+ switch (id) { -+ case CLOCK_SOURCE_COMBO_PHY_PLL0: -+ *atom_pll_id = ATOM_COMBOPHY_PLL0; -+ break; -+ case CLOCK_SOURCE_COMBO_PHY_PLL1: -+ *atom_pll_id = ATOM_COMBOPHY_PLL1; -+ break; -+ case CLOCK_SOURCE_COMBO_PHY_PLL2: -+ *atom_pll_id = ATOM_COMBOPHY_PLL2; -+ break; -+ case CLOCK_SOURCE_COMBO_PHY_PLL3: -+ *atom_pll_id = ATOM_COMBOPHY_PLL3; -+ break; -+ case CLOCK_SOURCE_COMBO_PHY_PLL4: -+ *atom_pll_id = ATOM_COMBOPHY_PLL4; -+ break; -+ case CLOCK_SOURCE_COMBO_PHY_PLL5: -+ *atom_pll_id = ATOM_COMBOPHY_PLL5; -+ break; -+ case CLOCK_SOURCE_COMBO_DISPLAY_PLL0: -+ *atom_pll_id = ATOM_PPLL0; -+ break; -+ case CLOCK_SOURCE_ID_DFS: -+ *atom_pll_id = ATOM_GCK_DFS; -+ break; -+ case CLOCK_SOURCE_ID_VCE: -+ *atom_pll_id = ATOM_DP_DTO; -+ break; -+ case CLOCK_SOURCE_ID_DP_DTO: -+ *atom_pll_id = ATOM_DP_DTO; -+ break; -+ case CLOCK_SOURCE_ID_UNDEFINED: -+ /* Should not happen */ -+ *atom_pll_id = ATOM_PPLL_INVALID; -+ result = false; -+ break; -+ default: -+ result = false; -+ break; -+ } -+ -+ return result; -+} -+ -+static bool engine_bp_to_atom(enum engine_id id, uint32_t *atom_engine_id) -+{ -+ bool result = false; -+ -+ if (atom_engine_id != NULL) -+ switch (id) { -+ case ENGINE_ID_DIGA: -+ *atom_engine_id = ASIC_INT_DIG1_ENCODER_ID; -+ result = true; -+ break; -+ case ENGINE_ID_DIGB: -+ *atom_engine_id = ASIC_INT_DIG2_ENCODER_ID; -+ result = true; -+ break; -+ case ENGINE_ID_DIGC: -+ *atom_engine_id = ASIC_INT_DIG3_ENCODER_ID; -+ result = true; -+ break; -+ case ENGINE_ID_DIGD: -+ *atom_engine_id = ASIC_INT_DIG4_ENCODER_ID; -+ result = true; -+ break; -+ case ENGINE_ID_DIGE: -+ *atom_engine_id = ASIC_INT_DIG5_ENCODER_ID; -+ result = true; -+ break; -+ case ENGINE_ID_DIGF: -+ *atom_engine_id = ASIC_INT_DIG6_ENCODER_ID; -+ result = true; -+ break; -+ case ENGINE_ID_DIGG: -+ *atom_engine_id = ASIC_INT_DIG7_ENCODER_ID; -+ result = true; -+ break; -+ case ENGINE_ID_DACA: -+ *atom_engine_id = ASIC_INT_DAC1_ENCODER_ID; -+ result = true; -+ break; -+ default: -+ break; -+ } -+ -+ return result; -+} -+ -+static uint8_t encoder_action_to_atom(enum bp_encoder_control_action action) -+{ -+ uint8_t atom_action = 0; -+ -+ switch (action) { -+ case ENCODER_CONTROL_ENABLE: -+ atom_action = ATOM_ENABLE; -+ break; -+ case ENCODER_CONTROL_DISABLE: -+ atom_action = ATOM_DISABLE; -+ break; -+ case ENCODER_CONTROL_SETUP: -+ atom_action = ATOM_ENCODER_CMD_STREAM_SETUP; -+ break; -+ case ENCODER_CONTROL_INIT: -+ atom_action = ATOM_ENCODER_INIT; -+ break; -+ default: -+ BREAK_TO_DEBUGGER(); /* Unhandle action in driver.!! */ -+ break; -+ } -+ -+ return atom_action; -+} -+ -+static uint8_t disp_power_gating_action_to_atom( -+ enum bp_pipe_control_action action) -+{ -+ uint8_t atom_pipe_action = 0; -+ -+ switch (action) { -+ case ASIC_PIPE_DISABLE: -+ atom_pipe_action = ATOM_DISABLE; -+ break; -+ case ASIC_PIPE_ENABLE: -+ atom_pipe_action = ATOM_ENABLE; -+ break; -+ case ASIC_PIPE_INIT: -+ atom_pipe_action = ATOM_INIT; -+ break; -+ default: -+ ASSERT_CRITICAL(false); /* Unhandle action in driver! */ -+ break; -+ } -+ -+ return atom_pipe_action; -+} -+ -+bool dc_clock_type_to_atom(enum bp_dce_clock_type id, uint32_t *atom_clock_type) -+{ -+ bool retCode = true; -+ -+ if (atom_clock_type != NULL) { -+ switch (id) { -+ case DCECLOCK_TYPE_DISPLAY_CLOCK: -+ *atom_clock_type = DCE_CLOCK_TYPE_DISPCLK; -+ break; -+ -+ case DCECLOCK_TYPE_DPREFCLK: -+ *atom_clock_type = DCE_CLOCK_TYPE_DPREFCLK; -+ break; -+ -+ default: -+ ASSERT_CRITICAL(false); /* Unhandle action in driver! */ -+ break; -+ } -+ } -+ -+ return retCode; -+} -+ -+uint8_t transmitter_color_depth_to_atom(enum transmitter_color_depth id) -+{ -+ uint8_t atomColorDepth = 0; -+ -+ switch (id) { -+ case TRANSMITTER_COLOR_DEPTH_24: -+ atomColorDepth = PIXEL_CLOCK_V7_DEEPCOLOR_RATIO_DIS; -+ break; -+ case TRANSMITTER_COLOR_DEPTH_30: -+ atomColorDepth = PIXEL_CLOCK_V7_DEEPCOLOR_RATIO_5_4; -+ break; -+ case TRANSMITTER_COLOR_DEPTH_36: -+ atomColorDepth = PIXEL_CLOCK_V7_DEEPCOLOR_RATIO_3_2; -+ break; -+ case TRANSMITTER_COLOR_DEPTH_48: -+ atomColorDepth = PIXEL_CLOCK_V7_DEEPCOLOR_RATIO_2_1; -+ break; -+ default: -+ ASSERT_CRITICAL(false); /* Unhandle action in driver! */ -+ break; -+ } -+ -+ return atomColorDepth; -+} -+ -+/* function table */ -+static const struct command_table_helper command_table_helper_funcs = { -+ .controller_id_to_atom = dal_cmd_table_helper_controller_id_to_atom, -+ .encoder_action_to_atom = encoder_action_to_atom, -+ .engine_bp_to_atom = engine_bp_to_atom, -+ .clock_source_id_to_atom = clock_source_id_to_atom, -+ .clock_source_id_to_atom_phy_clk_src_id = -+ clock_source_id_to_atom_phy_clk_src_id, -+ .signal_type_to_atom_dig_mode = signal_type_to_atom_dig_mode, -+ .hpd_sel_to_atom = hpd_sel_to_atom, -+ .dig_encoder_sel_to_atom = dig_encoder_sel_to_atom, -+ .phy_id_to_atom = phy_id_to_atom, -+ .disp_power_gating_action_to_atom = disp_power_gating_action_to_atom, -+ .assign_control_parameter = NULL, -+ .clock_source_id_to_ref_clk_src = NULL, -+ .transmitter_bp_to_atom = NULL, -+ .encoder_id_to_atom = dal_cmd_table_helper_encoder_id_to_atom, -+ .encoder_mode_bp_to_atom = dal_cmd_table_helper_encoder_mode_bp_to_atom, -+ .dc_clock_type_to_atom = dc_clock_type_to_atom, -+ .transmitter_color_depth_to_atom = transmitter_color_depth_to_atom, -+}; -+ -+/* -+ * dal_cmd_tbl_helper_dce110_get_table -+ * -+ * @brief -+ * Initialize command table helper functions -+ * -+ * @param -+ * const struct command_table_helper **h - [out] struct of functions -+ * -+ */ -+const struct command_table_helper *dal_cmd_tbl_helper_dce112_get_table() -+{ -+ return &command_table_helper_funcs; -+} -diff --git a/drivers/gpu/drm/amd/dal/dc/bios/dce112/command_table_helper_dce112.h b/drivers/gpu/drm/amd/dal/dc/bios/dce112/command_table_helper_dce112.h -new file mode 100644 -index 0000000..dc36609 ---- /dev/null -+++ b/drivers/gpu/drm/amd/dal/dc/bios/dce112/command_table_helper_dce112.h -@@ -0,0 +1,34 @@ -+/* -+ * Copyright 2012-15 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 __DAL_COMMAND_TABLE_HELPER_DCE112_H__ -+#define __DAL_COMMAND_TABLE_HELPER_DCE112_H__ -+ -+struct command_table_helper; -+ -+/* Initialize command table helper functions */ -+const struct command_table_helper *dal_cmd_tbl_helper_dce112_get_table(void); -+ -+#endif /* __DAL_COMMAND_TABLE_HELPER_DCE110_H__ */ -diff --git a/drivers/gpu/drm/amd/dal/dc/calcs/bandwidth_calcs.c b/drivers/gpu/drm/amd/dal/dc/calcs/bandwidth_calcs.c -index f39499a..8a19139 100644 ---- a/drivers/gpu/drm/amd/dal/dc/calcs/bandwidth_calcs.c -+++ b/drivers/gpu/drm/amd/dal/dc/calcs/bandwidth_calcs.c -@@ -3726,6 +3726,212 @@ void bw_calcs_init(struct bw_calcs_dceip *bw_dceip, - dceip.scatter_gather_pte_request_rows_in_tiling_mode = 2; - dceip.mcifwr_all_surfaces_burst_time = bw_int_to_fixed(0); /* todo: this is a bug*/ - break; -+ case BW_CALCS_VERSION_ELLESMERE: -+ vbios.number_of_dram_channels = 8; -+ vbios.dram_channel_width_in_bits = 32; -+ vbios.number_of_dram_banks = 8; -+ vbios.high_yclk = bw_int_to_fixed(6000); -+ vbios.mid_yclk = bw_int_to_fixed(3200); -+ vbios.low_yclk = bw_int_to_fixed(1000); -+ vbios.low_sclk = bw_int_to_fixed(300); -+ vbios.mid_sclk = bw_int_to_fixed(974); -+ vbios.high_sclk = bw_int_to_fixed(1154); -+ vbios.low_voltage_max_dispclk = bw_int_to_fixed(459); -+ vbios.mid_voltage_max_dispclk = bw_int_to_fixed(654); -+ vbios.high_voltage_max_dispclk = bw_int_to_fixed(1132); -+ vbios.data_return_bus_width = bw_int_to_fixed(32); -+ vbios.trc = bw_int_to_fixed(48); -+ vbios.dmifmc_urgent_latency = bw_int_to_fixed(3); -+ vbios.stutter_self_refresh_exit_latency = bw_int_to_fixed(5); -+ vbios.nbp_state_change_latency = bw_int_to_fixed(45); -+ vbios.mcifwrmc_urgent_latency = bw_int_to_fixed(10); -+ vbios.scatter_gather_enable = true; -+ vbios.down_spread_percentage = bw_frc_to_fixed(5, 10); -+ vbios.cursor_width = 32; -+ vbios.average_compression_rate = 4; -+ vbios.number_of_request_slots_gmc_reserves_for_dmif_per_channel = -+ 256; -+ vbios.blackout_duration = bw_int_to_fixed(0); /* us */ -+ vbios.maximum_blackout_recovery_time = bw_int_to_fixed(0); -+ -+ dceip.dmif_request_buffer_size = bw_int_to_fixed(768); -+ dceip.de_tiling_buffer = bw_int_to_fixed(0); -+ dceip.dcfclk_request_generation = 0; -+ dceip.lines_interleaved_into_lb = 2; -+ dceip.chunk_width = 256; -+ dceip.number_of_graphics_pipes = 6; -+ dceip.number_of_underlay_pipes = 0; -+ dceip.display_write_back_supported = false; -+ dceip.argb_compression_support = false; -+ dceip.underlay_vscaler_efficiency6_bit_per_component = -+ bw_frc_to_fixed(35556, 10000); -+ dceip.underlay_vscaler_efficiency8_bit_per_component = -+ bw_frc_to_fixed(34286, 10000); -+ dceip.underlay_vscaler_efficiency10_bit_per_component = -+ bw_frc_to_fixed(32, 10); -+ dceip.underlay_vscaler_efficiency12_bit_per_component = -+ bw_int_to_fixed(3); -+ dceip.graphics_vscaler_efficiency6_bit_per_component = -+ bw_frc_to_fixed(35, 10); -+ dceip.graphics_vscaler_efficiency8_bit_per_component = -+ bw_frc_to_fixed(34286, 10000); -+ dceip.graphics_vscaler_efficiency10_bit_per_component = -+ bw_frc_to_fixed(32, 10); -+ dceip.graphics_vscaler_efficiency12_bit_per_component = -+ bw_int_to_fixed(3); -+ dceip.alpha_vscaler_efficiency = bw_int_to_fixed(3); -+ dceip.max_dmif_buffer_allocated = 4; -+ dceip.graphics_dmif_size = 12288; -+ dceip.underlay_luma_dmif_size = 19456; -+ dceip.underlay_chroma_dmif_size = 23552; -+ dceip.pre_downscaler_enabled = true; -+ dceip.underlay_downscale_prefetch_enabled = true; -+ dceip.lb_write_pixels_per_dispclk = bw_int_to_fixed(1); -+ dceip.lb_size_per_component444 = bw_int_to_fixed(245952); -+ dceip.graphics_lb_nodownscaling_multi_line_prefetching = true; -+ dceip.stutter_and_dram_clock_state_change_gated_before_cursor = -+ bw_int_to_fixed(1); -+ dceip.underlay420_luma_lb_size_per_component = bw_int_to_fixed( -+ 82176); -+ dceip.underlay420_chroma_lb_size_per_component = -+ bw_int_to_fixed(164352); -+ dceip.underlay422_lb_size_per_component = bw_int_to_fixed( -+ 82176); -+ dceip.cursor_chunk_width = bw_int_to_fixed(64); -+ dceip.cursor_dcp_buffer_lines = bw_int_to_fixed(4); -+ dceip.cursor_memory_interface_buffer_pixels = bw_int_to_fixed( -+ 64); -+ dceip.underlay_maximum_width_efficient_for_tiling = -+ bw_int_to_fixed(1920); -+ dceip.underlay_maximum_height_efficient_for_tiling = -+ bw_int_to_fixed(1080); -+ dceip.peak_pte_request_to_eviction_ratio_limiting_multiple_displays_or_single_rotated_display = -+ bw_frc_to_fixed(3, 10); -+ dceip.peak_pte_request_to_eviction_ratio_limiting_single_display_no_rotation = -+ bw_int_to_fixed(25); -+ dceip.minimum_outstanding_pte_request_limit = bw_int_to_fixed( -+ 2); -+ dceip.maximum_total_outstanding_pte_requests_allowed_by_saw = -+ bw_int_to_fixed(128); -+ dceip.limit_excessive_outstanding_dmif_requests = true; -+ dceip.linear_mode_line_request_alternation_slice = -+ bw_int_to_fixed(64); -+ dceip.scatter_gather_lines_of_pte_prefetching_in_linear_mode = -+ 32; -+ dceip.display_write_back420_luma_mcifwr_buffer_size = 12288; -+ dceip.display_write_back420_chroma_mcifwr_buffer_size = 8192; -+ dceip.request_efficiency = bw_frc_to_fixed(8, 10); -+ dceip.dispclk_per_request = bw_int_to_fixed(2); -+ dceip.dispclk_ramping_factor = bw_frc_to_fixed(11, 10); -+ dceip.display_pipe_throughput_factor = bw_frc_to_fixed( -+ 105, -+ 100); -+ dceip.scatter_gather_pte_request_rows_in_tiling_mode = 2; -+ dceip.mcifwr_all_surfaces_burst_time = bw_int_to_fixed(0); -+ break; -+ case BW_CALCS_VERSION_BAFFIN: -+ vbios.number_of_dram_channels = 4; -+ vbios.dram_channel_width_in_bits = 32; -+ vbios.number_of_dram_banks = 8; -+ vbios.high_yclk = bw_int_to_fixed(6000); -+ vbios.mid_yclk = bw_int_to_fixed(3200); -+ vbios.low_yclk = bw_int_to_fixed(1000); -+ vbios.low_sclk = bw_int_to_fixed(300); -+ vbios.mid_sclk = bw_int_to_fixed(974); -+ vbios.high_sclk = bw_int_to_fixed(1154); -+ vbios.low_voltage_max_dispclk = bw_int_to_fixed(459); -+ vbios.mid_voltage_max_dispclk = bw_int_to_fixed(654); -+ vbios.high_voltage_max_dispclk = bw_int_to_fixed(1132); -+ vbios.data_return_bus_width = bw_int_to_fixed(32); -+ vbios.trc = bw_int_to_fixed(48); -+ vbios.dmifmc_urgent_latency = bw_int_to_fixed(3); -+ vbios.stutter_self_refresh_exit_latency = bw_int_to_fixed(5); -+ vbios.nbp_state_change_latency = bw_int_to_fixed(45); -+ vbios.mcifwrmc_urgent_latency = bw_int_to_fixed(10); -+ vbios.scatter_gather_enable = true; -+ vbios.down_spread_percentage = bw_frc_to_fixed(5, 10); -+ vbios.cursor_width = 32; -+ vbios.average_compression_rate = 4; -+ vbios.number_of_request_slots_gmc_reserves_for_dmif_per_channel = -+ 256; -+ vbios.blackout_duration = bw_int_to_fixed(0); /* us */ -+ vbios.maximum_blackout_recovery_time = bw_int_to_fixed(0); -+ -+ dceip.dmif_request_buffer_size = bw_int_to_fixed(768); -+ dceip.de_tiling_buffer = bw_int_to_fixed(0); -+ dceip.dcfclk_request_generation = 0; -+ dceip.lines_interleaved_into_lb = 2; -+ dceip.chunk_width = 256; -+ dceip.number_of_graphics_pipes = 5; -+ dceip.number_of_underlay_pipes = 0; -+ dceip.display_write_back_supported = false; -+ dceip.argb_compression_support = false; -+ dceip.underlay_vscaler_efficiency6_bit_per_component = -+ bw_frc_to_fixed(35556, 10000); -+ dceip.underlay_vscaler_efficiency8_bit_per_component = -+ bw_frc_to_fixed(34286, 10000); -+ dceip.underlay_vscaler_efficiency10_bit_per_component = -+ bw_frc_to_fixed(32, 10); -+ dceip.underlay_vscaler_efficiency12_bit_per_component = -+ bw_int_to_fixed(3); -+ dceip.graphics_vscaler_efficiency6_bit_per_component = -+ bw_frc_to_fixed(35, 10); -+ dceip.graphics_vscaler_efficiency8_bit_per_component = -+ bw_frc_to_fixed(34286, 10000); -+ dceip.graphics_vscaler_efficiency10_bit_per_component = -+ bw_frc_to_fixed(32, 10); -+ dceip.graphics_vscaler_efficiency12_bit_per_component = -+ bw_int_to_fixed(3); -+ dceip.alpha_vscaler_efficiency = bw_int_to_fixed(3); -+ dceip.max_dmif_buffer_allocated = 4; -+ dceip.graphics_dmif_size = 12288; -+ dceip.underlay_luma_dmif_size = 19456; -+ dceip.underlay_chroma_dmif_size = 23552; -+ dceip.pre_downscaler_enabled = true; -+ dceip.underlay_downscale_prefetch_enabled = true; -+ dceip.lb_write_pixels_per_dispclk = bw_int_to_fixed(1); -+ dceip.lb_size_per_component444 = bw_int_to_fixed(245952); -+ dceip.graphics_lb_nodownscaling_multi_line_prefetching = true; -+ dceip.stutter_and_dram_clock_state_change_gated_before_cursor = -+ bw_int_to_fixed(1); -+ dceip.underlay420_luma_lb_size_per_component = bw_int_to_fixed( -+ 82176); -+ dceip.underlay420_chroma_lb_size_per_component = -+ bw_int_to_fixed(164352); -+ dceip.underlay422_lb_size_per_component = bw_int_to_fixed( -+ 82176); -+ dceip.cursor_chunk_width = bw_int_to_fixed(64); -+ dceip.cursor_dcp_buffer_lines = bw_int_to_fixed(4); -+ dceip.cursor_memory_interface_buffer_pixels = bw_int_to_fixed( -+ 64); -+ dceip.underlay_maximum_width_efficient_for_tiling = -+ bw_int_to_fixed(1920); -+ dceip.underlay_maximum_height_efficient_for_tiling = -+ bw_int_to_fixed(1080); -+ dceip.peak_pte_request_to_eviction_ratio_limiting_multiple_displays_or_single_rotated_display = -+ bw_frc_to_fixed(3, 10); -+ dceip.peak_pte_request_to_eviction_ratio_limiting_single_display_no_rotation = -+ bw_int_to_fixed(25); -+ dceip.minimum_outstanding_pte_request_limit = bw_int_to_fixed( -+ 2); -+ dceip.maximum_total_outstanding_pte_requests_allowed_by_saw = -+ bw_int_to_fixed(128); -+ dceip.limit_excessive_outstanding_dmif_requests = true; -+ dceip.linear_mode_line_request_alternation_slice = -+ bw_int_to_fixed(64); -+ dceip.scatter_gather_lines_of_pte_prefetching_in_linear_mode = -+ 32; -+ dceip.display_write_back420_luma_mcifwr_buffer_size = 12288; -+ dceip.display_write_back420_chroma_mcifwr_buffer_size = 8192; -+ dceip.request_efficiency = bw_frc_to_fixed(8, 10); -+ dceip.dispclk_per_request = bw_int_to_fixed(2); -+ dceip.dispclk_ramping_factor = bw_frc_to_fixed(11, 10); -+ dceip.display_pipe_throughput_factor = bw_frc_to_fixed( -+ 105, -+ 100); -+ dceip.scatter_gather_pte_request_rows_in_tiling_mode = 2; -+ dceip.mcifwr_all_surfaces_burst_time = bw_int_to_fixed(0); -+ break; - default: - break; - } -diff --git a/drivers/gpu/drm/amd/dal/dc/core/dc_hw_sequencer.c b/drivers/gpu/drm/amd/dal/dc/core/dc_hw_sequencer.c -index 61bb67a..f9dd0d8 100644 ---- a/drivers/gpu/drm/amd/dal/dc/core/dc_hw_sequencer.c -+++ b/drivers/gpu/drm/amd/dal/dc/core/dc_hw_sequencer.c -@@ -34,6 +34,9 @@ - #if defined(CONFIG_DRM_AMD_DAL_DCE11_0) - #include "dce110/dce110_hw_sequencer.h" - #endif -+#if defined(CONFIG_DRM_AMD_DAL_DCE11_2) -+#include "dce112/dce112_hw_sequencer.h" -+#endif - - bool dc_construct_hw_sequencer( - struct adapter_service *adapter_serv, -@@ -55,6 +58,10 @@ bool dc_construct_hw_sequencer( - case DCE_VERSION_11_0: - return dce110_hw_sequencer_construct(dc); - #endif -+#if defined(CONFIG_DRM_AMD_DAL_DCE11_2) -+ case DCE_VERSION_11_2: -+ return dce112_hw_sequencer_construct(dc); -+#endif - default: - break; - } -diff --git a/drivers/gpu/drm/amd/dal/dc/core/dc_resource.c b/drivers/gpu/drm/amd/dal/dc/core/dc_resource.c -index 5f3b702..087670d 100644 ---- a/drivers/gpu/drm/amd/dal/dc/core/dc_resource.c -+++ b/drivers/gpu/drm/amd/dal/dc/core/dc_resource.c -@@ -41,11 +41,13 @@ - #if defined(CONFIG_DRM_AMD_DAL_DCE11_0) - #include "dce110/dce110_resource.h" - #endif -+#if defined(CONFIG_DRM_AMD_DAL_DCE11_2) -+#include "dce112/dce112_resource.h" -+#endif - - enum dce_version resource_parse_asic_id(struct hw_asic_id asic_id) -- { -+{ - enum dce_version dc_version = DCE_VERSION_UNKNOWN; -- - switch (asic_id.chip_family) { - - #if defined(CONFIG_DRM_AMD_DAL_DCE8_0) -@@ -68,6 +70,12 @@ enum dce_version resource_parse_asic_id(struct hw_asic_id asic_id) - break; - } - #endif -+#if defined(CONFIG_DRM_AMD_DAL_DCE11_2) -+ if (ASIC_REV_IS_POLARIS10_P(asic_id.hw_internal_rev) || -+ ASIC_REV_IS_POLARIS11_M(asic_id.hw_internal_rev)) { -+ dc_version = DCE_VERSION_11_2; -+ } -+#endif - break; - default: - dc_version = DCE_VERSION_UNKNOWN; -@@ -83,6 +91,11 @@ bool dc_construct_resource_pool(struct adapter_service *adapter_serv, - { - - switch (dc_version) { -+#if defined(CONFIG_DRM_AMD_DAL_DCE8_0) -+ case DCE_VERSION_8_0: -+ return dce80_construct_resource_pool( -+ adapter_serv, num_virtual_links, dc, &dc->res_pool); -+#endif - #if defined(CONFIG_DRM_AMD_DAL_DCE10_0) - case DCE_VERSION_10_0: - return dce100_construct_resource_pool( -@@ -93,6 +106,11 @@ bool dc_construct_resource_pool(struct adapter_service *adapter_serv, - return dce110_construct_resource_pool( - adapter_serv, num_virtual_links, dc, &dc->res_pool); - #endif -+#if defined(CONFIG_DRM_AMD_DAL_DCE11_2) -+ case DCE_VERSION_11_2: -+ return dce112_construct_resource_pool( -+ adapter_serv, num_virtual_links, dc, &dc->res_pool); -+#endif - default: - break; - } -diff --git a/drivers/gpu/drm/amd/dal/dc/dce110/dce110_hw_sequencer.c b/drivers/gpu/drm/amd/dal/dc/dce110/dce110_hw_sequencer.c -index 3d4f8b7..a21fcbd 100644 ---- a/drivers/gpu/drm/amd/dal/dc/dce110/dce110_hw_sequencer.c -+++ b/drivers/gpu/drm/amd/dal/dc/dce110/dce110_hw_sequencer.c -@@ -416,6 +416,7 @@ static void dce110_crtc_switch_to_clk_src( - uint32_t pixel_rate_cntl_value; - uint32_t addr; - -+ /* These addresses are the same across DCE8 - DCE11.2 */ - addr = mmCRTC0_PIXEL_RATE_CNTL + crtc_inst * - (mmCRTC1_PIXEL_RATE_CNTL - mmCRTC0_PIXEL_RATE_CNTL); - -diff --git a/drivers/gpu/drm/amd/dal/dc/dce110/dce110_timing_generator.c b/drivers/gpu/drm/amd/dal/dc/dce110/dce110_timing_generator.c -index de370ee..a9ef65d 100644 ---- a/drivers/gpu/drm/amd/dal/dc/dce110/dce110_timing_generator.c -+++ b/drivers/gpu/drm/amd/dal/dc/dce110/dce110_timing_generator.c -@@ -59,7 +59,7 @@ enum black_color_format { - - /* Flowing register offsets are same in files of - * dce/dce_11_0_d.h -- * dce/vi_ellesmere_p/vi_ellesmere_d.h -+ * dce/vi_polaris10_p/vi_polaris10_d.h - * - * So we can create dce110 timing generator to use it. - */ -diff --git a/drivers/gpu/drm/amd/dal/dc/dce112/Makefile b/drivers/gpu/drm/amd/dal/dc/dce112/Makefile -new file mode 100644 -index 0000000..c7d61d9 ---- /dev/null -+++ b/drivers/gpu/drm/amd/dal/dc/dce112/Makefile -@@ -0,0 +1,10 @@ -+# -+# Makefile for the 'controller' sub-component of DAL. -+# It provides the control and status of HW CRTC block. -+ -+DCE112 = dce112_link_encoder.o dce112_compressor.o dce112_hw_sequencer.o \ -+dce112_resource.o dce112_clock_source.o dce112_mem_input.o -+ -+AMD_DAL_DCE112 = $(addprefix $(AMDDALPATH)/dc/dce112/,$(DCE112)) -+ -+AMD_DAL_FILES += $(AMD_DAL_DCE112) -diff --git a/drivers/gpu/drm/amd/dal/dc/dce112/dce112_clock_source.c b/drivers/gpu/drm/amd/dal/dc/dce112/dce112_clock_source.c -new file mode 100644 -index 0000000..7ec9508 ---- /dev/null -+++ b/drivers/gpu/drm/amd/dal/dc/dce112/dce112_clock_source.c -@@ -0,0 +1,266 @@ -+/* -+ * Copyright 2012-15 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 "dm_services.h" -+ -+#include "dce112_clock_source.h" -+ -+/* include DCE11.2 register header files */ -+#include "dce/dce_11_2_d.h" -+#include "dce/dce_11_2_sh_mask.h" -+ -+#include "dc_types.h" -+#include "core_types.h" -+ -+#include "include/grph_object_id.h" -+#include "include/logger_interface.h" -+ -+/** -+ * Calculate PLL Dividers for given Clock Value. -+ * First will call VBIOS Adjust Exec table to check if requested Pixel clock -+ * will be Adjusted based on usage. -+ * Then it will calculate PLL Dividers for this Adjusted clock using preferred -+ * method (Maximum VCO frequency). -+ * -+ * \return -+ * Calculation error in units of 0.01% -+ */ -+static uint32_t dce112_get_pix_clk_dividers( -+ struct clock_source *cs, -+ struct pixel_clk_params *pix_clk_params, -+ struct pll_settings *pll_settings) -+{ -+ struct dce112_clk_src *clk_src = TO_DCE112_CLK_SRC(cs); -+ uint32_t actualPixelClockInKHz; -+ -+ if (pix_clk_params == NULL || pll_settings == NULL -+ || pix_clk_params->requested_pix_clk == 0) { -+ dal_logger_write(cs->ctx->logger, -+ LOG_MAJOR_ERROR, -+ LOG_MINOR_COMPONENT_GPU, -+ "%s: Invalid parameters!!\n", __func__); -+ return 0; -+ } -+ -+ memset(pll_settings, 0, sizeof(*pll_settings)); -+ -+ if (clk_src->base.id == CLOCK_SOURCE_ID_DP_DTO) { -+ pll_settings->adjusted_pix_clk = clk_src->ext_clk_khz; -+ pll_settings->calculated_pix_clk = clk_src->ext_clk_khz; -+ pll_settings->actual_pix_clk = -+ pix_clk_params->requested_pix_clk; -+ return 0; -+ } -+ /* PLL only after this point */ -+ -+ actualPixelClockInKHz = pix_clk_params->requested_pix_clk; -+ -+ /* Calculate Dividers */ -+ if (pix_clk_params->signal_type == SIGNAL_TYPE_HDMI_TYPE_A) { -+ switch (pix_clk_params->color_depth) { -+ case COLOR_DEPTH_101010: -+ actualPixelClockInKHz = (actualPixelClockInKHz * 5) >> 2; -+ break; -+ case COLOR_DEPTH_121212: -+ actualPixelClockInKHz = (actualPixelClockInKHz * 6) >> 2; -+ break; -+ case COLOR_DEPTH_161616: -+ actualPixelClockInKHz = actualPixelClockInKHz * 2; -+ break; -+ default: -+ break; -+ } -+ } -+ -+ pll_settings->actual_pix_clk = actualPixelClockInKHz; -+ pll_settings->adjusted_pix_clk = actualPixelClockInKHz; -+ pll_settings->calculated_pix_clk = pix_clk_params->requested_pix_clk; -+ -+ return 0; -+} -+ -+static void program_pixel_clk_resync( -+ struct dce112_clk_src *clk_src, -+ enum signal_type signal_type, -+ enum dc_color_depth colordepth) -+{ -+ uint32_t value = 0; -+ -+ value = dm_read_reg(clk_src->base.ctx, -+ clk_src->offsets.pixclk_resync_cntl); -+ -+ set_reg_field_value( -+ value, -+ 0, -+ PHYPLLA_PIXCLK_RESYNC_CNTL, -+ PHYPLLA_DCCG_DEEP_COLOR_CNTL); -+ -+ /* -+ 24 bit mode: TMDS clock = 1.0 x pixel clock (1:1) -+ 30 bit mode: TMDS clock = 1.25 x pixel clock (5:4) -+ 36 bit mode: TMDS clock = 1.5 x pixel clock (3:2) -+ 48 bit mode: TMDS clock = 2 x pixel clock (2:1) -+ */ -+ if (signal_type != SIGNAL_TYPE_HDMI_TYPE_A) -+ return; -+ -+ switch (colordepth) { -+ case COLOR_DEPTH_888: -+ set_reg_field_value( -+ value, -+ 0, -+ PHYPLLA_PIXCLK_RESYNC_CNTL, -+ PHYPLLA_DCCG_DEEP_COLOR_CNTL); -+ break; -+ case COLOR_DEPTH_101010: -+ set_reg_field_value( -+ value, -+ 1, -+ PHYPLLA_PIXCLK_RESYNC_CNTL, -+ PHYPLLA_DCCG_DEEP_COLOR_CNTL); -+ break; -+ case COLOR_DEPTH_121212: -+ set_reg_field_value( -+ value, -+ 2, -+ PHYPLLA_PIXCLK_RESYNC_CNTL, -+ PHYPLLA_DCCG_DEEP_COLOR_CNTL); -+ break; -+ case COLOR_DEPTH_161616: -+ set_reg_field_value( -+ value, -+ 3, -+ PHYPLLA_PIXCLK_RESYNC_CNTL, -+ PHYPLLA_DCCG_DEEP_COLOR_CNTL); -+ break; -+ default: -+ break; -+ } -+ -+ dm_write_reg( -+ clk_src->base.ctx, -+ clk_src->offsets.pixclk_resync_cntl, -+ value); -+} -+ -+static bool dce112_program_pix_clk( -+ struct clock_source *clk_src, -+ struct pixel_clk_params *pix_clk_params, -+ struct pll_settings *pll_settings) -+{ -+ struct dce112_clk_src *dce112_clk_src = TO_DCE112_CLK_SRC(clk_src); -+ struct bp_pixel_clock_parameters bp_pc_params = {0}; -+ -+ /*ATOMBIOS expects pixel rate adjusted by deep color ratio)*/ -+ bp_pc_params.controller_id = pix_clk_params->controller_id; -+ bp_pc_params.pll_id = clk_src->id; -+ bp_pc_params.target_pixel_clock = pll_settings->actual_pix_clk; -+ bp_pc_params.encoder_object_id = pix_clk_params->encoder_object_id; -+ bp_pc_params.signal_type = pix_clk_params->signal_type; -+ -+ if (clk_src->id != CLOCK_SOURCE_ID_DP_DTO) { -+ bp_pc_params.flags.SET_GENLOCK_REF_DIV_SRC = -+ pll_settings->use_external_clk; -+ bp_pc_params.flags.SET_XTALIN_REF_SRC = -+ !pll_settings->use_external_clk; -+ bp_pc_params.flags.SUPPORT_YUV_420 = 0; -+ } -+ -+ if (dce112_clk_src->bios->funcs->set_pixel_clock( -+ dce112_clk_src->bios, &bp_pc_params) != BP_RESULT_OK) -+ return false; -+ -+ /* TODO: support YCBCR420 */ -+ -+ /* Resync deep color DTO */ -+ if (clk_src->id != CLOCK_SOURCE_ID_DP_DTO) -+ program_pixel_clk_resync(dce112_clk_src, -+ pix_clk_params->signal_type, -+ pix_clk_params->color_depth); -+ -+ return true; -+} -+ -+static bool dce112_clock_source_power_down( -+ struct clock_source *clk_src) -+{ -+ struct dce112_clk_src *dce112_clk_src = TO_DCE112_CLK_SRC(clk_src); -+ enum bp_result bp_result; -+ struct bp_pixel_clock_parameters bp_pixel_clock_params = {0}; -+ -+ if (clk_src->id == CLOCK_SOURCE_ID_DP_DTO) -+ return true; -+ -+ /* If Pixel Clock is 0 it means Power Down Pll*/ -+ bp_pixel_clock_params.controller_id = CONTROLLER_ID_UNDEFINED; -+ bp_pixel_clock_params.pll_id = clk_src->id; -+ bp_pixel_clock_params.flags.FORCE_PROGRAMMING_OF_PLL = 1; -+ -+ /*Call ASICControl to process ATOMBIOS Exec table*/ -+ bp_result = dce112_clk_src->bios->funcs->set_pixel_clock( -+ dce112_clk_src->bios, -+ &bp_pixel_clock_params); -+ -+ return bp_result == BP_RESULT_OK; -+} -+ -+/*****************************************/ -+/* Constructor */ -+/*****************************************/ -+static struct clock_source_funcs dce112_clk_src_funcs = { -+ .cs_power_down = dce112_clock_source_power_down, -+ .program_pix_clk = dce112_program_pix_clk, -+ .get_pix_clk_dividers = dce112_get_pix_clk_dividers -+}; -+ -+bool dce112_clk_src_construct( -+ struct dce112_clk_src *clk_src, -+ struct dc_context *ctx, -+ struct dc_bios *bios, -+ enum clock_source_id id, -+ const struct dce112_clk_src_reg_offsets *reg_offsets) -+{ -+ struct firmware_info fw_info = { { 0 } }; -+ -+ clk_src->base.ctx = ctx; -+ clk_src->bios = bios; -+ clk_src->base.id = id; -+ clk_src->base.funcs = &dce112_clk_src_funcs; -+ clk_src->offsets = *reg_offsets; -+ -+ if (clk_src->bios->funcs->get_firmware_info( -+ clk_src->bios, &fw_info) != BP_RESULT_OK) { -+ ASSERT_CRITICAL(false); -+ goto unexpected_failure; -+ } -+ -+ clk_src->ext_clk_khz = fw_info.external_clock_source_frequency_for_dp; -+ -+ return true; -+ -+unexpected_failure: -+ return false; -+} -+ -diff --git a/drivers/gpu/drm/amd/dal/dc/dce112/dce112_clock_source.h b/drivers/gpu/drm/amd/dal/dc/dce112/dce112_clock_source.h -new file mode 100644 -index 0000000..40ecc58 ---- /dev/null -+++ b/drivers/gpu/drm/amd/dal/dc/dce112/dce112_clock_source.h -@@ -0,0 +1,52 @@ -+/* Copyright 2012-15 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 __DC_CLOCK_SOURCE_DCE110_H__ -+#define __DC_CLOCK_SOURCE_DCE110_H__ -+ -+#include "clock_source.h" -+ -+#define TO_DCE112_CLK_SRC(clk_src)\ -+ container_of(clk_src, struct dce112_clk_src, base) -+ -+struct dce112_clk_src_reg_offsets { -+ uint32_t pixclk_resync_cntl; -+}; -+ -+struct dce112_clk_src { -+ struct clock_source base; -+ struct dce112_clk_src_reg_offsets offsets; -+ struct dc_bios *bios; -+ -+ uint32_t ext_clk_khz; -+}; -+ -+bool dce112_clk_src_construct( -+ struct dce112_clk_src *clk_src, -+ struct dc_context *ctx, -+ struct dc_bios *bios, -+ enum clock_source_id, -+ const struct dce112_clk_src_reg_offsets *reg_offsets); -+ -+#endif -diff --git a/drivers/gpu/drm/amd/dal/dc/dce112/dce112_compressor.c b/drivers/gpu/drm/amd/dal/dc/dce112/dce112_compressor.c -new file mode 100644 -index 0000000..9526ffd ---- /dev/null -+++ b/drivers/gpu/drm/amd/dal/dc/dce112/dce112_compressor.c -@@ -0,0 +1,883 @@ -+/* -+ * Copyright 2012-15 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 "dm_services.h" -+ -+#include "dce/dce_11_2_d.h" -+#include "dce/dce_11_2_sh_mask.h" -+#include "gmc/gmc_8_1_sh_mask.h" -+#include "gmc/gmc_8_1_d.h" -+ -+#include "include/logger_interface.h" -+#include "include/adapter_service_interface.h" -+ -+#include "dce112_compressor.h" -+ -+#define DCP_REG(reg)\ -+ (reg + cp110->offsets.dcp_offset) -+#define DMIF_REG(reg)\ -+ (reg + cp110->offsets.dmif_offset) -+ -+static const struct dce112_compressor_reg_offsets reg_offsets[] = { -+{ -+ .dcp_offset = (mmDCP0_GRPH_CONTROL - mmDCP0_GRPH_CONTROL), -+ .dmif_offset = -+ (mmDMIF_PG0_DPG_PIPE_DPM_CONTROL -+ - mmDMIF_PG0_DPG_PIPE_DPM_CONTROL), -+}, -+{ -+ .dcp_offset = (mmDCP1_GRPH_CONTROL - mmDCP0_GRPH_CONTROL), -+ .dmif_offset = -+ (mmDMIF_PG1_DPG_PIPE_DPM_CONTROL -+ - mmDMIF_PG0_DPG_PIPE_DPM_CONTROL), -+}, -+{ -+ .dcp_offset = (mmDCP2_GRPH_CONTROL - mmDCP0_GRPH_CONTROL), -+ .dmif_offset = -+ (mmDMIF_PG2_DPG_PIPE_DPM_CONTROL -+ - mmDMIF_PG0_DPG_PIPE_DPM_CONTROL), -+} -+}; -+ -+static const uint32_t dce11_one_lpt_channel_max_resolution = 2560 * 1600; -+ -+enum fbc_idle_force { -+ /* Bit 0 - Display registers updated */ -+ FBC_IDLE_FORCE_DISPLAY_REGISTER_UPDATE = 0x00000001, -+ -+ /* Bit 2 - FBC_GRPH_COMP_EN register updated */ -+ FBC_IDLE_FORCE_GRPH_COMP_EN = 0x00000002, -+ /* Bit 3 - FBC_SRC_SEL register updated */ -+ FBC_IDLE_FORCE_SRC_SEL_CHANGE = 0x00000004, -+ /* Bit 4 - FBC_MIN_COMPRESSION register updated */ -+ FBC_IDLE_FORCE_MIN_COMPRESSION_CHANGE = 0x00000008, -+ /* Bit 5 - FBC_ALPHA_COMP_EN register updated */ -+ FBC_IDLE_FORCE_ALPHA_COMP_EN = 0x00000010, -+ /* Bit 6 - FBC_ZERO_ALPHA_CHUNK_SKIP_EN register updated */ -+ FBC_IDLE_FORCE_ZERO_ALPHA_CHUNK_SKIP_EN = 0x00000020, -+ /* Bit 7 - FBC_FORCE_COPY_TO_COMP_BUF register updated */ -+ FBC_IDLE_FORCE_FORCE_COPY_TO_COMP_BUF = 0x00000040, -+ -+ /* Bit 24 - Memory write to region 0 defined by MC registers. */ -+ FBC_IDLE_FORCE_MEMORY_WRITE_TO_REGION0 = 0x01000000, -+ /* Bit 25 - Memory write to region 1 defined by MC registers */ -+ FBC_IDLE_FORCE_MEMORY_WRITE_TO_REGION1 = 0x02000000, -+ /* Bit 26 - Memory write to region 2 defined by MC registers */ -+ FBC_IDLE_FORCE_MEMORY_WRITE_TO_REGION2 = 0x04000000, -+ /* Bit 27 - Memory write to region 3 defined by MC registers. */ -+ FBC_IDLE_FORCE_MEMORY_WRITE_TO_REGION3 = 0x08000000, -+ -+ /* Bit 28 - Memory write from any client other than MCIF */ -+ FBC_IDLE_FORCE_MEMORY_WRITE_OTHER_THAN_MCIF = 0x10000000, -+ /* Bit 29 - CG statics screen signal is inactive */ -+ FBC_IDLE_FORCE_CG_STATIC_SCREEN_IS_INACTIVE = 0x20000000, -+}; -+ -+static uint32_t lpt_size_alignment(struct dce112_compressor *cp110) -+{ -+ /*LPT_ALIGNMENT (in bytes) = ROW_SIZE * #BANKS * # DRAM CHANNELS. */ -+ return cp110->base.raw_size * cp110->base.banks_num * -+ cp110->base.dram_channels_num; -+} -+ -+static uint32_t lpt_memory_control_config(struct dce112_compressor *cp110, -+ uint32_t lpt_control) -+{ -+ /*LPT MC Config */ -+ if (cp110->base.options.bits.LPT_MC_CONFIG == 1) { -+ /* POSSIBLE VALUES for LPT NUM_PIPES (DRAM CHANNELS): -+ * 00 - 1 CHANNEL -+ * 01 - 2 CHANNELS -+ * 02 - 4 OR 6 CHANNELS -+ * (Only for discrete GPU, N/A for CZ) -+ * 03 - 8 OR 12 CHANNELS -+ * (Only for discrete GPU, N/A for CZ) */ -+ switch (cp110->base.dram_channels_num) { -+ case 2: -+ set_reg_field_value( -+ lpt_control, -+ 1, -+ LOW_POWER_TILING_CONTROL, -+ LOW_POWER_TILING_NUM_PIPES); -+ break; -+ case 1: -+ set_reg_field_value( -+ lpt_control, -+ 0, -+ LOW_POWER_TILING_CONTROL, -+ LOW_POWER_TILING_NUM_PIPES); -+ break; -+ default: -+ dal_logger_write( -+ cp110->base.ctx->logger, -+ LOG_MAJOR_WARNING, -+ LOG_MINOR_COMPONENT_CONTROLLER, -+ "%s: Invalid LPT NUM_PIPES!!!", -+ __func__); -+ break; -+ } -+ -+ /* The mapping for LPT NUM_BANKS is in -+ * GRPH_CONTROL.GRPH_NUM_BANKS register field -+ * Specifies the number of memory banks for tiling -+ * purposes. Only applies to 2D and 3D tiling modes. -+ * POSSIBLE VALUES: -+ * 00 - DCP_GRPH_NUM_BANKS_2BANK: ADDR_SURF_2_BANK -+ * 01 - DCP_GRPH_NUM_BANKS_4BANK: ADDR_SURF_4_BANK -+ * 02 - DCP_GRPH_NUM_BANKS_8BANK: ADDR_SURF_8_BANK -+ * 03 - DCP_GRPH_NUM_BANKS_16BANK: ADDR_SURF_16_BANK */ -+ switch (cp110->base.banks_num) { -+ case 16: -+ set_reg_field_value( -+ lpt_control, -+ 3, -+ LOW_POWER_TILING_CONTROL, -+ LOW_POWER_TILING_NUM_BANKS); -+ break; -+ case 8: -+ set_reg_field_value( -+ lpt_control, -+ 2, -+ LOW_POWER_TILING_CONTROL, -+ LOW_POWER_TILING_NUM_BANKS); -+ break; -+ case 4: -+ set_reg_field_value( -+ lpt_control, -+ 1, -+ LOW_POWER_TILING_CONTROL, -+ LOW_POWER_TILING_NUM_BANKS); -+ break; -+ case 2: -+ set_reg_field_value( -+ lpt_control, -+ 0, -+ LOW_POWER_TILING_CONTROL, -+ LOW_POWER_TILING_NUM_BANKS); -+ break; -+ default: -+ dal_logger_write( -+ cp110->base.ctx->logger, -+ LOG_MAJOR_WARNING, -+ LOG_MINOR_COMPONENT_CONTROLLER, -+ "%s: Invalid LPT NUM_BANKS!!!", -+ __func__); -+ break; -+ } -+ -+ /* The mapping is in DMIF_ADDR_CALC. -+ * ADDR_CONFIG_PIPE_INTERLEAVE_SIZE register field for -+ * Carrizo specifies the memory interleave per pipe. -+ * It effectively specifies the location of pipe bits in -+ * the memory address. -+ * POSSIBLE VALUES: -+ * 00 - ADDR_CONFIG_PIPE_INTERLEAVE_256B: 256 byte -+ * interleave -+ * 01 - ADDR_CONFIG_PIPE_INTERLEAVE_512B: 512 byte -+ * interleave -+ */ -+ switch (cp110->base.channel_interleave_size) { -+ case 256: /*256B */ -+ set_reg_field_value( -+ lpt_control, -+ 0, -+ LOW_POWER_TILING_CONTROL, -+ LOW_POWER_TILING_PIPE_INTERLEAVE_SIZE); -+ break; -+ case 512: /*512B */ -+ set_reg_field_value( -+ lpt_control, -+ 1, -+ LOW_POWER_TILING_CONTROL, -+ LOW_POWER_TILING_PIPE_INTERLEAVE_SIZE); -+ break; -+ default: -+ dal_logger_write( -+ cp110->base.ctx->logger, -+ LOG_MAJOR_WARNING, -+ LOG_MINOR_COMPONENT_CONTROLLER, -+ "%s: Invalid LPT INTERLEAVE_SIZE!!!", -+ __func__); -+ break; -+ } -+ -+ /* The mapping for LOW_POWER_TILING_ROW_SIZE is in -+ * DMIF_ADDR_CALC.ADDR_CONFIG_ROW_SIZE register field -+ * for Carrizo. Specifies the size of dram row in bytes. -+ * This should match up with NOOFCOLS field in -+ * MC_ARB_RAMCFG (ROW_SIZE = 4 * 2 ^^ columns). -+ * This register DMIF_ADDR_CALC is not used by the -+ * hardware as it is only used for addrlib assertions. -+ * POSSIBLE VALUES: -+ * 00 - ADDR_CONFIG_1KB_ROW: Treat 1KB as DRAM row -+ * boundary -+ * 01 - ADDR_CONFIG_2KB_ROW: Treat 2KB as DRAM row -+ * boundary -+ * 02 - ADDR_CONFIG_4KB_ROW: Treat 4KB as DRAM row -+ * boundary */ -+ switch (cp110->base.raw_size) { -+ case 4096: /*4 KB */ -+ set_reg_field_value( -+ lpt_control, -+ 2, -+ LOW_POWER_TILING_CONTROL, -+ LOW_POWER_TILING_ROW_SIZE); -+ break; -+ case 2048: -+ set_reg_field_value( -+ lpt_control, -+ 1, -+ LOW_POWER_TILING_CONTROL, -+ LOW_POWER_TILING_ROW_SIZE); -+ break; -+ case 1024: -+ set_reg_field_value( -+ lpt_control, -+ 0, -+ LOW_POWER_TILING_CONTROL, -+ LOW_POWER_TILING_ROW_SIZE); -+ break; -+ default: -+ dal_logger_write( -+ cp110->base.ctx->logger, -+ LOG_MAJOR_WARNING, -+ LOG_MINOR_COMPONENT_CONTROLLER, -+ "%s: Invalid LPT ROW_SIZE!!!", -+ __func__); -+ break; -+ } -+ } else { -+ dal_logger_write( -+ cp110->base.ctx->logger, -+ LOG_MAJOR_WARNING, -+ LOG_MINOR_COMPONENT_CONTROLLER, -+ "%s: LPT MC Configuration is not provided", -+ __func__); -+ } -+ -+ return lpt_control; -+} -+ -+static bool is_source_bigger_than_epanel_size( -+ struct dce112_compressor *cp110, -+ uint32_t source_view_width, -+ uint32_t source_view_height) -+{ -+ if (cp110->base.embedded_panel_h_size != 0 && -+ cp110->base.embedded_panel_v_size != 0 && -+ ((source_view_width * source_view_height) > -+ (cp110->base.embedded_panel_h_size * -+ cp110->base.embedded_panel_v_size))) -+ return true; -+ -+ return false; -+} -+ -+static uint32_t align_to_chunks_number_per_line( -+ struct dce112_compressor *cp110, -+ uint32_t pixels) -+{ -+ return 256 * ((pixels + 255) / 256); -+} -+ -+static void wait_for_fbc_state_changed( -+ struct dce112_compressor *cp110, -+ bool enabled) -+{ -+ uint8_t counter = 0; -+ uint32_t addr = mmFBC_STATUS; -+ uint32_t value; -+ -+ while (counter < 10) { -+ value = dm_read_reg(cp110->base.ctx, addr); -+ if (get_reg_field_value( -+ value, -+ FBC_STATUS, -+ FBC_ENABLE_STATUS) == enabled) -+ break; -+ udelay(10); -+ counter++; -+ } -+ -+ if (counter == 10) { -+ dal_logger_write( -+ cp110->base.ctx->logger, -+ LOG_MAJOR_WARNING, -+ LOG_MINOR_COMPONENT_CONTROLLER, -+ "%s: wait counter exceeded, changes to HW not applied", -+ __func__); -+ } -+} -+ -+void dce112_compressor_power_up_fbc(struct compressor *compressor) -+{ -+ uint32_t value; -+ uint32_t addr; -+ -+ addr = mmFBC_CNTL; -+ value = dm_read_reg(compressor->ctx, addr); -+ set_reg_field_value(value, 0, FBC_CNTL, FBC_GRPH_COMP_EN); -+ set_reg_field_value(value, 1, FBC_CNTL, FBC_EN); -+ set_reg_field_value(value, 2, FBC_CNTL, FBC_COHERENCY_MODE); -+ if (compressor->options.bits.CLK_GATING_DISABLED == 1) { -+ /* HW needs to do power measurement comparison. */ -+ set_reg_field_value( -+ value, -+ 0, -+ FBC_CNTL, -+ FBC_COMP_CLK_GATE_EN); -+ } -+ dm_write_reg(compressor->ctx, addr, value); -+ -+ addr = mmFBC_COMP_MODE; -+ value = dm_read_reg(compressor->ctx, addr); -+ set_reg_field_value(value, 1, FBC_COMP_MODE, FBC_RLE_EN); -+ set_reg_field_value(value, 1, FBC_COMP_MODE, FBC_DPCM4_RGB_EN); -+ set_reg_field_value(value, 1, FBC_COMP_MODE, FBC_IND_EN); -+ dm_write_reg(compressor->ctx, addr, value); -+ -+ addr = mmFBC_COMP_CNTL; -+ value = dm_read_reg(compressor->ctx, addr); -+ set_reg_field_value(value, 1, FBC_COMP_CNTL, FBC_DEPTH_RGB08_EN); -+ dm_write_reg(compressor->ctx, addr, value); -+ /*FBC_MIN_COMPRESSION 0 ==> 2:1 */ -+ /* 1 ==> 4:1 */ -+ /* 2 ==> 8:1 */ -+ /* 0xF ==> 1:1 */ -+ set_reg_field_value(value, 0xF, FBC_COMP_CNTL, FBC_MIN_COMPRESSION); -+ dm_write_reg(compressor->ctx, addr, value); -+ compressor->min_compress_ratio = FBC_COMPRESS_RATIO_1TO1; -+ -+ value = 0; -+ dm_write_reg(compressor->ctx, mmFBC_IND_LUT0, value); -+ -+ value = 0xFFFFFF; -+ dm_write_reg(compressor->ctx, mmFBC_IND_LUT1, value); -+} -+ -+void dce112_compressor_enable_fbc( -+ struct compressor *compressor, -+ uint32_t paths_num, -+ struct compr_addr_and_pitch_params *params) -+{ -+ struct dce112_compressor *cp110 = TO_DCE112_COMPRESSOR(compressor); -+ -+ if (compressor->options.bits.FBC_SUPPORT && -+ (compressor->options.bits.DUMMY_BACKEND == 0) && -+ (!dce112_compressor_is_fbc_enabled_in_hw(compressor, NULL)) && -+ (!is_source_bigger_than_epanel_size( -+ cp110, -+ params->source_view_width, -+ params->source_view_height))) { -+ -+ uint32_t addr; -+ uint32_t value; -+ -+ /* Before enabling FBC first need to enable LPT if applicable -+ * LPT state should always be changed (enable/disable) while FBC -+ * is disabled */ -+ if (compressor->options.bits.LPT_SUPPORT && (paths_num < 2) && -+ (params->source_view_width * -+ params->source_view_height <= -+ dce11_one_lpt_channel_max_resolution)) { -+ dce112_compressor_enable_lpt(compressor); -+ } -+ -+ addr = mmFBC_CNTL; -+ value = dm_read_reg(compressor->ctx, addr); -+ set_reg_field_value(value, 1, FBC_CNTL, FBC_GRPH_COMP_EN); -+ set_reg_field_value( -+ value, -+ params->inst, -+ FBC_CNTL, FBC_SRC_SEL); -+ dm_write_reg(compressor->ctx, addr, value); -+ -+ /* Keep track of enum controller_id FBC is attached to */ -+ compressor->is_enabled = true; -+ compressor->attached_inst = params->inst; -+ cp110->offsets = reg_offsets[params->inst - 1]; -+ -+ /*Toggle it as there is bug in HW */ -+ set_reg_field_value(value, 0, FBC_CNTL, FBC_GRPH_COMP_EN); -+ dm_write_reg(compressor->ctx, addr, value); -+ set_reg_field_value(value, 1, FBC_CNTL, FBC_GRPH_COMP_EN); -+ dm_write_reg(compressor->ctx, addr, value); -+ -+ wait_for_fbc_state_changed(cp110, true); -+ } -+} -+ -+void dce112_compressor_disable_fbc(struct compressor *compressor) -+{ -+ struct dce112_compressor *cp110 = TO_DCE112_COMPRESSOR(compressor); -+ -+ if (compressor->options.bits.FBC_SUPPORT && -+ dce112_compressor_is_fbc_enabled_in_hw(compressor, NULL)) { -+ uint32_t reg_data; -+ /* Turn off compression */ -+ reg_data = dm_read_reg(compressor->ctx, mmFBC_CNTL); -+ set_reg_field_value(reg_data, 0, FBC_CNTL, FBC_GRPH_COMP_EN); -+ dm_write_reg(compressor->ctx, mmFBC_CNTL, reg_data); -+ -+ /* Reset enum controller_id to undefined */ -+ compressor->attached_inst = 0; -+ compressor->is_enabled = false; -+ -+ /* Whenever disabling FBC make sure LPT is disabled if LPT -+ * supported */ -+ if (compressor->options.bits.LPT_SUPPORT) -+ dce112_compressor_disable_lpt(compressor); -+ -+ wait_for_fbc_state_changed(cp110, false); -+ } -+} -+ -+bool dce112_compressor_is_fbc_enabled_in_hw( -+ struct compressor *compressor, -+ uint32_t *inst) -+{ -+ /* Check the hardware register */ -+ uint32_t value; -+ -+ value = dm_read_reg(compressor->ctx, mmFBC_STATUS); -+ if (get_reg_field_value(value, FBC_STATUS, FBC_ENABLE_STATUS)) { -+ if (inst != NULL) -+ *inst = compressor->attached_inst; -+ return true; -+ } -+ -+ value = dm_read_reg(compressor->ctx, mmFBC_MISC); -+ if (get_reg_field_value(value, FBC_MISC, FBC_STOP_ON_HFLIP_EVENT)) { -+ value = dm_read_reg(compressor->ctx, mmFBC_CNTL); -+ -+ if (get_reg_field_value(value, FBC_CNTL, FBC_GRPH_COMP_EN)) { -+ if (inst != NULL) -+ *inst = -+ compressor->attached_inst; -+ return true; -+ } -+ } -+ return false; -+} -+ -+bool dce112_compressor_is_lpt_enabled_in_hw(struct compressor *compressor) -+{ -+ /* Check the hardware register */ -+ uint32_t value = dm_read_reg(compressor->ctx, -+ mmLOW_POWER_TILING_CONTROL); -+ -+ return get_reg_field_value( -+ value, -+ LOW_POWER_TILING_CONTROL, -+ LOW_POWER_TILING_ENABLE); -+} -+ -+void dce112_compressor_program_compressed_surface_address_and_pitch( -+ struct compressor *compressor, -+ struct compr_addr_and_pitch_params *params) -+{ -+ struct dce112_compressor *cp110 = TO_DCE112_COMPRESSOR(compressor); -+ uint32_t value = 0; -+ uint32_t fbc_pitch = 0; -+ uint32_t compressed_surf_address_low_part = -+ compressor->compr_surface_address.addr.low_part; -+ -+ /* Clear content first. */ -+ dm_write_reg( -+ compressor->ctx, -+ DCP_REG(mmGRPH_COMPRESS_SURFACE_ADDRESS_HIGH), -+ 0); -+ dm_write_reg(compressor->ctx, -+ DCP_REG(mmGRPH_COMPRESS_SURFACE_ADDRESS), 0); -+ -+ if (compressor->options.bits.LPT_SUPPORT) { -+ uint32_t lpt_alignment = lpt_size_alignment(cp110); -+ -+ if (lpt_alignment != 0) { -+ compressed_surf_address_low_part = -+ ((compressed_surf_address_low_part -+ + (lpt_alignment - 1)) / lpt_alignment) -+ * lpt_alignment; -+ } -+ } -+ -+ /* Write address, HIGH has to be first. */ -+ dm_write_reg(compressor->ctx, -+ DCP_REG(mmGRPH_COMPRESS_SURFACE_ADDRESS_HIGH), -+ compressor->compr_surface_address.addr.high_part); -+ dm_write_reg(compressor->ctx, -+ DCP_REG(mmGRPH_COMPRESS_SURFACE_ADDRESS), -+ compressed_surf_address_low_part); -+ -+ fbc_pitch = align_to_chunks_number_per_line( -+ cp110, -+ params->source_view_width); -+ -+ if (compressor->min_compress_ratio == FBC_COMPRESS_RATIO_1TO1) -+ fbc_pitch = fbc_pitch / 8; -+ else -+ dal_logger_write( -+ compressor->ctx->logger, -+ LOG_MAJOR_WARNING, -+ LOG_MINOR_COMPONENT_CONTROLLER, -+ "%s: Unexpected DCE11 compression ratio", -+ __func__); -+ -+ /* Clear content first. */ -+ dm_write_reg(compressor->ctx, DCP_REG(mmGRPH_COMPRESS_PITCH), 0); -+ -+ /* Write FBC Pitch. */ -+ set_reg_field_value( -+ value, -+ fbc_pitch, -+ GRPH_COMPRESS_PITCH, -+ GRPH_COMPRESS_PITCH); -+ dm_write_reg(compressor->ctx, DCP_REG(mmGRPH_COMPRESS_PITCH), value); -+ -+} -+ -+void dce112_compressor_disable_lpt(struct compressor *compressor) -+{ -+ struct dce112_compressor *cp110 = TO_DCE112_COMPRESSOR(compressor); -+ uint32_t value; -+ uint32_t addr; -+ uint32_t inx; -+ -+ /* Disable all pipes LPT Stutter */ -+ for (inx = 0; inx < 3; inx++) { -+ value = -+ dm_read_reg( -+ compressor->ctx, -+ DMIF_REG(mmDPG_PIPE_STUTTER_CONTROL_NONLPTCH)); -+ set_reg_field_value( -+ value, -+ 0, -+ DPG_PIPE_STUTTER_CONTROL_NONLPTCH, -+ STUTTER_ENABLE_NONLPTCH); -+ dm_write_reg( -+ compressor->ctx, -+ DMIF_REG(mmDPG_PIPE_STUTTER_CONTROL_NONLPTCH), -+ value); -+ } -+ /* Disable Underlay pipe LPT Stutter */ -+ addr = mmDPGV0_PIPE_STUTTER_CONTROL_NONLPTCH; -+ value = dm_read_reg(compressor->ctx, addr); -+ set_reg_field_value( -+ value, -+ 0, -+ DPGV0_PIPE_STUTTER_CONTROL_NONLPTCH, -+ STUTTER_ENABLE_NONLPTCH); -+ dm_write_reg(compressor->ctx, addr, value); -+ -+ /* Disable LPT */ -+ addr = mmLOW_POWER_TILING_CONTROL; -+ value = dm_read_reg(compressor->ctx, addr); -+ set_reg_field_value( -+ value, -+ 0, -+ LOW_POWER_TILING_CONTROL, -+ LOW_POWER_TILING_ENABLE); -+ dm_write_reg(compressor->ctx, addr, value); -+ -+ /* Clear selection of Channel(s) containing Compressed Surface */ -+ addr = mmGMCON_LPT_TARGET; -+ value = dm_read_reg(compressor->ctx, addr); -+ set_reg_field_value( -+ value, -+ 0xFFFFFFFF, -+ GMCON_LPT_TARGET, -+ STCTRL_LPT_TARGET); -+ dm_write_reg(compressor->ctx, mmGMCON_LPT_TARGET, value); -+} -+ -+void dce112_compressor_enable_lpt(struct compressor *compressor) -+{ -+ struct dce112_compressor *cp110 = TO_DCE112_COMPRESSOR(compressor); -+ uint32_t value; -+ uint32_t addr; -+ uint32_t value_control; -+ uint32_t channels; -+ -+ /* Enable LPT Stutter from Display pipe */ -+ value = dm_read_reg(compressor->ctx, -+ DMIF_REG(mmDPG_PIPE_STUTTER_CONTROL_NONLPTCH)); -+ set_reg_field_value( -+ value, -+ 1, -+ DPG_PIPE_STUTTER_CONTROL_NONLPTCH, -+ STUTTER_ENABLE_NONLPTCH); -+ dm_write_reg(compressor->ctx, -+ DMIF_REG(mmDPG_PIPE_STUTTER_CONTROL_NONLPTCH), value); -+ -+ /* Enable Underlay pipe LPT Stutter */ -+ addr = mmDPGV0_PIPE_STUTTER_CONTROL_NONLPTCH; -+ value = dm_read_reg(compressor->ctx, addr); -+ set_reg_field_value( -+ value, -+ 1, -+ DPGV0_PIPE_STUTTER_CONTROL_NONLPTCH, -+ STUTTER_ENABLE_NONLPTCH); -+ dm_write_reg(compressor->ctx, addr, value); -+ -+ /* Selection of Channel(s) containing Compressed Surface: 0xfffffff -+ * will disable LPT. -+ * STCTRL_LPT_TARGETn corresponds to channel n. */ -+ addr = mmLOW_POWER_TILING_CONTROL; -+ value_control = dm_read_reg(compressor->ctx, addr); -+ channels = get_reg_field_value(value_control, -+ LOW_POWER_TILING_CONTROL, -+ LOW_POWER_TILING_MODE); -+ -+ addr = mmGMCON_LPT_TARGET; -+ value = dm_read_reg(compressor->ctx, addr); -+ set_reg_field_value( -+ value, -+ channels + 1, /* not mentioned in programming guide, -+ but follow DCE8.1 */ -+ GMCON_LPT_TARGET, -+ STCTRL_LPT_TARGET); -+ dm_write_reg(compressor->ctx, addr, value); -+ -+ /* Enable LPT */ -+ addr = mmLOW_POWER_TILING_CONTROL; -+ value = dm_read_reg(compressor->ctx, addr); -+ set_reg_field_value( -+ value, -+ 1, -+ LOW_POWER_TILING_CONTROL, -+ LOW_POWER_TILING_ENABLE); -+ dm_write_reg(compressor->ctx, addr, value); -+} -+ -+void dce112_compressor_program_lpt_control( -+ struct compressor *compressor, -+ struct compr_addr_and_pitch_params *params) -+{ -+ struct dce112_compressor *cp110 = TO_DCE112_COMPRESSOR(compressor); -+ uint32_t rows_per_channel; -+ uint32_t lpt_alignment; -+ uint32_t source_view_width; -+ uint32_t source_view_height; -+ uint32_t lpt_control = 0; -+ -+ if (!compressor->options.bits.LPT_SUPPORT) -+ return; -+ -+ lpt_control = dm_read_reg(compressor->ctx, -+ mmLOW_POWER_TILING_CONTROL); -+ -+ /* POSSIBLE VALUES for Low Power Tiling Mode: -+ * 00 - Use channel 0 -+ * 01 - Use Channel 0 and 1 -+ * 02 - Use Channel 0,1,2,3 -+ * 03 - reserved */ -+ switch (compressor->lpt_channels_num) { -+ /* case 2: -+ * Use Channel 0 & 1 / Not used for DCE 11 */ -+ case 1: -+ /*Use Channel 0 for LPT for DCE 11 */ -+ set_reg_field_value( -+ lpt_control, -+ 0, -+ LOW_POWER_TILING_CONTROL, -+ LOW_POWER_TILING_MODE); -+ break; -+ default: -+ dal_logger_write( -+ compressor->ctx->logger, -+ LOG_MAJOR_WARNING, -+ LOG_MINOR_COMPONENT_CONTROLLER, -+ "%s: Invalid selected DRAM channels for LPT!!!", -+ __func__); -+ break; -+ } -+ -+ lpt_control = lpt_memory_control_config(cp110, lpt_control); -+ -+ /* Program LOW_POWER_TILING_ROWS_PER_CHAN field which depends on -+ * FBC compressed surface pitch. -+ * LOW_POWER_TILING_ROWS_PER_CHAN = Roundup ((Surface Height * -+ * Surface Pitch) / (Row Size * Number of Channels * -+ * Number of Banks)). */ -+ rows_per_channel = 0; -+ lpt_alignment = lpt_size_alignment(cp110); -+ source_view_width = -+ align_to_chunks_number_per_line( -+ cp110, -+ params->source_view_width); -+ source_view_height = (params->source_view_height + 1) & (~0x1); -+ -+ if (lpt_alignment != 0) { -+ rows_per_channel = source_view_width * source_view_height * 4; -+ rows_per_channel = -+ (rows_per_channel % lpt_alignment) ? -+ (rows_per_channel / lpt_alignment + 1) : -+ rows_per_channel / lpt_alignment; -+ } -+ -+ set_reg_field_value( -+ lpt_control, -+ rows_per_channel, -+ LOW_POWER_TILING_CONTROL, -+ LOW_POWER_TILING_ROWS_PER_CHAN); -+ -+ dm_write_reg(compressor->ctx, -+ mmLOW_POWER_TILING_CONTROL, lpt_control); -+} -+ -+/* -+ * DCE 11 Frame Buffer Compression Implementation -+ */ -+ -+void dce112_compressor_set_fbc_invalidation_triggers( -+ struct compressor *compressor, -+ uint32_t fbc_trigger) -+{ -+ /* Disable region hit event, FBC_MEMORY_REGION_MASK = 0 (bits 16-19) -+ * for DCE 11 regions cannot be used - does not work with S/G -+ */ -+ uint32_t addr = mmFBC_CLIENT_REGION_MASK; -+ uint32_t value = dm_read_reg(compressor->ctx, addr); -+ -+ set_reg_field_value( -+ value, -+ 0, -+ FBC_CLIENT_REGION_MASK, -+ FBC_MEMORY_REGION_MASK); -+ dm_write_reg(compressor->ctx, addr, value); -+ -+ /* Setup events when to clear all CSM entries (effectively marking -+ * current compressed data invalid) -+ * For DCE 11 CSM metadata 11111 means - "Not Compressed" -+ * Used as the initial value of the metadata sent to the compressor -+ * after invalidation, to indicate that the compressor should attempt -+ * to compress all chunks on the current pass. Also used when the chunk -+ * is not successfully written to memory. -+ * When this CSM value is detected, FBC reads from the uncompressed -+ * buffer. Set events according to passed in value, these events are -+ * valid for DCE11: -+ * - bit 0 - display register updated -+ * - bit 28 - memory write from any client except from MCIF -+ * - bit 29 - CG static screen signal is inactive -+ * In addition, DCE11.1 also needs to set new DCE11.1 specific events -+ * that are used to trigger invalidation on certain register changes, -+ * for example enabling of Alpha Compression may trigger invalidation of -+ * FBC once bit is set. These events are as follows: -+ * - Bit 2 - FBC_GRPH_COMP_EN register updated -+ * - Bit 3 - FBC_SRC_SEL register updated -+ * - Bit 4 - FBC_MIN_COMPRESSION register updated -+ * - Bit 5 - FBC_ALPHA_COMP_EN register updated -+ * - Bit 6 - FBC_ZERO_ALPHA_CHUNK_SKIP_EN register updated -+ * - Bit 7 - FBC_FORCE_COPY_TO_COMP_BUF register updated -+ */ -+ addr = mmFBC_IDLE_FORCE_CLEAR_MASK; -+ value = dm_read_reg(compressor->ctx, addr); -+ set_reg_field_value( -+ value, -+ fbc_trigger | -+ FBC_IDLE_FORCE_GRPH_COMP_EN | -+ FBC_IDLE_FORCE_SRC_SEL_CHANGE | -+ FBC_IDLE_FORCE_MIN_COMPRESSION_CHANGE | -+ FBC_IDLE_FORCE_ALPHA_COMP_EN | -+ FBC_IDLE_FORCE_ZERO_ALPHA_CHUNK_SKIP_EN | -+ FBC_IDLE_FORCE_FORCE_COPY_TO_COMP_BUF, -+ FBC_IDLE_FORCE_CLEAR_MASK, -+ FBC_IDLE_FORCE_CLEAR_MASK); -+ dm_write_reg(compressor->ctx, addr, value); -+} -+ -+bool dce112_compressor_construct(struct dce112_compressor *compressor, -+ struct dc_context *ctx, struct adapter_service *as) -+{ -+ struct embedded_panel_info panel_info; -+ -+ compressor->base.options.bits.FBC_SUPPORT = true; -+ if (!(dal_adapter_service_is_feature_supported( -+ FEATURE_DISABLE_LPT_SUPPORT))) -+ compressor->base.options.bits.LPT_SUPPORT = true; -+ /* For DCE 11 always use one DRAM channel for LPT */ -+ compressor->base.lpt_channels_num = 1; -+ -+ if (dal_adapter_service_is_feature_supported(FEATURE_DUMMY_FBC_BACKEND)) -+ compressor->base.options.bits.DUMMY_BACKEND = true; -+ -+ /* Check if this system has more than 1 DRAM channel; if only 1 then LPT -+ * should not be supported */ -+ if (compressor->base.memory_bus_width == 64) -+ compressor->base.options.bits.LPT_SUPPORT = false; -+ -+ if (dal_adapter_service_is_feature_supported( -+ FEATURE_DISABLE_FBC_COMP_CLK_GATE)) -+ compressor->base.options.bits.CLK_GATING_DISABLED = true; -+ -+ compressor->base.ctx = ctx; -+ compressor->base.embedded_panel_h_size = 0; -+ compressor->base.embedded_panel_v_size = 0; -+ compressor->base.memory_bus_width = -+ dal_adapter_service_get_asic_vram_bit_width(as); -+ compressor->base.allocated_size = 0; -+ compressor->base.preferred_requested_size = 0; -+ compressor->base.min_compress_ratio = FBC_COMPRESS_RATIO_INVALID; -+ compressor->base.options.raw = 0; -+ compressor->base.banks_num = 0; -+ compressor->base.raw_size = 0; -+ compressor->base.channel_interleave_size = 0; -+ compressor->base.dram_channels_num = 0; -+ compressor->base.lpt_channels_num = 0; -+ compressor->base.attached_inst = 0; -+ compressor->base.is_enabled = false; -+ -+ if (dal_adapter_service_get_embedded_panel_info(as, -+ &panel_info)) { -+ compressor->base.embedded_panel_h_size = -+ panel_info.lcd_timing.horizontal_addressable; -+ compressor->base.embedded_panel_v_size = -+ panel_info.lcd_timing.vertical_addressable; -+ } -+ return true; -+} -+ -+struct compressor *dce112_compressor_create(struct dc_context *ctx, -+ struct adapter_service *as) -+{ -+ struct dce112_compressor *cp110 = -+ dm_alloc(sizeof(struct dce112_compressor)); -+ -+ if (!cp110) -+ return NULL; -+ -+ if (dce112_compressor_construct(cp110, ctx, as)) -+ return &cp110->base; -+ -+ BREAK_TO_DEBUGGER(); -+ dm_free(cp110); -+ return NULL; -+} -+ -+void dce112_compressor_destroy(struct compressor **compressor) -+{ -+ dm_free(TO_DCE112_COMPRESSOR(*compressor)); -+ *compressor = NULL; -+} -diff --git a/drivers/gpu/drm/amd/dal/dc/dce112/dce112_compressor.h b/drivers/gpu/drm/amd/dal/dc/dce112/dce112_compressor.h -new file mode 100644 -index 0000000..bcf4480 ---- /dev/null -+++ b/drivers/gpu/drm/amd/dal/dc/dce112/dce112_compressor.h -@@ -0,0 +1,84 @@ -+/* Copyright 2012-15 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 __DC_COMPRESSOR_DCE112_H__ -+#define __DC_COMPRESSOR_DCE112_H__ -+ -+#include "../inc/compressor.h" -+ -+#define TO_DCE112_COMPRESSOR(compressor)\ -+ container_of(compressor, struct dce112_compressor, base) -+ -+struct dce112_compressor_reg_offsets { -+ uint32_t dcp_offset; -+ uint32_t dmif_offset; -+}; -+ -+struct dce112_compressor { -+ struct compressor base; -+ struct dce112_compressor_reg_offsets offsets; -+}; -+ -+struct compressor *dce112_compressor_create(struct dc_context *ctx, -+ struct adapter_service *as); -+ -+bool dce112_compressor_construct(struct dce112_compressor *cp110, -+ struct dc_context *ctx, struct adapter_service *as); -+ -+void dce112_compressor_destroy(struct compressor **cp); -+ -+/* FBC RELATED */ -+void dce112_compressor_power_up_fbc(struct compressor *cp); -+ -+void dce112_compressor_enable_fbc(struct compressor *cp, uint32_t paths_num, -+ struct compr_addr_and_pitch_params *params); -+ -+void dce112_compressor_disable_fbc(struct compressor *cp); -+ -+void dce112_compressor_set_fbc_invalidation_triggers(struct compressor *cp, -+ uint32_t fbc_trigger); -+ -+void dce112_compressor_program_compressed_surface_address_and_pitch( -+ struct compressor *cp, -+ struct compr_addr_and_pitch_params *params); -+ -+bool dce112_compressor_get_required_compressed_surface_size( -+ struct compressor *cp, -+ struct fbc_input_info *input_info, -+ struct fbc_requested_compressed_size *size); -+ -+bool dce112_compressor_is_fbc_enabled_in_hw(struct compressor *cp, -+ uint32_t *fbc_mapped_crtc_id); -+ -+/* LPT RELATED */ -+void dce112_compressor_enable_lpt(struct compressor *cp); -+ -+void dce112_compressor_disable_lpt(struct compressor *cp); -+ -+void dce112_compressor_program_lpt_control(struct compressor *cp, -+ struct compr_addr_and_pitch_params *params); -+ -+bool dce112_compressor_is_lpt_enabled_in_hw(struct compressor *cp); -+ -+#endif -diff --git a/drivers/gpu/drm/amd/dal/dc/dce112/dce112_hw_sequencer.c b/drivers/gpu/drm/amd/dal/dc/dce112/dce112_hw_sequencer.c -new file mode 100644 -index 0000000..b94130f ---- /dev/null -+++ b/drivers/gpu/drm/amd/dal/dc/dce112/dce112_hw_sequencer.c -@@ -0,0 +1,178 @@ -+/* -+ * Copyright 2015 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 "dm_services.h" -+#include "dc.h" -+#include "core_dc.h" -+#include "core_types.h" -+#include "dce112_hw_sequencer.h" -+ -+#include "dce110/dce110_hw_sequencer.h" -+#include "gpu/dce112/dc_clock_gating_dce112.h" -+ -+/* include DCE11.2 register header files */ -+#include "dce/dce_11_2_d.h" -+#include "dce/dce_11_2_sh_mask.h" -+ -+static void dce112_crtc_switch_to_clk_src( -+ struct clock_source *clk_src, uint8_t crtc_inst) -+{ -+ uint32_t pixel_rate_cntl_value; -+ uint32_t addr; -+ -+ addr = mmCRTC0_PIXEL_RATE_CNTL + crtc_inst * -+ (mmCRTC1_PIXEL_RATE_CNTL - mmCRTC0_PIXEL_RATE_CNTL); -+ -+ pixel_rate_cntl_value = dm_read_reg(clk_src->ctx, addr); -+ -+ if (clk_src->id == CLOCK_SOURCE_ID_DP_DTO) -+ set_reg_field_value(pixel_rate_cntl_value, 1, -+ CRTC0_PIXEL_RATE_CNTL, DP_DTO0_ENABLE); -+ else { -+ set_reg_field_value(pixel_rate_cntl_value, -+ 0, -+ CRTC0_PIXEL_RATE_CNTL, -+ DP_DTO0_ENABLE); -+ -+ set_reg_field_value(pixel_rate_cntl_value, -+ clk_src->id - 1, -+ CRTC0_PIXEL_RATE_CNTL, -+ CRTC0_PIXEL_RATE_SOURCE); -+ } -+ dm_write_reg(clk_src->ctx, addr, pixel_rate_cntl_value); -+} -+ -+static void dce112_init_pte(struct dc_context *ctx) -+{ -+ uint32_t addr; -+ uint32_t value = 0; -+ uint32_t chunk_int = 0; -+ uint32_t chunk_mul = 0; -+ -+ addr = mmUNP_DVMM_PTE_CONTROL; -+ value = dm_read_reg(ctx, addr); -+ -+ set_reg_field_value( -+ value, -+ 0, -+ DVMM_PTE_CONTROL, -+ DVMM_USE_SINGLE_PTE); -+ -+ set_reg_field_value( -+ value, -+ 1, -+ DVMM_PTE_CONTROL, -+ DVMM_PTE_BUFFER_MODE0); -+ -+ set_reg_field_value( -+ value, -+ 1, -+ DVMM_PTE_CONTROL, -+ DVMM_PTE_BUFFER_MODE1); -+ -+ dm_write_reg(ctx, addr, value); -+ -+ addr = mmDVMM_PTE_REQ; -+ value = dm_read_reg(ctx, addr); -+ -+ chunk_int = get_reg_field_value( -+ value, -+ DVMM_PTE_REQ, -+ HFLIP_PTEREQ_PER_CHUNK_INT); -+ -+ chunk_mul = get_reg_field_value( -+ value, -+ DVMM_PTE_REQ, -+ HFLIP_PTEREQ_PER_CHUNK_MULTIPLIER); -+ -+ if (chunk_int != 0x4 || chunk_mul != 0x4) { -+ -+ set_reg_field_value( -+ value, -+ 255, -+ DVMM_PTE_REQ, -+ MAX_PTEREQ_TO_ISSUE); -+ -+ set_reg_field_value( -+ value, -+ 4, -+ DVMM_PTE_REQ, -+ HFLIP_PTEREQ_PER_CHUNK_INT); -+ -+ set_reg_field_value( -+ value, -+ 4, -+ DVMM_PTE_REQ, -+ HFLIP_PTEREQ_PER_CHUNK_MULTIPLIER); -+ -+ dm_write_reg(ctx, addr, value); -+ } -+} -+ -+static bool dce112_enable_display_power_gating( -+ struct dc_context *ctx, -+ uint8_t controller_id, -+ struct dc_bios *dcb, -+ enum pipe_gating_control power_gating) -+{ -+ enum bp_result bp_result = BP_RESULT_OK; -+ enum bp_pipe_control_action cntl; -+ -+ if (IS_FPGA_MAXIMUS_DC(ctx->dce_environment)) -+ return true; -+ -+ if (power_gating == PIPE_GATING_CONTROL_INIT) -+ cntl = ASIC_PIPE_INIT; -+ else if (power_gating == PIPE_GATING_CONTROL_ENABLE) -+ cntl = ASIC_PIPE_ENABLE; -+ else -+ cntl = ASIC_PIPE_DISABLE; -+ -+ if (power_gating != PIPE_GATING_CONTROL_INIT || controller_id == 0) -+ bp_result = dcb->funcs->enable_disp_power_gating( -+ dcb, controller_id + 1, cntl); -+ -+ if (power_gating != PIPE_GATING_CONTROL_ENABLE) -+ dce112_init_pte(ctx); -+ -+ if (bp_result == BP_RESULT_OK) -+ return true; -+ else -+ return false; -+} -+ -+bool dce112_hw_sequencer_construct(struct core_dc *dc) -+{ -+ /* All registers used by dce11.2 match those in dce11 in offset and -+ * structure -+ */ -+ dce110_hw_sequencer_construct(dc); -+ dc->hwss.crtc_switch_to_clk_src = dce112_crtc_switch_to_clk_src; -+ dc->hwss.enable_display_power_gating = dce112_enable_display_power_gating; -+ dc->hwss.clock_gating_power_up = dal_dc_clock_gating_dce112_power_up; -+ -+ return true; -+} -+ -diff --git a/drivers/gpu/drm/amd/dal/dc/dce112/dce112_hw_sequencer.h b/drivers/gpu/drm/amd/dal/dc/dce112/dce112_hw_sequencer.h -new file mode 100644 -index 0000000..d96c582 ---- /dev/null -+++ b/drivers/gpu/drm/amd/dal/dc/dce112/dce112_hw_sequencer.h -@@ -0,0 +1,36 @@ -+/* -+* Copyright 2012-15 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 __DC_HWSS_DCE112_H__ -+#define __DC_HWSS_DCE112_H__ -+ -+#include "core_types.h" -+ -+struct core_dc; -+ -+bool dce112_hw_sequencer_construct(struct core_dc *dc); -+ -+#endif /* __DC_HWSS_DCE112_H__ */ -+ -diff --git a/drivers/gpu/drm/amd/dal/dc/dce112/dce112_link_encoder.c b/drivers/gpu/drm/amd/dal/dc/dce112/dce112_link_encoder.c -new file mode 100644 -index 0000000..23e127c ---- /dev/null -+++ b/drivers/gpu/drm/amd/dal/dc/dce112/dce112_link_encoder.c -@@ -0,0 +1,116 @@ -+/* -+ * Copyright 2012-15 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 "dm_services.h" -+#include "core_types.h" -+#include "link_encoder.h" -+#include "stream_encoder.h" -+#include "dce112_link_encoder.h" -+#include "../dce110/dce110_link_encoder.h" -+#include "i2caux_interface.h" -+#include "dce/dce_11_2_sh_mask.h" -+ -+/* For current ASICs pixel clock - 600MHz */ -+#define MAX_ENCODER_CLK 600000 -+ -+#define DCE11_UNIPHY_MAX_PIXEL_CLK_IN_KHZ 600000 -+ -+#define DEFAULT_AUX_MAX_DATA_SIZE 16 -+#define AUX_MAX_DEFER_WRITE_RETRY 20 -+ -+/* all values are in milliseconds */ -+/* For eDP, after power-up/power/down, -+ * 300/500 msec max. delay from LCDVCC to black video generation */ -+#define PANEL_POWER_UP_TIMEOUT 300 -+#define PANEL_POWER_DOWN_TIMEOUT 500 -+#define HPD_CHECK_INTERVAL 10 -+ -+/* Minimum pixel clock, in KHz. For TMDS signal is 25.00 MHz */ -+#define TMDS_MIN_PIXEL_CLOCK 25000 -+/* Maximum pixel clock, in KHz. For TMDS signal is 165.00 MHz */ -+#define TMDS_MAX_PIXEL_CLOCK 165000 -+/* For current ASICs pixel clock - 600MHz */ -+#define MAX_ENCODER_CLOCK 600000 -+ -+enum { -+ DP_MST_UPDATE_MAX_RETRY = 50 -+}; -+ -+static void dce112_link_encoder_dp_set_phy_pattern( -+ struct link_encoder *enc, -+ const struct encoder_set_dp_phy_pattern_param *param) -+{ -+ switch (param->dp_phy_pattern) { -+ case DP_TEST_PATTERN_TRAINING_PATTERN4: -+ dce110_link_encoder_set_dp_phy_pattern_training_pattern(enc, 3); -+ break; -+ default: -+ dce110_link_encoder_dp_set_phy_pattern(enc, param); -+ break; -+ } -+} -+ -+static struct link_encoder_funcs dce112_lnk_enc_funcs = { -+ .validate_output_with_stream = -+ dce110_link_encoder_validate_output_with_stream, -+ .hw_init = dce110_link_encoder_hw_init, -+ .setup = dce110_link_encoder_setup, -+ .enable_tmds_output = dce110_link_encoder_enable_tmds_output, -+ .enable_dp_output = dce110_link_encoder_enable_dp_output, -+ .enable_dp_mst_output = dce110_link_encoder_enable_dp_mst_output, -+ .disable_output = dce110_link_encoder_disable_output, -+ .dp_set_lane_settings = dce110_link_encoder_dp_set_lane_settings, -+ .dp_set_phy_pattern = dce112_link_encoder_dp_set_phy_pattern, -+ .update_mst_stream_allocation_table = -+ dce110_link_encoder_update_mst_stream_allocation_table, -+ .set_lcd_backlight_level = dce110_link_encoder_set_lcd_backlight_level, -+ .backlight_control = dce110_link_encoder_edp_backlight_control, -+ .power_control = dce110_link_encoder_edp_power_control, -+ .connect_dig_be_to_fe = dce110_link_encoder_connect_dig_be_to_fe, -+ .destroy = dce110_link_encoder_destroy -+}; -+ -+bool dce112_link_encoder_construct( -+ struct dce110_link_encoder *enc110, -+ const struct encoder_init_data *init_data, -+ const struct dce110_link_enc_registers *link_regs, -+ const struct dce110_link_enc_aux_registers *aux_regs, -+ const struct dce110_link_enc_bl_registers *bl_regs) -+{ -+ dce110_link_encoder_construct( -+ enc110, -+ init_data, -+ link_regs, -+ aux_regs, -+ bl_regs); -+ -+ enc110->base.funcs = &dce112_lnk_enc_funcs; -+ -+ enc110->base.features.flags.bits.IS_HBR3_CAPABLE = true; -+ -+ enc110->base.features.flags.bits.IS_TPS4_CAPABLE = true; -+ -+ return true; -+} -diff --git a/drivers/gpu/drm/amd/dal/dc/dce112/dce112_link_encoder.h b/drivers/gpu/drm/amd/dal/dc/dce112/dce112_link_encoder.h -new file mode 100644 -index 0000000..cfc9cc5 ---- /dev/null -+++ b/drivers/gpu/drm/amd/dal/dc/dce112/dce112_link_encoder.h -@@ -0,0 +1,41 @@ -+/* -+ * Copyright 2012-15 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 __DC_LINK_ENCODER__DCE112_H__ -+#define __DC_LINK_ENCODER__DCE112_H__ -+ -+#include "link_encoder.h" -+#include "../dce110/dce110_link_encoder.h" -+ -+bool dce112_link_encoder_construct( -+ struct dce110_link_encoder *enc110, -+ const struct encoder_init_data *init_data, -+ const struct dce110_link_enc_registers *link_regs, -+ const struct dce110_link_enc_aux_registers *aux_regs, -+ const struct dce110_link_enc_bl_registers *bl_regs); -+ -+/****************** HW programming ************************/ -+ -+#endif /* __DC_LINK_ENCODER__DCE112_H__ */ -diff --git a/drivers/gpu/drm/amd/dal/dc/dce112/dce112_mem_input.c b/drivers/gpu/drm/amd/dal/dc/dce112/dce112_mem_input.c -new file mode 100644 -index 0000000..823849e ---- /dev/null -+++ b/drivers/gpu/drm/amd/dal/dc/dce112/dce112_mem_input.c -@@ -0,0 +1,455 @@ -+/* -+ * Copyright 2012-15 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 "dm_services.h" -+#include "dce112_mem_input.h" -+ -+ -+#include "dce/dce_11_2_d.h" -+#include "dce/dce_11_2_sh_mask.h" -+ -+ -+#define DCP_REG(reg) (reg + mem_input110->offsets.dcp) -+#define DMIF_REG(reg) (reg + mem_input110->offsets.dmif) -+#define PIPE_REG(reg) (reg + mem_input110->offsets.pipe) -+ -+static void program_urgency_watermark( -+ const struct dc_context *ctx, -+ const uint32_t offset, -+ struct bw_watermarks marks_low, -+ uint32_t total_dest_line_time_ns) -+{ -+ /* register value */ -+ uint32_t urgency_cntl = 0; -+ uint32_t wm_mask_cntl = 0; -+ -+ uint32_t urgency_addr = offset + mmDPG_PIPE_URGENCY_CONTROL; -+ uint32_t wm_addr = offset + mmDPG_WATERMARK_MASK_CONTROL; -+ -+ /*Write mask to enable reading/writing of watermark set A*/ -+ wm_mask_cntl = dm_read_reg(ctx, wm_addr); -+ set_reg_field_value(wm_mask_cntl, -+ 0, -+ DPG_WATERMARK_MASK_CONTROL, -+ URGENCY_WATERMARK_MASK); -+ dm_write_reg(ctx, wm_addr, wm_mask_cntl); -+ -+ urgency_cntl = dm_read_reg(ctx, urgency_addr); -+ -+ set_reg_field_value( -+ urgency_cntl, -+ marks_low.a_mark, -+ DPG_PIPE_URGENCY_CONTROL, -+ URGENCY_LOW_WATERMARK); -+ -+ set_reg_field_value( -+ urgency_cntl, -+ total_dest_line_time_ns, -+ DPG_PIPE_URGENCY_CONTROL, -+ URGENCY_HIGH_WATERMARK); -+ dm_write_reg(ctx, urgency_addr, urgency_cntl); -+ -+ /*Write mask to enable reading/writing of watermark set B*/ -+ wm_mask_cntl = dm_read_reg(ctx, wm_addr); -+ set_reg_field_value(wm_mask_cntl, -+ 1, -+ DPG_WATERMARK_MASK_CONTROL, -+ URGENCY_WATERMARK_MASK); -+ dm_write_reg(ctx, wm_addr, wm_mask_cntl); -+ -+ urgency_cntl = dm_read_reg(ctx, urgency_addr); -+ -+ set_reg_field_value(urgency_cntl, -+ marks_low.b_mark, -+ DPG_PIPE_URGENCY_CONTROL, -+ URGENCY_LOW_WATERMARK); -+ -+ set_reg_field_value(urgency_cntl, -+ total_dest_line_time_ns, -+ DPG_PIPE_URGENCY_CONTROL, -+ URGENCY_HIGH_WATERMARK); -+ dm_write_reg(ctx, urgency_addr, urgency_cntl); -+ -+ /*Write mask to enable reading/writing of watermark set C*/ -+ wm_mask_cntl = dm_read_reg(ctx, wm_addr); -+ set_reg_field_value(wm_mask_cntl, -+ 2, -+ DPG_WATERMARK_MASK_CONTROL, -+ URGENCY_WATERMARK_MASK); -+ dm_write_reg(ctx, wm_addr, wm_mask_cntl); -+ -+ urgency_cntl = dm_read_reg(ctx, urgency_addr); -+ -+ set_reg_field_value(urgency_cntl, -+ marks_low.c_mark, -+ DPG_PIPE_URGENCY_CONTROL, -+ URGENCY_LOW_WATERMARK); -+ -+ set_reg_field_value(urgency_cntl, -+ total_dest_line_time_ns, -+ DPG_PIPE_URGENCY_CONTROL, -+ URGENCY_HIGH_WATERMARK); -+ dm_write_reg(ctx, urgency_addr, urgency_cntl); -+ -+ /*Write mask to enable reading/writing of watermark set D*/ -+ wm_mask_cntl = dm_read_reg(ctx, wm_addr); -+ set_reg_field_value(wm_mask_cntl, -+ 3, -+ DPG_WATERMARK_MASK_CONTROL, -+ URGENCY_WATERMARK_MASK); -+ dm_write_reg(ctx, wm_addr, wm_mask_cntl); -+ -+ urgency_cntl = dm_read_reg(ctx, urgency_addr); -+ -+ set_reg_field_value(urgency_cntl, -+ marks_low.d_mark, -+ DPG_PIPE_URGENCY_CONTROL, -+ URGENCY_LOW_WATERMARK); -+ -+ set_reg_field_value(urgency_cntl, -+ total_dest_line_time_ns, -+ DPG_PIPE_URGENCY_CONTROL, -+ URGENCY_HIGH_WATERMARK); -+ dm_write_reg(ctx, urgency_addr, urgency_cntl); -+} -+ -+static void program_stutter_watermark( -+ const struct dc_context *ctx, -+ const uint32_t offset, -+ struct bw_watermarks marks) -+{ -+ /* register value */ -+ uint32_t stutter_cntl = 0; -+ uint32_t wm_mask_cntl = 0; -+ -+ uint32_t stutter_addr = offset + mmDPG_PIPE_STUTTER_CONTROL; -+ uint32_t wm_addr = offset + mmDPG_WATERMARK_MASK_CONTROL; -+ -+ /*Write mask to enable reading/writing of watermark set A*/ -+ -+ wm_mask_cntl = dm_read_reg(ctx, wm_addr); -+ set_reg_field_value(wm_mask_cntl, -+ 0, -+ DPG_WATERMARK_MASK_CONTROL, -+ STUTTER_EXIT_SELF_REFRESH_WATERMARK_MASK); -+ dm_write_reg(ctx, wm_addr, wm_mask_cntl); -+ -+ stutter_cntl = dm_read_reg(ctx, stutter_addr); -+ -+ set_reg_field_value(stutter_cntl, -+ 1, -+ DPG_PIPE_STUTTER_CONTROL, -+ STUTTER_ENABLE); -+ set_reg_field_value(stutter_cntl, -+ 1, -+ DPG_PIPE_STUTTER_CONTROL, -+ STUTTER_IGNORE_FBC); -+ -+ /*Write watermark set A*/ -+ set_reg_field_value(stutter_cntl, -+ marks.a_mark, -+ DPG_PIPE_STUTTER_CONTROL, -+ STUTTER_EXIT_SELF_REFRESH_WATERMARK); -+ dm_write_reg(ctx, stutter_addr, stutter_cntl); -+ -+ /*Write mask to enable reading/writing of watermark set B*/ -+ wm_mask_cntl = dm_read_reg(ctx, wm_addr); -+ set_reg_field_value(wm_mask_cntl, -+ 1, -+ DPG_WATERMARK_MASK_CONTROL, -+ STUTTER_EXIT_SELF_REFRESH_WATERMARK_MASK); -+ dm_write_reg(ctx, wm_addr, wm_mask_cntl); -+ -+ stutter_cntl = dm_read_reg(ctx, stutter_addr); -+ set_reg_field_value(stutter_cntl, -+ 1, -+ DPG_PIPE_STUTTER_CONTROL, -+ STUTTER_ENABLE); -+ set_reg_field_value(stutter_cntl, -+ 1, -+ DPG_PIPE_STUTTER_CONTROL, -+ STUTTER_IGNORE_FBC); -+ -+ /*Write watermark set B*/ -+ set_reg_field_value(stutter_cntl, -+ marks.b_mark, -+ DPG_PIPE_STUTTER_CONTROL, -+ STUTTER_EXIT_SELF_REFRESH_WATERMARK); -+ dm_write_reg(ctx, stutter_addr, stutter_cntl); -+ -+ /*Write mask to enable reading/writing of watermark set C*/ -+ wm_mask_cntl = dm_read_reg(ctx, wm_addr); -+ set_reg_field_value(wm_mask_cntl, -+ 2, -+ DPG_WATERMARK_MASK_CONTROL, -+ STUTTER_EXIT_SELF_REFRESH_WATERMARK_MASK); -+ dm_write_reg(ctx, wm_addr, wm_mask_cntl); -+ -+ stutter_cntl = dm_read_reg(ctx, stutter_addr); -+ set_reg_field_value(stutter_cntl, -+ 1, -+ DPG_PIPE_STUTTER_CONTROL, -+ STUTTER_ENABLE); -+ set_reg_field_value(stutter_cntl, -+ 1, -+ DPG_PIPE_STUTTER_CONTROL, -+ STUTTER_IGNORE_FBC); -+ -+ /*Write watermark set C*/ -+ set_reg_field_value(stutter_cntl, -+ marks.c_mark, -+ DPG_PIPE_STUTTER_CONTROL, -+ STUTTER_EXIT_SELF_REFRESH_WATERMARK); -+ dm_write_reg(ctx, stutter_addr, stutter_cntl); -+ -+ /*Write mask to enable reading/writing of watermark set D*/ -+ wm_mask_cntl = dm_read_reg(ctx, wm_addr); -+ set_reg_field_value(wm_mask_cntl, -+ 3, -+ DPG_WATERMARK_MASK_CONTROL, -+ STUTTER_EXIT_SELF_REFRESH_WATERMARK_MASK); -+ dm_write_reg(ctx, wm_addr, wm_mask_cntl); -+ -+ stutter_cntl = dm_read_reg(ctx, stutter_addr); -+ set_reg_field_value(stutter_cntl, -+ 1, -+ DPG_PIPE_STUTTER_CONTROL, -+ STUTTER_ENABLE); -+ set_reg_field_value(stutter_cntl, -+ 1, -+ DPG_PIPE_STUTTER_CONTROL, -+ STUTTER_IGNORE_FBC); -+ -+ /*Write watermark set D*/ -+ set_reg_field_value(stutter_cntl, -+ marks.d_mark, -+ DPG_PIPE_STUTTER_CONTROL, -+ STUTTER_EXIT_SELF_REFRESH_WATERMARK); -+ dm_write_reg(ctx, stutter_addr, stutter_cntl); -+} -+ -+static void program_nbp_watermark( -+ const struct dc_context *ctx, -+ const uint32_t offset, -+ struct bw_watermarks marks) -+{ -+ uint32_t value; -+ uint32_t addr; -+ /* Write mask to enable reading/writing of watermark set A */ -+ addr = offset + mmDPG_WATERMARK_MASK_CONTROL; -+ value = dm_read_reg(ctx, addr); -+ set_reg_field_value( -+ value, -+ 0, -+ DPG_WATERMARK_MASK_CONTROL, -+ NB_PSTATE_CHANGE_WATERMARK_MASK); -+ dm_write_reg(ctx, addr, value); -+ -+ addr = offset + mmDPG_PIPE_NB_PSTATE_CHANGE_CONTROL; -+ value = dm_read_reg(ctx, addr); -+ set_reg_field_value( -+ value, -+ 1, -+ DPG_PIPE_NB_PSTATE_CHANGE_CONTROL, -+ NB_PSTATE_CHANGE_ENABLE); -+ set_reg_field_value( -+ value, -+ 1, -+ DPG_PIPE_NB_PSTATE_CHANGE_CONTROL, -+ NB_PSTATE_CHANGE_URGENT_DURING_REQUEST); -+ set_reg_field_value( -+ value, -+ 1, -+ DPG_PIPE_NB_PSTATE_CHANGE_CONTROL, -+ NB_PSTATE_CHANGE_NOT_SELF_REFRESH_DURING_REQUEST); -+ dm_write_reg(ctx, addr, value); -+ -+ /* Write watermark set A */ -+ value = dm_read_reg(ctx, addr); -+ set_reg_field_value( -+ value, -+ marks.a_mark, -+ DPG_PIPE_NB_PSTATE_CHANGE_CONTROL, -+ NB_PSTATE_CHANGE_WATERMARK); -+ dm_write_reg(ctx, addr, value); -+ -+ /* Write mask to enable reading/writing of watermark set B */ -+ addr = offset + mmDPG_WATERMARK_MASK_CONTROL; -+ value = dm_read_reg(ctx, addr); -+ set_reg_field_value( -+ value, -+ 1, -+ DPG_WATERMARK_MASK_CONTROL, -+ NB_PSTATE_CHANGE_WATERMARK_MASK); -+ dm_write_reg(ctx, addr, value); -+ -+ addr = offset + mmDPG_PIPE_NB_PSTATE_CHANGE_CONTROL; -+ value = dm_read_reg(ctx, addr); -+ set_reg_field_value( -+ value, -+ 1, -+ DPG_PIPE_NB_PSTATE_CHANGE_CONTROL, -+ NB_PSTATE_CHANGE_ENABLE); -+ set_reg_field_value( -+ value, -+ 1, -+ DPG_PIPE_NB_PSTATE_CHANGE_CONTROL, -+ NB_PSTATE_CHANGE_URGENT_DURING_REQUEST); -+ set_reg_field_value( -+ value, -+ 1, -+ DPG_PIPE_NB_PSTATE_CHANGE_CONTROL, -+ NB_PSTATE_CHANGE_NOT_SELF_REFRESH_DURING_REQUEST); -+ dm_write_reg(ctx, addr, value); -+ -+ /* Write watermark set B */ -+ value = dm_read_reg(ctx, addr); -+ set_reg_field_value( -+ value, -+ marks.b_mark, -+ DPG_PIPE_NB_PSTATE_CHANGE_CONTROL, -+ NB_PSTATE_CHANGE_WATERMARK); -+ dm_write_reg(ctx, addr, value); -+ -+ /* Write mask to enable reading/writing of watermark set C */ -+ addr = offset + mmDPG_WATERMARK_MASK_CONTROL; -+ value = dm_read_reg(ctx, addr); -+ set_reg_field_value( -+ value, -+ 2, -+ DPG_WATERMARK_MASK_CONTROL, -+ NB_PSTATE_CHANGE_WATERMARK_MASK); -+ dm_write_reg(ctx, addr, value); -+ -+ addr = offset + mmDPG_PIPE_NB_PSTATE_CHANGE_CONTROL; -+ value = dm_read_reg(ctx, addr); -+ set_reg_field_value( -+ value, -+ 1, -+ DPG_PIPE_NB_PSTATE_CHANGE_CONTROL, -+ NB_PSTATE_CHANGE_ENABLE); -+ set_reg_field_value( -+ value, -+ 1, -+ DPG_PIPE_NB_PSTATE_CHANGE_CONTROL, -+ NB_PSTATE_CHANGE_URGENT_DURING_REQUEST); -+ set_reg_field_value( -+ value, -+ 1, -+ DPG_PIPE_NB_PSTATE_CHANGE_CONTROL, -+ NB_PSTATE_CHANGE_NOT_SELF_REFRESH_DURING_REQUEST); -+ dm_write_reg(ctx, addr, value); -+ -+ /* Write watermark set C */ -+ value = dm_read_reg(ctx, addr); -+ set_reg_field_value( -+ value, -+ marks.c_mark, -+ DPG_PIPE_NB_PSTATE_CHANGE_CONTROL, -+ NB_PSTATE_CHANGE_WATERMARK); -+ dm_write_reg(ctx, addr, value); -+ -+ /* Write mask to enable reading/writing of watermark set D */ -+ addr = offset + mmDPG_WATERMARK_MASK_CONTROL; -+ value = dm_read_reg(ctx, addr); -+ set_reg_field_value( -+ value, -+ 3, -+ DPG_WATERMARK_MASK_CONTROL, -+ NB_PSTATE_CHANGE_WATERMARK_MASK); -+ dm_write_reg(ctx, addr, value); -+ -+ addr = offset + mmDPG_PIPE_NB_PSTATE_CHANGE_CONTROL; -+ value = dm_read_reg(ctx, addr); -+ set_reg_field_value( -+ value, -+ 1, -+ DPG_PIPE_NB_PSTATE_CHANGE_CONTROL, -+ NB_PSTATE_CHANGE_ENABLE); -+ set_reg_field_value( -+ value, -+ 1, -+ DPG_PIPE_NB_PSTATE_CHANGE_CONTROL, -+ NB_PSTATE_CHANGE_URGENT_DURING_REQUEST); -+ set_reg_field_value( -+ value, -+ 1, -+ DPG_PIPE_NB_PSTATE_CHANGE_CONTROL, -+ NB_PSTATE_CHANGE_NOT_SELF_REFRESH_DURING_REQUEST); -+ dm_write_reg(ctx, addr, value); -+ -+ /* Write watermark set D */ -+ value = dm_read_reg(ctx, addr); -+ set_reg_field_value( -+ value, -+ marks.d_mark, -+ DPG_PIPE_NB_PSTATE_CHANGE_CONTROL, -+ NB_PSTATE_CHANGE_WATERMARK); -+ dm_write_reg(ctx, addr, value); -+} -+ -+static void dce112_mem_input_program_display_marks( -+ struct mem_input *mem_input, -+ struct bw_watermarks nbp, -+ struct bw_watermarks stutter, -+ struct bw_watermarks urgent, -+ uint32_t total_dest_line_time_ns) -+{ -+ struct dce110_mem_input *bm_dce110 = TO_DCE110_MEM_INPUT(mem_input); -+ -+ program_urgency_watermark( -+ mem_input->ctx, -+ bm_dce110->offsets.dmif, -+ urgent, -+ total_dest_line_time_ns); -+ -+ program_nbp_watermark( -+ mem_input->ctx, -+ bm_dce110->offsets.dmif, -+ nbp); -+ -+ program_stutter_watermark( -+ mem_input->ctx, -+ bm_dce110->offsets.dmif, -+ stutter); -+} -+ -+/*****************************************/ -+/* Constructor, Destructor */ -+/*****************************************/ -+ -+bool dce112_mem_input_construct( -+ struct dce110_mem_input *mem_input110, -+ struct dc_context *ctx, -+ uint32_t inst, -+ const struct dce110_mem_input_reg_offsets *offsets) -+{ -+ if (!dce110_mem_input_construct(mem_input110, ctx, inst, offsets)) -+ return false; -+ -+ mem_input110->base.funcs->mem_input_program_display_marks = -+ dce112_mem_input_program_display_marks; -+ -+ return true; -+} -diff --git a/drivers/gpu/drm/amd/dal/dc/dce112/dce112_mem_input.h b/drivers/gpu/drm/amd/dal/dc/dce112/dce112_mem_input.h -new file mode 100644 -index 0000000..de2aaf0 ---- /dev/null -+++ b/drivers/gpu/drm/amd/dal/dc/dce112/dce112_mem_input.h -@@ -0,0 +1,38 @@ -+/* Copyright 2012-15 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 __DC_MEM_INPUT_DCE112_H__ -+#define __DC_MEM_INPUT_DCE112_H__ -+ -+#include "mem_input.h" -+#include "dce110/dce110_mem_input.h" -+ -+bool dce112_mem_input_construct( -+ struct dce110_mem_input *mem_input110, -+ struct dc_context *ctx, -+ uint32_t inst, -+ const struct dce110_mem_input_reg_offsets *offsets); -+ -+ -+#endif -diff --git a/drivers/gpu/drm/amd/dal/dc/dce112/dce112_resource.c b/drivers/gpu/drm/amd/dal/dc/dce112/dce112_resource.c -new file mode 100644 -index 0000000..420b8ca ---- /dev/null -+++ b/drivers/gpu/drm/amd/dal/dc/dce112/dce112_resource.c -@@ -0,0 +1,1404 @@ -+/* -+* Copyright 2012-15 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 "dm_services.h" -+ -+#include "link_encoder.h" -+#include "stream_encoder.h" -+ -+#include "resource.h" -+#include "include/irq_service_interface.h" -+#include "../virtual/virtual_stream_encoder.h" -+#include "dce110/dce110_resource.h" -+#include "dce110/dce110_timing_generator.h" -+#include "dce112/dce112_mem_input.h" -+#include "dce112/dce112_link_encoder.h" -+#include "dce110/dce110_link_encoder.h" -+#include "dce110/dce110_transform.h" -+#include "dce110/dce110_stream_encoder.h" -+#include "dce110/dce110_opp.h" -+#include "dce110/dce110_ipp.h" -+#include "dce112/dce112_clock_source.h" -+ -+#include "dce/dce_11_2_d.h" -+ -+#ifndef mmDP_DPHY_INTERNAL_CTRL -+ #define mmDP_DPHY_INTERNAL_CTRL 0x4aa7 -+ #define mmDP0_DP_DPHY_INTERNAL_CTRL 0x4aa7 -+ #define mmDP1_DP_DPHY_INTERNAL_CTRL 0x4ba7 -+ #define mmDP2_DP_DPHY_INTERNAL_CTRL 0x4ca7 -+ #define mmDP3_DP_DPHY_INTERNAL_CTRL 0x4da7 -+ #define mmDP4_DP_DPHY_INTERNAL_CTRL 0x4ea7 -+ #define mmDP5_DP_DPHY_INTERNAL_CTRL 0x4fa7 -+ #define mmDP6_DP_DPHY_INTERNAL_CTRL 0x54a7 -+ #define mmDP7_DP_DPHY_INTERNAL_CTRL 0x56a7 -+ #define mmDP8_DP_DPHY_INTERNAL_CTRL 0x57a7 -+#endif -+ -+enum dce112_clk_src_array_id { -+ DCE112_CLK_SRC_PLL0, -+ DCE112_CLK_SRC_PLL1, -+ DCE112_CLK_SRC_PLL2, -+ DCE112_CLK_SRC_PLL3, -+ DCE112_CLK_SRC_PLL4, -+ DCE112_CLK_SRC_PLL5, -+ -+ DCE112_CLK_SRC_TOTAL -+}; -+ -+static const struct dce110_transform_reg_offsets dce112_xfm_offsets[] = { -+{ -+ .scl_offset = (mmSCL0_SCL_CONTROL - mmSCL_CONTROL), -+ .dcfe_offset = (mmDCFE0_DCFE_MEM_PWR_CTRL - mmDCFE_MEM_PWR_CTRL), -+ .dcp_offset = (mmDCP0_GRPH_CONTROL - mmGRPH_CONTROL), -+ .lb_offset = (mmLB0_LB_DATA_FORMAT - mmLB_DATA_FORMAT), -+}, -+{ .scl_offset = (mmSCL1_SCL_CONTROL - mmSCL_CONTROL), -+ .dcfe_offset = (mmDCFE1_DCFE_MEM_PWR_CTRL - mmDCFE_MEM_PWR_CTRL), -+ .dcp_offset = (mmDCP1_GRPH_CONTROL - mmGRPH_CONTROL), -+ .lb_offset = (mmLB1_LB_DATA_FORMAT - mmLB_DATA_FORMAT), -+}, -+{ .scl_offset = (mmSCL2_SCL_CONTROL - mmSCL_CONTROL), -+ .dcfe_offset = (mmDCFE2_DCFE_MEM_PWR_CTRL - mmDCFE_MEM_PWR_CTRL), -+ .dcp_offset = (mmDCP2_GRPH_CONTROL - mmGRPH_CONTROL), -+ .lb_offset = (mmLB2_LB_DATA_FORMAT - mmLB_DATA_FORMAT), -+}, -+{ -+ .scl_offset = (mmSCL3_SCL_CONTROL - mmSCL_CONTROL), -+ .dcfe_offset = (mmDCFE3_DCFE_MEM_PWR_CTRL - mmDCFE_MEM_PWR_CTRL), -+ .dcp_offset = (mmDCP3_GRPH_CONTROL - mmGRPH_CONTROL), -+ .lb_offset = (mmLB3_LB_DATA_FORMAT - mmLB_DATA_FORMAT), -+}, -+{ .scl_offset = (mmSCL4_SCL_CONTROL - mmSCL_CONTROL), -+ .dcfe_offset = (mmDCFE4_DCFE_MEM_PWR_CTRL - mmDCFE_MEM_PWR_CTRL), -+ .dcp_offset = (mmDCP4_GRPH_CONTROL - mmGRPH_CONTROL), -+ .lb_offset = (mmLB4_LB_DATA_FORMAT - mmLB_DATA_FORMAT), -+}, -+{ .scl_offset = (mmSCL5_SCL_CONTROL - mmSCL_CONTROL), -+ .dcfe_offset = (mmDCFE5_DCFE_MEM_PWR_CTRL - mmDCFE_MEM_PWR_CTRL), -+ .dcp_offset = (mmDCP5_GRPH_CONTROL - mmGRPH_CONTROL), -+ .lb_offset = (mmLB5_LB_DATA_FORMAT - mmLB_DATA_FORMAT), -+} -+}; -+ -+static const struct dce110_timing_generator_offsets dce112_tg_offsets[] = { -+ { -+ .crtc = (mmCRTC0_CRTC_CONTROL - mmCRTC_CONTROL), -+ .dcp = (mmDCP0_GRPH_CONTROL - mmGRPH_CONTROL), -+ }, -+ { -+ .crtc = (mmCRTC1_CRTC_CONTROL - mmCRTC_CONTROL), -+ .dcp = (mmDCP1_GRPH_CONTROL - mmGRPH_CONTROL), -+ }, -+ { -+ .crtc = (mmCRTC2_CRTC_CONTROL - mmCRTC_CONTROL), -+ .dcp = (mmDCP2_GRPH_CONTROL - mmGRPH_CONTROL), -+ }, -+ { -+ .crtc = (mmCRTC3_CRTC_CONTROL - mmCRTC_CONTROL), -+ .dcp = (mmDCP3_GRPH_CONTROL - mmGRPH_CONTROL), -+ }, -+ { -+ .crtc = (mmCRTC4_CRTC_CONTROL - mmCRTC_CONTROL), -+ .dcp = (mmDCP4_GRPH_CONTROL - mmGRPH_CONTROL), -+ }, -+ { -+ .crtc = (mmCRTC5_CRTC_CONTROL - mmCRTC_CONTROL), -+ .dcp = (mmDCP5_GRPH_CONTROL - mmGRPH_CONTROL), -+ } -+}; -+ -+static const struct dce110_mem_input_reg_offsets dce112_mi_reg_offsets[] = { -+ { -+ .dcp = (mmDCP0_GRPH_CONTROL - mmGRPH_CONTROL), -+ .dmif = (mmDMIF_PG0_DPG_WATERMARK_MASK_CONTROL -+ - mmDPG_WATERMARK_MASK_CONTROL), -+ .pipe = (mmPIPE0_DMIF_BUFFER_CONTROL -+ - mmPIPE0_DMIF_BUFFER_CONTROL), -+ }, -+ { -+ .dcp = (mmDCP1_GRPH_CONTROL - mmGRPH_CONTROL), -+ .dmif = (mmDMIF_PG1_DPG_WATERMARK_MASK_CONTROL -+ - mmDPG_WATERMARK_MASK_CONTROL), -+ .pipe = (mmPIPE1_DMIF_BUFFER_CONTROL -+ - mmPIPE0_DMIF_BUFFER_CONTROL), -+ }, -+ { -+ .dcp = (mmDCP2_GRPH_CONTROL - mmGRPH_CONTROL), -+ .dmif = (mmDMIF_PG2_DPG_WATERMARK_MASK_CONTROL -+ - mmDPG_WATERMARK_MASK_CONTROL), -+ .pipe = (mmPIPE2_DMIF_BUFFER_CONTROL -+ - mmPIPE0_DMIF_BUFFER_CONTROL), -+ }, -+ { -+ .dcp = (mmDCP3_GRPH_CONTROL - mmGRPH_CONTROL), -+ .dmif = (mmDMIF_PG3_DPG_WATERMARK_MASK_CONTROL -+ - mmDPG_WATERMARK_MASK_CONTROL), -+ .pipe = (mmPIPE3_DMIF_BUFFER_CONTROL -+ - mmPIPE0_DMIF_BUFFER_CONTROL), -+ }, -+ { -+ .dcp = (mmDCP4_GRPH_CONTROL - mmGRPH_CONTROL), -+ .dmif = (mmDMIF_PG4_DPG_WATERMARK_MASK_CONTROL -+ - mmDPG_WATERMARK_MASK_CONTROL), -+ .pipe = (mmPIPE4_DMIF_BUFFER_CONTROL -+ - mmPIPE0_DMIF_BUFFER_CONTROL), -+ }, -+ { -+ .dcp = (mmDCP5_GRPH_CONTROL - mmGRPH_CONTROL), -+ .dmif = (mmDMIF_PG5_DPG_WATERMARK_MASK_CONTROL -+ - mmDPG_WATERMARK_MASK_CONTROL), -+ .pipe = (mmPIPE5_DMIF_BUFFER_CONTROL -+ - mmPIPE0_DMIF_BUFFER_CONTROL), -+ } -+}; -+ -+static const struct dce110_ipp_reg_offsets ipp_reg_offsets[] = { -+{ -+ .dcp_offset = (mmDCP0_CUR_CONTROL - mmCUR_CONTROL), -+}, -+{ -+ .dcp_offset = (mmDCP1_CUR_CONTROL - mmCUR_CONTROL), -+}, -+{ -+ .dcp_offset = (mmDCP2_CUR_CONTROL - mmCUR_CONTROL), -+}, -+{ -+ .dcp_offset = (mmDCP3_CUR_CONTROL - mmCUR_CONTROL), -+}, -+{ -+ .dcp_offset = (mmDCP4_CUR_CONTROL - mmCUR_CONTROL), -+}, -+{ -+ .dcp_offset = (mmDCP5_CUR_CONTROL - mmCUR_CONTROL), -+} -+}; -+ -+static const struct dce110_link_enc_bl_registers link_enc_bl_regs = { -+ .BL_PWM_CNTL = mmBL_PWM_CNTL, -+ .BL_PWM_GRP1_REG_LOCK = mmBL_PWM_GRP1_REG_LOCK, -+ .BL_PWM_PERIOD_CNTL = mmBL_PWM_PERIOD_CNTL, -+ .LVTMA_PWRSEQ_CNTL = mmLVTMA_PWRSEQ_CNTL, -+ .LVTMA_PWRSEQ_STATE = mmLVTMA_PWRSEQ_STATE -+}; -+ -+#define aux_regs(id)\ -+[id] = {\ -+ .AUX_CONTROL = mmDP_AUX ## id ## _AUX_CONTROL,\ -+ .AUX_DPHY_RX_CONTROL0 = mmDP_AUX ## id ## _AUX_DPHY_RX_CONTROL0\ -+} -+ -+static const struct dce110_link_enc_aux_registers link_enc_aux_regs[] = { -+ aux_regs(0), -+ aux_regs(1), -+ aux_regs(2), -+ aux_regs(3), -+ aux_regs(4), -+ aux_regs(5) -+}; -+ -+#define link_regs(id)\ -+[id] = {\ -+ .DIG_BE_CNTL = mmDIG ## id ## _DIG_BE_CNTL,\ -+ .DIG_BE_EN_CNTL = mmDIG ## id ## _DIG_BE_EN_CNTL,\ -+ .DP_CONFIG = mmDP ## id ## _DP_CONFIG,\ -+ .DP_DPHY_CNTL = mmDP ## id ## _DP_DPHY_CNTL,\ -+ .DP_DPHY_INTERNAL_CTRL = mmDP ## id ## _DP_DPHY_INTERNAL_CTRL,\ -+ .DP_DPHY_PRBS_CNTL = mmDP ## id ## _DP_DPHY_PRBS_CNTL,\ -+ .DP_DPHY_SYM0 = mmDP ## id ## _DP_DPHY_SYM0,\ -+ .DP_DPHY_SYM1 = mmDP ## id ## _DP_DPHY_SYM1,\ -+ .DP_DPHY_SYM2 = mmDP ## id ## _DP_DPHY_SYM2,\ -+ .DP_DPHY_TRAINING_PATTERN_SEL = mmDP ## id ## _DP_DPHY_TRAINING_PATTERN_SEL,\ -+ .DP_LINK_CNTL = mmDP ## id ## _DP_LINK_CNTL,\ -+ .DP_LINK_FRAMING_CNTL = mmDP ## id ## _DP_LINK_FRAMING_CNTL,\ -+ .DP_MSE_SAT0 = mmDP ## id ## _DP_MSE_SAT0,\ -+ .DP_MSE_SAT1 = mmDP ## id ## _DP_MSE_SAT1,\ -+ .DP_MSE_SAT2 = mmDP ## id ## _DP_MSE_SAT2,\ -+ .DP_MSE_SAT_UPDATE = mmDP ## id ## _DP_MSE_SAT_UPDATE,\ -+ .DP_SEC_CNTL = mmDP ## id ## _DP_SEC_CNTL,\ -+ .DP_VID_STREAM_CNTL = mmDP ## id ## _DP_VID_STREAM_CNTL\ -+} -+ -+static const struct dce110_link_enc_registers link_enc_regs[] = { -+ link_regs(0), -+ link_regs(1), -+ link_regs(2), -+ link_regs(3), -+ link_regs(4), -+ link_regs(5) -+}; -+ -+#define stream_enc_regs(id)\ -+[id] = {\ -+ .AFMT_AVI_INFO0 = mmDIG ## id ## _AFMT_AVI_INFO0,\ -+ .AFMT_AVI_INFO1 = mmDIG ## id ## _AFMT_AVI_INFO1,\ -+ .AFMT_AVI_INFO2 = mmDIG ## id ## _AFMT_AVI_INFO2,\ -+ .AFMT_AVI_INFO3 = mmDIG ## id ## _AFMT_AVI_INFO3,\ -+ .AFMT_GENERIC_0 = mmDIG ## id ## _AFMT_GENERIC_0,\ -+ .AFMT_GENERIC_7 = mmDIG ## id ## _AFMT_GENERIC_7,\ -+ .AFMT_GENERIC_HDR = mmDIG ## id ## _AFMT_GENERIC_HDR,\ -+ .AFMT_INFOFRAME_CONTROL0 = mmDIG ## id ## _AFMT_INFOFRAME_CONTROL0,\ -+ .AFMT_VBI_PACKET_CONTROL = mmDIG ## id ## _AFMT_VBI_PACKET_CONTROL,\ -+ .DIG_FE_CNTL = mmDIG ## id ## _DIG_FE_CNTL,\ -+ .DP_MSE_RATE_CNTL = mmDP ## id ## _DP_MSE_RATE_CNTL,\ -+ .DP_MSE_RATE_UPDATE = mmDP ## id ## _DP_MSE_RATE_UPDATE,\ -+ .DP_PIXEL_FORMAT = mmDP ## id ## _DP_PIXEL_FORMAT,\ -+ .DP_SEC_CNTL = mmDP ## id ## _DP_SEC_CNTL,\ -+ .DP_STEER_FIFO = mmDP ## id ## _DP_STEER_FIFO,\ -+ .DP_VID_M = mmDP ## id ## _DP_VID_M,\ -+ .DP_VID_N = mmDP ## id ## _DP_VID_N,\ -+ .DP_VID_STREAM_CNTL = mmDP ## id ## _DP_VID_STREAM_CNTL,\ -+ .DP_VID_TIMING = mmDP ## id ## _DP_VID_TIMING,\ -+ .HDMI_CONTROL = mmDIG ## id ## _HDMI_CONTROL,\ -+ .HDMI_GC = mmDIG ## id ## _HDMI_GC,\ -+ .HDMI_GENERIC_PACKET_CONTROL0 = mmDIG ## id ## _HDMI_GENERIC_PACKET_CONTROL0,\ -+ .HDMI_GENERIC_PACKET_CONTROL1 = mmDIG ## id ## _HDMI_GENERIC_PACKET_CONTROL1,\ -+ .HDMI_INFOFRAME_CONTROL0 = mmDIG ## id ## _HDMI_INFOFRAME_CONTROL0,\ -+ .HDMI_INFOFRAME_CONTROL1 = mmDIG ## id ## _HDMI_INFOFRAME_CONTROL1,\ -+ .HDMI_VBI_PACKET_CONTROL = mmDIG ## id ## _HDMI_VBI_PACKET_CONTROL,\ -+ .TMDS_CNTL = mmDIG ## id ## _TMDS_CNTL\ -+} -+ -+static const struct dce110_stream_enc_registers stream_enc_regs[] = { -+ stream_enc_regs(0), -+ stream_enc_regs(1), -+ stream_enc_regs(2), -+ stream_enc_regs(3), -+ stream_enc_regs(4), -+ stream_enc_regs(5) -+}; -+ -+static const struct dce110_opp_reg_offsets dce112_opp_reg_offsets[] = { -+{ -+ .fmt_offset = (mmFMT0_FMT_CONTROL - mmFMT0_FMT_CONTROL), -+ .dcfe_offset = (mmDCFE0_DCFE_MEM_PWR_CTRL - mmDCFE0_DCFE_MEM_PWR_CTRL), -+ .dcp_offset = (mmDCP0_GRPH_CONTROL - mmDCP0_GRPH_CONTROL), -+}, -+{ .fmt_offset = (mmFMT1_FMT_CONTROL - mmFMT0_FMT_CONTROL), -+ .dcfe_offset = (mmDCFE1_DCFE_MEM_PWR_CTRL - mmDCFE0_DCFE_MEM_PWR_CTRL), -+ .dcp_offset = (mmDCP1_GRPH_CONTROL - mmDCP0_GRPH_CONTROL), -+}, -+{ .fmt_offset = (mmFMT2_FMT_CONTROL - mmFMT0_FMT_CONTROL), -+ .dcfe_offset = (mmDCFE2_DCFE_MEM_PWR_CTRL - mmDCFE0_DCFE_MEM_PWR_CTRL), -+ .dcp_offset = (mmDCP2_GRPH_CONTROL - mmDCP0_GRPH_CONTROL), -+}, -+{ -+ .fmt_offset = (mmFMT3_FMT_CONTROL - mmFMT0_FMT_CONTROL), -+ .dcfe_offset = (mmDCFE3_DCFE_MEM_PWR_CTRL - mmDCFE0_DCFE_MEM_PWR_CTRL), -+ .dcp_offset = (mmDCP3_GRPH_CONTROL - mmDCP0_GRPH_CONTROL), -+}, -+{ .fmt_offset = (mmFMT4_FMT_CONTROL - mmFMT0_FMT_CONTROL), -+ .dcfe_offset = (mmDCFE4_DCFE_MEM_PWR_CTRL - mmDCFE0_DCFE_MEM_PWR_CTRL), -+ .dcp_offset = (mmDCP4_GRPH_CONTROL - mmDCP0_GRPH_CONTROL), -+}, -+{ .fmt_offset = (mmFMT5_FMT_CONTROL - mmFMT0_FMT_CONTROL), -+ .dcfe_offset = (mmDCFE5_DCFE_MEM_PWR_CTRL - mmDCFE0_DCFE_MEM_PWR_CTRL), -+ .dcp_offset = (mmDCP5_GRPH_CONTROL - mmDCP0_GRPH_CONTROL), -+} -+}; -+ -+static const struct dce112_clk_src_reg_offsets dce112_clk_src_reg_offsets[] = { -+ { -+ .pixclk_resync_cntl = mmPHYPLLA_PIXCLK_RESYNC_CNTL -+ }, -+ { -+ .pixclk_resync_cntl = mmPHYPLLB_PIXCLK_RESYNC_CNTL -+ }, -+ { -+ .pixclk_resync_cntl = mmPHYPLLC_PIXCLK_RESYNC_CNTL -+ }, -+ { -+ .pixclk_resync_cntl = mmPHYPLLD_PIXCLK_RESYNC_CNTL -+ }, -+ { -+ .pixclk_resync_cntl = mmPHYPLLE_PIXCLK_RESYNC_CNTL -+ }, -+ { -+ .pixclk_resync_cntl = mmPHYPLLF_PIXCLK_RESYNC_CNTL -+ } -+}; -+ -+static struct timing_generator *dce112_timing_generator_create( -+ struct adapter_service *as, -+ struct dc_context *ctx, -+ uint32_t instance, -+ const struct dce110_timing_generator_offsets *offsets) -+{ -+ struct dce110_timing_generator *tg110 = -+ dm_alloc(sizeof(struct dce110_timing_generator)); -+ -+ if (!tg110) -+ return NULL; -+ -+ if (dce110_timing_generator_construct(tg110, as, ctx, instance, offsets)) -+ return &tg110->base; -+ -+ BREAK_TO_DEBUGGER(); -+ dm_free(tg110); -+ return NULL; -+} -+ -+static struct stream_encoder *dce112_stream_encoder_create( -+ enum engine_id eng_id, -+ struct dc_context *ctx, -+ struct dc_bios *bp, -+ const struct dce110_stream_enc_registers *regs) -+{ -+ struct dce110_stream_encoder *enc110 = -+ dm_alloc(sizeof(struct dce110_stream_encoder)); -+ -+ if (!enc110) -+ return NULL; -+ -+ if (dce110_stream_encoder_construct(enc110, ctx, bp, eng_id, regs)) -+ return &enc110->base; -+ -+ BREAK_TO_DEBUGGER(); -+ dm_free(enc110); -+ return NULL; -+} -+ -+static struct mem_input *dce112_mem_input_create( -+ struct dc_context *ctx, -+ uint32_t inst, -+ const struct dce110_mem_input_reg_offsets *offset) -+{ -+ struct dce110_mem_input *mem_input110 = -+ dm_alloc(sizeof(struct dce110_mem_input)); -+ -+ if (!mem_input110) -+ return NULL; -+ -+ if (dce112_mem_input_construct(mem_input110, -+ ctx, inst, offset)) -+ return &mem_input110->base; -+ -+ BREAK_TO_DEBUGGER(); -+ dm_free(mem_input110); -+ return NULL; -+} -+ -+static void dce112_transform_destroy(struct transform **xfm) -+{ -+ dm_free(TO_DCE110_TRANSFORM(*xfm)); -+ *xfm = NULL; -+} -+ -+static struct transform *dce112_transform_create( -+ struct dc_context *ctx, -+ uint32_t inst, -+ const struct dce110_transform_reg_offsets *offsets) -+{ -+ struct dce110_transform *transform = -+ dm_alloc(sizeof(struct dce110_transform)); -+ -+ if (!transform) -+ return NULL; -+ -+ if (dce110_transform_construct(transform, ctx, inst, offsets)) -+ return &transform->base; -+ -+ BREAK_TO_DEBUGGER(); -+ dm_free(transform); -+ return NULL; -+} -+struct link_encoder *dce112_link_encoder_create( -+ const struct encoder_init_data *enc_init_data) -+{ -+ struct dce110_link_encoder *enc110 = -+ dm_alloc(sizeof(struct dce110_link_encoder)); -+ -+ if (!enc110) -+ return NULL; -+ -+ if (dce112_link_encoder_construct( -+ enc110, -+ enc_init_data, -+ &link_enc_regs[enc_init_data->transmitter], -+ &link_enc_aux_regs[enc_init_data->channel - 1], -+ &link_enc_bl_regs)) -+ return &enc110->base; -+ -+ BREAK_TO_DEBUGGER(); -+ dm_free(enc110); -+ return NULL; -+} -+ -+struct input_pixel_processor *dce112_ipp_create( -+ struct dc_context *ctx, -+ uint32_t inst, -+ const struct dce110_ipp_reg_offsets *offset) -+{ -+ struct dce110_ipp *ipp = -+ dm_alloc(sizeof(struct dce110_ipp)); -+ -+ if (!ipp) -+ return NULL; -+ -+ if (dce110_ipp_construct(ipp, ctx, inst, offset)) -+ return &ipp->base; -+ -+ BREAK_TO_DEBUGGER(); -+ dm_free(ipp); -+ return NULL; -+} -+ -+void dce112_ipp_destroy(struct input_pixel_processor **ipp) -+{ -+ dm_free(TO_DCE110_IPP(*ipp)); -+ *ipp = NULL; -+} -+ -+struct output_pixel_processor *dce112_opp_create( -+ struct dc_context *ctx, -+ uint32_t inst, -+ const struct dce110_opp_reg_offsets *offset) -+{ -+ struct dce110_opp *opp = -+ dm_alloc(sizeof(struct dce110_opp)); -+ -+ if (!opp) -+ return NULL; -+ -+ if (dce110_opp_construct(opp, -+ ctx, inst, offset)) -+ return &opp->base; -+ -+ BREAK_TO_DEBUGGER(); -+ dm_free(opp); -+ return NULL; -+} -+ -+void dce112_opp_destroy(struct output_pixel_processor **opp) -+{ -+ dm_free(FROM_DCE11_OPP(*opp)->regamma.coeff128_dx); -+ dm_free(FROM_DCE11_OPP(*opp)->regamma.coeff128_oem); -+ dm_free(FROM_DCE11_OPP(*opp)->regamma.coeff128); -+ dm_free(FROM_DCE11_OPP(*opp)->regamma.axis_x_1025); -+ dm_free(FROM_DCE11_OPP(*opp)->regamma.axis_x_256); -+ dm_free(FROM_DCE11_OPP(*opp)->regamma.coordinates_x); -+ dm_free(FROM_DCE11_OPP(*opp)->regamma.rgb_regamma); -+ dm_free(FROM_DCE11_OPP(*opp)->regamma.rgb_resulted); -+ dm_free(FROM_DCE11_OPP(*opp)->regamma.rgb_oem); -+ dm_free(FROM_DCE11_OPP(*opp)->regamma.rgb_user); -+ dm_free(FROM_DCE11_OPP(*opp)); -+ *opp = NULL; -+} -+ -+struct clock_source *dce112_clock_source_create( -+ struct dc_context *ctx, -+ struct dc_bios *bios, -+ enum clock_source_id id, -+ const struct dce112_clk_src_reg_offsets *offsets) -+{ -+ struct dce112_clk_src *clk_src = -+ dm_alloc(sizeof(struct dce112_clk_src)); -+ -+ if (!clk_src) -+ return NULL; -+ -+ if (dce112_clk_src_construct(clk_src, ctx, bios, id, offsets)) -+ return &clk_src->base; -+ -+ BREAK_TO_DEBUGGER(); -+ return NULL; -+} -+ -+void dce112_clock_source_destroy(struct clock_source **clk_src) -+{ -+ dm_free(TO_DCE112_CLK_SRC(*clk_src)); -+ *clk_src = NULL; -+} -+ -+void dce112_destruct_resource_pool(struct resource_pool *pool) -+{ -+ unsigned int i; -+ -+ for (i = 0; i < pool->pipe_count; i++) { -+ if (pool->opps[i] != NULL) -+ dce112_opp_destroy(&pool->opps[i]); -+ -+ if (pool->transforms[i] != NULL) -+ dce112_transform_destroy(&pool->transforms[i]); -+ -+ if (pool->ipps[i] != NULL) -+ dce112_ipp_destroy(&pool->ipps[i]); -+ -+ if (pool->mis[i] != NULL) { -+ dm_free(TO_DCE110_MEM_INPUT(pool->mis[i])); -+ pool->mis[i] = NULL; -+ } -+ -+ if (pool->timing_generators[i] != NULL) { -+ dm_free(DCE110TG_FROM_TG(pool->timing_generators[i])); -+ pool->timing_generators[i] = NULL; -+ } -+ } -+ -+ for (i = 0; i < pool->stream_enc_count; i++) { -+ if (pool->stream_enc[i] != NULL) -+ dm_free(DCE110STRENC_FROM_STRENC(pool->stream_enc[i])); -+ } -+ -+ for (i = 0; i < pool->clk_src_count; i++) { -+ if (pool->clock_sources[i] != NULL) { -+ dce112_clock_source_destroy(&pool->clock_sources[i]); -+ } -+ } -+ -+ if (pool->dp_clock_source != NULL) -+ dce112_clock_source_destroy(&pool->dp_clock_source); -+ -+ for (i = 0; i < pool->audio_count; i++) { -+ if (pool->audios[i] != NULL) { -+ dal_audio_destroy(&pool->audios[i]); -+ } -+ } -+ -+ if (pool->display_clock != NULL) { -+ dal_display_clock_destroy(&pool->display_clock); -+ } -+ -+ if (pool->scaler_filter != NULL) { -+ dal_scaler_filter_destroy(&pool->scaler_filter); -+ } -+ if (pool->irqs != NULL) { -+ dal_irq_service_destroy(&pool->irqs); -+ } -+ -+ if (pool->adapter_srv != NULL) { -+ dal_adapter_service_destroy(&pool->adapter_srv); -+ } -+} -+ -+static struct clock_source *find_matching_pll(struct resource_context *res_ctx, -+ const struct core_stream *const stream) -+{ -+ switch (stream->sink->link->link_enc->transmitter) { -+ case TRANSMITTER_UNIPHY_A: -+ return res_ctx->pool.clock_sources[DCE112_CLK_SRC_PLL0]; -+ case TRANSMITTER_UNIPHY_B: -+ return res_ctx->pool.clock_sources[DCE112_CLK_SRC_PLL1]; -+ case TRANSMITTER_UNIPHY_C: -+ return res_ctx->pool.clock_sources[DCE112_CLK_SRC_PLL2]; -+ case TRANSMITTER_UNIPHY_D: -+ return res_ctx->pool.clock_sources[DCE112_CLK_SRC_PLL3]; -+ case TRANSMITTER_UNIPHY_E: -+ return res_ctx->pool.clock_sources[DCE112_CLK_SRC_PLL4]; -+ case TRANSMITTER_UNIPHY_F: -+ return res_ctx->pool.clock_sources[DCE112_CLK_SRC_PLL5]; -+ default: -+ return NULL; -+ }; -+ -+ return 0; -+} -+ -+static enum audio_dto_source translate_to_dto_source(enum controller_id crtc_id) -+{ -+ switch (crtc_id) { -+ case CONTROLLER_ID_D0: -+ return DTO_SOURCE_ID0; -+ case CONTROLLER_ID_D1: -+ return DTO_SOURCE_ID1; -+ case CONTROLLER_ID_D2: -+ return DTO_SOURCE_ID2; -+ case CONTROLLER_ID_D3: -+ return DTO_SOURCE_ID3; -+ case CONTROLLER_ID_D4: -+ return DTO_SOURCE_ID4; -+ case CONTROLLER_ID_D5: -+ return DTO_SOURCE_ID5; -+ default: -+ return DTO_SOURCE_UNKNOWN; -+ } -+} -+ -+static void build_audio_output( -+ const struct pipe_ctx *pipe_ctx, -+ struct audio_output *audio_output) -+{ -+ const struct core_stream *stream = pipe_ctx->stream; -+ audio_output->engine_id = pipe_ctx->stream_enc->id; -+ -+ audio_output->signal = pipe_ctx->signal; -+ -+ /* audio_crtc_info */ -+ -+ audio_output->crtc_info.h_total = -+ stream->public.timing.h_total; -+ -+ /* Audio packets are sent during actual CRTC blank physical signal, we -+ * need to specify actual active signal portion */ -+ audio_output->crtc_info.h_active = -+ stream->public.timing.h_addressable -+ + stream->public.timing.h_border_left -+ + stream->public.timing.h_border_right; -+ -+ audio_output->crtc_info.v_active = -+ stream->public.timing.v_addressable -+ + stream->public.timing.v_border_top -+ + stream->public.timing.v_border_bottom; -+ -+ audio_output->crtc_info.pixel_repetition = 1; -+ -+ audio_output->crtc_info.interlaced = -+ stream->public.timing.flags.INTERLACE; -+ -+ audio_output->crtc_info.refresh_rate = -+ (stream->public.timing.pix_clk_khz*1000)/ -+ (stream->public.timing.h_total*stream->public.timing.v_total); -+ -+ audio_output->crtc_info.color_depth = -+ stream->public.timing.display_color_depth; -+ -+ audio_output->crtc_info.requested_pixel_clock = -+ pipe_ctx->pix_clk_params.requested_pix_clk; -+ -+ /* TODO - Investigate why calculated pixel clk has to be -+ * requested pixel clk */ -+ audio_output->crtc_info.calculated_pixel_clock = -+ pipe_ctx->pix_clk_params.requested_pix_clk; -+ -+ if (pipe_ctx->signal == SIGNAL_TYPE_DISPLAY_PORT || -+ pipe_ctx->signal == SIGNAL_TYPE_DISPLAY_PORT_MST) { -+ audio_output->pll_info.dp_dto_source_clock_in_khz = -+ dal_display_clock_get_dp_ref_clk_frequency( -+ pipe_ctx->dis_clk); -+ } -+ -+ audio_output->pll_info.feed_back_divider = -+ pipe_ctx->pll_settings.feedback_divider; -+ -+ audio_output->pll_info.dto_source = -+ translate_to_dto_source( -+ pipe_ctx->pipe_idx + 1); -+ -+ /* TODO hard code to enable for now. Need get from stream */ -+ audio_output->pll_info.ss_enabled = true; -+ -+ audio_output->pll_info.ss_percentage = -+ pipe_ctx->pll_settings.ss_percentage; -+} -+ -+static void get_pixel_clock_parameters( -+ const struct pipe_ctx *pipe_ctx, -+ struct pixel_clk_params *pixel_clk_params) -+{ -+ const struct core_stream *stream = pipe_ctx->stream; -+ pixel_clk_params->requested_pix_clk = stream->public.timing.pix_clk_khz; -+ pixel_clk_params->encoder_object_id = stream->sink->link->link_enc->id; -+ pixel_clk_params->signal_type = stream->sink->public.sink_signal; -+ pixel_clk_params->controller_id = pipe_ctx->pipe_idx + 1; -+ /* TODO: un-hardcode*/ -+ pixel_clk_params->requested_sym_clk = LINK_RATE_LOW * -+ LINK_RATE_REF_FREQ_IN_KHZ; -+ pixel_clk_params->flags.ENABLE_SS = 0; -+ pixel_clk_params->color_depth = -+ stream->public.timing.display_color_depth; -+ pixel_clk_params->flags.DISPLAY_BLANKED = 1; -+} -+ -+static enum dc_status build_pipe_hw_param(struct pipe_ctx *pipe_ctx) -+{ -+ /*TODO: unhardcode*/ -+ pipe_ctx->max_tmds_clk_from_edid_in_mhz = 0; -+ pipe_ctx->max_hdmi_deep_color = COLOR_DEPTH_121212; -+ pipe_ctx->max_hdmi_pixel_clock = 600000; -+ -+ get_pixel_clock_parameters(pipe_ctx, &pipe_ctx->pix_clk_params); -+ pipe_ctx->clock_source->funcs->get_pix_clk_dividers( -+ pipe_ctx->clock_source, -+ &pipe_ctx->pix_clk_params, -+ &pipe_ctx->pll_settings); -+ -+ build_audio_output(pipe_ctx, &pipe_ctx->audio_output); -+ -+ return DC_OK; -+} -+ -+static enum dc_status validate_mapped_resource( -+ const struct core_dc *dc, -+ struct validate_context *context) -+{ -+ enum dc_status status = DC_OK; -+ uint8_t i, j, k; -+ -+ for (i = 0; i < context->target_count; i++) { -+ struct core_target *target = context->targets[i]; -+ if (context->target_flags[i].unchanged) -+ continue; -+ for (j = 0; j < target->public.stream_count; j++) { -+ struct core_stream *stream = -+ DC_STREAM_TO_CORE(target->public.streams[j]); -+ struct core_link *link = stream->sink->link; -+ -+ for (k = 0; k < MAX_PIPES; k++) { -+ struct pipe_ctx *pipe_ctx = -+ &context->res_ctx.pipe_ctx[k]; -+ -+ if (context->res_ctx.pipe_ctx[k].stream != stream) -+ continue; -+ -+ if (!pipe_ctx->tg->funcs->validate_timing( -+ pipe_ctx->tg, &stream->public.timing)) -+ return DC_FAIL_CONTROLLER_VALIDATE; -+ -+ status = build_pipe_hw_param(pipe_ctx); -+ -+ if (status != DC_OK) -+ return status; -+ -+ if (!link->link_enc->funcs->validate_output_with_stream( -+ link->link_enc, -+ pipe_ctx)) -+ return DC_FAIL_ENC_VALIDATE; -+ -+ /* TODO: validate audio ASIC caps, encoder */ -+ -+ status = dc_link_validate_mode_timing(stream->sink, -+ link, -+ &stream->public.timing); -+ -+ if (status != DC_OK) -+ return status; -+ -+ resource_build_info_frame(pipe_ctx); -+ -+ /* do not need to validate non root pipes */ -+ break; -+ } -+ } -+ } -+ -+ return DC_OK; -+} -+ -+enum dc_status dce112_validate_bandwidth( -+ const struct core_dc *dc, -+ struct validate_context *context) -+{ -+ uint8_t i; -+ enum dc_status result = DC_ERROR_UNEXPECTED; -+ uint8_t number_of_displays = 0; -+ uint8_t max_htaps = 1; -+ uint8_t max_vtaps = 1; -+ bool all_displays_in_sync = true; -+ struct dc_crtc_timing prev_timing; -+ -+ memset(&context->bw_mode_data, 0, sizeof(context->bw_mode_data)); -+ -+ for (i = 0; i < MAX_PIPES; i++) { -+ struct pipe_ctx *pipe_ctx = &context->res_ctx.pipe_ctx[i]; -+ struct bw_calcs_input_single_display *disp = &context-> -+ bw_mode_data.displays_data[number_of_displays]; -+ -+ if (pipe_ctx->stream == NULL) -+ continue; -+ -+ if (pipe_ctx->scl_data.ratios.vert.value == 0) { -+ disp->graphics_scale_ratio = bw_int_to_fixed(1); -+ disp->graphics_h_taps = 2; -+ disp->graphics_v_taps = 2; -+ -+ /* TODO: remove when bw formula accepts taps per -+ * display -+ */ -+ if (max_vtaps < 2) -+ max_vtaps = 2; -+ if (max_htaps < 2) -+ max_htaps = 2; -+ -+ } else { -+ disp->graphics_scale_ratio = -+ fixed31_32_to_bw_fixed( -+ pipe_ctx->scl_data.ratios.vert.value); -+ disp->graphics_h_taps = pipe_ctx->scl_data.taps.h_taps; -+ disp->graphics_v_taps = pipe_ctx->scl_data.taps.v_taps; -+ -+ /* TODO: remove when bw formula accepts taps per -+ * display -+ */ -+ if (max_vtaps < pipe_ctx->scl_data.taps.v_taps) -+ max_vtaps = pipe_ctx->scl_data.taps.v_taps; -+ if (max_htaps < pipe_ctx->scl_data.taps.h_taps) -+ max_htaps = pipe_ctx->scl_data.taps.h_taps; -+ } -+ -+ disp->graphics_src_width = -+ pipe_ctx->stream->public.timing.h_addressable; -+ disp->graphics_src_height = -+ pipe_ctx->stream->public.timing.v_addressable; -+ disp->h_total = pipe_ctx->stream->public.timing.h_total; -+ disp->pixel_rate = bw_frc_to_fixed( -+ pipe_ctx->stream->public.timing.pix_clk_khz, 1000); -+ -+ /*TODO: get from surface*/ -+ disp->graphics_bytes_per_pixel = 4; -+ disp->graphics_tiling_mode = bw_def_tiled; -+ -+ /* DCE11 defaults*/ -+ disp->graphics_lb_bpc = 10; -+ disp->graphics_interlace_mode = false; -+ disp->fbc_enable = false; -+ disp->lpt_enable = false; -+ disp->graphics_stereo_mode = bw_def_mono; -+ disp->underlay_mode = bw_def_none; -+ -+ /*All displays will be synchronized if timings are all -+ * the same -+ */ -+ if (number_of_displays != 0 && all_displays_in_sync) -+ if (memcmp(&prev_timing, -+ &pipe_ctx->stream->public.timing, -+ sizeof(struct dc_crtc_timing)) != 0) -+ all_displays_in_sync = false; -+ if (number_of_displays == 0) -+ prev_timing = pipe_ctx->stream->public.timing; -+ -+ number_of_displays++; -+ } -+ -+ /* TODO: remove when bw formula accepts taps per -+ * display -+ */ -+ context->bw_mode_data.displays_data[0].graphics_v_taps = max_vtaps; -+ context->bw_mode_data.displays_data[0].graphics_h_taps = max_htaps; -+ -+ context->bw_mode_data.number_of_displays = number_of_displays; -+ context->bw_mode_data.display_synchronization_enabled = -+ all_displays_in_sync; -+ -+ dal_logger_write( -+ dc->ctx->logger, -+ LOG_MAJOR_BWM, -+ LOG_MINOR_BWM_REQUIRED_BANDWIDTH_CALCS, -+ "%s: start", -+ __func__); -+ -+ if (!bw_calcs( -+ dc->ctx, -+ &dc->bw_dceip, -+ &dc->bw_vbios, -+ &context->bw_mode_data, -+ &context->bw_results)) -+ result = DC_FAIL_BANDWIDTH_VALIDATE; -+ else -+ result = DC_OK; -+ -+ if (result == DC_FAIL_BANDWIDTH_VALIDATE) -+ dal_logger_write(dc->ctx->logger, -+ LOG_MAJOR_BWM, -+ LOG_MINOR_BWM_MODE_VALIDATION, -+ "%s: Bandwidth validation failed!", -+ __func__); -+ -+ if (memcmp(&dc->current_context.bw_results, -+ &context->bw_results, sizeof(context->bw_results))) { -+ struct log_entry log_entry; -+ dal_logger_open( -+ dc->ctx->logger, -+ &log_entry, -+ LOG_MAJOR_BWM, -+ LOG_MINOR_BWM_REQUIRED_BANDWIDTH_CALCS); -+ dal_logger_append(&log_entry, "%s: finish, numDisplays: %d\n" -+ "nbpMark_b: %d nbpMark_a: %d urgentMark_b: %d urgentMark_a: %d\n" -+ "stutMark_b: %d stutMark_a: %d\n", -+ __func__, number_of_displays, -+ context->bw_results.nbp_state_change_wm_ns[0].b_mark, -+ context->bw_results.nbp_state_change_wm_ns[0].a_mark, -+ context->bw_results.urgent_wm_ns[0].b_mark, -+ context->bw_results.urgent_wm_ns[0].a_mark, -+ context->bw_results.stutter_exit_wm_ns[0].b_mark, -+ context->bw_results.stutter_exit_wm_ns[0].a_mark); -+ dal_logger_append(&log_entry, -+ "nbpMark_b: %d nbpMark_a: %d urgentMark_b: %d urgentMark_a: %d\n" -+ "stutMark_b: %d stutMark_a: %d\n", -+ context->bw_results.nbp_state_change_wm_ns[1].b_mark, -+ context->bw_results.nbp_state_change_wm_ns[1].a_mark, -+ context->bw_results.urgent_wm_ns[1].b_mark, -+ context->bw_results.urgent_wm_ns[1].a_mark, -+ context->bw_results.stutter_exit_wm_ns[1].b_mark, -+ context->bw_results.stutter_exit_wm_ns[1].a_mark); -+ dal_logger_append(&log_entry, -+ "nbpMark_b: %d nbpMark_a: %d urgentMark_b: %d urgentMark_a: %d\n" -+ "stutMark_b: %d stutMark_a: %d stutter_mode_enable: %d\n", -+ context->bw_results.nbp_state_change_wm_ns[2].b_mark, -+ context->bw_results.nbp_state_change_wm_ns[2].a_mark, -+ context->bw_results.urgent_wm_ns[2].b_mark, -+ context->bw_results.urgent_wm_ns[2].a_mark, -+ context->bw_results.stutter_exit_wm_ns[2].b_mark, -+ context->bw_results.stutter_exit_wm_ns[2].a_mark, -+ context->bw_results.stutter_mode_enable); -+ dal_logger_append(&log_entry, -+ "cstate: %d pstate: %d nbpstate: %d sync: %d dispclk: %d\n" -+ "sclk: %d sclk_sleep: %d yclk: %d blackout_duration: %d\n", -+ context->bw_results.cpuc_state_change_enable, -+ context->bw_results.cpup_state_change_enable, -+ context->bw_results.nbp_state_change_enable, -+ context->bw_results.all_displays_in_sync, -+ context->bw_results.dispclk_khz, -+ context->bw_results.required_sclk, -+ context->bw_results.required_sclk_deep_sleep, -+ context->bw_results.required_yclk, -+ context->bw_results.required_blackout_duration_us); -+ dal_logger_close(&log_entry); -+ } -+ return result; -+} -+ -+static void set_target_unchanged( -+ struct validate_context *context, -+ uint8_t target_idx) -+{ -+ uint8_t i, j; -+ struct core_target *target = context->targets[target_idx]; -+ context->target_flags[target_idx].unchanged = true; -+ for (i = 0; i < target->public.stream_count; i++) { -+ struct core_stream *stream = -+ DC_STREAM_TO_CORE(target->public.streams[i]); -+ for (j = 0; j < MAX_PIPES; j++) { -+ if (context->res_ctx.pipe_ctx[j].stream == stream) -+ context->res_ctx.pipe_ctx[j].flags.unchanged = -+ true; -+ } -+ } -+} -+ -+static enum dc_status map_clock_resources( -+ const struct core_dc *dc, -+ struct validate_context *context) -+{ -+ uint8_t i, j, k; -+ -+ /* acquire new resources */ -+ for (i = 0; i < context->target_count; i++) { -+ struct core_target *target = context->targets[i]; -+ -+ if (context->target_flags[i].unchanged) -+ continue; -+ -+ for (j = 0; j < target->public.stream_count; j++) { -+ struct core_stream *stream = -+ DC_STREAM_TO_CORE(target->public.streams[j]); -+ -+ for (k = 0; k < MAX_PIPES; k++) { -+ struct pipe_ctx *pipe_ctx = -+ &context->res_ctx.pipe_ctx[k]; -+ -+ if (context->res_ctx.pipe_ctx[k].stream != stream) -+ continue; -+ -+ if (dc_is_dp_signal(pipe_ctx->signal) -+ || pipe_ctx->signal == SIGNAL_TYPE_VIRTUAL) -+ pipe_ctx->clock_source = -+ context->res_ctx.pool.dp_clock_source; -+ else -+ pipe_ctx->clock_source = -+ find_matching_pll(&context->res_ctx, -+ stream); -+ -+ if (pipe_ctx->clock_source == NULL) -+ return DC_NO_CLOCK_SOURCE_RESOURCE; -+ -+ resource_reference_clock_source( -+ &context->res_ctx, -+ pipe_ctx->clock_source); -+ -+ /* only one cs per stream regardless of mpo */ -+ break; -+ } -+ } -+ } -+ -+ return DC_OK; -+} -+ -+enum dc_status dce112_validate_with_context( -+ const struct core_dc *dc, -+ const struct dc_validation_set set[], -+ uint8_t set_count, -+ struct validate_context *context) -+{ -+ enum dc_status result = DC_ERROR_UNEXPECTED; -+ uint8_t i, j; -+ struct dc_context *dc_ctx = dc->ctx; -+ -+ for (i = 0; i < set_count; i++) { -+ bool unchanged = false; -+ -+ context->targets[i] = DC_TARGET_TO_CORE(set[i].target); -+ dc_target_retain(&context->targets[i]->public); -+ context->target_count++; -+ -+ for (j = 0; j < dc->current_context.target_count; j++) -+ if (dc->current_context.targets[j] -+ == context->targets[i]) { -+ unchanged = true; -+ set_target_unchanged(context, i); -+ resource_attach_surfaces_to_context( -+ (struct dc_surface **)dc->current_context. -+ target_status[j].surfaces, -+ dc->current_context.target_status[j].surface_count, -+ &context->targets[i]->public, -+ context); -+ context->target_status[i] = -+ dc->current_context.target_status[j]; -+ } -+ if (!unchanged || set[i].surface_count != 0) -+ if (!resource_attach_surfaces_to_context( -+ (struct dc_surface **)set[i].surfaces, -+ set[i].surface_count, -+ &context->targets[i]->public, -+ context)) { -+ DC_ERROR("Failed to attach surface to target!\n"); -+ return DC_FAIL_ATTACH_SURFACES; -+ } -+ } -+ -+ context->res_ctx.pool = dc->res_pool; -+ -+ result = resource_map_pool_resources(dc, context); -+ -+ if (result == DC_OK) -+ result = map_clock_resources(dc, context); -+ -+ if (result == DC_OK) -+ result = validate_mapped_resource(dc, context); -+ -+ if (result == DC_OK) -+ resource_build_scaling_params_for_context(dc, context); -+ -+ if (result == DC_OK) -+ result = dce112_validate_bandwidth(dc, context); -+ -+ return result; -+} -+ -+static struct resource_funcs dce112_res_pool_funcs = { -+ .destruct = dce112_destruct_resource_pool, -+ .link_enc_create = dce112_link_encoder_create, -+ .validate_with_context = dce112_validate_with_context, -+ .validate_bandwidth = dce112_validate_bandwidth -+}; -+ -+static void bw_calcs_data_update_from_pplib(struct core_dc *dc) -+{ -+ struct dm_pp_clock_levels clks = {0}; -+ -+ /*do system clock*/ -+ dm_pp_get_clock_levels_by_type( -+ dc->ctx, -+ DM_PP_CLOCK_TYPE_ENGINE_CLK, -+ &clks); -+ /* convert all the clock fro kHz to fix point mHz */ -+ dc->bw_vbios.high_sclk = bw_frc_to_fixed( -+ clks.clocks_in_khz[clks.num_levels-1], 1000); -+ dc->bw_vbios.mid_sclk = bw_frc_to_fixed( -+ clks.clocks_in_khz[clks.num_levels>>1], 1000); -+ dc->bw_vbios.low_sclk = bw_frc_to_fixed( -+ clks.clocks_in_khz[0], 1000); -+ -+ /*do display clock*/ -+ dm_pp_get_clock_levels_by_type( -+ dc->ctx, -+ DM_PP_CLOCK_TYPE_DISPLAY_CLK, -+ &clks); -+ -+ dc->bw_vbios.high_voltage_max_dispclk = bw_frc_to_fixed( -+ clks.clocks_in_khz[clks.num_levels-1], 1000); -+ dc->bw_vbios.mid_voltage_max_dispclk = bw_frc_to_fixed( -+ clks.clocks_in_khz[clks.num_levels>>1], 1000); -+ dc->bw_vbios.low_voltage_max_dispclk = bw_frc_to_fixed( -+ clks.clocks_in_khz[0], 1000); -+ -+ /*do memory clock*/ -+ dm_pp_get_clock_levels_by_type( -+ dc->ctx, -+ DM_PP_CLOCK_TYPE_MEMORY_CLK, -+ &clks); -+ -+ dc->bw_vbios.low_yclk = bw_frc_to_fixed( -+ clks.clocks_in_khz[0] * MEMORY_TYPE_MULTIPLIER, 1000); -+ dc->bw_vbios.mid_yclk = bw_frc_to_fixed( -+ clks.clocks_in_khz[clks.num_levels>>1] * MEMORY_TYPE_MULTIPLIER, -+ 1000); -+ dc->bw_vbios.high_yclk = bw_frc_to_fixed( -+ clks.clocks_in_khz[clks.num_levels-1] * MEMORY_TYPE_MULTIPLIER, -+ 1000); -+} -+ -+ -+bool dce112_construct_resource_pool( -+ struct adapter_service *adapter_serv, -+ uint8_t num_virtual_links, -+ struct core_dc *dc, -+ struct resource_pool *pool) -+{ -+ unsigned int i; -+ struct audio_init_data audio_init_data = { 0 }; -+ struct dc_context *ctx = dc->ctx; -+ -+ pool->adapter_srv = adapter_serv; -+ pool->funcs = &dce112_res_pool_funcs; -+ -+ pool->stream_engines.engine.ENGINE_ID_DIGA = 1; -+ pool->stream_engines.engine.ENGINE_ID_DIGB = 1; -+ pool->stream_engines.engine.ENGINE_ID_DIGC = 1; -+ pool->stream_engines.engine.ENGINE_ID_DIGD = 1; -+ pool->stream_engines.engine.ENGINE_ID_DIGE = 1; -+ pool->stream_engines.engine.ENGINE_ID_DIGF = 1; -+ -+ pool->clock_sources[DCE112_CLK_SRC_PLL0] = dce112_clock_source_create( -+ ctx, dal_adapter_service_get_bios_parser(adapter_serv), -+ CLOCK_SOURCE_COMBO_PHY_PLL0, &dce112_clk_src_reg_offsets[0]); -+ pool->clock_sources[DCE112_CLK_SRC_PLL1] = dce112_clock_source_create( -+ ctx, dal_adapter_service_get_bios_parser(adapter_serv), -+ CLOCK_SOURCE_COMBO_PHY_PLL1, &dce112_clk_src_reg_offsets[1]); -+ pool->clock_sources[DCE112_CLK_SRC_PLL2] = dce112_clock_source_create( -+ ctx, dal_adapter_service_get_bios_parser(adapter_serv), -+ CLOCK_SOURCE_COMBO_PHY_PLL2, &dce112_clk_src_reg_offsets[2]); -+ pool->clock_sources[DCE112_CLK_SRC_PLL3] = dce112_clock_source_create( -+ ctx, dal_adapter_service_get_bios_parser(adapter_serv), -+ CLOCK_SOURCE_COMBO_PHY_PLL3, &dce112_clk_src_reg_offsets[3]); -+ pool->clock_sources[DCE112_CLK_SRC_PLL4] = dce112_clock_source_create( -+ ctx, dal_adapter_service_get_bios_parser(adapter_serv), -+ CLOCK_SOURCE_COMBO_PHY_PLL4, &dce112_clk_src_reg_offsets[4]); -+ pool->clock_sources[DCE112_CLK_SRC_PLL5] = dce112_clock_source_create( -+ ctx, dal_adapter_service_get_bios_parser(adapter_serv), -+ CLOCK_SOURCE_COMBO_PHY_PLL5, &dce112_clk_src_reg_offsets[5]); -+ pool->clk_src_count = DCE112_CLK_SRC_TOTAL; -+ -+ pool->dp_clock_source = dce112_clock_source_create( -+ ctx, dal_adapter_service_get_bios_parser(adapter_serv), -+ CLOCK_SOURCE_ID_DP_DTO, &dce112_clk_src_reg_offsets[0]); -+ -+ for (i = 0; i < pool->clk_src_count; i++) { -+ if (pool->clock_sources[i] == NULL) { -+ dm_error("DC: failed to create clock sources!\n"); -+ BREAK_TO_DEBUGGER(); -+ goto clk_src_create_fail; -+ } -+ } -+ -+ pool->display_clock = dal_display_clock_dce112_create(ctx, adapter_serv); -+ if (pool->display_clock == NULL) { -+ dm_error("DC: failed to create display clock!\n"); -+ BREAK_TO_DEBUGGER(); -+ goto disp_clk_create_fail; -+ } -+ -+ { -+ struct irq_service_init_data init_data; -+ init_data.ctx = dc->ctx; -+ pool->irqs = dal_irq_service_create( -+ dal_adapter_service_get_dce_version( -+ dc->res_pool.adapter_srv), -+ &init_data); -+ if (!pool->irqs) -+ goto irqs_create_fail; -+ -+ } -+ -+ pool->pipe_count = -+ dal_adapter_service_get_func_controllers_num(adapter_serv); -+ pool->stream_enc_count = 6; -+ pool->scaler_filter = dal_scaler_filter_create(ctx); -+ if (pool->scaler_filter == NULL) { -+ BREAK_TO_DEBUGGER(); -+ dm_error("DC: failed to create filter!\n"); -+ goto filter_create_fail; -+ } -+ -+ for (i = 0; i < pool->pipe_count; i++) { -+ pool->timing_generators[i] = dce112_timing_generator_create( -+ adapter_serv, -+ ctx, -+ i, -+ &dce112_tg_offsets[i]); -+ if (pool->timing_generators[i] == NULL) { -+ BREAK_TO_DEBUGGER(); -+ dm_error("DC: failed to create tg!\n"); -+ goto controller_create_fail; -+ } -+ -+ pool->mis[i] = dce112_mem_input_create( -+ ctx, -+ i, -+ &dce112_mi_reg_offsets[i]); -+ if (pool->mis[i] == NULL) { -+ BREAK_TO_DEBUGGER(); -+ dm_error( -+ "DC: failed to create memory input!\n"); -+ goto controller_create_fail; -+ } -+ -+ pool->ipps[i] = dce112_ipp_create( -+ ctx, -+ i, -+ &ipp_reg_offsets[i]); -+ if (pool->ipps[i] == NULL) { -+ BREAK_TO_DEBUGGER(); -+ dm_error( -+ "DC: failed to create input pixel processor!\n"); -+ goto controller_create_fail; -+ } -+ -+ pool->transforms[i] = dce112_transform_create( -+ ctx, -+ i, -+ &dce112_xfm_offsets[i]); -+ if (pool->transforms[i] == NULL) { -+ BREAK_TO_DEBUGGER(); -+ dm_error( -+ "DC: failed to create transform!\n"); -+ goto controller_create_fail; -+ } -+ pool->transforms[i]->funcs->transform_set_scaler_filter( -+ pool->transforms[i], -+ pool->scaler_filter); -+ -+ pool->opps[i] = dce112_opp_create( -+ ctx, -+ i, -+ &dce112_opp_reg_offsets[i]); -+ if (pool->opps[i] == NULL) { -+ BREAK_TO_DEBUGGER(); -+ dm_error( -+ "DC: failed to create output pixel processor!\n"); -+ goto controller_create_fail; -+ } -+ } -+ -+ audio_init_data.as = adapter_serv; -+ audio_init_data.ctx = ctx; -+ pool->audio_count = 0; -+ for (i = 0; i < pool->pipe_count; i++) { -+ struct graphics_object_id obj_id; -+ -+ obj_id = dal_adapter_service_enum_audio_object(adapter_serv, i); -+ if (false == dal_graphics_object_id_is_valid(obj_id)) { -+ /* no more valid audio objects */ -+ break; -+ } -+ -+ audio_init_data.audio_stream_id = obj_id; -+ pool->audios[i] = dal_audio_create(&audio_init_data); -+ if (pool->audios[i] == NULL) { -+ BREAK_TO_DEBUGGER(); -+ dm_error("DC: failed to create DPPs!\n"); -+ goto audio_create_fail; -+ } -+ pool->audio_count++; -+ } -+ -+ for (i = 0; i < pool->stream_enc_count; i++) { -+ /* TODO: rework fragile code*/ -+ if (pool->stream_engines.u_all & 1 << i) { -+ pool->stream_enc[i] = dce112_stream_encoder_create( -+ i, dc->ctx, -+ dal_adapter_service_get_bios_parser( -+ adapter_serv), -+ &stream_enc_regs[i]); -+ if (pool->stream_enc[i] == NULL) { -+ BREAK_TO_DEBUGGER(); -+ dm_error("DC: failed to create stream_encoder!\n"); -+ goto stream_enc_create_fail; -+ } -+ } -+ } -+ -+ for (i = 0; i < num_virtual_links; i++) { -+ pool->stream_enc[pool->stream_enc_count] = -+ virtual_stream_encoder_create( -+ dc->ctx, dal_adapter_service_get_bios_parser( -+ adapter_serv)); -+ if (pool->stream_enc[pool->stream_enc_count] == NULL) { -+ BREAK_TO_DEBUGGER(); -+ dm_error("DC: failed to create stream_encoder!\n"); -+ goto stream_enc_create_fail; -+ } -+ pool->stream_enc_count++; -+ } -+ -+ /* Create hardware sequencer */ -+ if (!dc_construct_hw_sequencer(adapter_serv, dc)) -+ goto stream_enc_create_fail; -+ -+ bw_calcs_init(&dc->bw_dceip, &dc->bw_vbios, BW_CALCS_VERSION_BAFFIN); -+ -+ bw_calcs_data_update_from_pplib(dc); -+ -+ return true; -+ -+stream_enc_create_fail: -+ for (i = 0; i < pool->stream_enc_count; i++) { -+ if (pool->stream_enc[i] != NULL) -+ dm_free(DCE110STRENC_FROM_STRENC(pool->stream_enc[i])); -+ } -+ -+audio_create_fail: -+ for (i = 0; i < pool->pipe_count; i++) { -+ if (pool->audios[i] != NULL) -+ dal_audio_destroy(&pool->audios[i]); -+ } -+ -+controller_create_fail: -+ for (i = 0; i < pool->pipe_count; i++) { -+ if (pool->opps[i] != NULL) -+ dce112_opp_destroy(&pool->opps[i]); -+ -+ if (pool->transforms[i] != NULL) -+ dce112_transform_destroy(&pool->transforms[i]); -+ -+ if (pool->ipps[i] != NULL) -+ dce112_ipp_destroy(&pool->ipps[i]); -+ -+ if (pool->mis[i] != NULL) { -+ dm_free(TO_DCE110_MEM_INPUT(pool->mis[i])); -+ pool->mis[i] = NULL; -+ } -+ -+ if (pool->timing_generators[i] != NULL) { -+ dm_free(DCE110TG_FROM_TG(pool->timing_generators[i])); -+ pool->timing_generators[i] = NULL; -+ } -+ } -+ -+filter_create_fail: -+ dal_irq_service_destroy(&pool->irqs); -+ -+irqs_create_fail: -+ dal_display_clock_destroy(&pool->display_clock); -+ -+disp_clk_create_fail: -+clk_src_create_fail: -+ for (i = 0; i < pool->clk_src_count; i++) { -+ if (pool->clock_sources[i] != NULL) -+ dce112_clock_source_destroy(&pool->clock_sources[i]); -+ } -+ -+ return false; -+} -diff --git a/drivers/gpu/drm/amd/dal/dc/dce112/dce112_resource.h b/drivers/gpu/drm/amd/dal/dc/dce112/dce112_resource.h -new file mode 100644 -index 0000000..eed1faf ---- /dev/null -+++ b/drivers/gpu/drm/amd/dal/dc/dce112/dce112_resource.h -@@ -0,0 +1,42 @@ -+/* -+* Copyright 2012-15 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 __DC_RESOURCE_DCE112_H__ -+#define __DC_RESOURCE_DCE112_H__ -+ -+#include "core_types.h" -+ -+struct adapter_service; -+struct core_dc; -+struct resource_pool; -+ -+bool dce112_construct_resource_pool( -+ struct adapter_service *adapter_serv, -+ uint8_t num_virtual_links, -+ struct core_dc *dc, -+ struct resource_pool *pool); -+ -+#endif /* __DC_RESOURCE_DCE112_H__ */ -+ -diff --git a/drivers/gpu/drm/amd/dal/dc/dm_services_types.h b/drivers/gpu/drm/amd/dal/dc/dm_services_types.h -index 1e87624..982e968 100644 ---- a/drivers/gpu/drm/amd/dal/dc/dm_services_types.h -+++ b/drivers/gpu/drm/amd/dal/dc/dm_services_types.h -@@ -212,6 +212,11 @@ enum dm_pp_clock_type { - struct dm_pp_clock_levels { - uint32_t num_levels; - uint32_t clocks_in_khz[DM_PP_MAX_CLOCK_LEVELS]; -+ -+ /* TODO: add latency for polaris11 -+ * do we need to know invalid (unsustainable boost) level for watermark -+ * programming? if not we can just report less elements in array -+ */ - }; - - struct dm_pp_single_disp_config { -diff --git a/drivers/gpu/drm/amd/dal/dc/gpio/hw_factory.c b/drivers/gpu/drm/amd/dal/dc/gpio/hw_factory.c -index 63d6b54..5037a2d 100644 ---- a/drivers/gpu/drm/amd/dal/dc/gpio/hw_factory.c -+++ b/drivers/gpu/drm/amd/dal/dc/gpio/hw_factory.c -@@ -78,6 +78,9 @@ bool dal_hw_factory_init( - #endif - #if defined(CONFIG_DRM_AMD_DAL_DCE11_0) - case DCE_VERSION_11_0: -+#if defined(CONFIG_DRM_AMD_DAL_DCE11_2) -+ case DCE_VERSION_11_2: -+#endif - dal_hw_factory_dce110_init(factory); - return true; - #endif -diff --git a/drivers/gpu/drm/amd/dal/dc/gpio/hw_translate.c b/drivers/gpu/drm/amd/dal/dc/gpio/hw_translate.c -index d3c6bc8..da56db7 100644 ---- a/drivers/gpu/drm/amd/dal/dc/gpio/hw_translate.c -+++ b/drivers/gpu/drm/amd/dal/dc/gpio/hw_translate.c -@@ -75,6 +75,9 @@ bool dal_hw_translate_init( - case DCE_VERSION_10_0: - #endif - case DCE_VERSION_11_0: -+#if defined(CONFIG_DRM_AMD_DAL_DCE11_2) -+ case DCE_VERSION_11_2: -+#endif - dal_hw_translate_dce110_init(translate); - return true; - #endif -diff --git a/drivers/gpu/drm/amd/dal/dc/gpu/Makefile b/drivers/gpu/drm/amd/dal/dc/gpu/Makefile -index cb23508..3095006 100644 ---- a/drivers/gpu/drm/amd/dal/dc/gpu/Makefile -+++ b/drivers/gpu/drm/amd/dal/dc/gpu/Makefile -@@ -32,3 +32,11 @@ AMD_DAL_GPU_DCE110 = $(addprefix $(AMDDALPATH)/dc/gpu/dce110/,$(GPU_DCE110)) - - AMD_DAL_FILES += $(AMD_DAL_GPU_DCE110) - endif -+ -+ifdef CONFIG_DRM_AMD_DAL_DCE11_2 -+GPU_DCE112 = display_clock_dce112.o dc_clock_gating_dce112.o -+ -+AMD_DAL_GPU_DCE112 = $(addprefix $(AMDDALPATH)/dc/gpu/dce112/,$(GPU_DCE112)) -+ -+AMD_DAL_FILES += $(AMD_DAL_GPU_DCE110) $(AMD_DAL_GPU_DCE112) -+endif -diff --git a/drivers/gpu/drm/amd/dal/dc/gpu/dce112/dc_clock_gating_dce112.c b/drivers/gpu/drm/amd/dal/dc/gpu/dce112/dc_clock_gating_dce112.c -new file mode 100644 -index 0000000..bf24457 ---- /dev/null -+++ b/drivers/gpu/drm/amd/dal/dc/gpu/dce112/dc_clock_gating_dce112.c -@@ -0,0 +1,89 @@ -+/* -+ * Copyright 2012-15 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 "dm_services.h" -+ -+#include "include/logger_interface.h" -+ -+#include "dce/dce_11_2_d.h" -+#include "dce/dce_11_2_sh_mask.h" -+#include "dc_clock_gating_dce112.h" -+ -+/****************************************************************************** -+ * Macro definitions -+ *****************************************************************************/ -+ -+#define NOT_IMPLEMENTED() DAL_LOGGER_NOT_IMPL(LOG_MINOR_COMPONENT_GPU, \ -+ "%s:%s()\n", __FILE__, __func__) -+ -+/****************************************************************************** -+ * static functions -+ *****************************************************************************/ -+static void force_hw_base_light_sleep(struct dc_context *ctx) -+{ -+ uint32_t addr = 0; -+ uint32_t value = 0; -+ -+ addr = mmDC_MEM_GLOBAL_PWR_REQ_CNTL; -+ /* Read the mmDC_MEM_GLOBAL_PWR_REQ_CNTL to get the currently -+ * programmed DC_MEM_GLOBAL_PWR_REQ_DIS*/ -+ value = dm_read_reg(ctx, addr); -+ -+ set_reg_field_value( -+ value, -+ 1, -+ DC_MEM_GLOBAL_PWR_REQ_CNTL, -+ DC_MEM_GLOBAL_PWR_REQ_DIS); -+ -+ dm_write_reg(ctx, addr, value); -+ -+} -+ -+static void enable_hw_base_light_sleep(struct dc_context *ctx) -+{ -+ NOT_IMPLEMENTED(); -+} -+ -+static void disable_sw_manual_control_light_sleep( -+ struct dc_context *ctx) -+{ -+ NOT_IMPLEMENTED(); -+} -+ -+/****************************************************************************** -+ * public functions -+ *****************************************************************************/ -+ -+void dal_dc_clock_gating_dce112_power_up( -+ struct dc_context *ctx, -+ bool enable) -+{ -+ if (enable) { -+ enable_hw_base_light_sleep(ctx); -+ disable_sw_manual_control_light_sleep(ctx); -+ } else { -+ force_hw_base_light_sleep(ctx); -+ } -+} -diff --git a/drivers/gpu/drm/amd/dal/dc/gpu/dce112/dc_clock_gating_dce112.h b/drivers/gpu/drm/amd/dal/dc/gpu/dce112/dc_clock_gating_dce112.h -new file mode 100644 -index 0000000..118da64 ---- /dev/null -+++ b/drivers/gpu/drm/amd/dal/dc/gpu/dce112/dc_clock_gating_dce112.h -@@ -0,0 +1,33 @@ -+/* -+ * Copyright 2012-15 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 __DAL_DC_CLOCK_GATING_DCE112_H__ -+#define __DAL_DC_CLOCK_GATING_DCE112_H__ -+ -+void dal_dc_clock_gating_dce112_power_up( -+ struct dc_context *ctx, -+ bool enable); -+ -+#endif /* __DAL_DC_CLOCK_GATING_DCE110_H__ */ -diff --git a/drivers/gpu/drm/amd/dal/dc/gpu/dce112/display_clock_dce112.c b/drivers/gpu/drm/amd/dal/dc/gpu/dce112/display_clock_dce112.c -new file mode 100644 -index 0000000..e559f95 ---- /dev/null -+++ b/drivers/gpu/drm/amd/dal/dc/gpu/dce112/display_clock_dce112.c -@@ -0,0 +1,964 @@ -+/* -+ * Copyright 2012-15 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 "dm_services.h" -+ -+#include "dce/dce_11_2_d.h" -+#include "dce/dce_11_2_sh_mask.h" -+ -+#include "include/adapter_service_interface.h" -+#include "include/bios_parser_interface.h" -+#include "include/fixed32_32.h" -+#include "include/logger_interface.h" -+ -+#include "../divider_range.h" -+ -+#include "display_clock_dce112.h" -+ -+#define FROM_DISPLAY_CLOCK(base) \ -+ container_of(base, struct display_clock_dce112, disp_clk_base) -+ -+static struct state_dependent_clocks max_clks_by_state[] = { -+/*ClocksStateInvalid - should not be used*/ -+{ .display_clk_khz = 0, .pixel_clk_khz = 0 }, -+/*ClocksStateUltraLow - currently by HW design team not supposed to be used*/ -+{ .display_clk_khz = 352000, .pixel_clk_khz = 330000 }, -+/*ClocksStateLow*/ -+{ .display_clk_khz = 352000, .pixel_clk_khz = 330000 }, -+/*ClocksStateNominal*/ -+{ .display_clk_khz = 467000, .pixel_clk_khz = 400000 }, -+/*ClocksStatePerformance*/ -+{ .display_clk_khz = 643000, .pixel_clk_khz = 4000000 } }; -+ -+/* Starting point for each divider range.*/ -+enum divider_range_start { -+ DIVIDER_RANGE_01_START = 200, /* 2.00*/ -+ DIVIDER_RANGE_02_START = 1600, /* 16.00*/ -+ DIVIDER_RANGE_03_START = 3200, /* 32.00*/ -+ DIVIDER_RANGE_SCALE_FACTOR = 100 /* Results are scaled up by 100.*/ -+}; -+ -+/* Array identifiers and count for the divider ranges.*/ -+enum divider_range_count { -+ DIVIDER_RANGE_01 = 0, -+ DIVIDER_RANGE_02, -+ DIVIDER_RANGE_03, -+ DIVIDER_RANGE_MAX /* == 3*/ -+}; -+ -+/* Ranges for divider identifiers (Divider ID or DID) -+ mmDENTIST_DISPCLK_CNTL.DENTIST_DISPCLK_WDIVIDER*/ -+enum divider_id_register_setting { -+ DIVIDER_RANGE_01_BASE_DIVIDER_ID = 0X08, -+ DIVIDER_RANGE_02_BASE_DIVIDER_ID = 0X40, -+ DIVIDER_RANGE_03_BASE_DIVIDER_ID = 0X60, -+ DIVIDER_RANGE_MAX_DIVIDER_ID = 0X80 -+}; -+ -+/* Step size between each divider within a range. -+ Incrementing the DENTIST_DISPCLK_WDIVIDER by one -+ will increment the divider by this much.*/ -+enum divider_range_step_size { -+ DIVIDER_RANGE_01_STEP_SIZE = 25, /* 0.25*/ -+ DIVIDER_RANGE_02_STEP_SIZE = 50, /* 0.50*/ -+ DIVIDER_RANGE_03_STEP_SIZE = 100 /* 1.00 */ -+}; -+ -+static struct divider_range divider_ranges[DIVIDER_RANGE_MAX]; -+ -+#define dce112_DFS_BYPASS_THRESHOLD_KHZ 400000 -+/***************************************************************************** -+ * static functions -+ *****************************************************************************/ -+ -+/* -+ * store_max_clocks_state -+ * -+ * @brief -+ * Cache the clock state -+ * -+ * @param -+ * struct display_clock *base - [out] cach the state in this structure -+ * enum clocks_state max_clocks_state - [in] state to be stored -+ */ -+static void store_max_clocks_state( -+ struct display_clock *base, -+ enum clocks_state max_clocks_state) -+{ -+ struct display_clock_dce112 *dc = DCLCK112_FROM_BASE(base); -+ -+ switch (max_clocks_state) { -+ case CLOCKS_STATE_LOW: -+ case CLOCKS_STATE_NOMINAL: -+ case CLOCKS_STATE_PERFORMANCE: -+ case CLOCKS_STATE_ULTRA_LOW: -+ dc->max_clks_state = max_clocks_state; -+ break; -+ -+ case CLOCKS_STATE_INVALID: -+ default: -+ /*Invalid Clocks State!*/ -+ ASSERT_CRITICAL(false); -+ break; -+ } -+} -+ -+static enum clocks_state get_min_clocks_state(struct display_clock *base) -+{ -+ return base->cur_min_clks_state; -+} -+ -+static bool set_min_clocks_state( -+ struct display_clock *base, -+ enum clocks_state clocks_state) -+{ -+ struct display_clock_dce112 *dc = DCLCK112_FROM_BASE(base); -+ -+ if (clocks_state > dc->max_clks_state) { -+ /*Requested state exceeds max supported state.*/ -+ dal_logger_write(base->ctx->logger, -+ LOG_MAJOR_WARNING, -+ LOG_MINOR_COMPONENT_GPU, -+ "Requested state exceeds max supported state"); -+ return false; -+ } else if (clocks_state == base->cur_min_clks_state) { -+ /*if we're trying to set the same state, we can just return -+ * since nothing needs to be done*/ -+ return true; -+ } -+ -+ base->cur_min_clks_state = clocks_state; -+ -+ return true; -+} -+ -+static uint32_t get_dp_ref_clk_frequency(struct display_clock *dc) -+{ -+ uint32_t dispclk_cntl_value; -+ uint32_t dp_ref_clk_cntl_value; -+ uint32_t dp_ref_clk_cntl_src_sel_value; -+ uint32_t dp_ref_clk_khz = 600000; -+ uint32_t target_div = INVALID_DIVIDER; -+ struct display_clock_dce112 *disp_clk = FROM_DISPLAY_CLOCK(dc); -+ -+ /* ASSERT DP Reference Clock source is from DFS*/ -+ dp_ref_clk_cntl_value = dm_read_reg(dc->ctx, -+ mmDPREFCLK_CNTL); -+ -+ dp_ref_clk_cntl_src_sel_value = -+ get_reg_field_value( -+ dp_ref_clk_cntl_value, -+ DPREFCLK_CNTL, DPREFCLK_SRC_SEL); -+ -+ ASSERT(dp_ref_clk_cntl_src_sel_value == 0); -+ -+ /* Read the mmDENTIST_DISPCLK_CNTL to get the currently -+ * programmed DID DENTIST_DPREFCLK_WDIVIDER*/ -+ dispclk_cntl_value = dm_read_reg(dc->ctx, -+ mmDENTIST_DISPCLK_CNTL); -+ -+ /* Convert DENTIST_DPREFCLK_WDIVIDERto actual divider*/ -+ target_div = dal_divider_range_get_divider( -+ divider_ranges, -+ DIVIDER_RANGE_MAX, -+ get_reg_field_value(dispclk_cntl_value, -+ DENTIST_DISPCLK_CNTL, -+ DENTIST_DPREFCLK_WDIVIDER)); -+ -+ if (target_div != INVALID_DIVIDER) { -+ /* Calculate the current DFS clock, in kHz.*/ -+ dp_ref_clk_khz = (DIVIDER_RANGE_SCALE_FACTOR -+ * disp_clk->dentist_vco_freq_khz) / target_div; -+ } -+ -+ /* SW will adjust DP REF Clock average value for all purposes -+ * (DP DTO / DP Audio DTO and DP GTC) -+ if clock is spread for all cases: -+ -if SS enabled on DP Ref clock and HW de-spreading enabled with SW -+ calculations for DS_INCR/DS_MODULO (this is planned to be default case) -+ -if SS enabled on DP Ref clock and HW de-spreading enabled with HW -+ calculations (not planned to be used, but average clock should still -+ be valid) -+ -if SS enabled on DP Ref clock and HW de-spreading disabled -+ (should not be case with CIK) then SW should program all rates -+ generated according to average value (case as with previous ASICs) -+ */ -+ if ((disp_clk->ss_on_gpu_pll) && (disp_clk->gpu_pll_ss_divider != 0)) { -+ struct fixed32_32 ss_percentage = dal_fixed32_32_div_int( -+ dal_fixed32_32_from_fraction( -+ disp_clk->gpu_pll_ss_percentage, -+ disp_clk->gpu_pll_ss_divider), 200); -+ struct fixed32_32 adj_dp_ref_clk_khz; -+ -+ ss_percentage = dal_fixed32_32_sub(dal_fixed32_32_one, -+ ss_percentage); -+ adj_dp_ref_clk_khz = -+ dal_fixed32_32_mul_int( -+ ss_percentage, -+ dp_ref_clk_khz); -+ dp_ref_clk_khz = dal_fixed32_32_floor(adj_dp_ref_clk_khz); -+ } -+ -+ return dp_ref_clk_khz; -+} -+ -+static void destroy(struct display_clock **base) -+{ -+ struct display_clock_dce112 *dc112; -+ -+ dc112 = DCLCK112_FROM_BASE(*base); -+ -+ dm_free(dc112); -+ -+ *base = NULL; -+} -+ -+static uint32_t get_validation_clock(struct display_clock *dc) -+{ -+ uint32_t clk = 0; -+ struct display_clock_dce112 *disp_clk = DCLCK112_FROM_BASE(dc); -+ -+ switch (disp_clk->max_clks_state) { -+ case CLOCKS_STATE_ULTRA_LOW: -+ /*Currently not supported, it has 0 in table entry*/ -+ case CLOCKS_STATE_LOW: -+ clk = max_clks_by_state[CLOCKS_STATE_LOW]. -+ display_clk_khz; -+ break; -+ -+ case CLOCKS_STATE_NOMINAL: -+ clk = max_clks_by_state[CLOCKS_STATE_NOMINAL]. -+ display_clk_khz; -+ break; -+ -+ case CLOCKS_STATE_PERFORMANCE: -+ clk = max_clks_by_state[CLOCKS_STATE_PERFORMANCE]. -+ display_clk_khz; -+ break; -+ -+ case CLOCKS_STATE_INVALID: -+ default: -+ /*Invalid Clocks State*/ -+ dal_logger_write(dc->ctx->logger, -+ LOG_MAJOR_WARNING, -+ LOG_MINOR_COMPONENT_GPU, -+ "Invalid clock state"); -+ /* just return the display engine clock for -+ * lowest supported state*/ -+ clk = max_clks_by_state[CLOCKS_STATE_LOW]. -+ display_clk_khz; -+ break; -+ } -+ return clk; -+} -+ -+static struct fixed32_32 get_deep_color_factor(struct min_clock_params *params) -+{ -+ /* DeepColorFactor = IF (HDMI = True, bpp / 24, 1)*/ -+ struct fixed32_32 deep_color_factor = dal_fixed32_32_from_int(1); -+ -+ if (params->signal_type != SIGNAL_TYPE_HDMI_TYPE_A) -+ return deep_color_factor; -+ -+ switch (params->deep_color_depth) { -+ case COLOR_DEPTH_101010: -+ /*deep color ratio for 30bpp is 30/24 = 1.25*/ -+ deep_color_factor = dal_fixed32_32_from_fraction(30, 24); -+ break; -+ -+ case COLOR_DEPTH_121212: -+ /* deep color ratio for 36bpp is 36/24 = 1.5*/ -+ deep_color_factor = dal_fixed32_32_from_fraction(36, 24); -+ break; -+ -+ case COLOR_DEPTH_161616: -+ /* deep color ratio for 48bpp is 48/24 = 2.0 */ -+ deep_color_factor = dal_fixed32_32_from_fraction(48, 24); -+ break; -+ default: -+ break; -+ } -+ return deep_color_factor; -+} -+ -+static struct fixed32_32 get_scaler_efficiency( -+ struct dc_context *ctx, -+ struct min_clock_params *params) -+{ -+ struct fixed32_32 scaler_efficiency = dal_fixed32_32_from_int(3); -+ -+ if (params->scaler_efficiency == V_SCALER_EFFICIENCY_LB18BPP) { -+ scaler_efficiency = -+ dal_fixed32_32_add( -+ dal_fixed32_32_from_fraction(35555, 10000), -+ dal_fixed32_32_from_fraction( -+ 55556, -+ 100000 * 10000)); -+ } else if (params->scaler_efficiency == V_SCALER_EFFICIENCY_LB24BPP) { -+ scaler_efficiency = -+ dal_fixed32_32_add( -+ dal_fixed32_32_from_fraction(34285, 10000), -+ dal_fixed32_32_from_fraction( -+ 71429, -+ 100000 * 10000)); -+ } else if (params->scaler_efficiency == V_SCALER_EFFICIENCY_LB30BPP) -+ scaler_efficiency = dal_fixed32_32_from_fraction(32, 10); -+ -+ return scaler_efficiency; -+} -+ -+static struct fixed32_32 get_lb_lines_in_per_line_out( -+ struct min_clock_params *params, -+ struct fixed32_32 v_scale_ratio) -+{ -+ struct fixed32_32 two = dal_fixed32_32_from_int(2); -+ struct fixed32_32 four = dal_fixed32_32_from_int(4); -+ struct fixed32_32 f4_to_3 = dal_fixed32_32_from_fraction(4, 3); -+ struct fixed32_32 f6_to_4 = dal_fixed32_32_from_fraction(6, 4); -+ -+ if (params->line_buffer_prefetch_enabled) -+ return dal_fixed32_32_max(v_scale_ratio, dal_fixed32_32_one); -+ else if (dal_fixed32_32_le(v_scale_ratio, dal_fixed32_32_one)) -+ return dal_fixed32_32_one; -+ else if (dal_fixed32_32_le(v_scale_ratio, f4_to_3)) -+ return f4_to_3; -+ else if (dal_fixed32_32_le(v_scale_ratio, f6_to_4)) -+ return f6_to_4; -+ else if (dal_fixed32_32_le(v_scale_ratio, two)) -+ return two; -+ else if (dal_fixed32_32_le(v_scale_ratio, dal_fixed32_32_from_int(3))) -+ return four; -+ else -+ return dal_fixed32_32_zero; -+} -+ -+static uint32_t get_actual_required_display_clk( -+ struct display_clock_dce112 *disp_clk, -+ uint32_t target_clk_khz) -+{ -+ uint32_t disp_clk_khz = target_clk_khz; -+ uint32_t div = INVALID_DIVIDER; -+ uint32_t did = INVALID_DID; -+ uint32_t scaled_vco = -+ disp_clk->dentist_vco_freq_khz * DIVIDER_RANGE_SCALE_FACTOR; -+ -+ ASSERT_CRITICAL(!!disp_clk_khz); -+ -+ if (disp_clk_khz) -+ div = scaled_vco / disp_clk_khz; -+ -+ did = dal_divider_range_get_did(divider_ranges, DIVIDER_RANGE_MAX, div); -+ -+ if (did != INVALID_DID) { -+ div = dal_divider_range_get_divider( -+ divider_ranges, DIVIDER_RANGE_MAX, did); -+ -+ if ((div != INVALID_DIVIDER) && -+ (did > DIVIDER_RANGE_01_BASE_DIVIDER_ID)) -+ if (disp_clk_khz > (scaled_vco / div)) -+ div = dal_divider_range_get_divider( -+ divider_ranges, DIVIDER_RANGE_MAX, -+ did - 1); -+ -+ if (div != INVALID_DIVIDER) -+ disp_clk_khz = scaled_vco / div; -+ -+ } -+ /* We need to add 10KHz to this value because the accuracy in VBIOS is -+ in 10KHz units. So we need to always round the last digit up in order -+ to reach the next div level.*/ -+ return disp_clk_khz + 10; -+} -+ -+static uint32_t calc_single_display_min_clks( -+ struct display_clock *base, -+ struct min_clock_params *params, -+ bool set_clk) -+{ -+ struct fixed32_32 h_scale_ratio = dal_fixed32_32_one; -+ struct fixed32_32 v_scale_ratio = dal_fixed32_32_one; -+ uint32_t pix_clk_khz = 0; -+ uint32_t lb_source_width = 0; -+ struct fixed32_32 deep_color_factor; -+ struct fixed32_32 scaler_efficiency; -+ struct fixed32_32 v_filter_init; -+ uint32_t v_filter_init_trunc; -+ uint32_t num_lines_at_frame_start = 3; -+ struct fixed32_32 v_filter_init_ceil; -+ struct fixed32_32 lines_per_lines_out_at_frame_start; -+ struct fixed32_32 lb_lines_in_per_line_out; /* in middle of the frame*/ -+ uint32_t src_wdth_rnd_to_chunks; -+ struct fixed32_32 scaling_coeff; -+ struct fixed32_32 h_blank_granularity_factor = -+ dal_fixed32_32_one; -+ struct fixed32_32 fx_disp_clk_mhz; -+ struct fixed32_32 line_time; -+ struct fixed32_32 disp_pipe_pix_throughput; -+ struct fixed32_32 fx_alt_disp_clk_mhz; -+ uint32_t disp_clk_khz; -+ uint32_t alt_disp_clk_khz; -+ struct display_clock_dce112 *disp_clk_110 = DCLCK112_FROM_BASE(base); -+ uint32_t max_clk_khz = get_validation_clock(base); -+ bool panning_allowed = false; /* TODO: receive this value from AS */ -+ -+ if (params == NULL) { -+ dal_logger_write(base->ctx->logger, -+ LOG_MAJOR_WARNING, -+ LOG_MINOR_COMPONENT_GPU, -+ "Invalid input parameter in %s", -+ __func__); -+ return 0; -+ } -+ -+ deep_color_factor = get_deep_color_factor(params); -+ scaler_efficiency = get_scaler_efficiency(base->ctx, params); -+ pix_clk_khz = params->requested_pixel_clock; -+ lb_source_width = params->source_view.width; -+ -+ if (0 != params->dest_view.height && 0 != params->dest_view.width) { -+ -+ h_scale_ratio = dal_fixed32_32_from_fraction( -+ params->source_view.width, -+ params->dest_view.width); -+ v_scale_ratio = dal_fixed32_32_from_fraction( -+ params->source_view.height, -+ params->dest_view.height); -+ } else { -+ dal_logger_write(base->ctx->logger, -+ LOG_MAJOR_WARNING, -+ LOG_MINOR_COMPONENT_GPU, -+ "Destination height or width is 0!\n"); -+ } -+ -+ v_filter_init = -+ dal_fixed32_32_add( -+ v_scale_ratio, -+ dal_fixed32_32_add_int( -+ dal_fixed32_32_div_int( -+ dal_fixed32_32_mul_int( -+ v_scale_ratio, -+ params->timing_info.INTERLACED), -+ 2), -+ params->scaling_info.v_taps + 1)); -+ v_filter_init = dal_fixed32_32_div_int(v_filter_init, 2); -+ -+ v_filter_init_trunc = dal_fixed32_32_floor(v_filter_init); -+ -+ v_filter_init_ceil = dal_fixed32_32_from_fraction( -+ v_filter_init_trunc, 2); -+ v_filter_init_ceil = dal_fixed32_32_from_int( -+ dal_fixed32_32_ceil(v_filter_init_ceil)); -+ v_filter_init_ceil = dal_fixed32_32_mul_int(v_filter_init_ceil, 2); -+ -+ lines_per_lines_out_at_frame_start = -+ dal_fixed32_32_div_int(v_filter_init_ceil, -+ num_lines_at_frame_start); -+ lb_lines_in_per_line_out = -+ get_lb_lines_in_per_line_out(params, v_scale_ratio); -+ -+ if (panning_allowed) -+ src_wdth_rnd_to_chunks = -+ ((lb_source_width - 1) / 128) * 128 + 256; -+ else -+ src_wdth_rnd_to_chunks = -+ ((lb_source_width + 127) / 128) * 128; -+ -+ scaling_coeff = -+ dal_fixed32_32_div( -+ dal_fixed32_32_from_int(params->scaling_info.v_taps), -+ scaler_efficiency); -+ -+ if (dal_fixed32_32_le(h_scale_ratio, dal_fixed32_32_one)) -+ scaling_coeff = dal_fixed32_32_max( -+ dal_fixed32_32_from_int( -+ dal_fixed32_32_ceil( -+ dal_fixed32_32_from_fraction( -+ params->scaling_info.h_taps, -+ 4))), -+ dal_fixed32_32_max( -+ dal_fixed32_32_mul( -+ scaling_coeff, -+ h_scale_ratio), -+ dal_fixed32_32_one)); -+ -+ if (!params->line_buffer_prefetch_enabled && -+ dal_fixed32_32_floor(lb_lines_in_per_line_out) != 2 && -+ dal_fixed32_32_floor(lb_lines_in_per_line_out) != 4) { -+ uint32_t line_total_pixel = -+ params->timing_info.h_total + lb_source_width - 256; -+ h_blank_granularity_factor = dal_fixed32_32_div( -+ dal_fixed32_32_from_int(params->timing_info.h_total), -+ dal_fixed32_32_div( -+ dal_fixed32_32_from_fraction( -+ line_total_pixel, 2), -+ h_scale_ratio)); -+ } -+ -+ /* Calculate display clock with ramping. Ramping factor is 1.1*/ -+ fx_disp_clk_mhz = -+ dal_fixed32_32_div_int( -+ dal_fixed32_32_mul_int(scaling_coeff, 11), -+ 10); -+ line_time = dal_fixed32_32_from_fraction( -+ params->timing_info.h_total * 1000, pix_clk_khz); -+ -+ disp_pipe_pix_throughput = dal_fixed32_32_mul( -+ lb_lines_in_per_line_out, h_blank_granularity_factor); -+ disp_pipe_pix_throughput = dal_fixed32_32_max( -+ disp_pipe_pix_throughput, -+ lines_per_lines_out_at_frame_start); -+ disp_pipe_pix_throughput = dal_fixed32_32_div(dal_fixed32_32_mul_int( -+ disp_pipe_pix_throughput, src_wdth_rnd_to_chunks), -+ line_time); -+ -+ if (0 != params->timing_info.h_total) { -+ fx_disp_clk_mhz = -+ dal_fixed32_32_max( -+ dal_fixed32_32_div_int( -+ dal_fixed32_32_mul_int( -+ scaling_coeff, pix_clk_khz), -+ 1000), -+ disp_pipe_pix_throughput); -+ fx_disp_clk_mhz = -+ dal_fixed32_32_mul( -+ fx_disp_clk_mhz, -+ dal_fixed32_32_from_fraction(11, 10)); -+ } -+ -+ fx_disp_clk_mhz = dal_fixed32_32_max(fx_disp_clk_mhz, -+ dal_fixed32_32_mul(deep_color_factor, -+ dal_fixed32_32_from_fraction(11, 10))); -+ -+ /* Calculate display clock without ramping */ -+ fx_alt_disp_clk_mhz = scaling_coeff; -+ -+ if (0 != params->timing_info.h_total) { -+ fx_alt_disp_clk_mhz = dal_fixed32_32_max( -+ dal_fixed32_32_div_int(dal_fixed32_32_mul_int( -+ scaling_coeff, pix_clk_khz), -+ 1000), -+ dal_fixed32_32_div_int(dal_fixed32_32_mul_int( -+ disp_pipe_pix_throughput, 105), -+ 100)); -+ } -+ -+ if (set_clk && disp_clk_110->ss_on_gpu_pll && -+ disp_clk_110->gpu_pll_ss_divider) -+ fx_alt_disp_clk_mhz = dal_fixed32_32_mul(fx_alt_disp_clk_mhz, -+ dal_fixed32_32_add_int( -+ dal_fixed32_32_div_int( -+ dal_fixed32_32_div_int( -+ dal_fixed32_32_from_fraction( -+ disp_clk_110->gpu_pll_ss_percentage, -+ disp_clk_110->gpu_pll_ss_divider), 100), -+ 2), -+ 1)); -+ -+ /* convert to integer */ -+ disp_clk_khz = dal_fixed32_32_round( -+ dal_fixed32_32_mul_int(fx_disp_clk_mhz, 1000)); -+ alt_disp_clk_khz = dal_fixed32_32_round( -+ dal_fixed32_32_mul_int(fx_alt_disp_clk_mhz, 1000)); -+ -+ if ((disp_clk_khz > max_clk_khz) && (alt_disp_clk_khz <= max_clk_khz)) -+ disp_clk_khz = alt_disp_clk_khz; -+ -+ if (set_clk) { /* only compensate clock if we are going to set it.*/ -+ disp_clk_khz = get_actual_required_display_clk( -+ disp_clk_110, disp_clk_khz); -+ } -+ -+ disp_clk_khz = disp_clk_khz > max_clk_khz ? max_clk_khz : disp_clk_khz; -+ -+ return disp_clk_khz; -+} -+ -+static uint32_t calculate_min_clock( -+ struct display_clock *base, -+ uint32_t path_num, -+ struct min_clock_params *params) -+{ -+ uint32_t i; -+ uint32_t validation_clk_khz = -+ get_validation_clock(base); -+ uint32_t min_clk_khz = validation_clk_khz; -+ uint32_t max_clk_khz = 0; -+ struct display_clock_dce112 *dc = DCLCK112_FROM_BASE(base); -+ -+ if (dc->use_max_disp_clk) -+ return min_clk_khz; -+ -+ if (params != NULL) { -+ uint32_t disp_clk_khz = 0; -+ -+ for (i = 0; i < path_num; ++i) { -+ -+ disp_clk_khz = calc_single_display_min_clks( -+ base, params, true); -+ -+ /* update the max required clock found*/ -+ if (disp_clk_khz > max_clk_khz) -+ max_clk_khz = disp_clk_khz; -+ -+ params++; -+ } -+ } -+ -+ min_clk_khz = max_clk_khz; -+ -+ if (min_clk_khz > validation_clk_khz) -+ min_clk_khz = validation_clk_khz; -+ else if (min_clk_khz < base->min_display_clk_threshold_khz) -+ min_clk_khz = base->min_display_clk_threshold_khz; -+ -+ if (dc->use_max_disp_clk) -+ min_clk_khz = get_validation_clock(base); -+ -+ return min_clk_khz; -+} -+ -+static bool display_clock_integrated_info_construct( -+ struct display_clock_dce112 *disp_clk, -+ struct adapter_service *as) -+{ -+ struct integrated_info info; -+ uint32_t i; -+ struct display_clock *base = &disp_clk->disp_clk_base; -+ -+ memset(&info, 0, sizeof(struct integrated_info)); -+ -+ disp_clk->dentist_vco_freq_khz = info.dentist_vco_freq; -+ if (disp_clk->dentist_vco_freq_khz == 0) -+ disp_clk->dentist_vco_freq_khz = 3600000; -+ -+ disp_clk->crystal_freq_khz = 100000; -+ -+ base->min_display_clk_threshold_khz = -+ disp_clk->dentist_vco_freq_khz / 64; -+ -+ /*update the maximum display clock for each power state*/ -+ for (i = 0; i < NUMBER_OF_DISP_CLK_VOLTAGE; ++i) { -+ enum clocks_state clk_state = CLOCKS_STATE_INVALID; -+ -+ switch (i) { -+ case 0: -+ clk_state = CLOCKS_STATE_ULTRA_LOW; -+ break; -+ -+ case 1: -+ clk_state = CLOCKS_STATE_LOW; -+ break; -+ -+ case 2: -+ clk_state = CLOCKS_STATE_NOMINAL; -+ break; -+ -+ case 3: -+ clk_state = CLOCKS_STATE_PERFORMANCE; -+ break; -+ -+ default: -+ clk_state = CLOCKS_STATE_INVALID; -+ break; -+ } -+ -+ /*Do not allow bad VBIOS/SBIOS to override with invalid values, -+ * check for > 100MHz*/ -+ if (info.disp_clk_voltage[i].max_supported_clk >= 100000) { -+ max_clks_by_state[clk_state].display_clk_khz = -+ info.disp_clk_voltage[i].max_supported_clk; -+ } -+ } -+ disp_clk->dfs_bypass_enabled = -+ dal_adapter_service_is_dfs_bypass_enabled(as); -+ disp_clk->use_max_disp_clk = -+ dal_adapter_service_is_feature_supported( -+ FEATURE_USE_MAX_DISPLAY_CLK); -+ -+ return true; -+} -+ -+static uint32_t get_clock(struct display_clock *dc) -+{ -+ uint32_t disp_clock = get_validation_clock(dc); -+ uint32_t target_div = INVALID_DIVIDER; -+ uint32_t addr = mmDENTIST_DISPCLK_CNTL; -+ uint32_t value = 0; -+ uint32_t field = 0; -+ struct display_clock_dce112 *disp_clk = DCLCK112_FROM_BASE(dc); -+ -+ /* Read the mmDENTIST_DISPCLK_CNTL to get the currently programmed -+ DID DENTIST_DISPCLK_WDIVIDER.*/ -+ value = dm_read_reg(dc->ctx, addr); -+ field = get_reg_field_value( -+ value, DENTIST_DISPCLK_CNTL, DENTIST_DISPCLK_WDIVIDER); -+ -+ /* Convert DENTIST_DISPCLK_WDIVIDER to actual divider*/ -+ target_div = dal_divider_range_get_divider( -+ divider_ranges, -+ DIVIDER_RANGE_MAX, -+ field); -+ -+ if (target_div != INVALID_DIVIDER) -+ /* Calculate the current DFS clock in KHz. -+ Should be okay up to 42.9 THz before overflowing.*/ -+ disp_clock = (DIVIDER_RANGE_SCALE_FACTOR -+ * disp_clk->dentist_vco_freq_khz) / target_div; -+ return disp_clock; -+} -+ -+static enum clocks_state get_required_clocks_state( -+ struct display_clock *dc, -+ struct state_dependent_clocks *req_clocks) -+{ -+ int32_t i; -+ struct display_clock_dce112 *disp_clk = DCLCK112_FROM_BASE(dc); -+ enum clocks_state low_req_clk = disp_clk->max_clks_state; -+ -+ if (!req_clocks) { -+ /* NULL pointer*/ -+ dal_logger_write(dc->ctx->logger, -+ LOG_MAJOR_WARNING, -+ LOG_MINOR_COMPONENT_GPU, -+ "%s: Invalid parameter", -+ __func__); -+ return CLOCKS_STATE_INVALID; -+ } -+ -+ /* Iterate from highest supported to lowest valid state, and update -+ * lowest RequiredState with the lowest state that satisfies -+ * all required clocks -+ */ -+ for (i = disp_clk->max_clks_state; i >= CLOCKS_STATE_ULTRA_LOW; --i) { -+ if ((req_clocks->display_clk_khz <= -+ max_clks_by_state[i].display_clk_khz) && -+ (req_clocks->pixel_clk_khz <= -+ max_clks_by_state[i].pixel_clk_khz)) -+ low_req_clk = i; -+ } -+ return low_req_clk; -+} -+ -+static void set_clock( -+ struct display_clock *base, -+ uint32_t requested_clk_khz) -+{ -+ struct bp_set_dce_clock_parameters dce_clk_params; -+ struct display_clock_dce112 *dc = DCLCK112_FROM_BASE(base); -+ struct dc_bios *bp = dal_adapter_service_get_bios_parser(base->as); -+ -+ /* Prepare to program display clock*/ -+ memset(&dce_clk_params, 0, sizeof(dce_clk_params)); -+ -+ dce_clk_params.target_clock_frequency = requested_clk_khz; -+ dce_clk_params.pll_id = dc->disp_clk_base.id; -+ dce_clk_params.clock_type = DCECLOCK_TYPE_DISPLAY_CLOCK; -+ -+ bp->funcs->set_dce_clock(bp, &dce_clk_params); -+ -+ /* from power down, we need mark the clock state as ClocksStateNominal -+ * from HWReset, so when resume we will call pplib voltage regulator.*/ -+ if (requested_clk_khz == 0) -+ base->cur_min_clks_state = CLOCKS_STATE_NOMINAL; -+ -+ /*Program DP ref Clock*/ -+ /*VBIOS will determine DPREFCLK frequency, so we don't set it*/ -+ dce_clk_params.target_clock_frequency = 0; -+ dce_clk_params.clock_type = DCECLOCK_TYPE_DPREFCLK; -+ dce_clk_params.flags.USE_GENLOCK_AS_SOURCE_FOR_DPREFCLK = -+ (dce_clk_params.pll_id == CLOCK_SOURCE_COMBO_DISPLAY_PLL0); -+ -+ bp->funcs->set_dce_clock(bp, &dce_clk_params); -+} -+ -+static void set_clock_state( -+ struct display_clock *dc, -+ struct display_clock_state clk_state) -+{ -+ struct display_clock_dce112 *disp_clk = DCLCK112_FROM_BASE(dc); -+ -+ disp_clk->clock_state = clk_state; -+} -+ -+static struct display_clock_state get_clock_state( -+ struct display_clock *dc) -+{ -+ struct display_clock_dce112 *disp_clk = DCLCK112_FROM_BASE(dc); -+ -+ return disp_clk->clock_state; -+} -+ -+static uint32_t get_dfs_bypass_threshold(struct display_clock *dc) -+{ -+ return dce112_DFS_BYPASS_THRESHOLD_KHZ; -+} -+ -+static const struct display_clock_funcs funcs = { -+ .destroy = destroy, -+ .calculate_min_clock = calculate_min_clock, -+ .get_clock = get_clock, -+ .get_clock_state = get_clock_state, -+ .get_dfs_bypass_threshold = get_dfs_bypass_threshold, -+ .get_dp_ref_clk_frequency = get_dp_ref_clk_frequency, -+ .get_min_clocks_state = get_min_clocks_state, -+ .get_required_clocks_state = get_required_clocks_state, -+ .get_validation_clock = get_validation_clock, -+ .set_clock = set_clock, -+ .set_clock_state = set_clock_state, -+ .set_dp_ref_clock_source = NULL, -+ .set_min_clocks_state = set_min_clocks_state, -+ .store_max_clocks_state = store_max_clocks_state, -+ .validate = NULL, -+}; -+ -+static bool dal_display_clock_dce112_construct( -+ struct display_clock_dce112 *dc112, -+ struct dc_context *ctx, -+ struct adapter_service *as) -+{ -+ struct display_clock *dc_base = &dc112->disp_clk_base; -+ -+ if (NULL == as) -+ return false; -+ -+ if (!dal_display_clock_construct_base(dc_base, ctx, as)) -+ return false; -+ -+ dc_base->funcs = &funcs; -+ -+ dc112->dfs_bypass_disp_clk = 0; -+ -+ if (!display_clock_integrated_info_construct(dc112, as)) -+ dal_logger_write(dc_base->ctx->logger, -+ LOG_MAJOR_WARNING, -+ LOG_MINOR_COMPONENT_GPU, -+ "Cannot obtain VBIOS integrated info\n"); -+ -+ dc112->gpu_pll_ss_percentage = 0; -+ dc112->gpu_pll_ss_divider = 1000; -+ dc112->ss_on_gpu_pll = false; -+ -+ dc_base->id = CLOCK_SOURCE_ID_DFS; -+/* Initially set max clocks state to nominal. This should be updated by -+ * via a pplib call to DAL IRI eventually calling a -+ * DisplayEngineClock_dce112::StoreMaxClocksState(). This call will come in -+ * on PPLIB init. This is from DCE5x. in case HW wants to use mixed method.*/ -+ dc112->max_clks_state = CLOCKS_STATE_NOMINAL; -+ -+ dc112->disp_clk_base.min_display_clk_threshold_khz = -+ dc112->crystal_freq_khz; -+ -+ if (dc112->disp_clk_base.min_display_clk_threshold_khz < -+ (dc112->dentist_vco_freq_khz / 62)) -+ dc112->disp_clk_base.min_display_clk_threshold_khz = -+ (dc112->dentist_vco_freq_khz / 62); -+ -+ dal_divider_range_construct( -+ ÷r_ranges[DIVIDER_RANGE_01], -+ DIVIDER_RANGE_01_START, -+ DIVIDER_RANGE_01_STEP_SIZE, -+ DIVIDER_RANGE_01_BASE_DIVIDER_ID, -+ DIVIDER_RANGE_02_BASE_DIVIDER_ID); -+ dal_divider_range_construct( -+ ÷r_ranges[DIVIDER_RANGE_02], -+ DIVIDER_RANGE_02_START, -+ DIVIDER_RANGE_02_STEP_SIZE, -+ DIVIDER_RANGE_02_BASE_DIVIDER_ID, -+ DIVIDER_RANGE_03_BASE_DIVIDER_ID); -+ dal_divider_range_construct( -+ ÷r_ranges[DIVIDER_RANGE_03], -+ DIVIDER_RANGE_03_START, -+ DIVIDER_RANGE_03_STEP_SIZE, -+ DIVIDER_RANGE_03_BASE_DIVIDER_ID, -+ DIVIDER_RANGE_MAX_DIVIDER_ID); -+ -+ { -+ uint32_t ss_info_num = -+ dal_adapter_service_get_ss_info_num( -+ as, -+ AS_SIGNAL_TYPE_GPU_PLL); -+ -+ if (ss_info_num) { -+ struct spread_spectrum_info info; -+ bool result; -+ -+ memset(&info, 0, sizeof(info)); -+ -+ result = -+ dal_adapter_service_get_ss_info( -+ as, -+ AS_SIGNAL_TYPE_GPU_PLL, -+ 0, -+ &info); -+ -+ /* Based on VBIOS, VBIOS will keep entry for GPU PLL SS -+ * even if SS not enabled and in that case -+ * SSInfo.spreadSpectrumPercentage !=0 would be sign -+ * that SS is enabled -+ */ -+ if (result && info.spread_spectrum_percentage != 0) { -+ dc112->ss_on_gpu_pll = true; -+ dc112->gpu_pll_ss_divider = -+ info.spread_percentage_divider; -+ -+ if (info.type.CENTER_MODE == 0) { -+ /* Currently for DP Reference clock we -+ * need only SS percentage for -+ * downspread */ -+ dc112->gpu_pll_ss_percentage = -+ info.spread_spectrum_percentage; -+ } -+ } -+ -+ } -+ } -+ -+ dc112->use_max_disp_clk = true; -+ -+ return true; -+} -+ -+/***************************************************************************** -+ * public functions -+ *****************************************************************************/ -+ -+struct display_clock *dal_display_clock_dce112_create( -+ struct dc_context *ctx, -+ struct adapter_service *as) -+{ -+ struct display_clock_dce112 *dc112; -+ -+ dc112 = dm_alloc(sizeof(struct display_clock_dce112)); -+ -+ if (dc112 == NULL) -+ return NULL; -+ -+ if (dal_display_clock_dce112_construct(dc112, ctx, as)) -+ return &dc112->disp_clk_base; -+ -+ dm_free(dc112); -+ -+ return NULL; -+} -diff --git a/drivers/gpu/drm/amd/dal/dc/gpu/dce112/display_clock_dce112.h b/drivers/gpu/drm/amd/dal/dc/gpu/dce112/display_clock_dce112.h -new file mode 100644 -index 0000000..02fc67a ---- /dev/null -+++ b/drivers/gpu/drm/amd/dal/dc/gpu/dce112/display_clock_dce112.h -@@ -0,0 +1,54 @@ -+/* -+ * Copyright 2012-15 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 __DAL_DISPLAY_CLOCK_DCE112_H__ -+#define __DAL_DISPLAY_CLOCK_DCE112_H__ -+ -+#include "gpu/display_clock.h" -+ -+struct display_clock_dce112 { -+ struct display_clock disp_clk_base; -+ /* Max display block clocks state*/ -+ enum clocks_state max_clks_state; -+ bool use_max_disp_clk; -+ uint32_t crystal_freq_khz; -+ uint32_t dentist_vco_freq_khz; -+ /* Cache the status of DFS-bypass feature*/ -+ bool dfs_bypass_enabled; -+ /* GPU PLL SS percentage (if down-spread enabled) */ -+ uint32_t gpu_pll_ss_percentage; -+ /* GPU PLL SS percentage Divider (100 or 1000) */ -+ uint32_t gpu_pll_ss_divider; -+ /* Flag for Enabled SS on GPU PLL */ -+ bool ss_on_gpu_pll; -+ /* Cache the display clock returned by VBIOS if DFS-bypass is enabled. -+ * This is basically "Crystal Frequency In KHz" (XTALIN) frequency */ -+ uint32_t dfs_bypass_disp_clk; -+ struct display_clock_state clock_state; -+}; -+ -+#define DCLCK112_FROM_BASE(dc_base) \ -+ container_of(dc_base, struct display_clock_dce112, disp_clk_base) -+ -+#endif /* __DAL_DISPLAY_CLOCK_DCE112_H__ */ -diff --git a/drivers/gpu/drm/amd/dal/dc/i2caux/i2caux.c b/drivers/gpu/drm/amd/dal/dc/i2caux/i2caux.c -index 47e7922..2d394cf 100644 ---- a/drivers/gpu/drm/amd/dal/dc/i2caux/i2caux.c -+++ b/drivers/gpu/drm/amd/dal/dc/i2caux/i2caux.c -@@ -88,10 +88,13 @@ struct i2caux *dal_i2caux_create( - return dal_i2caux_dce80_create(as, ctx); - #endif - #if defined(CONFIG_DRM_AMD_DAL_DCE11_0) -+ case DCE_VERSION_11_0: -+#if defined(CONFIG_DRM_AMD_DAL_DCE11_2) -+ case DCE_VERSION_11_2: -+#endif - #if defined(CONFIG_DRM_AMD_DAL_DCE10_0) - case DCE_VERSION_10_0: - #endif -- case DCE_VERSION_11_0: - return dal_i2caux_dce110_create(as, ctx); - #endif - default: -diff --git a/drivers/gpu/drm/amd/dal/dc/inc/bandwidth_calcs.h b/drivers/gpu/drm/amd/dal/dc/inc/bandwidth_calcs.h -index d6a599c..da00b2e 100644 ---- a/drivers/gpu/drm/amd/dal/dc/inc/bandwidth_calcs.h -+++ b/drivers/gpu/drm/amd/dal/dc/inc/bandwidth_calcs.h -@@ -505,7 +505,9 @@ struct bw_calcs_output { - - enum bw_calcs_version { - BW_CALCS_VERSION_INVALID, -- BW_CALCS_VERSION_CARRIZO -+ BW_CALCS_VERSION_CARRIZO, -+ BW_CALCS_VERSION_ELLESMERE, -+ BW_CALCS_VERSION_BAFFIN - }; - - /** -diff --git a/drivers/gpu/drm/amd/dal/dc/irq/irq_service.c b/drivers/gpu/drm/amd/dal/dc/irq/irq_service.c -index cde34ce..bfffa8e 100644 ---- a/drivers/gpu/drm/amd/dal/dc/irq/irq_service.c -+++ b/drivers/gpu/drm/amd/dal/dc/irq/irq_service.c -@@ -65,6 +65,10 @@ struct irq_service *dal_irq_service_create( - case DCE_VERSION_10_0: - return dal_irq_service_dce110_create(init_data); - #endif -+#if defined(CONFIG_DRM_AMD_DAL_DCE11_2) -+ case DCE_VERSION_11_2: -+ return dal_irq_service_dce110_create(init_data); -+#endif - #if defined(CONFIG_DRM_AMD_DAL_DCE11_0) - case DCE_VERSION_11_0: - return dal_irq_service_dce110_create(init_data); -diff --git a/drivers/gpu/drm/amd/dal/include/dal_asic_id.h b/drivers/gpu/drm/amd/dal/include/dal_asic_id.h -index d8c4cd1..4cb6a9f 100644 ---- a/drivers/gpu/drm/amd/dal/include/dal_asic_id.h -+++ b/drivers/gpu/drm/amd/dal/include/dal_asic_id.h -@@ -83,11 +83,25 @@ - #define VI_TONGA_P_A1 21 - #define VI_FIJI_P_A0 60 - -+#if defined(CONFIG_DRM_AMD_DAL_DCE11_2) -+/* DCE112 */ -+#define VI_POLARIS10_P_A0 80 -+#define VI_POLARIS11_M_A0 90 -+#endif -+ -+#define VI_UNKNOWN 0xFF -+ - #define ASIC_REV_IS_TONGA_P(eChipRev) ((eChipRev >= VI_TONGA_P_A0) && \ - (eChipRev < 40)) - #define ASIC_REV_IS_FIJI_P(eChipRev) ((eChipRev >= VI_FIJI_P_A0) && \ - (eChipRev < 80)) - -+#if defined(CONFIG_DRM_AMD_DAL_DCE11_2) -+#define ASIC_REV_IS_POLARIS10_P(eChipRev) ((eChipRev >= VI_POLARIS10_P_A0) && \ -+ (eChipRev < VI_POLARIS11_M_A0)) -+#define ASIC_REV_IS_POLARIS11_M(eChipRev) (eChipRev >= VI_POLARIS11_M_A0) -+#endif -+ - /* DCE11 */ - #define CZ_CARRIZO_A0 0x01 - -diff --git a/drivers/gpu/drm/amd/dal/include/dal_types.h b/drivers/gpu/drm/amd/dal/include/dal_types.h -index bcf83e9..21ee669 100644 ---- a/drivers/gpu/drm/amd/dal/include/dal_types.h -+++ b/drivers/gpu/drm/amd/dal/include/dal_types.h -@@ -43,6 +43,9 @@ enum dce_version { - #if defined(CONFIG_DRM_AMD_DAL_DCE11_0) - DCE_VERSION_11_0, - #endif -+#if defined(CONFIG_DRM_AMD_DAL_DCE11_2) -+ DCE_VERSION_11_2, -+#endif - DCE_VERSION_MAX, - }; - -diff --git a/drivers/gpu/drm/amd/dal/include/display_clock_interface.h b/drivers/gpu/drm/amd/dal/include/display_clock_interface.h -index a625e24..317ce3b 100644 ---- a/drivers/gpu/drm/amd/dal/include/display_clock_interface.h -+++ b/drivers/gpu/drm/amd/dal/include/display_clock_interface.h -@@ -131,6 +131,12 @@ struct display_clock_state { - - struct display_clock; - -+#if defined(CONFIG_DRM_AMD_DAL_DCE11_2) -+struct display_clock *dal_display_clock_dce112_create( -+ struct dc_context *ctx, -+ struct adapter_service *as); -+#endif -+ - #if defined(CONFIG_DRM_AMD_DAL_DCE11_0) - struct display_clock *dal_display_clock_dce110_create( - struct dc_context *ctx, --- -2.7.4 - |