summaryrefslogtreecommitdiff
path: root/drivers/gpu/drm
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/gpu/drm')
-rw-r--r--drivers/gpu/drm/amd/dal/Makefile6
-rw-r--r--drivers/gpu/drm/amd/dal/include/bm_calcs.h31
-rw-r--r--drivers/gpu/drm/amd/dal/include/dal_interface.h261
-rw-r--r--drivers/gpu/drm/amd/dal/include/timing_list_query_interface.h83
-rw-r--r--drivers/gpu/drm/amd/dal/interface/Makefile10
-rw-r--r--drivers/gpu/drm/amd/dal/interface/dal.c1665
-rw-r--r--drivers/gpu/drm/amd/dal/interface/timing_list_query.c371
7 files changed, 2424 insertions, 3 deletions
diff --git a/drivers/gpu/drm/amd/dal/Makefile b/drivers/gpu/drm/amd/dal/Makefile
index b95ba1e51f55..d99e75f9b9ca 100644
--- a/drivers/gpu/drm/amd/dal/Makefile
+++ b/drivers/gpu/drm/amd/dal/Makefile
@@ -8,9 +8,9 @@ AMDDALPATH = $(RELATIVE_AMD_DAL_PATH)
subdir-ccflags-y += -I$(AMDDALPATH)/ -I$(AMDDALPATH)/include -DDAL_CZ_BRINGUP
DAL_LIBS = adapter amdgpu_dm audio asic_capability basics bios connector \
- controller dcs display_service display_path encoder gpio gpu \
- hw_sequencer i2caux irq link_service mode_manager timing_service \
- topology
+ controller dcs display_path display_service encoder gpio gpu \
+ hw_sequencer i2caux interface link_service mode_manager timing_service \
+ topology irq
AMD_DAL = $(addsuffix /Makefile, $(addprefix $(FULL_AMD_DAL_PATH)/,$(DAL_LIBS)))
diff --git a/drivers/gpu/drm/amd/dal/include/bm_calcs.h b/drivers/gpu/drm/amd/dal/include/bm_calcs.h
new file mode 100644
index 000000000000..4a5e2507da91
--- /dev/null
+++ b/drivers/gpu/drm/amd/dal/include/bm_calcs.h
@@ -0,0 +1,31 @@
+/*
+ * 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_BM_CALCS_H__
+#define __DAL_BM_CALCS_H__
+
+#include "bandwidth_manager_types.h"
+
+#endif /* __DAL_BM_CALCS_H__ */
diff --git a/drivers/gpu/drm/amd/dal/include/dal_interface.h b/drivers/gpu/drm/amd/dal/include/dal_interface.h
new file mode 100644
index 000000000000..4b7dca42e657
--- /dev/null
+++ b/drivers/gpu/drm/amd/dal/include/dal_interface.h
@@ -0,0 +1,261 @@
+/*
+ * 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_INTERFACE_H__
+#define __DAL_INTERFACE_H__
+
+#include "dal_types.h"
+#include "dal_asic_id.h"
+#include "set_mode_types.h"
+#include "plane_types.h"
+#include "dcs_types.h"
+#include "timing_list_query_interface.h"
+
+struct dal;
+struct dal_to_path_mode_set;
+struct surface_attributes;
+struct surface_address;
+struct view_port_area;
+struct dal_timing_list_query;
+struct topology_mgr;
+struct power_to_dal_info;
+struct address_info;
+struct wifi_display_caps;
+struct path_mode;
+struct path_mode_set;
+
+struct dal *dal_create(struct dal_init_data *init);
+void dal_destroy(struct dal **dal);
+
+/**
+ * Enable the DAL instance after resume from (S3/S4)
+ *
+ * Enables instance of the DAL specific to an adapter after resume.
+ * The function sets up the display mapping based on appropriate boot-up
+ * behaviour.
+ */
+void dal_resume(struct dal *dal);
+
+/* HW Capability queries */
+uint32_t dal_get_controllers_number(struct dal *dal);
+uint32_t dal_get_connected_targets_vector(struct dal *dal);
+uint32_t dal_get_cofunctional_targets_number(struct dal *dal);
+
+/* Return a bitvector of *all* Display Paths. */
+uint32_t dal_get_supported_displays_vector(struct dal *dal);
+/* Return a bitvector of a *single* Display Path. */
+uint32_t dal_get_display_vector_by_index(struct dal *dal,
+ uint32_t display_index);
+
+uint32_t dal_get_a_display_index_by_type(
+ struct dal *dal,
+ uint32_t display_type);
+
+enum signal_type dal_get_display_signal(
+ struct dal *dal,
+ uint32_t display_index);
+
+const uint8_t *dal_get_display_edid(
+ struct dal *dal,
+ uint32_t display_index,
+ uint32_t *buff_size);
+
+void dal_get_screen_info(
+ struct dal *dal,
+ uint32_t display_index,
+ struct edid_screen_info *screen_info);
+
+/* TODO: implement later
+bool dal_get_display_output_descriptor (struct dal *dal,
+ uint32_t display_index,
+ struct dal_display_output_descriptor *display_descriptor);
+*/
+
+/**************** Mode Validate / Set ****************/
+bool dal_set_path_mode(struct dal *dal,
+ const struct path_mode_set *pms);
+
+bool dal_reset_path_mode(struct dal *dal,
+ const uint32_t displays_num,
+ const uint32_t *display_indexes);
+
+struct mode_query;
+void dal_pin_active_path_modes(
+ struct dal *dal,
+ void *param,
+ uint32_t display_index,
+ void (*func)(void *, const struct path_mode *));
+
+/******************** PowerPlay ********************/
+
+bool dal_pre_adapter_clock_change(struct dal *dal,
+ struct power_to_dal_info *clks_info);
+
+bool dal_post_adapter_clock_change(struct dal *dal);
+
+/***************** Power Control *****************/
+void dal_set_display_dpms(
+ struct dal *dal,
+ uint32_t display_index,
+ uint32_t state);
+
+void dal_set_power_state(
+ struct dal *dal,
+ uint32_t power_state,
+ uint32_t video_power_state);
+
+void dal_set_blanking(struct dal *dal, uint32_t display_index, bool blank);
+void dal_shut_down_display_block(struct dal *dal);
+
+/***************** Brightness Interface *****************/
+bool dal_set_backlight_level(
+ struct dal *dal,
+ uint32_t display_index,
+ uint32_t brightness);
+bool dal_get_backlight_level_old(
+ struct dal *dal,
+ uint32_t display_index,
+ void *adjustment);
+bool dal_backlight_control_on(struct dal *dal);
+bool dal_backlight_control_off(struct dal *dal);
+
+/***************** Brightness and color Control *****************/
+void dal_set_palette(
+ struct dal *dal,
+ uint32_t display_index,
+ struct dal_dev_c_lut palette,
+ uint32_t start,
+ uint32_t length);
+
+bool dal_set_gamma(
+ struct dal *dal,
+ uint32_t display_index,
+ struct raw_gamma_ramp *gamma);
+
+/* Active Stereo Interface */
+bool dal_control_stereo(struct dal *dal, uint32_t display_index, bool enable);
+
+/* Disable All DC Pipes - blank CRTC and disable memory requests */
+void dal_disable_all_dc_pipes(struct dal *dal);
+
+/*
+uint32_t dal_get_interrupt_source(const struct dal_display_index_set *set,
+ uint64_t *irq_source);
+*/
+
+/* Timing List Query */
+struct dal_timing_list_query *dal_create_timing_list_query(struct dal *dal,
+ uint32_t display_index);
+
+/*hard code color square at CRTC0 for HDMI light up*/
+void dal_set_crtc_test_pattern(struct dal *dal);
+
+/* returns the display_index associated (that generated) to irq source */
+enum dal_irq_source;
+uint32_t dal_get_display_index_from_int_src(
+ struct dal *dal,
+ enum dal_irq_source src);
+
+/* return crtc scanout v/h counter, return if inside v_blank*/
+uint32_t dal_get_crtc_scanoutpos(
+ struct dal *dal,
+ uint32_t display_index,
+ int32_t *vpos,
+ int32_t *hpos);
+
+/* Return IRQ Source for Controller currently assigned to the Path. */
+enum dal_irq_source dal_get_vblank_irq_src_from_display_index(struct dal *dal,
+ uint32_t display_index);
+enum dal_irq_source dal_get_pflip_irq_src_from_display_index(struct dal *dal,
+ uint32_t display_index,
+ uint32_t plane_no);
+
+void dal_set_vblank_irq(struct dal *dal, uint32_t display_index, bool enable);
+
+
+struct topology;
+enum query_option;
+
+struct mode_query *dal_get_mode_query(
+ struct dal *dal,
+ struct topology *tp,
+ enum query_option query_option);
+
+struct mode_manager *dal_get_mode_manager(struct dal *dal);
+
+uint32_t dal_wifi_display_acquire(
+ struct dal *dal,
+ uint8_t *edid_data,
+ uint32_t edid_size,
+ struct dal_remote_display_receiver_capability *caps,
+ uint32_t *display_index);
+
+uint32_t dal_wifi_display_release(
+ struct dal *dal,
+ uint32_t *display_index);
+
+/* Get the current vertical blank counts for given CRTC. */
+uint32_t dal_get_vblank_counter(struct dal *dal, int disp_idx);
+
+/* Surface programming interface */
+
+/* TODO: move these below to separate header */
+bool dal_set_cursor_position(
+ struct dal *dal,
+ const uint32_t display_index,
+ const struct cursor_position *position
+ );
+
+bool dal_set_cursor_attributes(
+ struct dal *dal,
+ const uint32_t display_index,
+ const struct cursor_attributes *attributes
+ );
+
+bool dal_setup_plane_configurations(
+ struct dal *dal,
+ uint32_t num_planes,
+ struct plane_config *configs);
+
+bool dal_update_plane_addresses(
+ struct dal *dal,
+ uint32_t num_planes,
+ struct plane_addr_flip_info *info);
+
+bool dal_validate_plane_configurations(struct dal *dal,
+ int num_planes,
+ const struct plane_config *pl_config,
+ bool *supported);
+
+void dal_interrupt_set(struct dal *dal, enum dal_irq_source src, bool enable);
+
+void dal_interrupt_ack(struct dal *dal, enum dal_irq_source src);
+
+enum dal_irq_source dal_interrupt_to_irq_source(
+ struct dal *dal,
+ uint32_t src_id,
+ uint32_t ext_id);
+
+#endif
diff --git a/drivers/gpu/drm/amd/dal/include/timing_list_query_interface.h b/drivers/gpu/drm/amd/dal/include/timing_list_query_interface.h
new file mode 100644
index 000000000000..6f3564c58c24
--- /dev/null
+++ b/drivers/gpu/drm/amd/dal/include/timing_list_query_interface.h
@@ -0,0 +1,83 @@
+/*
+ * 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_TIMING_LIST_QUERY_INTERFACE_H__
+#define __DAL_TIMING_LIST_QUERY_INTERFACE_H__
+
+/* External dependencies */
+#include "include/timing_service_types.h"
+#include "include/dcs_interface.h"
+
+/* Forward declarations */
+struct dal;
+struct dal_timing_list_query;
+
+enum timing_support_level {
+ TIMING_SUPPORT_LEVEL_UNDEFINED,
+ /* assumed to be guaranteed supported by display,
+ * usually one timing is marked as native */
+ TIMING_SUPPORT_LEVEL_NATIVE,
+ /* user wants DAL to drive this timing as if Display supports it */
+ TIMING_SUPPORT_LEVEL_GUARANTEED,
+ /* user wants DAL to drive this timing even if display
+ * may not support it */
+ TIMING_SUPPORT_LEVEL_NOT_GUARANTEED
+};
+
+struct timing_list_query_init_data {
+ struct dal *dal; /* an instance of DAL */
+ struct timing_service *timing_srv;
+ struct dcs *dcs;
+ uint32_t display_index;
+};
+
+struct dal_timing_list_query *dal_timing_list_query_create(
+ struct timing_list_query_init_data *init_data);
+
+void dal_timing_list_query_destroy(struct dal_timing_list_query **tlsq);
+
+/* Get count of mode timings in the list. */
+uint32_t dal_timing_list_query_get_mode_timing_count(
+ const struct dal_timing_list_query *tlsq);
+
+const struct mode_timing *dal_timing_list_query_get_mode_timing_at_index(
+ const struct dal_timing_list_query *tlsq,
+ uint32_t index);
+
+/**
+ *****************************************************************************
+ * timing_list_query_add_timing() is used to add timing to a target timing
+ * mode list.
+ * In case device disconnected, the previously added modes will be stay with
+ * the target mode list until a newly connected device arrival and added
+ * timing will be removed automatically by DAL.
+ *****************************************************************************
+ */
+bool dal_timing_list_query_add_timing(struct dal_timing_list_query *tlsq,
+ const struct crtc_timing *crtc_timing,
+ enum timing_support_level support_level);
+
+
+#endif /* __DAL_TIMING_LIST_QUERY_INTERFACE_H__ */
diff --git a/drivers/gpu/drm/amd/dal/interface/Makefile b/drivers/gpu/drm/amd/dal/interface/Makefile
new file mode 100644
index 000000000000..cde4ab301efe
--- /dev/null
+++ b/drivers/gpu/drm/amd/dal/interface/Makefile
@@ -0,0 +1,10 @@
+#
+# Makefile for the 'dal_services' sub-component of DAL.
+# It provides the entry point for all DAL services to the driver.
+
+
+INTERFACE = dal.o timing_list_query.o
+
+AMD_DAL_INTERFACE = $(addprefix $(AMDDALPATH)/interface/,$(INTERFACE))
+
+AMD_DAL_FILES += $(AMD_DAL_INTERFACE)
diff --git a/drivers/gpu/drm/amd/dal/interface/dal.c b/drivers/gpu/drm/amd/dal/interface/dal.c
new file mode 100644
index 000000000000..115ab3c00dd2
--- /dev/null
+++ b/drivers/gpu/drm/amd/dal/interface/dal.c
@@ -0,0 +1,1665 @@
+/*
+ * 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 "dal_services.h"
+
+#include "include/dal_interface.h"
+#include "include/adapter_service_interface.h"
+#include "include/timing_service_interface.h"
+#include "include/topology_mgr_interface.h"
+#include "include/gpu_interface.h"
+#include "include/timing_list_query_interface.h"
+#include "include/display_service_interface.h"
+#include "include/set_mode_interface.h"
+#include "include/adjustment_interface.h"
+#include "include/display_path_interface.h"
+#include "include/controller_interface.h"
+#include "include/hw_sequencer_interface.h"
+#include "include/logger_interface.h"
+#include "include/mode_manager_interface.h"
+#include "include/dcs_interface.h"
+#include "include/irq_service_interface.h"
+
+/*
+* DAL - Display Abstraction Layer
+* represents the main high level object that provides
+* abstracted display services. One such object needs to
+* be created per GPU ASIC.
+*/
+
+struct dal {
+ struct dal_init_data init_data;
+ struct dal_context dal_context;
+ struct adapter_service *adapter_srv;
+ struct timing_service *timing_srv;
+ struct topology_mgr *topology_mgr;
+ struct display_service *display_service;
+ struct hw_sequencer *hws;
+ struct mode_manager *mm;
+ struct irq_service *irqs;
+};
+
+/* debugging macro definitions */
+#define DAL_IF_TRACE() \
+ dal_logger_write(dal_context->logger, \
+ LOG_MAJOR_INTERFACE_TRACE, \
+ LOG_MINOR_COMPONENT_DAL_INTERFACE, \
+ "DAL_IF_TRACE: %s()\n", __func__)
+
+#define DAL_IF_NOT_IMPLEMENTED() \
+ DAL_LOGGER_NOT_IMPL(LOG_MINOR_COMPONENT_DAL_INTERFACE, \
+ "DAL_IF:%s()\n", __func__)
+
+#define DAL_IF_ERROR(...) \
+ dal_logger_write(dal_context->logger, \
+ LOG_MAJOR_ERROR, \
+ LOG_MINOR_COMPONENT_DAL_INTERFACE, \
+ __VA_ARGS__)
+
+enum {
+ MAX_PLANE_NUM = 4
+};
+/******************************************************************************
+ Declarations for Timing List Query.
+******************************************************************************/
+
+/******************************************************************************
+ Prototypes of private functions.
+******************************************************************************/
+static bool dal_construct(struct dal_init_data *init,
+ struct dal *dal);
+static void dal_destruct(struct dal *dal);
+static struct adapter_service *create_as(
+ struct dal *dal);
+static bool dal_enable(struct dal *dal);
+
+/******************************************************************************
+ Implementation of the API provided by DAL.
+******************************************************************************/
+struct dal *dal_create(struct dal_init_data *init)
+{
+ struct dal *dal_instance = NULL;
+
+ /* DAL_IF_TRACE();*/
+
+ dal_instance = dal_alloc(sizeof(*dal_instance));
+
+ if (NULL == dal_instance) {
+ /*DAL_IF_ERROR("%s: failed to allocate %ld bytes!\n",
+ __func__, sizeof(*dal_instance)); */
+ return NULL;
+ }
+
+ if (!dal_construct(init, dal_instance)) {
+ dal_free(dal_instance);
+ return NULL;
+ }
+
+ return dal_instance;
+}
+
+void dal_destroy(struct dal **dal)
+{
+ struct dal_context *dal_context = NULL;
+
+ if (dal == NULL || *dal == NULL)
+ return;
+ dal_context = &((*dal)->dal_context);
+
+ DAL_IF_TRACE();
+
+ /***************************************
+ * deallocate all subcomponents of DAL
+ ***************************************/
+ dal_destruct(*dal);
+
+ /*************************
+ * deallocate DAL itself
+ *************************/
+ dal_free(*dal);
+ *dal = NULL;
+}
+
+static bool dal_construct(struct dal_init_data *init,
+ struct dal *dal_instance)
+{
+ struct dal_context *dal_context = &dal_instance->dal_context;
+
+ dal_instance->init_data = *init;
+ dal_instance->dal_context.driver_context = init->driver;
+ dal_instance->dal_context.cgs_device = init->cgs_device;
+
+ /* Logger */
+
+ dal_instance->dal_context.logger = dal_logger_create();
+
+ if (!dal_instance->dal_context.logger) {
+ /* can *not* call logger. call base driver 'print error' */
+ dal_error("%s: failed to create Logger!\n", __func__);
+ goto logger_fail;
+ }
+
+ /* Adapter Service */
+
+ dal_instance->adapter_srv = create_as(dal_instance);
+
+ if (!dal_instance->adapter_srv) {
+ DAL_IF_ERROR("%s: create_as() failed!\n", __func__);
+ goto as_fail;
+ }
+
+ /* Initialise HW controlled by Adapter Service */
+ if (false == dal_adapter_service_initialize_hw_data(
+ dal_instance->adapter_srv)) {
+ DAL_IF_ERROR("%s: dal_adapter_service_initialize_hw_data() failed!\n",
+ __func__);
+ /* Note that AS exist, so have to destroy it.*/
+ goto ts_fail;
+ }
+
+ /* Timing Service */
+ dal_instance->timing_srv =
+ dal_timing_service_create(
+ &dal_instance->dal_context,
+ true);
+
+ if (!dal_instance->timing_srv) {
+ DAL_IF_ERROR(
+ "%s: dal_timing_service_create() failed!\n",
+ __func__);
+ goto ts_fail;
+ }
+
+ {
+ struct hws_init_data hws_init_data;
+
+ hws_init_data.as = dal_instance->adapter_srv;
+ hws_init_data.dal_context = &dal_instance->dal_context;
+
+ dal_instance->hws = dal_hw_sequencer_create(&hws_init_data);
+
+ if (!dal_instance->hws) {
+ DAL_IF_ERROR("%s: dal_hw_sequencer_create() failed!\n",
+ __func__);
+ goto hws_fail;
+ }
+ }
+
+ {
+ struct mode_manager_init_data init_data;
+
+ init_data.as = dal_instance->adapter_srv;
+ init_data.default_modes =
+ dal_timing_service_get_default_mode_list(
+ dal_instance->timing_srv);
+ init_data.dal_context = &dal_instance->dal_context;
+ dal_instance->mm = dal_mode_manager_create(&init_data);
+
+ if (!dal_instance->mm)
+ goto mm_fail;
+ }
+
+ {
+ struct topology_mgr_init_data tm_init_data;
+
+ dal_memset(&tm_init_data, 0, sizeof(tm_init_data));
+
+ /* Topology Manager */
+ tm_init_data.dal_context = &dal_instance->dal_context;
+ tm_init_data.adapter_srv = dal_instance->adapter_srv;
+ tm_init_data.timing_srv = dal_instance->timing_srv;
+ tm_init_data.hwss_srvr = dal_instance->hws;
+ tm_init_data.mm = dal_instance->mm;
+
+ dal_instance->topology_mgr = dal_tm_create(&tm_init_data);
+
+ if (!dal_instance->topology_mgr) {
+ DAL_IF_ERROR("%s: dal_tm_create() failed!\n", __func__);
+ goto tm_fail;
+ }
+
+ /* TODO: Set embedded display index in AS for backlight ctrl?*/
+ }
+
+ {
+ struct ds_init_data ds_init_data = { 0 };
+
+ ds_init_data.dal_context = &dal_instance->dal_context;
+ ds_init_data.as = dal_instance->adapter_srv;
+ ds_init_data.ts = dal_instance->timing_srv;
+ ds_init_data.tm = dal_instance->topology_mgr;
+ ds_init_data.hwss = dal_instance->hws;
+
+ ds_init_data.view_port_alignment.x_start_alignment =
+ init->vp_alignment.x_start_alignment;
+ ds_init_data.view_port_alignment.x_width_size_alignment =
+ init->vp_alignment.x_width_size_alignment;
+ ds_init_data.view_port_alignment.y_height_size_alignment =
+ init->vp_alignment.y_height_size_alignment;
+ ds_init_data.view_port_alignment.y_start_alignment =
+ init->vp_alignment.y_start_alignment;
+
+ dal_instance->display_service =
+ dal_display_service_create(&ds_init_data);
+
+ if (!dal_instance->display_service) {
+ DAL_IF_ERROR(
+ "%s: dal_display_service_create() failed!\n",
+ __func__);
+ goto ds_fail;
+ }
+ }
+
+ {
+ struct irq_service_init_data init_data;
+
+ init_data.ctx = dal_context;
+ dal_instance->irqs =
+ dal_irq_service_create(
+ dal_adapter_service_get_dce_version(
+ dal_instance->adapter_srv),
+ &init_data);
+
+ if (!dal_instance->irqs)
+ goto irqs_fail;
+ }
+
+ dal_mode_manager_set_ds_dispatch(
+ dal_instance->mm,
+ dal_display_service_get_set_mode_interface(
+ dal_instance->display_service));
+
+ if (!dal_timing_service_initialize_filters(
+ dal_instance->timing_srv,
+ dal_display_service_get_set_mode_interface(
+ dal_instance->display_service)))
+ goto fail;
+
+ /* try to "enable" DAL */
+ if (dal_enable(dal_instance))
+ return true;
+
+fail:
+ dal_irq_service_destroy(&dal_instance->irqs);
+irqs_fail:
+ dal_display_service_destroy(&dal_instance->display_service);
+ds_fail:
+ dal_tm_destroy(&dal_instance->topology_mgr);
+tm_fail:
+ dal_mode_manager_destroy(&dal_instance->mm);
+mm_fail:
+ dal_hw_sequencer_destroy(&dal_instance->hws);
+hws_fail:
+ dal_timing_service_destroy(&dal_instance->timing_srv);
+ts_fail:
+ dal_adapter_service_destroy(&dal_instance->adapter_srv);
+as_fail:
+ dal_logger_destroy(&dal_instance->dal_context.logger);
+logger_fail:
+
+ return false;
+}
+
+static void release_hw(struct dal *dal)
+{
+ dal_tm_release_hw(dal->topology_mgr);
+}
+
+static void dal_destruct(struct dal *dal)
+{
+ release_hw(dal);
+
+ dal_irq_service_destroy(&dal->irqs);
+
+ dal_adapter_service_destroy(&dal->adapter_srv);
+
+ dal_timing_service_destroy(&dal->timing_srv);
+
+ dal_hw_sequencer_destroy(&dal->hws);
+
+ dal_display_service_destroy(&dal->display_service);
+
+ dal_tm_destroy(&dal->topology_mgr);
+
+ dal_logger_destroy(&dal->dal_context.logger);
+
+ dal_mode_manager_destroy(&dal->mm);
+}
+
+/**
+ *****************************************************************************
+ * Function: dal_enable
+ *
+ * @brief
+ * 1. Enable DAL instance and initialise the display HW.
+ * 2. Do initial detection.
+ *
+ * @return
+ * If DAL instance is enabled successfully, return true,
+ * otherwise, return false.
+ *
+ *****************************************************************************
+ */
+static bool dal_enable(struct dal *dal)
+{
+ enum tm_result tm_rc;
+ struct topology_mgr *tm_mgr = dal->topology_mgr;
+ struct dal_context *dal_context = &dal->dal_context;
+
+ DAL_IF_TRACE();
+
+ /* TODO: call Display Service to notify all subcomponents
+ * about initial display configuration. */
+
+ /* call TM to initialise HW */
+ dal_tm_set_current_power_state(tm_mgr, DAL_VIDEO_POWER_UNSPECIFIED);
+
+ tm_rc = dal_tm_init_hw(tm_mgr);
+
+ if (TM_RESULT_SUCCESS == tm_rc) {
+ /*blank all pipe.--> stop memory request to frame buffer*/
+ dal_tm_disable_all_dcp_pipes(tm_mgr);
+
+ /* no error */
+ /* call TM to detect connected displays */
+ dal_tm_do_initial_detection(tm_mgr);
+
+ /* Only if *everything* is initialised successfully, register
+ * to receive HPD interrupts. */
+ tm_rc = dal_tm_register_for_display_detection_interrupt(tm_mgr);
+ }
+
+ if (TM_RESULT_SUCCESS != tm_rc)
+ /* error occurred */
+ return false;
+
+ return true;
+}
+
+/*
+ * Enable the DAL instance after resume
+ *
+ * Enables instance of the DAL specific to an adapter after resume.
+ * The function sets up the display mapping based on appropriate boot-up
+ * behavior.
+ */
+void dal_resume(struct dal *dal)
+{
+ struct dal_context *dal_context = &dal->dal_context;
+
+ DAL_IF_TRACE();
+
+ dal_tm_do_complete_detection(dal->topology_mgr,
+ DETECTION_METHOD_DESTRUCTIVE,
+ false);
+}
+
+/* HW Capability queries */
+uint32_t dal_get_controllers_number(struct dal *dal)
+{
+ struct dal_context *dal_context = &dal->dal_context;
+
+ DAL_IF_TRACE();
+
+ return dal_tm_get_num_functional_controllers(dal->topology_mgr);
+}
+
+uint32_t dal_get_connected_targets_vector(struct dal *dal)
+{
+ struct topology_mgr *tm_mgr;
+ uint32_t connected_displays;
+ uint32_t ind;
+ uint32_t disp_path_num;
+ struct display_path *disp_path;
+
+ /* For DAL disabled support, report 1 pipe for fake display */
+ if (dal == NULL)
+ return 1;
+
+ tm_mgr = dal->topology_mgr;
+
+ disp_path_num = dal_tm_get_num_display_paths(tm_mgr, false);
+
+ connected_displays = 0;
+
+ for (ind = 0; ind < disp_path_num; ind++) {
+ disp_path = dal_tm_display_index_to_display_path(tm_mgr, ind);
+
+ if (dal_display_path_is_target_connected(disp_path))
+ connected_displays |= (1 << ind);
+ } /* for() */
+
+ return connected_displays;
+}
+
+uint32_t dal_get_cofunctional_targets_number(struct dal *dal)
+{
+ struct dal_context *dal_context = &dal->dal_context;
+
+ DAL_IF_TRACE();
+
+ return dal_tm_max_num_cofunctional_targets(dal->topology_mgr);
+}
+
+/* Return a bitvector of *all* Display Paths. */
+uint32_t dal_get_supported_displays_vector(struct dal *dal)
+{
+ uint32_t disp_path_num;
+ uint32_t supported_disp = 0;
+ uint32_t ind;
+
+ /* For DAL disabled support, report 1 pipe for fake display */
+ if (dal == NULL)
+ return 1;
+
+ disp_path_num = dal_tm_get_num_display_paths(dal->topology_mgr,
+ false);
+
+ for (ind = 0; ind < disp_path_num; ind++)
+ supported_disp |= dal_get_display_vector_by_index(dal, ind);
+
+ return supported_disp;
+}
+
+uint32_t dal_get_a_display_index_by_type(struct dal *dal,
+ uint32_t display_type)
+{
+ struct dal_context *dal_context = &dal->dal_context;
+
+ DAL_IF_NOT_IMPLEMENTED();
+
+ /* TODO */
+ return 0;
+}
+
+enum signal_type dal_get_display_signal(
+ struct dal *dal,
+ uint32_t display_index)
+{
+ struct display_path *path =
+ dal_tm_display_index_to_display_path(
+ dal->topology_mgr,
+ display_index);
+
+ if (!path)
+ return SIGNAL_TYPE_NONE;
+
+ return dal_display_path_get_active_signal(path, SINK_LINK_INDEX);
+}
+
+const uint8_t *dal_get_display_edid(
+ struct dal *dal,
+ uint32_t display_index,
+ uint32_t *buff_size)
+{
+ struct dcs *dcs;
+ struct display_path *path =
+ dal_tm_display_index_to_display_path(
+ dal->topology_mgr,
+ display_index);
+
+ if (!path)
+ return NULL;
+
+ dcs = dal_display_path_get_dcs(path);
+
+ if (!dcs)
+ return NULL;
+
+ return dal_dcs_get_edid_raw_data(dcs, buff_size);
+}
+
+void dal_get_screen_info(
+ struct dal *dal,
+ uint32_t display_index,
+ struct edid_screen_info *screen_info)
+{
+ struct dcs *dcs;
+ struct display_path *path =
+ dal_tm_display_index_to_display_path(
+ dal->topology_mgr,
+ display_index);
+
+ if (!screen_info)
+ return;
+
+ if (!path)
+ return;
+
+ dcs = dal_display_path_get_dcs(path);
+
+ if (!dcs)
+ return;
+
+ dal_dcs_get_screen_info(dcs, screen_info);
+}
+
+uint32_t dal_get_display_vector_by_index(struct dal *dal,
+ uint32_t display_index)
+{
+ uint32_t disp_path_num = 0;
+ uint32_t return_val;
+
+ disp_path_num = dal_tm_get_num_display_paths(dal->topology_mgr, false);
+
+ if (display_index >= disp_path_num)
+ return_val = 0;
+ else
+ return_val = (1 << display_index);
+
+ return return_val;
+}
+
+/* TODO: implement later
+bool dal_get_display_output_descriptor (struct dal *dal,
+ uint32_t display_index,
+ struct dal_display_output_descriptor *display_descriptor);
+*/
+
+void dal_pin_active_path_modes(
+ struct dal *dal,
+ void *param,
+ uint32_t display_index,
+ void (*func)(void *, const struct path_mode *))
+{
+ struct ds_dispatch *ds_dispatch;
+ struct dal_context *dal_context = &dal->dal_context;
+
+ DAL_IF_TRACE();
+
+ ds_dispatch = dal_display_service_get_set_mode_interface(
+ dal->display_service);
+
+ if (NULL == ds_dispatch) {
+ DAL_IF_ERROR("%s: DS Dispatch Interface is NULL!\n", __func__);
+ return;
+ }
+
+
+ dal_ds_dispatch_pin_active_path_modes(
+ ds_dispatch,
+ param,
+ display_index,
+ func);
+}
+
+static void dump_path_mode(struct dal *dal,
+ uint32_t pm_num,
+ const struct path_mode *pm)
+{
+ struct dal_context *dal_context = &dal->dal_context;
+
+ dal_logger_write(dal_context->logger, LOG_MAJOR_INTERFACE_TRACE,
+ LOG_MINOR_COMPONENT_DAL_INTERFACE,
+ "PM[%02d]: PathIndex=%02d: view.height: %d, view.width: %d\n",
+ pm_num, pm->display_path_index,
+ pm->view.height, pm->view.width);
+}
+
+static void dump_path_mode_set(struct dal *dal,
+ const struct path_mode_set *pms)
+{
+ uint32_t i;
+ struct dal_context *dal_context = &dal->dal_context;
+
+ if (false == dal_logger_should_log(dal_context->logger,
+ LOG_MAJOR_INTERFACE_TRACE,
+ LOG_MINOR_COMPONENT_DAL_INTERFACE))
+ return;
+
+ dal_logger_write(dal_context->logger, LOG_MAJOR_INTERFACE_TRACE,
+ LOG_MINOR_COMPONENT_DAL_INTERFACE,
+ "SetMode: Number of Path Modes in Set: %d\n", pms->count);
+
+ for (i = 0; i < pms->count; i++)
+ dump_path_mode(dal, i, &pms->path_mode_set[i]);
+}
+
+/* Mode Set */
+bool dal_set_path_mode(struct dal *dal,
+ const struct path_mode_set *pms)
+{
+ struct ds_dispatch *ds_dispatch;
+ struct dal_context *dal_context = &dal->dal_context;
+
+ ds_dispatch =
+ dal_display_service_get_set_mode_interface(
+ dal->display_service);
+
+ if (!ds_dispatch)
+ return false;
+
+ dump_path_mode_set(dal, pms);
+
+ if (DS_SUCCESS == dal_ds_dispatch_set_mode(ds_dispatch, pms))
+ return true;
+
+ DAL_IF_ERROR(
+ "%s: dal_set_mode_interface_set_mode() failed!\n",
+ __func__);
+
+ return false;
+}
+
+bool dal_reset_path_mode(struct dal *dal,
+ const uint32_t displays_num,
+ const uint32_t *display_indexes)
+{
+ struct ds_dispatch *ds_dispatch;
+ struct dal_context *dal_context = &dal->dal_context;
+
+ ds_dispatch =
+ dal_display_service_get_reset_mode_interface(
+ dal->display_service);
+
+ if (!ds_dispatch)
+ return false;
+
+ if (DS_SUCCESS == dal_ds_dispatch_reset_mode(ds_dispatch,
+ displays_num, display_indexes))
+ return true;
+
+ DAL_IF_ERROR(
+ "%s: dal_ds_dispatch_reset_mode() failed!\n",
+ __func__);
+
+ return false;
+}
+
+/* PowerPlay */
+
+bool dal_pre_adapter_clock_change(struct dal *dal,
+ struct power_to_dal_info *clks_info)
+{
+ if (dal_adapter_service_is_feature_supported(
+ FEATURE_USE_PPLIB)) {
+ struct dal_context *dal_context = &dal->dal_context;
+ struct ds_dispatch *ds_dispatch;
+ struct gpu *gpu = NULL;
+ enum ds_return result;
+ struct gpu_clock_info gpu_clk_info;
+
+ ds_dispatch = dal_display_service_get_set_mode_interface(
+ dal->display_service);
+
+ if (NULL == ds_dispatch) {
+ DAL_IF_ERROR("%s: Display Service is NULL!\n",
+ __func__);
+ return false;
+ }
+
+ result = dal_ds_dispatch_pre_adapter_clock_change(ds_dispatch);
+
+ /* cache new clock values, to be applied when
+ * post_adapter_clock_change is called
+ */
+ gpu_clk_info.min_sclk_khz = clks_info->min_sclk;
+ gpu_clk_info.max_sclk_khz = clks_info->max_sclk;
+ gpu_clk_info.min_mclk_khz = clks_info->min_mclk;
+ gpu_clk_info.max_mclk_khz = clks_info->max_mclk;
+
+ gpu = dal_tm_get_gpu(dal->topology_mgr);
+
+ dal_gpu_update_dynamic_clock_info(gpu, &gpu_clk_info);
+
+ if (result == DS_SUCCESS)
+ return true;
+
+ }
+
+ return false;
+}
+
+bool dal_post_adapter_clock_change(struct dal *dal)
+{
+ /* Up to this point we are using 'safe' marks, which are not
+ * power-efficient.
+ * Program stutter and other display marks to values provided
+ * by PPLib. */
+ if (dal_adapter_service_is_feature_supported(
+ FEATURE_USE_PPLIB)) {
+
+ struct dal_context *dal_context = &dal->dal_context;
+ struct ds_dispatch *ds_dispatch;
+ enum ds_return result;
+
+ ds_dispatch = dal_display_service_get_set_mode_interface(
+ dal->display_service);
+
+ if (NULL == ds_dispatch) {
+ DAL_IF_ERROR("%s: Display Service is NULL!\n",
+ __func__);
+ return false;
+ }
+
+ result = dal_ds_dispatch_post_adapter_clock_change(ds_dispatch);
+
+ if (result == DS_SUCCESS)
+ return true;
+ }
+
+ return false;
+}
+
+/* Power Control */
+void dal_set_display_dpms(
+ struct dal *dal,
+ uint32_t display_index,
+ enum dal_power_state state)
+{
+ switch (state) {
+ case DAL_POWER_STATE_ON:
+ dal_display_service_target_power_control(
+ dal->display_service,
+ display_index, true);
+ break;
+ case DAL_POWER_STATE_STANDBY:
+ case DAL_POWER_STATE_SUSPEND:
+ case DAL_POWER_STATE_OFF:
+ dal_display_service_mem_request_control(
+ dal->display_service,
+ display_index,
+ false);
+
+ dal_display_service_target_power_control(
+ dal->display_service,
+ display_index, false);
+ break;
+ default:
+ break;
+ }
+
+}
+
+void dal_set_power_state(
+ struct dal *dal,
+ enum dal_acpi_cm_power_state power_state,
+ enum dal_video_power_state video_power_state)
+{
+ dal_tm_set_current_power_state(
+ dal->topology_mgr, video_power_state);
+ switch (power_state) {
+ case DAL_ACPI_CM_POWER_STATE_D0:
+ /*TODO:NotifyMultiDisplayConfig*/
+ dal_tm_init_hw(dal->topology_mgr);
+ break;
+ default:
+ /*TODO: Synchronization code goes here*/
+ dal_tm_power_down_hw(dal->topology_mgr);
+ break;
+ }
+
+}
+
+void dal_set_blanking(struct dal *dal, uint32_t display_index, bool blank)
+{
+ struct dal_context *dal_context = &dal->dal_context;
+
+ DAL_IF_TRACE();
+
+ /* Return value is not checked here because dal_set_blanking could
+ * be called while HW is not ready for programming (i.e. on boot up) */
+ dal_display_service_mem_request_control(dal->display_service,
+ display_index, blank);
+}
+
+void dal_shut_down_display_block(struct dal *dal)
+{
+ struct dal_context *dal_context = &dal->dal_context;
+
+ DAL_IF_NOT_IMPLEMENTED();
+ /* TODO */
+}
+
+/* Brightness Interface */
+bool dal_set_backlight_level(
+ struct dal *dal,
+ uint32_t display_index,
+ uint32_t brightness)
+{
+ struct ds_dispatch *ds_dispatch =
+ dal_display_service_get_adjustment_interface(
+ dal->display_service);
+ enum ds_return result;
+
+ if (dal_tm_get_embedded_device_index(dal->topology_mgr) !=
+ display_index)
+ return false;
+
+ if (!ds_dispatch)
+ return NULL;
+
+ result =
+ dal_ds_dispatch_set_adjustment(
+ ds_dispatch,
+ display_index,
+ ADJ_ID_BACKLIGHT,
+ brightness);
+
+ return result == DS_SUCCESS;
+}
+
+bool dal_get_backlight_level_old(
+ struct dal *dal,
+ uint32_t display_index,
+ void *adjustment)
+{
+ struct dal_context *dal_context = &dal->dal_context;
+
+ DAL_IF_NOT_IMPLEMENTED();
+ /* TODO */
+ return 0;
+}
+
+bool dal_backlight_control_on(struct dal *dal)
+{
+ struct dal_context *dal_context = &dal->dal_context;
+
+ DAL_IF_NOT_IMPLEMENTED();
+ /* TODO */
+ return 0;
+}
+
+bool dal_backlight_control_off(struct dal *dal)
+{
+ struct dal_context *dal_context = &dal->dal_context;
+
+ DAL_IF_NOT_IMPLEMENTED();
+ /* TODO */
+ return 0;
+}
+
+/* Brightness and color Control */
+void dal_set_palette(struct dal *dal,
+ uint32_t display_index,
+ struct dal_dev_c_lut palette,
+ uint32_t start,
+ uint32_t length)
+{
+ struct dal_context *dal_context = &dal->dal_context;
+
+ DAL_IF_NOT_IMPLEMENTED();
+ /* TODO */
+}
+
+bool dal_set_gamma(
+ struct dal *dal,
+ uint32_t display_index,
+ struct raw_gamma_ramp *gamma)
+{
+ enum ds_return result;
+ struct dal_context *dal_context = &dal->dal_context;
+ struct ds_dispatch *ds_dispatch =
+ dal_display_service_get_adjustment_interface(
+ dal->display_service);
+
+ if (NULL == ds_dispatch) {
+ DAL_IF_ERROR("%s: Display Service is NULL!\n",
+ __func__);
+ return false;
+ }
+
+ result = dal_ds_dispatch_set_gamma_adjustment(
+ ds_dispatch,
+ display_index,
+ ADJ_ID_GAMMA_RAMP,
+ gamma);
+
+ return result == DS_SUCCESS;
+}
+
+/* Active Stereo Interface */
+bool dal_control_stereo(struct dal *dal,
+ uint32_t display_index,
+ bool enable)
+{
+ struct dal_context *dal_context = &dal->dal_context;
+
+ DAL_IF_NOT_IMPLEMENTED();
+ /* TODO */
+ return 0;
+}
+
+/* Disable All DC Pipes - blank CRTC and disable memory requests */
+void dal_disable_all_dc_pipes(struct dal *dal)
+{
+ struct dal_context *dal_context = &dal->dal_context;
+
+ DAL_IF_NOT_IMPLEMENTED();
+ /* TODO */
+}
+
+/******************************************************************************
+ Timing List Query
+******************************************************************************/
+struct dal_timing_list_query *dal_create_timing_list_query(struct dal *dal,
+ uint32_t display_index)
+{
+ struct display_path *display_path;
+ struct timing_list_query_init_data init_data = { 0 };
+ struct dal_timing_list_query *tlsq;
+ struct dal_context *dal_context = &dal->dal_context;
+
+ display_path = dal_tm_display_index_to_display_path(dal->topology_mgr,
+ display_index);
+ if (!display_path) {
+ DAL_IF_ERROR(
+ "%s: dal_tm_display_index_to_display_path() failed!\n",
+ __func__);
+ return NULL;
+ }
+
+ init_data.dal = dal;
+ init_data.dcs = dal_display_path_get_dcs(display_path);
+ init_data.timing_srv = dal->timing_srv;
+ init_data.display_index = display_index;
+
+ tlsq = dal_timing_list_query_create(&init_data);
+ if (!tlsq) {
+ DAL_IF_ERROR("%s: timing_list_query_create() failed!\n",
+ __func__);
+ return NULL;
+ }
+
+ return tlsq;
+}
+
+/*****************************************************************************
+ Implementation of private functions.
+ *****************************************************************************/
+static struct adapter_service *create_as(struct dal *dal)
+{
+ struct adapter_service *as = NULL;
+ struct as_init_data init_data;
+ struct dal_init_data *init = &dal->init_data;
+
+ dal_memset(&init_data, 0, sizeof(init_data));
+
+ init_data.dal_context = &dal->dal_context;
+
+ /* BIOS parser init data */
+ init_data.bp_init_data.dal_context = &dal->dal_context;
+ init_data.bp_init_data.bios = init->asic_id.atombios_base_address;
+
+ /* HW init data */
+ init_data.hw_init_data.chip_family = init->asic_id.chip_family;
+ init_data.hw_init_data.chip_id = init->asic_id.chip_id;
+ init_data.hw_init_data.fake_paths_num = init->asic_id.fake_paths_num;
+ init_data.hw_init_data.feature_flags = init->asic_id.feature_flags;
+ init_data.hw_init_data.hw_internal_rev = init->asic_id.hw_internal_rev;
+ init_data.hw_init_data.runtime_flags = init->asic_id.runtime_flags;
+ init_data.hw_init_data.vram_width = init->asic_id.vram_width;
+ init_data.hw_init_data.vram_type = init->asic_id.vram_type;
+
+ /* bdf is BUS,DEVICE,FUNCTION*/
+ init_data.bdf_info = init->bdf_info;
+
+ init_data.display_param = &init->display_param;
+
+ as = dal_adapter_service_create(&init_data);
+
+ return as;
+}
+
+/*hard code color square at CRTC0 for HDMI light up*/
+void dal_set_crtc_test_pattern(struct dal *dal)
+{
+ struct topology_mgr *tm = dal->topology_mgr;
+ struct display_path *dp = dal_tm_display_index_to_display_path(
+ tm, 0);
+ struct controller *crtc = NULL;
+
+ if (dal_display_path_is_acquired(dp))
+ crtc = dal_display_path_get_controller(dp);
+
+ if (crtc != NULL)
+ dal_controller_set_test_pattern(
+ crtc,
+ DP_TEST_PATTERN_COLOR_SQUARES,
+ HW_COLOR_DEPTH_888);
+}
+
+uint32_t dal_get_display_index_from_int_src(struct dal *dal,
+ enum dal_irq_source src)
+{
+ enum controller_id crtc_id;
+
+ /* check if DAL is disabled */
+ if (dal == NULL)
+ return INVALID_DISPLAY_INDEX;
+
+ /* the assumption here is that INT_Y int was generated by
+ CRTC_Y hardware block. That might not be true in the future
+ TODO: greate CRTC to IRQ SRC tables */
+ switch (src) {
+ case DAL_IRQ_SOURCE_CRTC1VSYNC:
+ case DAL_IRQ_SOURCE_CRTC2VSYNC:
+ case DAL_IRQ_SOURCE_CRTC3VSYNC:
+ case DAL_IRQ_SOURCE_CRTC4VSYNC:
+ case DAL_IRQ_SOURCE_CRTC5VSYNC:
+ case DAL_IRQ_SOURCE_CRTC6VSYNC:
+ /*TODO: should we add one for Underlay? */
+ crtc_id = src - DAL_IRQ_SOURCE_CRTC1VSYNC + 1;
+ break;
+ case DAL_IRQ_SOURCE_PFLIP1:
+ case DAL_IRQ_SOURCE_PFLIP2:
+ case DAL_IRQ_SOURCE_PFLIP3:
+ case DAL_IRQ_SOURCE_PFLIP4:
+ case DAL_IRQ_SOURCE_PFLIP5:
+ case DAL_IRQ_SOURCE_PFLIP6:
+ case DAL_IRQ_SOURCE_PFLIP_UNDERLAY0:
+ crtc_id = src - DAL_IRQ_SOURCE_PFLIP1 + 1;
+ break;
+ default:
+ dal_logger_write(dal->dal_context.logger,
+ LOG_MAJOR_ERROR, LOG_MINOR_COMPONENT_ISR,
+ "Unhandled interrupt source %d\n", src);
+ return INVALID_DISPLAY_INDEX;
+ }
+
+ return dal_tm_get_display_path_index_for_controller(
+ dal->topology_mgr,
+ crtc_id);
+}
+
+/* return crtc scanout v/h counter, return if inside v_blank*/
+uint32_t dal_get_crtc_scanoutpos(
+ struct dal *dal,
+ uint32_t display_index,
+ int32_t *vpos,
+ int32_t *hpos)
+{
+ struct topology_mgr *tm = dal->topology_mgr;
+ struct display_path *dp = dal_tm_display_index_to_display_path(
+ tm, display_index);
+ struct controller *cont = dal_display_path_get_controller(dp);
+
+ if (!cont) {
+ dal_logger_write(dal->dal_context.logger,
+ LOG_MAJOR_ERROR,
+ LOG_MINOR_COMPONENT_DAL_INTERFACE,
+ "Failed to find controller at display index %d\n",
+ display_index);
+ return 0;
+ }
+
+ return dal_controller_get_crtc_scanoutpos(cont, vpos, hpos);
+
+}
+
+static enum dal_irq_source get_irq_src_from_display_index_helper(
+ struct dal *dal,
+ uint32_t display_index,
+ uint32_t plane_no,
+ enum dal_irq_source base_irq_source)
+{
+ struct display_path *display_path;
+ struct controller *controller;
+ enum controller_id crtc_id;
+ enum dal_irq_source src;
+
+ /* return base irq source in DAL bypass mode */
+ if (dal == NULL)
+ return base_irq_source;
+
+ display_path = dal_tm_display_index_to_display_path(dal->topology_mgr,
+ display_index);
+
+ controller = dal_display_path_get_controller_for_layer_index(
+ display_path, plane_no);
+
+ if (NULL == controller)
+ return DAL_IRQ_SOURCE_INVALID;
+
+ crtc_id = dal_controller_get_graphics_object_id(controller).id;
+
+ src = crtc_id - 1 + base_irq_source;
+
+ return src;
+}
+
+enum dal_irq_source dal_get_vblank_irq_src_from_display_index(
+ struct dal *dal,
+ uint32_t display_index)
+{
+ return get_irq_src_from_display_index_helper(
+ dal,
+ display_index,
+ 0,
+ DAL_IRQ_SOURCE_CRTC1VSYNC);
+}
+
+void dal_set_vblank_irq(
+ struct dal *dal,
+ uint32_t display_index,
+ bool enable)
+{
+ struct display_path *display_path;
+ struct controller *controller;
+ struct line_buffer *lb;
+
+ display_path = dal_tm_display_index_to_display_path(dal->topology_mgr,
+ display_index);
+
+ controller = dal_tm_get_controller_from_display_path(dal->topology_mgr,
+ display_path);
+
+ if (NULL == controller)
+ return;
+
+ lb = dal_controller_get_line_buffer(controller);
+ if (NULL == lb)
+ return;
+ dal_line_buffer_set_vblank_irq(lb, enable);
+}
+
+enum dal_irq_source dal_get_pflip_irq_src_from_display_index(
+ struct dal *dal,
+ uint32_t display_index,
+ uint32_t plane_no)
+{
+ return get_irq_src_from_display_index_helper(
+ dal,
+ display_index,
+ plane_no,
+ DAL_IRQ_SOURCE_PFLIP1);
+}
+
+struct is_display_active_param {
+ bool active;
+ uint32_t display_index;
+};
+
+struct mode_manager *dal_get_mode_manager(struct dal *dal)
+{
+ return dal->mm;
+}
+
+struct mode_query *dal_get_mode_query(
+ struct dal *dal,
+ struct topology *tp,
+ enum query_option query_option)
+{
+ return dal_mode_manager_create_mode_query(dal->mm, tp, query_option);
+}
+
+
+/* DSAT Accessors, definition is in dsat.c */
+struct topology_mgr *dal_get_tm(struct dal *dal)
+{
+ return dal->topology_mgr;
+}
+
+struct adapter_service *dal_get_as(struct dal *dal)
+{
+ return dal->adapter_srv;
+}
+
+struct timing_service *dal_get_ts(struct dal *dal)
+{
+ return dal->timing_srv;
+}
+
+struct hw_sequencer *dal_get_hws(struct dal *dal)
+{
+ return dal->hws;
+}
+
+struct display_service *dal_get_ds(struct dal *dal)
+{
+ return dal->display_service;
+}
+
+struct mode_manager *dal_get_mm(struct dal *dal)
+{
+ return dal->mm;
+}
+
+struct dal_context *dal_get_dal_ctx(struct dal *dal)
+{
+ return &dal->dal_context;
+}
+
+struct dal_init_data *dal_get_init_data(struct dal *dal)
+{
+ return &dal->init_data;
+}
+
+bool dal_set_cursor_position(
+ struct dal *dal,
+ const uint32_t display_index,
+ const struct cursor_position *position
+ )
+{
+ struct display_path *dp_path;
+
+ if (!position)
+ return false;
+
+ dp_path =
+ dal_tm_display_index_to_display_path(
+ dal->topology_mgr,
+ display_index);
+
+ return dal_hw_sequencer_set_cursor_position(
+ dal->hws,
+ dp_path,
+ position);
+}
+
+bool dal_set_cursor_attributes(
+ struct dal *dal,
+ const uint32_t display_index,
+ const struct cursor_attributes *attributes
+ )
+{
+ struct display_path *dp_path;
+
+ if (!attributes)
+ return false;
+
+ dp_path =
+ dal_tm_display_index_to_display_path(
+ dal->topology_mgr,
+ display_index);
+
+ return dal_hw_sequencer_set_cursor_attributes(
+ dal->hws,
+ dp_path,
+ attributes);
+}
+
+
+static enum pixel_format convert_pixel_format_plane_to_dalsurface(
+ enum surface_pixel_format surface_pixel_format)
+{
+ enum pixel_format dal_pixel_format = PIXEL_FORMAT_UNKNOWN;
+
+ switch (surface_pixel_format) {
+ case SURFACE_PIXEL_FORMAT_GRPH_PALETA_256_COLORS:
+ dal_pixel_format = PIXEL_FORMAT_INDEX8;
+ break;
+ case SURFACE_PIXEL_FORMAT_GRPH_ARGB1555:
+ dal_pixel_format = PIXEL_FORMAT_RGB565;
+ break;
+ case SURFACE_PIXEL_FORMAT_GRPH_RGB565:
+ dal_pixel_format = PIXEL_FORMAT_RGB565;
+ break;
+ case SURFACE_PIXEL_FORMAT_GRPH_ARGB8888:
+ dal_pixel_format = PIXEL_FORMAT_ARGB8888;
+ break;
+ case SURFACE_PIXEL_FORMAT_GRPH_BGRA8888:
+ dal_pixel_format = PIXEL_FORMAT_ARGB8888;
+ break;
+ case SURFACE_PIXEL_FORMAT_GRPH_ARGB2101010:
+ dal_pixel_format = PIXEL_FORMAT_ARGB2101010;
+ break;
+ case SURFACE_PIXEL_FORMAT_GRPH_ABGR2101010:
+ dal_pixel_format = PIXEL_FORMAT_ARGB2101010;
+ break;
+ case SURFACE_PIXEL_FORMAT_GRPH_ABGR2101010_XR_BIAS:
+ dal_pixel_format = PIXEL_FORMAT_ARGB2101010_XRBIAS;
+ break;
+ case SURFACE_PIXEL_FORMAT_GRPH_ARGB16161616:
+ dal_pixel_format = PIXEL_FORMAT_FP16;
+ break;
+ case SURFACE_PIXEL_FORMAT_GRPH_ABGR16161616F:
+ dal_pixel_format = PIXEL_FORMAT_FP16;
+ break;
+
+
+ case SURFACE_PIXEL_FORMAT_VIDEO_420_YCbCr:
+ dal_pixel_format = PIXEL_FORMAT_420BPP12;
+ break;
+ case SURFACE_PIXEL_FORMAT_VIDEO_420_YCrCb:
+ dal_pixel_format = PIXEL_FORMAT_420BPP12;
+ break;
+ case SURFACE_PIXEL_FORMAT_VIDEO_422_YCb:
+ dal_pixel_format = PIXEL_FORMAT_422BPP16;
+ break;
+ case SURFACE_PIXEL_FORMAT_VIDEO_422_YCr:
+ dal_pixel_format = PIXEL_FORMAT_422BPP16;
+ break;
+ case SURFACE_PIXEL_FORMAT_VIDEO_422_CbY:
+ dal_pixel_format = PIXEL_FORMAT_422BPP16;
+ break;
+ case SURFACE_PIXEL_FORMAT_VIDEO_422_CrY:
+ dal_pixel_format = PIXEL_FORMAT_422BPP16;
+ break;
+ case SURFACE_PIXEL_FORMAT_VIDEO_444_ACrYCb1555:
+ dal_pixel_format = PIXEL_FORMAT_444BPP16;
+ break;
+ case SURFACE_PIXEL_FORMAT_VIDEO_444_CrYCb565:
+ dal_pixel_format = PIXEL_FORMAT_444BPP16;
+ break;
+ case SURFACE_PIXEL_FORMAT_VIDEO_444_ACrYCb4444:
+ dal_pixel_format = PIXEL_FORMAT_444BPP16;
+ break;
+ case SURFACE_PIXEL_FORMAT_VIDEO_444_CbYCrA5551:
+ dal_pixel_format = PIXEL_FORMAT_444BPP16;
+ break;
+ case SURFACE_PIXEL_FORMAT_VIDEO_444_ACrYCb8888:
+ dal_pixel_format = PIXEL_FORMAT_444BPP32;
+ break;
+ case SURFACE_PIXEL_FORMAT_VIDEO_444_ACrYCb2101010:
+ dal_pixel_format = PIXEL_FORMAT_444BPP32;
+ break;
+ case SURFACE_PIXEL_FORMAT_VIDEO_444_CbYCrA1010102:
+ dal_pixel_format = PIXEL_FORMAT_444BPP32;
+ break;
+ default:
+ dal_pixel_format = PIXEL_FORMAT_UNKNOWN;
+ break;
+ }
+ return dal_pixel_format;
+}
+
+bool dal_validate_plane_configurations(struct dal *dal,
+ int num_planes,
+ const struct plane_config *pl_config,
+ bool *supported)
+{
+ struct ds_dispatch *ds_dispatch =
+ dal_display_service_get_set_mode_interface(
+ dal->display_service);
+
+ if (NULL == ds_dispatch) {
+ struct dal_context *dal_context = &dal->dal_context;
+
+ DAL_IF_ERROR(
+ "%s: ds_dispatch is NULL!\n",
+ __func__);
+
+ return false;
+ }
+
+ if (dal_ds_dispatch_validate_plane_configurations(
+ ds_dispatch,
+ num_planes,
+ pl_config,
+ supported))
+ return true;
+
+ return false;
+}
+
+/*TODO fill struct plane_attributes attributes;
+ * for scaler*/
+bool dal_setup_plane_configurations(
+ struct dal *dal,
+ uint32_t num_planes,
+ struct plane_config *configs)
+{
+ struct dal_context *dal_context = &dal->dal_context;
+ struct ds_dispatch *ds_dispatch;
+ uint32_t display_index = configs[0].display_index;
+ uint32_t i = 0;
+
+ if (configs == NULL)
+ return false;
+
+ if (num_planes == 0 || num_planes > MAX_PLANE_NUM)
+ return false;
+
+ ds_dispatch =
+ dal_display_service_get_set_mode_interface(
+ dal->display_service);
+
+ if (!ds_dispatch) {
+ DAL_IF_ERROR("%s: ds_dispatch is NULL!\n", __func__);
+ return false;
+ }
+
+ /*convert dm surface pixel format into DAL internal surface format*/
+ for (i = 0; i < num_planes; i++) {
+ configs[i].config.dal_pixel_format =
+ convert_pixel_format_plane_to_dalsurface(
+ configs[i].config.format);
+ }
+
+ dal_ds_dispatch_setup_plane_configurations(
+ ds_dispatch,
+ display_index,
+ num_planes,
+ configs);
+
+ return true;
+}
+
+bool dal_update_plane_addresses(
+ struct dal *dal,
+ uint32_t num_planes,
+ struct plane_addr_flip_info *info)
+{
+ struct display_path *dp_path;
+
+ if (num_planes == 0 || num_planes > MAX_PLANE_NUM)
+ return false;
+
+ if (!info)
+ return false;
+
+ dp_path =
+ dal_tm_display_index_to_display_path(
+ dal->topology_mgr,
+ info[0].display_index);
+
+ return dal_hw_sequencer_update_plane_address(
+ dal->hws,
+ dp_path,
+ num_planes,
+ info);
+}
+
+static bool remote_display_receiver_caps_set(
+ struct dal *dal,
+ struct display_path *disp_path,
+ struct dal_remote_display_receiver_capability *caps)
+{
+ struct dcs *dcs;
+
+ dcs = dal_display_path_get_dcs(disp_path);
+ if (NULL == dcs) {
+ dal_logger_write(dal->dal_context.logger,
+ LOG_MAJOR_ERROR,
+ LOG_MINOR_COMPONENT_DAL_INTERFACE,
+ "%s: DCS is NULL!\n", __func__);
+ return false;
+ }
+
+ dal_dcs_set_remote_display_receiver_capabilities(dcs, caps);
+
+ return true;
+}
+
+uint32_t dal_wifi_display_acquire(
+ struct dal *dal,
+ uint8_t *edid_data,
+ uint32_t edid_size,
+ struct dal_remote_display_receiver_capability *caps,
+ uint32_t *display_index)
+{
+ struct display_path *disp_path = NULL;
+
+ if (edid_data == NULL || caps == NULL) {
+ ASSERT_CRITICAL(0);
+ dal_logger_write(dal->dal_context.logger,
+ LOG_MAJOR_ERROR,
+ LOG_MINOR_COMPONENT_DAL_INTERFACE,
+ "Wifi display capability is NULL");
+ /*TODO: define an enum for error codes
+ * and make this function return that enum
+ */
+ return -1;
+ }
+
+ *display_index = dal_tm_get_wireless_display_index(
+ dal->topology_mgr);
+
+ if (*display_index == INVALID_DISPLAY_INDEX) {
+ ASSERT_CRITICAL(0);
+ dal_logger_write(dal->dal_context.logger,
+ LOG_MAJOR_ERROR,
+ LOG_MINOR_COMPONENT_DAL_INTERFACE,
+ "Wireless display index is invalid");
+ return -1;
+ }
+
+ disp_path = dal_tm_display_index_to_display_path(
+ dal->topology_mgr, *display_index);
+
+ if (disp_path == NULL)
+ return -1;
+
+ if (dal_display_path_is_target_connected(disp_path)) {
+ dal_logger_write(dal->dal_context.logger,
+ LOG_MAJOR_ERROR,
+ LOG_MINOR_COMPONENT_DAL_INTERFACE,
+ "%s: Failed to acquire disp path - already in use\n",
+ __func__);
+ return -1;
+ }
+
+ if (false == remote_display_receiver_caps_set(dal, disp_path, caps)) {
+ dal_logger_write(dal->dal_context.logger,
+ LOG_MAJOR_ERROR,
+ LOG_MINOR_COMPONENT_DAL_INTERFACE,
+ "%s: Failed to set remote display caps!\n", __func__);
+ return -1;
+ }
+
+ dal_tm_update_display_edid(
+ dal->topology_mgr, *display_index,
+ edid_data, edid_size);
+
+ dal_tm_set_force_connected(
+ dal->topology_mgr,
+ *display_index,
+ true);
+
+ return 0;
+}
+
+static void remote_display_receiver_caps_clear(
+ struct dal *dal,
+ struct display_path *disp_path)
+{
+ struct dcs *dcs = dal_display_path_get_dcs(disp_path);
+
+ if (NULL == dcs) {
+ dal_logger_write(dal->dal_context.logger,
+ LOG_MAJOR_ERROR,
+ LOG_MINOR_COMPONENT_DAL_INTERFACE,
+ "%s: DCS is NULL!\n", __func__);
+ return;
+ }
+
+ dal_dcs_clear_remote_display_receiver_capabilities(dcs);
+}
+
+uint32_t dal_wifi_display_release(
+ struct dal *dal,
+ uint32_t *display_index)
+{
+ struct display_path *disp_path = NULL;
+
+ *display_index = dal_tm_get_wireless_display_index(
+ dal->topology_mgr);
+
+ if (*display_index == INVALID_DISPLAY_INDEX) {
+ ASSERT_CRITICAL(0);
+ dal_logger_write(dal->dal_context.logger,
+ LOG_MAJOR_ERROR,
+ LOG_MINOR_COMPONENT_DAL_INTERFACE,
+ "Wireless display index is invalid");
+ return -1;
+ }
+
+ disp_path = dal_tm_display_index_to_display_path(
+ dal->topology_mgr, *display_index);
+
+ if (false == dal_display_path_is_target_connected(disp_path)) {
+ dal_logger_write(dal->dal_context.logger,
+ LOG_MAJOR_ERROR,
+ LOG_MINOR_COMPONENT_DAL_INTERFACE,
+ "Display path is not connected, display path probably not acquired");
+ return -1;
+ }
+
+ dal_tm_set_force_connected(
+ dal->topology_mgr,
+ *display_index,
+ false);
+
+ remote_display_receiver_caps_clear(dal, disp_path);
+
+ return 0;
+}
+
+/*
+ * dal_get_vblank_counter
+ *
+ * @brief
+ * Get the current vertical blank counts for given CRTC.
+ *
+ * @param
+ * struct dal *dal - [in] DAL instance
+ * int disp_idx - [in] display index
+ *
+ * @return
+ * Return the CRTC counter for frame
+ */
+uint32_t dal_get_vblank_counter(struct dal *dal, int disp_idx)
+{
+ struct topology_mgr *tm = dal->topology_mgr;
+ struct display_path *dp = dal_tm_display_index_to_display_path(
+ tm, disp_idx);
+ struct controller *cont = NULL;
+
+ if (dal_display_path_is_acquired(dp))
+ cont = dal_display_path_get_controller(dp);
+ else
+ return 0;
+
+ return dal_controller_get_vblank_counter(cont);
+}
+
+void dal_interrupt_set(struct dal *dal, enum dal_irq_source src, bool enable)
+{
+ dal_irq_service_set(dal->irqs, src, enable);
+}
+
+void dal_interrupt_ack(struct dal *dal, enum dal_irq_source src)
+{
+ dal_irq_service_ack(dal->irqs, src);
+}
+
+enum dal_irq_source dal_interrupt_to_irq_source(
+ struct dal *dal,
+ uint32_t src_id,
+ uint32_t ext_id)
+{
+ return dal_irq_service_to_irq_source(dal->irqs, src_id, ext_id);
+}
diff --git a/drivers/gpu/drm/amd/dal/interface/timing_list_query.c b/drivers/gpu/drm/amd/dal/interface/timing_list_query.c
new file mode 100644
index 000000000000..bb5c044f03e0
--- /dev/null
+++ b/drivers/gpu/drm/amd/dal/interface/timing_list_query.c
@@ -0,0 +1,371 @@
+/* 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 "dal_services.h"
+
+#include "include/timing_list_query_interface.h"
+#include "include/timing_service_interface.h"
+#include "include/mode_timing_list_interface.h"
+#include "include/mode_manager_interface.h"
+#include "include/dal_interface.h"
+
+struct dal_timing_list_query {
+ /* instance of DAL which created this query */
+ struct dal *parent_dal;
+ struct timing_service *timing_srv;
+ struct dcs *dcs;
+ uint32_t display_index;
+ /* mode timing list for display_path */
+ struct mode_timing_list *mode_timing_list;
+ uint32_t added_timing_count;
+ struct display_pixel_encoding_support pes;
+
+ /* following var is used for caching. In DAL2 it static variable inside
+ * function. Was decided to refactor it */
+ struct display_color_depth_support cds;
+};
+
+
+/******************************************************************************
+ * Private functions
+ *****************************************************************************/
+
+static bool construct(
+ struct dal_timing_list_query *tlsq,
+ struct timing_list_query_init_data *init_data)
+{
+ tlsq->dcs = init_data->dcs;
+ tlsq->display_index = init_data->display_index;
+ tlsq->parent_dal = init_data->dal;
+ tlsq->timing_srv = init_data->timing_srv;
+
+ tlsq->mode_timing_list =
+ dal_timing_service_get_mode_timing_list_for_path(
+ tlsq->timing_srv,
+ tlsq->display_index);
+
+ return NULL != tlsq->mode_timing_list;
+}
+
+static void destruct(struct dal_timing_list_query *tlsq)
+{
+ if (tlsq->added_timing_count) {
+ dal_mode_manager_update_disp_path_func_view_tbl(
+ dal_get_mode_manager(tlsq->parent_dal),
+ tlsq->display_index,
+ dal_timing_service_get_mode_timing_list_for_path(
+ tlsq->timing_srv,
+ tlsq->display_index));
+
+ dal_timing_service_dump(tlsq->timing_srv,
+ tlsq->display_index);
+ }
+}
+
+/**
+ *****************************************************************************
+ * Function: get_next_display_supported_pixel_encoding()
+ *
+ * helper function to get next supported pixelEncoding from DCS data
+ *
+ * @param [in] update_from_dcs - get from DCS or use cache
+ * @param [in] pe - the specific PixelEncoding
+ *
+ * @return
+ * return true if found
+ *
+ * @note
+ *
+ * @see
+ *
+ *****************************************************************************
+ */
+
+static bool get_next_display_supported_pixel_encoding(
+ struct dal_timing_list_query *tlsq,
+ bool update_from_dcs,
+ enum pixel_encoding pe)
+{
+ bool ret = true;
+ /* TODO: can not complete because of dependency on DCS.
+ * Finish when DCS is ready. */
+ return ret;
+}
+
+/******************************************************************************
+ * Public interface implementation.
+ *****************************************************************************/
+struct dal_timing_list_query *dal_timing_list_query_create(
+ struct timing_list_query_init_data *init_data)
+{
+ struct dal_timing_list_query *tlsq;
+
+ tlsq = dal_alloc(sizeof(*tlsq));
+ if (!tlsq)
+ return NULL;
+
+ if (construct(tlsq, init_data))
+ return tlsq;
+
+ BREAK_TO_DEBUGGER();
+ dal_free(tlsq);
+ return NULL;
+}
+
+void dal_timing_list_query_destroy(struct dal_timing_list_query **tlsq)
+{
+ if (!tlsq || !*tlsq) {
+ BREAK_TO_DEBUGGER();
+ return;
+ }
+
+ destruct(*tlsq);
+
+ dal_free(*tlsq);
+
+ *tlsq = NULL;
+}
+
+/* Get count of mode timings in the list. */
+uint32_t dal_timing_list_query_get_mode_timing_count(
+ const struct dal_timing_list_query *tlsq)
+{
+ if (NULL == tlsq) {
+ /* getting here if OS ignores error in
+ * dal_timing_list_query_create() */
+ BREAK_TO_DEBUGGER();
+ return 0;
+ }
+
+ return dal_mode_timing_list_get_count(tlsq->mode_timing_list);
+}
+
+const struct mode_timing *dal_timing_list_query_get_mode_timing_at_index(
+ const struct dal_timing_list_query *tlsq,
+ uint32_t index)
+{
+ if (NULL == tlsq) {
+ /* getting here if OS ignores error in
+ * dal_timing_list_query_create() */
+ BREAK_TO_DEBUGGER();
+ return NULL;
+ }
+
+ return dal_mode_timing_list_get_timing_at_index(
+ tlsq->mode_timing_list, index);
+}
+
+static enum display_color_depth display_color_depth_from_dcs_color_depth(
+ enum color_depth_index color_depth)
+{
+ switch (color_depth) {
+ case COLOR_DEPTH_INDEX_666:
+ return DISPLAY_COLOR_DEPTH_666;
+ case COLOR_DEPTH_INDEX_888:
+ return DISPLAY_COLOR_DEPTH_888;
+ case COLOR_DEPTH_INDEX_101010:
+ return DISPLAY_COLOR_DEPTH_101010;
+ case COLOR_DEPTH_INDEX_121212:
+ return DISPLAY_COLOR_DEPTH_121212;
+ case COLOR_DEPTH_INDEX_141414:
+ return DISPLAY_COLOR_DEPTH_141414;
+ case COLOR_DEPTH_INDEX_161616:
+ return DISPLAY_COLOR_DEPTH_161616;
+ default:
+ return DISPLAY_COLOR_DEPTH_UNDEFINED;
+ }
+}
+
+static bool get_next_color_depth_from_dcs_support(
+ struct display_color_depth_support *cds,
+ enum display_color_depth current_cd,
+ enum display_color_depth *next_cd)
+{
+ enum color_depth_index i;
+ bool next_bit = (current_cd == DISPLAY_COLOR_DEPTH_UNDEFINED);
+
+ for (i = COLOR_DEPTH_INDEX_666; i < COLOR_DEPTH_INDEX_LAST; i <<= 1) {
+ if ((cds->mask & i) == 0)
+ continue;
+
+ if (next_bit) {
+ *next_cd = display_color_depth_from_dcs_color_depth(i);
+ if (*next_cd > DISPLAY_COLOR_DEPTH_888 &&
+ cds->deep_color_native_res_only)
+ continue;
+
+ return true;
+ }
+
+ /* found current bit */
+ if (current_cd == display_color_depth_from_dcs_color_depth(i))
+ next_bit = true;
+ }
+
+ return false;
+}
+
+static bool get_next_display_supported_color_depth(
+ struct dal_timing_list_query *tlsq,
+ bool update_from_dcs,
+ enum display_color_depth *cd)
+{
+ bool ret = true;
+
+ /* we update the data from DCS on demand
+ * so we can re-use the cached data
+ */
+ if (update_from_dcs) {
+ tlsq->cds.mask = 0;
+ ret = dal_dcs_get_display_color_depth(tlsq->dcs, &tlsq->cds);
+ }
+
+ if (ret)
+ ret = get_next_color_depth_from_dcs_support(
+ &tlsq->cds, *cd, cd);
+
+ return ret;
+}
+
+/**
+ *****************************************************************************
+ * timing_list_query_add_timing() is used to add timing to a target timing
+ * mode list.
+ * In case device disconnected, the previously added modes will stay in
+ * the target mode list until a newly connected device arrival and added
+ * timing will be removed automatically by DAL.
+ *****************************************************************************
+ */
+bool dal_timing_list_query_add_timing(struct dal_timing_list_query *tlsq,
+ const struct crtc_timing *crtc_timing,
+ enum timing_support_level support_level)
+{
+ enum timing_source ts;
+ struct mode_timing mt;
+ /* we use this boolean to track whether we need to ask DCS for
+ * the information */
+ bool query_dcs = true;
+ bool ret;
+
+ /* TODO: for wireless always return false, without adding
+ * the mode timing. */
+
+ /* set proper timing source */
+ if (TIMING_SUPPORT_LEVEL_NOT_GUARANTEED == support_level ||
+ TIMING_SUPPORT_LEVEL_UNDEFINED == support_level) {
+ ts = TIMING_SOURCE_DALINTERFACE_IMPLICIT;
+ } else if (TIMING_SUPPORT_LEVEL_GUARANTEED == support_level ||
+ TIMING_SUPPORT_LEVEL_NATIVE == support_level) {
+ ts = TIMING_SOURCE_DALINTERFACE_EXPLICIT;
+ } else {
+ /* bad input */
+ return false;
+ }
+
+ dal_memset(&mt, 0, sizeof(mt));
+
+ mt.crtc_timing = *crtc_timing;
+ mt.mode_info.timing_source = ts;
+
+ /* call TS helper function to create the 'mt.mode_info' */
+ dal_timing_service_create_mode_info_from_timing(crtc_timing,
+ &mt.mode_info);
+
+ mt.crtc_timing.vic = dal_timing_service_get_video_code_for_timing(
+ tlsq->timing_srv, crtc_timing);
+
+ /* Caller may not be able to provide pixel encoding or colour depth
+ * information. If such case occurs, we need to query DCS for
+ * the support */
+
+ if (mt.crtc_timing.display_color_depth != DISPLAY_COLOR_DEPTH_UNDEFINED
+ && mt.crtc_timing.pixel_encoding
+ != PIXEL_ENCODING_UNDEFINED) {
+ /* all defined, we can go ahead call TS */
+ ret = dal_timing_service_add_mode_timing_to_path(
+ tlsq->timing_srv, tlsq->display_index, &mt);
+ } else if (mt.crtc_timing.display_color_depth
+ != DISPLAY_COLOR_DEPTH_UNDEFINED) {
+ /* mt.crtc_timing.pixel_encoding is NOT defined.
+ * We need to get from DCS the supported pixel encoding. */
+ enum pixel_encoding pe;
+
+ query_dcs = true;
+ pe = PIXEL_ENCODING_UNDEFINED;
+
+ while (get_next_display_supported_pixel_encoding(tlsq,
+ query_dcs, pe)) {
+ mt.crtc_timing.pixel_encoding = pe;
+ query_dcs = false;
+
+ /* call TS to add mode timing */
+ ret = dal_timing_service_add_mode_timing_to_path(
+ tlsq->timing_srv, tlsq->display_index,
+ &mt);
+ }
+ } else {
+ /* both display color depth and pixel encoding not defined
+ * we need to get from DCS the supported
+ */
+ enum pixel_encoding pe = PIXEL_ENCODING_UNDEFINED;
+
+ query_dcs = true;
+ while (get_next_display_supported_pixel_encoding(
+ tlsq,
+ query_dcs,
+ pe)) {
+ enum display_color_depth cd =
+ DISPLAY_COLOR_DEPTH_UNDEFINED;
+ mt.crtc_timing.pixel_encoding = pe;
+ while (get_next_display_supported_color_depth(
+ tlsq, query_dcs, &cd)) {
+ mt.crtc_timing.display_color_depth = cd;
+ query_dcs = false;
+
+ if (dal_timing_service_add_mode_timing_to_path(
+ tlsq->timing_srv,
+ tlsq->display_index,
+ &mt))
+ ret = true;
+ }
+
+ if (query_dcs)
+ /* looks like color depth query failed, no need
+ * to continue */
+ break;
+ }
+ }
+
+ if (ret) {
+ dal_mode_manager_update_disp_path_func_view_tbl(
+ dal_get_mode_manager(tlsq->parent_dal),
+ tlsq->display_index,
+ dal_timing_service_get_mode_timing_list_for_path(
+ tlsq->timing_srv,
+ tlsq->display_index));
+ tlsq->added_timing_count++;
+ }
+
+ return ret;
+}