mirror of
https://github.com/torvalds/linux.git
synced 2026-05-24 07:03:03 +02:00
drm/amd/display: Set CRTC source for DAC using registers
Apparently the VBIOS SelectCRTC_Source function overwrites
a few registers (such as FMT_*) which DC writes in a different
place, which can cause problems.
Instead of using the SelectCRTC_Source function from the
VBIOS, use the DAC_SOURCE_SELECT register directly, similarly
to how it is done for digital link encoders.
Fixes: 3be26d81b1 ("drm/amd/display: Support DAC in dce110_hwseq")
Signed-off-by: Timur Kristóf <timur.kristof@gmail.com>
Tested-by: Mauro Rossi <issor.oruam@gmail.com>
Reviewed-by: Alex Hung <alex.hung@amd.com>
Signed-off-by: Alex Deucher <alexander.deucher@amd.com>
This commit is contained in:
parent
e2a024345b
commit
cbced93894
|
|
@ -1498,7 +1498,10 @@ static void dig_connect_to_otg(
|
|||
{
|
||||
struct dce110_stream_encoder *enc110 = DCE110STRENC_FROM_STRENC(enc);
|
||||
|
||||
REG_UPDATE(DIG_FE_CNTL, DIG_SOURCE_SELECT, tg_inst);
|
||||
if (enc->id == ENGINE_ID_DACA || enc->id == ENGINE_ID_DACB)
|
||||
REG_UPDATE(DAC_SOURCE_SELECT, DAC_SOURCE_SELECT, tg_inst);
|
||||
else
|
||||
REG_UPDATE(DIG_FE_CNTL, DIG_SOURCE_SELECT, tg_inst);
|
||||
}
|
||||
|
||||
static unsigned int dig_source_otg(
|
||||
|
|
@ -1507,7 +1510,10 @@ static unsigned int dig_source_otg(
|
|||
uint32_t tg_inst = 0;
|
||||
struct dce110_stream_encoder *enc110 = DCE110STRENC_FROM_STRENC(enc);
|
||||
|
||||
REG_GET(DIG_FE_CNTL, DIG_SOURCE_SELECT, &tg_inst);
|
||||
if (enc->id == ENGINE_ID_DACA || enc->id == ENGINE_ID_DACB)
|
||||
REG_GET(DAC_SOURCE_SELECT, DAC_SOURCE_SELECT, &tg_inst);
|
||||
else
|
||||
REG_GET(DIG_FE_CNTL, DIG_SOURCE_SELECT, &tg_inst);
|
||||
|
||||
return tg_inst;
|
||||
}
|
||||
|
|
@ -1568,16 +1574,25 @@ void dce110_stream_encoder_construct(
|
|||
enc110->se_mask = se_mask;
|
||||
}
|
||||
|
||||
static const struct stream_encoder_funcs dce110_an_str_enc_funcs = {};
|
||||
static const struct stream_encoder_funcs dce110_an_str_enc_funcs = {
|
||||
.dig_connect_to_otg = dig_connect_to_otg,
|
||||
.dig_source_otg = dig_source_otg,
|
||||
};
|
||||
|
||||
void dce110_analog_stream_encoder_construct(
|
||||
struct dce110_stream_encoder *enc110,
|
||||
struct dc_context *ctx,
|
||||
struct dc_bios *bp,
|
||||
enum engine_id eng_id)
|
||||
enum engine_id eng_id,
|
||||
const struct dce110_stream_enc_registers *regs,
|
||||
const struct dce_stream_encoder_shift *se_shift,
|
||||
const struct dce_stream_encoder_mask *se_mask)
|
||||
{
|
||||
enc110->base.funcs = &dce110_an_str_enc_funcs;
|
||||
enc110->base.ctx = ctx;
|
||||
enc110->base.id = eng_id;
|
||||
enc110->base.bp = bp;
|
||||
enc110->regs = regs;
|
||||
enc110->se_shift = se_shift;
|
||||
enc110->se_mask = se_mask;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -65,6 +65,7 @@
|
|||
SRI(AFMT_60958_1, DIG, id), \
|
||||
SRI(AFMT_60958_2, DIG, id), \
|
||||
SRI(DIG_FE_CNTL, DIG, id), \
|
||||
SR(DAC_SOURCE_SELECT), \
|
||||
SRI(HDMI_CONTROL, DIG, id), \
|
||||
SRI(HDMI_GC, DIG, id), \
|
||||
SRI(HDMI_GENERIC_PACKET_CONTROL0, DIG, id), \
|
||||
|
|
@ -290,7 +291,8 @@
|
|||
#define SE_COMMON_MASK_SH_LIST_DCE80_100(mask_sh)\
|
||||
SE_COMMON_MASK_SH_LIST_DCE_COMMON(mask_sh),\
|
||||
SE_SF(TMDS_CNTL, TMDS_PIXEL_ENCODING, mask_sh),\
|
||||
SE_SF(TMDS_CNTL, TMDS_COLOR_FORMAT, mask_sh)
|
||||
SE_SF(TMDS_CNTL, TMDS_COLOR_FORMAT, mask_sh),\
|
||||
SE_SF(DAC_SOURCE_SELECT, DAC_SOURCE_SELECT, mask_sh)
|
||||
|
||||
#define SE_COMMON_MASK_SH_LIST_DCE110(mask_sh)\
|
||||
SE_COMMON_MASK_SH_LIST_DCE_COMMON(mask_sh),\
|
||||
|
|
@ -494,6 +496,7 @@ struct dce_stream_encoder_shift {
|
|||
uint8_t DP_VID_N_MUL;
|
||||
uint8_t DP_VID_M_DOUBLE_VALUE_EN;
|
||||
uint8_t DIG_SOURCE_SELECT;
|
||||
uint8_t DAC_SOURCE_SELECT;
|
||||
};
|
||||
|
||||
struct dce_stream_encoder_mask {
|
||||
|
|
@ -626,6 +629,7 @@ struct dce_stream_encoder_mask {
|
|||
uint32_t DP_VID_N_MUL;
|
||||
uint32_t DP_VID_M_DOUBLE_VALUE_EN;
|
||||
uint32_t DIG_SOURCE_SELECT;
|
||||
uint32_t DAC_SOURCE_SELECT;
|
||||
};
|
||||
|
||||
struct dce110_stream_enc_registers {
|
||||
|
|
@ -653,6 +657,7 @@ struct dce110_stream_enc_registers {
|
|||
uint32_t AFMT_60958_1;
|
||||
uint32_t AFMT_60958_2;
|
||||
uint32_t DIG_FE_CNTL;
|
||||
uint32_t DAC_SOURCE_SELECT;
|
||||
uint32_t DP_MSE_RATE_CNTL;
|
||||
uint32_t DP_MSE_RATE_UPDATE;
|
||||
uint32_t DP_PIXEL_FORMAT;
|
||||
|
|
@ -712,7 +717,10 @@ void dce110_analog_stream_encoder_construct(
|
|||
struct dce110_stream_encoder *enc110,
|
||||
struct dc_context *ctx,
|
||||
struct dc_bios *bp,
|
||||
enum engine_id eng_id);
|
||||
enum engine_id eng_id,
|
||||
const struct dce110_stream_enc_registers *regs,
|
||||
const struct dce_stream_encoder_shift *se_shift,
|
||||
const struct dce_stream_encoder_mask *se_mask);
|
||||
|
||||
void dce110_se_audio_mute_control(
|
||||
struct stream_encoder *enc, bool mute);
|
||||
|
|
|
|||
|
|
@ -1581,25 +1581,6 @@ static enum dc_status dce110_enable_stream_timing(
|
|||
return DC_OK;
|
||||
}
|
||||
|
||||
static void
|
||||
dce110_select_crtc_source(struct pipe_ctx *pipe_ctx)
|
||||
{
|
||||
struct dc_link *link = pipe_ctx->stream->link;
|
||||
struct dc_bios *bios = link->ctx->dc_bios;
|
||||
struct bp_crtc_source_select crtc_source_select = {0};
|
||||
enum engine_id engine_id = link->link_enc->preferred_engine;
|
||||
|
||||
if (dc_is_rgb_signal(pipe_ctx->stream->signal))
|
||||
engine_id = link->link_enc->analog_engine;
|
||||
|
||||
crtc_source_select.controller_id = CONTROLLER_ID_D0 + pipe_ctx->stream_res.tg->inst;
|
||||
crtc_source_select.color_depth = pipe_ctx->stream->timing.display_color_depth;
|
||||
crtc_source_select.engine_id = engine_id;
|
||||
crtc_source_select.sink_signal = pipe_ctx->stream->signal;
|
||||
|
||||
bios->funcs->select_crtc_source(bios, &crtc_source_select);
|
||||
}
|
||||
|
||||
enum dc_status dce110_apply_single_controller_ctx_to_hw(
|
||||
struct pipe_ctx *pipe_ctx,
|
||||
struct dc_state *context,
|
||||
|
|
@ -1619,10 +1600,6 @@ enum dc_status dce110_apply_single_controller_ctx_to_hw(
|
|||
hws->funcs.disable_stream_gating(dc, pipe_ctx);
|
||||
}
|
||||
|
||||
if (pipe_ctx->stream->signal == SIGNAL_TYPE_RGB) {
|
||||
dce110_select_crtc_source(pipe_ctx);
|
||||
}
|
||||
|
||||
if (pipe_ctx->stream_res.audio != NULL) {
|
||||
struct audio_output audio_output = {0};
|
||||
|
||||
|
|
@ -1702,8 +1679,7 @@ enum dc_status dce110_apply_single_controller_ctx_to_hw(
|
|||
pipe_ctx->stream_res.tg->funcs->set_static_screen_control(
|
||||
pipe_ctx->stream_res.tg, event_triggers, 2);
|
||||
|
||||
if (!dc_is_virtual_signal(pipe_ctx->stream->signal) &&
|
||||
!dc_is_rgb_signal(pipe_ctx->stream->signal))
|
||||
if (!dc_is_virtual_signal(pipe_ctx->stream->signal))
|
||||
pipe_ctx->stream_res.stream_enc->funcs->dig_connect_to_otg(
|
||||
pipe_ctx->stream_res.stream_enc,
|
||||
pipe_ctx->stream_res.tg->inst);
|
||||
|
|
|
|||
|
|
@ -242,7 +242,8 @@ static const struct dce110_stream_enc_registers stream_enc_regs[] = {
|
|||
stream_enc_regs(3),
|
||||
stream_enc_regs(4),
|
||||
stream_enc_regs(5),
|
||||
stream_enc_regs(6)
|
||||
stream_enc_regs(6),
|
||||
{SR(DAC_SOURCE_SELECT),} /* DACA */
|
||||
};
|
||||
|
||||
static const struct dce_stream_encoder_shift se_shift = {
|
||||
|
|
@ -491,7 +492,8 @@ static struct stream_encoder *dce100_stream_encoder_create(
|
|||
return NULL;
|
||||
|
||||
if (eng_id == ENGINE_ID_DACA || eng_id == ENGINE_ID_DACB) {
|
||||
dce110_analog_stream_encoder_construct(enc110, ctx, ctx->dc_bios, eng_id);
|
||||
dce110_analog_stream_encoder_construct(enc110, ctx, ctx->dc_bios, eng_id,
|
||||
&stream_enc_regs[eng_id], &se_shift, &se_mask);
|
||||
return &enc110->base;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -258,7 +258,9 @@ static const struct dce110_stream_enc_registers stream_enc_regs[] = {
|
|||
stream_enc_regs(2),
|
||||
stream_enc_regs(3),
|
||||
stream_enc_regs(4),
|
||||
stream_enc_regs(5)
|
||||
stream_enc_regs(5),
|
||||
{0},
|
||||
{SR(DAC_SOURCE_SELECT),} /* DACA */
|
||||
};
|
||||
|
||||
static const struct dce_stream_encoder_shift se_shift = {
|
||||
|
|
@ -607,7 +609,8 @@ static struct stream_encoder *dce60_stream_encoder_create(
|
|||
return NULL;
|
||||
|
||||
if (eng_id == ENGINE_ID_DACA || eng_id == ENGINE_ID_DACB) {
|
||||
dce110_analog_stream_encoder_construct(enc110, ctx, ctx->dc_bios, eng_id);
|
||||
dce110_analog_stream_encoder_construct(enc110, ctx, ctx->dc_bios, eng_id,
|
||||
&stream_enc_regs[eng_id], &se_shift, &se_mask);
|
||||
return &enc110->base;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -258,7 +258,8 @@ static const struct dce110_stream_enc_registers stream_enc_regs[] = {
|
|||
stream_enc_regs(3),
|
||||
stream_enc_regs(4),
|
||||
stream_enc_regs(5),
|
||||
stream_enc_regs(6)
|
||||
stream_enc_regs(6),
|
||||
{SR(DAC_SOURCE_SELECT),} /* DACA */
|
||||
};
|
||||
|
||||
static const struct dce_stream_encoder_shift se_shift = {
|
||||
|
|
@ -614,7 +615,8 @@ static struct stream_encoder *dce80_stream_encoder_create(
|
|||
return NULL;
|
||||
|
||||
if (eng_id == ENGINE_ID_DACA || eng_id == ENGINE_ID_DACB) {
|
||||
dce110_analog_stream_encoder_construct(enc110, ctx, ctx->dc_bios, eng_id);
|
||||
dce110_analog_stream_encoder_construct(enc110, ctx, ctx->dc_bios, eng_id,
|
||||
&stream_enc_regs[eng_id], &se_shift, &se_mask);
|
||||
return &enc110->base;
|
||||
}
|
||||
|
||||
|
|
|
|||
Loading…
Reference in New Issue
Block a user