mirror of
https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux.git
synced 2026-09-22 09:34:56 +02:00
drm/amd/display: Add DCCG DIO, HPO, OPP, and OPTC support for FRL
This adds support to HW block programming for the core blocks for HDMI FRL: - DIO - HPO - OPP - OPTC Signed-off-by: Harry Wentland <harry.wentland@amd.com> Reviewed-by: Fangzhi Zuo <Jerry.Zuo@amd.com> Tested-by: Dan Wheeler <daniel.wheeler@amd.com> Signed-off-by: Alex Deucher <alexander.deucher@amd.com>
This commit is contained in:
committed by
Alex Deucher
parent
8812fae129
commit
d36771a034
@@ -42,8 +42,48 @@
|
||||
#define DC_LOGGER \
|
||||
dccg->ctx->logger
|
||||
|
||||
void dccg3_enable_hdmicharclk(struct dccg *dccg, int hpo_inst, int phypll_inst)
|
||||
{
|
||||
struct dcn_dccg *dccg_dcn = TO_DCN_DCCG(dccg);
|
||||
|
||||
ASSERT(hpo_inst >= 0 && phypll_inst >= 0);
|
||||
REG_UPDATE_2(HDMICHARCLK_CLOCK_CNTL[hpo_inst],
|
||||
HDMICHARCLK0_EN, 1,
|
||||
HDMICHARCLK0_SRC_SEL, phypll_inst);
|
||||
|
||||
/* Enable FORCE_EN for SYMCLK */
|
||||
switch (phypll_inst) {
|
||||
case 0:
|
||||
REG_UPDATE_2(PHYASYMCLK_CLOCK_CNTL,
|
||||
PHYASYMCLK_FORCE_EN, 1,
|
||||
PHYASYMCLK_FORCE_SRC_SEL, 1);
|
||||
break;
|
||||
case 1:
|
||||
REG_UPDATE_2(PHYBSYMCLK_CLOCK_CNTL,
|
||||
PHYBSYMCLK_FORCE_EN, 1,
|
||||
PHYBSYMCLK_FORCE_SRC_SEL, 1);
|
||||
break;
|
||||
case 2:
|
||||
REG_UPDATE_2(PHYCSYMCLK_CLOCK_CNTL,
|
||||
PHYCSYMCLK_FORCE_EN, 1,
|
||||
PHYCSYMCLK_FORCE_SRC_SEL, 1);
|
||||
break;
|
||||
default:
|
||||
BREAK_TO_DEBUGGER();
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
void dccg3_disable_hdmicharclk(struct dccg *dccg, int hpo_inst)
|
||||
{
|
||||
struct dcn_dccg *dccg_dcn = TO_DCN_DCCG(dccg);
|
||||
|
||||
REG_WRITE(HDMICHARCLK_CLOCK_CNTL[hpo_inst], 0);
|
||||
}
|
||||
|
||||
static const struct dccg_funcs dccg3_funcs = {
|
||||
.enable_hdmicharclk = dccg3_enable_hdmicharclk,
|
||||
.disable_hdmicharclk = dccg3_disable_hdmicharclk,
|
||||
.update_dpp_dto = dccg2_update_dpp_dto,
|
||||
.get_dccg_ref_freq = dccg2_get_dccg_ref_freq,
|
||||
.set_fifo_errdet_ovr_en = dccg2_set_fifo_errdet_ovr_en,
|
||||
|
||||
@@ -63,4 +63,12 @@ struct dccg *dccg30_create(
|
||||
const struct dccg_shift *dccg_shift,
|
||||
const struct dccg_mask *dccg_mask);
|
||||
|
||||
void dccg3_enable_hdmicharclk(
|
||||
struct dccg *dccg,
|
||||
int hpo_inst,
|
||||
int phypll_inst);
|
||||
|
||||
void dccg3_disable_hdmicharclk(
|
||||
struct dccg *dccg,
|
||||
int hpo_inst);
|
||||
#endif //__DCN30_DCCG_H__
|
||||
|
||||
@@ -664,6 +664,87 @@ void dccg31_set_dispclk_change_mode(
|
||||
change_mode == DISPCLK_CHANGE_MODE_RAMPING ? 2 : 0);
|
||||
}
|
||||
|
||||
void dccg31_set_hdmistreamclk(
|
||||
struct dccg *dccg,
|
||||
enum streamclk_source src,
|
||||
uint32_t otg_inst)
|
||||
{
|
||||
(void)otg_inst;
|
||||
struct dcn_dccg *dccg_dcn = TO_DCN_DCCG(dccg);
|
||||
|
||||
if (src == REFCLK) {
|
||||
REG_UPDATE_2(HDMISTREAMCLK_CNTL,
|
||||
HDMISTREAMCLK0_SRC_SEL, 0, /* SEL_REFCLK0 */
|
||||
HDMISTREAMCLK0_DTO_FORCE_DIS, 1); /* DTO_FORCE_BYPASS */
|
||||
} else {
|
||||
REG_UPDATE_2(HDMISTREAMCLK_CNTL,
|
||||
HDMISTREAMCLK0_SRC_SEL, 1, /* SEL_DTBCLK0 */
|
||||
HDMISTREAMCLK0_DTO_FORCE_DIS, 1); /* DTO_FORCE_BYPASS */
|
||||
}
|
||||
}
|
||||
|
||||
static void dccg31_disable_hdmistreamclk(struct dccg *dccg)
|
||||
{
|
||||
struct dcn_dccg *dccg_dcn = TO_DCN_DCCG(dccg);
|
||||
|
||||
if (dccg->ctx->dc->debug.root_clock_optimization.bits.hdmistream)
|
||||
REG_UPDATE_2(HDMISTREAMCLK0_DTO_PARAM,
|
||||
HDMISTREAMCLK0_DTO_PHASE, 0,
|
||||
HDMISTREAMCLK0_DTO_MODULO, 1);
|
||||
}
|
||||
|
||||
void dccg31_enable_hdmicharclk(struct dccg *dccg, int hpo_inst, int phypll_inst)
|
||||
{
|
||||
struct dcn_dccg *dccg_dcn = TO_DCN_DCCG(dccg);
|
||||
|
||||
ASSERT(hpo_inst >= 0 && phypll_inst >= 0);
|
||||
if (dccg->ctx->dc->debug.root_clock_optimization.bits.hdmichar) {
|
||||
REG_UPDATE(DCCG_GATE_DISABLE_CNTL4,
|
||||
HDMICHARCLK0_ROOT_GATE_DISABLE, 1);
|
||||
REG_UPDATE(DCCG_GATE_DISABLE_CNTL2,
|
||||
HDMICHARCLK0_GATE_DISABLE, 1);
|
||||
}
|
||||
|
||||
REG_UPDATE_2(HDMICHARCLK_CLOCK_CNTL[hpo_inst],
|
||||
HDMICHARCLK0_EN, 1,
|
||||
HDMICHARCLK0_SRC_SEL, phypll_inst);
|
||||
|
||||
/* Enable FORCE_EN for SYMCLK */
|
||||
switch (phypll_inst) {
|
||||
case 0:
|
||||
REG_UPDATE_2(PHYASYMCLK_CLOCK_CNTL,
|
||||
PHYASYMCLK_FORCE_EN, 1,
|
||||
PHYASYMCLK_FORCE_SRC_SEL, 1);
|
||||
break;
|
||||
case 1:
|
||||
REG_UPDATE_2(PHYBSYMCLK_CLOCK_CNTL,
|
||||
PHYBSYMCLK_FORCE_EN, 1,
|
||||
PHYBSYMCLK_FORCE_SRC_SEL, 1);
|
||||
break;
|
||||
case 2:
|
||||
REG_UPDATE_2(PHYCSYMCLK_CLOCK_CNTL,
|
||||
PHYCSYMCLK_FORCE_EN, 1,
|
||||
PHYCSYMCLK_FORCE_SRC_SEL, 1);
|
||||
break;
|
||||
default:
|
||||
BREAK_TO_DEBUGGER();
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
void dccg31_disable_hdmicharclk(struct dccg *dccg, int hpo_inst)
|
||||
{
|
||||
struct dcn_dccg *dccg_dcn = TO_DCN_DCCG(dccg);
|
||||
|
||||
REG_WRITE(HDMICHARCLK_CLOCK_CNTL[hpo_inst], 0);
|
||||
if (dccg->ctx->dc->debug.root_clock_optimization.bits.hdmichar) {
|
||||
REG_UPDATE(DCCG_GATE_DISABLE_CNTL2,
|
||||
HDMICHARCLK0_GATE_DISABLE, 0);
|
||||
REG_UPDATE(DCCG_GATE_DISABLE_CNTL4,
|
||||
HDMICHARCLK0_ROOT_GATE_DISABLE, 0);
|
||||
}
|
||||
}
|
||||
|
||||
void dccg31_init(struct dccg *dccg)
|
||||
{
|
||||
/* Set HPO stream encoder to use refclk to avoid case where PHY is
|
||||
@@ -692,6 +773,10 @@ void dccg31_init(struct dccg *dccg)
|
||||
dccg31_set_physymclk(dccg, 3, PHYSYMCLK_FORCE_SRC_SYMCLK, false);
|
||||
dccg31_set_physymclk(dccg, 4, PHYSYMCLK_FORCE_SRC_SYMCLK, false);
|
||||
}
|
||||
dccg31_disable_hdmistreamclk(dccg);
|
||||
|
||||
if (dccg->ctx->dc->debug.root_clock_optimization.bits.hdmichar)
|
||||
dccg31_disable_hdmicharclk(dccg, 0);
|
||||
}
|
||||
|
||||
void dccg31_otg_add_pixel(struct dccg *dccg,
|
||||
@@ -835,6 +920,9 @@ void dccg31_read_reg_state(struct dccg *dccg, struct dcn_dccg_reg_state *dccg_re
|
||||
}
|
||||
|
||||
static const struct dccg_funcs dccg31_funcs = {
|
||||
.enable_hdmicharclk = dccg31_enable_hdmicharclk,
|
||||
.disable_hdmicharclk = dccg31_disable_hdmicharclk,
|
||||
.set_hdmistreamclk = dccg31_set_hdmistreamclk,
|
||||
.update_dpp_dto = dccg31_update_dpp_dto,
|
||||
.get_dccg_ref_freq = dccg31_get_dccg_ref_freq,
|
||||
.dccg_init = dccg31_init,
|
||||
|
||||
@@ -202,6 +202,19 @@ void dccg31_set_physymclk(
|
||||
void dccg31_set_audio_dtbclk_dto(
|
||||
struct dccg *dccg,
|
||||
const struct dtbclk_dto_params *params);
|
||||
void dccg31_enable_hdmicharclk(
|
||||
struct dccg *dccg,
|
||||
int hpo_inst,
|
||||
int phypll_inst);
|
||||
|
||||
void dccg31_disable_hdmicharclk(
|
||||
struct dccg *dccg,
|
||||
int hpo_inst);
|
||||
|
||||
void dccg31_set_hdmistreamclk(
|
||||
struct dccg *dccg,
|
||||
enum streamclk_source src,
|
||||
uint32_t otg_inst);
|
||||
|
||||
void dccg31_update_dpp_dto(
|
||||
struct dccg *dccg,
|
||||
|
||||
@@ -286,6 +286,28 @@ void dccg314_set_dpstreamclk(
|
||||
}
|
||||
}
|
||||
|
||||
static void dccg314_set_hdmistreamclk(
|
||||
struct dccg *dccg,
|
||||
enum streamclk_source src,
|
||||
uint32_t otg_inst)
|
||||
{
|
||||
struct dcn_dccg *dccg_dcn = TO_DCN_DCCG(dccg);
|
||||
|
||||
/* set the dtbclk_p source */
|
||||
dccg314_set_dtbclk_p_src(dccg, src, otg_inst);
|
||||
|
||||
if (src == REFCLK) {
|
||||
REG_UPDATE_2(HDMISTREAMCLK_CNTL,
|
||||
HDMISTREAMCLK0_EN, 0, /* SEL_REFCLK */
|
||||
HDMISTREAMCLK0_DTO_FORCE_DIS, 1); /* DTO_FORCE_BYPASS */
|
||||
} else {
|
||||
REG_UPDATE_3(HDMISTREAMCLK_CNTL,
|
||||
HDMISTREAMCLK0_EN, 1, /* selects one of the dtbclk_p as per HDMISTREAMCLK0_SRC_SEL */
|
||||
HDMISTREAMCLK0_SRC_SEL, otg_inst, /* Selects dtbclk_p as source for hdmistreamclk */
|
||||
HDMISTREAMCLK0_DTO_FORCE_DIS, 1); /* DTO_FORCE_BYPASS */
|
||||
}
|
||||
}
|
||||
|
||||
static void dccg314_init(struct dccg *dccg)
|
||||
{
|
||||
int otg_inst;
|
||||
@@ -355,6 +377,9 @@ static void dccg314_dpp_root_clock_control(
|
||||
}
|
||||
|
||||
static const struct dccg_funcs dccg314_funcs = {
|
||||
.enable_hdmicharclk = dccg31_enable_hdmicharclk,
|
||||
.disable_hdmicharclk = dccg31_disable_hdmicharclk,
|
||||
.set_hdmistreamclk = dccg314_set_hdmistreamclk,
|
||||
.update_dpp_dto = dccg31_update_dpp_dto,
|
||||
.dpp_root_clock_control = dccg314_dpp_root_clock_control,
|
||||
.get_dccg_ref_freq = dccg31_get_dccg_ref_freq,
|
||||
|
||||
@@ -329,7 +329,75 @@ static void dccg32_otg_drop_pixel(struct dccg *dccg,
|
||||
OTG_DROP_PIXEL[otg_inst], 1);
|
||||
}
|
||||
|
||||
static void dccg32_set_hdmistreamclk(struct dccg *dccg,
|
||||
enum streamclk_source src,
|
||||
uint32_t otg_inst)
|
||||
{
|
||||
struct dcn_dccg *dccg_dcn = TO_DCN_DCCG(dccg);
|
||||
|
||||
/* set the dtbclk_p source */
|
||||
/* always program refclk as DTBCLK. No use-case expected to require DPREFCLK as refclk */
|
||||
dccg32_set_dtbclk_p_src(dccg, DTBCLK0, otg_inst);
|
||||
|
||||
if (src == REFCLK) {
|
||||
REG_UPDATE_2(HDMISTREAMCLK_CNTL,
|
||||
HDMISTREAMCLK0_EN, 0, /* SEL_REFCLK */
|
||||
HDMISTREAMCLK0_DTO_FORCE_DIS, 1); /* DTO_FORCE_BYPASS */
|
||||
} else {
|
||||
REG_UPDATE_3(HDMISTREAMCLK_CNTL,
|
||||
HDMISTREAMCLK0_EN, 1, /* selects one of the dtbclk_p as per HDMISTREAMCLK0_SRC_SEL */
|
||||
HDMISTREAMCLK0_SRC_SEL, otg_inst, /* Selects dtbclk_p as source for hdmistreamclk */
|
||||
HDMISTREAMCLK0_DTO_FORCE_DIS, 1); /* DTO_FORCE_BYPASS */
|
||||
}
|
||||
}
|
||||
|
||||
static void dccg32_enable_hdmicharclk(struct dccg *dccg, int hpo_inst,
|
||||
int phypll_inst)
|
||||
{
|
||||
struct dcn_dccg *dccg_dcn = TO_DCN_DCCG(dccg);
|
||||
|
||||
ASSERT(hpo_inst >= 0 && phypll_inst >= 0);
|
||||
REG_UPDATE_2(HDMICHARCLK_CLOCK_CNTL[hpo_inst],
|
||||
HDMICHARCLK0_EN, 1,
|
||||
HDMICHARCLK0_SRC_SEL, phypll_inst);
|
||||
|
||||
/* Enable FORCE_EN for SYMCLK */
|
||||
switch (phypll_inst) {
|
||||
case 0:
|
||||
REG_UPDATE_2(PHYASYMCLK_CLOCK_CNTL,
|
||||
PHYASYMCLK_FORCE_EN, 1,
|
||||
PHYASYMCLK_FORCE_SRC_SEL, 1);
|
||||
break;
|
||||
case 1:
|
||||
REG_UPDATE_2(PHYBSYMCLK_CLOCK_CNTL,
|
||||
PHYBSYMCLK_FORCE_EN, 1,
|
||||
PHYBSYMCLK_FORCE_SRC_SEL, 1);
|
||||
break;
|
||||
case 2:
|
||||
REG_UPDATE_2(PHYCSYMCLK_CLOCK_CNTL,
|
||||
PHYCSYMCLK_FORCE_EN, 1,
|
||||
PHYCSYMCLK_FORCE_SRC_SEL, 1);
|
||||
break;
|
||||
case 3:
|
||||
REG_UPDATE_2(PHYDSYMCLK_CLOCK_CNTL,
|
||||
PHYDSYMCLK_FORCE_EN, 1,
|
||||
PHYDSYMCLK_FORCE_SRC_SEL, 1);
|
||||
break;
|
||||
case 4:
|
||||
REG_UPDATE_2(PHYESYMCLK_CLOCK_CNTL,
|
||||
PHYESYMCLK_FORCE_EN, 1,
|
||||
PHYESYMCLK_FORCE_SRC_SEL, 1);
|
||||
break;
|
||||
default:
|
||||
BREAK_TO_DEBUGGER();
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
static const struct dccg_funcs dccg32_funcs = {
|
||||
.enable_hdmicharclk = dccg32_enable_hdmicharclk,
|
||||
.disable_hdmicharclk = dccg3_disable_hdmicharclk,
|
||||
.set_hdmistreamclk = dccg32_set_hdmistreamclk,
|
||||
.update_dpp_dto = dccg2_update_dpp_dto,
|
||||
.get_dccg_ref_freq = dccg32_get_dccg_ref_freq,
|
||||
.dccg_init = dccg31_init,
|
||||
|
||||
@@ -495,6 +495,92 @@ static void dccg35_set_smclk32_se_rcg(
|
||||
}
|
||||
}
|
||||
|
||||
static void dccg35_set_hdmistreamclk_rcg(
|
||||
struct dccg *dccg,
|
||||
int inst,
|
||||
bool enable)
|
||||
{
|
||||
struct dcn_dccg *dccg_dcn = TO_DCN_DCCG(dccg);
|
||||
|
||||
if (!dccg->ctx->dc->debug.root_clock_optimization.bits.hdmistream && enable)
|
||||
return;
|
||||
|
||||
switch (inst) {
|
||||
case 0:
|
||||
REG_UPDATE(DCCG_GATE_DISABLE_CNTL3, HDMISTREAMCLK0_GATE_DISABLE, enable ? 0 : 1);
|
||||
REG_UPDATE(DCCG_GATE_DISABLE_CNTL6, HDMISTREAMCLK0_ROOT_GATE_DISABLE, enable ? 0 : 1);
|
||||
break;
|
||||
default:
|
||||
BREAK_TO_DEBUGGER();
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
static void dccg35_set_hdmi_char_clk_rcg(
|
||||
struct dccg *dccg,
|
||||
int inst,
|
||||
bool enable)
|
||||
{
|
||||
struct dcn_dccg *dccg_dcn = TO_DCN_DCCG(dccg);
|
||||
|
||||
/* Only 1 HPO in DCN35 */
|
||||
if (!dccg->ctx->dc->debug.root_clock_optimization.bits.hdmichar && enable)
|
||||
return;
|
||||
|
||||
switch (inst) {
|
||||
case 0:
|
||||
REG_UPDATE(DCCG_GATE_DISABLE_CNTL2, HDMICHARCLK0_GATE_DISABLE, enable ? 0 : 1);
|
||||
REG_UPDATE(DCCG_GATE_DISABLE_CNTL4, HDMICHARCLK0_ROOT_GATE_DISABLE, enable ? 0 : 1);
|
||||
break;
|
||||
default:
|
||||
BREAK_TO_DEBUGGER();
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
static void dccg35_set_hdmi_char_clk_src_new(
|
||||
struct dccg *dccg,
|
||||
enum hdmi_char_clk src,
|
||||
int inst)
|
||||
{
|
||||
struct dcn_dccg *dccg_dcn = TO_DCN_DCCG(dccg);
|
||||
|
||||
/* If DTBCLK_P#_EN is 0 refclock is selected as functional clock
|
||||
* If DTBCLK_P#_EN is 1 functional clock is selected as DTBCLK_P#_SRC_SEL
|
||||
*/
|
||||
|
||||
switch (inst) {
|
||||
case 0:
|
||||
REG_UPDATE_2(HDMICHARCLK_CLOCK_CNTL[0],
|
||||
HDMICHARCLK0_SRC_SEL, (src == HDMI_CHAR_REFCLK) ? 0 : src,
|
||||
HDMICHARCLK0_EN, (src == HDMI_CHAR_REFCLK) ? 0 : 1);
|
||||
break;
|
||||
default:
|
||||
BREAK_TO_DEBUGGER();
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
static void dccg35_set_hdmistreamclk_src_new(
|
||||
struct dccg *dccg,
|
||||
enum hdmi_stream_clk_source src,
|
||||
int inst)
|
||||
{
|
||||
struct dcn_dccg *dccg_dcn = TO_DCN_DCCG(dccg);
|
||||
|
||||
switch (inst) {
|
||||
case 0:
|
||||
REG_UPDATE_2(HDMISTREAMCLK_CNTL, HDMISTREAMCLK0_EN,
|
||||
(src == HDMI_STREAM_REFCLK) ? 0 : 1,
|
||||
DPSTREAMCLK0_SRC_SEL,
|
||||
(src == HDMI_STREAM_REFCLK) ? 0 : src);
|
||||
break;
|
||||
default:
|
||||
BREAK_TO_DEBUGGER();
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
static void dccg35_set_dsc_clk_src_new(struct dccg *dccg, int inst, enum dsc_clk_source src)
|
||||
{
|
||||
struct dcn_dccg *dccg_dcn = TO_DCN_DCCG(dccg);
|
||||
@@ -1107,6 +1193,35 @@ static void dccg35_enable_dpstreamclk_new(struct dccg *dccg,
|
||||
dccg35_set_dpstreamclk_src_new(dccg, src, inst);
|
||||
}
|
||||
|
||||
static void dccg35_disable_hdmistreamclk_new(
|
||||
struct dccg *dccg,
|
||||
int inst)
|
||||
{
|
||||
dccg35_set_hdmistreamclk_src_new(dccg, HDMI_STREAM_REFCLK, inst);
|
||||
dccg35_set_hdmistreamclk_rcg(dccg, inst, true);
|
||||
}
|
||||
|
||||
static void dccg35_enable_hdmistreamclk_new(struct dccg *dccg,
|
||||
enum hdmi_stream_clk_source src,
|
||||
int inst)
|
||||
{
|
||||
dccg35_set_hdmistreamclk_rcg(dccg, inst, false);
|
||||
dccg35_set_hdmistreamclk_src_new(dccg, src, inst);
|
||||
}
|
||||
|
||||
static void dccg35_enable_hdmicharclk_new(struct dccg *dccg, enum hdmi_char_clk src,
|
||||
int inst)
|
||||
{
|
||||
dccg35_set_hdmi_char_clk_rcg(dccg, inst, false);
|
||||
dccg35_set_hdmi_char_clk_src_new(dccg, src, inst);
|
||||
}
|
||||
|
||||
static void dccg35_disable_hdmicharclk_new(struct dccg *dccg, int inst)
|
||||
{
|
||||
dccg35_set_hdmi_char_clk_src_new(dccg, HDMI_CHAR_REFCLK, inst);
|
||||
dccg35_set_hdmi_char_clk_rcg(dccg, inst, true);
|
||||
}
|
||||
|
||||
void dccg35_trigger_dio_fifo_resync(struct dccg *dccg)
|
||||
{
|
||||
struct dcn_dccg *dccg_dcn = TO_DCN_DCCG(dccg);
|
||||
@@ -1539,6 +1654,88 @@ void dccg35_set_dpstreamclk_root_clock_gating(struct dccg *dccg, int dp_hpo_inst
|
||||
|
||||
|
||||
|
||||
static void dccg35_set_hdmistreamclk(
|
||||
struct dccg *dccg,
|
||||
enum streamclk_source src,
|
||||
uint32_t otg_inst)
|
||||
{
|
||||
struct dcn_dccg *dccg_dcn = TO_DCN_DCCG(dccg);
|
||||
|
||||
/* set the dtbclk_p source */
|
||||
dccg35_set_dtbclk_p_src(dccg, src, otg_inst);
|
||||
|
||||
if (src == REFCLK) {
|
||||
REG_UPDATE(HDMISTREAMCLK_CNTL,
|
||||
HDMISTREAMCLK0_EN, 0); /* SEL_REFCLK */
|
||||
} else {
|
||||
REG_UPDATE_2(HDMISTREAMCLK_CNTL,
|
||||
HDMISTREAMCLK0_EN, 1, /* selects one of the dtbclk_p as per HDMISTREAMCLK0_SRC_SEL */
|
||||
HDMISTREAMCLK0_SRC_SEL, otg_inst); /* Selects dtbclk_p as source for hdmistreamclk */
|
||||
}
|
||||
DC_LOG_DEBUG("%s: OTG%d HDMISTREAMCLK_EN = %d, HDMISTREAMCLK_SRC_SEL = %d\n",
|
||||
__func__, otg_inst, (src == REFCLK) ? 0 : 1, otg_inst);
|
||||
}
|
||||
|
||||
void dccg35_set_hdmistreamclk_root_clock_gating(struct dccg *dccg, bool enable)
|
||||
{
|
||||
struct dcn_dccg *dccg_dcn = TO_DCN_DCCG(dccg);
|
||||
|
||||
if (dccg->ctx->dc->debug.root_clock_optimization.bits.hdmistream)
|
||||
REG_UPDATE(DCCG_GATE_DISABLE_CNTL6, HDMISTREAMCLK0_ROOT_GATE_DISABLE, enable ? 1 : 0);
|
||||
|
||||
DC_LOG_DEBUG("%s: HDMISTREAMCLK0_ROOT_GATE_DISABLE = %d\n", __func__, enable ? 1 : 0);
|
||||
}
|
||||
|
||||
static void dccg35_enable_hdmicharclk(struct dccg *dccg, int hpo_inst,
|
||||
int phypll_inst)
|
||||
{
|
||||
struct dcn_dccg *dccg_dcn = TO_DCN_DCCG(dccg);
|
||||
|
||||
if (dccg->ctx->dc->debug.root_clock_optimization.bits.hdmichar) {
|
||||
REG_UPDATE(DCCG_GATE_DISABLE_CNTL4,
|
||||
HDMICHARCLK0_ROOT_GATE_DISABLE, 1);
|
||||
REG_UPDATE(DCCG_GATE_DISABLE_CNTL2,
|
||||
HDMICHARCLK0_GATE_DISABLE, 1);
|
||||
}
|
||||
|
||||
ASSERT(hpo_inst >= 0 && phypll_inst >= 0);
|
||||
REG_UPDATE_2(HDMICHARCLK_CLOCK_CNTL[hpo_inst],
|
||||
HDMICHARCLK0_EN, 1,
|
||||
HDMICHARCLK0_SRC_SEL, phypll_inst);
|
||||
|
||||
/* Enable FORCE_EN for SYMCLK */
|
||||
switch (phypll_inst) {
|
||||
case 0:
|
||||
REG_UPDATE_2(PHYASYMCLK_CLOCK_CNTL,
|
||||
PHYASYMCLK_EN, 1,
|
||||
PHYASYMCLK_SRC_SEL, 1);
|
||||
break;
|
||||
case 1:
|
||||
REG_UPDATE_2(PHYBSYMCLK_CLOCK_CNTL,
|
||||
PHYBSYMCLK_EN, 1,
|
||||
PHYBSYMCLK_SRC_SEL, 1);
|
||||
break;
|
||||
case 2:
|
||||
REG_UPDATE_2(PHYCSYMCLK_CLOCK_CNTL,
|
||||
PHYCSYMCLK_EN, 1,
|
||||
PHYCSYMCLK_SRC_SEL, 1);
|
||||
break;
|
||||
case 3:
|
||||
REG_UPDATE_2(PHYDSYMCLK_CLOCK_CNTL,
|
||||
PHYDSYMCLK_EN, 1,
|
||||
PHYDSYMCLK_SRC_SEL, 1);
|
||||
break;
|
||||
case 4:
|
||||
REG_UPDATE_2(PHYESYMCLK_CLOCK_CNTL,
|
||||
PHYESYMCLK_EN, 1,
|
||||
PHYESYMCLK_SRC_SEL, 1);
|
||||
break;
|
||||
default:
|
||||
BREAK_TO_DEBUGGER();
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
static void dccg35_set_physymclk_root_clock_gating(
|
||||
struct dccg *dccg,
|
||||
int phy_inst,
|
||||
@@ -1756,6 +1953,33 @@ void dccg35_disable_symclk32_se(struct dccg *dccg, int hpo_se_inst)
|
||||
|
||||
}
|
||||
|
||||
static void dccg35_disable_hdmistreamclk(struct dccg *dccg)
|
||||
{
|
||||
struct dcn_dccg *dccg_dcn = TO_DCN_DCCG(dccg);
|
||||
|
||||
if (dccg->ctx->dc->debug.root_clock_optimization.bits.hdmistream) {
|
||||
// REG_UPDATE_2(HDMISTREAMCLK0_DTO_PARAM,
|
||||
// HDMISTREAMCLK0_DTO_PHASE, 0,
|
||||
// HDMISTREAMCLK0_DTO_MODULO, 1);
|
||||
REG_UPDATE(DCCG_GATE_DISABLE_CNTL6, HDMISTREAMCLK0_ROOT_GATE_DISABLE, 0);
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
static void dccg35_disable_hdmicharclk(struct dccg *dccg, int hpo_inst)
|
||||
{
|
||||
struct dcn_dccg *dccg_dcn = TO_DCN_DCCG(dccg);
|
||||
|
||||
REG_WRITE(HDMICHARCLK_CLOCK_CNTL[hpo_inst], 0);
|
||||
if (dccg->ctx->dc->debug.root_clock_optimization.bits.hdmichar) {
|
||||
REG_UPDATE(DCCG_GATE_DISABLE_CNTL2,
|
||||
HDMICHARCLK0_GATE_DISABLE, 0);
|
||||
REG_UPDATE(DCCG_GATE_DISABLE_CNTL4,
|
||||
HDMICHARCLK0_ROOT_GATE_DISABLE, 0);
|
||||
DC_LOG_DEBUG("%s: HDMICHARCLK0_ROOT_GATE_DISABLE = 0\n", __func__);
|
||||
}
|
||||
}
|
||||
|
||||
static void dccg35_init_cb(struct dccg *dccg)
|
||||
{
|
||||
(void)dccg;
|
||||
@@ -1793,6 +2017,9 @@ void dccg35_init(struct dccg *dccg)
|
||||
__func__, otg_inst);
|
||||
}
|
||||
|
||||
dccg35_disable_hdmistreamclk(dccg);
|
||||
if (dccg->ctx->dc->debug.root_clock_optimization.bits.hdmichar)
|
||||
dccg35_disable_hdmicharclk(dccg, 0);
|
||||
/*
|
||||
dccg35_enable_global_fgcg_rep(
|
||||
dccg, dccg->ctx->dc->debug.enable_fine_grain_clock_gating.bits
|
||||
@@ -2088,6 +2315,92 @@ void dccg35_disable_symclk_se(struct dccg *dccg, uint32_t stream_enc_inst, uint3
|
||||
}
|
||||
}
|
||||
|
||||
static void dccg35_enable_hdmicharclk_cb(struct dccg *dccg, int hpo_inst, int phypll_inst)
|
||||
{
|
||||
ASSERT(hpo_inst >= 0 && phypll_inst >= 0);
|
||||
|
||||
/* Note that this is now done in DMU as part of phy fsm enable sequence,
|
||||
* this function does not get called on x86
|
||||
*/
|
||||
enum hdmi_char_clk src = (enum hdmi_char_clk) phypll_inst;
|
||||
|
||||
dccg35_enable_hdmicharclk_new(dccg, src, hpo_inst);
|
||||
|
||||
/* Select PHYD18 as final SYMCLK going to the PHY from DCCG */
|
||||
dccg35_set_physymclk_src_new(dccg, phypll_inst, PHYSYMCLK_PHYD18CLK);
|
||||
}
|
||||
|
||||
static void dccg35_disable_hdmicharclk_cb(struct dccg *dccg, int hpo_inst)
|
||||
{
|
||||
ASSERT(hpo_inst >= 0);
|
||||
|
||||
/* Note that this is now done in DMU as part of phy fsm disable sequence,
|
||||
* this function does not get called on x86
|
||||
*/
|
||||
dccg35_disable_hdmicharclk_new(dccg, hpo_inst);
|
||||
|
||||
/* TBD Optionally check if SYMCLK is active and disable it */
|
||||
}
|
||||
|
||||
static void dccg35_set_hdmistreamclk_cb(
|
||||
struct dccg *dccg,
|
||||
enum streamclk_source src,
|
||||
uint32_t otg_inst)
|
||||
{
|
||||
enum dtbclk_source dtb_clk_src;
|
||||
enum hdmi_stream_clk_source hdmi_stream_clk_src;
|
||||
|
||||
switch (src) {
|
||||
case REFCLK:
|
||||
dtb_clk_src = DTBCLK_REFCLK;
|
||||
hdmi_stream_clk_src = HDMI_STREAM_REFCLK;
|
||||
break;
|
||||
case DPREFCLK:
|
||||
dtb_clk_src = DTBCLK_DPREFCLK;
|
||||
hdmi_stream_clk_src = (enum hdmi_stream_clk_source)otg_inst;
|
||||
break;
|
||||
case DTBCLK0:
|
||||
dtb_clk_src = DTBCLK_DTBCLK0;
|
||||
hdmi_stream_clk_src = (enum hdmi_stream_clk_source)otg_inst;
|
||||
break;
|
||||
default:
|
||||
BREAK_TO_DEBUGGER();
|
||||
return;
|
||||
}
|
||||
|
||||
if (dtb_clk_src == DTBCLK_REFCLK &&
|
||||
hdmi_stream_clk_src == HDMI_STREAM_REFCLK) {
|
||||
dccg35_disable_dtbclk_p_new(dccg, otg_inst);
|
||||
dccg35_disable_hdmistreamclk_new(dccg, 0);
|
||||
} else {
|
||||
dccg35_enable_dtbclk_p_new(dccg, dtb_clk_src, otg_inst);
|
||||
dccg35_enable_hdmistreamclk_new(dccg,
|
||||
hdmi_stream_clk_src,
|
||||
0);
|
||||
}
|
||||
}
|
||||
|
||||
static void dccg35_set_hdmistreamclk_root_clock_gating_cb(
|
||||
struct dccg *dccg,
|
||||
bool power_on)
|
||||
{
|
||||
/* power_on set indicates we need to ungate
|
||||
* Currently called from optimize_bandwidth and prepare_bandwidth calls
|
||||
* Since clock source is not passed restore to refclock on ungate
|
||||
* Instance 0 is implied here since only one streamclock resource
|
||||
* Redundant as gating when enabled is acheived through set_hdmistreamclk
|
||||
*/
|
||||
if (power_on) {
|
||||
dccg35_enable_hdmicharclk_new(dccg, HDMI_CHAR_REFCLK, 0);
|
||||
dccg35_enable_hdmistreamclk_new(dccg,
|
||||
HDMI_STREAM_REFCLK,
|
||||
0);
|
||||
} else {
|
||||
dccg35_disable_hdmistreamclk_new(dccg, 0);
|
||||
dccg35_disable_hdmicharclk_new(dccg, 0);
|
||||
}
|
||||
}
|
||||
|
||||
static void dccg35_set_dpstreamclk_cb(
|
||||
struct dccg *dccg,
|
||||
enum streamclk_source src,
|
||||
@@ -2386,6 +2699,10 @@ void dccg35_root_gate_disable_control(struct dccg *dccg, uint32_t pipe_idx, uint
|
||||
}
|
||||
|
||||
static const struct dccg_funcs dccg35_funcs_new = {
|
||||
.enable_hdmicharclk = dccg35_enable_hdmicharclk_cb,
|
||||
.disable_hdmicharclk = dccg35_disable_hdmicharclk_cb,
|
||||
.set_hdmistreamclk = dccg35_set_hdmistreamclk_cb,
|
||||
.set_hdmistreamclk_root_clock_gating = dccg35_set_hdmistreamclk_root_clock_gating_cb,
|
||||
.update_dpp_dto = dccg35_update_dpp_dto_cb,
|
||||
.dpp_root_clock_control = dccg35_dpp_root_clock_control_cb,
|
||||
.get_dccg_ref_freq = dccg31_get_dccg_ref_freq,
|
||||
@@ -2421,6 +2738,10 @@ static const struct dccg_funcs dccg35_funcs_new = {
|
||||
};
|
||||
|
||||
static const struct dccg_funcs dccg35_funcs = {
|
||||
.enable_hdmicharclk = dccg35_enable_hdmicharclk,
|
||||
.disable_hdmicharclk = dccg35_disable_hdmicharclk,
|
||||
.set_hdmistreamclk = dccg35_set_hdmistreamclk,
|
||||
.set_hdmistreamclk_root_clock_gating = dccg35_set_hdmistreamclk_root_clock_gating,
|
||||
.update_dpp_dto = dccg35_update_dpp_dto,
|
||||
.dpp_root_clock_control = dccg35_dpp_root_clock_control,
|
||||
.get_dccg_ref_freq = dccg31_get_dccg_ref_freq,
|
||||
|
||||
@@ -381,6 +381,72 @@ static void dccg401_otg_drop_pixel(struct dccg *dccg,
|
||||
OTG_DROP_PIXEL[otg_inst], 1);
|
||||
}
|
||||
|
||||
void dccg401_set_hdmistreamclk(
|
||||
struct dccg *dccg,
|
||||
enum streamclk_source src,
|
||||
uint32_t otg_inst)
|
||||
{
|
||||
struct dcn_dccg *dccg_dcn = TO_DCN_DCCG(dccg);
|
||||
|
||||
if (src == REFCLK) {
|
||||
REG_UPDATE(HDMISTREAMCLK_CNTL,
|
||||
HDMISTREAMCLK0_EN, 0); /* SEL_REFCLK */
|
||||
} else {
|
||||
REG_UPDATE_2(HDMISTREAMCLK_CNTL,
|
||||
HDMISTREAMCLK0_EN, 1, /* selects one of the dtbclk_p as per HDMISTREAMCLK0_SRC_SEL */
|
||||
HDMISTREAMCLK0_SRC_SEL, otg_inst); /* Selects dtbclk_p as source for hdmistreamclk */
|
||||
}
|
||||
}
|
||||
|
||||
void dccg401_enable_hdmicharclk(struct dccg *dccg, int hpo_inst, int phypll_inst)
|
||||
{
|
||||
struct dcn_dccg *dccg_dcn = TO_DCN_DCCG(dccg);
|
||||
|
||||
ASSERT(hpo_inst >= 0 && phypll_inst >= 0);
|
||||
if (dccg->ctx->dc->debug.root_clock_optimization.bits.hdmichar) {
|
||||
REG_UPDATE(DCCG_GATE_DISABLE_CNTL4,
|
||||
HDMICHARCLK0_ROOT_GATE_DISABLE, 1);
|
||||
REG_UPDATE(DCCG_GATE_DISABLE_CNTL2,
|
||||
HDMICHARCLK0_GATE_DISABLE, 1);
|
||||
}
|
||||
|
||||
REG_UPDATE_2(HDMICHARCLK_CLOCK_CNTL[hpo_inst],
|
||||
HDMICHARCLK0_EN, 1,
|
||||
HDMICHARCLK0_SRC_SEL, phypll_inst);
|
||||
|
||||
/* Enable FORCE_EN for SYMCLK */
|
||||
dccg401_set_physymclk(dccg, phypll_inst, PHYSYMCLK_FORCE_SRC_PHYD18CLK, true);
|
||||
}
|
||||
|
||||
void dccg401_disable_hdmicharclk(struct dccg *dccg, int hpo_inst)
|
||||
{
|
||||
struct dcn_dccg *dccg_dcn = TO_DCN_DCCG(dccg);
|
||||
//int phypll_inst = 0;
|
||||
|
||||
ASSERT(hpo_inst >= 0);
|
||||
//REG_GET(dccg, HDMICHARCLK_CLOCK_CNTL[hpo_inst], HDMICHARCLK0_SRC_SEL, &phypll_inst);
|
||||
REG_WRITE(HDMICHARCLK_CLOCK_CNTL[hpo_inst], 0);
|
||||
|
||||
/* TODO should we also disable physymclk? */
|
||||
/* Disable FORCE_EN for SYMCLK */
|
||||
//dccg401_set_physymclk(dccg, phypll_inst, PHYSYMCLK_FORCE_SRC_PHYD18CLK, true);
|
||||
|
||||
if (dccg->ctx->dc->debug.root_clock_optimization.bits.hdmichar) {
|
||||
REG_UPDATE(DCCG_GATE_DISABLE_CNTL2,
|
||||
HDMICHARCLK0_GATE_DISABLE, 0);
|
||||
REG_UPDATE(DCCG_GATE_DISABLE_CNTL4,
|
||||
HDMICHARCLK0_ROOT_GATE_DISABLE, 0);
|
||||
}
|
||||
}
|
||||
|
||||
static void dccg401_disable_hdmistreamclk(struct dccg *dccg)
|
||||
{
|
||||
struct dcn_dccg *dccg_dcn = TO_DCN_DCCG(dccg);
|
||||
|
||||
REG_UPDATE_2(HDMISTREAMCLK_CNTL,
|
||||
HDMISTREAMCLK0_EN, 0,
|
||||
HDMISTREAMCLK0_SRC_SEL, 0);
|
||||
}
|
||||
void dccg401_enable_symclk32_le(
|
||||
struct dccg *dccg,
|
||||
int hpo_le_inst,
|
||||
@@ -721,6 +787,10 @@ void dccg401_init(struct dccg *dccg)
|
||||
dccg401_set_physymclk(dccg, 2, PHYSYMCLK_FORCE_SRC_SYMCLK, false);
|
||||
dccg401_set_physymclk(dccg, 3, PHYSYMCLK_FORCE_SRC_SYMCLK, false);
|
||||
}
|
||||
dccg401_disable_hdmistreamclk(dccg);
|
||||
|
||||
if (dccg->ctx->dc->debug.root_clock_optimization.bits.hdmichar)
|
||||
dccg401_disable_hdmicharclk(dccg, 0);
|
||||
}
|
||||
|
||||
void dccg401_set_dto_dscclk(struct dccg *dccg, uint32_t inst, uint32_t num_slices_h)
|
||||
@@ -881,6 +951,9 @@ void dccg401_disable_symclk_se(struct dccg *dccg, uint32_t stream_enc_inst, uint
|
||||
}
|
||||
|
||||
static const struct dccg_funcs dccg401_funcs = {
|
||||
.enable_hdmicharclk = dccg401_enable_hdmicharclk,
|
||||
.disable_hdmicharclk = dccg401_disable_hdmicharclk,
|
||||
.set_hdmistreamclk = dccg401_set_hdmistreamclk,
|
||||
.update_dpp_dto = dccg401_update_dpp_dto,
|
||||
.get_dccg_ref_freq = dccg401_get_dccg_ref_freq,
|
||||
.dccg_init = dccg401_init,
|
||||
|
||||
@@ -246,4 +246,8 @@ void dccg401_set_physymclk(
|
||||
enum physymclk_clock_source clk_src,
|
||||
bool force_enable);
|
||||
|
||||
void dccg401_set_hdmistreamclk(struct dccg *dccg, enum streamclk_source src, uint32_t otg_inst);
|
||||
void dccg401_enable_hdmicharclk(struct dccg *dccg, int hpo_inst, int phypll_inst);
|
||||
void dccg401_disable_hdmicharclk(struct dccg *dccg, int hpo_inst);
|
||||
|
||||
#endif //__DCN401_DCCG_H__
|
||||
|
||||
@@ -181,6 +181,32 @@ void dccg42_set_physymclk(
|
||||
}
|
||||
}
|
||||
|
||||
static void dccg42_disable_hdmistreamclk(struct dccg *dccg)
|
||||
{
|
||||
struct dcn_dccg *dccg_dcn = TO_DCN_DCCG(dccg);
|
||||
|
||||
REG_UPDATE_2(HDMISTREAMCLK_CNTL,
|
||||
HDMISTREAMCLK0_EN, 0,
|
||||
HDMISTREAMCLK0_SRC_SEL, 0);
|
||||
|
||||
REG_UPDATE(DCCG_GATE_DISABLE_CNTL6,
|
||||
HDMISTREAMCLK0_ROOT_GATE_DISABLE,
|
||||
dccg->ctx->dc->debug.root_clock_optimization.bits.hdmistream ? 0 : 1);
|
||||
}
|
||||
|
||||
static void dccg42_disable_hdmicharclk(struct dccg *dccg, int hpo_inst)
|
||||
{
|
||||
struct dcn_dccg *dccg_dcn = TO_DCN_DCCG(dccg);
|
||||
|
||||
ASSERT(hpo_inst >= 0);
|
||||
REG_WRITE(HDMICHARCLK_CLOCK_CNTL[hpo_inst], 0);
|
||||
|
||||
REG_UPDATE(DCCG_GATE_DISABLE_CNTL2,
|
||||
HDMICHARCLK0_GATE_DISABLE, 0);
|
||||
REG_UPDATE(DCCG_GATE_DISABLE_CNTL4,
|
||||
HDMICHARCLK0_ROOT_GATE_DISABLE, dccg->ctx->dc->debug.root_clock_optimization.bits.hdmichar ? 0 : 1);
|
||||
}
|
||||
|
||||
void dccg42_set_pixel_rate_div(
|
||||
struct dccg *dccg,
|
||||
uint32_t otg_inst,
|
||||
@@ -270,10 +296,17 @@ static void dccg42_init(struct dccg *dccg)
|
||||
PHYDSYMCLK_ROOT_GATE_DISABLE, 1,
|
||||
PHYESYMCLK_ROOT_GATE_DISABLE, 1);
|
||||
}
|
||||
dccg42_disable_hdmistreamclk(dccg);
|
||||
if (dccg->ctx->dc->debug.root_clock_optimization.bits.hdmichar)
|
||||
dccg42_disable_hdmicharclk(dccg, 0);
|
||||
}
|
||||
|
||||
|
||||
static const struct dccg_funcs dccg42_funcs = {
|
||||
.enable_hdmicharclk = dccg401_enable_hdmicharclk,
|
||||
.disable_hdmicharclk = dccg42_disable_hdmicharclk,
|
||||
.set_hdmistreamclk = dccg401_set_hdmistreamclk,
|
||||
.set_hdmistreamclk_root_clock_gating = dccg35_set_hdmistreamclk_root_clock_gating,
|
||||
.update_dpp_dto = dccg35_update_dpp_dto,
|
||||
.dpp_root_clock_control = dccg35_dpp_root_clock_control,
|
||||
.get_dccg_ref_freq = dccg401_get_dccg_ref_freq,
|
||||
|
||||
@@ -1066,7 +1066,8 @@ void dcn10_link_encoder_disable_output(
|
||||
struct bp_transmitter_control cntl = { 0 };
|
||||
enum bp_result result;
|
||||
|
||||
if (enc->funcs->is_dig_enabled && !enc->funcs->is_dig_enabled(enc)) {
|
||||
if (!dc_is_hdmi_frl_signal(signal) &&
|
||||
(enc->funcs->is_dig_enabled && !enc->funcs->is_dig_enabled(enc))) {
|
||||
/* OF_SKIP_POWER_DOWN_INACTIVE_ENCODER */
|
||||
/*in DP_Alt_No_Connect case, we turn off the dig already,
|
||||
after excuation the PHY w/a sequence, not allow touch PHY any more*/
|
||||
|
||||
@@ -291,6 +291,7 @@ struct dpcssys_phy_seq_cfg {
|
||||
bool use_calibration_setting;
|
||||
struct mpll_cfg mpll_cfg;
|
||||
bool load_sram_fw;
|
||||
bool tx_hdmi_frl_mode;
|
||||
#if 0
|
||||
|
||||
bool hdmimode_enable;
|
||||
|
||||
@@ -48,11 +48,240 @@
|
||||
(enc10->link_regs->index)
|
||||
|
||||
|
||||
static bool dcn30_link_encoder_validate_hdmi_frl_output(
|
||||
const struct dcn10_link_encoder *enc10,
|
||||
const struct dc_crtc_timing *crtc_timing)
|
||||
{
|
||||
enum dc_color_depth max_deep_color =
|
||||
enc10->base.features.max_hdmi_deep_color;
|
||||
|
||||
if (!enc10->base.features.flags.bits.IS_HDMI_FRL_CAPABLE)
|
||||
return false;
|
||||
|
||||
if (max_deep_color < crtc_timing->display_color_depth)
|
||||
return false;
|
||||
|
||||
if (crtc_timing->display_color_depth < COLOR_DEPTH_888)
|
||||
return false;
|
||||
|
||||
/* TODO: check if hdmi_charclk is above ASIC cap (10 GBS for DCN3AG) */
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool dcn30_link_encoder_validate_output_with_stream(
|
||||
struct link_encoder *enc,
|
||||
const struct dc_stream_state *stream)
|
||||
{
|
||||
if (dc_is_hdmi_frl_signal(stream->signal)) {
|
||||
struct dcn10_link_encoder *enc10 = TO_DCN10_LINK_ENC(enc);
|
||||
|
||||
return dcn30_link_encoder_validate_hdmi_frl_output(enc10, &stream->timing);
|
||||
} else {
|
||||
return dcn10_link_encoder_validate_output_with_stream(enc, stream);
|
||||
}
|
||||
}
|
||||
|
||||
//---------------------------------------------------
|
||||
// Task: Program EQ setting
|
||||
// Note:
|
||||
// EQ setting can be dont during P2 state or P0 state
|
||||
// If set in P0 state, The values are latched in a single
|
||||
// cycle of txX_clk but will take maximum of 40 txX_clk symbols
|
||||
// to be reflected on the output. During this period the
|
||||
// analog serial lines might have a transitional behavior.
|
||||
//---------------------------------------------------
|
||||
void dpcs30_program_eq_setting(
|
||||
struct link_encoder *enc,
|
||||
uint8_t FFE_Level,
|
||||
bool de_emphasis_only,
|
||||
bool pre_shoot_only,
|
||||
bool no_ffe,
|
||||
const struct dc_hdmi_frl_link_settings *link_settings)
|
||||
{
|
||||
(void)link_settings;
|
||||
struct dcn10_link_encoder *enc10 = TO_DCN10_LINK_ENC(enc);
|
||||
/* EQ setting for DP lane0 */
|
||||
uint32_t eq_main;
|
||||
uint32_t eq_pre;
|
||||
uint32_t eq_post;
|
||||
|
||||
if (enc10->base.ctx->dc->debug.ignore_ffe)
|
||||
return;
|
||||
|
||||
if (FFE_Level < 0x5)
|
||||
enc10->base.txffe_state = FFE_Level;
|
||||
|
||||
if (FFE_Level == 0xEE) {
|
||||
enc10->base.txffe_state++;
|
||||
if (enc10->base.txffe_state > 3)
|
||||
enc10->base.txffe_state = 0;
|
||||
}
|
||||
|
||||
switch (enc10->base.txffe_state) {
|
||||
case 0:
|
||||
eq_main = 0x31;
|
||||
if (de_emphasis_only)
|
||||
eq_main = 0x36;
|
||||
if (pre_shoot_only)
|
||||
eq_main = 0x39;
|
||||
eq_pre = 0x5;
|
||||
eq_post = 0x8;
|
||||
break;
|
||||
case 1:
|
||||
eq_main = 0x2F;
|
||||
if (de_emphasis_only)
|
||||
eq_main = 0x34;
|
||||
if (pre_shoot_only)
|
||||
eq_main = 0x39;
|
||||
eq_pre = 0x5;
|
||||
eq_post = 0xA;
|
||||
break;
|
||||
case 2:
|
||||
eq_main = 0x2C;
|
||||
if (de_emphasis_only)
|
||||
eq_main = 0x31;
|
||||
if (pre_shoot_only)
|
||||
eq_main = 0x39;
|
||||
eq_pre = 0x5;
|
||||
eq_post = 0xD;
|
||||
break;
|
||||
case 3:
|
||||
eq_main = 0x29;
|
||||
if (de_emphasis_only)
|
||||
eq_main = 0x2E;
|
||||
if (pre_shoot_only)
|
||||
eq_main = 0x39;
|
||||
eq_pre = 0x5;
|
||||
eq_post = 0x10;
|
||||
break;
|
||||
default:
|
||||
return;
|
||||
}
|
||||
|
||||
eq_pre = de_emphasis_only ? 0 : eq_pre;
|
||||
eq_post = pre_shoot_only ? 0 : eq_post;
|
||||
|
||||
if (no_ffe) {
|
||||
eq_pre = 0;
|
||||
eq_post = 0;
|
||||
eq_main = 0x3E;
|
||||
}
|
||||
|
||||
REG_UPDATE_3(RDPCSTX_PHY_FUSE0,
|
||||
RDPCS_PHY_DP_TX0_EQ_MAIN, eq_main,
|
||||
RDPCS_PHY_DP_TX0_EQ_PRE, eq_pre,
|
||||
RDPCS_PHY_DP_TX0_EQ_POST, eq_post);
|
||||
|
||||
REG_UPDATE_3(RDPCSTX_PHY_FUSE1,
|
||||
RDPCS_PHY_DP_TX1_EQ_MAIN, eq_main,
|
||||
RDPCS_PHY_DP_TX1_EQ_PRE, eq_pre,
|
||||
RDPCS_PHY_DP_TX1_EQ_POST, eq_post);
|
||||
|
||||
REG_UPDATE_3(RDPCSTX_PHY_FUSE2,
|
||||
RDPCS_PHY_DP_TX2_EQ_MAIN, eq_main,
|
||||
RDPCS_PHY_DP_TX2_EQ_PRE, eq_pre,
|
||||
RDPCS_PHY_DP_TX2_EQ_POST, eq_post);
|
||||
|
||||
REG_UPDATE_3(RDPCSTX_PHY_FUSE3,
|
||||
RDPCS_PHY_DP_TX3_EQ_MAIN, eq_main,
|
||||
RDPCS_PHY_DP_TX3_EQ_PRE, eq_pre,
|
||||
RDPCS_PHY_DP_TX3_EQ_POST, eq_post);
|
||||
}
|
||||
|
||||
void dpcs30_get_txffe(
|
||||
struct link_encoder *enc,
|
||||
struct frl_txffe *lane_settings)
|
||||
{
|
||||
struct dcn10_link_encoder *enc10 = TO_DCN10_LINK_ENC(enc);
|
||||
/* EQ setting for DP lane0 */
|
||||
uint32_t eq_main;
|
||||
uint32_t eq_pre;
|
||||
uint32_t eq_post;
|
||||
|
||||
REG_GET_3(RDPCSTX_PHY_FUSE0,
|
||||
RDPCS_PHY_DP_TX0_EQ_MAIN, &eq_main,
|
||||
RDPCS_PHY_DP_TX0_EQ_PRE, &eq_pre,
|
||||
RDPCS_PHY_DP_TX0_EQ_POST, &eq_post);
|
||||
|
||||
lane_settings->amplitude[0] = eq_main;
|
||||
lane_settings->pre_emphasis[0] = eq_pre;
|
||||
lane_settings->post_emphasis[0] = eq_post;
|
||||
|
||||
REG_GET_3(RDPCSTX_PHY_FUSE1,
|
||||
RDPCS_PHY_DP_TX1_EQ_MAIN, &eq_main,
|
||||
RDPCS_PHY_DP_TX1_EQ_PRE, &eq_pre,
|
||||
RDPCS_PHY_DP_TX1_EQ_POST, &eq_post);
|
||||
|
||||
lane_settings->amplitude[1] = eq_main;
|
||||
lane_settings->pre_emphasis[1] = eq_pre;
|
||||
lane_settings->post_emphasis[1] = eq_post;
|
||||
|
||||
REG_GET_3(RDPCSTX_PHY_FUSE2,
|
||||
RDPCS_PHY_DP_TX2_EQ_MAIN, &eq_main,
|
||||
RDPCS_PHY_DP_TX2_EQ_PRE, &eq_pre,
|
||||
RDPCS_PHY_DP_TX2_EQ_POST, &eq_post);
|
||||
|
||||
lane_settings->amplitude[2] = eq_main;
|
||||
lane_settings->pre_emphasis[2] = eq_pre;
|
||||
lane_settings->post_emphasis[2] = eq_post;
|
||||
|
||||
REG_GET_3(RDPCSTX_PHY_FUSE3,
|
||||
RDPCS_PHY_DP_TX3_EQ_MAIN, &eq_main,
|
||||
RDPCS_PHY_DP_TX3_EQ_PRE, &eq_pre,
|
||||
RDPCS_PHY_DP_TX3_EQ_POST, &eq_post);
|
||||
|
||||
lane_settings->amplitude[3] = eq_main;
|
||||
lane_settings->pre_emphasis[3] = eq_pre;
|
||||
lane_settings->post_emphasis[3] = eq_post;
|
||||
|
||||
}
|
||||
|
||||
void dpcs30_set_txffe(
|
||||
struct link_encoder *enc,
|
||||
struct frl_txffe *lane_settings)
|
||||
{
|
||||
struct dcn10_link_encoder *enc10 = TO_DCN10_LINK_ENC(enc);
|
||||
/* EQ setting for DP lane0 */
|
||||
uint32_t eq_main;
|
||||
uint32_t eq_pre;
|
||||
uint32_t eq_post;
|
||||
|
||||
eq_main = lane_settings->amplitude[0];
|
||||
eq_pre = lane_settings->pre_emphasis[0];
|
||||
eq_post = lane_settings->post_emphasis[0];
|
||||
|
||||
REG_UPDATE_3(RDPCSTX_PHY_FUSE0,
|
||||
RDPCS_PHY_DP_TX0_EQ_MAIN, eq_main,
|
||||
RDPCS_PHY_DP_TX0_EQ_PRE, eq_pre,
|
||||
RDPCS_PHY_DP_TX0_EQ_POST, eq_post);
|
||||
|
||||
eq_main = lane_settings->amplitude[1];
|
||||
eq_pre = lane_settings->pre_emphasis[1];
|
||||
eq_post = lane_settings->post_emphasis[1];
|
||||
|
||||
REG_UPDATE_3(RDPCSTX_PHY_FUSE1,
|
||||
RDPCS_PHY_DP_TX1_EQ_MAIN, eq_main,
|
||||
RDPCS_PHY_DP_TX1_EQ_PRE, eq_pre,
|
||||
RDPCS_PHY_DP_TX1_EQ_POST, eq_post);
|
||||
|
||||
eq_main = lane_settings->amplitude[2];
|
||||
eq_pre = lane_settings->pre_emphasis[2];
|
||||
eq_post = lane_settings->post_emphasis[2];
|
||||
|
||||
REG_UPDATE_3(RDPCSTX_PHY_FUSE2,
|
||||
RDPCS_PHY_DP_TX2_EQ_MAIN, eq_main,
|
||||
RDPCS_PHY_DP_TX2_EQ_PRE, eq_pre,
|
||||
RDPCS_PHY_DP_TX2_EQ_POST, eq_post);
|
||||
|
||||
eq_main = lane_settings->amplitude[3];
|
||||
eq_pre = lane_settings->pre_emphasis[3];
|
||||
eq_post = lane_settings->post_emphasis[3];
|
||||
|
||||
REG_UPDATE_3(RDPCSTX_PHY_FUSE3,
|
||||
RDPCS_PHY_DP_TX3_EQ_MAIN, eq_main,
|
||||
RDPCS_PHY_DP_TX3_EQ_PRE, eq_pre,
|
||||
RDPCS_PHY_DP_TX3_EQ_POST, eq_post);
|
||||
}
|
||||
|
||||
static const struct link_encoder_funcs dcn30_link_enc_funcs = {
|
||||
@@ -84,6 +313,15 @@ static const struct link_encoder_funcs dcn30_link_enc_funcs = {
|
||||
.get_dig_mode = dcn10_get_dig_mode,
|
||||
.is_in_alt_mode = dcn20_link_encoder_is_in_alt_mode,
|
||||
.get_max_link_cap = dcn20_link_encoder_get_max_link_cap,
|
||||
.dpcstx_set_order_invert_18_bit = NULL,
|
||||
.set_phy_source = NULL,
|
||||
.dpcs_initialize_phy = NULL,
|
||||
.dpcs_configure_phypll = NULL,
|
||||
.dpcs_configure_dpcs = NULL,
|
||||
.dpcs_enable_dpcs = NULL,
|
||||
.prog_eq_setting = dpcs30_program_eq_setting,
|
||||
.get_txffe = dpcs30_get_txffe,
|
||||
.set_txffe = dpcs30_set_txffe,
|
||||
.get_hpd_state = dcn10_get_hpd_state,
|
||||
.program_hpd_filter = dcn10_program_hpd_filter,
|
||||
};
|
||||
@@ -198,6 +436,12 @@ void dcn30_link_encoder_construct(
|
||||
enc10->base.features.flags.bits.IS_UHBR20_CAPABLE = bp_cap_info.DP_UHBR20_EN;
|
||||
enc10->base.features.flags.bits.DP_IS_USB_C =
|
||||
bp_cap_info.DP_IS_USB_C;
|
||||
|
||||
enc10->base.features.flags.bits.IS_HDMI_FRL_CAPABLE = bp_cap_info.IS_HDMI_FRL_CAPABLE;
|
||||
enc10->base.features.flags.bits.IS_FRL_8G_CAPABLE = bp_cap_info.FRL_8G_EN;
|
||||
enc10->base.features.flags.bits.IS_FRL_10G_CAPABLE = bp_cap_info.FRL_10G_EN;
|
||||
enc10->base.features.flags.bits.IS_FRL_12G_CAPABLE = bp_cap_info.FRL_12G_EN;
|
||||
enc10->base.txffe_state = 0;
|
||||
} else {
|
||||
DC_LOG_WARNING("%s: Failed to get encoder_cap_info from VBIOS with error code %d!\n",
|
||||
__func__,
|
||||
@@ -206,6 +450,12 @@ void dcn30_link_encoder_construct(
|
||||
if (enc10->base.ctx->dc->debug.hdmi20_disable) {
|
||||
enc10->base.features.flags.bits.HDMI_6GB_EN = 0;
|
||||
}
|
||||
if (enc10->base.ctx->dc->config.force_hdmi21_frl_enc_enable) {
|
||||
enc10->base.features.flags.bits.IS_HDMI_FRL_CAPABLE = 1;
|
||||
enc10->base.features.flags.bits.IS_FRL_8G_CAPABLE = 1;
|
||||
enc10->base.features.flags.bits.IS_FRL_10G_CAPABLE = 1;
|
||||
enc10->base.features.flags.bits.IS_FRL_12G_CAPABLE = 1;
|
||||
}
|
||||
}
|
||||
|
||||
#define AUX_REG(reg)\
|
||||
|
||||
@@ -60,6 +60,8 @@
|
||||
|
||||
#define DPCS_DCN3_MASK_SH_LIST(mask_sh)\
|
||||
DPCS_DCN2_MASK_SH_LIST(mask_sh),\
|
||||
LE_SF(DPCSTX0_DPCSTX_TX_CNTL, DPCS_TX_HDMI_FRL_MODE, mask_sh),\
|
||||
LE_SF(DPCSTX0_DPCSTX_TX_CNTL, DPCS_TX_DATA_SWAP_10_BIT, mask_sh),\
|
||||
LE_SF(DPCSTX0_DPCSTX_TX_CNTL, DPCS_TX_DATA_ORDER_INVERT_18_BIT, mask_sh),\
|
||||
LE_SF(RDPCSTX0_RDPCSTX_PHY_CNTL0, RDPCS_PHY_TX_VBOOST_LVL, mask_sh),\
|
||||
LE_SF(RDPCSTX0_RDPCSTX_CLOCK_CNTL, RDPCS_TX_CLK_EN, mask_sh),\
|
||||
@@ -83,4 +85,19 @@ bool dcn30_link_encoder_validate_output_with_stream(
|
||||
struct link_encoder *enc,
|
||||
const struct dc_stream_state *stream);
|
||||
|
||||
void dpcs30_program_eq_setting(
|
||||
struct link_encoder *enc,
|
||||
uint8_t FFE_Level,
|
||||
bool de_emphasis_only,
|
||||
bool pre_shoot_only,
|
||||
bool no_ffe,
|
||||
const struct dc_hdmi_frl_link_settings *link_settings);
|
||||
|
||||
void dpcs30_get_txffe(
|
||||
struct link_encoder *enc,
|
||||
struct frl_txffe *lane_settings);
|
||||
|
||||
void dpcs30_set_txffe(
|
||||
struct link_encoder *enc,
|
||||
struct frl_txffe *lane_settings);
|
||||
#endif /* __DC_LINK_ENCODER__DCN30_H__ */
|
||||
|
||||
@@ -73,6 +73,13 @@ static const struct link_encoder_funcs dcn301_link_enc_funcs = {
|
||||
.get_dig_mode = dcn10_get_dig_mode,
|
||||
.is_in_alt_mode = dcn20_link_encoder_is_in_alt_mode,
|
||||
.get_max_link_cap = dcn20_link_encoder_get_max_link_cap,
|
||||
.dpcstx_set_order_invert_18_bit = NULL,
|
||||
.set_phy_source = NULL,
|
||||
.dpcs_initialize_phy = NULL,
|
||||
.dpcs_configure_phypll = NULL,
|
||||
.dpcs_configure_dpcs = NULL,
|
||||
.dpcs_enable_dpcs = NULL,
|
||||
.prog_eq_setting = NULL,
|
||||
.get_hpd_state = dcn10_get_hpd_state,
|
||||
.program_hpd_filter = dcn10_program_hpd_filter,
|
||||
};
|
||||
@@ -183,6 +190,11 @@ void dcn301_link_encoder_construct(
|
||||
enc10->base.features.flags.bits.HDMI_6GB_EN = bp_cap_info.HDMI_6GB_EN;
|
||||
enc10->base.features.flags.bits.DP_IS_USB_C =
|
||||
bp_cap_info.DP_IS_USB_C;
|
||||
enc10->base.features.flags.bits.IS_HDMI_FRL_CAPABLE = bp_cap_info.IS_HDMI_FRL_CAPABLE;
|
||||
enc10->base.features.flags.bits.IS_FRL_8G_CAPABLE = bp_cap_info.FRL_8G_EN;
|
||||
enc10->base.features.flags.bits.IS_FRL_10G_CAPABLE = bp_cap_info.FRL_10G_EN;
|
||||
enc10->base.features.flags.bits.IS_FRL_12G_CAPABLE = bp_cap_info.FRL_12G_EN;
|
||||
enc10->base.txffe_state = 0;
|
||||
} else {
|
||||
DC_LOG_WARNING("%s: Failed to get encoder_cap_info from VBIOS with error code %d!\n",
|
||||
__func__,
|
||||
@@ -191,4 +203,10 @@ void dcn301_link_encoder_construct(
|
||||
if (enc10->base.ctx->dc->debug.hdmi20_disable) {
|
||||
enc10->base.features.flags.bits.HDMI_6GB_EN = 0;
|
||||
}
|
||||
if (enc10->base.ctx->dc->config.force_hdmi21_frl_enc_enable) {
|
||||
enc10->base.features.flags.bits.IS_HDMI_FRL_CAPABLE = 1;
|
||||
enc10->base.features.flags.bits.IS_FRL_8G_CAPABLE = 1;
|
||||
enc10->base.features.flags.bits.IS_FRL_10G_CAPABLE = 1;
|
||||
enc10->base.features.flags.bits.IS_FRL_12G_CAPABLE = 1;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -67,6 +67,17 @@
|
||||
#define MIN(X, Y) ((X) < (Y) ? (X) : (Y))
|
||||
#endif
|
||||
|
||||
// HDMI FRL EQ Setting masks/shifts
|
||||
// EQ level 0-32 bits[0:1]
|
||||
#define HDMI_FRL_EQ__LEVEL__SHIFT 0x0
|
||||
#define HDMI_FRL_EQ__LEVEL__MASK 0x3
|
||||
// Enable no preshoot bit[5]
|
||||
#define HDMI_FRL_EQ__NO_PRE__SHIFT 0x5
|
||||
// Enable no demphasis bit[6]
|
||||
#define HDMI_FRL_EQ__NO_DEMPH__SHIFT 0x6
|
||||
// Enable no FFE bit[4]
|
||||
#define HDMI_FRL_EQ__NO_FFE__SHIFT 0x4
|
||||
|
||||
static uint8_t phy_id_from_transmitter(enum transmitter t)
|
||||
{
|
||||
uint8_t phy_id;
|
||||
@@ -246,6 +257,89 @@ void enc31_hw_init(struct link_encoder *enc)
|
||||
dcn10_aux_initialize(enc10);
|
||||
}
|
||||
|
||||
static enum bp_result link_transmitter_control(
|
||||
struct dcn10_link_encoder *enc10,
|
||||
struct bp_transmitter_control *cntl)
|
||||
{
|
||||
enum bp_result result;
|
||||
struct dc_bios *bp = enc10->base.ctx->dc_bios;
|
||||
|
||||
result = bp->funcs->transmitter_control(bp, cntl);
|
||||
|
||||
return result;
|
||||
}
|
||||
//---------------------------------------------------
|
||||
// Task: Program EQ setting in HDMI FRL mode
|
||||
// Note:
|
||||
// EQ setting can be dont during P2 state or P0 state
|
||||
// If set in P0 state, The values are latched in a single
|
||||
// cycle of txX_clk but will take maximum of 40 txX_clk symbols
|
||||
// to be reflected on the output. During this period the
|
||||
// analog serial lines might have a transitional behavior.
|
||||
//---------------------------------------------------
|
||||
void dpcs31_program_eq_setting(
|
||||
struct link_encoder *enc,
|
||||
uint8_t FFE_Level,
|
||||
bool de_emphasis_only,
|
||||
bool pre_shoot_only,
|
||||
bool no_ffe,
|
||||
const struct dc_hdmi_frl_link_settings *link_settings)
|
||||
{
|
||||
struct dcn10_link_encoder *enc10 = TO_DCN10_LINK_ENC(enc);
|
||||
struct bp_transmitter_control cntl = { 0 };
|
||||
/* EQ setting for DP lane0 */
|
||||
|
||||
if (enc10->base.ctx->dc->debug.ignore_ffe)
|
||||
return;
|
||||
|
||||
if (FFE_Level < 0x5)
|
||||
enc10->base.txffe_state = FFE_Level;
|
||||
|
||||
if (FFE_Level == 0xEE) {
|
||||
enc10->base.txffe_state++;
|
||||
if (enc10->base.txffe_state > 3)
|
||||
enc10->base.txffe_state = 0;
|
||||
}
|
||||
|
||||
if (no_ffe) {
|
||||
de_emphasis_only = true;
|
||||
pre_shoot_only = true;
|
||||
}
|
||||
/* Pass on the input params to DMCUB for proper calc of eq settings */
|
||||
cntl.lane_settings = ((de_emphasis_only ? 1 : 0) << HDMI_FRL_EQ__NO_PRE__SHIFT) |
|
||||
((pre_shoot_only ? 1 : 0) << HDMI_FRL_EQ__NO_DEMPH__SHIFT) |
|
||||
((enc10->base.txffe_state & HDMI_FRL_EQ__LEVEL__MASK)
|
||||
<< HDMI_FRL_EQ__LEVEL__SHIFT);
|
||||
cntl.lane_select = 0;
|
||||
cntl.action = TRANSMITTER_CONTROL_SET_VOLTAGE_AND_PREEMPASIS;
|
||||
cntl.transmitter = enc10->base.transmitter;
|
||||
cntl.connector_obj_id = enc10->base.connector;
|
||||
cntl.lanes_number = link_settings->frl_num_lanes;
|
||||
cntl.hpd_sel = enc10->base.hpd_source;
|
||||
/* Use below or dc_link_frl_bandwidth_kbps()? */
|
||||
switch (link_settings->frl_link_rate) {
|
||||
case HDMI_FRL_LINK_RATE_3GBPS:
|
||||
cntl.pixel_clock = 166667 / 10;
|
||||
break;
|
||||
case HDMI_FRL_LINK_RATE_6GBPS:
|
||||
case HDMI_FRL_LINK_RATE_6GBPS_4LANE:
|
||||
cntl.pixel_clock = 333333 / 10;
|
||||
break;
|
||||
case HDMI_FRL_LINK_RATE_8GBPS:
|
||||
cntl.pixel_clock = 444444 / 10;
|
||||
break;
|
||||
case HDMI_FRL_LINK_RATE_10GBPS:
|
||||
cntl.pixel_clock = 555555 / 10;
|
||||
break;
|
||||
case HDMI_FRL_LINK_RATE_12GBPS:
|
||||
default:
|
||||
cntl.pixel_clock = 666667 / 10;
|
||||
break;
|
||||
}
|
||||
/* call VBIOS table to set eq settings - voltage swing and pre-emphasis */
|
||||
link_transmitter_control(enc10, &cntl);
|
||||
}
|
||||
|
||||
static const struct link_encoder_funcs dcn31_link_enc_funcs = {
|
||||
.read_state = link_enc2_read_state,
|
||||
.validate_output_with_stream =
|
||||
@@ -275,6 +369,15 @@ static const struct link_encoder_funcs dcn31_link_enc_funcs = {
|
||||
.get_dig_mode = dcn10_get_dig_mode,
|
||||
.is_in_alt_mode = dcn31_link_encoder_is_in_alt_mode,
|
||||
.get_max_link_cap = dcn31_link_encoder_get_max_link_cap,
|
||||
.dpcstx_set_order_invert_18_bit = NULL,
|
||||
.set_phy_source = NULL,
|
||||
.dpcs_initialize_phy = NULL,
|
||||
.dpcs_configure_phypll = NULL,
|
||||
.dpcs_configure_dpcs = NULL,
|
||||
.dpcs_enable_dpcs = NULL,
|
||||
.prog_eq_setting = dpcs31_program_eq_setting,
|
||||
.get_txffe = dpcs30_get_txffe,
|
||||
.set_txffe = dpcs30_set_txffe,
|
||||
.set_dio_phy_mux = dcn31_link_encoder_set_dio_phy_mux,
|
||||
.get_hpd_state = dcn10_get_hpd_state,
|
||||
.program_hpd_filter = dcn10_program_hpd_filter,
|
||||
@@ -387,6 +490,11 @@ void dcn31_link_encoder_construct(
|
||||
enc10->base.features.flags.bits.IS_UHBR20_CAPABLE = bp_cap_info.DP_UHBR20_EN;
|
||||
enc10->base.features.flags.bits.DP_IS_USB_C =
|
||||
bp_cap_info.DP_IS_USB_C;
|
||||
enc10->base.features.flags.bits.IS_HDMI_FRL_CAPABLE = bp_cap_info.IS_HDMI_FRL_CAPABLE;
|
||||
enc10->base.features.flags.bits.IS_FRL_8G_CAPABLE = bp_cap_info.FRL_8G_EN;
|
||||
enc10->base.features.flags.bits.IS_FRL_10G_CAPABLE = bp_cap_info.FRL_10G_EN;
|
||||
enc10->base.features.flags.bits.IS_FRL_12G_CAPABLE = bp_cap_info.FRL_12G_EN;
|
||||
enc10->base.txffe_state = 0;
|
||||
} else {
|
||||
DC_LOG_WARNING("%s: Failed to get encoder_cap_info from VBIOS with error code %d!\n",
|
||||
__func__,
|
||||
@@ -395,6 +503,12 @@ void dcn31_link_encoder_construct(
|
||||
if (enc10->base.ctx->dc->debug.hdmi20_disable) {
|
||||
enc10->base.features.flags.bits.HDMI_6GB_EN = 0;
|
||||
}
|
||||
if (enc10->base.ctx->dc->config.force_hdmi21_frl_enc_enable) {
|
||||
enc10->base.features.flags.bits.IS_HDMI_FRL_CAPABLE = 1;
|
||||
enc10->base.features.flags.bits.IS_FRL_8G_CAPABLE = 1;
|
||||
enc10->base.features.flags.bits.IS_FRL_10G_CAPABLE = 1;
|
||||
enc10->base.features.flags.bits.IS_FRL_12G_CAPABLE = 1;
|
||||
}
|
||||
}
|
||||
|
||||
void dcn31_link_encoder_construct_minimal(
|
||||
|
||||
@@ -285,6 +285,14 @@ bool dcn31_link_encoder_is_in_alt_mode(
|
||||
void dcn31_link_encoder_get_max_link_cap(struct link_encoder *enc,
|
||||
struct dc_link_settings *link_settings);
|
||||
|
||||
void dpcs31_program_eq_setting(
|
||||
struct link_encoder *enc,
|
||||
uint8_t FFE_Level,
|
||||
bool de_emphasis_only,
|
||||
bool pre_shoot_only,
|
||||
bool no_ffe,
|
||||
const struct dc_hdmi_frl_link_settings *link_settings);
|
||||
|
||||
void enc31_hw_init(struct link_encoder *enc);
|
||||
|
||||
#endif /* __DC_LINK_ENCODER__DCN31_H__ */
|
||||
|
||||
@@ -62,6 +62,17 @@
|
||||
#define AUX_REG_WRITE(reg_name, val) \
|
||||
dm_write_reg(CTX, AUX_REG(reg_name), val)
|
||||
|
||||
// HDMI FRL EQ Setting masks/shifts
|
||||
// EQ level 0-32 bits[0:1]
|
||||
#define HDMI_FRL_EQ__LEVEL__SHIFT 0x0
|
||||
#define HDMI_FRL_EQ__LEVEL__MASK 0x3
|
||||
// Enable no preshoot bit[5]
|
||||
#define HDMI_FRL_EQ__NO_PRE__SHIFT 0x5
|
||||
// Enable no demphasis bit[6]
|
||||
#define HDMI_FRL_EQ__NO_DEMPH__SHIFT 0x6
|
||||
// Enable no FFE bit[4]
|
||||
#define HDMI_FRL_EQ__NO_FFE__SHIFT 0x4
|
||||
|
||||
static uint8_t phy_id_from_transmitter(enum transmitter t)
|
||||
{
|
||||
uint8_t phy_id;
|
||||
@@ -203,6 +214,188 @@ void dcn32_link_encoder_get_max_link_cap(struct link_encoder *enc,
|
||||
}
|
||||
|
||||
|
||||
static enum bp_result link_transmitter_control(
|
||||
struct dcn10_link_encoder *enc10,
|
||||
struct bp_transmitter_control *cntl)
|
||||
{
|
||||
enum bp_result result;
|
||||
struct dc_bios *bp = enc10->base.ctx->dc_bios;
|
||||
|
||||
result = bp->funcs->transmitter_control(bp, cntl);
|
||||
|
||||
return result;
|
||||
}
|
||||
//---------------------------------------------------
|
||||
// Task: Program EQ setting
|
||||
// Note:
|
||||
// EQ setting can be dont during P2 state or P0 state
|
||||
// If set in P0 state, The values are latched in a single
|
||||
// cycle of txX_clk but will take maximum of 40 txX_clk symbols
|
||||
// to be reflected on the output. During this period the
|
||||
// analog serial lines might have a transitional behavior.
|
||||
//---------------------------------------------------
|
||||
void dpcs32_program_eq_setting(
|
||||
struct link_encoder *enc,
|
||||
uint8_t FFE_Level,
|
||||
bool de_emphasis_only,
|
||||
bool pre_shoot_only,
|
||||
bool no_ffe,
|
||||
const struct dc_hdmi_frl_link_settings *link_settings)
|
||||
{
|
||||
struct dcn10_link_encoder *enc10 = TO_DCN10_LINK_ENC(enc);
|
||||
struct bp_transmitter_control cntl = { 0 };
|
||||
/* EQ setting for DP lane0 */
|
||||
|
||||
if (enc10->base.ctx->dc->debug.ignore_ffe)
|
||||
return;
|
||||
|
||||
if (FFE_Level < 0x5)
|
||||
enc10->base.txffe_state = FFE_Level;
|
||||
|
||||
if (FFE_Level == 0xEE) {
|
||||
enc10->base.txffe_state++;
|
||||
if (enc10->base.txffe_state > 3)
|
||||
enc10->base.txffe_state = 0;
|
||||
}
|
||||
|
||||
if (no_ffe) {
|
||||
de_emphasis_only = true;
|
||||
pre_shoot_only = true;
|
||||
}
|
||||
/* Pass on the input params to DMCUB for proper calc of eq settings */
|
||||
cntl.lane_settings = ((de_emphasis_only ? 1 : 0) << HDMI_FRL_EQ__NO_PRE__SHIFT) |
|
||||
((pre_shoot_only ? 1 : 0) << HDMI_FRL_EQ__NO_DEMPH__SHIFT) |
|
||||
((enc10->base.txffe_state & HDMI_FRL_EQ__LEVEL__MASK)
|
||||
<< HDMI_FRL_EQ__LEVEL__SHIFT);
|
||||
cntl.lane_select = 0;
|
||||
cntl.action = TRANSMITTER_CONTROL_SET_VOLTAGE_AND_PREEMPASIS;
|
||||
cntl.transmitter = enc10->base.transmitter;
|
||||
cntl.connector_obj_id = enc10->base.connector;
|
||||
cntl.lanes_number = link_settings->frl_num_lanes;
|
||||
cntl.hpd_sel = enc10->base.hpd_source;
|
||||
/* Use below or dc_link_frl_bandwidth_kbps()? */
|
||||
switch (link_settings->frl_link_rate) {
|
||||
case HDMI_FRL_LINK_RATE_3GBPS:
|
||||
cntl.pixel_clock = 166667 / 10;
|
||||
break;
|
||||
case HDMI_FRL_LINK_RATE_6GBPS:
|
||||
case HDMI_FRL_LINK_RATE_6GBPS_4LANE:
|
||||
cntl.pixel_clock = 333333 / 10;
|
||||
break;
|
||||
case HDMI_FRL_LINK_RATE_8GBPS:
|
||||
cntl.pixel_clock = 444444 / 10;
|
||||
break;
|
||||
case HDMI_FRL_LINK_RATE_10GBPS:
|
||||
cntl.pixel_clock = 555555 / 10;
|
||||
break;
|
||||
case HDMI_FRL_LINK_RATE_12GBPS:
|
||||
default:
|
||||
cntl.pixel_clock = 666667 / 10;
|
||||
break;
|
||||
}
|
||||
/* call VBIOS table to set eq settings - voltage swing and pre-emphasis */
|
||||
link_transmitter_control(enc10, &cntl);
|
||||
}
|
||||
|
||||
void dpcs32_get_txffe(
|
||||
struct link_encoder *enc,
|
||||
struct frl_txffe *lane_settings)
|
||||
{
|
||||
(void)enc;
|
||||
/* EQ setting for DP lane0 */
|
||||
uint32_t eq_main = 0;
|
||||
uint32_t eq_pre = 0;
|
||||
uint32_t eq_post = 0;
|
||||
|
||||
/* TODO */
|
||||
//REG_GET_3(RDPCSTX_PHY_FUSE0,
|
||||
// RDPCS_PHY_DP_TX0_EQ_MAIN, &eq_main,
|
||||
// RDPCS_PHY_DP_TX0_EQ_PRE, &eq_pre,
|
||||
// RDPCS_PHY_DP_TX0_EQ_POST, &eq_post);
|
||||
|
||||
lane_settings->amplitude[0] = eq_main;
|
||||
lane_settings->pre_emphasis[0] = eq_pre;
|
||||
lane_settings->post_emphasis[0] = eq_post;
|
||||
|
||||
//REG_GET_3(RDPCSTX_PHY_FUSE1,
|
||||
// RDPCS_PHY_DP_TX1_EQ_MAIN, &eq_main,
|
||||
// RDPCS_PHY_DP_TX1_EQ_PRE, &eq_pre,
|
||||
// RDPCS_PHY_DP_TX1_EQ_POST, &eq_post);
|
||||
|
||||
lane_settings->amplitude[1] = eq_main;
|
||||
lane_settings->pre_emphasis[1] = eq_pre;
|
||||
lane_settings->post_emphasis[1] = eq_post;
|
||||
|
||||
//REG_GET_3(RDPCSTX_PHY_FUSE2,
|
||||
// RDPCS_PHY_DP_TX2_EQ_MAIN, &eq_main,
|
||||
// RDPCS_PHY_DP_TX2_EQ_PRE, &eq_pre,
|
||||
// RDPCS_PHY_DP_TX2_EQ_POST, &eq_post);
|
||||
|
||||
lane_settings->amplitude[2] = eq_main;
|
||||
lane_settings->pre_emphasis[2] = eq_pre;
|
||||
lane_settings->post_emphasis[2] = eq_post;
|
||||
|
||||
//REG_GET_3(RDPCSTX_PHY_FUSE3,
|
||||
// RDPCS_PHY_DP_TX3_EQ_MAIN, &eq_main,
|
||||
// RDPCS_PHY_DP_TX3_EQ_PRE, &eq_pre,
|
||||
// RDPCS_PHY_DP_TX3_EQ_POST, &eq_post);
|
||||
|
||||
lane_settings->amplitude[3] = eq_main;
|
||||
lane_settings->pre_emphasis[3] = eq_pre;
|
||||
lane_settings->post_emphasis[3] = eq_post;
|
||||
|
||||
}
|
||||
|
||||
void dpcs32_set_txffe(
|
||||
struct link_encoder *enc,
|
||||
struct frl_txffe *lane_settings)
|
||||
{
|
||||
(void)enc;
|
||||
(void)lane_settings;
|
||||
/* EQ setting for DP lane0 */
|
||||
//uint32_t eq_main;
|
||||
//uint32_t eq_pre;
|
||||
//uint32_t eq_post;
|
||||
|
||||
//eq_main = lane_settings->amplitude[0];
|
||||
//eq_pre = lane_settings->pre_emphasis[0];
|
||||
//eq_post = lane_settings->post_emphasis[0];
|
||||
|
||||
/* TODO */
|
||||
//REG_UPDATE_3(RDPCSTX_PHY_FUSE0,
|
||||
// RDPCS_PHY_DP_TX0_EQ_MAIN, eq_main,
|
||||
// RDPCS_PHY_DP_TX0_EQ_PRE, eq_pre,
|
||||
// RDPCS_PHY_DP_TX0_EQ_POST, eq_post);
|
||||
|
||||
//eq_main = lane_settings->amplitude[1];
|
||||
//eq_pre = lane_settings->pre_emphasis[1];
|
||||
//eq_post = lane_settings->post_emphasis[1];
|
||||
|
||||
//REG_UPDATE_3(RDPCSTX_PHY_FUSE1,
|
||||
// RDPCS_PHY_DP_TX1_EQ_MAIN, eq_main,
|
||||
// RDPCS_PHY_DP_TX1_EQ_PRE, eq_pre,
|
||||
// RDPCS_PHY_DP_TX1_EQ_POST, eq_post);
|
||||
|
||||
//eq_main = lane_settings->amplitude[2];
|
||||
//eq_pre = lane_settings->pre_emphasis[2];
|
||||
//eq_post = lane_settings->post_emphasis[2];
|
||||
|
||||
//REG_UPDATE_3(RDPCSTX_PHY_FUSE2,
|
||||
// RDPCS_PHY_DP_TX2_EQ_MAIN, eq_main,
|
||||
// RDPCS_PHY_DP_TX2_EQ_PRE, eq_pre,
|
||||
// RDPCS_PHY_DP_TX2_EQ_POST, eq_post);
|
||||
|
||||
//1eq_main = lane_settings->amplitude[3];
|
||||
//eq_pre = lane_settings->pre_emphasis[3];
|
||||
//eq_post = lane_settings->post_emphasis[3];
|
||||
|
||||
//REG_UPDATE_3(RDPCSTX_PHY_FUSE3,
|
||||
// RDPCS_PHY_DP_TX3_EQ_MAIN, eq_main,
|
||||
// RDPCS_PHY_DP_TX3_EQ_PRE, eq_pre,
|
||||
// RDPCS_PHY_DP_TX3_EQ_POST, eq_post);
|
||||
}
|
||||
|
||||
|
||||
static const struct link_encoder_funcs dcn32_link_enc_funcs = {
|
||||
.read_state = link_enc2_read_state,
|
||||
.validate_output_with_stream =
|
||||
@@ -232,6 +425,15 @@ static const struct link_encoder_funcs dcn32_link_enc_funcs = {
|
||||
.get_dig_mode = dcn10_get_dig_mode,
|
||||
.is_in_alt_mode = dcn32_link_encoder_is_in_alt_mode,
|
||||
.get_max_link_cap = dcn32_link_encoder_get_max_link_cap,
|
||||
.dpcstx_set_order_invert_18_bit = NULL,
|
||||
.set_phy_source = NULL,
|
||||
.dpcs_initialize_phy = NULL,
|
||||
.dpcs_configure_phypll = NULL,
|
||||
.dpcs_configure_dpcs = NULL,
|
||||
.dpcs_enable_dpcs = NULL,
|
||||
.prog_eq_setting = dpcs32_program_eq_setting,
|
||||
.get_txffe = dpcs32_get_txffe,
|
||||
.set_txffe = dpcs32_set_txffe,
|
||||
.set_dio_phy_mux = dcn31_link_encoder_set_dio_phy_mux,
|
||||
.get_hpd_state = dcn10_get_hpd_state,
|
||||
.program_hpd_filter = dcn10_program_hpd_filter,
|
||||
@@ -329,6 +531,12 @@ void dcn32_link_encoder_construct(
|
||||
enc10->base.features.flags.bits.IS_UHBR10_CAPABLE = bp_cap_info.DP_UHBR10_EN;
|
||||
enc10->base.features.flags.bits.IS_UHBR13_5_CAPABLE = bp_cap_info.DP_UHBR13_5_EN;
|
||||
enc10->base.features.flags.bits.IS_UHBR20_CAPABLE = bp_cap_info.DP_UHBR20_EN;
|
||||
|
||||
enc10->base.features.flags.bits.IS_HDMI_FRL_CAPABLE = 1;
|
||||
enc10->base.features.flags.bits.IS_FRL_8G_CAPABLE = bp_cap_info.FRL_8G_EN;
|
||||
enc10->base.features.flags.bits.IS_FRL_10G_CAPABLE = bp_cap_info.FRL_10G_EN;
|
||||
enc10->base.features.flags.bits.IS_FRL_12G_CAPABLE = bp_cap_info.FRL_12G_EN;
|
||||
enc10->base.txffe_state = 0;
|
||||
} else {
|
||||
DC_LOG_WARNING("%s: Failed to get encoder_cap_info from VBIOS with error code %d!\n",
|
||||
__func__,
|
||||
@@ -337,4 +545,10 @@ void dcn32_link_encoder_construct(
|
||||
if (enc10->base.ctx->dc->debug.hdmi20_disable) {
|
||||
enc10->base.features.flags.bits.HDMI_6GB_EN = 0;
|
||||
}
|
||||
if (enc10->base.ctx->dc->config.force_hdmi21_frl_enc_enable) {
|
||||
enc10->base.features.flags.bits.IS_HDMI_FRL_CAPABLE = 1;
|
||||
enc10->base.features.flags.bits.IS_FRL_8G_CAPABLE = 1;
|
||||
enc10->base.features.flags.bits.IS_FRL_10G_CAPABLE = 1;
|
||||
enc10->base.features.flags.bits.IS_FRL_12G_CAPABLE = 1;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -50,4 +50,20 @@ bool dcn32_link_encoder_is_in_alt_mode(struct link_encoder *enc);
|
||||
void dcn32_link_encoder_get_max_link_cap(struct link_encoder *enc,
|
||||
struct dc_link_settings *link_settings);
|
||||
|
||||
void dpcs32_program_eq_setting(
|
||||
struct link_encoder *enc,
|
||||
uint8_t FFE_Level,
|
||||
bool de_emphasis_only,
|
||||
bool pre_shoot_only,
|
||||
bool no_ffe,
|
||||
const struct dc_hdmi_frl_link_settings *link_settings);
|
||||
|
||||
void dpcs32_get_txffe(
|
||||
struct link_encoder *enc,
|
||||
struct frl_txffe *lane_settings);
|
||||
|
||||
void dpcs32_set_txffe(
|
||||
struct link_encoder *enc,
|
||||
struct frl_txffe *lane_settings);
|
||||
|
||||
#endif /* __DC_LINK_ENCODER__DCN32_H__ */
|
||||
|
||||
@@ -88,6 +88,15 @@ static const struct link_encoder_funcs dcn321_link_enc_funcs = {
|
||||
.get_dig_mode = dcn10_get_dig_mode,
|
||||
.is_in_alt_mode = dcn20_link_encoder_is_in_alt_mode,
|
||||
.get_max_link_cap = dcn20_link_encoder_get_max_link_cap,
|
||||
.dpcstx_set_order_invert_18_bit = NULL,
|
||||
.set_phy_source = NULL,
|
||||
.dpcs_initialize_phy = NULL,
|
||||
.dpcs_configure_phypll = NULL,
|
||||
.dpcs_configure_dpcs = NULL,
|
||||
.dpcs_enable_dpcs = NULL,
|
||||
.prog_eq_setting = dpcs32_program_eq_setting,
|
||||
.get_txffe = dpcs32_get_txffe,
|
||||
.set_txffe = dpcs32_set_txffe,
|
||||
.set_dio_phy_mux = dcn31_link_encoder_set_dio_phy_mux,
|
||||
.get_hpd_state = dcn10_get_hpd_state,
|
||||
.program_hpd_filter = dcn10_program_hpd_filter,
|
||||
@@ -183,6 +192,11 @@ void dcn321_link_encoder_construct(
|
||||
enc10->base.features.flags.bits.IS_UHBR10_CAPABLE = bp_cap_info.DP_UHBR10_EN;
|
||||
enc10->base.features.flags.bits.IS_UHBR13_5_CAPABLE = bp_cap_info.DP_UHBR13_5_EN;
|
||||
enc10->base.features.flags.bits.IS_UHBR20_CAPABLE = bp_cap_info.DP_UHBR20_EN;
|
||||
enc10->base.features.flags.bits.IS_HDMI_FRL_CAPABLE = 1;
|
||||
enc10->base.features.flags.bits.IS_FRL_8G_CAPABLE = bp_cap_info.FRL_8G_EN;
|
||||
enc10->base.features.flags.bits.IS_FRL_10G_CAPABLE = bp_cap_info.FRL_10G_EN;
|
||||
enc10->base.features.flags.bits.IS_FRL_12G_CAPABLE = bp_cap_info.FRL_12G_EN;
|
||||
enc10->base.txffe_state = 0;
|
||||
} else {
|
||||
DC_LOG_WARNING("%s: Failed to get encoder_cap_info from VBIOS with error code %d!\n",
|
||||
__func__,
|
||||
@@ -190,4 +204,10 @@ void dcn321_link_encoder_construct(
|
||||
}
|
||||
if (enc10->base.ctx->dc->debug.hdmi20_disable)
|
||||
enc10->base.features.flags.bits.HDMI_6GB_EN = 0;
|
||||
if (enc10->base.ctx->dc->config.force_hdmi21_frl_enc_enable) {
|
||||
enc10->base.features.flags.bits.IS_HDMI_FRL_CAPABLE = 1;
|
||||
enc10->base.features.flags.bits.IS_FRL_8G_CAPABLE = 1;
|
||||
enc10->base.features.flags.bits.IS_FRL_10G_CAPABLE = 1;
|
||||
enc10->base.features.flags.bits.IS_FRL_12G_CAPABLE = 1;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -158,6 +158,15 @@ static const struct link_encoder_funcs dcn35_link_enc_funcs = {
|
||||
.get_dig_mode = dcn35_get_dig_mode,
|
||||
.is_in_alt_mode = dcn31_link_encoder_is_in_alt_mode,
|
||||
.get_max_link_cap = dcn31_link_encoder_get_max_link_cap,
|
||||
.dpcstx_set_order_invert_18_bit = NULL,
|
||||
.set_phy_source = NULL,
|
||||
.dpcs_initialize_phy = NULL,
|
||||
.dpcs_configure_phypll = NULL,
|
||||
.dpcs_configure_dpcs = NULL,
|
||||
.dpcs_enable_dpcs = NULL,
|
||||
.prog_eq_setting = dpcs32_program_eq_setting,
|
||||
.get_txffe = dpcs32_get_txffe,
|
||||
.set_txffe = dpcs32_set_txffe,
|
||||
.set_dio_phy_mux = dcn31_link_encoder_set_dio_phy_mux,
|
||||
.enable_dpia_output = dcn35_link_encoder_enable_dpia_output,
|
||||
.disable_dpia_output = dcn35_link_encoder_disable_dpia_output,
|
||||
@@ -261,6 +270,12 @@ void dcn35_link_encoder_construct(
|
||||
enc10->base.features.flags.bits.IS_UHBR13_5_CAPABLE = bp_cap_info.DP_UHBR13_5_EN;
|
||||
enc10->base.features.flags.bits.IS_UHBR20_CAPABLE = bp_cap_info.DP_UHBR20_EN;
|
||||
|
||||
enc10->base.features.flags.bits.IS_HDMI_FRL_CAPABLE =
|
||||
bp_cap_info.FRL_8G_EN || bp_cap_info.FRL_10G_EN || bp_cap_info.FRL_12G_EN;
|
||||
enc10->base.features.flags.bits.IS_FRL_8G_CAPABLE = bp_cap_info.FRL_8G_EN;
|
||||
enc10->base.features.flags.bits.IS_FRL_10G_CAPABLE = bp_cap_info.FRL_10G_EN;
|
||||
enc10->base.features.flags.bits.IS_FRL_12G_CAPABLE = bp_cap_info.FRL_12G_EN;
|
||||
enc10->base.txffe_state = 0;
|
||||
} else {
|
||||
DC_LOG_WARNING("%s: Failed to get encoder_cap_info from VBIOS with error code %d!\n",
|
||||
__func__,
|
||||
@@ -268,6 +283,12 @@ void dcn35_link_encoder_construct(
|
||||
}
|
||||
if (enc10->base.ctx->dc->debug.hdmi20_disable)
|
||||
enc10->base.features.flags.bits.HDMI_6GB_EN = 0;
|
||||
if (enc10->base.ctx->dc->config.force_hdmi21_frl_enc_enable) {
|
||||
enc10->base.features.flags.bits.IS_HDMI_FRL_CAPABLE = 1;
|
||||
enc10->base.features.flags.bits.IS_FRL_8G_CAPABLE = 1;
|
||||
enc10->base.features.flags.bits.IS_FRL_10G_CAPABLE = 1;
|
||||
enc10->base.features.flags.bits.IS_FRL_12G_CAPABLE = 1;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
@@ -65,6 +65,17 @@
|
||||
#define MIN(X, Y) ((X) < (Y) ? (X) : (Y))
|
||||
#endif
|
||||
|
||||
// HDMI FRL EQ Setting masks/shifts
|
||||
// EQ level 0-32 bits[0:1]
|
||||
#define HDMI_FRL_EQ__LEVEL__SHIFT 0x0
|
||||
#define HDMI_FRL_EQ__LEVEL__MASK 0x3
|
||||
// Enable no preshoot bit[5]
|
||||
#define HDMI_FRL_EQ__NO_PRE__SHIFT 0x5
|
||||
// Enable no demphasis bit[6]
|
||||
#define HDMI_FRL_EQ__NO_DEMPH__SHIFT 0x6
|
||||
// Enable no FFE bit[4]
|
||||
#define HDMI_FRL_EQ__NO_FFE__SHIFT 0x4
|
||||
|
||||
void enc401_hw_init(struct link_encoder *enc)
|
||||
{
|
||||
struct dcn10_link_encoder *enc10 = TO_DCN10_LINK_ENC(enc);
|
||||
@@ -120,6 +131,194 @@ void dcn401_link_encoder_enable_dp_output(
|
||||
}
|
||||
}
|
||||
|
||||
static enum bp_result link_transmitter_control(
|
||||
struct dcn10_link_encoder *enc10,
|
||||
struct bp_transmitter_control *cntl)
|
||||
{
|
||||
enum bp_result result;
|
||||
struct dc_bios *bp = enc10->base.ctx->dc_bios;
|
||||
|
||||
result = bp->funcs->transmitter_control(bp, cntl);
|
||||
|
||||
return result;
|
||||
}
|
||||
//---------------------------------------------------
|
||||
// Task: Program EQ setting
|
||||
// Note:
|
||||
// EQ setting can be dont during P2 state or P0 state
|
||||
// If set in P0 state, The values are latched in a single
|
||||
// cycle of txX_clk but will take maximum of 40 txX_clk symbols
|
||||
// to be reflected on the output. During this period the
|
||||
// analog serial lines might have a transitional behavior.
|
||||
//---------------------------------------------------
|
||||
|
||||
void dpcs401_program_eq_setting(
|
||||
struct link_encoder *enc,
|
||||
uint8_t FFE_Level,
|
||||
bool de_emphasis_only,
|
||||
bool pre_shoot_only,
|
||||
bool no_ffe,
|
||||
const struct dc_hdmi_frl_link_settings *link_settings)
|
||||
{
|
||||
struct dcn10_link_encoder *enc10 = TO_DCN10_LINK_ENC(enc);
|
||||
struct bp_transmitter_control cntl = { 0 };
|
||||
|
||||
if (enc10->base.ctx->dc->debug.ignore_ffe)
|
||||
return;
|
||||
|
||||
if (FFE_Level < 0x5)
|
||||
enc10->base.txffe_state = FFE_Level;
|
||||
|
||||
if (enc10->base.ctx->dc->debug.select_ffe)
|
||||
enc10->base.txffe_state =
|
||||
(uint8_t)enc10->base.ctx->dc->debug.select_ffe;
|
||||
|
||||
if (FFE_Level == 0xEE) {
|
||||
enc10->base.txffe_state++;
|
||||
if (enc10->base.txffe_state > 3)
|
||||
enc10->base.txffe_state = 0;
|
||||
}
|
||||
|
||||
if (no_ffe) {
|
||||
de_emphasis_only = true;
|
||||
pre_shoot_only = true;
|
||||
}
|
||||
/* Pass on the input params to DMCUB for proper calc of eq settings */
|
||||
cntl.lane_settings = ((de_emphasis_only ? 1 : 0) << HDMI_FRL_EQ__NO_PRE__SHIFT) |
|
||||
((pre_shoot_only ? 1 : 0) << HDMI_FRL_EQ__NO_DEMPH__SHIFT) |
|
||||
((enc10->base.txffe_state & HDMI_FRL_EQ__LEVEL__MASK)
|
||||
<< HDMI_FRL_EQ__LEVEL__SHIFT);
|
||||
cntl.lane_select = 0;
|
||||
cntl.action = TRANSMITTER_CONTROL_SET_VOLTAGE_AND_PREEMPASIS;
|
||||
cntl.transmitter = enc10->base.transmitter;
|
||||
cntl.connector_obj_id = enc10->base.connector;
|
||||
cntl.lanes_number = link_settings->frl_num_lanes;
|
||||
cntl.hpd_sel = enc10->base.hpd_source;
|
||||
/* Use below or dc_link_frl_bandwidth_kbps()? */
|
||||
switch (link_settings->frl_link_rate) {
|
||||
case HDMI_FRL_LINK_RATE_3GBPS:
|
||||
cntl.pixel_clock = 166667 / 10;
|
||||
break;
|
||||
case HDMI_FRL_LINK_RATE_6GBPS:
|
||||
case HDMI_FRL_LINK_RATE_6GBPS_4LANE:
|
||||
cntl.pixel_clock = 333333 / 10;
|
||||
break;
|
||||
case HDMI_FRL_LINK_RATE_8GBPS:
|
||||
cntl.pixel_clock = 444444 / 10;
|
||||
break;
|
||||
case HDMI_FRL_LINK_RATE_10GBPS:
|
||||
cntl.pixel_clock = 555555 / 10;
|
||||
break;
|
||||
case HDMI_FRL_LINK_RATE_12GBPS:
|
||||
default:
|
||||
cntl.pixel_clock = 666667 / 10;
|
||||
break;
|
||||
}
|
||||
/* call VBIOS table to set eq settings - voltage swing and pre-emphasis */
|
||||
link_transmitter_control(enc10, &cntl);
|
||||
}
|
||||
|
||||
void dpcs401_get_txffe(
|
||||
struct link_encoder *enc,
|
||||
struct frl_txffe *lane_settings)
|
||||
{
|
||||
(void)enc;
|
||||
/* EQ setting for DP lane0 */
|
||||
uint32_t eq_main = 0;
|
||||
uint32_t eq_pre = 0;
|
||||
uint32_t eq_post = 0;
|
||||
|
||||
/* TODO */
|
||||
//REG_GET_3(RDPCSTX_PHY_FUSE0,
|
||||
// RDPCS_PHY_DP_TX0_EQ_MAIN, &eq_main,
|
||||
// RDPCS_PHY_DP_TX0_EQ_PRE, &eq_pre,
|
||||
// RDPCS_PHY_DP_TX0_EQ_POST, &eq_post);
|
||||
|
||||
lane_settings->amplitude[0] = eq_main;
|
||||
lane_settings->pre_emphasis[0] = eq_pre;
|
||||
lane_settings->post_emphasis[0] = eq_post;
|
||||
|
||||
//REG_GET_3(RDPCSTX_PHY_FUSE1,
|
||||
// RDPCS_PHY_DP_TX1_EQ_MAIN, &eq_main,
|
||||
// RDPCS_PHY_DP_TX1_EQ_PRE, &eq_pre,
|
||||
// RDPCS_PHY_DP_TX1_EQ_POST, &eq_post);
|
||||
|
||||
lane_settings->amplitude[1] = eq_main;
|
||||
lane_settings->pre_emphasis[1] = eq_pre;
|
||||
lane_settings->post_emphasis[1] = eq_post;
|
||||
|
||||
//REG_GET_3(RDPCSTX_PHY_FUSE2,
|
||||
// RDPCS_PHY_DP_TX2_EQ_MAIN, &eq_main,
|
||||
// RDPCS_PHY_DP_TX2_EQ_PRE, &eq_pre,
|
||||
// RDPCS_PHY_DP_TX2_EQ_POST, &eq_post);
|
||||
|
||||
lane_settings->amplitude[2] = eq_main;
|
||||
lane_settings->pre_emphasis[2] = eq_pre;
|
||||
lane_settings->post_emphasis[2] = eq_post;
|
||||
|
||||
//REG_GET_3(RDPCSTX_PHY_FUSE3,
|
||||
// RDPCS_PHY_DP_TX3_EQ_MAIN, &eq_main,
|
||||
// RDPCS_PHY_DP_TX3_EQ_PRE, &eq_pre,
|
||||
// RDPCS_PHY_DP_TX3_EQ_POST, &eq_post);
|
||||
|
||||
lane_settings->amplitude[3] = eq_main;
|
||||
lane_settings->pre_emphasis[3] = eq_pre;
|
||||
lane_settings->post_emphasis[3] = eq_post;
|
||||
|
||||
}
|
||||
|
||||
void dpcs401_set_txffe(
|
||||
struct link_encoder *enc,
|
||||
struct frl_txffe *lane_settings)
|
||||
{
|
||||
(void)enc;
|
||||
(void)lane_settings;
|
||||
//struct dcn10_link_encoder *enc10 = TO_DCN10_LINK_ENC(enc);
|
||||
/* EQ setting for DP lane0 */
|
||||
//TODO: Unused
|
||||
//uint32_t eq_main;
|
||||
//uint32_t eq_pre;
|
||||
//uint32_t eq_post;
|
||||
|
||||
//eq_main = lane_settings->amplitude[0];
|
||||
//eq_pre = lane_settings->pre_emphasis[0];
|
||||
//eq_post = lane_settings->post_emphasis[0];
|
||||
|
||||
/* TODO */
|
||||
//REG_UPDATE_3(RDPCSTX_PHY_FUSE0,
|
||||
// RDPCS_PHY_DP_TX0_EQ_MAIN, eq_main,
|
||||
// RDPCS_PHY_DP_TX0_EQ_PRE, eq_pre,
|
||||
// RDPCS_PHY_DP_TX0_EQ_POST, eq_post);
|
||||
|
||||
//eq_main = lane_settings->amplitude[1];
|
||||
//eq_pre = lane_settings->pre_emphasis[1];
|
||||
//eq_post = lane_settings->post_emphasis[1];
|
||||
|
||||
//REG_UPDATE_3(RDPCSTX_PHY_FUSE1,
|
||||
// RDPCS_PHY_DP_TX1_EQ_MAIN, eq_main,
|
||||
// RDPCS_PHY_DP_TX1_EQ_PRE, eq_pre,
|
||||
// RDPCS_PHY_DP_TX1_EQ_POST, eq_post);
|
||||
|
||||
//eq_main = lane_settings->amplitude[2];
|
||||
//eq_pre = lane_settings->pre_emphasis[2];
|
||||
//eq_post = lane_settings->post_emphasis[2];
|
||||
|
||||
//REG_UPDATE_3(RDPCSTX_PHY_FUSE2,
|
||||
// RDPCS_PHY_DP_TX2_EQ_MAIN, eq_main,
|
||||
// RDPCS_PHY_DP_TX2_EQ_PRE, eq_pre,
|
||||
// RDPCS_PHY_DP_TX2_EQ_POST, eq_post);
|
||||
|
||||
//eq_main = lane_settings->amplitude[3];
|
||||
//eq_pre = lane_settings->pre_emphasis[3];
|
||||
//eq_post = lane_settings->post_emphasis[3];
|
||||
|
||||
//REG_UPDATE_3(RDPCSTX_PHY_FUSE3,
|
||||
// RDPCS_PHY_DP_TX3_EQ_MAIN, eq_main,
|
||||
// RDPCS_PHY_DP_TX3_EQ_PRE, eq_pre,
|
||||
// RDPCS_PHY_DP_TX3_EQ_POST, eq_post);
|
||||
}
|
||||
|
||||
|
||||
void dcn401_link_encoder_setup(
|
||||
struct link_encoder *enc,
|
||||
enum signal_type signal)
|
||||
@@ -214,6 +413,15 @@ static const struct link_encoder_funcs dcn401_link_enc_funcs = {
|
||||
.get_dig_mode = dcn401_get_dig_mode,
|
||||
.is_in_alt_mode = dcn32_link_encoder_is_in_alt_mode,
|
||||
.get_max_link_cap = dcn32_link_encoder_get_max_link_cap,
|
||||
.dpcstx_set_order_invert_18_bit = NULL,
|
||||
.set_phy_source = NULL,
|
||||
.dpcs_initialize_phy = NULL,
|
||||
.dpcs_configure_phypll = NULL,
|
||||
.dpcs_configure_dpcs = NULL,
|
||||
.dpcs_enable_dpcs = NULL,
|
||||
.prog_eq_setting = dpcs401_program_eq_setting,
|
||||
.get_txffe = dpcs401_get_txffe,
|
||||
.set_txffe = dpcs401_set_txffe,
|
||||
.set_dio_phy_mux = dcn31_link_encoder_set_dio_phy_mux,
|
||||
.get_hpd_state = dcn10_get_hpd_state,
|
||||
.program_hpd_filter = dcn10_program_hpd_filter,
|
||||
@@ -314,6 +522,12 @@ void dcn401_link_encoder_construct(
|
||||
enc10->base.features.flags.bits.IS_UHBR10_CAPABLE = bp_cap_info.DP_UHBR10_EN;
|
||||
enc10->base.features.flags.bits.IS_UHBR13_5_CAPABLE = bp_cap_info.DP_UHBR13_5_EN;
|
||||
enc10->base.features.flags.bits.IS_UHBR20_CAPABLE = bp_cap_info.DP_UHBR20_EN;
|
||||
enc10->base.features.flags.bits.IS_HDMI_FRL_CAPABLE =
|
||||
bp_cap_info.FRL_8G_EN || bp_cap_info.FRL_10G_EN || bp_cap_info.FRL_12G_EN;
|
||||
enc10->base.features.flags.bits.IS_FRL_8G_CAPABLE = bp_cap_info.FRL_8G_EN;
|
||||
enc10->base.features.flags.bits.IS_FRL_10G_CAPABLE = bp_cap_info.FRL_10G_EN;
|
||||
enc10->base.features.flags.bits.IS_FRL_12G_CAPABLE = bp_cap_info.FRL_12G_EN;
|
||||
enc10->base.txffe_state = 0;
|
||||
} else {
|
||||
DC_LOG_WARNING("%s: Failed to get encoder_cap_info from VBIOS with error code %d!\n",
|
||||
__func__,
|
||||
@@ -322,4 +536,10 @@ void dcn401_link_encoder_construct(
|
||||
if (enc10->base.ctx->dc->debug.hdmi20_disable) {
|
||||
enc10->base.features.flags.bits.HDMI_6GB_EN = 0;
|
||||
}
|
||||
if (enc10->base.ctx->dc->config.force_hdmi21_frl_enc_enable) {
|
||||
enc10->base.features.flags.bits.IS_HDMI_FRL_CAPABLE = 1;
|
||||
enc10->base.features.flags.bits.IS_FRL_8G_CAPABLE = 1;
|
||||
enc10->base.features.flags.bits.IS_FRL_10G_CAPABLE = 1;
|
||||
enc10->base.features.flags.bits.IS_FRL_12G_CAPABLE = 1;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -121,6 +121,22 @@ void dcn401_link_encoder_enable_dp_output(
|
||||
const struct dc_link_settings *link_settings,
|
||||
enum clock_source_id clock_source);
|
||||
|
||||
void dpcs401_program_eq_setting(
|
||||
struct link_encoder *enc,
|
||||
uint8_t FFE_Level,
|
||||
bool de_emphasis_only,
|
||||
bool pre_shoot_only,
|
||||
bool no_ffe,
|
||||
const struct dc_hdmi_frl_link_settings *link_settings);
|
||||
|
||||
void dpcs401_get_txffe(
|
||||
struct link_encoder *enc,
|
||||
struct frl_txffe *lane_settings);
|
||||
|
||||
void dpcs401_set_txffe(
|
||||
struct link_encoder *enc,
|
||||
struct frl_txffe *lane_settings);
|
||||
|
||||
void dcn401_link_encoder_setup(
|
||||
struct link_encoder *enc,
|
||||
enum signal_type signal);
|
||||
|
||||
@@ -93,6 +93,15 @@ static const struct link_encoder_funcs dcn42_link_enc_funcs = {
|
||||
.get_dig_mode = dcn401_get_dig_mode,
|
||||
.is_in_alt_mode = dcn32_link_encoder_is_in_alt_mode,
|
||||
.get_max_link_cap = dcn32_link_encoder_get_max_link_cap,
|
||||
.dpcstx_set_order_invert_18_bit = NULL,
|
||||
.set_phy_source = NULL,
|
||||
.dpcs_initialize_phy = NULL,
|
||||
.dpcs_configure_phypll = NULL,
|
||||
.dpcs_configure_dpcs = NULL,
|
||||
.dpcs_enable_dpcs = NULL,
|
||||
.prog_eq_setting = dpcs401_program_eq_setting,
|
||||
.get_txffe = dpcs401_get_txffe,
|
||||
.set_txffe = dpcs401_set_txffe,
|
||||
.set_dio_phy_mux = dcn31_link_encoder_set_dio_phy_mux,
|
||||
.enable_dpia_output = dcn35_link_encoder_enable_dpia_output,
|
||||
.disable_dpia_output = dcn35_link_encoder_disable_dpia_output,
|
||||
@@ -194,6 +203,12 @@ void dcn42_link_encoder_construct(
|
||||
enc10->base.features.flags.bits.IS_UHBR10_CAPABLE = bp_cap_info.DP_UHBR10_EN;
|
||||
enc10->base.features.flags.bits.IS_UHBR13_5_CAPABLE = bp_cap_info.DP_UHBR13_5_EN;
|
||||
enc10->base.features.flags.bits.IS_UHBR20_CAPABLE = bp_cap_info.DP_UHBR20_EN;
|
||||
enc10->base.features.flags.bits.IS_HDMI_FRL_CAPABLE =
|
||||
bp_cap_info.FRL_8G_EN || bp_cap_info.FRL_10G_EN || bp_cap_info.FRL_12G_EN;
|
||||
enc10->base.features.flags.bits.IS_FRL_8G_CAPABLE = bp_cap_info.FRL_8G_EN;
|
||||
enc10->base.features.flags.bits.IS_FRL_10G_CAPABLE = bp_cap_info.FRL_10G_EN;
|
||||
enc10->base.features.flags.bits.IS_FRL_12G_CAPABLE = bp_cap_info.FRL_12G_EN;
|
||||
enc10->base.txffe_state = 0;
|
||||
} else {
|
||||
DC_LOG_WARNING("%s: Failed to get encoder_cap_info from VBIOS with error code %d!\n",
|
||||
__func__,
|
||||
@@ -202,4 +217,10 @@ void dcn42_link_encoder_construct(
|
||||
if (enc10->base.ctx->dc->debug.hdmi20_disable) {
|
||||
enc10->base.features.flags.bits.HDMI_6GB_EN = 0;
|
||||
}
|
||||
if (enc10->base.ctx->dc->config.force_hdmi21_frl_enc_enable) {
|
||||
enc10->base.features.flags.bits.IS_HDMI_FRL_CAPABLE = 1;
|
||||
enc10->base.features.flags.bits.IS_FRL_8G_CAPABLE = 1;
|
||||
enc10->base.features.flags.bits.IS_FRL_10G_CAPABLE = 1;
|
||||
enc10->base.features.flags.bits.IS_FRL_12G_CAPABLE = 1;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -27,6 +27,7 @@ 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))
|
||||
|
||||
@@ -48,10 +49,19 @@ 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))
|
||||
|
||||
|
||||
@@ -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,938 @@
|
||||
/*
|
||||
* 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 "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 enc3->base.ctx->logger
|
||||
|
||||
#define DTRACE(str, ...) {DC_LOG_HDMI_FRL(str, ##__VA_ARGS__); }
|
||||
|
||||
#define DEBUG_FRL_CAP_CHK 1
|
||||
|
||||
#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
|
||||
|
||||
#define VBI_LINE_0 0
|
||||
|
||||
void hpo_enc3_enable(struct hpo_frl_stream_encoder *enc, int otg_inst)
|
||||
{
|
||||
struct dcn30_hpo_frl_stream_encoder *enc3 = DCN30_HPO_FRL_STRENC_FROM_HPO_FRL_STRENC(enc);
|
||||
|
||||
DC_LOG_HDMI_FRL("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_HDMI_FRL("Exiting [%s]\n", __func__);
|
||||
}
|
||||
|
||||
void hpo_enc3_unblank(struct hpo_frl_stream_encoder *enc, int otg_inst)
|
||||
{
|
||||
(void)otg_inst;
|
||||
struct dcn30_hpo_frl_stream_encoder *enc3 = DCN30_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__);
|
||||
}
|
||||
|
||||
bool hpo_enc3_fifo_odm_enabled(struct hpo_frl_stream_encoder *enc)
|
||||
{
|
||||
struct dcn30_hpo_frl_stream_encoder *enc3 = DCN30_HPO_FRL_STRENC_FROM_HPO_FRL_STRENC(enc);
|
||||
uint32_t fifo_odm_combine_mode;
|
||||
|
||||
REG_GET(HDMI_STREAM_ENC_CLOCK_RAMP_ADJUSTER_FIFO_STATUS_CONTROL0,
|
||||
FIFO_ODM_COMBINE_MODE, &fifo_odm_combine_mode);
|
||||
|
||||
return (fifo_odm_combine_mode != 0);
|
||||
}
|
||||
|
||||
void hpo_enc3_blank(struct hpo_frl_stream_encoder *enc)
|
||||
{
|
||||
struct dcn30_hpo_frl_stream_encoder *enc3 = DCN30_HPO_FRL_STRENC_FROM_HPO_FRL_STRENC(enc);
|
||||
|
||||
/* Disable Clock Ramp Adjuster FIFO */
|
||||
REG_UPDATE_2(HDMI_STREAM_ENC_CLOCK_RAMP_ADJUSTER_FIFO_STATUS_CONTROL0,
|
||||
FIFO_ENABLE, 0,
|
||||
FIFO_ODM_COMBINE_MODE, 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);
|
||||
}
|
||||
|
||||
/* Setup stream encoder in hdmi mode
|
||||
* - Precondition: link is trained
|
||||
*/
|
||||
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)
|
||||
{
|
||||
struct dcn30_hpo_frl_stream_encoder *enc3 = DCN30_HPO_FRL_STRENC_FROM_HPO_FRL_STRENC(enc);
|
||||
uint32_t h_active;
|
||||
uint32_t h_blank;
|
||||
|
||||
DC_LOG_HDMI_FRL("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_PIXEL_ENCODING, 1);
|
||||
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_PIXEL_ENCODING, 2);
|
||||
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_PIXEL_ENCODING, 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;
|
||||
}
|
||||
|
||||
/* Configure ODM combine mode */
|
||||
switch (odm_combine_num_segments) {
|
||||
case 1:
|
||||
REG_UPDATE(HDMI_STREAM_ENC_CLOCK_RAMP_ADJUSTER_FIFO_STATUS_CONTROL0,
|
||||
FIFO_ODM_COMBINE_MODE, 0);
|
||||
|
||||
if (enc3->hpo_se_mask->HDMI_ODM_COMBINE_MODE)
|
||||
REG_UPDATE(HDMI_TB_ENC_PIXEL_FORMAT,
|
||||
HDMI_ODM_COMBINE_MODE, 0);
|
||||
break;
|
||||
case 2:
|
||||
REG_UPDATE(HDMI_STREAM_ENC_CLOCK_RAMP_ADJUSTER_FIFO_STATUS_CONTROL0,
|
||||
FIFO_ODM_COMBINE_MODE, 1);
|
||||
|
||||
if (enc3->hpo_se_mask->HDMI_ODM_COMBINE_MODE)
|
||||
REG_UPDATE(HDMI_TB_ENC_PIXEL_FORMAT,
|
||||
HDMI_ODM_COMBINE_MODE, 1);
|
||||
break;
|
||||
case 4:
|
||||
REG_UPDATE(HDMI_STREAM_ENC_CLOCK_RAMP_ADJUSTER_FIFO_STATUS_CONTROL0,
|
||||
FIFO_ODM_COMBINE_MODE, 3);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
/* 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 */
|
||||
ASSERT(enc->afmt);
|
||||
enc->afmt->funcs->audio_info_immediate_update(enc->afmt);
|
||||
|
||||
/* Select line number on which to send Audio InfoFrame packets */
|
||||
REG_UPDATE(HDMI_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_HDMI_FRL("Exiting [%s]\n", __func__);
|
||||
}
|
||||
|
||||
void hpo_enc3_update_hdmi_info_packets(struct hpo_frl_stream_encoder *enc,
|
||||
const struct encoder_info_frame *info_frame)
|
||||
{
|
||||
struct dcn30_hpo_frl_stream_encoder *enc3 = DCN30_HPO_FRL_STRENC_FROM_HPO_FRL_STRENC(enc);
|
||||
|
||||
hpo_enc3_update_hdmi_info_packet(enc3, 0, &info_frame->avi);
|
||||
hpo_enc3_update_hdmi_info_packet(enc3, 1, &info_frame->vendor);
|
||||
hpo_enc3_update_hdmi_info_packet(enc3, 2, &info_frame->gamut);
|
||||
hpo_enc3_update_hdmi_info_packet(enc3, 3, &info_frame->spd);
|
||||
hpo_enc3_update_hdmi_info_packet(enc3, 4, &info_frame->hdrsmd);
|
||||
|
||||
/* 5-10 used by dsc */
|
||||
hpo_enc3_update_hdmi_info_packet(enc3, 11, &info_frame->hfvsif);
|
||||
hpo_enc3_update_hdmi_info_packet(enc3, 12, &info_frame->vtem);
|
||||
}
|
||||
|
||||
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)
|
||||
{
|
||||
uint32_t cont, send, line;
|
||||
|
||||
if (info_packet->valid) {
|
||||
enc3->base.vpg->funcs->update_generic_info_packet(
|
||||
enc3->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_enc3_stop_hdmi_info_packets(
|
||||
struct hpo_frl_stream_encoder *enc)
|
||||
{
|
||||
struct dcn30_hpo_frl_stream_encoder *enc3 = DCN30_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}
|
||||
};
|
||||
|
||||
static void 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_enc3_setup_hdmi_audio(
|
||||
struct hpo_frl_stream_encoder *enc,
|
||||
const struct audio_crtc_info *crtc_info)
|
||||
{
|
||||
struct dcn30_hpo_frl_stream_encoder *enc3 = DCN30_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 */
|
||||
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_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)
|
||||
{
|
||||
hpo_enc3_setup_hdmi_audio(enc, audio_crtc_info);
|
||||
ASSERT (enc->afmt);
|
||||
enc->afmt->funcs->se_audio_setup(enc->afmt, az_inst, info);
|
||||
}
|
||||
|
||||
void hpo_enc3_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_enc3_audio_mute_control(
|
||||
struct hpo_frl_stream_encoder *enc,
|
||||
bool mute)
|
||||
{
|
||||
ASSERT (enc->afmt);
|
||||
enc->afmt->funcs->audio_mute_control(enc->afmt, mute);
|
||||
}
|
||||
|
||||
void enc3_stream_encoder_set_avmute(
|
||||
struct hpo_frl_stream_encoder *enc,
|
||||
bool enable)
|
||||
{
|
||||
struct dcn30_hpo_frl_stream_encoder *enc3 = DCN30_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);
|
||||
}
|
||||
|
||||
static enum frl_cap_chk_result frl_cap_chk_uncompressed(
|
||||
struct hpo_frl_stream_encoder *enc,
|
||||
struct frl_cap_chk_params *params,
|
||||
struct frl_cap_chk_intermediates *inter)
|
||||
{
|
||||
int res;
|
||||
DC_FP_START();
|
||||
res = frl_fpu_cap_chk_uncompressed(enc, params, inter);
|
||||
DC_FP_END();
|
||||
return res;
|
||||
}
|
||||
|
||||
static enum frl_cap_chk_result frl_cap_chk_compressed(
|
||||
struct hpo_frl_stream_encoder *enc,
|
||||
struct frl_cap_chk_params *params,
|
||||
struct frl_cap_chk_intermediates *inter)
|
||||
{
|
||||
int res;
|
||||
DC_FP_START();
|
||||
res = frl_fpu_cap_chk_compressed(enc, params, inter);
|
||||
DC_FP_END();
|
||||
return res;
|
||||
}
|
||||
|
||||
static bool hpo_enc3_frl_cap_chk(
|
||||
struct hpo_frl_stream_encoder *enc,
|
||||
struct frl_cap_chk_params *params)
|
||||
{
|
||||
struct frl_cap_chk_intermediates inter;
|
||||
enum frl_cap_chk_result res;
|
||||
|
||||
if (params->compressed)
|
||||
res = frl_cap_chk_compressed(enc, params, &inter);
|
||||
else
|
||||
res = frl_cap_chk_uncompressed(enc, params, &inter);
|
||||
|
||||
return (res == FRL_CAP_CHK_OK);
|
||||
}
|
||||
|
||||
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)
|
||||
{
|
||||
struct frl_cap_chk_params frl_params = {0};
|
||||
bool frl_check_res = false;
|
||||
|
||||
/* Set inputs for FRL check */
|
||||
frl_params.lanes = frl_link_settings->frl_num_lanes;
|
||||
DC_FP_START();
|
||||
hpo_fpu_enc3_validate_hdmi_frl_output_link(enc,
|
||||
frl_link_settings,
|
||||
&frl_params,
|
||||
timing,
|
||||
dsc_max_rate);
|
||||
DC_FP_END();
|
||||
|
||||
if (timing->display_color_depth == COLOR_DEPTH_888)
|
||||
frl_params.bpc = 8;
|
||||
else if (timing->display_color_depth == COLOR_DEPTH_101010)
|
||||
frl_params.bpc = 10;
|
||||
else
|
||||
frl_params.bpc = 12;
|
||||
|
||||
switch (timing->hdmi_vic) {
|
||||
case 1:
|
||||
frl_params.vic = 95;
|
||||
break;
|
||||
case 2:
|
||||
frl_params.vic = 94;
|
||||
break;
|
||||
case 3:
|
||||
frl_params.vic = 93;
|
||||
break;
|
||||
case 4:
|
||||
frl_params.vic = 98;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
if (timing->pixel_encoding == PIXEL_ENCODING_YCBCR420)
|
||||
frl_params.pixel_encoding = HDMI_FRL_PIXEL_ENCODING_420;
|
||||
else if (timing->pixel_encoding == PIXEL_ENCODING_YCBCR422)
|
||||
frl_params.pixel_encoding = HDMI_FRL_PIXEL_ENCODING_422;
|
||||
else
|
||||
frl_params.pixel_encoding = HDMI_FRL_PIXEL_ENCODING_444;
|
||||
/* Audio parameters */
|
||||
/* TODO: set Audio parameters */
|
||||
|
||||
if (audio->audio_packet_type == 2) {
|
||||
if (audio->max_channel_count <= 2
|
||||
|| (timing->v_addressable + timing->v_border_top + timing->v_border_bottom) <= 576)
|
||||
frl_params.layout = 0;
|
||||
else
|
||||
frl_params.layout = 1;
|
||||
|
||||
}
|
||||
|
||||
/* Check HDMI FRL Capacity and compute borrow parameters */
|
||||
frl_check_res = hpo_enc3_frl_cap_chk(enc, &frl_params);
|
||||
/* Save borrow parameters and average tribyte rate (for capture sideband) */
|
||||
if (frl_check_res) {
|
||||
frl_link_settings->borrow_params.audio_packets_line =
|
||||
frl_params.borrow_params.audio_packets_line;
|
||||
frl_link_settings->borrow_params.hc_active_target =
|
||||
frl_params.borrow_params.hc_active_target;
|
||||
frl_link_settings->borrow_params.hc_blank_target =
|
||||
frl_params.borrow_params.hc_blank_target;
|
||||
frl_link_settings->borrow_params.borrow_mode =
|
||||
(unsigned int) frl_params.borrow_params.borrow_mode;
|
||||
frl_link_settings->average_tribyte_rate = frl_params.average_tribyte_rate;
|
||||
}
|
||||
|
||||
return frl_check_res;
|
||||
}
|
||||
|
||||
void hpo_enc3_read_state(
|
||||
struct hpo_frl_stream_encoder *enc,
|
||||
struct hpo_frl_stream_encoder_state *state)
|
||||
{
|
||||
int pixel_encoding;
|
||||
int color_depth;
|
||||
int odm_combine;
|
||||
struct dcn30_hpo_frl_stream_encoder *enc3 = DCN30_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;
|
||||
}
|
||||
|
||||
/* 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_enc3_set_dynamic_metadata(struct hpo_frl_stream_encoder *enc,
|
||||
bool enable_dme,
|
||||
uint32_t hubp_requestor_id,
|
||||
enum dynamic_metadata_mode dmdata_mode)
|
||||
{
|
||||
struct dcn30_hpo_frl_stream_encoder *enc3 = DCN30_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 dcn30_str_enc_funcs = {
|
||||
.hdmi_frl_enable = hpo_enc3_enable,
|
||||
.hdmi_frl_unblank = hpo_enc3_unblank,
|
||||
.hdmi_frl_blank = hpo_enc3_blank,
|
||||
.hdmi_frl_set_stream_attribute = hpo_enc3_set_hdmi_stream_attribute,
|
||||
.update_hdmi_info_packets = hpo_enc3_update_hdmi_info_packets,
|
||||
.stop_hdmi_info_packets = hpo_enc3_stop_hdmi_info_packets,
|
||||
.audio_mute_control = hpo_enc3_audio_mute_control,
|
||||
.hdmi_audio_setup = hpo_enc3_hdmi_audio_setup,
|
||||
.hdmi_audio_disable = hpo_enc3_hdmi_audio_disable,
|
||||
.set_avmute = enc3_stream_encoder_set_avmute,
|
||||
.validate_hdmi_frl_output = hpo_enc3_validate_hdmi_frl_output,
|
||||
.read_state = hpo_enc3_read_state,
|
||||
.set_dynamic_metadata = hpo_enc3_set_dynamic_metadata,
|
||||
.hdmi_frl_fifo_odm_enabled = hpo_enc3_fifo_odm_enabled,
|
||||
};
|
||||
|
||||
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)
|
||||
{
|
||||
enc3->base.funcs = &dcn30_str_enc_funcs;
|
||||
enc3->base.ctx = ctx;
|
||||
enc3->base.id = eng_id;
|
||||
enc3->base.bp = bp;
|
||||
enc3->base.vpg = vpg;
|
||||
enc3->base.afmt = afmt;
|
||||
enc3->regs = regs;
|
||||
enc3->hpo_se_shift = hpo_se_shift;
|
||||
enc3->hpo_se_mask = hpo_se_mask;
|
||||
enc3->base.stream_enc_inst = vpg->inst;
|
||||
}
|
||||
@@ -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,906 @@
|
||||
/*
|
||||
* 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)
|
||||
{
|
||||
int pixel_encoding;
|
||||
int 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,
|
||||
.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,206 @@
|
||||
// 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,
|
||||
.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__ */
|
||||
@@ -263,6 +263,7 @@ void opp1_set_dyn_expansion(
|
||||
/*00 - 10-bit -> 12-bit dynamic expansion*/
|
||||
/*01 - 8-bit -> 12-bit dynamic expansion*/
|
||||
if (signal == SIGNAL_TYPE_HDMI_TYPE_A ||
|
||||
signal == SIGNAL_TYPE_HDMI_FRL ||
|
||||
signal == SIGNAL_TYPE_DISPLAY_PORT ||
|
||||
signal == SIGNAL_TYPE_DISPLAY_PORT_MST ||
|
||||
signal == SIGNAL_TYPE_VIRTUAL) {
|
||||
|
||||
@@ -266,6 +266,7 @@
|
||||
|
||||
struct dcn_optc_registers {
|
||||
OPTC_REG_VARIABLE_LIST_DCN;
|
||||
uint32_t OTG_DRR_V_TOTAL_REACH_RANGE;
|
||||
OPTC_REG_VARIABLE_LIST_DCN42;
|
||||
};
|
||||
|
||||
@@ -595,7 +596,9 @@ struct dcn_optc_registers {
|
||||
type MANUAL_FLOW_CONTROL;\
|
||||
type MANUAL_FLOW_CONTROL_SEL;
|
||||
|
||||
#define V_TOTAL_REGS(type)
|
||||
#define V_TOTAL_REGS(type) \
|
||||
type OTG_DRR_V_TOTAL_REACH_LOWER_RANGE;\
|
||||
type OTG_DRR_V_TOTAL_REACH_UPPER_RANGE;
|
||||
|
||||
#define TG_REG_FIELD_LIST(type) \
|
||||
TG_REG_FIELD_LIST_DCN1_0(type)\
|
||||
|
||||
@@ -28,7 +28,9 @@
|
||||
|
||||
#include "dcn20/dcn20_optc.h"
|
||||
|
||||
#define V_TOTAL_REGS_DCN30_SRI(inst)
|
||||
#define V_TOTAL_REGS_DCN30_SRI(inst) \
|
||||
SRI(OTG_V_TOTAL_MID, OTG, inst),\
|
||||
SRI(OTG_DRR_V_TOTAL_REACH_RANGE, OTG, inst),
|
||||
|
||||
#define OPTC_COMMON_REG_LIST_DCN3_BASE(inst) \
|
||||
SRI(OTG_VSTARTUP_PARAM, OTG, inst),\
|
||||
@@ -112,7 +114,9 @@
|
||||
SR(DWB_SOURCE_SELECT),\
|
||||
SRI(OTG_PIPE_UPDATE_STATUS, OTG, inst)
|
||||
|
||||
#define DCN30_VTOTAL_REGS_SF(mask_sh)
|
||||
#define DCN30_VTOTAL_REGS_SF(mask_sh)\
|
||||
SF(OTG0_OTG_DRR_V_TOTAL_REACH_RANGE, OTG_DRR_V_TOTAL_REACH_LOWER_RANGE, mask_sh),\
|
||||
SF(OTG0_OTG_DRR_V_TOTAL_REACH_RANGE, OTG_DRR_V_TOTAL_REACH_UPPER_RANGE, mask_sh),
|
||||
|
||||
#define OPTC_COMMON_MASK_SH_LIST_DCN3_BASE(mask_sh)\
|
||||
SF(OTG0_OTG_VSTARTUP_PARAM, VSTARTUP_START, mask_sh),\
|
||||
|
||||
@@ -320,6 +320,8 @@ void optc31_read_reg_state(struct timing_generator *optc, struct dcn_optc_reg_st
|
||||
{
|
||||
struct optc *optc1 = DCN10TG_FROM_TG(optc);
|
||||
|
||||
optc_reg_state->otg_drr_v_total_reach_range = REG_READ(OTG_DRR_V_TOTAL_REACH_RANGE);
|
||||
|
||||
optc_reg_state->optc_bytes_per_pixel = REG_READ(OPTC_BYTES_PER_PIXEL);
|
||||
optc_reg_state->optc_data_format_control = REG_READ(OPTC_DATA_FORMAT_CONTROL);
|
||||
optc_reg_state->optc_data_source_select = REG_READ(OPTC_DATA_SOURCE_SELECT);
|
||||
|
||||
@@ -378,6 +378,8 @@ void optc401_set_out_mux(struct timing_generator *optc, enum otg_out_mux_dest de
|
||||
01 - OTG_CONTROL_OTG_OUT_MUX_1 : Reserved.
|
||||
02 - OTG_CONTROL_OTG_OUT_MUX_2 : Connects to HPO.
|
||||
*/
|
||||
if (dest == OUT_MUX_HPO_FRL)
|
||||
dest = OUT_MUX_HPO_DP;
|
||||
REG_UPDATE(OTG_CONTROL, OTG_OUT_MUX, dest);
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user