Adds dce110_resource and dce110_hw_sequencer files.

dce110_resource manages creation of HW resources, along with correct
ASIC register offset for each block.

dce110_hw_sequencers is responsible for programming HW sequences,
such as enable_stream, program_scaler, power_down_encoders, etc.

Signed-off-by: Harry Wentland <harry.wentland at amd.com>
Reviewed-by: Alex Deucher <alexander.deucher at amd.com>
---
 drivers/gpu/drm/amd/dal/dc/dce110/Makefile         |   15 +
 .../drm/amd/dal/dc/dce110/dce110_hw_sequencer.c    | 1658 ++++++++++++++++++++
 .../drm/amd/dal/dc/dce110/dce110_hw_sequencer.h    |   36 +
 .../gpu/drm/amd/dal/dc/dce110/dce110_resource.c    | 1238 +++++++++++++++
 .../gpu/drm/amd/dal/dc/dce110/dce110_resource.h    |   46 +
 5 files changed, 2993 insertions(+)
 create mode 100644 drivers/gpu/drm/amd/dal/dc/dce110/Makefile
 create mode 100644 drivers/gpu/drm/amd/dal/dc/dce110/dce110_hw_sequencer.c
 create mode 100644 drivers/gpu/drm/amd/dal/dc/dce110/dce110_hw_sequencer.h
 create mode 100644 drivers/gpu/drm/amd/dal/dc/dce110/dce110_resource.c
 create mode 100644 drivers/gpu/drm/amd/dal/dc/dce110/dce110_resource.h

