summaryrefslogtreecommitdiff
path: root/src/soc
diff options
context:
space:
mode:
Diffstat (limited to 'src/soc')
-rw-r--r--src/soc/mediatek/common/dsi.c92
1 files changed, 48 insertions, 44 deletions
diff --git a/src/soc/mediatek/common/dsi.c b/src/soc/mediatek/common/dsi.c
index 9222cb0c4b..be99fe8992 100644
--- a/src/soc/mediatek/common/dsi.c
+++ b/src/soc/mediatek/common/dsi.c
@@ -74,47 +74,43 @@ __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 *phy_timing)
+static void mtk_dsi_phy_timing(u32 data_rate, struct mtk_phy_timing *timing)
{
- u32 cycle_time, ui;
+ u32 timcon0, timcon1, timcon2, timcon3;
u32 data_rate_mhz = DIV_ROUND_UP(data_rate, MHz);
- ui = 1000 / data_rate_mhz + 0x01;
- cycle_time = 8000 / data_rate_mhz + 0x01;
-
- memset(phy_timing, 0, sizeof(*phy_timing));
+ memset(timing, 0, sizeof(*timing));
- phy_timing->lpx = DIV_ROUND_UP(60, cycle_time);
- phy_timing->da_hs_prepare = DIV_ROUND_UP((50 + 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) + 77), cycle_time);
+ 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 -
+ timing->da_hs_prepare;
+ timing->da_hs_trail = timing->da_hs_prepare + 1;
- 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;
+ timing->ta_go = 4 * timing->lpx - 2;
+ timing->ta_sure = timing->lpx + 2;
+ timing->ta_get = 4 * timing->lpx;
+ timing->da_hs_exit = 2 * timing->lpx + 1;
- 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;
+ timing->da_hs_sync = 1;
- 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;
+ timing->clk_hs_prepare = 70 * data_rate_mhz / (8 * 1000);
+ timing->clk_hs_post = timing->clk_hs_prepare + 8;
+ timing->clk_hs_trail = timing->clk_hs_prepare;
+ timing->clk_hs_zero = timing->clk_hs_trail * 4;
+ timing->clk_hs_exit = 2 * timing->clk_hs_trail;
/* Allow board-specific tuning. */
- mtk_dsi_override_phy_timing(phy_timing);
-
- u32 timcon0, timcon1, timcon2, timcon3;
+ mtk_dsi_override_phy_timing(timing);
- 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;
+ timcon0 = timing->lpx | timing->da_hs_prepare << 8 |
+ timing->da_hs_zero << 16 | timing->da_hs_trail << 24;
+ timcon1 = timing->ta_go | timing->ta_sure << 8 |
+ timing->ta_get << 16 | timing->da_hs_exit << 24;
+ timcon2 = timing->da_hs_sync << 8 | timing->clk_hs_zero << 16 |
+ timing->clk_hs_trail << 24;
+ timcon3 = timing->clk_hs_prepare | timing->clk_hs_post << 8 |
+ timing->clk_hs_exit << 16;
write32(&dsi0->dsi_phy_timecon0, timcon0);
write32(&dsi0->dsi_phy_timecon1, timcon1);
@@ -180,6 +176,8 @@ static void mtk_dsi_config_vdo_timing(u32 mode_flags, u32 format, u32 lanes,
const struct mtk_phy_timing *phy_timing)
{
u32 hsync_active_byte;
+ u32 hbp;
+ u32 hfp;
u32 hbp_byte;
u32 hfp_byte;
u32 vbp_byte;
@@ -199,17 +197,20 @@ static void mtk_dsi_config_vdo_timing(u32 mode_flags, u32 format, u32 lanes,
write32(&dsi0->dsi_vfp_nl, vfp_byte);
write32(&dsi0->dsi_vact_nl, edid->mode.va);
- unsigned int hspw = 0;
- if (mode_flags & MIPI_DSI_MODE_VIDEO_SYNC_PULSE)
- hspw = edid->mode.hspw;
-
- hbp_byte = (edid->mode.hbl - edid->mode.hso - hspw - edid->mode.hborder)
- * bytes_per_pixel - 10;
hsync_active_byte = edid->mode.hspw * bytes_per_pixel - 10;
- hfp_byte = (edid->mode.hso - edid->mode.hborder) * bytes_per_pixel;
+
+ 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 + 2;
+ phy_timing->da_hs_zero + phy_timing->da_hs_exit + 3;
u32 delta = 12;
if (mode_flags & MIPI_DSI_MODE_VIDEO_BURST)
@@ -218,11 +219,14 @@ static void mtk_dsi_config_vdo_timing(u32 mode_flags, u32 format, u32 lanes,
u32 d_phy = phy_timing->d_phy;
if (d_phy == 0)
d_phy = data_phy_cycles * lanes + delta;
- if (hfp_byte > d_phy)
- hfp_byte -= d_phy;
- else
- printk(BIOS_ERR, "HFP is not greater than d-phy, FPS < 60Hz "
- "and the panel may not work properly.\n");
+
+ if ((hfp + hbp) * bytes_per_pixel > d_phy) {
+ hfp_byte -= d_phy * hfp / (hfp + hbp);
+ hbp_byte -= d_phy * hbp / (hfp + hbp);
+ } else {
+ printk(BIOS_ERR, "HFP plus HBP is not greater than d_phy, "
+ "the panel may not work properly.\n");
+ }
write32(&dsi0->dsi_hsa_wc, hsync_active_byte);
write32(&dsi0->dsi_hbp_wc, hbp_byte);