diff options
Diffstat (limited to 'common/recipes-kernel/linux/linux-yocto-4.14.71/0085-drm-amd-display-Framework-for-degamma-and-regramma-t.patch')
-rw-r--r-- | common/recipes-kernel/linux/linux-yocto-4.14.71/0085-drm-amd-display-Framework-for-degamma-and-regramma-t.patch | 969 |
1 files changed, 969 insertions, 0 deletions
diff --git a/common/recipes-kernel/linux/linux-yocto-4.14.71/0085-drm-amd-display-Framework-for-degamma-and-regramma-t.patch b/common/recipes-kernel/linux/linux-yocto-4.14.71/0085-drm-amd-display-Framework-for-degamma-and-regramma-t.patch new file mode 100644 index 00000000..2be1da14 --- /dev/null +++ b/common/recipes-kernel/linux/linux-yocto-4.14.71/0085-drm-amd-display-Framework-for-degamma-and-regramma-t.patch @@ -0,0 +1,969 @@ +From d8f0471b0f0f688abdd8213b842f9a83d3caba37 Mon Sep 17 00:00:00 2001 +From: Amy Zhang <Amy.Zhang@amd.com> +Date: Mon, 12 Dec 2016 16:57:40 -0500 +Subject: [PATCH 0085/4131] drm/amd/display: Framework for degamma and regramma + through color module + +Signed-off-by: Amy Zhang <Amy.Zhang@amd.com> +Reviewed-by: Aric Cyr <Aric.Cyr@amd.com> +Acked-by: Harry Wentland <Harry.Wentland@amd.com> +Signed-off-by: Alex Deucher <alexander.deucher@amd.com> +--- + drivers/gpu/drm/amd/display/modules/color/color.c | 575 +++++++++++++++++---- + .../drm/amd/display/modules/color/color_helper.h | 2 +- + .../gpu/drm/amd/display/modules/inc/mod_color.h | 115 ++++- + 3 files changed, 598 insertions(+), 94 deletions(-) + +diff --git a/drivers/gpu/drm/amd/display/modules/color/color.c b/drivers/gpu/drm/amd/display/modules/color/color.c +index 6613ff9..9388672 100644 +--- a/drivers/gpu/drm/amd/display/modules/color/color.c ++++ b/drivers/gpu/drm/amd/display/modules/color/color.c +@@ -63,14 +63,18 @@ struct gamut_src_dst_matrix { + struct color_state { + bool user_enable_color_temperature; + int custom_color_temperature; +- struct color_space_coordinates source_gamut; +- struct color_space_coordinates destination_gamut; + struct color_range contrast; + struct color_range saturation; + struct color_range brightness; + struct color_range hue; + struct dc_gamma *gamma; + enum dc_quantization_range preferred_quantization_range; ++ ++ struct color_gamut_data source_gamut; ++ struct color_gamut_data destination_gamut; ++ enum color_transfer_func input_transfer_function; ++ enum color_transfer_func output_transfer_function; ++ struct color_mastering_info mastering_info; + }; + + struct core_color { +@@ -79,6 +83,7 @@ struct core_color { + int num_sinks; + struct sink_caps *caps; + struct color_state *state; ++ struct color_edid_caps *edid_caps; + }; + + #define MOD_COLOR_TO_CORE(mod_color)\ +@@ -1286,6 +1291,142 @@ static struct dc_surface *dc_stream_to_surface_from_pipe_ctx( + return out_surface; + } + ++static enum predefined_gamut_type color_space_to_predefined_gamut_types(enum ++ color_color_space color_space) ++{ ++ switch (color_space) { ++ case color_space_bt709: ++ case color_space_xv_ycc_bt709: ++ return gamut_type_bt709; ++ case color_space_bt601: ++ case color_space_xv_ycc_bt601: ++ return gamut_type_bt601; ++ case color_space_adobe: ++ return gamut_type_adobe_rgb; ++ case color_space_srgb: ++ case color_space_sc_rgb_ms_ref: ++ return gamut_type_srgb; ++ case color_space_bt2020: ++ return gamut_type_bt2020; ++ case color_space_dci_p3: /* TODO */ ++ default: ++ return gamut_type_unknown; ++ } ++} ++ ++static enum predefined_white_point_type white_point_to_predefined_white_point ++ (enum color_white_point_type white_point) ++{ ++ switch (white_point) { ++ case color_white_point_type_5000k_horizon: ++ return white_point_type_5000k_horizon; ++ case color_white_point_type_6500k_noon: ++ return white_point_type_6500k_noon; ++ case color_white_point_type_7500k_north_sky: ++ return white_point_type_7500k_north_sky; ++ case color_white_point_type_9300k: ++ return white_point_type_9300k; ++ default: ++ return white_point_type_unknown; ++ } ++} ++ ++static bool update_color_gamut_data(struct color_gamut_data *input_data, ++ struct color_gamut_data *output_data) ++{ ++ bool output_custom_cs = false; ++ bool output_custom_wp = false; ++ ++ if (input_data == NULL || output_data == NULL) ++ return false; ++ ++ if (input_data->color_space == color_space_custom_coordinates) { ++ output_data->color_space = input_data->color_space; ++ output_data->gamut.redX = input_data->gamut.redX; ++ output_data->gamut.redY = input_data->gamut.redY; ++ output_data->gamut.greenX = input_data->gamut.greenX; ++ output_data->gamut.greenY = input_data->gamut.greenY; ++ output_data->gamut.blueX = input_data->gamut.blueX; ++ output_data->gamut.blueY = input_data->gamut.blueY; ++ } else { ++ struct gamut_space_coordinates gamut_coord; ++ enum predefined_gamut_type gamut_type = ++ color_space_to_predefined_gamut_types ++ (input_data->color_space); ++ ++ /* fall back to original color space if unknown */ ++ if (gamut_type == gamut_type_unknown) { ++ if (output_data->color_space == ++ color_space_custom_coordinates) { ++ output_custom_cs = true; ++ } else { ++ gamut_type = ++ color_space_to_predefined_gamut_types ++ (output_data->color_space); ++ /* fall back to sRGB if both unknown*/ ++ if (gamut_type == gamut_type_unknown) { ++ output_data->color_space = ++ color_space_srgb; ++ gamut_type = gamut_type_srgb; ++ } ++ } ++ } else { ++ output_data->color_space = input_data->color_space; ++ } ++ ++ if (!output_custom_cs) { ++ mod_color_find_predefined_gamut(&gamut_coord, ++ gamut_type); ++ output_data->gamut.redX = gamut_coord.redX; ++ output_data->gamut.redY = gamut_coord.redY; ++ output_data->gamut.greenX = gamut_coord.greenX; ++ output_data->gamut.greenY = gamut_coord.greenY; ++ output_data->gamut.blueX = gamut_coord.blueX; ++ output_data->gamut.blueY = gamut_coord.blueY; ++ } ++ } ++ ++ if (input_data->white_point == color_space_custom_coordinates) { ++ output_data->white_point = input_data->white_point; ++ output_data->gamut.whiteX = input_data->gamut.whiteX; ++ output_data->gamut.whiteY = input_data->gamut.whiteY; ++ } else { ++ struct white_point_coodinates white_point_coord; ++ enum predefined_white_point_type white_type = ++ white_point_to_predefined_white_point ++ (input_data->white_point); ++ ++ /* fall back to original white point if not found */ ++ if (white_type == white_point_type_unknown) { ++ if (output_data->white_point == ++ color_white_point_type_custom_coordinates) { ++ output_custom_wp = true; ++ } else { ++ white_type = ++ white_point_to_predefined_white_point ++ (output_data->white_point); ++ /* fall back to 6500 if both unknown*/ ++ if (white_type == white_point_type_unknown) { ++ output_data->white_point = ++ color_white_point_type_6500k_noon; ++ white_type = ++ white_point_type_6500k_noon; ++ } ++ } ++ } else { ++ output_data->white_point = input_data->white_point; ++ } ++ ++ if (!output_custom_wp) { ++ mod_color_find_predefined_white_point( ++ &white_point_coord, white_type); ++ output_data->gamut.whiteX = white_point_coord.whiteX; ++ output_data->gamut.whiteY = white_point_coord.whiteY; ++ } ++ } ++ return true; ++} ++ + struct mod_color *mod_color_create(struct dc *dc) + { + int i = 0; +@@ -1311,23 +1452,36 @@ struct mod_color *mod_color_create(struct dc *dc) + + /*hardcoded to sRGB with 6500 color temperature*/ + for (i = 0; i < MOD_COLOR_MAX_CONCURRENT_SINKS; i++) { +- core_color->state[i].source_gamut.blueX = 1500; +- core_color->state[i].source_gamut.blueY = 600; +- core_color->state[i].source_gamut.greenX = 3000; +- core_color->state[i].source_gamut.greenY = 6000; +- core_color->state[i].source_gamut.redX = 6400; +- core_color->state[i].source_gamut.redY = 3300; +- core_color->state[i].source_gamut.whiteX = 3127; +- core_color->state[i].source_gamut.whiteY = 3290; +- +- core_color->state[i].destination_gamut.blueX = 1500; +- core_color->state[i].destination_gamut.blueY = 600; +- core_color->state[i].destination_gamut.greenX = 3000; +- core_color->state[i].destination_gamut.greenY = 6000; +- core_color->state[i].destination_gamut.redX = 6400; +- core_color->state[i].destination_gamut.redY = 3300; +- core_color->state[i].destination_gamut.whiteX = 3127; +- core_color->state[i].destination_gamut.whiteY = 3290; ++ core_color->state[i].source_gamut.color_space = ++ color_space_srgb; ++ core_color->state[i].source_gamut.white_point = ++ color_white_point_type_6500k_noon; ++ core_color->state[i].source_gamut.gamut.blueX = 1500; ++ core_color->state[i].source_gamut.gamut.blueY = 600; ++ core_color->state[i].source_gamut.gamut.greenX = 3000; ++ core_color->state[i].source_gamut.gamut.greenY = 6000; ++ core_color->state[i].source_gamut.gamut.redX = 6400; ++ core_color->state[i].source_gamut.gamut.redY = 3300; ++ core_color->state[i].source_gamut.gamut.whiteX = 3127; ++ core_color->state[i].source_gamut.gamut.whiteY = 3290; ++ ++ core_color->state[i].destination_gamut.color_space = ++ color_space_srgb; ++ core_color->state[i].destination_gamut.white_point = ++ color_white_point_type_6500k_noon; ++ core_color->state[i].destination_gamut.gamut.blueX = 1500; ++ core_color->state[i].destination_gamut.gamut.blueY = 600; ++ core_color->state[i].destination_gamut.gamut.greenX = 3000; ++ core_color->state[i].destination_gamut.gamut.greenY = 6000; ++ core_color->state[i].destination_gamut.gamut.redX = 6400; ++ core_color->state[i].destination_gamut.gamut.redY = 3300; ++ core_color->state[i].destination_gamut.gamut.whiteX = 3127; ++ core_color->state[i].destination_gamut.gamut.whiteY = 3290; ++ ++ core_color->state[i].input_transfer_function = ++ transfer_func_srgb; ++ core_color->state[i].output_transfer_function = ++ transfer_func_srgb; + + core_color->state[i].custom_color_temperature = 6500; + +@@ -1351,6 +1505,12 @@ struct mod_color *mod_color_create(struct dc *dc) + if (core_color->state == NULL) + goto fail_alloc_state; + ++ core_color->edid_caps = dm_alloc(sizeof(struct color_edid_caps) * ++ MOD_COLOR_MAX_CONCURRENT_SINKS); ++ ++ if (core_color->edid_caps == NULL) ++ goto fail_alloc_edid_caps; ++ + core_color->num_sinks = 0; + + if (dc == NULL) +@@ -1371,6 +1531,9 @@ struct mod_color *mod_color_create(struct dc *dc) + return &core_color->public; + + fail_construct: ++ dm_free(core_color->edid_caps); ++ ++fail_alloc_edid_caps: + dm_free(core_color->state); + + fail_alloc_state: +@@ -1390,6 +1553,8 @@ void mod_color_destroy(struct mod_color *mod_color) + struct core_color *core_color = + MOD_COLOR_TO_CORE(mod_color); + ++ dm_free(core_color->edid_caps); ++ + for (i = 0; i < core_color->num_sinks; i++) + if (core_color->state[i].gamma) + dc_gamma_release(core_color->state[i].gamma); +@@ -1405,7 +1570,8 @@ void mod_color_destroy(struct mod_color *mod_color) + } + } + +-bool mod_color_add_sink(struct mod_color *mod_color, const struct dc_sink *sink) ++bool mod_color_add_sink(struct mod_color *mod_color, const struct dc_sink *sink, ++ struct color_edid_caps *edid_caps) + { + struct core_color *core_color = MOD_COLOR_TO_CORE(mod_color); + struct core_dc *core_dc = DC_TO_CORE(core_color->dc); +@@ -1426,6 +1592,11 @@ bool mod_color_add_sink(struct mod_color *mod_color, const struct dc_sink *sink) + core_color->state[core_color->num_sinks]. + user_enable_color_temperature = true; + ++ core_color->edid_caps[core_color->num_sinks].colorimetry_caps = ++ edid_caps->colorimetry_caps; ++ core_color->edid_caps[core_color->num_sinks].hdr_caps = ++ edid_caps->hdr_caps; ++ + /* get persistent data from registry */ + flag.save_per_edid = true; + flag.save_per_link = false; +@@ -1462,25 +1633,25 @@ bool mod_color_add_sink(struct mod_color *mod_color, const struct dc_sink *sink) + sizeof(struct color_space_coordinates), + &flag)) { + memcpy(&core_color->state[core_color->num_sinks]. +- source_gamut, &persistent_source_gamut, ++ source_gamut.gamut, &persistent_source_gamut, + sizeof(struct color_space_coordinates)); + } else { + core_color->state[core_color->num_sinks]. +- source_gamut.blueX = 1500; ++ source_gamut.gamut.blueX = 1500; + core_color->state[core_color->num_sinks]. +- source_gamut.blueY = 600; ++ source_gamut.gamut.blueY = 600; + core_color->state[core_color->num_sinks]. +- source_gamut.greenX = 3000; ++ source_gamut.gamut.greenX = 3000; + core_color->state[core_color->num_sinks]. +- source_gamut.greenY = 6000; ++ source_gamut.gamut.greenY = 6000; + core_color->state[core_color->num_sinks]. +- source_gamut.redX = 6400; ++ source_gamut.gamut.redX = 6400; + core_color->state[core_color->num_sinks]. +- source_gamut.redY = 3300; ++ source_gamut.gamut.redY = 3300; + core_color->state[core_color->num_sinks]. +- source_gamut.whiteX = 3127; ++ source_gamut.gamut.whiteX = 3127; + core_color->state[core_color->num_sinks]. +- source_gamut.whiteY = 3290; ++ source_gamut.gamut.whiteY = 3290; + } + + if (dm_read_persistent_data(core_dc->ctx, sink, COLOR_REGISTRY_NAME, +@@ -1489,26 +1660,26 @@ bool mod_color_add_sink(struct mod_color *mod_color, const struct dc_sink *sink) + sizeof(struct color_space_coordinates), + &flag)) { + memcpy(&core_color->state[core_color->num_sinks]. +- destination_gamut, ++ destination_gamut.gamut, + &persistent_destination_gamut, + sizeof(struct color_space_coordinates)); + } else { + core_color->state[core_color->num_sinks]. +- destination_gamut.blueX = 1500; ++ destination_gamut.gamut.blueX = 1500; + core_color->state[core_color->num_sinks]. +- destination_gamut.blueY = 600; ++ destination_gamut.gamut.blueY = 600; + core_color->state[core_color->num_sinks]. +- destination_gamut.greenX = 3000; ++ destination_gamut.gamut.greenX = 3000; + core_color->state[core_color->num_sinks]. +- destination_gamut.greenY = 6000; ++ destination_gamut.gamut.greenY = 6000; + core_color->state[core_color->num_sinks]. +- destination_gamut.redX = 6400; ++ destination_gamut.gamut.redX = 6400; + core_color->state[core_color->num_sinks]. +- destination_gamut.redY = 3300; ++ destination_gamut.gamut.redY = 3300; + core_color->state[core_color->num_sinks]. +- destination_gamut.whiteX = 3127; ++ destination_gamut.gamut.whiteX = 3127; + core_color->state[core_color->num_sinks]. +- destination_gamut.whiteY = 3290; ++ destination_gamut.gamut.whiteY = 3290; + } + + if (dm_read_persistent_data(core_dc->ctx, sink, COLOR_REGISTRY_NAME, +@@ -1588,6 +1759,10 @@ bool mod_color_remove_sink(struct mod_color *mod_color, + memcpy(&core_color->state[j], + &core_color->state[j + 1], + sizeof(struct color_state)); ++ ++ memcpy(&core_color->edid_caps[j], ++ &core_color->edid_caps[j + 1], ++ sizeof(struct color_edid_caps)); + } + + core_color->num_sinks--; +@@ -1625,7 +1800,7 @@ bool mod_color_update_gamut_to_stream(struct mod_color *mod_color, + COLOR_REGISTRY_NAME, + "sourcegamut", + &core_color->state[sink_index]. +- source_gamut, ++ source_gamut.gamut, + sizeof(struct color_space_coordinates), + &flag); + +@@ -1634,19 +1809,19 @@ bool mod_color_update_gamut_to_stream(struct mod_color *mod_color, + COLOR_REGISTRY_NAME, + "destgamut", + &core_color->state[sink_index]. +- destination_gamut, ++ destination_gamut.gamut, + sizeof(struct color_space_coordinates), + &flag); + + if (!build_gamut_remap_matrix +- (core_color->state[sink_index].source_gamut, +- matrix->rgbCoeffSrc, +- matrix->whiteCoeffSrc)) ++ (core_color->state[sink_index].source_gamut.gamut, ++ matrix->rgbCoeffSrc, ++ matrix->whiteCoeffSrc)) + goto function_fail; + + if (!build_gamut_remap_matrix + (core_color->state[sink_index]. +- destination_gamut, ++ destination_gamut.gamut, + matrix->rgbCoeffDst, matrix->whiteCoeffDst)) + goto function_fail; + +@@ -1700,8 +1875,7 @@ bool mod_color_update_gamut_to_stream(struct mod_color *mod_color, + + bool mod_color_adjust_source_gamut(struct mod_color *mod_color, + const struct dc_stream **streams, int num_streams, +- struct gamut_space_coordinates *input_gamut_coordinates, +- struct white_point_coodinates *input_white_point_coordinates) ++ struct color_gamut_data *input_gamut_data) + { + struct core_color *core_color = MOD_COLOR_TO_CORE(mod_color); + +@@ -1711,25 +1885,35 @@ bool mod_color_adjust_source_gamut(struct mod_color *mod_color, + sink_index = sink_index_from_sink(core_color, + streams[stream_index]->sink); + +- core_color->state[sink_index].source_gamut.blueX = +- input_gamut_coordinates->blueX; +- core_color->state[sink_index].source_gamut.blueY = +- input_gamut_coordinates->blueY; +- core_color->state[sink_index].source_gamut.greenX = +- input_gamut_coordinates->greenX; +- core_color->state[sink_index].source_gamut.greenY = +- input_gamut_coordinates->greenY; +- core_color->state[sink_index].source_gamut.redX = +- input_gamut_coordinates->redX; +- core_color->state[sink_index].source_gamut.redY = +- input_gamut_coordinates->redY; +- core_color->state[sink_index].source_gamut.whiteX = +- input_white_point_coordinates->whiteX; +- core_color->state[sink_index].source_gamut.whiteY = +- input_white_point_coordinates->whiteY; ++ update_color_gamut_data(input_gamut_data, ++ &core_color->state[sink_index].source_gamut); + } + +- if (!mod_color_update_gamut_to_stream(mod_color, streams, num_streams)) ++ if (!mod_color_update_gamut_info(mod_color, streams, num_streams)) ++ return false; ++ ++ return true; ++} ++ ++bool mod_color_adjust_source_gamut_and_tf(struct mod_color *mod_color, ++ const struct dc_stream **streams, int num_streams, ++ struct color_gamut_data *input_gamut_data, ++ enum color_transfer_func input_transfer_func) ++{ ++ struct core_color *core_color = MOD_COLOR_TO_CORE(mod_color); ++ ++ unsigned int stream_index, sink_index; ++ ++ for (stream_index = 0; stream_index < num_streams; stream_index++) { ++ sink_index = sink_index_from_sink(core_color, ++ streams[stream_index]->sink); ++ update_color_gamut_data(input_gamut_data, ++ &core_color->state[sink_index].source_gamut); ++ core_color->state[sink_index].input_transfer_function = ++ input_transfer_func; ++ } ++ ++ if (!mod_color_update_gamut_info(mod_color, streams, num_streams)) + return false; + + return true; +@@ -1737,8 +1921,7 @@ bool mod_color_adjust_source_gamut(struct mod_color *mod_color, + + bool mod_color_adjust_destination_gamut(struct mod_color *mod_color, + const struct dc_stream **streams, int num_streams, +- struct gamut_space_coordinates *input_gamut_coordinates, +- struct white_point_coodinates *input_white_point_coordinates) ++ struct color_gamut_data *input_gamut_data) + { + struct core_color *core_color = MOD_COLOR_TO_CORE(mod_color); + +@@ -1748,22 +1931,8 @@ bool mod_color_adjust_destination_gamut(struct mod_color *mod_color, + sink_index = sink_index_from_sink(core_color, + streams[stream_index]->sink); + +- core_color->state[sink_index].destination_gamut.blueX = +- input_gamut_coordinates->blueX; +- core_color->state[sink_index].destination_gamut.blueY = +- input_gamut_coordinates->blueY; +- core_color->state[sink_index].destination_gamut.greenX = +- input_gamut_coordinates->greenX; +- core_color->state[sink_index].destination_gamut.greenY = +- input_gamut_coordinates->greenY; +- core_color->state[sink_index].destination_gamut.redX = +- input_gamut_coordinates->redX; +- core_color->state[sink_index].destination_gamut.redY = +- input_gamut_coordinates->redY; +- core_color->state[sink_index].destination_gamut.whiteX = +- input_white_point_coordinates->whiteX; +- core_color->state[sink_index].destination_gamut.whiteY = +- input_white_point_coordinates->whiteY; ++ update_color_gamut_data(input_gamut_data, ++ &core_color->state[sink_index].destination_gamut); + } + + if (!mod_color_update_gamut_to_stream(mod_color, streams, num_streams)) +@@ -1784,9 +1953,9 @@ bool mod_color_set_white_point(struct mod_color *mod_color, + stream_index++) { + sink_index = sink_index_from_sink(core_color, + streams[stream_index]->sink); +- core_color->state[sink_index].source_gamut.whiteX = ++ core_color->state[sink_index].source_gamut.gamut.whiteX = + white_point->whiteX; +- core_color->state[sink_index].source_gamut.whiteY = ++ core_color->state[sink_index].source_gamut.gamut.whiteY = + white_point->whiteY; + } + +@@ -1796,6 +1965,39 @@ bool mod_color_set_white_point(struct mod_color *mod_color, + return true; + } + ++ ++bool mod_color_set_mastering_info(struct mod_color *mod_color, ++ const struct dc_stream **streams, int num_streams, ++ struct color_mastering_info *mastering_info) ++{ ++ struct core_color *core_color = MOD_COLOR_TO_CORE(mod_color); ++ unsigned int stream_index, sink_index; ++ ++ for (stream_index = 0; stream_index < num_streams; stream_index++) { ++ sink_index = sink_index_from_sink(core_color, ++ streams[stream_index]->sink); ++ memcpy(&core_color->state[sink_index].mastering_info, ++ mastering_info, ++ sizeof(struct color_mastering_info)); ++ } ++ return true; ++} ++ ++bool mod_color_get_mastering_info(struct mod_color *mod_color, ++ const struct dc_sink *sink, ++ struct color_mastering_info *mastering_info) ++{ ++ struct core_color *core_color = ++ MOD_COLOR_TO_CORE(mod_color); ++ ++ unsigned int sink_index = sink_index_from_sink(core_color, sink); ++ ++ memcpy(mastering_info, &core_color->state[sink_index].mastering_info, ++ sizeof(struct color_mastering_info)); ++ ++ return true; ++} ++ + bool mod_color_set_user_enable(struct mod_color *mod_color, + const struct dc_stream **streams, int num_streams, + bool user_enable) +@@ -1953,7 +2155,7 @@ bool mod_color_get_source_gamut(struct mod_color *mod_color, + + unsigned int sink_index = sink_index_from_sink(core_color, sink); + +- *source_gamut = core_color->state[sink_index].source_gamut; ++ *source_gamut = core_color->state[sink_index].source_gamut.gamut; + + return true; + } +@@ -1973,14 +2175,14 @@ bool mod_color_notify_mode_change(struct mod_color *mod_color, + streams[stream_index]->sink); + + if (!build_gamut_remap_matrix +- (core_color->state[sink_index].source_gamut, +- matrix->rgbCoeffSrc, +- matrix->whiteCoeffSrc)) ++ (core_color->state[sink_index].source_gamut.gamut, ++ matrix->rgbCoeffSrc, ++ matrix->whiteCoeffSrc)) + goto function_fail; + + if (!build_gamut_remap_matrix + (core_color->state[sink_index]. +- destination_gamut, ++ destination_gamut.gamut, + matrix->rgbCoeffDst, matrix->whiteCoeffDst)) + goto function_fail; + +@@ -2379,3 +2581,200 @@ bool mod_color_is_rgb_limited_range_supported_for_timing( + + return result; + } ++ ++bool mod_color_set_regamma(struct mod_color *mod_color, ++ const struct dc_stream **streams, int num_streams) ++{ ++ /*TODO*/ ++ return true; ++} ++ ++bool mod_color_set_degamma(struct mod_color *mod_color, ++ const struct dc_stream **streams, int num_streams, ++ enum color_transfer_func transfer_function) ++{ ++ /*TODO*/ ++ return true; ++} ++ ++bool mod_color_update_gamut_info(struct mod_color *mod_color, ++ const struct dc_stream **streams, int num_streams) ++{ ++ struct core_color *core_color = MOD_COLOR_TO_CORE(mod_color); ++ unsigned int stream_index, sink_index; ++ bool should_defer = false; ++ bool is_hdr = false; ++ enum color_color_space source_color_space; ++ enum color_transfer_func input_transfer_function; ++ struct color_gamut_data new_gamut_source; ++ struct color_gamut_data new_gamut_destination; ++ ++ for (stream_index = 0; stream_index < num_streams; stream_index++) { ++ sink_index = sink_index_from_sink(core_color, ++ streams[stream_index]->sink); ++ source_color_space = ++ core_color->state[sink_index].source_gamut.color_space; ++ input_transfer_function = ++ core_color->state[sink_index].input_transfer_function; ++ new_gamut_source.color_space = source_color_space; ++ new_gamut_destination.color_space = ++ core_color->state[sink_index]. ++ destination_gamut.color_space; ++ ++ struct dc_surface *surface = ++ dc_stream_to_surface_from_pipe_ctx(core_color, ++ streams[stream_index]); ++ if (surface == NULL) ++ return false; ++ ++ if (surface->format == SURFACE_PIXEL_FORMAT_GRPH_ARGB8888 || ++ surface->format == ++ SURFACE_PIXEL_FORMAT_GRPH_ARGB2101010) { ++ ++ if (input_transfer_function == ++ transfer_func_pq2084 || ++ input_transfer_function == ++ transfer_func_pq2084_interim) { ++ /* For PQ and PQ interim, we bypass degamma+ ++ * remap+regamma, application needs to also ++ * handle gamut remapping ++ */ ++ /* TODO */ ++ is_hdr = true; ++ } else if (input_transfer_function == ++ transfer_func_linear_0_1 || ++ input_transfer_function == ++ transfer_func_linear_0_125) { ++ /* TF not supported in current surface format, ++ * but may be deferred to a later flip ++ */ ++ should_defer = true; ++ } else { ++ new_gamut_destination.color_space = ++ color_space_srgb; ++ } ++ } else if (surface->format == ++ SURFACE_PIXEL_FORMAT_GRPH_ARGB16161616F || ++ surface->format == ++ SURFACE_PIXEL_FORMAT_GRPH_ABGR16161616F || ++ surface->format == ++ SURFACE_PIXEL_FORMAT_GRPH_ARGB16161616) { ++ if (input_transfer_function == ++ transfer_func_linear_0_125) { ++ /* Regamma PQ for HDR supported displays and ++ * 0-125 source ++ */ ++ if ((core_color->edid_caps[sink_index]. ++ hdr_caps) & smpte_st2084) ++ is_hdr = true; ++ ++ /* override for BT.2020 whenever PQ */ ++ if (core_color->state[sink_index]. ++ destination_gamut.color_space != ++ color_space_bt2020) { ++ if (streams[stream_index]->timing. ++ pixel_encoding == ++ PIXEL_ENCODING_RGB) { ++ if ((core_color-> ++ edid_caps[sink_index]. ++ colorimetry_caps) & bt_2020_rgb) ++ new_gamut_destination. ++ color_space = ++ color_space_bt2020; ++ } else { ++ if ((core_color-> ++ edid_caps[sink_index]. ++ colorimetry_caps) & bt_2020_ycc) ++ new_gamut_destination. ++ color_space = ++ color_space_bt2020; ++ } ++ } ++ } else if (input_transfer_function == ++ transfer_func_linear_0_1) { ++ new_gamut_destination.color_space = ++ color_space_srgb; ++ } else { ++ /* TF not supported in current surface format, ++ * but may be deferred to a later flip ++ */ ++ should_defer = true; ++ } ++ } ++ ++ /* 0. ---- CHECK DEFERRED ---- */ ++ if (should_defer) ++ return true; ++ ++ /* 1. ---- SET GAMUT SOURCE ---- */ ++ new_gamut_source.white_point = core_color->state[sink_index]. ++ source_gamut.white_point; ++ update_color_gamut_data(&new_gamut_source, ++ &core_color->state[sink_index].source_gamut); ++ ++ /* 2. ---- SET GAMUT DESTINATION ---- */ ++ new_gamut_destination.white_point = ++ core_color->state[sink_index]. ++ destination_gamut.white_point; ++ update_color_gamut_data(&new_gamut_destination, ++ &core_color->state[sink_index].destination_gamut); ++ ++ /* 3. ---- SET DEGAMMA ---- */ ++ struct dc_transfer_func *input_tf = NULL; ++ ++ input_tf = dc_create_transfer_func(core_color->dc); ++ ++ if (input_tf != NULL) { ++ input_tf->type = TF_TYPE_PREDEFINED; ++ ++ switch (input_transfer_function) { ++ case transfer_func_srgb: ++ input_tf->tf = TRANSFER_FUNCTION_SRGB; ++ break; ++ case transfer_func_linear_0_1: ++ case transfer_func_linear_0_125: ++ input_tf->tf = TRANSFER_FUNCTION_LINEAR; ++ break; ++ default: ++ dc_transfer_func_release(input_tf); ++ input_tf = NULL; ++ break; ++ } ++ } ++ ++ /* 4. ---- SET REGAMMA ---- */ ++ struct dc_transfer_func *output_tf = NULL; ++ ++ output_tf = dc_create_transfer_func(core_color->dc); ++ ++ if (output_tf != NULL) { ++ output_tf->type = TF_TYPE_PREDEFINED; ++ if (is_hdr) ++ output_tf->tf = TRANSFER_FUNCTION_PQ; ++ else ++ output_tf->tf = TRANSFER_FUNCTION_SRGB; ++ } ++ ++ /* 5. ---- TODO: UPDATE INFOPACKETS ---- */ ++ ++ if (!mod_color_update_gamut_to_stream( ++ mod_color, streams, num_streams)) ++ return false; ++ ++ struct dc_surface_update updates[4] = {0}; ++ ++ updates[0].surface = surface; ++ updates[0].gamma = core_color->state[sink_index].gamma; ++ updates[0].in_transfer_func = input_tf; ++ updates[0].out_transfer_func = output_tf; ++ ++ dc_update_surfaces_for_target(core_color->dc, updates, 1, NULL); ++ ++ if (input_tf != NULL) ++ dc_transfer_func_release(input_tf); ++ ++ if (output_tf != NULL) ++ dc_transfer_func_release(output_tf); ++ } ++ return true; ++} +diff --git a/drivers/gpu/drm/amd/display/modules/color/color_helper.h b/drivers/gpu/drm/amd/display/modules/color/color_helper.h +index c0e6334..b7a7ca4 100644 +--- a/drivers/gpu/drm/amd/display/modules/color/color_helper.h ++++ b/drivers/gpu/drm/amd/display/modules/color/color_helper.h +@@ -37,7 +37,7 @@ bool mod_color_find_predefined_gamut( + + bool mod_color_find_predefined_white_point( + struct white_point_coodinates *out_white_point, +- unsigned int index); ++ enum predefined_white_point_type type); + + bool mod_color_find_white_point_from_temperature( + struct white_point_coodinates *out_white_point, +diff --git a/drivers/gpu/drm/amd/display/modules/inc/mod_color.h b/drivers/gpu/drm/amd/display/modules/inc/mod_color.h +index fbf9081..670b87fb 100644 +--- a/drivers/gpu/drm/amd/display/modules/inc/mod_color.h ++++ b/drivers/gpu/drm/amd/display/modules/inc/mod_color.h +@@ -30,6 +30,79 @@ + #include "dm_services.h" + #include "color_helper.h" + ++enum color_transfer_func { ++ transfer_func_unknown, ++ transfer_func_srgb, ++ transfer_func_bt709, ++ transfer_func_pq2084, ++ transfer_func_pq2084_interim, ++ transfer_func_linear_0_1, ++ transfer_func_linear_0_125, ++ transfer_func_dolbyvision, ++ transfer_func_gamma_22, ++ transfer_func_gamma_26 ++}; ++ ++enum color_color_space { ++ color_space_unsupported, ++ color_space_srgb, ++ color_space_bt601, ++ color_space_bt709, ++ color_space_xv_ycc_bt601, ++ color_space_xv_ycc_bt709, ++ color_space_xr_rgb, ++ color_space_bt2020, ++ color_space_adobe, ++ color_space_dci_p3, ++ color_space_sc_rgb_ms_ref, ++ color_space_display_native, ++ color_space_app_ctrl, ++ color_space_dolby_vision, ++ color_space_custom_coordinates ++}; ++ ++enum color_white_point_type { ++ color_white_point_type_unknown, ++ color_white_point_type_5000k_horizon, ++ color_white_point_type_6500k_noon, ++ color_white_point_type_7500k_north_sky, ++ color_white_point_type_9300k, ++ color_white_point_type_custom_coordinates ++}; ++ ++enum colorimetry_support_flag { ++ xv_ycc_bt601 = 0x01, ++ xv_ycc_bt709 = 0x02, ++ s_ycc_601 = 0x04, ++ adobe_ycc_601 = 0x08, ++ adobe_rgb = 0x10, ++ bt_2020_c_ycc = 0x20, ++ bt_2020_ycc = 0x40, ++ bt_2020_rgb = 0x80 ++}; ++ ++enum hdr_tf_support_flag { ++ traditional_gamma_sdr = 0x01, ++ traditional_gamma_hdr = 0x02, ++ smpte_st2084 = 0x04 ++}; ++ ++struct color_mastering_info { ++ unsigned int chromaticity_green_x; ++ unsigned int chromaticity_green_y; ++ unsigned int chromaticity_blue_x; ++ unsigned int chromaticity_blue_y; ++ unsigned int chromaticity_red_x; ++ unsigned int chromaticity_red_y; ++ unsigned int chromaticity_white_point_x; ++ unsigned int chromaticity_white_point_y; ++ ++ unsigned int min_luminance; ++ unsigned int max_luminance; ++ unsigned int maximum_content_light_level; ++ unsigned int maximum_frame_average_light_level; ++}; ++ + struct mod_color { + int dummy; + }; +@@ -86,12 +159,23 @@ struct color_range { + int max; + }; + ++struct color_gamut_data { ++ enum color_color_space color_space; ++ enum color_white_point_type white_point; ++ struct color_space_coordinates gamut; ++}; ++ ++struct color_edid_caps { ++ unsigned int colorimetry_caps; ++ unsigned int hdr_caps; ++}; ++ + struct mod_color *mod_color_create(struct dc *dc); + + void mod_color_destroy(struct mod_color *mod_color); + + bool mod_color_add_sink(struct mod_color *mod_color, +- const struct dc_sink *sink); ++ const struct dc_sink *sink, struct color_edid_caps *edid_caps); + + bool mod_color_remove_sink(struct mod_color *mod_color, + const struct dc_sink *sink); +@@ -105,18 +189,29 @@ bool mod_color_set_white_point(struct mod_color *mod_color, + + bool mod_color_adjust_source_gamut(struct mod_color *mod_color, + const struct dc_stream **streams, int num_streams, +- struct gamut_space_coordinates *input_gamut_coordinates, +- struct white_point_coodinates *input_white_point_coordinates); ++ struct color_gamut_data *input_gamut_data); + + bool mod_color_adjust_destination_gamut(struct mod_color *mod_color, + const struct dc_stream **streams, int num_streams, +- struct gamut_space_coordinates *input_gamut_coordinates, +- struct white_point_coodinates *input_white_point_coordinates); ++ struct color_gamut_data *input_gamut_data); ++ ++bool mod_color_adjust_source_gamut_and_tf(struct mod_color *mod_color, ++ const struct dc_stream **streams, int num_streams, ++ struct color_gamut_data *input_gamut_data, ++ enum color_transfer_func input_transfer_func); + + bool mod_color_get_user_enable(struct mod_color *mod_color, + const struct dc_sink *sink, + bool *user_enable); + ++bool mod_color_set_mastering_info(struct mod_color *mod_color, ++ const struct dc_stream **streams, int num_streams, ++ struct color_mastering_info *mastering_info); ++ ++bool mod_color_get_mastering_info(struct mod_color *mod_color, ++ const struct dc_sink *sink, ++ struct color_mastering_info *mastering_info); ++ + bool mod_color_set_user_enable(struct mod_color *mod_color, + const struct dc_stream **streams, int num_streams, + bool user_enable); +@@ -190,4 +285,14 @@ bool mod_color_is_rgb_limited_range_supported_for_timing( + const struct dc_sink *sink, + const struct dc_crtc_timing *timing); + ++bool mod_color_set_regamma(struct mod_color *mod_color, ++ const struct dc_stream **streams, int num_streams); ++ ++bool mod_color_set_degamma(struct mod_color *mod_color, ++ const struct dc_stream **streams, int num_streams, ++ enum color_transfer_func transfer_function); ++ ++bool mod_color_update_gamut_info(struct mod_color *mod_color, ++ const struct dc_stream **streams, int num_streams); ++ + #endif /* MOD_COLOR_H_ */ +-- +2.7.4 + |