diff mbox

[v2,02/26] drm/amd/dal: Add DAL Basic Types and Logger

Message ID 51cecb97fcf271e004e73b2e69264c4babfafecc.1455660366.git.harry.wentland@amd.com (mailing list archive)
State New, archived
Headers show

Commit Message

Harry Wentland Feb. 16, 2016, 10:27 p.m. UTC
Laying the groundwork for the AMD DAL display driver.
This patch includes the basic services and defines basic
types required by the display driver, such as:
- ASIC register access
- VBIOS access
- Vector and flat_set data structures
- Display signal types
- ASIC versions and IDs
- HW IDs
- Logging functionality

This patch adds Kconfig options to enable the DAL
display driver.
- DRM_AMD_DAL
- DRM_AMD_DAL_VBIOS_PRESENT
- DRM_AMD_DAL_DCE11_0
- DRM_AMD_DAL_DCE10_0
- DEBUG_KERNEL_DAL

Signed-off-by: Harry Wentland <harry.wentland@amd.com>
Reviewed-by: Alex Deucher <alexander.deucher@amd.com>
---
 drivers/gpu/drm/amd/dal/Kconfig                    |  48 ++
 drivers/gpu/drm/amd/dal/Makefile                   |  21 +
 drivers/gpu/drm/amd/dal/dc/basics/Makefile         |  10 +
 drivers/gpu/drm/amd/dal/dc/basics/conversion.c     | 224 +++++
 drivers/gpu/drm/amd/dal/dc/basics/conversion.h     |  49 ++
 drivers/gpu/drm/amd/dal/dc/basics/grph_object_id.c | 134 +++
 drivers/gpu/drm/amd/dal/dc/basics/logger.c         | 954 +++++++++++++++++++++
 drivers/gpu/drm/amd/dal/dc/basics/logger.h         |  64 ++
 .../gpu/drm/amd/dal/dc/basics/register_logger.c    | 197 +++++
 drivers/gpu/drm/amd/dal/dc/basics/signal_types.c   | 116 +++
 drivers/gpu/drm/amd/dal/dc/basics/vector.c         | 309 +++++++
 11 files changed, 2126 insertions(+)
 create mode 100644 drivers/gpu/drm/amd/dal/Kconfig
 create mode 100644 drivers/gpu/drm/amd/dal/Makefile
 create mode 100644 drivers/gpu/drm/amd/dal/dc/basics/Makefile
 create mode 100644 drivers/gpu/drm/amd/dal/dc/basics/conversion.c
 create mode 100644 drivers/gpu/drm/amd/dal/dc/basics/conversion.h
 create mode 100644 drivers/gpu/drm/amd/dal/dc/basics/grph_object_id.c
 create mode 100644 drivers/gpu/drm/amd/dal/dc/basics/logger.c
 create mode 100644 drivers/gpu/drm/amd/dal/dc/basics/logger.h
 create mode 100644 drivers/gpu/drm/amd/dal/dc/basics/register_logger.c
 create mode 100644 drivers/gpu/drm/amd/dal/dc/basics/signal_types.c
 create mode 100644 drivers/gpu/drm/amd/dal/dc/basics/vector.c
diff mbox

Patch

