[PATCH 21/29] drm/amd/dal: Add Carrizo HW sequencer and resource

Harry Wentland harry.wentland at amd.com
Thu Feb 11 17:20:01 UTC 2016


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



More information about the dri-devel mailing list