diff options
Diffstat (limited to 'drivers/gpu/drm/amd/display')
43 files changed, 1022 insertions, 573 deletions
diff --git a/drivers/gpu/drm/amd/display/Kconfig b/drivers/gpu/drm/amd/display/Kconfig index d5d4586e6176..4c35625eb2c7 100644 --- a/drivers/gpu/drm/amd/display/Kconfig +++ b/drivers/gpu/drm/amd/display/Kconfig @@ -9,19 +9,10 @@ config DRM_AMD_DC support for AMDGPU. This adds required support for Vega and Raven ASICs. -config DRM_AMD_DC_FBC - bool "AMD FBC - Enable Frame Buffer Compression" - depends on DRM_AMD_DC - help - Choose this option if you want to use frame buffer compression - support. - This is a power optimisation feature, check its availability - on your hardware before enabling this option. - - config DRM_AMD_DC_DCN1_0 bool "DCN 1.0 Raven family" depends on DRM_AMD_DC && X86 + default y help Choose this option if you want to have RV family for display engine diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c index a1dd49545a5b..655950102827 100644 --- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c +++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c @@ -347,7 +347,6 @@ static void hotplug_notify_work_func(struct work_struct *work) drm_kms_helper_hotplug_event(dev); } -#if defined(CONFIG_DRM_AMD_DC_FBC) /* Allocate memory for FBC compressed data */ static void amdgpu_dm_fbc_init(struct drm_connector *connector) { @@ -388,7 +387,6 @@ static void amdgpu_dm_fbc_init(struct drm_connector *connector) } } -#endif /* Init display KMS @@ -3426,12 +3424,15 @@ static int amdgpu_dm_connector_get_modes(struct drm_connector *connector) struct edid *edid = amdgpu_dm_connector->edid; encoder = helper->best_encoder(connector); - amdgpu_dm_connector_ddc_get_modes(connector, edid); - amdgpu_dm_connector_add_common_modes(encoder, connector); -#if defined(CONFIG_DRM_AMD_DC_FBC) + if (!edid || !drm_edid_is_valid(edid)) { + drm_add_modes_noedid(connector, 640, 480); + } else { + amdgpu_dm_connector_ddc_get_modes(connector, edid); + amdgpu_dm_connector_add_common_modes(encoder, connector); + } amdgpu_dm_fbc_init(connector); -#endif + return amdgpu_dm_connector->num_modes; } diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.h b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.h index d5aa89ad5571..a29dc35954c9 100644 --- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.h +++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.h @@ -72,13 +72,11 @@ struct irq_list_head { struct work_struct work; }; -#if defined(CONFIG_DRM_AMD_DC_FBC) struct dm_comressor_info { void *cpu_addr; struct amdgpu_bo *bo_ptr; uint64_t gpu_addr; }; -#endif struct amdgpu_display_manager { @@ -129,9 +127,8 @@ struct amdgpu_display_manager { * Caches device atomic state for suspend/resume */ struct drm_atomic_state *cached_state; -#if defined(CONFIG_DRM_AMD_DC_FBC) + struct dm_comressor_info compressor; -#endif }; struct amdgpu_dm_connector { diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_helpers.c b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_helpers.c index ec304b1a5973..b19dc4cfc030 100644 --- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_helpers.c +++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_helpers.c @@ -497,6 +497,34 @@ enum dc_edid_status dm_helpers_read_local_edid( DRM_ERROR("EDID err: %d, on connector: %s", edid_status, aconnector->base.name); + if (link->aux_mode) { + union test_request test_request = {0}; + union test_response test_response = {0}; + + dm_helpers_dp_read_dpcd(ctx, + link, + DP_TEST_REQUEST, + &test_request.raw, + sizeof(union test_request)); + + if (!test_request.bits.EDID_READ) + return edid_status; + + test_response.bits.EDID_CHECKSUM_WRITE = 1; + + dm_helpers_dp_write_dpcd(ctx, + link, + DP_TEST_EDID_CHECKSUM, + &sink->dc_edid.raw_edid[sink->dc_edid.length-1], + 1); + + dm_helpers_dp_write_dpcd(ctx, + link, + DP_TEST_RESPONSE, + &test_response.raw, + sizeof(test_response)); + + } return edid_status; } diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_services.c b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_services.c index 5a3346124a01..e861929dd981 100644 --- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_services.c +++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_services.c @@ -35,14 +35,6 @@ #include "amdgpu_dm_irq.h" #include "amdgpu_pm.h" -unsigned long long dm_get_timestamp(struct dc_context *ctx) -{ - struct timespec64 time; - - getrawmonotonic64(&time); - return timespec64_to_ns(&time); -} - unsigned long long dm_get_elapse_time_in_ns(struct dc_context *ctx, unsigned long long current_time_stamp, unsigned long long last_time_stamp) diff --git a/drivers/gpu/drm/amd/display/dc/basics/log_helpers.c b/drivers/gpu/drm/amd/display/dc/basics/log_helpers.c index 021451549ff7..f6c00a51d51a 100644 --- a/drivers/gpu/drm/amd/display/dc/basics/log_helpers.c +++ b/drivers/gpu/drm/amd/display/dc/basics/log_helpers.c @@ -78,6 +78,8 @@ void dc_conn_log(struct dc_context *ctx, if (i == NUM_ELEMENTS(signal_type_info_tbl)) goto fail; + dm_logger_append_heading(&entry); + dm_logger_append(&entry, "[%s][ConnIdx:%d] ", signal_type_info_tbl[i].name, link->link_index); diff --git a/drivers/gpu/drm/amd/display/dc/basics/logger.c b/drivers/gpu/drm/amd/display/dc/basics/logger.c index 0866874ae8c6..a3c56cd8b396 100644 --- a/drivers/gpu/drm/amd/display/dc/basics/logger.c +++ b/drivers/gpu/drm/amd/display/dc/basics/logger.c @@ -32,8 +32,9 @@ static const struct dc_log_type_info log_type_info_tbl[] = { {LOG_ERROR, "Error"}, {LOG_WARNING, "Warning"}, - {LOG_DEBUG, "Debug"}, + {LOG_DEBUG, "Debug"}, {LOG_DC, "DC_Interface"}, + {LOG_DTN, "DTN"}, {LOG_SURFACE, "Surface"}, {LOG_HW_HOTPLUG, "HW_Hotplug"}, {LOG_HW_LINK_TRAINING, "HW_LKTN"}, @@ -60,7 +61,7 @@ static const struct dc_log_type_info log_type_info_tbl[] = { {LOG_EVENT_LINK_LOSS, "LinkLoss"}, {LOG_EVENT_UNDERFLOW, "Underflow"}, {LOG_IF_TRACE, "InterfaceTrace"}, - {LOG_DTN, "DTN"}, + {LOG_PERF_TRACE, "PerfTrace"}, {LOG_DISPLAYSTATS, "DisplayStats"} }; @@ -128,8 +129,45 @@ uint32_t dal_logger_destroy(struct dal_logger **logger) } /* ------------------------------------------------------------------------ */ +void dm_logger_append_heading(struct log_entry *entry) +{ + int j; + + for (j = 0; j < NUM_ELEMENTS(log_type_info_tbl); j++) { + const struct dc_log_type_info *info = &log_type_info_tbl[j]; + if (info->type == entry->type) + dm_logger_append(entry, "[%s]\t", info->name); + } +} + + +/* Print everything unread existing in log_buffer to debug console*/ +void dm_logger_flush_buffer(struct dal_logger *logger, bool should_warn) +{ + char *string_start = &logger->log_buffer[logger->buffer_read_offset]; + + if (should_warn) + dm_output_to_console( + "---------------- FLUSHING LOG BUFFER ----------------\n"); + while (logger->buffer_read_offset < logger->buffer_write_offset) { + + if (logger->log_buffer[logger->buffer_read_offset] == '\0') { + dm_output_to_console("%s", string_start); + string_start = logger->log_buffer + logger->buffer_read_offset + 1; + } + logger->buffer_read_offset++; + } + if (should_warn) + dm_output_to_console( + "-------------- END FLUSHING LOG BUFFER --------------\n\n"); +} +/* ------------------------------------------------------------------------ */ + +/* Warning: Be careful that 'msg' is null terminated and the total size is + * less than DAL_LOGGER_BUFFER_MAX_LOG_LINE_SIZE (256) including '\0' + */ static bool dal_logger_should_log( struct dal_logger *logger, enum dc_log_type log_type) @@ -159,26 +197,6 @@ static void log_to_debug_console(struct log_entry *entry) } } -/* Print everything unread existing in log_buffer to debug console*/ -void dm_logger_flush_buffer(struct dal_logger *logger, bool should_warn) -{ - char *string_start = &logger->log_buffer[logger->buffer_read_offset]; - - if (should_warn) - dm_output_to_console( - "---------------- FLUSHING LOG BUFFER ----------------\n"); - while (logger->buffer_read_offset < logger->buffer_write_offset) { - - if (logger->log_buffer[logger->buffer_read_offset] == '\0') { - dm_output_to_console("%s", string_start); - string_start = logger->log_buffer + logger->buffer_read_offset + 1; - } - logger->buffer_read_offset++; - } - if (should_warn) - dm_output_to_console( - "-------------- END FLUSHING LOG BUFFER --------------\n\n"); -} static void log_to_internal_buffer(struct log_entry *entry) { @@ -229,19 +247,6 @@ static void log_to_internal_buffer(struct log_entry *entry) } } -static void log_heading(struct log_entry *entry) -{ - int j; - - for (j = 0; j < NUM_ELEMENTS(log_type_info_tbl); j++) { - - const struct dc_log_type_info *info = &log_type_info_tbl[j]; - - if (info->type == entry->type) - dm_logger_append(entry, "[%s]\t", info->name); - } -} - static void append_entry( struct log_entry *entry, char *buffer, @@ -259,11 +264,7 @@ static void append_entry( entry->buf_offset += buf_size; } -/* ------------------------------------------------------------------------ */ -/* Warning: Be careful that 'msg' is null terminated and the total size is - * less than DAL_LOGGER_BUFFER_MAX_LOG_LINE_SIZE (256) including '\0' - */ void dm_logger_write( struct dal_logger *logger, enum dc_log_type log_type, @@ -287,7 +288,7 @@ void dm_logger_write( entry.type = log_type; - log_heading(&entry); + dm_logger_append_heading(&entry); size = dm_log_to_buffer( buffer, LOG_MAX_LINE_SIZE - 1, msg, args); @@ -372,7 +373,7 @@ void dm_logger_open( logger->open_count++; - log_heading(entry); + dm_logger_append_heading(entry); } void dm_logger_close(struct log_entry *entry) diff --git a/drivers/gpu/drm/amd/display/dc/core/dc.c b/drivers/gpu/drm/amd/display/dc/core/dc.c index 644b2187507b..53ce7fa864b4 100644 --- a/drivers/gpu/drm/amd/display/dc/core/dc.c +++ b/drivers/gpu/drm/amd/display/dc/core/dc.c @@ -169,6 +169,22 @@ failed_alloc: return false; } +/** + ***************************************************************************** + * Function: dc_stream_adjust_vmin_vmax + * + * @brief + * Looks up the pipe context of dc_stream_state and updates the + * vertical_total_min and vertical_total_max of the DRR, Dynamic Refresh + * Rate, which is a power-saving feature that targets reducing panel + * refresh rate while the screen is static + * + * @param [in] dc: dc reference + * @param [in] stream: Initial dc stream state + * @param [in] adjust: Updated parameters for vertical_total_min and + * vertical_total_max + ***************************************************************************** + */ bool dc_stream_adjust_vmin_vmax(struct dc *dc, struct dc_stream_state **streams, int num_streams, int vmin, int vmax) @@ -465,6 +481,7 @@ static bool construct(struct dc *dc, dc_ctx->driver_context = init_params->driver; dc_ctx->dc = dc; dc_ctx->asic_id = init_params->asic_id; + dc_ctx->dc_sink_id_count = 0; dc->ctx = dc_ctx; dc->current_state = dc_create_state(); @@ -1548,7 +1565,7 @@ struct dc_sink *dc_link_add_remote_sink( struct dc_sink *dc_sink; enum dc_edid_status edid_status; - if (len > MAX_EDID_BUFFER_SIZE) { + if (len > DC_MAX_EDID_BUFFER_SIZE) { dm_error("Max EDID buffer size breached!\n"); return NULL; } 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 2fa521812d23..08b7ee526f0f 100644 --- a/drivers/gpu/drm/amd/display/dc/core/dc_link.c +++ b/drivers/gpu/drm/amd/display/dc/core/dc_link.c @@ -1861,28 +1861,6 @@ static enum dc_status enable_link( break; } - if (pipe_ctx->stream_res.audio && status == DC_OK) { - struct dc *core_dc = pipe_ctx->stream->ctx->dc; - /* notify audio driver for audio modes of monitor */ - struct pp_smu_funcs_rv *pp_smu = core_dc->res_pool->pp_smu; - unsigned int i, num_audio = 1; - for (i = 0; i < MAX_PIPES; i++) { - /*current_state not updated yet*/ - if (core_dc->current_state->res_ctx.pipe_ctx[i].stream_res.audio != NULL) - num_audio++; - } - - pipe_ctx->stream_res.audio->funcs->az_enable(pipe_ctx->stream_res.audio); - - if (num_audio == 1 && pp_smu != NULL && pp_smu->set_pme_wa_enable != NULL) - /*this is the first audio. apply the PME w/a in order to wake AZ from D3*/ - pp_smu->set_pme_wa_enable(&pp_smu->pp_smu); - /* un-mute audio */ - /* TODO: audio should be per stream rather than per link */ - pipe_ctx->stream_res.stream_enc->funcs->audio_mute_control( - pipe_ctx->stream_res.stream_enc, false); - } - return status; } @@ -2415,6 +2393,8 @@ void core_link_enable_stream( } } + core_dc->hwss.enable_audio_stream(pipe_ctx); + /* turn off otg test pattern if enable */ pipe_ctx->stream_res.tg->funcs->set_test_pattern(pipe_ctx->stream_res.tg, CONTROLLER_DP_TEST_PATTERN_VIDEOMODE, @@ -2453,6 +2433,22 @@ void core_link_set_avmute(struct pipe_ctx *pipe_ctx, bool enable) core_dc->hwss.set_avmute(pipe_ctx, enable); } +/** + ***************************************************************************** + * Function: dc_link_enable_hpd_filter + * + * @brief + * If enable is true, programs HPD filter on associated HPD line using + * delay_on_disconnect/delay_on_connect values dependent on + * link->connector_signal + * + * If enable is false, programs HPD filter on associated HPD line with no + * delays on connect or disconnect + * + * @param [in] link: pointer to the dc link + * @param [in] enable: boolean specifying whether to enable hbd + ***************************************************************************** + */ void dc_link_enable_hpd_filter(struct dc_link *link, bool enable) { struct gpio *hpd; 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 7857cb42b3e6..509f265663d2 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 @@ -1647,22 +1647,26 @@ static enum dc_status read_hpd_rx_irq_data( irq_data->raw, sizeof(union hpd_irq_data)); else { - /* Read 2 bytes at this location,... */ + /* Read 14 bytes in a single read and then copy only the required fields. + * This is more efficient than doing it in two separate AUX reads. */ + + uint8_t tmp[DP_SINK_STATUS_ESI - DP_SINK_COUNT_ESI + 1]; + retval = core_link_read_dpcd( link, DP_SINK_COUNT_ESI, - irq_data->raw, - 2); + tmp, + sizeof(tmp)); if (retval != DC_OK) return retval; - /* ... then read remaining 4 at the other location */ - retval = core_link_read_dpcd( - link, - DP_LANE0_1_STATUS_ESI, - &irq_data->raw[2], - 4); + irq_data->bytes.sink_cnt.raw = tmp[DP_SINK_COUNT_ESI - DP_SINK_COUNT_ESI]; + irq_data->bytes.device_service_irq.raw = tmp[DP_DEVICE_SERVICE_IRQ_VECTOR_ESI0 - DP_SINK_COUNT_ESI]; + irq_data->bytes.lane01_status.raw = tmp[DP_LANE0_1_STATUS_ESI - DP_SINK_COUNT_ESI]; + irq_data->bytes.lane23_status.raw = tmp[DP_LANE2_3_STATUS_ESI - DP_SINK_COUNT_ESI]; + irq_data->bytes.lane_status_updated.raw = tmp[DP_LANE_ALIGN_STATUS_UPDATED_ESI - DP_SINK_COUNT_ESI]; + irq_data->bytes.sink_status.raw = tmp[DP_SINK_STATUS_ESI - DP_SINK_COUNT_ESI]; } return retval; @@ -2305,6 +2309,7 @@ static bool retrieve_link_cap(struct dc_link *link) { uint8_t dpcd_data[DP_ADAPTER_CAP - DP_DPCD_REV + 1]; + struct dp_device_vendor_id sink_id; union down_stream_port_count down_strm_port_count; union edp_configuration_cap edp_config_cap; union dp_downstream_port_present ds_port = { 0 }; @@ -2391,6 +2396,17 @@ static bool retrieve_link_cap(struct dc_link *link) &link->dpcd_caps.sink_count.raw, sizeof(link->dpcd_caps.sink_count.raw)); + /* read sink ieee oui */ + core_link_read_dpcd(link, + DP_SINK_OUI, + (uint8_t *)(&sink_id), + sizeof(sink_id)); + + link->dpcd_caps.sink_dev_id = + (sink_id.ieee_oui[0] << 16) + + (sink_id.ieee_oui[1] << 8) + + (sink_id.ieee_oui[2]); + /* Connectivity log: detection */ CONN_DATA_DETECT(link, dpcd_data, sizeof(dpcd_data), "Rx Caps: "); 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 751f3ac9d921..fca22550417a 100644 --- a/drivers/gpu/drm/amd/display/dc/core/dc_resource.c +++ b/drivers/gpu/drm/amd/display/dc/core/dc_resource.c @@ -522,13 +522,12 @@ static void calculate_viewport(struct pipe_ctx *pipe_ctx) } } -static void calculate_recout(struct pipe_ctx *pipe_ctx, struct view *recout_skip) +static void calculate_recout(struct pipe_ctx *pipe_ctx, struct rect *recout_full) { const struct dc_plane_state *plane_state = pipe_ctx->plane_state; const struct dc_stream_state *stream = pipe_ctx->stream; 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 && @@ -597,20 +596,22 @@ static void calculate_recout(struct pipe_ctx *pipe_ctx, struct view *recout_skip } } /* 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) + * * 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; - recout_skip->width = pipe_ctx->plane_res.scl_data.recout.x - recout_full_x; - recout_skip->height = pipe_ctx->plane_res.scl_data.recout.y - recout_full_y; + recout_full->width = plane_state->dst_rect.width + * stream->dst.width / stream->src.width; + recout_full->height = plane_state->dst_rect.height + * stream->dst.height / stream->src.height; } static void calculate_scaling_ratios(struct pipe_ctx *pipe_ctx) @@ -662,7 +663,7 @@ static void calculate_scaling_ratios(struct pipe_ctx *pipe_ctx) pipe_ctx->plane_res.scl_data.ratios.vert_c, 19); } -static void calculate_inits_and_adj_vp(struct pipe_ctx *pipe_ctx, struct view *recout_skip) +static void calculate_inits_and_adj_vp(struct pipe_ctx *pipe_ctx, struct rect *recout_full) { struct scaler_data *data = &pipe_ctx->plane_res.scl_data; struct rect src = pipe_ctx->plane_state->src_rect; @@ -680,15 +681,14 @@ static void calculate_inits_and_adj_vp(struct pipe_ctx *pipe_ctx, struct view *r 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) { rect_swap_helper(&src); rect_swap_helper(&data->viewport_c); rect_swap_helper(&data->viewport); - } + } else if (pipe_ctx->plane_state->horizontal_mirror) + flip_horz_scan_dir = !flip_horz_scan_dir; /* * Init calculated according to formula: @@ -708,127 +708,286 @@ static void calculate_inits_and_adj_vp(struct pipe_ctx *pipe_ctx, struct view *r data->inits.v_c = dc_fixpt_truncate(dc_fixpt_add(data->inits.v_c, dc_fixpt_div_int( dc_fixpt_add_int(data->ratios.vert_c, data->taps.v_taps_c + 1), 2)), 19); + if (!flip_horz_scan_dir) { + /* Adjust for viewport end clip-off */ + if ((data->viewport.x + data->viewport.width) < (src.x + src.width)) { + int vp_clip = src.x + src.width - data->viewport.width - data->viewport.x; + int int_part = dc_fixpt_floor( + dc_fixpt_sub(data->inits.h, data->ratios.horz)); + int_part = int_part > 0 ? int_part : 0; + data->viewport.width += int_part < vp_clip ? int_part : vp_clip; + } + if ((data->viewport_c.x + data->viewport_c.width) < (src.x + src.width) / vpc_div) { + int vp_clip = (src.x + src.width) / vpc_div - + data->viewport_c.width - data->viewport_c.x; + int int_part = dc_fixpt_floor( + dc_fixpt_sub(data->inits.h_c, data->ratios.horz_c)); + + int_part = int_part > 0 ? int_part : 0; + data->viewport_c.width += int_part < vp_clip ? int_part : vp_clip; + } - /* Adjust for viewport end clip-off */ - if ((data->viewport.x + data->viewport.width) < (src.x + src.width) && !flip_horz_scan_dir) { - int vp_clip = src.x + src.width - data->viewport.width - data->viewport.x; - int int_part = dc_fixpt_floor( - dc_fixpt_sub(data->inits.h, data->ratios.horz)); - - int_part = int_part > 0 ? int_part : 0; - data->viewport.width += int_part < vp_clip ? int_part : vp_clip; - } - if ((data->viewport.y + data->viewport.height) < (src.y + src.height) && !flip_vert_scan_dir) { - int vp_clip = src.y + src.height - data->viewport.height - data->viewport.y; - int int_part = dc_fixpt_floor( - dc_fixpt_sub(data->inits.v, data->ratios.vert)); - - int_part = int_part > 0 ? int_part : 0; - data->viewport.height += int_part < vp_clip ? int_part : vp_clip; - } - if ((data->viewport_c.x + data->viewport_c.width) < (src.x + src.width) / vpc_div && !flip_horz_scan_dir) { - int vp_clip = (src.x + src.width) / vpc_div - - data->viewport_c.width - data->viewport_c.x; - int int_part = dc_fixpt_floor( - dc_fixpt_sub(data->inits.h_c, data->ratios.horz_c)); - - int_part = int_part > 0 ? int_part : 0; - data->viewport_c.width += int_part < vp_clip ? int_part : vp_clip; - } - if ((data->viewport_c.y + data->viewport_c.height) < (src.y + src.height) / vpc_div && !flip_vert_scan_dir) { - int vp_clip = (src.y + src.height) / vpc_div - - data->viewport_c.height - data->viewport_c.y; - int int_part = dc_fixpt_floor( - dc_fixpt_sub(data->inits.v_c, data->ratios.vert_c)); - - int_part = int_part > 0 ? int_part : 0; - data->viewport_c.height += int_part < vp_clip ? int_part : vp_clip; - } - - /* Adjust for non-0 viewport offset */ - if (data->viewport.x && !flip_horz_scan_dir) { - int int_part; - - data->inits.h = dc_fixpt_add(data->inits.h, dc_fixpt_mul_int( - data->ratios.horz, recout_skip->width)); - int_part = dc_fixpt_floor(data->inits.h) - data->viewport.x; - if (int_part < data->taps.h_taps) { - int int_adj = data->viewport.x >= (data->taps.h_taps - int_part) ? - (data->taps.h_taps - int_part) : data->viewport.x; - data->viewport.x -= int_adj; - data->viewport.width += int_adj; - int_part += int_adj; - } else if (int_part > data->taps.h_taps) { - data->viewport.x += int_part - data->taps.h_taps; - data->viewport.width -= int_part - data->taps.h_taps; - int_part = data->taps.h_taps; + /* Adjust for non-0 viewport offset */ + if (data->viewport.x) { + int int_part; + + data->inits.h = dc_fixpt_add(data->inits.h, dc_fixpt_mul_int( + data->ratios.horz, data->recout.x - recout_full->x)); + int_part = dc_fixpt_floor(data->inits.h) - data->viewport.x; + if (int_part < data->taps.h_taps) { + int int_adj = data->viewport.x >= (data->taps.h_taps - int_part) ? + (data->taps.h_taps - int_part) : data->viewport.x; + data->viewport.x -= int_adj; + data->viewport.width += int_adj; + int_part += int_adj; + } else if (int_part > data->taps.h_taps) { + data->viewport.x += int_part - data->taps.h_taps; + data->viewport.width -= int_part - data->taps.h_taps; + int_part = data->taps.h_taps; + } + data->inits.h.value &= 0xffffffff; + data->inits.h = dc_fixpt_add_int(data->inits.h, int_part); } - data->inits.h.value &= 0xffffffff; - data->inits.h = dc_fixpt_add_int(data->inits.h, int_part); - } - - if (data->viewport_c.x && !flip_horz_scan_dir) { - int int_part; - - data->inits.h_c = dc_fixpt_add(data->inits.h_c, dc_fixpt_mul_int( - data->ratios.horz_c, recout_skip->width)); - int_part = dc_fixpt_floor(data->inits.h_c) - data->viewport_c.x; - if (int_part < data->taps.h_taps_c) { - int int_adj = data->viewport_c.x >= (data->taps.h_taps_c - int_part) ? - (data->taps.h_taps_c - int_part) : data->viewport_c.x; - data->viewport_c.x -= int_adj; - data->viewport_c.width += int_adj; - int_part += int_adj; - } else if (int_part > data->taps.h_taps_c) { - data->viewport_c.x += int_part - data->taps.h_taps_c; - data->viewport_c.width -= int_part - data->taps.h_taps_c; - int_part = data->taps.h_taps_c; + + if (data->viewport_c.x) { + int int_part; + + data->inits.h_c = dc_fixpt_add(data->inits.h_c, dc_fixpt_mul_int( + data->ratios.horz_c, data->recout.x - recout_full->x)); + int_part = dc_fixpt_floor(data->inits.h_c) - data->viewport_c.x; + if (int_part < data->taps.h_taps_c) { + int int_adj = data->viewport_c.x >= (data->taps.h_taps_c - int_part) ? + (data->taps.h_taps_c - int_part) : data->viewport_c.x; + data->viewport_c.x -= int_adj; + data->viewport_c.width += int_adj; + int_part += int_adj; + } else if (int_part > data->taps.h_taps_c) { + data->viewport_c.x += int_part - data->taps.h_taps_c; + data->viewport_c.width -= int_part - data->taps.h_taps_c; + int_part = data->taps.h_taps_c; + } + data->inits.h_c.value &= 0xffffffff; + data->inits.h_c = dc_fixpt_add_int(data->inits.h_c, int_part); } - data->inits.h_c.value &= 0xffffffff; - data->inits.h_c = dc_fixpt_add_int(data->inits.h_c, int_part); - } - - if (data->viewport.y && !flip_vert_scan_dir) { - int int_part; - - data->inits.v = dc_fixpt_add(data->inits.v, dc_fixpt_mul_int( - data->ratios.vert, recout_skip->height)); - int_part = dc_fixpt_floor(data->inits.v) - data->viewport.y; - if (int_part < data->taps.v_taps) { - int int_adj = data->viewport.y >= (data->taps.v_taps - int_part) ? - (data->taps.v_taps - int_part) : data->viewport.y; - data->viewport.y -= int_adj; - data->viewport.height += int_adj; - int_part += int_adj; - } else if (int_part > data->taps.v_taps) { - data->viewport.y += int_part - data->taps.v_taps; - data->viewport.height -= int_part - data->taps.v_taps; - int_part = data->taps.v_taps; + } else { + /* Adjust for non-0 viewport offset */ + if (data->viewport.x) { + int int_part = dc_fixpt_floor( + dc_fixpt_sub(data->inits.h, data->ratios.horz)); + + int_part = int_part > 0 ? int_part : 0; + data->viewport.width += int_part < data->viewport.x ? int_part : data->viewport.x; + data->viewport.x -= int_part < data->viewport.x ? int_part : data->viewport.x; + } + if (data->viewport_c.x) { + int int_part = dc_fixpt_floor( + dc_fixpt_sub(data->inits.h_c, data->ratios.horz_c)); + + int_part = int_part > 0 ? int_part : 0; + data->viewport_c.width += int_part < data->viewport_c.x ? int_part : data->viewport_c.x; + data->viewport_c.x -= int_part < data->viewport_c.x ? int_part : data->viewport_c.x; } - data->inits.v.value &= 0xffffffff; - data->inits.v = dc_fixpt_add_int(data->inits.v, int_part); - } - - if (data->viewport_c.y && !flip_vert_scan_dir) { - int int_part; - - data->inits.v_c = dc_fixpt_add(data->inits.v_c, dc_fixpt_mul_int( - data->ratios.vert_c, recout_skip->height)); - int_part = dc_fixpt_floor(data->inits.v_c) - data->viewport_c.y; - if (int_part < data->taps.v_taps_c) { - int int_adj = data->viewport_c.y >= (data->taps.v_taps_c - int_part) ? - (data->taps.v_taps_c - int_part) : data->viewport_c.y; - data->viewport_c.y -= int_adj; - data->viewport_c.height += int_adj; - int_part += int_adj; - } else if (int_part > data->taps.v_taps_c) { - data->viewport_c.y += int_part - data->taps.v_taps_c; - data->viewport_c.height -= int_part - data->taps.v_taps_c; - int_part = data->taps.v_taps_c; + + /* Adjust for viewport end clip-off */ + if ((data->viewport.x + data->viewport.width) < (src.x + src.width)) { + int int_part; + int end_offset = src.x + src.width + - data->viewport.x - data->viewport.width; + + /* + * this is init if vp had no offset, keep in mind this is from the + * right side of vp due to scan direction + */ + data->inits.h = dc_fixpt_add(data->inits.h, dc_fixpt_mul_int( + data->ratios.horz, data->recout.x - recout_full->x)); + /* + * this is the difference between first pixel of viewport available to read + * and init position, takning into account scan direction + */ + int_part = dc_fixpt_floor(data->inits.h) - end_offset; + if (int_part < data->taps.h_taps) { + int int_adj = end_offset >= (data->taps.h_taps - int_part) ? + (data->taps.h_taps - int_part) : end_offset; + data->viewport.width += int_adj; + int_part += int_adj; + } else if (int_part > data->taps.h_taps) { + data->viewport.width += int_part - data->taps.h_taps; + int_part = data->taps.h_taps; + } + data->inits.h.value &= 0xffffffff; + data->inits.h = dc_fixpt_add_int(data->inits.h, int_part); + } + + if ((data->viewport_c.x + data->viewport_c.width) < (src.x + src.width) / vpc_div) { + int int_part; + int end_offset = (src.x + src.width) / vpc_div + - data->viewport_c.x - data->viewport_c.width; + + /* + * this is init if vp had no offset, keep in mind this is from the + * right side of vp due to scan direction + */ + data->inits.h_c = dc_fixpt_add(data->inits.h_c, dc_fixpt_mul_int( + data->ratios.horz_c, data->recout.x - recout_full->x)); + /* + * this is the difference between first pixel of viewport available to read + * and init position, takning into account scan direction + */ + int_part = dc_fixpt_floor(data->inits.h_c) - end_offset; + if (int_part < data->taps.h_taps_c) { + int int_adj = end_offset >= (data->taps.h_taps_c - int_part) ? + (data->taps.h_taps_c - int_part) : end_offset; + data->viewport_c.width += int_adj; + int_part += int_adj; + } else if (int_part > data->taps.h_taps_c) { + data->viewport_c.width += int_part - data->taps.h_taps_c; + int_part = data->taps.h_taps_c; + } + data->inits.h_c.value &= 0xffffffff; + data->inits.h_c = dc_fixpt_add_int(data->inits.h_c, int_part); + } + + } + if (!flip_vert_scan_dir) { + /* Adjust for viewport end clip-off */ + if ((data->viewport.y + data->viewport.height) < (src.y + src.height)) { + int vp_clip = src.y + src.height - data->viewport.height - data->viewport.y; + int int_part = dc_fixpt_floor( + dc_fixpt_sub(data->inits.v, data->ratios.vert)); + + int_part = int_part > 0 ? int_part : 0; + data->viewport.height += int_part < vp_clip ? int_part : vp_clip; + } + if ((data->viewport_c.y + data->viewport_c.height) < (src.y + src.height) / vpc_div) { + int vp_clip = (src.y + src.height) / vpc_div - + data->viewport_c.height - data->viewport_c.y; + int int_part = dc_fixpt_floor( + dc_fixpt_sub(data->inits.v_c, data->ratios.vert_c)); + + int_part = int_part > 0 ? int_part : 0; + data->viewport_c.height += int_part < vp_clip ? int_part : vp_clip; + } + + /* Adjust for non-0 viewport offset */ + if (data->viewport.y) { + int int_part; + + data->inits.v = dc_fixpt_add(data->inits.v, dc_fixpt_mul_int( + data->ratios.vert, data->recout.y - recout_full->y)); + int_part = dc_fixpt_floor(data->inits.v) - data->viewport.y; + if (int_part < data->taps.v_taps) { + int int_adj = data->viewport.y >= (data->taps.v_taps - int_part) ? + (data->taps.v_taps - int_part) : data->viewport.y; + data->viewport.y -= int_adj; + data->viewport.height += int_adj; + int_part += int_adj; + } else if (int_part > data->taps.v_taps) { + data->viewport.y += int_part - data->taps.v_taps; + data->viewport.height -= int_part - data->taps.v_taps; + int_part = data->taps.v_taps; + } + data->inits.v.value &= 0xffffffff; + data->inits.v = dc_fixpt_add_int(data->inits.v, int_part); + } + + if (data->viewport_c.y) { + int int_part; + + data->inits.v_c = dc_fixpt_add(data->inits.v_c, dc_fixpt_mul_int( + data->ratios.vert_c, data->recout.y - recout_full->y)); + int_part = dc_fixpt_floor(data->inits.v_c) - data->viewport_c.y; + if (int_part < data->taps.v_taps_c) { + int int_adj = data->viewport_c.y >= (data->taps.v_taps_c - int_part) ? + (data->taps.v_taps_c - int_part) : data->viewport_c.y; + data->viewport_c.y -= int_adj; + data->viewport_c.height += int_adj; + int_part += int_adj; + } else if (int_part > data->taps.v_taps_c) { + data->viewport_c.y += int_part - data->taps.v_taps_c; + data->viewport_c.height -= int_part - data->taps.v_taps_c; + int_part = data->taps.v_taps_c; + } + data->inits.v_c.value &= 0xffffffff; + data->inits.v_c = dc_fixpt_add_int(data->inits.v_c, int_part); + } + } else { + /* Adjust for non-0 viewport offset */ + if (data->viewport.y) { + int int_part = dc_fixpt_floor( + dc_fixpt_sub(data->inits.v, data->ratios.vert)); + + int_part = int_part > 0 ? int_part : 0; + data->viewport.height += int_part < data->viewport.y ? int_part : data->viewport.y; + data->viewport.y -= int_part < data->viewport.y ? int_part : data->viewport.y; + } + if (data->viewport_c.y) { + int int_part = dc_fixpt_floor( + dc_fixpt_sub(data->inits.v_c, data->ratios.vert_c)); + + int_part = int_part > 0 ? int_part : 0; + data->viewport_c.height += int_part < data->viewport_c.y ? int_part : data->viewport_c.y; + data->viewport_c.y -= int_part < data->viewport_c.y ? int_part : data->viewport_c.y; + } + + /* Adjust for viewport end clip-off */ + if ((data->viewport.y + data->viewport.height) < (src.y + src.height)) { + int int_part; + int end_offset = src.y + src.height + - data->viewport.y - data->viewport.height; + + /* + * this is init if vp had no offset, keep in mind this is from the + * right side of vp due to scan direction + */ + data->inits.v = dc_fixpt_add(data->inits.v, dc_fixpt_mul_int( + data->ratios.vert, data->recout.y - recout_full->y)); + /* + * this is the difference between first pixel of viewport available to read + * and init position, taking into account scan direction + */ + int_part = dc_fixpt_floor(data->inits.v) - end_offset; + if (int_part < data->taps.v_taps) { + int int_adj = end_offset >= (data->taps.v_taps - int_part) ? + (data->taps.v_taps - int_part) : end_offset; + data->viewport.height += int_adj; + int_part += int_adj; + } else if (int_part > data->taps.v_taps) { + data->viewport.height += int_part - data->taps.v_taps; + int_part = data->taps.v_taps; + } + data->inits.v.value &= 0xffffffff; + data->inits.v = dc_fixpt_add_int(data->inits.v, int_part); + } + + if ((data->viewport_c.y + data->viewport_c.height) < (src.y + src.height) / vpc_div) { + int int_part; + int end_offset = (src.y + src.height) / vpc_div + - data->viewport_c.y - data->viewport_c.height; + + /* + * this is init if vp had no offset, keep in mind this is from the + * right side of vp due to scan direction + */ + data->inits.v_c = dc_fixpt_add(data->inits.v_c, dc_fixpt_mul_int( + data->ratios.vert_c, data->recout.y - recout_full->y)); + /* + * this is the difference between first pixel of viewport available to read + * and init position, taking into account scan direction + */ + int_part = dc_fixpt_floor(data->inits.v_c) - end_offset; + if (int_part < data->taps.v_taps_c) { + int int_adj = end_offset >= (data->taps.v_taps_c - int_part) ? + (data->taps.v_taps_c - int_part) : end_offset; + data->viewport_c.height += int_adj; + int_part += int_adj; + } else if (int_part > data->taps.v_taps_c) { + data->viewport_c.height += int_part - data->taps.v_taps_c; + int_part = data->taps.v_taps_c; + } + data->inits.v_c.value &= 0xffffffff; + data->inits.v_c = dc_fixpt_add_int(data->inits.v_c, int_part); } - data->inits.v_c.value &= 0xffffffff; - data->inits.v_c = dc_fixpt_add_int(data->inits.v_c, int_part); } /* Interlaced inits based on final vert inits */ @@ -846,7 +1005,7 @@ bool resource_build_scaling_params(struct pipe_ctx *pipe_ctx) { const struct dc_plane_state *plane_state = pipe_ctx->plane_state; struct dc_crtc_timing *timing = &pipe_ctx->stream->timing; - struct view recout_skip = { 0 }; + struct rect recout_full = { 0 }; bool res = false; DC_LOGGER_INIT(pipe_ctx->stream->ctx->logger); /* Important: scaling ratio calculation requires pixel format, @@ -866,7 +1025,7 @@ bool resource_build_scaling_params(struct pipe_ctx *pipe_ctx) if (pipe_ctx->plane_res.scl_data.viewport.height < 16 || pipe_ctx->plane_res.scl_data.viewport.width < 16) return false; - calculate_recout(pipe_ctx, &recout_skip); + calculate_recout(pipe_ctx, &recout_full); /** * Setting line buffer pixel depth to 24bpp yields banding @@ -910,7 +1069,7 @@ bool resource_build_scaling_params(struct pipe_ctx *pipe_ctx) if (res) /* May need to re-check lb size after this in some obscure scenario */ - calculate_inits_and_adj_vp(pipe_ctx, &recout_skip); + calculate_inits_and_adj_vp(pipe_ctx, &recout_full); DC_LOG_SCALER( "%s: Viewport:\nheight:%d width:%d x:%d " @@ -2347,7 +2506,8 @@ static void set_hdr_static_info_packet( { /* HDR Static Metadata info packet for HDR10 */ - if (!stream->hdr_static_metadata.valid) + if (!stream->hdr_static_metadata.valid || + stream->use_dynamic_meta) return; *info_packet = stream->hdr_static_metadata; diff --git a/drivers/gpu/drm/amd/display/dc/core/dc_sink.c b/drivers/gpu/drm/amd/display/dc/core/dc_sink.c index 25fae38409ab..9971b515c3eb 100644 --- a/drivers/gpu/drm/amd/display/dc/core/dc_sink.c +++ b/drivers/gpu/drm/amd/display/dc/core/dc_sink.c @@ -53,6 +53,10 @@ static bool construct(struct dc_sink *sink, const struct dc_sink_init_data *init sink->dongle_max_pix_clk = init_params->dongle_max_pix_clk; sink->converter_disable_audio = init_params->converter_disable_audio; sink->dc_container_id = NULL; + sink->sink_id = init_params->link->ctx->dc_sink_id_count; + // increment dc_sink_id_count because we don't want two sinks with same ID + // unless they are actually the same + init_params->link->ctx->dc_sink_id_count++; return true; } diff --git a/drivers/gpu/drm/amd/display/dc/core/dc_surface.c b/drivers/gpu/drm/amd/display/dc/core/dc_surface.c index 68a71adeb12e..815dfb50089b 100644 --- a/drivers/gpu/drm/amd/display/dc/core/dc_surface.c +++ b/drivers/gpu/drm/amd/display/dc/core/dc_surface.c @@ -84,6 +84,17 @@ struct dc_plane_state *dc_create_plane_state(struct dc *dc) return plane_state; } +/** + ***************************************************************************** + * Function: dc_plane_get_status + * + * @brief + * Looks up the pipe context of plane_state and updates the pending status + * of the pipe context. Then returns plane_state->status + * + * @param [in] plane_state: pointer to the plane_state to get the status of + ***************************************************************************** + */ const struct dc_plane_status *dc_plane_get_status( const struct dc_plane_state *plane_state) { diff --git a/drivers/gpu/drm/amd/display/dc/dc.h b/drivers/gpu/drm/amd/display/dc/dc.h index 9cfde0ccf4e9..7ebce7669eea 100644 --- a/drivers/gpu/drm/amd/display/dc/dc.h +++ b/drivers/gpu/drm/amd/display/dc/dc.h @@ -38,7 +38,7 @@ #include "inc/compressor.h" #include "dml/display_mode_lib.h" -#define DC_VER "3.1.44" +#define DC_VER "3.1.47" #define MAX_SURFACES 3 #define MAX_STREAMS 6 @@ -68,6 +68,7 @@ struct dc_caps { uint32_t max_planes; uint32_t max_downscale_ratio; uint32_t i2c_speed_in_khz; + uint32_t dmdata_alloc_size; unsigned int max_cursor_size; unsigned int max_video_width; int linear_pitch_alignment; @@ -288,9 +289,7 @@ struct dc { bool apply_edp_fast_boot_optimization; /* FBC compressor */ -#if defined(CONFIG_DRM_AMD_DC_FBC) struct compressor *fbc_compressor; -#endif }; enum frame_buffer_mode { @@ -358,6 +357,7 @@ enum dc_transfer_func_type { TF_TYPE_PREDEFINED, TF_TYPE_DISTRIBUTED_POINTS, TF_TYPE_BYPASS, + TF_TYPE_HWPWL }; struct dc_transfer_func_distributed_points { @@ -377,16 +377,21 @@ enum dc_transfer_func_predefined { TRANSFER_FUNCTION_PQ, TRANSFER_FUNCTION_LINEAR, TRANSFER_FUNCTION_UNITY, + TRANSFER_FUNCTION_HLG, + TRANSFER_FUNCTION_HLG12 }; struct dc_transfer_func { struct kref refcount; - struct dc_transfer_func_distributed_points tf_pts; enum dc_transfer_func_type type; enum dc_transfer_func_predefined tf; /* FP16 1.0 reference level in nits, default is 80 nits, only for PQ*/ uint32_t sdr_ref_white_level; struct dc_context *ctx; + union { + struct pwl_params pwl; + struct dc_transfer_func_distributed_points tf_pts; + }; }; /* @@ -661,9 +666,13 @@ struct dc_sink { struct dc_link *link; struct dc_context *ctx; + uint32_t sink_id; + /* private to dc_sink.c */ + // refcount must be the last member in dc_sink, since we want the + // sink structure to be logically cloneable up to (but not including) + // refcount struct kref refcount; - }; void dc_sink_retain(struct dc_sink *sink); diff --git a/drivers/gpu/drm/amd/display/dc/dc_ddc_types.h b/drivers/gpu/drm/amd/display/dc/dc_ddc_types.h index e1affeb5cc51..05c8c31d8b31 100644 --- a/drivers/gpu/drm/amd/display/dc/dc_ddc_types.h +++ b/drivers/gpu/drm/amd/display/dc/dc_ddc_types.h @@ -25,6 +25,65 @@ #ifndef DC_DDC_TYPES_H_ #define DC_DDC_TYPES_H_ +enum aux_transaction_type { + AUX_TRANSACTION_TYPE_DP, + AUX_TRANSACTION_TYPE_I2C +}; + + +enum i2caux_transaction_action { + I2CAUX_TRANSACTION_ACTION_I2C_WRITE = 0x00, + I2CAUX_TRANSACTION_ACTION_I2C_READ = 0x10, + I2CAUX_TRANSACTION_ACTION_I2C_STATUS_REQUEST = 0x20, + + I2CAUX_TRANSACTION_ACTION_I2C_WRITE_MOT = 0x40, + I2CAUX_TRANSACTION_ACTION_I2C_READ_MOT = 0x50, + I2CAUX_TRANSACTION_ACTION_I2C_STATUS_REQUEST_MOT = 0x60, + + I2CAUX_TRANSACTION_ACTION_DP_WRITE = 0x80, + I2CAUX_TRANSACTION_ACTION_DP_READ = 0x90 +}; + +enum aux_channel_operation_result { + AUX_CHANNEL_OPERATION_SUCCEEDED, + AUX_CHANNEL_OPERATION_FAILED_REASON_UNKNOWN, + AUX_CHANNEL_OPERATION_FAILED_INVALID_REPLY, + AUX_CHANNEL_OPERATION_FAILED_TIMEOUT, + AUX_CHANNEL_OPERATION_FAILED_HPD_DISCON +}; + + +struct aux_request_transaction_data { + enum aux_transaction_type type; + enum i2caux_transaction_action action; + /* 20-bit AUX channel transaction address */ + uint32_t address; + /* delay, in 100-microsecond units */ + uint8_t delay; + uint32_t length; + uint8_t *data; +}; + +enum aux_transaction_reply { + AUX_TRANSACTION_REPLY_AUX_ACK = 0x00, + AUX_TRANSACTION_REPLY_AUX_NACK = 0x01, + AUX_TRANSACTION_REPLY_AUX_DEFER = 0x02, + + AUX_TRANSACTION_REPLY_I2C_ACK = 0x00, + AUX_TRANSACTION_REPLY_I2C_NACK = 0x10, + AUX_TRANSACTION_REPLY_I2C_DEFER = 0x20, + + AUX_TRANSACTION_REPLY_HPD_DISCON = 0x40, + + AUX_TRANSACTION_REPLY_INVALID = 0xFF +}; + +struct aux_reply_transaction_data { + enum aux_transaction_reply status; + uint32_t length; + uint8_t *data; +}; + struct i2c_payload { bool write; uint8_t address; @@ -109,7 +168,7 @@ struct ddc_service { uint32_t address; uint32_t edid_buf_len; - uint8_t edid_buf[MAX_EDID_BUFFER_SIZE]; + uint8_t edid_buf[DC_MAX_EDID_BUFFER_SIZE]; }; #endif /* DC_DDC_TYPES_H_ */ diff --git a/drivers/gpu/drm/amd/display/dc/dc_dp_types.h b/drivers/gpu/drm/amd/display/dc/dc_dp_types.h index 90bccd5ccaa2..da93ab43f2d8 100644 --- a/drivers/gpu/drm/amd/display/dc/dc_dp_types.h +++ b/drivers/gpu/drm/amd/display/dc/dc_dp_types.h @@ -430,7 +430,7 @@ union test_request { struct { uint8_t LINK_TRAINING :1; uint8_t LINK_TEST_PATTRN :1; - uint8_t EDID_REAT :1; + uint8_t EDID_READ :1; uint8_t PHY_TEST_PATTERN :1; uint8_t AUDIO_TEST_PATTERN :1; uint8_t RESERVED :1; @@ -443,7 +443,8 @@ union test_response { struct { uint8_t ACK :1; uint8_t NO_ACK :1; - uint8_t RESERVED :6; + uint8_t EDID_CHECKSUM_WRITE:1; + uint8_t RESERVED :5; } bits; uint8_t raw; }; diff --git a/drivers/gpu/drm/amd/display/dc/dc_hw_types.h b/drivers/gpu/drm/amd/display/dc/dc_hw_types.h index b1f70579d61b..d31023d57b58 100644 --- a/drivers/gpu/drm/amd/display/dc/dc_hw_types.h +++ b/drivers/gpu/drm/amd/display/dc/dc_hw_types.h @@ -567,25 +567,25 @@ struct scaling_taps { }; enum dc_timing_standard { - TIMING_STANDARD_UNDEFINED, - TIMING_STANDARD_DMT, - TIMING_STANDARD_GTF, - TIMING_STANDARD_CVT, - TIMING_STANDARD_CVT_RB, - TIMING_STANDARD_CEA770, - TIMING_STANDARD_CEA861, - TIMING_STANDARD_HDMI, - TIMING_STANDARD_TV_NTSC, - TIMING_STANDARD_TV_NTSC_J, - TIMING_STANDARD_TV_PAL, - TIMING_STANDARD_TV_PAL_M, - TIMING_STANDARD_TV_PAL_CN, - TIMING_STANDARD_TV_SECAM, - TIMING_STANDARD_EXPLICIT, + DC_TIMING_STANDARD_UNDEFINED, + DC_TIMING_STANDARD_DMT, + DC_TIMING_STANDARD_GTF, + DC_TIMING_STANDARD_CVT, + DC_TIMING_STANDARD_CVT_RB, + DC_TIMING_STANDARD_CEA770, + DC_TIMING_STANDARD_CEA861, + DC_TIMING_STANDARD_HDMI, + DC_TIMING_STANDARD_TV_NTSC, + DC_TIMING_STANDARD_TV_NTSC_J, + DC_TIMING_STANDARD_TV_PAL, + DC_TIMING_STANDARD_TV_PAL_M, + DC_TIMING_STANDARD_TV_PAL_CN, + DC_TIMING_STANDARD_TV_SECAM, + DC_TIMING_STANDARD_EXPLICIT, /*!< For explicit timings from EDID, VBIOS, etc.*/ - TIMING_STANDARD_USER_OVERRIDE, + DC_TIMING_STANDARD_USER_OVERRIDE, /*!< For mode timing override by user*/ - TIMING_STANDARD_MAX + DC_TIMING_STANDARD_MAX }; enum dc_color_depth { diff --git a/drivers/gpu/drm/amd/display/dc/dc_stream.h b/drivers/gpu/drm/amd/display/dc/dc_stream.h index d7e6d53bb383..af503e0286a7 100644 --- a/drivers/gpu/drm/amd/display/dc/dc_stream.h +++ b/drivers/gpu/drm/amd/display/dc/dc_stream.h @@ -59,6 +59,9 @@ struct dc_stream_state { struct freesync_context freesync_ctx; struct dc_info_packet hdr_static_metadata; + PHYSICAL_ADDRESS_LOC dmdata_address; + bool use_dynamic_meta; + struct dc_transfer_func *out_transfer_func; struct colorspace_transform gamut_remap_matrix; struct dc_csc_transform csc_color_matrix; @@ -299,9 +302,4 @@ bool dc_stream_get_crtc_position(struct dc *dc, unsigned int *v_pos, unsigned int *nom_v_pos); -void dc_stream_set_static_screen_events(struct dc *dc, - struct dc_stream_state **stream, - int num_streams, - const struct dc_static_screen_events *events); - #endif /* DC_STREAM_H_ */ diff --git a/drivers/gpu/drm/amd/display/dc/dc_types.h b/drivers/gpu/drm/amd/display/dc/dc_types.h index 76df2534c4a4..c96e526d07bb 100644 --- a/drivers/gpu/drm/amd/display/dc/dc_types.h +++ b/drivers/gpu/drm/amd/display/dc/dc_types.h @@ -92,13 +92,12 @@ struct dc_context { bool created_bios; struct gpio_service *gpio_service; struct i2caux *i2caux; -#if defined(CONFIG_DRM_AMD_DC_FBC) + uint32_t dc_sink_id_count; uint64_t fbc_gpu_addr; -#endif }; -#define MAX_EDID_BUFFER_SIZE 512 +#define DC_MAX_EDID_BUFFER_SIZE 512 #define EDID_BLOCK_SIZE 128 #define MAX_SURFACE_NUM 4 #define NUM_PIXEL_FORMATS 10 @@ -137,13 +136,13 @@ enum plane_stereo_format { */ enum dc_edid_connector_type { - EDID_CONNECTOR_UNKNOWN = 0, - EDID_CONNECTOR_ANALOG = 1, - EDID_CONNECTOR_DIGITAL = 10, - EDID_CONNECTOR_DVI = 11, - EDID_CONNECTOR_HDMIA = 12, - EDID_CONNECTOR_MDDI = 14, - EDID_CONNECTOR_DISPLAYPORT = 15 + DC_EDID_CONNECTOR_UNKNOWN = 0, + DC_EDID_CONNECTOR_ANALOG = 1, + DC_EDID_CONNECTOR_DIGITAL = 10, + DC_EDID_CONNECTOR_DVI = 11, + DC_EDID_CONNECTOR_HDMIA = 12, + DC_EDID_CONNECTOR_MDDI = 14, + DC_EDID_CONNECTOR_DISPLAYPORT = 15 }; enum dc_edid_status { @@ -169,7 +168,7 @@ struct dc_cea_audio_mode { struct dc_edid { uint32_t length; - uint8_t raw_edid[MAX_EDID_BUFFER_SIZE]; + uint8_t raw_edid[DC_MAX_EDID_BUFFER_SIZE]; }; /* When speaker location data block is not available, DEFAULT_SPEAKER_LOCATION diff --git a/drivers/gpu/drm/amd/display/dc/dce/dce_stream_encoder.c b/drivers/gpu/drm/amd/display/dc/dce/dce_stream_encoder.c index c0e813c7ddd4..91642e684858 100644 --- a/drivers/gpu/drm/amd/display/dc/dce/dce_stream_encoder.c +++ b/drivers/gpu/drm/amd/display/dc/dce/dce_stream_encoder.c @@ -289,11 +289,6 @@ static void dce110_stream_encoder_dp_set_stream_attribute( struct dce110_stream_encoder *enc110 = DCE110STRENC_FROM_STRENC(enc); -#if defined(CONFIG_DRM_AMD_DC_DCN1_0) - if (REG(DP_DB_CNTL)) - REG_UPDATE(DP_DB_CNTL, DP_DB_DISABLE, 1); -#endif - /* set pixel encoding */ switch (crtc_timing->pixel_encoding) { case PIXEL_ENCODING_YCBCR422: diff --git a/drivers/gpu/drm/amd/display/dc/dce110/dce110_compressor.c b/drivers/gpu/drm/amd/display/dc/dce110/dce110_compressor.c index e2994d337044..df027013e50c 100644 --- a/drivers/gpu/drm/amd/display/dc/dce110/dce110_compressor.c +++ b/drivers/gpu/drm/amd/display/dc/dce110/dce110_compressor.c @@ -143,7 +143,7 @@ static void wait_for_fbc_state_changed( struct dce110_compressor *cp110, bool enabled) { - uint8_t counter = 0; + uint16_t counter = 0; uint32_t addr = mmFBC_STATUS; uint32_t value; @@ -551,9 +551,7 @@ void dce110_compressor_construct(struct dce110_compressor *compressor, compressor->base.lpt_channels_num = 0; compressor->base.attached_inst = 0; compressor->base.is_enabled = false; -#if defined(CONFIG_DRM_AMD_DC_FBC) compressor->base.funcs = &dce110_compressor_funcs; -#endif } diff --git a/drivers/gpu/drm/amd/display/dc/dce110/dce110_hw_sequencer.c b/drivers/gpu/drm/amd/display/dc/dce110/dce110_hw_sequencer.c index c29052b6da5a..353ffcbdf5ba 100644 --- a/drivers/gpu/drm/amd/display/dc/dce110/dce110_hw_sequencer.c +++ b/drivers/gpu/drm/amd/display/dc/dce110/dce110_hw_sequencer.c @@ -34,9 +34,7 @@ #include "dce/dce_hwseq.h" #include "gpio_service_interface.h" -#if defined(CONFIG_DRM_AMD_DC_FBC) #include "dce110_compressor.h" -#endif #include "bios/bios_parser_helper.h" #include "timing_generator.h" @@ -667,16 +665,25 @@ static enum dc_status bios_parser_crtc_source_select( void dce110_update_info_frame(struct pipe_ctx *pipe_ctx) { + bool is_hdmi; + bool is_dp; + ASSERT(pipe_ctx->stream); if (pipe_ctx->stream_res.stream_enc == NULL) return; /* this is not root pipe */ - if (dc_is_hdmi_signal(pipe_ctx->stream->signal)) + is_hdmi = dc_is_hdmi_signal(pipe_ctx->stream->signal); + is_dp = dc_is_dp_signal(pipe_ctx->stream->signal); + + if (!is_hdmi && !is_dp) + return; + + if (is_hdmi) pipe_ctx->stream_res.stream_enc->funcs->update_hdmi_info_packets( pipe_ctx->stream_res.stream_enc, &pipe_ctx->stream_res.encoder_info_frame); - else if (dc_is_dp_signal(pipe_ctx->stream->signal)) + else pipe_ctx->stream_res.stream_enc->funcs->update_dp_info_packets( pipe_ctx->stream_res.stream_enc, &pipe_ctx->stream_res.encoder_info_frame); @@ -972,19 +979,35 @@ void hwss_edp_backlight_control( edp_receiver_ready_T9(link); } -void dce110_disable_stream(struct pipe_ctx *pipe_ctx, int option) +void dce110_enable_audio_stream(struct pipe_ctx *pipe_ctx) { - struct dc_stream_state *stream = pipe_ctx->stream; - struct dc_link *link = stream->sink->link; - struct dc *dc = pipe_ctx->stream->ctx->dc; + struct dc *core_dc = pipe_ctx->stream->ctx->dc; + /* notify audio driver for audio modes of monitor */ + struct pp_smu_funcs_rv *pp_smu = core_dc->res_pool->pp_smu; + unsigned int i, num_audio = 1; - if (dc_is_hdmi_signal(pipe_ctx->stream->signal)) - pipe_ctx->stream_res.stream_enc->funcs->stop_hdmi_info_packets( - pipe_ctx->stream_res.stream_enc); + if (pipe_ctx->stream_res.audio) { + for (i = 0; i < MAX_PIPES; i++) { + /*current_state not updated yet*/ + if (core_dc->current_state->res_ctx.pipe_ctx[i].stream_res.audio != NULL) + num_audio++; + } - if (dc_is_dp_signal(pipe_ctx->stream->signal)) - pipe_ctx->stream_res.stream_enc->funcs->stop_dp_info_packets( - pipe_ctx->stream_res.stream_enc); + pipe_ctx->stream_res.audio->funcs->az_enable(pipe_ctx->stream_res.audio); + + if (num_audio == 1 && pp_smu != NULL && pp_smu->set_pme_wa_enable != NULL) + /*this is the first audio. apply the PME w/a in order to wake AZ from D3*/ + pp_smu->set_pme_wa_enable(&pp_smu->pp_smu); + /* un-mute audio */ + /* TODO: audio should be per stream rather than per link */ + pipe_ctx->stream_res.stream_enc->funcs->audio_mute_control( + pipe_ctx->stream_res.stream_enc, false); + } +} + +void dce110_disable_audio_stream(struct pipe_ctx *pipe_ctx, int option) +{ + struct dc *dc = pipe_ctx->stream->ctx->dc; pipe_ctx->stream_res.stream_enc->funcs->audio_mute_control( pipe_ctx->stream_res.stream_enc, true); @@ -1015,7 +1038,23 @@ void dce110_disable_stream(struct pipe_ctx *pipe_ctx, int option) * stream->stream_engine_id); */ } +} +void dce110_disable_stream(struct pipe_ctx *pipe_ctx, int option) +{ + struct dc_stream_state *stream = pipe_ctx->stream; + struct dc_link *link = stream->sink->link; + struct dc *dc = pipe_ctx->stream->ctx->dc; + + if (dc_is_hdmi_signal(pipe_ctx->stream->signal)) + pipe_ctx->stream_res.stream_enc->funcs->stop_hdmi_info_packets( + pipe_ctx->stream_res.stream_enc); + + if (dc_is_dp_signal(pipe_ctx->stream->signal)) + pipe_ctx->stream_res.stream_enc->funcs->stop_dp_info_packets( + pipe_ctx->stream_res.stream_enc); + + dc->hwss.disable_audio_stream(pipe_ctx, option); link->link_enc->funcs->connect_dig_be_to_fe( link->link_enc, @@ -1298,6 +1337,30 @@ static enum dc_status apply_single_controller_ctx_to_hw( struct pipe_ctx *pipe_ctx_old = &dc->current_state->res_ctx. pipe_ctx[pipe_ctx->pipe_idx]; + if (pipe_ctx->stream_res.audio != NULL) { + struct audio_output audio_output; + + build_audio_output(context, pipe_ctx, &audio_output); + + if (dc_is_dp_signal(pipe_ctx->stream->signal)) + pipe_ctx->stream_res.stream_enc->funcs->dp_audio_setup( + pipe_ctx->stream_res.stream_enc, + pipe_ctx->stream_res.audio->inst, + &pipe_ctx->stream->audio_info); + else + pipe_ctx->stream_res.stream_enc->funcs->hdmi_audio_setup( + pipe_ctx->stream_res.stream_enc, + pipe_ctx->stream_res.audio->inst, + &pipe_ctx->stream->audio_info, + &audio_output.crtc_info); + + pipe_ctx->stream_res.audio->funcs->az_configure( + pipe_ctx->stream_res.audio, + pipe_ctx->stream->signal, + &audio_output.crtc_info, + &pipe_ctx->stream->audio_info); + } + /* */ dc->hwss.enable_stream_timing(pipe_ctx, context, dc); @@ -1441,10 +1504,8 @@ static void power_down_all_hw_blocks(struct dc *dc) power_down_clock_sources(dc); -#if defined(CONFIG_DRM_AMD_DC_FBC) if (dc->fbc_compressor) dc->fbc_compressor->funcs->disable_fbc(dc->fbc_compressor); -#endif } static void disable_vga_and_power_gate_all_controllers( @@ -1686,9 +1747,7 @@ static void set_static_screen_control(struct pipe_ctx **pipe_ctx, if (events->force_trigger) value |= 0x1; -#if defined(CONFIG_DRM_AMD_DC_FBC) value |= 0x84; -#endif for (i = 0; i < num_pipes; i++) pipe_ctx[i]->stream_res.tg->funcs-> @@ -1816,8 +1875,6 @@ static void apply_min_clocks( } } -#if defined(CONFIG_DRM_AMD_DC_FBC) - /* * Check if FBC can be enabled */ @@ -1896,7 +1953,6 @@ static void enable_fbc(struct dc *dc, compr->funcs->enable_fbc(compr, ¶ms); } } -#endif static void dce110_reset_hw_ctx_wrap( struct dc *dc, @@ -1949,6 +2005,86 @@ static void dce110_reset_hw_ctx_wrap( } } +static void dce110_setup_audio_dto( + struct dc *dc, + struct dc_state *context) +{ + int i; + + /* program audio wall clock. use HDMI as clock source if HDMI + * audio active. Otherwise, use DP as clock source + * first, loop to find any HDMI audio, if not, loop find DP audio + */ + /* Setup audio rate clock source */ + /* Issue: + * Audio lag happened on DP monitor when unplug a HDMI monitor + * + * Cause: + * In case of DP and HDMI connected or HDMI only, DCCG_AUDIO_DTO_SEL + * is set to either dto0 or dto1, audio should work fine. + * In case of DP connected only, DCCG_AUDIO_DTO_SEL should be dto1, + * set to dto0 will cause audio lag. + * + * Solution: + * Not optimized audio wall dto setup. When mode set, iterate pipe_ctx, + * find first available pipe with audio, setup audio wall DTO per topology + * instead of per pipe. + */ + for (i = 0; i < dc->res_pool->pipe_count; i++) { + struct pipe_ctx *pipe_ctx = &context->res_ctx.pipe_ctx[i]; + + if (pipe_ctx->stream == NULL) + continue; + + if (pipe_ctx->top_pipe) + continue; + + if (pipe_ctx->stream->signal != SIGNAL_TYPE_HDMI_TYPE_A) + continue; + + if (pipe_ctx->stream_res.audio != NULL) { + struct audio_output audio_output; + + build_audio_output(context, pipe_ctx, &audio_output); + + pipe_ctx->stream_res.audio->funcs->wall_dto_setup( + pipe_ctx->stream_res.audio, + pipe_ctx->stream->signal, + &audio_output.crtc_info, + &audio_output.pll_info); + break; + } + } + + /* no HDMI audio is found, try DP audio */ + if (i == dc->res_pool->pipe_count) { + for (i = 0; i < dc->res_pool->pipe_count; i++) { + struct pipe_ctx *pipe_ctx = &context->res_ctx.pipe_ctx[i]; + + if (pipe_ctx->stream == NULL) + continue; + + if (pipe_ctx->top_pipe) + continue; + + if (!dc_is_dp_signal(pipe_ctx->stream->signal)) + continue; + + if (pipe_ctx->stream_res.audio != NULL) { + struct audio_output audio_output; + + build_audio_output(context, pipe_ctx, &audio_output); + + pipe_ctx->stream_res.audio->funcs->wall_dto_setup( + pipe_ctx->stream_res.audio, + pipe_ctx->stream->signal, + &audio_output.crtc_info, + &audio_output.pll_info); + break; + } + } + } +} enum dc_status dce110_apply_ctx_to_hw( struct dc *dc, @@ -1993,10 +2129,9 @@ enum dc_status dce110_apply_ctx_to_hw( set_safe_displaymarks(&context->res_ctx, dc->res_pool); -#if defined(CONFIG_DRM_AMD_DC_FBC) if (dc->fbc_compressor) dc->fbc_compressor->funcs->disable_fbc(dc->fbc_compressor); -#endif + /*TODO: when pplib works*/ apply_min_clocks(dc, context, &clocks_state, true); @@ -2040,79 +2175,8 @@ enum dc_status dce110_apply_ctx_to_hw( dc->res_pool->display_clock, context->bw.dce.dispclk_khz * 115 / 100); } - /* program audio wall clock. use HDMI as clock source if HDMI - * audio active. Otherwise, use DP as clock source - * first, loop to find any HDMI audio, if not, loop find DP audio - */ - /* Setup audio rate clock source */ - /* Issue: - * Audio lag happened on DP monitor when unplug a HDMI monitor - * - * Cause: - * In case of DP and HDMI connected or HDMI only, DCCG_AUDIO_DTO_SEL - * is set to either dto0 or dto1, audio should work fine. - * In case of DP connected only, DCCG_AUDIO_DTO_SEL should be dto1, - * set to dto0 will cause audio lag. - * - * Solution: - * Not optimized audio wall dto setup. When mode set, iterate pipe_ctx, - * find first available pipe with audio, setup audio wall DTO per topology - * instead of per pipe. - */ - for (i = 0; i < dc->res_pool->pipe_count; i++) { - struct pipe_ctx *pipe_ctx = &context->res_ctx.pipe_ctx[i]; - - if (pipe_ctx->stream == NULL) - continue; - - if (pipe_ctx->top_pipe) - continue; - - if (pipe_ctx->stream->signal != SIGNAL_TYPE_HDMI_TYPE_A) - continue; - - if (pipe_ctx->stream_res.audio != NULL) { - struct audio_output audio_output; - - build_audio_output(context, pipe_ctx, &audio_output); - - pipe_ctx->stream_res.audio->funcs->wall_dto_setup( - pipe_ctx->stream_res.audio, - pipe_ctx->stream->signal, - &audio_output.crtc_info, - &audio_output.pll_info); - break; - } - } - /* no HDMI audio is found, try DP audio */ - if (i == dc->res_pool->pipe_count) { - for (i = 0; i < dc->res_pool->pipe_count; i++) { - struct pipe_ctx *pipe_ctx = &context->res_ctx.pipe_ctx[i]; - - if (pipe_ctx->stream == NULL) - continue; - - if (pipe_ctx->top_pipe) - continue; - - if (!dc_is_dp_signal(pipe_ctx->stream->signal)) - continue; - - if (pipe_ctx->stream_res.audio != NULL) { - struct audio_output audio_output; - - build_audio_output(context, pipe_ctx, &audio_output); - - pipe_ctx->stream_res.audio->funcs->wall_dto_setup( - pipe_ctx->stream_res.audio, - pipe_ctx->stream->signal, - &audio_output.crtc_info, - &audio_output.pll_info); - break; - } - } - } + dce110_setup_audio_dto(dc, context); for (i = 0; i < dc->res_pool->pipe_count; i++) { struct pipe_ctx *pipe_ctx_old = @@ -2131,31 +2195,6 @@ enum dc_status dce110_apply_ctx_to_hw( if (pipe_ctx->top_pipe) continue; - if (context->res_ctx.pipe_ctx[i].stream_res.audio != NULL) { - - struct audio_output audio_output; - - build_audio_output(context, pipe_ctx, &audio_output); - - if (dc_is_dp_signal(pipe_ctx->stream->signal)) - pipe_ctx->stream_res.stream_enc->funcs->dp_audio_setup( - pipe_ctx->stream_res.stream_enc, - pipe_ctx->stream_res.audio->inst, - &pipe_ctx->stream->audio_info); - else - pipe_ctx->stream_res.stream_enc->funcs->hdmi_audio_setup( - pipe_ctx->stream_res.stream_enc, - pipe_ctx->stream_res.audio->inst, - &pipe_ctx->stream->audio_info, - &audio_output.crtc_info); - - pipe_ctx->stream_res.audio->funcs->az_configure( - pipe_ctx->stream_res.audio, - pipe_ctx->stream->signal, - &audio_output.crtc_info, - &pipe_ctx->stream->audio_info); - } - status = apply_single_controller_ctx_to_hw( pipe_ctx, context, @@ -2170,12 +2209,9 @@ enum dc_status dce110_apply_ctx_to_hw( dcb->funcs->set_scratch_critical_state(dcb, false); -#if defined(CONFIG_DRM_AMD_DC_FBC) if (dc->fbc_compressor) enable_fbc(dc, context); -#endif - return DC_OK; } @@ -2490,10 +2526,9 @@ static void init_hw(struct dc *dc) abm->funcs->init_backlight(abm); abm->funcs->abm_init(abm); } -#if defined(CONFIG_DRM_AMD_DC_FBC) + if (dc->fbc_compressor) dc->fbc_compressor->funcs->power_up_fbc(dc->fbc_compressor); -#endif } @@ -2679,9 +2714,7 @@ static void dce110_program_front_end_for_pipe( struct dc_plane_state *plane_state = pipe_ctx->plane_state; struct xfm_grph_csc_adjustment adjust; struct out_csc_color_matrix tbl_entry; -#if defined(CONFIG_DRM_AMD_DC_FBC) unsigned int underlay_idx = dc->res_pool->underlay_pipe_index; -#endif unsigned int i; DC_LOGGER_INIT(); memset(&tbl_entry, 0, sizeof(tbl_entry)); @@ -2722,7 +2755,6 @@ static void dce110_program_front_end_for_pipe( program_scaler(dc, pipe_ctx); -#if defined(CONFIG_DRM_AMD_DC_FBC) /* fbc not applicable on Underlay pipe */ if (dc->fbc_compressor && old_pipe->stream && pipe_ctx->pipe_idx != underlay_idx) { @@ -2731,7 +2763,6 @@ static void dce110_program_front_end_for_pipe( else enable_fbc(dc, dc->current_state); } -#endif mi->funcs->mem_input_program_surface_config( mi, @@ -2968,6 +2999,8 @@ static const struct hw_sequencer_funcs dce110_funcs = { .disable_stream = dce110_disable_stream, .unblank_stream = dce110_unblank_stream, .blank_stream = dce110_blank_stream, + .enable_audio_stream = dce110_enable_audio_stream, + .disable_audio_stream = dce110_disable_audio_stream, .enable_display_pipe_clock_gating = enable_display_pipe_clock_gating, .enable_display_power_gating = dce110_enable_display_power_gating, .disable_plane = dce110_power_down_fe, diff --git a/drivers/gpu/drm/amd/display/dc/dce110/dce110_hw_sequencer.h b/drivers/gpu/drm/amd/display/dc/dce110/dce110_hw_sequencer.h index 5d7e9f516827..f48d5a68d238 100644 --- a/drivers/gpu/drm/amd/display/dc/dce110/dce110_hw_sequencer.h +++ b/drivers/gpu/drm/amd/display/dc/dce110/dce110_hw_sequencer.h @@ -49,6 +49,10 @@ void dce110_unblank_stream(struct pipe_ctx *pipe_ctx, struct dc_link_settings *link_settings); void dce110_blank_stream(struct pipe_ctx *pipe_ctx); + +void dce110_enable_audio_stream(struct pipe_ctx *pipe_ctx); +void dce110_disable_audio_stream(struct pipe_ctx *pipe_ctx, int option); + void dce110_update_info_frame(struct pipe_ctx *pipe_ctx); void dce110_set_avmute(struct pipe_ctx *pipe_ctx, bool enable); diff --git a/drivers/gpu/drm/amd/display/dc/dce110/dce110_resource.c b/drivers/gpu/drm/amd/display/dc/dce110/dce110_resource.c index ee33786bdef6..20c029089551 100644 --- a/drivers/gpu/drm/amd/display/dc/dce110/dce110_resource.c +++ b/drivers/gpu/drm/amd/display/dc/dce110/dce110_resource.c @@ -54,9 +54,8 @@ #define DC_LOGGER \ dc->ctx->logger -#if defined(CONFIG_DRM_AMD_DC_FBC) + #include "dce110/dce110_compressor.h" -#endif #include "reg_helper.h" @@ -1267,12 +1266,8 @@ static bool construct( } } -#if defined(CONFIG_DRM_AMD_DC_FBC) dc->fbc_compressor = dce110_compressor_create(ctx); - - -#endif if (!underlay_create(ctx, &pool->base)) goto res_create_fail; diff --git a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hw_sequencer.c b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hw_sequencer.c index f8e0576af6e0..03eb736a312f 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hw_sequencer.c +++ b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hw_sequencer.c @@ -719,19 +719,7 @@ static void reset_back_end_for_pipe( if (!pipe_ctx->stream->dpms_off) core_link_disable_stream(pipe_ctx, FREE_ACQUIRED_RESOURCE); else if (pipe_ctx->stream_res.audio) { - /* - * if stream is already disabled outside of commit streams path, - * audio disable was skipped. Need to do it here - */ - pipe_ctx->stream_res.audio->funcs->az_disable(pipe_ctx->stream_res.audio); - - if (dc->caps.dynamic_audio == true) { - /*we have to dynamic arbitrate the audio endpoints*/ - pipe_ctx->stream_res.audio = NULL; - /*we free the resource, need reset is_audio_acquired*/ - update_audio_usage(&dc->current_state->res_ctx, dc->res_pool, pipe_ctx->stream_res.audio, false); - } - + dc->hwss.disable_audio_stream(pipe_ctx, FREE_ACQUIRED_RESOURCE); } } @@ -2063,12 +2051,13 @@ static void update_dchubp_dpp( static void dcn10_blank_pixel_data( struct dc *dc, - struct stream_resource *stream_res, - struct dc_stream_state *stream, + struct pipe_ctx *pipe_ctx, bool blank) { enum dc_color_space color_space; struct tg_color black_color = {0}; + struct stream_resource *stream_res = &pipe_ctx->stream_res; + struct dc_stream_state *stream = pipe_ctx->stream; /* program otg blank color */ color_space = stream->output_color_space; @@ -2127,8 +2116,7 @@ static void program_all_pipe_in_tree( pipe_ctx->stream_res.tg->funcs->program_global_sync( pipe_ctx->stream_res.tg); - dc->hwss.blank_pixel_data(dc, &pipe_ctx->stream_res, - pipe_ctx->stream, blank); + dc->hwss.blank_pixel_data(dc, pipe_ctx, blank); } if (pipe_ctx->plane_state != NULL) { @@ -2247,7 +2235,7 @@ static void dcn10_apply_ctx_for_surface( if (num_planes == 0) { /* OTG blank before remove all front end */ - dc->hwss.blank_pixel_data(dc, &top_pipe_to_program->stream_res, top_pipe_to_program->stream, true); + dc->hwss.blank_pixel_data(dc, top_pipe_to_program, true); } /* Disconnect unused mpcc */ @@ -2778,6 +2766,8 @@ static const struct hw_sequencer_funcs dcn10_funcs = { .disable_stream = dce110_disable_stream, .unblank_stream = dce110_unblank_stream, .blank_stream = dce110_blank_stream, + .enable_audio_stream = dce110_enable_audio_stream, + .disable_audio_stream = dce110_disable_audio_stream, .enable_display_power_gating = dcn10_dummy_display_power_gating, .disable_plane = dcn10_disable_plane, .blank_pixel_data = dcn10_blank_pixel_data, diff --git a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_optc.c b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_optc.c index f2fbce0e3fc5..e6a3ade154b9 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_optc.c +++ b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_optc.c @@ -1257,6 +1257,37 @@ void optc1_read_otg_state(struct optc *optc1, OPTC_UNDERFLOW_OCCURRED_STATUS, &s->underflow_occurred_status); } +bool optc1_get_otg_active_size(struct timing_generator *optc, + uint32_t *otg_active_width, + uint32_t *otg_active_height) +{ + uint32_t otg_enabled; + uint32_t v_blank_start; + uint32_t v_blank_end; + uint32_t h_blank_start; + uint32_t h_blank_end; + struct optc *optc1 = DCN10TG_FROM_TG(optc); + + + REG_GET(OTG_CONTROL, + OTG_MASTER_EN, &otg_enabled); + + if (otg_enabled == 0) + return false; + + REG_GET_2(OTG_V_BLANK_START_END, + OTG_V_BLANK_START, &v_blank_start, + OTG_V_BLANK_END, &v_blank_end); + + REG_GET_2(OTG_H_BLANK_START_END, + OTG_H_BLANK_START, &h_blank_start, + OTG_H_BLANK_END, &h_blank_end); + + *otg_active_width = v_blank_start - v_blank_end; + *otg_active_height = h_blank_start - h_blank_end; + return true; +} + void optc1_clear_optc_underflow(struct timing_generator *optc) { struct optc *optc1 = DCN10TG_FROM_TG(optc); @@ -1305,6 +1336,7 @@ static const struct timing_generator_funcs dcn10_tg_funcs = { .get_position = optc1_get_position, .get_frame_count = optc1_get_vblank_counter, .get_scanoutpos = optc1_get_crtc_scanoutpos, + .get_otg_active_size = optc1_get_otg_active_size, .set_early_control = optc1_set_early_control, /* used by enable_timing_synchronization. Not need for FPGA */ .wait_for_state = optc1_wait_for_state, diff --git a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_optc.h b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_optc.h index c62052f46460..59ed272e0c49 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_optc.h +++ b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_optc.h @@ -507,4 +507,8 @@ bool optc1_is_optc_underflow_occurred(struct timing_generator *optc); void optc1_set_blank_data_double_buffer(struct timing_generator *optc, bool enable); +bool optc1_get_otg_active_size(struct timing_generator *optc, + uint32_t *otg_active_width, + uint32_t *otg_active_height); + #endif /* __DC_TIMING_GENERATOR_DCN10_H__ */ diff --git a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_resource.c b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_resource.c index df5cb2d1d164..2da325ce781b 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_resource.c +++ b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_resource.c @@ -417,6 +417,7 @@ static const struct dce110_clk_src_mask cs_mask = { static const struct resource_caps res_cap = { .num_timing_generator = 4, + .num_opp = 4, .num_video_plane = 4, .num_audio = 4, .num_stream_encoder = 4, @@ -1004,7 +1005,8 @@ static bool construct( ctx->dc_bios->regs = &bios_regs; - pool->base.res_cap = &res_cap; + pool->base.res_cap = &res_cap; + pool->base.funcs = &dcn10_res_pool_funcs; /* diff --git a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_stream_encoder.c b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_stream_encoder.c index c928ee4cd382..6f9078f3c4d3 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_stream_encoder.c +++ b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_stream_encoder.c @@ -257,20 +257,18 @@ void enc1_stream_encoder_dp_set_stream_attribute( uint8_t colorimetry_bpc; uint8_t dynamic_range_rgb = 0; /*full range*/ uint8_t dynamic_range_ycbcr = 1; /*bt709*/ + uint8_t dp_pixel_encoding = 0; + uint8_t dp_component_depth = 0; struct dcn10_stream_encoder *enc1 = DCN10STRENC_FROM_STRENC(enc); - REG_UPDATE(DP_DB_CNTL, DP_DB_DISABLE, 1); - /* set pixel encoding */ switch (crtc_timing->pixel_encoding) { case PIXEL_ENCODING_YCBCR422: - REG_UPDATE(DP_PIXEL_FORMAT, DP_PIXEL_ENCODING, - DP_PIXEL_ENCODING_TYPE_YCBCR422); + dp_pixel_encoding = DP_PIXEL_ENCODING_TYPE_YCBCR422; break; case PIXEL_ENCODING_YCBCR444: - REG_UPDATE(DP_PIXEL_FORMAT, DP_PIXEL_ENCODING, - DP_PIXEL_ENCODING_TYPE_YCBCR444); + dp_pixel_encoding = DP_PIXEL_ENCODING_TYPE_YCBCR444; if (crtc_timing->flags.Y_ONLY) if (crtc_timing->display_color_depth != COLOR_DEPTH_666) @@ -278,8 +276,8 @@ void enc1_stream_encoder_dp_set_stream_attribute( * Color depth of Y-only could be * 8, 10, 12, 16 bits */ - REG_UPDATE(DP_PIXEL_FORMAT, DP_PIXEL_ENCODING, - DP_PIXEL_ENCODING_TYPE_Y_ONLY); + dp_pixel_encoding = DP_PIXEL_ENCODING_TYPE_Y_ONLY; + /* Note: DP_MSA_MISC1 bit 7 is the indicator * of Y-only mode. * This bit is set in HW if register @@ -287,48 +285,55 @@ void enc1_stream_encoder_dp_set_stream_attribute( */ break; case PIXEL_ENCODING_YCBCR420: - REG_UPDATE(DP_PIXEL_FORMAT, DP_PIXEL_ENCODING, - DP_PIXEL_ENCODING_TYPE_YCBCR420); + dp_pixel_encoding = DP_PIXEL_ENCODING_TYPE_YCBCR420; REG_UPDATE(DP_VID_TIMING, DP_VID_N_MUL, 1); break; default: - REG_UPDATE(DP_PIXEL_FORMAT, DP_PIXEL_ENCODING, - DP_PIXEL_ENCODING_TYPE_RGB444); + dp_pixel_encoding = DP_PIXEL_ENCODING_TYPE_RGB444; break; } misc1 = REG_READ(DP_MSA_MISC); + /* For YCbCr420 and BT2020 Colorimetry Formats, VSC SDP shall be used. + * When MISC1, bit 6, is Set to 1, a Source device uses a VSC SDP to indicate the + * Pixel Encoding/Colorimetry Format and that a Sink device shall ignore MISC1, bit 7, + * and MISC0, bits 7:1 (MISC1, bit 7, and MISC0, bits 7:1, become "don't care"). + */ + if ((crtc_timing->pixel_encoding == PIXEL_ENCODING_YCBCR420) || + (output_color_space == COLOR_SPACE_2020_YCBCR) || + (output_color_space == COLOR_SPACE_2020_RGB_FULLRANGE) || + (output_color_space == COLOR_SPACE_2020_RGB_LIMITEDRANGE)) + misc1 = misc1 | 0x40; + else + misc1 = misc1 & ~0x40; /* set color depth */ - switch (crtc_timing->display_color_depth) { case COLOR_DEPTH_666: - REG_UPDATE(DP_PIXEL_FORMAT, DP_COMPONENT_DEPTH, - 0); + dp_component_depth = DP_COMPONENT_PIXEL_DEPTH_6BPC; break; case COLOR_DEPTH_888: - REG_UPDATE(DP_PIXEL_FORMAT, DP_COMPONENT_DEPTH, - DP_COMPONENT_PIXEL_DEPTH_8BPC); + dp_component_depth = DP_COMPONENT_PIXEL_DEPTH_8BPC; break; case COLOR_DEPTH_101010: - REG_UPDATE(DP_PIXEL_FORMAT, DP_COMPONENT_DEPTH, - DP_COMPONENT_PIXEL_DEPTH_10BPC); - + dp_component_depth = DP_COMPONENT_PIXEL_DEPTH_10BPC; break; case COLOR_DEPTH_121212: - REG_UPDATE(DP_PIXEL_FORMAT, DP_COMPONENT_DEPTH, - DP_COMPONENT_PIXEL_DEPTH_12BPC); + dp_component_depth = DP_COMPONENT_PIXEL_DEPTH_12BPC; break; case COLOR_DEPTH_161616: - REG_UPDATE(DP_PIXEL_FORMAT, DP_COMPONENT_DEPTH, - DP_COMPONENT_PIXEL_DEPTH_16BPC); + dp_component_depth = DP_COMPONENT_PIXEL_DEPTH_16BPC; break; default: - REG_UPDATE(DP_PIXEL_FORMAT, DP_COMPONENT_DEPTH, - DP_COMPONENT_PIXEL_DEPTH_6BPC); + dp_component_depth = DP_COMPONENT_PIXEL_DEPTH_6BPC; break; } + /* Set DP pixel encoding and component depth */ + REG_UPDATE_2(DP_PIXEL_FORMAT, + DP_PIXEL_ENCODING, dp_pixel_encoding, + DP_COMPONENT_DEPTH, dp_component_depth); + /* set dynamic range and YCbCr range */ switch (crtc_timing->display_color_depth) { @@ -354,7 +359,6 @@ void enc1_stream_encoder_dp_set_stream_attribute( switch (output_color_space) { case COLOR_SPACE_SRGB: - misc0 = misc0 | 0x0; misc1 = misc1 & ~0x80; /* bit7 = 0*/ dynamic_range_rgb = 0; /*full range*/ break; @@ -1087,27 +1091,6 @@ static union audio_cea_channels speakers_to_channels( return cea_channels; } -static uint32_t calc_max_audio_packets_per_line( - const struct audio_crtc_info *crtc_info) -{ - uint32_t max_packets_per_line; - - max_packets_per_line = - crtc_info->h_total - crtc_info->h_active; - - if (crtc_info->pixel_repetition) - max_packets_per_line *= crtc_info->pixel_repetition; - - /* for other hdmi features */ - max_packets_per_line -= 58; - /* for Control Period */ - max_packets_per_line -= 16; - /* Number of Audio Packets per Line */ - max_packets_per_line /= 32; - - return max_packets_per_line; -} - static void get_audio_clock_info( enum dc_color_depth color_depth, uint32_t crtc_pixel_clock_in_khz, @@ -1201,16 +1184,9 @@ static void enc1_se_setup_hdmi_audio( struct dcn10_stream_encoder *enc1 = DCN10STRENC_FROM_STRENC(enc); struct audio_clock_info audio_clock_info = {0}; - uint32_t max_packets_per_line; - - /* For now still do calculation, although this field is ignored when - * above HDMI_PACKET_GEN_VERSION set to 1 - */ - max_packets_per_line = calc_max_audio_packets_per_line(crtc_info); /* HDMI_AUDIO_PACKET_CONTROL */ - REG_UPDATE_2(HDMI_AUDIO_PACKET_CONTROL, - HDMI_AUDIO_PACKETS_PER_LINE, max_packets_per_line, + REG_UPDATE(HDMI_AUDIO_PACKET_CONTROL, HDMI_AUDIO_DELAY_EN, 1); /* AFMT_AUDIO_PACKET_CONTROL */ diff --git a/drivers/gpu/drm/amd/display/dc/dm_services.h b/drivers/gpu/drm/amd/display/dc/dm_services.h index 4ff9b2bba178..eb5ab3978e84 100644 --- a/drivers/gpu/drm/amd/display/dc/dm_services.h +++ b/drivers/gpu/drm/amd/display/dc/dm_services.h @@ -339,7 +339,10 @@ bool dm_dmcu_set_pipe(struct dc_context *ctx, unsigned int controller_id); #define dm_log_to_buffer(buffer, size, fmt, args)\ vsnprintf(buffer, size, fmt, args) -unsigned long long dm_get_timestamp(struct dc_context *ctx); +static inline unsigned long long dm_get_timestamp(struct dc_context *ctx) +{ + return ktime_get_raw_ns(); +} unsigned long long dm_get_elapse_time_in_ns(struct dc_context *ctx, unsigned long long current_time_stamp, diff --git a/drivers/gpu/drm/amd/display/dc/i2caux/aux_engine.c b/drivers/gpu/drm/amd/display/dc/i2caux/aux_engine.c index bb526ad326e5..1d7309611978 100644 --- a/drivers/gpu/drm/amd/display/dc/i2caux/aux_engine.c +++ b/drivers/gpu/drm/amd/display/dc/i2caux/aux_engine.c @@ -157,6 +157,10 @@ static void process_read_reply( ctx->operation_succeeded = false; } break; + case AUX_TRANSACTION_REPLY_HPD_DISCON: + ctx->status = I2CAUX_TRANSACTION_STATUS_FAILED_HPD_DISCON; + ctx->operation_succeeded = false; + break; default: ctx->status = I2CAUX_TRANSACTION_STATUS_UNKNOWN; ctx->operation_succeeded = false; @@ -215,6 +219,10 @@ static void process_read_request( * so we should not wait here */ } break; + case AUX_CHANNEL_OPERATION_FAILED_HPD_DISCON: + ctx->status = I2CAUX_TRANSACTION_STATUS_FAILED_HPD_DISCON; + ctx->operation_succeeded = false; + break; default: ctx->status = I2CAUX_TRANSACTION_STATUS_UNKNOWN; ctx->operation_succeeded = false; @@ -370,6 +378,10 @@ static void process_write_reply( ctx->operation_succeeded = false; } break; + case AUX_TRANSACTION_REPLY_HPD_DISCON: + ctx->status = I2CAUX_TRANSACTION_STATUS_FAILED_HPD_DISCON; + ctx->operation_succeeded = false; + break; default: ctx->status = I2CAUX_TRANSACTION_STATUS_UNKNOWN; ctx->operation_succeeded = false; @@ -422,6 +434,10 @@ static void process_write_request( * so we should not wait here */ } break; + case AUX_CHANNEL_OPERATION_FAILED_HPD_DISCON: + ctx->status = I2CAUX_TRANSACTION_STATUS_FAILED_HPD_DISCON; + ctx->operation_succeeded = false; + break; default: ctx->status = I2CAUX_TRANSACTION_STATUS_UNKNOWN; ctx->operation_succeeded = false; diff --git a/drivers/gpu/drm/amd/display/dc/i2caux/aux_engine.h b/drivers/gpu/drm/amd/display/dc/i2caux/aux_engine.h index 8e71324ccb10..b01488f710d5 100644 --- a/drivers/gpu/drm/amd/display/dc/i2caux/aux_engine.h +++ b/drivers/gpu/drm/amd/display/dc/i2caux/aux_engine.h @@ -26,46 +26,7 @@ #ifndef __DAL_AUX_ENGINE_H__ #define __DAL_AUX_ENGINE_H__ -enum aux_transaction_type { - AUX_TRANSACTION_TYPE_DP, - AUX_TRANSACTION_TYPE_I2C -}; - -struct aux_request_transaction_data { - enum aux_transaction_type type; - enum i2caux_transaction_action action; - /* 20-bit AUX channel transaction address */ - uint32_t address; - /* delay, in 100-microsecond units */ - uint8_t delay; - uint32_t length; - uint8_t *data; -}; - -enum aux_transaction_reply { - AUX_TRANSACTION_REPLY_AUX_ACK = 0x00, - AUX_TRANSACTION_REPLY_AUX_NACK = 0x01, - AUX_TRANSACTION_REPLY_AUX_DEFER = 0x02, - - AUX_TRANSACTION_REPLY_I2C_ACK = 0x00, - AUX_TRANSACTION_REPLY_I2C_NACK = 0x10, - AUX_TRANSACTION_REPLY_I2C_DEFER = 0x20, - - AUX_TRANSACTION_REPLY_INVALID = 0xFF -}; - -struct aux_reply_transaction_data { - enum aux_transaction_reply status; - uint32_t length; - uint8_t *data; -}; - -enum aux_channel_operation_result { - AUX_CHANNEL_OPERATION_SUCCEEDED, - AUX_CHANNEL_OPERATION_FAILED_REASON_UNKNOWN, - AUX_CHANNEL_OPERATION_FAILED_INVALID_REPLY, - AUX_CHANNEL_OPERATION_FAILED_TIMEOUT -}; +#include "dc_ddc_types.h" struct aux_engine; diff --git a/drivers/gpu/drm/amd/display/dc/i2caux/dce110/aux_engine_dce110.c b/drivers/gpu/drm/amd/display/dc/i2caux/dce110/aux_engine_dce110.c index 5f47f6c007ac..2b927f25937b 100644 --- a/drivers/gpu/drm/amd/display/dc/i2caux/dce110/aux_engine_dce110.c +++ b/drivers/gpu/drm/amd/display/dc/i2caux/dce110/aux_engine_dce110.c @@ -198,27 +198,27 @@ static void submit_channel_request( ((request->type == AUX_TRANSACTION_TYPE_I2C) && ((request->action == I2CAUX_TRANSACTION_ACTION_I2C_WRITE) || (request->action == I2CAUX_TRANSACTION_ACTION_I2C_WRITE_MOT))); + if (REG(AUXN_IMPCAL)) { + /* clear_aux_error */ + REG_UPDATE_SEQ(AUXN_IMPCAL, AUXN_CALOUT_ERROR_AK, + 1, + 0); - /* clear_aux_error */ - REG_UPDATE_SEQ(AUXN_IMPCAL, AUXN_CALOUT_ERROR_AK, - 1, - 0); - - REG_UPDATE_SEQ(AUXP_IMPCAL, AUXP_CALOUT_ERROR_AK, - 1, - 0); - - /* force_default_calibrate */ - REG_UPDATE_1BY1_2(AUXN_IMPCAL, - AUXN_IMPCAL_ENABLE, 1, - AUXN_IMPCAL_OVERRIDE_ENABLE, 0); + REG_UPDATE_SEQ(AUXP_IMPCAL, AUXP_CALOUT_ERROR_AK, + 1, + 0); - /* bug? why AUXN update EN and OVERRIDE_EN 1 by 1 while AUX P toggles OVERRIDE? */ + /* force_default_calibrate */ + REG_UPDATE_1BY1_2(AUXN_IMPCAL, + AUXN_IMPCAL_ENABLE, 1, + AUXN_IMPCAL_OVERRIDE_ENABLE, 0); - REG_UPDATE_SEQ(AUXP_IMPCAL, AUXP_IMPCAL_OVERRIDE_ENABLE, - 1, - 0); + /* bug? why AUXN update EN and OVERRIDE_EN 1 by 1 while AUX P toggles OVERRIDE? */ + REG_UPDATE_SEQ(AUXP_IMPCAL, AUXP_IMPCAL_OVERRIDE_ENABLE, + 1, + 0); + } /* set the delay and the number of bytes to write */ /* The length include @@ -291,6 +291,12 @@ static void process_channel_reply( value = REG_GET(AUX_SW_STATUS, AUX_SW_REPLY_BYTE_COUNT, &bytes_replied); + /* in case HPD is LOW, exit AUX transaction */ + if ((value & AUX_SW_STATUS__AUX_SW_HPD_DISCON_MASK)) { + reply->status = AUX_TRANSACTION_REPLY_HPD_DISCON; + return; + } + if (bytes_replied) { uint32_t reply_result; @@ -347,8 +353,10 @@ static void process_channel_reply( * because there was surely an error that was asserted * that should have been handled * for hot plug case, this could happens*/ - if (!(value & AUX_SW_STATUS__AUX_SW_HPD_DISCON_MASK)) + if (!(value & AUX_SW_STATUS__AUX_SW_HPD_DISCON_MASK)) { + reply->status = AUX_TRANSACTION_REPLY_INVALID; ASSERT_CRITICAL(false); + } } } @@ -371,6 +379,10 @@ static enum aux_channel_operation_result get_channel_status( value = REG_WAIT(AUX_SW_STATUS, AUX_SW_DONE, 1, 10, aux110->timeout_period/10); + /* in case HPD is LOW, exit AUX transaction */ + if ((value & AUX_SW_STATUS__AUX_SW_HPD_DISCON_MASK)) + return AUX_CHANNEL_OPERATION_FAILED_HPD_DISCON; + /* Note that the following bits are set in 'status.bits' * during CTS 4.2.1.2 (FW 3.3.1): * AUX_SW_RX_MIN_COUNT_VIOL, AUX_SW_RX_INVALID_STOP, @@ -402,10 +414,10 @@ static enum aux_channel_operation_result get_channel_status( return AUX_CHANNEL_OPERATION_SUCCEEDED; } } else { - /*time_elapsed >= aux_engine->timeout_period */ - if (!(value & AUX_SW_STATUS__AUX_SW_HPD_DISCON_MASK)) - ASSERT_CRITICAL(false); - + /*time_elapsed >= aux_engine->timeout_period + * AUX_SW_STATUS__AUX_SW_HPD_DISCON = at this point + */ + ASSERT_CRITICAL(false); return AUX_CHANNEL_OPERATION_FAILED_TIMEOUT; } } diff --git a/drivers/gpu/drm/amd/display/dc/i2caux/engine.h b/drivers/gpu/drm/amd/display/dc/i2caux/engine.h index 33de8a8834dc..1e8a1585e401 100644 --- a/drivers/gpu/drm/amd/display/dc/i2caux/engine.h +++ b/drivers/gpu/drm/amd/display/dc/i2caux/engine.h @@ -26,6 +26,8 @@ #ifndef __DAL_ENGINE_H__ #define __DAL_ENGINE_H__ +#include "dc_ddc_types.h" + enum i2caux_transaction_operation { I2CAUX_TRANSACTION_READ, I2CAUX_TRANSACTION_WRITE @@ -53,7 +55,8 @@ enum i2caux_transaction_status { I2CAUX_TRANSACTION_STATUS_FAILED_INCOMPLETE, I2CAUX_TRANSACTION_STATUS_FAILED_OPERATION, I2CAUX_TRANSACTION_STATUS_FAILED_INVALID_OPERATION, - I2CAUX_TRANSACTION_STATUS_FAILED_BUFFER_OVERFLOW + I2CAUX_TRANSACTION_STATUS_FAILED_BUFFER_OVERFLOW, + I2CAUX_TRANSACTION_STATUS_FAILED_HPD_DISCON }; struct i2caux_transaction_request { @@ -75,19 +78,6 @@ enum i2c_default_speed { I2CAUX_DEFAULT_I2C_SW_SPEED = 50 }; -enum i2caux_transaction_action { - I2CAUX_TRANSACTION_ACTION_I2C_WRITE = 0x00, - I2CAUX_TRANSACTION_ACTION_I2C_READ = 0x10, - I2CAUX_TRANSACTION_ACTION_I2C_STATUS_REQUEST = 0x20, - - I2CAUX_TRANSACTION_ACTION_I2C_WRITE_MOT = 0x40, - I2CAUX_TRANSACTION_ACTION_I2C_READ_MOT = 0x50, - I2CAUX_TRANSACTION_ACTION_I2C_STATUS_REQUEST_MOT = 0x60, - - I2CAUX_TRANSACTION_ACTION_DP_WRITE = 0x80, - I2CAUX_TRANSACTION_ACTION_DP_READ = 0x90 -}; - struct engine; struct engine_funcs { diff --git a/drivers/gpu/drm/amd/display/dc/inc/core_types.h b/drivers/gpu/drm/amd/display/dc/inc/core_types.h index a94942d4e66b..4beddca0180c 100644 --- a/drivers/gpu/drm/amd/display/dc/inc/core_types.h +++ b/drivers/gpu/drm/amd/display/dc/inc/core_types.h @@ -148,6 +148,7 @@ struct resource_pool { unsigned int underlay_pipe_index; unsigned int stream_enc_count; unsigned int ref_clock_inKhz; + unsigned int dentist_vco_freq_khz; unsigned int timing_generator_count; /* diff --git a/drivers/gpu/drm/amd/display/dc/inc/hw/timing_generator.h b/drivers/gpu/drm/amd/display/dc/inc/hw/timing_generator.h index 69cb0a105300..af700c7dac50 100644 --- a/drivers/gpu/drm/amd/display/dc/inc/hw/timing_generator.h +++ b/drivers/gpu/drm/amd/display/dc/inc/hw/timing_generator.h @@ -156,6 +156,9 @@ struct timing_generator_funcs { uint32_t *v_blank_end, uint32_t *h_position, uint32_t *v_position); + bool (*get_otg_active_size)(struct timing_generator *optc, + uint32_t *otg_active_width, + uint32_t *otg_active_height); void (*set_early_control)(struct timing_generator *tg, uint32_t early_cntl); void (*wait_for_state)(struct timing_generator *tg, diff --git a/drivers/gpu/drm/amd/display/dc/inc/hw_sequencer.h b/drivers/gpu/drm/amd/display/dc/inc/hw_sequencer.h index 63fc6c499789..a71770ed4b9f 100644 --- a/drivers/gpu/drm/amd/display/dc/inc/hw_sequencer.h +++ b/drivers/gpu/drm/amd/display/dc/inc/hw_sequencer.h @@ -154,14 +154,18 @@ struct hw_sequencer_funcs { struct dc_link_settings *link_settings); void (*blank_stream)(struct pipe_ctx *pipe_ctx); + + void (*enable_audio_stream)(struct pipe_ctx *pipe_ctx); + + void (*disable_audio_stream)(struct pipe_ctx *pipe_ctx, int option); + void (*pipe_control_lock)( struct dc *dc, struct pipe_ctx *pipe, bool lock); void (*blank_pixel_data)( struct dc *dc, - struct stream_resource *stream_res, - struct dc_stream_state *stream, + struct pipe_ctx *pipe_ctx, bool blank); void (*set_bandwidth)( diff --git a/drivers/gpu/drm/amd/display/dc/inc/resource.h b/drivers/gpu/drm/amd/display/dc/inc/resource.h index 640a647f4611..e92facbd038f 100644 --- a/drivers/gpu/drm/amd/display/dc/inc/resource.h +++ b/drivers/gpu/drm/amd/display/dc/inc/resource.h @@ -38,6 +38,7 @@ enum dce_version resource_parse_asic_id( struct resource_caps { int num_timing_generator; + int num_opp; int num_video_plane; int num_audio; int num_stream_encoder; diff --git a/drivers/gpu/drm/amd/display/include/ddc_service_types.h b/drivers/gpu/drm/amd/display/include/ddc_service_types.h index 019e7a095ea1..d968956a10cd 100644 --- a/drivers/gpu/drm/amd/display/include/ddc_service_types.h +++ b/drivers/gpu/drm/amd/display/include/ddc_service_types.h @@ -40,7 +40,8 @@ enum ddc_result { DDC_RESULT_FAILED_INCOMPLETE, DDC_RESULT_FAILED_OPERATION, DDC_RESULT_FAILED_INVALID_OPERATION, - DDC_RESULT_FAILED_BUFFER_OVERFLOW + DDC_RESULT_FAILED_BUFFER_OVERFLOW, + DDC_RESULT_FAILED_HPD_DISCON }; enum ddc_service_type { diff --git a/drivers/gpu/drm/amd/display/include/fixed31_32.h b/drivers/gpu/drm/amd/display/include/fixed31_32.h index a981b3e99ab3..52a73332befb 100644 --- a/drivers/gpu/drm/amd/display/include/fixed31_32.h +++ b/drivers/gpu/drm/amd/display/include/fixed31_32.h @@ -26,6 +26,13 @@ #ifndef __DAL_FIXED31_32_H__ #define __DAL_FIXED31_32_H__ +#ifndef LLONG_MAX +#define LLONG_MAX 9223372036854775807ll +#endif +#ifndef LLONG_MIN +#define LLONG_MIN (-LLONG_MAX - 1ll) +#endif + #define FIXED31_32_BITS_PER_FRACTIONAL_PART 32 #ifndef LLONG_MIN #define LLONG_MIN (1LL<<63) diff --git a/drivers/gpu/drm/amd/display/include/logger_interface.h b/drivers/gpu/drm/amd/display/include/logger_interface.h index dc98d6d4b2bd..0f10ed710e0d 100644 --- a/drivers/gpu/drm/amd/display/include/logger_interface.h +++ b/drivers/gpu/drm/amd/display/include/logger_interface.h @@ -62,6 +62,8 @@ void dm_logger_append_va( const char *msg, va_list args); +void dm_logger_append_heading(struct log_entry *entry); + void dm_logger_open( struct dal_logger *logger, struct log_entry *entry, diff --git a/drivers/gpu/drm/amd/display/modules/color/color_gamma.c b/drivers/gpu/drm/amd/display/modules/color/color_gamma.c index eee0dfad6962..98edaefa2b47 100644 --- a/drivers/gpu/drm/amd/display/modules/color/color_gamma.c +++ b/drivers/gpu/drm/amd/display/modules/color/color_gamma.c @@ -131,6 +131,63 @@ static void compute_de_pq(struct fixed31_32 in_x, struct fixed31_32 *out_y) dc_fixpt_div(dc_fixpt_one, m1)); } + +/*de gamma, none linear to linear*/ +static void compute_hlg_oetf(struct fixed31_32 in_x, bool is_light0_12, struct fixed31_32 *out_y) +{ + struct fixed31_32 a; + struct fixed31_32 b; + struct fixed31_32 c; + struct fixed31_32 threshold; + struct fixed31_32 reference_white_level; + + a = dc_fixpt_from_fraction(17883277, 100000000); + if (is_light0_12) { + /*light 0-12*/ + b = dc_fixpt_from_fraction(28466892, 100000000); + c = dc_fixpt_from_fraction(55991073, 100000000); + threshold = dc_fixpt_one; + reference_white_level = dc_fixpt_half; + } else { + /*light 0-1*/ + b = dc_fixpt_from_fraction(2372241, 100000000); + c = dc_fixpt_add(dc_fixpt_one, dc_fixpt_from_fraction(429347, 100000000)); + threshold = dc_fixpt_from_fraction(1, 12); + reference_white_level = dc_fixpt_pow(dc_fixpt_from_fraction(3, 1), dc_fixpt_half); + } + if (dc_fixpt_lt(threshold, in_x)) + *out_y = dc_fixpt_add(c, dc_fixpt_mul(a, dc_fixpt_log(dc_fixpt_sub(in_x, b)))); + else + *out_y = dc_fixpt_mul(dc_fixpt_pow(in_x, dc_fixpt_half), reference_white_level); +} + +/*re gamma, linear to none linear*/ +static void compute_hlg_eotf(struct fixed31_32 in_x, bool is_light0_12, struct fixed31_32 *out_y) +{ + struct fixed31_32 a; + struct fixed31_32 b; + struct fixed31_32 c; + struct fixed31_32 reference_white_level; + + a = dc_fixpt_from_fraction(17883277, 100000000); + if (is_light0_12) { + /*light 0-12*/ + b = dc_fixpt_from_fraction(28466892, 100000000); + c = dc_fixpt_from_fraction(55991073, 100000000); + reference_white_level = dc_fixpt_from_fraction(4, 1); + } else { + /*light 0-1*/ + b = dc_fixpt_from_fraction(2372241, 100000000); + c = dc_fixpt_add(dc_fixpt_one, dc_fixpt_from_fraction(429347, 100000000)); + reference_white_level = dc_fixpt_from_fraction(1, 3); + } + if (dc_fixpt_lt(dc_fixpt_half, in_x)) + *out_y = dc_fixpt_add(dc_fixpt_exp(dc_fixpt_div(dc_fixpt_sub(in_x, c), a)), b); + else + *out_y = dc_fixpt_mul(dc_fixpt_pow(in_x, dc_fixpt_from_fraction(2, 1)), reference_white_level); +} + + /* one-time pre-compute PQ values - only for sdr_white_level 80 */ void precompute_pq(void) { @@ -691,6 +748,48 @@ static void build_degamma(struct pwl_float_data_ex *curve, } } +static void build_hlg_degamma(struct pwl_float_data_ex *degamma, + uint32_t hw_points_num, + const struct hw_x_point *coordinate_x, bool is_light0_12) +{ + uint32_t i; + + struct pwl_float_data_ex *rgb = degamma; + const struct hw_x_point *coord_x = coordinate_x; + + i = 0; + + while (i != hw_points_num + 1) { + compute_hlg_oetf(coord_x->x, is_light0_12, &rgb->r); + rgb->g = rgb->r; + rgb->b = rgb->r; + ++coord_x; + ++rgb; + ++i; + } +} + +static void build_hlg_regamma(struct pwl_float_data_ex *regamma, + uint32_t hw_points_num, + const struct hw_x_point *coordinate_x, bool is_light0_12) +{ + uint32_t i; + + struct pwl_float_data_ex *rgb = regamma; + const struct hw_x_point *coord_x = coordinate_x; + + i = 0; + + while (i != hw_points_num + 1) { + compute_hlg_eotf(coord_x->x, is_light0_12, &rgb->r); + rgb->g = rgb->r; + rgb->b = rgb->r; + ++coord_x; + ++rgb; + ++i; + } +} + static void scale_gamma(struct pwl_float_data *pwl_rgb, const struct dc_gamma *ramp, struct dividers dividers) @@ -1622,6 +1721,25 @@ bool mod_color_calculate_curve(enum dc_transfer_func_predefined trans, ret = true; kvfree(rgb_regamma); + } else if (trans == TRANSFER_FUNCTION_HLG || + trans == TRANSFER_FUNCTION_HLG12) { + rgb_regamma = kvzalloc(sizeof(*rgb_regamma) * + (MAX_HW_POINTS + _EXTRA_POINTS), + GFP_KERNEL); + if (!rgb_regamma) + goto rgb_regamma_alloc_fail; + + build_hlg_regamma(rgb_regamma, + MAX_HW_POINTS, + coordinates_x, + trans == TRANSFER_FUNCTION_HLG12 ? true:false); + for (i = 0; i <= MAX_HW_POINTS ; i++) { + points->red[i] = rgb_regamma[i].r; + points->green[i] = rgb_regamma[i].g; + points->blue[i] = rgb_regamma[i].b; + } + ret = true; + kvfree(rgb_regamma); } rgb_regamma_alloc_fail: return ret; @@ -1682,6 +1800,25 @@ bool mod_color_calculate_degamma_curve(enum dc_transfer_func_predefined trans, ret = true; kvfree(rgb_degamma); + } else if (trans == TRANSFER_FUNCTION_HLG || + trans == TRANSFER_FUNCTION_HLG12) { + rgb_degamma = kvzalloc(sizeof(*rgb_degamma) * + (MAX_HW_POINTS + _EXTRA_POINTS), + GFP_KERNEL); + if (!rgb_degamma) + goto rgb_degamma_alloc_fail; + + build_hlg_degamma(rgb_degamma, + MAX_HW_POINTS, + coordinates_x, + trans == TRANSFER_FUNCTION_HLG12 ? true:false); + for (i = 0; i <= MAX_HW_POINTS ; i++) { + points->red[i] = rgb_degamma[i].r; + points->green[i] = rgb_degamma[i].g; + points->blue[i] = rgb_degamma[i].b; + } + ret = true; + kvfree(rgb_degamma); } points->end_exponent = 0; points->x_point_at_y1_red = 1; diff --git a/drivers/gpu/drm/amd/display/modules/stats/stats.c b/drivers/gpu/drm/amd/display/modules/stats/stats.c index 710852ad03f3..3d4c1b1ab8c4 100644 --- a/drivers/gpu/drm/amd/display/modules/stats/stats.c +++ b/drivers/gpu/drm/amd/display/modules/stats/stats.c @@ -29,7 +29,7 @@ #include "core_types.h" #define DAL_STATS_ENABLE_REGKEY "DalStatsEnable" -#define DAL_STATS_ENABLE_REGKEY_DEFAULT 0x00000001 +#define DAL_STATS_ENABLE_REGKEY_DEFAULT 0x00000000 #define DAL_STATS_ENABLE_REGKEY_ENABLED 0x00000001 #define DAL_STATS_ENTRIES_REGKEY "DalStatsEntries" @@ -238,7 +238,7 @@ void mod_stats_dump(struct mod_stats *mod_stats) for (int i = 0; i < core_stats->entry_id; i++) { if (event_index < core_stats->event_index && i == events[event_index].entry_id) { - DISPLAY_STATS("%s\n", events[event_index].event_string); + DISPLAY_STATS("==Event==%s\n", events[event_index].event_string); event_index++; } else if (time_index < core_stats->index && i == time[time_index].entry_id) { |