diff --git a/drivers/gpu/drm/amd/dal/Kconfig b/drivers/gpu/drm/amd/dal/Kconfig
new file mode 100644
index 000000000000..2289c0b10dae
--- /dev/null
+++ b/drivers/gpu/drm/amd/dal/Kconfig
@@ -0,0 +1,48 @@ 
+menu "Display Engine Configuration"
+	depends on DRM && (DRM_AMDSOC || DRM_AMDGPU)
+
+config DRM_AMD_DAL
+        bool "AMD DAL - Enable new display engine
+        help
+          Choose this option if you want to use the new display engine
+          support for AMD SOC.
+
+          Will be deprecated when the DAL component becomes stable and
+          AMDSOC will fully switch to it.
+
+config DRM_AMD_DAL_VBIOS_PRESENT
+        bool "Video Bios available on board"
+        depends on DRM_AMD_DAL
+        help
+         This option is needed to allow a full range of feature
+	 support when working on
+	 x86 platforms and there is a VBIOS
+	 present in the system
+
+config DRM_AMD_DAL_DCE11_0
+        bool "Carrizo family"
+        depends on DRM_AMD_DAL
+        help
+         Choose this option
+	 if you want to have
+	 CZ family
+	 for display engine
+
+config DRM_AMD_DAL_DCE10_0
+        bool "VI family"
+        depends on DRM_AMD_DAL
+        help
+         Choose this option
+	 if you want to have
+	 VI family for display
+	 engine.
+
+config DEBUG_KERNEL_DAL
+        bool "Enable kgdb break in DAL"
+        depends on DRM_AMD_DAL
+        help
+         Choose this option
+         if you want to hit
+         kdgb_break in assert.
+
+endmenu
diff --git a/drivers/gpu/drm/amd/dal/Makefile b/drivers/gpu/drm/amd/dal/Makefile
new file mode 100644
index 000000000000..25ae4646c4d3
--- /dev/null
+++ b/drivers/gpu/drm/amd/dal/Makefile
@@ -0,0 +1,21 @@ 
+#
+# Makefile for the DAL (Display Abstract Layer), which is a  sub-component
+# of the AMDGPU drm driver.
+# It provides the HW control for display related functionalities.
+
+AMDDALPATH = $(RELATIVE_AMD_DAL_PATH)
+
+subdir-ccflags-y += -Werror
+
+subdir-ccflags-y += -I$(AMDDALPATH)/ -I$(AMDDALPATH)/include
+
+subdir-ccflags-y += -I$(FULL_AMD_DAL_PATH)/dc/inc/
+
+#TODO: remove when Timing Sync feature is complete
+subdir-ccflags-y += -DBUILD_FEATURE_TIMING_SYNC=0
+
+DAL_LIBS = amdgpu_dm dc
+
+AMD_DAL = $(addsuffix /Makefile, $(addprefix $(FULL_AMD_DAL_PATH)/,$(DAL_LIBS)))
+
+include $(AMD_DAL)
diff --git a/drivers/gpu/drm/amd/dal/dc/basics/Makefile b/drivers/gpu/drm/amd/dal/dc/basics/Makefile
new file mode 100644
index 000000000000..6f382812fae3
--- /dev/null
+++ b/drivers/gpu/drm/amd/dal/dc/basics/Makefile
@@ -0,0 +1,10 @@ 
+#
+# Makefile for the 'utils' sub-component of DAL.
+# It provides the general basic services required by other DAL
+# subcomponents.
+
+BASICS = conversion.o grph_object_id.o logger.o register_logger.o signal_types.o vector.o
+
+AMD_DAL_BASICS = $(addprefix $(AMDDALPATH)/dc/basics/,$(BASICS))
+
+AMD_DAL_FILES += $(AMD_DAL_BASICS)
diff --git a/drivers/gpu/drm/amd/dal/dc/basics/conversion.c b/drivers/gpu/drm/amd/dal/dc/basics/conversion.c
new file mode 100644
index 000000000000..2f1f3d4ff96b
--- /dev/null
+++ b/drivers/gpu/drm/amd/dal/dc/basics/conversion.c
@@ -0,0 +1,224 @@ 
+/*
+ * 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"
+
+#define DIVIDER 10000
+
+/* S2D13 value in [-3.00...0.9999] */
+#define S2D13_MIN (-3 * DIVIDER)
+#define S2D13_MAX (3 * DIVIDER)
+
+uint16_t fixed_point_to_int_frac(
+	struct fixed31_32 arg,
+	uint8_t integer_bits,
+	uint8_t fractional_bits)
+{
+	int32_t numerator;
+	int32_t divisor = 1 << fractional_bits;
+
+	uint16_t result;
+
+	uint16_t d = (uint16_t)dal_fixed31_32_floor(
+		dal_fixed31_32_abs(
+			arg));
+
+	if (d <= (uint16_t)(1 << integer_bits) - (1 / (uint16_t)divisor))
+		numerator = (uint16_t)dal_fixed31_32_floor(
+			dal_fixed31_32_mul_int(
+				arg,
+				divisor));
+	else {
+		numerator = dal_fixed31_32_floor(
+			dal_fixed31_32_sub(
+				dal_fixed31_32_from_int(
+					1LL << integer_bits),
+				dal_fixed31_32_recip(
+					dal_fixed31_32_from_int(
+						divisor))));
+	}
+
+	if (numerator >= 0)
+		result = (uint16_t)numerator;
+	else
+		result = (uint16_t)(
+		(1 << (integer_bits + fractional_bits + 1)) + numerator);
+
+	if ((result != 0) && dal_fixed31_32_lt(
+		arg, dal_fixed31_32_zero))
+		result |= 1 << (integer_bits + fractional_bits);
+
+	return result;
+}
+/**
+* convert_float_matrix
+* This converts a double into HW register spec defined format S2D13.
+* @param :
+* @return None
+*/
+void convert_float_matrix(
+	uint16_t *matrix,
+	struct fixed31_32 *flt,
+	uint32_t buffer_size)
+{
+	const struct fixed31_32 min_2_13 =
+		dal_fixed31_32_from_fraction(S2D13_MIN, DIVIDER);
+	const struct fixed31_32 max_2_13 =
+		dal_fixed31_32_from_fraction(S2D13_MAX, DIVIDER);
+	uint32_t i;
+
+	for (i = 0; i < buffer_size; ++i) {
+		uint32_t reg_value =
+				fixed_point_to_int_frac(
+					dal_fixed31_32_clamp(
+						flt[i],
+						min_2_13,
+						max_2_13),
+						2,
+						13);
+
+		matrix[i] = (uint16_t)reg_value;
+	}
+}
+
+static void calculate_adjustments_common(
+	const struct fixed31_32 *ideal_matrix,
+	const struct dc_csc_adjustments *adjustments,
+	struct fixed31_32 *matrix)
+{
+	const struct fixed31_32 sin_hue =
+		dal_fixed31_32_sin(adjustments->hue);
+	const struct fixed31_32 cos_hue =
+		dal_fixed31_32_cos(adjustments->hue);
+
+	const struct fixed31_32 multiplier =
+		dal_fixed31_32_mul(
+			adjustments->contrast,
+			adjustments->saturation);
+
+	matrix[0] = dal_fixed31_32_mul(
+		ideal_matrix[0],
+		adjustments->contrast);
+
+	matrix[1] = dal_fixed31_32_mul(
+		ideal_matrix[1],
+		adjustments->contrast);
+
+	matrix[2] = dal_fixed31_32_mul(
+		ideal_matrix[2],
+		adjustments->contrast);
+
+	matrix[4] = dal_fixed31_32_mul(
+		multiplier,
+		dal_fixed31_32_add(
+			dal_fixed31_32_mul(
+				ideal_matrix[8],
+				sin_hue),
+			dal_fixed31_32_mul(
+				ideal_matrix[4],
+				cos_hue)));
+
+	matrix[5] = dal_fixed31_32_mul(
+		multiplier,
+		dal_fixed31_32_add(
+			dal_fixed31_32_mul(
+				ideal_matrix[9],
+				sin_hue),
+			dal_fixed31_32_mul(
+				ideal_matrix[5],
+				cos_hue)));
+
+	matrix[6] = dal_fixed31_32_mul(
+		multiplier,
+		dal_fixed31_32_add(
+			dal_fixed31_32_mul(
+				ideal_matrix[10],
+				sin_hue),
+			dal_fixed31_32_mul(
+				ideal_matrix[6],
+				cos_hue)));
+
+	matrix[7] = ideal_matrix[7];
+
+	matrix[8] = dal_fixed31_32_mul(
+		multiplier,
+		dal_fixed31_32_sub(
+			dal_fixed31_32_mul(
+				ideal_matrix[8],
+				cos_hue),
+			dal_fixed31_32_mul(
+				ideal_matrix[4],
+				sin_hue)));
+
+	matrix[9] = dal_fixed31_32_mul(
+		multiplier,
+		dal_fixed31_32_sub(
+			dal_fixed31_32_mul(
+				ideal_matrix[9],
+				cos_hue),
+			dal_fixed31_32_mul(
+				ideal_matrix[5],
+				sin_hue)));
+
+	matrix[10] = dal_fixed31_32_mul(
+		multiplier,
+		dal_fixed31_32_sub(
+			dal_fixed31_32_mul(
+				ideal_matrix[10],
+				cos_hue),
+			dal_fixed31_32_mul(
+				ideal_matrix[6],
+				sin_hue)));
+
+	matrix[11] = ideal_matrix[11];
+}
+
+void calculate_adjustments(
+	const struct fixed31_32 *ideal_matrix,
+	const struct dc_csc_adjustments *adjustments,
+	struct fixed31_32 *matrix)
+{
+	calculate_adjustments_common(ideal_matrix, adjustments, matrix);
+
+	matrix[3] = dal_fixed31_32_add(
+		ideal_matrix[3],
+		dal_fixed31_32_mul(
+			adjustments->brightness,
+			dal_fixed31_32_from_fraction(86, 100)));
+}
+
+void calculate_adjustments_y_only(
+	const struct fixed31_32 *ideal_matrix,
+	const struct dc_csc_adjustments *adjustments,
+	struct fixed31_32 *matrix)
+{
+	calculate_adjustments_common(ideal_matrix, adjustments, matrix);
+
+	matrix[3] = dal_fixed31_32_add(
+		ideal_matrix[3],
+		adjustments->brightness);
+}
+
diff --git a/drivers/gpu/drm/amd/dal/dc/basics/conversion.h b/drivers/gpu/drm/amd/dal/dc/basics/conversion.h
new file mode 100644
index 000000000000..24ff47352688
--- /dev/null
+++ b/drivers/gpu/drm/amd/dal/dc/basics/conversion.h
@@ -0,0 +1,49 @@ 
+/*
+ * 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_CONVERSION_H__
+#define __DAL_CONVERSION_H__
+
+uint16_t fixed_point_to_int_frac(
+	struct fixed31_32 arg,
+	uint8_t integer_bits,
+	uint8_t fractional_bits);
+
+void convert_float_matrix(
+	uint16_t *matrix,
+	struct fixed31_32 *flt,
+	uint32_t buffer_size);
+
+void calculate_adjustments(
+	const struct fixed31_32 *ideal_matrix,
+	const struct dc_csc_adjustments *adjustments,
+	struct fixed31_32 *matrix);
+
+void calculate_adjustments_y_only(
+	const struct fixed31_32 *ideal_matrix,
+	const struct dc_csc_adjustments *adjustments,
+	struct fixed31_32 *matrix);
+
+#endif
diff --git a/drivers/gpu/drm/amd/dal/dc/basics/grph_object_id.c b/drivers/gpu/drm/amd/dal/dc/basics/grph_object_id.c
new file mode 100644
index 000000000000..9c80847d03a9
--- /dev/null
+++ b/drivers/gpu/drm/amd/dal/dc/basics/grph_object_id.c
@@ -0,0 +1,134 @@ 
+/*
+ * Copyright 2012-15 Advanced Micro Devices, Inc.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
+ * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ *
+ * Authors: AMD
+ *
+ */
+
+#include "dm_services.h"
+#include "include/grph_object_id.h"
+
+bool dal_graphics_object_id_is_valid(struct graphics_object_id id)
+{
+	bool rc = true;
+
+	switch (id.type) {
+	case OBJECT_TYPE_UNKNOWN:
+		rc = false;
+		break;
+	case OBJECT_TYPE_GPU:
+	case OBJECT_TYPE_ENGINE:
+		/* do NOT check for id.id == 0 */
+		if (id.enum_id == ENUM_ID_UNKNOWN)
+			rc = false;
+		break;
+	default:
+		if (id.id == 0 || id.enum_id == ENUM_ID_UNKNOWN)
+			rc = false;
+		break;
+	}
+
+	return rc;
+}
+
+bool dal_graphics_object_id_is_equal(
+	struct graphics_object_id id1,
+	struct graphics_object_id id2)
+{
+	if (false == dal_graphics_object_id_is_valid(id1)) {
+		dm_output_to_console(
+		"%s: Warning: comparing invalid object 'id1'!\n", __func__);
+		return false;
+	}
+
+	if (false == dal_graphics_object_id_is_valid(id2)) {
+		dm_output_to_console(
+		"%s: Warning: comparing invalid object 'id2'!\n", __func__);
+		return false;
+	}
+
+	if (id1.id == id2.id && id1.enum_id == id2.enum_id
+		&& id1.type == id2.type)
+		return true;
+
+	return false;
+}
+
+/* Based on internal data members memory layout */
+uint32_t dal_graphics_object_id_to_uint(struct graphics_object_id id)
+{
+	uint32_t object_id = 0;
+
+	object_id = id.id + (id.enum_id << 0x8) + (id.type << 0xc);
+	return object_id;
+}
+
+/*
+ * ******* get specific ID - internal safe cast into specific type *******
+ */
+
+enum controller_id dal_graphics_object_id_get_controller_id(
+	struct graphics_object_id id)
+{
+	if (id.type == OBJECT_TYPE_CONTROLLER)
+		return id.id;
+	return CONTROLLER_ID_UNDEFINED;
+}
+
+enum clock_source_id dal_graphics_object_id_get_clock_source_id(
+	struct graphics_object_id id)
+{
+	if (id.type == OBJECT_TYPE_CLOCK_SOURCE)
+		return id.id;
+	return CLOCK_SOURCE_ID_UNDEFINED;
+}
+
+enum encoder_id dal_graphics_object_id_get_encoder_id(
+	struct graphics_object_id id)
+{
+	if (id.type == OBJECT_TYPE_ENCODER)
+		return id.id;
+	return ENCODER_ID_UNKNOWN;
+}
+
+enum connector_id dal_graphics_object_id_get_connector_id(
+	struct graphics_object_id id)
+{
+	if (id.type == OBJECT_TYPE_CONNECTOR)
+		return id.id;
+	return CONNECTOR_ID_UNKNOWN;
+}
+
+enum audio_id dal_graphics_object_id_get_audio_id(struct graphics_object_id id)
+{
+	if (id.type == OBJECT_TYPE_AUDIO)
+		return id.id;
+	return AUDIO_ID_UNKNOWN;
+}
+
+enum engine_id dal_graphics_object_id_get_engine_id(
+	struct graphics_object_id id)
+{
+	if (id.type == OBJECT_TYPE_ENGINE)
+		return id.id;
+	return ENGINE_ID_UNKNOWN;
+}
+
diff --git a/drivers/gpu/drm/amd/dal/dc/basics/logger.c b/drivers/gpu/drm/amd/dal/dc/basics/logger.c
new file mode 100644
index 000000000000..e7938ec9bb7c
--- /dev/null
+++ b/drivers/gpu/drm/amd/dal/dc/basics/logger.c
@@ -0,0 +1,954 @@ 
+/*
+ * 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 <stdarg.h>
+#include "dm_services.h"
+#include "include/dal_types.h"
+#include "include/logger_interface.h"
+#include "logger.h"
+
+/* TODO: for now - empty, use DRM defines from dal services.
+		Need to define appropriate levels of prints, and implement
+		this component
+void dal_log(const char *format, ...)
+{
+}
+*/
+
+/* ----------- Logging Major/Minor names ------------ */
+
+#define NUM_ELEMENTS(a) (sizeof(a) / sizeof((a)[0]))
+
+static const struct log_minor_info component_minor_info_tbl[] = {
+	{LOG_MINOR_COMPONENT_LINK_SERVICE, "LS"},
+	{LOG_MINOR_COMPONENT_DAL_INTERFACE, "DalIf"},
+	{LOG_MINOR_COMPONENT_HWSS, "HWSS"},
+	{LOG_MINOR_COMPONENT_ADAPTER_SERVICE, "AS"},
+	{LOG_MINOR_COMPONENT_DISPLAY_SERVICE, "DS"},
+	{LOG_MINOR_COMPONENT_TOPOLOGY_MANAGER, "TM"},
+	{LOG_MINOR_COMPONENT_ENCODER, "Encoder"},
+	{LOG_MINOR_COMPONENT_I2C_AUX, "I2cAux"},
+	{LOG_MINOR_COMPONENT_AUDIO, "Audio"},
+	{LOG_MINOR_COMPONENT_DISPLAY_CAPABILITY_SERVICE, "Dcs"},
+	{LOG_MINOR_COMPONENT_DMCU, "Dmcu"},
+	{LOG_MINOR_COMPONENT_GPU, "GPU"},
+	{LOG_MINOR_COMPONENT_CONTROLLER, "Cntrlr"},
+	{LOG_MINOR_COMPONENT_ISR, "ISR"},
+	{LOG_MINOR_COMPONENT_BIOS, "BIOS"},
+	{LOG_MINOR_COMPONENT_DC, "DC"},
+	{LOG_MINOR_COMPONENT_IRQ_SERVICE, "IRQ SERVICE"},
+
+};
+
+static const struct log_minor_info hw_trace_minor_info_tbl[] = {
+	{LOG_MINOR_HW_TRACE_MST, "Mst" },
+	{LOG_MINOR_HW_TRACE_TRAVIS, "Travis" },
+	{LOG_MINOR_HW_TRACE_HOTPLUG, "Hotplug" },
+	{LOG_MINOR_HW_TRACE_LINK_TRAINING, "LinkTraining" },
+	{LOG_MINOR_HW_TRACE_SET_MODE, "SetMode" },
+	{LOG_MINOR_HW_TRACE_RESUME_S3, "ResumeS3" },
+	{LOG_MINOR_HW_TRACE_RESUME_S4, "ResumeS4" },
+	{LOG_MINOR_HW_TRACE_BOOTUP, "BootUp" },
+	{LOG_MINOR_HW_TRACE_AUDIO, "Audio"},
+	{LOG_MINOR_HW_TRACE_HPD_IRQ, "HpdIrq" },
+	{LOG_MINOR_HW_TRACE_INTERRUPT, "Interrupt" },
+	{LOG_MINOR_HW_TRACE_MPO, "Planes" },
+};
+
+static const struct log_minor_info mst_minor_info_tbl[] = {
+	{LOG_MINOR_MST_IRQ_HPD_RX, "IrqHpdRx"},
+	{LOG_MINOR_MST_IRQ_TIMER, "IrqTimer"},
+	{LOG_MINOR_MST_NATIVE_AUX, "NativeAux"},
+	{LOG_MINOR_MST_SIDEBAND_MSG, "SB"},
+	{LOG_MINOR_MST_MSG_TRANSACTION, "MT"},
+	{LOG_MINOR_MST_SIDEBAND_MSG_PARSED, "SB Parsed"},
+	{LOG_MINOR_MST_MSG_TRANSACTION_PARSED, "MT Parsed"},
+	{LOG_MINOR_MST_AUX_MSG_DPCD_ACCESS, "AuxMsgDpcdAccess"},
+	{LOG_MINOR_MST_PROGRAMMING, "Programming"},
+	{LOG_MINOR_MST_TOPOLOGY_DISCOVERY, "TopologyDiscovery"},
+	{LOG_MINOR_MST_CONVERTER_CAPS, "ConverterCaps"},
+};
+
+static const struct log_minor_info dcs_minor_info_tbl[] = {
+	{LOG_MINOR_DCS_EDID_EMULATOR, "EdidEmul"},
+	{LOG_MINOR_DCS_DONGLE_DETECTION, "DongleDetect"},
+};
+
+static const struct log_minor_info dcp_minor_info_tbl[] = {
+	{ LOG_MINOR_DCP_GAMMA_GRPH, "GammaGrph"},
+	{ LOG_MINOR_DCP_GAMMA_OVL, "GammaOvl"},
+	{ LOG_MINOR_DCP_CSC_GRPH, "CscGrph"},
+	{ LOG_MINOR_DCP_CSC_OVL, "CscOvl"},
+	{ LOG_MINOR_DCP_SCALER, "Scaler"},
+	{ LOG_MINOR_DCP_SCALER_TABLES, "ScalerTables"},
+};
+
+static const struct log_minor_info bios_minor_info_tbl[] = {
+	{LOG_MINOR_BIOS_CMD_TABLE, "CmdTbl"},
+};
+
+static const struct log_minor_info reg_minor_info_tbl[] = {
+	{LOG_MINOR_REGISTER_INDEX, "Index"},
+};
+
+static const struct log_minor_info info_packet_minor_info_tbl[] = {
+	{LOG_MINOR_INFO_PACKETS_HDMI, "Hdmi"},
+};
+
+
+static const struct log_minor_info dsat_minor_info_tbl[] = {
+	{LOG_MINOR_DSAT_LOGGER, "Logger"},
+	{LOG_MINOR_DSAT_EDID_OVERRIDE, "EDID_Override"},
+};
+
+static const struct log_minor_info ec_minor_info_tbl[] = {
+	{LOG_MINOR_EC_PPLIB_NOTIFY, "PPLib_Notify" }, /* PPLib notifies DAL */
+	{LOG_MINOR_EC_PPLIB_QUERY, "PPLib_Query" } /* DAL requested info from
+							PPLib */
+};
+
+static const struct log_minor_info bwm_minor_info_tbl[] = {
+	{LOG_MINOR_BWM_MODE_VALIDATION, "ModeValidation"},
+	{LOG_MINOR_BWM_REQUIRED_BANDWIDTH_CALCS, "Req_Bandw_Calcs"}
+};
+
+static const struct log_minor_info mode_enum_minor_info_tbl[] = {
+	{LOG_MINOR_MODE_ENUM_BEST_VIEW_CANDIDATES, "BestviewCandidates"},
+	{LOG_MINOR_MODE_ENUM_VIEW_SOLUTION, "ViewSolution"},
+	{LOG_MINOR_MODE_ENUM_TS_LIST_BUILD, "TsListBuild"},
+	{LOG_MINOR_MODE_ENUM_TS_LIST, "TsList"},
+	{LOG_MINOR_MODE_ENUM_MASTER_VIEW_LIST, "MasterViewList"},
+	{LOG_MINOR_MODE_ENUM_MASTER_VIEW_LIST_UPDATE, "MasterViewListUpdate"},
+};
+
+static const struct log_minor_info i2caux_minor_info_tbl[] = {
+	{LOG_MINOR_I2C_AUX_LOG, "Log"},
+	{LOG_MINOR_I2C_AUX_AUX_TIMESTAMP, "Timestamp"},
+	{LOG_MINOR_I2C_AUX_CFG, "Config"}
+};
+
+static const struct log_minor_info line_buffer_minor_info_tbl[] = {
+	{LOG_MINOR_LINE_BUFFER_POWERGATING, "PowerGating"}
+};
+
+static const struct log_minor_info hwss_minor_info_tbl[] = {
+	{LOG_MINOR_HWSS_TAPS_VALIDATION, "HWSS Taps"}
+};
+
+static const struct log_minor_info optimization_minor_info_tbl[] = {
+	{LOG_MINOR_OPTMZ_GENERAL, "General Optimizations"},
+	{LOG_MINOR_OPTMZ_DO_NOT_TURN_OFF_VCC_DURING_SET_MODE,
+		"Skip Vcc Off During Set Mode"}
+};
+
+static const struct log_minor_info perf_measure_minor_info_tbl[] = {
+	{LOG_MINOR_PERF_MEASURE_GENERAL, "General Performance Measurement"},
+	{LOG_MINOR_PERF_MEASURE_HEAP_MEMORY, "Heap Memory Management"}
+};
+
+static const struct log_minor_info sync_minor_info_tbl[] = {
+	{LOG_MINOR_SYNC_HW_CLOCK_ADJUST, "Pixel Rate Tune-up"},
+	{LOG_MINOR_SYNC_TIMING, "Timing"}
+};
+
+static const struct log_minor_info backlight_minor_info_tbl[] = {
+	{LOG_MINOR_BACKLIGHT_BRIGHTESS_CAPS, "Caps"},
+	{LOG_MINOR_BACKLIGHT_DMCU_DELTALUT, "DMCU Delta LUT"},
+	{LOG_MINOR_BACKLIGHT_DMCU_BUILD_DELTALUT, "Build DMCU Delta LUT"},
+	{LOG_MINOR_BACKLIGHT_INTERFACE, "Interface"},
+	{LOG_MINOR_BACKLIGHT_LID, "Lid Status"}
+};
+
+
+static const struct log_minor_info override_feature_minor_info_tbl[] = {
+	{LOG_MINOR_FEATURE_OVERRIDE, "overriden feature"},
+};
+
+static const struct log_minor_info detection_minor_info_tbl[] = {
+	{LOG_MINOR_DETECTION_EDID_PARSER, "EDID Parser"},
+	{LOG_MINOR_DETECTION_DP_CAPS, "DP caps"},
+};
+
+static const struct log_minor_info tm_minor_info_tbl[] = {
+	{LOG_MINOR_TM_INFO, "INFO"},
+	{LOG_MINOR_TM_IFACE_TRACE, "IFACE_TRACE"},
+	{LOG_MINOR_TM_RESOURCES, "RESOURCES"},
+	{LOG_MINOR_TM_ENCODER_CTL, "ENCODER_CTL"},
+	{LOG_MINOR_TM_ENG_ASN, "ENG_ASN"},
+	{LOG_MINOR_TM_CONTROLLER_ASN, "CONTROLLER_ASN"},
+	{LOG_MINOR_TM_PWR_GATING, "PWR_GATING"},
+	{LOG_MINOR_TM_BUILD_DSP_PATH, "BUILD_PATH"},
+	{LOG_MINOR_TM_DISPLAY_DETECT, "DISPLAY_DETECT"},
+	{LOG_MINOR_TM_LINK_SRV,	"LINK_SRV"},
+	{LOG_MINOR_TM_NOT_IMPLEMENTED, "NOT_IMPL"},
+	{LOG_MINOR_TM_COFUNC_PATH, "COFUNC_PATH"}
+};
+
+static const struct log_minor_info ds_minor_info_tbl[] = {
+	{LOG_MINOR_DS_MODE_SETTING, "Mode_Setting"},
+};
+
+
+struct log_major_mask_info {
+	struct log_major_info major_info;
+	uint32_t default_mask;
+	const struct log_minor_info *minor_tbl;
+	uint32_t tbl_element_cnt;
+};
+
+/* A mask for each Major.
+ * Use a mask or zero. */
+#define LG_ERR_MSK 0xffffffff
+#define LG_WRN_MSK 0xffffffff
+#define LG_TM_MSK (1 << LOG_MINOR_TM_INFO)
+#define LG_FO_MSK (1 << LOG_MINOR_FEATURE_OVERRIDE)
+#define LG_EC_MSK ((1 << LOG_MINOR_EC_PPLIB_NOTIFY) | \
+			(1 << LOG_MINOR_EC_PPLIB_QUERY))
+#define LG_DSAT_MSK (1 << LOG_MINOR_DSAT_EDID_OVERRIDE)
+#define LG_DT_MSK (1 << LOG_MINOR_DETECTION_EDID_PARSER)
+
+/* IFT - InterFaceTrace */
+#define LG_IFT_MSK (1 << LOG_MINOR_COMPONENT_DC)
+
+
+#define LG_HW_TR_AUD_MSK (1 << LOG_MINOR_HW_TRACE_AUDIO)
+#define LG_HW_TR_INTERRUPT_MSK (1 << LOG_MINOR_HW_TRACE_INTERRUPT) | \
+		(1 << LOG_MINOR_HW_TRACE_HPD_IRQ)
+#define LG_HW_TR_PLANES_MSK (1 << LOG_MINOR_HW_TRACE_MPO)
+#define LG_ALL_MSK 0xffffffff
+#define LG_DCP_MSK ~(1 << LOG_MINOR_DCP_SCALER)
+
+#define LG_SYNC_MSK (1 << LOG_MINOR_SYNC_TIMING)
+
+#define LG_BWM_MSK (1 << LOG_MINOR_BWM_MODE_VALIDATION)
+
+static const struct log_major_mask_info log_major_mask_info_tbl[] = {
+	/* LogMajor                  major name       default     MinorTble                    tblElementCnt */
+	{{LOG_MAJOR_ERROR,           "Error"       }, LG_ALL_MSK, component_minor_info_tbl,    NUM_ELEMENTS(component_minor_info_tbl)},
+	{{LOG_MAJOR_WARNING,         "Warning"     }, LG_ALL_MSK, component_minor_info_tbl,    NUM_ELEMENTS(component_minor_info_tbl)},
+	{{LOG_MAJOR_INTERFACE_TRACE, "IfTrace"     }, LG_ALL_MSK, component_minor_info_tbl,    NUM_ELEMENTS(component_minor_info_tbl)},
+	{{LOG_MAJOR_HW_TRACE,        "HwTrace"     }, (LG_ALL_MSK &
+			~((1 << LOG_MINOR_HW_TRACE_LINK_TRAINING) |
+			(1 << LOG_MINOR_HW_TRACE_AUDIO))),
+								hw_trace_minor_info_tbl,     NUM_ELEMENTS(hw_trace_minor_info_tbl)},
+	{{LOG_MAJOR_MST,             "MST"         }, LG_ALL_MSK, mst_minor_info_tbl,          NUM_ELEMENTS(mst_minor_info_tbl)},
+	{{LOG_MAJOR_DCS,             "DCS"         }, LG_ALL_MSK, dcs_minor_info_tbl,          NUM_ELEMENTS(dcs_minor_info_tbl)},
+	{{LOG_MAJOR_DCP,             "DCP"         }, LG_DCP_MSK, dcp_minor_info_tbl,          NUM_ELEMENTS(dcp_minor_info_tbl)},
+	{{LOG_MAJOR_BIOS,            "Bios"        }, LG_ALL_MSK, bios_minor_info_tbl,         NUM_ELEMENTS(bios_minor_info_tbl)},
+	{{LOG_MAJOR_REGISTER,        "Register"    }, LG_ALL_MSK, reg_minor_info_tbl,          NUM_ELEMENTS(reg_minor_info_tbl)},
+	{{LOG_MAJOR_INFO_PACKETS,    "InfoPacket"  }, LG_ALL_MSK, info_packet_minor_info_tbl,  NUM_ELEMENTS(info_packet_minor_info_tbl)},
+	{{LOG_MAJOR_DSAT,            "DSAT"        }, LG_ALL_MSK, dsat_minor_info_tbl,         NUM_ELEMENTS(dsat_minor_info_tbl)},
+	{{LOG_MAJOR_EC,              "EC"          }, LG_ALL_MSK, ec_minor_info_tbl,           NUM_ELEMENTS(ec_minor_info_tbl)},
+	{{LOG_MAJOR_BWM,             "BWM"         }, LG_BWM_MSK, bwm_minor_info_tbl,          NUM_ELEMENTS(bwm_minor_info_tbl)},
+	{{LOG_MAJOR_MODE_ENUM,       "ModeEnum"    }, LG_ALL_MSK, mode_enum_minor_info_tbl,    NUM_ELEMENTS(mode_enum_minor_info_tbl)},
+	{{LOG_MAJOR_I2C_AUX,         "I2cAux"      }, LG_ALL_MSK, i2caux_minor_info_tbl,       NUM_ELEMENTS(i2caux_minor_info_tbl)},
+	{{LOG_MAJOR_LINE_BUFFER,     "LineBuffer"  }, LG_ALL_MSK, line_buffer_minor_info_tbl,  NUM_ELEMENTS(line_buffer_minor_info_tbl)},
+	{{LOG_MAJOR_HWSS,            "HWSS"        }, LG_ALL_MSK, hwss_minor_info_tbl,         NUM_ELEMENTS(hwss_minor_info_tbl)},
+	{{LOG_MAJOR_OPTIMIZATION,    "Optimization"}, LG_ALL_MSK, optimization_minor_info_tbl, NUM_ELEMENTS(optimization_minor_info_tbl)},
+	{{LOG_MAJOR_PERF_MEASURE,    "PerfMeasure" }, LG_ALL_MSK, perf_measure_minor_info_tbl, NUM_ELEMENTS(perf_measure_minor_info_tbl)},
+	{{LOG_MAJOR_SYNC,            "Sync"        }, LG_SYNC_MSK,sync_minor_info_tbl,         NUM_ELEMENTS(sync_minor_info_tbl)},
+	{{LOG_MAJOR_BACKLIGHT,       "Backlight"   }, LG_ALL_MSK, backlight_minor_info_tbl,    NUM_ELEMENTS(backlight_minor_info_tbl)},
+	{{LOG_MAJOR_INTERRUPTS,      "Interrupts"  }, LG_ALL_MSK, component_minor_info_tbl,    NUM_ELEMENTS(component_minor_info_tbl)},
+	{{LOG_MAJOR_TM,              "TM"          }, 0,          tm_minor_info_tbl,           NUM_ELEMENTS(tm_minor_info_tbl)},
+	{{LOG_MAJOR_DISPLAY_SERVICE, "DS"          }, LG_ALL_MSK, ds_minor_info_tbl,           NUM_ELEMENTS(ds_minor_info_tbl)},
+	{{LOG_MAJOR_FEATURE_OVERRIDE, "FeatureOverride" }, LG_ALL_MSK, override_feature_minor_info_tbl, NUM_ELEMENTS(override_feature_minor_info_tbl)},
+	{{LOG_MAJOR_DETECTION,       "Detection"   }, LG_ALL_MSK,  detection_minor_info_tbl,    NUM_ELEMENTS(detection_minor_info_tbl)},
+};
+
+/* ----------- Object init and destruction ----------- */
+static bool construct(struct dc_context *ctx, struct dal_logger *logger)
+{
+	uint32_t i;
+	/* malloc buffer and init offsets */
+
+	logger->log_buffer_size = DAL_LOGGER_BUFFER_MAX_SIZE;
+	logger->log_buffer = (char *)dm_alloc(ctx,
+		logger->log_buffer_size *
+		sizeof(char));
+
+	if (!logger->log_buffer)
+		return false;
+
+	/* todo: Fill buffer with \0 if not done by dal_alloc */
+
+	/* Initialize both offsets to start of buffer (empty) */
+	logger->buffer_read_offset = 0;
+	logger->buffer_write_offset = 0;
+
+	logger->write_wrap_count = 0;
+	logger->read_wrap_count = 0;
+	logger->open_count = 0;
+
+	logger->flags.bits.ENABLE_CONSOLE = 1;
+	logger->flags.bits.ENABLE_BUFFER = 0;
+
+	logger->ctx = ctx;
+
+	/* malloc and init minor mask array */
+	logger->log_enable_mask_minors =
+			(uint32_t *)dm_alloc(
+				ctx,
+				NUM_ELEMENTS(log_major_mask_info_tbl)
+				* sizeof(uint32_t));
+	if (!logger->log_enable_mask_minors)
+		return false;
+
+
+	/* Set default values for mask */
+	for (i = 0; i < NUM_ELEMENTS(log_major_mask_info_tbl); i++) {
+
+		uint32_t dflt_mask = log_major_mask_info_tbl[i].default_mask;
+
+		logger->log_enable_mask_minors[i] = dflt_mask;
+	}
+
+	return true;
+}
+
+static void destruct(struct dal_logger *logger)
+{
+	if (logger->log_buffer) {
+		dm_free(logger->ctx, logger->log_buffer);
+		logger->log_buffer = NULL;
+	}
+
+	if (logger->log_enable_mask_minors) {
+		dm_free(logger->ctx, logger->log_enable_mask_minors);
+		logger->log_enable_mask_minors = NULL;
+	}
+}
+
+struct dal_logger *dal_logger_create(struct dc_context *ctx)
+{
+	/* malloc struct */
+	struct dal_logger *logger = dm_alloc(ctx, sizeof(struct dal_logger));
+
+	if (!logger)
+		return NULL;
+	if (!construct(ctx, logger)) {
+		dm_free(ctx, logger);
+		return NULL;
+	}
+
+	return logger;
+}
+
+uint32_t dal_logger_destroy(struct dal_logger **logger)
+{
+	if (logger == NULL || *logger == NULL)
+		return 1;
+	destruct(*logger);
+	dm_free((*logger)->ctx, *logger);
+	*logger = NULL;
+
+	return 0;
+}
+
+/* ------------------------------------------------------------------------ */
+
+static void lock(struct dal_logger *logger)
+{
+	/* Todo: lock mutex? */
+}
+
+static void unlock(struct dal_logger *logger)
+{
+	/* Todo: unlock mutex */
+}
+
+bool dal_logger_should_log(
+	struct dal_logger *logger,
+	enum log_major major,
+	enum log_minor minor)
+{
+	if (major < LOG_MAJOR_COUNT) {
+
+		uint32_t minor_mask = logger->log_enable_mask_minors[major];
+
+		if ((minor_mask & (1 << minor)) != 0)
+			return true;
+	}
+
+	return false;
+}
+
+static void log_to_debug_console(struct log_entry *entry)
+{
+	struct dal_logger *logger = entry->logger;
+
+	if (logger->flags.bits.ENABLE_CONSOLE == 0)
+		return;
+
+	if (entry->buf_offset) {
+		switch (entry->major) {
+		case LOG_MAJOR_ERROR:
+			dm_error("%s", entry->buf);
+			break;
+		default:
+			dm_output_to_console("%s", entry->buf);
+			break;
+		}
+	}
+}
+
+/* Print everything unread existing in log_buffer to debug console*/
+static void flush_to_debug_console(struct dal_logger *logger)
+{
+	int i = logger->buffer_read_offset;
+	char *string_start = &logger->log_buffer[i];
+
+	dm_output_to_console(
+		"---------------- FLUSHING LOG BUFFER ----------------\n");
+	while (i < logger->buffer_write_offset)	{
+
+		if (logger->log_buffer[i] == '\0') {
+			dm_output_to_console("%s", string_start);
+			string_start = (char *)logger->log_buffer + i + 1;
+		}
+		i++;
+	}
+	dm_output_to_console(
+		"-------------- END FLUSHING LOG BUFFER --------------\n\n");
+}
+
+static void log_to_internal_buffer(struct log_entry *entry)
+{
+
+	uint32_t size = entry->buf_offset;
+	struct dal_logger *logger = entry->logger;
+
+	if (logger->flags.bits.ENABLE_BUFFER == 0)
+		return;
+
+	if (logger->log_buffer == NULL)
+		return;
+
+	if (size > 0 && size < logger->log_buffer_size) {
+
+		int total_free_space = 0;
+		int space_before_wrap = 0;
+
+		if (logger->buffer_write_offset > logger->buffer_read_offset) {
+			total_free_space = logger->log_buffer_size -
+					logger->buffer_write_offset +
+					logger->buffer_read_offset;
+			space_before_wrap = logger->log_buffer_size -
+					logger->buffer_write_offset;
+		} else if (logger->buffer_write_offset <
+				logger->buffer_read_offset) {
+			total_free_space = logger->log_buffer_size -
+					logger->buffer_read_offset +
+					logger->buffer_write_offset;
+			space_before_wrap = total_free_space;
+		} else if (logger->write_wrap_count !=
+				logger->read_wrap_count) {
+			/* Buffer is completely full already */
+			total_free_space = 0;
+			space_before_wrap = 0;
+		} else {
+			/* Buffer is empty, start writing at beginning */
+			total_free_space = logger->log_buffer_size;
+			space_before_wrap = logger->log_buffer_size;
+			logger->buffer_write_offset = 0;
+			logger->buffer_read_offset = 0;
+		}
+
+
+
+
+		if (space_before_wrap > size) {
+			/* No wrap around, copy 'size' bytes
+			 * from 'entry->buf' to 'log_buffer'
+			 */
+			dm_memmove(logger->log_buffer +
+					logger->buffer_write_offset,
+					entry->buf, size);
+			logger->buffer_write_offset += size;
+
+		} else if (total_free_space > size) {
+			/* We have enough room without flushing,
+			 * but need to wrap around */
+
+			int space_after_wrap = total_free_space -
+					space_before_wrap;
+
+			dm_memmove(logger->log_buffer +
+					logger->buffer_write_offset,
+					entry->buf, space_before_wrap);
+			dm_memmove(logger->log_buffer, entry->buf +
+					space_before_wrap, space_after_wrap);
+
+			logger->buffer_write_offset = space_after_wrap;
+			logger->write_wrap_count++;
+
+		} else {
+			/* Not enough room remaining, we should flush
+			 * existing logs */
+
+			/* Flush existing unread logs to console */
+			flush_to_debug_console(logger);
+
+			/* Start writing to beginning of buffer */
+			dm_memmove(logger->log_buffer, entry->buf, size);
+			logger->buffer_write_offset = size;
+			logger->buffer_read_offset = 0;
+		}
+
+	}
+
+	unlock(logger);
+}
+
+
+static void log_timestamp(struct log_entry *entry)
+{
+	dal_logger_append(entry, "00:00:00 ");
+}
+
+static void log_major_minor(struct log_entry *entry)
+{
+	uint32_t i;
+	enum log_major major = entry->major;
+	enum log_minor minor = entry->minor;
+
+	for (i = 0; i < NUM_ELEMENTS(log_major_mask_info_tbl); i++) {
+
+		const struct log_major_mask_info *maj_mask_info =
+				&log_major_mask_info_tbl[i];
+
+		if (maj_mask_info->major_info.major == major) {
+
+			dal_logger_append(entry, "[%s_",
+					maj_mask_info->major_info.major_name);
+
+			if (maj_mask_info->minor_tbl != NULL) {
+				uint32_t j;
+
+				for (j = 0; j < maj_mask_info->tbl_element_cnt; j++) {
+
+					const struct log_minor_info *min_info = &maj_mask_info->minor_tbl[j];
+
+					if (min_info->minor == minor)
+						dal_logger_append(entry, "%s]\t", min_info->minor_name);
+				}
+			}
+
+			break;
+		}
+	}
+}
+
+static void log_heading(struct log_entry *entry,
+			enum log_major major,
+			enum log_minor minor)
+{
+	log_timestamp(entry);
+	log_major_minor(entry);
+}
+
+
+static void append_entry(
+		struct log_entry *entry,
+		char *buffer,
+		uint32_t buf_size)
+{
+	if (!entry->buf ||
+		entry->buf_offset + buf_size > entry->max_buf_bytes
+	) {
+		BREAK_TO_DEBUGGER();
+		return;
+	}
+
+	/* Todo: check if off by 1 byte due to \0 anywhere */
+	dm_memmove(entry->buf + entry->buf_offset, buffer, buf_size);
+	entry->buf_offset += buf_size;
+}
+
+/* ------------------------------------------------------------------------ */
+
+/* Warning: Be careful that 'msg' is null terminated and the total size is
+ * less than DAL_LOGGER_BUFFER_MAX_LOG_LINE_SIZE (256) including '\0'
+ */
+void dal_logger_write(
+	struct dal_logger *logger,
+	enum log_major major,
+	enum log_minor minor,
+	const char *msg,
+	...)
+{
+
+	if (logger && dal_logger_should_log(logger, major, minor)) {
+
+		uint32_t size;
+		va_list args;
+		char buffer[DAL_LOGGER_BUFFER_MAX_LOG_LINE_SIZE];
+		struct log_entry entry;
+
+		va_start(args, msg);
+		dal_logger_open(logger, &entry, major, minor);
+
+
+		size = dm_log_to_buffer(
+			buffer, DAL_LOGGER_BUFFER_MAX_LOG_LINE_SIZE, msg, args);
+
+		if (size > 0 && size <
+				DAL_LOGGER_BUFFER_MAX_LOG_LINE_SIZE - 1) {
+
+			if (buffer[size] == '\0')
+				size++; /* Add one for null terminator */
+
+			/* Concatenate onto end of entry buffer */
+			append_entry(&entry, buffer, size);
+		} else {
+			append_entry(&entry,
+				"LOG_ERROR, line too long or null\n", 35);
+		}
+
+		dal_logger_close(&entry);
+		va_end(args);
+
+	}
+}
+
+
+/* Same as dal_logger_write, except without open() and close(), which must
+ * be done separately.
+ */
+void dal_logger_append(
+	struct log_entry *entry,
+	const char *msg,
+	...)
+{
+	struct dal_logger *logger;
+
+	if (!entry) {
+		BREAK_TO_DEBUGGER();
+		return;
+	}
+
+	logger = entry->logger;
+
+	if (logger && logger->open_count > 0 &&
+		dal_logger_should_log(logger, entry->major, entry->minor)) {
+
+		uint32_t size;
+		va_list args;
+		char buffer[DAL_LOGGER_BUFFER_MAX_LOG_LINE_SIZE];
+
+		va_start(args, msg);
+
+		size = dm_log_to_buffer(
+			buffer, DAL_LOGGER_BUFFER_MAX_LOG_LINE_SIZE, msg, args);
+
+		if (size < DAL_LOGGER_BUFFER_MAX_LOG_LINE_SIZE - 1) {
+			append_entry(entry, buffer, size);
+		} else {
+			append_entry(entry, "LOG_ERROR, line too long\n", 27);
+		}
+
+		va_end(args);
+	}
+}
+
+
+uint32_t dal_logger_read(
+	struct dal_logger *logger, /* <[in] */
+	uint32_t output_buffer_size, /* <[in] */
+	char *output_buffer, /* >[out] */
+	uint32_t *bytes_read, /* >[out] */
+	bool single_line)
+{
+	uint32_t bytes_remaining = 0;
+	uint32_t bytes_read_count = 0;
+	bool keep_reading = true;
+
+	if (!logger || output_buffer == NULL || output_buffer_size == 0) {
+		BREAK_TO_DEBUGGER();
+		*bytes_read = 0;
+		return 0;
+	}
+
+	lock(logger);
+
+	/* Read until null terminator (if single_line==true,
+	 *  max buffer size, or until we've read everything new
+	 */
+
+	do {
+		char cur;
+
+		/* Stop when we've read everything */
+		if (logger->buffer_read_offset ==
+			logger->buffer_write_offset) {
+
+			break;
+		}
+
+		cur = logger->log_buffer[logger->buffer_read_offset];
+		logger->buffer_read_offset++;
+
+		/* Wrap read pointer if at end */
+		if (logger->buffer_read_offset == logger->log_buffer_size) {
+
+			logger->buffer_read_offset = 0;
+			logger->read_wrap_count++;
+		}
+
+		/* Don't send null terminators to buffer */
+		if (cur != '\0') {
+			output_buffer[bytes_read_count] = cur;
+			bytes_read_count++;
+		} else if (single_line) {
+			keep_reading = false;
+		}
+
+	} while (bytes_read_count <= output_buffer_size && keep_reading);
+
+	/* We assume that reading can never be ahead of writing */
+	if (logger->write_wrap_count > logger->read_wrap_count) {
+		bytes_remaining = logger->log_buffer_size -
+			logger->buffer_read_offset +
+			logger->buffer_write_offset;
+	} else {
+		bytes_remaining = logger->buffer_write_offset -
+				logger->buffer_read_offset;
+	}
+
+	/* reset write/read wrap count to 0 if we've read everything */
+	if (bytes_remaining == 0) {
+
+		logger->write_wrap_count = 0;
+		logger->read_wrap_count = 0;
+	}
+
+	*bytes_read = bytes_read_count;
+	unlock(logger);
+
+	return bytes_remaining;
+}
+
+void dal_logger_open(
+		struct dal_logger *logger,
+		struct log_entry *entry, /* out */
+		enum log_major major,
+		enum log_minor minor)
+{
+	if (!entry) {
+		BREAK_TO_DEBUGGER();
+		return;
+	}
+
+	entry->major = LOG_MAJOR_COUNT;
+	entry->minor = 0;
+	entry->logger = logger;
+
+	entry->buf = dm_alloc(
+		logger->ctx,
+		DAL_LOGGER_BUFFER_MAX_SIZE * sizeof(char));
+
+	entry->buf_offset = 0;
+	entry->max_buf_bytes = DAL_LOGGER_BUFFER_MAX_SIZE * sizeof(char);
+
+	logger->open_count++;
+	entry->major = major;
+	entry->minor = minor;
+
+	log_heading(entry, major, minor);
+}
+
+void dal_logger_close(struct log_entry *entry)
+{
+	struct dal_logger *logger = entry->logger;
+
+
+	if (logger && logger->open_count > 0) {
+		logger->open_count--;
+	} else {
+		BREAK_TO_DEBUGGER();
+		goto cleanup;
+	}
+
+	/* --Flush log_entry buffer-- */
+	/* print to kernel console */
+	log_to_debug_console(entry);
+	/* log internally for dsat */
+	log_to_internal_buffer(entry);
+
+	/* TODO: Write end heading */
+
+cleanup:
+	if (entry->buf) {
+		dm_free(entry->logger->ctx, entry->buf);
+		entry->buf = NULL;
+		entry->buf_offset = 0;
+		entry->max_buf_bytes = 0;
+	}
+}
+
+uint32_t dal_logger_get_mask(
+	struct dal_logger *logger,
+	enum log_major lvl_major, enum log_minor lvl_minor)
+{
+	uint32_t log_mask = 0;
+
+	if (logger && lvl_major < LOG_MAJOR_COUNT)
+		log_mask = logger->log_enable_mask_minors[lvl_major];
+
+	log_mask &= 1 << lvl_minor;
+	return log_mask;
+}
+
+uint32_t dal_logger_set_mask(
+	struct dal_logger *logger,
+	enum log_major lvl_major, enum log_minor lvl_minor)
+{
+
+	if (logger && lvl_major < LOG_MAJOR_COUNT) {
+		if (lvl_minor == LOG_MINOR_MASK_ALL) {
+			logger->log_enable_mask_minors[lvl_major] = 0xFFFFFFFF;
+		} else {
+			logger->log_enable_mask_minors[lvl_major] |=
+				(1 << lvl_minor);
+		}
+		return 0;
+	}
+	return 1;
+}
+
+uint32_t dal_logger_get_masks(
+	struct dal_logger *logger,
+	enum log_major lvl_major)
+{
+	uint32_t log_mask = 0;
+
+	if (logger && lvl_major < LOG_MAJOR_COUNT)
+		log_mask = logger->log_enable_mask_minors[lvl_major];
+
+	return log_mask;
+}
+
+void dal_logger_set_masks(
+	struct dal_logger *logger,
+	enum log_major lvl_major, uint32_t log_mask)
+{
+	if (logger && lvl_major < LOG_MAJOR_COUNT)
+		logger->log_enable_mask_minors[lvl_major] = log_mask;
+}
+
+uint32_t dal_logger_unset_mask(
+	struct dal_logger *logger,
+	enum log_major lvl_major, enum log_minor lvl_minor)
+{
+
+	if (lvl_major < LOG_MAJOR_COUNT) {
+		if (lvl_minor == LOG_MINOR_MASK_ALL) {
+			logger->log_enable_mask_minors[lvl_major] = 0;
+		} else {
+			logger->log_enable_mask_minors[lvl_major] &=
+				~(1 << lvl_minor);
+		}
+		return 0;
+	}
+	return 1;
+}
+
+uint32_t dal_logger_get_flags(
+		struct dal_logger *logger)
+{
+
+	return logger->flags.value;
+}
+
+void dal_logger_set_flags(
+		struct dal_logger *logger,
+		union logger_flags flags)
+{
+
+	logger->flags = flags;
+}
+
+
+uint32_t dal_logger_get_buffer_size(struct dal_logger *logger)
+{
+	return DAL_LOGGER_BUFFER_MAX_SIZE;
+}
+
+uint32_t dal_logger_set_buffer_size(
+		struct dal_logger *logger,
+		uint32_t new_size)
+{
+	/* ToDo: implement dynamic size */
+
+	/* return new size */
+	return DAL_LOGGER_BUFFER_MAX_SIZE;
+}
+
+
+const struct log_major_info *dal_logger_enum_log_major_info(
+		struct dal_logger *logger,
+		unsigned int enum_index)
+{
+	const struct log_major_info *major_info;
+
+	if (enum_index >= NUM_ELEMENTS(log_major_mask_info_tbl))
+		return NULL;
+
+	major_info = &log_major_mask_info_tbl[enum_index].major_info;
+	return major_info;
+}
+
+const struct log_minor_info *dal_logger_enum_log_minor_info(
+		struct dal_logger *logger,
+		enum log_major major,
+		unsigned int enum_index)
+{
+	const struct log_minor_info *minor_info = NULL;
+	uint32_t i;
+
+	for (i = 0; i < NUM_ELEMENTS(log_major_mask_info_tbl); i++) {
+
+		const struct log_major_mask_info *maj_mask_info =
+				&log_major_mask_info_tbl[i];
+
+		if (maj_mask_info->major_info.major == major) {
+
+			if (maj_mask_info->minor_tbl != NULL) {
+				uint32_t j;
+
+				for (j = 0; j < maj_mask_info->tbl_element_cnt; j++) {
+
+					minor_info = &maj_mask_info->minor_tbl[j];
+
+					if (minor_info->minor == enum_index)
+						return minor_info;
+				}
+			}
+
+			break;
+		}
+	}
+	return NULL;
+
+}
+
diff --git a/drivers/gpu/drm/amd/dal/dc/basics/logger.h b/drivers/gpu/drm/amd/dal/dc/basics/logger.h
new file mode 100644
index 000000000000..fba5ec3264b6
--- /dev/null
+++ b/drivers/gpu/drm/amd/dal/dc/basics/logger.h
@@ -0,0 +1,64 @@ 
+/*
+ * 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_LOGGER_H__
+#define __DAL_LOGGER_H__
+
+/* Structure for keeping track of offsets, buffer, etc */
+
+#define DAL_LOGGER_BUFFER_MAX_SIZE 2048
+#define DAL_LOGGER_BUFFER_MAX_LOG_LINE_SIZE 256
+
+
+#include "include/logger_types.h"
+
+struct dal_logger {
+
+	/* How far into the circular buffer has been read by dsat
+	 * Read offset should never cross write offset. Write \0's to
+	 * read data just to be sure?
+	 */
+	uint32_t buffer_read_offset;
+
+	/* How far into the circular buffer we have written
+	 * Write offset should never cross read offset
+	 */
+	uint32_t buffer_write_offset;
+
+	uint32_t write_wrap_count;
+	uint32_t read_wrap_count;
+
+	uint32_t open_count;
+
+	char *log_buffer;	/* Pointer to malloc'ed buffer */
+	uint32_t log_buffer_size; /* Size of circular buffer */
+
+	uint32_t *log_enable_mask_minors; /*array of masks for major elements*/
+
+	union logger_flags flags;
+	struct dc_context *ctx;
+};
+
+#endif /* __DAL_LOGGER_H__ */
diff --git a/drivers/gpu/drm/amd/dal/dc/basics/register_logger.c b/drivers/gpu/drm/amd/dal/dc/basics/register_logger.c
new file mode 100644
index 000000000000..6d32b1bdf35c
--- /dev/null
+++ b/drivers/gpu/drm/amd/dal/dc/basics/register_logger.c
@@ -0,0 +1,197 @@ 
+/*
+ * Copyright 2012-15 Advanced Micro Devices, Inc.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
+ * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ *
+ * Authors: AMD
+ *
+ */
+
+#include "dm_services.h"
+#include "include/dal_types.h"
+#include "include/logger_interface.h"
+#include "logger.h"
+
+/******************************************************************************
+ * Register Logger.
+ * A facility to create register R/W logs.
+ * Currently used for DAL Test.
+ *****************************************************************************/
+
+/******************************************************************************
+ * Private structures
+ *****************************************************************************/
+struct dal_reg_dump_stack_location {
+	const char *current_caller_func;
+	long current_pid;
+	long current_tgid;
+	uint32_t rw_count;/* register access counter for current function. */
+};
+
+/* This the maximum number of nested calls to the 'reg_dump' facility. */
+#define DAL_REG_DUMP_STACK_MAX_SIZE 32
+
+struct dal_reg_dump_stack {
+	int32_t stack_pointer;
+	struct dal_reg_dump_stack_location
+		stack_locations[DAL_REG_DUMP_STACK_MAX_SIZE];
+	uint32_t total_rw_count; /* Total count for *all* functions. */
+};
+
+static struct dal_reg_dump_stack reg_dump_stack = {0};
+
+/******************************************************************************
+ * Private functions
+ *****************************************************************************/
+
+/* Check if current process is the one which requested register dump.
+ * The reason for the check:
+ * mmCRTC_STATUS_FRAME_COUNT is accessed by dal_controller_get_vblank_counter().
+ * Which runs all the time when at least one display is connected.
+ * (Triggered by drm_mode_page_flip_ioctl()). */
+static bool is_reg_dump_process(void)
+{
+	uint32_t i;
+
+	/* walk the list of our processes */
+	for (i = 0; i < reg_dump_stack.stack_pointer; i++) {
+		struct dal_reg_dump_stack_location *stack_location
+					= &reg_dump_stack.stack_locations[i];
+
+		if (stack_location->current_pid == dm_get_pid()
+			&& stack_location->current_tgid == dm_get_tgid())
+			return true;
+	}
+
+	return false;
+}
+
+static bool dal_reg_dump_stack_is_empty(void)
+{
+	if (reg_dump_stack.stack_pointer <= 0)
+		return true;
+	else
+		return false;
+}
+
+static struct dal_reg_dump_stack_location *dal_reg_dump_stack_push(void)
+{
+	struct dal_reg_dump_stack_location *current_location = NULL;
+
+	if (reg_dump_stack.stack_pointer >= DAL_REG_DUMP_STACK_MAX_SIZE) {
+		/* stack is full */
+		dm_output_to_console("[REG_DUMP]: %s: stack is full!\n",
+				__func__);
+	} else {
+		current_location =
+		&reg_dump_stack.stack_locations[reg_dump_stack.stack_pointer];
+		++reg_dump_stack.stack_pointer;
+	}
+
+	return current_location;
+}
+
+static struct dal_reg_dump_stack_location *dal_reg_dump_stack_pop(void)
+{
+	struct dal_reg_dump_stack_location *current_location = NULL;
+
+	if (dal_reg_dump_stack_is_empty()) {
+		/* stack is empty */
+		dm_output_to_console("[REG_DUMP]: %s: stack is empty!\n",
+				__func__);
+	} else {
+		--reg_dump_stack.stack_pointer;
+		current_location =
+		&reg_dump_stack.stack_locations[reg_dump_stack.stack_pointer];
+	}
+
+	return current_location;
+}
+
+/******************************************************************************
+ * Public functions
+ *****************************************************************************/
+
+void dal_reg_logger_push(const char *caller_func)
+{
+	struct dal_reg_dump_stack_location *free_stack_location;
+
+	free_stack_location = dal_reg_dump_stack_push();
+
+	if (NULL == free_stack_location)
+		return;
+
+	dm_memset(free_stack_location, 0, sizeof(*free_stack_location));
+
+	free_stack_location->current_caller_func = caller_func;
+	free_stack_location->current_pid = dm_get_pid();
+	free_stack_location->current_tgid = dm_get_tgid();
+
+	dm_output_to_console("[REG_DUMP]:%s - start (pid:%ld, tgid:%ld)\n",
+		caller_func,
+		free_stack_location->current_pid,
+		free_stack_location->current_tgid);
+}
+
+void dal_reg_logger_pop(void)
+{
+	struct dal_reg_dump_stack_location *top_stack_location;
+
+	top_stack_location = dal_reg_dump_stack_pop();
+
+	if (NULL == top_stack_location) {
+		dm_output_to_console("[REG_DUMP]:%s - Stack is Empty!\n",
+				__func__);
+		return;
+	}
+
+	dm_output_to_console(
+	"[REG_DUMP]:%s - end."\
+	" Reg R/W Count: Total=%d Function=%d. (pid:%ld, tgid:%ld)\n",
+			top_stack_location->current_caller_func,
+			reg_dump_stack.total_rw_count,
+			top_stack_location->rw_count,
+			dm_get_pid(),
+			dm_get_tgid());
+
+	dm_memset(top_stack_location, 0, sizeof(*top_stack_location));
+}
+
+void dal_reg_logger_rw_count_increment(void)
+{
+	++reg_dump_stack.total_rw_count;
+
+	++reg_dump_stack.stack_locations
+		[reg_dump_stack.stack_pointer - 1].rw_count;
+}
+
+bool dal_reg_logger_should_dump_register(void)
+{
+	if (true == dal_reg_dump_stack_is_empty())
+		return false;
+
+	if (false == is_reg_dump_process())
+		return false;
+
+	return true;
+}
+
+/******************************************************************************
+ * End of File.
+ *****************************************************************************/
diff --git a/drivers/gpu/drm/amd/dal/dc/basics/signal_types.c b/drivers/gpu/drm/amd/dal/dc/basics/signal_types.c
new file mode 100644
index 000000000000..44447e07803a
--- /dev/null
+++ b/drivers/gpu/drm/amd/dal/dc/basics/signal_types.c
@@ -0,0 +1,116 @@ 
+/*
+ * Copyright 2012-15 Advanced Micro Devices, Inc.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
+ * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ *
+ * Authors: AMD
+ *
+ */
+
+#include "dm_services.h"
+#include "include/signal_types.h"
+
+bool dc_is_hdmi_signal(enum signal_type signal)
+{
+	return (signal == SIGNAL_TYPE_HDMI_TYPE_A);
+}
+
+bool dc_is_dp_sst_signal(enum signal_type signal)
+{
+	return (signal == SIGNAL_TYPE_DISPLAY_PORT ||
+		signal == SIGNAL_TYPE_EDP);
+}
+
+bool dc_is_dp_signal(enum signal_type signal)
+{
+	return (signal == SIGNAL_TYPE_DISPLAY_PORT ||
+		signal == SIGNAL_TYPE_EDP ||
+		signal == SIGNAL_TYPE_DISPLAY_PORT_MST);
+}
+
+bool dc_is_dp_external_signal(enum signal_type signal)
+{
+	return (signal == SIGNAL_TYPE_DISPLAY_PORT ||
+		signal == SIGNAL_TYPE_DISPLAY_PORT_MST);
+}
+
+bool dc_is_analog_signal(enum signal_type signal)
+{
+	switch (signal) {
+	case SIGNAL_TYPE_RGB:
+		return true;
+	break;
+	default:
+		return false;
+	}
+}
+
+bool dc_is_embedded_signal(enum signal_type signal)
+{
+	return (signal == SIGNAL_TYPE_EDP || signal == SIGNAL_TYPE_LVDS);
+}
+
+bool dc_is_dvi_signal(enum signal_type signal)
+{
+	switch (signal) {
+	case SIGNAL_TYPE_DVI_SINGLE_LINK:
+	case SIGNAL_TYPE_DVI_DUAL_LINK:
+		return true;
+	break;
+	default:
+		return false;
+	}
+}
+
+bool dc_is_dvi_single_link_signal(enum signal_type signal)
+{
+	return (signal == SIGNAL_TYPE_DVI_SINGLE_LINK);
+}
+
+bool dc_is_dual_link_signal(enum signal_type signal)
+{
+	return (signal == SIGNAL_TYPE_DVI_DUAL_LINK);
+}
+
+bool dc_is_audio_capable_signal(enum signal_type signal)
+{
+	return (signal == SIGNAL_TYPE_DISPLAY_PORT ||
+		signal == SIGNAL_TYPE_DISPLAY_PORT_MST ||
+		dc_is_hdmi_signal(signal) ||
+		signal == SIGNAL_TYPE_WIRELESS);
+}
+
+/*
+ * @brief
+ * Returns whether the signal is compatible
+ * with other digital encoder signal types.
+ * This is true for DVI, LVDS, and HDMI signal types.
+ */
+bool dc_is_digital_encoder_compatible_signal(enum signal_type signal)
+{
+	switch (signal) {
+	case SIGNAL_TYPE_DVI_SINGLE_LINK:
+	case SIGNAL_TYPE_DVI_DUAL_LINK:
+	case SIGNAL_TYPE_HDMI_TYPE_A:
+	case SIGNAL_TYPE_LVDS:
+		return true;
+	default:
+		return false;
+	}
+}
diff --git a/drivers/gpu/drm/amd/dal/dc/basics/vector.c b/drivers/gpu/drm/amd/dal/dc/basics/vector.c
new file mode 100644
index 000000000000..32ca6b13a3bd
--- /dev/null
+++ b/drivers/gpu/drm/amd/dal/dc/basics/vector.c
@@ -0,0 +1,309 @@ 
+/*
+ * Copyright 2012-15 Advanced Micro Devices, Inc.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
+ * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ *
+ * Authors: AMD
+ *
+ */
+
+#include "dm_services.h"
+#include "include/vector.h"
+
+bool dal_vector_construct(
+	struct vector *vector,
+	struct dc_context *ctx,
+	uint32_t capacity,
+	uint32_t struct_size)
+{
+	vector->container = NULL;
+
+	if (!struct_size || !capacity) {
+		/* Container must be non-zero size*/
+		BREAK_TO_DEBUGGER();
+		return false;
+	}
+
+	vector->container = dm_alloc(ctx, struct_size * capacity);
+	if (vector->container == NULL)
+		return false;
+	vector->capacity = capacity;
+	vector->struct_size = struct_size;
+	vector->count = 0;
+	vector->ctx = ctx;
+	return true;
+}
+
+bool dal_vector_presized_costruct(
+	struct vector *vector,
+	struct dc_context *ctx,
+	uint32_t count,
+	void *initial_value,
+	uint32_t struct_size)
+{
+	uint32_t i;
+
+	vector->container = NULL;
+
+	if (!struct_size || !count) {
+		/* Container must be non-zero size*/
+		BREAK_TO_DEBUGGER();
+		return false;
+	}
+
+	vector->container = dm_alloc(ctx, struct_size * count);
+
+	if (vector->container == NULL)
+		return false;
+
+	/* If caller didn't supply initial value then the default
+	 * of all zeros is expected, which is exactly what dal_alloc()
+	 * initialises the memory to. */
+	if (NULL != initial_value) {
+		for (i = 0; i < count; ++i)
+			dm_memmove(
+				vector->container + i * struct_size,
+				initial_value,
+				struct_size);
+	}
+
+	vector->capacity = count;
+	vector->struct_size = struct_size;
+	vector->count = count;
+	return true;
+}
+
+struct vector *dal_vector_presized_create(
+	struct dc_context *ctx,
+	uint32_t size,
+	void *initial_value,
+	uint32_t struct_size)
+{
+	struct vector *vector = dm_alloc(ctx, sizeof(struct vector));
+
+	if (vector == NULL)
+		return NULL;
+
+	if (dal_vector_presized_costruct(
+		vector, ctx, size, initial_value, struct_size))
+		return vector;
+
+	BREAK_TO_DEBUGGER();
+	dm_free(ctx, vector);
+	return NULL;
+}
+
+struct vector *dal_vector_create(
+	struct dc_context *ctx,
+	uint32_t capacity,
+	uint32_t struct_size)
+{
+	struct vector *vector = dm_alloc(ctx, sizeof(struct vector));
+
+	if (vector == NULL)
+		return NULL;
+
+	if (dal_vector_construct(vector, ctx, capacity, struct_size))
+		return vector;
+
+
+	BREAK_TO_DEBUGGER();
+	dm_free(ctx, vector);
+	return NULL;
+}
+
+void dal_vector_destruct(
+	struct vector *vector)
+{
+	if (vector->container != NULL)
+		dm_free(vector->ctx, vector->container);
+	vector->count = 0;
+	vector->capacity = 0;
+}
+
+void dal_vector_destroy(
+	struct vector **vector)
+{
+	if (vector == NULL || *vector == NULL)
+		return;
+	dal_vector_destruct(*vector);
+	dm_free((*vector)->ctx, *vector);
+	*vector = NULL;
+}
+
+uint32_t dal_vector_get_count(
+	const struct vector *vector)
+{
+	return vector->count;
+}
+
+void *dal_vector_at_index(
+	const struct vector *vector,
+	uint32_t index)
+{
+	if (vector->container == NULL || index >= vector->count)
+		return NULL;
+	return vector->container + (index * vector->struct_size);
+}
+
+bool dal_vector_remove_at_index(
+	struct vector *vector,
+	uint32_t index)
+{
+	if (index >= vector->count)
+		return false;
+
+	if (index != vector->count - 1)
+		dm_memmove(
+			vector->container + (index * vector->struct_size),
+			vector->container + ((index + 1) * vector->struct_size),
+			(vector->count - index - 1) * vector->struct_size);
+	vector->count -= 1;
+
+	return true;
+}
+
+void dal_vector_set_at_index(
+	const struct vector *vector,
+	const void *what,
+	uint32_t index)
+{
+	void *where = dal_vector_at_index(vector, index);
+
+	if (!where) {
+		BREAK_TO_DEBUGGER();
+		return;
+	}
+	dm_memmove(
+		where,
+		what,
+		vector->struct_size);
+}
+
+static inline uint32_t calc_increased_capacity(
+	uint32_t old_capacity)
+{
+	return old_capacity * 2;
+}
+
+bool dal_vector_insert_at(
+	struct vector *vector,
+	const void *what,
+	uint32_t position)
+{
+	uint8_t *insert_address;
+
+	if (vector->count == vector->capacity) {
+		if (!dal_vector_reserve(
+			vector,
+			calc_increased_capacity(vector->capacity)))
+			return false;
+	}
+
+	insert_address = vector->container + (vector->struct_size * position);
+
+	if (vector->count && position < vector->count)
+		dm_memmove(
+			insert_address + vector->struct_size,
+			insert_address,
+			vector->struct_size * (vector->count - position));
+
+	dm_memmove(
+		insert_address,
+		what,
+		vector->struct_size);
+
+	vector->count++;
+
+	return true;
+}
+
+bool dal_vector_append(
+	struct vector *vector,
+	const void *item)
+{
+	return dal_vector_insert_at(vector, item, vector->count);
+}
+
+struct vector *dal_vector_clone(
+	const struct vector *vector)
+{
+	struct vector *vec_cloned;
+	uint32_t count;
+
+	/* create new vector */
+	count = dal_vector_get_count(vector);
+
+	if (count == 0)
+		/* when count is 0 we still want to create clone of the vector
+		 */
+		vec_cloned = dal_vector_create(
+			vector->ctx,
+			vector->capacity,
+			vector->struct_size);
+	else
+		/* Call "presized create" version, independently of how the
+		 * original vector was created.
+		 * The owner of original vector must know how to treat the new
+		 * vector - as "presized" or as "regular".
+		 * But from vector point of view it doesn't matter. */
+		vec_cloned = dal_vector_presized_create(vector->ctx, count,
+			NULL,/* no initial value */
+			vector->struct_size);
+
+	if (NULL == vec_cloned) {
+		BREAK_TO_DEBUGGER();
+		return NULL;
+	}
+
+	/* copy vector's data */
+	dm_memmove(vec_cloned->container, vector->container,
+			vec_cloned->struct_size * vec_cloned->capacity);
+
+	return vec_cloned;
+}
+
+uint32_t dal_vector_capacity(const struct vector *vector)
+{
+	return vector->capacity;
+}
+
+bool dal_vector_reserve(struct vector *vector, uint32_t capacity)
+{
+	void *new_container;
+
+	if (capacity <= vector->capacity)
+		return true;
+
+	new_container = dm_realloc(vector->ctx, vector->container,
+		capacity * vector->struct_size);
+
+	if (new_container) {
+		vector->container = new_container;
+		vector->capacity = capacity;
+		return true;
+	}
+
+	return false;
+}
+
+void dal_vector_clear(struct vector *vector)
+{
+	vector->count = 0;
+}