diff --git a/drivers/gpu/drm/amd/dal/dc/dce110/Makefile 
b/drivers/gpu/drm/amd/dal/dc/dce110/Makefile
new file mode 100644
index 000000000000..ae9d2de92da2
--- /dev/null
+++ b/drivers/gpu/drm/amd/dal/dc/dce110/Makefile
@@ -0,0 +1,15 @@
+#
+# Makefile for the 'controller' sub-component of DAL.
+# It provides the control and status of HW CRTC block.
+
+DCE110 = dce110_ipp.o dce110_ipp_cursor.o \
+dce110_ipp_gamma.o dce110_link_encoder.o dce110_opp.o \
+dce110_opp_formatter.o dce110_opp_regamma.o dce110_stream_encoder.o \
+dce110_timing_generator.o dce110_transform.o dce110_transform_gamut.o \
+dce110_transform_scl.o dce110_transform_sclv.o dce110_opp_csc.o\
+dce110_compressor.o dce110_mem_input.o dce110_hw_sequencer.o \
+dce110_resource.o dce110_transform_bit_depth.o dce110_clock_source.o
+
+AMD_DAL_DCE110 = $(addprefix $(AMDDALPATH)/dc/dce110/,$(DCE110))
+
+AMD_DAL_FILES += $(AMD_DAL_DCE110)
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
new file mode 100644
index 000000000000..71fa7b1f8061
--- /dev/null
+++ b/drivers/gpu/drm/amd/dal/dc/dce110/dce110_hw_sequencer.c
@@ -0,0 +1,1658 @@
+/*
+ * 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 "dc_bios_types.h"
+#include "core_types.h"
+#include "core_status.h"
+#include "resource.h"
+#include "hw_sequencer.h"
+#include "dm_helpers.h"
+#include "dce110_hw_sequencer.h"
+
+#include "gpu/dce110/dc_clock_gating_dce110.h"
+
+#include "timing_generator.h"
+#include "mem_input.h"
+#include "opp.h"
+#include "ipp.h"
+#include "transform.h"
+#include "stream_encoder.h"
+#include "link_encoder.h"
+#include "clock_source.h"
+
+/* include DCE11 register header files */
+#include "dce/dce_11_0_d.h"
+#include "dce/dce_11_0_sh_mask.h"
+
+struct dce110_hw_seq_reg_offsets {
+       uint32_t dcfe;
+       uint32_t blnd;
+       uint32_t crtc;
+};
+
+enum pipe_lock_control {
+       PIPE_LOCK_CONTROL_GRAPHICS = 1 << 0,
+       PIPE_LOCK_CONTROL_BLENDER = 1 << 1,
+       PIPE_LOCK_CONTROL_SCL = 1 << 2,
+       PIPE_LOCK_CONTROL_SURFACE = 1 << 3,
+       PIPE_LOCK_CONTROL_MODE = 1 << 4
+};
+
+enum blender_mode {
+       BLENDER_MODE_CURRENT_PIPE = 0,/* Data from current pipe only */
+       BLENDER_MODE_OTHER_PIPE, /* Data from other pipe only */
+       BLENDER_MODE_BLENDING,/* Alpha blending - blend 'current' and 'other' */
+       BLENDER_MODE_STEREO
+};
+
+static const struct dce110_hw_seq_reg_offsets reg_offsets[] = {
+{
+       .dcfe = (mmDCFE0_DCFE_MEM_PWR_CTRL - mmDCFE_MEM_PWR_CTRL),
+       .blnd = (mmBLND0_BLND_CONTROL - mmBLND_CONTROL),
+       .crtc = (mmCRTC0_CRTC_GSL_CONTROL - mmCRTC_GSL_CONTROL),
+},
+{
+       .dcfe = (mmDCFE1_DCFE_MEM_PWR_CTRL - mmDCFE_MEM_PWR_CTRL),
+       .blnd = (mmBLND1_BLND_CONTROL - mmBLND_CONTROL),
+       .crtc = (mmCRTC1_CRTC_GSL_CONTROL - mmCRTC_GSL_CONTROL),
+},
+{
+       .dcfe = (mmDCFE2_DCFE_MEM_PWR_CTRL - mmDCFE_MEM_PWR_CTRL),
+       .blnd = (mmBLND2_BLND_CONTROL - mmBLND_CONTROL),
+       .crtc = (mmCRTC2_CRTC_GSL_CONTROL - mmCRTC_GSL_CONTROL),
+}
+};
+
+#define HW_REG_DCFE(reg, id)\
+       (reg + reg_offsets[id].dcfe)
+
+#define HW_REG_BLND(reg, id)\
+       (reg + reg_offsets[id].blnd)
+
+#define HW_REG_CRTC(reg, id)\
+       (reg + reg_offsets[id].crtc)
+
+
+/*******************************************************************************
+ * Private definitions
+ 
******************************************************************************/
+/***************************PIPE_CONTROL***********************************/
+static void dce110_enable_fe_clock(
+       struct dc_context *ctx, uint8_t controller_id, bool enable)
+{
+       uint32_t value = 0;
+       uint32_t addr;
+
+       /*TODO: proper offset*/
+       addr = HW_REG_DCFE(mmDCFE_CLOCK_CONTROL, controller_id);
+
+       value = dm_read_reg(ctx, addr);
+
+       set_reg_field_value(
+               value,
+               enable,
+               DCFE_CLOCK_CONTROL,
+               DCFE_CLOCK_ENABLE);
+
+       dm_write_reg(ctx, addr, value);
+}
+
+static void dce110_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);
+       }
+}
+
+/* this is a workaround for hw bug - it is a trigger on r/w */
+static void trigger_write_crtc_h_blank_start_end(
+       struct dc_context *ctx,
+       uint8_t controller_id)
+{
+       uint32_t value;
+       uint32_t addr;
+
+       addr =  HW_REG_CRTC(mmCRTC_H_BLANK_START_END, controller_id);
+       value = dm_read_reg(ctx, addr);
+       dm_write_reg(ctx, addr, value);
+}
+
+static bool dce110_pipe_control_lock(
+       struct dc_context *ctx,
+       uint8_t controller_idx,
+       uint32_t control_mask,
+       bool lock)
+{
+       uint32_t addr = HW_REG_BLND(mmBLND_V_UPDATE_LOCK, controller_idx);
+       uint32_t value = dm_read_reg(ctx, addr);
+       bool need_to_wait = false;
+
+       if (control_mask & PIPE_LOCK_CONTROL_GRAPHICS)
+               set_reg_field_value(
+                       value,
+                       lock,
+                       BLND_V_UPDATE_LOCK,
+                       BLND_DCP_GRPH_V_UPDATE_LOCK);
+
+       if (control_mask & PIPE_LOCK_CONTROL_SCL)
+               set_reg_field_value(
+                       value,
+                       lock,
+                       BLND_V_UPDATE_LOCK,
+                       BLND_SCL_V_UPDATE_LOCK);
+
+       if (control_mask & PIPE_LOCK_CONTROL_SURFACE)
+               set_reg_field_value(
+                       value,
+                       lock,
+                       BLND_V_UPDATE_LOCK,
+                       BLND_DCP_GRPH_SURF_V_UPDATE_LOCK);
+
+       if (control_mask & PIPE_LOCK_CONTROL_BLENDER) {
+               set_reg_field_value(
+                       value,
+                       lock,
+                       BLND_V_UPDATE_LOCK,
+                       BLND_BLND_V_UPDATE_LOCK);
+               need_to_wait = true;
+       }
+
+       if (control_mask & PIPE_LOCK_CONTROL_MODE)
+               set_reg_field_value(
+                       value,
+                       lock,
+                       BLND_V_UPDATE_LOCK,
+                       BLND_V_UPDATE_LOCK_MODE);
+
+       dm_write_reg(ctx, addr, value);
+
+       if (!lock && need_to_wait) {
+               uint8_t counter = 0;
+               const uint8_t counter_limit = 100;
+               const uint16_t delay_us = 1000;
+
+               uint8_t pipe_pending;
+
+               addr = HW_REG_BLND(mmBLND_REG_UPDATE_STATUS,
+                               controller_idx);
+
+               while (counter < counter_limit) {
+                       value = dm_read_reg(ctx, addr);
+
+                       pipe_pending = 0;
+
+                       if (control_mask & PIPE_LOCK_CONTROL_BLENDER) {
+                               pipe_pending |=
+                                       get_reg_field_value(
+                                               value,
+                                               BLND_REG_UPDATE_STATUS,
+                                               BLND_BLNDC_UPDATE_PENDING);
+                               pipe_pending |= get_reg_field_value(
+                                       value,
+                                       BLND_REG_UPDATE_STATUS,
+                                       BLND_BLNDO_UPDATE_PENDING);
+                       }
+
+                       if (control_mask & PIPE_LOCK_CONTROL_SCL) {
+                               pipe_pending |=
+                                       get_reg_field_value(
+                                               value,
+                                               BLND_REG_UPDATE_STATUS,
+                                               SCL_BLNDC_UPDATE_PENDING);
+                               pipe_pending |=
+                                       get_reg_field_value(
+                                               value,
+                                               BLND_REG_UPDATE_STATUS,
+                                               SCL_BLNDO_UPDATE_PENDING);
+                       }
+                       if (control_mask & PIPE_LOCK_CONTROL_GRAPHICS) {
+                               pipe_pending |=
+                                       get_reg_field_value(
+                                               value,
+                                               BLND_REG_UPDATE_STATUS,
+                                               DCP_BLNDC_GRPH_UPDATE_PENDING);
+                               pipe_pending |=
+                                       get_reg_field_value(
+                                               value,
+                                               BLND_REG_UPDATE_STATUS,
+                                               DCP_BLNDO_GRPH_UPDATE_PENDING);
+                       }
+                       if (control_mask & PIPE_LOCK_CONTROL_SURFACE) {
+                               pipe_pending |= get_reg_field_value(
+                                       value,
+                                       BLND_REG_UPDATE_STATUS,
+                                       DCP_BLNDC_GRPH_SURF_UPDATE_PENDING);
+                               pipe_pending |= get_reg_field_value(
+                                       value,
+                                       BLND_REG_UPDATE_STATUS,
+                                       DCP_BLNDO_GRPH_SURF_UPDATE_PENDING);
+                       }
+
+                       if (pipe_pending == 0)
+                               break;
+
+                       counter++;
+                       dm_delay_in_microseconds(ctx, delay_us);
+               }
+
+               if (counter == counter_limit) {
+                       dal_logger_write(
+                               ctx->logger,
+                               LOG_MAJOR_WARNING,
+                               LOG_MINOR_COMPONENT_CONTROLLER,
+                               "%s: wait for update exceeded (wait %d us)\n",
+                               __func__,
+                               counter * delay_us);
+                       dal_logger_write(
+                               ctx->logger,
+                               LOG_MAJOR_WARNING,
+                               LOG_MINOR_COMPONENT_CONTROLLER,
+                               "%s: control %d, remain value %x\n",
+                               __func__,
+                               control_mask,
+                               value);
+               } else {
+                       /* OK. */
+               }
+       }
+
+       if (!lock && (control_mask & PIPE_LOCK_CONTROL_BLENDER))
+               trigger_write_crtc_h_blank_start_end(ctx, controller_idx);
+
+       return true;
+}
+
+static void dce110_set_blender_mode(
+       struct dc_context *ctx,
+       uint8_t controller_id,
+       uint32_t mode)
+{
+       uint32_t value;
+       uint32_t addr = HW_REG_BLND(mmBLND_CONTROL, controller_id);
+       uint32_t blnd_mode;
+       uint32_t feedthrough = 0;
+
+       switch (mode) {
+       case BLENDER_MODE_OTHER_PIPE:
+               feedthrough = 0;
+               blnd_mode = 1;
+               break;
+       case BLENDER_MODE_BLENDING:
+               feedthrough = 0;
+               blnd_mode = 2;
+               break;
+       case BLENDER_MODE_CURRENT_PIPE:
+       default:
+               feedthrough = 1;
+               blnd_mode = 0;
+               break;
+       }
+
+       value = dm_read_reg(ctx, addr);
+
+       set_reg_field_value(
+               value,
+               feedthrough,
+               BLND_CONTROL,
+               BLND_FEEDTHROUGH_EN);
+
+       set_reg_field_value(
+               value,
+               blnd_mode,
+               BLND_CONTROL,
+               BLND_MODE);
+
+       dm_write_reg(ctx, addr, value);
+}
+
+static void dce110_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_EXTERNAL)
+               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 enable_display_pipe_clock_gating(
+       struct dc_context *ctx,
+       bool clock_gating)
+{
+       /*TODO*/
+}
+
+static bool dce110_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)
+               dce110_init_pte(ctx);
+
+       if (bp_result == BP_RESULT_OK)
+               return true;
+       else
+               return false;
+}
+
+
+static bool set_gamma_ramp(
+       struct input_pixel_processor *ipp,
+       struct output_pixel_processor *opp,
+       const struct gamma_ramp *ramp,
+       const struct gamma_parameters *params)
+{
+       /*Power on LUT memory*/
+       opp->funcs->opp_power_on_regamma_lut(opp, true);
+
+
+       if (params->surface_pixel_format == PIXEL_FORMAT_INDEX8 ||
+               params->selected_gamma_lut == GRAPHICS_GAMMA_LUT_LEGACY) {
+               /* do legacy DCP for 256 colors if we are requested to do so */
+               ipp->funcs->ipp_set_legacy_input_gamma_ramp(
+                       ipp, ramp, params);
+
+               ipp->funcs->ipp_set_legacy_input_gamma_mode(ipp, true);
+
+               /* set bypass */
+               ipp->funcs->ipp_program_prescale(ipp, 
PIXEL_FORMAT_UNINITIALIZED);
+
+               ipp->funcs->ipp_set_degamma(ipp, params, true);
+
+               opp->funcs->opp_set_regamma(opp, ramp, params, true);
+       } else if (params->selected_gamma_lut ==
+                       GRAPHICS_GAMMA_LUT_LEGACY_AND_REGAMMA) {
+               if (!opp->funcs->opp_map_legacy_and_regamma_hw_to_x_user(
+                       opp, ramp, params)) {
+                       BREAK_TO_DEBUGGER();
+                       /* invalid parameters or bug */
+                       return false;
+               }
+
+               /* do legacy DCP for 256 colors if we are requested to do so */
+               ipp->funcs->ipp_set_legacy_input_gamma_ramp(
+                       ipp, ramp, params);
+
+               ipp->funcs->ipp_set_legacy_input_gamma_mode(ipp, true);
+
+               /* set bypass */
+               ipp->funcs->ipp_program_prescale(ipp, 
PIXEL_FORMAT_UNINITIALIZED);
+       } else {
+               ipp->funcs->ipp_set_legacy_input_gamma_mode(ipp, false);
+
+               ipp->funcs->ipp_program_prescale(ipp, 
params->surface_pixel_format);
+
+               /* Do degamma step : remove the given gamma value from FB.
+                * For FP16 or no degamma do by pass */
+               ipp->funcs->ipp_set_degamma(ipp, params, false);
+
+               opp->funcs->opp_set_regamma(opp, ramp, params, false);
+       }
+
+       /*re-enable low power mode for LUT memory*/
+       opp->funcs->opp_power_on_regamma_lut(opp, false);
+
+       return true;
+}
+
+static enum dc_status bios_parser_crtc_source_select(
+               struct core_stream *stream)
+{
+       struct dc_bios *dcb;
+       /* call VBIOS table to set CRTC source for the HW
+        * encoder block
+        * note: video bios clears all FMT setting here. */
+       struct bp_crtc_source_select crtc_source_select = {0};
+       const struct core_sink *sink = stream->sink;
+
+       crtc_source_select.engine_id = stream->stream_enc->id;
+       crtc_source_select.controller_id = stream->controller_idx + 1;
+       /*TODO: Need to un-hardcode color depth, dp_audio and account for
+        * the case where signal and sink signal is different (translator
+        * encoder)*/
+       crtc_source_select.signal = sink->public.sink_signal;
+       crtc_source_select.enable_dp_audio = false;
+       crtc_source_select.sink_signal = sink->public.sink_signal;
+       crtc_source_select.display_output_bit_depth = PANEL_8BIT_COLOR;
+
+       dcb = dal_adapter_service_get_bios_parser(sink->link->adapter_srv);
+
+       if (BP_RESULT_OK != dcb->funcs->crtc_source_select(
+               dcb,
+               &crtc_source_select)) {
+               return DC_ERROR_UNEXPECTED;
+       }
+
+       return DC_OK;
+}
+
+static enum color_space surface_color_to_color_space(
+       struct plane_colorimetry *colorimetry)
+{
+       enum color_space color_space = COLOR_SPACE_UNKNOWN;
+
+       switch (colorimetry->color_space) {
+       case SURFACE_COLOR_SPACE_SRGB:
+       case SURFACE_COLOR_SPACE_XRRGB:
+               if (colorimetry->limited_range)
+                       color_space = COLOR_SPACE_SRGB_LIMITED_RANGE;
+               else
+                       color_space = COLOR_SPACE_SRGB_FULL_RANGE;
+               break;
+       case SURFACE_COLOR_SPACE_BT601:
+       case SURFACE_COLOR_SPACE_XVYCC_BT601:
+               color_space = COLOR_SPACE_YCBCR601;
+               break;
+       case SURFACE_COLOR_SPACE_BT709:
+       case SURFACE_COLOR_SPACE_XVYCC_BT709:
+               color_space = COLOR_SPACE_YCBCR709;
+               break;
+       }
+
+       return color_space;
+}
+
+/*******************************FMT**************************************/
+static void program_fmt(
+               struct output_pixel_processor *opp,
+               struct bit_depth_reduction_params *fmt_bit_depth,
+               struct clamping_and_pixel_encoding_params *clamping)
+{
+       /* dithering is affected by <CrtcSourceSelect>, hence should be
+        * programmed afterwards */
+
+       opp->funcs->opp_program_bit_depth_reduction(
+               opp,
+               fmt_bit_depth);
+
+       opp->funcs->opp_program_clamping_and_pixel_encoding(
+               opp,
+               clamping);
+
+       return;
+}
+
+static void update_bios_scratch_critical_state(struct adapter_service *as,
+               bool state)
+{
+       struct dc_bios *dcb = dal_adapter_service_get_bios_parser(as);
+
+       dcb->funcs->set_scratch_critical_state(dcb, state);
+}
+
+static void update_info_frame(struct core_stream *stream)
+{
+       if (dc_is_hdmi_signal(stream->signal))
+               stream->stream_enc->funcs->update_hdmi_info_packets(
+                       stream->stream_enc,
+                       &stream->encoder_info_frame);
+       else if (dc_is_dp_signal(stream->signal))
+               stream->stream_enc->funcs->update_dp_info_packets(
+                       stream->stream_enc,
+                       &stream->encoder_info_frame);
+}
+
+
+static void enable_stream(struct core_stream *stream)
+{
+       enum lane_count lane_count =
+                       stream->sink->link->cur_link_settings.lane_count;
+
+       struct dc_crtc_timing *timing = &stream->public.timing;
+       struct core_link *link = stream->sink->link;
+
+       /* 1. update AVI info frame (HDMI, DP)
+        * we always need to update info frame
+       */
+       uint32_t active_total_with_borders;
+       uint32_t early_control = 0;
+       struct timing_generator *tg = stream->tg;
+
+       update_info_frame(stream);
+       /* enable early control to avoid corruption on DP monitor*/
+       active_total_with_borders =
+                       timing->h_addressable
+                               + timing->h_border_left
+                               + timing->h_border_right;
+
+       if (lane_count != 0)
+               early_control = active_total_with_borders % lane_count;
+
+       if (early_control == 0)
+               early_control = lane_count;
+
+       tg->funcs->set_early_control(tg, early_control);
+
+       /* enable audio only within mode set */
+       if (stream->audio != NULL) {
+               dal_audio_enable_output(
+                       stream->audio,
+                       stream->stream_enc->id,
+                       stream->signal);
+       }
+
+       /* For MST, there are multiply stream go to only one link.
+        * connect DIG back_end to front_end while enable_stream and
+        * disconnect them during disable_stream
+        * BY this, it is logic clean to separate stream and link */
+        link->link_enc->funcs->connect_dig_be_to_fe(link->link_enc,
+                       stream->stream_enc->id, true);
+
+}
+
+static void disable_stream(struct core_stream *stream)
+{
+       struct core_link *link = stream->sink->link;
+
+       if (dc_is_hdmi_signal(stream->signal))
+               stream->stream_enc->funcs->stop_hdmi_info_packets(
+                       stream->stream_enc);
+
+       if (dc_is_dp_signal(stream->signal))
+               stream->stream_enc->funcs->stop_dp_info_packets(
+                       stream->stream_enc);
+
+       if (stream->audio) {
+               /* mute audio */
+               dal_audio_mute(stream->audio, stream->stream_enc->id,
+                               stream->signal);
+
+               /* TODO: notify audio driver for if audio modes list changed
+                * add audio mode list change flag */
+               /* dal_audio_disable_azalia_audio_jack_presence(stream->audio,
+                * stream->stream_engine_id);
+                */
+       }
+
+       /* blank at encoder level */
+       if (dc_is_dp_signal(stream->signal))
+               stream->stream_enc->funcs->dp_blank(stream->stream_enc);
+
+       link->link_enc->funcs->connect_dig_be_to_fe(
+                       link->link_enc,
+                       stream->stream_enc->id,
+                       false);
+
+}
+
+static void unblank_stream(struct core_stream *stream,
+               struct link_settings *link_settings)
+{
+       struct encoder_unblank_param params = { { 0 } };
+
+       /* only 3 items below are used by unblank */
+       params.crtc_timing.pixel_clock =
+               stream->public.timing.pix_clk_khz;
+       params.link_settings.link_rate = link_settings->link_rate;
+       stream->stream_enc->funcs->dp_unblank(
+               stream->stream_enc, &params);
+}
+
+static enum color_space get_output_color_space(
+                               const struct dc_crtc_timing *dc_crtc_timing)
+{
+       enum color_space color_space = COLOR_SPACE_SRGB_FULL_RANGE;
+
+       switch (dc_crtc_timing->pixel_encoding) {
+       case PIXEL_ENCODING_YCBCR422:
+       case PIXEL_ENCODING_YCBCR444:
+       case PIXEL_ENCODING_YCBCR420:
+       {
+               if ((dc_crtc_timing->timing_standard ==
+                       TIMING_STANDARD_CEA770) ||
+                       (dc_crtc_timing->timing_standard ==
+                               TIMING_STANDARD_CEA861)) {
+                       if (dc_crtc_timing->pix_clk_khz > 27030) {
+                               if (dc_crtc_timing->flags.Y_ONLY)
+                                       color_space =
+                                               COLOR_SPACE_YCBCR709_YONLY;
+                               else
+                                       color_space = COLOR_SPACE_YCBCR709;
+                       } else {
+                               if (dc_crtc_timing->flags.Y_ONLY)
+                                       color_space =
+                                               COLOR_SPACE_YCBCR601_YONLY;
+                               else
+                                       color_space = COLOR_SPACE_YCBCR601;
+                       }
+               }
+       }
+       break;
+
+       default:
+               break;
+       }
+
+       return color_space;
+}
+
+static enum dc_status apply_single_controller_ctx_to_hw(uint8_t controller_idx,
+               struct validate_context *context,
+               const struct dc *dc)
+{
+       struct core_stream *stream =
+                       context->res_ctx.controller_ctx[controller_idx].stream;
+       struct output_pixel_processor *opp =
+               context->res_ctx.pool.opps[controller_idx];
+       bool timing_changed = context->res_ctx.controller_ctx[controller_idx]
+                       .flags.timing_changed;
+       enum color_space color_space;
+
+       if (timing_changed) {
+               /* Must blank CRTC after disabling power gating and before any
+                * programming, otherwise CRTC will be hung in bad state
+                */
+               stream->tg->funcs->set_blank(stream->tg, true);
+
+               core_link_disable_stream(stream->sink->link, stream);
+
+               /*TODO: AUTO check if timing changed*/
+               if (false == stream->clock_source->funcs->program_pix_clk(
+                               stream->clock_source,
+                               &stream->pix_clk_params,
+                               &stream->pll_settings)) {
+                       BREAK_TO_DEBUGGER();
+                       return DC_ERROR_UNEXPECTED;
+               }
+
+               stream->tg->funcs->program_timing(
+                               stream->tg,
+                               &stream->public.timing,
+                               true);
+       }
+
+       /*TODO: mst support - use total stream count*/
+       stream->mi->funcs->mem_input_allocate_dmif_buffer(
+                                       stream->mi,
+                                       &stream->public.timing,
+                                       context->target_count);
+
+       if (timing_changed) {
+               if (false == stream->tg->funcs->enable_crtc(
+                               stream->tg)) {
+                       BREAK_TO_DEBUGGER();
+                       return DC_ERROR_UNEXPECTED;
+               }
+       }
+
+       /* TODO: move to stream encoder */
+       if (stream->signal != SIGNAL_TYPE_VIRTUAL)
+               if (DC_OK != bios_parser_crtc_source_select(stream)) {
+                       BREAK_TO_DEBUGGER();
+                       return DC_ERROR_UNEXPECTED;
+               }
+
+       opp->funcs->opp_set_dyn_expansion(
+                       opp,
+                       COLOR_SPACE_YCBCR601,
+                       stream->public.timing.display_color_depth,
+                       stream->sink->public.sink_signal);
+
+       program_fmt(opp, &stream->bit_depth_params, &stream->clamping);
+
+       stream->sink->link->link_enc->funcs->setup(
+               stream->sink->link->link_enc,
+               stream->signal);
+
+       if (dc_is_dp_signal(stream->signal))
+               stream->stream_enc->funcs->dp_set_stream_attribute(
+                       stream->stream_enc,
+                       &stream->public.timing);
+
+       if (dc_is_hdmi_signal(stream->signal))
+               stream->stream_enc->funcs->hdmi_set_stream_attribute(
+                       stream->stream_enc,
+                       &stream->public.timing,
+                       stream->audio != NULL);
+
+       if (dc_is_dvi_signal(stream->signal))
+               stream->stream_enc->funcs->dvi_set_stream_attribute(
+                       stream->stream_enc,
+                       &stream->public.timing,
+                       (stream->signal == SIGNAL_TYPE_DVI_DUAL_LINK) ?
+                       true : false);
+
+       if (stream->audio != NULL) {
+               if (AUDIO_RESULT_OK != dal_audio_setup(
+                               stream->audio,
+                               &stream->audio_output,
+                               &stream->public.audio_info)) {
+                       BREAK_TO_DEBUGGER();
+                       return DC_ERROR_UNEXPECTED;
+               }
+       }
+
+       /* Setup audio rate clock source */
+       if (stream->audio != NULL)
+               dal_audio_setup_audio_wall_dto(
+                               stream->audio,
+                               stream->signal,
+                               &stream->audio_output.crtc_info,
+                               &stream->audio_output.pll_info);
+
+       /* program blank color */
+       color_space = get_output_color_space(&stream->public.timing);
+       stream->tg->funcs->set_blank_color(
+                       context->res_ctx.pool.timing_generators[controller_idx],
+                       color_space);
+
+       if (timing_changed)
+               core_link_enable_stream(stream->sink->link, stream);
+
+       if (dc_is_dp_signal(stream->signal))
+               unblank_stream(stream, &stream->sink->link->cur_link_settings);
+
+       return DC_OK;
+}
+
+
+/******************************************************************************/
+
+static void power_down_encoders(struct dc *dc)
+{
+       int i;
+
+       for (i = 0; i < dc->link_count; i++) {
+               dc->links[i]->link_enc->funcs->disable_output(
+                               dc->links[i]->link_enc, SIGNAL_TYPE_NONE);
+       }
+}
+
+static void power_down_controllers(struct dc *dc)
+{
+       int i;
+
+       for (i = 0; i < dc->res_pool.controller_count; i++) {
+               dc->res_pool.timing_generators[i]->funcs->disable_crtc(
+                               dc->res_pool.timing_generators[i]);
+       }
+}
+
+static void power_down_clock_sources(struct dc *dc)
+{
+       int i;
+
+       for (i = 0; i < dc->res_pool.clk_src_count; i++) {
+               if (dc->res_pool.clock_sources[i]->funcs->cs_power_down(
+                               dc->res_pool.clock_sources[i]) == false)
+                       dm_error("Failed to power down pll! (clk src 
index=%d)\n", i);
+       }
+}
+
+static void power_down_all_hw_blocks(struct dc *dc)
+{
+       power_down_encoders(dc);
+
+       power_down_controllers(dc);
+
+       power_down_clock_sources(dc);
+}
+
+static void disable_vga_and_power_gate_all_controllers(
+               struct dc *dc)
+{
+       int i;
+       struct timing_generator *tg;
+       struct dc_bios *dcb;
+       struct dc_context *ctx;
+
+       dcb = dal_adapter_service_get_bios_parser(
+                       dc->res_pool.adapter_srv);
+
+       for (i = 0; i < dc->res_pool.controller_count; i++) {
+               tg = dc->res_pool.timing_generators[i];
+               ctx = dc->ctx;
+
+               tg->funcs->disable_vga(tg);
+
+               /* Enable CLOCK gating for each pipe BEFORE controller
+                * powergating. */
+               enable_display_pipe_clock_gating(ctx,
+                               true);
+               dc->hwss.enable_display_power_gating(ctx, i, dcb,
+                               PIPE_GATING_CONTROL_ENABLE);
+       }
+}
+
+/**
+ * When ASIC goes from VBIOS/VGA mode to driver/accelerated mode we need:
+ *  1. Power down all DC HW blocks
+ *  2. Disable VGA engine on all controllers
+ *  3. Enable power gating for controller
+ *  4. Set acc_mode_change bit (VBIOS will clear this bit when going to FSDOS)
+ */
+static void enable_accelerated_mode(struct dc *dc)
+{
+       struct dc_bios *dcb;
+
+       dcb = dal_adapter_service_get_bios_parser(dc->res_pool.adapter_srv);
+
+       power_down_all_hw_blocks(dc);
+
+       disable_vga_and_power_gate_all_controllers(dc);
+
+       dcb->funcs->set_scratch_acc_mode_change(dcb);
+}
+
+#if 0
+static enum clocks_state get_required_clocks_state(
+       struct display_clock *display_clock,
+       struct state_dependent_clocks *req_state_dep_clks)
+{
+       enum clocks_state clocks_required_state;
+       enum clocks_state dp_link_required_state;
+       enum clocks_state overall_required_state;
+
+       clocks_required_state = dal_display_clock_get_required_clocks_state(
+                       display_clock, req_state_dep_clks);
+
+       dp_link_required_state = CLOCKS_STATE_ULTRA_LOW;
+
+       /* overall required state is the max of required state for clocks
+        * (pixel, display clock) and the required state for DP link. */
+       overall_required_state =
+               clocks_required_state > dp_link_required_state ?
+                       clocks_required_state : dp_link_required_state;
+
+       /* return the min required state */
+       return overall_required_state;
+}
+
+static bool dc_pre_clock_change(
+               struct dc_context *ctx,
+               struct minimum_clocks_calculation_result *min_clk_in,
+               enum clocks_state required_clocks_state,
+               struct power_to_dal_info *output)
+{
+       struct dal_to_power_info input = {0};
+
+       input.min_deep_sleep_sclk = min_clk_in->min_deep_sleep_sclk;
+       input.min_mclk = min_clk_in->min_mclk_khz;
+       input.min_sclk = min_clk_in->min_sclk_khz;
+
+       switch (required_clocks_state) {
+       case CLOCKS_STATE_ULTRA_LOW:
+               input.required_clock = PP_CLOCKS_STATE_ULTRA_LOW;
+               break;
+       case CLOCKS_STATE_LOW:
+               input.required_clock = PP_CLOCKS_STATE_LOW;
+               break;
+       case CLOCKS_STATE_NOMINAL:
+               input.required_clock = PP_CLOCKS_STATE_NOMINAL;
+               break;
+       case CLOCKS_STATE_PERFORMANCE:
+               input.required_clock = PP_CLOCKS_STATE_PERFORMANCE;
+               break;
+       default:
+               input.required_clock = PP_CLOCKS_STATE_NOMINAL;
+               break;
+       }
+
+       if (!dc_service_pp_pre_dce_clock_change(ctx, &input, output)) {
+               dm_error("DC: dc_service_pp_pre_dce_clock_change failed!\n");
+               return false;
+       }
+
+       return true;
+}
+
+static bool dc_set_clocks_and_clock_state (
+               struct validate_context *context)
+{
+       struct power_to_dal_info output = {0};
+
+       struct display_clock *disp_clk = context->res_ctx.pool.display_clock;
+       struct dc_context *ctx = context->targets[0]->ctx;
+
+
+       if (!dc_pre_clock_change(
+                       ctx,
+                       &context->res_ctx.min_clocks,
+                       get_required_clocks_state(
+                                       context->res_ctx.pool.display_clock,
+                                       &context->res_ctx.state_clocks),
+                       &output)) {
+               /* "output" was not updated by PPLib.
+                * DAL will use default values for set mode.
+                *
+                * Do NOT fail this call. */
+               return true;
+       }
+
+       /* PPLib accepted the "clock state" that we need, that means we
+        * can store it as minimum state because PPLib guarantees not go below
+        * that state.
+        *
+        * Update the clock state here (prior to setting Pixel clock,
+        * or Display clock)
+        **/
+       if (!dal_display_clock_set_min_clocks_state(
+                       disp_clk, context->res_ctx.required_clocks_state)) {
+               BREAK_TO_DEBUGGER();
+               dm_error("DC: failed to set minimum clock state!\n");
+       }
+
+
+       /*bm_clk_info.max_mclk_khz = output.max_mclk;
+       bm_clk_info.min_mclk_khz = output.min_mclk;
+       bm_clk_info.max_sclk_khz = output.max_sclk;
+       bm_clk_info.min_sclk_khz = output.min_sclk;*/
+
+       /* Now let Bandwidth Manager know about values we got from PPLib. */
+       /*dal_bandwidth_manager_set_dynamic_clock_info(bw_mgr, &bm_clk_info);*/
+
+       return true;
+}
+#endif
+
+/**
+ * Call display_engine_clock_dce80 to perform the Dclk programming.
+ */
+static void set_display_clock(struct validate_context *context)
+{
+       /* Program the display engine clock.
+        * Check DFS bypass mode support or not. DFSbypass feature is only when
+        * BIOS GPU info table reports support. */
+
+       if (/*dal_adapter_service_is_dfs_bypass_enabled()*/ false) {
+               /*TODO: set_display_clock_dfs_bypass(
+                               hws,
+                               path_set,
+                               context->res_ctx.pool.display_clock,
+                               context->res_ctx.min_clocks.min_dclk_khz);*/
+       } else
+               dal_display_clock_set_clock(context->res_ctx.pool.display_clock,
+                               context->bw_results.dispclk_khz);
+
+       /* TODO: When changing display engine clock, DMCU WaitLoop must be
+        * reconfigured in order to maintain the same delays within DMCU
+        * programming sequences. */
+
+       /* TODO: Start GTC counter */
+}
+
+static void set_displaymarks(
+       const struct dc *dc, struct validate_context *context)
+{
+       uint8_t i, j;
+       uint8_t total_streams = 0;
+       uint8_t target_count = context->target_count;
+
+       for (i = 0; i < target_count; i++) {
+               struct core_target *target = context->targets[i];
+
+               for (j = 0; j < target->public.stream_count; j++) {
+                       struct core_stream *stream =
+                               DC_STREAM_TO_CORE(target->public.streams[j]);
+
+                       stream->mi->funcs->mem_input_program_display_marks(
+                               stream->mi,
+                               context->bw_results
+                               .nbp_state_change_wm_ns[total_streams],
+                               context->bw_results
+                                       .stutter_exit_wm_ns[total_streams],
+                               context->bw_results
+                                       .urgent_wm_ns[total_streams],
+                               stream->public.timing.h_total,
+                               stream->public.timing.pix_clk_khz,
+                               1000 * dc->bw_vbios.blackout_duration
+                                                               .value >> 24);
+                       total_streams++;
+               }
+       }
+}
+
+static void set_safe_displaymarks(struct validate_context *context)
+{
+       uint8_t i, j;
+       uint8_t target_count = context->target_count;
+
+       for (i = 0; i < target_count; i++) {
+               struct core_target *target = context->targets[i];
+
+               for (j = 0; j < target->public.stream_count; j++) {
+                       struct core_stream *stream =
+                               DC_STREAM_TO_CORE(target->public.streams[j]);
+
+                       stream->mi->funcs->mem_input_program_safe_display_marks(
+                                       stream->mi);
+               }
+       }
+}
+
+static void program_bw(struct dc *dc, struct validate_context *context)
+{
+       set_safe_displaymarks(context);
+       /*TODO: when pplib works*/
+       /*dc_set_clocks_and_clock_state(context);*/
+
+       dc->hwss.set_display_clock(context);
+       dc->hwss.set_displaymarks(dc, context);
+}
+
+static void switch_dp_clock_sources(
+       const struct dc *dc,
+       struct validate_context *val_context)
+{
+       uint8_t i, j;
+       for (i = 0; i < val_context->target_count; i++) {
+               struct core_target *target = val_context->targets[i];
+               for (j = 0; j < target->public.stream_count; j++) {
+                       struct core_stream *stream =
+                               DC_STREAM_TO_CORE(target->public.streams[j]);
+
+                       if (dc_is_dp_signal(stream->signal)) {
+                               struct clock_source *clk_src =
+                                       find_used_clk_src_for_sharing(
+                                                       val_context, stream);
+
+                               if (clk_src &&
+                                       clk_src != stream->clock_source) {
+                                       unreference_clock_source(
+                                                       &val_context->res_ctx,
+                                                       stream->clock_source);
+                                       stream->clock_source = clk_src;
+                                       reference_clock_source(
+                                               &val_context->res_ctx, clk_src);
+                                       dc->hwss.crtc_switch_to_clk_src(
+                                               clk_src, stream->opp->inst);
+                               }
+                       }
+               }
+       }
+}
+
+/*******************************************************************************
+ * Public functions
+ 
******************************************************************************/
+
+/*TODO: const validate_context*/
+static enum dc_status apply_ctx_to_hw(
+               const struct dc *dc,
+               struct validate_context *context)
+{
+       enum dc_status status;
+       uint8_t i;
+       struct resource_pool *pool = &context->res_ctx.pool;
+
+       update_bios_scratch_critical_state(context->res_ctx.pool.adapter_srv,
+                       true);
+
+       for (i = 0; i < pool->controller_count; i++) {
+               struct controller_ctx *ctlr_ctx
+                       = &context->res_ctx.controller_ctx[i];
+               struct dc_bios *dcb;
+
+               if (ctlr_ctx->flags.unchanged || !ctlr_ctx->stream)
+                       continue;
+
+               dcb = dal_adapter_service_get_bios_parser(
+                               context->res_ctx.pool.adapter_srv);
+
+               dc->hwss.enable_display_power_gating(
+                               dc->ctx, i, dcb,
+                               PIPE_GATING_CONTROL_DISABLE);
+       }
+
+       set_safe_displaymarks(context);
+       /*TODO: when pplib works*/
+       /*dc_set_clocks_and_clock_state(context);*/
+
+       if (context->bw_results.dispclk_khz
+               > dc->current_context.bw_results.dispclk_khz)
+               set_display_clock(context);
+
+       for (i = 0; i < pool->controller_count; i++) {
+               struct controller_ctx *ctlr_ctx
+                       = &context->res_ctx.controller_ctx[i];
+               if (ctlr_ctx->flags.unchanged || !ctlr_ctx->stream)
+                       continue;
+
+               status = apply_single_controller_ctx_to_hw(
+                               i,
+                               context,
+                               dc);
+
+               if (DC_OK != status)
+                       return status;
+       }
+       dc->hwss.set_displaymarks(dc, context);
+
+       update_bios_scratch_critical_state(context->res_ctx.pool.adapter_srv,
+                       false);
+
+       switch_dp_clock_sources(dc, context);
+
+       return DC_OK;
+}
+
+
+/*******************************************************************************
+ * Front End programming
+ 
******************************************************************************/
+
+static bool setup_line_buffer_pixel_depth(
+       const struct core_stream *stream,
+       enum lb_pixel_depth depth,
+       bool blank)
+{
+       enum lb_pixel_depth current_depth;
+
+       struct timing_generator *tg = stream->tg;
+       struct transform *xfm = stream->xfm;
+
+       if (!xfm->funcs->transform_get_current_pixel_storage_depth(
+               xfm,
+               &current_depth))
+               return false;
+
+       if (current_depth != depth) {
+               if (blank)
+                       tg->funcs->wait_for_state(tg, CRTC_STATE_VBLANK);
+
+               return xfm->funcs->transform_set_pixel_storage_depth(xfm, depth,
+                               &stream->bit_depth_params);
+       }
+
+       return false;
+}
+
+static void hw_sequencer_build_scaler_parameter_plane(
+               const struct core_stream *stream,
+               struct scaler_data *scaler_data)
+{
+       /*TODO: per pipe not per stream*/
+       /*TODO: get from feature from adapterservice*/
+       scaler_data->flags.bits.SHOW_COLOURED_BORDER = false;
+
+       scaler_data->flags.bits.SHOULD_PROGRAM_ALPHA = 1;
+
+       scaler_data->flags.bits.SHOULD_PROGRAM_VIEWPORT = 0;
+
+       scaler_data->flags.bits.SHOULD_UNLOCK = 0;
+
+       scaler_data->flags.bits.INTERLACED = 0;
+
+       scaler_data->dal_pixel_format = stream->format;
+
+       scaler_data->taps = stream->taps;
+
+       scaler_data->viewport = stream->viewport;
+
+       scaler_data->overscan = stream->overscan;
+
+       scaler_data->ratios = &stream->ratios;
+
+       /*TODO rotation and adjustment */
+       scaler_data->h_sharpness = 0;
+       scaler_data->v_sharpness = 0;
+
+}
+
+static void set_default_colors(
+                               struct input_pixel_processor *ipp,
+                               struct output_pixel_processor *opp,
+                               enum pixel_format format,
+                               enum color_space input_color_space,
+                               enum color_space output_color_space,
+                               enum dc_color_depth color_depth)
+{
+       struct default_adjustment default_adjust = { 0 };
+
+       default_adjust.force_hw_default = false;
+       default_adjust.color_space = output_color_space;
+       default_adjust.csc_adjust_type = GRAPHICS_CSC_ADJUST_TYPE_SW;
+       default_adjust.surface_pixel_format = format;
+
+       /* display color depth */
+       default_adjust.color_depth = color_depth;
+
+       /* Lb color depth */
+       default_adjust.lb_color_depth = LB_PIXEL_DEPTH_24BPP;
+       /*dal_hw_sequencer_translate_to_lb_color_depth(
+                       build_params->
+                       line_buffer_params[path_id][plane_id].depth);*/
+
+       opp->funcs->opp_set_csc_default(opp, &default_adjust);
+}
+
+static void program_scaler(
+       uint8_t controller_idx,
+       struct timing_generator *tg,
+       struct transform *xfm,
+       const struct core_surface *surface,
+       const struct core_stream *stream)
+{
+       struct scaler_data scaler_data = { { 0 } };
+
+       hw_sequencer_build_scaler_parameter_plane(
+               stream,
+               &scaler_data);
+
+       setup_line_buffer_pixel_depth(
+               stream,
+               LB_PIXEL_DEPTH_24BPP,
+               false);
+
+       tg->funcs->set_overscan_blank_color(tg, 
surface->public.colorimetry.color_space);
+
+       xfm->funcs->transform_set_scaler(xfm, &scaler_data);
+
+       xfm->funcs->transform_update_viewport(
+                       xfm,
+                       &scaler_data.viewport,
+                       false);
+}
+
+/**
+ * Program the Front End of the Pipe.
+ * The Back End was already programmed by Set Mode.
+ */
+static bool set_plane_config(
+       const struct dc *dc,
+       struct core_surface *surface,
+       struct core_target *target)
+{
+       const struct core_stream *core_stream =
+               DC_STREAM_TO_CORE(target->public.streams[0]);
+       const struct dc_crtc_timing *dc_crtc_timing =
+                       &target->public.streams[0]->timing;
+       struct mem_input *mi = core_stream->mi;
+       struct input_pixel_processor *ipp = core_stream->ipp;
+       struct timing_generator *tg = core_stream->tg;
+       struct transform *xfm = core_stream->xfm;
+       struct output_pixel_processor *opp = core_stream->opp;
+       struct dc_context *ctx = core_stream->ctx;
+       uint8_t controller_idx = core_stream->controller_idx;
+
+       /* TODO: Clean up change, possibly change to use same type */
+       enum color_space input_color_space =
+                                       
surface_color_to_color_space(&(surface->public.colorimetry));
+
+       dc->hwss.pipe_control_lock(
+                       ctx,
+                       controller_idx,
+                       PIPE_LOCK_CONTROL_MODE,
+                       false);
+
+       /* While a non-root controller is programmed we
+        * have to lock the root controller. */
+       dc->hwss.pipe_control_lock(
+                       ctx,
+                       controller_idx,
+                       PIPE_LOCK_CONTROL_GRAPHICS |
+                       PIPE_LOCK_CONTROL_SCL |
+                       PIPE_LOCK_CONTROL_BLENDER |
+                       PIPE_LOCK_CONTROL_SURFACE,
+                       true);
+
+       tg->funcs->program_timing(tg, dc_crtc_timing, false);
+
+       dc->hwss.enable_fe_clock(ctx, controller_idx, true);
+
+       set_default_colors(
+                       ipp,
+                       opp,
+                       core_stream->format,
+                       input_color_space,
+                       get_output_color_space(dc_crtc_timing),
+                       dc_crtc_timing->display_color_depth);
+
+       /* program Scaler */
+       program_scaler(
+               controller_idx, tg, xfm, surface, core_stream);
+
+       dc->hwss.set_blender_mode(
+                       ctx,
+                       controller_idx,
+                       BLENDER_MODE_CURRENT_PIPE);
+
+       mi->funcs->mem_input_program_surface_config(
+                       mi,
+                       surface->public.format,
+                       &surface->public.tiling_info,
+                       &surface->public.plane_size,
+                       surface->public.rotation);
+
+       dc->hwss.pipe_control_lock(
+                       ctx,
+                       controller_idx,
+                       PIPE_LOCK_CONTROL_GRAPHICS |
+                       PIPE_LOCK_CONTROL_SCL |
+                       PIPE_LOCK_CONTROL_BLENDER |
+                       PIPE_LOCK_CONTROL_SURFACE,
+                       false);
+
+       return true;
+}
+
+static bool update_plane_address(
+       const struct dc *dc,
+       const struct core_surface *surface,
+       struct core_target *target)
+{
+       const struct core_stream *core_stream =
+               DC_STREAM_TO_CORE(target->public.streams[0]);
+       struct dc_context *ctx = core_stream->ctx;
+       struct mem_input *mi = core_stream->mi;
+       uint8_t controller_id = core_stream->controller_idx;
+
+       /* TODO: crtc should be per surface, NOT per-target */
+       dc->hwss.pipe_control_lock(
+               ctx,
+               controller_id,
+               PIPE_LOCK_CONTROL_SURFACE,
+               true);
+
+       if (false ==
+               core_stream->mi->funcs->mem_input_program_surface_flip_and_addr(
+               mi, &surface->public.address, surface->public.flip_immediate))
+               return false;
+
+       dc->hwss.pipe_control_lock(
+               ctx,
+               controller_id,
+               PIPE_LOCK_CONTROL_SURFACE,
+               false);
+
+       return true;
+}
+
+static void reset_single_stream_hw_ctx(
+               const struct dc *dc,
+               struct core_stream *stream,
+               struct validate_context *context)
+{
+       struct dc_bios *dcb;
+
+       dcb = dal_adapter_service_get_bios_parser(
+                       context->res_ctx.pool.adapter_srv);
+       if (stream->audio) {
+               dal_audio_disable_output(stream->audio,
+                               stream->stream_enc->id,
+                               stream->signal);
+               stream->audio = NULL;
+       }
+
+       core_link_disable_stream(stream->sink->link, stream);
+
+       stream->tg->funcs->set_blank(stream->tg, true);
+       stream->tg->funcs->disable_crtc(stream->tg);
+       stream->mi->funcs->mem_input_deallocate_dmif_buffer(
+                       stream->mi, context->target_count);
+       stream->xfm->funcs->transform_set_scaler_bypass(stream->xfm);
+       unreference_clock_source(&context->res_ctx, stream->clock_source);
+       dc->hwss.enable_display_power_gating(
+                       stream->ctx, stream->controller_idx, dcb,
+                       PIPE_GATING_CONTROL_ENABLE);
+}
+
+static void reset_hw_ctx(struct dc *dc,
+               struct validate_context *context,
+               uint8_t target_count)
+{
+       uint8_t i;
+       /* look up the targets that have been removed since last commit */
+       for (i = 0; i < dc->current_context.target_count; i++) {
+               const struct core_target *core_target =
+                       dc->current_context.targets[i];
+               struct core_stream *core_stream =
+                       DC_STREAM_TO_CORE(core_target->public.streams[0]);
+               uint8_t controller_idx = core_stream->controller_idx;
+
+               if (context->res_ctx.controller_ctx[controller_idx].stream &&
+                               !context->res_ctx.controller_ctx[controller_idx]
+                               .flags.timing_changed)
+                       continue;
+
+               reset_single_stream_hw_ctx(dc, core_stream, 
&dc->current_context);
+       }
+}
+
+static void power_down(struct dc *dc)
+{
+       power_down_all_hw_blocks(dc);
+       disable_vga_and_power_gate_all_controllers(dc);
+
+}
+
+static bool wait_for_reset_trigger_to_occur(
+       struct dc_context *dc_ctx,
+       struct timing_generator *tg)
+{
+       bool rc = false;
+
+       /* To avoid endless loop we wait at most
+        * frames_to_wait_on_triggered_reset frames for the reset to occur. */
+       const uint32_t frames_to_wait_on_triggered_reset = 10;
+       uint32_t i;
+
+       for (i = 0; i < frames_to_wait_on_triggered_reset; i++) {
+
+               if (!tg->funcs->is_counter_moving(tg)) {
+                       DC_ERROR("TG counter is not moving!\n");
+                       break;
+               }
+
+               if (tg->funcs->did_triggered_reset_occur(tg)) {
+                       rc = true;
+                       /* usually occurs at i=1 */
+                       DC_SYNC_INFO("GSL: reset occurred at wait count: %d\n",
+                                       i);
+                       break;
+               }
+
+               /* Wait for one frame. */
+               tg->funcs->wait_for_state(tg, CRTC_STATE_VACTIVE);
+               tg->funcs->wait_for_state(tg, CRTC_STATE_VBLANK);
+       }
+
+       if (false == rc)
+               DC_ERROR("GSL: Timeout on reset trigger!\n");
+
+       return rc;
+}
+
+/* Enable timing synchronization for a group of Timing Generators. */
+static void enable_timing_synchronization(
+       struct dc_context *dc_ctx,
+       uint32_t timing_generator_num,
+       struct timing_generator *tgs[])
+{
+       struct dcp_gsl_params gsl_params = { 0 };
+       struct trigger_params trigger_params;
+       uint32_t i;
+
+       DC_SYNC_INFO("GSL: Setting-up...\n");
+
+       gsl_params.gsl_group = SYNC_SOURCE_GSL_GROUP0;
+       gsl_params.gsl_purpose = DCP_GSL_PURPOSE_SURFACE_FLIP;
+
+       for (i = 0; i < timing_generator_num; i++) {
+               /* Designate a single TG in the group as a master.
+                * Since HW doesn't care which one, we always assign
+                * the 1st one in the group. */
+               gsl_params.timing_server = (0 == i ? true : false);
+
+               tgs[i]->funcs->setup_global_swap_lock(tgs[i], &gsl_params);
+       }
+
+       /* Reset slave controllers on master VSync */
+       DC_SYNC_INFO("GSL: enabling trigger-reset\n");
+       dm_memset(&trigger_params, 0, sizeof(trigger_params));
+
+       trigger_params.edge = TRIGGER_EDGE_DEFAULT;
+       trigger_params.source = SYNC_SOURCE_GSL_GROUP0;
+
+       for (i = 1 /* skip the master */; i < timing_generator_num; i++) {
+               tgs[i]->funcs->enable_reset_trigger(tgs[i], &trigger_params);
+
+               DC_SYNC_INFO("GSL: waiting for reset to occur.\n");
+               wait_for_reset_trigger_to_occur(dc_ctx, tgs[i]);
+
+               /* Regardless of success of the wait above, remove the reset or
+                * the driver will start timing out on Display requests. */
+               DC_SYNC_INFO("GSL: disabling trigger-reset.\n");
+               tgs[i]->funcs->disable_reset_trigger(tgs[i]);
+       }
+
+       /* GSL Vblank synchronization is a one time sync mechanism, assumption
+        * is that the sync'ed displays will not drift out of sync over time*/
+       DC_SYNC_INFO("GSL: Restoring register states.\n");
+       for (i = 0; i < timing_generator_num; i++)
+               tgs[i]->funcs->tear_down_global_swap_lock(tgs[i]);
+
+       DC_SYNC_INFO("GSL: Set-up complete.\n");
+}
+
+static const struct hw_sequencer_funcs dce110_funcs = {
+       .apply_ctx_to_hw = apply_ctx_to_hw,
+       .reset_hw_ctx = reset_hw_ctx,
+       .set_plane_config = set_plane_config,
+       .update_plane_address = update_plane_address,
+       .set_gamma_ramp = set_gamma_ramp,
+       .power_down = power_down,
+       .enable_accelerated_mode = enable_accelerated_mode,
+       .enable_timing_synchronization = enable_timing_synchronization,
+       .program_bw = program_bw,
+       .enable_stream = enable_stream,
+       .disable_stream = disable_stream,
+       .enable_display_pipe_clock_gating = enable_display_pipe_clock_gating,
+       .crtc_switch_to_clk_src = dce110_crtc_switch_to_clk_src,
+       .enable_display_power_gating = dce110_enable_display_power_gating,
+       .enable_fe_clock = dce110_enable_fe_clock,
+       .pipe_control_lock = dce110_pipe_control_lock,
+       .set_blender_mode = dce110_set_blender_mode,
+       .clock_gating_power_up = dal_dc_clock_gating_dce110_power_up,/*todo*/
+       .set_display_clock = set_display_clock,
+       .set_displaymarks = set_displaymarks,
+};
+
+bool dce110_hw_sequencer_construct(struct dc *dc)
+{
+       dc->hwss = dce110_funcs;
+
+       return true;
+}
+
diff --git a/drivers/gpu/drm/amd/dal/dc/dce110/dce110_hw_sequencer.h 
b/drivers/gpu/drm/amd/dal/dc/dce110/dce110_hw_sequencer.h
new file mode 100644
index 000000000000..def54df283d5
--- /dev/null
+++ b/drivers/gpu/drm/amd/dal/dc/dce110/dce110_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_DCE110_H__
+#define __DC_HWSS_DCE110_H__
+
+#include "core_types.h"
+
+struct dc;
+
+bool dce110_hw_sequencer_construct(struct dc *dc);
+
+#endif /* __DC_HWSS_DCE110_H__ */
+
diff --git a/drivers/gpu/drm/amd/dal/dc/dce110/dce110_resource.c 
b/drivers/gpu/drm/amd/dal/dc/dce110/dce110_resource.c
new file mode 100644
index 000000000000..9e2b5d95a521
--- /dev/null
+++ b/drivers/gpu/drm/amd/dal/dc/dce110/dce110_resource.c
@@ -0,0 +1,1238 @@
+/*
+* 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_timing_generator.h"
+#include "dce110/dce110_link_encoder.h"
+#include "dce110/dce110_mem_input.h"
+#include "dce110/dce110_ipp.h"
+#include "dce110/dce110_transform.h"
+#include "dce110/dce110_stream_encoder.h"
+#include "dce110/dce110_opp.h"
+#include "dce110/dce110_clock_source.h"
+
+#include "dce/dce_11_0_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 dce110_clk_src_array_id {
+       DCE110_CLK_SRC_PLL0 = 0,
+       DCE110_CLK_SRC_PLL1,
+       DCE110_CLK_SRC_EXT,
+
+       DCE110_CLK_SRC_TOTAL
+};
+
+static const struct dce110_timing_generator_offsets dce110_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 dce110_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),
+       }
+};
+
+static const struct dce110_transform_reg_offsets dce110_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),
+}
+};
+
+static const struct dce110_ipp_reg_offsets dce110_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),
+               link_regs(6)
+};
+
+#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),
+               stream_enc_regs(6)
+};
+
+
+/* AG TBD Needs to be reduced back to 3 pipes once dce10 hw sequencer 
implemented. */
+static const struct dce110_opp_reg_offsets dce110_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 dce110_clk_src_reg_offsets dce110_clk_src_reg_offsets[] = {
+       {
+               .pll_cntl = mmBPHYC_PLL0_PLL_CNTL,
+               .pixclk_resync_cntl  = mmPIXCLK0_RESYNC_CNTL
+       },
+       {
+               .pll_cntl = mmBPHYC_PLL1_PLL_CNTL,
+               .pixclk_resync_cntl  = mmPIXCLK1_RESYNC_CNTL
+       }
+};
+
+static struct timing_generator *dce110_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(ctx, 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(ctx, tg110);
+       return NULL;
+}
+
+static struct stream_encoder *dce110_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(ctx, 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(ctx, enc110);
+       return NULL;
+}
+
+static struct mem_input *dce110_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(ctx, sizeof(struct dce110_mem_input));
+
+       if (!mem_input110)
+               return NULL;
+
+       if (dce110_mem_input_construct(mem_input110,
+                       ctx, inst, offset))
+               return &mem_input110->base;
+
+       BREAK_TO_DEBUGGER();
+       dm_free(ctx, mem_input110);
+       return NULL;
+}
+
+static void dce110_transform_destroy(struct transform **xfm)
+{
+       dm_free((*xfm)->ctx, TO_DCE110_TRANSFORM(*xfm));
+       *xfm = NULL;
+}
+
+static struct transform *dce110_transform_create(
+       struct dc_context *ctx,
+       uint32_t inst,
+       const struct dce110_transform_reg_offsets *offsets)
+{
+       struct dce110_transform *transform =
+               dm_alloc(ctx, sizeof(struct dce110_transform));
+
+       if (!transform)
+               return NULL;
+
+       if (dce110_transform_construct(transform, ctx, inst, offsets))
+               return &transform->base;
+
+       BREAK_TO_DEBUGGER();
+       dm_free(ctx, transform);
+       return NULL;
+}
+
+static struct input_pixel_processor *dce110_ipp_create(
+       struct dc_context *ctx,
+       uint32_t inst,
+       const struct dce110_ipp_reg_offsets *offsets)
+{
+       struct dce110_ipp *ipp =
+               dm_alloc(ctx, sizeof(struct dce110_ipp));
+
+       if (!ipp)
+               return NULL;
+
+       if (dce110_ipp_construct(ipp, ctx, inst, offsets))
+               return &ipp->base;
+
+       BREAK_TO_DEBUGGER();
+       dm_free(ctx, ipp);
+       return NULL;
+}
+
+struct link_encoder *dce110_link_encoder_create(
+       const struct encoder_init_data *enc_init_data)
+{
+       struct dce110_link_encoder *enc110 =
+               dm_alloc(
+                       enc_init_data->ctx,
+                       sizeof(struct dce110_link_encoder));
+
+       if (!enc110)
+               return NULL;
+
+       if (dce110_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(enc_init_data->ctx, enc110);
+       return NULL;
+}
+
+void dce110_link_encoder_destroy(struct link_encoder **enc)
+{
+       dm_free((*enc)->ctx, TO_DCE110_LINK_ENC(*enc));
+       *enc = NULL;
+}
+
+
+static struct output_pixel_processor *dce110_opp_create(
+       struct dc_context *ctx,
+       uint32_t inst,
+       const struct dce110_opp_reg_offsets *offsets)
+{
+       struct dce110_opp *opp =
+               dm_alloc(ctx, sizeof(struct dce110_opp));
+
+       if (!opp)
+               return NULL;
+
+       if (dce110_opp_construct(opp,
+                       ctx, inst, offsets))
+               return &opp->base;
+
+       BREAK_TO_DEBUGGER();
+       dm_free(ctx, opp);
+       return NULL;
+}
+
+struct clock_source *dce110_clock_source_create(
+       struct dc_context *ctx,
+       struct dc_bios *bios,
+       enum clock_source_id id,
+       const struct dce110_clk_src_reg_offsets *offsets)
+{
+       struct dce110_clk_src *clk_src =
+               dm_alloc(ctx, sizeof(struct dce110_clk_src));
+
+       if (!clk_src)
+               return NULL;
+
+       if (dce110_clk_src_construct(clk_src, ctx, bios, id, offsets))
+               return &clk_src->base;
+
+       BREAK_TO_DEBUGGER();
+       return NULL;
+}
+
+void dce110_clock_source_destroy(struct clock_source **clk_src)
+{
+       dm_free((*clk_src)->ctx, TO_DCE110_CLK_SRC(*clk_src));
+       *clk_src = NULL;
+}
+
+void dce110_destruct_resource_pool(struct resource_pool *pool)
+{
+       unsigned int i;
+
+       for (i = 0; i < pool->controller_count; i++) {
+               if (pool->opps[i] != NULL)
+                       dce110_opp_destroy(&pool->opps[i]);
+
+               if (pool->transforms[i] != NULL)
+                       dce110_transform_destroy(&pool->transforms[i]);
+
+               if (pool->ipps[i] != NULL)
+                       dce110_ipp_destroy(&pool->ipps[i]);
+
+               if (pool->mis[i] != NULL) {
+                       dm_free(pool->mis[i]->ctx,
+                                       TO_DCE110_MEM_INPUT(pool->mis[i]));
+                       pool->mis[i] = NULL;
+               }
+
+               if (pool->timing_generators[i] != NULL) {
+                       dm_free(pool->timing_generators[i]->ctx, 
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(pool->stream_enc[i]->ctx,
+                               DCE110STRENC_FROM_STRENC(pool->stream_enc[i]));
+       }
+
+       for (i = 0; i < pool->clk_src_count; i++) {
+               if (pool->clock_sources[i] != NULL) {
+                       dce110_clock_source_destroy(&pool->clock_sources[i]);
+               }
+       }
+
+       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_first_free_pll(
+               struct resource_context *res_ctx)
+{
+       if (res_ctx->clock_source_ref_count[DCE110_CLK_SRC_PLL0] == 0) {
+               return res_ctx->pool.clock_sources[DCE110_CLK_SRC_PLL0];
+       }
+       if (res_ctx->clock_source_ref_count[DCE110_CLK_SRC_PLL1] == 0) {
+               return res_ctx->pool.clock_sources[DCE110_CLK_SRC_PLL1];
+       }
+
+       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 core_stream *stream,
+       struct audio_output *audio_output)
+{
+       audio_output->engine_id = stream->stream_enc->id;
+
+       audio_output->signal = stream->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 =
+                       stream->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 =
+                       stream->pix_clk_params.requested_pix_clk;
+
+       if (stream->signal == SIGNAL_TYPE_DISPLAY_PORT ||
+                       stream->signal == SIGNAL_TYPE_DISPLAY_PORT_MST) {
+               audio_output->pll_info.dp_dto_source_clock_in_khz =
+                       dal_display_clock_get_dp_ref_clk_frequency(
+                               stream->dis_clk);
+       }
+
+       audio_output->pll_info.feed_back_divider =
+                       stream->pll_settings.feedback_divider;
+
+       audio_output->pll_info.dto_source =
+               translate_to_dto_source(
+                       stream->controller_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 =
+                       stream->pll_settings.ss_percentage;
+}
+
+static void get_pixel_clock_parameters(
+       const struct core_stream *stream,
+       struct pixel_clk_params *pixel_clk_params)
+{
+       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 = stream->controller_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_stream_hw_param(struct core_stream *stream)
+{
+       /*TODO: unhardcode*/
+       stream->max_tmds_clk_from_edid_in_mhz = 0;
+       stream->max_hdmi_deep_color = COLOR_DEPTH_121212;
+       stream->max_hdmi_pixel_clock = 600000;
+
+       get_pixel_clock_parameters(stream, &stream->pix_clk_params);
+       stream->clock_source->funcs->get_pix_clk_dividers(
+               stream->clock_source,
+               &stream->pix_clk_params,
+               &stream->pll_settings);
+
+       build_audio_output(stream, &stream->audio_output);
+
+       return DC_OK;
+}
+
+static enum dc_status validate_mapped_resource(
+               const struct dc *dc,
+               struct validate_context *context)
+{
+       enum dc_status status = DC_OK;
+       uint8_t i, j;
+
+       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;
+
+                       if (!stream->tg->funcs->validate_timing(
+                                       stream->tg, &stream->public.timing))
+                               return DC_FAIL_CONTROLLER_VALIDATE;
+
+                       status = build_stream_hw_param(stream);
+
+                       if (status != DC_OK)
+                               return status;
+
+                       if (!link->link_enc->funcs->validate_output_with_stream(
+                                       link->link_enc,
+                                       stream))
+                               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;
+
+                       build_info_frame(stream);
+               }
+       }
+
+       return DC_OK;
+}
+
+enum dc_status dce110_validate_bandwidth(
+       const struct dc *dc,
+       struct validate_context *context)
+{
+       uint8_t i, j;
+       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 < context->target_count; i++) {
+               struct core_target *target = context->targets[i];
+               for (j = 0; j < target->public.stream_count; j++) {
+                       struct core_stream *stream =
+                               DC_STREAM_TO_CORE(target->public.streams[j]);
+                       struct bw_calcs_input_single_display *disp = &context->
+                               bw_mode_data.displays_data[number_of_displays];
+
+                       if (target->status.surface_count == 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(
+                                               stream->ratios.vert.value);
+                               disp->graphics_h_taps = stream->taps.h_taps;
+                               disp->graphics_v_taps = stream->taps.v_taps;
+
+                               /* TODO: remove when bw formula accepts taps per
+                                * display
+                                */
+                               if (max_vtaps < stream->taps.v_taps)
+                                       max_vtaps = stream->taps.v_taps;
+                               if (max_htaps < stream->taps.h_taps)
+                                       max_htaps = stream->taps.h_taps;
+                       }
+
+                       disp->graphics_src_width =
+                                       stream->public.timing.h_addressable;
+                       disp->graphics_src_height =
+                                       stream->public.timing.v_addressable;
+                       disp->h_total = stream->public.timing.h_total;
+                       disp->pixel_rate = bw_frc_to_fixed(
+                               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 (dm_memcmp(&prev_timing,
+                                       &stream->public.timing,
+                                       sizeof(struct dc_crtc_timing))!= 0)
+                                       all_displays_in_sync = false;
+                       if (number_of_displays == 0)
+                               prev_timing = 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\n",
+               __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 (dm_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;
+       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 *core_stream =
+                       DC_STREAM_TO_CORE(target->public.streams[i]);
+               uint8_t index = core_stream->controller_idx;
+               context->res_ctx.controller_ctx[index].flags.unchanged = true;
+       }
+}
+
+static enum dc_status map_clock_resources(
+               const struct dc *dc,
+               struct validate_context *context)
+{
+       uint8_t i, j;
+
+       /* mark resources used for targets that are already active */
+       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]);
+
+                       reference_clock_source(
+                               &context->res_ctx,
+                               stream->clock_source);
+               }
+       }
+
+       /* 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]);
+
+                       if (dc_is_dp_signal(stream->signal)
+                               || stream->signal == SIGNAL_TYPE_VIRTUAL)
+                               stream->clock_source = context->res_ctx.
+                                       pool.clock_sources[DCE110_CLK_SRC_EXT];
+                       else
+                               stream->clock_source =
+                                       find_used_clk_src_for_sharing(
+                                                       context, stream);
+                       if (stream->clock_source == NULL)
+                               stream->clock_source =
+                                       find_first_free_pll(&context->res_ctx);
+
+                       if (stream->clock_source == NULL)
+                               return DC_NO_CLOCK_SOURCE_RESOURCE;
+
+                       reference_clock_source(
+                                       &context->res_ctx,
+                                       stream->clock_source);
+               }
+       }
+
+       return DC_OK;
+}
+
+enum dc_status dce110_validate_with_context(
+               const struct 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++) {
+               context->targets[i] = DC_TARGET_TO_CORE(set[i].target);
+
+               for (j = 0; j < dc->current_context.target_count; j++)
+                       if (dc->current_context.targets[j] == 
context->targets[i])
+                               set_target_unchanged(context, i);
+
+               if (!context->target_flags[i].unchanged)
+                       if (!logical_attach_surfaces_to_target(
+                                                       (struct dc_surface 
**)set[i].surfaces,
+                                                       set[i].surface_count,
+                                                       
&context->targets[i]->public)) {
+                               DC_ERROR("Failed to attach surface to 
target!\n");
+                               return DC_FAIL_ATTACH_SURFACES;
+                       }
+       }
+
+       context->target_count = set_count;
+
+       context->res_ctx.pool = dc->res_pool;
+
+       result = map_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)
+               build_scaling_params_for_context(dc, context);
+
+       if (result == DC_OK)
+               result = dce110_validate_bandwidth(dc, context);
+
+       return result;
+}
+
+static struct resource_funcs dce110_res_pool_funcs = {
+       .destruct = dce110_destruct_resource_pool,
+       .link_enc_create = dce110_link_encoder_create,
+       .link_enc_destroy = dce110_link_encoder_destroy,
+       .validate_with_context = dce110_validate_with_context,
+       .validate_bandwidth = dce110_validate_bandwidth
+};
+
+bool dce110_construct_resource_pool(
+       struct adapter_service *adapter_serv,
+       uint8_t num_virtual_links,
+       struct 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 = &dce110_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[DCE110_CLK_SRC_PLL0] = dce110_clock_source_create(
+               ctx, dal_adapter_service_get_bios_parser(adapter_serv),
+               CLOCK_SOURCE_ID_PLL0, &dce110_clk_src_reg_offsets[0]);
+       pool->clock_sources[DCE110_CLK_SRC_PLL1] = dce110_clock_source_create(
+               ctx, dal_adapter_service_get_bios_parser(adapter_serv),
+               CLOCK_SOURCE_ID_PLL1, &dce110_clk_src_reg_offsets[1]);
+       pool->clock_sources[DCE110_CLK_SRC_EXT] =  dce110_clock_source_create(
+               ctx, dal_adapter_service_get_bios_parser(adapter_serv),
+               CLOCK_SOURCE_ID_EXTERNAL, &dce110_clk_src_reg_offsets[0]);
+       pool->clk_src_count = DCE110_CLK_SRC_TOTAL;
+
+       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_dce110_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->controller_count =
+               dal_adapter_service_get_func_controllers_num(adapter_serv);
+       pool->stream_enc_count = dal_adapter_service_get_stream_engines_num(
+                       adapter_serv);
+       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->controller_count; i++) {
+               pool->timing_generators[i] = dce110_timing_generator_create(
+                               adapter_serv, ctx, i, &dce110_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] = dce110_mem_input_create(ctx, i,
+                               &dce110_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] = dce110_ipp_create(ctx, i, 
&dce110_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] = dce110_transform_create(
+                                       ctx, i, &dce110_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] = dce110_opp_create(ctx, i, 
&dce110_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->controller_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] = dce110_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++;
+       }
+
+       return true;
+
+stream_enc_create_fail:
+       for (i = 0; i < pool->stream_enc_count; i++) {
+               if (pool->stream_enc[i] != NULL)
+                       dm_free(pool->stream_enc[i]->ctx,
+                               DCE110STRENC_FROM_STRENC(pool->stream_enc[i]));
+       }
+
+audio_create_fail:
+       for (i = 0; i < pool->controller_count; i++) {
+               if (pool->audios[i] != NULL)
+                       dal_audio_destroy(&pool->audios[i]);
+       }
+
+controller_create_fail:
+       for (i = 0; i < pool->controller_count; i++) {
+               if (pool->opps[i] != NULL)
+                       dce110_opp_destroy(&pool->opps[i]);
+
+               if (pool->transforms[i] != NULL)
+                       dce110_transform_destroy(&pool->transforms[i]);
+
+               if (pool->ipps[i] != NULL)
+                       dce110_ipp_destroy(&pool->ipps[i]);
+
+               if (pool->mis[i] != NULL) {
+                       dm_free(pool->mis[i]->ctx,
+                                       TO_DCE110_MEM_INPUT(pool->mis[i]));
+                       pool->mis[i] = NULL;
+               }
+
+               if (pool->timing_generators[i] != NULL) {
+                       dm_free(pool->timing_generators[i]->ctx,
+                               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)
+                       dce110_clock_source_destroy(&pool->clock_sources[i]);
+       }
+
+       return false;
+}
diff --git a/drivers/gpu/drm/amd/dal/dc/dce110/dce110_resource.h 
b/drivers/gpu/drm/amd/dal/dc/dce110/dce110_resource.h
new file mode 100644
index 000000000000..5d60df286835
--- /dev/null
+++ b/drivers/gpu/drm/amd/dal/dc/dce110/dce110_resource.h
@@ -0,0 +1,46 @@
+/*
+* 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_DCE110_H__
+#define __DC_RESOURCE_DCE110_H__
+
+#include "core_types.h"
+
+struct adapter_service;
+struct dc;
+struct resource_pool;
+
+bool dce110_construct_resource_pool(
+       struct adapter_service *adapter_serv,
+       uint8_t num_virtual_links,
+       struct dc *dc,
+       struct resource_pool *pool);
+
+void dce110_destruct_resource_pool(struct resource_pool *pool);
+
+void dce110_link_encoder_destroy(struct link_encoder **enc);
+
+#endif /* __DC_RESOURCE_DCE110_H__ */
+
-- 
2.1.4

Reply via email to