This adds core dc support for polaris 10 and 11.

v2: add missing files

Signed-off-by: Alex Deucher <alexander.deucher at 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..bcf44802
--- /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(
+               &divider_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(
+               &divider_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(
+               &divider_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.5.0

Reply via email to