diff options
Diffstat (limited to 'drivers/gpu/drm/amd/display/dc')
102 files changed, 6266 insertions, 4872 deletions
diff --git a/drivers/gpu/drm/amd/display/dc/basics/Makefile b/drivers/gpu/drm/amd/display/dc/basics/Makefile index 6af8c8a9ad80..bca33bd9a0d2 100644 --- a/drivers/gpu/drm/amd/display/dc/basics/Makefile +++ b/drivers/gpu/drm/amd/display/dc/basics/Makefile @@ -24,7 +24,7 @@ # It provides the general basic services required by other DAL # subcomponents. -BASICS = conversion.o fixpt31_32.o fixpt32_32.o grph_object_id.o \ +BASICS = conversion.o fixpt31_32.o fixpt32_32.o \ logger.o log_helpers.o vector.o AMD_DAL_BASICS = $(addprefix $(AMDDALPATH)/dc/basics/,$(BASICS)) diff --git a/drivers/gpu/drm/amd/display/dc/basics/conversion.c b/drivers/gpu/drm/amd/display/dc/basics/conversion.c index 23c9a0ec0181..310964915a83 100644 --- a/drivers/gpu/drm/amd/display/dc/basics/conversion.c +++ b/drivers/gpu/drm/amd/display/dc/basics/conversion.c @@ -46,7 +46,7 @@ uint16_t fixed_point_to_int_frac( arg)); if (d <= (uint16_t)(1 << integer_bits) - (1 / (uint16_t)divisor)) - numerator = (uint16_t)dal_fixed31_32_floor( + numerator = (uint16_t)dal_fixed31_32_round( dal_fixed31_32_mul_int( arg, divisor)); diff --git a/drivers/gpu/drm/amd/display/dc/basics/fixpt31_32.c b/drivers/gpu/drm/amd/display/dc/basics/fixpt31_32.c index 26936892c6f5..011a97f82fb6 100644 --- a/drivers/gpu/drm/amd/display/dc/basics/fixpt31_32.c +++ b/drivers/gpu/drm/amd/display/dc/basics/fixpt31_32.c @@ -554,6 +554,22 @@ static inline uint32_t ux_dy( return result | fractional_part; } +static inline uint32_t clamp_ux_dy( + int64_t value, + uint32_t integer_bits, + uint32_t fractional_bits, + uint32_t min_clamp) +{ + uint32_t truncated_val = ux_dy(value, integer_bits, fractional_bits); + + if (value >= (1LL << (integer_bits + FIXED31_32_BITS_PER_FRACTIONAL_PART))) + return (1 << (integer_bits + fractional_bits)) - 1; + else if (truncated_val > min_clamp) + return truncated_val; + else + return min_clamp; +} + uint32_t dal_fixed31_32_u2d19( struct fixed31_32 arg) { @@ -565,3 +581,15 @@ uint32_t dal_fixed31_32_u0d19( { return ux_dy(arg.value, 0, 19); } + +uint32_t dal_fixed31_32_clamp_u0d14( + struct fixed31_32 arg) +{ + return clamp_ux_dy(arg.value, 0, 14, 1); +} + +uint32_t dal_fixed31_32_clamp_u0d10( + struct fixed31_32 arg) +{ + return clamp_ux_dy(arg.value, 0, 10, 1); +} diff --git a/drivers/gpu/drm/amd/display/dc/basics/grph_object_id.c b/drivers/gpu/drm/amd/display/dc/basics/grph_object_id.c deleted file mode 100644 index 147822545252..000000000000 --- a/drivers/gpu/drm/amd/display/dc/basics/grph_object_id.c +++ /dev/null @@ -1,75 +0,0 @@ -/* - * Copyright 2012-15 Advanced Micro Devices, Inc. - * - * Permission is hereby granted, free of charge, to any person obtaining a - * copy of this software and associated documentation files (the "Software"), - * to deal in the Software without restriction, including without limitation - * the rights to use, copy, modify, merge, publish, distribute, sublicense, - * and/or sell copies of the Software, and to permit persons to whom the - * Software is furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL - * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR - * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, - * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR - * OTHER DEALINGS IN THE SOFTWARE. - * - * Authors: AMD - * - */ - -#include "dm_services.h" -#include "include/grph_object_id.h" - -static bool dal_graphics_object_id_is_valid(struct graphics_object_id id) -{ - bool rc = true; - - switch (id.type) { - case OBJECT_TYPE_UNKNOWN: - rc = false; - break; - case OBJECT_TYPE_GPU: - case OBJECT_TYPE_ENGINE: - /* do NOT check for id.id == 0 */ - if (id.enum_id == ENUM_ID_UNKNOWN) - rc = false; - break; - default: - if (id.id == 0 || id.enum_id == ENUM_ID_UNKNOWN) - rc = false; - break; - } - - return rc; -} - -bool dal_graphics_object_id_is_equal( - struct graphics_object_id id1, - struct graphics_object_id id2) -{ - if (false == dal_graphics_object_id_is_valid(id1)) { - dm_output_to_console( - "%s: Warning: comparing invalid object 'id1'!\n", __func__); - return false; - } - - if (false == dal_graphics_object_id_is_valid(id2)) { - dm_output_to_console( - "%s: Warning: comparing invalid object 'id2'!\n", __func__); - return false; - } - - if (id1.id == id2.id && id1.enum_id == id2.enum_id - && id1.type == id2.type) - return true; - - return false; -} - - diff --git a/drivers/gpu/drm/amd/display/dc/basics/log_helpers.c b/drivers/gpu/drm/amd/display/dc/basics/log_helpers.c index 6e43168fbdd6..854678a0c54b 100644 --- a/drivers/gpu/drm/amd/display/dc/basics/log_helpers.c +++ b/drivers/gpu/drm/amd/display/dc/basics/log_helpers.c @@ -83,15 +83,11 @@ void dc_conn_log(struct dc_context *ctx, link->link_index); va_start(args, msg); - entry.buf_offset += dm_log_to_buffer( - &entry.buf[entry.buf_offset], - LOG_MAX_LINE_SIZE - entry.buf_offset, - msg, args); + dm_logger_append_va(&entry, msg, args); - if (entry.buf[strlen(entry.buf) - 1] == '\n') { - entry.buf[strlen(entry.buf) - 1] = '\0'; + if (entry.buf_offset > 0 && + entry.buf[entry.buf_offset - 1] == '\n') entry.buf_offset--; - } if (hex_data) for (i = 0; i < hex_data_count; i++) diff --git a/drivers/gpu/drm/amd/display/dc/basics/logger.c b/drivers/gpu/drm/amd/display/dc/basics/logger.c index e04e8ecd4874..180a9d69d351 100644 --- a/drivers/gpu/drm/amd/display/dc/basics/logger.c +++ b/drivers/gpu/drm/amd/display/dc/basics/logger.c @@ -70,9 +70,8 @@ static bool construct(struct dc_context *ctx, struct dal_logger *logger, { /* malloc buffer and init offsets */ logger->log_buffer_size = DAL_LOGGER_BUFFER_MAX_SIZE; - logger->log_buffer = (char *)kzalloc(logger->log_buffer_size * sizeof(char), - GFP_KERNEL); - + logger->log_buffer = kcalloc(logger->log_buffer_size, sizeof(char), + GFP_KERNEL); if (!logger->log_buffer) return false; @@ -313,6 +312,18 @@ void dm_logger_append( const char *msg, ...) { + va_list args; + + va_start(args, msg); + dm_logger_append_va(entry, msg, args); + va_end(args); +} + +void dm_logger_append_va( + struct log_entry *entry, + const char *msg, + va_list args) +{ struct dal_logger *logger; if (!entry) { @@ -326,11 +337,8 @@ void dm_logger_append( dal_logger_should_log(logger, entry->type)) { uint32_t size; - va_list args; char buffer[LOG_MAX_LINE_SIZE]; - va_start(args, msg); - size = dm_log_to_buffer( buffer, LOG_MAX_LINE_SIZE, msg, args); @@ -339,8 +347,6 @@ void dm_logger_append( } else { append_entry(entry, "LOG_ERROR, line too long\n", 27); } - - va_end(args); } } diff --git a/drivers/gpu/drm/amd/display/dc/bios/bios_parser.c b/drivers/gpu/drm/amd/display/dc/bios/bios_parser.c index 86e6438c5cf3..c00e405b63e8 100644 --- a/drivers/gpu/drm/amd/display/dc/bios/bios_parser.c +++ b/drivers/gpu/drm/amd/display/dc/bios/bios_parser.c @@ -190,6 +190,7 @@ static struct graphics_object_id bios_parser_get_connector_id( struct bios_parser *bp = BP_FROM_DCB(dcb); struct graphics_object_id object_id = dal_graphics_object_id_init( 0, ENUM_ID_UNKNOWN, OBJECT_TYPE_UNKNOWN); + uint16_t id; uint32_t connector_table_offset = bp->object_info_tbl_offset + le16_to_cpu(bp->object_info_tbl.v1_1->usConnectorObjectTableOffset); @@ -197,12 +198,19 @@ static struct graphics_object_id bios_parser_get_connector_id( ATOM_OBJECT_TABLE *tbl = GET_IMAGE(ATOM_OBJECT_TABLE, connector_table_offset); - if (tbl && tbl->ucNumberOfObjects > i) { - const uint16_t id = le16_to_cpu(tbl->asObjects[i].usObjectID); + if (!tbl) { + dm_error("Can't get connector table from atom bios.\n"); + return object_id; + } - object_id = object_id_from_bios_object_id(id); + if (tbl->ucNumberOfObjects <= i) { + dm_error("Can't find connector id %d in connector table of size %d.\n", + i, tbl->ucNumberOfObjects); + return object_id; } + id = le16_to_cpu(tbl->asObjects[i].usObjectID); + object_id = object_id_from_bios_object_id(id); return object_id; } @@ -2254,6 +2262,52 @@ static enum bp_result get_gpio_i2c_info(struct bios_parser *bp, return BP_RESULT_OK; } +static bool dal_graphics_object_id_is_valid(struct graphics_object_id id) +{ + bool rc = true; + + switch (id.type) { + case OBJECT_TYPE_UNKNOWN: + rc = false; + break; + case OBJECT_TYPE_GPU: + case OBJECT_TYPE_ENGINE: + /* do NOT check for id.id == 0 */ + if (id.enum_id == ENUM_ID_UNKNOWN) + rc = false; + break; + default: + if (id.id == 0 || id.enum_id == ENUM_ID_UNKNOWN) + rc = false; + break; + } + + return rc; +} + +static bool dal_graphics_object_id_is_equal( + struct graphics_object_id id1, + struct graphics_object_id id2) +{ + if (false == dal_graphics_object_id_is_valid(id1)) { + dm_output_to_console( + "%s: Warning: comparing invalid object 'id1'!\n", __func__); + return false; + } + + if (false == dal_graphics_object_id_is_valid(id2)) { + dm_output_to_console( + "%s: Warning: comparing invalid object 'id2'!\n", __func__); + return false; + } + + if (id1.id == id2.id && id1.enum_id == id2.enum_id + && id1.type == id2.type) + return true; + + return false; +} + static ATOM_OBJECT *get_bios_object(struct bios_parser *bp, struct graphics_object_id id) { diff --git a/drivers/gpu/drm/amd/display/dc/bios/command_table.c b/drivers/gpu/drm/amd/display/dc/bios/command_table.c index 3f7b2dabc2b0..4b5fdd577848 100644 --- a/drivers/gpu/drm/amd/display/dc/bios/command_table.c +++ b/drivers/gpu/drm/amd/display/dc/bios/command_table.c @@ -387,6 +387,7 @@ static void init_transmitter_control(struct bios_parser *bp) bp->cmd_tbl.transmitter_control = transmitter_control_v1_6; break; default: + dm_output_to_console("Don't have transmitter_control for v%d\n", crev); bp->cmd_tbl.transmitter_control = NULL; break; } @@ -910,6 +911,8 @@ static void init_set_pixel_clock(struct bios_parser *bp) bp->cmd_tbl.set_pixel_clock = set_pixel_clock_v7; break; default: + dm_output_to_console("Don't have set_pixel_clock for v%d\n", + BIOS_CMD_TABLE_PARA_REVISION(SetPixelClock)); bp->cmd_tbl.set_pixel_clock = NULL; break; } @@ -1227,6 +1230,8 @@ static void init_enable_spread_spectrum_on_ppll(struct bios_parser *bp) enable_spread_spectrum_on_ppll_v3; break; default: + dm_output_to_console("Don't have enable_spread_spectrum_on_ppll for v%d\n", + BIOS_CMD_TABLE_PARA_REVISION(EnableSpreadSpectrumOnPPLL)); bp->cmd_tbl.enable_spread_spectrum_on_ppll = NULL; break; } @@ -1422,6 +1427,8 @@ static void init_adjust_display_pll(struct bios_parser *bp) bp->cmd_tbl.adjust_display_pll = adjust_display_pll_v3; break; default: + dm_output_to_console("Don't have adjust_display_pll for v%d\n", + BIOS_CMD_TABLE_PARA_REVISION(AdjustDisplayPll)); bp->cmd_tbl.adjust_display_pll = NULL; break; } @@ -1695,6 +1702,8 @@ static void init_set_crtc_timing(struct bios_parser *bp) set_crtc_using_dtd_timing_v3; break; default: + dm_output_to_console("Don't have set_crtc_timing for dtd v%d\n", + dtd_version); bp->cmd_tbl.set_crtc_timing = NULL; break; } @@ -1704,6 +1713,8 @@ static void init_set_crtc_timing(struct bios_parser *bp) bp->cmd_tbl.set_crtc_timing = set_crtc_timing_v1; break; default: + dm_output_to_console("Don't have set_crtc_timing for v%d\n", + BIOS_CMD_TABLE_PARA_REVISION(SetCRTC_Timing)); bp->cmd_tbl.set_crtc_timing = NULL; break; } @@ -1890,6 +1901,8 @@ static void init_select_crtc_source(struct bios_parser *bp) bp->cmd_tbl.select_crtc_source = select_crtc_source_v3; break; default: + dm_output_to_console("Don't select_crtc_source enable_crtc for v%d\n", + BIOS_CMD_TABLE_PARA_REVISION(SelectCRTC_Source)); bp->cmd_tbl.select_crtc_source = NULL; break; } @@ -1997,6 +2010,8 @@ static void init_enable_crtc(struct bios_parser *bp) bp->cmd_tbl.enable_crtc = enable_crtc_v1; break; default: + dm_output_to_console("Don't have enable_crtc for v%d\n", + BIOS_CMD_TABLE_PARA_REVISION(EnableCRTC)); bp->cmd_tbl.enable_crtc = NULL; break; } @@ -2103,6 +2118,8 @@ static void init_program_clock(struct bios_parser *bp) bp->cmd_tbl.program_clock = program_clock_v6; break; default: + dm_output_to_console("Don't have program_clock for v%d\n", + BIOS_CMD_TABLE_PARA_REVISION(SetPixelClock)); bp->cmd_tbl.program_clock = NULL; break; } @@ -2324,6 +2341,8 @@ static void init_enable_disp_power_gating( enable_disp_power_gating_v2_1; break; default: + dm_output_to_console("Don't enable_disp_power_gating enable_crtc for v%d\n", + BIOS_CMD_TABLE_PARA_REVISION(EnableDispPowerGating)); bp->cmd_tbl.enable_disp_power_gating = NULL; break; } @@ -2371,6 +2390,8 @@ static void init_set_dce_clock(struct bios_parser *bp) bp->cmd_tbl.set_dce_clock = set_dce_clock_v2_1; break; default: + dm_output_to_console("Don't have set_dce_clock for v%d\n", + BIOS_CMD_TABLE_PARA_REVISION(SetDCEClock)); bp->cmd_tbl.set_dce_clock = NULL; break; } diff --git a/drivers/gpu/drm/amd/display/dc/bios/command_table2.c b/drivers/gpu/drm/amd/display/dc/bios/command_table2.c index ba68693758a7..fea5e83736fd 100644 --- a/drivers/gpu/drm/amd/display/dc/bios/command_table2.c +++ b/drivers/gpu/drm/amd/display/dc/bios/command_table2.c @@ -118,6 +118,7 @@ static void init_dig_encoder_control(struct bios_parser *bp) bp->cmd_tbl.dig_encoder_control = encoder_control_digx_v1_5; break; default: + dm_output_to_console("Don't have dig_encoder_control for v%d\n", version); bp->cmd_tbl.dig_encoder_control = NULL; break; } @@ -205,6 +206,7 @@ static void init_transmitter_control(struct bios_parser *bp) bp->cmd_tbl.transmitter_control = transmitter_control_v1_6; break; default: + dm_output_to_console("Don't have transmitter_control for v%d\n", crev); bp->cmd_tbl.transmitter_control = NULL; break; } @@ -268,6 +270,8 @@ static void init_set_pixel_clock(struct bios_parser *bp) bp->cmd_tbl.set_pixel_clock = set_pixel_clock_v7; break; default: + dm_output_to_console("Don't have set_pixel_clock for v%d\n", + BIOS_CMD_TABLE_PARA_REVISION(setpixelclock)); bp->cmd_tbl.set_pixel_clock = NULL; break; } @@ -379,6 +383,7 @@ static void init_set_crtc_timing(struct bios_parser *bp) set_crtc_using_dtd_timing_v3; break; default: + dm_output_to_console("Don't have set_crtc_timing for v%d\n", dtd_version); bp->cmd_tbl.set_crtc_timing = NULL; break; } @@ -498,6 +503,8 @@ static void init_select_crtc_source(struct bios_parser *bp) bp->cmd_tbl.select_crtc_source = select_crtc_source_v3; break; default: + dm_output_to_console("Don't select_crtc_source enable_crtc for v%d\n", + BIOS_CMD_TABLE_PARA_REVISION(selectcrtc_source)); bp->cmd_tbl.select_crtc_source = NULL; break; } @@ -565,6 +572,8 @@ static void init_enable_crtc(struct bios_parser *bp) bp->cmd_tbl.enable_crtc = enable_crtc_v1; break; default: + dm_output_to_console("Don't have enable_crtc for v%d\n", + BIOS_CMD_TABLE_PARA_REVISION(enablecrtc)); bp->cmd_tbl.enable_crtc = NULL; break; } @@ -661,6 +670,8 @@ static void init_enable_disp_power_gating( enable_disp_power_gating_v2_1; break; default: + dm_output_to_console("Don't enable_disp_power_gating enable_crtc for v%d\n", + BIOS_CMD_TABLE_PARA_REVISION(enabledisppowergating)); bp->cmd_tbl.enable_disp_power_gating = NULL; break; } @@ -710,6 +721,8 @@ static void init_set_dce_clock(struct bios_parser *bp) bp->cmd_tbl.set_dce_clock = set_dce_clock_v2_1; break; default: + dm_output_to_console("Don't have set_dce_clock for v%d\n", + BIOS_CMD_TABLE_PARA_REVISION(setdceclock)); bp->cmd_tbl.set_dce_clock = NULL; break; } diff --git a/drivers/gpu/drm/amd/display/dc/calcs/dce_calcs.c b/drivers/gpu/drm/amd/display/dc/calcs/dce_calcs.c index 6347712db834..2e11fac2a63d 100644 --- a/drivers/gpu/drm/amd/display/dc/calcs/dce_calcs.c +++ b/drivers/gpu/drm/amd/display/dc/calcs/dce_calcs.c @@ -29,6 +29,15 @@ #include "core_types.h" #include "dal_asic_id.h" +/* + * NOTE: + * This file is gcc-parseable HW gospel, coming straight from HW engineers. + * + * It doesn't adhere to Linux kernel style and sometimes will do things in odd + * ways. Unless there is something clearly wrong with it the code should + * remain as-is as it provides us with a guarantee from HW that it is correct. + */ + /******************************************************************************* * Private Functions ******************************************************************************/ diff --git a/drivers/gpu/drm/amd/display/dc/calcs/dcn_calc_auto.c b/drivers/gpu/drm/amd/display/dc/calcs/dcn_calc_auto.c index 626f9cf8aad2..5e2ea12fbb73 100644 --- a/drivers/gpu/drm/amd/display/dc/calcs/dcn_calc_auto.c +++ b/drivers/gpu/drm/amd/display/dc/calcs/dcn_calc_auto.c @@ -27,6 +27,15 @@ #include "dcn_calc_auto.h" #include "dcn_calc_math.h" +/* + * NOTE: + * This file is gcc-parseable HW gospel, coming straight from HW engineers. + * + * It doesn't adhere to Linux kernel style and sometimes will do things in odd + * ways. Unless there is something clearly wrong with it the code should + * remain as-is as it provides us with a guarantee from HW that it is correct. + */ + /*REVISION#250*/ void scaler_settings_calculation(struct dcn_bw_internal_vars *v) { @@ -773,11 +782,11 @@ void mode_support_and_system_configuration(struct dcn_bw_internal_vars *v) v->dst_y_after_scaler = 0.0; } v->time_calc = 24.0 / v->projected_dcfclk_deep_sleep; - v->v_update_offset[k] =dcn_bw_ceil2(v->htotal[k] / 4.0, 1.0); + v->v_update_offset[k][j] = dcn_bw_ceil2(v->htotal[k] / 4.0, 1.0); v->total_repeater_delay = v->max_inter_dcn_tile_repeaters * (2.0 / (v->required_dispclk[i][j] / (j + 1)) + 3.0 / v->required_dispclk[i][j]); - v->v_update_width[k] = (14.0 / v->projected_dcfclk_deep_sleep + 12.0 / (v->required_dispclk[i][j] / (j + 1)) + v->total_repeater_delay) * v->pixel_clock[k]; - v->v_ready_offset[k] =dcn_bw_max2(150.0 / (v->required_dispclk[i][j] / (j + 1)), v->total_repeater_delay + 20.0 / v->projected_dcfclk_deep_sleep + 10.0 / (v->required_dispclk[i][j] / (j + 1))) * v->pixel_clock[k]; - v->time_setup = (v->v_update_offset[k] + v->v_update_width[k] + v->v_ready_offset[k]) / v->pixel_clock[k]; + v->v_update_width[k][j] = (14.0 / v->projected_dcfclk_deep_sleep + 12.0 / (v->required_dispclk[i][j] / (j + 1)) + v->total_repeater_delay) * v->pixel_clock[k]; + v->v_ready_offset[k][j] = dcn_bw_max2(150.0 / (v->required_dispclk[i][j] / (j + 1)), v->total_repeater_delay + 20.0 / v->projected_dcfclk_deep_sleep + 10.0 / (v->required_dispclk[i][j] / (j + 1))) * v->pixel_clock[k]; + v->time_setup = (v->v_update_offset[k][j] + v->v_update_width[k][j] + v->v_ready_offset[k][j]) / v->pixel_clock[k]; v->extra_latency = v->urgent_round_trip_and_out_of_order_latency_per_state[i] + (v->total_number_of_active_dpp[i][j] * v->pixel_chunk_size_in_kbyte + v->total_number_of_dcc_active_dpp[i][j] * v->meta_chunk_size) * 1024.0 / v->return_bw_per_state[i]; if (v->pte_enable == dcn_bw_yes) { v->extra_latency = v->extra_latency + v->total_number_of_active_dpp[i][j] * v->pte_chunk_size * 1024.0 / v->return_bw_per_state[i]; diff --git a/drivers/gpu/drm/amd/display/dc/calcs/dcn_calc_math.c b/drivers/gpu/drm/amd/display/dc/calcs/dcn_calc_math.c index b6abe0f3bb15..7600a4a4abc7 100644 --- a/drivers/gpu/drm/amd/display/dc/calcs/dcn_calc_math.c +++ b/drivers/gpu/drm/amd/display/dc/calcs/dcn_calc_math.c @@ -25,37 +25,44 @@ #include "dcn_calc_math.h" +#define isNaN(number) ((number) != (number)) + +/* + * NOTE: + * This file is gcc-parseable HW gospel, coming straight from HW engineers. + * + * It doesn't adhere to Linux kernel style and sometimes will do things in odd + * ways. Unless there is something clearly wrong with it the code should + * remain as-is as it provides us with a guarantee from HW that it is correct. + */ + float dcn_bw_mod(const float arg1, const float arg2) { - if (arg1 != arg1) + if (isNaN(arg1)) return arg2; - if (arg2 != arg2) + if (isNaN(arg2)) return arg1; return arg1 - arg1 * ((int) (arg1 / arg2)); } float dcn_bw_min2(const float arg1, const float arg2) { - if (arg1 != arg1) + if (isNaN(arg1)) return arg2; - if (arg2 != arg2) + if (isNaN(arg2)) return arg1; return arg1 < arg2 ? arg1 : arg2; } unsigned int dcn_bw_max(const unsigned int arg1, const unsigned int arg2) { - if (arg1 != arg1) - return arg2; - if (arg2 != arg2) - return arg1; return arg1 > arg2 ? arg1 : arg2; } float dcn_bw_max2(const float arg1, const float arg2) { - if (arg1 != arg1) + if (isNaN(arg1)) return arg2; - if (arg2 != arg2) + if (isNaN(arg2)) return arg1; return arg1 > arg2 ? arg1 : arg2; } diff --git a/drivers/gpu/drm/amd/display/dc/calcs/dcn_calcs.c b/drivers/gpu/drm/amd/display/dc/calcs/dcn_calcs.c index b142629a1058..331891c2c71a 100644 --- a/drivers/gpu/drm/amd/display/dc/calcs/dcn_calcs.c +++ b/drivers/gpu/drm/amd/display/dc/calcs/dcn_calcs.c @@ -33,6 +33,15 @@ #include "dcn10/dcn10_resource.h" #include "dcn_calc_math.h" +/* + * NOTE: + * This file is gcc-parseable HW gospel, coming straight from HW engineers. + * + * It doesn't adhere to Linux kernel style and sometimes will do things in odd + * ways. Unless there is something clearly wrong with it the code should + * remain as-is as it provides us with a guarantee from HW that it is correct. + */ + /* Defaults from spreadsheet rev#247 */ const struct dcn_soc_bounding_box dcn10_soc_defaults = { /* latencies */ @@ -432,25 +441,13 @@ static void dcn_bw_calc_rq_dlg_ttu( input.clks_cfg.dcfclk_mhz = v->dcfclk; input.clks_cfg.dispclk_mhz = v->dispclk; input.clks_cfg.dppclk_mhz = v->dppclk; - input.clks_cfg.refclk_mhz = dc->res_pool->ref_clock_inKhz/1000; + input.clks_cfg.refclk_mhz = dc->res_pool->ref_clock_inKhz / 1000.0; input.clks_cfg.socclk_mhz = v->socclk; input.clks_cfg.voltage = v->voltage_level; // dc->dml.logger = pool->base.logger; input.dout.output_format = (v->output_format[in_idx] == dcn_bw_420) ? dm_420 : dm_444; input.dout.output_type = (v->output[in_idx] == dcn_bw_hdmi) ? dm_hdmi : dm_dp; //input[in_idx].dout.output_standard; - switch (v->output_deep_color[in_idx]) { - case dcn_bw_encoder_12bpc: - input.dout.output_bpc = dm_out_12; - break; - case dcn_bw_encoder_10bpc: - input.dout.output_bpc = dm_out_10; - break; - case dcn_bw_encoder_8bpc: - default: - input.dout.output_bpc = dm_out_8; - break; - } /*todo: soc->sr_enter_plus_exit_time??*/ dlg_sys_param.t_srx_delay_us = dc->dcn_ip->dcfclk_cstate_latency / v->dcf_clk_deep_sleep; @@ -890,6 +887,17 @@ bool dcn_validate_bandwidth( + pipe->bottom_pipe->plane_res.scl_data.recout.width; } + if (pipe->plane_state->rotation % 2 == 0) { + ASSERT(pipe->plane_res.scl_data.ratios.horz.value != dal_fixed31_32_one.value + || v->scaler_rec_out_width[input_idx] == v->viewport_width[input_idx]); + ASSERT(pipe->plane_res.scl_data.ratios.vert.value != dal_fixed31_32_one.value + || v->scaler_recout_height[input_idx] == v->viewport_height[input_idx]); + } else { + ASSERT(pipe->plane_res.scl_data.ratios.horz.value != dal_fixed31_32_one.value + || v->scaler_recout_height[input_idx] == v->viewport_width[input_idx]); + ASSERT(pipe->plane_res.scl_data.ratios.vert.value != dal_fixed31_32_one.value + || v->scaler_rec_out_width[input_idx] == v->viewport_height[input_idx]); + } v->dcc_enable[input_idx] = pipe->plane_state->dcc.enable ? dcn_bw_yes : dcn_bw_no; v->source_pixel_format[input_idx] = tl_pixel_format_to_bw_defs( pipe->plane_state->format); @@ -1006,9 +1014,9 @@ bool dcn_validate_bandwidth( if (pipe->top_pipe && pipe->top_pipe->plane_state == pipe->plane_state) continue; - pipe->pipe_dlg_param.vupdate_width = v->v_update_width[input_idx]; - pipe->pipe_dlg_param.vupdate_offset = v->v_update_offset[input_idx]; - pipe->pipe_dlg_param.vready_offset = v->v_ready_offset[input_idx]; + pipe->pipe_dlg_param.vupdate_width = v->v_update_width[input_idx][v->dpp_per_plane[input_idx] == 2 ? 1 : 0]; + pipe->pipe_dlg_param.vupdate_offset = v->v_update_offset[input_idx][v->dpp_per_plane[input_idx] == 2 ? 1 : 0]; + pipe->pipe_dlg_param.vready_offset = v->v_ready_offset[input_idx][v->dpp_per_plane[input_idx] == 2 ? 1 : 0]; pipe->pipe_dlg_param.vstartup_start = v->v_startup[input_idx]; pipe->pipe_dlg_param.htotal = pipe->stream->timing.h_total; @@ -1034,6 +1042,8 @@ bool dcn_validate_bandwidth( if (pipe->plane_state) { struct pipe_ctx *hsplit_pipe = pipe->bottom_pipe; + pipe->plane_state->update_flags.bits.full_update = 1; + if (v->dpp_per_plane[input_idx] == 2 || ((pipe->stream->view_format == VIEW_3D_FORMAT_SIDE_BY_SIDE || @@ -1045,9 +1055,9 @@ bool dcn_validate_bandwidth( TIMING_3D_FORMAT_SIDE_BY_SIDE))) { if (hsplit_pipe && hsplit_pipe->plane_state == pipe->plane_state) { /* update previously split pipe */ - hsplit_pipe->pipe_dlg_param.vupdate_width = v->v_update_width[input_idx]; - hsplit_pipe->pipe_dlg_param.vupdate_offset = v->v_update_offset[input_idx]; - hsplit_pipe->pipe_dlg_param.vready_offset = v->v_ready_offset[input_idx]; + hsplit_pipe->pipe_dlg_param.vupdate_width = v->v_update_width[input_idx][v->dpp_per_plane[input_idx] == 2 ? 1 : 0]; + hsplit_pipe->pipe_dlg_param.vupdate_offset = v->v_update_offset[input_idx][v->dpp_per_plane[input_idx] == 2 ? 1 : 0]; + hsplit_pipe->pipe_dlg_param.vready_offset = v->v_ready_offset[input_idx][v->dpp_per_plane[input_idx] == 2 ? 1 : 0]; hsplit_pipe->pipe_dlg_param.vstartup_start = v->v_startup[input_idx]; hsplit_pipe->pipe_dlg_param.htotal = pipe->stream->timing.h_total; @@ -1073,6 +1083,9 @@ bool dcn_validate_bandwidth( hsplit_pipe->stream = NULL; hsplit_pipe->top_pipe = NULL; hsplit_pipe->bottom_pipe = NULL; + /* Clear plane_res and stream_res */ + memset(&hsplit_pipe->plane_res, 0, sizeof(hsplit_pipe->plane_res)); + memset(&hsplit_pipe->stream_res, 0, sizeof(hsplit_pipe->stream_res)); resource_build_scaling_params(pipe); } /* for now important to do this after pipe split for building e2e params */ @@ -1240,40 +1253,62 @@ unsigned int dcn_find_dcfclk_suits_all( return dcf_clk; } +static bool verify_clock_values(struct dm_pp_clock_levels_with_voltage *clks) +{ + int i; + + if (clks->num_levels == 0) + return false; + + for (i = 0; i < clks->num_levels; i++) + /* Ensure that the result is sane */ + if (clks->data[i].clocks_in_khz == 0) + return false; + + return true; +} + void dcn_bw_update_from_pplib(struct dc *dc) { struct dc_context *ctx = dc->ctx; - struct dm_pp_clock_levels_with_voltage clks = {0}; + struct dm_pp_clock_levels_with_voltage fclks = {0}, dcfclks = {0}; + bool res; kernel_fpu_begin(); /* TODO: This is not the proper way to obtain fabric_and_dram_bandwidth, should be min(fclk, memclk) */ - - if (dm_pp_get_clock_levels_by_type_with_voltage( - ctx, DM_PP_CLOCK_TYPE_FCLK, &clks) && - clks.num_levels != 0) { - ASSERT(clks.num_levels >= 3); - dc->dcn_soc->fabric_and_dram_bandwidth_vmin0p65 = 32 * (clks.data[0].clocks_in_khz / 1000.0) / 1000.0; - if (clks.num_levels > 2) { - dc->dcn_soc->fabric_and_dram_bandwidth_vmid0p72 = dc->dcn_soc->number_of_channels * - (clks.data[clks.num_levels - 3].clocks_in_khz / 1000.0) * ddr4_dram_factor_single_Channel / 1000.0; - } else { - dc->dcn_soc->fabric_and_dram_bandwidth_vmid0p72 = dc->dcn_soc->number_of_channels * - (clks.data[clks.num_levels - 2].clocks_in_khz / 1000.0) * ddr4_dram_factor_single_Channel / 1000.0; - } + res = dm_pp_get_clock_levels_by_type_with_voltage( + ctx, DM_PP_CLOCK_TYPE_FCLK, &fclks); + + if (res) + res = verify_clock_values(&fclks); + + if (res) { + ASSERT(fclks.num_levels >= 3); + dc->dcn_soc->fabric_and_dram_bandwidth_vmin0p65 = 32 * (fclks.data[0].clocks_in_khz / 1000.0) / 1000.0; + dc->dcn_soc->fabric_and_dram_bandwidth_vmid0p72 = dc->dcn_soc->number_of_channels * + (fclks.data[fclks.num_levels - (fclks.num_levels > 2 ? 3 : 2)].clocks_in_khz / 1000.0) + * ddr4_dram_factor_single_Channel / 1000.0; dc->dcn_soc->fabric_and_dram_bandwidth_vnom0p8 = dc->dcn_soc->number_of_channels * - (clks.data[clks.num_levels - 2].clocks_in_khz / 1000.0) * ddr4_dram_factor_single_Channel / 1000.0; + (fclks.data[fclks.num_levels - 2].clocks_in_khz / 1000.0) + * ddr4_dram_factor_single_Channel / 1000.0; dc->dcn_soc->fabric_and_dram_bandwidth_vmax0p9 = dc->dcn_soc->number_of_channels * - (clks.data[clks.num_levels - 1].clocks_in_khz / 1000.0) * ddr4_dram_factor_single_Channel / 1000.0; + (fclks.data[fclks.num_levels - 1].clocks_in_khz / 1000.0) + * ddr4_dram_factor_single_Channel / 1000.0; } else BREAK_TO_DEBUGGER(); - if (dm_pp_get_clock_levels_by_type_with_voltage( - ctx, DM_PP_CLOCK_TYPE_DCFCLK, &clks) && - clks.num_levels >= 3) { - dc->dcn_soc->dcfclkv_min0p65 = clks.data[0].clocks_in_khz / 1000.0; - dc->dcn_soc->dcfclkv_mid0p72 = clks.data[clks.num_levels - 3].clocks_in_khz / 1000.0; - dc->dcn_soc->dcfclkv_nom0p8 = clks.data[clks.num_levels - 2].clocks_in_khz / 1000.0; - dc->dcn_soc->dcfclkv_max0p9 = clks.data[clks.num_levels - 1].clocks_in_khz / 1000.0; + + res = dm_pp_get_clock_levels_by_type_with_voltage( + ctx, DM_PP_CLOCK_TYPE_DCFCLK, &dcfclks); + + if (res) + res = verify_clock_values(&dcfclks); + + if (res && dcfclks.num_levels >= 3) { + dc->dcn_soc->dcfclkv_min0p65 = dcfclks.data[0].clocks_in_khz / 1000.0; + dc->dcn_soc->dcfclkv_mid0p72 = dcfclks.data[dcfclks.num_levels - 3].clocks_in_khz / 1000.0; + dc->dcn_soc->dcfclkv_nom0p8 = dcfclks.data[dcfclks.num_levels - 2].clocks_in_khz / 1000.0; + dc->dcn_soc->dcfclkv_max0p9 = dcfclks.data[dcfclks.num_levels - 1].clocks_in_khz / 1000.0; } else BREAK_TO_DEBUGGER(); @@ -1550,35 +1585,6 @@ void dcn_bw_sync_calcs_and_dml(struct dc *dc) dc->dcn_ip->can_vstartup_lines_exceed_vsync_plus_back_porch_lines_minus_one, dc->dcn_ip->bug_forcing_luma_and_chroma_request_to_same_size_fixed, dc->dcn_ip->dcfclk_cstate_latency); - dc->dml.soc.vmin.socclk_mhz = dc->dcn_soc->socclk; - dc->dml.soc.vmid.socclk_mhz = dc->dcn_soc->socclk; - dc->dml.soc.vnom.socclk_mhz = dc->dcn_soc->socclk; - dc->dml.soc.vmax.socclk_mhz = dc->dcn_soc->socclk; - - dc->dml.soc.vmin.dcfclk_mhz = dc->dcn_soc->dcfclkv_min0p65; - dc->dml.soc.vmid.dcfclk_mhz = dc->dcn_soc->dcfclkv_mid0p72; - dc->dml.soc.vnom.dcfclk_mhz = dc->dcn_soc->dcfclkv_nom0p8; - dc->dml.soc.vmax.dcfclk_mhz = dc->dcn_soc->dcfclkv_max0p9; - - dc->dml.soc.vmin.dispclk_mhz = dc->dcn_soc->max_dispclk_vmin0p65; - dc->dml.soc.vmid.dispclk_mhz = dc->dcn_soc->max_dispclk_vmid0p72; - dc->dml.soc.vnom.dispclk_mhz = dc->dcn_soc->max_dispclk_vnom0p8; - dc->dml.soc.vmax.dispclk_mhz = dc->dcn_soc->max_dispclk_vmax0p9; - - dc->dml.soc.vmin.dppclk_mhz = dc->dcn_soc->max_dppclk_vmin0p65; - dc->dml.soc.vmid.dppclk_mhz = dc->dcn_soc->max_dppclk_vmid0p72; - dc->dml.soc.vnom.dppclk_mhz = dc->dcn_soc->max_dppclk_vnom0p8; - dc->dml.soc.vmax.dppclk_mhz = dc->dcn_soc->max_dppclk_vmax0p9; - - dc->dml.soc.vmin.phyclk_mhz = dc->dcn_soc->phyclkv_min0p65; - dc->dml.soc.vmid.phyclk_mhz = dc->dcn_soc->phyclkv_mid0p72; - dc->dml.soc.vnom.phyclk_mhz = dc->dcn_soc->phyclkv_nom0p8; - dc->dml.soc.vmax.phyclk_mhz = dc->dcn_soc->phyclkv_max0p9; - - dc->dml.soc.vmin.dram_bw_per_chan_gbps = dc->dcn_soc->fabric_and_dram_bandwidth_vmin0p65; - dc->dml.soc.vmid.dram_bw_per_chan_gbps = dc->dcn_soc->fabric_and_dram_bandwidth_vmid0p72; - dc->dml.soc.vnom.dram_bw_per_chan_gbps = dc->dcn_soc->fabric_and_dram_bandwidth_vnom0p8; - dc->dml.soc.vmax.dram_bw_per_chan_gbps = dc->dcn_soc->fabric_and_dram_bandwidth_vmax0p9; dc->dml.soc.sr_exit_time_us = dc->dcn_soc->sr_exit_time; dc->dml.soc.sr_enter_plus_exit_time_us = dc->dcn_soc->sr_enter_plus_exit_time; diff --git a/drivers/gpu/drm/amd/display/dc/core/dc.c b/drivers/gpu/drm/amd/display/dc/core/dc.c index 7240db2e6f09..35e84ed031de 100644 --- a/drivers/gpu/drm/amd/display/dc/core/dc.c +++ b/drivers/gpu/drm/amd/display/dc/core/dc.c @@ -54,6 +54,13 @@ /******************************************************************************* * Private functions ******************************************************************************/ + +static inline void elevate_update_type(enum surface_update_type *original, enum surface_update_type new) +{ + if (new > *original) + *original = new; +} + static void destroy_links(struct dc *dc) { uint32_t i; @@ -157,7 +164,7 @@ failed_alloc: return false; } -static bool stream_adjust_vmin_vmax(struct dc *dc, +bool dc_stream_adjust_vmin_vmax(struct dc *dc, struct dc_stream_state **streams, int num_streams, int vmin, int vmax) { @@ -182,7 +189,7 @@ static bool stream_adjust_vmin_vmax(struct dc *dc, return ret; } -static bool stream_get_crtc_position(struct dc *dc, +bool dc_stream_get_crtc_position(struct dc *dc, struct dc_stream_state **streams, int num_streams, unsigned int *v_pos, unsigned int *nom_v_pos) { @@ -207,45 +214,7 @@ static bool stream_get_crtc_position(struct dc *dc, return ret; } -static bool set_gamut_remap(struct dc *dc, const struct dc_stream_state *stream) -{ - int i = 0; - bool ret = false; - struct pipe_ctx *pipes; - - for (i = 0; i < MAX_PIPES; i++) { - if (dc->current_state->res_ctx.pipe_ctx[i].stream == stream) { - pipes = &dc->current_state->res_ctx.pipe_ctx[i]; - dc->hwss.program_gamut_remap(pipes); - ret = true; - } - } - - return ret; -} - -static bool program_csc_matrix(struct dc *dc, struct dc_stream_state *stream) -{ - int i = 0; - bool ret = false; - struct pipe_ctx *pipes; - - for (i = 0; i < MAX_PIPES; i++) { - if (dc->current_state->res_ctx.pipe_ctx[i].stream - == stream) { - - pipes = &dc->current_state->res_ctx.pipe_ctx[i]; - dc->hwss.program_csc_matrix(pipes, - stream->output_color_space, - stream->csc_color_matrix.matrix); - ret = true; - } - } - - return ret; -} - -static void set_static_screen_events(struct dc *dc, +void dc_stream_set_static_screen_events(struct dc *dc, struct dc_stream_state **streams, int num_streams, const struct dc_static_screen_events *events) @@ -270,177 +239,6 @@ static void set_static_screen_events(struct dc *dc, dc->hwss.set_static_screen_control(pipes_affected, num_pipes_affected, events); } -static void set_drive_settings(struct dc *dc, - struct link_training_settings *lt_settings, - const struct dc_link *link) -{ - - int i; - - for (i = 0; i < dc->link_count; i++) { - if (dc->links[i] == link) - break; - } - - if (i >= dc->link_count) - ASSERT_CRITICAL(false); - - dc_link_dp_set_drive_settings(dc->links[i], lt_settings); -} - -static void perform_link_training(struct dc *dc, - struct dc_link_settings *link_setting, - bool skip_video_pattern) -{ - int i; - - for (i = 0; i < dc->link_count; i++) - dc_link_dp_perform_link_training( - dc->links[i], - link_setting, - skip_video_pattern); -} - -static void set_preferred_link_settings(struct dc *dc, - struct dc_link_settings *link_setting, - struct dc_link *link) -{ - link->preferred_link_setting = *link_setting; - dp_retrain_link_dp_test(link, link_setting, false); -} - -static void enable_hpd(const struct dc_link *link) -{ - dc_link_dp_enable_hpd(link); -} - -static void disable_hpd(const struct dc_link *link) -{ - dc_link_dp_disable_hpd(link); -} - - -static void set_test_pattern( - struct dc_link *link, - enum dp_test_pattern test_pattern, - const struct link_training_settings *p_link_settings, - const unsigned char *p_custom_pattern, - unsigned int cust_pattern_size) -{ - if (link != NULL) - dc_link_dp_set_test_pattern( - link, - test_pattern, - p_link_settings, - p_custom_pattern, - cust_pattern_size); -} - -static void set_dither_option(struct dc_stream_state *stream, - enum dc_dither_option option) -{ - struct bit_depth_reduction_params params; - struct dc_link *link = stream->status.link; - struct pipe_ctx *pipes = NULL; - int i; - - for (i = 0; i < MAX_PIPES; i++) { - if (link->dc->current_state->res_ctx.pipe_ctx[i].stream == - stream) { - pipes = &link->dc->current_state->res_ctx.pipe_ctx[i]; - break; - } - } - - memset(¶ms, 0, sizeof(params)); - if (!pipes) - return; - if (option > DITHER_OPTION_MAX) - return; - - stream->dither_option = option; - - resource_build_bit_depth_reduction_params(stream, - ¶ms); - stream->bit_depth_params = params; - pipes->stream_res.opp->funcs-> - opp_program_bit_depth_reduction(pipes->stream_res.opp, ¶ms); -} - -void set_dpms( - struct dc *dc, - struct dc_stream_state *stream, - bool dpms_off) -{ - struct pipe_ctx *pipe_ctx = NULL; - int i; - - for (i = 0; i < MAX_PIPES; i++) { - if (dc->current_state->res_ctx.pipe_ctx[i].stream == stream) { - pipe_ctx = &dc->current_state->res_ctx.pipe_ctx[i]; - break; - } - } - - if (!pipe_ctx) { - ASSERT(0); - return; - } - - if (stream->dpms_off != dpms_off) { - stream->dpms_off = dpms_off; - if (dpms_off) - core_link_disable_stream(pipe_ctx, - KEEP_ACQUIRED_RESOURCE); - else - core_link_enable_stream(dc->current_state, pipe_ctx); - } -} - -static void allocate_dc_stream_funcs(struct dc *dc) -{ - if (dc->hwss.set_drr != NULL) { - dc->stream_funcs.adjust_vmin_vmax = - stream_adjust_vmin_vmax; - } - - dc->stream_funcs.set_static_screen_events = - set_static_screen_events; - - dc->stream_funcs.get_crtc_position = - stream_get_crtc_position; - - dc->stream_funcs.set_gamut_remap = - set_gamut_remap; - - dc->stream_funcs.program_csc_matrix = - program_csc_matrix; - - dc->stream_funcs.set_dither_option = - set_dither_option; - - dc->stream_funcs.set_dpms = - set_dpms; - - dc->link_funcs.set_drive_settings = - set_drive_settings; - - dc->link_funcs.perform_link_training = - perform_link_training; - - dc->link_funcs.set_preferred_link_settings = - set_preferred_link_settings; - - dc->link_funcs.enable_hpd = - enable_hpd; - - dc->link_funcs.disable_hpd = - disable_hpd; - - dc->link_funcs.set_test_pattern = - set_test_pattern; -} - static void destruct(struct dc *dc) { dc_release_state(dc->current_state); @@ -485,19 +283,17 @@ static bool construct(struct dc *dc, const struct dc_init_data *init_params) { struct dal_logger *logger; - struct dc_context *dc_ctx = kzalloc(sizeof(*dc_ctx), GFP_KERNEL); - struct bw_calcs_dceip *dc_dceip = kzalloc(sizeof(*dc_dceip), - GFP_KERNEL); - struct bw_calcs_vbios *dc_vbios = kzalloc(sizeof(*dc_vbios), - GFP_KERNEL); + struct dc_context *dc_ctx; + struct bw_calcs_dceip *dc_dceip; + struct bw_calcs_vbios *dc_vbios; #ifdef CONFIG_DRM_AMD_DC_DCN1_0 - struct dcn_soc_bounding_box *dcn_soc = kzalloc(sizeof(*dcn_soc), - GFP_KERNEL); - struct dcn_ip_params *dcn_ip = kzalloc(sizeof(*dcn_ip), GFP_KERNEL); + struct dcn_soc_bounding_box *dcn_soc; + struct dcn_ip_params *dcn_ip; #endif enum dce_version dc_version = DCE_VERSION_UNKNOWN; + dc_dceip = kzalloc(sizeof(*dc_dceip), GFP_KERNEL); if (!dc_dceip) { dm_error("%s: failed to create dceip\n", __func__); goto fail; @@ -505,6 +301,7 @@ static bool construct(struct dc *dc, dc->bw_dceip = dc_dceip; + dc_vbios = kzalloc(sizeof(*dc_vbios), GFP_KERNEL); if (!dc_vbios) { dm_error("%s: failed to create vbios\n", __func__); goto fail; @@ -512,6 +309,7 @@ static bool construct(struct dc *dc, dc->bw_vbios = dc_vbios; #ifdef CONFIG_DRM_AMD_DC_DCN1_0 + dcn_soc = kzalloc(sizeof(*dcn_soc), GFP_KERNEL); if (!dcn_soc) { dm_error("%s: failed to create dcn_soc\n", __func__); goto fail; @@ -519,6 +317,7 @@ static bool construct(struct dc *dc, dc->dcn_soc = dcn_soc; + dcn_ip = kzalloc(sizeof(*dcn_ip), GFP_KERNEL); if (!dcn_ip) { dm_error("%s: failed to create dcn_ip\n", __func__); goto fail; @@ -527,11 +326,18 @@ static bool construct(struct dc *dc, dc->dcn_ip = dcn_ip; #endif + dc_ctx = kzalloc(sizeof(*dc_ctx), GFP_KERNEL); if (!dc_ctx) { dm_error("%s: failed to create ctx\n", __func__); goto fail; } + dc_ctx->cgs_device = init_params->cgs_device; + dc_ctx->driver_context = init_params->driver; + dc_ctx->dc = dc; + dc_ctx->asic_id = init_params->asic_id; + dc->ctx = dc_ctx; + dc->current_state = dc_create_state(); if (!dc->current_state) { @@ -539,11 +345,6 @@ static bool construct(struct dc *dc, goto fail; } - dc_ctx->cgs_device = init_params->cgs_device; - dc_ctx->driver_context = init_params->driver; - dc_ctx->dc = dc; - dc_ctx->asic_id = init_params->asic_id; - /* Create logger */ logger = dal_logger_create(dc_ctx, init_params->log_mask); @@ -553,11 +354,11 @@ static bool construct(struct dc *dc, goto fail; } dc_ctx->logger = logger; - dc->ctx = dc_ctx; - dc->ctx->dce_environment = init_params->dce_environment; + dc_ctx->dce_environment = init_params->dce_environment; dc_version = resource_parse_asic_id(init_params->asic_id); - dc->ctx->dce_version = dc_version; + dc_ctx->dce_version = dc_version; + #if defined(CONFIG_DRM_AMD_DC_FBC) dc->ctx->fbc_gpu_addr = init_params->fbc_gpu_addr; #endif @@ -616,8 +417,6 @@ static bool construct(struct dc *dc, if (!create_links(dc, init_params->num_virtual_links)) goto fail; - allocate_dc_stream_funcs(dc); - return true; fail: @@ -686,6 +485,7 @@ struct dc *dc_create(const struct dc_init_data *init_params) dc->caps.max_links = dc->link_count; dc->caps.max_audios = dc->res_pool->audio_count; + dc->caps.linear_pitch_alignment = 64; dc->config = init_params->flags; @@ -712,6 +512,28 @@ void dc_destroy(struct dc **dc) *dc = NULL; } +static void enable_timing_multisync( + struct dc *dc, + struct dc_state *ctx) +{ + int i = 0, multisync_count = 0; + int pipe_count = dc->res_pool->pipe_count; + struct pipe_ctx *multisync_pipes[MAX_PIPES] = { NULL }; + + for (i = 0; i < pipe_count; i++) { + if (!ctx->res_ctx.pipe_ctx[i].stream || + !ctx->res_ctx.pipe_ctx[i].stream->triggered_crtc_reset.enabled) + continue; + multisync_pipes[multisync_count] = &ctx->res_ctx.pipe_ctx[i]; + multisync_count++; + } + + if (multisync_count > 1) { + dc->hwss.enable_per_frame_crtc_position_reset( + dc, multisync_count, multisync_pipes); + } +} + static void program_timing_sync( struct dc *dc, struct dc_state *ctx) @@ -758,7 +580,7 @@ static void program_timing_sync( for (j = 0; j < group_size; j++) { struct pipe_ctx *temp; - if (!pipe_set[j]->stream_res.tg->funcs->is_blanked(pipe_set[j]->stream_res.tg)) { + if (pipe_set[j]->stream_res.tg->funcs->is_blanked && !pipe_set[j]->stream_res.tg->funcs->is_blanked(pipe_set[j]->stream_res.tg)) { if (j == 0) break; @@ -771,7 +593,7 @@ static void program_timing_sync( /* remove any other unblanked pipes as they have already been synced */ for (j = j + 1; j < group_size; j++) { - if (!pipe_set[j]->stream_res.tg->funcs->is_blanked(pipe_set[j]->stream_res.tg)) { + if (pipe_set[j]->stream_res.tg->funcs->is_blanked && !pipe_set[j]->stream_res.tg->funcs->is_blanked(pipe_set[j]->stream_res.tg)) { group_size--; pipe_set[j] = pipe_set[group_size]; j--; @@ -838,7 +660,7 @@ static enum dc_status dc_commit_state_no_check(struct dc *dc, struct dc_state *c struct dc_bios *dcb = dc->ctx->dc_bios; enum dc_status result = DC_ERROR_UNEXPECTED; struct pipe_ctx *pipe; - int i, j, k, l; + int i, k, l; struct dc_stream_state *dc_streams[MAX_STREAMS] = {0}; disable_dangling_plane(dc, context); @@ -849,9 +671,44 @@ static enum dc_status dc_commit_state_no_check(struct dc *dc, struct dc_state *c if (!dcb->funcs->is_accelerated_mode(dcb)) dc->hwss.enable_accelerated_mode(dc); + /* re-program planes for existing stream, in case we need to + * free up plane resource for later use + */ + for (i = 0; i < context->stream_count; i++) { + if (context->streams[i]->mode_changed) + continue; + + dc->hwss.apply_ctx_for_surface( + dc, context->streams[i], + context->stream_status[i].plane_count, + context); /* use new pipe config in new context */ + } + + /* Program hardware */ + dc->hwss.ready_shared_resources(dc, context); + + for (i = 0; i < dc->res_pool->pipe_count; i++) { + pipe = &context->res_ctx.pipe_ctx[i]; + dc->hwss.wait_for_mpcc_disconnect(dc, dc->res_pool, pipe); + } + + result = dc->hwss.apply_ctx_to_hw(dc, context); + + if (result != DC_OK) + return result; + + if (context->stream_count > 1) { + enable_timing_multisync(dc, context); + program_timing_sync(dc, context); + } + + /* Program all planes within new context*/ for (i = 0; i < context->stream_count; i++) { const struct dc_sink *sink = context->streams[i]->sink; + if (!context->streams[i]->mode_changed) + continue; + dc->hwss.apply_ctx_for_surface( dc, context->streams[i], context->stream_status[i].plane_count, @@ -880,27 +737,8 @@ static enum dc_status dc_commit_state_no_check(struct dc *dc, struct dc_state *c context->streams[i]->timing.pix_clk_khz); } - dc->hwss.ready_shared_resources(dc, context); - - for (i = 0; i < dc->res_pool->pipe_count; i++) { - pipe = &context->res_ctx.pipe_ctx[i]; - dc->hwss.wait_for_mpcc_disconnect(dc, dc->res_pool, pipe); - } - result = dc->hwss.apply_ctx_to_hw(dc, context); - - program_timing_sync(dc, context); - dc_enable_stereo(dc, context, dc_streams, context->stream_count); - for (i = 0; i < context->stream_count; i++) { - for (j = 0; j < MAX_PIPES; j++) { - pipe = &context->res_ctx.pipe_ctx[j]; - - if (!pipe->top_pipe && pipe->stream == context->streams[i]) - dc->hwss.pipe_control_lock(dc, pipe, false); - } - } - dc_release_state(dc->current_state); dc->current_state = context; @@ -936,7 +774,6 @@ bool dc_commit_state(struct dc *dc, struct dc_state *context) return (result == DC_OK); } - bool dc_post_update_surfaces_to_stream(struct dc *dc) { int i; @@ -945,9 +782,13 @@ bool dc_post_update_surfaces_to_stream(struct dc *dc) post_surface_trace(dc); for (i = 0; i < dc->res_pool->pipe_count; i++) - if (context->res_ctx.pipe_ctx[i].stream == NULL - || context->res_ctx.pipe_ctx[i].plane_state == NULL) - dc->hwss.power_down_front_end(dc, i); + if (context->res_ctx.pipe_ctx[i].stream == NULL || + context->res_ctx.pipe_ctx[i].plane_state == NULL) { + context->res_ctx.pipe_ctx[i].pipe_idx = i; + dc->hwss.disable_plane(dc, &context->res_ctx.pipe_ctx[i]); + } + + dc->optimized_required = false; /* 3rd param should be true, temp w/a for RV*/ #if defined(CONFIG_DRM_AMD_DC_DCN1_0) @@ -1014,6 +855,7 @@ bool dc_commit_planes_to_stream( flip_addr[i].address = plane_states[i]->address; flip_addr[i].flip_immediate = plane_states[i]->flip_immediate; plane_info[i].color_space = plane_states[i]->color_space; + plane_info[i].input_tf = plane_states[i]->input_tf; plane_info[i].format = plane_states[i]->format; plane_info[i].plane_size = plane_states[i]->plane_size; plane_info[i].rotation = plane_states[i]->rotation; @@ -1118,79 +960,96 @@ static unsigned int pixel_format_to_bpp(enum surface_pixel_format format) } } -static enum surface_update_type get_plane_info_update_type( - const struct dc_surface_update *u, - int surface_index) +static enum surface_update_type get_plane_info_update_type(const struct dc_surface_update *u) { - struct dc_plane_info temp_plane_info; - memset(&temp_plane_info, 0, sizeof(temp_plane_info)); + union surface_update_flags *update_flags = &u->surface->update_flags; if (!u->plane_info) return UPDATE_TYPE_FAST; - temp_plane_info = *u->plane_info; + if (u->plane_info->color_space != u->surface->color_space) + update_flags->bits.color_space_change = 1; - /* Copy all parameters that will cause a full update - * from current surface, the rest of the parameters - * from provided plane configuration. - * Perform memory compare and special validation - * for those that can cause fast/medium updates - */ + if (u->plane_info->input_tf != u->surface->input_tf) + update_flags->bits.input_tf_change = 1; - /* Full update parameters */ - temp_plane_info.color_space = u->surface->color_space; - temp_plane_info.dcc = u->surface->dcc; - temp_plane_info.horizontal_mirror = u->surface->horizontal_mirror; - temp_plane_info.plane_size = u->surface->plane_size; - temp_plane_info.rotation = u->surface->rotation; - temp_plane_info.stereo_format = u->surface->stereo_format; - - if (surface_index == 0) - temp_plane_info.visible = u->plane_info->visible; - else - temp_plane_info.visible = u->surface->visible; - - if (memcmp(u->plane_info, &temp_plane_info, - sizeof(struct dc_plane_info)) != 0) - return UPDATE_TYPE_FULL; + if (u->plane_info->horizontal_mirror != u->surface->horizontal_mirror) + update_flags->bits.horizontal_mirror_change = 1; + + if (u->plane_info->rotation != u->surface->rotation) + update_flags->bits.rotation_change = 1; + + if (u->plane_info->stereo_format != u->surface->stereo_format) + update_flags->bits.stereo_format_change = 1; + + if (u->plane_info->per_pixel_alpha != u->surface->per_pixel_alpha) + update_flags->bits.per_pixel_alpha_change = 1; + + if (u->plane_info->dcc.enable != u->surface->dcc.enable + || u->plane_info->dcc.grph.independent_64b_blks != u->surface->dcc.grph.independent_64b_blks + || u->plane_info->dcc.grph.meta_pitch != u->surface->dcc.grph.meta_pitch) + update_flags->bits.dcc_change = 1; if (pixel_format_to_bpp(u->plane_info->format) != - pixel_format_to_bpp(u->surface->format)) { + pixel_format_to_bpp(u->surface->format)) /* different bytes per element will require full bandwidth * and DML calculation */ - return UPDATE_TYPE_FULL; - } + update_flags->bits.bpp_change = 1; if (memcmp(&u->plane_info->tiling_info, &u->surface->tiling_info, sizeof(union dc_tiling_info)) != 0) { + update_flags->bits.swizzle_change = 1; /* todo: below are HW dependent, we should add a hook to * DCE/N resource and validated there. */ - if (u->plane_info->tiling_info.gfx9.swizzle != DC_SW_LINEAR) { + if (u->plane_info->tiling_info.gfx9.swizzle != DC_SW_LINEAR) /* swizzled mode requires RQ to be setup properly, * thus need to run DML to calculate RQ settings */ - return UPDATE_TYPE_FULL; - } + update_flags->bits.bandwidth_change = 1; } + if (update_flags->bits.rotation_change + || update_flags->bits.stereo_format_change + || update_flags->bits.bpp_change + || update_flags->bits.bandwidth_change) + return UPDATE_TYPE_FULL; + return UPDATE_TYPE_MED; } -static enum surface_update_type get_scaling_info_update_type( +static enum surface_update_type get_scaling_info_update_type( const struct dc_surface_update *u) { + union surface_update_flags *update_flags = &u->surface->update_flags; + if (!u->scaling_info) return UPDATE_TYPE_FAST; - if (u->scaling_info->src_rect.width != u->surface->src_rect.width - || u->scaling_info->src_rect.height != u->surface->src_rect.height - || u->scaling_info->clip_rect.width != u->surface->clip_rect.width + if (u->scaling_info->clip_rect.width != u->surface->clip_rect.width || u->scaling_info->clip_rect.height != u->surface->clip_rect.height || u->scaling_info->dst_rect.width != u->surface->dst_rect.width - || u->scaling_info->dst_rect.height != u->surface->dst_rect.height) - return UPDATE_TYPE_FULL; + || u->scaling_info->dst_rect.height != u->surface->dst_rect.height) { + update_flags->bits.scaling_change = 1; + + if ((u->scaling_info->dst_rect.width < u->surface->dst_rect.width + || u->scaling_info->dst_rect.height < u->surface->dst_rect.height) + && (u->scaling_info->dst_rect.width < u->surface->src_rect.width + || u->scaling_info->dst_rect.height < u->surface->src_rect.height)) + /* Making dst rect smaller requires a bandwidth change */ + update_flags->bits.bandwidth_change = 1; + } + + if (u->scaling_info->src_rect.width != u->surface->src_rect.width + || u->scaling_info->src_rect.height != u->surface->src_rect.height) { + + update_flags->bits.scaling_change = 1; + if (u->scaling_info->src_rect.width > u->surface->src_rect.width + && u->scaling_info->src_rect.height > u->surface->src_rect.height) + /* Making src rect bigger requires a bandwidth change */ + update_flags->bits.clock_change = 1; + } if (u->scaling_info->src_rect.x != u->surface->src_rect.x || u->scaling_info->src_rect.y != u->surface->src_rect.y @@ -1198,41 +1057,56 @@ static enum surface_update_type get_scaling_info_update_type( || u->scaling_info->clip_rect.y != u->surface->clip_rect.y || u->scaling_info->dst_rect.x != u->surface->dst_rect.x || u->scaling_info->dst_rect.y != u->surface->dst_rect.y) + update_flags->bits.position_change = 1; + + if (update_flags->bits.clock_change + || update_flags->bits.bandwidth_change) + return UPDATE_TYPE_FULL; + + if (update_flags->bits.scaling_change + || update_flags->bits.position_change) return UPDATE_TYPE_MED; return UPDATE_TYPE_FAST; } -static enum surface_update_type det_surface_update( - const struct dc *dc, - const struct dc_surface_update *u, - int surface_index) +static enum surface_update_type det_surface_update(const struct dc *dc, + const struct dc_surface_update *u) { const struct dc_state *context = dc->current_state; - enum surface_update_type type = UPDATE_TYPE_FAST; + enum surface_update_type type; enum surface_update_type overall_type = UPDATE_TYPE_FAST; + union surface_update_flags *update_flags = &u->surface->update_flags; + + update_flags->raw = 0; // Reset all flags - if (!is_surface_in_context(context, u->surface)) + if (!is_surface_in_context(context, u->surface)) { + update_flags->bits.new_plane = 1; return UPDATE_TYPE_FULL; + } - type = get_plane_info_update_type(u, surface_index); - if (overall_type < type) - overall_type = type; + type = get_plane_info_update_type(u); + elevate_update_type(&overall_type, type); type = get_scaling_info_update_type(u); - if (overall_type < type) - overall_type = type; + elevate_update_type(&overall_type, type); + + if (u->in_transfer_func) + update_flags->bits.in_transfer_func = 1; - if (u->in_transfer_func || - u->hdr_static_metadata) { - if (overall_type < UPDATE_TYPE_MED) - overall_type = UPDATE_TYPE_MED; + if (u->input_csc_color_matrix) + update_flags->bits.input_csc_change = 1; + + if (update_flags->bits.in_transfer_func + || update_flags->bits.input_csc_change) { + type = UPDATE_TYPE_MED; + elevate_update_type(&overall_type, type); } return overall_type; } -enum surface_update_type dc_check_update_surfaces_for_stream( +static enum surface_update_type check_update_surfaces_for_stream( struct dc *dc, struct dc_surface_update *updates, int surface_count, @@ -1250,18 +1124,38 @@ enum surface_update_type dc_check_update_surfaces_for_stream( for (i = 0 ; i < surface_count; i++) { enum surface_update_type type = - det_surface_update(dc, &updates[i], i); + det_surface_update(dc, &updates[i]); if (type == UPDATE_TYPE_FULL) return type; - if (overall_type < type) - overall_type = type; + elevate_update_type(&overall_type, type); } return overall_type; } +enum surface_update_type dc_check_update_surfaces_for_stream( + struct dc *dc, + struct dc_surface_update *updates, + int surface_count, + struct dc_stream_update *stream_update, + const struct dc_stream_status *stream_status) +{ + int i; + enum surface_update_type type; + + for (i = 0; i < surface_count; i++) + updates[i].surface->update_flags.raw = 0; + + type = check_update_surfaces_for_stream(dc, updates, surface_count, stream_update, stream_status); + if (type == UPDATE_TYPE_FULL) + for (i = 0; i < surface_count; i++) + updates[i].surface->update_flags.bits.full_update = 1; + + return type; +} + static struct dc_stream_status *stream_get_status( struct dc_state *ctx, struct dc_stream_state *stream) @@ -1295,14 +1189,6 @@ static void commit_planes_for_stream(struct dc *dc, context_clock_trace(dc, context); } - if (update_type > UPDATE_TYPE_FAST) { - for (j = 0; j < dc->res_pool->pipe_count; j++) { - struct pipe_ctx *pipe_ctx = &context->res_ctx.pipe_ctx[j]; - - dc->hwss.wait_for_mpcc_disconnect(dc, dc->res_pool, pipe_ctx); - } - } - if (surface_count == 0) { /* * In case of turning off screen, no need to program front end a second time. @@ -1312,103 +1198,58 @@ static void commit_planes_for_stream(struct dc *dc, return; } - /* Lock pipes for provided surfaces, or all active if full update*/ - for (i = 0; i < surface_count; i++) { - struct dc_plane_state *plane_state = srf_updates[i].surface; - - for (j = 0; j < dc->res_pool->pipe_count; j++) { - struct pipe_ctx *pipe_ctx = &context->res_ctx.pipe_ctx[j]; - - if (update_type != UPDATE_TYPE_FULL && pipe_ctx->plane_state != plane_state) - continue; - if (!pipe_ctx->plane_state || pipe_ctx->top_pipe) - continue; - - dc->hwss.pipe_control_lock( - dc, - pipe_ctx, - true); - } - if (update_type == UPDATE_TYPE_FULL) - break; - } - /* Full fe update*/ for (j = 0; j < dc->res_pool->pipe_count; j++) { struct pipe_ctx *pipe_ctx = &context->res_ctx.pipe_ctx[j]; - if (update_type != UPDATE_TYPE_FULL || !pipe_ctx->plane_state) + if (update_type == UPDATE_TYPE_FAST || !pipe_ctx->plane_state) continue; - if (!pipe_ctx->top_pipe && pipe_ctx->stream) { - struct dc_stream_status *stream_status = stream_get_status(context, pipe_ctx->stream); + if (!pipe_ctx->top_pipe && + pipe_ctx->stream && + pipe_ctx->stream == stream) { + struct dc_stream_status *stream_status = + stream_get_status(context, pipe_ctx->stream); dc->hwss.apply_ctx_for_surface( dc, pipe_ctx->stream, stream_status->plane_count, context); } } - if (update_type > UPDATE_TYPE_FAST) + if (update_type == UPDATE_TYPE_FULL) context_timing_trace(dc, &context->res_ctx); /* Perform requested Updates */ for (i = 0; i < surface_count; i++) { struct dc_plane_state *plane_state = srf_updates[i].surface; - if (update_type == UPDATE_TYPE_MED) - dc->hwss.apply_ctx_for_surface( - dc, stream, surface_count, context); - for (j = 0; j < dc->res_pool->pipe_count; j++) { struct pipe_ctx *pipe_ctx = &context->res_ctx.pipe_ctx[j]; - if (pipe_ctx->plane_state != plane_state) + if (pipe_ctx->stream != stream) continue; - if (srf_updates[i].flip_addr) - dc->hwss.update_plane_addr(dc, pipe_ctx); - - if (update_type == UPDATE_TYPE_FAST) + if (pipe_ctx->plane_state != plane_state) continue; - /* work around to program degamma regs for split pipe after set mode. */ - if (srf_updates[i].in_transfer_func || (pipe_ctx->top_pipe && - pipe_ctx->top_pipe->plane_state == pipe_ctx->plane_state)) - dc->hwss.set_input_transfer_func( - pipe_ctx, pipe_ctx->plane_state); - - if (stream_update != NULL && - stream_update->out_transfer_func != NULL) { - dc->hwss.set_output_transfer_func( - pipe_ctx, pipe_ctx->stream); - } - - if (srf_updates[i].hdr_static_metadata) { - resource_build_info_frame(pipe_ctx); - dc->hwss.update_info_frame(pipe_ctx); - } + if (update_type == UPDATE_TYPE_FAST && srf_updates[i].flip_addr) + dc->hwss.update_plane_addr(dc, pipe_ctx); } } - /* Unlock pipes */ - for (i = dc->res_pool->pipe_count - 1; i >= 0; i--) { - struct pipe_ctx *pipe_ctx = &context->res_ctx.pipe_ctx[i]; + if (stream && stream_update && update_type > UPDATE_TYPE_FAST) + for (j = 0; j < dc->res_pool->pipe_count; j++) { + struct pipe_ctx *pipe_ctx = + &context->res_ctx.pipe_ctx[j]; - for (j = 0; j < surface_count; j++) { - if (update_type != UPDATE_TYPE_FULL && - srf_updates[j].surface != pipe_ctx->plane_state) - continue; - if (!pipe_ctx->plane_state || pipe_ctx->top_pipe) + if (pipe_ctx->stream != stream) continue; - dc->hwss.pipe_control_lock( - dc, - pipe_ctx, - false); - - break; + if (stream_update->hdr_static_metadata) { + resource_build_info_frame(pipe_ctx); + dc->hwss.update_info_frame(pipe_ctx); + } } - } } void dc_commit_updates_for_stream(struct dc *dc, @@ -1480,10 +1321,7 @@ void dc_commit_updates_for_stream(struct dc *dc, stream_update, update_type, context); - - if (update_type >= UPDATE_TYPE_FULL) - dc_post_update_surfaces_to_stream(dc); - + /*update current_State*/ if (dc->current_state != context) { struct dc_state *old = dc->current_state; @@ -1492,6 +1330,9 @@ void dc_commit_updates_for_stream(struct dc *dc, dc_release_state(old); } + /*let's use current_state to update watermark etc*/ + if (update_type >= UPDATE_TYPE_FULL) + dc_post_update_surfaces_to_stream(dc); return; diff --git a/drivers/gpu/drm/amd/display/dc/core/dc_debug.c b/drivers/gpu/drm/amd/display/dc/core/dc_debug.c index 43c7a7fddb83..1babac07bcc9 100644 --- a/drivers/gpu/drm/amd/display/dc/core/dc_debug.c +++ b/drivers/gpu/drm/amd/display/dc/core/dc_debug.c @@ -159,6 +159,7 @@ void pre_surface_trace( "plane_state->tiling_info.gfx8.pipe_config = %d;\n" "plane_state->tiling_info.gfx8.array_mode = %d;\n" "plane_state->color_space = %d;\n" + "plane_state->input_tf = %d;\n" "plane_state->dcc.enable = %d;\n" "plane_state->format = %d;\n" "plane_state->rotation = %d;\n" @@ -166,6 +167,7 @@ void pre_surface_trace( plane_state->tiling_info.gfx8.pipe_config, plane_state->tiling_info.gfx8.array_mode, plane_state->color_space, + plane_state->input_tf, plane_state->dcc.enable, plane_state->format, plane_state->rotation, @@ -206,6 +208,7 @@ void update_surface_trace( if (update->plane_info) { SURFACE_TRACE( "plane_info->color_space = %d;\n" + "plane_info->input_tf = %d;\n" "plane_info->format = %d;\n" "plane_info->plane_size.grph.surface_pitch = %d;\n" "plane_info->plane_size.grph.surface_size.height = %d;\n" @@ -214,6 +217,7 @@ void update_surface_trace( "plane_info->plane_size.grph.surface_size.y = %d;\n" "plane_info->rotation = %d;\n", update->plane_info->color_space, + update->plane_info->input_tf, update->plane_info->format, update->plane_info->plane_size.grph.surface_pitch, update->plane_info->plane_size.grph.surface_size.height, diff --git a/drivers/gpu/drm/amd/display/dc/core/dc_hw_sequencer.c b/drivers/gpu/drm/amd/display/dc/core/dc_hw_sequencer.c index 71993d5983bf..ebc96b720083 100644 --- a/drivers/gpu/drm/amd/display/dc/core/dc_hw_sequencer.c +++ b/drivers/gpu/drm/amd/display/dc/core/dc_hw_sequencer.c @@ -28,6 +28,8 @@ #include "timing_generator.h" #include "hw_sequencer.h" +#define NUM_ELEMENTS(a) (sizeof(a) / sizeof((a)[0])) + /* used as index in array of black_color_format */ enum black_color_format { BLACK_COLOR_FORMAT_RGB_FULLRANGE = 0, @@ -38,6 +40,15 @@ enum black_color_format { BLACK_COLOR_FORMAT_DEBUG, }; +enum dc_color_space_type { + COLOR_SPACE_RGB_TYPE, + COLOR_SPACE_RGB_LIMITED_TYPE, + COLOR_SPACE_YCBCR601_TYPE, + COLOR_SPACE_YCBCR709_TYPE, + COLOR_SPACE_YCBCR601_LIMITED_TYPE, + COLOR_SPACE_YCBCR709_LIMITED_TYPE +}; + static const struct tg_color black_color_format[] = { /* BlackColorFormat_RGB_FullRange */ {0, 0, 0}, @@ -53,6 +64,140 @@ static const struct tg_color black_color_format[] = { {0xff, 0xff, 0}, }; +struct out_csc_color_matrix_type { + enum dc_color_space_type color_space_type; + uint16_t regval[12]; +}; + +static const struct out_csc_color_matrix_type output_csc_matrix[] = { + { COLOR_SPACE_RGB_TYPE, + { 0x2000, 0, 0, 0, 0, 0x2000, 0, 0, 0, 0, 0x2000, 0} }, + { COLOR_SPACE_RGB_LIMITED_TYPE, + { 0x1B67, 0, 0, 0x201, 0, 0x1B67, 0, 0x201, 0, 0, 0x1B67, 0x201} }, + { COLOR_SPACE_YCBCR601_TYPE, + { 0xE04, 0xF444, 0xFDB9, 0x1004, 0x831, 0x1016, 0x320, 0x201, 0xFB45, + 0xF6B7, 0xE04, 0x1004} }, + { COLOR_SPACE_YCBCR709_TYPE, + { 0xE04, 0xF345, 0xFEB7, 0x1004, 0x5D3, 0x1399, 0x1FA, + 0x201, 0xFCCA, 0xF533, 0xE04, 0x1004} }, + + /* TODO: correct values below */ + { COLOR_SPACE_YCBCR601_LIMITED_TYPE, + { 0xE00, 0xF447, 0xFDB9, 0x1000, 0x991, + 0x12C9, 0x3A6, 0x200, 0xFB47, 0xF6B9, 0xE00, 0x1000} }, + { COLOR_SPACE_YCBCR709_LIMITED_TYPE, + { 0xE00, 0xF349, 0xFEB7, 0x1000, 0x6CE, 0x16E3, + 0x24F, 0x200, 0xFCCB, 0xF535, 0xE00, 0x1000} }, +}; + +static bool is_rgb_type( + enum dc_color_space color_space) +{ + bool ret = false; + + if (color_space == COLOR_SPACE_SRGB || + color_space == COLOR_SPACE_XR_RGB || + color_space == COLOR_SPACE_MSREF_SCRGB || + color_space == COLOR_SPACE_2020_RGB_FULLRANGE || + color_space == COLOR_SPACE_ADOBERGB || + color_space == COLOR_SPACE_DCIP3 || + color_space == COLOR_SPACE_DOLBYVISION) + ret = true; + return ret; +} + +static bool is_rgb_limited_type( + enum dc_color_space color_space) +{ + bool ret = false; + + if (color_space == COLOR_SPACE_SRGB_LIMITED || + color_space == COLOR_SPACE_2020_RGB_LIMITEDRANGE) + ret = true; + return ret; +} + +static bool is_ycbcr601_type( + enum dc_color_space color_space) +{ + bool ret = false; + + if (color_space == COLOR_SPACE_YCBCR601 || + color_space == COLOR_SPACE_XV_YCC_601) + ret = true; + return ret; +} + +static bool is_ycbcr601_limited_type( + enum dc_color_space color_space) +{ + bool ret = false; + + if (color_space == COLOR_SPACE_YCBCR601_LIMITED) + ret = true; + return ret; +} + +static bool is_ycbcr709_type( + enum dc_color_space color_space) +{ + bool ret = false; + + if (color_space == COLOR_SPACE_YCBCR709 || + color_space == COLOR_SPACE_XV_YCC_709) + ret = true; + return ret; +} + +static bool is_ycbcr709_limited_type( + enum dc_color_space color_space) +{ + bool ret = false; + + if (color_space == COLOR_SPACE_YCBCR709_LIMITED) + ret = true; + return ret; +} +enum dc_color_space_type get_color_space_type(enum dc_color_space color_space) +{ + enum dc_color_space_type type = COLOR_SPACE_RGB_TYPE; + + if (is_rgb_type(color_space)) + type = COLOR_SPACE_RGB_TYPE; + else if (is_rgb_limited_type(color_space)) + type = COLOR_SPACE_RGB_LIMITED_TYPE; + else if (is_ycbcr601_type(color_space)) + type = COLOR_SPACE_YCBCR601_TYPE; + else if (is_ycbcr709_type(color_space)) + type = COLOR_SPACE_YCBCR709_TYPE; + else if (is_ycbcr601_limited_type(color_space)) + type = COLOR_SPACE_YCBCR601_LIMITED_TYPE; + else if (is_ycbcr709_limited_type(color_space)) + type = COLOR_SPACE_YCBCR709_LIMITED_TYPE; + + return type; +} + +const uint16_t *find_color_matrix(enum dc_color_space color_space, + uint32_t *array_size) +{ + int i; + enum dc_color_space_type type; + const uint16_t *val = NULL; + int arr_size = NUM_ELEMENTS(output_csc_matrix); + + type = get_color_space_type(color_space); + for (i = 0; i < arr_size; i++) + if (output_csc_matrix[i].color_space_type == type) { + val = output_csc_matrix[i].regval; + *array_size = 12; + break; + } + + return val; +} + + void color_space_to_black_color( const struct dc *dc, enum dc_color_space colorspace, diff --git a/drivers/gpu/drm/amd/display/dc/core/dc_link.c b/drivers/gpu/drm/amd/display/dc/core/dc_link.c index 42a111b9505d..a37428271573 100644 --- a/drivers/gpu/drm/amd/display/dc/core/dc_link.c +++ b/drivers/gpu/drm/amd/display/dc/core/dc_link.c @@ -938,8 +938,9 @@ static bool construct( link->link_id = bios->funcs->get_connector_id(bios, init_params->connector_index); if (link->link_id.type != OBJECT_TYPE_CONNECTOR) { - dm_error("%s: Invalid Connector ObjectID from Adapter Service for connector index:%d!\n", - __func__, init_params->connector_index); + dm_error("%s: Invalid Connector ObjectID from Adapter Service for connector index:%d! type %d expected %d\n", + __func__, init_params->connector_index, + link->link_id.type, OBJECT_TYPE_CONNECTOR); goto create_fail; } @@ -1271,6 +1272,24 @@ static enum dc_status enable_link_dp( return status; } +static enum dc_status enable_link_edp( + struct dc_state *state, + struct pipe_ctx *pipe_ctx) +{ + enum dc_status status; + struct dc_stream_state *stream = pipe_ctx->stream; + struct dc_link *link = stream->sink->link; + + link->dc->hwss.edp_power_control(link, true); + link->dc->hwss.edp_wait_for_hpd_ready(link, true); + + status = enable_link_dp(state, pipe_ctx); + + link->dc->hwss.edp_backlight_control(link, true); + + return status; +} + static enum dc_status enable_link_dp_mst( struct dc_state *state, struct pipe_ctx *pipe_ctx) @@ -1746,9 +1765,11 @@ static enum dc_status enable_link( enum dc_status status = DC_ERROR_UNEXPECTED; switch (pipe_ctx->stream->signal) { case SIGNAL_TYPE_DISPLAY_PORT: - case SIGNAL_TYPE_EDP: status = enable_link_dp(state, pipe_ctx); break; + case SIGNAL_TYPE_EDP: + status = enable_link_edp(state, pipe_ctx); + break; case SIGNAL_TYPE_DISPLAY_PORT_MST: status = enable_link_dp_mst(state, pipe_ctx); msleep(200); @@ -1798,7 +1819,7 @@ static void disable_link(struct dc_link *link, enum signal_type signal) else dp_disable_link_phy_mst(link, signal); } else - link->link_enc->funcs->disable_output(link->link_enc, signal, link); + link->link_enc->funcs->disable_output(link->link_enc, signal); } static bool dp_active_dongle_validate_timing( @@ -1871,7 +1892,7 @@ enum dc_status dc_link_validate_mode_timing( const struct dc_crtc_timing *timing) { uint32_t max_pix_clk = stream->sink->dongle_max_pix_clk; - struct dc_dongle_caps *dongle_caps = &link->link_status.dpcd_caps->dongle_caps; + struct dc_dongle_caps *dongle_caps = &link->dpcd_caps.dongle_caps; /* A hack to avoid failing any modes for EDID override feature on * topology change such as lower quality cable for DP or different dongle @@ -1909,12 +1930,18 @@ bool dc_link_set_backlight_level(const struct dc_link *link, uint32_t level, { struct dc *core_dc = link->ctx->dc; struct abm *abm = core_dc->res_pool->abm; + struct dmcu *dmcu = core_dc->res_pool->dmcu; unsigned int controller_id = 0; + bool use_smooth_brightness = true; int i; - if ((abm == NULL) || (abm->funcs->set_backlight_level == NULL)) + if ((dmcu == NULL) || + (abm == NULL) || + (abm->funcs->set_backlight_level == NULL)) return false; + use_smooth_brightness = dmcu->funcs->is_dmcu_initialized(dmcu); + dm_logger_write(link->ctx->logger, LOG_BACKLIGHT, "New Backlight level: %d (0x%X)\n", level, level); @@ -1937,7 +1964,8 @@ bool dc_link_set_backlight_level(const struct dc_link *link, uint32_t level, abm, level, frame_ramp, - controller_id); + controller_id, + use_smooth_brightness); } return true; @@ -1954,144 +1982,6 @@ bool dc_link_set_psr_enable(const struct dc_link *link, bool enable, bool wait) return true; } -bool dc_link_get_psr_state(const struct dc_link *link, uint32_t *psr_state) -{ - struct dc *core_dc = link->ctx->dc; - struct dmcu *dmcu = core_dc->res_pool->dmcu; - - if (dmcu != NULL && link->psr_enabled) - dmcu->funcs->get_psr_state(dmcu, psr_state); - - return true; -} - -bool dc_link_setup_psr(struct dc_link *link, - const struct dc_stream_state *stream, struct psr_config *psr_config, - struct psr_context *psr_context) -{ - struct dc *core_dc = link->ctx->dc; - struct dmcu *dmcu = core_dc->res_pool->dmcu; - int i; - - psr_context->controllerId = CONTROLLER_ID_UNDEFINED; - - if (link != NULL && - dmcu != NULL) { - /* updateSinkPsrDpcdConfig*/ - union dpcd_psr_configuration psr_configuration; - - memset(&psr_configuration, 0, sizeof(psr_configuration)); - - psr_configuration.bits.ENABLE = 1; - psr_configuration.bits.CRC_VERIFICATION = 1; - psr_configuration.bits.FRAME_CAPTURE_INDICATION = - psr_config->psr_frame_capture_indication_req; - - /* Check for PSR v2*/ - if (psr_config->psr_version == 0x2) { - /* For PSR v2 selective update. - * Indicates whether sink should start capturing - * immediately following active scan line, - * or starting with the 2nd active scan line. - */ - psr_configuration.bits.LINE_CAPTURE_INDICATION = 0; - /*For PSR v2, determines whether Sink should generate - * IRQ_HPD when CRC mismatch is detected. - */ - psr_configuration.bits.IRQ_HPD_WITH_CRC_ERROR = 1; - } - - dm_helpers_dp_write_dpcd( - link->ctx, - link, - 368, - &psr_configuration.raw, - sizeof(psr_configuration.raw)); - - psr_context->channel = link->ddc->ddc_pin->hw_info.ddc_channel; - psr_context->transmitterId = link->link_enc->transmitter; - psr_context->engineId = link->link_enc->preferred_engine; - - for (i = 0; i < MAX_PIPES; i++) { - if (core_dc->current_state->res_ctx.pipe_ctx[i].stream - == stream) { - /* dmcu -1 for all controller id values, - * therefore +1 here - */ - psr_context->controllerId = - core_dc->current_state->res_ctx. - pipe_ctx[i].stream_res.tg->inst + 1; - break; - } - } - - /* Hardcoded for now. Can be Pcie or Uniphy (or Unknown)*/ - psr_context->phyType = PHY_TYPE_UNIPHY; - /*PhyId is associated with the transmitter id*/ - psr_context->smuPhyId = link->link_enc->transmitter; - - psr_context->crtcTimingVerticalTotal = stream->timing.v_total; - psr_context->vsyncRateHz = div64_u64(div64_u64((stream-> - timing.pix_clk_khz * 1000), - stream->timing.v_total), - stream->timing.h_total); - - psr_context->psrSupportedDisplayConfig = true; - psr_context->psrExitLinkTrainingRequired = - psr_config->psr_exit_link_training_required; - psr_context->sdpTransmitLineNumDeadline = - psr_config->psr_sdp_transmit_line_num_deadline; - psr_context->psrFrameCaptureIndicationReq = - psr_config->psr_frame_capture_indication_req; - - psr_context->skipPsrWaitForPllLock = 0; /* only = 1 in KV */ - - psr_context->numberOfControllers = - link->dc->res_pool->res_cap->num_timing_generator; - - psr_context->rfb_update_auto_en = true; - - /* 2 frames before enter PSR. */ - psr_context->timehyst_frames = 2; - /* half a frame - * (units in 100 lines, i.e. a value of 1 represents 100 lines) - */ - psr_context->hyst_lines = stream->timing.v_total / 2 / 100; - psr_context->aux_repeats = 10; - - psr_context->psr_level.u32all = 0; - -#if defined(CONFIG_DRM_AMD_DC_DCN1_0) - /*skip power down the single pipe since it blocks the cstate*/ - if (ASIC_REV_IS_RAVEN(link->ctx->asic_id.hw_internal_rev)) - psr_context->psr_level.bits.SKIP_CRTC_DISABLE = true; -#endif - - /* SMU will perform additional powerdown sequence. - * For unsupported ASICs, set psr_level flag to skip PSR - * static screen notification to SMU. - * (Always set for DAL2, did not check ASIC) - */ - psr_context->psr_level.bits.SKIP_SMU_NOTIFICATION = 1; - - /* Complete PSR entry before aborting to prevent intermittent - * freezes on certain eDPs - */ - psr_context->psr_level.bits.DISABLE_PSR_ENTRY_ABORT = 1; - - /* Controls additional delay after remote frame capture before - * continuing power down, default = 0 - */ - psr_context->frame_delay = 0; - - link->psr_enabled = true; - dmcu->funcs->setup_psr(dmcu, link, psr_context); - return true; - } else - return false; - -} - const struct dc_link_status *dc_link_get_status(const struct dc_link *link) { return &link->link_status; @@ -2420,6 +2310,9 @@ void core_link_disable_stream(struct pipe_ctx *pipe_ctx, int option) if (pipe_ctx->stream->signal == SIGNAL_TYPE_DISPLAY_PORT_MST) deallocate_mst_payload(pipe_ctx); + if (pipe_ctx->stream->signal == SIGNAL_TYPE_EDP) + core_dc->hwss.edp_backlight_control(pipe_ctx->stream->sink->link, false); + core_dc->hwss.disable_stream(pipe_ctx, option); disable_link(pipe_ctx->stream->sink->link, pipe_ctx->stream->signal); diff --git a/drivers/gpu/drm/amd/display/dc/core/dc_link_dp.c b/drivers/gpu/drm/amd/display/dc/core/dc_link_dp.c index e6bf05d76a94..61e8c3e02d16 100644 --- a/drivers/gpu/drm/amd/display/dc/core/dc_link_dp.c +++ b/drivers/gpu/drm/amd/display/dc/core/dc_link_dp.c @@ -220,8 +220,7 @@ static void dpcd_set_lt_pattern_and_lane_settings( size_in_bytes); dm_logger_write(link->ctx->logger, LOG_HW_LINK_TRAINING, - "%s:\n %x VS set = %x PE set = %x \ - max VS Reached = %x max PE Reached = %x\n", + "%s:\n %x VS set = %x PE set = %x max VS Reached = %x max PE Reached = %x\n", __func__, DP_TRAINING_LANE0_SET, dpcd_lane[0].bits.VOLTAGE_SWING_SET, @@ -558,8 +557,7 @@ static void dpcd_set_lane_settings( */ dm_logger_write(link->ctx->logger, LOG_HW_LINK_TRAINING, - "%s\n %x VS set = %x PE set = %x \ - max VS Reached = %x max PE Reached = %x\n", + "%s\n %x VS set = %x PE set = %x max VS Reached = %x max PE Reached = %x\n", __func__, DP_TRAINING_LANE0_SET, dpcd_lane[0].bits.VOLTAGE_SWING_SET, @@ -872,9 +870,8 @@ static bool perform_clock_recovery_sequence( if (retry_count >= LINK_TRAINING_MAX_CR_RETRY) { ASSERT(0); dm_logger_write(link->ctx->logger, LOG_ERROR, - "%s: Link Training Error, could not \ - get CR after %d tries. \ - Possibly voltage swing issue", __func__, + "%s: Link Training Error, could not get CR after %d tries. Possibly voltage swing issue", + __func__, LINK_TRAINING_MAX_CR_RETRY); } @@ -1473,6 +1470,12 @@ void decide_link_settings(struct dc_stream_state *stream, return; } + /* EDP use the link cap setting */ + if (stream->sink->sink_signal == SIGNAL_TYPE_EDP) { + *link_setting = link->verified_link_cap; + return; + } + /* search for the minimum link setting that: * 1. is supported according to the link training result * 2. could support the b/w requested by the timing @@ -2127,7 +2130,7 @@ static void get_active_converter_info( union dwnstream_port_caps_byte3_hdmi hdmi_caps = {.raw = det_caps[3] }; - union dwnstream_port_caps_byte1 + union dwnstream_port_caps_byte2 hdmi_color_caps = {.raw = det_caps[2] }; link->dpcd_caps.dongle_caps.dp_hdmi_max_pixel_clk = det_caps[1] * 25000; diff --git a/drivers/gpu/drm/amd/display/dc/core/dc_link_hwss.c b/drivers/gpu/drm/amd/display/dc/core/dc_link_hwss.c index 9a33b471270a..2096f2a179f2 100644 --- a/drivers/gpu/drm/amd/display/dc/core/dc_link_hwss.c +++ b/drivers/gpu/drm/amd/display/dc/core/dc_link_hwss.c @@ -88,15 +88,7 @@ void dp_enable_link_phy( } if (dc_is_dp_sst_signal(signal)) { - if (signal == SIGNAL_TYPE_EDP) { - link->dc->hwss.edp_power_control(link->link_enc, true); - link_enc->funcs->enable_dp_output( - link_enc, - link_settings, - clock_source); - link->dc->hwss.edp_backlight_control(link, true); - } else - link_enc->funcs->enable_dp_output( + link_enc->funcs->enable_dp_output( link_enc, link_settings, clock_source); @@ -138,12 +130,11 @@ void dp_disable_link_phy(struct dc_link *link, enum signal_type signal) dp_receiver_power_ctrl(link, false); if (signal == SIGNAL_TYPE_EDP) { - link->dc->hwss.edp_backlight_control(link, false); edp_receiver_ready_T9(link); - link->link_enc->funcs->disable_output(link->link_enc, signal, link); - link->dc->hwss.edp_power_control(link->link_enc, false); + link->link_enc->funcs->disable_output(link->link_enc, signal); + link->dc->hwss.edp_power_control(link, false); } else - link->link_enc->funcs->disable_output(link->link_enc, signal, link); + link->link_enc->funcs->disable_output(link->link_enc, signal); /* Clear current link setting.*/ memset(&link->cur_link_settings, 0, @@ -286,8 +277,7 @@ void dp_retrain_link_dp_test(struct dc_link *link, link->link_enc->funcs->disable_output( link->link_enc, - SIGNAL_TYPE_DISPLAY_PORT, - link); + SIGNAL_TYPE_DISPLAY_PORT); /* Clear current link setting. */ memset(&link->cur_link_settings, 0, diff --git a/drivers/gpu/drm/amd/display/dc/core/dc_resource.c b/drivers/gpu/drm/amd/display/dc/core/dc_resource.c index 928895809867..95b8dd0e53c6 100644 --- a/drivers/gpu/drm/amd/display/dc/core/dc_resource.c +++ b/drivers/gpu/drm/amd/display/dc/core/dc_resource.c @@ -426,15 +426,8 @@ static enum pixel_format convert_pixel_format_to_dalsurface( static void rect_swap_helper(struct rect *rect) { - uint32_t temp = 0; - - temp = rect->height; - rect->height = rect->width; - rect->width = temp; - - temp = rect->x; - rect->x = rect->y; - rect->y = temp; + swap(rect->height, rect->width); + swap(rect->x, rect->y); } static void calculate_viewport(struct pipe_ctx *pipe_ctx) @@ -505,26 +498,15 @@ static void calculate_viewport(struct pipe_ctx *pipe_ctx) data->viewport_c.height = (data->viewport.height + vpc_div - 1) / vpc_div; /* Handle hsplit */ - if (pri_split || sec_split) { - /* HMirror XOR Secondary_pipe XOR Rotation_180 */ - bool right_view = (sec_split != plane_state->horizontal_mirror) != - (plane_state->rotation == ROTATION_ANGLE_180); - - if (plane_state->rotation == ROTATION_ANGLE_90 - || plane_state->rotation == ROTATION_ANGLE_270) - /* Secondary_pipe XOR Rotation_270 */ - right_view = (plane_state->rotation == ROTATION_ANGLE_270) != sec_split; - - if (right_view) { - data->viewport.x += data->viewport.width / 2; - data->viewport_c.x += data->viewport_c.width / 2; - /* Ceil offset pipe */ - data->viewport.width = (data->viewport.width + 1) / 2; - data->viewport_c.width = (data->viewport_c.width + 1) / 2; - } else { - data->viewport.width /= 2; - data->viewport_c.width /= 2; - } + if (sec_split) { + data->viewport.x += data->viewport.width / 2; + data->viewport_c.x += data->viewport_c.width / 2; + /* Ceil offset pipe */ + data->viewport.width = (data->viewport.width + 1) / 2; + data->viewport_c.width = (data->viewport_c.width + 1) / 2; + } else if (pri_split) { + data->viewport.width /= 2; + data->viewport_c.width /= 2; } if (plane_state->rotation == ROTATION_ANGLE_90 || @@ -541,6 +523,11 @@ static void calculate_recout(struct pipe_ctx *pipe_ctx, struct view *recout_skip struct rect surf_src = plane_state->src_rect; struct rect surf_clip = plane_state->clip_rect; int recout_full_x, recout_full_y; + bool pri_split = pipe_ctx->bottom_pipe && + pipe_ctx->bottom_pipe->plane_state == pipe_ctx->plane_state; + bool sec_split = pipe_ctx->top_pipe && + pipe_ctx->top_pipe->plane_state == pipe_ctx->plane_state; + bool top_bottom_split = stream->view_format == VIEW_3D_FORMAT_TOP_AND_BOTTOM; if (pipe_ctx->plane_state->rotation == ROTATION_ANGLE_90 || pipe_ctx->plane_state->rotation == ROTATION_ANGLE_270) @@ -575,33 +562,43 @@ static void calculate_recout(struct pipe_ctx *pipe_ctx, struct view *recout_skip - pipe_ctx->plane_res.scl_data.recout.y; /* Handle h & vsplit */ - if (pipe_ctx->top_pipe && pipe_ctx->top_pipe->plane_state == - pipe_ctx->plane_state) { - if (stream->view_format == VIEW_3D_FORMAT_TOP_AND_BOTTOM) { - pipe_ctx->plane_res.scl_data.recout.y += pipe_ctx->plane_res.scl_data.recout.height / 2; - /* Floor primary pipe, ceil 2ndary pipe */ - pipe_ctx->plane_res.scl_data.recout.height = (pipe_ctx->plane_res.scl_data.recout.height + 1) / 2; + if (sec_split && top_bottom_split) { + pipe_ctx->plane_res.scl_data.recout.y += + pipe_ctx->plane_res.scl_data.recout.height / 2; + /* Floor primary pipe, ceil 2ndary pipe */ + pipe_ctx->plane_res.scl_data.recout.height = + (pipe_ctx->plane_res.scl_data.recout.height + 1) / 2; + } else if (pri_split && top_bottom_split) + pipe_ctx->plane_res.scl_data.recout.height /= 2; + else if (pri_split || sec_split) { + /* HMirror XOR Secondary_pipe XOR Rotation_180 */ + bool right_view = (sec_split != plane_state->horizontal_mirror) != + (plane_state->rotation == ROTATION_ANGLE_180); + + if (plane_state->rotation == ROTATION_ANGLE_90 + || plane_state->rotation == ROTATION_ANGLE_270) + /* Secondary_pipe XOR Rotation_270 */ + right_view = (plane_state->rotation == ROTATION_ANGLE_270) != sec_split; + + if (right_view) { + pipe_ctx->plane_res.scl_data.recout.x += + pipe_ctx->plane_res.scl_data.recout.width / 2; + /* Ceil offset pipe */ + pipe_ctx->plane_res.scl_data.recout.width = + (pipe_ctx->plane_res.scl_data.recout.width + 1) / 2; } else { - pipe_ctx->plane_res.scl_data.recout.x += pipe_ctx->plane_res.scl_data.recout.width / 2; - pipe_ctx->plane_res.scl_data.recout.width = (pipe_ctx->plane_res.scl_data.recout.width + 1) / 2; - } - } else if (pipe_ctx->bottom_pipe && - pipe_ctx->bottom_pipe->plane_state == pipe_ctx->plane_state) { - if (stream->view_format == VIEW_3D_FORMAT_TOP_AND_BOTTOM) - pipe_ctx->plane_res.scl_data.recout.height /= 2; - else pipe_ctx->plane_res.scl_data.recout.width /= 2; + } } - /* Unclipped recout offset = stream dst offset + ((surf dst offset - stream surf_src offset) * * 1/ stream scaling ratio) - (surf surf_src offset * 1/ full scl * ratio) */ - recout_full_x = stream->dst.x + (plane_state->dst_rect.x - stream->src.x) + recout_full_x = stream->dst.x + (plane_state->dst_rect.x - stream->src.x) * stream->dst.width / stream->src.width - surf_src.x * plane_state->dst_rect.width / surf_src.width * stream->dst.width / stream->src.width; - recout_full_y = stream->dst.y + (plane_state->dst_rect.y - stream->src.y) + recout_full_y = stream->dst.y + (plane_state->dst_rect.y - stream->src.y) * stream->dst.height / stream->src.height - surf_src.y * plane_state->dst_rect.height / surf_src.height * stream->dst.height / stream->src.height; @@ -657,7 +654,20 @@ static void calculate_inits_and_adj_vp(struct pipe_ctx *pipe_ctx, struct view *r struct rect src = pipe_ctx->plane_state->src_rect; int vpc_div = (data->format == PIXEL_FORMAT_420BPP8 || data->format == PIXEL_FORMAT_420BPP10) ? 2 : 1; + bool flip_vert_scan_dir = false, flip_horz_scan_dir = false; + /* + * Need to calculate the scan direction for viewport to make adjustments + */ + if (pipe_ctx->plane_state->rotation == ROTATION_ANGLE_180) { + flip_vert_scan_dir = true; + flip_horz_scan_dir = true; + } else if (pipe_ctx->plane_state->rotation == ROTATION_ANGLE_90) + flip_vert_scan_dir = true; + else if (pipe_ctx->plane_state->rotation == ROTATION_ANGLE_270) + flip_horz_scan_dir = true; + if (pipe_ctx->plane_state->horizontal_mirror) + flip_horz_scan_dir = !flip_horz_scan_dir; if (pipe_ctx->plane_state->rotation == ROTATION_ANGLE_90 || pipe_ctx->plane_state->rotation == ROTATION_ANGLE_270) { @@ -722,7 +732,7 @@ static void calculate_inits_and_adj_vp(struct pipe_ctx *pipe_ctx, struct view *r } /* Adjust for non-0 viewport offset */ - if (data->viewport.x) { + if (data->viewport.x && !flip_horz_scan_dir) { int int_part; data->inits.h = dal_fixed31_32_add(data->inits.h, dal_fixed31_32_mul_int( @@ -743,7 +753,7 @@ static void calculate_inits_and_adj_vp(struct pipe_ctx *pipe_ctx, struct view *r data->inits.h = dal_fixed31_32_add_int(data->inits.h, int_part); } - if (data->viewport_c.x) { + if (data->viewport_c.x && !flip_horz_scan_dir) { int int_part; data->inits.h_c = dal_fixed31_32_add(data->inits.h_c, dal_fixed31_32_mul_int( @@ -764,7 +774,7 @@ static void calculate_inits_and_adj_vp(struct pipe_ctx *pipe_ctx, struct view *r data->inits.h_c = dal_fixed31_32_add_int(data->inits.h_c, int_part); } - if (data->viewport.y) { + if (data->viewport.y && !flip_vert_scan_dir) { int int_part; data->inits.v = dal_fixed31_32_add(data->inits.v, dal_fixed31_32_mul_int( @@ -785,7 +795,7 @@ static void calculate_inits_and_adj_vp(struct pipe_ctx *pipe_ctx, struct view *r data->inits.v = dal_fixed31_32_add_int(data->inits.v, int_part); } - if (data->viewport_c.y) { + if (data->viewport_c.y && !flip_vert_scan_dir) { int int_part; data->inits.v_c = dal_fixed31_32_add(data->inits.v_c, dal_fixed31_32_mul_int( @@ -2319,20 +2329,13 @@ static void set_spd_info_packet( static void set_hdr_static_info_packet( struct encoder_info_packet *info_packet, - struct dc_plane_state *plane_state, struct dc_stream_state *stream) { uint16_t i = 0; enum signal_type signal = stream->signal; - struct dc_hdr_static_metadata hdr_metadata; uint32_t data; - if (!plane_state) - return; - - hdr_metadata = plane_state->hdr_static_ctx; - - if (!hdr_metadata.hdr_supported) + if (!stream->hdr_static_metadata.hdr_supported) return; if (dc_is_hdmi_signal(signal)) { @@ -2352,55 +2355,55 @@ static void set_hdr_static_info_packet( i = 2; } - data = hdr_metadata.is_hdr; + data = stream->hdr_static_metadata.is_hdr; info_packet->sb[i++] = data ? 0x02 : 0x00; info_packet->sb[i++] = 0x00; - data = hdr_metadata.chromaticity_green_x / 2; + data = stream->hdr_static_metadata.chromaticity_green_x / 2; info_packet->sb[i++] = data & 0xFF; info_packet->sb[i++] = (data & 0xFF00) >> 8; - data = hdr_metadata.chromaticity_green_y / 2; + data = stream->hdr_static_metadata.chromaticity_green_y / 2; info_packet->sb[i++] = data & 0xFF; info_packet->sb[i++] = (data & 0xFF00) >> 8; - data = hdr_metadata.chromaticity_blue_x / 2; + data = stream->hdr_static_metadata.chromaticity_blue_x / 2; info_packet->sb[i++] = data & 0xFF; info_packet->sb[i++] = (data & 0xFF00) >> 8; - data = hdr_metadata.chromaticity_blue_y / 2; + data = stream->hdr_static_metadata.chromaticity_blue_y / 2; info_packet->sb[i++] = data & 0xFF; info_packet->sb[i++] = (data & 0xFF00) >> 8; - data = hdr_metadata.chromaticity_red_x / 2; + data = stream->hdr_static_metadata.chromaticity_red_x / 2; info_packet->sb[i++] = data & 0xFF; info_packet->sb[i++] = (data & 0xFF00) >> 8; - data = hdr_metadata.chromaticity_red_y / 2; + data = stream->hdr_static_metadata.chromaticity_red_y / 2; info_packet->sb[i++] = data & 0xFF; info_packet->sb[i++] = (data & 0xFF00) >> 8; - data = hdr_metadata.chromaticity_white_point_x / 2; + data = stream->hdr_static_metadata.chromaticity_white_point_x / 2; info_packet->sb[i++] = data & 0xFF; info_packet->sb[i++] = (data & 0xFF00) >> 8; - data = hdr_metadata.chromaticity_white_point_y / 2; + data = stream->hdr_static_metadata.chromaticity_white_point_y / 2; info_packet->sb[i++] = data & 0xFF; info_packet->sb[i++] = (data & 0xFF00) >> 8; - data = hdr_metadata.max_luminance; + data = stream->hdr_static_metadata.max_luminance; info_packet->sb[i++] = data & 0xFF; info_packet->sb[i++] = (data & 0xFF00) >> 8; - data = hdr_metadata.min_luminance; + data = stream->hdr_static_metadata.min_luminance; info_packet->sb[i++] = data & 0xFF; info_packet->sb[i++] = (data & 0xFF00) >> 8; - data = hdr_metadata.maximum_content_light_level; + data = stream->hdr_static_metadata.maximum_content_light_level; info_packet->sb[i++] = data & 0xFF; info_packet->sb[i++] = (data & 0xFF00) >> 8; - data = hdr_metadata.maximum_frame_average_light_level; + data = stream->hdr_static_metadata.maximum_frame_average_light_level; info_packet->sb[i++] = data & 0xFF; info_packet->sb[i++] = (data & 0xFF00) >> 8; @@ -2551,16 +2554,14 @@ void resource_build_info_frame(struct pipe_ctx *pipe_ctx) set_spd_info_packet(&info->spd, pipe_ctx->stream); - set_hdr_static_info_packet(&info->hdrsmd, - pipe_ctx->plane_state, pipe_ctx->stream); + set_hdr_static_info_packet(&info->hdrsmd, pipe_ctx->stream); } else if (dc_is_dp_signal(signal)) { set_vsc_info_packet(&info->vsc, pipe_ctx->stream); set_spd_info_packet(&info->spd, pipe_ctx->stream); - set_hdr_static_info_packet(&info->hdrsmd, - pipe_ctx->plane_state, pipe_ctx->stream); + set_hdr_static_info_packet(&info->hdrsmd, pipe_ctx->stream); } patch_gamut_packet_checksum(&info->gamut); diff --git a/drivers/gpu/drm/amd/display/dc/core/dc_stream.c b/drivers/gpu/drm/amd/display/dc/core/dc_stream.c index e230cc44a0a7..261811e0c094 100644 --- a/drivers/gpu/drm/amd/display/dc/core/dc_stream.c +++ b/drivers/gpu/drm/amd/display/dc/core/dc_stream.c @@ -36,16 +36,13 @@ #define TMDS_MAX_PIXEL_CLOCK_IN_KHZ_UPMOST 297000 static void update_stream_signal(struct dc_stream_state *stream) { - if (stream->output_signal == SIGNAL_TYPE_NONE) { - struct dc_sink *dc_sink = stream->sink; - if (dc_sink->sink_signal == SIGNAL_TYPE_NONE) - stream->signal = stream->sink->link->connector_signal; - else - stream->signal = dc_sink->sink_signal; - } else { - stream->signal = stream->output_signal; - } + struct dc_sink *dc_sink = stream->sink; + + if (dc_sink->sink_signal == SIGNAL_TYPE_NONE) + stream->signal = stream->sink->link->connector_signal; + else + stream->signal = dc_sink->sink_signal; if (dc_is_dvi_signal(stream->signal)) { if (stream->timing.pix_clk_khz > TMDS_MAX_PIXEL_CLOCK_IN_KHZ_UPMOST && @@ -229,7 +226,7 @@ bool dc_stream_set_cursor_attributes( if (pipe_ctx->plane_res.dpp != NULL && pipe_ctx->plane_res.dpp->funcs->set_cursor_attributes != NULL) pipe_ctx->plane_res.dpp->funcs->set_cursor_attributes( - pipe_ctx->plane_res.dpp, attributes); + pipe_ctx->plane_res.dpp, attributes->color_format); } stream->cursor_attributes = *attributes; @@ -304,6 +301,8 @@ bool dc_stream_set_cursor_position( } + stream->cursor_position = *position; + return true; } diff --git a/drivers/gpu/drm/amd/display/dc/dc.h b/drivers/gpu/drm/amd/display/dc/dc.h index 9d8f4a55c74e..e2e3c9df79ea 100644 --- a/drivers/gpu/drm/amd/display/dc/dc.h +++ b/drivers/gpu/drm/amd/display/dc/dc.h @@ -38,7 +38,7 @@ #include "inc/compressor.h" #include "dml/display_mode_lib.h" -#define DC_VER "3.1.07" +#define DC_VER "3.1.27" #define MAX_SURFACES 3 #define MAX_STREAMS 6 @@ -58,8 +58,10 @@ struct dc_caps { uint32_t i2c_speed_in_khz; unsigned int max_cursor_size; unsigned int max_video_width; + int linear_pitch_alignment; bool dcc_const_color; bool dynamic_audio; + bool is_apu; }; struct dc_dcc_surface_param { @@ -97,69 +99,53 @@ struct dc_static_screen_events { bool overlay_update; }; + +/* Surface update type is used by dc_update_surfaces_and_stream + * The update type is determined at the very beginning of the function based + * on parameters passed in and decides how much programming (or updating) is + * going to be done during the call. + * + * UPDATE_TYPE_FAST is used for really fast updates that do not require much + * logical calculations or hardware register programming. This update MUST be + * ISR safe on windows. Currently fast update will only be used to flip surface + * address. + * + * UPDATE_TYPE_MED is used for slower updates which require significant hw + * re-programming however do not affect bandwidth consumption or clock + * requirements. At present, this is the level at which front end updates + * that do not require us to run bw_calcs happen. These are in/out transfer func + * updates, viewport offset changes, recout size changes and pixel depth changes. + * This update can be done at ISR, but we want to minimize how often this happens. + * + * UPDATE_TYPE_FULL is slow. Really slow. This requires us to recalculate our + * bandwidth and clocks, possibly rearrange some pipes and reprogram anything front + * end related. Any time viewport dimensions, recout dimensions, scaling ratios or + * gamma need to be adjusted or pipe needs to be turned on (or disconnected) we do + * a full update. This cannot be done at ISR level and should be a rare event. + * Unless someone is stress testing mpo enter/exit, playing with colour or adjusting + * underscan we don't expect to see this call at all. + */ + +enum surface_update_type { + UPDATE_TYPE_FAST, /* super fast, safe to execute in isr */ + UPDATE_TYPE_MED, /* ISR safe, most of programming needed, no bw/clk change*/ + UPDATE_TYPE_FULL, /* may need to shuffle resources */ +}; + /* Forward declaration*/ struct dc; struct dc_plane_state; struct dc_state; + struct dc_cap_funcs { bool (*get_dcc_compression_cap)(const struct dc *dc, const struct dc_dcc_surface_param *input, struct dc_surface_dcc_cap *output); }; -struct dc_stream_state_funcs { - bool (*adjust_vmin_vmax)(struct dc *dc, - struct dc_stream_state **stream, - int num_streams, - int vmin, - int vmax); - bool (*get_crtc_position)(struct dc *dc, - struct dc_stream_state **stream, - int num_streams, - unsigned int *v_pos, - unsigned int *nom_v_pos); - - bool (*set_gamut_remap)(struct dc *dc, - const struct dc_stream_state *stream); - - bool (*program_csc_matrix)(struct dc *dc, - struct dc_stream_state *stream); - - void (*set_static_screen_events)(struct dc *dc, - struct dc_stream_state **stream, - int num_streams, - const struct dc_static_screen_events *events); - - void (*set_dither_option)(struct dc_stream_state *stream, - enum dc_dither_option option); - - void (*set_dpms)(struct dc *dc, - struct dc_stream_state *stream, - bool dpms_off); -}; - struct link_training_settings; -struct dc_link_funcs { - void (*set_drive_settings)(struct dc *dc, - struct link_training_settings *lt_settings, - const struct dc_link *link); - void (*perform_link_training)(struct dc *dc, - struct dc_link_settings *link_setting, - bool skip_video_pattern); - void (*set_preferred_link_settings)(struct dc *dc, - struct dc_link_settings *link_setting, - struct dc_link *link); - void (*enable_hpd)(const struct dc_link *link); - void (*disable_hpd)(const struct dc_link *link); - void (*set_test_pattern)( - struct dc_link *link, - enum dp_test_pattern test_pattern, - const struct link_training_settings *p_link_settings, - const unsigned char *p_custom_pattern, - unsigned int cust_pattern_size); -}; /* Structure to hold configuration flags set by dm at dc creation. */ struct dc_config { @@ -232,8 +218,6 @@ struct dce_hwseq; struct dc { struct dc_caps caps; struct dc_cap_funcs cap_funcs; - struct dc_stream_state_funcs stream_funcs; - struct dc_link_funcs link_funcs; struct dc_config config; struct dc_debug debug; @@ -266,6 +250,8 @@ struct dc { */ struct dm_pp_display_configuration prev_display_config; + bool optimized_required; + /* FBC compressor */ #if defined(CONFIG_DRM_AMD_DC_FBC) struct compressor *fbc_compressor; @@ -333,24 +319,6 @@ enum color_transfer_func { 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 -}; - struct dc_hdr_static_metadata { /* display chromaticities and white point in units of 0.00001 */ unsigned int chromaticity_green_x; @@ -374,7 +342,7 @@ struct dc_hdr_static_metadata { enum dc_transfer_func_type { TF_TYPE_PREDEFINED, TF_TYPE_DISTRIBUTED_POINTS, - TF_TYPE_BYPASS + TF_TYPE_BYPASS, }; struct dc_transfer_func_distributed_points { @@ -393,6 +361,7 @@ enum dc_transfer_func_predefined { TRANSFER_FUNCTION_BT709, TRANSFER_FUNCTION_PQ, TRANSFER_FUNCTION_LINEAR, + TRANSFER_FUNCTION_UNITY, }; struct dc_transfer_func { @@ -415,6 +384,34 @@ struct dc_plane_status { bool is_right_eye; }; +union surface_update_flags { + + struct { + /* Medium updates */ + uint32_t dcc_change:1; + uint32_t color_space_change:1; + uint32_t input_tf_change:1; + uint32_t horizontal_mirror_change:1; + uint32_t per_pixel_alpha_change:1; + uint32_t rotation_change:1; + uint32_t swizzle_change:1; + uint32_t scaling_change:1; + uint32_t position_change:1; + uint32_t in_transfer_func:1; + uint32_t input_csc_change:1; + + /* Full updates */ + uint32_t new_plane:1; + uint32_t bpp_change:1; + uint32_t bandwidth_change:1; + uint32_t clock_change:1; + uint32_t stereo_format_change:1; + uint32_t full_update:1; + } bits; + + uint32_t raw; +}; + struct dc_plane_state { struct dc_plane_address address; struct scaling_taps scaling_quality; @@ -426,27 +423,30 @@ struct dc_plane_state { union dc_tiling_info tiling_info; struct dc_plane_dcc_param dcc; - struct dc_hdr_static_metadata hdr_static_ctx; struct dc_gamma *gamma_correction; struct dc_transfer_func *in_transfer_func; + struct dc_bias_and_scale *bias_and_scale; + struct csc_transform input_csc_color_matrix; + struct fixed31_32 coeff_reduction_factor; - // sourceContentAttribute cache - bool is_source_input_valid; - struct dc_hdr_static_metadata source_input_mastering_info; - enum color_color_space source_input_color_space; - enum color_transfer_func source_input_tf; + // TODO: No longer used, remove + struct dc_hdr_static_metadata hdr_static_ctx; enum dc_color_space color_space; + enum color_transfer_func input_tf; + enum surface_pixel_format format; enum dc_rotation_angle rotation; enum plane_stereo_format stereo_format; + bool is_tiling_rotated; bool per_pixel_alpha; bool visible; bool flip_immediate; bool horizontal_mirror; + union surface_update_flags update_flags; /* private to DC core */ struct dc_plane_status status; struct dc_context *ctx; @@ -463,10 +463,12 @@ struct dc_plane_info { enum surface_pixel_format format; enum dc_rotation_angle rotation; enum plane_stereo_format stereo_format; - enum dc_color_space color_space; /*todo: wrong place, fits in scaling info*/ + enum dc_color_space color_space; + enum color_transfer_func input_tf; bool horizontal_mirror; bool visible; bool per_pixel_alpha; + bool input_csc_enabled; }; struct dc_scaling_info { @@ -483,13 +485,18 @@ struct dc_surface_update { struct dc_flip_addrs *flip_addr; struct dc_plane_info *plane_info; struct dc_scaling_info *scaling_info; + /* following updates require alloc/sleep/spin that is not isr safe, * null means no updates */ /* gamma TO BE REMOVED */ struct dc_gamma *gamma; + enum color_transfer_func color_input_tf; + enum color_transfer_func color_output_tf; struct dc_transfer_func *in_transfer_func; - struct dc_hdr_static_metadata *hdr_static_metadata; + + struct csc_transform *input_csc_color_matrix; + struct fixed31_32 *coeff_reduction_factor; }; /* @@ -524,197 +531,7 @@ struct dc_flip_addrs { bool dc_post_update_surfaces_to_stream( struct dc *dc); -/* Surface update type is used by dc_update_surfaces_and_stream - * The update type is determined at the very beginning of the function based - * on parameters passed in and decides how much programming (or updating) is - * going to be done during the call. - * - * UPDATE_TYPE_FAST is used for really fast updates that do not require much - * logical calculations or hardware register programming. This update MUST be - * ISR safe on windows. Currently fast update will only be used to flip surface - * address. - * - * UPDATE_TYPE_MED is used for slower updates which require significant hw - * re-programming however do not affect bandwidth consumption or clock - * requirements. At present, this is the level at which front end updates - * that do not require us to run bw_calcs happen. These are in/out transfer func - * updates, viewport offset changes, recout size changes and pixel depth changes. - * This update can be done at ISR, but we want to minimize how often this happens. - * - * UPDATE_TYPE_FULL is slow. Really slow. This requires us to recalculate our - * bandwidth and clocks, possibly rearrange some pipes and reprogram anything front - * end related. Any time viewport dimensions, recout dimensions, scaling ratios or - * gamma need to be adjusted or pipe needs to be turned on (or disconnected) we do - * a full update. This cannot be done at ISR level and should be a rare event. - * Unless someone is stress testing mpo enter/exit, playing with colour or adjusting - * underscan we don't expect to see this call at all. - */ - -enum surface_update_type { - UPDATE_TYPE_FAST, /* super fast, safe to execute in isr */ - UPDATE_TYPE_MED, /* ISR safe, most of programming needed, no bw/clk change*/ - UPDATE_TYPE_FULL, /* may need to shuffle resources */ -}; - -/******************************************************************************* - * Stream Interfaces - ******************************************************************************/ - -struct dc_stream_status { - int primary_otg_inst; - int stream_enc_inst; - int plane_count; - struct dc_plane_state *plane_states[MAX_SURFACE_NUM]; - - /* - * link this stream passes through - */ - struct dc_link *link; -}; - -struct dc_stream_state { - struct dc_sink *sink; - struct dc_crtc_timing timing; - - struct rect src; /* composition area */ - struct rect dst; /* stream addressable area */ - - struct audio_info audio_info; - - struct freesync_context freesync_ctx; - - struct dc_transfer_func *out_transfer_func; - struct colorspace_transform gamut_remap_matrix; - struct csc_transform csc_color_matrix; - - enum signal_type output_signal; - - enum dc_color_space output_color_space; - enum dc_dither_option dither_option; - - enum view_3d_format view_format; - - bool ignore_msa_timing_param; - /* TODO: custom INFO packets */ - /* TODO: ABM info (DMCU) */ - /* TODO: PSR info */ - /* TODO: CEA VIC */ - - /* from core_stream struct */ - struct dc_context *ctx; - - /* used by DCP and FMT */ - struct bit_depth_reduction_params bit_depth_params; - struct clamping_and_pixel_encoding_params clamping; - - int phy_pix_clk; - enum signal_type signal; - bool dpms_off; - - struct dc_stream_status status; - - struct dc_cursor_attributes cursor_attributes; - - /* from stream struct */ - struct kref refcount; -}; - -struct dc_stream_update { - struct rect src; - struct rect dst; - struct dc_transfer_func *out_transfer_func; -}; - -bool dc_is_stream_unchanged( - struct dc_stream_state *old_stream, struct dc_stream_state *stream); -bool dc_is_stream_scaling_unchanged( - struct dc_stream_state *old_stream, struct dc_stream_state *stream); - -/* - * Set up surface attributes and associate to a stream - * The surfaces parameter is an absolute set of all surface active for the stream. - * If no surfaces are provided, the stream will be blanked; no memory read. - * Any flip related attribute changes must be done through this interface. - * - * After this call: - * Surfaces attributes are programmed and configured to be composed into stream. - * This does not trigger a flip. No surface address is programmed. - */ - -bool dc_commit_planes_to_stream( - struct dc *dc, - struct dc_plane_state **plane_states, - uint8_t new_plane_count, - struct dc_stream_state *dc_stream, - struct dc_state *state); - -void dc_commit_updates_for_stream(struct dc *dc, - struct dc_surface_update *srf_updates, - int surface_count, - struct dc_stream_state *stream, - struct dc_stream_update *stream_update, - struct dc_plane_state **plane_states, - struct dc_state *state); -/* - * Log the current stream state. - */ -void dc_stream_log( - const struct dc_stream_state *stream, - struct dal_logger *dc_logger, - enum dc_log_type log_type); - -uint8_t dc_get_current_stream_count(struct dc *dc); -struct dc_stream_state *dc_get_stream_at_index(struct dc *dc, uint8_t i); - -/* - * Return the current frame counter. - */ -uint32_t dc_stream_get_vblank_counter(const struct dc_stream_state *stream); - -/* TODO: Return parsed values rather than direct register read - * This has a dependency on the caller (amdgpu_get_crtc_scanoutpos) - * being refactored properly to be dce-specific - */ -bool dc_stream_get_scanoutpos(const struct dc_stream_state *stream, - uint32_t *v_blank_start, - uint32_t *v_blank_end, - uint32_t *h_position, - uint32_t *v_position); - -enum dc_status dc_add_stream_to_ctx( - struct dc *dc, - struct dc_state *new_ctx, - struct dc_stream_state *stream); - -enum dc_status dc_remove_stream_from_ctx( - struct dc *dc, - struct dc_state *new_ctx, - struct dc_stream_state *stream); - - -bool dc_add_plane_to_context( - const struct dc *dc, - struct dc_stream_state *stream, - struct dc_plane_state *plane_state, - struct dc_state *context); - -bool dc_remove_plane_from_context( - const struct dc *dc, - struct dc_stream_state *stream, - struct dc_plane_state *plane_state, - struct dc_state *context); - -bool dc_rem_all_planes_for_stream( - const struct dc *dc, - struct dc_stream_state *stream, - struct dc_state *context); - -bool dc_add_all_planes_for_stream( - const struct dc *dc, - struct dc_stream_state *stream, - struct dc_plane_state * const *plane_states, - int plane_count, - struct dc_state *context); +#include "dc_stream.h" /* * Structure to store surface/stream associations for validation @@ -725,22 +542,12 @@ struct dc_validation_set { uint8_t plane_count; }; -enum dc_status dc_validate_stream(struct dc *dc, struct dc_stream_state *stream); - enum dc_status dc_validate_plane(struct dc *dc, const struct dc_plane_state *plane_state); enum dc_status dc_validate_global_state( struct dc *dc, struct dc_state *new_ctx); -/* - * This function takes a stream and checks if it is guaranteed to be supported. - * Guaranteed means that MAX_COFUNC similar streams are supported. - * - * After this call: - * No hardware is programmed for call. Only validation is done. - */ - void dc_resource_state_construct( const struct dc *dc, @@ -767,42 +574,6 @@ void dc_resource_state_destruct(struct dc_state *context); */ bool dc_commit_state(struct dc *dc, struct dc_state *context); -/* - * Set up streams and links associated to drive sinks - * The streams parameter is an absolute set of all active streams. - * - * After this call: - * Phy, Encoder, Timing Generator are programmed and enabled. - * New streams are enabled with blank stream; no memory read. - */ -/* - * Enable stereo when commit_streams is not required, - * for example, frame alternate. - */ -bool dc_enable_stereo( - struct dc *dc, - struct dc_state *context, - struct dc_stream_state *streams[], - uint8_t stream_count); - -/** - * Create a new default stream for the requested sink - */ -struct dc_stream_state *dc_create_stream_for_sink(struct dc_sink *dc_sink); - -void dc_stream_retain(struct dc_stream_state *dc_stream); -void dc_stream_release(struct dc_stream_state *dc_stream); - -struct dc_stream_status *dc_stream_get_status( - struct dc_stream_state *dc_stream); - -enum surface_update_type dc_check_update_surfaces_for_stream( - struct dc *dc, - struct dc_surface_update *updates, - int surface_count, - struct dc_stream_update *stream_update, - const struct dc_stream_status *stream_status); - struct dc_state *dc_create_state(void); void dc_retain_state(struct dc_state *context); @@ -835,171 +606,7 @@ struct dpcd_caps { bool dpcd_display_control_capable; }; -struct dc_link_status { - struct dpcd_caps *dpcd_caps; -}; - -/* DP MST stream allocation (payload bandwidth number) */ -struct link_mst_stream_allocation { - /* DIG front */ - const struct stream_encoder *stream_enc; - /* associate DRM payload table with DC stream encoder */ - uint8_t vcp_id; - /* number of slots required for the DP stream in transport packet */ - uint8_t slot_count; -}; - -/* DP MST stream allocation table */ -struct link_mst_stream_allocation_table { - /* number of DP video streams */ - int stream_count; - /* array of stream allocations */ - struct link_mst_stream_allocation stream_allocations[MAX_CONTROLLER_NUM]; -}; - -/* - * A link contains one or more sinks and their connected status. - * The currently active signal type (HDMI, DP-SST, DP-MST) is also reported. - */ -struct dc_link { - struct dc_sink *remote_sinks[MAX_SINKS_PER_LINK]; - unsigned int sink_count; - struct dc_sink *local_sink; - unsigned int link_index; - enum dc_connection_type type; - enum signal_type connector_signal; - enum dc_irq_source irq_source_hpd; - enum dc_irq_source irq_source_hpd_rx;/* aka DP Short Pulse */ - /* caps is the same as reported_link_cap. link_traing use - * reported_link_cap. Will clean up. TODO - */ - struct dc_link_settings reported_link_cap; - struct dc_link_settings verified_link_cap; - struct dc_link_settings cur_link_settings; - struct dc_lane_settings cur_lane_setting; - struct dc_link_settings preferred_link_setting; - - uint8_t ddc_hw_inst; - - uint8_t hpd_src; - - uint8_t link_enc_hw_inst; - - bool test_pattern_enabled; - union compliance_test_state compliance_test_state; - - void *priv; - - struct ddc_service *ddc; - - bool aux_mode; - - /* Private to DC core */ - - const struct dc *dc; - - struct dc_context *ctx; - - struct link_encoder *link_enc; - struct graphics_object_id link_id; - union ddi_channel_mapping ddi_channel_mapping; - struct connector_device_tag_info device_tag; - struct dpcd_caps dpcd_caps; - unsigned short chip_caps; - unsigned int dpcd_sink_count; - enum edp_revision edp_revision; - bool psr_enabled; - - /* MST record stream using this link */ - struct link_flags { - bool dp_keep_receiver_powered; - } wa_flags; - struct link_mst_stream_allocation_table mst_stream_alloc_table; - - struct dc_link_status link_status; - -}; - -const struct dc_link_status *dc_link_get_status(const struct dc_link *dc_link); - -/* - * Return an enumerated dc_link. dc_link order is constant and determined at - * boot time. They cannot be created or destroyed. - * Use dc_get_caps() to get number of links. - */ -static inline struct dc_link *dc_get_link_at_index(struct dc *dc, uint32_t link_index) -{ - return dc->links[link_index]; -} - -/* Set backlight level of an embedded panel (eDP, LVDS). */ -bool dc_link_set_backlight_level(const struct dc_link *dc_link, uint32_t level, - uint32_t frame_ramp, const struct dc_stream_state *stream); - -bool dc_link_set_psr_enable(const struct dc_link *dc_link, bool enable, bool wait); - -bool dc_link_get_psr_state(const struct dc_link *dc_link, uint32_t *psr_state); - -bool dc_link_setup_psr(struct dc_link *dc_link, - const struct dc_stream_state *stream, struct psr_config *psr_config, - struct psr_context *psr_context); - -/* Request DC to detect if there is a Panel connected. - * boot - If this call is during initial boot. - * Return false for any type of detection failure or MST detection - * true otherwise. True meaning further action is required (status update - * and OS notification). - */ -enum dc_detect_reason { - DETECT_REASON_BOOT, - DETECT_REASON_HPD, - DETECT_REASON_HPDRX, -}; - -bool dc_link_detect(struct dc_link *dc_link, enum dc_detect_reason reason); - -/* Notify DC about DP RX Interrupt (aka Short Pulse Interrupt). - * Return: - * true - Downstream port status changed. DM should call DC to do the - * detection. - * false - no change in Downstream port status. No further action required - * from DM. */ -bool dc_link_handle_hpd_rx_irq(struct dc_link *dc_link, - union hpd_irq_data *hpd_irq_dpcd_data); - -struct dc_sink_init_data; - -struct dc_sink *dc_link_add_remote_sink( - struct dc_link *dc_link, - const uint8_t *edid, - int len, - struct dc_sink_init_data *init_data); - -void dc_link_remove_remote_sink( - struct dc_link *link, - struct dc_sink *sink); - -/* Used by diagnostics for virtual link at the moment */ - -void dc_link_dp_set_drive_settings( - struct dc_link *link, - struct link_training_settings *lt_settings); - -enum link_training_result dc_link_dp_perform_link_training( - struct dc_link *link, - const struct dc_link_settings *link_setting, - bool skip_video_pattern); - -void dc_link_dp_enable_hpd(const struct dc_link *link); - -void dc_link_dp_disable_hpd(const struct dc_link *link); - -bool dc_link_dp_set_test_pattern( - struct dc_link *link, - enum dp_test_pattern test_pattern, - const struct link_training_settings *p_link_settings, - const unsigned char *p_custom_pattern, - unsigned int cust_pattern_size); +#include "dc_link.h" /******************************************************************************* * Sink Interfaces - A sink corresponds to a display output device @@ -1037,6 +644,7 @@ struct dc_sink { /* private to dc_sink.c */ struct kref refcount; + }; void dc_sink_retain(struct dc_sink *sink); @@ -1051,18 +659,6 @@ struct dc_sink_init_data { struct dc_sink *dc_sink_create(const struct dc_sink_init_data *init_params); -/******************************************************************************* - * Cursor interfaces - To manages the cursor within a stream - ******************************************************************************/ -/* TODO: Deprecated once we switch to dc_set_cursor_position */ -bool dc_stream_set_cursor_attributes( - struct dc_stream_state *stream, - const struct dc_cursor_attributes *attributes); - -bool dc_stream_set_cursor_position( - struct dc_stream_state *stream, - const struct dc_cursor_position *position); - /* Newer interfaces */ struct dc_cursor { struct dc_plane_address address; @@ -1090,14 +686,4 @@ void dc_set_power_state( enum dc_acpi_cm_power_state power_state); void dc_resume(struct dc *dc); -/* - * DPCD access interfaces - */ - -bool dc_submit_i2c( - struct dc *dc, - uint32_t link_index, - struct i2c_command *cmd); - - #endif /* DC_INTERFACE_H_ */ diff --git a/drivers/gpu/drm/amd/display/dc/dc_dp_types.h b/drivers/gpu/drm/amd/display/dc/dc_dp_types.h index 77e2de69cca3..2726b02e006b 100644 --- a/drivers/gpu/drm/amd/display/dc/dc_dp_types.h +++ b/drivers/gpu/drm/amd/display/dc/dc_dp_types.h @@ -255,7 +255,7 @@ enum dpcd_downstream_port_detailed_type { DOWN_STREAM_DETAILED_DP_PLUS_PLUS }; -union dwnstream_port_caps_byte1 { +union dwnstream_port_caps_byte2 { struct { uint8_t MAX_BITS_PER_COLOR_COMPONENT:2; uint8_t RESERVED:6; @@ -298,6 +298,32 @@ union dwnstream_port_caps_byte3_hdmi { /*4-byte structure for detailed capabilities of a down-stream port (DP-to-TMDS converter).*/ +union dwnstream_portxcaps { + struct { + union dwnstream_port_caps_byte0 byte0; + unsigned char max_TMDS_clock; //byte1 + union dwnstream_port_caps_byte2 byte2; + + union { + union dwnstream_port_caps_byte3_dvi byteDVI; + union dwnstream_port_caps_byte3_hdmi byteHDMI; + } byte3; + } bytes; + + unsigned char raw[4]; +}; + +union downstream_port { + struct { + unsigned char present:1; + unsigned char type:2; + unsigned char format_conv:1; + unsigned char detailed_caps:1; + unsigned char reserved:3; + } bits; + unsigned char raw; +}; + union sink_status { struct { diff --git a/drivers/gpu/drm/amd/display/dc/dc_helper.c b/drivers/gpu/drm/amd/display/dc/dc_helper.c index 90e81f7ba919..48e1fcf53d43 100644 --- a/drivers/gpu/drm/amd/display/dc/dc_helper.c +++ b/drivers/gpu/drm/amd/display/dc/dc_helper.c @@ -178,8 +178,13 @@ uint32_t generic_reg_wait(const struct dc_context *ctx, field_value = get_reg_field_value_ex(reg_val, mask, shift); - if (field_value == condition_value) + if (field_value == condition_value) { + if (i * delay_between_poll_us > 1000) + dm_output_to_console("REG_WAIT taking a while: %dms in %s line:%d\n", + delay_between_poll_us * i / 1000, + func_name, line); return reg_val; + } } dm_error("REG_WAIT timeout %dus * %d tries - %s line:%d\n", diff --git a/drivers/gpu/drm/amd/display/dc/dc_hw_types.h b/drivers/gpu/drm/amd/display/dc/dc_hw_types.h index 1a9f57fb0838..03029f72dc3f 100644 --- a/drivers/gpu/drm/amd/display/dc/dc_hw_types.h +++ b/drivers/gpu/drm/amd/display/dc/dc_hw_types.h @@ -492,15 +492,24 @@ struct dc_cursor_attributes { enum dc_color_space { COLOR_SPACE_UNKNOWN, COLOR_SPACE_SRGB, + COLOR_SPACE_XR_RGB, COLOR_SPACE_SRGB_LIMITED, + COLOR_SPACE_MSREF_SCRGB, COLOR_SPACE_YCBCR601, COLOR_SPACE_YCBCR709, + COLOR_SPACE_XV_YCC_709, + COLOR_SPACE_XV_YCC_601, COLOR_SPACE_YCBCR601_LIMITED, COLOR_SPACE_YCBCR709_LIMITED, COLOR_SPACE_2020_RGB_FULLRANGE, COLOR_SPACE_2020_RGB_LIMITEDRANGE, COLOR_SPACE_2020_YCBCR, COLOR_SPACE_ADOBERGB, + COLOR_SPACE_DCIP3, + COLOR_SPACE_DISPLAYNATIVE, + COLOR_SPACE_DOLBYVISION, + COLOR_SPACE_APPCTRL, + COLOR_SPACE_CUSTOMPOINTS, }; enum dc_dither_option { @@ -570,8 +579,6 @@ enum dc_timing_standard { TIMING_STANDARD_MAX }; - - enum dc_color_depth { COLOR_DEPTH_UNDEFINED, COLOR_DEPTH_666, @@ -664,6 +671,22 @@ enum dc_timing_3d_format { TIMING_3D_FORMAT_MAX, }; +enum trigger_delay { + TRIGGER_DELAY_NEXT_PIXEL = 0, + TRIGGER_DELAY_NEXT_LINE, +}; + +enum crtc_event { + CRTC_EVENT_VSYNC_RISING = 0, + CRTC_EVENT_VSYNC_FALLING +}; + +struct crtc_trigger_info { + bool enabled; + struct dc_stream_state *event_source; + enum crtc_event event; + enum trigger_delay delay; +}; struct dc_crtc_timing { diff --git a/drivers/gpu/drm/amd/display/dc/dc_link.h b/drivers/gpu/drm/amd/display/dc/dc_link.h new file mode 100644 index 000000000000..f11a734da1db --- /dev/null +++ b/drivers/gpu/drm/amd/display/dc/dc_link.h @@ -0,0 +1,207 @@ +/* + * Copyright 2012-14 Advanced Micro Devices, Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + * + * Authors: AMD + * + */ + +#ifndef DC_LINK_H_ +#define DC_LINK_H_ + +#include "dc_types.h" +#include "grph_object_defs.h" + +struct dc_link_status { + struct dpcd_caps *dpcd_caps; +}; + +/* DP MST stream allocation (payload bandwidth number) */ +struct link_mst_stream_allocation { + /* DIG front */ + const struct stream_encoder *stream_enc; + /* associate DRM payload table with DC stream encoder */ + uint8_t vcp_id; + /* number of slots required for the DP stream in transport packet */ + uint8_t slot_count; +}; + +/* DP MST stream allocation table */ +struct link_mst_stream_allocation_table { + /* number of DP video streams */ + int stream_count; + /* array of stream allocations */ + struct link_mst_stream_allocation stream_allocations[MAX_CONTROLLER_NUM]; +}; + +/* + * A link contains one or more sinks and their connected status. + * The currently active signal type (HDMI, DP-SST, DP-MST) is also reported. + */ +struct dc_link { + struct dc_sink *remote_sinks[MAX_SINKS_PER_LINK]; + unsigned int sink_count; + struct dc_sink *local_sink; + unsigned int link_index; + enum dc_connection_type type; + enum signal_type connector_signal; + enum dc_irq_source irq_source_hpd; + enum dc_irq_source irq_source_hpd_rx;/* aka DP Short Pulse */ + /* caps is the same as reported_link_cap. link_traing use + * reported_link_cap. Will clean up. TODO + */ + struct dc_link_settings reported_link_cap; + struct dc_link_settings verified_link_cap; + struct dc_link_settings cur_link_settings; + struct dc_lane_settings cur_lane_setting; + struct dc_link_settings preferred_link_setting; + + uint8_t ddc_hw_inst; + + uint8_t hpd_src; + + uint8_t link_enc_hw_inst; + + bool test_pattern_enabled; + union compliance_test_state compliance_test_state; + + void *priv; + + struct ddc_service *ddc; + + bool aux_mode; + + /* Private to DC core */ + + const struct dc *dc; + + struct dc_context *ctx; + + struct link_encoder *link_enc; + struct graphics_object_id link_id; + union ddi_channel_mapping ddi_channel_mapping; + struct connector_device_tag_info device_tag; + struct dpcd_caps dpcd_caps; + unsigned short chip_caps; + unsigned int dpcd_sink_count; + enum edp_revision edp_revision; + bool psr_enabled; + + /* MST record stream using this link */ + struct link_flags { + bool dp_keep_receiver_powered; + } wa_flags; + struct link_mst_stream_allocation_table mst_stream_alloc_table; + + struct dc_link_status link_status; + +}; + +const struct dc_link_status *dc_link_get_status(const struct dc_link *dc_link); + +/* + * Return an enumerated dc_link. dc_link order is constant and determined at + * boot time. They cannot be created or destroyed. + * Use dc_get_caps() to get number of links. + */ +static inline struct dc_link *dc_get_link_at_index(struct dc *dc, uint32_t link_index) +{ + return dc->links[link_index]; +} + +/* Set backlight level of an embedded panel (eDP, LVDS). */ +bool dc_link_set_backlight_level(const struct dc_link *dc_link, uint32_t level, + uint32_t frame_ramp, const struct dc_stream_state *stream); + +bool dc_link_set_psr_enable(const struct dc_link *dc_link, bool enable, bool wait); + +bool dc_link_get_psr_state(const struct dc_link *dc_link, uint32_t *psr_state); + +bool dc_link_setup_psr(struct dc_link *dc_link, + const struct dc_stream_state *stream, struct psr_config *psr_config, + struct psr_context *psr_context); + +/* Request DC to detect if there is a Panel connected. + * boot - If this call is during initial boot. + * Return false for any type of detection failure or MST detection + * true otherwise. True meaning further action is required (status update + * and OS notification). + */ +enum dc_detect_reason { + DETECT_REASON_BOOT, + DETECT_REASON_HPD, + DETECT_REASON_HPDRX, +}; + +bool dc_link_detect(struct dc_link *dc_link, enum dc_detect_reason reason); + +/* Notify DC about DP RX Interrupt (aka Short Pulse Interrupt). + * Return: + * true - Downstream port status changed. DM should call DC to do the + * detection. + * false - no change in Downstream port status. No further action required + * from DM. */ +bool dc_link_handle_hpd_rx_irq(struct dc_link *dc_link, + union hpd_irq_data *hpd_irq_dpcd_data); + +struct dc_sink_init_data; + +struct dc_sink *dc_link_add_remote_sink( + struct dc_link *dc_link, + const uint8_t *edid, + int len, + struct dc_sink_init_data *init_data); + +void dc_link_remove_remote_sink( + struct dc_link *link, + struct dc_sink *sink); + +/* Used by diagnostics for virtual link at the moment */ + +void dc_link_dp_set_drive_settings( + struct dc_link *link, + struct link_training_settings *lt_settings); + +enum link_training_result dc_link_dp_perform_link_training( + struct dc_link *link, + const struct dc_link_settings *link_setting, + bool skip_video_pattern); + +void dc_link_dp_enable_hpd(const struct dc_link *link); + +void dc_link_dp_disable_hpd(const struct dc_link *link); + +bool dc_link_dp_set_test_pattern( + struct dc_link *link, + enum dp_test_pattern test_pattern, + const struct link_training_settings *p_link_settings, + const unsigned char *p_custom_pattern, + unsigned int cust_pattern_size); + +/* + * DPCD access interfaces + */ + +bool dc_submit_i2c( + struct dc *dc, + uint32_t link_index, + struct i2c_command *cmd); + +#endif /* DC_LINK_H_ */ diff --git a/drivers/gpu/drm/amd/display/dc/dc_stream.h b/drivers/gpu/drm/amd/display/dc/dc_stream.h new file mode 100644 index 000000000000..01c60f11b2bd --- /dev/null +++ b/drivers/gpu/drm/amd/display/dc/dc_stream.h @@ -0,0 +1,293 @@ +/* + * Copyright 2012-14 Advanced Micro Devices, Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + * + * Authors: AMD + * + */ + +#ifndef DC_STREAM_H_ +#define DC_STREAM_H_ + +#include "dc_types.h" +#include "grph_object_defs.h" + +/******************************************************************************* + * Stream Interfaces + ******************************************************************************/ + +struct dc_stream_status { + int primary_otg_inst; + int stream_enc_inst; + int plane_count; + struct dc_plane_state *plane_states[MAX_SURFACE_NUM]; + + /* + * link this stream passes through + */ + struct dc_link *link; +}; + +struct dc_stream_state { + struct dc_sink *sink; + struct dc_crtc_timing timing; + + struct rect src; /* composition area */ + struct rect dst; /* stream addressable area */ + + struct audio_info audio_info; + + struct freesync_context freesync_ctx; + + struct dc_hdr_static_metadata hdr_static_metadata; + struct dc_transfer_func *out_transfer_func; + struct colorspace_transform gamut_remap_matrix; + struct csc_transform csc_color_matrix; + + enum dc_color_space output_color_space; + enum dc_dither_option dither_option; + + enum view_3d_format view_format; + + bool ignore_msa_timing_param; + /* TODO: custom INFO packets */ + /* TODO: ABM info (DMCU) */ + /* TODO: PSR info */ + /* TODO: CEA VIC */ + + /* from core_stream struct */ + struct dc_context *ctx; + + /* used by DCP and FMT */ + struct bit_depth_reduction_params bit_depth_params; + struct clamping_and_pixel_encoding_params clamping; + + int phy_pix_clk; + enum signal_type signal; + bool dpms_off; + + struct dc_stream_status status; + + struct dc_cursor_attributes cursor_attributes; + struct dc_cursor_position cursor_position; + + /* from stream struct */ + struct kref refcount; + + struct crtc_trigger_info triggered_crtc_reset; + + /* Computed state bits */ + bool mode_changed : 1; + +}; + +struct dc_stream_update { + struct rect src; + struct rect dst; + struct dc_transfer_func *out_transfer_func; + struct dc_hdr_static_metadata *hdr_static_metadata; +}; + +bool dc_is_stream_unchanged( + struct dc_stream_state *old_stream, struct dc_stream_state *stream); +bool dc_is_stream_scaling_unchanged( + struct dc_stream_state *old_stream, struct dc_stream_state *stream); + +/* + * Set up surface attributes and associate to a stream + * The surfaces parameter is an absolute set of all surface active for the stream. + * If no surfaces are provided, the stream will be blanked; no memory read. + * Any flip related attribute changes must be done through this interface. + * + * After this call: + * Surfaces attributes are programmed and configured to be composed into stream. + * This does not trigger a flip. No surface address is programmed. + */ + +bool dc_commit_planes_to_stream( + struct dc *dc, + struct dc_plane_state **plane_states, + uint8_t new_plane_count, + struct dc_stream_state *dc_stream, + struct dc_state *state); + +void dc_commit_updates_for_stream(struct dc *dc, + struct dc_surface_update *srf_updates, + int surface_count, + struct dc_stream_state *stream, + struct dc_stream_update *stream_update, + struct dc_plane_state **plane_states, + struct dc_state *state); +/* + * Log the current stream state. + */ +void dc_stream_log( + const struct dc_stream_state *stream, + struct dal_logger *dc_logger, + enum dc_log_type log_type); + +uint8_t dc_get_current_stream_count(struct dc *dc); +struct dc_stream_state *dc_get_stream_at_index(struct dc *dc, uint8_t i); + +/* + * Return the current frame counter. + */ +uint32_t dc_stream_get_vblank_counter(const struct dc_stream_state *stream); + +/* TODO: Return parsed values rather than direct register read + * This has a dependency on the caller (amdgpu_get_crtc_scanoutpos) + * being refactored properly to be dce-specific + */ +bool dc_stream_get_scanoutpos(const struct dc_stream_state *stream, + uint32_t *v_blank_start, + uint32_t *v_blank_end, + uint32_t *h_position, + uint32_t *v_position); + +enum dc_status dc_add_stream_to_ctx( + struct dc *dc, + struct dc_state *new_ctx, + struct dc_stream_state *stream); + +enum dc_status dc_remove_stream_from_ctx( + struct dc *dc, + struct dc_state *new_ctx, + struct dc_stream_state *stream); + + +bool dc_add_plane_to_context( + const struct dc *dc, + struct dc_stream_state *stream, + struct dc_plane_state *plane_state, + struct dc_state *context); + +bool dc_remove_plane_from_context( + const struct dc *dc, + struct dc_stream_state *stream, + struct dc_plane_state *plane_state, + struct dc_state *context); + +bool dc_rem_all_planes_for_stream( + const struct dc *dc, + struct dc_stream_state *stream, + struct dc_state *context); + +bool dc_add_all_planes_for_stream( + const struct dc *dc, + struct dc_stream_state *stream, + struct dc_plane_state * const *plane_states, + int plane_count, + struct dc_state *context); + +enum dc_status dc_validate_stream(struct dc *dc, struct dc_stream_state *stream); + +/* + * This function takes a stream and checks if it is guaranteed to be supported. + * Guaranteed means that MAX_COFUNC similar streams are supported. + * + * After this call: + * No hardware is programmed for call. Only validation is done. + */ + +/* + * Set up streams and links associated to drive sinks + * The streams parameter is an absolute set of all active streams. + * + * After this call: + * Phy, Encoder, Timing Generator are programmed and enabled. + * New streams are enabled with blank stream; no memory read. + */ +/* + * Enable stereo when commit_streams is not required, + * for example, frame alternate. + */ +bool dc_enable_stereo( + struct dc *dc, + struct dc_state *context, + struct dc_stream_state *streams[], + uint8_t stream_count); + + +enum surface_update_type dc_check_update_surfaces_for_stream( + struct dc *dc, + struct dc_surface_update *updates, + int surface_count, + struct dc_stream_update *stream_update, + const struct dc_stream_status *stream_status); + +/** + * Create a new default stream for the requested sink + */ +struct dc_stream_state *dc_create_stream_for_sink(struct dc_sink *dc_sink); + +void dc_stream_retain(struct dc_stream_state *dc_stream); +void dc_stream_release(struct dc_stream_state *dc_stream); + +struct dc_stream_status *dc_stream_get_status( + struct dc_stream_state *dc_stream); + +/******************************************************************************* + * Cursor interfaces - To manages the cursor within a stream + ******************************************************************************/ +/* TODO: Deprecated once we switch to dc_set_cursor_position */ +bool dc_stream_set_cursor_attributes( + struct dc_stream_state *stream, + const struct dc_cursor_attributes *attributes); + +bool dc_stream_set_cursor_position( + struct dc_stream_state *stream, + const struct dc_cursor_position *position); + +bool dc_stream_adjust_vmin_vmax(struct dc *dc, + struct dc_stream_state **stream, + int num_streams, + int vmin, + int vmax); + +bool dc_stream_get_crtc_position(struct dc *dc, + struct dc_stream_state **stream, + int num_streams, + unsigned int *v_pos, + unsigned int *nom_v_pos); + +void dc_stream_set_static_screen_events(struct dc *dc, + struct dc_stream_state **stream, + int num_streams, + const struct dc_static_screen_events *events); + + +bool dc_stream_adjust_vmin_vmax(struct dc *dc, + struct dc_stream_state **stream, + int num_streams, + int vmin, + int vmax); + +bool dc_stream_get_crtc_position(struct dc *dc, + struct dc_stream_state **stream, + int num_streams, + unsigned int *v_pos, + unsigned int *nom_v_pos); + +void dc_stream_set_static_screen_events(struct dc *dc, + struct dc_stream_state **stream, + int num_streams, + const struct dc_static_screen_events *events); + +#endif /* DC_STREAM_H_ */ diff --git a/drivers/gpu/drm/amd/display/dc/dc_types.h b/drivers/gpu/drm/amd/display/dc/dc_types.h index a8698e399111..9faddfae241d 100644 --- a/drivers/gpu/drm/amd/display/dc/dc_types.h +++ b/drivers/gpu/drm/amd/display/dc/dc_types.h @@ -218,6 +218,7 @@ struct dc_edid_caps { bool lte_340mcsc_scramble; bool edid_hdmi; + bool hdr_supported; }; struct view { @@ -638,11 +639,6 @@ struct colorspace_transform { bool enable_remap; }; -struct csc_transform { - uint16_t matrix[12]; - bool enable_adjustment; -}; - enum i2c_mot_mode { I2C_MOT_UNDEF, I2C_MOT_TRUE, diff --git a/drivers/gpu/drm/amd/display/dc/dce/dce_abm.c b/drivers/gpu/drm/amd/display/dc/dce/dce_abm.c index 0e0336c5af4e..b48190f54907 100644 --- a/drivers/gpu/drm/amd/display/dc/dce/dce_abm.c +++ b/drivers/gpu/drm/amd/display/dc/dce/dce_abm.c @@ -51,16 +51,6 @@ #define MCP_DISABLE_ABM_IMMEDIATELY 255 -struct abm_backlight_registers { - unsigned int BL_PWM_CNTL; - unsigned int BL_PWM_CNTL2; - unsigned int BL_PWM_PERIOD_CNTL; - unsigned int LVTMA_PWRSEQ_REF_DIV_BL_PWM_REF_DIV; -}; - -/* registers setting needs to be save and restored used at InitBacklight */ -static struct abm_backlight_registers stored_backlight_registers = {0}; - static unsigned int get_current_backlight_16_bit(struct dce_abm *abm_dce) { @@ -347,16 +337,16 @@ static bool dce_abm_init_backlight(struct abm *abm) */ REG_GET(BL_PWM_CNTL, BL_ACTIVE_INT_FRAC_CNT, &value); if (value == 0 || value == 1) { - if (stored_backlight_registers.BL_PWM_CNTL != 0) { + if (abm->stored_backlight_registers.BL_PWM_CNTL != 0) { REG_WRITE(BL_PWM_CNTL, - stored_backlight_registers.BL_PWM_CNTL); + abm->stored_backlight_registers.BL_PWM_CNTL); REG_WRITE(BL_PWM_CNTL2, - stored_backlight_registers.BL_PWM_CNTL2); + abm->stored_backlight_registers.BL_PWM_CNTL2); REG_WRITE(BL_PWM_PERIOD_CNTL, - stored_backlight_registers.BL_PWM_PERIOD_CNTL); + abm->stored_backlight_registers.BL_PWM_PERIOD_CNTL); REG_UPDATE(LVTMA_PWRSEQ_REF_DIV, BL_PWM_REF_DIV, - stored_backlight_registers. + abm->stored_backlight_registers. LVTMA_PWRSEQ_REF_DIV_BL_PWM_REF_DIV); } else { /* TODO: Note: This should not really happen since VBIOS @@ -366,15 +356,15 @@ static bool dce_abm_init_backlight(struct abm *abm) REG_WRITE(BL_PWM_PERIOD_CNTL, 0x000C0FA0); } } else { - stored_backlight_registers.BL_PWM_CNTL = + abm->stored_backlight_registers.BL_PWM_CNTL = REG_READ(BL_PWM_CNTL); - stored_backlight_registers.BL_PWM_CNTL2 = + abm->stored_backlight_registers.BL_PWM_CNTL2 = REG_READ(BL_PWM_CNTL2); - stored_backlight_registers.BL_PWM_PERIOD_CNTL = + abm->stored_backlight_registers.BL_PWM_PERIOD_CNTL = REG_READ(BL_PWM_PERIOD_CNTL); REG_GET(LVTMA_PWRSEQ_REF_DIV, BL_PWM_REF_DIV, - &stored_backlight_registers. + &abm->stored_backlight_registers. LVTMA_PWRSEQ_REF_DIV_BL_PWM_REF_DIV); } @@ -395,21 +385,12 @@ static bool dce_abm_init_backlight(struct abm *abm) return true; } -static bool is_dmcu_initialized(struct abm *abm) -{ - struct dce_abm *abm_dce = TO_DCE_ABM(abm); - unsigned int dmcu_uc_reset; - - REG_GET(DMCU_STATUS, UC_IN_RESET, &dmcu_uc_reset); - - return !dmcu_uc_reset; -} - static bool dce_abm_set_backlight_level( struct abm *abm, unsigned int backlight_level, unsigned int frame_ramp, - unsigned int controller_id) + unsigned int controller_id, + bool use_smooth_brightness) { struct dce_abm *abm_dce = TO_DCE_ABM(abm); @@ -418,7 +399,7 @@ static bool dce_abm_set_backlight_level( backlight_level, backlight_level); /* If DMCU is in reset state, DMCU is uninitialized */ - if (is_dmcu_initialized(abm)) + if (use_smooth_brightness) dmcu_set_backlight_level(abm_dce, backlight_level, frame_ramp, @@ -435,8 +416,7 @@ static const struct abm_funcs dce_funcs = { .init_backlight = dce_abm_init_backlight, .set_backlight_level = dce_abm_set_backlight_level, .get_current_backlight_8_bit = dce_abm_get_current_backlight_8_bit, - .set_abm_immediate_disable = dce_abm_immediate_disable, - .is_dmcu_initialized = is_dmcu_initialized + .set_abm_immediate_disable = dce_abm_immediate_disable }; static void dce_abm_construct( @@ -450,6 +430,10 @@ static void dce_abm_construct( base->ctx = ctx; base->funcs = &dce_funcs; + base->stored_backlight_registers.BL_PWM_CNTL = 0; + base->stored_backlight_registers.BL_PWM_CNTL2 = 0; + base->stored_backlight_registers.BL_PWM_PERIOD_CNTL = 0; + base->stored_backlight_registers.LVTMA_PWRSEQ_REF_DIV_BL_PWM_REF_DIV = 0; abm_dce->regs = regs; abm_dce->abm_shift = abm_shift; diff --git a/drivers/gpu/drm/amd/display/dc/dce/dce_abm.h b/drivers/gpu/drm/amd/display/dc/dce/dce_abm.h index 59e909ec88f2..ff9436966041 100644 --- a/drivers/gpu/drm/amd/display/dc/dce/dce_abm.h +++ b/drivers/gpu/drm/amd/display/dc/dce/dce_abm.h @@ -37,8 +37,7 @@ SR(LVTMA_PWRSEQ_REF_DIV), \ SR(MASTER_COMM_CNTL_REG), \ SR(MASTER_COMM_CMD_REG), \ - SR(MASTER_COMM_DATA_REG1), \ - SR(DMCU_STATUS) + SR(MASTER_COMM_DATA_REG1) #define ABM_DCE110_COMMON_REG_LIST() \ ABM_COMMON_REG_LIST_DCE_BASE(), \ @@ -84,8 +83,7 @@ ABM_SF(MASTER_COMM_CNTL_REG, MASTER_COMM_INTERRUPT, mask_sh), \ ABM_SF(MASTER_COMM_CMD_REG, MASTER_COMM_CMD_REG_BYTE0, mask_sh), \ ABM_SF(MASTER_COMM_CMD_REG, MASTER_COMM_CMD_REG_BYTE1, mask_sh), \ - ABM_SF(MASTER_COMM_CMD_REG, MASTER_COMM_CMD_REG_BYTE2, mask_sh), \ - ABM_SF(DMCU_STATUS, UC_IN_RESET, mask_sh) + ABM_SF(MASTER_COMM_CMD_REG, MASTER_COMM_CMD_REG_BYTE2, mask_sh) #define ABM_MASK_SH_LIST_DCE110(mask_sh) \ ABM_COMMON_MASK_SH_LIST_DCE_COMMON_BASE(mask_sh), \ @@ -174,7 +172,6 @@ type MASTER_COMM_CMD_REG_BYTE2; \ type BL_PWM_REF_DIV; \ type BL_PWM_EN; \ - type UC_IN_RESET; \ type BL_PWM_GRP1_IGNORE_MASTER_LOCK_EN; \ type BL_PWM_GRP1_REG_LOCK; \ type BL_PWM_GRP1_REG_UPDATE_PENDING @@ -206,7 +203,6 @@ struct dce_abm_registers { uint32_t MASTER_COMM_CMD_REG; uint32_t MASTER_COMM_DATA_REG1; uint32_t BIOS_SCRATCH_2; - uint32_t DMCU_STATUS; uint32_t BL_PWM_GRP1_REG_LOCK; }; diff --git a/drivers/gpu/drm/amd/display/dc/dce/dce_clocks.c b/drivers/gpu/drm/amd/display/dc/dce/dce_clocks.c index 9031d22285ea..9e98a5f39a6d 100644 --- a/drivers/gpu/drm/amd/display/dc/dce/dce_clocks.c +++ b/drivers/gpu/drm/amd/display/dc/dce/dce_clocks.c @@ -29,7 +29,6 @@ #include "fixed32_32.h" #include "bios_parser_interface.h" #include "dc.h" -#include "dce_abm.h" #include "dmcu.h" #if defined(CONFIG_DRM_AMD_DC_DCN1_0) #include "dcn_calcs.h" @@ -384,7 +383,6 @@ static int dce112_set_clock( struct bp_set_dce_clock_parameters dce_clk_params; struct dc_bios *bp = clk->ctx->dc_bios; struct dc *core_dc = clk->ctx->dc; - struct abm *abm = core_dc->res_pool->abm; struct dmcu *dmcu = core_dc->res_pool->dmcu; int actual_clock = requested_clk_khz; /* Prepare to program display clock*/ @@ -417,7 +415,7 @@ static int dce112_set_clock( bp->funcs->set_dce_clock(bp, &dce_clk_params); - if (abm->funcs->is_dmcu_initialized(abm) && clk_dce->dfs_bypass_disp_clk != actual_clock) + if (clk_dce->dfs_bypass_disp_clk != actual_clock) dmcu->funcs->set_psr_wait_loop(dmcu, actual_clock / 1000 / 7); clk_dce->dfs_bypass_disp_clk = actual_clock; diff --git a/drivers/gpu/drm/amd/display/dc/dce/dce_dmcu.c b/drivers/gpu/drm/amd/display/dc/dce/dce_dmcu.c index fd77df573b61..f663adb33584 100644 --- a/drivers/gpu/drm/amd/display/dc/dce/dce_dmcu.c +++ b/drivers/gpu/drm/amd/display/dc/dce/dce_dmcu.c @@ -49,8 +49,16 @@ #define PSR_EXIT 0x21 #define PSR_SET 0x23 #define PSR_SET_WAITLOOP 0x31 +#define MCP_INIT_DMCU 0x88 +#define MCP_INIT_IRAM 0x89 +#define MCP_DMCU_VERSION 0x90 #define MASTER_COMM_CNTL_REG__MASTER_COMM_INTERRUPT_MASK 0x00000001L -unsigned int cached_wait_loop_number = 0; + +static bool dce_dmcu_init(struct dmcu *dmcu) +{ + // Do nothing + return true; +} bool dce_dmcu_load_iram(struct dmcu *dmcu, unsigned int start_offset, @@ -84,7 +92,7 @@ static void dce_get_dmcu_psr_state(struct dmcu *dmcu, uint32_t *psr_state) { struct dce_dmcu *dmcu_dce = TO_DCE_DMCU(dmcu); - uint32_t psrStateOffset = 0xf0; + uint32_t psr_state_offset = 0xf0; /* Enable write access to IRAM */ REG_UPDATE(DMCU_RAM_ACCESS_CTRL, IRAM_HOST_ACCESS_EN, 1); @@ -92,7 +100,7 @@ static void dce_get_dmcu_psr_state(struct dmcu *dmcu, uint32_t *psr_state) REG_WAIT(DCI_MEM_PWR_STATUS, DMCU_IRAM_MEM_PWR_STATE, 0, 2, 10); /* Write address to IRAM_RD_ADDR in DMCU_IRAM_RD_CTRL */ - REG_WRITE(DMCU_IRAM_RD_CTRL, psrStateOffset); + REG_WRITE(DMCU_IRAM_RD_CTRL, psr_state_offset); /* Read data from IRAM_RD_DATA in DMCU_IRAM_RD_DATA*/ *psr_state = REG_READ(DMCU_IRAM_RD_DATA); @@ -255,13 +263,33 @@ static void dce_dmcu_setup_psr(struct dmcu *dmcu, REG_UPDATE(MASTER_COMM_CNTL_REG, MASTER_COMM_INTERRUPT, 1); } +static bool dce_is_dmcu_initialized(struct dmcu *dmcu) +{ + struct dce_dmcu *dmcu_dce = TO_DCE_DMCU(dmcu); + unsigned int dmcu_uc_reset; + + /* microcontroller is not running */ + REG_GET(DMCU_STATUS, UC_IN_RESET, &dmcu_uc_reset); + + /* DMCU is not running */ + if (dmcu_uc_reset) + return false; + + return true; +} + static void dce_psr_wait_loop( struct dmcu *dmcu, unsigned int wait_loop_number) { struct dce_dmcu *dmcu_dce = TO_DCE_DMCU(dmcu); union dce_dmcu_psr_config_data_wait_loop_reg1 masterCmdData1; - if (cached_wait_loop_number == wait_loop_number) + + if (dmcu->cached_wait_loop_number == wait_loop_number) + return; + + /* DMCU is not running */ + if (!dce_is_dmcu_initialized(dmcu)) return; /* waitDMCUReadyForCmd */ @@ -269,7 +297,7 @@ static void dce_psr_wait_loop( masterCmdData1.u32 = 0; masterCmdData1.bits.wait_loop = wait_loop_number; - cached_wait_loop_number = wait_loop_number; + dmcu->cached_wait_loop_number = wait_loop_number; dm_write_reg(dmcu->ctx, REG(MASTER_COMM_DATA_REG1), masterCmdData1.u32); /* setDMCUParam_Cmd */ @@ -279,14 +307,136 @@ static void dce_psr_wait_loop( REG_UPDATE(MASTER_COMM_CNTL_REG, MASTER_COMM_INTERRUPT, 1); } -static void dce_get_psr_wait_loop(unsigned int *psr_wait_loop_number) +static void dce_get_psr_wait_loop( + struct dmcu *dmcu, unsigned int *psr_wait_loop_number) { - *psr_wait_loop_number = cached_wait_loop_number; + *psr_wait_loop_number = dmcu->cached_wait_loop_number; return; } #if defined(CONFIG_DRM_AMD_DC_DCN1_0) -bool dcn10_dmcu_load_iram(struct dmcu *dmcu, +static void dcn10_get_dmcu_state(struct dmcu *dmcu) +{ + struct dce_dmcu *dmcu_dce = TO_DCE_DMCU(dmcu); + uint32_t dmcu_state_offset = 0xf6; + + /* Enable write access to IRAM */ + REG_UPDATE_2(DMCU_RAM_ACCESS_CTRL, + IRAM_HOST_ACCESS_EN, 1, + IRAM_RD_ADDR_AUTO_INC, 1); + + REG_WAIT(DMU_MEM_PWR_CNTL, DMCU_IRAM_MEM_PWR_STATE, 0, 2, 10); + + /* Write address to IRAM_RD_ADDR in DMCU_IRAM_RD_CTRL */ + REG_WRITE(DMCU_IRAM_RD_CTRL, dmcu_state_offset); + + /* Read data from IRAM_RD_DATA in DMCU_IRAM_RD_DATA*/ + dmcu->dmcu_state = REG_READ(DMCU_IRAM_RD_DATA); + + /* Disable write access to IRAM to allow dynamic sleep state */ + REG_UPDATE_2(DMCU_RAM_ACCESS_CTRL, + IRAM_HOST_ACCESS_EN, 0, + IRAM_RD_ADDR_AUTO_INC, 0); +} + +static void dcn10_get_dmcu_version(struct dmcu *dmcu) +{ + struct dce_dmcu *dmcu_dce = TO_DCE_DMCU(dmcu); + uint32_t dmcu_version_offset = 0xf1; + + /* Clear scratch */ + REG_WRITE(DC_DMCU_SCRATCH, 0); + + /* Enable write access to IRAM */ + REG_UPDATE_2(DMCU_RAM_ACCESS_CTRL, + IRAM_HOST_ACCESS_EN, 1, + IRAM_RD_ADDR_AUTO_INC, 1); + + REG_WAIT(DMU_MEM_PWR_CNTL, DMCU_IRAM_MEM_PWR_STATE, 0, 2, 10); + + /* Write address to IRAM_RD_ADDR and read from DATA register */ + REG_WRITE(DMCU_IRAM_RD_CTRL, dmcu_version_offset); + dmcu->dmcu_version.interface_version = REG_READ(DMCU_IRAM_RD_DATA); + dmcu->dmcu_version.year = ((REG_READ(DMCU_IRAM_RD_DATA) << 8) | + REG_READ(DMCU_IRAM_RD_DATA)); + dmcu->dmcu_version.month = REG_READ(DMCU_IRAM_RD_DATA); + dmcu->dmcu_version.day = REG_READ(DMCU_IRAM_RD_DATA); + + /* Disable write access to IRAM to allow dynamic sleep state */ + REG_UPDATE_2(DMCU_RAM_ACCESS_CTRL, + IRAM_HOST_ACCESS_EN, 0, + IRAM_RD_ADDR_AUTO_INC, 0); + + /* Send MCP command message to DMCU to get version reply from FW. + * We expect this version should match the one in IRAM, otherwise + * something is wrong with DMCU and we should fail and disable UC. + */ + REG_WAIT(MASTER_COMM_CNTL_REG, MASTER_COMM_INTERRUPT, 0, 100, 800); + + /* Set command to get DMCU version from microcontroller */ + REG_UPDATE(MASTER_COMM_CMD_REG, MASTER_COMM_CMD_REG_BYTE0, + MCP_DMCU_VERSION); + + /* Notify microcontroller of new command */ + REG_UPDATE(MASTER_COMM_CNTL_REG, MASTER_COMM_INTERRUPT, 1); + + /* Ensure command has been executed before continuing */ + REG_WAIT(MASTER_COMM_CNTL_REG, MASTER_COMM_INTERRUPT, 0, 100, 800); + + /* Somehow version does not match, so fail and return version 0 */ + if (dmcu->dmcu_version.interface_version != REG_READ(DC_DMCU_SCRATCH)) + dmcu->dmcu_version.interface_version = 0; +} + +static bool dcn10_dmcu_init(struct dmcu *dmcu) +{ + struct dce_dmcu *dmcu_dce = TO_DCE_DMCU(dmcu); + + /* DMCU FW should populate the scratch register if running */ + if (REG_READ(DC_DMCU_SCRATCH) == 0) + return false; + + /* Check state is uninitialized */ + dcn10_get_dmcu_state(dmcu); + + /* If microcontroller is already initialized, do nothing */ + if (dmcu->dmcu_state == DMCU_RUNNING) + return true; + + /* Retrieve and cache the DMCU firmware version. */ + dcn10_get_dmcu_version(dmcu); + + /* Check interface version to confirm firmware is loaded and running */ + if (dmcu->dmcu_version.interface_version == 0) + return false; + + /* Wait until microcontroller is ready to process interrupt */ + REG_WAIT(MASTER_COMM_CNTL_REG, MASTER_COMM_INTERRUPT, 0, 100, 800); + + /* Set initialized ramping boundary value */ + REG_WRITE(MASTER_COMM_DATA_REG1, 0xFFFF); + + /* Set command to initialize microcontroller */ + REG_UPDATE(MASTER_COMM_CMD_REG, MASTER_COMM_CMD_REG_BYTE0, + MCP_INIT_DMCU); + + /* Notify microcontroller of new command */ + REG_UPDATE(MASTER_COMM_CNTL_REG, MASTER_COMM_INTERRUPT, 1); + + /* Ensure command has been executed before continuing */ + REG_WAIT(MASTER_COMM_CNTL_REG, MASTER_COMM_INTERRUPT, 0, 100, 800); + + // Check state is initialized + dcn10_get_dmcu_state(dmcu); + + // If microcontroller is not in running state, fail + if (dmcu->dmcu_state != DMCU_RUNNING) + return false; + + return true; +} + +static bool dcn10_dmcu_load_iram(struct dmcu *dmcu, unsigned int start_offset, const char *src, unsigned int bytes) @@ -294,7 +444,9 @@ bool dcn10_dmcu_load_iram(struct dmcu *dmcu, struct dce_dmcu *dmcu_dce = TO_DCE_DMCU(dmcu); unsigned int count = 0; - REG_UPDATE(DMCU_CTRL, DMCU_ENABLE, 1); + /* If microcontroller is not running, do nothing */ + if (dmcu->dmcu_state != DMCU_RUNNING) + return false; /* Enable write access to IRAM */ REG_UPDATE_2(DMCU_RAM_ACCESS_CTRL, @@ -313,6 +465,19 @@ bool dcn10_dmcu_load_iram(struct dmcu *dmcu, IRAM_HOST_ACCESS_EN, 0, IRAM_WR_ADDR_AUTO_INC, 0); + /* Wait until microcontroller is ready to process interrupt */ + REG_WAIT(MASTER_COMM_CNTL_REG, MASTER_COMM_INTERRUPT, 0, 100, 800); + + /* Set command to signal IRAM is loaded and to initialize IRAM */ + REG_UPDATE(MASTER_COMM_CMD_REG, MASTER_COMM_CMD_REG_BYTE0, + MCP_INIT_IRAM); + + /* Notify microcontroller of new command */ + REG_UPDATE(MASTER_COMM_CNTL_REG, MASTER_COMM_INTERRUPT, 1); + + /* Ensure command has been executed before continuing */ + REG_WAIT(MASTER_COMM_CNTL_REG, MASTER_COMM_INTERRUPT, 0, 100, 800); + return true; } @@ -320,7 +485,11 @@ static void dcn10_get_dmcu_psr_state(struct dmcu *dmcu, uint32_t *psr_state) { struct dce_dmcu *dmcu_dce = TO_DCE_DMCU(dmcu); - uint32_t psrStateOffset = 0xf0; + uint32_t psr_state_offset = 0xf0; + + /* If microcontroller is not running, do nothing */ + if (dmcu->dmcu_state != DMCU_RUNNING) + return; /* Enable write access to IRAM */ REG_UPDATE(DMCU_RAM_ACCESS_CTRL, IRAM_HOST_ACCESS_EN, 1); @@ -328,7 +497,7 @@ static void dcn10_get_dmcu_psr_state(struct dmcu *dmcu, uint32_t *psr_state) REG_WAIT(DMU_MEM_PWR_CNTL, DMCU_IRAM_MEM_PWR_STATE, 0, 2, 10); /* Write address to IRAM_RD_ADDR in DMCU_IRAM_RD_CTRL */ - REG_WRITE(DMCU_IRAM_RD_CTRL, psrStateOffset); + REG_WRITE(DMCU_IRAM_RD_CTRL, psr_state_offset); /* Read data from IRAM_RD_DATA in DMCU_IRAM_RD_DATA*/ *psr_state = REG_READ(DMCU_IRAM_RD_DATA); @@ -348,6 +517,10 @@ static void dcn10_dmcu_set_psr_enable(struct dmcu *dmcu, bool enable, bool wait) unsigned int retryCount; uint32_t psr_state = 0; + /* If microcontroller is not running, do nothing */ + if (dmcu->dmcu_state != DMCU_RUNNING) + return; + /* waitDMCUReadyForCmd */ REG_WAIT(MASTER_COMM_CNTL_REG, MASTER_COMM_INTERRUPT, 0, dmcu_wait_reg_ready_interval, @@ -399,6 +572,10 @@ static void dcn10_dmcu_setup_psr(struct dmcu *dmcu, union dce_dmcu_psr_config_data_reg2 masterCmdData2; union dce_dmcu_psr_config_data_reg3 masterCmdData3; + /* If microcontroller is not running, do nothing */ + if (dmcu->dmcu_state != DMCU_RUNNING) + return; + link->link_enc->funcs->psr_program_dp_dphy_fast_training(link->link_enc, psr_context->psrExitLinkTrainingRequired); @@ -505,13 +682,18 @@ static void dcn10_psr_wait_loop( { struct dce_dmcu *dmcu_dce = TO_DCE_DMCU(dmcu); union dce_dmcu_psr_config_data_wait_loop_reg1 masterCmdData1; + + /* If microcontroller is not running, do nothing */ + if (dmcu->dmcu_state != DMCU_RUNNING) + return; + if (wait_loop_number != 0) { /* waitDMCUReadyForCmd */ REG_WAIT(MASTER_COMM_CNTL_REG, MASTER_COMM_INTERRUPT, 0, 1, 10000); masterCmdData1.u32 = 0; masterCmdData1.bits.wait_loop = wait_loop_number; - cached_wait_loop_number = wait_loop_number; + dmcu->cached_wait_loop_number = wait_loop_number; dm_write_reg(dmcu->ctx, REG(MASTER_COMM_DATA_REG1), masterCmdData1.u32); /* setDMCUParam_Cmd */ @@ -522,31 +704,44 @@ static void dcn10_psr_wait_loop( } } -static void dcn10_get_psr_wait_loop(unsigned int *psr_wait_loop_number) +static void dcn10_get_psr_wait_loop( + struct dmcu *dmcu, unsigned int *psr_wait_loop_number) { - *psr_wait_loop_number = cached_wait_loop_number; + *psr_wait_loop_number = dmcu->cached_wait_loop_number; return; } +static bool dcn10_is_dmcu_initialized(struct dmcu *dmcu) +{ + /* microcontroller is not running */ + if (dmcu->dmcu_state != DMCU_RUNNING) + return false; + return true; +} + #endif static const struct dmcu_funcs dce_funcs = { + .dmcu_init = dce_dmcu_init, .load_iram = dce_dmcu_load_iram, .set_psr_enable = dce_dmcu_set_psr_enable, .setup_psr = dce_dmcu_setup_psr, .get_psr_state = dce_get_dmcu_psr_state, .set_psr_wait_loop = dce_psr_wait_loop, - .get_psr_wait_loop = dce_get_psr_wait_loop + .get_psr_wait_loop = dce_get_psr_wait_loop, + .is_dmcu_initialized = dce_is_dmcu_initialized }; #if defined(CONFIG_DRM_AMD_DC_DCN1_0) static const struct dmcu_funcs dcn10_funcs = { + .dmcu_init = dcn10_dmcu_init, .load_iram = dcn10_dmcu_load_iram, .set_psr_enable = dcn10_dmcu_set_psr_enable, .setup_psr = dcn10_dmcu_setup_psr, .get_psr_state = dcn10_get_dmcu_psr_state, .set_psr_wait_loop = dcn10_psr_wait_loop, - .get_psr_wait_loop = dcn10_get_psr_wait_loop + .get_psr_wait_loop = dcn10_get_psr_wait_loop, + .is_dmcu_initialized = dcn10_is_dmcu_initialized }; #endif @@ -561,6 +756,7 @@ static void dce_dmcu_construct( base->ctx = ctx; base->funcs = &dce_funcs; + base->cached_wait_loop_number = 0; dmcu_dce->regs = regs; dmcu_dce->dmcu_shift = dmcu_shift; diff --git a/drivers/gpu/drm/amd/display/dc/dce/dce_dmcu.h b/drivers/gpu/drm/amd/display/dc/dce/dce_dmcu.h index b85f53c2f6f8..1d4546f23135 100644 --- a/drivers/gpu/drm/amd/display/dc/dce/dce_dmcu.h +++ b/drivers/gpu/drm/amd/display/dc/dce/dce_dmcu.h @@ -31,6 +31,7 @@ #define DMCU_COMMON_REG_LIST_DCE_BASE() \ SR(DMCU_CTRL), \ + SR(DMCU_STATUS), \ SR(DMCU_RAM_ACCESS_CTRL), \ SR(DMCU_IRAM_WR_CTRL), \ SR(DMCU_IRAM_WR_DATA), \ @@ -42,7 +43,8 @@ SR(DMCU_IRAM_RD_CTRL), \ SR(DMCU_IRAM_RD_DATA), \ SR(DMCU_INTERRUPT_TO_UC_EN_MASK), \ - SR(SMU_INTERRUPT_CONTROL) + SR(SMU_INTERRUPT_CONTROL), \ + SR(DC_DMCU_SCRATCH) #define DMCU_DCE110_COMMON_REG_LIST() \ DMCU_COMMON_REG_LIST_DCE_BASE(), \ @@ -58,10 +60,16 @@ #define DMCU_COMMON_MASK_SH_LIST_DCE_COMMON_BASE(mask_sh) \ DMCU_SF(DMCU_CTRL, \ DMCU_ENABLE, mask_sh), \ + DMCU_SF(DMCU_STATUS, \ + UC_IN_STOP_MODE, mask_sh), \ + DMCU_SF(DMCU_STATUS, \ + UC_IN_RESET, mask_sh), \ DMCU_SF(DMCU_RAM_ACCESS_CTRL, \ IRAM_HOST_ACCESS_EN, mask_sh), \ DMCU_SF(DMCU_RAM_ACCESS_CTRL, \ IRAM_WR_ADDR_AUTO_INC, mask_sh), \ + DMCU_SF(DMCU_RAM_ACCESS_CTRL, \ + IRAM_RD_ADDR_AUTO_INC, mask_sh), \ DMCU_SF(MASTER_COMM_CMD_REG, \ MASTER_COMM_CMD_REG_BYTE0, mask_sh), \ DMCU_SF(MASTER_COMM_CNTL_REG, MASTER_COMM_INTERRUPT, mask_sh), \ @@ -89,7 +97,10 @@ type DMCU_IRAM_MEM_PWR_STATE; \ type IRAM_HOST_ACCESS_EN; \ type IRAM_WR_ADDR_AUTO_INC; \ + type IRAM_RD_ADDR_AUTO_INC; \ type DMCU_ENABLE; \ + type UC_IN_STOP_MODE; \ + type UC_IN_RESET; \ type MASTER_COMM_CMD_REG_BYTE0; \ type MASTER_COMM_INTERRUPT; \ type DPHY_RX_FAST_TRAINING_CAPABLE; \ @@ -112,6 +123,7 @@ struct dce_dmcu_mask { struct dce_dmcu_registers { uint32_t DMCU_CTRL; + uint32_t DMCU_STATUS; uint32_t DMCU_RAM_ACCESS_CTRL; uint32_t DCI_MEM_PWR_STATUS; uint32_t DMU_MEM_PWR_CNTL; @@ -127,6 +139,7 @@ struct dce_dmcu_registers { uint32_t DMCU_IRAM_RD_DATA; uint32_t DMCU_INTERRUPT_TO_UC_EN_MASK; uint32_t SMU_INTERRUPT_CONTROL; + uint32_t DC_DMCU_SCRATCH; }; struct dce_dmcu { diff --git a/drivers/gpu/drm/amd/display/dc/dce/dce_hwseq.h b/drivers/gpu/drm/amd/display/dc/dce/dce_hwseq.h index 52506155e361..b73db9e78437 100644 --- a/drivers/gpu/drm/amd/display/dc/dce/dce_hwseq.h +++ b/drivers/gpu/drm/amd/display/dc/dce/dce_hwseq.h @@ -140,10 +140,6 @@ BL_REG_LIST() #define HWSEQ_DCN_REG_LIST()\ - SRII(OTG_GLOBAL_SYNC_STATUS, OTG, 0), \ - SRII(OTG_GLOBAL_SYNC_STATUS, OTG, 1), \ - SRII(OTG_GLOBAL_SYNC_STATUS, OTG, 2), \ - SRII(OTG_GLOBAL_SYNC_STATUS, OTG, 3), \ SRII(DCHUBP_CNTL, HUBP, 0), \ SRII(DCHUBP_CNTL, HUBP, 1), \ SRII(DCHUBP_CNTL, HUBP, 2), \ @@ -264,7 +260,6 @@ struct dce_hwseq_registers { uint32_t DCHUB_AGP_BOT; uint32_t DCHUB_AGP_TOP; - uint32_t OTG_GLOBAL_SYNC_STATUS[4]; uint32_t DCHUBP_CNTL[4]; uint32_t HUBP_CLK_CNTL[4]; uint32_t DPP_CONTROL[4]; @@ -438,8 +433,6 @@ struct dce_hwseq_registers { #define HWSEQ_DCN_MASK_SH_LIST(mask_sh)\ HWSEQ_PIXEL_RATE_MASK_SH_LIST(mask_sh, OTG0_),\ HWS_SF1(OTG0_, PHYPLL_PIXEL_RATE_CNTL, PHYPLL_PIXEL_RATE_SOURCE, mask_sh), \ - HWS_SF(OTG0_, OTG_GLOBAL_SYNC_STATUS, VUPDATE_NO_LOCK_EVENT_CLEAR, mask_sh), \ - HWS_SF(OTG0_, OTG_GLOBAL_SYNC_STATUS, VUPDATE_NO_LOCK_EVENT_OCCURRED, mask_sh), \ HWS_SF(HUBP0_, DCHUBP_CNTL, HUBP_VTG_SEL, mask_sh), \ HWS_SF(HUBP0_, HUBP_CLK_CNTL, HUBP_CLOCK_ENABLE, mask_sh), \ HWS_SF(DPP_TOP0_, DPP_CONTROL, DPP_CLOCK_ENABLE, mask_sh), \ @@ -536,8 +529,6 @@ struct dce_hwseq_registers { type LVTMA_PWRSEQ_TARGET_STATE_R; #define HWSEQ_DCN_REG_FIELD_LIST(type) \ - type VUPDATE_NO_LOCK_EVENT_CLEAR; \ - type VUPDATE_NO_LOCK_EVENT_OCCURRED; \ type HUBP_VTG_SEL; \ type HUBP_CLOCK_ENABLE; \ type DPP_CLOCK_ENABLE; \ @@ -591,7 +582,8 @@ struct dce_hwseq_registers { type DOMAIN7_PGFSM_PWR_STATUS; \ type DCFCLK_GATE_DIS; \ type DCHUBBUB_GLOBAL_TIMER_REFDIV; \ - type DENTIST_DPPCLK_WDIVIDER; + type DENTIST_DPPCLK_WDIVIDER; \ + type DENTIST_DISPCLK_WDIVIDER; struct dce_hwseq_shift { HWSEQ_REG_FIELD_LIST(uint8_t) diff --git a/drivers/gpu/drm/amd/display/dc/dce/dce_ipp.c b/drivers/gpu/drm/amd/display/dc/dce/dce_ipp.c index d618fdd0cc82..d737e911971b 100644 --- a/drivers/gpu/drm/amd/display/dc/dce/dce_ipp.c +++ b/drivers/gpu/drm/amd/display/dc/dce/dce_ipp.c @@ -135,36 +135,34 @@ static void dce_ipp_cursor_set_attributes( } -static void dce_ipp_program_prescale( - struct input_pixel_processor *ipp, - struct ipp_prescale_params *params) +static void dce_ipp_program_prescale(struct input_pixel_processor *ipp, + struct ipp_prescale_params *params) { struct dce_ipp *ipp_dce = TO_DCE_IPP(ipp); /* set to bypass mode first before change */ REG_UPDATE(PRESCALE_GRPH_CONTROL, - GRPH_PRESCALE_BYPASS, - 1); + GRPH_PRESCALE_BYPASS, 1); REG_SET_2(PRESCALE_VALUES_GRPH_R, 0, - GRPH_PRESCALE_SCALE_R, params->scale, - GRPH_PRESCALE_BIAS_R, params->bias); + GRPH_PRESCALE_SCALE_R, params->scale, + GRPH_PRESCALE_BIAS_R, params->bias); REG_SET_2(PRESCALE_VALUES_GRPH_G, 0, - GRPH_PRESCALE_SCALE_G, params->scale, - GRPH_PRESCALE_BIAS_G, params->bias); + GRPH_PRESCALE_SCALE_G, params->scale, + GRPH_PRESCALE_BIAS_G, params->bias); REG_SET_2(PRESCALE_VALUES_GRPH_B, 0, - GRPH_PRESCALE_SCALE_B, params->scale, - GRPH_PRESCALE_BIAS_B, params->bias); + GRPH_PRESCALE_SCALE_B, params->scale, + GRPH_PRESCALE_BIAS_B, params->bias); if (params->mode != IPP_PRESCALE_MODE_BYPASS) { REG_UPDATE(PRESCALE_GRPH_CONTROL, - GRPH_PRESCALE_BYPASS, 0); + GRPH_PRESCALE_BYPASS, 0); /* If prescale is in use, then legacy lut should be bypassed */ REG_UPDATE(INPUT_GAMMA_CONTROL, - GRPH_INPUT_GAMMA_MODE, 1); + GRPH_INPUT_GAMMA_MODE, 1); } } @@ -223,13 +221,12 @@ static void dce_ipp_set_degamma( struct dce_ipp *ipp_dce = TO_DCE_IPP(ipp); uint32_t degamma_type = (mode == IPP_DEGAMMA_MODE_HW_sRGB) ? 1 : 0; - ASSERT(mode == IPP_DEGAMMA_MODE_BYPASS || - mode == IPP_DEGAMMA_MODE_HW_sRGB); + ASSERT(mode == IPP_DEGAMMA_MODE_BYPASS || mode == IPP_DEGAMMA_MODE_HW_sRGB); REG_SET_3(DEGAMMA_CONTROL, 0, - GRPH_DEGAMMA_MODE, degamma_type, - CURSOR_DEGAMMA_MODE, degamma_type, - CURSOR2_DEGAMMA_MODE, degamma_type); + GRPH_DEGAMMA_MODE, degamma_type, + CURSOR_DEGAMMA_MODE, degamma_type, + CURSOR2_DEGAMMA_MODE, degamma_type); } static const struct ipp_funcs dce_ipp_funcs = { diff --git a/drivers/gpu/drm/amd/display/dc/dce/dce_link_encoder.c b/drivers/gpu/drm/amd/display/dc/dce/dce_link_encoder.c index fe88852b4774..a266e3f5e75f 100644 --- a/drivers/gpu/drm/amd/display/dc/dce/dce_link_encoder.c +++ b/drivers/gpu/drm/amd/display/dc/dce/dce_link_encoder.c @@ -845,8 +845,6 @@ void dce110_link_encoder_hw_init( ASSERT(result == BP_RESULT_OK); - } else if (enc110->base.connector.id == CONNECTOR_ID_EDP) { - ctx->dc->hwss.edp_power_control(enc, true); } aux_initialize(enc110); @@ -1033,8 +1031,7 @@ void dce110_link_encoder_enable_dp_mst_output( */ void dce110_link_encoder_disable_output( struct link_encoder *enc, - enum signal_type signal, - struct dc_link *link) + enum signal_type signal) { struct dce110_link_encoder *enc110 = TO_DCE110_LINK_ENC(enc); struct dc_context *ctx = enc110->base.ctx; @@ -1045,8 +1042,6 @@ void dce110_link_encoder_disable_output( /* OF_SKIP_POWER_DOWN_INACTIVE_ENCODER */ return; } - if (enc110->base.connector.id == CONNECTOR_ID_EDP) - ctx->dc->hwss.edp_backlight_control(link, false); /* Power-down RX and disable GPU PHY should be paired. * Disabling PHY without powering down RX may cause * symbol lock loss, on which we will get DP Sink interrupt. */ @@ -1077,20 +1072,6 @@ void dce110_link_encoder_disable_output( /* disable encoder */ if (dc_is_dp_signal(signal)) link_encoder_disable(enc110); - - if (enc110->base.connector.id == CONNECTOR_ID_EDP) { - /* power down eDP panel */ - /* TODO: Power control cause regression, we should implement - * it properly, for now just comment it. - * - * link_encoder_edp_wait_for_hpd_ready( - link_enc, - link_enc->connector, - false); - - * link_encoder_edp_power_control( - link_enc, false); */ - } } void dce110_link_encoder_dp_set_lane_settings( diff --git a/drivers/gpu/drm/amd/display/dc/dce/dce_link_encoder.h b/drivers/gpu/drm/amd/display/dc/dce/dce_link_encoder.h index 494067dedd03..8ca9afe47a2b 100644 --- a/drivers/gpu/drm/amd/display/dc/dce/dce_link_encoder.h +++ b/drivers/gpu/drm/amd/display/dc/dce/dce_link_encoder.h @@ -228,9 +228,8 @@ void dce110_link_encoder_enable_dp_mst_output( /* disable PHY output */ void dce110_link_encoder_disable_output( - struct link_encoder *link_enc, - enum signal_type signal, - struct dc_link *link); + struct link_encoder *enc, + enum signal_type signal); /* set DP lane settings */ void dce110_link_encoder_dp_set_lane_settings( diff --git a/drivers/gpu/drm/amd/display/dc/dce/dce_stream_encoder.c b/drivers/gpu/drm/amd/display/dc/dce/dce_stream_encoder.c index e42b6eb1c1f0..83bae207371d 100644 --- a/drivers/gpu/drm/amd/display/dc/dce/dce_stream_encoder.c +++ b/drivers/gpu/drm/amd/display/dc/dce/dce_stream_encoder.c @@ -300,6 +300,8 @@ static void dce110_stream_encoder_dp_set_stream_attribute( uint32_t h_back_porch; uint8_t synchronous_clock = 0; /* asynchronous mode */ uint8_t colorimetry_bpc; + uint8_t dynamic_range_rgb = 0; /*full range*/ + uint8_t dynamic_range_ycbcr = 1; /*bt709*/ #endif struct dce110_stream_encoder *enc110 = DCE110STRENC_FROM_STRENC(enc); @@ -380,11 +382,7 @@ static void dce110_stream_encoder_dp_set_stream_attribute( } /* set dynamic range and YCbCr range */ - if (enc110->se_mask->DP_DYN_RANGE && enc110->se_mask->DP_YCBCR_RANGE) - REG_UPDATE_2( - DP_PIXEL_FORMAT, - DP_DYN_RANGE, 0, - DP_YCBCR_RANGE, 0); + #if defined(CONFIG_DRM_AMD_DC_DCN1_0) switch (crtc_timing->display_color_depth) { @@ -413,37 +411,57 @@ static void dce110_stream_encoder_dp_set_stream_attribute( case COLOR_SPACE_SRGB: misc0 = misc0 | 0x0; misc1 = misc1 & ~0x80; /* bit7 = 0*/ + dynamic_range_rgb = 0; /*full range*/ break; case COLOR_SPACE_SRGB_LIMITED: misc0 = misc0 | 0x8; /* bit3=1 */ misc1 = misc1 & ~0x80; /* bit7 = 0*/ + dynamic_range_rgb = 1; /*limited range*/ break; case COLOR_SPACE_YCBCR601: + case COLOR_SPACE_YCBCR601_LIMITED: misc0 = misc0 | 0x8; /* bit3=1, bit4=0 */ misc1 = misc1 & ~0x80; /* bit7 = 0*/ + dynamic_range_ycbcr = 0; /*bt601*/ if (crtc_timing->pixel_encoding == PIXEL_ENCODING_YCBCR422) misc0 = misc0 | 0x2; /* bit2=0, bit1=1 */ else if (crtc_timing->pixel_encoding == PIXEL_ENCODING_YCBCR444) misc0 = misc0 | 0x4; /* bit2=1, bit1=0 */ break; case COLOR_SPACE_YCBCR709: + case COLOR_SPACE_YCBCR709_LIMITED: misc0 = misc0 | 0x18; /* bit3=1, bit4=1 */ misc1 = misc1 & ~0x80; /* bit7 = 0*/ + dynamic_range_ycbcr = 1; /*bt709*/ if (crtc_timing->pixel_encoding == PIXEL_ENCODING_YCBCR422) misc0 = misc0 | 0x2; /* bit2=0, bit1=1 */ else if (crtc_timing->pixel_encoding == PIXEL_ENCODING_YCBCR444) misc0 = misc0 | 0x4; /* bit2=1, bit1=0 */ break; - case COLOR_SPACE_2020_RGB_FULLRANGE: case COLOR_SPACE_2020_RGB_LIMITEDRANGE: + dynamic_range_rgb = 1; /*limited range*/ + break; + case COLOR_SPACE_2020_RGB_FULLRANGE: case COLOR_SPACE_2020_YCBCR: + case COLOR_SPACE_XR_RGB: + case COLOR_SPACE_MSREF_SCRGB: case COLOR_SPACE_ADOBERGB: + case COLOR_SPACE_DCIP3: + case COLOR_SPACE_XV_YCC_709: + case COLOR_SPACE_XV_YCC_601: + case COLOR_SPACE_DISPLAYNATIVE: + case COLOR_SPACE_DOLBYVISION: + case COLOR_SPACE_APPCTRL: + case COLOR_SPACE_CUSTOMPOINTS: case COLOR_SPACE_UNKNOWN: - case COLOR_SPACE_YCBCR601_LIMITED: - case COLOR_SPACE_YCBCR709_LIMITED: /* do nothing */ break; } + if (enc110->se_mask->DP_DYN_RANGE && enc110->se_mask->DP_YCBCR_RANGE) + REG_UPDATE_2( + DP_PIXEL_FORMAT, + DP_DYN_RANGE, dynamic_range_rgb, + DP_YCBCR_RANGE, dynamic_range_ycbcr); #if defined(CONFIG_DRM_AMD_DC_DCN1_0) if (REG(DP_MSA_COLORIMETRY)) diff --git a/drivers/gpu/drm/amd/display/dc/dce/dce_transform.c b/drivers/gpu/drm/amd/display/dc/dce/dce_transform.c index ae32af31eff1..0f662e6ee9bd 100644 --- a/drivers/gpu/drm/amd/display/dc/dce/dce_transform.c +++ b/drivers/gpu/drm/amd/display/dc/dce/dce_transform.c @@ -1177,207 +1177,160 @@ void dce110_opp_set_csc_default( default_adjust->out_color_space); } -static void program_pwl( - struct dce_transform *xfm_dce, - const struct pwl_params *params) +static void program_pwl(struct dce_transform *xfm_dce, + const struct pwl_params *params) { - uint32_t value; int retval; + uint8_t max_tries = 10; + uint8_t counter = 0; + uint32_t i = 0; + const struct pwl_result_data *rgb = params->rgb_resulted; - { - uint8_t max_tries = 10; - uint8_t counter = 0; + /* Power on LUT memory */ + if (REG(DCFE_MEM_PWR_CTRL)) + REG_UPDATE(DCFE_MEM_PWR_CTRL, + DCP_REGAMMA_MEM_PWR_DIS, 1); + else + REG_UPDATE(DCFE_MEM_LIGHT_SLEEP_CNTL, + REGAMMA_LUT_LIGHT_SLEEP_DIS, 1); - /* Power on LUT memory */ - if (REG(DCFE_MEM_PWR_CTRL)) - REG_UPDATE(DCFE_MEM_PWR_CTRL, - DCP_REGAMMA_MEM_PWR_DIS, 1); - else - REG_UPDATE(DCFE_MEM_LIGHT_SLEEP_CNTL, - REGAMMA_LUT_LIGHT_SLEEP_DIS, 1); - - while (counter < max_tries) { - if (REG(DCFE_MEM_PWR_STATUS)) { - value = REG_READ(DCFE_MEM_PWR_STATUS); - REG_GET(DCFE_MEM_PWR_STATUS, - DCP_REGAMMA_MEM_PWR_STATE, - &retval); - - if (retval == 0) - break; - ++counter; - } else { - value = REG_READ(DCFE_MEM_LIGHT_SLEEP_CNTL); - REG_GET(DCFE_MEM_LIGHT_SLEEP_CNTL, - REGAMMA_LUT_MEM_PWR_STATE, - &retval); - - if (retval == 0) - break; - ++counter; - } + while (counter < max_tries) { + if (REG(DCFE_MEM_PWR_STATUS)) { + REG_GET(DCFE_MEM_PWR_STATUS, + DCP_REGAMMA_MEM_PWR_STATE, + &retval); + + if (retval == 0) + break; + ++counter; + } else { + REG_GET(DCFE_MEM_LIGHT_SLEEP_CNTL, + REGAMMA_LUT_MEM_PWR_STATE, + &retval); + + if (retval == 0) + break; + ++counter; } + } - if (counter == max_tries) { - dm_logger_write(xfm_dce->base.ctx->logger, LOG_WARNING, + if (counter == max_tries) { + dm_logger_write(xfm_dce->base.ctx->logger, LOG_WARNING, "%s: regamma lut was not powered on " "in a timely manner," " programming still proceeds\n", __func__); - } } REG_UPDATE(REGAMMA_LUT_WRITE_EN_MASK, - REGAMMA_LUT_WRITE_EN_MASK, 7); + REGAMMA_LUT_WRITE_EN_MASK, 7); REG_WRITE(REGAMMA_LUT_INDEX, 0); /* Program REGAMMA_LUT_DATA */ - { - uint32_t i = 0; - const struct pwl_result_data *rgb = params->rgb_resulted; - - while (i != params->hw_points_num) { + while (i != params->hw_points_num) { - REG_WRITE(REGAMMA_LUT_DATA, rgb->red_reg); - REG_WRITE(REGAMMA_LUT_DATA, rgb->green_reg); - REG_WRITE(REGAMMA_LUT_DATA, rgb->blue_reg); - REG_WRITE(REGAMMA_LUT_DATA, rgb->delta_red_reg); - REG_WRITE(REGAMMA_LUT_DATA, rgb->delta_green_reg); - REG_WRITE(REGAMMA_LUT_DATA, rgb->delta_blue_reg); + REG_WRITE(REGAMMA_LUT_DATA, rgb->red_reg); + REG_WRITE(REGAMMA_LUT_DATA, rgb->green_reg); + REG_WRITE(REGAMMA_LUT_DATA, rgb->blue_reg); + REG_WRITE(REGAMMA_LUT_DATA, rgb->delta_red_reg); + REG_WRITE(REGAMMA_LUT_DATA, rgb->delta_green_reg); + REG_WRITE(REGAMMA_LUT_DATA, rgb->delta_blue_reg); - ++rgb; - ++i; - } + ++rgb; + ++i; } /* we are done with DCP LUT memory; re-enable low power mode */ if (REG(DCFE_MEM_PWR_CTRL)) REG_UPDATE(DCFE_MEM_PWR_CTRL, - DCP_REGAMMA_MEM_PWR_DIS, 0); + DCP_REGAMMA_MEM_PWR_DIS, 0); else REG_UPDATE(DCFE_MEM_LIGHT_SLEEP_CNTL, - REGAMMA_LUT_LIGHT_SLEEP_DIS, 0); + REGAMMA_LUT_LIGHT_SLEEP_DIS, 0); } -static void regamma_config_regions_and_segments( - struct dce_transform *xfm_dce, - const struct pwl_params *params) +static void regamma_config_regions_and_segments(struct dce_transform *xfm_dce, + const struct pwl_params *params) { const struct gamma_curve *curve; - { - REG_SET_2(REGAMMA_CNTLA_START_CNTL, 0, - REGAMMA_CNTLA_EXP_REGION_START, params->arr_points[0].custom_float_x, - REGAMMA_CNTLA_EXP_REGION_START_SEGMENT, 0); - } - { - REG_SET(REGAMMA_CNTLA_SLOPE_CNTL, 0, - REGAMMA_CNTLA_EXP_REGION_LINEAR_SLOPE, params->arr_points[0].custom_float_slope); + REG_SET_2(REGAMMA_CNTLA_START_CNTL, 0, + REGAMMA_CNTLA_EXP_REGION_START, params->arr_points[0].custom_float_x, + REGAMMA_CNTLA_EXP_REGION_START_SEGMENT, 0); - } - { - REG_SET(REGAMMA_CNTLA_END_CNTL1, 0, - REGAMMA_CNTLA_EXP_REGION_END, params->arr_points[1].custom_float_x); - } - { - REG_SET_2(REGAMMA_CNTLA_END_CNTL2, 0, - REGAMMA_CNTLA_EXP_REGION_END_BASE, params->arr_points[1].custom_float_y, - REGAMMA_CNTLA_EXP_REGION_END_SLOPE, params->arr_points[2].custom_float_slope); - } + REG_SET(REGAMMA_CNTLA_SLOPE_CNTL, 0, + REGAMMA_CNTLA_EXP_REGION_LINEAR_SLOPE, params->arr_points[0].custom_float_slope); - curve = params->arr_curve_points; + REG_SET(REGAMMA_CNTLA_END_CNTL1, 0, + REGAMMA_CNTLA_EXP_REGION_END, params->arr_points[1].custom_float_x); - { - REG_SET_4(REGAMMA_CNTLA_REGION_0_1, 0, - REGAMMA_CNTLA_EXP_REGION0_LUT_OFFSET, curve[0].offset, - REGAMMA_CNTLA_EXP_REGION0_NUM_SEGMENTS, curve[0].segments_num, - REGAMMA_CNTLA_EXP_REGION1_LUT_OFFSET, curve[1].offset, - REGAMMA_CNTLA_EXP_REGION1_NUM_SEGMENTS, curve[1].segments_num); - } + REG_SET_2(REGAMMA_CNTLA_END_CNTL2, 0, + REGAMMA_CNTLA_EXP_REGION_END_BASE, params->arr_points[1].custom_float_y, + REGAMMA_CNTLA_EXP_REGION_END_SLOPE, params->arr_points[1].custom_float_slope); - curve += 2; - - { - REG_SET_4(REGAMMA_CNTLA_REGION_2_3, 0, - REGAMMA_CNTLA_EXP_REGION0_LUT_OFFSET, curve[0].offset, - REGAMMA_CNTLA_EXP_REGION0_NUM_SEGMENTS, curve[0].segments_num, - REGAMMA_CNTLA_EXP_REGION1_LUT_OFFSET, curve[1].offset, - REGAMMA_CNTLA_EXP_REGION1_NUM_SEGMENTS, curve[1].segments_num); - - } + curve = params->arr_curve_points; + REG_SET_4(REGAMMA_CNTLA_REGION_0_1, 0, + REGAMMA_CNTLA_EXP_REGION0_LUT_OFFSET, curve[0].offset, + REGAMMA_CNTLA_EXP_REGION0_NUM_SEGMENTS, curve[0].segments_num, + REGAMMA_CNTLA_EXP_REGION1_LUT_OFFSET, curve[1].offset, + REGAMMA_CNTLA_EXP_REGION1_NUM_SEGMENTS, curve[1].segments_num); curve += 2; - { - REG_SET_4(REGAMMA_CNTLA_REGION_4_5, 0, - REGAMMA_CNTLA_EXP_REGION0_LUT_OFFSET, curve[0].offset, - REGAMMA_CNTLA_EXP_REGION0_NUM_SEGMENTS, curve[0].segments_num, - REGAMMA_CNTLA_EXP_REGION1_LUT_OFFSET, curve[1].offset, - REGAMMA_CNTLA_EXP_REGION1_NUM_SEGMENTS, curve[1].segments_num); - - } - + REG_SET_4(REGAMMA_CNTLA_REGION_2_3, 0, + REGAMMA_CNTLA_EXP_REGION0_LUT_OFFSET, curve[0].offset, + REGAMMA_CNTLA_EXP_REGION0_NUM_SEGMENTS, curve[0].segments_num, + REGAMMA_CNTLA_EXP_REGION1_LUT_OFFSET, curve[1].offset, + REGAMMA_CNTLA_EXP_REGION1_NUM_SEGMENTS, curve[1].segments_num); curve += 2; - { - REG_SET_4(REGAMMA_CNTLA_REGION_6_7, 0, - REGAMMA_CNTLA_EXP_REGION0_LUT_OFFSET, curve[0].offset, - REGAMMA_CNTLA_EXP_REGION0_NUM_SEGMENTS, curve[0].segments_num, - REGAMMA_CNTLA_EXP_REGION1_LUT_OFFSET, curve[1].offset, - REGAMMA_CNTLA_EXP_REGION1_NUM_SEGMENTS, curve[1].segments_num); - - } - + REG_SET_4(REGAMMA_CNTLA_REGION_4_5, 0, + REGAMMA_CNTLA_EXP_REGION0_LUT_OFFSET, curve[0].offset, + REGAMMA_CNTLA_EXP_REGION0_NUM_SEGMENTS, curve[0].segments_num, + REGAMMA_CNTLA_EXP_REGION1_LUT_OFFSET, curve[1].offset, + REGAMMA_CNTLA_EXP_REGION1_NUM_SEGMENTS, curve[1].segments_num); curve += 2; - { - REG_SET_4(REGAMMA_CNTLA_REGION_8_9, 0, - REGAMMA_CNTLA_EXP_REGION0_LUT_OFFSET, curve[0].offset, - REGAMMA_CNTLA_EXP_REGION0_NUM_SEGMENTS, curve[0].segments_num, - REGAMMA_CNTLA_EXP_REGION1_LUT_OFFSET, curve[1].offset, - REGAMMA_CNTLA_EXP_REGION1_NUM_SEGMENTS, curve[1].segments_num); - - } - + REG_SET_4(REGAMMA_CNTLA_REGION_6_7, 0, + REGAMMA_CNTLA_EXP_REGION0_LUT_OFFSET, curve[0].offset, + REGAMMA_CNTLA_EXP_REGION0_NUM_SEGMENTS, curve[0].segments_num, + REGAMMA_CNTLA_EXP_REGION1_LUT_OFFSET, curve[1].offset, + REGAMMA_CNTLA_EXP_REGION1_NUM_SEGMENTS, curve[1].segments_num); curve += 2; - { - REG_SET_4(REGAMMA_CNTLA_REGION_10_11, 0, - REGAMMA_CNTLA_EXP_REGION0_LUT_OFFSET, curve[0].offset, - REGAMMA_CNTLA_EXP_REGION0_NUM_SEGMENTS, curve[0].segments_num, - REGAMMA_CNTLA_EXP_REGION1_LUT_OFFSET, curve[1].offset, - REGAMMA_CNTLA_EXP_REGION1_NUM_SEGMENTS, curve[1].segments_num); - - } - + REG_SET_4(REGAMMA_CNTLA_REGION_8_9, 0, + REGAMMA_CNTLA_EXP_REGION0_LUT_OFFSET, curve[0].offset, + REGAMMA_CNTLA_EXP_REGION0_NUM_SEGMENTS, curve[0].segments_num, + REGAMMA_CNTLA_EXP_REGION1_LUT_OFFSET, curve[1].offset, + REGAMMA_CNTLA_EXP_REGION1_NUM_SEGMENTS, curve[1].segments_num); curve += 2; - { - REG_SET_4(REGAMMA_CNTLA_REGION_12_13, 0, - REGAMMA_CNTLA_EXP_REGION0_LUT_OFFSET, curve[0].offset, - REGAMMA_CNTLA_EXP_REGION0_NUM_SEGMENTS, curve[0].segments_num, - REGAMMA_CNTLA_EXP_REGION1_LUT_OFFSET, curve[1].offset, - REGAMMA_CNTLA_EXP_REGION1_NUM_SEGMENTS, curve[1].segments_num); - - } + REG_SET_4(REGAMMA_CNTLA_REGION_10_11, 0, + REGAMMA_CNTLA_EXP_REGION0_LUT_OFFSET, curve[0].offset, + REGAMMA_CNTLA_EXP_REGION0_NUM_SEGMENTS, curve[0].segments_num, + REGAMMA_CNTLA_EXP_REGION1_LUT_OFFSET, curve[1].offset, + REGAMMA_CNTLA_EXP_REGION1_NUM_SEGMENTS, curve[1].segments_num); + curve += 2; + REG_SET_4(REGAMMA_CNTLA_REGION_12_13, 0, + REGAMMA_CNTLA_EXP_REGION0_LUT_OFFSET, curve[0].offset, + REGAMMA_CNTLA_EXP_REGION0_NUM_SEGMENTS, curve[0].segments_num, + REGAMMA_CNTLA_EXP_REGION1_LUT_OFFSET, curve[1].offset, + REGAMMA_CNTLA_EXP_REGION1_NUM_SEGMENTS, curve[1].segments_num); curve += 2; - { - REG_SET_4(REGAMMA_CNTLA_REGION_14_15, 0, - REGAMMA_CNTLA_EXP_REGION0_LUT_OFFSET, curve[0].offset, - REGAMMA_CNTLA_EXP_REGION0_NUM_SEGMENTS, curve[0].segments_num, - REGAMMA_CNTLA_EXP_REGION1_LUT_OFFSET, curve[1].offset, - REGAMMA_CNTLA_EXP_REGION1_NUM_SEGMENTS, curve[1].segments_num); - } + REG_SET_4(REGAMMA_CNTLA_REGION_14_15, 0, + REGAMMA_CNTLA_EXP_REGION0_LUT_OFFSET, curve[0].offset, + REGAMMA_CNTLA_EXP_REGION0_NUM_SEGMENTS, curve[0].segments_num, + REGAMMA_CNTLA_EXP_REGION1_LUT_OFFSET, curve[1].offset, + REGAMMA_CNTLA_EXP_REGION1_NUM_SEGMENTS, curve[1].segments_num); } -void dce110_opp_program_regamma_pwl( - struct transform *xfm, - const struct pwl_params *params) +void dce110_opp_program_regamma_pwl(struct transform *xfm, + const struct pwl_params *params) { struct dce_transform *xfm_dce = TO_DCE_TRANSFORM(xfm); @@ -1388,47 +1341,42 @@ void dce110_opp_program_regamma_pwl( program_pwl(xfm_dce, params); } -void dce110_opp_power_on_regamma_lut( - struct transform *xfm, - bool power_on) +void dce110_opp_power_on_regamma_lut(struct transform *xfm, + bool power_on) { struct dce_transform *xfm_dce = TO_DCE_TRANSFORM(xfm); if (REG(DCFE_MEM_PWR_CTRL)) REG_UPDATE_2(DCFE_MEM_PWR_CTRL, - DCP_REGAMMA_MEM_PWR_DIS, power_on, - DCP_LUT_MEM_PWR_DIS, power_on); + DCP_REGAMMA_MEM_PWR_DIS, power_on, + DCP_LUT_MEM_PWR_DIS, power_on); else REG_UPDATE_2(DCFE_MEM_LIGHT_SLEEP_CNTL, - REGAMMA_LUT_LIGHT_SLEEP_DIS, power_on, - DCP_LUT_LIGHT_SLEEP_DIS, power_on); + REGAMMA_LUT_LIGHT_SLEEP_DIS, power_on, + DCP_LUT_LIGHT_SLEEP_DIS, power_on); } void dce110_opp_set_regamma_mode(struct transform *xfm, - enum opp_regamma mode) + enum opp_regamma mode) { struct dce_transform *xfm_dce = TO_DCE_TRANSFORM(xfm); REG_SET(REGAMMA_CONTROL, 0, - GRPH_REGAMMA_MODE, mode); + GRPH_REGAMMA_MODE, mode); } static const struct transform_funcs dce_transform_funcs = { .transform_reset = dce_transform_reset, - .transform_set_scaler = - dce_transform_set_scaler, - .transform_set_gamut_remap = - dce_transform_set_gamut_remap, + .transform_set_scaler = dce_transform_set_scaler, + .transform_set_gamut_remap = dce_transform_set_gamut_remap, .opp_set_csc_adjustment = dce110_opp_set_csc_adjustment, .opp_set_csc_default = dce110_opp_set_csc_default, .opp_power_on_regamma_lut = dce110_opp_power_on_regamma_lut, .opp_program_regamma_pwl = dce110_opp_program_regamma_pwl, .opp_set_regamma_mode = dce110_opp_set_regamma_mode, - .transform_set_pixel_storage_depth = - dce_transform_set_pixel_storage_depth, - .transform_get_optimal_number_of_taps = - dce_transform_get_optimal_number_of_taps + .transform_set_pixel_storage_depth = dce_transform_set_pixel_storage_depth, + .transform_get_optimal_number_of_taps = dce_transform_get_optimal_number_of_taps }; /*****************************************/ diff --git a/drivers/gpu/drm/amd/display/dc/dce100/dce100_hw_sequencer.c b/drivers/gpu/drm/amd/display/dc/dce100/dce100_hw_sequencer.c index e7a694835e3e..469af0587604 100644 --- a/drivers/gpu/drm/amd/display/dc/dce100/dce100_hw_sequencer.c +++ b/drivers/gpu/drm/amd/display/dc/dce100/dce100_hw_sequencer.c @@ -148,5 +148,7 @@ void dce100_hw_sequencer_construct(struct dc *dc) dc->hwss.enable_display_power_gating = dce100_enable_display_power_gating; dc->hwss.set_bandwidth = dce100_set_bandwidth; + dc->hwss.pplib_apply_display_requirements = + dce100_pplib_apply_display_requirements; } diff --git a/drivers/gpu/drm/amd/display/dc/dce110/dce110_hw_sequencer.c b/drivers/gpu/drm/amd/display/dc/dce110/dce110_hw_sequencer.c index d844fadcd56f..86cdd7b4811f 100644 --- a/drivers/gpu/drm/amd/display/dc/dce110/dce110_hw_sequencer.c +++ b/drivers/gpu/drm/amd/display/dc/dce110/dce110_hw_sequencer.c @@ -257,9 +257,9 @@ static void build_prescale_params(struct ipp_prescale_params *prescale_params, } } -static bool dce110_set_input_transfer_func( - struct pipe_ctx *pipe_ctx, - const struct dc_plane_state *plane_state) +static bool +dce110_set_input_transfer_func(struct pipe_ctx *pipe_ctx, + const struct dc_plane_state *plane_state) { struct input_pixel_processor *ipp = pipe_ctx->plane_res.ipp; const struct dc_transfer_func *tf = NULL; @@ -280,25 +280,19 @@ static bool dce110_set_input_transfer_func( if (tf == NULL) { /* Default case if no input transfer function specified */ - ipp->funcs->ipp_set_degamma(ipp, - IPP_DEGAMMA_MODE_HW_sRGB); + ipp->funcs->ipp_set_degamma(ipp, IPP_DEGAMMA_MODE_HW_sRGB); } else if (tf->type == TF_TYPE_PREDEFINED) { switch (tf->tf) { case TRANSFER_FUNCTION_SRGB: - ipp->funcs->ipp_set_degamma(ipp, - IPP_DEGAMMA_MODE_HW_sRGB); + ipp->funcs->ipp_set_degamma(ipp, IPP_DEGAMMA_MODE_HW_sRGB); break; case TRANSFER_FUNCTION_BT709: - ipp->funcs->ipp_set_degamma(ipp, - IPP_DEGAMMA_MODE_HW_xvYCC); + ipp->funcs->ipp_set_degamma(ipp, IPP_DEGAMMA_MODE_HW_xvYCC); break; case TRANSFER_FUNCTION_LINEAR: - ipp->funcs->ipp_set_degamma(ipp, - IPP_DEGAMMA_MODE_BYPASS); + ipp->funcs->ipp_set_degamma(ipp, IPP_DEGAMMA_MODE_BYPASS); break; case TRANSFER_FUNCTION_PQ: - result = false; - break; default: result = false; break; @@ -313,10 +307,9 @@ static bool dce110_set_input_transfer_func( return result; } -static bool convert_to_custom_float( - struct pwl_result_data *rgb_resulted, - struct curve_points *arr_points, - uint32_t hw_points_num) +static bool convert_to_custom_float(struct pwl_result_data *rgb_resulted, + struct curve_points *arr_points, + uint32_t hw_points_num) { struct custom_float_format fmt; @@ -328,26 +321,20 @@ static bool convert_to_custom_float( fmt.mantissa_bits = 12; fmt.sign = true; - if (!convert_to_custom_float_format( - arr_points[0].x, - &fmt, - &arr_points[0].custom_float_x)) { + if (!convert_to_custom_float_format(arr_points[0].x, &fmt, + &arr_points[0].custom_float_x)) { BREAK_TO_DEBUGGER(); return false; } - if (!convert_to_custom_float_format( - arr_points[0].offset, - &fmt, - &arr_points[0].custom_float_offset)) { + if (!convert_to_custom_float_format(arr_points[0].offset, &fmt, + &arr_points[0].custom_float_offset)) { BREAK_TO_DEBUGGER(); return false; } - if (!convert_to_custom_float_format( - arr_points[0].slope, - &fmt, - &arr_points[0].custom_float_slope)) { + if (!convert_to_custom_float_format(arr_points[0].slope, &fmt, + &arr_points[0].custom_float_slope)) { BREAK_TO_DEBUGGER(); return false; } @@ -355,26 +342,20 @@ static bool convert_to_custom_float( fmt.mantissa_bits = 10; fmt.sign = false; - if (!convert_to_custom_float_format( - arr_points[1].x, - &fmt, - &arr_points[1].custom_float_x)) { + if (!convert_to_custom_float_format(arr_points[1].x, &fmt, + &arr_points[1].custom_float_x)) { BREAK_TO_DEBUGGER(); return false; } - if (!convert_to_custom_float_format( - arr_points[1].y, - &fmt, - &arr_points[1].custom_float_y)) { + if (!convert_to_custom_float_format(arr_points[1].y, &fmt, + &arr_points[1].custom_float_y)) { BREAK_TO_DEBUGGER(); return false; } - if (!convert_to_custom_float_format( - arr_points[2].slope, - &fmt, - &arr_points[2].custom_float_slope)) { + if (!convert_to_custom_float_format(arr_points[1].slope, &fmt, + &arr_points[1].custom_float_slope)) { BREAK_TO_DEBUGGER(); return false; } @@ -383,50 +364,38 @@ static bool convert_to_custom_float( fmt.sign = true; while (i != hw_points_num) { - if (!convert_to_custom_float_format( - rgb->red, - &fmt, - &rgb->red_reg)) { + if (!convert_to_custom_float_format(rgb->red, &fmt, + &rgb->red_reg)) { BREAK_TO_DEBUGGER(); return false; } - if (!convert_to_custom_float_format( - rgb->green, - &fmt, - &rgb->green_reg)) { + if (!convert_to_custom_float_format(rgb->green, &fmt, + &rgb->green_reg)) { BREAK_TO_DEBUGGER(); return false; } - if (!convert_to_custom_float_format( - rgb->blue, - &fmt, - &rgb->blue_reg)) { + if (!convert_to_custom_float_format(rgb->blue, &fmt, + &rgb->blue_reg)) { BREAK_TO_DEBUGGER(); return false; } - if (!convert_to_custom_float_format( - rgb->delta_red, - &fmt, - &rgb->delta_red_reg)) { + if (!convert_to_custom_float_format(rgb->delta_red, &fmt, + &rgb->delta_red_reg)) { BREAK_TO_DEBUGGER(); return false; } - if (!convert_to_custom_float_format( - rgb->delta_green, - &fmt, - &rgb->delta_green_reg)) { + if (!convert_to_custom_float_format(rgb->delta_green, &fmt, + &rgb->delta_green_reg)) { BREAK_TO_DEBUGGER(); return false; } - if (!convert_to_custom_float_format( - rgb->delta_blue, - &fmt, - &rgb->delta_blue_reg)) { + if (!convert_to_custom_float_format(rgb->delta_blue, &fmt, + &rgb->delta_blue_reg)) { BREAK_TO_DEBUGGER(); return false; } @@ -438,8 +407,9 @@ static bool convert_to_custom_float( return true; } -static bool dce110_translate_regamma_to_hw_format(const struct dc_transfer_func - *output_tf, struct pwl_params *regamma_params) +static bool +dce110_translate_regamma_to_hw_format(const struct dc_transfer_func *output_tf, + struct pwl_params *regamma_params) { struct curve_points *arr_points; struct pwl_result_data *rgb_resulted; @@ -454,8 +424,7 @@ static bool dce110_translate_regamma_to_hw_format(const struct dc_transfer_func int32_t segment_start, segment_end; uint32_t i, j, k, seg_distr[16], increment, start_index, hw_points; - if (output_tf == NULL || regamma_params == NULL || - output_tf->type == TF_TYPE_BYPASS) + if (output_tf == NULL || regamma_params == NULL || output_tf->type == TF_TYPE_BYPASS) return false; arr_points = regamma_params->arr_points; @@ -534,19 +503,14 @@ static bool dce110_translate_regamma_to_hw_format(const struct dc_transfer_func /* last point */ start_index = (segment_end + 25) * 32; - rgb_resulted[hw_points - 1].red = - output_tf->tf_pts.red[start_index]; - rgb_resulted[hw_points - 1].green = - output_tf->tf_pts.green[start_index]; - rgb_resulted[hw_points - 1].blue = - output_tf->tf_pts.blue[start_index]; + rgb_resulted[hw_points - 1].red = output_tf->tf_pts.red[start_index]; + rgb_resulted[hw_points - 1].green = output_tf->tf_pts.green[start_index]; + rgb_resulted[hw_points - 1].blue = output_tf->tf_pts.blue[start_index]; arr_points[0].x = dal_fixed31_32_pow(dal_fixed31_32_from_int(2), - dal_fixed31_32_from_int(segment_start)); + dal_fixed31_32_from_int(segment_start)); arr_points[1].x = dal_fixed31_32_pow(dal_fixed31_32_from_int(2), - dal_fixed31_32_from_int(segment_end)); - arr_points[2].x = dal_fixed31_32_pow(dal_fixed31_32_from_int(2), - dal_fixed31_32_from_int(segment_end)); + dal_fixed31_32_from_int(segment_end)); y_r = rgb_resulted[0].red; y_g = rgb_resulted[0].green; @@ -555,9 +519,8 @@ static bool dce110_translate_regamma_to_hw_format(const struct dc_transfer_func y1_min = dal_fixed31_32_min(y_r, dal_fixed31_32_min(y_g, y_b)); arr_points[0].y = y1_min; - arr_points[0].slope = dal_fixed31_32_div( - arr_points[0].y, - arr_points[0].x); + arr_points[0].slope = dal_fixed31_32_div(arr_points[0].y, + arr_points[0].x); y_r = rgb_resulted[hw_points - 1].red; y_g = rgb_resulted[hw_points - 1].green; @@ -569,24 +532,18 @@ static bool dce110_translate_regamma_to_hw_format(const struct dc_transfer_func y3_max = dal_fixed31_32_max(y_r, dal_fixed31_32_max(y_g, y_b)); arr_points[1].y = y3_max; - arr_points[2].y = y3_max; arr_points[1].slope = dal_fixed31_32_zero; - arr_points[2].slope = dal_fixed31_32_zero; if (output_tf->tf == TRANSFER_FUNCTION_PQ) { /* for PQ, we want to have a straight line from last HW X point, * and the slope to be such that we hit 1.0 at 10000 nits. */ - const struct fixed31_32 end_value = - dal_fixed31_32_from_int(125); + const struct fixed31_32 end_value = dal_fixed31_32_from_int(125); arr_points[1].slope = dal_fixed31_32_div( - dal_fixed31_32_sub(dal_fixed31_32_one, arr_points[1].y), - dal_fixed31_32_sub(end_value, arr_points[1].x)); - arr_points[2].slope = dal_fixed31_32_div( - dal_fixed31_32_sub(dal_fixed31_32_one, arr_points[1].y), - dal_fixed31_32_sub(end_value, arr_points[1].x)); + dal_fixed31_32_sub(dal_fixed31_32_one, arr_points[1].y), + dal_fixed31_32_sub(end_value, arr_points[1].x)); } regamma_params->hw_points_num = hw_points; @@ -594,18 +551,15 @@ static bool dce110_translate_regamma_to_hw_format(const struct dc_transfer_func i = 1; for (k = 0; k < 16 && i < 16; k++) { if (seg_distr[k] != -1) { - regamma_params->arr_curve_points[k].segments_num = - seg_distr[k]; + regamma_params->arr_curve_points[k].segments_num = seg_distr[k]; regamma_params->arr_curve_points[i].offset = - regamma_params->arr_curve_points[k]. - offset + (1 << seg_distr[k]); + regamma_params->arr_curve_points[k].offset + (1 << seg_distr[k]); } i++; } if (seg_distr[k] != -1) - regamma_params->arr_curve_points[k].segments_num = - seg_distr[k]; + regamma_params->arr_curve_points[k].segments_num = seg_distr[k]; rgb = rgb_resulted; rgb_plus_1 = rgb_resulted + 1; @@ -620,15 +574,9 @@ static bool dce110_translate_regamma_to_hw_format(const struct dc_transfer_func if (dal_fixed31_32_lt(rgb_plus_1->blue, rgb->blue)) rgb_plus_1->blue = rgb->blue; - rgb->delta_red = dal_fixed31_32_sub( - rgb_plus_1->red, - rgb->red); - rgb->delta_green = dal_fixed31_32_sub( - rgb_plus_1->green, - rgb->green); - rgb->delta_blue = dal_fixed31_32_sub( - rgb_plus_1->blue, - rgb->blue); + rgb->delta_red = dal_fixed31_32_sub(rgb_plus_1->red, rgb->red); + rgb->delta_green = dal_fixed31_32_sub(rgb_plus_1->green, rgb->green); + rgb->delta_blue = dal_fixed31_32_sub(rgb_plus_1->blue, rgb->blue); ++rgb_plus_1; ++rgb; @@ -640,9 +588,9 @@ static bool dce110_translate_regamma_to_hw_format(const struct dc_transfer_func return true; } -static bool dce110_set_output_transfer_func( - struct pipe_ctx *pipe_ctx, - const struct dc_stream_state *stream) +static bool +dce110_set_output_transfer_func(struct pipe_ctx *pipe_ctx, + const struct dc_stream_state *stream) { struct transform *xfm = pipe_ctx->plane_res.xfm; @@ -650,13 +598,11 @@ static bool dce110_set_output_transfer_func( xfm->regamma_params.hw_points_num = GAMMA_HW_POINTS_NUM; if (stream->out_transfer_func && - stream->out_transfer_func->type == - TF_TYPE_PREDEFINED && - stream->out_transfer_func->tf == - TRANSFER_FUNCTION_SRGB) { + stream->out_transfer_func->type == TF_TYPE_PREDEFINED && + stream->out_transfer_func->tf == TRANSFER_FUNCTION_SRGB) { xfm->funcs->opp_set_regamma_mode(xfm, OPP_REGAMMA_SRGB); - } else if (dce110_translate_regamma_to_hw_format( - stream->out_transfer_func, &xfm->regamma_params)) { + } else if (dce110_translate_regamma_to_hw_format(stream->out_transfer_func, + &xfm->regamma_params)) { xfm->funcs->opp_program_regamma_pwl(xfm, &xfm->regamma_params); xfm->funcs->opp_set_regamma_mode(xfm, OPP_REGAMMA_USER); } else { @@ -814,11 +760,11 @@ static enum bp_result link_transmitter_control( * eDP only. */ void hwss_edp_wait_for_hpd_ready( - struct link_encoder *enc, - bool power_up) + struct dc_link *link, + bool power_up) { - struct dc_context *ctx = enc->ctx; - struct graphics_object_id connector = enc->connector; + struct dc_context *ctx = link->ctx; + struct graphics_object_id connector = link->link_enc->connector; struct gpio *hpd; bool edp_hpd_high = false; uint32_t time_elapsed = 0; @@ -882,16 +828,16 @@ void hwss_edp_wait_for_hpd_ready( } void hwss_edp_power_control( - struct link_encoder *enc, - bool power_up) + struct dc_link *link, + bool power_up) { - struct dc_context *ctx = enc->ctx; + struct dc_context *ctx = link->ctx; struct dce_hwseq *hwseq = ctx->dc->hwseq; struct bp_transmitter_control cntl = { 0 }; enum bp_result bp_result; - if (dal_graphics_object_id_get_connector_id(enc->connector) + if (dal_graphics_object_id_get_connector_id(link->link_enc->connector) != CONNECTOR_ID_EDP) { BREAK_TO_DEBUGGER(); return; @@ -907,11 +853,11 @@ void hwss_edp_power_control( cntl.action = power_up ? TRANSMITTER_CONTROL_POWER_ON : TRANSMITTER_CONTROL_POWER_OFF; - cntl.transmitter = enc->transmitter; - cntl.connector_obj_id = enc->connector; + cntl.transmitter = link->link_enc->transmitter; + cntl.connector_obj_id = link->link_enc->connector; cntl.coherent = false; cntl.lanes_number = LANE_COUNT_FOUR; - cntl.hpd_sel = enc->hpd_source; + cntl.hpd_sel = link->link_enc->hpd_source; bp_result = link_transmitter_control(ctx->dc_bios, &cntl); @@ -924,8 +870,6 @@ void hwss_edp_power_control( "%s: Skipping Panel Power action: %s\n", __func__, (power_up ? "On":"Off")); } - - hwss_edp_wait_for_hpd_ready(enc, true); } /*todo: cloned in stream enc, fix*/ @@ -934,14 +878,14 @@ void hwss_edp_power_control( * eDP only. Control the backlight of the eDP panel */ void hwss_edp_backlight_control( - struct dc_link *link, - bool enable) + struct dc_link *link, + bool enable) { - struct dce_hwseq *hws = link->dc->hwseq; - struct dc_context *ctx = link->dc->ctx; + struct dc_context *ctx = link->ctx; + struct dce_hwseq *hws = ctx->dc->hwseq; struct bp_transmitter_control cntl = { 0 }; - if (dal_graphics_object_id_get_connector_id(link->link_id) + if (dal_graphics_object_id_get_connector_id(link->link_enc->connector) != CONNECTOR_ID_EDP) { BREAK_TO_DEBUGGER(); return; @@ -982,7 +926,7 @@ void hwss_edp_backlight_control( * Enable it in the future if necessary. */ /* dc_service_sleep_in_milliseconds(50); */ - link_transmitter_control(link->dc->ctx->dc_bios, &cntl); + link_transmitter_control(ctx->dc_bios, &cntl); } void dce110_disable_stream(struct pipe_ctx *pipe_ctx, int option) @@ -1026,11 +970,9 @@ void dce110_disable_stream(struct pipe_ctx *pipe_ctx, int option) } /* blank at encoder level */ - if (dc_is_dp_signal(pipe_ctx->stream->signal)) { - if (pipe_ctx->stream->sink->link->connector_signal == SIGNAL_TYPE_EDP) - hwss_edp_backlight_control(link, false); + if (dc_is_dp_signal(pipe_ctx->stream->signal)) pipe_ctx->stream_res.stream_enc->funcs->dp_blank(pipe_ctx->stream_res.stream_enc); - } + link->link_enc->funcs->connect_dig_be_to_fe( link->link_enc, pipe_ctx->stream_res.stream_enc->id, @@ -1042,15 +984,12 @@ void dce110_unblank_stream(struct pipe_ctx *pipe_ctx, struct dc_link_settings *link_settings) { struct encoder_unblank_param params = { { 0 } }; - struct dc_link *link = pipe_ctx->stream->sink->link; /* only 3 items below are used by unblank */ params.pixel_clk_khz = pipe_ctx->stream->timing.pix_clk_khz; params.link_settings.link_rate = link_settings->link_rate; pipe_ctx->stream_res.stream_enc->funcs->dp_unblank(pipe_ctx->stream_res.stream_enc, ¶ms); - if (link->connector_signal == SIGNAL_TYPE_EDP) - hwss_edp_backlight_control(link, true); } @@ -1401,7 +1340,7 @@ static void power_down_encoders(struct dc *dc) } dc->links[i]->link_enc->funcs->disable_output( - dc->links[i]->link_enc, signal, dc->links[i]); + dc->links[i]->link_enc, signal); } } @@ -1462,7 +1401,9 @@ static void disable_vga_and_power_gate_all_controllers( enable_display_pipe_clock_gating(ctx, true); - dc->hwss.power_down_front_end(dc, i); + dc->current_state->res_ctx.pipe_ctx[i].pipe_idx = i; + dc->hwss.disable_plane(dc, + &dc->current_state->res_ctx.pipe_ctx[i]); } } @@ -1748,60 +1689,54 @@ static void apply_min_clocks( /* * Check if FBC can be enabled */ -static enum dc_status validate_fbc(struct dc *dc, - struct dc_state *context) +static bool should_enable_fbc(struct dc *dc, + struct dc_state *context) { - struct pipe_ctx *pipe_ctx = - &context->res_ctx.pipe_ctx[0]; + struct pipe_ctx *pipe_ctx = &context->res_ctx.pipe_ctx[0]; ASSERT(dc->fbc_compressor); /* FBC memory should be allocated */ if (!dc->ctx->fbc_gpu_addr) - return DC_ERROR_UNEXPECTED; + return false; /* Only supports single display */ if (context->stream_count != 1) - return DC_ERROR_UNEXPECTED; + return false; /* Only supports eDP */ if (pipe_ctx->stream->sink->link->connector_signal != SIGNAL_TYPE_EDP) - return DC_ERROR_UNEXPECTED; + return false; /* PSR should not be enabled */ if (pipe_ctx->stream->sink->link->psr_enabled) - return DC_ERROR_UNEXPECTED; + return false; /* Nothing to compress */ if (!pipe_ctx->plane_state) - return DC_ERROR_UNEXPECTED; + return false; /* Only for non-linear tiling */ if (pipe_ctx->plane_state->tiling_info.gfx8.array_mode == DC_ARRAY_LINEAR_GENERAL) - return DC_ERROR_UNEXPECTED; + return false; - return DC_OK; + return true; } /* * Enable FBC */ -static enum dc_status enable_fbc(struct dc *dc, - struct dc_state *context) +static void enable_fbc(struct dc *dc, + struct dc_state *context) { - enum dc_status status = validate_fbc(dc, context); - - if (status == DC_OK) { + if (should_enable_fbc(dc, context)) { /* Program GRPH COMPRESSED ADDRESS and PITCH */ struct compr_addr_and_pitch_params params = {0, 0, 0}; struct compressor *compr = dc->fbc_compressor; - struct pipe_ctx *pipe_ctx = - &context->res_ctx.pipe_ctx[0]; + struct pipe_ctx *pipe_ctx = &context->res_ctx.pipe_ctx[0]; - params.source_view_width = - pipe_ctx->stream->timing.h_addressable; - params.source_view_height = - pipe_ctx->stream->timing.v_addressable; + params.source_view_width = pipe_ctx->stream->timing.h_addressable; + params.source_view_height = pipe_ctx->stream->timing.v_addressable; compr->compr_surface_address.quad_part = dc->ctx->fbc_gpu_addr; @@ -1810,7 +1745,6 @@ static enum dc_status enable_fbc(struct dc *dc, compr->funcs->enable_fbc(compr, ¶ms); } - return status; } #endif @@ -1888,7 +1822,7 @@ static void dce110_reset_hw_ctx_wrap( if (old_clk) old_clk->funcs->cs_power_down(old_clk); - dc->hwss.power_down_front_end(dc, pipe_ctx_old->pipe_idx); + dc->hwss.disable_plane(dc, pipe_ctx_old); pipe_ctx_old->stream = NULL; } @@ -2076,8 +2010,7 @@ enum dc_status dce110_apply_ctx_to_hw( if (pipe_ctx->stream == pipe_ctx_old->stream) continue; - if (pipe_ctx->stream && pipe_ctx_old->stream - && !pipe_need_reprogram(pipe_ctx_old, pipe_ctx)) + if (pipe_ctx_old->stream && !pipe_need_reprogram(pipe_ctx_old, pipe_ctx)) continue; if (pipe_ctx->top_pipe) @@ -2113,9 +2046,6 @@ enum dc_status dce110_apply_ctx_to_hw( context, dc); - if (dc->hwss.power_on_front_end) - dc->hwss.power_on_front_end(dc, pipe_ctx, context); - if (DC_OK != status) return status; } @@ -2145,16 +2075,8 @@ static void set_default_colors(struct pipe_ctx *pipe_ctx) struct default_adjustment default_adjust = { 0 }; default_adjust.force_hw_default = false; - if (pipe_ctx->plane_state == NULL) - default_adjust.in_color_space = COLOR_SPACE_SRGB; - else - default_adjust.in_color_space = - pipe_ctx->plane_state->color_space; - if (pipe_ctx->stream == NULL) - default_adjust.out_color_space = COLOR_SPACE_SRGB; - else - default_adjust.out_color_space = - pipe_ctx->stream->output_color_space; + default_adjust.in_color_space = pipe_ctx->plane_state->color_space; + default_adjust.out_color_space = pipe_ctx->stream->output_color_space; default_adjust.csc_adjust_type = GRAPHICS_CSC_ADJUST_TYPE_SW; default_adjust.surface_pixel_format = pipe_ctx->plane_res.scl_data.format; @@ -2279,8 +2201,7 @@ static void set_plane_config( dce_enable_fe_clock(dc->hwseq, pipe_ctx->pipe_idx, true); set_default_colors(pipe_ctx); - if (pipe_ctx->stream->csc_color_matrix.enable_adjustment - == true) { + if (pipe_ctx->stream->csc_color_matrix.enable_adjustment == true) { tbl_entry.color_space = pipe_ctx->stream->output_color_space; @@ -2458,20 +2379,16 @@ static void dce110_enable_timing_synchronization( for (i = 1 /* skip the master */; i < group_size; i++) grouped_pipes[i]->stream_res.tg->funcs->enable_reset_trigger( - grouped_pipes[i]->stream_res.tg, gsl_params.gsl_group); - - + grouped_pipes[i]->stream_res.tg, + gsl_params.gsl_group); for (i = 1 /* skip the master */; i < group_size; i++) { DC_SYNC_INFO("GSL: waiting for reset to occur.\n"); wait_for_reset_trigger_to_occur(dc_ctx, grouped_pipes[i]->stream_res.tg); - /* Regardless of success of the wait above, remove the reset or - * the driver will start timing out on Display requests. */ - DC_SYNC_INFO("GSL: disabling trigger-reset.\n"); - grouped_pipes[i]->stream_res.tg->funcs->disable_reset_trigger(grouped_pipes[i]->stream_res.tg); + grouped_pipes[i]->stream_res.tg->funcs->disable_reset_trigger( + grouped_pipes[i]->stream_res.tg); } - /* GSL Vblank synchronization is a one time sync mechanism, assumption * is that the sync'ed displays will not drift out of sync over time*/ DC_SYNC_INFO("GSL: Restoring register states.\n"); @@ -2481,6 +2398,39 @@ static void dce110_enable_timing_synchronization( DC_SYNC_INFO("GSL: Set-up complete.\n"); } +static void dce110_enable_per_frame_crtc_position_reset( + struct dc *dc, + int group_size, + struct pipe_ctx *grouped_pipes[]) +{ + struct dc_context *dc_ctx = dc->ctx; + struct dcp_gsl_params gsl_params = { 0 }; + int i; + + gsl_params.gsl_group = 0; + gsl_params.gsl_master = grouped_pipes[0]->stream->triggered_crtc_reset.event_source->status.primary_otg_inst; + + for (i = 0; i < group_size; i++) + grouped_pipes[i]->stream_res.tg->funcs->setup_global_swap_lock( + grouped_pipes[i]->stream_res.tg, &gsl_params); + + DC_SYNC_INFO("GSL: enabling trigger-reset\n"); + + for (i = 1; i < group_size; i++) + grouped_pipes[i]->stream_res.tg->funcs->enable_crtc_reset( + grouped_pipes[i]->stream_res.tg, + gsl_params.gsl_master, + &grouped_pipes[i]->stream->triggered_crtc_reset); + + DC_SYNC_INFO("GSL: waiting for reset to occur.\n"); + for (i = 1; i < group_size; i++) + wait_for_reset_trigger_to_occur(dc_ctx, grouped_pipes[i]->stream_res.tg); + + for (i = 0; i < group_size; i++) + grouped_pipes[i]->stream_res.tg->funcs->tear_down_global_swap_lock(grouped_pipes[i]->stream_res.tg); + +} + static void init_hw(struct dc *dc) { int i; @@ -2513,6 +2463,10 @@ static void init_hw(struct dc *dc) * required signal (which may be different from the * default signal on connector). */ struct dc_link *link = dc->links[i]; + + if (link->link_enc->connector.id == CONNECTOR_ID_EDP) + dc->hwss.edp_power_control(link, true); + link->link_enc->funcs->hw_init(link->link_enc); } @@ -2567,6 +2521,10 @@ void dce110_fill_display_configs( ASSERT(pipe_ctx != NULL); + /* only notify active stream */ + if (stream->dpms_off) + continue; + num_cfgs++; cfg->signal = pipe_ctx->stream->signal; cfg->pipe_idx = pipe_ctx->pipe_idx; @@ -2722,8 +2680,7 @@ static void dce110_program_front_end_for_pipe( struct dc_plane_state *plane_state = pipe_ctx->plane_state; struct xfm_grph_csc_adjustment adjust; struct out_csc_color_matrix tbl_entry; - struct pipe_ctx *cur_pipe_ctx = - &dc->current_state->res_ctx.pipe_ctx[pipe_ctx->pipe_idx]; + struct pipe_ctx *cur_pipe_ctx = &dc->current_state->res_ctx.pipe_ctx[pipe_ctx->pipe_idx]; unsigned int i; memset(&tbl_entry, 0, sizeof(tbl_entry)); @@ -2816,10 +2773,8 @@ static void dce110_program_front_end_for_pipe( /* Moved programming gamma from dc to hwss */ if (cur_pipe_ctx->plane_state != pipe_ctx->plane_state) { - dc->hwss.set_input_transfer_func( - pipe_ctx, pipe_ctx->plane_state); - dc->hwss.set_output_transfer_func( - pipe_ctx, pipe_ctx->stream); + dc->hwss.set_input_transfer_func(pipe_ctx, pipe_ctx->plane_state); + dc->hwss.set_output_transfer_func(pipe_ctx, pipe_ctx->stream); } dm_logger_write(dc->ctx->logger, LOG_SURFACE, @@ -2889,13 +2844,12 @@ static void dce110_apply_ctx_for_surface( continue; /* Need to allocate mem before program front end for Fiji */ - if (pipe_ctx->plane_res.mi != NULL) - pipe_ctx->plane_res.mi->funcs->allocate_mem_input( - pipe_ctx->plane_res.mi, - pipe_ctx->stream->timing.h_total, - pipe_ctx->stream->timing.v_total, - pipe_ctx->stream->timing.pix_clk_khz, - context->stream_count); + pipe_ctx->plane_res.mi->funcs->allocate_mem_input( + pipe_ctx->plane_res.mi, + pipe_ctx->stream->timing.h_total, + pipe_ctx->stream->timing.v_total, + pipe_ctx->stream->timing.pix_clk_khz, + context->stream_count); dce110_program_front_end_for_pipe(dc, pipe_ctx); @@ -2916,8 +2870,10 @@ static void dce110_apply_ctx_for_surface( } } -static void dce110_power_down_fe(struct dc *dc, int fe_idx) +static void dce110_power_down_fe(struct dc *dc, struct pipe_ctx *pipe_ctx) { + int fe_idx = pipe_ctx->pipe_idx; + /* Do not power down fe when stream is active on dce*/ if (dc->current_state->res_ctx.pipe_ctx[fe_idx].stream) return; @@ -2977,13 +2933,14 @@ static const struct hw_sequencer_funcs dce110_funcs = { .power_down = dce110_power_down, .enable_accelerated_mode = dce110_enable_accelerated_mode, .enable_timing_synchronization = dce110_enable_timing_synchronization, + .enable_per_frame_crtc_position_reset = dce110_enable_per_frame_crtc_position_reset, .update_info_frame = dce110_update_info_frame, .enable_stream = dce110_enable_stream, .disable_stream = dce110_disable_stream, .unblank_stream = dce110_unblank_stream, .enable_display_pipe_clock_gating = enable_display_pipe_clock_gating, .enable_display_power_gating = dce110_enable_display_power_gating, - .power_down_front_end = dce110_power_down_fe, + .disable_plane = dce110_power_down_fe, .pipe_control_lock = dce_pipe_control_lock, .set_bandwidth = dce110_set_bandwidth, .set_drr = set_drr, @@ -2996,8 +2953,10 @@ static const struct hw_sequencer_funcs dce110_funcs = { .wait_for_mpcc_disconnect = dce110_wait_for_mpcc_disconnect, .ready_shared_resources = ready_shared_resources, .optimize_shared_resources = optimize_shared_resources, + .pplib_apply_display_requirements = pplib_apply_display_requirements, .edp_backlight_control = hwss_edp_backlight_control, .edp_power_control = hwss_edp_power_control, + .edp_wait_for_hpd_ready = hwss_edp_wait_for_hpd_ready, }; void dce110_hw_sequencer_construct(struct dc *dc) diff --git a/drivers/gpu/drm/amd/display/dc/dce110/dce110_hw_sequencer.h b/drivers/gpu/drm/amd/display/dc/dce110/dce110_hw_sequencer.h index 4d72bb99be93..fc637647f643 100644 --- a/drivers/gpu/drm/amd/display/dc/dce110/dce110_hw_sequencer.h +++ b/drivers/gpu/drm/amd/display/dc/dce110/dce110_hw_sequencer.h @@ -70,12 +70,16 @@ uint32_t dce110_get_min_vblank_time_us(const struct dc_state *context); void dp_receiver_power_ctrl(struct dc_link *link, bool on); void hwss_edp_power_control( - struct link_encoder *enc, - bool power_up); + struct dc_link *link, + bool power_up); void hwss_edp_backlight_control( struct dc_link *link, bool enable); +void hwss_edp_wait_for_hpd_ready( + struct dc_link *link, + bool power_up); + #endif /* __DC_HWSS_DCE110_H__ */ diff --git a/drivers/gpu/drm/amd/display/dc/dce110/dce110_mem_input_v.c b/drivers/gpu/drm/amd/display/dc/dce110/dce110_mem_input_v.c index a06c6024deb4..7bab8c6d2a73 100644 --- a/drivers/gpu/drm/amd/display/dc/dce110/dce110_mem_input_v.c +++ b/drivers/gpu/drm/amd/display/dc/dce110/dce110_mem_input_v.c @@ -237,26 +237,14 @@ static void program_size_and_rotation( if (rotation == ROTATION_ANGLE_90 || rotation == ROTATION_ANGLE_270) { - uint32_t swap; - swap = local_size.video.luma_size.x; - local_size.video.luma_size.x = - local_size.video.luma_size.y; - local_size.video.luma_size.y = swap; - - swap = local_size.video.luma_size.width; - local_size.video.luma_size.width = - local_size.video.luma_size.height; - local_size.video.luma_size.height = swap; - - swap = local_size.video.chroma_size.x; - local_size.video.chroma_size.x = - local_size.video.chroma_size.y; - local_size.video.chroma_size.y = swap; - - swap = local_size.video.chroma_size.width; - local_size.video.chroma_size.width = - local_size.video.chroma_size.height; - local_size.video.chroma_size.height = swap; + swap(local_size.video.luma_size.x, + local_size.video.luma_size.y); + swap(local_size.video.luma_size.width, + local_size.video.luma_size.height); + swap(local_size.video.chroma_size.x, + local_size.video.chroma_size.y); + swap(local_size.video.chroma_size.width, + local_size.video.chroma_size.height); } value = 0; diff --git a/drivers/gpu/drm/amd/display/dc/dce110/dce110_opp_regamma_v.c b/drivers/gpu/drm/amd/display/dc/dce110/dce110_opp_regamma_v.c index e98ed3058ea2..9b65b77e8823 100644 --- a/drivers/gpu/drm/amd/display/dc/dce110/dce110_opp_regamma_v.c +++ b/drivers/gpu/drm/amd/display/dc/dce110/dce110_opp_regamma_v.c @@ -175,7 +175,7 @@ static void regamma_config_regions_and_segments( value = 0; set_reg_field_value( value, - params->arr_points[2].custom_float_slope, + params->arr_points[1].custom_float_slope, GAMMA_CORR_CNTLA_END_CNTL2, GAMMA_CORR_CNTLA_EXP_REGION_END_BASE); diff --git a/drivers/gpu/drm/amd/display/dc/dce110/dce110_resource.c b/drivers/gpu/drm/amd/display/dc/dce110/dce110_resource.c index 42df17f9aa8d..7c4779578fb7 100644 --- a/drivers/gpu/drm/amd/display/dc/dce110/dce110_resource.c +++ b/drivers/gpu/drm/amd/display/dc/dce110/dce110_resource.c @@ -1156,6 +1156,7 @@ static bool construct( dc->caps.max_downscale_ratio = 150; dc->caps.i2c_speed_in_khz = 100; dc->caps.max_cursor_size = 128; + dc->caps.is_apu = true; /************************************************* * Create resources * diff --git a/drivers/gpu/drm/amd/display/dc/dce110/dce110_timing_generator.c b/drivers/gpu/drm/amd/display/dc/dce110/dce110_timing_generator.c index 4befce6cd87a..25ca72139e5f 100644 --- a/drivers/gpu/drm/amd/display/dc/dce110/dce110_timing_generator.c +++ b/drivers/gpu/drm/amd/display/dc/dce110/dce110_timing_generator.c @@ -1224,26 +1224,46 @@ void dce110_timing_generator_setup_global_swap_lock( /* This pipe will belong to GSL Group zero. */ set_reg_field_value(value, - 1, - DCP_GSL_CONTROL, - DCP_GSL0_EN); + 1, + DCP_GSL_CONTROL, + DCP_GSL0_EN); set_reg_field_value(value, - gsl_params->gsl_master == tg->inst, - DCP_GSL_CONTROL, - DCP_GSL_MASTER_EN); + gsl_params->gsl_master == tg->inst, + DCP_GSL_CONTROL, + DCP_GSL_MASTER_EN); set_reg_field_value(value, - HFLIP_READY_DELAY, - DCP_GSL_CONTROL, - DCP_GSL_HSYNC_FLIP_FORCE_DELAY); + HFLIP_READY_DELAY, + DCP_GSL_CONTROL, + DCP_GSL_HSYNC_FLIP_FORCE_DELAY); /* Keep signal low (pending high) during 6 lines. * Also defines minimum interval before re-checking signal. */ set_reg_field_value(value, - HFLIP_CHECK_DELAY, - DCP_GSL_CONTROL, - DCP_GSL_HSYNC_FLIP_CHECK_DELAY); + HFLIP_CHECK_DELAY, + DCP_GSL_CONTROL, + DCP_GSL_HSYNC_FLIP_CHECK_DELAY); + + dm_write_reg(tg->ctx, CRTC_REG(mmDCP_GSL_CONTROL), value); + value = 0; + + set_reg_field_value(value, + gsl_params->gsl_master, + DCIO_GSL0_CNTL, + DCIO_GSL0_VSYNC_SEL); + + set_reg_field_value(value, + 0, + DCIO_GSL0_CNTL, + DCIO_GSL0_TIMING_SYNC_SEL); + + set_reg_field_value(value, + 0, + DCIO_GSL0_CNTL, + DCIO_GSL0_GLOBAL_UNLOCK_SEL); + + dm_write_reg(tg->ctx, CRTC_REG(mmDCIO_GSL0_CNTL), value); { @@ -1253,38 +1273,38 @@ void dce110_timing_generator_setup_global_swap_lock( CRTC_REG(mmCRTC_V_TOTAL)); set_reg_field_value(value, - 0,/* DCP_GSL_PURPOSE_SURFACE_FLIP */ - DCP_GSL_CONTROL, - DCP_GSL_SYNC_SOURCE); + 0,/* DCP_GSL_PURPOSE_SURFACE_FLIP */ + DCP_GSL_CONTROL, + DCP_GSL_SYNC_SOURCE); /* Checkpoint relative to end of frame */ check_point = get_reg_field_value(value_crtc_vtotal, - CRTC_V_TOTAL, - CRTC_V_TOTAL); + CRTC_V_TOTAL, + CRTC_V_TOTAL); dm_write_reg(tg->ctx, CRTC_REG(mmCRTC_GSL_WINDOW), 0); } set_reg_field_value(value, - 1, - DCP_GSL_CONTROL, - DCP_GSL_DELAY_SURFACE_UPDATE_PENDING); + 1, + DCP_GSL_CONTROL, + DCP_GSL_DELAY_SURFACE_UPDATE_PENDING); dm_write_reg(tg->ctx, address, value); /********************************************************************/ address = CRTC_REG(mmCRTC_GSL_CONTROL); - value = 0; + value = dm_read_reg(tg->ctx, address); set_reg_field_value(value, - check_point - FLIP_READY_BACK_LOOKUP, - CRTC_GSL_CONTROL, - CRTC_GSL_CHECK_LINE_NUM); + check_point - FLIP_READY_BACK_LOOKUP, + CRTC_GSL_CONTROL, + CRTC_GSL_CHECK_LINE_NUM); set_reg_field_value(value, - VFLIP_READY_DELAY, - CRTC_GSL_CONTROL, - CRTC_GSL_FORCE_DELAY); + VFLIP_READY_DELAY, + CRTC_GSL_CONTROL, + CRTC_GSL_FORCE_DELAY); dm_write_reg(tg->ctx, address, value); } @@ -1555,6 +1575,138 @@ void dce110_timing_generator_enable_reset_trigger( dm_write_reg(tg->ctx, CRTC_REG(mmCRTC_FORCE_COUNT_NOW_CNTL), value); } +void dce110_timing_generator_enable_crtc_reset( + struct timing_generator *tg, + int source_tg_inst, + struct crtc_trigger_info *crtc_tp) +{ + uint32_t value = 0; + uint32_t rising_edge = 0; + uint32_t falling_edge = 0; + struct dce110_timing_generator *tg110 = DCE110TG_FROM_TG(tg); + + /* Setup trigger edge */ + switch (crtc_tp->event) { + case CRTC_EVENT_VSYNC_RISING: + rising_edge = 1; + break; + + case CRTC_EVENT_VSYNC_FALLING: + falling_edge = 1; + break; + } + + value = dm_read_reg(tg->ctx, CRTC_REG(mmCRTC_TRIGB_CNTL)); + + set_reg_field_value(value, + source_tg_inst, + CRTC_TRIGB_CNTL, + CRTC_TRIGB_SOURCE_SELECT); + + set_reg_field_value(value, + TRIGGER_POLARITY_SELECT_LOGIC_ZERO, + CRTC_TRIGB_CNTL, + CRTC_TRIGB_POLARITY_SELECT); + + set_reg_field_value(value, + rising_edge, + CRTC_TRIGB_CNTL, + CRTC_TRIGB_RISING_EDGE_DETECT_CNTL); + + set_reg_field_value(value, + falling_edge, + CRTC_TRIGB_CNTL, + CRTC_TRIGB_FALLING_EDGE_DETECT_CNTL); + + set_reg_field_value(value, + 1, /* clear trigger status */ + CRTC_TRIGB_CNTL, + CRTC_TRIGB_CLEAR); + + dm_write_reg(tg->ctx, CRTC_REG(mmCRTC_TRIGB_CNTL), value); + + /**************************************************************/ + + switch (crtc_tp->delay) { + case TRIGGER_DELAY_NEXT_LINE: + value = dm_read_reg(tg->ctx, CRTC_REG(mmCRTC_FORCE_COUNT_NOW_CNTL)); + + set_reg_field_value(value, + 0, /* force H count to H_TOTAL and V count to V_TOTAL */ + CRTC_FORCE_COUNT_NOW_CNTL, + CRTC_FORCE_COUNT_NOW_MODE); + + set_reg_field_value(value, + 0, /* TriggerB - we never use TriggerA */ + CRTC_FORCE_COUNT_NOW_CNTL, + CRTC_FORCE_COUNT_NOW_TRIG_SEL); + + set_reg_field_value(value, + 1, /* clear trigger status */ + CRTC_FORCE_COUNT_NOW_CNTL, + CRTC_FORCE_COUNT_NOW_CLEAR); + + dm_write_reg(tg->ctx, CRTC_REG(mmCRTC_FORCE_COUNT_NOW_CNTL), value); + + value = dm_read_reg(tg->ctx, CRTC_REG(mmCRTC_VERT_SYNC_CONTROL)); + + set_reg_field_value(value, + 1, + CRTC_VERT_SYNC_CONTROL, + CRTC_FORCE_VSYNC_NEXT_LINE_CLEAR); + + set_reg_field_value(value, + 2, + CRTC_VERT_SYNC_CONTROL, + CRTC_AUTO_FORCE_VSYNC_MODE); + + break; + + case TRIGGER_DELAY_NEXT_PIXEL: + value = dm_read_reg(tg->ctx, CRTC_REG(mmCRTC_VERT_SYNC_CONTROL)); + + set_reg_field_value(value, + 1, + CRTC_VERT_SYNC_CONTROL, + CRTC_FORCE_VSYNC_NEXT_LINE_CLEAR); + + set_reg_field_value(value, + 0, + CRTC_VERT_SYNC_CONTROL, + CRTC_AUTO_FORCE_VSYNC_MODE); + + dm_write_reg(tg->ctx, CRTC_REG(mmCRTC_VERT_SYNC_CONTROL), value); + + value = dm_read_reg(tg->ctx, CRTC_REG(mmCRTC_FORCE_COUNT_NOW_CNTL)); + + set_reg_field_value(value, + 2, /* force H count to H_TOTAL and V count to V_TOTAL */ + CRTC_FORCE_COUNT_NOW_CNTL, + CRTC_FORCE_COUNT_NOW_MODE); + + set_reg_field_value(value, + 1, /* TriggerB - we never use TriggerA */ + CRTC_FORCE_COUNT_NOW_CNTL, + CRTC_FORCE_COUNT_NOW_TRIG_SEL); + + set_reg_field_value(value, + 1, /* clear trigger status */ + CRTC_FORCE_COUNT_NOW_CNTL, + CRTC_FORCE_COUNT_NOW_CLEAR); + + dm_write_reg(tg->ctx, CRTC_REG(mmCRTC_FORCE_COUNT_NOW_CNTL), value); + break; + } + + value = dm_read_reg(tg->ctx, CRTC_REG(mmCRTC_MASTER_UPDATE_MODE)); + + set_reg_field_value(value, + 2, + CRTC_MASTER_UPDATE_MODE, + MASTER_UPDATE_MODE); + + dm_write_reg(tg->ctx, CRTC_REG(mmCRTC_MASTER_UPDATE_MODE), value); +} void dce110_timing_generator_disable_reset_trigger( struct timing_generator *tg) { @@ -1564,34 +1716,48 @@ void dce110_timing_generator_disable_reset_trigger( value = dm_read_reg(tg->ctx, CRTC_REG(mmCRTC_FORCE_COUNT_NOW_CNTL)); set_reg_field_value(value, - 0, /* force counter now mode is disabled */ - CRTC_FORCE_COUNT_NOW_CNTL, - CRTC_FORCE_COUNT_NOW_MODE); + 0, /* force counter now mode is disabled */ + CRTC_FORCE_COUNT_NOW_CNTL, + CRTC_FORCE_COUNT_NOW_MODE); set_reg_field_value(value, - 1, /* clear trigger status */ - CRTC_FORCE_COUNT_NOW_CNTL, - CRTC_FORCE_COUNT_NOW_CLEAR); + 1, /* clear trigger status */ + CRTC_FORCE_COUNT_NOW_CNTL, + CRTC_FORCE_COUNT_NOW_CLEAR); dm_write_reg(tg->ctx, CRTC_REG(mmCRTC_FORCE_COUNT_NOW_CNTL), value); + value = dm_read_reg(tg->ctx, CRTC_REG(mmCRTC_VERT_SYNC_CONTROL)); + + set_reg_field_value(value, + 1, + CRTC_VERT_SYNC_CONTROL, + CRTC_FORCE_VSYNC_NEXT_LINE_CLEAR); + + set_reg_field_value(value, + 0, + CRTC_VERT_SYNC_CONTROL, + CRTC_AUTO_FORCE_VSYNC_MODE); + + dm_write_reg(tg->ctx, CRTC_REG(mmCRTC_VERT_SYNC_CONTROL), value); + /********************************************************************/ value = dm_read_reg(tg->ctx, CRTC_REG(mmCRTC_TRIGB_CNTL)); set_reg_field_value(value, - TRIGGER_SOURCE_SELECT_LOGIC_ZERO, - CRTC_TRIGB_CNTL, - CRTC_TRIGB_SOURCE_SELECT); + TRIGGER_SOURCE_SELECT_LOGIC_ZERO, + CRTC_TRIGB_CNTL, + CRTC_TRIGB_SOURCE_SELECT); set_reg_field_value(value, - TRIGGER_POLARITY_SELECT_LOGIC_ZERO, - CRTC_TRIGB_CNTL, - CRTC_TRIGB_POLARITY_SELECT); + TRIGGER_POLARITY_SELECT_LOGIC_ZERO, + CRTC_TRIGB_CNTL, + CRTC_TRIGB_POLARITY_SELECT); set_reg_field_value(value, - 1, /* clear trigger status */ - CRTC_TRIGB_CNTL, - CRTC_TRIGB_CLEAR); + 1, /* clear trigger status */ + CRTC_TRIGB_CNTL, + CRTC_TRIGB_CLEAR); dm_write_reg(tg->ctx, CRTC_REG(mmCRTC_TRIGB_CNTL), value); } @@ -1611,10 +1777,16 @@ bool dce110_timing_generator_did_triggered_reset_occur( struct dce110_timing_generator *tg110 = DCE110TG_FROM_TG(tg); uint32_t value = dm_read_reg(tg->ctx, CRTC_REG(mmCRTC_FORCE_COUNT_NOW_CNTL)); - - return get_reg_field_value(value, - CRTC_FORCE_COUNT_NOW_CNTL, - CRTC_FORCE_COUNT_NOW_OCCURRED) != 0; + uint32_t value1 = dm_read_reg(tg->ctx, + CRTC_REG(mmCRTC_VERT_SYNC_CONTROL)); + bool force = get_reg_field_value(value, + CRTC_FORCE_COUNT_NOW_CNTL, + CRTC_FORCE_COUNT_NOW_OCCURRED) != 0; + bool vert_sync = get_reg_field_value(value1, + CRTC_VERT_SYNC_CONTROL, + CRTC_FORCE_VSYNC_NEXT_LINE_OCCURRED) != 0; + + return (force || vert_sync); } /** @@ -1928,6 +2100,7 @@ static const struct timing_generator_funcs dce110_tg_funcs = { .setup_global_swap_lock = dce110_timing_generator_setup_global_swap_lock, .enable_reset_trigger = dce110_timing_generator_enable_reset_trigger, + .enable_crtc_reset = dce110_timing_generator_enable_crtc_reset, .disable_reset_trigger = dce110_timing_generator_disable_reset_trigger, .tear_down_global_swap_lock = dce110_timing_generator_tear_down_global_swap_lock, diff --git a/drivers/gpu/drm/amd/display/dc/dce110/dce110_timing_generator.h b/drivers/gpu/drm/amd/display/dc/dce110/dce110_timing_generator.h index 82737dea6984..232747c7c60b 100644 --- a/drivers/gpu/drm/amd/display/dc/dce110/dce110_timing_generator.h +++ b/drivers/gpu/drm/amd/display/dc/dce110/dce110_timing_generator.h @@ -174,6 +174,12 @@ void dce110_timing_generator_setup_global_swap_lock( void dce110_timing_generator_tear_down_global_swap_lock( struct timing_generator *tg); +/* Reset crtc position on master VSync */ +void dce110_timing_generator_enable_crtc_reset( + struct timing_generator *tg, + int source, + struct crtc_trigger_info *crtc_tp); + /* Reset slave controllers on master VSync */ void dce110_timing_generator_enable_reset_trigger( struct timing_generator *tg, diff --git a/drivers/gpu/drm/amd/display/dc/dce120/dce120_hw_sequencer.c b/drivers/gpu/drm/amd/display/dc/dce120/dce120_hw_sequencer.c index 1a0b54d6034e..75d029742f96 100644 --- a/drivers/gpu/drm/amd/display/dc/dce120/dce120_hw_sequencer.c +++ b/drivers/gpu/drm/amd/display/dc/dce120/dce120_hw_sequencer.c @@ -31,9 +31,9 @@ #include "dce110/dce110_hw_sequencer.h" -#include "vega10/DC/dce_12_0_offset.h" -#include "vega10/DC/dce_12_0_sh_mask.h" -#include "vega10/soc15ip.h" +#include "dce/dce_12_0_offset.h" +#include "dce/dce_12_0_sh_mask.h" +#include "soc15ip.h" #include "reg_helper.h" #define CTX \ diff --git a/drivers/gpu/drm/amd/display/dc/dce120/dce120_resource.c b/drivers/gpu/drm/amd/display/dc/dce120/dce120_resource.c index 5c48c22d9d98..57cd67359567 100644 --- a/drivers/gpu/drm/amd/display/dc/dce120/dce120_resource.c +++ b/drivers/gpu/drm/amd/display/dc/dce120/dce120_resource.c @@ -54,10 +54,10 @@ #include "dce/dce_abm.h" #include "dce/dce_dmcu.h" -#include "vega10/DC/dce_12_0_offset.h" -#include "vega10/DC/dce_12_0_sh_mask.h" -#include "vega10/soc15ip.h" -#include "vega10/NBIO/nbio_6_1_offset.h" +#include "dce/dce_12_0_offset.h" +#include "dce/dce_12_0_sh_mask.h" +#include "soc15ip.h" +#include "nbio/nbio_6_1_offset.h" #include "reg_helper.h" #include "dce100/dce100_resource.h" diff --git a/drivers/gpu/drm/amd/display/dc/dce120/dce120_timing_generator.c b/drivers/gpu/drm/amd/display/dc/dce120/dce120_timing_generator.c index 2502182d5e82..0aa60e5727e0 100644 --- a/drivers/gpu/drm/amd/display/dc/dce120/dce120_timing_generator.c +++ b/drivers/gpu/drm/amd/display/dc/dce120/dce120_timing_generator.c @@ -25,9 +25,9 @@ #include "dm_services.h" -#include "vega10/DC/dce_12_0_offset.h" -#include "vega10/DC/dce_12_0_sh_mask.h" -#include "vega10/soc15ip.h" +#include "dce/dce_12_0_offset.h" +#include "dce/dce_12_0_sh_mask.h" +#include "soc15ip.h" #include "dc_types.h" #include "dc_bios_types.h" diff --git a/drivers/gpu/drm/amd/display/dc/dce80/dce80_resource.c b/drivers/gpu/drm/amd/display/dc/dce80/dce80_resource.c index 9c18efd3446f..8f2bd56f3461 100644 --- a/drivers/gpu/drm/amd/display/dc/dce80/dce80_resource.c +++ b/drivers/gpu/drm/amd/display/dc/dce80/dce80_resource.c @@ -957,6 +957,7 @@ static bool dce81_construct( dc->caps.max_downscale_ratio = 200; dc->caps.i2c_speed_in_khz = 40; dc->caps.max_cursor_size = 128; + dc->caps.is_apu = true; /************************************************* * Create resources * @@ -1121,6 +1122,7 @@ static bool dce83_construct( dc->caps.max_downscale_ratio = 200; dc->caps.i2c_speed_in_khz = 40; dc->caps.max_cursor_size = 128; + dc->caps.is_apu = true; /************************************************* * Create resources * diff --git a/drivers/gpu/drm/amd/display/dc/dcn10/Makefile b/drivers/gpu/drm/amd/display/dc/dcn10/Makefile index f565a6042970..5469bdfe19f3 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn10/Makefile +++ b/drivers/gpu/drm/amd/display/dc/dcn10/Makefile @@ -23,9 +23,10 @@ # Makefile for DCN. DCN10 = dcn10_resource.o dcn10_ipp.o dcn10_hw_sequencer.o \ - dcn10_dpp.o dcn10_opp.o dcn10_timing_generator.o \ + dcn10_dpp.o dcn10_opp.o dcn10_optc.o \ dcn10_hubp.o dcn10_mpc.o \ - dcn10_dpp_dscl.o dcn10_dpp_cm.o dcn10_cm_common.o + dcn10_dpp_dscl.o dcn10_dpp_cm.o dcn10_cm_common.o \ + dcn10_hubbub.o AMD_DAL_DCN10 = $(addprefix $(AMDDALPATH)/dc/dcn10/,$(DCN10)) diff --git a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_cm_common.c b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_cm_common.c index 7f579cb19f4b..53ba3600ee6a 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_cm_common.c +++ b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_cm_common.c @@ -22,11 +22,12 @@ * Authors: AMD * */ - +#include "dc.h" #include "reg_helper.h" #include "dcn10_dpp.h" #include "dcn10_cm_common.h" +#include "custom_float.h" #define REG(reg) reg @@ -121,3 +122,294 @@ void cm_helper_program_xfer_func( } } + + + +bool cm_helper_convert_to_custom_float( + struct pwl_result_data *rgb_resulted, + struct curve_points *arr_points, + uint32_t hw_points_num, + bool fixpoint) +{ + struct custom_float_format fmt; + + struct pwl_result_data *rgb = rgb_resulted; + + uint32_t i = 0; + + fmt.exponenta_bits = 6; + fmt.mantissa_bits = 12; + fmt.sign = false; + + if (!convert_to_custom_float_format(arr_points[0].x, &fmt, + &arr_points[0].custom_float_x)) { + BREAK_TO_DEBUGGER(); + return false; + } + + if (!convert_to_custom_float_format(arr_points[0].offset, &fmt, + &arr_points[0].custom_float_offset)) { + BREAK_TO_DEBUGGER(); + return false; + } + + if (!convert_to_custom_float_format(arr_points[0].slope, &fmt, + &arr_points[0].custom_float_slope)) { + BREAK_TO_DEBUGGER(); + return false; + } + + fmt.mantissa_bits = 10; + fmt.sign = false; + + if (!convert_to_custom_float_format(arr_points[1].x, &fmt, + &arr_points[1].custom_float_x)) { + BREAK_TO_DEBUGGER(); + return false; + } + + if (fixpoint == true) + arr_points[1].custom_float_y = dal_fixed31_32_clamp_u0d14(arr_points[1].y); + else if (!convert_to_custom_float_format(arr_points[1].y, &fmt, + &arr_points[1].custom_float_y)) { + BREAK_TO_DEBUGGER(); + return false; + } + + if (!convert_to_custom_float_format(arr_points[1].slope, &fmt, + &arr_points[1].custom_float_slope)) { + BREAK_TO_DEBUGGER(); + return false; + } + + if (hw_points_num == 0 || rgb_resulted == NULL || fixpoint == true) + return true; + + fmt.mantissa_bits = 12; + fmt.sign = true; + + while (i != hw_points_num) { + if (!convert_to_custom_float_format(rgb->red, &fmt, + &rgb->red_reg)) { + BREAK_TO_DEBUGGER(); + return false; + } + + if (!convert_to_custom_float_format(rgb->green, &fmt, + &rgb->green_reg)) { + BREAK_TO_DEBUGGER(); + return false; + } + + if (!convert_to_custom_float_format(rgb->blue, &fmt, + &rgb->blue_reg)) { + BREAK_TO_DEBUGGER(); + return false; + } + + if (!convert_to_custom_float_format(rgb->delta_red, &fmt, + &rgb->delta_red_reg)) { + BREAK_TO_DEBUGGER(); + return false; + } + + if (!convert_to_custom_float_format(rgb->delta_green, &fmt, + &rgb->delta_green_reg)) { + BREAK_TO_DEBUGGER(); + return false; + } + + if (!convert_to_custom_float_format(rgb->delta_blue, &fmt, + &rgb->delta_blue_reg)) { + BREAK_TO_DEBUGGER(); + return false; + } + + ++rgb; + ++i; + } + + return true; +} + + +#define MAX_REGIONS_NUMBER 34 +#define MAX_LOW_POINT 25 +#define NUMBER_SEGMENTS 32 + +bool cm_helper_translate_curve_to_hw_format( + const struct dc_transfer_func *output_tf, + struct pwl_params *lut_params, bool fixpoint) +{ + struct curve_points *arr_points; + struct pwl_result_data *rgb_resulted; + struct pwl_result_data *rgb; + struct pwl_result_data *rgb_plus_1; + struct fixed31_32 y_r; + struct fixed31_32 y_g; + struct fixed31_32 y_b; + struct fixed31_32 y1_min; + struct fixed31_32 y3_max; + + int32_t segment_start, segment_end; + int32_t i; + uint32_t j, k, seg_distr[MAX_REGIONS_NUMBER], increment, start_index, hw_points; + + if (output_tf == NULL || lut_params == NULL || output_tf->type == TF_TYPE_BYPASS) + return false; + + PERF_TRACE(); + + arr_points = lut_params->arr_points; + rgb_resulted = lut_params->rgb_resulted; + hw_points = 0; + + memset(lut_params, 0, sizeof(struct pwl_params)); + memset(seg_distr, 0, sizeof(seg_distr)); + + if (output_tf->tf == TRANSFER_FUNCTION_PQ) { + /* 32 segments + * segments are from 2^-25 to 2^7 + */ + for (i = 0; i < 32 ; i++) + seg_distr[i] = 3; + + segment_start = -25; + segment_end = 7; + } else { + /* 10 segments + * segment is from 2^-10 to 2^0 + * There are less than 256 points, for optimization + */ + seg_distr[0] = 3; + seg_distr[1] = 4; + seg_distr[2] = 4; + seg_distr[3] = 4; + seg_distr[4] = 4; + seg_distr[5] = 4; + seg_distr[6] = 4; + seg_distr[7] = 4; + seg_distr[8] = 5; + seg_distr[9] = 5; + + segment_start = -10; + segment_end = 0; + } + + for (i = segment_end - segment_start; i < MAX_REGIONS_NUMBER ; i++) + seg_distr[i] = -1; + + for (k = 0; k < MAX_REGIONS_NUMBER; k++) { + if (seg_distr[k] != -1) + hw_points += (1 << seg_distr[k]); + } + + j = 0; + for (k = 0; k < (segment_end - segment_start); k++) { + increment = NUMBER_SEGMENTS / (1 << seg_distr[k]); + start_index = (segment_start + k + MAX_LOW_POINT) * NUMBER_SEGMENTS; + for (i = start_index; i < start_index + NUMBER_SEGMENTS; i += increment) { + if (j == hw_points - 1) + break; + rgb_resulted[j].red = output_tf->tf_pts.red[i]; + rgb_resulted[j].green = output_tf->tf_pts.green[i]; + rgb_resulted[j].blue = output_tf->tf_pts.blue[i]; + j++; + } + } + + /* last point */ + start_index = (segment_end + MAX_LOW_POINT) * NUMBER_SEGMENTS; + rgb_resulted[hw_points - 1].red = output_tf->tf_pts.red[start_index]; + rgb_resulted[hw_points - 1].green = output_tf->tf_pts.green[start_index]; + rgb_resulted[hw_points - 1].blue = output_tf->tf_pts.blue[start_index]; + + arr_points[0].x = dal_fixed31_32_pow(dal_fixed31_32_from_int(2), + dal_fixed31_32_from_int(segment_start)); + arr_points[1].x = dal_fixed31_32_pow(dal_fixed31_32_from_int(2), + dal_fixed31_32_from_int(segment_end)); + + y_r = rgb_resulted[0].red; + y_g = rgb_resulted[0].green; + y_b = rgb_resulted[0].blue; + + y1_min = dal_fixed31_32_min(y_r, dal_fixed31_32_min(y_g, y_b)); + + arr_points[0].y = y1_min; + arr_points[0].slope = dal_fixed31_32_div(arr_points[0].y, arr_points[0].x); + y_r = rgb_resulted[hw_points - 1].red; + y_g = rgb_resulted[hw_points - 1].green; + y_b = rgb_resulted[hw_points - 1].blue; + + /* see comment above, m_arrPoints[1].y should be the Y value for the + * region end (m_numOfHwPoints), not last HW point(m_numOfHwPoints - 1) + */ + y3_max = dal_fixed31_32_max(y_r, dal_fixed31_32_max(y_g, y_b)); + + arr_points[1].y = y3_max; + + arr_points[1].slope = dal_fixed31_32_zero; + + if (output_tf->tf == TRANSFER_FUNCTION_PQ) { + /* for PQ, we want to have a straight line from last HW X point, + * and the slope to be such that we hit 1.0 at 10000 nits. + */ + const struct fixed31_32 end_value = + dal_fixed31_32_from_int(125); + + arr_points[1].slope = dal_fixed31_32_div( + dal_fixed31_32_sub(dal_fixed31_32_one, arr_points[1].y), + dal_fixed31_32_sub(end_value, arr_points[1].x)); + } + + lut_params->hw_points_num = hw_points; + + i = 1; + for (k = 0; k < MAX_REGIONS_NUMBER && i < MAX_REGIONS_NUMBER; k++) { + if (seg_distr[k] != -1) { + lut_params->arr_curve_points[k].segments_num = + seg_distr[k]; + lut_params->arr_curve_points[i].offset = + lut_params->arr_curve_points[k].offset + (1 << seg_distr[k]); + } + i++; + } + + if (seg_distr[k] != -1) + lut_params->arr_curve_points[k].segments_num = seg_distr[k]; + + rgb = rgb_resulted; + rgb_plus_1 = rgb_resulted + 1; + + i = 1; + while (i != hw_points + 1) { + if (dal_fixed31_32_lt(rgb_plus_1->red, rgb->red)) + rgb_plus_1->red = rgb->red; + if (dal_fixed31_32_lt(rgb_plus_1->green, rgb->green)) + rgb_plus_1->green = rgb->green; + if (dal_fixed31_32_lt(rgb_plus_1->blue, rgb->blue)) + rgb_plus_1->blue = rgb->blue; + + rgb->delta_red = dal_fixed31_32_sub(rgb_plus_1->red, rgb->red); + rgb->delta_green = dal_fixed31_32_sub(rgb_plus_1->green, rgb->green); + rgb->delta_blue = dal_fixed31_32_sub(rgb_plus_1->blue, rgb->blue); + + if (fixpoint == true) { + rgb->delta_red_reg = dal_fixed31_32_clamp_u0d10(rgb->delta_red); + rgb->delta_green_reg = dal_fixed31_32_clamp_u0d10(rgb->delta_green); + rgb->delta_blue_reg = dal_fixed31_32_clamp_u0d10(rgb->delta_blue); + rgb->red_reg = dal_fixed31_32_clamp_u0d14(rgb->red); + rgb->green_reg = dal_fixed31_32_clamp_u0d14(rgb->green); + rgb->blue_reg = dal_fixed31_32_clamp_u0d14(rgb->blue); + } + + ++rgb_plus_1; + ++rgb; + ++i; + } + cm_helper_convert_to_custom_float(rgb_resulted, + lut_params->arr_points, + hw_points, fixpoint); + + return true; +} diff --git a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_cm_common.h b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_cm_common.h index 64836dcf21f2..64e476b83bcb 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_cm_common.h +++ b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_cm_common.h @@ -96,4 +96,14 @@ void cm_helper_program_xfer_func( const struct pwl_params *params, const struct xfer_func_reg *reg); +bool cm_helper_convert_to_custom_float( + struct pwl_result_data *rgb_resulted, + struct curve_points *arr_points, + uint32_t hw_points_num, + bool fixpoint); + +bool cm_helper_translate_curve_to_hw_format( + const struct dc_transfer_func *output_tf, + struct pwl_params *lut_params, bool fixpoint); + #endif diff --git a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_dpp.c b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_dpp.c index a9d55d0dd69e..f2a08b156cf0 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_dpp.c +++ b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_dpp.c @@ -177,37 +177,17 @@ void dpp_reset(struct dpp *dpp_base) dpp->filter_h = NULL; dpp->filter_v = NULL; - /* set boundary mode to 0 */ - REG_SET(DSCL_CONTROL, 0, SCL_BOUNDARY_MODE, 0); + memset(&dpp->scl_data, 0, sizeof(dpp->scl_data)); + memset(&dpp->pwl_data, 0, sizeof(dpp->pwl_data)); } static void dpp1_cm_set_regamma_pwl( - struct dpp *dpp_base, const struct pwl_params *params) -{ - struct dcn10_dpp *dpp = TO_DCN10_DPP(dpp_base); - - dpp1_cm_power_on_regamma_lut(dpp_base, true); - dpp1_cm_configure_regamma_lut(dpp_base, dpp->is_write_to_ram_a_safe); - - if (dpp->is_write_to_ram_a_safe) - dpp1_cm_program_regamma_luta_settings(dpp_base, params); - else - dpp1_cm_program_regamma_lutb_settings(dpp_base, params); - - dpp1_cm_program_regamma_lut( - dpp_base, params->rgb_resulted, params->hw_points_num); -} - -static void dpp1_cm_set_regamma_mode( - struct dpp *dpp_base, - enum opp_regamma mode) + struct dpp *dpp_base, const struct pwl_params *params, enum opp_regamma mode) { struct dcn10_dpp *dpp = TO_DCN10_DPP(dpp_base); uint32_t re_mode = 0; - uint32_t obuf_bypass = 0; /* need for pipe split */ - uint32_t obuf_hupscale = 0; switch (mode) { case OPP_REGAMMA_BYPASS: @@ -220,17 +200,29 @@ static void dpp1_cm_set_regamma_mode( re_mode = 2; break; case OPP_REGAMMA_USER: + re_mode = dpp->is_write_to_ram_a_safe ? 4 : 3; + if (memcmp(&dpp->pwl_data, params, sizeof(*params)) == 0) + break; + + dpp1_cm_power_on_regamma_lut(dpp_base, true); + dpp1_cm_configure_regamma_lut(dpp_base, dpp->is_write_to_ram_a_safe); + + if (dpp->is_write_to_ram_a_safe) + dpp1_cm_program_regamma_luta_settings(dpp_base, params); + else + dpp1_cm_program_regamma_lutb_settings(dpp_base, params); + + dpp1_cm_program_regamma_lut(dpp_base, params->rgb_resulted, + params->hw_points_num); + dpp->pwl_data = *params; + re_mode = dpp->is_write_to_ram_a_safe ? 3 : 4; dpp->is_write_to_ram_a_safe = !dpp->is_write_to_ram_a_safe; break; default: break; } - REG_SET(CM_RGAM_CONTROL, 0, CM_RGAM_LUT_MODE, re_mode); - REG_UPDATE_2(OBUF_CONTROL, - OBUF_BYPASS, obuf_bypass, - OBUF_H_2X_UPSCALE_EN, obuf_hupscale); } static void dpp1_setup_format_flags(enum surface_pixel_format input_format,\ @@ -263,8 +255,10 @@ static void dpp1_set_degamma_format_float( void dpp1_cnv_setup ( struct dpp *dpp_base, - enum surface_pixel_format input_format, - enum expansion_mode mode) + enum surface_pixel_format format, + enum expansion_mode mode, + struct csc_transform input_csc_color_matrix, + enum dc_color_space input_color_space) { uint32_t pixel_format; uint32_t alpha_en; @@ -274,8 +268,10 @@ void dpp1_cnv_setup ( bool is_float; struct dcn10_dpp *dpp = TO_DCN10_DPP(dpp_base); bool force_disable_cursor = false; + struct out_csc_color_matrix tbl_entry; + int i = 0; - dpp1_setup_format_flags(input_format, &fmt); + dpp1_setup_format_flags(format, &fmt); alpha_en = 1; pixel_format = 0; color_space = COLOR_SPACE_SRGB; @@ -305,7 +301,7 @@ void dpp1_cnv_setup ( dpp1_set_degamma_format_float(dpp_base, is_float); - switch (input_format) { + switch (format) { case SURFACE_PIXEL_FORMAT_GRPH_ARGB1555: pixel_format = 1; break; @@ -361,7 +357,23 @@ void dpp1_cnv_setup ( CNVC_SURFACE_PIXEL_FORMAT, pixel_format); REG_UPDATE(FORMAT_CONTROL, FORMAT_CONTROL__ALPHA_EN, alpha_en); - dpp1_program_input_csc(dpp_base, color_space, select); + // if input adjustments exist, program icsc with those values + + if (input_csc_color_matrix.enable_adjustment + == true) { + for (i = 0; i < 12; i++) + tbl_entry.regval[i] = input_csc_color_matrix.matrix[i]; + + tbl_entry.color_space = input_color_space; + + if (color_space >= COLOR_SPACE_YCBCR601) + select = INPUT_CSC_SELECT_ICSC; + else + select = INPUT_CSC_SELECT_BYPASS; + + dpp1_program_input_csc(dpp_base, color_space, select, &tbl_entry); + } else + dpp1_program_input_csc(dpp_base, color_space, select, NULL); if (force_disable_cursor) { REG_UPDATE(CURSOR_CONTROL, @@ -373,10 +385,9 @@ void dpp1_cnv_setup ( void dpp1_set_cursor_attributes( struct dpp *dpp_base, - const struct dc_cursor_attributes *attr) + enum dc_cursor_color_format color_format) { struct dcn10_dpp *dpp = TO_DCN10_DPP(dpp_base); - enum dc_cursor_color_format color_format = attr->color_format; REG_UPDATE_2(CURSOR0_CONTROL, CUR0_MODE, color_format, @@ -389,13 +400,6 @@ void dpp1_set_cursor_attributes( REG_UPDATE(CURSOR0_COLOR1, CUR0_COLOR1, 0xFFFFFFFF); } - - /* TODO: Fixed vs float */ - - REG_UPDATE_3(FORMAT_CONTROL, - CNVC_BYPASS, 0, - FORMAT_CONTROL__ALPHA_EN, 1, - FORMAT_EXPANSION_MODE, 0); } @@ -425,20 +429,20 @@ static const struct dpp_funcs dcn10_dpp_funcs = { .dpp_set_scaler = dpp1_dscl_set_scaler_manual_scale, .dpp_get_optimal_number_of_taps = dpp_get_optimal_number_of_taps, .dpp_set_gamut_remap = dpp1_cm_set_gamut_remap, - .opp_set_csc_adjustment = dpp1_cm_set_output_csc_adjustment, - .opp_set_csc_default = dpp1_cm_set_output_csc_default, - .opp_power_on_regamma_lut = dpp1_cm_power_on_regamma_lut, - .opp_program_regamma_lut = dpp1_cm_program_regamma_lut, - .opp_configure_regamma_lut = dpp1_cm_configure_regamma_lut, - .opp_program_regamma_lutb_settings = dpp1_cm_program_regamma_lutb_settings, - .opp_program_regamma_luta_settings = dpp1_cm_program_regamma_luta_settings, - .opp_program_regamma_pwl = dpp1_cm_set_regamma_pwl, - .opp_set_regamma_mode = dpp1_cm_set_regamma_mode, - .ipp_set_degamma = dpp1_set_degamma, - .ipp_program_input_lut = dpp1_program_input_lut, - .ipp_program_degamma_pwl = dpp1_set_degamma_pwl, - .ipp_setup = dpp1_cnv_setup, - .ipp_full_bypass = dpp1_full_bypass, + .dpp_set_csc_adjustment = dpp1_cm_set_output_csc_adjustment, + .dpp_set_csc_default = dpp1_cm_set_output_csc_default, + .dpp_power_on_regamma_lut = dpp1_cm_power_on_regamma_lut, + .dpp_program_regamma_lut = dpp1_cm_program_regamma_lut, + .dpp_configure_regamma_lut = dpp1_cm_configure_regamma_lut, + .dpp_program_regamma_lutb_settings = dpp1_cm_program_regamma_lutb_settings, + .dpp_program_regamma_luta_settings = dpp1_cm_program_regamma_luta_settings, + .dpp_program_regamma_pwl = dpp1_cm_set_regamma_pwl, + .dpp_program_bias_and_scale = dpp1_program_bias_and_scale, + .dpp_set_degamma = dpp1_set_degamma, + .dpp_program_input_lut = dpp1_program_input_lut, + .dpp_program_degamma_pwl = dpp1_set_degamma_pwl, + .dpp_setup = dpp1_cnv_setup, + .dpp_full_bypass = dpp1_full_bypass, .set_cursor_attributes = dpp1_set_cursor_attributes, .set_cursor_position = dpp1_set_cursor_position, }; diff --git a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_dpp.h b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_dpp.h index 34daf895f848..f56ee4d08d89 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_dpp.h +++ b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_dpp.h @@ -54,7 +54,6 @@ SRI(LB_MEMORY_CTRL, DSCL, id), \ SRI(DSCL_AUTOCAL, DSCL, id), \ SRI(SCL_BLACK_OFFSET, DSCL, id), \ - SRI(DSCL_CONTROL, DSCL, id), \ SRI(SCL_TAP_CONTROL, DSCL, id), \ SRI(SCL_COEF_RAM_TAP_SELECT, DSCL, id), \ SRI(SCL_COEF_RAM_TAP_DATA, DSCL, id), \ @@ -72,7 +71,6 @@ SRI(SCL_VERT_FILTER_INIT_BOT_C, DSCL, id), \ SRI(RECOUT_START, DSCL, id), \ SRI(RECOUT_SIZE, DSCL, id), \ - SRI(OBUF_CONTROL, DSCL, id), \ SRI(CM_ICSC_CONTROL, CM, id), \ SRI(CM_ICSC_C11_C12, CM, id), \ SRI(CM_ICSC_C33_C34, CM, id), \ @@ -127,6 +125,9 @@ SRI(CM_OCSC_CONTROL, CM, id), \ SRI(CM_OCSC_C11_C12, CM, id), \ SRI(CM_OCSC_C33_C34, CM, id), \ + SRI(CM_BNS_VALUES_R, CM, id), \ + SRI(CM_BNS_VALUES_G, CM, id), \ + SRI(CM_BNS_VALUES_B, CM, id), \ SRI(CM_MEM_PWR_CTRL, CM, id), \ SRI(CM_RGAM_LUT_DATA, CM, id), \ SRI(CM_RGAM_LUT_WRITE_EN_MASK, CM, id),\ @@ -191,7 +192,6 @@ TF_SF(DSCL0_DSCL_AUTOCAL, AUTOCAL_PIPE_ID, mask_sh),\ TF_SF(DSCL0_SCL_BLACK_OFFSET, SCL_BLACK_OFFSET_RGB_Y, mask_sh),\ TF_SF(DSCL0_SCL_BLACK_OFFSET, SCL_BLACK_OFFSET_CBCR, mask_sh),\ - TF_SF(DSCL0_DSCL_CONTROL, SCL_BOUNDARY_MODE, mask_sh),\ TF_SF(DSCL0_SCL_TAP_CONTROL, SCL_V_NUM_TAPS, mask_sh),\ TF_SF(DSCL0_SCL_TAP_CONTROL, SCL_H_NUM_TAPS, mask_sh),\ TF_SF(DSCL0_SCL_TAP_CONTROL, SCL_V_NUM_TAPS_C, mask_sh),\ @@ -235,7 +235,6 @@ TF_SF(DSCL0_SCL_VERT_FILTER_INIT_BOT_C, SCL_V_INIT_INT_BOT_C, mask_sh),\ TF_SF(DSCL0_SCL_MODE, SCL_CHROMA_COEF_MODE, mask_sh),\ TF_SF(DSCL0_SCL_MODE, SCL_COEF_RAM_SELECT_CURRENT, mask_sh), \ - TF_SF(DSCL0_OBUF_CONTROL, OBUF_BYPASS, mask_sh), \ TF_SF(CM0_CM_ICSC_CONTROL, CM_ICSC_MODE, mask_sh), \ TF_SF(CM0_CM_ICSC_C11_C12, CM_ICSC_C11, mask_sh), \ TF_SF(CM0_CM_ICSC_C11_C12, CM_ICSC_C12, mask_sh), \ @@ -329,6 +328,12 @@ TF_SF(CM0_CM_OCSC_C11_C12, CM_OCSC_C12, mask_sh), \ TF_SF(CM0_CM_OCSC_C33_C34, CM_OCSC_C33, mask_sh), \ TF_SF(CM0_CM_OCSC_C33_C34, CM_OCSC_C34, mask_sh), \ + TF_SF(CM0_CM_BNS_VALUES_R, CM_BNS_BIAS_R, mask_sh), \ + TF_SF(CM0_CM_BNS_VALUES_G, CM_BNS_BIAS_G, mask_sh), \ + TF_SF(CM0_CM_BNS_VALUES_B, CM_BNS_BIAS_B, mask_sh), \ + TF_SF(CM0_CM_BNS_VALUES_R, CM_BNS_SCALE_R, mask_sh), \ + TF_SF(CM0_CM_BNS_VALUES_G, CM_BNS_SCALE_G, mask_sh), \ + TF_SF(CM0_CM_BNS_VALUES_B, CM_BNS_SCALE_B, mask_sh), \ TF_SF(CM0_CM_MEM_PWR_CTRL, RGAM_MEM_PWR_FORCE, mask_sh), \ TF_SF(CM0_CM_RGAM_LUT_DATA, CM_RGAM_LUT_DATA, mask_sh), \ TF_SF(CM0_CM_RGAM_LUT_WRITE_EN_MASK, CM_RGAM_LUT_WRITE_EN_MASK, mask_sh), \ @@ -387,7 +392,6 @@ TF_SF(CM0_CM_RGAM_RAMA_REGION_32_33, CM_RGAM_RAMA_EXP_REGION33_LUT_OFFSET, mask_sh), \ TF_SF(CM0_CM_RGAM_RAMA_REGION_32_33, CM_RGAM_RAMA_EXP_REGION33_NUM_SEGMENTS, mask_sh), \ TF_SF(CM0_CM_RGAM_CONTROL, CM_RGAM_LUT_MODE, mask_sh), \ - TF_SF(DSCL0_OBUF_CONTROL, OBUF_H_2X_UPSCALE_EN, mask_sh), \ TF_SF(CM0_CM_IGAM_CONTROL, CM_IGAM_LUT_MODE, mask_sh), \ TF_SF(CM0_CM_IGAM_CONTROL, CM_IGAM_LUT_FORMAT_R, mask_sh), \ TF_SF(CM0_CM_IGAM_CONTROL, CM_IGAM_LUT_FORMAT_G, mask_sh), \ @@ -431,7 +435,6 @@ type AUTOCAL_PIPE_ID; \ type SCL_BLACK_OFFSET_RGB_Y; \ type SCL_BLACK_OFFSET_CBCR; \ - type SCL_BOUNDARY_MODE; \ type SCL_V_NUM_TAPS; \ type SCL_H_NUM_TAPS; \ type SCL_V_NUM_TAPS_C; \ @@ -552,8 +555,6 @@ type CM_RGAM_RAMA_EXP_REGION33_NUM_SEGMENTS; \ type CM_RGAM_LUT_MODE; \ type CM_CMOUT_ROUND_TRUNC_MODE; \ - type OBUF_BYPASS; \ - type OBUF_H_2X_UPSCALE_EN; \ type CM_BLNDGAM_LUT_MODE; \ type CM_BLNDGAM_RAMB_EXP_REGION_START_B; \ type CM_BLNDGAM_RAMB_EXP_REGION_START_SEGMENT_B; \ @@ -729,8 +730,9 @@ type CM_BLNDGAM_RAMA_EXP_REGION33_NUM_SEGMENTS; \ type CM_BLNDGAM_LUT_WRITE_EN_MASK; \ type CM_BLNDGAM_LUT_WRITE_SEL; \ + type CM_BLNDGAM_CONFIG_STATUS; \ type CM_BLNDGAM_LUT_INDEX; \ - type CM_BLNDGAM_LUT_DATA; \ + type BLNDGAM_MEM_PWR_FORCE; \ type CM_3DLUT_MODE; \ type CM_3DLUT_SIZE; \ type CM_3DLUT_INDEX; \ @@ -904,6 +906,7 @@ type CM_SHAPER_RAMA_EXP_REGION33_LUT_OFFSET; \ type CM_SHAPER_RAMA_EXP_REGION33_NUM_SEGMENTS; \ type CM_SHAPER_LUT_WRITE_EN_MASK; \ + type CM_SHAPER_CONFIG_STATUS; \ type CM_SHAPER_LUT_WRITE_SEL; \ type CM_SHAPER_LUT_INDEX; \ type CM_SHAPER_LUT_DATA; \ @@ -913,6 +916,12 @@ type CM_ICSC_C12; \ type CM_ICSC_C33; \ type CM_ICSC_C34; \ + type CM_BNS_BIAS_R; \ + type CM_BNS_BIAS_G; \ + type CM_BNS_BIAS_B; \ + type CM_BNS_SCALE_R; \ + type CM_BNS_SCALE_G; \ + type CM_BNS_SCALE_B; \ type CM_DGAM_RAMB_EXP_REGION_START_B; \ type CM_DGAM_RAMB_EXP_REGION_START_SEGMENT_B; \ type CM_DGAM_RAMB_EXP_REGION_START_G; \ @@ -998,257 +1007,255 @@ type CM_BYPASS; \ type FORMAT_CONTROL__ALPHA_EN; \ type CUR0_COLOR0; \ - type CUR0_COLOR1 - - + type CUR0_COLOR1; struct dcn_dpp_shift { - TF_REG_FIELD_LIST(uint8_t); + TF_REG_FIELD_LIST(uint8_t) }; struct dcn_dpp_mask { - TF_REG_FIELD_LIST(uint32_t); + TF_REG_FIELD_LIST(uint32_t) }; - - +#define DPP_COMMON_REG_VARIABLE_LIST \ + uint32_t DSCL_EXT_OVERSCAN_LEFT_RIGHT; \ + uint32_t DSCL_EXT_OVERSCAN_TOP_BOTTOM; \ + uint32_t OTG_H_BLANK; \ + uint32_t OTG_V_BLANK; \ + uint32_t SCL_MODE; \ + uint32_t LB_DATA_FORMAT; \ + uint32_t LB_MEMORY_CTRL; \ + uint32_t DSCL_AUTOCAL; \ + uint32_t SCL_BLACK_OFFSET; \ + uint32_t SCL_TAP_CONTROL; \ + uint32_t SCL_COEF_RAM_TAP_SELECT; \ + uint32_t SCL_COEF_RAM_TAP_DATA; \ + uint32_t DSCL_2TAP_CONTROL; \ + uint32_t MPC_SIZE; \ + uint32_t SCL_HORZ_FILTER_SCALE_RATIO; \ + uint32_t SCL_VERT_FILTER_SCALE_RATIO; \ + uint32_t SCL_HORZ_FILTER_SCALE_RATIO_C; \ + uint32_t SCL_VERT_FILTER_SCALE_RATIO_C; \ + uint32_t SCL_HORZ_FILTER_INIT; \ + uint32_t SCL_HORZ_FILTER_INIT_C; \ + uint32_t SCL_VERT_FILTER_INIT; \ + uint32_t SCL_VERT_FILTER_INIT_BOT; \ + uint32_t SCL_VERT_FILTER_INIT_C; \ + uint32_t SCL_VERT_FILTER_INIT_BOT_C; \ + uint32_t RECOUT_START; \ + uint32_t RECOUT_SIZE; \ + uint32_t CM_GAMUT_REMAP_CONTROL; \ + uint32_t CM_GAMUT_REMAP_C11_C12; \ + uint32_t CM_GAMUT_REMAP_C33_C34; \ + uint32_t CM_COMA_C11_C12; \ + uint32_t CM_COMA_C33_C34; \ + uint32_t CM_COMB_C11_C12; \ + uint32_t CM_COMB_C33_C34; \ + uint32_t CM_OCSC_CONTROL; \ + uint32_t CM_OCSC_C11_C12; \ + uint32_t CM_OCSC_C33_C34; \ + uint32_t CM_MEM_PWR_CTRL; \ + uint32_t CM_RGAM_LUT_DATA; \ + uint32_t CM_RGAM_LUT_WRITE_EN_MASK; \ + uint32_t CM_RGAM_LUT_INDEX; \ + uint32_t CM_RGAM_RAMB_START_CNTL_B; \ + uint32_t CM_RGAM_RAMB_START_CNTL_G; \ + uint32_t CM_RGAM_RAMB_START_CNTL_R; \ + uint32_t CM_RGAM_RAMB_SLOPE_CNTL_B; \ + uint32_t CM_RGAM_RAMB_SLOPE_CNTL_G; \ + uint32_t CM_RGAM_RAMB_SLOPE_CNTL_R; \ + uint32_t CM_RGAM_RAMB_END_CNTL1_B; \ + uint32_t CM_RGAM_RAMB_END_CNTL2_B; \ + uint32_t CM_RGAM_RAMB_END_CNTL1_G; \ + uint32_t CM_RGAM_RAMB_END_CNTL2_G; \ + uint32_t CM_RGAM_RAMB_END_CNTL1_R; \ + uint32_t CM_RGAM_RAMB_END_CNTL2_R; \ + uint32_t CM_RGAM_RAMB_REGION_0_1; \ + uint32_t CM_RGAM_RAMB_REGION_32_33; \ + uint32_t CM_RGAM_RAMA_START_CNTL_B; \ + uint32_t CM_RGAM_RAMA_START_CNTL_G; \ + uint32_t CM_RGAM_RAMA_START_CNTL_R; \ + uint32_t CM_RGAM_RAMA_SLOPE_CNTL_B; \ + uint32_t CM_RGAM_RAMA_SLOPE_CNTL_G; \ + uint32_t CM_RGAM_RAMA_SLOPE_CNTL_R; \ + uint32_t CM_RGAM_RAMA_END_CNTL1_B; \ + uint32_t CM_RGAM_RAMA_END_CNTL2_B; \ + uint32_t CM_RGAM_RAMA_END_CNTL1_G; \ + uint32_t CM_RGAM_RAMA_END_CNTL2_G; \ + uint32_t CM_RGAM_RAMA_END_CNTL1_R; \ + uint32_t CM_RGAM_RAMA_END_CNTL2_R; \ + uint32_t CM_RGAM_RAMA_REGION_0_1; \ + uint32_t CM_RGAM_RAMA_REGION_32_33; \ + uint32_t CM_RGAM_CONTROL; \ + uint32_t CM_CMOUT_CONTROL; \ + uint32_t CM_BLNDGAM_LUT_WRITE_EN_MASK; \ + uint32_t CM_BLNDGAM_CONTROL; \ + uint32_t CM_BLNDGAM_RAMB_START_CNTL_B; \ + uint32_t CM_BLNDGAM_RAMB_START_CNTL_G; \ + uint32_t CM_BLNDGAM_RAMB_START_CNTL_R; \ + uint32_t CM_BLNDGAM_RAMB_SLOPE_CNTL_B; \ + uint32_t CM_BLNDGAM_RAMB_SLOPE_CNTL_G; \ + uint32_t CM_BLNDGAM_RAMB_SLOPE_CNTL_R; \ + uint32_t CM_BLNDGAM_RAMB_END_CNTL1_B; \ + uint32_t CM_BLNDGAM_RAMB_END_CNTL2_B; \ + uint32_t CM_BLNDGAM_RAMB_END_CNTL1_G; \ + uint32_t CM_BLNDGAM_RAMB_END_CNTL2_G; \ + uint32_t CM_BLNDGAM_RAMB_END_CNTL1_R; \ + uint32_t CM_BLNDGAM_RAMB_END_CNTL2_R; \ + uint32_t CM_BLNDGAM_RAMB_REGION_0_1; \ + uint32_t CM_BLNDGAM_RAMB_REGION_2_3; \ + uint32_t CM_BLNDGAM_RAMB_REGION_4_5; \ + uint32_t CM_BLNDGAM_RAMB_REGION_6_7; \ + uint32_t CM_BLNDGAM_RAMB_REGION_8_9; \ + uint32_t CM_BLNDGAM_RAMB_REGION_10_11; \ + uint32_t CM_BLNDGAM_RAMB_REGION_12_13; \ + uint32_t CM_BLNDGAM_RAMB_REGION_14_15; \ + uint32_t CM_BLNDGAM_RAMB_REGION_16_17; \ + uint32_t CM_BLNDGAM_RAMB_REGION_18_19; \ + uint32_t CM_BLNDGAM_RAMB_REGION_20_21; \ + uint32_t CM_BLNDGAM_RAMB_REGION_22_23; \ + uint32_t CM_BLNDGAM_RAMB_REGION_24_25; \ + uint32_t CM_BLNDGAM_RAMB_REGION_26_27; \ + uint32_t CM_BLNDGAM_RAMB_REGION_28_29; \ + uint32_t CM_BLNDGAM_RAMB_REGION_30_31; \ + uint32_t CM_BLNDGAM_RAMB_REGION_32_33; \ + uint32_t CM_BLNDGAM_RAMA_START_CNTL_B; \ + uint32_t CM_BLNDGAM_RAMA_START_CNTL_G; \ + uint32_t CM_BLNDGAM_RAMA_START_CNTL_R; \ + uint32_t CM_BLNDGAM_RAMA_SLOPE_CNTL_B; \ + uint32_t CM_BLNDGAM_RAMA_SLOPE_CNTL_G; \ + uint32_t CM_BLNDGAM_RAMA_SLOPE_CNTL_R; \ + uint32_t CM_BLNDGAM_RAMA_END_CNTL1_B; \ + uint32_t CM_BLNDGAM_RAMA_END_CNTL2_B; \ + uint32_t CM_BLNDGAM_RAMA_END_CNTL1_G; \ + uint32_t CM_BLNDGAM_RAMA_END_CNTL2_G; \ + uint32_t CM_BLNDGAM_RAMA_END_CNTL1_R; \ + uint32_t CM_BLNDGAM_RAMA_END_CNTL2_R; \ + uint32_t CM_BLNDGAM_RAMA_REGION_0_1; \ + uint32_t CM_BLNDGAM_RAMA_REGION_2_3; \ + uint32_t CM_BLNDGAM_RAMA_REGION_4_5; \ + uint32_t CM_BLNDGAM_RAMA_REGION_6_7; \ + uint32_t CM_BLNDGAM_RAMA_REGION_8_9; \ + uint32_t CM_BLNDGAM_RAMA_REGION_10_11; \ + uint32_t CM_BLNDGAM_RAMA_REGION_12_13; \ + uint32_t CM_BLNDGAM_RAMA_REGION_14_15; \ + uint32_t CM_BLNDGAM_RAMA_REGION_16_17; \ + uint32_t CM_BLNDGAM_RAMA_REGION_18_19; \ + uint32_t CM_BLNDGAM_RAMA_REGION_20_21; \ + uint32_t CM_BLNDGAM_RAMA_REGION_22_23; \ + uint32_t CM_BLNDGAM_RAMA_REGION_24_25; \ + uint32_t CM_BLNDGAM_RAMA_REGION_26_27; \ + uint32_t CM_BLNDGAM_RAMA_REGION_28_29; \ + uint32_t CM_BLNDGAM_RAMA_REGION_30_31; \ + uint32_t CM_BLNDGAM_RAMA_REGION_32_33; \ + uint32_t CM_BLNDGAM_LUT_INDEX; \ + uint32_t CM_3DLUT_MODE; \ + uint32_t CM_3DLUT_INDEX; \ + uint32_t CM_3DLUT_DATA; \ + uint32_t CM_3DLUT_DATA_30BIT; \ + uint32_t CM_3DLUT_READ_WRITE_CONTROL; \ + uint32_t CM_SHAPER_LUT_WRITE_EN_MASK; \ + uint32_t CM_SHAPER_CONTROL; \ + uint32_t CM_SHAPER_RAMB_START_CNTL_B; \ + uint32_t CM_SHAPER_RAMB_START_CNTL_G; \ + uint32_t CM_SHAPER_RAMB_START_CNTL_R; \ + uint32_t CM_SHAPER_RAMB_END_CNTL_B; \ + uint32_t CM_SHAPER_RAMB_END_CNTL_G; \ + uint32_t CM_SHAPER_RAMB_END_CNTL_R; \ + uint32_t CM_SHAPER_RAMB_REGION_0_1; \ + uint32_t CM_SHAPER_RAMB_REGION_2_3; \ + uint32_t CM_SHAPER_RAMB_REGION_4_5; \ + uint32_t CM_SHAPER_RAMB_REGION_6_7; \ + uint32_t CM_SHAPER_RAMB_REGION_8_9; \ + uint32_t CM_SHAPER_RAMB_REGION_10_11; \ + uint32_t CM_SHAPER_RAMB_REGION_12_13; \ + uint32_t CM_SHAPER_RAMB_REGION_14_15; \ + uint32_t CM_SHAPER_RAMB_REGION_16_17; \ + uint32_t CM_SHAPER_RAMB_REGION_18_19; \ + uint32_t CM_SHAPER_RAMB_REGION_20_21; \ + uint32_t CM_SHAPER_RAMB_REGION_22_23; \ + uint32_t CM_SHAPER_RAMB_REGION_24_25; \ + uint32_t CM_SHAPER_RAMB_REGION_26_27; \ + uint32_t CM_SHAPER_RAMB_REGION_28_29; \ + uint32_t CM_SHAPER_RAMB_REGION_30_31; \ + uint32_t CM_SHAPER_RAMB_REGION_32_33; \ + uint32_t CM_SHAPER_RAMA_START_CNTL_B; \ + uint32_t CM_SHAPER_RAMA_START_CNTL_G; \ + uint32_t CM_SHAPER_RAMA_START_CNTL_R; \ + uint32_t CM_SHAPER_RAMA_END_CNTL_B; \ + uint32_t CM_SHAPER_RAMA_END_CNTL_G; \ + uint32_t CM_SHAPER_RAMA_END_CNTL_R; \ + uint32_t CM_SHAPER_RAMA_REGION_0_1; \ + uint32_t CM_SHAPER_RAMA_REGION_2_3; \ + uint32_t CM_SHAPER_RAMA_REGION_4_5; \ + uint32_t CM_SHAPER_RAMA_REGION_6_7; \ + uint32_t CM_SHAPER_RAMA_REGION_8_9; \ + uint32_t CM_SHAPER_RAMA_REGION_10_11; \ + uint32_t CM_SHAPER_RAMA_REGION_12_13; \ + uint32_t CM_SHAPER_RAMA_REGION_14_15; \ + uint32_t CM_SHAPER_RAMA_REGION_16_17; \ + uint32_t CM_SHAPER_RAMA_REGION_18_19; \ + uint32_t CM_SHAPER_RAMA_REGION_20_21; \ + uint32_t CM_SHAPER_RAMA_REGION_22_23; \ + uint32_t CM_SHAPER_RAMA_REGION_24_25; \ + uint32_t CM_SHAPER_RAMA_REGION_26_27; \ + uint32_t CM_SHAPER_RAMA_REGION_28_29; \ + uint32_t CM_SHAPER_RAMA_REGION_30_31; \ + uint32_t CM_SHAPER_RAMA_REGION_32_33; \ + uint32_t CM_SHAPER_LUT_INDEX; \ + uint32_t CM_SHAPER_LUT_DATA; \ + uint32_t CM_ICSC_CONTROL; \ + uint32_t CM_ICSC_C11_C12; \ + uint32_t CM_ICSC_C33_C34; \ + uint32_t CM_BNS_VALUES_R; \ + uint32_t CM_BNS_VALUES_G; \ + uint32_t CM_BNS_VALUES_B; \ + uint32_t CM_DGAM_RAMB_START_CNTL_B; \ + uint32_t CM_DGAM_RAMB_START_CNTL_G; \ + uint32_t CM_DGAM_RAMB_START_CNTL_R; \ + uint32_t CM_DGAM_RAMB_SLOPE_CNTL_B; \ + uint32_t CM_DGAM_RAMB_SLOPE_CNTL_G; \ + uint32_t CM_DGAM_RAMB_SLOPE_CNTL_R; \ + uint32_t CM_DGAM_RAMB_END_CNTL1_B; \ + uint32_t CM_DGAM_RAMB_END_CNTL2_B; \ + uint32_t CM_DGAM_RAMB_END_CNTL1_G; \ + uint32_t CM_DGAM_RAMB_END_CNTL2_G; \ + uint32_t CM_DGAM_RAMB_END_CNTL1_R; \ + uint32_t CM_DGAM_RAMB_END_CNTL2_R; \ + uint32_t CM_DGAM_RAMB_REGION_0_1; \ + uint32_t CM_DGAM_RAMB_REGION_14_15; \ + uint32_t CM_DGAM_RAMA_START_CNTL_B; \ + uint32_t CM_DGAM_RAMA_START_CNTL_G; \ + uint32_t CM_DGAM_RAMA_START_CNTL_R; \ + uint32_t CM_DGAM_RAMA_SLOPE_CNTL_B; \ + uint32_t CM_DGAM_RAMA_SLOPE_CNTL_G; \ + uint32_t CM_DGAM_RAMA_SLOPE_CNTL_R; \ + uint32_t CM_DGAM_RAMA_END_CNTL1_B; \ + uint32_t CM_DGAM_RAMA_END_CNTL2_B; \ + uint32_t CM_DGAM_RAMA_END_CNTL1_G; \ + uint32_t CM_DGAM_RAMA_END_CNTL2_G; \ + uint32_t CM_DGAM_RAMA_END_CNTL1_R; \ + uint32_t CM_DGAM_RAMA_END_CNTL2_R; \ + uint32_t CM_DGAM_RAMA_REGION_0_1; \ + uint32_t CM_DGAM_RAMA_REGION_14_15; \ + uint32_t CM_DGAM_LUT_WRITE_EN_MASK; \ + uint32_t CM_DGAM_LUT_INDEX; \ + uint32_t CM_DGAM_LUT_DATA; \ + uint32_t CM_CONTROL; \ + uint32_t CM_DGAM_CONTROL; \ + uint32_t CM_IGAM_CONTROL; \ + uint32_t CM_IGAM_LUT_RW_CONTROL; \ + uint32_t CM_IGAM_LUT_RW_INDEX; \ + uint32_t CM_IGAM_LUT_SEQ_COLOR; \ + uint32_t FORMAT_CONTROL; \ + uint32_t CNVC_SURFACE_PIXEL_FORMAT; \ + uint32_t CURSOR_CONTROL; \ + uint32_t CURSOR0_CONTROL; \ + uint32_t CURSOR0_COLOR0; \ + uint32_t CURSOR0_COLOR1; struct dcn_dpp_registers { - uint32_t DSCL_EXT_OVERSCAN_LEFT_RIGHT; - uint32_t DSCL_EXT_OVERSCAN_TOP_BOTTOM; - uint32_t OTG_H_BLANK; - uint32_t OTG_V_BLANK; - uint32_t SCL_MODE; - uint32_t LB_DATA_FORMAT; - uint32_t LB_MEMORY_CTRL; - uint32_t DSCL_AUTOCAL; - uint32_t SCL_BLACK_OFFSET; - uint32_t DSCL_CONTROL; - uint32_t SCL_TAP_CONTROL; - uint32_t SCL_COEF_RAM_TAP_SELECT; - uint32_t SCL_COEF_RAM_TAP_DATA; - uint32_t DSCL_2TAP_CONTROL; - uint32_t MPC_SIZE; - uint32_t SCL_HORZ_FILTER_SCALE_RATIO; - uint32_t SCL_VERT_FILTER_SCALE_RATIO; - uint32_t SCL_HORZ_FILTER_SCALE_RATIO_C; - uint32_t SCL_VERT_FILTER_SCALE_RATIO_C; - uint32_t SCL_HORZ_FILTER_INIT; - uint32_t SCL_HORZ_FILTER_INIT_C; - uint32_t SCL_VERT_FILTER_INIT; - uint32_t SCL_VERT_FILTER_INIT_BOT; - uint32_t SCL_VERT_FILTER_INIT_C; - uint32_t SCL_VERT_FILTER_INIT_BOT_C; - uint32_t RECOUT_START; - uint32_t RECOUT_SIZE; - uint32_t CM_GAMUT_REMAP_CONTROL; - uint32_t CM_GAMUT_REMAP_C11_C12; - uint32_t CM_GAMUT_REMAP_C33_C34; - uint32_t CM_COMA_C11_C12; - uint32_t CM_COMA_C33_C34; - uint32_t CM_COMB_C11_C12; - uint32_t CM_COMB_C33_C34; - uint32_t CM_OCSC_CONTROL; - uint32_t CM_OCSC_C11_C12; - uint32_t CM_OCSC_C33_C34; - uint32_t CM_MEM_PWR_CTRL; - uint32_t CM_RGAM_LUT_DATA; - uint32_t CM_RGAM_LUT_WRITE_EN_MASK; - uint32_t CM_RGAM_LUT_INDEX; - uint32_t CM_RGAM_RAMB_START_CNTL_B; - uint32_t CM_RGAM_RAMB_START_CNTL_G; - uint32_t CM_RGAM_RAMB_START_CNTL_R; - uint32_t CM_RGAM_RAMB_SLOPE_CNTL_B; - uint32_t CM_RGAM_RAMB_SLOPE_CNTL_G; - uint32_t CM_RGAM_RAMB_SLOPE_CNTL_R; - uint32_t CM_RGAM_RAMB_END_CNTL1_B; - uint32_t CM_RGAM_RAMB_END_CNTL2_B; - uint32_t CM_RGAM_RAMB_END_CNTL1_G; - uint32_t CM_RGAM_RAMB_END_CNTL2_G; - uint32_t CM_RGAM_RAMB_END_CNTL1_R; - uint32_t CM_RGAM_RAMB_END_CNTL2_R; - uint32_t CM_RGAM_RAMB_REGION_0_1; - uint32_t CM_RGAM_RAMB_REGION_32_33; - uint32_t CM_RGAM_RAMA_START_CNTL_B; - uint32_t CM_RGAM_RAMA_START_CNTL_G; - uint32_t CM_RGAM_RAMA_START_CNTL_R; - uint32_t CM_RGAM_RAMA_SLOPE_CNTL_B; - uint32_t CM_RGAM_RAMA_SLOPE_CNTL_G; - uint32_t CM_RGAM_RAMA_SLOPE_CNTL_R; - uint32_t CM_RGAM_RAMA_END_CNTL1_B; - uint32_t CM_RGAM_RAMA_END_CNTL2_B; - uint32_t CM_RGAM_RAMA_END_CNTL1_G; - uint32_t CM_RGAM_RAMA_END_CNTL2_G; - uint32_t CM_RGAM_RAMA_END_CNTL1_R; - uint32_t CM_RGAM_RAMA_END_CNTL2_R; - uint32_t CM_RGAM_RAMA_REGION_0_1; - uint32_t CM_RGAM_RAMA_REGION_32_33; - uint32_t CM_RGAM_CONTROL; - uint32_t CM_CMOUT_CONTROL; - uint32_t OBUF_CONTROL; - uint32_t CM_BLNDGAM_LUT_WRITE_EN_MASK; - uint32_t CM_BLNDGAM_CONTROL; - uint32_t CM_BLNDGAM_RAMB_START_CNTL_B; - uint32_t CM_BLNDGAM_RAMB_START_CNTL_G; - uint32_t CM_BLNDGAM_RAMB_START_CNTL_R; - uint32_t CM_BLNDGAM_RAMB_SLOPE_CNTL_B; - uint32_t CM_BLNDGAM_RAMB_SLOPE_CNTL_G; - uint32_t CM_BLNDGAM_RAMB_SLOPE_CNTL_R; - uint32_t CM_BLNDGAM_RAMB_END_CNTL1_B; - uint32_t CM_BLNDGAM_RAMB_END_CNTL2_B; - uint32_t CM_BLNDGAM_RAMB_END_CNTL1_G; - uint32_t CM_BLNDGAM_RAMB_END_CNTL2_G; - uint32_t CM_BLNDGAM_RAMB_END_CNTL1_R; - uint32_t CM_BLNDGAM_RAMB_END_CNTL2_R; - uint32_t CM_BLNDGAM_RAMB_REGION_0_1; - uint32_t CM_BLNDGAM_RAMB_REGION_2_3; - uint32_t CM_BLNDGAM_RAMB_REGION_4_5; - uint32_t CM_BLNDGAM_RAMB_REGION_6_7; - uint32_t CM_BLNDGAM_RAMB_REGION_8_9; - uint32_t CM_BLNDGAM_RAMB_REGION_10_11; - uint32_t CM_BLNDGAM_RAMB_REGION_12_13; - uint32_t CM_BLNDGAM_RAMB_REGION_14_15; - uint32_t CM_BLNDGAM_RAMB_REGION_16_17; - uint32_t CM_BLNDGAM_RAMB_REGION_18_19; - uint32_t CM_BLNDGAM_RAMB_REGION_20_21; - uint32_t CM_BLNDGAM_RAMB_REGION_22_23; - uint32_t CM_BLNDGAM_RAMB_REGION_24_25; - uint32_t CM_BLNDGAM_RAMB_REGION_26_27; - uint32_t CM_BLNDGAM_RAMB_REGION_28_29; - uint32_t CM_BLNDGAM_RAMB_REGION_30_31; - uint32_t CM_BLNDGAM_RAMB_REGION_32_33; - uint32_t CM_BLNDGAM_RAMA_START_CNTL_B; - uint32_t CM_BLNDGAM_RAMA_START_CNTL_G; - uint32_t CM_BLNDGAM_RAMA_START_CNTL_R; - uint32_t CM_BLNDGAM_RAMA_SLOPE_CNTL_B; - uint32_t CM_BLNDGAM_RAMA_SLOPE_CNTL_G; - uint32_t CM_BLNDGAM_RAMA_SLOPE_CNTL_R; - uint32_t CM_BLNDGAM_RAMA_END_CNTL1_B; - uint32_t CM_BLNDGAM_RAMA_END_CNTL2_B; - uint32_t CM_BLNDGAM_RAMA_END_CNTL1_G; - uint32_t CM_BLNDGAM_RAMA_END_CNTL2_G; - uint32_t CM_BLNDGAM_RAMA_END_CNTL1_R; - uint32_t CM_BLNDGAM_RAMA_END_CNTL2_R; - uint32_t CM_BLNDGAM_RAMA_REGION_0_1; - uint32_t CM_BLNDGAM_RAMA_REGION_2_3; - uint32_t CM_BLNDGAM_RAMA_REGION_4_5; - uint32_t CM_BLNDGAM_RAMA_REGION_6_7; - uint32_t CM_BLNDGAM_RAMA_REGION_8_9; - uint32_t CM_BLNDGAM_RAMA_REGION_10_11; - uint32_t CM_BLNDGAM_RAMA_REGION_12_13; - uint32_t CM_BLNDGAM_RAMA_REGION_14_15; - uint32_t CM_BLNDGAM_RAMA_REGION_16_17; - uint32_t CM_BLNDGAM_RAMA_REGION_18_19; - uint32_t CM_BLNDGAM_RAMA_REGION_20_21; - uint32_t CM_BLNDGAM_RAMA_REGION_22_23; - uint32_t CM_BLNDGAM_RAMA_REGION_24_25; - uint32_t CM_BLNDGAM_RAMA_REGION_26_27; - uint32_t CM_BLNDGAM_RAMA_REGION_28_29; - uint32_t CM_BLNDGAM_RAMA_REGION_30_31; - uint32_t CM_BLNDGAM_RAMA_REGION_32_33; - uint32_t CM_BLNDGAM_LUT_INDEX; - uint32_t CM_BLNDGAM_LUT_DATA; - uint32_t CM_3DLUT_MODE; - uint32_t CM_3DLUT_INDEX; - uint32_t CM_3DLUT_DATA; - uint32_t CM_3DLUT_DATA_30BIT; - uint32_t CM_3DLUT_READ_WRITE_CONTROL; - uint32_t CM_SHAPER_LUT_WRITE_EN_MASK; - uint32_t CM_SHAPER_CONTROL; - uint32_t CM_SHAPER_RAMB_START_CNTL_B; - uint32_t CM_SHAPER_RAMB_START_CNTL_G; - uint32_t CM_SHAPER_RAMB_START_CNTL_R; - uint32_t CM_SHAPER_RAMB_END_CNTL_B; - uint32_t CM_SHAPER_RAMB_END_CNTL_G; - uint32_t CM_SHAPER_RAMB_END_CNTL_R; - uint32_t CM_SHAPER_RAMB_REGION_0_1; - uint32_t CM_SHAPER_RAMB_REGION_2_3; - uint32_t CM_SHAPER_RAMB_REGION_4_5; - uint32_t CM_SHAPER_RAMB_REGION_6_7; - uint32_t CM_SHAPER_RAMB_REGION_8_9; - uint32_t CM_SHAPER_RAMB_REGION_10_11; - uint32_t CM_SHAPER_RAMB_REGION_12_13; - uint32_t CM_SHAPER_RAMB_REGION_14_15; - uint32_t CM_SHAPER_RAMB_REGION_16_17; - uint32_t CM_SHAPER_RAMB_REGION_18_19; - uint32_t CM_SHAPER_RAMB_REGION_20_21; - uint32_t CM_SHAPER_RAMB_REGION_22_23; - uint32_t CM_SHAPER_RAMB_REGION_24_25; - uint32_t CM_SHAPER_RAMB_REGION_26_27; - uint32_t CM_SHAPER_RAMB_REGION_28_29; - uint32_t CM_SHAPER_RAMB_REGION_30_31; - uint32_t CM_SHAPER_RAMB_REGION_32_33; - uint32_t CM_SHAPER_RAMA_START_CNTL_B; - uint32_t CM_SHAPER_RAMA_START_CNTL_G; - uint32_t CM_SHAPER_RAMA_START_CNTL_R; - uint32_t CM_SHAPER_RAMA_END_CNTL_B; - uint32_t CM_SHAPER_RAMA_END_CNTL_G; - uint32_t CM_SHAPER_RAMA_END_CNTL_R; - uint32_t CM_SHAPER_RAMA_REGION_0_1; - uint32_t CM_SHAPER_RAMA_REGION_2_3; - uint32_t CM_SHAPER_RAMA_REGION_4_5; - uint32_t CM_SHAPER_RAMA_REGION_6_7; - uint32_t CM_SHAPER_RAMA_REGION_8_9; - uint32_t CM_SHAPER_RAMA_REGION_10_11; - uint32_t CM_SHAPER_RAMA_REGION_12_13; - uint32_t CM_SHAPER_RAMA_REGION_14_15; - uint32_t CM_SHAPER_RAMA_REGION_16_17; - uint32_t CM_SHAPER_RAMA_REGION_18_19; - uint32_t CM_SHAPER_RAMA_REGION_20_21; - uint32_t CM_SHAPER_RAMA_REGION_22_23; - uint32_t CM_SHAPER_RAMA_REGION_24_25; - uint32_t CM_SHAPER_RAMA_REGION_26_27; - uint32_t CM_SHAPER_RAMA_REGION_28_29; - uint32_t CM_SHAPER_RAMA_REGION_30_31; - uint32_t CM_SHAPER_RAMA_REGION_32_33; - uint32_t CM_SHAPER_LUT_INDEX; - uint32_t CM_SHAPER_LUT_DATA; - uint32_t CM_ICSC_CONTROL; - uint32_t CM_ICSC_C11_C12; - uint32_t CM_ICSC_C33_C34; - uint32_t CM_DGAM_RAMB_START_CNTL_B; - uint32_t CM_DGAM_RAMB_START_CNTL_G; - uint32_t CM_DGAM_RAMB_START_CNTL_R; - uint32_t CM_DGAM_RAMB_SLOPE_CNTL_B; - uint32_t CM_DGAM_RAMB_SLOPE_CNTL_G; - uint32_t CM_DGAM_RAMB_SLOPE_CNTL_R; - uint32_t CM_DGAM_RAMB_END_CNTL1_B; - uint32_t CM_DGAM_RAMB_END_CNTL2_B; - uint32_t CM_DGAM_RAMB_END_CNTL1_G; - uint32_t CM_DGAM_RAMB_END_CNTL2_G; - uint32_t CM_DGAM_RAMB_END_CNTL1_R; - uint32_t CM_DGAM_RAMB_END_CNTL2_R; - uint32_t CM_DGAM_RAMB_REGION_0_1; - uint32_t CM_DGAM_RAMB_REGION_14_15; - uint32_t CM_DGAM_RAMA_START_CNTL_B; - uint32_t CM_DGAM_RAMA_START_CNTL_G; - uint32_t CM_DGAM_RAMA_START_CNTL_R; - uint32_t CM_DGAM_RAMA_SLOPE_CNTL_B; - uint32_t CM_DGAM_RAMA_SLOPE_CNTL_G; - uint32_t CM_DGAM_RAMA_SLOPE_CNTL_R; - uint32_t CM_DGAM_RAMA_END_CNTL1_B; - uint32_t CM_DGAM_RAMA_END_CNTL2_B; - uint32_t CM_DGAM_RAMA_END_CNTL1_G; - uint32_t CM_DGAM_RAMA_END_CNTL2_G; - uint32_t CM_DGAM_RAMA_END_CNTL1_R; - uint32_t CM_DGAM_RAMA_END_CNTL2_R; - uint32_t CM_DGAM_RAMA_REGION_0_1; - uint32_t CM_DGAM_RAMA_REGION_14_15; - uint32_t CM_DGAM_LUT_WRITE_EN_MASK; - uint32_t CM_DGAM_LUT_INDEX; - uint32_t CM_DGAM_LUT_DATA; - uint32_t CM_CONTROL; - uint32_t CM_DGAM_CONTROL; - uint32_t CM_IGAM_CONTROL; - uint32_t CM_IGAM_LUT_RW_CONTROL; - uint32_t CM_IGAM_LUT_RW_INDEX; - uint32_t CM_IGAM_LUT_SEQ_COLOR; - uint32_t FORMAT_CONTROL; - uint32_t CNVC_SURFACE_PIXEL_FORMAT; - uint32_t CURSOR_CONTROL; - uint32_t CURSOR0_CONTROL; - uint32_t CURSOR0_COLOR0; - uint32_t CURSOR0_COLOR1; + DPP_COMMON_REG_VARIABLE_LIST }; struct dcn10_dpp { @@ -1266,6 +1273,8 @@ struct dcn10_dpp { int lb_memory_size; int lb_bits_per_entry; bool is_write_to_ram_a_safe; + struct scaler_data scl_data; + struct pwl_params pwl_data; }; enum dcn10_input_csc_select { @@ -1274,6 +1283,10 @@ enum dcn10_input_csc_select { INPUT_CSC_SELECT_COMA }; +void dpp1_set_cursor_attributes( + struct dpp *dpp_base, + enum dc_cursor_color_format color_format); + bool dpp1_dscl_is_lb_conf_valid( int ceil_vratio, int num_partitions, @@ -1310,7 +1323,12 @@ void dpp1_power_on_degamma_lut( void dpp1_program_input_csc( struct dpp *dpp_base, enum dc_color_space color_space, - enum dcn10_input_csc_select select); + enum dcn10_input_csc_select select, + const struct out_csc_color_matrix *tbl_entry); + +void dpp1_program_bias_and_scale( + struct dpp *dpp_base, + struct dc_bias_and_scale *params); void dpp1_program_input_lut( struct dpp *dpp_base, @@ -1356,7 +1374,7 @@ void dpp1_cm_program_regamma_lutb_settings( const struct pwl_params *params); void dpp1_cm_set_output_csc_adjustment( struct dpp *dpp_base, - const struct out_csc_color_matrix *tbl_entry); + const uint16_t *regval); void dpp1_cm_set_output_csc_default( struct dpp *dpp_base, @@ -1372,8 +1390,10 @@ void dpp1_dscl_set_scaler_manual_scale( void dpp1_cnv_setup ( struct dpp *dpp_base, - enum surface_pixel_format input_format, - enum expansion_mode mode); + enum surface_pixel_format format, + enum expansion_mode mode, + struct csc_transform input_csc_color_matrix, + enum dc_color_space input_color_space); void dpp1_full_bypass(struct dpp *dpp_base); diff --git a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_dpp_cm.c b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_dpp_cm.c index ed1216b53465..a5b099023652 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_dpp_cm.c +++ b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_dpp_cm.c @@ -49,6 +49,8 @@ #define FN(reg_name, field_name) \ dpp->tf_shift->field_name, dpp->tf_mask->field_name +#define NUM_ELEMENTS(a) (sizeof(a) / sizeof((a)[0])) + struct dcn10_input_csc_matrix { enum dc_color_space color_space; uint16_t regval[12]; @@ -117,8 +119,6 @@ static const struct dcn10_input_csc_matrix dcn10_input_csc_matrix[] = { 0x2568, 0x43ee, 0xdbb2} } }; - - static void program_gamut_remap( struct dcn10_dpp *dpp, const uint16_t *regval, @@ -223,82 +223,20 @@ void dpp1_cm_set_gamut_remap( } } -void dpp1_cm_set_output_csc_default( - struct dpp *dpp_base, - enum dc_color_space colorspace) -{ - - struct dcn10_dpp *dpp = TO_DCN10_DPP(dpp_base); - uint32_t ocsc_mode = 0; - - switch (colorspace) { - case COLOR_SPACE_SRGB: - case COLOR_SPACE_2020_RGB_FULLRANGE: - ocsc_mode = 0; - break; - case COLOR_SPACE_SRGB_LIMITED: - case COLOR_SPACE_2020_RGB_LIMITEDRANGE: - ocsc_mode = 1; - break; - case COLOR_SPACE_YCBCR601: - case COLOR_SPACE_YCBCR601_LIMITED: - ocsc_mode = 2; - break; - case COLOR_SPACE_YCBCR709: - case COLOR_SPACE_YCBCR709_LIMITED: - case COLOR_SPACE_2020_YCBCR: - ocsc_mode = 3; - break; - case COLOR_SPACE_UNKNOWN: - default: - break; - } - - REG_SET(CM_OCSC_CONTROL, 0, CM_OCSC_MODE, ocsc_mode); - -} - -static void dpp1_cm_get_reg_field( - struct dcn10_dpp *dpp, - struct xfer_func_reg *reg) -{ - reg->shifts.exp_region0_lut_offset = dpp->tf_shift->CM_RGAM_RAMA_EXP_REGION0_LUT_OFFSET; - reg->masks.exp_region0_lut_offset = dpp->tf_mask->CM_RGAM_RAMA_EXP_REGION0_LUT_OFFSET; - reg->shifts.exp_region0_num_segments = dpp->tf_shift->CM_RGAM_RAMA_EXP_REGION0_NUM_SEGMENTS; - reg->masks.exp_region0_num_segments = dpp->tf_mask->CM_RGAM_RAMA_EXP_REGION0_NUM_SEGMENTS; - reg->shifts.exp_region1_lut_offset = dpp->tf_shift->CM_RGAM_RAMA_EXP_REGION1_LUT_OFFSET; - reg->masks.exp_region1_lut_offset = dpp->tf_mask->CM_RGAM_RAMA_EXP_REGION1_LUT_OFFSET; - reg->shifts.exp_region1_num_segments = dpp->tf_shift->CM_RGAM_RAMA_EXP_REGION1_NUM_SEGMENTS; - reg->masks.exp_region1_num_segments = dpp->tf_mask->CM_RGAM_RAMA_EXP_REGION1_NUM_SEGMENTS; - - reg->shifts.field_region_end = dpp->tf_shift->CM_RGAM_RAMB_EXP_REGION_END_B; - reg->masks.field_region_end = dpp->tf_mask->CM_RGAM_RAMB_EXP_REGION_END_B; - reg->shifts.field_region_end_slope = dpp->tf_shift->CM_RGAM_RAMB_EXP_REGION_END_SLOPE_B; - reg->masks.field_region_end_slope = dpp->tf_mask->CM_RGAM_RAMB_EXP_REGION_END_SLOPE_B; - reg->shifts.field_region_end_base = dpp->tf_shift->CM_RGAM_RAMB_EXP_REGION_END_BASE_B; - reg->masks.field_region_end_base = dpp->tf_mask->CM_RGAM_RAMB_EXP_REGION_END_BASE_B; - reg->shifts.field_region_linear_slope = dpp->tf_shift->CM_RGAM_RAMB_EXP_REGION_LINEAR_SLOPE_B; - reg->masks.field_region_linear_slope = dpp->tf_mask->CM_RGAM_RAMB_EXP_REGION_LINEAR_SLOPE_B; - reg->shifts.exp_region_start = dpp->tf_shift->CM_RGAM_RAMB_EXP_REGION_START_B; - reg->masks.exp_region_start = dpp->tf_mask->CM_RGAM_RAMB_EXP_REGION_START_B; - reg->shifts.exp_resion_start_segment = dpp->tf_shift->CM_RGAM_RAMB_EXP_REGION_START_SEGMENT_B; - reg->masks.exp_resion_start_segment = dpp->tf_mask->CM_RGAM_RAMB_EXP_REGION_START_SEGMENT_B; -} - static void dpp1_cm_program_color_matrix( struct dcn10_dpp *dpp, - const struct out_csc_color_matrix *tbl_entry) + const uint16_t *regval) { uint32_t mode; struct color_matrices_reg gam_regs; REG_GET(CM_OCSC_CONTROL, CM_OCSC_MODE, &mode); - if (tbl_entry == NULL) { + if (regval == NULL) { BREAK_TO_DEBUGGER(); return; } - + mode = 4; gam_regs.shifts.csc_c11 = dpp->tf_shift->CM_OCSC_C11; gam_regs.masks.csc_c11 = dpp->tf_mask->CM_OCSC_C11; gam_regs.shifts.csc_c12 = dpp->tf_shift->CM_OCSC_C12; @@ -311,7 +249,7 @@ static void dpp1_cm_program_color_matrix( cm_helper_program_color_matrices( dpp->base.ctx, - tbl_entry->regval, + regval, &gam_regs); } else { @@ -321,78 +259,91 @@ static void dpp1_cm_program_color_matrix( cm_helper_program_color_matrices( dpp->base.ctx, - tbl_entry->regval, + regval, &gam_regs); } } -void dpp1_cm_set_output_csc_adjustment( +void dpp1_cm_set_output_csc_default( struct dpp *dpp_base, - const struct out_csc_color_matrix *tbl_entry) + enum dc_color_space colorspace) { struct dcn10_dpp *dpp = TO_DCN10_DPP(dpp_base); - //enum csc_color_mode config = CSC_COLOR_MODE_GRAPHICS_OUTPUT_CSC; + const uint16_t *regval = NULL; + int arr_size; uint32_t ocsc_mode = 4; - /** - *if (tbl_entry != NULL) { - * switch (tbl_entry->color_space) { - * case COLOR_SPACE_SRGB: - * case COLOR_SPACE_2020_RGB_FULLRANGE: - * ocsc_mode = 0; - * break; - * case COLOR_SPACE_SRGB_LIMITED: - * case COLOR_SPACE_2020_RGB_LIMITEDRANGE: - * ocsc_mode = 1; - * break; - * case COLOR_SPACE_YCBCR601: - * case COLOR_SPACE_YCBCR601_LIMITED: - * ocsc_mode = 2; - * break; - * case COLOR_SPACE_YCBCR709: - * case COLOR_SPACE_YCBCR709_LIMITED: - * case COLOR_SPACE_2020_YCBCR: - * ocsc_mode = 3; - * break; - * case COLOR_SPACE_UNKNOWN: - * default: - * break; - * } - *} - */ + regval = find_color_matrix(colorspace, &arr_size); + if (regval == NULL) { + BREAK_TO_DEBUGGER(); + return; + } + dpp1_cm_program_color_matrix(dpp, regval); + REG_SET(CM_OCSC_CONTROL, 0, CM_OCSC_MODE, ocsc_mode); +} + +static void dpp1_cm_get_reg_field( + struct dcn10_dpp *dpp, + struct xfer_func_reg *reg) +{ + reg->shifts.exp_region0_lut_offset = dpp->tf_shift->CM_RGAM_RAMA_EXP_REGION0_LUT_OFFSET; + reg->masks.exp_region0_lut_offset = dpp->tf_mask->CM_RGAM_RAMA_EXP_REGION0_LUT_OFFSET; + reg->shifts.exp_region0_num_segments = dpp->tf_shift->CM_RGAM_RAMA_EXP_REGION0_NUM_SEGMENTS; + reg->masks.exp_region0_num_segments = dpp->tf_mask->CM_RGAM_RAMA_EXP_REGION0_NUM_SEGMENTS; + reg->shifts.exp_region1_lut_offset = dpp->tf_shift->CM_RGAM_RAMA_EXP_REGION1_LUT_OFFSET; + reg->masks.exp_region1_lut_offset = dpp->tf_mask->CM_RGAM_RAMA_EXP_REGION1_LUT_OFFSET; + reg->shifts.exp_region1_num_segments = dpp->tf_shift->CM_RGAM_RAMA_EXP_REGION1_NUM_SEGMENTS; + reg->masks.exp_region1_num_segments = dpp->tf_mask->CM_RGAM_RAMA_EXP_REGION1_NUM_SEGMENTS; + + reg->shifts.field_region_end = dpp->tf_shift->CM_RGAM_RAMB_EXP_REGION_END_B; + reg->masks.field_region_end = dpp->tf_mask->CM_RGAM_RAMB_EXP_REGION_END_B; + reg->shifts.field_region_end_slope = dpp->tf_shift->CM_RGAM_RAMB_EXP_REGION_END_SLOPE_B; + reg->masks.field_region_end_slope = dpp->tf_mask->CM_RGAM_RAMB_EXP_REGION_END_SLOPE_B; + reg->shifts.field_region_end_base = dpp->tf_shift->CM_RGAM_RAMB_EXP_REGION_END_BASE_B; + reg->masks.field_region_end_base = dpp->tf_mask->CM_RGAM_RAMB_EXP_REGION_END_BASE_B; + reg->shifts.field_region_linear_slope = dpp->tf_shift->CM_RGAM_RAMB_EXP_REGION_LINEAR_SLOPE_B; + reg->masks.field_region_linear_slope = dpp->tf_mask->CM_RGAM_RAMB_EXP_REGION_LINEAR_SLOPE_B; + reg->shifts.exp_region_start = dpp->tf_shift->CM_RGAM_RAMB_EXP_REGION_START_B; + reg->masks.exp_region_start = dpp->tf_mask->CM_RGAM_RAMB_EXP_REGION_START_B; + reg->shifts.exp_resion_start_segment = dpp->tf_shift->CM_RGAM_RAMB_EXP_REGION_START_SEGMENT_B; + reg->masks.exp_resion_start_segment = dpp->tf_mask->CM_RGAM_RAMB_EXP_REGION_START_SEGMENT_B; +} +void dpp1_cm_set_output_csc_adjustment( + struct dpp *dpp_base, + const uint16_t *regval) +{ + struct dcn10_dpp *dpp = TO_DCN10_DPP(dpp_base); + uint32_t ocsc_mode = 4; + dpp1_cm_program_color_matrix(dpp, regval); REG_SET(CM_OCSC_CONTROL, 0, CM_OCSC_MODE, ocsc_mode); - dpp1_cm_program_color_matrix(dpp, tbl_entry); } -void dpp1_cm_power_on_regamma_lut( - struct dpp *dpp_base, - bool power_on) +void dpp1_cm_power_on_regamma_lut(struct dpp *dpp_base, + bool power_on) { struct dcn10_dpp *dpp = TO_DCN10_DPP(dpp_base); + REG_SET(CM_MEM_PWR_CTRL, 0, - RGAM_MEM_PWR_FORCE, power_on == true ? 0:1); + RGAM_MEM_PWR_FORCE, power_on == true ? 0:1); } -void dpp1_cm_program_regamma_lut( - struct dpp *dpp_base, - const struct pwl_result_data *rgb, - uint32_t num) +void dpp1_cm_program_regamma_lut(struct dpp *dpp_base, + const struct pwl_result_data *rgb, + uint32_t num) { uint32_t i; struct dcn10_dpp *dpp = TO_DCN10_DPP(dpp_base); + for (i = 0 ; i < num; i++) { REG_SET(CM_RGAM_LUT_DATA, 0, CM_RGAM_LUT_DATA, rgb[i].red_reg); REG_SET(CM_RGAM_LUT_DATA, 0, CM_RGAM_LUT_DATA, rgb[i].green_reg); REG_SET(CM_RGAM_LUT_DATA, 0, CM_RGAM_LUT_DATA, rgb[i].blue_reg); - REG_SET(CM_RGAM_LUT_DATA, 0, - CM_RGAM_LUT_DATA, rgb[i].delta_red_reg); - REG_SET(CM_RGAM_LUT_DATA, 0, - CM_RGAM_LUT_DATA, rgb[i].delta_green_reg); - REG_SET(CM_RGAM_LUT_DATA, 0, - CM_RGAM_LUT_DATA, rgb[i].delta_blue_reg); + REG_SET(CM_RGAM_LUT_DATA, 0, CM_RGAM_LUT_DATA, rgb[i].delta_red_reg); + REG_SET(CM_RGAM_LUT_DATA, 0, CM_RGAM_LUT_DATA, rgb[i].delta_green_reg); + REG_SET(CM_RGAM_LUT_DATA, 0, CM_RGAM_LUT_DATA, rgb[i].delta_blue_reg); } @@ -471,7 +422,8 @@ void dpp1_cm_program_regamma_lutb_settings( void dpp1_program_input_csc( struct dpp *dpp_base, enum dc_color_space color_space, - enum dcn10_input_csc_select select) + enum dcn10_input_csc_select select, + const struct out_csc_color_matrix *tbl_entry) { struct dcn10_dpp *dpp = TO_DCN10_DPP(dpp_base); int i; @@ -485,15 +437,19 @@ void dpp1_program_input_csc( return; } - for (i = 0; i < arr_size; i++) - if (dcn10_input_csc_matrix[i].color_space == color_space) { - regval = dcn10_input_csc_matrix[i].regval; - break; + if (tbl_entry == NULL) { + for (i = 0; i < arr_size; i++) + if (dcn10_input_csc_matrix[i].color_space == color_space) { + regval = dcn10_input_csc_matrix[i].regval; + break; + } + + if (regval == NULL) { + BREAK_TO_DEBUGGER(); + return; } - - if (regval == NULL) { - BREAK_TO_DEBUGGER(); - return; + } else { + regval = tbl_entry->regval; } if (select == INPUT_CSC_SELECT_COMA) @@ -528,6 +484,27 @@ void dpp1_program_input_csc( } } +//keep here for now, decide multi dce support later +void dpp1_program_bias_and_scale( + struct dpp *dpp_base, + struct dc_bias_and_scale *params) +{ + struct dcn10_dpp *dpp = TO_DCN10_DPP(dpp_base); + + REG_SET_2(CM_BNS_VALUES_R, 0, + CM_BNS_SCALE_R, params->scale_red, + CM_BNS_BIAS_R, params->bias_red); + + REG_SET_2(CM_BNS_VALUES_G, 0, + CM_BNS_SCALE_G, params->scale_green, + CM_BNS_BIAS_G, params->bias_green); + + REG_SET_2(CM_BNS_VALUES_B, 0, + CM_BNS_SCALE_B, params->scale_blue, + CM_BNS_BIAS_B, params->bias_blue); + +} + /*program de gamma RAM B*/ void dpp1_program_degamma_lutb_settings( struct dpp *dpp_base, diff --git a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_dpp_dscl.c b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_dpp_dscl.c index cbad36410b32..3eb824debf43 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_dpp_dscl.c +++ b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_dpp_dscl.c @@ -648,6 +648,13 @@ void dpp1_dscl_set_scaler_manual_scale( bool ycbcr = scl_data->format >= PIXEL_FORMAT_VIDEO_BEGIN && scl_data->format <= PIXEL_FORMAT_VIDEO_END; + if (memcmp(&dpp->scl_data, scl_data, sizeof(*scl_data)) == 0) + return; + + PERF_TRACE(); + + dpp->scl_data = *scl_data; + /* Recout */ dpp1_dscl_set_recout(dpp, &scl_data->recout); @@ -699,4 +706,5 @@ void dpp1_dscl_set_scaler_manual_scale( SCL_H_NUM_TAPS_C, scl_data->taps.h_taps_c - 1); dpp1_dscl_set_scl_filter(dpp, scl_data, ycbcr); + PERF_TRACE(); } diff --git a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hubbub.c b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hubbub.c new file mode 100644 index 000000000000..eb8317187f30 --- /dev/null +++ b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hubbub.c @@ -0,0 +1,516 @@ +/* + * Copyright 2016 Advanced Micro Devices, Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + * + * Authors: AMD + * + */ + +#include "dm_services.h" +#include "dcn10_hubp.h" +#include "dcn10_hubbub.h" +#include "reg_helper.h" + +#define CTX \ + hubbub->ctx +#define REG(reg)\ + hubbub->regs->reg + +#undef FN +#define FN(reg_name, field_name) \ + hubbub->shifts->field_name, hubbub->masks->field_name + +void hubbub1_wm_read_state(struct hubbub *hubbub, + struct dcn_hubbub_wm *wm) +{ + struct dcn_hubbub_wm_set *s; + + memset(wm, 0, sizeof(struct dcn_hubbub_wm)); + + s = &wm->sets[0]; + s->wm_set = 0; + s->data_urgent = REG_READ(DCHUBBUB_ARB_DATA_URGENCY_WATERMARK_A); + s->pte_meta_urgent = REG_READ(DCHUBBUB_ARB_PTE_META_URGENCY_WATERMARK_A); + if (REG(DCHUBBUB_ARB_ALLOW_SR_ENTER_WATERMARK_A)) { + s->sr_enter = REG_READ(DCHUBBUB_ARB_ALLOW_SR_ENTER_WATERMARK_A); + s->sr_exit = REG_READ(DCHUBBUB_ARB_ALLOW_SR_EXIT_WATERMARK_A); + } + s->dram_clk_chanage = REG_READ(DCHUBBUB_ARB_ALLOW_DRAM_CLK_CHANGE_WATERMARK_A); + + s = &wm->sets[1]; + s->wm_set = 1; + s->data_urgent = REG_READ(DCHUBBUB_ARB_DATA_URGENCY_WATERMARK_B); + s->pte_meta_urgent = REG_READ(DCHUBBUB_ARB_PTE_META_URGENCY_WATERMARK_B); + if (REG(DCHUBBUB_ARB_ALLOW_SR_ENTER_WATERMARK_B)) { + s->sr_enter = REG_READ(DCHUBBUB_ARB_ALLOW_SR_ENTER_WATERMARK_B); + s->sr_exit = REG_READ(DCHUBBUB_ARB_ALLOW_SR_EXIT_WATERMARK_B); + } + s->dram_clk_chanage = REG_READ(DCHUBBUB_ARB_ALLOW_DRAM_CLK_CHANGE_WATERMARK_B); + + s = &wm->sets[2]; + s->wm_set = 2; + s->data_urgent = REG_READ(DCHUBBUB_ARB_DATA_URGENCY_WATERMARK_C); + s->pte_meta_urgent = REG_READ(DCHUBBUB_ARB_PTE_META_URGENCY_WATERMARK_C); + if (REG(DCHUBBUB_ARB_ALLOW_SR_ENTER_WATERMARK_C)) { + s->sr_enter = REG_READ(DCHUBBUB_ARB_ALLOW_SR_ENTER_WATERMARK_C); + s->sr_exit = REG_READ(DCHUBBUB_ARB_ALLOW_SR_EXIT_WATERMARK_C); + } + s->dram_clk_chanage = REG_READ(DCHUBBUB_ARB_ALLOW_DRAM_CLK_CHANGE_WATERMARK_C); + + s = &wm->sets[3]; + s->wm_set = 3; + s->data_urgent = REG_READ(DCHUBBUB_ARB_DATA_URGENCY_WATERMARK_D); + s->pte_meta_urgent = REG_READ(DCHUBBUB_ARB_PTE_META_URGENCY_WATERMARK_D); + if (REG(DCHUBBUB_ARB_ALLOW_SR_ENTER_WATERMARK_D)) { + s->sr_enter = REG_READ(DCHUBBUB_ARB_ALLOW_SR_ENTER_WATERMARK_D); + s->sr_exit = REG_READ(DCHUBBUB_ARB_ALLOW_SR_EXIT_WATERMARK_D); + } + s->dram_clk_chanage = REG_READ(DCHUBBUB_ARB_ALLOW_DRAM_CLK_CHANGE_WATERMARK_D); +} + +bool hubbub1_verify_allow_pstate_change_high( + struct hubbub *hubbub) +{ + /* pstate latency is ~20us so if we wait over 40us and pstate allow + * still not asserted, we are probably stuck and going to hang + * + * TODO: Figure out why it takes ~100us on linux + * pstate takes around ~100us on linux. Unknown currently as to + * why it takes that long on linux + */ + static unsigned int pstate_wait_timeout_us = 200; + static unsigned int pstate_wait_expected_timeout_us = 40; + static unsigned int max_sampled_pstate_wait_us; /* data collection */ + static bool forced_pstate_allow; /* help with revert wa */ + + unsigned int debug_index = 0x7; + unsigned int debug_data; + unsigned int i; + + if (forced_pstate_allow) { + /* we hacked to force pstate allow to prevent hang last time + * we verify_allow_pstate_change_high. so disable force + * here so we can check status + */ + REG_UPDATE_2(DCHUBBUB_ARB_DRAM_STATE_CNTL, + DCHUBBUB_ARB_ALLOW_PSTATE_CHANGE_FORCE_VALUE, 0, + DCHUBBUB_ARB_ALLOW_PSTATE_CHANGE_FORCE_ENABLE, 0); + forced_pstate_allow = false; + } + + /* description "3-0: Pipe0 cursor0 QOS + * 7-4: Pipe1 cursor0 QOS + * 11-8: Pipe2 cursor0 QOS + * 15-12: Pipe3 cursor0 QOS + * 16: Pipe0 Plane0 Allow Pstate Change + * 17: Pipe1 Plane0 Allow Pstate Change + * 18: Pipe2 Plane0 Allow Pstate Change + * 19: Pipe3 Plane0 Allow Pstate Change + * 20: Pipe0 Plane1 Allow Pstate Change + * 21: Pipe1 Plane1 Allow Pstate Change + * 22: Pipe2 Plane1 Allow Pstate Change + * 23: Pipe3 Plane1 Allow Pstate Change + * 24: Pipe0 cursor0 Allow Pstate Change + * 25: Pipe1 cursor0 Allow Pstate Change + * 26: Pipe2 cursor0 Allow Pstate Change + * 27: Pipe3 cursor0 Allow Pstate Change + * 28: WB0 Allow Pstate Change + * 29: WB1 Allow Pstate Change + * 30: Arbiter's allow_pstate_change + * 31: SOC pstate change request + */ + + REG_WRITE(DCHUBBUB_TEST_DEBUG_INDEX, debug_index); + + for (i = 0; i < pstate_wait_timeout_us; i++) { + debug_data = REG_READ(DCHUBBUB_TEST_DEBUG_DATA); + + if (debug_data & (1 << 30)) { + + if (i > pstate_wait_expected_timeout_us) + dm_logger_write(hubbub->ctx->logger, LOG_WARNING, + "pstate took longer than expected ~%dus\n", + i); + + return true; + } + if (max_sampled_pstate_wait_us < i) + max_sampled_pstate_wait_us = i; + + udelay(1); + } + + /* force pstate allow to prevent system hang + * and break to debugger to investigate + */ + REG_UPDATE_2(DCHUBBUB_ARB_DRAM_STATE_CNTL, + DCHUBBUB_ARB_ALLOW_PSTATE_CHANGE_FORCE_VALUE, 1, + DCHUBBUB_ARB_ALLOW_PSTATE_CHANGE_FORCE_ENABLE, 1); + forced_pstate_allow = true; + + dm_logger_write(hubbub->ctx->logger, LOG_WARNING, + "pstate TEST_DEBUG_DATA: 0x%X\n", + debug_data); + + return false; +} + +static uint32_t convert_and_clamp( + uint32_t wm_ns, + uint32_t refclk_mhz, + uint32_t clamp_value) +{ + uint32_t ret_val = 0; + ret_val = wm_ns * refclk_mhz; + ret_val /= 1000; + + if (ret_val > clamp_value) + ret_val = clamp_value; + + return ret_val; +} + + +void hubbub1_program_watermarks( + struct hubbub *hubbub, + struct dcn_watermark_set *watermarks, + unsigned int refclk_mhz) +{ + uint32_t force_en = hubbub->ctx->dc->debug.disable_stutter ? 1 : 0; + /* + * Need to clamp to max of the register values (i.e. no wrap) + * for dcn1, all wm registers are 21-bit wide + */ + uint32_t prog_wm_value; + + REG_UPDATE(DCHUBBUB_ARB_WATERMARK_CHANGE_CNTL, + DCHUBBUB_ARB_WATERMARK_CHANGE_REQUEST, 0); + + /* Repeat for water mark set A, B, C and D. */ + /* clock state A */ + prog_wm_value = convert_and_clamp(watermarks->a.urgent_ns, + refclk_mhz, 0x1fffff); + REG_WRITE(DCHUBBUB_ARB_DATA_URGENCY_WATERMARK_A, prog_wm_value); + + dm_logger_write(hubbub->ctx->logger, LOG_BANDWIDTH_CALCS, + "URGENCY_WATERMARK_A calculated =%d\n" + "HW register value = 0x%x\n", + watermarks->a.urgent_ns, prog_wm_value); + + prog_wm_value = convert_and_clamp(watermarks->a.pte_meta_urgent_ns, + refclk_mhz, 0x1fffff); + REG_WRITE(DCHUBBUB_ARB_PTE_META_URGENCY_WATERMARK_A, prog_wm_value); + dm_logger_write(hubbub->ctx->logger, LOG_BANDWIDTH_CALCS, + "PTE_META_URGENCY_WATERMARK_A calculated =%d\n" + "HW register value = 0x%x\n", + watermarks->a.pte_meta_urgent_ns, prog_wm_value); + + if (REG(DCHUBBUB_ARB_ALLOW_SR_ENTER_WATERMARK_A)) { + prog_wm_value = convert_and_clamp( + watermarks->a.cstate_pstate.cstate_enter_plus_exit_ns, + refclk_mhz, 0x1fffff); + REG_WRITE(DCHUBBUB_ARB_ALLOW_SR_ENTER_WATERMARK_A, prog_wm_value); + dm_logger_write(hubbub->ctx->logger, LOG_BANDWIDTH_CALCS, + "SR_ENTER_EXIT_WATERMARK_A calculated =%d\n" + "HW register value = 0x%x\n", + watermarks->a.cstate_pstate.cstate_enter_plus_exit_ns, prog_wm_value); + + + prog_wm_value = convert_and_clamp( + watermarks->a.cstate_pstate.cstate_exit_ns, + refclk_mhz, 0x1fffff); + REG_WRITE(DCHUBBUB_ARB_ALLOW_SR_EXIT_WATERMARK_A, prog_wm_value); + dm_logger_write(hubbub->ctx->logger, LOG_BANDWIDTH_CALCS, + "SR_EXIT_WATERMARK_A calculated =%d\n" + "HW register value = 0x%x\n", + watermarks->a.cstate_pstate.cstate_exit_ns, prog_wm_value); + } + + prog_wm_value = convert_and_clamp( + watermarks->a.cstate_pstate.pstate_change_ns, + refclk_mhz, 0x1fffff); + REG_WRITE(DCHUBBUB_ARB_ALLOW_DRAM_CLK_CHANGE_WATERMARK_A, prog_wm_value); + dm_logger_write(hubbub->ctx->logger, LOG_BANDWIDTH_CALCS, + "DRAM_CLK_CHANGE_WATERMARK_A calculated =%d\n" + "HW register value = 0x%x\n\n", + watermarks->a.cstate_pstate.pstate_change_ns, prog_wm_value); + + + /* clock state B */ + prog_wm_value = convert_and_clamp( + watermarks->b.urgent_ns, refclk_mhz, 0x1fffff); + REG_WRITE(DCHUBBUB_ARB_DATA_URGENCY_WATERMARK_B, prog_wm_value); + dm_logger_write(hubbub->ctx->logger, LOG_BANDWIDTH_CALCS, + "URGENCY_WATERMARK_B calculated =%d\n" + "HW register value = 0x%x\n", + watermarks->b.urgent_ns, prog_wm_value); + + + prog_wm_value = convert_and_clamp( + watermarks->b.pte_meta_urgent_ns, + refclk_mhz, 0x1fffff); + REG_WRITE(DCHUBBUB_ARB_PTE_META_URGENCY_WATERMARK_B, prog_wm_value); + dm_logger_write(hubbub->ctx->logger, LOG_BANDWIDTH_CALCS, + "PTE_META_URGENCY_WATERMARK_B calculated =%d\n" + "HW register value = 0x%x\n", + watermarks->b.pte_meta_urgent_ns, prog_wm_value); + + + if (REG(DCHUBBUB_ARB_ALLOW_SR_ENTER_WATERMARK_B)) { + prog_wm_value = convert_and_clamp( + watermarks->b.cstate_pstate.cstate_enter_plus_exit_ns, + refclk_mhz, 0x1fffff); + REG_WRITE(DCHUBBUB_ARB_ALLOW_SR_ENTER_WATERMARK_B, prog_wm_value); + dm_logger_write(hubbub->ctx->logger, LOG_BANDWIDTH_CALCS, + "SR_ENTER_WATERMARK_B calculated =%d\n" + "HW register value = 0x%x\n", + watermarks->b.cstate_pstate.cstate_enter_plus_exit_ns, prog_wm_value); + + + prog_wm_value = convert_and_clamp( + watermarks->b.cstate_pstate.cstate_exit_ns, + refclk_mhz, 0x1fffff); + REG_WRITE(DCHUBBUB_ARB_ALLOW_SR_EXIT_WATERMARK_B, prog_wm_value); + dm_logger_write(hubbub->ctx->logger, LOG_BANDWIDTH_CALCS, + "SR_EXIT_WATERMARK_B calculated =%d\n" + "HW register value = 0x%x\n", + watermarks->b.cstate_pstate.cstate_exit_ns, prog_wm_value); + } + + prog_wm_value = convert_and_clamp( + watermarks->b.cstate_pstate.pstate_change_ns, + refclk_mhz, 0x1fffff); + REG_WRITE(DCHUBBUB_ARB_ALLOW_DRAM_CLK_CHANGE_WATERMARK_B, prog_wm_value); + dm_logger_write(hubbub->ctx->logger, LOG_BANDWIDTH_CALCS, + "DRAM_CLK_CHANGE_WATERMARK_B calculated =%d\n\n" + "HW register value = 0x%x\n", + watermarks->b.cstate_pstate.pstate_change_ns, prog_wm_value); + + /* clock state C */ + prog_wm_value = convert_and_clamp( + watermarks->c.urgent_ns, refclk_mhz, 0x1fffff); + REG_WRITE(DCHUBBUB_ARB_DATA_URGENCY_WATERMARK_C, prog_wm_value); + dm_logger_write(hubbub->ctx->logger, LOG_BANDWIDTH_CALCS, + "URGENCY_WATERMARK_C calculated =%d\n" + "HW register value = 0x%x\n", + watermarks->c.urgent_ns, prog_wm_value); + + + prog_wm_value = convert_and_clamp( + watermarks->c.pte_meta_urgent_ns, + refclk_mhz, 0x1fffff); + REG_WRITE(DCHUBBUB_ARB_PTE_META_URGENCY_WATERMARK_C, prog_wm_value); + dm_logger_write(hubbub->ctx->logger, LOG_BANDWIDTH_CALCS, + "PTE_META_URGENCY_WATERMARK_C calculated =%d\n" + "HW register value = 0x%x\n", + watermarks->c.pte_meta_urgent_ns, prog_wm_value); + + + if (REG(DCHUBBUB_ARB_ALLOW_SR_ENTER_WATERMARK_C)) { + prog_wm_value = convert_and_clamp( + watermarks->c.cstate_pstate.cstate_enter_plus_exit_ns, + refclk_mhz, 0x1fffff); + REG_WRITE(DCHUBBUB_ARB_ALLOW_SR_ENTER_WATERMARK_C, prog_wm_value); + dm_logger_write(hubbub->ctx->logger, LOG_BANDWIDTH_CALCS, + "SR_ENTER_WATERMARK_C calculated =%d\n" + "HW register value = 0x%x\n", + watermarks->c.cstate_pstate.cstate_enter_plus_exit_ns, prog_wm_value); + + + prog_wm_value = convert_and_clamp( + watermarks->c.cstate_pstate.cstate_exit_ns, + refclk_mhz, 0x1fffff); + REG_WRITE(DCHUBBUB_ARB_ALLOW_SR_EXIT_WATERMARK_C, prog_wm_value); + dm_logger_write(hubbub->ctx->logger, LOG_BANDWIDTH_CALCS, + "SR_EXIT_WATERMARK_C calculated =%d\n" + "HW register value = 0x%x\n", + watermarks->c.cstate_pstate.cstate_exit_ns, prog_wm_value); + } + + prog_wm_value = convert_and_clamp( + watermarks->c.cstate_pstate.pstate_change_ns, + refclk_mhz, 0x1fffff); + REG_WRITE(DCHUBBUB_ARB_ALLOW_DRAM_CLK_CHANGE_WATERMARK_C, prog_wm_value); + dm_logger_write(hubbub->ctx->logger, LOG_BANDWIDTH_CALCS, + "DRAM_CLK_CHANGE_WATERMARK_C calculated =%d\n\n" + "HW register value = 0x%x\n", + watermarks->c.cstate_pstate.pstate_change_ns, prog_wm_value); + + /* clock state D */ + prog_wm_value = convert_and_clamp( + watermarks->d.urgent_ns, refclk_mhz, 0x1fffff); + REG_WRITE(DCHUBBUB_ARB_DATA_URGENCY_WATERMARK_D, prog_wm_value); + dm_logger_write(hubbub->ctx->logger, LOG_BANDWIDTH_CALCS, + "URGENCY_WATERMARK_D calculated =%d\n" + "HW register value = 0x%x\n", + watermarks->d.urgent_ns, prog_wm_value); + + prog_wm_value = convert_and_clamp( + watermarks->d.pte_meta_urgent_ns, + refclk_mhz, 0x1fffff); + REG_WRITE(DCHUBBUB_ARB_PTE_META_URGENCY_WATERMARK_D, prog_wm_value); + dm_logger_write(hubbub->ctx->logger, LOG_BANDWIDTH_CALCS, + "PTE_META_URGENCY_WATERMARK_D calculated =%d\n" + "HW register value = 0x%x\n", + watermarks->d.pte_meta_urgent_ns, prog_wm_value); + + + if (REG(DCHUBBUB_ARB_ALLOW_SR_ENTER_WATERMARK_D)) { + prog_wm_value = convert_and_clamp( + watermarks->d.cstate_pstate.cstate_enter_plus_exit_ns, + refclk_mhz, 0x1fffff); + REG_WRITE(DCHUBBUB_ARB_ALLOW_SR_ENTER_WATERMARK_D, prog_wm_value); + dm_logger_write(hubbub->ctx->logger, LOG_BANDWIDTH_CALCS, + "SR_ENTER_WATERMARK_D calculated =%d\n" + "HW register value = 0x%x\n", + watermarks->d.cstate_pstate.cstate_enter_plus_exit_ns, prog_wm_value); + + + prog_wm_value = convert_and_clamp( + watermarks->d.cstate_pstate.cstate_exit_ns, + refclk_mhz, 0x1fffff); + REG_WRITE(DCHUBBUB_ARB_ALLOW_SR_EXIT_WATERMARK_D, prog_wm_value); + dm_logger_write(hubbub->ctx->logger, LOG_BANDWIDTH_CALCS, + "SR_EXIT_WATERMARK_D calculated =%d\n" + "HW register value = 0x%x\n", + watermarks->d.cstate_pstate.cstate_exit_ns, prog_wm_value); + } + + + prog_wm_value = convert_and_clamp( + watermarks->d.cstate_pstate.pstate_change_ns, + refclk_mhz, 0x1fffff); + REG_WRITE(DCHUBBUB_ARB_ALLOW_DRAM_CLK_CHANGE_WATERMARK_D, prog_wm_value); + dm_logger_write(hubbub->ctx->logger, LOG_BANDWIDTH_CALCS, + "DRAM_CLK_CHANGE_WATERMARK_D calculated =%d\n" + "HW register value = 0x%x\n\n", + watermarks->d.cstate_pstate.pstate_change_ns, prog_wm_value); + + REG_UPDATE(DCHUBBUB_ARB_WATERMARK_CHANGE_CNTL, + DCHUBBUB_ARB_WATERMARK_CHANGE_REQUEST, 1); + + REG_UPDATE(DCHUBBUB_ARB_SAT_LEVEL, + DCHUBBUB_ARB_SAT_LEVEL, 60 * refclk_mhz); + REG_UPDATE(DCHUBBUB_ARB_DF_REQ_OUTSTAND, + DCHUBBUB_ARB_MIN_REQ_OUTSTAND, 68); + + REG_UPDATE_2(DCHUBBUB_ARB_DRAM_STATE_CNTL, + DCHUBBUB_ARB_ALLOW_SELF_REFRESH_FORCE_VALUE, 0, + DCHUBBUB_ARB_ALLOW_SELF_REFRESH_FORCE_ENABLE, force_en); + +#if 0 + REG_UPDATE_2(DCHUBBUB_ARB_WATERMARK_CHANGE_CNTL, + DCHUBBUB_ARB_WATERMARK_CHANGE_DONE_INTERRUPT_DISABLE, 1, + DCHUBBUB_ARB_WATERMARK_CHANGE_REQUEST, 1); +#endif +} + +void hubbub1_update_dchub( + struct hubbub *hubbub, + struct dchub_init_data *dh_data) +{ + /* TODO: port code from dal2 */ + switch (dh_data->fb_mode) { + case FRAME_BUFFER_MODE_ZFB_ONLY: + /*For ZFB case need to put DCHUB FB BASE and TOP upside down to indicate ZFB mode*/ + REG_UPDATE(DCHUBBUB_SDPIF_FB_TOP, + SDPIF_FB_TOP, 0); + + REG_UPDATE(DCHUBBUB_SDPIF_FB_BASE, + SDPIF_FB_BASE, 0x0FFFF); + + REG_UPDATE(DCHUBBUB_SDPIF_AGP_BASE, + SDPIF_AGP_BASE, dh_data->zfb_phys_addr_base >> 22); + + REG_UPDATE(DCHUBBUB_SDPIF_AGP_BOT, + SDPIF_AGP_BOT, dh_data->zfb_mc_base_addr >> 22); + + REG_UPDATE(DCHUBBUB_SDPIF_AGP_TOP, + SDPIF_AGP_TOP, (dh_data->zfb_mc_base_addr + + dh_data->zfb_size_in_byte - 1) >> 22); + break; + case FRAME_BUFFER_MODE_MIXED_ZFB_AND_LOCAL: + /*Should not touch FB LOCATION (done by VBIOS on AsicInit table)*/ + + REG_UPDATE(DCHUBBUB_SDPIF_AGP_BASE, + SDPIF_AGP_BASE, dh_data->zfb_phys_addr_base >> 22); + + REG_UPDATE(DCHUBBUB_SDPIF_AGP_BOT, + SDPIF_AGP_BOT, dh_data->zfb_mc_base_addr >> 22); + + REG_UPDATE(DCHUBBUB_SDPIF_AGP_TOP, + SDPIF_AGP_TOP, (dh_data->zfb_mc_base_addr + + dh_data->zfb_size_in_byte - 1) >> 22); + break; + case FRAME_BUFFER_MODE_LOCAL_ONLY: + /*Should not touch FB LOCATION (done by VBIOS on AsicInit table)*/ + REG_UPDATE(DCHUBBUB_SDPIF_AGP_BASE, + SDPIF_AGP_BASE, 0); + + REG_UPDATE(DCHUBBUB_SDPIF_AGP_BOT, + SDPIF_AGP_BOT, 0X03FFFF); + + REG_UPDATE(DCHUBBUB_SDPIF_AGP_TOP, + SDPIF_AGP_TOP, 0); + break; + default: + break; + } + + dh_data->dchub_initialzied = true; + dh_data->dchub_info_valid = false; +} + +void hubbub1_toggle_watermark_change_req(struct hubbub *hubbub) +{ + uint32_t watermark_change_req; + + REG_GET(DCHUBBUB_ARB_WATERMARK_CHANGE_CNTL, + DCHUBBUB_ARB_WATERMARK_CHANGE_REQUEST, &watermark_change_req); + + if (watermark_change_req) + watermark_change_req = 0; + else + watermark_change_req = 1; + + REG_UPDATE(DCHUBBUB_ARB_WATERMARK_CHANGE_CNTL, + DCHUBBUB_ARB_WATERMARK_CHANGE_REQUEST, watermark_change_req); +} + +static const struct hubbub_funcs hubbub1_funcs = { + .update_dchub = hubbub1_update_dchub +}; + +void hubbub1_construct(struct hubbub *hubbub, + struct dc_context *ctx, + const struct dcn_hubbub_registers *hubbub_regs, + const struct dcn_hubbub_shift *hubbub_shift, + const struct dcn_hubbub_mask *hubbub_mask) +{ + hubbub->ctx = ctx; + + hubbub->funcs = &hubbub1_funcs; + + hubbub->regs = hubbub_regs; + hubbub->shifts = hubbub_shift; + hubbub->masks = hubbub_mask; + +} + diff --git a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hubbub.h b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hubbub.h new file mode 100644 index 000000000000..d5c97844312f --- /dev/null +++ b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hubbub.h @@ -0,0 +1,214 @@ +/* + * Copyright 2016 Advanced Micro Devices, Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + * + * Authors: AMD + * + */ + +#ifndef __DC_HUBBUB_DCN10_H__ +#define __DC_HUBBUB_DCN10_H__ + +#include "core_types.h" + +#define HUBHUB_REG_LIST_DCN()\ + SR(DCHUBBUB_ARB_DATA_URGENCY_WATERMARK_A),\ + SR(DCHUBBUB_ARB_PTE_META_URGENCY_WATERMARK_A),\ + SR(DCHUBBUB_ARB_ALLOW_DRAM_CLK_CHANGE_WATERMARK_A),\ + SR(DCHUBBUB_ARB_DATA_URGENCY_WATERMARK_B),\ + SR(DCHUBBUB_ARB_PTE_META_URGENCY_WATERMARK_B),\ + SR(DCHUBBUB_ARB_ALLOW_DRAM_CLK_CHANGE_WATERMARK_B),\ + SR(DCHUBBUB_ARB_DATA_URGENCY_WATERMARK_C),\ + SR(DCHUBBUB_ARB_PTE_META_URGENCY_WATERMARK_C),\ + SR(DCHUBBUB_ARB_ALLOW_DRAM_CLK_CHANGE_WATERMARK_C),\ + SR(DCHUBBUB_ARB_DATA_URGENCY_WATERMARK_D),\ + SR(DCHUBBUB_ARB_PTE_META_URGENCY_WATERMARK_D),\ + SR(DCHUBBUB_ARB_ALLOW_DRAM_CLK_CHANGE_WATERMARK_D),\ + SR(DCHUBBUB_ARB_WATERMARK_CHANGE_CNTL),\ + SR(DCHUBBUB_ARB_DRAM_STATE_CNTL),\ + SR(DCHUBBUB_ARB_SAT_LEVEL),\ + SR(DCHUBBUB_ARB_DF_REQ_OUTSTAND),\ + SR(DCHUBBUB_GLOBAL_TIMER_CNTL), \ + SR(DCHUBBUB_TEST_DEBUG_INDEX), \ + SR(DCHUBBUB_TEST_DEBUG_DATA) + +#define HUBBUB_SR_WATERMARK_REG_LIST()\ + SR(DCHUBBUB_ARB_ALLOW_SR_ENTER_WATERMARK_A),\ + SR(DCHUBBUB_ARB_ALLOW_SR_EXIT_WATERMARK_A),\ + SR(DCHUBBUB_ARB_ALLOW_SR_ENTER_WATERMARK_B),\ + SR(DCHUBBUB_ARB_ALLOW_SR_EXIT_WATERMARK_B),\ + SR(DCHUBBUB_ARB_ALLOW_SR_ENTER_WATERMARK_C),\ + SR(DCHUBBUB_ARB_ALLOW_SR_EXIT_WATERMARK_C),\ + SR(DCHUBBUB_ARB_ALLOW_SR_ENTER_WATERMARK_D),\ + SR(DCHUBBUB_ARB_ALLOW_SR_EXIT_WATERMARK_D) + +#define HUBBUB_REG_LIST_DCN10(id)\ + HUBHUB_REG_LIST_DCN(), \ + HUBBUB_SR_WATERMARK_REG_LIST(), \ + SR(DCHUBBUB_SDPIF_FB_TOP),\ + SR(DCHUBBUB_SDPIF_FB_BASE),\ + SR(DCHUBBUB_SDPIF_FB_OFFSET),\ + SR(DCHUBBUB_SDPIF_AGP_BASE),\ + SR(DCHUBBUB_SDPIF_AGP_BOT),\ + SR(DCHUBBUB_SDPIF_AGP_TOP) + +struct dcn_hubbub_registers { + uint32_t DCHUBBUB_ARB_DATA_URGENCY_WATERMARK_A; + uint32_t DCHUBBUB_ARB_PTE_META_URGENCY_WATERMARK_A; + uint32_t DCHUBBUB_ARB_ALLOW_SR_ENTER_WATERMARK_A; + uint32_t DCHUBBUB_ARB_ALLOW_SR_EXIT_WATERMARK_A; + uint32_t DCHUBBUB_ARB_ALLOW_DRAM_CLK_CHANGE_WATERMARK_A; + uint32_t DCHUBBUB_ARB_DATA_URGENCY_WATERMARK_B; + uint32_t DCHUBBUB_ARB_PTE_META_URGENCY_WATERMARK_B; + uint32_t DCHUBBUB_ARB_ALLOW_SR_ENTER_WATERMARK_B; + uint32_t DCHUBBUB_ARB_ALLOW_SR_EXIT_WATERMARK_B; + uint32_t DCHUBBUB_ARB_ALLOW_DRAM_CLK_CHANGE_WATERMARK_B; + uint32_t DCHUBBUB_ARB_DATA_URGENCY_WATERMARK_C; + uint32_t DCHUBBUB_ARB_PTE_META_URGENCY_WATERMARK_C; + uint32_t DCHUBBUB_ARB_ALLOW_SR_ENTER_WATERMARK_C; + uint32_t DCHUBBUB_ARB_ALLOW_SR_EXIT_WATERMARK_C; + uint32_t DCHUBBUB_ARB_ALLOW_DRAM_CLK_CHANGE_WATERMARK_C; + uint32_t DCHUBBUB_ARB_DATA_URGENCY_WATERMARK_D; + uint32_t DCHUBBUB_ARB_PTE_META_URGENCY_WATERMARK_D; + uint32_t DCHUBBUB_ARB_ALLOW_SR_ENTER_WATERMARK_D; + uint32_t DCHUBBUB_ARB_ALLOW_SR_EXIT_WATERMARK_D; + uint32_t DCHUBBUB_ARB_ALLOW_DRAM_CLK_CHANGE_WATERMARK_D; + uint32_t DCHUBBUB_ARB_WATERMARK_CHANGE_CNTL; + uint32_t DCHUBBUB_ARB_SAT_LEVEL; + uint32_t DCHUBBUB_ARB_DF_REQ_OUTSTAND; + uint32_t DCHUBBUB_GLOBAL_TIMER_CNTL; + uint32_t DCHUBBUB_ARB_DRAM_STATE_CNTL; + uint32_t DCHUBBUB_TEST_DEBUG_INDEX; + uint32_t DCHUBBUB_TEST_DEBUG_DATA; + uint32_t DCHUBBUB_SDPIF_FB_TOP; + uint32_t DCHUBBUB_SDPIF_FB_BASE; + uint32_t DCHUBBUB_SDPIF_FB_OFFSET; + uint32_t DCHUBBUB_SDPIF_AGP_BASE; + uint32_t DCHUBBUB_SDPIF_AGP_BOT; + uint32_t DCHUBBUB_SDPIF_AGP_TOP; + uint32_t DCHUBBUB_CRC_CTRL; +}; + +/* set field name */ +#define HUBBUB_SF(reg_name, field_name, post_fix)\ + .field_name = reg_name ## __ ## field_name ## post_fix + + +#define HUBBUB_MASK_SH_LIST_DCN(mask_sh)\ + HUBBUB_SF(DCHUBBUB_GLOBAL_TIMER_CNTL, DCHUBBUB_GLOBAL_TIMER_ENABLE, mask_sh), \ + HUBBUB_SF(DCHUBBUB_ARB_WATERMARK_CHANGE_CNTL, DCHUBBUB_ARB_WATERMARK_CHANGE_REQUEST, mask_sh), \ + HUBBUB_SF(DCHUBBUB_ARB_WATERMARK_CHANGE_CNTL, DCHUBBUB_ARB_WATERMARK_CHANGE_DONE_INTERRUPT_DISABLE, mask_sh), \ + HUBBUB_SF(DCHUBBUB_ARB_DRAM_STATE_CNTL, DCHUBBUB_ARB_ALLOW_SELF_REFRESH_FORCE_VALUE, mask_sh), \ + HUBBUB_SF(DCHUBBUB_ARB_DRAM_STATE_CNTL, DCHUBBUB_ARB_ALLOW_SELF_REFRESH_FORCE_ENABLE, mask_sh), \ + HUBBUB_SF(DCHUBBUB_ARB_DRAM_STATE_CNTL, DCHUBBUB_ARB_ALLOW_PSTATE_CHANGE_FORCE_VALUE, mask_sh), \ + HUBBUB_SF(DCHUBBUB_ARB_DRAM_STATE_CNTL, DCHUBBUB_ARB_ALLOW_PSTATE_CHANGE_FORCE_ENABLE, mask_sh), \ + HUBBUB_SF(DCHUBBUB_ARB_SAT_LEVEL, DCHUBBUB_ARB_SAT_LEVEL, mask_sh), \ + HUBBUB_SF(DCHUBBUB_ARB_DF_REQ_OUTSTAND, DCHUBBUB_ARB_MIN_REQ_OUTSTAND, mask_sh) + +#define HUBBUB_MASK_SH_LIST_DCN10(mask_sh)\ + HUBBUB_MASK_SH_LIST_DCN(mask_sh), \ + HUBBUB_SF(DCHUBBUB_SDPIF_FB_TOP, SDPIF_FB_TOP, mask_sh), \ + HUBBUB_SF(DCHUBBUB_SDPIF_FB_BASE, SDPIF_FB_BASE, mask_sh), \ + HUBBUB_SF(DCHUBBUB_SDPIF_FB_OFFSET, SDPIF_FB_OFFSET, mask_sh), \ + HUBBUB_SF(DCHUBBUB_SDPIF_AGP_BASE, SDPIF_AGP_BASE, mask_sh), \ + HUBBUB_SF(DCHUBBUB_SDPIF_AGP_BOT, SDPIF_AGP_BOT, mask_sh), \ + HUBBUB_SF(DCHUBBUB_SDPIF_AGP_TOP, SDPIF_AGP_TOP, mask_sh) + +#define DCN_HUBBUB_REG_FIELD_LIST(type) \ + type DCHUBBUB_GLOBAL_TIMER_ENABLE; \ + type DCHUBBUB_ARB_WATERMARK_CHANGE_REQUEST;\ + type DCHUBBUB_ARB_WATERMARK_CHANGE_DONE_INTERRUPT_DISABLE;\ + type DCHUBBUB_ARB_ALLOW_SELF_REFRESH_FORCE_VALUE;\ + type DCHUBBUB_ARB_ALLOW_SELF_REFRESH_FORCE_ENABLE;\ + type DCHUBBUB_ARB_ALLOW_PSTATE_CHANGE_FORCE_VALUE;\ + type DCHUBBUB_ARB_ALLOW_PSTATE_CHANGE_FORCE_ENABLE;\ + type DCHUBBUB_ARB_SAT_LEVEL;\ + type DCHUBBUB_ARB_MIN_REQ_OUTSTAND;\ + type DCHUBBUB_GLOBAL_TIMER_REFDIV;\ + type SDPIF_FB_TOP;\ + type SDPIF_FB_BASE;\ + type SDPIF_FB_OFFSET;\ + type SDPIF_AGP_BASE;\ + type SDPIF_AGP_BOT;\ + type SDPIF_AGP_TOP + + +struct dcn_hubbub_shift { + DCN_HUBBUB_REG_FIELD_LIST(uint8_t); +}; + +struct dcn_hubbub_mask { + DCN_HUBBUB_REG_FIELD_LIST(uint32_t); +}; + +struct dc; + +struct dcn_hubbub_wm_set { + uint32_t wm_set; + uint32_t data_urgent; + uint32_t pte_meta_urgent; + uint32_t sr_enter; + uint32_t sr_exit; + uint32_t dram_clk_chanage; +}; + +struct dcn_hubbub_wm { + struct dcn_hubbub_wm_set sets[4]; +}; + +struct hubbub_funcs { + void (*update_dchub)( + struct hubbub *hubbub, + struct dchub_init_data *dh_data); +}; + +struct hubbub { + const struct hubbub_funcs *funcs; + struct dc_context *ctx; + const struct dcn_hubbub_registers *regs; + const struct dcn_hubbub_shift *shifts; + const struct dcn_hubbub_mask *masks; +}; + +void hubbub1_update_dchub( + struct hubbub *hubbub, + struct dchub_init_data *dh_data); + +bool hubbub1_verify_allow_pstate_change_high( + struct hubbub *hubbub); + +void hubbub1_program_watermarks( + struct hubbub *hubbub, + struct dcn_watermark_set *watermarks, + unsigned int refclk_mhz); + +void hubbub1_toggle_watermark_change_req( + struct hubbub *hubbub); + +void hubbub1_wm_read_state(struct hubbub *hubbub, + struct dcn_hubbub_wm *wm); + +void hubbub1_construct(struct hubbub *hubbub, + struct dc_context *ctx, + const struct dcn_hubbub_registers *hubbub_regs, + const struct dcn_hubbub_shift *hubbub_shift, + const struct dcn_hubbub_mask *hubbub_mask); + +#endif diff --git a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hubp.c b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hubp.c index b13dee64e0ce..585b33384002 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hubp.c +++ b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hubp.c @@ -29,14 +29,14 @@ #include "dcn10_hubp.h" #define REG(reg)\ - hubp1->mi_regs->reg + hubp1->hubp_regs->reg #define CTX \ hubp1->base.ctx #undef FN #define FN(reg_name, field_name) \ - hubp1->mi_shift->field_name, hubp1->mi_mask->field_name + hubp1->hubp_shift->field_name, hubp1->hubp_mask->field_name void hubp1_set_blank(struct hubp *hubp, bool blank) { @@ -48,14 +48,33 @@ void hubp1_set_blank(struct hubp *hubp, bool blank) HUBP_TTU_DISABLE, blank_en); if (blank) { - REG_WAIT(DCHUBP_CNTL, - HUBP_NO_OUTSTANDING_REQ, 1, - 1, 200); + uint32_t reg_val = REG_READ(DCHUBP_CNTL); + + if (reg_val) { + /* init sequence workaround: in case HUBP is + * power gated, this wait would timeout. + * + * we just wrote reg_val to non-0, if it stay 0 + * it means HUBP is gated + */ + REG_WAIT(DCHUBP_CNTL, + HUBP_NO_OUTSTANDING_REQ, 1, + 1, 200); + } + hubp->mpcc_id = 0xf; hubp->opp_id = 0xf; } } +static void hubp1_disconnect(struct hubp *hubp) +{ + struct dcn10_hubp *hubp1 = TO_DCN10_HUBP(hubp); + + REG_UPDATE(DCHUBP_CNTL, + HUBP_TTU_DISABLE, 1); +} + static void hubp1_set_hubp_blank_en(struct hubp *hubp, bool blank) { struct dcn10_hubp *hubp1 = TO_DCN10_HUBP(hubp); @@ -88,10 +107,12 @@ static void hubp1_vready_workaround(struct hubp *hubp, } void hubp1_program_tiling( - struct dcn10_hubp *hubp1, + struct hubp *hubp, const union dc_tiling_info *info, const enum surface_pixel_format pixel_format) { + struct dcn10_hubp *hubp1 = TO_DCN10_HUBP(hubp); + REG_UPDATE_6(DCSURF_ADDR_CONFIG, NUM_PIPES, log_2(info->gfx9.num_pipes), NUM_BANKS, log_2(info->gfx9.num_banks), @@ -108,13 +129,14 @@ void hubp1_program_tiling( } void hubp1_program_size_and_rotation( - struct dcn10_hubp *hubp1, + struct hubp *hubp, enum dc_rotation_angle rotation, enum surface_pixel_format format, const union plane_size *plane_size, struct dc_plane_dcc_param *dcc, bool horizontal_mirror) { + struct dcn10_hubp *hubp1 = TO_DCN10_HUBP(hubp); uint32_t pitch, meta_pitch, pitch_c, meta_pitch_c, mirror; /* Program data and meta surface pitch (calculation from addrlib) @@ -170,9 +192,10 @@ void hubp1_program_size_and_rotation( } void hubp1_program_pixel_format( - struct dcn10_hubp *hubp1, + struct hubp *hubp, enum surface_pixel_format format) { + struct dcn10_hubp *hubp1 = TO_DCN10_HUBP(hubp); uint32_t red_bar = 3; uint32_t blue_bar = 2; @@ -416,13 +439,11 @@ void hubp1_program_surface_config( struct dc_plane_dcc_param *dcc, bool horizontal_mirror) { - struct dcn10_hubp *hubp1 = TO_DCN10_HUBP(hubp); - hubp1_dcc_control(hubp, dcc->enable, dcc->grph.independent_64b_blks); - hubp1_program_tiling(hubp1, tiling_info, format); + hubp1_program_tiling(hubp, tiling_info, format); hubp1_program_size_and_rotation( - hubp1, rotation, format, plane_size, dcc, horizontal_mirror); - hubp1_program_pixel_format(hubp1, format); + hubp, rotation, format, plane_size, dcc, horizontal_mirror); + hubp1_program_pixel_format(hubp, format); } void hubp1_program_requestor( @@ -757,42 +778,7 @@ void hubp1_read_state(struct dcn10_hubp *hubp1, QoS_LEVEL_HIGH_WM, &s->qos_level_high_wm); } -enum cursor_pitch { - CURSOR_PITCH_64_PIXELS = 0, - CURSOR_PITCH_128_PIXELS, - CURSOR_PITCH_256_PIXELS -}; - -enum cursor_lines_per_chunk { - CURSOR_LINE_PER_CHUNK_2 = 1, - CURSOR_LINE_PER_CHUNK_4, - CURSOR_LINE_PER_CHUNK_8, - CURSOR_LINE_PER_CHUNK_16 -}; - -static bool ippn10_cursor_program_control( - struct dcn10_hubp *hubp1, - bool pixel_data_invert, - enum dc_cursor_color_format color_format) -{ - if (REG(CURSOR_SETTINS)) - REG_SET_2(CURSOR_SETTINS, 0, - /* no shift of the cursor HDL schedule */ - CURSOR0_DST_Y_OFFSET, 0, - /* used to shift the cursor chunk request deadline */ - CURSOR0_CHUNK_HDL_ADJUST, 3); - else - REG_SET_2(CURSOR_SETTINGS, 0, - /* no shift of the cursor HDL schedule */ - CURSOR0_DST_Y_OFFSET, 0, - /* used to shift the cursor chunk request deadline */ - CURSOR0_CHUNK_HDL_ADJUST, 3); - - return true; -} - -static enum cursor_pitch ippn10_get_cursor_pitch( - unsigned int pitch) +enum cursor_pitch hubp1_get_cursor_pitch(unsigned int pitch) { enum cursor_pitch hw_pitch; @@ -815,7 +801,7 @@ static enum cursor_pitch ippn10_get_cursor_pitch( return hw_pitch; } -static enum cursor_lines_per_chunk ippn10_get_lines_per_chunk( +static enum cursor_lines_per_chunk hubp1_get_lines_per_chunk( unsigned int cur_width, enum dc_cursor_color_format format) { @@ -841,8 +827,8 @@ void hubp1_cursor_set_attributes( const struct dc_cursor_attributes *attr) { struct dcn10_hubp *hubp1 = TO_DCN10_HUBP(hubp); - enum cursor_pitch hw_pitch = ippn10_get_cursor_pitch(attr->pitch); - enum cursor_lines_per_chunk lpc = ippn10_get_lines_per_chunk( + enum cursor_pitch hw_pitch = hubp1_get_cursor_pitch(attr->pitch); + enum cursor_lines_per_chunk lpc = hubp1_get_lines_per_chunk( attr->width, attr->color_format); hubp->curs_attr = *attr; @@ -855,13 +841,17 @@ void hubp1_cursor_set_attributes( REG_UPDATE_2(CURSOR_SIZE, CURSOR_WIDTH, attr->width, CURSOR_HEIGHT, attr->height); + REG_UPDATE_3(CURSOR_CONTROL, CURSOR_MODE, attr->color_format, CURSOR_PITCH, hw_pitch, CURSOR_LINES_PER_CHUNK, lpc); - ippn10_cursor_program_control(hubp1, - attr->attribute_flags.bits.INVERT_PIXEL_DATA, - attr->color_format); + + REG_SET_2(CURSOR_SETTINS, 0, + /* no shift of the cursor HDL schedule */ + CURSOR0_DST_Y_OFFSET, 0, + /* used to shift the cursor chunk request deadline */ + CURSOR0_CHUNK_HDL_ADJUST, 3); } void hubp1_cursor_set_position( @@ -901,7 +891,8 @@ void hubp1_cursor_set_position( cur_en = 0; /* not visible beyond left edge*/ if (cur_en && REG_READ(CURSOR_SURFACE_ADDRESS) == 0) - hubp1_cursor_set_attributes(hubp, &hubp->curs_attr); + hubp->funcs->set_cursor_attributes(hubp, &hubp->curs_attr); + REG_UPDATE(CURSOR_CONTROL, CURSOR_ENABLE, cur_en); @@ -933,6 +924,7 @@ static struct hubp_funcs dcn10_hubp_funcs = { .set_hubp_blank_en = hubp1_set_hubp_blank_en, .set_cursor_attributes = hubp1_cursor_set_attributes, .set_cursor_position = hubp1_cursor_set_position, + .hubp_disconnect = hubp1_disconnect, }; /*****************************************/ @@ -943,15 +935,15 @@ void dcn10_hubp_construct( struct dcn10_hubp *hubp1, struct dc_context *ctx, uint32_t inst, - const struct dcn_mi_registers *mi_regs, - const struct dcn_mi_shift *mi_shift, - const struct dcn_mi_mask *mi_mask) + const struct dcn_mi_registers *hubp_regs, + const struct dcn_mi_shift *hubp_shift, + const struct dcn_mi_mask *hubp_mask) { hubp1->base.funcs = &dcn10_hubp_funcs; hubp1->base.ctx = ctx; - hubp1->mi_regs = mi_regs; - hubp1->mi_shift = mi_shift; - hubp1->mi_mask = mi_mask; + hubp1->hubp_regs = hubp_regs; + hubp1->hubp_shift = hubp_shift; + hubp1->hubp_mask = hubp_mask; hubp1->base.inst = inst; hubp1->base.opp_id = 0xf; hubp1->base.mpcc_id = 0xf; diff --git a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hubp.h b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hubp.h index 66db453c801b..33e91d9c010f 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hubp.h +++ b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hubp.h @@ -30,7 +30,7 @@ #define TO_DCN10_HUBP(hubp)\ container_of(hubp, struct dcn10_hubp, base) -#define MI_REG_LIST_DCN(id)\ +#define HUBP_REG_LIST_DCN(id)\ SRI(DCHUBP_CNTL, HUBP, id),\ SRI(HUBPREQ_DEBUG_DB, HUBP, id),\ SRI(DCSURF_ADDR_CONFIG, HUBP, id),\ @@ -98,8 +98,8 @@ SRI(DCN_SURF1_TTU_CNTL1, HUBPREQ, id),\ SRI(DCN_VM_MX_L1_TLB_CNTL, HUBPREQ, id) -#define MI_REG_LIST_DCN10(id)\ - MI_REG_LIST_DCN(id),\ +#define HUBP_REG_LIST_DCN10(id)\ + HUBP_REG_LIST_DCN(id),\ SRI(PREFETCH_SETTINS, HUBPREQ, id),\ SRI(PREFETCH_SETTINS_C, HUBPREQ, id),\ SRI(DCN_VM_CONTEXT0_PAGE_TABLE_BASE_ADDR_MSB, HUBPREQ, id),\ @@ -127,277 +127,274 @@ SRI(CURSOR_HOT_SPOT, CURSOR, id), \ SRI(CURSOR_DST_OFFSET, CURSOR, id) - - -struct dcn_mi_registers { - uint32_t DCHUBP_CNTL; - uint32_t HUBPREQ_DEBUG_DB; - uint32_t DCSURF_ADDR_CONFIG; - uint32_t DCSURF_TILING_CONFIG; - uint32_t DCSURF_SURFACE_PITCH; - uint32_t DCSURF_SURFACE_PITCH_C; - uint32_t DCSURF_SURFACE_CONFIG; - uint32_t DCSURF_FLIP_CONTROL; - uint32_t DCSURF_PRI_VIEWPORT_DIMENSION; - uint32_t DCSURF_PRI_VIEWPORT_START; - uint32_t DCSURF_SEC_VIEWPORT_DIMENSION; - uint32_t DCSURF_SEC_VIEWPORT_START; - uint32_t DCSURF_PRI_VIEWPORT_DIMENSION_C; - uint32_t DCSURF_PRI_VIEWPORT_START_C; - uint32_t DCSURF_PRIMARY_SURFACE_ADDRESS_HIGH; - uint32_t DCSURF_PRIMARY_SURFACE_ADDRESS; - uint32_t DCSURF_SECONDARY_SURFACE_ADDRESS_HIGH; - uint32_t DCSURF_SECONDARY_SURFACE_ADDRESS; - uint32_t DCSURF_PRIMARY_META_SURFACE_ADDRESS_HIGH; - uint32_t DCSURF_PRIMARY_META_SURFACE_ADDRESS; - uint32_t DCSURF_SECONDARY_META_SURFACE_ADDRESS_HIGH; - uint32_t DCSURF_SECONDARY_META_SURFACE_ADDRESS; - uint32_t DCSURF_PRIMARY_SURFACE_ADDRESS_HIGH_C; - uint32_t DCSURF_PRIMARY_SURFACE_ADDRESS_C; - uint32_t DCSURF_PRIMARY_META_SURFACE_ADDRESS_HIGH_C; - uint32_t DCSURF_PRIMARY_META_SURFACE_ADDRESS_C; - uint32_t DCSURF_SURFACE_INUSE; - uint32_t DCSURF_SURFACE_INUSE_HIGH; - uint32_t DCSURF_SURFACE_INUSE_C; - uint32_t DCSURF_SURFACE_INUSE_HIGH_C; - uint32_t DCSURF_SURFACE_EARLIEST_INUSE; - uint32_t DCSURF_SURFACE_EARLIEST_INUSE_HIGH; - uint32_t DCSURF_SURFACE_EARLIEST_INUSE_C; - uint32_t DCSURF_SURFACE_EARLIEST_INUSE_HIGH_C; - uint32_t DCSURF_SURFACE_CONTROL; - uint32_t HUBPRET_CONTROL; - uint32_t DCN_EXPANSION_MODE; - uint32_t DCHUBP_REQ_SIZE_CONFIG; - uint32_t DCHUBP_REQ_SIZE_CONFIG_C; - uint32_t BLANK_OFFSET_0; - uint32_t BLANK_OFFSET_1; - uint32_t DST_DIMENSIONS; - uint32_t DST_AFTER_SCALER; - uint32_t PREFETCH_SETTINS; - uint32_t PREFETCH_SETTINGS; - uint32_t VBLANK_PARAMETERS_0; - uint32_t REF_FREQ_TO_PIX_FREQ; - uint32_t VBLANK_PARAMETERS_1; - uint32_t VBLANK_PARAMETERS_3; - uint32_t NOM_PARAMETERS_0; - uint32_t NOM_PARAMETERS_1; - uint32_t NOM_PARAMETERS_4; - uint32_t NOM_PARAMETERS_5; - uint32_t PER_LINE_DELIVERY_PRE; - uint32_t PER_LINE_DELIVERY; - uint32_t PREFETCH_SETTINS_C; - uint32_t PREFETCH_SETTINGS_C; - uint32_t VBLANK_PARAMETERS_2; - uint32_t VBLANK_PARAMETERS_4; - uint32_t NOM_PARAMETERS_2; - uint32_t NOM_PARAMETERS_3; - uint32_t NOM_PARAMETERS_6; - uint32_t NOM_PARAMETERS_7; - uint32_t DCN_TTU_QOS_WM; - uint32_t DCN_GLOBAL_TTU_CNTL; - uint32_t DCN_SURF0_TTU_CNTL0; - uint32_t DCN_SURF0_TTU_CNTL1; - uint32_t DCN_SURF1_TTU_CNTL0; - uint32_t DCN_SURF1_TTU_CNTL1; - uint32_t DCN_VM_CONTEXT0_PAGE_TABLE_BASE_ADDR_MSB; - uint32_t DCN_VM_CONTEXT0_PAGE_TABLE_BASE_ADDR_LSB; - uint32_t DCN_VM_CONTEXT0_PAGE_TABLE_START_ADDR_MSB; - uint32_t DCN_VM_CONTEXT0_PAGE_TABLE_START_ADDR_LSB; - uint32_t DCN_VM_CONTEXT0_PAGE_TABLE_END_ADDR_MSB; - uint32_t DCN_VM_CONTEXT0_PAGE_TABLE_END_ADDR_LSB; - uint32_t DCN_VM_CONTEXT0_PROTECTION_FAULT_DEFAULT_ADDR_MSB; - uint32_t DCN_VM_CONTEXT0_PROTECTION_FAULT_DEFAULT_ADDR_LSB; - uint32_t DCN_VM_MX_L1_TLB_CNTL; - uint32_t DCN_VM_SYSTEM_APERTURE_DEFAULT_ADDR_MSB; - uint32_t DCN_VM_SYSTEM_APERTURE_DEFAULT_ADDR_LSB; - uint32_t DCN_VM_SYSTEM_APERTURE_LOW_ADDR_MSB; - uint32_t DCN_VM_SYSTEM_APERTURE_LOW_ADDR_LSB; - uint32_t DCN_VM_SYSTEM_APERTURE_HIGH_ADDR_MSB; - uint32_t DCN_VM_SYSTEM_APERTURE_HIGH_ADDR_LSB; - uint32_t DCN_VM_SYSTEM_APERTURE_LOW_ADDR; - uint32_t DCN_VM_SYSTEM_APERTURE_HIGH_ADDR; - uint32_t DCHUBBUB_SDPIF_FB_BASE; - uint32_t DCHUBBUB_SDPIF_FB_OFFSET; - uint32_t DCN_VM_FB_LOCATION_TOP; - uint32_t DCN_VM_FB_LOCATION_BASE; - uint32_t DCN_VM_FB_OFFSET; - uint32_t DCN_VM_AGP_BASE; - uint32_t DCN_VM_AGP_BOT; - uint32_t DCN_VM_AGP_TOP; - uint32_t CURSOR_SETTINS; - uint32_t CURSOR_SETTINGS; - uint32_t CURSOR_SURFACE_ADDRESS_HIGH; - uint32_t CURSOR_SURFACE_ADDRESS; - uint32_t CURSOR_SIZE; - uint32_t CURSOR_CONTROL; - uint32_t CURSOR_POSITION; - uint32_t CURSOR_HOT_SPOT; - uint32_t CURSOR_DST_OFFSET; -}; - -#define MI_SF(reg_name, field_name, post_fix)\ +#define HUBP_COMMON_REG_VARIABLE_LIST \ + uint32_t DCHUBP_CNTL; \ + uint32_t HUBPREQ_DEBUG_DB; \ + uint32_t DCSURF_ADDR_CONFIG; \ + uint32_t DCSURF_TILING_CONFIG; \ + uint32_t DCSURF_SURFACE_PITCH; \ + uint32_t DCSURF_SURFACE_PITCH_C; \ + uint32_t DCSURF_SURFACE_CONFIG; \ + uint32_t DCSURF_FLIP_CONTROL; \ + uint32_t DCSURF_PRI_VIEWPORT_DIMENSION; \ + uint32_t DCSURF_PRI_VIEWPORT_START; \ + uint32_t DCSURF_SEC_VIEWPORT_DIMENSION; \ + uint32_t DCSURF_SEC_VIEWPORT_START; \ + uint32_t DCSURF_PRI_VIEWPORT_DIMENSION_C; \ + uint32_t DCSURF_PRI_VIEWPORT_START_C; \ + uint32_t DCSURF_PRIMARY_SURFACE_ADDRESS_HIGH; \ + uint32_t DCSURF_PRIMARY_SURFACE_ADDRESS; \ + uint32_t DCSURF_SECONDARY_SURFACE_ADDRESS_HIGH; \ + uint32_t DCSURF_SECONDARY_SURFACE_ADDRESS; \ + uint32_t DCSURF_PRIMARY_META_SURFACE_ADDRESS_HIGH; \ + uint32_t DCSURF_PRIMARY_META_SURFACE_ADDRESS; \ + uint32_t DCSURF_SECONDARY_META_SURFACE_ADDRESS_HIGH; \ + uint32_t DCSURF_SECONDARY_META_SURFACE_ADDRESS; \ + uint32_t DCSURF_PRIMARY_SURFACE_ADDRESS_HIGH_C; \ + uint32_t DCSURF_PRIMARY_SURFACE_ADDRESS_C; \ + uint32_t DCSURF_PRIMARY_META_SURFACE_ADDRESS_HIGH_C; \ + uint32_t DCSURF_PRIMARY_META_SURFACE_ADDRESS_C; \ + uint32_t DCSURF_SURFACE_INUSE; \ + uint32_t DCSURF_SURFACE_INUSE_HIGH; \ + uint32_t DCSURF_SURFACE_INUSE_C; \ + uint32_t DCSURF_SURFACE_INUSE_HIGH_C; \ + uint32_t DCSURF_SURFACE_EARLIEST_INUSE; \ + uint32_t DCSURF_SURFACE_EARLIEST_INUSE_HIGH; \ + uint32_t DCSURF_SURFACE_EARLIEST_INUSE_C; \ + uint32_t DCSURF_SURFACE_EARLIEST_INUSE_HIGH_C; \ + uint32_t DCSURF_SURFACE_CONTROL; \ + uint32_t HUBPRET_CONTROL; \ + uint32_t DCN_EXPANSION_MODE; \ + uint32_t DCHUBP_REQ_SIZE_CONFIG; \ + uint32_t DCHUBP_REQ_SIZE_CONFIG_C; \ + uint32_t BLANK_OFFSET_0; \ + uint32_t BLANK_OFFSET_1; \ + uint32_t DST_DIMENSIONS; \ + uint32_t DST_AFTER_SCALER; \ + uint32_t PREFETCH_SETTINS; \ + uint32_t PREFETCH_SETTINGS; \ + uint32_t VBLANK_PARAMETERS_0; \ + uint32_t REF_FREQ_TO_PIX_FREQ; \ + uint32_t VBLANK_PARAMETERS_1; \ + uint32_t VBLANK_PARAMETERS_3; \ + uint32_t NOM_PARAMETERS_0; \ + uint32_t NOM_PARAMETERS_1; \ + uint32_t NOM_PARAMETERS_4; \ + uint32_t NOM_PARAMETERS_5; \ + uint32_t PER_LINE_DELIVERY_PRE; \ + uint32_t PER_LINE_DELIVERY; \ + uint32_t PREFETCH_SETTINS_C; \ + uint32_t PREFETCH_SETTINGS_C; \ + uint32_t VBLANK_PARAMETERS_2; \ + uint32_t VBLANK_PARAMETERS_4; \ + uint32_t NOM_PARAMETERS_2; \ + uint32_t NOM_PARAMETERS_3; \ + uint32_t NOM_PARAMETERS_6; \ + uint32_t NOM_PARAMETERS_7; \ + uint32_t DCN_TTU_QOS_WM; \ + uint32_t DCN_GLOBAL_TTU_CNTL; \ + uint32_t DCN_SURF0_TTU_CNTL0; \ + uint32_t DCN_SURF0_TTU_CNTL1; \ + uint32_t DCN_SURF1_TTU_CNTL0; \ + uint32_t DCN_SURF1_TTU_CNTL1; \ + uint32_t DCN_VM_CONTEXT0_PAGE_TABLE_BASE_ADDR_MSB; \ + uint32_t DCN_VM_CONTEXT0_PAGE_TABLE_BASE_ADDR_LSB; \ + uint32_t DCN_VM_CONTEXT0_PAGE_TABLE_START_ADDR_MSB; \ + uint32_t DCN_VM_CONTEXT0_PAGE_TABLE_START_ADDR_LSB; \ + uint32_t DCN_VM_CONTEXT0_PAGE_TABLE_END_ADDR_MSB; \ + uint32_t DCN_VM_CONTEXT0_PAGE_TABLE_END_ADDR_LSB; \ + uint32_t DCN_VM_CONTEXT0_PROTECTION_FAULT_DEFAULT_ADDR_MSB; \ + uint32_t DCN_VM_CONTEXT0_PROTECTION_FAULT_DEFAULT_ADDR_LSB; \ + uint32_t DCN_VM_MX_L1_TLB_CNTL; \ + uint32_t DCN_VM_SYSTEM_APERTURE_DEFAULT_ADDR_MSB; \ + uint32_t DCN_VM_SYSTEM_APERTURE_DEFAULT_ADDR_LSB; \ + uint32_t DCN_VM_SYSTEM_APERTURE_LOW_ADDR_MSB; \ + uint32_t DCN_VM_SYSTEM_APERTURE_LOW_ADDR_LSB; \ + uint32_t DCN_VM_SYSTEM_APERTURE_HIGH_ADDR_MSB; \ + uint32_t DCN_VM_SYSTEM_APERTURE_HIGH_ADDR_LSB; \ + uint32_t DCN_VM_SYSTEM_APERTURE_LOW_ADDR; \ + uint32_t DCN_VM_SYSTEM_APERTURE_HIGH_ADDR; \ + uint32_t DCHUBBUB_SDPIF_FB_BASE; \ + uint32_t DCHUBBUB_SDPIF_FB_OFFSET; \ + uint32_t DCN_VM_FB_LOCATION_TOP; \ + uint32_t DCN_VM_FB_LOCATION_BASE; \ + uint32_t DCN_VM_FB_OFFSET; \ + uint32_t DCN_VM_AGP_BASE; \ + uint32_t DCN_VM_AGP_BOT; \ + uint32_t DCN_VM_AGP_TOP; \ + uint32_t CURSOR_SETTINS; \ + uint32_t CURSOR_SETTINGS; \ + uint32_t CURSOR_SURFACE_ADDRESS_HIGH; \ + uint32_t CURSOR_SURFACE_ADDRESS; \ + uint32_t CURSOR_SIZE; \ + uint32_t CURSOR_CONTROL; \ + uint32_t CURSOR_POSITION; \ + uint32_t CURSOR_HOT_SPOT; \ + uint32_t CURSOR_DST_OFFSET + +#define HUBP_SF(reg_name, field_name, post_fix)\ .field_name = reg_name ## __ ## field_name ## post_fix -#define MI_MASK_SH_LIST_DCN(mask_sh)\ - MI_SF(HUBP0_DCHUBP_CNTL, HUBP_BLANK_EN, mask_sh),\ - MI_SF(HUBP0_DCHUBP_CNTL, HUBP_TTU_DISABLE, mask_sh),\ - MI_SF(HUBP0_DCHUBP_CNTL, HUBP_UNDERFLOW_STATUS, mask_sh),\ - MI_SF(HUBP0_DCHUBP_CNTL, HUBP_NO_OUTSTANDING_REQ, mask_sh),\ - MI_SF(HUBP0_DCSURF_ADDR_CONFIG, NUM_PIPES, mask_sh),\ - MI_SF(HUBP0_DCSURF_ADDR_CONFIG, NUM_BANKS, mask_sh),\ - MI_SF(HUBP0_DCSURF_ADDR_CONFIG, PIPE_INTERLEAVE, mask_sh),\ - MI_SF(HUBP0_DCSURF_ADDR_CONFIG, NUM_SE, mask_sh),\ - MI_SF(HUBP0_DCSURF_ADDR_CONFIG, NUM_RB_PER_SE, mask_sh),\ - MI_SF(HUBP0_DCSURF_ADDR_CONFIG, MAX_COMPRESSED_FRAGS, mask_sh),\ - MI_SF(HUBP0_DCSURF_TILING_CONFIG, SW_MODE, mask_sh),\ - MI_SF(HUBP0_DCSURF_TILING_CONFIG, META_LINEAR, mask_sh),\ - MI_SF(HUBP0_DCSURF_TILING_CONFIG, RB_ALIGNED, mask_sh),\ - MI_SF(HUBP0_DCSURF_TILING_CONFIG, PIPE_ALIGNED, mask_sh),\ - MI_SF(HUBPREQ0_DCSURF_SURFACE_PITCH, PITCH, mask_sh),\ - MI_SF(HUBPREQ0_DCSURF_SURFACE_PITCH, META_PITCH, mask_sh),\ - MI_SF(HUBPREQ0_DCSURF_SURFACE_PITCH_C, PITCH_C, mask_sh),\ - MI_SF(HUBPREQ0_DCSURF_SURFACE_PITCH_C, META_PITCH_C, mask_sh),\ - MI_SF(HUBP0_DCSURF_SURFACE_CONFIG, ROTATION_ANGLE, mask_sh),\ - MI_SF(HUBP0_DCSURF_SURFACE_CONFIG, H_MIRROR_EN, mask_sh),\ - MI_SF(HUBP0_DCSURF_SURFACE_CONFIG, SURFACE_PIXEL_FORMAT, mask_sh),\ - MI_SF(HUBPREQ0_DCSURF_FLIP_CONTROL, SURFACE_FLIP_TYPE, mask_sh),\ - MI_SF(HUBPREQ0_DCSURF_FLIP_CONTROL, SURFACE_FLIP_PENDING, mask_sh),\ - MI_SF(HUBPREQ0_DCSURF_FLIP_CONTROL, SURFACE_UPDATE_LOCK, mask_sh),\ - MI_SF(HUBP0_DCSURF_PRI_VIEWPORT_DIMENSION, PRI_VIEWPORT_WIDTH, mask_sh),\ - MI_SF(HUBP0_DCSURF_PRI_VIEWPORT_DIMENSION, PRI_VIEWPORT_HEIGHT, mask_sh),\ - MI_SF(HUBP0_DCSURF_PRI_VIEWPORT_START, PRI_VIEWPORT_X_START, mask_sh),\ - MI_SF(HUBP0_DCSURF_PRI_VIEWPORT_START, PRI_VIEWPORT_Y_START, mask_sh),\ - MI_SF(HUBP0_DCSURF_SEC_VIEWPORT_DIMENSION, SEC_VIEWPORT_WIDTH, mask_sh),\ - MI_SF(HUBP0_DCSURF_SEC_VIEWPORT_DIMENSION, SEC_VIEWPORT_HEIGHT, mask_sh),\ - MI_SF(HUBP0_DCSURF_SEC_VIEWPORT_START, SEC_VIEWPORT_X_START, mask_sh),\ - MI_SF(HUBP0_DCSURF_SEC_VIEWPORT_START, SEC_VIEWPORT_Y_START, mask_sh),\ - MI_SF(HUBP0_DCSURF_PRI_VIEWPORT_DIMENSION_C, PRI_VIEWPORT_WIDTH_C, mask_sh),\ - MI_SF(HUBP0_DCSURF_PRI_VIEWPORT_DIMENSION_C, PRI_VIEWPORT_HEIGHT_C, mask_sh),\ - MI_SF(HUBP0_DCSURF_PRI_VIEWPORT_START_C, PRI_VIEWPORT_X_START_C, mask_sh),\ - MI_SF(HUBP0_DCSURF_PRI_VIEWPORT_START_C, PRI_VIEWPORT_Y_START_C, mask_sh),\ - MI_SF(HUBPREQ0_DCSURF_PRIMARY_SURFACE_ADDRESS_HIGH, PRIMARY_SURFACE_ADDRESS_HIGH, mask_sh),\ - MI_SF(HUBPREQ0_DCSURF_PRIMARY_SURFACE_ADDRESS, PRIMARY_SURFACE_ADDRESS, mask_sh),\ - MI_SF(HUBPREQ0_DCSURF_SECONDARY_SURFACE_ADDRESS_HIGH, SECONDARY_SURFACE_ADDRESS_HIGH, mask_sh),\ - MI_SF(HUBPREQ0_DCSURF_SECONDARY_SURFACE_ADDRESS, SECONDARY_SURFACE_ADDRESS, mask_sh),\ - MI_SF(HUBPREQ0_DCSURF_PRIMARY_META_SURFACE_ADDRESS_HIGH, PRIMARY_META_SURFACE_ADDRESS_HIGH, mask_sh),\ - MI_SF(HUBPREQ0_DCSURF_PRIMARY_META_SURFACE_ADDRESS, PRIMARY_META_SURFACE_ADDRESS, mask_sh),\ - MI_SF(HUBPREQ0_DCSURF_SECONDARY_META_SURFACE_ADDRESS_HIGH, SECONDARY_META_SURFACE_ADDRESS_HIGH, mask_sh),\ - MI_SF(HUBPREQ0_DCSURF_SECONDARY_META_SURFACE_ADDRESS, SECONDARY_META_SURFACE_ADDRESS, mask_sh),\ - MI_SF(HUBPREQ0_DCSURF_PRIMARY_SURFACE_ADDRESS_HIGH_C, PRIMARY_SURFACE_ADDRESS_HIGH_C, mask_sh),\ - MI_SF(HUBPREQ0_DCSURF_PRIMARY_SURFACE_ADDRESS_C, PRIMARY_SURFACE_ADDRESS_C, mask_sh),\ - MI_SF(HUBPREQ0_DCSURF_PRIMARY_META_SURFACE_ADDRESS_HIGH_C, PRIMARY_META_SURFACE_ADDRESS_HIGH_C, mask_sh),\ - MI_SF(HUBPREQ0_DCSURF_PRIMARY_META_SURFACE_ADDRESS_C, PRIMARY_META_SURFACE_ADDRESS_C, mask_sh),\ - MI_SF(HUBPREQ0_DCSURF_SURFACE_INUSE, SURFACE_INUSE_ADDRESS, mask_sh),\ - MI_SF(HUBPREQ0_DCSURF_SURFACE_INUSE_HIGH, SURFACE_INUSE_ADDRESS_HIGH, mask_sh),\ - MI_SF(HUBPREQ0_DCSURF_SURFACE_INUSE_C, SURFACE_INUSE_ADDRESS_C, mask_sh),\ - MI_SF(HUBPREQ0_DCSURF_SURFACE_INUSE_HIGH_C, SURFACE_INUSE_ADDRESS_HIGH_C, mask_sh),\ - MI_SF(HUBPREQ0_DCSURF_SURFACE_EARLIEST_INUSE, SURFACE_EARLIEST_INUSE_ADDRESS, mask_sh),\ - MI_SF(HUBPREQ0_DCSURF_SURFACE_EARLIEST_INUSE_HIGH, SURFACE_EARLIEST_INUSE_ADDRESS_HIGH, mask_sh),\ - MI_SF(HUBPREQ0_DCSURF_SURFACE_EARLIEST_INUSE_C, SURFACE_EARLIEST_INUSE_ADDRESS_C, mask_sh),\ - MI_SF(HUBPREQ0_DCSURF_SURFACE_EARLIEST_INUSE_HIGH_C, SURFACE_EARLIEST_INUSE_ADDRESS_HIGH_C, mask_sh),\ - MI_SF(HUBPREQ0_DCSURF_SURFACE_CONTROL, PRIMARY_SURFACE_TMZ, mask_sh),\ - MI_SF(HUBPREQ0_DCSURF_SURFACE_CONTROL, PRIMARY_SURFACE_DCC_EN, mask_sh),\ - MI_SF(HUBPREQ0_DCSURF_SURFACE_CONTROL, PRIMARY_SURFACE_DCC_IND_64B_BLK, mask_sh),\ - MI_SF(HUBPRET0_HUBPRET_CONTROL, DET_BUF_PLANE1_BASE_ADDRESS, mask_sh),\ - MI_SF(HUBPRET0_HUBPRET_CONTROL, CROSSBAR_SRC_CB_B, mask_sh),\ - MI_SF(HUBPRET0_HUBPRET_CONTROL, CROSSBAR_SRC_CR_R, mask_sh),\ - MI_SF(HUBPREQ0_DCN_EXPANSION_MODE, DRQ_EXPANSION_MODE, mask_sh),\ - MI_SF(HUBPREQ0_DCN_EXPANSION_MODE, PRQ_EXPANSION_MODE, mask_sh),\ - MI_SF(HUBPREQ0_DCN_EXPANSION_MODE, MRQ_EXPANSION_MODE, mask_sh),\ - MI_SF(HUBPREQ0_DCN_EXPANSION_MODE, CRQ_EXPANSION_MODE, mask_sh),\ - MI_SF(HUBP0_DCHUBP_REQ_SIZE_CONFIG, CHUNK_SIZE, mask_sh),\ - MI_SF(HUBP0_DCHUBP_REQ_SIZE_CONFIG, MIN_CHUNK_SIZE, mask_sh),\ - MI_SF(HUBP0_DCHUBP_REQ_SIZE_CONFIG, META_CHUNK_SIZE, mask_sh),\ - MI_SF(HUBP0_DCHUBP_REQ_SIZE_CONFIG, MIN_META_CHUNK_SIZE, mask_sh),\ - MI_SF(HUBP0_DCHUBP_REQ_SIZE_CONFIG, DPTE_GROUP_SIZE, mask_sh),\ - MI_SF(HUBP0_DCHUBP_REQ_SIZE_CONFIG, MPTE_GROUP_SIZE, mask_sh),\ - MI_SF(HUBP0_DCHUBP_REQ_SIZE_CONFIG, SWATH_HEIGHT, mask_sh),\ - MI_SF(HUBP0_DCHUBP_REQ_SIZE_CONFIG, PTE_ROW_HEIGHT_LINEAR, mask_sh),\ - MI_SF(HUBP0_DCHUBP_REQ_SIZE_CONFIG_C, CHUNK_SIZE_C, mask_sh),\ - MI_SF(HUBP0_DCHUBP_REQ_SIZE_CONFIG_C, MIN_CHUNK_SIZE_C, mask_sh),\ - MI_SF(HUBP0_DCHUBP_REQ_SIZE_CONFIG_C, META_CHUNK_SIZE_C, mask_sh),\ - MI_SF(HUBP0_DCHUBP_REQ_SIZE_CONFIG_C, MIN_META_CHUNK_SIZE_C, mask_sh),\ - MI_SF(HUBP0_DCHUBP_REQ_SIZE_CONFIG_C, DPTE_GROUP_SIZE_C, mask_sh),\ - MI_SF(HUBP0_DCHUBP_REQ_SIZE_CONFIG_C, MPTE_GROUP_SIZE_C, mask_sh),\ - MI_SF(HUBP0_DCHUBP_REQ_SIZE_CONFIG_C, SWATH_HEIGHT_C, mask_sh),\ - MI_SF(HUBP0_DCHUBP_REQ_SIZE_CONFIG_C, PTE_ROW_HEIGHT_LINEAR_C, mask_sh),\ - MI_SF(HUBPREQ0_BLANK_OFFSET_0, REFCYC_H_BLANK_END, mask_sh),\ - MI_SF(HUBPREQ0_BLANK_OFFSET_0, DLG_V_BLANK_END, mask_sh),\ - MI_SF(HUBPREQ0_BLANK_OFFSET_1, MIN_DST_Y_NEXT_START, mask_sh),\ - MI_SF(HUBPREQ0_DST_DIMENSIONS, REFCYC_PER_HTOTAL, mask_sh),\ - MI_SF(HUBPREQ0_DST_AFTER_SCALER, REFCYC_X_AFTER_SCALER, mask_sh),\ - MI_SF(HUBPREQ0_DST_AFTER_SCALER, DST_Y_AFTER_SCALER, mask_sh),\ - MI_SF(HUBPREQ0_VBLANK_PARAMETERS_0, DST_Y_PER_VM_VBLANK, mask_sh),\ - MI_SF(HUBPREQ0_VBLANK_PARAMETERS_0, DST_Y_PER_ROW_VBLANK, mask_sh),\ - MI_SF(HUBPREQ0_REF_FREQ_TO_PIX_FREQ, REF_FREQ_TO_PIX_FREQ, mask_sh),\ - MI_SF(HUBPREQ0_VBLANK_PARAMETERS_1, REFCYC_PER_PTE_GROUP_VBLANK_L, mask_sh),\ - MI_SF(HUBPREQ0_VBLANK_PARAMETERS_3, REFCYC_PER_META_CHUNK_VBLANK_L, mask_sh),\ - MI_SF(HUBPREQ0_NOM_PARAMETERS_0, DST_Y_PER_PTE_ROW_NOM_L, mask_sh),\ - MI_SF(HUBPREQ0_NOM_PARAMETERS_1, REFCYC_PER_PTE_GROUP_NOM_L, mask_sh),\ - MI_SF(HUBPREQ0_NOM_PARAMETERS_4, DST_Y_PER_META_ROW_NOM_L, mask_sh),\ - MI_SF(HUBPREQ0_NOM_PARAMETERS_5, REFCYC_PER_META_CHUNK_NOM_L, mask_sh),\ - MI_SF(HUBPREQ0_PER_LINE_DELIVERY_PRE, REFCYC_PER_LINE_DELIVERY_PRE_L, mask_sh),\ - MI_SF(HUBPREQ0_PER_LINE_DELIVERY_PRE, REFCYC_PER_LINE_DELIVERY_PRE_C, mask_sh),\ - MI_SF(HUBPREQ0_PER_LINE_DELIVERY, REFCYC_PER_LINE_DELIVERY_L, mask_sh),\ - MI_SF(HUBPREQ0_PER_LINE_DELIVERY, REFCYC_PER_LINE_DELIVERY_C, mask_sh),\ - MI_SF(HUBPREQ0_VBLANK_PARAMETERS_2, REFCYC_PER_PTE_GROUP_VBLANK_C, mask_sh),\ - MI_SF(HUBPREQ0_VBLANK_PARAMETERS_4, REFCYC_PER_META_CHUNK_VBLANK_C, mask_sh),\ - MI_SF(HUBPREQ0_NOM_PARAMETERS_2, DST_Y_PER_PTE_ROW_NOM_C, mask_sh),\ - MI_SF(HUBPREQ0_NOM_PARAMETERS_3, REFCYC_PER_PTE_GROUP_NOM_C, mask_sh),\ - MI_SF(HUBPREQ0_NOM_PARAMETERS_6, DST_Y_PER_META_ROW_NOM_C, mask_sh),\ - MI_SF(HUBPREQ0_NOM_PARAMETERS_7, REFCYC_PER_META_CHUNK_NOM_C, mask_sh),\ - MI_SF(HUBPREQ0_DCN_TTU_QOS_WM, QoS_LEVEL_LOW_WM, mask_sh),\ - MI_SF(HUBPREQ0_DCN_TTU_QOS_WM, QoS_LEVEL_HIGH_WM, mask_sh),\ - MI_SF(HUBPREQ0_DCN_GLOBAL_TTU_CNTL, MIN_TTU_VBLANK, mask_sh),\ - MI_SF(HUBPREQ0_DCN_GLOBAL_TTU_CNTL, QoS_LEVEL_FLIP, mask_sh),\ - MI_SF(HUBPREQ0_DCN_SURF0_TTU_CNTL0, REFCYC_PER_REQ_DELIVERY, mask_sh),\ - MI_SF(HUBPREQ0_DCN_SURF0_TTU_CNTL0, QoS_LEVEL_FIXED, mask_sh),\ - MI_SF(HUBPREQ0_DCN_SURF0_TTU_CNTL0, QoS_RAMP_DISABLE, mask_sh),\ - MI_SF(HUBPREQ0_DCN_SURF0_TTU_CNTL1, REFCYC_PER_REQ_DELIVERY_PRE, mask_sh),\ - MI_SF(HUBPREQ0_DCN_VM_MX_L1_TLB_CNTL, ENABLE_L1_TLB, mask_sh),\ - MI_SF(HUBPREQ0_DCN_VM_MX_L1_TLB_CNTL, SYSTEM_ACCESS_MODE, mask_sh) - -#define MI_MASK_SH_LIST_DCN10(mask_sh)\ - MI_MASK_SH_LIST_DCN(mask_sh),\ - MI_SF(HUBPREQ0_PREFETCH_SETTINS, DST_Y_PREFETCH, mask_sh),\ - MI_SF(HUBPREQ0_PREFETCH_SETTINS, VRATIO_PREFETCH, mask_sh),\ - MI_SF(HUBPREQ0_PREFETCH_SETTINS_C, VRATIO_PREFETCH_C, mask_sh),\ - MI_SF(HUBPREQ0_DCN_VM_CONTEXT0_PAGE_TABLE_BASE_ADDR_MSB, VM_CONTEXT0_PAGE_TABLE_BASE_ADDR_MSB, mask_sh),\ - MI_SF(HUBPREQ0_DCN_VM_CONTEXT0_PAGE_TABLE_BASE_ADDR_LSB, VM_CONTEXT0_PAGE_TABLE_BASE_ADDR_LSB, mask_sh),\ - MI_SF(HUBPREQ0_DCN_VM_CONTEXT0_PAGE_TABLE_START_ADDR_MSB, VM_CONTEXT0_PAGE_TABLE_START_ADDR_MSB, mask_sh),\ - MI_SF(HUBPREQ0_DCN_VM_CONTEXT0_PAGE_TABLE_START_ADDR_LSB, VM_CONTEXT0_PAGE_TABLE_START_ADDR_LSB, mask_sh),\ - MI_SF(HUBPREQ0_DCN_VM_CONTEXT0_PAGE_TABLE_END_ADDR_MSB, VM_CONTEXT0_PAGE_TABLE_END_ADDR_MSB, mask_sh),\ - MI_SF(HUBPREQ0_DCN_VM_CONTEXT0_PAGE_TABLE_END_ADDR_LSB, VM_CONTEXT0_PAGE_TABLE_END_ADDR_LSB, mask_sh),\ - MI_SF(HUBPREQ0_DCN_VM_CONTEXT0_PROTECTION_FAULT_DEFAULT_ADDR_MSB, VM_CONTEXT0_PROTECTION_FAULT_DEFAULT_ADDR_MSB, mask_sh),\ - MI_SF(HUBPREQ0_DCN_VM_CONTEXT0_PROTECTION_FAULT_DEFAULT_ADDR_MSB, VM_CONTEXT0_PROTECTION_FAULT_DEFAULT_SYSTEM, mask_sh),\ - MI_SF(HUBPREQ0_DCN_VM_CONTEXT0_PROTECTION_FAULT_DEFAULT_ADDR_LSB, VM_CONTEXT0_PROTECTION_FAULT_DEFAULT_ADDR_LSB, mask_sh),\ - MI_SF(HUBPREQ0_DCN_VM_SYSTEM_APERTURE_LOW_ADDR_MSB, MC_VM_SYSTEM_APERTURE_LOW_ADDR_MSB, mask_sh),\ - MI_SF(HUBPREQ0_DCN_VM_SYSTEM_APERTURE_LOW_ADDR_LSB, MC_VM_SYSTEM_APERTURE_LOW_ADDR_LSB, mask_sh),\ - MI_SF(HUBPREQ0_DCN_VM_SYSTEM_APERTURE_HIGH_ADDR_MSB, MC_VM_SYSTEM_APERTURE_HIGH_ADDR_MSB, mask_sh),\ - MI_SF(HUBPREQ0_DCN_VM_SYSTEM_APERTURE_HIGH_ADDR_LSB, MC_VM_SYSTEM_APERTURE_HIGH_ADDR_LSB, mask_sh),\ - MI_SF(DCHUBBUB_SDPIF_FB_BASE, SDPIF_FB_BASE, mask_sh),\ - MI_SF(DCHUBBUB_SDPIF_FB_OFFSET, SDPIF_FB_OFFSET, mask_sh),\ - MI_SF(HUBPREQ0_DCN_VM_SYSTEM_APERTURE_DEFAULT_ADDR_MSB, MC_VM_SYSTEM_APERTURE_DEFAULT_SYSTEM, mask_sh),\ - MI_SF(HUBPREQ0_DCN_VM_SYSTEM_APERTURE_DEFAULT_ADDR_MSB, MC_VM_SYSTEM_APERTURE_DEFAULT_ADDR_MSB, mask_sh),\ - MI_SF(HUBPREQ0_DCN_VM_SYSTEM_APERTURE_DEFAULT_ADDR_LSB, MC_VM_SYSTEM_APERTURE_DEFAULT_ADDR_LSB, mask_sh),\ - MI_SF(HUBPREQ0_CURSOR_SETTINS, CURSOR0_DST_Y_OFFSET, mask_sh), \ - MI_SF(HUBPREQ0_CURSOR_SETTINS, CURSOR0_CHUNK_HDL_ADJUST, mask_sh), \ - MI_SF(CURSOR0_CURSOR_SURFACE_ADDRESS_HIGH, CURSOR_SURFACE_ADDRESS_HIGH, mask_sh), \ - MI_SF(CURSOR0_CURSOR_SURFACE_ADDRESS, CURSOR_SURFACE_ADDRESS, mask_sh), \ - MI_SF(CURSOR0_CURSOR_SIZE, CURSOR_WIDTH, mask_sh), \ - MI_SF(CURSOR0_CURSOR_SIZE, CURSOR_HEIGHT, mask_sh), \ - MI_SF(CURSOR0_CURSOR_CONTROL, CURSOR_MODE, mask_sh), \ - MI_SF(CURSOR0_CURSOR_CONTROL, CURSOR_2X_MAGNIFY, mask_sh), \ - MI_SF(CURSOR0_CURSOR_CONTROL, CURSOR_PITCH, mask_sh), \ - MI_SF(CURSOR0_CURSOR_CONTROL, CURSOR_LINES_PER_CHUNK, mask_sh), \ - MI_SF(CURSOR0_CURSOR_CONTROL, CURSOR_ENABLE, mask_sh), \ - MI_SF(CURSOR0_CURSOR_POSITION, CURSOR_X_POSITION, mask_sh), \ - MI_SF(CURSOR0_CURSOR_POSITION, CURSOR_Y_POSITION, mask_sh), \ - MI_SF(CURSOR0_CURSOR_HOT_SPOT, CURSOR_HOT_SPOT_X, mask_sh), \ - MI_SF(CURSOR0_CURSOR_HOT_SPOT, CURSOR_HOT_SPOT_Y, mask_sh), \ - MI_SF(CURSOR0_CURSOR_DST_OFFSET, CURSOR_DST_X_OFFSET, mask_sh) - -#define DCN_MI_REG_FIELD_LIST(type) \ +#define HUBP_MASK_SH_LIST_DCN(mask_sh)\ + HUBP_SF(HUBP0_DCHUBP_CNTL, HUBP_BLANK_EN, mask_sh),\ + HUBP_SF(HUBP0_DCHUBP_CNTL, HUBP_TTU_DISABLE, mask_sh),\ + HUBP_SF(HUBP0_DCHUBP_CNTL, HUBP_UNDERFLOW_STATUS, mask_sh),\ + HUBP_SF(HUBP0_DCHUBP_CNTL, HUBP_NO_OUTSTANDING_REQ, mask_sh),\ + HUBP_SF(HUBP0_DCSURF_ADDR_CONFIG, NUM_PIPES, mask_sh),\ + HUBP_SF(HUBP0_DCSURF_ADDR_CONFIG, NUM_BANKS, mask_sh),\ + HUBP_SF(HUBP0_DCSURF_ADDR_CONFIG, PIPE_INTERLEAVE, mask_sh),\ + HUBP_SF(HUBP0_DCSURF_ADDR_CONFIG, NUM_SE, mask_sh),\ + HUBP_SF(HUBP0_DCSURF_ADDR_CONFIG, NUM_RB_PER_SE, mask_sh),\ + HUBP_SF(HUBP0_DCSURF_ADDR_CONFIG, MAX_COMPRESSED_FRAGS, mask_sh),\ + HUBP_SF(HUBP0_DCSURF_TILING_CONFIG, SW_MODE, mask_sh),\ + HUBP_SF(HUBP0_DCSURF_TILING_CONFIG, META_LINEAR, mask_sh),\ + HUBP_SF(HUBP0_DCSURF_TILING_CONFIG, RB_ALIGNED, mask_sh),\ + HUBP_SF(HUBP0_DCSURF_TILING_CONFIG, PIPE_ALIGNED, mask_sh),\ + HUBP_SF(HUBPREQ0_DCSURF_SURFACE_PITCH, PITCH, mask_sh),\ + HUBP_SF(HUBPREQ0_DCSURF_SURFACE_PITCH, META_PITCH, mask_sh),\ + HUBP_SF(HUBPREQ0_DCSURF_SURFACE_PITCH_C, PITCH_C, mask_sh),\ + HUBP_SF(HUBPREQ0_DCSURF_SURFACE_PITCH_C, META_PITCH_C, mask_sh),\ + HUBP_SF(HUBP0_DCSURF_SURFACE_CONFIG, ROTATION_ANGLE, mask_sh),\ + HUBP_SF(HUBP0_DCSURF_SURFACE_CONFIG, H_MIRROR_EN, mask_sh),\ + HUBP_SF(HUBP0_DCSURF_SURFACE_CONFIG, SURFACE_PIXEL_FORMAT, mask_sh),\ + HUBP_SF(HUBPREQ0_DCSURF_FLIP_CONTROL, SURFACE_FLIP_TYPE, mask_sh),\ + HUBP_SF(HUBPREQ0_DCSURF_FLIP_CONTROL, SURFACE_FLIP_PENDING, mask_sh),\ + HUBP_SF(HUBPREQ0_DCSURF_FLIP_CONTROL, SURFACE_UPDATE_LOCK, mask_sh),\ + HUBP_SF(HUBP0_DCSURF_PRI_VIEWPORT_DIMENSION, PRI_VIEWPORT_WIDTH, mask_sh),\ + HUBP_SF(HUBP0_DCSURF_PRI_VIEWPORT_DIMENSION, PRI_VIEWPORT_HEIGHT, mask_sh),\ + HUBP_SF(HUBP0_DCSURF_PRI_VIEWPORT_START, PRI_VIEWPORT_X_START, mask_sh),\ + HUBP_SF(HUBP0_DCSURF_PRI_VIEWPORT_START, PRI_VIEWPORT_Y_START, mask_sh),\ + HUBP_SF(HUBP0_DCSURF_SEC_VIEWPORT_DIMENSION, SEC_VIEWPORT_WIDTH, mask_sh),\ + HUBP_SF(HUBP0_DCSURF_SEC_VIEWPORT_DIMENSION, SEC_VIEWPORT_HEIGHT, mask_sh),\ + HUBP_SF(HUBP0_DCSURF_SEC_VIEWPORT_START, SEC_VIEWPORT_X_START, mask_sh),\ + HUBP_SF(HUBP0_DCSURF_SEC_VIEWPORT_START, SEC_VIEWPORT_Y_START, mask_sh),\ + HUBP_SF(HUBP0_DCSURF_PRI_VIEWPORT_DIMENSION_C, PRI_VIEWPORT_WIDTH_C, mask_sh),\ + HUBP_SF(HUBP0_DCSURF_PRI_VIEWPORT_DIMENSION_C, PRI_VIEWPORT_HEIGHT_C, mask_sh),\ + HUBP_SF(HUBP0_DCSURF_PRI_VIEWPORT_START_C, PRI_VIEWPORT_X_START_C, mask_sh),\ + HUBP_SF(HUBP0_DCSURF_PRI_VIEWPORT_START_C, PRI_VIEWPORT_Y_START_C, mask_sh),\ + HUBP_SF(HUBPREQ0_DCSURF_PRIMARY_SURFACE_ADDRESS_HIGH, PRIMARY_SURFACE_ADDRESS_HIGH, mask_sh),\ + HUBP_SF(HUBPREQ0_DCSURF_PRIMARY_SURFACE_ADDRESS, PRIMARY_SURFACE_ADDRESS, mask_sh),\ + HUBP_SF(HUBPREQ0_DCSURF_SECONDARY_SURFACE_ADDRESS_HIGH, SECONDARY_SURFACE_ADDRESS_HIGH, mask_sh),\ + HUBP_SF(HUBPREQ0_DCSURF_SECONDARY_SURFACE_ADDRESS, SECONDARY_SURFACE_ADDRESS, mask_sh),\ + HUBP_SF(HUBPREQ0_DCSURF_PRIMARY_META_SURFACE_ADDRESS_HIGH, PRIMARY_META_SURFACE_ADDRESS_HIGH, mask_sh),\ + HUBP_SF(HUBPREQ0_DCSURF_PRIMARY_META_SURFACE_ADDRESS, PRIMARY_META_SURFACE_ADDRESS, mask_sh),\ + HUBP_SF(HUBPREQ0_DCSURF_SECONDARY_META_SURFACE_ADDRESS_HIGH, SECONDARY_META_SURFACE_ADDRESS_HIGH, mask_sh),\ + HUBP_SF(HUBPREQ0_DCSURF_SECONDARY_META_SURFACE_ADDRESS, SECONDARY_META_SURFACE_ADDRESS, mask_sh),\ + HUBP_SF(HUBPREQ0_DCSURF_PRIMARY_SURFACE_ADDRESS_HIGH_C, PRIMARY_SURFACE_ADDRESS_HIGH_C, mask_sh),\ + HUBP_SF(HUBPREQ0_DCSURF_PRIMARY_SURFACE_ADDRESS_C, PRIMARY_SURFACE_ADDRESS_C, mask_sh),\ + HUBP_SF(HUBPREQ0_DCSURF_PRIMARY_META_SURFACE_ADDRESS_HIGH_C, PRIMARY_META_SURFACE_ADDRESS_HIGH_C, mask_sh),\ + HUBP_SF(HUBPREQ0_DCSURF_PRIMARY_META_SURFACE_ADDRESS_C, PRIMARY_META_SURFACE_ADDRESS_C, mask_sh),\ + HUBP_SF(HUBPREQ0_DCSURF_SURFACE_INUSE, SURFACE_INUSE_ADDRESS, mask_sh),\ + HUBP_SF(HUBPREQ0_DCSURF_SURFACE_INUSE_HIGH, SURFACE_INUSE_ADDRESS_HIGH, mask_sh),\ + HUBP_SF(HUBPREQ0_DCSURF_SURFACE_INUSE_C, SURFACE_INUSE_ADDRESS_C, mask_sh),\ + HUBP_SF(HUBPREQ0_DCSURF_SURFACE_INUSE_HIGH_C, SURFACE_INUSE_ADDRESS_HIGH_C, mask_sh),\ + HUBP_SF(HUBPREQ0_DCSURF_SURFACE_EARLIEST_INUSE, SURFACE_EARLIEST_INUSE_ADDRESS, mask_sh),\ + HUBP_SF(HUBPREQ0_DCSURF_SURFACE_EARLIEST_INUSE_HIGH, SURFACE_EARLIEST_INUSE_ADDRESS_HIGH, mask_sh),\ + HUBP_SF(HUBPREQ0_DCSURF_SURFACE_EARLIEST_INUSE_C, SURFACE_EARLIEST_INUSE_ADDRESS_C, mask_sh),\ + HUBP_SF(HUBPREQ0_DCSURF_SURFACE_EARLIEST_INUSE_HIGH_C, SURFACE_EARLIEST_INUSE_ADDRESS_HIGH_C, mask_sh),\ + HUBP_SF(HUBPREQ0_DCSURF_SURFACE_CONTROL, PRIMARY_SURFACE_TMZ, mask_sh),\ + HUBP_SF(HUBPREQ0_DCSURF_SURFACE_CONTROL, PRIMARY_SURFACE_DCC_EN, mask_sh),\ + HUBP_SF(HUBPREQ0_DCSURF_SURFACE_CONTROL, PRIMARY_SURFACE_DCC_IND_64B_BLK, mask_sh),\ + HUBP_SF(HUBPRET0_HUBPRET_CONTROL, DET_BUF_PLANE1_BASE_ADDRESS, mask_sh),\ + HUBP_SF(HUBPRET0_HUBPRET_CONTROL, CROSSBAR_SRC_CB_B, mask_sh),\ + HUBP_SF(HUBPRET0_HUBPRET_CONTROL, CROSSBAR_SRC_CR_R, mask_sh),\ + HUBP_SF(HUBPREQ0_DCN_EXPANSION_MODE, DRQ_EXPANSION_MODE, mask_sh),\ + HUBP_SF(HUBPREQ0_DCN_EXPANSION_MODE, PRQ_EXPANSION_MODE, mask_sh),\ + HUBP_SF(HUBPREQ0_DCN_EXPANSION_MODE, MRQ_EXPANSION_MODE, mask_sh),\ + HUBP_SF(HUBPREQ0_DCN_EXPANSION_MODE, CRQ_EXPANSION_MODE, mask_sh),\ + HUBP_SF(HUBP0_DCHUBP_REQ_SIZE_CONFIG, CHUNK_SIZE, mask_sh),\ + HUBP_SF(HUBP0_DCHUBP_REQ_SIZE_CONFIG, MIN_CHUNK_SIZE, mask_sh),\ + HUBP_SF(HUBP0_DCHUBP_REQ_SIZE_CONFIG, META_CHUNK_SIZE, mask_sh),\ + HUBP_SF(HUBP0_DCHUBP_REQ_SIZE_CONFIG, MIN_META_CHUNK_SIZE, mask_sh),\ + HUBP_SF(HUBP0_DCHUBP_REQ_SIZE_CONFIG, DPTE_GROUP_SIZE, mask_sh),\ + HUBP_SF(HUBP0_DCHUBP_REQ_SIZE_CONFIG, MPTE_GROUP_SIZE, mask_sh),\ + HUBP_SF(HUBP0_DCHUBP_REQ_SIZE_CONFIG, SWATH_HEIGHT, mask_sh),\ + HUBP_SF(HUBP0_DCHUBP_REQ_SIZE_CONFIG, PTE_ROW_HEIGHT_LINEAR, mask_sh),\ + HUBP_SF(HUBP0_DCHUBP_REQ_SIZE_CONFIG_C, CHUNK_SIZE_C, mask_sh),\ + HUBP_SF(HUBP0_DCHUBP_REQ_SIZE_CONFIG_C, MIN_CHUNK_SIZE_C, mask_sh),\ + HUBP_SF(HUBP0_DCHUBP_REQ_SIZE_CONFIG_C, META_CHUNK_SIZE_C, mask_sh),\ + HUBP_SF(HUBP0_DCHUBP_REQ_SIZE_CONFIG_C, MIN_META_CHUNK_SIZE_C, mask_sh),\ + HUBP_SF(HUBP0_DCHUBP_REQ_SIZE_CONFIG_C, DPTE_GROUP_SIZE_C, mask_sh),\ + HUBP_SF(HUBP0_DCHUBP_REQ_SIZE_CONFIG_C, MPTE_GROUP_SIZE_C, mask_sh),\ + HUBP_SF(HUBP0_DCHUBP_REQ_SIZE_CONFIG_C, SWATH_HEIGHT_C, mask_sh),\ + HUBP_SF(HUBP0_DCHUBP_REQ_SIZE_CONFIG_C, PTE_ROW_HEIGHT_LINEAR_C, mask_sh),\ + HUBP_SF(HUBPREQ0_BLANK_OFFSET_0, REFCYC_H_BLANK_END, mask_sh),\ + HUBP_SF(HUBPREQ0_BLANK_OFFSET_0, DLG_V_BLANK_END, mask_sh),\ + HUBP_SF(HUBPREQ0_BLANK_OFFSET_1, MIN_DST_Y_NEXT_START, mask_sh),\ + HUBP_SF(HUBPREQ0_DST_DIMENSIONS, REFCYC_PER_HTOTAL, mask_sh),\ + HUBP_SF(HUBPREQ0_DST_AFTER_SCALER, REFCYC_X_AFTER_SCALER, mask_sh),\ + HUBP_SF(HUBPREQ0_DST_AFTER_SCALER, DST_Y_AFTER_SCALER, mask_sh),\ + HUBP_SF(HUBPREQ0_VBLANK_PARAMETERS_0, DST_Y_PER_VM_VBLANK, mask_sh),\ + HUBP_SF(HUBPREQ0_VBLANK_PARAMETERS_0, DST_Y_PER_ROW_VBLANK, mask_sh),\ + HUBP_SF(HUBPREQ0_REF_FREQ_TO_PIX_FREQ, REF_FREQ_TO_PIX_FREQ, mask_sh),\ + HUBP_SF(HUBPREQ0_VBLANK_PARAMETERS_1, REFCYC_PER_PTE_GROUP_VBLANK_L, mask_sh),\ + HUBP_SF(HUBPREQ0_VBLANK_PARAMETERS_3, REFCYC_PER_META_CHUNK_VBLANK_L, mask_sh),\ + HUBP_SF(HUBPREQ0_NOM_PARAMETERS_0, DST_Y_PER_PTE_ROW_NOM_L, mask_sh),\ + HUBP_SF(HUBPREQ0_NOM_PARAMETERS_1, REFCYC_PER_PTE_GROUP_NOM_L, mask_sh),\ + HUBP_SF(HUBPREQ0_NOM_PARAMETERS_4, DST_Y_PER_META_ROW_NOM_L, mask_sh),\ + HUBP_SF(HUBPREQ0_NOM_PARAMETERS_5, REFCYC_PER_META_CHUNK_NOM_L, mask_sh),\ + HUBP_SF(HUBPREQ0_PER_LINE_DELIVERY_PRE, REFCYC_PER_LINE_DELIVERY_PRE_L, mask_sh),\ + HUBP_SF(HUBPREQ0_PER_LINE_DELIVERY_PRE, REFCYC_PER_LINE_DELIVERY_PRE_C, mask_sh),\ + HUBP_SF(HUBPREQ0_PER_LINE_DELIVERY, REFCYC_PER_LINE_DELIVERY_L, mask_sh),\ + HUBP_SF(HUBPREQ0_PER_LINE_DELIVERY, REFCYC_PER_LINE_DELIVERY_C, mask_sh),\ + HUBP_SF(HUBPREQ0_VBLANK_PARAMETERS_2, REFCYC_PER_PTE_GROUP_VBLANK_C, mask_sh),\ + HUBP_SF(HUBPREQ0_VBLANK_PARAMETERS_4, REFCYC_PER_META_CHUNK_VBLANK_C, mask_sh),\ + HUBP_SF(HUBPREQ0_NOM_PARAMETERS_2, DST_Y_PER_PTE_ROW_NOM_C, mask_sh),\ + HUBP_SF(HUBPREQ0_NOM_PARAMETERS_3, REFCYC_PER_PTE_GROUP_NOM_C, mask_sh),\ + HUBP_SF(HUBPREQ0_NOM_PARAMETERS_6, DST_Y_PER_META_ROW_NOM_C, mask_sh),\ + HUBP_SF(HUBPREQ0_NOM_PARAMETERS_7, REFCYC_PER_META_CHUNK_NOM_C, mask_sh),\ + HUBP_SF(HUBPREQ0_DCN_TTU_QOS_WM, QoS_LEVEL_LOW_WM, mask_sh),\ + HUBP_SF(HUBPREQ0_DCN_TTU_QOS_WM, QoS_LEVEL_HIGH_WM, mask_sh),\ + HUBP_SF(HUBPREQ0_DCN_GLOBAL_TTU_CNTL, MIN_TTU_VBLANK, mask_sh),\ + HUBP_SF(HUBPREQ0_DCN_GLOBAL_TTU_CNTL, QoS_LEVEL_FLIP, mask_sh),\ + HUBP_SF(HUBPREQ0_DCN_SURF0_TTU_CNTL0, REFCYC_PER_REQ_DELIVERY, mask_sh),\ + HUBP_SF(HUBPREQ0_DCN_SURF0_TTU_CNTL0, QoS_LEVEL_FIXED, mask_sh),\ + HUBP_SF(HUBPREQ0_DCN_SURF0_TTU_CNTL0, QoS_RAMP_DISABLE, mask_sh),\ + HUBP_SF(HUBPREQ0_DCN_SURF0_TTU_CNTL1, REFCYC_PER_REQ_DELIVERY_PRE, mask_sh),\ + HUBP_SF(HUBPREQ0_DCN_VM_MX_L1_TLB_CNTL, ENABLE_L1_TLB, mask_sh),\ + HUBP_SF(HUBPREQ0_DCN_VM_MX_L1_TLB_CNTL, SYSTEM_ACCESS_MODE, mask_sh) + +#define HUBP_MASK_SH_LIST_DCN10(mask_sh)\ + HUBP_MASK_SH_LIST_DCN(mask_sh),\ + HUBP_SF(HUBPREQ0_PREFETCH_SETTINS, DST_Y_PREFETCH, mask_sh),\ + HUBP_SF(HUBPREQ0_PREFETCH_SETTINS, VRATIO_PREFETCH, mask_sh),\ + HUBP_SF(HUBPREQ0_PREFETCH_SETTINS_C, VRATIO_PREFETCH_C, mask_sh),\ + HUBP_SF(HUBPREQ0_DCN_VM_CONTEXT0_PAGE_TABLE_BASE_ADDR_MSB, VM_CONTEXT0_PAGE_TABLE_BASE_ADDR_MSB, mask_sh),\ + HUBP_SF(HUBPREQ0_DCN_VM_CONTEXT0_PAGE_TABLE_BASE_ADDR_LSB, VM_CONTEXT0_PAGE_TABLE_BASE_ADDR_LSB, mask_sh),\ + HUBP_SF(HUBPREQ0_DCN_VM_CONTEXT0_PAGE_TABLE_START_ADDR_MSB, VM_CONTEXT0_PAGE_TABLE_START_ADDR_MSB, mask_sh),\ + HUBP_SF(HUBPREQ0_DCN_VM_CONTEXT0_PAGE_TABLE_START_ADDR_LSB, VM_CONTEXT0_PAGE_TABLE_START_ADDR_LSB, mask_sh),\ + HUBP_SF(HUBPREQ0_DCN_VM_CONTEXT0_PAGE_TABLE_END_ADDR_MSB, VM_CONTEXT0_PAGE_TABLE_END_ADDR_MSB, mask_sh),\ + HUBP_SF(HUBPREQ0_DCN_VM_CONTEXT0_PAGE_TABLE_END_ADDR_LSB, VM_CONTEXT0_PAGE_TABLE_END_ADDR_LSB, mask_sh),\ + HUBP_SF(HUBPREQ0_DCN_VM_CONTEXT0_PROTECTION_FAULT_DEFAULT_ADDR_MSB, VM_CONTEXT0_PROTECTION_FAULT_DEFAULT_ADDR_MSB, mask_sh),\ + HUBP_SF(HUBPREQ0_DCN_VM_CONTEXT0_PROTECTION_FAULT_DEFAULT_ADDR_MSB, VM_CONTEXT0_PROTECTION_FAULT_DEFAULT_SYSTEM, mask_sh),\ + HUBP_SF(HUBPREQ0_DCN_VM_CONTEXT0_PROTECTION_FAULT_DEFAULT_ADDR_LSB, VM_CONTEXT0_PROTECTION_FAULT_DEFAULT_ADDR_LSB, mask_sh),\ + HUBP_SF(HUBPREQ0_DCN_VM_SYSTEM_APERTURE_LOW_ADDR_MSB, MC_VM_SYSTEM_APERTURE_LOW_ADDR_MSB, mask_sh),\ + HUBP_SF(HUBPREQ0_DCN_VM_SYSTEM_APERTURE_LOW_ADDR_LSB, MC_VM_SYSTEM_APERTURE_LOW_ADDR_LSB, mask_sh),\ + HUBP_SF(HUBPREQ0_DCN_VM_SYSTEM_APERTURE_HIGH_ADDR_MSB, MC_VM_SYSTEM_APERTURE_HIGH_ADDR_MSB, mask_sh),\ + HUBP_SF(HUBPREQ0_DCN_VM_SYSTEM_APERTURE_HIGH_ADDR_LSB, MC_VM_SYSTEM_APERTURE_HIGH_ADDR_LSB, mask_sh),\ + HUBP_SF(DCHUBBUB_SDPIF_FB_BASE, SDPIF_FB_BASE, mask_sh),\ + HUBP_SF(DCHUBBUB_SDPIF_FB_OFFSET, SDPIF_FB_OFFSET, mask_sh),\ + HUBP_SF(HUBPREQ0_DCN_VM_SYSTEM_APERTURE_DEFAULT_ADDR_MSB, MC_VM_SYSTEM_APERTURE_DEFAULT_SYSTEM, mask_sh),\ + HUBP_SF(HUBPREQ0_DCN_VM_SYSTEM_APERTURE_DEFAULT_ADDR_MSB, MC_VM_SYSTEM_APERTURE_DEFAULT_ADDR_MSB, mask_sh),\ + HUBP_SF(HUBPREQ0_DCN_VM_SYSTEM_APERTURE_DEFAULT_ADDR_LSB, MC_VM_SYSTEM_APERTURE_DEFAULT_ADDR_LSB, mask_sh),\ + HUBP_SF(HUBPREQ0_CURSOR_SETTINS, CURSOR0_DST_Y_OFFSET, mask_sh), \ + HUBP_SF(HUBPREQ0_CURSOR_SETTINS, CURSOR0_CHUNK_HDL_ADJUST, mask_sh), \ + HUBP_SF(CURSOR0_CURSOR_SURFACE_ADDRESS_HIGH, CURSOR_SURFACE_ADDRESS_HIGH, mask_sh), \ + HUBP_SF(CURSOR0_CURSOR_SURFACE_ADDRESS, CURSOR_SURFACE_ADDRESS, mask_sh), \ + HUBP_SF(CURSOR0_CURSOR_SIZE, CURSOR_WIDTH, mask_sh), \ + HUBP_SF(CURSOR0_CURSOR_SIZE, CURSOR_HEIGHT, mask_sh), \ + HUBP_SF(CURSOR0_CURSOR_CONTROL, CURSOR_MODE, mask_sh), \ + HUBP_SF(CURSOR0_CURSOR_CONTROL, CURSOR_2X_MAGNIFY, mask_sh), \ + HUBP_SF(CURSOR0_CURSOR_CONTROL, CURSOR_PITCH, mask_sh), \ + HUBP_SF(CURSOR0_CURSOR_CONTROL, CURSOR_LINES_PER_CHUNK, mask_sh), \ + HUBP_SF(CURSOR0_CURSOR_CONTROL, CURSOR_ENABLE, mask_sh), \ + HUBP_SF(CURSOR0_CURSOR_POSITION, CURSOR_X_POSITION, mask_sh), \ + HUBP_SF(CURSOR0_CURSOR_POSITION, CURSOR_Y_POSITION, mask_sh), \ + HUBP_SF(CURSOR0_CURSOR_HOT_SPOT, CURSOR_HOT_SPOT_X, mask_sh), \ + HUBP_SF(CURSOR0_CURSOR_HOT_SPOT, CURSOR_HOT_SPOT_Y, mask_sh), \ + HUBP_SF(CURSOR0_CURSOR_DST_OFFSET, CURSOR_DST_X_OFFSET, mask_sh) + +#define DCN_HUBP_REG_FIELD_LIST(type) \ type HUBP_BLANK_EN;\ type HUBP_TTU_DISABLE;\ type HUBP_NO_OUTSTANDING_REQ;\ @@ -576,19 +573,23 @@ struct dcn_mi_registers { type CURSOR_DST_X_OFFSET; \ type OUTPUT_FP +struct dcn_mi_registers { + HUBP_COMMON_REG_VARIABLE_LIST; +}; + struct dcn_mi_shift { - DCN_MI_REG_FIELD_LIST(uint8_t); + DCN_HUBP_REG_FIELD_LIST(uint8_t); }; struct dcn_mi_mask { - DCN_MI_REG_FIELD_LIST(uint32_t); + DCN_HUBP_REG_FIELD_LIST(uint32_t); }; struct dcn10_hubp { struct hubp base; - const struct dcn_mi_registers *mi_regs; - const struct dcn_mi_shift *mi_shift; - const struct dcn_mi_mask *mi_mask; + const struct dcn_mi_registers *hubp_regs; + const struct dcn_mi_shift *hubp_shift; + const struct dcn_mi_mask *hubp_mask; }; void hubp1_program_surface_config( @@ -610,11 +611,11 @@ void hubp1_program_requestor( struct _vcs_dpi_display_rq_regs_st *rq_regs); void hubp1_program_pixel_format( - struct dcn10_hubp *hubp, + struct hubp *hubp, enum surface_pixel_format format); void hubp1_program_size_and_rotation( - struct dcn10_hubp *hubp, + struct hubp *hubp, enum dc_rotation_angle rotation, enum surface_pixel_format format, const union plane_size *plane_size, @@ -622,7 +623,7 @@ void hubp1_program_size_and_rotation( bool horizontal_mirror); void hubp1_program_tiling( - struct dcn10_hubp *hubp, + struct hubp *hubp, const union dc_tiling_info *info, const enum surface_pixel_format pixel_format); @@ -656,9 +657,9 @@ void dcn10_hubp_construct( struct dcn10_hubp *hubp1, struct dc_context *ctx, uint32_t inst, - const struct dcn_mi_registers *mi_regs, - const struct dcn_mi_shift *mi_shift, - const struct dcn_mi_mask *mi_mask); + const struct dcn_mi_registers *hubp_regs, + const struct dcn_mi_shift *hubp_shift, + const struct dcn_mi_mask *hubp_mask); struct dcn_hubp_state { @@ -680,4 +681,6 @@ struct dcn_hubp_state { void hubp1_read_state(struct dcn10_hubp *hubp1, struct dcn_hubp_state *s); +enum cursor_pitch hubp1_get_cursor_pitch(unsigned int pitch); + #endif diff --git a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hw_sequencer.c b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hw_sequencer.c index 05dc01e54531..82572863acab 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hw_sequencer.c +++ b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hw_sequencer.c @@ -31,7 +31,8 @@ #include "dce110/dce110_hw_sequencer.h" #include "dce/dce_hwseq.h" #include "abm.h" -#include "dcn10/dcn10_timing_generator.h" +#include "dmcu.h" +#include "dcn10_optc.h" #include "dcn10/dcn10_dpp.h" #include "dcn10/dcn10_mpc.h" #include "timing_generator.h" @@ -41,6 +42,8 @@ #include "reg_helper.h" #include "custom_float.h" #include "dcn10_hubp.h" +#include "dcn10_hubbub.h" +#include "dcn10_cm_common.h" #define CTX \ hws->ctx @@ -51,18 +54,8 @@ #define FN(reg_name, field_name) \ hws->shifts->field_name, hws->masks->field_name -static void log_mpc_crc(struct dc *dc) -{ - struct dc_context *dc_ctx = dc->ctx; - struct dce_hwseq *hws = dc->hwseq; - - if (REG(MPC_CRC_RESULT_GB)) - DTN_INFO("MPC_CRC_RESULT_GB:%d MPC_CRC_RESULT_C:%d MPC_CRC_RESULT_AR:%d\n", - REG_READ(MPC_CRC_RESULT_GB), REG_READ(MPC_CRC_RESULT_C), REG_READ(MPC_CRC_RESULT_AR)); - if (REG(DPP_TOP0_DPP_CRC_VAL_B_A)) - DTN_INFO("DPP_TOP0_DPP_CRC_VAL_B_A:%d DPP_TOP0_DPP_CRC_VAL_R_G:%d\n", - REG_READ(DPP_TOP0_DPP_CRC_VAL_B_A), REG_READ(DPP_TOP0_DPP_CRC_VAL_R_G)); -} +#define DTN_INFO_MICRO_SEC(ref_cycle) \ + print_microsec(dc_ctx, ref_cycle) void print_microsec(struct dc_context *dc_ctx, uint32_t ref_cycle) { @@ -75,67 +68,27 @@ void print_microsec(struct dc_context *dc_ctx, uint32_t ref_cycle) us_x10 % frac); } -#define DTN_INFO_MICRO_SEC(ref_cycle) \ - print_microsec(dc_ctx, ref_cycle) -struct dcn_hubbub_wm_set { - uint32_t wm_set; - uint32_t data_urgent; - uint32_t pte_meta_urgent; - uint32_t sr_enter; - uint32_t sr_exit; - uint32_t dram_clk_chanage; -}; +static void log_mpc_crc(struct dc *dc) +{ + struct dc_context *dc_ctx = dc->ctx; + struct dce_hwseq *hws = dc->hwseq; -struct dcn_hubbub_wm { - struct dcn_hubbub_wm_set sets[4]; -}; + if (REG(MPC_CRC_RESULT_GB)) + DTN_INFO("MPC_CRC_RESULT_GB:%d MPC_CRC_RESULT_C:%d MPC_CRC_RESULT_AR:%d\n", + REG_READ(MPC_CRC_RESULT_GB), REG_READ(MPC_CRC_RESULT_C), REG_READ(MPC_CRC_RESULT_AR)); + if (REG(DPP_TOP0_DPP_CRC_VAL_B_A)) + DTN_INFO("DPP_TOP0_DPP_CRC_VAL_B_A:%d DPP_TOP0_DPP_CRC_VAL_R_G:%d\n", + REG_READ(DPP_TOP0_DPP_CRC_VAL_B_A), REG_READ(DPP_TOP0_DPP_CRC_VAL_R_G)); +} -static void dcn10_hubbub_wm_read_state(struct dce_hwseq *hws, - struct dcn_hubbub_wm *wm) -{ - struct dcn_hubbub_wm_set *s; - - s = &wm->sets[0]; - s->wm_set = 0; - s->data_urgent = REG_READ(DCHUBBUB_ARB_DATA_URGENCY_WATERMARK_A); - s->pte_meta_urgent = REG_READ(DCHUBBUB_ARB_PTE_META_URGENCY_WATERMARK_A); - s->sr_enter = REG_READ(DCHUBBUB_ARB_ALLOW_SR_ENTER_WATERMARK_A); - s->sr_exit = REG_READ(DCHUBBUB_ARB_ALLOW_SR_EXIT_WATERMARK_A); - s->dram_clk_chanage = REG_READ(DCHUBBUB_ARB_ALLOW_DRAM_CLK_CHANGE_WATERMARK_A); - - s = &wm->sets[1]; - s->wm_set = 1; - s->data_urgent = REG_READ(DCHUBBUB_ARB_DATA_URGENCY_WATERMARK_B); - s->pte_meta_urgent = REG_READ(DCHUBBUB_ARB_PTE_META_URGENCY_WATERMARK_B); - s->sr_enter = REG_READ(DCHUBBUB_ARB_ALLOW_SR_ENTER_WATERMARK_B); - s->sr_exit = REG_READ(DCHUBBUB_ARB_ALLOW_SR_EXIT_WATERMARK_B); - s->dram_clk_chanage = REG_READ(DCHUBBUB_ARB_ALLOW_DRAM_CLK_CHANGE_WATERMARK_B); - - s = &wm->sets[2]; - s->wm_set = 2; - s->data_urgent = REG_READ(DCHUBBUB_ARB_DATA_URGENCY_WATERMARK_C); - s->pte_meta_urgent = REG_READ(DCHUBBUB_ARB_PTE_META_URGENCY_WATERMARK_C); - s->sr_enter = REG_READ(DCHUBBUB_ARB_ALLOW_SR_ENTER_WATERMARK_C); - s->sr_exit = REG_READ(DCHUBBUB_ARB_ALLOW_SR_EXIT_WATERMARK_C); - s->dram_clk_chanage = REG_READ(DCHUBBUB_ARB_ALLOW_DRAM_CLK_CHANGE_WATERMARK_C); - - s = &wm->sets[3]; - s->wm_set = 3; - s->data_urgent = REG_READ(DCHUBBUB_ARB_DATA_URGENCY_WATERMARK_D); - s->pte_meta_urgent = REG_READ(DCHUBBUB_ARB_PTE_META_URGENCY_WATERMARK_D); - s->sr_enter = REG_READ(DCHUBBUB_ARB_ALLOW_SR_ENTER_WATERMARK_D); - s->sr_exit = REG_READ(DCHUBBUB_ARB_ALLOW_SR_EXIT_WATERMARK_D); - s->dram_clk_chanage = REG_READ(DCHUBBUB_ARB_ALLOW_DRAM_CLK_CHANGE_WATERMARK_D); -} - -static void dcn10_log_hubbub_state(struct dc *dc) +void dcn10_log_hubbub_state(struct dc *dc) { struct dc_context *dc_ctx = dc->ctx; struct dcn_hubbub_wm wm; int i; - dcn10_hubbub_wm_read_state(dc->hwseq, &wm); + hubbub1_wm_read_state(dc->res_pool->hubbub, &wm); DTN_INFO("HUBBUB WM: \t data_urgent \t pte_meta_urgent \t " "sr_enter \t sr_exit \t dram_clk_change \n"); @@ -156,7 +109,7 @@ static void dcn10_log_hubbub_state(struct dc *dc) DTN_INFO("\n"); } -static void dcn10_log_hw_state(struct dc *dc) +void dcn10_log_hw_state(struct dc *dc) { struct dc_context *dc_ctx = dc->ctx; struct resource_pool *pool = dc->res_pool; @@ -206,7 +159,7 @@ static void dcn10_log_hw_state(struct dc *dc) struct timing_generator *tg = pool->timing_generators[i]; struct dcn_otg_state s = {0}; - tgn10_read_otg_state(DCN10TG_FROM_TG(tg), &s); + optc1_read_otg_state(DCN10TG_FROM_TG(tg), &s); //only print if OTG master is enabled if ((s.otg_enabled & 1) == 0) @@ -240,97 +193,6 @@ static void dcn10_log_hw_state(struct dc *dc) DTN_INFO_END(); } -static void verify_allow_pstate_change_high( - struct dce_hwseq *hws) -{ - /* pstate latency is ~20us so if we wait over 40us and pstate allow - * still not asserted, we are probably stuck and going to hang - * - * TODO: Figure out why it takes ~100us on linux - * pstate takes around ~100us on linux. Unknown currently as to - * why it takes that long on linux - */ - static unsigned int pstate_wait_timeout_us = 200; - static unsigned int pstate_wait_expected_timeout_us = 40; - static unsigned int max_sampled_pstate_wait_us; /* data collection */ - static bool forced_pstate_allow; /* help with revert wa */ - static bool should_log_hw_state; /* prevent hw state log by default */ - - unsigned int debug_index = 0x7; - unsigned int debug_data; - unsigned int i; - - if (forced_pstate_allow) { - /* we hacked to force pstate allow to prevent hang last time - * we verify_allow_pstate_change_high. so disable force - * here so we can check status - */ - REG_UPDATE_2(DCHUBBUB_ARB_DRAM_STATE_CNTL, - DCHUBBUB_ARB_ALLOW_PSTATE_CHANGE_FORCE_VALUE, 0, - DCHUBBUB_ARB_ALLOW_PSTATE_CHANGE_FORCE_ENABLE, 0); - forced_pstate_allow = false; - } - - /* description "3-0: Pipe0 cursor0 QOS - * 7-4: Pipe1 cursor0 QOS - * 11-8: Pipe2 cursor0 QOS - * 15-12: Pipe3 cursor0 QOS - * 16: Pipe0 Plane0 Allow Pstate Change - * 17: Pipe1 Plane0 Allow Pstate Change - * 18: Pipe2 Plane0 Allow Pstate Change - * 19: Pipe3 Plane0 Allow Pstate Change - * 20: Pipe0 Plane1 Allow Pstate Change - * 21: Pipe1 Plane1 Allow Pstate Change - * 22: Pipe2 Plane1 Allow Pstate Change - * 23: Pipe3 Plane1 Allow Pstate Change - * 24: Pipe0 cursor0 Allow Pstate Change - * 25: Pipe1 cursor0 Allow Pstate Change - * 26: Pipe2 cursor0 Allow Pstate Change - * 27: Pipe3 cursor0 Allow Pstate Change - * 28: WB0 Allow Pstate Change - * 29: WB1 Allow Pstate Change - * 30: Arbiter's allow_pstate_change - * 31: SOC pstate change request - */ - - REG_WRITE(DCHUBBUB_TEST_DEBUG_INDEX, debug_index); - - for (i = 0; i < pstate_wait_timeout_us; i++) { - debug_data = REG_READ(DCHUBBUB_TEST_DEBUG_DATA); - - if (debug_data & (1 << 30)) { - - if (i > pstate_wait_expected_timeout_us) - dm_logger_write(hws->ctx->logger, LOG_WARNING, - "pstate took longer than expected ~%dus\n", - i); - - return; - } - if (max_sampled_pstate_wait_us < i) - max_sampled_pstate_wait_us = i; - - udelay(1); - } - - /* force pstate allow to prevent system hang - * and break to debugger to investigate - */ - REG_UPDATE_2(DCHUBBUB_ARB_DRAM_STATE_CNTL, - DCHUBBUB_ARB_ALLOW_PSTATE_CHANGE_FORCE_VALUE, 1, - DCHUBBUB_ARB_ALLOW_PSTATE_CHANGE_FORCE_ENABLE, 1); - forced_pstate_allow = true; - - if (should_log_hw_state) { - dcn10_log_hw_state(hws->ctx->dc); - } - - dm_logger_write(hws->ctx->logger, LOG_WARNING, - "pstate TEST_DEBUG_DATA: 0x%X\n", - debug_data); - BREAK_TO_DEBUGGER(); -} - static void enable_dppclk( struct dce_hwseq *hws, uint8_t plane_id, @@ -432,312 +294,6 @@ static void dpp_pg_control( } } -static uint32_t convert_and_clamp( - uint32_t wm_ns, - uint32_t refclk_mhz, - uint32_t clamp_value) -{ - uint32_t ret_val = 0; - ret_val = wm_ns * refclk_mhz; - ret_val /= 1000; - - if (ret_val > clamp_value) - ret_val = clamp_value; - - return ret_val; -} - -static void program_watermarks( - struct dce_hwseq *hws, - struct dcn_watermark_set *watermarks, - unsigned int refclk_mhz) -{ - uint32_t force_en = hws->ctx->dc->debug.disable_stutter ? 1 : 0; - /* - * Need to clamp to max of the register values (i.e. no wrap) - * for dcn1, all wm registers are 21-bit wide - */ - uint32_t prog_wm_value; - - REG_UPDATE(DCHUBBUB_ARB_WATERMARK_CHANGE_CNTL, - DCHUBBUB_ARB_WATERMARK_CHANGE_REQUEST, 0); - - /* Repeat for water mark set A, B, C and D. */ - /* clock state A */ - prog_wm_value = convert_and_clamp(watermarks->a.urgent_ns, - refclk_mhz, 0x1fffff); - REG_WRITE(DCHUBBUB_ARB_DATA_URGENCY_WATERMARK_A, prog_wm_value); - - dm_logger_write(hws->ctx->logger, LOG_BANDWIDTH_CALCS, - "URGENCY_WATERMARK_A calculated =%d\n" - "HW register value = 0x%x\n", - watermarks->a.urgent_ns, prog_wm_value); - - prog_wm_value = convert_and_clamp(watermarks->a.pte_meta_urgent_ns, - refclk_mhz, 0x1fffff); - REG_WRITE(DCHUBBUB_ARB_PTE_META_URGENCY_WATERMARK_A, prog_wm_value); - dm_logger_write(hws->ctx->logger, LOG_BANDWIDTH_CALCS, - "PTE_META_URGENCY_WATERMARK_A calculated =%d\n" - "HW register value = 0x%x\n", - watermarks->a.pte_meta_urgent_ns, prog_wm_value); - - if (REG(DCHUBBUB_ARB_ALLOW_SR_ENTER_WATERMARK_A)) { - prog_wm_value = convert_and_clamp( - watermarks->a.cstate_pstate.cstate_enter_plus_exit_ns, - refclk_mhz, 0x1fffff); - REG_WRITE(DCHUBBUB_ARB_ALLOW_SR_ENTER_WATERMARK_A, prog_wm_value); - dm_logger_write(hws->ctx->logger, LOG_BANDWIDTH_CALCS, - "SR_ENTER_EXIT_WATERMARK_A calculated =%d\n" - "HW register value = 0x%x\n", - watermarks->a.cstate_pstate.cstate_enter_plus_exit_ns, prog_wm_value); - - - prog_wm_value = convert_and_clamp( - watermarks->a.cstate_pstate.cstate_exit_ns, - refclk_mhz, 0x1fffff); - REG_WRITE(DCHUBBUB_ARB_ALLOW_SR_EXIT_WATERMARK_A, prog_wm_value); - dm_logger_write(hws->ctx->logger, LOG_BANDWIDTH_CALCS, - "SR_EXIT_WATERMARK_A calculated =%d\n" - "HW register value = 0x%x\n", - watermarks->a.cstate_pstate.cstate_exit_ns, prog_wm_value); - } - - prog_wm_value = convert_and_clamp( - watermarks->a.cstate_pstate.pstate_change_ns, - refclk_mhz, 0x1fffff); - REG_WRITE(DCHUBBUB_ARB_ALLOW_DRAM_CLK_CHANGE_WATERMARK_A, prog_wm_value); - dm_logger_write(hws->ctx->logger, LOG_BANDWIDTH_CALCS, - "DRAM_CLK_CHANGE_WATERMARK_A calculated =%d\n" - "HW register value = 0x%x\n\n", - watermarks->a.cstate_pstate.pstate_change_ns, prog_wm_value); - - - /* clock state B */ - prog_wm_value = convert_and_clamp( - watermarks->b.urgent_ns, refclk_mhz, 0x1fffff); - REG_WRITE(DCHUBBUB_ARB_DATA_URGENCY_WATERMARK_B, prog_wm_value); - dm_logger_write(hws->ctx->logger, LOG_BANDWIDTH_CALCS, - "URGENCY_WATERMARK_B calculated =%d\n" - "HW register value = 0x%x\n", - watermarks->b.urgent_ns, prog_wm_value); - - - prog_wm_value = convert_and_clamp( - watermarks->b.pte_meta_urgent_ns, - refclk_mhz, 0x1fffff); - REG_WRITE(DCHUBBUB_ARB_PTE_META_URGENCY_WATERMARK_B, prog_wm_value); - dm_logger_write(hws->ctx->logger, LOG_BANDWIDTH_CALCS, - "PTE_META_URGENCY_WATERMARK_B calculated =%d\n" - "HW register value = 0x%x\n", - watermarks->b.pte_meta_urgent_ns, prog_wm_value); - - - if (REG(DCHUBBUB_ARB_ALLOW_SR_ENTER_WATERMARK_B)) { - prog_wm_value = convert_and_clamp( - watermarks->b.cstate_pstate.cstate_enter_plus_exit_ns, - refclk_mhz, 0x1fffff); - REG_WRITE(DCHUBBUB_ARB_ALLOW_SR_ENTER_WATERMARK_B, prog_wm_value); - dm_logger_write(hws->ctx->logger, LOG_BANDWIDTH_CALCS, - "SR_ENTER_WATERMARK_B calculated =%d\n" - "HW register value = 0x%x\n", - watermarks->b.cstate_pstate.cstate_enter_plus_exit_ns, prog_wm_value); - - - prog_wm_value = convert_and_clamp( - watermarks->b.cstate_pstate.cstate_exit_ns, - refclk_mhz, 0x1fffff); - REG_WRITE(DCHUBBUB_ARB_ALLOW_SR_EXIT_WATERMARK_B, prog_wm_value); - dm_logger_write(hws->ctx->logger, LOG_BANDWIDTH_CALCS, - "SR_EXIT_WATERMARK_B calculated =%d\n" - "HW register value = 0x%x\n", - watermarks->b.cstate_pstate.cstate_exit_ns, prog_wm_value); - } - - prog_wm_value = convert_and_clamp( - watermarks->b.cstate_pstate.pstate_change_ns, - refclk_mhz, 0x1fffff); - REG_WRITE(DCHUBBUB_ARB_ALLOW_DRAM_CLK_CHANGE_WATERMARK_B, prog_wm_value); - dm_logger_write(hws->ctx->logger, LOG_BANDWIDTH_CALCS, - "DRAM_CLK_CHANGE_WATERMARK_B calculated =%d\n\n" - "HW register value = 0x%x\n", - watermarks->b.cstate_pstate.pstate_change_ns, prog_wm_value); - - /* clock state C */ - prog_wm_value = convert_and_clamp( - watermarks->c.urgent_ns, refclk_mhz, 0x1fffff); - REG_WRITE(DCHUBBUB_ARB_DATA_URGENCY_WATERMARK_C, prog_wm_value); - dm_logger_write(hws->ctx->logger, LOG_BANDWIDTH_CALCS, - "URGENCY_WATERMARK_C calculated =%d\n" - "HW register value = 0x%x\n", - watermarks->c.urgent_ns, prog_wm_value); - - - prog_wm_value = convert_and_clamp( - watermarks->c.pte_meta_urgent_ns, - refclk_mhz, 0x1fffff); - REG_WRITE(DCHUBBUB_ARB_PTE_META_URGENCY_WATERMARK_C, prog_wm_value); - dm_logger_write(hws->ctx->logger, LOG_BANDWIDTH_CALCS, - "PTE_META_URGENCY_WATERMARK_C calculated =%d\n" - "HW register value = 0x%x\n", - watermarks->c.pte_meta_urgent_ns, prog_wm_value); - - - if (REG(DCHUBBUB_ARB_ALLOW_SR_ENTER_WATERMARK_C)) { - prog_wm_value = convert_and_clamp( - watermarks->c.cstate_pstate.cstate_enter_plus_exit_ns, - refclk_mhz, 0x1fffff); - REG_WRITE(DCHUBBUB_ARB_ALLOW_SR_ENTER_WATERMARK_C, prog_wm_value); - dm_logger_write(hws->ctx->logger, LOG_BANDWIDTH_CALCS, - "SR_ENTER_WATERMARK_C calculated =%d\n" - "HW register value = 0x%x\n", - watermarks->c.cstate_pstate.cstate_enter_plus_exit_ns, prog_wm_value); - - - prog_wm_value = convert_and_clamp( - watermarks->c.cstate_pstate.cstate_exit_ns, - refclk_mhz, 0x1fffff); - REG_WRITE(DCHUBBUB_ARB_ALLOW_SR_EXIT_WATERMARK_C, prog_wm_value); - dm_logger_write(hws->ctx->logger, LOG_BANDWIDTH_CALCS, - "SR_EXIT_WATERMARK_C calculated =%d\n" - "HW register value = 0x%x\n", - watermarks->c.cstate_pstate.cstate_exit_ns, prog_wm_value); - } - - prog_wm_value = convert_and_clamp( - watermarks->c.cstate_pstate.pstate_change_ns, - refclk_mhz, 0x1fffff); - REG_WRITE(DCHUBBUB_ARB_ALLOW_DRAM_CLK_CHANGE_WATERMARK_C, prog_wm_value); - dm_logger_write(hws->ctx->logger, LOG_BANDWIDTH_CALCS, - "DRAM_CLK_CHANGE_WATERMARK_C calculated =%d\n\n" - "HW register value = 0x%x\n", - watermarks->c.cstate_pstate.pstate_change_ns, prog_wm_value); - - /* clock state D */ - prog_wm_value = convert_and_clamp( - watermarks->d.urgent_ns, refclk_mhz, 0x1fffff); - REG_WRITE(DCHUBBUB_ARB_DATA_URGENCY_WATERMARK_D, prog_wm_value); - dm_logger_write(hws->ctx->logger, LOG_BANDWIDTH_CALCS, - "URGENCY_WATERMARK_D calculated =%d\n" - "HW register value = 0x%x\n", - watermarks->d.urgent_ns, prog_wm_value); - - prog_wm_value = convert_and_clamp( - watermarks->d.pte_meta_urgent_ns, - refclk_mhz, 0x1fffff); - REG_WRITE(DCHUBBUB_ARB_PTE_META_URGENCY_WATERMARK_D, prog_wm_value); - dm_logger_write(hws->ctx->logger, LOG_BANDWIDTH_CALCS, - "PTE_META_URGENCY_WATERMARK_D calculated =%d\n" - "HW register value = 0x%x\n", - watermarks->d.pte_meta_urgent_ns, prog_wm_value); - - - if (REG(DCHUBBUB_ARB_ALLOW_SR_ENTER_WATERMARK_D)) { - prog_wm_value = convert_and_clamp( - watermarks->d.cstate_pstate.cstate_enter_plus_exit_ns, - refclk_mhz, 0x1fffff); - REG_WRITE(DCHUBBUB_ARB_ALLOW_SR_ENTER_WATERMARK_D, prog_wm_value); - dm_logger_write(hws->ctx->logger, LOG_BANDWIDTH_CALCS, - "SR_ENTER_WATERMARK_D calculated =%d\n" - "HW register value = 0x%x\n", - watermarks->d.cstate_pstate.cstate_enter_plus_exit_ns, prog_wm_value); - - - prog_wm_value = convert_and_clamp( - watermarks->d.cstate_pstate.cstate_exit_ns, - refclk_mhz, 0x1fffff); - REG_WRITE(DCHUBBUB_ARB_ALLOW_SR_EXIT_WATERMARK_D, prog_wm_value); - dm_logger_write(hws->ctx->logger, LOG_BANDWIDTH_CALCS, - "SR_EXIT_WATERMARK_D calculated =%d\n" - "HW register value = 0x%x\n", - watermarks->d.cstate_pstate.cstate_exit_ns, prog_wm_value); - } - - - prog_wm_value = convert_and_clamp( - watermarks->d.cstate_pstate.pstate_change_ns, - refclk_mhz, 0x1fffff); - REG_WRITE(DCHUBBUB_ARB_ALLOW_DRAM_CLK_CHANGE_WATERMARK_D, prog_wm_value); - dm_logger_write(hws->ctx->logger, LOG_BANDWIDTH_CALCS, - "DRAM_CLK_CHANGE_WATERMARK_D calculated =%d\n" - "HW register value = 0x%x\n\n", - watermarks->d.cstate_pstate.pstate_change_ns, prog_wm_value); - - REG_UPDATE(DCHUBBUB_ARB_WATERMARK_CHANGE_CNTL, - DCHUBBUB_ARB_WATERMARK_CHANGE_REQUEST, 1); - - REG_UPDATE(DCHUBBUB_ARB_SAT_LEVEL, - DCHUBBUB_ARB_SAT_LEVEL, 60 * refclk_mhz); - REG_UPDATE(DCHUBBUB_ARB_DF_REQ_OUTSTAND, - DCHUBBUB_ARB_MIN_REQ_OUTSTAND, 68); - - REG_UPDATE_2(DCHUBBUB_ARB_DRAM_STATE_CNTL, - DCHUBBUB_ARB_ALLOW_SELF_REFRESH_FORCE_VALUE, 0, - DCHUBBUB_ARB_ALLOW_SELF_REFRESH_FORCE_ENABLE, force_en); - -#if 0 - REG_UPDATE_2(DCHUBBUB_ARB_WATERMARK_CHANGE_CNTL, - DCHUBBUB_ARB_WATERMARK_CHANGE_DONE_INTERRUPT_DISABLE, 1, - DCHUBBUB_ARB_WATERMARK_CHANGE_REQUEST, 1); -#endif -} - - -static void dcn10_update_dchub( - struct dce_hwseq *hws, - struct dchub_init_data *dh_data) -{ - /* TODO: port code from dal2 */ - switch (dh_data->fb_mode) { - case FRAME_BUFFER_MODE_ZFB_ONLY: - /*For ZFB case need to put DCHUB FB BASE and TOP upside down to indicate ZFB mode*/ - REG_UPDATE(DCHUBBUB_SDPIF_FB_TOP, - SDPIF_FB_TOP, 0); - - REG_UPDATE(DCHUBBUB_SDPIF_FB_BASE, - SDPIF_FB_BASE, 0x0FFFF); - - REG_UPDATE(DCHUBBUB_SDPIF_AGP_BASE, - SDPIF_AGP_BASE, dh_data->zfb_phys_addr_base >> 22); - - REG_UPDATE(DCHUBBUB_SDPIF_AGP_BOT, - SDPIF_AGP_BOT, dh_data->zfb_mc_base_addr >> 22); - - REG_UPDATE(DCHUBBUB_SDPIF_AGP_TOP, - SDPIF_AGP_TOP, (dh_data->zfb_mc_base_addr + - dh_data->zfb_size_in_byte - 1) >> 22); - break; - case FRAME_BUFFER_MODE_MIXED_ZFB_AND_LOCAL: - /*Should not touch FB LOCATION (done by VBIOS on AsicInit table)*/ - - REG_UPDATE(DCHUBBUB_SDPIF_AGP_BASE, - SDPIF_AGP_BASE, dh_data->zfb_phys_addr_base >> 22); - - REG_UPDATE(DCHUBBUB_SDPIF_AGP_BOT, - SDPIF_AGP_BOT, dh_data->zfb_mc_base_addr >> 22); - - REG_UPDATE(DCHUBBUB_SDPIF_AGP_TOP, - SDPIF_AGP_TOP, (dh_data->zfb_mc_base_addr + - dh_data->zfb_size_in_byte - 1) >> 22); - break; - case FRAME_BUFFER_MODE_LOCAL_ONLY: - /*Should not touch FB LOCATION (done by VBIOS on AsicInit table)*/ - REG_UPDATE(DCHUBBUB_SDPIF_AGP_BASE, - SDPIF_AGP_BASE, 0); - - REG_UPDATE(DCHUBBUB_SDPIF_AGP_BOT, - SDPIF_AGP_BOT, 0X03FFFF); - - REG_UPDATE(DCHUBBUB_SDPIF_AGP_TOP, - SDPIF_AGP_TOP, 0); - break; - default: - break; - } - - dh_data->dchub_initialzied = true; - dh_data->dchub_info_valid = false; -} - static void hubp_pg_control( struct dce_hwseq *hws, unsigned int hubp_inst, @@ -808,11 +364,8 @@ static void undo_DEGVIDCN10_253_wa(struct dc *dc) { struct dce_hwseq *hws = dc->hwseq; struct hubp *hubp = dc->res_pool->hubps[0]; - int pwr_status = 0; - REG_GET(DOMAIN0_PG_STATUS, DOMAIN0_PGFSM_PWR_STATUS, &pwr_status); - /* Don't need to blank if hubp is power gated*/ - if (pwr_status == 2) + if (!hws->wa_state.DEGVIDCN10_253_applied) return; hubp->funcs->set_blank(hubp, true); @@ -823,16 +376,29 @@ static void undo_DEGVIDCN10_253_wa(struct dc *dc) hubp_pg_control(hws, 0, false); REG_SET(DC_IP_REQUEST_CNTL, 0, IP_REQUEST_EN, 0); + + hws->wa_state.DEGVIDCN10_253_applied = false; } static void apply_DEGVIDCN10_253_wa(struct dc *dc) { struct dce_hwseq *hws = dc->hwseq; struct hubp *hubp = dc->res_pool->hubps[0]; + int i; if (dc->debug.disable_stutter) return; + if (!hws->wa.DEGVIDCN10_253) + return; + + for (i = 0; i < dc->res_pool->pipe_count; i++) { + if (!dc->res_pool->hubps[i]->power_gated) + return; + } + + /* all pipe power gated, apply work around to enable stutter. */ + REG_SET(DC_IP_REQUEST_CNTL, 0, IP_REQUEST_EN, 1); @@ -841,6 +407,7 @@ static void apply_DEGVIDCN10_253_wa(struct dc *dc) IP_REQUEST_EN, 0); hubp->funcs->set_hubp_blank_en(hubp, false); + hws->wa_state.DEGVIDCN10_253_applied = true; } static void bios_golden_init(struct dc *dc) @@ -859,85 +426,32 @@ static void bios_golden_init(struct dc *dc) } } -static void dcn10_init_hw(struct dc *dc) +static void false_optc_underflow_wa( + struct dc *dc, + const struct dc_stream_state *stream, + struct timing_generator *tg) { int i; - struct abm *abm = dc->res_pool->abm; - struct dce_hwseq *hws = dc->hwseq; - - if (IS_FPGA_MAXIMUS_DC(dc->ctx->dce_environment)) { - REG_WRITE(REFCLK_CNTL, 0); - REG_UPDATE(DCHUBBUB_GLOBAL_TIMER_CNTL, DCHUBBUB_GLOBAL_TIMER_ENABLE, 1); - REG_WRITE(DIO_MEM_PWR_CTRL, 0); + bool underflow; - if (!dc->debug.disable_clock_gate) { - /* enable all DCN clock gating */ - REG_WRITE(DCCG_GATE_DISABLE_CNTL, 0); - - REG_WRITE(DCCG_GATE_DISABLE_CNTL2, 0); - - REG_UPDATE(DCFCLK_CNTL, DCFCLK_GATE_DIS, 0); - } - - enable_power_gating_plane(dc->hwseq, true); + if (!dc->hwseq->wa.false_optc_underflow) return; - } - /* end of FPGA. Below if real ASIC */ - bios_golden_init(dc); - - disable_vga(dc->hwseq); - - for (i = 0; i < dc->link_count; i++) { - /* Power up AND update implementation according to the - * required signal (which may be different from the - * default signal on connector). - */ - struct dc_link *link = dc->links[i]; - - link->link_enc->funcs->hw_init(link->link_enc); - } + underflow = tg->funcs->is_optc_underflow_occurred(tg); for (i = 0; i < dc->res_pool->pipe_count; i++) { - struct dpp *dpp = dc->res_pool->dpps[i]; - struct timing_generator *tg = dc->res_pool->timing_generators[i]; + struct pipe_ctx *old_pipe_ctx = &dc->current_state->res_ctx.pipe_ctx[i]; - dpp->funcs->dpp_reset(dpp); - dc->res_pool->mpc->funcs->remove( - dc->res_pool->mpc, &(dc->res_pool->opps[i]->mpc_tree), - dc->res_pool->opps[i]->inst, i); - - /* Blank controller using driver code instead of - * command table. - */ - tg->funcs->set_blank(tg, true); - hwss_wait_for_blank_complete(tg); - } - - for (i = 0; i < dc->res_pool->audio_count; i++) { - struct audio *audio = dc->res_pool->audios[i]; - - audio->funcs->hw_init(audio); - } + if (old_pipe_ctx->stream != stream) + continue; - if (abm != NULL) { - abm->funcs->init_backlight(abm); - abm->funcs->abm_init(abm); + dc->hwss.wait_for_mpcc_disconnect(dc, dc->res_pool, old_pipe_ctx); } - /* power AFMT HDMI memory TODO: may move to dis/en output save power*/ - REG_WRITE(DIO_MEM_PWR_CTRL, 0); - - if (!dc->debug.disable_clock_gate) { - /* enable all DCN clock gating */ - REG_WRITE(DCCG_GATE_DISABLE_CNTL, 0); - - REG_WRITE(DCCG_GATE_DISABLE_CNTL2, 0); - - REG_UPDATE(DCFCLK_CNTL, DCFCLK_GATE_DIS, 0); - } + tg->funcs->set_blank_data_double_buffer(tg, true); - enable_power_gating_plane(dc->hwseq, true); + if (tg->funcs->is_optc_underflow_occurred(tg) && !underflow) + tg->funcs->clear_optc_underflow(tg); } static enum dc_status dcn10_prog_pixclk_crtc_otg( @@ -948,10 +462,6 @@ static enum dc_status dcn10_prog_pixclk_crtc_otg( struct dc_stream_state *stream = pipe_ctx->stream; enum dc_color_space color_space; struct tg_color black_color = {0}; - bool enableStereo = stream->timing.timing_3d_format == TIMING_3D_FORMAT_NONE ? - false:true; - bool rightEyePolarity = stream->timing.flags.RIGHT_EYE_3D_POLARITY; - /* by upper caller loop, pipe0 is parent pipe and be called first. * back end is set up by for pipe0. Other children pipe share back end @@ -986,11 +496,6 @@ static enum dc_status dcn10_prog_pixclk_crtc_otg( &stream->timing, true); - pipe_ctx->stream_res.opp->funcs->opp_set_stereo_polarity( - pipe_ctx->stream_res.opp, - enableStereo, - rightEyePolarity); - #if 0 /* move to after enable_crtc */ /* TODO: OPP FMT, ABM. etc. should be done here. */ /* or FPGA now. instance 0 only. TODO: move to opp.c */ @@ -1005,12 +510,18 @@ static enum dc_status dcn10_prog_pixclk_crtc_otg( /* program otg blank color */ color_space = stream->output_color_space; color_space_to_black_color(dc, color_space, &black_color); - pipe_ctx->stream_res.tg->funcs->set_blank_color( - pipe_ctx->stream_res.tg, - &black_color); - pipe_ctx->stream_res.tg->funcs->set_blank(pipe_ctx->stream_res.tg, true); - hwss_wait_for_blank_complete(pipe_ctx->stream_res.tg); + if (pipe_ctx->stream_res.tg->funcs->set_blank_color) + pipe_ctx->stream_res.tg->funcs->set_blank_color( + pipe_ctx->stream_res.tg, + &black_color); + + if (pipe_ctx->stream_res.tg->funcs->is_blanked && + !pipe_ctx->stream_res.tg->funcs->is_blanked(pipe_ctx->stream_res.tg)) { + pipe_ctx->stream_res.tg->funcs->set_blank(pipe_ctx->stream_res.tg, true); + hwss_wait_for_blank_complete(pipe_ctx->stream_res.tg); + false_optc_underflow_wa(dc, pipe_ctx->stream, pipe_ctx->stream_res.tg); + } /* VTG is within DCHUB command block. DCFCLK is always on */ if (false == pipe_ctx->stream_res.tg->funcs->enable_crtc(pipe_ctx->stream_res.tg)) { @@ -1070,83 +581,55 @@ static void reset_back_end_for_pipe( pipe_ctx->pipe_idx, pipe_ctx->stream_res.tg->inst); } +static void dcn10_verify_allow_pstate_change_high(struct dc *dc) +{ + static bool should_log_hw_state; /* prevent hw state log by default */ + + if (!hubbub1_verify_allow_pstate_change_high(dc->res_pool->hubbub)) { + if (should_log_hw_state) { + dcn10_log_hw_state(dc); + } + + BREAK_TO_DEBUGGER(); + } +} + /* trigger HW to start disconnect plane from stream on the next vsync */ -static void plane_atomic_disconnect(struct dc *dc, - int fe_idx) +static void plane_atomic_disconnect(struct dc *dc, struct pipe_ctx *pipe_ctx) { + int fe_idx = pipe_ctx->pipe_idx; struct hubp *hubp = dc->res_pool->hubps[fe_idx]; struct mpc *mpc = dc->res_pool->mpc; - int opp_id, z_idx; - int mpcc_id = -1; + int opp_id; + struct mpc_tree *mpc_tree_params; + struct mpcc *mpcc_to_remove = NULL; /* look at tree rather than mi here to know if we already reset */ for (opp_id = 0; opp_id < dc->res_pool->pipe_count; opp_id++) { struct output_pixel_processor *opp = dc->res_pool->opps[opp_id]; - for (z_idx = 0; z_idx < opp->mpc_tree.num_pipes; z_idx++) { - if (opp->mpc_tree.dpp[z_idx] == fe_idx) { - mpcc_id = opp->mpc_tree.mpcc[z_idx]; - break; - } - } - if (mpcc_id != -1) + mpc_tree_params = &(opp->mpc_tree_params); + mpcc_to_remove = mpc->funcs->get_mpcc_for_dpp(mpc_tree_params, fe_idx); + if (mpcc_to_remove != NULL) break; } + /*Already reset*/ if (opp_id == dc->res_pool->pipe_count) return; - if (dc->debug.sanity_checks) - verify_allow_pstate_change_high(dc->hwseq); - hubp->funcs->dcc_control(hubp, false, false); - if (dc->debug.sanity_checks) - verify_allow_pstate_change_high(dc->hwseq); + mpc->funcs->remove_mpcc(mpc, mpc_tree_params, mpcc_to_remove); + dc->res_pool->opps[opp_id]->mpcc_disconnect_pending[fe_idx] = true; - mpc->funcs->remove(mpc, &(dc->res_pool->opps[opp_id]->mpc_tree), - dc->res_pool->opps[opp_id]->inst, fe_idx); -} + dc->optimized_required = true; -/* disable HW used by plane. - * note: cannot disable until disconnect is complete */ -static void plane_atomic_disable(struct dc *dc, - int fe_idx) -{ - struct dce_hwseq *hws = dc->hwseq; - struct hubp *hubp = dc->res_pool->hubps[fe_idx]; - struct mpc *mpc = dc->res_pool->mpc; - int opp_id = hubp->opp_id; - - if (opp_id == 0xf) - return; - - mpc->funcs->wait_for_idle(mpc, hubp->mpcc_id); - dc->res_pool->opps[hubp->opp_id]->mpcc_disconnect_pending[hubp->mpcc_id] = false; - /*dm_logger_write(dc->ctx->logger, LOG_ERROR, - "[debug_mpo: atomic disable finished on mpcc %d]\n", - fe_idx);*/ - - hubp->funcs->set_blank(hubp, true); + if (hubp->funcs->hubp_disconnect) + hubp->funcs->hubp_disconnect(hubp); if (dc->debug.sanity_checks) - verify_allow_pstate_change_high(dc->hwseq); - - REG_UPDATE(HUBP_CLK_CNTL[fe_idx], - HUBP_CLOCK_ENABLE, 0); - REG_UPDATE(DPP_CONTROL[fe_idx], - DPP_CLOCK_ENABLE, 0); - - if (dc->res_pool->opps[opp_id]->mpc_tree.num_pipes == 0) - REG_UPDATE(OPP_PIPE_CONTROL[opp_id], - OPP_PIPE_CLOCK_EN, 0); - - if (dc->debug.sanity_checks) - verify_allow_pstate_change_high(dc->hwseq); + dcn10_verify_allow_pstate_change_high(dc); } -/* - * kill power to plane hw - * note: cannot power down until plane is disable - */ static void plane_atomic_power_down(struct dc *dc, int fe_idx) { struct dce_hwseq *hws = dc->hwseq; @@ -1162,125 +645,200 @@ static void plane_atomic_power_down(struct dc *dc, int fe_idx) IP_REQUEST_EN, 0); dm_logger_write(dc->ctx->logger, LOG_DEBUG, "Power gated front end %d\n", fe_idx); - - if (dc->debug.sanity_checks) - verify_allow_pstate_change_high(dc->hwseq); } } - -static void reset_front_end( - struct dc *dc, - int fe_idx) +/* disable HW used by plane. + * note: cannot disable until disconnect is complete + */ +static void plane_atomic_disable(struct dc *dc, struct pipe_ctx *pipe_ctx) { + int fe_idx = pipe_ctx->pipe_idx; struct dce_hwseq *hws = dc->hwseq; - struct timing_generator *tg; - int opp_id = dc->res_pool->hubps[fe_idx]->opp_id; + struct hubp *hubp = dc->res_pool->hubps[fe_idx]; + int opp_id = hubp->opp_id; - /*Already reset*/ - if (opp_id == 0xf) - return; + dc->hwss.wait_for_mpcc_disconnect(dc, dc->res_pool, pipe_ctx); - tg = dc->res_pool->timing_generators[opp_id]; - tg->funcs->lock(tg); + REG_UPDATE(HUBP_CLK_CNTL[fe_idx], + HUBP_CLOCK_ENABLE, 0); + REG_UPDATE(DPP_CONTROL[fe_idx], + DPP_CLOCK_ENABLE, 0); - plane_atomic_disconnect(dc, fe_idx); + if (opp_id != 0xf && dc->res_pool->opps[opp_id]->mpc_tree_params.opp_list == NULL) + REG_UPDATE(OPP_PIPE_CONTROL[opp_id], + OPP_PIPE_CLOCK_EN, 0); - REG_UPDATE(OTG_GLOBAL_SYNC_STATUS[tg->inst], VUPDATE_NO_LOCK_EVENT_CLEAR, 1); - tg->funcs->unlock(tg); + hubp->power_gated = true; + dc->optimized_required = false; /* We're powering off, no need to optimize */ - if (dc->debug.sanity_checks) - verify_allow_pstate_change_high(hws); + plane_atomic_power_down(dc, fe_idx); - if (tg->ctx->dce_environment != DCE_ENV_FPGA_MAXIMUS) - REG_WAIT(OTG_GLOBAL_SYNC_STATUS[tg->inst], - VUPDATE_NO_LOCK_EVENT_OCCURRED, 1, - 1, 100000); + pipe_ctx->stream = NULL; + memset(&pipe_ctx->stream_res, 0, sizeof(pipe_ctx->stream_res)); + memset(&pipe_ctx->plane_res, 0, sizeof(pipe_ctx->plane_res)); + pipe_ctx->top_pipe = NULL; + pipe_ctx->bottom_pipe = NULL; + pipe_ctx->plane_state = NULL; +} - plane_atomic_disable(dc, fe_idx); +static void dcn10_disable_plane(struct dc *dc, struct pipe_ctx *pipe_ctx) +{ + if (dc->res_pool->hubps[pipe_ctx->pipe_idx]->power_gated) + return; + + plane_atomic_disable(dc, pipe_ctx); + + apply_DEGVIDCN10_253_wa(dc); dm_logger_write(dc->ctx->logger, LOG_DC, - "Reset front end %d\n", - fe_idx); + "Power down front end %d\n", + pipe_ctx->pipe_idx); } -static void dcn10_power_down_fe(struct dc *dc, int fe_idx) +static void dcn10_init_hw(struct dc *dc) { + int i; + struct abm *abm = dc->res_pool->abm; + struct dmcu *dmcu = dc->res_pool->dmcu; struct dce_hwseq *hws = dc->hwseq; - struct dpp *dpp = dc->res_pool->dpps[fe_idx]; + struct dc_bios *dcb = dc->ctx->dc_bios; + struct dc_state *context = dc->current_state; - reset_front_end(dc, fe_idx); + if (IS_FPGA_MAXIMUS_DC(dc->ctx->dce_environment)) { + REG_WRITE(REFCLK_CNTL, 0); + REG_UPDATE(DCHUBBUB_GLOBAL_TIMER_CNTL, DCHUBBUB_GLOBAL_TIMER_ENABLE, 1); + REG_WRITE(DIO_MEM_PWR_CTRL, 0); - REG_SET(DC_IP_REQUEST_CNTL, 0, - IP_REQUEST_EN, 1); - dpp_pg_control(hws, fe_idx, false); - hubp_pg_control(hws, fe_idx, false); - dpp->funcs->dpp_reset(dpp); - REG_SET(DC_IP_REQUEST_CNTL, 0, - IP_REQUEST_EN, 0); - dm_logger_write(dc->ctx->logger, LOG_DEBUG, - "Power gated front end %d\n", fe_idx); + if (!dc->debug.disable_clock_gate) { + /* enable all DCN clock gating */ + REG_WRITE(DCCG_GATE_DISABLE_CNTL, 0); - if (dc->debug.sanity_checks) - verify_allow_pstate_change_high(dc->hwseq); -} + REG_WRITE(DCCG_GATE_DISABLE_CNTL2, 0); -static void reset_hw_ctx_wrap( - struct dc *dc, - struct dc_state *context) -{ - int i; + REG_UPDATE(DCFCLK_CNTL, DCFCLK_GATE_DIS, 0); + } + + enable_power_gating_plane(dc->hwseq, true); + return; + } + /* end of FPGA. Below if real ASIC */ + + if (!dcb->funcs->is_accelerated_mode(dcb)) { + bios_golden_init(dc); + disable_vga(dc->hwseq); + } + + for (i = 0; i < dc->link_count; i++) { + /* Power up AND update implementation according to the + * required signal (which may be different from the + * default signal on connector). + */ + struct dc_link *link = dc->links[i]; + + if (link->link_enc->connector.id == CONNECTOR_ID_EDP) + dc->hwss.edp_power_control(link, true); + + link->link_enc->funcs->hw_init(link->link_enc); + } - /* Reset Front End*/ - /* Lock*/ for (i = 0; i < dc->res_pool->pipe_count; i++) { - struct pipe_ctx *cur_pipe_ctx = &dc->current_state->res_ctx.pipe_ctx[i]; - struct timing_generator *tg = cur_pipe_ctx->stream_res.tg; + struct timing_generator *tg = dc->res_pool->timing_generators[i]; - if (cur_pipe_ctx->stream) + if (tg->funcs->is_tg_enabled(tg)) tg->funcs->lock(tg); } - /* Disconnect*/ - for (i = dc->res_pool->pipe_count - 1; i >= 0 ; i--) { - struct pipe_ctx *pipe_ctx_old = - &dc->current_state->res_ctx.pipe_ctx[i]; - struct pipe_ctx *pipe_ctx = &context->res_ctx.pipe_ctx[i]; - if (!pipe_ctx->stream || - !pipe_ctx->plane_state || - pipe_need_reprogram(pipe_ctx_old, pipe_ctx)) { + /* Blank controller using driver code instead of + * command table. + */ + for (i = 0; i < dc->res_pool->pipe_count; i++) { + struct timing_generator *tg = dc->res_pool->timing_generators[i]; - plane_atomic_disconnect(dc, i); + if (tg->funcs->is_tg_enabled(tg)) { + tg->funcs->set_blank(tg, true); + hwss_wait_for_blank_complete(tg); } } - /* Unlock*/ - for (i = dc->res_pool->pipe_count - 1; i >= 0; i--) { - struct pipe_ctx *cur_pipe_ctx = &dc->current_state->res_ctx.pipe_ctx[i]; - struct timing_generator *tg = cur_pipe_ctx->stream_res.tg; - if (cur_pipe_ctx->stream) + /* Reset all MPCC muxes */ + dc->res_pool->mpc->funcs->mpc_init(dc->res_pool->mpc); + + for (i = 0; i < dc->res_pool->pipe_count; i++) { + struct timing_generator *tg = dc->res_pool->timing_generators[i]; + struct pipe_ctx *pipe_ctx = &context->res_ctx.pipe_ctx[i]; + struct hubp *hubp = dc->res_pool->hubps[i]; + + pipe_ctx->stream_res.tg = tg; + pipe_ctx->pipe_idx = i; + + pipe_ctx->plane_res.hubp = hubp; + hubp->mpcc_id = i; + hubp->opp_id = 0xf; + hubp->power_gated = false; + + dc->res_pool->opps[i]->mpc_tree_params.opp_id = dc->res_pool->opps[i]->inst; + dc->res_pool->opps[i]->mpc_tree_params.opp_list = NULL; + dc->res_pool->opps[i]->mpcc_disconnect_pending[i] = true; + pipe_ctx->stream_res.opp = dc->res_pool->opps[i]; + + plane_atomic_disconnect(dc, pipe_ctx); + } + + for (i = 0; i < dc->res_pool->pipe_count; i++) { + struct timing_generator *tg = dc->res_pool->timing_generators[i]; + + if (tg->funcs->is_tg_enabled(tg)) tg->funcs->unlock(tg); } - /* Disable and Powerdown*/ - for (i = dc->res_pool->pipe_count - 1; i >= 0 ; i--) { - struct pipe_ctx *pipe_ctx_old = - &dc->current_state->res_ctx.pipe_ctx[i]; + for (i = 0; i < dc->res_pool->pipe_count; i++) { + struct timing_generator *tg = dc->res_pool->timing_generators[i]; struct pipe_ctx *pipe_ctx = &context->res_ctx.pipe_ctx[i]; - /*if (!pipe_ctx_old->stream) - continue;*/ + dcn10_disable_plane(dc, pipe_ctx); - if (pipe_ctx->stream && pipe_ctx->plane_state - && !pipe_need_reprogram(pipe_ctx_old, pipe_ctx)) - continue; + pipe_ctx->stream_res.tg = NULL; + pipe_ctx->plane_res.hubp = NULL; + + tg->funcs->tg_init(tg); + } - plane_atomic_disable(dc, i); + for (i = 0; i < dc->res_pool->audio_count; i++) { + struct audio *audio = dc->res_pool->audios[i]; - if (!pipe_ctx->stream || !pipe_ctx->plane_state) - plane_atomic_power_down(dc, i); + audio->funcs->hw_init(audio); } + if (abm != NULL) { + abm->funcs->init_backlight(abm); + abm->funcs->abm_init(abm); + } + + if (dmcu != NULL) + dmcu->funcs->dmcu_init(dmcu); + + /* power AFMT HDMI memory TODO: may move to dis/en output save power*/ + REG_WRITE(DIO_MEM_PWR_CTRL, 0); + + if (!dc->debug.disable_clock_gate) { + /* enable all DCN clock gating */ + REG_WRITE(DCCG_GATE_DISABLE_CNTL, 0); + + REG_WRITE(DCCG_GATE_DISABLE_CNTL2, 0); + + REG_UPDATE(DCFCLK_CNTL, DCFCLK_GATE_DIS, 0); + } + + enable_power_gating_plane(dc->hwseq, true); +} + +static void reset_hw_ctx_wrap( + struct dc *dc, + struct dc_state *context) +{ + int i; + /* Reset Back End*/ for (i = dc->res_pool->pipe_count - 1; i >= 0 ; i--) { struct pipe_ctx *pipe_ctx_old = @@ -1298,7 +856,6 @@ static void reset_hw_ctx_wrap( struct clock_source *old_clk = pipe_ctx_old->clock_source; reset_back_end_for_pipe(dc, pipe_ctx_old, dc->current_state); - if (old_clk) old_clk->funcs->cs_power_down(old_clk); } @@ -1332,21 +889,7 @@ static bool patch_address_for_sbs_tb_stereo( return false; } -static void toggle_watermark_change_req(struct dce_hwseq *hws) -{ - uint32_t watermark_change_req; - - REG_GET(DCHUBBUB_ARB_WATERMARK_CHANGE_CNTL, - DCHUBBUB_ARB_WATERMARK_CHANGE_REQUEST, &watermark_change_req); - - if (watermark_change_req) - watermark_change_req = 0; - else - watermark_change_req = 1; - REG_UPDATE(DCHUBBUB_ARB_WATERMARK_CHANGE_CNTL, - DCHUBBUB_ARB_WATERMARK_CHANGE_REQUEST, watermark_change_req); -} static void dcn10_update_plane_addr(const struct dc *dc, struct pipe_ctx *pipe_ctx) { @@ -1366,8 +909,8 @@ static void dcn10_update_plane_addr(const struct dc *dc, struct pipe_ctx *pipe_c pipe_ctx->plane_state->address.grph_stereo.left_addr = addr; } -static bool dcn10_set_input_transfer_func( - struct pipe_ctx *pipe_ctx, const struct dc_plane_state *plane_state) +static bool dcn10_set_input_transfer_func(struct pipe_ctx *pipe_ctx, + const struct dc_plane_state *plane_state) { struct dpp *dpp_base = pipe_ctx->plane_res.dpp; const struct dc_transfer_func *tf = NULL; @@ -1380,34 +923,28 @@ static bool dcn10_set_input_transfer_func( tf = plane_state->in_transfer_func; if (plane_state->gamma_correction && dce_use_lut(plane_state)) - dpp_base->funcs->ipp_program_input_lut(dpp_base, - plane_state->gamma_correction); + dpp_base->funcs->dpp_program_input_lut(dpp_base, plane_state->gamma_correction); if (tf == NULL) - dpp_base->funcs->ipp_set_degamma(dpp_base, IPP_DEGAMMA_MODE_BYPASS); + dpp_base->funcs->dpp_set_degamma(dpp_base, IPP_DEGAMMA_MODE_BYPASS); else if (tf->type == TF_TYPE_PREDEFINED) { switch (tf->tf) { case TRANSFER_FUNCTION_SRGB: - dpp_base->funcs->ipp_set_degamma(dpp_base, - IPP_DEGAMMA_MODE_HW_sRGB); + dpp_base->funcs->dpp_set_degamma(dpp_base, IPP_DEGAMMA_MODE_HW_sRGB); break; case TRANSFER_FUNCTION_BT709: - dpp_base->funcs->ipp_set_degamma(dpp_base, - IPP_DEGAMMA_MODE_HW_xvYCC); + dpp_base->funcs->dpp_set_degamma(dpp_base, IPP_DEGAMMA_MODE_HW_xvYCC); break; case TRANSFER_FUNCTION_LINEAR: - dpp_base->funcs->ipp_set_degamma(dpp_base, - IPP_DEGAMMA_MODE_BYPASS); + dpp_base->funcs->dpp_set_degamma(dpp_base, IPP_DEGAMMA_MODE_BYPASS); break; case TRANSFER_FUNCTION_PQ: - result = false; - break; default: result = false; break; } } else if (tf->type == TF_TYPE_BYPASS) { - dpp_base->funcs->ipp_set_degamma(dpp_base, IPP_DEGAMMA_MODE_BYPASS); + dpp_base->funcs->dpp_set_degamma(dpp_base, IPP_DEGAMMA_MODE_BYPASS); } else { /*TF_TYPE_DISTRIBUTED_POINTS*/ result = false; @@ -1415,324 +952,14 @@ static bool dcn10_set_input_transfer_func( return result; } -/*modify the method to handle rgb for arr_points*/ -static bool convert_to_custom_float( - struct pwl_result_data *rgb_resulted, - struct curve_points *arr_points, - uint32_t hw_points_num) -{ - struct custom_float_format fmt; - - struct pwl_result_data *rgb = rgb_resulted; - - uint32_t i = 0; - - fmt.exponenta_bits = 6; - fmt.mantissa_bits = 12; - fmt.sign = false; - - if (!convert_to_custom_float_format( - arr_points[0].x, - &fmt, - &arr_points[0].custom_float_x)) { - BREAK_TO_DEBUGGER(); - return false; - } - - if (!convert_to_custom_float_format( - arr_points[0].offset, - &fmt, - &arr_points[0].custom_float_offset)) { - BREAK_TO_DEBUGGER(); - return false; - } - - if (!convert_to_custom_float_format( - arr_points[0].slope, - &fmt, - &arr_points[0].custom_float_slope)) { - BREAK_TO_DEBUGGER(); - return false; - } - - fmt.mantissa_bits = 10; - fmt.sign = false; - - if (!convert_to_custom_float_format( - arr_points[1].x, - &fmt, - &arr_points[1].custom_float_x)) { - BREAK_TO_DEBUGGER(); - return false; - } - - if (!convert_to_custom_float_format( - arr_points[1].y, - &fmt, - &arr_points[1].custom_float_y)) { - BREAK_TO_DEBUGGER(); - return false; - } - - if (!convert_to_custom_float_format( - arr_points[1].slope, - &fmt, - &arr_points[1].custom_float_slope)) { - BREAK_TO_DEBUGGER(); - return false; - } - - fmt.mantissa_bits = 12; - fmt.sign = true; - - while (i != hw_points_num) { - if (!convert_to_custom_float_format( - rgb->red, - &fmt, - &rgb->red_reg)) { - BREAK_TO_DEBUGGER(); - return false; - } - - if (!convert_to_custom_float_format( - rgb->green, - &fmt, - &rgb->green_reg)) { - BREAK_TO_DEBUGGER(); - return false; - } - - if (!convert_to_custom_float_format( - rgb->blue, - &fmt, - &rgb->blue_reg)) { - BREAK_TO_DEBUGGER(); - return false; - } - - if (!convert_to_custom_float_format( - rgb->delta_red, - &fmt, - &rgb->delta_red_reg)) { - BREAK_TO_DEBUGGER(); - return false; - } - - if (!convert_to_custom_float_format( - rgb->delta_green, - &fmt, - &rgb->delta_green_reg)) { - BREAK_TO_DEBUGGER(); - return false; - } - - if (!convert_to_custom_float_format( - rgb->delta_blue, - &fmt, - &rgb->delta_blue_reg)) { - BREAK_TO_DEBUGGER(); - return false; - } - - ++rgb; - ++i; - } - - return true; -} -#define MAX_REGIONS_NUMBER 34 -#define MAX_LOW_POINT 25 -#define NUMBER_SEGMENTS 32 - -static bool dcn10_translate_regamma_to_hw_format(const struct dc_transfer_func - *output_tf, struct pwl_params *regamma_params) -{ - struct curve_points *arr_points; - struct pwl_result_data *rgb_resulted; - struct pwl_result_data *rgb; - struct pwl_result_data *rgb_plus_1; - struct fixed31_32 y_r; - struct fixed31_32 y_g; - struct fixed31_32 y_b; - struct fixed31_32 y1_min; - struct fixed31_32 y3_max; - - int32_t segment_start, segment_end; - int32_t i; - uint32_t j, k, seg_distr[MAX_REGIONS_NUMBER], increment, start_index, hw_points; - - if (output_tf == NULL || regamma_params == NULL || - output_tf->type == TF_TYPE_BYPASS) - return false; - arr_points = regamma_params->arr_points; - rgb_resulted = regamma_params->rgb_resulted; - hw_points = 0; - memset(regamma_params, 0, sizeof(struct pwl_params)); - memset(seg_distr, 0, sizeof(seg_distr)); - if (output_tf->tf == TRANSFER_FUNCTION_PQ) { - /* 32 segments - * segments are from 2^-25 to 2^7 - */ - for (i = 0; i < 32 ; i++) - seg_distr[i] = 3; - - segment_start = -25; - segment_end = 7; - } else { - /* 10 segments - * segment is from 2^-10 to 2^0 - * There are less than 256 points, for optimization - */ - seg_distr[0] = 3; - seg_distr[1] = 4; - seg_distr[2] = 4; - seg_distr[3] = 4; - seg_distr[4] = 4; - seg_distr[5] = 4; - seg_distr[6] = 4; - seg_distr[7] = 4; - seg_distr[8] = 5; - seg_distr[9] = 5; - - segment_start = -10; - segment_end = 0; - } - - for (i = segment_end - segment_start; i < MAX_REGIONS_NUMBER ; i++) - seg_distr[i] = -1; - - for (k = 0; k < MAX_REGIONS_NUMBER; k++) { - if (seg_distr[k] != -1) - hw_points += (1 << seg_distr[k]); - } - - j = 0; - for (k = 0; k < (segment_end - segment_start); k++) { - increment = NUMBER_SEGMENTS / (1 << seg_distr[k]); - start_index = (segment_start + k + MAX_LOW_POINT) * NUMBER_SEGMENTS; - for (i = start_index; i < start_index + NUMBER_SEGMENTS; i += increment) { - if (j == hw_points - 1) - break; - rgb_resulted[j].red = output_tf->tf_pts.red[i]; - rgb_resulted[j].green = output_tf->tf_pts.green[i]; - rgb_resulted[j].blue = output_tf->tf_pts.blue[i]; - j++; - } - } - /* last point */ - start_index = (segment_end + MAX_LOW_POINT) * NUMBER_SEGMENTS; - rgb_resulted[hw_points - 1].red = - output_tf->tf_pts.red[start_index]; - rgb_resulted[hw_points - 1].green = - output_tf->tf_pts.green[start_index]; - rgb_resulted[hw_points - 1].blue = - output_tf->tf_pts.blue[start_index]; - - arr_points[0].x = dal_fixed31_32_pow(dal_fixed31_32_from_int(2), - dal_fixed31_32_from_int(segment_start)); - arr_points[1].x = dal_fixed31_32_pow(dal_fixed31_32_from_int(2), - dal_fixed31_32_from_int(segment_end)); - arr_points[2].x = dal_fixed31_32_pow(dal_fixed31_32_from_int(2), - dal_fixed31_32_from_int(segment_end)); - - y_r = rgb_resulted[0].red; - y_g = rgb_resulted[0].green; - y_b = rgb_resulted[0].blue; - - y1_min = dal_fixed31_32_min(y_r, dal_fixed31_32_min(y_g, y_b)); - - arr_points[0].y = y1_min; - arr_points[0].slope = dal_fixed31_32_div( - arr_points[0].y, - arr_points[0].x); - y_r = rgb_resulted[hw_points - 1].red; - y_g = rgb_resulted[hw_points - 1].green; - y_b = rgb_resulted[hw_points - 1].blue; - - /* see comment above, m_arrPoints[1].y should be the Y value for the - * region end (m_numOfHwPoints), not last HW point(m_numOfHwPoints - 1) - */ - y3_max = dal_fixed31_32_max(y_r, dal_fixed31_32_max(y_g, y_b)); - - arr_points[1].y = y3_max; - arr_points[2].y = y3_max; - - arr_points[1].slope = dal_fixed31_32_zero; - arr_points[2].slope = dal_fixed31_32_zero; - if (output_tf->tf == TRANSFER_FUNCTION_PQ) { - /* for PQ, we want to have a straight line from last HW X point, - * and the slope to be such that we hit 1.0 at 10000 nits. - */ - const struct fixed31_32 end_value = - dal_fixed31_32_from_int(125); - - arr_points[1].slope = dal_fixed31_32_div( - dal_fixed31_32_sub(dal_fixed31_32_one, arr_points[1].y), - dal_fixed31_32_sub(end_value, arr_points[1].x)); - arr_points[2].slope = dal_fixed31_32_div( - dal_fixed31_32_sub(dal_fixed31_32_one, arr_points[1].y), - dal_fixed31_32_sub(end_value, arr_points[1].x)); - } - - regamma_params->hw_points_num = hw_points; - - i = 1; - for (k = 0; k < MAX_REGIONS_NUMBER && i < MAX_REGIONS_NUMBER; k++) { - if (seg_distr[k] != -1) { - regamma_params->arr_curve_points[k].segments_num = - seg_distr[k]; - regamma_params->arr_curve_points[i].offset = - regamma_params->arr_curve_points[k]. - offset + (1 << seg_distr[k]); - } - i++; - } - - if (seg_distr[k] != -1) - regamma_params->arr_curve_points[k].segments_num = - seg_distr[k]; - - rgb = rgb_resulted; - rgb_plus_1 = rgb_resulted + 1; - - i = 1; - - while (i != hw_points + 1) { - if (dal_fixed31_32_lt(rgb_plus_1->red, rgb->red)) - rgb_plus_1->red = rgb->red; - if (dal_fixed31_32_lt(rgb_plus_1->green, rgb->green)) - rgb_plus_1->green = rgb->green; - if (dal_fixed31_32_lt(rgb_plus_1->blue, rgb->blue)) - rgb_plus_1->blue = rgb->blue; - - rgb->delta_red = dal_fixed31_32_sub( - rgb_plus_1->red, - rgb->red); - rgb->delta_green = dal_fixed31_32_sub( - rgb_plus_1->green, - rgb->green); - rgb->delta_blue = dal_fixed31_32_sub( - rgb_plus_1->blue, - rgb->blue); - - ++rgb_plus_1; - ++rgb; - ++i; - } - - convert_to_custom_float(rgb_resulted, arr_points, hw_points); - - return true; -} - -static bool dcn10_set_output_transfer_func( - struct pipe_ctx *pipe_ctx, - const struct dc_stream_state *stream) +static bool +dcn10_set_output_transfer_func(struct pipe_ctx *pipe_ctx, + const struct dc_stream_state *stream) { struct dpp *dpp = pipe_ctx->plane_res.dpp; @@ -1742,18 +969,21 @@ static bool dcn10_set_output_transfer_func( dpp->regamma_params.hw_points_num = GAMMA_HW_POINTS_NUM; if (stream->out_transfer_func && - stream->out_transfer_func->type == - TF_TYPE_PREDEFINED && - stream->out_transfer_func->tf == - TRANSFER_FUNCTION_SRGB) { - dpp->funcs->opp_set_regamma_mode(dpp, OPP_REGAMMA_SRGB); - } else if (dcn10_translate_regamma_to_hw_format( - stream->out_transfer_func, &dpp->regamma_params)) { - dpp->funcs->opp_program_regamma_pwl(dpp, &dpp->regamma_params); - dpp->funcs->opp_set_regamma_mode(dpp, OPP_REGAMMA_USER); - } else { - dpp->funcs->opp_set_regamma_mode(dpp, OPP_REGAMMA_BYPASS); - } + stream->out_transfer_func->type == TF_TYPE_PREDEFINED && + stream->out_transfer_func->tf == TRANSFER_FUNCTION_SRGB) + dpp->funcs->dpp_program_regamma_pwl(dpp, NULL, OPP_REGAMMA_SRGB); + + /* dcn10_translate_regamma_to_hw_format takes 750us, only do it when full + * update. + */ + else if (cm_helper_translate_curve_to_hw_format( + stream->out_transfer_func, + &dpp->regamma_params, false)) { + dpp->funcs->dpp_program_regamma_pwl( + dpp, + &dpp->regamma_params, OPP_REGAMMA_USER); + } else + dpp->funcs->dpp_program_regamma_pwl(dpp, NULL, OPP_REGAMMA_BYPASS); return true; } @@ -1772,7 +1002,7 @@ static void dcn10_pipe_control_lock( return; if (dc->debug.sanity_checks) - verify_allow_pstate_change_high(dc->hwseq); + dcn10_verify_allow_pstate_change_high(dc); if (lock) pipe->stream_res.tg->funcs->lock(pipe->stream_res.tg); @@ -1780,7 +1010,7 @@ static void dcn10_pipe_control_lock( pipe->stream_res.tg->funcs->unlock(pipe->stream_res.tg); if (dc->debug.sanity_checks) - verify_allow_pstate_change_high(dc->hwseq); + dcn10_verify_allow_pstate_change_high(dc); } static bool wait_for_reset_trigger_to_occur( @@ -1833,14 +1063,15 @@ static void dcn10_enable_timing_synchronization( for (i = 1; i < group_size; i++) grouped_pipes[i]->stream_res.tg->funcs->enable_reset_trigger( - grouped_pipes[i]->stream_res.tg, grouped_pipes[0]->stream_res.tg->inst); - + grouped_pipes[i]->stream_res.tg, + grouped_pipes[0]->stream_res.tg->inst); DC_SYNC_INFO("Waiting for trigger\n"); /* Need to get only check 1 pipe for having reset as all the others are * synchronized. Look at last pipe programmed to reset. */ + wait_for_reset_trigger_to_occur(dc_ctx, grouped_pipes[1]->stream_res.tg); for (i = 1; i < group_size; i++) grouped_pipes[i]->stream_res.tg->funcs->disable_reset_trigger( @@ -1849,7 +1080,30 @@ static void dcn10_enable_timing_synchronization( DC_SYNC_INFO("Sync complete\n"); } -static void print_rq_dlg_ttu( +static void dcn10_enable_per_frame_crtc_position_reset( + struct dc *dc, + int group_size, + struct pipe_ctx *grouped_pipes[]) +{ + struct dc_context *dc_ctx = dc->ctx; + int i; + + DC_SYNC_INFO("Setting up\n"); + for (i = 0; i < group_size; i++) + grouped_pipes[i]->stream_res.tg->funcs->enable_crtc_reset( + grouped_pipes[i]->stream_res.tg, + grouped_pipes[i]->stream->triggered_crtc_reset.event_source->status.primary_otg_inst, + &grouped_pipes[i]->stream->triggered_crtc_reset); + + DC_SYNC_INFO("Waiting for trigger\n"); + + for (i = 1; i < group_size; i++) + wait_for_reset_trigger_to_occur(dc_ctx, grouped_pipes[i]->stream_res.tg); + + DC_SYNC_INFO("Multi-display sync is complete\n"); +} + +/*static void print_rq_dlg_ttu( struct dc *core_dc, struct pipe_ctx *pipe_ctx) { @@ -1970,19 +1224,104 @@ static void print_rq_dlg_ttu( pipe_ctx->rq_regs.rq_regs_l.pte_row_height_linear ); } +*/ + +static void mmhub_read_vm_system_aperture_settings(struct dcn10_hubp *hubp1, + struct vm_system_aperture_param *apt, + struct dce_hwseq *hws) +{ + PHYSICAL_ADDRESS_LOC physical_page_number; + uint32_t logical_addr_low; + uint32_t logical_addr_high; + + REG_GET(MC_VM_SYSTEM_APERTURE_DEFAULT_ADDR_MSB, + PHYSICAL_PAGE_NUMBER_MSB, &physical_page_number.high_part); + REG_GET(MC_VM_SYSTEM_APERTURE_DEFAULT_ADDR_LSB, + PHYSICAL_PAGE_NUMBER_LSB, &physical_page_number.low_part); + + REG_GET(MC_VM_SYSTEM_APERTURE_LOW_ADDR, + LOGICAL_ADDR, &logical_addr_low); + + REG_GET(MC_VM_SYSTEM_APERTURE_HIGH_ADDR, + LOGICAL_ADDR, &logical_addr_high); + + apt->sys_default.quad_part = physical_page_number.quad_part << 12; + apt->sys_low.quad_part = (int64_t)logical_addr_low << 18; + apt->sys_high.quad_part = (int64_t)logical_addr_high << 18; +} + +/* Temporary read settings, future will get values from kmd directly */ +static void mmhub_read_vm_context0_settings(struct dcn10_hubp *hubp1, + struct vm_context0_param *vm0, + struct dce_hwseq *hws) +{ + PHYSICAL_ADDRESS_LOC fb_base; + PHYSICAL_ADDRESS_LOC fb_offset; + uint32_t fb_base_value; + uint32_t fb_offset_value; + + REG_GET(DCHUBBUB_SDPIF_FB_BASE, SDPIF_FB_BASE, &fb_base_value); + REG_GET(DCHUBBUB_SDPIF_FB_OFFSET, SDPIF_FB_OFFSET, &fb_offset_value); + + REG_GET(VM_CONTEXT0_PAGE_TABLE_BASE_ADDR_HI32, + PAGE_DIRECTORY_ENTRY_HI32, &vm0->pte_base.high_part); + REG_GET(VM_CONTEXT0_PAGE_TABLE_BASE_ADDR_LO32, + PAGE_DIRECTORY_ENTRY_LO32, &vm0->pte_base.low_part); + + REG_GET(VM_CONTEXT0_PAGE_TABLE_START_ADDR_HI32, + LOGICAL_PAGE_NUMBER_HI4, &vm0->pte_start.high_part); + REG_GET(VM_CONTEXT0_PAGE_TABLE_START_ADDR_LO32, + LOGICAL_PAGE_NUMBER_LO32, &vm0->pte_start.low_part); + + REG_GET(VM_CONTEXT0_PAGE_TABLE_END_ADDR_HI32, + LOGICAL_PAGE_NUMBER_HI4, &vm0->pte_end.high_part); + REG_GET(VM_CONTEXT0_PAGE_TABLE_END_ADDR_LO32, + LOGICAL_PAGE_NUMBER_LO32, &vm0->pte_end.low_part); + + REG_GET(VM_L2_PROTECTION_FAULT_DEFAULT_ADDR_HI32, + PHYSICAL_PAGE_ADDR_HI4, &vm0->fault_default.high_part); + REG_GET(VM_L2_PROTECTION_FAULT_DEFAULT_ADDR_LO32, + PHYSICAL_PAGE_ADDR_LO32, &vm0->fault_default.low_part); + + /* + * The values in VM_CONTEXT0_PAGE_TABLE_BASE_ADDR is in UMA space. + * Therefore we need to do + * DCN_VM_CONTEXT0_PAGE_TABLE_BASE_ADDR = VM_CONTEXT0_PAGE_TABLE_BASE_ADDR + * - DCHUBBUB_SDPIF_FB_OFFSET + DCHUBBUB_SDPIF_FB_BASE + */ + fb_base.quad_part = (uint64_t)fb_base_value << 24; + fb_offset.quad_part = (uint64_t)fb_offset_value << 24; + vm0->pte_base.quad_part += fb_base.quad_part; + vm0->pte_base.quad_part -= fb_offset.quad_part; +} + -static void dcn10_power_on_fe( +static void dcn10_program_pte_vm(struct dce_hwseq *hws, struct hubp *hubp) +{ + struct dcn10_hubp *hubp1 = TO_DCN10_HUBP(hubp); + struct vm_system_aperture_param apt = { {{ 0 } } }; + struct vm_context0_param vm0 = { { { 0 } } }; + + mmhub_read_vm_system_aperture_settings(hubp1, &apt, hws); + mmhub_read_vm_context0_settings(hubp1, &vm0, hws); + + hubp->funcs->hubp_set_vm_system_aperture_settings(hubp, &apt); + hubp->funcs->hubp_set_vm_context0_settings(hubp, &vm0); +} + +static void dcn10_enable_plane( struct dc *dc, struct pipe_ctx *pipe_ctx, struct dc_state *context) { - struct dc_plane_state *plane_state = pipe_ctx->plane_state; struct dce_hwseq *hws = dc->hwseq; if (dc->debug.sanity_checks) { - verify_allow_pstate_change_high(dc->hwseq); + dcn10_verify_allow_pstate_change_high(dc); } + undo_DEGVIDCN10_253_wa(dc); + power_on_plane(dc->hwseq, pipe_ctx->pipe_idx); @@ -1993,8 +1332,8 @@ static void dcn10_power_on_fe( /* make sure OPP_PIPE_CLOCK_EN = 1 */ REG_UPDATE(OPP_PIPE_CONTROL[pipe_ctx->stream_res.tg->inst], OPP_PIPE_CLOCK_EN, 1); - /*TODO: REG_UPDATE(DENTIST_DISPCLK_CNTL, DENTIST_DPPCLK_WDIVIDER, 0x1f);*/ +/* TODO: enable/disable in dm as per update type. if (plane_state) { dm_logger_write(dc->ctx->logger, LOG_DC, "Pipe:%d 0x%x: addr hi:0x%x, " @@ -2030,9 +1369,12 @@ static void dcn10_power_on_fe( pipe_ctx->plane_res.scl_data.recout.y); print_rq_dlg_ttu(dc, pipe_ctx); } +*/ + if (dc->config.gpu_vm_support) + dcn10_program_pte_vm(hws, pipe_ctx->plane_res.hubp); if (dc->debug.sanity_checks) { - verify_allow_pstate_change_high(dc->hwseq); + dcn10_verify_allow_pstate_change_high(dc); } } @@ -2082,25 +1424,27 @@ static void program_csc_matrix(struct pipe_ctx *pipe_ctx, enum dc_color_space colorspace, uint16_t *matrix) { - int i; - struct out_csc_color_matrix tbl_entry; - - if (pipe_ctx->stream->csc_color_matrix.enable_adjustment - == true) { - enum dc_color_space color_space = - pipe_ctx->stream->output_color_space; - - //uint16_t matrix[12]; - for (i = 0; i < 12; i++) - tbl_entry.regval[i] = pipe_ctx->stream->csc_color_matrix.matrix[i]; - - tbl_entry.color_space = color_space; - //tbl_entry.regval = matrix; - pipe_ctx->plane_res.dpp->funcs->opp_set_csc_adjustment(pipe_ctx->plane_res.dpp, &tbl_entry); + if (pipe_ctx->stream->csc_color_matrix.enable_adjustment == true) { + if (pipe_ctx->plane_res.dpp->funcs->dpp_set_csc_adjustment != NULL) + pipe_ctx->plane_res.dpp->funcs->dpp_set_csc_adjustment(pipe_ctx->plane_res.dpp, matrix); } else { - pipe_ctx->plane_res.dpp->funcs->opp_set_csc_default(pipe_ctx->plane_res.dpp, colorspace); + if (pipe_ctx->plane_res.dpp->funcs->dpp_set_csc_default != NULL) + pipe_ctx->plane_res.dpp->funcs->dpp_set_csc_default(pipe_ctx->plane_res.dpp, colorspace); } } + +static void program_output_csc(struct dc *dc, + struct pipe_ctx *pipe_ctx, + enum dc_color_space colorspace, + uint16_t *matrix, + int opp_id) +{ + if (pipe_ctx->plane_res.dpp->funcs->dpp_set_csc_adjustment != NULL) + program_csc_matrix(pipe_ctx, + colorspace, + matrix); +} + static bool is_lower_pipe_tree_visible(struct pipe_ctx *pipe_ctx) { if (pipe_ctx->plane_state->visible) @@ -2188,91 +1532,169 @@ static void dcn10_get_surface_visual_confirm_color( } } -static void mmhub_read_vm_system_aperture_settings(struct dcn10_hubp *hubp1, - struct vm_system_aperture_param *apt, - struct dce_hwseq *hws) +static uint16_t fixed_point_to_int_frac( + struct fixed31_32 arg, + uint8_t integer_bits, + uint8_t fractional_bits) { - PHYSICAL_ADDRESS_LOC physical_page_number; - uint32_t logical_addr_low; - uint32_t logical_addr_high; + int32_t numerator; + int32_t divisor = 1 << fractional_bits; - REG_GET(MC_VM_SYSTEM_APERTURE_DEFAULT_ADDR_MSB, - PHYSICAL_PAGE_NUMBER_MSB, &physical_page_number.high_part); - REG_GET(MC_VM_SYSTEM_APERTURE_DEFAULT_ADDR_LSB, - PHYSICAL_PAGE_NUMBER_LSB, &physical_page_number.low_part); + uint16_t result; - REG_GET(MC_VM_SYSTEM_APERTURE_LOW_ADDR, - LOGICAL_ADDR, &logical_addr_low); + uint16_t d = (uint16_t)dal_fixed31_32_floor( + dal_fixed31_32_abs( + arg)); - REG_GET(MC_VM_SYSTEM_APERTURE_HIGH_ADDR, - LOGICAL_ADDR, &logical_addr_high); + if (d <= (uint16_t)(1 << integer_bits) - (1 / (uint16_t)divisor)) + numerator = (uint16_t)dal_fixed31_32_floor( + dal_fixed31_32_mul_int( + arg, + divisor)); + else { + numerator = dal_fixed31_32_floor( + dal_fixed31_32_sub( + dal_fixed31_32_from_int( + 1LL << integer_bits), + dal_fixed31_32_recip( + dal_fixed31_32_from_int( + divisor)))); + } - apt->sys_default.quad_part = physical_page_number.quad_part << 12; - apt->sys_low.quad_part = (int64_t)logical_addr_low << 18; - apt->sys_high.quad_part = (int64_t)logical_addr_high << 18; + if (numerator >= 0) + result = (uint16_t)numerator; + else + result = (uint16_t)( + (1 << (integer_bits + fractional_bits + 1)) + numerator); + + if ((result != 0) && dal_fixed31_32_lt( + arg, dal_fixed31_32_zero)) + result |= 1 << (integer_bits + fractional_bits); + + return result; } -/* Temporary read settings, future will get values from kmd directly */ -static void mmhub_read_vm_context0_settings(struct dcn10_hubp *hubp1, - struct vm_context0_param *vm0, - struct dce_hwseq *hws) +void build_prescale_params(struct dc_bias_and_scale *bias_and_scale, + const struct dc_plane_state *plane_state) +{ + if (plane_state->format >= SURFACE_PIXEL_FORMAT_VIDEO_BEGIN + && plane_state->format != SURFACE_PIXEL_FORMAT_INVALID + && plane_state->input_csc_color_matrix.enable_adjustment + && plane_state->coeff_reduction_factor.value != 0) { + bias_and_scale->scale_blue = fixed_point_to_int_frac( + dal_fixed31_32_mul(plane_state->coeff_reduction_factor, + dal_fixed31_32_from_fraction(256, 255)), + 2, + 13); + bias_and_scale->scale_red = bias_and_scale->scale_blue; + bias_and_scale->scale_green = bias_and_scale->scale_blue; + } else { + bias_and_scale->scale_blue = 0x2000; + bias_and_scale->scale_red = 0x2000; + bias_and_scale->scale_green = 0x2000; + } +} + +static void update_dpp(struct dpp *dpp, struct dc_plane_state *plane_state) { - PHYSICAL_ADDRESS_LOC fb_base; - PHYSICAL_ADDRESS_LOC fb_offset; - uint32_t fb_base_value; - uint32_t fb_offset_value; + struct dc_bias_and_scale bns_params = {0}; - REG_GET(DCHUBBUB_SDPIF_FB_BASE, SDPIF_FB_BASE, &fb_base_value); - REG_GET(DCHUBBUB_SDPIF_FB_OFFSET, SDPIF_FB_OFFSET, &fb_offset_value); + // program the input csc + dpp->funcs->dpp_setup(dpp, + plane_state->format, + EXPANSION_MODE_ZERO, + plane_state->input_csc_color_matrix, + COLOR_SPACE_YCBCR601_LIMITED); - REG_GET(VM_CONTEXT0_PAGE_TABLE_BASE_ADDR_HI32, - PAGE_DIRECTORY_ENTRY_HI32, &vm0->pte_base.high_part); - REG_GET(VM_CONTEXT0_PAGE_TABLE_BASE_ADDR_LO32, - PAGE_DIRECTORY_ENTRY_LO32, &vm0->pte_base.low_part); + //set scale and bias registers + build_prescale_params(&bns_params, plane_state); + if (dpp->funcs->dpp_program_bias_and_scale) + dpp->funcs->dpp_program_bias_and_scale(dpp, &bns_params); +} - REG_GET(VM_CONTEXT0_PAGE_TABLE_START_ADDR_HI32, - LOGICAL_PAGE_NUMBER_HI4, &vm0->pte_start.high_part); - REG_GET(VM_CONTEXT0_PAGE_TABLE_START_ADDR_LO32, - LOGICAL_PAGE_NUMBER_LO32, &vm0->pte_start.low_part); +static void update_mpcc(struct dc *dc, struct pipe_ctx *pipe_ctx) +{ + struct hubp *hubp = pipe_ctx->plane_res.hubp; + struct mpcc_blnd_cfg blnd_cfg; + bool per_pixel_alpha = pipe_ctx->plane_state->per_pixel_alpha && pipe_ctx->bottom_pipe; + int mpcc_id; + struct mpcc *new_mpcc; + struct mpc *mpc = dc->res_pool->mpc; + struct mpc_tree *mpc_tree_params = &(pipe_ctx->stream_res.opp->mpc_tree_params); - REG_GET(VM_CONTEXT0_PAGE_TABLE_END_ADDR_HI32, - LOGICAL_PAGE_NUMBER_HI4, &vm0->pte_end.high_part); - REG_GET(VM_CONTEXT0_PAGE_TABLE_END_ADDR_LO32, - LOGICAL_PAGE_NUMBER_LO32, &vm0->pte_end.low_part); + /* TODO: proper fix once fpga works */ - REG_GET(VM_L2_PROTECTION_FAULT_DEFAULT_ADDR_HI32, - PHYSICAL_PAGE_ADDR_HI4, &vm0->fault_default.high_part); - REG_GET(VM_L2_PROTECTION_FAULT_DEFAULT_ADDR_LO32, - PHYSICAL_PAGE_ADDR_LO32, &vm0->fault_default.low_part); + if (dc->debug.surface_visual_confirm) + dcn10_get_surface_visual_confirm_color( + pipe_ctx, &blnd_cfg.black_color); + else + color_space_to_black_color( + dc, pipe_ctx->stream->output_color_space, + &blnd_cfg.black_color); + + if (per_pixel_alpha) + blnd_cfg.alpha_mode = MPCC_ALPHA_BLEND_MODE_PER_PIXEL_ALPHA; + else + blnd_cfg.alpha_mode = MPCC_ALPHA_BLEND_MODE_GLOBAL_ALPHA; + + blnd_cfg.overlap_only = false; + blnd_cfg.global_alpha = 0xff; + blnd_cfg.global_gain = 0xff; + + /* DCN1.0 has output CM before MPC which seems to screw with + * pre-multiplied alpha. + */ + blnd_cfg.pre_multiplied_alpha = is_rgb_cspace( + pipe_ctx->stream->output_color_space) + && per_pixel_alpha; /* - * The values in VM_CONTEXT0_PAGE_TABLE_BASE_ADDR is in UMA space. - * Therefore we need to do - * DCN_VM_CONTEXT0_PAGE_TABLE_BASE_ADDR = VM_CONTEXT0_PAGE_TABLE_BASE_ADDR - * - DCHUBBUB_SDPIF_FB_OFFSET + DCHUBBUB_SDPIF_FB_BASE + * TODO: remove hack + * Note: currently there is a bug in init_hw such that + * on resume from hibernate, BIOS sets up MPCC0, and + * we do mpcc_remove but the mpcc cannot go to idle + * after remove. This cause us to pick mpcc1 here, + * which causes a pstate hang for yet unknown reason. */ - fb_base.quad_part = (uint64_t)fb_base_value << 24; - fb_offset.quad_part = (uint64_t)fb_offset_value << 24; - vm0->pte_base.quad_part += fb_base.quad_part; - vm0->pte_base.quad_part -= fb_offset.quad_part; + mpcc_id = hubp->inst; + + /* check if this MPCC is already being used */ + new_mpcc = mpc->funcs->get_mpcc_for_dpp(mpc_tree_params, mpcc_id); + /* remove MPCC if being used */ + if (new_mpcc != NULL) + mpc->funcs->remove_mpcc(mpc, mpc_tree_params, new_mpcc); + else + if (dc->debug.sanity_checks) + mpc->funcs->assert_mpcc_idle_before_connect( + dc->res_pool->mpc, mpcc_id); + + /* Call MPC to insert new plane */ + new_mpcc = mpc->funcs->insert_plane(dc->res_pool->mpc, + mpc_tree_params, + &blnd_cfg, + NULL, + NULL, + hubp->inst, + mpcc_id); + + ASSERT(new_mpcc != NULL); + + hubp->opp_id = pipe_ctx->stream_res.opp->inst; + hubp->mpcc_id = mpcc_id; } -static void dcn10_program_pte_vm(struct hubp *hubp, - enum surface_pixel_format format, - union dc_tiling_info *tiling_info, - enum dc_rotation_angle rotation, - struct dce_hwseq *hws) +static void update_scaler(struct pipe_ctx *pipe_ctx) { - struct dcn10_hubp *hubp1 = TO_DCN10_HUBP(hubp); - struct vm_system_aperture_param apt = { {{ 0 } } }; - struct vm_context0_param vm0 = { { { 0 } } }; - + bool per_pixel_alpha = + pipe_ctx->plane_state->per_pixel_alpha && pipe_ctx->bottom_pipe; - mmhub_read_vm_system_aperture_settings(hubp1, &apt, hws); - mmhub_read_vm_context0_settings(hubp1, &vm0, hws); + /* TODO: proper fix once fpga works */ - hubp->funcs->hubp_set_vm_system_aperture_settings(hubp, &apt); - hubp->funcs->hubp_set_vm_context0_settings(hubp, &vm0); + pipe_ctx->plane_res.scl_data.lb_params.alpha_en = per_pixel_alpha; + pipe_ctx->plane_res.scl_data.lb_params.depth = LB_PIXEL_DEPTH_30BPP; + /* scaler configuration */ + pipe_ctx->plane_res.dpp->funcs->dpp_set_scaler( + pipe_ctx->plane_res.dpp, &pipe_ctx->plane_res.scl_data); } static void update_dchubp_dpp( @@ -2285,95 +1707,89 @@ static void update_dchubp_dpp( struct dpp *dpp = pipe_ctx->plane_res.dpp; struct dc_plane_state *plane_state = pipe_ctx->plane_state; union plane_size size = plane_state->plane_size; - struct mpcc_cfg mpcc_cfg = {0}; - struct pipe_ctx *top_pipe; - bool per_pixel_alpha = plane_state->per_pixel_alpha && pipe_ctx->bottom_pipe; - /* TODO: proper fix once fpga works */ /* depends on DML calculation, DPP clock value may change dynamically */ - enable_dppclk( - dc->hwseq, - pipe_ctx->pipe_idx, - pipe_ctx->stream_res.pix_clk_params.requested_pix_clk, - context->bw.dcn.calc_clk.dppclk_div); - dc->current_state->bw.dcn.cur_clk.dppclk_div = - context->bw.dcn.calc_clk.dppclk_div; - context->bw.dcn.cur_clk.dppclk_div = context->bw.dcn.calc_clk.dppclk_div; + if (plane_state->update_flags.bits.full_update) { + enable_dppclk( + dc->hwseq, + pipe_ctx->pipe_idx, + pipe_ctx->stream_res.pix_clk_params.requested_pix_clk, + context->bw.dcn.calc_clk.dppclk_div); + dc->current_state->bw.dcn.cur_clk.dppclk_div = + context->bw.dcn.calc_clk.dppclk_div; + context->bw.dcn.cur_clk.dppclk_div = context->bw.dcn.calc_clk.dppclk_div; + } /* TODO: Need input parameter to tell current DCHUB pipe tie to which OTG * VTG is within DCHUBBUB which is commond block share by each pipe HUBP. * VTG is 1:1 mapping with OTG. Each pipe HUBP will select which VTG */ - REG_UPDATE(DCHUBP_CNTL[pipe_ctx->pipe_idx], HUBP_VTG_SEL, pipe_ctx->stream_res.tg->inst); + if (plane_state->update_flags.bits.full_update) { + REG_UPDATE(DCHUBP_CNTL[pipe_ctx->pipe_idx], HUBP_VTG_SEL, pipe_ctx->stream_res.tg->inst); - hubp->funcs->hubp_setup( - hubp, - &pipe_ctx->dlg_regs, - &pipe_ctx->ttu_regs, - &pipe_ctx->rq_regs, - &pipe_ctx->pipe_dlg_param); + hubp->funcs->hubp_setup( + hubp, + &pipe_ctx->dlg_regs, + &pipe_ctx->ttu_regs, + &pipe_ctx->rq_regs, + &pipe_ctx->pipe_dlg_param); + } size.grph.surface_size = pipe_ctx->plane_res.scl_data.viewport; - if (dc->config.gpu_vm_support) - dcn10_program_pte_vm( - pipe_ctx->plane_res.hubp, - plane_state->format, - &plane_state->tiling_info, - plane_state->rotation, - hws - ); - - dpp->funcs->ipp_setup(dpp, + if (plane_state->update_flags.bits.full_update || + plane_state->update_flags.bits.bpp_change) + update_dpp(dpp, plane_state); + + if (plane_state->update_flags.bits.full_update || + plane_state->update_flags.bits.per_pixel_alpha_change) + update_mpcc(dc, pipe_ctx); + + if (plane_state->update_flags.bits.full_update || + plane_state->update_flags.bits.per_pixel_alpha_change || + plane_state->update_flags.bits.scaling_change || + plane_state->update_flags.bits.position_change) { + update_scaler(pipe_ctx); + } + + if (plane_state->update_flags.bits.full_update || + plane_state->update_flags.bits.scaling_change || + plane_state->update_flags.bits.position_change) { + hubp->funcs->mem_program_viewport( + hubp, + &pipe_ctx->plane_res.scl_data.viewport, + &pipe_ctx->plane_res.scl_data.viewport_c); + } + + if (plane_state->update_flags.bits.full_update) { + /*gamut remap*/ + program_gamut_remap(pipe_ctx); + + program_output_csc(dc, + pipe_ctx, + pipe_ctx->stream->output_color_space, + pipe_ctx->stream->csc_color_matrix.matrix, + hubp->opp_id); + } + + if (plane_state->update_flags.bits.full_update || + plane_state->update_flags.bits.horizontal_mirror_change || + plane_state->update_flags.bits.rotation_change || + plane_state->update_flags.bits.swizzle_change || + plane_state->update_flags.bits.dcc_change || + plane_state->update_flags.bits.bpp_change || + plane_state->update_flags.bits.scaling_change) { + hubp->funcs->hubp_program_surface_config( + hubp, plane_state->format, - EXPANSION_MODE_ZERO); - - mpcc_cfg.dpp_id = hubp->inst; - mpcc_cfg.opp_id = pipe_ctx->stream_res.opp->inst; - mpcc_cfg.tree_cfg = &(pipe_ctx->stream_res.opp->mpc_tree); - for (top_pipe = pipe_ctx->top_pipe; top_pipe; top_pipe = top_pipe->top_pipe) - mpcc_cfg.z_index++; - if (dc->debug.surface_visual_confirm) - dcn10_get_surface_visual_confirm_color( - pipe_ctx, &mpcc_cfg.black_color); - else - color_space_to_black_color( - dc, pipe_ctx->stream->output_color_space, - &mpcc_cfg.black_color); - mpcc_cfg.per_pixel_alpha = per_pixel_alpha; - /* DCN1.0 has output CM before MPC which seems to screw with - * pre-multiplied alpha. - */ - mpcc_cfg.pre_multiplied_alpha = is_rgb_cspace( - pipe_ctx->stream->output_color_space) - && per_pixel_alpha; - hubp->mpcc_id = dc->res_pool->mpc->funcs->add(dc->res_pool->mpc, &mpcc_cfg); - hubp->opp_id = mpcc_cfg.opp_id; - - pipe_ctx->plane_res.scl_data.lb_params.alpha_en = per_pixel_alpha; - pipe_ctx->plane_res.scl_data.lb_params.depth = LB_PIXEL_DEPTH_30BPP; - /* scaler configuration */ - pipe_ctx->plane_res.dpp->funcs->dpp_set_scaler( - pipe_ctx->plane_res.dpp, &pipe_ctx->plane_res.scl_data); - - hubp->funcs->mem_program_viewport(hubp, - &pipe_ctx->plane_res.scl_data.viewport, &pipe_ctx->plane_res.scl_data.viewport_c); - - /*gamut remap*/ - program_gamut_remap(pipe_ctx); - - program_csc_matrix(pipe_ctx, - pipe_ctx->stream->output_color_space, - pipe_ctx->stream->csc_color_matrix.matrix); + &plane_state->tiling_info, + &size, + plane_state->rotation, + &plane_state->dcc, + plane_state->horizontal_mirror); + } - hubp->funcs->hubp_program_surface_config( - hubp, - plane_state->format, - &plane_state->tiling_info, - &size, - plane_state->rotation, - &plane_state->dcc, - plane_state->horizontal_mirror); + hubp->power_gated = false; dc->hwss.update_plane_addr(dc, pipe_ctx); @@ -2387,23 +1803,9 @@ static void program_all_pipe_in_tree( struct pipe_ctx *pipe_ctx, struct dc_state *context) { - unsigned int ref_clk_mhz = dc->res_pool->ref_clock_inKhz/1000; if (pipe_ctx->top_pipe == NULL) { - /* lock otg_master_update to process all pipes associated with - * this OTG. this is done only one time. - */ - /* watermark is for all pipes */ - program_watermarks(dc->hwseq, &context->bw.dcn.watermarks, ref_clk_mhz); - - if (dc->debug.sanity_checks) { - /* pstate stuck check after watermark update */ - verify_allow_pstate_change_high(dc->hwseq); - } - - pipe_ctx->stream_res.tg->funcs->lock(pipe_ctx->stream_res.tg); - pipe_ctx->stream_res.tg->dlg_otg_param.vready_offset = pipe_ctx->pipe_dlg_param.vready_offset; pipe_ctx->stream_res.tg->dlg_otg_param.vstartup_start = pipe_ctx->pipe_dlg_param.vstartup_start; pipe_ctx->stream_res.tg->dlg_otg_param.vupdate_offset = pipe_ctx->pipe_dlg_param.vupdate_offset; @@ -2412,46 +1814,33 @@ static void program_all_pipe_in_tree( pipe_ctx->stream_res.tg->funcs->program_global_sync( pipe_ctx->stream_res.tg); - pipe_ctx->stream_res.tg->funcs->set_blank(pipe_ctx->stream_res.tg, !is_pipe_tree_visible(pipe_ctx)); + + if (pipe_ctx->stream_res.tg->funcs->set_blank) + pipe_ctx->stream_res.tg->funcs->set_blank( + pipe_ctx->stream_res.tg, + !is_pipe_tree_visible(pipe_ctx)); } if (pipe_ctx->plane_state != NULL) { - struct dc_cursor_position position = { 0 }; struct pipe_ctx *cur_pipe_ctx = &dc->current_state->res_ctx.pipe_ctx[pipe_ctx->pipe_idx]; - dcn10_power_on_fe(dc, pipe_ctx, context); - - /* temporary dcn1 wa: - * watermark update requires toggle after a/b/c/d sets are programmed - * if hubp is pg then wm value doesn't get properaged to hubp - * need to toggle after ungate to ensure wm gets to hubp. - * - * final solution: we need to get SMU to do the toggle as - * DCHUBBUB_ARB_WATERMARK_CHANGE_REQUEST is owned by SMU we should have - * both driver and fw accessing same register - */ - toggle_watermark_change_req(dc->hwseq); + if (pipe_ctx->plane_state->update_flags.bits.full_update) + dcn10_enable_plane(dc, pipe_ctx, context); update_dchubp_dpp(dc, pipe_ctx, context); - /* TODO: this is a hack w/a for switching from mpo to pipe split */ - dc_stream_set_cursor_position(pipe_ctx->stream, &position); + if (cur_pipe_ctx->plane_state != pipe_ctx->plane_state) + dc->hwss.set_input_transfer_func(pipe_ctx, pipe_ctx->plane_state); - dc_stream_set_cursor_attributes(pipe_ctx->stream, - &pipe_ctx->stream->cursor_attributes); - - if (cur_pipe_ctx->plane_state != pipe_ctx->plane_state) { - dc->hwss.set_input_transfer_func( - pipe_ctx, pipe_ctx->plane_state); - dc->hwss.set_output_transfer_func( - pipe_ctx, pipe_ctx->stream); - } - } - - if (dc->debug.sanity_checks) { - /* pstate stuck check after each pipe is programmed */ - verify_allow_pstate_change_high(dc->hwseq); + /* dcn10_translate_regamma_to_hw_format takes 750us to finish + * only do gamma programming for full update. + * TODO: This can be further optimized/cleaned up + * Always call this for now since it does memcmp inside before + * doing heavy calculation and programming + */ + if (pipe_ctx->plane_state->update_flags.bits.full_update) + dc->hwss.set_output_transfer_func(pipe_ctx, pipe_ctx->stream); } if (pipe_ctx->bottom_pipe != NULL && pipe_ctx->bottom_pipe != pipe_ctx) @@ -2488,7 +1877,6 @@ static void dcn10_pplib_apply_display_requirements( static void optimize_shared_resources(struct dc *dc) { if (dc->current_state->stream_count == 0) { - apply_DEGVIDCN10_253_wa(dc); /* S0i2 message */ dcn10_pplib_apply_display_requirements(dc, dc->current_state); } @@ -2499,67 +1887,84 @@ static void optimize_shared_resources(struct dc *dc) static void ready_shared_resources(struct dc *dc, struct dc_state *context) { - if (dc->current_state->stream_count == 0 && - !dc->debug.disable_stutter) - undo_DEGVIDCN10_253_wa(dc); - /* S0i2 message */ if (dc->current_state->stream_count == 0 && context->stream_count != 0) dcn10_pplib_apply_display_requirements(dc, context); } +static struct pipe_ctx *find_top_pipe_for_stream( + struct dc *dc, + struct dc_state *context, + const struct dc_stream_state *stream) +{ + int i; + + for (i = 0; i < dc->res_pool->pipe_count; i++) { + struct pipe_ctx *pipe_ctx = &context->res_ctx.pipe_ctx[i]; + struct pipe_ctx *old_pipe_ctx = + &dc->current_state->res_ctx.pipe_ctx[i]; + + if (!pipe_ctx->plane_state && !old_pipe_ctx->plane_state) + continue; + + if (pipe_ctx->stream != stream) + continue; + + if (!pipe_ctx->top_pipe) + return pipe_ctx; + } + return NULL; +} + static void dcn10_apply_ctx_for_surface( struct dc *dc, const struct dc_stream_state *stream, int num_planes, struct dc_state *context) { - int i, be_idx; + int i; + struct timing_generator *tg; + struct output_pixel_processor *opp; + bool removed_pipe[4] = { false }; + unsigned int ref_clk_mhz = dc->res_pool->ref_clock_inKhz/1000; + bool program_water_mark = false; - if (dc->debug.sanity_checks) - verify_allow_pstate_change_high(dc->hwseq); + struct pipe_ctx *top_pipe_to_program = + find_top_pipe_for_stream(dc, context, stream); - be_idx = -1; - for (i = 0; i < dc->res_pool->pipe_count; i++) { - if (stream == context->res_ctx.pipe_ctx[i].stream) { - be_idx = context->res_ctx.pipe_ctx[i].stream_res.tg->inst; - break; - } - } + if (!top_pipe_to_program) + return; + + opp = top_pipe_to_program->stream_res.opp; - ASSERT(be_idx != -1); + tg = top_pipe_to_program->stream_res.tg; + + tg->funcs->lock(tg); if (num_planes == 0) { - for (i = dc->res_pool->pipe_count - 1; i >= 0 ; i--) { - struct pipe_ctx *old_pipe_ctx = - &dc->current_state->res_ctx.pipe_ctx[i]; - if (old_pipe_ctx->stream_res.tg && old_pipe_ctx->stream_res.tg->inst == be_idx) { - old_pipe_ctx->stream_res.tg->funcs->set_blank(old_pipe_ctx->stream_res.tg, true); - dcn10_power_down_fe(dc, old_pipe_ctx->pipe_idx); - } - } - return; + /* OTG blank before remove all front end */ + if (tg->funcs->set_blank) + tg->funcs->set_blank(tg, true); } - /* reset unused mpcc */ + /* Disconnect unused mpcc */ for (i = 0; i < dc->res_pool->pipe_count; i++) { struct pipe_ctx *pipe_ctx = &context->res_ctx.pipe_ctx[i]; struct pipe_ctx *old_pipe_ctx = &dc->current_state->res_ctx.pipe_ctx[i]; - - if (!pipe_ctx->plane_state && !old_pipe_ctx->plane_state) - continue; - /* * Powergate reused pipes that are not powergated * fairly hacky right now, using opp_id as indicator + * TODO: After move dc_post to dc_update, this will + * be removed. */ - if (pipe_ctx->plane_state && !old_pipe_ctx->plane_state) { - if (pipe_ctx->plane_res.hubp->opp_id != 0xf && pipe_ctx->stream_res.tg->inst == be_idx) { - dcn10_power_down_fe(dc, pipe_ctx->pipe_idx); + if (old_pipe_ctx->stream_res.tg == tg && + old_pipe_ctx->plane_res.hubp && + old_pipe_ctx->plane_res.hubp->opp_id != 0xf) { + dcn10_disable_plane(dc, pipe_ctx); /* * power down fe will unlock when calling reset, need * to lock it back here. Messy, need rework. @@ -2568,36 +1973,12 @@ static void dcn10_apply_ctx_for_surface( } } + if (!pipe_ctx->plane_state && + old_pipe_ctx->plane_state && + old_pipe_ctx->stream_res.tg == tg) { - if ((!pipe_ctx->plane_state && old_pipe_ctx->plane_state) - || (!pipe_ctx->stream && old_pipe_ctx->stream)) { - if (old_pipe_ctx->stream_res.tg->inst != be_idx) - continue; - - if (!old_pipe_ctx->top_pipe) { - ASSERT(0); - continue; - } - - /* reset mpc */ - dc->res_pool->mpc->funcs->remove( - dc->res_pool->mpc, - &(old_pipe_ctx->stream_res.opp->mpc_tree), - old_pipe_ctx->stream_res.opp->inst, - old_pipe_ctx->pipe_idx); - old_pipe_ctx->stream_res.opp->mpcc_disconnect_pending[old_pipe_ctx->plane_res.hubp->mpcc_id] = true; - - /*dm_logger_write(dc->ctx->logger, LOG_ERROR, - "[debug_mpo: apply_ctx disconnect pending on mpcc %d]\n", - old_pipe_ctx->mpcc->inst);*/ - - if (dc->debug.sanity_checks) - verify_allow_pstate_change_high(dc->hwseq); - - old_pipe_ctx->top_pipe = NULL; - old_pipe_ctx->bottom_pipe = NULL; - old_pipe_ctx->plane_state = NULL; - old_pipe_ctx->stream = NULL; + plane_atomic_disconnect(dc, old_pipe_ctx); + removed_pipe[i] = true; dm_logger_write(dc->ctx->logger, LOG_DC, "Reset mpcc for pipe %d\n", @@ -2605,18 +1986,44 @@ static void dcn10_apply_ctx_for_surface( } } + if (num_planes > 0) + program_all_pipe_in_tree(dc, top_pipe_to_program, context); + + tg->funcs->unlock(tg); + + if (num_planes == 0) + false_optc_underflow_wa(dc, stream, tg); + for (i = 0; i < dc->res_pool->pipe_count; i++) { + struct pipe_ctx *old_pipe_ctx = + &dc->current_state->res_ctx.pipe_ctx[i]; struct pipe_ctx *pipe_ctx = &context->res_ctx.pipe_ctx[i]; - if (pipe_ctx->stream != stream) - continue; + if (pipe_ctx->stream == stream && + pipe_ctx->plane_state && + pipe_ctx->plane_state->update_flags.bits.full_update) + program_water_mark = true; - /* looking for top pipe to program */ - if (!pipe_ctx->top_pipe) - program_all_pipe_in_tree(dc, pipe_ctx, context); + if (removed_pipe[i]) + dcn10_disable_plane(dc, old_pipe_ctx); } - dm_logger_write(dc->ctx->logger, LOG_BANDWIDTH_CALCS, + if (program_water_mark) { + if (dc->debug.sanity_checks) { + /* pstate stuck check after watermark update */ + dcn10_verify_allow_pstate_change_high(dc); + } + + /* watermark is for all pipes */ + hubbub1_program_watermarks(dc->res_pool->hubbub, + &context->bw.dcn.watermarks, ref_clk_mhz); + + if (dc->debug.sanity_checks) { + /* pstate stuck check after watermark update */ + dcn10_verify_allow_pstate_change_high(dc); + } + } +/* dm_logger_write(dc->ctx->logger, LOG_BANDWIDTH_CALCS, "\n============== Watermark parameters ==============\n" "a.urgent_ns: %d \n" "a.cstate_enter_plus_exit: %d \n" @@ -2662,9 +2069,7 @@ static void dcn10_apply_ctx_for_surface( context->bw.dcn.watermarks.d.cstate_pstate.pstate_change_ns, context->bw.dcn.watermarks.d.pte_meta_urgent_ns ); - - if (dc->debug.sanity_checks) - verify_allow_pstate_change_high(dc->hwseq); +*/ } static void dcn10_set_bandwidth( @@ -2678,7 +2083,7 @@ static void dcn10_set_bandwidth( struct pp_smu_funcs_rv *pp_smu = dc->res_pool->pp_smu; if (dc->debug.sanity_checks) { - verify_allow_pstate_change_high(dc->hwseq); + dcn10_verify_allow_pstate_change_high(dc); } if (IS_FPGA_MAXIMUS_DC(dc->ctx->dce_environment)) @@ -2734,7 +2139,7 @@ static void dcn10_set_bandwidth( dcn10_pplib_apply_display_requirements(dc, context); if (dc->debug.sanity_checks) { - verify_allow_pstate_change_high(dc->hwseq); + dcn10_verify_allow_pstate_change_high(dc); } /* need to fix this function. not doing the right thing here */ @@ -2838,10 +2243,10 @@ static void dcn10_setup_stereo(struct pipe_ctx *pipe_ctx, struct dc *dc) dcn10_config_stereo_parameters(stream, &flags); - pipe_ctx->stream_res.opp->funcs->opp_set_stereo_polarity( + pipe_ctx->stream_res.opp->funcs->opp_program_stereo( pipe_ctx->stream_res.opp, flags.PROGRAM_STEREO == 1 ? true:false, - stream->timing.flags.RIGHT_EYE_3D_POLARITY == 1 ? true:false); + &stream->timing); pipe_ctx->stream_res.tg->funcs->program_stereo( pipe_ctx->stream_res.tg, @@ -2859,7 +2264,7 @@ static void dcn10_wait_for_mpcc_disconnect( int i; if (dc->debug.sanity_checks) { - verify_allow_pstate_change_high(dc->hwseq); + dcn10_verify_allow_pstate_change_high(dc); } if (!pipe_ctx->stream_res.opp) @@ -2877,7 +2282,7 @@ static void dcn10_wait_for_mpcc_disconnect( } if (dc->debug.sanity_checks) { - verify_allow_pstate_change_high(dc->hwseq); + dcn10_verify_allow_pstate_change_high(dc); } } @@ -2911,7 +2316,11 @@ void dcn10_update_pending_status(struct pipe_ctx *pipe_ctx) } } - +void dcn10_update_dchub(struct dce_hwseq *hws, struct dchub_init_data *dh_data) +{ + if (hws->ctx->dc->res_pool->hubbub != NULL) + hubbub1_update_dchub(hws->ctx->dc->res_pool->hubbub, dh_data); +} static const struct hw_sequencer_funcs dcn10_funcs = { .program_gamut_remap = program_gamut_remap, @@ -2928,13 +2337,13 @@ static const struct hw_sequencer_funcs dcn10_funcs = { .power_down = dce110_power_down, .enable_accelerated_mode = dce110_enable_accelerated_mode, .enable_timing_synchronization = dcn10_enable_timing_synchronization, + .enable_per_frame_crtc_position_reset = dcn10_enable_per_frame_crtc_position_reset, .update_info_frame = dce110_update_info_frame, .enable_stream = dce110_enable_stream, .disable_stream = dce110_disable_stream, .unblank_stream = dce110_unblank_stream, .enable_display_power_gating = dcn10_dummy_display_power_gating, - .power_down_front_end = dcn10_power_down_fe, - .power_on_front_end = dcn10_power_on_fe, + .disable_plane = dcn10_disable_plane, .pipe_control_lock = dcn10_pipe_control_lock, .set_bandwidth = dcn10_set_bandwidth, .reset_hw_ctx_wrap = reset_hw_ctx_wrap, @@ -2948,8 +2357,11 @@ static const struct hw_sequencer_funcs dcn10_funcs = { .wait_for_mpcc_disconnect = dcn10_wait_for_mpcc_disconnect, .ready_shared_resources = ready_shared_resources, .optimize_shared_resources = optimize_shared_resources, + .pplib_apply_display_requirements = + dcn10_pplib_apply_display_requirements, .edp_backlight_control = hwss_edp_backlight_control, - .edp_power_control = hwss_edp_power_control + .edp_power_control = hwss_edp_power_control, + .edp_wait_for_hpd_ready = hwss_edp_wait_for_hpd_ready, }; diff --git a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hw_sequencer.h b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hw_sequencer.h index ca53dc1cc19b..b9d326082717 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hw_sequencer.h +++ b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hw_sequencer.h @@ -35,4 +35,5 @@ extern void fill_display_configs( const struct dc_state *context, struct dm_pp_display_configuration *pp_display_cfg); + #endif /* __DC_HWSS_DCN10_H__ */ diff --git a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_mpc.c b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_mpc.c index 76573e1f5b01..179890b1a8c4 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_mpc.c +++ b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_mpc.c @@ -25,8 +25,6 @@ #include "reg_helper.h" #include "dcn10_mpc.h" -#include "dc.h" -#include "mem_input.h" #define REG(reg)\ mpc10->mpc_regs->reg @@ -38,17 +36,13 @@ #define FN(reg_name, field_name) \ mpc10->mpc_shift->field_name, mpc10->mpc_mask->field_name -#define MODE_TOP_ONLY 1 -#define MODE_BLEND 3 -#define BLND_PP_ALPHA 0 -#define BLND_GLOBAL_ALPHA 2 - -static void mpc10_set_bg_color( - struct dcn10_mpc *mpc10, +void mpc1_set_bg_color(struct mpc *mpc, struct tg_color *bg_color, - int id) + int mpcc_id) { + struct dcn10_mpc *mpc10 = TO_DCN10_MPC(mpc); + /* mpc color is 12 bit. tg_color is 10 bit */ /* todo: might want to use 16 bit to represent color and have each * hw block translate to correct color depth. @@ -57,15 +51,47 @@ static void mpc10_set_bg_color( uint32_t bg_g_y = bg_color->color_g_y << 2; uint32_t bg_b_cb = bg_color->color_b_cb << 2; - REG_SET(MPCC_BG_R_CR[id], 0, + REG_SET(MPCC_BG_R_CR[mpcc_id], 0, MPCC_BG_R_CR, bg_r_cr); - REG_SET(MPCC_BG_G_Y[id], 0, + REG_SET(MPCC_BG_G_Y[mpcc_id], 0, MPCC_BG_G_Y, bg_g_y); - REG_SET(MPCC_BG_B_CB[id], 0, + REG_SET(MPCC_BG_B_CB[mpcc_id], 0, MPCC_BG_B_CB, bg_b_cb); } -void mpc10_assert_idle_mpcc(struct mpc *mpc, int id) +static void mpc1_update_blending( + struct mpc *mpc, + struct mpcc_blnd_cfg *blnd_cfg, + int mpcc_id) +{ + struct dcn10_mpc *mpc10 = TO_DCN10_MPC(mpc); + + REG_UPDATE_5(MPCC_CONTROL[mpcc_id], + MPCC_ALPHA_BLND_MODE, blnd_cfg->alpha_mode, + MPCC_ALPHA_MULTIPLIED_MODE, blnd_cfg->pre_multiplied_alpha, + MPCC_BLND_ACTIVE_OVERLAP_ONLY, blnd_cfg->overlap_only, + MPCC_GLOBAL_ALPHA, blnd_cfg->global_alpha, + MPCC_GLOBAL_GAIN, blnd_cfg->global_gain); + + mpc1_set_bg_color(mpc, &blnd_cfg->black_color, mpcc_id); +} + +void mpc1_update_stereo_mix( + struct mpc *mpc, + struct mpcc_sm_cfg *sm_cfg, + int mpcc_id) +{ + struct dcn10_mpc *mpc10 = TO_DCN10_MPC(mpc); + + REG_UPDATE_6(MPCC_SM_CONTROL[mpcc_id], + MPCC_SM_EN, sm_cfg->enable, + MPCC_SM_MODE, sm_cfg->sm_mode, + MPCC_SM_FRAME_ALT, sm_cfg->frame_alt, + MPCC_SM_FIELD_ALT, sm_cfg->field_alt, + MPCC_SM_FORCE_NEXT_FRAME_POL, sm_cfg->force_next_frame_porlarity, + MPCC_SM_FORCE_NEXT_TOP_POL, sm_cfg->force_next_field_polarity); +} +void mpc1_assert_idle_mpcc(struct mpc *mpc, int id) { struct dcn10_mpc *mpc10 = TO_DCN10_MPC(mpc); @@ -75,39 +101,52 @@ void mpc10_assert_idle_mpcc(struct mpc *mpc, int id) 1, 100000); } -static int mpc10_get_idle_mpcc_id(struct dcn10_mpc *mpc10) +struct mpcc *mpc1_get_mpcc(struct mpc *mpc, int mpcc_id) { - int i; - int last_free_mpcc_id = -1; + struct dcn10_mpc *mpc10 = TO_DCN10_MPC(mpc); - for (i = 0; i < mpc10->num_mpcc; i++) { - uint32_t is_idle = 0; + ASSERT(mpcc_id < mpc10->num_mpcc); + return &(mpc->mpcc_array[mpcc_id]); +} - if (mpc10->mpcc_in_use_mask & 1 << i) - continue; +struct mpcc *mpc1_get_mpcc_for_dpp(struct mpc_tree *tree, int dpp_id) +{ + struct mpcc *tmp_mpcc = tree->opp_list; - last_free_mpcc_id = i; - REG_GET(MPCC_STATUS[i], MPCC_IDLE, &is_idle); - if (is_idle) - return i; + while (tmp_mpcc != NULL) { + if (tmp_mpcc->dpp_id == dpp_id) + return tmp_mpcc; + tmp_mpcc = tmp_mpcc->mpcc_bot; } + return NULL; +} - /* This assert should never trigger, we have mpcc leak if it does */ - ASSERT(last_free_mpcc_id != -1); - - mpc10_assert_idle_mpcc(&mpc10->base, last_free_mpcc_id); - return last_free_mpcc_id; +bool mpc1_is_mpcc_idle(struct mpc *mpc, int mpcc_id) +{ + struct dcn10_mpc *mpc10 = TO_DCN10_MPC(mpc); + unsigned int top_sel; + unsigned int opp_id; + unsigned int idle; + + REG_GET(MPCC_TOP_SEL[mpcc_id], MPCC_TOP_SEL, &top_sel); + REG_GET(MPCC_OPP_ID[mpcc_id], MPCC_OPP_ID, &opp_id); + REG_GET(MPCC_STATUS[mpcc_id], MPCC_IDLE, &idle); + if (top_sel == 0xf && opp_id == 0xf && idle) + return true; + else + return false; } -static void mpc10_assert_mpcc_idle_before_connect(struct dcn10_mpc *mpc10, int id) +void mpc1_assert_mpcc_idle_before_connect(struct mpc *mpc, int mpcc_id) { + struct dcn10_mpc *mpc10 = TO_DCN10_MPC(mpc); unsigned int top_sel, mpc_busy, mpc_idle; - REG_GET(MPCC_TOP_SEL[id], + REG_GET(MPCC_TOP_SEL[mpcc_id], MPCC_TOP_SEL, &top_sel); if (top_sel == 0xf) { - REG_GET_2(MPCC_STATUS[id], + REG_GET_2(MPCC_STATUS[mpcc_id], MPCC_BUSY, &mpc_busy, MPCC_IDLE, &mpc_idle); @@ -116,230 +155,269 @@ static void mpc10_assert_mpcc_idle_before_connect(struct dcn10_mpc *mpc10, int i } } -void mpc10_mpcc_remove( - struct mpc *mpc, - struct mpc_tree_cfg *tree_cfg, - int opp_id, - int dpp_id) -{ - struct dcn10_mpc *mpc10 = TO_DCN10_MPC(mpc); - int mpcc_id, z_idx; - - /* find z_idx for the dpp to be removed */ - for (z_idx = 0; z_idx < tree_cfg->num_pipes; z_idx++) - if (tree_cfg->dpp[z_idx] == dpp_id) - break; - - if (z_idx == tree_cfg->num_pipes) { - /* In case of resume from S3/S4, remove mpcc from bios left over */ - REG_SET(MPCC_OPP_ID[dpp_id], 0, - MPCC_OPP_ID, 0xf); - REG_SET(MPCC_TOP_SEL[dpp_id], 0, - MPCC_TOP_SEL, 0xf); - REG_SET(MPCC_BOT_SEL[dpp_id], 0, - MPCC_BOT_SEL, 0xf); - return; - } - - mpcc_id = tree_cfg->mpcc[z_idx]; - - REG_SET(MPCC_OPP_ID[mpcc_id], 0, - MPCC_OPP_ID, 0xf); - REG_SET(MPCC_TOP_SEL[mpcc_id], 0, - MPCC_TOP_SEL, 0xf); - REG_SET(MPCC_BOT_SEL[mpcc_id], 0, - MPCC_BOT_SEL, 0xf); - - if (z_idx > 0) { - int top_mpcc_id = tree_cfg->mpcc[z_idx - 1]; - - if (z_idx + 1 < tree_cfg->num_pipes) - /* mpcc to be removed is in the middle of the tree */ - REG_SET(MPCC_BOT_SEL[top_mpcc_id], 0, - MPCC_BOT_SEL, tree_cfg->mpcc[z_idx + 1]); - else { - /* mpcc to be removed is at the bottom of the tree */ - REG_SET(MPCC_BOT_SEL[top_mpcc_id], 0, - MPCC_BOT_SEL, 0xf); - REG_UPDATE(MPCC_CONTROL[top_mpcc_id], - MPCC_MODE, MODE_TOP_ONLY); - } - } else if (tree_cfg->num_pipes > 1) - /* mpcc to be removed is at the top of the tree */ - REG_SET(MUX[opp_id], 0, - MPC_OUT_MUX, tree_cfg->mpcc[z_idx + 1]); - else - /* mpcc to be removed is the only one in the tree */ - REG_SET(MUX[opp_id], 0, MPC_OUT_MUX, 0xf); - - /* mark this mpcc as not in use */ - mpc10->mpcc_in_use_mask &= ~(1 << mpcc_id); - tree_cfg->num_pipes--; - for (; z_idx < tree_cfg->num_pipes; z_idx++) { - tree_cfg->dpp[z_idx] = tree_cfg->dpp[z_idx + 1]; - tree_cfg->mpcc[z_idx] = tree_cfg->mpcc[z_idx + 1]; - } - tree_cfg->dpp[tree_cfg->num_pipes] = 0xdeadbeef; - tree_cfg->mpcc[tree_cfg->num_pipes] = 0xdeadbeef; -} - -static void mpc10_add_to_tree_cfg( +/* + * Insert DPP into MPC tree based on specified blending position. + * Only used for planes that are part of blending chain for OPP output + * + * Parameters: + * [in/out] mpc - MPC context. + * [in/out] tree - MPC tree structure that plane will be added to. + * [in] blnd_cfg - MPCC blending configuration for the new blending layer. + * [in] sm_cfg - MPCC stereo mix configuration for the new blending layer. + * stereo mix must disable for the very bottom layer of the tree config. + * [in] insert_above_mpcc - Insert new plane above this MPCC. If NULL, insert as bottom plane. + * [in] dpp_id - DPP instance for the plane to be added. + * [in] mpcc_id - The MPCC physical instance to use for blending. + * + * Return: struct mpcc* - MPCC that was added. + */ +struct mpcc *mpc1_insert_plane( struct mpc *mpc, - struct mpcc_cfg *cfg, + struct mpc_tree *tree, + struct mpcc_blnd_cfg *blnd_cfg, + struct mpcc_sm_cfg *sm_cfg, + struct mpcc *insert_above_mpcc, + int dpp_id, int mpcc_id) { struct dcn10_mpc *mpc10 = TO_DCN10_MPC(mpc); - int mpcc_mode = MODE_TOP_ONLY; - int position = cfg->z_index; - struct mpc_tree_cfg *tree_cfg = cfg->tree_cfg; - int alpha_blnd_mode = cfg->per_pixel_alpha ? - BLND_PP_ALPHA : BLND_GLOBAL_ALPHA; - int z_idx; + struct mpcc *new_mpcc = NULL; - REG_SET(MPCC_OPP_ID[mpcc_id], 0, - MPCC_OPP_ID, cfg->opp_id); + /* sanity check parameters */ + ASSERT(mpcc_id < mpc10->num_mpcc); + ASSERT(!(mpc10->mpcc_in_use_mask & 1 << mpcc_id)); - REG_SET(MPCC_TOP_SEL[mpcc_id], 0, - MPCC_TOP_SEL, cfg->dpp_id); + if (insert_above_mpcc) { + /* check insert_above_mpcc exist in tree->opp_list */ + struct mpcc *temp_mpcc = tree->opp_list; - if (position == 0) { - /* idle dpp/mpcc is added to the top layer of tree */ + while (temp_mpcc && temp_mpcc->mpcc_bot != insert_above_mpcc) + temp_mpcc = temp_mpcc->mpcc_bot; + if (temp_mpcc == NULL) + return NULL; + } - if (tree_cfg->num_pipes > 0) { - /* get instance of previous top mpcc */ - int prev_top_mpcc_id = tree_cfg->mpcc[0]; + /* Get and update MPCC struct parameters */ + new_mpcc = mpc1_get_mpcc(mpc, mpcc_id); + new_mpcc->dpp_id = dpp_id; - REG_SET(MPCC_BOT_SEL[mpcc_id], 0, - MPCC_BOT_SEL, prev_top_mpcc_id); - mpcc_mode = MODE_BLEND; + /* program mux and MPCC_MODE */ + if (insert_above_mpcc) { + new_mpcc->mpcc_bot = insert_above_mpcc; + REG_SET(MPCC_BOT_SEL[mpcc_id], 0, MPCC_BOT_SEL, insert_above_mpcc->mpcc_id); + REG_UPDATE(MPCC_CONTROL[mpcc_id], MPCC_MODE, MPCC_BLEND_MODE_TOP_BOT_BLENDING); + } else { + new_mpcc->mpcc_bot = NULL; + REG_SET(MPCC_BOT_SEL[mpcc_id], 0, MPCC_BOT_SEL, 0xf); + REG_UPDATE(MPCC_CONTROL[mpcc_id], MPCC_MODE, MPCC_BLEND_MODE_TOP_LAYER_PASSTHROUGH); + } + REG_SET(MPCC_TOP_SEL[mpcc_id], 0, MPCC_TOP_SEL, dpp_id); + REG_SET(MPCC_OPP_ID[mpcc_id], 0, MPCC_OPP_ID, tree->opp_id); + + /* update mpc tree mux setting */ + if (tree->opp_list == insert_above_mpcc) { + /* insert the toppest mpcc */ + tree->opp_list = new_mpcc; + REG_UPDATE(MUX[tree->opp_id], MPC_OUT_MUX, mpcc_id); + } else { + /* find insert position */ + struct mpcc *temp_mpcc = tree->opp_list; + + while (temp_mpcc && temp_mpcc->mpcc_bot != insert_above_mpcc) + temp_mpcc = temp_mpcc->mpcc_bot; + if (temp_mpcc && temp_mpcc->mpcc_bot == insert_above_mpcc) { + REG_SET(MPCC_BOT_SEL[temp_mpcc->mpcc_id], 0, MPCC_BOT_SEL, mpcc_id); + temp_mpcc->mpcc_bot = new_mpcc; + if (!insert_above_mpcc) + REG_UPDATE(MPCC_CONTROL[temp_mpcc->mpcc_id], + MPCC_MODE, MPCC_BLEND_MODE_TOP_BOT_BLENDING); } + } - /* opp will get new output. from new added mpcc */ - REG_SET(MUX[cfg->opp_id], 0, MPC_OUT_MUX, mpcc_id); - - } else if (position == tree_cfg->num_pipes) { - /* idle dpp/mpcc is added to the bottom layer of tree */ - - /* get instance of previous bottom mpcc, set to middle layer */ - int prev_bot_mpcc_id = tree_cfg->mpcc[tree_cfg->num_pipes - 1]; - - REG_SET(MPCC_BOT_SEL[prev_bot_mpcc_id], 0, - MPCC_BOT_SEL, mpcc_id); - REG_UPDATE(MPCC_CONTROL[prev_bot_mpcc_id], - MPCC_MODE, MODE_BLEND); - - /* mpcc_id become new bottom mpcc*/ - REG_SET(MPCC_BOT_SEL[mpcc_id], 0, - MPCC_BOT_SEL, 0xf); + /* update the blending configuration */ + new_mpcc->blnd_cfg = *blnd_cfg; + mpc->funcs->update_blending(mpc, &new_mpcc->blnd_cfg, mpcc_id); - } else { - /* idle dpp/mpcc is added to middle of tree */ - int above_mpcc_id = tree_cfg->mpcc[position - 1]; - int below_mpcc_id = tree_cfg->mpcc[position]; - - /* mpcc above new mpcc_id has new bottom mux*/ - REG_SET(MPCC_BOT_SEL[above_mpcc_id], 0, - MPCC_BOT_SEL, mpcc_id); - REG_UPDATE(MPCC_CONTROL[above_mpcc_id], - MPCC_MODE, MODE_BLEND); - - /* mpcc_id bottom mux is from below mpcc*/ - REG_SET(MPCC_BOT_SEL[mpcc_id], 0, - MPCC_BOT_SEL, below_mpcc_id); - mpcc_mode = MODE_BLEND; + /* update the stereo mix settings, if provided */ + if (sm_cfg != NULL) { + new_mpcc->sm_cfg = *sm_cfg; + mpc1_update_stereo_mix(mpc, sm_cfg, mpcc_id); } - REG_SET_4(MPCC_CONTROL[mpcc_id], 0xffffffff, - MPCC_MODE, mpcc_mode, - MPCC_ALPHA_BLND_MODE, alpha_blnd_mode, - MPCC_ALPHA_MULTIPLIED_MODE, cfg->pre_multiplied_alpha, - MPCC_BLND_ACTIVE_OVERLAP_ONLY, false); + /* mark this mpcc as in use */ + mpc10->mpcc_in_use_mask |= 1 << mpcc_id; - /* update mpc_tree_cfg with new mpcc */ - for (z_idx = tree_cfg->num_pipes; z_idx > position; z_idx--) { - tree_cfg->dpp[z_idx] = tree_cfg->dpp[z_idx - 1]; - tree_cfg->mpcc[z_idx] = tree_cfg->mpcc[z_idx - 1]; - } - tree_cfg->dpp[position] = cfg->dpp_id; - tree_cfg->mpcc[position] = mpcc_id; - tree_cfg->num_pipes++; + return new_mpcc; } -int mpc10_mpcc_add(struct mpc *mpc, struct mpcc_cfg *cfg) +/* + * Remove a specified MPCC from the MPC tree. + * + * Parameters: + * [in/out] mpc - MPC context. + * [in/out] tree - MPC tree structure that plane will be removed from. + * [in/out] mpcc - MPCC to be removed from tree. + * + * Return: void + */ +void mpc1_remove_mpcc( + struct mpc *mpc, + struct mpc_tree *tree, + struct mpcc *mpcc_to_remove) { struct dcn10_mpc *mpc10 = TO_DCN10_MPC(mpc); - int mpcc_id, z_idx; - - ASSERT(cfg->z_index < mpc10->num_mpcc); - - /* check in dpp already exists in mpc tree */ - for (z_idx = 0; z_idx < cfg->tree_cfg->num_pipes; z_idx++) - if (cfg->tree_cfg->dpp[z_idx] == cfg->dpp_id) - break; - if (z_idx == cfg->tree_cfg->num_pipes) { - ASSERT(cfg->z_index <= cfg->tree_cfg->num_pipes); - mpcc_id = mpc10_get_idle_mpcc_id(mpc10); - - /* - * TODO: remove hack - * Note: currently there is a bug in init_hw such that - * on resume from hibernate, BIOS sets up MPCC0, and - * we do mpcc_remove but the mpcc cannot go to idle - * after remove. This cause us to pick mpcc1 here, - * which causes a pstate hang for yet unknown reason. - */ - mpcc_id = cfg->dpp_id; - /* end hack*/ - - ASSERT(!(mpc10->mpcc_in_use_mask & 1 << mpcc_id)); - - if (mpc->ctx->dc->debug.sanity_checks) - mpc10_assert_mpcc_idle_before_connect(mpc10, mpcc_id); + bool found = false; + int mpcc_id = mpcc_to_remove->mpcc_id; + + if (tree->opp_list == mpcc_to_remove) { + found = true; + /* remove MPCC from top of tree */ + if (mpcc_to_remove->mpcc_bot) { + /* set the next MPCC in list to be the top MPCC */ + tree->opp_list = mpcc_to_remove->mpcc_bot; + REG_UPDATE(MUX[tree->opp_id], MPC_OUT_MUX, tree->opp_list->mpcc_id); + } else { + /* there are no other MPCC is list */ + tree->opp_list = NULL; + REG_UPDATE(MUX[tree->opp_id], MPC_OUT_MUX, 0xf); + } } else { - ASSERT(cfg->z_index < cfg->tree_cfg->num_pipes); - mpcc_id = cfg->tree_cfg->mpcc[z_idx]; - mpc10_mpcc_remove(mpc, cfg->tree_cfg, cfg->opp_id, cfg->dpp_id); + /* find mpcc to remove MPCC list */ + struct mpcc *temp_mpcc = tree->opp_list; + + while (temp_mpcc && temp_mpcc->mpcc_bot != mpcc_to_remove) + temp_mpcc = temp_mpcc->mpcc_bot; + + if (temp_mpcc && temp_mpcc->mpcc_bot == mpcc_to_remove) { + found = true; + temp_mpcc->mpcc_bot = mpcc_to_remove->mpcc_bot; + if (mpcc_to_remove->mpcc_bot) { + /* remove MPCC in middle of list */ + REG_SET(MPCC_BOT_SEL[temp_mpcc->mpcc_id], 0, + MPCC_BOT_SEL, mpcc_to_remove->mpcc_bot->mpcc_id); + } else { + /* remove MPCC from bottom of list */ + REG_SET(MPCC_BOT_SEL[temp_mpcc->mpcc_id], 0, + MPCC_BOT_SEL, 0xf); + REG_UPDATE(MPCC_CONTROL[temp_mpcc->mpcc_id], + MPCC_MODE, MPCC_BLEND_MODE_TOP_LAYER_PASSTHROUGH); + } + } } - /* add dpp/mpcc pair to mpc_tree_cfg and update mpcc registers */ - mpc10_add_to_tree_cfg(mpc, cfg, mpcc_id); - - /* set background color */ - mpc10_set_bg_color(mpc10, &cfg->black_color, mpcc_id); + if (found) { + /* turn off MPCC mux registers */ + REG_SET(MPCC_TOP_SEL[mpcc_id], 0, MPCC_TOP_SEL, 0xf); + REG_SET(MPCC_BOT_SEL[mpcc_id], 0, MPCC_BOT_SEL, 0xf); + REG_SET(MPCC_OPP_ID[mpcc_id], 0, MPCC_OPP_ID, 0xf); - /* mark this mpcc as in use */ - mpc10->mpcc_in_use_mask |= 1 << mpcc_id; + /* mark this mpcc as not in use */ + mpc10->mpcc_in_use_mask &= ~(1 << mpcc_id); + mpcc_to_remove->dpp_id = 0xf; + mpcc_to_remove->mpcc_bot = NULL; + } else { + /* In case of resume from S3/S4, remove mpcc from bios left over */ + REG_SET(MPCC_TOP_SEL[mpcc_id], 0, MPCC_TOP_SEL, 0xf); + REG_SET(MPCC_BOT_SEL[mpcc_id], 0, MPCC_BOT_SEL, 0xf); + REG_SET(MPCC_OPP_ID[mpcc_id], 0, MPCC_OPP_ID, 0xf); + } +} - return mpcc_id; +static void mpc1_init_mpcc(struct mpcc *mpcc, int mpcc_inst) +{ + mpcc->mpcc_id = mpcc_inst; + mpcc->dpp_id = 0xf; + mpcc->mpcc_bot = NULL; + mpcc->blnd_cfg.overlap_only = false; + mpcc->blnd_cfg.global_alpha = 0xff; + mpcc->blnd_cfg.global_gain = 0xff; + mpcc->sm_cfg.enable = false; } -void mpc10_update_blend_mode( - struct mpc *mpc, - struct mpcc_cfg *cfg) +/* + * Reset the MPCC HW status by disconnecting all muxes. + * + * Parameters: + * [in/out] mpc - MPC context. + * + * Return: void + */ +void mpc1_mpc_init(struct mpc *mpc) { struct dcn10_mpc *mpc10 = TO_DCN10_MPC(mpc); - int mpcc_id, z_idx; - int alpha_blnd_mode = cfg->per_pixel_alpha ? - BLND_PP_ALPHA : BLND_GLOBAL_ALPHA; + int mpcc_id; + int opp_id; + + mpc10->mpcc_in_use_mask = 0; + for (mpcc_id = 0; mpcc_id < mpc10->num_mpcc; mpcc_id++) { + REG_SET(MPCC_TOP_SEL[mpcc_id], 0, MPCC_TOP_SEL, 0xf); + REG_SET(MPCC_BOT_SEL[mpcc_id], 0, MPCC_BOT_SEL, 0xf); + REG_SET(MPCC_OPP_ID[mpcc_id], 0, MPCC_OPP_ID, 0xf); - /* find z_idx for the dpp that requires blending mode update*/ - for (z_idx = 0; z_idx < cfg->tree_cfg->num_pipes; z_idx++) - if (cfg->tree_cfg->dpp[z_idx] == cfg->dpp_id) - break; + mpc1_init_mpcc(&(mpc->mpcc_array[mpcc_id]), mpcc_id); + } - ASSERT(z_idx < cfg->tree_cfg->num_pipes); - mpcc_id = cfg->tree_cfg->mpcc[z_idx]; + for (opp_id = 0; opp_id < MAX_OPP; opp_id++) { + if (REG(MUX[opp_id])) + REG_UPDATE(MUX[opp_id], MPC_OUT_MUX, 0xf); + } +} - REG_UPDATE_2(MPCC_CONTROL[mpcc_id], - MPCC_ALPHA_BLND_MODE, alpha_blnd_mode, - MPCC_ALPHA_MULTIPLIED_MODE, cfg->pre_multiplied_alpha); +void mpc1_init_mpcc_list_from_hw( + struct mpc *mpc, + struct mpc_tree *tree) +{ + struct dcn10_mpc *mpc10 = TO_DCN10_MPC(mpc); + unsigned int opp_id; + unsigned int top_sel; + unsigned int bot_sel; + unsigned int out_mux; + struct mpcc *mpcc; + int mpcc_id; + int bot_mpcc_id; + + REG_GET(MUX[tree->opp_id], MPC_OUT_MUX, &out_mux); + + if (out_mux != 0xf) { + for (mpcc_id = 0; mpcc_id < mpc10->num_mpcc; mpcc_id++) { + REG_GET(MPCC_OPP_ID[mpcc_id], MPCC_OPP_ID, &opp_id); + REG_GET(MPCC_TOP_SEL[mpcc_id], MPCC_TOP_SEL, &top_sel); + REG_GET(MPCC_BOT_SEL[mpcc_id], MPCC_BOT_SEL, &bot_sel); + + if (bot_sel == mpcc_id) + bot_sel = 0xf; + + if ((opp_id == tree->opp_id) && (top_sel != 0xf)) { + mpcc = mpc1_get_mpcc(mpc, mpcc_id); + mpcc->dpp_id = top_sel; + mpc10->mpcc_in_use_mask |= 1 << mpcc_id; + + if (out_mux == mpcc_id) + tree->opp_list = mpcc; + if (bot_sel != 0xf && bot_sel < mpc10->num_mpcc) { + bot_mpcc_id = bot_sel; + REG_GET(MPCC_OPP_ID[bot_mpcc_id], MPCC_OPP_ID, &opp_id); + REG_GET(MPCC_TOP_SEL[bot_mpcc_id], MPCC_TOP_SEL, &top_sel); + if ((opp_id == tree->opp_id) && (top_sel != 0xf)) { + struct mpcc *mpcc_bottom = mpc1_get_mpcc(mpc, bot_mpcc_id); + + mpcc->mpcc_bot = mpcc_bottom; + } + } + } + } + } } const struct mpc_funcs dcn10_mpc_funcs = { - .add = mpc10_mpcc_add, - .remove = mpc10_mpcc_remove, - .wait_for_idle = mpc10_assert_idle_mpcc, - .update_blend_mode = mpc10_update_blend_mode, + .insert_plane = mpc1_insert_plane, + .remove_mpcc = mpc1_remove_mpcc, + .mpc_init = mpc1_mpc_init, + .get_mpcc_for_dpp = mpc1_get_mpcc_for_dpp, + .wait_for_idle = mpc1_assert_idle_mpcc, + .assert_mpcc_idle_before_connect = mpc1_assert_mpcc_idle_before_connect, + .init_mpcc_list_from_hw = mpc1_init_mpcc_list_from_hw, + .update_blending = mpc1_update_blending, }; void dcn10_mpc_construct(struct dcn10_mpc *mpc10, @@ -349,6 +427,8 @@ void dcn10_mpc_construct(struct dcn10_mpc *mpc10, const struct dcn_mpc_mask *mpc_mask, int num_mpcc) { + int i; + mpc10->base.ctx = ctx; mpc10->base.funcs = &dcn10_mpc_funcs; @@ -359,5 +439,8 @@ void dcn10_mpc_construct(struct dcn10_mpc *mpc10, mpc10->mpcc_in_use_mask = 0; mpc10->num_mpcc = num_mpcc; + + for (i = 0; i < MAX_MPCC; i++) + mpc1_init_mpcc(&mpc10->base.mpcc_array[i], i); } diff --git a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_mpc.h b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_mpc.h index 683ce4aaa76e..267a2995ef6e 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_mpc.h +++ b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_mpc.h @@ -30,9 +30,6 @@ #define TO_DCN10_MPC(mpc_base) \ container_of(mpc_base, struct dcn10_mpc, base) -#define MAX_MPCC 6 -#define MAX_OPP 6 - #define MPC_COMMON_REG_LIST_DCN1_0(inst) \ SRII(MPCC_TOP_SEL, MPCC, inst),\ SRII(MPCC_BOT_SEL, MPCC, inst),\ @@ -42,7 +39,8 @@ SRII(MPCC_BG_G_Y, MPCC, inst),\ SRII(MPCC_BG_R_CR, MPCC, inst),\ SRII(MPCC_BG_B_CB, MPCC, inst),\ - SRII(MPCC_BG_B_CB, MPCC, inst) + SRII(MPCC_BG_B_CB, MPCC, inst),\ + SRII(MPCC_SM_CONTROL, MPCC, inst) #define MPC_OUT_MUX_COMMON_REG_LIST_DCN1_0(inst) \ SRII(MUX, MPC_OUT, inst) @@ -56,6 +54,7 @@ uint32_t MPCC_BG_G_Y[MAX_MPCC]; \ uint32_t MPCC_BG_R_CR[MAX_MPCC]; \ uint32_t MPCC_BG_B_CB[MAX_MPCC]; \ + uint32_t MPCC_SM_CONTROL[MAX_MPCC]; \ uint32_t MUX[MAX_OPP]; #define MPC_COMMON_MASK_SH_LIST_DCN1_0(mask_sh)\ @@ -65,12 +64,20 @@ SF(MPCC0_MPCC_CONTROL, MPCC_ALPHA_BLND_MODE, mask_sh),\ SF(MPCC0_MPCC_CONTROL, MPCC_ALPHA_MULTIPLIED_MODE, mask_sh),\ SF(MPCC0_MPCC_CONTROL, MPCC_BLND_ACTIVE_OVERLAP_ONLY, mask_sh),\ + SF(MPCC0_MPCC_CONTROL, MPCC_GLOBAL_ALPHA, mask_sh),\ + SF(MPCC0_MPCC_CONTROL, MPCC_GLOBAL_GAIN, mask_sh),\ SF(MPCC0_MPCC_STATUS, MPCC_IDLE, mask_sh),\ SF(MPCC0_MPCC_STATUS, MPCC_BUSY, mask_sh),\ SF(MPCC0_MPCC_OPP_ID, MPCC_OPP_ID, mask_sh),\ SF(MPCC0_MPCC_BG_G_Y, MPCC_BG_G_Y, mask_sh),\ SF(MPCC0_MPCC_BG_R_CR, MPCC_BG_R_CR, mask_sh),\ SF(MPCC0_MPCC_BG_B_CB, MPCC_BG_B_CB, mask_sh),\ + SF(MPCC0_MPCC_SM_CONTROL, MPCC_SM_EN, mask_sh),\ + SF(MPCC0_MPCC_SM_CONTROL, MPCC_SM_MODE, mask_sh),\ + SF(MPCC0_MPCC_SM_CONTROL, MPCC_SM_FRAME_ALT, mask_sh),\ + SF(MPCC0_MPCC_SM_CONTROL, MPCC_SM_FIELD_ALT, mask_sh),\ + SF(MPCC0_MPCC_SM_CONTROL, MPCC_SM_FORCE_NEXT_FRAME_POL, mask_sh),\ + SF(MPCC0_MPCC_SM_CONTROL, MPCC_SM_FORCE_NEXT_TOP_POL, mask_sh),\ SF(MPC_OUT0_MUX, MPC_OUT_MUX, mask_sh) #define MPC_REG_FIELD_LIST(type) \ @@ -80,12 +87,20 @@ type MPCC_ALPHA_BLND_MODE;\ type MPCC_ALPHA_MULTIPLIED_MODE;\ type MPCC_BLND_ACTIVE_OVERLAP_ONLY;\ + type MPCC_GLOBAL_ALPHA;\ + type MPCC_GLOBAL_GAIN;\ type MPCC_IDLE;\ type MPCC_BUSY;\ type MPCC_OPP_ID;\ type MPCC_BG_G_Y;\ type MPCC_BG_R_CR;\ type MPCC_BG_B_CB;\ + type MPCC_SM_EN;\ + type MPCC_SM_MODE;\ + type MPCC_SM_FRAME_ALT;\ + type MPCC_SM_FIELD_ALT;\ + type MPCC_SM_FORCE_NEXT_FRAME_POL;\ + type MPCC_SM_FORCE_NEXT_TOP_POL;\ type MPC_OUT_MUX; struct dcn_mpc_registers { @@ -117,22 +132,55 @@ void dcn10_mpc_construct(struct dcn10_mpc *mpcc10, const struct dcn_mpc_mask *mpc_mask, int num_mpcc); -int mpc10_mpcc_add( - struct mpc *mpc, - struct mpcc_cfg *cfg); - -void mpc10_mpcc_remove( - struct mpc *mpc, - struct mpc_tree_cfg *tree_cfg, - int opp_id, - int dpp_id); - -void mpc10_assert_idle_mpcc( - struct mpc *mpc, - int id); - -void mpc10_update_blend_mode( - struct mpc *mpc, - struct mpcc_cfg *cfg); +struct mpcc *mpc1_insert_plane( + struct mpc *mpc, + struct mpc_tree *tree, + struct mpcc_blnd_cfg *blnd_cfg, + struct mpcc_sm_cfg *sm_cfg, + struct mpcc *insert_above_mpcc, + int dpp_id, + int mpcc_id); + +void mpc1_remove_mpcc( + struct mpc *mpc, + struct mpc_tree *tree, + struct mpcc *mpcc); + +void mpc1_mpc_init( + struct mpc *mpc); + +void mpc1_assert_idle_mpcc( + struct mpc *mpc, + int id); + +void mpc1_set_bg_color( + struct mpc *mpc, + struct tg_color *bg_color, + int id); + +void mpc1_update_stereo_mix( + struct mpc *mpc, + struct mpcc_sm_cfg *sm_cfg, + int mpcc_id); + +bool mpc1_is_mpcc_idle( + struct mpc *mpc, + int mpcc_id); + +void mpc1_assert_mpcc_idle_before_connect( + struct mpc *mpc, + int mpcc_id); + +void mpc1_init_mpcc_list_from_hw( + struct mpc *mpc, + struct mpc_tree *tree); + +struct mpcc *mpc1_get_mpcc( + struct mpc *mpc, + int mpcc_id); + +struct mpcc *mpc1_get_mpcc_for_dpp( + struct mpc_tree *tree, + int dpp_id); #endif diff --git a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_opp.c b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_opp.c index a136f70b7a3c..f6ba0eef4489 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_opp.c +++ b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_opp.c @@ -38,7 +38,6 @@ oppn10->base.ctx - /************* FORMATTER ************/ /** @@ -47,7 +46,7 @@ * 2) enable truncation * 3) HW remove 12bit FMT support for DCE11 power saving reason. */ -static void set_truncation( +static void opp1_set_truncation( struct dcn10_opp *oppn10, const struct bit_depth_reduction_params *params) { @@ -57,7 +56,7 @@ static void set_truncation( FMT_TRUNCATE_MODE, params->flags.TRUNCATE_MODE); } -static void set_spatial_dither( +static void opp1_set_spatial_dither( struct dcn10_opp *oppn10, const struct bit_depth_reduction_params *params) { @@ -136,14 +135,14 @@ static void set_spatial_dither( FMT_RGB_RANDOM_ENABLE, params->flags.RGB_RANDOM); } -static void oppn10_program_bit_depth_reduction( +void opp1_program_bit_depth_reduction( struct output_pixel_processor *opp, const struct bit_depth_reduction_params *params) { struct dcn10_opp *oppn10 = TO_DCN10_OPP(opp); - set_truncation(oppn10, params); - set_spatial_dither(oppn10, params); + opp1_set_truncation(oppn10, params); + opp1_set_spatial_dither(oppn10, params); /* TODO * set_temporal_dither(oppn10, params); */ @@ -156,7 +155,7 @@ static void oppn10_program_bit_depth_reduction( * 0: RGB 4:4:4 or YCbCr 4:4:4 or YOnly * 1: YCbCr 4:2:2 */ -static void set_pixel_encoding( +static void opp1_set_pixel_encoding( struct dcn10_opp *oppn10, const struct clamping_and_pixel_encoding_params *params) { @@ -186,7 +185,7 @@ static void set_pixel_encoding( * 7 for programable * 2) Enable clamp if Limited range requested */ -static void opp_set_clamping( +static void opp1_set_clamping( struct dcn10_opp *oppn10, const struct clamping_and_pixel_encoding_params *params) { @@ -224,7 +223,7 @@ static void opp_set_clamping( } -static void oppn10_set_dyn_expansion( +void opp1_set_dyn_expansion( struct output_pixel_processor *opp, enum dc_color_space color_sp, enum dc_color_depth color_dpth, @@ -264,17 +263,17 @@ static void oppn10_set_dyn_expansion( } } -static void opp_program_clamping_and_pixel_encoding( +static void opp1_program_clamping_and_pixel_encoding( struct output_pixel_processor *opp, const struct clamping_and_pixel_encoding_params *params) { struct dcn10_opp *oppn10 = TO_DCN10_OPP(opp); - opp_set_clamping(oppn10, params); - set_pixel_encoding(oppn10, params); + opp1_set_clamping(oppn10, params); + opp1_set_pixel_encoding(oppn10, params); } -static void oppn10_program_fmt( +void opp1_program_fmt( struct output_pixel_processor *opp, struct bit_depth_reduction_params *fmt_bit_depth, struct clamping_and_pixel_encoding_params *clamping) @@ -286,44 +285,104 @@ static void oppn10_program_fmt( /* dithering is affected by <CrtcSourceSelect>, hence should be * programmed afterwards */ - oppn10_program_bit_depth_reduction( + opp1_program_bit_depth_reduction( opp, fmt_bit_depth); - opp_program_clamping_and_pixel_encoding( + opp1_program_clamping_and_pixel_encoding( opp, clamping); return; } +void opp1_program_stereo( + struct output_pixel_processor *opp, + bool enable, + const struct dc_crtc_timing *timing) +{ + struct dcn10_opp *oppn10 = TO_DCN10_OPP(opp); + + uint32_t active_width = timing->h_addressable - timing->h_border_right - timing->h_border_right; + uint32_t space1_size = timing->v_total - timing->v_addressable; + /* TODO: confirm computation of space2_size */ + uint32_t space2_size = timing->v_total - timing->v_addressable; + if (!enable) { + active_width = 0; + space1_size = 0; + space2_size = 0; + } + + /* TODO: for which cases should FMT_STEREOSYNC_OVERRIDE be set? */ + REG_UPDATE(FMT_CONTROL, FMT_STEREOSYNC_OVERRIDE, 0); + + REG_UPDATE(OPPBUF_CONTROL, OPPBUF_ACTIVE_WIDTH, active_width); + + /* Program OPPBUF_3D_VACT_SPACE1_SIZE and OPPBUF_VACT_SPACE2_SIZE registers + * In 3D progressive frames, Vactive space happens only in between the 2 frames, + * so only need to program OPPBUF_3D_VACT_SPACE1_SIZE + * In 3D alternative frames, left and right frames, top and bottom field. + */ + if (timing->timing_3d_format == TIMING_3D_FORMAT_FRAME_ALTERNATE) + REG_UPDATE(OPPBUF_3D_PARAMETERS_0, OPPBUF_3D_VACT_SPACE2_SIZE, space2_size); + else + REG_UPDATE(OPPBUF_3D_PARAMETERS_0, OPPBUF_3D_VACT_SPACE1_SIZE, space1_size); + + /* TODO: Is programming of OPPBUF_DUMMY_DATA_R/G/B needed? */ + /* + REG_UPDATE(OPPBUF_3D_PARAMETERS_0, + OPPBUF_DUMMY_DATA_R, data_r); + REG_UPDATE(OPPBUF_3D_PARAMETERS_1, + OPPBUF_DUMMY_DATA_G, data_g); + REG_UPDATE(OPPBUF_3D_PARAMETERS_1, + OPPBUF_DUMMY_DATA_B, _data_b); + */ +} -static void oppn10_set_stereo_polarity( - struct output_pixel_processor *opp, - bool enable, bool rightEyePolarity) +void opp1_program_oppbuf( + struct output_pixel_processor *opp, + struct oppbuf_params *oppbuf) { struct dcn10_opp *oppn10 = TO_DCN10_OPP(opp); - REG_UPDATE(FMT_CONTROL, FMT_STEREOSYNC_OVERRIDE, enable); + /* Program the oppbuf active width to be the frame width from mpc */ + REG_UPDATE(OPPBUF_CONTROL, OPPBUF_ACTIVE_WIDTH, oppbuf->active_width); + + /* Specifies the number of segments in multi-segment mode (DP-MSO operation) + * description "In 1/2/4 segment mode, specifies the horizontal active width in pixels of the display panel. + * In 4 segment split left/right mode, specifies the horizontal 1/2 active width in pixels of the display panel. + * Used to determine segment boundaries in multi-segment mode. Used to determine the width of the vertical active space in 3D frame packed modes. + * OPPBUF_ACTIVE_WIDTH must be integer divisible by the total number of segments." + */ + REG_UPDATE(OPPBUF_CONTROL, OPPBUF_DISPLAY_SEGMENTATION, oppbuf->mso_segmentation); + + /* description "Specifies the number of overlap pixels (1-8 overlapping pixels supported), used in multi-segment mode (DP-MSO operation)" */ + REG_UPDATE(OPPBUF_CONTROL, OPPBUF_OVERLAP_PIXEL_NUM, oppbuf->mso_overlap_pixel_num); + + /* description "Specifies the number of times a pixel is replicated (0-15 pixel replications supported). + * A value of 0 disables replication. The total number of times a pixel is output is OPPBUF_PIXEL_REPETITION + 1." + */ + REG_UPDATE(OPPBUF_CONTROL, OPPBUF_PIXEL_REPETITION, oppbuf->pixel_repetition); + } /*****************************************/ /* Constructor, Destructor */ /*****************************************/ -static void dcn10_opp_destroy(struct output_pixel_processor **opp) +void opp1_destroy(struct output_pixel_processor **opp) { kfree(TO_DCN10_OPP(*opp)); *opp = NULL; } static struct opp_funcs dcn10_opp_funcs = { - .opp_set_dyn_expansion = oppn10_set_dyn_expansion, - .opp_program_fmt = oppn10_program_fmt, - .opp_program_bit_depth_reduction = oppn10_program_bit_depth_reduction, - .opp_set_stereo_polarity = oppn10_set_stereo_polarity, - .opp_destroy = dcn10_opp_destroy + .opp_set_dyn_expansion = opp1_set_dyn_expansion, + .opp_program_fmt = opp1_program_fmt, + .opp_program_bit_depth_reduction = opp1_program_bit_depth_reduction, + .opp_program_stereo = opp1_program_stereo, + .opp_destroy = opp1_destroy }; void dcn10_opp_construct(struct dcn10_opp *oppn10, @@ -333,19 +392,12 @@ void dcn10_opp_construct(struct dcn10_opp *oppn10, const struct dcn10_opp_shift *opp_shift, const struct dcn10_opp_mask *opp_mask) { - int i; + oppn10->base.ctx = ctx; oppn10->base.inst = inst; oppn10->base.funcs = &dcn10_opp_funcs; - oppn10->base.mpc_tree.dpp[0] = inst; - oppn10->base.mpc_tree.mpcc[0] = inst; - oppn10->base.mpc_tree.num_pipes = 1; - for (i = 0; i < MAX_PIPES; i++) - oppn10->base.mpcc_disconnect_pending[i] = false; - oppn10->regs = regs; oppn10->opp_shift = opp_shift; oppn10->opp_mask = opp_mask; } - diff --git a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_opp.h b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_opp.h index 790ce6014832..bc5058af6266 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_opp.h +++ b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_opp.h @@ -41,11 +41,28 @@ SRI(FMT_DITHER_RAND_B_SEED, FMT, id), \ SRI(FMT_CLAMP_CNTL, FMT, id), \ SRI(FMT_DYNAMIC_EXP_CNTL, FMT, id), \ - SRI(FMT_MAP420_MEMORY_CONTROL, FMT, id) + SRI(FMT_MAP420_MEMORY_CONTROL, FMT, id), \ + SRI(OPPBUF_CONTROL, OPPBUF, id),\ + SRI(OPPBUF_3D_PARAMETERS_0, OPPBUF, id), \ + SRI(OPPBUF_3D_PARAMETERS_1, OPPBUF, id) #define OPP_REG_LIST_DCN10(id) \ OPP_REG_LIST_DCN(id) +#define OPP_COMMON_REG_VARIABLE_LIST \ + uint32_t FMT_BIT_DEPTH_CONTROL; \ + uint32_t FMT_CONTROL; \ + uint32_t FMT_DITHER_RAND_R_SEED; \ + uint32_t FMT_DITHER_RAND_G_SEED; \ + uint32_t FMT_DITHER_RAND_B_SEED; \ + uint32_t FMT_CLAMP_CNTL; \ + uint32_t FMT_DYNAMIC_EXP_CNTL; \ + uint32_t FMT_MAP420_MEMORY_CONTROL; \ + uint32_t OPPBUF_CONTROL; \ + uint32_t OPPBUF_CONTROL1; \ + uint32_t OPPBUF_3D_PARAMETERS_0; \ + uint32_t OPPBUF_3D_PARAMETERS_1 + #define OPP_MASK_SH_LIST_DCN(mask_sh) \ OPP_SF(FMT0_FMT_BIT_DEPTH_CONTROL, FMT_TRUNCATE_EN, mask_sh), \ OPP_SF(FMT0_FMT_BIT_DEPTH_CONTROL, FMT_TRUNCATE_DEPTH, mask_sh), \ @@ -68,46 +85,18 @@ OPP_SF(FMT0_FMT_CLAMP_CNTL, FMT_CLAMP_COLOR_FORMAT, mask_sh), \ OPP_SF(FMT0_FMT_DYNAMIC_EXP_CNTL, FMT_DYNAMIC_EXP_EN, mask_sh), \ OPP_SF(FMT0_FMT_DYNAMIC_EXP_CNTL, FMT_DYNAMIC_EXP_MODE, mask_sh), \ - OPP_SF(FMT0_FMT_MAP420_MEMORY_CONTROL, FMT_MAP420MEM_PWR_FORCE, mask_sh) + OPP_SF(FMT0_FMT_MAP420_MEMORY_CONTROL, FMT_MAP420MEM_PWR_FORCE, mask_sh), \ + OPP_SF(OPPBUF0_OPPBUF_CONTROL, OPPBUF_ACTIVE_WIDTH, mask_sh),\ + OPP_SF(OPPBUF0_OPPBUF_CONTROL, OPPBUF_PIXEL_REPETITION, mask_sh),\ + OPP_SF(OPPBUF0_OPPBUF_3D_PARAMETERS_0, OPPBUF_3D_VACT_SPACE1_SIZE, mask_sh), \ + OPP_SF(OPPBUF0_OPPBUF_3D_PARAMETERS_0, OPPBUF_3D_VACT_SPACE2_SIZE, mask_sh) #define OPP_MASK_SH_LIST_DCN10(mask_sh) \ - OPP_MASK_SH_LIST_DCN(mask_sh) + OPP_MASK_SH_LIST_DCN(mask_sh), \ + OPP_SF(OPPBUF0_OPPBUF_CONTROL, OPPBUF_DISPLAY_SEGMENTATION, mask_sh),\ + OPP_SF(OPPBUF0_OPPBUF_CONTROL, OPPBUF_OVERLAP_PIXEL_NUM, mask_sh) #define OPP_DCN10_REG_FIELD_LIST(type) \ - type DPG_EN; \ - type DPG_MODE; \ - type DPG_VRES; \ - type DPG_HRES; \ - type DPG_COLOUR0_R_CR; \ - type DPG_COLOUR1_R_CR; \ - type DPG_COLOUR0_B_CB; \ - type DPG_COLOUR1_B_CB; \ - type DPG_COLOUR0_G_Y; \ - type DPG_COLOUR1_G_Y; \ - type CM_OCSC_C11; \ - type CM_OCSC_C12; \ - type CM_OCSC_C13; \ - type CM_OCSC_C14; \ - type CM_OCSC_C21; \ - type CM_OCSC_C22; \ - type CM_OCSC_C23; \ - type CM_OCSC_C24; \ - type CM_OCSC_C31; \ - type CM_OCSC_C32; \ - type CM_OCSC_C33; \ - type CM_OCSC_C34; \ - type CM_COMB_C11; \ - type CM_COMB_C12; \ - type CM_COMB_C13; \ - type CM_COMB_C14; \ - type CM_COMB_C21; \ - type CM_COMB_C22; \ - type CM_COMB_C23; \ - type CM_COMB_C24; \ - type CM_COMB_C31; \ - type CM_COMB_C32; \ - type CM_COMB_C33; \ - type CM_COMB_C34; \ type FMT_TRUNCATE_EN; \ type FMT_TRUNCATE_DEPTH; \ type FMT_TRUNCATE_MODE; \ @@ -129,7 +118,18 @@ type FMT_DYNAMIC_EXP_EN; \ type FMT_DYNAMIC_EXP_MODE; \ type FMT_MAP420MEM_PWR_FORCE; \ - type FMT_STEREOSYNC_OVERRIDE + type FMT_STEREOSYNC_OVERRIDE; \ + type OPPBUF_ACTIVE_WIDTH;\ + type OPPBUF_PIXEL_REPETITION;\ + type OPPBUF_DISPLAY_SEGMENTATION;\ + type OPPBUF_OVERLAP_PIXEL_NUM;\ + type OPPBUF_NUM_SEGMENT_PADDED_PIXELS; \ + type OPPBUF_3D_VACT_SPACE1_SIZE; \ + type OPPBUF_3D_VACT_SPACE2_SIZE + +struct dcn10_opp_registers { + OPP_COMMON_REG_VARIABLE_LIST; +}; struct dcn10_opp_shift { OPP_DCN10_REG_FIELD_LIST(uint8_t); @@ -139,33 +139,6 @@ struct dcn10_opp_mask { OPP_DCN10_REG_FIELD_LIST(uint32_t); }; -struct dcn10_opp_registers { - uint32_t DPG_CONTROL; - uint32_t DPG_COLOUR_B_CB; - uint32_t DPG_COLOUR_G_Y; - uint32_t DPG_COLOUR_R_CR; - uint32_t CM_OCSC_C11_C12; - uint32_t CM_OCSC_C13_C14; - uint32_t CM_OCSC_C21_C22; - uint32_t CM_OCSC_C23_C24; - uint32_t CM_OCSC_C31_C32; - uint32_t CM_OCSC_C33_C34; - uint32_t CM_COMB_C11_C12; - uint32_t CM_COMB_C13_C14; - uint32_t CM_COMB_C21_C22; - uint32_t CM_COMB_C23_C24; - uint32_t CM_COMB_C31_C32; - uint32_t CM_COMB_C33_C34; - uint32_t FMT_BIT_DEPTH_CONTROL; - uint32_t FMT_CONTROL; - uint32_t FMT_DITHER_RAND_R_SEED; - uint32_t FMT_DITHER_RAND_G_SEED; - uint32_t FMT_DITHER_RAND_B_SEED; - uint32_t FMT_CLAMP_CNTL; - uint32_t FMT_DYNAMIC_EXP_CNTL; - uint32_t FMT_MAP420_MEMORY_CONTROL; -}; - struct dcn10_opp { struct output_pixel_processor base; @@ -183,4 +156,26 @@ void dcn10_opp_construct(struct dcn10_opp *oppn10, const struct dcn10_opp_shift *opp_shift, const struct dcn10_opp_mask *opp_mask); +void opp1_set_dyn_expansion( + struct output_pixel_processor *opp, + enum dc_color_space color_sp, + enum dc_color_depth color_dpth, + enum signal_type signal); + +void opp1_program_fmt( + struct output_pixel_processor *opp, + struct bit_depth_reduction_params *fmt_bit_depth, + struct clamping_and_pixel_encoding_params *clamping); + +void opp1_program_bit_depth_reduction( + struct output_pixel_processor *opp, + const struct bit_depth_reduction_params *params); + +void opp1_program_stereo( + struct output_pixel_processor *opp, + bool enable, + const struct dc_crtc_timing *timing); + +void opp1_destroy(struct output_pixel_processor **opp); + #endif diff --git a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_timing_generator.c b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_optc.c index fced178c8c79..4bf64d1b2c60 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_timing_generator.c +++ b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_optc.c @@ -23,19 +23,20 @@ * */ + #include "reg_helper.h" -#include "dcn10_timing_generator.h" +#include "dcn10_optc.h" #include "dc.h" #define REG(reg)\ - tgn10->tg_regs->reg + optc1->tg_regs->reg #define CTX \ - tgn10->base.ctx + optc1->base.ctx #undef FN #define FN(reg_name, field_name) \ - tgn10->tg_shift->field_name, tgn10->tg_mask->field_name + optc1->tg_shift->field_name, optc1->tg_mask->field_name #define STATIC_SCREEN_EVENT_MASK_RANGETIMING_DOUBLE_BUFFER_UPDATE_EN 0x100 @@ -45,8 +46,8 @@ * This is a workaround for a bug that has existed since R5xx and has not been * fixed keep Front porch at minimum 2 for Interlaced mode or 1 for progressive. */ -static void tgn10_apply_front_porch_workaround( - struct timing_generator *tg, +static void optc1_apply_front_porch_workaround( + struct timing_generator *optc, struct dc_crtc_timing *timing) { if (timing->flags.INTERLACE == 1) { @@ -58,30 +59,30 @@ static void tgn10_apply_front_porch_workaround( } } -static void tgn10_program_global_sync( - struct timing_generator *tg) +void optc1_program_global_sync( + struct timing_generator *optc) { - struct dcn10_timing_generator *tgn10 = DCN10TG_FROM_TG(tg); + struct optc *optc1 = DCN10TG_FROM_TG(optc); - if (tg->dlg_otg_param.vstartup_start == 0) { + if (optc->dlg_otg_param.vstartup_start == 0) { BREAK_TO_DEBUGGER(); return; } REG_SET(OTG_VSTARTUP_PARAM, 0, - VSTARTUP_START, tg->dlg_otg_param.vstartup_start); + VSTARTUP_START, optc->dlg_otg_param.vstartup_start); REG_SET_2(OTG_VUPDATE_PARAM, 0, - VUPDATE_OFFSET, tg->dlg_otg_param.vupdate_offset, - VUPDATE_WIDTH, tg->dlg_otg_param.vupdate_width); + VUPDATE_OFFSET, optc->dlg_otg_param.vupdate_offset, + VUPDATE_WIDTH, optc->dlg_otg_param.vupdate_width); REG_SET(OTG_VREADY_PARAM, 0, - VREADY_OFFSET, tg->dlg_otg_param.vready_offset); + VREADY_OFFSET, optc->dlg_otg_param.vready_offset); } -static void tgn10_disable_stereo(struct timing_generator *tg) +static void optc1_disable_stereo(struct timing_generator *optc) { - struct dcn10_timing_generator *tgn10 = DCN10TG_FROM_TG(tg); + struct optc *optc1 = DCN10TG_FROM_TG(optc); REG_SET(OTG_STEREO_CONTROL, 0, OTG_STEREO_EN, 0); @@ -90,11 +91,6 @@ static void tgn10_disable_stereo(struct timing_generator *tg) OTG_3D_STRUCTURE_EN, 0, OTG_3D_STRUCTURE_V_UPDATE_MODE, 0, OTG_3D_STRUCTURE_STEREO_SEL_OVR, 0); - - REG_UPDATE(OPPBUF_CONTROL, - OPPBUF_ACTIVE_WIDTH, 0); - REG_UPDATE(OPPBUF_3D_PARAMETERS_0, - OPPBUF_3D_VACT_SPACE1_SIZE, 0); } /** @@ -102,8 +98,8 @@ static void tgn10_disable_stereo(struct timing_generator *tg) * Program CRTC Timing Registers - OTG_H_*, OTG_V_*, Pixel repetition. * Including SYNC. Call BIOS command table to program Timings. */ -static void tgn10_program_timing( - struct timing_generator *tg, +void optc1_program_timing( + struct timing_generator *optc, const struct dc_crtc_timing *dc_crtc_timing, bool use_vbios) { @@ -121,10 +117,10 @@ static void tgn10_program_timing( uint32_t h_div_2; int32_t vertical_line_start; - struct dcn10_timing_generator *tgn10 = DCN10TG_FROM_TG(tg); + struct optc *optc1 = DCN10TG_FROM_TG(optc); patched_crtc_timing = *dc_crtc_timing; - tgn10_apply_front_porch_workaround(tg, &patched_crtc_timing); + optc1_apply_front_porch_workaround(optc, &patched_crtc_timing); /* Load horizontal timing */ @@ -217,7 +213,7 @@ static void tgn10_program_timing( /* Use OTG_VERTICAL_INTERRUPT2 replace VUPDATE interrupt, * program the reg for interrupt postition. */ - vertical_line_start = asic_blank_end - tg->dlg_otg_param.vstartup_start + 1; + vertical_line_start = asic_blank_end - optc->dlg_otg_param.vstartup_start + 1; if (vertical_line_start < 0) { ASSERT(0); vertical_line_start = 0; @@ -233,26 +229,25 @@ static void tgn10_program_timing( OTG_V_SYNC_A_POL, v_sync_polarity); v_init = asic_blank_start; - if (tg->dlg_otg_param.signal == SIGNAL_TYPE_DISPLAY_PORT || - tg->dlg_otg_param.signal == SIGNAL_TYPE_DISPLAY_PORT_MST || - tg->dlg_otg_param.signal == SIGNAL_TYPE_EDP) { + if (optc->dlg_otg_param.signal == SIGNAL_TYPE_DISPLAY_PORT || + optc->dlg_otg_param.signal == SIGNAL_TYPE_DISPLAY_PORT_MST || + optc->dlg_otg_param.signal == SIGNAL_TYPE_EDP) { start_point = 1; if (patched_crtc_timing.flags.INTERLACE == 1) field_num = 1; } v_fp2 = 0; - if (tg->dlg_otg_param.vstartup_start > asic_blank_end) - v_fp2 = tg->dlg_otg_param.vstartup_start > asic_blank_end; + if (optc->dlg_otg_param.vstartup_start > asic_blank_end) + v_fp2 = optc->dlg_otg_param.vstartup_start > asic_blank_end; /* Interlace */ if (patched_crtc_timing.flags.INTERLACE == 1) { REG_UPDATE(OTG_INTERLACE_CONTROL, OTG_INTERLACE_ENABLE, 1); v_init = v_init / 2; - if ((tg->dlg_otg_param.vstartup_start/2)*2 > asic_blank_end) + if ((optc->dlg_otg_param.vstartup_start/2)*2 > asic_blank_end) v_fp2 = v_fp2 / 2; - } - else + } else REG_UPDATE(OTG_INTERLACE_CONTROL, OTG_INTERLACE_ENABLE, 0); @@ -270,13 +265,13 @@ static void tgn10_program_timing( OTG_START_POINT_CNTL, start_point, OTG_FIELD_NUMBER_CNTL, field_num); - tgn10_program_global_sync(tg); + optc1_program_global_sync(optc); /* TODO * patched_crtc_timing.flags.HORZ_COUNT_BY_TWO == 1 * program_horz_count_by_2 * for DVI 30bpp mode, 0 otherwise - * program_horz_count_by_2(tg, &patched_crtc_timing); + * program_horz_count_by_2(optc, &patched_crtc_timing); */ /* Enable stereo - only when we need to pack 3D frame. Other types @@ -290,13 +285,23 @@ static void tgn10_program_timing( } +static void optc1_set_blank_data_double_buffer(struct timing_generator *optc, bool enable) +{ + struct optc *optc1 = DCN10TG_FROM_TG(optc); + + uint32_t blank_data_double_buffer_enable = enable ? 1 : 0; + + REG_UPDATE(OTG_DOUBLE_BUFFER_CONTROL, + OTG_BLANK_DATA_DOUBLE_BUFFER_EN, blank_data_double_buffer_enable); +} + /** * unblank_crtc * Call ASIC Control Object to UnBlank CRTC. */ -static void tgn10_unblank_crtc(struct timing_generator *tg) +static void optc1_unblank_crtc(struct timing_generator *optc) { - struct dcn10_timing_generator *tgn10 = DCN10TG_FROM_TG(tg); + struct optc *optc1 = DCN10TG_FROM_TG(optc); uint32_t vertical_interrupt_enable = 0; REG_GET(OTG_VERTICAL_INTERRUPT2_CONTROL, @@ -306,8 +311,7 @@ static void tgn10_unblank_crtc(struct timing_generator *tg) * this check will be removed. */ if (vertical_interrupt_enable) - REG_UPDATE(OTG_DOUBLE_BUFFER_CONTROL, - OTG_BLANK_DATA_DOUBLE_BUFFER_EN, 1); + optc1_set_blank_data_double_buffer(optc, true); REG_UPDATE_2(OTG_BLANK_CONTROL, OTG_BLANK_DATA_EN, 0, @@ -319,37 +323,29 @@ static void tgn10_unblank_crtc(struct timing_generator *tg) * Call ASIC Control Object to Blank CRTC. */ -static void tgn10_blank_crtc(struct timing_generator *tg) +static void optc1_blank_crtc(struct timing_generator *optc) { - struct dcn10_timing_generator *tgn10 = DCN10TG_FROM_TG(tg); + struct optc *optc1 = DCN10TG_FROM_TG(optc); REG_UPDATE_2(OTG_BLANK_CONTROL, OTG_BLANK_DATA_EN, 1, OTG_BLANK_DE_MODE, 0); - /* todo: why are we waiting for BLANK_DATA_EN? shouldn't we be waiting - * for status? - */ - REG_WAIT(OTG_BLANK_CONTROL, - OTG_BLANK_DATA_EN, 1, - 1, 100000); - - REG_UPDATE(OTG_DOUBLE_BUFFER_CONTROL, - OTG_BLANK_DATA_DOUBLE_BUFFER_EN, 0); + optc1_set_blank_data_double_buffer(optc, false); } -static void tgn10_set_blank(struct timing_generator *tg, +void optc1_set_blank(struct timing_generator *optc, bool enable_blanking) { if (enable_blanking) - tgn10_blank_crtc(tg); + optc1_blank_crtc(optc); else - tgn10_unblank_crtc(tg); + optc1_unblank_crtc(optc); } -static bool tgn10_is_blanked(struct timing_generator *tg) +bool optc1_is_blanked(struct timing_generator *optc) { - struct dcn10_timing_generator *tgn10 = DCN10TG_FROM_TG(tg); + struct optc *optc1 = DCN10TG_FROM_TG(optc); uint32_t blank_en; uint32_t blank_state; @@ -360,9 +356,9 @@ static bool tgn10_is_blanked(struct timing_generator *tg) return blank_en && blank_state; } -static void tgn10_enable_optc_clock(struct timing_generator *tg, bool enable) +void optc1_enable_optc_clock(struct timing_generator *optc, bool enable) { - struct dcn10_timing_generator *tgn10 = DCN10TG_FROM_TG(tg); + struct optc *optc1 = DCN10TG_FROM_TG(optc); if (enable) { REG_UPDATE_2(OPTC_INPUT_CLOCK_CONTROL, @@ -385,19 +381,9 @@ static void tgn10_enable_optc_clock(struct timing_generator *tg, bool enable) OTG_CLOCK_GATE_DIS, 0, OTG_CLOCK_EN, 0); - if (tg->ctx->dce_environment != DCE_ENV_FPGA_MAXIMUS) - REG_WAIT(OTG_CLOCK_CONTROL, - OTG_CLOCK_ON, 0, - 1, 1000); - REG_UPDATE_2(OPTC_INPUT_CLOCK_CONTROL, OPTC_INPUT_CLK_GATE_DIS, 0, OPTC_INPUT_CLK_EN, 0); - - if (tg->ctx->dce_environment != DCE_ENV_FPGA_MAXIMUS) - REG_WAIT(OPTC_INPUT_CLOCK_CONTROL, - OPTC_INPUT_CLK_ON, 0, - 1, 1000); } } @@ -405,19 +391,19 @@ static void tgn10_enable_optc_clock(struct timing_generator *tg, bool enable) * Enable CRTC * Enable CRTC - call ASIC Control Object to enable Timing generator. */ -static bool tgn10_enable_crtc(struct timing_generator *tg) +static bool optc1_enable_crtc(struct timing_generator *optc) { /* TODO FPGA wait for answer * OTG_MASTER_UPDATE_MODE != CRTC_MASTER_UPDATE_MODE * OTG_MASTER_UPDATE_LOCK != CRTC_MASTER_UPDATE_LOCK */ - struct dcn10_timing_generator *tgn10 = DCN10TG_FROM_TG(tg); + struct optc *optc1 = DCN10TG_FROM_TG(optc); /* opp instance for OTG. For DCN1.0, ODM is remoed. * OPP and OPTC should 1:1 mapping */ REG_UPDATE(OPTC_DATA_SOURCE_SELECT, - OPTC_SRC_SEL, tg->inst); + OPTC_SRC_SEL, optc->inst); /* VTG enable first is for HW workaround */ REG_UPDATE(CONTROL, @@ -432,9 +418,9 @@ static bool tgn10_enable_crtc(struct timing_generator *tg) } /* disable_crtc - call ASIC Control Object to disable Timing generator. */ -static bool tgn10_disable_crtc(struct timing_generator *tg) +bool optc1_disable_crtc(struct timing_generator *optc) { - struct dcn10_timing_generator *tgn10 = DCN10TG_FROM_TG(tg); + struct optc *optc1 = DCN10TG_FROM_TG(optc); /* disable otg request until end of the first line * in the vertical blank region @@ -455,11 +441,11 @@ static bool tgn10_disable_crtc(struct timing_generator *tg) } -static void tgn10_program_blank_color( - struct timing_generator *tg, +void optc1_program_blank_color( + struct timing_generator *optc, const struct tg_color *black_color) { - struct dcn10_timing_generator *tgn10 = DCN10TG_FROM_TG(tg); + struct optc *optc1 = DCN10TG_FROM_TG(optc); REG_SET_3(OTG_BLACK_COLOR, 0, OTG_BLACK_COLOR_B_CB, black_color->color_b_cb, @@ -467,15 +453,15 @@ static void tgn10_program_blank_color( OTG_BLACK_COLOR_R_CR, black_color->color_r_cr); } -static bool tgn10_validate_timing( - struct timing_generator *tg, +bool optc1_validate_timing( + struct timing_generator *optc, const struct dc_crtc_timing *timing) { uint32_t interlace_factor; uint32_t v_blank; uint32_t h_blank; uint32_t min_v_blank; - struct dcn10_timing_generator *tgn10 = DCN10TG_FROM_TG(tg); + struct optc *optc1 = DCN10TG_FROM_TG(optc); ASSERT(timing != NULL); @@ -505,19 +491,19 @@ static bool tgn10_validate_timing( * needs more than 8192 horizontal and * more than 8192 vertical total pixels) */ - if (timing->h_total > tgn10->max_h_total || - timing->v_total > tgn10->max_v_total) + if (timing->h_total > optc1->max_h_total || + timing->v_total > optc1->max_v_total) return false; - if (h_blank < tgn10->min_h_blank) + if (h_blank < optc1->min_h_blank) return false; - if (timing->h_sync_width < tgn10->min_h_sync_width || - timing->v_sync_width < tgn10->min_v_sync_width) + if (timing->h_sync_width < optc1->min_h_sync_width || + timing->v_sync_width < optc1->min_v_sync_width) return false; - min_v_blank = timing->flags.INTERLACE?tgn10->min_v_blank_interlace:tgn10->min_v_blank; + min_v_blank = timing->flags.INTERLACE?optc1->min_v_blank_interlace:optc1->min_v_blank; if (v_blank < min_v_blank) return false; @@ -534,15 +520,15 @@ static bool tgn10_validate_timing( * holds the counter of frames. * * @param - * struct timing_generator *tg - [in] timing generator which controls the + * struct timing_generator *optc - [in] timing generator which controls the * desired CRTC * * @return * Counter of frames, which should equal to number of vblanks. */ -static uint32_t tgn10_get_vblank_counter(struct timing_generator *tg) +uint32_t optc1_get_vblank_counter(struct timing_generator *optc) { - struct dcn10_timing_generator *tgn10 = DCN10TG_FROM_TG(tg); + struct optc *optc1 = DCN10TG_FROM_TG(optc); uint32_t frame_count; REG_GET(OTG_STATUS_FRAME_COUNT, @@ -551,38 +537,34 @@ static uint32_t tgn10_get_vblank_counter(struct timing_generator *tg) return frame_count; } -static void tgn10_lock(struct timing_generator *tg) +void optc1_lock(struct timing_generator *optc) { - struct dcn10_timing_generator *tgn10 = DCN10TG_FROM_TG(tg); + struct optc *optc1 = DCN10TG_FROM_TG(optc); REG_SET(OTG_GLOBAL_CONTROL0, 0, - OTG_MASTER_UPDATE_LOCK_SEL, tg->inst); + OTG_MASTER_UPDATE_LOCK_SEL, optc->inst); REG_SET(OTG_MASTER_UPDATE_LOCK, 0, OTG_MASTER_UPDATE_LOCK, 1); - if (tg->ctx->dce_environment != DCE_ENV_FPGA_MAXIMUS) + /* Should be fast, status does not update on maximus */ + if (optc->ctx->dce_environment != DCE_ENV_FPGA_MAXIMUS) REG_WAIT(OTG_MASTER_UPDATE_LOCK, UPDATE_LOCK_STATUS, 1, - 1, 100); + 1, 10); } -static void tgn10_unlock(struct timing_generator *tg) +void optc1_unlock(struct timing_generator *optc) { - struct dcn10_timing_generator *tgn10 = DCN10TG_FROM_TG(tg); + struct optc *optc1 = DCN10TG_FROM_TG(optc); REG_SET(OTG_MASTER_UPDATE_LOCK, 0, OTG_MASTER_UPDATE_LOCK, 0); - - /* why are we waiting here? */ - REG_WAIT(OTG_DOUBLE_BUFFER_CONTROL, - OTG_UPDATE_PENDING, 0, - 1, 100000); } -static void tgn10_get_position(struct timing_generator *tg, +void optc1_get_position(struct timing_generator *optc, struct crtc_position *position) { - struct dcn10_timing_generator *tgn10 = DCN10TG_FROM_TG(tg); + struct optc *optc1 = DCN10TG_FROM_TG(optc); REG_GET_2(OTG_STATUS_POSITION, OTG_HORZ_COUNT, &position->horizontal_count, @@ -592,12 +574,12 @@ static void tgn10_get_position(struct timing_generator *tg, OTG_VERT_COUNT_NOM, &position->nominal_vcount); } -static bool tgn10_is_counter_moving(struct timing_generator *tg) +bool optc1_is_counter_moving(struct timing_generator *optc) { struct crtc_position position1, position2; - tg->funcs->get_position(tg, &position1); - tg->funcs->get_position(tg, &position2); + optc->funcs->get_position(optc, &position1); + optc->funcs->get_position(optc, &position2); if (position1.horizontal_count == position2.horizontal_count && position1.vertical_count == position2.vertical_count) @@ -606,21 +588,37 @@ static bool tgn10_is_counter_moving(struct timing_generator *tg) return true; } -static bool tgn10_did_triggered_reset_occur( - struct timing_generator *tg) +bool optc1_did_triggered_reset_occur( + struct timing_generator *optc) { - struct dcn10_timing_generator *tgn10 = DCN10TG_FROM_TG(tg); - uint32_t occurred; + struct optc *optc1 = DCN10TG_FROM_TG(optc); + uint32_t occurred_force, occurred_vsync; REG_GET(OTG_FORCE_COUNT_NOW_CNTL, - OTG_FORCE_COUNT_NOW_OCCURRED, &occurred); + OTG_FORCE_COUNT_NOW_OCCURRED, &occurred_force); + + REG_GET(OTG_VERT_SYNC_CONTROL, + OTG_FORCE_VSYNC_NEXT_LINE_OCCURRED, &occurred_vsync); + + return occurred_vsync != 0 || occurred_force != 0; +} + +void optc1_disable_reset_trigger(struct timing_generator *optc) +{ + struct optc *optc1 = DCN10TG_FROM_TG(optc); + + REG_WRITE(OTG_TRIGA_CNTL, 0); + + REG_SET(OTG_FORCE_COUNT_NOW_CNTL, 0, + OTG_FORCE_COUNT_NOW_CLEAR, 1); - return occurred != 0; + REG_SET(OTG_VERT_SYNC_CONTROL, 0, + OTG_FORCE_VSYNC_NEXT_LINE_CLEAR, 1); } -static void tgn10_enable_reset_trigger(struct timing_generator *tg, int source_tg_inst) +void optc1_enable_reset_trigger(struct timing_generator *optc, int source_tg_inst) { - struct dcn10_timing_generator *tgn10 = DCN10TG_FROM_TG(tg); + struct optc *optc1 = DCN10TG_FROM_TG(optc); uint32_t falling_edge; REG_GET(OTG_V_SYNC_A_CNTL, @@ -652,20 +650,55 @@ static void tgn10_enable_reset_trigger(struct timing_generator *tg, int source_t OTG_FORCE_COUNT_NOW_MODE, 2); } -static void tgn10_disable_reset_trigger(struct timing_generator *tg) +void optc1_enable_crtc_reset( + struct timing_generator *optc, + int source_tg_inst, + struct crtc_trigger_info *crtc_tp) { - struct dcn10_timing_generator *tgn10 = DCN10TG_FROM_TG(tg); + struct optc *optc1 = DCN10TG_FROM_TG(optc); + uint32_t falling_edge = 0; + uint32_t rising_edge = 0; - REG_WRITE(OTG_TRIGA_CNTL, 0); + switch (crtc_tp->event) { - REG_SET(OTG_FORCE_COUNT_NOW_CNTL, 0, - OTG_FORCE_COUNT_NOW_CLEAR, 1); + case CRTC_EVENT_VSYNC_RISING: + rising_edge = 1; + break; + + case CRTC_EVENT_VSYNC_FALLING: + falling_edge = 1; + break; + } + + REG_SET_4(OTG_TRIGA_CNTL, 0, + /* vsync signal from selected OTG pipe based + * on OTG_TRIG_SOURCE_PIPE_SELECT setting + */ + OTG_TRIGA_SOURCE_SELECT, 20, + OTG_TRIGA_SOURCE_PIPE_SELECT, source_tg_inst, + /* always detect falling edge */ + OTG_TRIGA_RISING_EDGE_DETECT_CNTL, rising_edge, + OTG_TRIGA_FALLING_EDGE_DETECT_CNTL, falling_edge); + + switch (crtc_tp->delay) { + case TRIGGER_DELAY_NEXT_LINE: + REG_SET(OTG_VERT_SYNC_CONTROL, 0, + OTG_AUTO_FORCE_VSYNC_MODE, 1); + break; + case TRIGGER_DELAY_NEXT_PIXEL: + REG_SET(OTG_FORCE_COUNT_NOW_CNTL, 0, + /* force H count to H_TOTAL and V count to V_TOTAL in + * progressive mode and V_TOTAL-1 in interlaced mode + */ + OTG_FORCE_COUNT_NOW_MODE, 2); + break; + } } -static void tgn10_wait_for_state(struct timing_generator *tg, +void optc1_wait_for_state(struct timing_generator *optc, enum crtc_state state) { - struct dcn10_timing_generator *tgn10 = DCN10TG_FROM_TG(tg); + struct optc *optc1 = DCN10TG_FROM_TG(optc); switch (state) { case CRTC_STATE_VBLANK: @@ -685,8 +718,8 @@ static void tgn10_wait_for_state(struct timing_generator *tg, } } -static void tgn10_set_early_control( - struct timing_generator *tg, +void optc1_set_early_control( + struct timing_generator *optc, uint32_t early_cntl) { /* asic design change, do not need this control @@ -695,11 +728,11 @@ static void tgn10_set_early_control( } -static void tgn10_set_static_screen_control( - struct timing_generator *tg, +void optc1_set_static_screen_control( + struct timing_generator *optc, uint32_t value) { - struct dcn10_timing_generator *tgn10 = DCN10TG_FROM_TG(tg); + struct optc *optc1 = DCN10TG_FROM_TG(optc); /* Bit 8 is no longer applicable in RV for PSR case, * set bit 8 to 0 if given @@ -724,11 +757,11 @@ static void tgn10_set_static_screen_control( * ***************************************************************************** */ -static void tgn10_set_drr( - struct timing_generator *tg, +void optc1_set_drr( + struct timing_generator *optc, const struct drr_params *params) { - struct dcn10_timing_generator *tgn10 = DCN10TG_FROM_TG(tg); + struct optc *optc1 = DCN10TG_FROM_TG(optc); if (params != NULL && params->vertical_total_max > 0 && @@ -761,15 +794,15 @@ static void tgn10_set_drr( } } -static void tgn10_set_test_pattern( - struct timing_generator *tg, +static void optc1_set_test_pattern( + struct timing_generator *optc, /* TODO: replace 'controller_dp_test_pattern' by 'test_pattern_mode' * because this is not DP-specific (which is probably somewhere in DP * encoder) */ enum controller_dp_test_pattern test_pattern, enum dc_color_depth color_depth) { - struct dcn10_timing_generator *tgn10 = DCN10TG_FROM_TG(tg); + struct optc *optc1 = DCN10TG_FROM_TG(optc); enum test_pattern_color_format bit_depth; enum test_pattern_dyn_range dyn_range; enum test_pattern_mode mode; @@ -1020,35 +1053,30 @@ static void tgn10_set_test_pattern( } } -static void tgn10_get_crtc_scanoutpos( - struct timing_generator *tg, +void optc1_get_crtc_scanoutpos( + struct timing_generator *optc, uint32_t *v_blank_start, uint32_t *v_blank_end, uint32_t *h_position, uint32_t *v_position) { - struct dcn10_timing_generator *tgn10 = DCN10TG_FROM_TG(tg); + struct optc *optc1 = DCN10TG_FROM_TG(optc); struct crtc_position position; REG_GET_2(OTG_V_BLANK_START_END, OTG_V_BLANK_START, v_blank_start, OTG_V_BLANK_END, v_blank_end); - tgn10_get_position(tg, &position); + optc1_get_position(optc, &position); *h_position = position.horizontal_count; *v_position = position.vertical_count; } - - -static void tgn10_enable_stereo(struct timing_generator *tg, +static void optc1_enable_stereo(struct timing_generator *optc, const struct dc_crtc_timing *timing, struct crtc_stereo_flags *flags) { - struct dcn10_timing_generator *tgn10 = DCN10TG_FROM_TG(tg); - - uint32_t active_width = timing->h_addressable; - uint32_t space1_size = timing->v_total - timing->v_addressable; + struct optc *optc1 = DCN10TG_FROM_TG(optc); if (flags) { uint32_t stereo_en; @@ -1076,29 +1104,23 @@ static void tgn10_enable_stereo(struct timing_generator *tg, OTG_3D_STRUCTURE_STEREO_SEL_OVR, flags->FRAME_PACKED); } - - REG_UPDATE(OPPBUF_CONTROL, - OPPBUF_ACTIVE_WIDTH, active_width); - - REG_UPDATE(OPPBUF_3D_PARAMETERS_0, - OPPBUF_3D_VACT_SPACE1_SIZE, space1_size); } -static void tgn10_program_stereo(struct timing_generator *tg, +void optc1_program_stereo(struct timing_generator *optc, const struct dc_crtc_timing *timing, struct crtc_stereo_flags *flags) { if (flags->PROGRAM_STEREO) - tgn10_enable_stereo(tg, timing, flags); + optc1_enable_stereo(optc, timing, flags); else - tgn10_disable_stereo(tg); + optc1_disable_stereo(optc); } -static bool tgn10_is_stereo_left_eye(struct timing_generator *tg) +bool optc1_is_stereo_left_eye(struct timing_generator *optc) { bool ret = false; uint32_t left_eye = 0; - struct dcn10_timing_generator *tgn10 = DCN10TG_FROM_TG(tg); + struct optc *optc1 = DCN10TG_FROM_TG(optc); REG_GET(OTG_STEREO_STATUS, OTG_STEREO_CURRENT_EYE, &left_eye); @@ -1110,7 +1132,7 @@ static bool tgn10_is_stereo_left_eye(struct timing_generator *tg) return ret; } -void tgn10_read_otg_state(struct dcn10_timing_generator *tgn10, +void optc1_read_otg_state(struct optc *optc1, struct dcn_otg_state *s) { REG_GET(OTG_CONTROL, @@ -1154,47 +1176,88 @@ void tgn10_read_otg_state(struct dcn10_timing_generator *tgn10, OPTC_UNDERFLOW_OCCURRED_STATUS, &s->underflow_occurred_status); } +static void optc1_clear_optc_underflow(struct timing_generator *optc) +{ + struct optc *optc1 = DCN10TG_FROM_TG(optc); + + REG_UPDATE(OPTC_INPUT_GLOBAL_CONTROL, OPTC_UNDERFLOW_CLEAR, 1); +} + +static void optc1_tg_init(struct timing_generator *optc) +{ + optc1_set_blank_data_double_buffer(optc, true); + optc1_clear_optc_underflow(optc); +} + +static bool optc1_is_tg_enabled(struct timing_generator *optc) +{ + struct optc *optc1 = DCN10TG_FROM_TG(optc); + uint32_t otg_enabled = 0; + + REG_GET(OTG_CONTROL, OTG_MASTER_EN, &otg_enabled); + + return (otg_enabled != 0); + +} + +static bool optc1_is_optc_underflow_occurred(struct timing_generator *optc) +{ + struct optc *optc1 = DCN10TG_FROM_TG(optc); + uint32_t underflow_occurred = 0; + + REG_GET(OPTC_INPUT_GLOBAL_CONTROL, + OPTC_UNDERFLOW_OCCURRED_STATUS, + &underflow_occurred); + + return (underflow_occurred == 1); +} static const struct timing_generator_funcs dcn10_tg_funcs = { - .validate_timing = tgn10_validate_timing, - .program_timing = tgn10_program_timing, - .program_global_sync = tgn10_program_global_sync, - .enable_crtc = tgn10_enable_crtc, - .disable_crtc = tgn10_disable_crtc, + .validate_timing = optc1_validate_timing, + .program_timing = optc1_program_timing, + .program_global_sync = optc1_program_global_sync, + .enable_crtc = optc1_enable_crtc, + .disable_crtc = optc1_disable_crtc, /* used by enable_timing_synchronization. Not need for FPGA */ - .is_counter_moving = tgn10_is_counter_moving, - .get_position = tgn10_get_position, - .get_frame_count = tgn10_get_vblank_counter, - .get_scanoutpos = tgn10_get_crtc_scanoutpos, - .set_early_control = tgn10_set_early_control, + .is_counter_moving = optc1_is_counter_moving, + .get_position = optc1_get_position, + .get_frame_count = optc1_get_vblank_counter, + .get_scanoutpos = optc1_get_crtc_scanoutpos, + .set_early_control = optc1_set_early_control, /* used by enable_timing_synchronization. Not need for FPGA */ - .wait_for_state = tgn10_wait_for_state, - .set_blank = tgn10_set_blank, - .is_blanked = tgn10_is_blanked, - .set_blank_color = tgn10_program_blank_color, - .did_triggered_reset_occur = tgn10_did_triggered_reset_occur, - .enable_reset_trigger = tgn10_enable_reset_trigger, - .disable_reset_trigger = tgn10_disable_reset_trigger, - .lock = tgn10_lock, - .unlock = tgn10_unlock, - .enable_optc_clock = tgn10_enable_optc_clock, - .set_drr = tgn10_set_drr, - .set_static_screen_control = tgn10_set_static_screen_control, - .set_test_pattern = tgn10_set_test_pattern, - .program_stereo = tgn10_program_stereo, - .is_stereo_left_eye = tgn10_is_stereo_left_eye + .wait_for_state = optc1_wait_for_state, + .set_blank = optc1_set_blank, + .is_blanked = optc1_is_blanked, + .set_blank_color = optc1_program_blank_color, + .did_triggered_reset_occur = optc1_did_triggered_reset_occur, + .enable_reset_trigger = optc1_enable_reset_trigger, + .enable_crtc_reset = optc1_enable_crtc_reset, + .disable_reset_trigger = optc1_disable_reset_trigger, + .lock = optc1_lock, + .unlock = optc1_unlock, + .enable_optc_clock = optc1_enable_optc_clock, + .set_drr = optc1_set_drr, + .set_static_screen_control = optc1_set_static_screen_control, + .set_test_pattern = optc1_set_test_pattern, + .program_stereo = optc1_program_stereo, + .is_stereo_left_eye = optc1_is_stereo_left_eye, + .set_blank_data_double_buffer = optc1_set_blank_data_double_buffer, + .tg_init = optc1_tg_init, + .is_tg_enabled = optc1_is_tg_enabled, + .is_optc_underflow_occurred = optc1_is_optc_underflow_occurred, + .clear_optc_underflow = optc1_clear_optc_underflow, }; -void dcn10_timing_generator_init(struct dcn10_timing_generator *tgn10) +void dcn10_timing_generator_init(struct optc *optc1) { - tgn10->base.funcs = &dcn10_tg_funcs; + optc1->base.funcs = &dcn10_tg_funcs; - tgn10->max_h_total = tgn10->tg_mask->OTG_H_TOTAL + 1; - tgn10->max_v_total = tgn10->tg_mask->OTG_V_TOTAL + 1; + optc1->max_h_total = optc1->tg_mask->OTG_H_TOTAL + 1; + optc1->max_v_total = optc1->tg_mask->OTG_V_TOTAL + 1; - tgn10->min_h_blank = 32; - tgn10->min_v_blank = 3; - tgn10->min_v_blank_interlace = 5; - tgn10->min_h_sync_width = 8; - tgn10->min_v_sync_width = 1; + optc1->min_h_blank = 32; + optc1->min_v_blank = 3; + optc1->min_v_blank_interlace = 5; + optc1->min_h_sync_width = 8; + optc1->min_v_sync_width = 1; } diff --git a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_timing_generator.h b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_optc.h index 7d4818d7aa31..a3c7c2012f05 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_timing_generator.h +++ b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_optc.h @@ -29,7 +29,7 @@ #include "timing_generator.h" #define DCN10TG_FROM_TG(tg)\ - container_of(tg, struct dcn10_timing_generator, base) + container_of(tg, struct optc, base) #define TG_COMMON_REG_LIST_DCN(inst) \ SRI(OTG_VSTARTUP_PARAM, OTG, inst),\ @@ -70,9 +70,10 @@ SRI(OPTC_INPUT_CLOCK_CONTROL, ODM, inst),\ SRI(OPTC_DATA_SOURCE_SELECT, ODM, inst),\ SRI(OPTC_INPUT_GLOBAL_CONTROL, ODM, inst),\ - SRI(OPPBUF_CONTROL, OPPBUF, inst),\ - SRI(OPPBUF_3D_PARAMETERS_0, OPPBUF, inst),\ - SRI(CONTROL, VTG, inst) + SRI(CONTROL, VTG, inst),\ + SRI(OTG_VERT_SYNC_CONTROL, OTG, inst),\ + SRI(OTG_MASTER_UPDATE_MODE, OTG, inst),\ + SRI(OTG_GSL_CONTROL, OTG, inst) #define TG_COMMON_REG_LIST_DCN1_0(inst) \ TG_COMMON_REG_LIST_DCN(inst),\ @@ -81,7 +82,10 @@ SRI(OTG_TEST_PATTERN_COLOR, OTG, inst) -struct dcn_tg_registers { +struct dcn_optc_registers { + uint32_t OTG_VERT_SYNC_CONTROL; + uint32_t OTG_MASTER_UPDATE_MODE; + uint32_t OTG_GSL_CONTROL; uint32_t OTG_VSTARTUP_PARAM; uint32_t OTG_VUPDATE_PARAM; uint32_t OTG_VREADY_PARAM; @@ -123,9 +127,11 @@ struct dcn_tg_registers { uint32_t OPTC_INPUT_CLOCK_CONTROL; uint32_t OPTC_DATA_SOURCE_SELECT; uint32_t OPTC_INPUT_GLOBAL_CONTROL; - uint32_t OPPBUF_CONTROL; - uint32_t OPPBUF_3D_PARAMETERS_0; uint32_t CONTROL; + uint32_t OTG_GSL_WINDOW_X; + uint32_t OTG_GSL_WINDOW_Y; + uint32_t OTG_VUPDATE_KEEPOUT; + uint32_t OTG_DSC_START_POSITION; }; #define TG_COMMON_MASK_SH_LIST_DCN(mask_sh)\ @@ -204,11 +210,21 @@ struct dcn_tg_registers { SF(ODM0_OPTC_INPUT_CLOCK_CONTROL, OPTC_INPUT_CLK_ON, mask_sh),\ SF(ODM0_OPTC_INPUT_CLOCK_CONTROL, OPTC_INPUT_CLK_GATE_DIS, mask_sh),\ SF(ODM0_OPTC_INPUT_GLOBAL_CONTROL, OPTC_UNDERFLOW_OCCURRED_STATUS, mask_sh),\ - SF(OPPBUF0_OPPBUF_CONTROL, OPPBUF_ACTIVE_WIDTH, mask_sh),\ - SF(OPPBUF0_OPPBUF_3D_PARAMETERS_0, OPPBUF_3D_VACT_SPACE1_SIZE, mask_sh),\ + SF(ODM0_OPTC_INPUT_GLOBAL_CONTROL, OPTC_UNDERFLOW_CLEAR, mask_sh),\ SF(VTG0_CONTROL, VTG0_ENABLE, mask_sh),\ SF(VTG0_CONTROL, VTG0_FP2, mask_sh),\ - SF(VTG0_CONTROL, VTG0_VCOUNT_INIT, mask_sh) + SF(VTG0_CONTROL, VTG0_VCOUNT_INIT, mask_sh),\ + SF(OTG0_OTG_VERT_SYNC_CONTROL, OTG_FORCE_VSYNC_NEXT_LINE_OCCURRED, mask_sh),\ + SF(OTG0_OTG_VERT_SYNC_CONTROL, OTG_FORCE_VSYNC_NEXT_LINE_CLEAR, mask_sh),\ + SF(OTG0_OTG_VERT_SYNC_CONTROL, OTG_AUTO_FORCE_VSYNC_MODE, mask_sh),\ + SF(OTG0_OTG_MASTER_UPDATE_MODE, MASTER_UPDATE_INTERLACED_MODE, mask_sh),\ + SF(OTG0_OTG_GSL_CONTROL, OTG_GSL0_EN, mask_sh),\ + SF(OTG0_OTG_GSL_CONTROL, OTG_GSL1_EN, mask_sh),\ + SF(OTG0_OTG_GSL_CONTROL, OTG_GSL2_EN, mask_sh),\ + SF(OTG0_OTG_GSL_CONTROL, OTG_GSL_MASTER_EN, mask_sh),\ + SF(OTG0_OTG_GSL_CONTROL, OTG_GSL_FORCE_DELAY, mask_sh),\ + SF(OTG0_OTG_GSL_CONTROL, OTG_GSL_CHECK_ALL_FIELDS, mask_sh) + #define TG_COMMON_MASK_SH_LIST_DCN1_0(mask_sh)\ TG_COMMON_MASK_SH_LIST_DCN(mask_sh),\ @@ -313,26 +329,48 @@ struct dcn_tg_registers { type OPTC_SRC_SEL;\ type OPTC_SEG0_SRC_SEL;\ type OPTC_UNDERFLOW_OCCURRED_STATUS;\ - type OPPBUF_ACTIVE_WIDTH;\ - type OPPBUF_3D_VACT_SPACE1_SIZE;\ + type OPTC_UNDERFLOW_CLEAR;\ type VTG0_ENABLE;\ type VTG0_FP2;\ - type VTG0_VCOUNT_INIT; + type VTG0_VCOUNT_INIT;\ + type OTG_FORCE_VSYNC_NEXT_LINE_OCCURRED;\ + type OTG_FORCE_VSYNC_NEXT_LINE_CLEAR;\ + type OTG_AUTO_FORCE_VSYNC_MODE;\ + type MASTER_UPDATE_INTERLACED_MODE;\ + type OTG_GSL0_EN;\ + type OTG_GSL1_EN;\ + type OTG_GSL2_EN;\ + type OTG_GSL_MASTER_EN;\ + type OTG_GSL_FORCE_DELAY;\ + type OTG_GSL_CHECK_ALL_FIELDS;\ + type OTG_GSL_WINDOW_START_X;\ + type OTG_GSL_WINDOW_END_X;\ + type OTG_GSL_WINDOW_START_Y;\ + type OTG_GSL_WINDOW_END_Y;\ + type OTG_RANGE_TIMING_DBUF_UPDATE_MODE;\ + type OTG_GSL_MASTER_MODE;\ + type OTG_MASTER_UPDATE_LOCK_GSL_EN;\ + type MASTER_UPDATE_LOCK_VUPDATE_KEEPOUT_START_OFFSET;\ + type MASTER_UPDATE_LOCK_VUPDATE_KEEPOUT_END_OFFSET;\ + type OTG_DSC_START_POSITION_X;\ + type OTG_DSC_START_POSITION_LINE_NUM;\ + type OTG_MASTER_UPDATE_LOCK_VUPDATE_KEEPOUT_EN; + -struct dcn_tg_shift { +struct dcn_optc_shift { TG_REG_FIELD_LIST(uint8_t) }; -struct dcn_tg_mask { +struct dcn_optc_mask { TG_REG_FIELD_LIST(uint32_t) }; -struct dcn10_timing_generator { +struct optc { struct timing_generator base; - const struct dcn_tg_registers *tg_regs; - const struct dcn_tg_shift *tg_shift; - const struct dcn_tg_mask *tg_mask; + const struct dcn_optc_registers *tg_regs; + const struct dcn_optc_shift *tg_shift; + const struct dcn_optc_mask *tg_mask; enum controller_id controller_id; @@ -347,7 +385,7 @@ struct dcn10_timing_generator { uint32_t min_v_blank_interlace; }; -void dcn10_timing_generator_init(struct dcn10_timing_generator *tg); +void dcn10_timing_generator_init(struct optc *optc); struct dcn_otg_state { uint32_t v_blank_start; @@ -368,7 +406,77 @@ struct dcn_otg_state { uint32_t otg_enabled; }; -void tgn10_read_otg_state(struct dcn10_timing_generator *tgn10, +void optc1_read_otg_state(struct optc *optc1, struct dcn_otg_state *s); +bool optc1_validate_timing( + struct timing_generator *optc, + const struct dc_crtc_timing *timing); + +void optc1_program_timing( + struct timing_generator *optc, + const struct dc_crtc_timing *dc_crtc_timing, + bool use_vbios); + +void optc1_program_global_sync( + struct timing_generator *optc); + +bool optc1_disable_crtc(struct timing_generator *optc); + +bool optc1_is_counter_moving(struct timing_generator *optc); + +void optc1_get_position(struct timing_generator *optc, + struct crtc_position *position); + +uint32_t optc1_get_vblank_counter(struct timing_generator *optc); + +void optc1_get_crtc_scanoutpos( + struct timing_generator *optc, + uint32_t *v_blank_start, + uint32_t *v_blank_end, + uint32_t *h_position, + uint32_t *v_position); + +void optc1_set_early_control( + struct timing_generator *optc, + uint32_t early_cntl); + +void optc1_wait_for_state(struct timing_generator *optc, + enum crtc_state state); + +void optc1_set_blank(struct timing_generator *optc, + bool enable_blanking); + +bool optc1_is_blanked(struct timing_generator *optc); + +void optc1_program_blank_color( + struct timing_generator *optc, + const struct tg_color *black_color); + +bool optc1_did_triggered_reset_occur( + struct timing_generator *optc); + +void optc1_enable_reset_trigger(struct timing_generator *optc, int source_tg_inst); + +void optc1_disable_reset_trigger(struct timing_generator *optc); + +void optc1_lock(struct timing_generator *optc); + +void optc1_unlock(struct timing_generator *optc); + +void optc1_enable_optc_clock(struct timing_generator *optc, bool enable); + +void optc1_set_drr( + struct timing_generator *optc, + const struct drr_params *params); + +void optc1_set_static_screen_control( + struct timing_generator *optc, + uint32_t value); + +void optc1_program_stereo(struct timing_generator *optc, + const struct dc_crtc_timing *timing, struct crtc_stereo_flags *flags); + +bool optc1_is_stereo_left_eye(struct timing_generator *optc); + #endif /* __DC_TIMING_GENERATOR_DCN10_H__ */ diff --git a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_resource.c b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_resource.c index 9fc8f827f2a1..44825e2c9ebb 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_resource.c +++ b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_resource.c @@ -34,7 +34,7 @@ #include "dcn10/dcn10_mpc.h" #include "irq/dcn10/irq_service_dcn10.h" #include "dcn10/dcn10_dpp.h" -#include "dcn10/dcn10_timing_generator.h" +#include "dcn10_optc.h" #include "dcn10/dcn10_hw_sequencer.h" #include "dce110/dce110_hw_sequencer.h" #include "dcn10/dcn10_opp.h" @@ -48,16 +48,17 @@ #include "dce110/dce110_resource.h" #include "dce112/dce112_resource.h" #include "dcn10_hubp.h" +#include "dcn10_hubbub.h" -#include "vega10/soc15ip.h" +#include "soc15ip.h" -#include "raven1/DCN/dcn_1_0_offset.h" -#include "raven1/DCN/dcn_1_0_sh_mask.h" +#include "dcn/dcn_1_0_offset.h" +#include "dcn/dcn_1_0_sh_mask.h" -#include "raven1/NBIO/nbio_7_0_offset.h" +#include "nbio/nbio_7_0_offset.h" -#include "raven1/MMHUB/mmhub_9_1_offset.h" -#include "raven1/MMHUB/mmhub_9_1_sh_mask.h" +#include "mmhub/mmhub_9_1_offset.h" +#include "mmhub/mmhub_9_1_sh_mask.h" #include "reg_helper.h" #include "dce/dce_abm.h" @@ -347,18 +348,18 @@ static const struct dcn_mpc_mask mpc_mask = { #define tg_regs(id)\ [id] = {TG_COMMON_REG_LIST_DCN1_0(id)} -static const struct dcn_tg_registers tg_regs[] = { +static const struct dcn_optc_registers tg_regs[] = { tg_regs(0), tg_regs(1), tg_regs(2), tg_regs(3), }; -static const struct dcn_tg_shift tg_shift = { +static const struct dcn_optc_shift tg_shift = { TG_COMMON_MASK_SH_LIST_DCN1_0(__SHIFT) }; -static const struct dcn_tg_mask tg_mask = { +static const struct dcn_optc_mask tg_mask = { TG_COMMON_MASK_SH_LIST_DCN1_0(_MASK) }; @@ -367,25 +368,38 @@ static const struct bios_registers bios_regs = { NBIO_SR(BIOS_SCRATCH_6) }; -#define mi_regs(id)\ +#define hubp_regs(id)\ [id] = {\ - MI_REG_LIST_DCN10(id)\ + HUBP_REG_LIST_DCN10(id)\ } -static const struct dcn_mi_registers mi_regs[] = { - mi_regs(0), - mi_regs(1), - mi_regs(2), - mi_regs(3), +static const struct dcn_mi_registers hubp_regs[] = { + hubp_regs(0), + hubp_regs(1), + hubp_regs(2), + hubp_regs(3), }; -static const struct dcn_mi_shift mi_shift = { - MI_MASK_SH_LIST_DCN10(__SHIFT) +static const struct dcn_mi_shift hubp_shift = { + HUBP_MASK_SH_LIST_DCN10(__SHIFT) }; -static const struct dcn_mi_mask mi_mask = { - MI_MASK_SH_LIST_DCN10(_MASK) +static const struct dcn_mi_mask hubp_mask = { + HUBP_MASK_SH_LIST_DCN10(_MASK) +}; + + +static const struct dcn_hubbub_registers hubbub_reg = { + HUBBUB_REG_LIST_DCN10(0) +}; + +static const struct dcn_hubbub_shift hubbub_shift = { + HUBBUB_MASK_SH_LIST_DCN10(__SHIFT) +}; + +static const struct dcn_hubbub_mask hubbub_mask = { + HUBBUB_MASK_SH_LIST_DCN10(_MASK) }; #define clk_src_regs(index, pllid)\ @@ -519,12 +533,28 @@ static struct mpc *dcn10_mpc_create(struct dc_context *ctx) return &mpc10->base; } +static struct hubbub *dcn10_hubbub_create(struct dc_context *ctx) +{ + struct hubbub *hubbub = kzalloc(sizeof(struct hubbub), + GFP_KERNEL); + + if (!hubbub) + return NULL; + + hubbub1_construct(hubbub, ctx, + &hubbub_reg, + &hubbub_shift, + &hubbub_mask); + + return hubbub; +} + static struct timing_generator *dcn10_timing_generator_create( struct dc_context *ctx, uint32_t instance) { - struct dcn10_timing_generator *tgn10 = - kzalloc(sizeof(struct dcn10_timing_generator), GFP_KERNEL); + struct optc *tgn10 = + kzalloc(sizeof(struct optc), GFP_KERNEL); if (!tgn10) return NULL; @@ -647,6 +677,8 @@ static struct dce_hwseq *dcn10_hwseq_create( hws->regs = &hwseq_reg; hws->shifts = &hwseq_shift; hws->masks = &hwseq_mask; + hws->wa.DEGVIDCN10_253 = true; + hws->wa.false_optc_underflow = true; } return hws; } @@ -700,6 +732,12 @@ static void destruct(struct dcn10_resource_pool *pool) kfree(TO_DCN10_MPC(pool->base.mpc)); pool->base.mpc = NULL; } + + if (pool->base.hubbub != NULL) { + kfree(pool->base.hubbub); + pool->base.hubbub = NULL; + } + for (i = 0; i < pool->base.pipe_count; i++) { if (pool->base.opps[i] != NULL) pool->base.opps[i]->funcs->opp_destroy(&pool->base.opps[i]); @@ -768,7 +806,7 @@ static struct hubp *dcn10_hubp_create( return NULL; dcn10_hubp_construct(hubp1, ctx, inst, - &mi_regs[inst], &mi_shift, &mi_mask); + &hubp_regs[inst], &hubp_shift, &hubp_mask); return &hubp1->base; } @@ -1233,8 +1271,8 @@ static bool construct( dc->caps.max_downscale_ratio = 200; dc->caps.i2c_speed_in_khz = 100; dc->caps.max_cursor_size = 256; - dc->caps.max_slave_planes = 1; + dc->caps.is_apu = true; if (dc->ctx->dce_environment == DCE_ENV_PRODUCTION_DRV) dc->debug = debug_defaults_drv; @@ -1274,7 +1312,7 @@ static bool construct( if (pool->base.clock_sources[i] == NULL) { dm_error("DC: failed to create clock sources!\n"); BREAK_TO_DEBUGGER(); - goto clock_source_create_fail; + goto fail; } } @@ -1283,7 +1321,7 @@ static bool construct( if (pool->base.display_clock == NULL) { dm_error("DC: failed to create display clock!\n"); BREAK_TO_DEBUGGER(); - goto disp_clk_create_fail; + goto fail; } } @@ -1294,7 +1332,7 @@ static bool construct( if (pool->base.dmcu == NULL) { dm_error("DC: failed to create dmcu!\n"); BREAK_TO_DEBUGGER(); - goto res_create_fail; + goto fail; } pool->base.abm = dce_abm_create(ctx, @@ -1304,7 +1342,7 @@ static bool construct( if (pool->base.abm == NULL) { dm_error("DC: failed to create abm!\n"); BREAK_TO_DEBUGGER(); - goto res_create_fail; + goto fail; } dml_init_instance(&dc->dml, DML_PROJECT_RAVEN1); @@ -1344,13 +1382,11 @@ static bool construct( } { - #if defined(CONFIG_DRM_AMD_DC_DCN1_0) struct irq_service_init_data init_data; init_data.ctx = dc->ctx; pool->base.irqs = dal_irq_service_dcn10_create(&init_data); if (!pool->base.irqs) - goto irqs_create_fail; - #endif + goto fail; } /* index to valid pipe resource */ @@ -1368,7 +1404,7 @@ static bool construct( BREAK_TO_DEBUGGER(); dm_error( "DC: failed to create memory input!\n"); - goto mi_create_fail; + goto fail; } pool->base.ipps[j] = dcn10_ipp_create(ctx, i); @@ -1376,7 +1412,7 @@ static bool construct( BREAK_TO_DEBUGGER(); dm_error( "DC: failed to create input pixel processor!\n"); - goto ipp_create_fail; + goto fail; } pool->base.dpps[j] = dcn10_dpp_create(ctx, i); @@ -1384,7 +1420,7 @@ static bool construct( BREAK_TO_DEBUGGER(); dm_error( "DC: failed to create dpp!\n"); - goto dpp_create_fail; + goto fail; } pool->base.opps[j] = dcn10_opp_create(ctx, i); @@ -1392,7 +1428,7 @@ static bool construct( BREAK_TO_DEBUGGER(); dm_error( "DC: failed to create output pixel processor!\n"); - goto opp_create_fail; + goto fail; } pool->base.timing_generators[j] = dcn10_timing_generator_create( @@ -1400,8 +1436,9 @@ static bool construct( if (pool->base.timing_generators[j] == NULL) { BREAK_TO_DEBUGGER(); dm_error("DC: failed to create tg!\n"); - goto otg_create_fail; + goto fail; } + /* check next valid pipe */ j++; } @@ -1419,13 +1456,20 @@ static bool construct( if (pool->base.mpc == NULL) { BREAK_TO_DEBUGGER(); dm_error("DC: failed to create mpc!\n"); - goto mpc_create_fail; + goto fail; + } + + pool->base.hubbub = dcn10_hubbub_create(ctx); + if (pool->base.hubbub == NULL) { + BREAK_TO_DEBUGGER(); + dm_error("DC: failed to create hubbub!\n"); + goto fail; } if (!resource_construct(num_virtual_links, dc, &pool->base, (!IS_FPGA_MAXIMUS_DC(dc->ctx->dce_environment) ? &res_create_funcs : &res_create_maximus_funcs))) - goto res_create_fail; + goto fail; dcn10_hw_sequencer_construct(dc); dc->caps.max_planes = pool->base.pipe_count; @@ -1434,16 +1478,7 @@ static bool construct( return true; -disp_clk_create_fail: -mpc_create_fail: -otg_create_fail: -opp_create_fail: -dpp_create_fail: -ipp_create_fail: -mi_create_fail: -irqs_create_fail: -res_create_fail: -clock_source_create_fail: +fail: destruct(pool); diff --git a/drivers/gpu/drm/amd/display/dc/dm_services.h b/drivers/gpu/drm/amd/display/dc/dm_services.h index d4917037ac42..225b7bfb09a9 100644 --- a/drivers/gpu/drm/amd/display/dc/dm_services.h +++ b/drivers/gpu/drm/amd/display/dc/dm_services.h @@ -373,6 +373,13 @@ bool dm_dmcu_set_pipe(struct dc_context *ctx, unsigned int controller_id); unsigned long long dm_get_timestamp(struct dc_context *ctx); /* + * performance tracing + */ +void dm_perf_trace_timestamp(const char *func_name, unsigned int line); +#define PERF_TRACE() dm_perf_trace_timestamp(__func__, __LINE__) + + +/* * Debug and verification hooks */ bool dm_helpers_dc_conn_log( diff --git a/drivers/gpu/drm/amd/display/dc/dml/display_mode_lib.c b/drivers/gpu/drm/amd/display/dc/dml/display_mode_lib.c index 4c31fa54af39..c109b2c34c8f 100644 --- a/drivers/gpu/drm/amd/display/dc/dml/display_mode_lib.c +++ b/drivers/gpu/drm/amd/display/dc/dml/display_mode_lib.c @@ -35,35 +35,6 @@ static void set_soc_bounding_box(struct _vcs_dpi_soc_bounding_box_st *soc, enum soc->writeback_latency_us = 12.0; soc->ideal_dram_bw_after_urgent_percent = 80.0; soc->max_request_size_bytes = 256; - - soc->vmin.dcfclk_mhz = 300.0; - soc->vmin.dispclk_mhz = 608.0; - soc->vmin.dppclk_mhz = 435.0; - soc->vmin.dram_bw_per_chan_gbps = 12.8; - soc->vmin.phyclk_mhz = 540.0; - soc->vmin.socclk_mhz = 208.0; - - soc->vmid.dcfclk_mhz = 600.0; - soc->vmid.dispclk_mhz = 661.0; - soc->vmid.dppclk_mhz = 661.0; - soc->vmid.dram_bw_per_chan_gbps = 12.8; - soc->vmid.phyclk_mhz = 540.0; - soc->vmid.socclk_mhz = 208.0; - - soc->vnom.dcfclk_mhz = 600.0; - soc->vnom.dispclk_mhz = 661.0; - soc->vnom.dppclk_mhz = 661.0; - soc->vnom.dram_bw_per_chan_gbps = 38.4; - soc->vnom.phyclk_mhz = 810; - soc->vnom.socclk_mhz = 208.0; - - soc->vmax.dcfclk_mhz = 600.0; - soc->vmax.dispclk_mhz = 1086.0; - soc->vmax.dppclk_mhz = 661.0; - soc->vmax.dram_bw_per_chan_gbps = 38.4; - soc->vmax.phyclk_mhz = 810.0; - soc->vmax.socclk_mhz = 208.0; - soc->downspread_percent = 0.5; soc->dram_page_open_time_ns = 50.0; soc->dram_rw_turnaround_time_ns = 17.5; diff --git a/drivers/gpu/drm/amd/display/dc/dml/display_mode_structs.h b/drivers/gpu/drm/amd/display/dc/dml/display_mode_structs.h index baf182177736..aeebd8bee628 100644 --- a/drivers/gpu/drm/amd/display/dc/dml/display_mode_structs.h +++ b/drivers/gpu/drm/amd/display/dc/dml/display_mode_structs.h @@ -79,10 +79,6 @@ struct _vcs_dpi_soc_bounding_box_st { double writeback_latency_us; double ideal_dram_bw_after_urgent_percent; unsigned int max_request_size_bytes; - struct _vcs_dpi_voltage_scaling_st vmin; - struct _vcs_dpi_voltage_scaling_st vmid; - struct _vcs_dpi_voltage_scaling_st vnom; - struct _vcs_dpi_voltage_scaling_st vmax; double downspread_percent; double dram_page_open_time_ns; double dram_rw_turnaround_time_ns; @@ -229,7 +225,7 @@ struct _vcs_dpi_display_output_params_st { int output_bpp; int dsc_enable; int wb_enable; - int output_bpc; + int opp_input_bpc; int output_type; int output_format; int output_standard; diff --git a/drivers/gpu/drm/amd/display/dc/dml/display_mode_vba.c b/drivers/gpu/drm/amd/display/dc/dml/display_mode_vba.c index ea661ee44674..260e113fcc02 100644 --- a/drivers/gpu/drm/amd/display/dc/dml/display_mode_vba.c +++ b/drivers/gpu/drm/amd/display/dc/dml/display_mode_vba.c @@ -28,6 +28,17 @@ #include "dml_inline_defs.h" +/* + * NOTE: + * This file is gcc-parseable HW gospel, coming straight from HW engineers. + * + * It doesn't adhere to Linux kernel style and sometimes will do things in odd + * ways. Unless there is something clearly wrong with it the code should + * remain as-is as it provides us with a guarantee from HW that it is correct. + */ + +#define BPP_INVALID 0 +#define BPP_BLENDED_PIPE 0xffffffff static const unsigned int NumberOfStates = DC__VOLTAGE_STATES; static void fetch_socbb_params(struct display_mode_lib *mode_lib); @@ -587,7 +598,7 @@ static void fetch_pipe_params(struct display_mode_lib *mode_lib) mode_lib->vba.NumberOfDSCSlices[mode_lib->vba.NumberOfActivePlanes] = dout->dsc_slices; mode_lib->vba.DSCInputBitPerComponent[mode_lib->vba.NumberOfActivePlanes] = - dout->output_bpc == 0 ? 12 : dout->output_bpc; + dout->opp_input_bpc == 0 ? 12 : dout->opp_input_bpc; mode_lib->vba.WritebackEnable[mode_lib->vba.NumberOfActivePlanes] = dout->wb_enable; mode_lib->vba.WritebackSourceHeight[mode_lib->vba.NumberOfActivePlanes] = dout->wb.wb_src_height; @@ -3928,7 +3939,7 @@ static unsigned int TruncToValidBPP( else if (DecimalBPP >= 12) return 12; else - return 0; + return BPP_INVALID; } else if (Format == dm_444) { if (DecimalBPP >= 36) return 36; @@ -3937,7 +3948,7 @@ static unsigned int TruncToValidBPP( else if (DecimalBPP >= 24) return 24; else - return 0; + return BPP_INVALID; } else { if (DecimalBPP / 1.5 >= 24) return 24; @@ -3946,27 +3957,27 @@ static unsigned int TruncToValidBPP( else if (DecimalBPP / 1.5 >= 16) return 16; else - return 0; + return BPP_INVALID; } } else { if (DSCEnabled) { if (Format == dm_420) { if (DecimalBPP < 6) - return 0; + return BPP_INVALID; else if (DecimalBPP >= 1.5 * DSCInputBitPerComponent - 1 / 16) return 1.5 * DSCInputBitPerComponent - 1 / 16; else return dml_floor(16 * DecimalBPP, 1) / 16; } else if (Format == dm_n422) { if (DecimalBPP < 7) - return 0; + return BPP_INVALID; else if (DecimalBPP >= 2 * DSCInputBitPerComponent - 1 / 16) return 2 * DSCInputBitPerComponent - 1 / 16; else return dml_floor(16 * DecimalBPP, 1) / 16; } else { if (DecimalBPP < 8) - return 0; + return BPP_INVALID; else if (DecimalBPP >= 3 * DSCInputBitPerComponent - 1 / 16) return 3 * DSCInputBitPerComponent - 1 / 16; else @@ -3980,7 +3991,7 @@ static unsigned int TruncToValidBPP( else if (DecimalBPP >= 12) return 12; else - return 0; + return BPP_INVALID; } else if (Format == dm_s422 || Format == dm_n422) { if (DecimalBPP >= 24) return 24; @@ -3989,7 +4000,7 @@ static unsigned int TruncToValidBPP( else if (DecimalBPP >= 16) return 16; else - return 0; + return BPP_INVALID; } else { if (DecimalBPP >= 36) return 36; @@ -3998,7 +4009,7 @@ static unsigned int TruncToValidBPP( else if (DecimalBPP >= 24) return 24; else - return 0; + return BPP_INVALID; } } } @@ -4922,11 +4933,7 @@ static void ModeSupportAndSystemConfigurationFull(struct display_mode_lib *mode_ mode_lib->vba.ViewportSizeSupport[i] = true; for (k = 0; k <= mode_lib->vba.NumberOfActivePlanes - 1; k++) { if (mode_lib->vba.ODMCombineEnablePerState[i][k] == true) { - if (dml_min( - mode_lib->vba.SwathWidthYSingleDPP[k], - dml_round( - mode_lib->vba.HActive[k] / 2.0 - * mode_lib->vba.HRatio[k])) + if (dml_min(mode_lib->vba.SwathWidthYSingleDPP[k], dml_round(mode_lib->vba.HActive[k] / 2.0 * mode_lib->vba.HRatio[k])) > mode_lib->vba.MaximumSwathWidth[k]) { mode_lib->vba.ViewportSizeSupport[i] = false; } @@ -4980,12 +4987,8 @@ static void ModeSupportAndSystemConfigurationFull(struct display_mode_lib *mode_ mode_lib->vba.RequiresDSC[i][k] = 0; mode_lib->vba.RequiresFEC[i][k] = 0; mode_lib->vba.OutputBppPerState[i][k] = - TruncToValidBPP( - dml_min( - 600.0, - mode_lib->vba.PHYCLKPerState[i]) - / mode_lib->vba.PixelClockBackEnd[k] - * 24, + TruncToValidBPP(dml_min(600.0, mode_lib->vba.PHYCLKPerState[i]) + / mode_lib->vba.PixelClockBackEnd[k] * 24, false, mode_lib->vba.Output[k], mode_lib->vba.OutputFormat[k], @@ -5000,30 +5003,16 @@ static void ModeSupportAndSystemConfigurationFull(struct display_mode_lib *mode_ } if (mode_lib->vba.PHYCLKPerState[i] >= 270.0) { mode_lib->vba.Outbpp = - TruncToValidBPP( - (1.0 - - mode_lib->vba.Downspreading - / 100.0) - * 270.0 - * mode_lib->vba.OutputLinkDPLanes[k] - / mode_lib->vba.PixelClockBackEnd[k] - * 8.0, + TruncToValidBPP((1.0 - mode_lib->vba.Downspreading / 100.0) * 270.0 + * mode_lib->vba.OutputLinkDPLanes[k] / mode_lib->vba.PixelClockBackEnd[k] * 8.0, false, mode_lib->vba.Output[k], mode_lib->vba.OutputFormat[k], mode_lib->vba.DSCInputBitPerComponent[k]); mode_lib->vba.OutbppDSC = - TruncToValidBPP( - (1.0 - - mode_lib->vba.Downspreading - / 100.0) - * (1.0 - - mode_lib->vba.EffectiveFECOverhead - / 100.0) - * 270.0 - * mode_lib->vba.OutputLinkDPLanes[k] - / mode_lib->vba.PixelClockBackEnd[k] - * 8.0, + TruncToValidBPP((1.0 - mode_lib->vba.Downspreading / 100.0) + * (1.0 - mode_lib->vba.EffectiveFECOverhead / 100.0) * 270.0 + * mode_lib->vba.OutputLinkDPLanes[k] / mode_lib->vba.PixelClockBackEnd[k] * 8.0, true, mode_lib->vba.Output[k], mode_lib->vba.OutputFormat[k], @@ -5046,32 +5035,18 @@ static void ModeSupportAndSystemConfigurationFull(struct display_mode_lib *mode_ mode_lib->vba.OutputBppPerState[i][k] = mode_lib->vba.Outbpp; } - if (mode_lib->vba.Outbpp == 0) { + if (mode_lib->vba.Outbpp == BPP_INVALID) { mode_lib->vba.Outbpp = - TruncToValidBPP( - (1.0 - - mode_lib->vba.Downspreading - / 100.0) - * 540.0 - * mode_lib->vba.OutputLinkDPLanes[k] - / mode_lib->vba.PixelClockBackEnd[k] - * 8.0, + TruncToValidBPP((1.0 - mode_lib->vba.Downspreading / 100.0) * 540.0 + * mode_lib->vba.OutputLinkDPLanes[k] / mode_lib->vba.PixelClockBackEnd[k] * 8.0, false, mode_lib->vba.Output[k], mode_lib->vba.OutputFormat[k], mode_lib->vba.DSCInputBitPerComponent[k]); mode_lib->vba.OutbppDSC = - TruncToValidBPP( - (1.0 - - mode_lib->vba.Downspreading - / 100.0) - * (1.0 - - mode_lib->vba.EffectiveFECOverhead - / 100.0) - * 540.0 - * mode_lib->vba.OutputLinkDPLanes[k] - / mode_lib->vba.PixelClockBackEnd[k] - * 8.0, + TruncToValidBPP((1.0 - mode_lib->vba.Downspreading / 100.0) + * (1.0 - mode_lib->vba.EffectiveFECOverhead / 100.0) * 540.0 + * mode_lib->vba.OutputLinkDPLanes[k] / mode_lib->vba.PixelClockBackEnd[k] * 8.0, true, mode_lib->vba.Output[k], mode_lib->vba.OutputFormat[k], @@ -5094,40 +5069,26 @@ static void ModeSupportAndSystemConfigurationFull(struct display_mode_lib *mode_ mode_lib->vba.OutputBppPerState[i][k] = mode_lib->vba.Outbpp; } - if (mode_lib->vba.Outbpp == 0 + if (mode_lib->vba.Outbpp == BPP_INVALID && mode_lib->vba.PHYCLKPerState[i] >= 810.0) { mode_lib->vba.Outbpp = - TruncToValidBPP( - (1.0 - - mode_lib->vba.Downspreading - / 100.0) - * 810.0 - * mode_lib->vba.OutputLinkDPLanes[k] - / mode_lib->vba.PixelClockBackEnd[k] - * 8.0, + TruncToValidBPP((1.0 - mode_lib->vba.Downspreading / 100.0) * 810.0 + * mode_lib->vba.OutputLinkDPLanes[k] / mode_lib->vba.PixelClockBackEnd[k] * 8.0, false, mode_lib->vba.Output[k], mode_lib->vba.OutputFormat[k], mode_lib->vba.DSCInputBitPerComponent[k]); mode_lib->vba.OutbppDSC = - TruncToValidBPP( - (1.0 - - mode_lib->vba.Downspreading - / 100.0) - * (1.0 - - mode_lib->vba.EffectiveFECOverhead - / 100.0) - * 810.0 - * mode_lib->vba.OutputLinkDPLanes[k] - / mode_lib->vba.PixelClockBackEnd[k] - * 8.0, + TruncToValidBPP((1.0 - mode_lib->vba.Downspreading / 100.0) + * (1.0 - mode_lib->vba.EffectiveFECOverhead / 100.0) * 810.0 + * mode_lib->vba.OutputLinkDPLanes[k] / mode_lib->vba.PixelClockBackEnd[k] * 8.0, true, mode_lib->vba.Output[k], mode_lib->vba.OutputFormat[k], mode_lib->vba.DSCInputBitPerComponent[k]); if (mode_lib->vba.DSCEnabled[k] == true - || mode_lib->vba.Outbpp == 0) { + || mode_lib->vba.Outbpp == BPP_INVALID) { mode_lib->vba.RequiresDSC[i][k] = true; if (mode_lib->vba.Output[k] == dm_dp) { mode_lib->vba.RequiresFEC[i][k] = @@ -5147,14 +5108,14 @@ static void ModeSupportAndSystemConfigurationFull(struct display_mode_lib *mode_ } } } else { - mode_lib->vba.OutputBppPerState[i][k] = 0; + mode_lib->vba.OutputBppPerState[i][k] = BPP_BLENDED_PIPE; } } } for (i = 0; i <= DC__VOLTAGE_STATES; i++) { mode_lib->vba.DIOSupport[i] = true; for (k = 0; k <= mode_lib->vba.NumberOfActivePlanes - 1; k++) { - if (mode_lib->vba.OutputBppPerState[i][k] == 0 + if (mode_lib->vba.OutputBppPerState[i][k] == BPP_INVALID || (mode_lib->vba.OutputFormat[k] == dm_420 && mode_lib->vba.ProgressiveToInterlaceUnitInOPP == true)) { @@ -5243,8 +5204,8 @@ static void ModeSupportAndSystemConfigurationFull(struct display_mode_lib *mode_ } else { mode_lib->vba.slices = 1.0; } - if (mode_lib->vba.OutputBppPerState[i][k] == 0 - || mode_lib->vba.OutputBppPerState[i][k] == 0) { + if (mode_lib->vba.OutputBppPerState[i][k] == BPP_BLENDED_PIPE + || mode_lib->vba.OutputBppPerState[i][k] == BPP_INVALID) { mode_lib->vba.bpp = 0.0; } else { mode_lib->vba.bpp = mode_lib->vba.OutputBppPerState[i][k]; diff --git a/drivers/gpu/drm/amd/display/dc/dml/display_rq_dlg_calc.c b/drivers/gpu/drm/amd/display/dc/dml/display_rq_dlg_calc.c index 8ba962df42e6..325dd2b757d6 100644 --- a/drivers/gpu/drm/amd/display/dc/dml/display_rq_dlg_calc.c +++ b/drivers/gpu/drm/amd/display/dc/dml/display_rq_dlg_calc.c @@ -27,6 +27,15 @@ #include "display_mode_vba.h" #include "display_rq_dlg_calc.h" +/* + * NOTE: + * This file is gcc-parseable HW gospel, coming straight from HW engineers. + * + * It doesn't adhere to Linux kernel style and sometimes will do things in odd + * ways. Unless there is something clearly wrong with it the code should + * remain as-is as it provides us with a guarantee from HW that it is correct. + */ + static void calculate_ttu_cursor(struct display_mode_lib *mode_lib, double *refcyc_per_req_delivery_pre_cur, double *refcyc_per_req_delivery_cur, diff --git a/drivers/gpu/drm/amd/display/dc/dml/dml1_display_rq_dlg_calc.c b/drivers/gpu/drm/amd/display/dc/dml/dml1_display_rq_dlg_calc.c index 1e4b1e383401..c2037daa8e66 100644 --- a/drivers/gpu/drm/amd/display/dc/dml/dml1_display_rq_dlg_calc.c +++ b/drivers/gpu/drm/amd/display/dc/dml/dml1_display_rq_dlg_calc.c @@ -28,6 +28,15 @@ #include "dml_inline_defs.h" +/* + * NOTE: + * This file is gcc-parseable HW gospel, coming straight from HW engineers. + * + * It doesn't adhere to Linux kernel style and sometimes will do things in odd + * ways. Unless there is something clearly wrong with it the code should + * remain as-is as it provides us with a guarantee from HW that it is correct. + */ + static unsigned int get_bytes_per_element(enum source_format_class source_format, bool is_chroma) { unsigned int ret_val = 0; diff --git a/drivers/gpu/drm/amd/display/dc/dml/soc_bounding_box.c b/drivers/gpu/drm/amd/display/dc/dml/soc_bounding_box.c index bc7d8c707221..324239c77958 100644 --- a/drivers/gpu/drm/amd/display/dc/dml/soc_bounding_box.c +++ b/drivers/gpu/drm/amd/display/dc/dml/soc_bounding_box.c @@ -27,6 +27,16 @@ #include "dc_features.h" #include "dml_inline_defs.h" + +/* + * NOTE: + * This file is gcc-parseable HW gospel, coming straight from HW engineers. + * + * It doesn't adhere to Linux kernel style and sometimes will do things in odd + * ways. Unless there is something clearly wrong with it the code should + * remain as-is as it provides us with a guarantee from HW that it is correct. + */ + void dml_socbb_set_latencies(soc_bounding_box_st *to_box, soc_bounding_box_st *from_box) { to_box->dram_clock_change_latency_us = from_box->dram_clock_change_latency_us; diff --git a/drivers/gpu/drm/amd/display/dc/gpio/dce120/hw_factory_dce120.c b/drivers/gpu/drm/amd/display/dc/gpio/dce120/hw_factory_dce120.c index 4ced9a7d63dd..0c2314efb47e 100644 --- a/drivers/gpu/drm/amd/display/dc/gpio/dce120/hw_factory_dce120.c +++ b/drivers/gpu/drm/amd/display/dc/gpio/dce120/hw_factory_dce120.c @@ -34,9 +34,9 @@ #include "hw_factory_dce120.h" -#include "vega10/DC/dce_12_0_offset.h" -#include "vega10/DC/dce_12_0_sh_mask.h" -#include "vega10/soc15ip.h" +#include "dce/dce_12_0_offset.h" +#include "dce/dce_12_0_sh_mask.h" +#include "soc15ip.h" #define block HPD #define reg_num 0 diff --git a/drivers/gpu/drm/amd/display/dc/gpio/dce120/hw_translate_dce120.c b/drivers/gpu/drm/amd/display/dc/gpio/dce120/hw_translate_dce120.c index af3843a69652..a225b02cc779 100644 --- a/drivers/gpu/drm/amd/display/dc/gpio/dce120/hw_translate_dce120.c +++ b/drivers/gpu/drm/amd/display/dc/gpio/dce120/hw_translate_dce120.c @@ -33,9 +33,9 @@ #include "include/gpio_types.h" #include "../hw_translate.h" -#include "vega10/DC/dce_12_0_offset.h" -#include "vega10/DC/dce_12_0_sh_mask.h" -#include "vega10/soc15ip.h" +#include "dce/dce_12_0_offset.h" +#include "dce/dce_12_0_sh_mask.h" +#include "soc15ip.h" /* begin ********************* * macros to expend register list macro defined in HW object header file */ diff --git a/drivers/gpu/drm/amd/display/dc/gpio/dcn10/hw_factory_dcn10.c b/drivers/gpu/drm/amd/display/dc/gpio/dcn10/hw_factory_dcn10.c index 409763c70ce5..5235f69f0602 100644 --- a/drivers/gpu/drm/amd/display/dc/gpio/dcn10/hw_factory_dcn10.c +++ b/drivers/gpu/drm/amd/display/dc/gpio/dcn10/hw_factory_dcn10.c @@ -34,9 +34,9 @@ #include "hw_factory_dcn10.h" -#include "raven1/DCN/dcn_1_0_offset.h" -#include "raven1/DCN/dcn_1_0_sh_mask.h" -#include "vega10/soc15ip.h" +#include "dcn/dcn_1_0_offset.h" +#include "dcn/dcn_1_0_sh_mask.h" +#include "soc15ip.h" #define block HPD #define reg_num 0 diff --git a/drivers/gpu/drm/amd/display/dc/gpio/dcn10/hw_translate_dcn10.c b/drivers/gpu/drm/amd/display/dc/gpio/dcn10/hw_translate_dcn10.c index 64a6915b846b..347864810d01 100644 --- a/drivers/gpu/drm/amd/display/dc/gpio/dcn10/hw_translate_dcn10.c +++ b/drivers/gpu/drm/amd/display/dc/gpio/dcn10/hw_translate_dcn10.c @@ -33,9 +33,9 @@ #include "include/gpio_types.h" #include "../hw_translate.h" -#include "raven1/DCN/dcn_1_0_offset.h" -#include "raven1/DCN/dcn_1_0_sh_mask.h" -#include "vega10/soc15ip.h" +#include "dcn/dcn_1_0_offset.h" +#include "dcn/dcn_1_0_sh_mask.h" +#include "soc15ip.h" /* begin ********************* * macros to expend register list macro defined in HW object header file */ diff --git a/drivers/gpu/drm/amd/display/dc/i2caux/dce120/i2caux_dce120.c b/drivers/gpu/drm/amd/display/dc/i2caux/dce120/i2caux_dce120.c index 668981a4c285..a401636bf3f8 100644 --- a/drivers/gpu/drm/amd/display/dc/i2caux/dce120/i2caux_dce120.c +++ b/drivers/gpu/drm/amd/display/dc/i2caux/dce120/i2caux_dce120.c @@ -36,9 +36,9 @@ #include "../dce110/aux_engine_dce110.h" #include "../dce110/i2caux_dce110.h" -#include "vega10/DC/dce_12_0_offset.h" -#include "vega10/DC/dce_12_0_sh_mask.h" -#include "vega10/soc15ip.h" +#include "dce/dce_12_0_offset.h" +#include "dce/dce_12_0_sh_mask.h" +#include "soc15ip.h" /* begin ********************* * macros to expend register list macro defined in HW object header file */ diff --git a/drivers/gpu/drm/amd/display/dc/i2caux/dcn10/i2caux_dcn10.c b/drivers/gpu/drm/amd/display/dc/i2caux/dcn10/i2caux_dcn10.c index 13b807d8aff8..bed7cc3e77de 100644 --- a/drivers/gpu/drm/amd/display/dc/i2caux/dcn10/i2caux_dcn10.c +++ b/drivers/gpu/drm/amd/display/dc/i2caux/dcn10/i2caux_dcn10.c @@ -36,9 +36,9 @@ #include "../dce110/i2c_hw_engine_dce110.h" #include "../dce110/i2caux_dce110.h" -#include "raven1/DCN/dcn_1_0_offset.h" -#include "raven1/DCN/dcn_1_0_sh_mask.h" -#include "vega10/soc15ip.h" +#include "dcn/dcn_1_0_offset.h" +#include "dcn/dcn_1_0_sh_mask.h" +#include "soc15ip.h" /* begin ********************* * macros to expend register list macro defined in HW object header file */ diff --git a/drivers/gpu/drm/amd/display/dc/inc/core_types.h b/drivers/gpu/drm/amd/display/dc/inc/core_types.h index b69f321e2ab6..d6971054ec07 100644 --- a/drivers/gpu/drm/amd/display/dc/inc/core_types.h +++ b/drivers/gpu/drm/amd/display/dc/inc/core_types.h @@ -139,6 +139,7 @@ struct resource_pool { struct timing_generator *timing_generators[MAX_PIPES]; struct stream_encoder *stream_enc[MAX_PIPES * 2]; + struct hubbub *hubbub; struct mpc *mpc; struct pp_smu_funcs_rv *pp_smu; struct pp_smu_display_requirement_rv pp_smu_req; @@ -211,7 +212,6 @@ struct pipe_ctx { struct _vcs_dpi_display_rq_regs_st rq_regs; struct _vcs_dpi_display_pipe_dest_params_st pipe_dlg_param; #endif - struct dwbc *dwbc; }; struct resource_context { @@ -240,6 +240,7 @@ struct dce_bw_output { struct dcn_bw_clocks { int dispclk_khz; + int dppclk_khz; bool dppclk_div; int dcfclk_khz; int dcfclk_deep_sleep_khz; diff --git a/drivers/gpu/drm/amd/display/dc/inc/dcn_calcs.h b/drivers/gpu/drm/amd/display/dc/inc/dcn_calcs.h index 1e231f6de732..132d18d4b293 100644 --- a/drivers/gpu/drm/amd/display/dc/inc/dcn_calcs.h +++ b/drivers/gpu/drm/amd/display/dc/inc/dcn_calcs.h @@ -349,10 +349,10 @@ struct dcn_bw_internal_vars { float dst_x_after_scaler; float dst_y_after_scaler; float time_calc; - float v_update_offset[number_of_planes_minus_one + 1]; + float v_update_offset[number_of_planes_minus_one + 1][2]; float total_repeater_delay; - float v_update_width[number_of_planes_minus_one + 1]; - float v_ready_offset[number_of_planes_minus_one + 1]; + float v_update_width[number_of_planes_minus_one + 1][2]; + float v_ready_offset[number_of_planes_minus_one + 1][2]; float time_setup; float extra_latency; float maximum_vstartup; diff --git a/drivers/gpu/drm/amd/display/dc/inc/hw/abm.h b/drivers/gpu/drm/amd/display/dc/inc/hw/abm.h index c93b9b9a817c..a83a48494613 100644 --- a/drivers/gpu/drm/amd/display/dc/inc/hw/abm.h +++ b/drivers/gpu/drm/amd/display/dc/inc/hw/abm.h @@ -27,9 +27,19 @@ #include "dm_services_types.h" +struct abm_backlight_registers { + unsigned int BL_PWM_CNTL; + unsigned int BL_PWM_CNTL2; + unsigned int BL_PWM_PERIOD_CNTL; + unsigned int LVTMA_PWRSEQ_REF_DIV_BL_PWM_REF_DIV; +}; + struct abm { struct dc_context *ctx; const struct abm_funcs *funcs; + + /* registers setting needs to be saved and restored at InitBacklight */ + struct abm_backlight_registers stored_backlight_registers; }; struct abm_funcs { @@ -40,9 +50,9 @@ struct abm_funcs { bool (*set_backlight_level)(struct abm *abm, unsigned int backlight_level, unsigned int frame_ramp, - unsigned int controller_id); + unsigned int controller_id, + bool use_smooth_brightness); unsigned int (*get_current_backlight_8_bit)(struct abm *abm); - bool (*is_dmcu_initialized)(struct abm *abm); }; #endif diff --git a/drivers/gpu/drm/amd/display/dc/inc/hw/dmcu.h b/drivers/gpu/drm/amd/display/dc/inc/hw/dmcu.h index 0574c29cc4a8..ce206355461b 100644 --- a/drivers/gpu/drm/amd/display/dc/inc/hw/dmcu.h +++ b/drivers/gpu/drm/amd/display/dc/inc/hw/dmcu.h @@ -27,12 +27,29 @@ #include "dm_services_types.h" +enum dmcu_state { + DMCU_NOT_INITIALIZED = 0, + DMCU_RUNNING = 1 +}; + +struct dmcu_version { + unsigned int day; + unsigned int month; + unsigned int year; + unsigned int interface_version; +}; + struct dmcu { struct dc_context *ctx; const struct dmcu_funcs *funcs; + + enum dmcu_state dmcu_state; + struct dmcu_version dmcu_version; + unsigned int cached_wait_loop_number; }; struct dmcu_funcs { + bool (*dmcu_init)(struct dmcu *dmcu); bool (*load_iram)(struct dmcu *dmcu, unsigned int start_offset, const char *src, @@ -44,7 +61,9 @@ struct dmcu_funcs { void (*get_psr_state)(struct dmcu *dmcu, uint32_t *psr_state); void (*set_psr_wait_loop)(struct dmcu *dmcu, unsigned int wait_loop_number); - void (*get_psr_wait_loop)(unsigned int *psr_wait_loop_number); + void (*get_psr_wait_loop)(struct dmcu *dmcu, + unsigned int *psr_wait_loop_number); + bool (*is_dmcu_initialized)(struct dmcu *dmcu); }; #endif diff --git a/drivers/gpu/drm/amd/display/dc/inc/hw/dpp.h b/drivers/gpu/drm/amd/display/dc/inc/hw/dpp.h index 9420dfb94d39..25edbde6163e 100644 --- a/drivers/gpu/drm/amd/display/dc/inc/hw/dpp.h +++ b/drivers/gpu/drm/amd/display/dc/inc/hw/dpp.h @@ -62,63 +62,67 @@ struct dpp_funcs { struct dpp *dpp, const struct dpp_grph_csc_adjustment *adjust); - void (*opp_set_csc_default)( + void (*dpp_set_csc_default)( struct dpp *dpp, enum dc_color_space colorspace); - void (*opp_set_csc_adjustment)( + void (*dpp_set_csc_adjustment)( struct dpp *dpp, - const struct out_csc_color_matrix *tbl_entry); + const uint16_t *regval); - void (*opp_power_on_regamma_lut)( + void (*dpp_power_on_regamma_lut)( struct dpp *dpp, bool power_on); - void (*opp_program_regamma_lut)( + void (*dpp_program_regamma_lut)( struct dpp *dpp, const struct pwl_result_data *rgb, uint32_t num); - void (*opp_configure_regamma_lut)( + void (*dpp_configure_regamma_lut)( struct dpp *dpp, bool is_ram_a); - void (*opp_program_regamma_lutb_settings)( + void (*dpp_program_regamma_lutb_settings)( struct dpp *dpp, const struct pwl_params *params); - void (*opp_program_regamma_luta_settings)( + void (*dpp_program_regamma_luta_settings)( struct dpp *dpp, const struct pwl_params *params); - void (*opp_program_regamma_pwl)( - struct dpp *dpp, const struct pwl_params *params); + void (*dpp_program_regamma_pwl)( + struct dpp *dpp, + const struct pwl_params *params, + enum opp_regamma mode); - void (*opp_set_regamma_mode)( - struct dpp *dpp_base, - enum opp_regamma mode); + void (*dpp_program_bias_and_scale)( + struct dpp *dpp, + struct dc_bias_and_scale *params); - void (*ipp_set_degamma)( + void (*dpp_set_degamma)( struct dpp *dpp_base, enum ipp_degamma_mode mode); - void (*ipp_program_input_lut)( + void (*dpp_program_input_lut)( struct dpp *dpp_base, const struct dc_gamma *gamma); - void (*ipp_program_degamma_pwl)(struct dpp *dpp_base, + void (*dpp_program_degamma_pwl)(struct dpp *dpp_base, const struct pwl_params *params); - void (*ipp_setup)( + void (*dpp_setup)( struct dpp *dpp_base, - enum surface_pixel_format input_format, - enum expansion_mode mode); + enum surface_pixel_format format, + enum expansion_mode mode, + struct csc_transform input_csc_color_matrix, + enum dc_color_space input_color_space); - void (*ipp_full_bypass)(struct dpp *dpp_base); + void (*dpp_full_bypass)(struct dpp *dpp_base); void (*set_cursor_attributes)( struct dpp *dpp_base, - const struct dc_cursor_attributes *attr); + enum dc_cursor_color_format color_format); void (*set_cursor_position)( struct dpp *dpp_base, diff --git a/drivers/gpu/drm/amd/display/dc/inc/hw/hubp.h b/drivers/gpu/drm/amd/display/dc/inc/hw/hubp.h index 0d186be24cf4..b7c7e70022e4 100644 --- a/drivers/gpu/drm/amd/display/dc/inc/hw/hubp.h +++ b/drivers/gpu/drm/amd/display/dc/inc/hw/hubp.h @@ -28,15 +28,32 @@ #include "mem_input.h" + +enum cursor_pitch { + CURSOR_PITCH_64_PIXELS = 0, + CURSOR_PITCH_128_PIXELS, + CURSOR_PITCH_256_PIXELS +}; + +enum cursor_lines_per_chunk { + CURSOR_LINE_PER_CHUNK_2 = 1, + CURSOR_LINE_PER_CHUNK_4, + CURSOR_LINE_PER_CHUNK_8, + CURSOR_LINE_PER_CHUNK_16 +}; + struct hubp { struct hubp_funcs *funcs; struct dc_context *ctx; struct dc_plane_address request_address; struct dc_plane_address current_address; int inst; + + /* run time states */ int opp_id; int mpcc_id; struct dc_cursor_attributes curs_attr; + bool power_gated; }; @@ -100,6 +117,8 @@ struct hubp_funcs { const struct dc_cursor_position *pos, const struct dc_cursor_mi_param *param); + void (*hubp_disconnect)(struct hubp *hubp); + }; #endif diff --git a/drivers/gpu/drm/amd/display/dc/inc/hw/hw_shared.h b/drivers/gpu/drm/amd/display/dc/inc/hw/hw_shared.h index 9602f261b614..e3f0b4056318 100644 --- a/drivers/gpu/drm/amd/display/dc/inc/hw/hw_shared.h +++ b/drivers/gpu/drm/amd/display/dc/inc/hw/hw_shared.h @@ -73,7 +73,7 @@ struct pwl_result_data { struct pwl_params { struct gamma_curve arr_curve_points[34]; - struct curve_points arr_points[3]; + struct curve_points arr_points[2]; struct pwl_result_data rgb_resulted[256 + 3]; uint32_t hw_points_num; }; @@ -126,11 +126,13 @@ struct default_adjustment { bool force_hw_default; }; + struct out_csc_color_matrix { enum dc_color_space color_space; uint16_t regval[12]; }; + enum opp_regamma { OPP_REGAMMA_BYPASS = 0, OPP_REGAMMA_SRGB, @@ -138,4 +140,55 @@ enum opp_regamma { OPP_REGAMMA_USER }; +struct csc_transform { + uint16_t matrix[12]; + bool enable_adjustment; +}; + +struct dc_bias_and_scale { + uint16_t scale_red; + uint16_t bias_red; + uint16_t scale_green; + uint16_t bias_green; + uint16_t scale_blue; + uint16_t bias_blue; +}; + +enum test_pattern_dyn_range { + TEST_PATTERN_DYN_RANGE_VESA = 0, + TEST_PATTERN_DYN_RANGE_CEA +}; + +enum test_pattern_mode { + TEST_PATTERN_MODE_COLORSQUARES_RGB = 0, + TEST_PATTERN_MODE_COLORSQUARES_YCBCR601, + TEST_PATTERN_MODE_COLORSQUARES_YCBCR709, + TEST_PATTERN_MODE_VERTICALBARS, + TEST_PATTERN_MODE_HORIZONTALBARS, + TEST_PATTERN_MODE_SINGLERAMP_RGB, + TEST_PATTERN_MODE_DUALRAMP_RGB +}; + +enum test_pattern_color_format { + TEST_PATTERN_COLOR_FORMAT_BPC_6 = 0, + TEST_PATTERN_COLOR_FORMAT_BPC_8, + TEST_PATTERN_COLOR_FORMAT_BPC_10, + TEST_PATTERN_COLOR_FORMAT_BPC_12 +}; + +enum controller_dp_test_pattern { + CONTROLLER_DP_TEST_PATTERN_D102 = 0, + CONTROLLER_DP_TEST_PATTERN_SYMBOLERROR, + CONTROLLER_DP_TEST_PATTERN_PRBS7, + CONTROLLER_DP_TEST_PATTERN_COLORSQUARES, + CONTROLLER_DP_TEST_PATTERN_VERTICALBARS, + CONTROLLER_DP_TEST_PATTERN_HORIZONTALBARS, + CONTROLLER_DP_TEST_PATTERN_COLORRAMP, + CONTROLLER_DP_TEST_PATTERN_VIDEOMODE, + CONTROLLER_DP_TEST_PATTERN_RESERVED_8, + CONTROLLER_DP_TEST_PATTERN_RESERVED_9, + CONTROLLER_DP_TEST_PATTERN_RESERVED_A, + CONTROLLER_DP_TEST_PATTERN_COLORSQUARES_CEA +}; + #endif /* __DAL_HW_SHARED_H__ */ diff --git a/drivers/gpu/drm/amd/display/dc/inc/hw/ipp.h b/drivers/gpu/drm/amd/display/dc/inc/hw/ipp.h index f11aa484f46e..2109eac20a3d 100644 --- a/drivers/gpu/drm/amd/display/dc/inc/hw/ipp.h +++ b/drivers/gpu/drm/amd/display/dc/inc/hw/ipp.h @@ -85,8 +85,10 @@ struct ipp_funcs { /* setup ipp to expand/convert input to pixel processor internal format */ void (*ipp_setup)( struct input_pixel_processor *ipp, - enum surface_pixel_format input_format, - enum expansion_mode mode); + enum surface_pixel_format format, + enum expansion_mode mode, + struct csc_transform input_csc_color_matrix, + enum dc_color_space input_color_space); /* DCE function to setup IPP. TODO: see if we can consolidate to setup */ void (*ipp_program_prescale)( diff --git a/drivers/gpu/drm/amd/display/dc/inc/hw/link_encoder.h b/drivers/gpu/drm/amd/display/dc/inc/hw/link_encoder.h index 498b7f05c5ca..0fd329deacd8 100644 --- a/drivers/gpu/drm/amd/display/dc/inc/hw/link_encoder.h +++ b/drivers/gpu/drm/amd/display/dc/inc/hw/link_encoder.h @@ -133,7 +133,7 @@ struct link_encoder_funcs { const struct dc_link_settings *link_settings, enum clock_source_id clock_source); void (*disable_output)(struct link_encoder *link_enc, - enum signal_type signal, struct dc_link *link); + enum signal_type signal); void (*dp_set_lane_settings)(struct link_encoder *enc, const struct link_training_settings *link_settings); void (*dp_set_phy_pattern)(struct link_encoder *enc, diff --git a/drivers/gpu/drm/amd/display/dc/inc/hw/mpc.h b/drivers/gpu/drm/amd/display/dc/inc/hw/mpc.h index d4188b2c0626..23a8d5e53a89 100644 --- a/drivers/gpu/drm/amd/display/dc/inc/hw/mpc.h +++ b/drivers/gpu/drm/amd/display/dc/inc/hw/mpc.h @@ -26,35 +26,162 @@ #define __DC_MPCC_H__ #include "dc_hw_types.h" -#include "opp.h" +#include "hw_shared.h" -struct mpcc_cfg { - int dpp_id; - int opp_id; - struct mpc_tree_cfg *tree_cfg; - unsigned int z_index; +#define MAX_MPCC 6 +#define MAX_OPP 6 - struct tg_color black_color; - bool per_pixel_alpha; - bool pre_multiplied_alpha; +enum mpc_output_csc_mode { + MPC_OUTPUT_CSC_DISABLE = 0, + MPC_OUTPUT_CSC_COEF_A, + MPC_OUTPUT_CSC_COEF_B +}; + + +enum mpcc_blend_mode { + MPCC_BLEND_MODE_BYPASS, + MPCC_BLEND_MODE_TOP_LAYER_PASSTHROUGH, + MPCC_BLEND_MODE_TOP_LAYER_ONLY, + MPCC_BLEND_MODE_TOP_BOT_BLENDING +}; + +enum mpcc_alpha_blend_mode { + MPCC_ALPHA_BLEND_MODE_PER_PIXEL_ALPHA, + MPCC_ALPHA_BLEND_MODE_PER_PIXEL_ALPHA_COMBINED_GLOBAL_GAIN, + MPCC_ALPHA_BLEND_MODE_GLOBAL_ALPHA +}; + +/* + * MPCC blending configuration + */ +struct mpcc_blnd_cfg { + struct tg_color black_color; /* background color */ + enum mpcc_alpha_blend_mode alpha_mode; /* alpha blend mode */ + bool pre_multiplied_alpha; /* alpha pre-multiplied mode flag */ + int global_gain; + int global_alpha; + bool overlap_only; + +}; + +struct mpcc_sm_cfg { + bool enable; + /* 0-single plane,2-row subsampling,4-column subsampling,6-checkboard subsampling */ + int sm_mode; + /* 0- disable frame alternate, 1- enable frame alternate */ + bool frame_alt; + /* 0- disable field alternate, 1- enable field alternate */ + bool field_alt; + /* 0-no force,2-force frame polarity from top,3-force frame polarity from bottom */ + int force_next_frame_porlarity; + /* 0-no force,2-force field polarity from top,3-force field polarity from bottom */ + int force_next_field_polarity; +}; + +/* + * MPCC connection and blending configuration for a single MPCC instance. + * This struct is used as a node in an MPC tree. + */ +struct mpcc { + int mpcc_id; /* MPCC physical instance */ + int dpp_id; /* DPP input to this MPCC */ + struct mpcc *mpcc_bot; /* pointer to bottom layer MPCC. NULL when not connected */ + struct mpcc_blnd_cfg blnd_cfg; /* The blending configuration for this MPCC */ + struct mpcc_sm_cfg sm_cfg; /* stereo mix setting for this MPCC */ +}; + +/* + * MPC tree represents all MPCC connections for a pipe. + */ +struct mpc_tree { + int opp_id; /* The OPP instance that owns this MPC tree */ + struct mpcc *opp_list; /* The top MPCC layer of the MPC tree that outputs to OPP endpoint */ }; struct mpc { const struct mpc_funcs *funcs; struct dc_context *ctx; + + struct mpcc mpcc_array[MAX_MPCC]; }; struct mpc_funcs { - int (*add)(struct mpc *mpc, struct mpcc_cfg *cfg); + /* + * Insert DPP into MPC tree based on specified blending position. + * Only used for planes that are part of blending chain for OPP output + * + * Parameters: + * [in/out] mpc - MPC context. + * [in/out] tree - MPC tree structure that plane will be added to. + * [in] blnd_cfg - MPCC blending configuration for the new blending layer. + * [in] sm_cfg - MPCC stereo mix configuration for the new blending layer. + * stereo mix must disable for the very bottom layer of the tree config. + * [in] insert_above_mpcc - Insert new plane above this MPCC. If NULL, insert as bottom plane. + * [in] dpp_id - DPP instance for the plane to be added. + * [in] mpcc_id - The MPCC physical instance to use for blending. + * + * Return: struct mpcc* - MPCC that was added. + */ + struct mpcc* (*insert_plane)( + struct mpc *mpc, + struct mpc_tree *tree, + struct mpcc_blnd_cfg *blnd_cfg, + struct mpcc_sm_cfg *sm_cfg, + struct mpcc *insert_above_mpcc, + int dpp_id, + int mpcc_id); + + /* + * Remove a specified MPCC from the MPC tree. + * + * Parameters: + * [in/out] mpc - MPC context. + * [in/out] tree - MPC tree structure that plane will be removed from. + * [in/out] mpcc - MPCC to be removed from tree. + * + * Return: void + */ + void (*remove_mpcc)( + struct mpc *mpc, + struct mpc_tree *tree, + struct mpcc *mpcc); + + /* + * Reset the MPCC HW status by disconnecting all muxes. + * + * Parameters: + * [in/out] mpc - MPC context. + * + * Return: void + */ + void (*mpc_init)(struct mpc *mpc); - void (*remove)(struct mpc *mpc, - struct mpc_tree_cfg *tree_cfg, - int opp_id, - int mpcc_inst); + /* + * Update the blending configuration for a specified MPCC. + * + * Parameters: + * [in/out] mpc - MPC context. + * [in] blnd_cfg - MPCC blending configuration. + * [in] mpcc_id - The MPCC physical instance. + * + * Return: void + */ + void (*update_blending)( + struct mpc *mpc, + struct mpcc_blnd_cfg *blnd_cfg, + int mpcc_id); + + struct mpcc* (*get_mpcc_for_dpp)( + struct mpc_tree *tree, + int dpp_id); void (*wait_for_idle)(struct mpc *mpc, int id); - void (*update_blend_mode)(struct mpc *mpc, struct mpcc_cfg *cfg); + void (*assert_mpcc_idle_before_connect)(struct mpc *mpc, int mpcc_id); + + void (*init_mpcc_list_from_hw)( + struct mpc *mpc, + struct mpc_tree *tree); }; diff --git a/drivers/gpu/drm/amd/display/dc/inc/hw/opp.h b/drivers/gpu/drm/amd/display/dc/inc/hw/opp.h index 75adb8fec551..ab8fb77f1ae5 100644 --- a/drivers/gpu/drm/amd/display/dc/inc/hw/opp.h +++ b/drivers/gpu/drm/amd/display/dc/inc/hw/opp.h @@ -29,6 +29,7 @@ #include "hw_shared.h" #include "dc_hw_types.h" #include "transform.h" +#include "mpc.h" struct fixed31_32; @@ -204,7 +205,7 @@ struct output_pixel_processor { struct dc_context *ctx; uint32_t inst; struct pwl_params regamma_params; - struct mpc_tree_cfg mpc_tree; + struct mpc_tree mpc_tree_params; bool mpcc_disconnect_pending[MAX_PIPES]; const struct opp_funcs *funcs; }; @@ -248,6 +249,21 @@ enum ovl_csc_adjust_item { OVERLAY_COLOR_TEMPERATURE }; +enum oppbuf_display_segmentation { + OPPBUF_DISPLAY_SEGMENTATION_1_SEGMENT = 0, + OPPBUF_DISPLAY_SEGMENTATION_2_SEGMENT = 1, + OPPBUF_DISPLAY_SEGMENTATION_4_SEGMENT = 2, + OPPBUF_DISPLAY_SEGMENTATION_4_SEGMENT_SPLIT_LEFT = 3, + OPPBUF_DISPLAY_SEGMENTATION_4_SEGMENT_SPLIT_RIGHT = 4 +}; + +struct oppbuf_params { + uint32_t active_width; + enum oppbuf_display_segmentation mso_segmentation; + uint32_t mso_overlap_pixel_num; + uint32_t pixel_repetition; +}; + struct opp_funcs { @@ -276,14 +292,11 @@ struct opp_funcs { void (*opp_destroy)(struct output_pixel_processor **opp); - void (*opp_set_stereo_polarity)( - struct output_pixel_processor *opp, - bool enable, - bool rightEyePolarity); + void (*opp_program_stereo)( + struct output_pixel_processor *opp, + bool enable, + const struct dc_crtc_timing *timing); - void (*opp_set_test_pattern)( - struct output_pixel_processor *opp, - bool enable); }; #endif diff --git a/drivers/gpu/drm/amd/display/dc/inc/hw/timing_generator.h b/drivers/gpu/drm/amd/display/dc/inc/hw/timing_generator.h index c6ab38c5b2be..ec312f1a3e55 100644 --- a/drivers/gpu/drm/amd/display/dc/inc/hw/timing_generator.h +++ b/drivers/gpu/drm/amd/display/dc/inc/hw/timing_generator.h @@ -26,6 +26,8 @@ #ifndef __DAL_TIMING_GENERATOR_TYPES_H__ #define __DAL_TIMING_GENERATOR_TYPES_H__ +#include "hw_shared.h" + struct dc_bios; /* Contains CRTC vertical/horizontal pixel counters */ @@ -40,6 +42,19 @@ struct dcp_gsl_params { int gsl_master; }; +struct gsl_params { + int gsl0_en; + int gsl1_en; + int gsl2_en; + int gsl_master_en; + int gsl_master_mode; + int master_update_lock_gsl_en; + int gsl_window_start_x; + int gsl_window_end_x; + int gsl_window_start_y; + int gsl_window_end_y; +}; + /* define the structure of Dynamic Refresh Mode */ struct drr_params { uint32_t vertical_total_min; @@ -50,43 +65,6 @@ struct drr_params { #define LEFT_EYE_3D_PRIMARY_SURFACE 1 #define RIGHT_EYE_3D_PRIMARY_SURFACE 0 -enum test_pattern_dyn_range { - TEST_PATTERN_DYN_RANGE_VESA = 0, - TEST_PATTERN_DYN_RANGE_CEA -}; - -enum test_pattern_mode { - TEST_PATTERN_MODE_COLORSQUARES_RGB = 0, - TEST_PATTERN_MODE_COLORSQUARES_YCBCR601, - TEST_PATTERN_MODE_COLORSQUARES_YCBCR709, - TEST_PATTERN_MODE_VERTICALBARS, - TEST_PATTERN_MODE_HORIZONTALBARS, - TEST_PATTERN_MODE_SINGLERAMP_RGB, - TEST_PATTERN_MODE_DUALRAMP_RGB -}; - -enum test_pattern_color_format { - TEST_PATTERN_COLOR_FORMAT_BPC_6 = 0, - TEST_PATTERN_COLOR_FORMAT_BPC_8, - TEST_PATTERN_COLOR_FORMAT_BPC_10, - TEST_PATTERN_COLOR_FORMAT_BPC_12 -}; - -enum controller_dp_test_pattern { - CONTROLLER_DP_TEST_PATTERN_D102 = 0, - CONTROLLER_DP_TEST_PATTERN_SYMBOLERROR, - CONTROLLER_DP_TEST_PATTERN_PRBS7, - CONTROLLER_DP_TEST_PATTERN_COLORSQUARES, - CONTROLLER_DP_TEST_PATTERN_VERTICALBARS, - CONTROLLER_DP_TEST_PATTERN_HORIZONTALBARS, - CONTROLLER_DP_TEST_PATTERN_COLORRAMP, - CONTROLLER_DP_TEST_PATTERN_VIDEOMODE, - CONTROLLER_DP_TEST_PATTERN_RESERVED_8, - CONTROLLER_DP_TEST_PATTERN_RESERVED_9, - CONTROLLER_DP_TEST_PATTERN_RESERVED_A, - CONTROLLER_DP_TEST_PATTERN_COLORSQUARES_CEA -}; - enum crtc_state { CRTC_STATE_VBLANK = 0, CRTC_STATE_VACTIVE @@ -100,6 +78,12 @@ struct _dlg_otg_param { enum signal_type signal; }; +struct vupdate_keepout_params { + int start_offset; + int end_offset; + int enable; +}; + struct crtc_stereo_flags { uint8_t PROGRAM_STEREO : 1; uint8_t PROGRAM_POLARITY : 1; @@ -158,7 +142,11 @@ struct timing_generator_funcs { const struct dcp_gsl_params *gsl_params); void (*unlock)(struct timing_generator *tg); void (*lock)(struct timing_generator *tg); - void (*enable_reset_trigger)(struct timing_generator *tg, int source_tg_inst); + void (*enable_reset_trigger)(struct timing_generator *tg, + int source_tg_inst); + void (*enable_crtc_reset)(struct timing_generator *tg, + int source_tg_inst, + struct crtc_trigger_info *crtc_tp); void (*disable_reset_trigger)(struct timing_generator *tg); void (*tear_down_global_swap_lock)(struct timing_generator *tg); void (*enable_advanced_request)(struct timing_generator *tg, @@ -178,6 +166,13 @@ struct timing_generator_funcs { void (*program_stereo)(struct timing_generator *tg, const struct dc_crtc_timing *timing, struct crtc_stereo_flags *flags); bool (*is_stereo_left_eye)(struct timing_generator *tg); + + void (*set_blank_data_double_buffer)(struct timing_generator *tg, bool enable); + + void (*tg_init)(struct timing_generator *tg); + bool (*is_tg_enabled)(struct timing_generator *tg); + bool (*is_optc_underflow_occurred)(struct timing_generator *tg); + void (*clear_optc_underflow)(struct timing_generator *tg); }; #endif diff --git a/drivers/gpu/drm/amd/display/dc/inc/hw/transform.h b/drivers/gpu/drm/amd/display/dc/inc/hw/transform.h index ea88997e1bbd..6f6c02b89f90 100644 --- a/drivers/gpu/drm/amd/display/dc/inc/hw/transform.h +++ b/drivers/gpu/drm/amd/display/dc/inc/hw/transform.h @@ -250,8 +250,10 @@ struct transform_funcs { void (*ipp_setup)( struct transform *xfm_base, - enum surface_pixel_format input_format, - enum expansion_mode mode); + enum surface_pixel_format format, + enum expansion_mode mode, + struct csc_transform input_csc_color_matrix, + enum dc_color_space input_color_space); void (*ipp_full_bypass)(struct transform *xfm_base); diff --git a/drivers/gpu/drm/amd/display/dc/inc/hw_sequencer.h b/drivers/gpu/drm/amd/display/dc/inc/hw_sequencer.h index 8734689a9245..4c0aa56f7bae 100644 --- a/drivers/gpu/drm/amd/display/dc/inc/hw_sequencer.h +++ b/drivers/gpu/drm/amd/display/dc/inc/hw_sequencer.h @@ -28,6 +28,7 @@ #include "dc_types.h" #include "clock_source.h" #include "inc/hw/timing_generator.h" +#include "inc/hw/opp.h" #include "inc/hw/link_encoder.h" #include "core_status.h" @@ -39,6 +40,12 @@ enum pipe_gating_control { struct dce_hwseq_wa { bool blnd_crtc_trigger; + bool DEGVIDCN10_253; + bool false_optc_underflow; +}; + +struct hwseq_wa_state { + bool DEGVIDCN10_253_applied; }; struct dce_hwseq { @@ -47,6 +54,7 @@ struct dce_hwseq { const struct dce_hwseq_shift *shifts; const struct dce_hwseq_mask *masks; struct dce_hwseq_wa wa; + struct hwseq_wa_state wa_state; }; struct pipe_ctx; @@ -114,6 +122,11 @@ struct hw_sequencer_funcs { int group_size, struct pipe_ctx *grouped_pipes[]); + void (*enable_per_frame_crtc_position_reset)( + struct dc *dc, + int group_size, + struct pipe_ctx *grouped_pipes[]); + void (*enable_display_pipe_clock_gating)( struct dc_context *ctx, bool clock_gating); @@ -124,11 +137,7 @@ struct hw_sequencer_funcs { struct dc_bios *dcb, enum pipe_gating_control power_gating); - void (*power_down_front_end)(struct dc *dc, int fe_idx); - - void (*power_on_front_end)(struct dc *dc, - struct pipe_ctx *pipe, - struct dc_state *context); + void (*disable_plane)(struct dc *dc, struct pipe_ctx *pipe_ctx); void (*update_info_frame)(struct pipe_ctx *pipe_ctx); @@ -178,12 +187,17 @@ struct hw_sequencer_funcs { void (*ready_shared_resources)(struct dc *dc, struct dc_state *context); void (*optimize_shared_resources)(struct dc *dc); + void (*pplib_apply_display_requirements)( + struct dc *dc, + struct dc_state *context); void (*edp_power_control)( - struct link_encoder *enc, + struct dc_link *link, bool enable); void (*edp_backlight_control)( struct dc_link *link, bool enable); + void (*edp_wait_for_hpd_ready)(struct dc_link *link, bool power_up); + }; void color_space_to_black_color( @@ -194,4 +208,8 @@ void color_space_to_black_color( bool hwss_wait_for_blank_complete( struct timing_generator *tg); +const uint16_t *find_color_matrix( + enum dc_color_space color_space, + uint32_t *array_size); + #endif /* __DC_HW_SEQUENCER_H__ */ diff --git a/drivers/gpu/drm/amd/display/dc/irq/dce120/irq_service_dce120.c b/drivers/gpu/drm/amd/display/dc/irq/dce120/irq_service_dce120.c index 2ad56b1a4099..66d52580e29f 100644 --- a/drivers/gpu/drm/amd/display/dc/irq/dce120/irq_service_dce120.c +++ b/drivers/gpu/drm/amd/display/dc/irq/dce120/irq_service_dce120.c @@ -30,9 +30,9 @@ #include "irq_service_dce120.h" #include "../dce110/irq_service_dce110.h" -#include "vega10/DC/dce_12_0_offset.h" -#include "vega10/DC/dce_12_0_sh_mask.h" -#include "vega10/soc15ip.h" +#include "dce/dce_12_0_offset.h" +#include "dce/dce_12_0_sh_mask.h" +#include "soc15ip.h" #include "ivsrcid/ivsrcid_vislands30.h" diff --git a/drivers/gpu/drm/amd/display/dc/irq/dcn10/irq_service_dcn10.c b/drivers/gpu/drm/amd/display/dc/irq/dcn10/irq_service_dcn10.c index 74ad24714f6b..7f7db66c48b0 100644 --- a/drivers/gpu/drm/amd/display/dc/irq/dcn10/irq_service_dcn10.c +++ b/drivers/gpu/drm/amd/display/dc/irq/dcn10/irq_service_dcn10.c @@ -29,9 +29,9 @@ #include "../dce110/irq_service_dce110.h" -#include "raven1/DCN/dcn_1_0_offset.h" -#include "raven1/DCN/dcn_1_0_sh_mask.h" -#include "vega10/soc15ip.h" +#include "dcn/dcn_1_0_offset.h" +#include "dcn/dcn_1_0_sh_mask.h" +#include "soc15ip.h" #include "irq_service_dcn10.h" diff --git a/drivers/gpu/drm/amd/display/dc/os_types.h b/drivers/gpu/drm/amd/display/dc/os_types.h index a87c0329541f..1fcbc99e63b5 100644 --- a/drivers/gpu/drm/amd/display/dc/os_types.h +++ b/drivers/gpu/drm/amd/display/dc/os_types.h @@ -26,8 +26,6 @@ #ifndef _OS_TYPES_H_ #define _OS_TYPES_H_ -#if defined __KERNEL__ - #include <asm/byteorder.h> #include <linux/types.h> #include <drm/drmP.h> @@ -46,14 +44,12 @@ #undef WRITE #undef FRAME_SIZE -#define dm_output_to_console(fmt, ...) DRM_INFO(fmt, ##__VA_ARGS__) +#define dm_output_to_console(fmt, ...) DRM_DEBUG_KMS(fmt, ##__VA_ARGS__) #define dm_error(fmt, ...) DRM_ERROR(fmt, ##__VA_ARGS__) -#define dm_debug(fmt, ...) DRM_DEBUG_KMS(fmt, ##__VA_ARGS__) - -#define dm_vlog(fmt, args) vprintk(fmt, args) - +#if defined(CONFIG_DRM_AMD_DC_DCN1_0) +#include <asm/fpu/api.h> #endif /* @@ -89,8 +85,4 @@ BREAK_TO_DEBUGGER(); \ } while (0) -#if defined(CONFIG_DRM_AMD_DC_DCN1_0) -#include <asm/fpu/api.h> -#endif - #endif /* _OS_TYPES_H_ */ diff --git a/drivers/gpu/drm/amd/display/dc/virtual/virtual_link_encoder.c b/drivers/gpu/drm/amd/display/dc/virtual/virtual_link_encoder.c index 88c2bde3f039..57a54a7b89e5 100644 --- a/drivers/gpu/drm/amd/display/dc/virtual/virtual_link_encoder.c +++ b/drivers/gpu/drm/amd/display/dc/virtual/virtual_link_encoder.c @@ -58,8 +58,7 @@ static void virtual_link_encoder_enable_dp_mst_output( static void virtual_link_encoder_disable_output( struct link_encoder *link_enc, - enum signal_type signal, - struct dc_link *link) {} + enum signal_type signal) {} static void virtual_link_encoder_dp_set_lane_settings( struct link_encoder *enc, |