From 44635f328c1f3d7ddbcbb06dbf6bc15b21a4e98b Mon Sep 17 00:00:00 2001 From: Vince Liu Date: Mon, 27 Oct 2025 09:16:49 +0800 Subject: [PATCH] soc/mediatek/common: Add C-PHY support for MIPI DSI Introduce C-PHY support by adding PANEL_FLAG_CPHY flag, updating data rate calculations, timing configurations, and register settings for C-PHY operation. To improve code reusability, the D-PHY and C-PHY specific implementations are moved to `mtk_mipi_dphy.c` and `mtk_mipi_cphy.c`, respectively. BUG=b:433422905,b:428854543 BRANCH=skywalker TEST=check log on padme mtk_display_init: 'TM TL121BVMS07' 1600x2560@60Hz Change-Id: I9e81551484e605e1d74b9983fe00b5d0eba69358 Signed-off-by: Bincai Liu Signed-off-by: Vince Liu (cherry picked from commit 22a499836eeb6904e114023da6222b29da10f62f) Reviewed-on: https://review.coreboot.org/c/coreboot/+/89567 Reviewed-by: Yidi Lin Tested-by: build bot (Jenkins) Reviewed-by: Yu-Ping Wu --- src/soc/mediatek/common/Kconfig | 6 + src/soc/mediatek/common/display.c | 10 +- src/soc/mediatek/common/dsi_common.c | 161 +++++++++++------- src/soc/mediatek/common/dsi_v1.c | 62 +++++++ .../mediatek/common/include/soc/dsi_common.h | 26 ++- .../common/include/soc/dsi_register_v2.h | 15 +- src/soc/mediatek/common/mtk_mipi_cphy.c | 112 ++++++++++++ src/soc/mediatek/common/mtk_mipi_dphy.c | 56 +----- src/soc/mediatek/mt8173/dsi.c | 2 +- 9 files changed, 323 insertions(+), 127 deletions(-) create mode 100644 src/soc/mediatek/common/mtk_mipi_cphy.c diff --git a/src/soc/mediatek/common/Kconfig b/src/soc/mediatek/common/Kconfig index 63a11d0ca8..1f0f54ea7a 100644 --- a/src/soc/mediatek/common/Kconfig +++ b/src/soc/mediatek/common/Kconfig @@ -54,6 +54,12 @@ config MEDIATEK_DRAM_SCRAMBLE This option enables DRAM data scramble, which can prevent DRAM data from being hacked. +config MEDIATEK_DSI_CPHY + bool + default n + help + The configuration to support DSI C-PHY. + config MEMORY_TEST bool default y diff --git a/src/soc/mediatek/common/display.c b/src/soc/mediatek/common/display.c index 109da29d59..8e3979df26 100644 --- a/src/soc/mediatek/common/display.c +++ b/src/soc/mediatek/common/display.c @@ -103,6 +103,7 @@ int mtk_display_init(void) const char *name; struct panel_description *panel = get_active_panel(); uintptr_t fb_addr; + u32 lanes; if (!panel || panel->disp_path == DISP_PATH_NONE) { printk(BIOS_ERR, "%s: Failed to get the active panel\n", __func__); @@ -146,7 +147,14 @@ int mtk_display_init(void) MIPI_DSI_MODE_LPM | MIPI_DSI_MODE_EOT_PACKET); - if (mtk_dsi_init(mipi_dsi_flags, MIPI_DSI_FMT_RGB888, 4, &edid, + if (mipi_data->flags & PANEL_FLAG_CPHY) { + mipi_dsi_flags |= MIPI_DSI_MODE_CPHY; + lanes = 3; + } else { + lanes = 4; + } + + if (mtk_dsi_init(mipi_dsi_flags, MIPI_DSI_FMT_RGB888, lanes, &edid, mipi_data ? mipi_data->init : NULL) < 0) { printk(BIOS_ERR, "%s: Failed in DSI init\n", __func__); return -1; diff --git a/src/soc/mediatek/common/dsi_common.c b/src/soc/mediatek/common/dsi_common.c index 696f849a6a..027c748d0b 100644 --- a/src/soc/mediatek/common/dsi_common.c +++ b/src/soc/mediatek/common/dsi_common.c @@ -12,6 +12,9 @@ #define MIN_HFP_BYTE 2 #define MIN_HBP_BYTE 2 +#define CPHY_SYMBOL_RATE 7 +#define CPHY_SYMBOL_RATE_DIVISOR 16 + static unsigned int mtk_dsi_get_bits_per_pixel(u32 format) { switch (format) { @@ -29,7 +32,7 @@ static unsigned int mtk_dsi_get_bits_per_pixel(u32 format) } static u32 mtk_dsi_get_data_rate(u32 bits_per_pixel, u32 lanes, - const struct edid *edid) + const struct edid *edid, bool is_cphy) { /* data_rate = pixel_clock * bits_per_pixel * mipi_ratio / lanes * Note pixel_clock comes in kHz and returned data_rate is in bps. @@ -37,11 +40,16 @@ static u32 mtk_dsi_get_data_rate(u32 bits_per_pixel, u32 lanes, * for older platforms which do not have complete implementation in HFP. * Newer platforms should just set that to 1.0 (100 / 100). */ - u32 data_rate = DIV_ROUND_UP((u64)edid->mode.pixel_clock * - bits_per_pixel * 1000 * - MTK_DSI_MIPI_RATIO_NUMERATOR, - (u64)lanes * - MTK_DSI_MIPI_RATIO_DENOMINATOR); + u32 data_rate; + u64 dividend = (u64)edid->mode.pixel_clock * bits_per_pixel * 1000 * + MTK_DSI_MIPI_RATIO_NUMERATOR; + u64 divisor = (u64)lanes * MTK_DSI_MIPI_RATIO_DENOMINATOR; + + if (is_cphy) { + dividend *= CPHY_SYMBOL_RATE; + divisor *= CPHY_SYMBOL_RATE_DIVISOR; + } + data_rate = DIV_ROUND_UP(dividend, divisor); printk(BIOS_INFO, "DSI data_rate: %u bps\n", data_rate); if (data_rate < MTK_DSI_DATA_RATE_MIN_MHZ * MHz) { @@ -63,13 +71,11 @@ __weak void mtk_dsi_override_phy_timing(struct mtk_phy_timing *timing) /* Do nothing. */ } -static void mtk_dsi_phy_timing(u32 data_rate, struct mtk_phy_timing *timing) +static void mtk_dsi_dphy_timing(u32 data_rate, struct mtk_phy_timing *timing) { u32 timcon0, timcon1, timcon2, timcon3; u32 data_rate_mhz = DIV_ROUND_UP(data_rate, MHz); - memset(timing, 0, sizeof(*timing)); - timing->lpx = (60 * data_rate_mhz / (8 * 1000)) + 1; timing->da_hs_prepare = (80 * data_rate_mhz + 4 * 1000) / 8000; timing->da_hs_zero = (170 * data_rate_mhz + 10 * 1000) / 8000 + 1 - @@ -163,46 +169,19 @@ static void mtk_dsi_rxtx_control(u32 mode_flags, u32 lanes) write32(&dsi0->dsi_txrx_ctrl, tmp_reg); } -static void mtk_dsi_config_vdo_timing(u32 mode_flags, u32 format, u32 lanes, - const struct edid *edid, - const struct mtk_phy_timing *phy_timing) +static void mtk_dsi_dphy_vdo_timing(const u32 mode_flags, + const u32 lanes, + const struct edid *edid, + const struct mtk_phy_timing *phy_timing, + const u32 bytes_per_pixel, + const u32 hbp, + const u32 hfp, + s32 *hbp_byte, + s32 *hfp_byte, + u32 *hsync_active_byte) { - u32 hsync_active_byte; - u32 hbp; - u32 hfp; - s32 hbp_byte; - s32 hfp_byte; - u32 vbp_byte; - u32 vfp_byte; - u32 bytes_per_pixel; - u32 packet_fmt; - u32 hactive; - u32 data_phy_cycles; - - bytes_per_pixel = DIV_ROUND_UP(mtk_dsi_get_bits_per_pixel(format), 8); - vbp_byte = edid->mode.vbl - edid->mode.vso - edid->mode.vspw - - edid->mode.vborder; - vfp_byte = edid->mode.vso - edid->mode.vborder; - - write32(&dsi0->dsi_vsa_nl, edid->mode.vspw); - write32(&dsi0->dsi_vbp_nl, vbp_byte); - write32(&dsi0->dsi_vfp_nl, vfp_byte); - write32(&dsi0->dsi_vact_nl, edid->mode.va); - - hsync_active_byte = edid->mode.hspw * bytes_per_pixel - 10; - - hbp = edid->mode.hbl - edid->mode.hso - edid->mode.hspw - - edid->mode.hborder; - hfp = edid->mode.hso - edid->mode.hborder; - - if (mode_flags & MIPI_DSI_MODE_VIDEO_SYNC_PULSE) - hbp_byte = hbp * bytes_per_pixel - 10; - else - hbp_byte = (hbp + edid->mode.hspw) * bytes_per_pixel - 10; - hfp_byte = hfp * bytes_per_pixel; - - data_phy_cycles = phy_timing->lpx + phy_timing->da_hs_prepare + - phy_timing->da_hs_zero + phy_timing->da_hs_exit + 3; + u32 data_phy_cycles = phy_timing->lpx + phy_timing->da_hs_prepare + + phy_timing->da_hs_zero + phy_timing->da_hs_exit + 3; u32 delta = 10; @@ -217,20 +196,65 @@ static void mtk_dsi_config_vdo_timing(u32 mode_flags, u32 format, u32 lanes, d_phy = data_phy_cycles * lanes + delta; if ((hfp + hbp) * bytes_per_pixel > d_phy) { - hfp_byte -= d_phy * hfp / (hfp + hbp); - hbp_byte -= d_phy * hbp / (hfp + hbp); + *hfp_byte -= d_phy * hfp / (hfp + hbp); + *hbp_byte -= d_phy * hbp / (hfp + hbp); } else { printk(BIOS_ERR, "HFP %u plus HBP %u is not greater than d_phy %u, " - "the panel may not work properly.\n", hfp * bytes_per_pixel, - hbp * bytes_per_pixel, d_phy); + "the panel may not work properly.\n", hfp * bytes_per_pixel, + hbp * bytes_per_pixel, d_phy); } + *hsync_active_byte = edid->mode.hspw * bytes_per_pixel - 10; if (mode_flags & MIPI_DSI_MODE_LINE_END) { - hsync_active_byte = DIV_ROUND_UP(hsync_active_byte, lanes) * lanes - 2; - hbp_byte = DIV_ROUND_UP(hbp_byte, lanes) * lanes - 2; - hfp_byte = DIV_ROUND_UP(hfp_byte, lanes) * lanes - 2; - hbp_byte -= (edid->mode.ha * bytes_per_pixel + 2) % lanes; + *hsync_active_byte = DIV_ROUND_UP(*hsync_active_byte, lanes) * lanes - 2; + *hbp_byte = DIV_ROUND_UP(*hbp_byte, lanes) * lanes - 2; + *hfp_byte = DIV_ROUND_UP(*hfp_byte, lanes) * lanes - 2; + *hbp_byte -= (edid->mode.ha * bytes_per_pixel + 2) % lanes; } +} + +static void mtk_dsi_config_vdo_timing(u32 mode_flags, u32 format, u32 lanes, + const struct edid *edid, + const struct mtk_phy_timing *phy_timing) +{ + u32 hsync_active_byte; + u32 hbp; + u32 hfp; + s32 hbp_byte; + s32 hfp_byte; + u32 vbp_byte; + u32 vfp_byte; + u32 bytes_per_pixel; + u32 packet_fmt; + u32 hactive; + bool is_cphy = !!(mode_flags & MIPI_DSI_MODE_CPHY); + + bytes_per_pixel = DIV_ROUND_UP(mtk_dsi_get_bits_per_pixel(format), 8); + vbp_byte = edid->mode.vbl - edid->mode.vso - edid->mode.vspw - + edid->mode.vborder; + vfp_byte = edid->mode.vso - edid->mode.vborder; + + write32(&dsi0->dsi_vsa_nl, edid->mode.vspw); + write32(&dsi0->dsi_vbp_nl, vbp_byte); + write32(&dsi0->dsi_vfp_nl, vfp_byte); + write32(&dsi0->dsi_vact_nl, edid->mode.va); + + hbp = edid->mode.hbl - edid->mode.hso - edid->mode.hspw - + edid->mode.hborder; + hfp = edid->mode.hso - edid->mode.hborder; + + if (mode_flags & MIPI_DSI_MODE_VIDEO_SYNC_PULSE) + hbp_byte = hbp * bytes_per_pixel - 10; + else + hbp_byte = (hbp + edid->mode.hspw) * bytes_per_pixel - 10; + hfp_byte = hfp * bytes_per_pixel; + + if (CONFIG(MEDIATEK_DSI_CPHY) && is_cphy) + mtk_dsi_cphy_vdo_timing(lanes, edid, phy_timing, bytes_per_pixel, hbp, hfp, + &hbp_byte, &hfp_byte, &hsync_active_byte); + else + mtk_dsi_dphy_vdo_timing(mode_flags, lanes, edid, phy_timing, bytes_per_pixel, + hbp, hfp, &hbp_byte, &hfp_byte, &hsync_active_byte); if (hfp_byte + hbp_byte < MIN_HFP_BYTE + MIN_HBP_BYTE) { printk(BIOS_ERR, "Calculated hfp_byte %d and hbp_byte %d are too small, " @@ -281,6 +305,8 @@ static void mtk_dsi_config_vdo_timing(u32 mode_flags, u32 format, u32 lanes, write32(&dsi0->dsi_size_con, edid->mode.va << DSI_SIZE_CON_HEIGHT_SHIFT | hactive << DSI_SIZE_CON_WIDTH_SHIFT); + if (CONFIG(MEDIATEK_DSI_CPHY) && is_cphy) + mtk_dsi_cphy_enable_cmdq_6byte(); } static void mtk_dsi_start(void) @@ -339,6 +365,7 @@ static enum cb_err mtk_dsi_cmdq(enum mipi_dsi_transaction type, const u8 *data, } write32(&dsi0->dsi_cmdq_size, 1 + DIV_ROUND_UP(len, 4)); } + setbits32(&dsi0->dsi_cmdq_size, CMDQ_SIZE_SEL); mtk_dsi_start(); @@ -351,7 +378,7 @@ static enum cb_err mtk_dsi_cmdq(enum mipi_dsi_transaction type, const u8 *data, return CB_SUCCESS; } -static void mtk_dsi_reset_dphy(void) +static void mtk_dsi_reset_phy(void) { setbits32(&dsi0->dsi_con_ctrl, DPHY_RESET); clrbits32(&dsi0->dsi_con_ctrl, DPHY_RESET); @@ -362,18 +389,28 @@ int mtk_dsi_init(u32 mode_flags, u32 format, u32 lanes, const struct edid *edid, { u32 data_rate; u32 bits_per_pixel = mtk_dsi_get_bits_per_pixel(format); + bool is_cphy = !!(mode_flags & MIPI_DSI_MODE_CPHY); - data_rate = mtk_dsi_get_data_rate(bits_per_pixel, lanes, edid); + if (!CONFIG(MEDIATEK_DSI_CPHY) && is_cphy) { + printk(BIOS_ERR, "%s: Board is built without C-PHY interface support. " + "Please check Kconfig MEDIATEK_DSI_CPHY.\n", __func__); + return -1; + } + + data_rate = mtk_dsi_get_data_rate(bits_per_pixel, lanes, edid, is_cphy); if (!data_rate) return -1; - mtk_dsi_configure_mipi_tx(data_rate, lanes); + mtk_dsi_configure_mipi_tx(data_rate, lanes, is_cphy); mtk_dsi_reset(); - struct mtk_phy_timing phy_timing; - mtk_dsi_phy_timing(data_rate, &phy_timing); + struct mtk_phy_timing phy_timing = {}; + if (CONFIG(MEDIATEK_DSI_CPHY) && is_cphy) + mtk_dsi_cphy_timing(data_rate, &phy_timing); + else + mtk_dsi_dphy_timing(data_rate, &phy_timing); mtk_dsi_rxtx_control(mode_flags, lanes); mdelay(1); - mtk_dsi_reset_dphy(); + mtk_dsi_reset_phy(); mtk_dsi_clk_hs_mode_disable(); mtk_dsi_config_vdo_timing(mode_flags, format, lanes, edid, &phy_timing); mtk_dsi_clk_hs_mode_enable(); diff --git a/src/soc/mediatek/common/dsi_v1.c b/src/soc/mediatek/common/dsi_v1.c index 67654b1630..6177bc35ad 100644 --- a/src/soc/mediatek/common/dsi_v1.c +++ b/src/soc/mediatek/common/dsi_v1.c @@ -1,7 +1,69 @@ /* SPDX-License-Identifier: GPL-2.0-only OR MIT */ +#include +#include #include #include +#include + +void mtk_dsi_configure_mipi_tx(u32 data_rate, u32 lanes, bool is_cphy) +{ + unsigned int txdiv0; + u64 pcw; + + if (data_rate >= 2000 * MHz) { + txdiv0 = 0; + } else if (data_rate >= 1000 * MHz) { + txdiv0 = 1; + } else if (data_rate >= 500 * MHz) { + txdiv0 = 2; + } else if (data_rate > 250 * MHz) { + /* (data_rate == 250MHz) is a special case that should go to the + else-block below (txdiv0 = 4) */ + txdiv0 = 3; + } else { + /* MIN = 125 */ + assert(data_rate >= MTK_DSI_DATA_RATE_MIN_MHZ * MHz); + txdiv0 = 4; + } + + if (CONFIG(MEDIATEK_DSI_CPHY) && is_cphy) + mtk_dsi_cphy_lane_sel_setting(); + + clrbits32(&mipi_tx->pll_con4, BIT(11) | BIT(10)); + setbits32(&mipi_tx->pll_pwr, AD_DSI_PLL_SDM_PWR_ON); + udelay(30); + clrbits32(&mipi_tx->pll_pwr, AD_DSI_PLL_SDM_ISO_EN); + + pcw = (u64)data_rate * (1 << txdiv0); + pcw <<= 24; + pcw /= CLK26M_HZ; + + write32(&mipi_tx->pll_con0, pcw); + clrsetbits32(&mipi_tx->pll_con1, RG_DSI_PLL_POSDIV, txdiv0 << 8); + udelay(30); + setbits32(&mipi_tx->pll_con1, RG_DSI_PLL_EN); + + /* BG_LPF_EN / BG_CORE_EN */ + write32(&mipi_tx->lane_con, 0x3FFF0180); + udelay(40); + write32(&mipi_tx->lane_con, 0x3FFF00C0); + + if (CONFIG(MEDIATEK_DSI_CPHY) && is_cphy) + mtk_dsi_cphy_enable(); + + /* Switch OFF each Lane */ + clrbits32(&mipi_tx->d0_sw_ctl_en, DSI_SW_CTL_EN); + clrbits32(&mipi_tx->d1_sw_ctl_en, DSI_SW_CTL_EN); + clrbits32(&mipi_tx->d2_sw_ctl_en, DSI_SW_CTL_EN); + clrbits32(&mipi_tx->d3_sw_ctl_en, DSI_SW_CTL_EN); + clrbits32(&mipi_tx->ck_sw_ctl_en, DSI_SW_CTL_EN); + + if (CONFIG(MEDIATEK_DSI_CPHY) && is_cphy) + mtk_dsi_cphy_disable_ck_mode(); + else + mtk_dsi_dphy_disable_ck_mode(); +} void mtk_dsi_reset(void) { diff --git a/src/soc/mediatek/common/include/soc/dsi_common.h b/src/soc/mediatek/common/include/soc/dsi_common.h index f5fc70c1c6..d741db0f1d 100644 --- a/src/soc/mediatek/common/include/soc/dsi_common.h +++ b/src/soc/mediatek/common/include/soc/dsi_common.h @@ -43,6 +43,8 @@ enum { MIPI_DSI_MODE_LPM = BIT(11), /* dsi per line's data end same time on all lanes */ MIPI_DSI_MODE_LINE_END = BIT(12), + /* mipi is in CPHY mode */ + MIPI_DSI_MODE_CPHY = BIT(13), }; static struct dsi_regs *const dsi0 = (void *)DSI0_BASE; @@ -57,6 +59,11 @@ enum { DSI_BUSY = BIT(31), }; +/* DSI_CMD_TYPE1_HS */ +enum { + CMD_CPHY_6BYTE_EN = BIT(18), +}; + /* DSI_CON_CTRL */ enum { DSI_RESET = BIT(0), @@ -103,6 +110,7 @@ enum { /* DSI_CMDQ_SIZE */ enum { CMDQ_SIZE = 0x3f, + CMDQ_SIZE_SEL = BIT(15), }; /* DSI_PHY_LCCON */ @@ -192,13 +200,25 @@ struct mtk_phy_timing { /* Functions that each SOC should provide. */ void mtk_dsi_reset(void); -void mtk_dsi_configure_mipi_tx(u32 data_rate, u32 lanes); /* Functions as weak no-ops that can be overridden. */ void mtk_dsi_override_phy_timing(struct mtk_phy_timing *timing); -/* Public API provided in common/dsi_common.c */ -int mtk_dsi_bpp_from_format(u32 format); +/* + * Public API provided in common/dsi_common.c, common/dsi_v1.c, and + * common/mtk_mipi_{c/d}phy.c + */ +void mtk_dsi_cphy_enable(void); +void mtk_dsi_cphy_enable_cmdq_6byte(void); +void mtk_dsi_cphy_lane_sel_setting(void); +void mtk_dsi_cphy_timing(u32 data_rate, struct mtk_phy_timing *timing); +void mtk_dsi_cphy_vdo_timing(const u32 lanes, const struct edid *edid, + const struct mtk_phy_timing *phy_timing, + const u32 bytes_per_pixel, const u32 hbp, const u32 hfp, + s32 *hbp_byte, s32 *hfp_byte, u32 *hsync_active_byte); +void mtk_dsi_cphy_disable_ck_mode(void); +void mtk_dsi_dphy_disable_ck_mode(void); +void mtk_dsi_configure_mipi_tx(u32 data_rate, u32 lanes, bool is_cphy); int mtk_dsi_init(u32 mode_flags, u32 format, u32 lanes, const struct edid *edid, const u8 *init_commands); diff --git a/src/soc/mediatek/common/include/soc/dsi_register_v2.h b/src/soc/mediatek/common/include/soc/dsi_register_v2.h index 17809c79ef..5c26ba51af 100644 --- a/src/soc/mediatek/common/include/soc/dsi_register_v2.h +++ b/src/soc/mediatek/common/include/soc/dsi_register_v2.h @@ -31,24 +31,29 @@ struct dsi_regs { u32 dsi_bllp_wc; u32 dsi_cmdq_size; u32 dsi_hstx_cklp_wc; - u8 reserved2[156]; + u8 reserved2[4]; + u32 dsi_cmd_type1_hs; + u8 reserved3[148]; u32 dsi_phy_lccon; u32 dsi_phy_ld0con; - u8 reserved3[4]; + u8 reserved4[4]; u32 dsi_phy_timecon0; u32 dsi_phy_timecon1; u32 dsi_phy_timecon2; u32 dsi_phy_timecon3; - u8 reserved4[16]; + u32 dsi_cphy_con0; + u8 reserved5[12]; u32 dsi_vm_cmd_con; - u8 reserved5[92]; + u8 reserved6[92]; u32 dsi_force_commit; /* Available since MT8183 */ - u8 reserved6[2924]; + u8 reserved7[2924]; u32 dsi_cmdq[128]; }; +check_member(dsi_regs, dsi_cmd_type1_hs, 0x6c); check_member(dsi_regs, dsi_phy_lccon, 0x104); check_member(dsi_regs, dsi_phy_timecon3, 0x11c); +check_member(dsi_regs, dsi_cphy_con0, 0x120); check_member(dsi_regs, dsi_vm_cmd_con, 0x130); check_member(dsi_regs, dsi_force_commit, 0x190); check_member(dsi_regs, dsi_cmdq, 0xd00); diff --git a/src/soc/mediatek/common/mtk_mipi_cphy.c b/src/soc/mediatek/common/mtk_mipi_cphy.c new file mode 100644 index 0000000000..9ff62240fc --- /dev/null +++ b/src/soc/mediatek/common/mtk_mipi_cphy.c @@ -0,0 +1,112 @@ +/* SPDX-License-Identifier: GPL-2.0-only OR MIT */ + +#include +#include +#include +#include +#include +#include + +#define DE_EMPHASIS_EN BIT(9) +#define DSI_CPHY_EN BIT(3) +#define DSI_HSTX_LDO_REF_SEL GENMASK(9, 6) +#define HFP_HS_EN BIT(31) + +#define MIPITX_CPHY_LANE_SEL0_SETTING 0x65432101 +#define MIPITX_CPHY_LANE_SEL1_SETTING 0x24210987 +#define MIPITX_CPHY_LANE_SEL2_SETTING 0x68543102 +#define MIPITX_CPHY_LANE_SEL3_SETTING 0x00000007 + +void mtk_dsi_cphy_lane_sel_setting(void) +{ + write32(&mipi_tx->phy_sel[0], MIPITX_CPHY_LANE_SEL0_SETTING); + write32(&mipi_tx->phy_sel[1], MIPITX_CPHY_LANE_SEL1_SETTING); + write32(&mipi_tx->phy_sel[2], MIPITX_CPHY_LANE_SEL2_SETTING); + write32(&mipi_tx->phy_sel[3], MIPITX_CPHY_LANE_SEL3_SETTING); +} + +void mtk_dsi_cphy_enable(void) +{ + setbits32(&mipi_tx->lane_con, DSI_CPHY_EN); +} + +void mtk_dsi_cphy_disable_ck_mode(void) +{ + clrsetbits32(&mipi_tx->voltage_sel, DSI_HSTX_LDO_REF_SEL, 0xF << 6); + clrbits32(&mipi_tx->ck_ckmode_en, DSI_CK_CKMODE_EN); + setbits32(&mipi_tx->lane_con, DE_EMPHASIS_EN); +} + +void mtk_dsi_cphy_enable_cmdq_6byte(void) +{ + clrbits32(&dsi0->dsi_cmd_type1_hs, CMD_CPHY_6BYTE_EN); +} + +void mtk_dsi_cphy_timing(u32 data_rate, struct mtk_phy_timing *timing) +{ + u32 cycle_time, value; + + data_rate = data_rate / MHz; + cycle_time = 7000 / data_rate; + printk(BIOS_INFO, "cycle_time = %d data_rate= %d\n", cycle_time, data_rate); + /* spec. lpx > 50ns */ + timing->lpx = DIV_ROUND_UP(75, cycle_time); + /* spec. 38ns < hs_prpr < 95ns */ + timing->da_hs_prepare = DIV_ROUND_UP(64, cycle_time); + /* spec. 7ui < hs_zero(prebegin) < 448ui */ + timing->da_hs_zero = 48; + /* spec. 7ui < hs_trail(post) < 224ui */ + timing->da_hs_trail = 32; + + /* spec. ta_get = 5*lpx */ + timing->ta_get = 5 * timing->lpx; + /* spec. ta_sure = 1.5*lpx */ + timing->ta_sure = 3 * timing->lpx / 2; + /* spec. ta_go = 4*lpx */ + timing->ta_go = 4 * timing->lpx; + /* spec. da_hs_exit > 100ns */ + timing->da_hs_exit = DIV_ROUND_UP(125, cycle_time); + + /* Allow board-specific tuning. */ + mtk_dsi_override_phy_timing(timing); + + value = timing->lpx | timing->da_hs_prepare << 8 | + timing->da_hs_zero << 16 | timing->da_hs_trail << 24; + write32(&dsi0->dsi_phy_timecon0, value); + + value = timing->ta_go | timing->ta_sure << 8 | + timing->ta_get << 16 | timing->da_hs_exit << 24; + write32(&dsi0->dsi_phy_timecon1, value); + + write32(&dsi0->dsi_cphy_con0, 0x012C0003); + write32(&dsi0->dsi_bllp_wc, 16 * 3); +} + +void mtk_dsi_cphy_vdo_timing(const u32 lanes, + const struct edid *edid, + const struct mtk_phy_timing *phy_timing, + const u32 bytes_per_pixel, + const u32 hbp, + const u32 hfp, + s32 *hbp_byte, + s32 *hfp_byte, + u32 *hsync_active_byte) +{ + s32 active_byte, phy_cycle, phy_trail, tmp; + u32 hs_vb_ps_wc, ps_wc, data_phy_cycles; + + active_byte = edid->mode.hspw * bytes_per_pixel - 10 * lanes - 26; + *hsync_active_byte = MAX(4, active_byte); + active_byte = hbp * bytes_per_pixel - 12 * lanes - 26; + *hbp_byte = MAX(4, active_byte); + data_phy_cycles = phy_timing->lpx + phy_timing->da_hs_prepare + + phy_timing->da_hs_zero + phy_timing->da_hs_exit + 5; + phy_cycle = 8 * lanes + 28 + 2 * data_phy_cycles * lanes; + phy_trail = 2 * (phy_timing->da_hs_trail + 1) * lanes - 6 * lanes - 14; + tmp = hfp * bytes_per_pixel - phy_cycle; + *hfp_byte = MIN(MAX(8, tmp), phy_trail); + ps_wc = edid->mode.ha * bytes_per_pixel; + hs_vb_ps_wc = ps_wc - (phy_timing->lpx + phy_timing->da_hs_exit + + phy_timing->da_hs_prepare + phy_timing->da_hs_zero + 2) * lanes; + *hfp_byte |= hs_vb_ps_wc << 16 | HFP_HS_EN; +} diff --git a/src/soc/mediatek/common/mtk_mipi_dphy.c b/src/soc/mediatek/common/mtk_mipi_dphy.c index d50a7898be..278f578cf2 100644 --- a/src/soc/mediatek/common/mtk_mipi_dphy.c +++ b/src/soc/mediatek/common/mtk_mipi_dphy.c @@ -1,63 +1,9 @@ /* SPDX-License-Identifier: GPL-2.0-only */ -#include #include -#include #include -#include -#include -void mtk_dsi_configure_mipi_tx(u32 data_rate, u32 lanes) +void mtk_dsi_dphy_disable_ck_mode(void) { - unsigned int txdiv0, txdiv1; - u64 pcw; - - if (data_rate >= 2000 * MHz) { - txdiv0 = 0; - txdiv1 = 0; - } else if (data_rate >= 1000 * MHz) { - txdiv0 = 1; - txdiv1 = 0; - } else if (data_rate >= 500 * MHz) { - txdiv0 = 2; - txdiv1 = 0; - } else if (data_rate > 250 * MHz) { - /* (data_rate == 250MHz) is a special case that should go to the - else-block below (txdiv0 = 4) */ - txdiv0 = 3; - txdiv1 = 0; - } else { - /* MIN = 125 */ - assert(data_rate >= MTK_DSI_DATA_RATE_MIN_MHZ * MHz); - txdiv0 = 4; - txdiv1 = 0; - } - - clrbits32(&mipi_tx->pll_con4, BIT(11) | BIT(10)); - setbits32(&mipi_tx->pll_pwr, AD_DSI_PLL_SDM_PWR_ON); - udelay(30); - clrbits32(&mipi_tx->pll_pwr, AD_DSI_PLL_SDM_ISO_EN); - - pcw = (u64)data_rate * (1 << txdiv0) * (1 << txdiv1); - pcw <<= 24; - pcw /= CLK26M_HZ; - - write32(&mipi_tx->pll_con0, pcw); - clrsetbits32(&mipi_tx->pll_con1, RG_DSI_PLL_POSDIV, txdiv0 << 8); - udelay(30); - setbits32(&mipi_tx->pll_con1, RG_DSI_PLL_EN); - - /* BG_LPF_EN / BG_CORE_EN */ - write32(&mipi_tx->lane_con, 0x3fff0180); - udelay(40); - write32(&mipi_tx->lane_con, 0x3fff00c0); - - /* Switch OFF each Lane */ - clrbits32(&mipi_tx->d0_sw_ctl_en, DSI_SW_CTL_EN); - clrbits32(&mipi_tx->d1_sw_ctl_en, DSI_SW_CTL_EN); - clrbits32(&mipi_tx->d2_sw_ctl_en, DSI_SW_CTL_EN); - clrbits32(&mipi_tx->d3_sw_ctl_en, DSI_SW_CTL_EN); - clrbits32(&mipi_tx->ck_sw_ctl_en, DSI_SW_CTL_EN); - setbits32(&mipi_tx->ck_ckmode_en, DSI_CK_CKMODE_EN); } diff --git a/src/soc/mediatek/mt8173/dsi.c b/src/soc/mediatek/mt8173/dsi.c index ad379aecf5..c47634ef4e 100644 --- a/src/soc/mediatek/mt8173/dsi.c +++ b/src/soc/mediatek/mt8173/dsi.c @@ -7,7 +7,7 @@ #include #include -void mtk_dsi_configure_mipi_tx(u32 data_rate, u32 lanes) +void mtk_dsi_configure_mipi_tx(u32 data_rate, u32 lanes, bool is_cphy) { u32 txdiv0, txdiv1; u64 pcw;