From b73581329adb9e8105277a463a4d1801868b22e7 Mon Sep 17 00:00:00 2001 From: Alex Deucher Date: Wed, 26 Jun 2024 17:35:41 -0400 Subject: drm/amd/display: use vmalloc for struct dc_state This is a big structure so use vmalloc as malloc can fail when there is memory pressure. Closes: https://gitlab.freedesktop.org/drm/amd/-/issues/3454 Reviewed-by: Mario Limonciello Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_mst_types.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_mst_types.c b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_mst_types.c index 5d4f831b1e55..5442da90f508 100644 --- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_mst_types.c +++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_mst_types.c @@ -23,6 +23,7 @@ * */ +#include #include #include #include @@ -1491,9 +1492,10 @@ int pre_validate_dsc(struct drm_atomic_state *state, * from dm_state->context. */ - local_dc_state = kmemdup(dm_state->context, sizeof(struct dc_state), GFP_KERNEL); + local_dc_state = vmalloc(sizeof(struct dc_state)); if (!local_dc_state) return -ENOMEM; + memcpy(local_dc_state, dm_state->context, sizeof(struct dc_state)); for (i = 0; i < local_dc_state->stream_count; i++) { struct dc_stream_state *stream = dm_state->context->streams[i]; @@ -1563,7 +1565,7 @@ clean_exit: dc_stream_release(local_dc_state->streams[i]); } - kfree(local_dc_state); + vfree(local_dc_state); return ret; } -- cgit From 21ba615af622a6bded6931499bb28a31749c840b Mon Sep 17 00:00:00 2001 From: Anthony Koo Date: Sat, 15 Jun 2024 12:51:44 -0400 Subject: drm/amd/display: Add replay state entry to replay_state - Add new Replay states 2A (initial Replay entry) and 4E (frame update) to check is there is new frame update before sending Acked-by: Rodrigo Siqueira Signed-off-by: Jerry Zuo Signed-off-by: Anthony Koo Tested-by: Daniel Wheeler Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/dmub/inc/dmub_cmd.h | 2 ++ 1 file changed, 2 insertions(+) diff --git a/drivers/gpu/drm/amd/display/dmub/inc/dmub_cmd.h b/drivers/gpu/drm/amd/display/dmub/inc/dmub_cmd.h index 78e8698fe378..605dd9d45167 100644 --- a/drivers/gpu/drm/amd/display/dmub/inc/dmub_cmd.h +++ b/drivers/gpu/drm/amd/display/dmub/inc/dmub_cmd.h @@ -3326,6 +3326,7 @@ enum replay_state { REPLAY_STATE_1 = 0x10, REPLAY_STATE_1A = 0x11, REPLAY_STATE_2 = 0x20, + REPLAY_STATE_2A = 0x21, REPLAY_STATE_3 = 0x30, REPLAY_STATE_3INIT = 0x31, REPLAY_STATE_4 = 0x40, @@ -3333,6 +3334,7 @@ enum replay_state { REPLAY_STATE_4B = 0x42, REPLAY_STATE_4C = 0x43, REPLAY_STATE_4D = 0x44, + REPLAY_STATE_4E = 0x45, REPLAY_STATE_4B_LOCKED = 0x4A, REPLAY_STATE_4C_UNLOCKED = 0x4B, REPLAY_STATE_5 = 0x50, -- cgit From eb6dfbb7a9c67c7d9bcdb9f9b9131270e2144e3d Mon Sep 17 00:00:00 2001 From: Tom Chung Date: Mon, 17 Jun 2024 15:59:06 +0800 Subject: drm/amd/display: Reset freesync config before update new state [Why] Sometimes the new_crtc_state->vrr_infopacket did not sync up with the current state. It will affect the update_freesync_state_on_stream() does not update the state correctly. [How] Reset the freesync config before get_freesync_config_for_crtc() to make sure we have the correct new_crtc_state for VRR. Reviewed-by: Sun peng Li Signed-off-by: Jerry Zuo Signed-off-by: Tom Chung Tested-by: Daniel Wheeler Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c | 1 + 1 file changed, 1 insertion(+) 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 d743e2705399..0daf2b787d2f 100644 --- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c +++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c @@ -10462,6 +10462,7 @@ skip_modeset: } /* Update Freesync settings. */ + reset_freesync_config_for_crtc(dm_new_crtc_state); get_freesync_config_for_crtc(dm_new_crtc_state, dm_new_conn_state); -- cgit From ac01f6ad710c41c8c2cfab24be8bb71586bf8c44 Mon Sep 17 00:00:00 2001 From: George Shen Date: Fri, 14 Jun 2024 21:13:43 -0400 Subject: drm/amd/display: Fix divide by zero in CURSOR_DST_X_OFFSET calculation [Why] Certain situations cause pipes to have a recout of 0, such as when the dst_rect lies completely outside of a given ODM slice. [How] Skip calculation that transforms cursor coordinates to viewport space. Reviewed-by: Alvin Lee Signed-off-by: Jerry Zuo Signed-off-by: George Shen Tested-by: Daniel Wheeler Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/dc/hubp/dcn401/dcn401_hubp.c | 15 +++++++++++++-- 1 file changed, 13 insertions(+), 2 deletions(-) diff --git a/drivers/gpu/drm/amd/display/dc/hubp/dcn401/dcn401_hubp.c b/drivers/gpu/drm/amd/display/dc/hubp/dcn401/dcn401_hubp.c index f0c45a74c2e5..eb0da6c6b87c 100644 --- a/drivers/gpu/drm/amd/display/dc/hubp/dcn401/dcn401_hubp.c +++ b/drivers/gpu/drm/amd/display/dc/hubp/dcn401/dcn401_hubp.c @@ -677,12 +677,23 @@ void hubp401_cursor_set_position( int rec_x_offset = x_pos - pos->x_hotspot; int rec_y_offset = y_pos - pos->y_hotspot; int dst_x_offset; - int x_pos_viewport = x_pos * param->viewport.width / param->recout.width; - int x_hot_viewport = pos->x_hotspot * param->viewport.width / param->recout.width; + int x_pos_viewport = 0; + int x_hot_viewport = 0; uint32_t cur_en = pos->enable ? 1 : 0; hubp->curs_pos = *pos; + /* Recout is zero for pipes if the entire dst_rect is contained + * within preceeding ODM slices. + */ + if (param->recout.width) { + x_pos_viewport = x_pos * param->viewport.width / param->recout.width; + x_hot_viewport = pos->x_hotspot * param->viewport.width / param->recout.width; + } else { + ASSERT(!cur_en || x_pos == 0); + ASSERT(!cur_en || pos->x_hotspot == 0); + } + /* * Guard aganst cursor_set_position() from being called with invalid * attributes -- cgit From 032831f223bce58e2fea9542cade0ae9789dc378 Mon Sep 17 00:00:00 2001 From: Joshua Aberback Date: Mon, 17 Jun 2024 15:22:44 -0400 Subject: drm/amd/display: Remove unnecessary error message [Why] This error message is unnecessary because returning when aconnector is uninitialized is the desired outcome during initialization. As well, there is no equivalent error message for read_dpcd. Reviewed-by: Aurabindo Pillai Signed-off-by: Jerry Zuo Signed-off-by: Joshua Aberback Tested-by: Daniel Wheeler Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_helpers.c | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) 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 97614947d75b..b490ae67b6be 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 @@ -575,10 +575,8 @@ bool dm_helpers_dp_write_dpcd( { struct amdgpu_dm_connector *aconnector = link->priv; - if (!aconnector) { - DRM_ERROR("Failed to find connector for link!"); + if (!aconnector) return false; - } return drm_dp_dpcd_write(&aconnector->dm_dp_aux.aux, address, (uint8_t *)data, size) > 0; -- cgit From 73b8a388eb0c1328dab1161e42eed3d7b507764b Mon Sep 17 00:00:00 2001 From: Sung Joon Kim Date: Fri, 14 Jun 2024 19:14:31 -0400 Subject: drm/amd/display: Choose HUBP unbounded request based on DML output [why] Previously, we decide on the unbounded request purely based on pipe_cnt which is a wrong variable to use to determine how many pipes are in "use". DML already accounts for number of pipes in use along with other various factors and is a more reliable method of determination. [how] Use UnboundedRequestEnabledThisState to decide on unbounbded_req_enabled. Reviewed-by: Nicholas Kazlauskas Signed-off-by: Jerry Zuo Signed-off-by: Sung Joon Kim Tested-by: Daniel Wheeler Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/dc/dml2/dml2_utils.c | 12 ++---------- 1 file changed, 2 insertions(+), 10 deletions(-) diff --git a/drivers/gpu/drm/amd/display/dc/dml2/dml2_utils.c b/drivers/gpu/drm/amd/display/dc/dml2/dml2_utils.c index 0f8b3336e26d..d91948d6ff97 100644 --- a/drivers/gpu/drm/amd/display/dc/dml2/dml2_utils.c +++ b/drivers/gpu/drm/amd/display/dc/dml2/dml2_utils.c @@ -288,7 +288,6 @@ void dml2_calculate_rq_and_dlg_params(const struct dc *dc, struct dc_state *cont { unsigned int dc_pipe_ctx_index, dml_pipe_idx, plane_id; enum mall_stream_type pipe_mall_type; - bool unbounded_req_enabled = false; struct dml2_calculate_rq_and_dlg_params_scratch *s = &in_ctx->v20.scratch.calculate_rq_and_dlg_params_scratch; context->bw_ctx.bw.dcn.clk.dcfclk_deep_sleep_khz = (unsigned int)in_ctx->v20.dml_core_ctx.mp.DCFCLKDeepSleep * 1000; @@ -302,14 +301,6 @@ void dml2_calculate_rq_and_dlg_params(const struct dc *dc, struct dc_state *cont if (context->bw_ctx.bw.dcn.clk.dispclk_khz < dc->debug.min_disp_clk_khz) context->bw_ctx.bw.dcn.clk.dispclk_khz = dc->debug.min_disp_clk_khz; - unbounded_req_enabled = in_ctx->v20.dml_core_ctx.ms.UnboundedRequestEnabledThisState; - - if (unbounded_req_enabled && pipe_cnt > 1) { - // Unbounded requesting should not ever be used when more than 1 pipe is enabled. - //ASSERT(false); - unbounded_req_enabled = false; - } - context->bw_ctx.bw.dcn.compbuf_size_kb = in_ctx->v20.dml_core_ctx.ip.config_return_buffer_size_in_kbytes; for (dc_pipe_ctx_index = 0; dc_pipe_ctx_index < pipe_cnt; dc_pipe_ctx_index++) { @@ -344,7 +335,8 @@ void dml2_calculate_rq_and_dlg_params(const struct dc *dc, struct dc_state *cont context->res_ctx.pipe_ctx[dc_pipe_ctx_index].unbounded_req = false; } else { context->res_ctx.pipe_ctx[dc_pipe_ctx_index].det_buffer_size_kb = dml_get_det_buffer_size_kbytes(&context->bw_ctx.dml2->v20.dml_core_ctx, dml_pipe_idx); - context->res_ctx.pipe_ctx[dc_pipe_ctx_index].unbounded_req = unbounded_req_enabled; + // Unbounded requesting should not ever be used when more than 1 pipe is enabled. + context->res_ctx.pipe_ctx[dc_pipe_ctx_index].unbounded_req = in_ctx->v20.dml_core_ctx.ms.UnboundedRequestEnabledThisState; } context->bw_ctx.bw.dcn.compbuf_size_kb -= context->res_ctx.pipe_ctx[dc_pipe_ctx_index].det_buffer_size_kb; -- cgit From 02b438afc63b79490abb3ce82acfd6b49b88b34e Mon Sep 17 00:00:00 2001 From: Teeger Date: Wed, 19 Jun 2024 09:26:40 -0400 Subject: drm/amd/display: Revert Add workaround to restrict max frac urgent for DPM0 This reverts commit 871512e36f9c1c2cb4e62eb860ca0438800e4d63 due to multiple issues found. Reviewed-by: Nicholas Kazlauskas Signed-off-by: Jerry Zuo Signed-off-by: Teeger Tested-by: Daniel Wheeler Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/dc/dml2/dml2_wrapper.c | 15 --------------- drivers/gpu/drm/amd/display/dc/dml2/dml2_wrapper.h | 2 -- .../drm/amd/display/dc/resource/dcn35/dcn35_resource.c | 2 -- 3 files changed, 19 deletions(-) diff --git a/drivers/gpu/drm/amd/display/dc/dml2/dml2_wrapper.c b/drivers/gpu/drm/amd/display/dc/dml2/dml2_wrapper.c index c58235121474..d5dcc8b77281 100644 --- a/drivers/gpu/drm/amd/display/dc/dml2/dml2_wrapper.c +++ b/drivers/gpu/drm/amd/display/dc/dml2/dml2_wrapper.c @@ -626,21 +626,6 @@ static bool dml2_validate_and_build_resource(const struct dc *in_dc, struct dc_s if (result) { unsigned int lowest_state_idx = s->mode_support_params.out_lowest_state_idx; - double min_fclk_mhz_for_urgent_workaround = (double)dml2->config.min_fclk_for_urgent_workaround_khz / 1000.0; - double max_frac_urgent = (double)dml2->config.max_frac_urgent_for_min_fclk_x1000 / 1000.0; - - if (min_fclk_mhz_for_urgent_workaround > 0.0 && max_frac_urgent > 0.0 && - (dml2->v20.dml_core_ctx.mp.FractionOfUrgentBandwidth > max_frac_urgent || - dml2->v20.dml_core_ctx.mp.FractionOfUrgentBandwidthImmediateFlip > max_frac_urgent)) { - unsigned int forced_lowest_state_idx = lowest_state_idx; - - while (forced_lowest_state_idx < dml2->v20.dml_core_ctx.states.num_states && - dml2->v20.dml_core_ctx.states.state_array[forced_lowest_state_idx].fabricclk_mhz <= min_fclk_mhz_for_urgent_workaround) { - forced_lowest_state_idx += 1; - } - lowest_state_idx = forced_lowest_state_idx; - } - out_clks.dispclk_khz = (unsigned int)dml2->v20.dml_core_ctx.mp.Dispclk_calculated * 1000; out_clks.p_state_supported = s->mode_support_info.DRAMClockChangeSupport[0] != dml_dram_clock_change_unsupported; if (in_dc->config.use_default_clock_table && diff --git a/drivers/gpu/drm/amd/display/dc/dml2/dml2_wrapper.h b/drivers/gpu/drm/amd/display/dc/dml2/dml2_wrapper.h index 6e3d52eb45c7..023325e8f6e2 100644 --- a/drivers/gpu/drm/amd/display/dc/dml2/dml2_wrapper.h +++ b/drivers/gpu/drm/amd/display/dc/dml2/dml2_wrapper.h @@ -237,8 +237,6 @@ struct dml2_configuration_options { bool use_clock_dc_limits; bool gpuvm_enable; struct dml2_soc_bb *bb_from_dmub; - int max_frac_urgent_for_min_fclk_x1000; - int min_fclk_for_urgent_workaround_khz; }; /* diff --git a/drivers/gpu/drm/amd/display/dc/resource/dcn35/dcn35_resource.c b/drivers/gpu/drm/amd/display/dc/resource/dcn35/dcn35_resource.c index 1ce0f9ecff9c..ddf251901fb3 100644 --- a/drivers/gpu/drm/amd/display/dc/resource/dcn35/dcn35_resource.c +++ b/drivers/gpu/drm/amd/display/dc/resource/dcn35/dcn35_resource.c @@ -2153,8 +2153,6 @@ static bool dcn35_resource_construct( dc->dml2_options.max_segments_per_hubp = 24; dc->dml2_options.det_segment_size = DCN3_2_DET_SEG_SIZE;/*todo*/ - dc->dml2_options.max_frac_urgent_for_min_fclk_x1000 = 900; - dc->dml2_options.min_fclk_for_urgent_workaround_khz = 400 * 1000; if (dc->config.sdpif_request_limit_words_per_umc == 0) dc->config.sdpif_request_limit_words_per_umc = 16;/*todo*/ -- cgit From 95134e5852978a92d2290a3b1ee93189e75507ac Mon Sep 17 00:00:00 2001 From: George Shen Date: Mon, 17 Jun 2024 16:32:15 -0400 Subject: drm/amd/display: Add ASIC cap to limit DCC surface width [Why] Certain configurations of DCN401 require ODM4:1 to support DCC for 10K surfaces. DCC should be conservatively disabled in those cases. The issue is that current logic limits 10K surface DCC for all configurations of DCN401. [How] Add DC ASIC cap to indicate max surface width that can support DCC. Disable DCC if this ASIC cap is non-zero and surface width exceeds it. Reviewed-by: Jun Lei Signed-off-by: Jerry Zuo Signed-off-by: George Shen Tested-by: Daniel Wheeler Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/dc/dc.h | 2 ++ drivers/gpu/drm/amd/display/dc/hubbub/dcn401/dcn401_hubbub.c | 6 ++++++ drivers/gpu/drm/amd/display/dc/resource/dcn401/dcn401_resource.c | 3 +++ 3 files changed, 11 insertions(+) diff --git a/drivers/gpu/drm/amd/display/dc/dc.h b/drivers/gpu/drm/amd/display/dc/dc.h index 900892855436..55b94a72ddc2 100644 --- a/drivers/gpu/drm/amd/display/dc/dc.h +++ b/drivers/gpu/drm/amd/display/dc/dc.h @@ -293,6 +293,8 @@ struct dc_caps { bool cursor_not_scaled; bool dcmode_power_limits_present; bool sequential_ono; + /* Conservative limit for DCC cases which require ODM4:1 to support*/ + uint32_t dcc_plane_width_limit; }; struct dc_bug_wa { diff --git a/drivers/gpu/drm/amd/display/dc/hubbub/dcn401/dcn401_hubbub.c b/drivers/gpu/drm/amd/display/dc/hubbub/dcn401/dcn401_hubbub.c index 5126d603f0b1..181041d6d177 100644 --- a/drivers/gpu/drm/amd/display/dc/hubbub/dcn401/dcn401_hubbub.c +++ b/drivers/gpu/drm/amd/display/dc/hubbub/dcn401/dcn401_hubbub.c @@ -829,6 +829,7 @@ bool hubbub401_get_dcc_compression_cap(struct hubbub *hubbub, struct dc_surface_dcc_cap *output) { struct dc *dc = hubbub->ctx->dc; + const unsigned int max_dcc_plane_width = dc->caps.dcc_plane_width_limit; /* DCN4_Programming_Guide_DCHUB.docx, Section 5.11.2.2 */ enum dcc_control dcc_control; unsigned int plane0_bpe, plane1_bpe; @@ -843,6 +844,11 @@ bool hubbub401_get_dcc_compression_cap(struct hubbub *hubbub, if (dc->debug.disable_dcc == DCC_DISABLE) return false; + /* Conservatively disable DCC for cases where ODM4:1 may be required. */ + if (max_dcc_plane_width != 0 && + (input->surface_size.width > max_dcc_plane_width || input->plane1_size.width > max_dcc_plane_width)) + return false; + switch (input->format) { default: is_dual_plane = false; diff --git a/drivers/gpu/drm/amd/display/dc/resource/dcn401/dcn401_resource.c b/drivers/gpu/drm/amd/display/dc/resource/dcn401/dcn401_resource.c index 4e27d2cee9fb..a05a2209a44e 100644 --- a/drivers/gpu/drm/amd/display/dc/resource/dcn401/dcn401_resource.c +++ b/drivers/gpu/drm/amd/display/dc/resource/dcn401/dcn401_resource.c @@ -1822,6 +1822,9 @@ static bool dcn401_resource_construct( dc->caps.extended_aux_timeout_support = true; dc->caps.dmcub_support = true; + if (ASICREV_IS_GC_12_0_1_A0(dc->ctx->asic_id.hw_internal_rev)) + dc->caps.dcc_plane_width_limit = 7680; + /* Color pipeline capabilities */ dc->caps.color.dpp.dcn_arch = 1; dc->caps.color.dpp.input_lut_shared = 0; -- cgit From bbd0d1c942cbac87404ed2bca0aa4f7907b8f47f Mon Sep 17 00:00:00 2001 From: Alex Hung Date: Fri, 7 Jun 2024 22:09:53 -0600 Subject: drm/amd/display: Fix possible overflow in integer multiplication [WHAT & HOW] Integer multiplies integer may overflow in context that expects an expression of unsigned/siged long long (64 bits). This can be fixed by casting integer to unsigned/siged long long to force 64 bits results. This fixes 26 OVERFLOW_BEFORE_WIDEN issues reported by Coverity. Reviewed-by: Harry Wentland Signed-off-by: Jerry Zuo Signed-off-by: Alex Hung Tested-by: Daniel Wheeler Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_psr.c | 2 +- drivers/gpu/drm/amd/display/dc/basics/dce_calcs.c | 2 +- drivers/gpu/drm/amd/display/dc/clk_mgr/dcn32/dcn32_clk_mgr.c | 2 +- drivers/gpu/drm/amd/display/dc/core/dc_resource.c | 8 ++++---- drivers/gpu/drm/amd/display/dc/core/dc_stream.c | 6 +++--- drivers/gpu/drm/amd/display/dc/dce/dce_audio.c | 2 +- drivers/gpu/drm/amd/display/dc/dce/dce_clock_source.c | 8 ++++---- drivers/gpu/drm/amd/display/dc/dce/dce_panel_cntl.c | 2 +- drivers/gpu/drm/amd/display/dc/dml/dcn32/dcn32_fpu.c | 2 +- drivers/gpu/drm/amd/display/dc/hwss/dcn10/dcn10_hwseq.c | 2 +- .../drm/amd/display/dc/link/protocols/link_edp_panel_control.c | 2 +- drivers/gpu/drm/amd/display/dc/spl/dc_spl.c | 8 ++++---- drivers/gpu/drm/amd/display/modules/freesync/freesync.c | 2 +- 13 files changed, 24 insertions(+), 24 deletions(-) diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_psr.c b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_psr.c index 633ab1c16dc6..f40240aafe98 100644 --- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_psr.c +++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_psr.c @@ -158,7 +158,7 @@ void amdgpu_dm_psr_enable(struct dc_stream_state *stream) DRM_DEBUG_DRIVER("Enabling psr...\n"); vsync_rate_hz = div64_u64(div64_u64(( - stream->timing.pix_clk_100hz * 100), + stream->timing.pix_clk_100hz * (uint64_t)100), stream->timing.v_total), stream->timing.h_total); diff --git a/drivers/gpu/drm/amd/display/dc/basics/dce_calcs.c b/drivers/gpu/drm/amd/display/dc/basics/dce_calcs.c index b30c2cdc1a61..e47e9db062f4 100644 --- a/drivers/gpu/drm/amd/display/dc/basics/dce_calcs.c +++ b/drivers/gpu/drm/amd/display/dc/basics/dce_calcs.c @@ -1853,7 +1853,7 @@ static void calculate_bandwidth( /*compute total time to request one chunk from each active display pipe*/ for (i = 0; i <= maximum_number_of_surfaces - 1; i++) { if (data->enable[i]) { - data->chunk_request_time = bw_add(data->chunk_request_time, (bw_div((bw_div(bw_int_to_fixed(pixels_per_chunk * data->bytes_per_pixel[i]), data->useful_bytes_per_request[i])), bw_min2(sclk[data->sclk_level], bw_div(data->dispclk, bw_int_to_fixed(2)))))); + data->chunk_request_time = bw_add(data->chunk_request_time, (bw_div((bw_div(bw_int_to_fixed(pixels_per_chunk * (int64_t)data->bytes_per_pixel[i]), data->useful_bytes_per_request[i])), bw_min2(sclk[data->sclk_level], bw_div(data->dispclk, bw_int_to_fixed(2)))))); } } /*compute total time to request cursor data*/ diff --git a/drivers/gpu/drm/amd/display/dc/clk_mgr/dcn32/dcn32_clk_mgr.c b/drivers/gpu/drm/amd/display/dc/clk_mgr/dcn32/dcn32_clk_mgr.c index 3b10b24f5e23..084994c650c4 100644 --- a/drivers/gpu/drm/amd/display/dc/clk_mgr/dcn32/dcn32_clk_mgr.c +++ b/drivers/gpu/drm/amd/display/dc/clk_mgr/dcn32/dcn32_clk_mgr.c @@ -576,7 +576,7 @@ static void dcn32_auto_dpm_test_log( p_state_list[i] = curr_pipe_ctx->p_state_type; refresh_rate = (curr_pipe_ctx->stream->timing.pix_clk_100hz * (uint64_t)100 + - curr_pipe_ctx->stream->timing.v_total * curr_pipe_ctx->stream->timing.h_total - (uint64_t)1); + curr_pipe_ctx->stream->timing.v_total * (uint64_t)curr_pipe_ctx->stream->timing.h_total - (uint64_t)1); refresh_rate = div_u64(refresh_rate, curr_pipe_ctx->stream->timing.v_total); refresh_rate = div_u64(refresh_rate, curr_pipe_ctx->stream->timing.h_total); disp_src_refresh_list[i] = refresh_rate; 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 eb053e1791c0..bcb5267b5a6b 100644 --- a/drivers/gpu/drm/amd/display/dc/core/dc_resource.c +++ b/drivers/gpu/drm/amd/display/dc/core/dc_resource.c @@ -888,21 +888,21 @@ static struct rect calculate_plane_rec_in_timing_active( struct rect rec_out = {0}; struct fixed31_32 temp; - temp = dc_fixpt_from_fraction(rec_in->x * stream->dst.width, + temp = dc_fixpt_from_fraction(rec_in->x * (long long)stream->dst.width, stream->src.width); rec_out.x = stream->dst.x + dc_fixpt_round(temp); temp = dc_fixpt_from_fraction( - (rec_in->x + rec_in->width) * stream->dst.width, + (rec_in->x + rec_in->width) * (long long)stream->dst.width, stream->src.width); rec_out.width = stream->dst.x + dc_fixpt_round(temp) - rec_out.x; - temp = dc_fixpt_from_fraction(rec_in->y * stream->dst.height, + temp = dc_fixpt_from_fraction(rec_in->y * (long long)stream->dst.height, stream->src.height); rec_out.y = stream->dst.y + dc_fixpt_round(temp); temp = dc_fixpt_from_fraction( - (rec_in->y + rec_in->height) * stream->dst.height, + (rec_in->y + rec_in->height) * (long long)stream->dst.height, stream->src.height); rec_out.height = stream->dst.y + dc_fixpt_round(temp) - rec_out.y; 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 de0633f98158..be2638c763d7 100644 --- a/drivers/gpu/drm/amd/display/dc/core/dc_stream.c +++ b/drivers/gpu/drm/amd/display/dc/core/dc_stream.c @@ -975,7 +975,7 @@ static int dc_stream_calculate_flickerless_refresh_rate(struct dc_stream_state * } if (search_for_max_increase) - return (int)div64_s64((long long)stream->timing.pix_clk_100hz*100, stream->timing.v_total*stream->timing.h_total); + return (int)div64_s64((long long)stream->timing.pix_clk_100hz*100, stream->timing.v_total*(long long)stream->timing.h_total); else return stream->lumin_data.refresh_rate_hz[0]; } @@ -1024,7 +1024,7 @@ static unsigned int dc_stream_get_max_flickerless_instant_vtotal_delta(struct dc if (stream->timing.v_total * stream->timing.h_total == 0) return 0; - int current_refresh_hz = (int)div64_s64((long long)stream->timing.pix_clk_100hz*100, stream->timing.v_total*stream->timing.h_total); + int current_refresh_hz = (int)div64_s64((long long)stream->timing.pix_clk_100hz*100, stream->timing.v_total*(long long)stream->timing.h_total); int safe_refresh_hz = dc_stream_calculate_flickerless_refresh_rate(stream, dc_stream_get_brightness_millinits_from_refresh(stream, current_refresh_hz), @@ -1032,7 +1032,7 @@ static unsigned int dc_stream_get_max_flickerless_instant_vtotal_delta(struct dc is_gaming, increase); - int safe_refresh_v_total = (int)div64_s64((long long)stream->timing.pix_clk_100hz*100, safe_refresh_hz*stream->timing.h_total); + int safe_refresh_v_total = (int)div64_s64((long long)stream->timing.pix_clk_100hz*100, safe_refresh_hz*(long long)stream->timing.h_total); if (increase) return (((int) stream->timing.v_total - safe_refresh_v_total) >= 0) ? (stream->timing.v_total - safe_refresh_v_total) : 0; diff --git a/drivers/gpu/drm/amd/display/dc/dce/dce_audio.c b/drivers/gpu/drm/amd/display/dc/dce/dce_audio.c index 12f3c35b3a34..c3deb4ab3992 100644 --- a/drivers/gpu/drm/amd/display/dc/dce/dce_audio.c +++ b/drivers/gpu/drm/amd/display/dc/dce/dce_audio.c @@ -353,7 +353,7 @@ static uint32_t calculate_required_audio_bw_in_symbols( /* DP spec recommends between 1.05 to 1.1 safety margin to prevent sample under-run */ struct fixed31_32 audio_sdp_margin = dc_fixpt_from_fraction(110, 100); struct fixed31_32 horizontal_line_freq_khz = dc_fixpt_from_fraction( - crtc_info->requested_pixel_clock_100Hz, crtc_info->h_total * 10); + crtc_info->requested_pixel_clock_100Hz, (long long)crtc_info->h_total * 10); struct fixed31_32 samples_per_line; struct fixed31_32 layouts_per_line; struct fixed31_32 symbols_per_sdp_max_layout; diff --git a/drivers/gpu/drm/amd/display/dc/dce/dce_clock_source.c b/drivers/gpu/drm/amd/display/dc/dce/dce_clock_source.c index 042a4187fff4..b700608e4240 100644 --- a/drivers/gpu/drm/amd/display/dc/dce/dce_clock_source.c +++ b/drivers/gpu/drm/amd/display/dc/dce/dce_clock_source.c @@ -217,7 +217,7 @@ static bool calc_fb_divider_checking_tolerance( actual_calc_clk_100hz = (uint64_t)feedback_divider * calc_pll_cs->fract_fb_divider_factor + fract_feedback_divider; - actual_calc_clk_100hz *= calc_pll_cs->ref_freq_khz * 10; + actual_calc_clk_100hz *= (uint64_t)calc_pll_cs->ref_freq_khz * 10; actual_calc_clk_100hz = div_u64(actual_calc_clk_100hz, ref_divider * post_divider * @@ -680,7 +680,7 @@ static bool calculate_ss( * so have to divided by 100 * 100*/ ss_amount = dc_fixpt_mul( fb_div, dc_fixpt_from_fraction(ss_data->percentage, - 100 * ss_data->percentage_divider)); + 100 * (long long)ss_data->percentage_divider)); ds_data->feedback_amount = dc_fixpt_floor(ss_amount); ss_nslip_amount = dc_fixpt_sub(ss_amount, @@ -695,8 +695,8 @@ static bool calculate_ss( /* compute SS_STEP_SIZE_DSFRAC */ modulation_time = dc_fixpt_from_fraction( - pll_settings->reference_freq * 1000, - pll_settings->reference_divider * ss_data->modulation_freq_hz); + pll_settings->reference_freq * (uint64_t)1000, + pll_settings->reference_divider * (uint64_t)ss_data->modulation_freq_hz); if (ss_data->flags.CENTER_SPREAD) modulation_time = dc_fixpt_div_int(modulation_time, 4); diff --git a/drivers/gpu/drm/amd/display/dc/dce/dce_panel_cntl.c b/drivers/gpu/drm/amd/display/dc/dce/dce_panel_cntl.c index 5bca67407c5b..de31fb1b6819 100644 --- a/drivers/gpu/drm/amd/display/dc/dce/dce_panel_cntl.c +++ b/drivers/gpu/drm/amd/display/dc/dce/dce_panel_cntl.c @@ -218,7 +218,7 @@ static void dce_driver_set_backlight(struct panel_cntl *panel_cntl, * contain integer component, lower 16 bits contain fractional component * of active duty cycle e.g. 0x21BDC0 = 0xEFF0 * 0x24 */ - active_duty_cycle = backlight_pwm_u16_16 * masked_pwm_period; + active_duty_cycle = backlight_pwm_u16_16 * (uint64_t)masked_pwm_period; /* 1.3 Calculate 16 bit active duty cycle from integer and fractional * components shift by bitCount then mask 16 bits and add rounding bit diff --git a/drivers/gpu/drm/amd/display/dc/dml/dcn32/dcn32_fpu.c b/drivers/gpu/drm/amd/display/dc/dml/dcn32/dcn32_fpu.c index 7abf8b88ca91..9d399c4ce957 100644 --- a/drivers/gpu/drm/amd/display/dc/dml/dcn32/dcn32_fpu.c +++ b/drivers/gpu/drm/amd/display/dc/dml/dcn32/dcn32_fpu.c @@ -997,7 +997,7 @@ static bool subvp_subvp_admissable(struct dc *dc, if (pipe->plane_state && !pipe->top_pipe && dc_state_get_pipe_subvp_type(context, pipe) == SUBVP_MAIN) { refresh_rate = (pipe->stream->timing.pix_clk_100hz * (uint64_t)100 + - pipe->stream->timing.v_total * pipe->stream->timing.h_total - (uint64_t)1); + pipe->stream->timing.v_total * (uint64_t)pipe->stream->timing.h_total - (uint64_t)1); refresh_rate = div_u64(refresh_rate, pipe->stream->timing.v_total); refresh_rate = div_u64(refresh_rate, pipe->stream->timing.h_total); diff --git a/drivers/gpu/drm/amd/display/dc/hwss/dcn10/dcn10_hwseq.c b/drivers/gpu/drm/amd/display/dc/hwss/dcn10/dcn10_hwseq.c index 4ef329a4d764..e06fc370267b 100644 --- a/drivers/gpu/drm/amd/display/dc/hwss/dcn10/dcn10_hwseq.c +++ b/drivers/gpu/drm/amd/display/dc/hwss/dcn10/dcn10_hwseq.c @@ -2208,7 +2208,7 @@ static int dcn10_align_pixel_clocks(struct dc *dc, int group_size, grouped_pipes[i]->stream->signal)) { embedded = i; master = i; - phase[i] = embedded_pix_clk_100hz*100; + phase[i] = embedded_pix_clk_100hz*(uint64_t)100; modulo[i] = dp_ref_clk_100hz*100; } else { diff --git a/drivers/gpu/drm/amd/display/dc/link/protocols/link_edp_panel_control.c b/drivers/gpu/drm/amd/display/dc/link/protocols/link_edp_panel_control.c index 455b85adec28..bf820d2b4dc4 100644 --- a/drivers/gpu/drm/amd/display/dc/link/protocols/link_edp_panel_control.c +++ b/drivers/gpu/drm/amd/display/dc/link/protocols/link_edp_panel_control.c @@ -763,7 +763,7 @@ bool edp_setup_psr(struct dc_link *link, psr_context->crtcTimingVerticalTotal = stream->timing.v_total; psr_context->vsync_rate_hz = div64_u64(div64_u64((stream-> - timing.pix_clk_100hz * 100), + timing.pix_clk_100hz * (u64)100), stream->timing.v_total), stream->timing.h_total); diff --git a/drivers/gpu/drm/amd/display/dc/spl/dc_spl.c b/drivers/gpu/drm/amd/display/dc/spl/dc_spl.c index ac58991eebbc..e3e20cd86af6 100644 --- a/drivers/gpu/drm/amd/display/dc/spl/dc_spl.c +++ b/drivers/gpu/drm/amd/display/dc/spl/dc_spl.c @@ -110,21 +110,21 @@ static struct spl_rect calculate_plane_rec_in_timing_active( struct fixed31_32 temp; - temp = dc_fixpt_from_fraction(rec_in->x * stream_dst->width, + temp = dc_fixpt_from_fraction(rec_in->x * (long long)stream_dst->width, stream_src->width); rec_out.x = stream_dst->x + dc_fixpt_round(temp); temp = dc_fixpt_from_fraction( - (rec_in->x + rec_in->width) * stream_dst->width, + (rec_in->x + rec_in->width) * (long long)stream_dst->width, stream_src->width); rec_out.width = stream_dst->x + dc_fixpt_round(temp) - rec_out.x; - temp = dc_fixpt_from_fraction(rec_in->y * stream_dst->height, + temp = dc_fixpt_from_fraction(rec_in->y * (long long)stream_dst->height, stream_src->height); rec_out.y = stream_dst->y + dc_fixpt_round(temp); temp = dc_fixpt_from_fraction( - (rec_in->y + rec_in->height) * stream_dst->height, + (rec_in->y + rec_in->height) * (long long)stream_dst->height, stream_src->height); rec_out.height = stream_dst->y + dc_fixpt_round(temp) - rec_out.y; diff --git a/drivers/gpu/drm/amd/display/modules/freesync/freesync.c b/drivers/gpu/drm/amd/display/modules/freesync/freesync.c index d09627c15b9c..a40e6590215a 100644 --- a/drivers/gpu/drm/amd/display/modules/freesync/freesync.c +++ b/drivers/gpu/drm/amd/display/modules/freesync/freesync.c @@ -1002,7 +1002,7 @@ void mod_freesync_build_vrr_params(struct mod_freesync *mod_freesync, if (stream->ctx->dc->caps.max_v_total != 0 && stream->timing.h_total != 0) { min_hardware_refresh_in_uhz = div64_u64((stream->timing.pix_clk_100hz * 100000000ULL), - (stream->timing.h_total * stream->ctx->dc->caps.max_v_total)); + (stream->timing.h_total * (long long)stream->ctx->dc->caps.max_v_total)); } /* Limit minimum refresh rate to what can be supported by hardware */ min_refresh_in_uhz = min_hardware_refresh_in_uhz > in_config->min_refresh_in_uhz ? -- cgit From 3269d6fb7580e91313f40dffcff70c01cd3f0717 Mon Sep 17 00:00:00 2001 From: Sherry Wang Date: Thu, 6 Jun 2024 16:51:43 +0800 Subject: drm/amd/display: Skip unnecessary abm disable [Why] We try to disable abm immediately when it's being gradually disabled, which causes backlight ramping being paused in the middle [How] Don't disable abm immediately if abm has been or is being disabled through set_abm_level path Reviewed-by: Anthony Koo Signed-off-by: Jerry Zuo Signed-off-by: Sherry Wang Tested-by: Daniel Wheeler Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/dc/hwss/dcn21/dcn21_hwseq.c | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/drivers/gpu/drm/amd/display/dc/hwss/dcn21/dcn21_hwseq.c b/drivers/gpu/drm/amd/display/dc/hwss/dcn21/dcn21_hwseq.c index 3de65a9f0e6f..1ea95f8d4cbc 100644 --- a/drivers/gpu/drm/amd/display/dc/hwss/dcn21/dcn21_hwseq.c +++ b/drivers/gpu/drm/amd/display/dc/hwss/dcn21/dcn21_hwseq.c @@ -183,6 +183,12 @@ void dcn21_set_abm_immediate_disable(struct pipe_ctx *pipe_ctx) struct panel_cntl *panel_cntl = pipe_ctx->stream->link->panel_cntl; struct dmcu *dmcu = pipe_ctx->stream->ctx->dc->res_pool->dmcu; + // make a short term w/a for an issue that backlight ramping unexpectedly paused in the middle, + // will decouple backlight from ABM and redefine DMUB interface, then this w/a could be removed + if (pipe_ctx->stream->abm_level == 0 || pipe_ctx->stream->abm_level == ABM_LEVEL_IMMEDIATE_DISABLE) { + return; + } + if (dmcu) { dce110_set_abm_immediate_disable(pipe_ctx); return; -- cgit From cbe9d7c1d25ef6da67c9bf19eb02760632857f13 Mon Sep 17 00:00:00 2001 From: Nevenko Stupar Date: Wed, 19 Jun 2024 16:08:41 -0400 Subject: drm/amd/display: Adjust cursor visibility between MPC slices [Why & How] When MPC enabled, need to adjust x and hot spot x position on one pipe when the cursor is between MPC slices i.e. when the cursor is moving from one MPC slice to next slice, while whole cursor size is not contained within one pipe, to make part of the cursor to be visible on the other pipe. Reviewed-by: Sridevi Arvindekar Signed-off-by: Jerry Zuo Signed-off-by: Nevenko Stupar Tested-by: Daniel Wheeler Signed-off-by: Alex Deucher --- .../drm/amd/display/dc/hwss/dcn401/dcn401_hwseq.c | 47 +++++++++++++++++----- .../drm/amd/display/dc/hwss/dcn401/dcn401_hwseq.h | 1 + 2 files changed, 39 insertions(+), 9 deletions(-) diff --git a/drivers/gpu/drm/amd/display/dc/hwss/dcn401/dcn401_hwseq.c b/drivers/gpu/drm/amd/display/dc/hwss/dcn401/dcn401_hwseq.c index 11570ef06086..2c50c0f745a0 100644 --- a/drivers/gpu/drm/amd/display/dc/hwss/dcn401/dcn401_hwseq.c +++ b/drivers/gpu/drm/amd/display/dc/hwss/dcn401/dcn401_hwseq.c @@ -1088,6 +1088,17 @@ static bool dcn401_can_pipe_disable_cursor(struct pipe_ctx *pipe_ctx) return false; } +void adjust_hotspot_between_slices_for_2x_magnify(uint32_t cursor_width, struct dc_cursor_position *pos_cpy) +{ + if (cursor_width <= 128) { + pos_cpy->x_hotspot /= 2; + pos_cpy->x_hotspot += 1; + } else { + pos_cpy->x_hotspot /= 2; + pos_cpy->x_hotspot += 2; + } +} + void dcn401_set_cursor_position(struct pipe_ctx *pipe_ctx) { struct dc_cursor_position pos_cpy = pipe_ctx->stream->cursor_position; @@ -1109,12 +1120,21 @@ void dcn401_set_cursor_position(struct pipe_ctx *pipe_ctx) int prev_odm_width = 0; int prev_odm_offset = 0; struct pipe_ctx *prev_odm_pipe = NULL; + bool mpc_combine_on = false; + int bottom_pipe_x_pos = 0; int x_pos = pos_cpy.x; int y_pos = pos_cpy.y; int recout_x_pos = 0; int recout_y_pos = 0; + if ((pipe_ctx->top_pipe != NULL) || (pipe_ctx->bottom_pipe != NULL)) { + if ((pipe_ctx->plane_state->src_rect.width != pipe_ctx->plane_res.scl_data.viewport.width) || + (pipe_ctx->plane_state->src_rect.height != pipe_ctx->plane_res.scl_data.viewport.height)) { + mpc_combine_on = true; + } + } + /* DCN4 moved cursor composition after Scaler, so in HW it is in * recout space and for HW Cursor position programming need to * translate to recout space. @@ -1177,15 +1197,8 @@ void dcn401_set_cursor_position(struct pipe_ctx *pipe_ctx) if (x_pos < 0) { pos_cpy.x_hotspot -= x_pos; - if ((odm_combine_on) && (hubp->curs_attr.attribute_flags.bits.ENABLE_MAGNIFICATION)) { - if (hubp->curs_attr.width <= 128) { - pos_cpy.x_hotspot /= 2; - pos_cpy.x_hotspot += 1; - } else { - pos_cpy.x_hotspot /= 2; - pos_cpy.x_hotspot += 2; - } - } + if (hubp->curs_attr.attribute_flags.bits.ENABLE_MAGNIFICATION) + adjust_hotspot_between_slices_for_2x_magnify(hubp->curs_attr.width, &pos_cpy); x_pos = 0; } @@ -1194,6 +1207,22 @@ void dcn401_set_cursor_position(struct pipe_ctx *pipe_ctx) y_pos = 0; } + /* If the position on bottom MPC pipe is negative then we need to add to the hotspot and + * adjust x_pos on bottom pipe to make cursor visible when crossing between MPC slices. + */ + if (mpc_combine_on && + pipe_ctx->top_pipe && + (pipe_ctx == pipe_ctx->top_pipe->bottom_pipe)) { + + bottom_pipe_x_pos = x_pos - pipe_ctx->plane_res.scl_data.recout.x; + if (bottom_pipe_x_pos < 0) { + x_pos = pipe_ctx->plane_res.scl_data.recout.x; + pos_cpy.x_hotspot -= bottom_pipe_x_pos; + if (hubp->curs_attr.attribute_flags.bits.ENABLE_MAGNIFICATION) + adjust_hotspot_between_slices_for_2x_magnify(hubp->curs_attr.width, &pos_cpy); + } + } + pos_cpy.x = (uint32_t)x_pos; pos_cpy.y = (uint32_t)y_pos; diff --git a/drivers/gpu/drm/amd/display/dc/hwss/dcn401/dcn401_hwseq.h b/drivers/gpu/drm/amd/display/dc/hwss/dcn401/dcn401_hwseq.h index c1d4287d5a0d..8e9c1c17aa66 100644 --- a/drivers/gpu/drm/amd/display/dc/hwss/dcn401/dcn401_hwseq.h +++ b/drivers/gpu/drm/amd/display/dc/hwss/dcn401/dcn401_hwseq.h @@ -80,4 +80,5 @@ void dcn401_unblank_stream(struct pipe_ctx *pipe_ctx, struct dc_link_settings *l void dcn401_hardware_release(struct dc *dc); void dcn401_update_odm(struct dc *dc, struct dc_state *context, struct pipe_ctx *otg_master); +void adjust_hotspot_between_slices_for_2x_magnify(uint32_t cursor_width, struct dc_cursor_position *pos_cpy); #endif /* __DC_HWSS_DCN401_H__ */ -- cgit From 116a678f3a9abc24f5c9d2525b7393d18d9eb58e Mon Sep 17 00:00:00 2001 From: Alex Hung Date: Tue, 18 Jun 2024 16:21:20 -0600 Subject: drm/amd/display: Check denominator pbn_div before used [WHAT & HOW] A denominator cannot be 0, and is checked before used. This fixes 1 DIVIDE_BY_ZERO issue reported by Coverity. Reviewed-by: Harry Wentland Signed-off-by: Jerry Zuo Signed-off-by: Alex Hung Tested-by: Daniel Wheeler Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) 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 0daf2b787d2f..2c96863d320e 100644 --- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c +++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c @@ -7561,7 +7561,7 @@ static int dm_update_mst_vcpi_slots_for_dsc(struct drm_atomic_state *state, } } - if (j == dc_state->stream_count) + if (j == dc_state->stream_count || pbn_div == 0) continue; slot_num = DIV_ROUND_UP(pbn, pbn_div); -- cgit From ea79068d4073bf303f8203f2625af7d9185a1bc6 Mon Sep 17 00:00:00 2001 From: Alex Hung Date: Tue, 18 Jun 2024 16:19:48 -0600 Subject: drm/amd/display: Check denominator crb_pipes before used [WHAT & HOW] A denominator cannot be 0, and is checked before used. This fixes 2 DIVIDE_BY_ZERO issues reported by Coverity. Reviewed-by: Harry Wentland Signed-off-by: Jerry Zuo Signed-off-by: Alex Hung Tested-by: Daniel Wheeler Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/dc/resource/dcn315/dcn315_resource.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/gpu/drm/amd/display/dc/resource/dcn315/dcn315_resource.c b/drivers/gpu/drm/amd/display/dc/resource/dcn315/dcn315_resource.c index ad40a657e173..3f4b9dba4112 100644 --- a/drivers/gpu/drm/amd/display/dc/resource/dcn315/dcn315_resource.c +++ b/drivers/gpu/drm/amd/display/dc/resource/dcn315/dcn315_resource.c @@ -1760,7 +1760,7 @@ static int dcn315_populate_dml_pipes_from_context( bool split_required = pipe->stream->timing.pix_clk_100hz >= dcn_get_max_non_odm_pix_rate_100hz(&dc->dml.soc) || (pipe->plane_state && pipe->plane_state->src_rect.width > 5120); - if (remaining_det_segs > MIN_RESERVED_DET_SEGS) + if (remaining_det_segs > MIN_RESERVED_DET_SEGS && crb_pipes != 0) pipes[pipe_cnt].pipe.src.det_size_override += (remaining_det_segs - MIN_RESERVED_DET_SEGS) / crb_pipes + (crb_idx < (remaining_det_segs - MIN_RESERVED_DET_SEGS) % crb_pipes ? 1 : 0); if (pipes[pipe_cnt].pipe.src.det_size_override > 2 * DCN3_15_MAX_DET_SEGS) { -- cgit From aa08d1143890ead78d28a5286fd53b45907743fc Mon Sep 17 00:00:00 2001 From: Dillon Varone Date: Wed, 19 Jun 2024 10:05:12 -0400 Subject: drm/amd/display: Cleanup dce_get_dp_ref_freq_khz [WHY&HOW] Cleanup unnecessary code pathes as compile guards were added and removed overtime. Reviewed-by: Alvin Lee Signed-off-by: Jerry Zuo Signed-off-by: Dillon Varone Tested-by: Daniel Wheeler Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/dc/clk_mgr/dce100/dce_clk_mgr.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/gpu/drm/amd/display/dc/clk_mgr/dce100/dce_clk_mgr.c b/drivers/gpu/drm/amd/display/dc/clk_mgr/dce100/dce_clk_mgr.c index 2a5dd3a296b2..26feefbb8990 100644 --- a/drivers/gpu/drm/amd/display/dc/clk_mgr/dce100/dce_clk_mgr.c +++ b/drivers/gpu/drm/amd/display/dc/clk_mgr/dce100/dce_clk_mgr.c @@ -131,7 +131,7 @@ int dce_get_dp_ref_freq_khz(struct clk_mgr *clk_mgr_base) struct clk_mgr_internal *clk_mgr = TO_CLK_MGR_INTERNAL(clk_mgr_base); int dprefclk_wdivider; int dprefclk_src_sel; - int dp_ref_clk_khz = 600000; + int dp_ref_clk_khz; int target_div; /* ASSERT DP Reference Clock source is from DFS*/ -- cgit From 9023ec5d55f3991aaa76f3c87a6fc4552e776172 Mon Sep 17 00:00:00 2001 From: Tom Chung Date: Wed, 19 Jun 2024 14:03:55 +0800 Subject: drm/amd/display: Add refresh rate range check [Why] We only enable the VRR while monitor usable refresh rate range is greater than 10 Hz. But we did not check the range in DRM_EDID_FEATURE_CONTINUOUS_FREQ case. [How] Add a refresh rate range check before set the freesync_capable flag in DRM_EDID_FEATURE_CONTINUOUS_FREQ case. Reviewed-by: Mario Limonciello Reviewed-by: Rodrigo Siqueira Signed-off-by: Jerry Zuo Signed-off-by: Tom Chung Tested-by: Daniel Wheeler Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) 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 2c96863d320e..e64592e49568 100644 --- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c +++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c @@ -11991,9 +11991,11 @@ void amdgpu_dm_update_freesync_caps(struct drm_connector *connector, if (is_dp_capable_without_timing_msa(adev->dm.dc, amdgpu_dm_connector)) { if (edid->features & DRM_EDID_FEATURE_CONTINUOUS_FREQ) { - freesync_capable = true; amdgpu_dm_connector->min_vfreq = connector->display_info.monitor_range.min_vfreq; amdgpu_dm_connector->max_vfreq = connector->display_info.monitor_range.max_vfreq; + if (amdgpu_dm_connector->max_vfreq - + amdgpu_dm_connector->min_vfreq > 10) + freesync_capable = true; } else { edid_check_required = edid->version > 1 || (edid->version == 1 && -- cgit From d12b17e43aacc6a4a462f0918637b4097b72cf56 Mon Sep 17 00:00:00 2001 From: Ryan Seto Date: Thu, 20 Jun 2024 13:40:43 -0400 Subject: drm/amd/display: Add available bandwidth calculation for audio [Why] Audio for 8K 240Hz monitor was not available when it should be [How] Added calculation based on stream state Co-developed-by: Ryan Seto Reviewed-by: George Shen Signed-off-by: Jerry Zuo Signed-off-by: Ryan Seto Tested-by: Daniel Wheeler Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/dc/dce/dce_audio.c | 3 +- .../drm/amd/display/dc/hwss/dce110/dce110_hwseq.c | 62 ++++++++++++++++++++-- 2 files changed, 59 insertions(+), 6 deletions(-) diff --git a/drivers/gpu/drm/amd/display/dc/dce/dce_audio.c b/drivers/gpu/drm/amd/display/dc/dce/dce_audio.c index c3deb4ab3992..cf5f84fb9c69 100644 --- a/drivers/gpu/drm/amd/display/dc/dce/dce_audio.c +++ b/drivers/gpu/drm/amd/display/dc/dce/dce_audio.c @@ -455,7 +455,8 @@ static uint32_t calculate_available_hblank_bw_in_symbols( available_hblank_bw -= crtc_info->dsc_num_slices * 4; /* EOC overhead */ if (available_hblank_bw < dp_link_info->hblank_min_symbol_width) - available_hblank_bw = dp_link_info->hblank_min_symbol_width; + /* Each symbol takes 4 frames */ + available_hblank_bw = 4 * dp_link_info->hblank_min_symbol_width; if (available_hblank_bw < 12) available_hblank_bw = 0; diff --git a/drivers/gpu/drm/amd/display/dc/hwss/dce110/dce110_hwseq.c b/drivers/gpu/drm/amd/display/dc/hwss/dce110/dce110_hwseq.c index 1b410aff6c56..1f2eb2f727dc 100644 --- a/drivers/gpu/drm/amd/display/dc/hwss/dce110/dce110_hwseq.c +++ b/drivers/gpu/drm/amd/display/dc/hwss/dce110/dce110_hwseq.c @@ -1305,13 +1305,65 @@ static void populate_audio_dp_link_info( dp_link_info->link_bandwidth_kbps = dc_fixpt_floor(link_bw_kbps); - /* HW minimum for 128b/132b HBlank is 4 frame symbols. - * TODO: Plumb the actual programmed HBlank min symbol width to here. + /* Calculates hblank_min_symbol_width for 128b/132b + * Corresponding HBLANK_MIN_SYMBOL_WIDTH register is calculated as: + * floor(h_blank * bits_per_pixel / 128) */ - if (dp_link_info->encoding == DP_128b_132b_ENCODING) - dp_link_info->hblank_min_symbol_width = 4; - else + if (dp_link_info->encoding == DP_128b_132b_ENCODING) { + struct dc_crtc_timing *crtc_timing = &pipe_ctx->stream->timing; + + uint32_t h_active = crtc_timing->h_addressable + crtc_timing->h_border_left + + crtc_timing->h_border_right; + uint32_t h_blank = crtc_timing->h_total - h_active; + + uint32_t bpp; + + if (crtc_timing->flags.DSC) { + bpp = crtc_timing->dsc_cfg.bits_per_pixel; + } else { + /* When the timing is using DSC, dsc_cfg.bits_per_pixel is in 16th bits. + * The bpp in this path is scaled to 16th bits so the final calculation + * is correct for both cases. + */ + bpp = 16; + switch (crtc_timing->display_color_depth) { + case COLOR_DEPTH_666: + bpp *= 18; + break; + case COLOR_DEPTH_888: + bpp *= 24; + break; + case COLOR_DEPTH_101010: + bpp *= 30; + break; + case COLOR_DEPTH_121212: + bpp *= 36; + break; + default: + bpp = 0; + break; + } + + switch (crtc_timing->pixel_encoding) { + case PIXEL_ENCODING_YCBCR422: + bpp = bpp * 2 / 3; + break; + case PIXEL_ENCODING_YCBCR420: + bpp /= 2; + break; + default: + break; + } + } + + /* Min symbol width = floor(h_blank * (bpp/16) / 128) */ + dp_link_info->hblank_min_symbol_width = dc_fixpt_floor( + dc_fixpt_div(dc_fixpt_from_int(h_blank * bpp), + dc_fixpt_from_int(128 / 16))); + + } else { dp_link_info->hblank_min_symbol_width = 0; + } } static void build_audio_output( -- cgit From fe4b8c98dd1fcfab6e6c18bbc0f0f31a64bba7a5 Mon Sep 17 00:00:00 2001 From: Paul Hsieh Date: Thu, 20 Jun 2024 17:09:25 +0800 Subject: drm/amd/display: un-block 8k with single dimm [Why] Driver doesn't validate multi-display with scaling when OS calls DDI. This behavior causes the validated result to be a mismatch between some automated test cases. To address this issue, some workaround was added that caused issues in 8k. [How] Since the origin issue had been root caused, revert the previous workaround and unblock 8k with a single dimm. Reviewed-by: Aric Cyr Signed-off-by: Jerry Zuo Signed-off-by: Paul Hsieh Tested-by: Daniel Wheeler Signed-off-by: Alex Deucher --- .../display/dc/resource/dcn314/dcn314_resource.c | 22 ---------------------- 1 file changed, 22 deletions(-) diff --git a/drivers/gpu/drm/amd/display/dc/resource/dcn314/dcn314_resource.c b/drivers/gpu/drm/amd/display/dc/resource/dcn314/dcn314_resource.c index da73e842c55c..169924d0a839 100644 --- a/drivers/gpu/drm/amd/display/dc/resource/dcn314/dcn314_resource.c +++ b/drivers/gpu/drm/amd/display/dc/resource/dcn314/dcn314_resource.c @@ -1695,25 +1695,6 @@ static void dcn314_get_panel_config_defaults(struct dc_panel_config *panel_confi *panel_config = panel_config_defaults; } -static bool filter_modes_for_single_channel_workaround(struct dc *dc, - struct dc_state *context) -{ - // Filter 2K@240Hz+8K@24fps above combination timing if memory only has single dimm LPDDR - if (dc->clk_mgr->bw_params->vram_type == 34 && - dc->clk_mgr->bw_params->num_channels < 2 && - context->stream_count > 1) { - int total_phy_pix_clk = 0; - - for (int i = 0; i < context->stream_count; i++) - if (context->res_ctx.pipe_ctx[i].stream) - total_phy_pix_clk += context->res_ctx.pipe_ctx[i].stream->phy_pix_clk; - - if (total_phy_pix_clk >= (1148928+826260)) //2K@240Hz+8K@24fps - return true; - } - return false; -} - bool dcn314_validate_bandwidth(struct dc *dc, struct dc_state *context, bool fast_validate) @@ -1732,9 +1713,6 @@ bool dcn314_validate_bandwidth(struct dc *dc, if (!pipes) goto validate_fail; - if (filter_modes_for_single_channel_workaround(dc, context)) - goto validate_fail; - DC_FP_START(); // do not support self refresh only out = dcn30_internal_validate_bw(dc, context, pipes, &pipe_cnt, &vlevel, fast_validate, false); -- cgit From ea04ef19ebdcd22e8a21054a19c2c8fefae011ce Mon Sep 17 00:00:00 2001 From: Nicholas Kazlauskas Date: Mon, 17 Jun 2024 15:45:51 -0400 Subject: drm/amd/display: Add debug option for disabling SLDO optimizations [Why] DM can hook this up to disable SLDO optimizations in firmware during DMCUB initialization for debug purposes. [How] Add the option and pass it through dmub_srv. Reviewed-by: Hansen Dsouza Signed-off-by: Jerry Zuo Signed-off-by: Nicholas Kazlauskas Tested-by: Daniel Wheeler Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/dmub/dmub_srv.h | 1 + drivers/gpu/drm/amd/display/dmub/inc/dmub_cmd.h | 3 ++- drivers/gpu/drm/amd/display/dmub/src/dmub_dcn35.c | 1 + 3 files changed, 4 insertions(+), 1 deletion(-) diff --git a/drivers/gpu/drm/amd/display/dmub/dmub_srv.h b/drivers/gpu/drm/amd/display/dmub/dmub_srv.h index 85dcf6b4fe92..6589bb9aea6b 100644 --- a/drivers/gpu/drm/amd/display/dmub/dmub_srv.h +++ b/drivers/gpu/drm/amd/display/dmub/dmub_srv.h @@ -299,6 +299,7 @@ struct dmub_srv_hw_params { enum dmub_memory_access_type mem_access_type; enum dmub_ips_disable_type disable_ips; bool disallow_phy_access; + bool disable_sldo_opt; }; /** diff --git a/drivers/gpu/drm/amd/display/dmub/inc/dmub_cmd.h b/drivers/gpu/drm/amd/display/dmub/inc/dmub_cmd.h index 605dd9d45167..5ff0a865705f 100644 --- a/drivers/gpu/drm/amd/display/dmub/inc/dmub_cmd.h +++ b/drivers/gpu/drm/amd/display/dmub/inc/dmub_cmd.h @@ -684,7 +684,8 @@ union dmub_fw_boot_options { uint32_t ips_pg_disable: 1; /* 1 to disable ONO domains power gating*/ uint32_t ips_disable: 3; /* options to disable ips support*/ uint32_t ips_sequential_ono: 1; /**< 1 to enable sequential ONO IPS sequence */ - uint32_t reserved : 8; /**< reserved */ + uint32_t disable_sldo_opt: 1; /**< 1 to disable SLDO optimizations */ + uint32_t reserved : 7; /**< reserved */ } bits; /**< boot bits */ uint32_t all; /**< 32-bit access to bits */ }; diff --git a/drivers/gpu/drm/amd/display/dmub/src/dmub_dcn35.c b/drivers/gpu/drm/amd/display/dmub/src/dmub_dcn35.c index 80da117356c0..916ed022e96b 100644 --- a/drivers/gpu/drm/amd/display/dmub/src/dmub_dcn35.c +++ b/drivers/gpu/drm/amd/display/dmub/src/dmub_dcn35.c @@ -424,6 +424,7 @@ void dmub_dcn35_enable_dmub_boot_options(struct dmub_srv *dmub, const struct dmu boot_options.bits.disable_clk_gate = params->disable_clock_gate; boot_options.bits.ips_disable = params->disable_ips; boot_options.bits.ips_sequential_ono = params->ips_sequential_ono; + boot_options.bits.disable_sldo_opt = params->disable_sldo_opt; REG_WRITE(DMCUB_SCRATCH14, boot_options.all); } -- cgit From d6d884b68ad65c832be5ba22ac61dc7173059d9a Mon Sep 17 00:00:00 2001 From: Fangzhi Zuo Date: Thu, 20 Jun 2024 11:27:39 -0400 Subject: drm/amd/display: Fix dmub timeout after fams2 enabled Reset fams stream count upon stream removal, otherwise fams2 state machine in dmub will get corrupted. Reviewed-by: Dillon Varone Signed-off-by: Jerry Zuo Signed-off-by: Fangzhi Zuo Tested-by: Daniel Wheeler Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/dc/dml2/dml21/dml21_wrapper.c | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/drivers/gpu/drm/amd/display/dc/dml2/dml21/dml21_wrapper.c b/drivers/gpu/drm/amd/display/dc/dml2/dml21/dml21_wrapper.c index c310354cd5fc..9edcacdde6b7 100644 --- a/drivers/gpu/drm/amd/display/dc/dml2/dml21/dml21_wrapper.c +++ b/drivers/gpu/drm/amd/display/dc/dml2/dml21/dml21_wrapper.c @@ -197,8 +197,13 @@ static bool dml21_mode_check_and_programming(const struct dc *in_dc, struct dc_s memset(&dml_ctx->v21.dml_to_dc_pipe_mapping, 0, sizeof(struct dml2_dml_to_dc_pipe_mapping)); memset(&dml_ctx->v21.mode_programming.dml2_instance->scratch.build_mode_programming_locals.mode_programming_params, 0, sizeof(struct dml2_core_mode_programming_in_out)); - if (!context || context->stream_count == 0) + if (!context) + return true; + + if (context->stream_count == 0) { + dml21_build_fams2_programming(in_dc, context, dml_ctx); return true; + } /* scrub phantom's from current dc_state */ dml_ctx->config.svp_pstate.callbacks.remove_phantom_streams_and_planes(in_dc, context); -- cgit From b6d508533fa1371d870628a88b74c831c5881cde Mon Sep 17 00:00:00 2001 From: Wenjing Liu Date: Mon, 17 Jun 2024 12:58:35 -0400 Subject: drm/amd/display: fix a crash when clock source is reference for non otg master pipe [why] The function enumerates all pipes without checking pipe type. It is only supposed to call program pixel clock for OTG master pipe only. Reviewed-by: Alvin Lee Signed-off-by: Jerry Zuo Signed-off-by: Wenjing Liu Tested-by: Daniel Wheeler Signed-off-by: Alex Deucher --- .../amd/display/dc/clk_mgr/dcn401/dcn401_clk_mgr.c | 38 ++++++++++++---------- 1 file changed, 20 insertions(+), 18 deletions(-) diff --git a/drivers/gpu/drm/amd/display/dc/clk_mgr/dcn401/dcn401_clk_mgr.c b/drivers/gpu/drm/amd/display/dc/clk_mgr/dcn401/dcn401_clk_mgr.c index 606b2411eee9..45fe17a46890 100644 --- a/drivers/gpu/drm/amd/display/dc/clk_mgr/dcn401/dcn401_clk_mgr.c +++ b/drivers/gpu/drm/amd/display/dc/clk_mgr/dcn401/dcn401_clk_mgr.c @@ -306,27 +306,29 @@ static void dcn401_update_clocks_update_dtb_dto(struct clk_mgr_internal *clk_mgr struct dc_state *context, int ref_dtbclk_khz) { - struct dccg *dccg = clk_mgr->dccg; - uint32_t tg_mask = 0; int i; + struct dccg *dccg = clk_mgr->dccg; + struct pipe_ctx *otg_master; + bool use_hpo_encoder; - for (i = 0; i < clk_mgr->base.ctx->dc->res_pool->pipe_count; i++) { - struct pipe_ctx *pipe_ctx = &context->res_ctx.pipe_ctx[i]; - - /* use mask to program DTO once per tg */ - if (pipe_ctx->stream_res.tg && - !(tg_mask & (1 << pipe_ctx->stream_res.tg->inst))) { - tg_mask |= (1 << pipe_ctx->stream_res.tg->inst); - - if (dccg->ctx->dc->link_srv->dp_is_128b_132b_signal(pipe_ctx)) { - pipe_ctx->clock_source->funcs->program_pix_clk( - pipe_ctx->clock_source, - &pipe_ctx->stream_res.pix_clk_params, - dccg->ctx->dc->link_srv->dp_get_encoding_format(&pipe_ctx->link_config.dp_link_settings), - &pipe_ctx->pll_settings); - } - } + for (i = 0; i < context->stream_count; i++) { + otg_master = resource_get_otg_master_for_stream( + &context->res_ctx, context->streams[i]); + ASSERT(otg_master); + ASSERT(otg_master->clock_source); + ASSERT(otg_master->clock_source->funcs->program_pix_clk); + ASSERT(otg_master->stream_res.pix_clk_params.controller_id >= CONTROLLER_ID_D0); + + use_hpo_encoder = dccg->ctx->dc->link_srv->dp_is_128b_132b_signal(otg_master); + if (!use_hpo_encoder) + continue; + + otg_master->clock_source->funcs->program_pix_clk( + otg_master->clock_source, + &otg_master->stream_res.pix_clk_params, + dccg->ctx->dc->link_srv->dp_get_encoding_format(&otg_master->link_config.dp_link_settings), + &otg_master->pll_settings); } } -- cgit From 057638597a9819e53fb2dcfb292c76c21c6140f5 Mon Sep 17 00:00:00 2001 From: Alvin Lee Date: Thu, 20 Jun 2024 15:11:38 -0400 Subject: drm/amd/display: Account for cursor prefetch BW in DML1 mode support [Description] We need to ensure to take into account cursor prefetch BW in mode support or we may pass ModeQuery but fail an actual flip which will cause a hang. Flip may fail because the cursor_pre_bw is populated during mode programming (and mode programming is never called prior to ModeQuery). Reviewed-by: Chaitanya Dhere Reviewed-by: Nevenko Stupar Signed-off-by: Jerry Zuo Signed-off-by: Alvin Lee Tested-by: Daniel Wheeler Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/dc/dml/dcn32/display_mode_vba_32.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/drivers/gpu/drm/amd/display/dc/dml/dcn32/display_mode_vba_32.c b/drivers/gpu/drm/amd/display/dc/dml/dcn32/display_mode_vba_32.c index 6c84b0fa40f4..0782a34689a0 100644 --- a/drivers/gpu/drm/amd/display/dc/dml/dcn32/display_mode_vba_32.c +++ b/drivers/gpu/drm/amd/display/dc/dml/dcn32/display_mode_vba_32.c @@ -3364,6 +3364,9 @@ void dml32_ModeSupportAndSystemConfigurationFull(struct display_mode_lib *mode_l &mode_lib->vba.UrgentBurstFactorLumaPre[k], &mode_lib->vba.UrgentBurstFactorChromaPre[k], &mode_lib->vba.NotUrgentLatencyHidingPre[k]); + + v->cursor_bw_pre[k] = mode_lib->vba.NumberOfCursors[k] * mode_lib->vba.CursorWidth[k][0] * mode_lib->vba.CursorBPP[k][0] / + 8.0 / (mode_lib->vba.HTotal[k] / mode_lib->vba.PixelClock[k]) * v->VRatioPreY[i][j][k]; } { -- cgit From d19deabe5a4566851f6ecade5ebd2e63c3248cf2 Mon Sep 17 00:00:00 2001 From: Bhuvanachandra Pinninti Date: Thu, 20 Jun 2024 17:54:23 +0530 Subject: drm/amd/display: Move dio files into dio folder [why] Refactor the code of dio to unit test. [how] Moved files to respective folders and changed cMakeLists and makefiles. Acked-by: Rodrigo Siqueira Signed-off-by: Jerry Zuo Signed-off-by: Bhuvanachandra Pinninti Tested-by: Daniel Wheeler Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/dc/dcn10/Makefile | 1 - .../drm/amd/display/dc/dcn10/dcn10_link_encoder.c | 1474 ------------------ .../drm/amd/display/dc/dcn10/dcn10_link_encoder.h | 659 -------- .../amd/display/dc/dcn10/dcn10_stream_encoder.c | 1628 -------------------- .../amd/display/dc/dcn10/dcn10_stream_encoder.h | 749 --------- drivers/gpu/drm/amd/display/dc/dcn20/Makefile | 1 - .../drm/amd/display/dc/dcn20/dcn20_link_encoder.c | 502 ------ .../drm/amd/display/dc/dcn20/dcn20_link_encoder.h | 366 ----- .../amd/display/dc/dcn20/dcn20_stream_encoder.c | 661 -------- .../amd/display/dc/dcn20/dcn20_stream_encoder.h | 119 -- drivers/gpu/drm/amd/display/dc/dcn30/Makefile | 2 - .../amd/display/dc/dcn30/dcn30_dio_link_encoder.c | 257 --- .../amd/display/dc/dcn30/dcn30_dio_link_encoder.h | 86 -- .../display/dc/dcn30/dcn30_dio_stream_encoder.c | 899 ----------- .../display/dc/dcn30/dcn30_dio_stream_encoder.h | 327 ---- drivers/gpu/drm/amd/display/dc/dcn31/Makefile | 2 +- .../amd/display/dc/dcn31/dcn31_dio_link_encoder.c | 681 -------- .../amd/display/dc/dcn31/dcn31_dio_link_encoder.h | 290 ---- drivers/gpu/drm/amd/display/dc/dio/Makefile | 36 + .../amd/display/dc/dio/dcn10/dcn10_link_encoder.c | 1474 ++++++++++++++++++ .../amd/display/dc/dio/dcn10/dcn10_link_encoder.h | 659 ++++++++ .../display/dc/dio/dcn10/dcn10_stream_encoder.c | 1628 ++++++++++++++++++++ .../display/dc/dio/dcn10/dcn10_stream_encoder.h | 749 +++++++++ .../amd/display/dc/dio/dcn20/dcn20_link_encoder.c | 502 ++++++ .../amd/display/dc/dio/dcn20/dcn20_link_encoder.h | 366 +++++ .../display/dc/dio/dcn20/dcn20_stream_encoder.c | 661 ++++++++ .../display/dc/dio/dcn20/dcn20_stream_encoder.h | 119 ++ .../display/dc/dio/dcn30/dcn30_dio_link_encoder.c | 257 +++ .../display/dc/dio/dcn30/dcn30_dio_link_encoder.h | 86 ++ .../dc/dio/dcn30/dcn30_dio_stream_encoder.c | 899 +++++++++++ .../dc/dio/dcn30/dcn30_dio_stream_encoder.h | 327 ++++ .../display/dc/dio/dcn31/dcn31_dio_link_encoder.c | 681 ++++++++ .../display/dc/dio/dcn31/dcn31_dio_link_encoder.h | 290 ++++ 33 files changed, 8735 insertions(+), 8703 deletions(-) delete mode 100644 drivers/gpu/drm/amd/display/dc/dcn10/dcn10_link_encoder.c delete mode 100644 drivers/gpu/drm/amd/display/dc/dcn10/dcn10_link_encoder.h delete mode 100644 drivers/gpu/drm/amd/display/dc/dcn10/dcn10_stream_encoder.c delete mode 100644 drivers/gpu/drm/amd/display/dc/dcn10/dcn10_stream_encoder.h delete mode 100644 drivers/gpu/drm/amd/display/dc/dcn20/dcn20_link_encoder.c delete mode 100644 drivers/gpu/drm/amd/display/dc/dcn20/dcn20_link_encoder.h delete mode 100644 drivers/gpu/drm/amd/display/dc/dcn20/dcn20_stream_encoder.c delete mode 100644 drivers/gpu/drm/amd/display/dc/dcn20/dcn20_stream_encoder.h delete mode 100644 drivers/gpu/drm/amd/display/dc/dcn30/dcn30_dio_link_encoder.c delete mode 100644 drivers/gpu/drm/amd/display/dc/dcn30/dcn30_dio_link_encoder.h delete mode 100644 drivers/gpu/drm/amd/display/dc/dcn30/dcn30_dio_stream_encoder.c delete mode 100644 drivers/gpu/drm/amd/display/dc/dcn30/dcn30_dio_stream_encoder.h delete mode 100644 drivers/gpu/drm/amd/display/dc/dcn31/dcn31_dio_link_encoder.c delete mode 100644 drivers/gpu/drm/amd/display/dc/dcn31/dcn31_dio_link_encoder.h create mode 100644 drivers/gpu/drm/amd/display/dc/dio/dcn10/dcn10_link_encoder.c create mode 100644 drivers/gpu/drm/amd/display/dc/dio/dcn10/dcn10_link_encoder.h create mode 100644 drivers/gpu/drm/amd/display/dc/dio/dcn10/dcn10_stream_encoder.c create mode 100644 drivers/gpu/drm/amd/display/dc/dio/dcn10/dcn10_stream_encoder.h create mode 100644 drivers/gpu/drm/amd/display/dc/dio/dcn20/dcn20_link_encoder.c create mode 100644 drivers/gpu/drm/amd/display/dc/dio/dcn20/dcn20_link_encoder.h create mode 100644 drivers/gpu/drm/amd/display/dc/dio/dcn20/dcn20_stream_encoder.c create mode 100644 drivers/gpu/drm/amd/display/dc/dio/dcn20/dcn20_stream_encoder.h create mode 100644 drivers/gpu/drm/amd/display/dc/dio/dcn30/dcn30_dio_link_encoder.c create mode 100644 drivers/gpu/drm/amd/display/dc/dio/dcn30/dcn30_dio_link_encoder.h create mode 100644 drivers/gpu/drm/amd/display/dc/dio/dcn30/dcn30_dio_stream_encoder.c create mode 100644 drivers/gpu/drm/amd/display/dc/dio/dcn30/dcn30_dio_stream_encoder.h create mode 100644 drivers/gpu/drm/amd/display/dc/dio/dcn31/dcn31_dio_link_encoder.c create mode 100644 drivers/gpu/drm/amd/display/dc/dio/dcn31/dcn31_dio_link_encoder.h diff --git a/drivers/gpu/drm/amd/display/dc/dcn10/Makefile b/drivers/gpu/drm/amd/display/dc/dcn10/Makefile index 68484264831b..9923d0d620d4 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn10/Makefile +++ b/drivers/gpu/drm/amd/display/dc/dcn10/Makefile @@ -27,7 +27,6 @@ DCN10 = dcn10_ipp.o \ dcn10_opp.o \ dcn10_mpc.o \ dcn10_cm_common.o \ - dcn10_stream_encoder.o dcn10_link_encoder.o AMD_DAL_DCN10 = $(addprefix $(AMDDALPATH)/dc/dcn10/,$(DCN10)) diff --git a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_link_encoder.c b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_link_encoder.c deleted file mode 100644 index e0558a78b11c..000000000000 --- a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_link_encoder.c +++ /dev/null @@ -1,1474 +0,0 @@ -/* - * Copyright 2012-15 Advanced Micro Devices, Inc. - * - * Permission is hereby granted, free of charge, to any person obtaining a - * copy of this software and associated documentation files (the "Software"), - * to deal in the Software without restriction, including without limitation - * the rights to use, copy, modify, merge, publish, distribute, sublicense, - * and/or sell copies of the Software, and to permit persons to whom the - * Software is furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL - * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR - * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, - * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR - * OTHER DEALINGS IN THE SOFTWARE. - * - * Authors: AMD - * - */ - -#include "reg_helper.h" - -#include "core_types.h" -#include "link_encoder.h" -#include "dcn10_link_encoder.h" -#include "stream_encoder.h" -#include "dc_bios_types.h" - -#include "gpio_service_interface.h" - -#define CTX \ - enc10->base.ctx -#define DC_LOGGER \ - enc10->base.ctx->logger - -#define REG(reg)\ - (enc10->link_regs->reg) - -#undef FN -#define FN(reg_name, field_name) \ - enc10->link_shift->field_name, enc10->link_mask->field_name - - -/* - * @brief - * Trigger Source Select - * ASIC-dependent, actual values for register programming - */ -#define DCN10_DIG_FE_SOURCE_SELECT_INVALID 0x0 -#define DCN10_DIG_FE_SOURCE_SELECT_DIGA 0x1 -#define DCN10_DIG_FE_SOURCE_SELECT_DIGB 0x2 -#define DCN10_DIG_FE_SOURCE_SELECT_DIGC 0x4 -#define DCN10_DIG_FE_SOURCE_SELECT_DIGD 0x08 -#define DCN10_DIG_FE_SOURCE_SELECT_DIGE 0x10 -#define DCN10_DIG_FE_SOURCE_SELECT_DIGF 0x20 -#define DCN10_DIG_FE_SOURCE_SELECT_DIGG 0x40 - -enum { - DP_MST_UPDATE_MAX_RETRY = 50 -}; - -static const struct link_encoder_funcs dcn10_lnk_enc_funcs = { - .validate_output_with_stream = - dcn10_link_encoder_validate_output_with_stream, - .hw_init = dcn10_link_encoder_hw_init, - .setup = dcn10_link_encoder_setup, - .enable_tmds_output = dcn10_link_encoder_enable_tmds_output, - .enable_dp_output = dcn10_link_encoder_enable_dp_output, - .enable_dp_mst_output = dcn10_link_encoder_enable_dp_mst_output, - .disable_output = dcn10_link_encoder_disable_output, - .dp_set_lane_settings = dcn10_link_encoder_dp_set_lane_settings, - .dp_set_phy_pattern = dcn10_link_encoder_dp_set_phy_pattern, - .update_mst_stream_allocation_table = - dcn10_link_encoder_update_mst_stream_allocation_table, - .psr_program_dp_dphy_fast_training = - dcn10_psr_program_dp_dphy_fast_training, - .psr_program_secondary_packet = dcn10_psr_program_secondary_packet, - .connect_dig_be_to_fe = dcn10_link_encoder_connect_dig_be_to_fe, - .enable_hpd = dcn10_link_encoder_enable_hpd, - .disable_hpd = dcn10_link_encoder_disable_hpd, - .is_dig_enabled = dcn10_is_dig_enabled, - .get_dig_frontend = dcn10_get_dig_frontend, - .get_dig_mode = dcn10_get_dig_mode, - .destroy = dcn10_link_encoder_destroy, - .get_max_link_cap = dcn10_link_encoder_get_max_link_cap, -}; - -static enum bp_result link_transmitter_control( - struct dcn10_link_encoder *enc10, - struct bp_transmitter_control *cntl) -{ - enum bp_result result; - struct dc_bios *bp = enc10->base.ctx->dc_bios; - - result = bp->funcs->transmitter_control(bp, cntl); - - return result; -} - -static void enable_phy_bypass_mode( - struct dcn10_link_encoder *enc10, - bool enable) -{ - /* This register resides in DP back end block; - * transmitter is used for the offset - */ - REG_UPDATE(DP_DPHY_CNTL, DPHY_BYPASS, enable); - -} - -static void disable_prbs_symbols( - struct dcn10_link_encoder *enc10, - bool disable) -{ - /* This register resides in DP back end block; - * transmitter is used for the offset - */ - REG_UPDATE_4(DP_DPHY_CNTL, - DPHY_ATEST_SEL_LANE0, disable, - DPHY_ATEST_SEL_LANE1, disable, - DPHY_ATEST_SEL_LANE2, disable, - DPHY_ATEST_SEL_LANE3, disable); -} - -static void disable_prbs_mode( - struct dcn10_link_encoder *enc10) -{ - REG_UPDATE(DP_DPHY_PRBS_CNTL, DPHY_PRBS_EN, 0); -} - -static void program_pattern_symbols( - struct dcn10_link_encoder *enc10, - uint16_t pattern_symbols[8]) -{ - /* This register resides in DP back end block; - * transmitter is used for the offset - */ - REG_SET_3(DP_DPHY_SYM0, 0, - DPHY_SYM1, pattern_symbols[0], - DPHY_SYM2, pattern_symbols[1], - DPHY_SYM3, pattern_symbols[2]); - - /* This register resides in DP back end block; - * transmitter is used for the offset - */ - REG_SET_3(DP_DPHY_SYM1, 0, - DPHY_SYM4, pattern_symbols[3], - DPHY_SYM5, pattern_symbols[4], - DPHY_SYM6, pattern_symbols[5]); - - /* This register resides in DP back end block; - * transmitter is used for the offset - */ - REG_SET_2(DP_DPHY_SYM2, 0, - DPHY_SYM7, pattern_symbols[6], - DPHY_SYM8, pattern_symbols[7]); -} - -static void set_dp_phy_pattern_d102( - struct dcn10_link_encoder *enc10) -{ - /* Disable PHY Bypass mode to setup the test pattern */ - enable_phy_bypass_mode(enc10, false); - - /* For 10-bit PRBS or debug symbols - * please use the following sequence: - * - * Enable debug symbols on the lanes - */ - disable_prbs_symbols(enc10, true); - - /* Disable PRBS mode */ - disable_prbs_mode(enc10); - - /* Program debug symbols to be output */ - { - uint16_t pattern_symbols[8] = { - 0x2AA, 0x2AA, 0x2AA, 0x2AA, - 0x2AA, 0x2AA, 0x2AA, 0x2AA - }; - - program_pattern_symbols(enc10, pattern_symbols); - } - - /* Enable phy bypass mode to enable the test pattern */ - - enable_phy_bypass_mode(enc10, true); -} - -static void set_link_training_complete( - struct dcn10_link_encoder *enc10, - bool complete) -{ - /* This register resides in DP back end block; - * transmitter is used for the offset - */ - REG_UPDATE(DP_LINK_CNTL, DP_LINK_TRAINING_COMPLETE, complete); - -} - -void dcn10_link_encoder_set_dp_phy_pattern_training_pattern( - struct link_encoder *enc, - uint32_t index) -{ - struct dcn10_link_encoder *enc10 = TO_DCN10_LINK_ENC(enc); - /* Write Training Pattern */ - - REG_WRITE(DP_DPHY_TRAINING_PATTERN_SEL, index); - - /* Set HW Register Training Complete to false */ - - set_link_training_complete(enc10, false); - - /* Disable PHY Bypass mode to output Training Pattern */ - - enable_phy_bypass_mode(enc10, false); - - /* Disable PRBS mode */ - disable_prbs_mode(enc10); -} - -static void setup_panel_mode( - struct dcn10_link_encoder *enc10, - enum dp_panel_mode panel_mode) -{ - uint32_t value; - - if (!REG(DP_DPHY_INTERNAL_CTRL)) - return; - - value = REG_READ(DP_DPHY_INTERNAL_CTRL); - - switch (panel_mode) { - case DP_PANEL_MODE_EDP: - value = 0x1; - break; - case DP_PANEL_MODE_SPECIAL: - value = 0x11; - break; - default: - value = 0x0; - break; - } - - REG_WRITE(DP_DPHY_INTERNAL_CTRL, value); -} - -static void set_dp_phy_pattern_symbol_error( - struct dcn10_link_encoder *enc10) -{ - /* Disable PHY Bypass mode to setup the test pattern */ - enable_phy_bypass_mode(enc10, false); - - /* program correct panel mode*/ - setup_panel_mode(enc10, DP_PANEL_MODE_DEFAULT); - - /* A PRBS23 pattern is used for most DP electrical measurements. */ - - /* Enable PRBS symbols on the lanes */ - disable_prbs_symbols(enc10, false); - - /* For PRBS23 Set bit DPHY_PRBS_SEL=1 and Set bit DPHY_PRBS_EN=1 */ - REG_UPDATE_2(DP_DPHY_PRBS_CNTL, - DPHY_PRBS_SEL, 1, - DPHY_PRBS_EN, 1); - - /* Enable phy bypass mode to enable the test pattern */ - enable_phy_bypass_mode(enc10, true); -} - -static void set_dp_phy_pattern_prbs7( - struct dcn10_link_encoder *enc10) -{ - /* Disable PHY Bypass mode to setup the test pattern */ - enable_phy_bypass_mode(enc10, false); - - /* A PRBS7 pattern is used for most DP electrical measurements. */ - - /* Enable PRBS symbols on the lanes */ - disable_prbs_symbols(enc10, false); - - /* For PRBS7 Set bit DPHY_PRBS_SEL=0 and Set bit DPHY_PRBS_EN=1 */ - REG_UPDATE_2(DP_DPHY_PRBS_CNTL, - DPHY_PRBS_SEL, 0, - DPHY_PRBS_EN, 1); - - /* Enable phy bypass mode to enable the test pattern */ - enable_phy_bypass_mode(enc10, true); -} - -static void set_dp_phy_pattern_80bit_custom( - struct dcn10_link_encoder *enc10, - const uint8_t *pattern) -{ - /* Disable PHY Bypass mode to setup the test pattern */ - enable_phy_bypass_mode(enc10, false); - - /* Enable debug symbols on the lanes */ - - disable_prbs_symbols(enc10, true); - - /* Enable PHY bypass mode to enable the test pattern */ - /* TODO is it really needed ? */ - - enable_phy_bypass_mode(enc10, true); - - /* Program 80 bit custom pattern */ - { - uint16_t pattern_symbols[8]; - - pattern_symbols[0] = - ((pattern[1] & 0x03) << 8) | pattern[0]; - pattern_symbols[1] = - ((pattern[2] & 0x0f) << 6) | ((pattern[1] >> 2) & 0x3f); - pattern_symbols[2] = - ((pattern[3] & 0x3f) << 4) | ((pattern[2] >> 4) & 0x0f); - pattern_symbols[3] = - (pattern[4] << 2) | ((pattern[3] >> 6) & 0x03); - pattern_symbols[4] = - ((pattern[6] & 0x03) << 8) | pattern[5]; - pattern_symbols[5] = - ((pattern[7] & 0x0f) << 6) | ((pattern[6] >> 2) & 0x3f); - pattern_symbols[6] = - ((pattern[8] & 0x3f) << 4) | ((pattern[7] >> 4) & 0x0f); - pattern_symbols[7] = - (pattern[9] << 2) | ((pattern[8] >> 6) & 0x03); - - program_pattern_symbols(enc10, pattern_symbols); - } - - /* Enable phy bypass mode to enable the test pattern */ - - enable_phy_bypass_mode(enc10, true); -} - -static void set_dp_phy_pattern_hbr2_compliance_cp2520_2( - struct dcn10_link_encoder *enc10, - unsigned int cp2520_pattern) -{ - - /* previously there is a register DP_HBR2_EYE_PATTERN - * that is enabled to get the pattern. - * But it does not work with the latest spec change, - * so we are programming the following registers manually. - * - * The following settings have been confirmed - * by Nick Chorney and Sandra Liu - */ - - /* Disable PHY Bypass mode to setup the test pattern */ - - enable_phy_bypass_mode(enc10, false); - - /* Setup DIG encoder in DP SST mode */ - enc10->base.funcs->setup(&enc10->base, SIGNAL_TYPE_DISPLAY_PORT); - - /* ensure normal panel mode. */ - setup_panel_mode(enc10, DP_PANEL_MODE_DEFAULT); - - /* no vbid after BS (SR) - * DP_LINK_FRAMING_CNTL changed history Sandra Liu - * 11000260 / 11000104 / 110000FC - */ - REG_UPDATE_3(DP_LINK_FRAMING_CNTL, - DP_IDLE_BS_INTERVAL, 0xFC, - DP_VBID_DISABLE, 1, - DP_VID_ENHANCED_FRAME_MODE, 1); - - /* swap every BS with SR */ - REG_UPDATE(DP_DPHY_SCRAM_CNTL, DPHY_SCRAMBLER_BS_COUNT, 0); - - /* select cp2520 patterns */ - if (REG(DP_DPHY_HBR2_PATTERN_CONTROL)) - REG_UPDATE(DP_DPHY_HBR2_PATTERN_CONTROL, - DP_DPHY_HBR2_PATTERN_CONTROL, cp2520_pattern); - else - /* pre-DCE11 can only generate CP2520 pattern 2 */ - ASSERT(cp2520_pattern == 2); - - /* set link training complete */ - set_link_training_complete(enc10, true); - - /* disable video stream */ - REG_UPDATE(DP_VID_STREAM_CNTL, DP_VID_STREAM_ENABLE, 0); - - /* Disable PHY Bypass mode to setup the test pattern */ - enable_phy_bypass_mode(enc10, false); -} - -static void set_dp_phy_pattern_passthrough_mode( - struct dcn10_link_encoder *enc10, - enum dp_panel_mode panel_mode) -{ - /* program correct panel mode */ - setup_panel_mode(enc10, panel_mode); - - /* restore LINK_FRAMING_CNTL and DPHY_SCRAMBLER_BS_COUNT - * in case we were doing HBR2 compliance pattern before - */ - REG_UPDATE_3(DP_LINK_FRAMING_CNTL, - DP_IDLE_BS_INTERVAL, 0x2000, - DP_VBID_DISABLE, 0, - DP_VID_ENHANCED_FRAME_MODE, 1); - - REG_UPDATE(DP_DPHY_SCRAM_CNTL, DPHY_SCRAMBLER_BS_COUNT, 0x1FF); - - /* set link training complete */ - set_link_training_complete(enc10, true); - - /* Disable PHY Bypass mode to setup the test pattern */ - enable_phy_bypass_mode(enc10, false); - - /* Disable PRBS mode */ - disable_prbs_mode(enc10); -} - -/* return value is bit-vector */ -static uint8_t get_frontend_source( - enum engine_id engine) -{ - switch (engine) { - case ENGINE_ID_DIGA: - return DCN10_DIG_FE_SOURCE_SELECT_DIGA; - case ENGINE_ID_DIGB: - return DCN10_DIG_FE_SOURCE_SELECT_DIGB; - case ENGINE_ID_DIGC: - return DCN10_DIG_FE_SOURCE_SELECT_DIGC; - case ENGINE_ID_DIGD: - return DCN10_DIG_FE_SOURCE_SELECT_DIGD; - case ENGINE_ID_DIGE: - return DCN10_DIG_FE_SOURCE_SELECT_DIGE; - case ENGINE_ID_DIGF: - return DCN10_DIG_FE_SOURCE_SELECT_DIGF; - case ENGINE_ID_DIGG: - return DCN10_DIG_FE_SOURCE_SELECT_DIGG; - default: - ASSERT_CRITICAL(false); - return DCN10_DIG_FE_SOURCE_SELECT_INVALID; - } -} - -unsigned int dcn10_get_dig_frontend(struct link_encoder *enc) -{ - struct dcn10_link_encoder *enc10 = TO_DCN10_LINK_ENC(enc); - int32_t value; - enum engine_id result; - - REG_GET(DIG_BE_CNTL, DIG_FE_SOURCE_SELECT, &value); - - switch (value) { - case DCN10_DIG_FE_SOURCE_SELECT_DIGA: - result = ENGINE_ID_DIGA; - break; - case DCN10_DIG_FE_SOURCE_SELECT_DIGB: - result = ENGINE_ID_DIGB; - break; - case DCN10_DIG_FE_SOURCE_SELECT_DIGC: - result = ENGINE_ID_DIGC; - break; - case DCN10_DIG_FE_SOURCE_SELECT_DIGD: - result = ENGINE_ID_DIGD; - break; - case DCN10_DIG_FE_SOURCE_SELECT_DIGE: - result = ENGINE_ID_DIGE; - break; - case DCN10_DIG_FE_SOURCE_SELECT_DIGF: - result = ENGINE_ID_DIGF; - break; - case DCN10_DIG_FE_SOURCE_SELECT_DIGG: - result = ENGINE_ID_DIGG; - break; - default: - // invalid source select DIG - result = ENGINE_ID_UNKNOWN; - } - - return result; - -} - -void enc1_configure_encoder( - struct dcn10_link_encoder *enc10, - const struct dc_link_settings *link_settings) -{ - /* set number of lanes */ - REG_SET(DP_CONFIG, 0, - DP_UDI_LANES, link_settings->lane_count - LANE_COUNT_ONE); - - /* setup scrambler */ - REG_UPDATE(DP_DPHY_SCRAM_CNTL, DPHY_SCRAMBLER_ADVANCE, 1); -} - -void dcn10_psr_program_dp_dphy_fast_training(struct link_encoder *enc, - bool exit_link_training_required) -{ - struct dcn10_link_encoder *enc10 = TO_DCN10_LINK_ENC(enc); - - if (exit_link_training_required) - REG_UPDATE(DP_DPHY_FAST_TRAINING, - DPHY_RX_FAST_TRAINING_CAPABLE, 1); - else { - REG_UPDATE(DP_DPHY_FAST_TRAINING, - DPHY_RX_FAST_TRAINING_CAPABLE, 0); - /*In DCE 11, we are able to pre-program a Force SR register - * to be able to trigger SR symbol after 5 idle patterns - * transmitted. Upon PSR Exit, DMCU can trigger - * DPHY_LOAD_BS_COUNT_START = 1. Upon writing 1 to - * DPHY_LOAD_BS_COUNT_START and the internal counter - * reaches DPHY_LOAD_BS_COUNT, the next BS symbol will be - * replaced by SR symbol once. - */ - - REG_UPDATE(DP_DPHY_BS_SR_SWAP_CNTL, DPHY_LOAD_BS_COUNT, 0x5); - } -} - -void dcn10_psr_program_secondary_packet(struct link_encoder *enc, - unsigned int sdp_transmit_line_num_deadline) -{ - struct dcn10_link_encoder *enc10 = TO_DCN10_LINK_ENC(enc); - - REG_UPDATE_2(DP_SEC_CNTL1, - DP_SEC_GSP0_LINE_NUM, sdp_transmit_line_num_deadline, - DP_SEC_GSP0_PRIORITY, 1); -} - -bool dcn10_is_dig_enabled(struct link_encoder *enc) -{ - struct dcn10_link_encoder *enc10 = TO_DCN10_LINK_ENC(enc); - uint32_t value; - - REG_GET(DIG_BE_EN_CNTL, DIG_ENABLE, &value); - return value; -} - -static void link_encoder_disable(struct dcn10_link_encoder *enc10) -{ - /* reset training pattern */ - REG_SET(DP_DPHY_TRAINING_PATTERN_SEL, 0, - DPHY_TRAINING_PATTERN_SEL, 0); - - /* reset training complete */ - REG_UPDATE(DP_LINK_CNTL, DP_LINK_TRAINING_COMPLETE, 0); - - /* reset panel mode */ - setup_panel_mode(enc10, DP_PANEL_MODE_DEFAULT); -} - -static void hpd_initialize( - struct dcn10_link_encoder *enc10) -{ - /* Associate HPD with DIG_BE */ - enum hpd_source_id hpd_source = enc10->base.hpd_source; - - REG_UPDATE(DIG_BE_CNTL, DIG_HPD_SELECT, hpd_source); -} - -bool dcn10_link_encoder_validate_dvi_output( - const struct dcn10_link_encoder *enc10, - enum signal_type connector_signal, - enum signal_type signal, - const struct dc_crtc_timing *crtc_timing) -{ - uint32_t max_pixel_clock = TMDS_MAX_PIXEL_CLOCK; - - if (signal == SIGNAL_TYPE_DVI_DUAL_LINK) - max_pixel_clock *= 2; - - /* This handles the case of HDMI downgrade to DVI we don't want to - * we don't want to cap the pixel clock if the DDI is not DVI. - */ - if (connector_signal != SIGNAL_TYPE_DVI_DUAL_LINK && - connector_signal != SIGNAL_TYPE_DVI_SINGLE_LINK) - max_pixel_clock = enc10->base.features.max_hdmi_pixel_clock; - - /* DVI only support RGB pixel encoding */ - if (crtc_timing->pixel_encoding != PIXEL_ENCODING_RGB) - return false; - - /*connect DVI via adpater's HDMI connector*/ - if ((connector_signal == SIGNAL_TYPE_DVI_SINGLE_LINK || - connector_signal == SIGNAL_TYPE_HDMI_TYPE_A) && - signal != SIGNAL_TYPE_HDMI_TYPE_A && - crtc_timing->pix_clk_100hz > (TMDS_MAX_PIXEL_CLOCK * 10)) - return false; - if (crtc_timing->pix_clk_100hz < (TMDS_MIN_PIXEL_CLOCK * 10)) - return false; - - if (crtc_timing->pix_clk_100hz > (max_pixel_clock * 10)) - return false; - - /* DVI supports 6/8bpp single-link and 10/16bpp dual-link */ - switch (crtc_timing->display_color_depth) { - case COLOR_DEPTH_666: - case COLOR_DEPTH_888: - break; - case COLOR_DEPTH_101010: - case COLOR_DEPTH_161616: - if (signal != SIGNAL_TYPE_DVI_DUAL_LINK) - return false; - break; - default: - return false; - } - - return true; -} - -static bool dcn10_link_encoder_validate_hdmi_output( - const struct dcn10_link_encoder *enc10, - const struct dc_crtc_timing *crtc_timing, - const struct dc_edid_caps *edid_caps, - int adjusted_pix_clk_100hz) -{ - enum dc_color_depth max_deep_color = - enc10->base.features.max_hdmi_deep_color; - - // check pixel clock against edid specified max TMDS clk - if (edid_caps->max_tmds_clk_mhz != 0 && - adjusted_pix_clk_100hz > edid_caps->max_tmds_clk_mhz * 10000) - return false; - - if (max_deep_color < crtc_timing->display_color_depth) - return false; - - if (crtc_timing->display_color_depth < COLOR_DEPTH_888) - return false; - if (adjusted_pix_clk_100hz < (TMDS_MIN_PIXEL_CLOCK * 10)) - return false; - - if ((adjusted_pix_clk_100hz == 0) || - (adjusted_pix_clk_100hz > (enc10->base.features.max_hdmi_pixel_clock * 10))) - return false; - - /* DCE11 HW does not support 420 */ - if (!enc10->base.features.hdmi_ycbcr420_supported && - crtc_timing->pixel_encoding == PIXEL_ENCODING_YCBCR420) - return false; - - if ((!enc10->base.features.flags.bits.HDMI_6GB_EN || - enc10->base.ctx->dc->debug.hdmi20_disable) && - adjusted_pix_clk_100hz >= 3000000) - return false; - if (enc10->base.ctx->dc->debug.hdmi20_disable && - crtc_timing->pixel_encoding == PIXEL_ENCODING_YCBCR420) - return false; - return true; -} - -bool dcn10_link_encoder_validate_dp_output( - const struct dcn10_link_encoder *enc10, - const struct dc_crtc_timing *crtc_timing) -{ - if (crtc_timing->pixel_encoding == PIXEL_ENCODING_YCBCR420) { - if (!enc10->base.features.dp_ycbcr420_supported) - return false; - } - - return true; -} - -void dcn10_link_encoder_construct( - struct dcn10_link_encoder *enc10, - const struct encoder_init_data *init_data, - const struct encoder_feature_support *enc_features, - const struct dcn10_link_enc_registers *link_regs, - const struct dcn10_link_enc_aux_registers *aux_regs, - const struct dcn10_link_enc_hpd_registers *hpd_regs, - const struct dcn10_link_enc_shift *link_shift, - const struct dcn10_link_enc_mask *link_mask) -{ - struct bp_encoder_cap_info bp_cap_info = {0}; - const struct dc_vbios_funcs *bp_funcs = init_data->ctx->dc_bios->funcs; - enum bp_result result = BP_RESULT_OK; - - enc10->base.funcs = &dcn10_lnk_enc_funcs; - enc10->base.ctx = init_data->ctx; - enc10->base.id = init_data->encoder; - - enc10->base.hpd_source = init_data->hpd_source; - enc10->base.connector = init_data->connector; - - enc10->base.preferred_engine = ENGINE_ID_UNKNOWN; - - enc10->base.features = *enc_features; - - enc10->base.transmitter = init_data->transmitter; - - /* set the flag to indicate whether driver poll the I2C data pin - * while doing the DP sink detect - */ - -/* if (dal_adapter_service_is_feature_supported(as, - FEATURE_DP_SINK_DETECT_POLL_DATA_PIN)) - enc10->base.features.flags.bits. - DP_SINK_DETECT_POLL_DATA_PIN = true;*/ - - enc10->base.output_signals = - SIGNAL_TYPE_DVI_SINGLE_LINK | - SIGNAL_TYPE_DVI_DUAL_LINK | - SIGNAL_TYPE_LVDS | - SIGNAL_TYPE_DISPLAY_PORT | - SIGNAL_TYPE_DISPLAY_PORT_MST | - SIGNAL_TYPE_EDP | - SIGNAL_TYPE_HDMI_TYPE_A; - - /* For DCE 8.0 and 8.1, by design, UNIPHY is hardwired to DIG_BE. - * SW always assign DIG_FE 1:1 mapped to DIG_FE for non-MST UNIPHY. - * SW assign DIG_FE to non-MST UNIPHY first and MST last. So prefer - * DIG is per UNIPHY and used by SST DP, eDP, HDMI, DVI and LVDS. - * Prefer DIG assignment is decided by board design. - * For DCE 8.0, there are only max 6 UNIPHYs, we assume board design - * and VBIOS will filter out 7 UNIPHY for DCE 8.0. - * By this, adding DIGG should not hurt DCE 8.0. - * This will let DCE 8.1 share DCE 8.0 as much as possible - */ - - enc10->link_regs = link_regs; - enc10->aux_regs = aux_regs; - enc10->hpd_regs = hpd_regs; - enc10->link_shift = link_shift; - enc10->link_mask = link_mask; - - switch (enc10->base.transmitter) { - case TRANSMITTER_UNIPHY_A: - enc10->base.preferred_engine = ENGINE_ID_DIGA; - break; - case TRANSMITTER_UNIPHY_B: - enc10->base.preferred_engine = ENGINE_ID_DIGB; - break; - case TRANSMITTER_UNIPHY_C: - enc10->base.preferred_engine = ENGINE_ID_DIGC; - break; - case TRANSMITTER_UNIPHY_D: - enc10->base.preferred_engine = ENGINE_ID_DIGD; - break; - case TRANSMITTER_UNIPHY_E: - enc10->base.preferred_engine = ENGINE_ID_DIGE; - break; - case TRANSMITTER_UNIPHY_F: - enc10->base.preferred_engine = ENGINE_ID_DIGF; - break; - case TRANSMITTER_UNIPHY_G: - enc10->base.preferred_engine = ENGINE_ID_DIGG; - break; - default: - ASSERT_CRITICAL(false); - enc10->base.preferred_engine = ENGINE_ID_UNKNOWN; - } - - /* default to one to mirror Windows behavior */ - enc10->base.features.flags.bits.HDMI_6GB_EN = 1; - - result = bp_funcs->get_encoder_cap_info(enc10->base.ctx->dc_bios, - enc10->base.id, &bp_cap_info); - - /* Override features with DCE-specific values */ - if (result == BP_RESULT_OK) { - enc10->base.features.flags.bits.IS_HBR2_CAPABLE = - bp_cap_info.DP_HBR2_EN; - enc10->base.features.flags.bits.IS_HBR3_CAPABLE = - bp_cap_info.DP_HBR3_EN; - enc10->base.features.flags.bits.HDMI_6GB_EN = bp_cap_info.HDMI_6GB_EN; - enc10->base.features.flags.bits.DP_IS_USB_C = - bp_cap_info.DP_IS_USB_C; - } else { - DC_LOG_WARNING("%s: Failed to get encoder_cap_info from VBIOS with error code %d!\n", - __func__, - result); - } - if (enc10->base.ctx->dc->debug.hdmi20_disable) { - enc10->base.features.flags.bits.HDMI_6GB_EN = 0; - } -} - -bool dcn10_link_encoder_validate_output_with_stream( - struct link_encoder *enc, - const struct dc_stream_state *stream) -{ - struct dcn10_link_encoder *enc10 = TO_DCN10_LINK_ENC(enc); - bool is_valid; - - //if SCDC (340-600MHz) is disabled, set to HDMI 1.4 timing limit - if (stream->sink->edid_caps.panel_patch.skip_scdc_overwrite && - enc10->base.features.max_hdmi_pixel_clock > 300000) - enc10->base.features.max_hdmi_pixel_clock = 300000; - - switch (stream->signal) { - case SIGNAL_TYPE_DVI_SINGLE_LINK: - case SIGNAL_TYPE_DVI_DUAL_LINK: - is_valid = dcn10_link_encoder_validate_dvi_output( - enc10, - stream->link->connector_signal, - stream->signal, - &stream->timing); - break; - case SIGNAL_TYPE_HDMI_TYPE_A: - is_valid = dcn10_link_encoder_validate_hdmi_output( - enc10, - &stream->timing, - &stream->sink->edid_caps, - stream->phy_pix_clk * 10); - break; - case SIGNAL_TYPE_DISPLAY_PORT: - case SIGNAL_TYPE_DISPLAY_PORT_MST: - is_valid = dcn10_link_encoder_validate_dp_output( - enc10, &stream->timing); - break; - case SIGNAL_TYPE_EDP: - is_valid = (stream->timing.pixel_encoding == PIXEL_ENCODING_RGB) ? true : false; - break; - case SIGNAL_TYPE_VIRTUAL: - is_valid = true; - break; - default: - is_valid = false; - break; - } - - return is_valid; -} - -void dcn10_link_encoder_hw_init( - struct link_encoder *enc) -{ - struct dcn10_link_encoder *enc10 = TO_DCN10_LINK_ENC(enc); - struct bp_transmitter_control cntl = { 0 }; - enum bp_result result; - - cntl.action = TRANSMITTER_CONTROL_INIT; - cntl.engine_id = ENGINE_ID_UNKNOWN; - cntl.transmitter = enc10->base.transmitter; - cntl.connector_obj_id = enc10->base.connector; - cntl.lanes_number = LANE_COUNT_FOUR; - cntl.coherent = false; - cntl.hpd_sel = enc10->base.hpd_source; - - if (enc10->base.connector.id == CONNECTOR_ID_EDP) - cntl.signal = SIGNAL_TYPE_EDP; - - result = link_transmitter_control(enc10, &cntl); - - if (result != BP_RESULT_OK) { - DC_LOG_ERROR("%s: Failed to execute VBIOS command table!\n", - __func__); - BREAK_TO_DEBUGGER(); - return; - } - - if (enc10->base.connector.id == CONNECTOR_ID_LVDS) { - cntl.action = TRANSMITTER_CONTROL_BACKLIGHT_BRIGHTNESS; - - result = link_transmitter_control(enc10, &cntl); - - ASSERT(result == BP_RESULT_OK); - - } - dcn10_aux_initialize(enc10); - - /* reinitialize HPD. - * hpd_initialize() will pass DIG_FE id to HW context. - * All other routine within HW context will use fe_engine_offset - * as DIG_FE id even caller pass DIG_FE id. - * So this routine must be called first. - */ - hpd_initialize(enc10); -} - -void dcn10_link_encoder_destroy(struct link_encoder **enc) -{ - kfree(TO_DCN10_LINK_ENC(*enc)); - *enc = NULL; -} - -void dcn10_link_encoder_setup( - struct link_encoder *enc, - enum signal_type signal) -{ - struct dcn10_link_encoder *enc10 = TO_DCN10_LINK_ENC(enc); - - switch (signal) { - case SIGNAL_TYPE_EDP: - case SIGNAL_TYPE_DISPLAY_PORT: - /* DP SST */ - REG_UPDATE(DIG_BE_CNTL, DIG_MODE, 0); - break; - case SIGNAL_TYPE_LVDS: - /* LVDS */ - REG_UPDATE(DIG_BE_CNTL, DIG_MODE, 1); - break; - case SIGNAL_TYPE_DVI_SINGLE_LINK: - case SIGNAL_TYPE_DVI_DUAL_LINK: - /* TMDS-DVI */ - REG_UPDATE(DIG_BE_CNTL, DIG_MODE, 2); - break; - case SIGNAL_TYPE_HDMI_TYPE_A: - /* TMDS-HDMI */ - REG_UPDATE(DIG_BE_CNTL, DIG_MODE, 3); - break; - case SIGNAL_TYPE_DISPLAY_PORT_MST: - /* DP MST */ - REG_UPDATE(DIG_BE_CNTL, DIG_MODE, 5); - break; - default: - ASSERT_CRITICAL(false); - /* invalid mode ! */ - break; - } - -} - -/* TODO: still need depth or just pass in adjusted pixel clock? */ -void dcn10_link_encoder_enable_tmds_output( - struct link_encoder *enc, - enum clock_source_id clock_source, - enum dc_color_depth color_depth, - enum signal_type signal, - uint32_t pixel_clock) -{ - struct dcn10_link_encoder *enc10 = TO_DCN10_LINK_ENC(enc); - struct bp_transmitter_control cntl = { 0 }; - enum bp_result result; - - /* Enable the PHY */ - - cntl.action = TRANSMITTER_CONTROL_ENABLE; - cntl.engine_id = enc->preferred_engine; - cntl.transmitter = enc10->base.transmitter; - cntl.pll_id = clock_source; - cntl.signal = signal; - if (cntl.signal == SIGNAL_TYPE_DVI_DUAL_LINK) - cntl.lanes_number = 8; - else - cntl.lanes_number = 4; - - cntl.hpd_sel = enc10->base.hpd_source; - - cntl.pixel_clock = pixel_clock; - cntl.color_depth = color_depth; - - result = link_transmitter_control(enc10, &cntl); - - if (result != BP_RESULT_OK) { - DC_LOG_ERROR("%s: Failed to execute VBIOS command table!\n", - __func__); - BREAK_TO_DEBUGGER(); - } -} - -void dcn10_link_encoder_enable_tmds_output_with_clk_pattern_wa( - struct link_encoder *enc, - enum clock_source_id clock_source, - enum dc_color_depth color_depth, - enum signal_type signal, - uint32_t pixel_clock) -{ - struct dcn10_link_encoder *enc10 = TO_DCN10_LINK_ENC(enc); - - dcn10_link_encoder_enable_tmds_output( - enc, clock_source, color_depth, signal, pixel_clock); - - REG_UPDATE(DIG_CLOCK_PATTERN, DIG_CLOCK_PATTERN, 0x1F); -} - -/* enables DP PHY output */ -void dcn10_link_encoder_enable_dp_output( - struct link_encoder *enc, - const struct dc_link_settings *link_settings, - enum clock_source_id clock_source) -{ - struct dcn10_link_encoder *enc10 = TO_DCN10_LINK_ENC(enc); - struct bp_transmitter_control cntl = { 0 }; - enum bp_result result; - - /* Enable the PHY */ - - /* number_of_lanes is used for pixel clock adjust, - * but it's not passed to asic_control. - * We need to set number of lanes manually. - */ - enc1_configure_encoder(enc10, link_settings); - - cntl.action = TRANSMITTER_CONTROL_ENABLE; - cntl.engine_id = enc->preferred_engine; - cntl.transmitter = enc10->base.transmitter; - cntl.pll_id = clock_source; - cntl.signal = SIGNAL_TYPE_DISPLAY_PORT; - cntl.lanes_number = link_settings->lane_count; - cntl.hpd_sel = enc10->base.hpd_source; - cntl.pixel_clock = link_settings->link_rate - * LINK_RATE_REF_FREQ_IN_KHZ; - /* TODO: check if undefined works */ - cntl.color_depth = COLOR_DEPTH_UNDEFINED; - - result = link_transmitter_control(enc10, &cntl); - - if (result != BP_RESULT_OK) { - DC_LOG_ERROR("%s: Failed to execute VBIOS command table!\n", - __func__); - BREAK_TO_DEBUGGER(); - } -} - -/* enables DP PHY output in MST mode */ -void dcn10_link_encoder_enable_dp_mst_output( - struct link_encoder *enc, - const struct dc_link_settings *link_settings, - enum clock_source_id clock_source) -{ - struct dcn10_link_encoder *enc10 = TO_DCN10_LINK_ENC(enc); - struct bp_transmitter_control cntl = { 0 }; - enum bp_result result; - - /* Enable the PHY */ - - /* number_of_lanes is used for pixel clock adjust, - * but it's not passed to asic_control. - * We need to set number of lanes manually. - */ - enc1_configure_encoder(enc10, link_settings); - - cntl.action = TRANSMITTER_CONTROL_ENABLE; - cntl.engine_id = ENGINE_ID_UNKNOWN; - cntl.transmitter = enc10->base.transmitter; - cntl.pll_id = clock_source; - cntl.signal = SIGNAL_TYPE_DISPLAY_PORT_MST; - cntl.lanes_number = link_settings->lane_count; - cntl.hpd_sel = enc10->base.hpd_source; - cntl.pixel_clock = link_settings->link_rate - * LINK_RATE_REF_FREQ_IN_KHZ; - /* TODO: check if undefined works */ - cntl.color_depth = COLOR_DEPTH_UNDEFINED; - - result = link_transmitter_control(enc10, &cntl); - - if (result != BP_RESULT_OK) { - DC_LOG_ERROR("%s: Failed to execute VBIOS command table!\n", - __func__); - BREAK_TO_DEBUGGER(); - } -} -/* - * @brief - * Disable transmitter and its encoder - */ -void dcn10_link_encoder_disable_output( - struct link_encoder *enc, - enum signal_type signal) -{ - struct dcn10_link_encoder *enc10 = TO_DCN10_LINK_ENC(enc); - struct bp_transmitter_control cntl = { 0 }; - enum bp_result result; - - if (enc->funcs->is_dig_enabled && !enc->funcs->is_dig_enabled(enc)) { - /* OF_SKIP_POWER_DOWN_INACTIVE_ENCODER */ - /*in DP_Alt_No_Connect case, we turn off the dig already, - after excuation the PHY w/a sequence, not allow touch PHY any more*/ - return; - } - /* Power-down RX and disable GPU PHY should be paired. - * Disabling PHY without powering down RX may cause - * symbol lock loss, on which we will get DP Sink interrupt. - */ - - /* There is a case for the DP active dongles - * where we want to disable the PHY but keep RX powered, - * for those we need to ignore DP Sink interrupt - * by checking lane count that has been set - * on the last do_enable_output(). - */ - - /* disable transmitter */ - cntl.action = TRANSMITTER_CONTROL_DISABLE; - cntl.transmitter = enc10->base.transmitter; - cntl.hpd_sel = enc10->base.hpd_source; - cntl.signal = signal; - cntl.connector_obj_id = enc10->base.connector; - - result = link_transmitter_control(enc10, &cntl); - - if (result != BP_RESULT_OK) { - DC_LOG_ERROR("%s: Failed to execute VBIOS command table!\n", - __func__); - BREAK_TO_DEBUGGER(); - return; - } - - /* disable encoder */ - if (dc_is_dp_signal(signal)) - link_encoder_disable(enc10); -} - -void dcn10_link_encoder_dp_set_lane_settings( - struct link_encoder *enc, - const struct dc_link_settings *link_settings, - const struct dc_lane_settings lane_settings[LANE_COUNT_DP_MAX]) -{ - struct dcn10_link_encoder *enc10 = TO_DCN10_LINK_ENC(enc); - union dpcd_training_lane_set training_lane_set = { { 0 } }; - int32_t lane = 0; - struct bp_transmitter_control cntl = { 0 }; - enum bp_result result; - - if (!link_settings) { - BREAK_TO_DEBUGGER(); - return; - } - - cntl.action = TRANSMITTER_CONTROL_SET_VOLTAGE_AND_PREEMPASIS; - cntl.transmitter = enc10->base.transmitter; - cntl.connector_obj_id = enc10->base.connector; - cntl.lanes_number = link_settings->lane_count; - cntl.hpd_sel = enc10->base.hpd_source; - cntl.pixel_clock = link_settings->link_rate * LINK_RATE_REF_FREQ_IN_KHZ; - - for (lane = 0; lane < link_settings->lane_count; lane++) { - /* translate lane settings */ - - training_lane_set.bits.VOLTAGE_SWING_SET = - lane_settings[lane].VOLTAGE_SWING; - training_lane_set.bits.PRE_EMPHASIS_SET = - lane_settings[lane].PRE_EMPHASIS; - - /* post cursor 2 setting only applies to HBR2 link rate */ - if (link_settings->link_rate == LINK_RATE_HIGH2) { - /* this is passed to VBIOS - * to program post cursor 2 level - */ - training_lane_set.bits.POST_CURSOR2_SET = - lane_settings[lane].POST_CURSOR2; - } - - cntl.lane_select = lane; - cntl.lane_settings = training_lane_set.raw; - - /* call VBIOS table to set voltage swing and pre-emphasis */ - result = link_transmitter_control(enc10, &cntl); - - if (result != BP_RESULT_OK) { - DC_LOG_ERROR("%s: Failed to execute VBIOS command table!\n", __func__); - BREAK_TO_DEBUGGER(); - } - } -} - -/* set DP PHY test and training patterns */ -void dcn10_link_encoder_dp_set_phy_pattern( - struct link_encoder *enc, - const struct encoder_set_dp_phy_pattern_param *param) -{ - struct dcn10_link_encoder *enc10 = TO_DCN10_LINK_ENC(enc); - - switch (param->dp_phy_pattern) { - case DP_TEST_PATTERN_TRAINING_PATTERN1: - dcn10_link_encoder_set_dp_phy_pattern_training_pattern(enc, 0); - break; - case DP_TEST_PATTERN_TRAINING_PATTERN2: - dcn10_link_encoder_set_dp_phy_pattern_training_pattern(enc, 1); - break; - case DP_TEST_PATTERN_TRAINING_PATTERN3: - dcn10_link_encoder_set_dp_phy_pattern_training_pattern(enc, 2); - break; - case DP_TEST_PATTERN_TRAINING_PATTERN4: - dcn10_link_encoder_set_dp_phy_pattern_training_pattern(enc, 3); - break; - case DP_TEST_PATTERN_D102: - set_dp_phy_pattern_d102(enc10); - break; - case DP_TEST_PATTERN_SYMBOL_ERROR: - set_dp_phy_pattern_symbol_error(enc10); - break; - case DP_TEST_PATTERN_PRBS7: - set_dp_phy_pattern_prbs7(enc10); - break; - case DP_TEST_PATTERN_80BIT_CUSTOM: - set_dp_phy_pattern_80bit_custom( - enc10, param->custom_pattern); - break; - case DP_TEST_PATTERN_CP2520_1: - set_dp_phy_pattern_hbr2_compliance_cp2520_2(enc10, 1); - break; - case DP_TEST_PATTERN_CP2520_2: - set_dp_phy_pattern_hbr2_compliance_cp2520_2(enc10, 2); - break; - case DP_TEST_PATTERN_CP2520_3: - set_dp_phy_pattern_hbr2_compliance_cp2520_2(enc10, 3); - break; - case DP_TEST_PATTERN_VIDEO_MODE: { - set_dp_phy_pattern_passthrough_mode( - enc10, param->dp_panel_mode); - break; - } - - default: - /* invalid phy pattern */ - ASSERT_CRITICAL(false); - break; - } -} - -static void fill_stream_allocation_row_info( - const struct link_mst_stream_allocation *stream_allocation, - uint32_t *src, - uint32_t *slots) -{ - const struct stream_encoder *stream_enc = stream_allocation->stream_enc; - - if (stream_enc) { - *src = stream_enc->id; - *slots = stream_allocation->slot_count; - } else { - *src = 0; - *slots = 0; - } -} - -/* programs DP MST VC payload allocation */ -void dcn10_link_encoder_update_mst_stream_allocation_table( - struct link_encoder *enc, - const struct link_mst_stream_allocation_table *table) -{ - struct dcn10_link_encoder *enc10 = TO_DCN10_LINK_ENC(enc); - uint32_t value1 = 0; - uint32_t value2 = 0; - uint32_t slots = 0; - uint32_t src = 0; - uint32_t retries = 0; - - /* For CZ, there are only 3 pipes. So Virtual channel is up 3.*/ - - /* --- Set MSE Stream Attribute - - * Setup VC Payload Table on Tx Side, - * Issue allocation change trigger - * to commit payload on both tx and rx side - */ - - /* we should clean-up table each time */ - - if (table->stream_count >= 1) { - fill_stream_allocation_row_info( - &table->stream_allocations[0], - &src, - &slots); - } else { - src = 0; - slots = 0; - } - - REG_UPDATE_2(DP_MSE_SAT0, - DP_MSE_SAT_SRC0, src, - DP_MSE_SAT_SLOT_COUNT0, slots); - - if (table->stream_count >= 2) { - fill_stream_allocation_row_info( - &table->stream_allocations[1], - &src, - &slots); - } else { - src = 0; - slots = 0; - } - - REG_UPDATE_2(DP_MSE_SAT0, - DP_MSE_SAT_SRC1, src, - DP_MSE_SAT_SLOT_COUNT1, slots); - - if (table->stream_count >= 3) { - fill_stream_allocation_row_info( - &table->stream_allocations[2], - &src, - &slots); - } else { - src = 0; - slots = 0; - } - - REG_UPDATE_2(DP_MSE_SAT1, - DP_MSE_SAT_SRC2, src, - DP_MSE_SAT_SLOT_COUNT2, slots); - - if (table->stream_count >= 4) { - fill_stream_allocation_row_info( - &table->stream_allocations[3], - &src, - &slots); - } else { - src = 0; - slots = 0; - } - - REG_UPDATE_2(DP_MSE_SAT1, - DP_MSE_SAT_SRC3, src, - DP_MSE_SAT_SLOT_COUNT3, slots); - - /* --- wait for transaction finish */ - - /* send allocation change trigger (ACT) ? - * this step first sends the ACT, - * then double buffers the SAT into the hardware - * making the new allocation active on the DP MST mode link - */ - - /* DP_MSE_SAT_UPDATE: - * 0 - No Action - * 1 - Update SAT with trigger - * 2 - Update SAT without trigger - */ - REG_UPDATE(DP_MSE_SAT_UPDATE, - DP_MSE_SAT_UPDATE, 1); - - /* wait for update to complete - * (i.e. DP_MSE_SAT_UPDATE field is reset to 0) - * then wait for the transmission - * of at least 16 MTP headers on immediate local link. - * i.e. DP_MSE_16_MTP_KEEPOUT field (read only) is reset to 0 - * a value of 1 indicates that DP MST mode - * is in the 16 MTP keepout region after a VC has been added. - * MST stream bandwidth (VC rate) can be configured - * after this bit is cleared - */ - do { - udelay(10); - - REG_READ(DP_MSE_SAT_UPDATE); - - REG_GET(DP_MSE_SAT_UPDATE, - DP_MSE_SAT_UPDATE, &value1); - - REG_GET(DP_MSE_SAT_UPDATE, - DP_MSE_16_MTP_KEEPOUT, &value2); - - /* bit field DP_MSE_SAT_UPDATE is set to 1 already */ - if (!value1 && !value2) - break; - ++retries; - } while (retries < DP_MST_UPDATE_MAX_RETRY); -} - -void dcn10_link_encoder_connect_dig_be_to_fe( - struct link_encoder *enc, - enum engine_id engine, - bool connect) -{ - struct dcn10_link_encoder *enc10 = TO_DCN10_LINK_ENC(enc); - uint32_t field; - - if (engine != ENGINE_ID_UNKNOWN) { - - REG_GET(DIG_BE_CNTL, DIG_FE_SOURCE_SELECT, &field); - - if (connect) - field |= get_frontend_source(engine); - else - field &= ~get_frontend_source(engine); - - REG_UPDATE(DIG_BE_CNTL, DIG_FE_SOURCE_SELECT, field); - } -} - - -#define HPD_REG(reg)\ - (enc10->hpd_regs->reg) - -#define HPD_REG_READ(reg_name) \ - dm_read_reg(CTX, HPD_REG(reg_name)) - -#define HPD_REG_UPDATE_N(reg_name, n, ...) \ - generic_reg_update_ex(CTX, \ - HPD_REG(reg_name), \ - n, __VA_ARGS__) - -#define HPD_REG_UPDATE(reg_name, field, val) \ - HPD_REG_UPDATE_N(reg_name, 1, \ - FN(reg_name, field), val) - -void dcn10_link_encoder_enable_hpd(struct link_encoder *enc) -{ - struct dcn10_link_encoder *enc10 = TO_DCN10_LINK_ENC(enc); - - HPD_REG_UPDATE(DC_HPD_CONTROL, - DC_HPD_EN, 1); -} - -void dcn10_link_encoder_disable_hpd(struct link_encoder *enc) -{ - struct dcn10_link_encoder *enc10 = TO_DCN10_LINK_ENC(enc); - - HPD_REG_UPDATE(DC_HPD_CONTROL, - DC_HPD_EN, 0); -} - -#define AUX_REG(reg)\ - (enc10->aux_regs->reg) - -#define AUX_REG_READ(reg_name) \ - dm_read_reg(CTX, AUX_REG(reg_name)) - -#define AUX_REG_UPDATE_N(reg_name, n, ...) \ - generic_reg_update_ex(CTX, \ - AUX_REG(reg_name), \ - n, __VA_ARGS__) - -#define AUX_REG_UPDATE(reg_name, field, val) \ - AUX_REG_UPDATE_N(reg_name, 1, \ - FN(reg_name, field), val) - -#define AUX_REG_UPDATE_2(reg, f1, v1, f2, v2) \ - AUX_REG_UPDATE_N(reg, 2,\ - FN(reg, f1), v1,\ - FN(reg, f2), v2) - -void dcn10_aux_initialize(struct dcn10_link_encoder *enc10) -{ - enum hpd_source_id hpd_source = enc10->base.hpd_source; - - AUX_REG_UPDATE_2(AUX_CONTROL, - AUX_HPD_SEL, hpd_source, - AUX_LS_READ_EN, 0); - - /* 1/4 window (the maximum allowed) */ - AUX_REG_UPDATE(AUX_DPHY_RX_CONTROL0, - AUX_RX_RECEIVE_WINDOW, 0); -} - -enum signal_type dcn10_get_dig_mode( - struct link_encoder *enc) -{ - struct dcn10_link_encoder *enc10 = TO_DCN10_LINK_ENC(enc); - uint32_t value; - REG_GET(DIG_BE_CNTL, DIG_MODE, &value); - switch (value) { - case 1: - return SIGNAL_TYPE_DISPLAY_PORT; - case 2: - return SIGNAL_TYPE_DVI_SINGLE_LINK; - case 3: - return SIGNAL_TYPE_HDMI_TYPE_A; - case 5: - return SIGNAL_TYPE_DISPLAY_PORT_MST; - default: - return SIGNAL_TYPE_NONE; - } -} - -void dcn10_link_encoder_get_max_link_cap(struct link_encoder *enc, - struct dc_link_settings *link_settings) -{ - /* Set Default link settings */ - struct dc_link_settings max_link_cap = {LANE_COUNT_FOUR, LINK_RATE_HIGH, - LINK_SPREAD_05_DOWNSPREAD_30KHZ, false, 0}; - - /* Higher link settings based on feature supported */ - if (enc->features.flags.bits.IS_HBR2_CAPABLE) - max_link_cap.link_rate = LINK_RATE_HIGH2; - - if (enc->features.flags.bits.IS_HBR3_CAPABLE) - max_link_cap.link_rate = LINK_RATE_HIGH3; - - if (enc->features.flags.bits.IS_UHBR10_CAPABLE) - max_link_cap.link_rate = LINK_RATE_UHBR10; - - if (enc->features.flags.bits.IS_UHBR13_5_CAPABLE) - max_link_cap.link_rate = LINK_RATE_UHBR13_5; - - if (enc->features.flags.bits.IS_UHBR20_CAPABLE) - max_link_cap.link_rate = LINK_RATE_UHBR20; - - *link_settings = max_link_cap; -} diff --git a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_link_encoder.h b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_link_encoder.h deleted file mode 100644 index b7a89c39f445..000000000000 --- a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_link_encoder.h +++ /dev/null @@ -1,659 +0,0 @@ -/* - * Copyright 2012-15 Advanced Micro Devices, Inc. - * - * Permission is hereby granted, free of charge, to any person obtaining a - * copy of this software and associated documentation files (the "Software"), - * to deal in the Software without restriction, including without limitation - * the rights to use, copy, modify, merge, publish, distribute, sublicense, - * and/or sell copies of the Software, and to permit persons to whom the - * Software is furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL - * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR - * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, - * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR - * OTHER DEALINGS IN THE SOFTWARE. - * - * Authors: AMD - * - */ - -#ifndef __DC_LINK_ENCODER__DCN10_H__ -#define __DC_LINK_ENCODER__DCN10_H__ - -#include "link_encoder.h" - -#define TO_DCN10_LINK_ENC(link_encoder)\ - container_of(link_encoder, struct dcn10_link_encoder, base) - -#define AUX_REG_LIST(id)\ - SRI(AUX_CONTROL, DP_AUX, id), \ - SRI(AUX_DPHY_RX_CONTROL0, DP_AUX, id), \ - SRI(AUX_DPHY_RX_CONTROL1, DP_AUX, id) - -#define HPD_REG_LIST(id)\ - SRI(DC_HPD_CONTROL, HPD, id) - -#define LE_DCN_COMMON_REG_LIST(id) \ - SRI(DIG_BE_CNTL, DIG, id), \ - SRI(DIG_BE_EN_CNTL, DIG, id), \ - SRI(DIG_CLOCK_PATTERN, DIG, id), \ - SRI(TMDS_CTL_BITS, DIG, id), \ - SRI(DP_CONFIG, DP, id), \ - SRI(DP_DPHY_CNTL, DP, id), \ - SRI(DP_DPHY_PRBS_CNTL, DP, id), \ - SRI(DP_DPHY_SCRAM_CNTL, DP, id),\ - SRI(DP_DPHY_SYM0, DP, id), \ - SRI(DP_DPHY_SYM1, DP, id), \ - SRI(DP_DPHY_SYM2, DP, id), \ - SRI(DP_DPHY_TRAINING_PATTERN_SEL, DP, id), \ - SRI(DP_LINK_CNTL, DP, id), \ - SRI(DP_LINK_FRAMING_CNTL, DP, id), \ - SRI(DP_MSE_SAT0, DP, id), \ - SRI(DP_MSE_SAT1, DP, id), \ - SRI(DP_MSE_SAT2, DP, id), \ - SRI(DP_MSE_SAT_UPDATE, DP, id), \ - SRI(DP_SEC_CNTL, DP, id), \ - SRI(DP_VID_STREAM_CNTL, DP, id), \ - SRI(DP_DPHY_FAST_TRAINING, DP, id), \ - SRI(DP_SEC_CNTL1, DP, id), \ - SRI(DP_DPHY_BS_SR_SWAP_CNTL, DP, id), \ - SRI(DP_DPHY_HBR2_PATTERN_CONTROL, DP, id) - - -#define LE_DCN10_REG_LIST(id)\ - SRI(DP_DPHY_INTERNAL_CTRL, DP, id), \ - LE_DCN_COMMON_REG_LIST(id) - -struct dcn10_link_enc_aux_registers { - uint32_t AUX_CONTROL; - uint32_t AUX_DPHY_RX_CONTROL0; - uint32_t AUX_DPHY_TX_CONTROL; - uint32_t AUX_DPHY_RX_CONTROL1; -}; - -struct dcn10_link_enc_hpd_registers { - uint32_t DC_HPD_CONTROL; -}; - -struct dcn10_link_enc_registers { - uint32_t DIG_BE_CNTL; - uint32_t DIG_BE_EN_CNTL; - uint32_t DIG_CLOCK_PATTERN; - uint32_t DP_CONFIG; - uint32_t DP_DPHY_CNTL; - uint32_t DP_DPHY_INTERNAL_CTRL; - uint32_t DP_DPHY_PRBS_CNTL; - uint32_t DP_DPHY_SCRAM_CNTL; - uint32_t DP_DPHY_SYM0; - uint32_t DP_DPHY_SYM1; - uint32_t DP_DPHY_SYM2; - uint32_t DP_DPHY_TRAINING_PATTERN_SEL; - uint32_t DP_LINK_CNTL; - uint32_t DP_LINK_FRAMING_CNTL; - uint32_t DP_MSE_SAT0; - uint32_t DP_MSE_SAT1; - uint32_t DP_MSE_SAT2; - uint32_t DP_MSE_SAT_UPDATE; - uint32_t DP_SEC_CNTL; - uint32_t DP_VID_STREAM_CNTL; - uint32_t DP_DPHY_FAST_TRAINING; - uint32_t DP_DPHY_BS_SR_SWAP_CNTL; - uint32_t DP_DPHY_HBR2_PATTERN_CONTROL; - uint32_t DP_SEC_CNTL1; - uint32_t TMDS_CTL_BITS; - /* DCCG */ - uint32_t CLOCK_ENABLE; - /* DIG */ - uint32_t DIG_LANE_ENABLE; - /* UNIPHY */ - uint32_t CHANNEL_XBAR_CNTL; - /* DPCS */ - uint32_t RDPCSTX_PHY_CNTL3; - uint32_t RDPCSTX_PHY_CNTL4; - uint32_t RDPCSTX_PHY_CNTL5; - uint32_t RDPCSTX_PHY_CNTL6; - uint32_t RDPCSPIPE_PHY_CNTL6; - uint32_t RDPCSTX_PHY_CNTL7; - uint32_t RDPCSTX_PHY_CNTL8; - uint32_t RDPCSTX_PHY_CNTL9; - uint32_t RDPCSTX_PHY_CNTL10; - uint32_t RDPCSTX_PHY_CNTL11; - uint32_t RDPCSTX_PHY_CNTL12; - uint32_t RDPCSTX_PHY_CNTL13; - uint32_t RDPCSTX_PHY_CNTL14; - uint32_t RDPCSTX_PHY_CNTL15; - uint32_t RDPCSTX_CNTL; - uint32_t RDPCSTX_CLOCK_CNTL; - uint32_t RDPCSTX_PHY_CNTL0; - uint32_t RDPCSTX_PHY_CNTL2; - uint32_t RDPCSTX_PLL_UPDATE_DATA; - uint32_t RDPCS_TX_CR_ADDR; - uint32_t RDPCS_TX_CR_DATA; - uint32_t DPCSTX_TX_CLOCK_CNTL; - uint32_t DPCSTX_TX_CNTL; - uint32_t RDPCSTX_INTERRUPT_CONTROL; - uint32_t RDPCSTX_PHY_FUSE0; - uint32_t RDPCSTX_PHY_FUSE1; - uint32_t RDPCSTX_PHY_FUSE2; - uint32_t RDPCSTX_PHY_FUSE3; - uint32_t RDPCSTX_PHY_RX_LD_VAL; - uint32_t DPCSTX_DEBUG_CONFIG; - uint32_t RDPCSTX_DEBUG_CONFIG; - uint32_t RDPCSTX0_RDPCSTX_SCRATCH; - uint32_t RDPCSTX_DMCU_DPALT_DIS_BLOCK_REG; - uint32_t DCIO_SOFT_RESET; - /* indirect registers */ - uint32_t RAWLANE0_DIG_PCS_XF_RX_OVRD_IN_2; - uint32_t RAWLANE0_DIG_PCS_XF_RX_OVRD_IN_3; - uint32_t RAWLANE1_DIG_PCS_XF_RX_OVRD_IN_2; - uint32_t RAWLANE1_DIG_PCS_XF_RX_OVRD_IN_3; - uint32_t RAWLANE2_DIG_PCS_XF_RX_OVRD_IN_2; - uint32_t RAWLANE2_DIG_PCS_XF_RX_OVRD_IN_3; - uint32_t RAWLANE3_DIG_PCS_XF_RX_OVRD_IN_2; - uint32_t RAWLANE3_DIG_PCS_XF_RX_OVRD_IN_3; - uint32_t TMDS_DCBALANCER_CONTROL; - uint32_t PHYA_LINK_CNTL2; - uint32_t PHYB_LINK_CNTL2; - uint32_t PHYC_LINK_CNTL2; - uint32_t DIO_LINKA_CNTL; - uint32_t DIO_LINKB_CNTL; - uint32_t DIO_LINKC_CNTL; - uint32_t DIO_LINKD_CNTL; - uint32_t DIO_LINKE_CNTL; - uint32_t DIO_LINKF_CNTL; - uint32_t DIO_CLK_CNTL; - uint32_t DIG_BE_CLK_CNTL; -}; - -#define LE_SF(reg_name, field_name, post_fix)\ - .field_name = reg_name ## __ ## field_name ## post_fix - -#define LINK_ENCODER_MASK_SH_LIST_DCN10(mask_sh)\ - LE_SF(DIG0_DIG_BE_EN_CNTL, DIG_ENABLE, mask_sh),\ - LE_SF(DIG0_DIG_BE_CNTL, DIG_HPD_SELECT, mask_sh),\ - LE_SF(DIG0_DIG_BE_CNTL, DIG_MODE, mask_sh),\ - LE_SF(DIG0_DIG_BE_CNTL, DIG_FE_SOURCE_SELECT, mask_sh),\ - LE_SF(DIG0_DIG_CLOCK_PATTERN, DIG_CLOCK_PATTERN, mask_sh),\ - LE_SF(DIG0_TMDS_CTL_BITS, TMDS_CTL0, mask_sh), \ - LE_SF(DP0_DP_DPHY_CNTL, DPHY_BYPASS, mask_sh),\ - LE_SF(DP0_DP_DPHY_CNTL, DPHY_ATEST_SEL_LANE0, mask_sh),\ - LE_SF(DP0_DP_DPHY_CNTL, DPHY_ATEST_SEL_LANE1, mask_sh),\ - LE_SF(DP0_DP_DPHY_CNTL, DPHY_ATEST_SEL_LANE2, mask_sh),\ - LE_SF(DP0_DP_DPHY_CNTL, DPHY_ATEST_SEL_LANE3, mask_sh),\ - LE_SF(DP0_DP_DPHY_PRBS_CNTL, DPHY_PRBS_EN, mask_sh),\ - LE_SF(DP0_DP_DPHY_PRBS_CNTL, DPHY_PRBS_SEL, mask_sh),\ - LE_SF(DP0_DP_DPHY_SYM0, DPHY_SYM1, mask_sh),\ - LE_SF(DP0_DP_DPHY_SYM0, DPHY_SYM2, mask_sh),\ - LE_SF(DP0_DP_DPHY_SYM0, DPHY_SYM3, mask_sh),\ - LE_SF(DP0_DP_DPHY_SYM1, DPHY_SYM4, mask_sh),\ - LE_SF(DP0_DP_DPHY_SYM1, DPHY_SYM5, mask_sh),\ - LE_SF(DP0_DP_DPHY_SYM1, DPHY_SYM6, mask_sh),\ - LE_SF(DP0_DP_DPHY_SYM2, DPHY_SYM7, mask_sh),\ - LE_SF(DP0_DP_DPHY_SYM2, DPHY_SYM8, mask_sh),\ - LE_SF(DP0_DP_DPHY_SCRAM_CNTL, DPHY_SCRAMBLER_BS_COUNT, mask_sh),\ - LE_SF(DP0_DP_DPHY_SCRAM_CNTL, DPHY_SCRAMBLER_ADVANCE, mask_sh),\ - LE_SF(DP0_DP_DPHY_FAST_TRAINING, DPHY_RX_FAST_TRAINING_CAPABLE, mask_sh),\ - LE_SF(DP0_DP_DPHY_BS_SR_SWAP_CNTL, DPHY_LOAD_BS_COUNT, mask_sh),\ - LE_SF(DP0_DP_DPHY_TRAINING_PATTERN_SEL, DPHY_TRAINING_PATTERN_SEL, mask_sh),\ - LE_SF(DP0_DP_DPHY_HBR2_PATTERN_CONTROL, DP_DPHY_HBR2_PATTERN_CONTROL, mask_sh),\ - LE_SF(DP0_DP_LINK_CNTL, DP_LINK_TRAINING_COMPLETE, mask_sh),\ - LE_SF(DP0_DP_LINK_FRAMING_CNTL, DP_IDLE_BS_INTERVAL, mask_sh),\ - LE_SF(DP0_DP_LINK_FRAMING_CNTL, DP_VBID_DISABLE, mask_sh),\ - LE_SF(DP0_DP_LINK_FRAMING_CNTL, DP_VID_ENHANCED_FRAME_MODE, mask_sh),\ - LE_SF(DP0_DP_VID_STREAM_CNTL, DP_VID_STREAM_ENABLE, mask_sh),\ - LE_SF(DP0_DP_CONFIG, DP_UDI_LANES, mask_sh),\ - LE_SF(DP0_DP_SEC_CNTL1, DP_SEC_GSP0_LINE_NUM, mask_sh),\ - LE_SF(DP0_DP_SEC_CNTL1, DP_SEC_GSP0_PRIORITY, mask_sh),\ - LE_SF(DP0_DP_MSE_SAT0, DP_MSE_SAT_SRC0, mask_sh),\ - LE_SF(DP0_DP_MSE_SAT0, DP_MSE_SAT_SRC1, mask_sh),\ - LE_SF(DP0_DP_MSE_SAT0, DP_MSE_SAT_SLOT_COUNT0, mask_sh),\ - LE_SF(DP0_DP_MSE_SAT0, DP_MSE_SAT_SLOT_COUNT1, mask_sh),\ - LE_SF(DP0_DP_MSE_SAT1, DP_MSE_SAT_SRC2, mask_sh),\ - LE_SF(DP0_DP_MSE_SAT1, DP_MSE_SAT_SRC3, mask_sh),\ - LE_SF(DP0_DP_MSE_SAT1, DP_MSE_SAT_SLOT_COUNT2, mask_sh),\ - LE_SF(DP0_DP_MSE_SAT1, DP_MSE_SAT_SLOT_COUNT3, mask_sh),\ - LE_SF(DP0_DP_MSE_SAT_UPDATE, DP_MSE_SAT_UPDATE, mask_sh),\ - LE_SF(DP0_DP_MSE_SAT_UPDATE, DP_MSE_16_MTP_KEEPOUT, mask_sh),\ - LE_SF(DP_AUX0_AUX_CONTROL, AUX_HPD_SEL, mask_sh),\ - LE_SF(DP_AUX0_AUX_CONTROL, AUX_LS_READ_EN, mask_sh),\ - LE_SF(DP_AUX0_AUX_DPHY_RX_CONTROL0, AUX_RX_RECEIVE_WINDOW, mask_sh),\ - LE_SF(HPD0_DC_HPD_CONTROL, DC_HPD_EN, mask_sh) - -#define DCN_LINK_ENCODER_REG_FIELD_LIST(type) \ - type DIG_ENABLE;\ - type DIG_HPD_SELECT;\ - type DIG_MODE;\ - type DIG_FE_SOURCE_SELECT;\ - type DIG_CLOCK_PATTERN;\ - type DPHY_BYPASS;\ - type DPHY_ATEST_SEL_LANE0;\ - type DPHY_ATEST_SEL_LANE1;\ - type DPHY_ATEST_SEL_LANE2;\ - type DPHY_ATEST_SEL_LANE3;\ - type DPHY_PRBS_EN;\ - type DPHY_PRBS_SEL;\ - type DPHY_SYM1;\ - type DPHY_SYM2;\ - type DPHY_SYM3;\ - type DPHY_SYM4;\ - type DPHY_SYM5;\ - type DPHY_SYM6;\ - type DPHY_SYM7;\ - type DPHY_SYM8;\ - type DPHY_SCRAMBLER_BS_COUNT;\ - type DPHY_SCRAMBLER_ADVANCE;\ - type DPHY_RX_FAST_TRAINING_CAPABLE;\ - type DPHY_LOAD_BS_COUNT;\ - type DPHY_TRAINING_PATTERN_SEL;\ - type DP_DPHY_HBR2_PATTERN_CONTROL;\ - type DP_LINK_TRAINING_COMPLETE;\ - type DP_IDLE_BS_INTERVAL;\ - type DP_VBID_DISABLE;\ - type DP_VID_ENHANCED_FRAME_MODE;\ - type DP_VID_STREAM_ENABLE;\ - type DP_UDI_LANES;\ - type DP_SEC_GSP0_LINE_NUM;\ - type DP_SEC_GSP0_PRIORITY;\ - type DP_MSE_SAT_SRC0;\ - type DP_MSE_SAT_SRC1;\ - type DP_MSE_SAT_SRC2;\ - type DP_MSE_SAT_SRC3;\ - type DP_MSE_SAT_SLOT_COUNT0;\ - type DP_MSE_SAT_SLOT_COUNT1;\ - type DP_MSE_SAT_SLOT_COUNT2;\ - type DP_MSE_SAT_SLOT_COUNT3;\ - type DP_MSE_SAT_UPDATE;\ - type DP_MSE_16_MTP_KEEPOUT;\ - type DC_HPD_EN;\ - type TMDS_CTL0;\ - type AUX_HPD_SEL;\ - type AUX_LS_READ_EN;\ - type AUX_RX_RECEIVE_WINDOW - - -#define DCN20_LINK_ENCODER_DPCS_REG_FIELD_LIST(type) \ - type RDPCS_PHY_DP_TX0_DATA_EN;\ - type RDPCS_PHY_DP_TX1_DATA_EN;\ - type RDPCS_PHY_DP_TX2_DATA_EN;\ - type RDPCS_PHY_DP_TX3_DATA_EN;\ - type RDPCS_PHY_DP_TX0_PSTATE;\ - type RDPCS_PHY_DP_TX1_PSTATE;\ - type RDPCS_PHY_DP_TX2_PSTATE;\ - type RDPCS_PHY_DP_TX3_PSTATE;\ - type RDPCS_PHY_DP_TX0_MPLL_EN;\ - type RDPCS_PHY_DP_TX1_MPLL_EN;\ - type RDPCS_PHY_DP_TX2_MPLL_EN;\ - type RDPCS_PHY_DP_TX3_MPLL_EN;\ - type RDPCS_TX_FIFO_LANE0_EN;\ - type RDPCS_TX_FIFO_LANE1_EN;\ - type RDPCS_TX_FIFO_LANE2_EN;\ - type RDPCS_TX_FIFO_LANE3_EN;\ - type RDPCS_EXT_REFCLK_EN;\ - type RDPCS_TX_FIFO_EN;\ - type UNIPHY_LINK_ENABLE;\ - type UNIPHY_CHANNEL0_XBAR_SOURCE;\ - type UNIPHY_CHANNEL1_XBAR_SOURCE;\ - type UNIPHY_CHANNEL2_XBAR_SOURCE;\ - type UNIPHY_CHANNEL3_XBAR_SOURCE;\ - type UNIPHY_CHANNEL0_INVERT;\ - type UNIPHY_CHANNEL1_INVERT;\ - type UNIPHY_CHANNEL2_INVERT;\ - type UNIPHY_CHANNEL3_INVERT;\ - type UNIPHY_LINK_ENABLE_HPD_MASK;\ - type UNIPHY_LANE_STAGGER_DELAY;\ - type RDPCS_SRAMCLK_BYPASS;\ - type RDPCS_SRAMCLK_EN;\ - type RDPCS_SRAMCLK_CLOCK_ON;\ - type DPCS_TX_FIFO_EN;\ - type RDPCS_PHY_DP_TX0_DISABLE;\ - type RDPCS_PHY_DP_TX1_DISABLE;\ - type RDPCS_PHY_DP_TX2_DISABLE;\ - type RDPCS_PHY_DP_TX3_DISABLE;\ - type RDPCS_PHY_DP_TX0_CLK_RDY;\ - type RDPCS_PHY_DP_TX1_CLK_RDY;\ - type RDPCS_PHY_DP_TX2_CLK_RDY;\ - type RDPCS_PHY_DP_TX3_CLK_RDY;\ - type RDPCS_PHY_DP_TX0_REQ;\ - type RDPCS_PHY_DP_TX1_REQ;\ - type RDPCS_PHY_DP_TX2_REQ;\ - type RDPCS_PHY_DP_TX3_REQ;\ - type RDPCS_PHY_DP_TX0_ACK;\ - type RDPCS_PHY_DP_TX1_ACK;\ - type RDPCS_PHY_DP_TX2_ACK;\ - type RDPCS_PHY_DP_TX3_ACK;\ - type RDPCS_PHY_DP_TX0_RESET;\ - type RDPCS_PHY_DP_TX1_RESET;\ - type RDPCS_PHY_DP_TX2_RESET;\ - type RDPCS_PHY_DP_TX3_RESET;\ - type RDPCS_PHY_RESET;\ - type RDPCS_PHY_CR_MUX_SEL;\ - type RDPCS_PHY_REF_RANGE;\ - type RDPCS_PHY_DP4_POR;\ - type RDPCS_SRAM_BYPASS;\ - type RDPCS_SRAM_EXT_LD_DONE;\ - type RDPCS_PHY_DP_TX0_TERM_CTRL;\ - type RDPCS_PHY_DP_TX1_TERM_CTRL;\ - type RDPCS_PHY_DP_TX2_TERM_CTRL;\ - type RDPCS_PHY_DP_TX3_TERM_CTRL;\ - type RDPCS_PHY_DP_REF_CLK_MPLLB_DIV;\ - type RDPCS_PHY_DP_MPLLB_MULTIPLIER;\ - type RDPCS_PHY_DP_MPLLB_SSC_EN;\ - type RDPCS_PHY_DP_MPLLB_DIV5_CLK_EN;\ - type RDPCS_PHY_DP_MPLLB_TX_CLK_DIV;\ - type RDPCS_PHY_DP_MPLLB_WORD_DIV2_EN;\ - type RDPCS_PHY_DP_MPLLB_FRACN_EN;\ - type RDPCS_PHY_DP_MPLLB_PMIX_EN;\ - type RDPCS_PHY_DP_MPLLB_FRACN_QUOT;\ - type RDPCS_PHY_DP_MPLLB_FRACN_DEN;\ - type RDPCS_PHY_DP_MPLLB_FRACN_REM;\ - type RDPCS_PHY_DP_MPLLB_SSC_UP_SPREAD;\ - type RDPCS_PHY_DP_MPLLB_SSC_STEPSIZE;\ - type RDPCS_PHY_DP_MPLLB_SSC_PEAK;\ - type RDPCS_PHY_DP_MPLLB_DIV_CLK_EN;\ - type RDPCS_PHY_DP_MPLLB_DIV_MULTIPLIER;\ - type RDPCS_PHY_TX_VBOOST_LVL;\ - type RDPCS_PHY_HDMIMODE_ENABLE;\ - type RDPCS_PHY_DP_REF_CLK_EN;\ - type RDPCS_PLL_UPDATE_DATA;\ - type RDPCS_SRAM_INIT_DONE;\ - type RDPCS_TX_CR_ADDR;\ - type RDPCS_TX_CR_DATA;\ - type RDPCS_PHY_HDMI_MPLLB_HDMI_DIV;\ - type RDPCS_PHY_DP_MPLLB_STATE;\ - type RDPCS_PHY_DP_TX0_WIDTH;\ - type RDPCS_PHY_DP_TX0_RATE;\ - type RDPCS_PHY_DP_TX1_WIDTH;\ - type RDPCS_PHY_DP_TX1_RATE;\ - type RDPCS_PHY_DP_TX2_WIDTH;\ - type RDPCS_PHY_DP_TX2_RATE;\ - type RDPCS_PHY_DP_TX3_WIDTH;\ - type RDPCS_PHY_DP_TX3_RATE;\ - type DPCS_SYMCLK_CLOCK_ON;\ - type DPCS_SYMCLK_GATE_DIS;\ - type DPCS_SYMCLK_EN;\ - type RDPCS_SYMCLK_DIV2_CLOCK_ON;\ - type RDPCS_SYMCLK_DIV2_GATE_DIS;\ - type RDPCS_SYMCLK_DIV2_EN;\ - type DPCS_TX_DATA_SWAP;\ - type DPCS_TX_DATA_ORDER_INVERT;\ - type DPCS_TX_FIFO_RD_START_DELAY;\ - type RDPCS_TX_FIFO_RD_START_DELAY;\ - type RDPCS_REG_FIFO_ERROR_MASK;\ - type RDPCS_TX_FIFO_ERROR_MASK;\ - type RDPCS_DPALT_DISABLE_TOGGLE_MASK;\ - type RDPCS_DPALT_4LANE_TOGGLE_MASK;\ - type RDPCS_PHY_DPALT_DP4;\ - type RDPCS_PHY_DPALT_DISABLE;\ - type RDPCS_PHY_DPALT_DISABLE_ACK;\ - type RDPCS_PHY_DP_MPLLB_V2I;\ - type RDPCS_PHY_DP_MPLLB_FREQ_VCO;\ - type RDPCS_PHY_DP_MPLLB_CP_INT_GS;\ - type RDPCS_PHY_RX_VREF_CTRL;\ - type RDPCS_PHY_DP_MPLLB_CP_INT;\ - type RDPCS_PHY_DP_MPLLB_CP_PROP;\ - type RDPCS_PHY_RX_REF_LD_VAL;\ - type RDPCS_PHY_RX_VCO_LD_VAL;\ - type DPCSTX_DEBUG_CONFIG; \ - type RDPCSTX_DEBUG_CONFIG; \ - type RDPCS_PHY_DP_TX0_EQ_MAIN;\ - type RDPCS_PHY_DP_TX0_EQ_PRE;\ - type RDPCS_PHY_DP_TX0_EQ_POST;\ - type RDPCS_PHY_DP_TX1_EQ_MAIN;\ - type RDPCS_PHY_DP_TX1_EQ_PRE;\ - type RDPCS_PHY_DP_TX1_EQ_POST;\ - type RDPCS_PHY_DP_TX2_EQ_MAIN;\ - type RDPCS_PHY_DP_MPLLB_CP_PROP_GS;\ - type RDPCS_PHY_DP_TX2_EQ_PRE;\ - type RDPCS_PHY_DP_TX2_EQ_POST;\ - type RDPCS_PHY_DP_TX3_EQ_MAIN;\ - type RDPCS_PHY_DCO_RANGE;\ - type RDPCS_PHY_DCO_FINETUNE;\ - type RDPCS_PHY_DP_TX3_EQ_PRE;\ - type RDPCS_PHY_DP_TX3_EQ_POST;\ - type RDPCS_PHY_SUP_PRE_HP;\ - type RDPCS_PHY_DP_TX0_VREGDRV_BYP;\ - type RDPCS_PHY_DP_TX1_VREGDRV_BYP;\ - type RDPCS_PHY_DP_TX2_VREGDRV_BYP;\ - type RDPCS_PHY_DP_TX3_VREGDRV_BYP;\ - type RDPCS_DMCU_DPALT_DIS_BLOCK_REG;\ - type UNIPHYA_SOFT_RESET;\ - type UNIPHYB_SOFT_RESET;\ - type UNIPHYC_SOFT_RESET;\ - type UNIPHYD_SOFT_RESET;\ - type UNIPHYE_SOFT_RESET;\ - type UNIPHYF_SOFT_RESET - -#define DCN20_LINK_ENCODER_REG_FIELD_LIST(type) \ - type DIG_LANE0EN;\ - type DIG_LANE1EN;\ - type DIG_LANE2EN;\ - type DIG_LANE3EN;\ - type DIG_CLK_EN;\ - type SYMCLKA_CLOCK_ENABLE;\ - type DPHY_FEC_EN;\ - type DPHY_FEC_READY_SHADOW;\ - type DPHY_FEC_ACTIVE_STATUS;\ - DCN20_LINK_ENCODER_DPCS_REG_FIELD_LIST(type);\ - type VCO_LD_VAL_OVRD;\ - type VCO_LD_VAL_OVRD_EN;\ - type REF_LD_VAL_OVRD;\ - type REF_LD_VAL_OVRD_EN;\ - type AUX_RX_START_WINDOW; \ - type AUX_RX_HALF_SYM_DETECT_LEN; \ - type AUX_RX_TRANSITION_FILTER_EN; \ - type AUX_RX_ALLOW_BELOW_THRESHOLD_PHASE_DETECT; \ - type AUX_RX_ALLOW_BELOW_THRESHOLD_START; \ - type AUX_RX_ALLOW_BELOW_THRESHOLD_STOP; \ - type AUX_RX_PHASE_DETECT_LEN; \ - type AUX_RX_DETECTION_THRESHOLD; \ - type AUX_TX_PRECHARGE_LEN; \ - type AUX_TX_PRECHARGE_SYMBOLS; \ - type AUX_MODE_DET_CHECK_DELAY;\ - type DPCS_DBG_CBUS_DIS;\ - type AUX_RX_PRECHARGE_SKIP;\ - type AUX_RX_TIMEOUT_LEN;\ - type AUX_RX_TIMEOUT_LEN_MUL - -#define DCN30_LINK_ENCODER_REG_FIELD_LIST(type) \ - type TMDS_SYNC_DCBAL_EN;\ - type PHY_HPO_DIG_SRC_SEL;\ - type PHY_HPO_ENC_SRC_SEL;\ - type DPCS_TX_HDMI_FRL_MODE;\ - type DPCS_TX_DATA_SWAP_10_BIT;\ - type DPCS_TX_DATA_ORDER_INVERT_18_BIT;\ - type RDPCS_TX_CLK_EN - -#define DCN31_LINK_ENCODER_REG_FIELD_LIST(type) \ - type ENC_TYPE_SEL;\ - type HPO_DP_ENC_SEL;\ - type HPO_HDMI_ENC_SEL - -#define DCN35_LINK_ENCODER_REG_FIELD_LIST(type) \ - type DIG_BE_ENABLE;\ - type DIG_RB_SWITCH_EN;\ - type DIG_BE_MODE;\ - type DIG_BE_CLK_EN;\ - type DIG_BE_SOFT_RESET;\ - type HDCP_SOFT_RESET;\ - type DIG_BE_SYMCLK_G_CLOCK_ON;\ - type DIG_BE_SYMCLK_G_HDCP_CLOCK_ON;\ - type DIG_BE_SYMCLK_G_TMDS_CLOCK_ON;\ - type DISPCLK_R_GATE_DIS;\ - type DISPCLK_G_GATE_DIS;\ - type REFCLK_R_GATE_DIS;\ - type REFCLK_G_GATE_DIS;\ - type SOCCLK_G_GATE_DIS;\ - type SYMCLK_FE_R_GATE_DIS;\ - type SYMCLK_FE_G_GATE_DIS;\ - type SYMCLK_R_GATE_DIS;\ - type SYMCLK_G_GATE_DIS;\ - type DIO_FGCG_REP_DIS;\ - type DISPCLK_G_HDCP_GATE_DIS;\ - type SYMCLKA_G_HDCP_GATE_DIS;\ - type SYMCLKB_G_HDCP_GATE_DIS;\ - type SYMCLKC_G_HDCP_GATE_DIS;\ - type SYMCLKD_G_HDCP_GATE_DIS;\ - type SYMCLKE_G_HDCP_GATE_DIS;\ - type SYMCLKF_G_HDCP_GATE_DIS;\ - type SYMCLKG_G_HDCP_GATE_DIS - -struct dcn10_link_enc_shift { - DCN_LINK_ENCODER_REG_FIELD_LIST(uint8_t); - DCN20_LINK_ENCODER_REG_FIELD_LIST(uint8_t); - DCN30_LINK_ENCODER_REG_FIELD_LIST(uint8_t); - DCN31_LINK_ENCODER_REG_FIELD_LIST(uint8_t); - DCN35_LINK_ENCODER_REG_FIELD_LIST(uint8_t); -}; - -struct dcn10_link_enc_mask { - DCN_LINK_ENCODER_REG_FIELD_LIST(uint32_t); - DCN20_LINK_ENCODER_REG_FIELD_LIST(uint32_t); - DCN30_LINK_ENCODER_REG_FIELD_LIST(uint32_t); - DCN31_LINK_ENCODER_REG_FIELD_LIST(uint32_t); - DCN35_LINK_ENCODER_REG_FIELD_LIST(uint32_t); -}; - -struct dcn10_link_encoder { - struct link_encoder base; - const struct dcn10_link_enc_registers *link_regs; - const struct dcn10_link_enc_aux_registers *aux_regs; - const struct dcn10_link_enc_hpd_registers *hpd_regs; - const struct dcn10_link_enc_shift *link_shift; - const struct dcn10_link_enc_mask *link_mask; -}; - - -void dcn10_link_encoder_construct( - struct dcn10_link_encoder *enc10, - const struct encoder_init_data *init_data, - const struct encoder_feature_support *enc_features, - const struct dcn10_link_enc_registers *link_regs, - const struct dcn10_link_enc_aux_registers *aux_regs, - const struct dcn10_link_enc_hpd_registers *hpd_regs, - const struct dcn10_link_enc_shift *link_shift, - const struct dcn10_link_enc_mask *link_mask); - -bool dcn10_link_encoder_validate_dvi_output( - const struct dcn10_link_encoder *enc10, - enum signal_type connector_signal, - enum signal_type signal, - const struct dc_crtc_timing *crtc_timing); - -bool dcn10_link_encoder_validate_rgb_output( - const struct dcn10_link_encoder *enc10, - const struct dc_crtc_timing *crtc_timing); - -bool dcn10_link_encoder_validate_dp_output( - const struct dcn10_link_encoder *enc10, - const struct dc_crtc_timing *crtc_timing); - -bool dcn10_link_encoder_validate_wireless_output( - const struct dcn10_link_encoder *enc10, - const struct dc_crtc_timing *crtc_timing); - -bool dcn10_link_encoder_validate_output_with_stream( - struct link_encoder *enc, - const struct dc_stream_state *stream); - -/****************** HW programming ************************/ - -/* initialize HW */ /* why do we initialze aux in here? */ -void dcn10_link_encoder_hw_init(struct link_encoder *enc); - -void dcn10_link_encoder_destroy(struct link_encoder **enc); - -/* program DIG_MODE in DIG_BE */ -/* TODO can this be combined with enable_output? */ -void dcn10_link_encoder_setup( - struct link_encoder *enc, - enum signal_type signal); - -void enc1_configure_encoder( - struct dcn10_link_encoder *enc10, - const struct dc_link_settings *link_settings); - -/* enables TMDS PHY output */ -/* TODO: still need depth or just pass in adjusted pixel clock? */ -void dcn10_link_encoder_enable_tmds_output( - struct link_encoder *enc, - enum clock_source_id clock_source, - enum dc_color_depth color_depth, - enum signal_type signal, - uint32_t pixel_clock); - -void dcn10_link_encoder_enable_tmds_output_with_clk_pattern_wa( - struct link_encoder *enc, - enum clock_source_id clock_source, - enum dc_color_depth color_depth, - enum signal_type signal, - uint32_t pixel_clock); - -/* enables DP PHY output */ -void dcn10_link_encoder_enable_dp_output( - struct link_encoder *enc, - const struct dc_link_settings *link_settings, - enum clock_source_id clock_source); - -/* enables DP PHY output in MST mode */ -void dcn10_link_encoder_enable_dp_mst_output( - struct link_encoder *enc, - const struct dc_link_settings *link_settings, - enum clock_source_id clock_source); - -/* disable PHY output */ -void dcn10_link_encoder_disable_output( - struct link_encoder *enc, - enum signal_type signal); - -/* set DP lane settings */ -void dcn10_link_encoder_dp_set_lane_settings( - struct link_encoder *enc, - const struct dc_link_settings *link_settings, - const struct dc_lane_settings lane_settings[LANE_COUNT_DP_MAX]); - -void dcn10_link_encoder_dp_set_phy_pattern( - struct link_encoder *enc, - const struct encoder_set_dp_phy_pattern_param *param); - -/* programs DP MST VC payload allocation */ -void dcn10_link_encoder_update_mst_stream_allocation_table( - struct link_encoder *enc, - const struct link_mst_stream_allocation_table *table); - -void dcn10_link_encoder_connect_dig_be_to_fe( - struct link_encoder *enc, - enum engine_id engine, - bool connect); - -void dcn10_link_encoder_set_dp_phy_pattern_training_pattern( - struct link_encoder *enc, - uint32_t index); - -void dcn10_link_encoder_enable_hpd(struct link_encoder *enc); - -void dcn10_link_encoder_disable_hpd(struct link_encoder *enc); - -void dcn10_psr_program_dp_dphy_fast_training(struct link_encoder *enc, - bool exit_link_training_required); - -void dcn10_psr_program_secondary_packet(struct link_encoder *enc, - unsigned int sdp_transmit_line_num_deadline); - -bool dcn10_is_dig_enabled(struct link_encoder *enc); - -unsigned int dcn10_get_dig_frontend(struct link_encoder *enc); - -void dcn10_aux_initialize(struct dcn10_link_encoder *enc10); - -enum signal_type dcn10_get_dig_mode( - struct link_encoder *enc); - -void dcn10_link_encoder_get_max_link_cap(struct link_encoder *enc, - struct dc_link_settings *link_settings); -#endif /* __DC_LINK_ENCODER__DCN10_H__ */ 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 deleted file mode 100644 index f496e952ceec..000000000000 --- a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_stream_encoder.c +++ /dev/null @@ -1,1628 +0,0 @@ -/* - * Copyright 2012-15 Advanced Micro Devices, Inc. - * - * Permission is hereby granted, free of charge, to any person obtaining a - * copy of this software and associated documentation files (the "Software"), - * to deal in the Software without restriction, including without limitation - * the rights to use, copy, modify, merge, publish, distribute, sublicense, - * and/or sell copies of the Software, and to permit persons to whom the - * Software is furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL - * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR - * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, - * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR - * OTHER DEALINGS IN THE SOFTWARE. - * - * Authors: AMD - * - */ - -#include "dm_services.h" -#include "dc_bios_types.h" -#include "dcn10_stream_encoder.h" -#include "reg_helper.h" -#include "hw_shared.h" -#include "link.h" -#include "dpcd_defs.h" -#include "dcn30/dcn30_afmt.h" - -#define DC_LOGGER \ - enc1->base.ctx->logger - -#define REG(reg)\ - (enc1->regs->reg) - -#undef FN -#define FN(reg_name, field_name) \ - enc1->se_shift->field_name, enc1->se_mask->field_name - -#define VBI_LINE_0 0 -#define DP_BLANK_MAX_RETRY 20 -#define HDMI_CLOCK_CHANNEL_RATE_MORE_340M 340000 - - -enum { - DP_MST_UPDATE_MAX_RETRY = 50 -}; - -#define CTX \ - enc1->base.ctx - -void enc1_update_generic_info_packet( - struct dcn10_stream_encoder *enc1, - uint32_t packet_index, - const struct dc_info_packet *info_packet) -{ - /* TODOFPGA Figure out a proper number for max_retries polling for lock - * use 50 for now. - */ - uint32_t max_retries = 50; - - /*we need turn on clock before programming AFMT block*/ - REG_UPDATE(AFMT_CNTL, AFMT_AUDIO_CLOCK_EN, 1); - - if (packet_index >= 8) - ASSERT(0); - - /* poll dig_update_lock is not locked -> asic internal signal - * assume otg master lock will unlock it - */ -/* REG_WAIT(AFMT_VBI_PACKET_CONTROL, AFMT_GENERIC_LOCK_STATUS, - 0, 10, max_retries);*/ - - /* check if HW reading GSP memory */ - REG_WAIT(AFMT_VBI_PACKET_CONTROL, AFMT_GENERIC_CONFLICT, - 0, 10, max_retries); - - /* HW does is not reading GSP memory not reading too long -> - * something wrong. clear GPS memory access and notify? - * hw SW is writing to GSP memory - */ - REG_UPDATE(AFMT_VBI_PACKET_CONTROL, AFMT_GENERIC_CONFLICT_CLR, 1); - - /* choose which generic packet to use */ - REG_UPDATE(AFMT_VBI_PACKET_CONTROL, - AFMT_GENERIC_INDEX, packet_index); - - /* write generic packet header - * (4th byte is for GENERIC0 only) - */ - REG_SET_4(AFMT_GENERIC_HDR, 0, - AFMT_GENERIC_HB0, info_packet->hb0, - AFMT_GENERIC_HB1, info_packet->hb1, - AFMT_GENERIC_HB2, info_packet->hb2, - AFMT_GENERIC_HB3, info_packet->hb3); - - /* write generic packet contents - * (we never use last 4 bytes) - * there are 8 (0-7) mmDIG0_AFMT_GENERIC0_x registers - */ - { - const uint32_t *content = - (const uint32_t *) &info_packet->sb[0]; - - REG_WRITE(AFMT_GENERIC_0, *content++); - REG_WRITE(AFMT_GENERIC_1, *content++); - REG_WRITE(AFMT_GENERIC_2, *content++); - REG_WRITE(AFMT_GENERIC_3, *content++); - REG_WRITE(AFMT_GENERIC_4, *content++); - REG_WRITE(AFMT_GENERIC_5, *content++); - REG_WRITE(AFMT_GENERIC_6, *content++); - REG_WRITE(AFMT_GENERIC_7, *content); - } - - switch (packet_index) { - case 0: - REG_UPDATE(AFMT_VBI_PACKET_CONTROL1, - AFMT_GENERIC0_IMMEDIATE_UPDATE, 1); - break; - case 1: - REG_UPDATE(AFMT_VBI_PACKET_CONTROL1, - AFMT_GENERIC1_IMMEDIATE_UPDATE, 1); - break; - case 2: - REG_UPDATE(AFMT_VBI_PACKET_CONTROL1, - AFMT_GENERIC2_IMMEDIATE_UPDATE, 1); - break; - case 3: - REG_UPDATE(AFMT_VBI_PACKET_CONTROL1, - AFMT_GENERIC3_IMMEDIATE_UPDATE, 1); - break; - case 4: - REG_UPDATE(AFMT_VBI_PACKET_CONTROL1, - AFMT_GENERIC4_IMMEDIATE_UPDATE, 1); - break; - case 5: - REG_UPDATE(AFMT_VBI_PACKET_CONTROL1, - AFMT_GENERIC5_IMMEDIATE_UPDATE, 1); - break; - case 6: - REG_UPDATE(AFMT_VBI_PACKET_CONTROL1, - AFMT_GENERIC6_IMMEDIATE_UPDATE, 1); - break; - case 7: - REG_UPDATE(AFMT_VBI_PACKET_CONTROL1, - AFMT_GENERIC7_IMMEDIATE_UPDATE, 1); - break; - default: - break; - } -} - -static void enc1_update_hdmi_info_packet( - struct dcn10_stream_encoder *enc1, - uint32_t packet_index, - const struct dc_info_packet *info_packet) -{ - uint32_t cont, send, line; - - if (info_packet->valid) { - enc1_update_generic_info_packet( - enc1, - packet_index, - info_packet); - - /* enable transmission of packet(s) - - * packet transmission begins on the next frame - */ - cont = 1; - /* send packet(s) every frame */ - send = 1; - /* select line number to send packets on */ - line = 2; - } else { - cont = 0; - send = 0; - line = 0; - } - - /* choose which generic packet control to use */ - switch (packet_index) { - case 0: - REG_UPDATE_3(HDMI_GENERIC_PACKET_CONTROL0, - HDMI_GENERIC0_CONT, cont, - HDMI_GENERIC0_SEND, send, - HDMI_GENERIC0_LINE, line); - break; - case 1: - REG_UPDATE_3(HDMI_GENERIC_PACKET_CONTROL0, - HDMI_GENERIC1_CONT, cont, - HDMI_GENERIC1_SEND, send, - HDMI_GENERIC1_LINE, line); - break; - case 2: - REG_UPDATE_3(HDMI_GENERIC_PACKET_CONTROL1, - HDMI_GENERIC0_CONT, cont, - HDMI_GENERIC0_SEND, send, - HDMI_GENERIC0_LINE, line); - break; - case 3: - REG_UPDATE_3(HDMI_GENERIC_PACKET_CONTROL1, - HDMI_GENERIC1_CONT, cont, - HDMI_GENERIC1_SEND, send, - HDMI_GENERIC1_LINE, line); - break; - case 4: - REG_UPDATE_3(HDMI_GENERIC_PACKET_CONTROL2, - HDMI_GENERIC0_CONT, cont, - HDMI_GENERIC0_SEND, send, - HDMI_GENERIC0_LINE, line); - break; - case 5: - REG_UPDATE_3(HDMI_GENERIC_PACKET_CONTROL2, - HDMI_GENERIC1_CONT, cont, - HDMI_GENERIC1_SEND, send, - HDMI_GENERIC1_LINE, line); - break; - case 6: - REG_UPDATE_3(HDMI_GENERIC_PACKET_CONTROL3, - HDMI_GENERIC0_CONT, cont, - HDMI_GENERIC0_SEND, send, - HDMI_GENERIC0_LINE, line); - break; - case 7: - REG_UPDATE_3(HDMI_GENERIC_PACKET_CONTROL3, - HDMI_GENERIC1_CONT, cont, - HDMI_GENERIC1_SEND, send, - HDMI_GENERIC1_LINE, line); - break; - default: - /* invalid HW packet index */ - DC_LOG_WARNING( - "Invalid HW packet index: %s()\n", - __func__); - return; - } -} - -/* setup stream encoder in dp mode */ -void enc1_stream_encoder_dp_set_stream_attribute( - struct stream_encoder *enc, - struct dc_crtc_timing *crtc_timing, - enum dc_color_space output_color_space, - bool use_vsc_sdp_for_colorimetry, - uint32_t enable_sdp_splitting) -{ - uint32_t h_active_start; - uint32_t v_active_start; - uint32_t misc0 = 0; - uint32_t misc1 = 0; - uint32_t h_blank; - uint32_t h_back_porch; - uint8_t synchronous_clock = 0; /* asynchronous mode */ - uint8_t colorimetry_bpc; - uint8_t dp_pixel_encoding = 0; - uint8_t dp_component_depth = 0; - - struct dcn10_stream_encoder *enc1 = DCN10STRENC_FROM_STRENC(enc); - struct dc_crtc_timing hw_crtc_timing = *crtc_timing; - - if (hw_crtc_timing.flags.INTERLACE) { - /*the input timing is in VESA spec format with Interlace flag =1*/ - hw_crtc_timing.v_total /= 2; - hw_crtc_timing.v_border_top /= 2; - hw_crtc_timing.v_addressable /= 2; - hw_crtc_timing.v_border_bottom /= 2; - hw_crtc_timing.v_front_porch /= 2; - hw_crtc_timing.v_sync_width /= 2; - } - - - /* set pixel encoding */ - switch (hw_crtc_timing.pixel_encoding) { - case PIXEL_ENCODING_YCBCR422: - dp_pixel_encoding = DP_PIXEL_ENCODING_TYPE_YCBCR422; - break; - case PIXEL_ENCODING_YCBCR444: - dp_pixel_encoding = DP_PIXEL_ENCODING_TYPE_YCBCR444; - - if (hw_crtc_timing.flags.Y_ONLY) - if (hw_crtc_timing.display_color_depth != COLOR_DEPTH_666) - /* HW testing only, no use case yet. - * Color depth of Y-only could be - * 8, 10, 12, 16 bits - */ - 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 - * DP_PIXEL_ENCODING is programmed to 0x4 - */ - break; - case PIXEL_ENCODING_YCBCR420: - dp_pixel_encoding = DP_PIXEL_ENCODING_TYPE_YCBCR420; - break; - default: - 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 (use_vsc_sdp_for_colorimetry) - misc1 = misc1 | 0x40; - else - misc1 = misc1 & ~0x40; - - /* set color depth */ - switch (hw_crtc_timing.display_color_depth) { - case COLOR_DEPTH_666: - dp_component_depth = DP_COMPONENT_PIXEL_DEPTH_6BPC; - break; - case COLOR_DEPTH_888: - dp_component_depth = DP_COMPONENT_PIXEL_DEPTH_8BPC; - break; - case COLOR_DEPTH_101010: - dp_component_depth = DP_COMPONENT_PIXEL_DEPTH_10BPC; - break; - case COLOR_DEPTH_121212: - dp_component_depth = DP_COMPONENT_PIXEL_DEPTH_12BPC; - break; - case COLOR_DEPTH_161616: - dp_component_depth = DP_COMPONENT_PIXEL_DEPTH_16BPC; - break; - default: - 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 (hw_crtc_timing.display_color_depth) { - case COLOR_DEPTH_666: - colorimetry_bpc = 0; - break; - case COLOR_DEPTH_888: - colorimetry_bpc = 1; - break; - case COLOR_DEPTH_101010: - colorimetry_bpc = 2; - break; - case COLOR_DEPTH_121212: - colorimetry_bpc = 3; - break; - default: - colorimetry_bpc = 0; - break; - } - - misc0 = misc0 | synchronous_clock; - misc0 = colorimetry_bpc << 5; - - switch (output_color_space) { - case COLOR_SPACE_SRGB: - misc1 = misc1 & ~0x80; /* bit7 = 0*/ - break; - case COLOR_SPACE_SRGB_LIMITED: - misc0 = misc0 | 0x8; /* bit3=1 */ - misc1 = misc1 & ~0x80; /* bit7 = 0*/ - break; - case COLOR_SPACE_YCBCR601: - case COLOR_SPACE_YCBCR601_LIMITED: - misc0 = misc0 | 0x8; /* bit3=1, bit4=0 */ - misc1 = misc1 & ~0x80; /* bit7 = 0*/ - if (hw_crtc_timing.pixel_encoding == PIXEL_ENCODING_YCBCR422) - misc0 = misc0 | 0x2; /* bit2=0, bit1=1 */ - else if (hw_crtc_timing.pixel_encoding == PIXEL_ENCODING_YCBCR444) - misc0 = misc0 | 0x4; /* bit2=1, bit1=0 */ - break; - case COLOR_SPACE_YCBCR709: - case COLOR_SPACE_YCBCR709_LIMITED: - misc0 = misc0 | 0x18; /* bit3=1, bit4=1 */ - misc1 = misc1 & ~0x80; /* bit7 = 0*/ - if (hw_crtc_timing.pixel_encoding == PIXEL_ENCODING_YCBCR422) - misc0 = misc0 | 0x2; /* bit2=0, bit1=1 */ - else if (hw_crtc_timing.pixel_encoding == PIXEL_ENCODING_YCBCR444) - misc0 = misc0 | 0x4; /* bit2=1, bit1=0 */ - break; - case COLOR_SPACE_2020_RGB_LIMITEDRANGE: - case COLOR_SPACE_2020_RGB_FULLRANGE: - case COLOR_SPACE_2020_YCBCR: - case COLOR_SPACE_XR_RGB: - case COLOR_SPACE_MSREF_SCRGB: - case COLOR_SPACE_ADOBERGB: - case COLOR_SPACE_DCIP3: - case COLOR_SPACE_XV_YCC_709: - case COLOR_SPACE_XV_YCC_601: - case COLOR_SPACE_DISPLAYNATIVE: - case COLOR_SPACE_DOLBYVISION: - case COLOR_SPACE_APPCTRL: - case COLOR_SPACE_CUSTOMPOINTS: - case COLOR_SPACE_UNKNOWN: - case COLOR_SPACE_YCBCR709_BLACK: - /* do nothing */ - break; - } - - REG_SET(DP_MSA_COLORIMETRY, 0, DP_MSA_MISC0, misc0); - REG_WRITE(DP_MSA_MISC, misc1); /* MSA_MISC1 */ - - /* dcn new register - * dc_crtc_timing is vesa dmt struct. data from edid - */ - REG_SET_2(DP_MSA_TIMING_PARAM1, 0, - DP_MSA_HTOTAL, hw_crtc_timing.h_total, - DP_MSA_VTOTAL, hw_crtc_timing.v_total); - - /* calculate from vesa timing parameters - * h_active_start related to leading edge of sync - */ - - h_blank = hw_crtc_timing.h_total - hw_crtc_timing.h_border_left - - hw_crtc_timing.h_addressable - hw_crtc_timing.h_border_right; - - h_back_porch = h_blank - hw_crtc_timing.h_front_porch - - hw_crtc_timing.h_sync_width; - - /* start at beginning of left border */ - h_active_start = hw_crtc_timing.h_sync_width + h_back_porch; - - - v_active_start = hw_crtc_timing.v_total - hw_crtc_timing.v_border_top - - hw_crtc_timing.v_addressable - hw_crtc_timing.v_border_bottom - - hw_crtc_timing.v_front_porch; - - - /* start at beginning of left border */ - REG_SET_2(DP_MSA_TIMING_PARAM2, 0, - DP_MSA_HSTART, h_active_start, - DP_MSA_VSTART, v_active_start); - - REG_SET_4(DP_MSA_TIMING_PARAM3, 0, - DP_MSA_HSYNCWIDTH, - hw_crtc_timing.h_sync_width, - DP_MSA_HSYNCPOLARITY, - !hw_crtc_timing.flags.HSYNC_POSITIVE_POLARITY, - DP_MSA_VSYNCWIDTH, - hw_crtc_timing.v_sync_width, - DP_MSA_VSYNCPOLARITY, - !hw_crtc_timing.flags.VSYNC_POSITIVE_POLARITY); - - /* HWDITH include border or overscan */ - REG_SET_2(DP_MSA_TIMING_PARAM4, 0, - DP_MSA_HWIDTH, hw_crtc_timing.h_border_left + - hw_crtc_timing.h_addressable + hw_crtc_timing.h_border_right, - DP_MSA_VHEIGHT, hw_crtc_timing.v_border_top + - hw_crtc_timing.v_addressable + hw_crtc_timing.v_border_bottom); -} - -void enc1_stream_encoder_set_stream_attribute_helper( - struct dcn10_stream_encoder *enc1, - struct dc_crtc_timing *crtc_timing) -{ - switch (crtc_timing->pixel_encoding) { - case PIXEL_ENCODING_YCBCR422: - REG_UPDATE(DIG_FE_CNTL, TMDS_PIXEL_ENCODING, 1); - break; - default: - REG_UPDATE(DIG_FE_CNTL, TMDS_PIXEL_ENCODING, 0); - break; - } - REG_UPDATE(DIG_FE_CNTL, TMDS_COLOR_FORMAT, 0); -} - -/* setup stream encoder in hdmi mode */ -void enc1_stream_encoder_hdmi_set_stream_attribute( - struct stream_encoder *enc, - struct dc_crtc_timing *crtc_timing, - int actual_pix_clk_khz, - bool enable_audio) -{ - struct dcn10_stream_encoder *enc1 = DCN10STRENC_FROM_STRENC(enc); - struct bp_encoder_control cntl = {0}; - - cntl.action = ENCODER_CONTROL_SETUP; - cntl.engine_id = enc1->base.id; - cntl.signal = SIGNAL_TYPE_HDMI_TYPE_A; - cntl.enable_dp_audio = enable_audio; - cntl.pixel_clock = actual_pix_clk_khz; - cntl.lanes_number = LANE_COUNT_FOUR; - - if (enc1->base.bp->funcs->encoder_control( - enc1->base.bp, &cntl) != BP_RESULT_OK) - return; - - enc1_stream_encoder_set_stream_attribute_helper(enc1, crtc_timing); - - /* setup HDMI engine */ - REG_UPDATE_6(HDMI_CONTROL, - HDMI_PACKET_GEN_VERSION, 1, - HDMI_KEEPOUT_MODE, 1, - HDMI_DEEP_COLOR_ENABLE, 0, - HDMI_DATA_SCRAMBLE_EN, 0, - HDMI_NO_EXTRA_NULL_PACKET_FILLED, 1, - HDMI_CLOCK_CHANNEL_RATE, 0); - - - switch (crtc_timing->display_color_depth) { - case COLOR_DEPTH_888: - REG_UPDATE(HDMI_CONTROL, HDMI_DEEP_COLOR_DEPTH, 0); - DC_LOG_DEBUG("HDMI source set to 24BPP deep color depth\n"); - break; - case COLOR_DEPTH_101010: - if (crtc_timing->pixel_encoding == PIXEL_ENCODING_YCBCR422) { - REG_UPDATE_2(HDMI_CONTROL, - HDMI_DEEP_COLOR_DEPTH, 1, - HDMI_DEEP_COLOR_ENABLE, 0); - DC_LOG_DEBUG("HDMI source 30BPP deep color depth" \ - "disabled for YCBCR422 pixel encoding\n"); - } else { - REG_UPDATE_2(HDMI_CONTROL, - HDMI_DEEP_COLOR_DEPTH, 1, - HDMI_DEEP_COLOR_ENABLE, 1); - DC_LOG_DEBUG("HDMI source 30BPP deep color depth" \ - "enabled for YCBCR422 non-pixel encoding\n"); - } - break; - case COLOR_DEPTH_121212: - if (crtc_timing->pixel_encoding == PIXEL_ENCODING_YCBCR422) { - REG_UPDATE_2(HDMI_CONTROL, - HDMI_DEEP_COLOR_DEPTH, 2, - HDMI_DEEP_COLOR_ENABLE, 0); - DC_LOG_DEBUG("HDMI source 36BPP deep color depth" \ - "disabled for YCBCR422 pixel encoding\n"); - } else { - REG_UPDATE_2(HDMI_CONTROL, - HDMI_DEEP_COLOR_DEPTH, 2, - HDMI_DEEP_COLOR_ENABLE, 1); - DC_LOG_DEBUG("HDMI source 36BPP deep color depth" \ - "enabled for non-pixel YCBCR422 encoding\n"); - } - break; - case COLOR_DEPTH_161616: - REG_UPDATE_2(HDMI_CONTROL, - HDMI_DEEP_COLOR_DEPTH, 3, - HDMI_DEEP_COLOR_ENABLE, 1); - DC_LOG_DEBUG("HDMI source deep color depth enabled in" \ - "reserved mode\n"); - break; - default: - break; - } - - if (actual_pix_clk_khz >= HDMI_CLOCK_CHANNEL_RATE_MORE_340M) { - /* enable HDMI data scrambler - * HDMI_CLOCK_CHANNEL_RATE_MORE_340M - * Clock channel frequency is 1/4 of character rate. - */ - REG_UPDATE_2(HDMI_CONTROL, - HDMI_DATA_SCRAMBLE_EN, 1, - HDMI_CLOCK_CHANNEL_RATE, 1); - } else if (crtc_timing->flags.LTE_340MCSC_SCRAMBLE) { - - /* TODO: New feature for DCE11, still need to implement */ - - /* enable HDMI data scrambler - * HDMI_CLOCK_CHANNEL_FREQ_EQUAL_TO_CHAR_RATE - * Clock channel frequency is the same - * as character rate - */ - REG_UPDATE_2(HDMI_CONTROL, - HDMI_DATA_SCRAMBLE_EN, 1, - HDMI_CLOCK_CHANNEL_RATE, 0); - } - - - REG_UPDATE_3(HDMI_VBI_PACKET_CONTROL, - HDMI_GC_CONT, 1, - HDMI_GC_SEND, 1, - HDMI_NULL_SEND, 1); - - REG_UPDATE(HDMI_VBI_PACKET_CONTROL, HDMI_ACP_SEND, 0); - - /* following belongs to audio */ - REG_UPDATE(HDMI_INFOFRAME_CONTROL0, HDMI_AUDIO_INFO_SEND, 1); - - REG_UPDATE(AFMT_INFOFRAME_CONTROL0, AFMT_AUDIO_INFO_UPDATE, 1); - - REG_UPDATE(HDMI_INFOFRAME_CONTROL1, HDMI_AUDIO_INFO_LINE, - VBI_LINE_0 + 2); - - REG_UPDATE(HDMI_GC, HDMI_GC_AVMUTE, 0); -} - -/* setup stream encoder in dvi mode */ -void enc1_stream_encoder_dvi_set_stream_attribute( - struct stream_encoder *enc, - struct dc_crtc_timing *crtc_timing, - bool is_dual_link) -{ - struct dcn10_stream_encoder *enc1 = DCN10STRENC_FROM_STRENC(enc); - struct bp_encoder_control cntl = {0}; - - cntl.action = ENCODER_CONTROL_SETUP; - cntl.engine_id = enc1->base.id; - cntl.signal = is_dual_link ? - SIGNAL_TYPE_DVI_DUAL_LINK : SIGNAL_TYPE_DVI_SINGLE_LINK; - cntl.enable_dp_audio = false; - cntl.pixel_clock = crtc_timing->pix_clk_100hz / 10; - cntl.lanes_number = (is_dual_link) ? LANE_COUNT_EIGHT : LANE_COUNT_FOUR; - - if (enc1->base.bp->funcs->encoder_control( - enc1->base.bp, &cntl) != BP_RESULT_OK) - return; - - ASSERT(crtc_timing->pixel_encoding == PIXEL_ENCODING_RGB); - ASSERT(crtc_timing->display_color_depth == COLOR_DEPTH_888); - enc1_stream_encoder_set_stream_attribute_helper(enc1, crtc_timing); -} - -void enc1_stream_encoder_set_throttled_vcp_size( - struct stream_encoder *enc, - struct fixed31_32 avg_time_slots_per_mtp) -{ - struct dcn10_stream_encoder *enc1 = DCN10STRENC_FROM_STRENC(enc); - uint32_t x = dc_fixpt_floor( - avg_time_slots_per_mtp); - uint32_t y = dc_fixpt_ceil( - dc_fixpt_shl( - dc_fixpt_sub_int( - avg_time_slots_per_mtp, - x), - 26)); - - // If y rounds up to integer, carry it over to x. - if (y >> 26) { - x += 1; - y = 0; - } - - REG_SET_2(DP_MSE_RATE_CNTL, 0, - DP_MSE_RATE_X, x, - DP_MSE_RATE_Y, y); - - /* wait for update to be completed on the link */ - /* i.e. DP_MSE_RATE_UPDATE_PENDING field (read only) */ - /* is reset to 0 (not pending) */ - REG_WAIT(DP_MSE_RATE_UPDATE, DP_MSE_RATE_UPDATE_PENDING, - 0, - 10, DP_MST_UPDATE_MAX_RETRY); -} - -static void enc1_stream_encoder_update_hdmi_info_packets( - struct stream_encoder *enc, - const struct encoder_info_frame *info_frame) -{ - struct dcn10_stream_encoder *enc1 = DCN10STRENC_FROM_STRENC(enc); - - /* for bring up, disable dp double TODO */ - REG_UPDATE(HDMI_DB_CONTROL, HDMI_DB_DISABLE, 1); - - /*Always add mandatory packets first followed by optional ones*/ - enc1_update_hdmi_info_packet(enc1, 0, &info_frame->avi); - enc1_update_hdmi_info_packet(enc1, 1, &info_frame->hfvsif); - enc1_update_hdmi_info_packet(enc1, 2, &info_frame->gamut); - enc1_update_hdmi_info_packet(enc1, 3, &info_frame->vendor); - enc1_update_hdmi_info_packet(enc1, 4, &info_frame->spd); - enc1_update_hdmi_info_packet(enc1, 5, &info_frame->hdrsmd); -} - -static void enc1_stream_encoder_stop_hdmi_info_packets( - struct stream_encoder *enc) -{ - struct dcn10_stream_encoder *enc1 = DCN10STRENC_FROM_STRENC(enc); - - /* stop generic packets 0 & 1 on HDMI */ - REG_SET_6(HDMI_GENERIC_PACKET_CONTROL0, 0, - HDMI_GENERIC1_CONT, 0, - HDMI_GENERIC1_LINE, 0, - HDMI_GENERIC1_SEND, 0, - HDMI_GENERIC0_CONT, 0, - HDMI_GENERIC0_LINE, 0, - HDMI_GENERIC0_SEND, 0); - - /* stop generic packets 2 & 3 on HDMI */ - REG_SET_6(HDMI_GENERIC_PACKET_CONTROL1, 0, - HDMI_GENERIC0_CONT, 0, - HDMI_GENERIC0_LINE, 0, - HDMI_GENERIC0_SEND, 0, - HDMI_GENERIC1_CONT, 0, - HDMI_GENERIC1_LINE, 0, - HDMI_GENERIC1_SEND, 0); - - /* stop generic packets 2 & 3 on HDMI */ - REG_SET_6(HDMI_GENERIC_PACKET_CONTROL2, 0, - HDMI_GENERIC0_CONT, 0, - HDMI_GENERIC0_LINE, 0, - HDMI_GENERIC0_SEND, 0, - HDMI_GENERIC1_CONT, 0, - HDMI_GENERIC1_LINE, 0, - HDMI_GENERIC1_SEND, 0); - - REG_SET_6(HDMI_GENERIC_PACKET_CONTROL3, 0, - HDMI_GENERIC0_CONT, 0, - HDMI_GENERIC0_LINE, 0, - HDMI_GENERIC0_SEND, 0, - HDMI_GENERIC1_CONT, 0, - HDMI_GENERIC1_LINE, 0, - HDMI_GENERIC1_SEND, 0); -} - -void enc1_stream_encoder_update_dp_info_packets( - struct stream_encoder *enc, - const struct encoder_info_frame *info_frame) -{ - struct dcn10_stream_encoder *enc1 = DCN10STRENC_FROM_STRENC(enc); - uint32_t value = 0; - - if (info_frame->vsc.valid) - enc1_update_generic_info_packet( - enc1, - 0, /* packetIndex */ - &info_frame->vsc); - - /* VSC SDP at packetIndex 1 is used by PSR in DMCUB FW. - * Note that the enablement of GSP1 is not done below, - * it's done in FW. - */ - if (info_frame->vsc.valid) - enc1_update_generic_info_packet( - enc1, - 1, /* packetIndex */ - &info_frame->vsc); - - if (info_frame->spd.valid) - enc1_update_generic_info_packet( - enc1, - 2, /* packetIndex */ - &info_frame->spd); - - if (info_frame->hdrsmd.valid) - enc1_update_generic_info_packet( - enc1, - 3, /* packetIndex */ - &info_frame->hdrsmd); - - /* packetIndex 4 is used for send immediate sdp message, and please - * use other packetIndex (such as 5,6) for other info packet - */ - - if (info_frame->adaptive_sync.valid) - enc1_update_generic_info_packet( - enc1, - 5, /* packetIndex */ - &info_frame->adaptive_sync); - - /* enable/disable transmission of packet(s). - * If enabled, packet transmission begins on the next frame - */ - REG_UPDATE(DP_SEC_CNTL, DP_SEC_GSP0_ENABLE, info_frame->vsc.valid); - REG_UPDATE(DP_SEC_CNTL, DP_SEC_GSP2_ENABLE, info_frame->spd.valid); - REG_UPDATE(DP_SEC_CNTL, DP_SEC_GSP3_ENABLE, info_frame->hdrsmd.valid); - REG_UPDATE(DP_SEC_CNTL, DP_SEC_GSP5_ENABLE, info_frame->adaptive_sync.valid); - - /* This bit is the master enable bit. - * When enabling secondary stream engine, - * this master bit must also be set. - * This register shared with audio info frame. - * Therefore we need to enable master bit - * if at least on of the fields is not 0 - */ - value = REG_READ(DP_SEC_CNTL); - if (value) - REG_UPDATE(DP_SEC_CNTL, DP_SEC_STREAM_ENABLE, 1); -} - -void enc1_stream_encoder_send_immediate_sdp_message( - struct stream_encoder *enc, - const uint8_t *custom_sdp_message, - unsigned int sdp_message_size) -{ - struct dcn10_stream_encoder *enc1 = DCN10STRENC_FROM_STRENC(enc); - uint32_t value = 0; - - /* TODOFPGA Figure out a proper number for max_retries polling for lock - * use 50 for now. - */ - uint32_t max_retries = 50; - - /* check if GSP4 is transmitted */ - REG_WAIT(DP_SEC_CNTL2, DP_SEC_GSP4_SEND_PENDING, - 0, 10, max_retries); - - /* disable GSP4 transmitting */ - REG_UPDATE(DP_SEC_CNTL2, DP_SEC_GSP4_SEND, 0); - - /* transmit GSP4 at the earliest time in a frame */ - REG_UPDATE(DP_SEC_CNTL2, DP_SEC_GSP4_SEND_ANY_LINE, 1); - - /*we need turn on clock before programming AFMT block*/ - REG_UPDATE(AFMT_CNTL, AFMT_AUDIO_CLOCK_EN, 1); - - /* check if HW reading GSP memory */ - REG_WAIT(AFMT_VBI_PACKET_CONTROL, AFMT_GENERIC_CONFLICT, - 0, 10, max_retries); - - /* HW does is not reading GSP memory not reading too long -> - * something wrong. clear GPS memory access and notify? - * hw SW is writing to GSP memory - */ - REG_UPDATE(AFMT_VBI_PACKET_CONTROL, AFMT_GENERIC_CONFLICT_CLR, 1); - - /* use generic packet 4 for immediate sdp message */ - REG_UPDATE(AFMT_VBI_PACKET_CONTROL, - AFMT_GENERIC_INDEX, 4); - - /* write generic packet header - * (4th byte is for GENERIC0 only) - */ - REG_SET_4(AFMT_GENERIC_HDR, 0, - AFMT_GENERIC_HB0, custom_sdp_message[0], - AFMT_GENERIC_HB1, custom_sdp_message[1], - AFMT_GENERIC_HB2, custom_sdp_message[2], - AFMT_GENERIC_HB3, custom_sdp_message[3]); - - /* write generic packet contents - * (we never use last 4 bytes) - * there are 8 (0-7) mmDIG0_AFMT_GENERIC0_x registers - */ - { - const uint32_t *content = - (const uint32_t *) &custom_sdp_message[4]; - - REG_WRITE(AFMT_GENERIC_0, *content++); - REG_WRITE(AFMT_GENERIC_1, *content++); - REG_WRITE(AFMT_GENERIC_2, *content++); - REG_WRITE(AFMT_GENERIC_3, *content++); - REG_WRITE(AFMT_GENERIC_4, *content++); - REG_WRITE(AFMT_GENERIC_5, *content++); - REG_WRITE(AFMT_GENERIC_6, *content++); - REG_WRITE(AFMT_GENERIC_7, *content); - } - - /* check whether GENERIC4 registers double buffer update in immediate mode - * is pending - */ - REG_WAIT(AFMT_VBI_PACKET_CONTROL1, AFMT_GENERIC4_IMMEDIATE_UPDATE_PENDING, - 0, 10, max_retries); - - /* atomically update double-buffered GENERIC4 registers in immediate mode - * (update immediately) - */ - REG_UPDATE(AFMT_VBI_PACKET_CONTROL1, - AFMT_GENERIC4_IMMEDIATE_UPDATE, 1); - - /* enable GSP4 transmitting */ - REG_UPDATE(DP_SEC_CNTL2, DP_SEC_GSP4_SEND, 1); - - /* This bit is the master enable bit. - * When enabling secondary stream engine, - * this master bit must also be set. - * This register shared with audio info frame. - * Therefore we need to enable master bit - * if at least on of the fields is not 0 - */ - value = REG_READ(DP_SEC_CNTL); - if (value) - REG_UPDATE(DP_SEC_CNTL, DP_SEC_STREAM_ENABLE, 1); -} - -void enc1_stream_encoder_stop_dp_info_packets( - struct stream_encoder *enc) -{ - /* stop generic packets on DP */ - struct dcn10_stream_encoder *enc1 = DCN10STRENC_FROM_STRENC(enc); - uint32_t value = 0; - - REG_SET_10(DP_SEC_CNTL, 0, - DP_SEC_GSP0_ENABLE, 0, - DP_SEC_GSP1_ENABLE, 0, - DP_SEC_GSP2_ENABLE, 0, - DP_SEC_GSP3_ENABLE, 0, - DP_SEC_GSP4_ENABLE, 0, - DP_SEC_GSP5_ENABLE, 0, - DP_SEC_GSP6_ENABLE, 0, - DP_SEC_GSP7_ENABLE, 0, - DP_SEC_MPG_ENABLE, 0, - DP_SEC_STREAM_ENABLE, 0); - - /* this register shared with audio info frame. - * therefore we need to keep master enabled - * if at least one of the fields is not 0 */ - value = REG_READ(DP_SEC_CNTL); - if (value) - REG_UPDATE(DP_SEC_CNTL, DP_SEC_STREAM_ENABLE, 1); - -} - -void enc1_stream_encoder_dp_blank( - struct dc_link *link, - struct stream_encoder *enc) -{ - struct dcn10_stream_encoder *enc1 = DCN10STRENC_FROM_STRENC(enc); - uint32_t reg1 = 0; - uint32_t max_retries = DP_BLANK_MAX_RETRY * 10; - - /* Note: For CZ, we are changing driver default to disable - * stream deferred to next VBLANK. If results are positive, we - * will make the same change to all DCE versions. There are a - * handful of panels that cannot handle disable stream at - * HBLANK and will result in a white line flash across the - * screen on stream disable. - */ - REG_GET(DP_VID_STREAM_CNTL, DP_VID_STREAM_ENABLE, ®1); - if ((reg1 & 0x1) == 0) - /*stream not enabled*/ - return; - /* Specify the video stream disable point - * (2 = start of the next vertical blank) - */ - REG_UPDATE(DP_VID_STREAM_CNTL, DP_VID_STREAM_DIS_DEFER, 2); - /* Larger delay to wait until VBLANK - use max retry of - * 10us*10200=102ms. This covers 100.0ms of minimum 10 Hz mode + - * a little more because we may not trust delay accuracy. - */ - max_retries = DP_BLANK_MAX_RETRY * 501; - - /* disable DP stream */ - REG_UPDATE(DP_VID_STREAM_CNTL, DP_VID_STREAM_ENABLE, 0); - - link->dc->link_srv->dp_trace_source_sequence(link, DPCD_SOURCE_SEQ_AFTER_DISABLE_DP_VID_STREAM); - - /* the encoder stops sending the video stream - * at the start of the vertical blanking. - * Poll for DP_VID_STREAM_STATUS == 0 - */ - - REG_WAIT(DP_VID_STREAM_CNTL, DP_VID_STREAM_STATUS, - 0, - 10, max_retries); - - /* Tell the DP encoder to ignore timing from CRTC, must be done after - * the polling. If we set DP_STEER_FIFO_RESET before DP stream blank is - * complete, stream status will be stuck in video stream enabled state, - * i.e. DP_VID_STREAM_STATUS stuck at 1. - */ - - REG_UPDATE(DP_STEER_FIFO, DP_STEER_FIFO_RESET, true); - - link->dc->link_srv->dp_trace_source_sequence(link, DPCD_SOURCE_SEQ_AFTER_FIFO_STEER_RESET); -} - -/* output video stream to link encoder */ -void enc1_stream_encoder_dp_unblank( - struct dc_link *link, - struct stream_encoder *enc, - const struct encoder_unblank_param *param) -{ - struct dcn10_stream_encoder *enc1 = DCN10STRENC_FROM_STRENC(enc); - - if (param->link_settings.link_rate != LINK_RATE_UNKNOWN) { - uint32_t n_vid = 0x8000; - uint32_t m_vid; - uint32_t n_multiply = 0; - uint64_t m_vid_l = n_vid; - - /* YCbCr 4:2:0 : Computed VID_M will be 2X the input rate */ - if (param->timing.pixel_encoding == PIXEL_ENCODING_YCBCR420) { - /*this param->pixel_clk_khz is half of 444 rate for 420 already*/ - n_multiply = 1; - } - /* M / N = Fstream / Flink - * m_vid / n_vid = pixel rate / link rate - */ - - m_vid_l *= param->timing.pix_clk_100hz / 10; - m_vid_l = div_u64(m_vid_l, - param->link_settings.link_rate - * LINK_RATE_REF_FREQ_IN_KHZ); - - m_vid = (uint32_t) m_vid_l; - - /* enable auto measurement */ - - REG_UPDATE(DP_VID_TIMING, DP_VID_M_N_GEN_EN, 0); - - /* auto measurement need 1 full 0x8000 symbol cycle to kick in, - * therefore program initial value for Mvid and Nvid - */ - - REG_UPDATE(DP_VID_N, DP_VID_N, n_vid); - - REG_UPDATE(DP_VID_M, DP_VID_M, m_vid); - - REG_UPDATE_2(DP_VID_TIMING, - DP_VID_M_N_GEN_EN, 1, - DP_VID_N_MUL, n_multiply); - } - - /* set DIG_START to 0x1 to resync FIFO */ - - REG_UPDATE(DIG_FE_CNTL, DIG_START, 1); - - /* switch DP encoder to CRTC data */ - - REG_UPDATE(DP_STEER_FIFO, DP_STEER_FIFO_RESET, 0); - - /* wait 100us for DIG/DP logic to prime - * (i.e. a few video lines) - */ - udelay(100); - - /* the hardware would start sending video at the start of the next DP - * frame (i.e. rising edge of the vblank). - * NOTE: We used to program DP_VID_STREAM_DIS_DEFER = 2 here, but this - * register has no effect on enable transition! HW always guarantees - * VID_STREAM enable at start of next frame, and this is not - * programmable - */ - - REG_UPDATE(DP_VID_STREAM_CNTL, DP_VID_STREAM_ENABLE, true); - - link->dc->link_srv->dp_trace_source_sequence(link, - DPCD_SOURCE_SEQ_AFTER_ENABLE_DP_VID_STREAM); -} - -void enc1_stream_encoder_set_avmute( - struct stream_encoder *enc, - bool enable) -{ - struct dcn10_stream_encoder *enc1 = DCN10STRENC_FROM_STRENC(enc); - unsigned int value = enable ? 1 : 0; - - REG_UPDATE(HDMI_GC, HDMI_GC_AVMUTE, value); -} - -void enc1_reset_hdmi_stream_attribute( - struct stream_encoder *enc) -{ - struct dcn10_stream_encoder *enc1 = DCN10STRENC_FROM_STRENC(enc); - - REG_UPDATE_5(HDMI_CONTROL, - HDMI_PACKET_GEN_VERSION, 1, - HDMI_KEEPOUT_MODE, 1, - HDMI_DEEP_COLOR_ENABLE, 0, - HDMI_DATA_SCRAMBLE_EN, 0, - HDMI_CLOCK_CHANNEL_RATE, 0); -} - - -#define DP_SEC_AUD_N__DP_SEC_AUD_N__DEFAULT 0x8000 -#define DP_SEC_TIMESTAMP__DP_SEC_TIMESTAMP_MODE__AUTO_CALC 1 - -#include "include/audio_types.h" - - -/* 25.2MHz/1.001*/ -/* 25.2MHz/1.001*/ -/* 25.2MHz*/ -/* 27MHz */ -/* 27MHz*1.001*/ -/* 27MHz*1.001*/ -/* 54MHz*/ -/* 54MHz*1.001*/ -/* 74.25MHz/1.001*/ -/* 74.25MHz*/ -/* 148.5MHz/1.001*/ -/* 148.5MHz*/ - -static const struct audio_clock_info audio_clock_info_table[16] = { - {2517, 4576, 28125, 7007, 31250, 6864, 28125}, - {2518, 4576, 28125, 7007, 31250, 6864, 28125}, - {2520, 4096, 25200, 6272, 28000, 6144, 25200}, - {2700, 4096, 27000, 6272, 30000, 6144, 27000}, - {2702, 4096, 27027, 6272, 30030, 6144, 27027}, - {2703, 4096, 27027, 6272, 30030, 6144, 27027}, - {5400, 4096, 54000, 6272, 60000, 6144, 54000}, - {5405, 4096, 54054, 6272, 60060, 6144, 54054}, - {7417, 11648, 210937, 17836, 234375, 11648, 140625}, - {7425, 4096, 74250, 6272, 82500, 6144, 74250}, - {14835, 11648, 421875, 8918, 234375, 5824, 140625}, - {14850, 4096, 148500, 6272, 165000, 6144, 148500}, - {29670, 5824, 421875, 4459, 234375, 5824, 281250}, - {29700, 3072, 222750, 4704, 247500, 5120, 247500}, - {59340, 5824, 843750, 8918, 937500, 5824, 562500}, - {59400, 3072, 445500, 9408, 990000, 6144, 594000} -}; - -static const struct audio_clock_info audio_clock_info_table_36bpc[14] = { - {2517, 9152, 84375, 7007, 48875, 9152, 56250}, - {2518, 9152, 84375, 7007, 48875, 9152, 56250}, - {2520, 4096, 37800, 6272, 42000, 6144, 37800}, - {2700, 4096, 40500, 6272, 45000, 6144, 40500}, - {2702, 8192, 81081, 6272, 45045, 8192, 54054}, - {2703, 8192, 81081, 6272, 45045, 8192, 54054}, - {5400, 4096, 81000, 6272, 90000, 6144, 81000}, - {5405, 4096, 81081, 6272, 90090, 6144, 81081}, - {7417, 11648, 316406, 17836, 351562, 11648, 210937}, - {7425, 4096, 111375, 6272, 123750, 6144, 111375}, - {14835, 11648, 632812, 17836, 703125, 11648, 421875}, - {14850, 4096, 222750, 6272, 247500, 6144, 222750}, - {29670, 5824, 632812, 8918, 703125, 5824, 421875}, - {29700, 4096, 445500, 4704, 371250, 5120, 371250} -}; - -static const struct audio_clock_info audio_clock_info_table_48bpc[14] = { - {2517, 4576, 56250, 7007, 62500, 6864, 56250}, - {2518, 4576, 56250, 7007, 62500, 6864, 56250}, - {2520, 4096, 50400, 6272, 56000, 6144, 50400}, - {2700, 4096, 54000, 6272, 60000, 6144, 54000}, - {2702, 4096, 54054, 6267, 60060, 8192, 54054}, - {2703, 4096, 54054, 6272, 60060, 8192, 54054}, - {5400, 4096, 108000, 6272, 120000, 6144, 108000}, - {5405, 4096, 108108, 6272, 120120, 6144, 108108}, - {7417, 11648, 421875, 17836, 468750, 11648, 281250}, - {7425, 4096, 148500, 6272, 165000, 6144, 148500}, - {14835, 11648, 843750, 8918, 468750, 11648, 281250}, - {14850, 4096, 297000, 6272, 330000, 6144, 297000}, - {29670, 5824, 843750, 4459, 468750, 5824, 562500}, - {29700, 3072, 445500, 4704, 495000, 5120, 495000} - - -}; - -static union audio_cea_channels speakers_to_channels( - struct audio_speaker_flags speaker_flags) -{ - union audio_cea_channels cea_channels = {0}; - - /* these are one to one */ - cea_channels.channels.FL = speaker_flags.FL_FR; - cea_channels.channels.FR = speaker_flags.FL_FR; - cea_channels.channels.LFE = speaker_flags.LFE; - cea_channels.channels.FC = speaker_flags.FC; - - /* if Rear Left and Right exist move RC speaker to channel 7 - * otherwise to channel 5 - */ - if (speaker_flags.RL_RR) { - cea_channels.channels.RL_RC = speaker_flags.RL_RR; - cea_channels.channels.RR = speaker_flags.RL_RR; - cea_channels.channels.RC_RLC_FLC = speaker_flags.RC; - } else { - cea_channels.channels.RL_RC = speaker_flags.RC; - } - - /* FRONT Left Right Center and REAR Left Right Center are exclusive */ - if (speaker_flags.FLC_FRC) { - cea_channels.channels.RC_RLC_FLC = speaker_flags.FLC_FRC; - cea_channels.channels.RRC_FRC = speaker_flags.FLC_FRC; - } else { - cea_channels.channels.RC_RLC_FLC = speaker_flags.RLC_RRC; - cea_channels.channels.RRC_FRC = speaker_flags.RLC_RRC; - } - - return cea_channels; -} - -void get_audio_clock_info( - enum dc_color_depth color_depth, - uint32_t crtc_pixel_clock_100Hz, - uint32_t actual_pixel_clock_100Hz, - struct audio_clock_info *audio_clock_info) -{ - const struct audio_clock_info *clock_info; - uint32_t index; - uint32_t crtc_pixel_clock_in_10khz = crtc_pixel_clock_100Hz / 100; - uint32_t audio_array_size; - - switch (color_depth) { - case COLOR_DEPTH_161616: - clock_info = audio_clock_info_table_48bpc; - audio_array_size = ARRAY_SIZE( - audio_clock_info_table_48bpc); - break; - case COLOR_DEPTH_121212: - clock_info = audio_clock_info_table_36bpc; - audio_array_size = ARRAY_SIZE( - audio_clock_info_table_36bpc); - break; - default: - clock_info = audio_clock_info_table; - audio_array_size = ARRAY_SIZE( - audio_clock_info_table); - break; - } - - if (clock_info != NULL) { - /* search for exact pixel clock in table */ - for (index = 0; index < audio_array_size; index++) { - if (clock_info[index].pixel_clock_in_10khz > - crtc_pixel_clock_in_10khz) - break; /* not match */ - else if (clock_info[index].pixel_clock_in_10khz == - crtc_pixel_clock_in_10khz) { - /* match found */ - *audio_clock_info = clock_info[index]; - return; - } - } - } - - /* not found */ - if (actual_pixel_clock_100Hz == 0) - actual_pixel_clock_100Hz = crtc_pixel_clock_100Hz; - - /* See HDMI spec the table entry under - * pixel clock of "Other". */ - audio_clock_info->pixel_clock_in_10khz = - actual_pixel_clock_100Hz / 100; - audio_clock_info->cts_32khz = actual_pixel_clock_100Hz / 10; - audio_clock_info->cts_44khz = actual_pixel_clock_100Hz / 10; - audio_clock_info->cts_48khz = actual_pixel_clock_100Hz / 10; - - audio_clock_info->n_32khz = 4096; - audio_clock_info->n_44khz = 6272; - audio_clock_info->n_48khz = 6144; -} - -static void enc1_se_audio_setup( - struct stream_encoder *enc, - unsigned int az_inst, - struct audio_info *audio_info) -{ - struct dcn10_stream_encoder *enc1 = DCN10STRENC_FROM_STRENC(enc); - - uint32_t channels = 0; - - ASSERT(audio_info); - if (audio_info == NULL) - /* This should not happen.it does so we don't get BSOD*/ - return; - - channels = speakers_to_channels(audio_info->flags.speaker_flags).all; - - /* setup the audio stream source select (audio -> dig mapping) */ - REG_SET(AFMT_AUDIO_SRC_CONTROL, 0, AFMT_AUDIO_SRC_SELECT, az_inst); - - /* Channel allocation */ - REG_UPDATE(AFMT_AUDIO_PACKET_CONTROL2, AFMT_AUDIO_CHANNEL_ENABLE, channels); -} - -static void enc1_se_setup_hdmi_audio( - struct stream_encoder *enc, - const struct audio_crtc_info *crtc_info) -{ - struct dcn10_stream_encoder *enc1 = DCN10STRENC_FROM_STRENC(enc); - - struct audio_clock_info audio_clock_info = {0}; - - /* HDMI_AUDIO_PACKET_CONTROL */ - REG_UPDATE(HDMI_AUDIO_PACKET_CONTROL, - HDMI_AUDIO_DELAY_EN, 1); - - /* AFMT_AUDIO_PACKET_CONTROL */ - REG_UPDATE(AFMT_AUDIO_PACKET_CONTROL, AFMT_60958_CS_UPDATE, 1); - - /* AFMT_AUDIO_PACKET_CONTROL2 */ - REG_UPDATE_2(AFMT_AUDIO_PACKET_CONTROL2, - AFMT_AUDIO_LAYOUT_OVRD, 0, - AFMT_60958_OSF_OVRD, 0); - - /* HDMI_ACR_PACKET_CONTROL */ - REG_UPDATE_3(HDMI_ACR_PACKET_CONTROL, - HDMI_ACR_AUTO_SEND, 1, - HDMI_ACR_SOURCE, 0, - HDMI_ACR_AUDIO_PRIORITY, 0); - - /* Program audio clock sample/regeneration parameters */ - get_audio_clock_info(crtc_info->color_depth, - crtc_info->requested_pixel_clock_100Hz, - crtc_info->calculated_pixel_clock_100Hz, - &audio_clock_info); - DC_LOG_HW_AUDIO( - "\n%s:Input::requested_pixel_clock_100Hz = %d" \ - "calculated_pixel_clock_100Hz = %d \n", __func__, \ - crtc_info->requested_pixel_clock_100Hz, \ - crtc_info->calculated_pixel_clock_100Hz); - - /* HDMI_ACR_32_0__HDMI_ACR_CTS_32_MASK */ - REG_UPDATE(HDMI_ACR_32_0, HDMI_ACR_CTS_32, audio_clock_info.cts_32khz); - - /* HDMI_ACR_32_1__HDMI_ACR_N_32_MASK */ - REG_UPDATE(HDMI_ACR_32_1, HDMI_ACR_N_32, audio_clock_info.n_32khz); - - /* HDMI_ACR_44_0__HDMI_ACR_CTS_44_MASK */ - REG_UPDATE(HDMI_ACR_44_0, HDMI_ACR_CTS_44, audio_clock_info.cts_44khz); - - /* HDMI_ACR_44_1__HDMI_ACR_N_44_MASK */ - REG_UPDATE(HDMI_ACR_44_1, HDMI_ACR_N_44, audio_clock_info.n_44khz); - - /* HDMI_ACR_48_0__HDMI_ACR_CTS_48_MASK */ - REG_UPDATE(HDMI_ACR_48_0, HDMI_ACR_CTS_48, audio_clock_info.cts_48khz); - - /* HDMI_ACR_48_1__HDMI_ACR_N_48_MASK */ - REG_UPDATE(HDMI_ACR_48_1, HDMI_ACR_N_48, audio_clock_info.n_48khz); - - /* Video driver cannot know in advance which sample rate will - * be used by HD Audio driver - * HDMI_ACR_PACKET_CONTROL__HDMI_ACR_N_MULTIPLE field is - * programmed below in interruppt callback - */ - - /* AFMT_60958_0__AFMT_60958_CS_CHANNEL_NUMBER_L_MASK & - * AFMT_60958_0__AFMT_60958_CS_CLOCK_ACCURACY_MASK - */ - REG_UPDATE_2(AFMT_60958_0, - AFMT_60958_CS_CHANNEL_NUMBER_L, 1, - AFMT_60958_CS_CLOCK_ACCURACY, 0); - - /* AFMT_60958_1 AFMT_60958_CS_CHALNNEL_NUMBER_R */ - REG_UPDATE(AFMT_60958_1, AFMT_60958_CS_CHANNEL_NUMBER_R, 2); - - /* AFMT_60958_2 now keep this settings until - * Programming guide comes out - */ - REG_UPDATE_6(AFMT_60958_2, - AFMT_60958_CS_CHANNEL_NUMBER_2, 3, - AFMT_60958_CS_CHANNEL_NUMBER_3, 4, - AFMT_60958_CS_CHANNEL_NUMBER_4, 5, - AFMT_60958_CS_CHANNEL_NUMBER_5, 6, - AFMT_60958_CS_CHANNEL_NUMBER_6, 7, - AFMT_60958_CS_CHANNEL_NUMBER_7, 8); -} - -static void enc1_se_setup_dp_audio( - struct stream_encoder *enc) -{ - struct dcn10_stream_encoder *enc1 = DCN10STRENC_FROM_STRENC(enc); - - /* --- DP Audio packet configurations --- */ - - /* ATP Configuration */ - REG_SET(DP_SEC_AUD_N, 0, - DP_SEC_AUD_N, DP_SEC_AUD_N__DP_SEC_AUD_N__DEFAULT); - - /* Async/auto-calc timestamp mode */ - REG_SET(DP_SEC_TIMESTAMP, 0, DP_SEC_TIMESTAMP_MODE, - DP_SEC_TIMESTAMP__DP_SEC_TIMESTAMP_MODE__AUTO_CALC); - - /* --- The following are the registers - * copied from the SetupHDMI --- - */ - - /* AFMT_AUDIO_PACKET_CONTROL */ - REG_UPDATE(AFMT_AUDIO_PACKET_CONTROL, AFMT_60958_CS_UPDATE, 1); - - /* AFMT_AUDIO_PACKET_CONTROL2 */ - /* Program the ATP and AIP next */ - REG_UPDATE_2(AFMT_AUDIO_PACKET_CONTROL2, - AFMT_AUDIO_LAYOUT_OVRD, 0, - AFMT_60958_OSF_OVRD, 0); - - /* AFMT_INFOFRAME_CONTROL0 */ - REG_UPDATE(AFMT_INFOFRAME_CONTROL0, AFMT_AUDIO_INFO_UPDATE, 1); - - /* AFMT_60958_0__AFMT_60958_CS_CLOCK_ACCURACY_MASK */ - REG_UPDATE(AFMT_60958_0, AFMT_60958_CS_CLOCK_ACCURACY, 0); -} - -void enc1_se_enable_audio_clock( - struct stream_encoder *enc, - bool enable) -{ - struct dcn10_stream_encoder *enc1 = DCN10STRENC_FROM_STRENC(enc); - - if (REG(AFMT_CNTL) == 0) - return; /* DCE8/10 does not have this register */ - - REG_UPDATE(AFMT_CNTL, AFMT_AUDIO_CLOCK_EN, !!enable); - - /* wait for AFMT clock to turn on, - * expectation: this should complete in 1-2 reads - * - * REG_WAIT(AFMT_CNTL, AFMT_AUDIO_CLOCK_ON, !!enable, 1, 10); - * - * TODO: wait for clock_on does not work well. May need HW - * program sequence. But audio seems work normally even without wait - * for clock_on status change - */ -} - -void enc1_se_enable_dp_audio( - struct stream_encoder *enc) -{ - struct dcn10_stream_encoder *enc1 = DCN10STRENC_FROM_STRENC(enc); - - /* Enable Audio packets */ - REG_UPDATE(DP_SEC_CNTL, DP_SEC_ASP_ENABLE, 1); - - /* Program the ATP and AIP next */ - REG_UPDATE_2(DP_SEC_CNTL, - DP_SEC_ATP_ENABLE, 1, - DP_SEC_AIP_ENABLE, 1); - - /* Program STREAM_ENABLE after all the other enables. */ - REG_UPDATE(DP_SEC_CNTL, DP_SEC_STREAM_ENABLE, 1); -} - -static void enc1_se_disable_dp_audio( - struct stream_encoder *enc) -{ - struct dcn10_stream_encoder *enc1 = DCN10STRENC_FROM_STRENC(enc); - uint32_t value = 0; - - /* Disable Audio packets */ - REG_UPDATE_5(DP_SEC_CNTL, - DP_SEC_ASP_ENABLE, 0, - DP_SEC_ATP_ENABLE, 0, - DP_SEC_AIP_ENABLE, 0, - DP_SEC_ACM_ENABLE, 0, - DP_SEC_STREAM_ENABLE, 0); - - /* This register shared with encoder info frame. Therefore we need to - * keep master enabled if at least on of the fields is not 0 - */ - value = REG_READ(DP_SEC_CNTL); - if (value != 0) - REG_UPDATE(DP_SEC_CNTL, DP_SEC_STREAM_ENABLE, 1); - -} - -void enc1_se_audio_mute_control( - struct stream_encoder *enc, - bool mute) -{ - struct dcn10_stream_encoder *enc1 = DCN10STRENC_FROM_STRENC(enc); - - REG_UPDATE(AFMT_AUDIO_PACKET_CONTROL, AFMT_AUDIO_SAMPLE_SEND, !mute); -} - -void enc1_se_dp_audio_setup( - struct stream_encoder *enc, - unsigned int az_inst, - struct audio_info *info) -{ - enc1_se_audio_setup(enc, az_inst, info); -} - -void enc1_se_dp_audio_enable( - struct stream_encoder *enc) -{ - enc1_se_enable_audio_clock(enc, true); - enc1_se_setup_dp_audio(enc); - enc1_se_enable_dp_audio(enc); -} - -void enc1_se_dp_audio_disable( - struct stream_encoder *enc) -{ - enc1_se_disable_dp_audio(enc); - enc1_se_enable_audio_clock(enc, false); -} - -void enc1_se_hdmi_audio_setup( - struct stream_encoder *enc, - unsigned int az_inst, - struct audio_info *info, - struct audio_crtc_info *audio_crtc_info) -{ - enc1_se_enable_audio_clock(enc, true); - enc1_se_setup_hdmi_audio(enc, audio_crtc_info); - enc1_se_audio_setup(enc, az_inst, info); -} - -void enc1_se_hdmi_audio_disable( - struct stream_encoder *enc) -{ - if (enc->afmt && enc->afmt->funcs->afmt_powerdown) - enc->afmt->funcs->afmt_powerdown(enc->afmt); - - enc1_se_enable_audio_clock(enc, false); -} - - -void enc1_setup_stereo_sync( - struct stream_encoder *enc, - int tg_inst, bool enable) -{ - struct dcn10_stream_encoder *enc1 = DCN10STRENC_FROM_STRENC(enc); - REG_UPDATE(DIG_FE_CNTL, DIG_STEREOSYNC_SELECT, tg_inst); - REG_UPDATE(DIG_FE_CNTL, DIG_STEREOSYNC_GATE_EN, !enable); -} - -void enc1_dig_connect_to_otg( - struct stream_encoder *enc, - int tg_inst) -{ - struct dcn10_stream_encoder *enc1 = DCN10STRENC_FROM_STRENC(enc); - - REG_UPDATE(DIG_FE_CNTL, DIG_SOURCE_SELECT, tg_inst); -} - -unsigned int enc1_dig_source_otg( - struct stream_encoder *enc) -{ - uint32_t tg_inst = 0; - struct dcn10_stream_encoder *enc1 = DCN10STRENC_FROM_STRENC(enc); - - REG_GET(DIG_FE_CNTL, DIG_SOURCE_SELECT, &tg_inst); - - return tg_inst; -} - -bool enc1_stream_encoder_dp_get_pixel_format( - struct stream_encoder *enc, - enum dc_pixel_encoding *encoding, - enum dc_color_depth *depth) -{ - uint32_t hw_encoding = 0; - uint32_t hw_depth = 0; - struct dcn10_stream_encoder *enc1 = DCN10STRENC_FROM_STRENC(enc); - - if (enc == NULL || - encoding == NULL || - depth == NULL) - return false; - - REG_GET_2(DP_PIXEL_FORMAT, - DP_PIXEL_ENCODING, &hw_encoding, - DP_COMPONENT_DEPTH, &hw_depth); - - switch (hw_depth) { - case DP_COMPONENT_PIXEL_DEPTH_6BPC: - *depth = COLOR_DEPTH_666; - break; - case DP_COMPONENT_PIXEL_DEPTH_8BPC: - *depth = COLOR_DEPTH_888; - break; - case DP_COMPONENT_PIXEL_DEPTH_10BPC: - *depth = COLOR_DEPTH_101010; - break; - case DP_COMPONENT_PIXEL_DEPTH_12BPC: - *depth = COLOR_DEPTH_121212; - break; - case DP_COMPONENT_PIXEL_DEPTH_16BPC: - *depth = COLOR_DEPTH_161616; - break; - default: - *depth = COLOR_DEPTH_UNDEFINED; - break; - } - - switch (hw_encoding) { - case DP_PIXEL_ENCODING_TYPE_RGB444: - *encoding = PIXEL_ENCODING_RGB; - break; - case DP_PIXEL_ENCODING_TYPE_YCBCR422: - *encoding = PIXEL_ENCODING_YCBCR422; - break; - case DP_PIXEL_ENCODING_TYPE_YCBCR444: - case DP_PIXEL_ENCODING_TYPE_Y_ONLY: - *encoding = PIXEL_ENCODING_YCBCR444; - break; - case DP_PIXEL_ENCODING_TYPE_YCBCR420: - *encoding = PIXEL_ENCODING_YCBCR420; - break; - default: - *encoding = PIXEL_ENCODING_UNDEFINED; - break; - } - return true; -} - -static const struct stream_encoder_funcs dcn10_str_enc_funcs = { - .dp_set_stream_attribute = - enc1_stream_encoder_dp_set_stream_attribute, - .hdmi_set_stream_attribute = - enc1_stream_encoder_hdmi_set_stream_attribute, - .dvi_set_stream_attribute = - enc1_stream_encoder_dvi_set_stream_attribute, - .set_throttled_vcp_size = - enc1_stream_encoder_set_throttled_vcp_size, - .update_hdmi_info_packets = - enc1_stream_encoder_update_hdmi_info_packets, - .stop_hdmi_info_packets = - enc1_stream_encoder_stop_hdmi_info_packets, - .update_dp_info_packets = - enc1_stream_encoder_update_dp_info_packets, - .send_immediate_sdp_message = - enc1_stream_encoder_send_immediate_sdp_message, - .stop_dp_info_packets = - enc1_stream_encoder_stop_dp_info_packets, - .dp_blank = - enc1_stream_encoder_dp_blank, - .dp_unblank = - enc1_stream_encoder_dp_unblank, - .audio_mute_control = enc1_se_audio_mute_control, - - .dp_audio_setup = enc1_se_dp_audio_setup, - .dp_audio_enable = enc1_se_dp_audio_enable, - .dp_audio_disable = enc1_se_dp_audio_disable, - - .hdmi_audio_setup = enc1_se_hdmi_audio_setup, - .hdmi_audio_disable = enc1_se_hdmi_audio_disable, - .setup_stereo_sync = enc1_setup_stereo_sync, - .set_avmute = enc1_stream_encoder_set_avmute, - .dig_connect_to_otg = enc1_dig_connect_to_otg, - .hdmi_reset_stream_attribute = enc1_reset_hdmi_stream_attribute, - .dig_source_otg = enc1_dig_source_otg, - - .dp_get_pixel_format = enc1_stream_encoder_dp_get_pixel_format, -}; - -void dcn10_stream_encoder_construct( - struct dcn10_stream_encoder *enc1, - struct dc_context *ctx, - struct dc_bios *bp, - enum engine_id eng_id, - const struct dcn10_stream_enc_registers *regs, - const struct dcn10_stream_encoder_shift *se_shift, - const struct dcn10_stream_encoder_mask *se_mask) -{ - enc1->base.funcs = &dcn10_str_enc_funcs; - enc1->base.ctx = ctx; - enc1->base.id = eng_id; - enc1->base.bp = bp; - enc1->regs = regs; - enc1->se_shift = se_shift; - enc1->se_mask = se_mask; - enc1->base.stream_enc_inst = eng_id - ENGINE_ID_DIGA; -} - diff --git a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_stream_encoder.h b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_stream_encoder.h deleted file mode 100644 index 54a6a4ebd636..000000000000 --- a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_stream_encoder.h +++ /dev/null @@ -1,749 +0,0 @@ -/* - * Copyright 2012-15 Advanced Micro Devices, Inc. - * - * Permission is hereby granted, free of charge, to any person obtaining a - * copy of this software and associated documentation files (the "Software"), - * to deal in the Software without restriction, including without limitation - * the rights to use, copy, modify, merge, publish, distribute, sublicense, - * and/or sell copies of the Software, and to permit persons to whom the - * Software is furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL - * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR - * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, - * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR - * OTHER DEALINGS IN THE SOFTWARE. - * - * Authors: AMD - * - */ - -#ifndef __DC_STREAM_ENCODER_DCN10_H__ -#define __DC_STREAM_ENCODER_DCN10_H__ - -#include "stream_encoder.h" - -#define DCN10STRENC_FROM_STRENC(stream_encoder)\ - container_of(stream_encoder, struct dcn10_stream_encoder, base) - -#define SE_COMMON_DCN_REG_LIST(id) \ - SRI(AFMT_CNTL, DIG, id), \ - SRI(AFMT_GENERIC_0, DIG, id), \ - SRI(AFMT_GENERIC_1, DIG, id), \ - SRI(AFMT_GENERIC_2, DIG, id), \ - SRI(AFMT_GENERIC_3, DIG, id), \ - SRI(AFMT_GENERIC_4, DIG, id), \ - SRI(AFMT_GENERIC_5, DIG, id), \ - SRI(AFMT_GENERIC_6, DIG, id), \ - SRI(AFMT_GENERIC_7, DIG, id), \ - SRI(AFMT_GENERIC_HDR, DIG, id), \ - SRI(AFMT_INFOFRAME_CONTROL0, DIG, id), \ - SRI(AFMT_VBI_PACKET_CONTROL, DIG, id), \ - SRI(AFMT_VBI_PACKET_CONTROL1, DIG, id), \ - SRI(AFMT_AUDIO_PACKET_CONTROL, DIG, id), \ - SRI(AFMT_AUDIO_PACKET_CONTROL2, DIG, id), \ - SRI(AFMT_AUDIO_SRC_CONTROL, DIG, id), \ - SRI(AFMT_60958_0, DIG, id), \ - SRI(AFMT_60958_1, DIG, id), \ - SRI(AFMT_60958_2, DIG, id), \ - SRI(DIG_FE_CNTL, DIG, id), \ - SRI(DIG_FIFO_STATUS, DIG, id), \ - SRI(HDMI_CONTROL, DIG, id), \ - SRI(HDMI_DB_CONTROL, DIG, id), \ - SRI(HDMI_GC, DIG, id), \ - SRI(HDMI_GENERIC_PACKET_CONTROL0, DIG, id), \ - SRI(HDMI_GENERIC_PACKET_CONTROL1, DIG, id), \ - SRI(HDMI_GENERIC_PACKET_CONTROL2, DIG, id), \ - SRI(HDMI_GENERIC_PACKET_CONTROL3, DIG, id), \ - SRI(HDMI_INFOFRAME_CONTROL0, DIG, id), \ - SRI(HDMI_INFOFRAME_CONTROL1, DIG, id), \ - SRI(HDMI_VBI_PACKET_CONTROL, DIG, id), \ - SRI(HDMI_AUDIO_PACKET_CONTROL, DIG, id),\ - SRI(HDMI_ACR_PACKET_CONTROL, DIG, id),\ - SRI(HDMI_ACR_32_0, DIG, id),\ - SRI(HDMI_ACR_32_1, DIG, id),\ - SRI(HDMI_ACR_44_0, DIG, id),\ - SRI(HDMI_ACR_44_1, DIG, id),\ - SRI(HDMI_ACR_48_0, DIG, id),\ - SRI(HDMI_ACR_48_1, DIG, id),\ - SRI(DP_DB_CNTL, DP, id), \ - SRI(DP_MSA_MISC, DP, id), \ - SRI(DP_MSA_VBID_MISC, DP, id), \ - SRI(DP_MSA_COLORIMETRY, DP, id), \ - SRI(DP_MSA_TIMING_PARAM1, DP, id), \ - SRI(DP_MSA_TIMING_PARAM2, DP, id), \ - SRI(DP_MSA_TIMING_PARAM3, DP, id), \ - SRI(DP_MSA_TIMING_PARAM4, DP, id), \ - SRI(DP_MSE_RATE_CNTL, DP, id), \ - SRI(DP_MSE_RATE_UPDATE, DP, id), \ - SRI(DP_PIXEL_FORMAT, DP, id), \ - SRI(DP_SEC_CNTL, DP, id), \ - SRI(DP_SEC_CNTL1, DP, id), \ - SRI(DP_SEC_CNTL2, DP, id), \ - SRI(DP_SEC_CNTL5, DP, id), \ - SRI(DP_SEC_CNTL6, DP, id), \ - SRI(DP_STEER_FIFO, DP, id), \ - SRI(DP_VID_M, DP, id), \ - SRI(DP_VID_N, DP, id), \ - SRI(DP_VID_STREAM_CNTL, DP, id), \ - SRI(DP_VID_TIMING, DP, id), \ - SRI(DP_SEC_AUD_N, DP, id), \ - SRI(DP_SEC_AUD_N_READBACK, DP, id), \ - SRI(DP_SEC_AUD_M_READBACK, DP, id), \ - SRI(DP_SEC_TIMESTAMP, DP, id), \ - SRI(DIG_CLOCK_PATTERN, DIG, id) - -#define SE_DCN_REG_LIST(id)\ - SE_COMMON_DCN_REG_LIST(id) - - -struct dcn10_stream_enc_registers { - uint32_t AFMT_CNTL; - uint32_t AFMT_AVI_INFO0; - uint32_t AFMT_AVI_INFO1; - uint32_t AFMT_AVI_INFO2; - uint32_t AFMT_AVI_INFO3; - uint32_t AFMT_GENERIC_0; - uint32_t AFMT_GENERIC_1; - uint32_t AFMT_GENERIC_2; - uint32_t AFMT_GENERIC_3; - uint32_t AFMT_GENERIC_4; - uint32_t AFMT_GENERIC_5; - uint32_t AFMT_GENERIC_6; - uint32_t AFMT_GENERIC_7; - uint32_t AFMT_GENERIC_HDR; - uint32_t AFMT_INFOFRAME_CONTROL0; - uint32_t AFMT_VBI_PACKET_CONTROL; - uint32_t AFMT_VBI_PACKET_CONTROL1; - uint32_t AFMT_AUDIO_PACKET_CONTROL; - uint32_t AFMT_AUDIO_PACKET_CONTROL2; - uint32_t AFMT_AUDIO_SRC_CONTROL; - uint32_t AFMT_60958_0; - uint32_t AFMT_60958_1; - uint32_t AFMT_60958_2; - uint32_t DIG_FE_CNTL; - uint32_t DIG_FIFO_STATUS; - uint32_t DP_MSE_RATE_CNTL; - uint32_t DP_MSE_RATE_UPDATE; - uint32_t DP_PIXEL_FORMAT; - uint32_t DP_SEC_CNTL; - uint32_t DP_SEC_CNTL1; - uint32_t DP_SEC_CNTL2; - uint32_t DP_SEC_CNTL5; - uint32_t DP_SEC_CNTL6; - uint32_t DP_STEER_FIFO; - uint32_t DP_VID_M; - uint32_t DP_VID_N; - uint32_t DP_VID_STREAM_CNTL; - uint32_t DP_VID_TIMING; - uint32_t DP_SEC_AUD_N; - uint32_t DP_SEC_AUD_N_READBACK; - uint32_t DP_SEC_AUD_M_READBACK; - uint32_t DP_SEC_TIMESTAMP; - uint32_t HDMI_CONTROL; - uint32_t HDMI_GC; - uint32_t HDMI_GENERIC_PACKET_CONTROL0; - uint32_t HDMI_GENERIC_PACKET_CONTROL1; - uint32_t HDMI_GENERIC_PACKET_CONTROL2; - uint32_t HDMI_GENERIC_PACKET_CONTROL3; - uint32_t HDMI_GENERIC_PACKET_CONTROL4; - uint32_t HDMI_GENERIC_PACKET_CONTROL5; - uint32_t HDMI_INFOFRAME_CONTROL0; - uint32_t HDMI_INFOFRAME_CONTROL1; - uint32_t HDMI_VBI_PACKET_CONTROL; - uint32_t HDMI_AUDIO_PACKET_CONTROL; - uint32_t HDMI_ACR_PACKET_CONTROL; - uint32_t HDMI_ACR_32_0; - uint32_t HDMI_ACR_32_1; - uint32_t HDMI_ACR_44_0; - uint32_t HDMI_ACR_44_1; - uint32_t HDMI_ACR_48_0; - uint32_t HDMI_ACR_48_1; - uint32_t DP_DB_CNTL; - uint32_t DP_MSA_MISC; - uint32_t DP_MSA_VBID_MISC; - uint32_t DP_MSA_COLORIMETRY; - uint32_t DP_MSA_TIMING_PARAM1; - uint32_t DP_MSA_TIMING_PARAM2; - uint32_t DP_MSA_TIMING_PARAM3; - uint32_t DP_MSA_TIMING_PARAM4; - uint32_t HDMI_DB_CONTROL; - uint32_t DP_DSC_CNTL; - uint32_t DP_DSC_BYTES_PER_PIXEL; - uint32_t DME_CONTROL; - uint32_t DP_SEC_METADATA_TRANSMISSION; - uint32_t HDMI_METADATA_PACKET_CONTROL; - uint32_t DP_SEC_FRAMING4; - uint32_t DP_GSP11_CNTL; - uint32_t HDMI_GENERIC_PACKET_CONTROL6; - uint32_t HDMI_GENERIC_PACKET_CONTROL7; - uint32_t HDMI_GENERIC_PACKET_CONTROL8; - uint32_t HDMI_GENERIC_PACKET_CONTROL9; - uint32_t HDMI_GENERIC_PACKET_CONTROL10; - uint32_t DIG_CLOCK_PATTERN; - uint32_t DIG_FIFO_CTRL0; - uint32_t DIG_FE_CLK_CNTL; - uint32_t DIG_FE_EN_CNTL; - uint32_t STREAM_MAPPER_CONTROL; -}; - - -#define SE_SF(reg_name, field_name, post_fix)\ - .field_name = reg_name ## __ ## field_name ## post_fix - -#define SE_COMMON_MASK_SH_LIST_SOC(mask_sh)\ - SE_SF(DIG0_AFMT_VBI_PACKET_CONTROL, AFMT_GENERIC_INDEX, mask_sh),\ - SE_SF(DIG0_AFMT_GENERIC_HDR, AFMT_GENERIC_HB0, mask_sh),\ - SE_SF(DIG0_AFMT_GENERIC_HDR, AFMT_GENERIC_HB1, mask_sh),\ - SE_SF(DIG0_AFMT_GENERIC_HDR, AFMT_GENERIC_HB2, mask_sh),\ - SE_SF(DIG0_AFMT_GENERIC_HDR, AFMT_GENERIC_HB3, mask_sh),\ - SE_SF(DP0_DP_PIXEL_FORMAT, DP_PIXEL_ENCODING, mask_sh),\ - SE_SF(DP0_DP_PIXEL_FORMAT, DP_COMPONENT_DEPTH, mask_sh),\ - SE_SF(DIG0_HDMI_CONTROL, HDMI_PACKET_GEN_VERSION, mask_sh),\ - SE_SF(DIG0_HDMI_CONTROL, HDMI_KEEPOUT_MODE, mask_sh),\ - SE_SF(DIG0_HDMI_CONTROL, HDMI_DEEP_COLOR_ENABLE, mask_sh),\ - SE_SF(DIG0_HDMI_CONTROL, HDMI_DEEP_COLOR_DEPTH, mask_sh),\ - SE_SF(DIG0_HDMI_CONTROL, HDMI_DATA_SCRAMBLE_EN, mask_sh),\ - SE_SF(DIG0_HDMI_CONTROL, HDMI_NO_EXTRA_NULL_PACKET_FILLED, mask_sh),\ - SE_SF(DIG0_HDMI_VBI_PACKET_CONTROL, HDMI_GC_CONT, mask_sh),\ - SE_SF(DIG0_HDMI_VBI_PACKET_CONTROL, HDMI_GC_SEND, mask_sh),\ - SE_SF(DIG0_HDMI_VBI_PACKET_CONTROL, HDMI_NULL_SEND, mask_sh),\ - SE_SF(DIG0_HDMI_VBI_PACKET_CONTROL, HDMI_ACP_SEND, mask_sh),\ - SE_SF(DIG0_HDMI_INFOFRAME_CONTROL0, HDMI_AUDIO_INFO_SEND, mask_sh),\ - SE_SF(DIG0_AFMT_INFOFRAME_CONTROL0, AFMT_AUDIO_INFO_UPDATE, mask_sh),\ - SE_SF(DIG0_HDMI_INFOFRAME_CONTROL1, HDMI_AUDIO_INFO_LINE, mask_sh),\ - SE_SF(DIG0_HDMI_GC, HDMI_GC_AVMUTE, mask_sh),\ - SE_SF(DP0_DP_MSE_RATE_CNTL, DP_MSE_RATE_X, mask_sh),\ - SE_SF(DP0_DP_MSE_RATE_CNTL, DP_MSE_RATE_Y, mask_sh),\ - SE_SF(DP0_DP_MSE_RATE_UPDATE, DP_MSE_RATE_UPDATE_PENDING, mask_sh),\ - SE_SF(DP0_DP_SEC_CNTL, DP_SEC_GSP0_ENABLE, mask_sh),\ - SE_SF(DP0_DP_SEC_CNTL, DP_SEC_STREAM_ENABLE, mask_sh),\ - SE_SF(DP0_DP_SEC_CNTL, DP_SEC_GSP1_ENABLE, mask_sh),\ - SE_SF(DP0_DP_SEC_CNTL, DP_SEC_GSP2_ENABLE, mask_sh),\ - SE_SF(DP0_DP_SEC_CNTL, DP_SEC_GSP3_ENABLE, mask_sh),\ - SE_SF(DP0_DP_SEC_CNTL, DP_SEC_MPG_ENABLE, mask_sh),\ - SE_SF(DP0_DP_SEC_CNTL2, DP_SEC_GSP4_SEND, mask_sh),\ - SE_SF(DP0_DP_SEC_CNTL2, DP_SEC_GSP4_SEND_PENDING, mask_sh),\ - SE_SF(DP0_DP_SEC_CNTL4, DP_SEC_GSP4_LINE_NUM, mask_sh),\ - SE_SF(DP0_DP_SEC_CNTL2, DP_SEC_GSP4_SEND_ANY_LINE, mask_sh),\ - SE_SF(DP0_DP_VID_STREAM_CNTL, DP_VID_STREAM_DIS_DEFER, mask_sh),\ - SE_SF(DP0_DP_VID_STREAM_CNTL, DP_VID_STREAM_ENABLE, mask_sh),\ - SE_SF(DP0_DP_VID_STREAM_CNTL, DP_VID_STREAM_STATUS, mask_sh),\ - SE_SF(DP0_DP_STEER_FIFO, DP_STEER_FIFO_RESET, mask_sh),\ - SE_SF(DP0_DP_VID_TIMING, DP_VID_M_N_GEN_EN, mask_sh),\ - SE_SF(DP0_DP_VID_N, DP_VID_N, mask_sh),\ - SE_SF(DP0_DP_VID_M, DP_VID_M, mask_sh),\ - SE_SF(DIG0_DIG_FE_CNTL, DIG_START, mask_sh),\ - SE_SF(DIG0_AFMT_AUDIO_SRC_CONTROL, AFMT_AUDIO_SRC_SELECT, mask_sh),\ - SE_SF(DIG0_AFMT_AUDIO_PACKET_CONTROL2, AFMT_AUDIO_CHANNEL_ENABLE, mask_sh),\ - SE_SF(DIG0_HDMI_AUDIO_PACKET_CONTROL, HDMI_AUDIO_PACKETS_PER_LINE, mask_sh),\ - SE_SF(DIG0_HDMI_AUDIO_PACKET_CONTROL, HDMI_AUDIO_DELAY_EN, mask_sh),\ - SE_SF(DIG0_AFMT_AUDIO_PACKET_CONTROL, AFMT_60958_CS_UPDATE, mask_sh),\ - SE_SF(DIG0_AFMT_AUDIO_PACKET_CONTROL2, AFMT_AUDIO_LAYOUT_OVRD, mask_sh),\ - SE_SF(DIG0_AFMT_AUDIO_PACKET_CONTROL2, AFMT_60958_OSF_OVRD, mask_sh),\ - SE_SF(DIG0_HDMI_ACR_PACKET_CONTROL, HDMI_ACR_AUTO_SEND, mask_sh),\ - SE_SF(DIG0_HDMI_ACR_PACKET_CONTROL, HDMI_ACR_SOURCE, mask_sh),\ - SE_SF(DIG0_HDMI_ACR_PACKET_CONTROL, HDMI_ACR_AUDIO_PRIORITY, mask_sh),\ - SE_SF(DIG0_HDMI_ACR_32_0, HDMI_ACR_CTS_32, mask_sh),\ - SE_SF(DIG0_HDMI_ACR_32_1, HDMI_ACR_N_32, mask_sh),\ - SE_SF(DIG0_HDMI_ACR_44_0, HDMI_ACR_CTS_44, mask_sh),\ - SE_SF(DIG0_HDMI_ACR_44_1, HDMI_ACR_N_44, mask_sh),\ - SE_SF(DIG0_HDMI_ACR_48_0, HDMI_ACR_CTS_48, mask_sh),\ - SE_SF(DIG0_HDMI_ACR_48_1, HDMI_ACR_N_48, mask_sh),\ - SE_SF(DIG0_AFMT_60958_0, AFMT_60958_CS_CHANNEL_NUMBER_L, mask_sh),\ - SE_SF(DIG0_AFMT_60958_0, AFMT_60958_CS_CLOCK_ACCURACY, mask_sh),\ - SE_SF(DIG0_AFMT_60958_1, AFMT_60958_CS_CHANNEL_NUMBER_R, mask_sh),\ - SE_SF(DIG0_AFMT_60958_2, AFMT_60958_CS_CHANNEL_NUMBER_2, mask_sh),\ - SE_SF(DIG0_AFMT_60958_2, AFMT_60958_CS_CHANNEL_NUMBER_3, mask_sh),\ - SE_SF(DIG0_AFMT_60958_2, AFMT_60958_CS_CHANNEL_NUMBER_4, mask_sh),\ - SE_SF(DIG0_AFMT_60958_2, AFMT_60958_CS_CHANNEL_NUMBER_5, mask_sh),\ - SE_SF(DIG0_AFMT_60958_2, AFMT_60958_CS_CHANNEL_NUMBER_6, mask_sh),\ - SE_SF(DIG0_AFMT_60958_2, AFMT_60958_CS_CHANNEL_NUMBER_7, mask_sh),\ - SE_SF(DP0_DP_SEC_AUD_N, DP_SEC_AUD_N, mask_sh),\ - SE_SF(DP0_DP_SEC_AUD_N_READBACK, DP_SEC_AUD_N_READBACK, mask_sh),\ - SE_SF(DP0_DP_SEC_AUD_M_READBACK, DP_SEC_AUD_M_READBACK, mask_sh),\ - SE_SF(DP0_DP_SEC_TIMESTAMP, DP_SEC_TIMESTAMP_MODE, mask_sh),\ - SE_SF(DP0_DP_SEC_CNTL, DP_SEC_ASP_ENABLE, mask_sh),\ - SE_SF(DP0_DP_SEC_CNTL, DP_SEC_ATP_ENABLE, mask_sh),\ - SE_SF(DP0_DP_SEC_CNTL, DP_SEC_AIP_ENABLE, mask_sh),\ - SE_SF(DP0_DP_SEC_CNTL, DP_SEC_ACM_ENABLE, mask_sh),\ - SE_SF(DIG0_AFMT_AUDIO_PACKET_CONTROL, AFMT_AUDIO_SAMPLE_SEND, mask_sh),\ - SE_SF(DIG0_AFMT_CNTL, AFMT_AUDIO_CLOCK_EN, mask_sh),\ - SE_SF(DIG0_HDMI_CONTROL, HDMI_CLOCK_CHANNEL_RATE, mask_sh),\ - SE_SF(DIG0_DIG_FE_CNTL, TMDS_PIXEL_ENCODING, mask_sh),\ - SE_SF(DIG0_DIG_FE_CNTL, TMDS_COLOR_FORMAT, mask_sh),\ - SE_SF(DIG0_DIG_FE_CNTL, DIG_STEREOSYNC_SELECT, mask_sh),\ - SE_SF(DIG0_DIG_FE_CNTL, DIG_STEREOSYNC_GATE_EN, mask_sh),\ - SE_SF(DIG0_DIG_FIFO_STATUS, DIG_FIFO_LEVEL_ERROR, mask_sh),\ - SE_SF(DIG0_DIG_FIFO_STATUS, DIG_FIFO_USE_OVERWRITE_LEVEL, mask_sh),\ - SE_SF(DIG0_DIG_FIFO_STATUS, DIG_FIFO_OVERWRITE_LEVEL, mask_sh),\ - SE_SF(DIG0_DIG_FIFO_STATUS, DIG_FIFO_ERROR_ACK, mask_sh),\ - SE_SF(DIG0_DIG_FIFO_STATUS, DIG_FIFO_CAL_AVERAGE_LEVEL, mask_sh),\ - SE_SF(DIG0_DIG_FIFO_STATUS, DIG_FIFO_MAXIMUM_LEVEL, mask_sh),\ - SE_SF(DIG0_DIG_FIFO_STATUS, DIG_FIFO_MINIMUM_LEVEL, mask_sh),\ - SE_SF(DIG0_DIG_FIFO_STATUS, DIG_FIFO_READ_CLOCK_SRC, mask_sh),\ - SE_SF(DIG0_DIG_FIFO_STATUS, DIG_FIFO_CALIBRATED, mask_sh),\ - SE_SF(DIG0_DIG_FIFO_STATUS, DIG_FIFO_FORCE_RECAL_AVERAGE, mask_sh),\ - SE_SF(DIG0_DIG_FIFO_STATUS, DIG_FIFO_FORCE_RECOMP_MINMAX, mask_sh),\ - SE_SF(DIG0_AFMT_VBI_PACKET_CONTROL, AFMT_GENERIC_LOCK_STATUS, mask_sh),\ - SE_SF(DIG0_AFMT_VBI_PACKET_CONTROL, AFMT_GENERIC_CONFLICT, mask_sh),\ - SE_SF(DIG0_AFMT_VBI_PACKET_CONTROL, AFMT_GENERIC_CONFLICT_CLR, mask_sh),\ - SE_SF(DIG0_AFMT_VBI_PACKET_CONTROL1, AFMT_GENERIC0_FRAME_UPDATE_PENDING, mask_sh),\ - SE_SF(DIG0_AFMT_VBI_PACKET_CONTROL1, AFMT_GENERIC1_FRAME_UPDATE_PENDING, mask_sh),\ - SE_SF(DIG0_AFMT_VBI_PACKET_CONTROL1, AFMT_GENERIC2_FRAME_UPDATE_PENDING, mask_sh),\ - SE_SF(DIG0_AFMT_VBI_PACKET_CONTROL1, AFMT_GENERIC3_FRAME_UPDATE_PENDING, mask_sh),\ - SE_SF(DIG0_AFMT_VBI_PACKET_CONTROL1, AFMT_GENERIC4_FRAME_UPDATE_PENDING, mask_sh),\ - SE_SF(DIG0_AFMT_VBI_PACKET_CONTROL1, AFMT_GENERIC4_IMMEDIATE_UPDATE_PENDING, mask_sh),\ - SE_SF(DIG0_AFMT_VBI_PACKET_CONTROL1, AFMT_GENERIC5_FRAME_UPDATE_PENDING, mask_sh),\ - SE_SF(DIG0_AFMT_VBI_PACKET_CONTROL1, AFMT_GENERIC6_FRAME_UPDATE_PENDING, mask_sh),\ - SE_SF(DIG0_AFMT_VBI_PACKET_CONTROL1, AFMT_GENERIC7_FRAME_UPDATE_PENDING, mask_sh),\ - SE_SF(DIG0_AFMT_VBI_PACKET_CONTROL1, AFMT_GENERIC0_FRAME_UPDATE, mask_sh),\ - SE_SF(DIG0_AFMT_VBI_PACKET_CONTROL1, AFMT_GENERIC1_FRAME_UPDATE, mask_sh),\ - SE_SF(DIG0_AFMT_VBI_PACKET_CONTROL1, AFMT_GENERIC2_FRAME_UPDATE, mask_sh),\ - SE_SF(DIG0_AFMT_VBI_PACKET_CONTROL1, AFMT_GENERIC3_FRAME_UPDATE, mask_sh),\ - SE_SF(DIG0_AFMT_VBI_PACKET_CONTROL1, AFMT_GENERIC4_FRAME_UPDATE, mask_sh),\ - SE_SF(DIG0_AFMT_VBI_PACKET_CONTROL1, AFMT_GENERIC0_IMMEDIATE_UPDATE, mask_sh),\ - SE_SF(DIG0_AFMT_VBI_PACKET_CONTROL1, AFMT_GENERIC1_IMMEDIATE_UPDATE, mask_sh),\ - SE_SF(DIG0_AFMT_VBI_PACKET_CONTROL1, AFMT_GENERIC2_IMMEDIATE_UPDATE, mask_sh),\ - SE_SF(DIG0_AFMT_VBI_PACKET_CONTROL1, AFMT_GENERIC3_IMMEDIATE_UPDATE, mask_sh),\ - SE_SF(DIG0_AFMT_VBI_PACKET_CONTROL1, AFMT_GENERIC4_IMMEDIATE_UPDATE, mask_sh),\ - SE_SF(DIG0_AFMT_VBI_PACKET_CONTROL1, AFMT_GENERIC5_IMMEDIATE_UPDATE, mask_sh),\ - SE_SF(DIG0_AFMT_VBI_PACKET_CONTROL1, AFMT_GENERIC6_IMMEDIATE_UPDATE, mask_sh),\ - SE_SF(DIG0_AFMT_VBI_PACKET_CONTROL1, AFMT_GENERIC7_IMMEDIATE_UPDATE, mask_sh),\ - SE_SF(DIG0_AFMT_VBI_PACKET_CONTROL1, AFMT_GENERIC5_FRAME_UPDATE, mask_sh),\ - SE_SF(DIG0_AFMT_VBI_PACKET_CONTROL1, AFMT_GENERIC6_FRAME_UPDATE, mask_sh),\ - SE_SF(DIG0_AFMT_VBI_PACKET_CONTROL1, AFMT_GENERIC7_FRAME_UPDATE, mask_sh),\ - SE_SF(DP0_DP_SEC_CNTL, DP_SEC_GSP4_ENABLE, mask_sh),\ - SE_SF(DP0_DP_SEC_CNTL, DP_SEC_GSP5_ENABLE, mask_sh),\ - SE_SF(DP0_DP_SEC_CNTL, DP_SEC_GSP6_ENABLE, mask_sh),\ - SE_SF(DP0_DP_SEC_CNTL, DP_SEC_GSP7_ENABLE, mask_sh),\ - SE_SF(DP0_DP_SEC_CNTL2, DP_SEC_GSP7_PPS, mask_sh),\ - SE_SF(DP0_DP_SEC_CNTL2, DP_SEC_GSP7_SEND, mask_sh),\ - SE_SF(DP0_DP_SEC_CNTL6, DP_SEC_GSP7_LINE_NUM, mask_sh),\ - SE_SF(DP0_DP_DB_CNTL, DP_DB_DISABLE, mask_sh),\ - SE_SF(DP0_DP_MSA_COLORIMETRY, DP_MSA_MISC0, mask_sh),\ - SE_SF(DP0_DP_MSA_TIMING_PARAM1, DP_MSA_HTOTAL, mask_sh),\ - SE_SF(DP0_DP_MSA_TIMING_PARAM1, DP_MSA_VTOTAL, mask_sh),\ - SE_SF(DP0_DP_MSA_TIMING_PARAM2, DP_MSA_HSTART, mask_sh),\ - SE_SF(DP0_DP_MSA_TIMING_PARAM2, DP_MSA_VSTART, mask_sh),\ - SE_SF(DP0_DP_MSA_TIMING_PARAM3, DP_MSA_HSYNCWIDTH, mask_sh),\ - SE_SF(DP0_DP_MSA_TIMING_PARAM3, DP_MSA_HSYNCPOLARITY, mask_sh),\ - SE_SF(DP0_DP_MSA_TIMING_PARAM3, DP_MSA_VSYNCWIDTH, mask_sh),\ - SE_SF(DP0_DP_MSA_TIMING_PARAM3, DP_MSA_VSYNCPOLARITY, mask_sh),\ - SE_SF(DP0_DP_MSA_TIMING_PARAM4, DP_MSA_HWIDTH, mask_sh),\ - SE_SF(DP0_DP_MSA_TIMING_PARAM4, DP_MSA_VHEIGHT, mask_sh),\ - SE_SF(DIG0_HDMI_DB_CONTROL, HDMI_DB_DISABLE, mask_sh),\ - SE_SF(DP0_DP_VID_TIMING, DP_VID_N_MUL, mask_sh),\ - SE_SF(DIG0_DIG_FE_CNTL, DIG_SOURCE_SELECT, mask_sh),\ - SE_SF(DIG0_DIG_CLOCK_PATTERN, DIG_CLOCK_PATTERN, mask_sh) - -#define SE_COMMON_MASK_SH_LIST_DCN10(mask_sh)\ - SE_COMMON_MASK_SH_LIST_SOC(mask_sh),\ - SE_SF(DIG0_HDMI_GENERIC_PACKET_CONTROL0, HDMI_GENERIC0_CONT, mask_sh),\ - SE_SF(DIG0_HDMI_GENERIC_PACKET_CONTROL0, HDMI_GENERIC0_SEND, mask_sh),\ - SE_SF(DIG0_HDMI_GENERIC_PACKET_CONTROL0, HDMI_GENERIC0_LINE, mask_sh),\ - SE_SF(DIG0_HDMI_GENERIC_PACKET_CONTROL0, HDMI_GENERIC1_CONT, mask_sh),\ - SE_SF(DIG0_HDMI_GENERIC_PACKET_CONTROL0, HDMI_GENERIC1_SEND, mask_sh),\ - SE_SF(DIG0_HDMI_GENERIC_PACKET_CONTROL0, HDMI_GENERIC1_LINE, mask_sh) - - -#define SE_REG_FIELD_LIST_DCN1_0(type) \ - type AFMT_GENERIC_INDEX;\ - type AFMT_GENERIC_HB0;\ - type AFMT_GENERIC_HB1;\ - type AFMT_GENERIC_HB2;\ - type AFMT_GENERIC_HB3;\ - type AFMT_GENERIC_LOCK_STATUS;\ - type AFMT_GENERIC_CONFLICT;\ - type AFMT_GENERIC_CONFLICT_CLR;\ - type AFMT_GENERIC0_FRAME_UPDATE_PENDING;\ - type AFMT_GENERIC1_FRAME_UPDATE_PENDING;\ - type AFMT_GENERIC2_FRAME_UPDATE_PENDING;\ - type AFMT_GENERIC3_FRAME_UPDATE_PENDING;\ - type AFMT_GENERIC4_FRAME_UPDATE_PENDING;\ - type AFMT_GENERIC4_IMMEDIATE_UPDATE_PENDING;\ - type AFMT_GENERIC5_FRAME_UPDATE_PENDING;\ - type AFMT_GENERIC6_FRAME_UPDATE_PENDING;\ - type AFMT_GENERIC7_FRAME_UPDATE_PENDING;\ - type AFMT_GENERIC0_FRAME_UPDATE;\ - type AFMT_GENERIC1_FRAME_UPDATE;\ - type AFMT_GENERIC2_FRAME_UPDATE;\ - type AFMT_GENERIC3_FRAME_UPDATE;\ - type AFMT_GENERIC4_FRAME_UPDATE;\ - type AFMT_GENERIC0_IMMEDIATE_UPDATE;\ - type AFMT_GENERIC1_IMMEDIATE_UPDATE;\ - type AFMT_GENERIC2_IMMEDIATE_UPDATE;\ - type AFMT_GENERIC3_IMMEDIATE_UPDATE;\ - type AFMT_GENERIC4_IMMEDIATE_UPDATE;\ - type AFMT_GENERIC5_IMMEDIATE_UPDATE;\ - type AFMT_GENERIC6_IMMEDIATE_UPDATE;\ - type AFMT_GENERIC7_IMMEDIATE_UPDATE;\ - type AFMT_GENERIC5_FRAME_UPDATE;\ - type AFMT_GENERIC6_FRAME_UPDATE;\ - type AFMT_GENERIC7_FRAME_UPDATE;\ - type HDMI_GENERIC0_CONT;\ - type HDMI_GENERIC0_SEND;\ - type HDMI_GENERIC0_LINE;\ - type HDMI_GENERIC1_CONT;\ - type HDMI_GENERIC1_SEND;\ - type HDMI_GENERIC1_LINE;\ - type HDMI_GENERIC2_CONT;\ - type HDMI_GENERIC2_SEND;\ - type HDMI_GENERIC2_LINE;\ - type HDMI_GENERIC3_CONT;\ - type HDMI_GENERIC3_SEND;\ - type HDMI_GENERIC3_LINE;\ - type HDMI_GENERIC4_CONT;\ - type HDMI_GENERIC4_SEND;\ - type HDMI_GENERIC4_LINE;\ - type HDMI_GENERIC5_CONT;\ - type HDMI_GENERIC5_SEND;\ - type HDMI_GENERIC5_LINE;\ - type HDMI_GENERIC6_CONT;\ - type HDMI_GENERIC6_SEND;\ - type HDMI_GENERIC6_LINE;\ - type HDMI_GENERIC7_CONT;\ - type HDMI_GENERIC7_SEND;\ - type HDMI_GENERIC7_LINE;\ - type DP_PIXEL_ENCODING;\ - type DP_COMPONENT_DEPTH;\ - type HDMI_PACKET_GEN_VERSION;\ - type HDMI_KEEPOUT_MODE;\ - type HDMI_DEEP_COLOR_ENABLE;\ - type HDMI_CLOCK_CHANNEL_RATE;\ - type HDMI_DEEP_COLOR_DEPTH;\ - type HDMI_GC_CONT;\ - type HDMI_GC_SEND;\ - type HDMI_NULL_SEND;\ - type HDMI_DATA_SCRAMBLE_EN;\ - type HDMI_NO_EXTRA_NULL_PACKET_FILLED;\ - type HDMI_AUDIO_INFO_SEND;\ - type AFMT_AUDIO_INFO_UPDATE;\ - type HDMI_AUDIO_INFO_LINE;\ - type HDMI_GC_AVMUTE;\ - type DP_MSE_RATE_X;\ - type DP_MSE_RATE_Y;\ - type DP_MSE_RATE_UPDATE_PENDING;\ - type DP_SEC_GSP0_ENABLE;\ - type DP_SEC_STREAM_ENABLE;\ - type DP_SEC_GSP1_ENABLE;\ - type DP_SEC_GSP2_ENABLE;\ - type DP_SEC_GSP3_ENABLE;\ - type DP_SEC_GSP4_ENABLE;\ - type DP_SEC_GSP5_ENABLE;\ - type DP_SEC_GSP5_LINE_NUM;\ - type DP_SEC_GSP5_LINE_REFERENCE;\ - type DP_SEC_GSP6_ENABLE;\ - type DP_SEC_GSP7_ENABLE;\ - type DP_SEC_GSP7_PPS;\ - type DP_SEC_GSP7_SEND;\ - type DP_SEC_GSP4_SEND;\ - type DP_SEC_GSP4_SEND_PENDING;\ - type DP_SEC_GSP4_LINE_NUM;\ - type DP_SEC_GSP4_SEND_ANY_LINE;\ - type DP_SEC_MPG_ENABLE;\ - type DP_VID_STREAM_DIS_DEFER;\ - type DP_VID_STREAM_ENABLE;\ - type DP_VID_STREAM_STATUS;\ - type DP_STEER_FIFO_RESET;\ - type DP_VID_M_N_GEN_EN;\ - type DP_VID_N;\ - type DP_VID_M;\ - type DIG_START;\ - type AFMT_AUDIO_SRC_SELECT;\ - type AFMT_AUDIO_CHANNEL_ENABLE;\ - type HDMI_AUDIO_PACKETS_PER_LINE;\ - type HDMI_AUDIO_DELAY_EN;\ - type AFMT_60958_CS_UPDATE;\ - type AFMT_AUDIO_LAYOUT_OVRD;\ - type AFMT_60958_OSF_OVRD;\ - type HDMI_ACR_AUTO_SEND;\ - type HDMI_ACR_SOURCE;\ - type HDMI_ACR_AUDIO_PRIORITY;\ - type HDMI_ACR_CTS_32;\ - type HDMI_ACR_N_32;\ - type HDMI_ACR_CTS_44;\ - type HDMI_ACR_N_44;\ - type HDMI_ACR_CTS_48;\ - type HDMI_ACR_N_48;\ - type AFMT_60958_CS_CHANNEL_NUMBER_L;\ - type AFMT_60958_CS_CLOCK_ACCURACY;\ - type AFMT_60958_CS_CHANNEL_NUMBER_R;\ - type AFMT_60958_CS_CHANNEL_NUMBER_2;\ - type AFMT_60958_CS_CHANNEL_NUMBER_3;\ - type AFMT_60958_CS_CHANNEL_NUMBER_4;\ - type AFMT_60958_CS_CHANNEL_NUMBER_5;\ - type AFMT_60958_CS_CHANNEL_NUMBER_6;\ - type AFMT_60958_CS_CHANNEL_NUMBER_7;\ - type DP_SEC_AUD_N;\ - type DP_SEC_AUD_N_READBACK;\ - type DP_SEC_AUD_M_READBACK;\ - type DP_SEC_TIMESTAMP_MODE;\ - type DP_SEC_ASP_ENABLE;\ - type DP_SEC_ATP_ENABLE;\ - type DP_SEC_AIP_ENABLE;\ - type DP_SEC_ACM_ENABLE;\ - type DP_SEC_GSP7_LINE_NUM;\ - type AFMT_AUDIO_SAMPLE_SEND;\ - type AFMT_AUDIO_CLOCK_EN;\ - type TMDS_PIXEL_ENCODING;\ - type TMDS_COLOR_FORMAT;\ - type DIG_STEREOSYNC_SELECT;\ - type DIG_STEREOSYNC_GATE_EN;\ - type DP_DB_DISABLE;\ - type DP_MSA_MISC0;\ - type DP_MSA_HTOTAL;\ - type DP_MSA_VTOTAL;\ - type DP_MSA_HSTART;\ - type DP_MSA_VSTART;\ - type DP_MSA_HSYNCWIDTH;\ - type DP_MSA_HSYNCPOLARITY;\ - type DP_MSA_VSYNCWIDTH;\ - type DP_MSA_VSYNCPOLARITY;\ - type DP_MSA_HWIDTH;\ - type DP_MSA_VHEIGHT;\ - type HDMI_DB_DISABLE;\ - type DP_VID_N_MUL;\ - type DP_VID_M_DOUBLE_VALUE_EN;\ - type DIG_SOURCE_SELECT;\ - type DIG_FIFO_LEVEL_ERROR;\ - type DIG_FIFO_USE_OVERWRITE_LEVEL;\ - type DIG_FIFO_OVERWRITE_LEVEL;\ - type DIG_FIFO_ERROR_ACK;\ - type DIG_FIFO_CAL_AVERAGE_LEVEL;\ - type DIG_FIFO_MAXIMUM_LEVEL;\ - type DIG_FIFO_MINIMUM_LEVEL;\ - type DIG_FIFO_READ_CLOCK_SRC;\ - type DIG_FIFO_CALIBRATED;\ - type DIG_FIFO_FORCE_RECAL_AVERAGE;\ - type DIG_FIFO_FORCE_RECOMP_MINMAX;\ - type DIG_CLOCK_PATTERN - -#define SE_REG_FIELD_LIST_DCN2_0(type) \ - type DP_DSC_MODE;\ - type DP_DSC_SLICE_WIDTH;\ - type DP_DSC_BYTES_PER_PIXEL;\ - type DP_VBID6_LINE_REFERENCE;\ - type DP_VBID6_LINE_NUM;\ - type METADATA_ENGINE_EN;\ - type METADATA_HUBP_REQUESTOR_ID;\ - type METADATA_STREAM_TYPE;\ - type DP_SEC_METADATA_PACKET_ENABLE;\ - type DP_SEC_METADATA_PACKET_LINE_REFERENCE;\ - type DP_SEC_METADATA_PACKET_LINE;\ - type HDMI_METADATA_PACKET_ENABLE;\ - type HDMI_METADATA_PACKET_LINE_REFERENCE;\ - type HDMI_METADATA_PACKET_LINE;\ - type DOLBY_VISION_EN;\ - type DP_PIXEL_COMBINE;\ - type DP_SST_SDP_SPLITTING - -#define SE_REG_FIELD_LIST_DCN3_0(type) \ - type HDMI_GENERIC8_CONT;\ - type HDMI_GENERIC8_SEND;\ - type HDMI_GENERIC8_LINE;\ - type HDMI_GENERIC9_CONT;\ - type HDMI_GENERIC9_SEND;\ - type HDMI_GENERIC9_LINE;\ - type HDMI_GENERIC10_CONT;\ - type HDMI_GENERIC10_SEND;\ - type HDMI_GENERIC10_LINE;\ - type HDMI_GENERIC11_CONT;\ - type HDMI_GENERIC11_SEND;\ - type HDMI_GENERIC11_LINE;\ - type HDMI_GENERIC12_CONT;\ - type HDMI_GENERIC12_SEND;\ - type HDMI_GENERIC12_LINE;\ - type HDMI_GENERIC13_CONT;\ - type HDMI_GENERIC13_SEND;\ - type HDMI_GENERIC13_LINE;\ - type HDMI_GENERIC14_CONT;\ - type HDMI_GENERIC14_SEND;\ - type HDMI_GENERIC14_LINE;\ - type DP_SEC_GSP11_PPS;\ - type DP_SEC_GSP11_ENABLE;\ - type DP_SEC_GSP11_LINE_NUM - -#define SE_REG_FIELD_LIST_DCN3_1_COMMON(type) \ - type DIG_FIFO_OUTPUT_PIXEL_MODE;\ - type DP_PIXEL_PER_CYCLE_PROCESSING_MODE;\ - type DIG_SYMCLK_FE_ON;\ - type DIG_FIFO_READ_START_LEVEL;\ - type DIG_FIFO_ENABLE;\ - type DIG_FIFO_RESET;\ - type DIG_FIFO_RESET_DONE;\ - type PIXEL_ENCODING_TYPE;\ - type UNCOMPRESSED_PIXEL_FORMAT;\ - type UNCOMPRESSED_COMPONENT_DEPTH - -#define SE_REG_FIELD_LIST_DCN3_5_COMMON(type) \ - type DIG_FE_CLK_EN;\ - type DIG_FE_MODE;\ - type DIG_FE_SOFT_RESET;\ - type DIG_FE_ENABLE;\ - type DIG_FE_SYMCLK_FE_G_CLOCK_ON;\ - type DIG_FE_DISPCLK_G_CLOCK_ON;\ - type DIG_FE_SYMCLK_FE_G_AFMT_CLOCK_ON;\ - type DIG_FE_SYMCLK_FE_G_TMDS_CLOCK_ON;\ - type DIG_FE_SOCCLK_G_AFMT_CLOCK_ON;\ - type DIG_STREAM_LINK_TARGET - -#define SE_REG_FIELD_LIST_DCN4_01_COMMON(type) \ - type COMPRESSED_PIXEL_FORMAT;\ - type DP_VID_N_INTERVAL;\ - type DIG_FIFO_OUTPUT_PIXEL_PER_CYCLE;\ - type DP_STEER_FIFO_ENABLE -struct dcn10_stream_encoder_shift { - SE_REG_FIELD_LIST_DCN1_0(uint8_t); - uint8_t HDMI_ACP_SEND; - SE_REG_FIELD_LIST_DCN2_0(uint8_t); - SE_REG_FIELD_LIST_DCN3_0(uint8_t); - SE_REG_FIELD_LIST_DCN3_1_COMMON(uint8_t); - SE_REG_FIELD_LIST_DCN3_5_COMMON(uint8_t); - SE_REG_FIELD_LIST_DCN4_01_COMMON(uint32_t); -}; - -struct dcn10_stream_encoder_mask { - SE_REG_FIELD_LIST_DCN1_0(uint32_t); - uint32_t HDMI_ACP_SEND; - SE_REG_FIELD_LIST_DCN2_0(uint32_t); - SE_REG_FIELD_LIST_DCN3_0(uint32_t); - SE_REG_FIELD_LIST_DCN3_1_COMMON(uint32_t); - SE_REG_FIELD_LIST_DCN3_5_COMMON(uint32_t); - SE_REG_FIELD_LIST_DCN4_01_COMMON(uint32_t); -}; - -struct dcn10_stream_encoder { - struct stream_encoder base; - const struct dcn10_stream_enc_registers *regs; - const struct dcn10_stream_encoder_shift *se_shift; - const struct dcn10_stream_encoder_mask *se_mask; -}; - -void dcn10_stream_encoder_construct( - struct dcn10_stream_encoder *enc1, - struct dc_context *ctx, - struct dc_bios *bp, - enum engine_id eng_id, - const struct dcn10_stream_enc_registers *regs, - const struct dcn10_stream_encoder_shift *se_shift, - const struct dcn10_stream_encoder_mask *se_mask); - -void enc1_update_generic_info_packet( - struct dcn10_stream_encoder *enc1, - uint32_t packet_index, - const struct dc_info_packet *info_packet); - -void enc1_stream_encoder_dp_set_stream_attribute( - struct stream_encoder *enc, - struct dc_crtc_timing *crtc_timing, - enum dc_color_space output_color_space, - bool use_vsc_sdp_for_colorimetry, - uint32_t enable_sdp_splitting); - -void enc1_stream_encoder_hdmi_set_stream_attribute( - struct stream_encoder *enc, - struct dc_crtc_timing *crtc_timing, - int actual_pix_clk_khz, - bool enable_audio); - -void enc1_stream_encoder_dvi_set_stream_attribute( - struct stream_encoder *enc, - struct dc_crtc_timing *crtc_timing, - bool is_dual_link); - -void enc1_stream_encoder_set_throttled_vcp_size( - struct stream_encoder *enc, - struct fixed31_32 avg_time_slots_per_mtp); - -void enc1_stream_encoder_update_dp_info_packets( - struct stream_encoder *enc, - const struct encoder_info_frame *info_frame); - -void enc1_stream_encoder_send_immediate_sdp_message( - struct stream_encoder *enc, - const uint8_t *custom_sdp_message, - unsigned int sdp_message_size); - -void enc1_stream_encoder_stop_dp_info_packets( - struct stream_encoder *enc); - -void enc1_stream_encoder_dp_blank( - struct dc_link *link, - struct stream_encoder *enc); - -void enc1_stream_encoder_dp_unblank( - struct dc_link *link, - struct stream_encoder *enc, - const struct encoder_unblank_param *param); - -void enc1_setup_stereo_sync( - struct stream_encoder *enc, - int tg_inst, bool enable); - -void enc1_stream_encoder_set_avmute( - struct stream_encoder *enc, - bool enable); - -void enc1_se_audio_mute_control( - struct stream_encoder *enc, - bool mute); - -void enc1_se_dp_audio_setup( - struct stream_encoder *enc, - unsigned int az_inst, - struct audio_info *info); - -void enc1_se_dp_audio_enable( - struct stream_encoder *enc); - -void enc1_se_dp_audio_disable( - struct stream_encoder *enc); - -void enc1_se_hdmi_audio_setup( - struct stream_encoder *enc, - unsigned int az_inst, - struct audio_info *info, - struct audio_crtc_info *audio_crtc_info); - -void enc1_se_hdmi_audio_disable( - struct stream_encoder *enc); - -void enc1_dig_connect_to_otg( - struct stream_encoder *enc, - int tg_inst); - -unsigned int enc1_dig_source_otg( - struct stream_encoder *enc); - -void enc1_stream_encoder_set_stream_attribute_helper( - struct dcn10_stream_encoder *enc1, - struct dc_crtc_timing *crtc_timing); - -void enc1_se_enable_audio_clock( - struct stream_encoder *enc, - bool enable); - -void enc1_se_enable_dp_audio( - struct stream_encoder *enc); - -void get_audio_clock_info( - enum dc_color_depth color_depth, - uint32_t crtc_pixel_clock_100Hz, - uint32_t actual_pixel_clock_100Hz, - struct audio_clock_info *audio_clock_info); - -void enc1_reset_hdmi_stream_attribute( - struct stream_encoder *enc); - -bool enc1_stream_encoder_dp_get_pixel_format( - struct stream_encoder *enc, - enum dc_pixel_encoding *encoding, - enum dc_color_depth *depth); - -#endif /* __DC_STREAM_ENCODER_DCN10_H__ */ diff --git a/drivers/gpu/drm/amd/display/dc/dcn20/Makefile b/drivers/gpu/drm/amd/display/dc/dcn20/Makefile index 1ca1cbeabbca..b3aeabc4d605 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn20/Makefile +++ b/drivers/gpu/drm/amd/display/dc/dcn20/Makefile @@ -2,7 +2,6 @@ # Copyright © 2019-2024 Advanced Micro Devices, Inc. All rights reserved. DCN20 = dcn20_mpc.o dcn20_opp.o dcn20_mmhubbub.o \ - dcn20_stream_encoder.o dcn20_link_encoder.o \ dcn20_vmid.o dcn20_dwb.o dcn20_dwb_scl.o AMD_DAL_DCN20 = $(addprefix $(AMDDALPATH)/dc/dcn20/,$(DCN20)) diff --git a/drivers/gpu/drm/amd/display/dc/dcn20/dcn20_link_encoder.c b/drivers/gpu/drm/amd/display/dc/dcn20/dcn20_link_encoder.c deleted file mode 100644 index 51a57dae1811..000000000000 --- a/drivers/gpu/drm/amd/display/dc/dcn20/dcn20_link_encoder.c +++ /dev/null @@ -1,502 +0,0 @@ -/* - * Copyright 2012-15 Advanced Micro Devices, Inc. - * - * Permission is hereby granted, free of charge, to any person obtaining a - * copy of this software and associated documentation files (the "Software"), - * to deal in the Software without restriction, including without limitation - * the rights to use, copy, modify, merge, publish, distribute, sublicense, - * and/or sell copies of the Software, and to permit persons to whom the - * Software is furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL - * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR - * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, - * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR - * OTHER DEALINGS IN THE SOFTWARE. - * - * Authors: AMD - * - */ - -#include "reg_helper.h" - -#include "core_types.h" -#include "link_encoder.h" -#include "dcn20_link_encoder.h" -#include "stream_encoder.h" -#include "dc_bios_types.h" - -#include "gpio_service_interface.h" - -#define CTX \ - enc10->base.ctx -#define DC_LOGGER \ - enc10->base.ctx->logger - -#define REG(reg)\ - (enc10->link_regs->reg) - -#undef FN -#define FN(reg_name, field_name) \ - enc10->link_shift->field_name, enc10->link_mask->field_name - -#define IND_REG(index) \ - (enc10->link_regs->index) - -#ifndef MAX -#define MAX(X, Y) ((X) > (Y) ? (X) : (Y)) -#endif -#ifndef MIN -#define MIN(X, Y) ((X) < (Y) ? (X) : (Y)) -#endif - -static struct mpll_cfg dcn2_mpll_cfg[] = { - // RBR - { - .hdmimode_enable = 1, - .ref_range = 3, - .ref_clk_mpllb_div = 2, - .mpllb_ssc_en = 1, - .mpllb_div5_clk_en = 1, - .mpllb_multiplier = 226, - .mpllb_fracn_en = 1, - .mpllb_fracn_quot = 39321, - .mpllb_fracn_rem = 3, - .mpllb_fracn_den = 5, - .mpllb_ssc_up_spread = 0, - .mpllb_ssc_peak = 38221, - .mpllb_ssc_stepsize = 49314, - .mpllb_div_clk_en = 0, - .mpllb_div_multiplier = 0, - .mpllb_hdmi_div = 0, - .mpllb_tx_clk_div = 2, - .tx_vboost_lvl = 4, - .mpllb_pmix_en = 1, - .mpllb_word_div2_en = 0, - .mpllb_ana_v2i = 2, - .mpllb_ana_freq_vco = 2, - .mpllb_ana_cp_int = 7, - .mpllb_ana_cp_prop = 18, - .hdmi_pixel_clk_div = 0, - }, - // HBR - { - .hdmimode_enable = 1, - .ref_range = 3, - .ref_clk_mpllb_div = 2, - .mpllb_ssc_en = 1, - .mpllb_div5_clk_en = 1, - .mpllb_multiplier = 184, - .mpllb_fracn_en = 0, - .mpllb_fracn_quot = 0, - .mpllb_fracn_rem = 0, - .mpllb_fracn_den = 1, - .mpllb_ssc_up_spread = 0, - .mpllb_ssc_peak = 31850, - .mpllb_ssc_stepsize = 41095, - .mpllb_div_clk_en = 0, - .mpllb_div_multiplier = 0, - .mpllb_hdmi_div = 0, - .mpllb_tx_clk_div = 1, - .tx_vboost_lvl = 4, - .mpllb_pmix_en = 1, - .mpllb_word_div2_en = 0, - .mpllb_ana_v2i = 2, - .mpllb_ana_freq_vco = 3, - .mpllb_ana_cp_int = 7, - .mpllb_ana_cp_prop = 18, - .hdmi_pixel_clk_div = 0, - }, - //HBR2 - { - .hdmimode_enable = 1, - .ref_range = 3, - .ref_clk_mpllb_div = 2, - .mpllb_ssc_en = 1, - .mpllb_div5_clk_en = 1, - .mpllb_multiplier = 184, - .mpllb_fracn_en = 0, - .mpllb_fracn_quot = 0, - .mpllb_fracn_rem = 0, - .mpllb_fracn_den = 1, - .mpllb_ssc_up_spread = 0, - .mpllb_ssc_peak = 31850, - .mpllb_ssc_stepsize = 41095, - .mpllb_div_clk_en = 0, - .mpllb_div_multiplier = 0, - .mpllb_hdmi_div = 0, - .mpllb_tx_clk_div = 0, - .tx_vboost_lvl = 4, - .mpllb_pmix_en = 1, - .mpllb_word_div2_en = 0, - .mpllb_ana_v2i = 2, - .mpllb_ana_freq_vco = 3, - .mpllb_ana_cp_int = 7, - .mpllb_ana_cp_prop = 18, - .hdmi_pixel_clk_div = 0, - }, - //HBR3 - { - .hdmimode_enable = 1, - .ref_range = 3, - .ref_clk_mpllb_div = 2, - .mpllb_ssc_en = 1, - .mpllb_div5_clk_en = 1, - .mpllb_multiplier = 292, - .mpllb_fracn_en = 0, - .mpllb_fracn_quot = 0, - .mpllb_fracn_rem = 0, - .mpllb_fracn_den = 1, - .mpllb_ssc_up_spread = 0, - .mpllb_ssc_peak = 47776, - .mpllb_ssc_stepsize = 61642, - .mpllb_div_clk_en = 0, - .mpllb_div_multiplier = 0, - .mpllb_hdmi_div = 0, - .mpllb_tx_clk_div = 0, - .tx_vboost_lvl = 4, - .mpllb_pmix_en = 1, - .mpllb_word_div2_en = 0, - .mpllb_ana_v2i = 2, - .mpllb_ana_freq_vco = 0, - .mpllb_ana_cp_int = 7, - .mpllb_ana_cp_prop = 18, - .hdmi_pixel_clk_div = 0, - }, -}; - -void enc2_fec_set_enable(struct link_encoder *enc, bool enable) -{ - struct dcn10_link_encoder *enc10 = TO_DCN10_LINK_ENC(enc); - DC_LOG_DSC("%s FEC at link encoder inst %d", - enable ? "Enabling" : "Disabling", enc->id.enum_id); - REG_UPDATE(DP_DPHY_CNTL, DPHY_FEC_EN, enable); -} - -void enc2_fec_set_ready(struct link_encoder *enc, bool ready) -{ - struct dcn10_link_encoder *enc10 = TO_DCN10_LINK_ENC(enc); - - REG_UPDATE(DP_DPHY_CNTL, DPHY_FEC_READY_SHADOW, ready); -} - -bool enc2_fec_is_active(struct link_encoder *enc) -{ - uint32_t active = 0; - struct dcn10_link_encoder *enc10 = TO_DCN10_LINK_ENC(enc); - - REG_GET(DP_DPHY_CNTL, DPHY_FEC_ACTIVE_STATUS, &active); - - return (active != 0); -} - -/* this function reads dsc related register fields to be logged later in dcn10_log_hw_state - * into a dcn_dsc_state struct. - */ -void link_enc2_read_state(struct link_encoder *enc, struct link_enc_state *s) -{ - struct dcn10_link_encoder *enc10 = TO_DCN10_LINK_ENC(enc); - - REG_GET(DP_DPHY_CNTL, DPHY_FEC_EN, &s->dphy_fec_en); - REG_GET(DP_DPHY_CNTL, DPHY_FEC_READY_SHADOW, &s->dphy_fec_ready_shadow); - REG_GET(DP_DPHY_CNTL, DPHY_FEC_ACTIVE_STATUS, &s->dphy_fec_active_status); - REG_GET(DP_LINK_CNTL, DP_LINK_TRAINING_COMPLETE, &s->dp_link_training_complete); -} - -static bool update_cfg_data( - struct dcn10_link_encoder *enc10, - const struct dc_link_settings *link_settings, - struct dpcssys_phy_seq_cfg *cfg) -{ - int i; - - cfg->load_sram_fw = false; - - for (i = 0; i < link_settings->lane_count; i++) - cfg->lane_en[i] = true; - - switch (link_settings->link_rate) { - case LINK_RATE_LOW: - cfg->mpll_cfg = dcn2_mpll_cfg[0]; - break; - case LINK_RATE_HIGH: - cfg->mpll_cfg = dcn2_mpll_cfg[1]; - break; - case LINK_RATE_HIGH2: - cfg->mpll_cfg = dcn2_mpll_cfg[2]; - break; - case LINK_RATE_HIGH3: - cfg->mpll_cfg = dcn2_mpll_cfg[3]; - break; - default: - DC_LOG_ERROR("%s: No supported link rate found %X!\n", - __func__, link_settings->link_rate); - return false; - } - - return true; -} - -void dcn20_link_encoder_enable_dp_output( - struct link_encoder *enc, - const struct dc_link_settings *link_settings, - enum clock_source_id clock_source) -{ - struct dcn10_link_encoder *enc10 = TO_DCN10_LINK_ENC(enc); - struct dcn20_link_encoder *enc20 = (struct dcn20_link_encoder *) enc10; - struct dpcssys_phy_seq_cfg *cfg = &enc20->phy_seq_cfg; - - if (!enc->ctx->dc->debug.avoid_vbios_exec_table) { - dcn10_link_encoder_enable_dp_output(enc, link_settings, clock_source); - return; - } - - if (!update_cfg_data(enc10, link_settings, cfg)) - return; - - enc1_configure_encoder(enc10, link_settings); - - dcn10_link_encoder_setup(enc, SIGNAL_TYPE_DISPLAY_PORT); - -} - -void dcn20_link_encoder_get_max_link_cap(struct link_encoder *enc, - struct dc_link_settings *link_settings) -{ - struct dcn10_link_encoder *enc10 = TO_DCN10_LINK_ENC(enc); - uint32_t is_in_usb_c_dp4_mode = 0; - - dcn10_link_encoder_get_max_link_cap(enc, link_settings); - - /* in usb c dp2 mode, max lane count is 2 */ - if (enc->funcs->is_in_alt_mode && enc->funcs->is_in_alt_mode(enc)) { - REG_GET(RDPCSTX_PHY_CNTL6, RDPCS_PHY_DPALT_DP4, &is_in_usb_c_dp4_mode); - if (!is_in_usb_c_dp4_mode) - link_settings->lane_count = MIN(LANE_COUNT_TWO, link_settings->lane_count); - } - -} - -bool dcn20_link_encoder_is_in_alt_mode(struct link_encoder *enc) -{ - struct dcn10_link_encoder *enc10 = TO_DCN10_LINK_ENC(enc); - uint32_t dp_alt_mode_disable = 0; - bool is_usb_c_alt_mode = false; - - if (enc->features.flags.bits.DP_IS_USB_C) { - /* if value == 1 alt mode is disabled, otherwise it is enabled */ - REG_GET(RDPCSTX_PHY_CNTL6, RDPCS_PHY_DPALT_DISABLE, &dp_alt_mode_disable); - is_usb_c_alt_mode = (dp_alt_mode_disable == 0); - } - - return is_usb_c_alt_mode; -} - -#define AUX_REG(reg)\ - (enc10->aux_regs->reg) - -#define AUX_REG_READ(reg_name) \ - dm_read_reg(CTX, AUX_REG(reg_name)) - -#define AUX_REG_WRITE(reg_name, val) \ - dm_write_reg(CTX, AUX_REG(reg_name), val) -void enc2_hw_init(struct link_encoder *enc) -{ - struct dcn10_link_encoder *enc10 = TO_DCN10_LINK_ENC(enc); -/* - 00 - DP_AUX_DPHY_RX_DETECTION_THRESHOLD__1to2 : 1/2 - 01 - DP_AUX_DPHY_RX_DETECTION_THRESHOLD__3to4 : 3/4 - 02 - DP_AUX_DPHY_RX_DETECTION_THRESHOLD__7to8 : 7/8 - 03 - DP_AUX_DPHY_RX_DETECTION_THRESHOLD__15to16 : 15/16 - 04 - DP_AUX_DPHY_RX_DETECTION_THRESHOLD__31to32 : 31/32 - 05 - DP_AUX_DPHY_RX_DETECTION_THRESHOLD__63to64 : 63/64 - 06 - DP_AUX_DPHY_RX_DETECTION_THRESHOLD__127to128 : 127/128 - 07 - DP_AUX_DPHY_RX_DETECTION_THRESHOLD__255to256 : 255/256 -*/ - -/* - AUX_REG_UPDATE_5(AUX_DPHY_RX_CONTROL0, - AUX_RX_START_WINDOW = 1 [6:4] - AUX_RX_RECEIVE_WINDOW = 1 default is 2 [10:8] - AUX_RX_HALF_SYM_DETECT_LEN = 1 [13:12] default is 1 - AUX_RX_TRANSITION_FILTER_EN = 1 [16] default is 1 - AUX_RX_ALLOW_BELOW_THRESHOLD_PHASE_DETECT [17] is 0 default is 0 - AUX_RX_ALLOW_BELOW_THRESHOLD_START [18] is 1 default is 1 - AUX_RX_ALLOW_BELOW_THRESHOLD_STOP [19] is 1 default is 1 - AUX_RX_PHASE_DETECT_LEN, [21,20] = 0x3 default is 3 - AUX_RX_DETECTION_THRESHOLD [30:28] = 1 -*/ - if (enc->ctx->dc_bios->golden_table.dc_golden_table_ver > 0) { - AUX_REG_WRITE(AUX_DPHY_RX_CONTROL0, enc->ctx->dc_bios->golden_table.aux_dphy_rx_control0_val); - - AUX_REG_WRITE(AUX_DPHY_TX_CONTROL, enc->ctx->dc_bios->golden_table.aux_dphy_tx_control_val); - - AUX_REG_WRITE(AUX_DPHY_RX_CONTROL1, enc->ctx->dc_bios->golden_table.aux_dphy_rx_control1_val); - } else { - AUX_REG_WRITE(AUX_DPHY_RX_CONTROL0, 0x103d1110); - - AUX_REG_WRITE(AUX_DPHY_TX_CONTROL, 0x21c7a); - } - - //AUX_DPHY_TX_REF_CONTROL'AUX_TX_REF_DIV HW default is 0x32; - // Set AUX_TX_REF_DIV Divider to generate 2 MHz reference from refclk - // 27MHz -> 0xd - // 100MHz -> 0x32 - // 48MHz -> 0x18 - - // Set TMDS_CTL0 to 1. This is a legacy setting. - REG_UPDATE(TMDS_CTL_BITS, TMDS_CTL0, 1); - - dcn10_aux_initialize(enc10); -} - -static const struct link_encoder_funcs dcn20_link_enc_funcs = { - .read_state = link_enc2_read_state, - .validate_output_with_stream = - dcn10_link_encoder_validate_output_with_stream, - .hw_init = enc2_hw_init, - .setup = dcn10_link_encoder_setup, - .enable_tmds_output = dcn10_link_encoder_enable_tmds_output_with_clk_pattern_wa, - .enable_dp_output = dcn20_link_encoder_enable_dp_output, - .enable_dp_mst_output = dcn10_link_encoder_enable_dp_mst_output, - .disable_output = dcn10_link_encoder_disable_output, - .dp_set_lane_settings = dcn10_link_encoder_dp_set_lane_settings, - .dp_set_phy_pattern = dcn10_link_encoder_dp_set_phy_pattern, - .update_mst_stream_allocation_table = - dcn10_link_encoder_update_mst_stream_allocation_table, - .psr_program_dp_dphy_fast_training = - dcn10_psr_program_dp_dphy_fast_training, - .psr_program_secondary_packet = dcn10_psr_program_secondary_packet, - .connect_dig_be_to_fe = dcn10_link_encoder_connect_dig_be_to_fe, - .enable_hpd = dcn10_link_encoder_enable_hpd, - .disable_hpd = dcn10_link_encoder_disable_hpd, - .is_dig_enabled = dcn10_is_dig_enabled, - .destroy = dcn10_link_encoder_destroy, - .fec_set_enable = enc2_fec_set_enable, - .fec_set_ready = enc2_fec_set_ready, - .fec_is_active = enc2_fec_is_active, - .get_dig_mode = dcn10_get_dig_mode, - .get_dig_frontend = dcn10_get_dig_frontend, - .is_in_alt_mode = dcn20_link_encoder_is_in_alt_mode, - .get_max_link_cap = dcn20_link_encoder_get_max_link_cap, -}; - -void dcn20_link_encoder_construct( - struct dcn20_link_encoder *enc20, - const struct encoder_init_data *init_data, - const struct encoder_feature_support *enc_features, - const struct dcn10_link_enc_registers *link_regs, - const struct dcn10_link_enc_aux_registers *aux_regs, - const struct dcn10_link_enc_hpd_registers *hpd_regs, - const struct dcn10_link_enc_shift *link_shift, - const struct dcn10_link_enc_mask *link_mask) -{ - struct bp_encoder_cap_info bp_cap_info = {0}; - const struct dc_vbios_funcs *bp_funcs = init_data->ctx->dc_bios->funcs; - enum bp_result result = BP_RESULT_OK; - struct dcn10_link_encoder *enc10 = &enc20->enc10; - - enc10->base.funcs = &dcn20_link_enc_funcs; - enc10->base.ctx = init_data->ctx; - enc10->base.id = init_data->encoder; - - enc10->base.hpd_source = init_data->hpd_source; - enc10->base.connector = init_data->connector; - - enc10->base.preferred_engine = ENGINE_ID_UNKNOWN; - - enc10->base.features = *enc_features; - - enc10->base.transmitter = init_data->transmitter; - - /* set the flag to indicate whether driver poll the I2C data pin - * while doing the DP sink detect - */ - -/* if (dal_adapter_service_is_feature_supported(as, - FEATURE_DP_SINK_DETECT_POLL_DATA_PIN)) - enc10->base.features.flags.bits. - DP_SINK_DETECT_POLL_DATA_PIN = true;*/ - - enc10->base.output_signals = - SIGNAL_TYPE_DVI_SINGLE_LINK | - SIGNAL_TYPE_DVI_DUAL_LINK | - SIGNAL_TYPE_LVDS | - SIGNAL_TYPE_DISPLAY_PORT | - SIGNAL_TYPE_DISPLAY_PORT_MST | - SIGNAL_TYPE_EDP | - SIGNAL_TYPE_HDMI_TYPE_A; - - /* For DCE 8.0 and 8.1, by design, UNIPHY is hardwired to DIG_BE. - * SW always assign DIG_FE 1:1 mapped to DIG_FE for non-MST UNIPHY. - * SW assign DIG_FE to non-MST UNIPHY first and MST last. So prefer - * DIG is per UNIPHY and used by SST DP, eDP, HDMI, DVI and LVDS. - * Prefer DIG assignment is decided by board design. - * For DCE 8.0, there are only max 6 UNIPHYs, we assume board design - * and VBIOS will filter out 7 UNIPHY for DCE 8.0. - * By this, adding DIGG should not hurt DCE 8.0. - * This will let DCE 8.1 share DCE 8.0 as much as possible - */ - - enc10->link_regs = link_regs; - enc10->aux_regs = aux_regs; - enc10->hpd_regs = hpd_regs; - enc10->link_shift = link_shift; - enc10->link_mask = link_mask; - - switch (enc10->base.transmitter) { - case TRANSMITTER_UNIPHY_A: - enc10->base.preferred_engine = ENGINE_ID_DIGA; - break; - case TRANSMITTER_UNIPHY_B: - enc10->base.preferred_engine = ENGINE_ID_DIGB; - break; - case TRANSMITTER_UNIPHY_C: - enc10->base.preferred_engine = ENGINE_ID_DIGC; - break; - case TRANSMITTER_UNIPHY_D: - enc10->base.preferred_engine = ENGINE_ID_DIGD; - break; - case TRANSMITTER_UNIPHY_E: - enc10->base.preferred_engine = ENGINE_ID_DIGE; - break; - case TRANSMITTER_UNIPHY_F: - enc10->base.preferred_engine = ENGINE_ID_DIGF; - break; - case TRANSMITTER_UNIPHY_G: - enc10->base.preferred_engine = ENGINE_ID_DIGG; - break; - default: - ASSERT_CRITICAL(false); - enc10->base.preferred_engine = ENGINE_ID_UNKNOWN; - } - - /* default to one to mirror Windows behavior */ - enc10->base.features.flags.bits.HDMI_6GB_EN = 1; - - result = bp_funcs->get_encoder_cap_info(enc10->base.ctx->dc_bios, - enc10->base.id, &bp_cap_info); - - /* Override features with DCE-specific values */ - if (result == BP_RESULT_OK) { - enc10->base.features.flags.bits.IS_HBR2_CAPABLE = - bp_cap_info.DP_HBR2_EN; - enc10->base.features.flags.bits.IS_HBR3_CAPABLE = - bp_cap_info.DP_HBR3_EN; - enc10->base.features.flags.bits.HDMI_6GB_EN = bp_cap_info.HDMI_6GB_EN; - enc10->base.features.flags.bits.DP_IS_USB_C = - bp_cap_info.DP_IS_USB_C; - } else { - DC_LOG_WARNING("%s: Failed to get encoder_cap_info from VBIOS with error code %d!\n", - __func__, - result); - } - if (enc10->base.ctx->dc->debug.hdmi20_disable) { - enc10->base.features.flags.bits.HDMI_6GB_EN = 0; - } -} diff --git a/drivers/gpu/drm/amd/display/dc/dcn20/dcn20_link_encoder.h b/drivers/gpu/drm/amd/display/dc/dcn20/dcn20_link_encoder.h deleted file mode 100644 index 762c579fcb44..000000000000 --- a/drivers/gpu/drm/amd/display/dc/dcn20/dcn20_link_encoder.h +++ /dev/null @@ -1,366 +0,0 @@ -/* - * Copyright 2012-15 Advanced Micro Devices, Inc. - * - * Permission is hereby granted, free of charge, to any person obtaining a - * copy of this software and associated documentation files (the "Software"), - * to deal in the Software without restriction, including without limitation - * the rights to use, copy, modify, merge, publish, distribute, sublicense, - * and/or sell copies of the Software, and to permit persons to whom the - * Software is furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL - * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR - * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, - * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR - * OTHER DEALINGS IN THE SOFTWARE. - * - * Authors: AMD - * - */ - -#ifndef __DC_LINK_ENCODER__DCN20_H__ -#define __DC_LINK_ENCODER__DCN20_H__ - -#include "dcn10/dcn10_link_encoder.h" - -#define DCN2_AUX_REG_LIST(id)\ - AUX_REG_LIST(id), \ - SRI(AUX_DPHY_TX_CONTROL, DP_AUX, id) - -#define UNIPHY_MASK_SH_LIST(mask_sh)\ - LE_SF(SYMCLKA_CLOCK_ENABLE, SYMCLKA_CLOCK_ENABLE, mask_sh),\ - LE_SF(UNIPHYA_CHANNEL_XBAR_CNTL, UNIPHY_LINK_ENABLE, mask_sh),\ - LE_SF(UNIPHYA_CHANNEL_XBAR_CNTL, UNIPHY_CHANNEL0_XBAR_SOURCE, mask_sh),\ - LE_SF(UNIPHYA_CHANNEL_XBAR_CNTL, UNIPHY_CHANNEL1_XBAR_SOURCE, mask_sh),\ - LE_SF(UNIPHYA_CHANNEL_XBAR_CNTL, UNIPHY_CHANNEL2_XBAR_SOURCE, mask_sh),\ - LE_SF(UNIPHYA_CHANNEL_XBAR_CNTL, UNIPHY_CHANNEL3_XBAR_SOURCE, mask_sh) - -#define DPCS_MASK_SH_LIST(mask_sh)\ - LE_SF(RDPCSTX0_RDPCSTX_PHY_CNTL3, RDPCS_PHY_DP_TX0_CLK_RDY, mask_sh),\ - LE_SF(RDPCSTX0_RDPCSTX_PHY_CNTL3, RDPCS_PHY_DP_TX0_DATA_EN, mask_sh),\ - LE_SF(RDPCSTX0_RDPCSTX_PHY_CNTL3, RDPCS_PHY_DP_TX1_CLK_RDY, mask_sh),\ - LE_SF(RDPCSTX0_RDPCSTX_PHY_CNTL3, RDPCS_PHY_DP_TX1_DATA_EN, mask_sh),\ - LE_SF(RDPCSTX0_RDPCSTX_PHY_CNTL3, RDPCS_PHY_DP_TX2_CLK_RDY, mask_sh),\ - LE_SF(RDPCSTX0_RDPCSTX_PHY_CNTL3, RDPCS_PHY_DP_TX2_DATA_EN, mask_sh),\ - LE_SF(RDPCSTX0_RDPCSTX_PHY_CNTL3, RDPCS_PHY_DP_TX3_CLK_RDY, mask_sh),\ - LE_SF(RDPCSTX0_RDPCSTX_PHY_CNTL3, RDPCS_PHY_DP_TX3_DATA_EN, mask_sh),\ - LE_SF(RDPCSTX0_RDPCSTX_PHY_CNTL4, RDPCS_PHY_DP_TX0_TERM_CTRL, mask_sh),\ - LE_SF(RDPCSTX0_RDPCSTX_PHY_CNTL4, RDPCS_PHY_DP_TX1_TERM_CTRL, mask_sh),\ - LE_SF(RDPCSTX0_RDPCSTX_PHY_CNTL4, RDPCS_PHY_DP_TX2_TERM_CTRL, mask_sh),\ - LE_SF(RDPCSTX0_RDPCSTX_PHY_CNTL4, RDPCS_PHY_DP_TX3_TERM_CTRL, mask_sh),\ - LE_SF(RDPCSTX0_RDPCSTX_PHY_CNTL11, RDPCS_PHY_DP_MPLLB_MULTIPLIER, mask_sh),\ - LE_SF(RDPCSTX0_RDPCSTX_PHY_CNTL5, RDPCS_PHY_DP_TX0_WIDTH, mask_sh),\ - LE_SF(RDPCSTX0_RDPCSTX_PHY_CNTL5, RDPCS_PHY_DP_TX0_RATE, mask_sh),\ - LE_SF(RDPCSTX0_RDPCSTX_PHY_CNTL5, RDPCS_PHY_DP_TX1_WIDTH, mask_sh),\ - LE_SF(RDPCSTX0_RDPCSTX_PHY_CNTL5, RDPCS_PHY_DP_TX1_RATE, mask_sh),\ - LE_SF(RDPCSTX0_RDPCSTX_PHY_CNTL6, RDPCS_PHY_DP_TX2_PSTATE, mask_sh),\ - LE_SF(RDPCSTX0_RDPCSTX_PHY_CNTL6, RDPCS_PHY_DP_TX3_PSTATE, mask_sh),\ - LE_SF(RDPCSTX0_RDPCSTX_PHY_CNTL6, RDPCS_PHY_DP_TX2_MPLL_EN, mask_sh),\ - LE_SF(RDPCSTX0_RDPCSTX_PHY_CNTL6, RDPCS_PHY_DP_TX3_MPLL_EN, mask_sh),\ - LE_SF(RDPCSTX0_RDPCSTX_PHY_CNTL7, RDPCS_PHY_DP_MPLLB_FRACN_QUOT, mask_sh),\ - LE_SF(RDPCSTX0_RDPCSTX_PHY_CNTL7, RDPCS_PHY_DP_MPLLB_FRACN_DEN, mask_sh),\ - LE_SF(RDPCSTX0_RDPCSTX_PHY_CNTL8, RDPCS_PHY_DP_MPLLB_SSC_PEAK, mask_sh),\ - LE_SF(RDPCSTX0_RDPCSTX_PHY_CNTL9, RDPCS_PHY_DP_MPLLB_SSC_UP_SPREAD, mask_sh),\ - LE_SF(RDPCSTX0_RDPCSTX_PHY_CNTL9, RDPCS_PHY_DP_MPLLB_SSC_STEPSIZE, mask_sh),\ - LE_SF(RDPCSTX0_RDPCSTX_PHY_CNTL10, RDPCS_PHY_DP_MPLLB_FRACN_REM, mask_sh),\ - LE_SF(RDPCSTX0_RDPCSTX_PHY_CNTL11, RDPCS_PHY_DP_REF_CLK_MPLLB_DIV, mask_sh),\ - LE_SF(RDPCSTX0_RDPCSTX_PHY_CNTL11, RDPCS_PHY_HDMI_MPLLB_HDMI_DIV, mask_sh),\ - LE_SF(RDPCSTX0_RDPCSTX_PHY_CNTL12, RDPCS_PHY_DP_MPLLB_SSC_EN, mask_sh),\ - LE_SF(RDPCSTX0_RDPCSTX_PHY_CNTL12, RDPCS_PHY_DP_MPLLB_DIV5_CLK_EN, mask_sh),\ - LE_SF(RDPCSTX0_RDPCSTX_PHY_CNTL12, RDPCS_PHY_DP_MPLLB_TX_CLK_DIV, mask_sh),\ - LE_SF(RDPCSTX0_RDPCSTX_PHY_CNTL12, RDPCS_PHY_DP_MPLLB_WORD_DIV2_EN, mask_sh),\ - LE_SF(RDPCSTX0_RDPCSTX_PHY_CNTL12, RDPCS_PHY_DP_MPLLB_STATE, mask_sh),\ - LE_SF(RDPCSTX0_RDPCSTX_PHY_CNTL13, RDPCS_PHY_DP_MPLLB_DIV_CLK_EN, mask_sh),\ - LE_SF(RDPCSTX0_RDPCSTX_PHY_CNTL13, RDPCS_PHY_DP_MPLLB_DIV_MULTIPLIER, mask_sh),\ - LE_SF(RDPCSTX0_RDPCSTX_PHY_CNTL14, RDPCS_PHY_DP_MPLLB_FRACN_EN, mask_sh),\ - LE_SF(RDPCSTX0_RDPCSTX_PHY_CNTL14, RDPCS_PHY_DP_MPLLB_PMIX_EN, mask_sh),\ - LE_SF(RDPCSTX0_RDPCSTX_CNTL, RDPCS_TX_FIFO_LANE0_EN, mask_sh),\ - LE_SF(RDPCSTX0_RDPCSTX_CNTL, RDPCS_TX_FIFO_LANE1_EN, mask_sh),\ - LE_SF(RDPCSTX0_RDPCSTX_CNTL, RDPCS_TX_FIFO_LANE2_EN, mask_sh),\ - LE_SF(RDPCSTX0_RDPCSTX_CNTL, RDPCS_TX_FIFO_LANE3_EN, mask_sh),\ - LE_SF(RDPCSTX0_RDPCSTX_CNTL, RDPCS_TX_FIFO_EN, mask_sh),\ - LE_SF(RDPCSTX0_RDPCSTX_CNTL, RDPCS_TX_FIFO_RD_START_DELAY, mask_sh),\ - LE_SF(RDPCSTX0_RDPCSTX_CLOCK_CNTL, RDPCS_EXT_REFCLK_EN, mask_sh),\ - LE_SF(RDPCSTX0_RDPCSTX_CLOCK_CNTL, RDPCS_SRAMCLK_BYPASS, mask_sh),\ - LE_SF(RDPCSTX0_RDPCSTX_CLOCK_CNTL, RDPCS_SRAMCLK_EN, mask_sh),\ - LE_SF(RDPCSTX0_RDPCSTX_CLOCK_CNTL, RDPCS_SRAMCLK_CLOCK_ON, mask_sh),\ - LE_SF(RDPCSTX0_RDPCSTX_CLOCK_CNTL, RDPCS_SYMCLK_DIV2_CLOCK_ON, mask_sh),\ - LE_SF(RDPCSTX0_RDPCSTX_CLOCK_CNTL, RDPCS_SYMCLK_DIV2_GATE_DIS, mask_sh),\ - LE_SF(RDPCSTX0_RDPCSTX_CLOCK_CNTL, RDPCS_SYMCLK_DIV2_EN, mask_sh),\ - LE_SF(RDPCSTX0_RDPCSTX_PHY_CNTL3, RDPCS_PHY_DP_TX0_DISABLE, mask_sh),\ - LE_SF(RDPCSTX0_RDPCSTX_PHY_CNTL3, RDPCS_PHY_DP_TX1_DISABLE, mask_sh),\ - LE_SF(RDPCSTX0_RDPCSTX_PHY_CNTL3, RDPCS_PHY_DP_TX2_DISABLE, mask_sh),\ - LE_SF(RDPCSTX0_RDPCSTX_PHY_CNTL3, RDPCS_PHY_DP_TX3_DISABLE, mask_sh),\ - LE_SF(RDPCSTX0_RDPCSTX_PHY_CNTL3, RDPCS_PHY_DP_TX0_REQ, mask_sh),\ - LE_SF(RDPCSTX0_RDPCSTX_PHY_CNTL3, RDPCS_PHY_DP_TX1_REQ, mask_sh),\ - LE_SF(RDPCSTX0_RDPCSTX_PHY_CNTL3, RDPCS_PHY_DP_TX2_REQ, mask_sh),\ - LE_SF(RDPCSTX0_RDPCSTX_PHY_CNTL3, RDPCS_PHY_DP_TX3_REQ, mask_sh),\ - LE_SF(RDPCSTX0_RDPCSTX_PHY_CNTL3, RDPCS_PHY_DP_TX0_ACK, mask_sh),\ - LE_SF(RDPCSTX0_RDPCSTX_PHY_CNTL3, RDPCS_PHY_DP_TX1_ACK, mask_sh),\ - LE_SF(RDPCSTX0_RDPCSTX_PHY_CNTL3, RDPCS_PHY_DP_TX2_ACK, mask_sh),\ - LE_SF(RDPCSTX0_RDPCSTX_PHY_CNTL3, RDPCS_PHY_DP_TX3_ACK, mask_sh),\ - LE_SF(RDPCSTX0_RDPCSTX_PHY_CNTL3, RDPCS_PHY_DP_TX0_RESET, mask_sh),\ - LE_SF(RDPCSTX0_RDPCSTX_PHY_CNTL3, RDPCS_PHY_DP_TX1_RESET, mask_sh),\ - LE_SF(RDPCSTX0_RDPCSTX_PHY_CNTL3, RDPCS_PHY_DP_TX2_RESET, mask_sh),\ - LE_SF(RDPCSTX0_RDPCSTX_PHY_CNTL3, RDPCS_PHY_DP_TX3_RESET, mask_sh),\ - LE_SF(RDPCSTX0_RDPCSTX_PHY_CNTL0, RDPCS_PHY_RESET, mask_sh),\ - LE_SF(RDPCSTX0_RDPCSTX_PHY_CNTL0, RDPCS_PHY_CR_MUX_SEL, mask_sh),\ - LE_SF(RDPCSTX0_RDPCSTX_PHY_CNTL0, RDPCS_PHY_REF_RANGE, mask_sh),\ - LE_SF(RDPCSTX0_RDPCSTX_PHY_CNTL0, RDPCS_SRAM_BYPASS, mask_sh),\ - LE_SF(RDPCSTX0_RDPCSTX_PHY_CNTL0, RDPCS_SRAM_EXT_LD_DONE, mask_sh),\ - LE_SF(RDPCSTX0_RDPCSTX_PHY_CNTL0, RDPCS_PHY_HDMIMODE_ENABLE, mask_sh),\ - LE_SF(RDPCSTX0_RDPCSTX_PHY_CNTL0, RDPCS_SRAM_INIT_DONE, mask_sh),\ - LE_SF(RDPCSTX0_RDPCSTX_PHY_CNTL2, RDPCS_PHY_DP4_POR, mask_sh),\ - LE_SF(RDPCSTX0_RDPCSTX_PLL_UPDATE_DATA, RDPCS_PLL_UPDATE_DATA, mask_sh),\ - LE_SF(RDPCSTX0_RDPCSTX_INTERRUPT_CONTROL, RDPCS_REG_FIFO_ERROR_MASK, mask_sh),\ - LE_SF(RDPCSTX0_RDPCSTX_INTERRUPT_CONTROL, RDPCS_TX_FIFO_ERROR_MASK, mask_sh),\ - LE_SF(RDPCSTX0_RDPCSTX_INTERRUPT_CONTROL, RDPCS_DPALT_DISABLE_TOGGLE_MASK, mask_sh),\ - LE_SF(RDPCSTX0_RDPCSTX_INTERRUPT_CONTROL, RDPCS_DPALT_4LANE_TOGGLE_MASK, mask_sh),\ - LE_SF(RDPCSTX0_RDPCS_TX_CR_ADDR, RDPCS_TX_CR_ADDR, mask_sh),\ - LE_SF(RDPCSTX0_RDPCS_TX_CR_DATA, RDPCS_TX_CR_DATA, mask_sh),\ - LE_SF(RDPCSTX0_RDPCSTX_PHY_FUSE0, RDPCS_PHY_DP_MPLLB_V2I, mask_sh),\ - LE_SF(RDPCSTX0_RDPCSTX_PHY_FUSE0, RDPCS_PHY_DP_TX0_EQ_MAIN, mask_sh),\ - LE_SF(RDPCSTX0_RDPCSTX_PHY_FUSE0, RDPCS_PHY_DP_TX0_EQ_PRE, mask_sh),\ - LE_SF(RDPCSTX0_RDPCSTX_PHY_FUSE0, RDPCS_PHY_DP_TX0_EQ_POST, mask_sh),\ - LE_SF(RDPCSTX0_RDPCSTX_PHY_FUSE0, RDPCS_PHY_DP_MPLLB_FREQ_VCO, mask_sh),\ - LE_SF(RDPCSTX0_RDPCSTX_PHY_FUSE1, RDPCS_PHY_DP_MPLLB_CP_INT, mask_sh),\ - LE_SF(RDPCSTX0_RDPCSTX_PHY_FUSE1, RDPCS_PHY_DP_MPLLB_CP_PROP, mask_sh),\ - LE_SF(RDPCSTX0_RDPCSTX_PHY_FUSE1, RDPCS_PHY_DP_TX1_EQ_MAIN, mask_sh),\ - LE_SF(RDPCSTX0_RDPCSTX_PHY_FUSE1, RDPCS_PHY_DP_TX1_EQ_PRE, mask_sh),\ - LE_SF(RDPCSTX0_RDPCSTX_PHY_FUSE1, RDPCS_PHY_DP_TX1_EQ_POST, mask_sh),\ - LE_SF(RDPCSTX0_RDPCSTX_PHY_FUSE2, RDPCS_PHY_DP_TX2_EQ_MAIN, mask_sh),\ - LE_SF(RDPCSTX0_RDPCSTX_PHY_FUSE2, RDPCS_PHY_DP_TX2_EQ_PRE, mask_sh),\ - LE_SF(RDPCSTX0_RDPCSTX_PHY_FUSE2, RDPCS_PHY_DP_TX2_EQ_POST, mask_sh),\ - LE_SF(RDPCSTX0_RDPCSTX_PHY_FUSE3, RDPCS_PHY_DP_TX3_EQ_MAIN, mask_sh),\ - LE_SF(RDPCSTX0_RDPCSTX_PHY_FUSE3, RDPCS_PHY_DCO_FINETUNE, mask_sh),\ - LE_SF(RDPCSTX0_RDPCSTX_PHY_FUSE3, RDPCS_PHY_DCO_RANGE, mask_sh),\ - LE_SF(RDPCSTX0_RDPCSTX_PHY_FUSE3, RDPCS_PHY_DP_TX3_EQ_PRE, mask_sh),\ - LE_SF(RDPCSTX0_RDPCSTX_PHY_FUSE3, RDPCS_PHY_DP_TX3_EQ_POST, mask_sh),\ - LE_SF(DPCSTX0_DPCSTX_TX_CLOCK_CNTL, DPCS_SYMCLK_CLOCK_ON, mask_sh),\ - LE_SF(DPCSTX0_DPCSTX_TX_CLOCK_CNTL, DPCS_SYMCLK_GATE_DIS, mask_sh),\ - LE_SF(DPCSTX0_DPCSTX_TX_CLOCK_CNTL, DPCS_SYMCLK_EN, mask_sh),\ - LE_SF(DPCSTX0_DPCSTX_TX_CNTL, DPCS_TX_DATA_SWAP, mask_sh),\ - LE_SF(DPCSTX0_DPCSTX_TX_CNTL, DPCS_TX_DATA_ORDER_INVERT, mask_sh),\ - LE_SF(DPCSTX0_DPCSTX_TX_CNTL, DPCS_TX_FIFO_EN, mask_sh),\ - LE_SF(DPCSTX0_DPCSTX_TX_CNTL, DPCS_TX_FIFO_RD_START_DELAY, mask_sh),\ - LE_SF(DPCSTX0_DPCSTX_DEBUG_CONFIG, DPCS_DBG_CBUS_DIS, mask_sh) - -#define DPCS_DCN2_MASK_SH_LIST(mask_sh)\ - DPCS_MASK_SH_LIST(mask_sh),\ - LE_SF(RDPCSTX0_RDPCSTX_PHY_RX_LD_VAL, RDPCS_PHY_RX_REF_LD_VAL, mask_sh),\ - LE_SF(RDPCSTX0_RDPCSTX_PHY_RX_LD_VAL, RDPCS_PHY_RX_VCO_LD_VAL, mask_sh),\ - LE_SF(RDPCSTX0_RDPCSTX_PHY_CNTL6, RDPCS_PHY_DPALT_DISABLE_ACK, mask_sh),\ - LE_SF(RDPCSTX0_RDPCSTX_PHY_CNTL6, RDPCS_PHY_DP_TX0_PSTATE, mask_sh),\ - LE_SF(RDPCSTX0_RDPCSTX_PHY_CNTL6, RDPCS_PHY_DP_TX1_PSTATE, mask_sh),\ - LE_SF(RDPCSTX0_RDPCSTX_PHY_CNTL6, RDPCS_PHY_DP_TX0_MPLL_EN, mask_sh),\ - LE_SF(RDPCSTX0_RDPCSTX_PHY_CNTL6, RDPCS_PHY_DP_TX1_MPLL_EN, mask_sh),\ - LE_SF(RDPCSTX0_RDPCSTX_PHY_CNTL6, RDPCS_PHY_DP_REF_CLK_EN, mask_sh),\ - LE_SF(RDPCSTX0_RDPCSTX_PHY_CNTL5, RDPCS_PHY_DP_TX2_WIDTH, mask_sh),\ - LE_SF(RDPCSTX0_RDPCSTX_PHY_CNTL5, RDPCS_PHY_DP_TX2_RATE, mask_sh),\ - LE_SF(RDPCSTX0_RDPCSTX_PHY_CNTL5, RDPCS_PHY_DP_TX3_WIDTH, mask_sh),\ - LE_SF(RDPCSTX0_RDPCSTX_PHY_CNTL5, RDPCS_PHY_DP_TX3_RATE, mask_sh),\ - LE_SF(DCIO_SOFT_RESET, UNIPHYA_SOFT_RESET, mask_sh),\ - LE_SF(DCIO_SOFT_RESET, UNIPHYB_SOFT_RESET, mask_sh),\ - LE_SF(DCIO_SOFT_RESET, UNIPHYC_SOFT_RESET, mask_sh),\ - LE_SF(DCIO_SOFT_RESET, UNIPHYD_SOFT_RESET, mask_sh),\ - LE_SF(DCIO_SOFT_RESET, UNIPHYE_SOFT_RESET, mask_sh),\ - LE_SF(RDPCSTX0_RDPCSTX_PHY_CNTL6, RDPCS_PHY_DPALT_DP4, mask_sh),\ - LE_SF(RDPCSTX0_RDPCSTX_PHY_CNTL6, RDPCS_PHY_DPALT_DISABLE, mask_sh) - -#define LINK_ENCODER_MASK_SH_LIST_DCN20(mask_sh)\ - LINK_ENCODER_MASK_SH_LIST_DCN10(mask_sh),\ - LE_SF(DP0_DP_DPHY_CNTL, DPHY_FEC_EN, mask_sh),\ - LE_SF(DP0_DP_DPHY_CNTL, DPHY_FEC_READY_SHADOW, mask_sh),\ - LE_SF(DP0_DP_DPHY_CNTL, DPHY_FEC_ACTIVE_STATUS, mask_sh),\ - LE_SF(DIG0_DIG_LANE_ENABLE, DIG_LANE0EN, mask_sh),\ - LE_SF(DIG0_DIG_LANE_ENABLE, DIG_LANE1EN, mask_sh),\ - LE_SF(DIG0_DIG_LANE_ENABLE, DIG_LANE2EN, mask_sh),\ - LE_SF(DIG0_DIG_LANE_ENABLE, DIG_LANE3EN, mask_sh),\ - LE_SF(DIG0_DIG_LANE_ENABLE, DIG_CLK_EN, mask_sh),\ - LE_SF(DIG0_TMDS_CTL_BITS, TMDS_CTL0, mask_sh), \ - UNIPHY_MASK_SH_LIST(mask_sh),\ - LE_SF(DP_AUX0_AUX_DPHY_RX_CONTROL0, AUX_RX_START_WINDOW, mask_sh),\ - LE_SF(DP_AUX0_AUX_DPHY_RX_CONTROL0, AUX_RX_HALF_SYM_DETECT_LEN, mask_sh),\ - LE_SF(DP_AUX0_AUX_DPHY_RX_CONTROL0, AUX_RX_TRANSITION_FILTER_EN, mask_sh),\ - LE_SF(DP_AUX0_AUX_DPHY_RX_CONTROL0, AUX_RX_ALLOW_BELOW_THRESHOLD_PHASE_DETECT, mask_sh),\ - LE_SF(DP_AUX0_AUX_DPHY_RX_CONTROL0, AUX_RX_ALLOW_BELOW_THRESHOLD_START, mask_sh),\ - LE_SF(DP_AUX0_AUX_DPHY_RX_CONTROL0, AUX_RX_ALLOW_BELOW_THRESHOLD_STOP, mask_sh),\ - LE_SF(DP_AUX0_AUX_DPHY_RX_CONTROL0, AUX_RX_PHASE_DETECT_LEN, mask_sh),\ - LE_SF(DP_AUX0_AUX_DPHY_RX_CONTROL0, AUX_RX_DETECTION_THRESHOLD, mask_sh), \ - LE_SF(DP_AUX0_AUX_DPHY_TX_CONTROL, AUX_TX_PRECHARGE_LEN, mask_sh),\ - LE_SF(DP_AUX0_AUX_DPHY_TX_CONTROL, AUX_TX_PRECHARGE_SYMBOLS, mask_sh),\ - LE_SF(DP_AUX0_AUX_DPHY_TX_CONTROL, AUX_MODE_DET_CHECK_DELAY, mask_sh),\ - LE_SF(DP_AUX0_AUX_DPHY_RX_CONTROL1, AUX_RX_PRECHARGE_SKIP, mask_sh),\ - LE_SF(DP_AUX0_AUX_DPHY_RX_CONTROL1, AUX_RX_TIMEOUT_LEN, mask_sh),\ - LE_SF(DP_AUX0_AUX_DPHY_RX_CONTROL1, AUX_RX_TIMEOUT_LEN_MUL, mask_sh) - -#define UNIPHY_DCN2_REG_LIST(id) \ - SRI(CLOCK_ENABLE, SYMCLK, id), \ - SRI(CHANNEL_XBAR_CNTL, UNIPHY, id) - -#define DPCS_DCN2_CMN_REG_LIST(id) \ - SRI(DIG_LANE_ENABLE, DIG, id), \ - SRI(TMDS_CTL_BITS, DIG, id), \ - SRI(RDPCSTX_PHY_CNTL3, RDPCSTX, id), \ - SRI(RDPCSTX_PHY_CNTL4, RDPCSTX, id), \ - SRI(RDPCSTX_PHY_CNTL5, RDPCSTX, id), \ - SRI(RDPCSTX_PHY_CNTL6, RDPCSTX, id), \ - SRI(RDPCSTX_PHY_CNTL7, RDPCSTX, id), \ - SRI(RDPCSTX_PHY_CNTL8, RDPCSTX, id), \ - SRI(RDPCSTX_PHY_CNTL9, RDPCSTX, id), \ - SRI(RDPCSTX_PHY_CNTL10, RDPCSTX, id), \ - SRI(RDPCSTX_PHY_CNTL11, RDPCSTX, id), \ - SRI(RDPCSTX_PHY_CNTL12, RDPCSTX, id), \ - SRI(RDPCSTX_PHY_CNTL13, RDPCSTX, id), \ - SRI(RDPCSTX_PHY_CNTL14, RDPCSTX, id), \ - SRI(RDPCSTX_CNTL, RDPCSTX, id), \ - SRI(RDPCSTX_CLOCK_CNTL, RDPCSTX, id), \ - SRI(RDPCSTX_INTERRUPT_CONTROL, RDPCSTX, id), \ - SRI(RDPCSTX_PHY_CNTL0, RDPCSTX, id), \ - SRI(RDPCSTX_PHY_CNTL2, RDPCSTX, id), \ - SRI(RDPCSTX_PLL_UPDATE_DATA, RDPCSTX, id), \ - SRI(RDPCS_TX_CR_ADDR, RDPCSTX, id), \ - SRI(RDPCS_TX_CR_DATA, RDPCSTX, id), \ - SRI(RDPCSTX_PHY_FUSE0, RDPCSTX, id), \ - SRI(RDPCSTX_PHY_FUSE1, RDPCSTX, id), \ - SRI(RDPCSTX_PHY_FUSE2, RDPCSTX, id), \ - SRI(RDPCSTX_PHY_FUSE3, RDPCSTX, id), \ - SRI(DPCSTX_TX_CLOCK_CNTL, DPCSTX, id), \ - SRI(DPCSTX_TX_CNTL, DPCSTX, id), \ - SRI(DPCSTX_DEBUG_CONFIG, DPCSTX, id), \ - SRI(RDPCSTX_DEBUG_CONFIG, RDPCSTX, id), \ - SR(RDPCSTX0_RDPCSTX_SCRATCH) - - -#define DPCS_DCN2_REG_LIST(id) \ - DPCS_DCN2_CMN_REG_LIST(id), \ - SRI(RDPCSTX_PHY_RX_LD_VAL, RDPCSTX, id),\ - SRI(RDPCSTX_DMCU_DPALT_DIS_BLOCK_REG, RDPCSTX, id) - -#define LE_DCN2_REG_LIST(id) \ - LE_DCN10_REG_LIST(id), \ - SR(DCIO_SOFT_RESET) - -struct mpll_cfg { - uint32_t mpllb_ana_v2i; - uint32_t mpllb_ana_freq_vco; - uint32_t mpllb_ana_cp_int; - uint32_t mpllb_ana_cp_prop; - uint32_t mpllb_multiplier; - uint32_t ref_clk_mpllb_div; - bool mpllb_word_div2_en; - bool mpllb_ssc_en; - bool mpllb_div5_clk_en; - bool mpllb_div_clk_en; - bool mpllb_fracn_en; - bool mpllb_pmix_en; - uint32_t mpllb_div_multiplier; - uint32_t mpllb_tx_clk_div; - uint32_t mpllb_fracn_quot; - uint32_t mpllb_fracn_den; - uint32_t mpllb_ssc_peak; - uint32_t mpllb_ssc_stepsize; - uint32_t mpllb_ssc_up_spread; - uint32_t mpllb_fracn_rem; - uint32_t mpllb_hdmi_div; - // TODO: May not mpll params, need to figure out. - uint32_t tx_vboost_lvl; - uint32_t hdmi_pixel_clk_div; - uint32_t ref_range; - uint32_t ref_clk; - bool hdmimode_enable; - bool sup_pre_hp; - bool dp_tx0_vergdrv_byp; - bool dp_tx1_vergdrv_byp; - bool dp_tx2_vergdrv_byp; - bool dp_tx3_vergdrv_byp; - uint32_t tx_peaking_lvl; - uint32_t ctr_reqs_pll; - -}; - -struct dpcssys_phy_seq_cfg { - bool program_fuse; - bool bypass_sram; - bool lane_en[4]; - bool use_calibration_setting; - struct mpll_cfg mpll_cfg; - bool load_sram_fw; -#if 0 - - bool hdmimode_enable; - bool silver2; - bool ext_refclk_en; - uint32_t dp_tx0_term_ctrl; - uint32_t dp_tx1_term_ctrl; - uint32_t dp_tx2_term_ctrl; - uint32_t dp_tx3_term_ctrl; - uint32_t fw_data[0x1000]; - uint32_t dp_tx0_width; - uint32_t dp_tx1_width; - uint32_t dp_tx2_width; - uint32_t dp_tx3_width; - uint32_t dp_tx0_rate; - uint32_t dp_tx1_rate; - uint32_t dp_tx2_rate; - uint32_t dp_tx3_rate; - uint32_t dp_tx0_eq_main; - uint32_t dp_tx0_eq_pre; - uint32_t dp_tx0_eq_post; - uint32_t dp_tx1_eq_main; - uint32_t dp_tx1_eq_pre; - uint32_t dp_tx1_eq_post; - uint32_t dp_tx2_eq_main; - uint32_t dp_tx2_eq_pre; - uint32_t dp_tx2_eq_post; - uint32_t dp_tx3_eq_main; - uint32_t dp_tx3_eq_pre; - uint32_t dp_tx3_eq_post; - bool data_swap_en; - bool data_order_invert_en; - uint32_t ldpcs_fifo_start_delay; - uint32_t rdpcs_fifo_start_delay; - bool rdpcs_reg_fifo_error_mask; - bool rdpcs_tx_fifo_error_mask; - bool rdpcs_dpalt_disable_mask; - bool rdpcs_dpalt_4lane_mask; -#endif -}; - -struct dcn20_link_encoder { - struct dcn10_link_encoder enc10; - struct dpcssys_phy_seq_cfg phy_seq_cfg; -}; - -void enc2_fec_set_enable(struct link_encoder *enc, bool enable); -void enc2_fec_set_ready(struct link_encoder *enc, bool ready); -bool enc2_fec_is_active(struct link_encoder *enc); -void enc2_hw_init(struct link_encoder *enc); - -void link_enc2_read_state(struct link_encoder *enc, struct link_enc_state *s); - -void dcn20_link_encoder_enable_dp_output( - struct link_encoder *enc, - const struct dc_link_settings *link_settings, - enum clock_source_id clock_source); - -bool dcn20_link_encoder_is_in_alt_mode(struct link_encoder *enc); -void dcn20_link_encoder_get_max_link_cap(struct link_encoder *enc, - struct dc_link_settings *link_settings); - -void dcn20_link_encoder_construct( - struct dcn20_link_encoder *enc20, - const struct encoder_init_data *init_data, - const struct encoder_feature_support *enc_features, - const struct dcn10_link_enc_registers *link_regs, - const struct dcn10_link_enc_aux_registers *aux_regs, - const struct dcn10_link_enc_hpd_registers *hpd_regs, - const struct dcn10_link_enc_shift *link_shift, - const struct dcn10_link_enc_mask *link_mask); - -#endif /* __DC_LINK_ENCODER__DCN20_H__ */ diff --git a/drivers/gpu/drm/amd/display/dc/dcn20/dcn20_stream_encoder.c b/drivers/gpu/drm/amd/display/dc/dcn20/dcn20_stream_encoder.c deleted file mode 100644 index 0b47aeb60e79..000000000000 --- a/drivers/gpu/drm/amd/display/dc/dcn20/dcn20_stream_encoder.c +++ /dev/null @@ -1,661 +0,0 @@ -/* - * Copyright 2012-15 Advanced Micro Devices, Inc. - * - * Permission is hereby granted, free of charge, to any person obtaining a - * copy of this software and associated documentation files (the "Software"), - * to deal in the Software without restriction, including without limitation - * the rights to use, copy, modify, merge, publish, distribute, sublicense, - * and/or sell copies of the Software, and to permit persons to whom the - * Software is furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL - * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR - * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, - * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR - * OTHER DEALINGS IN THE SOFTWARE. - * - * Authors: AMD - * - */ - -#include - -#include "dc_bios_types.h" -#include "dcn20_stream_encoder.h" -#include "reg_helper.h" -#include "hw_shared.h" -#include "link.h" -#include "dpcd_defs.h" - -#define DC_LOGGER \ - enc1->base.ctx->logger - -#define REG(reg)\ - (enc1->regs->reg) - -#undef FN -#define FN(reg_name, field_name) \ - enc1->se_shift->field_name, enc1->se_mask->field_name - - -#define CTX \ - enc1->base.ctx - - -static void enc2_update_hdmi_info_packet( - struct dcn10_stream_encoder *enc1, - uint32_t packet_index, - const struct dc_info_packet *info_packet) -{ - uint32_t cont, send, line; - - if (info_packet->valid) { - enc1_update_generic_info_packet( - enc1, - packet_index, - info_packet); - - /* enable transmission of packet(s) - - * packet transmission begins on the next frame */ - cont = 1; - /* send packet(s) every frame */ - send = 1; - /* select line number to send packets on */ - line = 2; - } else { - cont = 0; - send = 0; - line = 0; - } - - /* DP_SEC_GSP[x]_LINE_REFERENCE - keep default value REFER_TO_DP_SOF */ - - /* choose which generic packet control to use */ - switch (packet_index) { - case 0: - REG_UPDATE_2(HDMI_GENERIC_PACKET_CONTROL0, - HDMI_GENERIC0_CONT, cont, - HDMI_GENERIC0_SEND, send); - REG_UPDATE(HDMI_GENERIC_PACKET_CONTROL1, - HDMI_GENERIC0_LINE, line); - break; - case 1: - REG_UPDATE_2(HDMI_GENERIC_PACKET_CONTROL0, - HDMI_GENERIC1_CONT, cont, - HDMI_GENERIC1_SEND, send); - REG_UPDATE(HDMI_GENERIC_PACKET_CONTROL1, - HDMI_GENERIC1_LINE, line); - break; - case 2: - REG_UPDATE_2(HDMI_GENERIC_PACKET_CONTROL0, - HDMI_GENERIC2_CONT, cont, - HDMI_GENERIC2_SEND, send); - REG_UPDATE(HDMI_GENERIC_PACKET_CONTROL2, - HDMI_GENERIC2_LINE, line); - break; - case 3: - REG_UPDATE_2(HDMI_GENERIC_PACKET_CONTROL0, - HDMI_GENERIC3_CONT, cont, - HDMI_GENERIC3_SEND, send); - REG_UPDATE(HDMI_GENERIC_PACKET_CONTROL2, - HDMI_GENERIC3_LINE, line); - break; - case 4: - REG_UPDATE_2(HDMI_GENERIC_PACKET_CONTROL0, - HDMI_GENERIC4_CONT, cont, - HDMI_GENERIC4_SEND, send); - REG_UPDATE(HDMI_GENERIC_PACKET_CONTROL3, - HDMI_GENERIC4_LINE, line); - break; - case 5: - REG_UPDATE_2(HDMI_GENERIC_PACKET_CONTROL0, - HDMI_GENERIC5_CONT, cont, - HDMI_GENERIC5_SEND, send); - REG_UPDATE(HDMI_GENERIC_PACKET_CONTROL3, - HDMI_GENERIC5_LINE, line); - break; - case 6: - REG_UPDATE_2(HDMI_GENERIC_PACKET_CONTROL0, - HDMI_GENERIC6_CONT, cont, - HDMI_GENERIC6_SEND, send); - REG_UPDATE(HDMI_GENERIC_PACKET_CONTROL4, - HDMI_GENERIC6_LINE, line); - break; - case 7: - REG_UPDATE_2(HDMI_GENERIC_PACKET_CONTROL0, - HDMI_GENERIC7_CONT, cont, - HDMI_GENERIC7_SEND, send); - REG_UPDATE(HDMI_GENERIC_PACKET_CONTROL4, - HDMI_GENERIC7_LINE, line); - break; - default: - /* invalid HW packet index */ - DC_LOG_WARNING( - "Invalid HW packet index: %s()\n", - __func__); - return; - } -} - -static void enc2_stream_encoder_update_hdmi_info_packets( - struct stream_encoder *enc, - const struct encoder_info_frame *info_frame) -{ - struct dcn10_stream_encoder *enc1 = DCN10STRENC_FROM_STRENC(enc); - - /* for bring up, disable dp double TODO */ - REG_UPDATE(HDMI_DB_CONTROL, HDMI_DB_DISABLE, 1); - - /*Always add mandatory packets first followed by optional ones*/ - enc2_update_hdmi_info_packet(enc1, 0, &info_frame->avi); - enc2_update_hdmi_info_packet(enc1, 1, &info_frame->hfvsif); - enc2_update_hdmi_info_packet(enc1, 2, &info_frame->gamut); - enc2_update_hdmi_info_packet(enc1, 3, &info_frame->vendor); - enc2_update_hdmi_info_packet(enc1, 4, &info_frame->spd); - enc2_update_hdmi_info_packet(enc1, 5, &info_frame->hdrsmd); - enc2_update_hdmi_info_packet(enc1, 6, &info_frame->vtem); -} - -static void enc2_stream_encoder_stop_hdmi_info_packets( - struct stream_encoder *enc) -{ - struct dcn10_stream_encoder *enc1 = DCN10STRENC_FROM_STRENC(enc); - - /* stop generic packets 0,1 on HDMI */ - REG_SET_4(HDMI_GENERIC_PACKET_CONTROL0, 0, - HDMI_GENERIC0_CONT, 0, - HDMI_GENERIC0_SEND, 0, - HDMI_GENERIC1_CONT, 0, - HDMI_GENERIC1_SEND, 0); - REG_SET_2(HDMI_GENERIC_PACKET_CONTROL1, 0, - HDMI_GENERIC0_LINE, 0, - HDMI_GENERIC1_LINE, 0); - - /* stop generic packets 2,3 on HDMI */ - REG_SET_4(HDMI_GENERIC_PACKET_CONTROL0, 0, - HDMI_GENERIC2_CONT, 0, - HDMI_GENERIC2_SEND, 0, - HDMI_GENERIC3_CONT, 0, - HDMI_GENERIC3_SEND, 0); - REG_SET_2(HDMI_GENERIC_PACKET_CONTROL2, 0, - HDMI_GENERIC2_LINE, 0, - HDMI_GENERIC3_LINE, 0); - - /* stop generic packets 4,5 on HDMI */ - REG_SET_4(HDMI_GENERIC_PACKET_CONTROL0, 0, - HDMI_GENERIC4_CONT, 0, - HDMI_GENERIC4_SEND, 0, - HDMI_GENERIC5_CONT, 0, - HDMI_GENERIC5_SEND, 0); - REG_SET_2(HDMI_GENERIC_PACKET_CONTROL3, 0, - HDMI_GENERIC4_LINE, 0, - HDMI_GENERIC5_LINE, 0); - - /* stop generic packets 6,7 on HDMI */ - REG_SET_4(HDMI_GENERIC_PACKET_CONTROL0, 0, - HDMI_GENERIC6_CONT, 0, - HDMI_GENERIC6_SEND, 0, - HDMI_GENERIC7_CONT, 0, - HDMI_GENERIC7_SEND, 0); - REG_SET_2(HDMI_GENERIC_PACKET_CONTROL4, 0, - HDMI_GENERIC6_LINE, 0, - HDMI_GENERIC7_LINE, 0); -} - - -/* Update GSP7 SDP 128 byte long */ -static void enc2_update_gsp7_128_info_packet( - struct dcn10_stream_encoder *enc1, - const struct dc_info_packet_128 *info_packet, - bool immediate_update) -{ - uint32_t i; - - /* TODOFPGA Figure out a proper number for max_retries polling for lock - * use 50 for now. - */ - uint32_t max_retries = 50; - const uint32_t *content = (const uint32_t *) &info_packet->sb[0]; - - ASSERT(info_packet->hb1 == DC_DP_INFOFRAME_TYPE_PPS); - - /* Configure for PPS packet size (128 bytes) */ - REG_UPDATE(DP_SEC_CNTL2, DP_SEC_GSP7_PPS, 1); - - /* We need turn on clock before programming AFMT block*/ - REG_UPDATE(AFMT_CNTL, AFMT_AUDIO_CLOCK_EN, 1); - - /* Poll dig_update_lock is not locked -> asic internal signal - * assumes otg master lock will unlock it - */ - /*REG_WAIT(AFMT_VBI_PACKET_CONTROL, AFMT_GENERIC_LOCK_STATUS, 0, 10, max_retries);*/ - - /* Wait for HW/SW GSP memory access conflict to go away */ - REG_WAIT(AFMT_VBI_PACKET_CONTROL, AFMT_GENERIC_CONFLICT, - 0, 10, max_retries); - - /* Clear HW/SW memory access conflict flag */ - REG_UPDATE(AFMT_VBI_PACKET_CONTROL, AFMT_GENERIC_CONFLICT_CLR, 1); - - /* write generic packet header */ - REG_UPDATE(AFMT_VBI_PACKET_CONTROL, AFMT_GENERIC_INDEX, 7); - REG_SET_4(AFMT_GENERIC_HDR, 0, - AFMT_GENERIC_HB0, info_packet->hb0, - AFMT_GENERIC_HB1, info_packet->hb1, - AFMT_GENERIC_HB2, info_packet->hb2, - AFMT_GENERIC_HB3, info_packet->hb3); - - /* Write generic packet content 128 bytes long. Four sets are used (indexes 7 - * through 10) to fit 128 bytes. - */ - for (i = 0; i < 4; i++) { - uint32_t packet_index = 7 + i; - REG_UPDATE(AFMT_VBI_PACKET_CONTROL, AFMT_GENERIC_INDEX, packet_index); - - REG_WRITE(AFMT_GENERIC_0, *content++); - REG_WRITE(AFMT_GENERIC_1, *content++); - REG_WRITE(AFMT_GENERIC_2, *content++); - REG_WRITE(AFMT_GENERIC_3, *content++); - REG_WRITE(AFMT_GENERIC_4, *content++); - REG_WRITE(AFMT_GENERIC_5, *content++); - REG_WRITE(AFMT_GENERIC_6, *content++); - REG_WRITE(AFMT_GENERIC_7, *content++); - } - - REG_UPDATE_2(AFMT_VBI_PACKET_CONTROL1, - AFMT_GENERIC7_FRAME_UPDATE, !immediate_update, - AFMT_GENERIC7_IMMEDIATE_UPDATE, immediate_update); -} - -/* Set DSC-related configuration. - * dsc_mode: 0 disables DSC, other values enable DSC in specified format - * sc_bytes_per_pixel: Bytes per pixel in u3.28 format - * dsc_slice_width: Slice width in pixels - */ -static void enc2_dp_set_dsc_config(struct stream_encoder *enc, - enum optc_dsc_mode dsc_mode, - uint32_t dsc_bytes_per_pixel, - uint32_t dsc_slice_width) -{ - struct dcn10_stream_encoder *enc1 = DCN10STRENC_FROM_STRENC(enc); - - REG_UPDATE_2(DP_DSC_CNTL, - DP_DSC_MODE, dsc_mode, - DP_DSC_SLICE_WIDTH, dsc_slice_width); - - REG_SET(DP_DSC_BYTES_PER_PIXEL, 0, - DP_DSC_BYTES_PER_PIXEL, dsc_bytes_per_pixel); -} - - -static void enc2_dp_set_dsc_pps_info_packet(struct stream_encoder *enc, - bool enable, - uint8_t *dsc_packed_pps, - bool immediate_update) -{ - struct dcn10_stream_encoder *enc1 = DCN10STRENC_FROM_STRENC(enc); - - if (enable) { - struct dc_info_packet_128 pps_sdp; - - ASSERT(dsc_packed_pps); - - /* Load PPS into infoframe (SDP) registers */ - pps_sdp.valid = true; - pps_sdp.hb0 = 0; - pps_sdp.hb1 = DC_DP_INFOFRAME_TYPE_PPS; - pps_sdp.hb2 = 127; - pps_sdp.hb3 = 0; - memcpy(&pps_sdp.sb[0], dsc_packed_pps, sizeof(pps_sdp.sb)); - enc2_update_gsp7_128_info_packet(enc1, &pps_sdp, immediate_update); - - /* Enable Generic Stream Packet 7 (GSP) transmission */ - //REG_UPDATE(DP_SEC_CNTL, - // DP_SEC_GSP7_ENABLE, 1); - - /* SW should make sure VBID[6] update line number is bigger - * than PPS transmit line number - */ - REG_UPDATE(DP_SEC_CNTL6, - DP_SEC_GSP7_LINE_NUM, 2); - REG_UPDATE_2(DP_MSA_VBID_MISC, - DP_VBID6_LINE_REFERENCE, 0, - DP_VBID6_LINE_NUM, 3); - - /* Send PPS data at the line number specified above. - * DP spec requires PPS to be sent only when it changes, however since - * decoder has to be able to handle its change on every frame, we're - * sending it always (i.e. on every frame) to reduce the chance it'd be - * missed by decoder. If it turns out required to send PPS only when it - * changes, we can use DP_SEC_GSP7_SEND register. - */ - REG_UPDATE_2(DP_SEC_CNTL, - DP_SEC_GSP7_ENABLE, 1, - DP_SEC_STREAM_ENABLE, 1); - } else { - /* Disable Generic Stream Packet 7 (GSP) transmission */ - REG_UPDATE(DP_SEC_CNTL, DP_SEC_GSP7_ENABLE, 0); - REG_UPDATE(DP_SEC_CNTL2, DP_SEC_GSP7_PPS, 0); - } -} - - -/* this function read dsc related register fields to be logged later in dcn10_log_hw_state - * into a dcn_dsc_state struct. - */ -static void enc2_read_state(struct stream_encoder *enc, struct enc_state *s) -{ - struct dcn10_stream_encoder *enc1 = DCN10STRENC_FROM_STRENC(enc); - - //if dsc is enabled, continue to read - REG_GET(DP_DSC_CNTL, DP_DSC_MODE, &s->dsc_mode); - if (s->dsc_mode) { - REG_GET(DP_DSC_CNTL, DP_DSC_SLICE_WIDTH, &s->dsc_slice_width); - REG_GET(DP_SEC_CNTL6, DP_SEC_GSP7_LINE_NUM, &s->sec_gsp_pps_line_num); - - REG_GET(DP_MSA_VBID_MISC, DP_VBID6_LINE_REFERENCE, &s->vbid6_line_reference); - REG_GET(DP_MSA_VBID_MISC, DP_VBID6_LINE_NUM, &s->vbid6_line_num); - - REG_GET(DP_SEC_CNTL, DP_SEC_GSP7_ENABLE, &s->sec_gsp_pps_enable); - REG_GET(DP_SEC_CNTL, DP_SEC_STREAM_ENABLE, &s->sec_stream_enable); - } -} - -/* Set Dynamic Metadata-configuration. - * enable_dme: TRUE: enables Dynamic Metadata Enfine, FALSE: disables DME - * hubp_requestor_id: HUBP physical instance that is the source of dynamic metadata - * only needs to be set when enable_dme is TRUE - * dmdata_mode: dynamic metadata packet type: DP, HDMI, or Dolby Vision - * - * Ensure the OTG master update lock is set when changing DME configuration. - */ -void enc2_set_dynamic_metadata(struct stream_encoder *enc, - bool enable_dme, - uint32_t hubp_requestor_id, - enum dynamic_metadata_mode dmdata_mode) -{ - struct dcn10_stream_encoder *enc1 = DCN10STRENC_FROM_STRENC(enc); - - if (enable_dme) { - REG_UPDATE_2(DME_CONTROL, - METADATA_HUBP_REQUESTOR_ID, hubp_requestor_id, - METADATA_STREAM_TYPE, (dmdata_mode == dmdata_dolby_vision) ? 1 : 0); - - /* Use default line reference DP_SOF for bringup. - * Should use OTG_SOF for DRR cases - */ - if (dmdata_mode == dmdata_dp) - REG_UPDATE_3(DP_SEC_METADATA_TRANSMISSION, - DP_SEC_METADATA_PACKET_ENABLE, 1, - DP_SEC_METADATA_PACKET_LINE_REFERENCE, 0, - DP_SEC_METADATA_PACKET_LINE, 20); - else { - REG_UPDATE_3(HDMI_METADATA_PACKET_CONTROL, - HDMI_METADATA_PACKET_ENABLE, 1, - HDMI_METADATA_PACKET_LINE_REFERENCE, 0, - HDMI_METADATA_PACKET_LINE, 2); - - if (dmdata_mode == dmdata_dolby_vision) - REG_UPDATE(DIG_FE_CNTL, - DOLBY_VISION_EN, 1); - } - - REG_UPDATE(DME_CONTROL, - METADATA_ENGINE_EN, 1); - } else { - REG_UPDATE(DME_CONTROL, - METADATA_ENGINE_EN, 0); - - if (dmdata_mode == dmdata_dp) - REG_UPDATE(DP_SEC_METADATA_TRANSMISSION, - DP_SEC_METADATA_PACKET_ENABLE, 0); - else { - REG_UPDATE(HDMI_METADATA_PACKET_CONTROL, - HDMI_METADATA_PACKET_ENABLE, 0); - REG_UPDATE(DIG_FE_CNTL, - DOLBY_VISION_EN, 0); - } - } -} - -static void enc2_stream_encoder_update_dp_info_packets_sdp_line_num( - struct stream_encoder *enc, - struct encoder_info_frame *info_frame) -{ - struct dcn10_stream_encoder *enc1 = DCN10STRENC_FROM_STRENC(enc); - - if (info_frame->adaptive_sync.valid == true && - info_frame->sdp_line_num.adaptive_sync_line_num_valid == true) { - //00: REFER_TO_DP_SOF, 01: REFER_TO_OTG_SOF - REG_UPDATE(DP_SEC_CNTL1, DP_SEC_GSP5_LINE_REFERENCE, 1); - - REG_UPDATE(DP_SEC_CNTL5, DP_SEC_GSP5_LINE_NUM, - info_frame->sdp_line_num.adaptive_sync_line_num); - } -} - -static void enc2_stream_encoder_update_dp_info_packets( - struct stream_encoder *enc, - const struct encoder_info_frame *info_frame) -{ - struct dcn10_stream_encoder *enc1 = DCN10STRENC_FROM_STRENC(enc); - uint32_t dmdata_packet_enabled = 0; - - enc1_stream_encoder_update_dp_info_packets(enc, info_frame); - - /* check if dynamic metadata packet transmission is enabled */ - REG_GET(DP_SEC_METADATA_TRANSMISSION, - DP_SEC_METADATA_PACKET_ENABLE, &dmdata_packet_enabled); - - if (dmdata_packet_enabled) - REG_UPDATE(DP_SEC_CNTL, DP_SEC_STREAM_ENABLE, 1); -} - -static bool is_two_pixels_per_containter(const struct dc_crtc_timing *timing) -{ - bool two_pix = timing->pixel_encoding == PIXEL_ENCODING_YCBCR420; - - two_pix = two_pix || (timing->flags.DSC && timing->pixel_encoding == PIXEL_ENCODING_YCBCR422 - && !timing->dsc_cfg.ycbcr422_simple); - return two_pix; -} - -void enc2_stream_encoder_dp_unblank( - struct dc_link *link, - struct stream_encoder *enc, - const struct encoder_unblank_param *param) -{ - struct dcn10_stream_encoder *enc1 = DCN10STRENC_FROM_STRENC(enc); - - if (param->link_settings.link_rate != LINK_RATE_UNKNOWN) { - uint32_t n_vid = 0x8000; - uint32_t m_vid; - uint32_t n_multiply = 0; - uint64_t m_vid_l = n_vid; - - /* YCbCr 4:2:0 : Computed VID_M will be 2X the input rate */ - if (is_two_pixels_per_containter(¶m->timing) || param->opp_cnt > 1) { - /*this logic should be the same in get_pixel_clock_parameters() */ - n_multiply = 1; - } - /* M / N = Fstream / Flink - * m_vid / n_vid = pixel rate / link rate - */ - - m_vid_l *= param->timing.pix_clk_100hz / 10; - m_vid_l = div_u64(m_vid_l, - param->link_settings.link_rate - * LINK_RATE_REF_FREQ_IN_KHZ); - - m_vid = (uint32_t) m_vid_l; - - /* enable auto measurement */ - - REG_UPDATE(DP_VID_TIMING, DP_VID_M_N_GEN_EN, 0); - - /* auto measurement need 1 full 0x8000 symbol cycle to kick in, - * therefore program initial value for Mvid and Nvid - */ - - REG_UPDATE(DP_VID_N, DP_VID_N, n_vid); - - REG_UPDATE(DP_VID_M, DP_VID_M, m_vid); - - REG_UPDATE_2(DP_VID_TIMING, - DP_VID_M_N_GEN_EN, 1, - DP_VID_N_MUL, n_multiply); - } - - /* make sure stream is disabled before resetting steer fifo */ - REG_UPDATE(DP_VID_STREAM_CNTL, DP_VID_STREAM_ENABLE, false); - REG_WAIT(DP_VID_STREAM_CNTL, DP_VID_STREAM_STATUS, 0, 10, 5000); - - /* set DIG_START to 0x1 to reset FIFO */ - REG_UPDATE(DIG_FE_CNTL, DIG_START, 1); - udelay(1); - - /* write 0 to take the FIFO out of reset */ - - REG_UPDATE(DIG_FE_CNTL, DIG_START, 0); - - /* switch DP encoder to CRTC data, but reset it the fifo first. It may happen - * that it overflows during mode transition, and sometimes doesn't recover. - */ - REG_UPDATE(DP_STEER_FIFO, DP_STEER_FIFO_RESET, 1); - udelay(10); - - REG_UPDATE(DP_STEER_FIFO, DP_STEER_FIFO_RESET, 0); - - /* wait 100us for DIG/DP logic to prime - * (i.e. a few video lines) - */ - udelay(100); - - /* the hardware would start sending video at the start of the next DP - * frame (i.e. rising edge of the vblank). - * NOTE: We used to program DP_VID_STREAM_DIS_DEFER = 2 here, but this - * register has no effect on enable transition! HW always guarantees - * VID_STREAM enable at start of next frame, and this is not - * programmable - */ - - REG_UPDATE(DP_VID_STREAM_CNTL, DP_VID_STREAM_ENABLE, true); - - link->dc->link_srv->dp_trace_source_sequence(link, - DPCD_SOURCE_SEQ_AFTER_ENABLE_DP_VID_STREAM); -} - -static void enc2_dp_set_odm_combine( - struct stream_encoder *enc, - bool odm_combine) -{ - struct dcn10_stream_encoder *enc1 = DCN10STRENC_FROM_STRENC(enc); - - REG_UPDATE(DP_PIXEL_FORMAT, DP_PIXEL_COMBINE, odm_combine); -} - -void enc2_stream_encoder_dp_set_stream_attribute( - struct stream_encoder *enc, - struct dc_crtc_timing *crtc_timing, - enum dc_color_space output_color_space, - bool use_vsc_sdp_for_colorimetry, - uint32_t enable_sdp_splitting) -{ - struct dcn10_stream_encoder *enc1 = DCN10STRENC_FROM_STRENC(enc); - - enc1_stream_encoder_dp_set_stream_attribute(enc, - crtc_timing, - output_color_space, - use_vsc_sdp_for_colorimetry, - enable_sdp_splitting); - - REG_UPDATE(DP_SEC_FRAMING4, - DP_SST_SDP_SPLITTING, enable_sdp_splitting); -} - -uint32_t enc2_get_fifo_cal_average_level( - struct stream_encoder *enc) -{ - struct dcn10_stream_encoder *enc1 = DCN10STRENC_FROM_STRENC(enc); - uint32_t fifo_level; - - REG_GET(DIG_FIFO_STATUS, - DIG_FIFO_CAL_AVERAGE_LEVEL, &fifo_level); - return fifo_level; -} - -static const struct stream_encoder_funcs dcn20_str_enc_funcs = { - .dp_set_odm_combine = - enc2_dp_set_odm_combine, - .dp_set_stream_attribute = - enc2_stream_encoder_dp_set_stream_attribute, - .hdmi_set_stream_attribute = - enc1_stream_encoder_hdmi_set_stream_attribute, - .dvi_set_stream_attribute = - enc1_stream_encoder_dvi_set_stream_attribute, - .set_throttled_vcp_size = - enc1_stream_encoder_set_throttled_vcp_size, - .update_hdmi_info_packets = - enc2_stream_encoder_update_hdmi_info_packets, - .stop_hdmi_info_packets = - enc2_stream_encoder_stop_hdmi_info_packets, - .update_dp_info_packets_sdp_line_num = - enc2_stream_encoder_update_dp_info_packets_sdp_line_num, - .update_dp_info_packets = - enc2_stream_encoder_update_dp_info_packets, - .send_immediate_sdp_message = - enc1_stream_encoder_send_immediate_sdp_message, - .stop_dp_info_packets = - enc1_stream_encoder_stop_dp_info_packets, - .dp_blank = - enc1_stream_encoder_dp_blank, - .dp_unblank = - enc2_stream_encoder_dp_unblank, - .audio_mute_control = enc1_se_audio_mute_control, - - .dp_audio_setup = enc1_se_dp_audio_setup, - .dp_audio_enable = enc1_se_dp_audio_enable, - .dp_audio_disable = enc1_se_dp_audio_disable, - - .hdmi_audio_setup = enc1_se_hdmi_audio_setup, - .hdmi_audio_disable = enc1_se_hdmi_audio_disable, - .setup_stereo_sync = enc1_setup_stereo_sync, - .set_avmute = enc1_stream_encoder_set_avmute, - .dig_connect_to_otg = enc1_dig_connect_to_otg, - .dig_source_otg = enc1_dig_source_otg, - - .dp_get_pixel_format = - enc1_stream_encoder_dp_get_pixel_format, - - .enc_read_state = enc2_read_state, - .dp_set_dsc_config = enc2_dp_set_dsc_config, - .dp_set_dsc_pps_info_packet = enc2_dp_set_dsc_pps_info_packet, - .set_dynamic_metadata = enc2_set_dynamic_metadata, - .hdmi_reset_stream_attribute = enc1_reset_hdmi_stream_attribute, - .get_fifo_cal_average_level = enc2_get_fifo_cal_average_level, -}; - -void dcn20_stream_encoder_construct( - struct dcn10_stream_encoder *enc1, - struct dc_context *ctx, - struct dc_bios *bp, - enum engine_id eng_id, - const struct dcn10_stream_enc_registers *regs, - const struct dcn10_stream_encoder_shift *se_shift, - const struct dcn10_stream_encoder_mask *se_mask) -{ - enc1->base.funcs = &dcn20_str_enc_funcs; - enc1->base.ctx = ctx; - enc1->base.id = eng_id; - enc1->base.bp = bp; - enc1->regs = regs; - enc1->se_shift = se_shift; - enc1->se_mask = se_mask; - enc1->base.stream_enc_inst = eng_id - ENGINE_ID_DIGA; -} - diff --git a/drivers/gpu/drm/amd/display/dc/dcn20/dcn20_stream_encoder.h b/drivers/gpu/drm/amd/display/dc/dcn20/dcn20_stream_encoder.h deleted file mode 100644 index baa1e539f341..000000000000 --- a/drivers/gpu/drm/amd/display/dc/dcn20/dcn20_stream_encoder.h +++ /dev/null @@ -1,119 +0,0 @@ -/* - * Copyright 2012-15 Advanced Micro Devices, Inc. - * - * Permission is hereby granted, free of charge, to any person obtaining a - * copy of this software and associated documentation files (the "Software"), - * to deal in the Software without restriction, including without limitation - * the rights to use, copy, modify, merge, publish, distribute, sublicense, - * and/or sell copies of the Software, and to permit persons to whom the - * Software is furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL - * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR - * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, - * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR - * OTHER DEALINGS IN THE SOFTWARE. - * - * Authors: AMD - * - */ - -#ifndef __DC_STREAM_ENCODER_DCN20_H__ -#define __DC_STREAM_ENCODER_DCN20_H__ - -#include "stream_encoder.h" -#include "dcn10/dcn10_stream_encoder.h" - - -#define SE_DCN2_REG_LIST(id)\ - SE_COMMON_DCN_REG_LIST(id),\ - SRI(HDMI_GENERIC_PACKET_CONTROL4, DIG, id), \ - SRI(HDMI_GENERIC_PACKET_CONTROL5, DIG, id), \ - SRI(DP_DSC_CNTL, DP, id), \ - SRI(DP_DSC_BYTES_PER_PIXEL, DP, id), \ - SRI(DME_CONTROL, DIG, id),\ - SRI(DP_SEC_METADATA_TRANSMISSION, DP, id), \ - SRI(HDMI_METADATA_PACKET_CONTROL, DIG, id), \ - SRI(DP_SEC_FRAMING4, DP, id) - -#define SE_COMMON_MASK_SH_LIST_DCN20(mask_sh)\ - SE_COMMON_MASK_SH_LIST_SOC(mask_sh),\ - SE_SF(DIG0_HDMI_GENERIC_PACKET_CONTROL0, HDMI_GENERIC0_CONT, mask_sh),\ - SE_SF(DIG0_HDMI_GENERIC_PACKET_CONTROL0, HDMI_GENERIC0_SEND, mask_sh),\ - SE_SF(DIG0_HDMI_GENERIC_PACKET_CONTROL0, HDMI_GENERIC1_CONT, mask_sh),\ - SE_SF(DIG0_HDMI_GENERIC_PACKET_CONTROL0, HDMI_GENERIC1_SEND, mask_sh),\ - SE_SF(DIG0_HDMI_GENERIC_PACKET_CONTROL0, HDMI_GENERIC2_CONT, mask_sh),\ - SE_SF(DIG0_HDMI_GENERIC_PACKET_CONTROL0, HDMI_GENERIC2_SEND, mask_sh),\ - SE_SF(DIG0_HDMI_GENERIC_PACKET_CONTROL0, HDMI_GENERIC3_CONT, mask_sh),\ - SE_SF(DIG0_HDMI_GENERIC_PACKET_CONTROL0, HDMI_GENERIC3_SEND, mask_sh),\ - SE_SF(DIG0_HDMI_GENERIC_PACKET_CONTROL0, HDMI_GENERIC4_CONT, mask_sh),\ - SE_SF(DIG0_HDMI_GENERIC_PACKET_CONTROL0, HDMI_GENERIC4_SEND, mask_sh),\ - SE_SF(DIG0_HDMI_GENERIC_PACKET_CONTROL0, HDMI_GENERIC5_CONT, mask_sh),\ - SE_SF(DIG0_HDMI_GENERIC_PACKET_CONTROL0, HDMI_GENERIC5_SEND, mask_sh),\ - SE_SF(DIG0_HDMI_GENERIC_PACKET_CONTROL0, HDMI_GENERIC6_CONT, mask_sh),\ - SE_SF(DIG0_HDMI_GENERIC_PACKET_CONTROL0, HDMI_GENERIC6_SEND, mask_sh),\ - SE_SF(DIG0_HDMI_GENERIC_PACKET_CONTROL0, HDMI_GENERIC7_CONT, mask_sh),\ - SE_SF(DIG0_HDMI_GENERIC_PACKET_CONTROL0, HDMI_GENERIC7_SEND, mask_sh),\ - SE_SF(DIG0_HDMI_GENERIC_PACKET_CONTROL1, HDMI_GENERIC0_LINE, mask_sh),\ - SE_SF(DIG0_HDMI_GENERIC_PACKET_CONTROL1, HDMI_GENERIC1_LINE, mask_sh),\ - SE_SF(DIG0_HDMI_GENERIC_PACKET_CONTROL2, HDMI_GENERIC2_LINE, mask_sh),\ - SE_SF(DIG0_HDMI_GENERIC_PACKET_CONTROL2, HDMI_GENERIC3_LINE, mask_sh),\ - SE_SF(DIG0_HDMI_GENERIC_PACKET_CONTROL3, HDMI_GENERIC4_LINE, mask_sh),\ - SE_SF(DIG0_HDMI_GENERIC_PACKET_CONTROL3, HDMI_GENERIC5_LINE, mask_sh),\ - SE_SF(DIG0_HDMI_GENERIC_PACKET_CONTROL4, HDMI_GENERIC6_LINE, mask_sh),\ - SE_SF(DIG0_HDMI_GENERIC_PACKET_CONTROL4, HDMI_GENERIC7_LINE, mask_sh),\ - SE_SF(DP0_DP_DSC_CNTL, DP_DSC_MODE, mask_sh),\ - SE_SF(DP0_DP_DSC_CNTL, DP_DSC_SLICE_WIDTH, mask_sh),\ - SE_SF(DP0_DP_DSC_BYTES_PER_PIXEL, DP_DSC_BYTES_PER_PIXEL, mask_sh),\ - SE_SF(DP0_DP_MSA_VBID_MISC, DP_VBID6_LINE_REFERENCE, mask_sh),\ - SE_SF(DP0_DP_MSA_VBID_MISC, DP_VBID6_LINE_NUM, mask_sh),\ - SE_SF(DIG0_DME_CONTROL, METADATA_ENGINE_EN, mask_sh),\ - SE_SF(DIG0_DME_CONTROL, METADATA_HUBP_REQUESTOR_ID, mask_sh),\ - SE_SF(DIG0_DME_CONTROL, METADATA_STREAM_TYPE, mask_sh),\ - SE_SF(DP0_DP_SEC_METADATA_TRANSMISSION, DP_SEC_METADATA_PACKET_ENABLE, mask_sh),\ - SE_SF(DP0_DP_SEC_METADATA_TRANSMISSION, DP_SEC_METADATA_PACKET_LINE_REFERENCE, mask_sh),\ - SE_SF(DP0_DP_SEC_METADATA_TRANSMISSION, DP_SEC_METADATA_PACKET_LINE, mask_sh),\ - SE_SF(DIG0_HDMI_METADATA_PACKET_CONTROL, HDMI_METADATA_PACKET_ENABLE, mask_sh),\ - SE_SF(DIG0_HDMI_METADATA_PACKET_CONTROL, HDMI_METADATA_PACKET_LINE_REFERENCE, mask_sh),\ - SE_SF(DIG0_HDMI_METADATA_PACKET_CONTROL, HDMI_METADATA_PACKET_LINE, mask_sh),\ - SE_SF(DIG0_DIG_FE_CNTL, DOLBY_VISION_EN, mask_sh),\ - SE_SF(DP0_DP_PIXEL_FORMAT, DP_PIXEL_COMBINE, mask_sh),\ - SE_SF(DP0_DP_SEC_CNTL1, DP_SEC_GSP5_LINE_REFERENCE, mask_sh),\ - SE_SF(DP0_DP_SEC_CNTL5, DP_SEC_GSP5_LINE_NUM, mask_sh),\ - SE_SF(DP0_DP_SEC_FRAMING4, DP_SST_SDP_SPLITTING, mask_sh) - -void dcn20_stream_encoder_construct( - struct dcn10_stream_encoder *enc1, - struct dc_context *ctx, - struct dc_bios *bp, - enum engine_id eng_id, - const struct dcn10_stream_enc_registers *regs, - const struct dcn10_stream_encoder_shift *se_shift, - const struct dcn10_stream_encoder_mask *se_mask); - -void enc2_stream_encoder_dp_set_stream_attribute( - struct stream_encoder *enc, - struct dc_crtc_timing *crtc_timing, - enum dc_color_space output_color_space, - bool use_vsc_sdp_for_colorimetry, - uint32_t enable_sdp_splitting); - -void enc2_stream_encoder_dp_unblank( - struct dc_link *link, - struct stream_encoder *enc, - const struct encoder_unblank_param *param); - -void enc2_set_dynamic_metadata(struct stream_encoder *enc, - bool enable_dme, - uint32_t hubp_requestor_id, - enum dynamic_metadata_mode dmdata_mode); - -uint32_t enc2_get_fifo_cal_average_level( - struct stream_encoder *enc); - -#endif /* __DC_STREAM_ENCODER_DCN20_H__ */ diff --git a/drivers/gpu/drm/amd/display/dc/dcn30/Makefile b/drivers/gpu/drm/amd/display/dc/dcn30/Makefile index 2131d228f6fb..4c43af867d86 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn30/Makefile +++ b/drivers/gpu/drm/amd/display/dc/dcn30/Makefile @@ -25,12 +25,10 @@ DCN30 := dcn30_mpc.o dcn30_vpg.o \ dcn30_afmt.o \ - dcn30_dio_stream_encoder.o \ dcn30_dwb.o \ dcn30_dwb_cm.o \ dcn30_cm_common.o \ dcn30_mmhubbub.o \ - dcn30_dio_link_encoder.o diff --git a/drivers/gpu/drm/amd/display/dc/dcn30/dcn30_dio_link_encoder.c b/drivers/gpu/drm/amd/display/dc/dcn30/dcn30_dio_link_encoder.c deleted file mode 100644 index b8e31b5ea114..000000000000 --- a/drivers/gpu/drm/amd/display/dc/dcn30/dcn30_dio_link_encoder.c +++ /dev/null @@ -1,257 +0,0 @@ -/* - * Copyright 2020 Advanced Micro Devices, Inc. - * - * Permission is hereby granted, free of charge, to any person obtaining a - * copy of this software and associated documentation files (the "Software"), - * to deal in the Software without restriction, including without limitation - * the rights to use, copy, modify, merge, publish, distribute, sublicense, - * and/or sell copies of the Software, and to permit persons to whom the - * Software is furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL - * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR - * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, - * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR - * OTHER DEALINGS IN THE SOFTWARE. - * - * Authors: AMD - * - */ - -#include "reg_helper.h" - -#include "core_types.h" -#include "link_encoder.h" -#include "dcn30_dio_link_encoder.h" -#include "stream_encoder.h" -#include "dc_bios_types.h" -#include "gpio_service_interface.h" - -#define CTX \ - enc10->base.ctx -#define DC_LOGGER \ - enc10->base.ctx->logger - -#define REG(reg)\ - (enc10->link_regs->reg) - -#undef FN -#define FN(reg_name, field_name) \ - enc10->link_shift->field_name, enc10->link_mask->field_name - -#define IND_REG(index) \ - (enc10->link_regs->index) - - -bool dcn30_link_encoder_validate_output_with_stream( - struct link_encoder *enc, - const struct dc_stream_state *stream) -{ - return dcn10_link_encoder_validate_output_with_stream(enc, stream); -} - -static const struct link_encoder_funcs dcn30_link_enc_funcs = { - .read_state = link_enc2_read_state, - .validate_output_with_stream = - dcn30_link_encoder_validate_output_with_stream, - .hw_init = enc3_hw_init, - .setup = dcn10_link_encoder_setup, - .enable_tmds_output = dcn10_link_encoder_enable_tmds_output, - .enable_dp_output = dcn20_link_encoder_enable_dp_output, - .enable_dp_mst_output = dcn10_link_encoder_enable_dp_mst_output, - .disable_output = dcn10_link_encoder_disable_output, - .dp_set_lane_settings = dcn10_link_encoder_dp_set_lane_settings, - .dp_set_phy_pattern = dcn10_link_encoder_dp_set_phy_pattern, - .update_mst_stream_allocation_table = - dcn10_link_encoder_update_mst_stream_allocation_table, - .psr_program_dp_dphy_fast_training = - dcn10_psr_program_dp_dphy_fast_training, - .psr_program_secondary_packet = dcn10_psr_program_secondary_packet, - .connect_dig_be_to_fe = dcn10_link_encoder_connect_dig_be_to_fe, - .enable_hpd = dcn10_link_encoder_enable_hpd, - .disable_hpd = dcn10_link_encoder_disable_hpd, - .is_dig_enabled = dcn10_is_dig_enabled, - .destroy = dcn10_link_encoder_destroy, - .fec_set_enable = enc2_fec_set_enable, - .fec_set_ready = enc2_fec_set_ready, - .fec_is_active = enc2_fec_is_active, - .get_dig_frontend = dcn10_get_dig_frontend, - .get_dig_mode = dcn10_get_dig_mode, - .is_in_alt_mode = dcn20_link_encoder_is_in_alt_mode, - .get_max_link_cap = dcn20_link_encoder_get_max_link_cap, -}; - -void dcn30_link_encoder_construct( - struct dcn20_link_encoder *enc20, - const struct encoder_init_data *init_data, - const struct encoder_feature_support *enc_features, - const struct dcn10_link_enc_registers *link_regs, - const struct dcn10_link_enc_aux_registers *aux_regs, - const struct dcn10_link_enc_hpd_registers *hpd_regs, - const struct dcn10_link_enc_shift *link_shift, - const struct dcn10_link_enc_mask *link_mask) -{ - struct bp_encoder_cap_info bp_cap_info = {0}; - const struct dc_vbios_funcs *bp_funcs = init_data->ctx->dc_bios->funcs; - enum bp_result result = BP_RESULT_OK; - struct dcn10_link_encoder *enc10 = &enc20->enc10; - - enc10->base.funcs = &dcn30_link_enc_funcs; - enc10->base.ctx = init_data->ctx; - enc10->base.id = init_data->encoder; - - enc10->base.hpd_source = init_data->hpd_source; - enc10->base.connector = init_data->connector; - - enc10->base.preferred_engine = ENGINE_ID_UNKNOWN; - - enc10->base.features = *enc_features; - - enc10->base.transmitter = init_data->transmitter; - - /* set the flag to indicate whether driver poll the I2C data pin - * while doing the DP sink detect - */ - -/* if (dal_adapter_service_is_feature_supported(as, - FEATURE_DP_SINK_DETECT_POLL_DATA_PIN)) - enc10->base.features.flags.bits. - DP_SINK_DETECT_POLL_DATA_PIN = true;*/ - - enc10->base.output_signals = - SIGNAL_TYPE_DVI_SINGLE_LINK | - SIGNAL_TYPE_DVI_DUAL_LINK | - SIGNAL_TYPE_LVDS | - SIGNAL_TYPE_DISPLAY_PORT | - SIGNAL_TYPE_DISPLAY_PORT_MST | - SIGNAL_TYPE_EDP | - SIGNAL_TYPE_HDMI_TYPE_A; - - /* For DCE 8.0 and 8.1, by design, UNIPHY is hardwired to DIG_BE. - * SW always assign DIG_FE 1:1 mapped to DIG_FE for non-MST UNIPHY. - * SW assign DIG_FE to non-MST UNIPHY first and MST last. So prefer - * DIG is per UNIPHY and used by SST DP, eDP, HDMI, DVI and LVDS. - * Prefer DIG assignment is decided by board design. - * For DCE 8.0, there are only max 6 UNIPHYs, we assume board design - * and VBIOS will filter out 7 UNIPHY for DCE 8.0. - * By this, adding DIGG should not hurt DCE 8.0. - * This will let DCE 8.1 share DCE 8.0 as much as possible - */ - - enc10->link_regs = link_regs; - enc10->aux_regs = aux_regs; - enc10->hpd_regs = hpd_regs; - enc10->link_shift = link_shift; - enc10->link_mask = link_mask; - - switch (enc10->base.transmitter) { - case TRANSMITTER_UNIPHY_A: - enc10->base.preferred_engine = ENGINE_ID_DIGA; - break; - case TRANSMITTER_UNIPHY_B: - enc10->base.preferred_engine = ENGINE_ID_DIGB; - break; - case TRANSMITTER_UNIPHY_C: - enc10->base.preferred_engine = ENGINE_ID_DIGC; - break; - case TRANSMITTER_UNIPHY_D: - enc10->base.preferred_engine = ENGINE_ID_DIGD; - break; - case TRANSMITTER_UNIPHY_E: - enc10->base.preferred_engine = ENGINE_ID_DIGE; - break; - case TRANSMITTER_UNIPHY_F: - enc10->base.preferred_engine = ENGINE_ID_DIGF; - break; - case TRANSMITTER_UNIPHY_G: - enc10->base.preferred_engine = ENGINE_ID_DIGG; - break; - default: - ASSERT_CRITICAL(false); - enc10->base.preferred_engine = ENGINE_ID_UNKNOWN; - } - - /* default to one to mirror Windows behavior */ - enc10->base.features.flags.bits.HDMI_6GB_EN = 1; - - result = bp_funcs->get_encoder_cap_info(enc10->base.ctx->dc_bios, - enc10->base.id, &bp_cap_info); - - /* Override features with DCE-specific values */ - if (result == BP_RESULT_OK) { - enc10->base.features.flags.bits.IS_HBR2_CAPABLE = - bp_cap_info.DP_HBR2_EN; - enc10->base.features.flags.bits.IS_HBR3_CAPABLE = - bp_cap_info.DP_HBR3_EN; - enc10->base.features.flags.bits.HDMI_6GB_EN = bp_cap_info.HDMI_6GB_EN; - enc10->base.features.flags.bits.IS_DP2_CAPABLE = bp_cap_info.IS_DP2_CAPABLE; - enc10->base.features.flags.bits.IS_UHBR10_CAPABLE = bp_cap_info.DP_UHBR10_EN; - enc10->base.features.flags.bits.IS_UHBR13_5_CAPABLE = bp_cap_info.DP_UHBR13_5_EN; - enc10->base.features.flags.bits.IS_UHBR20_CAPABLE = bp_cap_info.DP_UHBR20_EN; - enc10->base.features.flags.bits.DP_IS_USB_C = - bp_cap_info.DP_IS_USB_C; - } else { - DC_LOG_WARNING("%s: Failed to get encoder_cap_info from VBIOS with error code %d!\n", - __func__, - result); - } - if (enc10->base.ctx->dc->debug.hdmi20_disable) { - enc10->base.features.flags.bits.HDMI_6GB_EN = 0; - } -} - -#define AUX_REG(reg)\ - (enc10->aux_regs->reg) - -#define AUX_REG_READ(reg_name) \ - dm_read_reg(CTX, AUX_REG(reg_name)) - -#define AUX_REG_WRITE(reg_name, val) \ - dm_write_reg(CTX, AUX_REG(reg_name), val) -void enc3_hw_init(struct link_encoder *enc) -{ - struct dcn10_link_encoder *enc10 = TO_DCN10_LINK_ENC(enc); - -/* - 00 - DP_AUX_DPHY_RX_DETECTION_THRESHOLD__1to2 : 1/2 - 01 - DP_AUX_DPHY_RX_DETECTION_THRESHOLD__3to4 : 3/4 - 02 - DP_AUX_DPHY_RX_DETECTION_THRESHOLD__7to8 : 7/8 - 03 - DP_AUX_DPHY_RX_DETECTION_THRESHOLD__15to16 : 15/16 - 04 - DP_AUX_DPHY_RX_DETECTION_THRESHOLD__31to32 : 31/32 - 05 - DP_AUX_DPHY_RX_DETECTION_THRESHOLD__63to64 : 63/64 - 06 - DP_AUX_DPHY_RX_DETECTION_THRESHOLD__127to128 : 127/128 - 07 - DP_AUX_DPHY_RX_DETECTION_THRESHOLD__255to256 : 255/256 -*/ - -/* - AUX_REG_UPDATE_5(AUX_DPHY_RX_CONTROL0, - AUX_RX_START_WINDOW = 1 [6:4] - AUX_RX_RECEIVE_WINDOW = 1 default is 2 [10:8] - AUX_RX_HALF_SYM_DETECT_LEN = 1 [13:12] default is 1 - AUX_RX_TRANSITION_FILTER_EN = 1 [16] default is 1 - AUX_RX_ALLOW_BELOW_THRESHOLD_PHASE_DETECT [17] is 0 default is 0 - AUX_RX_ALLOW_BELOW_THRESHOLD_START [18] is 1 default is 1 - AUX_RX_ALLOW_BELOW_THRESHOLD_STOP [19] is 1 default is 1 - AUX_RX_PHASE_DETECT_LEN, [21,20] = 0x3 default is 3 - AUX_RX_DETECTION_THRESHOLD [30:28] = 1 -*/ - AUX_REG_WRITE(AUX_DPHY_RX_CONTROL0, 0x103d1110); - - AUX_REG_WRITE(AUX_DPHY_TX_CONTROL, 0x21c7a); - - //AUX_DPHY_TX_REF_CONTROL'AUX_TX_REF_DIV HW default is 0x32; - // Set AUX_TX_REF_DIV Divider to generate 2 MHz reference from refclk - // 27MHz -> 0xd - // 100MHz -> 0x32 - // 48MHz -> 0x18 - - // Set TMDS_CTL0 to 1. This is a legacy setting. - REG_UPDATE(TMDS_CTL_BITS, TMDS_CTL0, 1); - - dcn10_aux_initialize(enc10); -} diff --git a/drivers/gpu/drm/amd/display/dc/dcn30/dcn30_dio_link_encoder.h b/drivers/gpu/drm/amd/display/dc/dcn30/dcn30_dio_link_encoder.h deleted file mode 100644 index 5b6177c2ae98..000000000000 --- a/drivers/gpu/drm/amd/display/dc/dcn30/dcn30_dio_link_encoder.h +++ /dev/null @@ -1,86 +0,0 @@ -/* - * Copyright 2020 Advanced Micro Devices, Inc. - * - * Permission is hereby granted, free of charge, to any person obtaining a - * copy of this software and associated documentation files (the "Software"), - * to deal in the Software without restriction, including without limitation - * the rights to use, copy, modify, merge, publish, distribute, sublicense, - * and/or sell copies of the Software, and to permit persons to whom the - * Software is furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL - * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR - * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, - * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR - * OTHER DEALINGS IN THE SOFTWARE. - * - * Authors: AMD - * - */ - -#ifndef __DC_LINK_ENCODER__DCN30_H__ -#define __DC_LINK_ENCODER__DCN30_H__ - -#include "dcn20/dcn20_link_encoder.h" - -#define LE_DCN3_REG_LIST(id)\ - SRI(DIG_BE_CNTL, DIG, id), \ - SRI(DIG_BE_EN_CNTL, DIG, id), \ - SRI(TMDS_CTL_BITS, DIG, id), \ - SRI(TMDS_DCBALANCER_CONTROL, DIG, id), \ - SRI(DP_CONFIG, DP, id), \ - SRI(DP_DPHY_CNTL, DP, id), \ - SRI(DP_DPHY_PRBS_CNTL, DP, id), \ - SRI(DP_DPHY_SCRAM_CNTL, DP, id),\ - SRI(DP_DPHY_SYM0, DP, id), \ - SRI(DP_DPHY_SYM1, DP, id), \ - SRI(DP_DPHY_SYM2, DP, id), \ - SRI(DP_DPHY_TRAINING_PATTERN_SEL, DP, id), \ - SRI(DP_LINK_CNTL, DP, id), \ - SRI(DP_LINK_FRAMING_CNTL, DP, id), \ - SRI(DP_MSE_SAT0, DP, id), \ - SRI(DP_MSE_SAT1, DP, id), \ - SRI(DP_MSE_SAT2, DP, id), \ - SRI(DP_MSE_SAT_UPDATE, DP, id), \ - SRI(DP_SEC_CNTL, DP, id), \ - SRI(DP_VID_STREAM_CNTL, DP, id), \ - SRI(DP_DPHY_FAST_TRAINING, DP, id), \ - SRI(DP_SEC_CNTL1, DP, id), \ - SRI(DP_DPHY_BS_SR_SWAP_CNTL, DP, id), \ - SRI(DP_DPHY_HBR2_PATTERN_CONTROL, DP, id) - -#define LINK_ENCODER_MASK_SH_LIST_DCN30(mask_sh) \ - LINK_ENCODER_MASK_SH_LIST_DCN20(mask_sh),\ - LE_SF(DIG0_TMDS_DCBALANCER_CONTROL, TMDS_SYNC_DCBAL_EN, mask_sh) - -#define DPCS_DCN3_MASK_SH_LIST(mask_sh)\ - DPCS_DCN2_MASK_SH_LIST(mask_sh),\ - LE_SF(DPCSTX0_DPCSTX_TX_CNTL, DPCS_TX_DATA_ORDER_INVERT_18_BIT, mask_sh),\ - LE_SF(RDPCSTX0_RDPCSTX_PHY_CNTL0, RDPCS_PHY_TX_VBOOST_LVL, mask_sh),\ - LE_SF(RDPCSTX0_RDPCSTX_CLOCK_CNTL, RDPCS_TX_CLK_EN, mask_sh),\ - LE_SF(RDPCSTX0_RDPCSTX_PHY_CNTL6, RDPCS_PHY_DPALT_DP4, mask_sh),\ - LE_SF(RDPCSTX0_RDPCSTX_PHY_CNTL6, RDPCS_PHY_DPALT_DISABLE, mask_sh) - - -void dcn30_link_encoder_construct( - struct dcn20_link_encoder *enc20, - const struct encoder_init_data *init_data, - const struct encoder_feature_support *enc_features, - const struct dcn10_link_enc_registers *link_regs, - const struct dcn10_link_enc_aux_registers *aux_regs, - const struct dcn10_link_enc_hpd_registers *hpd_regs, - const struct dcn10_link_enc_shift *link_shift, - const struct dcn10_link_enc_mask *link_mask); - -void enc3_hw_init(struct link_encoder *enc); - -bool dcn30_link_encoder_validate_output_with_stream( - struct link_encoder *enc, - const struct dc_stream_state *stream); - -#endif /* __DC_LINK_ENCODER__DCN30_H__ */ diff --git a/drivers/gpu/drm/amd/display/dc/dcn30/dcn30_dio_stream_encoder.c b/drivers/gpu/drm/amd/display/dc/dcn30/dcn30_dio_stream_encoder.c deleted file mode 100644 index 425b830b88d2..000000000000 --- a/drivers/gpu/drm/amd/display/dc/dcn30/dcn30_dio_stream_encoder.c +++ /dev/null @@ -1,899 +0,0 @@ -/* - * Copyright 2020 Advanced Micro Devices, Inc. - * - * Permission is hereby granted, free of charge, to any person obtaining a - * copy of this software and associated documentation files (the "Software"), - * to deal in the Software without restriction, including without limitation - * the rights to use, copy, modify, merge, publish, distribute, sublicense, - * and/or sell copies of the Software, and to permit persons to whom the - * Software is furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL - * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR - * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, - * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR - * OTHER DEALINGS IN THE SOFTWARE. - * - * Authors: AMD - * - */ - - -#include "dc_bios_types.h" -#include "dcn30_dio_stream_encoder.h" -#include "reg_helper.h" -#include "hw_shared.h" -#include "dc.h" - -#define DC_LOGGER \ - enc1->base.ctx->logger - -#define REG(reg)\ - (enc1->regs->reg) - -#undef FN -#define FN(reg_name, field_name) \ - enc1->se_shift->field_name, enc1->se_mask->field_name - -#define VBI_LINE_0 0 -#define HDMI_CLOCK_CHANNEL_RATE_MORE_340M 340000 - -#define CTX \ - enc1->base.ctx - - -static void enc3_update_hdmi_info_packet( - struct dcn10_stream_encoder *enc1, - uint32_t packet_index, - const struct dc_info_packet *info_packet) -{ - uint32_t cont, send, line; - - if (info_packet->valid) { - enc1->base.vpg->funcs->update_generic_info_packet( - enc1->base.vpg, - packet_index, - info_packet, - true); - - /* enable transmission of packet(s) - - * packet transmission begins on the next frame */ - cont = 1; - /* send packet(s) every frame */ - send = 1; - /* select line number to send packets on */ - line = 2; - } else { - cont = 0; - send = 0; - line = 0; - } - - /* DP_SEC_GSP[x]_LINE_REFERENCE - keep default value REFER_TO_DP_SOF */ - - /* choose which generic packet control to use */ - switch (packet_index) { - case 0: - REG_UPDATE_2(HDMI_GENERIC_PACKET_CONTROL0, - HDMI_GENERIC0_CONT, cont, - HDMI_GENERIC0_SEND, send); - REG_UPDATE(HDMI_GENERIC_PACKET_CONTROL1, - HDMI_GENERIC0_LINE, line); - break; - case 1: - REG_UPDATE_2(HDMI_GENERIC_PACKET_CONTROL0, - HDMI_GENERIC1_CONT, cont, - HDMI_GENERIC1_SEND, send); - REG_UPDATE(HDMI_GENERIC_PACKET_CONTROL1, - HDMI_GENERIC1_LINE, line); - break; - case 2: - REG_UPDATE_2(HDMI_GENERIC_PACKET_CONTROL0, - HDMI_GENERIC2_CONT, cont, - HDMI_GENERIC2_SEND, send); - REG_UPDATE(HDMI_GENERIC_PACKET_CONTROL2, - HDMI_GENERIC2_LINE, line); - break; - case 3: - REG_UPDATE_2(HDMI_GENERIC_PACKET_CONTROL0, - HDMI_GENERIC3_CONT, cont, - HDMI_GENERIC3_SEND, send); - REG_UPDATE(HDMI_GENERIC_PACKET_CONTROL2, - HDMI_GENERIC3_LINE, line); - break; - case 4: - REG_UPDATE_2(HDMI_GENERIC_PACKET_CONTROL0, - HDMI_GENERIC4_CONT, cont, - HDMI_GENERIC4_SEND, send); - REG_UPDATE(HDMI_GENERIC_PACKET_CONTROL3, - HDMI_GENERIC4_LINE, line); - break; - case 5: - REG_UPDATE_2(HDMI_GENERIC_PACKET_CONTROL0, - HDMI_GENERIC5_CONT, cont, - HDMI_GENERIC5_SEND, send); - REG_UPDATE(HDMI_GENERIC_PACKET_CONTROL3, - HDMI_GENERIC5_LINE, line); - break; - case 6: - REG_UPDATE_2(HDMI_GENERIC_PACKET_CONTROL0, - HDMI_GENERIC6_CONT, cont, - HDMI_GENERIC6_SEND, send); - REG_UPDATE(HDMI_GENERIC_PACKET_CONTROL4, - HDMI_GENERIC6_LINE, line); - break; - case 7: - REG_UPDATE_2(HDMI_GENERIC_PACKET_CONTROL0, - HDMI_GENERIC7_CONT, cont, - HDMI_GENERIC7_SEND, send); - REG_UPDATE(HDMI_GENERIC_PACKET_CONTROL4, - HDMI_GENERIC7_LINE, line); - break; - case 8: - REG_UPDATE_2(HDMI_GENERIC_PACKET_CONTROL6, - HDMI_GENERIC8_CONT, cont, - HDMI_GENERIC8_SEND, send); - REG_UPDATE(HDMI_GENERIC_PACKET_CONTROL7, - HDMI_GENERIC8_LINE, line); - break; - case 9: - REG_UPDATE_2(HDMI_GENERIC_PACKET_CONTROL6, - HDMI_GENERIC9_CONT, cont, - HDMI_GENERIC9_SEND, send); - REG_UPDATE(HDMI_GENERIC_PACKET_CONTROL7, - HDMI_GENERIC9_LINE, line); - break; - case 10: - REG_UPDATE_2(HDMI_GENERIC_PACKET_CONTROL6, - HDMI_GENERIC10_CONT, cont, - HDMI_GENERIC10_SEND, send); - REG_UPDATE(HDMI_GENERIC_PACKET_CONTROL8, - HDMI_GENERIC10_LINE, line); - break; - case 11: - REG_UPDATE_2(HDMI_GENERIC_PACKET_CONTROL6, - HDMI_GENERIC11_CONT, cont, - HDMI_GENERIC11_SEND, send); - REG_UPDATE(HDMI_GENERIC_PACKET_CONTROL8, - HDMI_GENERIC11_LINE, line); - break; - case 12: - REG_UPDATE_2(HDMI_GENERIC_PACKET_CONTROL6, - HDMI_GENERIC12_CONT, cont, - HDMI_GENERIC12_SEND, send); - REG_UPDATE(HDMI_GENERIC_PACKET_CONTROL9, - HDMI_GENERIC12_LINE, line); - break; - case 13: - REG_UPDATE_2(HDMI_GENERIC_PACKET_CONTROL6, - HDMI_GENERIC13_CONT, cont, - HDMI_GENERIC13_SEND, send); - REG_UPDATE(HDMI_GENERIC_PACKET_CONTROL9, - HDMI_GENERIC13_LINE, line); - break; - case 14: - REG_UPDATE_2(HDMI_GENERIC_PACKET_CONTROL6, - HDMI_GENERIC14_CONT, cont, - HDMI_GENERIC14_SEND, send); - REG_UPDATE(HDMI_GENERIC_PACKET_CONTROL10, - HDMI_GENERIC14_LINE, line); - break; - default: - /* invalid HW packet index */ - DC_LOG_WARNING( - "Invalid HW packet index: %s()\n", - __func__); - return; - } -} - -void enc3_stream_encoder_update_hdmi_info_packets( - struct stream_encoder *enc, - const struct encoder_info_frame *info_frame) -{ - struct dcn10_stream_encoder *enc1 = DCN10STRENC_FROM_STRENC(enc); - - /* for bring up, disable dp double TODO */ - REG_UPDATE(HDMI_DB_CONTROL, HDMI_DB_DISABLE, 1); - REG_UPDATE(AFMT_CNTL, AFMT_AUDIO_CLOCK_EN, 1); - - /*Always add mandatory packets first followed by optional ones*/ - enc3_update_hdmi_info_packet(enc1, 0, &info_frame->avi); - enc3_update_hdmi_info_packet(enc1, 5, &info_frame->hfvsif); - enc3_update_hdmi_info_packet(enc1, 2, &info_frame->gamut); - enc3_update_hdmi_info_packet(enc1, 1, &info_frame->vendor); - enc3_update_hdmi_info_packet(enc1, 3, &info_frame->spd); - enc3_update_hdmi_info_packet(enc1, 4, &info_frame->hdrsmd); - enc3_update_hdmi_info_packet(enc1, 6, &info_frame->vtem); -} - -void enc3_stream_encoder_stop_hdmi_info_packets( - struct stream_encoder *enc) -{ - struct dcn10_stream_encoder *enc1 = DCN10STRENC_FROM_STRENC(enc); - - /* stop generic packets 0,1 on HDMI */ - REG_SET_4(HDMI_GENERIC_PACKET_CONTROL0, 0, - HDMI_GENERIC0_CONT, 0, - HDMI_GENERIC0_SEND, 0, - HDMI_GENERIC1_CONT, 0, - HDMI_GENERIC1_SEND, 0); - REG_SET_2(HDMI_GENERIC_PACKET_CONTROL1, 0, - HDMI_GENERIC0_LINE, 0, - HDMI_GENERIC1_LINE, 0); - - /* stop generic packets 2,3 on HDMI */ - REG_SET_4(HDMI_GENERIC_PACKET_CONTROL0, 0, - HDMI_GENERIC2_CONT, 0, - HDMI_GENERIC2_SEND, 0, - HDMI_GENERIC3_CONT, 0, - HDMI_GENERIC3_SEND, 0); - REG_SET_2(HDMI_GENERIC_PACKET_CONTROL2, 0, - HDMI_GENERIC2_LINE, 0, - HDMI_GENERIC3_LINE, 0); - - /* stop generic packets 4,5 on HDMI */ - REG_SET_4(HDMI_GENERIC_PACKET_CONTROL0, 0, - HDMI_GENERIC4_CONT, 0, - HDMI_GENERIC4_SEND, 0, - HDMI_GENERIC5_CONT, 0, - HDMI_GENERIC5_SEND, 0); - REG_SET_2(HDMI_GENERIC_PACKET_CONTROL3, 0, - HDMI_GENERIC4_LINE, 0, - HDMI_GENERIC5_LINE, 0); - - /* stop generic packets 6,7 on HDMI */ - REG_SET_4(HDMI_GENERIC_PACKET_CONTROL0, 0, - HDMI_GENERIC6_CONT, 0, - HDMI_GENERIC6_SEND, 0, - HDMI_GENERIC7_CONT, 0, - HDMI_GENERIC7_SEND, 0); - REG_SET_2(HDMI_GENERIC_PACKET_CONTROL4, 0, - HDMI_GENERIC6_LINE, 0, - HDMI_GENERIC7_LINE, 0); - - /* stop generic packets 8,9 on HDMI */ - REG_SET_4(HDMI_GENERIC_PACKET_CONTROL6, 0, - HDMI_GENERIC8_CONT, 0, - HDMI_GENERIC8_SEND, 0, - HDMI_GENERIC9_CONT, 0, - HDMI_GENERIC9_SEND, 0); - REG_SET_2(HDMI_GENERIC_PACKET_CONTROL7, 0, - HDMI_GENERIC8_LINE, 0, - HDMI_GENERIC9_LINE, 0); - - /* stop generic packets 10,11 on HDMI */ - REG_SET_4(HDMI_GENERIC_PACKET_CONTROL6, 0, - HDMI_GENERIC10_CONT, 0, - HDMI_GENERIC10_SEND, 0, - HDMI_GENERIC11_CONT, 0, - HDMI_GENERIC11_SEND, 0); - REG_SET_2(HDMI_GENERIC_PACKET_CONTROL8, 0, - HDMI_GENERIC10_LINE, 0, - HDMI_GENERIC11_LINE, 0); - - /* stop generic packets 12,13 on HDMI */ - REG_SET_4(HDMI_GENERIC_PACKET_CONTROL6, 0, - HDMI_GENERIC12_CONT, 0, - HDMI_GENERIC12_SEND, 0, - HDMI_GENERIC13_CONT, 0, - HDMI_GENERIC13_SEND, 0); - REG_SET_2(HDMI_GENERIC_PACKET_CONTROL9, 0, - HDMI_GENERIC12_LINE, 0, - HDMI_GENERIC13_LINE, 0); - - /* stop generic packet 14 on HDMI */ - REG_SET_2(HDMI_GENERIC_PACKET_CONTROL6, 0, - HDMI_GENERIC14_CONT, 0, - HDMI_GENERIC14_SEND, 0); - REG_UPDATE(HDMI_GENERIC_PACKET_CONTROL10, - HDMI_GENERIC14_LINE, 0); -} - -/* Set DSC-related configuration. - * dsc_mode: 0 disables DSC, other values enable DSC in specified format - * sc_bytes_per_pixel: Bytes per pixel in u3.28 format - * dsc_slice_width: Slice width in pixels - */ -static void enc3_dp_set_dsc_config(struct stream_encoder *enc, - enum optc_dsc_mode dsc_mode, - uint32_t dsc_bytes_per_pixel, - uint32_t dsc_slice_width) -{ - struct dcn10_stream_encoder *enc1 = DCN10STRENC_FROM_STRENC(enc); - - REG_UPDATE_2(DP_DSC_CNTL, - DP_DSC_MODE, dsc_mode, - DP_DSC_SLICE_WIDTH, dsc_slice_width); - - REG_SET(DP_DSC_BYTES_PER_PIXEL, 0, - DP_DSC_BYTES_PER_PIXEL, dsc_bytes_per_pixel); -} - - -void enc3_dp_set_dsc_pps_info_packet(struct stream_encoder *enc, - bool enable, - uint8_t *dsc_packed_pps, - bool immediate_update) -{ - struct dcn10_stream_encoder *enc1 = DCN10STRENC_FROM_STRENC(enc); - - if (enable) { - struct dc_info_packet pps_sdp; - int i; - - /* Configure for PPS packet size (128 bytes) */ - REG_UPDATE(DP_SEC_CNTL2, DP_SEC_GSP11_PPS, 1); - - /* We need turn on clock before programming AFMT block - * - * TODO: We may not need this here anymore since update_generic_info_packet - * no longer touches AFMT - */ - REG_UPDATE(AFMT_CNTL, AFMT_AUDIO_CLOCK_EN, 1); - - /* Load PPS into infoframe (SDP) registers */ - pps_sdp.valid = true; - pps_sdp.hb0 = 0; - pps_sdp.hb1 = DC_DP_INFOFRAME_TYPE_PPS; - pps_sdp.hb2 = 127; - pps_sdp.hb3 = 0; - - for (i = 0; i < 4; i++) { - memcpy(pps_sdp.sb, &dsc_packed_pps[i * 32], 32); - enc1->base.vpg->funcs->update_generic_info_packet( - enc1->base.vpg, - 11 + i, - &pps_sdp, - immediate_update); - } - - /* SW should make sure VBID[6] update line number is bigger - * than PPS transmit line number - */ - REG_UPDATE(DP_GSP11_CNTL, - DP_SEC_GSP11_LINE_NUM, 2); - REG_UPDATE_2(DP_MSA_VBID_MISC, - DP_VBID6_LINE_REFERENCE, 0, - DP_VBID6_LINE_NUM, 3); - - /* Send PPS data at the line number specified above. - * DP spec requires PPS to be sent only when it changes, however since - * decoder has to be able to handle its change on every frame, we're - * sending it always (i.e. on every frame) to reduce the chance it'd be - * missed by decoder. If it turns out required to send PPS only when it - * changes, we can use DP_SEC_GSP11_SEND register. - */ - REG_UPDATE(DP_GSP11_CNTL, - DP_SEC_GSP11_ENABLE, 1); - REG_UPDATE(DP_SEC_CNTL, - DP_SEC_STREAM_ENABLE, 1); - } else { - /* Disable Generic Stream Packet 11 (GSP) transmission */ - REG_UPDATE(DP_GSP11_CNTL, DP_SEC_GSP11_ENABLE, 0); - REG_UPDATE(DP_SEC_CNTL2, DP_SEC_GSP11_PPS, 0); - } -} - - -/* this function read dsc related register fields to be logged later in dcn10_log_hw_state - * into a dcn_dsc_state struct. - */ -static void enc3_read_state(struct stream_encoder *enc, struct enc_state *s) -{ - struct dcn10_stream_encoder *enc1 = DCN10STRENC_FROM_STRENC(enc); - - //if dsc is enabled, continue to read - REG_GET(DP_DSC_CNTL, DP_DSC_MODE, &s->dsc_mode); - if (s->dsc_mode) { - REG_GET(DP_DSC_CNTL, DP_DSC_SLICE_WIDTH, &s->dsc_slice_width); - REG_GET(DP_GSP11_CNTL, DP_SEC_GSP11_LINE_NUM, &s->sec_gsp_pps_line_num); - - REG_GET(DP_MSA_VBID_MISC, DP_VBID6_LINE_REFERENCE, &s->vbid6_line_reference); - REG_GET(DP_MSA_VBID_MISC, DP_VBID6_LINE_NUM, &s->vbid6_line_num); - - REG_GET(DP_GSP11_CNTL, DP_SEC_GSP11_ENABLE, &s->sec_gsp_pps_enable); - REG_GET(DP_SEC_CNTL, DP_SEC_STREAM_ENABLE, &s->sec_stream_enable); - } -} - -void enc3_stream_encoder_update_dp_info_packets_sdp_line_num( - struct stream_encoder *enc, - struct encoder_info_frame *info_frame) -{ - struct dcn10_stream_encoder *enc1 = DCN10STRENC_FROM_STRENC(enc); - - if (info_frame->adaptive_sync.valid == true && - info_frame->sdp_line_num.adaptive_sync_line_num_valid == true) { - //00: REFER_TO_DP_SOF, 01: REFER_TO_OTG_SOF - REG_UPDATE(DP_SEC_CNTL1, DP_SEC_GSP5_LINE_REFERENCE, 1); - - REG_UPDATE(DP_SEC_CNTL5, DP_SEC_GSP5_LINE_NUM, - info_frame->sdp_line_num.adaptive_sync_line_num); - } -} - -void enc3_stream_encoder_update_dp_info_packets( - struct stream_encoder *enc, - const struct encoder_info_frame *info_frame) -{ - struct dcn10_stream_encoder *enc1 = DCN10STRENC_FROM_STRENC(enc); - uint32_t value = 0; - uint32_t dmdata_packet_enabled = 0; - - if (info_frame->vsc.valid) { - enc->vpg->funcs->update_generic_info_packet( - enc->vpg, - 0, /* packetIndex */ - &info_frame->vsc, - true); - } - /* TODO: VSC SDP at packetIndex 1 should be retricted only if PSR-SU on. - * There should have another Infopacket type (e.g. vsc_psrsu) for PSR_SU. - * In addition, currently the driver check the valid bit then update and - * send the corresponding Infopacket. For PSR-SU, the SDP only be sent - * while entering PSR-SU mode. So we need another parameter(e.g. send) - * in dc_info_packet to indicate which infopacket should be enabled by - * default here. - */ - if (info_frame->vsc.valid) { - enc->vpg->funcs->update_generic_info_packet( - enc->vpg, - 1, /* packetIndex */ - &info_frame->vsc, - true); - } - /* TODO: VSC SDP at packetIndex 1 should be restricted only if PSR-SU on. - * There should have another Infopacket type (e.g. vsc_psrsu) for PSR_SU. - * In addition, currently the driver check the valid bit then update and - * send the corresponding Infopacket. For PSR-SU, the SDP only be sent - * while entering PSR-SU mode. So we need another parameter(e.g. send) - * in dc_info_packet to indicate which infopacket should be enabled by - * default here. - */ - if (info_frame->vsc.valid) { - enc->vpg->funcs->update_generic_info_packet( - enc->vpg, - 1, /* packetIndex */ - &info_frame->vsc, - true); - } - if (info_frame->spd.valid) { - enc->vpg->funcs->update_generic_info_packet( - enc->vpg, - 2, /* packetIndex */ - &info_frame->spd, - true); - } - if (info_frame->hdrsmd.valid) { - enc->vpg->funcs->update_generic_info_packet( - enc->vpg, - 3, /* packetIndex */ - &info_frame->hdrsmd, - true); - } - /* packetIndex 4 is used for send immediate sdp message, and please - * use other packetIndex (such as 5,6) for other info packet - */ - - if (info_frame->adaptive_sync.valid) - enc->vpg->funcs->update_generic_info_packet( - enc->vpg, - 5, /* packetIndex */ - &info_frame->adaptive_sync, - true); - - /* enable/disable transmission of packet(s). - * If enabled, packet transmission begins on the next frame - */ - REG_UPDATE(DP_SEC_CNTL, DP_SEC_GSP0_ENABLE, info_frame->vsc.valid); - REG_UPDATE(DP_SEC_CNTL, DP_SEC_GSP2_ENABLE, info_frame->spd.valid); - REG_UPDATE(DP_SEC_CNTL, DP_SEC_GSP3_ENABLE, info_frame->hdrsmd.valid); - REG_UPDATE(DP_SEC_CNTL, DP_SEC_GSP5_ENABLE, info_frame->adaptive_sync.valid); - - /* This bit is the master enable bit. - * When enabling secondary stream engine, - * this master bit must also be set. - * This register shared with audio info frame. - * Therefore we need to enable master bit - * if at least on of the fields is not 0 - */ - value = REG_READ(DP_SEC_CNTL); - if (value) - REG_UPDATE(DP_SEC_CNTL, DP_SEC_STREAM_ENABLE, 1); - - /* check if dynamic metadata packet transmission is enabled */ - REG_GET(DP_SEC_METADATA_TRANSMISSION, - DP_SEC_METADATA_PACKET_ENABLE, &dmdata_packet_enabled); - - if (dmdata_packet_enabled) - REG_UPDATE(DP_SEC_CNTL, DP_SEC_STREAM_ENABLE, 1); -} - -static void enc3_dp_set_odm_combine( - struct stream_encoder *enc, - bool odm_combine) -{ - struct dcn10_stream_encoder *enc1 = DCN10STRENC_FROM_STRENC(enc); - - REG_UPDATE(DP_PIXEL_FORMAT, DP_PIXEL_COMBINE, odm_combine); -} - -/* setup stream encoder in dvi mode */ -static void enc3_stream_encoder_dvi_set_stream_attribute( - struct stream_encoder *enc, - struct dc_crtc_timing *crtc_timing, - bool is_dual_link) -{ - struct dcn10_stream_encoder *enc1 = DCN10STRENC_FROM_STRENC(enc); - - if (!enc->ctx->dc->debug.avoid_vbios_exec_table) { - struct bp_encoder_control cntl = {0}; - - cntl.action = ENCODER_CONTROL_SETUP; - cntl.engine_id = enc1->base.id; - cntl.signal = is_dual_link ? - SIGNAL_TYPE_DVI_DUAL_LINK : SIGNAL_TYPE_DVI_SINGLE_LINK; - cntl.enable_dp_audio = false; - cntl.pixel_clock = crtc_timing->pix_clk_100hz / 10; - cntl.lanes_number = (is_dual_link) ? LANE_COUNT_EIGHT : LANE_COUNT_FOUR; - - if (enc1->base.bp->funcs->encoder_control( - enc1->base.bp, &cntl) != BP_RESULT_OK) - return; - - } else { - - //Set pattern for clock channel, default vlue 0x63 does not work - REG_UPDATE(DIG_CLOCK_PATTERN, DIG_CLOCK_PATTERN, 0x1F); - - //DIG_BE_TMDS_DVI_MODE : TMDS-DVI mode is already set in link_encoder_setup - - //DIG_SOURCE_SELECT is already set in dig_connect_to_otg - - /* set DIG_START to 0x1 to reset FIFO */ - REG_UPDATE(DIG_FE_CNTL, DIG_START, 1); - udelay(1); - - /* write 0 to take the FIFO out of reset */ - REG_UPDATE(DIG_FE_CNTL, DIG_START, 0); - udelay(1); - } - - ASSERT(crtc_timing->pixel_encoding == PIXEL_ENCODING_RGB); - ASSERT(crtc_timing->display_color_depth == COLOR_DEPTH_888); - enc1_stream_encoder_set_stream_attribute_helper(enc1, crtc_timing); -} - -/* setup stream encoder in hdmi mode */ -static void enc3_stream_encoder_hdmi_set_stream_attribute( - struct stream_encoder *enc, - struct dc_crtc_timing *crtc_timing, - int actual_pix_clk_khz, - bool enable_audio) -{ - struct dcn10_stream_encoder *enc1 = DCN10STRENC_FROM_STRENC(enc); - - if (!enc->ctx->dc->debug.avoid_vbios_exec_table) { - struct bp_encoder_control cntl = {0}; - - cntl.action = ENCODER_CONTROL_SETUP; - cntl.engine_id = enc1->base.id; - cntl.signal = SIGNAL_TYPE_HDMI_TYPE_A; - cntl.enable_dp_audio = enable_audio; - cntl.pixel_clock = actual_pix_clk_khz; - cntl.lanes_number = LANE_COUNT_FOUR; - - if (enc1->base.bp->funcs->encoder_control( - enc1->base.bp, &cntl) != BP_RESULT_OK) - return; - - } else { - - //Set pattern for clock channel, default vlue 0x63 does not work - REG_UPDATE(DIG_CLOCK_PATTERN, DIG_CLOCK_PATTERN, 0x1F); - - //DIG_BE_TMDS_HDMI_MODE : TMDS-HDMI mode is already set in link_encoder_setup - - //DIG_SOURCE_SELECT is already set in dig_connect_to_otg - - /* set DIG_START to 0x1 to reset FIFO */ - REG_UPDATE(DIG_FE_CNTL, DIG_START, 1); - udelay(1); - - /* write 0 to take the FIFO out of reset */ - REG_UPDATE(DIG_FE_CNTL, DIG_START, 0); - udelay(1); - } - - /* Configure pixel encoding */ - enc1_stream_encoder_set_stream_attribute_helper(enc1, crtc_timing); - - /* setup HDMI engine */ - REG_UPDATE_6(HDMI_CONTROL, - HDMI_PACKET_GEN_VERSION, 1, - HDMI_KEEPOUT_MODE, 1, - HDMI_DEEP_COLOR_ENABLE, 0, - HDMI_DATA_SCRAMBLE_EN, 0, - HDMI_NO_EXTRA_NULL_PACKET_FILLED, 1, - HDMI_CLOCK_CHANNEL_RATE, 0); - - /* Configure color depth */ - switch (crtc_timing->display_color_depth) { - case COLOR_DEPTH_888: - REG_UPDATE(HDMI_CONTROL, HDMI_DEEP_COLOR_DEPTH, 0); - break; - case COLOR_DEPTH_101010: - if (crtc_timing->pixel_encoding == PIXEL_ENCODING_YCBCR422) { - REG_UPDATE_2(HDMI_CONTROL, - HDMI_DEEP_COLOR_DEPTH, 1, - HDMI_DEEP_COLOR_ENABLE, 0); - } else { - REG_UPDATE_2(HDMI_CONTROL, - HDMI_DEEP_COLOR_DEPTH, 1, - HDMI_DEEP_COLOR_ENABLE, 1); - } - break; - case COLOR_DEPTH_121212: - if (crtc_timing->pixel_encoding == PIXEL_ENCODING_YCBCR422) { - REG_UPDATE_2(HDMI_CONTROL, - HDMI_DEEP_COLOR_DEPTH, 2, - HDMI_DEEP_COLOR_ENABLE, 0); - } else { - REG_UPDATE_2(HDMI_CONTROL, - HDMI_DEEP_COLOR_DEPTH, 2, - HDMI_DEEP_COLOR_ENABLE, 1); - } - break; - case COLOR_DEPTH_161616: - REG_UPDATE_2(HDMI_CONTROL, - HDMI_DEEP_COLOR_DEPTH, 3, - HDMI_DEEP_COLOR_ENABLE, 1); - break; - default: - break; - } - - if (actual_pix_clk_khz >= HDMI_CLOCK_CHANNEL_RATE_MORE_340M) { - /* enable HDMI data scrambler - * HDMI_CLOCK_CHANNEL_RATE_MORE_340M - * Clock channel frequency is 1/4 of character rate. - */ - REG_UPDATE_2(HDMI_CONTROL, - HDMI_DATA_SCRAMBLE_EN, 1, - HDMI_CLOCK_CHANNEL_RATE, 1); - } else if (crtc_timing->flags.LTE_340MCSC_SCRAMBLE) { - - /* TODO: New feature for DCE11, still need to implement */ - - /* enable HDMI data scrambler - * HDMI_CLOCK_CHANNEL_FREQ_EQUAL_TO_CHAR_RATE - * Clock channel frequency is the same - * as character rate - */ - REG_UPDATE_2(HDMI_CONTROL, - HDMI_DATA_SCRAMBLE_EN, 1, - HDMI_CLOCK_CHANNEL_RATE, 0); - } - - - /* Enable transmission of General Control packet on every frame */ - REG_UPDATE_3(HDMI_VBI_PACKET_CONTROL, - HDMI_GC_CONT, 1, - HDMI_GC_SEND, 1, - HDMI_NULL_SEND, 1); - - /* Disable Audio Content Protection packet transmission */ - REG_UPDATE(HDMI_VBI_PACKET_CONTROL, HDMI_ACP_SEND, 0); - - /* following belongs to audio */ - /* Enable Audio InfoFrame packet transmission. */ - REG_UPDATE(HDMI_INFOFRAME_CONTROL0, HDMI_AUDIO_INFO_SEND, 1); - - /* update double-buffered AUDIO_INFO registers immediately */ - ASSERT (enc->afmt); - enc->afmt->funcs->audio_info_immediate_update(enc->afmt); - - /* Select line number on which to send Audio InfoFrame packets */ - REG_UPDATE(HDMI_INFOFRAME_CONTROL1, HDMI_AUDIO_INFO_LINE, - VBI_LINE_0 + 2); - - /* set HDMI GC AVMUTE */ - REG_UPDATE(HDMI_GC, HDMI_GC_AVMUTE, 0); -} - -void enc3_audio_mute_control( - struct stream_encoder *enc, - bool mute) -{ - ASSERT (enc->afmt); - enc->afmt->funcs->audio_mute_control(enc->afmt, mute); -} - -void enc3_se_dp_audio_setup( - struct stream_encoder *enc, - unsigned int az_inst, - struct audio_info *info) -{ - ASSERT (enc->afmt); - enc->afmt->funcs->se_audio_setup(enc->afmt, az_inst, info); -} - -#define DP_SEC_AUD_N__DP_SEC_AUD_N__DEFAULT 0x8000 -#define DP_SEC_TIMESTAMP__DP_SEC_TIMESTAMP_MODE__AUTO_CALC 1 - -static void enc3_se_setup_dp_audio( - struct stream_encoder *enc) -{ - struct dcn10_stream_encoder *enc1 = DCN10STRENC_FROM_STRENC(enc); - - /* --- DP Audio packet configurations --- */ - - /* ATP Configuration */ - REG_SET(DP_SEC_AUD_N, 0, - DP_SEC_AUD_N, DP_SEC_AUD_N__DP_SEC_AUD_N__DEFAULT); - - /* Async/auto-calc timestamp mode */ - REG_SET(DP_SEC_TIMESTAMP, 0, DP_SEC_TIMESTAMP_MODE, - DP_SEC_TIMESTAMP__DP_SEC_TIMESTAMP_MODE__AUTO_CALC); - - ASSERT (enc->afmt); - enc->afmt->funcs->setup_dp_audio(enc->afmt); -} - -void enc3_se_dp_audio_enable( - struct stream_encoder *enc) -{ - enc1_se_enable_audio_clock(enc, true); - enc3_se_setup_dp_audio(enc); - enc1_se_enable_dp_audio(enc); -} - -static void enc3_se_setup_hdmi_audio( - struct stream_encoder *enc, - const struct audio_crtc_info *crtc_info) -{ - struct dcn10_stream_encoder *enc1 = DCN10STRENC_FROM_STRENC(enc); - - struct audio_clock_info audio_clock_info = {0}; - - /* Setup audio in AFMT - program AFMT block associated with DIO */ - ASSERT (enc->afmt); - enc->afmt->funcs->setup_hdmi_audio(enc->afmt); - - /* HDMI_AUDIO_PACKET_CONTROL */ - REG_UPDATE(HDMI_AUDIO_PACKET_CONTROL, - HDMI_AUDIO_DELAY_EN, 1); - - /* HDMI_ACR_PACKET_CONTROL */ - REG_UPDATE_3(HDMI_ACR_PACKET_CONTROL, - HDMI_ACR_AUTO_SEND, 1, - HDMI_ACR_SOURCE, 0, - HDMI_ACR_AUDIO_PRIORITY, 0); - - /* Program audio clock sample/regeneration parameters */ - get_audio_clock_info(crtc_info->color_depth, - crtc_info->requested_pixel_clock_100Hz, - crtc_info->calculated_pixel_clock_100Hz, - &audio_clock_info); - DC_LOG_HW_AUDIO( - "\n%s:Input::requested_pixel_clock_100Hz = %d" \ - "calculated_pixel_clock_100Hz = %d \n", __func__, \ - crtc_info->requested_pixel_clock_100Hz, \ - crtc_info->calculated_pixel_clock_100Hz); - - /* HDMI_ACR_32_0__HDMI_ACR_CTS_32_MASK */ - REG_UPDATE(HDMI_ACR_32_0, HDMI_ACR_CTS_32, audio_clock_info.cts_32khz); - - /* HDMI_ACR_32_1__HDMI_ACR_N_32_MASK */ - REG_UPDATE(HDMI_ACR_32_1, HDMI_ACR_N_32, audio_clock_info.n_32khz); - - /* HDMI_ACR_44_0__HDMI_ACR_CTS_44_MASK */ - REG_UPDATE(HDMI_ACR_44_0, HDMI_ACR_CTS_44, audio_clock_info.cts_44khz); - - /* HDMI_ACR_44_1__HDMI_ACR_N_44_MASK */ - REG_UPDATE(HDMI_ACR_44_1, HDMI_ACR_N_44, audio_clock_info.n_44khz); - - /* HDMI_ACR_48_0__HDMI_ACR_CTS_48_MASK */ - REG_UPDATE(HDMI_ACR_48_0, HDMI_ACR_CTS_48, audio_clock_info.cts_48khz); - - /* HDMI_ACR_48_1__HDMI_ACR_N_48_MASK */ - REG_UPDATE(HDMI_ACR_48_1, HDMI_ACR_N_48, audio_clock_info.n_48khz); - - /* Video driver cannot know in advance which sample rate will - * be used by HD Audio driver - * HDMI_ACR_PACKET_CONTROL__HDMI_ACR_N_MULTIPLE field is - * programmed below in interruppt callback - */ -} - -void enc3_se_hdmi_audio_setup( - struct stream_encoder *enc, - unsigned int az_inst, - struct audio_info *info, - struct audio_crtc_info *audio_crtc_info) -{ - enc1_se_enable_audio_clock(enc, true); - enc3_se_setup_hdmi_audio(enc, audio_crtc_info); - ASSERT (enc->afmt); - enc->afmt->funcs->se_audio_setup(enc->afmt, az_inst, info); -} - - -static const struct stream_encoder_funcs dcn30_str_enc_funcs = { - .dp_set_odm_combine = - enc3_dp_set_odm_combine, - .dp_set_stream_attribute = - enc2_stream_encoder_dp_set_stream_attribute, - .hdmi_set_stream_attribute = - enc3_stream_encoder_hdmi_set_stream_attribute, - .dvi_set_stream_attribute = - enc3_stream_encoder_dvi_set_stream_attribute, - .set_throttled_vcp_size = - enc1_stream_encoder_set_throttled_vcp_size, - .update_hdmi_info_packets = - enc3_stream_encoder_update_hdmi_info_packets, - .stop_hdmi_info_packets = - enc3_stream_encoder_stop_hdmi_info_packets, - .update_dp_info_packets_sdp_line_num = - enc3_stream_encoder_update_dp_info_packets_sdp_line_num, - .update_dp_info_packets = - enc3_stream_encoder_update_dp_info_packets, - .stop_dp_info_packets = - enc1_stream_encoder_stop_dp_info_packets, - .dp_blank = - enc1_stream_encoder_dp_blank, - .dp_unblank = - enc2_stream_encoder_dp_unblank, - .audio_mute_control = enc3_audio_mute_control, - - .dp_audio_setup = enc3_se_dp_audio_setup, - .dp_audio_enable = enc3_se_dp_audio_enable, - .dp_audio_disable = enc1_se_dp_audio_disable, - - .hdmi_audio_setup = enc3_se_hdmi_audio_setup, - .hdmi_audio_disable = enc1_se_hdmi_audio_disable, - .setup_stereo_sync = enc1_setup_stereo_sync, - .set_avmute = enc1_stream_encoder_set_avmute, - .dig_connect_to_otg = enc1_dig_connect_to_otg, - .dig_source_otg = enc1_dig_source_otg, - - .dp_get_pixel_format = enc1_stream_encoder_dp_get_pixel_format, - - .enc_read_state = enc3_read_state, - .dp_set_dsc_config = enc3_dp_set_dsc_config, - .dp_set_dsc_pps_info_packet = enc3_dp_set_dsc_pps_info_packet, - .set_dynamic_metadata = enc2_set_dynamic_metadata, - .hdmi_reset_stream_attribute = enc1_reset_hdmi_stream_attribute, - - .get_fifo_cal_average_level = enc2_get_fifo_cal_average_level, -}; - -void dcn30_dio_stream_encoder_construct( - struct dcn10_stream_encoder *enc1, - struct dc_context *ctx, - struct dc_bios *bp, - enum engine_id eng_id, - struct vpg *vpg, - struct afmt *afmt, - const struct dcn10_stream_enc_registers *regs, - const struct dcn10_stream_encoder_shift *se_shift, - const struct dcn10_stream_encoder_mask *se_mask) -{ - enc1->base.funcs = &dcn30_str_enc_funcs; - enc1->base.ctx = ctx; - enc1->base.id = eng_id; - enc1->base.bp = bp; - enc1->base.vpg = vpg; - enc1->base.afmt = afmt; - enc1->regs = regs; - enc1->se_shift = se_shift; - enc1->se_mask = se_mask; - enc1->base.stream_enc_inst = vpg->inst; -} - diff --git a/drivers/gpu/drm/amd/display/dc/dcn30/dcn30_dio_stream_encoder.h b/drivers/gpu/drm/amd/display/dc/dcn30/dcn30_dio_stream_encoder.h deleted file mode 100644 index 06310973ded2..000000000000 --- a/drivers/gpu/drm/amd/display/dc/dcn30/dcn30_dio_stream_encoder.h +++ /dev/null @@ -1,327 +0,0 @@ -/* - * Copyright 2020 Advanced Micro Devices, Inc. - * - * Permission is hereby granted, free of charge, to any person obtaining a - * copy of this software and associated documentation files (the "Software"), - * to deal in the Software without restriction, including without limitation - * the rights to use, copy, modify, merge, publish, distribute, sublicense, - * and/or sell copies of the Software, and to permit persons to whom the - * Software is furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL - * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR - * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, - * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR - * OTHER DEALINGS IN THE SOFTWARE. - * - * Authors: AMD - * - */ - -#ifndef __DC_DIO_STREAM_ENCODER_DCN30_H__ -#define __DC_DIO_STREAM_ENCODER_DCN30_H__ - -#include "dcn30/dcn30_vpg.h" -#include "dcn30/dcn30_afmt.h" -#include "stream_encoder.h" -#include "dcn20/dcn20_stream_encoder.h" - -/* Register bit field name change */ -#define RDPCSTX0_RDPCSTX_CLOCK_CNTL__RDPCS_SYMCLK_DIV2_GATE_DIS__SHIFT 0x8 -#define RDPCSTX0_RDPCSTX_CLOCK_CNTL__RDPCS_SYMCLK_DIV2_EN__SHIFT 0x9 -#define RDPCSTX0_RDPCSTX_CLOCK_CNTL__RDPCS_SYMCLK_DIV2_CLOCK_ON__SHIFT 0xa -#define DPCSTX0_DPCSTX_TX_CNTL__DPCS_TX_DATA_SWAP__SHIFT 0xe -#define DPCSTX0_DPCSTX_TX_CNTL__DPCS_TX_DATA_ORDER_INVERT__SHIFT 0xf - -#define RDPCSTX0_RDPCSTX_CLOCK_CNTL__RDPCS_SYMCLK_DIV2_GATE_DIS_MASK 0x00000100L -#define RDPCSTX0_RDPCSTX_CLOCK_CNTL__RDPCS_SYMCLK_DIV2_EN_MASK 0x00000200L -#define RDPCSTX0_RDPCSTX_CLOCK_CNTL__RDPCS_SYMCLK_DIV2_CLOCK_ON_MASK 0x00000400L -#define DPCSTX0_DPCSTX_TX_CNTL__DPCS_TX_DATA_SWAP_MASK 0x00004000L -#define DPCSTX0_DPCSTX_TX_CNTL__DPCS_TX_DATA_ORDER_INVERT_MASK 0x00008000L - - -#define SE_DCN3_REG_LIST(id)\ - SRI(AFMT_CNTL, DIG, id), \ - SRI(DIG_FE_CNTL, DIG, id), \ - SRI(HDMI_CONTROL, DIG, id), \ - SRI(HDMI_DB_CONTROL, DIG, id), \ - SRI(HDMI_GC, DIG, id), \ - SRI(HDMI_GENERIC_PACKET_CONTROL0, DIG, id), \ - SRI(HDMI_GENERIC_PACKET_CONTROL1, DIG, id), \ - SRI(HDMI_GENERIC_PACKET_CONTROL2, DIG, id), \ - SRI(HDMI_GENERIC_PACKET_CONTROL3, DIG, id), \ - SRI(HDMI_GENERIC_PACKET_CONTROL4, DIG, id), \ - SRI(HDMI_GENERIC_PACKET_CONTROL5, DIG, id), \ - SRI(HDMI_GENERIC_PACKET_CONTROL6, DIG, id), \ - SRI(HDMI_GENERIC_PACKET_CONTROL7, DIG, id), \ - SRI(HDMI_GENERIC_PACKET_CONTROL8, DIG, id), \ - SRI(HDMI_GENERIC_PACKET_CONTROL9, DIG, id), \ - SRI(HDMI_GENERIC_PACKET_CONTROL10, DIG, id), \ - SRI(HDMI_INFOFRAME_CONTROL0, DIG, id), \ - SRI(HDMI_INFOFRAME_CONTROL1, DIG, id), \ - SRI(HDMI_VBI_PACKET_CONTROL, DIG, id), \ - SRI(HDMI_AUDIO_PACKET_CONTROL, DIG, id),\ - SRI(HDMI_ACR_PACKET_CONTROL, DIG, id),\ - SRI(HDMI_ACR_32_0, DIG, id),\ - SRI(HDMI_ACR_32_1, DIG, id),\ - SRI(HDMI_ACR_44_0, DIG, id),\ - SRI(HDMI_ACR_44_1, DIG, id),\ - SRI(HDMI_ACR_48_0, DIG, id),\ - SRI(HDMI_ACR_48_1, DIG, id),\ - SRI(DP_DB_CNTL, DP, id), \ - SRI(DP_MSA_MISC, DP, id), \ - SRI(DP_MSA_VBID_MISC, DP, id), \ - SRI(DP_MSA_COLORIMETRY, DP, id), \ - SRI(DP_MSA_TIMING_PARAM1, DP, id), \ - SRI(DP_MSA_TIMING_PARAM2, DP, id), \ - SRI(DP_MSA_TIMING_PARAM3, DP, id), \ - SRI(DP_MSA_TIMING_PARAM4, DP, id), \ - SRI(DP_MSE_RATE_CNTL, DP, id), \ - SRI(DP_MSE_RATE_UPDATE, DP, id), \ - SRI(DP_PIXEL_FORMAT, DP, id), \ - SRI(DP_SEC_CNTL, DP, id), \ - SRI(DP_SEC_CNTL1, DP, id), \ - SRI(DP_SEC_CNTL2, DP, id), \ - SRI(DP_SEC_CNTL5, DP, id), \ - SRI(DP_SEC_CNTL6, DP, id), \ - SRI(DP_STEER_FIFO, DP, id), \ - SRI(DP_VID_M, DP, id), \ - SRI(DP_VID_N, DP, id), \ - SRI(DP_VID_STREAM_CNTL, DP, id), \ - SRI(DP_VID_TIMING, DP, id), \ - SRI(DP_SEC_AUD_N, DP, id), \ - SRI(DP_SEC_AUD_N_READBACK, DP, id), \ - SRI(DP_SEC_AUD_M_READBACK, DP, id), \ - SRI(DP_SEC_TIMESTAMP, DP, id), \ - SRI(DP_DSC_CNTL, DP, id), \ - SRI(DP_DSC_BYTES_PER_PIXEL, DP, id), \ - SRI(DP_SEC_METADATA_TRANSMISSION, DP, id), \ - SRI(HDMI_METADATA_PACKET_CONTROL, DIG, id), \ - SRI(DP_SEC_FRAMING4, DP, id), \ - SRI(DP_GSP11_CNTL, DP, id), \ - SRI(DME_CONTROL, DME, id),\ - SRI(DP_SEC_METADATA_TRANSMISSION, DP, id), \ - SRI(HDMI_METADATA_PACKET_CONTROL, DIG, id), \ - SRI(DIG_FE_CNTL, DIG, id), \ - SRI(DIG_FIFO_STATUS, DIG, id), \ - SRI(DIG_CLOCK_PATTERN, DIG, id) - - -#define SE_COMMON_MASK_SH_LIST_DCN30(mask_sh)\ - SE_SF(DP0_DP_PIXEL_FORMAT, DP_PIXEL_ENCODING, mask_sh),\ - SE_SF(DP0_DP_PIXEL_FORMAT, DP_COMPONENT_DEPTH, mask_sh),\ - SE_SF(DIG0_HDMI_CONTROL, HDMI_PACKET_GEN_VERSION, mask_sh),\ - SE_SF(DIG0_HDMI_CONTROL, HDMI_KEEPOUT_MODE, mask_sh),\ - SE_SF(DIG0_HDMI_CONTROL, HDMI_DEEP_COLOR_ENABLE, mask_sh),\ - SE_SF(DIG0_HDMI_CONTROL, HDMI_DEEP_COLOR_DEPTH, mask_sh),\ - SE_SF(DIG0_HDMI_CONTROL, HDMI_DATA_SCRAMBLE_EN, mask_sh),\ - SE_SF(DIG0_HDMI_CONTROL, HDMI_NO_EXTRA_NULL_PACKET_FILLED, mask_sh),\ - SE_SF(DIG0_HDMI_VBI_PACKET_CONTROL, HDMI_GC_CONT, mask_sh),\ - SE_SF(DIG0_HDMI_VBI_PACKET_CONTROL, HDMI_GC_SEND, mask_sh),\ - SE_SF(DIG0_HDMI_VBI_PACKET_CONTROL, HDMI_NULL_SEND, mask_sh),\ - SE_SF(DIG0_HDMI_VBI_PACKET_CONTROL, HDMI_ACP_SEND, mask_sh),\ - SE_SF(DIG0_HDMI_INFOFRAME_CONTROL0, HDMI_AUDIO_INFO_SEND, mask_sh),\ - SE_SF(DIG0_HDMI_INFOFRAME_CONTROL1, HDMI_AUDIO_INFO_LINE, mask_sh),\ - SE_SF(DIG0_HDMI_GC, HDMI_GC_AVMUTE, mask_sh),\ - SE_SF(DP0_DP_MSE_RATE_CNTL, DP_MSE_RATE_X, mask_sh),\ - SE_SF(DP0_DP_MSE_RATE_CNTL, DP_MSE_RATE_Y, mask_sh),\ - SE_SF(DP0_DP_MSE_RATE_UPDATE, DP_MSE_RATE_UPDATE_PENDING, mask_sh),\ - SE_SF(DP0_DP_SEC_CNTL, DP_SEC_GSP0_ENABLE, mask_sh),\ - SE_SF(DP0_DP_SEC_CNTL, DP_SEC_STREAM_ENABLE, mask_sh),\ - SE_SF(DP0_DP_SEC_CNTL, DP_SEC_GSP1_ENABLE, mask_sh),\ - SE_SF(DP0_DP_SEC_CNTL, DP_SEC_GSP2_ENABLE, mask_sh),\ - SE_SF(DP0_DP_SEC_CNTL, DP_SEC_GSP3_ENABLE, mask_sh),\ - SE_SF(DP0_DP_SEC_CNTL, DP_SEC_MPG_ENABLE, mask_sh),\ - SE_SF(DP0_DP_SEC_CNTL2, DP_SEC_GSP4_SEND, mask_sh),\ - SE_SF(DP0_DP_SEC_CNTL2, DP_SEC_GSP4_SEND_PENDING, mask_sh),\ - SE_SF(DP0_DP_SEC_CNTL4, DP_SEC_GSP4_LINE_NUM, mask_sh),\ - SE_SF(DP0_DP_SEC_CNTL2, DP_SEC_GSP4_SEND_ANY_LINE, mask_sh),\ - SE_SF(DP0_DP_VID_STREAM_CNTL, DP_VID_STREAM_DIS_DEFER, mask_sh),\ - SE_SF(DP0_DP_VID_STREAM_CNTL, DP_VID_STREAM_ENABLE, mask_sh),\ - SE_SF(DP0_DP_VID_STREAM_CNTL, DP_VID_STREAM_STATUS, mask_sh),\ - SE_SF(DP0_DP_STEER_FIFO, DP_STEER_FIFO_RESET, mask_sh),\ - SE_SF(DP0_DP_VID_TIMING, DP_VID_M_N_GEN_EN, mask_sh),\ - SE_SF(DP0_DP_VID_N, DP_VID_N, mask_sh),\ - SE_SF(DP0_DP_VID_M, DP_VID_M, mask_sh),\ - SE_SF(DIG0_DIG_FE_CNTL, DIG_START, mask_sh),\ - SE_SF(DIG0_HDMI_AUDIO_PACKET_CONTROL, HDMI_AUDIO_DELAY_EN, mask_sh),\ - SE_SF(DIG0_HDMI_ACR_PACKET_CONTROL, HDMI_ACR_AUTO_SEND, mask_sh),\ - SE_SF(DIG0_HDMI_ACR_PACKET_CONTROL, HDMI_ACR_SOURCE, mask_sh),\ - SE_SF(DIG0_HDMI_ACR_PACKET_CONTROL, HDMI_ACR_AUDIO_PRIORITY, mask_sh),\ - SE_SF(DIG0_HDMI_ACR_32_0, HDMI_ACR_CTS_32, mask_sh),\ - SE_SF(DIG0_HDMI_ACR_32_1, HDMI_ACR_N_32, mask_sh),\ - SE_SF(DIG0_HDMI_ACR_44_0, HDMI_ACR_CTS_44, mask_sh),\ - SE_SF(DIG0_HDMI_ACR_44_1, HDMI_ACR_N_44, mask_sh),\ - SE_SF(DIG0_HDMI_ACR_48_0, HDMI_ACR_CTS_48, mask_sh),\ - SE_SF(DIG0_HDMI_ACR_48_1, HDMI_ACR_N_48, mask_sh),\ - SE_SF(DP0_DP_SEC_AUD_N, DP_SEC_AUD_N, mask_sh),\ - SE_SF(DP0_DP_SEC_AUD_N_READBACK, DP_SEC_AUD_N_READBACK, mask_sh),\ - SE_SF(DP0_DP_SEC_AUD_M_READBACK, DP_SEC_AUD_M_READBACK, mask_sh),\ - SE_SF(DP0_DP_SEC_TIMESTAMP, DP_SEC_TIMESTAMP_MODE, mask_sh),\ - SE_SF(DP0_DP_SEC_CNTL, DP_SEC_ASP_ENABLE, mask_sh),\ - SE_SF(DP0_DP_SEC_CNTL, DP_SEC_ATP_ENABLE, mask_sh),\ - SE_SF(DP0_DP_SEC_CNTL, DP_SEC_AIP_ENABLE, mask_sh),\ - SE_SF(DP0_DP_SEC_CNTL, DP_SEC_ACM_ENABLE, mask_sh),\ - SE_SF(DIG0_AFMT_CNTL, AFMT_AUDIO_CLOCK_EN, mask_sh),\ - SE_SF(DIG0_HDMI_CONTROL, HDMI_CLOCK_CHANNEL_RATE, mask_sh),\ - SE_SF(DIG0_DIG_FE_CNTL, TMDS_PIXEL_ENCODING, mask_sh),\ - SE_SF(DIG0_DIG_FE_CNTL, TMDS_COLOR_FORMAT, mask_sh),\ - SE_SF(DIG0_DIG_FE_CNTL, DIG_STEREOSYNC_SELECT, mask_sh),\ - SE_SF(DIG0_DIG_FE_CNTL, DIG_STEREOSYNC_GATE_EN, mask_sh),\ - SE_SF(DIG0_DIG_FIFO_STATUS, DIG_FIFO_LEVEL_ERROR, mask_sh),\ - SE_SF(DIG0_DIG_FIFO_STATUS, DIG_FIFO_USE_OVERWRITE_LEVEL, mask_sh),\ - SE_SF(DIG0_DIG_FIFO_STATUS, DIG_FIFO_OVERWRITE_LEVEL, mask_sh),\ - SE_SF(DIG0_DIG_FIFO_STATUS, DIG_FIFO_ERROR_ACK, mask_sh),\ - SE_SF(DIG0_DIG_FIFO_STATUS, DIG_FIFO_CAL_AVERAGE_LEVEL, mask_sh),\ - SE_SF(DIG0_DIG_FIFO_STATUS, DIG_FIFO_MAXIMUM_LEVEL, mask_sh),\ - SE_SF(DIG0_DIG_FIFO_STATUS, DIG_FIFO_MINIMUM_LEVEL, mask_sh),\ - SE_SF(DIG0_DIG_FIFO_STATUS, DIG_FIFO_READ_CLOCK_SRC, mask_sh),\ - SE_SF(DIG0_DIG_FIFO_STATUS, DIG_FIFO_CALIBRATED, mask_sh),\ - SE_SF(DIG0_DIG_FIFO_STATUS, DIG_FIFO_FORCE_RECAL_AVERAGE, mask_sh),\ - SE_SF(DIG0_DIG_FIFO_STATUS, DIG_FIFO_FORCE_RECOMP_MINMAX, mask_sh),\ - SE_SF(DP0_DP_SEC_CNTL, DP_SEC_GSP4_ENABLE, mask_sh),\ - SE_SF(DP0_DP_SEC_CNTL, DP_SEC_GSP5_ENABLE, mask_sh),\ - SE_SF(DP0_DP_SEC_CNTL, DP_SEC_GSP6_ENABLE, mask_sh),\ - SE_SF(DP0_DP_SEC_CNTL, DP_SEC_GSP7_ENABLE, mask_sh),\ - SE_SF(DP0_DP_SEC_CNTL1, DP_SEC_GSP5_LINE_REFERENCE, mask_sh),\ - SE_SF(DP0_DP_SEC_CNTL2, DP_SEC_GSP7_SEND, mask_sh),\ - SE_SF(DP0_DP_SEC_CNTL5, DP_SEC_GSP5_LINE_NUM, mask_sh),\ - SE_SF(DP0_DP_SEC_CNTL6, DP_SEC_GSP7_LINE_NUM, mask_sh),\ - SE_SF(DP0_DP_SEC_CNTL2, DP_SEC_GSP11_PPS, mask_sh),\ - SE_SF(DP0_DP_GSP11_CNTL, DP_SEC_GSP11_ENABLE, mask_sh),\ - SE_SF(DP0_DP_GSP11_CNTL, DP_SEC_GSP11_LINE_NUM, mask_sh),\ - SE_SF(DP0_DP_DB_CNTL, DP_DB_DISABLE, mask_sh),\ - SE_SF(DP0_DP_MSA_COLORIMETRY, DP_MSA_MISC0, mask_sh),\ - SE_SF(DP0_DP_MSA_TIMING_PARAM1, DP_MSA_HTOTAL, mask_sh),\ - SE_SF(DP0_DP_MSA_TIMING_PARAM1, DP_MSA_VTOTAL, mask_sh),\ - SE_SF(DP0_DP_MSA_TIMING_PARAM2, DP_MSA_HSTART, mask_sh),\ - SE_SF(DP0_DP_MSA_TIMING_PARAM2, DP_MSA_VSTART, mask_sh),\ - SE_SF(DP0_DP_MSA_TIMING_PARAM3, DP_MSA_HSYNCWIDTH, mask_sh),\ - SE_SF(DP0_DP_MSA_TIMING_PARAM3, DP_MSA_HSYNCPOLARITY, mask_sh),\ - SE_SF(DP0_DP_MSA_TIMING_PARAM3, DP_MSA_VSYNCWIDTH, mask_sh),\ - SE_SF(DP0_DP_MSA_TIMING_PARAM3, DP_MSA_VSYNCPOLARITY, mask_sh),\ - SE_SF(DP0_DP_MSA_TIMING_PARAM4, DP_MSA_HWIDTH, mask_sh),\ - SE_SF(DP0_DP_MSA_TIMING_PARAM4, DP_MSA_VHEIGHT, mask_sh),\ - SE_SF(DIG0_HDMI_DB_CONTROL, HDMI_DB_DISABLE, mask_sh),\ - SE_SF(DP0_DP_VID_TIMING, DP_VID_N_MUL, mask_sh),\ - SE_SF(DIG0_DIG_FE_CNTL, DIG_SOURCE_SELECT, mask_sh), \ - SE_SF(DIG0_HDMI_GENERIC_PACKET_CONTROL0, HDMI_GENERIC0_CONT, mask_sh),\ - SE_SF(DIG0_HDMI_GENERIC_PACKET_CONTROL0, HDMI_GENERIC0_SEND, mask_sh),\ - SE_SF(DIG0_HDMI_GENERIC_PACKET_CONTROL0, HDMI_GENERIC1_CONT, mask_sh),\ - SE_SF(DIG0_HDMI_GENERIC_PACKET_CONTROL0, HDMI_GENERIC1_SEND, mask_sh),\ - SE_SF(DIG0_HDMI_GENERIC_PACKET_CONTROL0, HDMI_GENERIC2_CONT, mask_sh),\ - SE_SF(DIG0_HDMI_GENERIC_PACKET_CONTROL0, HDMI_GENERIC2_SEND, mask_sh),\ - SE_SF(DIG0_HDMI_GENERIC_PACKET_CONTROL0, HDMI_GENERIC3_CONT, mask_sh),\ - SE_SF(DIG0_HDMI_GENERIC_PACKET_CONTROL0, HDMI_GENERIC3_SEND, mask_sh),\ - SE_SF(DIG0_HDMI_GENERIC_PACKET_CONTROL0, HDMI_GENERIC4_CONT, mask_sh),\ - SE_SF(DIG0_HDMI_GENERIC_PACKET_CONTROL0, HDMI_GENERIC4_SEND, mask_sh),\ - SE_SF(DIG0_HDMI_GENERIC_PACKET_CONTROL0, HDMI_GENERIC5_CONT, mask_sh),\ - SE_SF(DIG0_HDMI_GENERIC_PACKET_CONTROL0, HDMI_GENERIC5_SEND, mask_sh),\ - SE_SF(DIG0_HDMI_GENERIC_PACKET_CONTROL0, HDMI_GENERIC6_CONT, mask_sh),\ - SE_SF(DIG0_HDMI_GENERIC_PACKET_CONTROL0, HDMI_GENERIC6_SEND, mask_sh),\ - SE_SF(DIG0_HDMI_GENERIC_PACKET_CONTROL0, HDMI_GENERIC7_CONT, mask_sh),\ - SE_SF(DIG0_HDMI_GENERIC_PACKET_CONTROL0, HDMI_GENERIC7_SEND, mask_sh),\ - SE_SF(DIG0_HDMI_GENERIC_PACKET_CONTROL6, HDMI_GENERIC8_CONT, mask_sh),\ - SE_SF(DIG0_HDMI_GENERIC_PACKET_CONTROL6, HDMI_GENERIC8_SEND, mask_sh),\ - SE_SF(DIG0_HDMI_GENERIC_PACKET_CONTROL6, HDMI_GENERIC9_CONT, mask_sh),\ - SE_SF(DIG0_HDMI_GENERIC_PACKET_CONTROL6, HDMI_GENERIC9_SEND, mask_sh),\ - SE_SF(DIG0_HDMI_GENERIC_PACKET_CONTROL6, HDMI_GENERIC10_CONT, mask_sh),\ - SE_SF(DIG0_HDMI_GENERIC_PACKET_CONTROL6, HDMI_GENERIC10_SEND, mask_sh),\ - SE_SF(DIG0_HDMI_GENERIC_PACKET_CONTROL6, HDMI_GENERIC11_CONT, mask_sh),\ - SE_SF(DIG0_HDMI_GENERIC_PACKET_CONTROL6, HDMI_GENERIC11_SEND, mask_sh),\ - SE_SF(DIG0_HDMI_GENERIC_PACKET_CONTROL6, HDMI_GENERIC12_CONT, mask_sh),\ - SE_SF(DIG0_HDMI_GENERIC_PACKET_CONTROL6, HDMI_GENERIC12_SEND, mask_sh),\ - SE_SF(DIG0_HDMI_GENERIC_PACKET_CONTROL6, HDMI_GENERIC13_CONT, mask_sh),\ - SE_SF(DIG0_HDMI_GENERIC_PACKET_CONTROL6, HDMI_GENERIC13_SEND, mask_sh),\ - SE_SF(DIG0_HDMI_GENERIC_PACKET_CONTROL6, HDMI_GENERIC14_CONT, mask_sh),\ - SE_SF(DIG0_HDMI_GENERIC_PACKET_CONTROL6, HDMI_GENERIC14_SEND, mask_sh),\ - SE_SF(DIG0_HDMI_GENERIC_PACKET_CONTROL1, HDMI_GENERIC0_LINE, mask_sh),\ - SE_SF(DIG0_HDMI_GENERIC_PACKET_CONTROL1, HDMI_GENERIC1_LINE, mask_sh),\ - SE_SF(DIG0_HDMI_GENERIC_PACKET_CONTROL2, HDMI_GENERIC2_LINE, mask_sh),\ - SE_SF(DIG0_HDMI_GENERIC_PACKET_CONTROL2, HDMI_GENERIC3_LINE, mask_sh),\ - SE_SF(DIG0_HDMI_GENERIC_PACKET_CONTROL3, HDMI_GENERIC4_LINE, mask_sh),\ - SE_SF(DIG0_HDMI_GENERIC_PACKET_CONTROL3, HDMI_GENERIC5_LINE, mask_sh),\ - SE_SF(DIG0_HDMI_GENERIC_PACKET_CONTROL4, HDMI_GENERIC6_LINE, mask_sh),\ - SE_SF(DIG0_HDMI_GENERIC_PACKET_CONTROL4, HDMI_GENERIC7_LINE, mask_sh),\ - SE_SF(DIG0_HDMI_GENERIC_PACKET_CONTROL7, HDMI_GENERIC8_LINE, mask_sh),\ - SE_SF(DIG0_HDMI_GENERIC_PACKET_CONTROL7, HDMI_GENERIC9_LINE, mask_sh),\ - SE_SF(DIG0_HDMI_GENERIC_PACKET_CONTROL8, HDMI_GENERIC10_LINE, mask_sh),\ - SE_SF(DIG0_HDMI_GENERIC_PACKET_CONTROL8, HDMI_GENERIC11_LINE, mask_sh),\ - SE_SF(DIG0_HDMI_GENERIC_PACKET_CONTROL9, HDMI_GENERIC12_LINE, mask_sh),\ - SE_SF(DIG0_HDMI_GENERIC_PACKET_CONTROL9, HDMI_GENERIC13_LINE, mask_sh),\ - SE_SF(DIG0_HDMI_GENERIC_PACKET_CONTROL10, HDMI_GENERIC14_LINE, mask_sh),\ - SE_SF(DP0_DP_DSC_CNTL, DP_DSC_MODE, mask_sh),\ - SE_SF(DP0_DP_DSC_CNTL, DP_DSC_SLICE_WIDTH, mask_sh),\ - SE_SF(DP0_DP_DSC_BYTES_PER_PIXEL, DP_DSC_BYTES_PER_PIXEL, mask_sh),\ - SE_SF(DP0_DP_MSA_VBID_MISC, DP_VBID6_LINE_REFERENCE, mask_sh),\ - SE_SF(DP0_DP_MSA_VBID_MISC, DP_VBID6_LINE_NUM, mask_sh),\ - SE_SF(DME0_DME_CONTROL, METADATA_ENGINE_EN, mask_sh),\ - SE_SF(DME0_DME_CONTROL, METADATA_HUBP_REQUESTOR_ID, mask_sh),\ - SE_SF(DME0_DME_CONTROL, METADATA_STREAM_TYPE, mask_sh),\ - SE_SF(DP0_DP_SEC_METADATA_TRANSMISSION, DP_SEC_METADATA_PACKET_ENABLE, mask_sh),\ - SE_SF(DP0_DP_SEC_METADATA_TRANSMISSION, DP_SEC_METADATA_PACKET_LINE_REFERENCE, mask_sh),\ - SE_SF(DP0_DP_SEC_METADATA_TRANSMISSION, DP_SEC_METADATA_PACKET_LINE, mask_sh),\ - SE_SF(DIG0_HDMI_METADATA_PACKET_CONTROL, HDMI_METADATA_PACKET_ENABLE, mask_sh),\ - SE_SF(DIG0_HDMI_METADATA_PACKET_CONTROL, HDMI_METADATA_PACKET_LINE_REFERENCE, mask_sh),\ - SE_SF(DIG0_HDMI_METADATA_PACKET_CONTROL, HDMI_METADATA_PACKET_LINE, mask_sh),\ - SE_SF(DIG0_DIG_FE_CNTL, DOLBY_VISION_EN, mask_sh),\ - SE_SF(DP0_DP_PIXEL_FORMAT, DP_PIXEL_COMBINE, mask_sh),\ - SE_SF(DP0_DP_SEC_FRAMING4, DP_SST_SDP_SPLITTING, mask_sh),\ - SE_SF(DIG0_DIG_CLOCK_PATTERN, DIG_CLOCK_PATTERN, mask_sh) - -void dcn30_dio_stream_encoder_construct( - struct dcn10_stream_encoder *enc1, - struct dc_context *ctx, - struct dc_bios *bp, - enum engine_id eng_id, - struct vpg *vpg, - struct afmt *afmt, - const struct dcn10_stream_enc_registers *regs, - const struct dcn10_stream_encoder_shift *se_shift, - const struct dcn10_stream_encoder_mask *se_mask); - -void enc3_stream_encoder_update_hdmi_info_packets( - struct stream_encoder *enc, - const struct encoder_info_frame *info_frame); - -void enc3_stream_encoder_stop_hdmi_info_packets( - struct stream_encoder *enc); - -void enc3_stream_encoder_update_dp_info_packets_sdp_line_num( - struct stream_encoder *enc, - struct encoder_info_frame *info_frame); - -void enc3_stream_encoder_update_dp_info_packets( - struct stream_encoder *enc, - const struct encoder_info_frame *info_frame); - -void enc3_audio_mute_control( - struct stream_encoder *enc, - bool mute); - -void enc3_se_dp_audio_setup( - struct stream_encoder *enc, - unsigned int az_inst, - struct audio_info *info); - -void enc3_se_dp_audio_enable( - struct stream_encoder *enc); - -void enc3_se_hdmi_audio_setup( - struct stream_encoder *enc, - unsigned int az_inst, - struct audio_info *info, - struct audio_crtc_info *audio_crtc_info); - -void enc3_dp_set_dsc_pps_info_packet( - struct stream_encoder *enc, - bool enable, - uint8_t *dsc_packed_pps, - bool immediate_update); - -#endif /* __DC_DIO_STREAM_ENCODER_DCN30_H__ */ diff --git a/drivers/gpu/drm/amd/display/dc/dcn31/Makefile b/drivers/gpu/drm/amd/display/dc/dcn31/Makefile index d9816313c3b1..e2601d0aba41 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn31/Makefile +++ b/drivers/gpu/drm/amd/display/dc/dcn31/Makefile @@ -4,7 +4,7 @@ # # Makefile for dcn31. -DCN31 = dcn31_dio_link_encoder.o dcn31_panel_cntl.o \ +DCN31 = dcn31_panel_cntl.o \ dcn31_apg.o dcn31_hpo_dp_stream_encoder.o dcn31_hpo_dp_link_encoder.o \ dcn31_afmt.o dcn31_vpg.o diff --git a/drivers/gpu/drm/amd/display/dc/dcn31/dcn31_dio_link_encoder.c b/drivers/gpu/drm/amd/display/dc/dcn31/dcn31_dio_link_encoder.c deleted file mode 100644 index b2cea59ba5d4..000000000000 --- a/drivers/gpu/drm/amd/display/dc/dcn31/dcn31_dio_link_encoder.c +++ /dev/null @@ -1,681 +0,0 @@ -/* - * Copyright 2012-15 Advanced Micro Devices, Inc. - * - * Permission is hereby granted, free of charge, to any person obtaining a - * copy of this software and associated documentation files (the "Software"), - * to deal in the Software without restriction, including without limitation - * the rights to use, copy, modify, merge, publish, distribute, sublicense, - * and/or sell copies of the Software, and to permit persons to whom the - * Software is furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL - * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR - * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, - * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR - * OTHER DEALINGS IN THE SOFTWARE. - * - * Authors: AMD - * - */ - - -#include "reg_helper.h" - -#include "core_types.h" -#include "link_encoder.h" -#include "dcn31_dio_link_encoder.h" -#include "stream_encoder.h" -#include "dc_bios_types.h" - -#include "gpio_service_interface.h" - -#include "link_enc_cfg.h" -#include "dc_dmub_srv.h" -#include "dal_asic_id.h" -#include "link.h" - -#define CTX \ - enc10->base.ctx -#define DC_LOGGER \ - enc10->base.ctx->logger - -#define REG(reg)\ - (enc10->link_regs->reg) - -#undef FN -#define FN(reg_name, field_name) \ - enc10->link_shift->field_name, enc10->link_mask->field_name - -#define IND_REG(index) \ - (enc10->link_regs->index) - -#define AUX_REG(reg)\ - (enc10->aux_regs->reg) - -#define AUX_REG_READ(reg_name) \ - dm_read_reg(CTX, AUX_REG(reg_name)) - -#define AUX_REG_WRITE(reg_name, val) \ - dm_write_reg(CTX, AUX_REG(reg_name), val) - -#ifndef MIN -#define MIN(X, Y) ((X) < (Y) ? (X) : (Y)) -#endif - -static uint8_t phy_id_from_transmitter(enum transmitter t) -{ - uint8_t phy_id; - - switch (t) { - case TRANSMITTER_UNIPHY_A: - phy_id = 0; - break; - case TRANSMITTER_UNIPHY_B: - phy_id = 1; - break; - case TRANSMITTER_UNIPHY_C: - phy_id = 2; - break; - case TRANSMITTER_UNIPHY_D: - phy_id = 3; - break; - case TRANSMITTER_UNIPHY_E: - phy_id = 4; - break; - case TRANSMITTER_UNIPHY_F: - phy_id = 5; - break; - case TRANSMITTER_UNIPHY_G: - phy_id = 6; - break; - default: - phy_id = 0; - break; - } - return phy_id; -} - -static bool has_query_dp_alt(struct link_encoder *enc) -{ - struct dc_dmub_srv *dc_dmub_srv = enc->ctx->dmub_srv; - - if (enc->ctx->dce_version >= DCN_VERSION_3_15) - return true; - - /* Supports development firmware and firmware >= 4.0.11 */ - return dc_dmub_srv && - !(dc_dmub_srv->dmub->fw_version >= DMUB_FW_VERSION(4, 0, 0) && - dc_dmub_srv->dmub->fw_version <= DMUB_FW_VERSION(4, 0, 10)); -} - -static bool query_dp_alt_from_dmub(struct link_encoder *enc, - union dmub_rb_cmd *cmd) -{ - struct dcn10_link_encoder *enc10 = TO_DCN10_LINK_ENC(enc); - - memset(cmd, 0, sizeof(*cmd)); - cmd->query_dp_alt.header.type = DMUB_CMD__VBIOS; - cmd->query_dp_alt.header.sub_type = - DMUB_CMD__VBIOS_TRANSMITTER_QUERY_DP_ALT; - cmd->query_dp_alt.header.payload_bytes = sizeof(cmd->query_dp_alt.data); - cmd->query_dp_alt.data.phy_id = phy_id_from_transmitter(enc10->base.transmitter); - - if (!dc_wake_and_execute_dmub_cmd(enc->ctx, cmd, DM_DMUB_WAIT_TYPE_WAIT_WITH_REPLY)) - return false; - - return true; -} - -void dcn31_link_encoder_set_dio_phy_mux( - struct link_encoder *enc, - enum encoder_type_select sel, - uint32_t hpo_inst) -{ - struct dcn10_link_encoder *enc10 = TO_DCN10_LINK_ENC(enc); - - switch (enc->transmitter) { - case TRANSMITTER_UNIPHY_A: - if (sel == ENCODER_TYPE_HDMI_FRL) - REG_UPDATE(DIO_LINKA_CNTL, - HPO_HDMI_ENC_SEL, hpo_inst); - else if (sel == ENCODER_TYPE_DP_128B132B) - REG_UPDATE(DIO_LINKA_CNTL, - HPO_DP_ENC_SEL, hpo_inst); - REG_UPDATE(DIO_LINKA_CNTL, - ENC_TYPE_SEL, sel); - break; - case TRANSMITTER_UNIPHY_B: - if (sel == ENCODER_TYPE_HDMI_FRL) - REG_UPDATE(DIO_LINKB_CNTL, - HPO_HDMI_ENC_SEL, hpo_inst); - else if (sel == ENCODER_TYPE_DP_128B132B) - REG_UPDATE(DIO_LINKB_CNTL, - HPO_DP_ENC_SEL, hpo_inst); - REG_UPDATE(DIO_LINKB_CNTL, - ENC_TYPE_SEL, sel); - break; - case TRANSMITTER_UNIPHY_C: - if (sel == ENCODER_TYPE_HDMI_FRL) - REG_UPDATE(DIO_LINKC_CNTL, - HPO_HDMI_ENC_SEL, hpo_inst); - else if (sel == ENCODER_TYPE_DP_128B132B) - REG_UPDATE(DIO_LINKC_CNTL, - HPO_DP_ENC_SEL, hpo_inst); - REG_UPDATE(DIO_LINKC_CNTL, - ENC_TYPE_SEL, sel); - break; - case TRANSMITTER_UNIPHY_D: - if (sel == ENCODER_TYPE_HDMI_FRL) - REG_UPDATE(DIO_LINKD_CNTL, - HPO_HDMI_ENC_SEL, hpo_inst); - else if (sel == ENCODER_TYPE_DP_128B132B) - REG_UPDATE(DIO_LINKD_CNTL, - HPO_DP_ENC_SEL, hpo_inst); - REG_UPDATE(DIO_LINKD_CNTL, - ENC_TYPE_SEL, sel); - break; - case TRANSMITTER_UNIPHY_E: - if (sel == ENCODER_TYPE_HDMI_FRL) - REG_UPDATE(DIO_LINKE_CNTL, - HPO_HDMI_ENC_SEL, hpo_inst); - else if (sel == ENCODER_TYPE_DP_128B132B) - REG_UPDATE(DIO_LINKE_CNTL, - HPO_DP_ENC_SEL, hpo_inst); - REG_UPDATE(DIO_LINKE_CNTL, - ENC_TYPE_SEL, sel); - break; - case TRANSMITTER_UNIPHY_F: - if (sel == ENCODER_TYPE_HDMI_FRL) - REG_UPDATE(DIO_LINKF_CNTL, - HPO_HDMI_ENC_SEL, hpo_inst); - else if (sel == ENCODER_TYPE_DP_128B132B) - REG_UPDATE(DIO_LINKF_CNTL, - HPO_DP_ENC_SEL, hpo_inst); - REG_UPDATE(DIO_LINKF_CNTL, - ENC_TYPE_SEL, sel); - break; - default: - /* Do nothing */ - break; - } -} - -void enc31_hw_init(struct link_encoder *enc) -{ - struct dcn10_link_encoder *enc10 = TO_DCN10_LINK_ENC(enc); - -/* - 00 - DP_AUX_DPHY_RX_DETECTION_THRESHOLD__1to2 : 1/2 - 01 - DP_AUX_DPHY_RX_DETECTION_THRESHOLD__3to4 : 3/4 - 02 - DP_AUX_DPHY_RX_DETECTION_THRESHOLD__7to8 : 7/8 - 03 - DP_AUX_DPHY_RX_DETECTION_THRESHOLD__15to16 : 15/16 - 04 - DP_AUX_DPHY_RX_DETECTION_THRESHOLD__31to32 : 31/32 - 05 - DP_AUX_DPHY_RX_DETECTION_THRESHOLD__63to64 : 63/64 - 06 - DP_AUX_DPHY_RX_DETECTION_THRESHOLD__127to128 : 127/128 - 07 - DP_AUX_DPHY_RX_DETECTION_THRESHOLD__255to256 : 255/256 -*/ - -/* - AUX_REG_UPDATE_5(AUX_DPHY_RX_CONTROL0, - AUX_RX_START_WINDOW = 1 [6:4] - AUX_RX_RECEIVE_WINDOW = 1 default is 2 [10:8] - AUX_RX_HALF_SYM_DETECT_LEN = 1 [13:12] default is 1 - AUX_RX_TRANSITION_FILTER_EN = 1 [16] default is 1 - AUX_RX_ALLOW_BELOW_THRESHOLD_PHASE_DETECT [17] is 0 default is 0 - AUX_RX_ALLOW_BELOW_THRESHOLD_START [18] is 1 default is 1 - AUX_RX_ALLOW_BELOW_THRESHOLD_STOP [19] is 1 default is 1 - AUX_RX_PHASE_DETECT_LEN, [21,20] = 0x3 default is 3 - AUX_RX_DETECTION_THRESHOLD [30:28] = 1 -*/ - // dmub will read AUX_DPHY_RX_CONTROL0/AUX_DPHY_TX_CONTROL from vbios table in dp_aux_init - - //AUX_DPHY_TX_REF_CONTROL'AUX_TX_REF_DIV HW default is 0x32; - // Set AUX_TX_REF_DIV Divider to generate 2 MHz reference from refclk - // 27MHz -> 0xd - // 100MHz -> 0x32 - // 48MHz -> 0x18 - - // Set TMDS_CTL0 to 1. This is a legacy setting. - REG_UPDATE(TMDS_CTL_BITS, TMDS_CTL0, 1); - - dcn10_aux_initialize(enc10); -} - -static const struct link_encoder_funcs dcn31_link_enc_funcs = { - .read_state = link_enc2_read_state, - .validate_output_with_stream = - dcn30_link_encoder_validate_output_with_stream, - .hw_init = enc31_hw_init, - .setup = dcn10_link_encoder_setup, - .enable_tmds_output = dcn10_link_encoder_enable_tmds_output, - .enable_dp_output = dcn31_link_encoder_enable_dp_output, - .enable_dp_mst_output = dcn31_link_encoder_enable_dp_mst_output, - .disable_output = dcn31_link_encoder_disable_output, - .dp_set_lane_settings = dcn10_link_encoder_dp_set_lane_settings, - .dp_set_phy_pattern = dcn10_link_encoder_dp_set_phy_pattern, - .update_mst_stream_allocation_table = - dcn10_link_encoder_update_mst_stream_allocation_table, - .psr_program_dp_dphy_fast_training = - dcn10_psr_program_dp_dphy_fast_training, - .psr_program_secondary_packet = dcn10_psr_program_secondary_packet, - .connect_dig_be_to_fe = dcn10_link_encoder_connect_dig_be_to_fe, - .enable_hpd = dcn10_link_encoder_enable_hpd, - .disable_hpd = dcn10_link_encoder_disable_hpd, - .is_dig_enabled = dcn10_is_dig_enabled, - .destroy = dcn10_link_encoder_destroy, - .fec_set_enable = enc2_fec_set_enable, - .fec_set_ready = enc2_fec_set_ready, - .fec_is_active = enc2_fec_is_active, - .get_dig_frontend = dcn10_get_dig_frontend, - .get_dig_mode = dcn10_get_dig_mode, - .is_in_alt_mode = dcn31_link_encoder_is_in_alt_mode, - .get_max_link_cap = dcn31_link_encoder_get_max_link_cap, - .set_dio_phy_mux = dcn31_link_encoder_set_dio_phy_mux, -}; - -void dcn31_link_encoder_construct( - struct dcn20_link_encoder *enc20, - const struct encoder_init_data *init_data, - const struct encoder_feature_support *enc_features, - const struct dcn10_link_enc_registers *link_regs, - const struct dcn10_link_enc_aux_registers *aux_regs, - const struct dcn10_link_enc_hpd_registers *hpd_regs, - const struct dcn10_link_enc_shift *link_shift, - const struct dcn10_link_enc_mask *link_mask) -{ - struct bp_encoder_cap_info bp_cap_info = {0}; - const struct dc_vbios_funcs *bp_funcs = init_data->ctx->dc_bios->funcs; - enum bp_result result = BP_RESULT_OK; - struct dcn10_link_encoder *enc10 = &enc20->enc10; - - enc10->base.funcs = &dcn31_link_enc_funcs; - enc10->base.ctx = init_data->ctx; - enc10->base.id = init_data->encoder; - - enc10->base.hpd_source = init_data->hpd_source; - enc10->base.connector = init_data->connector; - - enc10->base.preferred_engine = ENGINE_ID_UNKNOWN; - - enc10->base.features = *enc_features; - - enc10->base.transmitter = init_data->transmitter; - - /* set the flag to indicate whether driver poll the I2C data pin - * while doing the DP sink detect - */ - -/* if (dal_adapter_service_is_feature_supported(as, - FEATURE_DP_SINK_DETECT_POLL_DATA_PIN)) - enc10->base.features.flags.bits. - DP_SINK_DETECT_POLL_DATA_PIN = true;*/ - - enc10->base.output_signals = - SIGNAL_TYPE_DVI_SINGLE_LINK | - SIGNAL_TYPE_DVI_DUAL_LINK | - SIGNAL_TYPE_LVDS | - SIGNAL_TYPE_DISPLAY_PORT | - SIGNAL_TYPE_DISPLAY_PORT_MST | - SIGNAL_TYPE_EDP | - SIGNAL_TYPE_HDMI_TYPE_A; - - /* For DCE 8.0 and 8.1, by design, UNIPHY is hardwired to DIG_BE. - * SW always assign DIG_FE 1:1 mapped to DIG_FE for non-MST UNIPHY. - * SW assign DIG_FE to non-MST UNIPHY first and MST last. So prefer - * DIG is per UNIPHY and used by SST DP, eDP, HDMI, DVI and LVDS. - * Prefer DIG assignment is decided by board design. - * For DCE 8.0, there are only max 6 UNIPHYs, we assume board design - * and VBIOS will filter out 7 UNIPHY for DCE 8.0. - * By this, adding DIGG should not hurt DCE 8.0. - * This will let DCE 8.1 share DCE 8.0 as much as possible - */ - - enc10->link_regs = link_regs; - enc10->aux_regs = aux_regs; - enc10->hpd_regs = hpd_regs; - enc10->link_shift = link_shift; - enc10->link_mask = link_mask; - - switch (enc10->base.transmitter) { - case TRANSMITTER_UNIPHY_A: - enc10->base.preferred_engine = ENGINE_ID_DIGA; - break; - case TRANSMITTER_UNIPHY_B: - enc10->base.preferred_engine = ENGINE_ID_DIGB; - break; - case TRANSMITTER_UNIPHY_C: - enc10->base.preferred_engine = ENGINE_ID_DIGC; - break; - case TRANSMITTER_UNIPHY_D: - enc10->base.preferred_engine = ENGINE_ID_DIGD; - break; - case TRANSMITTER_UNIPHY_E: - enc10->base.preferred_engine = ENGINE_ID_DIGE; - break; - case TRANSMITTER_UNIPHY_F: - enc10->base.preferred_engine = ENGINE_ID_DIGF; - break; - default: - ASSERT_CRITICAL(false); - enc10->base.preferred_engine = ENGINE_ID_UNKNOWN; - } - - /* default to one to mirror Windows behavior */ - enc10->base.features.flags.bits.HDMI_6GB_EN = 1; - - result = bp_funcs->get_encoder_cap_info(enc10->base.ctx->dc_bios, - enc10->base.id, &bp_cap_info); - - /* Override features with DCE-specific values */ - if (result == BP_RESULT_OK) { - enc10->base.features.flags.bits.IS_HBR2_CAPABLE = - bp_cap_info.DP_HBR2_EN; - enc10->base.features.flags.bits.IS_HBR3_CAPABLE = - bp_cap_info.DP_HBR3_EN; - enc10->base.features.flags.bits.HDMI_6GB_EN = bp_cap_info.HDMI_6GB_EN; - enc10->base.features.flags.bits.IS_DP2_CAPABLE = bp_cap_info.IS_DP2_CAPABLE; - enc10->base.features.flags.bits.IS_UHBR10_CAPABLE = bp_cap_info.DP_UHBR10_EN; - enc10->base.features.flags.bits.IS_UHBR13_5_CAPABLE = bp_cap_info.DP_UHBR13_5_EN; - enc10->base.features.flags.bits.IS_UHBR20_CAPABLE = bp_cap_info.DP_UHBR20_EN; - enc10->base.features.flags.bits.DP_IS_USB_C = - bp_cap_info.DP_IS_USB_C; - } else { - DC_LOG_WARNING("%s: Failed to get encoder_cap_info from VBIOS with error code %d!\n", - __func__, - result); - } - if (enc10->base.ctx->dc->debug.hdmi20_disable) { - enc10->base.features.flags.bits.HDMI_6GB_EN = 0; - } -} - -void dcn31_link_encoder_construct_minimal( - struct dcn20_link_encoder *enc20, - struct dc_context *ctx, - const struct encoder_feature_support *enc_features, - const struct dcn10_link_enc_registers *link_regs, - enum engine_id eng_id) -{ - struct dcn10_link_encoder *enc10 = &enc20->enc10; - - enc10->base.funcs = &dcn31_link_enc_funcs; - enc10->base.ctx = ctx; - enc10->base.id.type = OBJECT_TYPE_ENCODER; - enc10->base.hpd_source = HPD_SOURCEID_UNKNOWN; - enc10->base.connector.type = OBJECT_TYPE_CONNECTOR; - enc10->base.preferred_engine = eng_id; - enc10->base.features = *enc_features; - enc10->base.transmitter = TRANSMITTER_UNKNOWN; - enc10->link_regs = link_regs; - - enc10->base.output_signals = - SIGNAL_TYPE_DISPLAY_PORT | - SIGNAL_TYPE_DISPLAY_PORT_MST | - SIGNAL_TYPE_EDP; -} - -/* DPIA equivalent of link_transmitter_control. */ -static bool link_dpia_control(struct dc_context *dc_ctx, - struct dmub_cmd_dig_dpia_control_data *dpia_control) -{ - union dmub_rb_cmd cmd; - - memset(&cmd, 0, sizeof(cmd)); - - cmd.dig1_dpia_control.header.type = DMUB_CMD__DPIA; - cmd.dig1_dpia_control.header.sub_type = - DMUB_CMD__DPIA_DIG1_DPIA_CONTROL; - cmd.dig1_dpia_control.header.payload_bytes = - sizeof(cmd.dig1_dpia_control) - - sizeof(cmd.dig1_dpia_control.header); - - cmd.dig1_dpia_control.dpia_control = *dpia_control; - - dc_wake_and_execute_dmub_cmd(dc_ctx, &cmd, DM_DMUB_WAIT_TYPE_WAIT); - - return true; -} - -static void link_encoder_disable(struct dcn10_link_encoder *enc10) -{ - /* reset training complete */ - REG_UPDATE(DP_LINK_CNTL, DP_LINK_TRAINING_COMPLETE, 0); -} - -void dcn31_link_encoder_enable_dp_output( - struct link_encoder *enc, - const struct dc_link_settings *link_settings, - enum clock_source_id clock_source) -{ - struct dcn10_link_encoder *enc10 = TO_DCN10_LINK_ENC(enc); - - /* Enable transmitter and encoder. */ - if (!link_enc_cfg_is_transmitter_mappable(enc->ctx->dc, enc)) { - - DC_LOG_DEBUG("%s: enc_id(%d)\n", __func__, enc->preferred_engine); - dcn20_link_encoder_enable_dp_output(enc, link_settings, clock_source); - - } else { - - struct dmub_cmd_dig_dpia_control_data dpia_control = { 0 }; - struct dc_link *link; - - link = link_enc_cfg_get_link_using_link_enc(enc->ctx->dc, enc->preferred_engine); - - enc1_configure_encoder(enc10, link_settings); - - dpia_control.action = (uint8_t)TRANSMITTER_CONTROL_ENABLE; - dpia_control.enc_id = enc->preferred_engine; - dpia_control.mode_laneset.digmode = 0; /* 0 for SST; 5 for MST */ - dpia_control.lanenum = (uint8_t)link_settings->lane_count; - dpia_control.symclk_10khz = link_settings->link_rate * - LINK_RATE_REF_FREQ_IN_KHZ / 10; - /* DIG_BE_CNTL.DIG_HPD_SELECT set to 5 (hpdsel - 1) to indicate HPD pin - * unused by DPIA. - */ - dpia_control.hpdsel = 6; - - if (link) { - dpia_control.dpia_id = link->ddc_hw_inst; - dpia_control.fec_rdy = link->dc->link_srv->dp_should_enable_fec(link); - } else { - DC_LOG_ERROR("%s: Failed to execute DPIA enable DMUB command.\n", __func__); - BREAK_TO_DEBUGGER(); - return; - } - - DC_LOG_DEBUG("%s: DPIA(%d) - enc_id(%d)\n", __func__, dpia_control.dpia_id, dpia_control.enc_id); - link_dpia_control(enc->ctx, &dpia_control); - } -} - -void dcn31_link_encoder_enable_dp_mst_output( - struct link_encoder *enc, - const struct dc_link_settings *link_settings, - enum clock_source_id clock_source) -{ - struct dcn10_link_encoder *enc10 = TO_DCN10_LINK_ENC(enc); - - /* Enable transmitter and encoder. */ - if (!link_enc_cfg_is_transmitter_mappable(enc->ctx->dc, enc)) { - - DC_LOG_DEBUG("%s: enc_id(%d)\n", __func__, enc->preferred_engine); - dcn10_link_encoder_enable_dp_mst_output(enc, link_settings, clock_source); - - } else { - - struct dmub_cmd_dig_dpia_control_data dpia_control = { 0 }; - struct dc_link *link; - - link = link_enc_cfg_get_link_using_link_enc(enc->ctx->dc, enc->preferred_engine); - - enc1_configure_encoder(enc10, link_settings); - - dpia_control.action = (uint8_t)TRANSMITTER_CONTROL_ENABLE; - dpia_control.enc_id = enc->preferred_engine; - dpia_control.mode_laneset.digmode = 5; /* 0 for SST; 5 for MST */ - dpia_control.lanenum = (uint8_t)link_settings->lane_count; - dpia_control.symclk_10khz = link_settings->link_rate * - LINK_RATE_REF_FREQ_IN_KHZ / 10; - /* DIG_BE_CNTL.DIG_HPD_SELECT set to 5 (hpdsel - 1) to indicate HPD pin - * unused by DPIA. - */ - dpia_control.hpdsel = 6; - - if (link) { - dpia_control.dpia_id = link->ddc_hw_inst; - dpia_control.fec_rdy = link->dc->link_srv->dp_should_enable_fec(link); - } else { - DC_LOG_ERROR("%s: Failed to execute DPIA enable DMUB command.\n", __func__); - BREAK_TO_DEBUGGER(); - return; - } - - DC_LOG_DEBUG("%s: DPIA(%d) - enc_id(%d)\n", __func__, dpia_control.dpia_id, dpia_control.enc_id); - link_dpia_control(enc->ctx, &dpia_control); - } -} - -void dcn31_link_encoder_disable_output( - struct link_encoder *enc, - enum signal_type signal) -{ - struct dcn10_link_encoder *enc10 = TO_DCN10_LINK_ENC(enc); - - /* Disable transmitter and encoder. */ - if (!link_enc_cfg_is_transmitter_mappable(enc->ctx->dc, enc)) { - - DC_LOG_DEBUG("%s: enc_id(%d)\n", __func__, enc->preferred_engine); - dcn10_link_encoder_disable_output(enc, signal); - - } else { - - struct dmub_cmd_dig_dpia_control_data dpia_control = { 0 }; - struct dc_link *link; - - if (enc->funcs->is_dig_enabled && !enc->funcs->is_dig_enabled(enc)) - return; - - link = link_enc_cfg_get_link_using_link_enc(enc->ctx->dc, enc->preferred_engine); - - dpia_control.action = (uint8_t)TRANSMITTER_CONTROL_DISABLE; - dpia_control.enc_id = enc->preferred_engine; - if (signal == SIGNAL_TYPE_DISPLAY_PORT) { - dpia_control.mode_laneset.digmode = 0; /* 0 for SST; 5 for MST */ - } else if (signal == SIGNAL_TYPE_DISPLAY_PORT_MST) { - dpia_control.mode_laneset.digmode = 5; /* 0 for SST; 5 for MST */ - } else { - DC_LOG_ERROR("%s: USB4 DPIA only supports DisplayPort.\n", __func__); - BREAK_TO_DEBUGGER(); - } - - if (link) { - dpia_control.dpia_id = link->ddc_hw_inst; - } else { - DC_LOG_ERROR("%s: Failed to execute DPIA enable DMUB command.\n", __func__); - BREAK_TO_DEBUGGER(); - return; - } - - DC_LOG_DEBUG("%s: DPIA(%d) - enc_id(%d)\n", __func__, dpia_control.dpia_id, dpia_control.enc_id); - link_dpia_control(enc->ctx, &dpia_control); - - link_encoder_disable(enc10); - } -} - -bool dcn31_link_encoder_is_in_alt_mode(struct link_encoder *enc) -{ - struct dcn10_link_encoder *enc10 = TO_DCN10_LINK_ENC(enc); - union dmub_rb_cmd cmd; - uint32_t dp_alt_mode_disable; - - /* Only applicable to USB-C PHY. */ - if (!enc->features.flags.bits.DP_IS_USB_C) - return false; - - /* - * Use the new interface from DMCUB if available. - * Avoids hanging the RDCPSPIPE if DMCUB wasn't already running. - */ - if (has_query_dp_alt(enc)) { - if (!query_dp_alt_from_dmub(enc, &cmd)) - return false; - - return (cmd.query_dp_alt.data.is_dp_alt_disable == 0); - } - - /* Legacy path, avoid if possible. */ - if (enc->ctx->asic_id.hw_internal_rev != YELLOW_CARP_B0) { - REG_GET(RDPCSTX_PHY_CNTL6, RDPCS_PHY_DPALT_DISABLE, - &dp_alt_mode_disable); - } else { - /* - * B0 phys use a new set of registers to check whether alt mode is disabled. - * if value == 1 alt mode is disabled, otherwise it is enabled. - */ - if ((enc10->base.transmitter == TRANSMITTER_UNIPHY_A) || - (enc10->base.transmitter == TRANSMITTER_UNIPHY_B) || - (enc10->base.transmitter == TRANSMITTER_UNIPHY_E)) { - REG_GET(RDPCSTX_PHY_CNTL6, RDPCS_PHY_DPALT_DISABLE, - &dp_alt_mode_disable); - } else { - REG_GET(RDPCSPIPE_PHY_CNTL6, RDPCS_PHY_DPALT_DISABLE, - &dp_alt_mode_disable); - } - } - - return (dp_alt_mode_disable == 0); -} - -void dcn31_link_encoder_get_max_link_cap(struct link_encoder *enc, struct dc_link_settings *link_settings) -{ - struct dcn10_link_encoder *enc10 = TO_DCN10_LINK_ENC(enc); - union dmub_rb_cmd cmd; - uint32_t is_in_usb_c_dp4_mode = 0; - - dcn10_link_encoder_get_max_link_cap(enc, link_settings); - - /* Take the link cap directly if not USB */ - if (!enc->features.flags.bits.DP_IS_USB_C) - return; - - /* - * Use the new interface from DMCUB if available. - * Avoids hanging the RDCPSPIPE if DMCUB wasn't already running. - */ - if (has_query_dp_alt(enc)) { - if (!query_dp_alt_from_dmub(enc, &cmd)) - return; - - if (cmd.query_dp_alt.data.is_usb && - cmd.query_dp_alt.data.is_dp4 == 0) - link_settings->lane_count = MIN(LANE_COUNT_TWO, link_settings->lane_count); - - return; - } - - /* Legacy path, avoid if possible. */ - if (enc->ctx->asic_id.hw_internal_rev != YELLOW_CARP_B0) { - REG_GET(RDPCSTX_PHY_CNTL6, RDPCS_PHY_DPALT_DP4, - &is_in_usb_c_dp4_mode); - } else { - if ((enc10->base.transmitter == TRANSMITTER_UNIPHY_A) || - (enc10->base.transmitter == TRANSMITTER_UNIPHY_B) || - (enc10->base.transmitter == TRANSMITTER_UNIPHY_E)) { - REG_GET(RDPCSTX_PHY_CNTL6, RDPCS_PHY_DPALT_DP4, - &is_in_usb_c_dp4_mode); - } else { - REG_GET(RDPCSPIPE_PHY_CNTL6, RDPCS_PHY_DPALT_DP4, - &is_in_usb_c_dp4_mode); - } - } - - if (!is_in_usb_c_dp4_mode) - link_settings->lane_count = MIN(LANE_COUNT_TWO, link_settings->lane_count); -} diff --git a/drivers/gpu/drm/amd/display/dc/dcn31/dcn31_dio_link_encoder.h b/drivers/gpu/drm/amd/display/dc/dcn31/dcn31_dio_link_encoder.h deleted file mode 100644 index ee78ba80797c..000000000000 --- a/drivers/gpu/drm/amd/display/dc/dcn31/dcn31_dio_link_encoder.h +++ /dev/null @@ -1,290 +0,0 @@ -/* - * Copyright 2012-15 Advanced Micro Devices, Inc. - * - * Permission is hereby granted, free of charge, to any person obtaining a - * copy of this software and associated documentation files (the "Software"), - * to deal in the Software without restriction, including without limitation - * the rights to use, copy, modify, merge, publish, distribute, sublicense, - * and/or sell copies of the Software, and to permit persons to whom the - * Software is furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL - * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR - * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, - * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR - * OTHER DEALINGS IN THE SOFTWARE. - * - * Authors: AMD - * - */ - -#ifndef __DC_LINK_ENCODER__DCN31_H__ -#define __DC_LINK_ENCODER__DCN31_H__ - -#include "dcn30/dcn30_dio_link_encoder.h" - - -#define LE_DCN31_REG_LIST(id)\ - LE_DCN3_REG_LIST(id),\ - SRI(DP_DPHY_INTERNAL_CTRL, DP, id), \ - SR(DIO_LINKA_CNTL), \ - SR(DIO_LINKB_CNTL), \ - SR(DIO_LINKC_CNTL), \ - SR(DIO_LINKD_CNTL), \ - SR(DIO_LINKE_CNTL), \ - SR(DIO_LINKF_CNTL) - -#define LINK_ENCODER_MASK_SH_LIST_DCN31(mask_sh) \ - LINK_ENCODER_MASK_SH_LIST_DCN10(mask_sh),\ - LE_SF(DP0_DP_DPHY_CNTL, DPHY_FEC_EN, mask_sh),\ - LE_SF(DP0_DP_DPHY_CNTL, DPHY_FEC_READY_SHADOW, mask_sh),\ - LE_SF(DP0_DP_DPHY_CNTL, DPHY_FEC_ACTIVE_STATUS, mask_sh),\ - LE_SF(DIG0_TMDS_CTL_BITS, TMDS_CTL0, mask_sh), \ - LE_SF(DP_AUX0_AUX_DPHY_RX_CONTROL0, AUX_RX_START_WINDOW, mask_sh),\ - LE_SF(DP_AUX0_AUX_DPHY_RX_CONTROL0, AUX_RX_HALF_SYM_DETECT_LEN, mask_sh),\ - LE_SF(DP_AUX0_AUX_DPHY_RX_CONTROL0, AUX_RX_TRANSITION_FILTER_EN, mask_sh),\ - LE_SF(DP_AUX0_AUX_DPHY_RX_CONTROL0, AUX_RX_ALLOW_BELOW_THRESHOLD_PHASE_DETECT, mask_sh),\ - LE_SF(DP_AUX0_AUX_DPHY_RX_CONTROL0, AUX_RX_ALLOW_BELOW_THRESHOLD_START, mask_sh),\ - LE_SF(DP_AUX0_AUX_DPHY_RX_CONTROL0, AUX_RX_ALLOW_BELOW_THRESHOLD_STOP, mask_sh),\ - LE_SF(DP_AUX0_AUX_DPHY_RX_CONTROL0, AUX_RX_PHASE_DETECT_LEN, mask_sh),\ - LE_SF(DP_AUX0_AUX_DPHY_RX_CONTROL0, AUX_RX_DETECTION_THRESHOLD, mask_sh), \ - LE_SF(DP_AUX0_AUX_DPHY_TX_CONTROL, AUX_TX_PRECHARGE_LEN, mask_sh),\ - LE_SF(DP_AUX0_AUX_DPHY_TX_CONTROL, AUX_TX_PRECHARGE_SYMBOLS, mask_sh),\ - LE_SF(DP_AUX0_AUX_DPHY_TX_CONTROL, AUX_MODE_DET_CHECK_DELAY, mask_sh),\ - LE_SF(DP_AUX0_AUX_DPHY_RX_CONTROL1, AUX_RX_PRECHARGE_SKIP, mask_sh),\ - LE_SF(DP_AUX0_AUX_DPHY_RX_CONTROL1, AUX_RX_TIMEOUT_LEN, mask_sh),\ - LE_SF(DP_AUX0_AUX_DPHY_RX_CONTROL1, AUX_RX_TIMEOUT_LEN_MUL, mask_sh),\ - LE_SF(DIO_LINKA_CNTL, ENC_TYPE_SEL, mask_sh),\ - LE_SF(DIO_LINKA_CNTL, HPO_DP_ENC_SEL, mask_sh),\ - LE_SF(DIO_LINKA_CNTL, HPO_HDMI_ENC_SEL, mask_sh) - -#define DPCS_DCN31_REG_LIST(id) \ - SRI(TMDS_CTL_BITS, DIG, id), \ - SRI(RDPCSTX_PHY_CNTL3, RDPCSTX, id), \ - SRI(RDPCSTX_PHY_CNTL4, RDPCSTX, id), \ - SRI(RDPCSTX_PHY_CNTL5, RDPCSTX, id), \ - SRI(RDPCSTX_PHY_CNTL6, RDPCSTX, id), \ - SRI(RDPCSPIPE_PHY_CNTL6, RDPCSPIPE, id), \ - SRI(RDPCSTX_PHY_CNTL7, RDPCSTX, id), \ - SRI(RDPCSTX_PHY_CNTL8, RDPCSTX, id), \ - SRI(RDPCSTX_PHY_CNTL9, RDPCSTX, id), \ - SRI(RDPCSTX_PHY_CNTL10, RDPCSTX, id), \ - SRI(RDPCSTX_PHY_CNTL11, RDPCSTX, id), \ - SRI(RDPCSTX_PHY_CNTL12, RDPCSTX, id), \ - SRI(RDPCSTX_PHY_CNTL13, RDPCSTX, id), \ - SRI(RDPCSTX_PHY_CNTL14, RDPCSTX, id), \ - SRI(RDPCSTX_CNTL, RDPCSTX, id), \ - SRI(RDPCSTX_CLOCK_CNTL, RDPCSTX, id), \ - SRI(RDPCSTX_INTERRUPT_CONTROL, RDPCSTX, id), \ - SRI(RDPCSTX_PHY_CNTL0, RDPCSTX, id), \ - SRI(RDPCSTX_PHY_CNTL2, RDPCSTX, id), \ - SRI(RDPCS_TX_CR_ADDR, RDPCSTX, id), \ - SRI(RDPCS_TX_CR_DATA, RDPCSTX, id), \ - SRI(RDPCSTX_PHY_FUSE0, RDPCSTX, id), \ - SRI(RDPCSTX_PHY_FUSE1, RDPCSTX, id), \ - SRI(RDPCSTX_PHY_FUSE2, RDPCSTX, id), \ - SRI(RDPCSTX_PHY_FUSE3, RDPCSTX, id), \ - SRI(RDPCSTX_DEBUG_CONFIG, RDPCSTX, id), \ - SR(RDPCSTX0_RDPCSTX_SCRATCH), \ - SRI(RDPCSTX_PHY_RX_LD_VAL, RDPCSTX, id),\ - SRI(RDPCSTX_DMCU_DPALT_DIS_BLOCK_REG, RDPCSTX, id) - -#define DPCS_DCN31_MASK_SH_LIST(mask_sh)\ - LE_SF(RDPCSTX0_RDPCSTX_PHY_CNTL3, RDPCS_PHY_DP_TX0_CLK_RDY, mask_sh),\ - LE_SF(RDPCSTX0_RDPCSTX_PHY_CNTL3, RDPCS_PHY_DP_TX0_DATA_EN, mask_sh),\ - LE_SF(RDPCSTX0_RDPCSTX_PHY_CNTL3, RDPCS_PHY_DP_TX1_CLK_RDY, mask_sh),\ - LE_SF(RDPCSTX0_RDPCSTX_PHY_CNTL3, RDPCS_PHY_DP_TX1_DATA_EN, mask_sh),\ - LE_SF(RDPCSTX0_RDPCSTX_PHY_CNTL3, RDPCS_PHY_DP_TX2_CLK_RDY, mask_sh),\ - LE_SF(RDPCSTX0_RDPCSTX_PHY_CNTL3, RDPCS_PHY_DP_TX2_DATA_EN, mask_sh),\ - LE_SF(RDPCSTX0_RDPCSTX_PHY_CNTL3, RDPCS_PHY_DP_TX3_CLK_RDY, mask_sh),\ - LE_SF(RDPCSTX0_RDPCSTX_PHY_CNTL3, RDPCS_PHY_DP_TX3_DATA_EN, mask_sh),\ - LE_SF(RDPCSTX0_RDPCSTX_PHY_CNTL4, RDPCS_PHY_DP_TX0_TERM_CTRL, mask_sh),\ - LE_SF(RDPCSTX0_RDPCSTX_PHY_CNTL4, RDPCS_PHY_DP_TX1_TERM_CTRL, mask_sh),\ - LE_SF(RDPCSTX0_RDPCSTX_PHY_CNTL4, RDPCS_PHY_DP_TX2_TERM_CTRL, mask_sh),\ - LE_SF(RDPCSTX0_RDPCSTX_PHY_CNTL4, RDPCS_PHY_DP_TX3_TERM_CTRL, mask_sh),\ - LE_SF(RDPCSTX0_RDPCSTX_PHY_CNTL11, RDPCS_PHY_DP_MPLLB_MULTIPLIER, mask_sh),\ - LE_SF(RDPCSTX0_RDPCSTX_PHY_CNTL5, RDPCS_PHY_DP_TX0_WIDTH, mask_sh),\ - LE_SF(RDPCSTX0_RDPCSTX_PHY_CNTL5, RDPCS_PHY_DP_TX0_RATE, mask_sh),\ - LE_SF(RDPCSTX0_RDPCSTX_PHY_CNTL5, RDPCS_PHY_DP_TX1_WIDTH, mask_sh),\ - LE_SF(RDPCSTX0_RDPCSTX_PHY_CNTL5, RDPCS_PHY_DP_TX1_RATE, mask_sh),\ - LE_SF(RDPCSTX0_RDPCSTX_PHY_CNTL6, RDPCS_PHY_DP_TX2_PSTATE, mask_sh),\ - LE_SF(RDPCSTX0_RDPCSTX_PHY_CNTL6, RDPCS_PHY_DP_TX3_PSTATE, mask_sh),\ - LE_SF(RDPCSTX0_RDPCSTX_PHY_CNTL6, RDPCS_PHY_DP_TX2_MPLL_EN, mask_sh),\ - LE_SF(RDPCSTX0_RDPCSTX_PHY_CNTL6, RDPCS_PHY_DP_TX3_MPLL_EN, mask_sh),\ - LE_SF(RDPCSTX0_RDPCSTX_PHY_CNTL6, RDPCS_PHY_DPALT_DP4, mask_sh),\ - LE_SF(RDPCSPIPE0_RDPCSPIPE_PHY_CNTL6, RDPCS_PHY_DPALT_DP4, mask_sh),\ - LE_SF(RDPCSPIPE0_RDPCSPIPE_PHY_CNTL6, RDPCS_PHY_DPALT_DISABLE, mask_sh),\ - LE_SF(RDPCSPIPE0_RDPCSPIPE_PHY_CNTL6, RDPCS_PHY_DPALT_DISABLE_ACK, mask_sh),\ - LE_SF(RDPCSTX0_RDPCSTX_PHY_CNTL7, RDPCS_PHY_DP_MPLLB_FRACN_QUOT, mask_sh),\ - LE_SF(RDPCSTX0_RDPCSTX_PHY_CNTL7, RDPCS_PHY_DP_MPLLB_FRACN_DEN, mask_sh),\ - LE_SF(RDPCSTX0_RDPCSTX_PHY_CNTL8, RDPCS_PHY_DP_MPLLB_SSC_PEAK, mask_sh),\ - LE_SF(RDPCSTX0_RDPCSTX_PHY_CNTL9, RDPCS_PHY_DP_MPLLB_SSC_UP_SPREAD, mask_sh),\ - LE_SF(RDPCSTX0_RDPCSTX_PHY_CNTL9, RDPCS_PHY_DP_MPLLB_SSC_STEPSIZE, mask_sh),\ - LE_SF(RDPCSTX0_RDPCSTX_PHY_CNTL10, RDPCS_PHY_DP_MPLLB_FRACN_REM, mask_sh),\ - LE_SF(RDPCSTX0_RDPCSTX_PHY_CNTL11, RDPCS_PHY_DP_REF_CLK_MPLLB_DIV, mask_sh),\ - LE_SF(RDPCSTX0_RDPCSTX_PHY_CNTL11, RDPCS_PHY_HDMI_MPLLB_HDMI_DIV, mask_sh),\ - LE_SF(RDPCSTX0_RDPCSTX_PHY_CNTL12, RDPCS_PHY_DP_MPLLB_SSC_EN, mask_sh),\ - LE_SF(RDPCSTX0_RDPCSTX_PHY_CNTL12, RDPCS_PHY_DP_MPLLB_DIV5_CLK_EN, mask_sh),\ - LE_SF(RDPCSTX0_RDPCSTX_PHY_CNTL12, RDPCS_PHY_DP_MPLLB_TX_CLK_DIV, mask_sh),\ - LE_SF(RDPCSTX0_RDPCSTX_PHY_CNTL12, RDPCS_PHY_DP_MPLLB_WORD_DIV2_EN, mask_sh),\ - LE_SF(RDPCSTX0_RDPCSTX_PHY_CNTL12, RDPCS_PHY_DP_MPLLB_STATE, mask_sh),\ - LE_SF(RDPCSTX0_RDPCSTX_PHY_CNTL13, RDPCS_PHY_DP_MPLLB_DIV_CLK_EN, mask_sh),\ - LE_SF(RDPCSTX0_RDPCSTX_PHY_CNTL13, RDPCS_PHY_DP_MPLLB_DIV_MULTIPLIER, mask_sh),\ - LE_SF(RDPCSTX0_RDPCSTX_PHY_CNTL14, RDPCS_PHY_DP_MPLLB_FRACN_EN, mask_sh),\ - LE_SF(RDPCSTX0_RDPCSTX_PHY_CNTL14, RDPCS_PHY_DP_MPLLB_PMIX_EN, mask_sh),\ - LE_SF(RDPCSTX0_RDPCSTX_CNTL, RDPCS_TX_FIFO_LANE0_EN, mask_sh),\ - LE_SF(RDPCSTX0_RDPCSTX_CNTL, RDPCS_TX_FIFO_LANE1_EN, mask_sh),\ - LE_SF(RDPCSTX0_RDPCSTX_CNTL, RDPCS_TX_FIFO_LANE2_EN, mask_sh),\ - LE_SF(RDPCSTX0_RDPCSTX_CNTL, RDPCS_TX_FIFO_LANE3_EN, mask_sh),\ - LE_SF(RDPCSTX0_RDPCSTX_CNTL, RDPCS_TX_FIFO_EN, mask_sh),\ - LE_SF(RDPCSTX0_RDPCSTX_CNTL, RDPCS_TX_FIFO_RD_START_DELAY, mask_sh),\ - LE_SF(RDPCSTX0_RDPCSTX_CLOCK_CNTL, RDPCS_EXT_REFCLK_EN, mask_sh),\ - LE_SF(RDPCSTX0_RDPCSTX_CLOCK_CNTL, RDPCS_SRAMCLK_BYPASS, mask_sh),\ - LE_SF(RDPCSTX0_RDPCSTX_CLOCK_CNTL, RDPCS_SRAMCLK_EN, mask_sh),\ - LE_SF(RDPCSTX0_RDPCSTX_CLOCK_CNTL, RDPCS_SRAMCLK_CLOCK_ON, mask_sh),\ - LE_SF(RDPCSTX0_RDPCSTX_CLOCK_CNTL, RDPCS_SYMCLK_DIV2_CLOCK_ON, mask_sh),\ - LE_SF(RDPCSTX0_RDPCSTX_CLOCK_CNTL, RDPCS_SYMCLK_DIV2_GATE_DIS, mask_sh),\ - LE_SF(RDPCSTX0_RDPCSTX_CLOCK_CNTL, RDPCS_SYMCLK_DIV2_EN, mask_sh),\ - LE_SF(RDPCSTX0_RDPCSTX_PHY_CNTL3, RDPCS_PHY_DP_TX0_DISABLE, mask_sh),\ - LE_SF(RDPCSTX0_RDPCSTX_PHY_CNTL3, RDPCS_PHY_DP_TX1_DISABLE, mask_sh),\ - LE_SF(RDPCSTX0_RDPCSTX_PHY_CNTL3, RDPCS_PHY_DP_TX2_DISABLE, mask_sh),\ - LE_SF(RDPCSTX0_RDPCSTX_PHY_CNTL3, RDPCS_PHY_DP_TX3_DISABLE, mask_sh),\ - LE_SF(RDPCSTX0_RDPCSTX_PHY_CNTL3, RDPCS_PHY_DP_TX0_REQ, mask_sh),\ - LE_SF(RDPCSTX0_RDPCSTX_PHY_CNTL3, RDPCS_PHY_DP_TX1_REQ, mask_sh),\ - LE_SF(RDPCSTX0_RDPCSTX_PHY_CNTL3, RDPCS_PHY_DP_TX2_REQ, mask_sh),\ - LE_SF(RDPCSTX0_RDPCSTX_PHY_CNTL3, RDPCS_PHY_DP_TX3_REQ, mask_sh),\ - LE_SF(RDPCSTX0_RDPCSTX_PHY_CNTL3, RDPCS_PHY_DP_TX0_ACK, mask_sh),\ - LE_SF(RDPCSTX0_RDPCSTX_PHY_CNTL3, RDPCS_PHY_DP_TX1_ACK, mask_sh),\ - LE_SF(RDPCSTX0_RDPCSTX_PHY_CNTL3, RDPCS_PHY_DP_TX2_ACK, mask_sh),\ - LE_SF(RDPCSTX0_RDPCSTX_PHY_CNTL3, RDPCS_PHY_DP_TX3_ACK, mask_sh),\ - LE_SF(RDPCSTX0_RDPCSTX_PHY_CNTL3, RDPCS_PHY_DP_TX0_RESET, mask_sh),\ - LE_SF(RDPCSTX0_RDPCSTX_PHY_CNTL3, RDPCS_PHY_DP_TX1_RESET, mask_sh),\ - LE_SF(RDPCSTX0_RDPCSTX_PHY_CNTL3, RDPCS_PHY_DP_TX2_RESET, mask_sh),\ - LE_SF(RDPCSTX0_RDPCSTX_PHY_CNTL3, RDPCS_PHY_DP_TX3_RESET, mask_sh),\ - LE_SF(RDPCSTX0_RDPCSTX_PHY_CNTL0, RDPCS_PHY_RESET, mask_sh),\ - LE_SF(RDPCSTX0_RDPCSTX_PHY_CNTL0, RDPCS_PHY_CR_MUX_SEL, mask_sh),\ - LE_SF(RDPCSTX0_RDPCSTX_PHY_CNTL0, RDPCS_PHY_REF_RANGE, mask_sh),\ - LE_SF(RDPCSTX0_RDPCSTX_PHY_CNTL0, RDPCS_SRAM_BYPASS, mask_sh),\ - LE_SF(RDPCSTX0_RDPCSTX_PHY_CNTL0, RDPCS_SRAM_EXT_LD_DONE, mask_sh),\ - LE_SF(RDPCSTX0_RDPCSTX_PHY_CNTL0, RDPCS_PHY_HDMIMODE_ENABLE, mask_sh),\ - LE_SF(RDPCSTX0_RDPCSTX_PHY_CNTL0, RDPCS_SRAM_INIT_DONE, mask_sh),\ - LE_SF(RDPCSTX0_RDPCSTX_PHY_CNTL2, RDPCS_PHY_DP4_POR, mask_sh),\ - LE_SF(RDPCSTX0_RDPCSTX_INTERRUPT_CONTROL, RDPCS_REG_FIFO_ERROR_MASK, mask_sh),\ - LE_SF(RDPCSTX0_RDPCSTX_INTERRUPT_CONTROL, RDPCS_TX_FIFO_ERROR_MASK, mask_sh),\ - LE_SF(RDPCSTX0_RDPCSTX_INTERRUPT_CONTROL, RDPCS_DPALT_DISABLE_TOGGLE_MASK, mask_sh),\ - LE_SF(RDPCSTX0_RDPCSTX_INTERRUPT_CONTROL, RDPCS_DPALT_4LANE_TOGGLE_MASK, mask_sh),\ - LE_SF(RDPCSTX0_RDPCS_TX_CR_ADDR, RDPCS_TX_CR_ADDR, mask_sh),\ - LE_SF(RDPCSTX0_RDPCS_TX_CR_DATA, RDPCS_TX_CR_DATA, mask_sh),\ - LE_SF(RDPCSTX0_RDPCSTX_PHY_FUSE0, RDPCS_PHY_DP_MPLLB_V2I, mask_sh),\ - LE_SF(RDPCSTX0_RDPCSTX_PHY_FUSE0, RDPCS_PHY_DP_TX0_EQ_MAIN, mask_sh),\ - LE_SF(RDPCSTX0_RDPCSTX_PHY_FUSE0, RDPCS_PHY_DP_TX0_EQ_PRE, mask_sh),\ - LE_SF(RDPCSTX0_RDPCSTX_PHY_FUSE0, RDPCS_PHY_DP_TX0_EQ_POST, mask_sh),\ - LE_SF(RDPCSTX0_RDPCSTX_PHY_FUSE0, RDPCS_PHY_DP_MPLLB_FREQ_VCO, mask_sh),\ - LE_SF(RDPCSTX0_RDPCSTX_PHY_FUSE1, RDPCS_PHY_DP_MPLLB_CP_INT, mask_sh),\ - LE_SF(RDPCSTX0_RDPCSTX_PHY_FUSE1, RDPCS_PHY_DP_MPLLB_CP_PROP, mask_sh),\ - LE_SF(RDPCSTX0_RDPCSTX_PHY_FUSE1, RDPCS_PHY_DP_TX1_EQ_MAIN, mask_sh),\ - LE_SF(RDPCSTX0_RDPCSTX_PHY_FUSE1, RDPCS_PHY_DP_TX1_EQ_PRE, mask_sh),\ - LE_SF(RDPCSTX0_RDPCSTX_PHY_FUSE1, RDPCS_PHY_DP_TX1_EQ_POST, mask_sh),\ - LE_SF(RDPCSTX0_RDPCSTX_PHY_FUSE2, RDPCS_PHY_DP_TX2_EQ_MAIN, mask_sh),\ - LE_SF(RDPCSTX0_RDPCSTX_PHY_FUSE2, RDPCS_PHY_DP_TX2_EQ_PRE, mask_sh),\ - LE_SF(RDPCSTX0_RDPCSTX_PHY_FUSE2, RDPCS_PHY_DP_TX2_EQ_POST, mask_sh),\ - LE_SF(RDPCSTX0_RDPCSTX_PHY_FUSE3, RDPCS_PHY_DP_TX3_EQ_MAIN, mask_sh),\ - LE_SF(RDPCSTX0_RDPCSTX_PHY_FUSE3, RDPCS_PHY_DCO_FINETUNE, mask_sh),\ - LE_SF(RDPCSTX0_RDPCSTX_PHY_FUSE3, RDPCS_PHY_DCO_RANGE, mask_sh),\ - LE_SF(RDPCSTX0_RDPCSTX_PHY_FUSE3, RDPCS_PHY_DP_TX3_EQ_PRE, mask_sh),\ - LE_SF(RDPCSTX0_RDPCSTX_PHY_FUSE3, RDPCS_PHY_DP_TX3_EQ_POST, mask_sh) - -#define DPCS_DCN314_REG_LIST(id) \ - SRI(TMDS_CTL_BITS, DIG, id), \ - SRI(RDPCSTX_PHY_CNTL3, RDPCSTX, id), \ - SRI(RDPCSTX_PHY_CNTL4, RDPCSTX, id), \ - SRI(RDPCSTX_PHY_CNTL5, RDPCSTX, id), \ - SRI(RDPCSTX_PHY_CNTL7, RDPCSTX, id), \ - SRI(RDPCSTX_PHY_CNTL8, RDPCSTX, id), \ - SRI(RDPCSTX_PHY_CNTL9, RDPCSTX, id), \ - SRI(RDPCSTX_PHY_CNTL10, RDPCSTX, id), \ - SRI(RDPCSTX_PHY_CNTL11, RDPCSTX, id), \ - SRI(RDPCSTX_PHY_CNTL12, RDPCSTX, id), \ - SRI(RDPCSTX_PHY_CNTL13, RDPCSTX, id), \ - SRI(RDPCSTX_PHY_CNTL14, RDPCSTX, id), \ - SRI(RDPCSTX_CNTL, RDPCSTX, id), \ - SRI(RDPCSTX_CLOCK_CNTL, RDPCSTX, id), \ - SRI(RDPCSTX_INTERRUPT_CONTROL, RDPCSTX, id), \ - SRI(RDPCSTX_PHY_CNTL0, RDPCSTX, id), \ - SRI(RDPCSTX_PHY_CNTL2, RDPCSTX, id), \ - SRI(RDPCS_TX_CR_ADDR, RDPCSTX, id), \ - SRI(RDPCS_TX_CR_DATA, RDPCSTX, id), \ - SRI(RDPCSTX_PHY_FUSE0, RDPCSTX, id), \ - SRI(RDPCSTX_PHY_FUSE1, RDPCSTX, id), \ - SRI(RDPCSTX_PHY_FUSE2, RDPCSTX, id), \ - SRI(RDPCSTX_PHY_FUSE3, RDPCSTX, id), \ - SRI(RDPCSTX_DEBUG_CONFIG, RDPCSTX, id), \ - SR(RDPCSTX0_RDPCSTX_SCRATCH), \ - SRI(RDPCSTX_PHY_RX_LD_VAL, RDPCSTX, id),\ - SRI(RDPCSTX_DMCU_DPALT_DIS_BLOCK_REG, RDPCSTX, id) - -void dcn31_link_encoder_construct( - struct dcn20_link_encoder *enc20, - const struct encoder_init_data *init_data, - const struct encoder_feature_support *enc_features, - const struct dcn10_link_enc_registers *link_regs, - const struct dcn10_link_enc_aux_registers *aux_regs, - const struct dcn10_link_enc_hpd_registers *hpd_regs, - const struct dcn10_link_enc_shift *link_shift, - const struct dcn10_link_enc_mask *link_mask); - -/* - * Create a minimal link encoder object with no dc_link object associated with it. - */ -void dcn31_link_encoder_construct_minimal( - struct dcn20_link_encoder *enc20, - struct dc_context *ctx, - const struct encoder_feature_support *enc_features, - const struct dcn10_link_enc_registers *link_regs, - enum engine_id eng_id); - -void dcn31_link_encoder_set_dio_phy_mux( - struct link_encoder *enc, - enum encoder_type_select sel, - uint32_t hpo_inst); - -/* - * Enable DP transmitter and its encoder. - */ -void dcn31_link_encoder_enable_dp_output( - struct link_encoder *enc, - const struct dc_link_settings *link_settings, - enum clock_source_id clock_source); - -/* - * Enable DP transmitter and its encoder in MST mode. - */ -void dcn31_link_encoder_enable_dp_mst_output( - struct link_encoder *enc, - const struct dc_link_settings *link_settings, - enum clock_source_id clock_source); - -/* - * Disable transmitter and its encoder. - */ -void dcn31_link_encoder_disable_output( - struct link_encoder *enc, - enum signal_type signal); - -/* - * Check whether USB-C DP Alt mode is disabled - */ -bool dcn31_link_encoder_is_in_alt_mode( - struct link_encoder *enc); - -void dcn31_link_encoder_get_max_link_cap(struct link_encoder *enc, - struct dc_link_settings *link_settings); - -void enc31_hw_init(struct link_encoder *enc); - -#endif /* __DC_LINK_ENCODER__DCN31_H__ */ diff --git a/drivers/gpu/drm/amd/display/dc/dio/Makefile b/drivers/gpu/drm/amd/display/dc/dio/Makefile index 5fa905c2fe55..67840e474d7a 100644 --- a/drivers/gpu/drm/amd/display/dc/dio/Makefile +++ b/drivers/gpu/drm/amd/display/dc/dio/Makefile @@ -24,6 +24,42 @@ # ifdef CONFIG_DRM_AMD_DC_FP +############################################################################### +# DCN10 +############################################################################### +DIO_DCN10 = dcn10_link_encoder.o dcn10_stream_encoder.o + +AMD_DAL_DIO_DCN10 = $(addprefix $(AMDDALPATH)/dc/dio/dcn10/,$(DIO_DCN10)) + +AMD_DISPLAY_FILES += $(AMD_DAL_DIO_DCN10) + +############################################################################### +# DCN20 +############################################################################### +DIO_DCN20 = dcn20_link_encoder.o dcn20_stream_encoder.o + +AMD_DAL_DIO_DCN20 = $(addprefix $(AMDDALPATH)/dc/dio/dcn20/,$(DIO_DCN20)) + +AMD_DISPLAY_FILES += $(AMD_DAL_DIO_DCN20) + +############################################################################### +# DCN30 +############################################################################### +DIO_DCN30 = dcn30_dio_link_encoder.o dcn30_dio_stream_encoder.o + +AMD_DAL_DIO_DCN30 = $(addprefix $(AMDDALPATH)/dc/dio/dcn30/,$(DIO_DCN30)) + +AMD_DISPLAY_FILES += $(AMD_DAL_DIO_DCN30) + +############################################################################### +# DCN31 +############################################################################### +DIO_DCN31 = dcn31_dio_link_encoder.o + +AMD_DAL_DIO_DCN31 = $(addprefix $(AMDDALPATH)/dc/dio/dcn31/,$(DIO_DCN31)) + +AMD_DISPLAY_FILES += $(AMD_DAL_DIO_DCN31) + ############################################################################### # DCN32 ############################################################################### diff --git a/drivers/gpu/drm/amd/display/dc/dio/dcn10/dcn10_link_encoder.c b/drivers/gpu/drm/amd/display/dc/dio/dcn10/dcn10_link_encoder.c new file mode 100644 index 000000000000..e0558a78b11c --- /dev/null +++ b/drivers/gpu/drm/amd/display/dc/dio/dcn10/dcn10_link_encoder.c @@ -0,0 +1,1474 @@ +/* + * Copyright 2012-15 Advanced Micro Devices, Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + * + * Authors: AMD + * + */ + +#include "reg_helper.h" + +#include "core_types.h" +#include "link_encoder.h" +#include "dcn10_link_encoder.h" +#include "stream_encoder.h" +#include "dc_bios_types.h" + +#include "gpio_service_interface.h" + +#define CTX \ + enc10->base.ctx +#define DC_LOGGER \ + enc10->base.ctx->logger + +#define REG(reg)\ + (enc10->link_regs->reg) + +#undef FN +#define FN(reg_name, field_name) \ + enc10->link_shift->field_name, enc10->link_mask->field_name + + +/* + * @brief + * Trigger Source Select + * ASIC-dependent, actual values for register programming + */ +#define DCN10_DIG_FE_SOURCE_SELECT_INVALID 0x0 +#define DCN10_DIG_FE_SOURCE_SELECT_DIGA 0x1 +#define DCN10_DIG_FE_SOURCE_SELECT_DIGB 0x2 +#define DCN10_DIG_FE_SOURCE_SELECT_DIGC 0x4 +#define DCN10_DIG_FE_SOURCE_SELECT_DIGD 0x08 +#define DCN10_DIG_FE_SOURCE_SELECT_DIGE 0x10 +#define DCN10_DIG_FE_SOURCE_SELECT_DIGF 0x20 +#define DCN10_DIG_FE_SOURCE_SELECT_DIGG 0x40 + +enum { + DP_MST_UPDATE_MAX_RETRY = 50 +}; + +static const struct link_encoder_funcs dcn10_lnk_enc_funcs = { + .validate_output_with_stream = + dcn10_link_encoder_validate_output_with_stream, + .hw_init = dcn10_link_encoder_hw_init, + .setup = dcn10_link_encoder_setup, + .enable_tmds_output = dcn10_link_encoder_enable_tmds_output, + .enable_dp_output = dcn10_link_encoder_enable_dp_output, + .enable_dp_mst_output = dcn10_link_encoder_enable_dp_mst_output, + .disable_output = dcn10_link_encoder_disable_output, + .dp_set_lane_settings = dcn10_link_encoder_dp_set_lane_settings, + .dp_set_phy_pattern = dcn10_link_encoder_dp_set_phy_pattern, + .update_mst_stream_allocation_table = + dcn10_link_encoder_update_mst_stream_allocation_table, + .psr_program_dp_dphy_fast_training = + dcn10_psr_program_dp_dphy_fast_training, + .psr_program_secondary_packet = dcn10_psr_program_secondary_packet, + .connect_dig_be_to_fe = dcn10_link_encoder_connect_dig_be_to_fe, + .enable_hpd = dcn10_link_encoder_enable_hpd, + .disable_hpd = dcn10_link_encoder_disable_hpd, + .is_dig_enabled = dcn10_is_dig_enabled, + .get_dig_frontend = dcn10_get_dig_frontend, + .get_dig_mode = dcn10_get_dig_mode, + .destroy = dcn10_link_encoder_destroy, + .get_max_link_cap = dcn10_link_encoder_get_max_link_cap, +}; + +static enum bp_result link_transmitter_control( + struct dcn10_link_encoder *enc10, + struct bp_transmitter_control *cntl) +{ + enum bp_result result; + struct dc_bios *bp = enc10->base.ctx->dc_bios; + + result = bp->funcs->transmitter_control(bp, cntl); + + return result; +} + +static void enable_phy_bypass_mode( + struct dcn10_link_encoder *enc10, + bool enable) +{ + /* This register resides in DP back end block; + * transmitter is used for the offset + */ + REG_UPDATE(DP_DPHY_CNTL, DPHY_BYPASS, enable); + +} + +static void disable_prbs_symbols( + struct dcn10_link_encoder *enc10, + bool disable) +{ + /* This register resides in DP back end block; + * transmitter is used for the offset + */ + REG_UPDATE_4(DP_DPHY_CNTL, + DPHY_ATEST_SEL_LANE0, disable, + DPHY_ATEST_SEL_LANE1, disable, + DPHY_ATEST_SEL_LANE2, disable, + DPHY_ATEST_SEL_LANE3, disable); +} + +static void disable_prbs_mode( + struct dcn10_link_encoder *enc10) +{ + REG_UPDATE(DP_DPHY_PRBS_CNTL, DPHY_PRBS_EN, 0); +} + +static void program_pattern_symbols( + struct dcn10_link_encoder *enc10, + uint16_t pattern_symbols[8]) +{ + /* This register resides in DP back end block; + * transmitter is used for the offset + */ + REG_SET_3(DP_DPHY_SYM0, 0, + DPHY_SYM1, pattern_symbols[0], + DPHY_SYM2, pattern_symbols[1], + DPHY_SYM3, pattern_symbols[2]); + + /* This register resides in DP back end block; + * transmitter is used for the offset + */ + REG_SET_3(DP_DPHY_SYM1, 0, + DPHY_SYM4, pattern_symbols[3], + DPHY_SYM5, pattern_symbols[4], + DPHY_SYM6, pattern_symbols[5]); + + /* This register resides in DP back end block; + * transmitter is used for the offset + */ + REG_SET_2(DP_DPHY_SYM2, 0, + DPHY_SYM7, pattern_symbols[6], + DPHY_SYM8, pattern_symbols[7]); +} + +static void set_dp_phy_pattern_d102( + struct dcn10_link_encoder *enc10) +{ + /* Disable PHY Bypass mode to setup the test pattern */ + enable_phy_bypass_mode(enc10, false); + + /* For 10-bit PRBS or debug symbols + * please use the following sequence: + * + * Enable debug symbols on the lanes + */ + disable_prbs_symbols(enc10, true); + + /* Disable PRBS mode */ + disable_prbs_mode(enc10); + + /* Program debug symbols to be output */ + { + uint16_t pattern_symbols[8] = { + 0x2AA, 0x2AA, 0x2AA, 0x2AA, + 0x2AA, 0x2AA, 0x2AA, 0x2AA + }; + + program_pattern_symbols(enc10, pattern_symbols); + } + + /* Enable phy bypass mode to enable the test pattern */ + + enable_phy_bypass_mode(enc10, true); +} + +static void set_link_training_complete( + struct dcn10_link_encoder *enc10, + bool complete) +{ + /* This register resides in DP back end block; + * transmitter is used for the offset + */ + REG_UPDATE(DP_LINK_CNTL, DP_LINK_TRAINING_COMPLETE, complete); + +} + +void dcn10_link_encoder_set_dp_phy_pattern_training_pattern( + struct link_encoder *enc, + uint32_t index) +{ + struct dcn10_link_encoder *enc10 = TO_DCN10_LINK_ENC(enc); + /* Write Training Pattern */ + + REG_WRITE(DP_DPHY_TRAINING_PATTERN_SEL, index); + + /* Set HW Register Training Complete to false */ + + set_link_training_complete(enc10, false); + + /* Disable PHY Bypass mode to output Training Pattern */ + + enable_phy_bypass_mode(enc10, false); + + /* Disable PRBS mode */ + disable_prbs_mode(enc10); +} + +static void setup_panel_mode( + struct dcn10_link_encoder *enc10, + enum dp_panel_mode panel_mode) +{ + uint32_t value; + + if (!REG(DP_DPHY_INTERNAL_CTRL)) + return; + + value = REG_READ(DP_DPHY_INTERNAL_CTRL); + + switch (panel_mode) { + case DP_PANEL_MODE_EDP: + value = 0x1; + break; + case DP_PANEL_MODE_SPECIAL: + value = 0x11; + break; + default: + value = 0x0; + break; + } + + REG_WRITE(DP_DPHY_INTERNAL_CTRL, value); +} + +static void set_dp_phy_pattern_symbol_error( + struct dcn10_link_encoder *enc10) +{ + /* Disable PHY Bypass mode to setup the test pattern */ + enable_phy_bypass_mode(enc10, false); + + /* program correct panel mode*/ + setup_panel_mode(enc10, DP_PANEL_MODE_DEFAULT); + + /* A PRBS23 pattern is used for most DP electrical measurements. */ + + /* Enable PRBS symbols on the lanes */ + disable_prbs_symbols(enc10, false); + + /* For PRBS23 Set bit DPHY_PRBS_SEL=1 and Set bit DPHY_PRBS_EN=1 */ + REG_UPDATE_2(DP_DPHY_PRBS_CNTL, + DPHY_PRBS_SEL, 1, + DPHY_PRBS_EN, 1); + + /* Enable phy bypass mode to enable the test pattern */ + enable_phy_bypass_mode(enc10, true); +} + +static void set_dp_phy_pattern_prbs7( + struct dcn10_link_encoder *enc10) +{ + /* Disable PHY Bypass mode to setup the test pattern */ + enable_phy_bypass_mode(enc10, false); + + /* A PRBS7 pattern is used for most DP electrical measurements. */ + + /* Enable PRBS symbols on the lanes */ + disable_prbs_symbols(enc10, false); + + /* For PRBS7 Set bit DPHY_PRBS_SEL=0 and Set bit DPHY_PRBS_EN=1 */ + REG_UPDATE_2(DP_DPHY_PRBS_CNTL, + DPHY_PRBS_SEL, 0, + DPHY_PRBS_EN, 1); + + /* Enable phy bypass mode to enable the test pattern */ + enable_phy_bypass_mode(enc10, true); +} + +static void set_dp_phy_pattern_80bit_custom( + struct dcn10_link_encoder *enc10, + const uint8_t *pattern) +{ + /* Disable PHY Bypass mode to setup the test pattern */ + enable_phy_bypass_mode(enc10, false); + + /* Enable debug symbols on the lanes */ + + disable_prbs_symbols(enc10, true); + + /* Enable PHY bypass mode to enable the test pattern */ + /* TODO is it really needed ? */ + + enable_phy_bypass_mode(enc10, true); + + /* Program 80 bit custom pattern */ + { + uint16_t pattern_symbols[8]; + + pattern_symbols[0] = + ((pattern[1] & 0x03) << 8) | pattern[0]; + pattern_symbols[1] = + ((pattern[2] & 0x0f) << 6) | ((pattern[1] >> 2) & 0x3f); + pattern_symbols[2] = + ((pattern[3] & 0x3f) << 4) | ((pattern[2] >> 4) & 0x0f); + pattern_symbols[3] = + (pattern[4] << 2) | ((pattern[3] >> 6) & 0x03); + pattern_symbols[4] = + ((pattern[6] & 0x03) << 8) | pattern[5]; + pattern_symbols[5] = + ((pattern[7] & 0x0f) << 6) | ((pattern[6] >> 2) & 0x3f); + pattern_symbols[6] = + ((pattern[8] & 0x3f) << 4) | ((pattern[7] >> 4) & 0x0f); + pattern_symbols[7] = + (pattern[9] << 2) | ((pattern[8] >> 6) & 0x03); + + program_pattern_symbols(enc10, pattern_symbols); + } + + /* Enable phy bypass mode to enable the test pattern */ + + enable_phy_bypass_mode(enc10, true); +} + +static void set_dp_phy_pattern_hbr2_compliance_cp2520_2( + struct dcn10_link_encoder *enc10, + unsigned int cp2520_pattern) +{ + + /* previously there is a register DP_HBR2_EYE_PATTERN + * that is enabled to get the pattern. + * But it does not work with the latest spec change, + * so we are programming the following registers manually. + * + * The following settings have been confirmed + * by Nick Chorney and Sandra Liu + */ + + /* Disable PHY Bypass mode to setup the test pattern */ + + enable_phy_bypass_mode(enc10, false); + + /* Setup DIG encoder in DP SST mode */ + enc10->base.funcs->setup(&enc10->base, SIGNAL_TYPE_DISPLAY_PORT); + + /* ensure normal panel mode. */ + setup_panel_mode(enc10, DP_PANEL_MODE_DEFAULT); + + /* no vbid after BS (SR) + * DP_LINK_FRAMING_CNTL changed history Sandra Liu + * 11000260 / 11000104 / 110000FC + */ + REG_UPDATE_3(DP_LINK_FRAMING_CNTL, + DP_IDLE_BS_INTERVAL, 0xFC, + DP_VBID_DISABLE, 1, + DP_VID_ENHANCED_FRAME_MODE, 1); + + /* swap every BS with SR */ + REG_UPDATE(DP_DPHY_SCRAM_CNTL, DPHY_SCRAMBLER_BS_COUNT, 0); + + /* select cp2520 patterns */ + if (REG(DP_DPHY_HBR2_PATTERN_CONTROL)) + REG_UPDATE(DP_DPHY_HBR2_PATTERN_CONTROL, + DP_DPHY_HBR2_PATTERN_CONTROL, cp2520_pattern); + else + /* pre-DCE11 can only generate CP2520 pattern 2 */ + ASSERT(cp2520_pattern == 2); + + /* set link training complete */ + set_link_training_complete(enc10, true); + + /* disable video stream */ + REG_UPDATE(DP_VID_STREAM_CNTL, DP_VID_STREAM_ENABLE, 0); + + /* Disable PHY Bypass mode to setup the test pattern */ + enable_phy_bypass_mode(enc10, false); +} + +static void set_dp_phy_pattern_passthrough_mode( + struct dcn10_link_encoder *enc10, + enum dp_panel_mode panel_mode) +{ + /* program correct panel mode */ + setup_panel_mode(enc10, panel_mode); + + /* restore LINK_FRAMING_CNTL and DPHY_SCRAMBLER_BS_COUNT + * in case we were doing HBR2 compliance pattern before + */ + REG_UPDATE_3(DP_LINK_FRAMING_CNTL, + DP_IDLE_BS_INTERVAL, 0x2000, + DP_VBID_DISABLE, 0, + DP_VID_ENHANCED_FRAME_MODE, 1); + + REG_UPDATE(DP_DPHY_SCRAM_CNTL, DPHY_SCRAMBLER_BS_COUNT, 0x1FF); + + /* set link training complete */ + set_link_training_complete(enc10, true); + + /* Disable PHY Bypass mode to setup the test pattern */ + enable_phy_bypass_mode(enc10, false); + + /* Disable PRBS mode */ + disable_prbs_mode(enc10); +} + +/* return value is bit-vector */ +static uint8_t get_frontend_source( + enum engine_id engine) +{ + switch (engine) { + case ENGINE_ID_DIGA: + return DCN10_DIG_FE_SOURCE_SELECT_DIGA; + case ENGINE_ID_DIGB: + return DCN10_DIG_FE_SOURCE_SELECT_DIGB; + case ENGINE_ID_DIGC: + return DCN10_DIG_FE_SOURCE_SELECT_DIGC; + case ENGINE_ID_DIGD: + return DCN10_DIG_FE_SOURCE_SELECT_DIGD; + case ENGINE_ID_DIGE: + return DCN10_DIG_FE_SOURCE_SELECT_DIGE; + case ENGINE_ID_DIGF: + return DCN10_DIG_FE_SOURCE_SELECT_DIGF; + case ENGINE_ID_DIGG: + return DCN10_DIG_FE_SOURCE_SELECT_DIGG; + default: + ASSERT_CRITICAL(false); + return DCN10_DIG_FE_SOURCE_SELECT_INVALID; + } +} + +unsigned int dcn10_get_dig_frontend(struct link_encoder *enc) +{ + struct dcn10_link_encoder *enc10 = TO_DCN10_LINK_ENC(enc); + int32_t value; + enum engine_id result; + + REG_GET(DIG_BE_CNTL, DIG_FE_SOURCE_SELECT, &value); + + switch (value) { + case DCN10_DIG_FE_SOURCE_SELECT_DIGA: + result = ENGINE_ID_DIGA; + break; + case DCN10_DIG_FE_SOURCE_SELECT_DIGB: + result = ENGINE_ID_DIGB; + break; + case DCN10_DIG_FE_SOURCE_SELECT_DIGC: + result = ENGINE_ID_DIGC; + break; + case DCN10_DIG_FE_SOURCE_SELECT_DIGD: + result = ENGINE_ID_DIGD; + break; + case DCN10_DIG_FE_SOURCE_SELECT_DIGE: + result = ENGINE_ID_DIGE; + break; + case DCN10_DIG_FE_SOURCE_SELECT_DIGF: + result = ENGINE_ID_DIGF; + break; + case DCN10_DIG_FE_SOURCE_SELECT_DIGG: + result = ENGINE_ID_DIGG; + break; + default: + // invalid source select DIG + result = ENGINE_ID_UNKNOWN; + } + + return result; + +} + +void enc1_configure_encoder( + struct dcn10_link_encoder *enc10, + const struct dc_link_settings *link_settings) +{ + /* set number of lanes */ + REG_SET(DP_CONFIG, 0, + DP_UDI_LANES, link_settings->lane_count - LANE_COUNT_ONE); + + /* setup scrambler */ + REG_UPDATE(DP_DPHY_SCRAM_CNTL, DPHY_SCRAMBLER_ADVANCE, 1); +} + +void dcn10_psr_program_dp_dphy_fast_training(struct link_encoder *enc, + bool exit_link_training_required) +{ + struct dcn10_link_encoder *enc10 = TO_DCN10_LINK_ENC(enc); + + if (exit_link_training_required) + REG_UPDATE(DP_DPHY_FAST_TRAINING, + DPHY_RX_FAST_TRAINING_CAPABLE, 1); + else { + REG_UPDATE(DP_DPHY_FAST_TRAINING, + DPHY_RX_FAST_TRAINING_CAPABLE, 0); + /*In DCE 11, we are able to pre-program a Force SR register + * to be able to trigger SR symbol after 5 idle patterns + * transmitted. Upon PSR Exit, DMCU can trigger + * DPHY_LOAD_BS_COUNT_START = 1. Upon writing 1 to + * DPHY_LOAD_BS_COUNT_START and the internal counter + * reaches DPHY_LOAD_BS_COUNT, the next BS symbol will be + * replaced by SR symbol once. + */ + + REG_UPDATE(DP_DPHY_BS_SR_SWAP_CNTL, DPHY_LOAD_BS_COUNT, 0x5); + } +} + +void dcn10_psr_program_secondary_packet(struct link_encoder *enc, + unsigned int sdp_transmit_line_num_deadline) +{ + struct dcn10_link_encoder *enc10 = TO_DCN10_LINK_ENC(enc); + + REG_UPDATE_2(DP_SEC_CNTL1, + DP_SEC_GSP0_LINE_NUM, sdp_transmit_line_num_deadline, + DP_SEC_GSP0_PRIORITY, 1); +} + +bool dcn10_is_dig_enabled(struct link_encoder *enc) +{ + struct dcn10_link_encoder *enc10 = TO_DCN10_LINK_ENC(enc); + uint32_t value; + + REG_GET(DIG_BE_EN_CNTL, DIG_ENABLE, &value); + return value; +} + +static void link_encoder_disable(struct dcn10_link_encoder *enc10) +{ + /* reset training pattern */ + REG_SET(DP_DPHY_TRAINING_PATTERN_SEL, 0, + DPHY_TRAINING_PATTERN_SEL, 0); + + /* reset training complete */ + REG_UPDATE(DP_LINK_CNTL, DP_LINK_TRAINING_COMPLETE, 0); + + /* reset panel mode */ + setup_panel_mode(enc10, DP_PANEL_MODE_DEFAULT); +} + +static void hpd_initialize( + struct dcn10_link_encoder *enc10) +{ + /* Associate HPD with DIG_BE */ + enum hpd_source_id hpd_source = enc10->base.hpd_source; + + REG_UPDATE(DIG_BE_CNTL, DIG_HPD_SELECT, hpd_source); +} + +bool dcn10_link_encoder_validate_dvi_output( + const struct dcn10_link_encoder *enc10, + enum signal_type connector_signal, + enum signal_type signal, + const struct dc_crtc_timing *crtc_timing) +{ + uint32_t max_pixel_clock = TMDS_MAX_PIXEL_CLOCK; + + if (signal == SIGNAL_TYPE_DVI_DUAL_LINK) + max_pixel_clock *= 2; + + /* This handles the case of HDMI downgrade to DVI we don't want to + * we don't want to cap the pixel clock if the DDI is not DVI. + */ + if (connector_signal != SIGNAL_TYPE_DVI_DUAL_LINK && + connector_signal != SIGNAL_TYPE_DVI_SINGLE_LINK) + max_pixel_clock = enc10->base.features.max_hdmi_pixel_clock; + + /* DVI only support RGB pixel encoding */ + if (crtc_timing->pixel_encoding != PIXEL_ENCODING_RGB) + return false; + + /*connect DVI via adpater's HDMI connector*/ + if ((connector_signal == SIGNAL_TYPE_DVI_SINGLE_LINK || + connector_signal == SIGNAL_TYPE_HDMI_TYPE_A) && + signal != SIGNAL_TYPE_HDMI_TYPE_A && + crtc_timing->pix_clk_100hz > (TMDS_MAX_PIXEL_CLOCK * 10)) + return false; + if (crtc_timing->pix_clk_100hz < (TMDS_MIN_PIXEL_CLOCK * 10)) + return false; + + if (crtc_timing->pix_clk_100hz > (max_pixel_clock * 10)) + return false; + + /* DVI supports 6/8bpp single-link and 10/16bpp dual-link */ + switch (crtc_timing->display_color_depth) { + case COLOR_DEPTH_666: + case COLOR_DEPTH_888: + break; + case COLOR_DEPTH_101010: + case COLOR_DEPTH_161616: + if (signal != SIGNAL_TYPE_DVI_DUAL_LINK) + return false; + break; + default: + return false; + } + + return true; +} + +static bool dcn10_link_encoder_validate_hdmi_output( + const struct dcn10_link_encoder *enc10, + const struct dc_crtc_timing *crtc_timing, + const struct dc_edid_caps *edid_caps, + int adjusted_pix_clk_100hz) +{ + enum dc_color_depth max_deep_color = + enc10->base.features.max_hdmi_deep_color; + + // check pixel clock against edid specified max TMDS clk + if (edid_caps->max_tmds_clk_mhz != 0 && + adjusted_pix_clk_100hz > edid_caps->max_tmds_clk_mhz * 10000) + return false; + + if (max_deep_color < crtc_timing->display_color_depth) + return false; + + if (crtc_timing->display_color_depth < COLOR_DEPTH_888) + return false; + if (adjusted_pix_clk_100hz < (TMDS_MIN_PIXEL_CLOCK * 10)) + return false; + + if ((adjusted_pix_clk_100hz == 0) || + (adjusted_pix_clk_100hz > (enc10->base.features.max_hdmi_pixel_clock * 10))) + return false; + + /* DCE11 HW does not support 420 */ + if (!enc10->base.features.hdmi_ycbcr420_supported && + crtc_timing->pixel_encoding == PIXEL_ENCODING_YCBCR420) + return false; + + if ((!enc10->base.features.flags.bits.HDMI_6GB_EN || + enc10->base.ctx->dc->debug.hdmi20_disable) && + adjusted_pix_clk_100hz >= 3000000) + return false; + if (enc10->base.ctx->dc->debug.hdmi20_disable && + crtc_timing->pixel_encoding == PIXEL_ENCODING_YCBCR420) + return false; + return true; +} + +bool dcn10_link_encoder_validate_dp_output( + const struct dcn10_link_encoder *enc10, + const struct dc_crtc_timing *crtc_timing) +{ + if (crtc_timing->pixel_encoding == PIXEL_ENCODING_YCBCR420) { + if (!enc10->base.features.dp_ycbcr420_supported) + return false; + } + + return true; +} + +void dcn10_link_encoder_construct( + struct dcn10_link_encoder *enc10, + const struct encoder_init_data *init_data, + const struct encoder_feature_support *enc_features, + const struct dcn10_link_enc_registers *link_regs, + const struct dcn10_link_enc_aux_registers *aux_regs, + const struct dcn10_link_enc_hpd_registers *hpd_regs, + const struct dcn10_link_enc_shift *link_shift, + const struct dcn10_link_enc_mask *link_mask) +{ + struct bp_encoder_cap_info bp_cap_info = {0}; + const struct dc_vbios_funcs *bp_funcs = init_data->ctx->dc_bios->funcs; + enum bp_result result = BP_RESULT_OK; + + enc10->base.funcs = &dcn10_lnk_enc_funcs; + enc10->base.ctx = init_data->ctx; + enc10->base.id = init_data->encoder; + + enc10->base.hpd_source = init_data->hpd_source; + enc10->base.connector = init_data->connector; + + enc10->base.preferred_engine = ENGINE_ID_UNKNOWN; + + enc10->base.features = *enc_features; + + enc10->base.transmitter = init_data->transmitter; + + /* set the flag to indicate whether driver poll the I2C data pin + * while doing the DP sink detect + */ + +/* if (dal_adapter_service_is_feature_supported(as, + FEATURE_DP_SINK_DETECT_POLL_DATA_PIN)) + enc10->base.features.flags.bits. + DP_SINK_DETECT_POLL_DATA_PIN = true;*/ + + enc10->base.output_signals = + SIGNAL_TYPE_DVI_SINGLE_LINK | + SIGNAL_TYPE_DVI_DUAL_LINK | + SIGNAL_TYPE_LVDS | + SIGNAL_TYPE_DISPLAY_PORT | + SIGNAL_TYPE_DISPLAY_PORT_MST | + SIGNAL_TYPE_EDP | + SIGNAL_TYPE_HDMI_TYPE_A; + + /* For DCE 8.0 and 8.1, by design, UNIPHY is hardwired to DIG_BE. + * SW always assign DIG_FE 1:1 mapped to DIG_FE for non-MST UNIPHY. + * SW assign DIG_FE to non-MST UNIPHY first and MST last. So prefer + * DIG is per UNIPHY and used by SST DP, eDP, HDMI, DVI and LVDS. + * Prefer DIG assignment is decided by board design. + * For DCE 8.0, there are only max 6 UNIPHYs, we assume board design + * and VBIOS will filter out 7 UNIPHY for DCE 8.0. + * By this, adding DIGG should not hurt DCE 8.0. + * This will let DCE 8.1 share DCE 8.0 as much as possible + */ + + enc10->link_regs = link_regs; + enc10->aux_regs = aux_regs; + enc10->hpd_regs = hpd_regs; + enc10->link_shift = link_shift; + enc10->link_mask = link_mask; + + switch (enc10->base.transmitter) { + case TRANSMITTER_UNIPHY_A: + enc10->base.preferred_engine = ENGINE_ID_DIGA; + break; + case TRANSMITTER_UNIPHY_B: + enc10->base.preferred_engine = ENGINE_ID_DIGB; + break; + case TRANSMITTER_UNIPHY_C: + enc10->base.preferred_engine = ENGINE_ID_DIGC; + break; + case TRANSMITTER_UNIPHY_D: + enc10->base.preferred_engine = ENGINE_ID_DIGD; + break; + case TRANSMITTER_UNIPHY_E: + enc10->base.preferred_engine = ENGINE_ID_DIGE; + break; + case TRANSMITTER_UNIPHY_F: + enc10->base.preferred_engine = ENGINE_ID_DIGF; + break; + case TRANSMITTER_UNIPHY_G: + enc10->base.preferred_engine = ENGINE_ID_DIGG; + break; + default: + ASSERT_CRITICAL(false); + enc10->base.preferred_engine = ENGINE_ID_UNKNOWN; + } + + /* default to one to mirror Windows behavior */ + enc10->base.features.flags.bits.HDMI_6GB_EN = 1; + + result = bp_funcs->get_encoder_cap_info(enc10->base.ctx->dc_bios, + enc10->base.id, &bp_cap_info); + + /* Override features with DCE-specific values */ + if (result == BP_RESULT_OK) { + enc10->base.features.flags.bits.IS_HBR2_CAPABLE = + bp_cap_info.DP_HBR2_EN; + enc10->base.features.flags.bits.IS_HBR3_CAPABLE = + bp_cap_info.DP_HBR3_EN; + enc10->base.features.flags.bits.HDMI_6GB_EN = bp_cap_info.HDMI_6GB_EN; + enc10->base.features.flags.bits.DP_IS_USB_C = + bp_cap_info.DP_IS_USB_C; + } else { + DC_LOG_WARNING("%s: Failed to get encoder_cap_info from VBIOS with error code %d!\n", + __func__, + result); + } + if (enc10->base.ctx->dc->debug.hdmi20_disable) { + enc10->base.features.flags.bits.HDMI_6GB_EN = 0; + } +} + +bool dcn10_link_encoder_validate_output_with_stream( + struct link_encoder *enc, + const struct dc_stream_state *stream) +{ + struct dcn10_link_encoder *enc10 = TO_DCN10_LINK_ENC(enc); + bool is_valid; + + //if SCDC (340-600MHz) is disabled, set to HDMI 1.4 timing limit + if (stream->sink->edid_caps.panel_patch.skip_scdc_overwrite && + enc10->base.features.max_hdmi_pixel_clock > 300000) + enc10->base.features.max_hdmi_pixel_clock = 300000; + + switch (stream->signal) { + case SIGNAL_TYPE_DVI_SINGLE_LINK: + case SIGNAL_TYPE_DVI_DUAL_LINK: + is_valid = dcn10_link_encoder_validate_dvi_output( + enc10, + stream->link->connector_signal, + stream->signal, + &stream->timing); + break; + case SIGNAL_TYPE_HDMI_TYPE_A: + is_valid = dcn10_link_encoder_validate_hdmi_output( + enc10, + &stream->timing, + &stream->sink->edid_caps, + stream->phy_pix_clk * 10); + break; + case SIGNAL_TYPE_DISPLAY_PORT: + case SIGNAL_TYPE_DISPLAY_PORT_MST: + is_valid = dcn10_link_encoder_validate_dp_output( + enc10, &stream->timing); + break; + case SIGNAL_TYPE_EDP: + is_valid = (stream->timing.pixel_encoding == PIXEL_ENCODING_RGB) ? true : false; + break; + case SIGNAL_TYPE_VIRTUAL: + is_valid = true; + break; + default: + is_valid = false; + break; + } + + return is_valid; +} + +void dcn10_link_encoder_hw_init( + struct link_encoder *enc) +{ + struct dcn10_link_encoder *enc10 = TO_DCN10_LINK_ENC(enc); + struct bp_transmitter_control cntl = { 0 }; + enum bp_result result; + + cntl.action = TRANSMITTER_CONTROL_INIT; + cntl.engine_id = ENGINE_ID_UNKNOWN; + cntl.transmitter = enc10->base.transmitter; + cntl.connector_obj_id = enc10->base.connector; + cntl.lanes_number = LANE_COUNT_FOUR; + cntl.coherent = false; + cntl.hpd_sel = enc10->base.hpd_source; + + if (enc10->base.connector.id == CONNECTOR_ID_EDP) + cntl.signal = SIGNAL_TYPE_EDP; + + result = link_transmitter_control(enc10, &cntl); + + if (result != BP_RESULT_OK) { + DC_LOG_ERROR("%s: Failed to execute VBIOS command table!\n", + __func__); + BREAK_TO_DEBUGGER(); + return; + } + + if (enc10->base.connector.id == CONNECTOR_ID_LVDS) { + cntl.action = TRANSMITTER_CONTROL_BACKLIGHT_BRIGHTNESS; + + result = link_transmitter_control(enc10, &cntl); + + ASSERT(result == BP_RESULT_OK); + + } + dcn10_aux_initialize(enc10); + + /* reinitialize HPD. + * hpd_initialize() will pass DIG_FE id to HW context. + * All other routine within HW context will use fe_engine_offset + * as DIG_FE id even caller pass DIG_FE id. + * So this routine must be called first. + */ + hpd_initialize(enc10); +} + +void dcn10_link_encoder_destroy(struct link_encoder **enc) +{ + kfree(TO_DCN10_LINK_ENC(*enc)); + *enc = NULL; +} + +void dcn10_link_encoder_setup( + struct link_encoder *enc, + enum signal_type signal) +{ + struct dcn10_link_encoder *enc10 = TO_DCN10_LINK_ENC(enc); + + switch (signal) { + case SIGNAL_TYPE_EDP: + case SIGNAL_TYPE_DISPLAY_PORT: + /* DP SST */ + REG_UPDATE(DIG_BE_CNTL, DIG_MODE, 0); + break; + case SIGNAL_TYPE_LVDS: + /* LVDS */ + REG_UPDATE(DIG_BE_CNTL, DIG_MODE, 1); + break; + case SIGNAL_TYPE_DVI_SINGLE_LINK: + case SIGNAL_TYPE_DVI_DUAL_LINK: + /* TMDS-DVI */ + REG_UPDATE(DIG_BE_CNTL, DIG_MODE, 2); + break; + case SIGNAL_TYPE_HDMI_TYPE_A: + /* TMDS-HDMI */ + REG_UPDATE(DIG_BE_CNTL, DIG_MODE, 3); + break; + case SIGNAL_TYPE_DISPLAY_PORT_MST: + /* DP MST */ + REG_UPDATE(DIG_BE_CNTL, DIG_MODE, 5); + break; + default: + ASSERT_CRITICAL(false); + /* invalid mode ! */ + break; + } + +} + +/* TODO: still need depth or just pass in adjusted pixel clock? */ +void dcn10_link_encoder_enable_tmds_output( + struct link_encoder *enc, + enum clock_source_id clock_source, + enum dc_color_depth color_depth, + enum signal_type signal, + uint32_t pixel_clock) +{ + struct dcn10_link_encoder *enc10 = TO_DCN10_LINK_ENC(enc); + struct bp_transmitter_control cntl = { 0 }; + enum bp_result result; + + /* Enable the PHY */ + + cntl.action = TRANSMITTER_CONTROL_ENABLE; + cntl.engine_id = enc->preferred_engine; + cntl.transmitter = enc10->base.transmitter; + cntl.pll_id = clock_source; + cntl.signal = signal; + if (cntl.signal == SIGNAL_TYPE_DVI_DUAL_LINK) + cntl.lanes_number = 8; + else + cntl.lanes_number = 4; + + cntl.hpd_sel = enc10->base.hpd_source; + + cntl.pixel_clock = pixel_clock; + cntl.color_depth = color_depth; + + result = link_transmitter_control(enc10, &cntl); + + if (result != BP_RESULT_OK) { + DC_LOG_ERROR("%s: Failed to execute VBIOS command table!\n", + __func__); + BREAK_TO_DEBUGGER(); + } +} + +void dcn10_link_encoder_enable_tmds_output_with_clk_pattern_wa( + struct link_encoder *enc, + enum clock_source_id clock_source, + enum dc_color_depth color_depth, + enum signal_type signal, + uint32_t pixel_clock) +{ + struct dcn10_link_encoder *enc10 = TO_DCN10_LINK_ENC(enc); + + dcn10_link_encoder_enable_tmds_output( + enc, clock_source, color_depth, signal, pixel_clock); + + REG_UPDATE(DIG_CLOCK_PATTERN, DIG_CLOCK_PATTERN, 0x1F); +} + +/* enables DP PHY output */ +void dcn10_link_encoder_enable_dp_output( + struct link_encoder *enc, + const struct dc_link_settings *link_settings, + enum clock_source_id clock_source) +{ + struct dcn10_link_encoder *enc10 = TO_DCN10_LINK_ENC(enc); + struct bp_transmitter_control cntl = { 0 }; + enum bp_result result; + + /* Enable the PHY */ + + /* number_of_lanes is used for pixel clock adjust, + * but it's not passed to asic_control. + * We need to set number of lanes manually. + */ + enc1_configure_encoder(enc10, link_settings); + + cntl.action = TRANSMITTER_CONTROL_ENABLE; + cntl.engine_id = enc->preferred_engine; + cntl.transmitter = enc10->base.transmitter; + cntl.pll_id = clock_source; + cntl.signal = SIGNAL_TYPE_DISPLAY_PORT; + cntl.lanes_number = link_settings->lane_count; + cntl.hpd_sel = enc10->base.hpd_source; + cntl.pixel_clock = link_settings->link_rate + * LINK_RATE_REF_FREQ_IN_KHZ; + /* TODO: check if undefined works */ + cntl.color_depth = COLOR_DEPTH_UNDEFINED; + + result = link_transmitter_control(enc10, &cntl); + + if (result != BP_RESULT_OK) { + DC_LOG_ERROR("%s: Failed to execute VBIOS command table!\n", + __func__); + BREAK_TO_DEBUGGER(); + } +} + +/* enables DP PHY output in MST mode */ +void dcn10_link_encoder_enable_dp_mst_output( + struct link_encoder *enc, + const struct dc_link_settings *link_settings, + enum clock_source_id clock_source) +{ + struct dcn10_link_encoder *enc10 = TO_DCN10_LINK_ENC(enc); + struct bp_transmitter_control cntl = { 0 }; + enum bp_result result; + + /* Enable the PHY */ + + /* number_of_lanes is used for pixel clock adjust, + * but it's not passed to asic_control. + * We need to set number of lanes manually. + */ + enc1_configure_encoder(enc10, link_settings); + + cntl.action = TRANSMITTER_CONTROL_ENABLE; + cntl.engine_id = ENGINE_ID_UNKNOWN; + cntl.transmitter = enc10->base.transmitter; + cntl.pll_id = clock_source; + cntl.signal = SIGNAL_TYPE_DISPLAY_PORT_MST; + cntl.lanes_number = link_settings->lane_count; + cntl.hpd_sel = enc10->base.hpd_source; + cntl.pixel_clock = link_settings->link_rate + * LINK_RATE_REF_FREQ_IN_KHZ; + /* TODO: check if undefined works */ + cntl.color_depth = COLOR_DEPTH_UNDEFINED; + + result = link_transmitter_control(enc10, &cntl); + + if (result != BP_RESULT_OK) { + DC_LOG_ERROR("%s: Failed to execute VBIOS command table!\n", + __func__); + BREAK_TO_DEBUGGER(); + } +} +/* + * @brief + * Disable transmitter and its encoder + */ +void dcn10_link_encoder_disable_output( + struct link_encoder *enc, + enum signal_type signal) +{ + struct dcn10_link_encoder *enc10 = TO_DCN10_LINK_ENC(enc); + struct bp_transmitter_control cntl = { 0 }; + enum bp_result result; + + if (enc->funcs->is_dig_enabled && !enc->funcs->is_dig_enabled(enc)) { + /* OF_SKIP_POWER_DOWN_INACTIVE_ENCODER */ + /*in DP_Alt_No_Connect case, we turn off the dig already, + after excuation the PHY w/a sequence, not allow touch PHY any more*/ + return; + } + /* Power-down RX and disable GPU PHY should be paired. + * Disabling PHY without powering down RX may cause + * symbol lock loss, on which we will get DP Sink interrupt. + */ + + /* There is a case for the DP active dongles + * where we want to disable the PHY but keep RX powered, + * for those we need to ignore DP Sink interrupt + * by checking lane count that has been set + * on the last do_enable_output(). + */ + + /* disable transmitter */ + cntl.action = TRANSMITTER_CONTROL_DISABLE; + cntl.transmitter = enc10->base.transmitter; + cntl.hpd_sel = enc10->base.hpd_source; + cntl.signal = signal; + cntl.connector_obj_id = enc10->base.connector; + + result = link_transmitter_control(enc10, &cntl); + + if (result != BP_RESULT_OK) { + DC_LOG_ERROR("%s: Failed to execute VBIOS command table!\n", + __func__); + BREAK_TO_DEBUGGER(); + return; + } + + /* disable encoder */ + if (dc_is_dp_signal(signal)) + link_encoder_disable(enc10); +} + +void dcn10_link_encoder_dp_set_lane_settings( + struct link_encoder *enc, + const struct dc_link_settings *link_settings, + const struct dc_lane_settings lane_settings[LANE_COUNT_DP_MAX]) +{ + struct dcn10_link_encoder *enc10 = TO_DCN10_LINK_ENC(enc); + union dpcd_training_lane_set training_lane_set = { { 0 } }; + int32_t lane = 0; + struct bp_transmitter_control cntl = { 0 }; + enum bp_result result; + + if (!link_settings) { + BREAK_TO_DEBUGGER(); + return; + } + + cntl.action = TRANSMITTER_CONTROL_SET_VOLTAGE_AND_PREEMPASIS; + cntl.transmitter = enc10->base.transmitter; + cntl.connector_obj_id = enc10->base.connector; + cntl.lanes_number = link_settings->lane_count; + cntl.hpd_sel = enc10->base.hpd_source; + cntl.pixel_clock = link_settings->link_rate * LINK_RATE_REF_FREQ_IN_KHZ; + + for (lane = 0; lane < link_settings->lane_count; lane++) { + /* translate lane settings */ + + training_lane_set.bits.VOLTAGE_SWING_SET = + lane_settings[lane].VOLTAGE_SWING; + training_lane_set.bits.PRE_EMPHASIS_SET = + lane_settings[lane].PRE_EMPHASIS; + + /* post cursor 2 setting only applies to HBR2 link rate */ + if (link_settings->link_rate == LINK_RATE_HIGH2) { + /* this is passed to VBIOS + * to program post cursor 2 level + */ + training_lane_set.bits.POST_CURSOR2_SET = + lane_settings[lane].POST_CURSOR2; + } + + cntl.lane_select = lane; + cntl.lane_settings = training_lane_set.raw; + + /* call VBIOS table to set voltage swing and pre-emphasis */ + result = link_transmitter_control(enc10, &cntl); + + if (result != BP_RESULT_OK) { + DC_LOG_ERROR("%s: Failed to execute VBIOS command table!\n", __func__); + BREAK_TO_DEBUGGER(); + } + } +} + +/* set DP PHY test and training patterns */ +void dcn10_link_encoder_dp_set_phy_pattern( + struct link_encoder *enc, + const struct encoder_set_dp_phy_pattern_param *param) +{ + struct dcn10_link_encoder *enc10 = TO_DCN10_LINK_ENC(enc); + + switch (param->dp_phy_pattern) { + case DP_TEST_PATTERN_TRAINING_PATTERN1: + dcn10_link_encoder_set_dp_phy_pattern_training_pattern(enc, 0); + break; + case DP_TEST_PATTERN_TRAINING_PATTERN2: + dcn10_link_encoder_set_dp_phy_pattern_training_pattern(enc, 1); + break; + case DP_TEST_PATTERN_TRAINING_PATTERN3: + dcn10_link_encoder_set_dp_phy_pattern_training_pattern(enc, 2); + break; + case DP_TEST_PATTERN_TRAINING_PATTERN4: + dcn10_link_encoder_set_dp_phy_pattern_training_pattern(enc, 3); + break; + case DP_TEST_PATTERN_D102: + set_dp_phy_pattern_d102(enc10); + break; + case DP_TEST_PATTERN_SYMBOL_ERROR: + set_dp_phy_pattern_symbol_error(enc10); + break; + case DP_TEST_PATTERN_PRBS7: + set_dp_phy_pattern_prbs7(enc10); + break; + case DP_TEST_PATTERN_80BIT_CUSTOM: + set_dp_phy_pattern_80bit_custom( + enc10, param->custom_pattern); + break; + case DP_TEST_PATTERN_CP2520_1: + set_dp_phy_pattern_hbr2_compliance_cp2520_2(enc10, 1); + break; + case DP_TEST_PATTERN_CP2520_2: + set_dp_phy_pattern_hbr2_compliance_cp2520_2(enc10, 2); + break; + case DP_TEST_PATTERN_CP2520_3: + set_dp_phy_pattern_hbr2_compliance_cp2520_2(enc10, 3); + break; + case DP_TEST_PATTERN_VIDEO_MODE: { + set_dp_phy_pattern_passthrough_mode( + enc10, param->dp_panel_mode); + break; + } + + default: + /* invalid phy pattern */ + ASSERT_CRITICAL(false); + break; + } +} + +static void fill_stream_allocation_row_info( + const struct link_mst_stream_allocation *stream_allocation, + uint32_t *src, + uint32_t *slots) +{ + const struct stream_encoder *stream_enc = stream_allocation->stream_enc; + + if (stream_enc) { + *src = stream_enc->id; + *slots = stream_allocation->slot_count; + } else { + *src = 0; + *slots = 0; + } +} + +/* programs DP MST VC payload allocation */ +void dcn10_link_encoder_update_mst_stream_allocation_table( + struct link_encoder *enc, + const struct link_mst_stream_allocation_table *table) +{ + struct dcn10_link_encoder *enc10 = TO_DCN10_LINK_ENC(enc); + uint32_t value1 = 0; + uint32_t value2 = 0; + uint32_t slots = 0; + uint32_t src = 0; + uint32_t retries = 0; + + /* For CZ, there are only 3 pipes. So Virtual channel is up 3.*/ + + /* --- Set MSE Stream Attribute - + * Setup VC Payload Table on Tx Side, + * Issue allocation change trigger + * to commit payload on both tx and rx side + */ + + /* we should clean-up table each time */ + + if (table->stream_count >= 1) { + fill_stream_allocation_row_info( + &table->stream_allocations[0], + &src, + &slots); + } else { + src = 0; + slots = 0; + } + + REG_UPDATE_2(DP_MSE_SAT0, + DP_MSE_SAT_SRC0, src, + DP_MSE_SAT_SLOT_COUNT0, slots); + + if (table->stream_count >= 2) { + fill_stream_allocation_row_info( + &table->stream_allocations[1], + &src, + &slots); + } else { + src = 0; + slots = 0; + } + + REG_UPDATE_2(DP_MSE_SAT0, + DP_MSE_SAT_SRC1, src, + DP_MSE_SAT_SLOT_COUNT1, slots); + + if (table->stream_count >= 3) { + fill_stream_allocation_row_info( + &table->stream_allocations[2], + &src, + &slots); + } else { + src = 0; + slots = 0; + } + + REG_UPDATE_2(DP_MSE_SAT1, + DP_MSE_SAT_SRC2, src, + DP_MSE_SAT_SLOT_COUNT2, slots); + + if (table->stream_count >= 4) { + fill_stream_allocation_row_info( + &table->stream_allocations[3], + &src, + &slots); + } else { + src = 0; + slots = 0; + } + + REG_UPDATE_2(DP_MSE_SAT1, + DP_MSE_SAT_SRC3, src, + DP_MSE_SAT_SLOT_COUNT3, slots); + + /* --- wait for transaction finish */ + + /* send allocation change trigger (ACT) ? + * this step first sends the ACT, + * then double buffers the SAT into the hardware + * making the new allocation active on the DP MST mode link + */ + + /* DP_MSE_SAT_UPDATE: + * 0 - No Action + * 1 - Update SAT with trigger + * 2 - Update SAT without trigger + */ + REG_UPDATE(DP_MSE_SAT_UPDATE, + DP_MSE_SAT_UPDATE, 1); + + /* wait for update to complete + * (i.e. DP_MSE_SAT_UPDATE field is reset to 0) + * then wait for the transmission + * of at least 16 MTP headers on immediate local link. + * i.e. DP_MSE_16_MTP_KEEPOUT field (read only) is reset to 0 + * a value of 1 indicates that DP MST mode + * is in the 16 MTP keepout region after a VC has been added. + * MST stream bandwidth (VC rate) can be configured + * after this bit is cleared + */ + do { + udelay(10); + + REG_READ(DP_MSE_SAT_UPDATE); + + REG_GET(DP_MSE_SAT_UPDATE, + DP_MSE_SAT_UPDATE, &value1); + + REG_GET(DP_MSE_SAT_UPDATE, + DP_MSE_16_MTP_KEEPOUT, &value2); + + /* bit field DP_MSE_SAT_UPDATE is set to 1 already */ + if (!value1 && !value2) + break; + ++retries; + } while (retries < DP_MST_UPDATE_MAX_RETRY); +} + +void dcn10_link_encoder_connect_dig_be_to_fe( + struct link_encoder *enc, + enum engine_id engine, + bool connect) +{ + struct dcn10_link_encoder *enc10 = TO_DCN10_LINK_ENC(enc); + uint32_t field; + + if (engine != ENGINE_ID_UNKNOWN) { + + REG_GET(DIG_BE_CNTL, DIG_FE_SOURCE_SELECT, &field); + + if (connect) + field |= get_frontend_source(engine); + else + field &= ~get_frontend_source(engine); + + REG_UPDATE(DIG_BE_CNTL, DIG_FE_SOURCE_SELECT, field); + } +} + + +#define HPD_REG(reg)\ + (enc10->hpd_regs->reg) + +#define HPD_REG_READ(reg_name) \ + dm_read_reg(CTX, HPD_REG(reg_name)) + +#define HPD_REG_UPDATE_N(reg_name, n, ...) \ + generic_reg_update_ex(CTX, \ + HPD_REG(reg_name), \ + n, __VA_ARGS__) + +#define HPD_REG_UPDATE(reg_name, field, val) \ + HPD_REG_UPDATE_N(reg_name, 1, \ + FN(reg_name, field), val) + +void dcn10_link_encoder_enable_hpd(struct link_encoder *enc) +{ + struct dcn10_link_encoder *enc10 = TO_DCN10_LINK_ENC(enc); + + HPD_REG_UPDATE(DC_HPD_CONTROL, + DC_HPD_EN, 1); +} + +void dcn10_link_encoder_disable_hpd(struct link_encoder *enc) +{ + struct dcn10_link_encoder *enc10 = TO_DCN10_LINK_ENC(enc); + + HPD_REG_UPDATE(DC_HPD_CONTROL, + DC_HPD_EN, 0); +} + +#define AUX_REG(reg)\ + (enc10->aux_regs->reg) + +#define AUX_REG_READ(reg_name) \ + dm_read_reg(CTX, AUX_REG(reg_name)) + +#define AUX_REG_UPDATE_N(reg_name, n, ...) \ + generic_reg_update_ex(CTX, \ + AUX_REG(reg_name), \ + n, __VA_ARGS__) + +#define AUX_REG_UPDATE(reg_name, field, val) \ + AUX_REG_UPDATE_N(reg_name, 1, \ + FN(reg_name, field), val) + +#define AUX_REG_UPDATE_2(reg, f1, v1, f2, v2) \ + AUX_REG_UPDATE_N(reg, 2,\ + FN(reg, f1), v1,\ + FN(reg, f2), v2) + +void dcn10_aux_initialize(struct dcn10_link_encoder *enc10) +{ + enum hpd_source_id hpd_source = enc10->base.hpd_source; + + AUX_REG_UPDATE_2(AUX_CONTROL, + AUX_HPD_SEL, hpd_source, + AUX_LS_READ_EN, 0); + + /* 1/4 window (the maximum allowed) */ + AUX_REG_UPDATE(AUX_DPHY_RX_CONTROL0, + AUX_RX_RECEIVE_WINDOW, 0); +} + +enum signal_type dcn10_get_dig_mode( + struct link_encoder *enc) +{ + struct dcn10_link_encoder *enc10 = TO_DCN10_LINK_ENC(enc); + uint32_t value; + REG_GET(DIG_BE_CNTL, DIG_MODE, &value); + switch (value) { + case 1: + return SIGNAL_TYPE_DISPLAY_PORT; + case 2: + return SIGNAL_TYPE_DVI_SINGLE_LINK; + case 3: + return SIGNAL_TYPE_HDMI_TYPE_A; + case 5: + return SIGNAL_TYPE_DISPLAY_PORT_MST; + default: + return SIGNAL_TYPE_NONE; + } +} + +void dcn10_link_encoder_get_max_link_cap(struct link_encoder *enc, + struct dc_link_settings *link_settings) +{ + /* Set Default link settings */ + struct dc_link_settings max_link_cap = {LANE_COUNT_FOUR, LINK_RATE_HIGH, + LINK_SPREAD_05_DOWNSPREAD_30KHZ, false, 0}; + + /* Higher link settings based on feature supported */ + if (enc->features.flags.bits.IS_HBR2_CAPABLE) + max_link_cap.link_rate = LINK_RATE_HIGH2; + + if (enc->features.flags.bits.IS_HBR3_CAPABLE) + max_link_cap.link_rate = LINK_RATE_HIGH3; + + if (enc->features.flags.bits.IS_UHBR10_CAPABLE) + max_link_cap.link_rate = LINK_RATE_UHBR10; + + if (enc->features.flags.bits.IS_UHBR13_5_CAPABLE) + max_link_cap.link_rate = LINK_RATE_UHBR13_5; + + if (enc->features.flags.bits.IS_UHBR20_CAPABLE) + max_link_cap.link_rate = LINK_RATE_UHBR20; + + *link_settings = max_link_cap; +} diff --git a/drivers/gpu/drm/amd/display/dc/dio/dcn10/dcn10_link_encoder.h b/drivers/gpu/drm/amd/display/dc/dio/dcn10/dcn10_link_encoder.h new file mode 100644 index 000000000000..b7a89c39f445 --- /dev/null +++ b/drivers/gpu/drm/amd/display/dc/dio/dcn10/dcn10_link_encoder.h @@ -0,0 +1,659 @@ +/* + * Copyright 2012-15 Advanced Micro Devices, Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + * + * Authors: AMD + * + */ + +#ifndef __DC_LINK_ENCODER__DCN10_H__ +#define __DC_LINK_ENCODER__DCN10_H__ + +#include "link_encoder.h" + +#define TO_DCN10_LINK_ENC(link_encoder)\ + container_of(link_encoder, struct dcn10_link_encoder, base) + +#define AUX_REG_LIST(id)\ + SRI(AUX_CONTROL, DP_AUX, id), \ + SRI(AUX_DPHY_RX_CONTROL0, DP_AUX, id), \ + SRI(AUX_DPHY_RX_CONTROL1, DP_AUX, id) + +#define HPD_REG_LIST(id)\ + SRI(DC_HPD_CONTROL, HPD, id) + +#define LE_DCN_COMMON_REG_LIST(id) \ + SRI(DIG_BE_CNTL, DIG, id), \ + SRI(DIG_BE_EN_CNTL, DIG, id), \ + SRI(DIG_CLOCK_PATTERN, DIG, id), \ + SRI(TMDS_CTL_BITS, DIG, id), \ + SRI(DP_CONFIG, DP, id), \ + SRI(DP_DPHY_CNTL, DP, id), \ + SRI(DP_DPHY_PRBS_CNTL, DP, id), \ + SRI(DP_DPHY_SCRAM_CNTL, DP, id),\ + SRI(DP_DPHY_SYM0, DP, id), \ + SRI(DP_DPHY_SYM1, DP, id), \ + SRI(DP_DPHY_SYM2, DP, id), \ + SRI(DP_DPHY_TRAINING_PATTERN_SEL, DP, id), \ + SRI(DP_LINK_CNTL, DP, id), \ + SRI(DP_LINK_FRAMING_CNTL, DP, id), \ + SRI(DP_MSE_SAT0, DP, id), \ + SRI(DP_MSE_SAT1, DP, id), \ + SRI(DP_MSE_SAT2, DP, id), \ + SRI(DP_MSE_SAT_UPDATE, DP, id), \ + SRI(DP_SEC_CNTL, DP, id), \ + SRI(DP_VID_STREAM_CNTL, DP, id), \ + SRI(DP_DPHY_FAST_TRAINING, DP, id), \ + SRI(DP_SEC_CNTL1, DP, id), \ + SRI(DP_DPHY_BS_SR_SWAP_CNTL, DP, id), \ + SRI(DP_DPHY_HBR2_PATTERN_CONTROL, DP, id) + + +#define LE_DCN10_REG_LIST(id)\ + SRI(DP_DPHY_INTERNAL_CTRL, DP, id), \ + LE_DCN_COMMON_REG_LIST(id) + +struct dcn10_link_enc_aux_registers { + uint32_t AUX_CONTROL; + uint32_t AUX_DPHY_RX_CONTROL0; + uint32_t AUX_DPHY_TX_CONTROL; + uint32_t AUX_DPHY_RX_CONTROL1; +}; + +struct dcn10_link_enc_hpd_registers { + uint32_t DC_HPD_CONTROL; +}; + +struct dcn10_link_enc_registers { + uint32_t DIG_BE_CNTL; + uint32_t DIG_BE_EN_CNTL; + uint32_t DIG_CLOCK_PATTERN; + uint32_t DP_CONFIG; + uint32_t DP_DPHY_CNTL; + uint32_t DP_DPHY_INTERNAL_CTRL; + uint32_t DP_DPHY_PRBS_CNTL; + uint32_t DP_DPHY_SCRAM_CNTL; + uint32_t DP_DPHY_SYM0; + uint32_t DP_DPHY_SYM1; + uint32_t DP_DPHY_SYM2; + uint32_t DP_DPHY_TRAINING_PATTERN_SEL; + uint32_t DP_LINK_CNTL; + uint32_t DP_LINK_FRAMING_CNTL; + uint32_t DP_MSE_SAT0; + uint32_t DP_MSE_SAT1; + uint32_t DP_MSE_SAT2; + uint32_t DP_MSE_SAT_UPDATE; + uint32_t DP_SEC_CNTL; + uint32_t DP_VID_STREAM_CNTL; + uint32_t DP_DPHY_FAST_TRAINING; + uint32_t DP_DPHY_BS_SR_SWAP_CNTL; + uint32_t DP_DPHY_HBR2_PATTERN_CONTROL; + uint32_t DP_SEC_CNTL1; + uint32_t TMDS_CTL_BITS; + /* DCCG */ + uint32_t CLOCK_ENABLE; + /* DIG */ + uint32_t DIG_LANE_ENABLE; + /* UNIPHY */ + uint32_t CHANNEL_XBAR_CNTL; + /* DPCS */ + uint32_t RDPCSTX_PHY_CNTL3; + uint32_t RDPCSTX_PHY_CNTL4; + uint32_t RDPCSTX_PHY_CNTL5; + uint32_t RDPCSTX_PHY_CNTL6; + uint32_t RDPCSPIPE_PHY_CNTL6; + uint32_t RDPCSTX_PHY_CNTL7; + uint32_t RDPCSTX_PHY_CNTL8; + uint32_t RDPCSTX_PHY_CNTL9; + uint32_t RDPCSTX_PHY_CNTL10; + uint32_t RDPCSTX_PHY_CNTL11; + uint32_t RDPCSTX_PHY_CNTL12; + uint32_t RDPCSTX_PHY_CNTL13; + uint32_t RDPCSTX_PHY_CNTL14; + uint32_t RDPCSTX_PHY_CNTL15; + uint32_t RDPCSTX_CNTL; + uint32_t RDPCSTX_CLOCK_CNTL; + uint32_t RDPCSTX_PHY_CNTL0; + uint32_t RDPCSTX_PHY_CNTL2; + uint32_t RDPCSTX_PLL_UPDATE_DATA; + uint32_t RDPCS_TX_CR_ADDR; + uint32_t RDPCS_TX_CR_DATA; + uint32_t DPCSTX_TX_CLOCK_CNTL; + uint32_t DPCSTX_TX_CNTL; + uint32_t RDPCSTX_INTERRUPT_CONTROL; + uint32_t RDPCSTX_PHY_FUSE0; + uint32_t RDPCSTX_PHY_FUSE1; + uint32_t RDPCSTX_PHY_FUSE2; + uint32_t RDPCSTX_PHY_FUSE3; + uint32_t RDPCSTX_PHY_RX_LD_VAL; + uint32_t DPCSTX_DEBUG_CONFIG; + uint32_t RDPCSTX_DEBUG_CONFIG; + uint32_t RDPCSTX0_RDPCSTX_SCRATCH; + uint32_t RDPCSTX_DMCU_DPALT_DIS_BLOCK_REG; + uint32_t DCIO_SOFT_RESET; + /* indirect registers */ + uint32_t RAWLANE0_DIG_PCS_XF_RX_OVRD_IN_2; + uint32_t RAWLANE0_DIG_PCS_XF_RX_OVRD_IN_3; + uint32_t RAWLANE1_DIG_PCS_XF_RX_OVRD_IN_2; + uint32_t RAWLANE1_DIG_PCS_XF_RX_OVRD_IN_3; + uint32_t RAWLANE2_DIG_PCS_XF_RX_OVRD_IN_2; + uint32_t RAWLANE2_DIG_PCS_XF_RX_OVRD_IN_3; + uint32_t RAWLANE3_DIG_PCS_XF_RX_OVRD_IN_2; + uint32_t RAWLANE3_DIG_PCS_XF_RX_OVRD_IN_3; + uint32_t TMDS_DCBALANCER_CONTROL; + uint32_t PHYA_LINK_CNTL2; + uint32_t PHYB_LINK_CNTL2; + uint32_t PHYC_LINK_CNTL2; + uint32_t DIO_LINKA_CNTL; + uint32_t DIO_LINKB_CNTL; + uint32_t DIO_LINKC_CNTL; + uint32_t DIO_LINKD_CNTL; + uint32_t DIO_LINKE_CNTL; + uint32_t DIO_LINKF_CNTL; + uint32_t DIO_CLK_CNTL; + uint32_t DIG_BE_CLK_CNTL; +}; + +#define LE_SF(reg_name, field_name, post_fix)\ + .field_name = reg_name ## __ ## field_name ## post_fix + +#define LINK_ENCODER_MASK_SH_LIST_DCN10(mask_sh)\ + LE_SF(DIG0_DIG_BE_EN_CNTL, DIG_ENABLE, mask_sh),\ + LE_SF(DIG0_DIG_BE_CNTL, DIG_HPD_SELECT, mask_sh),\ + LE_SF(DIG0_DIG_BE_CNTL, DIG_MODE, mask_sh),\ + LE_SF(DIG0_DIG_BE_CNTL, DIG_FE_SOURCE_SELECT, mask_sh),\ + LE_SF(DIG0_DIG_CLOCK_PATTERN, DIG_CLOCK_PATTERN, mask_sh),\ + LE_SF(DIG0_TMDS_CTL_BITS, TMDS_CTL0, mask_sh), \ + LE_SF(DP0_DP_DPHY_CNTL, DPHY_BYPASS, mask_sh),\ + LE_SF(DP0_DP_DPHY_CNTL, DPHY_ATEST_SEL_LANE0, mask_sh),\ + LE_SF(DP0_DP_DPHY_CNTL, DPHY_ATEST_SEL_LANE1, mask_sh),\ + LE_SF(DP0_DP_DPHY_CNTL, DPHY_ATEST_SEL_LANE2, mask_sh),\ + LE_SF(DP0_DP_DPHY_CNTL, DPHY_ATEST_SEL_LANE3, mask_sh),\ + LE_SF(DP0_DP_DPHY_PRBS_CNTL, DPHY_PRBS_EN, mask_sh),\ + LE_SF(DP0_DP_DPHY_PRBS_CNTL, DPHY_PRBS_SEL, mask_sh),\ + LE_SF(DP0_DP_DPHY_SYM0, DPHY_SYM1, mask_sh),\ + LE_SF(DP0_DP_DPHY_SYM0, DPHY_SYM2, mask_sh),\ + LE_SF(DP0_DP_DPHY_SYM0, DPHY_SYM3, mask_sh),\ + LE_SF(DP0_DP_DPHY_SYM1, DPHY_SYM4, mask_sh),\ + LE_SF(DP0_DP_DPHY_SYM1, DPHY_SYM5, mask_sh),\ + LE_SF(DP0_DP_DPHY_SYM1, DPHY_SYM6, mask_sh),\ + LE_SF(DP0_DP_DPHY_SYM2, DPHY_SYM7, mask_sh),\ + LE_SF(DP0_DP_DPHY_SYM2, DPHY_SYM8, mask_sh),\ + LE_SF(DP0_DP_DPHY_SCRAM_CNTL, DPHY_SCRAMBLER_BS_COUNT, mask_sh),\ + LE_SF(DP0_DP_DPHY_SCRAM_CNTL, DPHY_SCRAMBLER_ADVANCE, mask_sh),\ + LE_SF(DP0_DP_DPHY_FAST_TRAINING, DPHY_RX_FAST_TRAINING_CAPABLE, mask_sh),\ + LE_SF(DP0_DP_DPHY_BS_SR_SWAP_CNTL, DPHY_LOAD_BS_COUNT, mask_sh),\ + LE_SF(DP0_DP_DPHY_TRAINING_PATTERN_SEL, DPHY_TRAINING_PATTERN_SEL, mask_sh),\ + LE_SF(DP0_DP_DPHY_HBR2_PATTERN_CONTROL, DP_DPHY_HBR2_PATTERN_CONTROL, mask_sh),\ + LE_SF(DP0_DP_LINK_CNTL, DP_LINK_TRAINING_COMPLETE, mask_sh),\ + LE_SF(DP0_DP_LINK_FRAMING_CNTL, DP_IDLE_BS_INTERVAL, mask_sh),\ + LE_SF(DP0_DP_LINK_FRAMING_CNTL, DP_VBID_DISABLE, mask_sh),\ + LE_SF(DP0_DP_LINK_FRAMING_CNTL, DP_VID_ENHANCED_FRAME_MODE, mask_sh),\ + LE_SF(DP0_DP_VID_STREAM_CNTL, DP_VID_STREAM_ENABLE, mask_sh),\ + LE_SF(DP0_DP_CONFIG, DP_UDI_LANES, mask_sh),\ + LE_SF(DP0_DP_SEC_CNTL1, DP_SEC_GSP0_LINE_NUM, mask_sh),\ + LE_SF(DP0_DP_SEC_CNTL1, DP_SEC_GSP0_PRIORITY, mask_sh),\ + LE_SF(DP0_DP_MSE_SAT0, DP_MSE_SAT_SRC0, mask_sh),\ + LE_SF(DP0_DP_MSE_SAT0, DP_MSE_SAT_SRC1, mask_sh),\ + LE_SF(DP0_DP_MSE_SAT0, DP_MSE_SAT_SLOT_COUNT0, mask_sh),\ + LE_SF(DP0_DP_MSE_SAT0, DP_MSE_SAT_SLOT_COUNT1, mask_sh),\ + LE_SF(DP0_DP_MSE_SAT1, DP_MSE_SAT_SRC2, mask_sh),\ + LE_SF(DP0_DP_MSE_SAT1, DP_MSE_SAT_SRC3, mask_sh),\ + LE_SF(DP0_DP_MSE_SAT1, DP_MSE_SAT_SLOT_COUNT2, mask_sh),\ + LE_SF(DP0_DP_MSE_SAT1, DP_MSE_SAT_SLOT_COUNT3, mask_sh),\ + LE_SF(DP0_DP_MSE_SAT_UPDATE, DP_MSE_SAT_UPDATE, mask_sh),\ + LE_SF(DP0_DP_MSE_SAT_UPDATE, DP_MSE_16_MTP_KEEPOUT, mask_sh),\ + LE_SF(DP_AUX0_AUX_CONTROL, AUX_HPD_SEL, mask_sh),\ + LE_SF(DP_AUX0_AUX_CONTROL, AUX_LS_READ_EN, mask_sh),\ + LE_SF(DP_AUX0_AUX_DPHY_RX_CONTROL0, AUX_RX_RECEIVE_WINDOW, mask_sh),\ + LE_SF(HPD0_DC_HPD_CONTROL, DC_HPD_EN, mask_sh) + +#define DCN_LINK_ENCODER_REG_FIELD_LIST(type) \ + type DIG_ENABLE;\ + type DIG_HPD_SELECT;\ + type DIG_MODE;\ + type DIG_FE_SOURCE_SELECT;\ + type DIG_CLOCK_PATTERN;\ + type DPHY_BYPASS;\ + type DPHY_ATEST_SEL_LANE0;\ + type DPHY_ATEST_SEL_LANE1;\ + type DPHY_ATEST_SEL_LANE2;\ + type DPHY_ATEST_SEL_LANE3;\ + type DPHY_PRBS_EN;\ + type DPHY_PRBS_SEL;\ + type DPHY_SYM1;\ + type DPHY_SYM2;\ + type DPHY_SYM3;\ + type DPHY_SYM4;\ + type DPHY_SYM5;\ + type DPHY_SYM6;\ + type DPHY_SYM7;\ + type DPHY_SYM8;\ + type DPHY_SCRAMBLER_BS_COUNT;\ + type DPHY_SCRAMBLER_ADVANCE;\ + type DPHY_RX_FAST_TRAINING_CAPABLE;\ + type DPHY_LOAD_BS_COUNT;\ + type DPHY_TRAINING_PATTERN_SEL;\ + type DP_DPHY_HBR2_PATTERN_CONTROL;\ + type DP_LINK_TRAINING_COMPLETE;\ + type DP_IDLE_BS_INTERVAL;\ + type DP_VBID_DISABLE;\ + type DP_VID_ENHANCED_FRAME_MODE;\ + type DP_VID_STREAM_ENABLE;\ + type DP_UDI_LANES;\ + type DP_SEC_GSP0_LINE_NUM;\ + type DP_SEC_GSP0_PRIORITY;\ + type DP_MSE_SAT_SRC0;\ + type DP_MSE_SAT_SRC1;\ + type DP_MSE_SAT_SRC2;\ + type DP_MSE_SAT_SRC3;\ + type DP_MSE_SAT_SLOT_COUNT0;\ + type DP_MSE_SAT_SLOT_COUNT1;\ + type DP_MSE_SAT_SLOT_COUNT2;\ + type DP_MSE_SAT_SLOT_COUNT3;\ + type DP_MSE_SAT_UPDATE;\ + type DP_MSE_16_MTP_KEEPOUT;\ + type DC_HPD_EN;\ + type TMDS_CTL0;\ + type AUX_HPD_SEL;\ + type AUX_LS_READ_EN;\ + type AUX_RX_RECEIVE_WINDOW + + +#define DCN20_LINK_ENCODER_DPCS_REG_FIELD_LIST(type) \ + type RDPCS_PHY_DP_TX0_DATA_EN;\ + type RDPCS_PHY_DP_TX1_DATA_EN;\ + type RDPCS_PHY_DP_TX2_DATA_EN;\ + type RDPCS_PHY_DP_TX3_DATA_EN;\ + type RDPCS_PHY_DP_TX0_PSTATE;\ + type RDPCS_PHY_DP_TX1_PSTATE;\ + type RDPCS_PHY_DP_TX2_PSTATE;\ + type RDPCS_PHY_DP_TX3_PSTATE;\ + type RDPCS_PHY_DP_TX0_MPLL_EN;\ + type RDPCS_PHY_DP_TX1_MPLL_EN;\ + type RDPCS_PHY_DP_TX2_MPLL_EN;\ + type RDPCS_PHY_DP_TX3_MPLL_EN;\ + type RDPCS_TX_FIFO_LANE0_EN;\ + type RDPCS_TX_FIFO_LANE1_EN;\ + type RDPCS_TX_FIFO_LANE2_EN;\ + type RDPCS_TX_FIFO_LANE3_EN;\ + type RDPCS_EXT_REFCLK_EN;\ + type RDPCS_TX_FIFO_EN;\ + type UNIPHY_LINK_ENABLE;\ + type UNIPHY_CHANNEL0_XBAR_SOURCE;\ + type UNIPHY_CHANNEL1_XBAR_SOURCE;\ + type UNIPHY_CHANNEL2_XBAR_SOURCE;\ + type UNIPHY_CHANNEL3_XBAR_SOURCE;\ + type UNIPHY_CHANNEL0_INVERT;\ + type UNIPHY_CHANNEL1_INVERT;\ + type UNIPHY_CHANNEL2_INVERT;\ + type UNIPHY_CHANNEL3_INVERT;\ + type UNIPHY_LINK_ENABLE_HPD_MASK;\ + type UNIPHY_LANE_STAGGER_DELAY;\ + type RDPCS_SRAMCLK_BYPASS;\ + type RDPCS_SRAMCLK_EN;\ + type RDPCS_SRAMCLK_CLOCK_ON;\ + type DPCS_TX_FIFO_EN;\ + type RDPCS_PHY_DP_TX0_DISABLE;\ + type RDPCS_PHY_DP_TX1_DISABLE;\ + type RDPCS_PHY_DP_TX2_DISABLE;\ + type RDPCS_PHY_DP_TX3_DISABLE;\ + type RDPCS_PHY_DP_TX0_CLK_RDY;\ + type RDPCS_PHY_DP_TX1_CLK_RDY;\ + type RDPCS_PHY_DP_TX2_CLK_RDY;\ + type RDPCS_PHY_DP_TX3_CLK_RDY;\ + type RDPCS_PHY_DP_TX0_REQ;\ + type RDPCS_PHY_DP_TX1_REQ;\ + type RDPCS_PHY_DP_TX2_REQ;\ + type RDPCS_PHY_DP_TX3_REQ;\ + type RDPCS_PHY_DP_TX0_ACK;\ + type RDPCS_PHY_DP_TX1_ACK;\ + type RDPCS_PHY_DP_TX2_ACK;\ + type RDPCS_PHY_DP_TX3_ACK;\ + type RDPCS_PHY_DP_TX0_RESET;\ + type RDPCS_PHY_DP_TX1_RESET;\ + type RDPCS_PHY_DP_TX2_RESET;\ + type RDPCS_PHY_DP_TX3_RESET;\ + type RDPCS_PHY_RESET;\ + type RDPCS_PHY_CR_MUX_SEL;\ + type RDPCS_PHY_REF_RANGE;\ + type RDPCS_PHY_DP4_POR;\ + type RDPCS_SRAM_BYPASS;\ + type RDPCS_SRAM_EXT_LD_DONE;\ + type RDPCS_PHY_DP_TX0_TERM_CTRL;\ + type RDPCS_PHY_DP_TX1_TERM_CTRL;\ + type RDPCS_PHY_DP_TX2_TERM_CTRL;\ + type RDPCS_PHY_DP_TX3_TERM_CTRL;\ + type RDPCS_PHY_DP_REF_CLK_MPLLB_DIV;\ + type RDPCS_PHY_DP_MPLLB_MULTIPLIER;\ + type RDPCS_PHY_DP_MPLLB_SSC_EN;\ + type RDPCS_PHY_DP_MPLLB_DIV5_CLK_EN;\ + type RDPCS_PHY_DP_MPLLB_TX_CLK_DIV;\ + type RDPCS_PHY_DP_MPLLB_WORD_DIV2_EN;\ + type RDPCS_PHY_DP_MPLLB_FRACN_EN;\ + type RDPCS_PHY_DP_MPLLB_PMIX_EN;\ + type RDPCS_PHY_DP_MPLLB_FRACN_QUOT;\ + type RDPCS_PHY_DP_MPLLB_FRACN_DEN;\ + type RDPCS_PHY_DP_MPLLB_FRACN_REM;\ + type RDPCS_PHY_DP_MPLLB_SSC_UP_SPREAD;\ + type RDPCS_PHY_DP_MPLLB_SSC_STEPSIZE;\ + type RDPCS_PHY_DP_MPLLB_SSC_PEAK;\ + type RDPCS_PHY_DP_MPLLB_DIV_CLK_EN;\ + type RDPCS_PHY_DP_MPLLB_DIV_MULTIPLIER;\ + type RDPCS_PHY_TX_VBOOST_LVL;\ + type RDPCS_PHY_HDMIMODE_ENABLE;\ + type RDPCS_PHY_DP_REF_CLK_EN;\ + type RDPCS_PLL_UPDATE_DATA;\ + type RDPCS_SRAM_INIT_DONE;\ + type RDPCS_TX_CR_ADDR;\ + type RDPCS_TX_CR_DATA;\ + type RDPCS_PHY_HDMI_MPLLB_HDMI_DIV;\ + type RDPCS_PHY_DP_MPLLB_STATE;\ + type RDPCS_PHY_DP_TX0_WIDTH;\ + type RDPCS_PHY_DP_TX0_RATE;\ + type RDPCS_PHY_DP_TX1_WIDTH;\ + type RDPCS_PHY_DP_TX1_RATE;\ + type RDPCS_PHY_DP_TX2_WIDTH;\ + type RDPCS_PHY_DP_TX2_RATE;\ + type RDPCS_PHY_DP_TX3_WIDTH;\ + type RDPCS_PHY_DP_TX3_RATE;\ + type DPCS_SYMCLK_CLOCK_ON;\ + type DPCS_SYMCLK_GATE_DIS;\ + type DPCS_SYMCLK_EN;\ + type RDPCS_SYMCLK_DIV2_CLOCK_ON;\ + type RDPCS_SYMCLK_DIV2_GATE_DIS;\ + type RDPCS_SYMCLK_DIV2_EN;\ + type DPCS_TX_DATA_SWAP;\ + type DPCS_TX_DATA_ORDER_INVERT;\ + type DPCS_TX_FIFO_RD_START_DELAY;\ + type RDPCS_TX_FIFO_RD_START_DELAY;\ + type RDPCS_REG_FIFO_ERROR_MASK;\ + type RDPCS_TX_FIFO_ERROR_MASK;\ + type RDPCS_DPALT_DISABLE_TOGGLE_MASK;\ + type RDPCS_DPALT_4LANE_TOGGLE_MASK;\ + type RDPCS_PHY_DPALT_DP4;\ + type RDPCS_PHY_DPALT_DISABLE;\ + type RDPCS_PHY_DPALT_DISABLE_ACK;\ + type RDPCS_PHY_DP_MPLLB_V2I;\ + type RDPCS_PHY_DP_MPLLB_FREQ_VCO;\ + type RDPCS_PHY_DP_MPLLB_CP_INT_GS;\ + type RDPCS_PHY_RX_VREF_CTRL;\ + type RDPCS_PHY_DP_MPLLB_CP_INT;\ + type RDPCS_PHY_DP_MPLLB_CP_PROP;\ + type RDPCS_PHY_RX_REF_LD_VAL;\ + type RDPCS_PHY_RX_VCO_LD_VAL;\ + type DPCSTX_DEBUG_CONFIG; \ + type RDPCSTX_DEBUG_CONFIG; \ + type RDPCS_PHY_DP_TX0_EQ_MAIN;\ + type RDPCS_PHY_DP_TX0_EQ_PRE;\ + type RDPCS_PHY_DP_TX0_EQ_POST;\ + type RDPCS_PHY_DP_TX1_EQ_MAIN;\ + type RDPCS_PHY_DP_TX1_EQ_PRE;\ + type RDPCS_PHY_DP_TX1_EQ_POST;\ + type RDPCS_PHY_DP_TX2_EQ_MAIN;\ + type RDPCS_PHY_DP_MPLLB_CP_PROP_GS;\ + type RDPCS_PHY_DP_TX2_EQ_PRE;\ + type RDPCS_PHY_DP_TX2_EQ_POST;\ + type RDPCS_PHY_DP_TX3_EQ_MAIN;\ + type RDPCS_PHY_DCO_RANGE;\ + type RDPCS_PHY_DCO_FINETUNE;\ + type RDPCS_PHY_DP_TX3_EQ_PRE;\ + type RDPCS_PHY_DP_TX3_EQ_POST;\ + type RDPCS_PHY_SUP_PRE_HP;\ + type RDPCS_PHY_DP_TX0_VREGDRV_BYP;\ + type RDPCS_PHY_DP_TX1_VREGDRV_BYP;\ + type RDPCS_PHY_DP_TX2_VREGDRV_BYP;\ + type RDPCS_PHY_DP_TX3_VREGDRV_BYP;\ + type RDPCS_DMCU_DPALT_DIS_BLOCK_REG;\ + type UNIPHYA_SOFT_RESET;\ + type UNIPHYB_SOFT_RESET;\ + type UNIPHYC_SOFT_RESET;\ + type UNIPHYD_SOFT_RESET;\ + type UNIPHYE_SOFT_RESET;\ + type UNIPHYF_SOFT_RESET + +#define DCN20_LINK_ENCODER_REG_FIELD_LIST(type) \ + type DIG_LANE0EN;\ + type DIG_LANE1EN;\ + type DIG_LANE2EN;\ + type DIG_LANE3EN;\ + type DIG_CLK_EN;\ + type SYMCLKA_CLOCK_ENABLE;\ + type DPHY_FEC_EN;\ + type DPHY_FEC_READY_SHADOW;\ + type DPHY_FEC_ACTIVE_STATUS;\ + DCN20_LINK_ENCODER_DPCS_REG_FIELD_LIST(type);\ + type VCO_LD_VAL_OVRD;\ + type VCO_LD_VAL_OVRD_EN;\ + type REF_LD_VAL_OVRD;\ + type REF_LD_VAL_OVRD_EN;\ + type AUX_RX_START_WINDOW; \ + type AUX_RX_HALF_SYM_DETECT_LEN; \ + type AUX_RX_TRANSITION_FILTER_EN; \ + type AUX_RX_ALLOW_BELOW_THRESHOLD_PHASE_DETECT; \ + type AUX_RX_ALLOW_BELOW_THRESHOLD_START; \ + type AUX_RX_ALLOW_BELOW_THRESHOLD_STOP; \ + type AUX_RX_PHASE_DETECT_LEN; \ + type AUX_RX_DETECTION_THRESHOLD; \ + type AUX_TX_PRECHARGE_LEN; \ + type AUX_TX_PRECHARGE_SYMBOLS; \ + type AUX_MODE_DET_CHECK_DELAY;\ + type DPCS_DBG_CBUS_DIS;\ + type AUX_RX_PRECHARGE_SKIP;\ + type AUX_RX_TIMEOUT_LEN;\ + type AUX_RX_TIMEOUT_LEN_MUL + +#define DCN30_LINK_ENCODER_REG_FIELD_LIST(type) \ + type TMDS_SYNC_DCBAL_EN;\ + type PHY_HPO_DIG_SRC_SEL;\ + type PHY_HPO_ENC_SRC_SEL;\ + type DPCS_TX_HDMI_FRL_MODE;\ + type DPCS_TX_DATA_SWAP_10_BIT;\ + type DPCS_TX_DATA_ORDER_INVERT_18_BIT;\ + type RDPCS_TX_CLK_EN + +#define DCN31_LINK_ENCODER_REG_FIELD_LIST(type) \ + type ENC_TYPE_SEL;\ + type HPO_DP_ENC_SEL;\ + type HPO_HDMI_ENC_SEL + +#define DCN35_LINK_ENCODER_REG_FIELD_LIST(type) \ + type DIG_BE_ENABLE;\ + type DIG_RB_SWITCH_EN;\ + type DIG_BE_MODE;\ + type DIG_BE_CLK_EN;\ + type DIG_BE_SOFT_RESET;\ + type HDCP_SOFT_RESET;\ + type DIG_BE_SYMCLK_G_CLOCK_ON;\ + type DIG_BE_SYMCLK_G_HDCP_CLOCK_ON;\ + type DIG_BE_SYMCLK_G_TMDS_CLOCK_ON;\ + type DISPCLK_R_GATE_DIS;\ + type DISPCLK_G_GATE_DIS;\ + type REFCLK_R_GATE_DIS;\ + type REFCLK_G_GATE_DIS;\ + type SOCCLK_G_GATE_DIS;\ + type SYMCLK_FE_R_GATE_DIS;\ + type SYMCLK_FE_G_GATE_DIS;\ + type SYMCLK_R_GATE_DIS;\ + type SYMCLK_G_GATE_DIS;\ + type DIO_FGCG_REP_DIS;\ + type DISPCLK_G_HDCP_GATE_DIS;\ + type SYMCLKA_G_HDCP_GATE_DIS;\ + type SYMCLKB_G_HDCP_GATE_DIS;\ + type SYMCLKC_G_HDCP_GATE_DIS;\ + type SYMCLKD_G_HDCP_GATE_DIS;\ + type SYMCLKE_G_HDCP_GATE_DIS;\ + type SYMCLKF_G_HDCP_GATE_DIS;\ + type SYMCLKG_G_HDCP_GATE_DIS + +struct dcn10_link_enc_shift { + DCN_LINK_ENCODER_REG_FIELD_LIST(uint8_t); + DCN20_LINK_ENCODER_REG_FIELD_LIST(uint8_t); + DCN30_LINK_ENCODER_REG_FIELD_LIST(uint8_t); + DCN31_LINK_ENCODER_REG_FIELD_LIST(uint8_t); + DCN35_LINK_ENCODER_REG_FIELD_LIST(uint8_t); +}; + +struct dcn10_link_enc_mask { + DCN_LINK_ENCODER_REG_FIELD_LIST(uint32_t); + DCN20_LINK_ENCODER_REG_FIELD_LIST(uint32_t); + DCN30_LINK_ENCODER_REG_FIELD_LIST(uint32_t); + DCN31_LINK_ENCODER_REG_FIELD_LIST(uint32_t); + DCN35_LINK_ENCODER_REG_FIELD_LIST(uint32_t); +}; + +struct dcn10_link_encoder { + struct link_encoder base; + const struct dcn10_link_enc_registers *link_regs; + const struct dcn10_link_enc_aux_registers *aux_regs; + const struct dcn10_link_enc_hpd_registers *hpd_regs; + const struct dcn10_link_enc_shift *link_shift; + const struct dcn10_link_enc_mask *link_mask; +}; + + +void dcn10_link_encoder_construct( + struct dcn10_link_encoder *enc10, + const struct encoder_init_data *init_data, + const struct encoder_feature_support *enc_features, + const struct dcn10_link_enc_registers *link_regs, + const struct dcn10_link_enc_aux_registers *aux_regs, + const struct dcn10_link_enc_hpd_registers *hpd_regs, + const struct dcn10_link_enc_shift *link_shift, + const struct dcn10_link_enc_mask *link_mask); + +bool dcn10_link_encoder_validate_dvi_output( + const struct dcn10_link_encoder *enc10, + enum signal_type connector_signal, + enum signal_type signal, + const struct dc_crtc_timing *crtc_timing); + +bool dcn10_link_encoder_validate_rgb_output( + const struct dcn10_link_encoder *enc10, + const struct dc_crtc_timing *crtc_timing); + +bool dcn10_link_encoder_validate_dp_output( + const struct dcn10_link_encoder *enc10, + const struct dc_crtc_timing *crtc_timing); + +bool dcn10_link_encoder_validate_wireless_output( + const struct dcn10_link_encoder *enc10, + const struct dc_crtc_timing *crtc_timing); + +bool dcn10_link_encoder_validate_output_with_stream( + struct link_encoder *enc, + const struct dc_stream_state *stream); + +/****************** HW programming ************************/ + +/* initialize HW */ /* why do we initialze aux in here? */ +void dcn10_link_encoder_hw_init(struct link_encoder *enc); + +void dcn10_link_encoder_destroy(struct link_encoder **enc); + +/* program DIG_MODE in DIG_BE */ +/* TODO can this be combined with enable_output? */ +void dcn10_link_encoder_setup( + struct link_encoder *enc, + enum signal_type signal); + +void enc1_configure_encoder( + struct dcn10_link_encoder *enc10, + const struct dc_link_settings *link_settings); + +/* enables TMDS PHY output */ +/* TODO: still need depth or just pass in adjusted pixel clock? */ +void dcn10_link_encoder_enable_tmds_output( + struct link_encoder *enc, + enum clock_source_id clock_source, + enum dc_color_depth color_depth, + enum signal_type signal, + uint32_t pixel_clock); + +void dcn10_link_encoder_enable_tmds_output_with_clk_pattern_wa( + struct link_encoder *enc, + enum clock_source_id clock_source, + enum dc_color_depth color_depth, + enum signal_type signal, + uint32_t pixel_clock); + +/* enables DP PHY output */ +void dcn10_link_encoder_enable_dp_output( + struct link_encoder *enc, + const struct dc_link_settings *link_settings, + enum clock_source_id clock_source); + +/* enables DP PHY output in MST mode */ +void dcn10_link_encoder_enable_dp_mst_output( + struct link_encoder *enc, + const struct dc_link_settings *link_settings, + enum clock_source_id clock_source); + +/* disable PHY output */ +void dcn10_link_encoder_disable_output( + struct link_encoder *enc, + enum signal_type signal); + +/* set DP lane settings */ +void dcn10_link_encoder_dp_set_lane_settings( + struct link_encoder *enc, + const struct dc_link_settings *link_settings, + const struct dc_lane_settings lane_settings[LANE_COUNT_DP_MAX]); + +void dcn10_link_encoder_dp_set_phy_pattern( + struct link_encoder *enc, + const struct encoder_set_dp_phy_pattern_param *param); + +/* programs DP MST VC payload allocation */ +void dcn10_link_encoder_update_mst_stream_allocation_table( + struct link_encoder *enc, + const struct link_mst_stream_allocation_table *table); + +void dcn10_link_encoder_connect_dig_be_to_fe( + struct link_encoder *enc, + enum engine_id engine, + bool connect); + +void dcn10_link_encoder_set_dp_phy_pattern_training_pattern( + struct link_encoder *enc, + uint32_t index); + +void dcn10_link_encoder_enable_hpd(struct link_encoder *enc); + +void dcn10_link_encoder_disable_hpd(struct link_encoder *enc); + +void dcn10_psr_program_dp_dphy_fast_training(struct link_encoder *enc, + bool exit_link_training_required); + +void dcn10_psr_program_secondary_packet(struct link_encoder *enc, + unsigned int sdp_transmit_line_num_deadline); + +bool dcn10_is_dig_enabled(struct link_encoder *enc); + +unsigned int dcn10_get_dig_frontend(struct link_encoder *enc); + +void dcn10_aux_initialize(struct dcn10_link_encoder *enc10); + +enum signal_type dcn10_get_dig_mode( + struct link_encoder *enc); + +void dcn10_link_encoder_get_max_link_cap(struct link_encoder *enc, + struct dc_link_settings *link_settings); +#endif /* __DC_LINK_ENCODER__DCN10_H__ */ diff --git a/drivers/gpu/drm/amd/display/dc/dio/dcn10/dcn10_stream_encoder.c b/drivers/gpu/drm/amd/display/dc/dio/dcn10/dcn10_stream_encoder.c new file mode 100644 index 000000000000..f496e952ceec --- /dev/null +++ b/drivers/gpu/drm/amd/display/dc/dio/dcn10/dcn10_stream_encoder.c @@ -0,0 +1,1628 @@ +/* + * Copyright 2012-15 Advanced Micro Devices, Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + * + * Authors: AMD + * + */ + +#include "dm_services.h" +#include "dc_bios_types.h" +#include "dcn10_stream_encoder.h" +#include "reg_helper.h" +#include "hw_shared.h" +#include "link.h" +#include "dpcd_defs.h" +#include "dcn30/dcn30_afmt.h" + +#define DC_LOGGER \ + enc1->base.ctx->logger + +#define REG(reg)\ + (enc1->regs->reg) + +#undef FN +#define FN(reg_name, field_name) \ + enc1->se_shift->field_name, enc1->se_mask->field_name + +#define VBI_LINE_0 0 +#define DP_BLANK_MAX_RETRY 20 +#define HDMI_CLOCK_CHANNEL_RATE_MORE_340M 340000 + + +enum { + DP_MST_UPDATE_MAX_RETRY = 50 +}; + +#define CTX \ + enc1->base.ctx + +void enc1_update_generic_info_packet( + struct dcn10_stream_encoder *enc1, + uint32_t packet_index, + const struct dc_info_packet *info_packet) +{ + /* TODOFPGA Figure out a proper number for max_retries polling for lock + * use 50 for now. + */ + uint32_t max_retries = 50; + + /*we need turn on clock before programming AFMT block*/ + REG_UPDATE(AFMT_CNTL, AFMT_AUDIO_CLOCK_EN, 1); + + if (packet_index >= 8) + ASSERT(0); + + /* poll dig_update_lock is not locked -> asic internal signal + * assume otg master lock will unlock it + */ +/* REG_WAIT(AFMT_VBI_PACKET_CONTROL, AFMT_GENERIC_LOCK_STATUS, + 0, 10, max_retries);*/ + + /* check if HW reading GSP memory */ + REG_WAIT(AFMT_VBI_PACKET_CONTROL, AFMT_GENERIC_CONFLICT, + 0, 10, max_retries); + + /* HW does is not reading GSP memory not reading too long -> + * something wrong. clear GPS memory access and notify? + * hw SW is writing to GSP memory + */ + REG_UPDATE(AFMT_VBI_PACKET_CONTROL, AFMT_GENERIC_CONFLICT_CLR, 1); + + /* choose which generic packet to use */ + REG_UPDATE(AFMT_VBI_PACKET_CONTROL, + AFMT_GENERIC_INDEX, packet_index); + + /* write generic packet header + * (4th byte is for GENERIC0 only) + */ + REG_SET_4(AFMT_GENERIC_HDR, 0, + AFMT_GENERIC_HB0, info_packet->hb0, + AFMT_GENERIC_HB1, info_packet->hb1, + AFMT_GENERIC_HB2, info_packet->hb2, + AFMT_GENERIC_HB3, info_packet->hb3); + + /* write generic packet contents + * (we never use last 4 bytes) + * there are 8 (0-7) mmDIG0_AFMT_GENERIC0_x registers + */ + { + const uint32_t *content = + (const uint32_t *) &info_packet->sb[0]; + + REG_WRITE(AFMT_GENERIC_0, *content++); + REG_WRITE(AFMT_GENERIC_1, *content++); + REG_WRITE(AFMT_GENERIC_2, *content++); + REG_WRITE(AFMT_GENERIC_3, *content++); + REG_WRITE(AFMT_GENERIC_4, *content++); + REG_WRITE(AFMT_GENERIC_5, *content++); + REG_WRITE(AFMT_GENERIC_6, *content++); + REG_WRITE(AFMT_GENERIC_7, *content); + } + + switch (packet_index) { + case 0: + REG_UPDATE(AFMT_VBI_PACKET_CONTROL1, + AFMT_GENERIC0_IMMEDIATE_UPDATE, 1); + break; + case 1: + REG_UPDATE(AFMT_VBI_PACKET_CONTROL1, + AFMT_GENERIC1_IMMEDIATE_UPDATE, 1); + break; + case 2: + REG_UPDATE(AFMT_VBI_PACKET_CONTROL1, + AFMT_GENERIC2_IMMEDIATE_UPDATE, 1); + break; + case 3: + REG_UPDATE(AFMT_VBI_PACKET_CONTROL1, + AFMT_GENERIC3_IMMEDIATE_UPDATE, 1); + break; + case 4: + REG_UPDATE(AFMT_VBI_PACKET_CONTROL1, + AFMT_GENERIC4_IMMEDIATE_UPDATE, 1); + break; + case 5: + REG_UPDATE(AFMT_VBI_PACKET_CONTROL1, + AFMT_GENERIC5_IMMEDIATE_UPDATE, 1); + break; + case 6: + REG_UPDATE(AFMT_VBI_PACKET_CONTROL1, + AFMT_GENERIC6_IMMEDIATE_UPDATE, 1); + break; + case 7: + REG_UPDATE(AFMT_VBI_PACKET_CONTROL1, + AFMT_GENERIC7_IMMEDIATE_UPDATE, 1); + break; + default: + break; + } +} + +static void enc1_update_hdmi_info_packet( + struct dcn10_stream_encoder *enc1, + uint32_t packet_index, + const struct dc_info_packet *info_packet) +{ + uint32_t cont, send, line; + + if (info_packet->valid) { + enc1_update_generic_info_packet( + enc1, + packet_index, + info_packet); + + /* enable transmission of packet(s) - + * packet transmission begins on the next frame + */ + cont = 1; + /* send packet(s) every frame */ + send = 1; + /* select line number to send packets on */ + line = 2; + } else { + cont = 0; + send = 0; + line = 0; + } + + /* choose which generic packet control to use */ + switch (packet_index) { + case 0: + REG_UPDATE_3(HDMI_GENERIC_PACKET_CONTROL0, + HDMI_GENERIC0_CONT, cont, + HDMI_GENERIC0_SEND, send, + HDMI_GENERIC0_LINE, line); + break; + case 1: + REG_UPDATE_3(HDMI_GENERIC_PACKET_CONTROL0, + HDMI_GENERIC1_CONT, cont, + HDMI_GENERIC1_SEND, send, + HDMI_GENERIC1_LINE, line); + break; + case 2: + REG_UPDATE_3(HDMI_GENERIC_PACKET_CONTROL1, + HDMI_GENERIC0_CONT, cont, + HDMI_GENERIC0_SEND, send, + HDMI_GENERIC0_LINE, line); + break; + case 3: + REG_UPDATE_3(HDMI_GENERIC_PACKET_CONTROL1, + HDMI_GENERIC1_CONT, cont, + HDMI_GENERIC1_SEND, send, + HDMI_GENERIC1_LINE, line); + break; + case 4: + REG_UPDATE_3(HDMI_GENERIC_PACKET_CONTROL2, + HDMI_GENERIC0_CONT, cont, + HDMI_GENERIC0_SEND, send, + HDMI_GENERIC0_LINE, line); + break; + case 5: + REG_UPDATE_3(HDMI_GENERIC_PACKET_CONTROL2, + HDMI_GENERIC1_CONT, cont, + HDMI_GENERIC1_SEND, send, + HDMI_GENERIC1_LINE, line); + break; + case 6: + REG_UPDATE_3(HDMI_GENERIC_PACKET_CONTROL3, + HDMI_GENERIC0_CONT, cont, + HDMI_GENERIC0_SEND, send, + HDMI_GENERIC0_LINE, line); + break; + case 7: + REG_UPDATE_3(HDMI_GENERIC_PACKET_CONTROL3, + HDMI_GENERIC1_CONT, cont, + HDMI_GENERIC1_SEND, send, + HDMI_GENERIC1_LINE, line); + break; + default: + /* invalid HW packet index */ + DC_LOG_WARNING( + "Invalid HW packet index: %s()\n", + __func__); + return; + } +} + +/* setup stream encoder in dp mode */ +void enc1_stream_encoder_dp_set_stream_attribute( + struct stream_encoder *enc, + struct dc_crtc_timing *crtc_timing, + enum dc_color_space output_color_space, + bool use_vsc_sdp_for_colorimetry, + uint32_t enable_sdp_splitting) +{ + uint32_t h_active_start; + uint32_t v_active_start; + uint32_t misc0 = 0; + uint32_t misc1 = 0; + uint32_t h_blank; + uint32_t h_back_porch; + uint8_t synchronous_clock = 0; /* asynchronous mode */ + uint8_t colorimetry_bpc; + uint8_t dp_pixel_encoding = 0; + uint8_t dp_component_depth = 0; + + struct dcn10_stream_encoder *enc1 = DCN10STRENC_FROM_STRENC(enc); + struct dc_crtc_timing hw_crtc_timing = *crtc_timing; + + if (hw_crtc_timing.flags.INTERLACE) { + /*the input timing is in VESA spec format with Interlace flag =1*/ + hw_crtc_timing.v_total /= 2; + hw_crtc_timing.v_border_top /= 2; + hw_crtc_timing.v_addressable /= 2; + hw_crtc_timing.v_border_bottom /= 2; + hw_crtc_timing.v_front_porch /= 2; + hw_crtc_timing.v_sync_width /= 2; + } + + + /* set pixel encoding */ + switch (hw_crtc_timing.pixel_encoding) { + case PIXEL_ENCODING_YCBCR422: + dp_pixel_encoding = DP_PIXEL_ENCODING_TYPE_YCBCR422; + break; + case PIXEL_ENCODING_YCBCR444: + dp_pixel_encoding = DP_PIXEL_ENCODING_TYPE_YCBCR444; + + if (hw_crtc_timing.flags.Y_ONLY) + if (hw_crtc_timing.display_color_depth != COLOR_DEPTH_666) + /* HW testing only, no use case yet. + * Color depth of Y-only could be + * 8, 10, 12, 16 bits + */ + 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 + * DP_PIXEL_ENCODING is programmed to 0x4 + */ + break; + case PIXEL_ENCODING_YCBCR420: + dp_pixel_encoding = DP_PIXEL_ENCODING_TYPE_YCBCR420; + break; + default: + 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 (use_vsc_sdp_for_colorimetry) + misc1 = misc1 | 0x40; + else + misc1 = misc1 & ~0x40; + + /* set color depth */ + switch (hw_crtc_timing.display_color_depth) { + case COLOR_DEPTH_666: + dp_component_depth = DP_COMPONENT_PIXEL_DEPTH_6BPC; + break; + case COLOR_DEPTH_888: + dp_component_depth = DP_COMPONENT_PIXEL_DEPTH_8BPC; + break; + case COLOR_DEPTH_101010: + dp_component_depth = DP_COMPONENT_PIXEL_DEPTH_10BPC; + break; + case COLOR_DEPTH_121212: + dp_component_depth = DP_COMPONENT_PIXEL_DEPTH_12BPC; + break; + case COLOR_DEPTH_161616: + dp_component_depth = DP_COMPONENT_PIXEL_DEPTH_16BPC; + break; + default: + 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 (hw_crtc_timing.display_color_depth) { + case COLOR_DEPTH_666: + colorimetry_bpc = 0; + break; + case COLOR_DEPTH_888: + colorimetry_bpc = 1; + break; + case COLOR_DEPTH_101010: + colorimetry_bpc = 2; + break; + case COLOR_DEPTH_121212: + colorimetry_bpc = 3; + break; + default: + colorimetry_bpc = 0; + break; + } + + misc0 = misc0 | synchronous_clock; + misc0 = colorimetry_bpc << 5; + + switch (output_color_space) { + case COLOR_SPACE_SRGB: + misc1 = misc1 & ~0x80; /* bit7 = 0*/ + break; + case COLOR_SPACE_SRGB_LIMITED: + misc0 = misc0 | 0x8; /* bit3=1 */ + misc1 = misc1 & ~0x80; /* bit7 = 0*/ + break; + case COLOR_SPACE_YCBCR601: + case COLOR_SPACE_YCBCR601_LIMITED: + misc0 = misc0 | 0x8; /* bit3=1, bit4=0 */ + misc1 = misc1 & ~0x80; /* bit7 = 0*/ + if (hw_crtc_timing.pixel_encoding == PIXEL_ENCODING_YCBCR422) + misc0 = misc0 | 0x2; /* bit2=0, bit1=1 */ + else if (hw_crtc_timing.pixel_encoding == PIXEL_ENCODING_YCBCR444) + misc0 = misc0 | 0x4; /* bit2=1, bit1=0 */ + break; + case COLOR_SPACE_YCBCR709: + case COLOR_SPACE_YCBCR709_LIMITED: + misc0 = misc0 | 0x18; /* bit3=1, bit4=1 */ + misc1 = misc1 & ~0x80; /* bit7 = 0*/ + if (hw_crtc_timing.pixel_encoding == PIXEL_ENCODING_YCBCR422) + misc0 = misc0 | 0x2; /* bit2=0, bit1=1 */ + else if (hw_crtc_timing.pixel_encoding == PIXEL_ENCODING_YCBCR444) + misc0 = misc0 | 0x4; /* bit2=1, bit1=0 */ + break; + case COLOR_SPACE_2020_RGB_LIMITEDRANGE: + case COLOR_SPACE_2020_RGB_FULLRANGE: + case COLOR_SPACE_2020_YCBCR: + case COLOR_SPACE_XR_RGB: + case COLOR_SPACE_MSREF_SCRGB: + case COLOR_SPACE_ADOBERGB: + case COLOR_SPACE_DCIP3: + case COLOR_SPACE_XV_YCC_709: + case COLOR_SPACE_XV_YCC_601: + case COLOR_SPACE_DISPLAYNATIVE: + case COLOR_SPACE_DOLBYVISION: + case COLOR_SPACE_APPCTRL: + case COLOR_SPACE_CUSTOMPOINTS: + case COLOR_SPACE_UNKNOWN: + case COLOR_SPACE_YCBCR709_BLACK: + /* do nothing */ + break; + } + + REG_SET(DP_MSA_COLORIMETRY, 0, DP_MSA_MISC0, misc0); + REG_WRITE(DP_MSA_MISC, misc1); /* MSA_MISC1 */ + + /* dcn new register + * dc_crtc_timing is vesa dmt struct. data from edid + */ + REG_SET_2(DP_MSA_TIMING_PARAM1, 0, + DP_MSA_HTOTAL, hw_crtc_timing.h_total, + DP_MSA_VTOTAL, hw_crtc_timing.v_total); + + /* calculate from vesa timing parameters + * h_active_start related to leading edge of sync + */ + + h_blank = hw_crtc_timing.h_total - hw_crtc_timing.h_border_left - + hw_crtc_timing.h_addressable - hw_crtc_timing.h_border_right; + + h_back_porch = h_blank - hw_crtc_timing.h_front_porch - + hw_crtc_timing.h_sync_width; + + /* start at beginning of left border */ + h_active_start = hw_crtc_timing.h_sync_width + h_back_porch; + + + v_active_start = hw_crtc_timing.v_total - hw_crtc_timing.v_border_top - + hw_crtc_timing.v_addressable - hw_crtc_timing.v_border_bottom - + hw_crtc_timing.v_front_porch; + + + /* start at beginning of left border */ + REG_SET_2(DP_MSA_TIMING_PARAM2, 0, + DP_MSA_HSTART, h_active_start, + DP_MSA_VSTART, v_active_start); + + REG_SET_4(DP_MSA_TIMING_PARAM3, 0, + DP_MSA_HSYNCWIDTH, + hw_crtc_timing.h_sync_width, + DP_MSA_HSYNCPOLARITY, + !hw_crtc_timing.flags.HSYNC_POSITIVE_POLARITY, + DP_MSA_VSYNCWIDTH, + hw_crtc_timing.v_sync_width, + DP_MSA_VSYNCPOLARITY, + !hw_crtc_timing.flags.VSYNC_POSITIVE_POLARITY); + + /* HWDITH include border or overscan */ + REG_SET_2(DP_MSA_TIMING_PARAM4, 0, + DP_MSA_HWIDTH, hw_crtc_timing.h_border_left + + hw_crtc_timing.h_addressable + hw_crtc_timing.h_border_right, + DP_MSA_VHEIGHT, hw_crtc_timing.v_border_top + + hw_crtc_timing.v_addressable + hw_crtc_timing.v_border_bottom); +} + +void enc1_stream_encoder_set_stream_attribute_helper( + struct dcn10_stream_encoder *enc1, + struct dc_crtc_timing *crtc_timing) +{ + switch (crtc_timing->pixel_encoding) { + case PIXEL_ENCODING_YCBCR422: + REG_UPDATE(DIG_FE_CNTL, TMDS_PIXEL_ENCODING, 1); + break; + default: + REG_UPDATE(DIG_FE_CNTL, TMDS_PIXEL_ENCODING, 0); + break; + } + REG_UPDATE(DIG_FE_CNTL, TMDS_COLOR_FORMAT, 0); +} + +/* setup stream encoder in hdmi mode */ +void enc1_stream_encoder_hdmi_set_stream_attribute( + struct stream_encoder *enc, + struct dc_crtc_timing *crtc_timing, + int actual_pix_clk_khz, + bool enable_audio) +{ + struct dcn10_stream_encoder *enc1 = DCN10STRENC_FROM_STRENC(enc); + struct bp_encoder_control cntl = {0}; + + cntl.action = ENCODER_CONTROL_SETUP; + cntl.engine_id = enc1->base.id; + cntl.signal = SIGNAL_TYPE_HDMI_TYPE_A; + cntl.enable_dp_audio = enable_audio; + cntl.pixel_clock = actual_pix_clk_khz; + cntl.lanes_number = LANE_COUNT_FOUR; + + if (enc1->base.bp->funcs->encoder_control( + enc1->base.bp, &cntl) != BP_RESULT_OK) + return; + + enc1_stream_encoder_set_stream_attribute_helper(enc1, crtc_timing); + + /* setup HDMI engine */ + REG_UPDATE_6(HDMI_CONTROL, + HDMI_PACKET_GEN_VERSION, 1, + HDMI_KEEPOUT_MODE, 1, + HDMI_DEEP_COLOR_ENABLE, 0, + HDMI_DATA_SCRAMBLE_EN, 0, + HDMI_NO_EXTRA_NULL_PACKET_FILLED, 1, + HDMI_CLOCK_CHANNEL_RATE, 0); + + + switch (crtc_timing->display_color_depth) { + case COLOR_DEPTH_888: + REG_UPDATE(HDMI_CONTROL, HDMI_DEEP_COLOR_DEPTH, 0); + DC_LOG_DEBUG("HDMI source set to 24BPP deep color depth\n"); + break; + case COLOR_DEPTH_101010: + if (crtc_timing->pixel_encoding == PIXEL_ENCODING_YCBCR422) { + REG_UPDATE_2(HDMI_CONTROL, + HDMI_DEEP_COLOR_DEPTH, 1, + HDMI_DEEP_COLOR_ENABLE, 0); + DC_LOG_DEBUG("HDMI source 30BPP deep color depth" \ + "disabled for YCBCR422 pixel encoding\n"); + } else { + REG_UPDATE_2(HDMI_CONTROL, + HDMI_DEEP_COLOR_DEPTH, 1, + HDMI_DEEP_COLOR_ENABLE, 1); + DC_LOG_DEBUG("HDMI source 30BPP deep color depth" \ + "enabled for YCBCR422 non-pixel encoding\n"); + } + break; + case COLOR_DEPTH_121212: + if (crtc_timing->pixel_encoding == PIXEL_ENCODING_YCBCR422) { + REG_UPDATE_2(HDMI_CONTROL, + HDMI_DEEP_COLOR_DEPTH, 2, + HDMI_DEEP_COLOR_ENABLE, 0); + DC_LOG_DEBUG("HDMI source 36BPP deep color depth" \ + "disabled for YCBCR422 pixel encoding\n"); + } else { + REG_UPDATE_2(HDMI_CONTROL, + HDMI_DEEP_COLOR_DEPTH, 2, + HDMI_DEEP_COLOR_ENABLE, 1); + DC_LOG_DEBUG("HDMI source 36BPP deep color depth" \ + "enabled for non-pixel YCBCR422 encoding\n"); + } + break; + case COLOR_DEPTH_161616: + REG_UPDATE_2(HDMI_CONTROL, + HDMI_DEEP_COLOR_DEPTH, 3, + HDMI_DEEP_COLOR_ENABLE, 1); + DC_LOG_DEBUG("HDMI source deep color depth enabled in" \ + "reserved mode\n"); + break; + default: + break; + } + + if (actual_pix_clk_khz >= HDMI_CLOCK_CHANNEL_RATE_MORE_340M) { + /* enable HDMI data scrambler + * HDMI_CLOCK_CHANNEL_RATE_MORE_340M + * Clock channel frequency is 1/4 of character rate. + */ + REG_UPDATE_2(HDMI_CONTROL, + HDMI_DATA_SCRAMBLE_EN, 1, + HDMI_CLOCK_CHANNEL_RATE, 1); + } else if (crtc_timing->flags.LTE_340MCSC_SCRAMBLE) { + + /* TODO: New feature for DCE11, still need to implement */ + + /* enable HDMI data scrambler + * HDMI_CLOCK_CHANNEL_FREQ_EQUAL_TO_CHAR_RATE + * Clock channel frequency is the same + * as character rate + */ + REG_UPDATE_2(HDMI_CONTROL, + HDMI_DATA_SCRAMBLE_EN, 1, + HDMI_CLOCK_CHANNEL_RATE, 0); + } + + + REG_UPDATE_3(HDMI_VBI_PACKET_CONTROL, + HDMI_GC_CONT, 1, + HDMI_GC_SEND, 1, + HDMI_NULL_SEND, 1); + + REG_UPDATE(HDMI_VBI_PACKET_CONTROL, HDMI_ACP_SEND, 0); + + /* following belongs to audio */ + REG_UPDATE(HDMI_INFOFRAME_CONTROL0, HDMI_AUDIO_INFO_SEND, 1); + + REG_UPDATE(AFMT_INFOFRAME_CONTROL0, AFMT_AUDIO_INFO_UPDATE, 1); + + REG_UPDATE(HDMI_INFOFRAME_CONTROL1, HDMI_AUDIO_INFO_LINE, + VBI_LINE_0 + 2); + + REG_UPDATE(HDMI_GC, HDMI_GC_AVMUTE, 0); +} + +/* setup stream encoder in dvi mode */ +void enc1_stream_encoder_dvi_set_stream_attribute( + struct stream_encoder *enc, + struct dc_crtc_timing *crtc_timing, + bool is_dual_link) +{ + struct dcn10_stream_encoder *enc1 = DCN10STRENC_FROM_STRENC(enc); + struct bp_encoder_control cntl = {0}; + + cntl.action = ENCODER_CONTROL_SETUP; + cntl.engine_id = enc1->base.id; + cntl.signal = is_dual_link ? + SIGNAL_TYPE_DVI_DUAL_LINK : SIGNAL_TYPE_DVI_SINGLE_LINK; + cntl.enable_dp_audio = false; + cntl.pixel_clock = crtc_timing->pix_clk_100hz / 10; + cntl.lanes_number = (is_dual_link) ? LANE_COUNT_EIGHT : LANE_COUNT_FOUR; + + if (enc1->base.bp->funcs->encoder_control( + enc1->base.bp, &cntl) != BP_RESULT_OK) + return; + + ASSERT(crtc_timing->pixel_encoding == PIXEL_ENCODING_RGB); + ASSERT(crtc_timing->display_color_depth == COLOR_DEPTH_888); + enc1_stream_encoder_set_stream_attribute_helper(enc1, crtc_timing); +} + +void enc1_stream_encoder_set_throttled_vcp_size( + struct stream_encoder *enc, + struct fixed31_32 avg_time_slots_per_mtp) +{ + struct dcn10_stream_encoder *enc1 = DCN10STRENC_FROM_STRENC(enc); + uint32_t x = dc_fixpt_floor( + avg_time_slots_per_mtp); + uint32_t y = dc_fixpt_ceil( + dc_fixpt_shl( + dc_fixpt_sub_int( + avg_time_slots_per_mtp, + x), + 26)); + + // If y rounds up to integer, carry it over to x. + if (y >> 26) { + x += 1; + y = 0; + } + + REG_SET_2(DP_MSE_RATE_CNTL, 0, + DP_MSE_RATE_X, x, + DP_MSE_RATE_Y, y); + + /* wait for update to be completed on the link */ + /* i.e. DP_MSE_RATE_UPDATE_PENDING field (read only) */ + /* is reset to 0 (not pending) */ + REG_WAIT(DP_MSE_RATE_UPDATE, DP_MSE_RATE_UPDATE_PENDING, + 0, + 10, DP_MST_UPDATE_MAX_RETRY); +} + +static void enc1_stream_encoder_update_hdmi_info_packets( + struct stream_encoder *enc, + const struct encoder_info_frame *info_frame) +{ + struct dcn10_stream_encoder *enc1 = DCN10STRENC_FROM_STRENC(enc); + + /* for bring up, disable dp double TODO */ + REG_UPDATE(HDMI_DB_CONTROL, HDMI_DB_DISABLE, 1); + + /*Always add mandatory packets first followed by optional ones*/ + enc1_update_hdmi_info_packet(enc1, 0, &info_frame->avi); + enc1_update_hdmi_info_packet(enc1, 1, &info_frame->hfvsif); + enc1_update_hdmi_info_packet(enc1, 2, &info_frame->gamut); + enc1_update_hdmi_info_packet(enc1, 3, &info_frame->vendor); + enc1_update_hdmi_info_packet(enc1, 4, &info_frame->spd); + enc1_update_hdmi_info_packet(enc1, 5, &info_frame->hdrsmd); +} + +static void enc1_stream_encoder_stop_hdmi_info_packets( + struct stream_encoder *enc) +{ + struct dcn10_stream_encoder *enc1 = DCN10STRENC_FROM_STRENC(enc); + + /* stop generic packets 0 & 1 on HDMI */ + REG_SET_6(HDMI_GENERIC_PACKET_CONTROL0, 0, + HDMI_GENERIC1_CONT, 0, + HDMI_GENERIC1_LINE, 0, + HDMI_GENERIC1_SEND, 0, + HDMI_GENERIC0_CONT, 0, + HDMI_GENERIC0_LINE, 0, + HDMI_GENERIC0_SEND, 0); + + /* stop generic packets 2 & 3 on HDMI */ + REG_SET_6(HDMI_GENERIC_PACKET_CONTROL1, 0, + HDMI_GENERIC0_CONT, 0, + HDMI_GENERIC0_LINE, 0, + HDMI_GENERIC0_SEND, 0, + HDMI_GENERIC1_CONT, 0, + HDMI_GENERIC1_LINE, 0, + HDMI_GENERIC1_SEND, 0); + + /* stop generic packets 2 & 3 on HDMI */ + REG_SET_6(HDMI_GENERIC_PACKET_CONTROL2, 0, + HDMI_GENERIC0_CONT, 0, + HDMI_GENERIC0_LINE, 0, + HDMI_GENERIC0_SEND, 0, + HDMI_GENERIC1_CONT, 0, + HDMI_GENERIC1_LINE, 0, + HDMI_GENERIC1_SEND, 0); + + REG_SET_6(HDMI_GENERIC_PACKET_CONTROL3, 0, + HDMI_GENERIC0_CONT, 0, + HDMI_GENERIC0_LINE, 0, + HDMI_GENERIC0_SEND, 0, + HDMI_GENERIC1_CONT, 0, + HDMI_GENERIC1_LINE, 0, + HDMI_GENERIC1_SEND, 0); +} + +void enc1_stream_encoder_update_dp_info_packets( + struct stream_encoder *enc, + const struct encoder_info_frame *info_frame) +{ + struct dcn10_stream_encoder *enc1 = DCN10STRENC_FROM_STRENC(enc); + uint32_t value = 0; + + if (info_frame->vsc.valid) + enc1_update_generic_info_packet( + enc1, + 0, /* packetIndex */ + &info_frame->vsc); + + /* VSC SDP at packetIndex 1 is used by PSR in DMCUB FW. + * Note that the enablement of GSP1 is not done below, + * it's done in FW. + */ + if (info_frame->vsc.valid) + enc1_update_generic_info_packet( + enc1, + 1, /* packetIndex */ + &info_frame->vsc); + + if (info_frame->spd.valid) + enc1_update_generic_info_packet( + enc1, + 2, /* packetIndex */ + &info_frame->spd); + + if (info_frame->hdrsmd.valid) + enc1_update_generic_info_packet( + enc1, + 3, /* packetIndex */ + &info_frame->hdrsmd); + + /* packetIndex 4 is used for send immediate sdp message, and please + * use other packetIndex (such as 5,6) for other info packet + */ + + if (info_frame->adaptive_sync.valid) + enc1_update_generic_info_packet( + enc1, + 5, /* packetIndex */ + &info_frame->adaptive_sync); + + /* enable/disable transmission of packet(s). + * If enabled, packet transmission begins on the next frame + */ + REG_UPDATE(DP_SEC_CNTL, DP_SEC_GSP0_ENABLE, info_frame->vsc.valid); + REG_UPDATE(DP_SEC_CNTL, DP_SEC_GSP2_ENABLE, info_frame->spd.valid); + REG_UPDATE(DP_SEC_CNTL, DP_SEC_GSP3_ENABLE, info_frame->hdrsmd.valid); + REG_UPDATE(DP_SEC_CNTL, DP_SEC_GSP5_ENABLE, info_frame->adaptive_sync.valid); + + /* This bit is the master enable bit. + * When enabling secondary stream engine, + * this master bit must also be set. + * This register shared with audio info frame. + * Therefore we need to enable master bit + * if at least on of the fields is not 0 + */ + value = REG_READ(DP_SEC_CNTL); + if (value) + REG_UPDATE(DP_SEC_CNTL, DP_SEC_STREAM_ENABLE, 1); +} + +void enc1_stream_encoder_send_immediate_sdp_message( + struct stream_encoder *enc, + const uint8_t *custom_sdp_message, + unsigned int sdp_message_size) +{ + struct dcn10_stream_encoder *enc1 = DCN10STRENC_FROM_STRENC(enc); + uint32_t value = 0; + + /* TODOFPGA Figure out a proper number for max_retries polling for lock + * use 50 for now. + */ + uint32_t max_retries = 50; + + /* check if GSP4 is transmitted */ + REG_WAIT(DP_SEC_CNTL2, DP_SEC_GSP4_SEND_PENDING, + 0, 10, max_retries); + + /* disable GSP4 transmitting */ + REG_UPDATE(DP_SEC_CNTL2, DP_SEC_GSP4_SEND, 0); + + /* transmit GSP4 at the earliest time in a frame */ + REG_UPDATE(DP_SEC_CNTL2, DP_SEC_GSP4_SEND_ANY_LINE, 1); + + /*we need turn on clock before programming AFMT block*/ + REG_UPDATE(AFMT_CNTL, AFMT_AUDIO_CLOCK_EN, 1); + + /* check if HW reading GSP memory */ + REG_WAIT(AFMT_VBI_PACKET_CONTROL, AFMT_GENERIC_CONFLICT, + 0, 10, max_retries); + + /* HW does is not reading GSP memory not reading too long -> + * something wrong. clear GPS memory access and notify? + * hw SW is writing to GSP memory + */ + REG_UPDATE(AFMT_VBI_PACKET_CONTROL, AFMT_GENERIC_CONFLICT_CLR, 1); + + /* use generic packet 4 for immediate sdp message */ + REG_UPDATE(AFMT_VBI_PACKET_CONTROL, + AFMT_GENERIC_INDEX, 4); + + /* write generic packet header + * (4th byte is for GENERIC0 only) + */ + REG_SET_4(AFMT_GENERIC_HDR, 0, + AFMT_GENERIC_HB0, custom_sdp_message[0], + AFMT_GENERIC_HB1, custom_sdp_message[1], + AFMT_GENERIC_HB2, custom_sdp_message[2], + AFMT_GENERIC_HB3, custom_sdp_message[3]); + + /* write generic packet contents + * (we never use last 4 bytes) + * there are 8 (0-7) mmDIG0_AFMT_GENERIC0_x registers + */ + { + const uint32_t *content = + (const uint32_t *) &custom_sdp_message[4]; + + REG_WRITE(AFMT_GENERIC_0, *content++); + REG_WRITE(AFMT_GENERIC_1, *content++); + REG_WRITE(AFMT_GENERIC_2, *content++); + REG_WRITE(AFMT_GENERIC_3, *content++); + REG_WRITE(AFMT_GENERIC_4, *content++); + REG_WRITE(AFMT_GENERIC_5, *content++); + REG_WRITE(AFMT_GENERIC_6, *content++); + REG_WRITE(AFMT_GENERIC_7, *content); + } + + /* check whether GENERIC4 registers double buffer update in immediate mode + * is pending + */ + REG_WAIT(AFMT_VBI_PACKET_CONTROL1, AFMT_GENERIC4_IMMEDIATE_UPDATE_PENDING, + 0, 10, max_retries); + + /* atomically update double-buffered GENERIC4 registers in immediate mode + * (update immediately) + */ + REG_UPDATE(AFMT_VBI_PACKET_CONTROL1, + AFMT_GENERIC4_IMMEDIATE_UPDATE, 1); + + /* enable GSP4 transmitting */ + REG_UPDATE(DP_SEC_CNTL2, DP_SEC_GSP4_SEND, 1); + + /* This bit is the master enable bit. + * When enabling secondary stream engine, + * this master bit must also be set. + * This register shared with audio info frame. + * Therefore we need to enable master bit + * if at least on of the fields is not 0 + */ + value = REG_READ(DP_SEC_CNTL); + if (value) + REG_UPDATE(DP_SEC_CNTL, DP_SEC_STREAM_ENABLE, 1); +} + +void enc1_stream_encoder_stop_dp_info_packets( + struct stream_encoder *enc) +{ + /* stop generic packets on DP */ + struct dcn10_stream_encoder *enc1 = DCN10STRENC_FROM_STRENC(enc); + uint32_t value = 0; + + REG_SET_10(DP_SEC_CNTL, 0, + DP_SEC_GSP0_ENABLE, 0, + DP_SEC_GSP1_ENABLE, 0, + DP_SEC_GSP2_ENABLE, 0, + DP_SEC_GSP3_ENABLE, 0, + DP_SEC_GSP4_ENABLE, 0, + DP_SEC_GSP5_ENABLE, 0, + DP_SEC_GSP6_ENABLE, 0, + DP_SEC_GSP7_ENABLE, 0, + DP_SEC_MPG_ENABLE, 0, + DP_SEC_STREAM_ENABLE, 0); + + /* this register shared with audio info frame. + * therefore we need to keep master enabled + * if at least one of the fields is not 0 */ + value = REG_READ(DP_SEC_CNTL); + if (value) + REG_UPDATE(DP_SEC_CNTL, DP_SEC_STREAM_ENABLE, 1); + +} + +void enc1_stream_encoder_dp_blank( + struct dc_link *link, + struct stream_encoder *enc) +{ + struct dcn10_stream_encoder *enc1 = DCN10STRENC_FROM_STRENC(enc); + uint32_t reg1 = 0; + uint32_t max_retries = DP_BLANK_MAX_RETRY * 10; + + /* Note: For CZ, we are changing driver default to disable + * stream deferred to next VBLANK. If results are positive, we + * will make the same change to all DCE versions. There are a + * handful of panels that cannot handle disable stream at + * HBLANK and will result in a white line flash across the + * screen on stream disable. + */ + REG_GET(DP_VID_STREAM_CNTL, DP_VID_STREAM_ENABLE, ®1); + if ((reg1 & 0x1) == 0) + /*stream not enabled*/ + return; + /* Specify the video stream disable point + * (2 = start of the next vertical blank) + */ + REG_UPDATE(DP_VID_STREAM_CNTL, DP_VID_STREAM_DIS_DEFER, 2); + /* Larger delay to wait until VBLANK - use max retry of + * 10us*10200=102ms. This covers 100.0ms of minimum 10 Hz mode + + * a little more because we may not trust delay accuracy. + */ + max_retries = DP_BLANK_MAX_RETRY * 501; + + /* disable DP stream */ + REG_UPDATE(DP_VID_STREAM_CNTL, DP_VID_STREAM_ENABLE, 0); + + link->dc->link_srv->dp_trace_source_sequence(link, DPCD_SOURCE_SEQ_AFTER_DISABLE_DP_VID_STREAM); + + /* the encoder stops sending the video stream + * at the start of the vertical blanking. + * Poll for DP_VID_STREAM_STATUS == 0 + */ + + REG_WAIT(DP_VID_STREAM_CNTL, DP_VID_STREAM_STATUS, + 0, + 10, max_retries); + + /* Tell the DP encoder to ignore timing from CRTC, must be done after + * the polling. If we set DP_STEER_FIFO_RESET before DP stream blank is + * complete, stream status will be stuck in video stream enabled state, + * i.e. DP_VID_STREAM_STATUS stuck at 1. + */ + + REG_UPDATE(DP_STEER_FIFO, DP_STEER_FIFO_RESET, true); + + link->dc->link_srv->dp_trace_source_sequence(link, DPCD_SOURCE_SEQ_AFTER_FIFO_STEER_RESET); +} + +/* output video stream to link encoder */ +void enc1_stream_encoder_dp_unblank( + struct dc_link *link, + struct stream_encoder *enc, + const struct encoder_unblank_param *param) +{ + struct dcn10_stream_encoder *enc1 = DCN10STRENC_FROM_STRENC(enc); + + if (param->link_settings.link_rate != LINK_RATE_UNKNOWN) { + uint32_t n_vid = 0x8000; + uint32_t m_vid; + uint32_t n_multiply = 0; + uint64_t m_vid_l = n_vid; + + /* YCbCr 4:2:0 : Computed VID_M will be 2X the input rate */ + if (param->timing.pixel_encoding == PIXEL_ENCODING_YCBCR420) { + /*this param->pixel_clk_khz is half of 444 rate for 420 already*/ + n_multiply = 1; + } + /* M / N = Fstream / Flink + * m_vid / n_vid = pixel rate / link rate + */ + + m_vid_l *= param->timing.pix_clk_100hz / 10; + m_vid_l = div_u64(m_vid_l, + param->link_settings.link_rate + * LINK_RATE_REF_FREQ_IN_KHZ); + + m_vid = (uint32_t) m_vid_l; + + /* enable auto measurement */ + + REG_UPDATE(DP_VID_TIMING, DP_VID_M_N_GEN_EN, 0); + + /* auto measurement need 1 full 0x8000 symbol cycle to kick in, + * therefore program initial value for Mvid and Nvid + */ + + REG_UPDATE(DP_VID_N, DP_VID_N, n_vid); + + REG_UPDATE(DP_VID_M, DP_VID_M, m_vid); + + REG_UPDATE_2(DP_VID_TIMING, + DP_VID_M_N_GEN_EN, 1, + DP_VID_N_MUL, n_multiply); + } + + /* set DIG_START to 0x1 to resync FIFO */ + + REG_UPDATE(DIG_FE_CNTL, DIG_START, 1); + + /* switch DP encoder to CRTC data */ + + REG_UPDATE(DP_STEER_FIFO, DP_STEER_FIFO_RESET, 0); + + /* wait 100us for DIG/DP logic to prime + * (i.e. a few video lines) + */ + udelay(100); + + /* the hardware would start sending video at the start of the next DP + * frame (i.e. rising edge of the vblank). + * NOTE: We used to program DP_VID_STREAM_DIS_DEFER = 2 here, but this + * register has no effect on enable transition! HW always guarantees + * VID_STREAM enable at start of next frame, and this is not + * programmable + */ + + REG_UPDATE(DP_VID_STREAM_CNTL, DP_VID_STREAM_ENABLE, true); + + link->dc->link_srv->dp_trace_source_sequence(link, + DPCD_SOURCE_SEQ_AFTER_ENABLE_DP_VID_STREAM); +} + +void enc1_stream_encoder_set_avmute( + struct stream_encoder *enc, + bool enable) +{ + struct dcn10_stream_encoder *enc1 = DCN10STRENC_FROM_STRENC(enc); + unsigned int value = enable ? 1 : 0; + + REG_UPDATE(HDMI_GC, HDMI_GC_AVMUTE, value); +} + +void enc1_reset_hdmi_stream_attribute( + struct stream_encoder *enc) +{ + struct dcn10_stream_encoder *enc1 = DCN10STRENC_FROM_STRENC(enc); + + REG_UPDATE_5(HDMI_CONTROL, + HDMI_PACKET_GEN_VERSION, 1, + HDMI_KEEPOUT_MODE, 1, + HDMI_DEEP_COLOR_ENABLE, 0, + HDMI_DATA_SCRAMBLE_EN, 0, + HDMI_CLOCK_CHANNEL_RATE, 0); +} + + +#define DP_SEC_AUD_N__DP_SEC_AUD_N__DEFAULT 0x8000 +#define DP_SEC_TIMESTAMP__DP_SEC_TIMESTAMP_MODE__AUTO_CALC 1 + +#include "include/audio_types.h" + + +/* 25.2MHz/1.001*/ +/* 25.2MHz/1.001*/ +/* 25.2MHz*/ +/* 27MHz */ +/* 27MHz*1.001*/ +/* 27MHz*1.001*/ +/* 54MHz*/ +/* 54MHz*1.001*/ +/* 74.25MHz/1.001*/ +/* 74.25MHz*/ +/* 148.5MHz/1.001*/ +/* 148.5MHz*/ + +static const struct audio_clock_info audio_clock_info_table[16] = { + {2517, 4576, 28125, 7007, 31250, 6864, 28125}, + {2518, 4576, 28125, 7007, 31250, 6864, 28125}, + {2520, 4096, 25200, 6272, 28000, 6144, 25200}, + {2700, 4096, 27000, 6272, 30000, 6144, 27000}, + {2702, 4096, 27027, 6272, 30030, 6144, 27027}, + {2703, 4096, 27027, 6272, 30030, 6144, 27027}, + {5400, 4096, 54000, 6272, 60000, 6144, 54000}, + {5405, 4096, 54054, 6272, 60060, 6144, 54054}, + {7417, 11648, 210937, 17836, 234375, 11648, 140625}, + {7425, 4096, 74250, 6272, 82500, 6144, 74250}, + {14835, 11648, 421875, 8918, 234375, 5824, 140625}, + {14850, 4096, 148500, 6272, 165000, 6144, 148500}, + {29670, 5824, 421875, 4459, 234375, 5824, 281250}, + {29700, 3072, 222750, 4704, 247500, 5120, 247500}, + {59340, 5824, 843750, 8918, 937500, 5824, 562500}, + {59400, 3072, 445500, 9408, 990000, 6144, 594000} +}; + +static const struct audio_clock_info audio_clock_info_table_36bpc[14] = { + {2517, 9152, 84375, 7007, 48875, 9152, 56250}, + {2518, 9152, 84375, 7007, 48875, 9152, 56250}, + {2520, 4096, 37800, 6272, 42000, 6144, 37800}, + {2700, 4096, 40500, 6272, 45000, 6144, 40500}, + {2702, 8192, 81081, 6272, 45045, 8192, 54054}, + {2703, 8192, 81081, 6272, 45045, 8192, 54054}, + {5400, 4096, 81000, 6272, 90000, 6144, 81000}, + {5405, 4096, 81081, 6272, 90090, 6144, 81081}, + {7417, 11648, 316406, 17836, 351562, 11648, 210937}, + {7425, 4096, 111375, 6272, 123750, 6144, 111375}, + {14835, 11648, 632812, 17836, 703125, 11648, 421875}, + {14850, 4096, 222750, 6272, 247500, 6144, 222750}, + {29670, 5824, 632812, 8918, 703125, 5824, 421875}, + {29700, 4096, 445500, 4704, 371250, 5120, 371250} +}; + +static const struct audio_clock_info audio_clock_info_table_48bpc[14] = { + {2517, 4576, 56250, 7007, 62500, 6864, 56250}, + {2518, 4576, 56250, 7007, 62500, 6864, 56250}, + {2520, 4096, 50400, 6272, 56000, 6144, 50400}, + {2700, 4096, 54000, 6272, 60000, 6144, 54000}, + {2702, 4096, 54054, 6267, 60060, 8192, 54054}, + {2703, 4096, 54054, 6272, 60060, 8192, 54054}, + {5400, 4096, 108000, 6272, 120000, 6144, 108000}, + {5405, 4096, 108108, 6272, 120120, 6144, 108108}, + {7417, 11648, 421875, 17836, 468750, 11648, 281250}, + {7425, 4096, 148500, 6272, 165000, 6144, 148500}, + {14835, 11648, 843750, 8918, 468750, 11648, 281250}, + {14850, 4096, 297000, 6272, 330000, 6144, 297000}, + {29670, 5824, 843750, 4459, 468750, 5824, 562500}, + {29700, 3072, 445500, 4704, 495000, 5120, 495000} + + +}; + +static union audio_cea_channels speakers_to_channels( + struct audio_speaker_flags speaker_flags) +{ + union audio_cea_channels cea_channels = {0}; + + /* these are one to one */ + cea_channels.channels.FL = speaker_flags.FL_FR; + cea_channels.channels.FR = speaker_flags.FL_FR; + cea_channels.channels.LFE = speaker_flags.LFE; + cea_channels.channels.FC = speaker_flags.FC; + + /* if Rear Left and Right exist move RC speaker to channel 7 + * otherwise to channel 5 + */ + if (speaker_flags.RL_RR) { + cea_channels.channels.RL_RC = speaker_flags.RL_RR; + cea_channels.channels.RR = speaker_flags.RL_RR; + cea_channels.channels.RC_RLC_FLC = speaker_flags.RC; + } else { + cea_channels.channels.RL_RC = speaker_flags.RC; + } + + /* FRONT Left Right Center and REAR Left Right Center are exclusive */ + if (speaker_flags.FLC_FRC) { + cea_channels.channels.RC_RLC_FLC = speaker_flags.FLC_FRC; + cea_channels.channels.RRC_FRC = speaker_flags.FLC_FRC; + } else { + cea_channels.channels.RC_RLC_FLC = speaker_flags.RLC_RRC; + cea_channels.channels.RRC_FRC = speaker_flags.RLC_RRC; + } + + return cea_channels; +} + +void get_audio_clock_info( + enum dc_color_depth color_depth, + uint32_t crtc_pixel_clock_100Hz, + uint32_t actual_pixel_clock_100Hz, + struct audio_clock_info *audio_clock_info) +{ + const struct audio_clock_info *clock_info; + uint32_t index; + uint32_t crtc_pixel_clock_in_10khz = crtc_pixel_clock_100Hz / 100; + uint32_t audio_array_size; + + switch (color_depth) { + case COLOR_DEPTH_161616: + clock_info = audio_clock_info_table_48bpc; + audio_array_size = ARRAY_SIZE( + audio_clock_info_table_48bpc); + break; + case COLOR_DEPTH_121212: + clock_info = audio_clock_info_table_36bpc; + audio_array_size = ARRAY_SIZE( + audio_clock_info_table_36bpc); + break; + default: + clock_info = audio_clock_info_table; + audio_array_size = ARRAY_SIZE( + audio_clock_info_table); + break; + } + + if (clock_info != NULL) { + /* search for exact pixel clock in table */ + for (index = 0; index < audio_array_size; index++) { + if (clock_info[index].pixel_clock_in_10khz > + crtc_pixel_clock_in_10khz) + break; /* not match */ + else if (clock_info[index].pixel_clock_in_10khz == + crtc_pixel_clock_in_10khz) { + /* match found */ + *audio_clock_info = clock_info[index]; + return; + } + } + } + + /* not found */ + if (actual_pixel_clock_100Hz == 0) + actual_pixel_clock_100Hz = crtc_pixel_clock_100Hz; + + /* See HDMI spec the table entry under + * pixel clock of "Other". */ + audio_clock_info->pixel_clock_in_10khz = + actual_pixel_clock_100Hz / 100; + audio_clock_info->cts_32khz = actual_pixel_clock_100Hz / 10; + audio_clock_info->cts_44khz = actual_pixel_clock_100Hz / 10; + audio_clock_info->cts_48khz = actual_pixel_clock_100Hz / 10; + + audio_clock_info->n_32khz = 4096; + audio_clock_info->n_44khz = 6272; + audio_clock_info->n_48khz = 6144; +} + +static void enc1_se_audio_setup( + struct stream_encoder *enc, + unsigned int az_inst, + struct audio_info *audio_info) +{ + struct dcn10_stream_encoder *enc1 = DCN10STRENC_FROM_STRENC(enc); + + uint32_t channels = 0; + + ASSERT(audio_info); + if (audio_info == NULL) + /* This should not happen.it does so we don't get BSOD*/ + return; + + channels = speakers_to_channels(audio_info->flags.speaker_flags).all; + + /* setup the audio stream source select (audio -> dig mapping) */ + REG_SET(AFMT_AUDIO_SRC_CONTROL, 0, AFMT_AUDIO_SRC_SELECT, az_inst); + + /* Channel allocation */ + REG_UPDATE(AFMT_AUDIO_PACKET_CONTROL2, AFMT_AUDIO_CHANNEL_ENABLE, channels); +} + +static void enc1_se_setup_hdmi_audio( + struct stream_encoder *enc, + const struct audio_crtc_info *crtc_info) +{ + struct dcn10_stream_encoder *enc1 = DCN10STRENC_FROM_STRENC(enc); + + struct audio_clock_info audio_clock_info = {0}; + + /* HDMI_AUDIO_PACKET_CONTROL */ + REG_UPDATE(HDMI_AUDIO_PACKET_CONTROL, + HDMI_AUDIO_DELAY_EN, 1); + + /* AFMT_AUDIO_PACKET_CONTROL */ + REG_UPDATE(AFMT_AUDIO_PACKET_CONTROL, AFMT_60958_CS_UPDATE, 1); + + /* AFMT_AUDIO_PACKET_CONTROL2 */ + REG_UPDATE_2(AFMT_AUDIO_PACKET_CONTROL2, + AFMT_AUDIO_LAYOUT_OVRD, 0, + AFMT_60958_OSF_OVRD, 0); + + /* HDMI_ACR_PACKET_CONTROL */ + REG_UPDATE_3(HDMI_ACR_PACKET_CONTROL, + HDMI_ACR_AUTO_SEND, 1, + HDMI_ACR_SOURCE, 0, + HDMI_ACR_AUDIO_PRIORITY, 0); + + /* Program audio clock sample/regeneration parameters */ + get_audio_clock_info(crtc_info->color_depth, + crtc_info->requested_pixel_clock_100Hz, + crtc_info->calculated_pixel_clock_100Hz, + &audio_clock_info); + DC_LOG_HW_AUDIO( + "\n%s:Input::requested_pixel_clock_100Hz = %d" \ + "calculated_pixel_clock_100Hz = %d \n", __func__, \ + crtc_info->requested_pixel_clock_100Hz, \ + crtc_info->calculated_pixel_clock_100Hz); + + /* HDMI_ACR_32_0__HDMI_ACR_CTS_32_MASK */ + REG_UPDATE(HDMI_ACR_32_0, HDMI_ACR_CTS_32, audio_clock_info.cts_32khz); + + /* HDMI_ACR_32_1__HDMI_ACR_N_32_MASK */ + REG_UPDATE(HDMI_ACR_32_1, HDMI_ACR_N_32, audio_clock_info.n_32khz); + + /* HDMI_ACR_44_0__HDMI_ACR_CTS_44_MASK */ + REG_UPDATE(HDMI_ACR_44_0, HDMI_ACR_CTS_44, audio_clock_info.cts_44khz); + + /* HDMI_ACR_44_1__HDMI_ACR_N_44_MASK */ + REG_UPDATE(HDMI_ACR_44_1, HDMI_ACR_N_44, audio_clock_info.n_44khz); + + /* HDMI_ACR_48_0__HDMI_ACR_CTS_48_MASK */ + REG_UPDATE(HDMI_ACR_48_0, HDMI_ACR_CTS_48, audio_clock_info.cts_48khz); + + /* HDMI_ACR_48_1__HDMI_ACR_N_48_MASK */ + REG_UPDATE(HDMI_ACR_48_1, HDMI_ACR_N_48, audio_clock_info.n_48khz); + + /* Video driver cannot know in advance which sample rate will + * be used by HD Audio driver + * HDMI_ACR_PACKET_CONTROL__HDMI_ACR_N_MULTIPLE field is + * programmed below in interruppt callback + */ + + /* AFMT_60958_0__AFMT_60958_CS_CHANNEL_NUMBER_L_MASK & + * AFMT_60958_0__AFMT_60958_CS_CLOCK_ACCURACY_MASK + */ + REG_UPDATE_2(AFMT_60958_0, + AFMT_60958_CS_CHANNEL_NUMBER_L, 1, + AFMT_60958_CS_CLOCK_ACCURACY, 0); + + /* AFMT_60958_1 AFMT_60958_CS_CHALNNEL_NUMBER_R */ + REG_UPDATE(AFMT_60958_1, AFMT_60958_CS_CHANNEL_NUMBER_R, 2); + + /* AFMT_60958_2 now keep this settings until + * Programming guide comes out + */ + REG_UPDATE_6(AFMT_60958_2, + AFMT_60958_CS_CHANNEL_NUMBER_2, 3, + AFMT_60958_CS_CHANNEL_NUMBER_3, 4, + AFMT_60958_CS_CHANNEL_NUMBER_4, 5, + AFMT_60958_CS_CHANNEL_NUMBER_5, 6, + AFMT_60958_CS_CHANNEL_NUMBER_6, 7, + AFMT_60958_CS_CHANNEL_NUMBER_7, 8); +} + +static void enc1_se_setup_dp_audio( + struct stream_encoder *enc) +{ + struct dcn10_stream_encoder *enc1 = DCN10STRENC_FROM_STRENC(enc); + + /* --- DP Audio packet configurations --- */ + + /* ATP Configuration */ + REG_SET(DP_SEC_AUD_N, 0, + DP_SEC_AUD_N, DP_SEC_AUD_N__DP_SEC_AUD_N__DEFAULT); + + /* Async/auto-calc timestamp mode */ + REG_SET(DP_SEC_TIMESTAMP, 0, DP_SEC_TIMESTAMP_MODE, + DP_SEC_TIMESTAMP__DP_SEC_TIMESTAMP_MODE__AUTO_CALC); + + /* --- The following are the registers + * copied from the SetupHDMI --- + */ + + /* AFMT_AUDIO_PACKET_CONTROL */ + REG_UPDATE(AFMT_AUDIO_PACKET_CONTROL, AFMT_60958_CS_UPDATE, 1); + + /* AFMT_AUDIO_PACKET_CONTROL2 */ + /* Program the ATP and AIP next */ + REG_UPDATE_2(AFMT_AUDIO_PACKET_CONTROL2, + AFMT_AUDIO_LAYOUT_OVRD, 0, + AFMT_60958_OSF_OVRD, 0); + + /* AFMT_INFOFRAME_CONTROL0 */ + REG_UPDATE(AFMT_INFOFRAME_CONTROL0, AFMT_AUDIO_INFO_UPDATE, 1); + + /* AFMT_60958_0__AFMT_60958_CS_CLOCK_ACCURACY_MASK */ + REG_UPDATE(AFMT_60958_0, AFMT_60958_CS_CLOCK_ACCURACY, 0); +} + +void enc1_se_enable_audio_clock( + struct stream_encoder *enc, + bool enable) +{ + struct dcn10_stream_encoder *enc1 = DCN10STRENC_FROM_STRENC(enc); + + if (REG(AFMT_CNTL) == 0) + return; /* DCE8/10 does not have this register */ + + REG_UPDATE(AFMT_CNTL, AFMT_AUDIO_CLOCK_EN, !!enable); + + /* wait for AFMT clock to turn on, + * expectation: this should complete in 1-2 reads + * + * REG_WAIT(AFMT_CNTL, AFMT_AUDIO_CLOCK_ON, !!enable, 1, 10); + * + * TODO: wait for clock_on does not work well. May need HW + * program sequence. But audio seems work normally even without wait + * for clock_on status change + */ +} + +void enc1_se_enable_dp_audio( + struct stream_encoder *enc) +{ + struct dcn10_stream_encoder *enc1 = DCN10STRENC_FROM_STRENC(enc); + + /* Enable Audio packets */ + REG_UPDATE(DP_SEC_CNTL, DP_SEC_ASP_ENABLE, 1); + + /* Program the ATP and AIP next */ + REG_UPDATE_2(DP_SEC_CNTL, + DP_SEC_ATP_ENABLE, 1, + DP_SEC_AIP_ENABLE, 1); + + /* Program STREAM_ENABLE after all the other enables. */ + REG_UPDATE(DP_SEC_CNTL, DP_SEC_STREAM_ENABLE, 1); +} + +static void enc1_se_disable_dp_audio( + struct stream_encoder *enc) +{ + struct dcn10_stream_encoder *enc1 = DCN10STRENC_FROM_STRENC(enc); + uint32_t value = 0; + + /* Disable Audio packets */ + REG_UPDATE_5(DP_SEC_CNTL, + DP_SEC_ASP_ENABLE, 0, + DP_SEC_ATP_ENABLE, 0, + DP_SEC_AIP_ENABLE, 0, + DP_SEC_ACM_ENABLE, 0, + DP_SEC_STREAM_ENABLE, 0); + + /* This register shared with encoder info frame. Therefore we need to + * keep master enabled if at least on of the fields is not 0 + */ + value = REG_READ(DP_SEC_CNTL); + if (value != 0) + REG_UPDATE(DP_SEC_CNTL, DP_SEC_STREAM_ENABLE, 1); + +} + +void enc1_se_audio_mute_control( + struct stream_encoder *enc, + bool mute) +{ + struct dcn10_stream_encoder *enc1 = DCN10STRENC_FROM_STRENC(enc); + + REG_UPDATE(AFMT_AUDIO_PACKET_CONTROL, AFMT_AUDIO_SAMPLE_SEND, !mute); +} + +void enc1_se_dp_audio_setup( + struct stream_encoder *enc, + unsigned int az_inst, + struct audio_info *info) +{ + enc1_se_audio_setup(enc, az_inst, info); +} + +void enc1_se_dp_audio_enable( + struct stream_encoder *enc) +{ + enc1_se_enable_audio_clock(enc, true); + enc1_se_setup_dp_audio(enc); + enc1_se_enable_dp_audio(enc); +} + +void enc1_se_dp_audio_disable( + struct stream_encoder *enc) +{ + enc1_se_disable_dp_audio(enc); + enc1_se_enable_audio_clock(enc, false); +} + +void enc1_se_hdmi_audio_setup( + struct stream_encoder *enc, + unsigned int az_inst, + struct audio_info *info, + struct audio_crtc_info *audio_crtc_info) +{ + enc1_se_enable_audio_clock(enc, true); + enc1_se_setup_hdmi_audio(enc, audio_crtc_info); + enc1_se_audio_setup(enc, az_inst, info); +} + +void enc1_se_hdmi_audio_disable( + struct stream_encoder *enc) +{ + if (enc->afmt && enc->afmt->funcs->afmt_powerdown) + enc->afmt->funcs->afmt_powerdown(enc->afmt); + + enc1_se_enable_audio_clock(enc, false); +} + + +void enc1_setup_stereo_sync( + struct stream_encoder *enc, + int tg_inst, bool enable) +{ + struct dcn10_stream_encoder *enc1 = DCN10STRENC_FROM_STRENC(enc); + REG_UPDATE(DIG_FE_CNTL, DIG_STEREOSYNC_SELECT, tg_inst); + REG_UPDATE(DIG_FE_CNTL, DIG_STEREOSYNC_GATE_EN, !enable); +} + +void enc1_dig_connect_to_otg( + struct stream_encoder *enc, + int tg_inst) +{ + struct dcn10_stream_encoder *enc1 = DCN10STRENC_FROM_STRENC(enc); + + REG_UPDATE(DIG_FE_CNTL, DIG_SOURCE_SELECT, tg_inst); +} + +unsigned int enc1_dig_source_otg( + struct stream_encoder *enc) +{ + uint32_t tg_inst = 0; + struct dcn10_stream_encoder *enc1 = DCN10STRENC_FROM_STRENC(enc); + + REG_GET(DIG_FE_CNTL, DIG_SOURCE_SELECT, &tg_inst); + + return tg_inst; +} + +bool enc1_stream_encoder_dp_get_pixel_format( + struct stream_encoder *enc, + enum dc_pixel_encoding *encoding, + enum dc_color_depth *depth) +{ + uint32_t hw_encoding = 0; + uint32_t hw_depth = 0; + struct dcn10_stream_encoder *enc1 = DCN10STRENC_FROM_STRENC(enc); + + if (enc == NULL || + encoding == NULL || + depth == NULL) + return false; + + REG_GET_2(DP_PIXEL_FORMAT, + DP_PIXEL_ENCODING, &hw_encoding, + DP_COMPONENT_DEPTH, &hw_depth); + + switch (hw_depth) { + case DP_COMPONENT_PIXEL_DEPTH_6BPC: + *depth = COLOR_DEPTH_666; + break; + case DP_COMPONENT_PIXEL_DEPTH_8BPC: + *depth = COLOR_DEPTH_888; + break; + case DP_COMPONENT_PIXEL_DEPTH_10BPC: + *depth = COLOR_DEPTH_101010; + break; + case DP_COMPONENT_PIXEL_DEPTH_12BPC: + *depth = COLOR_DEPTH_121212; + break; + case DP_COMPONENT_PIXEL_DEPTH_16BPC: + *depth = COLOR_DEPTH_161616; + break; + default: + *depth = COLOR_DEPTH_UNDEFINED; + break; + } + + switch (hw_encoding) { + case DP_PIXEL_ENCODING_TYPE_RGB444: + *encoding = PIXEL_ENCODING_RGB; + break; + case DP_PIXEL_ENCODING_TYPE_YCBCR422: + *encoding = PIXEL_ENCODING_YCBCR422; + break; + case DP_PIXEL_ENCODING_TYPE_YCBCR444: + case DP_PIXEL_ENCODING_TYPE_Y_ONLY: + *encoding = PIXEL_ENCODING_YCBCR444; + break; + case DP_PIXEL_ENCODING_TYPE_YCBCR420: + *encoding = PIXEL_ENCODING_YCBCR420; + break; + default: + *encoding = PIXEL_ENCODING_UNDEFINED; + break; + } + return true; +} + +static const struct stream_encoder_funcs dcn10_str_enc_funcs = { + .dp_set_stream_attribute = + enc1_stream_encoder_dp_set_stream_attribute, + .hdmi_set_stream_attribute = + enc1_stream_encoder_hdmi_set_stream_attribute, + .dvi_set_stream_attribute = + enc1_stream_encoder_dvi_set_stream_attribute, + .set_throttled_vcp_size = + enc1_stream_encoder_set_throttled_vcp_size, + .update_hdmi_info_packets = + enc1_stream_encoder_update_hdmi_info_packets, + .stop_hdmi_info_packets = + enc1_stream_encoder_stop_hdmi_info_packets, + .update_dp_info_packets = + enc1_stream_encoder_update_dp_info_packets, + .send_immediate_sdp_message = + enc1_stream_encoder_send_immediate_sdp_message, + .stop_dp_info_packets = + enc1_stream_encoder_stop_dp_info_packets, + .dp_blank = + enc1_stream_encoder_dp_blank, + .dp_unblank = + enc1_stream_encoder_dp_unblank, + .audio_mute_control = enc1_se_audio_mute_control, + + .dp_audio_setup = enc1_se_dp_audio_setup, + .dp_audio_enable = enc1_se_dp_audio_enable, + .dp_audio_disable = enc1_se_dp_audio_disable, + + .hdmi_audio_setup = enc1_se_hdmi_audio_setup, + .hdmi_audio_disable = enc1_se_hdmi_audio_disable, + .setup_stereo_sync = enc1_setup_stereo_sync, + .set_avmute = enc1_stream_encoder_set_avmute, + .dig_connect_to_otg = enc1_dig_connect_to_otg, + .hdmi_reset_stream_attribute = enc1_reset_hdmi_stream_attribute, + .dig_source_otg = enc1_dig_source_otg, + + .dp_get_pixel_format = enc1_stream_encoder_dp_get_pixel_format, +}; + +void dcn10_stream_encoder_construct( + struct dcn10_stream_encoder *enc1, + struct dc_context *ctx, + struct dc_bios *bp, + enum engine_id eng_id, + const struct dcn10_stream_enc_registers *regs, + const struct dcn10_stream_encoder_shift *se_shift, + const struct dcn10_stream_encoder_mask *se_mask) +{ + enc1->base.funcs = &dcn10_str_enc_funcs; + enc1->base.ctx = ctx; + enc1->base.id = eng_id; + enc1->base.bp = bp; + enc1->regs = regs; + enc1->se_shift = se_shift; + enc1->se_mask = se_mask; + enc1->base.stream_enc_inst = eng_id - ENGINE_ID_DIGA; +} + diff --git a/drivers/gpu/drm/amd/display/dc/dio/dcn10/dcn10_stream_encoder.h b/drivers/gpu/drm/amd/display/dc/dio/dcn10/dcn10_stream_encoder.h new file mode 100644 index 000000000000..54a6a4ebd636 --- /dev/null +++ b/drivers/gpu/drm/amd/display/dc/dio/dcn10/dcn10_stream_encoder.h @@ -0,0 +1,749 @@ +/* + * Copyright 2012-15 Advanced Micro Devices, Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + * + * Authors: AMD + * + */ + +#ifndef __DC_STREAM_ENCODER_DCN10_H__ +#define __DC_STREAM_ENCODER_DCN10_H__ + +#include "stream_encoder.h" + +#define DCN10STRENC_FROM_STRENC(stream_encoder)\ + container_of(stream_encoder, struct dcn10_stream_encoder, base) + +#define SE_COMMON_DCN_REG_LIST(id) \ + SRI(AFMT_CNTL, DIG, id), \ + SRI(AFMT_GENERIC_0, DIG, id), \ + SRI(AFMT_GENERIC_1, DIG, id), \ + SRI(AFMT_GENERIC_2, DIG, id), \ + SRI(AFMT_GENERIC_3, DIG, id), \ + SRI(AFMT_GENERIC_4, DIG, id), \ + SRI(AFMT_GENERIC_5, DIG, id), \ + SRI(AFMT_GENERIC_6, DIG, id), \ + SRI(AFMT_GENERIC_7, DIG, id), \ + SRI(AFMT_GENERIC_HDR, DIG, id), \ + SRI(AFMT_INFOFRAME_CONTROL0, DIG, id), \ + SRI(AFMT_VBI_PACKET_CONTROL, DIG, id), \ + SRI(AFMT_VBI_PACKET_CONTROL1, DIG, id), \ + SRI(AFMT_AUDIO_PACKET_CONTROL, DIG, id), \ + SRI(AFMT_AUDIO_PACKET_CONTROL2, DIG, id), \ + SRI(AFMT_AUDIO_SRC_CONTROL, DIG, id), \ + SRI(AFMT_60958_0, DIG, id), \ + SRI(AFMT_60958_1, DIG, id), \ + SRI(AFMT_60958_2, DIG, id), \ + SRI(DIG_FE_CNTL, DIG, id), \ + SRI(DIG_FIFO_STATUS, DIG, id), \ + SRI(HDMI_CONTROL, DIG, id), \ + SRI(HDMI_DB_CONTROL, DIG, id), \ + SRI(HDMI_GC, DIG, id), \ + SRI(HDMI_GENERIC_PACKET_CONTROL0, DIG, id), \ + SRI(HDMI_GENERIC_PACKET_CONTROL1, DIG, id), \ + SRI(HDMI_GENERIC_PACKET_CONTROL2, DIG, id), \ + SRI(HDMI_GENERIC_PACKET_CONTROL3, DIG, id), \ + SRI(HDMI_INFOFRAME_CONTROL0, DIG, id), \ + SRI(HDMI_INFOFRAME_CONTROL1, DIG, id), \ + SRI(HDMI_VBI_PACKET_CONTROL, DIG, id), \ + SRI(HDMI_AUDIO_PACKET_CONTROL, DIG, id),\ + SRI(HDMI_ACR_PACKET_CONTROL, DIG, id),\ + SRI(HDMI_ACR_32_0, DIG, id),\ + SRI(HDMI_ACR_32_1, DIG, id),\ + SRI(HDMI_ACR_44_0, DIG, id),\ + SRI(HDMI_ACR_44_1, DIG, id),\ + SRI(HDMI_ACR_48_0, DIG, id),\ + SRI(HDMI_ACR_48_1, DIG, id),\ + SRI(DP_DB_CNTL, DP, id), \ + SRI(DP_MSA_MISC, DP, id), \ + SRI(DP_MSA_VBID_MISC, DP, id), \ + SRI(DP_MSA_COLORIMETRY, DP, id), \ + SRI(DP_MSA_TIMING_PARAM1, DP, id), \ + SRI(DP_MSA_TIMING_PARAM2, DP, id), \ + SRI(DP_MSA_TIMING_PARAM3, DP, id), \ + SRI(DP_MSA_TIMING_PARAM4, DP, id), \ + SRI(DP_MSE_RATE_CNTL, DP, id), \ + SRI(DP_MSE_RATE_UPDATE, DP, id), \ + SRI(DP_PIXEL_FORMAT, DP, id), \ + SRI(DP_SEC_CNTL, DP, id), \ + SRI(DP_SEC_CNTL1, DP, id), \ + SRI(DP_SEC_CNTL2, DP, id), \ + SRI(DP_SEC_CNTL5, DP, id), \ + SRI(DP_SEC_CNTL6, DP, id), \ + SRI(DP_STEER_FIFO, DP, id), \ + SRI(DP_VID_M, DP, id), \ + SRI(DP_VID_N, DP, id), \ + SRI(DP_VID_STREAM_CNTL, DP, id), \ + SRI(DP_VID_TIMING, DP, id), \ + SRI(DP_SEC_AUD_N, DP, id), \ + SRI(DP_SEC_AUD_N_READBACK, DP, id), \ + SRI(DP_SEC_AUD_M_READBACK, DP, id), \ + SRI(DP_SEC_TIMESTAMP, DP, id), \ + SRI(DIG_CLOCK_PATTERN, DIG, id) + +#define SE_DCN_REG_LIST(id)\ + SE_COMMON_DCN_REG_LIST(id) + + +struct dcn10_stream_enc_registers { + uint32_t AFMT_CNTL; + uint32_t AFMT_AVI_INFO0; + uint32_t AFMT_AVI_INFO1; + uint32_t AFMT_AVI_INFO2; + uint32_t AFMT_AVI_INFO3; + uint32_t AFMT_GENERIC_0; + uint32_t AFMT_GENERIC_1; + uint32_t AFMT_GENERIC_2; + uint32_t AFMT_GENERIC_3; + uint32_t AFMT_GENERIC_4; + uint32_t AFMT_GENERIC_5; + uint32_t AFMT_GENERIC_6; + uint32_t AFMT_GENERIC_7; + uint32_t AFMT_GENERIC_HDR; + uint32_t AFMT_INFOFRAME_CONTROL0; + uint32_t AFMT_VBI_PACKET_CONTROL; + uint32_t AFMT_VBI_PACKET_CONTROL1; + uint32_t AFMT_AUDIO_PACKET_CONTROL; + uint32_t AFMT_AUDIO_PACKET_CONTROL2; + uint32_t AFMT_AUDIO_SRC_CONTROL; + uint32_t AFMT_60958_0; + uint32_t AFMT_60958_1; + uint32_t AFMT_60958_2; + uint32_t DIG_FE_CNTL; + uint32_t DIG_FIFO_STATUS; + uint32_t DP_MSE_RATE_CNTL; + uint32_t DP_MSE_RATE_UPDATE; + uint32_t DP_PIXEL_FORMAT; + uint32_t DP_SEC_CNTL; + uint32_t DP_SEC_CNTL1; + uint32_t DP_SEC_CNTL2; + uint32_t DP_SEC_CNTL5; + uint32_t DP_SEC_CNTL6; + uint32_t DP_STEER_FIFO; + uint32_t DP_VID_M; + uint32_t DP_VID_N; + uint32_t DP_VID_STREAM_CNTL; + uint32_t DP_VID_TIMING; + uint32_t DP_SEC_AUD_N; + uint32_t DP_SEC_AUD_N_READBACK; + uint32_t DP_SEC_AUD_M_READBACK; + uint32_t DP_SEC_TIMESTAMP; + uint32_t HDMI_CONTROL; + uint32_t HDMI_GC; + uint32_t HDMI_GENERIC_PACKET_CONTROL0; + uint32_t HDMI_GENERIC_PACKET_CONTROL1; + uint32_t HDMI_GENERIC_PACKET_CONTROL2; + uint32_t HDMI_GENERIC_PACKET_CONTROL3; + uint32_t HDMI_GENERIC_PACKET_CONTROL4; + uint32_t HDMI_GENERIC_PACKET_CONTROL5; + uint32_t HDMI_INFOFRAME_CONTROL0; + uint32_t HDMI_INFOFRAME_CONTROL1; + uint32_t HDMI_VBI_PACKET_CONTROL; + uint32_t HDMI_AUDIO_PACKET_CONTROL; + uint32_t HDMI_ACR_PACKET_CONTROL; + uint32_t HDMI_ACR_32_0; + uint32_t HDMI_ACR_32_1; + uint32_t HDMI_ACR_44_0; + uint32_t HDMI_ACR_44_1; + uint32_t HDMI_ACR_48_0; + uint32_t HDMI_ACR_48_1; + uint32_t DP_DB_CNTL; + uint32_t DP_MSA_MISC; + uint32_t DP_MSA_VBID_MISC; + uint32_t DP_MSA_COLORIMETRY; + uint32_t DP_MSA_TIMING_PARAM1; + uint32_t DP_MSA_TIMING_PARAM2; + uint32_t DP_MSA_TIMING_PARAM3; + uint32_t DP_MSA_TIMING_PARAM4; + uint32_t HDMI_DB_CONTROL; + uint32_t DP_DSC_CNTL; + uint32_t DP_DSC_BYTES_PER_PIXEL; + uint32_t DME_CONTROL; + uint32_t DP_SEC_METADATA_TRANSMISSION; + uint32_t HDMI_METADATA_PACKET_CONTROL; + uint32_t DP_SEC_FRAMING4; + uint32_t DP_GSP11_CNTL; + uint32_t HDMI_GENERIC_PACKET_CONTROL6; + uint32_t HDMI_GENERIC_PACKET_CONTROL7; + uint32_t HDMI_GENERIC_PACKET_CONTROL8; + uint32_t HDMI_GENERIC_PACKET_CONTROL9; + uint32_t HDMI_GENERIC_PACKET_CONTROL10; + uint32_t DIG_CLOCK_PATTERN; + uint32_t DIG_FIFO_CTRL0; + uint32_t DIG_FE_CLK_CNTL; + uint32_t DIG_FE_EN_CNTL; + uint32_t STREAM_MAPPER_CONTROL; +}; + + +#define SE_SF(reg_name, field_name, post_fix)\ + .field_name = reg_name ## __ ## field_name ## post_fix + +#define SE_COMMON_MASK_SH_LIST_SOC(mask_sh)\ + SE_SF(DIG0_AFMT_VBI_PACKET_CONTROL, AFMT_GENERIC_INDEX, mask_sh),\ + SE_SF(DIG0_AFMT_GENERIC_HDR, AFMT_GENERIC_HB0, mask_sh),\ + SE_SF(DIG0_AFMT_GENERIC_HDR, AFMT_GENERIC_HB1, mask_sh),\ + SE_SF(DIG0_AFMT_GENERIC_HDR, AFMT_GENERIC_HB2, mask_sh),\ + SE_SF(DIG0_AFMT_GENERIC_HDR, AFMT_GENERIC_HB3, mask_sh),\ + SE_SF(DP0_DP_PIXEL_FORMAT, DP_PIXEL_ENCODING, mask_sh),\ + SE_SF(DP0_DP_PIXEL_FORMAT, DP_COMPONENT_DEPTH, mask_sh),\ + SE_SF(DIG0_HDMI_CONTROL, HDMI_PACKET_GEN_VERSION, mask_sh),\ + SE_SF(DIG0_HDMI_CONTROL, HDMI_KEEPOUT_MODE, mask_sh),\ + SE_SF(DIG0_HDMI_CONTROL, HDMI_DEEP_COLOR_ENABLE, mask_sh),\ + SE_SF(DIG0_HDMI_CONTROL, HDMI_DEEP_COLOR_DEPTH, mask_sh),\ + SE_SF(DIG0_HDMI_CONTROL, HDMI_DATA_SCRAMBLE_EN, mask_sh),\ + SE_SF(DIG0_HDMI_CONTROL, HDMI_NO_EXTRA_NULL_PACKET_FILLED, mask_sh),\ + SE_SF(DIG0_HDMI_VBI_PACKET_CONTROL, HDMI_GC_CONT, mask_sh),\ + SE_SF(DIG0_HDMI_VBI_PACKET_CONTROL, HDMI_GC_SEND, mask_sh),\ + SE_SF(DIG0_HDMI_VBI_PACKET_CONTROL, HDMI_NULL_SEND, mask_sh),\ + SE_SF(DIG0_HDMI_VBI_PACKET_CONTROL, HDMI_ACP_SEND, mask_sh),\ + SE_SF(DIG0_HDMI_INFOFRAME_CONTROL0, HDMI_AUDIO_INFO_SEND, mask_sh),\ + SE_SF(DIG0_AFMT_INFOFRAME_CONTROL0, AFMT_AUDIO_INFO_UPDATE, mask_sh),\ + SE_SF(DIG0_HDMI_INFOFRAME_CONTROL1, HDMI_AUDIO_INFO_LINE, mask_sh),\ + SE_SF(DIG0_HDMI_GC, HDMI_GC_AVMUTE, mask_sh),\ + SE_SF(DP0_DP_MSE_RATE_CNTL, DP_MSE_RATE_X, mask_sh),\ + SE_SF(DP0_DP_MSE_RATE_CNTL, DP_MSE_RATE_Y, mask_sh),\ + SE_SF(DP0_DP_MSE_RATE_UPDATE, DP_MSE_RATE_UPDATE_PENDING, mask_sh),\ + SE_SF(DP0_DP_SEC_CNTL, DP_SEC_GSP0_ENABLE, mask_sh),\ + SE_SF(DP0_DP_SEC_CNTL, DP_SEC_STREAM_ENABLE, mask_sh),\ + SE_SF(DP0_DP_SEC_CNTL, DP_SEC_GSP1_ENABLE, mask_sh),\ + SE_SF(DP0_DP_SEC_CNTL, DP_SEC_GSP2_ENABLE, mask_sh),\ + SE_SF(DP0_DP_SEC_CNTL, DP_SEC_GSP3_ENABLE, mask_sh),\ + SE_SF(DP0_DP_SEC_CNTL, DP_SEC_MPG_ENABLE, mask_sh),\ + SE_SF(DP0_DP_SEC_CNTL2, DP_SEC_GSP4_SEND, mask_sh),\ + SE_SF(DP0_DP_SEC_CNTL2, DP_SEC_GSP4_SEND_PENDING, mask_sh),\ + SE_SF(DP0_DP_SEC_CNTL4, DP_SEC_GSP4_LINE_NUM, mask_sh),\ + SE_SF(DP0_DP_SEC_CNTL2, DP_SEC_GSP4_SEND_ANY_LINE, mask_sh),\ + SE_SF(DP0_DP_VID_STREAM_CNTL, DP_VID_STREAM_DIS_DEFER, mask_sh),\ + SE_SF(DP0_DP_VID_STREAM_CNTL, DP_VID_STREAM_ENABLE, mask_sh),\ + SE_SF(DP0_DP_VID_STREAM_CNTL, DP_VID_STREAM_STATUS, mask_sh),\ + SE_SF(DP0_DP_STEER_FIFO, DP_STEER_FIFO_RESET, mask_sh),\ + SE_SF(DP0_DP_VID_TIMING, DP_VID_M_N_GEN_EN, mask_sh),\ + SE_SF(DP0_DP_VID_N, DP_VID_N, mask_sh),\ + SE_SF(DP0_DP_VID_M, DP_VID_M, mask_sh),\ + SE_SF(DIG0_DIG_FE_CNTL, DIG_START, mask_sh),\ + SE_SF(DIG0_AFMT_AUDIO_SRC_CONTROL, AFMT_AUDIO_SRC_SELECT, mask_sh),\ + SE_SF(DIG0_AFMT_AUDIO_PACKET_CONTROL2, AFMT_AUDIO_CHANNEL_ENABLE, mask_sh),\ + SE_SF(DIG0_HDMI_AUDIO_PACKET_CONTROL, HDMI_AUDIO_PACKETS_PER_LINE, mask_sh),\ + SE_SF(DIG0_HDMI_AUDIO_PACKET_CONTROL, HDMI_AUDIO_DELAY_EN, mask_sh),\ + SE_SF(DIG0_AFMT_AUDIO_PACKET_CONTROL, AFMT_60958_CS_UPDATE, mask_sh),\ + SE_SF(DIG0_AFMT_AUDIO_PACKET_CONTROL2, AFMT_AUDIO_LAYOUT_OVRD, mask_sh),\ + SE_SF(DIG0_AFMT_AUDIO_PACKET_CONTROL2, AFMT_60958_OSF_OVRD, mask_sh),\ + SE_SF(DIG0_HDMI_ACR_PACKET_CONTROL, HDMI_ACR_AUTO_SEND, mask_sh),\ + SE_SF(DIG0_HDMI_ACR_PACKET_CONTROL, HDMI_ACR_SOURCE, mask_sh),\ + SE_SF(DIG0_HDMI_ACR_PACKET_CONTROL, HDMI_ACR_AUDIO_PRIORITY, mask_sh),\ + SE_SF(DIG0_HDMI_ACR_32_0, HDMI_ACR_CTS_32, mask_sh),\ + SE_SF(DIG0_HDMI_ACR_32_1, HDMI_ACR_N_32, mask_sh),\ + SE_SF(DIG0_HDMI_ACR_44_0, HDMI_ACR_CTS_44, mask_sh),\ + SE_SF(DIG0_HDMI_ACR_44_1, HDMI_ACR_N_44, mask_sh),\ + SE_SF(DIG0_HDMI_ACR_48_0, HDMI_ACR_CTS_48, mask_sh),\ + SE_SF(DIG0_HDMI_ACR_48_1, HDMI_ACR_N_48, mask_sh),\ + SE_SF(DIG0_AFMT_60958_0, AFMT_60958_CS_CHANNEL_NUMBER_L, mask_sh),\ + SE_SF(DIG0_AFMT_60958_0, AFMT_60958_CS_CLOCK_ACCURACY, mask_sh),\ + SE_SF(DIG0_AFMT_60958_1, AFMT_60958_CS_CHANNEL_NUMBER_R, mask_sh),\ + SE_SF(DIG0_AFMT_60958_2, AFMT_60958_CS_CHANNEL_NUMBER_2, mask_sh),\ + SE_SF(DIG0_AFMT_60958_2, AFMT_60958_CS_CHANNEL_NUMBER_3, mask_sh),\ + SE_SF(DIG0_AFMT_60958_2, AFMT_60958_CS_CHANNEL_NUMBER_4, mask_sh),\ + SE_SF(DIG0_AFMT_60958_2, AFMT_60958_CS_CHANNEL_NUMBER_5, mask_sh),\ + SE_SF(DIG0_AFMT_60958_2, AFMT_60958_CS_CHANNEL_NUMBER_6, mask_sh),\ + SE_SF(DIG0_AFMT_60958_2, AFMT_60958_CS_CHANNEL_NUMBER_7, mask_sh),\ + SE_SF(DP0_DP_SEC_AUD_N, DP_SEC_AUD_N, mask_sh),\ + SE_SF(DP0_DP_SEC_AUD_N_READBACK, DP_SEC_AUD_N_READBACK, mask_sh),\ + SE_SF(DP0_DP_SEC_AUD_M_READBACK, DP_SEC_AUD_M_READBACK, mask_sh),\ + SE_SF(DP0_DP_SEC_TIMESTAMP, DP_SEC_TIMESTAMP_MODE, mask_sh),\ + SE_SF(DP0_DP_SEC_CNTL, DP_SEC_ASP_ENABLE, mask_sh),\ + SE_SF(DP0_DP_SEC_CNTL, DP_SEC_ATP_ENABLE, mask_sh),\ + SE_SF(DP0_DP_SEC_CNTL, DP_SEC_AIP_ENABLE, mask_sh),\ + SE_SF(DP0_DP_SEC_CNTL, DP_SEC_ACM_ENABLE, mask_sh),\ + SE_SF(DIG0_AFMT_AUDIO_PACKET_CONTROL, AFMT_AUDIO_SAMPLE_SEND, mask_sh),\ + SE_SF(DIG0_AFMT_CNTL, AFMT_AUDIO_CLOCK_EN, mask_sh),\ + SE_SF(DIG0_HDMI_CONTROL, HDMI_CLOCK_CHANNEL_RATE, mask_sh),\ + SE_SF(DIG0_DIG_FE_CNTL, TMDS_PIXEL_ENCODING, mask_sh),\ + SE_SF(DIG0_DIG_FE_CNTL, TMDS_COLOR_FORMAT, mask_sh),\ + SE_SF(DIG0_DIG_FE_CNTL, DIG_STEREOSYNC_SELECT, mask_sh),\ + SE_SF(DIG0_DIG_FE_CNTL, DIG_STEREOSYNC_GATE_EN, mask_sh),\ + SE_SF(DIG0_DIG_FIFO_STATUS, DIG_FIFO_LEVEL_ERROR, mask_sh),\ + SE_SF(DIG0_DIG_FIFO_STATUS, DIG_FIFO_USE_OVERWRITE_LEVEL, mask_sh),\ + SE_SF(DIG0_DIG_FIFO_STATUS, DIG_FIFO_OVERWRITE_LEVEL, mask_sh),\ + SE_SF(DIG0_DIG_FIFO_STATUS, DIG_FIFO_ERROR_ACK, mask_sh),\ + SE_SF(DIG0_DIG_FIFO_STATUS, DIG_FIFO_CAL_AVERAGE_LEVEL, mask_sh),\ + SE_SF(DIG0_DIG_FIFO_STATUS, DIG_FIFO_MAXIMUM_LEVEL, mask_sh),\ + SE_SF(DIG0_DIG_FIFO_STATUS, DIG_FIFO_MINIMUM_LEVEL, mask_sh),\ + SE_SF(DIG0_DIG_FIFO_STATUS, DIG_FIFO_READ_CLOCK_SRC, mask_sh),\ + SE_SF(DIG0_DIG_FIFO_STATUS, DIG_FIFO_CALIBRATED, mask_sh),\ + SE_SF(DIG0_DIG_FIFO_STATUS, DIG_FIFO_FORCE_RECAL_AVERAGE, mask_sh),\ + SE_SF(DIG0_DIG_FIFO_STATUS, DIG_FIFO_FORCE_RECOMP_MINMAX, mask_sh),\ + SE_SF(DIG0_AFMT_VBI_PACKET_CONTROL, AFMT_GENERIC_LOCK_STATUS, mask_sh),\ + SE_SF(DIG0_AFMT_VBI_PACKET_CONTROL, AFMT_GENERIC_CONFLICT, mask_sh),\ + SE_SF(DIG0_AFMT_VBI_PACKET_CONTROL, AFMT_GENERIC_CONFLICT_CLR, mask_sh),\ + SE_SF(DIG0_AFMT_VBI_PACKET_CONTROL1, AFMT_GENERIC0_FRAME_UPDATE_PENDING, mask_sh),\ + SE_SF(DIG0_AFMT_VBI_PACKET_CONTROL1, AFMT_GENERIC1_FRAME_UPDATE_PENDING, mask_sh),\ + SE_SF(DIG0_AFMT_VBI_PACKET_CONTROL1, AFMT_GENERIC2_FRAME_UPDATE_PENDING, mask_sh),\ + SE_SF(DIG0_AFMT_VBI_PACKET_CONTROL1, AFMT_GENERIC3_FRAME_UPDATE_PENDING, mask_sh),\ + SE_SF(DIG0_AFMT_VBI_PACKET_CONTROL1, AFMT_GENERIC4_FRAME_UPDATE_PENDING, mask_sh),\ + SE_SF(DIG0_AFMT_VBI_PACKET_CONTROL1, AFMT_GENERIC4_IMMEDIATE_UPDATE_PENDING, mask_sh),\ + SE_SF(DIG0_AFMT_VBI_PACKET_CONTROL1, AFMT_GENERIC5_FRAME_UPDATE_PENDING, mask_sh),\ + SE_SF(DIG0_AFMT_VBI_PACKET_CONTROL1, AFMT_GENERIC6_FRAME_UPDATE_PENDING, mask_sh),\ + SE_SF(DIG0_AFMT_VBI_PACKET_CONTROL1, AFMT_GENERIC7_FRAME_UPDATE_PENDING, mask_sh),\ + SE_SF(DIG0_AFMT_VBI_PACKET_CONTROL1, AFMT_GENERIC0_FRAME_UPDATE, mask_sh),\ + SE_SF(DIG0_AFMT_VBI_PACKET_CONTROL1, AFMT_GENERIC1_FRAME_UPDATE, mask_sh),\ + SE_SF(DIG0_AFMT_VBI_PACKET_CONTROL1, AFMT_GENERIC2_FRAME_UPDATE, mask_sh),\ + SE_SF(DIG0_AFMT_VBI_PACKET_CONTROL1, AFMT_GENERIC3_FRAME_UPDATE, mask_sh),\ + SE_SF(DIG0_AFMT_VBI_PACKET_CONTROL1, AFMT_GENERIC4_FRAME_UPDATE, mask_sh),\ + SE_SF(DIG0_AFMT_VBI_PACKET_CONTROL1, AFMT_GENERIC0_IMMEDIATE_UPDATE, mask_sh),\ + SE_SF(DIG0_AFMT_VBI_PACKET_CONTROL1, AFMT_GENERIC1_IMMEDIATE_UPDATE, mask_sh),\ + SE_SF(DIG0_AFMT_VBI_PACKET_CONTROL1, AFMT_GENERIC2_IMMEDIATE_UPDATE, mask_sh),\ + SE_SF(DIG0_AFMT_VBI_PACKET_CONTROL1, AFMT_GENERIC3_IMMEDIATE_UPDATE, mask_sh),\ + SE_SF(DIG0_AFMT_VBI_PACKET_CONTROL1, AFMT_GENERIC4_IMMEDIATE_UPDATE, mask_sh),\ + SE_SF(DIG0_AFMT_VBI_PACKET_CONTROL1, AFMT_GENERIC5_IMMEDIATE_UPDATE, mask_sh),\ + SE_SF(DIG0_AFMT_VBI_PACKET_CONTROL1, AFMT_GENERIC6_IMMEDIATE_UPDATE, mask_sh),\ + SE_SF(DIG0_AFMT_VBI_PACKET_CONTROL1, AFMT_GENERIC7_IMMEDIATE_UPDATE, mask_sh),\ + SE_SF(DIG0_AFMT_VBI_PACKET_CONTROL1, AFMT_GENERIC5_FRAME_UPDATE, mask_sh),\ + SE_SF(DIG0_AFMT_VBI_PACKET_CONTROL1, AFMT_GENERIC6_FRAME_UPDATE, mask_sh),\ + SE_SF(DIG0_AFMT_VBI_PACKET_CONTROL1, AFMT_GENERIC7_FRAME_UPDATE, mask_sh),\ + SE_SF(DP0_DP_SEC_CNTL, DP_SEC_GSP4_ENABLE, mask_sh),\ + SE_SF(DP0_DP_SEC_CNTL, DP_SEC_GSP5_ENABLE, mask_sh),\ + SE_SF(DP0_DP_SEC_CNTL, DP_SEC_GSP6_ENABLE, mask_sh),\ + SE_SF(DP0_DP_SEC_CNTL, DP_SEC_GSP7_ENABLE, mask_sh),\ + SE_SF(DP0_DP_SEC_CNTL2, DP_SEC_GSP7_PPS, mask_sh),\ + SE_SF(DP0_DP_SEC_CNTL2, DP_SEC_GSP7_SEND, mask_sh),\ + SE_SF(DP0_DP_SEC_CNTL6, DP_SEC_GSP7_LINE_NUM, mask_sh),\ + SE_SF(DP0_DP_DB_CNTL, DP_DB_DISABLE, mask_sh),\ + SE_SF(DP0_DP_MSA_COLORIMETRY, DP_MSA_MISC0, mask_sh),\ + SE_SF(DP0_DP_MSA_TIMING_PARAM1, DP_MSA_HTOTAL, mask_sh),\ + SE_SF(DP0_DP_MSA_TIMING_PARAM1, DP_MSA_VTOTAL, mask_sh),\ + SE_SF(DP0_DP_MSA_TIMING_PARAM2, DP_MSA_HSTART, mask_sh),\ + SE_SF(DP0_DP_MSA_TIMING_PARAM2, DP_MSA_VSTART, mask_sh),\ + SE_SF(DP0_DP_MSA_TIMING_PARAM3, DP_MSA_HSYNCWIDTH, mask_sh),\ + SE_SF(DP0_DP_MSA_TIMING_PARAM3, DP_MSA_HSYNCPOLARITY, mask_sh),\ + SE_SF(DP0_DP_MSA_TIMING_PARAM3, DP_MSA_VSYNCWIDTH, mask_sh),\ + SE_SF(DP0_DP_MSA_TIMING_PARAM3, DP_MSA_VSYNCPOLARITY, mask_sh),\ + SE_SF(DP0_DP_MSA_TIMING_PARAM4, DP_MSA_HWIDTH, mask_sh),\ + SE_SF(DP0_DP_MSA_TIMING_PARAM4, DP_MSA_VHEIGHT, mask_sh),\ + SE_SF(DIG0_HDMI_DB_CONTROL, HDMI_DB_DISABLE, mask_sh),\ + SE_SF(DP0_DP_VID_TIMING, DP_VID_N_MUL, mask_sh),\ + SE_SF(DIG0_DIG_FE_CNTL, DIG_SOURCE_SELECT, mask_sh),\ + SE_SF(DIG0_DIG_CLOCK_PATTERN, DIG_CLOCK_PATTERN, mask_sh) + +#define SE_COMMON_MASK_SH_LIST_DCN10(mask_sh)\ + SE_COMMON_MASK_SH_LIST_SOC(mask_sh),\ + SE_SF(DIG0_HDMI_GENERIC_PACKET_CONTROL0, HDMI_GENERIC0_CONT, mask_sh),\ + SE_SF(DIG0_HDMI_GENERIC_PACKET_CONTROL0, HDMI_GENERIC0_SEND, mask_sh),\ + SE_SF(DIG0_HDMI_GENERIC_PACKET_CONTROL0, HDMI_GENERIC0_LINE, mask_sh),\ + SE_SF(DIG0_HDMI_GENERIC_PACKET_CONTROL0, HDMI_GENERIC1_CONT, mask_sh),\ + SE_SF(DIG0_HDMI_GENERIC_PACKET_CONTROL0, HDMI_GENERIC1_SEND, mask_sh),\ + SE_SF(DIG0_HDMI_GENERIC_PACKET_CONTROL0, HDMI_GENERIC1_LINE, mask_sh) + + +#define SE_REG_FIELD_LIST_DCN1_0(type) \ + type AFMT_GENERIC_INDEX;\ + type AFMT_GENERIC_HB0;\ + type AFMT_GENERIC_HB1;\ + type AFMT_GENERIC_HB2;\ + type AFMT_GENERIC_HB3;\ + type AFMT_GENERIC_LOCK_STATUS;\ + type AFMT_GENERIC_CONFLICT;\ + type AFMT_GENERIC_CONFLICT_CLR;\ + type AFMT_GENERIC0_FRAME_UPDATE_PENDING;\ + type AFMT_GENERIC1_FRAME_UPDATE_PENDING;\ + type AFMT_GENERIC2_FRAME_UPDATE_PENDING;\ + type AFMT_GENERIC3_FRAME_UPDATE_PENDING;\ + type AFMT_GENERIC4_FRAME_UPDATE_PENDING;\ + type AFMT_GENERIC4_IMMEDIATE_UPDATE_PENDING;\ + type AFMT_GENERIC5_FRAME_UPDATE_PENDING;\ + type AFMT_GENERIC6_FRAME_UPDATE_PENDING;\ + type AFMT_GENERIC7_FRAME_UPDATE_PENDING;\ + type AFMT_GENERIC0_FRAME_UPDATE;\ + type AFMT_GENERIC1_FRAME_UPDATE;\ + type AFMT_GENERIC2_FRAME_UPDATE;\ + type AFMT_GENERIC3_FRAME_UPDATE;\ + type AFMT_GENERIC4_FRAME_UPDATE;\ + type AFMT_GENERIC0_IMMEDIATE_UPDATE;\ + type AFMT_GENERIC1_IMMEDIATE_UPDATE;\ + type AFMT_GENERIC2_IMMEDIATE_UPDATE;\ + type AFMT_GENERIC3_IMMEDIATE_UPDATE;\ + type AFMT_GENERIC4_IMMEDIATE_UPDATE;\ + type AFMT_GENERIC5_IMMEDIATE_UPDATE;\ + type AFMT_GENERIC6_IMMEDIATE_UPDATE;\ + type AFMT_GENERIC7_IMMEDIATE_UPDATE;\ + type AFMT_GENERIC5_FRAME_UPDATE;\ + type AFMT_GENERIC6_FRAME_UPDATE;\ + type AFMT_GENERIC7_FRAME_UPDATE;\ + type HDMI_GENERIC0_CONT;\ + type HDMI_GENERIC0_SEND;\ + type HDMI_GENERIC0_LINE;\ + type HDMI_GENERIC1_CONT;\ + type HDMI_GENERIC1_SEND;\ + type HDMI_GENERIC1_LINE;\ + type HDMI_GENERIC2_CONT;\ + type HDMI_GENERIC2_SEND;\ + type HDMI_GENERIC2_LINE;\ + type HDMI_GENERIC3_CONT;\ + type HDMI_GENERIC3_SEND;\ + type HDMI_GENERIC3_LINE;\ + type HDMI_GENERIC4_CONT;\ + type HDMI_GENERIC4_SEND;\ + type HDMI_GENERIC4_LINE;\ + type HDMI_GENERIC5_CONT;\ + type HDMI_GENERIC5_SEND;\ + type HDMI_GENERIC5_LINE;\ + type HDMI_GENERIC6_CONT;\ + type HDMI_GENERIC6_SEND;\ + type HDMI_GENERIC6_LINE;\ + type HDMI_GENERIC7_CONT;\ + type HDMI_GENERIC7_SEND;\ + type HDMI_GENERIC7_LINE;\ + type DP_PIXEL_ENCODING;\ + type DP_COMPONENT_DEPTH;\ + type HDMI_PACKET_GEN_VERSION;\ + type HDMI_KEEPOUT_MODE;\ + type HDMI_DEEP_COLOR_ENABLE;\ + type HDMI_CLOCK_CHANNEL_RATE;\ + type HDMI_DEEP_COLOR_DEPTH;\ + type HDMI_GC_CONT;\ + type HDMI_GC_SEND;\ + type HDMI_NULL_SEND;\ + type HDMI_DATA_SCRAMBLE_EN;\ + type HDMI_NO_EXTRA_NULL_PACKET_FILLED;\ + type HDMI_AUDIO_INFO_SEND;\ + type AFMT_AUDIO_INFO_UPDATE;\ + type HDMI_AUDIO_INFO_LINE;\ + type HDMI_GC_AVMUTE;\ + type DP_MSE_RATE_X;\ + type DP_MSE_RATE_Y;\ + type DP_MSE_RATE_UPDATE_PENDING;\ + type DP_SEC_GSP0_ENABLE;\ + type DP_SEC_STREAM_ENABLE;\ + type DP_SEC_GSP1_ENABLE;\ + type DP_SEC_GSP2_ENABLE;\ + type DP_SEC_GSP3_ENABLE;\ + type DP_SEC_GSP4_ENABLE;\ + type DP_SEC_GSP5_ENABLE;\ + type DP_SEC_GSP5_LINE_NUM;\ + type DP_SEC_GSP5_LINE_REFERENCE;\ + type DP_SEC_GSP6_ENABLE;\ + type DP_SEC_GSP7_ENABLE;\ + type DP_SEC_GSP7_PPS;\ + type DP_SEC_GSP7_SEND;\ + type DP_SEC_GSP4_SEND;\ + type DP_SEC_GSP4_SEND_PENDING;\ + type DP_SEC_GSP4_LINE_NUM;\ + type DP_SEC_GSP4_SEND_ANY_LINE;\ + type DP_SEC_MPG_ENABLE;\ + type DP_VID_STREAM_DIS_DEFER;\ + type DP_VID_STREAM_ENABLE;\ + type DP_VID_STREAM_STATUS;\ + type DP_STEER_FIFO_RESET;\ + type DP_VID_M_N_GEN_EN;\ + type DP_VID_N;\ + type DP_VID_M;\ + type DIG_START;\ + type AFMT_AUDIO_SRC_SELECT;\ + type AFMT_AUDIO_CHANNEL_ENABLE;\ + type HDMI_AUDIO_PACKETS_PER_LINE;\ + type HDMI_AUDIO_DELAY_EN;\ + type AFMT_60958_CS_UPDATE;\ + type AFMT_AUDIO_LAYOUT_OVRD;\ + type AFMT_60958_OSF_OVRD;\ + type HDMI_ACR_AUTO_SEND;\ + type HDMI_ACR_SOURCE;\ + type HDMI_ACR_AUDIO_PRIORITY;\ + type HDMI_ACR_CTS_32;\ + type HDMI_ACR_N_32;\ + type HDMI_ACR_CTS_44;\ + type HDMI_ACR_N_44;\ + type HDMI_ACR_CTS_48;\ + type HDMI_ACR_N_48;\ + type AFMT_60958_CS_CHANNEL_NUMBER_L;\ + type AFMT_60958_CS_CLOCK_ACCURACY;\ + type AFMT_60958_CS_CHANNEL_NUMBER_R;\ + type AFMT_60958_CS_CHANNEL_NUMBER_2;\ + type AFMT_60958_CS_CHANNEL_NUMBER_3;\ + type AFMT_60958_CS_CHANNEL_NUMBER_4;\ + type AFMT_60958_CS_CHANNEL_NUMBER_5;\ + type AFMT_60958_CS_CHANNEL_NUMBER_6;\ + type AFMT_60958_CS_CHANNEL_NUMBER_7;\ + type DP_SEC_AUD_N;\ + type DP_SEC_AUD_N_READBACK;\ + type DP_SEC_AUD_M_READBACK;\ + type DP_SEC_TIMESTAMP_MODE;\ + type DP_SEC_ASP_ENABLE;\ + type DP_SEC_ATP_ENABLE;\ + type DP_SEC_AIP_ENABLE;\ + type DP_SEC_ACM_ENABLE;\ + type DP_SEC_GSP7_LINE_NUM;\ + type AFMT_AUDIO_SAMPLE_SEND;\ + type AFMT_AUDIO_CLOCK_EN;\ + type TMDS_PIXEL_ENCODING;\ + type TMDS_COLOR_FORMAT;\ + type DIG_STEREOSYNC_SELECT;\ + type DIG_STEREOSYNC_GATE_EN;\ + type DP_DB_DISABLE;\ + type DP_MSA_MISC0;\ + type DP_MSA_HTOTAL;\ + type DP_MSA_VTOTAL;\ + type DP_MSA_HSTART;\ + type DP_MSA_VSTART;\ + type DP_MSA_HSYNCWIDTH;\ + type DP_MSA_HSYNCPOLARITY;\ + type DP_MSA_VSYNCWIDTH;\ + type DP_MSA_VSYNCPOLARITY;\ + type DP_MSA_HWIDTH;\ + type DP_MSA_VHEIGHT;\ + type HDMI_DB_DISABLE;\ + type DP_VID_N_MUL;\ + type DP_VID_M_DOUBLE_VALUE_EN;\ + type DIG_SOURCE_SELECT;\ + type DIG_FIFO_LEVEL_ERROR;\ + type DIG_FIFO_USE_OVERWRITE_LEVEL;\ + type DIG_FIFO_OVERWRITE_LEVEL;\ + type DIG_FIFO_ERROR_ACK;\ + type DIG_FIFO_CAL_AVERAGE_LEVEL;\ + type DIG_FIFO_MAXIMUM_LEVEL;\ + type DIG_FIFO_MINIMUM_LEVEL;\ + type DIG_FIFO_READ_CLOCK_SRC;\ + type DIG_FIFO_CALIBRATED;\ + type DIG_FIFO_FORCE_RECAL_AVERAGE;\ + type DIG_FIFO_FORCE_RECOMP_MINMAX;\ + type DIG_CLOCK_PATTERN + +#define SE_REG_FIELD_LIST_DCN2_0(type) \ + type DP_DSC_MODE;\ + type DP_DSC_SLICE_WIDTH;\ + type DP_DSC_BYTES_PER_PIXEL;\ + type DP_VBID6_LINE_REFERENCE;\ + type DP_VBID6_LINE_NUM;\ + type METADATA_ENGINE_EN;\ + type METADATA_HUBP_REQUESTOR_ID;\ + type METADATA_STREAM_TYPE;\ + type DP_SEC_METADATA_PACKET_ENABLE;\ + type DP_SEC_METADATA_PACKET_LINE_REFERENCE;\ + type DP_SEC_METADATA_PACKET_LINE;\ + type HDMI_METADATA_PACKET_ENABLE;\ + type HDMI_METADATA_PACKET_LINE_REFERENCE;\ + type HDMI_METADATA_PACKET_LINE;\ + type DOLBY_VISION_EN;\ + type DP_PIXEL_COMBINE;\ + type DP_SST_SDP_SPLITTING + +#define SE_REG_FIELD_LIST_DCN3_0(type) \ + type HDMI_GENERIC8_CONT;\ + type HDMI_GENERIC8_SEND;\ + type HDMI_GENERIC8_LINE;\ + type HDMI_GENERIC9_CONT;\ + type HDMI_GENERIC9_SEND;\ + type HDMI_GENERIC9_LINE;\ + type HDMI_GENERIC10_CONT;\ + type HDMI_GENERIC10_SEND;\ + type HDMI_GENERIC10_LINE;\ + type HDMI_GENERIC11_CONT;\ + type HDMI_GENERIC11_SEND;\ + type HDMI_GENERIC11_LINE;\ + type HDMI_GENERIC12_CONT;\ + type HDMI_GENERIC12_SEND;\ + type HDMI_GENERIC12_LINE;\ + type HDMI_GENERIC13_CONT;\ + type HDMI_GENERIC13_SEND;\ + type HDMI_GENERIC13_LINE;\ + type HDMI_GENERIC14_CONT;\ + type HDMI_GENERIC14_SEND;\ + type HDMI_GENERIC14_LINE;\ + type DP_SEC_GSP11_PPS;\ + type DP_SEC_GSP11_ENABLE;\ + type DP_SEC_GSP11_LINE_NUM + +#define SE_REG_FIELD_LIST_DCN3_1_COMMON(type) \ + type DIG_FIFO_OUTPUT_PIXEL_MODE;\ + type DP_PIXEL_PER_CYCLE_PROCESSING_MODE;\ + type DIG_SYMCLK_FE_ON;\ + type DIG_FIFO_READ_START_LEVEL;\ + type DIG_FIFO_ENABLE;\ + type DIG_FIFO_RESET;\ + type DIG_FIFO_RESET_DONE;\ + type PIXEL_ENCODING_TYPE;\ + type UNCOMPRESSED_PIXEL_FORMAT;\ + type UNCOMPRESSED_COMPONENT_DEPTH + +#define SE_REG_FIELD_LIST_DCN3_5_COMMON(type) \ + type DIG_FE_CLK_EN;\ + type DIG_FE_MODE;\ + type DIG_FE_SOFT_RESET;\ + type DIG_FE_ENABLE;\ + type DIG_FE_SYMCLK_FE_G_CLOCK_ON;\ + type DIG_FE_DISPCLK_G_CLOCK_ON;\ + type DIG_FE_SYMCLK_FE_G_AFMT_CLOCK_ON;\ + type DIG_FE_SYMCLK_FE_G_TMDS_CLOCK_ON;\ + type DIG_FE_SOCCLK_G_AFMT_CLOCK_ON;\ + type DIG_STREAM_LINK_TARGET + +#define SE_REG_FIELD_LIST_DCN4_01_COMMON(type) \ + type COMPRESSED_PIXEL_FORMAT;\ + type DP_VID_N_INTERVAL;\ + type DIG_FIFO_OUTPUT_PIXEL_PER_CYCLE;\ + type DP_STEER_FIFO_ENABLE +struct dcn10_stream_encoder_shift { + SE_REG_FIELD_LIST_DCN1_0(uint8_t); + uint8_t HDMI_ACP_SEND; + SE_REG_FIELD_LIST_DCN2_0(uint8_t); + SE_REG_FIELD_LIST_DCN3_0(uint8_t); + SE_REG_FIELD_LIST_DCN3_1_COMMON(uint8_t); + SE_REG_FIELD_LIST_DCN3_5_COMMON(uint8_t); + SE_REG_FIELD_LIST_DCN4_01_COMMON(uint32_t); +}; + +struct dcn10_stream_encoder_mask { + SE_REG_FIELD_LIST_DCN1_0(uint32_t); + uint32_t HDMI_ACP_SEND; + SE_REG_FIELD_LIST_DCN2_0(uint32_t); + SE_REG_FIELD_LIST_DCN3_0(uint32_t); + SE_REG_FIELD_LIST_DCN3_1_COMMON(uint32_t); + SE_REG_FIELD_LIST_DCN3_5_COMMON(uint32_t); + SE_REG_FIELD_LIST_DCN4_01_COMMON(uint32_t); +}; + +struct dcn10_stream_encoder { + struct stream_encoder base; + const struct dcn10_stream_enc_registers *regs; + const struct dcn10_stream_encoder_shift *se_shift; + const struct dcn10_stream_encoder_mask *se_mask; +}; + +void dcn10_stream_encoder_construct( + struct dcn10_stream_encoder *enc1, + struct dc_context *ctx, + struct dc_bios *bp, + enum engine_id eng_id, + const struct dcn10_stream_enc_registers *regs, + const struct dcn10_stream_encoder_shift *se_shift, + const struct dcn10_stream_encoder_mask *se_mask); + +void enc1_update_generic_info_packet( + struct dcn10_stream_encoder *enc1, + uint32_t packet_index, + const struct dc_info_packet *info_packet); + +void enc1_stream_encoder_dp_set_stream_attribute( + struct stream_encoder *enc, + struct dc_crtc_timing *crtc_timing, + enum dc_color_space output_color_space, + bool use_vsc_sdp_for_colorimetry, + uint32_t enable_sdp_splitting); + +void enc1_stream_encoder_hdmi_set_stream_attribute( + struct stream_encoder *enc, + struct dc_crtc_timing *crtc_timing, + int actual_pix_clk_khz, + bool enable_audio); + +void enc1_stream_encoder_dvi_set_stream_attribute( + struct stream_encoder *enc, + struct dc_crtc_timing *crtc_timing, + bool is_dual_link); + +void enc1_stream_encoder_set_throttled_vcp_size( + struct stream_encoder *enc, + struct fixed31_32 avg_time_slots_per_mtp); + +void enc1_stream_encoder_update_dp_info_packets( + struct stream_encoder *enc, + const struct encoder_info_frame *info_frame); + +void enc1_stream_encoder_send_immediate_sdp_message( + struct stream_encoder *enc, + const uint8_t *custom_sdp_message, + unsigned int sdp_message_size); + +void enc1_stream_encoder_stop_dp_info_packets( + struct stream_encoder *enc); + +void enc1_stream_encoder_dp_blank( + struct dc_link *link, + struct stream_encoder *enc); + +void enc1_stream_encoder_dp_unblank( + struct dc_link *link, + struct stream_encoder *enc, + const struct encoder_unblank_param *param); + +void enc1_setup_stereo_sync( + struct stream_encoder *enc, + int tg_inst, bool enable); + +void enc1_stream_encoder_set_avmute( + struct stream_encoder *enc, + bool enable); + +void enc1_se_audio_mute_control( + struct stream_encoder *enc, + bool mute); + +void enc1_se_dp_audio_setup( + struct stream_encoder *enc, + unsigned int az_inst, + struct audio_info *info); + +void enc1_se_dp_audio_enable( + struct stream_encoder *enc); + +void enc1_se_dp_audio_disable( + struct stream_encoder *enc); + +void enc1_se_hdmi_audio_setup( + struct stream_encoder *enc, + unsigned int az_inst, + struct audio_info *info, + struct audio_crtc_info *audio_crtc_info); + +void enc1_se_hdmi_audio_disable( + struct stream_encoder *enc); + +void enc1_dig_connect_to_otg( + struct stream_encoder *enc, + int tg_inst); + +unsigned int enc1_dig_source_otg( + struct stream_encoder *enc); + +void enc1_stream_encoder_set_stream_attribute_helper( + struct dcn10_stream_encoder *enc1, + struct dc_crtc_timing *crtc_timing); + +void enc1_se_enable_audio_clock( + struct stream_encoder *enc, + bool enable); + +void enc1_se_enable_dp_audio( + struct stream_encoder *enc); + +void get_audio_clock_info( + enum dc_color_depth color_depth, + uint32_t crtc_pixel_clock_100Hz, + uint32_t actual_pixel_clock_100Hz, + struct audio_clock_info *audio_clock_info); + +void enc1_reset_hdmi_stream_attribute( + struct stream_encoder *enc); + +bool enc1_stream_encoder_dp_get_pixel_format( + struct stream_encoder *enc, + enum dc_pixel_encoding *encoding, + enum dc_color_depth *depth); + +#endif /* __DC_STREAM_ENCODER_DCN10_H__ */ diff --git a/drivers/gpu/drm/amd/display/dc/dio/dcn20/dcn20_link_encoder.c b/drivers/gpu/drm/amd/display/dc/dio/dcn20/dcn20_link_encoder.c new file mode 100644 index 000000000000..51a57dae1811 --- /dev/null +++ b/drivers/gpu/drm/amd/display/dc/dio/dcn20/dcn20_link_encoder.c @@ -0,0 +1,502 @@ +/* + * Copyright 2012-15 Advanced Micro Devices, Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + * + * Authors: AMD + * + */ + +#include "reg_helper.h" + +#include "core_types.h" +#include "link_encoder.h" +#include "dcn20_link_encoder.h" +#include "stream_encoder.h" +#include "dc_bios_types.h" + +#include "gpio_service_interface.h" + +#define CTX \ + enc10->base.ctx +#define DC_LOGGER \ + enc10->base.ctx->logger + +#define REG(reg)\ + (enc10->link_regs->reg) + +#undef FN +#define FN(reg_name, field_name) \ + enc10->link_shift->field_name, enc10->link_mask->field_name + +#define IND_REG(index) \ + (enc10->link_regs->index) + +#ifndef MAX +#define MAX(X, Y) ((X) > (Y) ? (X) : (Y)) +#endif +#ifndef MIN +#define MIN(X, Y) ((X) < (Y) ? (X) : (Y)) +#endif + +static struct mpll_cfg dcn2_mpll_cfg[] = { + // RBR + { + .hdmimode_enable = 1, + .ref_range = 3, + .ref_clk_mpllb_div = 2, + .mpllb_ssc_en = 1, + .mpllb_div5_clk_en = 1, + .mpllb_multiplier = 226, + .mpllb_fracn_en = 1, + .mpllb_fracn_quot = 39321, + .mpllb_fracn_rem = 3, + .mpllb_fracn_den = 5, + .mpllb_ssc_up_spread = 0, + .mpllb_ssc_peak = 38221, + .mpllb_ssc_stepsize = 49314, + .mpllb_div_clk_en = 0, + .mpllb_div_multiplier = 0, + .mpllb_hdmi_div = 0, + .mpllb_tx_clk_div = 2, + .tx_vboost_lvl = 4, + .mpllb_pmix_en = 1, + .mpllb_word_div2_en = 0, + .mpllb_ana_v2i = 2, + .mpllb_ana_freq_vco = 2, + .mpllb_ana_cp_int = 7, + .mpllb_ana_cp_prop = 18, + .hdmi_pixel_clk_div = 0, + }, + // HBR + { + .hdmimode_enable = 1, + .ref_range = 3, + .ref_clk_mpllb_div = 2, + .mpllb_ssc_en = 1, + .mpllb_div5_clk_en = 1, + .mpllb_multiplier = 184, + .mpllb_fracn_en = 0, + .mpllb_fracn_quot = 0, + .mpllb_fracn_rem = 0, + .mpllb_fracn_den = 1, + .mpllb_ssc_up_spread = 0, + .mpllb_ssc_peak = 31850, + .mpllb_ssc_stepsize = 41095, + .mpllb_div_clk_en = 0, + .mpllb_div_multiplier = 0, + .mpllb_hdmi_div = 0, + .mpllb_tx_clk_div = 1, + .tx_vboost_lvl = 4, + .mpllb_pmix_en = 1, + .mpllb_word_div2_en = 0, + .mpllb_ana_v2i = 2, + .mpllb_ana_freq_vco = 3, + .mpllb_ana_cp_int = 7, + .mpllb_ana_cp_prop = 18, + .hdmi_pixel_clk_div = 0, + }, + //HBR2 + { + .hdmimode_enable = 1, + .ref_range = 3, + .ref_clk_mpllb_div = 2, + .mpllb_ssc_en = 1, + .mpllb_div5_clk_en = 1, + .mpllb_multiplier = 184, + .mpllb_fracn_en = 0, + .mpllb_fracn_quot = 0, + .mpllb_fracn_rem = 0, + .mpllb_fracn_den = 1, + .mpllb_ssc_up_spread = 0, + .mpllb_ssc_peak = 31850, + .mpllb_ssc_stepsize = 41095, + .mpllb_div_clk_en = 0, + .mpllb_div_multiplier = 0, + .mpllb_hdmi_div = 0, + .mpllb_tx_clk_div = 0, + .tx_vboost_lvl = 4, + .mpllb_pmix_en = 1, + .mpllb_word_div2_en = 0, + .mpllb_ana_v2i = 2, + .mpllb_ana_freq_vco = 3, + .mpllb_ana_cp_int = 7, + .mpllb_ana_cp_prop = 18, + .hdmi_pixel_clk_div = 0, + }, + //HBR3 + { + .hdmimode_enable = 1, + .ref_range = 3, + .ref_clk_mpllb_div = 2, + .mpllb_ssc_en = 1, + .mpllb_div5_clk_en = 1, + .mpllb_multiplier = 292, + .mpllb_fracn_en = 0, + .mpllb_fracn_quot = 0, + .mpllb_fracn_rem = 0, + .mpllb_fracn_den = 1, + .mpllb_ssc_up_spread = 0, + .mpllb_ssc_peak = 47776, + .mpllb_ssc_stepsize = 61642, + .mpllb_div_clk_en = 0, + .mpllb_div_multiplier = 0, + .mpllb_hdmi_div = 0, + .mpllb_tx_clk_div = 0, + .tx_vboost_lvl = 4, + .mpllb_pmix_en = 1, + .mpllb_word_div2_en = 0, + .mpllb_ana_v2i = 2, + .mpllb_ana_freq_vco = 0, + .mpllb_ana_cp_int = 7, + .mpllb_ana_cp_prop = 18, + .hdmi_pixel_clk_div = 0, + }, +}; + +void enc2_fec_set_enable(struct link_encoder *enc, bool enable) +{ + struct dcn10_link_encoder *enc10 = TO_DCN10_LINK_ENC(enc); + DC_LOG_DSC("%s FEC at link encoder inst %d", + enable ? "Enabling" : "Disabling", enc->id.enum_id); + REG_UPDATE(DP_DPHY_CNTL, DPHY_FEC_EN, enable); +} + +void enc2_fec_set_ready(struct link_encoder *enc, bool ready) +{ + struct dcn10_link_encoder *enc10 = TO_DCN10_LINK_ENC(enc); + + REG_UPDATE(DP_DPHY_CNTL, DPHY_FEC_READY_SHADOW, ready); +} + +bool enc2_fec_is_active(struct link_encoder *enc) +{ + uint32_t active = 0; + struct dcn10_link_encoder *enc10 = TO_DCN10_LINK_ENC(enc); + + REG_GET(DP_DPHY_CNTL, DPHY_FEC_ACTIVE_STATUS, &active); + + return (active != 0); +} + +/* this function reads dsc related register fields to be logged later in dcn10_log_hw_state + * into a dcn_dsc_state struct. + */ +void link_enc2_read_state(struct link_encoder *enc, struct link_enc_state *s) +{ + struct dcn10_link_encoder *enc10 = TO_DCN10_LINK_ENC(enc); + + REG_GET(DP_DPHY_CNTL, DPHY_FEC_EN, &s->dphy_fec_en); + REG_GET(DP_DPHY_CNTL, DPHY_FEC_READY_SHADOW, &s->dphy_fec_ready_shadow); + REG_GET(DP_DPHY_CNTL, DPHY_FEC_ACTIVE_STATUS, &s->dphy_fec_active_status); + REG_GET(DP_LINK_CNTL, DP_LINK_TRAINING_COMPLETE, &s->dp_link_training_complete); +} + +static bool update_cfg_data( + struct dcn10_link_encoder *enc10, + const struct dc_link_settings *link_settings, + struct dpcssys_phy_seq_cfg *cfg) +{ + int i; + + cfg->load_sram_fw = false; + + for (i = 0; i < link_settings->lane_count; i++) + cfg->lane_en[i] = true; + + switch (link_settings->link_rate) { + case LINK_RATE_LOW: + cfg->mpll_cfg = dcn2_mpll_cfg[0]; + break; + case LINK_RATE_HIGH: + cfg->mpll_cfg = dcn2_mpll_cfg[1]; + break; + case LINK_RATE_HIGH2: + cfg->mpll_cfg = dcn2_mpll_cfg[2]; + break; + case LINK_RATE_HIGH3: + cfg->mpll_cfg = dcn2_mpll_cfg[3]; + break; + default: + DC_LOG_ERROR("%s: No supported link rate found %X!\n", + __func__, link_settings->link_rate); + return false; + } + + return true; +} + +void dcn20_link_encoder_enable_dp_output( + struct link_encoder *enc, + const struct dc_link_settings *link_settings, + enum clock_source_id clock_source) +{ + struct dcn10_link_encoder *enc10 = TO_DCN10_LINK_ENC(enc); + struct dcn20_link_encoder *enc20 = (struct dcn20_link_encoder *) enc10; + struct dpcssys_phy_seq_cfg *cfg = &enc20->phy_seq_cfg; + + if (!enc->ctx->dc->debug.avoid_vbios_exec_table) { + dcn10_link_encoder_enable_dp_output(enc, link_settings, clock_source); + return; + } + + if (!update_cfg_data(enc10, link_settings, cfg)) + return; + + enc1_configure_encoder(enc10, link_settings); + + dcn10_link_encoder_setup(enc, SIGNAL_TYPE_DISPLAY_PORT); + +} + +void dcn20_link_encoder_get_max_link_cap(struct link_encoder *enc, + struct dc_link_settings *link_settings) +{ + struct dcn10_link_encoder *enc10 = TO_DCN10_LINK_ENC(enc); + uint32_t is_in_usb_c_dp4_mode = 0; + + dcn10_link_encoder_get_max_link_cap(enc, link_settings); + + /* in usb c dp2 mode, max lane count is 2 */ + if (enc->funcs->is_in_alt_mode && enc->funcs->is_in_alt_mode(enc)) { + REG_GET(RDPCSTX_PHY_CNTL6, RDPCS_PHY_DPALT_DP4, &is_in_usb_c_dp4_mode); + if (!is_in_usb_c_dp4_mode) + link_settings->lane_count = MIN(LANE_COUNT_TWO, link_settings->lane_count); + } + +} + +bool dcn20_link_encoder_is_in_alt_mode(struct link_encoder *enc) +{ + struct dcn10_link_encoder *enc10 = TO_DCN10_LINK_ENC(enc); + uint32_t dp_alt_mode_disable = 0; + bool is_usb_c_alt_mode = false; + + if (enc->features.flags.bits.DP_IS_USB_C) { + /* if value == 1 alt mode is disabled, otherwise it is enabled */ + REG_GET(RDPCSTX_PHY_CNTL6, RDPCS_PHY_DPALT_DISABLE, &dp_alt_mode_disable); + is_usb_c_alt_mode = (dp_alt_mode_disable == 0); + } + + return is_usb_c_alt_mode; +} + +#define AUX_REG(reg)\ + (enc10->aux_regs->reg) + +#define AUX_REG_READ(reg_name) \ + dm_read_reg(CTX, AUX_REG(reg_name)) + +#define AUX_REG_WRITE(reg_name, val) \ + dm_write_reg(CTX, AUX_REG(reg_name), val) +void enc2_hw_init(struct link_encoder *enc) +{ + struct dcn10_link_encoder *enc10 = TO_DCN10_LINK_ENC(enc); +/* + 00 - DP_AUX_DPHY_RX_DETECTION_THRESHOLD__1to2 : 1/2 + 01 - DP_AUX_DPHY_RX_DETECTION_THRESHOLD__3to4 : 3/4 + 02 - DP_AUX_DPHY_RX_DETECTION_THRESHOLD__7to8 : 7/8 + 03 - DP_AUX_DPHY_RX_DETECTION_THRESHOLD__15to16 : 15/16 + 04 - DP_AUX_DPHY_RX_DETECTION_THRESHOLD__31to32 : 31/32 + 05 - DP_AUX_DPHY_RX_DETECTION_THRESHOLD__63to64 : 63/64 + 06 - DP_AUX_DPHY_RX_DETECTION_THRESHOLD__127to128 : 127/128 + 07 - DP_AUX_DPHY_RX_DETECTION_THRESHOLD__255to256 : 255/256 +*/ + +/* + AUX_REG_UPDATE_5(AUX_DPHY_RX_CONTROL0, + AUX_RX_START_WINDOW = 1 [6:4] + AUX_RX_RECEIVE_WINDOW = 1 default is 2 [10:8] + AUX_RX_HALF_SYM_DETECT_LEN = 1 [13:12] default is 1 + AUX_RX_TRANSITION_FILTER_EN = 1 [16] default is 1 + AUX_RX_ALLOW_BELOW_THRESHOLD_PHASE_DETECT [17] is 0 default is 0 + AUX_RX_ALLOW_BELOW_THRESHOLD_START [18] is 1 default is 1 + AUX_RX_ALLOW_BELOW_THRESHOLD_STOP [19] is 1 default is 1 + AUX_RX_PHASE_DETECT_LEN, [21,20] = 0x3 default is 3 + AUX_RX_DETECTION_THRESHOLD [30:28] = 1 +*/ + if (enc->ctx->dc_bios->golden_table.dc_golden_table_ver > 0) { + AUX_REG_WRITE(AUX_DPHY_RX_CONTROL0, enc->ctx->dc_bios->golden_table.aux_dphy_rx_control0_val); + + AUX_REG_WRITE(AUX_DPHY_TX_CONTROL, enc->ctx->dc_bios->golden_table.aux_dphy_tx_control_val); + + AUX_REG_WRITE(AUX_DPHY_RX_CONTROL1, enc->ctx->dc_bios->golden_table.aux_dphy_rx_control1_val); + } else { + AUX_REG_WRITE(AUX_DPHY_RX_CONTROL0, 0x103d1110); + + AUX_REG_WRITE(AUX_DPHY_TX_CONTROL, 0x21c7a); + } + + //AUX_DPHY_TX_REF_CONTROL'AUX_TX_REF_DIV HW default is 0x32; + // Set AUX_TX_REF_DIV Divider to generate 2 MHz reference from refclk + // 27MHz -> 0xd + // 100MHz -> 0x32 + // 48MHz -> 0x18 + + // Set TMDS_CTL0 to 1. This is a legacy setting. + REG_UPDATE(TMDS_CTL_BITS, TMDS_CTL0, 1); + + dcn10_aux_initialize(enc10); +} + +static const struct link_encoder_funcs dcn20_link_enc_funcs = { + .read_state = link_enc2_read_state, + .validate_output_with_stream = + dcn10_link_encoder_validate_output_with_stream, + .hw_init = enc2_hw_init, + .setup = dcn10_link_encoder_setup, + .enable_tmds_output = dcn10_link_encoder_enable_tmds_output_with_clk_pattern_wa, + .enable_dp_output = dcn20_link_encoder_enable_dp_output, + .enable_dp_mst_output = dcn10_link_encoder_enable_dp_mst_output, + .disable_output = dcn10_link_encoder_disable_output, + .dp_set_lane_settings = dcn10_link_encoder_dp_set_lane_settings, + .dp_set_phy_pattern = dcn10_link_encoder_dp_set_phy_pattern, + .update_mst_stream_allocation_table = + dcn10_link_encoder_update_mst_stream_allocation_table, + .psr_program_dp_dphy_fast_training = + dcn10_psr_program_dp_dphy_fast_training, + .psr_program_secondary_packet = dcn10_psr_program_secondary_packet, + .connect_dig_be_to_fe = dcn10_link_encoder_connect_dig_be_to_fe, + .enable_hpd = dcn10_link_encoder_enable_hpd, + .disable_hpd = dcn10_link_encoder_disable_hpd, + .is_dig_enabled = dcn10_is_dig_enabled, + .destroy = dcn10_link_encoder_destroy, + .fec_set_enable = enc2_fec_set_enable, + .fec_set_ready = enc2_fec_set_ready, + .fec_is_active = enc2_fec_is_active, + .get_dig_mode = dcn10_get_dig_mode, + .get_dig_frontend = dcn10_get_dig_frontend, + .is_in_alt_mode = dcn20_link_encoder_is_in_alt_mode, + .get_max_link_cap = dcn20_link_encoder_get_max_link_cap, +}; + +void dcn20_link_encoder_construct( + struct dcn20_link_encoder *enc20, + const struct encoder_init_data *init_data, + const struct encoder_feature_support *enc_features, + const struct dcn10_link_enc_registers *link_regs, + const struct dcn10_link_enc_aux_registers *aux_regs, + const struct dcn10_link_enc_hpd_registers *hpd_regs, + const struct dcn10_link_enc_shift *link_shift, + const struct dcn10_link_enc_mask *link_mask) +{ + struct bp_encoder_cap_info bp_cap_info = {0}; + const struct dc_vbios_funcs *bp_funcs = init_data->ctx->dc_bios->funcs; + enum bp_result result = BP_RESULT_OK; + struct dcn10_link_encoder *enc10 = &enc20->enc10; + + enc10->base.funcs = &dcn20_link_enc_funcs; + enc10->base.ctx = init_data->ctx; + enc10->base.id = init_data->encoder; + + enc10->base.hpd_source = init_data->hpd_source; + enc10->base.connector = init_data->connector; + + enc10->base.preferred_engine = ENGINE_ID_UNKNOWN; + + enc10->base.features = *enc_features; + + enc10->base.transmitter = init_data->transmitter; + + /* set the flag to indicate whether driver poll the I2C data pin + * while doing the DP sink detect + */ + +/* if (dal_adapter_service_is_feature_supported(as, + FEATURE_DP_SINK_DETECT_POLL_DATA_PIN)) + enc10->base.features.flags.bits. + DP_SINK_DETECT_POLL_DATA_PIN = true;*/ + + enc10->base.output_signals = + SIGNAL_TYPE_DVI_SINGLE_LINK | + SIGNAL_TYPE_DVI_DUAL_LINK | + SIGNAL_TYPE_LVDS | + SIGNAL_TYPE_DISPLAY_PORT | + SIGNAL_TYPE_DISPLAY_PORT_MST | + SIGNAL_TYPE_EDP | + SIGNAL_TYPE_HDMI_TYPE_A; + + /* For DCE 8.0 and 8.1, by design, UNIPHY is hardwired to DIG_BE. + * SW always assign DIG_FE 1:1 mapped to DIG_FE for non-MST UNIPHY. + * SW assign DIG_FE to non-MST UNIPHY first and MST last. So prefer + * DIG is per UNIPHY and used by SST DP, eDP, HDMI, DVI and LVDS. + * Prefer DIG assignment is decided by board design. + * For DCE 8.0, there are only max 6 UNIPHYs, we assume board design + * and VBIOS will filter out 7 UNIPHY for DCE 8.0. + * By this, adding DIGG should not hurt DCE 8.0. + * This will let DCE 8.1 share DCE 8.0 as much as possible + */ + + enc10->link_regs = link_regs; + enc10->aux_regs = aux_regs; + enc10->hpd_regs = hpd_regs; + enc10->link_shift = link_shift; + enc10->link_mask = link_mask; + + switch (enc10->base.transmitter) { + case TRANSMITTER_UNIPHY_A: + enc10->base.preferred_engine = ENGINE_ID_DIGA; + break; + case TRANSMITTER_UNIPHY_B: + enc10->base.preferred_engine = ENGINE_ID_DIGB; + break; + case TRANSMITTER_UNIPHY_C: + enc10->base.preferred_engine = ENGINE_ID_DIGC; + break; + case TRANSMITTER_UNIPHY_D: + enc10->base.preferred_engine = ENGINE_ID_DIGD; + break; + case TRANSMITTER_UNIPHY_E: + enc10->base.preferred_engine = ENGINE_ID_DIGE; + break; + case TRANSMITTER_UNIPHY_F: + enc10->base.preferred_engine = ENGINE_ID_DIGF; + break; + case TRANSMITTER_UNIPHY_G: + enc10->base.preferred_engine = ENGINE_ID_DIGG; + break; + default: + ASSERT_CRITICAL(false); + enc10->base.preferred_engine = ENGINE_ID_UNKNOWN; + } + + /* default to one to mirror Windows behavior */ + enc10->base.features.flags.bits.HDMI_6GB_EN = 1; + + result = bp_funcs->get_encoder_cap_info(enc10->base.ctx->dc_bios, + enc10->base.id, &bp_cap_info); + + /* Override features with DCE-specific values */ + if (result == BP_RESULT_OK) { + enc10->base.features.flags.bits.IS_HBR2_CAPABLE = + bp_cap_info.DP_HBR2_EN; + enc10->base.features.flags.bits.IS_HBR3_CAPABLE = + bp_cap_info.DP_HBR3_EN; + enc10->base.features.flags.bits.HDMI_6GB_EN = bp_cap_info.HDMI_6GB_EN; + enc10->base.features.flags.bits.DP_IS_USB_C = + bp_cap_info.DP_IS_USB_C; + } else { + DC_LOG_WARNING("%s: Failed to get encoder_cap_info from VBIOS with error code %d!\n", + __func__, + result); + } + if (enc10->base.ctx->dc->debug.hdmi20_disable) { + enc10->base.features.flags.bits.HDMI_6GB_EN = 0; + } +} diff --git a/drivers/gpu/drm/amd/display/dc/dio/dcn20/dcn20_link_encoder.h b/drivers/gpu/drm/amd/display/dc/dio/dcn20/dcn20_link_encoder.h new file mode 100644 index 000000000000..762c579fcb44 --- /dev/null +++ b/drivers/gpu/drm/amd/display/dc/dio/dcn20/dcn20_link_encoder.h @@ -0,0 +1,366 @@ +/* + * Copyright 2012-15 Advanced Micro Devices, Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + * + * Authors: AMD + * + */ + +#ifndef __DC_LINK_ENCODER__DCN20_H__ +#define __DC_LINK_ENCODER__DCN20_H__ + +#include "dcn10/dcn10_link_encoder.h" + +#define DCN2_AUX_REG_LIST(id)\ + AUX_REG_LIST(id), \ + SRI(AUX_DPHY_TX_CONTROL, DP_AUX, id) + +#define UNIPHY_MASK_SH_LIST(mask_sh)\ + LE_SF(SYMCLKA_CLOCK_ENABLE, SYMCLKA_CLOCK_ENABLE, mask_sh),\ + LE_SF(UNIPHYA_CHANNEL_XBAR_CNTL, UNIPHY_LINK_ENABLE, mask_sh),\ + LE_SF(UNIPHYA_CHANNEL_XBAR_CNTL, UNIPHY_CHANNEL0_XBAR_SOURCE, mask_sh),\ + LE_SF(UNIPHYA_CHANNEL_XBAR_CNTL, UNIPHY_CHANNEL1_XBAR_SOURCE, mask_sh),\ + LE_SF(UNIPHYA_CHANNEL_XBAR_CNTL, UNIPHY_CHANNEL2_XBAR_SOURCE, mask_sh),\ + LE_SF(UNIPHYA_CHANNEL_XBAR_CNTL, UNIPHY_CHANNEL3_XBAR_SOURCE, mask_sh) + +#define DPCS_MASK_SH_LIST(mask_sh)\ + LE_SF(RDPCSTX0_RDPCSTX_PHY_CNTL3, RDPCS_PHY_DP_TX0_CLK_RDY, mask_sh),\ + LE_SF(RDPCSTX0_RDPCSTX_PHY_CNTL3, RDPCS_PHY_DP_TX0_DATA_EN, mask_sh),\ + LE_SF(RDPCSTX0_RDPCSTX_PHY_CNTL3, RDPCS_PHY_DP_TX1_CLK_RDY, mask_sh),\ + LE_SF(RDPCSTX0_RDPCSTX_PHY_CNTL3, RDPCS_PHY_DP_TX1_DATA_EN, mask_sh),\ + LE_SF(RDPCSTX0_RDPCSTX_PHY_CNTL3, RDPCS_PHY_DP_TX2_CLK_RDY, mask_sh),\ + LE_SF(RDPCSTX0_RDPCSTX_PHY_CNTL3, RDPCS_PHY_DP_TX2_DATA_EN, mask_sh),\ + LE_SF(RDPCSTX0_RDPCSTX_PHY_CNTL3, RDPCS_PHY_DP_TX3_CLK_RDY, mask_sh),\ + LE_SF(RDPCSTX0_RDPCSTX_PHY_CNTL3, RDPCS_PHY_DP_TX3_DATA_EN, mask_sh),\ + LE_SF(RDPCSTX0_RDPCSTX_PHY_CNTL4, RDPCS_PHY_DP_TX0_TERM_CTRL, mask_sh),\ + LE_SF(RDPCSTX0_RDPCSTX_PHY_CNTL4, RDPCS_PHY_DP_TX1_TERM_CTRL, mask_sh),\ + LE_SF(RDPCSTX0_RDPCSTX_PHY_CNTL4, RDPCS_PHY_DP_TX2_TERM_CTRL, mask_sh),\ + LE_SF(RDPCSTX0_RDPCSTX_PHY_CNTL4, RDPCS_PHY_DP_TX3_TERM_CTRL, mask_sh),\ + LE_SF(RDPCSTX0_RDPCSTX_PHY_CNTL11, RDPCS_PHY_DP_MPLLB_MULTIPLIER, mask_sh),\ + LE_SF(RDPCSTX0_RDPCSTX_PHY_CNTL5, RDPCS_PHY_DP_TX0_WIDTH, mask_sh),\ + LE_SF(RDPCSTX0_RDPCSTX_PHY_CNTL5, RDPCS_PHY_DP_TX0_RATE, mask_sh),\ + LE_SF(RDPCSTX0_RDPCSTX_PHY_CNTL5, RDPCS_PHY_DP_TX1_WIDTH, mask_sh),\ + LE_SF(RDPCSTX0_RDPCSTX_PHY_CNTL5, RDPCS_PHY_DP_TX1_RATE, mask_sh),\ + LE_SF(RDPCSTX0_RDPCSTX_PHY_CNTL6, RDPCS_PHY_DP_TX2_PSTATE, mask_sh),\ + LE_SF(RDPCSTX0_RDPCSTX_PHY_CNTL6, RDPCS_PHY_DP_TX3_PSTATE, mask_sh),\ + LE_SF(RDPCSTX0_RDPCSTX_PHY_CNTL6, RDPCS_PHY_DP_TX2_MPLL_EN, mask_sh),\ + LE_SF(RDPCSTX0_RDPCSTX_PHY_CNTL6, RDPCS_PHY_DP_TX3_MPLL_EN, mask_sh),\ + LE_SF(RDPCSTX0_RDPCSTX_PHY_CNTL7, RDPCS_PHY_DP_MPLLB_FRACN_QUOT, mask_sh),\ + LE_SF(RDPCSTX0_RDPCSTX_PHY_CNTL7, RDPCS_PHY_DP_MPLLB_FRACN_DEN, mask_sh),\ + LE_SF(RDPCSTX0_RDPCSTX_PHY_CNTL8, RDPCS_PHY_DP_MPLLB_SSC_PEAK, mask_sh),\ + LE_SF(RDPCSTX0_RDPCSTX_PHY_CNTL9, RDPCS_PHY_DP_MPLLB_SSC_UP_SPREAD, mask_sh),\ + LE_SF(RDPCSTX0_RDPCSTX_PHY_CNTL9, RDPCS_PHY_DP_MPLLB_SSC_STEPSIZE, mask_sh),\ + LE_SF(RDPCSTX0_RDPCSTX_PHY_CNTL10, RDPCS_PHY_DP_MPLLB_FRACN_REM, mask_sh),\ + LE_SF(RDPCSTX0_RDPCSTX_PHY_CNTL11, RDPCS_PHY_DP_REF_CLK_MPLLB_DIV, mask_sh),\ + LE_SF(RDPCSTX0_RDPCSTX_PHY_CNTL11, RDPCS_PHY_HDMI_MPLLB_HDMI_DIV, mask_sh),\ + LE_SF(RDPCSTX0_RDPCSTX_PHY_CNTL12, RDPCS_PHY_DP_MPLLB_SSC_EN, mask_sh),\ + LE_SF(RDPCSTX0_RDPCSTX_PHY_CNTL12, RDPCS_PHY_DP_MPLLB_DIV5_CLK_EN, mask_sh),\ + LE_SF(RDPCSTX0_RDPCSTX_PHY_CNTL12, RDPCS_PHY_DP_MPLLB_TX_CLK_DIV, mask_sh),\ + LE_SF(RDPCSTX0_RDPCSTX_PHY_CNTL12, RDPCS_PHY_DP_MPLLB_WORD_DIV2_EN, mask_sh),\ + LE_SF(RDPCSTX0_RDPCSTX_PHY_CNTL12, RDPCS_PHY_DP_MPLLB_STATE, mask_sh),\ + LE_SF(RDPCSTX0_RDPCSTX_PHY_CNTL13, RDPCS_PHY_DP_MPLLB_DIV_CLK_EN, mask_sh),\ + LE_SF(RDPCSTX0_RDPCSTX_PHY_CNTL13, RDPCS_PHY_DP_MPLLB_DIV_MULTIPLIER, mask_sh),\ + LE_SF(RDPCSTX0_RDPCSTX_PHY_CNTL14, RDPCS_PHY_DP_MPLLB_FRACN_EN, mask_sh),\ + LE_SF(RDPCSTX0_RDPCSTX_PHY_CNTL14, RDPCS_PHY_DP_MPLLB_PMIX_EN, mask_sh),\ + LE_SF(RDPCSTX0_RDPCSTX_CNTL, RDPCS_TX_FIFO_LANE0_EN, mask_sh),\ + LE_SF(RDPCSTX0_RDPCSTX_CNTL, RDPCS_TX_FIFO_LANE1_EN, mask_sh),\ + LE_SF(RDPCSTX0_RDPCSTX_CNTL, RDPCS_TX_FIFO_LANE2_EN, mask_sh),\ + LE_SF(RDPCSTX0_RDPCSTX_CNTL, RDPCS_TX_FIFO_LANE3_EN, mask_sh),\ + LE_SF(RDPCSTX0_RDPCSTX_CNTL, RDPCS_TX_FIFO_EN, mask_sh),\ + LE_SF(RDPCSTX0_RDPCSTX_CNTL, RDPCS_TX_FIFO_RD_START_DELAY, mask_sh),\ + LE_SF(RDPCSTX0_RDPCSTX_CLOCK_CNTL, RDPCS_EXT_REFCLK_EN, mask_sh),\ + LE_SF(RDPCSTX0_RDPCSTX_CLOCK_CNTL, RDPCS_SRAMCLK_BYPASS, mask_sh),\ + LE_SF(RDPCSTX0_RDPCSTX_CLOCK_CNTL, RDPCS_SRAMCLK_EN, mask_sh),\ + LE_SF(RDPCSTX0_RDPCSTX_CLOCK_CNTL, RDPCS_SRAMCLK_CLOCK_ON, mask_sh),\ + LE_SF(RDPCSTX0_RDPCSTX_CLOCK_CNTL, RDPCS_SYMCLK_DIV2_CLOCK_ON, mask_sh),\ + LE_SF(RDPCSTX0_RDPCSTX_CLOCK_CNTL, RDPCS_SYMCLK_DIV2_GATE_DIS, mask_sh),\ + LE_SF(RDPCSTX0_RDPCSTX_CLOCK_CNTL, RDPCS_SYMCLK_DIV2_EN, mask_sh),\ + LE_SF(RDPCSTX0_RDPCSTX_PHY_CNTL3, RDPCS_PHY_DP_TX0_DISABLE, mask_sh),\ + LE_SF(RDPCSTX0_RDPCSTX_PHY_CNTL3, RDPCS_PHY_DP_TX1_DISABLE, mask_sh),\ + LE_SF(RDPCSTX0_RDPCSTX_PHY_CNTL3, RDPCS_PHY_DP_TX2_DISABLE, mask_sh),\ + LE_SF(RDPCSTX0_RDPCSTX_PHY_CNTL3, RDPCS_PHY_DP_TX3_DISABLE, mask_sh),\ + LE_SF(RDPCSTX0_RDPCSTX_PHY_CNTL3, RDPCS_PHY_DP_TX0_REQ, mask_sh),\ + LE_SF(RDPCSTX0_RDPCSTX_PHY_CNTL3, RDPCS_PHY_DP_TX1_REQ, mask_sh),\ + LE_SF(RDPCSTX0_RDPCSTX_PHY_CNTL3, RDPCS_PHY_DP_TX2_REQ, mask_sh),\ + LE_SF(RDPCSTX0_RDPCSTX_PHY_CNTL3, RDPCS_PHY_DP_TX3_REQ, mask_sh),\ + LE_SF(RDPCSTX0_RDPCSTX_PHY_CNTL3, RDPCS_PHY_DP_TX0_ACK, mask_sh),\ + LE_SF(RDPCSTX0_RDPCSTX_PHY_CNTL3, RDPCS_PHY_DP_TX1_ACK, mask_sh),\ + LE_SF(RDPCSTX0_RDPCSTX_PHY_CNTL3, RDPCS_PHY_DP_TX2_ACK, mask_sh),\ + LE_SF(RDPCSTX0_RDPCSTX_PHY_CNTL3, RDPCS_PHY_DP_TX3_ACK, mask_sh),\ + LE_SF(RDPCSTX0_RDPCSTX_PHY_CNTL3, RDPCS_PHY_DP_TX0_RESET, mask_sh),\ + LE_SF(RDPCSTX0_RDPCSTX_PHY_CNTL3, RDPCS_PHY_DP_TX1_RESET, mask_sh),\ + LE_SF(RDPCSTX0_RDPCSTX_PHY_CNTL3, RDPCS_PHY_DP_TX2_RESET, mask_sh),\ + LE_SF(RDPCSTX0_RDPCSTX_PHY_CNTL3, RDPCS_PHY_DP_TX3_RESET, mask_sh),\ + LE_SF(RDPCSTX0_RDPCSTX_PHY_CNTL0, RDPCS_PHY_RESET, mask_sh),\ + LE_SF(RDPCSTX0_RDPCSTX_PHY_CNTL0, RDPCS_PHY_CR_MUX_SEL, mask_sh),\ + LE_SF(RDPCSTX0_RDPCSTX_PHY_CNTL0, RDPCS_PHY_REF_RANGE, mask_sh),\ + LE_SF(RDPCSTX0_RDPCSTX_PHY_CNTL0, RDPCS_SRAM_BYPASS, mask_sh),\ + LE_SF(RDPCSTX0_RDPCSTX_PHY_CNTL0, RDPCS_SRAM_EXT_LD_DONE, mask_sh),\ + LE_SF(RDPCSTX0_RDPCSTX_PHY_CNTL0, RDPCS_PHY_HDMIMODE_ENABLE, mask_sh),\ + LE_SF(RDPCSTX0_RDPCSTX_PHY_CNTL0, RDPCS_SRAM_INIT_DONE, mask_sh),\ + LE_SF(RDPCSTX0_RDPCSTX_PHY_CNTL2, RDPCS_PHY_DP4_POR, mask_sh),\ + LE_SF(RDPCSTX0_RDPCSTX_PLL_UPDATE_DATA, RDPCS_PLL_UPDATE_DATA, mask_sh),\ + LE_SF(RDPCSTX0_RDPCSTX_INTERRUPT_CONTROL, RDPCS_REG_FIFO_ERROR_MASK, mask_sh),\ + LE_SF(RDPCSTX0_RDPCSTX_INTERRUPT_CONTROL, RDPCS_TX_FIFO_ERROR_MASK, mask_sh),\ + LE_SF(RDPCSTX0_RDPCSTX_INTERRUPT_CONTROL, RDPCS_DPALT_DISABLE_TOGGLE_MASK, mask_sh),\ + LE_SF(RDPCSTX0_RDPCSTX_INTERRUPT_CONTROL, RDPCS_DPALT_4LANE_TOGGLE_MASK, mask_sh),\ + LE_SF(RDPCSTX0_RDPCS_TX_CR_ADDR, RDPCS_TX_CR_ADDR, mask_sh),\ + LE_SF(RDPCSTX0_RDPCS_TX_CR_DATA, RDPCS_TX_CR_DATA, mask_sh),\ + LE_SF(RDPCSTX0_RDPCSTX_PHY_FUSE0, RDPCS_PHY_DP_MPLLB_V2I, mask_sh),\ + LE_SF(RDPCSTX0_RDPCSTX_PHY_FUSE0, RDPCS_PHY_DP_TX0_EQ_MAIN, mask_sh),\ + LE_SF(RDPCSTX0_RDPCSTX_PHY_FUSE0, RDPCS_PHY_DP_TX0_EQ_PRE, mask_sh),\ + LE_SF(RDPCSTX0_RDPCSTX_PHY_FUSE0, RDPCS_PHY_DP_TX0_EQ_POST, mask_sh),\ + LE_SF(RDPCSTX0_RDPCSTX_PHY_FUSE0, RDPCS_PHY_DP_MPLLB_FREQ_VCO, mask_sh),\ + LE_SF(RDPCSTX0_RDPCSTX_PHY_FUSE1, RDPCS_PHY_DP_MPLLB_CP_INT, mask_sh),\ + LE_SF(RDPCSTX0_RDPCSTX_PHY_FUSE1, RDPCS_PHY_DP_MPLLB_CP_PROP, mask_sh),\ + LE_SF(RDPCSTX0_RDPCSTX_PHY_FUSE1, RDPCS_PHY_DP_TX1_EQ_MAIN, mask_sh),\ + LE_SF(RDPCSTX0_RDPCSTX_PHY_FUSE1, RDPCS_PHY_DP_TX1_EQ_PRE, mask_sh),\ + LE_SF(RDPCSTX0_RDPCSTX_PHY_FUSE1, RDPCS_PHY_DP_TX1_EQ_POST, mask_sh),\ + LE_SF(RDPCSTX0_RDPCSTX_PHY_FUSE2, RDPCS_PHY_DP_TX2_EQ_MAIN, mask_sh),\ + LE_SF(RDPCSTX0_RDPCSTX_PHY_FUSE2, RDPCS_PHY_DP_TX2_EQ_PRE, mask_sh),\ + LE_SF(RDPCSTX0_RDPCSTX_PHY_FUSE2, RDPCS_PHY_DP_TX2_EQ_POST, mask_sh),\ + LE_SF(RDPCSTX0_RDPCSTX_PHY_FUSE3, RDPCS_PHY_DP_TX3_EQ_MAIN, mask_sh),\ + LE_SF(RDPCSTX0_RDPCSTX_PHY_FUSE3, RDPCS_PHY_DCO_FINETUNE, mask_sh),\ + LE_SF(RDPCSTX0_RDPCSTX_PHY_FUSE3, RDPCS_PHY_DCO_RANGE, mask_sh),\ + LE_SF(RDPCSTX0_RDPCSTX_PHY_FUSE3, RDPCS_PHY_DP_TX3_EQ_PRE, mask_sh),\ + LE_SF(RDPCSTX0_RDPCSTX_PHY_FUSE3, RDPCS_PHY_DP_TX3_EQ_POST, mask_sh),\ + LE_SF(DPCSTX0_DPCSTX_TX_CLOCK_CNTL, DPCS_SYMCLK_CLOCK_ON, mask_sh),\ + LE_SF(DPCSTX0_DPCSTX_TX_CLOCK_CNTL, DPCS_SYMCLK_GATE_DIS, mask_sh),\ + LE_SF(DPCSTX0_DPCSTX_TX_CLOCK_CNTL, DPCS_SYMCLK_EN, mask_sh),\ + LE_SF(DPCSTX0_DPCSTX_TX_CNTL, DPCS_TX_DATA_SWAP, mask_sh),\ + LE_SF(DPCSTX0_DPCSTX_TX_CNTL, DPCS_TX_DATA_ORDER_INVERT, mask_sh),\ + LE_SF(DPCSTX0_DPCSTX_TX_CNTL, DPCS_TX_FIFO_EN, mask_sh),\ + LE_SF(DPCSTX0_DPCSTX_TX_CNTL, DPCS_TX_FIFO_RD_START_DELAY, mask_sh),\ + LE_SF(DPCSTX0_DPCSTX_DEBUG_CONFIG, DPCS_DBG_CBUS_DIS, mask_sh) + +#define DPCS_DCN2_MASK_SH_LIST(mask_sh)\ + DPCS_MASK_SH_LIST(mask_sh),\ + LE_SF(RDPCSTX0_RDPCSTX_PHY_RX_LD_VAL, RDPCS_PHY_RX_REF_LD_VAL, mask_sh),\ + LE_SF(RDPCSTX0_RDPCSTX_PHY_RX_LD_VAL, RDPCS_PHY_RX_VCO_LD_VAL, mask_sh),\ + LE_SF(RDPCSTX0_RDPCSTX_PHY_CNTL6, RDPCS_PHY_DPALT_DISABLE_ACK, mask_sh),\ + LE_SF(RDPCSTX0_RDPCSTX_PHY_CNTL6, RDPCS_PHY_DP_TX0_PSTATE, mask_sh),\ + LE_SF(RDPCSTX0_RDPCSTX_PHY_CNTL6, RDPCS_PHY_DP_TX1_PSTATE, mask_sh),\ + LE_SF(RDPCSTX0_RDPCSTX_PHY_CNTL6, RDPCS_PHY_DP_TX0_MPLL_EN, mask_sh),\ + LE_SF(RDPCSTX0_RDPCSTX_PHY_CNTL6, RDPCS_PHY_DP_TX1_MPLL_EN, mask_sh),\ + LE_SF(RDPCSTX0_RDPCSTX_PHY_CNTL6, RDPCS_PHY_DP_REF_CLK_EN, mask_sh),\ + LE_SF(RDPCSTX0_RDPCSTX_PHY_CNTL5, RDPCS_PHY_DP_TX2_WIDTH, mask_sh),\ + LE_SF(RDPCSTX0_RDPCSTX_PHY_CNTL5, RDPCS_PHY_DP_TX2_RATE, mask_sh),\ + LE_SF(RDPCSTX0_RDPCSTX_PHY_CNTL5, RDPCS_PHY_DP_TX3_WIDTH, mask_sh),\ + LE_SF(RDPCSTX0_RDPCSTX_PHY_CNTL5, RDPCS_PHY_DP_TX3_RATE, mask_sh),\ + LE_SF(DCIO_SOFT_RESET, UNIPHYA_SOFT_RESET, mask_sh),\ + LE_SF(DCIO_SOFT_RESET, UNIPHYB_SOFT_RESET, mask_sh),\ + LE_SF(DCIO_SOFT_RESET, UNIPHYC_SOFT_RESET, mask_sh),\ + LE_SF(DCIO_SOFT_RESET, UNIPHYD_SOFT_RESET, mask_sh),\ + LE_SF(DCIO_SOFT_RESET, UNIPHYE_SOFT_RESET, mask_sh),\ + LE_SF(RDPCSTX0_RDPCSTX_PHY_CNTL6, RDPCS_PHY_DPALT_DP4, mask_sh),\ + LE_SF(RDPCSTX0_RDPCSTX_PHY_CNTL6, RDPCS_PHY_DPALT_DISABLE, mask_sh) + +#define LINK_ENCODER_MASK_SH_LIST_DCN20(mask_sh)\ + LINK_ENCODER_MASK_SH_LIST_DCN10(mask_sh),\ + LE_SF(DP0_DP_DPHY_CNTL, DPHY_FEC_EN, mask_sh),\ + LE_SF(DP0_DP_DPHY_CNTL, DPHY_FEC_READY_SHADOW, mask_sh),\ + LE_SF(DP0_DP_DPHY_CNTL, DPHY_FEC_ACTIVE_STATUS, mask_sh),\ + LE_SF(DIG0_DIG_LANE_ENABLE, DIG_LANE0EN, mask_sh),\ + LE_SF(DIG0_DIG_LANE_ENABLE, DIG_LANE1EN, mask_sh),\ + LE_SF(DIG0_DIG_LANE_ENABLE, DIG_LANE2EN, mask_sh),\ + LE_SF(DIG0_DIG_LANE_ENABLE, DIG_LANE3EN, mask_sh),\ + LE_SF(DIG0_DIG_LANE_ENABLE, DIG_CLK_EN, mask_sh),\ + LE_SF(DIG0_TMDS_CTL_BITS, TMDS_CTL0, mask_sh), \ + UNIPHY_MASK_SH_LIST(mask_sh),\ + LE_SF(DP_AUX0_AUX_DPHY_RX_CONTROL0, AUX_RX_START_WINDOW, mask_sh),\ + LE_SF(DP_AUX0_AUX_DPHY_RX_CONTROL0, AUX_RX_HALF_SYM_DETECT_LEN, mask_sh),\ + LE_SF(DP_AUX0_AUX_DPHY_RX_CONTROL0, AUX_RX_TRANSITION_FILTER_EN, mask_sh),\ + LE_SF(DP_AUX0_AUX_DPHY_RX_CONTROL0, AUX_RX_ALLOW_BELOW_THRESHOLD_PHASE_DETECT, mask_sh),\ + LE_SF(DP_AUX0_AUX_DPHY_RX_CONTROL0, AUX_RX_ALLOW_BELOW_THRESHOLD_START, mask_sh),\ + LE_SF(DP_AUX0_AUX_DPHY_RX_CONTROL0, AUX_RX_ALLOW_BELOW_THRESHOLD_STOP, mask_sh),\ + LE_SF(DP_AUX0_AUX_DPHY_RX_CONTROL0, AUX_RX_PHASE_DETECT_LEN, mask_sh),\ + LE_SF(DP_AUX0_AUX_DPHY_RX_CONTROL0, AUX_RX_DETECTION_THRESHOLD, mask_sh), \ + LE_SF(DP_AUX0_AUX_DPHY_TX_CONTROL, AUX_TX_PRECHARGE_LEN, mask_sh),\ + LE_SF(DP_AUX0_AUX_DPHY_TX_CONTROL, AUX_TX_PRECHARGE_SYMBOLS, mask_sh),\ + LE_SF(DP_AUX0_AUX_DPHY_TX_CONTROL, AUX_MODE_DET_CHECK_DELAY, mask_sh),\ + LE_SF(DP_AUX0_AUX_DPHY_RX_CONTROL1, AUX_RX_PRECHARGE_SKIP, mask_sh),\ + LE_SF(DP_AUX0_AUX_DPHY_RX_CONTROL1, AUX_RX_TIMEOUT_LEN, mask_sh),\ + LE_SF(DP_AUX0_AUX_DPHY_RX_CONTROL1, AUX_RX_TIMEOUT_LEN_MUL, mask_sh) + +#define UNIPHY_DCN2_REG_LIST(id) \ + SRI(CLOCK_ENABLE, SYMCLK, id), \ + SRI(CHANNEL_XBAR_CNTL, UNIPHY, id) + +#define DPCS_DCN2_CMN_REG_LIST(id) \ + SRI(DIG_LANE_ENABLE, DIG, id), \ + SRI(TMDS_CTL_BITS, DIG, id), \ + SRI(RDPCSTX_PHY_CNTL3, RDPCSTX, id), \ + SRI(RDPCSTX_PHY_CNTL4, RDPCSTX, id), \ + SRI(RDPCSTX_PHY_CNTL5, RDPCSTX, id), \ + SRI(RDPCSTX_PHY_CNTL6, RDPCSTX, id), \ + SRI(RDPCSTX_PHY_CNTL7, RDPCSTX, id), \ + SRI(RDPCSTX_PHY_CNTL8, RDPCSTX, id), \ + SRI(RDPCSTX_PHY_CNTL9, RDPCSTX, id), \ + SRI(RDPCSTX_PHY_CNTL10, RDPCSTX, id), \ + SRI(RDPCSTX_PHY_CNTL11, RDPCSTX, id), \ + SRI(RDPCSTX_PHY_CNTL12, RDPCSTX, id), \ + SRI(RDPCSTX_PHY_CNTL13, RDPCSTX, id), \ + SRI(RDPCSTX_PHY_CNTL14, RDPCSTX, id), \ + SRI(RDPCSTX_CNTL, RDPCSTX, id), \ + SRI(RDPCSTX_CLOCK_CNTL, RDPCSTX, id), \ + SRI(RDPCSTX_INTERRUPT_CONTROL, RDPCSTX, id), \ + SRI(RDPCSTX_PHY_CNTL0, RDPCSTX, id), \ + SRI(RDPCSTX_PHY_CNTL2, RDPCSTX, id), \ + SRI(RDPCSTX_PLL_UPDATE_DATA, RDPCSTX, id), \ + SRI(RDPCS_TX_CR_ADDR, RDPCSTX, id), \ + SRI(RDPCS_TX_CR_DATA, RDPCSTX, id), \ + SRI(RDPCSTX_PHY_FUSE0, RDPCSTX, id), \ + SRI(RDPCSTX_PHY_FUSE1, RDPCSTX, id), \ + SRI(RDPCSTX_PHY_FUSE2, RDPCSTX, id), \ + SRI(RDPCSTX_PHY_FUSE3, RDPCSTX, id), \ + SRI(DPCSTX_TX_CLOCK_CNTL, DPCSTX, id), \ + SRI(DPCSTX_TX_CNTL, DPCSTX, id), \ + SRI(DPCSTX_DEBUG_CONFIG, DPCSTX, id), \ + SRI(RDPCSTX_DEBUG_CONFIG, RDPCSTX, id), \ + SR(RDPCSTX0_RDPCSTX_SCRATCH) + + +#define DPCS_DCN2_REG_LIST(id) \ + DPCS_DCN2_CMN_REG_LIST(id), \ + SRI(RDPCSTX_PHY_RX_LD_VAL, RDPCSTX, id),\ + SRI(RDPCSTX_DMCU_DPALT_DIS_BLOCK_REG, RDPCSTX, id) + +#define LE_DCN2_REG_LIST(id) \ + LE_DCN10_REG_LIST(id), \ + SR(DCIO_SOFT_RESET) + +struct mpll_cfg { + uint32_t mpllb_ana_v2i; + uint32_t mpllb_ana_freq_vco; + uint32_t mpllb_ana_cp_int; + uint32_t mpllb_ana_cp_prop; + uint32_t mpllb_multiplier; + uint32_t ref_clk_mpllb_div; + bool mpllb_word_div2_en; + bool mpllb_ssc_en; + bool mpllb_div5_clk_en; + bool mpllb_div_clk_en; + bool mpllb_fracn_en; + bool mpllb_pmix_en; + uint32_t mpllb_div_multiplier; + uint32_t mpllb_tx_clk_div; + uint32_t mpllb_fracn_quot; + uint32_t mpllb_fracn_den; + uint32_t mpllb_ssc_peak; + uint32_t mpllb_ssc_stepsize; + uint32_t mpllb_ssc_up_spread; + uint32_t mpllb_fracn_rem; + uint32_t mpllb_hdmi_div; + // TODO: May not mpll params, need to figure out. + uint32_t tx_vboost_lvl; + uint32_t hdmi_pixel_clk_div; + uint32_t ref_range; + uint32_t ref_clk; + bool hdmimode_enable; + bool sup_pre_hp; + bool dp_tx0_vergdrv_byp; + bool dp_tx1_vergdrv_byp; + bool dp_tx2_vergdrv_byp; + bool dp_tx3_vergdrv_byp; + uint32_t tx_peaking_lvl; + uint32_t ctr_reqs_pll; + +}; + +struct dpcssys_phy_seq_cfg { + bool program_fuse; + bool bypass_sram; + bool lane_en[4]; + bool use_calibration_setting; + struct mpll_cfg mpll_cfg; + bool load_sram_fw; +#if 0 + + bool hdmimode_enable; + bool silver2; + bool ext_refclk_en; + uint32_t dp_tx0_term_ctrl; + uint32_t dp_tx1_term_ctrl; + uint32_t dp_tx2_term_ctrl; + uint32_t dp_tx3_term_ctrl; + uint32_t fw_data[0x1000]; + uint32_t dp_tx0_width; + uint32_t dp_tx1_width; + uint32_t dp_tx2_width; + uint32_t dp_tx3_width; + uint32_t dp_tx0_rate; + uint32_t dp_tx1_rate; + uint32_t dp_tx2_rate; + uint32_t dp_tx3_rate; + uint32_t dp_tx0_eq_main; + uint32_t dp_tx0_eq_pre; + uint32_t dp_tx0_eq_post; + uint32_t dp_tx1_eq_main; + uint32_t dp_tx1_eq_pre; + uint32_t dp_tx1_eq_post; + uint32_t dp_tx2_eq_main; + uint32_t dp_tx2_eq_pre; + uint32_t dp_tx2_eq_post; + uint32_t dp_tx3_eq_main; + uint32_t dp_tx3_eq_pre; + uint32_t dp_tx3_eq_post; + bool data_swap_en; + bool data_order_invert_en; + uint32_t ldpcs_fifo_start_delay; + uint32_t rdpcs_fifo_start_delay; + bool rdpcs_reg_fifo_error_mask; + bool rdpcs_tx_fifo_error_mask; + bool rdpcs_dpalt_disable_mask; + bool rdpcs_dpalt_4lane_mask; +#endif +}; + +struct dcn20_link_encoder { + struct dcn10_link_encoder enc10; + struct dpcssys_phy_seq_cfg phy_seq_cfg; +}; + +void enc2_fec_set_enable(struct link_encoder *enc, bool enable); +void enc2_fec_set_ready(struct link_encoder *enc, bool ready); +bool enc2_fec_is_active(struct link_encoder *enc); +void enc2_hw_init(struct link_encoder *enc); + +void link_enc2_read_state(struct link_encoder *enc, struct link_enc_state *s); + +void dcn20_link_encoder_enable_dp_output( + struct link_encoder *enc, + const struct dc_link_settings *link_settings, + enum clock_source_id clock_source); + +bool dcn20_link_encoder_is_in_alt_mode(struct link_encoder *enc); +void dcn20_link_encoder_get_max_link_cap(struct link_encoder *enc, + struct dc_link_settings *link_settings); + +void dcn20_link_encoder_construct( + struct dcn20_link_encoder *enc20, + const struct encoder_init_data *init_data, + const struct encoder_feature_support *enc_features, + const struct dcn10_link_enc_registers *link_regs, + const struct dcn10_link_enc_aux_registers *aux_regs, + const struct dcn10_link_enc_hpd_registers *hpd_regs, + const struct dcn10_link_enc_shift *link_shift, + const struct dcn10_link_enc_mask *link_mask); + +#endif /* __DC_LINK_ENCODER__DCN20_H__ */ diff --git a/drivers/gpu/drm/amd/display/dc/dio/dcn20/dcn20_stream_encoder.c b/drivers/gpu/drm/amd/display/dc/dio/dcn20/dcn20_stream_encoder.c new file mode 100644 index 000000000000..0b47aeb60e79 --- /dev/null +++ b/drivers/gpu/drm/amd/display/dc/dio/dcn20/dcn20_stream_encoder.c @@ -0,0 +1,661 @@ +/* + * Copyright 2012-15 Advanced Micro Devices, Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + * + * Authors: AMD + * + */ + +#include + +#include "dc_bios_types.h" +#include "dcn20_stream_encoder.h" +#include "reg_helper.h" +#include "hw_shared.h" +#include "link.h" +#include "dpcd_defs.h" + +#define DC_LOGGER \ + enc1->base.ctx->logger + +#define REG(reg)\ + (enc1->regs->reg) + +#undef FN +#define FN(reg_name, field_name) \ + enc1->se_shift->field_name, enc1->se_mask->field_name + + +#define CTX \ + enc1->base.ctx + + +static void enc2_update_hdmi_info_packet( + struct dcn10_stream_encoder *enc1, + uint32_t packet_index, + const struct dc_info_packet *info_packet) +{ + uint32_t cont, send, line; + + if (info_packet->valid) { + enc1_update_generic_info_packet( + enc1, + packet_index, + info_packet); + + /* enable transmission of packet(s) - + * packet transmission begins on the next frame */ + cont = 1; + /* send packet(s) every frame */ + send = 1; + /* select line number to send packets on */ + line = 2; + } else { + cont = 0; + send = 0; + line = 0; + } + + /* DP_SEC_GSP[x]_LINE_REFERENCE - keep default value REFER_TO_DP_SOF */ + + /* choose which generic packet control to use */ + switch (packet_index) { + case 0: + REG_UPDATE_2(HDMI_GENERIC_PACKET_CONTROL0, + HDMI_GENERIC0_CONT, cont, + HDMI_GENERIC0_SEND, send); + REG_UPDATE(HDMI_GENERIC_PACKET_CONTROL1, + HDMI_GENERIC0_LINE, line); + break; + case 1: + REG_UPDATE_2(HDMI_GENERIC_PACKET_CONTROL0, + HDMI_GENERIC1_CONT, cont, + HDMI_GENERIC1_SEND, send); + REG_UPDATE(HDMI_GENERIC_PACKET_CONTROL1, + HDMI_GENERIC1_LINE, line); + break; + case 2: + REG_UPDATE_2(HDMI_GENERIC_PACKET_CONTROL0, + HDMI_GENERIC2_CONT, cont, + HDMI_GENERIC2_SEND, send); + REG_UPDATE(HDMI_GENERIC_PACKET_CONTROL2, + HDMI_GENERIC2_LINE, line); + break; + case 3: + REG_UPDATE_2(HDMI_GENERIC_PACKET_CONTROL0, + HDMI_GENERIC3_CONT, cont, + HDMI_GENERIC3_SEND, send); + REG_UPDATE(HDMI_GENERIC_PACKET_CONTROL2, + HDMI_GENERIC3_LINE, line); + break; + case 4: + REG_UPDATE_2(HDMI_GENERIC_PACKET_CONTROL0, + HDMI_GENERIC4_CONT, cont, + HDMI_GENERIC4_SEND, send); + REG_UPDATE(HDMI_GENERIC_PACKET_CONTROL3, + HDMI_GENERIC4_LINE, line); + break; + case 5: + REG_UPDATE_2(HDMI_GENERIC_PACKET_CONTROL0, + HDMI_GENERIC5_CONT, cont, + HDMI_GENERIC5_SEND, send); + REG_UPDATE(HDMI_GENERIC_PACKET_CONTROL3, + HDMI_GENERIC5_LINE, line); + break; + case 6: + REG_UPDATE_2(HDMI_GENERIC_PACKET_CONTROL0, + HDMI_GENERIC6_CONT, cont, + HDMI_GENERIC6_SEND, send); + REG_UPDATE(HDMI_GENERIC_PACKET_CONTROL4, + HDMI_GENERIC6_LINE, line); + break; + case 7: + REG_UPDATE_2(HDMI_GENERIC_PACKET_CONTROL0, + HDMI_GENERIC7_CONT, cont, + HDMI_GENERIC7_SEND, send); + REG_UPDATE(HDMI_GENERIC_PACKET_CONTROL4, + HDMI_GENERIC7_LINE, line); + break; + default: + /* invalid HW packet index */ + DC_LOG_WARNING( + "Invalid HW packet index: %s()\n", + __func__); + return; + } +} + +static void enc2_stream_encoder_update_hdmi_info_packets( + struct stream_encoder *enc, + const struct encoder_info_frame *info_frame) +{ + struct dcn10_stream_encoder *enc1 = DCN10STRENC_FROM_STRENC(enc); + + /* for bring up, disable dp double TODO */ + REG_UPDATE(HDMI_DB_CONTROL, HDMI_DB_DISABLE, 1); + + /*Always add mandatory packets first followed by optional ones*/ + enc2_update_hdmi_info_packet(enc1, 0, &info_frame->avi); + enc2_update_hdmi_info_packet(enc1, 1, &info_frame->hfvsif); + enc2_update_hdmi_info_packet(enc1, 2, &info_frame->gamut); + enc2_update_hdmi_info_packet(enc1, 3, &info_frame->vendor); + enc2_update_hdmi_info_packet(enc1, 4, &info_frame->spd); + enc2_update_hdmi_info_packet(enc1, 5, &info_frame->hdrsmd); + enc2_update_hdmi_info_packet(enc1, 6, &info_frame->vtem); +} + +static void enc2_stream_encoder_stop_hdmi_info_packets( + struct stream_encoder *enc) +{ + struct dcn10_stream_encoder *enc1 = DCN10STRENC_FROM_STRENC(enc); + + /* stop generic packets 0,1 on HDMI */ + REG_SET_4(HDMI_GENERIC_PACKET_CONTROL0, 0, + HDMI_GENERIC0_CONT, 0, + HDMI_GENERIC0_SEND, 0, + HDMI_GENERIC1_CONT, 0, + HDMI_GENERIC1_SEND, 0); + REG_SET_2(HDMI_GENERIC_PACKET_CONTROL1, 0, + HDMI_GENERIC0_LINE, 0, + HDMI_GENERIC1_LINE, 0); + + /* stop generic packets 2,3 on HDMI */ + REG_SET_4(HDMI_GENERIC_PACKET_CONTROL0, 0, + HDMI_GENERIC2_CONT, 0, + HDMI_GENERIC2_SEND, 0, + HDMI_GENERIC3_CONT, 0, + HDMI_GENERIC3_SEND, 0); + REG_SET_2(HDMI_GENERIC_PACKET_CONTROL2, 0, + HDMI_GENERIC2_LINE, 0, + HDMI_GENERIC3_LINE, 0); + + /* stop generic packets 4,5 on HDMI */ + REG_SET_4(HDMI_GENERIC_PACKET_CONTROL0, 0, + HDMI_GENERIC4_CONT, 0, + HDMI_GENERIC4_SEND, 0, + HDMI_GENERIC5_CONT, 0, + HDMI_GENERIC5_SEND, 0); + REG_SET_2(HDMI_GENERIC_PACKET_CONTROL3, 0, + HDMI_GENERIC4_LINE, 0, + HDMI_GENERIC5_LINE, 0); + + /* stop generic packets 6,7 on HDMI */ + REG_SET_4(HDMI_GENERIC_PACKET_CONTROL0, 0, + HDMI_GENERIC6_CONT, 0, + HDMI_GENERIC6_SEND, 0, + HDMI_GENERIC7_CONT, 0, + HDMI_GENERIC7_SEND, 0); + REG_SET_2(HDMI_GENERIC_PACKET_CONTROL4, 0, + HDMI_GENERIC6_LINE, 0, + HDMI_GENERIC7_LINE, 0); +} + + +/* Update GSP7 SDP 128 byte long */ +static void enc2_update_gsp7_128_info_packet( + struct dcn10_stream_encoder *enc1, + const struct dc_info_packet_128 *info_packet, + bool immediate_update) +{ + uint32_t i; + + /* TODOFPGA Figure out a proper number for max_retries polling for lock + * use 50 for now. + */ + uint32_t max_retries = 50; + const uint32_t *content = (const uint32_t *) &info_packet->sb[0]; + + ASSERT(info_packet->hb1 == DC_DP_INFOFRAME_TYPE_PPS); + + /* Configure for PPS packet size (128 bytes) */ + REG_UPDATE(DP_SEC_CNTL2, DP_SEC_GSP7_PPS, 1); + + /* We need turn on clock before programming AFMT block*/ + REG_UPDATE(AFMT_CNTL, AFMT_AUDIO_CLOCK_EN, 1); + + /* Poll dig_update_lock is not locked -> asic internal signal + * assumes otg master lock will unlock it + */ + /*REG_WAIT(AFMT_VBI_PACKET_CONTROL, AFMT_GENERIC_LOCK_STATUS, 0, 10, max_retries);*/ + + /* Wait for HW/SW GSP memory access conflict to go away */ + REG_WAIT(AFMT_VBI_PACKET_CONTROL, AFMT_GENERIC_CONFLICT, + 0, 10, max_retries); + + /* Clear HW/SW memory access conflict flag */ + REG_UPDATE(AFMT_VBI_PACKET_CONTROL, AFMT_GENERIC_CONFLICT_CLR, 1); + + /* write generic packet header */ + REG_UPDATE(AFMT_VBI_PACKET_CONTROL, AFMT_GENERIC_INDEX, 7); + REG_SET_4(AFMT_GENERIC_HDR, 0, + AFMT_GENERIC_HB0, info_packet->hb0, + AFMT_GENERIC_HB1, info_packet->hb1, + AFMT_GENERIC_HB2, info_packet->hb2, + AFMT_GENERIC_HB3, info_packet->hb3); + + /* Write generic packet content 128 bytes long. Four sets are used (indexes 7 + * through 10) to fit 128 bytes. + */ + for (i = 0; i < 4; i++) { + uint32_t packet_index = 7 + i; + REG_UPDATE(AFMT_VBI_PACKET_CONTROL, AFMT_GENERIC_INDEX, packet_index); + + REG_WRITE(AFMT_GENERIC_0, *content++); + REG_WRITE(AFMT_GENERIC_1, *content++); + REG_WRITE(AFMT_GENERIC_2, *content++); + REG_WRITE(AFMT_GENERIC_3, *content++); + REG_WRITE(AFMT_GENERIC_4, *content++); + REG_WRITE(AFMT_GENERIC_5, *content++); + REG_WRITE(AFMT_GENERIC_6, *content++); + REG_WRITE(AFMT_GENERIC_7, *content++); + } + + REG_UPDATE_2(AFMT_VBI_PACKET_CONTROL1, + AFMT_GENERIC7_FRAME_UPDATE, !immediate_update, + AFMT_GENERIC7_IMMEDIATE_UPDATE, immediate_update); +} + +/* Set DSC-related configuration. + * dsc_mode: 0 disables DSC, other values enable DSC in specified format + * sc_bytes_per_pixel: Bytes per pixel in u3.28 format + * dsc_slice_width: Slice width in pixels + */ +static void enc2_dp_set_dsc_config(struct stream_encoder *enc, + enum optc_dsc_mode dsc_mode, + uint32_t dsc_bytes_per_pixel, + uint32_t dsc_slice_width) +{ + struct dcn10_stream_encoder *enc1 = DCN10STRENC_FROM_STRENC(enc); + + REG_UPDATE_2(DP_DSC_CNTL, + DP_DSC_MODE, dsc_mode, + DP_DSC_SLICE_WIDTH, dsc_slice_width); + + REG_SET(DP_DSC_BYTES_PER_PIXEL, 0, + DP_DSC_BYTES_PER_PIXEL, dsc_bytes_per_pixel); +} + + +static void enc2_dp_set_dsc_pps_info_packet(struct stream_encoder *enc, + bool enable, + uint8_t *dsc_packed_pps, + bool immediate_update) +{ + struct dcn10_stream_encoder *enc1 = DCN10STRENC_FROM_STRENC(enc); + + if (enable) { + struct dc_info_packet_128 pps_sdp; + + ASSERT(dsc_packed_pps); + + /* Load PPS into infoframe (SDP) registers */ + pps_sdp.valid = true; + pps_sdp.hb0 = 0; + pps_sdp.hb1 = DC_DP_INFOFRAME_TYPE_PPS; + pps_sdp.hb2 = 127; + pps_sdp.hb3 = 0; + memcpy(&pps_sdp.sb[0], dsc_packed_pps, sizeof(pps_sdp.sb)); + enc2_update_gsp7_128_info_packet(enc1, &pps_sdp, immediate_update); + + /* Enable Generic Stream Packet 7 (GSP) transmission */ + //REG_UPDATE(DP_SEC_CNTL, + // DP_SEC_GSP7_ENABLE, 1); + + /* SW should make sure VBID[6] update line number is bigger + * than PPS transmit line number + */ + REG_UPDATE(DP_SEC_CNTL6, + DP_SEC_GSP7_LINE_NUM, 2); + REG_UPDATE_2(DP_MSA_VBID_MISC, + DP_VBID6_LINE_REFERENCE, 0, + DP_VBID6_LINE_NUM, 3); + + /* Send PPS data at the line number specified above. + * DP spec requires PPS to be sent only when it changes, however since + * decoder has to be able to handle its change on every frame, we're + * sending it always (i.e. on every frame) to reduce the chance it'd be + * missed by decoder. If it turns out required to send PPS only when it + * changes, we can use DP_SEC_GSP7_SEND register. + */ + REG_UPDATE_2(DP_SEC_CNTL, + DP_SEC_GSP7_ENABLE, 1, + DP_SEC_STREAM_ENABLE, 1); + } else { + /* Disable Generic Stream Packet 7 (GSP) transmission */ + REG_UPDATE(DP_SEC_CNTL, DP_SEC_GSP7_ENABLE, 0); + REG_UPDATE(DP_SEC_CNTL2, DP_SEC_GSP7_PPS, 0); + } +} + + +/* this function read dsc related register fields to be logged later in dcn10_log_hw_state + * into a dcn_dsc_state struct. + */ +static void enc2_read_state(struct stream_encoder *enc, struct enc_state *s) +{ + struct dcn10_stream_encoder *enc1 = DCN10STRENC_FROM_STRENC(enc); + + //if dsc is enabled, continue to read + REG_GET(DP_DSC_CNTL, DP_DSC_MODE, &s->dsc_mode); + if (s->dsc_mode) { + REG_GET(DP_DSC_CNTL, DP_DSC_SLICE_WIDTH, &s->dsc_slice_width); + REG_GET(DP_SEC_CNTL6, DP_SEC_GSP7_LINE_NUM, &s->sec_gsp_pps_line_num); + + REG_GET(DP_MSA_VBID_MISC, DP_VBID6_LINE_REFERENCE, &s->vbid6_line_reference); + REG_GET(DP_MSA_VBID_MISC, DP_VBID6_LINE_NUM, &s->vbid6_line_num); + + REG_GET(DP_SEC_CNTL, DP_SEC_GSP7_ENABLE, &s->sec_gsp_pps_enable); + REG_GET(DP_SEC_CNTL, DP_SEC_STREAM_ENABLE, &s->sec_stream_enable); + } +} + +/* Set Dynamic Metadata-configuration. + * enable_dme: TRUE: enables Dynamic Metadata Enfine, FALSE: disables DME + * hubp_requestor_id: HUBP physical instance that is the source of dynamic metadata + * only needs to be set when enable_dme is TRUE + * dmdata_mode: dynamic metadata packet type: DP, HDMI, or Dolby Vision + * + * Ensure the OTG master update lock is set when changing DME configuration. + */ +void enc2_set_dynamic_metadata(struct stream_encoder *enc, + bool enable_dme, + uint32_t hubp_requestor_id, + enum dynamic_metadata_mode dmdata_mode) +{ + struct dcn10_stream_encoder *enc1 = DCN10STRENC_FROM_STRENC(enc); + + if (enable_dme) { + REG_UPDATE_2(DME_CONTROL, + METADATA_HUBP_REQUESTOR_ID, hubp_requestor_id, + METADATA_STREAM_TYPE, (dmdata_mode == dmdata_dolby_vision) ? 1 : 0); + + /* Use default line reference DP_SOF for bringup. + * Should use OTG_SOF for DRR cases + */ + if (dmdata_mode == dmdata_dp) + REG_UPDATE_3(DP_SEC_METADATA_TRANSMISSION, + DP_SEC_METADATA_PACKET_ENABLE, 1, + DP_SEC_METADATA_PACKET_LINE_REFERENCE, 0, + DP_SEC_METADATA_PACKET_LINE, 20); + else { + REG_UPDATE_3(HDMI_METADATA_PACKET_CONTROL, + HDMI_METADATA_PACKET_ENABLE, 1, + HDMI_METADATA_PACKET_LINE_REFERENCE, 0, + HDMI_METADATA_PACKET_LINE, 2); + + if (dmdata_mode == dmdata_dolby_vision) + REG_UPDATE(DIG_FE_CNTL, + DOLBY_VISION_EN, 1); + } + + REG_UPDATE(DME_CONTROL, + METADATA_ENGINE_EN, 1); + } else { + REG_UPDATE(DME_CONTROL, + METADATA_ENGINE_EN, 0); + + if (dmdata_mode == dmdata_dp) + REG_UPDATE(DP_SEC_METADATA_TRANSMISSION, + DP_SEC_METADATA_PACKET_ENABLE, 0); + else { + REG_UPDATE(HDMI_METADATA_PACKET_CONTROL, + HDMI_METADATA_PACKET_ENABLE, 0); + REG_UPDATE(DIG_FE_CNTL, + DOLBY_VISION_EN, 0); + } + } +} + +static void enc2_stream_encoder_update_dp_info_packets_sdp_line_num( + struct stream_encoder *enc, + struct encoder_info_frame *info_frame) +{ + struct dcn10_stream_encoder *enc1 = DCN10STRENC_FROM_STRENC(enc); + + if (info_frame->adaptive_sync.valid == true && + info_frame->sdp_line_num.adaptive_sync_line_num_valid == true) { + //00: REFER_TO_DP_SOF, 01: REFER_TO_OTG_SOF + REG_UPDATE(DP_SEC_CNTL1, DP_SEC_GSP5_LINE_REFERENCE, 1); + + REG_UPDATE(DP_SEC_CNTL5, DP_SEC_GSP5_LINE_NUM, + info_frame->sdp_line_num.adaptive_sync_line_num); + } +} + +static void enc2_stream_encoder_update_dp_info_packets( + struct stream_encoder *enc, + const struct encoder_info_frame *info_frame) +{ + struct dcn10_stream_encoder *enc1 = DCN10STRENC_FROM_STRENC(enc); + uint32_t dmdata_packet_enabled = 0; + + enc1_stream_encoder_update_dp_info_packets(enc, info_frame); + + /* check if dynamic metadata packet transmission is enabled */ + REG_GET(DP_SEC_METADATA_TRANSMISSION, + DP_SEC_METADATA_PACKET_ENABLE, &dmdata_packet_enabled); + + if (dmdata_packet_enabled) + REG_UPDATE(DP_SEC_CNTL, DP_SEC_STREAM_ENABLE, 1); +} + +static bool is_two_pixels_per_containter(const struct dc_crtc_timing *timing) +{ + bool two_pix = timing->pixel_encoding == PIXEL_ENCODING_YCBCR420; + + two_pix = two_pix || (timing->flags.DSC && timing->pixel_encoding == PIXEL_ENCODING_YCBCR422 + && !timing->dsc_cfg.ycbcr422_simple); + return two_pix; +} + +void enc2_stream_encoder_dp_unblank( + struct dc_link *link, + struct stream_encoder *enc, + const struct encoder_unblank_param *param) +{ + struct dcn10_stream_encoder *enc1 = DCN10STRENC_FROM_STRENC(enc); + + if (param->link_settings.link_rate != LINK_RATE_UNKNOWN) { + uint32_t n_vid = 0x8000; + uint32_t m_vid; + uint32_t n_multiply = 0; + uint64_t m_vid_l = n_vid; + + /* YCbCr 4:2:0 : Computed VID_M will be 2X the input rate */ + if (is_two_pixels_per_containter(¶m->timing) || param->opp_cnt > 1) { + /*this logic should be the same in get_pixel_clock_parameters() */ + n_multiply = 1; + } + /* M / N = Fstream / Flink + * m_vid / n_vid = pixel rate / link rate + */ + + m_vid_l *= param->timing.pix_clk_100hz / 10; + m_vid_l = div_u64(m_vid_l, + param->link_settings.link_rate + * LINK_RATE_REF_FREQ_IN_KHZ); + + m_vid = (uint32_t) m_vid_l; + + /* enable auto measurement */ + + REG_UPDATE(DP_VID_TIMING, DP_VID_M_N_GEN_EN, 0); + + /* auto measurement need 1 full 0x8000 symbol cycle to kick in, + * therefore program initial value for Mvid and Nvid + */ + + REG_UPDATE(DP_VID_N, DP_VID_N, n_vid); + + REG_UPDATE(DP_VID_M, DP_VID_M, m_vid); + + REG_UPDATE_2(DP_VID_TIMING, + DP_VID_M_N_GEN_EN, 1, + DP_VID_N_MUL, n_multiply); + } + + /* make sure stream is disabled before resetting steer fifo */ + REG_UPDATE(DP_VID_STREAM_CNTL, DP_VID_STREAM_ENABLE, false); + REG_WAIT(DP_VID_STREAM_CNTL, DP_VID_STREAM_STATUS, 0, 10, 5000); + + /* set DIG_START to 0x1 to reset FIFO */ + REG_UPDATE(DIG_FE_CNTL, DIG_START, 1); + udelay(1); + + /* write 0 to take the FIFO out of reset */ + + REG_UPDATE(DIG_FE_CNTL, DIG_START, 0); + + /* switch DP encoder to CRTC data, but reset it the fifo first. It may happen + * that it overflows during mode transition, and sometimes doesn't recover. + */ + REG_UPDATE(DP_STEER_FIFO, DP_STEER_FIFO_RESET, 1); + udelay(10); + + REG_UPDATE(DP_STEER_FIFO, DP_STEER_FIFO_RESET, 0); + + /* wait 100us for DIG/DP logic to prime + * (i.e. a few video lines) + */ + udelay(100); + + /* the hardware would start sending video at the start of the next DP + * frame (i.e. rising edge of the vblank). + * NOTE: We used to program DP_VID_STREAM_DIS_DEFER = 2 here, but this + * register has no effect on enable transition! HW always guarantees + * VID_STREAM enable at start of next frame, and this is not + * programmable + */ + + REG_UPDATE(DP_VID_STREAM_CNTL, DP_VID_STREAM_ENABLE, true); + + link->dc->link_srv->dp_trace_source_sequence(link, + DPCD_SOURCE_SEQ_AFTER_ENABLE_DP_VID_STREAM); +} + +static void enc2_dp_set_odm_combine( + struct stream_encoder *enc, + bool odm_combine) +{ + struct dcn10_stream_encoder *enc1 = DCN10STRENC_FROM_STRENC(enc); + + REG_UPDATE(DP_PIXEL_FORMAT, DP_PIXEL_COMBINE, odm_combine); +} + +void enc2_stream_encoder_dp_set_stream_attribute( + struct stream_encoder *enc, + struct dc_crtc_timing *crtc_timing, + enum dc_color_space output_color_space, + bool use_vsc_sdp_for_colorimetry, + uint32_t enable_sdp_splitting) +{ + struct dcn10_stream_encoder *enc1 = DCN10STRENC_FROM_STRENC(enc); + + enc1_stream_encoder_dp_set_stream_attribute(enc, + crtc_timing, + output_color_space, + use_vsc_sdp_for_colorimetry, + enable_sdp_splitting); + + REG_UPDATE(DP_SEC_FRAMING4, + DP_SST_SDP_SPLITTING, enable_sdp_splitting); +} + +uint32_t enc2_get_fifo_cal_average_level( + struct stream_encoder *enc) +{ + struct dcn10_stream_encoder *enc1 = DCN10STRENC_FROM_STRENC(enc); + uint32_t fifo_level; + + REG_GET(DIG_FIFO_STATUS, + DIG_FIFO_CAL_AVERAGE_LEVEL, &fifo_level); + return fifo_level; +} + +static const struct stream_encoder_funcs dcn20_str_enc_funcs = { + .dp_set_odm_combine = + enc2_dp_set_odm_combine, + .dp_set_stream_attribute = + enc2_stream_encoder_dp_set_stream_attribute, + .hdmi_set_stream_attribute = + enc1_stream_encoder_hdmi_set_stream_attribute, + .dvi_set_stream_attribute = + enc1_stream_encoder_dvi_set_stream_attribute, + .set_throttled_vcp_size = + enc1_stream_encoder_set_throttled_vcp_size, + .update_hdmi_info_packets = + enc2_stream_encoder_update_hdmi_info_packets, + .stop_hdmi_info_packets = + enc2_stream_encoder_stop_hdmi_info_packets, + .update_dp_info_packets_sdp_line_num = + enc2_stream_encoder_update_dp_info_packets_sdp_line_num, + .update_dp_info_packets = + enc2_stream_encoder_update_dp_info_packets, + .send_immediate_sdp_message = + enc1_stream_encoder_send_immediate_sdp_message, + .stop_dp_info_packets = + enc1_stream_encoder_stop_dp_info_packets, + .dp_blank = + enc1_stream_encoder_dp_blank, + .dp_unblank = + enc2_stream_encoder_dp_unblank, + .audio_mute_control = enc1_se_audio_mute_control, + + .dp_audio_setup = enc1_se_dp_audio_setup, + .dp_audio_enable = enc1_se_dp_audio_enable, + .dp_audio_disable = enc1_se_dp_audio_disable, + + .hdmi_audio_setup = enc1_se_hdmi_audio_setup, + .hdmi_audio_disable = enc1_se_hdmi_audio_disable, + .setup_stereo_sync = enc1_setup_stereo_sync, + .set_avmute = enc1_stream_encoder_set_avmute, + .dig_connect_to_otg = enc1_dig_connect_to_otg, + .dig_source_otg = enc1_dig_source_otg, + + .dp_get_pixel_format = + enc1_stream_encoder_dp_get_pixel_format, + + .enc_read_state = enc2_read_state, + .dp_set_dsc_config = enc2_dp_set_dsc_config, + .dp_set_dsc_pps_info_packet = enc2_dp_set_dsc_pps_info_packet, + .set_dynamic_metadata = enc2_set_dynamic_metadata, + .hdmi_reset_stream_attribute = enc1_reset_hdmi_stream_attribute, + .get_fifo_cal_average_level = enc2_get_fifo_cal_average_level, +}; + +void dcn20_stream_encoder_construct( + struct dcn10_stream_encoder *enc1, + struct dc_context *ctx, + struct dc_bios *bp, + enum engine_id eng_id, + const struct dcn10_stream_enc_registers *regs, + const struct dcn10_stream_encoder_shift *se_shift, + const struct dcn10_stream_encoder_mask *se_mask) +{ + enc1->base.funcs = &dcn20_str_enc_funcs; + enc1->base.ctx = ctx; + enc1->base.id = eng_id; + enc1->base.bp = bp; + enc1->regs = regs; + enc1->se_shift = se_shift; + enc1->se_mask = se_mask; + enc1->base.stream_enc_inst = eng_id - ENGINE_ID_DIGA; +} + diff --git a/drivers/gpu/drm/amd/display/dc/dio/dcn20/dcn20_stream_encoder.h b/drivers/gpu/drm/amd/display/dc/dio/dcn20/dcn20_stream_encoder.h new file mode 100644 index 000000000000..baa1e539f341 --- /dev/null +++ b/drivers/gpu/drm/amd/display/dc/dio/dcn20/dcn20_stream_encoder.h @@ -0,0 +1,119 @@ +/* + * Copyright 2012-15 Advanced Micro Devices, Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + * + * Authors: AMD + * + */ + +#ifndef __DC_STREAM_ENCODER_DCN20_H__ +#define __DC_STREAM_ENCODER_DCN20_H__ + +#include "stream_encoder.h" +#include "dcn10/dcn10_stream_encoder.h" + + +#define SE_DCN2_REG_LIST(id)\ + SE_COMMON_DCN_REG_LIST(id),\ + SRI(HDMI_GENERIC_PACKET_CONTROL4, DIG, id), \ + SRI(HDMI_GENERIC_PACKET_CONTROL5, DIG, id), \ + SRI(DP_DSC_CNTL, DP, id), \ + SRI(DP_DSC_BYTES_PER_PIXEL, DP, id), \ + SRI(DME_CONTROL, DIG, id),\ + SRI(DP_SEC_METADATA_TRANSMISSION, DP, id), \ + SRI(HDMI_METADATA_PACKET_CONTROL, DIG, id), \ + SRI(DP_SEC_FRAMING4, DP, id) + +#define SE_COMMON_MASK_SH_LIST_DCN20(mask_sh)\ + SE_COMMON_MASK_SH_LIST_SOC(mask_sh),\ + SE_SF(DIG0_HDMI_GENERIC_PACKET_CONTROL0, HDMI_GENERIC0_CONT, mask_sh),\ + SE_SF(DIG0_HDMI_GENERIC_PACKET_CONTROL0, HDMI_GENERIC0_SEND, mask_sh),\ + SE_SF(DIG0_HDMI_GENERIC_PACKET_CONTROL0, HDMI_GENERIC1_CONT, mask_sh),\ + SE_SF(DIG0_HDMI_GENERIC_PACKET_CONTROL0, HDMI_GENERIC1_SEND, mask_sh),\ + SE_SF(DIG0_HDMI_GENERIC_PACKET_CONTROL0, HDMI_GENERIC2_CONT, mask_sh),\ + SE_SF(DIG0_HDMI_GENERIC_PACKET_CONTROL0, HDMI_GENERIC2_SEND, mask_sh),\ + SE_SF(DIG0_HDMI_GENERIC_PACKET_CONTROL0, HDMI_GENERIC3_CONT, mask_sh),\ + SE_SF(DIG0_HDMI_GENERIC_PACKET_CONTROL0, HDMI_GENERIC3_SEND, mask_sh),\ + SE_SF(DIG0_HDMI_GENERIC_PACKET_CONTROL0, HDMI_GENERIC4_CONT, mask_sh),\ + SE_SF(DIG0_HDMI_GENERIC_PACKET_CONTROL0, HDMI_GENERIC4_SEND, mask_sh),\ + SE_SF(DIG0_HDMI_GENERIC_PACKET_CONTROL0, HDMI_GENERIC5_CONT, mask_sh),\ + SE_SF(DIG0_HDMI_GENERIC_PACKET_CONTROL0, HDMI_GENERIC5_SEND, mask_sh),\ + SE_SF(DIG0_HDMI_GENERIC_PACKET_CONTROL0, HDMI_GENERIC6_CONT, mask_sh),\ + SE_SF(DIG0_HDMI_GENERIC_PACKET_CONTROL0, HDMI_GENERIC6_SEND, mask_sh),\ + SE_SF(DIG0_HDMI_GENERIC_PACKET_CONTROL0, HDMI_GENERIC7_CONT, mask_sh),\ + SE_SF(DIG0_HDMI_GENERIC_PACKET_CONTROL0, HDMI_GENERIC7_SEND, mask_sh),\ + SE_SF(DIG0_HDMI_GENERIC_PACKET_CONTROL1, HDMI_GENERIC0_LINE, mask_sh),\ + SE_SF(DIG0_HDMI_GENERIC_PACKET_CONTROL1, HDMI_GENERIC1_LINE, mask_sh),\ + SE_SF(DIG0_HDMI_GENERIC_PACKET_CONTROL2, HDMI_GENERIC2_LINE, mask_sh),\ + SE_SF(DIG0_HDMI_GENERIC_PACKET_CONTROL2, HDMI_GENERIC3_LINE, mask_sh),\ + SE_SF(DIG0_HDMI_GENERIC_PACKET_CONTROL3, HDMI_GENERIC4_LINE, mask_sh),\ + SE_SF(DIG0_HDMI_GENERIC_PACKET_CONTROL3, HDMI_GENERIC5_LINE, mask_sh),\ + SE_SF(DIG0_HDMI_GENERIC_PACKET_CONTROL4, HDMI_GENERIC6_LINE, mask_sh),\ + SE_SF(DIG0_HDMI_GENERIC_PACKET_CONTROL4, HDMI_GENERIC7_LINE, mask_sh),\ + SE_SF(DP0_DP_DSC_CNTL, DP_DSC_MODE, mask_sh),\ + SE_SF(DP0_DP_DSC_CNTL, DP_DSC_SLICE_WIDTH, mask_sh),\ + SE_SF(DP0_DP_DSC_BYTES_PER_PIXEL, DP_DSC_BYTES_PER_PIXEL, mask_sh),\ + SE_SF(DP0_DP_MSA_VBID_MISC, DP_VBID6_LINE_REFERENCE, mask_sh),\ + SE_SF(DP0_DP_MSA_VBID_MISC, DP_VBID6_LINE_NUM, mask_sh),\ + SE_SF(DIG0_DME_CONTROL, METADATA_ENGINE_EN, mask_sh),\ + SE_SF(DIG0_DME_CONTROL, METADATA_HUBP_REQUESTOR_ID, mask_sh),\ + SE_SF(DIG0_DME_CONTROL, METADATA_STREAM_TYPE, mask_sh),\ + SE_SF(DP0_DP_SEC_METADATA_TRANSMISSION, DP_SEC_METADATA_PACKET_ENABLE, mask_sh),\ + SE_SF(DP0_DP_SEC_METADATA_TRANSMISSION, DP_SEC_METADATA_PACKET_LINE_REFERENCE, mask_sh),\ + SE_SF(DP0_DP_SEC_METADATA_TRANSMISSION, DP_SEC_METADATA_PACKET_LINE, mask_sh),\ + SE_SF(DIG0_HDMI_METADATA_PACKET_CONTROL, HDMI_METADATA_PACKET_ENABLE, mask_sh),\ + SE_SF(DIG0_HDMI_METADATA_PACKET_CONTROL, HDMI_METADATA_PACKET_LINE_REFERENCE, mask_sh),\ + SE_SF(DIG0_HDMI_METADATA_PACKET_CONTROL, HDMI_METADATA_PACKET_LINE, mask_sh),\ + SE_SF(DIG0_DIG_FE_CNTL, DOLBY_VISION_EN, mask_sh),\ + SE_SF(DP0_DP_PIXEL_FORMAT, DP_PIXEL_COMBINE, mask_sh),\ + SE_SF(DP0_DP_SEC_CNTL1, DP_SEC_GSP5_LINE_REFERENCE, mask_sh),\ + SE_SF(DP0_DP_SEC_CNTL5, DP_SEC_GSP5_LINE_NUM, mask_sh),\ + SE_SF(DP0_DP_SEC_FRAMING4, DP_SST_SDP_SPLITTING, mask_sh) + +void dcn20_stream_encoder_construct( + struct dcn10_stream_encoder *enc1, + struct dc_context *ctx, + struct dc_bios *bp, + enum engine_id eng_id, + const struct dcn10_stream_enc_registers *regs, + const struct dcn10_stream_encoder_shift *se_shift, + const struct dcn10_stream_encoder_mask *se_mask); + +void enc2_stream_encoder_dp_set_stream_attribute( + struct stream_encoder *enc, + struct dc_crtc_timing *crtc_timing, + enum dc_color_space output_color_space, + bool use_vsc_sdp_for_colorimetry, + uint32_t enable_sdp_splitting); + +void enc2_stream_encoder_dp_unblank( + struct dc_link *link, + struct stream_encoder *enc, + const struct encoder_unblank_param *param); + +void enc2_set_dynamic_metadata(struct stream_encoder *enc, + bool enable_dme, + uint32_t hubp_requestor_id, + enum dynamic_metadata_mode dmdata_mode); + +uint32_t enc2_get_fifo_cal_average_level( + struct stream_encoder *enc); + +#endif /* __DC_STREAM_ENCODER_DCN20_H__ */ diff --git a/drivers/gpu/drm/amd/display/dc/dio/dcn30/dcn30_dio_link_encoder.c b/drivers/gpu/drm/amd/display/dc/dio/dcn30/dcn30_dio_link_encoder.c new file mode 100644 index 000000000000..b8e31b5ea114 --- /dev/null +++ b/drivers/gpu/drm/amd/display/dc/dio/dcn30/dcn30_dio_link_encoder.c @@ -0,0 +1,257 @@ +/* + * Copyright 2020 Advanced Micro Devices, Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + * + * Authors: AMD + * + */ + +#include "reg_helper.h" + +#include "core_types.h" +#include "link_encoder.h" +#include "dcn30_dio_link_encoder.h" +#include "stream_encoder.h" +#include "dc_bios_types.h" +#include "gpio_service_interface.h" + +#define CTX \ + enc10->base.ctx +#define DC_LOGGER \ + enc10->base.ctx->logger + +#define REG(reg)\ + (enc10->link_regs->reg) + +#undef FN +#define FN(reg_name, field_name) \ + enc10->link_shift->field_name, enc10->link_mask->field_name + +#define IND_REG(index) \ + (enc10->link_regs->index) + + +bool dcn30_link_encoder_validate_output_with_stream( + struct link_encoder *enc, + const struct dc_stream_state *stream) +{ + return dcn10_link_encoder_validate_output_with_stream(enc, stream); +} + +static const struct link_encoder_funcs dcn30_link_enc_funcs = { + .read_state = link_enc2_read_state, + .validate_output_with_stream = + dcn30_link_encoder_validate_output_with_stream, + .hw_init = enc3_hw_init, + .setup = dcn10_link_encoder_setup, + .enable_tmds_output = dcn10_link_encoder_enable_tmds_output, + .enable_dp_output = dcn20_link_encoder_enable_dp_output, + .enable_dp_mst_output = dcn10_link_encoder_enable_dp_mst_output, + .disable_output = dcn10_link_encoder_disable_output, + .dp_set_lane_settings = dcn10_link_encoder_dp_set_lane_settings, + .dp_set_phy_pattern = dcn10_link_encoder_dp_set_phy_pattern, + .update_mst_stream_allocation_table = + dcn10_link_encoder_update_mst_stream_allocation_table, + .psr_program_dp_dphy_fast_training = + dcn10_psr_program_dp_dphy_fast_training, + .psr_program_secondary_packet = dcn10_psr_program_secondary_packet, + .connect_dig_be_to_fe = dcn10_link_encoder_connect_dig_be_to_fe, + .enable_hpd = dcn10_link_encoder_enable_hpd, + .disable_hpd = dcn10_link_encoder_disable_hpd, + .is_dig_enabled = dcn10_is_dig_enabled, + .destroy = dcn10_link_encoder_destroy, + .fec_set_enable = enc2_fec_set_enable, + .fec_set_ready = enc2_fec_set_ready, + .fec_is_active = enc2_fec_is_active, + .get_dig_frontend = dcn10_get_dig_frontend, + .get_dig_mode = dcn10_get_dig_mode, + .is_in_alt_mode = dcn20_link_encoder_is_in_alt_mode, + .get_max_link_cap = dcn20_link_encoder_get_max_link_cap, +}; + +void dcn30_link_encoder_construct( + struct dcn20_link_encoder *enc20, + const struct encoder_init_data *init_data, + const struct encoder_feature_support *enc_features, + const struct dcn10_link_enc_registers *link_regs, + const struct dcn10_link_enc_aux_registers *aux_regs, + const struct dcn10_link_enc_hpd_registers *hpd_regs, + const struct dcn10_link_enc_shift *link_shift, + const struct dcn10_link_enc_mask *link_mask) +{ + struct bp_encoder_cap_info bp_cap_info = {0}; + const struct dc_vbios_funcs *bp_funcs = init_data->ctx->dc_bios->funcs; + enum bp_result result = BP_RESULT_OK; + struct dcn10_link_encoder *enc10 = &enc20->enc10; + + enc10->base.funcs = &dcn30_link_enc_funcs; + enc10->base.ctx = init_data->ctx; + enc10->base.id = init_data->encoder; + + enc10->base.hpd_source = init_data->hpd_source; + enc10->base.connector = init_data->connector; + + enc10->base.preferred_engine = ENGINE_ID_UNKNOWN; + + enc10->base.features = *enc_features; + + enc10->base.transmitter = init_data->transmitter; + + /* set the flag to indicate whether driver poll the I2C data pin + * while doing the DP sink detect + */ + +/* if (dal_adapter_service_is_feature_supported(as, + FEATURE_DP_SINK_DETECT_POLL_DATA_PIN)) + enc10->base.features.flags.bits. + DP_SINK_DETECT_POLL_DATA_PIN = true;*/ + + enc10->base.output_signals = + SIGNAL_TYPE_DVI_SINGLE_LINK | + SIGNAL_TYPE_DVI_DUAL_LINK | + SIGNAL_TYPE_LVDS | + SIGNAL_TYPE_DISPLAY_PORT | + SIGNAL_TYPE_DISPLAY_PORT_MST | + SIGNAL_TYPE_EDP | + SIGNAL_TYPE_HDMI_TYPE_A; + + /* For DCE 8.0 and 8.1, by design, UNIPHY is hardwired to DIG_BE. + * SW always assign DIG_FE 1:1 mapped to DIG_FE for non-MST UNIPHY. + * SW assign DIG_FE to non-MST UNIPHY first and MST last. So prefer + * DIG is per UNIPHY and used by SST DP, eDP, HDMI, DVI and LVDS. + * Prefer DIG assignment is decided by board design. + * For DCE 8.0, there are only max 6 UNIPHYs, we assume board design + * and VBIOS will filter out 7 UNIPHY for DCE 8.0. + * By this, adding DIGG should not hurt DCE 8.0. + * This will let DCE 8.1 share DCE 8.0 as much as possible + */ + + enc10->link_regs = link_regs; + enc10->aux_regs = aux_regs; + enc10->hpd_regs = hpd_regs; + enc10->link_shift = link_shift; + enc10->link_mask = link_mask; + + switch (enc10->base.transmitter) { + case TRANSMITTER_UNIPHY_A: + enc10->base.preferred_engine = ENGINE_ID_DIGA; + break; + case TRANSMITTER_UNIPHY_B: + enc10->base.preferred_engine = ENGINE_ID_DIGB; + break; + case TRANSMITTER_UNIPHY_C: + enc10->base.preferred_engine = ENGINE_ID_DIGC; + break; + case TRANSMITTER_UNIPHY_D: + enc10->base.preferred_engine = ENGINE_ID_DIGD; + break; + case TRANSMITTER_UNIPHY_E: + enc10->base.preferred_engine = ENGINE_ID_DIGE; + break; + case TRANSMITTER_UNIPHY_F: + enc10->base.preferred_engine = ENGINE_ID_DIGF; + break; + case TRANSMITTER_UNIPHY_G: + enc10->base.preferred_engine = ENGINE_ID_DIGG; + break; + default: + ASSERT_CRITICAL(false); + enc10->base.preferred_engine = ENGINE_ID_UNKNOWN; + } + + /* default to one to mirror Windows behavior */ + enc10->base.features.flags.bits.HDMI_6GB_EN = 1; + + result = bp_funcs->get_encoder_cap_info(enc10->base.ctx->dc_bios, + enc10->base.id, &bp_cap_info); + + /* Override features with DCE-specific values */ + if (result == BP_RESULT_OK) { + enc10->base.features.flags.bits.IS_HBR2_CAPABLE = + bp_cap_info.DP_HBR2_EN; + enc10->base.features.flags.bits.IS_HBR3_CAPABLE = + bp_cap_info.DP_HBR3_EN; + enc10->base.features.flags.bits.HDMI_6GB_EN = bp_cap_info.HDMI_6GB_EN; + enc10->base.features.flags.bits.IS_DP2_CAPABLE = bp_cap_info.IS_DP2_CAPABLE; + enc10->base.features.flags.bits.IS_UHBR10_CAPABLE = bp_cap_info.DP_UHBR10_EN; + enc10->base.features.flags.bits.IS_UHBR13_5_CAPABLE = bp_cap_info.DP_UHBR13_5_EN; + enc10->base.features.flags.bits.IS_UHBR20_CAPABLE = bp_cap_info.DP_UHBR20_EN; + enc10->base.features.flags.bits.DP_IS_USB_C = + bp_cap_info.DP_IS_USB_C; + } else { + DC_LOG_WARNING("%s: Failed to get encoder_cap_info from VBIOS with error code %d!\n", + __func__, + result); + } + if (enc10->base.ctx->dc->debug.hdmi20_disable) { + enc10->base.features.flags.bits.HDMI_6GB_EN = 0; + } +} + +#define AUX_REG(reg)\ + (enc10->aux_regs->reg) + +#define AUX_REG_READ(reg_name) \ + dm_read_reg(CTX, AUX_REG(reg_name)) + +#define AUX_REG_WRITE(reg_name, val) \ + dm_write_reg(CTX, AUX_REG(reg_name), val) +void enc3_hw_init(struct link_encoder *enc) +{ + struct dcn10_link_encoder *enc10 = TO_DCN10_LINK_ENC(enc); + +/* + 00 - DP_AUX_DPHY_RX_DETECTION_THRESHOLD__1to2 : 1/2 + 01 - DP_AUX_DPHY_RX_DETECTION_THRESHOLD__3to4 : 3/4 + 02 - DP_AUX_DPHY_RX_DETECTION_THRESHOLD__7to8 : 7/8 + 03 - DP_AUX_DPHY_RX_DETECTION_THRESHOLD__15to16 : 15/16 + 04 - DP_AUX_DPHY_RX_DETECTION_THRESHOLD__31to32 : 31/32 + 05 - DP_AUX_DPHY_RX_DETECTION_THRESHOLD__63to64 : 63/64 + 06 - DP_AUX_DPHY_RX_DETECTION_THRESHOLD__127to128 : 127/128 + 07 - DP_AUX_DPHY_RX_DETECTION_THRESHOLD__255to256 : 255/256 +*/ + +/* + AUX_REG_UPDATE_5(AUX_DPHY_RX_CONTROL0, + AUX_RX_START_WINDOW = 1 [6:4] + AUX_RX_RECEIVE_WINDOW = 1 default is 2 [10:8] + AUX_RX_HALF_SYM_DETECT_LEN = 1 [13:12] default is 1 + AUX_RX_TRANSITION_FILTER_EN = 1 [16] default is 1 + AUX_RX_ALLOW_BELOW_THRESHOLD_PHASE_DETECT [17] is 0 default is 0 + AUX_RX_ALLOW_BELOW_THRESHOLD_START [18] is 1 default is 1 + AUX_RX_ALLOW_BELOW_THRESHOLD_STOP [19] is 1 default is 1 + AUX_RX_PHASE_DETECT_LEN, [21,20] = 0x3 default is 3 + AUX_RX_DETECTION_THRESHOLD [30:28] = 1 +*/ + AUX_REG_WRITE(AUX_DPHY_RX_CONTROL0, 0x103d1110); + + AUX_REG_WRITE(AUX_DPHY_TX_CONTROL, 0x21c7a); + + //AUX_DPHY_TX_REF_CONTROL'AUX_TX_REF_DIV HW default is 0x32; + // Set AUX_TX_REF_DIV Divider to generate 2 MHz reference from refclk + // 27MHz -> 0xd + // 100MHz -> 0x32 + // 48MHz -> 0x18 + + // Set TMDS_CTL0 to 1. This is a legacy setting. + REG_UPDATE(TMDS_CTL_BITS, TMDS_CTL0, 1); + + dcn10_aux_initialize(enc10); +} diff --git a/drivers/gpu/drm/amd/display/dc/dio/dcn30/dcn30_dio_link_encoder.h b/drivers/gpu/drm/amd/display/dc/dio/dcn30/dcn30_dio_link_encoder.h new file mode 100644 index 000000000000..5b6177c2ae98 --- /dev/null +++ b/drivers/gpu/drm/amd/display/dc/dio/dcn30/dcn30_dio_link_encoder.h @@ -0,0 +1,86 @@ +/* + * Copyright 2020 Advanced Micro Devices, Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + * + * Authors: AMD + * + */ + +#ifndef __DC_LINK_ENCODER__DCN30_H__ +#define __DC_LINK_ENCODER__DCN30_H__ + +#include "dcn20/dcn20_link_encoder.h" + +#define LE_DCN3_REG_LIST(id)\ + SRI(DIG_BE_CNTL, DIG, id), \ + SRI(DIG_BE_EN_CNTL, DIG, id), \ + SRI(TMDS_CTL_BITS, DIG, id), \ + SRI(TMDS_DCBALANCER_CONTROL, DIG, id), \ + SRI(DP_CONFIG, DP, id), \ + SRI(DP_DPHY_CNTL, DP, id), \ + SRI(DP_DPHY_PRBS_CNTL, DP, id), \ + SRI(DP_DPHY_SCRAM_CNTL, DP, id),\ + SRI(DP_DPHY_SYM0, DP, id), \ + SRI(DP_DPHY_SYM1, DP, id), \ + SRI(DP_DPHY_SYM2, DP, id), \ + SRI(DP_DPHY_TRAINING_PATTERN_SEL, DP, id), \ + SRI(DP_LINK_CNTL, DP, id), \ + SRI(DP_LINK_FRAMING_CNTL, DP, id), \ + SRI(DP_MSE_SAT0, DP, id), \ + SRI(DP_MSE_SAT1, DP, id), \ + SRI(DP_MSE_SAT2, DP, id), \ + SRI(DP_MSE_SAT_UPDATE, DP, id), \ + SRI(DP_SEC_CNTL, DP, id), \ + SRI(DP_VID_STREAM_CNTL, DP, id), \ + SRI(DP_DPHY_FAST_TRAINING, DP, id), \ + SRI(DP_SEC_CNTL1, DP, id), \ + SRI(DP_DPHY_BS_SR_SWAP_CNTL, DP, id), \ + SRI(DP_DPHY_HBR2_PATTERN_CONTROL, DP, id) + +#define LINK_ENCODER_MASK_SH_LIST_DCN30(mask_sh) \ + LINK_ENCODER_MASK_SH_LIST_DCN20(mask_sh),\ + LE_SF(DIG0_TMDS_DCBALANCER_CONTROL, TMDS_SYNC_DCBAL_EN, mask_sh) + +#define DPCS_DCN3_MASK_SH_LIST(mask_sh)\ + DPCS_DCN2_MASK_SH_LIST(mask_sh),\ + LE_SF(DPCSTX0_DPCSTX_TX_CNTL, DPCS_TX_DATA_ORDER_INVERT_18_BIT, mask_sh),\ + LE_SF(RDPCSTX0_RDPCSTX_PHY_CNTL0, RDPCS_PHY_TX_VBOOST_LVL, mask_sh),\ + LE_SF(RDPCSTX0_RDPCSTX_CLOCK_CNTL, RDPCS_TX_CLK_EN, mask_sh),\ + LE_SF(RDPCSTX0_RDPCSTX_PHY_CNTL6, RDPCS_PHY_DPALT_DP4, mask_sh),\ + LE_SF(RDPCSTX0_RDPCSTX_PHY_CNTL6, RDPCS_PHY_DPALT_DISABLE, mask_sh) + + +void dcn30_link_encoder_construct( + struct dcn20_link_encoder *enc20, + const struct encoder_init_data *init_data, + const struct encoder_feature_support *enc_features, + const struct dcn10_link_enc_registers *link_regs, + const struct dcn10_link_enc_aux_registers *aux_regs, + const struct dcn10_link_enc_hpd_registers *hpd_regs, + const struct dcn10_link_enc_shift *link_shift, + const struct dcn10_link_enc_mask *link_mask); + +void enc3_hw_init(struct link_encoder *enc); + +bool dcn30_link_encoder_validate_output_with_stream( + struct link_encoder *enc, + const struct dc_stream_state *stream); + +#endif /* __DC_LINK_ENCODER__DCN30_H__ */ diff --git a/drivers/gpu/drm/amd/display/dc/dio/dcn30/dcn30_dio_stream_encoder.c b/drivers/gpu/drm/amd/display/dc/dio/dcn30/dcn30_dio_stream_encoder.c new file mode 100644 index 000000000000..425b830b88d2 --- /dev/null +++ b/drivers/gpu/drm/amd/display/dc/dio/dcn30/dcn30_dio_stream_encoder.c @@ -0,0 +1,899 @@ +/* + * Copyright 2020 Advanced Micro Devices, Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + * + * Authors: AMD + * + */ + + +#include "dc_bios_types.h" +#include "dcn30_dio_stream_encoder.h" +#include "reg_helper.h" +#include "hw_shared.h" +#include "dc.h" + +#define DC_LOGGER \ + enc1->base.ctx->logger + +#define REG(reg)\ + (enc1->regs->reg) + +#undef FN +#define FN(reg_name, field_name) \ + enc1->se_shift->field_name, enc1->se_mask->field_name + +#define VBI_LINE_0 0 +#define HDMI_CLOCK_CHANNEL_RATE_MORE_340M 340000 + +#define CTX \ + enc1->base.ctx + + +static void enc3_update_hdmi_info_packet( + struct dcn10_stream_encoder *enc1, + uint32_t packet_index, + const struct dc_info_packet *info_packet) +{ + uint32_t cont, send, line; + + if (info_packet->valid) { + enc1->base.vpg->funcs->update_generic_info_packet( + enc1->base.vpg, + packet_index, + info_packet, + true); + + /* enable transmission of packet(s) - + * packet transmission begins on the next frame */ + cont = 1; + /* send packet(s) every frame */ + send = 1; + /* select line number to send packets on */ + line = 2; + } else { + cont = 0; + send = 0; + line = 0; + } + + /* DP_SEC_GSP[x]_LINE_REFERENCE - keep default value REFER_TO_DP_SOF */ + + /* choose which generic packet control to use */ + switch (packet_index) { + case 0: + REG_UPDATE_2(HDMI_GENERIC_PACKET_CONTROL0, + HDMI_GENERIC0_CONT, cont, + HDMI_GENERIC0_SEND, send); + REG_UPDATE(HDMI_GENERIC_PACKET_CONTROL1, + HDMI_GENERIC0_LINE, line); + break; + case 1: + REG_UPDATE_2(HDMI_GENERIC_PACKET_CONTROL0, + HDMI_GENERIC1_CONT, cont, + HDMI_GENERIC1_SEND, send); + REG_UPDATE(HDMI_GENERIC_PACKET_CONTROL1, + HDMI_GENERIC1_LINE, line); + break; + case 2: + REG_UPDATE_2(HDMI_GENERIC_PACKET_CONTROL0, + HDMI_GENERIC2_CONT, cont, + HDMI_GENERIC2_SEND, send); + REG_UPDATE(HDMI_GENERIC_PACKET_CONTROL2, + HDMI_GENERIC2_LINE, line); + break; + case 3: + REG_UPDATE_2(HDMI_GENERIC_PACKET_CONTROL0, + HDMI_GENERIC3_CONT, cont, + HDMI_GENERIC3_SEND, send); + REG_UPDATE(HDMI_GENERIC_PACKET_CONTROL2, + HDMI_GENERIC3_LINE, line); + break; + case 4: + REG_UPDATE_2(HDMI_GENERIC_PACKET_CONTROL0, + HDMI_GENERIC4_CONT, cont, + HDMI_GENERIC4_SEND, send); + REG_UPDATE(HDMI_GENERIC_PACKET_CONTROL3, + HDMI_GENERIC4_LINE, line); + break; + case 5: + REG_UPDATE_2(HDMI_GENERIC_PACKET_CONTROL0, + HDMI_GENERIC5_CONT, cont, + HDMI_GENERIC5_SEND, send); + REG_UPDATE(HDMI_GENERIC_PACKET_CONTROL3, + HDMI_GENERIC5_LINE, line); + break; + case 6: + REG_UPDATE_2(HDMI_GENERIC_PACKET_CONTROL0, + HDMI_GENERIC6_CONT, cont, + HDMI_GENERIC6_SEND, send); + REG_UPDATE(HDMI_GENERIC_PACKET_CONTROL4, + HDMI_GENERIC6_LINE, line); + break; + case 7: + REG_UPDATE_2(HDMI_GENERIC_PACKET_CONTROL0, + HDMI_GENERIC7_CONT, cont, + HDMI_GENERIC7_SEND, send); + REG_UPDATE(HDMI_GENERIC_PACKET_CONTROL4, + HDMI_GENERIC7_LINE, line); + break; + case 8: + REG_UPDATE_2(HDMI_GENERIC_PACKET_CONTROL6, + HDMI_GENERIC8_CONT, cont, + HDMI_GENERIC8_SEND, send); + REG_UPDATE(HDMI_GENERIC_PACKET_CONTROL7, + HDMI_GENERIC8_LINE, line); + break; + case 9: + REG_UPDATE_2(HDMI_GENERIC_PACKET_CONTROL6, + HDMI_GENERIC9_CONT, cont, + HDMI_GENERIC9_SEND, send); + REG_UPDATE(HDMI_GENERIC_PACKET_CONTROL7, + HDMI_GENERIC9_LINE, line); + break; + case 10: + REG_UPDATE_2(HDMI_GENERIC_PACKET_CONTROL6, + HDMI_GENERIC10_CONT, cont, + HDMI_GENERIC10_SEND, send); + REG_UPDATE(HDMI_GENERIC_PACKET_CONTROL8, + HDMI_GENERIC10_LINE, line); + break; + case 11: + REG_UPDATE_2(HDMI_GENERIC_PACKET_CONTROL6, + HDMI_GENERIC11_CONT, cont, + HDMI_GENERIC11_SEND, send); + REG_UPDATE(HDMI_GENERIC_PACKET_CONTROL8, + HDMI_GENERIC11_LINE, line); + break; + case 12: + REG_UPDATE_2(HDMI_GENERIC_PACKET_CONTROL6, + HDMI_GENERIC12_CONT, cont, + HDMI_GENERIC12_SEND, send); + REG_UPDATE(HDMI_GENERIC_PACKET_CONTROL9, + HDMI_GENERIC12_LINE, line); + break; + case 13: + REG_UPDATE_2(HDMI_GENERIC_PACKET_CONTROL6, + HDMI_GENERIC13_CONT, cont, + HDMI_GENERIC13_SEND, send); + REG_UPDATE(HDMI_GENERIC_PACKET_CONTROL9, + HDMI_GENERIC13_LINE, line); + break; + case 14: + REG_UPDATE_2(HDMI_GENERIC_PACKET_CONTROL6, + HDMI_GENERIC14_CONT, cont, + HDMI_GENERIC14_SEND, send); + REG_UPDATE(HDMI_GENERIC_PACKET_CONTROL10, + HDMI_GENERIC14_LINE, line); + break; + default: + /* invalid HW packet index */ + DC_LOG_WARNING( + "Invalid HW packet index: %s()\n", + __func__); + return; + } +} + +void enc3_stream_encoder_update_hdmi_info_packets( + struct stream_encoder *enc, + const struct encoder_info_frame *info_frame) +{ + struct dcn10_stream_encoder *enc1 = DCN10STRENC_FROM_STRENC(enc); + + /* for bring up, disable dp double TODO */ + REG_UPDATE(HDMI_DB_CONTROL, HDMI_DB_DISABLE, 1); + REG_UPDATE(AFMT_CNTL, AFMT_AUDIO_CLOCK_EN, 1); + + /*Always add mandatory packets first followed by optional ones*/ + enc3_update_hdmi_info_packet(enc1, 0, &info_frame->avi); + enc3_update_hdmi_info_packet(enc1, 5, &info_frame->hfvsif); + enc3_update_hdmi_info_packet(enc1, 2, &info_frame->gamut); + enc3_update_hdmi_info_packet(enc1, 1, &info_frame->vendor); + enc3_update_hdmi_info_packet(enc1, 3, &info_frame->spd); + enc3_update_hdmi_info_packet(enc1, 4, &info_frame->hdrsmd); + enc3_update_hdmi_info_packet(enc1, 6, &info_frame->vtem); +} + +void enc3_stream_encoder_stop_hdmi_info_packets( + struct stream_encoder *enc) +{ + struct dcn10_stream_encoder *enc1 = DCN10STRENC_FROM_STRENC(enc); + + /* stop generic packets 0,1 on HDMI */ + REG_SET_4(HDMI_GENERIC_PACKET_CONTROL0, 0, + HDMI_GENERIC0_CONT, 0, + HDMI_GENERIC0_SEND, 0, + HDMI_GENERIC1_CONT, 0, + HDMI_GENERIC1_SEND, 0); + REG_SET_2(HDMI_GENERIC_PACKET_CONTROL1, 0, + HDMI_GENERIC0_LINE, 0, + HDMI_GENERIC1_LINE, 0); + + /* stop generic packets 2,3 on HDMI */ + REG_SET_4(HDMI_GENERIC_PACKET_CONTROL0, 0, + HDMI_GENERIC2_CONT, 0, + HDMI_GENERIC2_SEND, 0, + HDMI_GENERIC3_CONT, 0, + HDMI_GENERIC3_SEND, 0); + REG_SET_2(HDMI_GENERIC_PACKET_CONTROL2, 0, + HDMI_GENERIC2_LINE, 0, + HDMI_GENERIC3_LINE, 0); + + /* stop generic packets 4,5 on HDMI */ + REG_SET_4(HDMI_GENERIC_PACKET_CONTROL0, 0, + HDMI_GENERIC4_CONT, 0, + HDMI_GENERIC4_SEND, 0, + HDMI_GENERIC5_CONT, 0, + HDMI_GENERIC5_SEND, 0); + REG_SET_2(HDMI_GENERIC_PACKET_CONTROL3, 0, + HDMI_GENERIC4_LINE, 0, + HDMI_GENERIC5_LINE, 0); + + /* stop generic packets 6,7 on HDMI */ + REG_SET_4(HDMI_GENERIC_PACKET_CONTROL0, 0, + HDMI_GENERIC6_CONT, 0, + HDMI_GENERIC6_SEND, 0, + HDMI_GENERIC7_CONT, 0, + HDMI_GENERIC7_SEND, 0); + REG_SET_2(HDMI_GENERIC_PACKET_CONTROL4, 0, + HDMI_GENERIC6_LINE, 0, + HDMI_GENERIC7_LINE, 0); + + /* stop generic packets 8,9 on HDMI */ + REG_SET_4(HDMI_GENERIC_PACKET_CONTROL6, 0, + HDMI_GENERIC8_CONT, 0, + HDMI_GENERIC8_SEND, 0, + HDMI_GENERIC9_CONT, 0, + HDMI_GENERIC9_SEND, 0); + REG_SET_2(HDMI_GENERIC_PACKET_CONTROL7, 0, + HDMI_GENERIC8_LINE, 0, + HDMI_GENERIC9_LINE, 0); + + /* stop generic packets 10,11 on HDMI */ + REG_SET_4(HDMI_GENERIC_PACKET_CONTROL6, 0, + HDMI_GENERIC10_CONT, 0, + HDMI_GENERIC10_SEND, 0, + HDMI_GENERIC11_CONT, 0, + HDMI_GENERIC11_SEND, 0); + REG_SET_2(HDMI_GENERIC_PACKET_CONTROL8, 0, + HDMI_GENERIC10_LINE, 0, + HDMI_GENERIC11_LINE, 0); + + /* stop generic packets 12,13 on HDMI */ + REG_SET_4(HDMI_GENERIC_PACKET_CONTROL6, 0, + HDMI_GENERIC12_CONT, 0, + HDMI_GENERIC12_SEND, 0, + HDMI_GENERIC13_CONT, 0, + HDMI_GENERIC13_SEND, 0); + REG_SET_2(HDMI_GENERIC_PACKET_CONTROL9, 0, + HDMI_GENERIC12_LINE, 0, + HDMI_GENERIC13_LINE, 0); + + /* stop generic packet 14 on HDMI */ + REG_SET_2(HDMI_GENERIC_PACKET_CONTROL6, 0, + HDMI_GENERIC14_CONT, 0, + HDMI_GENERIC14_SEND, 0); + REG_UPDATE(HDMI_GENERIC_PACKET_CONTROL10, + HDMI_GENERIC14_LINE, 0); +} + +/* Set DSC-related configuration. + * dsc_mode: 0 disables DSC, other values enable DSC in specified format + * sc_bytes_per_pixel: Bytes per pixel in u3.28 format + * dsc_slice_width: Slice width in pixels + */ +static void enc3_dp_set_dsc_config(struct stream_encoder *enc, + enum optc_dsc_mode dsc_mode, + uint32_t dsc_bytes_per_pixel, + uint32_t dsc_slice_width) +{ + struct dcn10_stream_encoder *enc1 = DCN10STRENC_FROM_STRENC(enc); + + REG_UPDATE_2(DP_DSC_CNTL, + DP_DSC_MODE, dsc_mode, + DP_DSC_SLICE_WIDTH, dsc_slice_width); + + REG_SET(DP_DSC_BYTES_PER_PIXEL, 0, + DP_DSC_BYTES_PER_PIXEL, dsc_bytes_per_pixel); +} + + +void enc3_dp_set_dsc_pps_info_packet(struct stream_encoder *enc, + bool enable, + uint8_t *dsc_packed_pps, + bool immediate_update) +{ + struct dcn10_stream_encoder *enc1 = DCN10STRENC_FROM_STRENC(enc); + + if (enable) { + struct dc_info_packet pps_sdp; + int i; + + /* Configure for PPS packet size (128 bytes) */ + REG_UPDATE(DP_SEC_CNTL2, DP_SEC_GSP11_PPS, 1); + + /* We need turn on clock before programming AFMT block + * + * TODO: We may not need this here anymore since update_generic_info_packet + * no longer touches AFMT + */ + REG_UPDATE(AFMT_CNTL, AFMT_AUDIO_CLOCK_EN, 1); + + /* Load PPS into infoframe (SDP) registers */ + pps_sdp.valid = true; + pps_sdp.hb0 = 0; + pps_sdp.hb1 = DC_DP_INFOFRAME_TYPE_PPS; + pps_sdp.hb2 = 127; + pps_sdp.hb3 = 0; + + for (i = 0; i < 4; i++) { + memcpy(pps_sdp.sb, &dsc_packed_pps[i * 32], 32); + enc1->base.vpg->funcs->update_generic_info_packet( + enc1->base.vpg, + 11 + i, + &pps_sdp, + immediate_update); + } + + /* SW should make sure VBID[6] update line number is bigger + * than PPS transmit line number + */ + REG_UPDATE(DP_GSP11_CNTL, + DP_SEC_GSP11_LINE_NUM, 2); + REG_UPDATE_2(DP_MSA_VBID_MISC, + DP_VBID6_LINE_REFERENCE, 0, + DP_VBID6_LINE_NUM, 3); + + /* Send PPS data at the line number specified above. + * DP spec requires PPS to be sent only when it changes, however since + * decoder has to be able to handle its change on every frame, we're + * sending it always (i.e. on every frame) to reduce the chance it'd be + * missed by decoder. If it turns out required to send PPS only when it + * changes, we can use DP_SEC_GSP11_SEND register. + */ + REG_UPDATE(DP_GSP11_CNTL, + DP_SEC_GSP11_ENABLE, 1); + REG_UPDATE(DP_SEC_CNTL, + DP_SEC_STREAM_ENABLE, 1); + } else { + /* Disable Generic Stream Packet 11 (GSP) transmission */ + REG_UPDATE(DP_GSP11_CNTL, DP_SEC_GSP11_ENABLE, 0); + REG_UPDATE(DP_SEC_CNTL2, DP_SEC_GSP11_PPS, 0); + } +} + + +/* this function read dsc related register fields to be logged later in dcn10_log_hw_state + * into a dcn_dsc_state struct. + */ +static void enc3_read_state(struct stream_encoder *enc, struct enc_state *s) +{ + struct dcn10_stream_encoder *enc1 = DCN10STRENC_FROM_STRENC(enc); + + //if dsc is enabled, continue to read + REG_GET(DP_DSC_CNTL, DP_DSC_MODE, &s->dsc_mode); + if (s->dsc_mode) { + REG_GET(DP_DSC_CNTL, DP_DSC_SLICE_WIDTH, &s->dsc_slice_width); + REG_GET(DP_GSP11_CNTL, DP_SEC_GSP11_LINE_NUM, &s->sec_gsp_pps_line_num); + + REG_GET(DP_MSA_VBID_MISC, DP_VBID6_LINE_REFERENCE, &s->vbid6_line_reference); + REG_GET(DP_MSA_VBID_MISC, DP_VBID6_LINE_NUM, &s->vbid6_line_num); + + REG_GET(DP_GSP11_CNTL, DP_SEC_GSP11_ENABLE, &s->sec_gsp_pps_enable); + REG_GET(DP_SEC_CNTL, DP_SEC_STREAM_ENABLE, &s->sec_stream_enable); + } +} + +void enc3_stream_encoder_update_dp_info_packets_sdp_line_num( + struct stream_encoder *enc, + struct encoder_info_frame *info_frame) +{ + struct dcn10_stream_encoder *enc1 = DCN10STRENC_FROM_STRENC(enc); + + if (info_frame->adaptive_sync.valid == true && + info_frame->sdp_line_num.adaptive_sync_line_num_valid == true) { + //00: REFER_TO_DP_SOF, 01: REFER_TO_OTG_SOF + REG_UPDATE(DP_SEC_CNTL1, DP_SEC_GSP5_LINE_REFERENCE, 1); + + REG_UPDATE(DP_SEC_CNTL5, DP_SEC_GSP5_LINE_NUM, + info_frame->sdp_line_num.adaptive_sync_line_num); + } +} + +void enc3_stream_encoder_update_dp_info_packets( + struct stream_encoder *enc, + const struct encoder_info_frame *info_frame) +{ + struct dcn10_stream_encoder *enc1 = DCN10STRENC_FROM_STRENC(enc); + uint32_t value = 0; + uint32_t dmdata_packet_enabled = 0; + + if (info_frame->vsc.valid) { + enc->vpg->funcs->update_generic_info_packet( + enc->vpg, + 0, /* packetIndex */ + &info_frame->vsc, + true); + } + /* TODO: VSC SDP at packetIndex 1 should be retricted only if PSR-SU on. + * There should have another Infopacket type (e.g. vsc_psrsu) for PSR_SU. + * In addition, currently the driver check the valid bit then update and + * send the corresponding Infopacket. For PSR-SU, the SDP only be sent + * while entering PSR-SU mode. So we need another parameter(e.g. send) + * in dc_info_packet to indicate which infopacket should be enabled by + * default here. + */ + if (info_frame->vsc.valid) { + enc->vpg->funcs->update_generic_info_packet( + enc->vpg, + 1, /* packetIndex */ + &info_frame->vsc, + true); + } + /* TODO: VSC SDP at packetIndex 1 should be restricted only if PSR-SU on. + * There should have another Infopacket type (e.g. vsc_psrsu) for PSR_SU. + * In addition, currently the driver check the valid bit then update and + * send the corresponding Infopacket. For PSR-SU, the SDP only be sent + * while entering PSR-SU mode. So we need another parameter(e.g. send) + * in dc_info_packet to indicate which infopacket should be enabled by + * default here. + */ + if (info_frame->vsc.valid) { + enc->vpg->funcs->update_generic_info_packet( + enc->vpg, + 1, /* packetIndex */ + &info_frame->vsc, + true); + } + if (info_frame->spd.valid) { + enc->vpg->funcs->update_generic_info_packet( + enc->vpg, + 2, /* packetIndex */ + &info_frame->spd, + true); + } + if (info_frame->hdrsmd.valid) { + enc->vpg->funcs->update_generic_info_packet( + enc->vpg, + 3, /* packetIndex */ + &info_frame->hdrsmd, + true); + } + /* packetIndex 4 is used for send immediate sdp message, and please + * use other packetIndex (such as 5,6) for other info packet + */ + + if (info_frame->adaptive_sync.valid) + enc->vpg->funcs->update_generic_info_packet( + enc->vpg, + 5, /* packetIndex */ + &info_frame->adaptive_sync, + true); + + /* enable/disable transmission of packet(s). + * If enabled, packet transmission begins on the next frame + */ + REG_UPDATE(DP_SEC_CNTL, DP_SEC_GSP0_ENABLE, info_frame->vsc.valid); + REG_UPDATE(DP_SEC_CNTL, DP_SEC_GSP2_ENABLE, info_frame->spd.valid); + REG_UPDATE(DP_SEC_CNTL, DP_SEC_GSP3_ENABLE, info_frame->hdrsmd.valid); + REG_UPDATE(DP_SEC_CNTL, DP_SEC_GSP5_ENABLE, info_frame->adaptive_sync.valid); + + /* This bit is the master enable bit. + * When enabling secondary stream engine, + * this master bit must also be set. + * This register shared with audio info frame. + * Therefore we need to enable master bit + * if at least on of the fields is not 0 + */ + value = REG_READ(DP_SEC_CNTL); + if (value) + REG_UPDATE(DP_SEC_CNTL, DP_SEC_STREAM_ENABLE, 1); + + /* check if dynamic metadata packet transmission is enabled */ + REG_GET(DP_SEC_METADATA_TRANSMISSION, + DP_SEC_METADATA_PACKET_ENABLE, &dmdata_packet_enabled); + + if (dmdata_packet_enabled) + REG_UPDATE(DP_SEC_CNTL, DP_SEC_STREAM_ENABLE, 1); +} + +static void enc3_dp_set_odm_combine( + struct stream_encoder *enc, + bool odm_combine) +{ + struct dcn10_stream_encoder *enc1 = DCN10STRENC_FROM_STRENC(enc); + + REG_UPDATE(DP_PIXEL_FORMAT, DP_PIXEL_COMBINE, odm_combine); +} + +/* setup stream encoder in dvi mode */ +static void enc3_stream_encoder_dvi_set_stream_attribute( + struct stream_encoder *enc, + struct dc_crtc_timing *crtc_timing, + bool is_dual_link) +{ + struct dcn10_stream_encoder *enc1 = DCN10STRENC_FROM_STRENC(enc); + + if (!enc->ctx->dc->debug.avoid_vbios_exec_table) { + struct bp_encoder_control cntl = {0}; + + cntl.action = ENCODER_CONTROL_SETUP; + cntl.engine_id = enc1->base.id; + cntl.signal = is_dual_link ? + SIGNAL_TYPE_DVI_DUAL_LINK : SIGNAL_TYPE_DVI_SINGLE_LINK; + cntl.enable_dp_audio = false; + cntl.pixel_clock = crtc_timing->pix_clk_100hz / 10; + cntl.lanes_number = (is_dual_link) ? LANE_COUNT_EIGHT : LANE_COUNT_FOUR; + + if (enc1->base.bp->funcs->encoder_control( + enc1->base.bp, &cntl) != BP_RESULT_OK) + return; + + } else { + + //Set pattern for clock channel, default vlue 0x63 does not work + REG_UPDATE(DIG_CLOCK_PATTERN, DIG_CLOCK_PATTERN, 0x1F); + + //DIG_BE_TMDS_DVI_MODE : TMDS-DVI mode is already set in link_encoder_setup + + //DIG_SOURCE_SELECT is already set in dig_connect_to_otg + + /* set DIG_START to 0x1 to reset FIFO */ + REG_UPDATE(DIG_FE_CNTL, DIG_START, 1); + udelay(1); + + /* write 0 to take the FIFO out of reset */ + REG_UPDATE(DIG_FE_CNTL, DIG_START, 0); + udelay(1); + } + + ASSERT(crtc_timing->pixel_encoding == PIXEL_ENCODING_RGB); + ASSERT(crtc_timing->display_color_depth == COLOR_DEPTH_888); + enc1_stream_encoder_set_stream_attribute_helper(enc1, crtc_timing); +} + +/* setup stream encoder in hdmi mode */ +static void enc3_stream_encoder_hdmi_set_stream_attribute( + struct stream_encoder *enc, + struct dc_crtc_timing *crtc_timing, + int actual_pix_clk_khz, + bool enable_audio) +{ + struct dcn10_stream_encoder *enc1 = DCN10STRENC_FROM_STRENC(enc); + + if (!enc->ctx->dc->debug.avoid_vbios_exec_table) { + struct bp_encoder_control cntl = {0}; + + cntl.action = ENCODER_CONTROL_SETUP; + cntl.engine_id = enc1->base.id; + cntl.signal = SIGNAL_TYPE_HDMI_TYPE_A; + cntl.enable_dp_audio = enable_audio; + cntl.pixel_clock = actual_pix_clk_khz; + cntl.lanes_number = LANE_COUNT_FOUR; + + if (enc1->base.bp->funcs->encoder_control( + enc1->base.bp, &cntl) != BP_RESULT_OK) + return; + + } else { + + //Set pattern for clock channel, default vlue 0x63 does not work + REG_UPDATE(DIG_CLOCK_PATTERN, DIG_CLOCK_PATTERN, 0x1F); + + //DIG_BE_TMDS_HDMI_MODE : TMDS-HDMI mode is already set in link_encoder_setup + + //DIG_SOURCE_SELECT is already set in dig_connect_to_otg + + /* set DIG_START to 0x1 to reset FIFO */ + REG_UPDATE(DIG_FE_CNTL, DIG_START, 1); + udelay(1); + + /* write 0 to take the FIFO out of reset */ + REG_UPDATE(DIG_FE_CNTL, DIG_START, 0); + udelay(1); + } + + /* Configure pixel encoding */ + enc1_stream_encoder_set_stream_attribute_helper(enc1, crtc_timing); + + /* setup HDMI engine */ + REG_UPDATE_6(HDMI_CONTROL, + HDMI_PACKET_GEN_VERSION, 1, + HDMI_KEEPOUT_MODE, 1, + HDMI_DEEP_COLOR_ENABLE, 0, + HDMI_DATA_SCRAMBLE_EN, 0, + HDMI_NO_EXTRA_NULL_PACKET_FILLED, 1, + HDMI_CLOCK_CHANNEL_RATE, 0); + + /* Configure color depth */ + switch (crtc_timing->display_color_depth) { + case COLOR_DEPTH_888: + REG_UPDATE(HDMI_CONTROL, HDMI_DEEP_COLOR_DEPTH, 0); + break; + case COLOR_DEPTH_101010: + if (crtc_timing->pixel_encoding == PIXEL_ENCODING_YCBCR422) { + REG_UPDATE_2(HDMI_CONTROL, + HDMI_DEEP_COLOR_DEPTH, 1, + HDMI_DEEP_COLOR_ENABLE, 0); + } else { + REG_UPDATE_2(HDMI_CONTROL, + HDMI_DEEP_COLOR_DEPTH, 1, + HDMI_DEEP_COLOR_ENABLE, 1); + } + break; + case COLOR_DEPTH_121212: + if (crtc_timing->pixel_encoding == PIXEL_ENCODING_YCBCR422) { + REG_UPDATE_2(HDMI_CONTROL, + HDMI_DEEP_COLOR_DEPTH, 2, + HDMI_DEEP_COLOR_ENABLE, 0); + } else { + REG_UPDATE_2(HDMI_CONTROL, + HDMI_DEEP_COLOR_DEPTH, 2, + HDMI_DEEP_COLOR_ENABLE, 1); + } + break; + case COLOR_DEPTH_161616: + REG_UPDATE_2(HDMI_CONTROL, + HDMI_DEEP_COLOR_DEPTH, 3, + HDMI_DEEP_COLOR_ENABLE, 1); + break; + default: + break; + } + + if (actual_pix_clk_khz >= HDMI_CLOCK_CHANNEL_RATE_MORE_340M) { + /* enable HDMI data scrambler + * HDMI_CLOCK_CHANNEL_RATE_MORE_340M + * Clock channel frequency is 1/4 of character rate. + */ + REG_UPDATE_2(HDMI_CONTROL, + HDMI_DATA_SCRAMBLE_EN, 1, + HDMI_CLOCK_CHANNEL_RATE, 1); + } else if (crtc_timing->flags.LTE_340MCSC_SCRAMBLE) { + + /* TODO: New feature for DCE11, still need to implement */ + + /* enable HDMI data scrambler + * HDMI_CLOCK_CHANNEL_FREQ_EQUAL_TO_CHAR_RATE + * Clock channel frequency is the same + * as character rate + */ + REG_UPDATE_2(HDMI_CONTROL, + HDMI_DATA_SCRAMBLE_EN, 1, + HDMI_CLOCK_CHANNEL_RATE, 0); + } + + + /* Enable transmission of General Control packet on every frame */ + REG_UPDATE_3(HDMI_VBI_PACKET_CONTROL, + HDMI_GC_CONT, 1, + HDMI_GC_SEND, 1, + HDMI_NULL_SEND, 1); + + /* Disable Audio Content Protection packet transmission */ + REG_UPDATE(HDMI_VBI_PACKET_CONTROL, HDMI_ACP_SEND, 0); + + /* following belongs to audio */ + /* Enable Audio InfoFrame packet transmission. */ + REG_UPDATE(HDMI_INFOFRAME_CONTROL0, HDMI_AUDIO_INFO_SEND, 1); + + /* update double-buffered AUDIO_INFO registers immediately */ + ASSERT (enc->afmt); + enc->afmt->funcs->audio_info_immediate_update(enc->afmt); + + /* Select line number on which to send Audio InfoFrame packets */ + REG_UPDATE(HDMI_INFOFRAME_CONTROL1, HDMI_AUDIO_INFO_LINE, + VBI_LINE_0 + 2); + + /* set HDMI GC AVMUTE */ + REG_UPDATE(HDMI_GC, HDMI_GC_AVMUTE, 0); +} + +void enc3_audio_mute_control( + struct stream_encoder *enc, + bool mute) +{ + ASSERT (enc->afmt); + enc->afmt->funcs->audio_mute_control(enc->afmt, mute); +} + +void enc3_se_dp_audio_setup( + struct stream_encoder *enc, + unsigned int az_inst, + struct audio_info *info) +{ + ASSERT (enc->afmt); + enc->afmt->funcs->se_audio_setup(enc->afmt, az_inst, info); +} + +#define DP_SEC_AUD_N__DP_SEC_AUD_N__DEFAULT 0x8000 +#define DP_SEC_TIMESTAMP__DP_SEC_TIMESTAMP_MODE__AUTO_CALC 1 + +static void enc3_se_setup_dp_audio( + struct stream_encoder *enc) +{ + struct dcn10_stream_encoder *enc1 = DCN10STRENC_FROM_STRENC(enc); + + /* --- DP Audio packet configurations --- */ + + /* ATP Configuration */ + REG_SET(DP_SEC_AUD_N, 0, + DP_SEC_AUD_N, DP_SEC_AUD_N__DP_SEC_AUD_N__DEFAULT); + + /* Async/auto-calc timestamp mode */ + REG_SET(DP_SEC_TIMESTAMP, 0, DP_SEC_TIMESTAMP_MODE, + DP_SEC_TIMESTAMP__DP_SEC_TIMESTAMP_MODE__AUTO_CALC); + + ASSERT (enc->afmt); + enc->afmt->funcs->setup_dp_audio(enc->afmt); +} + +void enc3_se_dp_audio_enable( + struct stream_encoder *enc) +{ + enc1_se_enable_audio_clock(enc, true); + enc3_se_setup_dp_audio(enc); + enc1_se_enable_dp_audio(enc); +} + +static void enc3_se_setup_hdmi_audio( + struct stream_encoder *enc, + const struct audio_crtc_info *crtc_info) +{ + struct dcn10_stream_encoder *enc1 = DCN10STRENC_FROM_STRENC(enc); + + struct audio_clock_info audio_clock_info = {0}; + + /* Setup audio in AFMT - program AFMT block associated with DIO */ + ASSERT (enc->afmt); + enc->afmt->funcs->setup_hdmi_audio(enc->afmt); + + /* HDMI_AUDIO_PACKET_CONTROL */ + REG_UPDATE(HDMI_AUDIO_PACKET_CONTROL, + HDMI_AUDIO_DELAY_EN, 1); + + /* HDMI_ACR_PACKET_CONTROL */ + REG_UPDATE_3(HDMI_ACR_PACKET_CONTROL, + HDMI_ACR_AUTO_SEND, 1, + HDMI_ACR_SOURCE, 0, + HDMI_ACR_AUDIO_PRIORITY, 0); + + /* Program audio clock sample/regeneration parameters */ + get_audio_clock_info(crtc_info->color_depth, + crtc_info->requested_pixel_clock_100Hz, + crtc_info->calculated_pixel_clock_100Hz, + &audio_clock_info); + DC_LOG_HW_AUDIO( + "\n%s:Input::requested_pixel_clock_100Hz = %d" \ + "calculated_pixel_clock_100Hz = %d \n", __func__, \ + crtc_info->requested_pixel_clock_100Hz, \ + crtc_info->calculated_pixel_clock_100Hz); + + /* HDMI_ACR_32_0__HDMI_ACR_CTS_32_MASK */ + REG_UPDATE(HDMI_ACR_32_0, HDMI_ACR_CTS_32, audio_clock_info.cts_32khz); + + /* HDMI_ACR_32_1__HDMI_ACR_N_32_MASK */ + REG_UPDATE(HDMI_ACR_32_1, HDMI_ACR_N_32, audio_clock_info.n_32khz); + + /* HDMI_ACR_44_0__HDMI_ACR_CTS_44_MASK */ + REG_UPDATE(HDMI_ACR_44_0, HDMI_ACR_CTS_44, audio_clock_info.cts_44khz); + + /* HDMI_ACR_44_1__HDMI_ACR_N_44_MASK */ + REG_UPDATE(HDMI_ACR_44_1, HDMI_ACR_N_44, audio_clock_info.n_44khz); + + /* HDMI_ACR_48_0__HDMI_ACR_CTS_48_MASK */ + REG_UPDATE(HDMI_ACR_48_0, HDMI_ACR_CTS_48, audio_clock_info.cts_48khz); + + /* HDMI_ACR_48_1__HDMI_ACR_N_48_MASK */ + REG_UPDATE(HDMI_ACR_48_1, HDMI_ACR_N_48, audio_clock_info.n_48khz); + + /* Video driver cannot know in advance which sample rate will + * be used by HD Audio driver + * HDMI_ACR_PACKET_CONTROL__HDMI_ACR_N_MULTIPLE field is + * programmed below in interruppt callback + */ +} + +void enc3_se_hdmi_audio_setup( + struct stream_encoder *enc, + unsigned int az_inst, + struct audio_info *info, + struct audio_crtc_info *audio_crtc_info) +{ + enc1_se_enable_audio_clock(enc, true); + enc3_se_setup_hdmi_audio(enc, audio_crtc_info); + ASSERT (enc->afmt); + enc->afmt->funcs->se_audio_setup(enc->afmt, az_inst, info); +} + + +static const struct stream_encoder_funcs dcn30_str_enc_funcs = { + .dp_set_odm_combine = + enc3_dp_set_odm_combine, + .dp_set_stream_attribute = + enc2_stream_encoder_dp_set_stream_attribute, + .hdmi_set_stream_attribute = + enc3_stream_encoder_hdmi_set_stream_attribute, + .dvi_set_stream_attribute = + enc3_stream_encoder_dvi_set_stream_attribute, + .set_throttled_vcp_size = + enc1_stream_encoder_set_throttled_vcp_size, + .update_hdmi_info_packets = + enc3_stream_encoder_update_hdmi_info_packets, + .stop_hdmi_info_packets = + enc3_stream_encoder_stop_hdmi_info_packets, + .update_dp_info_packets_sdp_line_num = + enc3_stream_encoder_update_dp_info_packets_sdp_line_num, + .update_dp_info_packets = + enc3_stream_encoder_update_dp_info_packets, + .stop_dp_info_packets = + enc1_stream_encoder_stop_dp_info_packets, + .dp_blank = + enc1_stream_encoder_dp_blank, + .dp_unblank = + enc2_stream_encoder_dp_unblank, + .audio_mute_control = enc3_audio_mute_control, + + .dp_audio_setup = enc3_se_dp_audio_setup, + .dp_audio_enable = enc3_se_dp_audio_enable, + .dp_audio_disable = enc1_se_dp_audio_disable, + + .hdmi_audio_setup = enc3_se_hdmi_audio_setup, + .hdmi_audio_disable = enc1_se_hdmi_audio_disable, + .setup_stereo_sync = enc1_setup_stereo_sync, + .set_avmute = enc1_stream_encoder_set_avmute, + .dig_connect_to_otg = enc1_dig_connect_to_otg, + .dig_source_otg = enc1_dig_source_otg, + + .dp_get_pixel_format = enc1_stream_encoder_dp_get_pixel_format, + + .enc_read_state = enc3_read_state, + .dp_set_dsc_config = enc3_dp_set_dsc_config, + .dp_set_dsc_pps_info_packet = enc3_dp_set_dsc_pps_info_packet, + .set_dynamic_metadata = enc2_set_dynamic_metadata, + .hdmi_reset_stream_attribute = enc1_reset_hdmi_stream_attribute, + + .get_fifo_cal_average_level = enc2_get_fifo_cal_average_level, +}; + +void dcn30_dio_stream_encoder_construct( + struct dcn10_stream_encoder *enc1, + struct dc_context *ctx, + struct dc_bios *bp, + enum engine_id eng_id, + struct vpg *vpg, + struct afmt *afmt, + const struct dcn10_stream_enc_registers *regs, + const struct dcn10_stream_encoder_shift *se_shift, + const struct dcn10_stream_encoder_mask *se_mask) +{ + enc1->base.funcs = &dcn30_str_enc_funcs; + enc1->base.ctx = ctx; + enc1->base.id = eng_id; + enc1->base.bp = bp; + enc1->base.vpg = vpg; + enc1->base.afmt = afmt; + enc1->regs = regs; + enc1->se_shift = se_shift; + enc1->se_mask = se_mask; + enc1->base.stream_enc_inst = vpg->inst; +} + diff --git a/drivers/gpu/drm/amd/display/dc/dio/dcn30/dcn30_dio_stream_encoder.h b/drivers/gpu/drm/amd/display/dc/dio/dcn30/dcn30_dio_stream_encoder.h new file mode 100644 index 000000000000..06310973ded2 --- /dev/null +++ b/drivers/gpu/drm/amd/display/dc/dio/dcn30/dcn30_dio_stream_encoder.h @@ -0,0 +1,327 @@ +/* + * Copyright 2020 Advanced Micro Devices, Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + * + * Authors: AMD + * + */ + +#ifndef __DC_DIO_STREAM_ENCODER_DCN30_H__ +#define __DC_DIO_STREAM_ENCODER_DCN30_H__ + +#include "dcn30/dcn30_vpg.h" +#include "dcn30/dcn30_afmt.h" +#include "stream_encoder.h" +#include "dcn20/dcn20_stream_encoder.h" + +/* Register bit field name change */ +#define RDPCSTX0_RDPCSTX_CLOCK_CNTL__RDPCS_SYMCLK_DIV2_GATE_DIS__SHIFT 0x8 +#define RDPCSTX0_RDPCSTX_CLOCK_CNTL__RDPCS_SYMCLK_DIV2_EN__SHIFT 0x9 +#define RDPCSTX0_RDPCSTX_CLOCK_CNTL__RDPCS_SYMCLK_DIV2_CLOCK_ON__SHIFT 0xa +#define DPCSTX0_DPCSTX_TX_CNTL__DPCS_TX_DATA_SWAP__SHIFT 0xe +#define DPCSTX0_DPCSTX_TX_CNTL__DPCS_TX_DATA_ORDER_INVERT__SHIFT 0xf + +#define RDPCSTX0_RDPCSTX_CLOCK_CNTL__RDPCS_SYMCLK_DIV2_GATE_DIS_MASK 0x00000100L +#define RDPCSTX0_RDPCSTX_CLOCK_CNTL__RDPCS_SYMCLK_DIV2_EN_MASK 0x00000200L +#define RDPCSTX0_RDPCSTX_CLOCK_CNTL__RDPCS_SYMCLK_DIV2_CLOCK_ON_MASK 0x00000400L +#define DPCSTX0_DPCSTX_TX_CNTL__DPCS_TX_DATA_SWAP_MASK 0x00004000L +#define DPCSTX0_DPCSTX_TX_CNTL__DPCS_TX_DATA_ORDER_INVERT_MASK 0x00008000L + + +#define SE_DCN3_REG_LIST(id)\ + SRI(AFMT_CNTL, DIG, id), \ + SRI(DIG_FE_CNTL, DIG, id), \ + SRI(HDMI_CONTROL, DIG, id), \ + SRI(HDMI_DB_CONTROL, DIG, id), \ + SRI(HDMI_GC, DIG, id), \ + SRI(HDMI_GENERIC_PACKET_CONTROL0, DIG, id), \ + SRI(HDMI_GENERIC_PACKET_CONTROL1, DIG, id), \ + SRI(HDMI_GENERIC_PACKET_CONTROL2, DIG, id), \ + SRI(HDMI_GENERIC_PACKET_CONTROL3, DIG, id), \ + SRI(HDMI_GENERIC_PACKET_CONTROL4, DIG, id), \ + SRI(HDMI_GENERIC_PACKET_CONTROL5, DIG, id), \ + SRI(HDMI_GENERIC_PACKET_CONTROL6, DIG, id), \ + SRI(HDMI_GENERIC_PACKET_CONTROL7, DIG, id), \ + SRI(HDMI_GENERIC_PACKET_CONTROL8, DIG, id), \ + SRI(HDMI_GENERIC_PACKET_CONTROL9, DIG, id), \ + SRI(HDMI_GENERIC_PACKET_CONTROL10, DIG, id), \ + SRI(HDMI_INFOFRAME_CONTROL0, DIG, id), \ + SRI(HDMI_INFOFRAME_CONTROL1, DIG, id), \ + SRI(HDMI_VBI_PACKET_CONTROL, DIG, id), \ + SRI(HDMI_AUDIO_PACKET_CONTROL, DIG, id),\ + SRI(HDMI_ACR_PACKET_CONTROL, DIG, id),\ + SRI(HDMI_ACR_32_0, DIG, id),\ + SRI(HDMI_ACR_32_1, DIG, id),\ + SRI(HDMI_ACR_44_0, DIG, id),\ + SRI(HDMI_ACR_44_1, DIG, id),\ + SRI(HDMI_ACR_48_0, DIG, id),\ + SRI(HDMI_ACR_48_1, DIG, id),\ + SRI(DP_DB_CNTL, DP, id), \ + SRI(DP_MSA_MISC, DP, id), \ + SRI(DP_MSA_VBID_MISC, DP, id), \ + SRI(DP_MSA_COLORIMETRY, DP, id), \ + SRI(DP_MSA_TIMING_PARAM1, DP, id), \ + SRI(DP_MSA_TIMING_PARAM2, DP, id), \ + SRI(DP_MSA_TIMING_PARAM3, DP, id), \ + SRI(DP_MSA_TIMING_PARAM4, DP, id), \ + SRI(DP_MSE_RATE_CNTL, DP, id), \ + SRI(DP_MSE_RATE_UPDATE, DP, id), \ + SRI(DP_PIXEL_FORMAT, DP, id), \ + SRI(DP_SEC_CNTL, DP, id), \ + SRI(DP_SEC_CNTL1, DP, id), \ + SRI(DP_SEC_CNTL2, DP, id), \ + SRI(DP_SEC_CNTL5, DP, id), \ + SRI(DP_SEC_CNTL6, DP, id), \ + SRI(DP_STEER_FIFO, DP, id), \ + SRI(DP_VID_M, DP, id), \ + SRI(DP_VID_N, DP, id), \ + SRI(DP_VID_STREAM_CNTL, DP, id), \ + SRI(DP_VID_TIMING, DP, id), \ + SRI(DP_SEC_AUD_N, DP, id), \ + SRI(DP_SEC_AUD_N_READBACK, DP, id), \ + SRI(DP_SEC_AUD_M_READBACK, DP, id), \ + SRI(DP_SEC_TIMESTAMP, DP, id), \ + SRI(DP_DSC_CNTL, DP, id), \ + SRI(DP_DSC_BYTES_PER_PIXEL, DP, id), \ + SRI(DP_SEC_METADATA_TRANSMISSION, DP, id), \ + SRI(HDMI_METADATA_PACKET_CONTROL, DIG, id), \ + SRI(DP_SEC_FRAMING4, DP, id), \ + SRI(DP_GSP11_CNTL, DP, id), \ + SRI(DME_CONTROL, DME, id),\ + SRI(DP_SEC_METADATA_TRANSMISSION, DP, id), \ + SRI(HDMI_METADATA_PACKET_CONTROL, DIG, id), \ + SRI(DIG_FE_CNTL, DIG, id), \ + SRI(DIG_FIFO_STATUS, DIG, id), \ + SRI(DIG_CLOCK_PATTERN, DIG, id) + + +#define SE_COMMON_MASK_SH_LIST_DCN30(mask_sh)\ + SE_SF(DP0_DP_PIXEL_FORMAT, DP_PIXEL_ENCODING, mask_sh),\ + SE_SF(DP0_DP_PIXEL_FORMAT, DP_COMPONENT_DEPTH, mask_sh),\ + SE_SF(DIG0_HDMI_CONTROL, HDMI_PACKET_GEN_VERSION, mask_sh),\ + SE_SF(DIG0_HDMI_CONTROL, HDMI_KEEPOUT_MODE, mask_sh),\ + SE_SF(DIG0_HDMI_CONTROL, HDMI_DEEP_COLOR_ENABLE, mask_sh),\ + SE_SF(DIG0_HDMI_CONTROL, HDMI_DEEP_COLOR_DEPTH, mask_sh),\ + SE_SF(DIG0_HDMI_CONTROL, HDMI_DATA_SCRAMBLE_EN, mask_sh),\ + SE_SF(DIG0_HDMI_CONTROL, HDMI_NO_EXTRA_NULL_PACKET_FILLED, mask_sh),\ + SE_SF(DIG0_HDMI_VBI_PACKET_CONTROL, HDMI_GC_CONT, mask_sh),\ + SE_SF(DIG0_HDMI_VBI_PACKET_CONTROL, HDMI_GC_SEND, mask_sh),\ + SE_SF(DIG0_HDMI_VBI_PACKET_CONTROL, HDMI_NULL_SEND, mask_sh),\ + SE_SF(DIG0_HDMI_VBI_PACKET_CONTROL, HDMI_ACP_SEND, mask_sh),\ + SE_SF(DIG0_HDMI_INFOFRAME_CONTROL0, HDMI_AUDIO_INFO_SEND, mask_sh),\ + SE_SF(DIG0_HDMI_INFOFRAME_CONTROL1, HDMI_AUDIO_INFO_LINE, mask_sh),\ + SE_SF(DIG0_HDMI_GC, HDMI_GC_AVMUTE, mask_sh),\ + SE_SF(DP0_DP_MSE_RATE_CNTL, DP_MSE_RATE_X, mask_sh),\ + SE_SF(DP0_DP_MSE_RATE_CNTL, DP_MSE_RATE_Y, mask_sh),\ + SE_SF(DP0_DP_MSE_RATE_UPDATE, DP_MSE_RATE_UPDATE_PENDING, mask_sh),\ + SE_SF(DP0_DP_SEC_CNTL, DP_SEC_GSP0_ENABLE, mask_sh),\ + SE_SF(DP0_DP_SEC_CNTL, DP_SEC_STREAM_ENABLE, mask_sh),\ + SE_SF(DP0_DP_SEC_CNTL, DP_SEC_GSP1_ENABLE, mask_sh),\ + SE_SF(DP0_DP_SEC_CNTL, DP_SEC_GSP2_ENABLE, mask_sh),\ + SE_SF(DP0_DP_SEC_CNTL, DP_SEC_GSP3_ENABLE, mask_sh),\ + SE_SF(DP0_DP_SEC_CNTL, DP_SEC_MPG_ENABLE, mask_sh),\ + SE_SF(DP0_DP_SEC_CNTL2, DP_SEC_GSP4_SEND, mask_sh),\ + SE_SF(DP0_DP_SEC_CNTL2, DP_SEC_GSP4_SEND_PENDING, mask_sh),\ + SE_SF(DP0_DP_SEC_CNTL4, DP_SEC_GSP4_LINE_NUM, mask_sh),\ + SE_SF(DP0_DP_SEC_CNTL2, DP_SEC_GSP4_SEND_ANY_LINE, mask_sh),\ + SE_SF(DP0_DP_VID_STREAM_CNTL, DP_VID_STREAM_DIS_DEFER, mask_sh),\ + SE_SF(DP0_DP_VID_STREAM_CNTL, DP_VID_STREAM_ENABLE, mask_sh),\ + SE_SF(DP0_DP_VID_STREAM_CNTL, DP_VID_STREAM_STATUS, mask_sh),\ + SE_SF(DP0_DP_STEER_FIFO, DP_STEER_FIFO_RESET, mask_sh),\ + SE_SF(DP0_DP_VID_TIMING, DP_VID_M_N_GEN_EN, mask_sh),\ + SE_SF(DP0_DP_VID_N, DP_VID_N, mask_sh),\ + SE_SF(DP0_DP_VID_M, DP_VID_M, mask_sh),\ + SE_SF(DIG0_DIG_FE_CNTL, DIG_START, mask_sh),\ + SE_SF(DIG0_HDMI_AUDIO_PACKET_CONTROL, HDMI_AUDIO_DELAY_EN, mask_sh),\ + SE_SF(DIG0_HDMI_ACR_PACKET_CONTROL, HDMI_ACR_AUTO_SEND, mask_sh),\ + SE_SF(DIG0_HDMI_ACR_PACKET_CONTROL, HDMI_ACR_SOURCE, mask_sh),\ + SE_SF(DIG0_HDMI_ACR_PACKET_CONTROL, HDMI_ACR_AUDIO_PRIORITY, mask_sh),\ + SE_SF(DIG0_HDMI_ACR_32_0, HDMI_ACR_CTS_32, mask_sh),\ + SE_SF(DIG0_HDMI_ACR_32_1, HDMI_ACR_N_32, mask_sh),\ + SE_SF(DIG0_HDMI_ACR_44_0, HDMI_ACR_CTS_44, mask_sh),\ + SE_SF(DIG0_HDMI_ACR_44_1, HDMI_ACR_N_44, mask_sh),\ + SE_SF(DIG0_HDMI_ACR_48_0, HDMI_ACR_CTS_48, mask_sh),\ + SE_SF(DIG0_HDMI_ACR_48_1, HDMI_ACR_N_48, mask_sh),\ + SE_SF(DP0_DP_SEC_AUD_N, DP_SEC_AUD_N, mask_sh),\ + SE_SF(DP0_DP_SEC_AUD_N_READBACK, DP_SEC_AUD_N_READBACK, mask_sh),\ + SE_SF(DP0_DP_SEC_AUD_M_READBACK, DP_SEC_AUD_M_READBACK, mask_sh),\ + SE_SF(DP0_DP_SEC_TIMESTAMP, DP_SEC_TIMESTAMP_MODE, mask_sh),\ + SE_SF(DP0_DP_SEC_CNTL, DP_SEC_ASP_ENABLE, mask_sh),\ + SE_SF(DP0_DP_SEC_CNTL, DP_SEC_ATP_ENABLE, mask_sh),\ + SE_SF(DP0_DP_SEC_CNTL, DP_SEC_AIP_ENABLE, mask_sh),\ + SE_SF(DP0_DP_SEC_CNTL, DP_SEC_ACM_ENABLE, mask_sh),\ + SE_SF(DIG0_AFMT_CNTL, AFMT_AUDIO_CLOCK_EN, mask_sh),\ + SE_SF(DIG0_HDMI_CONTROL, HDMI_CLOCK_CHANNEL_RATE, mask_sh),\ + SE_SF(DIG0_DIG_FE_CNTL, TMDS_PIXEL_ENCODING, mask_sh),\ + SE_SF(DIG0_DIG_FE_CNTL, TMDS_COLOR_FORMAT, mask_sh),\ + SE_SF(DIG0_DIG_FE_CNTL, DIG_STEREOSYNC_SELECT, mask_sh),\ + SE_SF(DIG0_DIG_FE_CNTL, DIG_STEREOSYNC_GATE_EN, mask_sh),\ + SE_SF(DIG0_DIG_FIFO_STATUS, DIG_FIFO_LEVEL_ERROR, mask_sh),\ + SE_SF(DIG0_DIG_FIFO_STATUS, DIG_FIFO_USE_OVERWRITE_LEVEL, mask_sh),\ + SE_SF(DIG0_DIG_FIFO_STATUS, DIG_FIFO_OVERWRITE_LEVEL, mask_sh),\ + SE_SF(DIG0_DIG_FIFO_STATUS, DIG_FIFO_ERROR_ACK, mask_sh),\ + SE_SF(DIG0_DIG_FIFO_STATUS, DIG_FIFO_CAL_AVERAGE_LEVEL, mask_sh),\ + SE_SF(DIG0_DIG_FIFO_STATUS, DIG_FIFO_MAXIMUM_LEVEL, mask_sh),\ + SE_SF(DIG0_DIG_FIFO_STATUS, DIG_FIFO_MINIMUM_LEVEL, mask_sh),\ + SE_SF(DIG0_DIG_FIFO_STATUS, DIG_FIFO_READ_CLOCK_SRC, mask_sh),\ + SE_SF(DIG0_DIG_FIFO_STATUS, DIG_FIFO_CALIBRATED, mask_sh),\ + SE_SF(DIG0_DIG_FIFO_STATUS, DIG_FIFO_FORCE_RECAL_AVERAGE, mask_sh),\ + SE_SF(DIG0_DIG_FIFO_STATUS, DIG_FIFO_FORCE_RECOMP_MINMAX, mask_sh),\ + SE_SF(DP0_DP_SEC_CNTL, DP_SEC_GSP4_ENABLE, mask_sh),\ + SE_SF(DP0_DP_SEC_CNTL, DP_SEC_GSP5_ENABLE, mask_sh),\ + SE_SF(DP0_DP_SEC_CNTL, DP_SEC_GSP6_ENABLE, mask_sh),\ + SE_SF(DP0_DP_SEC_CNTL, DP_SEC_GSP7_ENABLE, mask_sh),\ + SE_SF(DP0_DP_SEC_CNTL1, DP_SEC_GSP5_LINE_REFERENCE, mask_sh),\ + SE_SF(DP0_DP_SEC_CNTL2, DP_SEC_GSP7_SEND, mask_sh),\ + SE_SF(DP0_DP_SEC_CNTL5, DP_SEC_GSP5_LINE_NUM, mask_sh),\ + SE_SF(DP0_DP_SEC_CNTL6, DP_SEC_GSP7_LINE_NUM, mask_sh),\ + SE_SF(DP0_DP_SEC_CNTL2, DP_SEC_GSP11_PPS, mask_sh),\ + SE_SF(DP0_DP_GSP11_CNTL, DP_SEC_GSP11_ENABLE, mask_sh),\ + SE_SF(DP0_DP_GSP11_CNTL, DP_SEC_GSP11_LINE_NUM, mask_sh),\ + SE_SF(DP0_DP_DB_CNTL, DP_DB_DISABLE, mask_sh),\ + SE_SF(DP0_DP_MSA_COLORIMETRY, DP_MSA_MISC0, mask_sh),\ + SE_SF(DP0_DP_MSA_TIMING_PARAM1, DP_MSA_HTOTAL, mask_sh),\ + SE_SF(DP0_DP_MSA_TIMING_PARAM1, DP_MSA_VTOTAL, mask_sh),\ + SE_SF(DP0_DP_MSA_TIMING_PARAM2, DP_MSA_HSTART, mask_sh),\ + SE_SF(DP0_DP_MSA_TIMING_PARAM2, DP_MSA_VSTART, mask_sh),\ + SE_SF(DP0_DP_MSA_TIMING_PARAM3, DP_MSA_HSYNCWIDTH, mask_sh),\ + SE_SF(DP0_DP_MSA_TIMING_PARAM3, DP_MSA_HSYNCPOLARITY, mask_sh),\ + SE_SF(DP0_DP_MSA_TIMING_PARAM3, DP_MSA_VSYNCWIDTH, mask_sh),\ + SE_SF(DP0_DP_MSA_TIMING_PARAM3, DP_MSA_VSYNCPOLARITY, mask_sh),\ + SE_SF(DP0_DP_MSA_TIMING_PARAM4, DP_MSA_HWIDTH, mask_sh),\ + SE_SF(DP0_DP_MSA_TIMING_PARAM4, DP_MSA_VHEIGHT, mask_sh),\ + SE_SF(DIG0_HDMI_DB_CONTROL, HDMI_DB_DISABLE, mask_sh),\ + SE_SF(DP0_DP_VID_TIMING, DP_VID_N_MUL, mask_sh),\ + SE_SF(DIG0_DIG_FE_CNTL, DIG_SOURCE_SELECT, mask_sh), \ + SE_SF(DIG0_HDMI_GENERIC_PACKET_CONTROL0, HDMI_GENERIC0_CONT, mask_sh),\ + SE_SF(DIG0_HDMI_GENERIC_PACKET_CONTROL0, HDMI_GENERIC0_SEND, mask_sh),\ + SE_SF(DIG0_HDMI_GENERIC_PACKET_CONTROL0, HDMI_GENERIC1_CONT, mask_sh),\ + SE_SF(DIG0_HDMI_GENERIC_PACKET_CONTROL0, HDMI_GENERIC1_SEND, mask_sh),\ + SE_SF(DIG0_HDMI_GENERIC_PACKET_CONTROL0, HDMI_GENERIC2_CONT, mask_sh),\ + SE_SF(DIG0_HDMI_GENERIC_PACKET_CONTROL0, HDMI_GENERIC2_SEND, mask_sh),\ + SE_SF(DIG0_HDMI_GENERIC_PACKET_CONTROL0, HDMI_GENERIC3_CONT, mask_sh),\ + SE_SF(DIG0_HDMI_GENERIC_PACKET_CONTROL0, HDMI_GENERIC3_SEND, mask_sh),\ + SE_SF(DIG0_HDMI_GENERIC_PACKET_CONTROL0, HDMI_GENERIC4_CONT, mask_sh),\ + SE_SF(DIG0_HDMI_GENERIC_PACKET_CONTROL0, HDMI_GENERIC4_SEND, mask_sh),\ + SE_SF(DIG0_HDMI_GENERIC_PACKET_CONTROL0, HDMI_GENERIC5_CONT, mask_sh),\ + SE_SF(DIG0_HDMI_GENERIC_PACKET_CONTROL0, HDMI_GENERIC5_SEND, mask_sh),\ + SE_SF(DIG0_HDMI_GENERIC_PACKET_CONTROL0, HDMI_GENERIC6_CONT, mask_sh),\ + SE_SF(DIG0_HDMI_GENERIC_PACKET_CONTROL0, HDMI_GENERIC6_SEND, mask_sh),\ + SE_SF(DIG0_HDMI_GENERIC_PACKET_CONTROL0, HDMI_GENERIC7_CONT, mask_sh),\ + SE_SF(DIG0_HDMI_GENERIC_PACKET_CONTROL0, HDMI_GENERIC7_SEND, mask_sh),\ + SE_SF(DIG0_HDMI_GENERIC_PACKET_CONTROL6, HDMI_GENERIC8_CONT, mask_sh),\ + SE_SF(DIG0_HDMI_GENERIC_PACKET_CONTROL6, HDMI_GENERIC8_SEND, mask_sh),\ + SE_SF(DIG0_HDMI_GENERIC_PACKET_CONTROL6, HDMI_GENERIC9_CONT, mask_sh),\ + SE_SF(DIG0_HDMI_GENERIC_PACKET_CONTROL6, HDMI_GENERIC9_SEND, mask_sh),\ + SE_SF(DIG0_HDMI_GENERIC_PACKET_CONTROL6, HDMI_GENERIC10_CONT, mask_sh),\ + SE_SF(DIG0_HDMI_GENERIC_PACKET_CONTROL6, HDMI_GENERIC10_SEND, mask_sh),\ + SE_SF(DIG0_HDMI_GENERIC_PACKET_CONTROL6, HDMI_GENERIC11_CONT, mask_sh),\ + SE_SF(DIG0_HDMI_GENERIC_PACKET_CONTROL6, HDMI_GENERIC11_SEND, mask_sh),\ + SE_SF(DIG0_HDMI_GENERIC_PACKET_CONTROL6, HDMI_GENERIC12_CONT, mask_sh),\ + SE_SF(DIG0_HDMI_GENERIC_PACKET_CONTROL6, HDMI_GENERIC12_SEND, mask_sh),\ + SE_SF(DIG0_HDMI_GENERIC_PACKET_CONTROL6, HDMI_GENERIC13_CONT, mask_sh),\ + SE_SF(DIG0_HDMI_GENERIC_PACKET_CONTROL6, HDMI_GENERIC13_SEND, mask_sh),\ + SE_SF(DIG0_HDMI_GENERIC_PACKET_CONTROL6, HDMI_GENERIC14_CONT, mask_sh),\ + SE_SF(DIG0_HDMI_GENERIC_PACKET_CONTROL6, HDMI_GENERIC14_SEND, mask_sh),\ + SE_SF(DIG0_HDMI_GENERIC_PACKET_CONTROL1, HDMI_GENERIC0_LINE, mask_sh),\ + SE_SF(DIG0_HDMI_GENERIC_PACKET_CONTROL1, HDMI_GENERIC1_LINE, mask_sh),\ + SE_SF(DIG0_HDMI_GENERIC_PACKET_CONTROL2, HDMI_GENERIC2_LINE, mask_sh),\ + SE_SF(DIG0_HDMI_GENERIC_PACKET_CONTROL2, HDMI_GENERIC3_LINE, mask_sh),\ + SE_SF(DIG0_HDMI_GENERIC_PACKET_CONTROL3, HDMI_GENERIC4_LINE, mask_sh),\ + SE_SF(DIG0_HDMI_GENERIC_PACKET_CONTROL3, HDMI_GENERIC5_LINE, mask_sh),\ + SE_SF(DIG0_HDMI_GENERIC_PACKET_CONTROL4, HDMI_GENERIC6_LINE, mask_sh),\ + SE_SF(DIG0_HDMI_GENERIC_PACKET_CONTROL4, HDMI_GENERIC7_LINE, mask_sh),\ + SE_SF(DIG0_HDMI_GENERIC_PACKET_CONTROL7, HDMI_GENERIC8_LINE, mask_sh),\ + SE_SF(DIG0_HDMI_GENERIC_PACKET_CONTROL7, HDMI_GENERIC9_LINE, mask_sh),\ + SE_SF(DIG0_HDMI_GENERIC_PACKET_CONTROL8, HDMI_GENERIC10_LINE, mask_sh),\ + SE_SF(DIG0_HDMI_GENERIC_PACKET_CONTROL8, HDMI_GENERIC11_LINE, mask_sh),\ + SE_SF(DIG0_HDMI_GENERIC_PACKET_CONTROL9, HDMI_GENERIC12_LINE, mask_sh),\ + SE_SF(DIG0_HDMI_GENERIC_PACKET_CONTROL9, HDMI_GENERIC13_LINE, mask_sh),\ + SE_SF(DIG0_HDMI_GENERIC_PACKET_CONTROL10, HDMI_GENERIC14_LINE, mask_sh),\ + SE_SF(DP0_DP_DSC_CNTL, DP_DSC_MODE, mask_sh),\ + SE_SF(DP0_DP_DSC_CNTL, DP_DSC_SLICE_WIDTH, mask_sh),\ + SE_SF(DP0_DP_DSC_BYTES_PER_PIXEL, DP_DSC_BYTES_PER_PIXEL, mask_sh),\ + SE_SF(DP0_DP_MSA_VBID_MISC, DP_VBID6_LINE_REFERENCE, mask_sh),\ + SE_SF(DP0_DP_MSA_VBID_MISC, DP_VBID6_LINE_NUM, mask_sh),\ + SE_SF(DME0_DME_CONTROL, METADATA_ENGINE_EN, mask_sh),\ + SE_SF(DME0_DME_CONTROL, METADATA_HUBP_REQUESTOR_ID, mask_sh),\ + SE_SF(DME0_DME_CONTROL, METADATA_STREAM_TYPE, mask_sh),\ + SE_SF(DP0_DP_SEC_METADATA_TRANSMISSION, DP_SEC_METADATA_PACKET_ENABLE, mask_sh),\ + SE_SF(DP0_DP_SEC_METADATA_TRANSMISSION, DP_SEC_METADATA_PACKET_LINE_REFERENCE, mask_sh),\ + SE_SF(DP0_DP_SEC_METADATA_TRANSMISSION, DP_SEC_METADATA_PACKET_LINE, mask_sh),\ + SE_SF(DIG0_HDMI_METADATA_PACKET_CONTROL, HDMI_METADATA_PACKET_ENABLE, mask_sh),\ + SE_SF(DIG0_HDMI_METADATA_PACKET_CONTROL, HDMI_METADATA_PACKET_LINE_REFERENCE, mask_sh),\ + SE_SF(DIG0_HDMI_METADATA_PACKET_CONTROL, HDMI_METADATA_PACKET_LINE, mask_sh),\ + SE_SF(DIG0_DIG_FE_CNTL, DOLBY_VISION_EN, mask_sh),\ + SE_SF(DP0_DP_PIXEL_FORMAT, DP_PIXEL_COMBINE, mask_sh),\ + SE_SF(DP0_DP_SEC_FRAMING4, DP_SST_SDP_SPLITTING, mask_sh),\ + SE_SF(DIG0_DIG_CLOCK_PATTERN, DIG_CLOCK_PATTERN, mask_sh) + +void dcn30_dio_stream_encoder_construct( + struct dcn10_stream_encoder *enc1, + struct dc_context *ctx, + struct dc_bios *bp, + enum engine_id eng_id, + struct vpg *vpg, + struct afmt *afmt, + const struct dcn10_stream_enc_registers *regs, + const struct dcn10_stream_encoder_shift *se_shift, + const struct dcn10_stream_encoder_mask *se_mask); + +void enc3_stream_encoder_update_hdmi_info_packets( + struct stream_encoder *enc, + const struct encoder_info_frame *info_frame); + +void enc3_stream_encoder_stop_hdmi_info_packets( + struct stream_encoder *enc); + +void enc3_stream_encoder_update_dp_info_packets_sdp_line_num( + struct stream_encoder *enc, + struct encoder_info_frame *info_frame); + +void enc3_stream_encoder_update_dp_info_packets( + struct stream_encoder *enc, + const struct encoder_info_frame *info_frame); + +void enc3_audio_mute_control( + struct stream_encoder *enc, + bool mute); + +void enc3_se_dp_audio_setup( + struct stream_encoder *enc, + unsigned int az_inst, + struct audio_info *info); + +void enc3_se_dp_audio_enable( + struct stream_encoder *enc); + +void enc3_se_hdmi_audio_setup( + struct stream_encoder *enc, + unsigned int az_inst, + struct audio_info *info, + struct audio_crtc_info *audio_crtc_info); + +void enc3_dp_set_dsc_pps_info_packet( + struct stream_encoder *enc, + bool enable, + uint8_t *dsc_packed_pps, + bool immediate_update); + +#endif /* __DC_DIO_STREAM_ENCODER_DCN30_H__ */ diff --git a/drivers/gpu/drm/amd/display/dc/dio/dcn31/dcn31_dio_link_encoder.c b/drivers/gpu/drm/amd/display/dc/dio/dcn31/dcn31_dio_link_encoder.c new file mode 100644 index 000000000000..b2cea59ba5d4 --- /dev/null +++ b/drivers/gpu/drm/amd/display/dc/dio/dcn31/dcn31_dio_link_encoder.c @@ -0,0 +1,681 @@ +/* + * Copyright 2012-15 Advanced Micro Devices, Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + * + * Authors: AMD + * + */ + + +#include "reg_helper.h" + +#include "core_types.h" +#include "link_encoder.h" +#include "dcn31_dio_link_encoder.h" +#include "stream_encoder.h" +#include "dc_bios_types.h" + +#include "gpio_service_interface.h" + +#include "link_enc_cfg.h" +#include "dc_dmub_srv.h" +#include "dal_asic_id.h" +#include "link.h" + +#define CTX \ + enc10->base.ctx +#define DC_LOGGER \ + enc10->base.ctx->logger + +#define REG(reg)\ + (enc10->link_regs->reg) + +#undef FN +#define FN(reg_name, field_name) \ + enc10->link_shift->field_name, enc10->link_mask->field_name + +#define IND_REG(index) \ + (enc10->link_regs->index) + +#define AUX_REG(reg)\ + (enc10->aux_regs->reg) + +#define AUX_REG_READ(reg_name) \ + dm_read_reg(CTX, AUX_REG(reg_name)) + +#define AUX_REG_WRITE(reg_name, val) \ + dm_write_reg(CTX, AUX_REG(reg_name), val) + +#ifndef MIN +#define MIN(X, Y) ((X) < (Y) ? (X) : (Y)) +#endif + +static uint8_t phy_id_from_transmitter(enum transmitter t) +{ + uint8_t phy_id; + + switch (t) { + case TRANSMITTER_UNIPHY_A: + phy_id = 0; + break; + case TRANSMITTER_UNIPHY_B: + phy_id = 1; + break; + case TRANSMITTER_UNIPHY_C: + phy_id = 2; + break; + case TRANSMITTER_UNIPHY_D: + phy_id = 3; + break; + case TRANSMITTER_UNIPHY_E: + phy_id = 4; + break; + case TRANSMITTER_UNIPHY_F: + phy_id = 5; + break; + case TRANSMITTER_UNIPHY_G: + phy_id = 6; + break; + default: + phy_id = 0; + break; + } + return phy_id; +} + +static bool has_query_dp_alt(struct link_encoder *enc) +{ + struct dc_dmub_srv *dc_dmub_srv = enc->ctx->dmub_srv; + + if (enc->ctx->dce_version >= DCN_VERSION_3_15) + return true; + + /* Supports development firmware and firmware >= 4.0.11 */ + return dc_dmub_srv && + !(dc_dmub_srv->dmub->fw_version >= DMUB_FW_VERSION(4, 0, 0) && + dc_dmub_srv->dmub->fw_version <= DMUB_FW_VERSION(4, 0, 10)); +} + +static bool query_dp_alt_from_dmub(struct link_encoder *enc, + union dmub_rb_cmd *cmd) +{ + struct dcn10_link_encoder *enc10 = TO_DCN10_LINK_ENC(enc); + + memset(cmd, 0, sizeof(*cmd)); + cmd->query_dp_alt.header.type = DMUB_CMD__VBIOS; + cmd->query_dp_alt.header.sub_type = + DMUB_CMD__VBIOS_TRANSMITTER_QUERY_DP_ALT; + cmd->query_dp_alt.header.payload_bytes = sizeof(cmd->query_dp_alt.data); + cmd->query_dp_alt.data.phy_id = phy_id_from_transmitter(enc10->base.transmitter); + + if (!dc_wake_and_execute_dmub_cmd(enc->ctx, cmd, DM_DMUB_WAIT_TYPE_WAIT_WITH_REPLY)) + return false; + + return true; +} + +void dcn31_link_encoder_set_dio_phy_mux( + struct link_encoder *enc, + enum encoder_type_select sel, + uint32_t hpo_inst) +{ + struct dcn10_link_encoder *enc10 = TO_DCN10_LINK_ENC(enc); + + switch (enc->transmitter) { + case TRANSMITTER_UNIPHY_A: + if (sel == ENCODER_TYPE_HDMI_FRL) + REG_UPDATE(DIO_LINKA_CNTL, + HPO_HDMI_ENC_SEL, hpo_inst); + else if (sel == ENCODER_TYPE_DP_128B132B) + REG_UPDATE(DIO_LINKA_CNTL, + HPO_DP_ENC_SEL, hpo_inst); + REG_UPDATE(DIO_LINKA_CNTL, + ENC_TYPE_SEL, sel); + break; + case TRANSMITTER_UNIPHY_B: + if (sel == ENCODER_TYPE_HDMI_FRL) + REG_UPDATE(DIO_LINKB_CNTL, + HPO_HDMI_ENC_SEL, hpo_inst); + else if (sel == ENCODER_TYPE_DP_128B132B) + REG_UPDATE(DIO_LINKB_CNTL, + HPO_DP_ENC_SEL, hpo_inst); + REG_UPDATE(DIO_LINKB_CNTL, + ENC_TYPE_SEL, sel); + break; + case TRANSMITTER_UNIPHY_C: + if (sel == ENCODER_TYPE_HDMI_FRL) + REG_UPDATE(DIO_LINKC_CNTL, + HPO_HDMI_ENC_SEL, hpo_inst); + else if (sel == ENCODER_TYPE_DP_128B132B) + REG_UPDATE(DIO_LINKC_CNTL, + HPO_DP_ENC_SEL, hpo_inst); + REG_UPDATE(DIO_LINKC_CNTL, + ENC_TYPE_SEL, sel); + break; + case TRANSMITTER_UNIPHY_D: + if (sel == ENCODER_TYPE_HDMI_FRL) + REG_UPDATE(DIO_LINKD_CNTL, + HPO_HDMI_ENC_SEL, hpo_inst); + else if (sel == ENCODER_TYPE_DP_128B132B) + REG_UPDATE(DIO_LINKD_CNTL, + HPO_DP_ENC_SEL, hpo_inst); + REG_UPDATE(DIO_LINKD_CNTL, + ENC_TYPE_SEL, sel); + break; + case TRANSMITTER_UNIPHY_E: + if (sel == ENCODER_TYPE_HDMI_FRL) + REG_UPDATE(DIO_LINKE_CNTL, + HPO_HDMI_ENC_SEL, hpo_inst); + else if (sel == ENCODER_TYPE_DP_128B132B) + REG_UPDATE(DIO_LINKE_CNTL, + HPO_DP_ENC_SEL, hpo_inst); + REG_UPDATE(DIO_LINKE_CNTL, + ENC_TYPE_SEL, sel); + break; + case TRANSMITTER_UNIPHY_F: + if (sel == ENCODER_TYPE_HDMI_FRL) + REG_UPDATE(DIO_LINKF_CNTL, + HPO_HDMI_ENC_SEL, hpo_inst); + else if (sel == ENCODER_TYPE_DP_128B132B) + REG_UPDATE(DIO_LINKF_CNTL, + HPO_DP_ENC_SEL, hpo_inst); + REG_UPDATE(DIO_LINKF_CNTL, + ENC_TYPE_SEL, sel); + break; + default: + /* Do nothing */ + break; + } +} + +void enc31_hw_init(struct link_encoder *enc) +{ + struct dcn10_link_encoder *enc10 = TO_DCN10_LINK_ENC(enc); + +/* + 00 - DP_AUX_DPHY_RX_DETECTION_THRESHOLD__1to2 : 1/2 + 01 - DP_AUX_DPHY_RX_DETECTION_THRESHOLD__3to4 : 3/4 + 02 - DP_AUX_DPHY_RX_DETECTION_THRESHOLD__7to8 : 7/8 + 03 - DP_AUX_DPHY_RX_DETECTION_THRESHOLD__15to16 : 15/16 + 04 - DP_AUX_DPHY_RX_DETECTION_THRESHOLD__31to32 : 31/32 + 05 - DP_AUX_DPHY_RX_DETECTION_THRESHOLD__63to64 : 63/64 + 06 - DP_AUX_DPHY_RX_DETECTION_THRESHOLD__127to128 : 127/128 + 07 - DP_AUX_DPHY_RX_DETECTION_THRESHOLD__255to256 : 255/256 +*/ + +/* + AUX_REG_UPDATE_5(AUX_DPHY_RX_CONTROL0, + AUX_RX_START_WINDOW = 1 [6:4] + AUX_RX_RECEIVE_WINDOW = 1 default is 2 [10:8] + AUX_RX_HALF_SYM_DETECT_LEN = 1 [13:12] default is 1 + AUX_RX_TRANSITION_FILTER_EN = 1 [16] default is 1 + AUX_RX_ALLOW_BELOW_THRESHOLD_PHASE_DETECT [17] is 0 default is 0 + AUX_RX_ALLOW_BELOW_THRESHOLD_START [18] is 1 default is 1 + AUX_RX_ALLOW_BELOW_THRESHOLD_STOP [19] is 1 default is 1 + AUX_RX_PHASE_DETECT_LEN, [21,20] = 0x3 default is 3 + AUX_RX_DETECTION_THRESHOLD [30:28] = 1 +*/ + // dmub will read AUX_DPHY_RX_CONTROL0/AUX_DPHY_TX_CONTROL from vbios table in dp_aux_init + + //AUX_DPHY_TX_REF_CONTROL'AUX_TX_REF_DIV HW default is 0x32; + // Set AUX_TX_REF_DIV Divider to generate 2 MHz reference from refclk + // 27MHz -> 0xd + // 100MHz -> 0x32 + // 48MHz -> 0x18 + + // Set TMDS_CTL0 to 1. This is a legacy setting. + REG_UPDATE(TMDS_CTL_BITS, TMDS_CTL0, 1); + + dcn10_aux_initialize(enc10); +} + +static const struct link_encoder_funcs dcn31_link_enc_funcs = { + .read_state = link_enc2_read_state, + .validate_output_with_stream = + dcn30_link_encoder_validate_output_with_stream, + .hw_init = enc31_hw_init, + .setup = dcn10_link_encoder_setup, + .enable_tmds_output = dcn10_link_encoder_enable_tmds_output, + .enable_dp_output = dcn31_link_encoder_enable_dp_output, + .enable_dp_mst_output = dcn31_link_encoder_enable_dp_mst_output, + .disable_output = dcn31_link_encoder_disable_output, + .dp_set_lane_settings = dcn10_link_encoder_dp_set_lane_settings, + .dp_set_phy_pattern = dcn10_link_encoder_dp_set_phy_pattern, + .update_mst_stream_allocation_table = + dcn10_link_encoder_update_mst_stream_allocation_table, + .psr_program_dp_dphy_fast_training = + dcn10_psr_program_dp_dphy_fast_training, + .psr_program_secondary_packet = dcn10_psr_program_secondary_packet, + .connect_dig_be_to_fe = dcn10_link_encoder_connect_dig_be_to_fe, + .enable_hpd = dcn10_link_encoder_enable_hpd, + .disable_hpd = dcn10_link_encoder_disable_hpd, + .is_dig_enabled = dcn10_is_dig_enabled, + .destroy = dcn10_link_encoder_destroy, + .fec_set_enable = enc2_fec_set_enable, + .fec_set_ready = enc2_fec_set_ready, + .fec_is_active = enc2_fec_is_active, + .get_dig_frontend = dcn10_get_dig_frontend, + .get_dig_mode = dcn10_get_dig_mode, + .is_in_alt_mode = dcn31_link_encoder_is_in_alt_mode, + .get_max_link_cap = dcn31_link_encoder_get_max_link_cap, + .set_dio_phy_mux = dcn31_link_encoder_set_dio_phy_mux, +}; + +void dcn31_link_encoder_construct( + struct dcn20_link_encoder *enc20, + const struct encoder_init_data *init_data, + const struct encoder_feature_support *enc_features, + const struct dcn10_link_enc_registers *link_regs, + const struct dcn10_link_enc_aux_registers *aux_regs, + const struct dcn10_link_enc_hpd_registers *hpd_regs, + const struct dcn10_link_enc_shift *link_shift, + const struct dcn10_link_enc_mask *link_mask) +{ + struct bp_encoder_cap_info bp_cap_info = {0}; + const struct dc_vbios_funcs *bp_funcs = init_data->ctx->dc_bios->funcs; + enum bp_result result = BP_RESULT_OK; + struct dcn10_link_encoder *enc10 = &enc20->enc10; + + enc10->base.funcs = &dcn31_link_enc_funcs; + enc10->base.ctx = init_data->ctx; + enc10->base.id = init_data->encoder; + + enc10->base.hpd_source = init_data->hpd_source; + enc10->base.connector = init_data->connector; + + enc10->base.preferred_engine = ENGINE_ID_UNKNOWN; + + enc10->base.features = *enc_features; + + enc10->base.transmitter = init_data->transmitter; + + /* set the flag to indicate whether driver poll the I2C data pin + * while doing the DP sink detect + */ + +/* if (dal_adapter_service_is_feature_supported(as, + FEATURE_DP_SINK_DETECT_POLL_DATA_PIN)) + enc10->base.features.flags.bits. + DP_SINK_DETECT_POLL_DATA_PIN = true;*/ + + enc10->base.output_signals = + SIGNAL_TYPE_DVI_SINGLE_LINK | + SIGNAL_TYPE_DVI_DUAL_LINK | + SIGNAL_TYPE_LVDS | + SIGNAL_TYPE_DISPLAY_PORT | + SIGNAL_TYPE_DISPLAY_PORT_MST | + SIGNAL_TYPE_EDP | + SIGNAL_TYPE_HDMI_TYPE_A; + + /* For DCE 8.0 and 8.1, by design, UNIPHY is hardwired to DIG_BE. + * SW always assign DIG_FE 1:1 mapped to DIG_FE for non-MST UNIPHY. + * SW assign DIG_FE to non-MST UNIPHY first and MST last. So prefer + * DIG is per UNIPHY and used by SST DP, eDP, HDMI, DVI and LVDS. + * Prefer DIG assignment is decided by board design. + * For DCE 8.0, there are only max 6 UNIPHYs, we assume board design + * and VBIOS will filter out 7 UNIPHY for DCE 8.0. + * By this, adding DIGG should not hurt DCE 8.0. + * This will let DCE 8.1 share DCE 8.0 as much as possible + */ + + enc10->link_regs = link_regs; + enc10->aux_regs = aux_regs; + enc10->hpd_regs = hpd_regs; + enc10->link_shift = link_shift; + enc10->link_mask = link_mask; + + switch (enc10->base.transmitter) { + case TRANSMITTER_UNIPHY_A: + enc10->base.preferred_engine = ENGINE_ID_DIGA; + break; + case TRANSMITTER_UNIPHY_B: + enc10->base.preferred_engine = ENGINE_ID_DIGB; + break; + case TRANSMITTER_UNIPHY_C: + enc10->base.preferred_engine = ENGINE_ID_DIGC; + break; + case TRANSMITTER_UNIPHY_D: + enc10->base.preferred_engine = ENGINE_ID_DIGD; + break; + case TRANSMITTER_UNIPHY_E: + enc10->base.preferred_engine = ENGINE_ID_DIGE; + break; + case TRANSMITTER_UNIPHY_F: + enc10->base.preferred_engine = ENGINE_ID_DIGF; + break; + default: + ASSERT_CRITICAL(false); + enc10->base.preferred_engine = ENGINE_ID_UNKNOWN; + } + + /* default to one to mirror Windows behavior */ + enc10->base.features.flags.bits.HDMI_6GB_EN = 1; + + result = bp_funcs->get_encoder_cap_info(enc10->base.ctx->dc_bios, + enc10->base.id, &bp_cap_info); + + /* Override features with DCE-specific values */ + if (result == BP_RESULT_OK) { + enc10->base.features.flags.bits.IS_HBR2_CAPABLE = + bp_cap_info.DP_HBR2_EN; + enc10->base.features.flags.bits.IS_HBR3_CAPABLE = + bp_cap_info.DP_HBR3_EN; + enc10->base.features.flags.bits.HDMI_6GB_EN = bp_cap_info.HDMI_6GB_EN; + enc10->base.features.flags.bits.IS_DP2_CAPABLE = bp_cap_info.IS_DP2_CAPABLE; + enc10->base.features.flags.bits.IS_UHBR10_CAPABLE = bp_cap_info.DP_UHBR10_EN; + enc10->base.features.flags.bits.IS_UHBR13_5_CAPABLE = bp_cap_info.DP_UHBR13_5_EN; + enc10->base.features.flags.bits.IS_UHBR20_CAPABLE = bp_cap_info.DP_UHBR20_EN; + enc10->base.features.flags.bits.DP_IS_USB_C = + bp_cap_info.DP_IS_USB_C; + } else { + DC_LOG_WARNING("%s: Failed to get encoder_cap_info from VBIOS with error code %d!\n", + __func__, + result); + } + if (enc10->base.ctx->dc->debug.hdmi20_disable) { + enc10->base.features.flags.bits.HDMI_6GB_EN = 0; + } +} + +void dcn31_link_encoder_construct_minimal( + struct dcn20_link_encoder *enc20, + struct dc_context *ctx, + const struct encoder_feature_support *enc_features, + const struct dcn10_link_enc_registers *link_regs, + enum engine_id eng_id) +{ + struct dcn10_link_encoder *enc10 = &enc20->enc10; + + enc10->base.funcs = &dcn31_link_enc_funcs; + enc10->base.ctx = ctx; + enc10->base.id.type = OBJECT_TYPE_ENCODER; + enc10->base.hpd_source = HPD_SOURCEID_UNKNOWN; + enc10->base.connector.type = OBJECT_TYPE_CONNECTOR; + enc10->base.preferred_engine = eng_id; + enc10->base.features = *enc_features; + enc10->base.transmitter = TRANSMITTER_UNKNOWN; + enc10->link_regs = link_regs; + + enc10->base.output_signals = + SIGNAL_TYPE_DISPLAY_PORT | + SIGNAL_TYPE_DISPLAY_PORT_MST | + SIGNAL_TYPE_EDP; +} + +/* DPIA equivalent of link_transmitter_control. */ +static bool link_dpia_control(struct dc_context *dc_ctx, + struct dmub_cmd_dig_dpia_control_data *dpia_control) +{ + union dmub_rb_cmd cmd; + + memset(&cmd, 0, sizeof(cmd)); + + cmd.dig1_dpia_control.header.type = DMUB_CMD__DPIA; + cmd.dig1_dpia_control.header.sub_type = + DMUB_CMD__DPIA_DIG1_DPIA_CONTROL; + cmd.dig1_dpia_control.header.payload_bytes = + sizeof(cmd.dig1_dpia_control) - + sizeof(cmd.dig1_dpia_control.header); + + cmd.dig1_dpia_control.dpia_control = *dpia_control; + + dc_wake_and_execute_dmub_cmd(dc_ctx, &cmd, DM_DMUB_WAIT_TYPE_WAIT); + + return true; +} + +static void link_encoder_disable(struct dcn10_link_encoder *enc10) +{ + /* reset training complete */ + REG_UPDATE(DP_LINK_CNTL, DP_LINK_TRAINING_COMPLETE, 0); +} + +void dcn31_link_encoder_enable_dp_output( + struct link_encoder *enc, + const struct dc_link_settings *link_settings, + enum clock_source_id clock_source) +{ + struct dcn10_link_encoder *enc10 = TO_DCN10_LINK_ENC(enc); + + /* Enable transmitter and encoder. */ + if (!link_enc_cfg_is_transmitter_mappable(enc->ctx->dc, enc)) { + + DC_LOG_DEBUG("%s: enc_id(%d)\n", __func__, enc->preferred_engine); + dcn20_link_encoder_enable_dp_output(enc, link_settings, clock_source); + + } else { + + struct dmub_cmd_dig_dpia_control_data dpia_control = { 0 }; + struct dc_link *link; + + link = link_enc_cfg_get_link_using_link_enc(enc->ctx->dc, enc->preferred_engine); + + enc1_configure_encoder(enc10, link_settings); + + dpia_control.action = (uint8_t)TRANSMITTER_CONTROL_ENABLE; + dpia_control.enc_id = enc->preferred_engine; + dpia_control.mode_laneset.digmode = 0; /* 0 for SST; 5 for MST */ + dpia_control.lanenum = (uint8_t)link_settings->lane_count; + dpia_control.symclk_10khz = link_settings->link_rate * + LINK_RATE_REF_FREQ_IN_KHZ / 10; + /* DIG_BE_CNTL.DIG_HPD_SELECT set to 5 (hpdsel - 1) to indicate HPD pin + * unused by DPIA. + */ + dpia_control.hpdsel = 6; + + if (link) { + dpia_control.dpia_id = link->ddc_hw_inst; + dpia_control.fec_rdy = link->dc->link_srv->dp_should_enable_fec(link); + } else { + DC_LOG_ERROR("%s: Failed to execute DPIA enable DMUB command.\n", __func__); + BREAK_TO_DEBUGGER(); + return; + } + + DC_LOG_DEBUG("%s: DPIA(%d) - enc_id(%d)\n", __func__, dpia_control.dpia_id, dpia_control.enc_id); + link_dpia_control(enc->ctx, &dpia_control); + } +} + +void dcn31_link_encoder_enable_dp_mst_output( + struct link_encoder *enc, + const struct dc_link_settings *link_settings, + enum clock_source_id clock_source) +{ + struct dcn10_link_encoder *enc10 = TO_DCN10_LINK_ENC(enc); + + /* Enable transmitter and encoder. */ + if (!link_enc_cfg_is_transmitter_mappable(enc->ctx->dc, enc)) { + + DC_LOG_DEBUG("%s: enc_id(%d)\n", __func__, enc->preferred_engine); + dcn10_link_encoder_enable_dp_mst_output(enc, link_settings, clock_source); + + } else { + + struct dmub_cmd_dig_dpia_control_data dpia_control = { 0 }; + struct dc_link *link; + + link = link_enc_cfg_get_link_using_link_enc(enc->ctx->dc, enc->preferred_engine); + + enc1_configure_encoder(enc10, link_settings); + + dpia_control.action = (uint8_t)TRANSMITTER_CONTROL_ENABLE; + dpia_control.enc_id = enc->preferred_engine; + dpia_control.mode_laneset.digmode = 5; /* 0 for SST; 5 for MST */ + dpia_control.lanenum = (uint8_t)link_settings->lane_count; + dpia_control.symclk_10khz = link_settings->link_rate * + LINK_RATE_REF_FREQ_IN_KHZ / 10; + /* DIG_BE_CNTL.DIG_HPD_SELECT set to 5 (hpdsel - 1) to indicate HPD pin + * unused by DPIA. + */ + dpia_control.hpdsel = 6; + + if (link) { + dpia_control.dpia_id = link->ddc_hw_inst; + dpia_control.fec_rdy = link->dc->link_srv->dp_should_enable_fec(link); + } else { + DC_LOG_ERROR("%s: Failed to execute DPIA enable DMUB command.\n", __func__); + BREAK_TO_DEBUGGER(); + return; + } + + DC_LOG_DEBUG("%s: DPIA(%d) - enc_id(%d)\n", __func__, dpia_control.dpia_id, dpia_control.enc_id); + link_dpia_control(enc->ctx, &dpia_control); + } +} + +void dcn31_link_encoder_disable_output( + struct link_encoder *enc, + enum signal_type signal) +{ + struct dcn10_link_encoder *enc10 = TO_DCN10_LINK_ENC(enc); + + /* Disable transmitter and encoder. */ + if (!link_enc_cfg_is_transmitter_mappable(enc->ctx->dc, enc)) { + + DC_LOG_DEBUG("%s: enc_id(%d)\n", __func__, enc->preferred_engine); + dcn10_link_encoder_disable_output(enc, signal); + + } else { + + struct dmub_cmd_dig_dpia_control_data dpia_control = { 0 }; + struct dc_link *link; + + if (enc->funcs->is_dig_enabled && !enc->funcs->is_dig_enabled(enc)) + return; + + link = link_enc_cfg_get_link_using_link_enc(enc->ctx->dc, enc->preferred_engine); + + dpia_control.action = (uint8_t)TRANSMITTER_CONTROL_DISABLE; + dpia_control.enc_id = enc->preferred_engine; + if (signal == SIGNAL_TYPE_DISPLAY_PORT) { + dpia_control.mode_laneset.digmode = 0; /* 0 for SST; 5 for MST */ + } else if (signal == SIGNAL_TYPE_DISPLAY_PORT_MST) { + dpia_control.mode_laneset.digmode = 5; /* 0 for SST; 5 for MST */ + } else { + DC_LOG_ERROR("%s: USB4 DPIA only supports DisplayPort.\n", __func__); + BREAK_TO_DEBUGGER(); + } + + if (link) { + dpia_control.dpia_id = link->ddc_hw_inst; + } else { + DC_LOG_ERROR("%s: Failed to execute DPIA enable DMUB command.\n", __func__); + BREAK_TO_DEBUGGER(); + return; + } + + DC_LOG_DEBUG("%s: DPIA(%d) - enc_id(%d)\n", __func__, dpia_control.dpia_id, dpia_control.enc_id); + link_dpia_control(enc->ctx, &dpia_control); + + link_encoder_disable(enc10); + } +} + +bool dcn31_link_encoder_is_in_alt_mode(struct link_encoder *enc) +{ + struct dcn10_link_encoder *enc10 = TO_DCN10_LINK_ENC(enc); + union dmub_rb_cmd cmd; + uint32_t dp_alt_mode_disable; + + /* Only applicable to USB-C PHY. */ + if (!enc->features.flags.bits.DP_IS_USB_C) + return false; + + /* + * Use the new interface from DMCUB if available. + * Avoids hanging the RDCPSPIPE if DMCUB wasn't already running. + */ + if (has_query_dp_alt(enc)) { + if (!query_dp_alt_from_dmub(enc, &cmd)) + return false; + + return (cmd.query_dp_alt.data.is_dp_alt_disable == 0); + } + + /* Legacy path, avoid if possible. */ + if (enc->ctx->asic_id.hw_internal_rev != YELLOW_CARP_B0) { + REG_GET(RDPCSTX_PHY_CNTL6, RDPCS_PHY_DPALT_DISABLE, + &dp_alt_mode_disable); + } else { + /* + * B0 phys use a new set of registers to check whether alt mode is disabled. + * if value == 1 alt mode is disabled, otherwise it is enabled. + */ + if ((enc10->base.transmitter == TRANSMITTER_UNIPHY_A) || + (enc10->base.transmitter == TRANSMITTER_UNIPHY_B) || + (enc10->base.transmitter == TRANSMITTER_UNIPHY_E)) { + REG_GET(RDPCSTX_PHY_CNTL6, RDPCS_PHY_DPALT_DISABLE, + &dp_alt_mode_disable); + } else { + REG_GET(RDPCSPIPE_PHY_CNTL6, RDPCS_PHY_DPALT_DISABLE, + &dp_alt_mode_disable); + } + } + + return (dp_alt_mode_disable == 0); +} + +void dcn31_link_encoder_get_max_link_cap(struct link_encoder *enc, struct dc_link_settings *link_settings) +{ + struct dcn10_link_encoder *enc10 = TO_DCN10_LINK_ENC(enc); + union dmub_rb_cmd cmd; + uint32_t is_in_usb_c_dp4_mode = 0; + + dcn10_link_encoder_get_max_link_cap(enc, link_settings); + + /* Take the link cap directly if not USB */ + if (!enc->features.flags.bits.DP_IS_USB_C) + return; + + /* + * Use the new interface from DMCUB if available. + * Avoids hanging the RDCPSPIPE if DMCUB wasn't already running. + */ + if (has_query_dp_alt(enc)) { + if (!query_dp_alt_from_dmub(enc, &cmd)) + return; + + if (cmd.query_dp_alt.data.is_usb && + cmd.query_dp_alt.data.is_dp4 == 0) + link_settings->lane_count = MIN(LANE_COUNT_TWO, link_settings->lane_count); + + return; + } + + /* Legacy path, avoid if possible. */ + if (enc->ctx->asic_id.hw_internal_rev != YELLOW_CARP_B0) { + REG_GET(RDPCSTX_PHY_CNTL6, RDPCS_PHY_DPALT_DP4, + &is_in_usb_c_dp4_mode); + } else { + if ((enc10->base.transmitter == TRANSMITTER_UNIPHY_A) || + (enc10->base.transmitter == TRANSMITTER_UNIPHY_B) || + (enc10->base.transmitter == TRANSMITTER_UNIPHY_E)) { + REG_GET(RDPCSTX_PHY_CNTL6, RDPCS_PHY_DPALT_DP4, + &is_in_usb_c_dp4_mode); + } else { + REG_GET(RDPCSPIPE_PHY_CNTL6, RDPCS_PHY_DPALT_DP4, + &is_in_usb_c_dp4_mode); + } + } + + if (!is_in_usb_c_dp4_mode) + link_settings->lane_count = MIN(LANE_COUNT_TWO, link_settings->lane_count); +} diff --git a/drivers/gpu/drm/amd/display/dc/dio/dcn31/dcn31_dio_link_encoder.h b/drivers/gpu/drm/amd/display/dc/dio/dcn31/dcn31_dio_link_encoder.h new file mode 100644 index 000000000000..ee78ba80797c --- /dev/null +++ b/drivers/gpu/drm/amd/display/dc/dio/dcn31/dcn31_dio_link_encoder.h @@ -0,0 +1,290 @@ +/* + * Copyright 2012-15 Advanced Micro Devices, Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + * + * Authors: AMD + * + */ + +#ifndef __DC_LINK_ENCODER__DCN31_H__ +#define __DC_LINK_ENCODER__DCN31_H__ + +#include "dcn30/dcn30_dio_link_encoder.h" + + +#define LE_DCN31_REG_LIST(id)\ + LE_DCN3_REG_LIST(id),\ + SRI(DP_DPHY_INTERNAL_CTRL, DP, id), \ + SR(DIO_LINKA_CNTL), \ + SR(DIO_LINKB_CNTL), \ + SR(DIO_LINKC_CNTL), \ + SR(DIO_LINKD_CNTL), \ + SR(DIO_LINKE_CNTL), \ + SR(DIO_LINKF_CNTL) + +#define LINK_ENCODER_MASK_SH_LIST_DCN31(mask_sh) \ + LINK_ENCODER_MASK_SH_LIST_DCN10(mask_sh),\ + LE_SF(DP0_DP_DPHY_CNTL, DPHY_FEC_EN, mask_sh),\ + LE_SF(DP0_DP_DPHY_CNTL, DPHY_FEC_READY_SHADOW, mask_sh),\ + LE_SF(DP0_DP_DPHY_CNTL, DPHY_FEC_ACTIVE_STATUS, mask_sh),\ + LE_SF(DIG0_TMDS_CTL_BITS, TMDS_CTL0, mask_sh), \ + LE_SF(DP_AUX0_AUX_DPHY_RX_CONTROL0, AUX_RX_START_WINDOW, mask_sh),\ + LE_SF(DP_AUX0_AUX_DPHY_RX_CONTROL0, AUX_RX_HALF_SYM_DETECT_LEN, mask_sh),\ + LE_SF(DP_AUX0_AUX_DPHY_RX_CONTROL0, AUX_RX_TRANSITION_FILTER_EN, mask_sh),\ + LE_SF(DP_AUX0_AUX_DPHY_RX_CONTROL0, AUX_RX_ALLOW_BELOW_THRESHOLD_PHASE_DETECT, mask_sh),\ + LE_SF(DP_AUX0_AUX_DPHY_RX_CONTROL0, AUX_RX_ALLOW_BELOW_THRESHOLD_START, mask_sh),\ + LE_SF(DP_AUX0_AUX_DPHY_RX_CONTROL0, AUX_RX_ALLOW_BELOW_THRESHOLD_STOP, mask_sh),\ + LE_SF(DP_AUX0_AUX_DPHY_RX_CONTROL0, AUX_RX_PHASE_DETECT_LEN, mask_sh),\ + LE_SF(DP_AUX0_AUX_DPHY_RX_CONTROL0, AUX_RX_DETECTION_THRESHOLD, mask_sh), \ + LE_SF(DP_AUX0_AUX_DPHY_TX_CONTROL, AUX_TX_PRECHARGE_LEN, mask_sh),\ + LE_SF(DP_AUX0_AUX_DPHY_TX_CONTROL, AUX_TX_PRECHARGE_SYMBOLS, mask_sh),\ + LE_SF(DP_AUX0_AUX_DPHY_TX_CONTROL, AUX_MODE_DET_CHECK_DELAY, mask_sh),\ + LE_SF(DP_AUX0_AUX_DPHY_RX_CONTROL1, AUX_RX_PRECHARGE_SKIP, mask_sh),\ + LE_SF(DP_AUX0_AUX_DPHY_RX_CONTROL1, AUX_RX_TIMEOUT_LEN, mask_sh),\ + LE_SF(DP_AUX0_AUX_DPHY_RX_CONTROL1, AUX_RX_TIMEOUT_LEN_MUL, mask_sh),\ + LE_SF(DIO_LINKA_CNTL, ENC_TYPE_SEL, mask_sh),\ + LE_SF(DIO_LINKA_CNTL, HPO_DP_ENC_SEL, mask_sh),\ + LE_SF(DIO_LINKA_CNTL, HPO_HDMI_ENC_SEL, mask_sh) + +#define DPCS_DCN31_REG_LIST(id) \ + SRI(TMDS_CTL_BITS, DIG, id), \ + SRI(RDPCSTX_PHY_CNTL3, RDPCSTX, id), \ + SRI(RDPCSTX_PHY_CNTL4, RDPCSTX, id), \ + SRI(RDPCSTX_PHY_CNTL5, RDPCSTX, id), \ + SRI(RDPCSTX_PHY_CNTL6, RDPCSTX, id), \ + SRI(RDPCSPIPE_PHY_CNTL6, RDPCSPIPE, id), \ + SRI(RDPCSTX_PHY_CNTL7, RDPCSTX, id), \ + SRI(RDPCSTX_PHY_CNTL8, RDPCSTX, id), \ + SRI(RDPCSTX_PHY_CNTL9, RDPCSTX, id), \ + SRI(RDPCSTX_PHY_CNTL10, RDPCSTX, id), \ + SRI(RDPCSTX_PHY_CNTL11, RDPCSTX, id), \ + SRI(RDPCSTX_PHY_CNTL12, RDPCSTX, id), \ + SRI(RDPCSTX_PHY_CNTL13, RDPCSTX, id), \ + SRI(RDPCSTX_PHY_CNTL14, RDPCSTX, id), \ + SRI(RDPCSTX_CNTL, RDPCSTX, id), \ + SRI(RDPCSTX_CLOCK_CNTL, RDPCSTX, id), \ + SRI(RDPCSTX_INTERRUPT_CONTROL, RDPCSTX, id), \ + SRI(RDPCSTX_PHY_CNTL0, RDPCSTX, id), \ + SRI(RDPCSTX_PHY_CNTL2, RDPCSTX, id), \ + SRI(RDPCS_TX_CR_ADDR, RDPCSTX, id), \ + SRI(RDPCS_TX_CR_DATA, RDPCSTX, id), \ + SRI(RDPCSTX_PHY_FUSE0, RDPCSTX, id), \ + SRI(RDPCSTX_PHY_FUSE1, RDPCSTX, id), \ + SRI(RDPCSTX_PHY_FUSE2, RDPCSTX, id), \ + SRI(RDPCSTX_PHY_FUSE3, RDPCSTX, id), \ + SRI(RDPCSTX_DEBUG_CONFIG, RDPCSTX, id), \ + SR(RDPCSTX0_RDPCSTX_SCRATCH), \ + SRI(RDPCSTX_PHY_RX_LD_VAL, RDPCSTX, id),\ + SRI(RDPCSTX_DMCU_DPALT_DIS_BLOCK_REG, RDPCSTX, id) + +#define DPCS_DCN31_MASK_SH_LIST(mask_sh)\ + LE_SF(RDPCSTX0_RDPCSTX_PHY_CNTL3, RDPCS_PHY_DP_TX0_CLK_RDY, mask_sh),\ + LE_SF(RDPCSTX0_RDPCSTX_PHY_CNTL3, RDPCS_PHY_DP_TX0_DATA_EN, mask_sh),\ + LE_SF(RDPCSTX0_RDPCSTX_PHY_CNTL3, RDPCS_PHY_DP_TX1_CLK_RDY, mask_sh),\ + LE_SF(RDPCSTX0_RDPCSTX_PHY_CNTL3, RDPCS_PHY_DP_TX1_DATA_EN, mask_sh),\ + LE_SF(RDPCSTX0_RDPCSTX_PHY_CNTL3, RDPCS_PHY_DP_TX2_CLK_RDY, mask_sh),\ + LE_SF(RDPCSTX0_RDPCSTX_PHY_CNTL3, RDPCS_PHY_DP_TX2_DATA_EN, mask_sh),\ + LE_SF(RDPCSTX0_RDPCSTX_PHY_CNTL3, RDPCS_PHY_DP_TX3_CLK_RDY, mask_sh),\ + LE_SF(RDPCSTX0_RDPCSTX_PHY_CNTL3, RDPCS_PHY_DP_TX3_DATA_EN, mask_sh),\ + LE_SF(RDPCSTX0_RDPCSTX_PHY_CNTL4, RDPCS_PHY_DP_TX0_TERM_CTRL, mask_sh),\ + LE_SF(RDPCSTX0_RDPCSTX_PHY_CNTL4, RDPCS_PHY_DP_TX1_TERM_CTRL, mask_sh),\ + LE_SF(RDPCSTX0_RDPCSTX_PHY_CNTL4, RDPCS_PHY_DP_TX2_TERM_CTRL, mask_sh),\ + LE_SF(RDPCSTX0_RDPCSTX_PHY_CNTL4, RDPCS_PHY_DP_TX3_TERM_CTRL, mask_sh),\ + LE_SF(RDPCSTX0_RDPCSTX_PHY_CNTL11, RDPCS_PHY_DP_MPLLB_MULTIPLIER, mask_sh),\ + LE_SF(RDPCSTX0_RDPCSTX_PHY_CNTL5, RDPCS_PHY_DP_TX0_WIDTH, mask_sh),\ + LE_SF(RDPCSTX0_RDPCSTX_PHY_CNTL5, RDPCS_PHY_DP_TX0_RATE, mask_sh),\ + LE_SF(RDPCSTX0_RDPCSTX_PHY_CNTL5, RDPCS_PHY_DP_TX1_WIDTH, mask_sh),\ + LE_SF(RDPCSTX0_RDPCSTX_PHY_CNTL5, RDPCS_PHY_DP_TX1_RATE, mask_sh),\ + LE_SF(RDPCSTX0_RDPCSTX_PHY_CNTL6, RDPCS_PHY_DP_TX2_PSTATE, mask_sh),\ + LE_SF(RDPCSTX0_RDPCSTX_PHY_CNTL6, RDPCS_PHY_DP_TX3_PSTATE, mask_sh),\ + LE_SF(RDPCSTX0_RDPCSTX_PHY_CNTL6, RDPCS_PHY_DP_TX2_MPLL_EN, mask_sh),\ + LE_SF(RDPCSTX0_RDPCSTX_PHY_CNTL6, RDPCS_PHY_DP_TX3_MPLL_EN, mask_sh),\ + LE_SF(RDPCSTX0_RDPCSTX_PHY_CNTL6, RDPCS_PHY_DPALT_DP4, mask_sh),\ + LE_SF(RDPCSPIPE0_RDPCSPIPE_PHY_CNTL6, RDPCS_PHY_DPALT_DP4, mask_sh),\ + LE_SF(RDPCSPIPE0_RDPCSPIPE_PHY_CNTL6, RDPCS_PHY_DPALT_DISABLE, mask_sh),\ + LE_SF(RDPCSPIPE0_RDPCSPIPE_PHY_CNTL6, RDPCS_PHY_DPALT_DISABLE_ACK, mask_sh),\ + LE_SF(RDPCSTX0_RDPCSTX_PHY_CNTL7, RDPCS_PHY_DP_MPLLB_FRACN_QUOT, mask_sh),\ + LE_SF(RDPCSTX0_RDPCSTX_PHY_CNTL7, RDPCS_PHY_DP_MPLLB_FRACN_DEN, mask_sh),\ + LE_SF(RDPCSTX0_RDPCSTX_PHY_CNTL8, RDPCS_PHY_DP_MPLLB_SSC_PEAK, mask_sh),\ + LE_SF(RDPCSTX0_RDPCSTX_PHY_CNTL9, RDPCS_PHY_DP_MPLLB_SSC_UP_SPREAD, mask_sh),\ + LE_SF(RDPCSTX0_RDPCSTX_PHY_CNTL9, RDPCS_PHY_DP_MPLLB_SSC_STEPSIZE, mask_sh),\ + LE_SF(RDPCSTX0_RDPCSTX_PHY_CNTL10, RDPCS_PHY_DP_MPLLB_FRACN_REM, mask_sh),\ + LE_SF(RDPCSTX0_RDPCSTX_PHY_CNTL11, RDPCS_PHY_DP_REF_CLK_MPLLB_DIV, mask_sh),\ + LE_SF(RDPCSTX0_RDPCSTX_PHY_CNTL11, RDPCS_PHY_HDMI_MPLLB_HDMI_DIV, mask_sh),\ + LE_SF(RDPCSTX0_RDPCSTX_PHY_CNTL12, RDPCS_PHY_DP_MPLLB_SSC_EN, mask_sh),\ + LE_SF(RDPCSTX0_RDPCSTX_PHY_CNTL12, RDPCS_PHY_DP_MPLLB_DIV5_CLK_EN, mask_sh),\ + LE_SF(RDPCSTX0_RDPCSTX_PHY_CNTL12, RDPCS_PHY_DP_MPLLB_TX_CLK_DIV, mask_sh),\ + LE_SF(RDPCSTX0_RDPCSTX_PHY_CNTL12, RDPCS_PHY_DP_MPLLB_WORD_DIV2_EN, mask_sh),\ + LE_SF(RDPCSTX0_RDPCSTX_PHY_CNTL12, RDPCS_PHY_DP_MPLLB_STATE, mask_sh),\ + LE_SF(RDPCSTX0_RDPCSTX_PHY_CNTL13, RDPCS_PHY_DP_MPLLB_DIV_CLK_EN, mask_sh),\ + LE_SF(RDPCSTX0_RDPCSTX_PHY_CNTL13, RDPCS_PHY_DP_MPLLB_DIV_MULTIPLIER, mask_sh),\ + LE_SF(RDPCSTX0_RDPCSTX_PHY_CNTL14, RDPCS_PHY_DP_MPLLB_FRACN_EN, mask_sh),\ + LE_SF(RDPCSTX0_RDPCSTX_PHY_CNTL14, RDPCS_PHY_DP_MPLLB_PMIX_EN, mask_sh),\ + LE_SF(RDPCSTX0_RDPCSTX_CNTL, RDPCS_TX_FIFO_LANE0_EN, mask_sh),\ + LE_SF(RDPCSTX0_RDPCSTX_CNTL, RDPCS_TX_FIFO_LANE1_EN, mask_sh),\ + LE_SF(RDPCSTX0_RDPCSTX_CNTL, RDPCS_TX_FIFO_LANE2_EN, mask_sh),\ + LE_SF(RDPCSTX0_RDPCSTX_CNTL, RDPCS_TX_FIFO_LANE3_EN, mask_sh),\ + LE_SF(RDPCSTX0_RDPCSTX_CNTL, RDPCS_TX_FIFO_EN, mask_sh),\ + LE_SF(RDPCSTX0_RDPCSTX_CNTL, RDPCS_TX_FIFO_RD_START_DELAY, mask_sh),\ + LE_SF(RDPCSTX0_RDPCSTX_CLOCK_CNTL, RDPCS_EXT_REFCLK_EN, mask_sh),\ + LE_SF(RDPCSTX0_RDPCSTX_CLOCK_CNTL, RDPCS_SRAMCLK_BYPASS, mask_sh),\ + LE_SF(RDPCSTX0_RDPCSTX_CLOCK_CNTL, RDPCS_SRAMCLK_EN, mask_sh),\ + LE_SF(RDPCSTX0_RDPCSTX_CLOCK_CNTL, RDPCS_SRAMCLK_CLOCK_ON, mask_sh),\ + LE_SF(RDPCSTX0_RDPCSTX_CLOCK_CNTL, RDPCS_SYMCLK_DIV2_CLOCK_ON, mask_sh),\ + LE_SF(RDPCSTX0_RDPCSTX_CLOCK_CNTL, RDPCS_SYMCLK_DIV2_GATE_DIS, mask_sh),\ + LE_SF(RDPCSTX0_RDPCSTX_CLOCK_CNTL, RDPCS_SYMCLK_DIV2_EN, mask_sh),\ + LE_SF(RDPCSTX0_RDPCSTX_PHY_CNTL3, RDPCS_PHY_DP_TX0_DISABLE, mask_sh),\ + LE_SF(RDPCSTX0_RDPCSTX_PHY_CNTL3, RDPCS_PHY_DP_TX1_DISABLE, mask_sh),\ + LE_SF(RDPCSTX0_RDPCSTX_PHY_CNTL3, RDPCS_PHY_DP_TX2_DISABLE, mask_sh),\ + LE_SF(RDPCSTX0_RDPCSTX_PHY_CNTL3, RDPCS_PHY_DP_TX3_DISABLE, mask_sh),\ + LE_SF(RDPCSTX0_RDPCSTX_PHY_CNTL3, RDPCS_PHY_DP_TX0_REQ, mask_sh),\ + LE_SF(RDPCSTX0_RDPCSTX_PHY_CNTL3, RDPCS_PHY_DP_TX1_REQ, mask_sh),\ + LE_SF(RDPCSTX0_RDPCSTX_PHY_CNTL3, RDPCS_PHY_DP_TX2_REQ, mask_sh),\ + LE_SF(RDPCSTX0_RDPCSTX_PHY_CNTL3, RDPCS_PHY_DP_TX3_REQ, mask_sh),\ + LE_SF(RDPCSTX0_RDPCSTX_PHY_CNTL3, RDPCS_PHY_DP_TX0_ACK, mask_sh),\ + LE_SF(RDPCSTX0_RDPCSTX_PHY_CNTL3, RDPCS_PHY_DP_TX1_ACK, mask_sh),\ + LE_SF(RDPCSTX0_RDPCSTX_PHY_CNTL3, RDPCS_PHY_DP_TX2_ACK, mask_sh),\ + LE_SF(RDPCSTX0_RDPCSTX_PHY_CNTL3, RDPCS_PHY_DP_TX3_ACK, mask_sh),\ + LE_SF(RDPCSTX0_RDPCSTX_PHY_CNTL3, RDPCS_PHY_DP_TX0_RESET, mask_sh),\ + LE_SF(RDPCSTX0_RDPCSTX_PHY_CNTL3, RDPCS_PHY_DP_TX1_RESET, mask_sh),\ + LE_SF(RDPCSTX0_RDPCSTX_PHY_CNTL3, RDPCS_PHY_DP_TX2_RESET, mask_sh),\ + LE_SF(RDPCSTX0_RDPCSTX_PHY_CNTL3, RDPCS_PHY_DP_TX3_RESET, mask_sh),\ + LE_SF(RDPCSTX0_RDPCSTX_PHY_CNTL0, RDPCS_PHY_RESET, mask_sh),\ + LE_SF(RDPCSTX0_RDPCSTX_PHY_CNTL0, RDPCS_PHY_CR_MUX_SEL, mask_sh),\ + LE_SF(RDPCSTX0_RDPCSTX_PHY_CNTL0, RDPCS_PHY_REF_RANGE, mask_sh),\ + LE_SF(RDPCSTX0_RDPCSTX_PHY_CNTL0, RDPCS_SRAM_BYPASS, mask_sh),\ + LE_SF(RDPCSTX0_RDPCSTX_PHY_CNTL0, RDPCS_SRAM_EXT_LD_DONE, mask_sh),\ + LE_SF(RDPCSTX0_RDPCSTX_PHY_CNTL0, RDPCS_PHY_HDMIMODE_ENABLE, mask_sh),\ + LE_SF(RDPCSTX0_RDPCSTX_PHY_CNTL0, RDPCS_SRAM_INIT_DONE, mask_sh),\ + LE_SF(RDPCSTX0_RDPCSTX_PHY_CNTL2, RDPCS_PHY_DP4_POR, mask_sh),\ + LE_SF(RDPCSTX0_RDPCSTX_INTERRUPT_CONTROL, RDPCS_REG_FIFO_ERROR_MASK, mask_sh),\ + LE_SF(RDPCSTX0_RDPCSTX_INTERRUPT_CONTROL, RDPCS_TX_FIFO_ERROR_MASK, mask_sh),\ + LE_SF(RDPCSTX0_RDPCSTX_INTERRUPT_CONTROL, RDPCS_DPALT_DISABLE_TOGGLE_MASK, mask_sh),\ + LE_SF(RDPCSTX0_RDPCSTX_INTERRUPT_CONTROL, RDPCS_DPALT_4LANE_TOGGLE_MASK, mask_sh),\ + LE_SF(RDPCSTX0_RDPCS_TX_CR_ADDR, RDPCS_TX_CR_ADDR, mask_sh),\ + LE_SF(RDPCSTX0_RDPCS_TX_CR_DATA, RDPCS_TX_CR_DATA, mask_sh),\ + LE_SF(RDPCSTX0_RDPCSTX_PHY_FUSE0, RDPCS_PHY_DP_MPLLB_V2I, mask_sh),\ + LE_SF(RDPCSTX0_RDPCSTX_PHY_FUSE0, RDPCS_PHY_DP_TX0_EQ_MAIN, mask_sh),\ + LE_SF(RDPCSTX0_RDPCSTX_PHY_FUSE0, RDPCS_PHY_DP_TX0_EQ_PRE, mask_sh),\ + LE_SF(RDPCSTX0_RDPCSTX_PHY_FUSE0, RDPCS_PHY_DP_TX0_EQ_POST, mask_sh),\ + LE_SF(RDPCSTX0_RDPCSTX_PHY_FUSE0, RDPCS_PHY_DP_MPLLB_FREQ_VCO, mask_sh),\ + LE_SF(RDPCSTX0_RDPCSTX_PHY_FUSE1, RDPCS_PHY_DP_MPLLB_CP_INT, mask_sh),\ + LE_SF(RDPCSTX0_RDPCSTX_PHY_FUSE1, RDPCS_PHY_DP_MPLLB_CP_PROP, mask_sh),\ + LE_SF(RDPCSTX0_RDPCSTX_PHY_FUSE1, RDPCS_PHY_DP_TX1_EQ_MAIN, mask_sh),\ + LE_SF(RDPCSTX0_RDPCSTX_PHY_FUSE1, RDPCS_PHY_DP_TX1_EQ_PRE, mask_sh),\ + LE_SF(RDPCSTX0_RDPCSTX_PHY_FUSE1, RDPCS_PHY_DP_TX1_EQ_POST, mask_sh),\ + LE_SF(RDPCSTX0_RDPCSTX_PHY_FUSE2, RDPCS_PHY_DP_TX2_EQ_MAIN, mask_sh),\ + LE_SF(RDPCSTX0_RDPCSTX_PHY_FUSE2, RDPCS_PHY_DP_TX2_EQ_PRE, mask_sh),\ + LE_SF(RDPCSTX0_RDPCSTX_PHY_FUSE2, RDPCS_PHY_DP_TX2_EQ_POST, mask_sh),\ + LE_SF(RDPCSTX0_RDPCSTX_PHY_FUSE3, RDPCS_PHY_DP_TX3_EQ_MAIN, mask_sh),\ + LE_SF(RDPCSTX0_RDPCSTX_PHY_FUSE3, RDPCS_PHY_DCO_FINETUNE, mask_sh),\ + LE_SF(RDPCSTX0_RDPCSTX_PHY_FUSE3, RDPCS_PHY_DCO_RANGE, mask_sh),\ + LE_SF(RDPCSTX0_RDPCSTX_PHY_FUSE3, RDPCS_PHY_DP_TX3_EQ_PRE, mask_sh),\ + LE_SF(RDPCSTX0_RDPCSTX_PHY_FUSE3, RDPCS_PHY_DP_TX3_EQ_POST, mask_sh) + +#define DPCS_DCN314_REG_LIST(id) \ + SRI(TMDS_CTL_BITS, DIG, id), \ + SRI(RDPCSTX_PHY_CNTL3, RDPCSTX, id), \ + SRI(RDPCSTX_PHY_CNTL4, RDPCSTX, id), \ + SRI(RDPCSTX_PHY_CNTL5, RDPCSTX, id), \ + SRI(RDPCSTX_PHY_CNTL7, RDPCSTX, id), \ + SRI(RDPCSTX_PHY_CNTL8, RDPCSTX, id), \ + SRI(RDPCSTX_PHY_CNTL9, RDPCSTX, id), \ + SRI(RDPCSTX_PHY_CNTL10, RDPCSTX, id), \ + SRI(RDPCSTX_PHY_CNTL11, RDPCSTX, id), \ + SRI(RDPCSTX_PHY_CNTL12, RDPCSTX, id), \ + SRI(RDPCSTX_PHY_CNTL13, RDPCSTX, id), \ + SRI(RDPCSTX_PHY_CNTL14, RDPCSTX, id), \ + SRI(RDPCSTX_CNTL, RDPCSTX, id), \ + SRI(RDPCSTX_CLOCK_CNTL, RDPCSTX, id), \ + SRI(RDPCSTX_INTERRUPT_CONTROL, RDPCSTX, id), \ + SRI(RDPCSTX_PHY_CNTL0, RDPCSTX, id), \ + SRI(RDPCSTX_PHY_CNTL2, RDPCSTX, id), \ + SRI(RDPCS_TX_CR_ADDR, RDPCSTX, id), \ + SRI(RDPCS_TX_CR_DATA, RDPCSTX, id), \ + SRI(RDPCSTX_PHY_FUSE0, RDPCSTX, id), \ + SRI(RDPCSTX_PHY_FUSE1, RDPCSTX, id), \ + SRI(RDPCSTX_PHY_FUSE2, RDPCSTX, id), \ + SRI(RDPCSTX_PHY_FUSE3, RDPCSTX, id), \ + SRI(RDPCSTX_DEBUG_CONFIG, RDPCSTX, id), \ + SR(RDPCSTX0_RDPCSTX_SCRATCH), \ + SRI(RDPCSTX_PHY_RX_LD_VAL, RDPCSTX, id),\ + SRI(RDPCSTX_DMCU_DPALT_DIS_BLOCK_REG, RDPCSTX, id) + +void dcn31_link_encoder_construct( + struct dcn20_link_encoder *enc20, + const struct encoder_init_data *init_data, + const struct encoder_feature_support *enc_features, + const struct dcn10_link_enc_registers *link_regs, + const struct dcn10_link_enc_aux_registers *aux_regs, + const struct dcn10_link_enc_hpd_registers *hpd_regs, + const struct dcn10_link_enc_shift *link_shift, + const struct dcn10_link_enc_mask *link_mask); + +/* + * Create a minimal link encoder object with no dc_link object associated with it. + */ +void dcn31_link_encoder_construct_minimal( + struct dcn20_link_encoder *enc20, + struct dc_context *ctx, + const struct encoder_feature_support *enc_features, + const struct dcn10_link_enc_registers *link_regs, + enum engine_id eng_id); + +void dcn31_link_encoder_set_dio_phy_mux( + struct link_encoder *enc, + enum encoder_type_select sel, + uint32_t hpo_inst); + +/* + * Enable DP transmitter and its encoder. + */ +void dcn31_link_encoder_enable_dp_output( + struct link_encoder *enc, + const struct dc_link_settings *link_settings, + enum clock_source_id clock_source); + +/* + * Enable DP transmitter and its encoder in MST mode. + */ +void dcn31_link_encoder_enable_dp_mst_output( + struct link_encoder *enc, + const struct dc_link_settings *link_settings, + enum clock_source_id clock_source); + +/* + * Disable transmitter and its encoder. + */ +void dcn31_link_encoder_disable_output( + struct link_encoder *enc, + enum signal_type signal); + +/* + * Check whether USB-C DP Alt mode is disabled + */ +bool dcn31_link_encoder_is_in_alt_mode( + struct link_encoder *enc); + +void dcn31_link_encoder_get_max_link_cap(struct link_encoder *enc, + struct dc_link_settings *link_settings); + +void enc31_hw_init(struct link_encoder *enc); + +#endif /* __DC_LINK_ENCODER__DCN31_H__ */ -- cgit From 9ff3ba3e769361ebc22e59c76b18bc67427b541f Mon Sep 17 00:00:00 2001 From: "Xi (Alex) Liu" Date: Wed, 12 Jun 2024 12:45:19 -0400 Subject: drm/amd/display: replace CRTC disable function call [Why] In OTG disable workarund, CRTC is disabled immediately to improve performance, but this may cause timing issue in DP HPO encoder FIFO and result in blank CRCs. [How] Replace the immediate CRTC disable call with normal disable call Reviewed-by: Nicholas Kazlauskas Signed-off-by: Jerry Zuo Signed-off-by: Xi (Alex) Liu Tested-by: Daniel Wheeler Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/dc/clk_mgr/dcn35/dcn35_clk_mgr.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/gpu/drm/amd/display/dc/clk_mgr/dcn35/dcn35_clk_mgr.c b/drivers/gpu/drm/amd/display/dc/clk_mgr/dcn35/dcn35_clk_mgr.c index 5691714f738d..70ee0089a20d 100644 --- a/drivers/gpu/drm/amd/display/dc/clk_mgr/dcn35/dcn35_clk_mgr.c +++ b/drivers/gpu/drm/amd/display/dc/clk_mgr/dcn35/dcn35_clk_mgr.c @@ -137,8 +137,8 @@ static void dcn35_disable_otg_wa(struct clk_mgr *clk_mgr_base, struct dc_state * if (pipe->stream && (pipe->stream->dpms_off || dc_is_virtual_signal(pipe->stream->signal) || !pipe->stream->link_enc)) { if (disable) { - if (pipe->stream_res.tg && pipe->stream_res.tg->funcs->immediate_disable_crtc) - pipe->stream_res.tg->funcs->immediate_disable_crtc(pipe->stream_res.tg); + if (pipe->stream_res.tg && pipe->stream_res.tg->funcs->disable_crtc) + pipe->stream_res.tg->funcs->disable_crtc(pipe->stream_res.tg); reset_sync_context_for_pipe(dc, context, i); } else { -- cgit From a638b837d0e6052678a686d42018271042e38408 Mon Sep 17 00:00:00 2001 From: Tom Chung Date: Fri, 14 Jun 2024 15:38:56 +0800 Subject: drm/amd/display: Fix refresh rate range for some panel [Why] Some of the panels does not have the refresh rate range info in base EDID and only have the refresh rate range info in DisplayID block. It will cause the max/min freesync refresh rate set to 0. [How] Try to parse the refresh rate range info from DisplayID if the max/min refresh rate is 0. Reviewed-by: Sun peng Li Signed-off-by: Jerry Zuo Signed-off-by: Tom Chung Tested-by: Daniel Wheeler Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c | 48 +++++++++++++++++++++++ 1 file changed, 48 insertions(+) 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 e64592e49568..f83ef3e1554c 100644 --- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c +++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c @@ -11864,6 +11864,49 @@ static bool parse_edid_cea(struct amdgpu_dm_connector *aconnector, return ret; } +static void parse_edid_displayid_vrr(struct drm_connector *connector, + struct edid *edid) +{ + u8 *edid_ext = NULL; + int i; + int j = 0; + u16 min_vfreq; + u16 max_vfreq; + + if (edid == NULL || edid->extensions == 0) + return; + + /* Find DisplayID extension */ + for (i = 0; i < edid->extensions; i++) { + edid_ext = (void *)(edid + (i + 1)); + if (edid_ext[0] == DISPLAYID_EXT) + break; + } + + if (edid_ext == NULL) + return; + + while (j < EDID_LENGTH) { + /* Get dynamic video timing range from DisplayID if available */ + if (EDID_LENGTH - j > 13 && edid_ext[j] == 0x25 && + (edid_ext[j+1] & 0xFE) == 0 && (edid_ext[j+2] == 9)) { + min_vfreq = edid_ext[j+9]; + if (edid_ext[j+1] & 7) + max_vfreq = edid_ext[j+10] + ((edid_ext[j+11] & 3) << 8); + else + max_vfreq = edid_ext[j+10]; + + if (max_vfreq && min_vfreq) { + connector->display_info.monitor_range.max_vfreq = max_vfreq; + connector->display_info.monitor_range.min_vfreq = min_vfreq; + + return; + } + } + j++; + } +} + static int parse_amd_vsdb(struct amdgpu_dm_connector *aconnector, struct edid *edid, struct amdgpu_hdmi_vsdb_info *vsdb_info) { @@ -11984,6 +12027,11 @@ void amdgpu_dm_update_freesync_caps(struct drm_connector *connector, if (!adev->dm.freesync_module) goto update; + /* Some eDP panels only have the refresh rate range info in DisplayID */ + if ((connector->display_info.monitor_range.min_vfreq == 0 || + connector->display_info.monitor_range.max_vfreq == 0)) + parse_edid_displayid_vrr(connector, edid); + if (edid && (sink->sink_signal == SIGNAL_TYPE_DISPLAY_PORT || sink->sink_signal == SIGNAL_TYPE_EDP)) { bool edid_check_required = false; -- cgit From 882643a95fe60c23a70917f97ac0781e92c583dc Mon Sep 17 00:00:00 2001 From: Fangzhi Zuo Date: Wed, 26 Jun 2024 14:07:49 -0400 Subject: drm/amd/display: Update efficiency bandwidth for dcn351 Fix 4k240 underflow on dcn351 Acked-by: Rodrigo Siqueira Signed-off-by: Fangzhi Zuo Tested-by: Daniel Wheeler Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/dc/dml2/dml2_translation_helper.c | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/gpu/drm/amd/display/dc/dml2/dml2_translation_helper.c b/drivers/gpu/drm/amd/display/dc/dml2/dml2_translation_helper.c index 935893456849..8b9dcee77266 100644 --- a/drivers/gpu/drm/amd/display/dc/dml2/dml2_translation_helper.c +++ b/drivers/gpu/drm/amd/display/dc/dml2/dml2_translation_helper.c @@ -296,6 +296,7 @@ void dml2_init_socbb_params(struct dml2_context *dml2, const struct dc *in_dc, s out->round_trip_ping_latency_dcfclk_cycles = 106; out->smn_latency_us = 2; out->dispclk_dppclk_vco_speed_mhz = 3600; + out->pct_ideal_dram_bw_after_urgent_pixel_only = 65.0; break; case dml_project_dcn401: -- cgit From 9ef37ff38d01a616a670019330190ce1817df887 Mon Sep 17 00:00:00 2001 From: Roman Li Date: Wed, 26 Jun 2024 14:08:41 -0400 Subject: drm/amd/display: Fix array-index-out-of-bounds in dml2/FCLKChangeSupport [Why] Potential out of bounds access in dml2_calculate_rq_and_dlg_params() because the value of out_lowest_state_idx used as an index for FCLKChangeSupport array can be greater than 1. [How] Currently dml2 core specifies identical values for all FCLKChangeSupport elements. Always use index 0 in the condition to avoid out of bounds access. Acked-by: Rodrigo Siqueira Signed-off-by: Jerry Zuo Signed-off-by: Roman Li Tested-by: Daniel Wheeler Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/dc/dml2/dml2_utils.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/gpu/drm/amd/display/dc/dml2/dml2_utils.c b/drivers/gpu/drm/amd/display/dc/dml2/dml2_utils.c index d91948d6ff97..92238ff333a4 100644 --- a/drivers/gpu/drm/amd/display/dc/dml2/dml2_utils.c +++ b/drivers/gpu/drm/amd/display/dc/dml2/dml2_utils.c @@ -293,7 +293,7 @@ void dml2_calculate_rq_and_dlg_params(const struct dc *dc, struct dc_state *cont context->bw_ctx.bw.dcn.clk.dcfclk_deep_sleep_khz = (unsigned int)in_ctx->v20.dml_core_ctx.mp.DCFCLKDeepSleep * 1000; context->bw_ctx.bw.dcn.clk.dppclk_khz = 0; - if (in_ctx->v20.dml_core_ctx.ms.support.FCLKChangeSupport[in_ctx->v20.scratch.mode_support_params.out_lowest_state_idx] == dml_fclock_change_unsupported) + if (in_ctx->v20.dml_core_ctx.ms.support.FCLKChangeSupport[0] == dml_fclock_change_unsupported) context->bw_ctx.bw.dcn.clk.fclk_p_state_change_support = false; else context->bw_ctx.bw.dcn.clk.fclk_p_state_change_support = true; -- cgit From 230806dddc2601e58073740b74bf85a03d12ba53 Mon Sep 17 00:00:00 2001 From: Aric Cyr Date: Sun, 23 Jun 2024 16:45:28 -0400 Subject: drm/amd/display: 3.2.291 * FW Release 0.0.224.0 * Fix bw issue for dcn351 * Fix FAMS2 logic issue for dcn401 * Fix Coverity issues * Fix cursor issues * Refactor dio sources Acked-by: Rodrigo Siqueira Signed-off-by: Jerry Zuo Signed-off-by: Aric Cyr Tested-by: Daniel Wheeler Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/dc/dc.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/gpu/drm/amd/display/dc/dc.h b/drivers/gpu/drm/amd/display/dc/dc.h index 55b94a72ddc2..73cdebcd9f37 100644 --- a/drivers/gpu/drm/amd/display/dc/dc.h +++ b/drivers/gpu/drm/amd/display/dc/dc.h @@ -55,7 +55,7 @@ struct aux_payload; struct set_config_cmd_payload; struct dmub_notification; -#define DC_VER "3.2.290" +#define DC_VER "3.2.291" #define MAX_SURFACES 3 #define MAX_PLANES 6 -- cgit From 11317d2963fa79767cd7c6231a00a9d77f2e0f54 Mon Sep 17 00:00:00 2001 From: Marek Olšák Date: Sat, 1 Jun 2024 16:36:27 -0400 Subject: drm/amdgpu: check for LINEAR_ALIGNED correctly in check_tiling_flags_gfx6 MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Fix incorrect check. Signed-off-by: Marek Olšák Acked-by: Alex Deucher Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/amdgpu/amdgpu_display.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_display.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_display.c index cfec85563bc6..3c5fb907bdd9 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_display.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_display.c @@ -954,8 +954,7 @@ static int check_tiling_flags_gfx6(struct amdgpu_framebuffer *afb) { u64 micro_tile_mode; - /* Zero swizzle mode means linear */ - if (AMDGPU_TILING_GET(afb->tiling_flags, SWIZZLE_MODE) == 0) + if (AMDGPU_TILING_GET(afb->tiling_flags, ARRAY_MODE) == 1) /* LINEAR_ALIGNED */ return 0; micro_tile_mode = AMDGPU_TILING_GET(afb->tiling_flags, MICRO_TILE_MODE); -- cgit From b16ec6300fc5c74f12622fca7de0255f7016b675 Mon Sep 17 00:00:00 2001 From: Marek Olšák Date: Fri, 31 May 2024 19:38:18 -0400 Subject: drm/amdgpu/gfx11: remove superfluous cache flags MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit If any INV flags are needed, they should be executed via ACQUIRE_MEM before INDIRECT_BUFFER. Signed-off-by: Marek Olšák Acked-by: Christian König Acked-by: Alex Deucher Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/amdgpu/gfx_v11_0.c | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) diff --git a/drivers/gpu/drm/amd/amdgpu/gfx_v11_0.c b/drivers/gpu/drm/amd/amdgpu/gfx_v11_0.c index 5c17409439f8..0d078d0db162 100644 --- a/drivers/gpu/drm/amd/amdgpu/gfx_v11_0.c +++ b/drivers/gpu/drm/amd/amdgpu/gfx_v11_0.c @@ -5604,11 +5604,7 @@ static void gfx_v11_0_ring_emit_fence(struct amdgpu_ring *ring, u64 addr, amdgpu_ring_write(ring, PACKET3(PACKET3_RELEASE_MEM, 6)); amdgpu_ring_write(ring, (PACKET3_RELEASE_MEM_GCR_SEQ | PACKET3_RELEASE_MEM_GCR_GL2_WB | - PACKET3_RELEASE_MEM_GCR_GL2_INV | - PACKET3_RELEASE_MEM_GCR_GL2_US | - PACKET3_RELEASE_MEM_GCR_GL1_INV | - PACKET3_RELEASE_MEM_GCR_GLV_INV | - PACKET3_RELEASE_MEM_GCR_GLM_INV | + PACKET3_RELEASE_MEM_GCR_GLM_INV | /* must be set with GLM_WB */ PACKET3_RELEASE_MEM_GCR_GLM_WB | PACKET3_RELEASE_MEM_CACHE_POLICY(3) | PACKET3_RELEASE_MEM_EVENT_TYPE(CACHE_FLUSH_AND_INV_TS_EVENT) | -- cgit From e5f6bfe4025f881c17ae1829d76b19efcb353c81 Mon Sep 17 00:00:00 2001 From: Marek Olšák Date: Fri, 31 May 2024 19:38:18 -0400 Subject: drm/amdgpu/gfx12: remove superfluous cache flags MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit If any INV flags are needed, they should be executed via ACQUIRE_MEM before INDIRECT_BUFFER. GLM flags are also removed because the hw ignores them. Signed-off-by: Marek Olšák Acked-by: Christian König Acked-by: Alex Deucher Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/amdgpu/gfx_v12_0.c | 6 ------ 1 file changed, 6 deletions(-) diff --git a/drivers/gpu/drm/amd/amdgpu/gfx_v12_0.c b/drivers/gpu/drm/amd/amdgpu/gfx_v12_0.c index e9559bdd8264..a638696b2142 100644 --- a/drivers/gpu/drm/amd/amdgpu/gfx_v12_0.c +++ b/drivers/gpu/drm/amd/amdgpu/gfx_v12_0.c @@ -4144,12 +4144,6 @@ static void gfx_v12_0_ring_emit_fence(struct amdgpu_ring *ring, u64 addr, amdgpu_ring_write(ring, PACKET3(PACKET3_RELEASE_MEM, 6)); amdgpu_ring_write(ring, (PACKET3_RELEASE_MEM_GCR_SEQ | PACKET3_RELEASE_MEM_GCR_GL2_WB | - PACKET3_RELEASE_MEM_GCR_GL2_INV | - PACKET3_RELEASE_MEM_GCR_GL2_US | - PACKET3_RELEASE_MEM_GCR_GL1_INV | - PACKET3_RELEASE_MEM_GCR_GLV_INV | - PACKET3_RELEASE_MEM_GCR_GLM_INV | - PACKET3_RELEASE_MEM_GCR_GLM_WB | PACKET3_RELEASE_MEM_CACHE_POLICY(3) | PACKET3_RELEASE_MEM_EVENT_TYPE(CACHE_FLUSH_AND_INV_TS_EVENT) | PACKET3_RELEASE_MEM_EVENT_INDEX(5))); -- cgit From 30fb9cad6fbbd9d23d2d0ff7be8c59ce39b882bc Mon Sep 17 00:00:00 2001 From: Marek Olšák Date: Fri, 31 May 2024 19:48:05 -0400 Subject: drm/amdgpu/gfx12: remove GDS leftovers MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit GDS doesn't exist in gfx12. The incomplete packet allows userspace to hang the hw from the kernel. Signed-off-by: Marek Olšák Acked-by: Christian König Acked-by: Alex Deucher Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/amdgpu/gfx_v12_0.c | 16 ---------------- 1 file changed, 16 deletions(-) diff --git a/drivers/gpu/drm/amd/amdgpu/gfx_v12_0.c b/drivers/gpu/drm/amd/amdgpu/gfx_v12_0.c index a638696b2142..ccb26f78252a 100644 --- a/drivers/gpu/drm/amd/amdgpu/gfx_v12_0.c +++ b/drivers/gpu/drm/amd/amdgpu/gfx_v12_0.c @@ -4108,21 +4108,6 @@ static void gfx_v12_0_ring_emit_ib_compute(struct amdgpu_ring *ring, /* inherit vmid from mqd */ control |= 0x40000000; - /* Currently, there is a high possibility to get wave ID mismatch - * between ME and GDS, leading to a hw deadlock, because ME generates - * different wave IDs than the GDS expects. This situation happens - * randomly when at least 5 compute pipes use GDS ordered append. - * The wave IDs generated by ME are also wrong after suspend/resume. - * Those are probably bugs somewhere else in the kernel driver. - * - * Writing GDS_COMPUTE_MAX_WAVE_ID resets wave ID counters in ME and - * GDS to 0 for this ring (me/pipe). - */ - if (ib->flags & AMDGPU_IB_FLAG_RESET_GDS_MAX_WAVE_ID) { - amdgpu_ring_write(ring, PACKET3(PACKET3_SET_CONFIG_REG, 1)); - amdgpu_ring_write(ring, regGDS_COMPUTE_MAX_WAVE_ID); - } - amdgpu_ring_write(ring, PACKET3(PACKET3_INDIRECT_BUFFER, 2)); BUG_ON(ib->gpu_addr & 0x3); /* Dword align */ amdgpu_ring_write(ring, @@ -4721,7 +4706,6 @@ static const struct amdgpu_ring_funcs gfx_v12_0_ring_funcs_gfx = { SOC15_FLUSH_GPU_TLB_NUM_REG_WAIT * 7 + 2 + /* VM_FLUSH */ 8 + /* FENCE for VM_FLUSH */ - 20 + /* GDS switch */ 5 + /* COND_EXEC */ 7 + /* HDP_flush */ 4 + /* VGT_flush */ -- cgit From 8d9ffd15ff5c9da7bc6171f2536aaaff40bcab6e Mon Sep 17 00:00:00 2001 From: Marek Olšák Date: Sat, 1 Jun 2024 14:56:16 -0400 Subject: drm/amdgpu: remove AMD_FMT_MOD_GFX12_DCC_MAX_COMPRESSED_BLOCK_* definitions MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit They were added accidentally. Signed-off-by: Marek Olšák Acked-by: Alex Deucher Reviewed-by: Aurabindo Pillai Signed-off-by: Alex Deucher --- include/uapi/drm/drm_fourcc.h | 3 --- 1 file changed, 3 deletions(-) diff --git a/include/uapi/drm/drm_fourcc.h b/include/uapi/drm/drm_fourcc.h index d0063ac6e09f..4168445fbb8b 100644 --- a/include/uapi/drm/drm_fourcc.h +++ b/include/uapi/drm/drm_fourcc.h @@ -1540,9 +1540,6 @@ drm_fourcc_canonicalize_nvidia_format_mod(__u64 modifier) #define AMD_FMT_MOD_DCC_MAX_COMPRESSED_BLOCK_SHIFT 18 #define AMD_FMT_MOD_DCC_MAX_COMPRESSED_BLOCK_MASK 0x3 -#define AMD_FMT_MOD_GFX12_DCC_MAX_COMPRESSED_BLOCK_SHIFT 3 -#define AMD_FMT_MOD_GFX12_DCC_MAX_COMPRESSED_BLOCK_MASK 0x3 /* 0:64B, 1:128B, 2:256B */ - /* * DCC supports embedding some clear colors directly in the DCC surface. * However, on older GPUs the rendering HW ignores the embedded clear color -- cgit From f21373802da4e8c4fcf8acab60d98af307294b87 Mon Sep 17 00:00:00 2001 From: Marek Olšák Date: Sat, 1 Jun 2024 14:36:41 -0400 Subject: drm/amdgpu/display: handle gfx12 in dm_check_cursor_fb MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Checking SWIZZLE_MODE has undefined behavior on gfx12. Signed-off-by: Marek Olšák Acked-by: Alex Deucher Reviewed-by: Aurabindo Pillai Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) 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 f83ef3e1554c..98cf523a629e 100644 --- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c +++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c @@ -10667,12 +10667,14 @@ static int dm_check_cursor_fb(struct amdgpu_crtc *new_acrtc, * check tiling flags when the FB doesn't have a modifier. */ if (!(fb->flags & DRM_MODE_FB_MODIFIERS)) { - if (adev->family < AMDGPU_FAMILY_AI) { + if (adev->family >= AMDGPU_FAMILY_GC_12_0_0) { + linear = AMDGPU_TILING_GET(afb->tiling_flags, GFX12_SWIZZLE_MODE) == 0; + } else if (adev->family >= AMDGPU_FAMILY_AI) { + linear = AMDGPU_TILING_GET(afb->tiling_flags, SWIZZLE_MODE) == 0; + } else { linear = AMDGPU_TILING_GET(afb->tiling_flags, ARRAY_MODE) != DC_ARRAY_2D_TILED_THIN1 && AMDGPU_TILING_GET(afb->tiling_flags, ARRAY_MODE) != DC_ARRAY_1D_TILED_THIN1 && AMDGPU_TILING_GET(afb->tiling_flags, MICRO_TILE_MODE) == 0; - } else { - linear = AMDGPU_TILING_GET(afb->tiling_flags, SWIZZLE_MODE) == 0; } if (!linear) { DRM_DEBUG_ATOMIC("Cursor FB not linear"); -- cgit From fd536d2e12d6fd8e6b199c343aa6475fa969ed99 Mon Sep 17 00:00:00 2001 From: Marek Olšák Date: Sat, 1 Jun 2024 17:25:51 -0400 Subject: drm/amdgpu: don't use amdgpu_lookup_format_info on gfx12 MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit It only uses fields for GFX9-11 related to the separate DCC buffer, which doesn't exist in GFX12. Signed-off-by: Marek Olšák Acked-by: Alex Deucher Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/amdgpu/amdgpu_display.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_display.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_display.c index 3c5fb907bdd9..b69a4e1b864b 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_display.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_display.c @@ -654,6 +654,10 @@ amdgpu_lookup_format_info(u32 format, uint64_t modifier) if (!IS_AMD_FMT_MOD(modifier)) return NULL; + if (AMD_FMT_MOD_GET(TILE_VERSION, modifier) < AMD_FMT_MOD_TILE_VER_GFX9 || + AMD_FMT_MOD_GET(TILE_VERSION, modifier) >= AMD_FMT_MOD_TILE_VER_GFX12) + return NULL; + if (AMD_FMT_MOD_GET(DCC_RETILE, modifier)) return lookup_format_info(dcc_retile_formats, ARRAY_SIZE(dcc_retile_formats), -- cgit From c2fad7317441be573175c4d98b28347ddec7fe77 Mon Sep 17 00:00:00 2001 From: Hawking Zhang Date: Fri, 28 Jun 2024 16:47:36 +0800 Subject: drm/amdgpu: Correct register used to clear fault status Driver should write to fault_cntl registers to do one-shot address/status clear. Signed-off-by: Hawking Zhang Reviewed-by: Tao Zhou Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/amdgpu/mmhub_v1_8.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/gpu/drm/amd/amdgpu/mmhub_v1_8.c b/drivers/gpu/drm/amd/amdgpu/mmhub_v1_8.c index 8d7267a013d2..621761a17ac7 100644 --- a/drivers/gpu/drm/amd/amdgpu/mmhub_v1_8.c +++ b/drivers/gpu/drm/amd/amdgpu/mmhub_v1_8.c @@ -569,7 +569,7 @@ static bool mmhub_v1_8_query_utcl2_poison_status(struct amdgpu_device *adev, if (!amdgpu_sriov_vf(adev)) { /* clear page fault status and address */ WREG32_P(SOC15_REG_OFFSET(MMHUB, hub_inst, - regVM_L2_PROTECTION_FAULT_STATUS), 1, ~1); + regVM_L2_PROTECTION_FAULT_CNTL), 1, ~1); } return fed; -- cgit From 8dd1426e2c80e32ac1995007330c8f95ffa28ebb Mon Sep 17 00:00:00 2001 From: Marek Olšák Date: Sat, 1 Jun 2024 19:53:01 -0400 Subject: drm/amdgpu: handle gfx12 in amdgpu_display_verify_sizes MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit It verified GFX9-11 swizzle modes on GFX12, which has undefined behavior. Signed-off-by: Marek Olšák Acked-by: Alex Deucher Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/amdgpu/amdgpu_display.c | 27 ++++++++++++++++++++++++++- include/uapi/drm/drm_fourcc.h | 2 ++ 2 files changed, 28 insertions(+), 1 deletion(-) diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_display.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_display.c index b69a4e1b864b..3bb4ca9b8a40 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_display.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_display.c @@ -1082,6 +1082,30 @@ static int amdgpu_display_verify_sizes(struct amdgpu_framebuffer *rfb) block_width = 256 / format_info->cpp[i]; block_height = 1; block_size_log2 = 8; + } else if (AMD_FMT_MOD_GET(TILE_VERSION, modifier) >= AMD_FMT_MOD_TILE_VER_GFX12) { + int swizzle = AMD_FMT_MOD_GET(TILE, modifier); + + switch (swizzle) { + case AMD_FMT_MOD_TILE_GFX12_256B_2D: + block_size_log2 = 8; + break; + case AMD_FMT_MOD_TILE_GFX12_4K_2D: + block_size_log2 = 12; + break; + case AMD_FMT_MOD_TILE_GFX12_64K_2D: + block_size_log2 = 16; + break; + case AMD_FMT_MOD_TILE_GFX12_256K_2D: + block_size_log2 = 18; + break; + default: + drm_dbg_kms(rfb->base.dev, + "Gfx12 swizzle mode with unknown block size: %d\n", swizzle); + return -EINVAL; + } + + get_block_dimensions(block_size_log2, format_info->cpp[i], + &block_width, &block_height); } else { int swizzle = AMD_FMT_MOD_GET(TILE, modifier); @@ -1117,7 +1141,8 @@ static int amdgpu_display_verify_sizes(struct amdgpu_framebuffer *rfb) return ret; } - if (AMD_FMT_MOD_GET(DCC, modifier)) { + if (AMD_FMT_MOD_GET(TILE_VERSION, modifier) <= AMD_FMT_MOD_TILE_VER_GFX11 && + AMD_FMT_MOD_GET(DCC, modifier)) { if (AMD_FMT_MOD_GET(DCC_RETILE, modifier)) { block_size_log2 = get_dcc_block_size(modifier, false, false); get_block_dimensions(block_size_log2 + 8, format_info->cpp[0], diff --git a/include/uapi/drm/drm_fourcc.h b/include/uapi/drm/drm_fourcc.h index 4168445fbb8b..2d84a8052b15 100644 --- a/include/uapi/drm/drm_fourcc.h +++ b/include/uapi/drm/drm_fourcc.h @@ -1506,6 +1506,8 @@ drm_fourcc_canonicalize_nvidia_format_mod(__u64 modifier) * 6 - 64KB_3D * 7 - 256KB_3D */ +#define AMD_FMT_MOD_TILE_GFX12_256B_2D 1 +#define AMD_FMT_MOD_TILE_GFX12_4K_2D 2 #define AMD_FMT_MOD_TILE_GFX12_64K_2D 3 #define AMD_FMT_MOD_TILE_GFX12_256K_2D 4 -- cgit From ed17b63e7e25f03b40db66a8d5802b89aac40441 Mon Sep 17 00:00:00 2001 From: Marek Olšák Date: Sat, 1 Jun 2024 19:59:34 -0400 Subject: drm/amdgpu/display: handle gfx12 in amdgpu_dm_plane_format_mod_supported MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit All this code has undefined behavior on GFX12 and shouldn't be executed. Signed-off-by: Marek Olšák Acked-by: Alex Deucher Reviewed-by: Aurabindo Pillai Signed-off-by: Alex Deucher --- .../drm/amd/display/amdgpu_dm/amdgpu_dm_plane.c | 47 ++++++++++++---------- 1 file changed, 25 insertions(+), 22 deletions(-) diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_plane.c b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_plane.c index bb534b2b0b71..5a6a21e28548 100644 --- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_plane.c +++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_plane.c @@ -1419,8 +1419,6 @@ static bool amdgpu_dm_plane_format_mod_supported(struct drm_plane *plane, const struct drm_format_info *info = drm_format_info(format); int i; - enum dm_micro_swizzle microtile = amdgpu_dm_plane_modifier_gfx9_swizzle_mode(modifier) & 3; - if (!info) return false; @@ -1442,29 +1440,34 @@ static bool amdgpu_dm_plane_format_mod_supported(struct drm_plane *plane, if (i == plane->modifier_count) return false; - /* - * For D swizzle the canonical modifier depends on the bpp, so check - * it here. - */ - if (AMD_FMT_MOD_GET(TILE_VERSION, modifier) == AMD_FMT_MOD_TILE_VER_GFX9 && - adev->family >= AMDGPU_FAMILY_NV) { - if (microtile == MICRO_SWIZZLE_D && info->cpp[0] == 4) - return false; - } - - if (adev->family >= AMDGPU_FAMILY_RV && microtile == MICRO_SWIZZLE_D && - info->cpp[0] < 8) - return false; + /* GFX12 doesn't have these limitations. */ + if (AMD_FMT_MOD_GET(TILE_VERSION, modifier) <= AMD_FMT_MOD_TILE_VER_GFX11) { + enum dm_micro_swizzle microtile = amdgpu_dm_plane_modifier_gfx9_swizzle_mode(modifier) & 3; - if (amdgpu_dm_plane_modifier_has_dcc(modifier)) { - /* Per radeonsi comments 16/64 bpp are more complicated. */ - if (info->cpp[0] != 4) - return false; - /* We support multi-planar formats, but not when combined with - * additional DCC metadata planes. + /* + * For D swizzle the canonical modifier depends on the bpp, so check + * it here. */ - if (info->num_planes > 1) + if (AMD_FMT_MOD_GET(TILE_VERSION, modifier) == AMD_FMT_MOD_TILE_VER_GFX9 && + adev->family >= AMDGPU_FAMILY_NV) { + if (microtile == MICRO_SWIZZLE_D && info->cpp[0] == 4) + return false; + } + + if (adev->family >= AMDGPU_FAMILY_RV && microtile == MICRO_SWIZZLE_D && + info->cpp[0] < 8) return false; + + if (amdgpu_dm_plane_modifier_has_dcc(modifier)) { + /* Per radeonsi comments 16/64 bpp are more complicated. */ + if (info->cpp[0] != 4) + return false; + /* We support multi-planar formats, but not when combined with + * additional DCC metadata planes. + */ + if (info->num_planes > 1) + return false; + } } return true; -- cgit From ce7985fd94a0eff154e13913e4ca553aa09e1097 Mon Sep 17 00:00:00 2001 From: Marek Olšák Date: Sat, 1 Jun 2024 16:37:22 -0400 Subject: drm/amdgpu/display: set plane attributes for gfx12 correctly MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit It used gfx9 flags, which has undefined behavior on gfx12. Signed-off-by: Marek Olšák Acked-by: Alex Deucher Reviewed-by: Aurabindo Pillai Signed-off-by: Alex Deucher --- .../drm/amd/display/amdgpu_dm/amdgpu_dm_plane.c | 50 +++++++++++++++++++++- 1 file changed, 49 insertions(+), 1 deletion(-) diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_plane.c b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_plane.c index 5a6a21e28548..e13938e01b70 100644 --- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_plane.c +++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_plane.c @@ -352,6 +352,46 @@ static int amdgpu_dm_plane_fill_gfx9_plane_attributes_from_modifiers(struct amdg return ret; } +static int amdgpu_dm_plane_fill_gfx12_plane_attributes_from_modifiers(struct amdgpu_device *adev, + const struct amdgpu_framebuffer *afb, + const enum surface_pixel_format format, + const enum dc_rotation_angle rotation, + const struct plane_size *plane_size, + union dc_tiling_info *tiling_info, + struct dc_plane_dcc_param *dcc, + struct dc_plane_address *address, + const bool force_disable_dcc) +{ + const uint64_t modifier = afb->base.modifier; + int ret = 0; + + /* TODO: Most of this function shouldn't be needed on GFX12. */ + amdgpu_dm_plane_fill_gfx9_tiling_info_from_device(adev, tiling_info); + + tiling_info->gfx9.swizzle = amdgpu_dm_plane_modifier_gfx9_swizzle_mode(modifier); + + if (amdgpu_dm_plane_modifier_has_dcc(modifier) && !force_disable_dcc) { + int max_compressed_block = AMD_FMT_MOD_GET(DCC_MAX_COMPRESSED_BLOCK, modifier); + + dcc->enable = 1; + dcc->independent_64b_blks = max_compressed_block == 0; + + if (max_compressed_block == 0) + dcc->dcc_ind_blk = hubp_ind_block_64b; + else if (max_compressed_block == 1) + dcc->dcc_ind_blk = hubp_ind_block_128b; + else + dcc->dcc_ind_blk = hubp_ind_block_unconstrained; + } + + /* TODO: This seems wrong because there is no DCC plane on GFX12. */ + ret = amdgpu_dm_plane_validate_dcc(adev, format, rotation, tiling_info, dcc, address, plane_size); + if (ret) + drm_dbg_kms(adev_to_drm(adev), "amdgpu_dm_plane_validate_dcc: returned error: %d\n", ret); + + return ret; +} + static void amdgpu_dm_plane_add_gfx10_1_modifiers(const struct amdgpu_device *adev, uint64_t **mods, uint64_t *size, @@ -835,7 +875,15 @@ int amdgpu_dm_plane_fill_plane_buffer_attributes(struct amdgpu_device *adev, upper_32_bits(chroma_addr); } - if (adev->family >= AMDGPU_FAMILY_AI) { + if (adev->family >= AMDGPU_FAMILY_GC_12_0_0) { + ret = amdgpu_dm_plane_fill_gfx12_plane_attributes_from_modifiers(adev, afb, format, + rotation, plane_size, + tiling_info, dcc, + address, + force_disable_dcc); + if (ret) + return ret; + } else if (adev->family >= AMDGPU_FAMILY_AI) { ret = amdgpu_dm_plane_fill_gfx9_plane_attributes_from_modifiers(adev, afb, format, rotation, plane_size, tiling_info, dcc, -- cgit From cc6e00a6c4f6504b61a11154f15140cf85b5980d Mon Sep 17 00:00:00 2001 From: Marek Olšák Date: Wed, 26 Jun 2024 14:01:33 -0400 Subject: drm/amdgpu/display: add all gfx12 modifiers MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Marek Olšák Acked-by: Alex Deucher Reviewed-by: Aurabindo Pillai Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_plane.c | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_plane.c b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_plane.c index e13938e01b70..0320200dae94 100644 --- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_plane.c +++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_plane.c @@ -688,12 +688,13 @@ static void amdgpu_dm_plane_add_gfx11_modifiers(struct amdgpu_device *adev, static void amdgpu_dm_plane_add_gfx12_modifiers(struct amdgpu_device *adev, uint64_t **mods, uint64_t *size, uint64_t *capacity) { - uint64_t mod_64K_2D = AMD_FMT_MOD | - AMD_FMT_MOD_SET(TILE_VERSION, AMD_FMT_MOD_TILE_VER_GFX12) | - AMD_FMT_MOD_SET(TILE, AMD_FMT_MOD_TILE_GFX12_64K_2D); + uint64_t ver = AMD_FMT_MOD | AMD_FMT_MOD_SET(TILE_VERSION, AMD_FMT_MOD_TILE_VER_GFX12); - /* 64K without DCC */ - amdgpu_dm_plane_add_modifier(mods, size, capacity, mod_64K_2D); + /* Without DCC: */ + amdgpu_dm_plane_add_modifier(mods, size, capacity, ver | AMD_FMT_MOD_SET(TILE, AMD_FMT_MOD_TILE_GFX12_256K_2D)); + amdgpu_dm_plane_add_modifier(mods, size, capacity, ver | AMD_FMT_MOD_SET(TILE, AMD_FMT_MOD_TILE_GFX12_64K_2D)); + amdgpu_dm_plane_add_modifier(mods, size, capacity, ver | AMD_FMT_MOD_SET(TILE, AMD_FMT_MOD_TILE_GFX12_4K_2D)); + amdgpu_dm_plane_add_modifier(mods, size, capacity, ver | AMD_FMT_MOD_SET(TILE, AMD_FMT_MOD_TILE_GFX12_256B_2D)); amdgpu_dm_plane_add_modifier(mods, size, capacity, DRM_FORMAT_MOD_LINEAR); } -- cgit From 0d3157d04d9cafd54f32b68366f0fa227076aa0d Mon Sep 17 00:00:00 2001 From: Marek Olšák Date: Sat, 1 Jun 2024 15:05:20 -0400 Subject: drm/amdgpu: add amdgpu_framebuffer::gfx12_dcc MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit amdgpu_framebuffer doesn't have tiling_flags, so we need this. amdgpu_display_get_fb_info never gets NULL parameters, so checking for NULL was useless. Signed-off-by: Marek Olšák Acked-by: Alex Deucher Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/amdgpu/amdgpu_display.c | 15 ++++++++------- drivers/gpu/drm/amd/amdgpu/amdgpu_mode.h | 1 + 2 files changed, 9 insertions(+), 7 deletions(-) diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_display.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_display.c index 3bb4ca9b8a40..ec0299c5918e 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_display.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_display.c @@ -1172,7 +1172,8 @@ static int amdgpu_display_verify_sizes(struct amdgpu_framebuffer *rfb) } static int amdgpu_display_get_fb_info(const struct amdgpu_framebuffer *amdgpu_fb, - uint64_t *tiling_flags, bool *tmz_surface) + uint64_t *tiling_flags, bool *tmz_surface, + bool *gfx12_dcc) { struct amdgpu_bo *rbo; int r; @@ -1180,6 +1181,7 @@ static int amdgpu_display_get_fb_info(const struct amdgpu_framebuffer *amdgpu_fb if (!amdgpu_fb) { *tiling_flags = 0; *tmz_surface = false; + *gfx12_dcc = false; return 0; } @@ -1193,11 +1195,9 @@ static int amdgpu_display_get_fb_info(const struct amdgpu_framebuffer *amdgpu_fb return r; } - if (tiling_flags) - amdgpu_bo_get_tiling_flags(rbo, tiling_flags); - - if (tmz_surface) - *tmz_surface = amdgpu_bo_encrypted(rbo); + amdgpu_bo_get_tiling_flags(rbo, tiling_flags); + *tmz_surface = amdgpu_bo_encrypted(rbo); + *gfx12_dcc = rbo->flags & AMDGPU_GEM_CREATE_GFX12_DCC; amdgpu_bo_unreserve(rbo); @@ -1266,7 +1266,8 @@ static int amdgpu_display_framebuffer_init(struct drm_device *dev, } } - ret = amdgpu_display_get_fb_info(rfb, &rfb->tiling_flags, &rfb->tmz_surface); + ret = amdgpu_display_get_fb_info(rfb, &rfb->tiling_flags, &rfb->tmz_surface, + &rfb->gfx12_dcc); if (ret) return ret; diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_mode.h b/drivers/gpu/drm/amd/amdgpu/amdgpu_mode.h index 1fe21a70ddd0..d002b845d8ac 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_mode.h +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_mode.h @@ -300,6 +300,7 @@ struct amdgpu_framebuffer { uint64_t tiling_flags; bool tmz_surface; + bool gfx12_dcc; /* caching for later use */ uint64_t address; -- cgit From d3dbccacfd2d47a73e2bb6f9be45a116de94cef3 Mon Sep 17 00:00:00 2001 From: Hawking Zhang Date: Fri, 28 Jun 2024 16:50:56 +0800 Subject: drm/amdgpu: Fix hbm stack id in boot error report To align with firmware, hbm id field 0x1 refers to hbm stack 0, 0x2 refers to hbm statck 1. Signed-off-by: Hawking Zhang Reviewed-by: Tao Zhou Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/amdgpu/amdgpu_ras.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_ras.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_ras.c index 4edd8e333d36..6d1f974e2987 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_ras.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_ras.c @@ -4565,7 +4565,7 @@ static void amdgpu_ras_boot_time_error_reporting(struct amdgpu_device *adev, socket_id = AMDGPU_RAS_GPU_ERR_SOCKET_ID(boot_error); aid_id = AMDGPU_RAS_GPU_ERR_AID_ID(boot_error); - hbm_id = AMDGPU_RAS_GPU_ERR_HBM_ID(boot_error); + hbm_id = ((1 == AMDGPU_RAS_GPU_ERR_HBM_ID(boot_error)) ? 0 : 1); if (AMDGPU_RAS_GPU_ERR_MEM_TRAINING(boot_error)) dev_info(adev->dev, -- cgit From 62ec7d38b769ccf33b1080e69c2ae5b7344d116d Mon Sep 17 00:00:00 2001 From: Lijo Lazar Date: Mon, 24 Jun 2024 13:33:16 +0530 Subject: drm/amdkfd: Use device based logging for errors Convert some pr_* to some dev_* APIs to identify the device. Signed-off-by: Lijo Lazar Reviewed-by: Alex Deucher Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/amdkfd/kfd_flat_memory.c | 3 +- drivers/gpu/drm/amd/amdkfd/kfd_kernel_queue.c | 21 +++++---- drivers/gpu/drm/amd/amdkfd/kfd_mqd_manager.c | 8 ++-- drivers/gpu/drm/amd/amdkfd/kfd_packet_manager.c | 63 ++++++++++++++++--------- drivers/gpu/drm/amd/amdkfd/kfd_process.c | 24 ++++++---- 5 files changed, 74 insertions(+), 45 deletions(-) diff --git a/drivers/gpu/drm/amd/amdkfd/kfd_flat_memory.c b/drivers/gpu/drm/amd/amdkfd/kfd_flat_memory.c index 4a64307bc438..dbcb60eb54b2 100644 --- a/drivers/gpu/drm/amd/amdkfd/kfd_flat_memory.c +++ b/drivers/gpu/drm/amd/amdkfd/kfd_flat_memory.c @@ -380,7 +380,8 @@ int kfd_init_apertures(struct kfd_process *process) pdd = kfd_create_process_device_data(dev, process); if (!pdd) { - pr_err("Failed to create process device data\n"); + dev_err(dev->adev->dev, + "Failed to create process device data\n"); return -ENOMEM; } /* diff --git a/drivers/gpu/drm/amd/amdkfd/kfd_kernel_queue.c b/drivers/gpu/drm/amd/amdkfd/kfd_kernel_queue.c index 3ea75a9d86ec..4843dcb9a5f7 100644 --- a/drivers/gpu/drm/amd/amdkfd/kfd_kernel_queue.c +++ b/drivers/gpu/drm/amd/amdkfd/kfd_kernel_queue.c @@ -69,7 +69,7 @@ static bool kq_initialize(struct kernel_queue *kq, struct kfd_node *dev, kq->mqd_mgr = dev->dqm->mqd_mgrs[KFD_MQD_TYPE_HIQ]; break; default: - pr_err("Invalid queue type %d\n", type); + dev_err(dev->adev->dev, "Invalid queue type %d\n", type); return false; } @@ -79,13 +79,14 @@ static bool kq_initialize(struct kernel_queue *kq, struct kfd_node *dev, prop.doorbell_ptr = kfd_get_kernel_doorbell(dev->kfd, &prop.doorbell_off); if (!prop.doorbell_ptr) { - pr_err("Failed to initialize doorbell"); + dev_err(dev->adev->dev, "Failed to initialize doorbell"); goto err_get_kernel_doorbell; } retval = kfd_gtt_sa_allocate(dev, queue_size, &kq->pq); if (retval != 0) { - pr_err("Failed to init pq queues size %d\n", queue_size); + dev_err(dev->adev->dev, "Failed to init pq queues size %d\n", + queue_size); goto err_pq_allocate_vidmem; } @@ -341,7 +342,7 @@ struct kernel_queue *kernel_queue_init(struct kfd_node *dev, if (kq_initialize(kq, dev, type, KFD_KERNEL_QUEUE_SIZE)) return kq; - pr_err("Failed to init kernel queue\n"); + dev_err(dev->adev->dev, "Failed to init kernel queue\n"); kfree(kq); return NULL; @@ -360,26 +361,26 @@ static __attribute__((unused)) void test_kq(struct kfd_node *dev) uint32_t *buffer, i; int retval; - pr_err("Starting kernel queue test\n"); + dev_err(dev->adev->dev, "Starting kernel queue test\n"); kq = kernel_queue_init(dev, KFD_QUEUE_TYPE_HIQ); if (unlikely(!kq)) { - pr_err(" Failed to initialize HIQ\n"); - pr_err("Kernel queue test failed\n"); + dev_err(dev->adev->dev, " Failed to initialize HIQ\n"); + dev_err(dev->adev->dev, "Kernel queue test failed\n"); return; } retval = kq_acquire_packet_buffer(kq, 5, &buffer); if (unlikely(retval != 0)) { - pr_err(" Failed to acquire packet buffer\n"); - pr_err("Kernel queue test failed\n"); + dev_err(dev->adev->dev, " Failed to acquire packet buffer\n"); + dev_err(dev->adev->dev, "Kernel queue test failed\n"); return; } for (i = 0; i < 5; i++) buffer[i] = kq->nop_packet; kq_submit_packet(kq); - pr_err("Ending kernel queue test\n"); + dev_err(dev->adev->dev, "Ending kernel queue test\n"); } diff --git a/drivers/gpu/drm/amd/amdkfd/kfd_mqd_manager.c b/drivers/gpu/drm/amd/amdkfd/kfd_mqd_manager.c index ccfa5a0a8f6b..50a81da43ce1 100644 --- a/drivers/gpu/drm/amd/amdkfd/kfd_mqd_manager.c +++ b/drivers/gpu/drm/amd/amdkfd/kfd_mqd_manager.c @@ -118,12 +118,14 @@ void mqd_symmetrically_map_cu_mask(struct mqd_manager *mm, * attention grabbing. */ if (gfx_info->max_shader_engines > KFD_MAX_NUM_SE) { - pr_err("Exceeded KFD_MAX_NUM_SE, chip reports %d\n", - gfx_info->max_shader_engines); + dev_err(mm->dev->adev->dev, + "Exceeded KFD_MAX_NUM_SE, chip reports %d\n", + gfx_info->max_shader_engines); return; } if (gfx_info->max_sh_per_se > KFD_MAX_NUM_SH_PER_SE) { - pr_err("Exceeded KFD_MAX_NUM_SH, chip reports %d\n", + dev_err(mm->dev->adev->dev, + "Exceeded KFD_MAX_NUM_SH, chip reports %d\n", gfx_info->max_sh_per_se * gfx_info->max_shader_engines); return; } diff --git a/drivers/gpu/drm/amd/amdkfd/kfd_packet_manager.c b/drivers/gpu/drm/amd/amdkfd/kfd_packet_manager.c index a05d5c1097a8..37930629edc5 100644 --- a/drivers/gpu/drm/amd/amdkfd/kfd_packet_manager.c +++ b/drivers/gpu/drm/amd/amdkfd/kfd_packet_manager.c @@ -45,7 +45,8 @@ static void pm_calc_rlib_size(struct packet_manager *pm, unsigned int process_count, queue_count, compute_queue_count, gws_queue_count; unsigned int map_queue_size; unsigned int max_proc_per_quantum = 1; - struct kfd_node *dev = pm->dqm->dev; + struct kfd_node *node = pm->dqm->dev; + struct device *dev = node->adev->dev; process_count = pm->dqm->processes_count; queue_count = pm->dqm->active_queue_count; @@ -59,14 +60,14 @@ static void pm_calc_rlib_size(struct packet_manager *pm, */ *over_subscription = false; - if (dev->max_proc_per_quantum > 1) - max_proc_per_quantum = dev->max_proc_per_quantum; + if (node->max_proc_per_quantum > 1) + max_proc_per_quantum = node->max_proc_per_quantum; if ((process_count > max_proc_per_quantum) || compute_queue_count > get_cp_queues_num(pm->dqm) || gws_queue_count > 1) { *over_subscription = true; - pr_debug("Over subscribed runlist\n"); + dev_dbg(dev, "Over subscribed runlist\n"); } map_queue_size = pm->pmf->map_queues_size; @@ -81,7 +82,7 @@ static void pm_calc_rlib_size(struct packet_manager *pm, if (*over_subscription) *rlib_size += pm->pmf->runlist_size; - pr_debug("runlist ib size %d\n", *rlib_size); + dev_dbg(dev, "runlist ib size %d\n", *rlib_size); } static int pm_allocate_runlist_ib(struct packet_manager *pm, @@ -90,6 +91,8 @@ static int pm_allocate_runlist_ib(struct packet_manager *pm, unsigned int *rl_buffer_size, bool *is_over_subscription) { + struct kfd_node *node = pm->dqm->dev; + struct device *dev = node->adev->dev; int retval; if (WARN_ON(pm->allocated)) @@ -99,11 +102,10 @@ static int pm_allocate_runlist_ib(struct packet_manager *pm, mutex_lock(&pm->lock); - retval = kfd_gtt_sa_allocate(pm->dqm->dev, *rl_buffer_size, - &pm->ib_buffer_obj); + retval = kfd_gtt_sa_allocate(node, *rl_buffer_size, &pm->ib_buffer_obj); if (retval) { - pr_err("Failed to allocate runlist IB\n"); + dev_err(dev, "Failed to allocate runlist IB\n"); goto out; } @@ -125,6 +127,8 @@ static int pm_create_runlist_ib(struct packet_manager *pm, { unsigned int alloc_size_bytes; unsigned int *rl_buffer, rl_wptr, i; + struct kfd_node *node = pm->dqm->dev; + struct device *dev = node->adev->dev; int retval, processes_mapped; struct device_process_node *cur; struct qcm_process_device *qpd; @@ -142,7 +146,7 @@ static int pm_create_runlist_ib(struct packet_manager *pm, *rl_size_bytes = alloc_size_bytes; pm->ib_size_bytes = alloc_size_bytes; - pr_debug("Building runlist ib process count: %d queues count %d\n", + dev_dbg(dev, "Building runlist ib process count: %d queues count %d\n", pm->dqm->processes_count, pm->dqm->active_queue_count); /* build the run list ib packet */ @@ -150,7 +154,7 @@ static int pm_create_runlist_ib(struct packet_manager *pm, qpd = cur->qpd; /* build map process packet */ if (processes_mapped >= pm->dqm->processes_count) { - pr_debug("Not enough space left in runlist IB\n"); + dev_dbg(dev, "Not enough space left in runlist IB\n"); pm_release_ib(pm); return -ENOMEM; } @@ -167,7 +171,8 @@ static int pm_create_runlist_ib(struct packet_manager *pm, if (!kq->queue->properties.is_active) continue; - pr_debug("static_queue, mapping kernel q %d, is debug status %d\n", + dev_dbg(dev, + "static_queue, mapping kernel q %d, is debug status %d\n", kq->queue->queue, qpd->is_debug); retval = pm->pmf->map_queues(pm, @@ -186,7 +191,8 @@ static int pm_create_runlist_ib(struct packet_manager *pm, if (!q->properties.is_active) continue; - pr_debug("static_queue, mapping user queue %d, is debug status %d\n", + dev_dbg(dev, + "static_queue, mapping user queue %d, is debug status %d\n", q->queue, qpd->is_debug); retval = pm->pmf->map_queues(pm, @@ -203,11 +209,13 @@ static int pm_create_runlist_ib(struct packet_manager *pm, } } - pr_debug("Finished map process and queues to runlist\n"); + dev_dbg(dev, "Finished map process and queues to runlist\n"); if (is_over_subscription) { if (!pm->is_over_subscription) - pr_warn("Runlist is getting oversubscribed. Expect reduced ROCm performance.\n"); + dev_warn( + dev, + "Runlist is getting oversubscribed. Expect reduced ROCm performance.\n"); retval = pm->pmf->runlist(pm, &rl_buffer[rl_wptr], *rl_gpu_addr, alloc_size_bytes / sizeof(uint32_t), @@ -273,6 +281,8 @@ void pm_uninit(struct packet_manager *pm) int pm_send_set_resources(struct packet_manager *pm, struct scheduling_resources *res) { + struct kfd_node *node = pm->dqm->dev; + struct device *dev = node->adev->dev; uint32_t *buffer, size; int retval = 0; @@ -282,7 +292,7 @@ int pm_send_set_resources(struct packet_manager *pm, size / sizeof(uint32_t), (unsigned int **)&buffer); if (!buffer) { - pr_err("Failed to allocate buffer on kernel queue\n"); + dev_err(dev, "Failed to allocate buffer on kernel queue\n"); retval = -ENOMEM; goto out; } @@ -344,6 +354,8 @@ fail_create_runlist_ib: int pm_send_query_status(struct packet_manager *pm, uint64_t fence_address, uint64_t fence_value) { + struct kfd_node *node = pm->dqm->dev; + struct device *dev = node->adev->dev; uint32_t *buffer, size; int retval = 0; @@ -355,7 +367,7 @@ int pm_send_query_status(struct packet_manager *pm, uint64_t fence_address, kq_acquire_packet_buffer(pm->priv_queue, size / sizeof(uint32_t), (unsigned int **)&buffer); if (!buffer) { - pr_err("Failed to allocate buffer on kernel queue\n"); + dev_err(dev, "Failed to allocate buffer on kernel queue\n"); retval = -ENOMEM; goto out; } @@ -373,6 +385,8 @@ out: int pm_update_grace_period(struct packet_manager *pm, uint32_t grace_period) { + struct kfd_node *node = pm->dqm->dev; + struct device *dev = node->adev->dev; int retval = 0; uint32_t *buffer, size; @@ -386,7 +400,8 @@ int pm_update_grace_period(struct packet_manager *pm, uint32_t grace_period) (unsigned int **)&buffer); if (!buffer) { - pr_err("Failed to allocate buffer on kernel queue\n"); + dev_err(dev, + "Failed to allocate buffer on kernel queue\n"); retval = -ENOMEM; goto out; } @@ -407,6 +422,8 @@ int pm_send_unmap_queue(struct packet_manager *pm, enum kfd_unmap_queues_filter filter, uint32_t filter_param, bool reset) { + struct kfd_node *node = pm->dqm->dev; + struct device *dev = node->adev->dev; uint32_t *buffer, size; int retval = 0; @@ -415,7 +432,7 @@ int pm_send_unmap_queue(struct packet_manager *pm, kq_acquire_packet_buffer(pm->priv_queue, size / sizeof(uint32_t), (unsigned int **)&buffer); if (!buffer) { - pr_err("Failed to allocate buffer on kernel queue\n"); + dev_err(dev, "Failed to allocate buffer on kernel queue\n"); retval = -ENOMEM; goto out; } @@ -464,6 +481,8 @@ out: int pm_debugfs_hang_hws(struct packet_manager *pm) { + struct kfd_node *node = pm->dqm->dev; + struct device *dev = node->adev->dev; uint32_t *buffer, size; int r = 0; @@ -475,16 +494,16 @@ int pm_debugfs_hang_hws(struct packet_manager *pm) kq_acquire_packet_buffer(pm->priv_queue, size / sizeof(uint32_t), (unsigned int **)&buffer); if (!buffer) { - pr_err("Failed to allocate buffer on kernel queue\n"); + dev_err(dev, "Failed to allocate buffer on kernel queue\n"); r = -ENOMEM; goto out; } memset(buffer, 0x55, size); kq_submit_packet(pm->priv_queue); - pr_info("Submitting %x %x %x %x %x %x %x to HIQ to hang the HWS.", - buffer[0], buffer[1], buffer[2], buffer[3], - buffer[4], buffer[5], buffer[6]); + dev_info(dev, "Submitting %x %x %x %x %x %x %x to HIQ to hang the HWS.", + buffer[0], buffer[1], buffer[2], buffer[3], buffer[4], + buffer[5], buffer[6]); out: mutex_unlock(&pm->lock); return r; diff --git a/drivers/gpu/drm/amd/amdkfd/kfd_process.c b/drivers/gpu/drm/amd/amdkfd/kfd_process.c index 6251f37c312a..17e42161b015 100644 --- a/drivers/gpu/drm/amd/amdkfd/kfd_process.c +++ b/drivers/gpu/drm/amd/amdkfd/kfd_process.c @@ -1311,7 +1311,8 @@ int kfd_process_init_cwsr_apu(struct kfd_process *p, struct file *filep) if (IS_ERR_VALUE(qpd->tba_addr)) { int err = qpd->tba_addr; - pr_err("Failure to set tba address. error %d.\n", err); + dev_err(dev->adev->dev, + "Failure to set tba address. error %d.\n", err); qpd->tba_addr = 0; qpd->cwsr_kaddr = NULL; return err; @@ -1611,7 +1612,8 @@ struct kfd_process_device *kfd_create_process_device_data(struct kfd_node *dev, &pdd->proc_ctx_cpu_ptr, false); if (retval) { - pr_err("failed to allocate process context bo\n"); + dev_err(dev->adev->dev, + "failed to allocate process context bo\n"); goto err_free_pdd; } memset(pdd->proc_ctx_cpu_ptr, 0, AMDGPU_MES_PROC_CTX_SIZE); @@ -1676,7 +1678,7 @@ int kfd_process_device_init_vm(struct kfd_process_device *pdd, &p->kgd_process_info, &ef); if (ret) { - pr_err("Failed to create process VM object\n"); + dev_err(dev->adev->dev, "Failed to create process VM object\n"); return ret; } RCU_INIT_POINTER(p->ef, ef); @@ -1723,7 +1725,7 @@ struct kfd_process_device *kfd_bind_process_to_device(struct kfd_node *dev, pdd = kfd_get_process_device_data(dev, p); if (!pdd) { - pr_err("Process device data doesn't exist\n"); + dev_err(dev->adev->dev, "Process device data doesn't exist\n"); return ERR_PTR(-ENOMEM); } @@ -1833,6 +1835,7 @@ int kfd_process_evict_queues(struct kfd_process *p, uint32_t trigger) for (i = 0; i < p->n_pdds; i++) { struct kfd_process_device *pdd = p->pdds[i]; + struct device *dev = pdd->dev->adev->dev; kfd_smi_event_queue_eviction(pdd->dev, p->lead_thread->pid, trigger); @@ -1844,7 +1847,7 @@ int kfd_process_evict_queues(struct kfd_process *p, uint32_t trigger) * them been add back since they actually not be saved right now. */ if (r && r != -EIO) { - pr_err("Failed to evict process queues\n"); + dev_err(dev, "Failed to evict process queues\n"); goto fail; } n_evicted++; @@ -1866,7 +1869,8 @@ fail: if (pdd->dev->dqm->ops.restore_process_queues(pdd->dev->dqm, &pdd->qpd)) - pr_err("Failed to restore queues\n"); + dev_err(pdd->dev->adev->dev, + "Failed to restore queues\n"); n_evicted--; } @@ -1882,13 +1886,14 @@ int kfd_process_restore_queues(struct kfd_process *p) for (i = 0; i < p->n_pdds; i++) { struct kfd_process_device *pdd = p->pdds[i]; + struct device *dev = pdd->dev->adev->dev; kfd_smi_event_queue_restore(pdd->dev, p->lead_thread->pid); r = pdd->dev->dqm->ops.restore_process_queues(pdd->dev->dqm, &pdd->qpd); if (r) { - pr_err("Failed to restore process queues\n"); + dev_err(dev, "Failed to restore process queues\n"); if (!ret) ret = r; } @@ -2065,7 +2070,7 @@ int kfd_reserved_mem_mmap(struct kfd_node *dev, struct kfd_process *process, struct qcm_process_device *qpd; if ((vma->vm_end - vma->vm_start) != KFD_CWSR_TBA_TMA_SIZE) { - pr_err("Incorrect CWSR mapping size.\n"); + dev_err(dev->adev->dev, "Incorrect CWSR mapping size.\n"); return -EINVAL; } @@ -2077,7 +2082,8 @@ int kfd_reserved_mem_mmap(struct kfd_node *dev, struct kfd_process *process, qpd->cwsr_kaddr = (void *)__get_free_pages(GFP_KERNEL | __GFP_ZERO, get_order(KFD_CWSR_TBA_TMA_SIZE)); if (!qpd->cwsr_kaddr) { - pr_err("Error allocating per process CWSR buffer.\n"); + dev_err(dev->adev->dev, + "Error allocating per process CWSR buffer.\n"); return -ENOMEM; } -- cgit From ca280d291967dee97ad4340e1c68084c702d2b3c Mon Sep 17 00:00:00 2001 From: Pierre-Eric Pelloux-Prayer Date: Tue, 25 Jun 2024 14:31:34 +0200 Subject: drm/radeon: check bo_va->bo is non-NULL before using it The call to radeon_vm_clear_freed might clear bo_va->bo, so we have to check it before dereferencing it. Signed-off-by: Pierre-Eric Pelloux-Prayer Acked-by: Alex Deucher Signed-off-by: Alex Deucher --- drivers/gpu/drm/radeon/radeon_gem.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/gpu/drm/radeon/radeon_gem.c b/drivers/gpu/drm/radeon/radeon_gem.c index 2ef201a072f1..e66a230331ee 100644 --- a/drivers/gpu/drm/radeon/radeon_gem.c +++ b/drivers/gpu/drm/radeon/radeon_gem.c @@ -642,7 +642,7 @@ static void radeon_gem_va_update_vm(struct radeon_device *rdev, if (r) goto error_unlock; - if (bo_va->it.start) + if (bo_va->it.start && bo_va->bo) r = radeon_vm_bo_update(rdev, bo_va, bo_va->bo->tbo.resource); error_unlock: -- cgit From f340f2bad1c790d2759680b7df853f548e7beadc Mon Sep 17 00:00:00 2001 From: Marek Olšák Date: Sat, 1 Jun 2024 14:31:39 -0400 Subject: drm/amdgpu: rewrite convert_tiling_flags_to_modifier_gfx12 MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit There were multiple bugs, like checking SWIZZLE_MODE before checking GFX12_SWIZZLE_MODE, which has undefined behavior. The function had no effect before (it always returned -EINVAL). Signed-off-by: Marek Olšák Acked-by: Alex Deucher Reviewed-by: Aurabindo Pillai Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/amdgpu/amdgpu_display.c | 45 ++++++++++++----------------- 1 file changed, 18 insertions(+), 27 deletions(-) diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_display.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_display.c index ec0299c5918e..092ec11258cd 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_display.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_display.c @@ -724,32 +724,25 @@ extract_render_dcc_offset(struct amdgpu_device *adev, static int convert_tiling_flags_to_modifier_gfx12(struct amdgpu_framebuffer *afb) { - struct amdgpu_device *adev = drm_to_adev(afb->base.dev); - const struct drm_format_info *format_info; u64 modifier = 0; - int tile = 0; - int swizzle = 0; + int swizzle_mode = AMDGPU_TILING_GET(afb->tiling_flags, GFX12_SWIZZLE_MODE); - if (amdgpu_ip_version(adev, GC_HWIP, 0) >= IP_VERSION(12, 0, 0)) { - tile = AMD_FMT_MOD_TILE_VER_GFX12; - swizzle = AMDGPU_TILING_GET(afb->tiling_flags, GFX12_SWIZZLE_MODE); + if (!swizzle_mode) { + modifier = DRM_FORMAT_MOD_LINEAR; + } else { + int max_comp_block = + AMDGPU_TILING_GET(afb->tiling_flags, GFX12_DCC_MAX_COMPRESSED_BLOCK); + + modifier = + AMD_FMT_MOD | + AMD_FMT_MOD_SET(TILE_VERSION, AMD_FMT_MOD_TILE_VER_GFX12) | + AMD_FMT_MOD_SET(TILE, swizzle_mode) | + AMD_FMT_MOD_SET(DCC, afb->gfx12_dcc) | + AMD_FMT_MOD_SET(DCC_MAX_COMPRESSED_BLOCK, max_comp_block); } - modifier = - AMD_FMT_MOD | - AMD_FMT_MOD_SET(TILE, swizzle) | - AMD_FMT_MOD_SET(TILE_VERSION, tile) | - AMD_FMT_MOD_SET(DCC, 0) | - AMD_FMT_MOD_SET(DCC_MAX_COMPRESSED_BLOCK, 0); - - format_info = amdgpu_lookup_format_info(afb->base.format->format, - modifier); - if (!format_info) - return -EINVAL; - afb->base.modifier = modifier; afb->base.flags |= DRM_MODE_FB_MODIFIERS; - return 0; } @@ -777,12 +770,6 @@ static int convert_tiling_flags_to_modifier(struct amdgpu_framebuffer *afb) int pipes = ilog2(num_pipes); uint32_t dcc_offset = AMDGPU_TILING_GET(afb->tiling_flags, DCC_OFFSET_256B); - - if (amdgpu_ip_version(adev, GC_HWIP, 0) >= IP_VERSION(12, 0, 0)) { - convert_tiling_flags_to_modifier_gfx12(afb); - return 0; - } - switch (swizzle >> 2) { case 0: /* 256B */ block_size_bits = 8; @@ -1281,7 +1268,11 @@ static int amdgpu_display_framebuffer_init(struct drm_device *dev, if (!dev->mode_config.fb_modifiers_not_supported && !(rfb->base.flags & DRM_MODE_FB_MODIFIERS)) { - ret = convert_tiling_flags_to_modifier(rfb); + if (amdgpu_ip_version(adev, GC_HWIP, 0) >= IP_VERSION(12, 0, 0)) + ret = convert_tiling_flags_to_modifier_gfx12(rfb); + else + ret = convert_tiling_flags_to_modifier(rfb); + if (ret) { drm_dbg_kms(dev, "Failed to convert tiling flags 0x%llX to a modifier", rfb->tiling_flags); -- cgit From fcb2f988ef4905ac787fef040a28d0f0f610ad83 Mon Sep 17 00:00:00 2001 From: Jiapeng Chong Date: Mon, 1 Jul 2024 10:50:28 +0800 Subject: drm/amd/display: Fix unsigned comparison with less than zero The return value from the call to dml21_find_dc_pipes_for_plane() is int. However, the return value is being assigned to an unsigned int variable 'num_pipes', the condition if(num_pipes <= 0) is not rigorous enough, so making 'num_pipes' an int. ./drivers/gpu/drm/amd/display/dc/dml2/dml21/dml21_wrapper.c:318:6-15: WARNING: Unsigned expression compared with zero: num_pipes <= 0. ./drivers/gpu/drm/amd/display/dc/dml2/dml21/dml21_wrapper.c:360:6-15: WARNING: Unsigned expression compared with zero: num_pipes <= 0. Reported-by: Abaci Robot Closes: https://bugzilla.openanolis.cn/show_bug.cgi?id=9454 Signed-off-by: Jiapeng Chong Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/dc/dml2/dml21/dml21_wrapper.c | 15 ++++++--------- 1 file changed, 6 insertions(+), 9 deletions(-) diff --git a/drivers/gpu/drm/amd/display/dc/dml2/dml21/dml21_wrapper.c b/drivers/gpu/drm/amd/display/dc/dml2/dml21/dml21_wrapper.c index 9edcacdde6b7..41ecf00ed196 100644 --- a/drivers/gpu/drm/amd/display/dc/dml2/dml21/dml21_wrapper.c +++ b/drivers/gpu/drm/amd/display/dc/dml2/dml21/dml21_wrapper.c @@ -285,7 +285,8 @@ bool dml21_validate(const struct dc *in_dc, struct dc_state *context, struct dml void dml21_prepare_mcache_programming(struct dc *in_dc, struct dc_state *context, struct dml2_context *dml_ctx) { - unsigned int num_pipes, dml_prog_idx, dml_phantom_prog_idx, dc_pipe_index; + unsigned int dml_prog_idx, dml_phantom_prog_idx, dc_pipe_index; + int num_pipes; struct pipe_ctx *dc_main_pipes[__DML2_WRAPPER_MAX_STREAMS_PLANES__]; struct pipe_ctx *dc_phantom_pipes[__DML2_WRAPPER_MAX_STREAMS_PLANES__] = {0}; @@ -319,10 +320,8 @@ void dml21_prepare_mcache_programming(struct dc *in_dc, struct dc_state *context } num_pipes = dml21_find_dc_pipes_for_plane(in_dc, context, dml_ctx, dc_main_pipes, dc_phantom_pipes, dml_prog_idx); - - if (num_pipes <= 0 || - dc_main_pipes[0]->stream == NULL || - dc_main_pipes[0]->plane_state == NULL) + if (num_pipes <= 0 || dc_main_pipes[0]->stream == NULL || + dc_main_pipes[0]->plane_state == NULL) continue; /* get config for each pipe */ @@ -361,10 +360,8 @@ void dml21_prepare_mcache_programming(struct dc *in_dc, struct dc_state *context pln_prog = &dml_ctx->v21.mode_programming.programming->plane_programming[dml_prog_idx]; num_pipes = dml21_find_dc_pipes_for_plane(in_dc, context, dml_ctx, dc_main_pipes, dc_phantom_pipes, dml_prog_idx); - - if (num_pipes <= 0 || - dc_main_pipes[0]->stream == NULL || - dc_main_pipes[0]->plane_state == NULL) + if (num_pipes <= 0 || dc_main_pipes[0]->stream == NULL || + dc_main_pipes[0]->plane_state == NULL) continue; /* get config for each pipe */ -- cgit From 5380092f65b84cb843f363a145526047ef48d1fe Mon Sep 17 00:00:00 2001 From: Jiapeng Chong Date: Mon, 1 Jul 2024 15:04:54 +0800 Subject: drm/amd/display: Fix warning comparing pointer to 0 Avoid pointer type value compared with 0 to make code clear. ./drivers/gpu/drm/amd/display/dc/dml2/dml21/src/dml2_pmo/dml2_pmo_factory.c:31:12-13: WARNING comparing pointer to 0. Reported-by: Abaci Robot Closes: https://bugzilla.openanolis.cn/show_bug.cgi?id=9458 Signed-off-by: Jiapeng Chong Signed-off-by: Alex Deucher --- .../gpu/drm/amd/display/dc/dml2/dml21/src/dml2_pmo/dml2_pmo_factory.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/gpu/drm/amd/display/dc/dml2/dml21/src/dml2_pmo/dml2_pmo_factory.c b/drivers/gpu/drm/amd/display/dc/dml2/dml21/src/dml2_pmo/dml2_pmo_factory.c index a34506a78c50..e0b9ece7901d 100644 --- a/drivers/gpu/drm/amd/display/dc/dml2/dml21/src/dml2_pmo/dml2_pmo_factory.c +++ b/drivers/gpu/drm/amd/display/dc/dml2/dml21/src/dml2_pmo/dml2_pmo_factory.c @@ -28,7 +28,7 @@ bool dml2_pmo_create(enum dml2_project_id project_id, struct dml2_pmo_instance * { bool result = false; - if (out == 0) + if (!out) return false; memset(out, 0, sizeof(struct dml2_pmo_instance)); -- cgit From dcac51bd102cdb2aff1ad337d3c2fd354491ba42 Mon Sep 17 00:00:00 2001 From: Jiapeng Chong Date: Mon, 1 Jul 2024 15:04:53 +0800 Subject: drm/amd/display: Fix warning comparing pointer to 0 Avoid pointer type value compared with 0 to make code clear. ./drivers/gpu/drm/amd/display/dc/dml2/dml21/src/dml2_mcg/dml2_mcg_factory.c:19:12-13: WARNING comparing pointer to 0. Reported-by: Abaci Robot Closes: https://bugzilla.openanolis.cn/show_bug.cgi?id=9458 Signed-off-by: Jiapeng Chong Signed-off-by: Alex Deucher --- .../gpu/drm/amd/display/dc/dml2/dml21/src/dml2_mcg/dml2_mcg_factory.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/gpu/drm/amd/display/dc/dml2/dml21/src/dml2_mcg/dml2_mcg_factory.c b/drivers/gpu/drm/amd/display/dc/dml2/dml21/src/dml2_mcg/dml2_mcg_factory.c index ce83c10253a2..55085b85f8ed 100644 --- a/drivers/gpu/drm/amd/display/dc/dml2/dml21/src/dml2_mcg/dml2_mcg_factory.c +++ b/drivers/gpu/drm/amd/display/dc/dml2/dml21/src/dml2_mcg/dml2_mcg_factory.c @@ -16,7 +16,7 @@ bool dml2_mcg_create(enum dml2_project_id project_id, struct dml2_mcg_instance * { bool result = false; - if (out == 0) + if (!out) return false; memset(out, 0, sizeof(struct dml2_mcg_instance)); -- cgit From f4b1dbf413624ad07cc2ca2a6e6ec25c3f1e733b Mon Sep 17 00:00:00 2001 From: Jiapeng Chong Date: Mon, 1 Jul 2024 15:04:52 +0800 Subject: drm/amd/display: Fix warning comparing pointer to 0 Avoid pointer type value compared with 0 to make code clear. ./drivers/gpu/drm/amd/display/dc/dml2/dml21/src/dml2_dpmm/dml2_dpmm_factory.c:24:12-13: WARNING comparing pointer to 0. Reported-by: Abaci Robot Closes: https://bugzilla.openanolis.cn/show_bug.cgi?id=9458 Signed-off-by: Jiapeng Chong Signed-off-by: Alex Deucher --- .../gpu/drm/amd/display/dc/dml2/dml21/src/dml2_dpmm/dml2_dpmm_factory.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/gpu/drm/amd/display/dc/dml2/dml21/src/dml2_dpmm/dml2_dpmm_factory.c b/drivers/gpu/drm/amd/display/dc/dml2/dml21/src/dml2_dpmm/dml2_dpmm_factory.c index 657ec2e1b119..2c983daf2dad 100644 --- a/drivers/gpu/drm/amd/display/dc/dml2/dml21/src/dml2_dpmm/dml2_dpmm_factory.c +++ b/drivers/gpu/drm/amd/display/dc/dml2/dml21/src/dml2_dpmm/dml2_dpmm_factory.c @@ -21,7 +21,7 @@ bool dml2_dpmm_create(enum dml2_project_id project_id, struct dml2_dpmm_instance { bool result = false; - if (out == 0) + if (!out) return false; memset(out, 0, sizeof(struct dml2_dpmm_instance)); -- cgit From e931ab3eea505535abd0369c5da27e3a5d0057bb Mon Sep 17 00:00:00 2001 From: Jiapeng Chong Date: Mon, 1 Jul 2024 15:04:51 +0800 Subject: drm/amd/display: Fix warning comparing pointer to 0 Avoid pointer type value compared with 0 to make code clear. ./drivers/gpu/drm/amd/display/dc/dml2/dml21/src/dml2_core/dml2_core_factory.c:14:12-13: WARNING comparing pointer to 0. Reported-by: Abaci Robot Closes: https://bugzilla.openanolis.cn/show_bug.cgi?id=9458 Signed-off-by: Jiapeng Chong Signed-off-by: Alex Deucher --- .../gpu/drm/amd/display/dc/dml2/dml21/src/dml2_core/dml2_core_factory.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/gpu/drm/amd/display/dc/dml2/dml21/src/dml2_core/dml2_core_factory.c b/drivers/gpu/drm/amd/display/dc/dml2/dml21/src/dml2_core/dml2_core_factory.c index 1a0da8c6df5a..f56abe9ab919 100644 --- a/drivers/gpu/drm/amd/display/dc/dml2/dml21/src/dml2_core/dml2_core_factory.c +++ b/drivers/gpu/drm/amd/display/dc/dml2/dml21/src/dml2_core/dml2_core_factory.c @@ -11,7 +11,7 @@ bool dml2_core_create(enum dml2_project_id project_id, struct dml2_core_instance { bool result = false; - if (out == 0) + if (!out) return false; memset(out, 0, sizeof(struct dml2_core_instance)); -- cgit From 425c4a6f8ba62f77669a6a10ce9678153dee3e03 Mon Sep 17 00:00:00 2001 From: Sunil Khatri Date: Tue, 2 Jul 2024 13:46:50 +0530 Subject: drm/amdgpu: fix out of bounds access in gfx10 during ip dump MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit During ip dump in gfx10 the index variable is reused but is not reinitialized to 0 and this causes the index calculation to be wrong and access out of bound access. Acked-by: Christian König Signed-off-by: Sunil Khatri Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/amdgpu/gfx_v10_0.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/drivers/gpu/drm/amd/amdgpu/gfx_v10_0.c b/drivers/gpu/drm/amd/amdgpu/gfx_v10_0.c index 18488c02d1cf..a52c72739b40 100644 --- a/drivers/gpu/drm/amd/amdgpu/gfx_v10_0.c +++ b/drivers/gpu/drm/amd/amdgpu/gfx_v10_0.c @@ -9287,6 +9287,7 @@ static void gfx_v10_ip_print(void *handle, struct drm_printer *p) if (!adev->gfx.ip_dump_gfx_queues) return; + index = 0; reg_count = ARRAY_SIZE(gc_gfx_queue_reg_list_10); drm_printf(p, "\nnum_me: %d num_pipe: %d num_queue: %d\n", adev->gfx.me.num_me, @@ -9352,6 +9353,7 @@ static void gfx_v10_ip_dump(void *handle) if (!adev->gfx.ip_dump_gfx_queues) return; + index = 0; reg_count = ARRAY_SIZE(gc_gfx_queue_reg_list_10); amdgpu_gfx_off_ctrl(adev, false); mutex_lock(&adev->srbm_mutex); -- cgit From b6a343df46d69070a7073405e470e6348180ea34 Mon Sep 17 00:00:00 2001 From: Tim Huang Date: Tue, 14 May 2024 14:06:03 +0800 Subject: drm/amdgpu: initialize GC IP v11.5.2 Initialize GC 11.5.2 and set gfx hw configuration. Signed-off-by: Tim Huang Reviewed-by: Yifan Zhang Reviewed-by: Alex Deucher Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/amdgpu/gfx_v11_0.c | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/drivers/gpu/drm/amd/amdgpu/gfx_v11_0.c b/drivers/gpu/drm/amd/amdgpu/gfx_v11_0.c index 0d078d0db162..9acdabd7719a 100644 --- a/drivers/gpu/drm/amd/amdgpu/gfx_v11_0.c +++ b/drivers/gpu/drm/amd/amdgpu/gfx_v11_0.c @@ -1054,6 +1054,7 @@ static int gfx_v11_0_gpu_early_init(struct amdgpu_device *adev) case IP_VERSION(11, 0, 4): case IP_VERSION(11, 5, 0): case IP_VERSION(11, 5, 1): + case IP_VERSION(11, 5, 2): adev->gfx.config.max_hw_contexts = 8; adev->gfx.config.sc_prim_fifo_size_frontend = 0x20; adev->gfx.config.sc_prim_fifo_size_backend = 0x100; @@ -1534,6 +1535,7 @@ static int gfx_v11_0_sw_init(void *handle) case IP_VERSION(11, 0, 4): case IP_VERSION(11, 5, 0): case IP_VERSION(11, 5, 1): + case IP_VERSION(11, 5, 2): adev->gfx.me.num_me = 1; adev->gfx.me.num_pipe_per_me = 1; adev->gfx.me.num_queue_per_pipe = 1; @@ -2782,7 +2784,8 @@ static int gfx_v11_0_wait_for_rlc_autoload_complete(struct amdgpu_device *adev) amdgpu_ip_version(adev, GC_HWIP, 0) == IP_VERSION(11, 0, 4) || amdgpu_ip_version(adev, GC_HWIP, 0) == IP_VERSION(11, 5, 0) || - amdgpu_ip_version(adev, GC_HWIP, 0) == IP_VERSION(11, 5, 1)) + amdgpu_ip_version(adev, GC_HWIP, 0) == IP_VERSION(11, 5, 1) || + amdgpu_ip_version(adev, GC_HWIP, 0) == IP_VERSION(11, 5, 2)) bootload_status = RREG32_SOC15(GC, 0, regRLC_RLCS_BOOTLOAD_STATUS_gc_11_0_1); else @@ -5296,6 +5299,7 @@ static void gfx_v11_cntl_power_gating(struct amdgpu_device *adev, bool enable) case IP_VERSION(11, 0, 4): case IP_VERSION(11, 5, 0): case IP_VERSION(11, 5, 1): + case IP_VERSION(11, 5, 2): WREG32_SOC15(GC, 0, regRLC_PG_DELAY_3, RLC_PG_DELAY_3_DEFAULT_GC_11_0_1); break; default: @@ -5332,6 +5336,7 @@ static int gfx_v11_0_set_powergating_state(void *handle, case IP_VERSION(11, 0, 4): case IP_VERSION(11, 5, 0): case IP_VERSION(11, 5, 1): + case IP_VERSION(11, 5, 2): if (!enable) amdgpu_gfx_off_ctrl(adev, false); @@ -5364,6 +5369,7 @@ static int gfx_v11_0_set_clockgating_state(void *handle, case IP_VERSION(11, 0, 4): case IP_VERSION(11, 5, 0): case IP_VERSION(11, 5, 1): + case IP_VERSION(11, 5, 2): gfx_v11_0_update_gfx_clock_gating(adev, state == AMD_CG_STATE_GATE); break; -- cgit From 02cf3ed62783ba42b66605408666fd648ac3a090 Mon Sep 17 00:00:00 2001 From: Tim Huang Date: Tue, 14 May 2024 14:11:22 +0800 Subject: drm/amdgpu: add GFXHUB IP v11.5.2 support This patch is to add GFXHUB 11.5.2 support. Signed-off-by: Tim Huang Reviewed-by: Yifan Zhang Reviewed-by: Alex Deucher Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/amdgpu/gmc_v11_0.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/drivers/gpu/drm/amd/amdgpu/gmc_v11_0.c b/drivers/gpu/drm/amd/amdgpu/gmc_v11_0.c index cad883783834..b88a6fa173b3 100644 --- a/drivers/gpu/drm/amd/amdgpu/gmc_v11_0.c +++ b/drivers/gpu/drm/amd/amdgpu/gmc_v11_0.c @@ -592,6 +592,7 @@ static void gmc_v11_0_set_gfxhub_funcs(struct amdgpu_device *adev) break; case IP_VERSION(11, 5, 0): case IP_VERSION(11, 5, 1): + case IP_VERSION(11, 5, 2): adev->gfxhub.funcs = &gfxhub_v11_5_0_funcs; break; default: @@ -754,6 +755,7 @@ static int gmc_v11_0_sw_init(void *handle) case IP_VERSION(11, 0, 4): case IP_VERSION(11, 5, 0): case IP_VERSION(11, 5, 1): + case IP_VERSION(11, 5, 2): set_bit(AMDGPU_GFXHUB(0), adev->vmhubs_mask); set_bit(AMDGPU_MMHUB0(0), adev->vmhubs_mask); /* -- cgit From 98392782df666cee2b9d4161494bb23177d67605 Mon Sep 17 00:00:00 2001 From: Tim Huang Date: Tue, 14 May 2024 14:14:17 +0800 Subject: drm/amdgpu: add tmz support for GC IP v11.5.2 Add tmz support for GC 11.5.2. Signed-off-by: Tim Huang Reviewed-by: Yifan Zhang Reviewed-by: Alex Deucher Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/amdgpu/amdgpu_gmc.c | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_gmc.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_gmc.c index 3a7622611916..c02659025656 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_gmc.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_gmc.c @@ -848,6 +848,7 @@ void amdgpu_gmc_tmz_set(struct amdgpu_device *adev) case IP_VERSION(11, 0, 4): case IP_VERSION(11, 5, 0): case IP_VERSION(11, 5, 1): + case IP_VERSION(11, 5, 2): /* Don't enable it by default yet. */ if (amdgpu_tmz < 1) { -- cgit From 43e4cc22994290668b1ac63a0da4c74388c1cfe8 Mon Sep 17 00:00:00 2001 From: Tim Huang Date: Tue, 14 May 2024 14:17:13 +0800 Subject: drm/amdgpu: add GC IP v11.5.2 soc21 support Add CG and PG flags for GFX IP v11.5.2 and PG flags for VCN IP v4.0.5. Signed-off-by: Saleemkhan Jamadar Signed-off-by: Li Ma Signed-off-by: Tim Huang Reviewed-by: Yifan Zhang Reviewed-by: Veerabadhran Gopalakrishnan Reviewed-by: Alex Deucher Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/amdgpu/soc21.c | 26 ++++++++++++++++++++++++++ 1 file changed, 26 insertions(+) diff --git a/drivers/gpu/drm/amd/amdgpu/soc21.c b/drivers/gpu/drm/amd/amdgpu/soc21.c index 15845ecca7c7..b04c763015d3 100644 --- a/drivers/gpu/drm/amd/amdgpu/soc21.c +++ b/drivers/gpu/drm/amd/amdgpu/soc21.c @@ -752,6 +752,32 @@ static int soc21_common_early_init(void *handle) AMD_PG_SUPPORT_JPEG; adev->external_rev_id = adev->rev_id + 0xc1; break; + case IP_VERSION(11, 5, 2): + adev->cg_flags = AMD_CG_SUPPORT_VCN_MGCG | + AMD_CG_SUPPORT_JPEG_MGCG | + AMD_CG_SUPPORT_GFX_CGCG | + AMD_CG_SUPPORT_GFX_CGLS | + AMD_CG_SUPPORT_GFX_MGCG | + AMD_CG_SUPPORT_GFX_FGCG | + AMD_CG_SUPPORT_REPEATER_FGCG | + AMD_CG_SUPPORT_GFX_PERF_CLK | + AMD_CG_SUPPORT_GFX_3D_CGCG | + AMD_CG_SUPPORT_GFX_3D_CGLS | + AMD_CG_SUPPORT_MC_MGCG | + AMD_CG_SUPPORT_MC_LS | + AMD_CG_SUPPORT_HDP_LS | + AMD_CG_SUPPORT_HDP_DS | + AMD_CG_SUPPORT_HDP_SD | + AMD_CG_SUPPORT_ATHUB_MGCG | + AMD_CG_SUPPORT_ATHUB_LS | + AMD_CG_SUPPORT_IH_CG | + AMD_CG_SUPPORT_BIF_MGCG | + AMD_CG_SUPPORT_BIF_LS; + adev->pg_flags = AMD_PG_SUPPORT_VCN | + AMD_PG_SUPPORT_JPEG | + AMD_PG_SUPPORT_GFX_PG; + adev->external_rev_id = adev->rev_id + 0x40; + break; default: /* FIXME: not supported yet */ return -EINVAL; -- cgit From 23c1ea02417d10ddcf4d50b5cd5ea7b02c69cceb Mon Sep 17 00:00:00 2001 From: Tim Huang Date: Tue, 14 May 2024 14:22:09 +0800 Subject: drm/amdgpu: add GC IP v11.5.2 to GC 11.5.0 family This patch is to add GC 11.5.2 to GC 11.5.0 family. Signed-off-by: Tim Huang Reviewed-by: Yifan Zhang Reviewed-by: Veerabadhran Gopalakrishnan Reviewed-by: Alex Deucher Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/amdgpu/amdgpu_discovery.c | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_discovery.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_discovery.c index 90475ddf1c03..4078ff5e91c3 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_discovery.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_discovery.c @@ -1808,6 +1808,7 @@ static int amdgpu_discovery_set_common_ip_blocks(struct amdgpu_device *adev) case IP_VERSION(11, 0, 4): case IP_VERSION(11, 5, 0): case IP_VERSION(11, 5, 1): + case IP_VERSION(11, 5, 2): amdgpu_device_ip_block_add(adev, &soc21_common_ip_block); break; case IP_VERSION(12, 0, 0): @@ -1861,6 +1862,7 @@ static int amdgpu_discovery_set_gmc_ip_blocks(struct amdgpu_device *adev) case IP_VERSION(11, 0, 4): case IP_VERSION(11, 5, 0): case IP_VERSION(11, 5, 1): + case IP_VERSION(11, 5, 2): amdgpu_device_ip_block_add(adev, &gmc_v11_0_ip_block); break; case IP_VERSION(12, 0, 0): @@ -2152,6 +2154,7 @@ static int amdgpu_discovery_set_gc_ip_blocks(struct amdgpu_device *adev) case IP_VERSION(11, 0, 4): case IP_VERSION(11, 5, 0): case IP_VERSION(11, 5, 1): + case IP_VERSION(11, 5, 2): amdgpu_device_ip_block_add(adev, &gfx_v11_0_ip_block); break; case IP_VERSION(12, 0, 0): @@ -2325,6 +2328,7 @@ static int amdgpu_discovery_set_mes_ip_blocks(struct amdgpu_device *adev) case IP_VERSION(11, 0, 4): case IP_VERSION(11, 5, 0): case IP_VERSION(11, 5, 1): + case IP_VERSION(11, 5, 2): amdgpu_device_ip_block_add(adev, &mes_v11_0_ip_block); adev->enable_mes = true; adev->enable_mes_kiq = true; @@ -2634,6 +2638,7 @@ int amdgpu_discovery_set_ip_blocks(struct amdgpu_device *adev) break; case IP_VERSION(11, 5, 0): case IP_VERSION(11, 5, 1): + case IP_VERSION(11, 5, 2): adev->family = AMDGPU_FAMILY_GC_11_5_0; break; case IP_VERSION(12, 0, 0): @@ -2658,6 +2663,7 @@ int amdgpu_discovery_set_ip_blocks(struct amdgpu_device *adev) case IP_VERSION(11, 0, 4): case IP_VERSION(11, 5, 0): case IP_VERSION(11, 5, 1): + case IP_VERSION(11, 5, 2): adev->flags |= AMD_IS_APU; break; default: -- cgit From 53c3a37436c400a00d05702334920354f2e3fdc2 Mon Sep 17 00:00:00 2001 From: Tim Huang Date: Tue, 14 May 2024 14:24:44 +0800 Subject: drm/amdkfd: add KFD support for GC IP v11.5.2 Enable KFD for GC 11.5.2. Signed-off-by: Tim Huang Reviewed-by: Yifan Zhang Reviewed-by: Alex Deucher Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/amdkfd/kfd_crat.c | 1 + drivers/gpu/drm/amd/amdkfd/kfd_device.c | 5 +++++ 2 files changed, 6 insertions(+) diff --git a/drivers/gpu/drm/amd/amdkfd/kfd_crat.c b/drivers/gpu/drm/amd/amdkfd/kfd_crat.c index ead43386a7ef..cd7b81b7b939 100644 --- a/drivers/gpu/drm/amd/amdkfd/kfd_crat.c +++ b/drivers/gpu/drm/amd/amdkfd/kfd_crat.c @@ -1678,6 +1678,7 @@ int kfd_get_gpu_cache_info(struct kfd_node *kdev, struct kfd_gpu_cache_info **pc case IP_VERSION(11, 0, 4): case IP_VERSION(11, 5, 0): case IP_VERSION(11, 5, 1): + case IP_VERSION(11, 5, 2): case IP_VERSION(12, 0, 0): case IP_VERSION(12, 0, 1): num_of_cache_types = diff --git a/drivers/gpu/drm/amd/amdkfd/kfd_device.c b/drivers/gpu/drm/amd/amdkfd/kfd_device.c index 6040ee7918bf..e6debd63a116 100644 --- a/drivers/gpu/drm/amd/amdkfd/kfd_device.c +++ b/drivers/gpu/drm/amd/amdkfd/kfd_device.c @@ -175,6 +175,7 @@ static void kfd_device_info_set_event_interrupt_class(struct kfd_dev *kfd) case IP_VERSION(11, 0, 4): case IP_VERSION(11, 5, 0): case IP_VERSION(11, 5, 1): + case IP_VERSION(11, 5, 2): kfd->device_info.event_interrupt_class = &event_interrupt_class_v11; break; case IP_VERSION(12, 0, 0): @@ -438,6 +439,10 @@ struct kfd_dev *kgd2kfd_probe(struct amdgpu_device *adev, bool vf) gfx_target_version = 110501; f2g = &gfx_v11_kfd2kgd; break; + case IP_VERSION(11, 5, 2): + gfx_target_version = 110502; + f2g = &gfx_v11_kfd2kgd; + break; case IP_VERSION(12, 0, 0): gfx_target_version = 120000; f2g = &gfx_v12_kfd2kgd; -- cgit From 4448b1ff4d267873575a7b74a3786b9c7c114c1d Mon Sep 17 00:00:00 2001 From: Tim Huang Date: Tue, 4 Jun 2024 13:22:39 +0800 Subject: drm/amdgpu: add firmware for GC IP v11.5.2 This patch is to add firmware for GC 11.5.2. Signed-off-by: Tim Huang Reviewed-by: Yifan Zhang Reviewed-by: Alex Deucher Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/amdgpu/gfx_v11_0.c | 4 ++++ drivers/gpu/drm/amd/amdgpu/imu_v11_0.c | 1 + drivers/gpu/drm/amd/amdgpu/mes_v11_0.c | 2 ++ 3 files changed, 7 insertions(+) diff --git a/drivers/gpu/drm/amd/amdgpu/gfx_v11_0.c b/drivers/gpu/drm/amd/amdgpu/gfx_v11_0.c index 9acdabd7719a..38150398a31b 100644 --- a/drivers/gpu/drm/amd/amdgpu/gfx_v11_0.c +++ b/drivers/gpu/drm/amd/amdgpu/gfx_v11_0.c @@ -93,6 +93,10 @@ MODULE_FIRMWARE("amdgpu/gc_11_5_1_pfp.bin"); MODULE_FIRMWARE("amdgpu/gc_11_5_1_me.bin"); MODULE_FIRMWARE("amdgpu/gc_11_5_1_mec.bin"); MODULE_FIRMWARE("amdgpu/gc_11_5_1_rlc.bin"); +MODULE_FIRMWARE("amdgpu/gc_11_5_2_pfp.bin"); +MODULE_FIRMWARE("amdgpu/gc_11_5_2_me.bin"); +MODULE_FIRMWARE("amdgpu/gc_11_5_2_mec.bin"); +MODULE_FIRMWARE("amdgpu/gc_11_5_2_rlc.bin"); static const struct amdgpu_hwip_reg_entry gc_reg_list_11_0[] = { SOC15_REG_ENTRY_STR(GC, 0, regGRBM_STATUS), diff --git a/drivers/gpu/drm/amd/amdgpu/imu_v11_0.c b/drivers/gpu/drm/amd/amdgpu/imu_v11_0.c index a9f5d9e4610d..6c1891889c4d 100644 --- a/drivers/gpu/drm/amd/amdgpu/imu_v11_0.c +++ b/drivers/gpu/drm/amd/amdgpu/imu_v11_0.c @@ -38,6 +38,7 @@ MODULE_FIRMWARE("amdgpu/gc_11_0_3_imu.bin"); MODULE_FIRMWARE("amdgpu/gc_11_0_4_imu.bin"); MODULE_FIRMWARE("amdgpu/gc_11_5_0_imu.bin"); MODULE_FIRMWARE("amdgpu/gc_11_5_1_imu.bin"); +MODULE_FIRMWARE("amdgpu/gc_11_5_2_imu.bin"); static int imu_v11_0_init_microcode(struct amdgpu_device *adev) { diff --git a/drivers/gpu/drm/amd/amdgpu/mes_v11_0.c b/drivers/gpu/drm/amd/amdgpu/mes_v11_0.c index 3b1f6ad99100..1376b6ff1b77 100644 --- a/drivers/gpu/drm/amd/amdgpu/mes_v11_0.c +++ b/drivers/gpu/drm/amd/amdgpu/mes_v11_0.c @@ -51,6 +51,8 @@ MODULE_FIRMWARE("amdgpu/gc_11_5_0_mes_2.bin"); MODULE_FIRMWARE("amdgpu/gc_11_5_0_mes1.bin"); MODULE_FIRMWARE("amdgpu/gc_11_5_1_mes_2.bin"); MODULE_FIRMWARE("amdgpu/gc_11_5_1_mes1.bin"); +MODULE_FIRMWARE("amdgpu/gc_11_5_2_mes_2.bin"); +MODULE_FIRMWARE("amdgpu/gc_11_5_2_mes1.bin"); static int mes_v11_0_hw_init(void *handle); static int mes_v11_0_hw_fini(void *handle); -- cgit From dfeccf4d5437bdba1bf9cec14490d989677743c5 Mon Sep 17 00:00:00 2001 From: Tim Huang Date: Tue, 14 May 2024 14:48:01 +0800 Subject: drm/amdgpu: add SDMA IP v6.1.2 discovery support This patch is to add SDMA 6.1.2 support. Signed-off-by: Tim Huang Reviewed-by: Yifan Zhang Reviewed-by: Alex Deucher Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/amdgpu/amdgpu_discovery.c | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_discovery.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_discovery.c index 4078ff5e91c3..08945fba98a2 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_discovery.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_discovery.c @@ -2210,6 +2210,7 @@ static int amdgpu_discovery_set_sdma_ip_blocks(struct amdgpu_device *adev) case IP_VERSION(6, 0, 3): case IP_VERSION(6, 1, 0): case IP_VERSION(6, 1, 1): + case IP_VERSION(6, 1, 2): amdgpu_device_ip_block_add(adev, &sdma_v6_0_ip_block); break; case IP_VERSION(7, 0, 0): -- cgit From 71d8af38d3a9d9e17c255c13b6ff5fc1379ebade Mon Sep 17 00:00:00 2001 From: Tim Huang Date: Tue, 14 May 2024 14:50:12 +0800 Subject: drm/amdkfd: add KFD support for SDMA IP v6.1.2 Enable KFD setting SDMA info for SDMA 6.1.2. Signed-off-by: Tim Huang Reviewed-by: Yifan Zhang Reviewed-by: Alex Deucher Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/amdkfd/kfd_device.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/drivers/gpu/drm/amd/amdkfd/kfd_device.c b/drivers/gpu/drm/amd/amdkfd/kfd_device.c index e6debd63a116..f4d20adaa068 100644 --- a/drivers/gpu/drm/amd/amdkfd/kfd_device.c +++ b/drivers/gpu/drm/amd/amdkfd/kfd_device.c @@ -99,6 +99,7 @@ static void kfd_device_info_set_sdma_info(struct kfd_dev *kfd) case IP_VERSION(6, 0, 3): case IP_VERSION(6, 1, 0): case IP_VERSION(6, 1, 1): + case IP_VERSION(6, 1, 2): case IP_VERSION(7, 0, 0): case IP_VERSION(7, 0, 1): kfd->device_info.num_sdma_queues_per_engine = 8; @@ -119,6 +120,7 @@ static void kfd_device_info_set_sdma_info(struct kfd_dev *kfd) case IP_VERSION(6, 0, 3): case IP_VERSION(6, 1, 0): case IP_VERSION(6, 1, 1): + case IP_VERSION(6, 1, 2): case IP_VERSION(7, 0, 0): case IP_VERSION(7, 0, 1): /* Reserve 1 for paging and 1 for gfx */ -- cgit From 6857669a2276fdc31f53b0edec46661149237112 Mon Sep 17 00:00:00 2001 From: Tim Huang Date: Tue, 4 Jun 2024 13:27:23 +0800 Subject: drm/amdgpu: add firmware for SDMA IP v6.1.2 This patch is to add firmware for SDMA 6.1.2. Signed-off-by: Tim Huang Reviewed-by: Yifan Zhang Reviewed-by: Alex Deucher Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/amdgpu/sdma_v6_0.c | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/gpu/drm/amd/amdgpu/sdma_v6_0.c b/drivers/gpu/drm/amd/amdgpu/sdma_v6_0.c index c833b6b8373b..dab4c2db8c9d 100644 --- a/drivers/gpu/drm/amd/amdgpu/sdma_v6_0.c +++ b/drivers/gpu/drm/amd/amdgpu/sdma_v6_0.c @@ -50,6 +50,7 @@ MODULE_FIRMWARE("amdgpu/sdma_6_0_2.bin"); MODULE_FIRMWARE("amdgpu/sdma_6_0_3.bin"); MODULE_FIRMWARE("amdgpu/sdma_6_1_0.bin"); MODULE_FIRMWARE("amdgpu/sdma_6_1_1.bin"); +MODULE_FIRMWARE("amdgpu/sdma_6_1_2.bin"); #define SDMA1_REG_OFFSET 0x600 #define SDMA0_HYP_DEC_REG_START 0x5880 -- cgit From 5aea87169414101686c90c23719cce30c96d6ef0 Mon Sep 17 00:00:00 2001 From: Tim Huang Date: Tue, 14 May 2024 15:01:42 +0800 Subject: drm/amdgpu: add NBIO IP v7.11.3 discovery support This patch is to add NBIO 7.11.3 support. Signed-off-by: Tim Huang Reviewed-by: Yifan Zhang Reviewed-by: Alex Deucher Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/amdgpu/amdgpu_discovery.c | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_discovery.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_discovery.c index 08945fba98a2..c4b9a7dd8dcb 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_discovery.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_discovery.c @@ -2703,6 +2703,7 @@ int amdgpu_discovery_set_ip_blocks(struct amdgpu_device *adev) break; case IP_VERSION(7, 11, 0): case IP_VERSION(7, 11, 1): + case IP_VERSION(7, 11, 3): adev->nbio.funcs = &nbio_v7_11_funcs; adev->nbio.hdp_flush_reg = &nbio_v7_11_hdp_flush_reg; break; -- cgit From 410bb279a8ca540cb8101160fefba5891b89d03a Mon Sep 17 00:00:00 2001 From: Tim Huang Date: Tue, 14 May 2024 15:04:02 +0800 Subject: drm/amdgpu: Add NBIO IP v7.11.3 support Enable setting soc21 common clockgating for NBIO 7.11.3. Signed-off-by: Tim Huang Reviewed-by: Yifan Zhang Reviewed-by: Alex Deucher Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/amdgpu/soc21.c | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/gpu/drm/amd/amdgpu/soc21.c b/drivers/gpu/drm/amd/amdgpu/soc21.c index b04c763015d3..b43c50f1c7ad 100644 --- a/drivers/gpu/drm/amd/amdgpu/soc21.c +++ b/drivers/gpu/drm/amd/amdgpu/soc21.c @@ -953,6 +953,7 @@ static int soc21_common_set_clockgating_state(void *handle, case IP_VERSION(7, 7, 1): case IP_VERSION(7, 11, 0): case IP_VERSION(7, 11, 1): + case IP_VERSION(7, 11, 3): adev->nbio.funcs->update_medium_grain_clock_gating(adev, state == AMD_CG_STATE_GATE); adev->nbio.funcs->update_medium_grain_light_sleep(adev, -- cgit From f3e2a425c6b212d88d26c7d194e09508e520a5e8 Mon Sep 17 00:00:00 2001 From: Tim Huang Date: Wed, 15 May 2024 16:27:06 +0800 Subject: drm/amdgpu: add VPE IP v6.1.3 support This patch is to add VPE 6.1.3 support. Signed-off-by: Tim Huang Reviewed-by: Yifan Zhang Reviewed-by: Alex Deucher Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/amdgpu/amdgpu_vpe.c | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_vpe.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_vpe.c index bad232859972..5acd20ff5979 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_vpe.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_vpe.c @@ -302,6 +302,7 @@ static int vpe_early_init(void *handle) switch (amdgpu_ip_version(adev, VPE_HWIP, 0)) { case IP_VERSION(6, 1, 0): + case IP_VERSION(6, 1, 3): vpe_v6_1_set_funcs(vpe); break; case IP_VERSION(6, 1, 1): -- cgit From ca15cd559fd841c968989ee44d3fda6e75974198 Mon Sep 17 00:00:00 2001 From: Tim Huang Date: Wed, 15 May 2024 16:32:28 +0800 Subject: drm/amdgpu: add VPE IP v6.1.3 discovery support This patch is to add VPE 6.1.3 support. Signed-off-by: Tim Huang Reviewed-by: Yifan Zhang Reviewed-by: Alex Deucher Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/amdgpu/amdgpu_discovery.c | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_discovery.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_discovery.c index c4b9a7dd8dcb..8277c4abcad3 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_discovery.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_discovery.c @@ -2365,6 +2365,7 @@ static int amdgpu_discovery_set_vpe_ip_blocks(struct amdgpu_device *adev) switch (amdgpu_ip_version(adev, VPE_HWIP, 0)) { case IP_VERSION(6, 1, 0): case IP_VERSION(6, 1, 1): + case IP_VERSION(6, 1, 3): amdgpu_device_ip_block_add(adev, &vpe_v6_1_ip_block); break; default: -- cgit From 614a9f5ed5b079af9cb933b9ebc6b3e128a2560d Mon Sep 17 00:00:00 2001 From: Tim Huang Date: Tue, 4 Jun 2024 13:51:30 +0800 Subject: drm/amdgpu: add firmware for VPE IP v6.1.3 This patch is to add firmware for VPE 6.1.3. Signed-off-by: Tim Huang Reviewed-by: Yifan Zhang Reviewed-by: Alex Deucher Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/amdgpu/vpe_v6_1.c | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/gpu/drm/amd/amdgpu/vpe_v6_1.c b/drivers/gpu/drm/amd/amdgpu/vpe_v6_1.c index 09315dd5a1ec..45876883bbf3 100644 --- a/drivers/gpu/drm/amd/amdgpu/vpe_v6_1.c +++ b/drivers/gpu/drm/amd/amdgpu/vpe_v6_1.c @@ -34,6 +34,7 @@ MODULE_FIRMWARE("amdgpu/vpe_6_1_0.bin"); MODULE_FIRMWARE("amdgpu/vpe_6_1_1.bin"); +MODULE_FIRMWARE("amdgpu/vpe_6_1_3.bin"); #define VPE_THREAD1_UCODE_OFFSET 0x8000 -- cgit From c7c3f786b931f89a5b645e01a7cc3214e791e73b Mon Sep 17 00:00:00 2001 From: Tim Huang Date: Tue, 14 May 2024 15:53:25 +0800 Subject: drm/amdgpu: add PSP IP v14.0.4 support This patch is to add PSP 14.0.4 support. Signed-off-by: Tim Huang Reviewed-by: Yifan Zhang Reviewed-by: Alex Deucher Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/amdgpu/amdgpu_psp.c | 1 + drivers/gpu/drm/amd/amdgpu/psp_v13_0.c | 1 + 2 files changed, 2 insertions(+) diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_psp.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_psp.c index e15814d9ca17..800cc7a148b2 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_psp.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_psp.c @@ -219,6 +219,7 @@ static int psp_early_init(void *handle) case IP_VERSION(13, 0, 11): case IP_VERSION(14, 0, 0): case IP_VERSION(14, 0, 1): + case IP_VERSION(14, 0, 4): psp_v13_0_set_psp_funcs(psp); psp->boot_time_tmr = false; break; diff --git a/drivers/gpu/drm/amd/amdgpu/psp_v13_0.c b/drivers/gpu/drm/amd/amdgpu/psp_v13_0.c index b52e15e2dcc7..407477b895d1 100644 --- a/drivers/gpu/drm/amd/amdgpu/psp_v13_0.c +++ b/drivers/gpu/drm/amd/amdgpu/psp_v13_0.c @@ -106,6 +106,7 @@ static int psp_v13_0_init_microcode(struct psp_context *psp) case IP_VERSION(13, 0, 11): case IP_VERSION(14, 0, 0): case IP_VERSION(14, 0, 1): + case IP_VERSION(14, 0, 4): err = psp_init_toc_microcode(psp, ucode_prefix); if (err) return err; -- cgit From 9cd2ad14d88d6a99fb1f9364fabaf6bca5b1fc9a Mon Sep 17 00:00:00 2001 From: Tim Huang Date: Tue, 14 May 2024 15:56:37 +0800 Subject: drm/amdgpu: add PSP IP v14.0.4 discovery support This patch is to add PSP 14.0.4 support. Signed-off-by: Tim Huang Reviewed-by: Yifan Zhang Reviewed-by: Alex Deucher Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/amdgpu/amdgpu_discovery.c | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_discovery.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_discovery.c index 8277c4abcad3..d84ce9679dd4 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_discovery.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_discovery.c @@ -1964,6 +1964,7 @@ static int amdgpu_discovery_set_psp_ip_blocks(struct amdgpu_device *adev) case IP_VERSION(13, 0, 14): case IP_VERSION(14, 0, 0): case IP_VERSION(14, 0, 1): + case IP_VERSION(14, 0, 4): amdgpu_device_ip_block_add(adev, &psp_v13_0_ip_block); break; case IP_VERSION(13, 0, 4): -- cgit From 11382d02fb5ad2d6d3145c9d1c863720add7efa5 Mon Sep 17 00:00:00 2001 From: Li Ma Date: Tue, 28 May 2024 16:30:56 +0800 Subject: drm/amd/pm: smu v14.0.4 reuse smu v14.0.0 dpmtable Replace IP VERSION with smu->is_apu in if condition. And the dpmtable of smu v14.0.4 is same as smu v14.0.0. Signed-off-by: Li Ma Reviewed-by: Yifan Zhang Reviewed-by: Alex Deucher Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/pm/swsmu/smu14/smu_v14_0.c | 18 +++++-------- .../gpu/drm/amd/pm/swsmu/smu14/smu_v14_0_0_ppt.c | 30 +++++++++++----------- 2 files changed, 21 insertions(+), 27 deletions(-) diff --git a/drivers/gpu/drm/amd/pm/swsmu/smu14/smu_v14_0.c b/drivers/gpu/drm/amd/pm/swsmu/smu14/smu_v14_0.c index 5ffd7144d99e..095ee7e2c4bb 100644 --- a/drivers/gpu/drm/amd/pm/swsmu/smu14/smu_v14_0.c +++ b/drivers/gpu/drm/amd/pm/swsmu/smu14/smu_v14_0.c @@ -136,8 +136,7 @@ int smu_v14_0_load_microcode(struct smu_context *smu) 1 & ~MP1_SMN_PUB_CTRL__LX3_RESET_MASK); for (i = 0; i < adev->usec_timeout; i++) { - if (amdgpu_ip_version(adev, MP1_HWIP, 0) == IP_VERSION(14, 0, 0) || - amdgpu_ip_version(adev, MP1_HWIP, 0) == IP_VERSION(14, 0, 1)) + if (smu->is_apu) mp1_fw_flags = RREG32_PCIE(MP1_Public | (smnMP1_FIRMWARE_FLAGS_14_0_0 & 0xffffffff)); else @@ -210,8 +209,7 @@ int smu_v14_0_check_fw_status(struct smu_context *smu) struct amdgpu_device *adev = smu->adev; uint32_t mp1_fw_flags; - if (amdgpu_ip_version(adev, MP1_HWIP, 0) == IP_VERSION(14, 0, 0) || - amdgpu_ip_version(adev, MP1_HWIP, 0) == IP_VERSION(14, 0, 1)) + if (smu->is_apu) mp1_fw_flags = RREG32_PCIE(MP1_Public | (smnMP1_FIRMWARE_FLAGS_14_0_0 & 0xffffffff)); else @@ -866,8 +864,7 @@ static int smu_v14_0_set_irq_state(struct amdgpu_device *adev, WREG32_SOC15(THM, 0, regTHM_THERMAL_INT_ENA, 0); /* For MP1 SW irqs */ - if (amdgpu_ip_version(adev, MP1_HWIP, 0) == IP_VERSION(14, 0, 0) || - amdgpu_ip_version(adev, MP1_HWIP, 0) == IP_VERSION(14, 0, 1)) { + if (smu->is_apu) { val = RREG32_SOC15(MP1, 0, regMP1_SMN_IH_SW_INT_CTRL_mp1_14_0_0); val = REG_SET_FIELD(val, MP1_SMN_IH_SW_INT_CTRL, INT_MASK, 1); WREG32_SOC15(MP1, 0, regMP1_SMN_IH_SW_INT_CTRL_mp1_14_0_0, val); @@ -900,8 +897,7 @@ static int smu_v14_0_set_irq_state(struct amdgpu_device *adev, WREG32_SOC15(THM, 0, regTHM_THERMAL_INT_ENA, val); /* For MP1 SW irqs */ - if (amdgpu_ip_version(adev, MP1_HWIP, 0) == IP_VERSION(14, 0, 0) || - amdgpu_ip_version(adev, MP1_HWIP, 0) == IP_VERSION(14, 0, 1)) { + if (smu->is_apu) { val = RREG32_SOC15(MP1, 0, regMP1_SMN_IH_SW_INT_mp1_14_0_0); val = REG_SET_FIELD(val, MP1_SMN_IH_SW_INT, ID, 0xFE); val = REG_SET_FIELD(val, MP1_SMN_IH_SW_INT, VALID, 0); @@ -1494,8 +1490,7 @@ int smu_v14_0_set_vcn_enable(struct smu_context *smu, if (adev->vcn.harvest_config & (1 << i)) continue; - if (amdgpu_ip_version(adev, MP1_HWIP, 0) == IP_VERSION(14, 0, 0) || - amdgpu_ip_version(adev, MP1_HWIP, 0) == IP_VERSION(14, 0, 1)) { + if (smu->is_apu) { if (i == 0) ret = smu_cmn_send_smc_msg_with_param(smu, enable ? SMU_MSG_PowerUpVcn0 : SMU_MSG_PowerDownVcn0, @@ -1527,8 +1522,7 @@ int smu_v14_0_set_jpeg_enable(struct smu_context *smu, if (adev->jpeg.harvest_config & (1 << i)) continue; - if (amdgpu_ip_version(adev, MP1_HWIP, 0) == IP_VERSION(14, 0, 0) || - amdgpu_ip_version(adev, MP1_HWIP, 0) == IP_VERSION(14, 0, 1)) { + if (smu->is_apu) { if (i == 0) ret = smu_cmn_send_smc_msg_with_param(smu, enable ? SMU_MSG_PowerUpJpeg0 : SMU_MSG_PowerDownJpeg0, diff --git a/drivers/gpu/drm/amd/pm/swsmu/smu14/smu_v14_0_0_ppt.c b/drivers/gpu/drm/amd/pm/swsmu/smu14/smu_v14_0_0_ppt.c index 18abfbd6d059..3a9d58c036ea 100644 --- a/drivers/gpu/drm/amd/pm/swsmu/smu14/smu_v14_0_0_ppt.c +++ b/drivers/gpu/drm/amd/pm/swsmu/smu14/smu_v14_0_0_ppt.c @@ -723,10 +723,10 @@ static int smu_v14_0_common_get_dpm_freq_by_index(struct smu_context *smu, uint32_t dpm_level, uint32_t *freq) { - if (amdgpu_ip_version(smu->adev, MP1_HWIP, 0) == IP_VERSION(14, 0, 0)) - smu_v14_0_0_get_dpm_freq_by_index(smu, clk_type, dpm_level, freq); - else if (amdgpu_ip_version(smu->adev, MP1_HWIP, 0) == IP_VERSION(14, 0, 1)) + if (amdgpu_ip_version(smu->adev, MP1_HWIP, 0) == IP_VERSION(14, 0, 1)) smu_v14_0_1_get_dpm_freq_by_index(smu, clk_type, dpm_level, freq); + else + smu_v14_0_0_get_dpm_freq_by_index(smu, clk_type, dpm_level, freq); return 0; } @@ -999,10 +999,10 @@ static int smu_v14_0_common_get_dpm_ultimate_freq(struct smu_context *smu, uint32_t *min, uint32_t *max) { - if (amdgpu_ip_version(smu->adev, MP1_HWIP, 0) == IP_VERSION(14, 0, 0)) - smu_v14_0_0_get_dpm_ultimate_freq(smu, clk_type, min, max); - else if (amdgpu_ip_version(smu->adev, MP1_HWIP, 0) == IP_VERSION(14, 0, 1)) + if (amdgpu_ip_version(smu->adev, MP1_HWIP, 0) == IP_VERSION(14, 0, 1)) smu_v14_0_1_get_dpm_ultimate_freq(smu, clk_type, min, max); + else + smu_v14_0_0_get_dpm_ultimate_freq(smu, clk_type, min, max); return 0; } @@ -1104,10 +1104,10 @@ static int smu_v14_0_common_get_dpm_level_count(struct smu_context *smu, enum smu_clk_type clk_type, uint32_t *count) { - if (amdgpu_ip_version(smu->adev, MP1_HWIP, 0) == IP_VERSION(14, 0, 0)) - smu_v14_0_0_get_dpm_level_count(smu, clk_type, count); - else if (amdgpu_ip_version(smu->adev, MP1_HWIP, 0) == IP_VERSION(14, 0, 1)) + if (amdgpu_ip_version(smu->adev, MP1_HWIP, 0) == IP_VERSION(14, 0, 1)) smu_v14_0_1_get_dpm_level_count(smu, clk_type, count); + else + smu_v14_0_0_get_dpm_level_count(smu, clk_type, count); return 0; } @@ -1372,10 +1372,10 @@ static int smu_v14_0_0_set_fine_grain_gfx_freq_parameters(struct smu_context *sm static int smu_v14_0_common_set_fine_grain_gfx_freq_parameters(struct smu_context *smu) { - if (amdgpu_ip_version(smu->adev, MP1_HWIP, 0) == IP_VERSION(14, 0, 0)) - smu_v14_0_0_set_fine_grain_gfx_freq_parameters(smu); - else if (amdgpu_ip_version(smu->adev, MP1_HWIP, 0) == IP_VERSION(14, 0, 1)) + if (amdgpu_ip_version(smu->adev, MP1_HWIP, 0) == IP_VERSION(14, 0, 1)) smu_v14_0_1_set_fine_grain_gfx_freq_parameters(smu); + else + smu_v14_0_0_set_fine_grain_gfx_freq_parameters(smu); return 0; } @@ -1436,10 +1436,10 @@ static int smu_14_0_0_get_dpm_table(struct smu_context *smu, struct dpm_clocks * static int smu_v14_0_common_get_dpm_table(struct smu_context *smu, struct dpm_clocks *clock_table) { - if (amdgpu_ip_version(smu->adev, MP1_HWIP, 0) == IP_VERSION(14, 0, 0)) - smu_14_0_0_get_dpm_table(smu, clock_table); - else if (amdgpu_ip_version(smu->adev, MP1_HWIP, 0) == IP_VERSION(14, 0, 1)) + if (amdgpu_ip_version(smu->adev, MP1_HWIP, 0) == IP_VERSION(14, 0, 1)) smu_14_0_1_get_dpm_table(smu, clock_table); + else + smu_14_0_0_get_dpm_table(smu, clock_table); return 0; } -- cgit From 80ffdc273a75f5049277f590b0c287df979a5169 Mon Sep 17 00:00:00 2001 From: Tim Huang Date: Wed, 15 May 2024 12:57:02 +0800 Subject: drm/amd/pm: add SMU IP v14.0.4 support This patch is to add SMU 14.0.4 support. Signed-off-by: Li Ma Signed-off-by: Tim Huang Reviewed-by: Yifan Zhang Reviewed-by: Alex Deucher Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/pm/swsmu/amdgpu_smu.c | 1 + drivers/gpu/drm/amd/pm/swsmu/smu14/smu_v14_0.c | 2 ++ 2 files changed, 3 insertions(+) diff --git a/drivers/gpu/drm/amd/pm/swsmu/amdgpu_smu.c b/drivers/gpu/drm/amd/pm/swsmu/amdgpu_smu.c index 00384b381289..d79bdb1e8cdf 100644 --- a/drivers/gpu/drm/amd/pm/swsmu/amdgpu_smu.c +++ b/drivers/gpu/drm/amd/pm/swsmu/amdgpu_smu.c @@ -727,6 +727,7 @@ static int smu_set_funcs(struct amdgpu_device *adev) break; case IP_VERSION(14, 0, 0): case IP_VERSION(14, 0, 1): + case IP_VERSION(14, 0, 4): smu_v14_0_0_set_ppt_funcs(smu); break; case IP_VERSION(14, 0, 2): diff --git a/drivers/gpu/drm/amd/pm/swsmu/smu14/smu_v14_0.c b/drivers/gpu/drm/amd/pm/swsmu/smu14/smu_v14_0.c index 095ee7e2c4bb..09973615f210 100644 --- a/drivers/gpu/drm/amd/pm/swsmu/smu14/smu_v14_0.c +++ b/drivers/gpu/drm/amd/pm/swsmu/smu14/smu_v14_0.c @@ -243,6 +243,7 @@ int smu_v14_0_check_fw_version(struct smu_context *smu) switch (amdgpu_ip_version(adev, MP1_HWIP, 0)) { case IP_VERSION(14, 0, 0): + case IP_VERSION(14, 0, 4): smu->smc_driver_if_version = SMU14_DRIVER_IF_VERSION_SMU_V14_0_0; break; case IP_VERSION(14, 0, 1): @@ -757,6 +758,7 @@ int smu_v14_0_gfx_off_control(struct smu_context *smu, bool enable) case IP_VERSION(14, 0, 1): case IP_VERSION(14, 0, 2): case IP_VERSION(14, 0, 3): + case IP_VERSION(14, 0, 4): if (!(adev->pm.pp_feature & PP_GFXOFF_MASK)) return 0; if (enable) -- cgit From 38a16bfe6fae93d3d4b7273f0d3add9ffcc4ff03 Mon Sep 17 00:00:00 2001 From: Tim Huang Date: Tue, 14 May 2024 16:38:48 +0800 Subject: drm/amdgpu: add SMU IP v14.0.4 discovery support This patch is to add SMU 14.0.4 support Signed-off-by: Tim Huang Reviewed-by: Yifan Zhang Reviewed-by: Alex Deucher Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/amdgpu/amdgpu_discovery.c | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_discovery.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_discovery.c index d84ce9679dd4..f927ccd7ec45 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_discovery.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_discovery.c @@ -2028,6 +2028,7 @@ static int amdgpu_discovery_set_smu_ip_blocks(struct amdgpu_device *adev) case IP_VERSION(14, 0, 1): case IP_VERSION(14, 0, 2): case IP_VERSION(14, 0, 3): + case IP_VERSION(14, 0, 4): amdgpu_device_ip_block_add(adev, &smu_v14_0_ip_block); break; default: -- cgit From b709f949f0e5576cd5e8949bfd21474f60ba3df5 Mon Sep 17 00:00:00 2001 From: Tim Huang Date: Tue, 14 May 2024 16:41:48 +0800 Subject: drm/amdgpu: enable mode2 reset for SMU IP v14.0.4 Set the default reset method to mode2 for SMU 14.0.4. Signed-off-by: Tim Huang Reviewed-by: Yifan Zhang Reviewed-by: Alex Deucher Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/amdgpu/soc21.c | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/gpu/drm/amd/amdgpu/soc21.c b/drivers/gpu/drm/amd/amdgpu/soc21.c index b43c50f1c7ad..6cc86d13f32a 100644 --- a/drivers/gpu/drm/amd/amdgpu/soc21.c +++ b/drivers/gpu/drm/amd/amdgpu/soc21.c @@ -389,6 +389,7 @@ soc21_asic_reset_method(struct amdgpu_device *adev) case IP_VERSION(13, 0, 11): case IP_VERSION(14, 0, 0): case IP_VERSION(14, 0, 1): + case IP_VERSION(14, 0, 4): return AMD_RESET_METHOD_MODE2; default: if (amdgpu_dpm_is_baco_supported(adev)) -- cgit From 94845ea05758ae94cc305a7bf3d536cad40bf15c Mon Sep 17 00:00:00 2001 From: Tim Huang Date: Tue, 4 Jun 2024 13:33:05 +0800 Subject: drm/amdgpu: add firmware for PSP IP v14.0.4 This patch is to add firmware for PSP 14.0.4. Signed-off-by: Tim Huang Reviewed-by: Yifan Zhang Reviewed-by: Alex Deucher Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/amdgpu/psp_v13_0.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/drivers/gpu/drm/amd/amdgpu/psp_v13_0.c b/drivers/gpu/drm/amd/amdgpu/psp_v13_0.c index 407477b895d1..1251ee38a676 100644 --- a/drivers/gpu/drm/amd/amdgpu/psp_v13_0.c +++ b/drivers/gpu/drm/amd/amdgpu/psp_v13_0.c @@ -57,6 +57,8 @@ MODULE_FIRMWARE("amdgpu/psp_14_0_0_toc.bin"); MODULE_FIRMWARE("amdgpu/psp_14_0_0_ta.bin"); MODULE_FIRMWARE("amdgpu/psp_14_0_1_toc.bin"); MODULE_FIRMWARE("amdgpu/psp_14_0_1_ta.bin"); +MODULE_FIRMWARE("amdgpu/psp_14_0_4_toc.bin"); +MODULE_FIRMWARE("amdgpu/psp_14_0_4_ta.bin"); /* For large FW files the time to complete can be very long */ #define USBC_PD_POLLING_LIMIT_S 240 -- cgit From ea67deb03cc0b3f6e00b4aab87732672d73295b5 Mon Sep 17 00:00:00 2001 From: Sunil Khatri Date: Tue, 2 Jul 2024 13:49:20 +0530 Subject: drm/amdgpu: fix out of bounds access in gfx11 during ip dump MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit During ip dump in gfx11 the index variable is reused but is not reinitialized to 0 and this causes the index calculation to be wrong and access out of bound access. Acked-by: Christian König Signed-off-by: Sunil Khatri Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/amdgpu/gfx_v11_0.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/drivers/gpu/drm/amd/amdgpu/gfx_v11_0.c b/drivers/gpu/drm/amd/amdgpu/gfx_v11_0.c index 38150398a31b..6228dd0450a7 100644 --- a/drivers/gpu/drm/amd/amdgpu/gfx_v11_0.c +++ b/drivers/gpu/drm/amd/amdgpu/gfx_v11_0.c @@ -6411,6 +6411,7 @@ static void gfx_v11_ip_print(void *handle, struct drm_printer *p) if (!adev->gfx.ip_dump_gfx_queues) return; + index = 0; reg_count = ARRAY_SIZE(gc_gfx_queue_reg_list_11); drm_printf(p, "\nnum_me: %d num_pipe: %d num_queue: %d\n", adev->gfx.me.num_me, @@ -6475,6 +6476,7 @@ static void gfx_v11_ip_dump(void *handle) if (!adev->gfx.ip_dump_gfx_queues) return; + index = 0; reg_count = ARRAY_SIZE(gc_gfx_queue_reg_list_11); amdgpu_gfx_off_ctrl(adev, false); mutex_lock(&adev->srbm_mutex); -- cgit From 4ed6a3689caba239e6df18c60af9489001f481c3 Mon Sep 17 00:00:00 2001 From: Alex Deucher Date: Mon, 1 Jul 2024 12:50:10 -0400 Subject: drm/amdgpu/atomfirmware: silence UBSAN warning This is a variable sized array. Link: https://lists.freedesktop.org/archives/amd-gfx/2024-June/110420.html Tested-by: Jeff Layton Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/include/atomfirmware.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/gpu/drm/amd/include/atomfirmware.h b/drivers/gpu/drm/amd/include/atomfirmware.h index 571691837200..09cbc3afd6d8 100644 --- a/drivers/gpu/drm/amd/include/atomfirmware.h +++ b/drivers/gpu/drm/amd/include/atomfirmware.h @@ -734,7 +734,7 @@ struct atom_gpio_pin_lut_v2_1 { struct atom_common_table_header table_header; /*the real number of this included in the structure is calcualted by using the (whole structure size - the header size)/size of atom_gpio_pin_lut */ - struct atom_gpio_pin_assignment gpio_pin[8]; + struct atom_gpio_pin_assignment gpio_pin[]; }; -- cgit