All of lore.kernel.org
 help / color / mirror / Atom feed
From: Harry Wentland <harry.wentland@amd.com>
To: dri-devel@lists.freedesktop.org
Subject: [PATCH v2 20/26] drm/amd/dal: Add transform & scaler HW programming
Date: Tue, 16 Feb 2016 17:28:00 -0500	[thread overview]
Message-ID: <b24928ff6137d7afceb758a1a24ff029a34e76f2.1455660367.git.harry.wentland@amd.com> (raw)
In-Reply-To: <cover.1455660366.git.harry.wentland@amd.com>

Adds scaler, viewport, gamut remap, and pixel depth programming.

Signed-off-by: Harry Wentland <harry.wentland@amd.com>
Reviewed-by: Alex Deucher <alexander.deucher@amd.com>
---
 .../gpu/drm/amd/dal/dc/dce110/dce110_transform.c   |  91 +++
 .../gpu/drm/amd/dal/dc/dce110/dce110_transform.h   |  87 +++
 .../amd/dal/dc/dce110/dce110_transform_bit_depth.c | 851 +++++++++++++++++++++
 .../amd/dal/dc/dce110/dce110_transform_bit_depth.h |  51 ++
 .../drm/amd/dal/dc/dce110/dce110_transform_gamut.c | 296 +++++++
 .../drm/amd/dal/dc/dce110/dce110_transform_scl.c   | 818 ++++++++++++++++++++
 .../drm/amd/dal/dc/dce110/dce110_transform_sclv.c  | 531 +++++++++++++
 7 files changed, 2725 insertions(+)
 create mode 100644 drivers/gpu/drm/amd/dal/dc/dce110/dce110_transform.c
 create mode 100644 drivers/gpu/drm/amd/dal/dc/dce110/dce110_transform.h
 create mode 100644 drivers/gpu/drm/amd/dal/dc/dce110/dce110_transform_bit_depth.c
 create mode 100644 drivers/gpu/drm/amd/dal/dc/dce110/dce110_transform_bit_depth.h
 create mode 100644 drivers/gpu/drm/amd/dal/dc/dce110/dce110_transform_gamut.c
 create mode 100644 drivers/gpu/drm/amd/dal/dc/dce110/dce110_transform_scl.c
 create mode 100644 drivers/gpu/drm/amd/dal/dc/dce110/dce110_transform_sclv.c

