summaryrefslogtreecommitdiff
path: root/drivers/gpu/drm/amd/dal/display_service/grph_colors_group.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/gpu/drm/amd/dal/display_service/grph_colors_group.c')
-rw-r--r--drivers/gpu/drm/amd/dal/display_service/grph_colors_group.c1326
1 files changed, 1326 insertions, 0 deletions
diff --git a/drivers/gpu/drm/amd/dal/display_service/grph_colors_group.c b/drivers/gpu/drm/amd/dal/display_service/grph_colors_group.c
new file mode 100644
index 000000000000..e70624188285
--- /dev/null
+++ b/drivers/gpu/drm/amd/dal/display_service/grph_colors_group.c
@@ -0,0 +1,1326 @@
+/*
+ * Copyright 2015 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/hw_sequencer_types.h"
+#include "include/display_service_types.h"
+#include "include/display_path_interface.h"
+#include "include/set_mode_interface.h"
+#include "include/adjustment_interface.h"
+#include "include/hw_sequencer_interface.h"
+#include "include/hw_adjustment_set.h"
+#include "include/logger_interface.h"
+#include "include/fixed31_32.h"
+
+#include "ds_dispatch.h"
+#include "adjustment_container.h"
+#include "grph_colors_group.h"
+#include "gamut_space.h"
+#include "color_temperature.h"
+#include "ds_translation.h"
+
+enum ds_color_space dal_grph_colors_group_get_color_space(
+ struct grph_colors_group *grph_colors_adj,
+ const struct crtc_timing *timing,
+ const struct display_path *disp_path,
+ struct adj_container *adj_container)
+{
+ const struct adjustment_info *nominal_limited = NULL;
+ enum ds_color_space color_space = DS_COLOR_SPACE_UNKNOWN;
+
+ if (disp_path == NULL || timing == NULL)
+ return color_space;
+
+ if (adj_container != NULL) {
+ nominal_limited = dal_adj_info_set_get_adj_info(
+ &adj_container->adj_info_set,
+ ADJ_ID_NOMINAL_RANGE_RGB_LIMITED);
+ switch (dal_display_path_get_query_signal(
+ disp_path, SINK_LINK_INDEX)) {
+ case SIGNAL_TYPE_MVPU_A:
+ case SIGNAL_TYPE_MVPU_B:
+ case SIGNAL_TYPE_MVPU_AB:
+ color_space = dal_adj_container_get_color_space(
+ adj_container);
+ break;
+ default:
+ break;
+ }
+ }
+ if (color_space == DS_COLOR_SPACE_UNKNOWN) {
+ enum ds_color_space hdmi_request_color_space =
+ DS_COLOR_SPACE_SRGB_LIMITEDRANGE;
+ if (nominal_limited != NULL &&
+ (nominal_limited->adj_data.ranged.cur ==
+ nominal_limited->adj_data.ranged.min))
+ hdmi_request_color_space =
+ DS_COLOR_SPACE_SRGB_FULLRANGE;
+ color_space =
+ dal_grph_colors_group_build_default_color_space(
+ grph_colors_adj,
+ timing,
+ disp_path,
+ hdmi_request_color_space);
+ if (nominal_limited != NULL &&
+ nominal_limited->adj_data.ranged.cur !=
+ nominal_limited->adj_data.ranged.min &&
+ color_space == DS_COLOR_SPACE_SRGB_FULLRANGE)
+ color_space = DS_COLOR_SPACE_SRGB_LIMITEDRANGE;
+ else if (nominal_limited != NULL &&
+ nominal_limited->adj_data.ranged.cur ==
+ nominal_limited->adj_data.ranged.min &&
+ color_space == DS_COLOR_SPACE_SRGB_LIMITEDRANGE)
+ color_space = DS_COLOR_SPACE_SRGB_FULLRANGE;
+
+ }
+ return color_space;
+}
+
+enum ds_return dal_grph_colors_group_set_adjustment(
+ struct grph_colors_group *grph_colors_adj,
+ struct display_path *disp_path,
+ enum adjustment_id adj_id,
+ uint32_t value)
+{
+ enum ds_return ret = DS_ERROR;
+ const struct path_mode_set_with_data *pms_wd;
+ struct adj_container *adj_container;
+ const struct path_mode *path_mode;
+ const struct adjustment_info *adj_info;
+ struct gamut_parameter *gamut = NULL;
+ struct ds_regamma_lut *regamma = NULL;
+ struct hw_adjustment_color_control *color_control = NULL;
+ uint32_t display_index;
+
+ if (!disp_path)
+ return DS_ERROR;
+
+ display_index = dal_display_path_get_display_index(
+ disp_path);
+
+ pms_wd = dal_ds_dispatch_get_active_pms_with_data(
+ grph_colors_adj->ds);
+ if (!pms_wd)
+ return DS_ERROR;
+
+ adj_container = dal_ds_dispatch_get_adj_container_for_path(
+ grph_colors_adj->ds,
+ display_index);
+
+ if (!adj_container)
+ return DS_ERROR;
+
+ path_mode =
+ dal_pms_with_data_get_path_mode_for_display_index(
+ pms_wd,
+ display_index);
+
+ if (!path_mode)
+ return DS_ERROR;
+
+
+ adj_info = dal_adj_info_set_get_adj_info(
+ &adj_container->adj_info_set,
+ adj_id);
+
+ if (!adj_info)
+ return DS_ERROR;
+
+ if (dal_adj_container_is_adjustment_committed(
+ adj_container, adj_id) &&
+ (adj_info->adj_data.ranged.cur == value))
+ return DS_SUCCESS;
+
+ if (!dal_adj_info_set_update_cur_value(
+ &adj_container->adj_info_set,
+ adj_id, value))
+ return DS_ERROR;
+
+ gamut = dal_alloc(sizeof(*gamut));
+ if (!gamut)
+ goto gamut_fail;
+ regamma = dal_alloc(sizeof(*regamma));
+ if (!regamma)
+ goto regamma_fail;
+ color_control = dal_alloc(sizeof(*color_control));
+ if (!color_control)
+ goto color_control_fail;
+
+ if (dal_grph_colors_group_compute_hw_adj_color_control(
+ grph_colors_adj,
+ adj_container,
+ &path_mode->mode_timing->crtc_timing,
+ disp_path,
+ adj_id,
+ gamut,
+ regamma,
+ color_control)) {
+ enum ds_color_space color_space;
+
+ color_control->surface_pixel_format =
+ path_mode->pixel_format;
+
+ dal_adj_container_set_regamma(
+ adj_container,
+ regamma);
+
+ dal_hw_sequencer_set_color_control_adjustment(
+ grph_colors_adj->hws,
+ dal_display_path_get_controller(disp_path),
+ color_control);
+
+ color_space =
+ dal_ds_translation_color_space_from_hw_color_space(
+ color_control->color_space);
+
+ dal_adj_container_update_color_space(
+ adj_container,
+ color_space);
+ dal_adj_container_commit_adj(adj_container, adj_id);
+ ret = DS_SUCCESS;
+ }
+
+ dal_free(color_control);
+color_control_fail:
+ dal_free(regamma);
+regamma_fail:
+ dal_free(gamut);
+gamut_fail:
+ return ret;
+}
+
+static int32_t get_hw_value_from_sw_value(
+ const struct hw_adjustment_range *hw_range,
+ const struct adjustment_info *sw_range)
+{
+ int32_t sw_val = sw_range->adj_data.ranged.cur;
+ int32_t sw_min = sw_range->adj_data.ranged.min;
+ int32_t sw_max = sw_range->adj_data.ranged.max;
+ int32_t hw_max = hw_range->max;
+ int32_t hw_min = hw_range->min;
+ int32_t sw_data = sw_max - sw_min;
+ int32_t hw_data = hw_max - hw_min;
+ int32_t hw_val;
+
+ if (sw_data == 0)
+ return hw_min;
+ if (sw_data != hw_data)
+ hw_val =
+ (sw_val - sw_min) * hw_data / sw_data + hw_min;
+ else {
+ hw_val = sw_val;
+ if (sw_min != hw_min)
+ hw_val += (hw_min - sw_min);
+ }
+
+ return hw_val;
+}
+
+static bool is_current_same_as_default(
+ struct adjustment_info *adj_info)
+{
+ return adj_info->adj_data.ranged.cur ==
+ adj_info->adj_data.ranged.def;
+}
+
+bool dal_grph_colors_group_compute_hw_adj_color_control(
+ struct grph_colors_group *grph_colors_adj,
+ struct adj_container *adj_container,
+ const struct crtc_timing *timing,
+ struct display_path *disp_path,
+ enum adjustment_id reason_id,
+ struct gamut_parameter *gamut,
+ struct ds_regamma_lut *regamma,
+ struct hw_adjustment_color_control *color_control)
+{
+ struct adjustment_info *brightness =
+ dal_adj_info_set_get_adj_info(
+ &adj_container->adj_info_set,
+ ADJ_ID_BRIGHTNESS);
+ struct adjustment_info *contrast =
+ dal_adj_info_set_get_adj_info(
+ &adj_container->adj_info_set,
+ ADJ_ID_CONTRAST);
+ struct adjustment_info *hue =
+ dal_adj_info_set_get_adj_info(
+ &adj_container->adj_info_set,
+ ADJ_ID_HUE);
+ struct adjustment_info *saturation =
+ dal_adj_info_set_get_adj_info(
+ &adj_container->adj_info_set,
+ ADJ_ID_SATURATION);
+ struct adjustment_info *temperature =
+ dal_adj_info_set_get_adj_info(
+ &adj_container->adj_info_set,
+ ADJ_ID_TEMPERATURE);
+ struct adjustment_info *temperature_src =
+ dal_adj_info_set_get_adj_info(
+ &adj_container->adj_info_set,
+ ADJ_ID_TEMPERATURE_SOURCE);
+ const struct display_characteristics *disp_char =
+ dal_adj_container_get_disp_character(
+ adj_container);
+ struct hw_color_control_range hw_color_range;
+ struct white_point_data white_point;
+ const struct ds_regamma_lut *const_regamma = NULL;
+ int32_t requested_temperature;
+ bool gamut_adj_avails;
+ enum signal_type signal;
+
+ /* reset updated info */
+ grph_colors_adj->regamma_updated = false;
+ grph_colors_adj->gamut_dst_updated = false;
+ grph_colors_adj->gamut_src_updated = false;
+
+ if (NULL == grph_colors_adj->hws ||
+ NULL == brightness ||
+ NULL == contrast ||
+ NULL == hue ||
+ NULL == saturation ||
+ NULL == temperature ||
+ NULL == disp_path)
+ return false;
+
+ dal_memset(&hw_color_range, 0, sizeof(hw_color_range));
+ dal_memset(&white_point, 0, sizeof(white_point));
+ requested_temperature = temperature->adj_data.ranged.cur;
+ signal = dal_display_path_get_query_signal(
+ disp_path, SINK_LINK_INDEX);
+ color_control->adjust_divider = ADJUST_DIVIDER;
+ color_control->temperature_divider = GAMUT_DIVIDER;
+ gamut_adj_avails =
+ dal_hw_sequencer_is_support_custom_gamut_adj(
+ grph_colors_adj->hws,
+ disp_path,
+ HW_GRAPHIC_SURFACE);
+
+ if (!dal_adj_container_get_gamut(
+ adj_container,
+ ADJ_ID_GAMUT_SOURCE_GRPH,
+ &gamut->gamut_src))
+ return false;
+
+ if (!dal_adj_container_get_gamut(
+ adj_container,
+ ADJ_ID_GAMUT_DESTINATION,
+ &gamut->gamut_dst))
+ return false;
+
+ const_regamma = dal_adj_container_get_regamma(
+ adj_container);
+ if (!const_regamma)
+ return false;
+ dal_memmove(&gamut->regamma, const_regamma, sizeof(gamut->regamma));
+
+ if (signal == SIGNAL_TYPE_HDMI_TYPE_A)
+ gamut->source = GAMUT_SPACE_SOURCE_DEFAULT;
+ else {
+ gamut->source =
+ temperature_src->adj_data.ranged.cur ==
+ COLOR_TEMPERATURE_SOURCE_EDID ?
+ GAMUT_SPACE_SOURCE_EDID :
+ GAMUT_SPACE_SOURCE_USER_GAMUT;
+ if (requested_temperature == -1)
+ gamut->source = GAMUT_SPACE_SOURCE_EDID;
+
+ if (disp_char == NULL && gamut->source ==
+ GAMUT_SPACE_SOURCE_EDID)
+ gamut->source = GAMUT_SPACE_SOURCE_DEFAULT;
+
+ if (gamut->source == GAMUT_SPACE_SOURCE_EDID) {
+ uint32_t i;
+
+ dal_gamut_space_reset_gamut(
+ &gamut->gamut_dst, true, true);
+
+ for (i = 0;
+ i < sizeof(gamut->color_charact.color_charact);
+ i++) {
+ gamut->color_charact.color_charact[i] =
+ disp_char->color_characteristics[i];
+ }
+ if (disp_char->gamma > 0)
+ gamut->color_charact.gamma =
+ (disp_char->gamma + 100)*10;
+ else
+ gamut->color_charact.gamma = 0;
+ }
+ }
+ if (gamut->source == GAMUT_SPACE_SOURCE_DEFAULT) {
+ requested_temperature = temperature->adj_data.ranged.def;
+ if (!dal_color_temperature_find_white_point(
+ requested_temperature,
+ &white_point))
+ return false;
+ dal_gamut_space_reset_gamut(
+ &gamut->gamut_src, false, true);
+ gamut->gamut_src.option.bits.CUSTOM_WHITE_POINT = 1;
+ gamut->gamut_src.white_point.custom.white_x =
+ white_point.white_x;
+ gamut->gamut_src.white_point.custom.white_y =
+ white_point.white_y;
+
+ if (!dal_adj_container_validate_gamut(
+ adj_container,
+ &gamut->gamut_src))
+ return false;
+
+ dal_adj_container_update_gamut(
+ adj_container,
+ ADJ_ID_GAMUT_SOURCE_GRPH,
+ &gamut->gamut_src);
+ {
+ struct adjustment_info *non_const_temp = temperature;
+
+ non_const_temp->adj_data.ranged.cur =
+ requested_temperature;
+ }
+ }
+ {
+ union update_color_flags flags = {0};
+
+ if (!dal_gamut_space_update_gamut(
+ gamut, false, &flags))
+ return false;
+ if (flags.bits.GAMUT_DST == 1)
+ dal_adj_container_update_gamut(
+ adj_container,
+ ADJ_ID_GAMUT_DESTINATION,
+ &gamut->gamut_dst);
+ if (reason_id != ADJ_ID_GAMUT_SOURCE_GRPH &&
+ reason_id != ADJ_ID_GAMUT_DESTINATION) {
+ if (gamut->source == GAMUT_SPACE_SOURCE_EDID)
+ dal_gamut_space_setup_default_gamut(
+ reason_id,
+ &gamut->gamut_src,
+ false,
+ true);
+ }
+ if (!dal_gamut_space_build_gamut_space_matrix(
+ gamut,
+ color_control->temperature_matrix,
+ regamma,
+ &flags))
+ return false;
+
+ if (flags.bits.REGAMMA > 0)
+ grph_colors_adj->regamma_updated = true;
+ if (flags.bits.GAMUT_SRC > 0)
+ grph_colors_adj->gamut_src_updated = true;
+ if (flags.bits.GAMUT_DST > 0)
+ grph_colors_adj->gamut_dst_updated = true;
+ }
+ if (dal_hw_sequencer_get_hw_color_adj_range(
+ grph_colors_adj->hws,
+ disp_path,
+ &hw_color_range) != HWSS_RESULT_OK)
+ return false;
+ color_control->color_space =
+ dal_ds_translation_hw_color_space_from_color_space(
+ dal_grph_colors_group_get_color_space(
+ grph_colors_adj,
+ timing,
+ disp_path,
+ adj_container));
+ if (color_control->color_space ==
+ HW_COLOR_SPACE_UNKNOWN)
+ return false;
+ {
+ struct hw_crtc_timing hw_timing;
+ enum signal_type asic_signal =
+ dal_display_path_get_query_signal(
+ disp_path, ASIC_LINK_INDEX);
+ dal_ds_translation_hw_crtc_timing_from_crtc_timing(
+ &hw_timing,
+ timing,
+ VIEW_3D_FORMAT_NONE,
+ asic_signal);
+
+ color_control->color_depth =
+ hw_timing.flags.COLOR_DEPTH;
+ color_control->brightness =
+ get_hw_value_from_sw_value(
+ &hw_color_range.brightness,
+ brightness);
+ color_control->contrast =
+ get_hw_value_from_sw_value(
+ &hw_color_range.contrast,
+ contrast);
+ color_control->hue =
+ get_hw_value_from_sw_value(
+ &hw_color_range.hue,
+ hue);
+ color_control->saturation =
+ get_hw_value_from_sw_value(
+ &hw_color_range.saturation,
+ saturation);
+ if (gamut->source == GAMUT_SPACE_SOURCE_USER_GAMUT &&
+ gamut_adj_avails == false &&
+ is_current_same_as_default(saturation) &&
+ is_current_same_as_default(contrast) &&
+ is_current_same_as_default(brightness) &&
+ is_current_same_as_default(hue) &&
+ is_current_same_as_default(temperature))
+ color_control->option = HWS_COLOR_MATRIX_HW_DEFAULT;
+ else
+ color_control->option = HWS_COLOR_MATRIX_SW;
+
+ }
+
+ return true;
+}
+
+bool dal_grph_colors_group_build_color_control_adj(
+ struct grph_colors_group *grph_colors_adj,
+ const struct path_mode *mode,
+ struct display_path *disp_path,
+ struct hw_adjustment_set *set)
+{
+ struct adj_container *adj_container;
+ struct gamut_parameter *gamut = NULL;
+ struct ds_regamma_lut *regamma = NULL;
+ struct hw_adjustment_color_control *color_control = NULL;
+ enum ds_color_space color_space;
+
+ if (!disp_path)
+ return false;
+ gamut = dal_alloc(sizeof(*gamut));
+ if (!gamut)
+ goto gamut_fail;
+ regamma = dal_alloc(sizeof(*regamma));
+ if (!regamma)
+ goto regamma_fail;
+ color_control = dal_alloc(sizeof(*color_control));
+ if (!color_control)
+ goto color_control_fail;
+
+ adj_container = dal_ds_dispatch_get_adj_container_for_path(
+ grph_colors_adj->ds,
+ mode->display_path_index);
+ if (!adj_container)
+ goto adj_container_fail;
+
+ color_control->color_space = HW_COLOR_SPACE_UNKNOWN;
+
+ if (!dal_grph_colors_group_compute_hw_adj_color_control(
+ grph_colors_adj,
+ adj_container,
+ &mode->mode_timing->crtc_timing,
+ disp_path,
+ ADJ_ID_INVALID,
+ gamut,
+ regamma,
+ color_control))
+ goto adj_container_fail;
+ color_control->surface_pixel_format = mode->pixel_format;
+ set->color_control = color_control;
+ color_space = dal_ds_translation_color_space_from_hw_color_space(
+ color_control->color_space);
+ dal_adj_container_update_color_space(
+ adj_container,
+ color_space);
+
+ dal_free(regamma);
+ dal_free(gamut);
+
+ return true;
+
+adj_container_fail:
+ dal_free(color_control);
+color_control_fail:
+ dal_free(regamma);
+regamma_fail:
+ dal_free(gamut);
+gamut_fail:
+ return false;
+}
+
+enum ds_color_space dal_grph_colors_group_build_default_color_space(
+ struct grph_colors_group *grph_colors_adj,
+ const struct crtc_timing *timing,
+ const struct display_path *disp_path,
+ enum ds_color_space hdmi_request_color_space)
+{
+ enum ds_color_space color_space =
+ DS_COLOR_SPACE_SRGB_FULLRANGE;
+
+ switch (dal_display_path_get_query_signal(
+ disp_path, SINK_LINK_INDEX)) {
+ case SIGNAL_TYPE_DISPLAY_PORT:
+ case SIGNAL_TYPE_DISPLAY_PORT_MST:
+ case SIGNAL_TYPE_EDP:
+ if (timing->pixel_encoding == PIXEL_ENCODING_YCBCR422 ||
+ timing->pixel_encoding == PIXEL_ENCODING_YCBCR444) {
+ color_space = (timing->pix_clk_khz > PIXEL_CLOCK) ?
+ DS_COLOR_SPACE_YCBCR709 :
+ DS_COLOR_SPACE_YCBCR601;
+ if (timing->flags.YONLY == 1)
+ color_space =
+ (timing->pix_clk_khz > PIXEL_CLOCK) ?
+ DS_COLOR_SPACE_YCBCR709_YONLY :
+ DS_COLOR_SPACE_YCBCR601_YONLY;
+ }
+ break;
+ case SIGNAL_TYPE_HDMI_TYPE_A:
+ {
+ uint32_t pix_clk_khz;
+
+ color_space = hdmi_request_color_space;
+ if (timing->pixel_encoding == PIXEL_ENCODING_YCBCR422 &&
+ timing->pixel_encoding == PIXEL_ENCODING_YCBCR444) {
+ if (timing->timing_standard ==
+ TIMING_STANDARD_CEA770 &&
+ timing->timing_standard ==
+ TIMING_STANDARD_CEA861)
+ color_space = DS_COLOR_SPACE_SRGB_FULLRANGE;
+ /* else {
+ union cea_video_capability_data_block
+ vcdb = {{0 }};
+ bool ret =
+ dal_edid_base_get_cea_video_capability_data_block(
+ disp_path->dcs->edid_mgr->edid_list,
+ &vcdb);
+ if ((ret == true) && (vcdb.bits.QS == 1))
+ color_space = DS_COLOR_SPACE_SRGB_FULLRANGE;
+ } */
+ pix_clk_khz = timing->pix_clk_khz / 10;
+ if (timing->h_addressable == 640 &&
+ timing->v_addressable == 480 &&
+ (pix_clk_khz == 2520 || pix_clk_khz == 2517))
+ color_space = DS_COLOR_SPACE_SRGB_FULLRANGE;
+ } else {
+ if (timing->timing_standard ==
+ TIMING_STANDARD_CEA770 ||
+ timing->timing_standard ==
+ TIMING_STANDARD_CEA861) {
+ /* struct cea_colorimetry_data_block
+ * data_block = {0};
+ if (dal_edid_base_get_cea_colorimetry_data_block(
+ disp_path->dcs->edid_mgr->edid_list,
+ &data_block)) {
+ if (data_block->flag.XV_YCC601 == 1 &&
+ data_block->flag.XV_YCC709 == 1)
+ color_space =
+ (timing->pix_clk_khz > PIXEL_CLOCK) ?
+ DS_COLOR_SPACE_YCBCR709 :
+ DS_COLOR_SPACE_YCBCR601;
+ else
+ color_space =
+ (data_block->flag.XV_YCC709 == 1) ?
+ DS_COLOR_SPACE_YCBCR709 :
+ DS_COLOR_SPACE_YCBCR601;
+ } else */
+ color_space =
+ (timing->pix_clk_khz > PIXEL_CLOCK) ?
+ DS_COLOR_SPACE_YCBCR709 :
+ DS_COLOR_SPACE_YCBCR601;
+ }
+ }
+ break;
+ }
+ default:
+ switch (timing->pixel_encoding) {
+ case PIXEL_ENCODING_YCBCR422:
+ case PIXEL_ENCODING_YCBCR444:
+ if (timing->pix_clk_khz > PIXEL_CLOCK)
+ color_space = DS_COLOR_SPACE_YCBCR709;
+ else
+ color_space = DS_COLOR_SPACE_YCBCR601;
+ break;
+ default:
+ break;
+ }
+ break;
+ }
+ return color_space;
+}
+enum ds_color_space dal_grph_colors_group_adjust_color_space(
+ struct grph_colors_group *grph_colors_adj,
+ enum ds_color_space color_space,
+ bool rgb_limited)
+{
+ if (rgb_limited && color_space == DS_COLOR_SPACE_SRGB_FULLRANGE)
+ color_space = DS_COLOR_SPACE_SRGB_LIMITEDRANGE;
+ return color_space;
+}
+
+bool dal_grph_colors_group_synch_color_temperature_with_gamut(
+ struct grph_colors_group *grph_colors_adj,
+ struct adj_container *adj_container)
+{
+ struct gamut_data gamut_data;
+ struct ds_white_point_coordinates data;
+ struct white_point_data white_data;
+ int32_t temperature;
+ bool extra_match;
+
+ dal_memset(&gamut_data, 0, sizeof(gamut_data));
+ dal_memset(&data, 0, sizeof(data));
+ dal_memset(&white_data, 0, sizeof(white_data));
+
+ dal_adj_container_get_gamut(
+ adj_container,
+ ADJ_ID_GAMUT_SOURCE_GRPH,
+ &gamut_data);
+ if (!dal_gamut_space_setup_white_point(
+ &gamut_data,
+ &data))
+ return false;
+
+ white_data.white_x = data.white_x;
+ white_data.white_y = data.white_y;
+
+ if (!dal_color_temperature_find_color_temperature(
+ &white_data,
+ &temperature,
+ &extra_match))
+ return false;
+
+ if (!dal_adj_info_set_update_cur_value(
+ &adj_container->adj_info_set,
+ ADJ_ID_TEMPERATURE,
+ temperature))
+ return false;
+
+ return true;
+}
+
+bool dal_grph_colors_group_synch_gamut_with_color_temperature(
+ struct grph_colors_group *grph_colors_adj,
+ struct adj_container *adj_container)
+{
+ struct gamut_data gamut_data;
+ struct white_point_data white_data;
+ struct adjustment_info *temperature =
+ dal_adj_info_set_get_adj_info(
+ &adj_container->adj_info_set,
+ ADJ_ID_TEMPERATURE);
+
+ dal_memset(&gamut_data, 0, sizeof(gamut_data));
+ dal_memset(&white_data, 0, sizeof(white_data));
+
+ if (!dal_color_temperature_find_white_point(
+ temperature->adj_data.ranged.cur,
+ &white_data))
+ return false;
+ dal_adj_container_get_gamut(
+ adj_container,
+ ADJ_ID_GAMUT_SOURCE_GRPH,
+ &gamut_data);
+ dal_gamut_space_reset_gamut(
+ &gamut_data,
+ false,
+ true);
+
+ gamut_data.option.bits.CUSTOM_WHITE_POINT = 1;
+ gamut_data.white_point.custom.white_x = white_data.white_x;
+ gamut_data.white_point.custom.white_y = white_data.white_y;
+
+ if (!dal_adj_container_validate_gamut(
+ adj_container,
+ &gamut_data))
+ return false;
+
+ dal_adj_container_update_gamut(
+ adj_container,
+ ADJ_ID_GAMUT_SOURCE_GRPH,
+ &gamut_data);
+ return true;
+
+}
+
+bool dal_grph_colors_group_get_color_temperature(
+ struct grph_colors_group *grph_colors_adj,
+ struct adj_container *adj_container,
+ int32_t *temp)
+{
+ struct gamut_data gamut_data;
+ struct ds_white_point_coordinates data;
+ struct white_point_data white_data;
+ bool exact_match;
+
+ dal_adj_container_get_gamut(
+ adj_container,
+ ADJ_ID_GAMUT_SOURCE_GRPH,
+ &gamut_data);
+ if (dal_gamut_space_setup_white_point(
+ &gamut_data,
+ &data)) {
+ white_data.white_x = data.white_x;
+ white_data.white_y = data.white_y;
+ return dal_color_temperature_find_color_temperature(
+ &white_data, temp, &exact_match);
+ }
+ return false;
+}
+
+enum ds_return dal_grph_colors_group_set_color_graphics_gamut(
+ struct grph_colors_group *grph_colors_adj,
+ struct display_path *disp_path,
+ struct gamut_data *gamut_data,
+ enum adjustment_id adj_id,
+ bool apply_to_hw)
+{
+ uint32_t display_index;
+ struct adj_container *adj_container = NULL;
+ const struct path_mode_set_with_data *pms_wd = NULL;
+ const struct path_mode *path_mode = NULL;
+ struct hw_adjustment_color_control *color_control = NULL;
+ struct gamut_parameter *gamut = NULL;
+ struct ds_regamma_lut *regamma = NULL;
+ struct ds_regamma_lut *old_regamma = NULL;
+
+ if (!disp_path)
+ return DS_ERROR;
+ display_index = dal_display_path_get_display_index(
+ disp_path);
+
+ adj_container = dal_ds_dispatch_get_adj_container_for_path(
+ grph_colors_adj->ds, display_index);
+ if (!adj_container)
+ return DS_ERROR;
+
+ pms_wd = dal_ds_dispatch_get_active_pms_with_data(
+ grph_colors_adj->ds);
+ if (!pms_wd)
+ return DS_ERROR;
+
+ path_mode = dal_pms_with_data_get_path_mode_for_display_index(
+ pms_wd, display_index);
+ if (!path_mode)
+ return DS_ERROR;
+
+ if (!dal_hw_sequencer_is_support_custom_gamut_adj(
+ grph_colors_adj->hws,
+ disp_path,
+ HW_GRAPHIC_SURFACE))
+ return DS_ERROR;
+
+ if (!dal_adj_container_validate_gamut(
+ adj_container,
+ gamut_data))
+ return DS_ERROR;
+
+ dal_adj_container_update_gamut(
+ adj_container,
+ adj_id, gamut_data);
+
+ if (apply_to_hw) {
+ enum hwss_result result;
+ enum ds_color_space color_space;
+
+ color_control = dal_alloc(sizeof(*color_control));
+ if (!color_control)
+ return DS_ERROR;
+ gamut = dal_alloc(sizeof(*gamut));
+ if (!gamut)
+ goto gamut_fail;
+ regamma = dal_alloc(sizeof(*regamma));
+ if (!regamma)
+ goto regamma_fail;
+ old_regamma = dal_alloc(sizeof(*old_regamma));
+ if (!old_regamma)
+ goto old_regamma_fail;
+
+ if (!dal_grph_colors_group_compute_hw_adj_color_control(
+ grph_colors_adj,
+ adj_container,
+ &path_mode->mode_timing->crtc_timing,
+ disp_path,
+ adj_id,
+ gamut,
+ regamma,
+ color_control))
+ goto adj_color_control_fail;
+
+ color_control->surface_pixel_format =
+ path_mode->pixel_format;
+
+ result = dal_hw_sequencer_set_color_control_adjustment(
+ grph_colors_adj->hws,
+ dal_display_path_get_controller(disp_path),
+ color_control);
+
+ if (result == HWSS_RESULT_OK) {
+ if (grph_colors_adj->regamma_updated) {
+ enum ds_return ret;
+
+ if (!dal_adj_container_get_regamma_copy(
+ adj_container,
+ old_regamma))
+ goto adj_color_control_fail;
+
+ dal_adj_container_set_regamma(
+ adj_container,
+ regamma);
+ ret = dal_ds_dispatch_set_gamma_adjustment(
+ grph_colors_adj->ds,
+ display_index,
+ ADJ_ID_GAMMA_RAMP,
+ dal_ds_dispatch_get_current_gamma(
+ grph_colors_adj->ds,
+ display_index,
+ ADJ_ID_GAMMA_RAMP));
+ if (ret != DS_SUCCESS)
+ dal_adj_container_set_regamma(
+ adj_container,
+ regamma);
+ }
+ }
+ color_space =
+ dal_ds_translation_color_space_from_hw_color_space(
+ color_control->color_space);
+ dal_ds_dispatch_update_adj_container_for_path_with_color_space(
+ grph_colors_adj->ds,
+ display_index,
+ color_space);
+ }
+ dal_grph_colors_group_synch_color_temperature_with_gamut(
+ grph_colors_adj,
+ adj_container);
+ return DS_SUCCESS;
+
+adj_color_control_fail:
+ dal_free(old_regamma);
+old_regamma_fail:
+ dal_free(regamma);
+regamma_fail:
+ dal_free(gamut);
+gamut_fail:
+ dal_free(color_control);
+
+ return DS_ERROR;
+}
+
+enum ds_return dal_grph_colors_group_get_color_gamut(
+ struct grph_colors_group *grph_colors_adj,
+ struct display_path *disp_path,
+ const struct ds_gamut_reference_data *ref,
+ struct ds_get_gamut_data *data)
+{
+ enum ds_return ret;
+ uint32_t display_index;
+ struct adj_container *adj_container = NULL;
+ struct adjustment_info *temperature_src = NULL;
+ const struct display_characteristics *disp_char = NULL;
+ struct color_characteristic color_charact = {{0 } };
+ struct gamut_data gamut_data;
+ enum adjustment_id adj_id;
+ struct fixed31_32 result;
+
+ if (!disp_path)
+ return DS_ERROR;
+ display_index = dal_display_path_get_display_index(
+ disp_path);
+
+ adj_container = dal_ds_dispatch_get_adj_container_for_path(
+ grph_colors_adj->ds, display_index);
+ if (!adj_container)
+ return DS_ERROR;
+
+ if (!dal_hw_sequencer_is_support_custom_gamut_adj(
+ grph_colors_adj->hws,
+ disp_path,
+ HW_GRAPHIC_SURFACE))
+ return DS_ERROR;
+
+ dal_memset(&gamut_data, 0, sizeof(gamut_data));
+ if (!dal_ds_translate_gamut_reference(
+ ref, &adj_id))
+ return DS_ERROR;
+
+ if (adj_id == ADJ_ID_GAMUT_DESTINATION) {
+ temperature_src = dal_adj_info_set_get_adj_info(
+ &adj_container->adj_info_set,
+ ADJ_ID_TEMPERATURE_SOURCE);
+ if (temperature_src != NULL &&
+ temperature_src->adj_data.ranged.cur ==
+ COLOR_TEMPERATURE_SOURCE_EDID) {
+
+ disp_char = dal_adj_container_get_disp_character(
+ adj_container);
+ if (!disp_char)
+ return DS_ERROR;
+ if (!dal_gamut_space_convert_edid_format_color_charact(
+ disp_char->color_characteristics,
+ &color_charact))
+ return DS_ERROR;
+ gamut_data.option.bits.CUSTOM_GAMUT_SPACE = 1;
+ gamut_data.option.bits.CUSTOM_WHITE_POINT = 1;
+
+ result = dal_fixed31_32_mul(
+ dal_fixed31_32_from_int(
+ (int64_t)GAMUT_DIVIDER),
+ color_charact.red_x);
+ gamut_data.gamut.custom.red_x =
+ dal_fixed31_32_floor(result);
+
+ result = dal_fixed31_32_mul(
+ dal_fixed31_32_from_int(
+ (int64_t)GAMUT_DIVIDER),
+ color_charact.red_y);
+ gamut_data.gamut.custom.red_y =
+ dal_fixed31_32_floor(result);
+
+ result = dal_fixed31_32_mul(
+ dal_fixed31_32_from_int(
+ (int64_t)GAMUT_DIVIDER),
+ color_charact.blue_x);
+ gamut_data.gamut.custom.blue_x =
+ dal_fixed31_32_floor(result);
+
+ result = dal_fixed31_32_mul(
+ dal_fixed31_32_from_int(
+ (int64_t)GAMUT_DIVIDER),
+ color_charact.blue_y);
+ gamut_data.gamut.custom.blue_y =
+ dal_fixed31_32_floor(result);
+
+ result = dal_fixed31_32_mul(
+ dal_fixed31_32_from_int(
+ (int64_t)GAMUT_DIVIDER),
+ color_charact.green_x);
+ gamut_data.gamut.custom.green_x =
+ dal_fixed31_32_floor(result);
+
+ result = dal_fixed31_32_mul(
+ dal_fixed31_32_from_int(
+ (int64_t)GAMUT_DIVIDER),
+ color_charact.green_y);
+ gamut_data.gamut.custom.green_y =
+ dal_fixed31_32_floor(result);
+
+ result = dal_fixed31_32_mul(
+ dal_fixed31_32_from_int(
+ (int64_t)GAMUT_DIVIDER),
+ color_charact.white_x);
+ gamut_data.white_point.custom.white_x =
+ dal_fixed31_32_floor(result);
+
+ result = dal_fixed31_32_mul(
+ dal_fixed31_32_from_int(
+ (int64_t)GAMUT_DIVIDER),
+ color_charact.white_y);
+ gamut_data.white_point.custom.white_y =
+ dal_fixed31_32_floor(result);
+
+ ret = DS_SUCCESS;
+ }
+ }
+ if (ret != DS_SUCCESS)
+ if (!dal_adj_container_get_gamut(
+ adj_container,
+ adj_id,
+ &gamut_data))
+ return DS_ERROR;
+ if (!dal_ds_translate_internal_gamut_to_external_parameter(
+ &gamut_data,
+ &data->gamut))
+ return DS_ERROR;
+ return ret;
+}
+
+enum ds_return dal_grph_colors_group_get_color_gamut_info(
+ struct grph_colors_group *grph_colors_adj,
+ struct display_path *disp_path,
+ const struct ds_gamut_reference_data *ref,
+ struct ds_gamut_info *data)
+{
+ if (!disp_path)
+ return DS_ERROR;
+
+ if (!dal_hw_sequencer_is_support_custom_gamut_adj(
+ grph_colors_adj->hws,
+ disp_path,
+ HW_GRAPHIC_SURFACE))
+ return DS_ERROR;
+
+ if (!dal_gamut_space_get_supported_gamuts(data))
+ return DS_ERROR;
+
+ return DS_SUCCESS;
+}
+
+enum ds_return dal_grph_colors_group_get_regamma_lut(
+ struct grph_colors_group *grph_colors_adj,
+ struct display_path *disp_path,
+ struct ds_regamma_lut *data)
+{
+ uint32_t display_index;
+ struct adj_container *adj_container = NULL;
+ const struct ds_regamma_lut *regamma = NULL;
+
+ if (!disp_path)
+ return DS_ERROR;
+ display_index = dal_display_path_get_display_index(
+ disp_path);
+ adj_container = dal_ds_dispatch_get_adj_container_for_path(
+ grph_colors_adj->ds, display_index);
+ if (!adj_container)
+ return DS_ERROR;
+
+ if (!dal_hw_sequencer_is_support_custom_gamma_coefficients(
+ grph_colors_adj->hws,
+ disp_path,
+ HW_GRAPHIC_SURFACE))
+ return DS_ERROR;
+
+ regamma = dal_adj_container_get_regamma(adj_container);
+ if (!regamma)
+ return DS_ERROR;
+
+ dal_ds_translate_regamma_to_external(regamma, data);
+ return DS_SUCCESS;
+}
+
+enum ds_return dal_grph_colors_group_set_regamma_lut(
+ struct grph_colors_group *grph_colors_adj,
+ struct display_path *disp_path,
+ const struct ds_regamma_lut *data)
+{
+ uint32_t display_index;
+ enum ds_return ret;
+ struct adj_container *adj_container = NULL;
+ struct ds_regamma_lut *regamma = NULL;
+ struct ds_regamma_lut *old_regamma = NULL;
+ const struct raw_gamma_ramp *ramp = NULL;
+ struct gamut_data original_gamut = {{0 } };
+ struct gamut_data updated_gamut = {{0 } };
+ bool updated_gamut_dst = false;
+
+ if (!disp_path)
+ return DS_ERROR;
+ display_index = dal_display_path_get_display_index(
+ disp_path);
+ adj_container = dal_ds_dispatch_get_adj_container_for_path(
+ grph_colors_adj->ds, display_index);
+ if (!adj_container)
+ return DS_ERROR;
+
+ if (data->flags.bits.GAMMA_FROM_EDID_EX == 1 ||
+ data->flags.bits.COEFF_FROM_EDID == 1)
+ return DS_ERROR;
+
+ if (!dal_hw_sequencer_is_support_custom_gamma_coefficients(
+ grph_colors_adj->hws,
+ disp_path,
+ HW_GRAPHIC_SURFACE))
+ return DS_ERROR;
+
+ regamma = dal_alloc(sizeof(*regamma));
+ if (!regamma)
+ goto regamma_fail;
+
+ old_regamma = dal_alloc(sizeof(*old_regamma));
+ if (!old_regamma)
+ goto old_regamma_fail;
+
+ ramp = dal_ds_dispatch_get_current_gamma(
+ grph_colors_adj->ds,
+ display_index,
+ ADJ_ID_GAMMA_RAMP);
+ if (!dal_adj_container_get_regamma_copy(
+ adj_container,
+ old_regamma))
+ goto regamma_copy_fail;
+
+ dal_memmove(regamma, old_regamma, sizeof(*regamma));
+
+ if (!dal_ds_translate_regamma_to_internal(
+ data, regamma))
+ goto regamma_copy_fail;
+
+ if (!dal_adj_container_get_gamut(
+ adj_container,
+ ADJ_ID_GAMUT_DESTINATION,
+ &original_gamut))
+ goto regamma_copy_fail;
+
+ if (!dal_adj_container_set_regamma(
+ adj_container,
+ regamma))
+ goto regamma_copy_fail;
+
+ updated_gamut_dst = dal_grph_colors_group_update_gamut(
+ grph_colors_adj,
+ disp_path,
+ adj_container);
+
+ ret = dal_ds_dispatch_set_gamma_adjustment(
+ grph_colors_adj->ds,
+ display_index,
+ ADJ_ID_GAMMA_RAMP_REGAMMA_UPDATE,
+ ramp);
+
+ if (ret != DS_SUCCESS) {
+ if (updated_gamut_dst)
+ dal_adj_container_update_gamut(
+ adj_container,
+ ADJ_ID_GAMUT_DESTINATION,
+ &original_gamut);
+ if (!dal_adj_container_set_regamma(
+ adj_container,
+ old_regamma))
+ goto regamma_copy_fail;
+ } else {
+ if (!dal_adj_container_get_gamut(
+ adj_container,
+ ADJ_ID_GAMUT_DESTINATION,
+ &updated_gamut))
+ goto regamma_copy_fail;
+
+ return ret;
+ }
+
+regamma_copy_fail:
+ dal_free(old_regamma);
+old_regamma_fail:
+ dal_free(regamma);
+regamma_fail:
+ return DS_ERROR;
+}
+
+enum ds_return dal_grph_colors_group_update_gamut(
+ struct grph_colors_group *grph_colors_adj,
+ struct display_path *disp_path,
+ struct adj_container *adj_container)
+{
+ struct gamut_parameter *gamut = NULL;
+ enum signal_type signal;
+ const struct adjustment_info *temperature = NULL;
+ const struct adjustment_info *temperature_src = NULL;
+ const struct ds_regamma_lut *const_regamma = NULL;
+
+ if (!disp_path)
+ return false;
+
+ signal = dal_display_path_get_query_signal(
+ disp_path, SINK_LINK_INDEX);
+ if (signal == SIGNAL_TYPE_HDMI_TYPE_A)
+ return false;
+
+ gamut = dal_alloc(sizeof(*gamut));
+ if (!gamut)
+ return false;
+
+ temperature = dal_adj_info_set_get_adj_info(
+ &adj_container->adj_info_set,
+ ADJ_ID_TEMPERATURE);
+ temperature_src = dal_adj_info_set_get_adj_info(
+ &adj_container->adj_info_set,
+ ADJ_ID_TEMPERATURE_SOURCE);
+ if (temperature == NULL ||
+ temperature->adj_data.ranged.cur == -1)
+ goto gamut_fail;
+
+ gamut->source = ((temperature_src != NULL) &&
+ (temperature_src->adj_data.ranged.cur ==
+ COLOR_TEMPERATURE_SOURCE_EDID)) ?
+ GAMUT_SPACE_SOURCE_EDID :
+ GAMUT_SPACE_SOURCE_USER_GAMUT;
+ if (gamut->source != GAMUT_SPACE_SOURCE_USER_GAMUT)
+ goto gamut_fail;
+
+ if (!dal_adj_container_get_gamut(
+ adj_container,
+ ADJ_ID_GAMUT_SOURCE_GRPH,
+ &gamut->gamut_src))
+ goto gamut_fail;
+
+ if (!dal_adj_container_get_gamut(
+ adj_container,
+ ADJ_ID_GAMUT_DESTINATION,
+ &gamut->gamut_dst))
+ goto gamut_fail;
+
+ const_regamma = dal_adj_container_get_regamma(
+ adj_container);
+ if (!const_regamma)
+ goto gamut_fail;
+ dal_memmove(&gamut->regamma, const_regamma, sizeof(gamut->regamma));
+ {
+ union update_color_flags flags = {0};
+
+ if (!dal_gamut_space_update_gamut(
+ gamut, false, &flags))
+ goto gamut_fail;
+ if (flags.bits.GAMUT_DST == 1)
+ return dal_adj_container_update_gamut(
+ adj_container,
+ ADJ_ID_GAMUT_DESTINATION,
+ &gamut->gamut_dst);
+ }
+
+gamut_fail:
+ dal_free(gamut);
+ return false;
+}
+
+static bool grph_colors_group_construct(
+ struct grph_colors_group *grph_colors_adj,
+ struct grph_colors_group_init_data *init_data)
+{
+ if (!init_data)
+ return false;
+
+ grph_colors_adj->ds = init_data->ds;
+ grph_colors_adj->hws = init_data->hws;
+ grph_colors_adj->dal_context = init_data->dal_context;
+
+ return true;
+}
+
+struct grph_colors_group *dal_grph_colors_group_create(
+ struct grph_colors_group_init_data *init_data)
+{
+ struct grph_colors_group *grph_colors_adj = NULL;
+
+ grph_colors_adj = dal_alloc(sizeof(*grph_colors_adj));
+
+ if (!grph_colors_adj)
+ return NULL;
+
+ if (grph_colors_group_construct(grph_colors_adj, init_data))
+ return grph_colors_adj;
+
+ dal_free(grph_colors_adj);
+
+ return NULL;
+}
+
+static void destruct(
+ struct grph_colors_group *grph_colors_adj)
+{
+
+}
+
+void dal_grph_colors_adj_group_destroy(
+ struct grph_colors_group **grph_colors_adj)
+{
+ if (grph_colors_adj == NULL || *grph_colors_adj == NULL)
+ return;
+ destruct(*grph_colors_adj);
+ dal_free(*grph_colors_adj);
+ *grph_colors_adj = NULL;
+}