diff options
Diffstat (limited to 'drivers/gpu/drm/amd/display/dc/core/dc.c')
-rw-r--r-- | drivers/gpu/drm/amd/display/dc/core/dc.c | 261 |
1 files changed, 221 insertions, 40 deletions
diff --git a/drivers/gpu/drm/amd/display/dc/core/dc.c b/drivers/gpu/drm/amd/display/dc/core/dc.c index 5fd52094d459..c68fbd55db3c 100644 --- a/drivers/gpu/drm/amd/display/dc/core/dc.c +++ b/drivers/gpu/drm/amd/display/dc/core/dc.c @@ -384,7 +384,7 @@ void dc_stream_set_dither_option(struct dc_stream_state *stream, enum dc_dither_option option) { struct bit_depth_reduction_params params; - struct dc_link *link = stream->sink->link; + struct dc_link *link = stream->link; struct pipe_ctx *pipes = NULL; int i; @@ -451,7 +451,7 @@ bool dc_stream_program_csc_matrix(struct dc *dc, struct dc_stream_state *stream) pipes, stream->output_color_space, stream->csc_color_matrix.matrix, - pipes->plane_res.hubp->opp_id); + pipes->plane_res.hubp ? pipes->plane_res.hubp->opp_id : 0); ret = true; } } @@ -526,9 +526,8 @@ void dc_link_set_preferred_link_settings(struct dc *dc, for (i = 0; i < MAX_PIPES; i++) { pipe = &dc->current_state->res_ctx.pipe_ctx[i]; - if (pipe->stream && pipe->stream->sink - && pipe->stream->sink->link) { - if (pipe->stream->sink->link == link) + if (pipe->stream && pipe->stream->link) { + if (pipe->stream->link == link) break; } } @@ -586,9 +585,6 @@ static void destruct(struct dc *dc) if (dc->ctx->gpio_service) dal_gpio_service_destroy(&dc->ctx->gpio_service); - if (dc->ctx->i2caux) - dal_i2caux_destroy(&dc->ctx->i2caux); - if (dc->ctx->created_bios) dal_bios_parser_destroy(&dc->ctx->dc_bios); @@ -625,7 +621,6 @@ static bool construct(struct dc *dc, #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__); @@ -670,6 +665,7 @@ static bool construct(struct dc *dc, dc_ctx->dc = dc; dc_ctx->asic_id = init_params->asic_id; dc_ctx->dc_sink_id_count = 0; + dc_ctx->dc_stream_id_count = 0; dc->ctx = dc_ctx; dc->current_state = dc_create_state(); @@ -709,14 +705,6 @@ static bool construct(struct dc *dc, dc_ctx->created_bios = true; } - /* Create I2C AUX */ - dc_ctx->i2caux = dal_i2caux_create(dc_ctx); - - if (!dc_ctx->i2caux) { - ASSERT_CRITICAL(false); - goto fail; - } - dc_ctx->perf_trace = dc_perf_trace_create(); if (!dc_ctx->perf_trace) { ASSERT_CRITICAL(false); @@ -840,6 +828,11 @@ alloc_fail: return NULL; } +void dc_init_callbacks(struct dc *dc, + const struct dc_callback_init *init_params) +{ +} + void dc_destroy(struct dc **dc) { destruct(*dc); @@ -875,8 +868,9 @@ static void program_timing_sync( struct dc *dc, struct dc_state *ctx) { - int i, j; + int i, j, k; int group_index = 0; + int num_group = 0; int pipe_count = dc->res_pool->pipe_count; struct pipe_ctx *unsynced_pipes[MAX_PIPES] = { NULL }; @@ -913,11 +907,11 @@ static void program_timing_sync( } } - /* set first unblanked pipe as master */ + /* set first pipe with plane as master */ 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->funcs->is_blanked(pipe_set[j]->stream_res.tg)) { + if (pipe_set[j]->plane_state) { if (j == 0) break; @@ -928,9 +922,21 @@ static void program_timing_sync( } } - /* remove any other unblanked pipes as they have already been synced */ + + for (k = 0; k < group_size; k++) { + struct dc_stream_status *status = dc_stream_get_status_from_state(ctx, pipe_set[k]->stream); + + status->timing_sync_info.group_id = num_group; + status->timing_sync_info.group_size = group_size; + if (k == 0) + status->timing_sync_info.master = true; + else + status->timing_sync_info.master = false; + + } + /* remove any other pipes with plane 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->funcs->is_blanked(pipe_set[j]->stream_res.tg)) { + if (pipe_set[j]->plane_state) { group_size--; pipe_set[j] = pipe_set[group_size]; j--; @@ -942,6 +948,7 @@ static void program_timing_sync( dc, group_index, group_size, pipe_set); group_index++; } + num_group++; } } @@ -962,6 +969,52 @@ static bool context_changed( return false; } +bool dc_validate_seamless_boot_timing(struct dc *dc, + const struct dc_sink *sink, + struct dc_crtc_timing *crtc_timing) +{ + struct timing_generator *tg; + struct dc_link *link = sink->link; + unsigned int inst; + + /* Check for enabled DIG to identify enabled display */ + if (!link->link_enc->funcs->is_dig_enabled(link->link_enc)) + return false; + + /* Check for which front end is used by this encoder. + * Note the inst is 1 indexed, where 0 is undefined. + * Note that DIG_FE can source from different OTG but our + * current implementation always map 1-to-1, so this code makes + * the same assumption and doesn't check OTG source. + */ + inst = link->link_enc->funcs->get_dig_frontend(link->link_enc) - 1; + + /* Instance should be within the range of the pool */ + if (inst >= dc->res_pool->pipe_count) + return false; + + tg = dc->res_pool->timing_generators[inst]; + + if (!tg->funcs->is_matching_timing) + return false; + + if (!tg->funcs->is_matching_timing(tg, crtc_timing)) + return false; + + if (dc_is_dp_signal(link->connector_signal)) { + unsigned int pix_clk_100hz; + + dc->res_pool->dp_clock_source->funcs->get_pixel_clk_frequency_100hz( + dc->res_pool->dp_clock_source, + inst, &pix_clk_100hz); + + if (crtc_timing->pix_clk_100hz != pix_clk_100hz) + return false; + } + + return true; +} + bool dc_enable_stereo( struct dc *dc, struct dc_state *context, @@ -1040,7 +1093,11 @@ static enum dc_status dc_commit_state_no_check(struct dc *dc, struct dc_state *c /* Program all planes within new context*/ for (i = 0; i < context->stream_count; i++) { - const struct dc_sink *sink = context->streams[i]->sink; + const struct dc_link *link = context->streams[i]->link; + struct dc_stream_status *status; + + if (context->streams[i]->apply_seamless_boot_optimization) + context->streams[i]->apply_seamless_boot_optimization = false; if (!context->streams[i]->mode_changed) continue; @@ -1065,12 +1122,15 @@ static enum dc_status dc_commit_state_no_check(struct dc *dc, struct dc_state *c } } - CONN_MSG_MODE(sink->link, "{%dx%d, %dx%d@%dKhz}", + status = dc_stream_get_status_from_state(context, context->streams[i]); + context->streams[i]->out.otg_offset = status->primary_otg_inst; + + CONN_MSG_MODE(link, "{%dx%d, %dx%d@%dKhz}", context->streams[i]->timing.h_addressable, context->streams[i]->timing.v_addressable, context->streams[i]->timing.h_total, context->streams[i]->timing.v_total, - context->streams[i]->timing.pix_clk_khz); + context->streams[i]->timing.pix_clk_100hz / 10); } dc_enable_stereo(dc, context, dc_streams, context->stream_count); @@ -1078,6 +1138,9 @@ static enum dc_status dc_commit_state_no_check(struct dc *dc, struct dc_state *c /* pplib is notified if disp_num changed */ dc->hwss.optimize_bandwidth(dc, context); + for (i = 0; i < context->stream_count; i++) + context->streams[i]->mode_changed = false; + dc_release_state(dc->current_state); dc->current_state = context; @@ -1114,6 +1177,9 @@ bool dc_post_update_surfaces_to_stream(struct dc *dc) int i; struct dc_state *context = dc->current_state; + if (dc->optimized_required == false) + return true; + post_surface_trace(dc); for (i = 0; i < dc->res_pool->pipe_count; i++) @@ -1215,6 +1281,12 @@ static enum surface_update_type get_plane_info_update_type(const struct dc_surfa */ update_flags->bits.bpp_change = 1; + if (u->plane_info->plane_size.grph.surface_pitch != u->surface->plane_size.grph.surface_pitch + || u->plane_info->plane_size.video.luma_pitch != u->surface->plane_size.video.luma_pitch + || u->plane_info->plane_size.video.chroma_pitch != u->surface->plane_size.video.chroma_pitch) + update_flags->bits.plane_size_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; @@ -1236,7 +1308,7 @@ static enum surface_update_type get_plane_info_update_type(const struct dc_surfa || update_flags->bits.output_tf_change) return UPDATE_TYPE_FULL; - return UPDATE_TYPE_MED; + return update_flags->raw ? UPDATE_TYPE_MED : UPDATE_TYPE_FAST; } static enum surface_update_type get_scaling_info_update_type( @@ -1436,6 +1508,101 @@ static struct dc_stream_status *stream_get_status( static const enum surface_update_type update_surface_trace_level = UPDATE_TYPE_FULL; +static void copy_surface_update_to_plane( + struct dc_plane_state *surface, + struct dc_surface_update *srf_update) +{ + if (srf_update->flip_addr) { + surface->address = srf_update->flip_addr->address; + surface->flip_immediate = + srf_update->flip_addr->flip_immediate; + surface->time.time_elapsed_in_us[surface->time.index] = + srf_update->flip_addr->flip_timestamp_in_us - + surface->time.prev_update_time_in_us; + surface->time.prev_update_time_in_us = + srf_update->flip_addr->flip_timestamp_in_us; + surface->time.index++; + if (surface->time.index >= DC_PLANE_UPDATE_TIMES_MAX) + surface->time.index = 0; + } + + if (srf_update->scaling_info) { + surface->scaling_quality = + srf_update->scaling_info->scaling_quality; + surface->dst_rect = + srf_update->scaling_info->dst_rect; + surface->src_rect = + srf_update->scaling_info->src_rect; + surface->clip_rect = + srf_update->scaling_info->clip_rect; + } + + if (srf_update->plane_info) { + surface->color_space = + srf_update->plane_info->color_space; + surface->format = + srf_update->plane_info->format; + surface->plane_size = + srf_update->plane_info->plane_size; + surface->rotation = + srf_update->plane_info->rotation; + surface->horizontal_mirror = + srf_update->plane_info->horizontal_mirror; + surface->stereo_format = + srf_update->plane_info->stereo_format; + surface->tiling_info = + srf_update->plane_info->tiling_info; + surface->visible = + srf_update->plane_info->visible; + surface->per_pixel_alpha = + srf_update->plane_info->per_pixel_alpha; + surface->global_alpha = + srf_update->plane_info->global_alpha; + surface->global_alpha_value = + srf_update->plane_info->global_alpha_value; + surface->dcc = + srf_update->plane_info->dcc; + surface->sdr_white_level = + srf_update->plane_info->sdr_white_level; + } + + if (srf_update->gamma && + (surface->gamma_correction != + srf_update->gamma)) { + memcpy(&surface->gamma_correction->entries, + &srf_update->gamma->entries, + sizeof(struct dc_gamma_entries)); + surface->gamma_correction->is_identity = + srf_update->gamma->is_identity; + surface->gamma_correction->num_entries = + srf_update->gamma->num_entries; + surface->gamma_correction->type = + srf_update->gamma->type; + } + + if (srf_update->in_transfer_func && + (surface->in_transfer_func != + srf_update->in_transfer_func)) { + surface->in_transfer_func->sdr_ref_white_level = + srf_update->in_transfer_func->sdr_ref_white_level; + surface->in_transfer_func->tf = + srf_update->in_transfer_func->tf; + surface->in_transfer_func->type = + srf_update->in_transfer_func->type; + memcpy(&surface->in_transfer_func->tf_pts, + &srf_update->in_transfer_func->tf_pts, + sizeof(struct dc_transfer_func_distributed_points)); + } + + if (srf_update->input_csc_color_matrix) + surface->input_csc_color_matrix = + *srf_update->input_csc_color_matrix; + + if (srf_update->coeff_reduction_factor) + surface->coeff_reduction_factor = + *srf_update->coeff_reduction_factor; +} + static void commit_planes_do_stream_update(struct dc *dc, struct dc_stream_state *stream, struct dc_stream_update *stream_update, @@ -1459,11 +1626,13 @@ static void commit_planes_do_stream_update(struct dc *dc, stream_update->adjust->v_total_min, stream_update->adjust->v_total_max); - if (stream_update->periodic_fn_vsync_delta && - pipe_ctx->stream_res.tg->funcs->program_vline_interrupt) - pipe_ctx->stream_res.tg->funcs->program_vline_interrupt( - pipe_ctx->stream_res.tg, &pipe_ctx->stream->timing, - pipe_ctx->stream->periodic_fn_vsync_delta); + if (stream_update->periodic_interrupt0 && + dc->hwss.setup_periodic_interrupt) + dc->hwss.setup_periodic_interrupt(pipe_ctx, VLINE0); + + if (stream_update->periodic_interrupt1 && + dc->hwss.setup_periodic_interrupt) + dc->hwss.setup_periodic_interrupt(pipe_ctx, VLINE1); if ((stream_update->hdr_static_metadata && !stream->use_dynamic_meta) || stream_update->vrr_infopacket || @@ -1605,7 +1774,6 @@ void dc_commit_updates_for_stream(struct dc *dc, int surface_count, struct dc_stream_state *stream, struct dc_stream_update *stream_update, - struct dc_plane_state **plane_states, struct dc_state *state) { const struct dc_stream_status *stream_status; @@ -1640,14 +1808,7 @@ void dc_commit_updates_for_stream(struct dc *dc, for (i = 0; i < surface_count; i++) { struct dc_plane_state *surface = srf_updates[i].surface; - /* TODO: On flip we don't build the state, so it still has the - * old address. Which is why we are updating the address here - */ - if (srf_updates[i].flip_addr) { - surface->address = srf_updates[i].flip_addr->address; - surface->flip_immediate = srf_updates[i].flip_addr->flip_immediate; - - } + copy_surface_update_to_plane(surface, &srf_updates[i]); if (update_type >= UPDATE_TYPE_MED) { for (j = 0; j < dc->res_pool->pipe_count; j++) { @@ -1764,6 +1925,26 @@ void dc_resume(struct dc *dc) core_link_resume(dc->links[i]); } +unsigned int dc_get_current_backlight_pwm(struct dc *dc) +{ + struct abm *abm = dc->res_pool->abm; + + if (abm) + return abm->funcs->get_current_backlight(abm); + + return 0; +} + +unsigned int dc_get_target_backlight_pwm(struct dc *dc) +{ + struct abm *abm = dc->res_pool->abm; + + if (abm) + return abm->funcs->get_target_backlight(abm); + + return 0; +} + bool dc_is_dmcu_initialized(struct dc *dc) { struct dmcu *dmcu = dc->res_pool->dmcu; |