diff --git a/drivers/gpu/drm/amd/dal/dc/dce110/dce110_transform.c b/drivers/gpu/drm/amd/dal/dc/dce110/dce110_transform.c
new file mode 100644
index 000000000000..2654a965065d
--- /dev/null
+++ b/drivers/gpu/drm/amd/dal/dc/dce110/dce110_transform.c
@@ -0,0 +1,91 @@
+/*
+ * 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 DCE11 register header files */
+#include "dce/dce_11_0_d.h"
+#include "dce/dce_11_0_sh_mask.h"
+
+#include "dc_types.h"
+#include "core_types.h"
+
+#include "include/grph_object_id.h"
+#include "include/fixed31_32.h"
+#include "include/logger_interface.h"
+
+#include "dce110_transform.h"
+
+#include "dce110_transform_bit_depth.h"
+
+static struct transform_funcs dce110_transform_funcs = {
+	.transform_power_up =
+		dce110_transform_power_up,
+	.transform_set_scaler =
+		dce110_transform_set_scaler,
+	.transform_set_scaler_bypass =
+		dce110_transform_set_scaler_bypass,
+	.transform_update_viewport =
+		dce110_transform_update_viewport,
+	.transform_set_scaler_filter =
+		dce110_transform_set_scaler_filter,
+	.transform_set_gamut_remap =
+		dce110_transform_set_gamut_remap,
+	.transform_set_pixel_storage_depth =
+		dce110_transform_set_pixel_storage_depth,
+	.transform_get_current_pixel_storage_depth =
+		dce110_transform_get_current_pixel_storage_depth
+};
+
+/*****************************************/
+/* Constructor, Destructor               */
+/*****************************************/
+
+bool dce110_transform_construct(
+	struct dce110_transform *xfm110,
+	struct dc_context *ctx,
+	uint32_t inst,
+	const struct dce110_transform_reg_offsets *reg_offsets)
+{
+	xfm110->base.ctx = ctx;
+
+	xfm110->base.inst = inst;
+	xfm110->base.funcs = &dce110_transform_funcs;
+
+	xfm110->offsets = *reg_offsets;
+
+	xfm110->lb_pixel_depth_supported =
+			LB_PIXEL_DEPTH_18BPP |
+			LB_PIXEL_DEPTH_24BPP |
+			LB_PIXEL_DEPTH_30BPP;
+
+	return true;
+}
+
+bool dce110_transform_power_up(struct transform *xfm)
+{
+	return dce110_transform_power_up_line_buffer(xfm);
+}
+
diff --git a/drivers/gpu/drm/amd/dal/dc/dce110/dce110_transform.h b/drivers/gpu/drm/amd/dal/dc/dce110/dce110_transform.h
new file mode 100644
index 000000000000..117aca337f9d
--- /dev/null
+++ b/drivers/gpu/drm/amd/dal/dc/dce110/dce110_transform.h
@@ -0,0 +1,87 @@
+/* Copyright 2012-15 Advanced Micro Devices, Inc.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
+ * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ *
+ * Authors: AMD
+ *
+ */
+
+#ifndef __DAL_TRANSFORM_DCE110_H__
+#define __DAL_TRANSFORM_DCE110_H__
+
+#include "inc/transform.h"
+#include "include/grph_csc_types.h"
+
+#define TO_DCE110_TRANSFORM(transform)\
+	container_of(transform, struct dce110_transform, base)
+
+struct dce110_transform_reg_offsets {
+	uint32_t scl_offset;
+	uint32_t dcfe_offset;
+	uint32_t dcp_offset;
+	uint32_t lb_offset;
+};
+
+struct dce110_transform {
+	struct transform base;
+	struct dce110_transform_reg_offsets offsets;
+
+	uint32_t lb_pixel_depth_supported;
+};
+
+bool dce110_transform_construct(struct dce110_transform *xfm110,
+	struct dc_context *ctx,
+	uint32_t inst,
+	const struct dce110_transform_reg_offsets *reg_offsets);
+
+bool dce110_transform_power_up(struct transform *xfm);
+
+/* SCALER RELATED */
+bool dce110_transform_set_scaler(
+	struct transform *xfm,
+	const struct scaler_data *data);
+
+void dce110_transform_set_scaler_bypass(struct transform *xfm);
+
+bool dce110_transform_update_viewport(
+	struct transform *xfm,
+	const struct rect *view_port,
+	bool is_fbc_attached);
+
+void dce110_transform_set_scaler_filter(
+	struct transform *xfm,
+	struct scaler_filter *filter);
+
+/* GAMUT RELATED */
+void dce110_transform_set_gamut_remap(
+	struct transform *xfm,
+	const struct grph_csc_adjustment *adjust);
+
+/* BIT DEPTH RELATED */
+bool dce110_transform_set_pixel_storage_depth(
+	struct transform *xfm,
+	enum lb_pixel_depth depth,
+	const struct bit_depth_reduction_params *bit_depth_params);
+
+bool dce110_transform_get_current_pixel_storage_depth(
+	struct transform *xfm,
+	enum lb_pixel_depth *depth);
+
+
+#endif
diff --git a/drivers/gpu/drm/amd/dal/dc/dce110/dce110_transform_bit_depth.c b/drivers/gpu/drm/amd/dal/dc/dce110/dce110_transform_bit_depth.c
new file mode 100644
index 000000000000..fb5ef6d2c859
--- /dev/null
+++ b/drivers/gpu/drm/amd/dal/dc/dce110/dce110_transform_bit_depth.c
@@ -0,0 +1,851 @@
+/*
+ * 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 DCE11 register header files */
+#include "dce/dce_11_0_d.h"
+#include "dce/dce_11_0_sh_mask.h"
+
+#include "dce110_transform.h"
+#include "opp.h"
+#include "include/logger_interface.h"
+#include "include/fixed32_32.h"
+
+#define DCP_REG(reg)\
+	(reg + xfm110->offsets.dcp_offset)
+
+#define LB_REG(reg)\
+	(reg + xfm110->offsets.lb_offset)
+
+#define LB_TOTAL_NUMBER_OF_ENTRIES 1712
+#define LB_BITS_PER_ENTRY 144
+
+enum dcp_out_trunc_round_mode {
+	DCP_OUT_TRUNC_ROUND_MODE_TRUNCATE,
+	DCP_OUT_TRUNC_ROUND_MODE_ROUND
+};
+
+enum dcp_out_trunc_round_depth {
+	DCP_OUT_TRUNC_ROUND_DEPTH_14BIT,
+	DCP_OUT_TRUNC_ROUND_DEPTH_13BIT,
+	DCP_OUT_TRUNC_ROUND_DEPTH_12BIT,
+	DCP_OUT_TRUNC_ROUND_DEPTH_11BIT,
+	DCP_OUT_TRUNC_ROUND_DEPTH_10BIT,
+	DCP_OUT_TRUNC_ROUND_DEPTH_9BIT,
+	DCP_OUT_TRUNC_ROUND_DEPTH_8BIT
+};
+
+/*  defines the various methods of bit reduction available for use */
+enum dcp_bit_depth_reduction_mode {
+	DCP_BIT_DEPTH_REDUCTION_MODE_DITHER,
+	DCP_BIT_DEPTH_REDUCTION_MODE_ROUND,
+	DCP_BIT_DEPTH_REDUCTION_MODE_TRUNCATE,
+	DCP_BIT_DEPTH_REDUCTION_MODE_DISABLED,
+	DCP_BIT_DEPTH_REDUCTION_MODE_INVALID
+};
+
+enum dcp_spatial_dither_mode {
+	DCP_SPATIAL_DITHER_MODE_AAAA,
+	DCP_SPATIAL_DITHER_MODE_A_AA_A,
+	DCP_SPATIAL_DITHER_MODE_AABBAABB,
+	DCP_SPATIAL_DITHER_MODE_AABBCCAABBCC,
+	DCP_SPATIAL_DITHER_MODE_INVALID
+};
+
+enum dcp_spatial_dither_depth {
+	DCP_SPATIAL_DITHER_DEPTH_30BPP,
+	DCP_SPATIAL_DITHER_DEPTH_24BPP
+};
+
+static bool set_clamp(
+	struct dce110_transform *xfm110,
+	enum dc_color_depth depth);
+
+static bool set_round(
+	struct dce110_transform *xfm110,
+	enum dcp_out_trunc_round_mode mode,
+	enum dcp_out_trunc_round_depth depth);
+
+static bool set_dither(
+	struct dce110_transform *xfm110,
+	bool dither_enable,
+	enum dcp_spatial_dither_mode dither_mode,
+	enum dcp_spatial_dither_depth dither_depth,
+	bool frame_random_enable,
+	bool rgb_random_enable,
+	bool highpass_random_enable);
+
+/**
+ *******************************************************************************
+ * dce110_transform_bit_depth_reduction_program
+ *
+ * @brief
+ *     Programs the DCP bit depth reduction registers (Clamp, Round/Truncate,
+ *      Dither) for dce110
+ *
+ * @param depth : bit depth to set the clamp to (should match denorm)
+ *
+ * @return
+ *     true if succeeds.
+ *******************************************************************************
+ */
+static bool program_bit_depth_reduction(
+	struct dce110_transform *xfm110,
+	enum dc_color_depth depth,
+	const struct bit_depth_reduction_params *bit_depth_params)
+{
+	enum dcp_bit_depth_reduction_mode depth_reduction_mode;
+	enum dcp_spatial_dither_mode spatial_dither_mode;
+	bool frame_random_enable;
+	bool rgb_random_enable;
+	bool highpass_random_enable;
+
+	if (depth > COLOR_DEPTH_121212) {
+		ASSERT_CRITICAL(false); /* Invalid clamp bit depth */
+		return false;
+	}
+
+	if (bit_depth_params->flags.SPATIAL_DITHER_ENABLED) {
+		depth_reduction_mode = DCP_BIT_DEPTH_REDUCTION_MODE_DITHER;
+		frame_random_enable = true;
+		rgb_random_enable = true;
+		highpass_random_enable = true;
+
+	} else {
+		depth_reduction_mode = DCP_BIT_DEPTH_REDUCTION_MODE_DISABLED;
+		frame_random_enable = false;
+		rgb_random_enable = false;
+		highpass_random_enable = false;
+	}
+
+	spatial_dither_mode = DCP_SPATIAL_DITHER_MODE_A_AA_A;
+
+	if (!set_clamp(xfm110, depth)) {
+		/* Failure in set_clamp() */
+		ASSERT_CRITICAL(false);
+		return false;
+	}
+
+	switch (depth_reduction_mode) {
+	case DCP_BIT_DEPTH_REDUCTION_MODE_DITHER:
+		/*  Spatial Dither: Set round/truncate to bypass (12bit),
+		 *  enable Dither (30bpp) */
+		set_round(xfm110,
+			DCP_OUT_TRUNC_ROUND_MODE_TRUNCATE,
+			DCP_OUT_TRUNC_ROUND_DEPTH_12BIT);
+
+		set_dither(xfm110, true, spatial_dither_mode,
+			DCP_SPATIAL_DITHER_DEPTH_30BPP, frame_random_enable,
+			rgb_random_enable, highpass_random_enable);
+		break;
+	case DCP_BIT_DEPTH_REDUCTION_MODE_ROUND:
+		/*  Round: Enable round (10bit), disable Dither */
+		set_round(xfm110,
+			DCP_OUT_TRUNC_ROUND_MODE_ROUND,
+			DCP_OUT_TRUNC_ROUND_DEPTH_10BIT);
+
+		set_dither(xfm110, false, spatial_dither_mode,
+			DCP_SPATIAL_DITHER_DEPTH_30BPP, frame_random_enable,
+			rgb_random_enable, highpass_random_enable);
+		break;
+	case DCP_BIT_DEPTH_REDUCTION_MODE_TRUNCATE: /*  Truncate */
+		/*  Truncate: Enable truncate (10bit), disable Dither */
+		set_round(xfm110,
+			DCP_OUT_TRUNC_ROUND_MODE_TRUNCATE,
+			DCP_OUT_TRUNC_ROUND_DEPTH_10BIT);
+
+		set_dither(xfm110, false, spatial_dither_mode,
+			DCP_SPATIAL_DITHER_DEPTH_30BPP, frame_random_enable,
+			rgb_random_enable, highpass_random_enable);
+		break;
+
+	case DCP_BIT_DEPTH_REDUCTION_MODE_DISABLED: /*  Disabled */
+		/*  Truncate: Set round/truncate to bypass (12bit),
+		 * disable Dither */
+		set_round(xfm110,
+			DCP_OUT_TRUNC_ROUND_MODE_TRUNCATE,
+			DCP_OUT_TRUNC_ROUND_DEPTH_12BIT);
+
+		set_dither(xfm110, false, spatial_dither_mode,
+			DCP_SPATIAL_DITHER_DEPTH_30BPP, frame_random_enable,
+			rgb_random_enable, highpass_random_enable);
+		break;
+	default:
+		/* Invalid DCP Depth reduction mode */
+		ASSERT_CRITICAL(false);
+		break;
+	}
+
+	return true;
+}
+
+/**
+ *******************************************************************************
+ * set_clamp
+ *
+ * @param depth : bit depth to set the clamp to (should match denorm)
+ *
+ * @brief
+ *     Programs clamp according to panel bit depth.
+ *
+ * @return
+ *     true if succeeds
+ *
+ *******************************************************************************
+ */
+static bool set_clamp(
+	struct dce110_transform *xfm110,
+	enum dc_color_depth depth)
+{
+	uint32_t clamp_max = 0;
+
+	/* At the clamp block the data will be MSB aligned, so we set the max
+	 * clamp accordingly.
+	 * For example, the max value for 6 bits MSB aligned (14 bit bus) would
+	 * be "11 1111 0000 0000" in binary, so 0x3F00.
+	 */
+	switch (depth) {
+	case COLOR_DEPTH_666:
+		/* 6bit MSB aligned on 14 bit bus '11 1111 0000 0000' */
+		clamp_max = 0x3F00;
+		break;
+	case COLOR_DEPTH_888:
+		/* 8bit MSB aligned on 14 bit bus '11 1111 1100 0000' */
+		clamp_max = 0x3FC0;
+		break;
+	case COLOR_DEPTH_101010:
+		/* 10bit MSB aligned on 14 bit bus '11 1111 1111 1100' */
+		clamp_max = 0x3FFC;
+		break;
+	case COLOR_DEPTH_121212:
+		/* 12bit MSB aligned on 14 bit bus '11 1111 1111 1111' */
+		clamp_max = 0x3FFF;
+		break;
+	default:
+		ASSERT_CRITICAL(false); /* Invalid clamp bit depth */
+		return false;
+	}
+
+	{
+		uint32_t value = 0;
+		/*  always set min to 0 */
+			set_reg_field_value(
+			value,
+			0,
+			OUT_CLAMP_CONTROL_B_CB,
+			OUT_CLAMP_MIN_B_CB);
+
+		set_reg_field_value(
+			value,
+			clamp_max,
+			OUT_CLAMP_CONTROL_B_CB,
+			OUT_CLAMP_MAX_B_CB);
+
+		dm_write_reg(xfm110->base.ctx,
+			DCP_REG(mmOUT_CLAMP_CONTROL_B_CB),
+			value);
+	}
+
+	{
+		uint32_t value = 0;
+		/*  always set min to 0 */
+		set_reg_field_value(
+			value,
+			0,
+			OUT_CLAMP_CONTROL_G_Y,
+			OUT_CLAMP_MIN_G_Y);
+
+		set_reg_field_value(
+			value,
+			clamp_max,
+			OUT_CLAMP_CONTROL_G_Y,
+			OUT_CLAMP_MAX_G_Y);
+
+		dm_write_reg(xfm110->base.ctx,
+			DCP_REG(mmOUT_CLAMP_CONTROL_G_Y),
+			value);
+	}
+
+	{
+		uint32_t value = 0;
+		/*  always set min to 0 */
+		set_reg_field_value(
+			value,
+			0,
+			OUT_CLAMP_CONTROL_R_CR,
+			OUT_CLAMP_MIN_R_CR);
+
+		set_reg_field_value(
+			value,
+			clamp_max,
+			OUT_CLAMP_CONTROL_R_CR,
+			OUT_CLAMP_MAX_R_CR);
+
+		dm_write_reg(xfm110->base.ctx,
+			DCP_REG(mmOUT_CLAMP_CONTROL_R_CR),
+			value);
+	}
+
+	return true;
+}
+
+/**
+ *******************************************************************************
+ * set_round
+ *
+ * @brief
+ *     Programs Round/Truncate
+ *
+ * @param [in] mode  :round or truncate
+ * @param [in] depth :bit depth to round/truncate to
+ OUT_ROUND_TRUNC_MODE 3:0 0xA Output data round or truncate mode
+ POSSIBLE VALUES:
+      00 - truncate to u0.12
+      01 - truncate to u0.11
+      02 - truncate to u0.10
+      03 - truncate to u0.9
+      04 - truncate to u0.8
+      05 - reserved
+      06 - truncate to u0.14
+      07 - truncate to u0.13		set_reg_field_value(
+			value,
+			clamp_max,
+			OUT_CLAMP_CONTROL_R_CR,
+			OUT_CLAMP_MAX_R_CR);
+      08 - round to u0.12
+      09 - round to u0.11
+      10 - round to u0.10
+      11 - round to u0.9
+      12 - round to u0.8
+      13 - reserved
+      14 - round to u0.14
+      15 - round to u0.13
+
+ * @return
+ *     true if succeeds.
+ *******************************************************************************
+ */
+static bool set_round(
+	struct dce110_transform *xfm110,
+	enum dcp_out_trunc_round_mode mode,
+	enum dcp_out_trunc_round_depth depth)
+{
+	uint32_t depth_bits = 0;
+	uint32_t mode_bit = 0;
+	/*  zero out all bits */
+	uint32_t value = 0;
+
+	/*  set up bit depth */
+	switch (depth) {
+	case DCP_OUT_TRUNC_ROUND_DEPTH_14BIT:
+		depth_bits = 6;
+		break;
+	case DCP_OUT_TRUNC_ROUND_DEPTH_13BIT:
+		depth_bits = 7;
+		break;
+	case DCP_OUT_TRUNC_ROUND_DEPTH_12BIT:
+		depth_bits = 0;
+		break;
+	case DCP_OUT_TRUNC_ROUND_DEPTH_11BIT:
+		depth_bits = 1;
+		break;
+	case DCP_OUT_TRUNC_ROUND_DEPTH_10BIT:
+		depth_bits = 2;
+		break;
+	case DCP_OUT_TRUNC_ROUND_DEPTH_9BIT:
+		depth_bits = 3;
+		break;
+	case DCP_OUT_TRUNC_ROUND_DEPTH_8BIT:
+		depth_bits = 4;
+		break;
+	default:
+		/* Invalid dcp_out_trunc_round_depth */
+		ASSERT_CRITICAL(false);
+		return false;
+	}
+
+	set_reg_field_value(
+		value,
+		depth_bits,
+		OUT_ROUND_CONTROL,
+		OUT_ROUND_TRUNC_MODE);
+
+	/*  set up round or truncate */
+	switch (mode) {
+	case DCP_OUT_TRUNC_ROUND_MODE_TRUNCATE:
+		mode_bit = 0;
+		break;
+	case DCP_OUT_TRUNC_ROUND_MODE_ROUND:
+		mode_bit = 1;
+		break;
+	default:
+		/* Invalid dcp_out_trunc_round_mode */
+		ASSERT_CRITICAL(false);
+		return false;
+	}
+
+	depth_bits |= mode_bit << 3;
+
+	set_reg_field_value(
+		value,
+		depth_bits,
+		OUT_ROUND_CONTROL,
+		OUT_ROUND_TRUNC_MODE);
+
+	/*  write the register */
+	dm_write_reg(xfm110->base.ctx,
+				DCP_REG(mmOUT_ROUND_CONTROL),
+				value);
+
+	return true;
+}
+
+/**
+ *******************************************************************************
+ * set_dither
+ *
+ * @brief
+ *     Programs Dither
+ *
+ * @param [in] dither_enable        : enable dither
+ * @param [in] dither_mode           : dither mode to set
+ * @param [in] dither_depth          : bit depth to dither to
+ * @param [in] frame_random_enable    : enable frame random
+ * @param [in] rgb_random_enable      : enable rgb random
+ * @param [in] highpass_random_enable : enable highpass random
+ *
+ * @return
+ *     true if succeeds.
+ *******************************************************************************
+ */
+
+static bool set_dither(
+	struct dce110_transform *xfm110,
+	bool dither_enable,
+	enum dcp_spatial_dither_mode dither_mode,
+	enum dcp_spatial_dither_depth dither_depth,
+	bool frame_random_enable,
+	bool rgb_random_enable,
+	bool highpass_random_enable)
+{
+	uint32_t dither_depth_bits = 0;
+	uint32_t dither_mode_bits = 0;
+	/*  zero out all bits */
+	uint32_t value = 0;
+
+	/* set up the fields */
+	if (dither_enable)
+		set_reg_field_value(
+			value,
+			1,
+			DCP_SPATIAL_DITHER_CNTL,
+			DCP_SPATIAL_DITHER_EN);
+
+	switch (dither_mode) {
+	case DCP_SPATIAL_DITHER_MODE_AAAA:
+		dither_mode_bits = 0;
+		break;
+	case DCP_SPATIAL_DITHER_MODE_A_AA_A:
+		dither_mode_bits = 1;
+		break;
+	case DCP_SPATIAL_DITHER_MODE_AABBAABB:
+		dither_mode_bits = 2;
+		break;
+	case DCP_SPATIAL_DITHER_MODE_AABBCCAABBCC:
+		dither_mode_bits = 3;
+		break;
+	default:
+		/* Invalid dcp_spatial_dither_mode */
+		ASSERT_CRITICAL(false);
+		return false;
+
+	}
+	set_reg_field_value(
+		value,
+		dither_mode_bits,
+		DCP_SPATIAL_DITHER_CNTL,
+		DCP_SPATIAL_DITHER_MODE);
+
+	switch (dither_depth) {
+	case DCP_SPATIAL_DITHER_DEPTH_30BPP:
+		dither_depth_bits = 0;
+		break;
+	case DCP_SPATIAL_DITHER_DEPTH_24BPP:
+		dither_depth_bits = 1;
+		break;
+	default:
+		/* Invalid dcp_spatial_dither_depth */
+		ASSERT_CRITICAL(false);
+		return false;
+	}
+
+	set_reg_field_value(
+		value,
+		dither_depth_bits,
+		DCP_SPATIAL_DITHER_CNTL,
+		DCP_SPATIAL_DITHER_DEPTH);
+
+	if (frame_random_enable)
+		set_reg_field_value(
+			value,
+			1,
+			DCP_SPATIAL_DITHER_CNTL,
+			DCP_FRAME_RANDOM_ENABLE);
+
+	if (rgb_random_enable)
+		set_reg_field_value(
+			value,
+			1,
+			DCP_SPATIAL_DITHER_CNTL,
+			DCP_RGB_RANDOM_ENABLE);
+
+	if (highpass_random_enable)
+		set_reg_field_value(
+			value,
+			1,
+			DCP_SPATIAL_DITHER_CNTL,
+			DCP_HIGHPASS_RANDOM_ENABLE);
+
+	/*  write the register */
+	dm_write_reg(xfm110->base.ctx,
+				DCP_REG(mmDCP_SPATIAL_DITHER_CNTL),
+				value);
+
+	return true;
+}
+
+bool dce110_transform_get_max_num_of_supported_lines(
+	struct dce110_transform *xfm110,
+	enum lb_pixel_depth depth,
+	uint32_t pixel_width,
+	uint32_t *lines)
+{
+	uint32_t pixels_per_entries = 0;
+	uint32_t max_pixels_supports = 0;
+
+	if (pixel_width == 0)
+		return false;
+
+	/* Find number of pixels that can fit into a single LB entry and
+	 * take floor of the value since we cannot store a single pixel
+	 * across multiple entries. */
+	switch (depth) {
+	case LB_PIXEL_DEPTH_18BPP:
+		pixels_per_entries = LB_BITS_PER_ENTRY / 18;
+		break;
+
+	case LB_PIXEL_DEPTH_24BPP:
+		pixels_per_entries = LB_BITS_PER_ENTRY / 24;
+		break;
+
+	case LB_PIXEL_DEPTH_30BPP:
+		pixels_per_entries = LB_BITS_PER_ENTRY / 30;
+		break;
+
+	case LB_PIXEL_DEPTH_36BPP:
+		pixels_per_entries = LB_BITS_PER_ENTRY / 36;
+		break;
+
+	default:
+		dal_logger_write(xfm110->base.ctx->logger,
+			LOG_MAJOR_WARNING,
+			LOG_MINOR_COMPONENT_GPU,
+			"%s: Invalid LB pixel depth",
+			__func__);
+		break;
+	}
+
+	if (pixels_per_entries == 0)
+		return false;
+
+	max_pixels_supports = pixels_per_entries * LB_TOTAL_NUMBER_OF_ENTRIES;
+
+	*lines = max_pixels_supports / pixel_width;
+	return true;
+}
+
+void dce110_transform_enable_alpha(
+	struct dce110_transform *xfm110,
+	bool enable)
+{
+	struct dc_context *ctx = xfm110->base.ctx;
+	uint32_t value;
+	uint32_t addr = LB_REG(mmLB_DATA_FORMAT);
+
+	value = dm_read_reg(ctx, addr);
+
+	if (enable == 1)
+		set_reg_field_value(
+				value,
+				1,
+				LB_DATA_FORMAT,
+				ALPHA_EN);
+	else
+		set_reg_field_value(
+				value,
+				0,
+				LB_DATA_FORMAT,
+				ALPHA_EN);
+
+	dm_write_reg(ctx, addr, value);
+}
+
+static enum lb_pixel_depth translate_display_bpp_to_lb_depth(
+	uint32_t display_bpp)
+{
+	switch (display_bpp) {
+	case 18:
+		return LB_PIXEL_DEPTH_18BPP;
+	case 24:
+		return LB_PIXEL_DEPTH_24BPP;
+	case 36:
+	case 42:
+	case 48:
+		return LB_PIXEL_DEPTH_36BPP;
+	case 30:
+	default:
+		return LB_PIXEL_DEPTH_30BPP;
+	}
+}
+
+bool dce110_transform_get_next_lower_pixel_storage_depth(
+	struct dce110_transform *xfm110,
+	uint32_t display_bpp,
+	enum lb_pixel_depth depth,
+	enum lb_pixel_depth *lower_depth)
+{
+	enum lb_pixel_depth depth_req_by_display =
+		translate_display_bpp_to_lb_depth(display_bpp);
+	uint32_t current_required_depth = depth_req_by_display;
+	uint32_t current_depth = depth;
+
+	/* if required display depth < current we could go down, for example
+	 * from LB_PIXEL_DEPTH_30BPP to LB_PIXEL_DEPTH_24BPP
+	 */
+	if (current_required_depth < current_depth) {
+		current_depth = current_depth >> 1;
+		if (xfm110->lb_pixel_depth_supported & current_depth) {
+			*lower_depth = current_depth;
+			return true;
+		}
+	}
+	return false;
+}
+
+bool dce110_transform_is_prefetch_enabled(
+	struct dce110_transform *xfm110)
+{
+	uint32_t value = dm_read_reg(
+			xfm110->base.ctx, LB_REG(mmLB_DATA_FORMAT));
+
+	if (get_reg_field_value(value, LB_DATA_FORMAT, PREFETCH) == 1)
+		return true;
+
+	return false;
+}
+
+bool dce110_transform_get_current_pixel_storage_depth(
+	struct transform *xfm,
+	enum lb_pixel_depth *depth)
+{
+	struct dce110_transform *xfm110 = TO_DCE110_TRANSFORM(xfm);
+	uint32_t value = 0;
+
+	if (depth == NULL)
+		return false;
+
+	value = dm_read_reg(
+			xfm->ctx,
+			LB_REG(mmLB_DATA_FORMAT));
+
+	switch (get_reg_field_value(value, LB_DATA_FORMAT, PIXEL_DEPTH)) {
+	case 0:
+		*depth = LB_PIXEL_DEPTH_30BPP;
+		break;
+	case 1:
+		*depth = LB_PIXEL_DEPTH_24BPP;
+		break;
+	case 2:
+		*depth = LB_PIXEL_DEPTH_18BPP;
+		break;
+	case 3:
+		*depth = LB_PIXEL_DEPTH_36BPP;
+		break;
+	default:
+		dal_logger_write(xfm->ctx->logger,
+			LOG_MAJOR_WARNING,
+			LOG_MINOR_COMPONENT_GPU,
+			"%s: Invalid LB pixel depth",
+			__func__);
+		*depth = LB_PIXEL_DEPTH_30BPP;
+		break;
+	}
+	return true;
+
+}
+
+static void set_denormalization(
+	struct dce110_transform *xfm110,
+	enum dc_color_depth depth)
+{
+	uint32_t value = dm_read_reg(xfm110->base.ctx,
+			DCP_REG(mmDENORM_CONTROL));
+
+	switch (depth) {
+	case COLOR_DEPTH_666:
+		/* 63/64 for 6 bit output color depth */
+		set_reg_field_value(
+			value,
+			1,
+			DENORM_CONTROL,
+			DENORM_MODE);
+		break;
+	case COLOR_DEPTH_888:
+		/* Unity for 8 bit output color depth
+		 * because prescale is disabled by default */
+		set_reg_field_value(
+			value,
+			0,
+			DENORM_CONTROL,
+			DENORM_MODE);
+		break;
+	case COLOR_DEPTH_101010:
+		/* 1023/1024 for 10 bit output color depth */
+		set_reg_field_value(
+			value,
+			3,
+			DENORM_CONTROL,
+			DENORM_MODE);
+		break;
+	case COLOR_DEPTH_121212:
+		/* 4095/4096 for 12 bit output color depth */
+		set_reg_field_value(
+			value,
+			5,
+			DENORM_CONTROL,
+			DENORM_MODE);
+		break;
+	case COLOR_DEPTH_141414:
+	case COLOR_DEPTH_161616:
+	default:
+		/* not valid used case! */
+		break;
+	}
+
+	dm_write_reg(xfm110->base.ctx,
+			DCP_REG(mmDENORM_CONTROL),
+			value);
+
+}
+
+bool dce110_transform_set_pixel_storage_depth(
+	struct transform *xfm,
+	enum lb_pixel_depth depth,
+	const struct bit_depth_reduction_params *bit_depth_params)
+{
+	struct dce110_transform *xfm110 = TO_DCE110_TRANSFORM(xfm);
+	bool ret = true;
+	uint32_t value;
+	enum dc_color_depth color_depth;
+
+	value = dm_read_reg(
+			xfm->ctx,
+			LB_REG(mmLB_DATA_FORMAT));
+	switch (depth) {
+	case LB_PIXEL_DEPTH_18BPP:
+		color_depth = COLOR_DEPTH_666;
+		set_reg_field_value(value, 2, LB_DATA_FORMAT, PIXEL_DEPTH);
+		set_reg_field_value(value, 1, LB_DATA_FORMAT, PIXEL_EXPAN_MODE);
+		break;
+	case LB_PIXEL_DEPTH_24BPP:
+		color_depth = COLOR_DEPTH_888;
+		set_reg_field_value(value, 1, LB_DATA_FORMAT, PIXEL_DEPTH);
+		set_reg_field_value(value, 1, LB_DATA_FORMAT, PIXEL_EXPAN_MODE);
+		break;
+	case LB_PIXEL_DEPTH_30BPP:
+		color_depth = COLOR_DEPTH_101010;
+		set_reg_field_value(value, 0, LB_DATA_FORMAT, PIXEL_DEPTH);
+		set_reg_field_value(value, 1, LB_DATA_FORMAT, PIXEL_EXPAN_MODE);
+		break;
+	case LB_PIXEL_DEPTH_36BPP:
+		color_depth = COLOR_DEPTH_121212;
+		set_reg_field_value(value, 3, LB_DATA_FORMAT, PIXEL_DEPTH);
+		set_reg_field_value(value, 0, LB_DATA_FORMAT, PIXEL_EXPAN_MODE);
+		break;
+	default:
+		ret = false;
+		break;
+	}
+
+	if (ret == true) {
+		set_denormalization(xfm110, color_depth);
+		ret = program_bit_depth_reduction(xfm110, color_depth,
+				bit_depth_params);
+
+		set_reg_field_value(value, 0, LB_DATA_FORMAT, ALPHA_EN);
+		dm_write_reg(
+				xfm->ctx, LB_REG(mmLB_DATA_FORMAT), value);
+		if (!(xfm110->lb_pixel_depth_supported & depth)) {
+			/*we should use unsupported capabilities
+			 *  unless it is required by w/a*/
+			dal_logger_write(xfm->ctx->logger,
+				LOG_MAJOR_WARNING,
+				LOG_MINOR_COMPONENT_GPU,
+				"%s: Capability not supported",
+				__func__);
+		}
+	}
+
+	return ret;
+}
+
+/* LB_MEMORY_CONFIG
+ *  00 - Use all three pieces of memory
+ *  01 - Use only one piece of memory of total 720x144 bits
+ *  10 - Use two pieces of memory of total 960x144 bits
+ *  11 - reserved
+ *
+ * LB_MEMORY_SIZE
+ *  Total entries of LB memory.
+ *  This number should be larger than 960. The default value is 1712(0x6B0) */
+bool dce110_transform_power_up_line_buffer(struct transform *xfm)
+{
+	struct dce110_transform *xfm110 = TO_DCE110_TRANSFORM(xfm);
+	uint32_t value;
+
+	value = dm_read_reg(xfm110->base.ctx, LB_REG(mmLB_MEMORY_CTRL));
+
+	/*Use all three pieces of memory always*/
+	set_reg_field_value(value, 0, LB_MEMORY_CTRL, LB_MEMORY_CONFIG);
+	/*hard coded number DCE11 1712(0x6B0) Partitions: 720/960/1712*/
+	set_reg_field_value(value, LB_TOTAL_NUMBER_OF_ENTRIES, LB_MEMORY_CTRL,
+			LB_MEMORY_SIZE);
+
+	dm_write_reg(xfm110->base.ctx, LB_REG(mmLB_MEMORY_CTRL), value);
+
+	return true;
+}
+
diff --git a/drivers/gpu/drm/amd/dal/dc/dce110/dce110_transform_bit_depth.h b/drivers/gpu/drm/amd/dal/dc/dce110/dce110_transform_bit_depth.h
new file mode 100644
index 000000000000..ff100cc7f30f
--- /dev/null
+++ b/drivers/gpu/drm/amd/dal/dc/dce110/dce110_transform_bit_depth.h
@@ -0,0 +1,51 @@
+/* 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_TRANSFORM_BIT_DEPTH_DCE110_H__
+#define __DC_TRANSFORM_BIT_DEPTH_DCE110_H__
+
+#include "dce110_transform.h"
+
+bool dce110_transform_power_up_line_buffer(struct transform *xfm);
+
+bool dce110_transform_get_max_num_of_supported_lines(
+	struct dce110_transform *xfm110,
+	enum lb_pixel_depth depth,
+	uint32_t pixel_width,
+	uint32_t *lines);
+
+void dce110_transform_enable_alpha(
+	struct dce110_transform *xfm110,
+	bool enable);
+
+bool dce110_transform_get_next_lower_pixel_storage_depth(
+	struct dce110_transform *xfm110,
+	uint32_t display_bpp,
+	enum lb_pixel_depth depth,
+	enum lb_pixel_depth *lower_depth);
+
+bool dce110_transform_is_prefetch_enabled(
+	struct dce110_transform *xfm110);
+
+#endif
diff --git a/drivers/gpu/drm/amd/dal/dc/dce110/dce110_transform_gamut.c b/drivers/gpu/drm/amd/dal/dc/dce110/dce110_transform_gamut.c
new file mode 100644
index 000000000000..05309c9f9482
--- /dev/null
+++ b/drivers/gpu/drm/amd/dal/dc/dce110/dce110_transform_gamut.c
@@ -0,0 +1,296 @@
+/* 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 "dce110_transform.h"
+#include "dce/dce_11_0_d.h"
+#include "dce/dce_11_0_sh_mask.h"
+#include "include/fixed31_32.h"
+#include "basics/conversion.h"
+#include "include/grph_object_id.h"
+
+enum {
+	GAMUT_MATRIX_SIZE = 12
+};
+
+#define DCP_REG(reg)\
+	(reg + xfm110->offsets.dcp_offset)
+
+#define DISP_BRIGHTNESS_DEFAULT_HW 0
+#define DISP_BRIGHTNESS_MIN_HW -25
+#define DISP_BRIGHTNESS_MAX_HW 25
+#define DISP_BRIGHTNESS_STEP_HW 1
+#define DISP_BRIGHTNESS_HW_DIVIDER 100
+
+#define DISP_HUE_DEFAULT_HW 0
+#define DISP_HUE_MIN_HW -30
+#define DISP_HUE_MAX_HW 30
+#define DISP_HUE_STEP_HW 1
+#define DISP_HUE_HW_DIVIDER 1
+
+#define DISP_CONTRAST_DEFAULT_HW 100
+#define DISP_CONTRAST_MIN_HW 50
+#define DISP_CONTRAST_MAX_HW 150
+#define DISP_CONTRAST_STEP_HW 1
+#define DISP_CONTRAST_HW_DIVIDER 100
+
+#define DISP_SATURATION_DEFAULT_HW 100
+#define DISP_SATURATION_MIN_HW 0
+#define DISP_SATURATION_MAX_HW 200
+#define DISP_SATURATION_STEP_HW 1
+#define DISP_SATURATION_HW_DIVIDER 100
+
+#define DISP_KELVIN_DEGRES_DEFAULT 6500
+#define DISP_KELVIN_DEGRES_MIN 4000
+#define DISP_KELVIN_DEGRES_MAX 10000
+#define DISP_KELVIN_DEGRES_STEP 100
+#define DISP_KELVIN_HW_DIVIDER 10000
+
+static void program_gamut_remap(
+	struct dce110_transform *xfm110,
+	const uint16_t *reg_val)
+{
+	struct dc_context *ctx = xfm110->base.ctx;
+	uint32_t value = 0;
+	uint32_t addr = DCP_REG(mmGAMUT_REMAP_CONTROL);
+
+	/* the register controls ovl also */
+	value = dm_read_reg(ctx, addr);
+
+	if (reg_val) {
+		{
+			uint32_t reg_data = 0;
+			uint32_t addr = DCP_REG(mmGAMUT_REMAP_C11_C12);
+
+			/* fixed S2.13 format */
+			set_reg_field_value(
+				reg_data,
+				reg_val[0],
+				GAMUT_REMAP_C11_C12,
+				GAMUT_REMAP_C11);
+			/* fixed S2.13 format */
+			set_reg_field_value(
+				reg_data,
+				reg_val[1],
+				GAMUT_REMAP_C11_C12,
+				GAMUT_REMAP_C12);
+
+			dm_write_reg(ctx, addr, reg_data);
+		}
+		{
+			uint32_t reg_data = 0;
+			uint32_t addr = DCP_REG(mmGAMUT_REMAP_C13_C14);
+
+			/* fixed S2.13 format */
+			set_reg_field_value(
+				reg_data,
+				reg_val[2],
+				GAMUT_REMAP_C13_C14,
+				GAMUT_REMAP_C13);
+
+			/* fixed S0.13 format */
+			set_reg_field_value(
+				reg_data,
+				reg_val[3],
+				GAMUT_REMAP_C13_C14,
+				GAMUT_REMAP_C14);
+
+			dm_write_reg(ctx, addr, reg_data);
+		}
+		{
+			uint32_t reg_data = 0;
+			uint32_t addr = DCP_REG(mmGAMUT_REMAP_C21_C22);
+
+			/* fixed S2.13 format */
+			set_reg_field_value(
+				reg_data,
+				reg_val[4],
+				GAMUT_REMAP_C21_C22,
+				GAMUT_REMAP_C21);
+
+			/* fixed S0.13 format */
+			set_reg_field_value(
+				reg_data,
+				reg_val[5],
+				GAMUT_REMAP_C21_C22,
+				GAMUT_REMAP_C22);
+
+			dm_write_reg(ctx, addr, reg_data);
+		}
+		{
+			uint32_t reg_data = 0;
+			uint32_t addr = DCP_REG(mmGAMUT_REMAP_C23_C24);
+
+			/* fixed S2.13 format */
+			set_reg_field_value(
+				reg_data,
+				reg_val[6],
+				GAMUT_REMAP_C23_C24,
+				GAMUT_REMAP_C23);
+
+			/* fixed S0.13 format */
+			set_reg_field_value(
+				reg_data,
+				reg_val[7],
+				GAMUT_REMAP_C23_C24,
+				GAMUT_REMAP_C24);
+
+			dm_write_reg(ctx, addr, reg_data);
+		}
+		{
+			uint32_t reg_data = 0;
+			uint32_t addr = DCP_REG(mmGAMUT_REMAP_C31_C32);
+
+			/* fixed S2.13 format */
+			set_reg_field_value(
+				reg_data,
+				reg_val[8],
+				GAMUT_REMAP_C31_C32,
+				GAMUT_REMAP_C31);
+
+			/* fixed S0.13 format */
+			set_reg_field_value(
+				reg_data,
+				reg_val[9],
+				GAMUT_REMAP_C31_C32,
+				GAMUT_REMAP_C32);
+
+			dm_write_reg(ctx, addr, reg_data);
+		}
+		{
+			uint32_t reg_data = 0;
+			uint32_t addr = DCP_REG(mmGAMUT_REMAP_C33_C34);
+
+			/* fixed S2.13 format */
+			set_reg_field_value(
+				reg_data,
+				reg_val[10],
+				GAMUT_REMAP_C33_C34,
+				GAMUT_REMAP_C33);
+
+			/* fixed S0.13 format */
+			set_reg_field_value(
+				reg_data,
+				reg_val[11],
+				GAMUT_REMAP_C33_C34,
+				GAMUT_REMAP_C34);
+
+			dm_write_reg(ctx, addr, reg_data);
+		}
+
+		set_reg_field_value(
+			value,
+			1,
+			GAMUT_REMAP_CONTROL,
+			GRPH_GAMUT_REMAP_MODE);
+
+	} else
+		set_reg_field_value(
+			value,
+			0,
+			GAMUT_REMAP_CONTROL,
+			GRPH_GAMUT_REMAP_MODE);
+
+	addr = DCP_REG(mmGAMUT_REMAP_CONTROL);
+	dm_write_reg(ctx, addr, value);
+
+}
+
+/**
+ *****************************************************************************
+ *  Function: dal_transform_wide_gamut_set_gamut_remap
+ *
+ *  @param [in] const struct grph_csc_adjustment *adjust
+ *
+ *  @return
+ *     void
+ *
+ *  @note calculate and apply color temperature adjustment to in Rgb color space
+ *
+ *  @see
+ *
+ *****************************************************************************
+ */
+void dce110_transform_set_gamut_remap(
+	struct transform *xfm,
+	const struct grph_csc_adjustment *adjust)
+{
+	struct dce110_transform *xfm110 = TO_DCE110_TRANSFORM(xfm);
+
+	if (adjust->gamut_adjust_type != GRAPHICS_GAMUT_ADJUST_TYPE_SW ||
+		adjust->temperature_divider == 0)
+		program_gamut_remap(xfm110, NULL);
+	else {
+		struct fixed31_32 arr_matrix[GAMUT_MATRIX_SIZE];
+		uint16_t arr_reg_val[GAMUT_MATRIX_SIZE];
+
+		arr_matrix[0] =
+			dal_fixed31_32_from_fraction(
+				adjust->temperature_matrix[0],
+				adjust->temperature_divider);
+		arr_matrix[1] =
+			dal_fixed31_32_from_fraction(
+				adjust->temperature_matrix[1],
+				adjust->temperature_divider);
+		arr_matrix[2] =
+			dal_fixed31_32_from_fraction(
+				adjust->temperature_matrix[2],
+				adjust->temperature_divider);
+		arr_matrix[3] = dal_fixed31_32_zero;
+
+		arr_matrix[4] =
+			dal_fixed31_32_from_fraction(
+				adjust->temperature_matrix[3],
+				adjust->temperature_divider);
+		arr_matrix[5] =
+			dal_fixed31_32_from_fraction(
+				adjust->temperature_matrix[4],
+				adjust->temperature_divider);
+		arr_matrix[6] =
+			dal_fixed31_32_from_fraction(
+				adjust->temperature_matrix[5],
+				adjust->temperature_divider);
+		arr_matrix[7] = dal_fixed31_32_zero;
+
+		arr_matrix[8] =
+			dal_fixed31_32_from_fraction(
+				adjust->temperature_matrix[6],
+				adjust->temperature_divider);
+		arr_matrix[9] =
+			dal_fixed31_32_from_fraction(
+				adjust->temperature_matrix[7],
+				adjust->temperature_divider);
+		arr_matrix[10] =
+			dal_fixed31_32_from_fraction(
+				adjust->temperature_matrix[8],
+				adjust->temperature_divider);
+		arr_matrix[11] = dal_fixed31_32_zero;
+
+		convert_float_matrix(
+			arr_reg_val, arr_matrix, GAMUT_MATRIX_SIZE);
+
+		program_gamut_remap(xfm110, arr_reg_val);
+	}
+}
+
diff --git a/drivers/gpu/drm/amd/dal/dc/dce110/dce110_transform_scl.c b/drivers/gpu/drm/amd/dal/dc/dce110/dce110_transform_scl.c
new file mode 100644
index 000000000000..7c15a13cb9fc
--- /dev/null
+++ b/drivers/gpu/drm/amd/dal/dc/dce110/dce110_transform_scl.c
@@ -0,0 +1,818 @@
+/*
+ * 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 DCE11 register header files */
+#include "dce/dce_11_0_d.h"
+#include "dce/dce_11_0_sh_mask.h"
+
+#include "dce110_transform.h"
+
+#define UP_SCALER_RATIO_MAX 16000
+#define DOWN_SCALER_RATIO_MAX 250
+#define SCALER_RATIO_DIVIDER 1000
+
+#define SCL_REG(reg)\
+	(reg + xfm110->offsets.scl_offset)
+
+#define DCFE_REG(reg)\
+	(reg + xfm110->offsets.dcfe_offset)
+
+static void disable_enhanced_sharpness(struct dce110_transform *xfm110)
+{
+	uint32_t  value;
+
+	value = dm_read_reg(xfm110->base.ctx,
+			SCL_REG(mmSCL_F_SHARP_CONTROL));
+
+	set_reg_field_value(value, 0,
+			SCL_F_SHARP_CONTROL, SCL_HF_SHARP_EN);
+
+	set_reg_field_value(value, 0,
+			SCL_F_SHARP_CONTROL, SCL_VF_SHARP_EN);
+
+	set_reg_field_value(value, 0,
+			SCL_F_SHARP_CONTROL, SCL_HF_SHARP_SCALE_FACTOR);
+
+	set_reg_field_value(value, 0,
+			SCL_F_SHARP_CONTROL, SCL_VF_SHARP_SCALE_FACTOR);
+
+	dm_write_reg(xfm110->base.ctx,
+			SCL_REG(mmSCL_F_SHARP_CONTROL), value);
+}
+
+/**
+* Function:
+* void setup_scaling_configuration
+*
+* Purpose: setup scaling mode : bypass, RGb, YCbCr and nummber of taps
+* Input:   data
+*
+* Output:
+   void
+*/
+static bool setup_scaling_configuration(
+	struct dce110_transform *xfm110,
+	const struct scaler_data *data)
+{
+	struct dc_context *ctx = xfm110->base.ctx;
+	uint32_t addr;
+	uint32_t value;
+
+	if (data->taps.h_taps + data->taps.v_taps <= 2) {
+		dce110_transform_set_scaler_bypass(&xfm110->base);
+		return false;
+	}
+
+	{
+		addr = SCL_REG(mmSCL_MODE);
+		value = dm_read_reg(ctx, addr);
+
+		if (data->dal_pixel_format <= PIXEL_FORMAT_GRPH_END)
+			set_reg_field_value(value, 1, SCL_MODE, SCL_MODE);
+		else
+			set_reg_field_value(value, 2, SCL_MODE, SCL_MODE);
+
+		set_reg_field_value(value, 1, SCL_MODE, SCL_PSCL_EN);
+
+		dm_write_reg(ctx, addr, value);
+	}
+	{
+		addr = SCL_REG(mmSCL_TAP_CONTROL);
+		value = dm_read_reg(ctx, addr);
+
+		set_reg_field_value(value, data->taps.h_taps - 1,
+				SCL_TAP_CONTROL, SCL_H_NUM_OF_TAPS);
+
+		set_reg_field_value(value, data->taps.v_taps - 1,
+				SCL_TAP_CONTROL, SCL_V_NUM_OF_TAPS);
+
+		dm_write_reg(ctx, addr, value);
+	}
+	{
+		addr = SCL_REG(mmSCL_CONTROL);
+		value = dm_read_reg(ctx, addr);
+		 /* 1 - Replaced out of bound pixels with edge */
+		set_reg_field_value(value, 1, SCL_CONTROL, SCL_BOUNDARY_MODE);
+
+		/* 1 - Replaced out of bound pixels with the edge pixel. */
+		dm_write_reg(ctx, addr, value);
+	}
+
+	return true;
+}
+
+/**
+* Function:
+* void program_overscan
+*
+* Purpose: Programs overscan border
+* Input:   overscan
+*
+* Output:
+   void
+*/
+static void program_overscan(
+		struct dce110_transform *xfm110,
+		const struct overscan_info *overscan)
+{
+	uint32_t overscan_left_right = 0;
+	uint32_t overscan_top_bottom = 0;
+
+	set_reg_field_value(overscan_left_right, overscan->left,
+			EXT_OVERSCAN_LEFT_RIGHT, EXT_OVERSCAN_LEFT);
+
+	set_reg_field_value(overscan_left_right, overscan->right,
+			EXT_OVERSCAN_LEFT_RIGHT, EXT_OVERSCAN_RIGHT);
+
+	set_reg_field_value(overscan_top_bottom, overscan->top,
+			EXT_OVERSCAN_TOP_BOTTOM, EXT_OVERSCAN_TOP);
+
+	set_reg_field_value(overscan_top_bottom, overscan->bottom,
+			EXT_OVERSCAN_TOP_BOTTOM, EXT_OVERSCAN_BOTTOM);
+
+	dm_write_reg(xfm110->base.ctx,
+			SCL_REG(mmEXT_OVERSCAN_LEFT_RIGHT),
+			overscan_left_right);
+
+	dm_write_reg(xfm110->base.ctx,
+			SCL_REG(mmEXT_OVERSCAN_TOP_BOTTOM),
+			overscan_top_bottom);
+}
+
+static void program_two_taps_filter(
+	struct dce110_transform *xfm110,
+	bool enable,
+	bool vertical)
+{
+	uint32_t addr;
+	uint32_t value;
+	/* 1: Hard coded 2 tap filter
+	 * 0: Programmable 2 tap filter from coefficient RAM
+	 */
+	if (vertical) {
+		addr = SCL_REG(mmSCL_VERT_FILTER_CONTROL);
+		value = dm_read_reg(xfm110->base.ctx, addr);
+		set_reg_field_value(
+			value,
+			enable ? 1 : 0,
+				SCL_VERT_FILTER_CONTROL,
+				SCL_V_2TAP_HARDCODE_COEF_EN);
+
+	} else {
+		addr = SCL_REG(mmSCL_HORZ_FILTER_CONTROL);
+		value = dm_read_reg(xfm110->base.ctx, addr);
+		set_reg_field_value(
+			value,
+			enable ? 1 : 0,
+			SCL_HORZ_FILTER_CONTROL,
+			SCL_H_2TAP_HARDCODE_COEF_EN);
+	}
+
+	dm_write_reg(xfm110->base.ctx, addr, value);
+}
+
+static void set_coeff_update_complete(struct dce110_transform *xfm110)
+{
+	uint32_t value;
+	uint32_t addr = SCL_REG(mmSCL_UPDATE);
+
+	value = dm_read_reg(xfm110->base.ctx, addr);
+	set_reg_field_value(value, 1,
+			SCL_UPDATE, SCL_COEF_UPDATE_COMPLETE);
+	dm_write_reg(xfm110->base.ctx, addr, value);
+}
+
+static void program_filter(
+	struct dce110_transform *xfm110,
+	enum ram_filter_type filter_type,
+	struct scaler_filter_params *scl_filter_params,
+	uint32_t *coeffs,
+	uint32_t coeffs_num)
+{
+	uint32_t phase = 0;
+	uint32_t array_idx = 0;
+	uint32_t pair = 0;
+
+	uint32_t taps_pairs = (scl_filter_params->taps + 1) / 2;
+	uint32_t phases_to_program = scl_filter_params->phases / 2 + 1;
+
+	uint32_t i;
+	uint32_t addr;
+	uint32_t select_addr;
+	uint32_t select;
+	uint32_t data;
+	/* We need to disable power gating on coeff memory to do programming */
+
+	uint32_t pwr_ctrl_orig;
+	uint32_t pwr_ctrl_off;
+
+	addr = DCFE_REG(mmDCFE_MEM_PWR_CTRL);
+	pwr_ctrl_orig = dm_read_reg(xfm110->base.ctx, addr);
+	pwr_ctrl_off = pwr_ctrl_orig;
+	set_reg_field_value(
+		pwr_ctrl_off,
+		1,
+		DCFE_MEM_PWR_CTRL,
+		SCL_COEFF_MEM_PWR_DIS);
+	dm_write_reg(xfm110->base.ctx, addr, pwr_ctrl_off);
+
+	addr = DCFE_REG(mmDCFE_MEM_PWR_STATUS);
+	/* Wait to disable gating: */
+	for (i = 0;
+		i < 10 &&
+		get_reg_field_value(
+			dm_read_reg(xfm110->base.ctx, addr),
+			DCFE_MEM_PWR_STATUS,
+			SCL_COEFF_MEM_PWR_STATE);
+		i++)
+		dm_delay_in_microseconds(xfm110->base.ctx, 1);
+
+	ASSERT(i < 10);
+
+	select_addr = SCL_REG(mmSCL_COEF_RAM_SELECT);
+	select = dm_read_reg(xfm110->base.ctx, select_addr);
+
+	set_reg_field_value(
+		select,
+		filter_type,
+		SCL_COEF_RAM_SELECT,
+		SCL_C_RAM_FILTER_TYPE);
+	set_reg_field_value(
+		select,
+		0,
+		SCL_COEF_RAM_SELECT,
+		SCL_C_RAM_TAP_PAIR_IDX);
+	set_reg_field_value(
+		select,
+		0,
+		SCL_COEF_RAM_SELECT,
+		SCL_C_RAM_PHASE);
+
+	data = 0;
+
+	for (phase = 0; phase < phases_to_program; phase++) {
+		/* we always program N/2 + 1 phases, total phases N, but N/2-1
+		 * are just mirror phase 0 is unique and phase N/2 is unique
+		 * if N is even
+		 */
+
+		set_reg_field_value(
+			select,
+			phase,
+			SCL_COEF_RAM_SELECT,
+			SCL_C_RAM_PHASE);
+
+		for (pair = 0; pair < taps_pairs; pair++) {
+			set_reg_field_value(
+				select,
+				pair,
+				SCL_COEF_RAM_SELECT,
+				SCL_C_RAM_TAP_PAIR_IDX);
+			dm_write_reg(xfm110->base.ctx, select_addr, select);
+
+			/* even tap write enable */
+			set_reg_field_value(
+				data,
+				1,
+				SCL_COEF_RAM_TAP_DATA,
+				SCL_C_RAM_EVEN_TAP_COEF_EN);
+			/* even tap data */
+			set_reg_field_value(
+				data,
+				coeffs[array_idx],
+				SCL_COEF_RAM_TAP_DATA,
+				SCL_C_RAM_EVEN_TAP_COEF);
+
+			/* if we have odd number of taps and the last pair is
+			 * here then we do not need to program
+			 */
+			if (scl_filter_params->taps % 2 &&
+				pair == taps_pairs - 1) {
+				/* odd tap write disable */
+				set_reg_field_value(
+					data,
+					0,
+					SCL_COEF_RAM_TAP_DATA,
+					SCL_C_RAM_ODD_TAP_COEF_EN);
+				set_reg_field_value(
+					data,
+					0,
+					SCL_COEF_RAM_TAP_DATA,
+					SCL_C_RAM_ODD_TAP_COEF);
+				array_idx += 1;
+			} else {
+				/* odd tap write enable */
+				set_reg_field_value(
+					data,
+					1,
+					SCL_COEF_RAM_TAP_DATA,
+					SCL_C_RAM_ODD_TAP_COEF_EN);
+				/* dbg_val: 0x1000 / sclFilterParams->taps; */
+				set_reg_field_value(
+					data,
+					coeffs[array_idx + 1],
+					SCL_COEF_RAM_TAP_DATA,
+					SCL_C_RAM_ODD_TAP_COEF);
+
+				array_idx += 2;
+			}
+
+			dm_write_reg(
+				xfm110->base.ctx,
+				SCL_REG(mmSCL_COEF_RAM_TAP_DATA),
+				data);
+		}
+	}
+
+	ASSERT(coeffs_num == array_idx);
+
+	/* reset the power gating register */
+	dm_write_reg(
+		xfm110->base.ctx,
+		DCFE_REG(mmDCFE_MEM_PWR_CTRL),
+		pwr_ctrl_orig);
+
+	set_coeff_update_complete(xfm110);
+}
+
+/*
+ *
+ * Populates an array with filter coefficients in 1.1.12 fixed point form
+*/
+static bool get_filter_coefficients(
+	struct dce110_transform *xfm110,
+	uint32_t taps,
+	uint32_t **data_tab,
+	uint32_t *data_size)
+{
+	uint32_t num = 0;
+	uint32_t i;
+	const struct fixed31_32 *filter =
+		dal_scaler_filter_get(
+			xfm110->base.filter,
+			data_tab,
+			&num);
+	uint32_t *data_row;
+
+	if (!filter) {
+		BREAK_TO_DEBUGGER();
+		return false;
+	}
+	data_row = *data_tab;
+
+	for (i = 0; i < num; ++i) {
+		/* req. format sign fixed 1.1.12, the values are always between
+		 * [-1; 1]
+		 *
+		 * Each phase is mirrored as follows :
+		 * 0 : Phase 0
+		 * 1 : Phase 1 or Phase 64 - 1 / 128 - 1
+		 * N : Phase N or Phase 64 - N / 128 - N
+		 *
+		 * Convert from Fixed31_32 to 1.1.12 by using floor on value
+		 * shifted by number of required fractional bits(12)
+		 */
+		struct fixed31_32 value = filter[i];
+
+		data_row[i] =
+			dal_fixed31_32_floor(dal_fixed31_32_shl(value, 12)) &
+			0x3FFC;
+	}
+	*data_size = num;
+
+	return true;
+}
+
+static bool program_multi_taps_filter(
+	struct dce110_transform *xfm110,
+	const struct scaler_data *data,
+	bool horizontal)
+{
+	struct scaler_filter_params filter_params;
+	enum ram_filter_type filter_type;
+	uint32_t src_size;
+	uint32_t dst_size;
+
+	uint32_t *filter_data = NULL;
+	uint32_t filter_data_size = 0;
+
+	/* 16 phases total for DCE11 */
+	filter_params.phases = 16;
+
+	if (horizontal) {
+		filter_params.taps = data->taps.h_taps;
+		filter_params.sharpness = data->h_sharpness;
+		filter_params.flags.bits.HORIZONTAL = 1;
+
+		src_size = data->viewport.width;
+		dst_size =
+			dal_fixed31_32_floor(
+				dal_fixed31_32_div(
+					dal_fixed31_32_from_int(
+						data->viewport.width),
+					data->ratios->horz));
+
+		filter_type = FILTER_TYPE_RGB_Y_HORIZONTAL;
+	} else {
+		filter_params.taps = data->taps.v_taps;
+		filter_params.sharpness = data->v_sharpness;
+		filter_params.flags.bits.HORIZONTAL = 0;
+
+		src_size = data->viewport.height;
+		dst_size =
+			dal_fixed31_32_floor(
+				dal_fixed31_32_div(
+					dal_fixed31_32_from_int(
+						data->viewport.height),
+					data->ratios->vert));
+
+		filter_type = FILTER_TYPE_RGB_Y_VERTICAL;
+	}
+
+	/* 1. Generate the coefficients */
+	if (!dal_scaler_filter_generate(
+		xfm110->base.filter,
+		&filter_params,
+		src_size,
+		dst_size))
+		return false;
+
+	/* 2. Convert coefficients to fixed point format 1.12 (note coeff.
+	 * could be negative(!) and  range is [ from -1 to 1 ]) */
+	if (!get_filter_coefficients(
+		xfm110,
+		filter_params.taps,
+		&filter_data,
+		&filter_data_size))
+		return false;
+
+	/* 3. Program the filter */
+	program_filter(
+		xfm110,
+		filter_type,
+		&filter_params,
+		filter_data,
+		filter_data_size);
+
+	/* 4. Program the alpha if necessary */
+	if (data->flags.bits.SHOULD_PROGRAM_ALPHA) {
+		if (horizontal)
+			filter_type = FILTER_TYPE_ALPHA_HORIZONTAL;
+		else
+			filter_type = FILTER_TYPE_ALPHA_VERTICAL;
+
+		program_filter(
+			xfm110,
+			filter_type,
+			&filter_params,
+			filter_data,
+			filter_data_size);
+	}
+
+	return true;
+}
+
+static void program_viewport(
+	struct dce110_transform *xfm110,
+	const struct rect *view_port)
+{
+	struct dc_context *ctx = xfm110->base.ctx;
+	uint32_t value = 0;
+	uint32_t addr = 0;
+
+	addr = SCL_REG(mmVIEWPORT_START);
+	value = dm_read_reg(ctx, addr);
+	set_reg_field_value(
+		value,
+		view_port->x,
+		VIEWPORT_START,
+		VIEWPORT_X_START);
+	set_reg_field_value(
+		value,
+		view_port->y,
+		VIEWPORT_START,
+		VIEWPORT_Y_START);
+	dm_write_reg(ctx, addr, value);
+
+	addr = SCL_REG(mmVIEWPORT_SIZE);
+	value = dm_read_reg(ctx, addr);
+	set_reg_field_value(
+		value,
+		view_port->height,
+		VIEWPORT_SIZE,
+		VIEWPORT_HEIGHT);
+	set_reg_field_value(
+		value,
+		view_port->width,
+		VIEWPORT_SIZE,
+		VIEWPORT_WIDTH);
+	dm_write_reg(ctx, addr, value);
+
+	/* TODO: add stereo support */
+}
+
+static void calculate_inits(
+	struct dce110_transform *xfm110,
+	const struct scaler_data *data,
+	struct scl_ratios_inits *inits)
+{
+	struct fixed31_32 h_init;
+	struct fixed31_32 v_init;
+	struct fixed31_32 v_init_bot;
+
+	inits->bottom_enable = 0;
+	inits->h_int_scale_ratio =
+		dal_fixed31_32_u2d19(data->ratios->horz) << 5;
+	inits->v_int_scale_ratio =
+		dal_fixed31_32_u2d19(data->ratios->vert) << 5;
+
+	h_init =
+		dal_fixed31_32_div_int(
+			dal_fixed31_32_add(
+				data->ratios->horz,
+				dal_fixed31_32_from_int(data->taps.h_taps + 1)),
+				2);
+	inits->h_init.integer = dal_fixed31_32_floor(h_init);
+	inits->h_init.fraction = dal_fixed31_32_u0d19(h_init) << 5;
+
+	v_init =
+		dal_fixed31_32_div_int(
+			dal_fixed31_32_add(
+				data->ratios->vert,
+				dal_fixed31_32_from_int(data->taps.v_taps + 1)),
+				2);
+	inits->v_init.integer = dal_fixed31_32_floor(v_init);
+	inits->v_init.fraction = dal_fixed31_32_u0d19(v_init) << 5;
+
+	if (data->flags.bits.INTERLACED) {
+		v_init_bot =
+			dal_fixed31_32_add(
+				dal_fixed31_32_div_int(
+					dal_fixed31_32_add(
+						data->ratios->vert,
+						dal_fixed31_32_from_int(
+							data->taps.v_taps + 1)),
+					2),
+				data->ratios->vert);
+		inits->v_init_bottom.integer = dal_fixed31_32_floor(v_init_bot);
+		inits->v_init_bottom.fraction =
+			dal_fixed31_32_u0d19(v_init_bot) << 5;
+
+		inits->bottom_enable = 1;
+	}
+}
+
+static void program_scl_ratios_inits(
+	struct dce110_transform *xfm110,
+	struct scl_ratios_inits *inits)
+{
+	uint32_t addr = SCL_REG(mmSCL_HORZ_FILTER_SCALE_RATIO);
+	uint32_t value = 0;
+
+	set_reg_field_value(
+		value,
+		inits->h_int_scale_ratio,
+		SCL_HORZ_FILTER_SCALE_RATIO,
+		SCL_H_SCALE_RATIO);
+	dm_write_reg(xfm110->base.ctx, addr, value);
+
+	addr = SCL_REG(mmSCL_VERT_FILTER_SCALE_RATIO);
+	value = 0;
+	set_reg_field_value(
+		value,
+		inits->v_int_scale_ratio,
+		SCL_VERT_FILTER_SCALE_RATIO,
+		SCL_V_SCALE_RATIO);
+	dm_write_reg(xfm110->base.ctx, addr, value);
+
+	addr = SCL_REG(mmSCL_HORZ_FILTER_INIT);
+	value = 0;
+	set_reg_field_value(
+		value,
+		inits->h_init.integer,
+		SCL_HORZ_FILTER_INIT,
+		SCL_H_INIT_INT);
+	set_reg_field_value(
+		value,
+		inits->h_init.fraction,
+		SCL_HORZ_FILTER_INIT,
+		SCL_H_INIT_FRAC);
+	dm_write_reg(xfm110->base.ctx, addr, value);
+
+	addr = SCL_REG(mmSCL_VERT_FILTER_INIT);
+	value = 0;
+	set_reg_field_value(
+		value,
+		inits->v_init.integer,
+		SCL_VERT_FILTER_INIT,
+		SCL_V_INIT_INT);
+	set_reg_field_value(
+		value,
+		inits->v_init.fraction,
+		SCL_VERT_FILTER_INIT,
+		SCL_V_INIT_FRAC);
+	dm_write_reg(xfm110->base.ctx, addr, value);
+
+	if (inits->bottom_enable) {
+		addr = SCL_REG(mmSCL_VERT_FILTER_INIT_BOT);
+		value = 0;
+		set_reg_field_value(
+			value,
+			inits->v_init_bottom.integer,
+			SCL_VERT_FILTER_INIT_BOT,
+			SCL_V_INIT_INT_BOT);
+		set_reg_field_value(
+			value,
+			inits->v_init_bottom.fraction,
+			SCL_VERT_FILTER_INIT_BOT,
+			SCL_V_INIT_FRAC_BOT);
+		dm_write_reg(xfm110->base.ctx, addr, value);
+	}
+
+	addr = SCL_REG(mmSCL_AUTOMATIC_MODE_CONTROL);
+	value = 0;
+	set_reg_field_value(
+		value,
+		0,
+		SCL_AUTOMATIC_MODE_CONTROL,
+		SCL_V_CALC_AUTO_RATIO_EN);
+	set_reg_field_value(
+		value,
+		0,
+		SCL_AUTOMATIC_MODE_CONTROL,
+		SCL_H_CALC_AUTO_RATIO_EN);
+	dm_write_reg(xfm110->base.ctx, addr, value);
+}
+
+static void get_viewport(
+		struct dce110_transform *xfm110,
+		struct rect *current_view_port)
+{
+	uint32_t value_start;
+	uint32_t value_size;
+
+	if (current_view_port == NULL)
+		return;
+
+	value_start = dm_read_reg(xfm110->base.ctx, SCL_REG(mmVIEWPORT_START));
+	value_size = dm_read_reg(xfm110->base.ctx, SCL_REG(mmVIEWPORT_SIZE));
+
+	current_view_port->x = get_reg_field_value(
+			value_start,
+			VIEWPORT_START,
+			VIEWPORT_X_START);
+	current_view_port->y = get_reg_field_value(
+			value_start,
+			VIEWPORT_START,
+			VIEWPORT_Y_START);
+	current_view_port->height = get_reg_field_value(
+			value_size,
+			VIEWPORT_SIZE,
+			VIEWPORT_HEIGHT);
+	current_view_port->width = get_reg_field_value(
+			value_size,
+			VIEWPORT_SIZE,
+			VIEWPORT_WIDTH);
+}
+
+
+bool dce110_transform_set_scaler(
+	struct transform *xfm,
+	const struct scaler_data *data)
+{
+	struct dce110_transform *xfm110 = TO_DCE110_TRANSFORM(xfm);
+	bool is_scaling_required;
+	struct dc_context *ctx = xfm->ctx;
+
+	{
+		uint32_t addr = SCL_REG(mmSCL_BYPASS_CONTROL);
+		uint32_t value = dm_read_reg(xfm->ctx, addr);
+
+		set_reg_field_value(
+			value,
+			0,
+			SCL_BYPASS_CONTROL,
+			SCL_BYPASS_MODE);
+		dm_write_reg(xfm->ctx, addr, value);
+	}
+
+	disable_enhanced_sharpness(xfm110);
+
+	/* 3. Program overscan */
+	program_overscan(xfm110, &data->overscan);
+
+	/* 4. Program taps and configuration */
+	is_scaling_required = setup_scaling_configuration(xfm110, data);
+	if (is_scaling_required) {
+		/* 5. Calculate and program ratio, filter initialization */
+		struct scl_ratios_inits inits = { 0 };
+
+		calculate_inits(xfm110, data, &inits);
+
+		program_scl_ratios_inits(xfm110, &inits);
+
+		/* 6. Program vertical filters */
+		if (data->taps.v_taps > 2) {
+			program_two_taps_filter(xfm110, false, true);
+
+			if (!program_multi_taps_filter(xfm110, data, false)) {
+				dal_logger_write(ctx->logger,
+					LOG_MAJOR_DCP,
+					LOG_MINOR_DCP_SCALER,
+					"Failed vertical taps programming\n");
+				return false;
+			}
+		} else
+			program_two_taps_filter(xfm110, true, true);
+
+		/* 7. Program horizontal filters */
+		if (data->taps.h_taps > 2) {
+			program_two_taps_filter(xfm110, false, false);
+
+			if (!program_multi_taps_filter(xfm110, data, true)) {
+				dal_logger_write(ctx->logger,
+					LOG_MAJOR_DCP,
+					LOG_MINOR_DCP_SCALER,
+					"Failed horizontal taps programming\n");
+				return false;
+			}
+		} else
+			program_two_taps_filter(xfm110, true, false);
+	}
+
+	return true;
+}
+
+void dce110_transform_set_scaler_bypass(struct transform *xfm)
+{
+	struct dce110_transform *xfm110 = TO_DCE110_TRANSFORM(xfm);
+	uint32_t sclv_mode;
+
+	disable_enhanced_sharpness(xfm110);
+
+	sclv_mode = dm_read_reg(xfm->ctx, SCL_REG(mmSCL_MODE));
+	set_reg_field_value(sclv_mode, 0, SCL_MODE, SCL_MODE);
+	set_reg_field_value(sclv_mode, 0, SCL_MODE, SCL_PSCL_EN);
+	dm_write_reg(xfm->ctx, SCL_REG(mmSCL_MODE), sclv_mode);
+}
+
+bool dce110_transform_update_viewport(
+	struct transform *xfm,
+	const struct rect *view_port,
+	bool is_fbc_attached)
+{
+	struct dce110_transform *xfm110 = TO_DCE110_TRANSFORM(xfm);
+	bool program_req = false;
+	struct rect current_view_port;
+
+	if (view_port == NULL)
+		return program_req;
+
+	get_viewport(xfm110, &current_view_port);
+
+	if (current_view_port.x != view_port->x ||
+			current_view_port.y != view_port->y ||
+			current_view_port.height != view_port->height ||
+			current_view_port.width != view_port->width)
+		program_req = true;
+
+	if (program_req) {
+		/*underlay viewport is programmed with scaler
+		 *program_viewport function pointer is not exposed*/
+		program_viewport(xfm110, view_port);
+	}
+
+	return program_req;
+}
+
+void dce110_transform_set_scaler_filter(
+	struct transform *xfm,
+	struct scaler_filter *filter)
+{
+	xfm->filter = filter;
+}
+
diff --git a/drivers/gpu/drm/amd/dal/dc/dce110/dce110_transform_sclv.c b/drivers/gpu/drm/amd/dal/dc/dce110/dce110_transform_sclv.c
new file mode 100644
index 000000000000..1968296bd596
--- /dev/null
+++ b/drivers/gpu/drm/amd/dal/dc/dce110/dce110_transform_sclv.c
@@ -0,0 +1,531 @@
+/* Copyright 2012-15 Advanced Micro Devices, Inc.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
+ * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ *
+ * Authors: AMD
+ *
+ */
+
+#include "dm_services.h"
+
+#include "dce/dce_11_0_d.h"
+#include "dce/dce_11_0_sh_mask.h"
+
+#include "dce110_transform.h"
+
+#define NOT_IMPLEMENTED()  DAL_LOGGER_NOT_IMPL(LOG_MINOR_COMPONENT_CONTROLLER,\
+			"TRANSFORM SCALER:%s()\n", __func__)
+
+/*
+*****************************************************************************
+*  Function: calculateViewport
+*
+*  @brief
+*     Calculates all of the data required to set the viewport
+*
+*  @param [in]  pData:      scaler settings data
+*  @param [out] pLumaVp:    luma viewport information
+*  @param [out] pChromaVp:  chroma viewport information
+*  @param [out] srcResCx2:  source chroma resolution times 2  - for multi-taps
+*
+*****************************************************************************
+*/
+static void calculate_viewport(
+		const struct scaler_data *scl_data,
+		struct rect *luma_viewport,
+		struct rect *chroma_viewport)
+{
+	/*Do not set chroma vp for rgb444 pixel format*/
+	luma_viewport->x = scl_data->viewport.x - scl_data->viewport.x % 2;
+	luma_viewport->y = scl_data->viewport.y - scl_data->viewport.y % 2;
+	luma_viewport->width =
+		scl_data->viewport.width - scl_data->viewport.width % 2;
+	luma_viewport->height =
+		scl_data->viewport.height - scl_data->viewport.height % 2;
+
+
+	if (scl_data->dal_pixel_format == PIXEL_FORMAT_422BPP16) {
+		luma_viewport->width += luma_viewport->width % 2;
+
+		chroma_viewport->x = luma_viewport->x / 2;
+		chroma_viewport->width = luma_viewport->width / 2;
+	} else if (scl_data->dal_pixel_format == PIXEL_FORMAT_420BPP12) {
+		luma_viewport->height += luma_viewport->height % 2;
+		luma_viewport->width += luma_viewport->width % 2;
+		/*for 420 video chroma is 1/4 the area of luma, scaled
+		 *vertically and horizontally
+		 */
+		chroma_viewport->x = luma_viewport->x / 2;
+		chroma_viewport->y = luma_viewport->y / 2;
+		chroma_viewport->height = luma_viewport->height / 2;
+		chroma_viewport->width = luma_viewport->width / 2;
+	}
+}
+
+
+static void program_viewport(
+	struct dce110_transform *xfm110,
+	struct rect *luma_view_port,
+	struct rect *chroma_view_port)
+{
+	struct dc_context *ctx = xfm110->base.ctx;
+	uint32_t value = 0;
+	uint32_t addr = 0;
+
+	if (luma_view_port->width != 0 && luma_view_port->height != 0) {
+		addr = mmSCLV_VIEWPORT_START;
+		value = 0;
+		set_reg_field_value(
+			value,
+			luma_view_port->x,
+			SCLV_VIEWPORT_START,
+			VIEWPORT_X_START);
+		set_reg_field_value(
+			value,
+			luma_view_port->y,
+			SCLV_VIEWPORT_START,
+			VIEWPORT_Y_START);
+		dm_write_reg(ctx, addr, value);
+
+		addr = mmSCLV_VIEWPORT_SIZE;
+		value = 0;
+		set_reg_field_value(
+			value,
+			luma_view_port->height,
+			SCLV_VIEWPORT_SIZE,
+			VIEWPORT_HEIGHT);
+		set_reg_field_value(
+			value,
+			luma_view_port->width,
+			SCLV_VIEWPORT_SIZE,
+			VIEWPORT_WIDTH);
+		dm_write_reg(ctx, addr, value);
+	}
+
+	if (chroma_view_port->width != 0 && chroma_view_port->height != 0) {
+		addr = mmSCLV_VIEWPORT_START_C;
+		value = 0;
+		set_reg_field_value(
+			value,
+			chroma_view_port->x,
+			SCLV_VIEWPORT_START_C,
+			VIEWPORT_X_START_C);
+		set_reg_field_value(
+			value,
+			chroma_view_port->y,
+			SCLV_VIEWPORT_START_C,
+			VIEWPORT_Y_START_C);
+		dm_write_reg(ctx, addr, value);
+
+		addr = mmSCLV_VIEWPORT_SIZE_C;
+		value = 0;
+		set_reg_field_value(
+			value,
+			chroma_view_port->height,
+			SCLV_VIEWPORT_SIZE_C,
+			VIEWPORT_HEIGHT_C);
+		set_reg_field_value(
+			value,
+			chroma_view_port->width,
+			SCLV_VIEWPORT_SIZE_C,
+			VIEWPORT_WIDTH_C);
+		dm_write_reg(ctx, addr, value);
+	}
+	/* TODO: add stereo support */
+}
+
+
+/* Until and For MPO video play story, to reduce time for implementation,
+ * below limits are applied for now: 2_TAPS only
+ * Use auto-calculated filter values
+ * Following routines will be empty for now:
+ *
+ * programSclRatiosInits -- calcualate scaler ratio manually
+ * calculateInits --- calcualate scaler ratio manually
+ * programFilter -- multi-taps
+ * GetOptimalNumberOfTaps -- will hard coded to 2 TAPS
+ * GetNextLowerNumberOfTaps -- will hard coded to 2TAPS
+ * validateRequestedScaleRatio - used by GetOptimalNumberOfTaps internally
+ */
+
+/**
+* Function:
+* void setup_scaling_configuration
+*
+* Purpose: setup scaling mode : bypass, RGb, YCbCr and nummber of taps
+* Input:   data
+*
+* Output:
+   void
+*/
+static bool setup_scaling_configuration(
+	struct dce110_transform *xfm110,
+	const struct scaler_data *data)
+{
+	bool is_scaling_needed = false;
+	struct dc_context *ctx = xfm110->base.ctx;
+	uint32_t value = 0;
+
+	if (data->taps.h_taps + data->taps.v_taps > 2) {
+		set_reg_field_value(value, 1, SCLV_MODE, SCL_MODE);
+		set_reg_field_value(value, 1, SCLV_MODE, SCL_PSCL_EN);
+		is_scaling_needed = true;
+	} else {
+		set_reg_field_value(value, 0, SCLV_MODE, SCL_MODE);
+		set_reg_field_value(value, 0, SCLV_MODE, SCL_PSCL_EN);
+	}
+
+	if (data->taps.h_taps_c + data->taps.v_taps_c > 2) {
+		set_reg_field_value(value, 1, SCLV_MODE, SCL_MODE_C);
+		set_reg_field_value(value, 1, SCLV_MODE, SCL_PSCL_EN_C);
+		is_scaling_needed = true;
+	} else if (data->dal_pixel_format != PIXEL_FORMAT_420BPP12 &&
+		data->dal_pixel_format != PIXEL_FORMAT_422BPP16) {
+		set_reg_field_value(
+			value,
+			get_reg_field_value(value, SCLV_MODE, SCL_MODE),
+			SCLV_MODE,
+			SCL_MODE_C);
+		set_reg_field_value(
+			value,
+			get_reg_field_value(value, SCLV_MODE, SCL_PSCL_EN),
+			SCLV_MODE,
+			SCL_PSCL_EN_C);
+	} else {
+		set_reg_field_value(value, 0, SCLV_MODE, SCL_MODE_C);
+		set_reg_field_value(value, 0, SCLV_MODE, SCL_PSCL_EN_C);
+	}
+	dm_write_reg(ctx, mmSCLV_MODE, value);
+
+	{
+		value = dm_read_reg(ctx, mmSCLV_TAP_CONTROL);
+
+		set_reg_field_value(value, data->taps.h_taps - 1,
+				SCLV_TAP_CONTROL, SCL_H_NUM_OF_TAPS);
+
+		set_reg_field_value(value, data->taps.v_taps - 1,
+				SCLV_TAP_CONTROL, SCL_V_NUM_OF_TAPS);
+
+		set_reg_field_value(value, data->taps.h_taps_c - 1,
+				SCLV_TAP_CONTROL, SCL_H_NUM_OF_TAPS_C);
+
+		set_reg_field_value(value, data->taps.v_taps_c - 1,
+				SCLV_TAP_CONTROL, SCL_V_NUM_OF_TAPS_C);
+
+		dm_write_reg(ctx, mmSCLV_TAP_CONTROL, value);
+	}
+
+	{
+		/* we can ignore this register because we are ok with hw
+		 * default 0 -- change to 1 according to dal2 code*/
+		value = dm_read_reg(ctx, mmSCLV_CONTROL);
+		 /* 0 - Replaced out of bound pixels with black pixel
+		  * (or any other required color) */
+		set_reg_field_value(value, 1, SCLV_CONTROL, SCL_BOUNDARY_MODE);
+
+		/* 1 - Replaced out of bound pixels with the edge pixel. */
+		dm_write_reg(ctx, mmSCLV_CONTROL, value);
+	}
+
+	return is_scaling_needed;
+}
+
+/**
+* Function:
+* void program_overscan
+*
+* Purpose: Programs overscan border
+* Input:   overscan
+*
+* Output:
+   void
+*/
+static void program_overscan(
+		struct dce110_transform *xfm110,
+		const struct overscan_info *overscan)
+{
+	uint32_t overscan_left_right = 0;
+	uint32_t overscan_top_bottom = 0;
+
+	set_reg_field_value(overscan_left_right, overscan->left,
+		SCLV_EXT_OVERSCAN_LEFT_RIGHT, EXT_OVERSCAN_LEFT);
+
+	set_reg_field_value(overscan_left_right, overscan->right,
+		SCLV_EXT_OVERSCAN_LEFT_RIGHT, EXT_OVERSCAN_RIGHT);
+
+	set_reg_field_value(overscan_top_bottom, overscan->top,
+		SCLV_EXT_OVERSCAN_TOP_BOTTOM, EXT_OVERSCAN_TOP);
+
+	set_reg_field_value(overscan_top_bottom, overscan->bottom,
+		SCLV_EXT_OVERSCAN_TOP_BOTTOM, EXT_OVERSCAN_BOTTOM);
+
+	dm_write_reg(xfm110->base.ctx,
+			mmSCLV_EXT_OVERSCAN_LEFT_RIGHT,
+			overscan_left_right);
+
+	dm_write_reg(xfm110->base.ctx,
+			mmSCLV_EXT_OVERSCAN_TOP_BOTTOM,
+			overscan_top_bottom);
+}
+/*
+static void setup_auto_scaling(struct dce110_transform *xfm110)
+{
+	uint32_t value = 0;
+	set_reg_field_value(value, 1, SCLV_AUTOMATIC_MODE_CONTROL,
+			SCL_V_CALC_AUTO_RATIO_EN);
+	set_reg_field_value(value, 1, SCLV_AUTOMATIC_MODE_CONTROL,
+			SCL_H_CALC_AUTO_RATIO_EN);
+	dal_write_reg(xfm->ctx,
+			xfm->regs[IDX_SCL_AUTOMATIC_MODE_CONTROL],
+			value);
+}
+*/
+
+static void program_two_taps_filter_horz(
+	struct dce110_transform *xfm110,
+	bool hardcode_coff)
+{
+	uint32_t value = 0;
+
+	if (hardcode_coff)
+		set_reg_field_value(
+				value,
+				1,
+				SCLV_HORZ_FILTER_CONTROL,
+				SCL_H_2TAP_HARDCODE_COEF_EN);
+
+	dm_write_reg(xfm110->base.ctx,
+			mmSCLV_HORZ_FILTER_CONTROL,
+			value);
+}
+
+static void program_two_taps_filter_vert(
+	struct dce110_transform *xfm110,
+	bool hardcode_coff)
+{
+	uint32_t value = 0;
+
+	if (hardcode_coff)
+		set_reg_field_value(value, 1, SCLV_VERT_FILTER_CONTROL,
+				SCL_V_2TAP_HARDCODE_COEF_EN);
+
+	dm_write_reg(xfm110->base.ctx,
+			mmSCLV_VERT_FILTER_CONTROL,
+			value);
+}
+
+static void set_coeff_update_complete(
+		struct dce110_transform *xfm110)
+{
+	/*TODO: Until now, only scaler bypass, up-scaler 2 -TAPS coeff auto
+	 * calculation are implemented. Coefficient RAM is not used
+	 * Do not check this flag yet
+	 */
+
+	/*uint32_t value;
+	uint32_t addr = xfm->regs[IDX_SCL_UPDATE];
+
+	value = dal_read_reg(xfm->ctx, addr);
+	set_reg_field_value(value, 0,
+			SCL_UPDATE, SCL_COEF_UPDATE_COMPLETE);
+	dal_write_reg(xfm->ctx, addr, value);*/
+}
+
+static bool program_multi_taps_filter(
+	struct dce110_transform *xfm110,
+	const struct scaler_data *data,
+	bool horizontal)
+{
+	struct dc_context *ctx = xfm110->base.ctx;
+
+	NOT_IMPLEMENTED();
+	return false;
+}
+
+static void calculate_inits(
+	struct dce110_transform *xfm110,
+	const struct scaler_data *data,
+	struct sclv_ratios_inits *inits,
+	struct rect *luma_viewport,
+	struct rect *chroma_viewport)
+{
+	if (data->dal_pixel_format == PIXEL_FORMAT_420BPP12 ||
+		data->dal_pixel_format == PIXEL_FORMAT_422BPP16)
+		inits->chroma_enable = true;
+
+	/* TODO: implement rest of this function properly */
+	if (inits->chroma_enable) {
+		inits->h_int_scale_ratio_luma = 0x1000000;
+		inits->v_int_scale_ratio_luma = 0x1000000;
+		inits->h_int_scale_ratio_chroma = 0x800000;
+		inits->v_int_scale_ratio_chroma = 0x800000;
+	}
+}
+
+static void program_scl_ratios_inits(
+	struct dce110_transform *xfm110,
+	struct sclv_ratios_inits *inits)
+{
+	struct dc_context *ctx = xfm110->base.ctx;
+	uint32_t addr = mmSCLV_HORZ_FILTER_SCALE_RATIO;
+	uint32_t value = dm_read_reg(ctx, addr);
+
+	set_reg_field_value(
+		value,
+		inits->h_int_scale_ratio_luma,
+		SCLV_HORZ_FILTER_SCALE_RATIO,
+		SCL_H_SCALE_RATIO);
+	dm_write_reg(ctx, addr, value);
+
+	addr = mmSCLV_VERT_FILTER_SCALE_RATIO;
+	value = dm_read_reg(ctx, addr);
+	set_reg_field_value(
+		value,
+		inits->v_int_scale_ratio_luma,
+		SCLV_VERT_FILTER_SCALE_RATIO,
+		SCL_V_SCALE_RATIO);
+	dm_write_reg(ctx, addr, value);
+
+	addr = mmSCLV_HORZ_FILTER_SCALE_RATIO_C;
+	value = dm_read_reg(ctx, addr);
+	set_reg_field_value(
+		value,
+		inits->h_int_scale_ratio_chroma,
+		SCLV_HORZ_FILTER_SCALE_RATIO_C,
+		SCL_H_SCALE_RATIO_C);
+	dm_write_reg(ctx, addr, value);
+
+	addr = mmSCLV_VERT_FILTER_SCALE_RATIO_C;
+	value = dm_read_reg(ctx, addr);
+	set_reg_field_value(
+		value,
+		inits->v_int_scale_ratio_chroma,
+		SCLV_VERT_FILTER_SCALE_RATIO_C,
+		SCL_V_SCALE_RATIO_C);
+	dm_write_reg(ctx, addr, value);
+}
+
+void dce110_transform_underlay_set_scalerv_bypass(struct transform *xfm)
+{
+	uint32_t addr = mmSCLV_MODE;
+	uint32_t value = dm_read_reg(xfm->ctx, addr);
+
+	set_reg_field_value(value, 0, SCLV_MODE, SCL_MODE);
+	set_reg_field_value(value, 0, SCLV_MODE, SCL_MODE_C);
+	set_reg_field_value(value, 0, SCLV_MODE, SCL_PSCL_EN);
+	set_reg_field_value(value, 0, SCLV_MODE, SCL_PSCL_EN_C);
+	dm_write_reg(xfm->ctx, addr, value);
+}
+
+bool dce110_transform_underlay_is_scaling_enabled(struct transform *xfm)
+{
+	uint32_t value = dm_read_reg(xfm->ctx, mmSCLV_MODE);
+	uint8_t scl_mode = get_reg_field_value(value, SCLV_MODE, SCL_MODE);
+
+	return scl_mode == 0;
+}
+
+/* TODO: sync this one with DAL2 */
+bool dce110_transform_underlay_set_scaler(
+	struct transform *xfm,
+	const struct scaler_data *data)
+{
+	struct dce110_transform *xfm110 = TO_DCE110_TRANSFORM(xfm);
+	bool is_scaling_required;
+	struct rect luma_viewport = {0};
+	struct rect chroma_viewport = {0};
+	struct dc_context *ctx = xfm->ctx;
+
+	/* 1. Lock Scaler TODO: enable?*/
+	/*set_scaler_update_lock(xfm, true);*/
+
+	/* 2. Calculate viewport, viewport programming should happen after init
+	 * calculations as they may require an adjustment in the viewport.
+	 */
+
+	calculate_viewport(data, &luma_viewport, &chroma_viewport);
+
+	/* 3. Program overscan */
+	program_overscan(xfm110, &data->overscan);
+
+	/* 4. Program taps and configuration */
+	is_scaling_required = setup_scaling_configuration(xfm110, data);
+
+	if (is_scaling_required) {
+		/* 5. Calculate and program ratio, filter initialization */
+
+		struct sclv_ratios_inits inits = { 0 };
+
+		calculate_inits(
+			xfm110,
+			data,
+			&inits,
+			&luma_viewport,
+			&chroma_viewport);
+
+		program_scl_ratios_inits(xfm110, &inits);
+
+		/*scaler coeff of 2-TAPS use hardware auto calculated value*/
+
+		/* 6. Program vertical filters */
+		if (data->taps.v_taps > 2) {
+			program_two_taps_filter_vert(xfm110, false);
+
+			if (!program_multi_taps_filter(xfm110, data, false)) {
+				dal_logger_write(ctx->logger,
+					LOG_MAJOR_DCP,
+					LOG_MINOR_DCP_SCALER,
+					"Failed vertical taps programming\n");
+				return false;
+			}
+		} else
+			program_two_taps_filter_vert(xfm110, true);
+
+		/* 7. Program horizontal filters */
+		if (data->taps.h_taps > 2) {
+			program_two_taps_filter_horz(xfm110, false);
+
+			if (!program_multi_taps_filter(xfm110, data, true)) {
+				dal_logger_write(ctx->logger,
+					LOG_MAJOR_DCP,
+					LOG_MINOR_DCP_SCALER,
+					"Failed horizontal taps programming\n");
+				return false;
+			}
+		} else
+			program_two_taps_filter_horz(xfm110, true);
+	}
+
+	/* 8. Program the viewport */
+	if (data->flags.bits.SHOULD_PROGRAM_VIEWPORT)
+		program_viewport(xfm110, &luma_viewport, &chroma_viewport);
+
+	/* 9. Unlock the Scaler TODO: enable?*/
+	/* Every call to "set_scaler_update_lock(xfm, TRUE)"
+	 * must have a corresponding call to
+	 * "set_scaler_update_lock(xfm, FALSE)" */
+	/*set_scaler_update_lock(xfm, false);*/
+
+	/* TODO: investigate purpose/need of SHOULD_UNLOCK */
+	if (data->flags.bits.SHOULD_UNLOCK == false)
+		set_coeff_update_complete(xfm110);
+
+	return true;
+}
+
-- 
2.1.4

