diff options
Diffstat (limited to 'drivers/gpu/drm/amd/display/dc/core')
-rw-r--r-- | drivers/gpu/drm/amd/display/dc/core/dc.c | 342 | ||||
-rw-r--r-- | drivers/gpu/drm/amd/display/dc/core/dc_link.c | 208 | ||||
-rw-r--r-- | drivers/gpu/drm/amd/display/dc/core/dc_link_ddc.c | 10 | ||||
-rw-r--r-- | drivers/gpu/drm/amd/display/dc/core/dc_link_dp.c | 3 | ||||
-rw-r--r-- | drivers/gpu/drm/amd/display/dc/core/dc_resource.c | 287 | ||||
-rw-r--r-- | drivers/gpu/drm/amd/display/dc/core/dc_stream.c | 2 |
6 files changed, 575 insertions, 277 deletions
diff --git a/drivers/gpu/drm/amd/display/dc/core/dc.c b/drivers/gpu/drm/amd/display/dc/core/dc.c index 6ae050dc3220..7c491c91465f 100644 --- a/drivers/gpu/drm/amd/display/dc/core/dc.c +++ b/drivers/gpu/drm/amd/display/dc/core/dc.c @@ -54,9 +54,13 @@ #include "hubp.h" #include "dc_link_dp.h" + +#include "dce/dce_i2c.h" + #define DC_LOGGER \ dc->ctx->logger +const static char DC_BUILD_ID[] = "production-build"; /******************************************************************************* * Private functions @@ -188,11 +192,9 @@ failed_alloc: ***************************************************************************** */ bool dc_stream_adjust_vmin_vmax(struct dc *dc, - struct dc_stream_state **streams, int num_streams, - int vmin, int vmax) + struct dc_stream_state *stream, + struct dc_crtc_timing_adjust *adjust) { - /* TODO: Support multiple streams */ - struct dc_stream_state *stream = streams[0]; int i = 0; bool ret = false; @@ -200,11 +202,11 @@ bool dc_stream_adjust_vmin_vmax(struct dc *dc, struct pipe_ctx *pipe = &dc->current_state->res_ctx.pipe_ctx[i]; if (pipe->stream == stream && pipe->stream_res.stream_enc) { - dc->hwss.set_drr(&pipe, 1, vmin, vmax); - - /* build and update the info frame */ - resource_build_info_frame(pipe); - dc->hwss.update_info_frame(pipe); + pipe->stream->adjust = *adjust; + dc->hwss.set_drr(&pipe, + 1, + adjust->v_total_min, + adjust->v_total_max); ret = true; } @@ -217,7 +219,7 @@ bool dc_stream_get_crtc_position(struct dc *dc, unsigned int *v_pos, unsigned int *nom_v_pos) { /* TODO: Support multiple streams */ - struct dc_stream_state *stream = streams[0]; + const struct dc_stream_state *stream = streams[0]; int i = 0; bool ret = false; struct crtc_position position; @@ -361,6 +363,44 @@ void dc_stream_set_dither_option(struct dc_stream_state *stream, opp_program_bit_depth_reduction(pipes->stream_res.opp, ¶ms); } +bool dc_stream_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; +} + +bool dc_stream_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; +} + void dc_stream_set_static_screen_events(struct dc *dc, struct dc_stream_state **streams, int num_streams, @@ -421,9 +461,25 @@ void dc_link_set_preferred_link_settings(struct dc *dc, struct dc_link_settings *link_setting, struct dc_link *link) { + int i; + struct pipe_ctx *pipe; + struct dc_stream_state *link_stream; struct dc_link_settings store_settings = *link_setting; - struct dc_stream_state *link_stream = - link->dc->current_state->res_ctx.pipe_ctx[0].stream; + + 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) + break; + } + } + + /* Stream not found */ + if (i == MAX_PIPES) + return; + + link_stream = link->dc->current_state->res_ctx.pipe_ctx[i].stream; link->preferred_link_setting = store_settings; if (link_stream) @@ -703,11 +759,11 @@ struct dc *dc_create(const struct dc_init_data *init_params) dc->config = init_params->flags; + dc->build_id = DC_BUILD_ID; + DC_LOG_DC("Display Core initialized\n"); - /* TODO: missing feature to be enabled */ - dc->debug.disable_dfs_bypass = true; return dc; @@ -1057,32 +1113,6 @@ static bool is_surface_in_context( return false; } -static unsigned int pixel_format_to_bpp(enum surface_pixel_format format) -{ - switch (format) { - case SURFACE_PIXEL_FORMAT_VIDEO_420_YCbCr: - case SURFACE_PIXEL_FORMAT_VIDEO_420_YCrCb: - return 12; - case SURFACE_PIXEL_FORMAT_GRPH_ARGB1555: - case SURFACE_PIXEL_FORMAT_GRPH_RGB565: - case SURFACE_PIXEL_FORMAT_VIDEO_420_10bpc_YCbCr: - case SURFACE_PIXEL_FORMAT_VIDEO_420_10bpc_YCrCb: - return 16; - case SURFACE_PIXEL_FORMAT_GRPH_ARGB8888: - case SURFACE_PIXEL_FORMAT_GRPH_ABGR8888: - case SURFACE_PIXEL_FORMAT_GRPH_ARGB2101010: - case SURFACE_PIXEL_FORMAT_GRPH_ABGR2101010: - return 32; - case SURFACE_PIXEL_FORMAT_GRPH_ARGB16161616: - case SURFACE_PIXEL_FORMAT_GRPH_ARGB16161616F: - case SURFACE_PIXEL_FORMAT_GRPH_ABGR16161616F: - return 64; - default: - ASSERT_CRITICAL(false); - return -1; - } -} - static enum surface_update_type get_plane_info_update_type(const struct dc_surface_update *u) { union surface_update_flags *update_flags = &u->surface->update_flags; @@ -1108,21 +1138,21 @@ static enum surface_update_type get_plane_info_update_type(const struct dc_surfa if (u->plane_info->per_pixel_alpha != u->surface->per_pixel_alpha) update_flags->bits.per_pixel_alpha_change = 1; + if (u->plane_info->global_alpha_value != u->surface->global_alpha_value) + update_flags->bits.global_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)) + if (resource_pixel_format_to_bpp(u->plane_info->format) != + resource_pixel_format_to_bpp(u->surface->format)) /* different bytes per element will require full bandwidth * and DML calculation */ update_flags->bits.bpp_change = 1; - if (u->gamma && dce_use_lut(u->plane_info->format)) - update_flags->bits.gamma_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; @@ -1139,7 +1169,6 @@ static enum surface_update_type get_plane_info_update_type(const struct dc_surfa if (update_flags->bits.rotation_change || update_flags->bits.stereo_format_change || update_flags->bits.pixel_format_change - || update_flags->bits.gamma_change || update_flags->bits.bpp_change || update_flags->bits.bandwidth_change || update_flags->bits.output_tf_change) @@ -1229,13 +1258,26 @@ static enum surface_update_type det_surface_update(const struct dc *dc, if (u->coeff_reduction_factor) update_flags->bits.coeff_reduction_change = 1; + if (u->gamma) { + enum surface_pixel_format format = SURFACE_PIXEL_FORMAT_GRPH_BEGIN; + + if (u->plane_info) + format = u->plane_info->format; + else if (u->surface) + format = u->surface->format; + + if (dce_use_lut(format)) + update_flags->bits.gamma_change = 1; + } + if (update_flags->bits.in_transfer_func_change) { type = UPDATE_TYPE_MED; elevate_update_type(&overall_type, type); } if (update_flags->bits.input_csc_change - || update_flags->bits.coeff_reduction_change) { + || update_flags->bits.coeff_reduction_change + || update_flags->bits.gamma_change) { type = UPDATE_TYPE_FULL; elevate_update_type(&overall_type, type); } @@ -1256,8 +1298,25 @@ static enum surface_update_type check_update_surfaces_for_stream( if (stream_status == NULL || stream_status->plane_count != surface_count) return UPDATE_TYPE_FULL; - if (stream_update) - return UPDATE_TYPE_FULL; + /* some stream updates require passive update */ + if (stream_update) { + if ((stream_update->src.height != 0) && + (stream_update->src.width != 0)) + return UPDATE_TYPE_FULL; + + if ((stream_update->dst.height != 0) && + (stream_update->dst.width != 0)) + return UPDATE_TYPE_FULL; + + if (stream_update->out_transfer_func) + return UPDATE_TYPE_FULL; + + if (stream_update->abm_level) + return UPDATE_TYPE_FULL; + + if (stream_update->dpms_off) + return UPDATE_TYPE_FULL; + } for (i = 0 ; i < surface_count; i++) { enum surface_update_type type = @@ -1310,6 +1369,111 @@ static struct dc_stream_status *stream_get_status( static const enum surface_update_type update_surface_trace_level = UPDATE_TYPE_FULL; +static void notify_display_count_to_smu( + struct dc *dc, + struct dc_state *context) +{ + int i, display_count; + struct pp_smu_funcs_rv *pp_smu = dc->res_pool->pp_smu; + + /* + * if function pointer not set up, this message is + * sent as part of pplib_apply_display_requirements. + * So just return. + */ + if (!pp_smu || !pp_smu->set_display_count) + return; + + display_count = 0; + for (i = 0; i < context->stream_count; i++) { + const struct dc_stream_state *stream = context->streams[i]; + + /* only notify active stream */ + if (stream->dpms_off) + continue; + + display_count++; + } + + pp_smu->set_display_count(&pp_smu->pp_smu, display_count); +} + +static void commit_planes_do_stream_update(struct dc *dc, + struct dc_stream_state *stream, + struct dc_stream_update *stream_update, + enum surface_update_type update_type, + struct dc_state *context) +{ + int j; + + // Stream updates + for (j = 0; j < dc->res_pool->pipe_count; j++) { + struct pipe_ctx *pipe_ctx = &context->res_ctx.pipe_ctx[j]; + + if (!pipe_ctx->top_pipe && + pipe_ctx->stream && + pipe_ctx->stream == stream) { + + /* Fast update*/ + // VRR program can be done as part of FAST UPDATE + if (stream_update->adjust) + dc->hwss.set_drr(&pipe_ctx, 1, + stream_update->adjust->v_total_min, + stream_update->adjust->v_total_max); + + if (stream_update->periodic_fn_vsync_delta && + pipe_ctx->stream_res.tg && + 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->hdr_static_metadata && !stream->use_dynamic_meta) || + stream_update->vrr_infopacket || + stream_update->vsc_infopacket) { + resource_build_info_frame(pipe_ctx); + dc->hwss.update_info_frame(pipe_ctx); + } + + if (stream_update->gamut_remap) + dc_stream_set_gamut_remap(dc, stream); + + if (stream_update->output_csc_transform) + dc_stream_program_csc_matrix(dc, stream); + + /* Full fe update*/ + if (update_type == UPDATE_TYPE_FAST) + continue; + + if (stream_update->dpms_off) { + if (*stream_update->dpms_off) { + core_link_disable_stream(pipe_ctx, KEEP_ACQUIRED_RESOURCE); + dc->hwss.pplib_apply_display_requirements( + dc, dc->current_state); + notify_display_count_to_smu(dc, dc->current_state); + } else { + dc->hwss.pplib_apply_display_requirements( + dc, dc->current_state); + notify_display_count_to_smu(dc, dc->current_state); + core_link_enable_stream(dc->current_state, pipe_ctx); + } + } + + + + if (stream_update->abm_level && pipe_ctx->stream_res.abm) { + if (pipe_ctx->stream_res.tg->funcs->is_blanked) { + // if otg funcs defined check if blanked before programming + if (!pipe_ctx->stream_res.tg->funcs->is_blanked(pipe_ctx->stream_res.tg)) + pipe_ctx->stream_res.abm->funcs->set_abm_level( + pipe_ctx->stream_res.abm, stream->abm_level); + } else + pipe_ctx->stream_res.abm->funcs->set_abm_level( + pipe_ctx->stream_res.abm, stream->abm_level); + } + } + } +} static void commit_planes_for_stream(struct dc *dc, struct dc_surface_update *srf_updates, @@ -1327,16 +1491,20 @@ static void commit_planes_for_stream(struct dc *dc, context_clock_trace(dc, context); } + // Stream updates + if (stream_update) + commit_planes_do_stream_update(dc, stream, stream_update, update_type, context); + if (surface_count == 0) { /* * In case of turning off screen, no need to program front end a second time. - * just return after program front end. + * just return after program blank. */ - dc->hwss.apply_ctx_for_surface(dc, stream, surface_count, context); + dc->hwss.apply_ctx_for_surface(dc, stream, 0, context); return; } - /* Full fe update*/ + // Update Type FULL, Surface updates for (j = 0; j < dc->res_pool->pipe_count; j++) { struct pipe_ctx *pipe_ctx = &context->res_ctx.pipe_ctx[j]; @@ -1347,42 +1515,30 @@ static void commit_planes_for_stream(struct dc *dc, top_pipe_to_program = pipe_ctx; - if (update_type == UPDATE_TYPE_FAST || !pipe_ctx->plane_state) + if (!pipe_ctx->plane_state) + continue; + + /* Full fe update*/ + if (update_type == UPDATE_TYPE_FAST) continue; stream_status = - stream_get_status(context, pipe_ctx->stream); + stream_get_status(context, pipe_ctx->stream); dc->hwss.apply_ctx_for_surface( dc, pipe_ctx->stream, stream_status->plane_count, context); - - if (stream_update && stream_update->abm_level && pipe_ctx->stream_res.abm) { - if (pipe_ctx->stream_res.tg->funcs->is_blanked) { - // if otg funcs defined check if blanked before programming - if (!pipe_ctx->stream_res.tg->funcs->is_blanked(pipe_ctx->stream_res.tg)) - pipe_ctx->stream_res.abm->funcs->set_abm_level( - pipe_ctx->stream_res.abm, stream->abm_level); - } else - pipe_ctx->stream_res.abm->funcs->set_abm_level( - pipe_ctx->stream_res.abm, stream->abm_level); - } - - if (stream_update && 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 (update_type == UPDATE_TYPE_FULL) context_timing_trace(dc, &context->res_ctx); - /* Lock the top pipe while updating plane addrs, since freesync requires - * plane addr update event triggers to be synchronized. - * top_pipe_to_program is expected to never be NULL - */ + // Update Type FAST, Surface updates if (update_type == UPDATE_TYPE_FAST) { + /* Lock the top pipe while updating plane addrs, since freesync requires + * plane addr update event triggers to be synchronized. + * top_pipe_to_program is expected to never be NULL + */ dc->hwss.pipe_control_lock(dc, top_pipe_to_program, true); /* Perform requested Updates */ @@ -1405,20 +1561,6 @@ static void commit_planes_for_stream(struct dc *dc, dc->hwss.pipe_control_lock(dc, top_pipe_to_program, false); } - - 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]; - - if (pipe_ctx->stream != stream) - continue; - - 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, @@ -1554,9 +1696,7 @@ void dc_set_power_state( dc->hwss.init_hw(dc); break; default: - - dc->hwss.power_down(dc); - + ASSERT(dc->current_state->stream_count == 0); /* Zero out the current context so that on resume we start with * clean state, and dc hw programming optimizations will not * cause any trouble. @@ -1592,9 +1732,8 @@ bool dc_submit_i2c( struct dc_link *link = dc->links[link_index]; struct ddc_service *ddc = link->ddc; - - return dal_i2caux_submit_i2c_command( - ddc->ctx->i2caux, + return dce_i2c_submit_command( + dc->res_pool, ddc->ddc_pin, cmd); } @@ -1697,3 +1836,16 @@ void dc_link_remove_remote_sink(struct dc_link *link, struct dc_sink *sink) } } } + +void get_clock_requirements_for_state(struct dc_state *state, struct AsicStateEx *info) +{ + info->displayClock = (unsigned int)state->bw.dcn.clk.dispclk_khz; + info->engineClock = (unsigned int)state->bw.dcn.clk.dcfclk_khz; + info->memoryClock = (unsigned int)state->bw.dcn.clk.dramclk_khz; + info->maxSupportedDppClock = (unsigned int)state->bw.dcn.clk.max_supported_dppclk_khz; + info->dppClock = (unsigned int)state->bw.dcn.clk.dppclk_khz; + info->socClock = (unsigned int)state->bw.dcn.clk.socclk_khz; + info->dcfClockDeepSleep = (unsigned int)state->bw.dcn.clk.dcfclk_deep_sleep_khz; + info->fClock = (unsigned int)state->bw.dcn.clk.fclk_khz; + info->phyClock = (unsigned int)state->bw.dcn.clk.phyclk_khz; +}
\ No newline at end of file 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 fced3c1c2ef5..fb04a4ad141f 100644 --- a/drivers/gpu/drm/amd/display/dc/core/dc_link.c +++ b/drivers/gpu/drm/amd/display/dc/core/dc_link.c @@ -54,6 +54,9 @@ DC_LOG_HW_HOTPLUG( \ __VA_ARGS__) +#define RETIMER_REDRIVER_INFO(...) \ + DC_LOG_RETIMER_REDRIVER( \ + __VA_ARGS__) /******************************************************************************* * Private structures ******************************************************************************/ @@ -200,6 +203,11 @@ bool dc_link_detect_sink(struct dc_link *link, enum dc_connection_type *type) uint32_t is_hpd_high = 0; struct gpio *hpd_pin; + if (link->connector_signal == SIGNAL_TYPE_LVDS) { + *type = dc_connection_single; + return true; + } + /* todo: may need to lock gpio access */ hpd_pin = get_hpd_gpio(link->ctx->dc_bios, link->link_id, link->ctx->gpio_service); if (hpd_pin == NULL) @@ -613,6 +621,10 @@ bool dc_link_detect(struct dc_link *link, enum dc_detect_reason reason) link->local_sink) return true; + if (link->connector_signal == SIGNAL_TYPE_LVDS && + link->local_sink) + return true; + prev_sink = link->local_sink; if (prev_sink != NULL) { dc_sink_retain(prev_sink); @@ -646,6 +658,12 @@ bool dc_link_detect(struct dc_link *link, enum dc_detect_reason reason) break; } + case SIGNAL_TYPE_LVDS: { + sink_caps.transaction_type = DDC_TRANSACTION_TYPE_I2C; + sink_caps.signal = SIGNAL_TYPE_LVDS; + break; + } + case SIGNAL_TYPE_EDP: { detect_edp_sink_caps(link); sink_caps.transaction_type = @@ -872,6 +890,24 @@ bool dc_link_detect(struct dc_link *link, enum dc_detect_reason reason) return true; } +bool dc_link_get_hpd_state(struct dc_link *dc_link) +{ + struct gpio *hpd_pin; + uint32_t state; + + hpd_pin = get_hpd_gpio(dc_link->ctx->dc_bios, + dc_link->link_id, dc_link->ctx->gpio_service); + if (hpd_pin == NULL) + ASSERT(false); + + dal_gpio_open(hpd_pin, GPIO_MODE_INTERRUPT); + dal_gpio_get_value(hpd_pin, &state); + dal_gpio_close(hpd_pin); + dal_gpio_destroy_irq(&hpd_pin); + + return state; +} + static enum hpd_source_id get_hpd_line( struct dc_link *link) { @@ -1088,6 +1124,9 @@ static bool construct( dal_irq_get_rx_source(hpd_gpio); } break; + case CONNECTOR_ID_LVDS: + link->connector_signal = SIGNAL_TYPE_LVDS; + break; default: DC_LOG_WARNING("Unsupported Connector type:%d!\n", link->link_id.id); goto create_fail; @@ -1531,8 +1570,8 @@ static bool i2c_write(struct pipe_ctx *pipe_ctx, payload.write = true; cmd.payloads = &payload; - if (dc_submit_i2c(pipe_ctx->stream->ctx->dc, - pipe_ctx->stream->sink->link->link_index, &cmd)) + if (dm_helpers_submit_i2c(pipe_ctx->stream->ctx, + pipe_ctx->stream->sink->link, &cmd)) return true; return false; @@ -1551,6 +1590,7 @@ static void write_i2c_retimer_setting( uint8_t value = 0; int i = 0; bool i2c_success = false; + DC_LOGGER_INIT(pipe_ctx->stream->ctx->logger); memset(&buffer, 0, sizeof(buffer)); @@ -1564,6 +1604,9 @@ static void write_i2c_retimer_setting( buffer[1] = settings->reg_settings[i].i2c_reg_val; i2c_success = i2c_write(pipe_ctx, slave_address, buffer, sizeof(buffer)); + RETIMER_REDRIVER_INFO("retimer write to slave_address = 0x%x,\ + offset = 0x%x, reg_val= 0x%x, i2c_success = %d\n", + slave_address, buffer[0], buffer[1], i2c_success?1:0); if (!i2c_success) /* Write failure */ @@ -1594,6 +1637,9 @@ static void write_i2c_retimer_setting( buffer[1] = value | apply_rx_tx_change; i2c_success = i2c_write(pipe_ctx, slave_address, buffer, sizeof(buffer)); + RETIMER_REDRIVER_INFO("retimer write to slave_address = 0x%x,\ + offset = 0x%x, reg_val = 0x%x, i2c_success = %d\n", + slave_address, buffer[0], buffer[1], i2c_success?1:0); if (!i2c_success) /* Write failure */ ASSERT(i2c_success); @@ -1611,6 +1657,9 @@ static void write_i2c_retimer_setting( buffer[1] = settings->reg_settings_6g[i].i2c_reg_val; i2c_success = i2c_write(pipe_ctx, slave_address, buffer, sizeof(buffer)); + RETIMER_REDRIVER_INFO("above 340Mhz: retimer write to slave_address = 0x%x,\ + offset = 0x%x, reg_val = 0x%x, i2c_success = %d\n", + slave_address, buffer[0], buffer[1], i2c_success?1:0); if (!i2c_success) /* Write failure */ @@ -1641,6 +1690,9 @@ static void write_i2c_retimer_setting( buffer[1] = value | apply_rx_tx_change; i2c_success = i2c_write(pipe_ctx, slave_address, buffer, sizeof(buffer)); + RETIMER_REDRIVER_INFO("retimer write to slave_address = 0x%x,\ + offset = 0x%x, reg_val = 0x%x, i2c_success = %d\n", + slave_address, buffer[0], buffer[1], i2c_success?1:0); if (!i2c_success) /* Write failure */ ASSERT(i2c_success); @@ -1657,6 +1709,9 @@ static void write_i2c_retimer_setting( buffer[1] = 0x01; i2c_success = i2c_write(pipe_ctx, slave_address, buffer, sizeof(buffer)); + RETIMER_REDRIVER_INFO("retimer write to slave_address = 0x%x,\ + offset = 0x%x, reg_val = 0x%x, i2c_success = %d\n", + slave_address, buffer[0], buffer[1], i2c_success?1:0); if (!i2c_success) /* Write failure */ ASSERT(i2c_success); @@ -1666,6 +1721,9 @@ static void write_i2c_retimer_setting( buffer[1] = 0x23; i2c_success = i2c_write(pipe_ctx, slave_address, buffer, sizeof(buffer)); + RETIMER_REDRIVER_INFO("retimer write to slave_address = 0x%x,\ + offset = 0x%d, reg_val = 0x%d, i2c_success = %d\n", + slave_address, buffer[0], buffer[1], i2c_success?1:0); if (!i2c_success) /* Write failure */ ASSERT(i2c_success); @@ -1675,6 +1733,9 @@ static void write_i2c_retimer_setting( buffer[1] = 0x00; i2c_success = i2c_write(pipe_ctx, slave_address, buffer, sizeof(buffer)); + RETIMER_REDRIVER_INFO("retimer write to slave_address = 0x%x,\ + offset = 0x%d, reg_val = 0x%d, i2c_success = %d\n", + slave_address, buffer[0], buffer[1], i2c_success?1:0); if (!i2c_success) /* Write failure */ ASSERT(i2c_success); @@ -1690,6 +1751,7 @@ static void write_i2c_default_retimer_setting( uint8_t slave_address = (0xBA >> 1); uint8_t buffer[2]; bool i2c_success = false; + DC_LOGGER_INIT(pipe_ctx->stream->ctx->logger); memset(&buffer, 0, sizeof(buffer)); @@ -1699,6 +1761,9 @@ static void write_i2c_default_retimer_setting( buffer[1] = 0x13; i2c_success = i2c_write(pipe_ctx, slave_address, buffer, sizeof(buffer)); + RETIMER_REDRIVER_INFO("retimer writes default setting to slave_address = 0x%x,\ + offset = 0x%x, reg_val = 0x%x, i2c_success = %d\n", + slave_address, buffer[0], buffer[1], i2c_success?1:0); if (!i2c_success) /* Write failure */ ASSERT(i2c_success); @@ -1708,6 +1773,9 @@ static void write_i2c_default_retimer_setting( buffer[1] = 0x17; i2c_success = i2c_write(pipe_ctx, slave_address, buffer, sizeof(buffer)); + RETIMER_REDRIVER_INFO("retimer write to slave_addr = 0x%x,\ + offset = 0x%x, reg_val = 0x%x, i2c_success = %d\n", + slave_address, buffer[0], buffer[1], i2c_success?1:0); if (!i2c_success) /* Write failure */ ASSERT(i2c_success); @@ -1717,6 +1785,9 @@ static void write_i2c_default_retimer_setting( buffer[1] = is_over_340mhz ? 0xDA : 0xD8; i2c_success = i2c_write(pipe_ctx, slave_address, buffer, sizeof(buffer)); + RETIMER_REDRIVER_INFO("retimer write to slave_addr = 0x%x,\ + offset = 0x%x, reg_val = 0x%x, i2c_success = %d\n", + slave_address, buffer[0], buffer[1], i2c_success?1:0); if (!i2c_success) /* Write failure */ ASSERT(i2c_success); @@ -1726,6 +1797,9 @@ static void write_i2c_default_retimer_setting( buffer[1] = 0x17; i2c_success = i2c_write(pipe_ctx, slave_address, buffer, sizeof(buffer)); + RETIMER_REDRIVER_INFO("retimer write to slave_addr = 0x%x,\ + offset = 0x%x, reg_val= 0x%x, i2c_success = %d\n", + slave_address, buffer[0], buffer[1], i2c_success?1:0); if (!i2c_success) /* Write failure */ ASSERT(i2c_success); @@ -1735,6 +1809,9 @@ static void write_i2c_default_retimer_setting( buffer[1] = is_over_340mhz ? 0x1D : 0x91; i2c_success = i2c_write(pipe_ctx, slave_address, buffer, sizeof(buffer)); + RETIMER_REDRIVER_INFO("retimer write to slave_addr = 0x%x,\ + offset = 0x%x, reg_val = 0x%x, i2c_success = %d\n", + slave_address, buffer[0], buffer[1], i2c_success?1:0); if (!i2c_success) /* Write failure */ ASSERT(i2c_success); @@ -1744,6 +1821,9 @@ static void write_i2c_default_retimer_setting( buffer[1] = 0x17; i2c_success = i2c_write(pipe_ctx, slave_address, buffer, sizeof(buffer)); + RETIMER_REDRIVER_INFO("retimer write to slave_addr = 0x%x,\ + offset = 0x%x, reg_val = 0x%x, i2c_success = %d\n", + slave_address, buffer[0], buffer[1], i2c_success?1:0); if (!i2c_success) /* Write failure */ ASSERT(i2c_success); @@ -1757,6 +1837,9 @@ static void write_i2c_default_retimer_setting( buffer[1] = 0x01; i2c_success = i2c_write(pipe_ctx, slave_address, buffer, sizeof(buffer)); + RETIMER_REDRIVER_INFO("retimer write to slave_addr = 0x%x,\ + offset = 0x%x, reg_val = 0x%x, i2c_success = %d\n", + slave_address, buffer[0], buffer[1], i2c_success?1:0); if (!i2c_success) /* Write failure */ ASSERT(i2c_success); @@ -1766,6 +1849,9 @@ static void write_i2c_default_retimer_setting( buffer[1] = 0x23; i2c_success = i2c_write(pipe_ctx, slave_address, buffer, sizeof(buffer)); + RETIMER_REDRIVER_INFO("retimer write to slave_addr = 0x%x,\ + offset = 0x%x, reg_val= 0x%x, i2c_success = %d\n", + slave_address, buffer[0], buffer[1], i2c_success?1:0); if (!i2c_success) /* Write failure */ ASSERT(i2c_success); @@ -1775,6 +1861,9 @@ static void write_i2c_default_retimer_setting( buffer[1] = 0x00; i2c_success = i2c_write(pipe_ctx, slave_address, buffer, sizeof(buffer)); + RETIMER_REDRIVER_INFO("retimer write default setting to slave_addr = 0x%x,\ + offset = 0x%x, reg_val= 0x%x, i2c_success = %d end here\n", + slave_address, buffer[0], buffer[1], i2c_success?1:0); if (!i2c_success) /* Write failure */ ASSERT(i2c_success); @@ -1788,6 +1877,7 @@ static void write_i2c_redriver_setting( uint8_t slave_address = (0xF0 >> 1); uint8_t buffer[16]; bool i2c_success = false; + DC_LOGGER_INIT(pipe_ctx->stream->ctx->logger); memset(&buffer, 0, sizeof(buffer)); @@ -1799,6 +1889,11 @@ static void write_i2c_redriver_setting( i2c_success = i2c_write(pipe_ctx, slave_address, buffer, sizeof(buffer)); + RETIMER_REDRIVER_INFO("redriver write 0 to all 16 reg offset expect following:\n\ + \t slave_addr = 0x%x, offset[3] = 0x%x, offset[4] = 0x%x,\ + offset[5] = 0x%x,offset[6] is_over_340mhz = 0x%x,\ + i2c_success = %d\n", + slave_address, buffer[3], buffer[4], buffer[5], buffer[6], i2c_success?1:0); if (!i2c_success) /* Write failure */ @@ -1865,6 +1960,24 @@ static void enable_link_hdmi(struct pipe_ctx *pipe_ctx) dal_ddc_service_read_scdc_data(link->ddc); } +static void enable_link_lvds(struct pipe_ctx *pipe_ctx) +{ + struct dc_stream_state *stream = pipe_ctx->stream; + struct dc_link *link = stream->sink->link; + + if (stream->phy_pix_clk == 0) + stream->phy_pix_clk = stream->timing.pix_clk_khz; + + memset(&stream->sink->link->cur_link_settings, 0, + sizeof(struct dc_link_settings)); + + link->link_enc->funcs->enable_lvds_output( + link->link_enc, + pipe_ctx->clock_source->id, + stream->phy_pix_clk); + +} + /****************************enable_link***********************************/ static enum dc_status enable_link( struct dc_state *state, @@ -1888,6 +2001,10 @@ static enum dc_status enable_link( enable_link_hdmi(pipe_ctx); status = DC_OK; break; + case SIGNAL_TYPE_LVDS: + enable_link_lvds(pipe_ctx); + status = DC_OK; + break; case SIGNAL_TYPE_VIRTUAL: status = DC_OK; break; @@ -2403,23 +2520,63 @@ void core_link_enable_stream( struct pipe_ctx *pipe_ctx) { struct dc *core_dc = pipe_ctx->stream->ctx->dc; + struct dc_stream_state *stream = pipe_ctx->stream; enum dc_status status; DC_LOGGER_INIT(pipe_ctx->stream->ctx->logger); - /* eDP lit up by bios already, no need to enable again. */ - if (pipe_ctx->stream->signal == SIGNAL_TYPE_EDP && - core_dc->apply_edp_fast_boot_optimization) { - core_dc->apply_edp_fast_boot_optimization = false; - pipe_ctx->stream->dpms_off = false; - return; + if (pipe_ctx->stream->signal != SIGNAL_TYPE_VIRTUAL) { + stream->sink->link->link_enc->funcs->setup( + stream->sink->link->link_enc, + pipe_ctx->stream->signal); + pipe_ctx->stream_res.stream_enc->funcs->setup_stereo_sync( + pipe_ctx->stream_res.stream_enc, + pipe_ctx->stream_res.tg->inst, + stream->timing.timing_3d_format != TIMING_3D_FORMAT_NONE); } - if (pipe_ctx->stream->dpms_off) - return; + if (dc_is_dp_signal(pipe_ctx->stream->signal)) + pipe_ctx->stream_res.stream_enc->funcs->dp_set_stream_attribute( + pipe_ctx->stream_res.stream_enc, + &stream->timing, + stream->output_color_space); + + if (dc_is_hdmi_signal(pipe_ctx->stream->signal)) + pipe_ctx->stream_res.stream_enc->funcs->hdmi_set_stream_attribute( + pipe_ctx->stream_res.stream_enc, + &stream->timing, + stream->phy_pix_clk, + pipe_ctx->stream_res.audio != NULL); + + if (dc_is_dvi_signal(pipe_ctx->stream->signal)) + pipe_ctx->stream_res.stream_enc->funcs->dvi_set_stream_attribute( + pipe_ctx->stream_res.stream_enc, + &stream->timing, + (pipe_ctx->stream->signal == SIGNAL_TYPE_DVI_DUAL_LINK) ? + true : false); + + if (dc_is_lvds_signal(pipe_ctx->stream->signal)) + pipe_ctx->stream_res.stream_enc->funcs->lvds_set_stream_attribute( + pipe_ctx->stream_res.stream_enc, + &stream->timing); + + if (!IS_FPGA_MAXIMUS_DC(core_dc->ctx->dce_environment)) { + resource_build_info_frame(pipe_ctx); + core_dc->hwss.update_info_frame(pipe_ctx); + + /* eDP lit up by bios already, no need to enable again. */ + if (pipe_ctx->stream->signal == SIGNAL_TYPE_EDP && + pipe_ctx->stream->apply_edp_fast_boot_optimization) { + pipe_ctx->stream->apply_edp_fast_boot_optimization = false; + pipe_ctx->stream->dpms_off = false; + return; + } - status = enable_link(state, pipe_ctx); + if (pipe_ctx->stream->dpms_off) + return; - if (status != DC_OK) { + status = enable_link(state, pipe_ctx); + + if (status != DC_OK) { DC_LOG_WARNING("enabling link %u failed: %d\n", pipe_ctx->stream->sink->link->link_index, status); @@ -2434,23 +2591,26 @@ void core_link_enable_stream( BREAK_TO_DEBUGGER(); return; } - } + } - core_dc->hwss.enable_audio_stream(pipe_ctx); + core_dc->hwss.enable_audio_stream(pipe_ctx); - /* turn off otg test pattern if enable */ - if (pipe_ctx->stream_res.tg->funcs->set_test_pattern) - pipe_ctx->stream_res.tg->funcs->set_test_pattern(pipe_ctx->stream_res.tg, - CONTROLLER_DP_TEST_PATTERN_VIDEOMODE, - COLOR_DEPTH_UNDEFINED); + /* turn off otg test pattern if enable */ + if (pipe_ctx->stream_res.tg->funcs->set_test_pattern) + pipe_ctx->stream_res.tg->funcs->set_test_pattern(pipe_ctx->stream_res.tg, + CONTROLLER_DP_TEST_PATTERN_VIDEOMODE, + COLOR_DEPTH_UNDEFINED); - core_dc->hwss.enable_stream(pipe_ctx); + core_dc->hwss.enable_stream(pipe_ctx); - if (pipe_ctx->stream->signal == SIGNAL_TYPE_DISPLAY_PORT_MST) - allocate_mst_payload(pipe_ctx); + if (pipe_ctx->stream->signal == SIGNAL_TYPE_DISPLAY_PORT_MST) + allocate_mst_payload(pipe_ctx); + + core_dc->hwss.unblank_stream(pipe_ctx, + &pipe_ctx->stream->sink->link->cur_link_settings); + + } - core_dc->hwss.unblank_stream(pipe_ctx, - &pipe_ctx->stream->sink->link->cur_link_settings); } void core_link_disable_stream(struct pipe_ctx *pipe_ctx, int option) diff --git a/drivers/gpu/drm/amd/display/dc/core/dc_link_ddc.c b/drivers/gpu/drm/amd/display/dc/core/dc_link_ddc.c index 8def0d9fa0ff..506a97e16956 100644 --- a/drivers/gpu/drm/amd/display/dc/core/dc_link_ddc.c +++ b/drivers/gpu/drm/amd/display/dc/core/dc_link_ddc.c @@ -666,13 +666,9 @@ int dc_link_aux_transfer(struct ddc_service *ddc, switch (operation_result) { case AUX_CHANNEL_OPERATION_SUCCEEDED: - res = returned_bytes; - - if (res <= size && res >= 0) - res = aux_engine->funcs->read_channel_reply(aux_engine, size, - buffer, reply, - &status); - + res = aux_engine->funcs->read_channel_reply(aux_engine, size, + buffer, reply, + &status); break; case AUX_CHANNEL_OPERATION_FAILED_HPD_DISCON: res = 0; 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 a7553b6d59c2..d91df5ef0cb3 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 @@ -2389,6 +2389,9 @@ static bool retrieve_link_cap(struct dc_link *link) dp_wa_power_up_0010FA(link, dpcd_data, sizeof(dpcd_data)); + down_strm_port_count.raw = dpcd_data[DP_DOWN_STREAM_PORT_COUNT - + DP_DPCD_REV]; + link->dpcd_caps.allow_invalid_MSA_timing_param = down_strm_port_count.bits.IGNORE_MSA_TIMING_PARAM; 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 ea6beccfd89d..b6fe29b9fb65 100644 --- a/drivers/gpu/drm/amd/display/dc/core/dc_resource.c +++ b/drivers/gpu/drm/amd/display/dc/core/dc_resource.c @@ -88,6 +88,10 @@ enum dce_version resource_parse_asic_id(struct hw_asic_id asic_id) #if defined(CONFIG_DRM_AMD_DC_DCN1_0) case FAMILY_RV: dc_version = DCN_VERSION_1_0; +#if defined(CONFIG_DRM_AMD_DC_DCN1_01) + if (ASICREV_IS_RAVEN2(asic_id.hw_internal_rev)) + dc_version = DCN_VERSION_1_01; +#endif break; #endif default: @@ -138,6 +142,9 @@ struct resource_pool *dc_create_resource_pool( #if defined(CONFIG_DRM_AMD_DC_DCN1_0) case DCN_VERSION_1_0: +#if defined(CONFIG_DRM_AMD_DC_DCN1_01) + case DCN_VERSION_1_01: +#endif res_pool = dcn10_create_resource_pool( num_virtual_links, dc); break; @@ -356,6 +363,9 @@ bool resource_are_streams_timing_synchronizable( || !dc_is_dp_signal(stream2->signal))) return false; + if (stream1->view_format != stream2->view_format) + return false; + return true; } static bool is_dp_and_hdmi_sharable( @@ -366,8 +376,8 @@ static bool is_dp_and_hdmi_sharable( return false; if (stream1->clamping.c_depth != COLOR_DEPTH_888 || - stream2->clamping.c_depth != COLOR_DEPTH_888) - return false; + stream2->clamping.c_depth != COLOR_DEPTH_888) + return false; return true; @@ -487,6 +497,18 @@ static void calculate_viewport(struct pipe_ctx *pipe_ctx) 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 flip_vert_scan_dir = false, flip_horz_scan_dir = false; + + /* + * Need to calculate the scan direction for viewport to properly determine offset + */ + 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 (stream->view_format == VIEW_3D_FORMAT_SIDE_BY_SIDE || stream->view_format == VIEW_3D_FORMAT_TOP_AND_BOTTOM) { @@ -530,6 +552,34 @@ static void calculate_viewport(struct pipe_ctx *pipe_ctx) data->viewport.height = clip.height * surf_src.height / plane_state->dst_rect.height; + /* To transfer the x, y to correct coordinate on mirror image (camera). + * deg 0 : transfer x, + * deg 90 : don't need to transfer, + * deg180 : transfer y, + * deg270 : transfer x and y. + * To transfer the x, y to correct coordinate on non-mirror image (video). + * deg 0 : don't need to transfer, + * deg 90 : transfer y, + * deg180 : transfer x and y, + * deg270 : transfer x. + */ + if (pipe_ctx->plane_state->horizontal_mirror) { + if (flip_horz_scan_dir && !flip_vert_scan_dir) { + data->viewport.y = surf_src.height - data->viewport.y - data->viewport.height; + data->viewport.x = surf_src.width - data->viewport.x - data->viewport.width; + } else if (flip_horz_scan_dir && flip_vert_scan_dir) + data->viewport.y = surf_src.height - data->viewport.y - data->viewport.height; + else { + if (!flip_horz_scan_dir && !flip_vert_scan_dir) + data->viewport.x = surf_src.width - data->viewport.x - data->viewport.width; + } + } else { + if (flip_horz_scan_dir) + data->viewport.x = surf_src.width - data->viewport.x - data->viewport.width; + if (flip_vert_scan_dir) + data->viewport.y = surf_src.height - data->viewport.y - data->viewport.height; + } + /* Round down, compensate in init */ data->viewport_c.x = data->viewport.x / vpc_div; data->viewport_c.y = data->viewport.y / vpc_div; @@ -549,8 +599,10 @@ static void calculate_viewport(struct pipe_ctx *pipe_ctx) 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 (data->viewport.width > 1) + data->viewport.width /= 2; + if (data->viewport_c.width > 1) + data->viewport_c.width /= 2; } if (plane_state->rotation == ROTATION_ANGLE_90 || @@ -630,7 +682,8 @@ static void calculate_recout(struct pipe_ctx *pipe_ctx, struct rect *recout_full 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.width /= 2; + if (pipe_ctx->plane_res.scl_data.recout.width > 1) + pipe_ctx->plane_res.scl_data.recout.width /= 2; } } /* Unclipped recout offset = stream dst offset + ((surf dst offset - stream surf_src offset) @@ -725,6 +778,15 @@ static void calculate_inits_and_adj_vp(struct pipe_ctx *pipe_ctx, struct rect *r rect_swap_helper(&src); rect_swap_helper(&data->viewport_c); rect_swap_helper(&data->viewport); + + if (pipe_ctx->plane_state->rotation == ROTATION_ANGLE_270 && + pipe_ctx->plane_state->horizontal_mirror) { + flip_vert_scan_dir = true; + } + if (pipe_ctx->plane_state->rotation == ROTATION_ANGLE_90 && + pipe_ctx->plane_state->horizontal_mirror) { + flip_vert_scan_dir = false; + } } else if (pipe_ctx->plane_state->horizontal_mirror) flip_horz_scan_dir = !flip_horz_scan_dir; @@ -1526,6 +1588,20 @@ static bool is_hdr_static_meta_changed(struct dc_stream_state *cur_stream, return false; } +static bool is_vsc_info_packet_changed(struct dc_stream_state *cur_stream, + struct dc_stream_state *new_stream) +{ + if (cur_stream == NULL) + return true; + + if (memcmp(&cur_stream->vsc_infopacket, + &new_stream->vsc_infopacket, + sizeof(struct dc_info_packet)) != 0) + return true; + + return false; +} + static bool is_timing_changed(struct dc_stream_state *cur_stream, struct dc_stream_state *new_stream) { @@ -1563,6 +1639,12 @@ static bool are_stream_backends_same( if (is_hdr_static_meta_changed(stream_a, stream_b)) return false; + if (stream_a->dpms_off != stream_b->dpms_off) + return false; + + if (is_vsc_info_packet_changed(stream_a, stream_b)) + return false; + return true; } @@ -1690,7 +1772,7 @@ static struct stream_encoder *find_first_free_match_stream_enc_for_link( * required for non DP connectors. */ - if (j >= 0 && dc_is_dp_signal(stream->signal)) + if (j >= 0 && link->connector_signal == SIGNAL_TYPE_DISPLAY_PORT) return pool->stream_enc[j]; return NULL; @@ -1893,6 +1975,9 @@ static void calculate_phy_pix_clks(struct dc_stream_state *stream) else stream->phy_pix_clk = stream->timing.pix_clk_khz; + + if (stream->timing.timing_3d_format == TIMING_3D_FORMAT_HW_FRAME_PACKING) + stream->phy_pix_clk *= 2; } enum dc_status resource_map_pool_resources( @@ -2014,6 +2099,14 @@ enum dc_status dc_validate_global_state( if (pipe_ctx->stream != stream) continue; + if (dc->res_pool->funcs->get_default_swizzle_mode && + pipe_ctx->plane_state && + pipe_ctx->plane_state->tiling_info.gfx9.swizzle == DC_SW_UNKNOWN) { + result = dc->res_pool->funcs->get_default_swizzle_mode(pipe_ctx->plane_state); + if (result != DC_OK) + return result; + } + /* Switch to dp clock source only if there is * no non dp stream that shares the same timing * with the dp stream. @@ -2423,119 +2516,13 @@ static void set_spd_info_packet( { /* SPD info packet for FreeSync */ - unsigned char checksum = 0; - unsigned int idx, payload_size = 0; - /* Check if Freesync is supported. Return if false. If true, * set the corresponding bit in the info packet */ - if (stream->freesync_ctx.supported == false) + if (!stream->vrr_infopacket.valid) return; - if (dc_is_hdmi_signal(stream->signal)) { - - /* HEADER */ - - /* HB0 = Packet Type = 0x83 (Source Product - * Descriptor InfoFrame) - */ - info_packet->hb0 = HDMI_INFOFRAME_TYPE_SPD; - - /* HB1 = Version = 0x01 */ - info_packet->hb1 = 0x01; - - /* HB2 = [Bits 7:5 = 0] [Bits 4:0 = Length = 0x08] */ - info_packet->hb2 = 0x08; - - payload_size = 0x08; - - } else if (dc_is_dp_signal(stream->signal)) { - - /* HEADER */ - - /* HB0 = Secondary-data Packet ID = 0 - Only non-zero - * when used to associate audio related info packets - */ - info_packet->hb0 = 0x00; - - /* HB1 = Packet Type = 0x83 (Source Product - * Descriptor InfoFrame) - */ - info_packet->hb1 = HDMI_INFOFRAME_TYPE_SPD; - - /* HB2 = [Bits 7:0 = Least significant eight bits - - * For INFOFRAME, the value must be 1Bh] - */ - info_packet->hb2 = 0x1B; - - /* HB3 = [Bits 7:2 = INFOFRAME SDP Version Number = 0x1] - * [Bits 1:0 = Most significant two bits = 0x00] - */ - info_packet->hb3 = 0x04; - - payload_size = 0x1B; - } - - /* PB1 = 0x1A (24bit AMD IEEE OUI (0x00001A) - Byte 0) */ - info_packet->sb[1] = 0x1A; - - /* PB2 = 0x00 (24bit AMD IEEE OUI (0x00001A) - Byte 1) */ - info_packet->sb[2] = 0x00; - - /* PB3 = 0x00 (24bit AMD IEEE OUI (0x00001A) - Byte 2) */ - info_packet->sb[3] = 0x00; - - /* PB4 = Reserved */ - info_packet->sb[4] = 0x00; - - /* PB5 = Reserved */ - info_packet->sb[5] = 0x00; - - /* PB6 = [Bits 7:3 = Reserved] */ - info_packet->sb[6] = 0x00; - - if (stream->freesync_ctx.supported == true) - /* PB6 = [Bit 0 = FreeSync Supported] */ - info_packet->sb[6] |= 0x01; - - if (stream->freesync_ctx.enabled == true) - /* PB6 = [Bit 1 = FreeSync Enabled] */ - info_packet->sb[6] |= 0x02; - - if (stream->freesync_ctx.active == true) - /* PB6 = [Bit 2 = FreeSync Active] */ - info_packet->sb[6] |= 0x04; - - /* PB7 = FreeSync Minimum refresh rate (Hz) */ - info_packet->sb[7] = (unsigned char) (stream->freesync_ctx. - min_refresh_in_micro_hz / 1000000); - - /* PB8 = FreeSync Maximum refresh rate (Hz) - * - * Note: We do not use the maximum capable refresh rate - * of the panel, because we should never go above the field - * rate of the mode timing set. - */ - info_packet->sb[8] = (unsigned char) (stream->freesync_ctx. - nominal_refresh_in_micro_hz / 1000000); - - /* PB9 - PB27 = Reserved */ - for (idx = 9; idx <= 27; idx++) - info_packet->sb[idx] = 0x00; - - /* Calculate checksum */ - checksum += info_packet->hb0; - checksum += info_packet->hb1; - checksum += info_packet->hb2; - checksum += info_packet->hb3; - - for (idx = 1; idx <= payload_size; idx++) - checksum += info_packet->sb[idx]; - - /* PB0 = Checksum (one byte complement) */ - info_packet->sb[0] = (unsigned char) (0x100 - checksum); - - info_packet->valid = true; + *info_packet = stream->vrr_infopacket; } static void set_hdr_static_info_packet( @@ -2555,43 +2542,10 @@ static void set_vsc_info_packet( struct dc_info_packet *info_packet, struct dc_stream_state *stream) { - unsigned int vscPacketRevision = 0; - unsigned int i; - - /*VSC packet set to 2 when DP revision >= 1.2*/ - if (stream->psr_version != 0) { - vscPacketRevision = 2; - } - - /* VSC packet not needed based on the features - * supported by this DP display - */ - if (vscPacketRevision == 0) + if (!stream->vsc_infopacket.valid) return; - if (vscPacketRevision == 0x2) { - /* Secondary-data Packet ID = 0*/ - info_packet->hb0 = 0x00; - /* 07h - Packet Type Value indicating Video - * Stream Configuration packet - */ - info_packet->hb1 = 0x07; - /* 02h = VSC SDP supporting 3D stereo and PSR - * (applies to eDP v1.3 or higher). - */ - info_packet->hb2 = 0x02; - /* 08h = VSC packet supporting 3D stereo + PSR - * (HB2 = 02h). - */ - info_packet->hb3 = 0x08; - - for (i = 0; i < 28; i++) - info_packet->sb[i] = 0; - - info_packet->valid = true; - } - - /*TODO: stereo 3D support and extend pixel encoding colorimetry*/ + *info_packet = stream->vsc_infopacket; } void dc_resource_state_destruct(struct dc_state *context) @@ -2770,6 +2724,12 @@ bool pipe_need_reprogram( if (is_hdr_static_meta_changed(pipe_ctx_old->stream, pipe_ctx->stream)) return true; + if (pipe_ctx_old->stream->dpms_off != pipe_ctx->stream->dpms_off) + return true; + + if (is_vsc_info_packet_changed(pipe_ctx_old->stream, pipe_ctx->stream)) + return true; + return false; } @@ -2936,3 +2896,32 @@ enum dc_status dc_validate_plane(struct dc *dc, const struct dc_plane_state *pla return res; } + +unsigned int resource_pixel_format_to_bpp(enum surface_pixel_format format) +{ + switch (format) { + case SURFACE_PIXEL_FORMAT_GRPH_PALETA_256_COLORS: + return 8; + case SURFACE_PIXEL_FORMAT_VIDEO_420_YCbCr: + case SURFACE_PIXEL_FORMAT_VIDEO_420_YCrCb: + return 12; + case SURFACE_PIXEL_FORMAT_GRPH_ARGB1555: + case SURFACE_PIXEL_FORMAT_GRPH_RGB565: + case SURFACE_PIXEL_FORMAT_VIDEO_420_10bpc_YCbCr: + case SURFACE_PIXEL_FORMAT_VIDEO_420_10bpc_YCrCb: + return 16; + case SURFACE_PIXEL_FORMAT_GRPH_ARGB8888: + case SURFACE_PIXEL_FORMAT_GRPH_ABGR8888: + case SURFACE_PIXEL_FORMAT_GRPH_ARGB2101010: + case SURFACE_PIXEL_FORMAT_GRPH_ABGR2101010: + case SURFACE_PIXEL_FORMAT_GRPH_ABGR2101010_XR_BIAS: + return 32; + case SURFACE_PIXEL_FORMAT_GRPH_ARGB16161616: + case SURFACE_PIXEL_FORMAT_GRPH_ARGB16161616F: + case SURFACE_PIXEL_FORMAT_GRPH_ABGR16161616F: + return 64; + default: + ASSERT_CRITICAL(false); + return -1; + } +} 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 fdcc8ab19bf3..2ac848a106ba 100644 --- a/drivers/gpu/drm/amd/display/dc/core/dc_stream.c +++ b/drivers/gpu/drm/amd/display/dc/core/dc_stream.c @@ -205,8 +205,6 @@ bool dc_stream_set_cursor_attributes( if (pipe_ctx->stream != stream) continue; - if (pipe_ctx->top_pipe && pipe_ctx->plane_state != pipe_ctx->top_pipe->plane_state) - continue; if (!pipe_to_program) { pipe_to_program = pipe_ctx; |