summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorHarry Wentland <harry.wentland@amd.com>2015-12-17 14:13:44 -0500
committerAlex Deucher <alexander.deucher@amd.com>2016-03-09 14:37:25 -0500
commit16fc6c8fe4fc0aa5b1b78b795810e86a9e2917ea (patch)
treeaa119d7caefef267a8ad704822036c9da0128ab9
parenta51e4d607f87d52764befeb3bd1b81cc30522de0 (diff)
drm/amd/dal: Adapter Service
Provides information about ASIC features and capabilities. Also provides access to ASIC resources such as VBIOS, GPIO and I2cAux Manager 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/dc/adapter/Makefile24
-rw-r--r--drivers/gpu/drm/amd/dal/dc/adapter/adapter_service.c2089
-rw-r--r--drivers/gpu/drm/amd/dal/dc/adapter/adapter_service.h71
-rw-r--r--drivers/gpu/drm/amd/dal/dc/adapter/dce110/hw_ctx_adapter_service_dce110.c304
-rw-r--r--drivers/gpu/drm/amd/dal/dc/adapter/dce110/hw_ctx_adapter_service_dce110.h40
-rw-r--r--drivers/gpu/drm/amd/dal/dc/adapter/diagnostics/hw_ctx_adapter_service_diag.c133
-rw-r--r--drivers/gpu/drm/amd/dal/dc/adapter/diagnostics/hw_ctx_adapter_service_diag.h33
-rw-r--r--drivers/gpu/drm/amd/dal/dc/adapter/hw_ctx_adapter_service.c164
-rw-r--r--drivers/gpu/drm/amd/dal/dc/adapter/hw_ctx_adapter_service.h86
-rw-r--r--drivers/gpu/drm/amd/dal/dc/adapter/wireless_data_source.c208
-rw-r--r--drivers/gpu/drm/amd/dal/dc/adapter/wireless_data_source.h80
11 files changed, 3232 insertions, 0 deletions
diff --git a/drivers/gpu/drm/amd/dal/dc/adapter/Makefile b/drivers/gpu/drm/amd/dal/dc/adapter/Makefile
new file mode 100644
index 000000000000..2c6ca7a513bd
--- /dev/null
+++ b/drivers/gpu/drm/amd/dal/dc/adapter/Makefile
@@ -0,0 +1,24 @@
+#
+# Makefile for the 'adapter' sub-component of DAL.
+# It provides the control and status of HW adapter.
+
+ADAPTER = adapter_service.o hw_ctx_adapter_service.o wireless_data_source.o
+
+AMD_DAL_ADAPTER = $(addprefix $(AMDDALPATH)/dc/adapter/,$(ADAPTER))
+
+AMD_DAL_FILES += $(AMD_DAL_ADAPTER)
+
+
+###############################################################################
+# DCE 11x
+###############################################################################
+
+ifdef CONFIG_DRM_AMD_DAL_DCE11_0
+AMD_DAL_FILES += $(AMDDALPATH)/dc/adapter/dce110/hw_ctx_adapter_service_dce110.o
+endif
+
+###############################################################################
+# FPGA Diagnositcs
+###############################################################################
+
+AMD_DAL_FILES += $(AMDDALPATH)/dc/adapter/diagnostics/hw_ctx_adapter_service_diag.o
diff --git a/drivers/gpu/drm/amd/dal/dc/adapter/adapter_service.c b/drivers/gpu/drm/amd/dal/dc/adapter/adapter_service.c
new file mode 100644
index 000000000000..dd2f931fe9a1
--- /dev/null
+++ b/drivers/gpu/drm/amd/dal/dc/adapter/adapter_service.c
@@ -0,0 +1,2089 @@
+/*
+ * 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 "dc_bios_types.h"
+
+#include "include/adapter_service_interface.h"
+#include "include/i2caux_interface.h"
+#include "include/asic_capability_types.h"
+#include "include/gpio_service_interface.h"
+#include "include/asic_capability_interface.h"
+#include "include/logger_interface.h"
+
+#include "adapter_service.h"
+
+#include "hw_ctx_adapter_service.h"
+#include "wireless_data_source.h"
+
+#include "atom.h"
+
+#if defined(CONFIG_DRM_AMD_DAL_DCE11_0)
+#include "dce110/hw_ctx_adapter_service_dce110.h"
+#endif
+
+#include "diagnostics/hw_ctx_adapter_service_diag.h"
+
+/*
+ * Adapter service feature entry table.
+ *
+ * This is an array of features that is used to generate feature set. Each
+ * entry consists three element:
+ *
+ * Feature name, default value, and if this feature is a boolean type. A
+ * feature can only be a boolean or int type.
+ *
+ * Example 1: a boolean type feature
+ * FEATURE_ENABLE_HW_EDID_POLLING, false, true
+ *
+ * First element is feature name: EATURE_ENABLE_HW_EDID_POLLING, it has a
+ * default value 0, and it is a boolean feature.
+ *
+ * Example 2: an int type feature
+ * FEATURE_DCP_PROGRAMMING_WA, 0x1FF7, false
+ *
+ * In this case, the default value is 0x1FF7 and not a boolean type, which
+ * makes it an int type.
+ */
+
+static struct feature_source_entry feature_entry_table[] = {
+ /* Feature name | default value | is boolean type */
+ {FEATURE_ENABLE_HW_EDID_POLLING, false, true},
+ {FEATURE_DP_SINK_DETECT_POLL_DATA_PIN, false, true},
+ {FEATURE_UNDERFLOW_INTERRUPT, false, true},
+ {FEATURE_ALLOW_WATERMARK_ADJUSTMENT, false, true},
+ {FEATURE_LIGHT_SLEEP, false, true},
+ {FEATURE_DCP_DITHER_FRAME_RANDOM_ENABLE, false, true},
+ {FEATURE_DCP_DITHER_RGB_RANDOM_ENABLE, false, true},
+ {FEATURE_DCP_DITHER_HIGH_PASS_RANDOM_ENABLE, false, true},
+ {FEATURE_LINE_BUFFER_ENHANCED_PIXEL_DEPTH, false, true},
+ {FEATURE_MAXIMIZE_URGENCY_WATERMARKS, false, true},
+ {FEATURE_MAXIMIZE_STUTTER_MARKS, false, true},
+ {FEATURE_MAXIMIZE_NBP_MARKS, false, true},
+ /*
+ * We meet HW I2C issue when test S3 resume on KB.
+ * An EPR is created for debug the issue.
+ * Make Test has already been implemented
+ * with HW I2C. The work load for revert back to SW I2C in make test
+ * is big. Below is workaround for this issue.
+ * Driver uses SW I2C.
+ * Make Test uses HW I2C.
+ */
+ {FEATURE_RESTORE_USAGE_I2C_SW_ENGINE, false, true},
+ {FEATURE_USE_MAX_DISPLAY_CLK, false, true},
+ {FEATURE_ALLOW_EDP_RESOURCE_SHARING, false, true},
+ {FEATURE_SUPPORT_DP_YUV, false, true},
+ {FEATURE_SUPPORT_DP_Y_ONLY, false, true},
+ {FEATURE_DISABLE_DP_GTC_SYNC, true, true},
+ {FEATURE_MODIFY_TIMINGS_FOR_WIRELESS, false, true},
+ {FEATURE_DCP_BIT_DEPTH_REDUCTION_MODE, 0, false},
+ {FEATURE_DCP_DITHER_MODE, 0, false},
+ {FEATURE_DCP_PROGRAMMING_WA, 0, false},
+ {FEATURE_NO_HPD_LOW_POLLING_VCC_OFF, false, true},
+ {FEATURE_ENABLE_DFS_BYPASS, false, true},
+ {FEATURE_WIRELESS_FULL_TIMING_ADJUSTMENT, false, true},
+ {FEATURE_MAX_COFUNC_NON_DP_DISPLAYS, 2, false},
+ {FEATURE_WIRELESS_LIMIT_720P, false, true},
+ {FEATURE_MODIFY_TIMINGS_FOR_WIRELESS, false, true},
+ {FEATURE_SUPPORTED_HDMI_CONNECTION_NUM, 0, false},
+ {FEATURE_DETECT_REQUIRE_HPD_HIGH, false, true},
+ {FEATURE_NO_HPD_LOW_POLLING_VCC_OFF, false, true},
+ {FEATURE_LB_HIGH_RESOLUTION, false, true},
+ {FEATURE_MAX_CONTROLLER_NUM, 0, false},
+ {FEATURE_DRR_SUPPORT, AS_DRR_SUPPORT_ENABLED, false},
+ {FEATURE_STUTTER_MODE, 15, false},
+ {FEATURE_DP_DISPLAY_FORCE_SS_ENABLE, false, true},
+ {FEATURE_REPORT_CE_MODE_ONLY, false, true},
+ {FEATURE_ALLOW_OPTIMIZED_MODE_AS_DEFAULT, false, true},
+ {FEATURE_DDC_READ_FORCE_REPEATED_START, false, true},
+ {FEATURE_FORCE_TIMING_RESYNC, false, true},
+ {FEATURE_TMDS_DISABLE_DITHERING, false, true},
+ {FEATURE_HDMI_DISABLE_DITHERING, false, true},
+ {FEATURE_DP_DISABLE_DITHERING, false, true},
+ {FEATURE_EMBEDDED_DISABLE_DITHERING, true, true},
+ {FEATURE_ALLOW_SELF_REFRESH, false, true},
+ {FEATURE_ALLOW_DYNAMIC_PIXEL_ENCODING_CHANGE, false, true},
+ {FEATURE_ALLOW_HSYNC_VSYNC_ADJUSTMENT, false, true},
+ {FEATURE_FORCE_PSR, false, true},
+ {FEATURE_PSR_SETUP_TIME_TEST, 0, false},
+ {FEATURE_POWER_GATING_PIPE_IN_TILE, true, true},
+ {FEATURE_POWER_GATING_LB_PORTION, true, true},
+ {FEATURE_PREFER_3D_TIMING, false, true},
+ {FEATURE_VARI_BRIGHT_ENABLE, true, true},
+ {FEATURE_PSR_ENABLE, false, true},
+ {FEATURE_WIRELESS_ENABLE_COMPRESSED_AUDIO, false, true},
+ {FEATURE_WIRELESS_INCLUDE_UNVERIFIED_TIMINGS, true, true},
+ {FEATURE_EDID_STRESS_READ, false, true},
+ {FEATURE_DP_FRAME_PACK_STEREO3D, false, true},
+ {FEATURE_DISPLAY_PREFERRED_VIEW, 0, false},
+ {FEATURE_ALLOW_HDMI_WITHOUT_AUDIO, false, true},
+ {FEATURE_ABM_2_0, false, true},
+ {FEATURE_SUPPORT_MIRABILIS, false, true},
+ {FEATURE_OPTIMIZATION, 0xFFFF, false},
+ {FEATURE_PERF_MEASURE, 0, false},
+ {FEATURE_MIN_BACKLIGHT_LEVEL, 0, false},
+ {FEATURE_MAX_BACKLIGHT_LEVEL, 255, false},
+ {FEATURE_LOAD_DMCU_FIRMWARE, true, true},
+ {FEATURE_DISABLE_AZ_CLOCK_GATING, false, true},
+ {FEATURE_ENABLE_GPU_SCALING, false, true},
+ {FEATURE_DONGLE_SINK_COUNT_CHECK, true, true},
+ {FEATURE_INSTANT_UP_SCALE_DOWN_SCALE, false, true},
+ {FEATURE_TILED_DISPLAY, false, true},
+ {FEATURE_PREFERRED_ABM_CONFIG_SET, 0, false},
+ {FEATURE_CHANGE_SW_I2C_SPEED, 50, false},
+ {FEATURE_CHANGE_HW_I2C_SPEED, 50, false},
+ {FEATURE_CHANGE_I2C_SPEED_CONTROL, false, true},
+ {FEATURE_DEFAULT_PSR_LEVEL, 0, false},
+ {FEATURE_MAX_CLOCK_SOURCE_NUM, 0, false},
+ {FEATURE_REPORT_SINGLE_SELECTED_TIMING, false, true},
+ {FEATURE_ALLOW_HDMI_HIGH_CLK_DP_DONGLE, true, true},
+ {FEATURE_SUPPORT_EXTERNAL_PANEL_DRR, false, true},
+ {FEATURE_LVDS_SAFE_PIXEL_CLOCK_RANGE, 0, false},
+ {FEATURE_ABM_CONFIG, 0, false},
+ {FEATURE_WIRELESS_ENABLE, false, true},
+ {FEATURE_ALLOW_DIRECT_MEMORY_ACCESS_TRIG, false, true},
+ {FEATURE_FORCE_STATIC_SCREEN_EVENT_TRIGGERS, 0, false},
+ {FEATURE_USE_PPLIB, true, true},
+ {FEATURE_DISABLE_LPT_SUPPORT, false, true},
+ {FEATURE_DUMMY_FBC_BACKEND, false, true},
+ {FEATURE_DPMS_AUDIO_ENDPOINT_CONTROL, true, true},
+ {FEATURE_DISABLE_FBC_COMP_CLK_GATE, false, true},
+ {FEATURE_PIXEL_PERFECT_OUTPUT, false, true},
+ {FEATURE_8BPP_SUPPORTED, false, true}
+};
+
+
+/* Stores entire ASIC features by sets */
+uint32_t adapter_feature_set[FEATURE_MAXIMUM/32];
+
+enum {
+ LEGACY_MAX_NUM_OF_CONTROLLERS = 2,
+ DEFAULT_NUM_COFUNC_NON_DP_DISPLAYS = 2
+};
+
+/*
+ * get_feature_entries_num
+ *
+ * Get number of feature entries
+ */
+static inline uint32_t get_feature_entries_num(void)
+{
+ return ARRAY_SIZE(feature_entry_table);
+}
+
+static void get_platform_info_methods(
+ struct adapter_service *as)
+{
+ struct platform_info_params params;
+ uint32_t mask = 0;
+
+ params.data = &mask;
+ params.method = PM_GET_AVAILABLE_METHODS;
+
+ if (dm_get_platform_info(as->ctx, &params))
+ as->platform_methods_mask = mask;
+
+
+}
+
+static void initialize_backlight_caps(
+ struct adapter_service *as)
+{
+ struct firmware_info fw_info;
+ struct embedded_panel_info panel_info;
+ struct platform_info_ext_brightness_caps caps;
+ struct platform_info_params params;
+ bool custom_curve_present = false;
+ bool custom_min_max_present = false;
+ struct dc_bios *dcb = dal_adapter_service_get_bios_parser(as);
+
+ if (!(PM_GET_EXTENDED_BRIGHNESS_CAPS & as->platform_methods_mask)) {
+ dal_logger_write(as->ctx->logger,
+ LOG_MAJOR_BACKLIGHT,
+ LOG_MINOR_BACKLIGHT_BRIGHTESS_CAPS,
+ "This method is not supported\n");
+ return;
+ }
+
+ if (dcb->funcs->get_firmware_info(dcb, &fw_info) != BP_RESULT_OK ||
+ dcb->funcs->get_embedded_panel_info(dcb, &panel_info) != BP_RESULT_OK)
+ return;
+
+ params.data = &caps;
+ params.method = PM_GET_EXTENDED_BRIGHNESS_CAPS;
+
+ if (dm_get_platform_info(as->ctx, &params)) {
+ as->ac_level_percentage = caps.basic_caps.ac_level_percentage;
+ as->dc_level_percentage = caps.basic_caps.dc_level_percentage;
+ custom_curve_present = (caps.data_points_num > 0);
+ custom_min_max_present = true;
+ } else
+ return;
+ /* Choose minimum backlight level base on priority:
+ * extended caps,VBIOS,default */
+ if (custom_min_max_present)
+ as->backlight_8bit_lut[0] = caps.min_input_signal;
+
+ else if (fw_info.min_allowed_bl_level > 0)
+ as->backlight_8bit_lut[0] = fw_info.min_allowed_bl_level;
+
+ else
+ as->backlight_8bit_lut[0] = DEFAULT_MIN_BACKLIGHT;
+
+ /* Choose maximum backlight level base on priority:
+ * extended caps,default */
+ if (custom_min_max_present)
+ as->backlight_8bit_lut[100] = caps.max_input_signal;
+
+ else
+ as->backlight_8bit_lut[100] = DEFAULT_MAX_BACKLIGHT;
+
+ if (as->backlight_8bit_lut[100] > ABSOLUTE_BACKLIGHT_MAX)
+ as->backlight_8bit_lut[100] = ABSOLUTE_BACKLIGHT_MAX;
+
+ if (as->backlight_8bit_lut[0] > as->backlight_8bit_lut[100])
+ as->backlight_8bit_lut[0] = as->backlight_8bit_lut[100];
+
+ if (custom_curve_present) {
+ uint16_t index = 1;
+ uint16_t i;
+ uint16_t num_of_data_points = (caps.data_points_num <= 99 ?
+ caps.data_points_num : 99);
+ /* Filling translation table from data points -
+ * between every two provided data points we
+ * lineary interpolate missing values
+ */
+ for (i = 0 ; i < num_of_data_points; i++) {
+ uint16_t luminance = caps.data_points[i].luminance;
+ uint16_t signal_level =
+ caps.data_points[i].signal_level;
+
+ if (signal_level < as->backlight_8bit_lut[0])
+ signal_level = as->backlight_8bit_lut[0];
+
+ if (signal_level > as->backlight_8bit_lut[100])
+ signal_level = as->backlight_8bit_lut[100];
+
+ /* Lineary interpolate missing values */
+ if (index < luminance) {
+ uint16_t base_value =
+ as->backlight_8bit_lut[index-1];
+ uint16_t delta_signal =
+ signal_level - base_value;
+ uint16_t delta_luma = luminance - index + 1;
+ uint16_t step = delta_signal;
+
+ for (; index < luminance ; index++) {
+ as->backlight_8bit_lut[index] =
+ base_value +
+ (step / delta_luma);
+ step += delta_signal;
+ }
+ }
+ /* Now [index == luminance], so we can add
+ * data point to the translation table */
+ as->backlight_8bit_lut[index++] = signal_level;
+ }
+ /* Complete the final segment of interpolation -
+ * between last datapoint and maximum value */
+ if (index < 100) {
+ uint16_t base_value = as->backlight_8bit_lut[index-1];
+ uint16_t delta_signal =
+ as->backlight_8bit_lut[100]-base_value;
+ uint16_t delta_luma = 100 - index + 1;
+ uint16_t step = delta_signal;
+
+ for (; index < 100 ; index++) {
+ as->backlight_8bit_lut[index] = base_value +
+ (step / delta_luma);
+ step += delta_signal;
+ }
+ }
+ }
+ /* build backlight translation table based on default curve */
+ else {
+ /* Default backlight curve can be defined by
+ * polinomial F(x) = A(x*x) + Bx + C.
+ * Backlight curve should always satisfy
+ * F(0) = min, F(100) = max, so polinomial coefficients are:
+ * A is 0.0255 - B/100 - min/10000 -
+ * (255-max)/10000 = (max - min)/10000 - B/100
+ * B is adjustable factor to modify the curve.
+ * Bigger B results in less concave curve.
+ * B range is [0..(max-min)/100]
+ * C is backlight minimum
+ */
+ uint16_t delta = as->backlight_8bit_lut[100] -
+ as->backlight_8bit_lut[0];
+ uint16_t coeffc = as->backlight_8bit_lut[0];
+ uint16_t coeffb = (BACKLIGHT_CURVE_COEFFB < delta ?
+ BACKLIGHT_CURVE_COEFFB : delta);
+ uint16_t coeffa = delta - coeffb;
+ uint16_t i;
+ uint32_t temp;
+
+ for (i = 1; i < 100 ; i++) {
+ temp = (coeffa * i * i) / BACKLIGHT_CURVE_COEFFA_FACTOR;
+ as->backlight_8bit_lut[i] = temp + (coeffb * i) /
+ BACKLIGHT_CURVE_COEFFB_FACTOR + coeffc;
+ }
+ }
+ as->backlight_caps_initialized = true;
+}
+
+static void log_overriden_features(
+ struct adapter_service *as,
+ const char *feature_name,
+ enum adapter_feature_id id,
+ bool bool_feature,
+ uint32_t value)
+{
+ if (bool_feature)
+ dal_logger_write(as->ctx->logger,
+ LOG_MAJOR_FEATURE_OVERRIDE,
+ LOG_MINOR_FEATURE_OVERRIDE,
+ "Overridden %s is %s now\n",
+ feature_name,
+ (value == 0) ? "disabled" : "enabled");
+ else
+ dal_logger_write(as->ctx->logger,
+ LOG_MAJOR_FEATURE_OVERRIDE,
+ LOG_MINOR_FEATURE_OVERRIDE,
+ "Overridden %s new value: %d\n",
+ feature_name,
+ value);
+}
+
+/*************************************
+ * Local static functions definition *
+ *************************************/
+
+#define check_bool_feature(feature) \
+case FEATURE_ ## feature: \
+ if (param->bool_param_enable_mask & \
+ (1 << DAL_PARAM_ ## feature)) { \
+ *data = param->bool_param_values & \
+ (1 << DAL_PARAM_ ## feature); \
+ ret = true; \
+ feature_name = "FEATURE_" #feature; \
+ } \
+ break
+
+#define check_int_feature(feature) \
+case FEATURE_ ## feature: \
+ if (param->int_param_values[DAL_PARAM_ ## feature] != \
+ DAL_PARAM_INVALID_INT) { \
+ *data = param->int_param_values[DAL_PARAM_ ## feature];\
+ ret = true;\
+ bool_feature = false;\
+ feature_name = "FEATURE_" #feature;\
+ } \
+ break
+
+/*
+ * override_default_parameters
+ *
+ * Override features (from runtime parameter)
+ * corresponding to Adapter Service Feature ID
+ */
+static bool override_default_parameters(
+ struct adapter_service *as,
+ const struct dal_override_parameters *param,
+ const uint32_t idx,
+ uint32_t *data)
+{
+ bool ret = false;
+ bool bool_feature = true;
+ char *feature_name;
+
+ if (idx >= get_feature_entries_num()) {
+ ASSERT_CRITICAL(false);
+ return false;
+ }
+
+ switch (feature_entry_table[idx].feature_id) {
+ check_int_feature(MAX_COFUNC_NON_DP_DISPLAYS);
+ check_int_feature(DRR_SUPPORT);
+ check_bool_feature(LIGHT_SLEEP);
+ check_bool_feature(MAXIMIZE_STUTTER_MARKS);
+ check_bool_feature(MAXIMIZE_URGENCY_WATERMARKS);
+ check_bool_feature(USE_MAX_DISPLAY_CLK);
+ check_bool_feature(ENABLE_DFS_BYPASS);
+ check_bool_feature(POWER_GATING_PIPE_IN_TILE);
+ check_bool_feature(POWER_GATING_LB_PORTION);
+ check_bool_feature(PSR_ENABLE);
+ check_bool_feature(VARI_BRIGHT_ENABLE);
+ check_bool_feature(USE_PPLIB);
+ check_bool_feature(DISABLE_LPT_SUPPORT);
+ check_bool_feature(DUMMY_FBC_BACKEND);
+ check_bool_feature(ENABLE_GPU_SCALING);
+ default:
+ return false;
+ }
+ if (ret)
+ log_overriden_features(
+ as,
+ feature_name,
+ feature_entry_table[idx].feature_id,
+ bool_feature,
+ *data);
+
+ return ret;
+}
+
+/*
+ * get_feature_value_from_data_sources
+ *
+ * For a given feature, determine its value from ASIC cap and wireless
+ * data source.
+ * idx : index of feature_entry_table for the feature id.
+ */
+static bool get_feature_value_from_data_sources(
+ const struct adapter_service *as,
+ const uint32_t idx,
+ uint32_t *data)
+{
+ if (idx >= get_feature_entries_num()) {
+ ASSERT_CRITICAL(false);
+ return false;
+ }
+
+ switch (feature_entry_table[idx].feature_id) {
+ case FEATURE_MAX_COFUNC_NON_DP_DISPLAYS:
+ *data = as->asic_cap->data[ASIC_DATA_MAX_COFUNC_NONDP_DISPLAYS];
+ break;
+
+ case FEATURE_WIRELESS_LIMIT_720P:
+ *data = as->asic_cap->caps.WIRELESS_LIMIT_TO_720P;
+ break;
+
+ case FEATURE_WIRELESS_FULL_TIMING_ADJUSTMENT:
+ *data = as->asic_cap->caps.WIRELESS_FULL_TIMING_ADJUSTMENT;
+ break;
+
+ case FEATURE_MODIFY_TIMINGS_FOR_WIRELESS:
+ *data = as->asic_cap->caps.WIRELESS_TIMING_ADJUSTMENT;
+ break;
+
+ case FEATURE_SUPPORTED_HDMI_CONNECTION_NUM:
+ *data =
+ as->asic_cap->data[ASIC_DATA_SUPPORTED_HDMI_CONNECTION_NUM];
+ break;
+
+ case FEATURE_DETECT_REQUIRE_HPD_HIGH:
+ *data = as->asic_cap->caps.HPD_CHECK_FOR_EDID;
+ break;
+
+ case FEATURE_NO_HPD_LOW_POLLING_VCC_OFF:
+ *data = as->asic_cap->caps.NO_VCC_OFF_HPD_POLLING;
+ break;
+
+ case FEATURE_STUTTER_MODE:
+ *data = as->asic_cap->data[ASIC_DATA_STUTTERMODE];
+ break;
+
+ case FEATURE_WIRELESS_ENABLE:
+ *data = as->wireless_data.wireless_enable;
+ break;
+
+ case FEATURE_8BPP_SUPPORTED:
+ *data = as->asic_cap->caps.SUPPORT_8BPP;
+ break;
+
+ default:
+ return false;
+ }
+
+ return true;
+}
+
+/* get_bool_value
+ *
+ * Get the boolean value of a given feature
+ */
+static bool get_bool_value(
+ const uint32_t set,
+ const uint32_t idx)
+{
+ if (idx >= 32) {
+ ASSERT_CRITICAL(false);
+ return false;
+ }
+
+ return ((set & (1 << idx)) != 0);
+}
+
+/*
+ * get_hpd_info
+ *
+ * Get HPD information from BIOS
+ */
+static bool get_hpd_info(struct adapter_service *as,
+ struct graphics_object_id id,
+ struct graphics_object_hpd_info *info)
+{
+ struct dc_bios *dcb = dal_adapter_service_get_bios_parser(as);
+
+ return BP_RESULT_OK == dcb->funcs->get_hpd_info(dcb, id, info);
+}
+
+/*
+ * lookup_feature_entry
+ *
+ * Find the entry index of a given feature in feature table
+ */
+static uint32_t lookup_feature_entry(
+ enum adapter_feature_id feature_id)
+{
+ uint32_t entries_num = get_feature_entries_num();
+ uint32_t i = 0;
+
+ while (i != entries_num) {
+ if (feature_entry_table[i].feature_id == feature_id)
+ break;
+
+ ++i;
+ }
+
+ return i;
+}
+
+/*
+ * set_bool_value
+ *
+ * Set the boolean value of a given feature
+ */
+static void set_bool_value(
+ uint32_t *set,
+ const uint32_t idx,
+ bool value)
+{
+ if (idx >= 32) {
+ ASSERT_CRITICAL(false);
+ return;
+ }
+
+ if (value)
+ *set |= (1 << idx);
+ else
+ *set &= ~(1 << idx);
+}
+
+/*
+ * generate_feature_set
+ *
+ * Generate the internal feature set from multiple data sources
+ */
+static bool generate_feature_set(
+ struct adapter_service *as,
+ const struct dal_override_parameters *param)
+{
+ uint32_t i = 0;
+ uint32_t value = 0;
+ uint32_t set_idx = 0;
+ uint32_t internal_idx = 0;
+ uint32_t entry_num = 0;
+ const struct feature_source_entry *entry = NULL;
+
+ dm_memset(adapter_feature_set, 0, sizeof(adapter_feature_set));
+ entry_num = get_feature_entries_num();
+
+
+ while (i != entry_num) {
+ entry = &feature_entry_table[i];
+
+ if (entry->feature_id <= FEATURE_UNKNOWN ||
+ entry->feature_id >= FEATURE_MAXIMUM) {
+ ASSERT_CRITICAL(false);
+ return false;
+ }
+
+ set_idx = (uint32_t)((entry->feature_id - 1) / 32);
+ internal_idx = (uint32_t)((entry->feature_id - 1) % 32);
+
+ /* TODO: wireless, runtime parameter, vbios */
+ if (!override_default_parameters(as, param, i, &value)) {
+ if (!get_feature_value_from_data_sources(
+ as, i, &value)) {
+ /*
+ * Can't find feature values from
+ * above data sources
+ * Assign default value
+ */
+ value = entry->default_value;
+ }
+ }
+
+ if (entry->is_boolean_type)
+ set_bool_value(&adapter_feature_set[set_idx],
+ internal_idx,
+ value != 0);
+ else
+ adapter_feature_set[set_idx] = value;
+
+ i++;
+ }
+
+ return true;
+}
+
+
+/*
+ * create_hw_ctx
+ *
+ * Create HW context for adapter service. This is DCE specific.
+ */
+static struct hw_ctx_adapter_service *create_hw_ctx(
+ enum dce_version dce_version,
+ enum dce_environment dce_environment,
+ struct dc_context *ctx)
+{
+ if (IS_FPGA_MAXIMUS_DC(dce_environment))
+ return dal_adapter_service_create_hw_ctx_diag(ctx);
+
+ switch (dce_version) {
+#if defined(CONFIG_DRM_AMD_DAL_DCE10_0)
+ case DCE_VERSION_10_0:
+ return dal_adapter_service_create_hw_ctx_dce110(ctx);
+#endif
+#if defined(CONFIG_DRM_AMD_DAL_DCE11_0)
+ case DCE_VERSION_11_0:
+ return dal_adapter_service_create_hw_ctx_dce110(ctx);
+#endif
+ default:
+ ASSERT_CRITICAL(false);
+ return NULL;
+ }
+}
+
+/*
+ * adapter_service_destruct
+ *
+ * Release memory of objects in adapter service
+ */
+static void adapter_service_destruct(
+ struct adapter_service *as)
+{
+ struct dc_bios *dcb = dal_adapter_service_get_bios_parser(as);
+
+ dal_adapter_service_destroy_hw_ctx(&as->hw_ctx);
+ dal_i2caux_destroy(&as->i2caux);
+ dal_gpio_service_destroy(&as->gpio_service);
+ dal_asic_capability_destroy(&as->asic_cap);
+
+ dcb->funcs->destroy_integrated_info(dcb, &as->integrated_info);
+
+ if (as->dcb_internal) {
+ /* We are responsible only for destruction of Internal BIOS.
+ * The External one will be destroyed by its creator. */
+ dal_bios_parser_destroy(&as->dcb_internal);
+ }
+}
+
+/*
+ * adapter_service_construct
+ *
+ * Construct the derived type of adapter service
+ */
+static bool adapter_service_construct(
+ struct adapter_service *as,
+ struct as_init_data *init_data)
+{
+ struct dc_bios *dcb;
+ enum dce_version dce_version;
+
+ if (!init_data)
+ return false;
+
+ /* Create ASIC capability */
+ as->ctx = init_data->ctx;
+ as->asic_cap = dal_asic_capability_create(
+ &init_data->hw_init_data, as->ctx);
+
+ if (!as->asic_cap) {
+ ASSERT_CRITICAL(false);
+ return false;
+ }
+
+#if defined(CONFIG_DRM_AMD_DAL_DCE11_0)
+ if (dal_adapter_service_get_dce_version(as) == DCE_VERSION_11_0) {
+ uint32_t i;
+
+ for (i = 0; i < ARRAY_SIZE(feature_entry_table); i++) {
+ enum adapter_feature_id id =
+ feature_entry_table[i].feature_id;
+ if (id == FEATURE_MAXIMIZE_URGENCY_WATERMARKS ||
+ id == FEATURE_MAXIMIZE_STUTTER_MARKS ||
+ id == FEATURE_MAXIMIZE_NBP_MARKS)
+ feature_entry_table[i].default_value = true;
+ }
+ }
+#endif
+
+ /* Generate feature set table */
+ if (!generate_feature_set(as, init_data->display_param)) {
+ ASSERT_CRITICAL(false);
+ goto failed_to_generate_features;
+ }
+
+ as->dce_environment = init_data->dce_environment;
+
+ if (init_data->vbios_override)
+ as->dcb_override = init_data->vbios_override;
+ else {
+ /* Create BIOS parser */
+ init_data->bp_init_data.ctx = init_data->ctx;
+
+ as->dcb_internal = dal_bios_parser_create(
+ &init_data->bp_init_data, as);
+
+ if (!as->dcb_internal) {
+ ASSERT_CRITICAL(false);
+ goto failed_to_create_bios_parser;
+ }
+ }
+
+ dcb = dal_adapter_service_get_bios_parser(as);
+
+ dce_version = dal_adapter_service_get_dce_version(as);
+
+ /* Create GPIO service */
+ as->gpio_service = dal_gpio_service_create(
+ dce_version,
+ as->dce_environment,
+ as->ctx);
+
+ if (!as->gpio_service) {
+ ASSERT_CRITICAL(false);
+ goto failed_to_create_gpio_service;
+ }
+
+ /* Create I2C AUX */
+ as->i2caux = dal_i2caux_create(as, as->ctx);
+
+ if (!as->i2caux) {
+ ASSERT_CRITICAL(false);
+ goto failed_to_create_i2caux;
+ }
+
+ /* Create Adapter Service HW Context*/
+ as->hw_ctx = create_hw_ctx(
+ dce_version,
+ as->dce_environment,
+ as->ctx);
+
+ if (!as->hw_ctx) {
+ ASSERT_CRITICAL(false);
+ goto failed_to_create_hw_ctx;
+ }
+
+ /* Avoid wireless encoder creation in upstream branch. */
+
+ /* Integrated info is not provided on discrete ASIC. NULL is allowed */
+ as->integrated_info = dcb->funcs->create_integrated_info(dcb);
+
+ dcb->funcs->post_init(dcb);
+
+ /* Generate backlight translation table and initializes
+ other brightness properties */
+ as->backlight_caps_initialized = false;
+
+ get_platform_info_methods(as);
+
+ initialize_backlight_caps(as);
+
+ return true;
+
+failed_to_generate_features:
+ dal_adapter_service_destroy_hw_ctx(&as->hw_ctx);
+
+failed_to_create_hw_ctx:
+ dal_i2caux_destroy(&as->i2caux);
+
+failed_to_create_i2caux:
+ dal_gpio_service_destroy(&as->gpio_service);
+
+failed_to_create_gpio_service:
+ if (as->dcb_internal)
+ dal_bios_parser_destroy(&as->dcb_internal);
+
+failed_to_create_bios_parser:
+ dal_asic_capability_destroy(&as->asic_cap);
+
+ return false;
+}
+
+/*
+ * Global function definition
+ */
+
+/*
+ * dal_adapter_service_create
+ *
+ * Create adapter service
+ */
+struct adapter_service *dal_adapter_service_create(
+ struct as_init_data *init_data)
+{
+ struct adapter_service *as;
+
+ as = dm_alloc(init_data->ctx, sizeof(struct adapter_service));
+
+ if (!as) {
+ ASSERT_CRITICAL(false);
+ return NULL;
+ }
+
+ if (adapter_service_construct(as, init_data))
+ return as;
+
+ ASSERT_CRITICAL(false);
+
+ dm_free(init_data->ctx, as);
+
+ return NULL;
+}
+
+/*
+ * dal_adapter_service_destroy
+ *
+ * Destroy adapter service and objects it contains
+ */
+void dal_adapter_service_destroy(
+ struct adapter_service **as)
+{
+ if (!as) {
+ ASSERT_CRITICAL(false);
+ return;
+ }
+
+ if (!*as) {
+ ASSERT_CRITICAL(false);
+ return;
+ }
+
+ adapter_service_destruct(*as);
+
+ dm_free((*as)->ctx, *as);
+
+ *as = NULL;
+}
+
+/*
+ * dal_adapter_service_get_dce_version
+ *
+ * Get the DCE version of current ASIC
+ */
+enum dce_version dal_adapter_service_get_dce_version(
+ const struct adapter_service *as)
+{
+ uint32_t version = as->asic_cap->data[ASIC_DATA_DCE_VERSION];
+
+ switch (version) {
+#if defined(CONFIG_DRM_AMD_DAL_DCE10_0)
+ case 0x100:
+ return DCE_VERSION_10_0;
+#endif
+#if defined(CONFIG_DRM_AMD_DAL_DCE11_0)
+ case 0x110:
+ return DCE_VERSION_11_0;
+#endif
+ default:
+ ASSERT_CRITICAL(false);
+ return DCE_VERSION_UNKNOWN;
+ }
+}
+
+enum dce_environment dal_adapter_service_get_dce_environment(
+ const struct adapter_service *as)
+{
+ return as->dce_environment;
+}
+
+
+/*
+ * dal_adapter_service_get_controllers_num
+ *
+ * Get number of controllers
+ */
+uint8_t dal_adapter_service_get_controllers_num(
+ struct adapter_service *as)
+{
+ uint32_t result = as->asic_cap->data[ASIC_DATA_CONTROLLERS_NUM];
+
+ /* Check the "max num of controllers" feature,
+ * use it for debugging purposes only */
+ /* TODO implement
+ * dal_adapter_service_get_feature_value(as, ) */
+
+ return result;
+}
+
+/** Get total number of connectors.
+ *
+ * \param as Adapter Service
+ *
+ * \return Total number of connectors. It is up-to-the caller to decide
+ * if the number is valid.
+ */
+uint8_t dal_adapter_service_get_connectors_num(
+ struct adapter_service *as)
+{
+ uint8_t vbios_connectors_num = 0;
+ uint8_t wireless_connectors_num = 0;
+ struct dc_bios *dcb;
+
+ dcb = dal_adapter_service_get_bios_parser(as);
+
+ vbios_connectors_num = dcb->funcs->get_connectors_number(dcb);
+
+ wireless_connectors_num = wireless_get_connectors_num(as);
+
+ return vbios_connectors_num + wireless_connectors_num;
+}
+
+static bool is_wireless_object(struct graphics_object_id id)
+{
+ if ((id.type == OBJECT_TYPE_ENCODER &&
+ id.id == ENCODER_ID_INTERNAL_WIRELESS) ||
+ (id.type == OBJECT_TYPE_CONNECTOR && id.id ==
+ CONNECTOR_ID_WIRELESS) ||
+ (id.type == OBJECT_TYPE_CONNECTOR && id.id ==
+ CONNECTOR_ID_MIRACAST))
+ return true;
+ return false;
+}
+
+/**
+ * Get the number of source objects of an object
+ *
+ * \param [in] as: Adapter Service
+ *
+ * \param [in] id: The graphics object id
+ *
+ * \return
+ * The number of the source objects of an object
+ */
+uint32_t dal_adapter_service_get_src_num(
+ struct adapter_service *as, struct graphics_object_id id)
+{
+ struct dc_bios *dcb = dal_adapter_service_get_bios_parser(as);
+
+ if (is_wireless_object(id))
+ return wireless_get_srcs_num(as, id);
+ else
+ return dcb->funcs->get_src_number(dcb, id);
+}
+
+/**
+ * Get the source objects of an object
+ *
+ * \param [in] id The graphics object id
+ * \param [in] index Enumerating index which starts at 0
+ *
+ * \return If enumerating successfully, return the VALID source object id,
+ * otherwise, returns "zeroed out" object id.
+ * Client should call dal_graphics_object_id_is_valid() to check
+ * weather the id is valid.
+ */
+struct graphics_object_id dal_adapter_service_get_src_obj(
+ struct adapter_service *as,
+ struct graphics_object_id id,
+ uint32_t index)
+{
+ struct graphics_object_id src_object_id;
+ struct dc_bios *dcb = dal_adapter_service_get_bios_parser(as);
+
+ if (is_wireless_object(id))
+ src_object_id = wireless_get_src_obj_id(as, id, index);
+ else {
+ if (BP_RESULT_OK != dcb->funcs->get_src_obj(dcb, id, index,
+ &src_object_id)) {
+ src_object_id =
+ dal_graphics_object_id_init(
+ 0,
+ ENUM_ID_UNKNOWN,
+ OBJECT_TYPE_UNKNOWN);
+ }
+ }
+
+ return src_object_id;
+}
+
+/** Get connector object id associated with a connector index.
+ *
+ * \param as Adapter Service
+ *
+ * \param connector_index Index of connector between zero and total number
+ * returned by dal_adapter_service_get_connectors_num()
+ *
+ * \return graphics object id corresponding to the connector_index.
+ */
+struct graphics_object_id dal_adapter_service_get_connector_obj_id(
+ struct adapter_service *as,
+ uint8_t connector_index)
+{
+ struct dc_bios *dcb;
+ uint8_t bios_connectors_num;
+
+ dcb = dal_adapter_service_get_bios_parser(as);
+
+ bios_connectors_num = dcb->funcs->get_connectors_number(dcb);
+
+ if (connector_index >= bios_connectors_num)
+ return wireless_get_connector_id(as, connector_index);
+ else
+ return dcb->funcs->get_connector_id(dcb, connector_index);
+}
+
+bool dal_adapter_service_get_device_tag(
+ struct adapter_service *as,
+ struct graphics_object_id connector_object_id,
+ uint32_t device_tag_index,
+ struct connector_device_tag_info *info)
+{
+ struct dc_bios *dcb = dal_adapter_service_get_bios_parser(as);
+
+ if (BP_RESULT_OK == dcb->funcs->get_device_tag(dcb,
+ connector_object_id, device_tag_index, info))
+ return true;
+ else
+ return false;
+}
+
+/* Check if DeviceId is supported by ATOM_OBJECT_HEADER support info */
+bool dal_adapter_service_is_device_id_supported(struct adapter_service *as,
+ struct device_id id)
+{
+ struct dc_bios *dcb = dal_adapter_service_get_bios_parser(as);
+
+ return dcb->funcs->is_device_id_supported(dcb, id);
+}
+
+bool dal_adapter_service_is_meet_underscan_req(struct adapter_service *as)
+{
+ struct firmware_info fw_info;
+ enum bp_result bp_result = dal_adapter_service_get_firmware_info(
+ as, &fw_info);
+ uint32_t disp_clk_limit =
+ as->asic_cap->data[ASIC_DATA_MIN_DISPCLK_FOR_UNDERSCAN];
+ if (BP_RESULT_OK == bp_result) {
+ dal_logger_write(as->ctx->logger,
+ LOG_MAJOR_ERROR,
+ LOG_MINOR_COMPONENT_ADAPTER_SERVICE,
+ "Read firmware is NULL");
+ return false;
+ }
+ if (fw_info.default_display_engine_pll_frequency < disp_clk_limit)
+ return false;
+ return true;
+}
+
+bool dal_adapter_service_underscan_for_hdmi_only(struct adapter_service *as)
+{
+ return as->asic_cap->caps.UNDERSCAN_FOR_HDMI_ONLY;
+}
+/*
+ * dal_adapter_service_get_clock_sources_num
+ *
+ * Get number of clock sources
+ */
+uint8_t dal_adapter_service_get_clock_sources_num(
+ struct adapter_service *as)
+{
+ struct firmware_info fw_info;
+ uint32_t max_clk_src = 0;
+ uint32_t num = as->asic_cap->data[ASIC_DATA_CLOCKSOURCES_NUM];
+ struct dc_bios *dcb = dal_adapter_service_get_bios_parser(as);
+
+ /*
+ * Check is system supports the use of the External clock source
+ * as a clock source for DP
+ */
+ enum bp_result bp_result = dcb->funcs->get_firmware_info(dcb, &fw_info);
+
+ if (BP_RESULT_OK == bp_result &&
+ fw_info.external_clock_source_frequency_for_dp != 0)
+ ++num;
+
+ /*
+ * Add clock source for wireless if supported
+ */
+ num += (uint32_t)wireless_get_clocks_num(as);
+
+ /* Check the "max number of clock sources" feature */
+ if (dal_adapter_service_get_feature_value(
+ FEATURE_MAX_CLOCK_SOURCE_NUM,
+ &max_clk_src,
+ sizeof(uint32_t)))
+ if ((max_clk_src != 0) && (max_clk_src < num))
+ num = max_clk_src;
+
+ return num;
+}
+
+/*
+ * dal_adapter_service_get_func_controllers_num
+ *
+ * Get number of controllers
+ */
+uint8_t dal_adapter_service_get_func_controllers_num(
+ struct adapter_service *as)
+{
+ uint32_t result =
+ as->asic_cap->data[ASIC_DATA_FUNCTIONAL_CONTROLLERS_NUM];
+
+ /* Check the "max num of controllers" feature,
+ * use it for debugging purposes only */
+
+ /* Limit number of controllers by OS */
+
+ struct asic_feature_flags flags;
+
+ flags.raw = as->asic_cap->data[ASIC_DATA_FEATURE_FLAGS];
+
+ if (flags.bits.LEGACY_CLIENT &&
+ (result > LEGACY_MAX_NUM_OF_CONTROLLERS))
+ result = LEGACY_MAX_NUM_OF_CONTROLLERS;
+
+ return result;
+}
+
+/*
+ * dal_adapter_service_is_feature_supported
+ *
+ * Return if a given feature is supported by the ASIC. The feature has to be
+ * a boolean type.
+ */
+bool dal_adapter_service_is_feature_supported(
+ enum adapter_feature_id feature_id)
+{
+ bool data = 0;
+
+ dal_adapter_service_get_feature_value(feature_id, &data, sizeof(bool));
+
+ return data;
+}
+
+/**
+ * Reports maximum number of confunctional non-DP displays.
+ * Value can be overriden if FEATURE_REPORT_SINGLE_SELECTED_TIMING feature is
+ * enabled.
+ *
+ * \return
+ * Maximum number of confunctional non-DP displays
+ */
+uint32_t dal_adapter_service_get_max_cofunc_non_dp_displays(void)
+{
+ uint32_t non_dp_displays = DEFAULT_NUM_COFUNC_NON_DP_DISPLAYS;
+
+ if (true == dal_adapter_service_get_feature_value(
+ FEATURE_MAX_COFUNC_NON_DP_DISPLAYS,
+ &non_dp_displays,
+ sizeof(non_dp_displays))) {
+ /* the cached value exist */
+ /* TODO: add more logic as per-DAL2 */
+ }
+
+ return non_dp_displays;
+}
+
+uint32_t dal_adapter_service_get_single_selected_timing_signals(void)
+{
+ uint32_t signals_bitmap = 0;
+
+ if (dal_adapter_service_is_feature_supported(
+ FEATURE_REPORT_SINGLE_SELECTED_TIMING)) {
+ /* the cached value exist */
+ /* TODO: add more logic as per-DAL2 */
+ signals_bitmap = 0;
+ }
+
+ return signals_bitmap;
+}
+
+/*
+ * dal_adapter_service_get_i2c_info
+ *
+ * Get I2C information from BIOS
+ */
+bool dal_adapter_service_get_i2c_info(
+ struct adapter_service *as,
+ struct graphics_object_id id,
+ struct graphics_object_i2c_info *i2c_info)
+{
+ struct dc_bios *dcb = dal_adapter_service_get_bios_parser(as);
+
+ if (!i2c_info) {
+ ASSERT_CRITICAL(false);
+ return false;
+ }
+
+ return BP_RESULT_OK == dcb->funcs->get_i2c_info(dcb, id, i2c_info);
+}
+
+/*
+ * dal_adapter_service_obtain_ddc
+ *
+ * Obtain DDC
+ */
+struct ddc *dal_adapter_service_obtain_ddc(
+ struct adapter_service *as,
+ struct graphics_object_id id)
+{
+ struct graphics_object_i2c_info i2c_info;
+ struct gpio_ddc_hw_info hw_info;
+
+
+ if (!dal_adapter_service_get_i2c_info(as, id, &i2c_info))
+ return NULL;
+
+ hw_info.ddc_channel = i2c_info.i2c_line;
+ hw_info.hw_supported = i2c_info.i2c_hw_assist;
+
+ return dal_gpio_service_create_ddc(
+ as->gpio_service,
+ i2c_info.gpio_info.clk_a_register_index,
+ 1 << i2c_info.gpio_info.clk_a_shift,
+ &hw_info);
+}
+
+/*
+ * dal_adapter_service_release_ddc
+ *
+ * Release DDC
+ */
+void dal_adapter_service_release_ddc(
+ struct adapter_service *as,
+ struct ddc *ddc)
+{
+ dal_gpio_service_destroy_ddc(&ddc);
+}
+
+/*
+ * dal_adapter_service_obtain_hpd_irq
+ *
+ * Obtain HPD interrupt request
+ */
+struct irq *dal_adapter_service_obtain_hpd_irq(
+ struct adapter_service *as,
+ struct graphics_object_id id)
+{
+ enum bp_result bp_result;
+ struct dc_bios *dcb = dal_adapter_service_get_bios_parser(as);
+ struct graphics_object_hpd_info hpd_info;
+ struct gpio_pin_info pin_info;
+
+ if (!get_hpd_info(as, id, &hpd_info))
+ return NULL;
+
+ bp_result = dcb->funcs->get_gpio_pin_info(dcb,
+ hpd_info.hpd_int_gpio_uid, &pin_info);
+
+ if (bp_result != BP_RESULT_OK) {
+ ASSERT(bp_result == BP_RESULT_NORECORD);
+ return NULL;
+ }
+
+ return dal_gpio_service_create_irq(
+ as->gpio_service,
+ pin_info.offset,
+ pin_info.mask);
+}
+
+/*
+ * dal_adapter_service_release_irq
+ *
+ * Release interrupt request
+ */
+void dal_adapter_service_release_irq(
+ struct adapter_service *as,
+ struct irq *irq)
+{
+ dal_gpio_service_destroy_irq(&irq);
+}
+
+/*
+ * dal_adapter_service_get_ss_info_num
+ *
+ * Get number of spread spectrum entries from BIOS
+ */
+uint32_t dal_adapter_service_get_ss_info_num(
+ struct adapter_service *as,
+ enum as_signal_type signal)
+{
+ struct dc_bios *dcb = dal_adapter_service_get_bios_parser(as);
+
+ return dcb->funcs->get_ss_entry_number(dcb, signal);
+}
+
+/*
+ * dal_adapter_service_get_ss_info
+ *
+ * Get spread spectrum info from BIOS
+ */
+bool dal_adapter_service_get_ss_info(
+ struct adapter_service *as,
+ enum as_signal_type signal,
+ uint32_t idx,
+ struct spread_spectrum_info *info)
+{
+ struct dc_bios *dcb = dal_adapter_service_get_bios_parser(as);
+
+ enum bp_result bp_result = dcb->funcs->get_spread_spectrum_info(dcb,
+ signal, idx, info);
+
+ return BP_RESULT_OK == bp_result;
+}
+
+/*
+ * dal_adapter_service_get_integrated_info
+ *
+ * Get integrated information on BIOS
+ */
+bool dal_adapter_service_get_integrated_info(
+ struct adapter_service *as,
+ struct integrated_info *info)
+{
+ if (info == NULL || as->integrated_info == NULL)
+ return false;
+
+ dm_memmove(info, as->integrated_info, sizeof(struct integrated_info));
+
+ return true;
+}
+
+/*
+ * dal_adapter_service_is_dfs_bypass_enabled
+ *
+ * Check if DFS bypass is enabled
+ */
+bool dal_adapter_service_is_dfs_bypass_enabled(
+ struct adapter_service *as)
+{
+ if (as->integrated_info == NULL)
+ return false;
+ if ((as->integrated_info->gpu_cap_info & DFS_BYPASS_ENABLE) &&
+ dal_adapter_service_is_feature_supported(
+ FEATURE_ENABLE_DFS_BYPASS))
+ return true;
+ else
+ return false;
+}
+
+/*
+ * dal_adapter_service_get_sw_i2c_speed
+ *
+ * Get SW I2C speed
+ */
+uint32_t dal_adapter_service_get_sw_i2c_speed(
+ struct adapter_service *as)
+{
+ /* TODO: only from ASIC caps. Feature key is not implemented*/
+ return as->asic_cap->data[ASIC_DATA_DEFAULT_I2C_SPEED_IN_KHZ];
+}
+
+/*
+ * dal_adapter_service_get_hw_i2c_speed
+ *
+ * Get HW I2C speed
+ */
+uint32_t dal_adapter_service_get_hw_i2c_speed(
+ struct adapter_service *as)
+{
+ /* TODO: only from ASIC caps. Feature key is not implemented*/
+ return as->asic_cap->data[ASIC_DATA_DEFAULT_I2C_SPEED_IN_KHZ];
+}
+
+/*
+ * dal_adapter_service_get_mc_latency
+ *
+ * Get memory controller latency
+ */
+uint32_t dal_adapter_service_get_mc_latency(
+ struct adapter_service *as)
+{
+ return as->asic_cap->data[ASIC_DATA_MC_LATENCY];
+}
+
+/*
+ * dal_adapter_service_get_asic_vram_bit_width
+ *
+ * Get the video RAM bit width set on the ASIC
+ */
+uint32_t dal_adapter_service_get_asic_vram_bit_width(
+ struct adapter_service *as)
+{
+ return as->asic_cap->data[ASIC_DATA_VRAM_BITWIDTH];
+}
+
+/*
+ * dal_adapter_service_get_asic_bugs
+ *
+ * Get the bug flags set on this ASIC
+ */
+struct asic_bugs dal_adapter_service_get_asic_bugs(
+ struct adapter_service *as)
+{
+ return as->asic_cap->bugs;
+}
+
+
+struct dal_asic_runtime_flags dal_adapter_service_get_asic_runtime_flags(
+ struct adapter_service *as)
+{
+ return as->asic_cap->runtime_flags;
+}
+
+/*
+ * dal_adapter_service_get_line_buffer_size
+ *
+ * Get line buffer size
+ */
+uint32_t dal_adapter_service_get_line_buffer_size(
+ struct adapter_service *as)
+{
+ return as->asic_cap->data[ASIC_DATA_LINEBUFFER_SIZE];
+}
+
+/*
+ * dal_adapter_service_get_bandwidth_tuning_params
+ *
+ * Get parameters for bandwidth tuning
+ */
+bool dal_adapter_service_get_bandwidth_tuning_params(
+ struct adapter_service *as,
+ union bandwidth_tuning_params *params)
+{
+ /* TODO: add implementation */
+ /* note: data comes from runtime parameters */
+ return false;
+}
+
+/*
+ * dal_adapter_service_get_feature_flags
+ *
+ * Get a copy of ASIC feature flags
+ */
+struct asic_feature_flags dal_adapter_service_get_feature_flags(
+ struct adapter_service *as)
+{
+ struct asic_feature_flags result = { { 0 } };
+
+ if (!as) {
+ ASSERT_CRITICAL(false);
+ return result;
+ }
+
+ result.raw = as->asic_cap->data[ASIC_DATA_FEATURE_FLAGS];
+
+ return result;
+}
+
+/*
+ * dal_adapter_service_get_dram_bandwidth_efficiency
+ *
+ * Get efficiency of DRAM
+ */
+uint32_t dal_adapter_service_get_dram_bandwidth_efficiency(
+ struct adapter_service *as)
+{
+ return as->asic_cap->data[ASIC_DATA_DRAM_BANDWIDTH_EFFICIENCY];
+}
+
+/*
+ * dal_adapter_service_obtain_gpio
+ *
+ * Obtain GPIO
+ */
+struct gpio *dal_adapter_service_obtain_gpio(
+ struct adapter_service *as,
+ enum gpio_id id,
+ uint32_t en)
+{
+ return dal_gpio_service_create_gpio_ex(
+ as->gpio_service, id, en,
+ GPIO_PIN_OUTPUT_STATE_DEFAULT);
+}
+
+/*
+ * dal_adapter_service_obtain_stereo_gpio
+ *
+ * Obtain GPIO for stereo3D
+ */
+struct gpio *dal_adapter_service_obtain_stereo_gpio(
+ struct adapter_service *as)
+{
+ const bool have_param_stereo_gpio = false;
+
+ struct asic_feature_flags result;
+
+ result.raw = as->asic_cap->data[ASIC_DATA_FEATURE_FLAGS];
+
+ /* Case 1 : Workstation stereo */
+ if (result.bits.WORKSTATION_STEREO) {
+ /* "active low" <--> "default 3d right eye polarity" = false */
+ return dal_gpio_service_create_gpio_ex(as->gpio_service,
+ GPIO_ID_GENERIC, GPIO_GENERIC_A,
+ GPIO_PIN_OUTPUT_STATE_ACTIVE_LOW);
+ /* Case 2 : runtime parameter override for sideband stereo */
+ } else if (have_param_stereo_gpio) {
+ /* TODO implement */
+ return NULL;
+ /* Case 3 : VBIOS gives us GPIO for sideband stereo */
+ } else {
+ const struct graphics_object_id id =
+ dal_graphics_object_id_init(GENERIC_ID_STEREO,
+ ENUM_ID_1, OBJECT_TYPE_GENERIC);
+
+ struct bp_gpio_cntl_info cntl_info;
+ struct gpio_pin_info pin_info;
+ struct dc_bios *dcb = dal_adapter_service_get_bios_parser(as);
+
+ /* Get GPIO record for this object.
+ * Stereo GPIO record should have exactly one entry
+ * where active state defines stereosync polarity */
+ if (1 != dcb->funcs->get_gpio_record(
+ dcb, id, &cntl_info,
+ 1)) {
+ return NULL;
+ } else if (BP_RESULT_OK
+ != dcb->funcs->get_gpio_pin_info(
+ dcb, cntl_info.id,
+ &pin_info)) {
+ /*ASSERT_CRITICAL(false);*/
+ return NULL;
+ } else {
+ return dal_gpio_service_create_gpio_ex(as->gpio_service,
+ pin_info.offset, pin_info.mask,
+ cntl_info.state);
+ }
+ }
+}
+
+/*
+ * dal_adapter_service_release_gpio
+ *
+ * Release GPIO
+ */
+void dal_adapter_service_release_gpio(
+ struct adapter_service *as,
+ struct gpio *gpio)
+{
+ dal_gpio_service_destroy_gpio(&gpio);
+}
+
+/*
+ * dal_adapter_service_get_firmware_info
+ *
+ * Get firmware information from BIOS
+ */
+bool dal_adapter_service_get_firmware_info(
+ struct adapter_service *as,
+ struct firmware_info *info)
+{
+ struct dc_bios *dcb = dal_adapter_service_get_bios_parser(as);
+
+ return dcb->funcs->get_firmware_info(dcb, info) == BP_RESULT_OK;
+}
+
+/*
+ * dal_adapter_service_get_audio_support
+ *
+ * Get information on audio support
+ */
+union audio_support dal_adapter_service_get_audio_support(
+ struct adapter_service *as)
+{
+ return dal_adapter_service_hw_ctx_get_audio_support(as->hw_ctx);
+}
+
+/*
+ * dal_adapter_service_get_stream_engines_num
+ *
+ * Get number of stream engines
+ */
+uint8_t dal_adapter_service_get_stream_engines_num(
+ struct adapter_service *as)
+{
+ return as->asic_cap->data[ASIC_DATA_DIGFE_NUM];
+}
+
+/*
+ * dal_adapter_service_get_feature_value
+ *
+ * Get the cached value of a given feature. This value can be a boolean, int,
+ * or characters.
+ */
+bool dal_adapter_service_get_feature_value(
+ const enum adapter_feature_id feature_id,
+ void *data,
+ uint32_t size)
+{
+ uint32_t entry_idx = 0;
+ uint32_t set_idx = 0;
+ uint32_t set_internal_idx = 0;
+
+ if (feature_id >= FEATURE_MAXIMUM || feature_id <= FEATURE_UNKNOWN) {
+ ASSERT_CRITICAL(false);
+ return false;
+ }
+
+ if (data == NULL) {
+ ASSERT_CRITICAL(false);
+ return false;
+ }
+
+ entry_idx = lookup_feature_entry(feature_id);
+ set_idx = (uint32_t)((feature_id - 1)/32);
+ set_internal_idx = (uint32_t)((feature_id - 1) % 32);
+
+ if (entry_idx >= get_feature_entries_num()) {
+ /* Cannot find this entry */
+ ASSERT_CRITICAL(false);
+ return false;
+ }
+
+ if (feature_entry_table[entry_idx].is_boolean_type) {
+ if (size != sizeof(bool)) {
+ ASSERT_CRITICAL(false);
+ return false;
+ }
+
+ *(bool *)data = get_bool_value(adapter_feature_set[set_idx],
+ set_internal_idx);
+ } else {
+ if (size != sizeof(uint32_t)) {
+ ASSERT_CRITICAL(false);
+ return false;
+ }
+
+ *(uint32_t *)data = adapter_feature_set[set_idx];
+ }
+
+ return true;
+}
+
+/*
+ * dal_adapter_service_get_memory_type_multiplier
+ *
+ * Get multiplier for the memory type
+ */
+uint32_t dal_adapter_service_get_memory_type_multiplier(
+ struct adapter_service *as)
+{
+ return as->asic_cap->data[ASIC_DATA_MEMORYTYPE_MULTIPLIER];
+}
+
+/*
+ * dal_adapter_service_get_bios_parser
+ *
+ * Get BIOS parser handler
+ */
+struct dc_bios *dal_adapter_service_get_bios_parser(
+ struct adapter_service *as)
+{
+ return as->dcb_override ? as->dcb_override : as->dcb_internal;
+}
+
+/*
+ * dal_adapter_service_get_i2caux
+ *
+ * Get i2c aux handler
+ */
+struct i2caux *dal_adapter_service_get_i2caux(
+ struct adapter_service *as)
+{
+ return as->i2caux;
+}
+
+bool dal_adapter_service_initialize_hw_data(
+ struct adapter_service *as)
+{
+ return as->hw_ctx->funcs->power_up(as->hw_ctx);
+}
+
+struct graphics_object_id dal_adapter_service_enum_fake_path_resource(
+ struct adapter_service *as,
+ uint32_t index)
+{
+ return as->hw_ctx->funcs->enum_fake_path_resource(as->hw_ctx, index);
+}
+
+struct graphics_object_id dal_adapter_service_enum_stereo_sync_object(
+ struct adapter_service *as,
+ uint32_t index)
+{
+ return as->hw_ctx->funcs->enum_stereo_sync_object(as->hw_ctx, index);
+}
+
+struct graphics_object_id dal_adapter_service_enum_sync_output_object(
+ struct adapter_service *as,
+ uint32_t index)
+{
+ return as->hw_ctx->funcs->enum_sync_output_object(as->hw_ctx, index);
+}
+
+struct graphics_object_id dal_adapter_service_enum_audio_object(
+ struct adapter_service *as,
+ uint32_t index)
+{
+ return as->hw_ctx->funcs->enum_audio_object(as->hw_ctx, index);
+}
+
+
+void dal_adapter_service_update_audio_connectivity(
+ struct adapter_service *as,
+ uint32_t number_of_audio_capable_display_path)
+{
+ as->hw_ctx->funcs->update_audio_connectivity(
+ as->hw_ctx,
+ number_of_audio_capable_display_path,
+ dal_adapter_service_get_controllers_num(as));
+}
+
+bool dal_adapter_service_has_embedded_display_connector(
+ struct adapter_service *as)
+{
+ uint8_t index;
+ uint8_t num_connectors = dal_adapter_service_get_connectors_num(as);
+
+ if (num_connectors == 0 || num_connectors > ENUM_ID_COUNT)
+ return false;
+
+ for (index = 0; index < num_connectors; index++) {
+ struct graphics_object_id obj_id =
+ dal_adapter_service_get_connector_obj_id(as, index);
+ enum connector_id connector_id =
+ dal_graphics_object_id_get_connector_id(obj_id);
+
+ if ((connector_id == CONNECTOR_ID_LVDS) ||
+ (connector_id == CONNECTOR_ID_EDP))
+ return true;
+ }
+
+ return false;
+}
+
+bool dal_adapter_service_get_embedded_panel_info(
+ struct adapter_service *as,
+ struct embedded_panel_info *info)
+{
+ enum bp_result result;
+ struct dc_bios *dcb = dal_adapter_service_get_bios_parser(as);
+
+ if (info == NULL)
+ /*TODO: add DALASSERT_MSG here*/
+ return false;
+
+ result = dcb->funcs->get_embedded_panel_info(dcb, info);
+
+ return result == BP_RESULT_OK;
+}
+
+bool dal_adapter_service_enum_embedded_panel_patch_mode(
+ struct adapter_service *as,
+ uint32_t index,
+ struct embedded_panel_patch_mode *mode)
+{
+ enum bp_result result;
+ struct dc_bios *dcb = dal_adapter_service_get_bios_parser(as);
+
+ if (mode == NULL)
+ /*TODO: add DALASSERT_MSG here*/
+ return false;
+
+ result = dcb->funcs->enum_embedded_panel_patch_mode(dcb, index, mode);
+
+ return result == BP_RESULT_OK;
+}
+
+bool dal_adapter_service_get_faked_edid_len(
+ struct adapter_service *as,
+ uint32_t *len)
+{
+ enum bp_result result;
+ struct dc_bios *dcb = dal_adapter_service_get_bios_parser(as);
+
+ result = dcb->funcs->get_faked_edid_len(dcb, len);
+
+ return result == BP_RESULT_OK;
+}
+
+bool dal_adapter_service_get_faked_edid_buf(
+ struct adapter_service *as,
+ uint8_t *buf,
+ uint32_t len)
+{
+ enum bp_result result;
+ struct dc_bios *dcb = dal_adapter_service_get_bios_parser(as);
+
+ result = dcb->funcs->get_faked_edid_buf(dcb, buf, len);
+
+ return result == BP_RESULT_OK;
+
+}
+
+/*
+ * dal_adapter_service_is_fusion
+ *
+ * Is this Fusion ASIC
+ */
+bool dal_adapter_service_is_fusion(struct adapter_service *as)
+{
+ return as->asic_cap->caps.IS_FUSION;
+}
+
+/*
+ * dal_adapter_service_is_dfsbyass_dynamic
+ *
+ *
+ **/
+bool dal_adapter_service_is_dfsbyass_dynamic(struct adapter_service *as)
+{
+ return as->asic_cap->caps.DFSBYPASS_DYNAMIC_SUPPORT;
+}
+
+/*
+ * dal_adapter_service_should_optimize
+ *
+ * @brief Reports whether driver settings allow requested optimization
+ *
+ * @param
+ * as: adapter service handler
+ * feature: for which optimization is validated
+ *
+ * @return
+ * true if requested feature can be optimized
+ */
+bool dal_adapter_service_should_optimize(
+ struct adapter_service *as, enum optimization_feature feature)
+{
+ uint32_t supported_optimization = 0;
+ struct dal_asic_runtime_flags flags;
+
+ if (!dal_adapter_service_get_feature_value(FEATURE_OPTIMIZATION,
+ &supported_optimization, sizeof(uint32_t)))
+ return false;
+
+ /* Retrieve ASIC runtime flags */
+ flags = dal_adapter_service_get_asic_runtime_flags(as);
+
+ /* Check runtime flags against different optimization features */
+ switch (feature) {
+ case OF_SKIP_HW_PROGRAMMING_ON_ENABLED_EMBEDDED_DISPLAY:
+ if (!flags.flags.bits.OPTIMIZED_DISPLAY_PROGRAMMING_ON_BOOT)
+ return false;
+ break;
+
+ case OF_SKIP_RESET_OF_ALL_HW_ON_S3RESUME:
+ if (as->integrated_info == NULL ||
+ !flags.flags.bits.SKIP_POWER_DOWN_ON_RESUME)
+ return false;
+ break;
+ case OF_SKIP_POWER_DOWN_INACTIVE_ENCODER:
+ if (!dal_adapter_service_get_asic_runtime_flags(as).flags.bits.
+ SKIP_POWER_DOWN_ON_RESUME)
+ return false;
+ break;
+ default:
+ break;
+ }
+
+ return (supported_optimization & feature) != 0;
+}
+
+/*
+ * dal_adapter_service_is_in_accelerated_mode
+ *
+ * @brief Determine if driver is in accelerated mode
+ *
+ * @param
+ * as: Adapter Service handler
+ *
+ * @out
+ * True if driver is in accelerated mode, false otherwise.
+ */
+bool dal_adapter_service_is_in_accelerated_mode(struct adapter_service *as)
+{
+ struct dc_bios *dcb = dal_adapter_service_get_bios_parser(as);
+
+ return dcb->funcs->is_accelerated_mode(dcb);
+}
+
+struct ddc *dal_adapter_service_obtain_ddc_from_i2c_info(
+ struct adapter_service *as,
+ struct graphics_object_i2c_info *info)
+{
+ struct gpio_ddc_hw_info hw_info = {
+ info->i2c_hw_assist,
+ info->i2c_line };
+ return dal_gpio_service_create_ddc(as->gpio_service,
+ info->gpio_info.clk_a_register_index,
+ (1 << info->gpio_info.clk_a_shift), &hw_info);
+}
+
+struct bdf_info dal_adapter_service_get_adapter_info(struct adapter_service *as)
+{
+ return as->bdf_info;
+}
+
+/*
+ * dal_adapter_service_should_psr_skip_wait_for_pll_lock
+ *
+ * @brief Determine if this ASIC needs to wait on PLL lock bit
+ *
+ * @param
+ * as: Adapter Service handle
+ *
+ * @out
+ * True if ASIC does not need to wait for PLL lock bit, i.e. skip the wait.
+ */
+bool dal_adapter_service_should_psr_skip_wait_for_pll_lock(
+ struct adapter_service *as)
+{
+ return as->asic_cap->caps.SKIP_PSR_WAIT_FOR_PLL_LOCK_BIT;
+}
+
+bool dal_adapter_service_is_lid_open(struct adapter_service *as)
+{
+ bool is_lid_open = false;
+ struct platform_info_params params;
+ struct dc_bios *dcb = dal_adapter_service_get_bios_parser(as);
+
+ params.data = &is_lid_open;
+ params.method = PM_GET_LID_STATE;
+
+ if ((PM_GET_LID_STATE & as->platform_methods_mask) &&
+ dm_get_platform_info(as->ctx, &params))
+ return is_lid_open;
+
+#if defined(CONFIG_DRM_AMD_DAL_VBIOS_PRESENT)
+ return dcb->funcs->is_lid_open(dcb);
+#else
+ return false;
+#endif
+}
+
+bool dal_adapter_service_get_panel_backlight_default_levels(
+ struct adapter_service *as,
+ struct panel_backlight_levels *levels)
+{
+ if (!as->backlight_caps_initialized)
+ return false;
+
+ levels->ac_level_percentage = as->ac_level_percentage;
+ levels->dc_level_percentage = as->dc_level_percentage;
+ return true;
+}
+
+bool dal_adapter_service_get_panel_backlight_boundaries(
+ struct adapter_service *as,
+ struct panel_backlight_boundaries *boundaries)
+{
+ if (!as->backlight_caps_initialized)
+ return false;
+ if (boundaries != NULL) {
+ boundaries->min_signal_level = as->backlight_8bit_lut[0];
+ boundaries->max_signal_level =
+ as->backlight_8bit_lut[SIZEOF_BACKLIGHT_LUT - 1];
+ return true;
+ }
+ return false;
+}
+
+
+uint32_t dal_adapter_service_get_view_port_pixel_granularity(
+ struct adapter_service *as)
+{
+ return as->asic_cap->data[ASIC_DATA_VIEWPORT_PIXEL_GRANULARITY];
+}
+
+/**
+ * Get number of paths per DP 1.2 connector from the runtime parameter if it
+ * exists.
+ * A check to see if MST is supported for the generation of ASIC is done
+ *
+ * \return
+ * Number of paths per DP 1.2 connector is exists in runtime parameters
+ * or ASIC cap
+ */
+uint32_t dal_adapter_service_get_num_of_path_per_dp_mst_connector(
+ struct adapter_service *as)
+{
+ if (as->asic_cap->caps.DP_MST_SUPPORTED == 0) {
+ /* ASIC doesn't support DP MST at all */
+ return 0;
+ }
+
+ return as->asic_cap->data[ASIC_DATA_PATH_NUM_PER_DPMST_CONNECTOR];
+}
+
+uint32_t dal_adapter_service_get_num_of_underlays(
+ struct adapter_service *as)
+{
+ return as->asic_cap->data[ASIC_DATA_NUM_OF_VIDEO_PLANES];
+}
+
+bool dal_adapter_service_get_encoder_cap_info(
+ struct adapter_service *as,
+ struct graphics_object_id id,
+ struct graphics_object_encoder_cap_info *info)
+{
+ struct bp_encoder_cap_info bp_cap_info = {0};
+ enum bp_result result;
+ struct dc_bios *dcb = dal_adapter_service_get_bios_parser(as);
+
+ if (NULL == info) {
+ ASSERT_CRITICAL(false);
+ return false;
+ }
+
+ /*
+ * Retrieve Encoder Capability Information from VBIOS and store the
+ * call result (success or fail)
+ * Info from VBIOS about HBR2 has two fields:
+ *
+ * - dpHbr2Cap: indicates supported/not supported by HW Encoder
+ * - dpHbr2En : indicates DP spec compliant/not compliant
+ */
+ result = dcb->funcs->get_encoder_cap_info(dcb, id, &bp_cap_info);
+
+ /* Set dp_hbr2_validated flag (it's equal to Enable) */
+ info->dp_hbr2_validated = bp_cap_info.DP_HBR2_EN;
+
+ if (result == BP_RESULT_OK) {
+ info->dp_hbr2_cap = bp_cap_info.DP_HBR2_CAP;
+ return true;
+ }
+
+ return false;
+}
+
+bool dal_adapter_service_is_mc_tuning_req(struct adapter_service *as)
+{
+ return as->asic_cap->caps.NEED_MC_TUNING ? true : false;
+}
diff --git a/drivers/gpu/drm/amd/dal/dc/adapter/adapter_service.h b/drivers/gpu/drm/amd/dal/dc/adapter/adapter_service.h
new file mode 100644
index 000000000000..60464e89cc5b
--- /dev/null
+++ b/drivers/gpu/drm/amd/dal/dc/adapter/adapter_service.h
@@ -0,0 +1,71 @@
+/*
+ * 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_ADAPTER_SERVICE_H__
+#define __DAL_ADAPTER_SERVICE_H__
+
+/* Include */
+#include "dc_bios_types.h"
+#include "include/adapter_service_interface.h"
+#include "wireless_data_source.h"
+
+/*
+ * Forward declaration
+ */
+struct gpio_service;
+struct asic_cap;
+
+
+/* Adapter service */
+struct adapter_service {
+ struct dc_context *ctx;
+ struct asic_capability *asic_cap;
+ struct dc_bios *dcb_internal;/* created by DC */
+ struct dc_bios *dcb_override;/* supplied by creator of DC */
+ enum dce_environment dce_environment;
+ struct gpio_service *gpio_service;
+ struct i2caux *i2caux;
+ struct wireless_data wireless_data;
+ struct hw_ctx_adapter_service *hw_ctx;
+ struct integrated_info *integrated_info;
+ struct bdf_info bdf_info;
+ uint32_t platform_methods_mask;
+ uint32_t ac_level_percentage;
+ uint32_t dc_level_percentage;
+ uint32_t backlight_caps_initialized;
+ uint32_t backlight_8bit_lut[SIZEOF_BACKLIGHT_LUT];
+};
+
+/* Type of feature with its runtime parameter and default value */
+struct feature_source_entry {
+ enum adapter_feature_id feature_id;
+ uint32_t default_value;
+ bool is_boolean_type;
+};
+
+/* Stores entire ASIC features by sets */
+extern uint32_t adapter_feature_set[];
+
+#endif /* __DAL_ADAPTER_SERVICE_H__ */
diff --git a/drivers/gpu/drm/amd/dal/dc/adapter/dce110/hw_ctx_adapter_service_dce110.c b/drivers/gpu/drm/amd/dal/dc/adapter/dce110/hw_ctx_adapter_service_dce110.c
new file mode 100644
index 000000000000..f10bee6f2b83
--- /dev/null
+++ b/drivers/gpu/drm/amd/dal/dc/adapter/dce110/hw_ctx_adapter_service_dce110.c
@@ -0,0 +1,304 @@
+/*
+ * 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 "../hw_ctx_adapter_service.h"
+
+#include "hw_ctx_adapter_service_dce110.h"
+
+#include "include/logger_interface.h"
+#include "include/grph_object_id.h"
+
+#include "dce/dce_11_0_d.h"
+#include "dce/dce_11_0_sh_mask.h"
+
+#ifndef mmCC_DC_HDMI_STRAPS
+#define mmCC_DC_HDMI_STRAPS 0x4819
+#define CC_DC_HDMI_STRAPS__HDMI_DISABLE_MASK 0x40
+#define CC_DC_HDMI_STRAPS__HDMI_DISABLE__SHIFT 0x6
+#define CC_DC_HDMI_STRAPS__AUDIO_STREAM_NUMBER_MASK 0x700
+#define CC_DC_HDMI_STRAPS__AUDIO_STREAM_NUMBER__SHIFT 0x8
+#endif
+
+static const struct graphics_object_id invalid_go = {
+ 0, ENUM_ID_UNKNOWN, OBJECT_TYPE_UNKNOWN, 0
+};
+
+/* Macro */
+#define AUDIO_STRAPS_HDMI_ENABLE 0x2
+
+#define FROM_HW_CTX(ptr) \
+ container_of((ptr), struct hw_ctx_adapter_service_dce110, base)
+
+static const uint32_t audio_index_reg_offset[] = {
+ /*CZ has 3 DIGs but 4 audio endpoints*/
+ mmAZF0ENDPOINT0_AZALIA_F0_CODEC_ENDPOINT_INDEX,
+ mmAZF0ENDPOINT1_AZALIA_F0_CODEC_ENDPOINT_INDEX,
+ mmAZF0ENDPOINT2_AZALIA_F0_CODEC_ENDPOINT_INDEX,
+ mmAZF0ENDPOINT3_AZALIA_F0_CODEC_ENDPOINT_INDEX
+};
+
+static const uint32_t audio_data_reg_offset[] = {
+ mmAZF0ENDPOINT0_AZALIA_F0_CODEC_ENDPOINT_DATA,
+ mmAZF0ENDPOINT1_AZALIA_F0_CODEC_ENDPOINT_DATA,
+ mmAZF0ENDPOINT2_AZALIA_F0_CODEC_ENDPOINT_DATA,
+ mmAZF0ENDPOINT3_AZALIA_F0_CODEC_ENDPOINT_DATA,
+};
+
+enum {
+ MAX_NUMBER_OF_AUDIO_PINS = 4
+};
+
+static void destruct(
+ struct hw_ctx_adapter_service_dce110 *hw_ctx)
+{
+ /* There is nothing to destruct at the moment */
+ dal_adapter_service_destruct_hw_ctx(&hw_ctx->base);
+}
+
+static void destroy(
+ struct hw_ctx_adapter_service *ptr)
+{
+ struct hw_ctx_adapter_service_dce110 *hw_ctx =
+ FROM_HW_CTX(ptr);
+
+ destruct(hw_ctx);
+
+ dm_free(ptr->ctx, hw_ctx);
+}
+
+/*
+ * enum_audio_object
+ *
+ * @brief enumerate audio object
+ *
+ * @param
+ * const struct hw_ctx_adapter_service *hw_ctx - [in] provides num of endpoints
+ * uint32_t index - [in] audio index
+ *
+ * @return
+ * grphic object id
+ */
+static struct graphics_object_id enum_audio_object(
+ const struct hw_ctx_adapter_service *hw_ctx,
+ uint32_t index)
+{
+ uint32_t number_of_connected_audio_endpoints =
+ FROM_HW_CTX(hw_ctx)->number_of_connected_audio_endpoints;
+
+ if (index >= number_of_connected_audio_endpoints ||
+ number_of_connected_audio_endpoints == 0)
+ return invalid_go;
+ else
+ return dal_graphics_object_id_init(
+ AUDIO_ID_INTERNAL_AZALIA,
+ (enum object_enum_id)(index + 1),
+ OBJECT_TYPE_AUDIO);
+}
+
+static uint32_t get_number_of_connected_audio_endpoints_multistream(
+ struct dc_context *ctx)
+{
+ uint32_t num_connected_audio_endpoints = 0;
+ uint32_t i;
+ uint32_t default_config =
+ ixAZALIA_F0_CODEC_PIN_CONTROL_RESPONSE_CONFIGURATION_DEFAULT;
+
+ /* find the total number of streams available via the
+ * AZALIA_F0_CODEC_PIN_CONTROL_RESPONSE_CONFIGURATION_DEFAULT
+ * registers (one for each pin) starting from pin 1
+ * up to the max number of audio pins.
+ * We stop on the first pin where
+ * PORT_CONNECTIVITY == 1 (as instructed by HW team).
+ */
+ for (i = 0; i < MAX_NUMBER_OF_AUDIO_PINS; i++) {
+ uint32_t value = 0;
+
+ set_reg_field_value(value,
+ default_config,
+ AZALIA_F0_CODEC_ENDPOINT_INDEX,
+ AZALIA_ENDPOINT_REG_INDEX);
+
+ dm_write_reg(ctx, audio_index_reg_offset[i], value);
+
+ value = 0;
+ value = dm_read_reg(ctx, audio_data_reg_offset[i]);
+
+ /* 1 means not supported*/
+ if (get_reg_field_value(value,
+ AZALIA_F0_CODEC_PIN_CONTROL_RESPONSE_CONFIGURATION_DEFAULT,
+ PORT_CONNECTIVITY) == 1)
+ break;
+
+ num_connected_audio_endpoints++;
+ }
+
+ return num_connected_audio_endpoints;
+
+}
+
+/*
+ * get_number_of_connected_audio_endpoints
+ */
+static uint32_t get_number_of_connected_audio_endpoints(
+ struct hw_ctx_adapter_service *hw_ctx)
+{
+ uint32_t addr = mmCC_DC_HDMI_STRAPS;
+ uint32_t value = 0;
+ uint32_t field = 0;
+
+ if (hw_ctx->cached_audio_straps == AUDIO_STRAPS_NOT_ALLOWED)
+ /* audio straps indicate no audio supported */
+ return 0;
+
+ value = dm_read_reg(hw_ctx->ctx, addr);
+
+ field = get_reg_field_value(
+ value, CC_DC_HDMI_STRAPS, AUDIO_STREAM_NUMBER);
+ if (field == 1)
+ /* multi streams not supported */
+ return 1;
+ else if (field == 0)
+ /* multi streams supported */
+ return get_number_of_connected_audio_endpoints_multistream(
+ hw_ctx->ctx);
+
+ /* unexpected value */
+ ASSERT_CRITICAL(false);
+ return field;
+}
+
+
+/*
+ * power_up
+ *
+ * @brief
+ * Determine and cache audio support from register.
+ *
+ * @param
+ * struct hw_ctx_adapter_service *hw_ctx - [in] adapter service hw context
+ *
+ * @return
+ * true if succeed, false otherwise
+ */
+static bool power_up(
+ struct hw_ctx_adapter_service *hw_ctx)
+{
+ struct hw_ctx_adapter_service_dce110 *hw_ctx_dce11 =
+ FROM_HW_CTX(hw_ctx);
+ /* Allow DP audio all the time
+ * without additional pinstrap check on Fusion */
+
+
+ {
+ uint32_t value = 0;
+ uint32_t field = 0;
+
+ value = dm_read_reg(hw_ctx->ctx, mmCC_DC_HDMI_STRAPS);
+ field = get_reg_field_value(
+ value, CC_DC_HDMI_STRAPS, HDMI_DISABLE);
+
+ if (field == 0) {
+ hw_ctx->cached_audio_straps = AUDIO_STRAPS_DP_HDMI_AUDIO;
+ } else {
+ value = dm_read_reg(
+ hw_ctx->ctx, mmDC_PINSTRAPS);
+ field = get_reg_field_value(
+ value,
+ DC_PINSTRAPS,
+ DC_PINSTRAPS_AUDIO);
+
+ if (field & AUDIO_STRAPS_HDMI_ENABLE)
+ hw_ctx->cached_audio_straps =
+ AUDIO_STRAPS_DP_HDMI_AUDIO_ON_DONGLE;
+ else
+ hw_ctx->cached_audio_straps =
+ AUDIO_STRAPS_DP_AUDIO_ALLOWED;
+ }
+
+ }
+
+ /* get the number of connected audio endpoints */
+ hw_ctx_dce11->number_of_connected_audio_endpoints =
+ get_number_of_connected_audio_endpoints(hw_ctx);
+
+ return true;
+}
+
+static void update_audio_connectivity(
+ struct hw_ctx_adapter_service *hw_ctx,
+ uint32_t number_of_audio_capable_display_path,
+ uint32_t number_of_controllers)
+{
+ /* this one should be empty on DCE110 */
+}
+
+static const struct hw_ctx_adapter_service_funcs funcs = {
+ .destroy = destroy,
+ .power_up = power_up,
+ .enum_fake_path_resource = NULL,
+ .enum_stereo_sync_object = NULL,
+ .enum_sync_output_object = NULL,
+ .enum_audio_object = enum_audio_object,
+ .update_audio_connectivity = update_audio_connectivity
+};
+
+static bool construct(
+ struct hw_ctx_adapter_service_dce110 *hw_ctx,
+ struct dc_context *ctx)
+{
+ if (!dal_adapter_service_construct_hw_ctx(&hw_ctx->base, ctx)) {
+ ASSERT_CRITICAL(false);
+ return false;
+ }
+
+ hw_ctx->base.funcs = &funcs;
+ hw_ctx->number_of_connected_audio_endpoints = 0;
+
+ return true;
+}
+
+struct hw_ctx_adapter_service *
+ dal_adapter_service_create_hw_ctx_dce110(
+ struct dc_context *ctx)
+{
+ struct hw_ctx_adapter_service_dce110 *hw_ctx =
+ dm_alloc(ctx, sizeof(struct hw_ctx_adapter_service_dce110));
+
+ if (!hw_ctx) {
+ ASSERT_CRITICAL(false);
+ return NULL;
+ }
+
+ if (construct(hw_ctx, ctx))
+ return &hw_ctx->base;
+
+ ASSERT_CRITICAL(false);
+
+ dm_free(ctx, hw_ctx);
+
+ return NULL;
+}
diff --git a/drivers/gpu/drm/amd/dal/dc/adapter/dce110/hw_ctx_adapter_service_dce110.h b/drivers/gpu/drm/amd/dal/dc/adapter/dce110/hw_ctx_adapter_service_dce110.h
new file mode 100644
index 000000000000..092b67173dc4
--- /dev/null
+++ b/drivers/gpu/drm/amd/dal/dc/adapter/dce110/hw_ctx_adapter_service_dce110.h
@@ -0,0 +1,40 @@
+/*
+ * 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_HW_CTX_ADAPTER_SERVICE_DCE110_H__
+#define __DAL_HW_CTX_ADAPTER_SERVICE_DCE110_H__
+
+struct hw_ctx_adapter_service_dce110 {
+ struct hw_ctx_adapter_service base;
+ uint32_t number_of_connected_audio_endpoints;
+};
+
+struct hw_ctx_adapter_service *
+ dal_adapter_service_create_hw_ctx_dce110(
+ struct dc_context *ctx);
+
+#endif /* __DAL_HW_CTX_ADAPTER_SERVICE_DCE110_H__ */
+
+
diff --git a/drivers/gpu/drm/amd/dal/dc/adapter/diagnostics/hw_ctx_adapter_service_diag.c b/drivers/gpu/drm/amd/dal/dc/adapter/diagnostics/hw_ctx_adapter_service_diag.c
new file mode 100644
index 000000000000..4f5f0403af84
--- /dev/null
+++ b/drivers/gpu/drm/amd/dal/dc/adapter/diagnostics/hw_ctx_adapter_service_diag.c
@@ -0,0 +1,133 @@
+/*
+ * Copyright 2012-16 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
+ *
+ */
+
+/* FPGA Diagnostics version of AS HW CTX. */
+
+#include "dm_services.h"
+
+#include "../hw_ctx_adapter_service.h"
+
+#include "hw_ctx_adapter_service_diag.h"
+
+#include "include/logger_interface.h"
+#include "include/grph_object_id.h"
+
+static const struct graphics_object_id invalid_go = {
+ 0, ENUM_ID_UNKNOWN, OBJECT_TYPE_UNKNOWN
+};
+
+static void destroy(
+ struct hw_ctx_adapter_service *hw_ctx)
+{
+}
+
+static bool power_up(
+ struct hw_ctx_adapter_service *hw_ctx)
+{
+ return true;
+}
+
+static struct graphics_object_id enum_fake_path_resource(
+ const struct hw_ctx_adapter_service *hw_ctx,
+ uint32_t index)
+{
+ return invalid_go;
+}
+
+static struct graphics_object_id enum_stereo_sync_object(
+ const struct hw_ctx_adapter_service *hw_ctx,
+ uint32_t index)
+{
+ return invalid_go;
+}
+
+static struct graphics_object_id enum_sync_output_object(
+ const struct hw_ctx_adapter_service *hw_ctx,
+ uint32_t index)
+{
+ return invalid_go;
+}
+
+static struct graphics_object_id enum_audio_object(
+ const struct hw_ctx_adapter_service *hw_ctx,
+ uint32_t index)
+{
+ return invalid_go;
+}
+
+static void update_audio_connectivity(
+ struct hw_ctx_adapter_service *hw_ctx,
+ uint32_t number_of_audio_capable_display_path,
+ uint32_t number_of_controllers)
+{
+}
+
+static const struct hw_ctx_adapter_service_funcs funcs = {
+ destroy,
+ power_up,
+ enum_fake_path_resource,
+ enum_stereo_sync_object,
+ enum_sync_output_object,
+ enum_audio_object,
+ update_audio_connectivity
+};
+
+static bool construct(
+ struct hw_ctx_adapter_service *hw_ctx,
+ struct dc_context *ctx)
+
+{
+ if (!dal_adapter_service_construct_hw_ctx(hw_ctx, ctx)) {
+ ASSERT_CRITICAL(false);
+ return false;
+ }
+
+ hw_ctx->funcs = &funcs;
+
+ return true;
+}
+
+struct hw_ctx_adapter_service *dal_adapter_service_create_hw_ctx_diag(
+ struct dc_context *ctx)
+{
+ struct hw_ctx_adapter_service *hw_ctx = dm_alloc(ctx,
+ sizeof(*hw_ctx));
+
+ if (!hw_ctx) {
+ ASSERT_CRITICAL(false);
+ return NULL;
+ }
+
+ if (construct(hw_ctx, ctx))
+ return hw_ctx;
+
+ ASSERT_CRITICAL(false);
+
+ dm_free(ctx, hw_ctx);
+
+ return NULL;
+}
+
+/*****************************************************************************/
diff --git a/drivers/gpu/drm/amd/dal/dc/adapter/diagnostics/hw_ctx_adapter_service_diag.h b/drivers/gpu/drm/amd/dal/dc/adapter/diagnostics/hw_ctx_adapter_service_diag.h
new file mode 100644
index 000000000000..39ae7524506c
--- /dev/null
+++ b/drivers/gpu/drm/amd/dal/dc/adapter/diagnostics/hw_ctx_adapter_service_diag.h
@@ -0,0 +1,33 @@
+/*
+ * Copyright 2012-16 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_HW_CTX_ADAPTER_SERVICE_DIAG_H__
+#define __DAL_HW_CTX_ADAPTER_SERVICE_DIAG_H__
+
+
+struct hw_ctx_adapter_service *dal_adapter_service_create_hw_ctx_diag(
+ struct dc_context *ctx);
+
+#endif /* __DAL_HW_CTX_ADAPTER_SERVICE_DIAG_H__ */
diff --git a/drivers/gpu/drm/amd/dal/dc/adapter/hw_ctx_adapter_service.c b/drivers/gpu/drm/amd/dal/dc/adapter/hw_ctx_adapter_service.c
new file mode 100644
index 000000000000..12eabe0c3f89
--- /dev/null
+++ b/drivers/gpu/drm/amd/dal/dc/adapter/hw_ctx_adapter_service.c
@@ -0,0 +1,164 @@
+/*
+ * 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/adapter_service_types.h"
+#include "include/grph_object_id.h"
+#include "hw_ctx_adapter_service.h"
+
+static const struct graphics_object_id invalid_go = {
+ 0, ENUM_ID_UNKNOWN, OBJECT_TYPE_UNKNOWN
+};
+
+static void destroy(
+ struct hw_ctx_adapter_service *hw_ctx)
+{
+ /* Attention!
+ * You must override impl method in derived class */
+ BREAK_TO_DEBUGGER();
+}
+
+static bool power_up(
+ struct hw_ctx_adapter_service *hw_ctx)
+{
+ /* Attention!
+ * You must override impl method in derived class */
+ BREAK_TO_DEBUGGER();
+
+ return false;
+}
+
+static struct graphics_object_id enum_fake_path_resource(
+ const struct hw_ctx_adapter_service *hw_ctx,
+ uint32_t index)
+{
+ return invalid_go;
+}
+
+static struct graphics_object_id enum_stereo_sync_object(
+ const struct hw_ctx_adapter_service *hw_ctx,
+ uint32_t index)
+{
+ return invalid_go;
+}
+
+static struct graphics_object_id enum_sync_output_object(
+ const struct hw_ctx_adapter_service *hw_ctx,
+ uint32_t index)
+{
+ return invalid_go;
+}
+
+static struct graphics_object_id enum_audio_object(
+ const struct hw_ctx_adapter_service *hw_ctx,
+ uint32_t index)
+{
+ /* by default, we only allow one audio */
+
+ if (index > 0)
+ return invalid_go;
+ else if (hw_ctx->cached_audio_straps == AUDIO_STRAPS_NOT_ALLOWED)
+ return invalid_go;
+ else
+ return dal_graphics_object_id_init(
+ AUDIO_ID_INTERNAL_AZALIA,
+ ENUM_ID_1,
+ OBJECT_TYPE_AUDIO);
+}
+
+static void update_audio_connectivity(
+ struct hw_ctx_adapter_service *hw_ctx,
+ uint32_t number_of_audio_capable_display_path,
+ uint32_t number_of_controllers)
+{
+ /* Attention!
+ * You must override impl method in derived class */
+ BREAK_TO_DEBUGGER();
+}
+
+static const struct hw_ctx_adapter_service_funcs funcs = {
+ destroy,
+ power_up,
+ enum_fake_path_resource,
+ enum_stereo_sync_object,
+ enum_sync_output_object,
+ enum_audio_object,
+ update_audio_connectivity
+};
+
+bool dal_adapter_service_construct_hw_ctx(
+ struct hw_ctx_adapter_service *hw_ctx,
+ struct dc_context *ctx)
+{
+
+ hw_ctx->ctx = ctx;
+ hw_ctx->funcs = &funcs;
+ hw_ctx->cached_audio_straps = AUDIO_STRAPS_NOT_ALLOWED;
+
+ return true;
+}
+
+union audio_support dal_adapter_service_hw_ctx_get_audio_support(
+ const struct hw_ctx_adapter_service *hw_ctx)
+{
+ union audio_support result;
+
+ result.raw = 0;
+
+ switch (hw_ctx->cached_audio_straps) {
+ case AUDIO_STRAPS_DP_HDMI_AUDIO:
+ result.bits.HDMI_AUDIO_NATIVE = true;
+ /* do not break ! */
+ case AUDIO_STRAPS_DP_HDMI_AUDIO_ON_DONGLE:
+ result.bits.HDMI_AUDIO_ON_DONGLE = true;
+ /* do not break ! */
+ case AUDIO_STRAPS_DP_AUDIO_ALLOWED:
+ result.bits.DP_AUDIO = true;
+ break;
+ default:
+ break;
+ }
+
+ return result;
+}
+
+void dal_adapter_service_destruct_hw_ctx(
+ struct hw_ctx_adapter_service *hw_ctx)
+{
+ /* There is nothing to destruct at the moment */
+}
+
+void dal_adapter_service_destroy_hw_ctx(
+ struct hw_ctx_adapter_service **ptr)
+{
+ if (!ptr || !*ptr) {
+ BREAK_TO_DEBUGGER();
+ return;
+ }
+
+ (*ptr)->funcs->destroy(*ptr);
+
+ *ptr = NULL;
+}
diff --git a/drivers/gpu/drm/amd/dal/dc/adapter/hw_ctx_adapter_service.h b/drivers/gpu/drm/amd/dal/dc/adapter/hw_ctx_adapter_service.h
new file mode 100644
index 000000000000..f98c2d428b2a
--- /dev/null
+++ b/drivers/gpu/drm/amd/dal/dc/adapter/hw_ctx_adapter_service.h
@@ -0,0 +1,86 @@
+/*
+ * 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_HW_CTX_ADAPTER_SERVICE_H__
+#define __DAL_HW_CTX_ADAPTER_SERVICE_H__
+
+enum audio_straps {
+ AUDIO_STRAPS_NOT_ALLOWED = 0,
+ AUDIO_STRAPS_DP_AUDIO_ALLOWED,
+ AUDIO_STRAPS_DP_HDMI_AUDIO_ON_DONGLE,
+ AUDIO_STRAPS_DP_HDMI_AUDIO
+};
+
+struct hw_ctx_adapter_service;
+
+struct hw_ctx_adapter_service_funcs {
+ void (*destroy)(
+ struct hw_ctx_adapter_service *hw_ctx);
+ /* Initializes relevant HW registers
+ * and caches relevant data from HW registers */
+ bool (*power_up)(
+ struct hw_ctx_adapter_service *hw_ctx);
+ /* Enumerate fake path resources */
+ struct graphics_object_id (*enum_fake_path_resource)(
+ const struct hw_ctx_adapter_service *hw_ctx,
+ uint32_t index);
+ /* Enumerate stereo sync objects */
+ struct graphics_object_id (*enum_stereo_sync_object)(
+ const struct hw_ctx_adapter_service *hw_ctx,
+ uint32_t index);
+ /* Enumerate (H/V) sync output objects */
+ struct graphics_object_id (*enum_sync_output_object)(
+ const struct hw_ctx_adapter_service *hw_ctx,
+ uint32_t index);
+ /* Enumerate audio objects */
+ struct graphics_object_id (*enum_audio_object)(
+ const struct hw_ctx_adapter_service *hw_ctx,
+ uint32_t index);
+ void (*update_audio_connectivity)(
+ struct hw_ctx_adapter_service *hw_ctx,
+ uint32_t number_of_audio_capable_display_path,
+ uint32_t number_of_controllers);
+};
+
+struct hw_ctx_adapter_service {
+ struct dc_context *ctx;
+ const struct hw_ctx_adapter_service_funcs *funcs;
+ enum audio_straps cached_audio_straps;
+};
+
+bool dal_adapter_service_construct_hw_ctx(
+ struct hw_ctx_adapter_service *hw_ctx,
+ struct dc_context *ctx);
+
+union audio_support dal_adapter_service_hw_ctx_get_audio_support(
+ const struct hw_ctx_adapter_service *hw_ctx);
+
+void dal_adapter_service_destruct_hw_ctx(
+ struct hw_ctx_adapter_service *hw_ctx);
+
+void dal_adapter_service_destroy_hw_ctx(
+ struct hw_ctx_adapter_service **ptr);
+
+#endif /* __DAL_HW_CTX_ADAPTER_SERVICE_H__ */
diff --git a/drivers/gpu/drm/amd/dal/dc/adapter/wireless_data_source.c b/drivers/gpu/drm/amd/dal/dc/adapter/wireless_data_source.c
new file mode 100644
index 000000000000..0b1151ec5a2c
--- /dev/null
+++ b/drivers/gpu/drm/amd/dal/dc/adapter/wireless_data_source.c
@@ -0,0 +1,208 @@
+/*
+ * 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 "adapter_service.h"
+#include "wireless_data_source.h"
+
+#include "atom.h"
+
+/*construct wireless data*/
+bool wireless_data_init(struct wireless_data *data,
+ struct dc_bios *dcb,
+ struct wireless_init_data *init_data)
+{
+ struct firmware_info info;
+
+ if (data == NULL || dcb == NULL || init_data == NULL) {
+ ASSERT_CRITICAL(false);
+ return false;
+ }
+
+ data->miracast_connector_enable = false;
+ data->wireless_disp_path_enable = false;
+ data->wireless_enable = false;
+
+ /* Wireless it not supported if VCE is not supported */
+ if (!init_data->vce_supported)
+ return true;
+
+ if (init_data->miracast_target_required)
+ data->miracast_connector_enable = true;
+
+ /*
+ * If override is in place for platform support, we will both
+ * enable wireless display as a feature (i.e. CCC aspect) and
+ * enable the wireless display path without any further checks.
+ */
+ if (init_data->platform_override) {
+ data->wireless_enable = true;
+ data->wireless_disp_path_enable = true;
+ } else {
+ /*
+ * Check if SBIOS sets remote display enable, exposed
+ * through VBIOS. This is only valid for APU, not dGPU
+ */
+ dcb->funcs->get_firmware_info(dcb, &info);
+
+ if ((REMOTE_DISPLAY_ENABLE == info.remote_display_config) &&
+ init_data->fusion) {
+ data->wireless_enable = true;
+ data->wireless_disp_path_enable = true;
+ }
+ }
+
+ /*
+ * If remote display path override is enabled, we enable just the
+ * remote display path. This is mainly used for testing purposes
+ */
+ if (init_data->remote_disp_path_override)
+ data->wireless_disp_path_enable = true;
+
+ return true;
+}
+
+uint8_t wireless_get_clocks_num(
+ struct adapter_service *as)
+{
+ if (as->wireless_data.wireless_enable ||
+ as->wireless_data.wireless_disp_path_enable)
+ return 1;
+ else
+ return 0;
+}
+
+static uint8_t wireless_get_encoders_num(
+ struct adapter_service *as)
+{
+ if (as->wireless_data.wireless_enable ||
+ as->wireless_data.wireless_disp_path_enable)
+ return 1;
+ else
+ return 0;
+}
+
+uint8_t wireless_get_connectors_num(
+ struct adapter_service *as)
+{
+ uint8_t wireless_connectors_num = 0;
+
+ if (as->wireless_data.wireless_enable &&
+ as->wireless_data.miracast_connector_enable)
+ wireless_connectors_num++;
+
+ if (as->wireless_data.wireless_disp_path_enable)
+ wireless_connectors_num++;
+
+ return wireless_connectors_num;
+}
+
+struct graphics_object_id wireless_get_connector_id(
+ struct adapter_service *as,
+ uint8_t index)
+{
+ struct graphics_object_id unknown_object_id =
+ dal_graphics_object_id_init(
+ 0,
+ ENUM_ID_UNKNOWN,
+ OBJECT_TYPE_UNKNOWN);
+
+ if (!as->wireless_data.wireless_enable &&
+ !as->wireless_data.wireless_disp_path_enable)
+ return unknown_object_id;
+
+ else if (!as->wireless_data.miracast_connector_enable)
+ return dal_graphics_object_id_init(
+ CONNECTOR_ID_WIRELESS,
+ ENUM_ID_1,
+ OBJECT_TYPE_CONNECTOR);
+
+ switch (index) {
+ case 0:
+ return dal_graphics_object_id_init(
+ CONNECTOR_ID_WIRELESS,
+ ENUM_ID_1,
+ OBJECT_TYPE_CONNECTOR);
+ break;
+ case 1:
+ return dal_graphics_object_id_init(
+ CONNECTOR_ID_MIRACAST,
+ ENUM_ID_1,
+ OBJECT_TYPE_CONNECTOR);
+ break;
+ default:
+ return unknown_object_id;
+ }
+}
+
+uint8_t wireless_get_srcs_num(
+ struct adapter_service *as,
+ struct graphics_object_id id)
+{
+ switch (id.type) {
+ case OBJECT_TYPE_CONNECTOR:
+ return wireless_get_encoders_num(as);
+ case OBJECT_TYPE_ENCODER:
+ return 1;
+
+ default:
+ ASSERT_CRITICAL(false);
+ break;
+ }
+
+ return 0;
+}
+
+struct graphics_object_id wireless_get_src_obj_id(
+ struct adapter_service *as,
+ struct graphics_object_id id,
+ uint8_t index)
+{
+ if (index < wireless_get_srcs_num(as, id)) {
+ switch (id.type) {
+ case OBJECT_TYPE_CONNECTOR:
+ return dal_graphics_object_id_init(
+ ENCODER_ID_INTERNAL_WIRELESS,
+ ENUM_ID_1,
+ OBJECT_TYPE_ENCODER);
+ break;
+ case OBJECT_TYPE_ENCODER:
+ return dal_graphics_object_id_init(
+ 0,
+ ENUM_ID_1,
+ OBJECT_TYPE_GPU);
+ break;
+ default:
+ ASSERT_CRITICAL(false);
+ break;
+ }
+ }
+
+ return dal_graphics_object_id_init(
+ 0,
+ ENUM_ID_UNKNOWN,
+ OBJECT_TYPE_UNKNOWN);
+}
diff --git a/drivers/gpu/drm/amd/dal/dc/adapter/wireless_data_source.h b/drivers/gpu/drm/amd/dal/dc/adapter/wireless_data_source.h
new file mode 100644
index 000000000000..b64089e3960e
--- /dev/null
+++ b/drivers/gpu/drm/amd/dal/dc/adapter/wireless_data_source.h
@@ -0,0 +1,80 @@
+/*
+ * 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_WIRELESS_DATA_SOURCE_H__
+#define __DAL_WIRELESS_DATA_SOURCE_H__
+
+/* Include */
+#include "include/grph_object_id.h"
+
+/*
+ * Forward declaration
+ */
+struct adapter_service;
+struct dc_bios;
+
+/* Wireless data init structure */
+struct wireless_init_data {
+ bool fusion; /* Fusion flag */
+ bool platform_override; /* Override for platform BIOS option */
+ bool remote_disp_path_override; /* Override enabling wireless path */
+ bool vce_supported; /* Existence of VCE block on this DCE */
+ bool miracast_target_required; /* OS requires Miracast target */
+};
+
+/* Wireless data */
+struct wireless_data {
+ bool wireless_enable;
+ bool wireless_disp_path_enable;
+ bool miracast_connector_enable;
+};
+
+
+/*construct wireless data*/
+bool wireless_data_init(
+ struct wireless_data *data,
+ struct dc_bios *dcb,
+ struct wireless_init_data *init_data);
+
+uint8_t wireless_get_clocks_num(
+ struct adapter_service *as);
+
+uint8_t wireless_get_connectors_num(
+ struct adapter_service *as);
+
+struct graphics_object_id wireless_get_connector_id(
+ struct adapter_service *as,
+ uint8_t connector_index);
+
+uint8_t wireless_get_srcs_num(
+ struct adapter_service *as,
+ struct graphics_object_id id);
+
+struct graphics_object_id wireless_get_src_obj_id(
+ struct adapter_service *as,
+ struct graphics_object_id id,
+ uint8_t index);
+
+#endif /* __DAL_WIRELESS_DATA_SOURCE_H__ */