Commit d76b12da authored by Fangzhi Zuo's avatar Fangzhi Zuo Committed by Alex Deucher

drm/amd/display: Add DP 2.0 DCCG

HW Blocks:

        +--------+  +-----+  +------+
        |  OPTC  |  | HDA |  | HUBP |
        +--------+  +-----+  +------+
            |          |        |
            |          |        |
    HPO ====|==========|========|====
     |      |          v        |
     |      |       +-----+     |
     |      |       | APG |     |
     |      |       +-----+     |
     |      |          |        |
     |      v          v        v
     |     +---------------------+
     |     |  HPO Stream Encoder |
     |     +---------------------+
     |                 |
     |                 v
     |      +--------------------+
     |      |  HPO Link Encoder  |
     |      +--------------------+
     |                 |
     v  ===============|=============
                       v
              +------------------+
              |  DIO Output Mux  |
              +------------------+
                       |
                       v
                    +-----+
                    | PHY |
                    +-----+
                       | PHYD32CLK[0]
                       v
                    +------+
                    | DCCG |
                    +------+
                       |
                       v
                   SYMCLK32
Signed-off-by: default avatarFangzhi Zuo <Jerry.Zuo@amd.com>
Reviewed-by: default avatarNicholas Kazlauskas <Nicholas.Kazlauskas@amd.com>
Signed-off-by: default avatarAlex Deucher <alexander.deucher@amd.com>
parent 3bc8d921
......@@ -42,6 +42,155 @@
#define DC_LOGGER \
dccg->ctx->logger
void dccg31_set_dpstreamclk(
struct dccg *dccg,
enum hdmistreamclk_source src,
int otg_inst)
{
struct dcn_dccg *dccg_dcn = TO_DCN_DCCG(dccg);
/* enabled to select one of the DTBCLKs for pipe */
switch (otg_inst) {
case 0:
REG_UPDATE(DPSTREAMCLK_CNTL,
DPSTREAMCLK_PIPE0_EN, (src == REFCLK) ? 0 : 1);
break;
case 1:
REG_UPDATE(DPSTREAMCLK_CNTL,
DPSTREAMCLK_PIPE1_EN, (src == REFCLK) ? 0 : 1);
break;
case 2:
REG_UPDATE(DPSTREAMCLK_CNTL,
DPSTREAMCLK_PIPE2_EN, (src == REFCLK) ? 0 : 1);
break;
case 3:
REG_UPDATE(DPSTREAMCLK_CNTL,
DPSTREAMCLK_PIPE3_EN, (src == REFCLK) ? 0 : 1);
break;
default:
BREAK_TO_DEBUGGER();
return;
}
}
void dccg31_enable_symclk32_se(
struct dccg *dccg,
int hpo_se_inst,
enum phyd32clk_clock_source phyd32clk)
{
struct dcn_dccg *dccg_dcn = TO_DCN_DCCG(dccg);
/* select one of the PHYD32CLKs as the source for symclk32_se */
switch (hpo_se_inst) {
case 0:
REG_UPDATE_2(SYMCLK32_SE_CNTL,
SYMCLK32_SE0_SRC_SEL, phyd32clk,
SYMCLK32_SE0_EN, 1);
break;
case 1:
REG_UPDATE_2(SYMCLK32_SE_CNTL,
SYMCLK32_SE1_SRC_SEL, phyd32clk,
SYMCLK32_SE1_EN, 1);
break;
case 2:
REG_UPDATE_2(SYMCLK32_SE_CNTL,
SYMCLK32_SE2_SRC_SEL, phyd32clk,
SYMCLK32_SE2_EN, 1);
break;
case 3:
REG_UPDATE_2(SYMCLK32_SE_CNTL,
SYMCLK32_SE3_SRC_SEL, phyd32clk,
SYMCLK32_SE3_EN, 1);
break;
default:
BREAK_TO_DEBUGGER();
return;
}
}
void dccg31_disable_symclk32_se(
struct dccg *dccg,
int hpo_se_inst)
{
struct dcn_dccg *dccg_dcn = TO_DCN_DCCG(dccg);
/* set refclk as the source for symclk32_se */
switch (hpo_se_inst) {
case 0:
REG_UPDATE_2(SYMCLK32_SE_CNTL,
SYMCLK32_SE0_SRC_SEL, 0,
SYMCLK32_SE0_EN, 0);
break;
case 1:
REG_UPDATE_2(SYMCLK32_SE_CNTL,
SYMCLK32_SE1_SRC_SEL, 0,
SYMCLK32_SE1_EN, 0);
break;
case 2:
REG_UPDATE_2(SYMCLK32_SE_CNTL,
SYMCLK32_SE2_SRC_SEL, 0,
SYMCLK32_SE2_EN, 0);
break;
case 3:
REG_UPDATE_2(SYMCLK32_SE_CNTL,
SYMCLK32_SE3_SRC_SEL, 0,
SYMCLK32_SE3_EN, 0);
break;
default:
BREAK_TO_DEBUGGER();
return;
}
}
void dccg31_enable_symclk32_le(
struct dccg *dccg,
int hpo_le_inst,
enum phyd32clk_clock_source phyd32clk)
{
struct dcn_dccg *dccg_dcn = TO_DCN_DCCG(dccg);
/* select one of the PHYD32CLKs as the source for symclk32_le */
switch (hpo_le_inst) {
case 0:
REG_UPDATE_2(SYMCLK32_LE_CNTL,
SYMCLK32_LE0_SRC_SEL, phyd32clk,
SYMCLK32_LE0_EN, 1);
break;
case 1:
REG_UPDATE_2(SYMCLK32_LE_CNTL,
SYMCLK32_LE1_SRC_SEL, phyd32clk,
SYMCLK32_LE1_EN, 1);
break;
default:
BREAK_TO_DEBUGGER();
return;
}
}
void dccg31_disable_symclk32_le(
struct dccg *dccg,
int hpo_le_inst)
{
struct dcn_dccg *dccg_dcn = TO_DCN_DCCG(dccg);
/* set refclk as the source for symclk32_le */
switch (hpo_le_inst) {
case 0:
REG_UPDATE_2(SYMCLK32_LE_CNTL,
SYMCLK32_LE0_SRC_SEL, 0,
SYMCLK32_LE0_EN, 0);
break;
case 1:
REG_UPDATE_2(SYMCLK32_LE_CNTL,
SYMCLK32_LE1_SRC_SEL, 0,
SYMCLK32_LE1_EN, 0);
break;
default:
BREAK_TO_DEBUGGER();
return;
}
}
void dccg31_set_physymclk(
struct dccg *dccg,
int phy_inst,
......@@ -241,12 +390,25 @@ static void dccg31_set_dispclk_change_mode(
void dccg31_init(struct dccg *dccg)
{
/* Set HPO stream encoder to use refclk to avoid case where PHY is
* disabled and SYMCLK32 for HPO SE is sourced from PHYD32CLK which
* will cause DCN to hang.
*/
dccg31_disable_symclk32_se(dccg, 0);
dccg31_disable_symclk32_se(dccg, 1);
dccg31_disable_symclk32_se(dccg, 2);
dccg31_disable_symclk32_se(dccg, 3);
}
static const struct dccg_funcs dccg31_funcs = {
.update_dpp_dto = dccg2_update_dpp_dto,
.get_dccg_ref_freq = dccg31_get_dccg_ref_freq,
.dccg_init = dccg31_init,
.set_dpstreamclk = dccg31_set_dpstreamclk,
.enable_symclk32_se = dccg31_enable_symclk32_se,
.disable_symclk32_se = dccg31_disable_symclk32_se,
.enable_symclk32_le = dccg31_enable_symclk32_le,
.disable_symclk32_le = dccg31_disable_symclk32_le,
.set_physymclk = dccg31_set_physymclk,
.set_dtbclk_dto = dccg31_set_dtbclk_dto,
.set_audio_dtbclk_dto = dccg31_set_audio_dtbclk_dto,
......
......@@ -130,6 +130,24 @@ struct dccg *dccg31_create(
void dccg31_init(struct dccg *dccg);
void dccg31_enable_symclk32_se(
struct dccg *dccg,
int hpo_se_inst,
enum phyd32clk_clock_source phyd32clk);
void dccg31_disable_symclk32_se(
struct dccg *dccg,
int hpo_se_inst);
void dccg31_enable_symclk32_le(
struct dccg *dccg,
int hpo_le_inst,
enum phyd32clk_clock_source phyd32clk);
void dccg31_disable_symclk32_le(
struct dccg *dccg,
int hpo_le_inst);
void dccg31_set_physymclk(
struct dccg *dccg,
int phy_inst,
......
......@@ -79,7 +79,30 @@ struct dccg_funcs {
void (*otg_drop_pixel)(struct dccg *dccg,
uint32_t otg_inst);
void (*dccg_init)(struct dccg *dccg);
#if defined(CONFIG_DRM_AMD_DC_DCN)
void (*set_dpstreamclk)(
struct dccg *dccg,
enum hdmistreamclk_source src,
int otg_inst);
void (*enable_symclk32_se)(
struct dccg *dccg,
int hpo_se_inst,
enum phyd32clk_clock_source phyd32clk);
void (*disable_symclk32_se)(
struct dccg *dccg,
int hpo_se_inst);
void (*enable_symclk32_le)(
struct dccg *dccg,
int hpo_le_inst,
enum phyd32clk_clock_source phyd32clk);
void (*disable_symclk32_le)(
struct dccg *dccg,
int hpo_le_inst);
#endif
void (*set_physymclk)(
struct dccg *dccg,
int phy_inst,
......
......@@ -100,6 +100,9 @@ enum crc_selection {
enum otg_out_mux_dest {
OUT_MUX_DIO = 0,
#if defined(CONFIG_DRM_AMD_DC_DCN)
OUT_MUX_HPO_DP = 2,
#endif
};
enum h_timing_div_mode {
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment