Skip to content

Commit 9c6669c

Browse files
Michael Straussalexdeucher
authored andcommitted
drm/amd/display: Fix Link Override Sequencing When Switching Between DIO/HPO
[WHY] When performing certain link maintenance compliance tests or forcing link settings, changing between 128b/132b and 8b/10b rates no longer works on some ASICs. Some rate divider updates only occur when we set timings or validate state, which is not performed currently when toggling DPMS to change rates. [HOW] Re-calculate dividers and reprogram audio when switching between DIO and HPO through DP compliance/escape code path. Add OTG disable/re-enable so we don't touch the clock while OTG is active. Acquire dcLock before forcing link settings to avoid thread synchronization errors due to added programming in escape code path and potential HPD interrupts. Reviewed-by: George Shen <george.shen@amd.com> Signed-off-by: Michael Strauss <michael.strauss@amd.com> Signed-off-by: Mike Katsnelson <mike.katsnelson@amd.com> Signed-off-by: Ray Wu <ray.wu@amd.com> Tested-by: Daniel Wheeler <daniel.wheeler@amd.com> Signed-off-by: Alex Deucher <alexander.deucher@amd.com>
1 parent 51496c7 commit 9c6669c

12 files changed

Lines changed: 126 additions & 14 deletions

File tree

drivers/gpu/drm/amd/display/dc/hwss/dce110/dce110_hwseq.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1381,7 +1381,7 @@ static void populate_audio_dp_link_info(
13811381
}
13821382
}
13831383

1384-
static void build_audio_output(
1384+
void build_audio_output(
13851385
struct dc_state *state,
13861386
const struct pipe_ctx *pipe_ctx,
13871387
struct audio_output *audio_output)

drivers/gpu/drm/amd/display/dc/hwss/dce110/dce110_hwseq.h

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -110,5 +110,9 @@ void dce110_enable_dp_link_output(
110110
enum signal_type signal,
111111
enum clock_source_id clock_source,
112112
const struct dc_link_settings *link_settings);
113+
void build_audio_output(
114+
struct dc_state *state,
115+
const struct pipe_ctx *pipe_ctx,
116+
struct audio_output *audio_output);
113117
#endif /* __DC_HWSS_DCE110_H__ */
114118

drivers/gpu/drm/amd/display/dc/inc/core_types.h

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -223,6 +223,11 @@ struct resource_funcs {
223223
const struct dc_stream_state *stream);
224224
bool (*program_mcache_pipe_config)(struct dc_state *context,
225225
const struct dc_mcache_params *mcache_params);
226+
enum dc_status (*update_dc_state_for_encoder_switch)(struct dc_link *link,
227+
struct dc_link_settings *link_setting,
228+
uint8_t pipe_count,
229+
struct pipe_ctx *pipes,
230+
struct audio_output *audio_output);
226231
};
227232

