diff --git a/src/soc/mediatek/common/display.c b/src/soc/mediatek/common/display.c index 3b9d8be96c..d1fce217a6 100644 --- a/src/soc/mediatek/common/display.c +++ b/src/soc/mediatek/common/display.c @@ -16,6 +16,7 @@ #include #include +static u32 dsi_mode_flags; static struct panel_serializable_data *mipi_data; static struct panel_serializable_data *get_mipi_cmd_from_cbfs(struct panel_description *desc) @@ -172,6 +173,8 @@ int mtk_display_init(void) lanes = 4; } + dsi_mode_flags = mipi_dsi_flags; + 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__); @@ -219,6 +222,14 @@ int mtk_display_init(void) return 0; } +int mtk_mipi_panel_poweroff(void) +{ + if (!mipi_data) + return 0; + + return mtk_dsi_panel_poweroff(dsi_mode_flags, mipi_data->poweroff); +} + u32 mtk_get_vrefresh(const struct edid *edid) { u32 width = edid->mode.ha; diff --git a/src/soc/mediatek/common/dsi_common.c b/src/soc/mediatek/common/dsi_common.c index 6f8d640845..04dc0a85c3 100644 --- a/src/soc/mediatek/common/dsi_common.c +++ b/src/soc/mediatek/common/dsi_common.c @@ -444,6 +444,11 @@ static void mtk_dsi_reset_phy(struct dsi_regs *const dsi_reg) clrbits32(&dsi_reg->dsi_con_ctrl, DPHY_RESET); } +static void mtk_dsi_stop(struct dsi_regs *dsi) +{ + write32(&dsi->dsi_start, 0); +} + int mtk_dsi_init(u32 mode_flags, u32 format, u32 lanes, const struct edid *edid, const u8 *init_commands) { @@ -502,3 +507,45 @@ int mtk_dsi_init(u32 mode_flags, u32 format, u32 lanes, const struct edid *edid, return 0; } + +int mtk_dsi_panel_poweroff(u32 mode_flags, const u8 *poweroff_cmds) +{ + int ret; + unsigned int num_dsi = (mode_flags & MIPI_DSI_DUAL_CHANNEL) ? 2 : 1; + + /* Stop DSI-0 engine */ + mtk_dsi_stop(dsi_mipi_regs[0].dsi_reg); + + /* Wait for DSI engines to become idle */ + for (unsigned int i = 0; i < num_dsi; i++) { + struct dsi_regs *dsi = dsi_mipi_regs[i].dsi_reg; + + if (!wait_ms(20, !(read32(&dsi->dsi_intsta) & DSI_BUSY))) { + u32 intsta = read32(&dsi->dsi_intsta); + + printk(BIOS_ERR, "%s: Timeout (20ms) waiting for DSI-%d idle " + "and the panel may not power-off properly. " + "DSI_INTSTA=0x%08x.\n", + __func__, i, intsta); + return -1; + } + + write32(&dsi->dsi_intsta, 0); + write32(&dsi->dsi_mode_ctrl, CMD_MODE); + } + + /* Send panel poweroff commands */ + ret = mipi_panel_parse_commands(poweroff_cmds, mtk_dsi_cmdq, + &mode_flags); + + /* Final shutdown: stop + disable PHY */ + mtk_dsi_stop(dsi_mipi_regs[0].dsi_reg); + + for (unsigned int i = 0; i < num_dsi; i++) { + struct dsi_regs *dsi = dsi_mipi_regs[i].dsi_reg; + + write32(&dsi->dsi_phy_lccon, 0x0); + } + + return ret; +} diff --git a/src/soc/mediatek/common/include/soc/display.h b/src/soc/mediatek/common/include/soc/display.h index 3e3b4a2164..87a6a04d9d 100644 --- a/src/soc/mediatek/common/include/soc/display.h +++ b/src/soc/mediatek/common/include/soc/display.h @@ -32,6 +32,7 @@ struct panel_description { struct panel_description *get_active_panel(void); void mtk_display_disable_secure_mode(void); int mtk_display_init(void); +int mtk_mipi_panel_poweroff(void); void mtk_ddp_init(void); u32 mtk_get_vrefresh(const struct edid *edid); diff --git a/src/soc/mediatek/common/include/soc/display_dsi.h b/src/soc/mediatek/common/include/soc/display_dsi.h index 62bdb3cca3..6a51dca55a 100644 --- a/src/soc/mediatek/common/include/soc/display_dsi.h +++ b/src/soc/mediatek/common/include/soc/display_dsi.h @@ -51,5 +51,6 @@ enum { /* Public API for common display code (display.c). */ int mtk_dsi_init(u32 mode_flags, u32 format, u32 lanes, const struct edid *edid, const u8 *init_commands); +int mtk_dsi_panel_poweroff(u32 mode_flags, const u8 *poweroff_cmds); #endif /* SOC_MEDIATEK_DISPLAY_DSI_H */