_______________________________________________
dri-devel mailing list
dri-devel@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/dri-devel

  parent reply	other threads:[~2016-02-16 22:28 UTC|newest]

Thread overview: 87+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2016-02-11 17:19 [PATCH 00/29] Enabling new DAL display driver for amdgpu on Carrizo and Tonga Harry Wentland
2016-02-11 17:19 ` [PATCH 01/29] drm/amd/dal: Add dal headers Harry Wentland
2016-02-11 17:19 ` [PATCH 02/29] drm/amd/dal: Add DAL Basic Types and Logger Harry Wentland
2016-02-11 17:19 ` [PATCH 03/29] drm/amd/dal: Fixed point arithmetic Harry Wentland
2016-02-11 17:19 ` [PATCH 04/29] drm/amd/dal: Asic Capabilities Harry Wentland
2016-02-11 17:19 ` [PATCH 05/29] drm/amd/dal: GPIO (General Purpose IO) Harry Wentland
2016-02-11 17:19 ` [PATCH 06/29] drm/amd/dal: Adapter Service Harry Wentland
2016-02-12  0:26   ` Dave Airlie
2016-02-12 14:30     ` Wentland, Harry
2016-02-11 17:19 ` [PATCH 07/29] drm/amd/dal: BIOS Parser Harry Wentland
2016-02-11 17:19 ` [PATCH 08/29] drm/amd/dal: I2C Aux Manager Harry Wentland
2016-02-11 20:19   ` Rob Clark
2016-02-11 20:52     ` Daniel Vetter
2016-02-17  3:23     ` Harry Wentland
2016-02-11 17:19 ` [PATCH 09/29] drm/amd/dal: IRQ Service Harry Wentland
2016-02-11 17:19 ` [PATCH 10/29] drm/amd/dal: GPU Harry Wentland
2016-02-11 17:19 ` [PATCH 11/29] drm/amd/dal: Audio Harry Wentland
2016-02-11 17:19 ` [PATCH 12/29] drm/amd/dal: Bandwidth calculations Harry Wentland
2016-02-11 17:19 ` [PATCH 13/29] drm/amd/dal: Add encoder HW programming Harry Wentland
2016-02-11 17:19 ` [PATCH 14/29] drm/amd/dal: Add clock source " Harry Wentland
2016-02-11 17:19 ` [PATCH 15/29] drm/amd/dal: Add timing generator " Harry Wentland
2016-02-11 17:19 ` [PATCH 16/29] drm/amd/dal: Add surface " Harry Wentland
2016-02-11 17:19 ` [PATCH 17/29] drm/amd/dal: Add framebuffer compression " Harry Wentland
2016-02-11 17:19 ` [PATCH 18/29] drm/amd/dal: Add input pixel processing " Harry Wentland
2016-02-11 17:19 ` [PATCH 19/29] drm/amd/dal: Add output " Harry Wentland
2016-02-11 17:20 ` [PATCH 20/29] drm/amd/dal: Add transform & scaler " Harry Wentland
2016-02-11 17:20 ` [PATCH 21/29] drm/amd/dal: Add Carrizo HW sequencer and resource Harry Wentland
2016-02-11 17:20 ` [PATCH 22/29] drm/amd/dal: Add Tonga/Fiji " Harry Wentland
2016-02-11 17:20 ` [PATCH 23/29] drm/amd/dal: Add empty encoder programming for virtual HW Harry Wentland
2016-02-11 17:20 ` [PATCH 24/29] drm/amd/dal: Add display core Harry Wentland
2016-02-11 17:20 ` [PATCH 25/29] drm/amd/dal: Adding amdgpu_dm for dal Harry Wentland
2016-02-11 17:20 ` [PATCH 26/29] drm/amdgpu: Use dal driver for Carrizo, Tonga, and Fiji Harry Wentland
2016-02-11 17:20 ` [PATCH 27/29] drm/amd/dal: Correctly interpret rotation as bit set Harry Wentland
2016-02-11 21:00   ` Oded Gabbay
2016-02-16 16:46     ` Harry Wentland
2016-02-11 17:20 ` [PATCH 28/29] drm/amd/dal: fix flip clean-up state Harry Wentland
2016-02-11 17:20 ` [PATCH 29/29] drm/amd/dal: Force bw programming for DCE 10 until we start calculate BW Harry Wentland
2016-02-11 20:02 ` [PATCH 00/29] Enabling new DAL display driver for amdgpu on Carrizo and Tonga Mike Lothian
2016-02-11 20:05   ` Wentland, Harry
2016-02-11 20:52 ` Dave Airlie
2016-02-11 21:06   ` Daniel Vetter
2016-02-12  0:57     ` Dave Airlie
2016-02-12  5:34     ` Daniel Vetter
2016-02-13  0:05       ` Wentland, Harry
2016-02-14 11:22         ` Jerome Glisse
2016-02-14 13:23           ` Daniel Vetter
2016-02-17  3:28           ` Harry Wentland
2016-02-14 13:32         ` Rob Clark
2016-02-14 13:51           ` Daniel Vetter
2016-02-17  3:26           ` Harry Wentland
2016-02-14 14:01         ` Daniel Vetter
2016-02-17  3:32           ` Harry Wentland
2016-02-14 21:44         ` Daniel Stone
2016-02-16 22:27 ` [PATCH v2 00/26] " Harry Wentland
2016-02-16 22:27   ` [PATCH v2 01/26] drm/amd/dal: Add dal headers Harry Wentland
2016-02-16 22:27   ` [PATCH v2 02/26] drm/amd/dal: Add DAL Basic Types and Logger Harry Wentland
2016-02-16 22:27   ` [PATCH v2 03/26] drm/amd/dal: Fixed point arithmetic Harry Wentland
2016-02-16 22:27   ` [PATCH v2 04/26] drm/amd/dal: Asic Capabilities Harry Wentland
2016-02-16 22:27   ` [PATCH v2 05/26] drm/amd/dal: GPIO (General Purpose IO) Harry Wentland
2016-02-16 22:27   ` [PATCH v2 06/26] drm/amd/dal: Adapter Service Harry Wentland
2016-02-16 22:27   ` [PATCH v2 07/26] drm/amd/dal: BIOS Parser Harry Wentland
2016-02-16 22:27   ` [PATCH v2 08/26] drm/amd/dal: I2C Aux Manager Harry Wentland
2016-02-16 22:27   ` [PATCH v2 09/26] drm/amd/dal: IRQ Service Harry Wentland
2016-02-16 22:27   ` [PATCH v2 10/26] drm/amd/dal: GPU Harry Wentland
2016-02-16 22:27   ` [PATCH v2 11/26] drm/amd/dal: Audio Harry Wentland
2016-02-16 22:27   ` [PATCH v2 12/26] drm/amd/dal: Bandwidth calculations Harry Wentland
2016-02-16 22:27   ` [PATCH v2 13/26] drm/amd/dal: Add encoder HW programming Harry Wentland
2016-02-16 22:27   ` [PATCH v2 14/26] drm/amd/dal: Add clock source " Harry Wentland
2016-02-16 22:27   ` [PATCH v2 15/26] drm/amd/dal: Add timing generator " Harry Wentland
2016-02-16 22:27   ` [PATCH v2 16/26] drm/amd/dal: Add surface " Harry Wentland
2016-02-16 22:27   ` [PATCH v2 17/26] drm/amd/dal: Add framebuffer compression " Harry Wentland
2016-02-16 22:27   ` [PATCH v2 18/26] drm/amd/dal: Add input pixel processing " Harry Wentland
2016-02-16 22:27   ` [PATCH v2 19/26] drm/amd/dal: Add output " Harry Wentland
2016-02-16 22:28   ` Harry Wentland [this message]
2016-02-16 22:28   ` [PATCH v2 21/26] drm/amd/dal: Add Carrizo HW sequencer and resource Harry Wentland
2016-02-16 22:28   ` [PATCH v2 22/26] drm/amd/dal: Add Tonga/Fiji " Harry Wentland
2016-02-16 22:28   ` [PATCH v2 23/26] drm/amd/dal: Add empty encoder programming for virtual HW Harry Wentland
2016-02-16 22:28   ` [PATCH v2 24/26] drm/amd/dal: Add display core Harry Wentland
2016-02-16 22:28   ` [PATCH v2 25/26] drm/amd/dal: Adding amdgpu_dm for dal Harry Wentland
2016-02-16 22:28   ` [PATCH v2 26/26] drm/amdgpu: Use dal driver for Carrizo, Tonga, and Fiji Harry Wentland
2016-02-29 21:56 ` [PATCH v3 00/26] Enabling new DAL display driver for amdgpu on Carrizo and Tonga Harry Wentland
2016-02-29 21:56   ` [PATCH v3 01/26] drm/amd/dal: Add dal headers Harry Wentland
2016-02-29 21:56   ` [PATCH v3 05/26] drm/amd/dal: GPIO (General Purpose IO) Harry Wentland
2016-02-29 21:56   ` [PATCH v3 07/26] drm/amd/dal: BIOS Parser Harry Wentland
2016-02-29 21:56   ` [PATCH v3 24/26] drm/amd/dal: Add display core Harry Wentland
2016-02-29 21:56   ` [PATCH v3 25/26] drm/amd/dal: Adding amdgpu_dm for dal Harry Wentland
2016-02-29 21:56   ` [PATCH v3 26/26] drm/amdgpu: Use dal driver for Carrizo, Tonga, and Fiji Harry Wentland

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=b24928ff6137d7afceb758a1a24ff029a34e76f2.1455660367.git.harry.wentland@amd.com \
    --to=harry.wentland@amd.com \
    --cc=dri-devel@lists.freedesktop.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.