diff options
author | Hung-Te Lin <hungte@chromium.org> | 2019-08-07 09:59:16 +0800 |
---|---|---|
committer | Julius Werner <jwerner@chromium.org> | 2019-08-14 21:16:09 +0000 |
commit | ff0945e8ec8162d463ee017a86d1423dc51dd633 (patch) | |
tree | 3781f70c445689e4f472b89706baabc268b234ba /src/soc | |
parent | 4a73bf8378d8e36f0bae1488aa0b17cb5d5bd4ce (diff) |
soc/mediatek: dsi: Refactor PHY timing calculation
The PHY timing should be calculated by data rate (Mbps). However for
8173 some values were hard-coded so we want to introduce a new
mtk_phy_timing structure and a weak function mtk_dsi_override_phy_timing
that allows per-SOC customization to apply PHY timings.
BUG=b:80501386,b:117254947
TEST=make -j # board = oak and boots
Change-Id: I1176ca06dda026029ff431aca7f9e21479eed670
Signed-off-by: Hung-Te Lin <hungte@chromium.org>
Reviewed-on: https://review.coreboot.org/c/coreboot/+/34771
Tested-by: build bot (Jenkins) <no-reply@coreboot.org>
Reviewed-by: Julius Werner <jwerner@chromium.org>
Diffstat (limited to 'src/soc')
-rw-r--r-- | src/soc/mediatek/common/dsi.c | 56 | ||||
-rw-r--r-- | src/soc/mediatek/common/include/soc/dsi_common.h | 23 | ||||
-rw-r--r-- | src/soc/mediatek/mt8173/dsi.c | 17 |
3 files changed, 83 insertions, 13 deletions
diff --git a/src/soc/mediatek/common/dsi.c b/src/soc/mediatek/common/dsi.c index 12d536b497..1a768a59a5 100644 --- a/src/soc/mediatek/common/dsi.c +++ b/src/soc/mediatek/common/dsi.c @@ -19,6 +19,7 @@ #include <delay.h> #include <edid.h> #include <soc/dsi.h> +#include <string.h> #include <timer.h> static unsigned int mtk_dsi_get_bits_per_pixel(u32 format) @@ -64,23 +65,51 @@ static int mtk_dsi_get_data_rate(u32 bits_per_pixel, u32 lanes, return data_rate; } -static void mtk_dsi_phy_timconfig(u32 data_rate) +__weak void mtk_dsi_override_phy_timing(struct mtk_phy_timing *timing) { - u32 timcon0, timcon1, timcon2, timcon3; - u32 cycle_time, ui, lpx; + /* Do nothing. */ +} + +static void mtk_dsi_phy_timing(int data_rate, struct mtk_phy_timing *phy_timing) +{ + u32 cycle_time, ui; ui = 1000 / data_rate + 0x01; cycle_time = 8000 / data_rate + 0x01; - lpx = 5; - timcon0 = (8 << 24) | (0xa << 16) | (0x6 << 8) | lpx; - timcon1 = (7 << 24) | (5 * lpx << 16) | ((3 * lpx) / 2) << 8 | - (4 * lpx); - timcon2 = ((DIV_ROUND_UP(0x64, cycle_time) + 0xa) << 24) | - (DIV_ROUND_UP(0x150, cycle_time) << 16); - timcon3 = (2 * lpx) << 16 | - DIV_ROUND_UP(80 + 52 * ui, cycle_time) << 8 | - DIV_ROUND_UP(0x40, cycle_time); + memset(phy_timing, 0, sizeof(*phy_timing)); + + phy_timing->lpx = DIV_ROUND_UP(60, cycle_time); + phy_timing->da_hs_prepare = DIV_ROUND_UP((40 + 5 * ui), cycle_time); + phy_timing->da_hs_zero = DIV_ROUND_UP((110 + 6 * ui), cycle_time); + phy_timing->da_hs_trail = DIV_ROUND_UP(((4 * ui) + 80), cycle_time); + + phy_timing->ta_go = 4U * phy_timing->lpx; + phy_timing->ta_sure = 3U * phy_timing->lpx / 2U; + phy_timing->ta_get = 5U * phy_timing->lpx; + phy_timing->da_hs_exit = 2U * phy_timing->lpx; + + phy_timing->da_hs_sync = 1; + phy_timing->clk_hs_zero = DIV_ROUND_UP(0x150U, cycle_time); + phy_timing->clk_hs_trail = DIV_ROUND_UP(0x64U, cycle_time) + 0xaU; + + phy_timing->clk_hs_prepare = DIV_ROUND_UP(0x40U, cycle_time); + phy_timing->clk_hs_post = DIV_ROUND_UP(80U + 52U * ui, cycle_time); + phy_timing->clk_hs_exit = 2U * phy_timing->lpx; + + /* Allow board-specific tuning. */ + mtk_dsi_override_phy_timing(phy_timing); + + u32 timcon0, timcon1, timcon2, timcon3; + + timcon0 = phy_timing->lpx | phy_timing->da_hs_prepare << 8 | + phy_timing->da_hs_zero << 16 | phy_timing->da_hs_trail << 24; + timcon1 = phy_timing->ta_go | phy_timing->ta_sure << 8 | + phy_timing->ta_get << 16 | phy_timing->da_hs_exit << 24; + timcon2 = phy_timing->da_hs_sync << 8 | phy_timing->clk_hs_zero << 16 | + phy_timing->clk_hs_trail << 24; + timcon3 = phy_timing->clk_hs_prepare | phy_timing->clk_hs_post << 8 | + phy_timing->clk_hs_exit << 16; write32(&dsi0->dsi_phy_timecon0, timcon0); write32(&dsi0->dsi_phy_timecon1, timcon1); @@ -219,7 +248,8 @@ int mtk_dsi_init(u32 mode_flags, u32 format, u32 lanes, const struct edid *edid) mtk_dsi_configure_mipi_tx(data_rate, lanes); mtk_dsi_reset(); - mtk_dsi_phy_timconfig(data_rate); + struct mtk_phy_timing phy_timing; + mtk_dsi_phy_timing(data_rate, &phy_timing); mtk_dsi_rxtx_control(mode_flags, lanes); mtk_dsi_clk_hs_mode_disable(); mtk_dsi_config_vdo_timing(mode_flags, format, edid); diff --git a/src/soc/mediatek/common/include/soc/dsi_common.h b/src/soc/mediatek/common/include/soc/dsi_common.h index 7241097380..bfdd4073d6 100644 --- a/src/soc/mediatek/common/include/soc/dsi_common.h +++ b/src/soc/mediatek/common/include/soc/dsi_common.h @@ -300,10 +300,33 @@ enum { MIPI_DCS_READ_DDB_CONTINUE = 0xA8, }; +struct mtk_phy_timing { + u8 lpx; + u8 da_hs_prepare; + u8 da_hs_zero; + u8 da_hs_trail; + + u8 ta_go; + u8 ta_sure; + u8 ta_get; + u8 da_hs_exit; + + u8 da_hs_sync; + u8 clk_hs_zero; + u8 clk_hs_trail; + + u8 clk_hs_prepare; + u8 clk_hs_post; + u8 clk_hs_exit; +}; + /* Functions that each SOC should provide. */ void mtk_dsi_reset(void); void mtk_dsi_configure_mipi_tx(int 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.c */ int mtk_dsi_init(u32 mode_flags, u32 format, u32 lanes, const struct edid *edid); diff --git a/src/soc/mediatek/mt8173/dsi.c b/src/soc/mediatek/mt8173/dsi.c index 2e4a4bd58a..32f4f1ce1c 100644 --- a/src/soc/mediatek/mt8173/dsi.c +++ b/src/soc/mediatek/mt8173/dsi.c @@ -107,6 +107,23 @@ void mtk_dsi_reset(void) clrbits_le32(&dsi0->dsi_con_ctrl, 1); } +void mtk_dsi_override_phy_timing(struct mtk_phy_timing *timing) +{ + int lpx = 5; + timing->lpx = lpx; + timing->da_hs_prepare = 6; + timing->da_hs_zero = 10; + timing->da_hs_trail = 8; + + timing->ta_go = 4 * lpx; + timing->ta_sure = 3 * lpx / 2; + timing->ta_get = 5 * lpx; + timing->da_hs_exit = 7; + + timing->da_hs_sync = 0; + timing->clk_hs_exit = 2 * lpx; +} + void mtk_dsi_pin_drv_ctrl(void) { struct stopwatch sw; |