diff options
Diffstat (limited to 'drivers/gpu/drm/amd/display/dc/dce110')
7 files changed, 407 insertions, 276 deletions
diff --git a/drivers/gpu/drm/amd/display/dc/dce110/dce110_hw_sequencer.c b/drivers/gpu/drm/amd/display/dc/dce110/dce110_hw_sequencer.c index d844fadcd56f..86cdd7b4811f 100644 --- a/drivers/gpu/drm/amd/display/dc/dce110/dce110_hw_sequencer.c +++ b/drivers/gpu/drm/amd/display/dc/dce110/dce110_hw_sequencer.c @@ -257,9 +257,9 @@ static void build_prescale_params(struct ipp_prescale_params *prescale_params, } } -static bool dce110_set_input_transfer_func( - struct pipe_ctx *pipe_ctx, - const struct dc_plane_state *plane_state) +static bool +dce110_set_input_transfer_func(struct pipe_ctx *pipe_ctx, + const struct dc_plane_state *plane_state) { struct input_pixel_processor *ipp = pipe_ctx->plane_res.ipp; const struct dc_transfer_func *tf = NULL; @@ -280,25 +280,19 @@ static bool dce110_set_input_transfer_func( if (tf == NULL) { /* Default case if no input transfer function specified */ - ipp->funcs->ipp_set_degamma(ipp, - IPP_DEGAMMA_MODE_HW_sRGB); + ipp->funcs->ipp_set_degamma(ipp, IPP_DEGAMMA_MODE_HW_sRGB); } else if (tf->type == TF_TYPE_PREDEFINED) { switch (tf->tf) { case TRANSFER_FUNCTION_SRGB: - ipp->funcs->ipp_set_degamma(ipp, - IPP_DEGAMMA_MODE_HW_sRGB); + ipp->funcs->ipp_set_degamma(ipp, IPP_DEGAMMA_MODE_HW_sRGB); break; case TRANSFER_FUNCTION_BT709: - ipp->funcs->ipp_set_degamma(ipp, - IPP_DEGAMMA_MODE_HW_xvYCC); + ipp->funcs->ipp_set_degamma(ipp, IPP_DEGAMMA_MODE_HW_xvYCC); break; case TRANSFER_FUNCTION_LINEAR: - ipp->funcs->ipp_set_degamma(ipp, - IPP_DEGAMMA_MODE_BYPASS); + ipp->funcs->ipp_set_degamma(ipp, IPP_DEGAMMA_MODE_BYPASS); break; case TRANSFER_FUNCTION_PQ: - result = false; - break; default: result = false; break; @@ -313,10 +307,9 @@ static bool dce110_set_input_transfer_func( return result; } -static bool convert_to_custom_float( - struct pwl_result_data *rgb_resulted, - struct curve_points *arr_points, - uint32_t hw_points_num) +static bool convert_to_custom_float(struct pwl_result_data *rgb_resulted, + struct curve_points *arr_points, + uint32_t hw_points_num) { struct custom_float_format fmt; @@ -328,26 +321,20 @@ static bool convert_to_custom_float( fmt.mantissa_bits = 12; fmt.sign = true; - if (!convert_to_custom_float_format( - arr_points[0].x, - &fmt, - &arr_points[0].custom_float_x)) { + if (!convert_to_custom_float_format(arr_points[0].x, &fmt, + &arr_points[0].custom_float_x)) { BREAK_TO_DEBUGGER(); return false; } - if (!convert_to_custom_float_format( - arr_points[0].offset, - &fmt, - &arr_points[0].custom_float_offset)) { + if (!convert_to_custom_float_format(arr_points[0].offset, &fmt, + &arr_points[0].custom_float_offset)) { BREAK_TO_DEBUGGER(); return false; } - if (!convert_to_custom_float_format( - arr_points[0].slope, - &fmt, - &arr_points[0].custom_float_slope)) { + if (!convert_to_custom_float_format(arr_points[0].slope, &fmt, + &arr_points[0].custom_float_slope)) { BREAK_TO_DEBUGGER(); return false; } @@ -355,26 +342,20 @@ static bool convert_to_custom_float( fmt.mantissa_bits = 10; fmt.sign = false; - if (!convert_to_custom_float_format( - arr_points[1].x, - &fmt, - &arr_points[1].custom_float_x)) { + if (!convert_to_custom_float_format(arr_points[1].x, &fmt, + &arr_points[1].custom_float_x)) { BREAK_TO_DEBUGGER(); return false; } - if (!convert_to_custom_float_format( - arr_points[1].y, - &fmt, - &arr_points[1].custom_float_y)) { + if (!convert_to_custom_float_format(arr_points[1].y, &fmt, + &arr_points[1].custom_float_y)) { BREAK_TO_DEBUGGER(); return false; } - if (!convert_to_custom_float_format( - arr_points[2].slope, - &fmt, - &arr_points[2].custom_float_slope)) { + if (!convert_to_custom_float_format(arr_points[1].slope, &fmt, + &arr_points[1].custom_float_slope)) { BREAK_TO_DEBUGGER(); return false; } @@ -383,50 +364,38 @@ static bool convert_to_custom_float( fmt.sign = true; while (i != hw_points_num) { - if (!convert_to_custom_float_format( - rgb->red, - &fmt, - &rgb->red_reg)) { + if (!convert_to_custom_float_format(rgb->red, &fmt, + &rgb->red_reg)) { BREAK_TO_DEBUGGER(); return false; } - if (!convert_to_custom_float_format( - rgb->green, - &fmt, - &rgb->green_reg)) { + if (!convert_to_custom_float_format(rgb->green, &fmt, + &rgb->green_reg)) { BREAK_TO_DEBUGGER(); return false; } - if (!convert_to_custom_float_format( - rgb->blue, - &fmt, - &rgb->blue_reg)) { + if (!convert_to_custom_float_format(rgb->blue, &fmt, + &rgb->blue_reg)) { BREAK_TO_DEBUGGER(); return false; } - if (!convert_to_custom_float_format( - rgb->delta_red, - &fmt, - &rgb->delta_red_reg)) { + if (!convert_to_custom_float_format(rgb->delta_red, &fmt, + &rgb->delta_red_reg)) { BREAK_TO_DEBUGGER(); return false; } - if (!convert_to_custom_float_format( - rgb->delta_green, - &fmt, - &rgb->delta_green_reg)) { + if (!convert_to_custom_float_format(rgb->delta_green, &fmt, + &rgb->delta_green_reg)) { BREAK_TO_DEBUGGER(); return false; } - if (!convert_to_custom_float_format( - rgb->delta_blue, - &fmt, - &rgb->delta_blue_reg)) { + if (!convert_to_custom_float_format(rgb->delta_blue, &fmt, + &rgb->delta_blue_reg)) { BREAK_TO_DEBUGGER(); return false; } @@ -438,8 +407,9 @@ static bool convert_to_custom_float( return true; } -static bool dce110_translate_regamma_to_hw_format(const struct dc_transfer_func - *output_tf, struct pwl_params *regamma_params) +static bool +dce110_translate_regamma_to_hw_format(const struct dc_transfer_func *output_tf, + struct pwl_params *regamma_params) { struct curve_points *arr_points; struct pwl_result_data *rgb_resulted; @@ -454,8 +424,7 @@ static bool dce110_translate_regamma_to_hw_format(const struct dc_transfer_func int32_t segment_start, segment_end; uint32_t i, j, k, seg_distr[16], increment, start_index, hw_points; - if (output_tf == NULL || regamma_params == NULL || - output_tf->type == TF_TYPE_BYPASS) + if (output_tf == NULL || regamma_params == NULL || output_tf->type == TF_TYPE_BYPASS) return false; arr_points = regamma_params->arr_points; @@ -534,19 +503,14 @@ static bool dce110_translate_regamma_to_hw_format(const struct dc_transfer_func /* last point */ start_index = (segment_end + 25) * 32; - rgb_resulted[hw_points - 1].red = - output_tf->tf_pts.red[start_index]; - rgb_resulted[hw_points - 1].green = - output_tf->tf_pts.green[start_index]; - rgb_resulted[hw_points - 1].blue = - output_tf->tf_pts.blue[start_index]; + rgb_resulted[hw_points - 1].red = output_tf->tf_pts.red[start_index]; + rgb_resulted[hw_points - 1].green = output_tf->tf_pts.green[start_index]; + rgb_resulted[hw_points - 1].blue = output_tf->tf_pts.blue[start_index]; arr_points[0].x = dal_fixed31_32_pow(dal_fixed31_32_from_int(2), - dal_fixed31_32_from_int(segment_start)); + dal_fixed31_32_from_int(segment_start)); arr_points[1].x = dal_fixed31_32_pow(dal_fixed31_32_from_int(2), - dal_fixed31_32_from_int(segment_end)); - arr_points[2].x = dal_fixed31_32_pow(dal_fixed31_32_from_int(2), - dal_fixed31_32_from_int(segment_end)); + dal_fixed31_32_from_int(segment_end)); y_r = rgb_resulted[0].red; y_g = rgb_resulted[0].green; @@ -555,9 +519,8 @@ static bool dce110_translate_regamma_to_hw_format(const struct dc_transfer_func y1_min = dal_fixed31_32_min(y_r, dal_fixed31_32_min(y_g, y_b)); arr_points[0].y = y1_min; - arr_points[0].slope = dal_fixed31_32_div( - arr_points[0].y, - arr_points[0].x); + arr_points[0].slope = dal_fixed31_32_div(arr_points[0].y, + arr_points[0].x); y_r = rgb_resulted[hw_points - 1].red; y_g = rgb_resulted[hw_points - 1].green; @@ -569,24 +532,18 @@ static bool dce110_translate_regamma_to_hw_format(const struct dc_transfer_func y3_max = dal_fixed31_32_max(y_r, dal_fixed31_32_max(y_g, y_b)); arr_points[1].y = y3_max; - arr_points[2].y = y3_max; arr_points[1].slope = dal_fixed31_32_zero; - arr_points[2].slope = dal_fixed31_32_zero; if (output_tf->tf == TRANSFER_FUNCTION_PQ) { /* for PQ, we want to have a straight line from last HW X point, * and the slope to be such that we hit 1.0 at 10000 nits. */ - const struct fixed31_32 end_value = - dal_fixed31_32_from_int(125); + const struct fixed31_32 end_value = dal_fixed31_32_from_int(125); arr_points[1].slope = dal_fixed31_32_div( - dal_fixed31_32_sub(dal_fixed31_32_one, arr_points[1].y), - dal_fixed31_32_sub(end_value, arr_points[1].x)); - arr_points[2].slope = dal_fixed31_32_div( - dal_fixed31_32_sub(dal_fixed31_32_one, arr_points[1].y), - dal_fixed31_32_sub(end_value, arr_points[1].x)); + dal_fixed31_32_sub(dal_fixed31_32_one, arr_points[1].y), + dal_fixed31_32_sub(end_value, arr_points[1].x)); } regamma_params->hw_points_num = hw_points; @@ -594,18 +551,15 @@ static bool dce110_translate_regamma_to_hw_format(const struct dc_transfer_func i = 1; for (k = 0; k < 16 && i < 16; k++) { if (seg_distr[k] != -1) { - regamma_params->arr_curve_points[k].segments_num = - seg_distr[k]; + regamma_params->arr_curve_points[k].segments_num = seg_distr[k]; regamma_params->arr_curve_points[i].offset = - regamma_params->arr_curve_points[k]. - offset + (1 << seg_distr[k]); + regamma_params->arr_curve_points[k].offset + (1 << seg_distr[k]); } i++; } if (seg_distr[k] != -1) - regamma_params->arr_curve_points[k].segments_num = - seg_distr[k]; + regamma_params->arr_curve_points[k].segments_num = seg_distr[k]; rgb = rgb_resulted; rgb_plus_1 = rgb_resulted + 1; @@ -620,15 +574,9 @@ static bool dce110_translate_regamma_to_hw_format(const struct dc_transfer_func if (dal_fixed31_32_lt(rgb_plus_1->blue, rgb->blue)) rgb_plus_1->blue = rgb->blue; - rgb->delta_red = dal_fixed31_32_sub( - rgb_plus_1->red, - rgb->red); - rgb->delta_green = dal_fixed31_32_sub( - rgb_plus_1->green, - rgb->green); - rgb->delta_blue = dal_fixed31_32_sub( - rgb_plus_1->blue, - rgb->blue); + rgb->delta_red = dal_fixed31_32_sub(rgb_plus_1->red, rgb->red); + rgb->delta_green = dal_fixed31_32_sub(rgb_plus_1->green, rgb->green); + rgb->delta_blue = dal_fixed31_32_sub(rgb_plus_1->blue, rgb->blue); ++rgb_plus_1; ++rgb; @@ -640,9 +588,9 @@ static bool dce110_translate_regamma_to_hw_format(const struct dc_transfer_func return true; } -static bool dce110_set_output_transfer_func( - struct pipe_ctx *pipe_ctx, - const struct dc_stream_state *stream) +static bool +dce110_set_output_transfer_func(struct pipe_ctx *pipe_ctx, + const struct dc_stream_state *stream) { struct transform *xfm = pipe_ctx->plane_res.xfm; @@ -650,13 +598,11 @@ static bool dce110_set_output_transfer_func( xfm->regamma_params.hw_points_num = GAMMA_HW_POINTS_NUM; if (stream->out_transfer_func && - stream->out_transfer_func->type == - TF_TYPE_PREDEFINED && - stream->out_transfer_func->tf == - TRANSFER_FUNCTION_SRGB) { + stream->out_transfer_func->type == TF_TYPE_PREDEFINED && + stream->out_transfer_func->tf == TRANSFER_FUNCTION_SRGB) { xfm->funcs->opp_set_regamma_mode(xfm, OPP_REGAMMA_SRGB); - } else if (dce110_translate_regamma_to_hw_format( - stream->out_transfer_func, &xfm->regamma_params)) { + } else if (dce110_translate_regamma_to_hw_format(stream->out_transfer_func, + &xfm->regamma_params)) { xfm->funcs->opp_program_regamma_pwl(xfm, &xfm->regamma_params); xfm->funcs->opp_set_regamma_mode(xfm, OPP_REGAMMA_USER); } else { @@ -814,11 +760,11 @@ static enum bp_result link_transmitter_control( * eDP only. */ void hwss_edp_wait_for_hpd_ready( - struct link_encoder *enc, - bool power_up) + struct dc_link *link, + bool power_up) { - struct dc_context *ctx = enc->ctx; - struct graphics_object_id connector = enc->connector; + struct dc_context *ctx = link->ctx; + struct graphics_object_id connector = link->link_enc->connector; struct gpio *hpd; bool edp_hpd_high = false; uint32_t time_elapsed = 0; @@ -882,16 +828,16 @@ void hwss_edp_wait_for_hpd_ready( } void hwss_edp_power_control( - struct link_encoder *enc, - bool power_up) + struct dc_link *link, + bool power_up) { - struct dc_context *ctx = enc->ctx; + struct dc_context *ctx = link->ctx; struct dce_hwseq *hwseq = ctx->dc->hwseq; struct bp_transmitter_control cntl = { 0 }; enum bp_result bp_result; - if (dal_graphics_object_id_get_connector_id(enc->connector) + if (dal_graphics_object_id_get_connector_id(link->link_enc->connector) != CONNECTOR_ID_EDP) { BREAK_TO_DEBUGGER(); return; @@ -907,11 +853,11 @@ void hwss_edp_power_control( cntl.action = power_up ? TRANSMITTER_CONTROL_POWER_ON : TRANSMITTER_CONTROL_POWER_OFF; - cntl.transmitter = enc->transmitter; - cntl.connector_obj_id = enc->connector; + cntl.transmitter = link->link_enc->transmitter; + cntl.connector_obj_id = link->link_enc->connector; cntl.coherent = false; cntl.lanes_number = LANE_COUNT_FOUR; - cntl.hpd_sel = enc->hpd_source; + cntl.hpd_sel = link->link_enc->hpd_source; bp_result = link_transmitter_control(ctx->dc_bios, &cntl); @@ -924,8 +870,6 @@ void hwss_edp_power_control( "%s: Skipping Panel Power action: %s\n", __func__, (power_up ? "On":"Off")); } - - hwss_edp_wait_for_hpd_ready(enc, true); } /*todo: cloned in stream enc, fix*/ @@ -934,14 +878,14 @@ void hwss_edp_power_control( * eDP only. Control the backlight of the eDP panel */ void hwss_edp_backlight_control( - struct dc_link *link, - bool enable) + struct dc_link *link, + bool enable) { - struct dce_hwseq *hws = link->dc->hwseq; - struct dc_context *ctx = link->dc->ctx; + struct dc_context *ctx = link->ctx; + struct dce_hwseq *hws = ctx->dc->hwseq; struct bp_transmitter_control cntl = { 0 }; - if (dal_graphics_object_id_get_connector_id(link->link_id) + if (dal_graphics_object_id_get_connector_id(link->link_enc->connector) != CONNECTOR_ID_EDP) { BREAK_TO_DEBUGGER(); return; @@ -982,7 +926,7 @@ void hwss_edp_backlight_control( * Enable it in the future if necessary. */ /* dc_service_sleep_in_milliseconds(50); */ - link_transmitter_control(link->dc->ctx->dc_bios, &cntl); + link_transmitter_control(ctx->dc_bios, &cntl); } void dce110_disable_stream(struct pipe_ctx *pipe_ctx, int option) @@ -1026,11 +970,9 @@ void dce110_disable_stream(struct pipe_ctx *pipe_ctx, int option) } /* blank at encoder level */ - if (dc_is_dp_signal(pipe_ctx->stream->signal)) { - if (pipe_ctx->stream->sink->link->connector_signal == SIGNAL_TYPE_EDP) - hwss_edp_backlight_control(link, false); + if (dc_is_dp_signal(pipe_ctx->stream->signal)) pipe_ctx->stream_res.stream_enc->funcs->dp_blank(pipe_ctx->stream_res.stream_enc); - } + link->link_enc->funcs->connect_dig_be_to_fe( link->link_enc, pipe_ctx->stream_res.stream_enc->id, @@ -1042,15 +984,12 @@ void dce110_unblank_stream(struct pipe_ctx *pipe_ctx, struct dc_link_settings *link_settings) { struct encoder_unblank_param params = { { 0 } }; - struct dc_link *link = pipe_ctx->stream->sink->link; /* only 3 items below are used by unblank */ params.pixel_clk_khz = pipe_ctx->stream->timing.pix_clk_khz; params.link_settings.link_rate = link_settings->link_rate; pipe_ctx->stream_res.stream_enc->funcs->dp_unblank(pipe_ctx->stream_res.stream_enc, ¶ms); - if (link->connector_signal == SIGNAL_TYPE_EDP) - hwss_edp_backlight_control(link, true); } @@ -1401,7 +1340,7 @@ static void power_down_encoders(struct dc *dc) } dc->links[i]->link_enc->funcs->disable_output( - dc->links[i]->link_enc, signal, dc->links[i]); + dc->links[i]->link_enc, signal); } } @@ -1462,7 +1401,9 @@ static void disable_vga_and_power_gate_all_controllers( enable_display_pipe_clock_gating(ctx, true); - dc->hwss.power_down_front_end(dc, i); + dc->current_state->res_ctx.pipe_ctx[i].pipe_idx = i; + dc->hwss.disable_plane(dc, + &dc->current_state->res_ctx.pipe_ctx[i]); } } @@ -1748,60 +1689,54 @@ static void apply_min_clocks( /* * Check if FBC can be enabled */ -static enum dc_status validate_fbc(struct dc *dc, - struct dc_state *context) +static bool should_enable_fbc(struct dc *dc, + struct dc_state *context) { - struct pipe_ctx *pipe_ctx = - &context->res_ctx.pipe_ctx[0]; + struct pipe_ctx *pipe_ctx = &context->res_ctx.pipe_ctx[0]; ASSERT(dc->fbc_compressor); /* FBC memory should be allocated */ if (!dc->ctx->fbc_gpu_addr) - return DC_ERROR_UNEXPECTED; + return false; /* Only supports single display */ if (context->stream_count != 1) - return DC_ERROR_UNEXPECTED; + return false; /* Only supports eDP */ if (pipe_ctx->stream->sink->link->connector_signal != SIGNAL_TYPE_EDP) - return DC_ERROR_UNEXPECTED; + return false; /* PSR should not be enabled */ if (pipe_ctx->stream->sink->link->psr_enabled) - return DC_ERROR_UNEXPECTED; + return false; /* Nothing to compress */ if (!pipe_ctx->plane_state) - return DC_ERROR_UNEXPECTED; + return false; /* Only for non-linear tiling */ if (pipe_ctx->plane_state->tiling_info.gfx8.array_mode == DC_ARRAY_LINEAR_GENERAL) - return DC_ERROR_UNEXPECTED; + return false; - return DC_OK; + return true; } /* * Enable FBC */ -static enum dc_status enable_fbc(struct dc *dc, - struct dc_state *context) +static void enable_fbc(struct dc *dc, + struct dc_state *context) { - enum dc_status status = validate_fbc(dc, context); - - if (status == DC_OK) { + if (should_enable_fbc(dc, context)) { /* Program GRPH COMPRESSED ADDRESS and PITCH */ struct compr_addr_and_pitch_params params = {0, 0, 0}; struct compressor *compr = dc->fbc_compressor; - struct pipe_ctx *pipe_ctx = - &context->res_ctx.pipe_ctx[0]; + struct pipe_ctx *pipe_ctx = &context->res_ctx.pipe_ctx[0]; - params.source_view_width = - pipe_ctx->stream->timing.h_addressable; - params.source_view_height = - pipe_ctx->stream->timing.v_addressable; + params.source_view_width = pipe_ctx->stream->timing.h_addressable; + params.source_view_height = pipe_ctx->stream->timing.v_addressable; compr->compr_surface_address.quad_part = dc->ctx->fbc_gpu_addr; @@ -1810,7 +1745,6 @@ static enum dc_status enable_fbc(struct dc *dc, compr->funcs->enable_fbc(compr, ¶ms); } - return status; } #endif @@ -1888,7 +1822,7 @@ static void dce110_reset_hw_ctx_wrap( if (old_clk) old_clk->funcs->cs_power_down(old_clk); - dc->hwss.power_down_front_end(dc, pipe_ctx_old->pipe_idx); + dc->hwss.disable_plane(dc, pipe_ctx_old); pipe_ctx_old->stream = NULL; } @@ -2076,8 +2010,7 @@ enum dc_status dce110_apply_ctx_to_hw( if (pipe_ctx->stream == pipe_ctx_old->stream) continue; - if (pipe_ctx->stream && pipe_ctx_old->stream - && !pipe_need_reprogram(pipe_ctx_old, pipe_ctx)) + if (pipe_ctx_old->stream && !pipe_need_reprogram(pipe_ctx_old, pipe_ctx)) continue; if (pipe_ctx->top_pipe) @@ -2113,9 +2046,6 @@ enum dc_status dce110_apply_ctx_to_hw( context, dc); - if (dc->hwss.power_on_front_end) - dc->hwss.power_on_front_end(dc, pipe_ctx, context); - if (DC_OK != status) return status; } @@ -2145,16 +2075,8 @@ static void set_default_colors(struct pipe_ctx *pipe_ctx) struct default_adjustment default_adjust = { 0 }; default_adjust.force_hw_default = false; - if (pipe_ctx->plane_state == NULL) - default_adjust.in_color_space = COLOR_SPACE_SRGB; - else - default_adjust.in_color_space = - pipe_ctx->plane_state->color_space; - if (pipe_ctx->stream == NULL) - default_adjust.out_color_space = COLOR_SPACE_SRGB; - else - default_adjust.out_color_space = - pipe_ctx->stream->output_color_space; + default_adjust.in_color_space = pipe_ctx->plane_state->color_space; + default_adjust.out_color_space = pipe_ctx->stream->output_color_space; default_adjust.csc_adjust_type = GRAPHICS_CSC_ADJUST_TYPE_SW; default_adjust.surface_pixel_format = pipe_ctx->plane_res.scl_data.format; @@ -2279,8 +2201,7 @@ static void set_plane_config( dce_enable_fe_clock(dc->hwseq, pipe_ctx->pipe_idx, true); set_default_colors(pipe_ctx); - if (pipe_ctx->stream->csc_color_matrix.enable_adjustment - == true) { + if (pipe_ctx->stream->csc_color_matrix.enable_adjustment == true) { tbl_entry.color_space = pipe_ctx->stream->output_color_space; @@ -2458,20 +2379,16 @@ static void dce110_enable_timing_synchronization( for (i = 1 /* skip the master */; i < group_size; i++) grouped_pipes[i]->stream_res.tg->funcs->enable_reset_trigger( - grouped_pipes[i]->stream_res.tg, gsl_params.gsl_group); - - + grouped_pipes[i]->stream_res.tg, + gsl_params.gsl_group); for (i = 1 /* skip the master */; i < group_size; i++) { DC_SYNC_INFO("GSL: waiting for reset to occur.\n"); wait_for_reset_trigger_to_occur(dc_ctx, grouped_pipes[i]->stream_res.tg); - /* Regardless of success of the wait above, remove the reset or - * the driver will start timing out on Display requests. */ - DC_SYNC_INFO("GSL: disabling trigger-reset.\n"); - grouped_pipes[i]->stream_res.tg->funcs->disable_reset_trigger(grouped_pipes[i]->stream_res.tg); + grouped_pipes[i]->stream_res.tg->funcs->disable_reset_trigger( + grouped_pipes[i]->stream_res.tg); } - /* GSL Vblank synchronization is a one time sync mechanism, assumption * is that the sync'ed displays will not drift out of sync over time*/ DC_SYNC_INFO("GSL: Restoring register states.\n"); @@ -2481,6 +2398,39 @@ static void dce110_enable_timing_synchronization( DC_SYNC_INFO("GSL: Set-up complete.\n"); } +static void dce110_enable_per_frame_crtc_position_reset( + struct dc *dc, + int group_size, + struct pipe_ctx *grouped_pipes[]) +{ + struct dc_context *dc_ctx = dc->ctx; + struct dcp_gsl_params gsl_params = { 0 }; + int i; + + gsl_params.gsl_group = 0; + gsl_params.gsl_master = grouped_pipes[0]->stream->triggered_crtc_reset.event_source->status.primary_otg_inst; + + for (i = 0; i < group_size; i++) + grouped_pipes[i]->stream_res.tg->funcs->setup_global_swap_lock( + grouped_pipes[i]->stream_res.tg, &gsl_params); + + DC_SYNC_INFO("GSL: enabling trigger-reset\n"); + + for (i = 1; i < group_size; i++) + grouped_pipes[i]->stream_res.tg->funcs->enable_crtc_reset( + grouped_pipes[i]->stream_res.tg, + gsl_params.gsl_master, + &grouped_pipes[i]->stream->triggered_crtc_reset); + + DC_SYNC_INFO("GSL: waiting for reset to occur.\n"); + for (i = 1; i < group_size; i++) + wait_for_reset_trigger_to_occur(dc_ctx, grouped_pipes[i]->stream_res.tg); + + for (i = 0; i < group_size; i++) + grouped_pipes[i]->stream_res.tg->funcs->tear_down_global_swap_lock(grouped_pipes[i]->stream_res.tg); + +} + static void init_hw(struct dc *dc) { int i; @@ -2513,6 +2463,10 @@ static void init_hw(struct dc *dc) * required signal (which may be different from the * default signal on connector). */ struct dc_link *link = dc->links[i]; + + if (link->link_enc->connector.id == CONNECTOR_ID_EDP) + dc->hwss.edp_power_control(link, true); + link->link_enc->funcs->hw_init(link->link_enc); } @@ -2567,6 +2521,10 @@ void dce110_fill_display_configs( ASSERT(pipe_ctx != NULL); + /* only notify active stream */ + if (stream->dpms_off) + continue; + num_cfgs++; cfg->signal = pipe_ctx->stream->signal; cfg->pipe_idx = pipe_ctx->pipe_idx; @@ -2722,8 +2680,7 @@ static void dce110_program_front_end_for_pipe( struct dc_plane_state *plane_state = pipe_ctx->plane_state; struct xfm_grph_csc_adjustment adjust; struct out_csc_color_matrix tbl_entry; - struct pipe_ctx *cur_pipe_ctx = - &dc->current_state->res_ctx.pipe_ctx[pipe_ctx->pipe_idx]; + struct pipe_ctx *cur_pipe_ctx = &dc->current_state->res_ctx.pipe_ctx[pipe_ctx->pipe_idx]; unsigned int i; memset(&tbl_entry, 0, sizeof(tbl_entry)); @@ -2816,10 +2773,8 @@ static void dce110_program_front_end_for_pipe( /* Moved programming gamma from dc to hwss */ if (cur_pipe_ctx->plane_state != pipe_ctx->plane_state) { - dc->hwss.set_input_transfer_func( - pipe_ctx, pipe_ctx->plane_state); - dc->hwss.set_output_transfer_func( - pipe_ctx, pipe_ctx->stream); + dc->hwss.set_input_transfer_func(pipe_ctx, pipe_ctx->plane_state); + dc->hwss.set_output_transfer_func(pipe_ctx, pipe_ctx->stream); } dm_logger_write(dc->ctx->logger, LOG_SURFACE, @@ -2889,13 +2844,12 @@ static void dce110_apply_ctx_for_surface( continue; /* Need to allocate mem before program front end for Fiji */ - if (pipe_ctx->plane_res.mi != NULL) - pipe_ctx->plane_res.mi->funcs->allocate_mem_input( - pipe_ctx->plane_res.mi, - pipe_ctx->stream->timing.h_total, - pipe_ctx->stream->timing.v_total, - pipe_ctx->stream->timing.pix_clk_khz, - context->stream_count); + pipe_ctx->plane_res.mi->funcs->allocate_mem_input( + pipe_ctx->plane_res.mi, + pipe_ctx->stream->timing.h_total, + pipe_ctx->stream->timing.v_total, + pipe_ctx->stream->timing.pix_clk_khz, + context->stream_count); dce110_program_front_end_for_pipe(dc, pipe_ctx); @@ -2916,8 +2870,10 @@ static void dce110_apply_ctx_for_surface( } } -static void dce110_power_down_fe(struct dc *dc, int fe_idx) +static void dce110_power_down_fe(struct dc *dc, struct pipe_ctx *pipe_ctx) { + int fe_idx = pipe_ctx->pipe_idx; + /* Do not power down fe when stream is active on dce*/ if (dc->current_state->res_ctx.pipe_ctx[fe_idx].stream) return; @@ -2977,13 +2933,14 @@ static const struct hw_sequencer_funcs dce110_funcs = { .power_down = dce110_power_down, .enable_accelerated_mode = dce110_enable_accelerated_mode, .enable_timing_synchronization = dce110_enable_timing_synchronization, + .enable_per_frame_crtc_position_reset = dce110_enable_per_frame_crtc_position_reset, .update_info_frame = dce110_update_info_frame, .enable_stream = dce110_enable_stream, .disable_stream = dce110_disable_stream, .unblank_stream = dce110_unblank_stream, .enable_display_pipe_clock_gating = enable_display_pipe_clock_gating, .enable_display_power_gating = dce110_enable_display_power_gating, - .power_down_front_end = dce110_power_down_fe, + .disable_plane = dce110_power_down_fe, .pipe_control_lock = dce_pipe_control_lock, .set_bandwidth = dce110_set_bandwidth, .set_drr = set_drr, @@ -2996,8 +2953,10 @@ static const struct hw_sequencer_funcs dce110_funcs = { .wait_for_mpcc_disconnect = dce110_wait_for_mpcc_disconnect, .ready_shared_resources = ready_shared_resources, .optimize_shared_resources = optimize_shared_resources, + .pplib_apply_display_requirements = pplib_apply_display_requirements, .edp_backlight_control = hwss_edp_backlight_control, .edp_power_control = hwss_edp_power_control, + .edp_wait_for_hpd_ready = hwss_edp_wait_for_hpd_ready, }; void dce110_hw_sequencer_construct(struct dc *dc) diff --git a/drivers/gpu/drm/amd/display/dc/dce110/dce110_hw_sequencer.h b/drivers/gpu/drm/amd/display/dc/dce110/dce110_hw_sequencer.h index 4d72bb99be93..fc637647f643 100644 --- a/drivers/gpu/drm/amd/display/dc/dce110/dce110_hw_sequencer.h +++ b/drivers/gpu/drm/amd/display/dc/dce110/dce110_hw_sequencer.h @@ -70,12 +70,16 @@ uint32_t dce110_get_min_vblank_time_us(const struct dc_state *context); void dp_receiver_power_ctrl(struct dc_link *link, bool on); void hwss_edp_power_control( - struct link_encoder *enc, - bool power_up); + struct dc_link *link, + bool power_up); void hwss_edp_backlight_control( struct dc_link *link, bool enable); +void hwss_edp_wait_for_hpd_ready( + struct dc_link *link, + bool power_up); + #endif /* __DC_HWSS_DCE110_H__ */ diff --git a/drivers/gpu/drm/amd/display/dc/dce110/dce110_mem_input_v.c b/drivers/gpu/drm/amd/display/dc/dce110/dce110_mem_input_v.c index a06c6024deb4..7bab8c6d2a73 100644 --- a/drivers/gpu/drm/amd/display/dc/dce110/dce110_mem_input_v.c +++ b/drivers/gpu/drm/amd/display/dc/dce110/dce110_mem_input_v.c @@ -237,26 +237,14 @@ static void program_size_and_rotation( if (rotation == ROTATION_ANGLE_90 || rotation == ROTATION_ANGLE_270) { - uint32_t swap; - swap = local_size.video.luma_size.x; - local_size.video.luma_size.x = - local_size.video.luma_size.y; - local_size.video.luma_size.y = swap; - - swap = local_size.video.luma_size.width; - local_size.video.luma_size.width = - local_size.video.luma_size.height; - local_size.video.luma_size.height = swap; - - swap = local_size.video.chroma_size.x; - local_size.video.chroma_size.x = - local_size.video.chroma_size.y; - local_size.video.chroma_size.y = swap; - - swap = local_size.video.chroma_size.width; - local_size.video.chroma_size.width = - local_size.video.chroma_size.height; - local_size.video.chroma_size.height = swap; + swap(local_size.video.luma_size.x, + local_size.video.luma_size.y); + swap(local_size.video.luma_size.width, + local_size.video.luma_size.height); + swap(local_size.video.chroma_size.x, + local_size.video.chroma_size.y); + swap(local_size.video.chroma_size.width, + local_size.video.chroma_size.height); } value = 0; diff --git a/drivers/gpu/drm/amd/display/dc/dce110/dce110_opp_regamma_v.c b/drivers/gpu/drm/amd/display/dc/dce110/dce110_opp_regamma_v.c index e98ed3058ea2..9b65b77e8823 100644 --- a/drivers/gpu/drm/amd/display/dc/dce110/dce110_opp_regamma_v.c +++ b/drivers/gpu/drm/amd/display/dc/dce110/dce110_opp_regamma_v.c @@ -175,7 +175,7 @@ static void regamma_config_regions_and_segments( value = 0; set_reg_field_value( value, - params->arr_points[2].custom_float_slope, + params->arr_points[1].custom_float_slope, GAMMA_CORR_CNTLA_END_CNTL2, GAMMA_CORR_CNTLA_EXP_REGION_END_BASE); diff --git a/drivers/gpu/drm/amd/display/dc/dce110/dce110_resource.c b/drivers/gpu/drm/amd/display/dc/dce110/dce110_resource.c index 42df17f9aa8d..7c4779578fb7 100644 --- a/drivers/gpu/drm/amd/display/dc/dce110/dce110_resource.c +++ b/drivers/gpu/drm/amd/display/dc/dce110/dce110_resource.c @@ -1156,6 +1156,7 @@ static bool construct( dc->caps.max_downscale_ratio = 150; dc->caps.i2c_speed_in_khz = 100; dc->caps.max_cursor_size = 128; + dc->caps.is_apu = true; /************************************************* * Create resources * diff --git a/drivers/gpu/drm/amd/display/dc/dce110/dce110_timing_generator.c b/drivers/gpu/drm/amd/display/dc/dce110/dce110_timing_generator.c index 4befce6cd87a..25ca72139e5f 100644 --- a/drivers/gpu/drm/amd/display/dc/dce110/dce110_timing_generator.c +++ b/drivers/gpu/drm/amd/display/dc/dce110/dce110_timing_generator.c @@ -1224,26 +1224,46 @@ void dce110_timing_generator_setup_global_swap_lock( /* This pipe will belong to GSL Group zero. */ set_reg_field_value(value, - 1, - DCP_GSL_CONTROL, - DCP_GSL0_EN); + 1, + DCP_GSL_CONTROL, + DCP_GSL0_EN); set_reg_field_value(value, - gsl_params->gsl_master == tg->inst, - DCP_GSL_CONTROL, - DCP_GSL_MASTER_EN); + gsl_params->gsl_master == tg->inst, + DCP_GSL_CONTROL, + DCP_GSL_MASTER_EN); set_reg_field_value(value, - HFLIP_READY_DELAY, - DCP_GSL_CONTROL, - DCP_GSL_HSYNC_FLIP_FORCE_DELAY); + HFLIP_READY_DELAY, + DCP_GSL_CONTROL, + DCP_GSL_HSYNC_FLIP_FORCE_DELAY); /* Keep signal low (pending high) during 6 lines. * Also defines minimum interval before re-checking signal. */ set_reg_field_value(value, - HFLIP_CHECK_DELAY, - DCP_GSL_CONTROL, - DCP_GSL_HSYNC_FLIP_CHECK_DELAY); + HFLIP_CHECK_DELAY, + DCP_GSL_CONTROL, + DCP_GSL_HSYNC_FLIP_CHECK_DELAY); + + dm_write_reg(tg->ctx, CRTC_REG(mmDCP_GSL_CONTROL), value); + value = 0; + + set_reg_field_value(value, + gsl_params->gsl_master, + DCIO_GSL0_CNTL, + DCIO_GSL0_VSYNC_SEL); + + set_reg_field_value(value, + 0, + DCIO_GSL0_CNTL, + DCIO_GSL0_TIMING_SYNC_SEL); + + set_reg_field_value(value, + 0, + DCIO_GSL0_CNTL, + DCIO_GSL0_GLOBAL_UNLOCK_SEL); + + dm_write_reg(tg->ctx, CRTC_REG(mmDCIO_GSL0_CNTL), value); { @@ -1253,38 +1273,38 @@ void dce110_timing_generator_setup_global_swap_lock( CRTC_REG(mmCRTC_V_TOTAL)); set_reg_field_value(value, - 0,/* DCP_GSL_PURPOSE_SURFACE_FLIP */ - DCP_GSL_CONTROL, - DCP_GSL_SYNC_SOURCE); + 0,/* DCP_GSL_PURPOSE_SURFACE_FLIP */ + DCP_GSL_CONTROL, + DCP_GSL_SYNC_SOURCE); /* Checkpoint relative to end of frame */ check_point = get_reg_field_value(value_crtc_vtotal, - CRTC_V_TOTAL, - CRTC_V_TOTAL); + CRTC_V_TOTAL, + CRTC_V_TOTAL); dm_write_reg(tg->ctx, CRTC_REG(mmCRTC_GSL_WINDOW), 0); } set_reg_field_value(value, - 1, - DCP_GSL_CONTROL, - DCP_GSL_DELAY_SURFACE_UPDATE_PENDING); + 1, + DCP_GSL_CONTROL, + DCP_GSL_DELAY_SURFACE_UPDATE_PENDING); dm_write_reg(tg->ctx, address, value); /********************************************************************/ address = CRTC_REG(mmCRTC_GSL_CONTROL); - value = 0; + value = dm_read_reg(tg->ctx, address); set_reg_field_value(value, - check_point - FLIP_READY_BACK_LOOKUP, - CRTC_GSL_CONTROL, - CRTC_GSL_CHECK_LINE_NUM); + check_point - FLIP_READY_BACK_LOOKUP, + CRTC_GSL_CONTROL, + CRTC_GSL_CHECK_LINE_NUM); set_reg_field_value(value, - VFLIP_READY_DELAY, - CRTC_GSL_CONTROL, - CRTC_GSL_FORCE_DELAY); + VFLIP_READY_DELAY, + CRTC_GSL_CONTROL, + CRTC_GSL_FORCE_DELAY); dm_write_reg(tg->ctx, address, value); } @@ -1555,6 +1575,138 @@ void dce110_timing_generator_enable_reset_trigger( dm_write_reg(tg->ctx, CRTC_REG(mmCRTC_FORCE_COUNT_NOW_CNTL), value); } +void dce110_timing_generator_enable_crtc_reset( + struct timing_generator *tg, + int source_tg_inst, + struct crtc_trigger_info *crtc_tp) +{ + uint32_t value = 0; + uint32_t rising_edge = 0; + uint32_t falling_edge = 0; + struct dce110_timing_generator *tg110 = DCE110TG_FROM_TG(tg); + + /* Setup trigger edge */ + switch (crtc_tp->event) { + case CRTC_EVENT_VSYNC_RISING: + rising_edge = 1; + break; + + case CRTC_EVENT_VSYNC_FALLING: + falling_edge = 1; + break; + } + + value = dm_read_reg(tg->ctx, CRTC_REG(mmCRTC_TRIGB_CNTL)); + + set_reg_field_value(value, + source_tg_inst, + CRTC_TRIGB_CNTL, + CRTC_TRIGB_SOURCE_SELECT); + + set_reg_field_value(value, + TRIGGER_POLARITY_SELECT_LOGIC_ZERO, + CRTC_TRIGB_CNTL, + CRTC_TRIGB_POLARITY_SELECT); + + set_reg_field_value(value, + rising_edge, + CRTC_TRIGB_CNTL, + CRTC_TRIGB_RISING_EDGE_DETECT_CNTL); + + set_reg_field_value(value, + falling_edge, + CRTC_TRIGB_CNTL, + CRTC_TRIGB_FALLING_EDGE_DETECT_CNTL); + + set_reg_field_value(value, + 1, /* clear trigger status */ + CRTC_TRIGB_CNTL, + CRTC_TRIGB_CLEAR); + + dm_write_reg(tg->ctx, CRTC_REG(mmCRTC_TRIGB_CNTL), value); + + /**************************************************************/ + + switch (crtc_tp->delay) { + case TRIGGER_DELAY_NEXT_LINE: + value = dm_read_reg(tg->ctx, CRTC_REG(mmCRTC_FORCE_COUNT_NOW_CNTL)); + + set_reg_field_value(value, + 0, /* force H count to H_TOTAL and V count to V_TOTAL */ + CRTC_FORCE_COUNT_NOW_CNTL, + CRTC_FORCE_COUNT_NOW_MODE); + + set_reg_field_value(value, + 0, /* TriggerB - we never use TriggerA */ + CRTC_FORCE_COUNT_NOW_CNTL, + CRTC_FORCE_COUNT_NOW_TRIG_SEL); + + set_reg_field_value(value, + 1, /* clear trigger status */ + CRTC_FORCE_COUNT_NOW_CNTL, + CRTC_FORCE_COUNT_NOW_CLEAR); + + dm_write_reg(tg->ctx, CRTC_REG(mmCRTC_FORCE_COUNT_NOW_CNTL), value); + + value = dm_read_reg(tg->ctx, CRTC_REG(mmCRTC_VERT_SYNC_CONTROL)); + + set_reg_field_value(value, + 1, + CRTC_VERT_SYNC_CONTROL, + CRTC_FORCE_VSYNC_NEXT_LINE_CLEAR); + + set_reg_field_value(value, + 2, + CRTC_VERT_SYNC_CONTROL, + CRTC_AUTO_FORCE_VSYNC_MODE); + + break; + + case TRIGGER_DELAY_NEXT_PIXEL: + value = dm_read_reg(tg->ctx, CRTC_REG(mmCRTC_VERT_SYNC_CONTROL)); + + set_reg_field_value(value, + 1, + CRTC_VERT_SYNC_CONTROL, + CRTC_FORCE_VSYNC_NEXT_LINE_CLEAR); + + set_reg_field_value(value, + 0, + CRTC_VERT_SYNC_CONTROL, + CRTC_AUTO_FORCE_VSYNC_MODE); + + dm_write_reg(tg->ctx, CRTC_REG(mmCRTC_VERT_SYNC_CONTROL), value); + + value = dm_read_reg(tg->ctx, CRTC_REG(mmCRTC_FORCE_COUNT_NOW_CNTL)); + + set_reg_field_value(value, + 2, /* force H count to H_TOTAL and V count to V_TOTAL */ + CRTC_FORCE_COUNT_NOW_CNTL, + CRTC_FORCE_COUNT_NOW_MODE); + + set_reg_field_value(value, + 1, /* TriggerB - we never use TriggerA */ + CRTC_FORCE_COUNT_NOW_CNTL, + CRTC_FORCE_COUNT_NOW_TRIG_SEL); + + set_reg_field_value(value, + 1, /* clear trigger status */ + CRTC_FORCE_COUNT_NOW_CNTL, + CRTC_FORCE_COUNT_NOW_CLEAR); + + dm_write_reg(tg->ctx, CRTC_REG(mmCRTC_FORCE_COUNT_NOW_CNTL), value); + break; + } + + value = dm_read_reg(tg->ctx, CRTC_REG(mmCRTC_MASTER_UPDATE_MODE)); + + set_reg_field_value(value, + 2, + CRTC_MASTER_UPDATE_MODE, + MASTER_UPDATE_MODE); + + dm_write_reg(tg->ctx, CRTC_REG(mmCRTC_MASTER_UPDATE_MODE), value); +} void dce110_timing_generator_disable_reset_trigger( struct timing_generator *tg) { @@ -1564,34 +1716,48 @@ void dce110_timing_generator_disable_reset_trigger( value = dm_read_reg(tg->ctx, CRTC_REG(mmCRTC_FORCE_COUNT_NOW_CNTL)); set_reg_field_value(value, - 0, /* force counter now mode is disabled */ - CRTC_FORCE_COUNT_NOW_CNTL, - CRTC_FORCE_COUNT_NOW_MODE); + 0, /* force counter now mode is disabled */ + CRTC_FORCE_COUNT_NOW_CNTL, + CRTC_FORCE_COUNT_NOW_MODE); set_reg_field_value(value, - 1, /* clear trigger status */ - CRTC_FORCE_COUNT_NOW_CNTL, - CRTC_FORCE_COUNT_NOW_CLEAR); + 1, /* clear trigger status */ + CRTC_FORCE_COUNT_NOW_CNTL, + CRTC_FORCE_COUNT_NOW_CLEAR); dm_write_reg(tg->ctx, CRTC_REG(mmCRTC_FORCE_COUNT_NOW_CNTL), value); + value = dm_read_reg(tg->ctx, CRTC_REG(mmCRTC_VERT_SYNC_CONTROL)); + + set_reg_field_value(value, + 1, + CRTC_VERT_SYNC_CONTROL, + CRTC_FORCE_VSYNC_NEXT_LINE_CLEAR); + + set_reg_field_value(value, + 0, + CRTC_VERT_SYNC_CONTROL, + CRTC_AUTO_FORCE_VSYNC_MODE); + + dm_write_reg(tg->ctx, CRTC_REG(mmCRTC_VERT_SYNC_CONTROL), value); + /********************************************************************/ value = dm_read_reg(tg->ctx, CRTC_REG(mmCRTC_TRIGB_CNTL)); set_reg_field_value(value, - TRIGGER_SOURCE_SELECT_LOGIC_ZERO, - CRTC_TRIGB_CNTL, - CRTC_TRIGB_SOURCE_SELECT); + TRIGGER_SOURCE_SELECT_LOGIC_ZERO, + CRTC_TRIGB_CNTL, + CRTC_TRIGB_SOURCE_SELECT); set_reg_field_value(value, - TRIGGER_POLARITY_SELECT_LOGIC_ZERO, - CRTC_TRIGB_CNTL, - CRTC_TRIGB_POLARITY_SELECT); + TRIGGER_POLARITY_SELECT_LOGIC_ZERO, + CRTC_TRIGB_CNTL, + CRTC_TRIGB_POLARITY_SELECT); set_reg_field_value(value, - 1, /* clear trigger status */ - CRTC_TRIGB_CNTL, - CRTC_TRIGB_CLEAR); + 1, /* clear trigger status */ + CRTC_TRIGB_CNTL, + CRTC_TRIGB_CLEAR); dm_write_reg(tg->ctx, CRTC_REG(mmCRTC_TRIGB_CNTL), value); } @@ -1611,10 +1777,16 @@ bool dce110_timing_generator_did_triggered_reset_occur( struct dce110_timing_generator *tg110 = DCE110TG_FROM_TG(tg); uint32_t value = dm_read_reg(tg->ctx, CRTC_REG(mmCRTC_FORCE_COUNT_NOW_CNTL)); - - return get_reg_field_value(value, - CRTC_FORCE_COUNT_NOW_CNTL, - CRTC_FORCE_COUNT_NOW_OCCURRED) != 0; + uint32_t value1 = dm_read_reg(tg->ctx, + CRTC_REG(mmCRTC_VERT_SYNC_CONTROL)); + bool force = get_reg_field_value(value, + CRTC_FORCE_COUNT_NOW_CNTL, + CRTC_FORCE_COUNT_NOW_OCCURRED) != 0; + bool vert_sync = get_reg_field_value(value1, + CRTC_VERT_SYNC_CONTROL, + CRTC_FORCE_VSYNC_NEXT_LINE_OCCURRED) != 0; + + return (force || vert_sync); } /** @@ -1928,6 +2100,7 @@ static const struct timing_generator_funcs dce110_tg_funcs = { .setup_global_swap_lock = dce110_timing_generator_setup_global_swap_lock, .enable_reset_trigger = dce110_timing_generator_enable_reset_trigger, + .enable_crtc_reset = dce110_timing_generator_enable_crtc_reset, .disable_reset_trigger = dce110_timing_generator_disable_reset_trigger, .tear_down_global_swap_lock = dce110_timing_generator_tear_down_global_swap_lock, diff --git a/drivers/gpu/drm/amd/display/dc/dce110/dce110_timing_generator.h b/drivers/gpu/drm/amd/display/dc/dce110/dce110_timing_generator.h index 82737dea6984..232747c7c60b 100644 --- a/drivers/gpu/drm/amd/display/dc/dce110/dce110_timing_generator.h +++ b/drivers/gpu/drm/amd/display/dc/dce110/dce110_timing_generator.h @@ -174,6 +174,12 @@ void dce110_timing_generator_setup_global_swap_lock( void dce110_timing_generator_tear_down_global_swap_lock( struct timing_generator *tg); +/* Reset crtc position on master VSync */ +void dce110_timing_generator_enable_crtc_reset( + struct timing_generator *tg, + int source, + struct crtc_trigger_info *crtc_tp); + /* Reset slave controllers on master VSync */ void dce110_timing_generator_enable_reset_trigger( struct timing_generator *tg, |