diff options
Diffstat (limited to 'drivers/gpu/drm/amd/display/dc/dcn10')
20 files changed, 3542 insertions, 2708 deletions
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); |