summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorHarry Wentland <harry.wentland@amd.com>2015-12-17 09:56:11 -0500
committerAlex Deucher <alexander.deucher@amd.com>2016-03-09 14:36:28 -0500
commit05af5e4eadafa72ce57172b9736f471043acffdd (patch)
treeda2a7811c6273d7b8eef26acdf0c8de46b32ec0b
parentdf37711de5453c0104d4c2b08a79976a092ee489 (diff)
drm/amd/dal: Add DAL Basic Types and Logger
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> Signed-off-by: Alex Deucher <alexander.deucher@amd.com>
-rw-r--r--drivers/gpu/drm/amd/dal/Kconfig48
-rw-r--r--drivers/gpu/drm/amd/dal/Makefile21
-rw-r--r--drivers/gpu/drm/amd/dal/dc/basics/Makefile10
-rw-r--r--drivers/gpu/drm/amd/dal/dc/basics/conversion.c224
-rw-r--r--drivers/gpu/drm/amd/dal/dc/basics/conversion.h49
-rw-r--r--drivers/gpu/drm/amd/dal/dc/basics/grph_object_id.c134
-rw-r--r--drivers/gpu/drm/amd/dal/dc/basics/logger.c954
-rw-r--r--drivers/gpu/drm/amd/dal/dc/basics/logger.h64
-rw-r--r--drivers/gpu/drm/amd/dal/dc/basics/register_logger.c197
-rw-r--r--drivers/gpu/drm/amd/dal/dc/basics/signal_types.c116
-rw-r--r--drivers/gpu/drm/amd/dal/dc/basics/vector.c309
11 files changed, 2126 insertions, 0 deletions
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;
+}