Resguardo inicial

This commit is contained in:
lastdragon
2026-09-06 12:53:21 -06:00
parent 662efe3c2a
commit ad2088d178
94853 changed files with 43200404 additions and 0 deletions
@@ -0,0 +1,69 @@
#
# Copyright 2020-2026 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
#
#
ifdef CONFIG_DRM_AMD_DC_FP
###############################################################################
# DCN30
###############################################################################
HPO_DCN30 = dcn30_hpo_frl_link_encoder.o dcn30_hpo_frl_stream_encoder.o
AMD_DAL_HPO_DCN30 = $(addprefix $(AMDDALPATH)/dc/hpo/dcn30/,$(HPO_DCN30))
AMD_DISPLAY_FILES += $(AMD_DAL_HPO_DCN30)
###############################################################################
# DCN31
###############################################################################
HPO_DCN31 = dcn31_hpo_dp_stream_encoder.o dcn31_hpo_dp_link_encoder.o
AMD_DAL_HPO_DCN31 = $(addprefix $(AMDDALPATH)/dc/hpo/dcn31/,$(HPO_DCN31))
AMD_DISPLAY_FILES += $(AMD_DAL_HPO_DCN31)
###############################################################################
# DCN32
###############################################################################
HPO_DCN32 = dcn32_hpo_dp_link_encoder.o
AMD_DAL_HPO_DCN32 = $(addprefix $(AMDDALPATH)/dc/hpo/dcn32/,$(HPO_DCN32))
AMD_DISPLAY_FILES += $(AMD_DAL_HPO_DCN32)
###############################################################################
# DCN401
###############################################################################
HPO_DCN401 = dcn401_hpo_frl_stream_encoder.o
AMD_DAL_HPO_DCN401 = $(addprefix $(AMDDALPATH)/dc/hpo/dcn401/,$(HPO_DCN401))
AMD_DISPLAY_FILES += $(AMD_DAL_HPO_DCN401)
###############################################################################
# DCN42
###############################################################################
HPO_DCN42 = dcn42_hpo_dp_link_encoder.o
HPO_DCN42 += dcn42_hpo_frl_stream_encoder.o
AMD_DAL_HPO_DCN42 = $(addprefix $(AMDDALPATH)/dc/hpo/dcn42/,$(HPO_DCN42))
AMD_DISPLAY_FILES += $(AMD_DAL_HPO_DCN42)
endif
@@ -0,0 +1,286 @@
/*
* Copyright 2019 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 "core_types.h"
#include "dc_bios_types.h"
#include "dcn30_hpo_frl_link_encoder.h"
#include "reg_helper.h"
#include "dcn10/dcn10_link_encoder.h"
#define DC_LOGGER enc3->base.ctx->logger
#define REG(reg) (enc3->regs->reg)
#undef FN
#define FN(reg_name, field_name) enc3->hpo_le_shift->field_name, enc3->hpo_le_mask->field_name
#define CTX enc3->base.ctx
void hpo_frl_link_enc3_setup_link_encoder(struct hpo_frl_link_encoder *enc,
int lane_count)
{
struct dcn30_hpo_frl_link_encoder *enc3 = DCN30_HPO_FRL_LINK_ENC_FROM_HPO_FRL_LINK_ENC(enc);
DC_LOG_DEBUG("Entering [%s]\n", __func__);
if (enc->ctx->dc->caps.ips_v2_support) {
REG_UPDATE(HDMI_FRL_ENC_MEM_CTRL,
METERBUFFER_MEM_PWR_DIS, 1);
REG_WAIT(HDMI_FRL_ENC_MEM_CTRL, METERBUFFER_MEM_PWR_STATE, 0, 1, 100);
}
/* Enable Link encoder clock */
REG_UPDATE(HDMI_LINK_ENC_CLK_CTRL,
HDMI_LINK_ENC_CLOCK_EN, 1);
/* Configure lane count of FRL encoder */
REG_UPDATE(HDMI_FRL_ENC_CONFIG,
HDMI_LINK_LANE_COUNT, lane_count == 3 ? 0 : 1);
/* Reset link encoder */
REG_UPDATE_2(HDMI_LINK_ENC_CONTROL,
HDMI_LINK_ENC_ENABLE, 0,
HDMI_LINK_ENC_SOFT_RESET, 1);
REG_UPDATE(HDMI_LINK_ENC_CONTROL,
HDMI_LINK_ENC_SOFT_RESET, 0);
/* Enable link encoder */
REG_UPDATE(HDMI_LINK_ENC_CONTROL,
HDMI_LINK_ENC_ENABLE, 1);
DC_LOG_HDMI_FRL("Exiting [%s]\n", __func__);
}
void hpo_frl_link_enc3_set_training_pattern(struct hpo_frl_link_encoder *enc,
uint32_t lane0_pattern,
uint32_t lane1_pattern,
uint32_t lane2_pattern,
uint32_t lane3_pattern)
{
struct dcn30_hpo_frl_link_encoder *enc3 = DCN30_HPO_FRL_LINK_ENC_FROM_HPO_FRL_LINK_ENC(enc);
/* Configure lane count of FRL encoder */
REG_UPDATE(HDMI_FRL_ENC_CONFIG,
HDMI_LINK_TRAINING_ENABLE, 1);
if (lane0_pattern < 8)
REG_UPDATE(HDMI_FRL_ENC_CONFIG,
HDMI_LINK_LANE0_TRAINING_PATTERN, lane0_pattern);
if (lane1_pattern < 8)
REG_UPDATE(HDMI_FRL_ENC_CONFIG,
HDMI_LINK_LANE1_TRAINING_PATTERN, lane1_pattern);
if (lane2_pattern < 8)
REG_UPDATE(HDMI_FRL_ENC_CONFIG,
HDMI_LINK_LANE2_TRAINING_PATTERN, lane2_pattern);
if (lane3_pattern < 8)
REG_UPDATE(HDMI_FRL_ENC_CONFIG,
HDMI_LINK_LANE3_TRAINING_PATTERN, lane3_pattern);
}
void hpo_frl_link_enc3_get_training_pattern(struct hpo_frl_link_encoder *enc,
uint32_t *lane0_pattern,
uint32_t *lane1_pattern,
uint32_t *lane2_pattern,
uint32_t *lane3_pattern)
{
struct dcn30_hpo_frl_link_encoder *enc3 = DCN30_HPO_FRL_LINK_ENC_FROM_HPO_FRL_LINK_ENC(enc);
/* Configure lane count of FRL encoder */
REG_GET_4(HDMI_FRL_ENC_CONFIG,
HDMI_LINK_LANE0_TRAINING_PATTERN, lane0_pattern,
HDMI_LINK_LANE1_TRAINING_PATTERN, lane1_pattern,
HDMI_LINK_LANE2_TRAINING_PATTERN, lane2_pattern,
HDMI_LINK_LANE3_TRAINING_PATTERN, lane3_pattern);
}
static enum bp_result link_transmitter_control(struct dcn10_link_encoder *enc10,
struct bp_transmitter_control *cntl)
{
struct dc_bios *bp = enc10->base.ctx->dc_bios;
return bp->funcs->transmitter_control(bp, cntl);
}
static void hpo_frl_link_enc3_enable_phy_output(struct hpo_frl_link_encoder *hpo_enc,
struct link_encoder *enc,
enum clock_source_id clock_source,
enum hdmi_frl_link_rate frl_link_rate)
{
struct dcn30_hpo_frl_link_encoder *enc3 = DCN30_HPO_FRL_LINK_ENC_FROM_HPO_FRL_LINK_ENC(hpo_enc);
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_TYPE_HDMI_FRL;
cntl.hpd_sel = enc10->base.hpd_source;
switch (frl_link_rate) {
case HDMI_FRL_LINK_RATE_3GBPS:
cntl.pixel_clock = 166667;
break;
case HDMI_FRL_LINK_RATE_6GBPS:
case HDMI_FRL_LINK_RATE_6GBPS_4LANE:
cntl.pixel_clock = 333333;
break;
case HDMI_FRL_LINK_RATE_8GBPS:
cntl.pixel_clock = 444444;
break;
case HDMI_FRL_LINK_RATE_10GBPS:
cntl.pixel_clock = 555555;
break;
case HDMI_FRL_LINK_RATE_12GBPS:
default:
cntl.pixel_clock = 666667;
break;
}
cntl.hpo_engine_id = enc3->base.inst + ENGINE_ID_HPO_0;
if (frl_link_rate <= HDMI_FRL_LINK_RATE_6GBPS)
cntl.lanes_number = 3;
else
cntl.lanes_number = 4;
result = link_transmitter_control(enc10, &cntl);
if (result != BP_RESULT_OK) {
DC_LOG_HDMI_FRL("%s: Failed to execute VBIOS command table!\n", __func__);
BREAK_TO_DEBUGGER();
}
}
void hpo_frl_link_enc3_enable_output(struct hpo_frl_link_encoder *enc)
{
struct dcn30_hpo_frl_link_encoder *enc3 = DCN30_HPO_FRL_LINK_ENC_FROM_HPO_FRL_LINK_ENC(enc);
DC_LOG_HDMI_FRL("Entering [%s]\n", __func__);
/* Enable FRL packet transmission */
REG_UPDATE(HDMI_FRL_ENC_CONFIG,
HDMI_LINK_TRAINING_ENABLE, 0);
DC_LOG_HDMI_FRL("Exiting [%s]\n", __func__);
}
void hpo_frl_link_enc3_disable(struct hpo_frl_link_encoder *enc)
{
struct dcn30_hpo_frl_link_encoder *enc3 = DCN30_HPO_FRL_LINK_ENC_FROM_HPO_FRL_LINK_ENC(enc);
DC_LOG_HDMI_FRL("Entering [%s]\n", __func__);
REG_UPDATE_5(HDMI_FRL_ENC_CONFIG,
HDMI_LINK_TRAINING_ENABLE, 1,
HDMI_LINK_LANE0_TRAINING_PATTERN, 0,
HDMI_LINK_LANE1_TRAINING_PATTERN, 0,
HDMI_LINK_LANE2_TRAINING_PATTERN, 0,
HDMI_LINK_LANE3_TRAINING_PATTERN, 0);
/* Disable link encoder */
REG_UPDATE(HDMI_LINK_ENC_CONTROL,
HDMI_LINK_ENC_ENABLE, 0);
/* Disable Link encoder clock */
REG_UPDATE(HDMI_LINK_ENC_CLK_CTRL,
HDMI_LINK_ENC_CLOCK_EN, 0);
REG_UPDATE(HDMI_FRL_ENC_CONFIG2,
HDMI_LINK_RC_COMPRESS_DISABLE, 0);
DC_LOG_HDMI_FRL("Exiting [%s]\n", __func__);
}
void hpo_frl_link_enc3_read_state(struct hpo_frl_link_encoder *enc,
struct hpo_frl_link_enc_state *state)
{
struct dcn30_hpo_frl_link_encoder *enc3 = DCN30_HPO_FRL_LINK_ENC_FROM_HPO_FRL_LINK_ENC(enc);
unsigned int link_training_enabled;
unsigned int lane_count_field;
ASSERT(state);
REG_GET(HDMI_LINK_ENC_CONTROL,
HDMI_LINK_ENC_ENABLE, &state->link_enc_enabled);
REG_GET_2(HDMI_FRL_ENC_CONFIG,
HDMI_LINK_TRAINING_ENABLE, &link_training_enabled,
HDMI_LINK_LANE_COUNT, &lane_count_field);
state->link_active = link_training_enabled == 1;
if (lane_count_field == 1)
state->lane_count = 4;
else
state->lane_count = 3;
}
void hpo_frl_link_enc3_destroy(struct hpo_frl_link_encoder **enc)
{
kfree(DCN30_HPO_FRL_LINK_ENC_FROM_HPO_FRL_LINK_ENC(*enc));
*enc = NULL;
}
void hpo_frl_link_enc3_apply_vsdb_rcc_wa(struct hpo_frl_link_encoder *enc)
{
struct dcn30_hpo_frl_link_encoder *enc3 =
DCN30_HPO_FRL_LINK_ENC_FROM_HPO_FRL_LINK_ENC(enc);
REG_UPDATE(HDMI_FRL_ENC_CONFIG2,
HDMI_LINK_RC_COMPRESS_DISABLE, 1);
}
static struct hpo_frl_link_encoder_funcs dcn30_hpo_frl_link_encoder_funcs = {
.setup_link_encoder = hpo_frl_link_enc3_setup_link_encoder,
.set_hdmi_training_pattern = hpo_frl_link_enc3_set_training_pattern,
.get_hdmi_training_pattern = hpo_frl_link_enc3_get_training_pattern,
.enable_frl_phy_output = hpo_frl_link_enc3_enable_phy_output,
.enable_output = hpo_frl_link_enc3_enable_output,
.disable_link_encoder = hpo_frl_link_enc3_disable,
.read_state = hpo_frl_link_enc3_read_state,
.destroy = hpo_frl_link_enc3_destroy,
.apply_vsdb_rcc_wa = hpo_frl_link_enc3_apply_vsdb_rcc_wa
};
void hpo_frl_link_encoder3_construct(struct dcn30_hpo_frl_link_encoder *enc3,
struct dc_context *ctx,
uint32_t inst,
const struct dcn30_hpo_frl_link_encoder_registers *hpo_le_regs,
const struct dcn30_hpo_frl_link_encoder_shift *hpo_le_shift,
const struct dcn30_hpo_frl_link_encoder_mask *hpo_le_mask)
{
enc3->base.ctx = ctx;
enc3->base.inst = inst;
enc3->base.funcs = &dcn30_hpo_frl_link_encoder_funcs;
enc3->regs = hpo_le_regs;
enc3->hpo_le_shift = hpo_le_shift;
enc3->hpo_le_mask = hpo_le_mask;
}
@@ -0,0 +1,146 @@
/*
* Copyright 2019 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 __DAL_DCN30_HPO_FRL_LINK_ENCODER_H__
#define __DAL_DCN30_HPO_FRL_LINK_ENCODER_H__
#include "link_encoder.h"
#define DCN30_HPO_FRL_LINK_ENC_FROM_HPO_FRL_LINK_ENC(hpo_frl_link_encoder)\
container_of(hpo_frl_link_encoder, struct dcn30_hpo_frl_link_encoder, base)
#define DCN3_0_HPO_FRL_LINK_ENC_REG_LIST(id) \
SR(HDMI_LINK_ENC_CLK_CTRL), \
SR(HDMI_LINK_ENC_CONTROL), \
SR(HDMI_FRL_ENC_CONFIG), \
SR(HDMI_FRL_ENC_CONFIG2),\
SR(HDMI_FRL_ENC_MEM_CTRL)
struct dcn30_hpo_frl_link_encoder_registers {
uint32_t HDMI_LINK_ENC_CLK_CTRL;
uint32_t HDMI_LINK_ENC_CONTROL;
uint32_t HDMI_FRL_ENC_CONFIG;
uint32_t HDMI_FRL_ENC_CONFIG2;
uint32_t HDMI_FRL_ENC_MEM_CTRL;
};
#define DCN3_0_HPO_FRL_LINK_ENC_MASK_SH_LIST(mask_sh)\
SE_SF(HDMI_LINK_ENC_CLK_CTRL, HDMI_LINK_ENC_CLOCK_EN, mask_sh),\
SE_SF(HDMI_LINK_ENC_CONTROL, HDMI_LINK_ENC_ENABLE, mask_sh),\
SE_SF(HDMI_LINK_ENC_CONTROL, HDMI_LINK_ENC_SOFT_RESET, mask_sh),\
SE_SF(HDMI_FRL_ENC_MEM_CTRL, METERBUFFER_MEM_PWR_DIS, mask_sh),\
SE_SF(HDMI_FRL_ENC_MEM_CTRL, METERBUFFER_MEM_PWR_FORCE, mask_sh),\
SE_SF(HDMI_FRL_ENC_MEM_CTRL, METERBUFFER_MEM_PWR_STATE, mask_sh),\
SE_SF(HDMI_FRL_ENC_MEM_CTRL, METERBUFFER_MEM_DEFAULT_MEM_LOW_POWER_STATE, mask_sh),\
SE_SF(HDMI_FRL_ENC_CONFIG, HDMI_LINK_LANE_COUNT, mask_sh),\
SE_SF(HDMI_FRL_ENC_CONFIG, HDMI_LINK_TRAINING_ENABLE, mask_sh),\
SE_SF(HDMI_FRL_ENC_CONFIG, HDMI_LINK_LANE0_TRAINING_PATTERN, mask_sh),\
SE_SF(HDMI_FRL_ENC_CONFIG, HDMI_LINK_LANE1_TRAINING_PATTERN, mask_sh),\
SE_SF(HDMI_FRL_ENC_CONFIG, HDMI_LINK_LANE2_TRAINING_PATTERN, mask_sh),\
SE_SF(HDMI_FRL_ENC_CONFIG, HDMI_LINK_LANE3_TRAINING_PATTERN, mask_sh),\
SE_SF(HDMI_FRL_ENC_CONFIG2, HDMI_LINK_MAX_JITTER_VALUE, mask_sh),\
SE_SF(HDMI_FRL_ENC_CONFIG2, HDMI_LINK_JITTER_THRESHOLD, mask_sh),\
SE_SF(HDMI_FRL_ENC_CONFIG2, HDMI_LINK_JITTER_CAL_EN, mask_sh),\
SE_SF(HDMI_FRL_ENC_CONFIG2, HDMI_LINK_RC_COMPRESS_DISABLE, mask_sh),\
SE_SF(HDMI_FRL_ENC_CONFIG2, HDMI_FRL_HDMISTREAMCLK_DB_SEL, mask_sh),\
SE_SF(HDMI_FRL_ENC_CONFIG2, HDMI_LINK_MAX_JITTER_VALUE_RESET, mask_sh),\
SE_SF(HDMI_FRL_ENC_CONFIG2, HDMI_LINK_JITTER_EXCEED_STATUS, mask_sh),\
SE_SF(HDMI_FRL_ENC_CONFIG2, HDMI_LINK_METER_BUFFER_OVERFLOW_STATUS, mask_sh)
#define HPO_FRL_LINK_ENC_DCN3_REG_FIELD_LIST(type) \
type HDMI_LINK_ENC_CLOCK_EN;\
type HDMI_LINK_ENC_ENABLE;\
type HDMI_LINK_ENC_SOFT_RESET;\
type HDMI_LINK_LANE_COUNT;\
type HDMI_LINK_TRAINING_ENABLE;\
type HDMI_LINK_LANE0_TRAINING_PATTERN;\
type HDMI_LINK_LANE1_TRAINING_PATTERN;\
type HDMI_LINK_LANE2_TRAINING_PATTERN;\
type HDMI_LINK_LANE3_TRAINING_PATTERN;\
type HDMI_LINK_MAX_JITTER_VALUE;\
type HDMI_LINK_JITTER_THRESHOLD;\
type HDMI_LINK_JITTER_CAL_EN;\
type HDMI_LINK_RC_COMPRESS_DISABLE;\
type METERBUFFER_MEM_PWR_DIS;\
type METERBUFFER_MEM_PWR_STATE;\
type METERBUFFER_MEM_PWR_FORCE;\
type METERBUFFER_MEM_DEFAULT_MEM_LOW_POWER_STATE;\
type HDMI_FRL_HDMISTREAMCLK_DB_SEL;\
type HDMI_LINK_MAX_JITTER_VALUE_RESET;\
type HDMI_LINK_JITTER_EXCEED_STATUS;\
type HDMI_LINK_METER_BUFFER_OVERFLOW_STATUS
struct dcn30_hpo_frl_link_encoder_shift {
HPO_FRL_LINK_ENC_DCN3_REG_FIELD_LIST(uint8_t);
};
struct dcn30_hpo_frl_link_encoder_mask {
HPO_FRL_LINK_ENC_DCN3_REG_FIELD_LIST(uint32_t);
};
struct dcn30_hpo_frl_link_encoder {
struct hpo_frl_link_encoder base;
const struct dcn30_hpo_frl_link_encoder_registers *regs;
const struct dcn30_hpo_frl_link_encoder_shift *hpo_le_shift;
const struct dcn30_hpo_frl_link_encoder_mask *hpo_le_mask;
};
void hpo_frl_link_enc3_setup_link_encoder(struct hpo_frl_link_encoder *enc,
int lane_count);
void hpo_frl_link_enc3_set_training_pattern(struct hpo_frl_link_encoder *enc,
uint32_t lane0_pattern,
uint32_t lane1_pattern,
uint32_t lane2_pattern,
uint32_t lane3_pattern);
void hpo_frl_link_enc3_get_training_pattern(struct hpo_frl_link_encoder *enc,
uint32_t *lane0_pattern,
uint32_t *lane1_pattern,
uint32_t *lane2_pattern,
uint32_t *lane3_pattern);
void hpo_frl_link_enc3_enable_output(struct hpo_frl_link_encoder *enc);
void hpo_frl_link_enc3_disable(struct hpo_frl_link_encoder *enc);
void hpo_frl_link_enc3_read_state(struct hpo_frl_link_encoder *enc,
struct hpo_frl_link_enc_state *state);
void hpo_frl_link_enc3_destroy(struct hpo_frl_link_encoder **enc);
void hpo_frl_link_enc3_apply_vsdb_rcc_wa(struct hpo_frl_link_encoder *enc);
void hpo_frl_link_encoder3_construct(struct dcn30_hpo_frl_link_encoder *enc3,
struct dc_context *ctx,
uint32_t inst,
const struct dcn30_hpo_frl_link_encoder_registers *hpo_le_regs,
const struct dcn30_hpo_frl_link_encoder_shift *hpo_le_shift,
const struct dcn30_hpo_frl_link_encoder_mask *hpo_le_mask);
#endif
@@ -0,0 +1,436 @@
/*
* Copyright 2019 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_HPO_FRL_STREAM_ENCODER_DCN30_H__
#define __DC_HPO_FRL_STREAM_ENCODER_DCN30_H__
#include "dcn30/dcn30_vpg.h"
#include "dcn30/dcn30_afmt.h"
#include "stream_encoder.h"
#include "dml/dml1_frl_cap_chk.h"
#define DCN30_HPO_FRL_STRENC_FROM_HPO_FRL_STRENC(hpo_frl_stream_encoder)\
container_of(hpo_frl_stream_encoder, struct dcn30_hpo_frl_stream_encoder, base)
#define SE_SF(reg_name, field_name, post_fix)\
.field_name = reg_name ## __ ## field_name ## post_fix
#define DCN3_0_HDMI_STREAM_ENC_REG_LIST \
SR(HDMI_STREAM_ENC_CLOCK_CONTROL), \
SR(HDMI_STREAM_ENC_INPUT_MUX_CONTROL), \
SR(HDMI_STREAM_ENC_CLOCK_RAMP_ADJUSTER_FIFO_STATUS_CONTROL0), \
SR(HDMI_STREAM_ENC_CLOCK_RAMP_ADJUSTER_FIFO_STATUS_CONTROL2)
#define DCN3_0_HDMI_TB_ENC_REG_LIST \
SR(HDMI_TB_ENC_CONTROL), \
SR(HDMI_TB_ENC_H_ACTIVE_BLANK), \
SR(HDMI_TB_ENC_HC_ACTIVE_BLANK), \
SR(HDMI_TB_ENC_MODE), \
SR(HDMI_TB_ENC_PACKET_CONTROL), \
SR(HDMI_TB_ENC_DB_CONTROL), \
SR(HDMI_TB_ENC_PIXEL_FORMAT), \
SR(HDMI_TB_ENC_VBI_PACKET_CONTROL1), \
SR(HDMI_TB_ENC_GC_CONTROL), \
SR(HDMI_TB_ENC_GENERIC_PACKET_CONTROL0), \
SR(HDMI_TB_ENC_GENERIC_PACKET_CONTROL1), \
SR(HDMI_TB_ENC_GENERIC_PACKET0_1_LINE), \
SR(HDMI_TB_ENC_GENERIC_PACKET2_3_LINE), \
SR(HDMI_TB_ENC_GENERIC_PACKET4_5_LINE), \
SR(HDMI_TB_ENC_GENERIC_PACKET6_7_LINE), \
SR(HDMI_TB_ENC_GENERIC_PACKET8_9_LINE), \
SR(HDMI_TB_ENC_GENERIC_PACKET10_11_LINE), \
SR(HDMI_TB_ENC_GENERIC_PACKET12_13_LINE), \
SR(HDMI_TB_ENC_GENERIC_PACKET14_LINE), \
SR(HDMI_TB_ENC_ACR_PACKET_CONTROL), \
SR(HDMI_TB_ENC_ACR_32_0), \
SR(HDMI_TB_ENC_ACR_32_1), \
SR(HDMI_TB_ENC_ACR_44_0), \
SR(HDMI_TB_ENC_ACR_44_1), \
SR(HDMI_TB_ENC_ACR_48_0), \
SR(HDMI_TB_ENC_ACR_48_1), \
SR(HDMI_TB_ENC_CRC_CNTL),\
SR(HDMI_TB_ENC_METADATA_PACKET_CONTROL)
#define DCN3_0_HPO_FRL_STREAM_ENC_REG_LIST(id) \
DCN3_0_HDMI_STREAM_ENC_REG_LIST, \
DCN3_0_HDMI_TB_ENC_REG_LIST
#define DCN3_0_HPO_STREAM_ENC_DME_REG_LIST(id, offset) \
[id - offset]SRI(DME_CONTROL, DME, id)
struct dcn30_hpo_frl_stream_enc_registers {
uint32_t HDMI_STREAM_ENC_CLOCK_CONTROL;
uint32_t HDMI_STREAM_ENC_INPUT_MUX_CONTROL;
uint32_t HDMI_STREAM_ENC_CLOCK_RAMP_ADJUSTER_FIFO_STATUS_CONTROL0;
uint32_t HDMI_STREAM_ENC_CLOCK_RAMP_ADJUSTER_FIFO_STATUS_CONTROL2;
uint32_t HDMI_STREAM_ENC_AUDIO_CONTROL;
uint32_t HDMI_TB_ENC_CONTROL;
uint32_t HDMI_TB_ENC_MODE;
uint32_t HDMI_TB_ENC_H_ACTIVE_BLANK;
uint32_t HDMI_TB_ENC_HC_ACTIVE_BLANK;
uint32_t HDMI_TB_ENC_PACKET_CONTROL;
uint32_t HDMI_TB_ENC_DB_CONTROL;
uint32_t HDMI_TB_ENC_PIXEL_FORMAT;
uint32_t HDMI_TB_ENC_VBI_PACKET_CONTROL1;
uint32_t HDMI_TB_ENC_GC_CONTROL;
uint32_t HDMI_TB_ENC_GENERIC_PACKET_CONTROL0;
uint32_t HDMI_TB_ENC_GENERIC_PACKET_CONTROL1;
uint32_t HDMI_TB_ENC_GENERIC_PACKET0_1_LINE;
uint32_t HDMI_TB_ENC_GENERIC_PACKET2_3_LINE;
uint32_t HDMI_TB_ENC_GENERIC_PACKET4_5_LINE;
uint32_t HDMI_TB_ENC_GENERIC_PACKET6_7_LINE;
uint32_t HDMI_TB_ENC_GENERIC_PACKET8_9_LINE;
uint32_t HDMI_TB_ENC_GENERIC_PACKET10_11_LINE;
uint32_t HDMI_TB_ENC_GENERIC_PACKET12_13_LINE;
uint32_t HDMI_TB_ENC_GENERIC_PACKET14_LINE;
uint32_t HDMI_TB_ENC_ACR_PACKET_CONTROL;
uint32_t HDMI_TB_ENC_ACR_32_0;
uint32_t HDMI_TB_ENC_ACR_32_1;
uint32_t HDMI_TB_ENC_ACR_44_0;
uint32_t HDMI_TB_ENC_ACR_44_1;
uint32_t HDMI_TB_ENC_ACR_48_0;
uint32_t HDMI_TB_ENC_ACR_48_1;
uint32_t HDMI_TB_ENC_CRC_CNTL;
uint32_t DME_CONTROL;
uint32_t HDMI_TB_ENC_METADATA_PACKET_CONTROL;
uint32_t HDMI_TB_ENC_MEM_CTRL;
uint32_t HDMI_FRL_ENC_MEM_CTRL;
};
#define DCN3_0_HDMI_STREAM_ENC_MASK_SH_LIST(mask_sh)\
SE_SF(HDMI_STREAM_ENC_INPUT_MUX_CONTROL, HDMI_STREAM_ENC_INPUT_MUX_SOURCE_SEL, mask_sh),\
SE_SF(HDMI_STREAM_ENC_CLOCK_RAMP_ADJUSTER_FIFO_STATUS_CONTROL0, FIFO_ENABLE, mask_sh),\
SE_SF(HDMI_STREAM_ENC_CLOCK_RAMP_ADJUSTER_FIFO_STATUS_CONTROL0, FIFO_RESET, mask_sh),\
SE_SF(HDMI_STREAM_ENC_CLOCK_RAMP_ADJUSTER_FIFO_STATUS_CONTROL0, FIFO_RESET_DONE, mask_sh),\
SE_SF(HDMI_STREAM_ENC_CLOCK_RAMP_ADJUSTER_FIFO_STATUS_CONTROL0, FIFO_PIXEL_ENCODING, mask_sh),\
SE_SF(HDMI_STREAM_ENC_CLOCK_CONTROL, HDMI_STREAM_ENC_CLOCK_EN, mask_sh),\
SE_SF(HDMI_STREAM_ENC_CLOCK_RAMP_ADJUSTER_FIFO_STATUS_CONTROL0, FIFO_ODM_COMBINE_MODE, mask_sh),\
SE_SF(HDMI_STREAM_ENC_CLOCK_RAMP_ADJUSTER_FIFO_STATUS_CONTROL0, FIFO_DSC_MODE, mask_sh),\
SE_SF(HDMI_STREAM_ENC_CLOCK_RAMP_ADJUSTER_FIFO_STATUS_CONTROL2, FIFO_DB_DISABLE, mask_sh),\
SE_SF(HDMI_STREAM_ENC_CLOCK_RAMP_ADJUSTER_FIFO_STATUS_CONTROL2, FIFO_DB_DISABLE, mask_sh),\
SE_SF(DME0_DME_CONTROL, METADATA_HUBP_REQUESTOR_ID, mask_sh),\
SE_SF(DME0_DME_CONTROL, METADATA_ENGINE_EN, mask_sh),\
SE_SF(DME0_DME_CONTROL, METADATA_STREAM_TYPE, mask_sh),\
SE_SF(HDMI_TB_ENC_MEM_CTRL, BORROWBUFFER_MEM_PWR_DIS, mask_sh),\
SE_SF(HDMI_TB_ENC_MEM_CTRL, BORROWBUFFER_MEM_PWR_FORCE, mask_sh),\
SE_SF(HDMI_TB_ENC_MEM_CTRL, BORROWBUFFER_MEM_PWR_STATE, mask_sh),\
SE_SF(HDMI_TB_ENC_MEM_CTRL, BORROWBUFFER_MEM_DEFAULT_MEM_LOW_POWER_STATE, mask_sh),\
SE_SF(HDMI_TB_ENC_METADATA_PACKET_CONTROL, HDMI_METADATA_PACKET_ENABLE, mask_sh),\
SE_SF(HDMI_TB_ENC_METADATA_PACKET_CONTROL, HDMI_METADATA_PACKET_LINE_REFERENCE, mask_sh),\
SE_SF(HDMI_TB_ENC_METADATA_PACKET_CONTROL, HDMI_METADATA_PACKET_MISSED, mask_sh),\
SE_SF(HDMI_TB_ENC_METADATA_PACKET_CONTROL, HDMI_METADATA_PACKET_LINE, mask_sh)
#define DCN3_0_HDMI_TB_ENC_MASK_SH_LIST(mask_sh)\
SE_SF(HDMI_TB_ENC_CONTROL, HDMI_TB_ENC_EN, mask_sh),\
SE_SF(HDMI_TB_ENC_CONTROL, HDMI_RESET, mask_sh),\
SE_SF(HDMI_TB_ENC_CONTROL, HDMI_RESET_DONE, mask_sh),\
SE_SF(HDMI_TB_ENC_MODE, HDMI_BORROW_MODE, mask_sh),\
SE_SF(HDMI_TB_ENC_H_ACTIVE_BLANK, HDMI_H_ACTIVE, mask_sh),\
SE_SF(HDMI_TB_ENC_H_ACTIVE_BLANK, HDMI_H_BLANK, mask_sh),\
SE_SF(HDMI_TB_ENC_HC_ACTIVE_BLANK, HDMI_HC_ACTIVE, mask_sh),\
SE_SF(HDMI_TB_ENC_HC_ACTIVE_BLANK, HDMI_HC_BLANK, mask_sh),\
SE_SF(HDMI_TB_ENC_PACKET_CONTROL, HDMI_MAX_PACKETS_PER_LINE, mask_sh),\
SE_SF(HDMI_TB_ENC_DB_CONTROL, HDMI_DB_DISABLE, mask_sh),\
SE_SF(HDMI_TB_ENC_PIXEL_FORMAT, HDMI_PIXEL_ENCODING, mask_sh),\
SE_SF(HDMI_TB_ENC_PIXEL_FORMAT, HDMI_DEEP_COLOR_DEPTH, mask_sh),\
SE_SF(HDMI_TB_ENC_PIXEL_FORMAT, HDMI_DEEP_COLOR_ENABLE, mask_sh),\
SE_SF(HDMI_TB_ENC_PIXEL_FORMAT, HDMI_DSC_MODE, mask_sh),\
SE_SF(HDMI_TB_ENC_VBI_PACKET_CONTROL1, HDMI_GC_CONT, mask_sh),\
SE_SF(HDMI_TB_ENC_VBI_PACKET_CONTROL1, HDMI_GC_SEND, mask_sh),\
SE_SF(HDMI_TB_ENC_VBI_PACKET_CONTROL1, HDMI_ACP_SEND, mask_sh),\
SE_SF(HDMI_TB_ENC_VBI_PACKET_CONTROL1, HDMI_AUDIO_INFO_SEND, mask_sh),\
SE_SF(HDMI_TB_ENC_VBI_PACKET_CONTROL1, HDMI_AUDIO_INFO_LINE, mask_sh),\
SE_SF(HDMI_TB_ENC_GC_CONTROL, HDMI_GC_AVMUTE, mask_sh),\
SE_SF(HDMI_TB_ENC_GENERIC_PACKET_CONTROL0, HDMI_GENERIC0_CONT, mask_sh),\
SE_SF(HDMI_TB_ENC_GENERIC_PACKET_CONTROL0, HDMI_GENERIC1_CONT, mask_sh),\
SE_SF(HDMI_TB_ENC_GENERIC_PACKET_CONTROL0, HDMI_GENERIC2_CONT, mask_sh),\
SE_SF(HDMI_TB_ENC_GENERIC_PACKET_CONTROL0, HDMI_GENERIC3_CONT, mask_sh),\
SE_SF(HDMI_TB_ENC_GENERIC_PACKET_CONTROL0, HDMI_GENERIC4_CONT, mask_sh),\
SE_SF(HDMI_TB_ENC_GENERIC_PACKET_CONTROL0, HDMI_GENERIC5_CONT, mask_sh),\
SE_SF(HDMI_TB_ENC_GENERIC_PACKET_CONTROL0, HDMI_GENERIC6_CONT, mask_sh),\
SE_SF(HDMI_TB_ENC_GENERIC_PACKET_CONTROL0, HDMI_GENERIC7_CONT, mask_sh),\
SE_SF(HDMI_TB_ENC_GENERIC_PACKET_CONTROL1, HDMI_GENERIC8_CONT, mask_sh),\
SE_SF(HDMI_TB_ENC_GENERIC_PACKET_CONTROL1, HDMI_GENERIC9_CONT, mask_sh),\
SE_SF(HDMI_TB_ENC_GENERIC_PACKET_CONTROL1, HDMI_GENERIC10_CONT, mask_sh),\
SE_SF(HDMI_TB_ENC_GENERIC_PACKET_CONTROL1, HDMI_GENERIC11_CONT, mask_sh),\
SE_SF(HDMI_TB_ENC_GENERIC_PACKET_CONTROL1, HDMI_GENERIC12_CONT, mask_sh),\
SE_SF(HDMI_TB_ENC_GENERIC_PACKET_CONTROL1, HDMI_GENERIC13_CONT, mask_sh),\
SE_SF(HDMI_TB_ENC_GENERIC_PACKET_CONTROL1, HDMI_GENERIC14_CONT, mask_sh),\
SE_SF(HDMI_TB_ENC_GENERIC_PACKET_CONTROL0, HDMI_GENERIC0_SEND, mask_sh),\
SE_SF(HDMI_TB_ENC_GENERIC_PACKET_CONTROL0, HDMI_GENERIC1_SEND, mask_sh),\
SE_SF(HDMI_TB_ENC_GENERIC_PACKET_CONTROL0, HDMI_GENERIC2_SEND, mask_sh),\
SE_SF(HDMI_TB_ENC_GENERIC_PACKET_CONTROL0, HDMI_GENERIC3_SEND, mask_sh),\
SE_SF(HDMI_TB_ENC_GENERIC_PACKET_CONTROL0, HDMI_GENERIC4_SEND, mask_sh),\
SE_SF(HDMI_TB_ENC_GENERIC_PACKET_CONTROL0, HDMI_GENERIC5_SEND, mask_sh),\
SE_SF(HDMI_TB_ENC_GENERIC_PACKET_CONTROL0, HDMI_GENERIC6_SEND, mask_sh),\
SE_SF(HDMI_TB_ENC_GENERIC_PACKET_CONTROL0, HDMI_GENERIC7_SEND, mask_sh),\
SE_SF(HDMI_TB_ENC_GENERIC_PACKET_CONTROL1, HDMI_GENERIC8_SEND, mask_sh),\
SE_SF(HDMI_TB_ENC_GENERIC_PACKET_CONTROL1, HDMI_GENERIC9_SEND, mask_sh),\
SE_SF(HDMI_TB_ENC_GENERIC_PACKET_CONTROL1, HDMI_GENERIC10_SEND, mask_sh),\
SE_SF(HDMI_TB_ENC_GENERIC_PACKET_CONTROL1, HDMI_GENERIC11_SEND, mask_sh),\
SE_SF(HDMI_TB_ENC_GENERIC_PACKET_CONTROL1, HDMI_GENERIC12_SEND, mask_sh),\
SE_SF(HDMI_TB_ENC_GENERIC_PACKET_CONTROL1, HDMI_GENERIC13_SEND, mask_sh),\
SE_SF(HDMI_TB_ENC_GENERIC_PACKET_CONTROL1, HDMI_GENERIC14_SEND, mask_sh),\
SE_SF(HDMI_TB_ENC_GENERIC_PACKET0_1_LINE, HDMI_GENERIC0_LINE, mask_sh),\
SE_SF(HDMI_TB_ENC_GENERIC_PACKET0_1_LINE, HDMI_GENERIC1_LINE, mask_sh),\
SE_SF(HDMI_TB_ENC_GENERIC_PACKET2_3_LINE, HDMI_GENERIC2_LINE, mask_sh),\
SE_SF(HDMI_TB_ENC_GENERIC_PACKET2_3_LINE, HDMI_GENERIC3_LINE, mask_sh),\
SE_SF(HDMI_TB_ENC_GENERIC_PACKET4_5_LINE, HDMI_GENERIC4_LINE, mask_sh),\
SE_SF(HDMI_TB_ENC_GENERIC_PACKET4_5_LINE, HDMI_GENERIC5_LINE, mask_sh),\
SE_SF(HDMI_TB_ENC_GENERIC_PACKET6_7_LINE, HDMI_GENERIC6_LINE, mask_sh),\
SE_SF(HDMI_TB_ENC_GENERIC_PACKET6_7_LINE, HDMI_GENERIC7_LINE, mask_sh),\
SE_SF(HDMI_TB_ENC_GENERIC_PACKET8_9_LINE, HDMI_GENERIC8_LINE, mask_sh),\
SE_SF(HDMI_TB_ENC_GENERIC_PACKET8_9_LINE, HDMI_GENERIC9_LINE, mask_sh),\
SE_SF(HDMI_TB_ENC_GENERIC_PACKET10_11_LINE, HDMI_GENERIC10_LINE, mask_sh),\
SE_SF(HDMI_TB_ENC_GENERIC_PACKET10_11_LINE, HDMI_GENERIC11_LINE, mask_sh),\
SE_SF(HDMI_TB_ENC_GENERIC_PACKET12_13_LINE, HDMI_GENERIC12_LINE, mask_sh),\
SE_SF(HDMI_TB_ENC_GENERIC_PACKET12_13_LINE, HDMI_GENERIC13_LINE, mask_sh),\
SE_SF(HDMI_TB_ENC_GENERIC_PACKET14_LINE, HDMI_GENERIC14_LINE, mask_sh),\
SE_SF(HDMI_TB_ENC_ACR_PACKET_CONTROL, HDMI_ACR_AUTO_SEND, mask_sh),\
SE_SF(HDMI_TB_ENC_ACR_PACKET_CONTROL, HDMI_ACR_SOURCE, mask_sh),\
SE_SF(HDMI_TB_ENC_ACR_PACKET_CONTROL, HDMI_ACR_AUDIO_PRIORITY, mask_sh),\
SE_SF(HDMI_TB_ENC_ACR_32_0, HDMI_ACR_CTS_32, mask_sh),\
SE_SF(HDMI_TB_ENC_ACR_32_1, HDMI_ACR_N_32, mask_sh),\
SE_SF(HDMI_TB_ENC_ACR_44_0, HDMI_ACR_CTS_44, mask_sh),\
SE_SF(HDMI_TB_ENC_ACR_44_1, HDMI_ACR_N_44, mask_sh),\
SE_SF(HDMI_TB_ENC_ACR_48_0, HDMI_ACR_CTS_48, mask_sh),\
SE_SF(HDMI_TB_ENC_ACR_48_1, HDMI_ACR_N_48, mask_sh),\
SE_SF(HDMI_TB_ENC_CRC_CNTL, HDMI_CRC_EN, mask_sh),\
SE_SF(HDMI_TB_ENC_CRC_CNTL, HDMI_CRC_CONT_EN, mask_sh)
#define DCN3_0_HPO_STREAM_ENC_MASK_SH_LIST(mask_sh)\
DCN3_0_HDMI_STREAM_ENC_MASK_SH_LIST(mask_sh),\
DCN3_0_HDMI_TB_ENC_MASK_SH_LIST(mask_sh)
#define DCN3_HDMI_TB_ENC_REG_FIELD_LIST(type) \
type HDMI_TB_ENC_EN;\
type HDMI_RESET;\
type HDMI_RESET_DONE;\
type HDMI_STREAM_ENC_CLOCK_EN;\
type HDMI_STREAM_ENC_INPUT_MUX_SOURCE_SEL;\
type HDMI_MAX_PACKETS_PER_LINE;\
type FIFO_ENABLE;\
type FIFO_RESET;\
type FIFO_RESET_DONE;\
type FIFO_PIXEL_ENCODING;\
type FIFO_ODM_COMBINE_MODE;\
type FIFO_DSC_MODE;\
type FIFO_DB_DISABLE;\
type HDMI_BORROW_MODE;\
type HDMI_H_ACTIVE;\
type HDMI_H_BLANK;\
type HDMI_HC_ACTIVE;\
type HDMI_HC_BLANK;\
type HDMI_DB_DISABLE;\
type HDMI_PIXEL_ENCODING;\
type HDMI_DEEP_COLOR_DEPTH;\
type HDMI_DEEP_COLOR_ENABLE;\
type HDMI_ODM_COMBINE_MODE;\
type HDMI_DSC_MODE;\
type HDMI_GC_CONT;\
type HDMI_GC_SEND;\
type HDMI_ACP_SEND;\
type HDMI_AUDIO_INFO_SEND;\
type HDMI_AUDIO_INFO_LINE;\
type HDMI_GC_AVMUTE;\
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 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 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 HDMI_CRC_EN;\
type HDMI_CRC_CONT_EN;\
type METADATA_HUBP_REQUESTOR_ID;\
type METADATA_ENGINE_EN;\
type METADATA_STREAM_TYPE;\
type HDMI_METADATA_PACKET_ENABLE;\
type HDMI_METADATA_PACKET_LINE_REFERENCE;\
type HDMI_METADATA_PACKET_MISSED;\
type HDMI_METADATA_PACKET_LINE;\
type BORROWBUFFER_MEM_PWR_DIS;\
type BORROWBUFFER_MEM_PWR_FORCE;\
type BORROWBUFFER_MEM_PWR_STATE;\
type BORROWBUFFER_MEM_DEFAULT_MEM_LOW_POWER_STATE
struct dcn30_hpo_frl_stream_encoder_shift {
DCN3_HDMI_TB_ENC_REG_FIELD_LIST(uint8_t);
};
struct dcn30_hpo_frl_stream_encoder_mask {
DCN3_HDMI_TB_ENC_REG_FIELD_LIST(uint32_t);
};
struct dcn30_hpo_frl_stream_encoder {
struct hpo_frl_stream_encoder base;
const struct dcn30_hpo_frl_stream_enc_registers *regs;
const struct dcn30_hpo_frl_stream_encoder_shift *hpo_se_shift;
const struct dcn30_hpo_frl_stream_encoder_mask *hpo_se_mask;
};
void hpo_enc3_enable(
struct hpo_frl_stream_encoder *enc,
int otg_inst);
void hpo_enc3_unblank(
struct hpo_frl_stream_encoder *enc,
int otg_inst);
void hpo_enc3_read_state(
struct hpo_frl_stream_encoder *enc,
struct hpo_frl_stream_encoder_state *state);
bool hpo_enc3_fifo_odm_enabled(
struct hpo_frl_stream_encoder *enc);
void hpo_enc3_blank(
struct hpo_frl_stream_encoder *enc);
void hpo_enc3_set_hdmi_stream_attribute(
struct hpo_frl_stream_encoder *enc,
struct dc_crtc_timing *crtc_timing,
struct frl_borrow_params *borrow_params,
int odm_combine_num_segments);
void hpo_enc3_update_hdmi_info_packet(
struct dcn30_hpo_frl_stream_encoder *enc3,
uint32_t packet_index,
const struct dc_info_packet *info_packet);
void hpo_enc3_update_hdmi_info_packets(
struct hpo_frl_stream_encoder *enc,
const struct encoder_info_frame *info_frame);
void hpo_enc3_hdmi_set_dsc_config(
struct hpo_frl_stream_encoder *enc,
struct dc_crtc_timing *timing,
uint8_t *dsc_packed_pps);
void hpo_enc3_stop_hdmi_info_packets(
struct hpo_frl_stream_encoder *enc);
void hpo_enc3_setup_hdmi_audio(
struct hpo_frl_stream_encoder *enc,
const struct audio_crtc_info *crtc_info);
void hpo_enc3_hdmi_audio_setup(
struct hpo_frl_stream_encoder *enc,
unsigned int az_inst,
struct audio_info *info,
struct audio_crtc_info *audio_crtc_info);
void hpo_enc3_hdmi_audio_disable(
struct hpo_frl_stream_encoder *enc);
void hpo_enc3_audio_mute_control(
struct hpo_frl_stream_encoder *enc,
bool mute);
void enc3_stream_encoder_set_avmute(
struct hpo_frl_stream_encoder *enc,
bool enable);
bool hpo_enc3_validate_hdmi_frl_output(
struct hpo_frl_stream_encoder *enc,
const struct dc_crtc_timing *timing,
const struct audio_check *audio,
struct dc_hdmi_frl_link_settings *frl_link_settings,
unsigned int dsc_max_rate);
void hpo_enc3_set_dynamic_metadata(
struct hpo_frl_stream_encoder *enc,
bool enable_dme,
uint32_t hubp_requestor_id,
enum dynamic_metadata_mode dmdata_mode);
void dcn30_hpo_frl_stream_encoder_construct(
struct dcn30_hpo_frl_stream_encoder *enc3,
struct dc_context *ctx,
struct dc_bios *bp,
enum engine_id eng_id,
struct vpg *vpg,
struct afmt *afmt,
const struct dcn30_hpo_frl_stream_enc_registers *regs,
const struct dcn30_hpo_frl_stream_encoder_shift *hpo_se_shift,
const struct dcn30_hpo_frl_stream_encoder_mask *hpo_se_mask);
void convert_dc_info_packet_to_128(
const struct dc_info_packet *info_packet,
struct dc_info_packet_128 *info_packet_128);
#endif
@@ -0,0 +1,628 @@
/*
* Copyright 2019 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 "dcn31_hpo_dp_link_encoder.h"
#include "reg_helper.h"
#include "stream_encoder.h"
#define DC_LOGGER \
enc3->base.ctx->logger
#define REG(reg)\
(enc3->regs->reg)
#undef FN
#define FN(reg_name, field_name) \
enc3->hpo_le_shift->field_name, enc3->hpo_le_mask->field_name
#define CTX \
enc3->base.ctx
enum {
DP_SAT_UPDATE_MAX_RETRY = 200
};
void dcn31_hpo_dp_link_enc_enable(
struct hpo_dp_link_encoder *enc,
enum dc_lane_count num_lanes)
{
struct dcn31_hpo_dp_link_encoder *enc3 = DCN3_1_HPO_DP_LINK_ENC_FROM_HPO_LINK_ENC(enc);
uint32_t dp_link_enabled;
/* get current status of link enabled */
REG_GET(DP_DPHY_SYM32_STATUS,
STATUS, &dp_link_enabled);
/* Enable clocks first */
REG_UPDATE(DP_LINK_ENC_CLOCK_CONTROL, DP_LINK_ENC_CLOCK_EN, 1);
/* Reset DPHY. Only reset if going from disable to enable */
if (!dp_link_enabled) {
REG_UPDATE(DP_DPHY_SYM32_CONTROL, DPHY_RESET, 1);
REG_UPDATE(DP_DPHY_SYM32_CONTROL, DPHY_RESET, 0);
}
/* Configure DPHY settings */
REG_UPDATE_3(DP_DPHY_SYM32_CONTROL,
DPHY_ENABLE, 1,
PRECODER_ENABLE, 1,
NUM_LANES, num_lanes == LANE_COUNT_ONE ? 0 : num_lanes == LANE_COUNT_TWO ? 1 : 3);
}
void dcn31_hpo_dp_link_enc_disable(
struct hpo_dp_link_encoder *enc)
{
struct dcn31_hpo_dp_link_encoder *enc3 = DCN3_1_HPO_DP_LINK_ENC_FROM_HPO_LINK_ENC(enc);
/* Configure DPHY settings */
REG_UPDATE(DP_DPHY_SYM32_CONTROL,
DPHY_ENABLE, 0);
/* Shut down clock last */
REG_UPDATE(DP_LINK_ENC_CLOCK_CONTROL, DP_LINK_ENC_CLOCK_EN, 0);
}
void dcn31_hpo_dp_link_enc_set_link_test_pattern(
struct hpo_dp_link_encoder *enc,
struct encoder_set_dp_phy_pattern_param *tp_params)
{
struct dcn31_hpo_dp_link_encoder *enc3 = DCN3_1_HPO_DP_LINK_ENC_FROM_HPO_LINK_ENC(enc);
uint32_t tp_custom;
switch (tp_params->dp_phy_pattern) {
case DP_TEST_PATTERN_VIDEO_MODE:
REG_UPDATE(DP_DPHY_SYM32_CONTROL,
MODE, DP2_LINK_ACTIVE);
break;
case DP_TEST_PATTERN_128b_132b_TPS1_TRAINING_MODE:
REG_UPDATE(DP_DPHY_SYM32_CONTROL,
MODE, DP2_LINK_TRAINING_TPS1);
break;
case DP_TEST_PATTERN_128b_132b_TPS2_TRAINING_MODE:
REG_UPDATE(DP_DPHY_SYM32_CONTROL,
MODE, DP2_LINK_TRAINING_TPS2);
break;
case DP_TEST_PATTERN_128b_132b_TPS1:
REG_UPDATE_4(DP_DPHY_SYM32_TP_CONFIG,
TP_SELECT0, DP_DPHY_TP_SELECT_TPS1,
TP_SELECT1, DP_DPHY_TP_SELECT_TPS1,
TP_SELECT2, DP_DPHY_TP_SELECT_TPS1,
TP_SELECT3, DP_DPHY_TP_SELECT_TPS1);
REG_UPDATE(DP_DPHY_SYM32_CONTROL,
MODE, DP2_TEST_PATTERN);
break;
case DP_TEST_PATTERN_128b_132b_TPS2:
REG_UPDATE_4(DP_DPHY_SYM32_TP_CONFIG,
TP_SELECT0, DP_DPHY_TP_SELECT_TPS2,
TP_SELECT1, DP_DPHY_TP_SELECT_TPS2,
TP_SELECT2, DP_DPHY_TP_SELECT_TPS2,
TP_SELECT3, DP_DPHY_TP_SELECT_TPS2);
REG_UPDATE(DP_DPHY_SYM32_CONTROL,
MODE, DP2_TEST_PATTERN);
break;
case DP_TEST_PATTERN_PRBS7:
REG_UPDATE_4(DP_DPHY_SYM32_TP_CONFIG,
TP_PRBS_SEL0, DP_DPHY_TP_PRBS7,
TP_PRBS_SEL1, DP_DPHY_TP_PRBS7,
TP_PRBS_SEL2, DP_DPHY_TP_PRBS7,
TP_PRBS_SEL3, DP_DPHY_TP_PRBS7);
REG_UPDATE_4(DP_DPHY_SYM32_TP_CONFIG,
TP_SELECT0, DP_DPHY_TP_SELECT_PRBS,
TP_SELECT1, DP_DPHY_TP_SELECT_PRBS,
TP_SELECT2, DP_DPHY_TP_SELECT_PRBS,
TP_SELECT3, DP_DPHY_TP_SELECT_PRBS);
REG_UPDATE(DP_DPHY_SYM32_CONTROL,
MODE, DP2_TEST_PATTERN);
break;
case DP_TEST_PATTERN_PRBS9:
REG_UPDATE_4(DP_DPHY_SYM32_TP_CONFIG,
TP_PRBS_SEL0, DP_DPHY_TP_PRBS9,
TP_PRBS_SEL1, DP_DPHY_TP_PRBS9,
TP_PRBS_SEL2, DP_DPHY_TP_PRBS9,
TP_PRBS_SEL3, DP_DPHY_TP_PRBS9);
REG_UPDATE_4(DP_DPHY_SYM32_TP_CONFIG,
TP_SELECT0, DP_DPHY_TP_SELECT_PRBS,
TP_SELECT1, DP_DPHY_TP_SELECT_PRBS,
TP_SELECT2, DP_DPHY_TP_SELECT_PRBS,
TP_SELECT3, DP_DPHY_TP_SELECT_PRBS);
REG_UPDATE(DP_DPHY_SYM32_CONTROL,
MODE, DP2_TEST_PATTERN);
break;
case DP_TEST_PATTERN_PRBS11:
REG_UPDATE_4(DP_DPHY_SYM32_TP_CONFIG,
TP_PRBS_SEL0, DP_DPHY_TP_PRBS11,
TP_PRBS_SEL1, DP_DPHY_TP_PRBS11,
TP_PRBS_SEL2, DP_DPHY_TP_PRBS11,
TP_PRBS_SEL3, DP_DPHY_TP_PRBS11);
REG_UPDATE_4(DP_DPHY_SYM32_TP_CONFIG,
TP_SELECT0, DP_DPHY_TP_SELECT_PRBS,
TP_SELECT1, DP_DPHY_TP_SELECT_PRBS,
TP_SELECT2, DP_DPHY_TP_SELECT_PRBS,
TP_SELECT3, DP_DPHY_TP_SELECT_PRBS);
REG_UPDATE(DP_DPHY_SYM32_CONTROL,
MODE, DP2_TEST_PATTERN);
break;
case DP_TEST_PATTERN_PRBS15:
REG_UPDATE_4(DP_DPHY_SYM32_TP_CONFIG,
TP_PRBS_SEL0, DP_DPHY_TP_PRBS15,
TP_PRBS_SEL1, DP_DPHY_TP_PRBS15,
TP_PRBS_SEL2, DP_DPHY_TP_PRBS15,
TP_PRBS_SEL3, DP_DPHY_TP_PRBS15);
REG_UPDATE_4(DP_DPHY_SYM32_TP_CONFIG,
TP_SELECT0, DP_DPHY_TP_SELECT_PRBS,
TP_SELECT1, DP_DPHY_TP_SELECT_PRBS,
TP_SELECT2, DP_DPHY_TP_SELECT_PRBS,
TP_SELECT3, DP_DPHY_TP_SELECT_PRBS);
REG_UPDATE(DP_DPHY_SYM32_CONTROL,
MODE, DP2_TEST_PATTERN);
break;
case DP_TEST_PATTERN_PRBS23:
REG_UPDATE_4(DP_DPHY_SYM32_TP_CONFIG,
TP_PRBS_SEL0, DP_DPHY_TP_PRBS23,
TP_PRBS_SEL1, DP_DPHY_TP_PRBS23,
TP_PRBS_SEL2, DP_DPHY_TP_PRBS23,
TP_PRBS_SEL3, DP_DPHY_TP_PRBS23);
REG_UPDATE_4(DP_DPHY_SYM32_TP_CONFIG,
TP_SELECT0, DP_DPHY_TP_SELECT_PRBS,
TP_SELECT1, DP_DPHY_TP_SELECT_PRBS,
TP_SELECT2, DP_DPHY_TP_SELECT_PRBS,
TP_SELECT3, DP_DPHY_TP_SELECT_PRBS);
REG_UPDATE(DP_DPHY_SYM32_CONTROL,
MODE, DP2_TEST_PATTERN);
break;
case DP_TEST_PATTERN_PRBS31:
REG_UPDATE_4(DP_DPHY_SYM32_TP_CONFIG,
TP_PRBS_SEL0, DP_DPHY_TP_PRBS31,
TP_PRBS_SEL1, DP_DPHY_TP_PRBS31,
TP_PRBS_SEL2, DP_DPHY_TP_PRBS31,
TP_PRBS_SEL3, DP_DPHY_TP_PRBS31);
REG_UPDATE_4(DP_DPHY_SYM32_TP_CONFIG,
TP_SELECT0, DP_DPHY_TP_SELECT_PRBS,
TP_SELECT1, DP_DPHY_TP_SELECT_PRBS,
TP_SELECT2, DP_DPHY_TP_SELECT_PRBS,
TP_SELECT3, DP_DPHY_TP_SELECT_PRBS);
REG_UPDATE(DP_DPHY_SYM32_CONTROL,
MODE, DP2_TEST_PATTERN);
break;
case DP_TEST_PATTERN_264BIT_CUSTOM:
tp_custom = (tp_params->custom_pattern[2] << 16) | (tp_params->custom_pattern[1] << 8) | tp_params->custom_pattern[0];
REG_SET(DP_DPHY_SYM32_TP_CUSTOM0, 0, TP_CUSTOM, tp_custom);
tp_custom = (tp_params->custom_pattern[5] << 16) | (tp_params->custom_pattern[4] << 8) | tp_params->custom_pattern[3];
REG_SET(DP_DPHY_SYM32_TP_CUSTOM1, 0, TP_CUSTOM, tp_custom);
tp_custom = (tp_params->custom_pattern[8] << 16) | (tp_params->custom_pattern[7] << 8) | tp_params->custom_pattern[6];
REG_SET(DP_DPHY_SYM32_TP_CUSTOM2, 0, TP_CUSTOM, tp_custom);
tp_custom = (tp_params->custom_pattern[11] << 16) | (tp_params->custom_pattern[10] << 8) | tp_params->custom_pattern[9];
REG_SET(DP_DPHY_SYM32_TP_CUSTOM3, 0, TP_CUSTOM, tp_custom);
tp_custom = (tp_params->custom_pattern[14] << 16) | (tp_params->custom_pattern[13] << 8) | tp_params->custom_pattern[12];
REG_SET(DP_DPHY_SYM32_TP_CUSTOM4, 0, TP_CUSTOM, tp_custom);
tp_custom = (tp_params->custom_pattern[17] << 16) | (tp_params->custom_pattern[16] << 8) | tp_params->custom_pattern[15];
REG_SET(DP_DPHY_SYM32_TP_CUSTOM5, 0, TP_CUSTOM, tp_custom);
tp_custom = (tp_params->custom_pattern[20] << 16) | (tp_params->custom_pattern[19] << 8) | tp_params->custom_pattern[18];
REG_SET(DP_DPHY_SYM32_TP_CUSTOM6, 0, TP_CUSTOM, tp_custom);
tp_custom = (tp_params->custom_pattern[23] << 16) | (tp_params->custom_pattern[22] << 8) | tp_params->custom_pattern[21];
REG_SET(DP_DPHY_SYM32_TP_CUSTOM7, 0, TP_CUSTOM, tp_custom);
tp_custom = (tp_params->custom_pattern[26] << 16) | (tp_params->custom_pattern[25] << 8) | tp_params->custom_pattern[24];
REG_SET(DP_DPHY_SYM32_TP_CUSTOM8, 0, TP_CUSTOM, tp_custom);
tp_custom = (tp_params->custom_pattern[29] << 16) | (tp_params->custom_pattern[28] << 8) | tp_params->custom_pattern[27];
REG_SET(DP_DPHY_SYM32_TP_CUSTOM9, 0, TP_CUSTOM, tp_custom);
tp_custom = (tp_params->custom_pattern[32] << 16) | (tp_params->custom_pattern[31] << 8) | tp_params->custom_pattern[30];
REG_SET(DP_DPHY_SYM32_TP_CUSTOM10, 0, TP_CUSTOM, tp_custom);
REG_UPDATE_4(DP_DPHY_SYM32_TP_CONFIG,
TP_SELECT0, DP_DPHY_TP_SELECT_CUSTOM,
TP_SELECT1, DP_DPHY_TP_SELECT_CUSTOM,
TP_SELECT2, DP_DPHY_TP_SELECT_CUSTOM,
TP_SELECT3, DP_DPHY_TP_SELECT_CUSTOM);
REG_UPDATE(DP_DPHY_SYM32_CONTROL,
MODE, DP2_TEST_PATTERN);
break;
case DP_TEST_PATTERN_SQUARE:
case DP_TEST_PATTERN_SQUARE_PRESHOOT_DISABLED:
case DP_TEST_PATTERN_SQUARE_DEEMPHASIS_DISABLED:
case DP_TEST_PATTERN_SQUARE_PRESHOOT_DEEMPHASIS_DISABLED:
REG_SET(DP_DPHY_SYM32_TP_SQ_PULSE, 0,
TP_SQ_PULSE_WIDTH, tp_params->custom_pattern[0]);
REG_UPDATE_4(DP_DPHY_SYM32_TP_CONFIG,
TP_SELECT0, DP_DPHY_TP_SELECT_SQUARE,
TP_SELECT1, DP_DPHY_TP_SELECT_SQUARE,
TP_SELECT2, DP_DPHY_TP_SELECT_SQUARE,
TP_SELECT3, DP_DPHY_TP_SELECT_SQUARE);
REG_UPDATE(DP_DPHY_SYM32_CONTROL,
MODE, DP2_TEST_PATTERN);
break;
default:
break;
}
}
void dcn31_fill_stream_allocation_row_info(
const struct link_mst_stream_allocation *stream_allocation,
uint32_t *src,
uint32_t *slots)
{
const struct hpo_dp_stream_encoder *stream_enc = stream_allocation->hpo_dp_stream_enc;
if (stream_enc && (stream_enc->id >= ENGINE_ID_HPO_DP_0)) {
*src = stream_enc->id - ENGINE_ID_HPO_DP_0;
*slots = stream_allocation->slot_count;
} else {
*src = 0;
*slots = 0;
}
}
/* programs DP VC payload allocation */
void dcn31_hpo_dp_link_enc_update_stream_allocation_table(
struct hpo_dp_link_encoder *enc,
const struct link_mst_stream_allocation_table *table)
{
struct dcn31_hpo_dp_link_encoder *enc3 = DCN3_1_HPO_DP_LINK_ENC_FROM_HPO_LINK_ENC(enc);
uint32_t slots = 0;
uint32_t src = 0;
/* --- 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) {
dcn31_fill_stream_allocation_row_info(
&table->stream_allocations[0],
&src,
&slots);
} else {
src = 0;
slots = 0;
}
REG_UPDATE_2(DP_DPHY_SYM32_SAT_VC0,
SAT_STREAM_SOURCE, src,
SAT_SLOT_COUNT, slots);
if (table->stream_count >= 2) {
dcn31_fill_stream_allocation_row_info(
&table->stream_allocations[1],
&src,
&slots);
} else {
src = 0;
slots = 0;
}
REG_UPDATE_2(DP_DPHY_SYM32_SAT_VC1,
SAT_STREAM_SOURCE, src,
SAT_SLOT_COUNT, slots);
if (table->stream_count >= 3) {
dcn31_fill_stream_allocation_row_info(
&table->stream_allocations[2],
&src,
&slots);
} else {
src = 0;
slots = 0;
}
REG_UPDATE_2(DP_DPHY_SYM32_SAT_VC2,
SAT_STREAM_SOURCE, src,
SAT_SLOT_COUNT, slots);
if (table->stream_count >= 4) {
dcn31_fill_stream_allocation_row_info(
&table->stream_allocations[3],
&src,
&slots);
} else {
src = 0;
slots = 0;
}
REG_UPDATE_2(DP_DPHY_SYM32_SAT_VC3,
SAT_STREAM_SOURCE, src,
SAT_SLOT_COUNT, 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
*/
/* SAT_UPDATE:
* 0 - No Action
* 1 - Update SAT with trigger
* 2 - Update SAT without trigger
*/
REG_UPDATE(DP_DPHY_SYM32_SAT_UPDATE,
SAT_UPDATE, 1);
/* wait for update to complete
* (i.e. SAT_UPDATE_PENDING field is set to 0)
* No need for HW to enforce keepout.
*/
/* Best case and worst case wait time for SAT_UPDATE_PENDING
* best: 109 us
* worst: 868 us
*/
REG_WAIT(DP_DPHY_SYM32_STATUS,
SAT_UPDATE_PENDING, 0,
100, DP_SAT_UPDATE_MAX_RETRY);
}
void dcn31_hpo_dp_link_enc_set_throttled_vcp_size(
struct hpo_dp_link_encoder *enc,
uint32_t stream_encoder_inst,
struct fixed31_32 avg_time_slots_per_mtp)
{
struct dcn31_hpo_dp_link_encoder *enc3 = DCN3_1_HPO_DP_LINK_ENC_FROM_HPO_LINK_ENC(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),
25));
// If y rounds up to integer, carry it over to x.
if (y >> 25) {
x += 1;
y = 0;
}
switch (stream_encoder_inst) {
case 0:
REG_SET_2(DP_DPHY_SYM32_VC_RATE_CNTL0, 0,
STREAM_VC_RATE_X, x,
STREAM_VC_RATE_Y, y);
break;
case 1:
REG_SET_2(DP_DPHY_SYM32_VC_RATE_CNTL1, 0,
STREAM_VC_RATE_X, x,
STREAM_VC_RATE_Y, y);
break;
case 2:
REG_SET_2(DP_DPHY_SYM32_VC_RATE_CNTL2, 0,
STREAM_VC_RATE_X, x,
STREAM_VC_RATE_Y, y);
break;
case 3:
REG_SET_2(DP_DPHY_SYM32_VC_RATE_CNTL3, 0,
STREAM_VC_RATE_X, x,
STREAM_VC_RATE_Y, y);
break;
default:
ASSERT(0);
}
/* Best case and worst case wait time for RATE_UPDATE_PENDING
* best: 116 ns
* worst: 903 ns
*/
/* wait for update to be completed on the link */
REG_WAIT(DP_DPHY_SYM32_STATUS,
RATE_UPDATE_PENDING, 0,
1, 10);
}
static bool dcn31_hpo_dp_link_enc_is_in_alt_mode(
struct hpo_dp_link_encoder *enc)
{
struct dcn31_hpo_dp_link_encoder *enc3 = DCN3_1_HPO_DP_LINK_ENC_FROM_HPO_LINK_ENC(enc);
uint32_t dp_alt_mode_disable = 0;
ASSERT((enc->transmitter >= TRANSMITTER_UNIPHY_A) && (enc->transmitter <= TRANSMITTER_UNIPHY_E));
/* if value == 1 alt mode is disabled, otherwise it is enabled */
REG_GET(RDPCSTX_PHY_CNTL6[enc->transmitter], RDPCS_PHY_DPALT_DISABLE, &dp_alt_mode_disable);
return (dp_alt_mode_disable == 0);
}
void dcn31_hpo_dp_link_enc_read_state(
struct hpo_dp_link_encoder *enc,
struct hpo_dp_link_enc_state *state)
{
struct dcn31_hpo_dp_link_encoder *enc3 = DCN3_1_HPO_DP_LINK_ENC_FROM_HPO_LINK_ENC(enc);
ASSERT(state);
REG_GET(DP_DPHY_SYM32_STATUS,
STATUS, &state->link_enc_enabled);
REG_GET(DP_DPHY_SYM32_CONTROL,
NUM_LANES, &state->lane_count);
REG_GET(DP_DPHY_SYM32_CONTROL,
MODE, (uint32_t *)&state->link_mode);
REG_GET_2(DP_DPHY_SYM32_SAT_VC0,
SAT_STREAM_SOURCE, &state->stream_src[0],
SAT_SLOT_COUNT, &state->slot_count[0]);
REG_GET_2(DP_DPHY_SYM32_SAT_VC1,
SAT_STREAM_SOURCE, &state->stream_src[1],
SAT_SLOT_COUNT, &state->slot_count[1]);
REG_GET_2(DP_DPHY_SYM32_SAT_VC2,
SAT_STREAM_SOURCE, &state->stream_src[2],
SAT_SLOT_COUNT, &state->slot_count[2]);
REG_GET_2(DP_DPHY_SYM32_SAT_VC3,
SAT_STREAM_SOURCE, &state->stream_src[3],
SAT_SLOT_COUNT, &state->slot_count[3]);
REG_GET_2(DP_DPHY_SYM32_VC_RATE_CNTL0,
STREAM_VC_RATE_X, &state->vc_rate_x[0],
STREAM_VC_RATE_Y, &state->vc_rate_y[0]);
REG_GET_2(DP_DPHY_SYM32_VC_RATE_CNTL1,
STREAM_VC_RATE_X, &state->vc_rate_x[1],
STREAM_VC_RATE_Y, &state->vc_rate_y[1]);
REG_GET_2(DP_DPHY_SYM32_VC_RATE_CNTL2,
STREAM_VC_RATE_X, &state->vc_rate_x[2],
STREAM_VC_RATE_Y, &state->vc_rate_y[2]);
REG_GET_2(DP_DPHY_SYM32_VC_RATE_CNTL3,
STREAM_VC_RATE_X, &state->vc_rate_x[3],
STREAM_VC_RATE_Y, &state->vc_rate_y[3]);
}
static enum bp_result link_transmitter_control(
struct dcn31_hpo_dp_link_encoder *enc3,
struct bp_transmitter_control *cntl)
{
enum bp_result result;
struct dc_bios *bp = enc3->base.ctx->dc_bios;
result = bp->funcs->transmitter_control(bp, cntl);
return result;
}
/* enables DP PHY output for 128b132b encoding */
void dcn31_hpo_dp_link_enc_enable_dp_output(
struct hpo_dp_link_encoder *enc,
const struct dc_link_settings *link_settings,
enum transmitter transmitter,
enum hpd_source_id hpd_source)
{
struct dcn31_hpo_dp_link_encoder *enc3 = DCN3_1_HPO_DP_LINK_ENC_FROM_HPO_LINK_ENC(enc);
struct bp_transmitter_control cntl = { 0 };
enum bp_result result;
/* Set the transmitter */
enc3->base.transmitter = transmitter;
/* Set the hpd source */
enc3->base.hpd_source = hpd_source;
/* Enable the PHY */
cntl.action = TRANSMITTER_CONTROL_ENABLE;
cntl.engine_id = ENGINE_ID_UNKNOWN;
cntl.transmitter = enc3->base.transmitter;
//cntl.pll_id = clock_source;
cntl.signal = SIGNAL_TYPE_DISPLAY_PORT_MST;
cntl.lanes_number = link_settings->lane_count;
cntl.hpd_sel = enc3->base.hpd_source;
cntl.pixel_clock = link_settings->link_rate * 1000;
cntl.color_depth = COLOR_DEPTH_UNDEFINED;
cntl.hpo_engine_id = enc->inst + ENGINE_ID_HPO_DP_0;
result = link_transmitter_control(enc3, &cntl);
if (result != BP_RESULT_OK) {
DC_LOG_ERROR("%s: Failed to execute VBIOS command table!\n",
__func__);
BREAK_TO_DEBUGGER();
}
}
void dcn31_hpo_dp_link_enc_disable_output(
struct hpo_dp_link_encoder *enc,
enum signal_type signal)
{
struct dcn31_hpo_dp_link_encoder *enc3 = DCN3_1_HPO_DP_LINK_ENC_FROM_HPO_LINK_ENC(enc);
struct bp_transmitter_control cntl = { 0 };
enum bp_result result;
/* disable transmitter */
cntl.action = TRANSMITTER_CONTROL_DISABLE;
cntl.transmitter = enc3->base.transmitter;
cntl.hpd_sel = enc3->base.hpd_source;
cntl.signal = signal;
result = link_transmitter_control(enc3, &cntl);
if (result != BP_RESULT_OK) {
DC_LOG_ERROR("%s: Failed to execute VBIOS command table!\n",
__func__);
BREAK_TO_DEBUGGER();
return;
}
/* disable encoder */
dcn31_hpo_dp_link_enc_disable(enc);
}
void dcn31_hpo_dp_link_enc_set_ffe(
struct hpo_dp_link_encoder *enc,
const struct dc_link_settings *link_settings,
uint8_t ffe_preset)
{
struct dcn31_hpo_dp_link_encoder *enc3 = DCN3_1_HPO_DP_LINK_ENC_FROM_HPO_LINK_ENC(enc);
struct bp_transmitter_control cntl = { 0 };
enum bp_result result;
/* disable transmitter */
cntl.transmitter = enc3->base.transmitter;
cntl.action = TRANSMITTER_CONTROL_SET_VOLTAGE_AND_PREEMPASIS;
cntl.signal = SIGNAL_TYPE_DISPLAY_PORT_MST;
cntl.lanes_number = link_settings->lane_count;
cntl.pixel_clock = link_settings->link_rate * 1000;
cntl.lane_settings = ffe_preset;
result = link_transmitter_control(enc3, &cntl);
if (result != BP_RESULT_OK) {
DC_LOG_ERROR("%s: Failed to execute VBIOS command table!\n",
__func__);
BREAK_TO_DEBUGGER();
return;
}
}
static struct hpo_dp_link_encoder_funcs dcn31_hpo_dp_link_encoder_funcs = {
.enable_link_phy = dcn31_hpo_dp_link_enc_enable_dp_output,
.disable_link_phy = dcn31_hpo_dp_link_enc_disable_output,
.link_enable = dcn31_hpo_dp_link_enc_enable,
.link_disable = dcn31_hpo_dp_link_enc_disable,
.set_link_test_pattern = dcn31_hpo_dp_link_enc_set_link_test_pattern,
.update_stream_allocation_table = dcn31_hpo_dp_link_enc_update_stream_allocation_table,
.set_throttled_vcp_size = dcn31_hpo_dp_link_enc_set_throttled_vcp_size,
.is_in_alt_mode = dcn31_hpo_dp_link_enc_is_in_alt_mode,
.read_state = dcn31_hpo_dp_link_enc_read_state,
.set_ffe = dcn31_hpo_dp_link_enc_set_ffe,
};
void hpo_dp_link_encoder31_construct(struct dcn31_hpo_dp_link_encoder *enc31,
struct dc_context *ctx,
uint32_t inst,
const struct dcn31_hpo_dp_link_encoder_registers *hpo_le_regs,
const struct dcn31_hpo_dp_link_encoder_shift *hpo_le_shift,
const struct dcn31_hpo_dp_link_encoder_mask *hpo_le_mask)
{
enc31->base.ctx = ctx;
enc31->base.inst = inst;
enc31->base.funcs = &dcn31_hpo_dp_link_encoder_funcs;
enc31->base.hpd_source = HPD_SOURCEID_UNKNOWN;
enc31->base.transmitter = TRANSMITTER_UNKNOWN;
enc31->regs = hpo_le_regs;
enc31->hpo_le_shift = hpo_le_shift;
enc31->hpo_le_mask = hpo_le_mask;
}
@@ -0,0 +1,235 @@
/*
* Copyright 2019 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 __DAL_DCN31_HPO_DP_LINK_ENCODER_H__
#define __DAL_DCN31_HPO_DP_LINK_ENCODER_H__
#include "link_encoder.h"
#define DCN3_1_HPO_DP_LINK_ENC_FROM_HPO_LINK_ENC(hpo_dp_link_encoder)\
container_of(hpo_dp_link_encoder, struct dcn31_hpo_dp_link_encoder, base)
#define DCN3_1_HPO_DP_LINK_ENC_REG_LIST(id) \
SRI(DP_LINK_ENC_CLOCK_CONTROL, DP_LINK_ENC, id), \
SRI(DP_DPHY_SYM32_CONTROL, DP_DPHY_SYM32, id), \
SRI(DP_DPHY_SYM32_STATUS, DP_DPHY_SYM32, id), \
SRI(DP_DPHY_SYM32_TP_CONFIG, DP_DPHY_SYM32, id), \
SRI(DP_DPHY_SYM32_TP_PRBS_SEED0, DP_DPHY_SYM32, id), \
SRI(DP_DPHY_SYM32_TP_PRBS_SEED1, DP_DPHY_SYM32, id), \
SRI(DP_DPHY_SYM32_TP_PRBS_SEED2, DP_DPHY_SYM32, id), \
SRI(DP_DPHY_SYM32_TP_PRBS_SEED3, DP_DPHY_SYM32, id), \
SRI(DP_DPHY_SYM32_TP_SQ_PULSE, DP_DPHY_SYM32, id), \
SRI(DP_DPHY_SYM32_TP_CUSTOM0, DP_DPHY_SYM32, id), \
SRI(DP_DPHY_SYM32_TP_CUSTOM1, DP_DPHY_SYM32, id), \
SRI(DP_DPHY_SYM32_TP_CUSTOM2, DP_DPHY_SYM32, id), \
SRI(DP_DPHY_SYM32_TP_CUSTOM3, DP_DPHY_SYM32, id), \
SRI(DP_DPHY_SYM32_TP_CUSTOM4, DP_DPHY_SYM32, id), \
SRI(DP_DPHY_SYM32_TP_CUSTOM5, DP_DPHY_SYM32, id), \
SRI(DP_DPHY_SYM32_TP_CUSTOM6, DP_DPHY_SYM32, id), \
SRI(DP_DPHY_SYM32_TP_CUSTOM7, DP_DPHY_SYM32, id), \
SRI(DP_DPHY_SYM32_TP_CUSTOM8, DP_DPHY_SYM32, id), \
SRI(DP_DPHY_SYM32_TP_CUSTOM9, DP_DPHY_SYM32, id), \
SRI(DP_DPHY_SYM32_TP_CUSTOM10, DP_DPHY_SYM32, id), \
SRI(DP_DPHY_SYM32_SAT_VC0, DP_DPHY_SYM32, id), \
SRI(DP_DPHY_SYM32_SAT_VC1, DP_DPHY_SYM32, id), \
SRI(DP_DPHY_SYM32_SAT_VC2, DP_DPHY_SYM32, id), \
SRI(DP_DPHY_SYM32_SAT_VC3, DP_DPHY_SYM32, id), \
SRI(DP_DPHY_SYM32_VC_RATE_CNTL0, DP_DPHY_SYM32, id), \
SRI(DP_DPHY_SYM32_VC_RATE_CNTL1, DP_DPHY_SYM32, id), \
SRI(DP_DPHY_SYM32_VC_RATE_CNTL2, DP_DPHY_SYM32, id), \
SRI(DP_DPHY_SYM32_VC_RATE_CNTL3, DP_DPHY_SYM32, id), \
SRI(DP_DPHY_SYM32_SAT_UPDATE, DP_DPHY_SYM32, id)
#define DCN3_1_RDPCSTX_REG_LIST(id) \
SRII(RDPCSTX_PHY_CNTL6, RDPCSTX, id)
#define DCN3_1_HPO_DP_LINK_ENC_REGS \
uint32_t DP_LINK_ENC_CLOCK_CONTROL;\
uint32_t DP_DPHY_SYM32_CONTROL;\
uint32_t DP_DPHY_SYM32_STATUS;\
uint32_t DP_DPHY_SYM32_TP_CONFIG;\
uint32_t DP_DPHY_SYM32_TP_PRBS_SEED0;\
uint32_t DP_DPHY_SYM32_TP_PRBS_SEED1;\
uint32_t DP_DPHY_SYM32_TP_PRBS_SEED2;\
uint32_t DP_DPHY_SYM32_TP_PRBS_SEED3;\
uint32_t DP_DPHY_SYM32_TP_SQ_PULSE;\
uint32_t DP_DPHY_SYM32_TP_CUSTOM0;\
uint32_t DP_DPHY_SYM32_TP_CUSTOM1;\
uint32_t DP_DPHY_SYM32_TP_CUSTOM2;\
uint32_t DP_DPHY_SYM32_TP_CUSTOM3;\
uint32_t DP_DPHY_SYM32_TP_CUSTOM4;\
uint32_t DP_DPHY_SYM32_TP_CUSTOM5;\
uint32_t DP_DPHY_SYM32_TP_CUSTOM6;\
uint32_t DP_DPHY_SYM32_TP_CUSTOM7;\
uint32_t DP_DPHY_SYM32_TP_CUSTOM8;\
uint32_t DP_DPHY_SYM32_TP_CUSTOM9;\
uint32_t DP_DPHY_SYM32_TP_CUSTOM10;\
uint32_t DP_DPHY_SYM32_SAT_VC0;\
uint32_t DP_DPHY_SYM32_SAT_VC1;\
uint32_t DP_DPHY_SYM32_SAT_VC2;\
uint32_t DP_DPHY_SYM32_SAT_VC3;\
uint32_t DP_DPHY_SYM32_VC_RATE_CNTL0;\
uint32_t DP_DPHY_SYM32_VC_RATE_CNTL1;\
uint32_t DP_DPHY_SYM32_VC_RATE_CNTL2;\
uint32_t DP_DPHY_SYM32_VC_RATE_CNTL3;\
uint32_t DP_DPHY_SYM32_SAT_UPDATE
struct dcn31_hpo_dp_link_encoder_registers {
DCN3_1_HPO_DP_LINK_ENC_REGS;
uint32_t RDPCSTX_PHY_CNTL6[5];
};
#define DCN3_1_HPO_DP_LINK_ENC_RDPCSTX_MASK_SH_LIST(mask_sh)\
SE_SF(RDPCSTX0_RDPCSTX_PHY_CNTL6, RDPCS_PHY_DPALT_DISABLE, mask_sh)
#define DCN3_1_HPO_DP_LINK_ENC_COMMON_MASK_SH_LIST(mask_sh)\
SE_SF(DP_LINK_ENC0_DP_LINK_ENC_CLOCK_CONTROL, DP_LINK_ENC_CLOCK_EN, mask_sh),\
SE_SF(DP_DPHY_SYM320_DP_DPHY_SYM32_CONTROL, DPHY_RESET, mask_sh),\
SE_SF(DP_DPHY_SYM320_DP_DPHY_SYM32_CONTROL, DPHY_ENABLE, mask_sh),\
SE_SF(DP_DPHY_SYM320_DP_DPHY_SYM32_CONTROL, PRECODER_ENABLE, mask_sh),\
SE_SF(DP_DPHY_SYM320_DP_DPHY_SYM32_CONTROL, MODE, mask_sh),\
SE_SF(DP_DPHY_SYM320_DP_DPHY_SYM32_CONTROL, NUM_LANES, mask_sh),\
SE_SF(DP_DPHY_SYM320_DP_DPHY_SYM32_STATUS, STATUS, mask_sh),\
SE_SF(DP_DPHY_SYM320_DP_DPHY_SYM32_STATUS, SAT_UPDATE_PENDING, mask_sh),\
SE_SF(DP_DPHY_SYM320_DP_DPHY_SYM32_STATUS, RATE_UPDATE_PENDING, mask_sh),\
SE_SF(DP_DPHY_SYM320_DP_DPHY_SYM32_TP_CUSTOM0, TP_CUSTOM, mask_sh),\
SE_SF(DP_DPHY_SYM320_DP_DPHY_SYM32_TP_CONFIG, TP_SELECT0, mask_sh),\
SE_SF(DP_DPHY_SYM320_DP_DPHY_SYM32_TP_CONFIG, TP_SELECT1, mask_sh),\
SE_SF(DP_DPHY_SYM320_DP_DPHY_SYM32_TP_CONFIG, TP_SELECT2, mask_sh),\
SE_SF(DP_DPHY_SYM320_DP_DPHY_SYM32_TP_CONFIG, TP_SELECT3, mask_sh),\
SE_SF(DP_DPHY_SYM320_DP_DPHY_SYM32_TP_CONFIG, TP_PRBS_SEL0, mask_sh),\
SE_SF(DP_DPHY_SYM320_DP_DPHY_SYM32_TP_CONFIG, TP_PRBS_SEL1, mask_sh),\
SE_SF(DP_DPHY_SYM320_DP_DPHY_SYM32_TP_CONFIG, TP_PRBS_SEL2, mask_sh),\
SE_SF(DP_DPHY_SYM320_DP_DPHY_SYM32_TP_CONFIG, TP_PRBS_SEL3, mask_sh),\
SE_SF(DP_DPHY_SYM320_DP_DPHY_SYM32_TP_SQ_PULSE, TP_SQ_PULSE_WIDTH, mask_sh),\
SE_SF(DP_DPHY_SYM320_DP_DPHY_SYM32_SAT_VC0, SAT_STREAM_SOURCE, mask_sh),\
SE_SF(DP_DPHY_SYM320_DP_DPHY_SYM32_SAT_VC0, SAT_SLOT_COUNT, mask_sh),\
SE_SF(DP_DPHY_SYM320_DP_DPHY_SYM32_VC_RATE_CNTL0, STREAM_VC_RATE_X, mask_sh),\
SE_SF(DP_DPHY_SYM320_DP_DPHY_SYM32_VC_RATE_CNTL0, STREAM_VC_RATE_Y, mask_sh),\
SE_SF(DP_DPHY_SYM320_DP_DPHY_SYM32_SAT_UPDATE, SAT_UPDATE, mask_sh)
#define DCN3_1_HPO_DP_LINK_ENC_MASK_SH_LIST(mask_sh)\
DCN3_1_HPO_DP_LINK_ENC_COMMON_MASK_SH_LIST(mask_sh),\
DCN3_1_HPO_DP_LINK_ENC_RDPCSTX_MASK_SH_LIST(mask_sh)\
#define DCN3_1_HPO_DP_LINK_ENC_REG_FIELD_LIST(type) \
type DP_LINK_ENC_CLOCK_EN;\
type DPHY_RESET;\
type DPHY_ENABLE;\
type PRECODER_ENABLE;\
type NUM_LANES;\
type MODE;\
type STATUS;\
type SAT_UPDATE_PENDING;\
type RATE_UPDATE_PENDING;\
type TP_CUSTOM;\
type TP_SELECT0;\
type TP_SELECT1;\
type TP_SELECT2;\
type TP_SELECT3;\
type TP_PRBS_SEL0;\
type TP_PRBS_SEL1;\
type TP_PRBS_SEL2;\
type TP_PRBS_SEL3;\
type TP_SQ_PULSE_WIDTH;\
type SAT_STREAM_SOURCE;\
type SAT_SLOT_COUNT;\
type STREAM_VC_RATE_X;\
type STREAM_VC_RATE_Y;\
type SAT_UPDATE;\
type RDPCS_PHY_DPALT_DISABLE
struct dcn31_hpo_dp_link_encoder_shift {
DCN3_1_HPO_DP_LINK_ENC_REG_FIELD_LIST(uint8_t);
};
struct dcn31_hpo_dp_link_encoder_mask {
DCN3_1_HPO_DP_LINK_ENC_REG_FIELD_LIST(uint32_t);
};
struct dcn31_hpo_dp_link_encoder {
struct hpo_dp_link_encoder base;
const struct dcn31_hpo_dp_link_encoder_registers *regs;
const struct dcn31_hpo_dp_link_encoder_shift *hpo_le_shift;
const struct dcn31_hpo_dp_link_encoder_mask *hpo_le_mask;
};
void hpo_dp_link_encoder31_construct(struct dcn31_hpo_dp_link_encoder *enc31,
struct dc_context *ctx,
uint32_t inst,
const struct dcn31_hpo_dp_link_encoder_registers *hpo_le_regs,
const struct dcn31_hpo_dp_link_encoder_shift *hpo_le_shift,
const struct dcn31_hpo_dp_link_encoder_mask *hpo_le_mask);
void dcn31_hpo_dp_link_enc_enable_dp_output(
struct hpo_dp_link_encoder *enc,
const struct dc_link_settings *link_settings,
enum transmitter transmitter,
enum hpd_source_id hpd_source);
void dcn31_hpo_dp_link_enc_disable_output(
struct hpo_dp_link_encoder *enc,
enum signal_type signal);
void dcn31_hpo_dp_link_enc_enable(
struct hpo_dp_link_encoder *enc,
enum dc_lane_count num_lanes);
void dcn31_hpo_dp_link_enc_disable(
struct hpo_dp_link_encoder *enc);
void dcn31_hpo_dp_link_enc_set_link_test_pattern(
struct hpo_dp_link_encoder *enc,
struct encoder_set_dp_phy_pattern_param *tp_params);
void dcn31_hpo_dp_link_enc_update_stream_allocation_table(
struct hpo_dp_link_encoder *enc,
const struct link_mst_stream_allocation_table *table);
void dcn31_hpo_dp_link_enc_set_throttled_vcp_size(
struct hpo_dp_link_encoder *enc,
uint32_t stream_encoder_inst,
struct fixed31_32 avg_time_slots_per_mtp);
void dcn31_hpo_dp_link_enc_read_state(
struct hpo_dp_link_encoder *enc,
struct hpo_dp_link_enc_state *state);
void dcn31_hpo_dp_link_enc_set_ffe(
struct hpo_dp_link_encoder *enc,
const struct dc_link_settings *link_settings,
uint8_t ffe_preset);
void dcn31_fill_stream_allocation_row_info(
const struct link_mst_stream_allocation *stream_allocation,
uint32_t *src,
uint32_t *slots);
#endif // __DAL_DCN31_HPO_LINK_ENCODER_H__
@@ -0,0 +1,785 @@
/*
* Copyright 2019 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 "dcn31_hpo_dp_stream_encoder.h"
#include "reg_helper.h"
#include "dc.h"
#define DC_LOGGER \
enc3->base.ctx->logger
#define REG(reg)\
(enc3->regs->reg)
#undef FN
#define FN(reg_name, field_name) \
enc3->hpo_se_shift->field_name, enc3->hpo_se_mask->field_name
#define CTX \
enc3->base.ctx
enum dp2_pixel_encoding {
DP_SYM32_ENC_PIXEL_ENCODING_RGB_YCBCR444,
DP_SYM32_ENC_PIXEL_ENCODING_YCBCR422,
DP_SYM32_ENC_PIXEL_ENCODING_YCBCR420,
DP_SYM32_ENC_PIXEL_ENCODING_Y_ONLY
};
enum dp2_uncompressed_component_depth {
DP_SYM32_ENC_COMPONENT_DEPTH_6BPC,
DP_SYM32_ENC_COMPONENT_DEPTH_8BPC,
DP_SYM32_ENC_COMPONENT_DEPTH_10BPC,
DP_SYM32_ENC_COMPONENT_DEPTH_12BPC
};
static void dcn31_hpo_dp_stream_enc_enable_stream(
struct hpo_dp_stream_encoder *enc)
{
struct dcn31_hpo_dp_stream_encoder *enc3 = DCN3_1_HPO_DP_STREAM_ENC_FROM_HPO_STREAM_ENC(enc);
/* Enable all clocks in the DP_STREAM_ENC */
REG_UPDATE(DP_STREAM_ENC_CLOCK_CONTROL,
DP_STREAM_ENC_CLOCK_EN, 1);
/* Assert reset to the DP_SYM32_ENC logic */
REG_UPDATE(DP_SYM32_ENC_CONTROL,
DP_SYM32_ENC_RESET, 1);
/* Wait for reset to complete (to assert) */
REG_WAIT(DP_SYM32_ENC_CONTROL,
DP_SYM32_ENC_RESET_DONE, 1,
1, 10);
/* De-assert reset to the DP_SYM32_ENC logic */
REG_UPDATE(DP_SYM32_ENC_CONTROL,
DP_SYM32_ENC_RESET, 0);
/* Wait for reset to de-assert */
REG_WAIT(DP_SYM32_ENC_CONTROL,
DP_SYM32_ENC_RESET_DONE, 0,
1, 10);
/* Enable idle pattern generation */
REG_UPDATE(DP_SYM32_ENC_CONTROL,
DP_SYM32_ENC_ENABLE, 1);
}
static void dcn31_hpo_dp_stream_enc_dp_unblank(
struct hpo_dp_stream_encoder *enc,
uint32_t stream_source)
{
struct dcn31_hpo_dp_stream_encoder *enc3 = DCN3_1_HPO_DP_STREAM_ENC_FROM_HPO_STREAM_ENC(enc);
/* Set the input mux for video stream source */
REG_UPDATE(DP_STREAM_ENC_INPUT_MUX_CONTROL,
DP_STREAM_ENC_INPUT_MUX_PIXEL_STREAM_SOURCE_SEL, stream_source);
/* Enable video transmission in main framer */
REG_UPDATE(DP_SYM32_ENC_VID_STREAM_CONTROL,
VID_STREAM_ENABLE, 1);
/* Reset and Enable Pixel to Symbol FIFO */
REG_UPDATE(DP_SYM32_ENC_VID_FIFO_CONTROL,
PIXEL_TO_SYMBOL_FIFO_RESET, 1);
REG_WAIT(DP_SYM32_ENC_VID_FIFO_CONTROL,
PIXEL_TO_SYMBOL_FIFO_RESET_DONE, 1,
1, 10);
REG_UPDATE(DP_SYM32_ENC_VID_FIFO_CONTROL,
PIXEL_TO_SYMBOL_FIFO_RESET, 0);
REG_WAIT(DP_SYM32_ENC_VID_FIFO_CONTROL, /* Disable Clock Ramp Adjuster FIFO */
PIXEL_TO_SYMBOL_FIFO_RESET_DONE, 0,
1, 10);
REG_UPDATE(DP_SYM32_ENC_VID_FIFO_CONTROL,
PIXEL_TO_SYMBOL_FIFO_ENABLE, 1);
/* Reset and Enable Clock Ramp Adjuster FIFO */
REG_UPDATE(DP_STREAM_ENC_CLOCK_RAMP_ADJUSTER_FIFO_STATUS_CONTROL0,
FIFO_RESET, 1);
REG_WAIT(DP_STREAM_ENC_CLOCK_RAMP_ADJUSTER_FIFO_STATUS_CONTROL0,
FIFO_RESET_DONE, 1,
1, 10);
REG_UPDATE(DP_STREAM_ENC_CLOCK_RAMP_ADJUSTER_FIFO_STATUS_CONTROL0,
FIFO_RESET, 0);
REG_WAIT(DP_STREAM_ENC_CLOCK_RAMP_ADJUSTER_FIFO_STATUS_CONTROL0,
FIFO_RESET_DONE, 0,
1, 10);
/* For Debug -- Enable CRC */
REG_UPDATE_2(DP_SYM32_ENC_VID_CRC_CONTROL,
CRC_ENABLE, 1,
CRC_CONT_MODE_ENABLE, 1);
REG_UPDATE(DP_STREAM_ENC_CLOCK_RAMP_ADJUSTER_FIFO_STATUS_CONTROL0,
FIFO_ENABLE, 1);
}
static void dcn31_hpo_dp_stream_enc_dp_blank(
struct hpo_dp_stream_encoder *enc)
{
struct dcn31_hpo_dp_stream_encoder *enc3 = DCN3_1_HPO_DP_STREAM_ENC_FROM_HPO_STREAM_ENC(enc);
/* Disable video transmission */
REG_UPDATE(DP_SYM32_ENC_VID_STREAM_CONTROL,
VID_STREAM_ENABLE, 0);
/* Wait for video stream transmission disabled
* Larger delay to wait until VBLANK - use max retry of
* 10us*5000=50ms. This covers 41.7ms of minimum 24 Hz mode +
* a little more because we may not trust delay accuracy.
*/
REG_WAIT(DP_SYM32_ENC_VID_STREAM_CONTROL,
VID_STREAM_STATUS, 0,
10, 5000);
/* Disable SDP transmission */
REG_UPDATE(DP_SYM32_ENC_SDP_CONTROL,
SDP_STREAM_ENABLE, 0);
/* Disable Pixel to Symbol FIFO */
REG_UPDATE(DP_SYM32_ENC_VID_FIFO_CONTROL,
PIXEL_TO_SYMBOL_FIFO_ENABLE, 0);
/* Disable Clock Ramp Adjuster FIFO */
REG_UPDATE(DP_STREAM_ENC_CLOCK_RAMP_ADJUSTER_FIFO_STATUS_CONTROL0,
FIFO_ENABLE, 0);
}
static void dcn31_hpo_dp_stream_enc_disable(
struct hpo_dp_stream_encoder *enc)
{
struct dcn31_hpo_dp_stream_encoder *enc3 = DCN3_1_HPO_DP_STREAM_ENC_FROM_HPO_STREAM_ENC(enc);
/* Disable DP_SYM32_ENC */
REG_UPDATE(DP_SYM32_ENC_CONTROL,
DP_SYM32_ENC_ENABLE, 0);
/* Disable clocks in the DP_STREAM_ENC */
REG_UPDATE(DP_STREAM_ENC_CLOCK_CONTROL,
DP_STREAM_ENC_CLOCK_EN, 0);
}
static void dcn31_hpo_dp_stream_enc_set_stream_attribute(
struct hpo_dp_stream_encoder *enc,
struct dc_crtc_timing *crtc_timing,
enum dc_color_space output_color_space,
bool use_vsc_sdp_for_colorimetry,
bool compressed_format,
bool double_buffer_en)
{
enum dp2_pixel_encoding pixel_encoding;
enum dp2_uncompressed_component_depth component_depth;
uint32_t h_active_start;
uint32_t v_active_start;
uint32_t h_blank;
uint32_t h_back_porch;
uint32_t h_width;
uint32_t v_height;
uint64_t v_freq;
uint8_t misc0 = 0;
uint8_t misc1 = 0;
uint8_t hsp;
uint8_t vsp;
struct dcn31_hpo_dp_stream_encoder *enc3 = DCN3_1_HPO_DP_STREAM_ENC_FROM_HPO_STREAM_ENC(enc);
struct dc_crtc_timing hw_crtc_timing = *crtc_timing;
/* MISC0[0] = 0 video and link clocks are asynchronous
* MISC1[0] = 0 interlace not supported
* MISC1[2:1] = 0 stereo field is handled by hardware
* MISC1[5:3] = 0 Reserved
*/
/* Interlaced not supported */
if (hw_crtc_timing.flags.INTERLACE) {
BREAK_TO_DEBUGGER();
}
/* Double buffer enable for MSA and pixel format registers
* Only double buffer for changing stream attributes for active streams
* Do not double buffer when initially enabling a stream
*/
REG_UPDATE(DP_SYM32_ENC_VID_MSA_DOUBLE_BUFFER_CONTROL,
MSA_DOUBLE_BUFFER_ENABLE, double_buffer_en);
REG_UPDATE(DP_SYM32_ENC_VID_PIXEL_FORMAT_DOUBLE_BUFFER_CONTROL,
PIXEL_FORMAT_DOUBLE_BUFFER_ENABLE, double_buffer_en);
/* Pixel Encoding */
switch (hw_crtc_timing.pixel_encoding) {
case PIXEL_ENCODING_YCBCR422:
pixel_encoding = DP_SYM32_ENC_PIXEL_ENCODING_YCBCR422;
misc0 = misc0 | 0x2; // MISC0[2:1] = 01
break;
case PIXEL_ENCODING_YCBCR444:
pixel_encoding = DP_SYM32_ENC_PIXEL_ENCODING_RGB_YCBCR444;
misc0 = misc0 | 0x4; // MISC0[2:1] = 10
if (hw_crtc_timing.flags.Y_ONLY) {
pixel_encoding = DP_SYM32_ENC_PIXEL_ENCODING_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
*/
misc1 = misc1 | 0x80; // MISC1[7] = 1
}
}
break;
case PIXEL_ENCODING_YCBCR420:
pixel_encoding = DP_SYM32_ENC_PIXEL_ENCODING_YCBCR420;
misc1 = misc1 | 0x40; // MISC1[6] = 1
break;
case PIXEL_ENCODING_RGB:
default:
pixel_encoding = DP_SYM32_ENC_PIXEL_ENCODING_RGB_YCBCR444;
break;
}
/* 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;
/* Color depth */
switch (hw_crtc_timing.display_color_depth) {
case COLOR_DEPTH_666:
component_depth = DP_SYM32_ENC_COMPONENT_DEPTH_6BPC;
// MISC0[7:5] = 000
break;
case COLOR_DEPTH_888:
component_depth = DP_SYM32_ENC_COMPONENT_DEPTH_8BPC;
misc0 = misc0 | 0x20; // MISC0[7:5] = 001
break;
case COLOR_DEPTH_101010:
component_depth = DP_SYM32_ENC_COMPONENT_DEPTH_10BPC;
misc0 = misc0 | 0x40; // MISC0[7:5] = 010
break;
case COLOR_DEPTH_121212:
component_depth = DP_SYM32_ENC_COMPONENT_DEPTH_12BPC;
misc0 = misc0 | 0x60; // MISC0[7:5] = 011
break;
default:
component_depth = DP_SYM32_ENC_COMPONENT_DEPTH_6BPC;
break;
}
REG_UPDATE_3(DP_SYM32_ENC_VID_PIXEL_FORMAT,
PIXEL_ENCODING_TYPE, compressed_format,
UNCOMPRESSED_PIXEL_ENCODING, pixel_encoding,
UNCOMPRESSED_COMPONENT_DEPTH, component_depth);
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_LIMITED:
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:
default:
/* do nothing */
break;
}
/* 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;
h_width = hw_crtc_timing.h_border_left + hw_crtc_timing.h_addressable + hw_crtc_timing.h_border_right;
v_height = hw_crtc_timing.v_border_top + hw_crtc_timing.v_addressable + hw_crtc_timing.v_border_bottom;
hsp = hw_crtc_timing.flags.HSYNC_POSITIVE_POLARITY ? 0 : 0x80;
vsp = hw_crtc_timing.flags.VSYNC_POSITIVE_POLARITY ? 0 : 0x80;
v_freq = (uint64_t)hw_crtc_timing.pix_clk_100hz * 100;
/* MSA Packet Mapping to 32-bit Link Symbols - DP2 spec, section 2.7.4.1
*
* Lane 0 Lane 1 Lane 2 Lane 3
* MSA[0] = { 0, 0, 0, VFREQ[47:40]}
* MSA[1] = { 0, 0, 0, VFREQ[39:32]}
* MSA[2] = { 0, 0, 0, VFREQ[31:24]}
* MSA[3] = { HTotal[15:8], HStart[15:8], HWidth[15:8], VFREQ[23:16]}
* MSA[4] = { HTotal[ 7:0], HStart[ 7:0], HWidth[ 7:0], VFREQ[15: 8]}
* MSA[5] = { VTotal[15:8], VStart[15:8], VHeight[15:8], VFREQ[ 7: 0]}
* MSA[6] = { VTotal[ 7:0], VStart[ 7:0], VHeight[ 7:0], MISC0[ 7: 0]}
* MSA[7] = { HSP|HSW[14:8], VSP|VSW[14:8], 0, MISC1[ 7: 0]}
* MSA[8] = { HSW[ 7:0], VSW[ 7:0], 0, 0}
*/
REG_SET_4(DP_SYM32_ENC_VID_MSA0, 0,
MSA_DATA_LANE_0, 0,
MSA_DATA_LANE_1, 0,
MSA_DATA_LANE_2, 0,
MSA_DATA_LANE_3, v_freq >> 40);
REG_SET_4(DP_SYM32_ENC_VID_MSA1, 0,
MSA_DATA_LANE_0, 0,
MSA_DATA_LANE_1, 0,
MSA_DATA_LANE_2, 0,
MSA_DATA_LANE_3, (v_freq >> 32) & 0xff);
REG_SET_4(DP_SYM32_ENC_VID_MSA2, 0,
MSA_DATA_LANE_0, 0,
MSA_DATA_LANE_1, 0,
MSA_DATA_LANE_2, 0,
MSA_DATA_LANE_3, (v_freq >> 24) & 0xff);
REG_SET_4(DP_SYM32_ENC_VID_MSA3, 0,
MSA_DATA_LANE_0, hw_crtc_timing.h_total >> 8,
MSA_DATA_LANE_1, h_active_start >> 8,
MSA_DATA_LANE_2, h_width >> 8,
MSA_DATA_LANE_3, (v_freq >> 16) & 0xff);
REG_SET_4(DP_SYM32_ENC_VID_MSA4, 0,
MSA_DATA_LANE_0, hw_crtc_timing.h_total & 0xff,
MSA_DATA_LANE_1, h_active_start & 0xff,
MSA_DATA_LANE_2, h_width & 0xff,
MSA_DATA_LANE_3, (v_freq >> 8) & 0xff);
REG_SET_4(DP_SYM32_ENC_VID_MSA5, 0,
MSA_DATA_LANE_0, hw_crtc_timing.v_total >> 8,
MSA_DATA_LANE_1, v_active_start >> 8,
MSA_DATA_LANE_2, v_height >> 8,
MSA_DATA_LANE_3, v_freq & 0xff);
REG_SET_4(DP_SYM32_ENC_VID_MSA6, 0,
MSA_DATA_LANE_0, hw_crtc_timing.v_total & 0xff,
MSA_DATA_LANE_1, v_active_start & 0xff,
MSA_DATA_LANE_2, v_height & 0xff,
MSA_DATA_LANE_3, misc0);
REG_SET_4(DP_SYM32_ENC_VID_MSA7, 0,
MSA_DATA_LANE_0, hsp | (hw_crtc_timing.h_sync_width >> 8),
MSA_DATA_LANE_1, vsp | (hw_crtc_timing.v_sync_width >> 8),
MSA_DATA_LANE_2, 0,
MSA_DATA_LANE_3, misc1);
REG_SET_4(DP_SYM32_ENC_VID_MSA8, 0,
MSA_DATA_LANE_0, hw_crtc_timing.h_sync_width & 0xff,
MSA_DATA_LANE_1, hw_crtc_timing.v_sync_width & 0xff,
MSA_DATA_LANE_2, 0,
MSA_DATA_LANE_3, 0);
}
static void dcn31_hpo_dp_stream_enc_update_dp_info_packets_sdp_line_num(
struct hpo_dp_stream_encoder *enc,
struct encoder_info_frame *info_frame)
{
struct dcn31_hpo_dp_stream_encoder *enc3 = DCN3_1_HPO_DP_STREAM_ENC_FROM_HPO_STREAM_ENC(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_SYM32_ENC_SDP_GSP_CONTROL5, GSP_SOF_REFERENCE, 1);
REG_UPDATE(DP_SYM32_ENC_SDP_GSP_CONTROL5, GSP_TRANSMISSION_LINE_NUMBER,
info_frame->sdp_line_num.adaptive_sync_line_num);
}
}
static void dcn31_hpo_dp_stream_enc_update_dp_info_packets(
struct hpo_dp_stream_encoder *enc,
const struct encoder_info_frame *info_frame)
{
struct dcn31_hpo_dp_stream_encoder *enc3 = DCN3_1_HPO_DP_STREAM_ENC_FROM_HPO_STREAM_ENC(enc);
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);
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 && !info_frame->firmware_controlled_hdr_info_packet)
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_SYM32_ENC_SDP_GSP_CONTROL0, GSP_VIDEO_CONTINUOUS_TRANSMISSION_ENABLE, info_frame->vsc.valid);
REG_UPDATE(DP_SYM32_ENC_SDP_GSP_CONTROL2, GSP_VIDEO_CONTINUOUS_TRANSMISSION_ENABLE, info_frame->spd.valid);
REG_UPDATE(DP_SYM32_ENC_SDP_GSP_CONTROL3, GSP_VIDEO_CONTINUOUS_TRANSMISSION_ENABLE, info_frame->hdrsmd.valid);
REG_UPDATE(DP_SYM32_ENC_SDP_GSP_CONTROL5, GSP_VIDEO_CONTINUOUS_TRANSMISSION_ENABLE, info_frame->adaptive_sync.valid);
/* check if dynamic metadata packet transmission is enabled */
REG_GET(DP_SYM32_ENC_SDP_METADATA_PACKET_CONTROL,
METADATA_PACKET_ENABLE, &dmdata_packet_enabled);
/* Enable secondary data path */
REG_UPDATE(DP_SYM32_ENC_SDP_CONTROL,
SDP_STREAM_ENABLE, 1);
}
static void dcn31_hpo_dp_stream_enc_stop_dp_info_packets(
struct hpo_dp_stream_encoder *enc)
{
/* stop generic packets on DP */
struct dcn31_hpo_dp_stream_encoder *enc3 = DCN3_1_HPO_DP_STREAM_ENC_FROM_HPO_STREAM_ENC(enc);
uint32_t asp_enable = 0;
uint32_t atp_enable = 0;
uint32_t aip_enable = 0;
uint32_t acm_enable = 0;
REG_UPDATE(DP_SYM32_ENC_SDP_GSP_CONTROL0, GSP_VIDEO_CONTINUOUS_TRANSMISSION_ENABLE, 0);
REG_UPDATE(DP_SYM32_ENC_SDP_GSP_CONTROL2, GSP_VIDEO_CONTINUOUS_TRANSMISSION_ENABLE, 0);
REG_UPDATE(DP_SYM32_ENC_SDP_GSP_CONTROL3, GSP_VIDEO_CONTINUOUS_TRANSMISSION_ENABLE, 0);
/* Disable secondary data path if audio is also disabled */
REG_GET_4(DP_SYM32_ENC_SDP_AUDIO_CONTROL0,
ASP_ENABLE, &asp_enable,
ATP_ENABLE, &atp_enable,
AIP_ENABLE, &aip_enable,
ACM_ENABLE, &acm_enable);
if (!(asp_enable || atp_enable || aip_enable || acm_enable))
REG_UPDATE(DP_SYM32_ENC_SDP_CONTROL,
SDP_STREAM_ENABLE, 0);
}
static uint32_t hpo_dp_is_gsp_enabled(
struct hpo_dp_stream_encoder *enc)
{
struct dcn31_hpo_dp_stream_encoder *enc3 = DCN3_1_HPO_DP_STREAM_ENC_FROM_HPO_STREAM_ENC(enc);
uint32_t gsp0_enabled = 0;
uint32_t gsp2_enabled = 0;
uint32_t gsp3_enabled = 0;
uint32_t gsp11_enabled = 0;
REG_GET(DP_SYM32_ENC_SDP_GSP_CONTROL0, GSP_VIDEO_CONTINUOUS_TRANSMISSION_ENABLE, &gsp0_enabled);
REG_GET(DP_SYM32_ENC_SDP_GSP_CONTROL2, GSP_VIDEO_CONTINUOUS_TRANSMISSION_ENABLE, &gsp2_enabled);
REG_GET(DP_SYM32_ENC_SDP_GSP_CONTROL3, GSP_VIDEO_CONTINUOUS_TRANSMISSION_ENABLE, &gsp3_enabled);
REG_GET(DP_SYM32_ENC_SDP_GSP_CONTROL11, GSP_VIDEO_CONTINUOUS_TRANSMISSION_ENABLE, &gsp11_enabled);
return (gsp0_enabled || gsp2_enabled || gsp3_enabled || gsp11_enabled);
}
static void dcn31_hpo_dp_stream_enc_set_dsc_pps_info_packet(
struct hpo_dp_stream_encoder *enc,
bool enable,
uint8_t *dsc_packed_pps,
bool immediate_update)
{
struct dcn31_hpo_dp_stream_encoder *enc3 = DCN3_1_HPO_DP_STREAM_ENC_FROM_HPO_STREAM_ENC(enc);
if (enable) {
struct dc_info_packet pps_sdp;
int i;
/* Configure for PPS packet size (128 bytes) */
REG_UPDATE(DP_SYM32_ENC_SDP_GSP_CONTROL11,
GSP_PAYLOAD_SIZE, 3);
/* 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);
enc3->base.vpg->funcs->update_generic_info_packet(
enc3->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_SYM32_ENC_SDP_GSP_CONTROL11,
GSP_TRANSMISSION_LINE_NUMBER, 2);
REG_UPDATE_2(DP_SYM32_ENC_VID_VBID_CONTROL,
VBID_6_COMPRESSEDSTREAM_FLAG_SOF_REFERENCE, 0,
VBID_6_COMPRESSEDSTREAM_FLAG_LINE_NUMBER, 3);
/* Send PPS data at the line number specified above. */
REG_UPDATE(DP_SYM32_ENC_SDP_GSP_CONTROL11,
GSP_VIDEO_CONTINUOUS_TRANSMISSION_ENABLE, 1);
REG_UPDATE(DP_SYM32_ENC_SDP_CONTROL,
SDP_STREAM_ENABLE, 1);
} else {
/* Disable Generic Stream Packet 11 (GSP) transmission */
REG_UPDATE_2(DP_SYM32_ENC_SDP_GSP_CONTROL11,
GSP_VIDEO_CONTINUOUS_TRANSMISSION_ENABLE, 0,
GSP_PAYLOAD_SIZE, 0);
}
}
static void dcn31_hpo_dp_stream_enc_map_stream_to_link(
struct hpo_dp_stream_encoder *enc,
uint32_t stream_enc_inst,
uint32_t link_enc_inst)
{
struct dcn31_hpo_dp_stream_encoder *enc3 = DCN3_1_HPO_DP_STREAM_ENC_FROM_HPO_STREAM_ENC(enc);
ASSERT(stream_enc_inst < 4 && link_enc_inst < 2);
switch (stream_enc_inst) {
case 0:
REG_UPDATE(DP_STREAM_MAPPER_CONTROL0,
DP_STREAM_LINK_TARGET, link_enc_inst);
break;
case 1:
REG_UPDATE(DP_STREAM_MAPPER_CONTROL1,
DP_STREAM_LINK_TARGET, link_enc_inst);
break;
case 2:
REG_UPDATE(DP_STREAM_MAPPER_CONTROL2,
DP_STREAM_LINK_TARGET, link_enc_inst);
break;
case 3:
REG_UPDATE(DP_STREAM_MAPPER_CONTROL3,
DP_STREAM_LINK_TARGET, link_enc_inst);
break;
}
}
static void dcn31_hpo_dp_stream_enc_audio_setup(
struct hpo_dp_stream_encoder *enc,
unsigned int az_inst,
struct audio_info *info)
{
struct dcn31_hpo_dp_stream_encoder *enc3 = DCN3_1_HPO_DP_STREAM_ENC_FROM_HPO_STREAM_ENC(enc);
/* Set the input mux for video stream source */
REG_UPDATE(DP_STREAM_ENC_AUDIO_CONTROL,
DP_STREAM_ENC_INPUT_MUX_AUDIO_STREAM_SOURCE_SEL, az_inst);
if (enc3->hpo_se_mask->DP_STREAM_ENC_APG_CLOCK_EN) {
/*enable apg clk*/
REG_UPDATE(DP_STREAM_ENC_AUDIO_CONTROL,
DP_STREAM_ENC_APG_CLOCK_EN, 1);
}
ASSERT(enc->apg);
enc->apg->funcs->se_audio_setup(enc->apg, az_inst, info);
}
static void dcn31_hpo_dp_stream_enc_audio_enable(
struct hpo_dp_stream_encoder *enc)
{
struct dcn31_hpo_dp_stream_encoder *enc3 = DCN3_1_HPO_DP_STREAM_ENC_FROM_HPO_STREAM_ENC(enc);
/* Enable Audio packets */
REG_UPDATE(DP_SYM32_ENC_SDP_AUDIO_CONTROL0, ASP_ENABLE, 1);
/* Program the ATP and AIP next */
REG_UPDATE_2(DP_SYM32_ENC_SDP_AUDIO_CONTROL0,
ATP_ENABLE, 1,
AIP_ENABLE, 1);
/* Enable secondary data path */
REG_UPDATE(DP_SYM32_ENC_SDP_CONTROL,
SDP_STREAM_ENABLE, 1);
/* Enable APG block */
enc->apg->funcs->enable_apg(enc->apg);
}
static void dcn31_hpo_dp_stream_enc_audio_disable(
struct hpo_dp_stream_encoder *enc)
{
struct dcn31_hpo_dp_stream_encoder *enc3 = DCN3_1_HPO_DP_STREAM_ENC_FROM_HPO_STREAM_ENC(enc);
/* Disable Audio packets */
REG_UPDATE_4(DP_SYM32_ENC_SDP_AUDIO_CONTROL0,
ASP_ENABLE, 0,
ATP_ENABLE, 0,
AIP_ENABLE, 0,
ACM_ENABLE, 0);
/* Disable STP Stream Enable if other SDP GSP are also disabled */
if (!(hpo_dp_is_gsp_enabled(enc)))
REG_UPDATE(DP_SYM32_ENC_SDP_CONTROL,
SDP_STREAM_ENABLE, 0);
/* Disable APG block */
enc->apg->funcs->disable_apg(enc->apg);
}
static void dcn31_hpo_dp_stream_enc_read_state(
struct hpo_dp_stream_encoder *enc,
struct hpo_dp_stream_encoder_state *s)
{
struct dcn31_hpo_dp_stream_encoder *enc3 = DCN3_1_HPO_DP_STREAM_ENC_FROM_HPO_STREAM_ENC(enc);
REG_GET(DP_SYM32_ENC_CONTROL,
DP_SYM32_ENC_ENABLE, &s->stream_enc_enabled);
REG_GET(DP_SYM32_ENC_VID_STREAM_CONTROL,
VID_STREAM_ENABLE, &s->vid_stream_enabled);
REG_GET(DP_STREAM_ENC_INPUT_MUX_CONTROL,
DP_STREAM_ENC_INPUT_MUX_PIXEL_STREAM_SOURCE_SEL, &s->otg_inst);
REG_GET_3(DP_SYM32_ENC_VID_PIXEL_FORMAT,
PIXEL_ENCODING_TYPE, &s->compressed_format,
UNCOMPRESSED_PIXEL_ENCODING, &s->pixel_encoding,
UNCOMPRESSED_COMPONENT_DEPTH, &s->component_depth);
REG_GET(DP_SYM32_ENC_SDP_CONTROL,
SDP_STREAM_ENABLE, &s->sdp_enabled);
switch (enc->inst) {
case 0:
REG_GET(DP_STREAM_MAPPER_CONTROL0,
DP_STREAM_LINK_TARGET, &s->mapped_to_link_enc);
break;
case 1:
REG_GET(DP_STREAM_MAPPER_CONTROL1,
DP_STREAM_LINK_TARGET, &s->mapped_to_link_enc);
break;
case 2:
REG_GET(DP_STREAM_MAPPER_CONTROL2,
DP_STREAM_LINK_TARGET, &s->mapped_to_link_enc);
break;
case 3:
REG_GET(DP_STREAM_MAPPER_CONTROL3,
DP_STREAM_LINK_TARGET, &s->mapped_to_link_enc);
break;
}
}
static void dcn31_set_hblank_min_symbol_width(
struct hpo_dp_stream_encoder *enc,
uint16_t width)
{
struct dcn31_hpo_dp_stream_encoder *enc3 = DCN3_1_HPO_DP_STREAM_ENC_FROM_HPO_STREAM_ENC(enc);
REG_SET(DP_SYM32_ENC_HBLANK_CONTROL, 0,
HBLANK_MINIMUM_SYMBOL_WIDTH, width);
}
static const struct hpo_dp_stream_encoder_funcs dcn30_str_enc_funcs = {
.enable_stream = dcn31_hpo_dp_stream_enc_enable_stream,
.dp_unblank = dcn31_hpo_dp_stream_enc_dp_unblank,
.dp_blank = dcn31_hpo_dp_stream_enc_dp_blank,
.disable = dcn31_hpo_dp_stream_enc_disable,
.set_stream_attribute = dcn31_hpo_dp_stream_enc_set_stream_attribute,
.update_dp_info_packets_sdp_line_num = dcn31_hpo_dp_stream_enc_update_dp_info_packets_sdp_line_num,
.update_dp_info_packets = dcn31_hpo_dp_stream_enc_update_dp_info_packets,
.stop_dp_info_packets = dcn31_hpo_dp_stream_enc_stop_dp_info_packets,
.dp_set_dsc_pps_info_packet = dcn31_hpo_dp_stream_enc_set_dsc_pps_info_packet,
.map_stream_to_link = dcn31_hpo_dp_stream_enc_map_stream_to_link,
.dp_audio_setup = dcn31_hpo_dp_stream_enc_audio_setup,
.dp_audio_enable = dcn31_hpo_dp_stream_enc_audio_enable,
.dp_audio_disable = dcn31_hpo_dp_stream_enc_audio_disable,
.read_state = dcn31_hpo_dp_stream_enc_read_state,
.set_hblank_min_symbol_width = dcn31_set_hblank_min_symbol_width,
};
void dcn31_hpo_dp_stream_encoder_construct(
struct dcn31_hpo_dp_stream_encoder *enc3,
struct dc_context *ctx,
struct dc_bios *bp,
uint32_t inst,
enum engine_id eng_id,
struct vpg *vpg,
struct apg *apg,
const struct dcn31_hpo_dp_stream_encoder_registers *regs,
const struct dcn31_hpo_dp_stream_encoder_shift *hpo_se_shift,
const struct dcn31_hpo_dp_stream_encoder_mask *hpo_se_mask)
{
enc3->base.funcs = &dcn30_str_enc_funcs;
enc3->base.ctx = ctx;
enc3->base.inst = inst;
enc3->base.id = eng_id;
enc3->base.bp = bp;
enc3->base.vpg = vpg;
enc3->base.apg = apg;
enc3->regs = regs;
enc3->hpo_se_shift = hpo_se_shift;
enc3->hpo_se_mask = hpo_se_mask;
}
@@ -0,0 +1,298 @@
/*
* Copyright 2019-2026 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 __DAL_DCN31_HPO_DP_STREAM_ENCODER_H__
#define __DAL_DCN31_HPO_DP_STREAM_ENCODER_H__
#include "dcn30/dcn30_vpg.h"
#include "dcn31/dcn31_apg.h"
#include "stream_encoder.h"
#define DCN3_1_HPO_DP_STREAM_ENC_FROM_HPO_STREAM_ENC(hpo_dp_stream_encoder)\
container_of(hpo_dp_stream_encoder, struct dcn31_hpo_dp_stream_encoder, base)
/* Define MSA_DATA_LANE_[0-3] fields to make programming easier */
#define DP_SYM32_ENC_VID_MSA__MSA_DATA_LANE_0__SHIFT 0x0
#define DP_SYM32_ENC_VID_MSA__MSA_DATA_LANE_1__SHIFT 0x8
#define DP_SYM32_ENC_VID_MSA__MSA_DATA_LANE_2__SHIFT 0x10
#define DP_SYM32_ENC_VID_MSA__MSA_DATA_LANE_3__SHIFT 0x18
#define DP_SYM32_ENC_VID_MSA__MSA_DATA_LANE_0_MASK 0x000000FFL
#define DP_SYM32_ENC_VID_MSA__MSA_DATA_LANE_1_MASK 0x0000FF00L
#define DP_SYM32_ENC_VID_MSA__MSA_DATA_LANE_2_MASK 0x00FF0000L
#define DP_SYM32_ENC_VID_MSA__MSA_DATA_LANE_3_MASK 0xFF000000L
#define DCN3_1_HPO_DP_STREAM_ENC_REG_LIST(id) \
SR(DP_STREAM_MAPPER_CONTROL0),\
SR(DP_STREAM_MAPPER_CONTROL1),\
SR(DP_STREAM_MAPPER_CONTROL2),\
SR(DP_STREAM_MAPPER_CONTROL3),\
SRI(DP_STREAM_ENC_CLOCK_CONTROL, DP_STREAM_ENC, id),\
SRI(DP_STREAM_ENC_INPUT_MUX_CONTROL, DP_STREAM_ENC, id),\
SRI(DP_STREAM_ENC_AUDIO_CONTROL, DP_STREAM_ENC, id),\
SRI(DP_STREAM_ENC_CLOCK_RAMP_ADJUSTER_FIFO_STATUS_CONTROL0, DP_STREAM_ENC, id),\
SRI(DP_SYM32_ENC_CONTROL, DP_SYM32_ENC, id),\
SRI(DP_SYM32_ENC_VID_PIXEL_FORMAT, DP_SYM32_ENC, id),\
SRI(DP_SYM32_ENC_VID_PIXEL_FORMAT_DOUBLE_BUFFER_CONTROL, DP_SYM32_ENC, id),\
SRI(DP_SYM32_ENC_VID_MSA0, DP_SYM32_ENC, id),\
SRI(DP_SYM32_ENC_VID_MSA1, DP_SYM32_ENC, id),\
SRI(DP_SYM32_ENC_VID_MSA2, DP_SYM32_ENC, id),\
SRI(DP_SYM32_ENC_VID_MSA3, DP_SYM32_ENC, id),\
SRI(DP_SYM32_ENC_VID_MSA4, DP_SYM32_ENC, id),\
SRI(DP_SYM32_ENC_VID_MSA5, DP_SYM32_ENC, id),\
SRI(DP_SYM32_ENC_VID_MSA6, DP_SYM32_ENC, id),\
SRI(DP_SYM32_ENC_VID_MSA7, DP_SYM32_ENC, id),\
SRI(DP_SYM32_ENC_VID_MSA8, DP_SYM32_ENC, id),\
SRI(DP_SYM32_ENC_VID_MSA_CONTROL, DP_SYM32_ENC, id),\
SRI(DP_SYM32_ENC_VID_MSA_DOUBLE_BUFFER_CONTROL, DP_SYM32_ENC, id),\
SRI(DP_SYM32_ENC_VID_FIFO_CONTROL, DP_SYM32_ENC, id),\
SRI(DP_SYM32_ENC_VID_STREAM_CONTROL, DP_SYM32_ENC, id),\
SRI(DP_SYM32_ENC_VID_VBID_CONTROL, DP_SYM32_ENC, id),\
SRI(DP_SYM32_ENC_SDP_CONTROL, DP_SYM32_ENC, id),\
SRI(DP_SYM32_ENC_SDP_GSP_CONTROL0, DP_SYM32_ENC, id),\
SRI(DP_SYM32_ENC_SDP_GSP_CONTROL2, DP_SYM32_ENC, id),\
SRI(DP_SYM32_ENC_SDP_GSP_CONTROL3, DP_SYM32_ENC, id),\
SRI(DP_SYM32_ENC_SDP_GSP_CONTROL5, DP_SYM32_ENC, id),\
SRI(DP_SYM32_ENC_SDP_GSP_CONTROL11, DP_SYM32_ENC, id),\
SRI(DP_SYM32_ENC_SDP_METADATA_PACKET_CONTROL, DP_SYM32_ENC, id),\
SRI(DP_SYM32_ENC_SDP_AUDIO_CONTROL0, DP_SYM32_ENC, id),\
SRI(DP_SYM32_ENC_VID_CRC_CONTROL, DP_SYM32_ENC, id), \
SRI(DP_SYM32_ENC_HBLANK_CONTROL, DP_SYM32_ENC, id)
#define DCN3_1_HPO_DP_STREAM_ENC_REGS \
uint32_t DP_STREAM_MAPPER_CONTROL0;\
uint32_t DP_STREAM_MAPPER_CONTROL1;\
uint32_t DP_STREAM_MAPPER_CONTROL2;\
uint32_t DP_STREAM_MAPPER_CONTROL3;\
uint32_t DP_STREAM_ENC_CLOCK_CONTROL;\
uint32_t DP_STREAM_ENC_INPUT_MUX_CONTROL;\
uint32_t DP_STREAM_ENC_AUDIO_CONTROL;\
uint32_t DP_STREAM_ENC_CLOCK_RAMP_ADJUSTER_FIFO_STATUS_CONTROL0;\
uint32_t DP_SYM32_ENC_CONTROL;\
uint32_t DP_SYM32_ENC_VID_PIXEL_FORMAT;\
uint32_t DP_SYM32_ENC_VID_PIXEL_FORMAT_DOUBLE_BUFFER_CONTROL;\
uint32_t DP_SYM32_ENC_VID_MSA0;\
uint32_t DP_SYM32_ENC_VID_MSA1;\
uint32_t DP_SYM32_ENC_VID_MSA2;\
uint32_t DP_SYM32_ENC_VID_MSA3;\
uint32_t DP_SYM32_ENC_VID_MSA4;\
uint32_t DP_SYM32_ENC_VID_MSA5;\
uint32_t DP_SYM32_ENC_VID_MSA6;\
uint32_t DP_SYM32_ENC_VID_MSA7;\
uint32_t DP_SYM32_ENC_VID_MSA8;\
uint32_t DP_SYM32_ENC_VID_MSA_CONTROL;\
uint32_t DP_SYM32_ENC_VID_MSA_DOUBLE_BUFFER_CONTROL;\
uint32_t DP_SYM32_ENC_VID_FIFO_CONTROL;\
uint32_t DP_SYM32_ENC_VID_STREAM_CONTROL;\
uint32_t DP_SYM32_ENC_VID_VBID_CONTROL;\
uint32_t DP_SYM32_ENC_SDP_CONTROL;\
uint32_t DP_SYM32_ENC_SDP_GSP_CONTROL0;\
uint32_t DP_SYM32_ENC_SDP_GSP_CONTROL2;\
uint32_t DP_SYM32_ENC_SDP_GSP_CONTROL3;\
uint32_t DP_SYM32_ENC_SDP_GSP_CONTROL5;\
uint32_t DP_SYM32_ENC_SDP_GSP_CONTROL11;\
uint32_t DP_SYM32_ENC_SDP_METADATA_PACKET_CONTROL;\
uint32_t DP_SYM32_ENC_SDP_AUDIO_CONTROL0;\
uint32_t DP_SYM32_ENC_VID_CRC_CONTROL;\
uint32_t DP_SYM32_ENC_HBLANK_CONTROL
#define DCN3_1_HPO_DP_STREAM_ENC_MASK_SH_LIST(mask_sh)\
SE_SF(DP_STREAM_MAPPER_CONTROL0, DP_STREAM_LINK_TARGET, mask_sh),\
SE_SF(DP_STREAM_ENC0_DP_STREAM_ENC_CLOCK_CONTROL, DP_STREAM_ENC_CLOCK_EN, mask_sh),\
SE_SF(DP_STREAM_ENC0_DP_STREAM_ENC_INPUT_MUX_CONTROL, DP_STREAM_ENC_INPUT_MUX_PIXEL_STREAM_SOURCE_SEL, mask_sh),\
SE_SF(DP_STREAM_ENC0_DP_STREAM_ENC_AUDIO_CONTROL, DP_STREAM_ENC_INPUT_MUX_AUDIO_STREAM_SOURCE_SEL, mask_sh),\
SE_SF(DP_STREAM_ENC0_DP_STREAM_ENC_CLOCK_RAMP_ADJUSTER_FIFO_STATUS_CONTROL0, FIFO_RESET, mask_sh),\
SE_SF(DP_STREAM_ENC0_DP_STREAM_ENC_CLOCK_RAMP_ADJUSTER_FIFO_STATUS_CONTROL0, FIFO_RESET_DONE, mask_sh),\
SE_SF(DP_STREAM_ENC0_DP_STREAM_ENC_CLOCK_RAMP_ADJUSTER_FIFO_STATUS_CONTROL0, FIFO_ENABLE, mask_sh),\
SE_SF(DP_SYM32_ENC0_DP_SYM32_ENC_CONTROL, DP_SYM32_ENC_RESET, mask_sh),\
SE_SF(DP_SYM32_ENC0_DP_SYM32_ENC_CONTROL, DP_SYM32_ENC_RESET_DONE, mask_sh),\
SE_SF(DP_SYM32_ENC0_DP_SYM32_ENC_CONTROL, DP_SYM32_ENC_ENABLE, mask_sh),\
SE_SF(DP_SYM32_ENC0_DP_SYM32_ENC_VID_PIXEL_FORMAT, PIXEL_ENCODING_TYPE, mask_sh),\
SE_SF(DP_SYM32_ENC0_DP_SYM32_ENC_VID_PIXEL_FORMAT, UNCOMPRESSED_PIXEL_ENCODING, mask_sh),\
SE_SF(DP_SYM32_ENC0_DP_SYM32_ENC_VID_PIXEL_FORMAT, UNCOMPRESSED_COMPONENT_DEPTH, mask_sh),\
SE_SF(DP_SYM32_ENC0_DP_SYM32_ENC_VID_PIXEL_FORMAT_DOUBLE_BUFFER_CONTROL, PIXEL_FORMAT_DOUBLE_BUFFER_ENABLE, mask_sh),\
SE_SF(DP_SYM32_ENC0_DP_SYM32_ENC_VID_MSA_DOUBLE_BUFFER_CONTROL, MSA_DOUBLE_BUFFER_ENABLE, mask_sh),\
SE_SF(DP_SYM32_ENC_VID_MSA, MSA_DATA_LANE_0, mask_sh),\
SE_SF(DP_SYM32_ENC_VID_MSA, MSA_DATA_LANE_1, mask_sh),\
SE_SF(DP_SYM32_ENC_VID_MSA, MSA_DATA_LANE_2, mask_sh),\
SE_SF(DP_SYM32_ENC_VID_MSA, MSA_DATA_LANE_3, mask_sh),\
SE_SF(DP_SYM32_ENC0_DP_SYM32_ENC_VID_FIFO_CONTROL, PIXEL_TO_SYMBOL_FIFO_RESET, mask_sh),\
SE_SF(DP_SYM32_ENC0_DP_SYM32_ENC_VID_FIFO_CONTROL, PIXEL_TO_SYMBOL_FIFO_RESET_DONE, mask_sh),\
SE_SF(DP_SYM32_ENC0_DP_SYM32_ENC_VID_FIFO_CONTROL, PIXEL_TO_SYMBOL_FIFO_ENABLE, mask_sh),\
SE_SF(DP_SYM32_ENC0_DP_SYM32_ENC_VID_STREAM_CONTROL, VID_STREAM_ENABLE, mask_sh),\
SE_SF(DP_SYM32_ENC0_DP_SYM32_ENC_VID_STREAM_CONTROL, VID_STREAM_STATUS, mask_sh),\
SE_SF(DP_SYM32_ENC0_DP_SYM32_ENC_VID_VBID_CONTROL, VBID_6_COMPRESSEDSTREAM_FLAG_SOF_REFERENCE, mask_sh),\
SE_SF(DP_SYM32_ENC0_DP_SYM32_ENC_VID_VBID_CONTROL, VBID_6_COMPRESSEDSTREAM_FLAG_LINE_NUMBER, mask_sh),\
SE_SF(DP_SYM32_ENC0_DP_SYM32_ENC_SDP_CONTROL, SDP_STREAM_ENABLE, mask_sh),\
SE_SF(DP_SYM32_ENC0_DP_SYM32_ENC_SDP_GSP_CONTROL0, GSP_VIDEO_CONTINUOUS_TRANSMISSION_ENABLE, mask_sh),\
SE_SF(DP_SYM32_ENC0_DP_SYM32_ENC_SDP_GSP_CONTROL0, GSP_PAYLOAD_SIZE, mask_sh),\
SE_SF(DP_SYM32_ENC0_DP_SYM32_ENC_SDP_GSP_CONTROL0, GSP_TRANSMISSION_LINE_NUMBER, mask_sh),\
SE_SF(DP_SYM32_ENC0_DP_SYM32_ENC_SDP_GSP_CONTROL5, GSP_VIDEO_CONTINUOUS_TRANSMISSION_ENABLE, mask_sh),\
SE_SF(DP_SYM32_ENC0_DP_SYM32_ENC_SDP_GSP_CONTROL5, GSP_TRANSMISSION_LINE_NUMBER, mask_sh),\
SE_SF(DP_SYM32_ENC0_DP_SYM32_ENC_SDP_GSP_CONTROL5, GSP_SOF_REFERENCE, mask_sh),\
SE_SF(DP_SYM32_ENC0_DP_SYM32_ENC_SDP_METADATA_PACKET_CONTROL, METADATA_PACKET_ENABLE, mask_sh),\
SE_SF(DP_SYM32_ENC0_DP_SYM32_ENC_SDP_AUDIO_CONTROL0, AUDIO_MUTE, mask_sh),\
SE_SF(DP_SYM32_ENC0_DP_SYM32_ENC_SDP_AUDIO_CONTROL0, ASP_ENABLE, mask_sh),\
SE_SF(DP_SYM32_ENC0_DP_SYM32_ENC_SDP_AUDIO_CONTROL0, ATP_ENABLE, mask_sh),\
SE_SF(DP_SYM32_ENC0_DP_SYM32_ENC_SDP_AUDIO_CONTROL0, AIP_ENABLE, mask_sh),\
SE_SF(DP_SYM32_ENC0_DP_SYM32_ENC_SDP_AUDIO_CONTROL0, ACM_ENABLE, mask_sh),\
SE_SF(DP_SYM32_ENC0_DP_SYM32_ENC_VID_CRC_CONTROL, CRC_ENABLE, mask_sh),\
SE_SF(DP_SYM32_ENC0_DP_SYM32_ENC_VID_CRC_CONTROL, CRC_CONT_MODE_ENABLE, mask_sh),\
SE_SF(DP_SYM32_ENC0_DP_SYM32_ENC_HBLANK_CONTROL, HBLANK_MINIMUM_SYMBOL_WIDTH, mask_sh)
/* Not in DCN42B:
* SE_SF(DP_SYM32_ENC0_DP_SYM32_ENC_VID_CRC_CONTROL, CRC_ENABLE, mask_sh),
* SE_SF(DP_SYM32_ENC0_DP_SYM32_ENC_VID_CRC_CONTROL, CRC_CONT_MODE_ENABLE, mask_sh),
* SE_SF(DP_SYM32_ENC0_DP_SYM32_ENC_HBLANK_CONTROL, HBLANK_MINIMUM_SYMBOL_WIDTH, mask_sh),
*/
#define DCN4_2B_HPO_DP_STREAM_ENC_MASK_SH_LIST(mask_sh)\
SE_SF(DP_STREAM_MAPPER_CONTROL0, DP_STREAM_LINK_TARGET, mask_sh),\
SE_SF(DP_STREAM_ENC0_DP_STREAM_ENC_CLOCK_CONTROL, DP_STREAM_ENC_CLOCK_EN, mask_sh),\
SE_SF(DP_STREAM_ENC0_DP_STREAM_ENC_INPUT_MUX_CONTROL, DP_STREAM_ENC_INPUT_MUX_PIXEL_STREAM_SOURCE_SEL, mask_sh),\
SE_SF(DP_STREAM_ENC0_DP_STREAM_ENC_AUDIO_CONTROL, DP_STREAM_ENC_INPUT_MUX_AUDIO_STREAM_SOURCE_SEL, mask_sh),\
SE_SF(DP_STREAM_ENC0_DP_STREAM_ENC_AUDIO_CONTROL, DP_STREAM_ENC_APG_CLOCK_EN, mask_sh),\
SE_SF(DP_STREAM_ENC0_DP_STREAM_ENC_CLOCK_RAMP_ADJUSTER_FIFO_STATUS_CONTROL0, FIFO_RESET, mask_sh),\
SE_SF(DP_STREAM_ENC0_DP_STREAM_ENC_CLOCK_RAMP_ADJUSTER_FIFO_STATUS_CONTROL0, FIFO_RESET_DONE, mask_sh),\
SE_SF(DP_STREAM_ENC0_DP_STREAM_ENC_CLOCK_RAMP_ADJUSTER_FIFO_STATUS_CONTROL0, FIFO_ENABLE, mask_sh),\
SE_SF(DP_SYM32_ENC0_DP_SYM32_ENC_CONTROL, DP_SYM32_ENC_RESET, mask_sh),\
SE_SF(DP_SYM32_ENC0_DP_SYM32_ENC_CONTROL, DP_SYM32_ENC_RESET_DONE, mask_sh),\
SE_SF(DP_SYM32_ENC0_DP_SYM32_ENC_CONTROL, DP_SYM32_ENC_ENABLE, mask_sh),\
SE_SF(DP_SYM32_ENC0_DP_SYM32_ENC_VID_PIXEL_FORMAT, PIXEL_ENCODING_TYPE, mask_sh),\
SE_SF(DP_SYM32_ENC0_DP_SYM32_ENC_VID_PIXEL_FORMAT, UNCOMPRESSED_PIXEL_ENCODING, mask_sh),\
SE_SF(DP_SYM32_ENC0_DP_SYM32_ENC_VID_PIXEL_FORMAT, UNCOMPRESSED_COMPONENT_DEPTH, mask_sh),\
SE_SF(DP_SYM32_ENC0_DP_SYM32_ENC_VID_PIXEL_FORMAT_DOUBLE_BUFFER_CONTROL, PIXEL_FORMAT_DOUBLE_BUFFER_ENABLE, mask_sh),\
SE_SF(DP_SYM32_ENC0_DP_SYM32_ENC_VID_MSA_DOUBLE_BUFFER_CONTROL, MSA_DOUBLE_BUFFER_ENABLE, mask_sh),\
SE_SF(DP_SYM32_ENC_VID_MSA, MSA_DATA_LANE_0, mask_sh),\
SE_SF(DP_SYM32_ENC_VID_MSA, MSA_DATA_LANE_1, mask_sh),\
SE_SF(DP_SYM32_ENC_VID_MSA, MSA_DATA_LANE_2, mask_sh),\
SE_SF(DP_SYM32_ENC_VID_MSA, MSA_DATA_LANE_3, mask_sh),\
SE_SF(DP_SYM32_ENC0_DP_SYM32_ENC_VID_FIFO_CONTROL, PIXEL_TO_SYMBOL_FIFO_RESET, mask_sh),\
SE_SF(DP_SYM32_ENC0_DP_SYM32_ENC_VID_FIFO_CONTROL, PIXEL_TO_SYMBOL_FIFO_RESET_DONE, mask_sh),\
SE_SF(DP_SYM32_ENC0_DP_SYM32_ENC_VID_FIFO_CONTROL, PIXEL_TO_SYMBOL_FIFO_ENABLE, mask_sh),\
SE_SF(DP_SYM32_ENC0_DP_SYM32_ENC_VID_STREAM_CONTROL, VID_STREAM_ENABLE, mask_sh),\
SE_SF(DP_SYM32_ENC0_DP_SYM32_ENC_VID_STREAM_CONTROL, VID_STREAM_STATUS, mask_sh),\
SE_SF(DP_SYM32_ENC0_DP_SYM32_ENC_VID_VBID_CONTROL, VBID_6_COMPRESSEDSTREAM_FLAG_SOF_REFERENCE, mask_sh),\
SE_SF(DP_SYM32_ENC0_DP_SYM32_ENC_VID_VBID_CONTROL, VBID_6_COMPRESSEDSTREAM_FLAG_LINE_NUMBER, mask_sh),\
SE_SF(DP_SYM32_ENC0_DP_SYM32_ENC_SDP_CONTROL, SDP_STREAM_ENABLE, mask_sh),\
SE_SF(DP_SYM32_ENC0_DP_SYM32_ENC_SDP_GSP_CONTROL0, GSP_VIDEO_CONTINUOUS_TRANSMISSION_ENABLE, mask_sh),\
SE_SF(DP_SYM32_ENC0_DP_SYM32_ENC_SDP_GSP_CONTROL0, GSP_PAYLOAD_SIZE, mask_sh),\
SE_SF(DP_SYM32_ENC0_DP_SYM32_ENC_SDP_GSP_CONTROL0, GSP_TRANSMISSION_LINE_NUMBER, mask_sh),\
SE_SF(DP_SYM32_ENC0_DP_SYM32_ENC_SDP_GSP_CONTROL5, GSP_VIDEO_CONTINUOUS_TRANSMISSION_ENABLE, mask_sh),\
SE_SF(DP_SYM32_ENC0_DP_SYM32_ENC_SDP_GSP_CONTROL5, GSP_TRANSMISSION_LINE_NUMBER, mask_sh),\
SE_SF(DP_SYM32_ENC0_DP_SYM32_ENC_SDP_GSP_CONTROL5, GSP_SOF_REFERENCE, mask_sh),\
SE_SF(DP_SYM32_ENC0_DP_SYM32_ENC_SDP_METADATA_PACKET_CONTROL, METADATA_PACKET_ENABLE, mask_sh),\
SE_SF(DP_SYM32_ENC0_DP_SYM32_ENC_SDP_AUDIO_CONTROL0, AUDIO_MUTE, mask_sh),\
SE_SF(DP_SYM32_ENC0_DP_SYM32_ENC_SDP_AUDIO_CONTROL0, ASP_ENABLE, mask_sh),\
SE_SF(DP_SYM32_ENC0_DP_SYM32_ENC_SDP_AUDIO_CONTROL0, ATP_ENABLE, mask_sh),\
SE_SF(DP_SYM32_ENC0_DP_SYM32_ENC_SDP_AUDIO_CONTROL0, AIP_ENABLE, mask_sh),\
SE_SF(DP_SYM32_ENC0_DP_SYM32_ENC_SDP_AUDIO_CONTROL0, ACM_ENABLE, mask_sh)
#define DCN3_1_HPO_DP_STREAM_ENC_REG_FIELD_LIST(type) \
type DP_STREAM_LINK_TARGET;\
type DP_STREAM_ENC_CLOCK_EN;\
type DP_STREAM_ENC_INPUT_MUX_PIXEL_STREAM_SOURCE_SEL;\
type DP_STREAM_ENC_INPUT_MUX_AUDIO_STREAM_SOURCE_SEL;\
type FIFO_RESET;\
type FIFO_RESET_DONE;\
type FIFO_ENABLE;\
type DP_SYM32_ENC_RESET;\
type DP_SYM32_ENC_RESET_DONE;\
type DP_SYM32_ENC_ENABLE;\
type PIXEL_ENCODING_TYPE;\
type UNCOMPRESSED_PIXEL_ENCODING;\
type UNCOMPRESSED_COMPONENT_DEPTH;\
type PIXEL_FORMAT_DOUBLE_BUFFER_ENABLE;\
type MSA_DOUBLE_BUFFER_ENABLE;\
type MSA_DATA_LANE_0;\
type MSA_DATA_LANE_1;\
type MSA_DATA_LANE_2;\
type MSA_DATA_LANE_3;\
type PIXEL_TO_SYMBOL_FIFO_RESET;\
type PIXEL_TO_SYMBOL_FIFO_RESET_DONE;\
type PIXEL_TO_SYMBOL_FIFO_ENABLE;\
type VID_STREAM_ENABLE;\
type VID_STREAM_STATUS;\
type VBID_6_COMPRESSEDSTREAM_FLAG_SOF_REFERENCE;\
type VBID_6_COMPRESSEDSTREAM_FLAG_LINE_NUMBER;\
type SDP_STREAM_ENABLE;\
type AUDIO_MUTE;\
type ASP_ENABLE;\
type ATP_ENABLE;\
type AIP_ENABLE;\
type ACM_ENABLE;\
type GSP_VIDEO_CONTINUOUS_TRANSMISSION_ENABLE;\
type GSP_PAYLOAD_SIZE;\
type GSP_TRANSMISSION_LINE_NUMBER;\
type GSP_SOF_REFERENCE;\
type METADATA_PACKET_ENABLE;\
type CRC_ENABLE;\
type CRC_CONT_MODE_ENABLE;\
type HBLANK_MINIMUM_SYMBOL_WIDTH
#define DCN4_2_HPO_DP_STREAM_ENC_REG_FIELD_LIST(type) \
type DP_STREAM_ENC_APG_CLOCK_EN
#define DCN4_2_HPO_DP_STREAM_ENC_MASK_SH_LIST(mask_sh)\
DCN3_1_HPO_DP_STREAM_ENC_MASK_SH_LIST(mask_sh),\
SE_SF(DP_STREAM_ENC0_DP_STREAM_ENC_AUDIO_CONTROL, DP_STREAM_ENC_APG_CLOCK_EN, mask_sh)
struct dcn31_hpo_dp_stream_encoder_registers {
DCN3_1_HPO_DP_STREAM_ENC_REGS;
};
struct dcn31_hpo_dp_stream_encoder_shift {
DCN3_1_HPO_DP_STREAM_ENC_REG_FIELD_LIST(uint8_t);
DCN4_2_HPO_DP_STREAM_ENC_REG_FIELD_LIST(uint8_t);
};
struct dcn31_hpo_dp_stream_encoder_mask {
DCN3_1_HPO_DP_STREAM_ENC_REG_FIELD_LIST(uint32_t);
DCN4_2_HPO_DP_STREAM_ENC_REG_FIELD_LIST(uint32_t);
};
struct dcn31_hpo_dp_stream_encoder {
struct hpo_dp_stream_encoder base;
const struct dcn31_hpo_dp_stream_encoder_registers *regs;
const struct dcn31_hpo_dp_stream_encoder_shift *hpo_se_shift;
const struct dcn31_hpo_dp_stream_encoder_mask *hpo_se_mask;
};
void dcn31_hpo_dp_stream_encoder_construct(
struct dcn31_hpo_dp_stream_encoder *enc3,
struct dc_context *ctx,
struct dc_bios *bp,
uint32_t inst,
enum engine_id eng_id,
struct vpg *vpg,
struct apg *apg,
const struct dcn31_hpo_dp_stream_encoder_registers *regs,
const struct dcn31_hpo_dp_stream_encoder_shift *hpo_se_shift,
const struct dcn31_hpo_dp_stream_encoder_mask *hpo_se_mask);
#endif // __DAL_DCN31_HPO_STREAM_ENCODER_H__
@@ -0,0 +1,89 @@
/*
* Copyright 2019 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 "dcn31/dcn31_hpo_dp_link_encoder.h"
#include "dcn32_hpo_dp_link_encoder.h"
#include "reg_helper.h"
#include "stream_encoder.h"
#define DC_LOGGER \
enc3->base.ctx->logger
#define REG(reg)\
(enc3->regs->reg)
#undef FN
#define FN(reg_name, field_name) \
enc3->hpo_le_shift->field_name, enc3->hpo_le_mask->field_name
#define CTX \
enc3->base.ctx
bool dcn32_hpo_dp_link_enc_is_in_alt_mode(
struct hpo_dp_link_encoder *enc)
{
struct dcn31_hpo_dp_link_encoder *enc3 = DCN3_1_HPO_DP_LINK_ENC_FROM_HPO_LINK_ENC(enc);
uint32_t dp_alt_mode_disable = 0;
ASSERT((enc->transmitter >= TRANSMITTER_UNIPHY_A) && (enc->transmitter <= TRANSMITTER_UNIPHY_E));
/* if value == 1 alt mode is disabled, otherwise it is enabled */
REG_GET(RDPCSTX_PHY_CNTL6[enc->transmitter], RDPCS_PHY_DPALT_DISABLE, &dp_alt_mode_disable);
return (dp_alt_mode_disable == 0);
}
static struct hpo_dp_link_encoder_funcs dcn32_hpo_dp_link_encoder_funcs = {
.enable_link_phy = dcn31_hpo_dp_link_enc_enable_dp_output,
.disable_link_phy = dcn31_hpo_dp_link_enc_disable_output,
.link_enable = dcn31_hpo_dp_link_enc_enable,
.link_disable = dcn31_hpo_dp_link_enc_disable,
.set_link_test_pattern = dcn31_hpo_dp_link_enc_set_link_test_pattern,
.update_stream_allocation_table = dcn31_hpo_dp_link_enc_update_stream_allocation_table,
.set_throttled_vcp_size = dcn31_hpo_dp_link_enc_set_throttled_vcp_size,
.is_in_alt_mode = dcn32_hpo_dp_link_enc_is_in_alt_mode,
.read_state = dcn31_hpo_dp_link_enc_read_state,
.set_ffe = dcn31_hpo_dp_link_enc_set_ffe,
};
void hpo_dp_link_encoder32_construct(struct dcn31_hpo_dp_link_encoder *enc31,
struct dc_context *ctx,
uint32_t inst,
const struct dcn31_hpo_dp_link_encoder_registers *hpo_le_regs,
const struct dcn31_hpo_dp_link_encoder_shift *hpo_le_shift,
const struct dcn31_hpo_dp_link_encoder_mask *hpo_le_mask)
{
enc31->base.ctx = ctx;
enc31->base.inst = inst;
enc31->base.funcs = &dcn32_hpo_dp_link_encoder_funcs;
enc31->base.hpd_source = HPD_SOURCEID_UNKNOWN;
enc31->base.transmitter = TRANSMITTER_UNKNOWN;
enc31->regs = hpo_le_regs;
enc31->hpo_le_shift = hpo_le_shift;
enc31->hpo_le_mask = hpo_le_mask;
}
@@ -0,0 +1,68 @@
/*
* Copyright 2021 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 __DAL_DCN32_HPO_DP_LINK_ENCODER_H__
#define __DAL_DCN32_HPO_DP_LINK_ENCODER_H__
#include "link_encoder.h"
#define DCN3_2_HPO_DP_LINK_ENC_MASK_SH_LIST(mask_sh)\
SE_SF(DP_LINK_ENC0_DP_LINK_ENC_CLOCK_CONTROL, DP_LINK_ENC_CLOCK_EN, mask_sh),\
SE_SF(DP_DPHY_SYM320_DP_DPHY_SYM32_CONTROL, DPHY_RESET, mask_sh),\
SE_SF(DP_DPHY_SYM320_DP_DPHY_SYM32_CONTROL, DPHY_ENABLE, mask_sh),\
SE_SF(DP_DPHY_SYM320_DP_DPHY_SYM32_CONTROL, PRECODER_ENABLE, mask_sh),\
SE_SF(DP_DPHY_SYM320_DP_DPHY_SYM32_CONTROL, MODE, mask_sh),\
SE_SF(DP_DPHY_SYM320_DP_DPHY_SYM32_CONTROL, NUM_LANES, mask_sh),\
SE_SF(DP_DPHY_SYM320_DP_DPHY_SYM32_STATUS, STATUS, mask_sh),\
SE_SF(DP_DPHY_SYM320_DP_DPHY_SYM32_STATUS, SAT_UPDATE_PENDING, mask_sh),\
SE_SF(DP_DPHY_SYM320_DP_DPHY_SYM32_STATUS, RATE_UPDATE_PENDING, mask_sh),\
SE_SF(DP_DPHY_SYM320_DP_DPHY_SYM32_TP_CUSTOM0, TP_CUSTOM, mask_sh),\
SE_SF(DP_DPHY_SYM320_DP_DPHY_SYM32_TP_CONFIG, TP_SELECT0, mask_sh),\
SE_SF(DP_DPHY_SYM320_DP_DPHY_SYM32_TP_CONFIG, TP_SELECT1, mask_sh),\
SE_SF(DP_DPHY_SYM320_DP_DPHY_SYM32_TP_CONFIG, TP_SELECT2, mask_sh),\
SE_SF(DP_DPHY_SYM320_DP_DPHY_SYM32_TP_CONFIG, TP_SELECT3, mask_sh),\
SE_SF(DP_DPHY_SYM320_DP_DPHY_SYM32_TP_CONFIG, TP_PRBS_SEL0, mask_sh),\
SE_SF(DP_DPHY_SYM320_DP_DPHY_SYM32_TP_CONFIG, TP_PRBS_SEL1, mask_sh),\
SE_SF(DP_DPHY_SYM320_DP_DPHY_SYM32_TP_CONFIG, TP_PRBS_SEL2, mask_sh),\
SE_SF(DP_DPHY_SYM320_DP_DPHY_SYM32_TP_CONFIG, TP_PRBS_SEL3, mask_sh),\
SE_SF(DP_DPHY_SYM320_DP_DPHY_SYM32_TP_SQ_PULSE, TP_SQ_PULSE_WIDTH, mask_sh),\
SE_SF(DP_DPHY_SYM320_DP_DPHY_SYM32_SAT_VC0, SAT_STREAM_SOURCE, mask_sh),\
SE_SF(DP_DPHY_SYM320_DP_DPHY_SYM32_SAT_VC0, SAT_SLOT_COUNT, mask_sh),\
SE_SF(DP_DPHY_SYM320_DP_DPHY_SYM32_VC_RATE_CNTL0, STREAM_VC_RATE_X, mask_sh),\
SE_SF(DP_DPHY_SYM320_DP_DPHY_SYM32_VC_RATE_CNTL0, STREAM_VC_RATE_Y, mask_sh),\
SE_SF(DP_DPHY_SYM320_DP_DPHY_SYM32_SAT_UPDATE, SAT_UPDATE, mask_sh)
bool dcn32_hpo_dp_link_enc_is_in_alt_mode(struct hpo_dp_link_encoder *enc);
void hpo_dp_link_encoder32_construct(struct dcn31_hpo_dp_link_encoder *enc31,
struct dc_context *ctx,
uint32_t inst,
const struct dcn31_hpo_dp_link_encoder_registers *hpo_le_regs,
const struct dcn31_hpo_dp_link_encoder_shift *hpo_le_shift,
const struct dcn31_hpo_dp_link_encoder_mask *hpo_le_mask);
bool dcn32_hpo_dp_link_enc_is_in_alt_mode(
struct hpo_dp_link_encoder *enc);
#endif // __DAL_DCN32_HPO_DP_LINK_ENCODER_H__
@@ -0,0 +1,907 @@
/*
* Copyright 2019 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 "core_types.h"
#include "dcn401_hpo_frl_stream_encoder.h"
#include "dcn30/dcn30_hpo_frl_stream_encoder.h"
#include "reg_helper.h"
#include "hw_shared.h"
#include "dcn_calc_math.h"
#include "dml/dcn30/dcn30_fpu.h"
#undef DC_LOGGER
#define DC_LOGGER \
enc401->base.ctx->logger
#define DTRACE(str, ...) {DC_LOG_HDMI_FRL(str, ##__VA_ARGS__); }
#define DEBUG_FRL_CAP_CHK 1
#define REG(reg)\
(enc401->regs->reg)
#undef FN
#define FN(reg_name, field_name) \
enc401->hpo_se_shift->field_name, enc401->hpo_se_mask->field_name
#define CTX \
enc401->base.ctx
#define VBI_LINE_0 0
void hpo_enc401_enable(
struct hpo_frl_stream_encoder *enc,
int otg_inst)
{
struct dcn401_hpo_frl_stream_encoder *enc401 = DCN401_HPO_FRL_STRENC_FROM_HPO_FRL_STRENC(enc);
DC_LOG_DEBUG("Entering [%s]\n", __func__);
/* Enable DISPCLK, SOCCLK, and HDMISTREAMCLK */
REG_UPDATE(HDMI_STREAM_ENC_CLOCK_CONTROL, HDMI_STREAM_ENC_CLOCK_EN, 1);
/* Reset */
REG_UPDATE_2(HDMI_TB_ENC_CONTROL,
HDMI_RESET, 1,
HDMI_TB_ENC_EN, 0);
REG_WAIT(HDMI_TB_ENC_CONTROL, HDMI_RESET_DONE,
1, 10, 100);
REG_UPDATE(HDMI_TB_ENC_CONTROL,
HDMI_RESET, 0);
/* FOR DEBUG: enable CRC */
REG_UPDATE_2(HDMI_TB_ENC_CRC_CNTL,
HDMI_CRC_EN, 1,
HDMI_CRC_CONT_EN, 1);
// REG_UPDATE(HDMI_STREAM_ENC_CLOCK_RAMP_ADJUSTER_FIFO_STATUS_CONTROL2, FIFO_DB_DISABLE, 1);
/* TODO: confirm if need to set HDMI_DB_DISABLE -- HW team only setting FIFO_DB_DISABLE */
REG_UPDATE(HDMI_TB_ENC_DB_CONTROL, HDMI_DB_DISABLE, 1);
/* Set the input mux to select OTG source */
REG_UPDATE(HDMI_STREAM_ENC_INPUT_MUX_CONTROL, HDMI_STREAM_ENC_INPUT_MUX_SOURCE_SEL, otg_inst);
DC_LOG_DEBUG("Exiting [%s]\n", __func__);
}
void hpo_enc401_unblank(struct hpo_frl_stream_encoder *enc, int otg_inst)
{
(void)otg_inst;
struct dcn401_hpo_frl_stream_encoder *enc401 = DCN401_HPO_FRL_STRENC_FROM_HPO_FRL_STRENC(enc);
DC_LOG_HDMI_FRL("Entering [%s]\n", __func__);
/*make sure FIFO_VIDEO_STREAM_ACTIVE =1*/
REG_UPDATE(HDMI_STREAM_ENC_CLOCK_RAMP_ADJUSTER_FIFO_STATUS_CONTROL0,
FIFO_ENABLE, 0);
/* Reset */
REG_UPDATE(HDMI_STREAM_ENC_CLOCK_RAMP_ADJUSTER_FIFO_STATUS_CONTROL0,
FIFO_RESET, 1);
REG_WAIT(HDMI_STREAM_ENC_CLOCK_RAMP_ADJUSTER_FIFO_STATUS_CONTROL0, FIFO_RESET_DONE,
1, 10, 1000);
REG_UPDATE(HDMI_STREAM_ENC_CLOCK_RAMP_ADJUSTER_FIFO_STATUS_CONTROL0,
FIFO_RESET, 0);
REG_WAIT(HDMI_STREAM_ENC_CLOCK_RAMP_ADJUSTER_FIFO_STATUS_CONTROL0, FIFO_RESET_DONE,
0, 10, 1000);
/* Enable HDMI Tribyte Encoder */
REG_UPDATE(HDMI_TB_ENC_CONTROL,
HDMI_TB_ENC_EN, 1);
/* Enable Clock Ramp Adjuster FIFO */
REG_UPDATE(HDMI_STREAM_ENC_CLOCK_RAMP_ADJUSTER_FIFO_STATUS_CONTROL0,
FIFO_ENABLE, 1);
DC_LOG_HDMI_FRL("Exiting [%s]\n", __func__);
}
void hpo_enc401_blank(struct hpo_frl_stream_encoder *enc)
{
struct dcn401_hpo_frl_stream_encoder *enc401 = DCN401_HPO_FRL_STRENC_FROM_HPO_FRL_STRENC(enc);
/* Disable Clock Ramp Adjuster FIFO */
REG_UPDATE(HDMI_STREAM_ENC_CLOCK_RAMP_ADJUSTER_FIFO_STATUS_CONTROL0,
FIFO_ENABLE, 0);
/* Disable HDMI Tribyte Encoder */
REG_UPDATE(HDMI_TB_ENC_CONTROL,
HDMI_TB_ENC_EN, 0);
/* Disable DISPCLK, SOCCLK, and HDMISTREAMCLK */
REG_UPDATE(HDMI_STREAM_ENC_CLOCK_CONTROL,
HDMI_STREAM_ENC_CLOCK_EN, 0);
}
void hpo_enc401_read_state(
struct hpo_frl_stream_encoder *enc,
struct hpo_frl_stream_encoder_state *state)
{
uint32_t pixel_encoding;
uint32_t color_depth;
// int odm_combine;
struct dcn401_hpo_frl_stream_encoder *enc401 = DCN401_HPO_FRL_STRENC_FROM_HPO_FRL_STRENC(enc);
ASSERT(state);
REG_GET(HDMI_TB_ENC_CONTROL,
HDMI_TB_ENC_EN, &state->stream_enc_enabled);
REG_GET(HDMI_STREAM_ENC_INPUT_MUX_CONTROL,
HDMI_STREAM_ENC_INPUT_MUX_SOURCE_SEL, &state->otg_inst);
REG_GET_2(HDMI_TB_ENC_PIXEL_FORMAT,
HDMI_PIXEL_ENCODING, &pixel_encoding,
HDMI_DEEP_COLOR_DEPTH, &color_depth);
// REG_GET(HDMI_STREAM_ENC_CLOCK_RAMP_ADJUSTER_FIFO_STATUS_CONTROL0,
// FIFO_ODM_COMBINE_MODE, &odm_combine);
REG_GET_2(HDMI_TB_ENC_H_ACTIVE_BLANK,
HDMI_H_ACTIVE, &state->h_active,
HDMI_H_BLANK, &state->h_blank);
REG_GET(HDMI_TB_ENC_MODE,
HDMI_BORROW_MODE, &state->borrow_mode);
if (pixel_encoding == 0)
state->pixel_format = PIXEL_ENCODING_YCBCR444;
else if (pixel_encoding == 1)
state->pixel_format = PIXEL_ENCODING_YCBCR422;
else
state->pixel_format = PIXEL_ENCODING_YCBCR420;
if (color_depth == 0)
state->color_depth = 8;
else if (color_depth == 1)
state->color_depth = 10;
else
state->color_depth = 12;
// state->num_odm_segments = odm_combine + 1;
}
/* setup stream encoder in hdmi mode */
/* Precondition: link is trained */
void hpo_enc401_set_hdmi_stream_attribute(
struct hpo_frl_stream_encoder *enc,
struct dc_crtc_timing *crtc_timing,
struct frl_borrow_params *borrow_params,
int odm_combine_num_segments)
{
(void)odm_combine_num_segments;
uint32_t h_active;
uint32_t h_blank;
struct dcn401_hpo_frl_stream_encoder *enc401 = DCN401_HPO_FRL_STRENC_FROM_HPO_FRL_STRENC(enc);
DC_LOG_DEBUG("Entering [%s]\n", __func__);
/* Configure pixel encoding */
switch (crtc_timing->pixel_encoding) {
case PIXEL_ENCODING_YCBCR422:
REG_UPDATE(HDMI_TB_ENC_PIXEL_FORMAT,
HDMI_PIXEL_ENCODING, 1);
REG_UPDATE(HDMI_STREAM_ENC_CLOCK_RAMP_ADJUSTER_FIFO_STATUS_CONTROL0,
FIFO_UNCOMPRESSED_PIXEL_FORMAT, 0);
break;
case PIXEL_ENCODING_YCBCR420:
REG_UPDATE(HDMI_TB_ENC_PIXEL_FORMAT,
HDMI_PIXEL_ENCODING, 2);
REG_UPDATE(HDMI_STREAM_ENC_CLOCK_RAMP_ADJUSTER_FIFO_STATUS_CONTROL0,
FIFO_UNCOMPRESSED_PIXEL_FORMAT, 1);
break;
default:
REG_UPDATE(HDMI_TB_ENC_PIXEL_FORMAT,
HDMI_PIXEL_ENCODING, 0);
REG_UPDATE(HDMI_STREAM_ENC_CLOCK_RAMP_ADJUSTER_FIFO_STATUS_CONTROL0,
FIFO_UNCOMPRESSED_PIXEL_FORMAT, 0);
break;
}
/* Configure color depth */
switch (crtc_timing->display_color_depth) {
case COLOR_DEPTH_888:
REG_UPDATE_2(HDMI_TB_ENC_PIXEL_FORMAT,
HDMI_DEEP_COLOR_DEPTH, 0,
HDMI_DEEP_COLOR_ENABLE, 0);
break;
case COLOR_DEPTH_101010:
if (crtc_timing->pixel_encoding == PIXEL_ENCODING_YCBCR422) {
REG_UPDATE_2(HDMI_TB_ENC_PIXEL_FORMAT,
HDMI_DEEP_COLOR_DEPTH, 1,
HDMI_DEEP_COLOR_ENABLE, 0);
} else {
REG_UPDATE_2(HDMI_TB_ENC_PIXEL_FORMAT,
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_TB_ENC_PIXEL_FORMAT,
HDMI_DEEP_COLOR_DEPTH, 2,
HDMI_DEEP_COLOR_ENABLE, 0);
} else {
REG_UPDATE_2(HDMI_TB_ENC_PIXEL_FORMAT,
HDMI_DEEP_COLOR_DEPTH, 2,
HDMI_DEEP_COLOR_ENABLE, 1);
}
break;
default:
break;
}
/* When compression active, CD/PP/Phase field shall be zero in GCP */
if (crtc_timing->flags.DSC) {
REG_UPDATE_2(HDMI_TB_ENC_PIXEL_FORMAT,
HDMI_DEEP_COLOR_DEPTH, 0,
HDMI_DEEP_COLOR_ENABLE, 0);
}
/* Configure horizontal active and blank size */
h_active = crtc_timing->h_addressable + crtc_timing->h_border_left + crtc_timing->h_border_right;
h_blank = crtc_timing->h_total - h_active;
if (crtc_timing->pixel_encoding == PIXEL_ENCODING_YCBCR420 ||
crtc_timing->pixel_encoding == PIXEL_ENCODING_YCBCR422) {
h_active /= 2;
h_blank /= 2;
}
REG_SET_2(HDMI_TB_ENC_H_ACTIVE_BLANK, 0,
HDMI_H_ACTIVE, h_active,
HDMI_H_BLANK, h_blank);
/* Configure borrow parameters */
REG_UPDATE(HDMI_TB_ENC_MODE,
HDMI_BORROW_MODE, borrow_params->borrow_mode);
REG_UPDATE(HDMI_TB_ENC_PACKET_CONTROL,
HDMI_MAX_PACKETS_PER_LINE, borrow_params->audio_packets_line);
REG_SET_2(HDMI_TB_ENC_HC_ACTIVE_BLANK, 0,
HDMI_HC_ACTIVE, borrow_params->hc_active_target,
HDMI_HC_BLANK, borrow_params->hc_blank_target);
/* Enable transmission of General Control packet on every frame */
REG_UPDATE_2(HDMI_TB_ENC_VBI_PACKET_CONTROL1,
HDMI_GC_CONT, 1,
HDMI_GC_SEND, 1);
/* Disable Audio Content Protection packet transmission */
/* TODO: review if this needs to be here */
REG_UPDATE(HDMI_TB_ENC_VBI_PACKET_CONTROL1, HDMI_ACP_SEND, 0);
/* Enable Audio InfoFrame packet transmission. */
REG_UPDATE(HDMI_TB_ENC_VBI_PACKET_CONTROL1, HDMI_AUDIO_INFO_SEND, 1);
/* update double-buffered AUDIO_INFO registers immediately */
if (enc->afmt && enc->afmt->funcs->audio_info_immediate_update)
enc->afmt->funcs->audio_info_immediate_update(enc->afmt);
/* Select line number on which to send Audio InfoFrame packets */
REG_UPDATE(HDMI_TB_ENC_VBI_PACKET_CONTROL1, HDMI_AUDIO_INFO_LINE,
VBI_LINE_0 + 2);
/* set HDMI GC AVMUTE */
REG_UPDATE(HDMI_TB_ENC_GC_CONTROL, HDMI_GC_AVMUTE, 0);
DC_LOG_DEBUG("Exiting [%s]\n", __func__);
}
void hpo_enc401_update_hdmi_info_packet(
struct dcn401_hpo_frl_stream_encoder *enc401,
uint32_t packet_index,
const struct dc_info_packet *info_packet)
{
uint32_t cont, send, line;
if (info_packet->valid) {
enc401->base.vpg->funcs->update_generic_info_packet(
enc401->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 */
/* TODO: check if line 2 is correct */
line = 2;
} else {
cont = 0;
send = 0;
line = 0;
}
/* TODO: set bit to indicate if packet is Extended Metadata Packet. */
/* TODO: In DCN3, there are 0-14 generic packets */
/* choose which generic packet control to use */
switch (packet_index) {
case 0:
REG_UPDATE_2(HDMI_TB_ENC_GENERIC_PACKET_CONTROL0,
HDMI_GENERIC0_CONT, cont,
HDMI_GENERIC0_SEND, send);
REG_UPDATE(HDMI_TB_ENC_GENERIC_PACKET0_1_LINE,
HDMI_GENERIC0_LINE, line);
break;
case 1:
REG_UPDATE_2(HDMI_TB_ENC_GENERIC_PACKET_CONTROL0,
HDMI_GENERIC1_CONT, cont,
HDMI_GENERIC1_SEND, send);
REG_UPDATE(HDMI_TB_ENC_GENERIC_PACKET0_1_LINE,
HDMI_GENERIC1_LINE, line);
break;
case 2:
REG_UPDATE_2(HDMI_TB_ENC_GENERIC_PACKET_CONTROL0,
HDMI_GENERIC2_CONT, cont,
HDMI_GENERIC2_SEND, send);
REG_UPDATE(HDMI_TB_ENC_GENERIC_PACKET2_3_LINE,
HDMI_GENERIC2_LINE, line);
break;
case 3:
REG_UPDATE_2(HDMI_TB_ENC_GENERIC_PACKET_CONTROL0,
HDMI_GENERIC3_CONT, cont,
HDMI_GENERIC3_SEND, send);
REG_UPDATE(HDMI_TB_ENC_GENERIC_PACKET2_3_LINE,
HDMI_GENERIC3_LINE, line);
break;
case 4:
REG_UPDATE_2(HDMI_TB_ENC_GENERIC_PACKET_CONTROL0,
HDMI_GENERIC4_CONT, cont,
HDMI_GENERIC4_SEND, send);
REG_UPDATE(HDMI_TB_ENC_GENERIC_PACKET4_5_LINE,
HDMI_GENERIC4_LINE, line);
break;
case 5:
REG_UPDATE_2(HDMI_TB_ENC_GENERIC_PACKET_CONTROL0,
HDMI_GENERIC5_CONT, cont,
HDMI_GENERIC5_SEND, send);
REG_UPDATE(HDMI_TB_ENC_GENERIC_PACKET4_5_LINE,
HDMI_GENERIC5_LINE, line);
break;
case 6:
REG_UPDATE_2(HDMI_TB_ENC_GENERIC_PACKET_CONTROL0,
HDMI_GENERIC6_CONT, cont,
HDMI_GENERIC6_SEND, send);
REG_UPDATE(HDMI_TB_ENC_GENERIC_PACKET6_7_LINE,
HDMI_GENERIC6_LINE, line);
break;
case 7:
REG_UPDATE_2(HDMI_TB_ENC_GENERIC_PACKET_CONTROL0,
HDMI_GENERIC7_CONT, cont,
HDMI_GENERIC7_SEND, send);
REG_UPDATE(HDMI_TB_ENC_GENERIC_PACKET6_7_LINE,
HDMI_GENERIC7_LINE, line);
break;
case 8:
REG_UPDATE_2(HDMI_TB_ENC_GENERIC_PACKET_CONTROL1,
HDMI_GENERIC8_CONT, cont,
HDMI_GENERIC8_SEND, send);
REG_UPDATE(HDMI_TB_ENC_GENERIC_PACKET8_9_LINE,
HDMI_GENERIC8_LINE, line);
break;
case 9:
REG_UPDATE_2(HDMI_TB_ENC_GENERIC_PACKET_CONTROL1,
HDMI_GENERIC9_CONT, cont,
HDMI_GENERIC9_SEND, send);
REG_UPDATE(HDMI_TB_ENC_GENERIC_PACKET8_9_LINE,
HDMI_GENERIC9_LINE, line);
break;
case 10:
REG_UPDATE_2(HDMI_TB_ENC_GENERIC_PACKET_CONTROL1,
HDMI_GENERIC10_CONT, cont,
HDMI_GENERIC10_SEND, send);
REG_UPDATE(HDMI_TB_ENC_GENERIC_PACKET10_11_LINE,
HDMI_GENERIC10_LINE, line);
break;
case 11:
REG_UPDATE_2(HDMI_TB_ENC_GENERIC_PACKET_CONTROL1,
HDMI_GENERIC11_CONT, cont,
HDMI_GENERIC11_SEND, send);
REG_UPDATE(HDMI_TB_ENC_GENERIC_PACKET10_11_LINE,
HDMI_GENERIC11_LINE, line);
break;
case 12:
REG_UPDATE_2(HDMI_TB_ENC_GENERIC_PACKET_CONTROL1,
HDMI_GENERIC12_CONT, cont,
HDMI_GENERIC12_SEND, send);
REG_UPDATE(HDMI_TB_ENC_GENERIC_PACKET12_13_LINE,
HDMI_GENERIC12_LINE, line);
break;
case 13:
REG_UPDATE_2(HDMI_TB_ENC_GENERIC_PACKET_CONTROL1,
HDMI_GENERIC13_CONT, cont,
HDMI_GENERIC13_SEND, send);
REG_UPDATE(HDMI_TB_ENC_GENERIC_PACKET12_13_LINE,
HDMI_GENERIC13_LINE, line);
break;
case 14:
REG_UPDATE_2(HDMI_TB_ENC_GENERIC_PACKET_CONTROL1,
HDMI_GENERIC14_CONT, cont,
HDMI_GENERIC14_SEND, send);
REG_UPDATE(HDMI_TB_ENC_GENERIC_PACKET14_LINE,
HDMI_GENERIC14_LINE, line);
break;
default:
/* invalid HW packet index */
DC_LOG_WARNING(
"Invalid HW packet index: %s()\n",
__func__);
return;
}
}
void hpo_enc401_update_hdmi_info_packets(struct hpo_frl_stream_encoder *enc,
const struct encoder_info_frame *info_frame)
{
struct dcn401_hpo_frl_stream_encoder *enc401 = DCN401_HPO_FRL_STRENC_FROM_HPO_FRL_STRENC(enc);
hpo_enc401_update_hdmi_info_packet(enc401, 0, &info_frame->avi);
hpo_enc401_update_hdmi_info_packet(enc401, 1, &info_frame->vendor);
hpo_enc401_update_hdmi_info_packet(enc401, 2, &info_frame->gamut);
hpo_enc401_update_hdmi_info_packet(enc401, 3, &info_frame->spd);
hpo_enc401_update_hdmi_info_packet(enc401, 4, &info_frame->hdrsmd);
/* 5-10 used by dsc */
hpo_enc401_update_hdmi_info_packet(enc401, 11, &info_frame->hfvsif);
hpo_enc401_update_hdmi_info_packet(enc401, 12, &info_frame->vtem);
}
void hpo_enc401_hdmi_set_dsc_config(
struct hpo_frl_stream_encoder *enc,
struct dc_crtc_timing *timing,
uint8_t *dsc_packed_pps)
{
struct dcn401_hpo_frl_stream_encoder *enc401 = DCN401_HPO_FRL_STRENC_FROM_HPO_FRL_STRENC(enc);
enum optc_dsc_mode dsc_mode = OPTC_DSC_DISABLED;
uint8_t i;
if (dsc_packed_pps) {
if (timing->pixel_encoding == PIXEL_ENCODING_YCBCR420 ||
(timing->pixel_encoding == PIXEL_ENCODING_YCBCR422
&& !timing->dsc_cfg.ycbcr422_simple))
dsc_mode = OPTC_DSC_ENABLED_NATIVE_SUBSAMPLED;
else
dsc_mode = OPTC_DSC_ENABLED_444;
}
switch (dsc_mode) {
case OPTC_DSC_DISABLED:
REG_UPDATE_2(HDMI_STREAM_ENC_CLOCK_RAMP_ADJUSTER_FIFO_STATUS_CONTROL0,
FIFO_PIXEL_ENCODING_TYPE, 0,
FIFO_COMPRESSED_PIXEL_FORMAT, 0);
break;
case OPTC_DSC_ENABLED_NATIVE_SUBSAMPLED:
REG_UPDATE_2(HDMI_STREAM_ENC_CLOCK_RAMP_ADJUSTER_FIFO_STATUS_CONTROL0,
FIFO_PIXEL_ENCODING_TYPE, 1,
FIFO_COMPRESSED_PIXEL_FORMAT, 1);
break;
case OPTC_DSC_ENABLED_444:
REG_UPDATE_2(HDMI_STREAM_ENC_CLOCK_RAMP_ADJUSTER_FIFO_STATUS_CONTROL0,
FIFO_PIXEL_ENCODING_TYPE, 1,
FIFO_COMPRESSED_PIXEL_FORMAT, 0);
break;
}
REG_UPDATE(HDMI_TB_ENC_PIXEL_FORMAT,
HDMI_DSC_MODE, dsc_mode);
/* 5 packets for hdmi 2.1, use generic packets 5-10 to transmit*/
/* TODO: do we change new bit to 0 after first transmission? Do we set End bit when exiting dsc? */
if (dsc_mode != OPTC_DSC_DISABLED) {
struct dc_info_packet emp_packet = {0};
/* Need to find the padded h_total to recover the expected h_back*/
uint32_t h_active_padding = timing->h_addressable % timing->dsc_cfg.num_slices_h;
if (h_active_padding != 0)
h_active_padding = timing->dsc_cfg.num_slices_h - h_active_padding;
/* if YCBCR420, ensure slice width is even */
uint32_t slice_width = (timing->h_addressable + h_active_padding) / timing->dsc_cfg.num_slices_h;
if (timing->pixel_encoding == PIXEL_ENCODING_YCBCR420 &&
slice_width % 2 != 0)
h_active_padding += timing->dsc_cfg.num_slices_h;
uint32_t dsc_pic_width = timing->h_addressable + timing->h_border_left + timing->h_border_right + h_active_padding;
uint32_t h_back = timing->h_total - dsc_pic_width - timing->h_sync_width - timing->h_front_porch + h_active_padding;
/* HCactivebytes = Slices * ceil(SliceWidth * bpp/8)
* Since bpp is stored as 16x actual value do (sliceWidth * bpp + 127) / 128 to ceil
*/
uint32_t h_cactive_bytes = timing->dsc_cfg.num_slices_h * (
(dsc_pic_width /
timing->dsc_cfg.num_slices_h * timing->dsc_cfg.bits_per_pixel + 127) / 128);
/* Packet 0 */
emp_packet.valid = true;
emp_packet.hb0 = 0x7F; /* Default */
emp_packet.hb1 = (1 << 7); /* First */
emp_packet.hb2 = 0; /* Sequence index */
emp_packet.sb[0] = (1 << 1) | (1 << 2) | (1 << 7); /* Sync[1] = 1, VFR[2] = 1, New[7] = 1*/
emp_packet.sb[2] = 1; /* Organization_ID = 1 (Vesa spec)*/
emp_packet.sb[4] = 2; /* Data_Set_Tag(LSB) = 2*/
emp_packet.sb[6] = 136; /* Data_Set_Length(LSB) = 136*/
memcpy(&emp_packet.sb[7], dsc_packed_pps, 21);
hpo_enc401_update_hdmi_info_packet(enc401, 5, &emp_packet);
/* Packets 1-3 */
emp_packet.hb1 = 0; /* Not first or last*/
for (i = 1; i < 4; i++) {
emp_packet.hb2 = i; /* Sequence index */
memcpy(&emp_packet.sb[0], &dsc_packed_pps[21 + 28 * (i - 1)], 28);
hpo_enc401_update_hdmi_info_packet(enc401, 5 + i, &emp_packet);
}
/* Packet 4 */
emp_packet.hb2 = 4; /* Sequence index */
memcpy(&emp_packet.sb[0], &dsc_packed_pps[105], 23);
emp_packet.sb[23] = (uint8_t)timing->h_front_porch; /* Hfront[7:0] */
emp_packet.sb[24] = (uint8_t)(timing->h_front_porch >> 8); /* Hfront[15:8] */
emp_packet.sb[25] = (uint8_t)timing->h_sync_width; /* Hsync[7:0] */
emp_packet.sb[26] = (uint8_t)(timing->h_sync_width >> 8); /* Hsync[15:8] */
emp_packet.sb[27] = (uint8_t)h_back; /* Hback[7:0] */
hpo_enc401_update_hdmi_info_packet(enc401, 9, &emp_packet);
/* Packet 5 */
emp_packet.hb1 = (1 << 6); /* Last */
emp_packet.hb2 = 5;
emp_packet.sb[0] = (uint8_t)(h_back >> 8); /* Hback[15:8] */
emp_packet.sb[1] = (uint8_t)h_cactive_bytes; /* HCactive_bytes[7:0] */
emp_packet.sb[2] = (uint8_t)(h_cactive_bytes >> 8); /* HCactive_bytes[15:8] */
hpo_enc401_update_hdmi_info_packet(enc401, 10, &emp_packet);
/* Packet 0 - Clear New[7] */
emp_packet.valid = true;
emp_packet.hb0 = 0x7F; /* Default */
emp_packet.hb1 = (1 << 7); /* First */
emp_packet.hb2 = 0; /* Sequence index */
emp_packet.sb[0] = (1 << 1) | (1 << 2); /* Sync[1] = 1, VFR[2] = 1*/
emp_packet.sb[2] = 1; /* Organization_ID = 1 (Vesa spec)*/
emp_packet.sb[4] = 2; /* Data_Set_Tag(LSB) = 2*/
emp_packet.sb[6] = 136; /* Data_Set_Length(LSB) = 136*/
memcpy(&emp_packet.sb[7], dsc_packed_pps, 21);
hpo_enc401_update_hdmi_info_packet(enc401, 5, &emp_packet);
}
}
void hpo_enc401_stop_hdmi_info_packets(
struct hpo_frl_stream_encoder *enc)
{
struct dcn401_hpo_frl_stream_encoder *enc401 = DCN401_HPO_FRL_STRENC_FROM_HPO_FRL_STRENC(enc);
/* TODO: should also set extended metadata packet bit back to 0? */
/* stop generic packets 0,1 on HDMI */
REG_SET_4(HDMI_TB_ENC_GENERIC_PACKET_CONTROL0, 0,
HDMI_GENERIC0_CONT, 0,
HDMI_GENERIC0_SEND, 0,
HDMI_GENERIC1_CONT, 0,
HDMI_GENERIC1_SEND, 0);
REG_SET_2(HDMI_TB_ENC_GENERIC_PACKET0_1_LINE, 0,
HDMI_GENERIC0_LINE, 0,
HDMI_GENERIC1_LINE, 0);
/* stop generic packets 2,3 on HDMI */
REG_SET_4(HDMI_TB_ENC_GENERIC_PACKET_CONTROL0, 0,
HDMI_GENERIC2_CONT, 0,
HDMI_GENERIC2_SEND, 0,
HDMI_GENERIC3_CONT, 0,
HDMI_GENERIC3_SEND, 0);
REG_SET_2(HDMI_TB_ENC_GENERIC_PACKET2_3_LINE, 0,
HDMI_GENERIC2_LINE, 0,
HDMI_GENERIC3_LINE, 0);
/* stop generic packets 4,5 on HDMI */
REG_SET_4(HDMI_TB_ENC_GENERIC_PACKET_CONTROL0, 0,
HDMI_GENERIC4_CONT, 0,
HDMI_GENERIC4_SEND, 0,
HDMI_GENERIC5_CONT, 0,
HDMI_GENERIC5_SEND, 0);
REG_SET_2(HDMI_TB_ENC_GENERIC_PACKET4_5_LINE, 0,
HDMI_GENERIC4_LINE, 0,
HDMI_GENERIC5_LINE, 0);
/* stop generic packets 6,7 on HDMI */
REG_SET_4(HDMI_TB_ENC_GENERIC_PACKET_CONTROL0, 0,
HDMI_GENERIC6_CONT, 0,
HDMI_GENERIC6_SEND, 0,
HDMI_GENERIC7_CONT, 0,
HDMI_GENERIC7_SEND, 0);
REG_SET_2(HDMI_TB_ENC_GENERIC_PACKET6_7_LINE, 0,
HDMI_GENERIC6_LINE, 0,
HDMI_GENERIC7_LINE, 0);
/* stop generic packets 8,9 on HDMI */
REG_SET_4(HDMI_TB_ENC_GENERIC_PACKET_CONTROL1, 0,
HDMI_GENERIC8_CONT, 0,
HDMI_GENERIC8_SEND, 0,
HDMI_GENERIC9_CONT, 0,
HDMI_GENERIC9_SEND, 0);
REG_SET_2(HDMI_TB_ENC_GENERIC_PACKET8_9_LINE, 0,
HDMI_GENERIC8_LINE, 0,
HDMI_GENERIC9_LINE, 0);
/* stop generic packets 10,11 on HDMI */
REG_SET_4(HDMI_TB_ENC_GENERIC_PACKET_CONTROL1, 0,
HDMI_GENERIC10_CONT, 0,
HDMI_GENERIC10_SEND, 0,
HDMI_GENERIC11_CONT, 0,
HDMI_GENERIC11_SEND, 0);
REG_SET_2(HDMI_TB_ENC_GENERIC_PACKET10_11_LINE, 0,
HDMI_GENERIC10_LINE, 0,
HDMI_GENERIC11_LINE, 0);
/* stop generic packets 12,13 on HDMI */
REG_SET_4(HDMI_TB_ENC_GENERIC_PACKET_CONTROL1, 0,
HDMI_GENERIC12_CONT, 0,
HDMI_GENERIC12_SEND, 0,
HDMI_GENERIC13_CONT, 0,
HDMI_GENERIC13_SEND, 0);
REG_SET_2(HDMI_TB_ENC_GENERIC_PACKET12_13_LINE, 0,
HDMI_GENERIC12_LINE, 0,
HDMI_GENERIC13_LINE, 0);
/* stop generic packets 14 on HDMI */
REG_SET_2(HDMI_TB_ENC_GENERIC_PACKET_CONTROL1, 0,
HDMI_GENERIC14_CONT, 0,
HDMI_GENERIC14_SEND, 0);
REG_SET(HDMI_TB_ENC_GENERIC_PACKET14_LINE, 0,
HDMI_GENERIC14_LINE, 0);
}
//Covered both, rounding up or rounding down from FRL Link Rate /18.
static const struct frl_audio_clock_info frl_audio_clock_info_table[10] = {
{166666, 4224, 171875, 5292, 156250, 5760, 156250},
{166667, 4224, 171875, 5292, 156250, 5760, 156250},
{333333, 4032, 328125, 5292, 312500, 6048, 328125},
{333334, 4032, 328125, 5292, 312500, 6048, 328125},
{444444, 4032, 437500, 3969, 312500, 6048, 437500},
{444445, 4032, 437500, 3969, 312500, 6048, 437500},
{555555, 3456, 468750, 3969, 390625, 5184, 468750},
{555556, 3456, 468750, 3969, 390625, 5184, 468750},
{666666, 3072, 500000, 3969, 468750, 4752, 515625},
{666667, 3072, 500000, 3969, 468750, 4752, 515625}
};
void frl_get_audio_clock_info(
enum dc_color_depth color_depth,
uint32_t frl_character_clock_kHz,
struct frl_audio_clock_info *audio_clock_info)
{
(void)color_depth;
const struct frl_audio_clock_info *clock_info;
uint32_t index;
uint32_t audio_array_size;
clock_info = frl_audio_clock_info_table;
audio_array_size = ARRAY_SIZE(
frl_audio_clock_info_table);
if (clock_info != NULL) {
/* search for exact frl character clock in table */
for (index = 0; index < audio_array_size; index++) {
if (clock_info[index].frl_character_clock_kHz >
frl_character_clock_kHz)
break; /* not match */
else if (clock_info[index].frl_character_clock_kHz ==
frl_character_clock_kHz) {
/* match found */
*audio_clock_info = clock_info[index];
return;
}
}
}
/*Only 3, 6, 8, 10 and 12 Gbps are used for FRL Link rates with character
*clocks of 166.667, 333.333, 444.444, 555.555 and 666.667 MHz are used
*so entry should be found in above table if no bugs */
BREAK_TO_DEBUGGER();
}
void hpo_enc401_setup_hdmi_audio(
struct hpo_frl_stream_encoder *enc,
const struct audio_crtc_info *crtc_info)
{
struct dcn401_hpo_frl_stream_encoder *enc401 = DCN401_HPO_FRL_STRENC_FROM_HPO_FRL_STRENC(enc);
struct frl_audio_clock_info audio_clock_info = {0};
DC_LOG_DEBUG("Entering [%s]\n", __func__);
/* TODO: HDMI_AUDIO_DELAY_EN bit only in DIG -- not in HPO? */
/* HDMI_AUDIO_PACKET_CONTROL */
//REG_UPDATE(HDMI_AUDIO_PACKET_CONTROL,
// HDMI_AUDIO_DELAY_EN, 1);
/* Setup audio in AFMT - program AFMT block associated with HPO */
ASSERT (enc->afmt);
enc->afmt->funcs->setup_hdmi_audio(enc->afmt);
/* TODO: Same programming, but using HDMI_TB_ENC register */
/* HDMI_ACR_PACKET_CONTROL */
REG_UPDATE_3(HDMI_TB_ENC_ACR_PACKET_CONTROL,
HDMI_ACR_AUTO_SEND, 1,
HDMI_ACR_SOURCE, 0,
HDMI_ACR_AUDIO_PRIORITY, 0);
/* N/CTS computed relative to FRL rate instead of video rate (TMDS character clock). */
/* Program audio clock sample/regeneration parameters */
frl_get_audio_clock_info(crtc_info->color_depth,
crtc_info->frl_character_clock_kHz,
&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);
/* Same register definition, but using HDMI_TB_ENC register */
/* HDMI_ACR_32_0__HDMI_ACR_CTS_32_MASK */
REG_UPDATE(HDMI_TB_ENC_ACR_32_0, HDMI_ACR_CTS_32, audio_clock_info.cts_32khz);
/* HDMI_ACR_32_1__HDMI_ACR_N_32_MASK */
REG_UPDATE(HDMI_TB_ENC_ACR_32_1, HDMI_ACR_N_32, audio_clock_info.n_32khz);
/* HDMI_ACR_44_0__HDMI_ACR_CTS_44_MASK */
REG_UPDATE(HDMI_TB_ENC_ACR_44_0, HDMI_ACR_CTS_44, audio_clock_info.cts_44khz);
/* HDMI_ACR_44_1__HDMI_ACR_N_44_MASK */
REG_UPDATE(HDMI_TB_ENC_ACR_44_1, HDMI_ACR_N_44, audio_clock_info.n_44khz);
/* HDMI_ACR_48_0__HDMI_ACR_CTS_48_MASK */
REG_UPDATE(HDMI_TB_ENC_ACR_48_0, HDMI_ACR_CTS_48, audio_clock_info.cts_48khz);
/* HDMI_ACR_48_1__HDMI_ACR_N_48_MASK */
REG_UPDATE(HDMI_TB_ENC_ACR_48_1, HDMI_ACR_N_48, audio_clock_info.n_48khz);
/* TODO: HDMI_TB_ENC_ACR_PACKET_CONTROL::ACR_N_MULTIPLE
* Same register definition, but using HDMI_TB_ENC register*/
/* 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 interrupt callback
*/
DC_LOG_DEBUG("Exiting [%s]\n", __func__);
}
void hpo_enc401_hdmi_audio_setup(
struct hpo_frl_stream_encoder *enc,
unsigned int az_inst,
struct audio_info *info,
struct audio_crtc_info *audio_crtc_info)
{
hpo_enc401_setup_hdmi_audio(enc, audio_crtc_info);
ASSERT (enc->afmt);
enc->afmt->funcs->se_audio_setup(enc->afmt, az_inst, info);
}
void hpo_enc401_hdmi_audio_disable(
struct hpo_frl_stream_encoder *enc)
{
ASSERT(enc->afmt);
if (enc->afmt->funcs->afmt_powerdown)
enc->afmt->funcs->afmt_powerdown(enc->afmt);
}
void hpo_enc401_audio_mute_control(
struct hpo_frl_stream_encoder *enc,
bool mute)
{
ASSERT (enc->afmt);
enc->afmt->funcs->audio_mute_control(enc->afmt, mute);
}
void enc401_stream_encoder_set_avmute(
struct hpo_frl_stream_encoder *enc,
bool enable)
{
struct dcn401_hpo_frl_stream_encoder *enc401 = DCN401_HPO_FRL_STRENC_FROM_HPO_FRL_STRENC(enc);
unsigned int value = enable ? 1 : 0;
REG_UPDATE(HDMI_TB_ENC_GC_CONTROL, HDMI_GC_AVMUTE, value);
}
/* 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 hpo_enc401_set_dynamic_metadata(struct hpo_frl_stream_encoder *enc,
bool enable_dme,
uint32_t hubp_requestor_id,
enum dynamic_metadata_mode dmdata_mode)
{
struct dcn401_hpo_frl_stream_encoder *enc401 = DCN401_HPO_FRL_STRENC_FROM_HPO_FRL_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);
REG_UPDATE_3(HDMI_TB_ENC_METADATA_PACKET_CONTROL,
HDMI_METADATA_PACKET_ENABLE, 1,
HDMI_METADATA_PACKET_LINE_REFERENCE, 0,
HDMI_METADATA_PACKET_LINE, 2);
REG_UPDATE(DME_CONTROL,
METADATA_ENGINE_EN, 1);
} else {
REG_UPDATE(DME_CONTROL,
METADATA_ENGINE_EN, 0);
REG_UPDATE(HDMI_TB_ENC_METADATA_PACKET_CONTROL,
HDMI_METADATA_PACKET_ENABLE, 0);
}
}
static const struct hpo_frl_stream_encoder_funcs dcn401_str_enc_funcs = {
.hdmi_frl_enable = hpo_enc401_enable,
.hdmi_frl_unblank = hpo_enc401_unblank,
.hdmi_frl_blank = hpo_enc401_blank,
.hdmi_frl_set_stream_attribute = hpo_enc401_set_hdmi_stream_attribute,
.validate_hdmi_frl_output = hpo_enc3_validate_hdmi_frl_output,
.update_hdmi_info_packets = hpo_enc401_update_hdmi_info_packets,
.stop_hdmi_info_packets = hpo_enc401_stop_hdmi_info_packets,
.audio_mute_control = hpo_enc401_audio_mute_control,
.hdmi_audio_setup = hpo_enc401_hdmi_audio_setup,
.hdmi_audio_disable = hpo_enc401_hdmi_audio_disable,
.set_avmute = enc401_stream_encoder_set_avmute,
.read_state = hpo_enc401_read_state,
.hdmi_frl_set_dsc_config = hpo_enc401_hdmi_set_dsc_config,
.set_dynamic_metadata = hpo_enc401_set_dynamic_metadata,
};
void dcn401_hpo_frl_stream_encoder_construct(
struct dcn401_hpo_frl_stream_encoder *enc401,
struct dc_context *ctx,
struct dc_bios *bp,
enum engine_id eng_id,
struct vpg *vpg,
struct afmt *afmt,
const struct dcn30_hpo_frl_stream_enc_registers *regs,
const struct dcn401_hpo_frl_stream_encoder_shift *hpo_se_shift,
const struct dcn401_hpo_frl_stream_encoder_mask *hpo_se_mask)
{
enc401->base.funcs = &dcn401_str_enc_funcs;
enc401->base.ctx = ctx;
enc401->base.id = eng_id;
enc401->base.bp = bp;
enc401->base.vpg = vpg;
enc401->base.afmt = afmt;
enc401->regs = regs;
enc401->hpo_se_shift = hpo_se_shift;
enc401->hpo_se_mask = hpo_se_mask;
enc401->base.stream_enc_inst = vpg->inst;
}
@@ -0,0 +1,335 @@
/*
* Copyright 2023 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_HPO_FRL_STREAM_ENCODER_DCN401_H__
#define __DC_HPO_FRL_STREAM_ENCODER_DCN401_H__
#include "dcn30/dcn30_vpg.h"
#include "dcn30/dcn30_afmt.h"
#include "dcn30/dcn30_hpo_frl_stream_encoder.h"
#include "stream_encoder.h"
#include "dml/dml1_frl_cap_chk.h"
#define DCN401_HPO_FRL_STRENC_FROM_HPO_FRL_STRENC(hpo_frl_stream_encoder)\
container_of(hpo_frl_stream_encoder, struct dcn401_hpo_frl_stream_encoder, base)
#define SE_SF(reg_name, field_name, post_fix)\
.field_name = reg_name ## __ ## field_name ## post_fix
#define DCN401_HDMI_STREAM_ENC_MASK_SH_LIST(mask_sh)\
SE_SF(HDMI_STREAM_ENC_INPUT_MUX_CONTROL, HDMI_STREAM_ENC_INPUT_MUX_SOURCE_SEL, mask_sh),\
SE_SF(HDMI_STREAM_ENC_CLOCK_RAMP_ADJUSTER_FIFO_STATUS_CONTROL0, FIFO_ENABLE, mask_sh),\
SE_SF(HDMI_STREAM_ENC_CLOCK_RAMP_ADJUSTER_FIFO_STATUS_CONTROL0, FIFO_RESET, mask_sh),\
SE_SF(HDMI_STREAM_ENC_CLOCK_RAMP_ADJUSTER_FIFO_STATUS_CONTROL0, FIFO_PIXEL_ENCODING_TYPE, mask_sh),\
SE_SF(HDMI_STREAM_ENC_CLOCK_RAMP_ADJUSTER_FIFO_STATUS_CONTROL0, FIFO_UNCOMPRESSED_PIXEL_FORMAT, mask_sh),\
SE_SF(HDMI_STREAM_ENC_CLOCK_RAMP_ADJUSTER_FIFO_STATUS_CONTROL0, FIFO_COMPRESSED_PIXEL_FORMAT, mask_sh),\
SE_SF(HDMI_STREAM_ENC_CLOCK_RAMP_ADJUSTER_FIFO_STATUS_CONTROL0, FIFO_RESET_DONE, mask_sh),\
SE_SF(HDMI_STREAM_ENC_CLOCK_CONTROL, HDMI_STREAM_ENC_CLOCK_EN, mask_sh),\
SE_SF(DME0_DME_CONTROL, METADATA_HUBP_REQUESTOR_ID, mask_sh),\
SE_SF(DME0_DME_CONTROL, METADATA_ENGINE_EN, mask_sh),\
SE_SF(DME0_DME_CONTROL, METADATA_STREAM_TYPE, mask_sh),\
SE_SF(HDMI_TB_ENC_METADATA_PACKET_CONTROL, HDMI_METADATA_PACKET_ENABLE, mask_sh),\
SE_SF(HDMI_TB_ENC_METADATA_PACKET_CONTROL, HDMI_METADATA_PACKET_LINE_REFERENCE, mask_sh),\
SE_SF(HDMI_TB_ENC_METADATA_PACKET_CONTROL, HDMI_METADATA_PACKET_MISSED, mask_sh),\
SE_SF(HDMI_TB_ENC_METADATA_PACKET_CONTROL, HDMI_METADATA_PACKET_LINE, mask_sh)
#define DCN401_HDMI_TB_ENC_MASK_SH_LIST(mask_sh)\
SE_SF(HDMI_TB_ENC_CONTROL, HDMI_TB_ENC_EN, mask_sh),\
SE_SF(HDMI_TB_ENC_CONTROL, HDMI_RESET, mask_sh),\
SE_SF(HDMI_TB_ENC_CONTROL, HDMI_RESET_DONE, mask_sh),\
SE_SF(HDMI_TB_ENC_MODE, HDMI_BORROW_MODE, mask_sh),\
SE_SF(HDMI_TB_ENC_H_ACTIVE_BLANK, HDMI_H_ACTIVE, mask_sh),\
SE_SF(HDMI_TB_ENC_H_ACTIVE_BLANK, HDMI_H_BLANK, mask_sh),\
SE_SF(HDMI_TB_ENC_HC_ACTIVE_BLANK, HDMI_HC_ACTIVE, mask_sh),\
SE_SF(HDMI_TB_ENC_HC_ACTIVE_BLANK, HDMI_HC_BLANK, mask_sh),\
SE_SF(HDMI_TB_ENC_PACKET_CONTROL, HDMI_MAX_PACKETS_PER_LINE, mask_sh),\
SE_SF(HDMI_TB_ENC_DB_CONTROL, HDMI_DB_DISABLE, mask_sh),\
SE_SF(HDMI_TB_ENC_PIXEL_FORMAT, HDMI_PIXEL_ENCODING, mask_sh),\
SE_SF(HDMI_TB_ENC_PIXEL_FORMAT, HDMI_DEEP_COLOR_DEPTH, mask_sh),\
SE_SF(HDMI_TB_ENC_PIXEL_FORMAT, HDMI_DEEP_COLOR_ENABLE, mask_sh),\
SE_SF(HDMI_TB_ENC_PIXEL_FORMAT, HDMI_DSC_MODE, mask_sh),\
SE_SF(HDMI_TB_ENC_VBI_PACKET_CONTROL1, HDMI_GC_CONT, mask_sh),\
SE_SF(HDMI_TB_ENC_VBI_PACKET_CONTROL1, HDMI_GC_SEND, mask_sh),\
SE_SF(HDMI_TB_ENC_VBI_PACKET_CONTROL1, HDMI_ACP_SEND, mask_sh),\
SE_SF(HDMI_TB_ENC_VBI_PACKET_CONTROL1, HDMI_AUDIO_INFO_SEND, mask_sh),\
SE_SF(HDMI_TB_ENC_VBI_PACKET_CONTROL1, HDMI_AUDIO_INFO_LINE, mask_sh),\
SE_SF(HDMI_TB_ENC_GC_CONTROL, HDMI_GC_AVMUTE, mask_sh),\
SE_SF(HDMI_TB_ENC_GENERIC_PACKET_CONTROL0, HDMI_GENERIC0_CONT, mask_sh),\
SE_SF(HDMI_TB_ENC_GENERIC_PACKET_CONTROL0, HDMI_GENERIC1_CONT, mask_sh),\
SE_SF(HDMI_TB_ENC_GENERIC_PACKET_CONTROL0, HDMI_GENERIC2_CONT, mask_sh),\
SE_SF(HDMI_TB_ENC_GENERIC_PACKET_CONTROL0, HDMI_GENERIC3_CONT, mask_sh),\
SE_SF(HDMI_TB_ENC_GENERIC_PACKET_CONTROL0, HDMI_GENERIC4_CONT, mask_sh),\
SE_SF(HDMI_TB_ENC_GENERIC_PACKET_CONTROL0, HDMI_GENERIC5_CONT, mask_sh),\
SE_SF(HDMI_TB_ENC_GENERIC_PACKET_CONTROL0, HDMI_GENERIC6_CONT, mask_sh),\
SE_SF(HDMI_TB_ENC_GENERIC_PACKET_CONTROL0, HDMI_GENERIC7_CONT, mask_sh),\
SE_SF(HDMI_TB_ENC_GENERIC_PACKET_CONTROL1, HDMI_GENERIC8_CONT, mask_sh),\
SE_SF(HDMI_TB_ENC_GENERIC_PACKET_CONTROL1, HDMI_GENERIC9_CONT, mask_sh),\
SE_SF(HDMI_TB_ENC_GENERIC_PACKET_CONTROL1, HDMI_GENERIC10_CONT, mask_sh),\
SE_SF(HDMI_TB_ENC_GENERIC_PACKET_CONTROL1, HDMI_GENERIC11_CONT, mask_sh),\
SE_SF(HDMI_TB_ENC_GENERIC_PACKET_CONTROL1, HDMI_GENERIC12_CONT, mask_sh),\
SE_SF(HDMI_TB_ENC_GENERIC_PACKET_CONTROL1, HDMI_GENERIC13_CONT, mask_sh),\
SE_SF(HDMI_TB_ENC_GENERIC_PACKET_CONTROL1, HDMI_GENERIC14_CONT, mask_sh),\
SE_SF(HDMI_TB_ENC_GENERIC_PACKET_CONTROL0, HDMI_GENERIC0_SEND, mask_sh),\
SE_SF(HDMI_TB_ENC_GENERIC_PACKET_CONTROL0, HDMI_GENERIC1_SEND, mask_sh),\
SE_SF(HDMI_TB_ENC_GENERIC_PACKET_CONTROL0, HDMI_GENERIC2_SEND, mask_sh),\
SE_SF(HDMI_TB_ENC_GENERIC_PACKET_CONTROL0, HDMI_GENERIC3_SEND, mask_sh),\
SE_SF(HDMI_TB_ENC_GENERIC_PACKET_CONTROL0, HDMI_GENERIC4_SEND, mask_sh),\
SE_SF(HDMI_TB_ENC_GENERIC_PACKET_CONTROL0, HDMI_GENERIC5_SEND, mask_sh),\
SE_SF(HDMI_TB_ENC_GENERIC_PACKET_CONTROL0, HDMI_GENERIC6_SEND, mask_sh),\
SE_SF(HDMI_TB_ENC_GENERIC_PACKET_CONTROL0, HDMI_GENERIC7_SEND, mask_sh),\
SE_SF(HDMI_TB_ENC_GENERIC_PACKET_CONTROL1, HDMI_GENERIC8_SEND, mask_sh),\
SE_SF(HDMI_TB_ENC_GENERIC_PACKET_CONTROL1, HDMI_GENERIC9_SEND, mask_sh),\
SE_SF(HDMI_TB_ENC_GENERIC_PACKET_CONTROL1, HDMI_GENERIC10_SEND, mask_sh),\
SE_SF(HDMI_TB_ENC_GENERIC_PACKET_CONTROL1, HDMI_GENERIC11_SEND, mask_sh),\
SE_SF(HDMI_TB_ENC_GENERIC_PACKET_CONTROL1, HDMI_GENERIC12_SEND, mask_sh),\
SE_SF(HDMI_TB_ENC_GENERIC_PACKET_CONTROL1, HDMI_GENERIC13_SEND, mask_sh),\
SE_SF(HDMI_TB_ENC_GENERIC_PACKET_CONTROL1, HDMI_GENERIC14_SEND, mask_sh),\
SE_SF(HDMI_TB_ENC_GENERIC_PACKET0_1_LINE, HDMI_GENERIC0_LINE, mask_sh),\
SE_SF(HDMI_TB_ENC_GENERIC_PACKET0_1_LINE, HDMI_GENERIC1_LINE, mask_sh),\
SE_SF(HDMI_TB_ENC_GENERIC_PACKET2_3_LINE, HDMI_GENERIC2_LINE, mask_sh),\
SE_SF(HDMI_TB_ENC_GENERIC_PACKET2_3_LINE, HDMI_GENERIC3_LINE, mask_sh),\
SE_SF(HDMI_TB_ENC_GENERIC_PACKET4_5_LINE, HDMI_GENERIC4_LINE, mask_sh),\
SE_SF(HDMI_TB_ENC_GENERIC_PACKET4_5_LINE, HDMI_GENERIC5_LINE, mask_sh),\
SE_SF(HDMI_TB_ENC_GENERIC_PACKET6_7_LINE, HDMI_GENERIC6_LINE, mask_sh),\
SE_SF(HDMI_TB_ENC_GENERIC_PACKET6_7_LINE, HDMI_GENERIC7_LINE, mask_sh),\
SE_SF(HDMI_TB_ENC_GENERIC_PACKET8_9_LINE, HDMI_GENERIC8_LINE, mask_sh),\
SE_SF(HDMI_TB_ENC_GENERIC_PACKET8_9_LINE, HDMI_GENERIC9_LINE, mask_sh),\
SE_SF(HDMI_TB_ENC_GENERIC_PACKET10_11_LINE, HDMI_GENERIC10_LINE, mask_sh),\
SE_SF(HDMI_TB_ENC_GENERIC_PACKET10_11_LINE, HDMI_GENERIC11_LINE, mask_sh),\
SE_SF(HDMI_TB_ENC_GENERIC_PACKET12_13_LINE, HDMI_GENERIC12_LINE, mask_sh),\
SE_SF(HDMI_TB_ENC_GENERIC_PACKET12_13_LINE, HDMI_GENERIC13_LINE, mask_sh),\
SE_SF(HDMI_TB_ENC_GENERIC_PACKET14_LINE, HDMI_GENERIC14_LINE, mask_sh),\
SE_SF(HDMI_TB_ENC_ACR_PACKET_CONTROL, HDMI_ACR_AUTO_SEND, mask_sh),\
SE_SF(HDMI_TB_ENC_ACR_PACKET_CONTROL, HDMI_ACR_SOURCE, mask_sh),\
SE_SF(HDMI_TB_ENC_ACR_PACKET_CONTROL, HDMI_ACR_AUDIO_PRIORITY, mask_sh),\
SE_SF(HDMI_TB_ENC_ACR_32_0, HDMI_ACR_CTS_32, mask_sh),\
SE_SF(HDMI_TB_ENC_ACR_32_1, HDMI_ACR_N_32, mask_sh),\
SE_SF(HDMI_TB_ENC_ACR_44_0, HDMI_ACR_CTS_44, mask_sh),\
SE_SF(HDMI_TB_ENC_ACR_44_1, HDMI_ACR_N_44, mask_sh),\
SE_SF(HDMI_TB_ENC_ACR_48_0, HDMI_ACR_CTS_48, mask_sh),\
SE_SF(HDMI_TB_ENC_ACR_48_1, HDMI_ACR_N_48, mask_sh),\
SE_SF(HDMI_TB_ENC_CRC_CNTL, HDMI_CRC_EN, mask_sh),\
SE_SF(HDMI_TB_ENC_CRC_CNTL, HDMI_CRC_CONT_EN, mask_sh)
#define DCN401_HDMI_TB_ENC_REG_FIELD_LIST(type) \
type HDMI_TB_ENC_EN;\
type HDMI_RESET;\
type HDMI_RESET_DONE;\
type HDMI_STREAM_ENC_CLOCK_EN;\
type HDMI_STREAM_ENC_INPUT_MUX_SOURCE_SEL;\
type HDMI_MAX_PACKETS_PER_LINE;\
type FIFO_ENABLE;\
type FIFO_RESET;\
type FIFO_PIXEL_ENCODING_TYPE;\
type FIFO_UNCOMPRESSED_PIXEL_FORMAT;\
type FIFO_COMPRESSED_PIXEL_FORMAT;\
type FIFO_RESET_DONE;\
type HDMI_BORROW_MODE;\
type HDMI_H_ACTIVE;\
type HDMI_H_BLANK;\
type HDMI_HC_ACTIVE;\
type HDMI_HC_BLANK;\
type HDMI_DB_DISABLE;\
type HDMI_PIXEL_ENCODING;\
type HDMI_DEEP_COLOR_DEPTH;\
type HDMI_DEEP_COLOR_ENABLE;\
type HDMI_ODM_COMBINE_MODE;\
type HDMI_DSC_MODE;\
type HDMI_GC_CONT;\
type HDMI_GC_SEND;\
type HDMI_ACP_SEND;\
type HDMI_AUDIO_INFO_SEND;\
type HDMI_AUDIO_INFO_LINE;\
type HDMI_GC_AVMUTE;\
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 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 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 HDMI_CRC_EN;\
type HDMI_CRC_CONT_EN;\
type METADATA_HUBP_REQUESTOR_ID;\
type METADATA_ENGINE_EN;\
type METADATA_STREAM_TYPE;\
type HDMI_METADATA_PACKET_ENABLE;\
type HDMI_METADATA_PACKET_LINE_REFERENCE;\
type HDMI_METADATA_PACKET_MISSED;\
type HDMI_METADATA_PACKET_LINE
#define DCN401_HPO_STREAM_ENC_MASK_SH_LIST(mask_sh)\
DCN401_HDMI_STREAM_ENC_MASK_SH_LIST(mask_sh),\
DCN401_HDMI_TB_ENC_MASK_SH_LIST(mask_sh)
#define DCN42_HDMI_TB_ENC_REG_FIELD_LIST(type) \
type HDMI_STREAM_ENC_INPUT_MUX_AUDIO_STREAM_SOURCE_SEL;\
type HDMI_STREAM_ENC_APG_CLOCK_EN
struct dcn401_hpo_frl_stream_encoder_shift {
DCN401_HDMI_TB_ENC_REG_FIELD_LIST(uint8_t);
DCN42_HDMI_TB_ENC_REG_FIELD_LIST(uint8_t);
};
struct dcn401_hpo_frl_stream_encoder_mask {
DCN401_HDMI_TB_ENC_REG_FIELD_LIST(uint32_t);
DCN42_HDMI_TB_ENC_REG_FIELD_LIST(uint32_t);
};
struct dcn401_hpo_frl_stream_encoder {
struct hpo_frl_stream_encoder base;
const struct dcn30_hpo_frl_stream_enc_registers *regs;
const struct dcn401_hpo_frl_stream_encoder_shift *hpo_se_shift;
const struct dcn401_hpo_frl_stream_encoder_mask *hpo_se_mask;
};
void hpo_enc401_enable(
struct hpo_frl_stream_encoder *enc,
int otg_inst);
void hpo_enc401_unblank(
struct hpo_frl_stream_encoder *enc,
int otg_inst);
void hpo_enc401_read_state(
struct hpo_frl_stream_encoder *enc,
struct hpo_frl_stream_encoder_state *state);
void hpo_enc401_blank(
struct hpo_frl_stream_encoder *enc);
void hpo_enc401_set_hdmi_stream_attribute(
struct hpo_frl_stream_encoder *enc,
struct dc_crtc_timing *crtc_timing,
struct frl_borrow_params *borrow_params,
int odm_combine_num_segments);
void hpo_enc401_update_hdmi_info_packet(
struct dcn401_hpo_frl_stream_encoder *enc401,
uint32_t packet_index,
const struct dc_info_packet *info_packet);
void hpo_enc401_update_hdmi_info_packets(
struct hpo_frl_stream_encoder *enc,
const struct encoder_info_frame *info_frame);
void hpo_enc401_hdmi_set_dsc_config(
struct hpo_frl_stream_encoder *enc,
struct dc_crtc_timing *timing,
uint8_t *dsc_packed_pps);
void hpo_enc401_stop_hdmi_info_packets(
struct hpo_frl_stream_encoder *enc);
void hpo_enc401_setup_hdmi_audio(
struct hpo_frl_stream_encoder *enc,
const struct audio_crtc_info *crtc_info);
void hpo_enc401_hdmi_audio_setup(
struct hpo_frl_stream_encoder *enc,
unsigned int az_inst,
struct audio_info *info,
struct audio_crtc_info *audio_crtc_info);
void hpo_enc401_hdmi_audio_disable(
struct hpo_frl_stream_encoder *enc);
void hpo_enc401_audio_mute_control(
struct hpo_frl_stream_encoder *enc,
bool mute);
void enc401_stream_encoder_set_avmute(
struct hpo_frl_stream_encoder *enc,
bool enable);
void hpo_enc401_set_dynamic_metadata(
struct hpo_frl_stream_encoder *enc,
bool enable_dme,
uint32_t hubp_requestor_id,
enum dynamic_metadata_mode dmdata_mode);
void frl_get_audio_clock_info(
enum dc_color_depth color_depth,
uint32_t frl_character_clock_kHz,
struct frl_audio_clock_info *audio_clock_info);
void dcn401_hpo_frl_stream_encoder_construct(
struct dcn401_hpo_frl_stream_encoder *enc401,
struct dc_context *ctx,
struct dc_bios *bp,
enum engine_id eng_id,
struct vpg *vpg,
struct afmt *afmt,
const struct dcn30_hpo_frl_stream_enc_registers *regs,
const struct dcn401_hpo_frl_stream_encoder_shift *hpo_se_shift,
const struct dcn401_hpo_frl_stream_encoder_mask *hpo_se_mask);
#endif
@@ -0,0 +1,93 @@
// SPDX-License-Identifier: MIT
//
// Copyright 2026 Advanced Micro Devices, Inc.
#include "dc_bios_types.h"
#include "dcn31/dcn31_hpo_dp_link_encoder.h"
#include "dcn32/dcn32_hpo_dp_link_encoder.h"
#include "dcn42_hpo_dp_link_encoder.h"
#include "reg_helper.h"
#include "stream_encoder.h"
#define DC_LOGGER \
enc3->base.ctx->logger
#define REG(reg)\
(enc3->regs->reg)
#undef FN
#define FN(reg_name, field_name) \
enc3->hpo_le_shift->field_name, enc3->hpo_le_mask->field_name
#define CTX \
enc3->base.ctx
static void dcn42_hpo_dp_link_enc_read_state(
struct hpo_dp_link_encoder *enc,
struct hpo_dp_link_enc_state *state)
{
struct dcn31_hpo_dp_link_encoder *enc3 = DCN3_1_HPO_DP_LINK_ENC_FROM_HPO_LINK_ENC(enc);
ASSERT(state);
REG_GET(DP_DPHY_SYM32_STATUS,
STATUS, &state->link_enc_enabled);
REG_GET(DP_DPHY_SYM32_CONTROL,
NUM_LANES, &state->lane_count);
REG_GET(DP_DPHY_SYM32_CONTROL,
MODE, (uint32_t *)&state->link_mode);
REG_GET_2(DP_DPHY_SYM32_SAT_VC0,
SAT_STREAM_SOURCE, &state->stream_src[0],
SAT_SLOT_COUNT, &state->slot_count[0]);
REG_GET_2(DP_DPHY_SYM32_SAT_VC1,
SAT_STREAM_SOURCE, &state->stream_src[1],
SAT_SLOT_COUNT, &state->slot_count[1]);
REG_GET_2(DP_DPHY_SYM32_SAT_VC2,
SAT_STREAM_SOURCE, &state->stream_src[2],
SAT_SLOT_COUNT, &state->slot_count[2]);
REG_GET_2(DP_DPHY_SYM32_VC_RATE_CNTL0,
STREAM_VC_RATE_X, &state->vc_rate_x[0],
STREAM_VC_RATE_Y, &state->vc_rate_y[0]);
REG_GET_2(DP_DPHY_SYM32_VC_RATE_CNTL1,
STREAM_VC_RATE_X, &state->vc_rate_x[1],
STREAM_VC_RATE_Y, &state->vc_rate_y[1]);
REG_GET_2(DP_DPHY_SYM32_VC_RATE_CNTL2,
STREAM_VC_RATE_X, &state->vc_rate_x[2],
STREAM_VC_RATE_Y, &state->vc_rate_y[2]);
}
static struct hpo_dp_link_encoder_funcs dcn42_hpo_dp_link_encoder_funcs = {
.enable_link_phy = dcn31_hpo_dp_link_enc_enable_dp_output,
.disable_link_phy = dcn31_hpo_dp_link_enc_disable_output,
.link_enable = dcn31_hpo_dp_link_enc_enable,
.link_disable = dcn31_hpo_dp_link_enc_disable,
.set_link_test_pattern = dcn31_hpo_dp_link_enc_set_link_test_pattern,
.update_stream_allocation_table = dcn31_hpo_dp_link_enc_update_stream_allocation_table,
.set_throttled_vcp_size = dcn31_hpo_dp_link_enc_set_throttled_vcp_size,
.is_in_alt_mode = dcn32_hpo_dp_link_enc_is_in_alt_mode,
.read_state = dcn42_hpo_dp_link_enc_read_state,
.set_ffe = dcn31_hpo_dp_link_enc_set_ffe,
};
void hpo_dp_link_encoder42_construct(struct dcn31_hpo_dp_link_encoder *enc31,
struct dc_context *ctx,
uint32_t inst,
const struct dcn31_hpo_dp_link_encoder_registers *hpo_le_regs,
const struct dcn31_hpo_dp_link_encoder_shift *hpo_le_shift,
const struct dcn31_hpo_dp_link_encoder_mask *hpo_le_mask)
{
enc31->base.ctx = ctx;
enc31->base.inst = inst;
enc31->base.funcs = &dcn42_hpo_dp_link_encoder_funcs;
enc31->base.hpd_source = HPD_SOURCEID_UNKNOWN;
enc31->base.transmitter = TRANSMITTER_UNKNOWN;
enc31->regs = hpo_le_regs;
enc31->hpo_le_shift = hpo_le_shift;
enc31->hpo_le_mask = hpo_le_mask;
}
@@ -0,0 +1,17 @@
/* SPDX-License-Identifier: MIT */
/* Copyright 2026 Advanced Micro Devices, Inc. */
#ifndef __DAL_DCN42_HPO_DP_LINK_ENCODER_H__
#define __DAL_DCN42_HPO_DP_LINK_ENCODER_H__
#include "link_encoder.h"
void hpo_dp_link_encoder42_construct(struct dcn31_hpo_dp_link_encoder *enc31,
struct dc_context *ctx,
uint32_t inst,
const struct dcn31_hpo_dp_link_encoder_registers *hpo_le_regs,
const struct dcn31_hpo_dp_link_encoder_shift *hpo_le_shift,
const struct dcn31_hpo_dp_link_encoder_mask *hpo_le_mask);
#endif // __DAL_DCN32_HPO_DP_LINK_ENCODER_H__
@@ -0,0 +1,207 @@
// SPDX-License-Identifier: MIT
//
// Copyright 2025 Advanced Micro Devices, Inc.
#include "dc_bios_types.h"
#include "core_types.h"
#include "dcn42_hpo_frl_stream_encoder.h"
#include "dcn31/dcn31_apg.h"
#include "dcn401/dcn401_hpo_frl_stream_encoder.h"
#include "dcn30/dcn30_hpo_frl_stream_encoder.h"
#include "reg_helper.h"
#include "hw_shared.h"
#include "dcn_calc_math.h"
#include "dml/dcn30/dcn30_fpu.h"
#undef DC_LOGGER
#define DC_LOGGER \
enc401->base.ctx->logger
#define DTRACE(str, ...) {DC_LOG_HDMI_FRL(str, ##__VA_ARGS__); }
#define DEBUG_FRL_CAP_CHK 1
#define REG(reg)\
(enc401->regs->reg)
#undef FN
#define FN(reg_name, field_name) \
enc401->hpo_se_shift->field_name, enc401->hpo_se_mask->field_name
#define CTX \
enc401->base.ctx
#define VBI_LINE_0 0
void hpo_enc42_unblank(struct hpo_frl_stream_encoder *enc, int otg_inst)
{
(void)otg_inst;
struct dcn401_hpo_frl_stream_encoder *enc401 = DCN401_HPO_FRL_STRENC_FROM_HPO_FRL_STRENC(enc);
DC_LOG_HDMI_FRL("Entering [%s]\n", __func__);
/*make sure FIFO_VIDEO_STREAM_ACTIVE =1*/
REG_UPDATE(HDMI_STREAM_ENC_CLOCK_RAMP_ADJUSTER_FIFO_STATUS_CONTROL0,
FIFO_ENABLE, 0);
/* Reset */
REG_UPDATE(HDMI_STREAM_ENC_CLOCK_RAMP_ADJUSTER_FIFO_STATUS_CONTROL0,
FIFO_RESET, 1);
REG_WAIT(HDMI_STREAM_ENC_CLOCK_RAMP_ADJUSTER_FIFO_STATUS_CONTROL0, FIFO_RESET_DONE,
1, 10, 1000);
REG_UPDATE(HDMI_STREAM_ENC_CLOCK_RAMP_ADJUSTER_FIFO_STATUS_CONTROL0,
FIFO_RESET, 0);
REG_WAIT(HDMI_STREAM_ENC_CLOCK_RAMP_ADJUSTER_FIFO_STATUS_CONTROL0, FIFO_RESET_DONE,
0, 10, 1000);
/* Enable HDMI Tribyte Encoder */
REG_UPDATE(HDMI_TB_ENC_CONTROL,
HDMI_TB_ENC_EN, 1);
/* Enable Clock Ramp Adjuster FIFO */
REG_UPDATE(HDMI_STREAM_ENC_CLOCK_RAMP_ADJUSTER_FIFO_STATUS_CONTROL0,
FIFO_ENABLE, 1);
DC_LOG_HDMI_FRL("Exiting [%s]\n", __func__);
}
void hpo_enc42_setup_hdmi_audio(
struct hpo_frl_stream_encoder *enc,
const struct audio_crtc_info *crtc_info)
{
struct dcn401_hpo_frl_stream_encoder *enc401 = DCN401_HPO_FRL_STRENC_FROM_HPO_FRL_STRENC(enc);
struct frl_audio_clock_info audio_clock_info = {0};
DC_LOG_DEBUG("Entering [%s]\n", __func__);
/* TODO: HDMI_AUDIO_DELAY_EN bit only in DIG -- not in HPO? */
/* HDMI_AUDIO_PACKET_CONTROL */
//REG_UPDATE(HDMI_AUDIO_PACKET_CONTROL,
// HDMI_AUDIO_DELAY_EN, 1);
/* Setup audio in APG - program APG block associated with HPO */
ASSERT(enc->apg);
/* HDMI_ACR_PACKET_CONTROL */
REG_UPDATE_3(HDMI_TB_ENC_ACR_PACKET_CONTROL,
HDMI_ACR_AUTO_SEND, 1,
HDMI_ACR_SOURCE, 0,
HDMI_ACR_AUDIO_PRIORITY, 0);
/* N/CTS computed relative to FRL rate instead of video rate (TMDS character clock). */
/* Program audio clock sample/regeneration parameters */
frl_get_audio_clock_info(crtc_info->color_depth,
crtc_info->frl_character_clock_kHz,
&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);
/* Same register definition, but using HDMI_TB_ENC register */
/* HDMI_ACR_32_0__HDMI_ACR_CTS_32_MASK */
REG_UPDATE(HDMI_TB_ENC_ACR_32_0, HDMI_ACR_CTS_32, audio_clock_info.cts_32khz);
/* HDMI_ACR_32_1__HDMI_ACR_N_32_MASK */
REG_UPDATE(HDMI_TB_ENC_ACR_32_1, HDMI_ACR_N_32, audio_clock_info.n_32khz);
/* HDMI_ACR_44_0__HDMI_ACR_CTS_44_MASK */
REG_UPDATE(HDMI_TB_ENC_ACR_44_0, HDMI_ACR_CTS_44, audio_clock_info.cts_44khz);
/* HDMI_ACR_44_1__HDMI_ACR_N_44_MASK */
REG_UPDATE(HDMI_TB_ENC_ACR_44_1, HDMI_ACR_N_44, audio_clock_info.n_44khz);
/* HDMI_ACR_48_0__HDMI_ACR_CTS_48_MASK */
REG_UPDATE(HDMI_TB_ENC_ACR_48_0, HDMI_ACR_CTS_48, audio_clock_info.cts_48khz);
/* HDMI_ACR_48_1__HDMI_ACR_N_48_MASK */
REG_UPDATE(HDMI_TB_ENC_ACR_48_1, HDMI_ACR_N_48, audio_clock_info.n_48khz);
/* TODO: HDMI_TB_ENC_ACR_PACKET_CONTROL::ACR_N_MULTIPLE
* Same register definition, but using HDMI_TB_ENC register*/
/* 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 interrupt callback
*/
DC_LOG_DEBUG("Exiting [%s]\n", __func__);
}
void hpo_enc42_hdmi_audio_setup(
struct hpo_frl_stream_encoder *enc,
unsigned int az_inst,
struct audio_info *info,
struct audio_crtc_info *audio_crtc_info)
{
struct dcn401_hpo_frl_stream_encoder *enc401 = DCN401_HPO_FRL_STRENC_FROM_HPO_FRL_STRENC(enc);
REG_UPDATE_2(HDMI_STREAM_ENC_AUDIO_CONTROL,
HDMI_STREAM_ENC_INPUT_MUX_AUDIO_STREAM_SOURCE_SEL, az_inst,
HDMI_STREAM_ENC_APG_CLOCK_EN, 1);
hpo_enc42_setup_hdmi_audio(enc, audio_crtc_info);
ASSERT (enc->apg);
enc->apg->funcs->se_audio_setup(enc->apg, az_inst, info);
}
void hpo_enc42_hdmi_audio_disable(
struct hpo_frl_stream_encoder *enc)
{
ASSERT(enc->apg);
if (enc->apg->funcs->disable_apg)
enc->apg->funcs->disable_apg(enc->apg);
}
void hpo_enc42_audio_mute_control(
struct hpo_frl_stream_encoder *enc,
bool mute)
{
ASSERT (enc->apg);
if (mute)
enc->apg->funcs->disable_apg(enc->apg);
else
enc->apg->funcs->enable_apg(enc->apg);
}
static const struct hpo_frl_stream_encoder_funcs dcn42_str_enc_funcs = {
.hdmi_frl_enable = hpo_enc401_enable,
.hdmi_frl_unblank = hpo_enc42_unblank,
.hdmi_frl_blank = hpo_enc401_blank,
.hdmi_frl_set_stream_attribute = hpo_enc401_set_hdmi_stream_attribute,
.validate_hdmi_frl_output = hpo_enc3_validate_hdmi_frl_output,
.update_hdmi_info_packets = hpo_enc401_update_hdmi_info_packets,
.stop_hdmi_info_packets = hpo_enc401_stop_hdmi_info_packets,
.audio_mute_control = hpo_enc42_audio_mute_control,
.hdmi_audio_setup = hpo_enc42_hdmi_audio_setup,
.hdmi_audio_disable = hpo_enc42_hdmi_audio_disable,
.set_avmute = enc401_stream_encoder_set_avmute,
.read_state = hpo_enc401_read_state,
.hdmi_frl_set_dsc_config = hpo_enc401_hdmi_set_dsc_config,
.set_dynamic_metadata = hpo_enc401_set_dynamic_metadata,
};
void dcn42_hpo_frl_stream_encoder_construct(
struct dcn42_hpo_frl_stream_encoder *enc42,
struct dc_context *ctx,
struct dc_bios *bp,
enum engine_id eng_id,
struct vpg *vpg,
struct apg *apg,
const struct dcn30_hpo_frl_stream_enc_registers *regs,
const struct dcn401_hpo_frl_stream_encoder_shift *hpo_se_shift,
const struct dcn401_hpo_frl_stream_encoder_mask *hpo_se_mask)
{
enc42->base.funcs = &dcn42_str_enc_funcs;
enc42->base.ctx = ctx;
enc42->base.id = eng_id;
enc42->base.bp = bp;
enc42->base.vpg = vpg;
enc42->base.apg = apg;
enc42->regs = regs;
enc42->hpo_se_shift = hpo_se_shift;
enc42->hpo_se_mask = hpo_se_mask;
enc42->base.stream_enc_inst = vpg->inst;
}
@@ -0,0 +1,59 @@
// SPDX-License-Identifier: MIT
//
// Copyright 2025 Advanced Micro Devices, Inc.
#ifndef __DC_HPO_FRL_STREAM_ENCODER_DCN42_H__
#define __DC_HPO_FRL_STREAM_ENCODER_DCN42_H__
#include "dcn30/dcn30_vpg.h"
#include "dcn31/dcn31_apg.h"
#include "dcn30/dcn30_hpo_frl_stream_encoder.h"
#include "dcn401/dcn401_hpo_frl_stream_encoder.h"
#include "stream_encoder.h"
#include "dml/dml1_frl_cap_chk.h"
#define DCN42_HDMI_STREAM_ENC_MASK_SH_LIST(mask_sh)\
DCN401_HPO_STREAM_ENC_MASK_SH_LIST(mask_sh),\
SE_SF(HDMI_STREAM_ENC_AUDIO_CONTROL, HDMI_STREAM_ENC_INPUT_MUX_AUDIO_STREAM_SOURCE_SEL, mask_sh),\
SE_SF(HDMI_STREAM_ENC_AUDIO_CONTROL, HDMI_STREAM_ENC_APG_CLOCK_EN, mask_sh)
struct dcn42_hpo_frl_stream_encoder {
struct hpo_frl_stream_encoder base;
const struct dcn30_hpo_frl_stream_enc_registers *regs;
const struct dcn401_hpo_frl_stream_encoder_shift *hpo_se_shift;
const struct dcn401_hpo_frl_stream_encoder_mask *hpo_se_mask;
};
void hpo_enc42_unblank(
struct hpo_frl_stream_encoder *enc,
int otg_inst);
void hpo_enc42_setup_hdmi_audio(
struct hpo_frl_stream_encoder *enc,
const struct audio_crtc_info *crtc_info);
void hpo_enc42_hdmi_audio_setup(
struct hpo_frl_stream_encoder *enc,
unsigned int az_inst,
struct audio_info *info,
struct audio_crtc_info *audio_crtc_info);
void hpo_enc42_hdmi_audio_disable(
struct hpo_frl_stream_encoder *enc);
void hpo_enc42_audio_mute_control(
struct hpo_frl_stream_encoder *enc,
bool mute);
void dcn42_hpo_frl_stream_encoder_construct(
struct dcn42_hpo_frl_stream_encoder *enc42,
struct dc_context *ctx,
struct dc_bios *bp,
enum engine_id eng_id,
struct vpg *vpg,
struct apg *apg,
const struct dcn30_hpo_frl_stream_enc_registers *regs,
const struct dcn401_hpo_frl_stream_encoder_shift *hpo_se_shift,
const struct dcn401_hpo_frl_stream_encoder_mask *hpo_se_mask);
#endif /* __DC_HPO_STREAM_ENCODER_DCN42_H__ */