summaryrefslogtreecommitdiff
path: root/drivers/gpu/drm/amd/dal/display_service/ds_dispatch_adjustment.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/gpu/drm/amd/dal/display_service/ds_dispatch_adjustment.c')
-rw-r--r--drivers/gpu/drm/amd/dal/display_service/ds_dispatch_adjustment.c1128
1 files changed, 1128 insertions, 0 deletions
diff --git a/drivers/gpu/drm/amd/dal/display_service/ds_dispatch_adjustment.c b/drivers/gpu/drm/amd/dal/display_service/ds_dispatch_adjustment.c
new file mode 100644
index 000000000000..6210302e74ce
--- /dev/null
+++ b/drivers/gpu/drm/amd/dal/display_service/ds_dispatch_adjustment.c
@@ -0,0 +1,1128 @@
+/*
+ * 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/adjustment_interface.h"
+#include "include/display_path_interface.h"
+#include "include/signal_types.h"
+#include "include/dcs_interface.h"
+#include "include/topology_mgr_interface.h"
+#include "include/display_service_interface.h"
+#include "include/set_mode_interface.h"
+#include "include/logger_interface.h"
+#include "include/fixed31_32.h"
+
+#include "ds_dispatch.h"
+#include "adjustment_container.h"
+#include "scaler_adj_group.h"
+#include "adjustment_api.h"
+#include "backlight_adj_group.h"
+#include "single_adj_group.h"
+#include "grph_colors_group.h"
+#include "gamut_space.h"
+#include "gamma_lut.h"
+#include "path_mode_set_with_data.h"
+
+#define NOT_IMPLEMENTED() DAL_LOGGER_NOT_IMPL( \
+ LOG_MINOR_COMPONENT_DISPLAY_SERVICE, "Display Service:%s\n", __func__)
+
+/* NOTE make sure to update CURRENT_ADJUSTMENT_NUM when updating this array */
+static const struct adj_global_info adj_global_info_array[CURRENT_ADJUSTMENT_NUM] = {
+ { ADJ_ID_SATURATION, ADJ_RANGED, { 0x140 }, { 1, 1, 1, 1, 1, 1, 1, 0, 1 } },
+ { ADJ_ID_BIT_DEPTH_REDUCTION, ADJ_RANGED, { 0x14A }, { 1, 1, 1, 1, 1, 1, 1, 0, 0 } },
+ { ADJ_ID_UNDERSCAN, ADJ_RANGED, { 0x145 }, { 0, 0, 1, 1, 1, 1, 1, 0, 1 } },
+ { ADJ_ID_UNDERSCAN_TYPE, ADJ_RANGED, { 0x101 }, { 0, 0, 1, 0, 1, 0, 0, 0, 1 } },
+ { ADJ_ID_BACKLIGHT, ADJ_RANGED, { 0x1a0 }, { 1, 1, 1, 1, 1, 1, 1, 0, 0 } },
+ { ADJ_ID_CONTRAST, ADJ_RANGED, { 0x160 }, { 1, 1, 1, 1, 1, 1, 1, 0, 1 } },
+ { ADJ_ID_BRIGHTNESS, ADJ_RANGED, { 0x140 }, { 1, 1, 1, 1, 1, 1, 1, 0, 1 } },
+ { ADJ_ID_HUE, ADJ_RANGED, { 0x140 }, { 1, 1, 1, 1, 1, 1, 1, 0, 1 } },
+ { ADJ_ID_TEMPERATURE, ADJ_RANGED, { 0x140 }, { 1, 1, 1, 1, 1, 1, 1, 0, 1 } },
+ { ADJ_ID_TEMPERATURE_SOURCE, ADJ_RANGED, { 0x142 }, { 1, 1, 1, 1, 0, 1, 1, 0, 1 } },
+ { ADJ_ID_NOMINAL_RANGE_RGB_LIMITED, ADJ_RANGED, { 0x141 }, { 1, 1, 1, 1, 1, 1, 1, 0, 1 } },
+ { ADJ_ID_GAMMA_RAMP, ADJ_LUT, { 0x108 }, { 1, 1, 1, 1, 1, 1, 1, 1, 1 } }
+};
+
+static void build_adj_container_for_path(struct ds_dispatch *ds,
+ struct display_path *display_path);
+
+static enum ds_signal_type get_ds_signal_from_display_path(
+ struct ds_dispatch *ds,
+ struct display_path *display_path,
+ uint32_t idx);
+
+/*get info from global table adj_global_info_array*/
+static enum ds_return get_adj_type(
+ struct ds_dispatch *ds,
+ enum adjustment_id adj_id,
+ enum adjustment_data_type *type)
+{
+ uint32_t i = 0;
+
+ if (adj_id < ADJ_ID_BEGIN || ADJ_ID_END < adj_id)
+ return DS_ERROR;
+ for (i = 0; i < CURRENT_ADJUSTMENT_NUM; i++) {
+ if (adj_global_info_array[i].adj_id == adj_id) {
+ *type = adj_global_info_array[i].adj_data_type;
+ return DS_SUCCESS;
+ }
+ }
+ return DS_ERROR;
+}
+
+static enum ds_return get_adj_info_from_defaults(
+ struct ds_dispatch *ds,
+ uint32_t disp_index,
+ struct display_path *path,
+ enum adjustment_id adjust_id,
+ struct adjustment_info *adj_info)
+{
+ struct adjustment_api *api = NULL;
+ enum signal_type signal;
+ union cea_video_capability_data_block video_cap = { {0} };
+ struct dcs *dcs = dal_display_path_get_dcs(path);
+
+ dal_dcs_get_cea_video_capability_data_block(dcs, &video_cap);
+ signal = dal_display_path_get_query_signal(path, SINK_LINK_INDEX);
+
+ api = dal_adj_parent_api_what_is_the_target_obj(
+ ds->default_adjustments,
+ signal);
+ if (!api)
+ return DS_ERROR;
+ get_adj_type(
+ ds,
+ adjust_id,
+ &adj_info->adj_data_type);
+
+ if (adj_info->adj_data_type == ADJ_RANGED) {
+ /*default value from table*/
+ if (!dal_adj_api_get_range_adj_data(
+ api, adjust_id, adj_info))
+ return DS_ERROR;
+ /*then override it by signal types and other requests*/
+ if (adjust_id == ADJ_ID_UNDERSCAN) {
+ if (signal == SIGNAL_TYPE_DVI_SINGLE_LINK ||
+ signal == SIGNAL_TYPE_DVI_SINGLE_LINK1 ||
+ signal == SIGNAL_TYPE_DVI_DUAL_LINK ||
+ signal == SIGNAL_TYPE_HDMI_TYPE_A ||
+ signal == SIGNAL_TYPE_WIRELESS) {
+ /*reviewers:this parts i changed a little bit
+ * compare with dal2*/
+ /*we set 0 underscan for non-HDMI or S_CE1 is
+ * 1,S_CE1 indicates monitor will underscan
+ * automaticlly*/
+ if (video_cap.bits.S_CE1 || signal !=
+ SIGNAL_TYPE_HDMI_TYPE_A)
+ adj_info->adj_data.ranged.def = 0;
+ }
+ }
+
+ }
+ return DS_SUCCESS;
+}
+
+static bool is_underscan_supported(
+ struct ds_dispatch *ds,
+ struct display_path *path,
+ enum dcs_edid_connector_type connector_type,
+ enum ds_signal_type ds_signal
+ )
+{
+ bool supported = true;
+ /* This call will check if underscan requirements are met.
+ Currently, this is checking to see if the display engine
+ clock is high enough to support underscan.*/
+ if (!dal_adapter_service_is_meet_underscan_req(ds->as))
+ supported = false;
+ /* Checks if underscan is for HDMI only */
+ else if (dal_adapter_service_underscan_for_hdmi_only(ds->as)) {
+ connector_type = dal_dcs_get_connector_type(
+ dal_display_path_get_dcs(path));
+
+ if (!((connector_type == EDID_CONNECTOR_HDMIA) ||
+ (dal_adapter_service_is_feature_supported(
+ FEATURE_INSTANT_UP_SCALE_DOWN_SCALE) &&
+ (ds_signal == DS_SIGNAL_TYPE_EDP))))
+ supported = false;
+
+ } else if (!dal_adapter_service_is_feature_supported(
+ FEATURE_INSTANT_UP_SCALE_DOWN_SCALE)) {
+ if (ds_signal == DS_SIGNAL_TYPE_EDP)
+ supported = false;
+ } else
+ supported = true;
+ return supported;
+}
+
+static bool is_adjustment_supported(
+ struct ds_dispatch *ds,
+ struct display_path *path,
+ enum adjustment_id adjust_id)
+{
+ bool supported = true;
+ uint32_t display_index;
+ uint32_t index = 0;
+ enum ds_signal_type ds_signal;
+ enum dcs_edid_connector_type connector_type;
+
+ if (!path) {
+ dal_logger_write(ds->dal_context->logger,
+ LOG_MAJOR_ERROR,
+ LOG_MINOR_COMPONENT_DISPLAY_SERVICE,
+ "display path is NULL");
+ return false;
+ }
+ display_index = dal_tm_display_path_to_display_index(ds->tm, path);
+ ds_signal = get_ds_signal_from_display_path(ds, path, display_index);
+ connector_type =
+ dal_dcs_get_connector_type(
+ dal_display_path_get_dcs(path));
+ if (ds_signal == DS_SIGNAL_TYPE_UNKNOWN) {
+ dal_logger_write(ds->dal_context->logger,
+ LOG_MAJOR_ERROR,
+ LOG_MINOR_COMPONENT_DISPLAY_SERVICE,
+ "DS_SIGNAL_TYPE_UNKNOWN");
+ return false;
+ }
+ for (index = 0; index < CURRENT_ADJUSTMENT_NUM; index++) {
+ if (adjust_id == adj_global_info_array[index].adj_id) {
+ if (false == adj_global_info_array[index].
+ display_is_supported[ds_signal])
+ return false;
+ else {
+ if ((adjust_id == ADJ_ID_UNDERSCAN) ||
+ (adjust_id == ADJ_ID_UNDERSCAN_TYPE))
+ supported =
+ is_underscan_supported(
+ ds,
+ path,
+ connector_type,
+ ds_signal);
+ break;
+ }
+ }
+ }
+ return supported;
+}
+
+static enum ds_return get_adjustment_info(
+ struct ds_dispatch *ds,
+ struct display_path *disp_path,
+ enum adjustment_id adjust_id,
+ bool fallback_to_default,
+ struct adjustment_info *adj_info)
+{
+ uint32_t display_index =
+ dal_display_path_get_display_index(disp_path);
+ struct adj_container *adj_container =
+ dal_ds_dispatch_get_adj_container_for_path(ds, display_index);
+ const struct adjustment_info *cont_info =
+ dal_adj_info_set_get_adj_info(
+ &adj_container->adj_info_set, adjust_id);
+
+ if (disp_path == NULL || adj_info == NULL ||
+ !is_adjustment_supported(ds, disp_path, adjust_id))
+ return DS_ERROR;
+
+ if (!adj_container)
+ return DS_ERROR;
+
+ if (cont_info != NULL)
+ *adj_info = *cont_info;
+ else if (fallback_to_default)
+ return get_adj_info_from_defaults(
+ ds,
+ display_index,
+ disp_path,
+ adjust_id,
+ adj_info);
+ else
+ return DS_ERROR;
+
+ return DS_SUCCESS;
+}
+
+enum ds_return dal_ds_dispatch_get_adjustment_info(
+ struct ds_dispatch *ds,
+ uint32_t display_index,
+ enum adjustment_id adjust_id,
+ struct adjustment_info *adj_info)
+{
+ struct display_path *display_path =
+ dal_tm_display_index_to_display_path(
+ ds->tm, display_index);
+ return get_adjustment_info(
+ ds,
+ display_path,
+ adjust_id,
+ true,
+ adj_info);
+}
+
+static enum ds_return get_adj_property(
+ struct ds_dispatch *ds,
+ uint32_t disp_index,
+ enum adjustment_id adjust_id,
+ union adjustment_property *adj_property)
+{
+ enum ds_return result = DS_ERROR;
+ uint32_t i = 0;
+
+ if (disp_index >= dal_tm_get_num_display_paths(ds->tm, false))
+ return DS_ERROR;
+ for (i = 0; i < CURRENT_ADJUSTMENT_NUM; i++) {
+ if (adj_global_info_array[i].adj_id == adjust_id) {
+ *adj_property = adj_global_info_array[i].adj_prop;
+ result = DS_SUCCESS;
+ break;
+ }
+ }
+ return result;
+}
+/* no used for now
+static void update_adj_container_use_edid(
+ struct ds_dispatch *ds,
+ struct display_path *display_path)
+{
+
+}*/
+
+static void build_gamut_adj_for_path(
+ struct ds_dispatch *ds,
+ uint32_t disp_index,
+ struct adj_container *adj_container,
+ struct display_path *display_path)
+{
+ struct gamut_data gamut_source_grph;
+ struct gamut_data gamut_destination;
+ struct ds_regamma_lut *regamma = NULL;
+
+ dal_memset(&gamut_source_grph, 0, sizeof(gamut_source_grph));
+ dal_memset(&gamut_destination, 0, sizeof(gamut_destination));
+
+ /* Gamut source grph */
+ dal_gamut_space_setup_default_gamut(
+ ADJ_ID_GAMUT_SOURCE_GRPH,
+ &gamut_source_grph,
+ true,
+ true);
+ dal_adj_container_update_gamut(
+ adj_container,
+ ADJ_ID_GAMUT_SOURCE_GRPH,
+ &gamut_source_grph);
+
+ /* Gamut Destination */
+ dal_gamut_space_setup_default_gamut(
+ ADJ_ID_GAMUT_DESTINATION,
+ &gamut_destination,
+ true,
+ true);
+ dal_adj_container_update_gamut(
+ adj_container,
+ ADJ_ID_GAMUT_DESTINATION,
+ &gamut_destination);
+
+ regamma = dal_alloc(sizeof(*regamma));
+ if (!dal_gamut_space_setup_predefined_regamma_coefficients(
+ &gamut_destination, regamma))
+ dal_ds_dispatch_setup_default_regamma(
+ ds, regamma);
+
+ dal_adj_container_set_regamma(
+ adj_container,
+ regamma);
+
+ dal_free(regamma);
+ regamma = NULL;
+
+}
+
+void dal_ds_dispatch_setup_default_regamma(
+ struct ds_dispatch *ds,
+ struct ds_regamma_lut *regamma)
+{
+ uint32_t i;
+
+ regamma->flags.u32all = 0;
+ regamma->flags.bits.COEFF_FROM_USER = 1;
+
+ for (i = 0 ; i < COEFF_RANGE ; i++) {
+ regamma->coeff.coeff_a0[i] = REGAMMA_COEFF_A0;
+ regamma->coeff.coeff_a1[i] = REGAMMA_COEFF_A1;
+ regamma->coeff.coeff_a2[i] = REGAMMA_COEFF_A2;
+ regamma->coeff.coeff_a3[i] = REGAMMA_COEFF_A3;
+ regamma->coeff.gamma[i] = REGAMMA_COEFF_GAMMA;
+ }
+
+}
+
+enum ds_return dal_ds_dispatch_get_adjustment_current_value(
+ struct ds_dispatch *ds,
+ struct adj_container *container,
+ struct adjustment_info *info,
+ enum adjustment_id id,
+ bool fall_back_to_default)
+{
+ if (info)
+ if (info->adj_data_type == ADJ_RANGED)
+ info->adj_data.ranged.cur = info->adj_data.ranged.def;
+ if (id == ADJ_ID_UNDERSCAN || id == ADJ_ID_UNDERSCAN_TYPE)
+ if (container &&
+ dal_adj_container_get_default_underscan_allow(
+ container))
+ info->adj_data.ranged.cur = 0;
+ return DS_SUCCESS;
+}
+
+enum ds_return dal_ds_dispatch_get_adjustment_value(
+ struct ds_dispatch *ds,
+ struct display_path *disp_path,
+ enum adjustment_id adj_id,
+ bool fall_back_to_default,
+ int32_t *value)
+{
+ uint32_t display_index;
+ struct adj_container *adj_container;
+ struct adjustment_info adj_info;
+
+ if (!disp_path)
+ return DS_ERROR;
+
+ if (!is_adjustment_supported(ds, disp_path, adj_id))
+ return DS_ERROR;
+
+ display_index = dal_display_path_get_display_index(
+ disp_path);
+ adj_container = dal_ds_dispatch_get_adj_container_for_path(
+ ds, display_index);
+
+ if (DS_SUCCESS != get_adjustment_info(ds,
+ disp_path, adj_id,
+ fall_back_to_default, &adj_info))
+ return DS_ERROR;
+
+ *value = adj_info.adj_data.ranged.cur;
+
+ if (adj_id == ADJ_ID_UNDERSCAN || adj_id == ADJ_ID_UNDERSCAN_TYPE)
+ if (adj_container &&
+ dal_adj_container_get_default_underscan_allow(
+ adj_container))
+ *value = 0;
+ if (adj_info.adj_data_type == ADJ_RANGED)
+ adj_info.adj_data.ranged.cur = *value;
+ else if (adj_info.adj_data_type == ADJ_BITVECTOR)
+ adj_info.adj_data.bit_vector.current_supported = *value;
+
+ return DS_SUCCESS;
+}
+
+void dal_ds_dispatch_update_adj_container_for_path_with_edid(
+ struct ds_dispatch *ds,
+ struct display_path *path)
+{
+ uint32_t index = dal_display_path_get_display_index(path);
+ struct adj_container *container;
+
+ if (!path)
+ dal_logger_write(ds->dal_context->logger,
+ LOG_MAJOR_ERROR,
+ LOG_MINOR_COMPONENT_DISPLAY_SERVICE,
+ "display_path is unknown");
+ container = dal_ds_dispatch_get_adj_container_for_path(ds, index);
+ dal_adj_container_update_display_cap(container, path);
+ dal_adj_container_update_signal_type(
+ container,
+ dal_display_path_get_query_signal(path, SINK_LINK_INDEX));
+ build_adj_container_for_path(ds, path);
+}
+
+void dal_ds_dispatch_update_adj_container_for_path_with_mode_info(
+ struct ds_dispatch *ds,
+ struct display_path *display_path,
+ const struct path_mode *path_mode)
+{
+ uint32_t index = dal_display_path_get_display_index(display_path);
+ struct adj_container *container;
+
+ if (!display_path)
+ dal_logger_write(ds->dal_context->logger,
+ LOG_MAJOR_ERROR,
+ LOG_MINOR_COMPONENT_DISPLAY_SERVICE,
+ "display_path is unknown");
+ container = dal_ds_dispatch_get_adj_container_for_path(ds, index);
+ if (container) {
+ dal_adj_container_update_timing_mode(
+ container,
+ &path_mode->mode_timing->mode_info,
+ &path_mode->view);
+ dal_ds_dispatch_update_adj_container_for_path_with_edid(
+ ds,
+ display_path);
+ }
+
+}
+
+static enum ds_signal_type get_ds_signal_from_display_path(
+ struct ds_dispatch *ds,
+ struct display_path *display_path,
+ uint32_t idx)
+{ enum ds_signal_type ds_signal = DS_SIGNAL_TYPE_CRT;
+ enum signal_type signal = dal_display_path_get_query_signal(
+ display_path,
+ SINK_LINK_INDEX);
+ switch (signal) {
+ case SIGNAL_TYPE_DVI_SINGLE_LINK:
+ case SIGNAL_TYPE_DVI_SINGLE_LINK1:
+ case SIGNAL_TYPE_DVI_DUAL_LINK:
+ ds_signal = DS_SIGNAL_TYPE_DFP;
+ break;
+ case SIGNAL_TYPE_HDMI_TYPE_A:
+ ds_signal = DS_SIGNAL_TYPE_HDMI;
+ break;
+ case SIGNAL_TYPE_DISPLAY_PORT:
+ case SIGNAL_TYPE_DISPLAY_PORT_MST:
+ ds_signal = DS_SIGNAL_TYPE_DP;
+ break;
+ case SIGNAL_TYPE_EDP:
+ ds_signal = DS_SIGNAL_TYPE_EDP;
+ break;
+ case SIGNAL_TYPE_RGB:
+ if (dal_dcs_is_non_continous_frequency(
+ dal_display_path_get_dcs(display_path)))
+ ds_signal = DS_SIGNAL_TYPE_DISCRETEVGA;
+ else
+ ds_signal = DS_SIGNAL_TYPE_CRT;
+ break;
+ case SIGNAL_TYPE_MVPU_A:
+ case SIGNAL_TYPE_MVPU_B:
+ case SIGNAL_TYPE_MVPU_AB:
+ ds_signal = DS_SIGNAL_TYPE_CF;
+ break;
+ case SIGNAL_TYPE_WIRELESS:
+ ds_signal = DS_SIGNAL_TYPE_WIRELESS;
+ break;
+ default:
+ ds_signal = DS_SIGNAL_TYPE_UNKNOWN;
+ dal_logger_write(ds->dal_context->logger,
+ LOG_MAJOR_ERROR,
+ LOG_MINOR_COMPONENT_DISPLAY_SERVICE,
+ "dignal type is unknown");
+ break;
+ }
+ return ds_signal;
+}
+
+struct adj_container *dal_ds_dispatch_get_adj_container_for_path(
+ const struct ds_dispatch *ds,
+ uint32_t display_index)
+{
+
+ if (display_index < ds->disp_path_num)
+ return ds->applicable_adj[display_index];
+ return NULL;
+}
+
+bool dal_ds_dispatch_initialize_adjustment(struct ds_dispatch *ds)
+{
+ uint32_t i;
+ uint32_t num;
+
+ /* TODO unnecesary init_data. can just pass ds */
+ struct backlight_adj_group_init_data backlight_init_data;
+ struct single_adj_group_init_data single_init_data;
+ struct grph_colors_group_init_data colors_init_data;
+ struct grph_gamma_lut_group_init_data gamma_init_data;
+
+ ds->disp_path_num = dal_tm_get_num_display_paths(ds->tm, false);
+ num = ds->disp_path_num;
+
+ if (num == 0)
+ return false;
+
+ ds->applicable_adj = dal_alloc((sizeof(*ds->applicable_adj) * num));
+ if (ds->applicable_adj == NULL)
+ return false;
+ for (i = 0; i < num; i++) {
+ ds->applicable_adj[i] = dal_adj_container_create();
+ if (!ds->applicable_adj[i]) {
+ dal_logger_write(
+ ds->dal_context->logger,
+ LOG_MAJOR_ERROR,
+ LOG_MINOR_COMPONENT_DISPLAY_SERVICE,
+ "initilize_adjustment has error");
+ dal_adj_container_destroy(ds->applicable_adj);
+ return false;
+ }
+ }
+
+ ds->default_adjustments = dal_adj_parent_api_create();
+ if (!ds->default_adjustments)
+ return false;
+ dal_adj_parent_api_build_child_objs(ds->default_adjustments);
+
+ backlight_init_data.ds = ds;
+ backlight_init_data.as = ds->as;
+ backlight_init_data.hws = ds->hwss;
+ backlight_init_data.tm = ds->tm;
+ backlight_init_data.dal_context = ds->dal_context;
+ ds->backlight_adj = dal_backlight_adj_group_create(
+ &backlight_init_data);
+ if (!ds->backlight_adj) {
+ dal_ds_dispatch_cleanup_adjustment(ds);
+ return false;
+ }
+ single_init_data.ds = ds;
+ single_init_data.hws = ds->hwss;
+ single_init_data.tm = ds->tm;
+ single_init_data.dal_context = ds->dal_context;
+ ds->single_adj = dal_single_adj_group_create(&single_init_data);
+
+ if (!ds->single_adj) {
+ dal_ds_dispatch_cleanup_adjustment(ds);
+ return false;
+ }
+ colors_init_data.ds = ds;
+ colors_init_data.hws = ds->hwss;
+ colors_init_data.dal_context = ds->dal_context;
+ ds->grph_colors_adj =
+ dal_grph_colors_group_create(&colors_init_data);
+ if (!ds->grph_colors_adj) {
+ dal_ds_dispatch_cleanup_adjustment(ds);
+ return false;
+ }
+
+ gamma_init_data.ds = ds;
+ gamma_init_data.hws = ds->hwss;
+ gamma_init_data.dal_context = ds->dal_context;
+ ds->grph_gamma_adj = dal_gamma_adj_group_create(&gamma_init_data);
+ if (!ds->grph_gamma_adj) {
+ dal_ds_dispatch_cleanup_adjustment(ds);
+ return false;
+ }
+
+ return true;
+}
+
+void dal_ds_dispatch_cleanup_adjustment(struct ds_dispatch *ds)
+{
+ uint32_t i;
+ uint32_t num;
+
+ num = ds->disp_path_num;
+
+ for (i = 0; i < num; i++)
+ dal_adj_container_destroy(ds->applicable_adj + i);
+ dal_free(ds->applicable_adj);
+
+ if (ds->default_adjustments)
+ dal_adj_parent_api_destroy(&ds->default_adjustments);
+
+ if (ds->backlight_adj != NULL)
+ dal_backlight_adj_group_destroy(&ds->backlight_adj);
+
+ if (ds->single_adj != NULL)
+ dal_single_adj_group_destroy(&ds->single_adj);
+
+ if (ds->grph_colors_adj != NULL)
+ dal_grph_colors_adj_group_destroy(&ds->grph_colors_adj);
+
+ if (ds->grph_gamma_adj != NULL)
+ dal_grph_gamma_adj_group_destroy(&ds->grph_gamma_adj);
+
+}
+
+bool dal_ds_dispatch_build_post_set_mode_adj(
+ struct ds_dispatch *ds,
+ const struct path_mode *mode,
+ struct display_path *display_path,
+ struct hw_adjustment_set *set)
+{
+ /*TODO: add implementation*/
+ return false;
+}
+
+bool dal_ds_dispatch_apply_scaling(
+ struct ds_dispatch *ds,
+ const struct path_mode *mode,
+ struct adj_container *container,
+ enum build_path_set_reason reason,
+ struct hw_path_mode *hw_path_mode)
+{
+ enum adjustment_id adj_id = ADJ_ID_UNDERSCAN;
+ struct ds_adjustment_scaler scaler;
+ const struct adjustment_info *info;
+ struct adj_container *set;
+
+ if (!hw_path_mode || !container)
+ return false;
+ info = dal_adj_info_set_get_adj_info(&container->adj_info_set, adj_id);
+
+ if (!info)
+ return false;
+ if (reason == BUILD_PATH_SET_REASON_FALLBACK_UNDERSCAN &&
+ hw_path_mode->action == HW_PATH_ACTION_SET) {
+ set = dal_ds_dispatch_get_adj_container_for_path(
+ ds,
+ mode->display_path_index);
+ dal_adj_info_set_update_cur_value(
+ &set->adj_info_set, adj_id, 0);
+ }
+ if (!dal_scaler_adj_group_build_scaler_parameter(
+ mode,
+ container,
+ reason,
+ adj_id,
+ info->adj_data.ranged.cur,
+ NULL,
+ hw_path_mode->display_path,
+ &scaler))
+ return false;
+ return dal_scaler_adj_group_apply_scaling(
+ &scaler,
+ container,
+ reason,
+ hw_path_mode);
+}
+
+bool dal_ds_dispatch_is_adjustment_supported(
+ struct ds_dispatch *ds,
+ uint32_t display_index,
+ enum adjustment_id adjust_id)
+{
+ struct display_path *display_path =
+ dal_tm_display_index_to_display_path(
+ ds->tm, display_index);
+ return is_adjustment_supported(ds, display_path, adjust_id);
+}
+
+enum ds_return dal_ds_dispatch_get_property(
+ struct ds_dispatch *adj,
+ uint32_t display_index,
+ enum adjustment_id adjust_id,
+ union adjustment_property *property)
+{
+ /*TODO: add implementation*/
+ return DS_ERROR;
+}
+
+enum ds_return dal_ds_dispatch_set_adjustment(
+ struct ds_dispatch *ds,
+ const uint32_t display_index,
+ enum adjustment_id adjust_id,
+ int32_t value)
+{
+ enum ds_return result = DS_ERROR;
+ struct display_path *display_path =
+ dal_tm_display_index_to_display_path(
+ ds->tm, display_index);
+ if (display_path == NULL || !is_adjustment_supported(
+ ds, display_path, adjust_id)) {
+ dal_logger_write(ds->dal_context->logger,
+ LOG_MAJOR_ERROR,
+ LOG_MINOR_COMPONENT_DISPLAY_SERVICE,
+ "display path is NULL");
+ return DS_ERROR;
+ }
+ switch (adjust_id) {
+ case ADJ_ID_SATURATION:
+ result = dal_grph_colors_group_set_adjustment(
+ ds->grph_colors_adj,
+ display_path,
+ adjust_id,
+ value);
+ break;
+
+ case ADJ_ID_UNDERSCAN:
+ case ADJ_ID_UNDERSCAN_TYPE:
+ result = dal_scaler_adj_group_set_adjustment(
+ ds,
+ display_index,
+ display_path,
+ adjust_id,
+ value);
+ break;
+
+ case ADJ_ID_BACKLIGHT:
+ result = dal_backlight_adj_group_set_adjustment(
+ ds->backlight_adj,
+ display_path,
+ adjust_id,
+ value);
+ break;
+ case ADJ_ID_BIT_DEPTH_REDUCTION:
+ result = dal_single_adj_group_set_adjustment(
+ ds->single_adj,
+ display_path,
+ adjust_id,
+ value);
+ break;
+ default:
+ dal_logger_write(ds->dal_context->logger,
+ LOG_MAJOR_ERROR,
+ LOG_MINOR_COMPONENT_DISPLAY_SERVICE,
+ "set_adjustment failed");
+ result = DS_ERROR;
+ }
+ return result;
+}
+
+enum ds_return dal_ds_dispatch_set_gamma_adjustment(struct ds_dispatch *ds,
+ uint32_t display_index, enum adjustment_id adjust_id,
+ const struct raw_gamma_ramp *gamma) {
+ struct adj_container *adj_container = NULL;
+ const struct adjustment_info *cont_info = NULL;
+ const struct ds_regamma_lut *regumma_lut = NULL;
+ struct display_path *disp_path;
+ const struct path_mode *disp_path_mode;
+
+ if (ds == NULL)
+ return DS_ERROR;
+
+ disp_path = dal_tm_display_index_to_display_path(
+ ds->tm, display_index);
+
+ disp_path_mode = dal_pms_with_data_get_path_mode_for_display_index(
+ ds->set,
+ display_index);
+
+ if (disp_path == NULL || disp_path_mode == NULL)
+ return DS_ERROR;
+
+ adj_container = dal_ds_dispatch_get_adj_container_for_path(ds,
+ display_index);
+
+ if (adj_container == NULL)
+ return DS_ERROR;
+
+ cont_info = dal_adj_info_set_get_adj_info(&adj_container->adj_info_set,
+ adjust_id);
+
+ if (cont_info == NULL)
+ return DS_ERROR;
+
+ if (disp_path == NULL || cont_info == NULL ||
+ !is_adjustment_supported(ds, disp_path, adjust_id))
+ return DS_ERROR;
+
+ if (!is_adjustment_supported(ds, disp_path, adjust_id))
+ return DS_ERROR;
+
+ regumma_lut = dal_adj_container_get_regamma(
+ adj_container);
+
+ if (regumma_lut == NULL)
+ return DS_ERROR;
+
+ if (dal_grph_gamma_lut_set_adjustment(ds, disp_path, disp_path_mode,
+ adjust_id, gamma, regumma_lut))
+ return DS_SUCCESS;
+
+ return DS_ERROR;
+}
+
+const struct raw_gamma_ramp *dal_ds_dispatch_get_current_gamma(
+ struct ds_dispatch *ds,
+ uint32_t display_index,
+ enum adjustment_id adjust_id)
+{
+ /*TODO: add implementation*/
+ return NULL;
+}
+
+const struct raw_gamma_ramp *dal_ds_dispatch_get_default_gamma(
+ struct ds_dispatch *ds,
+ uint32_t display_index,
+ enum adjustment_id adjust_id)
+{
+ /*TODO: add implementation*/
+ return NULL;
+}
+
+enum ds_return dal_ds_dispatch_set_current_gamma(
+ struct ds_dispatch *ds,
+ uint32_t display_index,
+ enum adjustment_id adjust_id,
+ const struct raw_gamma_ramp *gamma)
+{
+ /*TODO: add implementation*/
+ return DS_ERROR;
+}
+
+enum ds_return dal_ds_dispatch_set_gamma(
+ struct ds_dispatch *ds,
+ uint32_t display_index,
+ enum adjustment_id adjust_id,
+ const struct raw_gamma_ramp *gamma)
+{
+ /*TODO: add implementation*/
+ return DS_ERROR;
+}
+
+bool dal_ds_dispatch_get_underscan_info(
+ struct ds_dispatch *ds,
+ uint32_t display_index,
+ struct ds_underscan_info *info)
+{
+ bool result = false;
+ struct display_path *display_path =
+ dal_tm_display_index_to_display_path(
+ ds->tm, display_index);
+ const struct path_mode *path_mode =
+ dal_pms_with_data_get_path_mode_for_display_index(
+ ds->set, display_index);
+ if (!display_path || !path_mode)
+ return false;
+ /*TODO: add implementation*
+ * result = scaler_adj->get_underscan_info();*/
+ return result;
+}
+
+bool dal_ds_dispatch_get_underscan_mode(
+ struct ds_dispatch *ds,
+ uint32_t display_index,
+ struct ds_underscan_desc *desc)
+{
+ /*TODO: add implementation*/
+ return false;
+}
+
+bool dal_ds_dispatch_set_underscan_mode(
+ struct ds_dispatch *ds,
+ uint32_t display_index,
+ struct ds_underscan_desc *desc)
+{
+ /*TODO: add implementation*/
+ return false;
+}
+
+bool dal_ds_dispatch_setup_overlay(
+ struct ds_dispatch *adj,
+ uint32_t display_index,
+ struct overlay_data *data)
+{
+ /*TODO: add implementation*/
+ return false;
+}
+
+void dal_ds_dispatch_set_applicable_adj(
+ struct ds_dispatch *adj,
+ uint32_t display_index,
+ const struct adj_container *applicable)
+{
+ /*TODO: add implementation*/
+}
+
+enum ds_return dal_ds_dispatch_set_color_gamut(
+ struct ds_dispatch *adj,
+ uint32_t display_index,
+ const struct ds_set_gamut_data *data)
+{
+ /*TODO: add implementation*/
+ return DS_ERROR;
+}
+
+enum ds_return dal_ds_dispatch_get_color_gamut(
+ struct ds_dispatch *adj,
+ uint32_t display_index,
+ const struct ds_gamut_reference_data *ref,
+ struct ds_get_gamut_data *data)
+{
+ /*TODO: add implementation*/
+ return DS_ERROR;
+}
+
+enum ds_return dal_ds_dispatch_get_color_gamut_info(
+ struct ds_dispatch *adj,
+ uint32_t display_index,
+ const struct ds_gamut_reference_data *ref,
+ struct ds_gamut_info *data)
+{
+ /*TODO: add implementation*/
+ return DS_ERROR;
+}
+
+enum ds_return dal_ds_dispatch_get_regamma_lut(
+ struct ds_dispatch *adj,
+ uint32_t display_index,
+ struct ds_regamma_lut *data)
+{
+ /*TODO: add implementation*/
+ return DS_ERROR;
+}
+
+enum ds_return dal_ds_dispatch_set_regamma_lut(
+ struct ds_dispatch *adj,
+ uint32_t display_index,
+ struct ds_regamma_lut *data)
+{
+ /*TODO: add implementation*/
+ return DS_ERROR;
+}
+
+enum ds_return dal_ds_dispatch_set_info_packets(
+ struct ds_dispatch *adj,
+ uint32_t display_index,
+ const struct info_frame *info_frames)
+{
+ /*TODO: add implementation*/
+ return DS_ERROR;
+}
+
+enum ds_return dal_ds_dispatch_get_info_packets(
+ struct ds_dispatch *adj,
+ uint32_t display_index,
+ struct info_frame *info_frames)
+{
+ /*TODO: add implementation*/
+ return DS_ERROR;
+}
+
+static void build_adj_container_for_path(
+ struct ds_dispatch *ds,
+ struct display_path *display_path)
+{
+ uint32_t index = 0;
+ uint32_t i = 0;
+
+ struct adjustment_info info;
+ struct adj_container *container = NULL;
+
+ dal_memset(&info, 0, sizeof(struct adjustment_info));
+ index = dal_display_path_get_display_index(display_path);
+ if (!display_path)
+ dal_logger_write(ds->dal_context->logger,
+ LOG_MAJOR_ERROR,
+ LOG_MINOR_COMPONENT_DISPLAY_SERVICE,
+ "display_path is unknown");
+ container = dal_ds_dispatch_get_adj_container_for_path(ds, index);
+
+ if (!container)
+ return;
+
+ if (!dal_adj_container_is_update_required(container))
+ return;
+
+ dal_adj_info_set_clear(&container->adj_info_set);
+
+ build_gamut_adj_for_path(ds, index, container, display_path);
+
+ for (i = ADJ_ID_BEGIN; i < ADJ_ID_END; i++) {
+ enum adjustment_id adj_id = i;
+
+ if (is_adjustment_supported(ds, display_path, adj_id)) {
+ if (DS_SUCCESS != get_adj_info_from_defaults(
+ ds,
+ index,
+ display_path,
+ adj_id,
+ &info))
+ continue;
+ if (DS_SUCCESS != get_adj_property(
+ ds,
+ index,
+ adj_id,
+ &info.adj_prop))
+ continue;
+ info.adj_id = adj_id;
+ info.adj_state = ADJUSTMENT_STATE_VALID;
+ dal_adj_info_set_add_adj_info(
+ &container->adj_info_set,
+ &info);
+ if (ADJ_RANGED == info.adj_data_type) {
+ dal_ds_dispatch_get_adjustment_current_value(
+ ds,
+ container,
+ &info,
+ adj_id,
+ true);
+ dal_adj_info_set_update_cur_value(
+ &container->adj_info_set,
+ adj_id,
+ info.adj_data.ranged.cur);
+ }
+
+ }
+ }
+
+ dal_adj_container_updated(container);
+}
+
+bool dal_ds_dispatch_include_adjustment(
+ struct ds_dispatch *ds,
+ struct display_path *disp_path,
+ struct ds_adj_id_value adj,
+ struct hw_adjustment_set *set)
+{
+ bool ret = false;
+
+ if (adj.adj_id == ADJ_ID_BIT_DEPTH_REDUCTION)
+ ret = dal_single_adj_group_include_adjustment(
+ ds->single_adj,
+ disp_path, adj, set);
+ return ret;
+}
+
+bool dal_ds_dispatch_build_include_adj(
+ struct ds_dispatch *ds,
+ const struct path_mode *mode,
+ struct display_path *display_path,
+ struct hw_path_mode *hw_mode,
+ struct hw_adjustment_set *set)
+{
+ /* TODO implement build_include_adjustments */
+ return false;
+}
+
+bool dal_ds_dispatch_build_color_control_adj(
+ struct ds_dispatch *ds,
+ const struct path_mode *mode,
+ struct display_path *disp_path,
+ struct hw_adjustment_set *set)
+{
+ if (!ds->grph_colors_adj || !disp_path)
+ return false;
+
+ return dal_grph_colors_group_build_color_control_adj(
+ ds->grph_colors_adj,
+ mode,
+ disp_path,
+ set);
+}
+
+void dal_ds_dispatch_update_adj_container_for_path_with_color_space(
+ struct ds_dispatch *ds,
+ uint32_t display_index,
+ enum ds_color_space color_space)
+{
+ struct adj_container *adj_container;
+
+ adj_container = dal_ds_dispatch_get_adj_container_for_path(
+ ds, display_index);
+
+ if (adj_container != NULL)
+ dal_adj_container_update_color_space(
+ adj_container,
+ color_space);
+}