Attention is currently required from: Hung-Te Lin, Yidi Lin, Yu-Ping Wu.
Hello Yidi Lin,
I'd like you to do a code review. Please visit
https://review.coreboot.org/c/coreboot/+/85949?usp=email
to review the following change.
Change subject: soc/mediatek/mt8196: Add eDP driver ......................................................................
soc/mediatek/mt8196: Add eDP driver
Add eDP driver to adjust training flow and turn off PHY power before PHY configuration to prevent potential link traning failures.
TEST=check edp training pass and show log: EQ training pass BUG=b:343351631
Change-Id: Iccba53f6c6181ca84624c216f9641a2ae9041671 Signed-off-by: Bincai Liu bincai.liu@mediatek.corp-partner.google.com Signed-off-by: Yidi Lin yidilin@chromium.org --- M src/soc/mediatek/common/dp/include/soc/dptx_common.h M src/soc/mediatek/mt8196/Makefile.mk A src/soc/mediatek/mt8196/dp_intf.c A src/soc/mediatek/mt8196/dptx.c A src/soc/mediatek/mt8196/dptx_hal.c M src/soc/mediatek/mt8196/include/soc/addressmap.h A src/soc/mediatek/mt8196/include/soc/dp_intf.h A src/soc/mediatek/mt8196/include/soc/dptx.h A src/soc/mediatek/mt8196/include/soc/dptx_hal.h A src/soc/mediatek/mt8196/include/soc/dptx_reg.h 10 files changed, 1,508 insertions(+), 0 deletions(-)
git pull ssh://review.coreboot.org:29418/coreboot refs/changes/49/85949/1
diff --git a/src/soc/mediatek/common/dp/include/soc/dptx_common.h b/src/soc/mediatek/common/dp/include/soc/dptx_common.h index 1d7e135..97cfc5b 100644 --- a/src/soc/mediatek/common/dp/include/soc/dptx_common.h +++ b/src/soc/mediatek/common/dp/include/soc/dptx_common.h @@ -211,6 +211,7 @@ bool powered; };
+int mtk_edp_enable(void); int mtk_edp_init(struct edid *edid); bool dptx_auxread_dpcd(struct mtk_dp *mtk_dp, u8 cmd, u32 dpcd_addr, size_t length, u8 *rxbuf); diff --git a/src/soc/mediatek/mt8196/Makefile.mk b/src/soc/mediatek/mt8196/Makefile.mk index a287949..88207f1 100644 --- a/src/soc/mediatek/mt8196/Makefile.mk +++ b/src/soc/mediatek/mt8196/Makefile.mk @@ -48,6 +48,8 @@
ramstage-$(CONFIG_ARM64_USE_ARM_TRUSTED_FIRMWARE) += ../common/bl31.c ramstage-y += ../common/dpm_v2.c +ramstage-y += ../common/dp/dptx_common.c ../common/dp/dptx_hal_common.c +ramstage-y += dptx.c dptx_hal.c dp_intf.c ramstage-y += dramc_info.c ramstage-y += ../common/early_init.c ramstage-y += ../common/emi.c @@ -73,6 +75,7 @@
CPPFLAGS_common += -Isrc/soc/mediatek/mt8196/include CPPFLAGS_common += -Isrc/soc/mediatek/common/include +CPPFLAGS_common += -Isrc/soc/mediatek/common/dp/include
MT8196_BLOB_DIR := 3rdparty/blobs/soc/mediatek/mt8196
diff --git a/src/soc/mediatek/mt8196/dp_intf.c b/src/soc/mediatek/mt8196/dp_intf.c new file mode 100644 index 0000000..0cbaeb7 --- /dev/null +++ b/src/soc/mediatek/mt8196/dp_intf.c @@ -0,0 +1,200 @@ +/* SPDX-License-Identifier: GPL-2.0-only OR MIT */ + +#include <console/console.h> +#include <device/mmio.h> +#include <edid.h> +#include <soc/addressmap.h> +#include <soc/dp_intf.h> +#include <soc/pll.h> +#include <soc/spm.h> +#include <types.h> + +static struct mtk_dvo_gs_info mtk_dvo_gs[MTK_DVO_GSL_MAX] = { + [MTK_DVO_FHD_60FPS_1920] = {6880, 511}, + [MTK_DVO_8K_30FPS] = {5255, 3899}, +}; + +static void mtk_dvo_mask(const struct mtk_dvo *dvo, u32 offset, u32 val, u32 mask) +{ + clrsetbits32(dvo->regs + offset, mask, val); +} + +static void mtk_dvo_sw_reset(const struct mtk_dvo *dvo, bool reset) +{ + mtk_dvo_mask(dvo, DVO_RET, reset ? SWRST : 0, SWRST); +} + +static void mtk_dvo_enable(const struct mtk_dvo *dvo) +{ + mtk_dvo_mask(dvo, DVO_EN, EN, EN); +} + +static void mtk_dvo_config_hsync(const struct mtk_dvo *dvo, struct mtk_dvo_sync_param *sync) +{ + mtk_dvo_mask(dvo, DVO_TGEN_H0, sync->sync_width << HSYNC, HFP_MASK << HSYNC); + mtk_dvo_mask(dvo, DVO_TGEN_H0, sync->front_porch << HFP, HFP_MASK << HFP); + mtk_dvo_mask(dvo, DVO_TGEN_H1, (sync->back_porch + sync->sync_width) << HSYNC2ACT, + HFP_MASK << HSYNC2ACT); +} + +static void mtk_dvo_config_vsync(const struct mtk_dvo *dvo, struct mtk_dvo_sync_param *sync, + u32 width_addr, u32 porch_addr) +{ + mtk_dvo_mask(dvo, width_addr, sync->sync_width << VSYNC, HFP_MASK << VSYNC); + mtk_dvo_mask(dvo, width_addr, sync->front_porch << VFP, HFP_MASK << VFP); + mtk_dvo_mask(dvo, porch_addr, (sync->back_porch + sync->sync_width) << VSYNC2ACT, + HFP_MASK << VSYNC2ACT); +} + +static void mtk_dvo_config_vsync_lodd(const struct mtk_dvo *dvo, + struct mtk_dvo_sync_param *sync) +{ + mtk_dvo_config_vsync(dvo, sync, DVO_TGEN_V0, DVO_TGEN_V1); +} + +static void mtk_dvo_config_interface(const struct mtk_dvo *dvo, bool inter) +{ + mtk_dvo_mask(dvo, DVO_CON, inter ? INTL_EN : 0, INTL_EN); +} + +static void mtk_dvo_config_fb_size(const struct mtk_dvo *dvo, u32 width, u32 height) +{ + mtk_dvo_mask(dvo, DVO_SRC_SIZE, width << SRC_HSIZE, PIC_HSIZE_MASK << SRC_HSIZE); + mtk_dvo_mask(dvo, DVO_SRC_SIZE, height << SRC_VSIZE, PIC_HSIZE_MASK << SRC_VSIZE); + + mtk_dvo_mask(dvo, DVO_PIC_SIZE, width << PIC_HSIZE, PIC_HSIZE_MASK << PIC_HSIZE); + mtk_dvo_mask(dvo, DVO_PIC_SIZE, height << PIC_VSIZE, PIC_HSIZE_MASK << PIC_VSIZE); + + mtk_dvo_mask(dvo, DVO_TGEN_H1, (width / 4) << HACT, PIC_HSIZE_MASK << HACT); + mtk_dvo_mask(dvo, DVO_TGEN_V1, height << VACT, PIC_HSIZE_MASK << VACT); +} + +static void mtk_dvo_irq_enable(const struct mtk_dvo *dvo) +{ + mtk_dvo_mask(dvo, DVO_INTEN, INT_VDE_END_EN, INT_VDE_END_EN); +} + +static void mtk_dvo_info_queue_start(const struct mtk_dvo *dvo) +{ + mtk_dvo_mask(dvo, DVO_TGEN_INFOQ_LATENCY, 0, + INFOQ_START_LATENCY_MASK | INFOQ_END_LATENCY_MASK); +} + +static void mtk_dvo_buffer_ctrl(const struct mtk_dvo *dvo) +{ + mtk_dvo_mask(dvo, DVO_BUF_CON0, DISP_BUF_EN, DISP_BUF_EN); + mtk_dvo_mask(dvo, DVO_BUF_CON0, FIFO_UNDERFLOW_DONE_BLOCK, FIFO_UNDERFLOW_DONE_BLOCK); +} + +static void mtk_dvo_trailing_blank_setting(const struct mtk_dvo *dvo) +{ + mtk_dvo_mask(dvo, DVO_TGEN_V_LAST_TRAILING_BLANK, 0x20, V_LAST_TRAILING_BLANK_MASK); + mtk_dvo_mask(dvo, DVO_TGEN_OUTPUT_DELAY_LINE, 0x20, EXT_TG_DLY_LINE_MASK); +} + +static void mtk_dvo_golden_setting(const struct mtk_dvo *dvo) +{ + struct mtk_dvo_gs_info *gs_info = NULL; + + if (dvo->gs_level >= MTK_DVO_GSL_MAX) + return; + + gs_info = &mtk_dvo_gs[MTK_DVO_8K_30FPS]; + + printk(BIOS_INFO, "[eDPTX] gs_level %d sodi %d %d\n", dvo->gs_level, + gs_info->dvo_buf_sodi_high, gs_info->dvo_buf_sodi_low); + + mtk_dvo_mask(dvo, DVO_BUF_SODI_HIGHT, gs_info->dvo_buf_sodi_high, 0xffffffff); + mtk_dvo_mask(dvo, DVO_BUF_SODI_LOW, gs_info->dvo_buf_sodi_low, 0xffffffff); +} + +static void mtk_dvo_shadow_ctrl(const struct mtk_dvo *dvo) +{ + mtk_dvo_mask(dvo, DVO_SHADOW_CTRL, 0, BYPASS_SHADOW); + mtk_dvo_mask(dvo, DVO_SHADOW_CTRL, FORCE_COMMIT, FORCE_COMMIT); +} + +static int mtk_dvo_power_on(const struct mtk_dvo *dvo, const struct edid *edid) +{ + u32 clksrc; + u32 pll_rate; + + if (edid->mode.pixel_clock < 70000) + clksrc = TVDPLL_D16; + else if (edid->mode.pixel_clock < 200000) + clksrc = TVDPLL_D8; + else + clksrc = TVDPLL_D4; + + pll_rate = edid->mode.pixel_clock * 1000 * (1 << (clksrc + 1)); + + mt_pll_set_tvd_pll1_freq(pll_rate / 4); + mt_pll_edp_mux_set_sel(clksrc); + printk(BIOS_INFO, "[eDPTX reg dvo] pll=%u clksrc=%u\n", pll_rate, clksrc); + mtk_dvo_enable(dvo); + + return 0; +} + +static int mtk_dvo_set_display_mode(const struct mtk_dvo *dvo, const struct edid *edid) +{ + struct mtk_dvo_sync_param hsync; + struct mtk_dvo_sync_param vsync_lodd = {0}; + + write32(dvo->regs_mm + MMSYS1_CG_CLR0, 0xFFFFFFFF); + write32(dvo->regs_mm + MMSYS1_CG_CLR1, 0x00040000); + + vsync_lodd.back_porch = + edid->mode.vbl - edid->mode.vso - edid->mode.vspw - edid->mode.vborder; + vsync_lodd.front_porch = edid->mode.vso - edid->mode.vborder; + vsync_lodd.sync_width = edid->mode.vspw; + vsync_lodd.shift_half_line = false; + + hsync.sync_width = edid->mode.hspw / 4; + hsync.back_porch = + (edid->mode.hbl - edid->mode.hso - edid->mode.hspw - edid->mode.hborder) / 4; + hsync.front_porch = (edid->mode.hso - edid->mode.hborder) / 4; + hsync.shift_half_line = false; + + /* Let pll_rate be able to fix the valid range of tvdpll (1G~2GHz) */ + + write32(dvo->regs_ck + CKSYS2_CLK_CFG_3_SET, 0x80000000); + write32(dvo->regs_ck + CKSYS2_CLK_CFG_UPDATE, 0x8000); + + mtk_dvo_sw_reset(dvo, true); + mtk_dvo_irq_enable(dvo); + + mtk_dvo_config_hsync(dvo, &hsync); + mtk_dvo_config_vsync_lodd(dvo, &vsync_lodd); + + mtk_dvo_config_interface(dvo, false); + mtk_dvo_config_fb_size(dvo, edid->mode.ha, edid->mode.va); + + mtk_dvo_info_queue_start(dvo); + mtk_dvo_buffer_ctrl(dvo); + mtk_dvo_trailing_blank_setting(dvo); + + mtk_dvo_golden_setting(dvo); + + mtk_dvo_shadow_ctrl(dvo); + + mtk_dvo_mask(dvo, DVO_OUTPUT_SET, 0x2, OUT_NP_SEL); + mtk_dvo_sw_reset(dvo, false); + + return 0; +} + +const struct mtk_dvo dvo_data = { + .regs = (void *)(DISP_DVO0), + .regs_ck = (void *)(CKSYS_GP2_BASE), + .regs_mm = (void *)(MMSYS1_CONFIG_BASE), +}; + +void dp_intf_config(const struct edid *edid) +{ + const struct mtk_dvo *data = &dvo_data; + + printk(BIOS_INFO, "[eDPTX] dvo begin\n"); + mtk_dvo_power_on(data, edid); + mtk_dvo_set_display_mode(data, edid); +} diff --git a/src/soc/mediatek/mt8196/dptx.c b/src/soc/mediatek/mt8196/dptx.c new file mode 100644 index 0000000..48b5fca --- /dev/null +++ b/src/soc/mediatek/mt8196/dptx.c @@ -0,0 +1,409 @@ +/* SPDX-License-Identifier: GPL-2.0-only OR MIT */ + +#include <commonlib/bsd/helpers.h> +#include <console/console.h> +#include <delay.h> +#include <device/mmio.h> +#include <edid.h> +#include <soc/addressmap.h> +#include <soc/dp_intf.h> +#include <soc/dptx.h> +#include <soc/dptx_hal.h> +#include <soc/dptx_reg.h> + +static void mtk_edp_pattern(struct mtk_dp *mtk_dp, u8 lane_count, u8 pattern) +{ + u8 aux_offset = 0x0; + + switch (pattern) { + case DPTX_PATTERN_TPS1: + aux_offset = DP_TRAINING_PATTERN_1 | DP_LINK_SCRAMBLING_DISABLE; + mtk_edp_hal_phy_set_idle_pattern(mtk_dp, lane_count, false); + mtk_dp_mask(mtk_dp, REG_3400_DP_TRANS_P0, PATTERN1_EN_DP_TRANS_4P_TPS1, + PATTERN_EN_DP_TRANS_4P_MASK); + break; + case DPTX_PATTERN_TPS2: + aux_offset = DP_TRAINING_PATTERN_2 | DP_LINK_SCRAMBLING_DISABLE; + mtk_dp_mask(mtk_dp, REG_3400_DP_TRANS_P0, PATTERN2_EN_DP_TRANS_4P_TPS2, + PATTERN_EN_DP_TRANS_4P_MASK); + break; + case DPTX_PATTERN_TPS3: + aux_offset = DP_TRAINING_PATTERN_3 | DP_LINK_SCRAMBLING_DISABLE; + mtk_dp_mask(mtk_dp, REG_3400_DP_TRANS_P0, PATTERN3_EN_DP_TRANS_4P_TPS3, + PATTERN_EN_DP_TRANS_4P_MASK); + break; + case DPTX_PATTERN_TPS4: + aux_offset = DP_TRAINING_PATTERN_4; + mtk_dp_mask(mtk_dp, REG_3400_DP_TRANS_P0, PATTERN4_EN_DP_TRANS_4P_TPS4, + PATTERN_EN_DP_TRANS_4P_MASK); + break; + default: + mtk_dp_mask(mtk_dp, REG_3400_DP_TRANS_P0, 0x0, PATTERN_EN_DP_TRANS_4P_MASK); + return; + } + + dptx_auxwrite_dpcd(mtk_dp, DP_AUX_NATIVE_WRITE, DPCD_00102, 0x1, &aux_offset); +} + +static void mtk_edp_train_update_swing_pre(struct mtk_dp *mtk_dp, u8 lane_count, + u8 dpcd_adjust_req[2]) +{ + u8 swing[MAX_LANECOUNT]; + u8 preemphasis[MAX_LANECOUNT]; + + for (int lane = 0; lane < lane_count; lane++) { + u8 val; + int index = lane / 2; + int shift = lane % 2 ? DP_ADJUST_VOLTAGE_SWING_LANE1_SHIFT : 0; + u8 swing_value = dpcd_adjust_req[index] >> shift; + + swing[lane] = swing_value & DP_ADJUST_VOLTAGE_SWING_LANE0_MASK; + preemphasis[lane] = swing_value & DP_ADJUST_PRE_EMPHASIS_LANE0_MASK; + preemphasis[lane] >>= DP_ADJUST_PRE_EMPHASIS_LANE0_SHIFT; + val = swing[lane] << DP_TRAIN_VOLTAGE_SWING_SHIFT | + preemphasis[lane] << DP_TRAIN_PRE_EMPHASIS_SHIFT; + + if (swing[lane] == DP_TRAIN_VOLTAGE_SWING_LEVEL_3) + val |= DP_TRAIN_MAX_SWING_REACHED; + if (preemphasis[lane] == 3) + val |= DP_TRAIN_MAX_PRE_EMPHASIS_REACHED; + + dptx_auxwrite_dpcd(mtk_dp, DP_AUX_NATIVE_WRITE, DPCD_00103 + lane, 0x1, &val); + } + + mtk_edp_set_swing_pre_emphasis(mtk_dp, lane_count, swing, preemphasis); +} + +static void dptx_training_changemode(struct mtk_dp *mtk_dp) +{ + dptx_hal_phyd_reset(mtk_dp); + mtk_edp_hal_reset_swing_pre_emphasis(mtk_dp); + + mdelay(2); +} + +static void mtk_edp_train_setting(struct mtk_dp *mtk_dp) +{ + u8 lane_count = 0x0; + u8 dpcd_data; + u8 target_link_rate = mtk_dp->train_info.linkrate; + u8 target_lane_count = mtk_dp->train_info.linklane_count; + + lane_count = target_lane_count | DP_LANE_COUNT_ENHANCED_FRAME_EN; + + dptx_auxwrite_dpcd(mtk_dp, DP_AUX_NATIVE_WRITE, DPCD_00100, 0x1, &target_link_rate); + dptx_auxwrite_dpcd(mtk_dp, DP_AUX_NATIVE_WRITE, DPCD_00101, 0x1, &lane_count); + if (mtk_dp->train_info.sink_ssc_en) { + dpcd_data = DP_SPREAD_AMP_0_5; + dptx_auxwrite_dpcd(mtk_dp, DP_AUX_NATIVE_WRITE, DPCD_00107, 0x1, &dpcd_data); + dptx_hal_ssc_en(mtk_dp, true); + } else { + dpcd_data = 0x0; + dptx_auxwrite_dpcd(mtk_dp, DP_AUX_NATIVE_WRITE, DPCD_00107, 0x1, &dpcd_data); + dptx_hal_ssc_en(mtk_dp, false); + } + dptx_hal_set_txlane(mtk_dp, target_lane_count / 2); + dptx_hal_phy_setting(mtk_dp); + + printk(BIOS_INFO, "Link train target_link_rate = #%x, target_lane_count = #%x\n", + target_link_rate, target_lane_count); +} + +static void drm_dp_dpcd_read_link_status(struct mtk_dp *mtk_dp, u8 status[DP_LINK_STATUS_SIZE]) +{ + dptx_auxread_dpcd(mtk_dp, DP_AUX_NATIVE_READ, DPCD_00202, DP_LINK_STATUS_SIZE, status); +} + +static int mtk_edp_train_cr(struct mtk_dp *mtk_dp, u8 lane_count) +{ + u8 lane_adjust[DP_LANSE_ADJUST_SIZE]; + u8 link_status[DP_LINK_STATUS_SIZE]; + u8 prev_lane_adjust = 0xff; + int train_retries = 0; + int voltage_retries = 0; + u8 buff = 0x0; + + mtk_edp_pattern(mtk_dp, lane_count, DPTX_PATTERN_TPS1); + + /* In DP spec 1.4, the retry count of CR is defined as 10. */ + do { + train_retries++; + if (!dptx_hal_hpd_high(mtk_dp)) { + mtk_edp_pattern(mtk_dp, lane_count, DPTX_PATTERN_UNKNOWN); + return -ENODEV; + } + + dptx_auxread_dpcd(mtk_dp, DP_AUX_NATIVE_READ, DPCD_00206, sizeof(lane_adjust), + lane_adjust); + printk(BIOS_DEBUG, "[aux_read] dpcd206 lane_adjust[0]=#%x\n", lane_adjust[0]); + printk(BIOS_DEBUG, "[aux_read] dpcd207 lane_adjust[1]=#%x\n", lane_adjust[1]); + mtk_edp_train_update_swing_pre(mtk_dp, lane_count, lane_adjust); + + dptx_link_train_clock_recovery_delay(mtk_dp->rx_cap); + + /* Check link status from sink device */ + drm_dp_dpcd_read_link_status(mtk_dp, link_status); + if (dptx_clock_recovery_ok(link_status, lane_count)) { + printk(BIOS_INFO, "Link train CR pass\n"); + return 0; + } + + /* + * In DP spec 1.4, if current voltage level is the same + * with previous voltage level, we need to retry 5 times. + */ + if (prev_lane_adjust == link_status[4]) { + voltage_retries++; + /* + * Condition of CR fail: + * 1. Failed to pass CR using the same voltage + * level over five times. + * 2. Failed to pass CR when the current voltage + * level is the same with previous voltage + * level and reach max voltage level (3). + */ + if (voltage_retries > MTK_DP_TRAIN_VOLTAGE_LEVEL_RETRY || + (prev_lane_adjust & DP_ADJUST_VOLTAGE_SWING_LANE0_MASK) == 3) { + printk(BIOS_INFO, "Link train CR fail\n"); + break; + } + } else { + /* + * If the voltage level is changed, we need to + * re-calculate this retry count. + */ + voltage_retries = 0; + } + prev_lane_adjust = link_status[4]; + printk(BIOS_INFO, "CR training retries %d\n", voltage_retries); + } while (train_retries < MTK_DP_TRAIN_DOWNSCALE_RETRY); + + /* Failed to train CR, and disable pattern. */ + buff = DP_TRAINING_PATTERN_DISABLE; + dptx_auxwrite_dpcd(mtk_dp, DP_AUX_NATIVE_WRITE, DPCD_00102, 0x1, &buff); + mtk_edp_pattern(mtk_dp, lane_count, DPTX_PATTERN_UNKNOWN); + + return -ETIMEDOUT; +} + +static int mtk_edp_train_eq(struct mtk_dp *mtk_dp, u8 lane_count) +{ + u8 lane_adjust[2]; + u8 link_status[DP_LINK_STATUS_SIZE]; + int train_retries = 0; + u8 buff = 0x0; + + if (mtk_dp->train_info.tps4) + mtk_edp_pattern(mtk_dp, lane_count, DPTX_PATTERN_TPS4); + else if (mtk_dp->train_info.tps3) + mtk_edp_pattern(mtk_dp, lane_count, DPTX_PATTERN_TPS3); + else + mtk_edp_pattern(mtk_dp, lane_count, DPTX_PATTERN_TPS2); + + do { + train_retries++; + if (!dptx_hal_hpd_high(mtk_dp)) { + mtk_edp_pattern(mtk_dp, lane_count, DPTX_PATTERN_UNKNOWN); + return -ENODEV; + } + + dptx_auxread_dpcd(mtk_dp, DP_AUX_NATIVE_READ, DPCD_00206, sizeof(lane_adjust), + lane_adjust); + printk(BIOS_DEBUG, "[aux_read] dpcd206 lane_adjust[0]=#%x\n", lane_adjust[0]); + printk(BIOS_DEBUG, "[aux_read] dpcd207 lane_adjust[1]=#%x\n", lane_adjust[1]); + mtk_edp_train_update_swing_pre(mtk_dp, lane_count, lane_adjust); + + dptx_link_train_channel_eq_delay(mtk_dp->rx_cap); + + /* check link status from sink device */ + drm_dp_dpcd_read_link_status(mtk_dp, link_status); + if (dptx_channel_eq_ok(link_status, lane_count)) { + printk(BIOS_DEBUG, "Link train EQ pass\n"); + + /* Training done, and disable pattern. */ + buff = DP_TRAINING_PATTERN_DISABLE; + dptx_auxwrite_dpcd(mtk_dp, DP_AUX_NATIVE_WRITE, DPCD_00102, 0x1, &buff); + mtk_edp_pattern(mtk_dp, lane_count, DPTX_PATTERN_UNKNOWN); + return 0; + } + printk(BIOS_INFO, "Link train EQ fail retry:%d\n", train_retries); + } while (train_retries < MTK_DP_TRAIN_DOWNSCALE_RETRY); + + /* Failed to train EQ, and disable pattern. */ + buff = DP_TRAINING_PATTERN_DISABLE; + dptx_auxwrite_dpcd(mtk_dp, DP_AUX_NATIVE_WRITE, DPCD_00102, 0x1, &buff); + mtk_edp_pattern(mtk_dp, lane_count, DPTX_PATTERN_UNKNOWN); + + return -ETIMEDOUT; +} + +static int dptx_set_trainingstart(struct mtk_dp *mtk_dp) +{ + u8 lanecount; + u8 linkrate; + u8 buffer; + u8 train_limit; + u8 max_linkrate; + int ret; + + buffer = 0x1; + dptx_auxwrite_dpcd(mtk_dp, DP_AUX_NATIVE_WRITE, DPCD_00600, 0x1, &buffer); + + linkrate = mtk_dp->rx_cap[1]; + lanecount = mtk_dp->rx_cap[2] & 0x1f; + + printk(BIOS_INFO, "RX support linkrate = %#x, lanecount = %#x\n", linkrate, lanecount); + + mtk_dp->train_info.linkrate = (linkrate >= mtk_dp->train_info.sys_max_linkrate) ? + mtk_dp->train_info.sys_max_linkrate : linkrate; + mtk_dp->train_info.linklane_count = MIN(lanecount, MAX_LANECOUNT); + + if (mtk_dp->train_info.sink_extcap_en) + dptx_auxread_dpcd(mtk_dp, DP_AUX_NATIVE_READ, DPCD_02002, 0x1, &buffer); + else + dptx_auxread_dpcd(mtk_dp, DP_AUX_NATIVE_READ, DPCD_00200, 0x1, &buffer); + + if ((buffer & 0xbf) != 0) + mtk_dp->train_info.sink_count_num = buffer & 0xbf; + + linkrate = mtk_dp->train_info.linkrate; + lanecount = mtk_dp->train_info.linklane_count; + + dptx_hal_setscramble(mtk_dp, false); + switch (linkrate) { + case DP_LINKRATE_RBR: + case DP_LINKRATE_HBR: + case DP_LINKRATE_HBR2: + case DP_LINKRATE_HBR3: + break; + default: + mtk_dp->train_info.linkrate = DP_LINKRATE_HBR3; + break; + }; + + max_linkrate = mtk_dp->train_info.linkrate; + printk(BIOS_INFO, "[eDPTX] linkrate = %#x, lanecount = %#x\n", linkrate, lanecount); + for (train_limit = 6; train_limit > 0; train_limit--) { + dptx_training_changemode(mtk_dp); + + mtk_edp_train_setting(mtk_dp); + ret = mtk_edp_train_cr(mtk_dp, lanecount); + if (ret == -ENODEV) { + return ret; + } else if (ret) { + /* Reduce link rate */ + switch (linkrate) { + case DP_LINKRATE_RBR: + lanecount = lanecount / 2; + linkrate = max_linkrate; + if (lanecount == 0) + return -EIO; + break; + case DP_LINKRATE_HBR: + linkrate = DP_LINKRATE_RBR; + break; + case DP_LINKRATE_HBR2: + linkrate = DP_LINKRATE_HBR; + break; + case DP_LINKRATE_HBR3: + linkrate = DP_LINKRATE_HBR2; + break; + default: + return -EINVAL; + } + continue; + } + ret = mtk_edp_train_eq(mtk_dp, lanecount); + if (ret == -ENODEV) { + return ret; + } else if (ret) { + /* Reduce lane count */ + if (lanecount == 0) + return -EIO; + lanecount /= 2; + continue; + } + printk(BIOS_INFO, "[eDPTX] EQ training pass\n"); + /* If we can run to this, training is done. */ + break; + } + + if (train_limit == 0) + return -ETIMEDOUT; + + mtk_dp->train_info.linkrate = linkrate; + mtk_dp->train_info.linklane_count = lanecount; + /* + * After training done, we need to output normal stream instead of TPS, + * so we need to enable scramble. + */ + dptx_hal_setscramble(mtk_dp, true); + dptx_hal_set_ef_mode(mtk_dp, ENABLE_DPTX_EF_MODE); + + printk(BIOS_INFO, "%s: done\n", __func__); + + return 0; +} + +static void dptx_init_port(struct mtk_dp *mtk_dp) +{ + dptx_hal_phy_setidlepattern(mtk_dp, true); + dptx_hal_init_setting(mtk_dp); + dptx_hal_aux_setting(mtk_dp); + dptx_hal_digital_setting(mtk_dp); + dptx_hal_phy_init(mtk_dp); + dptx_hal_phy_setting(mtk_dp); + dptx_hal_hpd_detect_setting(mtk_dp); + + dptx_hal_digital_swreset(mtk_dp); + + dptx_hal_analog_power_en(mtk_dp, true); + dptx_hal_hpd_int_en(mtk_dp, true); +} + +static struct mtk_dp *edp; + +int mtk_edp_init(struct edid *edid) +{ + static struct mtk_dp mtk_edp; + printk(BIOS_INFO, "[eDPTX] begin\n"); + + write32p(EDP_CLK_BASE + DISP_EDPTX_PWR_CON, 0xC2FC224D); + write32p(MMSYS1_CONFIG_BASE + MMSYS1_CG_CLR0, 0xFFFFFFFF); + write32p(MMSYS1_CONFIG_BASE + MMSYS1_CG_CLR1, 0x00040000); + /* add 26m clock */ + write32p(CKSYS_GP2_BASE + CKSYS2_CLK_CFG_3_SET, 0xff000000); + write32p(CKSYS_GP2_BASE + CKSYS2_CLK_CFG_UPDATE, 0x8000); + + dptx_init_variable(&mtk_edp); + dptx_init_port(&mtk_edp); + edp = &mtk_edp; + + if (!dptx_hal_hpd_high(&mtk_edp)) { + printk(BIOS_ERR, "HPD is low\n"); + return -1; + } + + dptx_check_sinkcap(&mtk_edp); + + if (dptx_get_edid(&mtk_edp, edid) != 0) { + printk(BIOS_ERR, "Failed to get EDID\n"); + return -1; + } + + dptx_set_trainingstart(&mtk_edp); + dp_intf_config(edid); + dptx_video_config(&mtk_edp); + + return 0; +} + +int mtk_edp_enable(void) +{ + if (!edp) { + printk(BIOS_ERR, "%s: eDP is not initialized\n", __func__); + return -1; + } + dptx_video_enable(edp, true); + return 0; +} diff --git a/src/soc/mediatek/mt8196/dptx_hal.c b/src/soc/mediatek/mt8196/dptx_hal.c new file mode 100644 index 0000000..26da369 --- /dev/null +++ b/src/soc/mediatek/mt8196/dptx_hal.c @@ -0,0 +1,413 @@ +/* SPDX-License-Identifier: GPL-2.0-only OR MIT */ + +#include <console/console.h> +#include <device/mmio.h> +#include <delay.h> +#include <edid.h> +#include <soc/dptx.h> +#include <soc/dptx_hal.h> +#include <soc/dptx_reg.h> +#include <types.h> + +static const int driving_offset[] = { + PHYD_DIG_LAN0_OFFSET + DRIVING_FORCE, + PHYD_DIG_LAN1_OFFSET + DRIVING_FORCE, + PHYD_DIG_LAN2_OFFSET + DRIVING_FORCE, + PHYD_DIG_LAN3_OFFSET + DRIVING_FORCE, +}; + +void dptx_hal_init_setting(struct mtk_dp *mtk_dp) +{ + mtk_dp_mask(mtk_dp, 0x2000, GENMASK(1, 0), GENMASK(1, 0)); + + mtk_dp_mask(mtk_dp, REG_3540_DP_TRANS_P0, BIT(3), BIT(3)); + mtk_dp_mask(mtk_dp, REG_342C_DP_TRANS_P0, 0x68, 0xff); + mtk_dp_mask(mtk_dp, REG_31EC_DP_ENCODER0_P0, BIT(4), BIT(4)); + mtk_dp_mask(mtk_dp, REG_304C_DP_ENCODER0_P0, 0, BIT(8)); + mtk_dp_mask(mtk_dp, REG_304C_DP_ENCODER0_P0, BIT(3), BIT(3)); + + /* default marker */ + mtk_dp_mask(mtk_dp, REG_3F04_DP_ENC_4P_3, 0, 0xFFFF); + mtk_dp_mask(mtk_dp, REG_3F08_DP_ENC_4P_3, BIT(3), BIT(3)); + mtk_dp_mask(mtk_dp, REG_3F0C_DP_ENC_4P_3, BIT(1), BIT(1)); + mtk_dp_mask(mtk_dp, REG_3F10_DP_ENC_4P_3, BIT(3), BIT(3)); + + mtk_dp_mask(mtk_dp, REG_33C0_DP_ENCODER1_P0, 0, 0xf000); + mtk_dp_mask(mtk_dp, REG_33C0_DP_ENCODER1_P0, 0x80, 0x80); + mtk_dp_mask(mtk_dp, REG_33C4_DP_ENCODER1_P0, BIT(5), 0x60); + mtk_dp_mask(mtk_dp, REG_3F28_DP_ENC_4P_3, 10 << 2, 0x3C); + mtk_dp_mask(mtk_dp, DP_TX_TOP_RESET_AND_PROBE, 0x9100FF, 0x9100FF); + + mtk_dp_mask(mtk_dp, MTK_DP_TOP_IRQ_MASK, ENCODER_IRQ_MSK | TRANS_IRQ_MSK, + ENCODER_IRQ_MSK | TRANS_IRQ_MSK); +} + +void dptx_hal_set_color_format(struct mtk_dp *mtk_dp, u8 out_format) +{ + /* MISC0 */ + mtk_dp_mask(mtk_dp, REG_3034_DP_ENCODER0_P0, out_format << DP_TEST_COLOR_FORMAT_SHIFT, + DP_TEST_COLOR_FORMAT_MASK); + mtk_dp_mask(mtk_dp, REG_3034_DP_ENCODER0_P0, BIT(3), BIT(3)); + + switch (out_format) { + case DP_COLOR_FORMAT_RGB_444: + case DP_COLOR_FORMAT_YUV_444: + mtk_dp_mask(mtk_dp, REG_303C_DP_ENCODER0_P0, 0 << 12, GENMASK(14, 12)); + break; + case DP_COLOR_FORMAT_YUV_422: + mtk_dp_mask(mtk_dp, REG_303C_DP_ENCODER0_P0, BIT(12), GENMASK(14, 12)); + break; + case DP_COLOR_FORMAT_YUV_420: + mtk_dp_mask(mtk_dp, REG_303C_DP_ENCODER0_P0, 0x2 << 12, GENMASK(14, 12)); + break; + default: + break; + } +} + +void dptx_hal_settu_setencoder(struct mtk_dp *mtk_dp) +{ + mtk_dp_mask(mtk_dp, REG_303C_DP_ENCODER0_P0, BIT(15), BIT(15)); + DP_WRITE2BYTE(mtk_dp, REG_3040_DP_ENCODER0_P0, 0x2020); + DP_WRITE2BYTE(mtk_dp, REG_3364_DP_ENCODER1_P0, 0x2020); + mtk_dp_mask(mtk_dp, REG_3300_DP_ENCODER1_P0, 0x2 << 8, BIT(9) | BIT(8)); + mtk_dp_mask(mtk_dp, REG_3364_DP_ENCODER1_P0, 0x40 << 8, 0x70 << 8); +} + +bool dptx_hal_hpd_high(struct mtk_dp *mtk_dp) +{ + return mtk_dp_read(mtk_dp, REG_364C_AUX_TX_P0) & BIT(15); +} + +void mtk_edp_phy_set_swing_pre_emphasis(struct mtk_dp *mtk_dp, u8 lane_count, + u8 *swing_val, u8 *pre_emphasis) +{ + if (lane_count >= DPTX_LANE_MAX) { + printk(BIOS_ERR, "Invalid lane number: %d\n", lane_count); + return; + } + for (int i = 0; i < lane_count && i < DPTX_LANE_MAX; ++i) { + mtk_dp_phy_mask(mtk_dp, driving_offset[i], + swing_val[i] << 1 | pre_emphasis[i] << 3, + EDP_TX_LN_VOLT_SWING_VAL_MASK | EDP_TX_LN_PRE_EMPH_VAL_MASK); + printk(BIOS_DEBUG, "lane(%d), set swing(%u), emp(%u)\n", + lane_count, swing_val[i], pre_emphasis[i]); + } +} + + +bool dptx_hal_setswing_preemphasis(struct mtk_dp *mtk_dp, int lane_num, int swing_value, + int preemphasis) +{ + if (lane_num >= DPTX_LANE_MAX) { + printk(BIOS_ERR, "invalid lane number: %d\n", lane_num); + return false; + } + + for (int i = 0; i < lane_num && i < DPTX_LANE_MAX; ++i) { + mtk_dp_phy_mask(mtk_dp, driving_offset[i], + swing_value << 1 | preemphasis << 3, + EDP_TX_LN_VOLT_SWING_VAL_MASK | EDP_TX_LN_PRE_EMPH_VAL_MASK); + printk(BIOS_DEBUG, "lane(%d), set swing(%u), emp(%u)\n", + lane_num, swing_value, preemphasis); + } + mtk_dp_mask(mtk_dp, 0x2000, GENMASK(1, 0), GENMASK(1, 0)); + return true; +} + +void dptx_hal_reset_swing_preemphasis(struct mtk_dp *mtk_dp) +{ + for (int i = 0; i < ARRAY_SIZE(driving_offset); i++) { + mtk_dp_phy_mask(mtk_dp, driving_offset[i], 0, 0x18); + mtk_dp_phy_mask(mtk_dp, driving_offset[i], 0, 0x6); + } +} + +void dptx_hal_hpd_detect_setting(struct mtk_dp *mtk_dp) +{ + mtk_dp_mask(mtk_dp, REG_364C_AUX_TX_P0, HPD_INT_THD_FLDMASK_VAL << 4, + HPD_INT_THD_FLDMASK); +} + +void dptx_hal_phy_init(struct mtk_dp *mtk_dp) +{ + /* edp phy init*/ + mtk_dp_phy_mask(mtk_dp, IPMUX_CONTROL, 0 << EDPTX_DSI_PHYD_SEL_FLDMASK_POS, + EDPTX_DSI_PHYD_SEL_FLDMASK); + + mtk_dp_phy_mask(mtk_dp, PHYD_DIG_GLB_OFFSET + 0x10, BIT(0) | BIT(1) | BIT(2), + BIT(0) | BIT(1) | BIT(2)); + dptx_hal_ssc_en(mtk_dp, false); +} + +void dptx_hal_set_txrate(struct mtk_dp *mtk_dp, int value) +{ + printk(BIOS_INFO, "Link rate = 0x%x\n", value); + switch (value) { + case DP_LINKRATE_RBR: + mtk_dp_phy_write(mtk_dp, 0x143C, 0x1); + break; + case DP_LINKRATE_HBR: + mtk_dp_phy_write(mtk_dp, 0x143C, 0x4); + break; + case DP_LINKRATE_HBR2: + mtk_dp_phy_write(mtk_dp, 0x143C, 0x7); + break; + case DP_LINKRATE_HBR3: + mtk_dp_phy_write(mtk_dp, 0x143C, 0x9); + break; + default: + printk(BIOS_ERR, "Link rate not support(%d)\n", value); + break; + } +} + +void dptx_hal_phy_set_lanes(struct mtk_dp *mtk_dp, u8 lane_count) +{ + for (int i = 0; i < lane_count; i++) + mtk_dp_phy_mask(mtk_dp, PHYD_DIG_GLB_OFFSET + 0x74, BIT(i), BIT(i)); +} + +void dptx_hal_phy_setting(struct mtk_dp *mtk_dp) +{ + u8 link_rate = mtk_dp->train_info.linkrate; + u8 lane_count = mtk_dp->train_info.linklane_count; + + dptx_hal_phy_set_lanes(mtk_dp, lane_count); + dptx_hal_set_txrate(mtk_dp, link_rate); + + /* Turn on phy power after phy configure */ + mtk_dp_mask(mtk_dp, REG_3FF8_DP_ENC_4P_3, PHY_STATE_W_1_DP_ENC_4P_3, + PHY_STATE_W_1_DP_ENC_4P_3_MASK); + mtk_dp_mask(mtk_dp, 0x2000, GENMASK(1, 0), GENMASK(1, 0)); + printk(BIOS_DEBUG, "[eDPTX] DP_PHY_DIG_PLL_CTL_1:%#x\n", + mtk_dp_phy_read(mtk_dp, DP_PHY_DIG_PLL_CTL_1)); +} + +void dptx_hal_ssc_en(struct mtk_dp *mtk_dp, bool enable) +{ + if (enable) { + printk(BIOS_DEBUG, "[eDPTX] enable ssc\n"); + mtk_dp_phy_mask(mtk_dp, DP_PHY_DIG_PLL_CTL_1, BIT(8), BIT(8)); + } else { + printk(BIOS_DEBUG, "[eDPTX] disable ssc\n"); + mtk_dp_phy_mask(mtk_dp, DP_PHY_DIG_PLL_CTL_1, 0x0, BIT(8)); + } + printk(BIOS_DEBUG, "[eDPTX] DP_PHY_DIG_PLL_CTL_1:%#x\n", + mtk_dp_phy_read(mtk_dp, DP_PHY_DIG_PLL_CTL_1)); + + mdelay(1); +} + +void dptx_hal_aux_setting(struct mtk_dp *mtk_dp) +{ + /* Modify timeout threshold = 1595 [12 : 8] */ + mtk_dp_mask(mtk_dp, REG_360C_AUX_TX_P0, 0x1D0C, 0x1fff); + mtk_dp_mask(mtk_dp, REG_3658_AUX_TX_P0, 0, BIT(0)); + /* [0]mtk_dp, REG_aux_tx_ov_en */ + mtk_dp_mask(mtk_dp, REG_36A0_AUX_TX_4P, 0xFFFC, 0xFFFC); + + /* 26M */ + mtk_dp_mask(mtk_dp, REG_3634_AUX_TX_P0, AUX_TX_OVER_SAMPLE_RATE_FOR_26M << 8, + 0xff << 8); + mtk_dp_mask(mtk_dp, REG_3614_AUX_TX_P0, AUX_RX_UI_CNT_THR_AUX_FOR_26M, 0x7f); + + /* Modify, 13 for 26M */ + mtk_dp_mask(mtk_dp, REG_37C8_AUX_TX_P0, MTK_ATOP_EN_AUX_TX_4P, MTK_ATOP_EN_AUX_TX_4P); + /* Disable aux sync_stop detect function */ + mtk_dp_mask(mtk_dp, REG_3690_AUX_TX_P0, RX_REPLY_COMPLETE_MODE_AUX_TX_4P, + RX_REPLY_COMPLETE_MODE_AUX_TX_4P); + + mtk_dp_mask(mtk_dp, REG_367C_AUX_TX_P0, HPD_CONN_THD_AUX_TX_P0_FLDMASK_POS << 6, + HPD_CONN_THD_AUX_TX_P0_FLDMASK); + + mtk_dp_mask(mtk_dp, REG_37A0_AUX_TX_P0, HPD_DISC_THD_AUX_TX_P0_FLDMASK_POS << 4, + HPD_DISC_THD_AUX_TX_P0_FLDMASK); + mtk_dp_mask(mtk_dp, REG_3690_AUX_TX_P0, RX_REPLY_COMPLETE_MODE_AUX_TX_4P, + RX_REPLY_COMPLETE_MODE_AUX_TX_4P); + mtk_dp_mask(mtk_dp, REG_3FF8_DP_ENC_4P_3, XTAL_FREQ_FOR_PSR_DP_ENC_4P_3_VALUE << 9, + XTAL_FREQ_FOR_PSR_DP_ENC_4P_3_MASK); + mtk_dp_mask(mtk_dp, REG_366C_AUX_TX_P0, XTAL_FREQ_DP_TX_AUX_366C_VALUE << 8, + XTAL_FREQ_DP_TX_AUX_366C_MASK); +} + +void dptx_hal_digital_setting(struct mtk_dp *mtk_dp) +{ + mtk_dp_mask(mtk_dp, REG_304C_DP_ENCODER0_P0, 0, VBID_VIDEO_MUTE_DP_ENC0_4P_MASK); + mtk_dp_mask(mtk_dp, REG_3368_DP_ENCODER1_P0, BS2BS_MODE_DP_ENC1_4P_VAL << 12, + 0x3 << 12); + mtk_dp_mask(mtk_dp, REG_3030_DP_ENCODER0_P0, BIT(11), BIT(11)); + + /* dp I-mode enable */ + mtk_dp_mask(mtk_dp, BS2BS_MODE_DP_ENCODER1_P0_FLDMASK, DP_I_MODE_ENABLE, + DP_I_MODE_ENABLE); + mtk_dp_mask(mtk_dp, REG_3030_DP_ENCODER0_P0, 0x3ff, 0x3ff); + mtk_dp_mask(mtk_dp, REG_3028_DP_ENCODER0_P0, 0, BIT(15)); + mtk_dp_mask(mtk_dp, REG_302C_DP_ENCODER0_P0, 0, BIT(15)); + + /* set color format */ + dptx_hal_set_color_format(mtk_dp, DP_COLOR_FORMAT_RGB_444); + + /* set color depth */ + dptx_hal_set_color_depth(mtk_dp, DP_COLOR_DEPTH_8BIT); + + /* reg_bs)symbol_cnt_reset */ + mtk_dp_mask(mtk_dp, REG_3000_DP_ENCODER0_P0, REG_BS_SYMBOL_CNT_RESET, + REG_BS_SYMBOL_CNT_RESET); + mtk_dp_mask(mtk_dp, REG_3004_DP_ENCODER0_P0, BIT(14), BIT(14)); + printk(BIOS_DEBUG, "[eDPTX] REG_3004_DP_ENCODER0_P0:%#x\n", + mtk_dp_read(mtk_dp, REG_3004_DP_ENCODER0_P0)); + + mtk_dp_mask(mtk_dp, REG_3368_DP_ENCODER1_P0, 0x2, BIT(1) | BIT(2)); + mtk_dp_mask(mtk_dp, REG_3368_DP_ENCODER1_P0, BIT(15), BIT(15)); + mtk_dp_mask(mtk_dp, REG_304C_DP_ENCODER0_P0, 0, BIT(8)); + + /* [5:0]video sram start address */ + mtk_dp_mask(mtk_dp, REG_303C_DP_ENCODER0_P0, 0x8, 0x3F); + + /* reg_psr_patgen_avt_en patch */ + mtk_dp_mask(mtk_dp, REG_3F80_DP_ENC_4P_3, 0, PSR_PATGEN_AVT_EN_FLDMASK); + + /* phy D enable */ + mtk_dp_mask(mtk_dp, REG_3FF8_DP_ENC_4P_3, PHY_STATE_W_1_DP_ENC_4P_3, + PHY_STATE_W_1_DP_ENC_4P_3_MASK); + + /* reg_dvo_on_ow_en */ + mtk_dp_mask(mtk_dp, REG_3FF8_DP_ENC_4P_3, DVO_ON_W_1_FLDMASK, DVO_ON_W_1_FLDMASK); + + /* dp tx encoder reset all sw */ + mtk_dp_mask(mtk_dp, REG_3004_DP_ENCODER0_P0, DP_TX_ENCODER_4P_RESET_SW_DP_ENC0_P0, + DP_TX_ENCODER_4P_RESET_SW_DP_ENC0_P0); + printk(BIOS_DEBUG, "[eDPTX] REG_3004_DP_ENCODER0_P0:%#x\n", + mtk_dp_read(mtk_dp, REG_3004_DP_ENCODER0_P0)); + + mtk_dp_mask(mtk_dp, REG_3004_DP_ENCODER0_P0, 0, BIT(9)); + printk(BIOS_DEBUG, "[eDPTX] REG_3004_DP_ENCODER0_P0:%#x\n", + mtk_dp_read(mtk_dp, REG_3004_DP_ENCODER0_P0)); + + mtk_dp_mask(mtk_dp, REG_3FF8_DP_ENC_4P_3, 0xff, 0xff); + + /* Wait for sw reset to complete */ + mdelay(1); +} + +void dptx_hal_digital_swreset(struct mtk_dp *mtk_dp) +{ + printk(BIOS_DEBUG, "[eDPTX] DP_PHY_DIG_TX_CTL_0:%#x\n", + mtk_dp_phy_read(mtk_dp, DP_PHY_DIG_TX_CTL_0)); + mtk_dp_mask(mtk_dp, REG_340C_DP_TRANS_P0, BIT(13), BIT(13)); + mdelay(1); + mtk_dp_mask(mtk_dp, REG_340C_DP_TRANS_P0, 0, BIT(13)); + + mtk_dp_mask(mtk_dp, EDP_TX_TOP_CLKGEN_0, 0x0000000f, 0x0000000f); + printk(BIOS_DEBUG, "[eDPTX] DP_PHY_DIG_TX_CTL_0:%#x\n", + mtk_dp_phy_read(mtk_dp, DP_PHY_DIG_TX_CTL_0)); +} + +void mtk_edp_hal_reset_swing_pre_emphasis(struct mtk_dp *mtk_dp) +{ + mtk_dp_mask(mtk_dp, REG_2004_TOP_SWING_EMP, 0, + DP_TX0_VOLT_SWING_MASK | DP_TX1_VOLT_SWING_MASK | DP_TX2_VOLT_SWING_MASK | + DP_TX3_VOLT_SWING_MASK | DP_TX0_PRE_EMPH_MASK | DP_TX1_PRE_EMPH_MASK | + DP_TX2_PRE_EMPH_MASK | DP_TX3_PRE_EMPH_MASK); +} + +void dptx_hal_phyd_reset(struct mtk_dp *mtk_dp) +{ + u32 val; + + mtk_dp_phy_mask(mtk_dp, DP_PHY_DIG_SW_RST, 0, BIT(0)); + mdelay(100); + mtk_dp_phy_mask(mtk_dp, DP_PHY_DIG_SW_RST, BIT(0), BIT(0)); + + val = mtk_dp_phy_read(mtk_dp, DP_PHY_DIG_TX_CTL_0); + printk(BIOS_DEBUG, "[eDPTX] DP_PHY_DIG_TX_CTL_0:%#x\n", val); + + val = val & 0xf; + printk(BIOS_DEBUG, "[eDPTX] DP_PHY_DIG_TX_CTL_0:%#x\n", val); + + while (val > 0) { + val >>= 1; + mtk_dp_phy_mask(mtk_dp, DP_PHY_DIG_TX_CTL_0, val, 0xf); + printk(BIOS_DEBUG, "[eDPTX] DP_PHY_DIG_TX_CTL_0:%#x\n", val); + } + printk(BIOS_DEBUG, "[eDPTX] DP_PHY_DIG_TX_CTL_0:%#x\n", + mtk_dp_phy_read(mtk_dp, DP_PHY_DIG_TX_CTL_0)); + + dptx_hal_reset_swing_preemphasis(mtk_dp); +} + +void mtk_edp_phy_wait_aux_ldo_ready(struct mtk_dp *mtk_dp) +{ + int retry = WAIT_AUX_READY_RETRY_TIMES; + u32 val; + u32 mask = RGS_BG_CORE_EN_READY_MASK | RGS_AUX_LDO_EN_READY_MASK; + + do { + val = mtk_dp_phy_read(mtk_dp, 0x146c); + if ((val & mask) == mask) + break; + mdelay(100); + } while (retry--); +} + +void dptx_hal_set_txlane(struct mtk_dp *mtk_dp, u8 value) +{ + /* Turn off phy power before phy configure */ + mtk_dp_mask(mtk_dp, REG_3F44_DP_ENC_4P_3, PHY_PWR_STATE_OW_EN_DP_ENC_4P_3, + PHY_PWR_STATE_OW_EN_DP_ENC_4P_3_MASK); + mtk_dp_mask(mtk_dp, REG_3F44_DP_ENC_4P_3, BIAS_POWER_ON, + PHY_PWR_STATE_OW_VALUE_DP_ENC_4P_3_MASK); + mtk_edp_phy_wait_aux_ldo_ready(mtk_dp); + mtk_dp_mask(mtk_dp, REG_3F44_DP_ENC_4P_3, 0 << 2, PHY_PWR_STATE_OW_EN_DP_ENC_4P_3_MASK); + + if (value == 0) + mtk_dp_mask(mtk_dp, REG_35F0_DP_TRANS_P0, 0, BIT(3) | BIT(2)); + else + mtk_dp_mask(mtk_dp, REG_35F0_DP_TRANS_P0, BIT(3), BIT(3) | BIT(2)); + + if ((value << 2) <= UINT8_MAX) { + mtk_dp_mask(mtk_dp, REG_3000_DP_ENCODER0_P0, value, BIT(1) | BIT(0)); + mtk_dp_mask(mtk_dp, REG_34A4_DP_TRANS_P0, value << 2, BIT(3) | BIT(2)); + } else { + printk(BIOS_ERR, "[%s]value << 2 > 0xff\n", __func__); + } +} + +void mtk_edp_set_swing_pre_emphasis(struct mtk_dp *mtk_dp, u8 lane_count, u8 *swing_val, + u8 *pre_emphasis) +{ + for (int lane = 0; lane < lane_count; lane++) + printk(BIOS_INFO, + "Link training lane%d: swing_val = 0x%x, pre-emphasis = 0x%x\n", lane, + swing_val[lane], pre_emphasis[lane]); + + mtk_edp_phy_set_swing_pre_emphasis(mtk_dp, lane_count, swing_val, pre_emphasis); +} + +void mtk_edp_hal_phy_set_idle_pattern(struct mtk_dp *mtk_dp, u8 lane_count, bool enable) +{ + u32 val = 0x0; + + printk(BIOS_INFO, "lane_count: %x idle pattern enable: %d\n", lane_count, enable); + switch (lane_count) { + case 1: + val = POST_MISC_DATA_LANE0_OV_DP_TRANS_4P_MASK; + break; + case 2: + val = POST_MISC_DATA_LANE0_OV_DP_TRANS_4P_MASK | + POST_MISC_DATA_LANE1_OV_DP_TRANS_4P_MASK; + break; + case 4: + val = POST_MISC_DATA_LANE0_OV_DP_TRANS_4P_MASK | + POST_MISC_DATA_LANE1_OV_DP_TRANS_4P_MASK | + POST_MISC_DATA_LANE2_OV_DP_TRANS_4P_MASK | + POST_MISC_DATA_LANE3_OV_DP_TRANS_4P_MASK; + break; + default: + printk(BIOS_ERR, "Set idle pattern failed, lane count %d\n", lane_count); + break; + } + mtk_dp_mask(mtk_dp, REG_3580_DP_TRANS_P0, (enable ? val : 0x0) << 8, + POST_MISC_DATA_LANE_OV_DP_TRANS_4P_MASK); +} diff --git a/src/soc/mediatek/mt8196/include/soc/addressmap.h b/src/soc/mediatek/mt8196/include/soc/addressmap.h index 1ec3c86..d0269ed 100644 --- a/src/soc/mediatek/mt8196/include/soc/addressmap.h +++ b/src/soc/mediatek/mt8196/include/soc/addressmap.h @@ -72,6 +72,7 @@ IOCFG_LT_BASE = IO_PHYS + 0x03000000, IOCFG_LM1_BASE = IO_PHYS + 0x03020000, IOCFG_LM2_BASE = IO_PHYS + 0x03040000, + EDP_PHY_BASE = IO_PHYS + 0x030a0000, MIPITX0_BASE = IO_PHYS + 0x030b0000, IOCFG_LB1_BASE = IO_PHYS + 0x030f0000, IOCFG_LB2_BASE = IO_PHYS + 0x03110000, @@ -193,6 +194,7 @@ OVLSYS_CONFIG_BASE = IO_PHYS + 0x22800000, OVLSYS1_CONFIG_BASE = IO_PHYS + 0x22C00000, DISP_VDISP_AO_CONFIG_BASE = IO_PHYS + 0x2E800000, + EDP_CLK_BASE = IO_PHYS + 0x21B50000, EDP_BASE = IO_PHYS + 0x2EC40000, MFG_TOP_CFG_BASE = MFGSYS_BASE + 0x08500000, MFG_GPUEB_BASE = MFGSYS_BASE + 0x0B000000, diff --git a/src/soc/mediatek/mt8196/include/soc/dp_intf.h b/src/soc/mediatek/mt8196/include/soc/dp_intf.h new file mode 100644 index 0000000..d1ddf75 --- /dev/null +++ b/src/soc/mediatek/mt8196/include/soc/dp_intf.h @@ -0,0 +1,211 @@ +/* SPDX-License-Identifier: GPL-2.0-only OR MIT */ + +#ifndef __SOC_MEDIATEK_MT8196_DP_DP_INTF_H__ +#define __SOC_MEDIATEK_MT8196_DP_DP_INTF_H__ + +#include <edid.h> +#include <soc/addressmap.h> +#include <types.h> + +#define DVO_EN 0x00 +#define EN BIT(0) +#define DVO_FORCE_ON BIT(4) +#define LINK_OFF BIT(8) + +#define MMSYS1_CG_CLR0 0x108 +#define MMSYS1_CG_CLR1 0x118 +#define CKSYS2_CLK_CFG_3_SET 0x48 +#define CKSYS2_CLK_CFG_UPDATE 0x4 +#define DISP_EDPTX_PWR_CON 0x74 + +#define DVO_RET 0x04 +#define SWRST BIT(0) +#define SWRST_SEL BIT(4) + +#define DVO_INTEN 0x08 +#define INT_VFP_START_EN BIT(0) +#define INT_VSYNC_START_EN BIT(1) +#define INT_VSYNC_END_EN BIT(2) +#define INT_VDE_START_EN BIT(3) +#define INT_VDE_END_EN BIT(4) +#define INT_WR_INFOQ_REG_EN BIT(5) +#define INT_TARGET_LINE0_EN BIT(6) +#define INT_TARGET_LINE1_EN BIT(7) +#define INT_TARGET_LINE2_EN BIT(8) +#define INT_TARGET_LINE3_EN BIT(9) +#define INT_WR_INFOQ_START_EN BIT(10) +#define INT_WR_INFOQ_END_EN BIT(11) +#define EXT_VSYNC_START_EN BIT(12) +#define EXT_VSYNC_END_EN BIT(13) +#define EXT_VDE_START_EN BIT(14) +#define EXT_VDE_END_EN BIT(15) +#define EXT_VBLANK_END_EN BIT(16) +#define UNDERFLOW_EN BIT(17) +#define INFOQ_ABORT_EN BIT(18) + +#define DVO_INTSTA 0x0C +#define INT_VFP_START_STA BIT(0) +#define INT_VSYNC_START_STA BIT(1) +#define INT_VSYNC_END_STA BIT(2) +#define INT_VDE_START_STA BIT(3) +#define INT_VDE_END_STA BIT(4) +#define INT_WR_INFOQ_REG_STA BIT(5) +#define INT_TARGET_LINE0_STA BIT(6) +#define INT_TARGET_LINE1_STA BIT(7) +#define INT_TARGET_LINE2_STA BIT(8) +#define INT_TARGET_LINE3_STA BIT(9) +#define INT_WR_INFOQ_START_STA BIT(10) +#define INT_WR_INFOQ_END_STA BIT(11) +#define EXT_VSYNC_START_STA BIT(12) +#define EXT_VSYNC_END_STA BIT(13) +#define EXT_VDE_START_STA BIT(14) +#define EXT_VDE_END_STA BIT(15) +#define EXT_VBLANK_END_STA BIT(16) +#define INT_UNDERFLOW_STA BIT(17) +#define INFOQ_ABORT_STA BIT(18) + +#define DVO_CON 0x10 +#define INTL_EN BIT(0) + +#define DVO_OUTPUT_SET 0x18 +#define OUT_NP_SEL (0x3 << 0) + +#define BIT_SWAP BIT(4) +#define CH_SWAP_MASK (0x7 << 5) +#define SWAP_RGB 0x00 +#define SWAP_GBR 0x01 +#define SWAP_BRG 0x02 +#define SWAP_RBG 0x03 +#define SWAP_GRB 0x04 +#define SWAP_BGR 0x05 +#define PXL_SWAP BIT(8) +#define R_MASK BIT(12) +#define G_MASK BIT(13) +#define B_MASK BIT(14) +#define DE_MASK BIT(16) +#define HS_MASK BIT(17) +#define VS_MASK BIT(18) +#define HS_INV BIT(19) +#define VS_INV BIT(20) + +#define DVO_SRC_SIZE 0x20 +#define SRC_HSIZE 0 +#define SRC_HSIZE_MASK (0xFFFF << 0) +#define SRC_VSIZE 16 +#define SRC_VSIZE_MASK (0xFFFF << 16) + +#define DVO_PIC_SIZE 0x24 +#define PIC_HSIZE 0 +#define PIC_HSIZE_MASK (0xFFFF << 0) +#define PIC_VSIZE 16 +#define PIC_VSIZE_MASK (0xFFFF << 16) + +#define DVO_TGEN_H0 0x50 +#define HFP 0 +#define HFP_MASK (0xFFFF << 0) +#define HSYNC 16 +#define HSYNC_MASK (0xFFFF << 16) + +#define DVO_TGEN_H1 0x54 +#define HSYNC2ACT 0 +#define HSYNC2ACT_MASK (0xFFFF << 0) +#define HACT 16 +#define HACT_MASK (0xFFFF << 16) + +#define DVO_TGEN_V0 0x58 +#define VFP 0 +#define VFP_MASK (0xFFFF << 0) +#define VSYNC 16 +#define VSYNC_MASK (0xFFFF << 16) + +#define DVO_TGEN_V1 0x5C +#define VSYNC2ACT 0 +#define VSYNC2ACT_MASK (0xFFFF << 0) +#define VACT 16 +#define VACT_MASK (0xFFFF << 16) + +#define DVO_TGEN_INFOQ_LATENCY 0x80 +#define INFOQ_START_LATENCY 0 +#define INFOQ_START_LATENCY_MASK (0xFFFF << 0) +#define INFOQ_END_LATENCY 16 +#define INFOQ_END_LATENCY_MASK (0xFFFF << 16) + +#define DVO_BUF_CON0 0x220 +#define DISP_BUF_EN BIT(0) +#define FIFO_UNDERFLOW_DONE_BLOCK BIT(4) + +#define DVO_TGEN_V_LAST_TRAILING_BLANK 0x6c +#define V_LAST_TRAILING_BLANK 0 +#define V_LAST_TRAILING_BLANK_MASK (0xFFFF << 0) + +#define DVO_TGEN_OUTPUT_DELAY_LINE 0x7c +#define EXT_TG_DLY_LINE 0 +#define EXT_TG_DLY_LINE_MASK (0xFFFF << 0) + +#define DVO_PATTERN_CTRL 0x100 +#define PRE_PAT_EN BIT(0) +#define PRE_PAT_SEL_MASK (0x7 << 4) +#define COLOR_BAR (0x4 << 4) +#define PRE_PAT_FORCE_ON BIT(8) + +#define DVO_PATTERN_COLOR 0x104 +#define PAT_R (0x3FF << 0) +#define PAT_G (0x3FF << 10) +#define PAT_B (0x3FF << 20) + +#define DVO_SHADOW_CTRL 0x190 +#define FORCE_COMMIT BIT(0) +#define BYPASS_SHADOW BIT(1) +#define READ_WRK_REG BIT(2) + +#define DVO_SIZE 0x18 +#define DVO_TGEN_VWIDTH 0x28 +#define DVO_TGEN_VPORCH 0x2C +#define DVO_TGEN_HPORCH 0x24 +#define DVO_TGEN_HWIDTH 0x20 + +#define DVO_BUF_SODI_HIGHT 0x230 +#define DVO_BUF_SODI_LOW 0x234 + +enum mtk_dvo_golden_setting_level { + MTK_DVO_FHD_60FPS_1920 = 0, + MTK_DVO_FHD_60FPS_2180, + MTK_DVO_FHD_60FPS_2400, + MTK_DVO_FHD_60FPS_2520, + MTK_DVO_FHD_90FPS, + MTK_DVO_FHD_120FPS, + MTK_DVO_WQHD_60FPS, + MTK_DVO_WQHD_120FPS, + MTK_DVO_8K_30FPS, + MTK_DVO_GSL_MAX, +}; + +struct mtk_dvo_gs_info { + u32 dvo_buf_sodi_high; + u32 dvo_buf_sodi_low; +}; + +enum TVDPLL_CLK { + TVDPLL_PLL = 0, + TVDPLL_D16 = 1, + TVDPLL_D8 = 2, + TVDPLL_D4 = 3, +}; + +struct mtk_dvo { + void *regs; + void *regs_ck; + void *regs_mm; + enum mtk_dvo_golden_setting_level gs_level; +}; + +struct mtk_dvo_sync_param { + u32 sync_width; + u32 front_porch; + u32 back_porch; + bool shift_half_line; +}; + +void dp_intf_config(const struct edid *edid); + +#endif /* __SOC_MEDIATEK_MT8196_DP_DP_INTF_H__ */ diff --git a/src/soc/mediatek/mt8196/include/soc/dptx.h b/src/soc/mediatek/mt8196/include/soc/dptx.h new file mode 100644 index 0000000..4f21b9f --- /dev/null +++ b/src/soc/mediatek/mt8196/include/soc/dptx.h @@ -0,0 +1,8 @@ +/* SPDX-License-Identifier: GPL-2.0-only OR MIT */ + +#ifndef __SOC_MEDIATEK_MT8196_INCLUDE_SOC_DPTX_H__ +#define __SOC_MEDIATEK_MT8196_INCLUDE_SOC_DPTX_H__ + +#include <soc/dptx_common.h> +#define DP_LANSE_ADJUST_SIZE 2 +#endif /* __SOC_MEDIATEK_MT8196_INCLUDE_SOC_DPTX_H__ */ diff --git a/src/soc/mediatek/mt8196/include/soc/dptx_hal.h b/src/soc/mediatek/mt8196/include/soc/dptx_hal.h new file mode 100644 index 0000000..1de292e --- /dev/null +++ b/src/soc/mediatek/mt8196/include/soc/dptx_hal.h @@ -0,0 +1,42 @@ +/* SPDX-License-Identifier: GPL-2.0-only OR MIT */ + +#ifndef __SOC_MEDIATEK_MT8196_DP_DPTX_HAL_H__ +#define __SOC_MEDIATEK_MT8196_DP_DPTX_HAL_H__ + +#include <soc/dptx_hal_common.h> + +#define DP_BRANCH_OUI_HEADER_SIZE 0xc +#define DP_RECEIVER_CAP_SIZE 0xf +#define DP_DSC_RECEIVER_CAP_SIZE 0xf +#define EDP_PSR_RECEIVER_CAP_SIZE 2 +#define EDP_DISPLAY_CTL_CAP_SIZE 3 +#define DP_LTTPR_COMMON_CAP_SIZE 8 +#define DP_LTTPR_PHY_CAP_SIZE 3 +#define MTK_DP_TRAIN_VOLTAGE_LEVEL_RETRY 5 +#define MTK_DP_TRAIN_DOWNSCALE_RETRY 10 + +enum { + DPTX_PATTERN_TPS1 = 1, + DPTX_PATTERN_TPS2, + DPTX_PATTERN_TPS3, + DPTX_PATTERN_TPS4, + DPTX_PATTERN_UNKNOWN, +}; + +enum { + ENODEV = 1, + ETIMEDOUT, + EIO, + EINVAL, +}; + +void mtk_edp_hal_reset_swing_pre_emphasis(struct mtk_dp *mtk_dp); +void dptx_hal_phy_init(struct mtk_dp *mtk_dp); +void dptx_hal_phy_set_lanes(struct mtk_dp *mtk_dp, u8 lane_count); +void mtk_edp_phy_set_swing_pre_emphasis(struct mtk_dp *mtk_dp, u8 lane_count, + u8 *swing_val, u8 *pre_emphasis); +void mtk_edp_phy_wait_aux_ldo_ready(struct mtk_dp *mtk_dp); +void mtk_edp_hal_phy_set_idle_pattern(struct mtk_dp *mtk_dp, u8 lane_count, bool enable); +void mtk_edp_set_swing_pre_emphasis(struct mtk_dp *mtk_dp, u8 lane_count, u8 *swing_val, + u8 *pre_emphasis); +#endif /* __SOC_MEDIATEK_MT8196_DP_DPTX_HAL_H__ */ diff --git a/src/soc/mediatek/mt8196/include/soc/dptx_reg.h b/src/soc/mediatek/mt8196/include/soc/dptx_reg.h new file mode 100644 index 0000000..a83e12e --- /dev/null +++ b/src/soc/mediatek/mt8196/include/soc/dptx_reg.h @@ -0,0 +1,219 @@ +/* SPDX-License-Identifier: GPL-2.0-only OR MIT */ + +#ifndef __SOC_MEDIATEK_MT8196_DP_DPTX_REG_H__ +#define __SOC_MEDIATEK_MT8196_DP_DPTX_REG_H__ + +#include <soc/dptx_reg_common.h> + +#define WAIT_AUX_READY_RETRY_TIMES 5 +#define PHYD_DIG_GLB_OFFSET 0x1400 +#define SEC_OFFSET 0x4000 +#define IPMUX_CONTROL (PHYD_DIG_GLB_OFFSET + 0x98) +#define EDPTX_DSI_PHYD_SEL_FLDMASK 0x1 +#define EDPTX_DSI_PHYD_SEL_FLDMASK_POS 0 +#define TOP_OFFSET 0x2000 +#define MTK_DP_TOP_IRQ_MASK 0x202c +#define ENCODER_IRQ_MSK BIT(0) +#define TRANS_IRQ_MSK BIT(1) +#define EDP_TX_TOP_CLKGEN_0 0x2074 +#define DP_PHY_DIG_PLL_CTL_1 0x1414 +#define DP_PHY_DIG_SW_RST 0x1438 +#define DP_PHY_DIG_TX_CTL_0 0x1474 +#define RGS_BG_CORE_EN_READY_MASK BIT(0) +#define RGS_AUX_LDO_EN_READY_MASK BIT(1) +#define REG_2004_TOP_SWING_EMP 0x2004 +#define DP_TX0_VOLT_SWING_MASK GENMASK(1, 0) +#define DP_TX0_PRE_EMPH_MASK GENMASK(3, 2) +#define DP_TX1_VOLT_SWING_MASK GENMASK(9, 8) +#define DP_TX1_PRE_EMPH_MASK GENMASK(11, 10) +#define DP_TX2_VOLT_SWING_MASK GENMASK(17, 16) +#define DP_TX2_PRE_EMPH_MASK GENMASK(19, 18) +#define DP_TX3_VOLT_SWING_MASK GENMASK(25, 24) +#define DP_TX3_PRE_EMPH_MASK GENMASK(27, 26) +#define REG_3000_DP_ENCODER0_P0 0x3000 +#define REG_BS_SYMBOL_CNT_RESET BIT(7) +#define REG_3004_DP_ENCODER0_P0 0x3004 +#define DP_TX_ENCODER_4P_RESET_SW_DP_ENC0_P0 BIT(9) +#define REG_3008_DP_ENCODER0_P0 0x3008 +#define REG_300C_DP_ENCODER0_P0 0x300C +#define REG_3010_DP_ENCODER0_P0 0x3010 +#define REG_3014_DP_ENCODER0_P0 0x3014 +#define REG_3018_DP_ENCODER0_P0 0x3018 +#define REG_301C_DP_ENCODER0_P0 0x301C +#define REG_3020_DP_ENCODER0_P0 0x3020 +#define REG_3024_DP_ENCODER0_P0 0x3024 +#define REG_3028_DP_ENCODER0_P0 0x3028 +#define HSW_SW_DP_ENCODER0_P0_FLDMASK 0x7fff +#define HSW_SW_DP_ENCODER0_P0_FLDMASK_POS 0 +#define HSP_SW_DP_ENCODER0_P0_FLDMASK 0x8000 +#define HSP_SW_DP_ENCODER0_P0_FLDMASK_POS 15 +#define REG_302C_DP_ENCODER0_P0 0x302C +#define VSW_SW_DP_ENCODER0_P0_FLDMASK 0x7fff +#define VSW_SW_DP_ENCODER0_P0_FLDMASK_POS 0 +#define REG_3030_DP_ENCODER0_P0 0x3030 +#define REG_3034_DP_ENCODER0_P0 0x3034 +#define DP_TEST_COLOR_FORMAT_MASK (3 << 1) +#define DP_TEST_COLOR_FORMAT_SHIFT 1 +#define REG_303C_DP_ENCODER0_P0 0x303C +#define REG_3040_DP_ENCODER0_P0 0x3040 +#define REG_3044_DP_ENCODER0_P0 0x3044 +#define REG_3048_DP_ENCODER0_P0 0x3048 +#define REG_304C_DP_ENCODER0_P0 0x304C +#define VBID_VIDEO_MUTE_DP_ENC0_4P_MASK BIT(2) +#define REG_3050_DP_ENCODER0_P0 0x3050 +#define REG_3054_DP_ENCODER0_P0 0x3054 +#define REG_3064_DP_ENCODER0_P0 0x3064 +#define REG_3154_DP_ENCODER0_P0 0x3154 +#define REG_3158_DP_ENCODER0_P0 0x3158 +#define REG_315C_DP_ENCODER0_P0 0x315C +#define REG_3160_DP_ENCODER0_P0 0x3160 +#define REG_3164_DP_ENCODER0_P0 0x3164 +#define REG_3168_DP_ENCODER0_P0 0x3168 +#define REG_316C_DP_ENCODER0_P0 0x316C +#define REG_3170_DP_ENCODER0_P0 0x3170 +#define REG_3174_DP_ENCODER0_P0 0x3174 +#define REG_3178_DP_ENCODER0_P0 0x3178 +#define REG_31EC_DP_ENCODER0_P0 0x31EC +#define REG_3300_DP_ENCODER1_P0 0x3300 +#define REG_3364_DP_ENCODER1_P0 0x3364 +#define REG_3368_DP_ENCODER1_P0 0x3368 +#define BS2BS_MODE_DP_ENC1_4P_VAL 1 +#define BS2BS_MODE_DP_ENCODER1_P0_FLDMASK 0x3000 +#define DP_I_MODE_ENABLE BIT(6) +#define REG_33C0_DP_ENCODER1_P0 0x33C0 +#define REG_33C4_DP_ENCODER1_P0 0x33C4 +#define REG_33C8_DP_ENCODER1_P0 0x33C8 +#define REG_3400_DP_TRANS_P0 0x3400 +#define PATTERN1_EN_DP_TRANS_4P_TPS1 BIT(12) +#define PATTERN2_EN_DP_TRANS_4P_TPS2 BIT(13) +#define PATTERN3_EN_DP_TRANS_4P_TPS3 BIT(14) +#define PATTERN4_EN_DP_TRANS_4P_TPS4 BIT(15) +#define PATTERN_EN_DP_TRANS_4P_MASK GENMASK(15, 12) +#define REG_3404_DP_TRANS_P0 0x3404 +#define REG_340C_DP_TRANS_P0 0x340C +#define REG_3418_DP_TRANS_P0 0x3418 +#define REG_342C_DP_TRANS_P0 0x342C +#define REG_34A4_DP_TRANS_P0 0x34A4 +#define REG_3540_DP_TRANS_P0 0x3540 +#define REG_3580_DP_TRANS_P0 0x3580 +#define POST_MISC_DATA_LANE0_OV_DP_TRANS_4P_MASK BIT(8) +#define POST_MISC_DATA_LANE1_OV_DP_TRANS_4P_MASK BIT(9) +#define POST_MISC_DATA_LANE2_OV_DP_TRANS_4P_MASK BIT(10) +#define POST_MISC_DATA_LANE3_OV_DP_TRANS_4P_MASK BIT(11) +#define POST_MISC_DATA_LANE_OV_DP_TRANS_4P_MASK GENMASK(11, 8) +#define REG_35F0_DP_TRANS_P0 0x35F0 +#define REG_360C_AUX_TX_P0 0x360C +#define REG_3614_AUX_TX_P0 0x3614 +#define AUX_RX_UI_CNT_THR_AUX_FOR_26M 13 +#define REG_3618_AUX_TX_P0 0x3618 +#define AUX_RX_FIFO_FULL_AUX_TX_P0_FLDMASK 0x200 +#define AUX_RX_FIFO_WRITE_POINTER_AUX_TX_P0_FLDMASK 0xf +#define REG_3620_AUX_TX_P0 0x3620 +#define AUX_RD_MODE_AUX_TX_P0_FLDMASK 0x200 +#define AUX_RD_MODE_AUX_TX_P0_FLDMASK_POS 9 +#define AUX_RX_FIFO_READ_PULSE_TX_P0_FLDMASK 0x100 +#define AUX_RX_FIFO_R_PULSE_TX_P0_FLDMASK_POS 8 +#define REG_3624_AUX_TX_P0 0x3624 +#define REG_3628_AUX_TX_P0 0x3628 +#define REG_362C_AUX_TX_P0 0x362C +#define AUX_NO_LENGTH_AUX_TX_P0_FLDMASK 0x1 +#define AUX_NO_LENGTH_AUX_TX_P0_FLDMASK_POS 0 +#define REG_3630_AUX_TX_P0 0x3630 +#define AUX_TX_REQUEST_READY_AUX_TX_P0_FLDMASK 0x8 +#define AUX_TX_REQUEST_READY_AUX_TX_P0_FLDMASK_POS 3 +#define REG_3634_AUX_TX_P0 0x3634 +#define AUX_TX_OVER_SAMPLE_RATE_FOR_26M 25 +#define REG_3640_AUX_TX_P0 0x3640 +#define AUX_RX_RECV_COMPLETE_IRQ_TX_P0_FLDMASK 0x40 +#define AUX_400US_TIMEOUT_IRQ_AUX_TX_P0_FLDMASK 0x1 +#define REG_3644_AUX_TX_P0 0x3644 +#define REG_3648_AUX_TX_P0 0x3648 +#define REG_364C_AUX_TX_P0 0x364C +#define HPD_INT_THD_FLDMASK_VAL 0x32 +#define HPD_INT_THD_FLDMASK 0x3f0 +#define REG_3650_AUX_TX_P0 0x3650 +#define MCU_REQUEST_DATA_NUM_AUX_TX_P0_FLDMASK 0xf000 +#define MCU_REQ_DATA_NUM_AUX_TX_P0_FLDMASK_POS 12 +#define MCU_ACK_TRANSACTION_COMPLETE_AUX_TX_P0_FLDMASK 0x100 +#define MCU_ACK_TRAN_COMPLETE_AUX_TX_P0_FLDMASK_POS 8 +#define REG_3658_AUX_TX_P0 0x3658 +#define REG_366C_AUX_TX_P0 0x366C +#define XTAL_FREQ_DP_TX_AUX_366C_VALUE 0x68 +#define XTAL_FREQ_DP_TX_AUX_366C_MASK 0xFF00 +#define REG_367C_AUX_TX_P0 0x367C +#define HPD_CONN_THD_AUX_TX_P0_FLDMASK_POS 5 +#define HPD_CONN_THD_AUX_TX_P0_FLDMASK 0x3c0 +#define REG_3690_AUX_TX_P0 0x3690 +#define RX_REPLY_COMPLETE_MODE_AUX_TX_4P BIT(8) +#define REG_36A0_AUX_TX_4P 0x36A0 +#define REG_3704_AUX_TX_P0 0x3704 +#define AUX_TX_FIFO_WRITE_DATA_TOGGLE_AUX_TX_P0_FLDMASK 0x2 +#define AUX_TX_FIFO_NEW_MODE_EN_AUX_TX_P0_FLDMASK 0x4 +#define AUX_TX_FIFO_NEW_MODE_EN_AUX_TX_P0_FLDMASK_POS 2 +#define REG_3708_AUX_TX_P0 0x3708 +#define REG_37A0_AUX_TX_P0 0x37A0 +#define HPD_DISC_THD_AUX_TX_P0_FLDMASK_POS 5 +#define HPD_DISC_THD_AUX_TX_P0_FLDMASK 0xF0 +#define REG_37C8_AUX_TX_P0 0x37C8 +#define MTK_ATOP_EN_AUX_TX_4P BIT(0) +#define REG_3F04_DP_ENC_4P_3 0x3F04 +#define REG_3F08_DP_ENC_4P_3 0x3F08 +#define REG_3F0C_DP_ENC_4P_3 0x3F0C +#define REG_3F10_DP_ENC_4P_3 0x3F10 +#define REG_3F28_DP_ENC_4P_3 0x3F28 +#define REG_3F44_DP_ENC_4P_3 0x3F44 +#define PHY_PWR_STATE_OW_EN_DP_ENC_4P_3 BIT(2) +#define PHY_PWR_STATE_OW_EN_DP_ENC_4P_3_MASK BIT(2) +#define BIAS_POWER_ON (0x01 << 3) +#define PHY_PWR_STATE_OW_VALUE_DP_ENC_4P_3_MASK GENMASK(4, 3) +#define REG_3F80_DP_ENC_4P_3 0x3F80 +#define PSR_PATGEN_AVT_EN_FLDMASK 0x20 +#define REG_3FF8_DP_ENC_4P_3 0x3FF8 +#define PHY_STATE_W_1_DP_ENC_4P_3 BIT(6) +#define PHY_STATE_W_1_DP_ENC_4P_3_MASK BIT(6) +#define DVO_ON_W_1_FLDMASK 0x20 +#define XTAL_FREQ_FOR_PSR_DP_ENC_4P_3_VALUE 25 +#define XTAL_FREQ_FOR_PSR_DP_ENC_4P_3_MASK 0x3E00 +#define PHYD_DIG_LAN0_OFFSET 0x1000 +#define PHYD_DIG_LAN1_OFFSET 0x1100 +#define PHYD_DIG_LAN2_OFFSET 0x1200 +#define PHYD_DIG_LAN3_OFFSET 0x1300 +#define DRIVING_FORCE 0x30 +#define EDP_TX_LN_VOLT_SWING_VAL_MASK GENMASK(2, 1) +#define EDP_TX_LN_PRE_EMPH_VAL_MASK GENMASK(4, 3) +#define DP_TX_TOP_APB_WSTRB (TOP_OFFSET + 0x10) +#define DP_TX_TOP_RESET_AND_PROBE (TOP_OFFSET + 0x20) +#define DP_TX_SECURE_REG11 (SEC_OFFSET + 0x2C) +#define DP_LANE_COUNT_ENHANCED_FRAME_EN (1 << 7) +#define DPCD_00000 0x00000 +#define DPCD_0000E 0x0000E +#define DPCD_00021 0x00021 +#define DPCD_00100 0x00100 +#define DPCD_00101 0x00101 +#define DPCD_00102 0x00102 +#define DP_TRAINING_PATTERN_DISABLE 0 +#define DP_TRAINING_PATTERN_1 1 +#define DP_TRAINING_PATTERN_2 2 +#define DP_TRAINING_PATTERN_3 3 /* 1.2 */ +#define DP_TRAINING_PATTERN_4 7 /* 1.4 */ +#define DP_LINK_SCRAMBLING_DISABLE BIT(5) +#define DPCD_00103 0x00103 +#define DP_TRAIN_VOLTAGE_SWING_SHIFT 0 +#define DP_TRAIN_MAX_SWING_REACHED BIT(2) +#define DP_TRAIN_VOLTAGE_SWING_LEVEL_3 0x3 +#define DP_TRAIN_PRE_EMPHASIS_SHIFT 3 +#define DP_TRAIN_MAX_PRE_EMPHASIS_REACHED BIT(5) +#define DPCD_00107 0x00107 +#define DP_SPREAD_AMP_0_5 BIT(4) +#define DPCD_00200 0x00200 +#define DPCD_00202 0x00202 +#define DPCD_00206 0x00206 +#define DP_ADJUST_VOLTAGE_SWING_LANE0_MASK 0x03 +#define DP_ADJUST_PRE_EMPHASIS_LANE0_MASK 0x0c +#define DP_ADJUST_PRE_EMPHASIS_LANE0_SHIFT 2 +#define DP_ADJUST_VOLTAGE_SWING_LANE1_SHIFT 4 +#define DPCD_00600 0x00600 +#define DPCD_02002 0x02002 +#define DPCD_02003 0x02003 + +#endif /* __SOC_MEDIATEK_MT8196_DP_DPTX_REG_H__ */