diff options
Diffstat (limited to 'drivers/gpu/drm/amd/display/dc/core')
-rw-r--r-- | drivers/gpu/drm/amd/display/dc/core/dc.c | 625 | ||||
-rw-r--r-- | drivers/gpu/drm/amd/display/dc/core/dc_debug.c | 4 | ||||
-rw-r--r-- | drivers/gpu/drm/amd/display/dc/core/dc_hw_sequencer.c | 145 | ||||
-rw-r--r-- | drivers/gpu/drm/amd/display/dc/core/dc_link.c | 183 | ||||
-rw-r--r-- | drivers/gpu/drm/amd/display/dc/core/dc_link_dp.c | 23 | ||||
-rw-r--r-- | drivers/gpu/drm/amd/display/dc/core/dc_link_hwss.c | 20 | ||||
-rw-r--r-- | drivers/gpu/drm/amd/display/dc/core/dc_resource.c | 151 | ||||
-rw-r--r-- | drivers/gpu/drm/amd/display/dc/core/dc_stream.c | 25 |
8 files changed, 527 insertions, 649 deletions
diff --git a/drivers/gpu/drm/amd/display/dc/core/dc.c b/drivers/gpu/drm/amd/display/dc/core/dc.c index 7240db2e6f09..35e84ed031de 100644 --- a/drivers/gpu/drm/amd/display/dc/core/dc.c +++ b/drivers/gpu/drm/amd/display/dc/core/dc.c @@ -54,6 +54,13 @@ /******************************************************************************* * Private functions ******************************************************************************/ + +static inline void elevate_update_type(enum surface_update_type *original, enum surface_update_type new) +{ + if (new > *original) + *original = new; +} + static void destroy_links(struct dc *dc) { uint32_t i; @@ -157,7 +164,7 @@ failed_alloc: return false; } -static bool stream_adjust_vmin_vmax(struct dc *dc, +bool dc_stream_adjust_vmin_vmax(struct dc *dc, struct dc_stream_state **streams, int num_streams, int vmin, int vmax) { @@ -182,7 +189,7 @@ static bool stream_adjust_vmin_vmax(struct dc *dc, return ret; } -static bool stream_get_crtc_position(struct dc *dc, +bool dc_stream_get_crtc_position(struct dc *dc, struct dc_stream_state **streams, int num_streams, unsigned int *v_pos, unsigned int *nom_v_pos) { @@ -207,45 +214,7 @@ static bool stream_get_crtc_position(struct dc *dc, return ret; } -static bool set_gamut_remap(struct dc *dc, const struct dc_stream_state *stream) -{ - int i = 0; - bool ret = false; - struct pipe_ctx *pipes; - - for (i = 0; i < MAX_PIPES; i++) { - if (dc->current_state->res_ctx.pipe_ctx[i].stream == stream) { - pipes = &dc->current_state->res_ctx.pipe_ctx[i]; - dc->hwss.program_gamut_remap(pipes); - ret = true; - } - } - - return ret; -} - -static bool program_csc_matrix(struct dc *dc, struct dc_stream_state *stream) -{ - int i = 0; - bool ret = false; - struct pipe_ctx *pipes; - - for (i = 0; i < MAX_PIPES; i++) { - if (dc->current_state->res_ctx.pipe_ctx[i].stream - == stream) { - - pipes = &dc->current_state->res_ctx.pipe_ctx[i]; - dc->hwss.program_csc_matrix(pipes, - stream->output_color_space, - stream->csc_color_matrix.matrix); - ret = true; - } - } - - return ret; -} - -static void set_static_screen_events(struct dc *dc, +void dc_stream_set_static_screen_events(struct dc *dc, struct dc_stream_state **streams, int num_streams, const struct dc_static_screen_events *events) @@ -270,177 +239,6 @@ static void set_static_screen_events(struct dc *dc, dc->hwss.set_static_screen_control(pipes_affected, num_pipes_affected, events); } -static void set_drive_settings(struct dc *dc, - struct link_training_settings *lt_settings, - const struct dc_link *link) -{ - - int i; - - for (i = 0; i < dc->link_count; i++) { - if (dc->links[i] == link) - break; - } - - if (i >= dc->link_count) - ASSERT_CRITICAL(false); - - dc_link_dp_set_drive_settings(dc->links[i], lt_settings); -} - -static void perform_link_training(struct dc *dc, - struct dc_link_settings *link_setting, - bool skip_video_pattern) -{ - int i; - - for (i = 0; i < dc->link_count; i++) - dc_link_dp_perform_link_training( - dc->links[i], - link_setting, - skip_video_pattern); -} - -static void set_preferred_link_settings(struct dc *dc, - struct dc_link_settings *link_setting, - struct dc_link *link) -{ - link->preferred_link_setting = *link_setting; - dp_retrain_link_dp_test(link, link_setting, false); -} - -static void enable_hpd(const struct dc_link *link) -{ - dc_link_dp_enable_hpd(link); -} - -static void disable_hpd(const struct dc_link *link) -{ - dc_link_dp_disable_hpd(link); -} - - -static void set_test_pattern( - struct dc_link *link, - enum dp_test_pattern test_pattern, - const struct link_training_settings *p_link_settings, - const unsigned char *p_custom_pattern, - unsigned int cust_pattern_size) -{ - if (link != NULL) - dc_link_dp_set_test_pattern( - link, - test_pattern, - p_link_settings, - p_custom_pattern, - cust_pattern_size); -} - -static void set_dither_option(struct dc_stream_state *stream, - enum dc_dither_option option) -{ - struct bit_depth_reduction_params params; - struct dc_link *link = stream->status.link; - struct pipe_ctx *pipes = NULL; - int i; - - for (i = 0; i < MAX_PIPES; i++) { - if (link->dc->current_state->res_ctx.pipe_ctx[i].stream == - stream) { - pipes = &link->dc->current_state->res_ctx.pipe_ctx[i]; - break; - } - } - - memset(¶ms, 0, sizeof(params)); - if (!pipes) - return; - if (option > DITHER_OPTION_MAX) - return; - - stream->dither_option = option; - - resource_build_bit_depth_reduction_params(stream, - ¶ms); - stream->bit_depth_params = params; - pipes->stream_res.opp->funcs-> - opp_program_bit_depth_reduction(pipes->stream_res.opp, ¶ms); -} - -void set_dpms( - struct dc *dc, - struct dc_stream_state *stream, - bool dpms_off) -{ - struct pipe_ctx *pipe_ctx = NULL; - int i; - - for (i = 0; i < MAX_PIPES; i++) { - if (dc->current_state->res_ctx.pipe_ctx[i].stream == stream) { - pipe_ctx = &dc->current_state->res_ctx.pipe_ctx[i]; - break; - } - } - - if (!pipe_ctx) { - ASSERT(0); - return; - } - - if (stream->dpms_off != dpms_off) { - stream->dpms_off = dpms_off; - if (dpms_off) - core_link_disable_stream(pipe_ctx, - KEEP_ACQUIRED_RESOURCE); - else - core_link_enable_stream(dc->current_state, pipe_ctx); - } -} - -static void allocate_dc_stream_funcs(struct dc *dc) -{ - if (dc->hwss.set_drr != NULL) { - dc->stream_funcs.adjust_vmin_vmax = - stream_adjust_vmin_vmax; - } - - dc->stream_funcs.set_static_screen_events = - set_static_screen_events; - - dc->stream_funcs.get_crtc_position = - stream_get_crtc_position; - - dc->stream_funcs.set_gamut_remap = - set_gamut_remap; - - dc->stream_funcs.program_csc_matrix = - program_csc_matrix; - - dc->stream_funcs.set_dither_option = - set_dither_option; - - dc->stream_funcs.set_dpms = - set_dpms; - - dc->link_funcs.set_drive_settings = - set_drive_settings; - - dc->link_funcs.perform_link_training = - perform_link_training; - - dc->link_funcs.set_preferred_link_settings = - set_preferred_link_settings; - - dc->link_funcs.enable_hpd = - enable_hpd; - - dc->link_funcs.disable_hpd = - disable_hpd; - - dc->link_funcs.set_test_pattern = - set_test_pattern; -} - static void destruct(struct dc *dc) { dc_release_state(dc->current_state); @@ -485,19 +283,17 @@ static bool construct(struct dc *dc, const struct dc_init_data *init_params) { struct dal_logger *logger; - struct dc_context *dc_ctx = kzalloc(sizeof(*dc_ctx), GFP_KERNEL); - struct bw_calcs_dceip *dc_dceip = kzalloc(sizeof(*dc_dceip), - GFP_KERNEL); - struct bw_calcs_vbios *dc_vbios = kzalloc(sizeof(*dc_vbios), - GFP_KERNEL); + struct dc_context *dc_ctx; + struct bw_calcs_dceip *dc_dceip; + struct bw_calcs_vbios *dc_vbios; #ifdef CONFIG_DRM_AMD_DC_DCN1_0 - struct dcn_soc_bounding_box *dcn_soc = kzalloc(sizeof(*dcn_soc), - GFP_KERNEL); - struct dcn_ip_params *dcn_ip = kzalloc(sizeof(*dcn_ip), GFP_KERNEL); + struct dcn_soc_bounding_box *dcn_soc; + struct dcn_ip_params *dcn_ip; #endif enum dce_version dc_version = DCE_VERSION_UNKNOWN; + dc_dceip = kzalloc(sizeof(*dc_dceip), GFP_KERNEL); if (!dc_dceip) { dm_error("%s: failed to create dceip\n", __func__); goto fail; @@ -505,6 +301,7 @@ static bool construct(struct dc *dc, dc->bw_dceip = dc_dceip; + dc_vbios = kzalloc(sizeof(*dc_vbios), GFP_KERNEL); if (!dc_vbios) { dm_error("%s: failed to create vbios\n", __func__); goto fail; @@ -512,6 +309,7 @@ static bool construct(struct dc *dc, dc->bw_vbios = dc_vbios; #ifdef CONFIG_DRM_AMD_DC_DCN1_0 + dcn_soc = kzalloc(sizeof(*dcn_soc), GFP_KERNEL); if (!dcn_soc) { dm_error("%s: failed to create dcn_soc\n", __func__); goto fail; @@ -519,6 +317,7 @@ static bool construct(struct dc *dc, dc->dcn_soc = dcn_soc; + dcn_ip = kzalloc(sizeof(*dcn_ip), GFP_KERNEL); if (!dcn_ip) { dm_error("%s: failed to create dcn_ip\n", __func__); goto fail; @@ -527,11 +326,18 @@ static bool construct(struct dc *dc, dc->dcn_ip = dcn_ip; #endif + dc_ctx = kzalloc(sizeof(*dc_ctx), GFP_KERNEL); if (!dc_ctx) { dm_error("%s: failed to create ctx\n", __func__); goto fail; } + dc_ctx->cgs_device = init_params->cgs_device; + dc_ctx->driver_context = init_params->driver; + dc_ctx->dc = dc; + dc_ctx->asic_id = init_params->asic_id; + dc->ctx = dc_ctx; + dc->current_state = dc_create_state(); if (!dc->current_state) { @@ -539,11 +345,6 @@ static bool construct(struct dc *dc, goto fail; } - dc_ctx->cgs_device = init_params->cgs_device; - dc_ctx->driver_context = init_params->driver; - dc_ctx->dc = dc; - dc_ctx->asic_id = init_params->asic_id; - /* Create logger */ logger = dal_logger_create(dc_ctx, init_params->log_mask); @@ -553,11 +354,11 @@ static bool construct(struct dc *dc, goto fail; } dc_ctx->logger = logger; - dc->ctx = dc_ctx; - dc->ctx->dce_environment = init_params->dce_environment; + dc_ctx->dce_environment = init_params->dce_environment; dc_version = resource_parse_asic_id(init_params->asic_id); - dc->ctx->dce_version = dc_version; + dc_ctx->dce_version = dc_version; + #if defined(CONFIG_DRM_AMD_DC_FBC) dc->ctx->fbc_gpu_addr = init_params->fbc_gpu_addr; #endif @@ -616,8 +417,6 @@ static bool construct(struct dc *dc, if (!create_links(dc, init_params->num_virtual_links)) goto fail; - allocate_dc_stream_funcs(dc); - return true; fail: @@ -686,6 +485,7 @@ struct dc *dc_create(const struct dc_init_data *init_params) dc->caps.max_links = dc->link_count; dc->caps.max_audios = dc->res_pool->audio_count; + dc->caps.linear_pitch_alignment = 64; dc->config = init_params->flags; @@ -712,6 +512,28 @@ void dc_destroy(struct dc **dc) *dc = NULL; } +static void enable_timing_multisync( + struct dc *dc, + struct dc_state *ctx) +{ + int i = 0, multisync_count = 0; + int pipe_count = dc->res_pool->pipe_count; + struct pipe_ctx *multisync_pipes[MAX_PIPES] = { NULL }; + + for (i = 0; i < pipe_count; i++) { + if (!ctx->res_ctx.pipe_ctx[i].stream || + !ctx->res_ctx.pipe_ctx[i].stream->triggered_crtc_reset.enabled) + continue; + multisync_pipes[multisync_count] = &ctx->res_ctx.pipe_ctx[i]; + multisync_count++; + } + + if (multisync_count > 1) { + dc->hwss.enable_per_frame_crtc_position_reset( + dc, multisync_count, multisync_pipes); + } +} + static void program_timing_sync( struct dc *dc, struct dc_state *ctx) @@ -758,7 +580,7 @@ static void program_timing_sync( for (j = 0; j < group_size; j++) { struct pipe_ctx *temp; - if (!pipe_set[j]->stream_res.tg->funcs->is_blanked(pipe_set[j]->stream_res.tg)) { + if (pipe_set[j]->stream_res.tg->funcs->is_blanked && !pipe_set[j]->stream_res.tg->funcs->is_blanked(pipe_set[j]->stream_res.tg)) { if (j == 0) break; @@ -771,7 +593,7 @@ static void program_timing_sync( /* remove any other unblanked pipes as they have already been synced */ for (j = j + 1; j < group_size; j++) { - if (!pipe_set[j]->stream_res.tg->funcs->is_blanked(pipe_set[j]->stream_res.tg)) { + if (pipe_set[j]->stream_res.tg->funcs->is_blanked && !pipe_set[j]->stream_res.tg->funcs->is_blanked(pipe_set[j]->stream_res.tg)) { group_size--; pipe_set[j] = pipe_set[group_size]; j--; @@ -838,7 +660,7 @@ static enum dc_status dc_commit_state_no_check(struct dc *dc, struct dc_state *c struct dc_bios *dcb = dc->ctx->dc_bios; enum dc_status result = DC_ERROR_UNEXPECTED; struct pipe_ctx *pipe; - int i, j, k, l; + int i, k, l; struct dc_stream_state *dc_streams[MAX_STREAMS] = {0}; disable_dangling_plane(dc, context); @@ -849,9 +671,44 @@ static enum dc_status dc_commit_state_no_check(struct dc *dc, struct dc_state *c if (!dcb->funcs->is_accelerated_mode(dcb)) dc->hwss.enable_accelerated_mode(dc); + /* re-program planes for existing stream, in case we need to + * free up plane resource for later use + */ + for (i = 0; i < context->stream_count; i++) { + if (context->streams[i]->mode_changed) + continue; + + dc->hwss.apply_ctx_for_surface( + dc, context->streams[i], + context->stream_status[i].plane_count, + context); /* use new pipe config in new context */ + } + + /* Program hardware */ + dc->hwss.ready_shared_resources(dc, context); + + for (i = 0; i < dc->res_pool->pipe_count; i++) { + pipe = &context->res_ctx.pipe_ctx[i]; + dc->hwss.wait_for_mpcc_disconnect(dc, dc->res_pool, pipe); + } + + result = dc->hwss.apply_ctx_to_hw(dc, context); + + if (result != DC_OK) + return result; + + if (context->stream_count > 1) { + enable_timing_multisync(dc, context); + program_timing_sync(dc, context); + } + + /* Program all planes within new context*/ for (i = 0; i < context->stream_count; i++) { const struct dc_sink *sink = context->streams[i]->sink; + if (!context->streams[i]->mode_changed) + continue; + dc->hwss.apply_ctx_for_surface( dc, context->streams[i], context->stream_status[i].plane_count, @@ -880,27 +737,8 @@ static enum dc_status dc_commit_state_no_check(struct dc *dc, struct dc_state *c context->streams[i]->timing.pix_clk_khz); } - dc->hwss.ready_shared_resources(dc, context); - - for (i = 0; i < dc->res_pool->pipe_count; i++) { - pipe = &context->res_ctx.pipe_ctx[i]; - dc->hwss.wait_for_mpcc_disconnect(dc, dc->res_pool, pipe); - } - result = dc->hwss.apply_ctx_to_hw(dc, context); - - program_timing_sync(dc, context); - dc_enable_stereo(dc, context, dc_streams, context->stream_count); - for (i = 0; i < context->stream_count; i++) { - for (j = 0; j < MAX_PIPES; j++) { - pipe = &context->res_ctx.pipe_ctx[j]; - - if (!pipe->top_pipe && pipe->stream == context->streams[i]) - dc->hwss.pipe_control_lock(dc, pipe, false); - } - } - dc_release_state(dc->current_state); dc->current_state = context; @@ -936,7 +774,6 @@ bool dc_commit_state(struct dc *dc, struct dc_state *context) return (result == DC_OK); } - bool dc_post_update_surfaces_to_stream(struct dc *dc) { int i; @@ -945,9 +782,13 @@ bool dc_post_update_surfaces_to_stream(struct dc *dc) post_surface_trace(dc); for (i = 0; i < dc->res_pool->pipe_count; i++) - if (context->res_ctx.pipe_ctx[i].stream == NULL - || context->res_ctx.pipe_ctx[i].plane_state == NULL) - dc->hwss.power_down_front_end(dc, i); + if (context->res_ctx.pipe_ctx[i].stream == NULL || + context->res_ctx.pipe_ctx[i].plane_state == NULL) { + context->res_ctx.pipe_ctx[i].pipe_idx = i; + dc->hwss.disable_plane(dc, &context->res_ctx.pipe_ctx[i]); + } + + dc->optimized_required = false; /* 3rd param should be true, temp w/a for RV*/ #if defined(CONFIG_DRM_AMD_DC_DCN1_0) @@ -1014,6 +855,7 @@ bool dc_commit_planes_to_stream( flip_addr[i].address = plane_states[i]->address; flip_addr[i].flip_immediate = plane_states[i]->flip_immediate; plane_info[i].color_space = plane_states[i]->color_space; + plane_info[i].input_tf = plane_states[i]->input_tf; plane_info[i].format = plane_states[i]->format; plane_info[i].plane_size = plane_states[i]->plane_size; plane_info[i].rotation = plane_states[i]->rotation; @@ -1118,79 +960,96 @@ static unsigned int pixel_format_to_bpp(enum surface_pixel_format format) } } -static enum surface_update_type get_plane_info_update_type( - const struct dc_surface_update *u, - int surface_index) +static enum surface_update_type get_plane_info_update_type(const struct dc_surface_update *u) { - struct dc_plane_info temp_plane_info; - memset(&temp_plane_info, 0, sizeof(temp_plane_info)); + union surface_update_flags *update_flags = &u->surface->update_flags; if (!u->plane_info) return UPDATE_TYPE_FAST; - temp_plane_info = *u->plane_info; + if (u->plane_info->color_space != u->surface->color_space) + update_flags->bits.color_space_change = 1; - /* Copy all parameters that will cause a full update - * from current surface, the rest of the parameters - * from provided plane configuration. - * Perform memory compare and special validation - * for those that can cause fast/medium updates - */ + if (u->plane_info->input_tf != u->surface->input_tf) + update_flags->bits.input_tf_change = 1; - /* Full update parameters */ - temp_plane_info.color_space = u->surface->color_space; - temp_plane_info.dcc = u->surface->dcc; - temp_plane_info.horizontal_mirror = u->surface->horizontal_mirror; - temp_plane_info.plane_size = u->surface->plane_size; - temp_plane_info.rotation = u->surface->rotation; - temp_plane_info.stereo_format = u->surface->stereo_format; - - if (surface_index == 0) - temp_plane_info.visible = u->plane_info->visible; - else - temp_plane_info.visible = u->surface->visible; - - if (memcmp(u->plane_info, &temp_plane_info, - sizeof(struct dc_plane_info)) != 0) - return UPDATE_TYPE_FULL; + if (u->plane_info->horizontal_mirror != u->surface->horizontal_mirror) + update_flags->bits.horizontal_mirror_change = 1; + + if (u->plane_info->rotation != u->surface->rotation) + update_flags->bits.rotation_change = 1; + + if (u->plane_info->stereo_format != u->surface->stereo_format) + update_flags->bits.stereo_format_change = 1; + + if (u->plane_info->per_pixel_alpha != u->surface->per_pixel_alpha) + update_flags->bits.per_pixel_alpha_change = 1; + + if (u->plane_info->dcc.enable != u->surface->dcc.enable + || u->plane_info->dcc.grph.independent_64b_blks != u->surface->dcc.grph.independent_64b_blks + || u->plane_info->dcc.grph.meta_pitch != u->surface->dcc.grph.meta_pitch) + update_flags->bits.dcc_change = 1; if (pixel_format_to_bpp(u->plane_info->format) != - pixel_format_to_bpp(u->surface->format)) { + pixel_format_to_bpp(u->surface->format)) /* different bytes per element will require full bandwidth * and DML calculation */ - return UPDATE_TYPE_FULL; - } + update_flags->bits.bpp_change = 1; if (memcmp(&u->plane_info->tiling_info, &u->surface->tiling_info, sizeof(union dc_tiling_info)) != 0) { + update_flags->bits.swizzle_change = 1; /* todo: below are HW dependent, we should add a hook to * DCE/N resource and validated there. */ - if (u->plane_info->tiling_info.gfx9.swizzle != DC_SW_LINEAR) { + if (u->plane_info->tiling_info.gfx9.swizzle != DC_SW_LINEAR) /* swizzled mode requires RQ to be setup properly, * thus need to run DML to calculate RQ settings */ - return UPDATE_TYPE_FULL; - } + update_flags->bits.bandwidth_change = 1; } + if (update_flags->bits.rotation_change + || update_flags->bits.stereo_format_change + || update_flags->bits.bpp_change + || update_flags->bits.bandwidth_change) + return UPDATE_TYPE_FULL; + return UPDATE_TYPE_MED; } -static enum surface_update_type get_scaling_info_update_type( +static enum surface_update_type get_scaling_info_update_type( const struct dc_surface_update *u) { + union surface_update_flags *update_flags = &u->surface->update_flags; + if (!u->scaling_info) return UPDATE_TYPE_FAST; - if (u->scaling_info->src_rect.width != u->surface->src_rect.width - || u->scaling_info->src_rect.height != u->surface->src_rect.height - || u->scaling_info->clip_rect.width != u->surface->clip_rect.width + if (u->scaling_info->clip_rect.width != u->surface->clip_rect.width || u->scaling_info->clip_rect.height != u->surface->clip_rect.height || u->scaling_info->dst_rect.width != u->surface->dst_rect.width - || u->scaling_info->dst_rect.height != u->surface->dst_rect.height) - return UPDATE_TYPE_FULL; + || u->scaling_info->dst_rect.height != u->surface->dst_rect.height) { + update_flags->bits.scaling_change = 1; + + if ((u->scaling_info->dst_rect.width < u->surface->dst_rect.width + || u->scaling_info->dst_rect.height < u->surface->dst_rect.height) + && (u->scaling_info->dst_rect.width < u->surface->src_rect.width + || u->scaling_info->dst_rect.height < u->surface->src_rect.height)) + /* Making dst rect smaller requires a bandwidth change */ + update_flags->bits.bandwidth_change = 1; + } + + if (u->scaling_info->src_rect.width != u->surface->src_rect.width + || u->scaling_info->src_rect.height != u->surface->src_rect.height) { + + update_flags->bits.scaling_change = 1; + if (u->scaling_info->src_rect.width > u->surface->src_rect.width + && u->scaling_info->src_rect.height > u->surface->src_rect.height) + /* Making src rect bigger requires a bandwidth change */ + update_flags->bits.clock_change = 1; + } if (u->scaling_info->src_rect.x != u->surface->src_rect.x || u->scaling_info->src_rect.y != u->surface->src_rect.y @@ -1198,41 +1057,56 @@ static enum surface_update_type get_scaling_info_update_type( || u->scaling_info->clip_rect.y != u->surface->clip_rect.y || u->scaling_info->dst_rect.x != u->surface->dst_rect.x || u->scaling_info->dst_rect.y != u->surface->dst_rect.y) + update_flags->bits.position_change = 1; + + if (update_flags->bits.clock_change + || update_flags->bits.bandwidth_change) + return UPDATE_TYPE_FULL; + + if (update_flags->bits.scaling_change + || update_flags->bits.position_change) return UPDATE_TYPE_MED; return UPDATE_TYPE_FAST; } -static enum surface_update_type det_surface_update( - const struct dc *dc, - const struct dc_surface_update *u, - int surface_index) +static enum surface_update_type det_surface_update(const struct dc *dc, + const struct dc_surface_update *u) { const struct dc_state *context = dc->current_state; - enum surface_update_type type = UPDATE_TYPE_FAST; + enum surface_update_type type; enum surface_update_type overall_type = UPDATE_TYPE_FAST; + union surface_update_flags *update_flags = &u->surface->update_flags; + + update_flags->raw = 0; // Reset all flags - if (!is_surface_in_context(context, u->surface)) + if (!is_surface_in_context(context, u->surface)) { + update_flags->bits.new_plane = 1; return UPDATE_TYPE_FULL; + } - type = get_plane_info_update_type(u, surface_index); - if (overall_type < type) - overall_type = type; + type = get_plane_info_update_type(u); + elevate_update_type(&overall_type, type); type = get_scaling_info_update_type(u); - if (overall_type < type) - overall_type = type; + elevate_update_type(&overall_type, type); + + if (u->in_transfer_func) + update_flags->bits.in_transfer_func = 1; - if (u->in_transfer_func || - u->hdr_static_metadata) { - if (overall_type < UPDATE_TYPE_MED) - overall_type = UPDATE_TYPE_MED; + if (u->input_csc_color_matrix) + update_flags->bits.input_csc_change = 1; + + if (update_flags->bits.in_transfer_func + || update_flags->bits.input_csc_change) { + type = UPDATE_TYPE_MED; + elevate_update_type(&overall_type, type); } return overall_type; } -enum surface_update_type dc_check_update_surfaces_for_stream( +static enum surface_update_type check_update_surfaces_for_stream( struct dc *dc, struct dc_surface_update *updates, int surface_count, @@ -1250,18 +1124,38 @@ enum surface_update_type dc_check_update_surfaces_for_stream( for (i = 0 ; i < surface_count; i++) { enum surface_update_type type = - det_surface_update(dc, &updates[i], i); + det_surface_update(dc, &updates[i]); if (type == UPDATE_TYPE_FULL) return type; - if (overall_type < type) - overall_type = type; + elevate_update_type(&overall_type, type); } return overall_type; } +enum surface_update_type dc_check_update_surfaces_for_stream( + struct dc *dc, + struct dc_surface_update *updates, + int surface_count, + struct dc_stream_update *stream_update, + const struct dc_stream_status *stream_status) +{ + int i; + enum surface_update_type type; + + for (i = 0; i < surface_count; i++) + updates[i].surface->update_flags.raw = 0; + + type = check_update_surfaces_for_stream(dc, updates, surface_count, stream_update, stream_status); + if (type == UPDATE_TYPE_FULL) + for (i = 0; i < surface_count; i++) + updates[i].surface->update_flags.bits.full_update = 1; + + return type; +} + static struct dc_stream_status *stream_get_status( struct dc_state *ctx, struct dc_stream_state *stream) @@ -1295,14 +1189,6 @@ static void commit_planes_for_stream(struct dc *dc, context_clock_trace(dc, context); } - if (update_type > UPDATE_TYPE_FAST) { - for (j = 0; j < dc->res_pool->pipe_count; j++) { - struct pipe_ctx *pipe_ctx = &context->res_ctx.pipe_ctx[j]; - - dc->hwss.wait_for_mpcc_disconnect(dc, dc->res_pool, pipe_ctx); - } - } - if (surface_count == 0) { /* * In case of turning off screen, no need to program front end a second time. @@ -1312,103 +1198,58 @@ static void commit_planes_for_stream(struct dc *dc, return; } - /* Lock pipes for provided surfaces, or all active if full update*/ - for (i = 0; i < surface_count; i++) { - struct dc_plane_state *plane_state = srf_updates[i].surface; - - for (j = 0; j < dc->res_pool->pipe_count; j++) { - struct pipe_ctx *pipe_ctx = &context->res_ctx.pipe_ctx[j]; - - if (update_type != UPDATE_TYPE_FULL && pipe_ctx->plane_state != plane_state) - continue; - if (!pipe_ctx->plane_state || pipe_ctx->top_pipe) - continue; - - dc->hwss.pipe_control_lock( - dc, - pipe_ctx, - true); - } - if (update_type == UPDATE_TYPE_FULL) - break; - } - /* Full fe update*/ for (j = 0; j < dc->res_pool->pipe_count; j++) { struct pipe_ctx *pipe_ctx = &context->res_ctx.pipe_ctx[j]; - if (update_type != UPDATE_TYPE_FULL || !pipe_ctx->plane_state) + if (update_type == UPDATE_TYPE_FAST || !pipe_ctx->plane_state) continue; - if (!pipe_ctx->top_pipe && pipe_ctx->stream) { - struct dc_stream_status *stream_status = stream_get_status(context, pipe_ctx->stream); + if (!pipe_ctx->top_pipe && + pipe_ctx->stream && + pipe_ctx->stream == stream) { + struct dc_stream_status *stream_status = + stream_get_status(context, pipe_ctx->stream); dc->hwss.apply_ctx_for_surface( dc, pipe_ctx->stream, stream_status->plane_count, context); } } - if (update_type > UPDATE_TYPE_FAST) + if (update_type == UPDATE_TYPE_FULL) context_timing_trace(dc, &context->res_ctx); /* Perform requested Updates */ for (i = 0; i < surface_count; i++) { struct dc_plane_state *plane_state = srf_updates[i].surface; - if (update_type == UPDATE_TYPE_MED) - dc->hwss.apply_ctx_for_surface( - dc, stream, surface_count, context); - for (j = 0; j < dc->res_pool->pipe_count; j++) { struct pipe_ctx *pipe_ctx = &context->res_ctx.pipe_ctx[j]; - if (pipe_ctx->plane_state != plane_state) + if (pipe_ctx->stream != stream) continue; - if (srf_updates[i].flip_addr) - dc->hwss.update_plane_addr(dc, pipe_ctx); - - if (update_type == UPDATE_TYPE_FAST) + if (pipe_ctx->plane_state != plane_state) continue; - /* work around to program degamma regs for split pipe after set mode. */ - if (srf_updates[i].in_transfer_func || (pipe_ctx->top_pipe && - pipe_ctx->top_pipe->plane_state == pipe_ctx->plane_state)) - dc->hwss.set_input_transfer_func( - pipe_ctx, pipe_ctx->plane_state); - - if (stream_update != NULL && - stream_update->out_transfer_func != NULL) { - dc->hwss.set_output_transfer_func( - pipe_ctx, pipe_ctx->stream); - } - - if (srf_updates[i].hdr_static_metadata) { - resource_build_info_frame(pipe_ctx); - dc->hwss.update_info_frame(pipe_ctx); - } + if (update_type == UPDATE_TYPE_FAST && srf_updates[i].flip_addr) + dc->hwss.update_plane_addr(dc, pipe_ctx); } } - /* Unlock pipes */ - for (i = dc->res_pool->pipe_count - 1; i >= 0; i--) { - struct pipe_ctx *pipe_ctx = &context->res_ctx.pipe_ctx[i]; + if (stream && stream_update && update_type > UPDATE_TYPE_FAST) + for (j = 0; j < dc->res_pool->pipe_count; j++) { + struct pipe_ctx *pipe_ctx = + &context->res_ctx.pipe_ctx[j]; - for (j = 0; j < surface_count; j++) { - if (update_type != UPDATE_TYPE_FULL && - srf_updates[j].surface != pipe_ctx->plane_state) - continue; - if (!pipe_ctx->plane_state || pipe_ctx->top_pipe) + if (pipe_ctx->stream != stream) continue; - dc->hwss.pipe_control_lock( - dc, - pipe_ctx, - false); - - break; + if (stream_update->hdr_static_metadata) { + resource_build_info_frame(pipe_ctx); + dc->hwss.update_info_frame(pipe_ctx); + } } - } } void dc_commit_updates_for_stream(struct dc *dc, @@ -1480,10 +1321,7 @@ void dc_commit_updates_for_stream(struct dc *dc, stream_update, update_type, context); - - if (update_type >= UPDATE_TYPE_FULL) - dc_post_update_surfaces_to_stream(dc); - + /*update current_State*/ if (dc->current_state != context) { struct dc_state *old = dc->current_state; @@ -1492,6 +1330,9 @@ void dc_commit_updates_for_stream(struct dc *dc, dc_release_state(old); } + /*let's use current_state to update watermark etc*/ + if (update_type >= UPDATE_TYPE_FULL) + dc_post_update_surfaces_to_stream(dc); return; diff --git a/drivers/gpu/drm/amd/display/dc/core/dc_debug.c b/drivers/gpu/drm/amd/display/dc/core/dc_debug.c index 43c7a7fddb83..1babac07bcc9 100644 --- a/drivers/gpu/drm/amd/display/dc/core/dc_debug.c +++ b/drivers/gpu/drm/amd/display/dc/core/dc_debug.c @@ -159,6 +159,7 @@ void pre_surface_trace( "plane_state->tiling_info.gfx8.pipe_config = %d;\n" "plane_state->tiling_info.gfx8.array_mode = %d;\n" "plane_state->color_space = %d;\n" + "plane_state->input_tf = %d;\n" "plane_state->dcc.enable = %d;\n" "plane_state->format = %d;\n" "plane_state->rotation = %d;\n" @@ -166,6 +167,7 @@ void pre_surface_trace( plane_state->tiling_info.gfx8.pipe_config, plane_state->tiling_info.gfx8.array_mode, plane_state->color_space, + plane_state->input_tf, plane_state->dcc.enable, plane_state->format, plane_state->rotation, @@ -206,6 +208,7 @@ void update_surface_trace( if (update->plane_info) { SURFACE_TRACE( "plane_info->color_space = %d;\n" + "plane_info->input_tf = %d;\n" "plane_info->format = %d;\n" "plane_info->plane_size.grph.surface_pitch = %d;\n" "plane_info->plane_size.grph.surface_size.height = %d;\n" @@ -214,6 +217,7 @@ void update_surface_trace( "plane_info->plane_size.grph.surface_size.y = %d;\n" "plane_info->rotation = %d;\n", update->plane_info->color_space, + update->plane_info->input_tf, update->plane_info->format, update->plane_info->plane_size.grph.surface_pitch, update->plane_info->plane_size.grph.surface_size.height, diff --git a/drivers/gpu/drm/amd/display/dc/core/dc_hw_sequencer.c b/drivers/gpu/drm/amd/display/dc/core/dc_hw_sequencer.c index 71993d5983bf..ebc96b720083 100644 --- a/drivers/gpu/drm/amd/display/dc/core/dc_hw_sequencer.c +++ b/drivers/gpu/drm/amd/display/dc/core/dc_hw_sequencer.c @@ -28,6 +28,8 @@ #include "timing_generator.h" #include "hw_sequencer.h" +#define NUM_ELEMENTS(a) (sizeof(a) / sizeof((a)[0])) + /* used as index in array of black_color_format */ enum black_color_format { BLACK_COLOR_FORMAT_RGB_FULLRANGE = 0, @@ -38,6 +40,15 @@ enum black_color_format { BLACK_COLOR_FORMAT_DEBUG, }; +enum dc_color_space_type { + COLOR_SPACE_RGB_TYPE, + COLOR_SPACE_RGB_LIMITED_TYPE, + COLOR_SPACE_YCBCR601_TYPE, + COLOR_SPACE_YCBCR709_TYPE, + COLOR_SPACE_YCBCR601_LIMITED_TYPE, + COLOR_SPACE_YCBCR709_LIMITED_TYPE +}; + static const struct tg_color black_color_format[] = { /* BlackColorFormat_RGB_FullRange */ {0, 0, 0}, @@ -53,6 +64,140 @@ static const struct tg_color black_color_format[] = { {0xff, 0xff, 0}, }; +struct out_csc_color_matrix_type { + enum dc_color_space_type color_space_type; + uint16_t regval[12]; +}; + +static const struct out_csc_color_matrix_type output_csc_matrix[] = { + { COLOR_SPACE_RGB_TYPE, + { 0x2000, 0, 0, 0, 0, 0x2000, 0, 0, 0, 0, 0x2000, 0} }, + { COLOR_SPACE_RGB_LIMITED_TYPE, + { 0x1B67, 0, 0, 0x201, 0, 0x1B67, 0, 0x201, 0, 0, 0x1B67, 0x201} }, + { COLOR_SPACE_YCBCR601_TYPE, + { 0xE04, 0xF444, 0xFDB9, 0x1004, 0x831, 0x1016, 0x320, 0x201, 0xFB45, + 0xF6B7, 0xE04, 0x1004} }, + { COLOR_SPACE_YCBCR709_TYPE, + { 0xE04, 0xF345, 0xFEB7, 0x1004, 0x5D3, 0x1399, 0x1FA, + 0x201, 0xFCCA, 0xF533, 0xE04, 0x1004} }, + + /* TODO: correct values below */ + { COLOR_SPACE_YCBCR601_LIMITED_TYPE, + { 0xE00, 0xF447, 0xFDB9, 0x1000, 0x991, + 0x12C9, 0x3A6, 0x200, 0xFB47, 0xF6B9, 0xE00, 0x1000} }, + { COLOR_SPACE_YCBCR709_LIMITED_TYPE, + { 0xE00, 0xF349, 0xFEB7, 0x1000, 0x6CE, 0x16E3, + 0x24F, 0x200, 0xFCCB, 0xF535, 0xE00, 0x1000} }, +}; + +static bool is_rgb_type( + enum dc_color_space color_space) +{ + bool ret = false; + + if (color_space == COLOR_SPACE_SRGB || + color_space == COLOR_SPACE_XR_RGB || + color_space == COLOR_SPACE_MSREF_SCRGB || + color_space == COLOR_SPACE_2020_RGB_FULLRANGE || + color_space == COLOR_SPACE_ADOBERGB || + color_space == COLOR_SPACE_DCIP3 || + color_space == COLOR_SPACE_DOLBYVISION) + ret = true; + return ret; +} + +static bool is_rgb_limited_type( + enum dc_color_space color_space) +{ + bool ret = false; + + if (color_space == COLOR_SPACE_SRGB_LIMITED || + color_space == COLOR_SPACE_2020_RGB_LIMITEDRANGE) + ret = true; + return ret; +} + +static bool is_ycbcr601_type( + enum dc_color_space color_space) +{ + bool ret = false; + + if (color_space == COLOR_SPACE_YCBCR601 || + color_space == COLOR_SPACE_XV_YCC_601) + ret = true; + return ret; +} + +static bool is_ycbcr601_limited_type( + enum dc_color_space color_space) +{ + bool ret = false; + + if (color_space == COLOR_SPACE_YCBCR601_LIMITED) + ret = true; + return ret; +} + +static bool is_ycbcr709_type( + enum dc_color_space color_space) +{ + bool ret = false; + + if (color_space == COLOR_SPACE_YCBCR709 || + color_space == COLOR_SPACE_XV_YCC_709) + ret = true; + return ret; +} + +static bool is_ycbcr709_limited_type( + enum dc_color_space color_space) +{ + bool ret = false; + + if (color_space == COLOR_SPACE_YCBCR709_LIMITED) + ret = true; + return ret; +} +enum dc_color_space_type get_color_space_type(enum dc_color_space color_space) +{ + enum dc_color_space_type type = COLOR_SPACE_RGB_TYPE; + + if (is_rgb_type(color_space)) + type = COLOR_SPACE_RGB_TYPE; + else if (is_rgb_limited_type(color_space)) + type = COLOR_SPACE_RGB_LIMITED_TYPE; + else if (is_ycbcr601_type(color_space)) + type = COLOR_SPACE_YCBCR601_TYPE; + else if (is_ycbcr709_type(color_space)) + type = COLOR_SPACE_YCBCR709_TYPE; + else if (is_ycbcr601_limited_type(color_space)) + type = COLOR_SPACE_YCBCR601_LIMITED_TYPE; + else if (is_ycbcr709_limited_type(color_space)) + type = COLOR_SPACE_YCBCR709_LIMITED_TYPE; + + return type; +} + +const uint16_t *find_color_matrix(enum dc_color_space color_space, + uint32_t *array_size) +{ + int i; + enum dc_color_space_type type; + const uint16_t *val = NULL; + int arr_size = NUM_ELEMENTS(output_csc_matrix); + + type = get_color_space_type(color_space); + for (i = 0; i < arr_size; i++) + if (output_csc_matrix[i].color_space_type == type) { + val = output_csc_matrix[i].regval; + *array_size = 12; + break; + } + + return val; +} + + void color_space_to_black_color( const struct dc *dc, enum dc_color_space colorspace, diff --git a/drivers/gpu/drm/amd/display/dc/core/dc_link.c b/drivers/gpu/drm/amd/display/dc/core/dc_link.c index 42a111b9505d..a37428271573 100644 --- a/drivers/gpu/drm/amd/display/dc/core/dc_link.c +++ b/drivers/gpu/drm/amd/display/dc/core/dc_link.c @@ -938,8 +938,9 @@ static bool construct( link->link_id = bios->funcs->get_connector_id(bios, init_params->connector_index); if (link->link_id.type != OBJECT_TYPE_CONNECTOR) { - dm_error("%s: Invalid Connector ObjectID from Adapter Service for connector index:%d!\n", - __func__, init_params->connector_index); + dm_error("%s: Invalid Connector ObjectID from Adapter Service for connector index:%d! type %d expected %d\n", + __func__, init_params->connector_index, + link->link_id.type, OBJECT_TYPE_CONNECTOR); goto create_fail; } @@ -1271,6 +1272,24 @@ static enum dc_status enable_link_dp( return status; } +static enum dc_status enable_link_edp( + struct dc_state *state, + struct pipe_ctx *pipe_ctx) +{ + enum dc_status status; + struct dc_stream_state *stream = pipe_ctx->stream; + struct dc_link *link = stream->sink->link; + + link->dc->hwss.edp_power_control(link, true); + link->dc->hwss.edp_wait_for_hpd_ready(link, true); + + status = enable_link_dp(state, pipe_ctx); + + link->dc->hwss.edp_backlight_control(link, true); + + return status; +} + static enum dc_status enable_link_dp_mst( struct dc_state *state, struct pipe_ctx *pipe_ctx) @@ -1746,9 +1765,11 @@ static enum dc_status enable_link( enum dc_status status = DC_ERROR_UNEXPECTED; switch (pipe_ctx->stream->signal) { case SIGNAL_TYPE_DISPLAY_PORT: - case SIGNAL_TYPE_EDP: status = enable_link_dp(state, pipe_ctx); break; + case SIGNAL_TYPE_EDP: + status = enable_link_edp(state, pipe_ctx); + break; case SIGNAL_TYPE_DISPLAY_PORT_MST: status = enable_link_dp_mst(state, pipe_ctx); msleep(200); @@ -1798,7 +1819,7 @@ static void disable_link(struct dc_link *link, enum signal_type signal) else dp_disable_link_phy_mst(link, signal); } else - link->link_enc->funcs->disable_output(link->link_enc, signal, link); + link->link_enc->funcs->disable_output(link->link_enc, signal); } static bool dp_active_dongle_validate_timing( @@ -1871,7 +1892,7 @@ enum dc_status dc_link_validate_mode_timing( const struct dc_crtc_timing *timing) { uint32_t max_pix_clk = stream->sink->dongle_max_pix_clk; - struct dc_dongle_caps *dongle_caps = &link->link_status.dpcd_caps->dongle_caps; + struct dc_dongle_caps *dongle_caps = &link->dpcd_caps.dongle_caps; /* A hack to avoid failing any modes for EDID override feature on * topology change such as lower quality cable for DP or different dongle @@ -1909,12 +1930,18 @@ bool dc_link_set_backlight_level(const struct dc_link *link, uint32_t level, { struct dc *core_dc = link->ctx->dc; struct abm *abm = core_dc->res_pool->abm; + struct dmcu *dmcu = core_dc->res_pool->dmcu; unsigned int controller_id = 0; + bool use_smooth_brightness = true; int i; - if ((abm == NULL) || (abm->funcs->set_backlight_level == NULL)) + if ((dmcu == NULL) || + (abm == NULL) || + (abm->funcs->set_backlight_level == NULL)) return false; + use_smooth_brightness = dmcu->funcs->is_dmcu_initialized(dmcu); + dm_logger_write(link->ctx->logger, LOG_BACKLIGHT, "New Backlight level: %d (0x%X)\n", level, level); @@ -1937,7 +1964,8 @@ bool dc_link_set_backlight_level(const struct dc_link *link, uint32_t level, abm, level, frame_ramp, - controller_id); + controller_id, + use_smooth_brightness); } return true; @@ -1954,144 +1982,6 @@ bool dc_link_set_psr_enable(const struct dc_link *link, bool enable, bool wait) return true; } -bool dc_link_get_psr_state(const struct dc_link *link, uint32_t *psr_state) -{ - struct dc *core_dc = link->ctx->dc; - struct dmcu *dmcu = core_dc->res_pool->dmcu; - - if (dmcu != NULL && link->psr_enabled) - dmcu->funcs->get_psr_state(dmcu, psr_state); - - return true; -} - -bool dc_link_setup_psr(struct dc_link *link, - const struct dc_stream_state *stream, struct psr_config *psr_config, - struct psr_context *psr_context) -{ - struct dc *core_dc = link->ctx->dc; - struct dmcu *dmcu = core_dc->res_pool->dmcu; - int i; - - psr_context->controllerId = CONTROLLER_ID_UNDEFINED; - - if (link != NULL && - dmcu != NULL) { - /* updateSinkPsrDpcdConfig*/ - union dpcd_psr_configuration psr_configuration; - - memset(&psr_configuration, 0, sizeof(psr_configuration)); - - psr_configuration.bits.ENABLE = 1; - psr_configuration.bits.CRC_VERIFICATION = 1; - psr_configuration.bits.FRAME_CAPTURE_INDICATION = - psr_config->psr_frame_capture_indication_req; - - /* Check for PSR v2*/ - if (psr_config->psr_version == 0x2) { - /* For PSR v2 selective update. - * Indicates whether sink should start capturing - * immediately following active scan line, - * or starting with the 2nd active scan line. - */ - psr_configuration.bits.LINE_CAPTURE_INDICATION = 0; - /*For PSR v2, determines whether Sink should generate - * IRQ_HPD when CRC mismatch is detected. - */ - psr_configuration.bits.IRQ_HPD_WITH_CRC_ERROR = 1; - } - - dm_helpers_dp_write_dpcd( - link->ctx, - link, - 368, - &psr_configuration.raw, - sizeof(psr_configuration.raw)); - - psr_context->channel = link->ddc->ddc_pin->hw_info.ddc_channel; - psr_context->transmitterId = link->link_enc->transmitter; - psr_context->engineId = link->link_enc->preferred_engine; - - for (i = 0; i < MAX_PIPES; i++) { - if (core_dc->current_state->res_ctx.pipe_ctx[i].stream - == stream) { - /* dmcu -1 for all controller id values, - * therefore +1 here - */ - psr_context->controllerId = - core_dc->current_state->res_ctx. - pipe_ctx[i].stream_res.tg->inst + 1; - break; - } - } - - /* Hardcoded for now. Can be Pcie or Uniphy (or Unknown)*/ - psr_context->phyType = PHY_TYPE_UNIPHY; - /*PhyId is associated with the transmitter id*/ - psr_context->smuPhyId = link->link_enc->transmitter; - - psr_context->crtcTimingVerticalTotal = stream->timing.v_total; - psr_context->vsyncRateHz = div64_u64(div64_u64((stream-> - timing.pix_clk_khz * 1000), - stream->timing.v_total), - stream->timing.h_total); - - psr_context->psrSupportedDisplayConfig = true; - psr_context->psrExitLinkTrainingRequired = - psr_config->psr_exit_link_training_required; - psr_context->sdpTransmitLineNumDeadline = - psr_config->psr_sdp_transmit_line_num_deadline; - psr_context->psrFrameCaptureIndicationReq = - psr_config->psr_frame_capture_indication_req; - - psr_context->skipPsrWaitForPllLock = 0; /* only = 1 in KV */ - - psr_context->numberOfControllers = - link->dc->res_pool->res_cap->num_timing_generator; - - psr_context->rfb_update_auto_en = true; - - /* 2 frames before enter PSR. */ - psr_context->timehyst_frames = 2; - /* half a frame - * (units in 100 lines, i.e. a value of 1 represents 100 lines) - */ - psr_context->hyst_lines = stream->timing.v_total / 2 / 100; - psr_context->aux_repeats = 10; - - psr_context->psr_level.u32all = 0; - -#if defined(CONFIG_DRM_AMD_DC_DCN1_0) - /*skip power down the single pipe since it blocks the cstate*/ - if (ASIC_REV_IS_RAVEN(link->ctx->asic_id.hw_internal_rev)) - psr_context->psr_level.bits.SKIP_CRTC_DISABLE = true; -#endif - - /* SMU will perform additional powerdown sequence. - * For unsupported ASICs, set psr_level flag to skip PSR - * static screen notification to SMU. - * (Always set for DAL2, did not check ASIC) - */ - psr_context->psr_level.bits.SKIP_SMU_NOTIFICATION = 1; - - /* Complete PSR entry before aborting to prevent intermittent - * freezes on certain eDPs - */ - psr_context->psr_level.bits.DISABLE_PSR_ENTRY_ABORT = 1; - - /* Controls additional delay after remote frame capture before - * continuing power down, default = 0 - */ - psr_context->frame_delay = 0; - - link->psr_enabled = true; - dmcu->funcs->setup_psr(dmcu, link, psr_context); - return true; - } else - return false; - -} - const struct dc_link_status *dc_link_get_status(const struct dc_link *link) { return &link->link_status; @@ -2420,6 +2310,9 @@ void core_link_disable_stream(struct pipe_ctx *pipe_ctx, int option) if (pipe_ctx->stream->signal == SIGNAL_TYPE_DISPLAY_PORT_MST) deallocate_mst_payload(pipe_ctx); + if (pipe_ctx->stream->signal == SIGNAL_TYPE_EDP) + core_dc->hwss.edp_backlight_control(pipe_ctx->stream->sink->link, false); + core_dc->hwss.disable_stream(pipe_ctx, option); disable_link(pipe_ctx->stream->sink->link, pipe_ctx->stream->signal); diff --git a/drivers/gpu/drm/amd/display/dc/core/dc_link_dp.c b/drivers/gpu/drm/amd/display/dc/core/dc_link_dp.c index e6bf05d76a94..639421a00ab6 100644 --- a/drivers/gpu/drm/amd/display/dc/core/dc_link_dp.c +++ b/drivers/gpu/drm/amd/display/dc/core/dc_link_dp.c @@ -220,8 +220,7 @@ static void dpcd_set_lt_pattern_and_lane_settings( size_in_bytes); dm_logger_write(link->ctx->logger, LOG_HW_LINK_TRAINING, - "%s:\n %x VS set = %x PE set = %x \ - max VS Reached = %x max PE Reached = %x\n", + "%s:\n %x VS set = %x PE set = %x max VS Reached = %x max PE Reached = %x\n", __func__, DP_TRAINING_LANE0_SET, dpcd_lane[0].bits.VOLTAGE_SWING_SET, @@ -558,8 +557,7 @@ static void dpcd_set_lane_settings( */ dm_logger_write(link->ctx->logger, LOG_HW_LINK_TRAINING, - "%s\n %x VS set = %x PE set = %x \ - max VS Reached = %x max PE Reached = %x\n", + "%s\n %x VS set = %x PE set = %x max VS Reached = %x max PE Reached = %x\n", __func__, DP_TRAINING_LANE0_SET, dpcd_lane[0].bits.VOLTAGE_SWING_SET, @@ -720,7 +718,7 @@ static enum link_training_result perform_channel_equalization_sequence( uint32_t retries_ch_eq; enum dc_lane_count lane_count = lt_settings->link_settings.lane_count; union lane_align_status_updated dpcd_lane_status_updated = {{0}}; - union lane_status dpcd_lane_status[LANE_COUNT_DP_MAX] = {{{0}}};; + union lane_status dpcd_lane_status[LANE_COUNT_DP_MAX] = {{{0}}}; hw_tr_pattern = get_supported_tp(link); @@ -872,9 +870,8 @@ static bool perform_clock_recovery_sequence( if (retry_count >= LINK_TRAINING_MAX_CR_RETRY) { ASSERT(0); dm_logger_write(link->ctx->logger, LOG_ERROR, - "%s: Link Training Error, could not \ - get CR after %d tries. \ - Possibly voltage swing issue", __func__, + "%s: Link Training Error, could not get CR after %d tries. Possibly voltage swing issue", + __func__, LINK_TRAINING_MAX_CR_RETRY); } @@ -1468,7 +1465,13 @@ void decide_link_settings(struct dc_stream_state *stream, /* MST doesn't perform link training for now * TODO: add MST specific link training routine */ - if (is_mst_supported(link)) { + if (stream->signal == SIGNAL_TYPE_DISPLAY_PORT_MST) { + *link_setting = link->verified_link_cap; + return; + } + + /* EDP use the link cap setting */ + if (stream->sink->sink_signal == SIGNAL_TYPE_EDP) { *link_setting = link->verified_link_cap; return; } @@ -2127,7 +2130,7 @@ static void get_active_converter_info( union dwnstream_port_caps_byte3_hdmi hdmi_caps = {.raw = det_caps[3] }; - union dwnstream_port_caps_byte1 + union dwnstream_port_caps_byte2 hdmi_color_caps = {.raw = det_caps[2] }; link->dpcd_caps.dongle_caps.dp_hdmi_max_pixel_clk = det_caps[1] * 25000; diff --git a/drivers/gpu/drm/amd/display/dc/core/dc_link_hwss.c b/drivers/gpu/drm/amd/display/dc/core/dc_link_hwss.c index 9a33b471270a..2096f2a179f2 100644 --- a/drivers/gpu/drm/amd/display/dc/core/dc_link_hwss.c +++ b/drivers/gpu/drm/amd/display/dc/core/dc_link_hwss.c @@ -88,15 +88,7 @@ void dp_enable_link_phy( } if (dc_is_dp_sst_signal(signal)) { - if (signal == SIGNAL_TYPE_EDP) { - link->dc->hwss.edp_power_control(link->link_enc, true); - link_enc->funcs->enable_dp_output( - link_enc, - link_settings, - clock_source); - link->dc->hwss.edp_backlight_control(link, true); - } else - link_enc->funcs->enable_dp_output( + link_enc->funcs->enable_dp_output( link_enc, link_settings, clock_source); @@ -138,12 +130,11 @@ void dp_disable_link_phy(struct dc_link *link, enum signal_type signal) dp_receiver_power_ctrl(link, false); if (signal == SIGNAL_TYPE_EDP) { - link->dc->hwss.edp_backlight_control(link, false); edp_receiver_ready_T9(link); - link->link_enc->funcs->disable_output(link->link_enc, signal, link); - link->dc->hwss.edp_power_control(link->link_enc, false); + link->link_enc->funcs->disable_output(link->link_enc, signal); + link->dc->hwss.edp_power_control(link, false); } else - link->link_enc->funcs->disable_output(link->link_enc, signal, link); + link->link_enc->funcs->disable_output(link->link_enc, signal); /* Clear current link setting.*/ memset(&link->cur_link_settings, 0, @@ -286,8 +277,7 @@ void dp_retrain_link_dp_test(struct dc_link *link, link->link_enc->funcs->disable_output( link->link_enc, - SIGNAL_TYPE_DISPLAY_PORT, - link); + SIGNAL_TYPE_DISPLAY_PORT); /* Clear current link setting. */ memset(&link->cur_link_settings, 0, diff --git a/drivers/gpu/drm/amd/display/dc/core/dc_resource.c b/drivers/gpu/drm/amd/display/dc/core/dc_resource.c index 928895809867..95b8dd0e53c6 100644 --- a/drivers/gpu/drm/amd/display/dc/core/dc_resource.c +++ b/drivers/gpu/drm/amd/display/dc/core/dc_resource.c @@ -426,15 +426,8 @@ static enum pixel_format convert_pixel_format_to_dalsurface( static void rect_swap_helper(struct rect *rect) { - uint32_t temp = 0; - - temp = rect->height; - rect->height = rect->width; - rect->width = temp; - - temp = rect->x; - rect->x = rect->y; - rect->y = temp; + swap(rect->height, rect->width); + swap(rect->x, rect->y); } static void calculate_viewport(struct pipe_ctx *pipe_ctx) @@ -505,26 +498,15 @@ static void calculate_viewport(struct pipe_ctx *pipe_ctx) data->viewport_c.height = (data->viewport.height + vpc_div - 1) / vpc_div; /* Handle hsplit */ - if (pri_split || sec_split) { - /* HMirror XOR Secondary_pipe XOR Rotation_180 */ - bool right_view = (sec_split != plane_state->horizontal_mirror) != - (plane_state->rotation == ROTATION_ANGLE_180); - - if (plane_state->rotation == ROTATION_ANGLE_90 - || plane_state->rotation == ROTATION_ANGLE_270) - /* Secondary_pipe XOR Rotation_270 */ - right_view = (plane_state->rotation == ROTATION_ANGLE_270) != sec_split; - - if (right_view) { - data->viewport.x += data->viewport.width / 2; - data->viewport_c.x += data->viewport_c.width / 2; - /* Ceil offset pipe */ - data->viewport.width = (data->viewport.width + 1) / 2; - data->viewport_c.width = (data->viewport_c.width + 1) / 2; - } else { - data->viewport.width /= 2; - data->viewport_c.width /= 2; - } + if (sec_split) { + data->viewport.x += data->viewport.width / 2; + data->viewport_c.x += data->viewport_c.width / 2; + /* Ceil offset pipe */ + data->viewport.width = (data->viewport.width + 1) / 2; + data->viewport_c.width = (data->viewport_c.width + 1) / 2; + } else if (pri_split) { + data->viewport.width /= 2; + data->viewport_c.width /= 2; } if (plane_state->rotation == ROTATION_ANGLE_90 || @@ -541,6 +523,11 @@ static void calculate_recout(struct pipe_ctx *pipe_ctx, struct view *recout_skip struct rect surf_src = plane_state->src_rect; struct rect surf_clip = plane_state->clip_rect; int recout_full_x, recout_full_y; + bool pri_split = pipe_ctx->bottom_pipe && + pipe_ctx->bottom_pipe->plane_state == pipe_ctx->plane_state; + bool sec_split = pipe_ctx->top_pipe && + pipe_ctx->top_pipe->plane_state == pipe_ctx->plane_state; + bool top_bottom_split = stream->view_format == VIEW_3D_FORMAT_TOP_AND_BOTTOM; if (pipe_ctx->plane_state->rotation == ROTATION_ANGLE_90 || pipe_ctx->plane_state->rotation == ROTATION_ANGLE_270) @@ -575,33 +562,43 @@ static void calculate_recout(struct pipe_ctx *pipe_ctx, struct view *recout_skip - pipe_ctx->plane_res.scl_data.recout.y; /* Handle h & vsplit */ - if (pipe_ctx->top_pipe && pipe_ctx->top_pipe->plane_state == - pipe_ctx->plane_state) { - if (stream->view_format == VIEW_3D_FORMAT_TOP_AND_BOTTOM) { - pipe_ctx->plane_res.scl_data.recout.y += pipe_ctx->plane_res.scl_data.recout.height / 2; - /* Floor primary pipe, ceil 2ndary pipe */ - pipe_ctx->plane_res.scl_data.recout.height = (pipe_ctx->plane_res.scl_data.recout.height + 1) / 2; + if (sec_split && top_bottom_split) { + pipe_ctx->plane_res.scl_data.recout.y += + pipe_ctx->plane_res.scl_data.recout.height / 2; + /* Floor primary pipe, ceil 2ndary pipe */ + pipe_ctx->plane_res.scl_data.recout.height = + (pipe_ctx->plane_res.scl_data.recout.height + 1) / 2; + } else if (pri_split && top_bottom_split) + pipe_ctx->plane_res.scl_data.recout.height /= 2; + else if (pri_split || sec_split) { + /* HMirror XOR Secondary_pipe XOR Rotation_180 */ + bool right_view = (sec_split != plane_state->horizontal_mirror) != + (plane_state->rotation == ROTATION_ANGLE_180); + + if (plane_state->rotation == ROTATION_ANGLE_90 + || plane_state->rotation == ROTATION_ANGLE_270) + /* Secondary_pipe XOR Rotation_270 */ + right_view = (plane_state->rotation == ROTATION_ANGLE_270) != sec_split; + + if (right_view) { + pipe_ctx->plane_res.scl_data.recout.x += + pipe_ctx->plane_res.scl_data.recout.width / 2; + /* Ceil offset pipe */ + pipe_ctx->plane_res.scl_data.recout.width = + (pipe_ctx->plane_res.scl_data.recout.width + 1) / 2; } else { - pipe_ctx->plane_res.scl_data.recout.x += pipe_ctx->plane_res.scl_data.recout.width / 2; - pipe_ctx->plane_res.scl_data.recout.width = (pipe_ctx->plane_res.scl_data.recout.width + 1) / 2; - } - } else if (pipe_ctx->bottom_pipe && - pipe_ctx->bottom_pipe->plane_state == pipe_ctx->plane_state) { - if (stream->view_format == VIEW_3D_FORMAT_TOP_AND_BOTTOM) - pipe_ctx->plane_res.scl_data.recout.height /= 2; - else pipe_ctx->plane_res.scl_data.recout.width /= 2; + } } - /* Unclipped recout offset = stream dst offset + ((surf dst offset - stream surf_src offset) * * 1/ stream scaling ratio) - (surf surf_src offset * 1/ full scl * ratio) */ - recout_full_x = stream->dst.x + (plane_state->dst_rect.x - stream->src.x) + recout_full_x = stream->dst.x + (plane_state->dst_rect.x - stream->src.x) * stream->dst.width / stream->src.width - surf_src.x * plane_state->dst_rect.width / surf_src.width * stream->dst.width / stream->src.width; - recout_full_y = stream->dst.y + (plane_state->dst_rect.y - stream->src.y) + recout_full_y = stream->dst.y + (plane_state->dst_rect.y - stream->src.y) * stream->dst.height / stream->src.height - surf_src.y * plane_state->dst_rect.height / surf_src.height * stream->dst.height / stream->src.height; @@ -657,7 +654,20 @@ static void calculate_inits_and_adj_vp(struct pipe_ctx *pipe_ctx, struct view *r struct rect src = pipe_ctx->plane_state->src_rect; int vpc_div = (data->format == PIXEL_FORMAT_420BPP8 || data->format == PIXEL_FORMAT_420BPP10) ? 2 : 1; + bool flip_vert_scan_dir = false, flip_horz_scan_dir = false; + /* + * Need to calculate the scan direction for viewport to make adjustments + */ + if (pipe_ctx->plane_state->rotation == ROTATION_ANGLE_180) { + flip_vert_scan_dir = true; + flip_horz_scan_dir = true; + } else if (pipe_ctx->plane_state->rotation == ROTATION_ANGLE_90) + flip_vert_scan_dir = true; + else if (pipe_ctx->plane_state->rotation == ROTATION_ANGLE_270) + flip_horz_scan_dir = true; + if (pipe_ctx->plane_state->horizontal_mirror) + flip_horz_scan_dir = !flip_horz_scan_dir; if (pipe_ctx->plane_state->rotation == ROTATION_ANGLE_90 || pipe_ctx->plane_state->rotation == ROTATION_ANGLE_270) { @@ -722,7 +732,7 @@ static void calculate_inits_and_adj_vp(struct pipe_ctx *pipe_ctx, struct view *r } /* Adjust for non-0 viewport offset */ - if (data->viewport.x) { + if (data->viewport.x && !flip_horz_scan_dir) { int int_part; data->inits.h = dal_fixed31_32_add(data->inits.h, dal_fixed31_32_mul_int( @@ -743,7 +753,7 @@ static void calculate_inits_and_adj_vp(struct pipe_ctx *pipe_ctx, struct view *r data->inits.h = dal_fixed31_32_add_int(data->inits.h, int_part); } - if (data->viewport_c.x) { + if (data->viewport_c.x && !flip_horz_scan_dir) { int int_part; data->inits.h_c = dal_fixed31_32_add(data->inits.h_c, dal_fixed31_32_mul_int( @@ -764,7 +774,7 @@ static void calculate_inits_and_adj_vp(struct pipe_ctx *pipe_ctx, struct view *r data->inits.h_c = dal_fixed31_32_add_int(data->inits.h_c, int_part); } - if (data->viewport.y) { + if (data->viewport.y && !flip_vert_scan_dir) { int int_part; data->inits.v = dal_fixed31_32_add(data->inits.v, dal_fixed31_32_mul_int( @@ -785,7 +795,7 @@ static void calculate_inits_and_adj_vp(struct pipe_ctx *pipe_ctx, struct view *r data->inits.v = dal_fixed31_32_add_int(data->inits.v, int_part); } - if (data->viewport_c.y) { + if (data->viewport_c.y && !flip_vert_scan_dir) { int int_part; data->inits.v_c = dal_fixed31_32_add(data->inits.v_c, dal_fixed31_32_mul_int( @@ -2319,20 +2329,13 @@ static void set_spd_info_packet( static void set_hdr_static_info_packet( struct encoder_info_packet *info_packet, - struct dc_plane_state *plane_state, struct dc_stream_state *stream) { uint16_t i = 0; enum signal_type signal = stream->signal; - struct dc_hdr_static_metadata hdr_metadata; uint32_t data; - if (!plane_state) - return; - - hdr_metadata = plane_state->hdr_static_ctx; - - if (!hdr_metadata.hdr_supported) + if (!stream->hdr_static_metadata.hdr_supported) return; if (dc_is_hdmi_signal(signal)) { @@ -2352,55 +2355,55 @@ static void set_hdr_static_info_packet( i = 2; } - data = hdr_metadata.is_hdr; + data = stream->hdr_static_metadata.is_hdr; info_packet->sb[i++] = data ? 0x02 : 0x00; info_packet->sb[i++] = 0x00; - data = hdr_metadata.chromaticity_green_x / 2; + data = stream->hdr_static_metadata.chromaticity_green_x / 2; info_packet->sb[i++] = data & 0xFF; info_packet->sb[i++] = (data & 0xFF00) >> 8; - data = hdr_metadata.chromaticity_green_y / 2; + data = stream->hdr_static_metadata.chromaticity_green_y / 2; info_packet->sb[i++] = data & 0xFF; info_packet->sb[i++] = (data & 0xFF00) >> 8; - data = hdr_metadata.chromaticity_blue_x / 2; + data = stream->hdr_static_metadata.chromaticity_blue_x / 2; info_packet->sb[i++] = data & 0xFF; info_packet->sb[i++] = (data & 0xFF00) >> 8; - data = hdr_metadata.chromaticity_blue_y / 2; + data = stream->hdr_static_metadata.chromaticity_blue_y / 2; info_packet->sb[i++] = data & 0xFF; info_packet->sb[i++] = (data & 0xFF00) >> 8; - data = hdr_metadata.chromaticity_red_x / 2; + data = stream->hdr_static_metadata.chromaticity_red_x / 2; info_packet->sb[i++] = data & 0xFF; info_packet->sb[i++] = (data & 0xFF00) >> 8; - data = hdr_metadata.chromaticity_red_y / 2; + data = stream->hdr_static_metadata.chromaticity_red_y / 2; info_packet->sb[i++] = data & 0xFF; info_packet->sb[i++] = (data & 0xFF00) >> 8; - data = hdr_metadata.chromaticity_white_point_x / 2; + data = stream->hdr_static_metadata.chromaticity_white_point_x / 2; info_packet->sb[i++] = data & 0xFF; info_packet->sb[i++] = (data & 0xFF00) >> 8; - data = hdr_metadata.chromaticity_white_point_y / 2; + data = stream->hdr_static_metadata.chromaticity_white_point_y / 2; info_packet->sb[i++] = data & 0xFF; info_packet->sb[i++] = (data & 0xFF00) >> 8; - data = hdr_metadata.max_luminance; + data = stream->hdr_static_metadata.max_luminance; info_packet->sb[i++] = data & 0xFF; info_packet->sb[i++] = (data & 0xFF00) >> 8; - data = hdr_metadata.min_luminance; + data = stream->hdr_static_metadata.min_luminance; info_packet->sb[i++] = data & 0xFF; info_packet->sb[i++] = (data & 0xFF00) >> 8; - data = hdr_metadata.maximum_content_light_level; + data = stream->hdr_static_metadata.maximum_content_light_level; info_packet->sb[i++] = data & 0xFF; info_packet->sb[i++] = (data & 0xFF00) >> 8; - data = hdr_metadata.maximum_frame_average_light_level; + data = stream->hdr_static_metadata.maximum_frame_average_light_level; info_packet->sb[i++] = data & 0xFF; info_packet->sb[i++] = (data & 0xFF00) >> 8; @@ -2551,16 +2554,14 @@ void resource_build_info_frame(struct pipe_ctx *pipe_ctx) set_spd_info_packet(&info->spd, pipe_ctx->stream); - set_hdr_static_info_packet(&info->hdrsmd, - pipe_ctx->plane_state, pipe_ctx->stream); + set_hdr_static_info_packet(&info->hdrsmd, pipe_ctx->stream); } else if (dc_is_dp_signal(signal)) { set_vsc_info_packet(&info->vsc, pipe_ctx->stream); set_spd_info_packet(&info->spd, pipe_ctx->stream); - set_hdr_static_info_packet(&info->hdrsmd, - pipe_ctx->plane_state, pipe_ctx->stream); + set_hdr_static_info_packet(&info->hdrsmd, pipe_ctx->stream); } patch_gamut_packet_checksum(&info->gamut); diff --git a/drivers/gpu/drm/amd/display/dc/core/dc_stream.c b/drivers/gpu/drm/amd/display/dc/core/dc_stream.c index e230cc44a0a7..539c3e0a6292 100644 --- a/drivers/gpu/drm/amd/display/dc/core/dc_stream.c +++ b/drivers/gpu/drm/amd/display/dc/core/dc_stream.c @@ -36,16 +36,13 @@ #define TMDS_MAX_PIXEL_CLOCK_IN_KHZ_UPMOST 297000 static void update_stream_signal(struct dc_stream_state *stream) { - if (stream->output_signal == SIGNAL_TYPE_NONE) { - struct dc_sink *dc_sink = stream->sink; - if (dc_sink->sink_signal == SIGNAL_TYPE_NONE) - stream->signal = stream->sink->link->connector_signal; - else - stream->signal = dc_sink->sink_signal; - } else { - stream->signal = stream->output_signal; - } + struct dc_sink *dc_sink = stream->sink; + + if (dc_sink->sink_signal == SIGNAL_TYPE_NONE) + stream->signal = stream->sink->link->connector_signal; + else + stream->signal = dc_sink->sink_signal; if (dc_is_dvi_signal(stream->signal)) { if (stream->timing.pix_clk_khz > TMDS_MAX_PIXEL_CLOCK_IN_KHZ_UPMOST && @@ -200,7 +197,8 @@ bool dc_stream_set_cursor_attributes( for (i = 0; i < MAX_PIPES; i++) { struct pipe_ctx *pipe_ctx = &res_ctx->pipe_ctx[i]; - if (pipe_ctx->stream != stream || (!pipe_ctx->plane_res.xfm && !pipe_ctx->plane_res.dpp)) + if (pipe_ctx->stream != stream || (!pipe_ctx->plane_res.xfm && + !pipe_ctx->plane_res.dpp) || !pipe_ctx->plane_res.ipp) continue; if (pipe_ctx->top_pipe && pipe_ctx->plane_state != pipe_ctx->top_pipe->plane_state) continue; @@ -229,7 +227,7 @@ bool dc_stream_set_cursor_attributes( if (pipe_ctx->plane_res.dpp != NULL && pipe_ctx->plane_res.dpp->funcs->set_cursor_attributes != NULL) pipe_ctx->plane_res.dpp->funcs->set_cursor_attributes( - pipe_ctx->plane_res.dpp, attributes); + pipe_ctx->plane_res.dpp, attributes->color_format); } stream->cursor_attributes = *attributes; @@ -276,7 +274,8 @@ bool dc_stream_set_cursor_position( if (pipe_ctx->stream != stream || (!pipe_ctx->plane_res.mi && !pipe_ctx->plane_res.hubp) || !pipe_ctx->plane_state || - (!pipe_ctx->plane_res.xfm && !pipe_ctx->plane_res.dpp)) + (!pipe_ctx->plane_res.xfm && !pipe_ctx->plane_res.dpp) || + !pipe_ctx->plane_res.ipp) continue; if (pipe_ctx->plane_state->address.type @@ -304,6 +303,8 @@ bool dc_stream_set_cursor_position( } + stream->cursor_position = *position; + return true; } |