228233
struct audio_support{

drivers/gpu/drm/amd/display/dc/link/accessories/link_dp_cts.c

Lines changed: 57 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,7 @@
3434
#include "dm_helpers.h"
3535
#include "dc_dmub_srv.h"
3636
#include "dce/dmub_hw_lock_mgr.h"
37+
#include "clk_mgr.h"
3738

3839
#define DC_LOGGER \
3940
link->ctx->logger
@@ -67,10 +68,17 @@ static void dp_retrain_link_dp_test(struct dc_link *link,
6768
{
6869
struct pipe_ctx *pipes[MAX_PIPES];
6970
struct dc_state *state = link->dc->current_state;
71+
struct dc_stream_update stream_update = { 0 };
72+
bool dpms_off = false;
73+
bool needs_divider_update = false;
7074
bool was_hpo_acquired = resource_is_hpo_acquired(link->dc->current_state);
7175
bool is_hpo_acquired;
7276
uint8_t count;
7377
int i;
78+
struct audio_output audio_output[MAX_PIPES];
79+
80+
needs_divider_update = (link->dc->link_srv->dp_get_encoding_format(link_setting) !=
81+
link->dc->link_srv->dp_get_encoding_format((const struct dc_link_settings *) &link->cur_link_settings));
7482

7583
udelay(100);
7684

@@ -83,16 +91,59 @@ static void dp_retrain_link_dp_test(struct dc_link *link,
8391
link->dc,
8492
state,
8593
pipes[i]);
94+
95+
// Disable OTG and re-enable after updating clocks
96+
pipes[i]->stream_res.tg->funcs->disable_crtc(pipes[i]->stream_res.tg);
8697
}
8798

88-
if (link->dc->hwss.setup_hpo_hw_control) {
89-
is_hpo_acquired = resource_is_hpo_acquired(state);
90-
if (was_hpo_acquired != is_hpo_acquired)
91-
link->dc->hwss.setup_hpo_hw_control(link->dc->hwseq, is_hpo_acquired);
99+
if (needs_divider_update && link->dc->res_pool->funcs->update_dc_state_for_encoder_switch) {
100+
link->dc->res_pool->funcs->update_dc_state_for_encoder_switch(link,
101+
link_setting, count,
102+
*pipes, &audio_output[0]);
103+
for (i = 0; i < count; i++) {
104+
pipes[i]->clock_source->funcs->program_pix_clk(
105+
pipes[i]->clock_source,
106+
&pipes[i]->stream_res.pix_clk_params,
107+
link->dc->link_srv->dp_get_encoding_format(&pipes[i]->link_config.dp_link_settings),
108+
&pipes[i]->pll_settings);
109+
110+
if (pipes[i]->stream_res.audio != NULL) {
111+
const struct link_hwss *link_hwss = get_link_hwss(
112+
link, &pipes[i]->link_res);
113+
114+
link_hwss->setup_audio_output(pipes[i], &audio_output[i],
115+
pipes[i]->stream_res.audio->inst);
116+
117+
pipes[i]->stream_res.audio->funcs->az_configure(
118+
pipes[i]->stream_res.audio,
119+
pipes[i]->stream->signal,
120+
&audio_output[i].crtc_info,
121+
&pipes[i]->stream->audio_info,
122+
&audio_output[i].dp_link_info);
123+
124+
if (link->dc->config.disable_hbr_audio_dp2 &&
125+
pipes[i]->stream_res.audio->funcs->az_disable_hbr_audio &&
126+
link->dc->link_srv->dp_is_128b_132b_signal(pipes[i]))
127+
pipes[i]->stream_res.audio->funcs->az_disable_hbr_audio(pipes[i]->stream_res.audio);
128+
}
129+
}
92130
}
93131

94-
for (i = count-1; i >= 0; i--)
95-
link_set_dpms_on(state, pipes[i]);
132+
// Toggle on HPO I/O if necessary
133+
is_hpo_acquired = resource_is_hpo_acquired(state);
134+
if (was_hpo_acquired != is_hpo_acquired && link->dc->hwss.setup_hpo_hw_control)
135+
link->dc->hwss.setup_hpo_hw_control(link->dc->hwseq, is_hpo_acquired);
136+
137+
for (i = 0; i < count; i++)
138+
pipes[i]->stream_res.tg->funcs->enable_crtc(pipes[i]->stream_res.tg);
139+
140+
// Set DPMS on with stream update
141+
for (i = 0; i < state->stream_count; i++)
142+
if (state->streams[i] && state->streams[i]->link && state->streams[i]->link == link) {
143+
stream_update.stream = state->streams[i];
144+
stream_update.dpms_off = &dpms_off;
145+
dc_update_planes_and_stream(state->clk_mgr->ctx->dc, NULL, 0, state->streams[i], &stream_update);
146+
}
96147
}
97148

98149
static void dp_test_send_link_training(struct dc_link *link)

drivers/gpu/drm/amd/display/dc/resource/dcn31/dcn31_resource.c

Lines changed: 35 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1850,7 +1850,9 @@ static struct resource_funcs dcn31_res_pool_funcs = {
18501850
.patch_unknown_plane_state = dcn20_patch_unknown_plane_state,
18511851
.get_panel_config_defaults = dcn31_get_panel_config_defaults,
18521852
.get_det_buffer_size = dcn31_get_det_buffer_size,
1853-
.get_vstartup_for_pipe = dcn10_get_vstartup_for_pipe
1853+
.get_vstartup_for_pipe = dcn10_get_vstartup_for_pipe,
1854+
.update_dc_state_for_encoder_switch = dcn31_update_dc_state_for_encoder_switch,
1855+
.build_pipe_pix_clk_params = dcn20_build_pipe_pix_clk_params
18541856
};
18551857

18561858
static struct clock_source *dcn30_clock_source_create(
@@ -2231,3 +2233,35 @@ struct resource_pool *dcn31_create_resource_pool(
22312233
kfree(pool);
22322234
return NULL;
22332235
}
2236+
2237+
enum dc_status dcn31_update_dc_state_for_encoder_switch(struct dc_link *link,
2238+
struct dc_link_settings *link_setting,
2239+
uint8_t pipe_count,
2240+
struct pipe_ctx *pipes,
2241+
struct audio_output *audio_output)
2242+
{
2243+
struct dc_state *state = link->dc->current_state;
2244+
int i;
2245+
2246+
#if defined(CONFIG_DRM_AMD_DC_FP)
2247+
for (i = 0; i < state->stream_count; i++)
2248+
if (state->streams[i] && state->streams[i]->link && state->streams[i]->link == link)
2249+
link->dc->hwss.calculate_pix_rate_divider((struct dc *)link->dc, state, state->streams[i]);
2250+
2251+
for (i = 0; i < pipe_count; i++) {
2252+
link->dc->res_pool->funcs->build_pipe_pix_clk_params(&pipes[i]);
2253+
2254+
// Setup audio
2255+
if (pipes[i].stream_res.audio != NULL)
2256+
build_audio_output(state, &pipes[i], &audio_output[i]);
2257+
}
2258+
#else
2259+
/* This DCN requires rate divider updates and audio reprogramming to allow DP1<-->DP2 link rate switching,
2260+
* but the above will not compile on architectures without an FPU.
2261+
*/
2262+
DC_LOG_WARNING("%s: DP1<-->DP2 link retraining will not work on this DCN on non-FPU platforms", __func__);
2263+
ASSERT(0);
2264+
#endif
2265+
2266+
return DC_OK;
2267+
}

drivers/gpu/drm/amd/display/dc/resource/dcn31/dcn31_resource.h

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -66,6 +66,12 @@ struct resource_pool *dcn31_create_resource_pool(
6666
unsigned int dcn31_get_det_buffer_size(
6767
const struct dc_state *context);
6868

69+
enum dc_status dcn31_update_dc_state_for_encoder_switch(struct dc_link *link,
70+
struct dc_link_settings *link_setting,
71+
uint8_t pipe_count,
72+
struct pipe_ctx *pipes,
73+
struct audio_output *audio_output);
74+
6975
/*temp: B0 specific before switch to dcn313 headers*/
7076
#ifndef regPHYPLLF_PIXCLK_RESYNC_CNTL
7177
#define regPHYPLLF_PIXCLK_RESYNC_CNTL 0x007e

drivers/gpu/drm/amd/display/dc/resource/dcn314/dcn314_resource.c

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1779,7 +1779,9 @@ static struct resource_funcs dcn314_res_pool_funcs = {
17791779
.get_panel_config_defaults = dcn314_get_panel_config_defaults,
17801780
.get_preferred_eng_id_dpia = dcn314_get_preferred_eng_id_dpia,
17811781
.get_det_buffer_size = dcn31_get_det_buffer_size,
1782-
.get_vstartup_for_pipe = dcn10_get_vstartup_for_pipe
1782+
.get_vstartup_for_pipe = dcn10_get_vstartup_for_pipe,
1783+
.update_dc_state_for_encoder_switch = dcn31_update_dc_state_for_encoder_switch,
1784+
.build_pipe_pix_clk_params = dcn20_build_pipe_pix_clk_params
17831785
};
17841786

17851787
static struct clock_source *dcn30_clock_source_create(

drivers/gpu/drm/amd/display/dc/resource/dcn315/dcn315_resource.c

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1844,7 +1844,9 @@ static struct resource_funcs dcn315_res_pool_funcs = {
18441844
.get_panel_config_defaults = dcn315_get_panel_config_defaults,
18451845
.get_power_profile = dcn315_get_power_profile,
18461846
.get_det_buffer_size = dcn31_get_det_buffer_size,
1847-
.get_vstartup_for_pipe = dcn10_get_vstartup_for_pipe
1847+
.get_vstartup_for_pipe = dcn10_get_vstartup_for_pipe,
1848+
.update_dc_state_for_encoder_switch = dcn31_update_dc_state_for_encoder_switch,
1849+
.build_pipe_pix_clk_params = dcn20_build_pipe_pix_clk_params
18481850
};
18491851

18501852
static bool dcn315_resource_construct(

drivers/gpu/drm/amd/display/dc/resource/dcn316/dcn316_resource.c

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1720,7 +1720,9 @@ static struct resource_funcs dcn316_res_pool_funcs = {
17201720
.patch_unknown_plane_state = dcn20_patch_unknown_plane_state,
17211721
.get_panel_config_defaults = dcn316_get_panel_config_defaults,
17221722
.get_det_buffer_size = dcn31_get_det_buffer_size,
1723-
.get_vstartup_for_pipe = dcn10_get_vstartup_for_pipe
1723+
.get_vstartup_for_pipe = dcn10_get_vstartup_for_pipe,
1724+
.update_dc_state_for_encoder_switch = dcn31_update_dc_state_for_encoder_switch,
1725+
.build_pipe_pix_clk_params = dcn20_build_pipe_pix_clk_params
17241726
};
17251727

17261728
static bool dcn316_resource_construct(

drivers/gpu/drm/amd/display/dc/resource/dcn35/dcn35_resource.c

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1786,7 +1786,9 @@ static struct resource_funcs dcn35_res_pool_funcs = {
17861786
.get_panel_config_defaults = dcn35_get_panel_config_defaults,
17871787
.get_preferred_eng_id_dpia = dcn35_get_preferred_eng_id_dpia,
17881788
.get_det_buffer_size = dcn31_get_det_buffer_size,
1789-
.get_vstartup_for_pipe = dcn10_get_vstartup_for_pipe
1789+
.get_vstartup_for_pipe = dcn10_get_vstartup_for_pipe,
1790+
.update_dc_state_for_encoder_switch = dcn31_update_dc_state_for_encoder_switch,
1791+
.build_pipe_pix_clk_params = dcn20_build_pipe_pix_clk_params
17901792
};
17911793

17921794
static bool dcn35_resource_construct(

0 commit comments

Comments
 (0)