[PATCH v2 3/3] drm/mediatek: fine tune the dsi panel's power sequence
From: Jitao Shi
Date: Sun Aug 08 2021 - 08:53:02 EST
Add the drm_panel_prepare_power and drm_panel_unprepare_power control.
Turn on panel power(drm_panel_prepare_power) and control before dsi
enable. And then dsi enable, send dcs cmd in drm_panel_prepare, last
turn on backlight.
Most dsi panels, have five steps when poweron.
1. turn on dsi signal to LP11 --> dsi host's action
2. turn on the power supplies, --> panel's action
3. send the DCS cmd to panel --> panel's action
4. start send video stream --> dsi host's action
5. turn on backlight. --> panel's action
we put "turn on the power supplies" and "send the DCS cmd to panel" in
panel_prepare. And "turn on backlight" in panel_enable.
But some other panels has a special poweron sequence as the following.
1. turn on the power supplies, --> panel's action
2. turn on dsi signal to LP11 --> dsi host's action
3. send the DCS cmd to panel --> panel's action
4. start send video stream --> dsi host's action
5. turn on backlight. --> panel's action
panel's actions are divided into three parts.
So I add a new api "drm_panel_prepare_power/rm_panel_unprepare_power" to
control the sequence.
Signed-off-by: Jitao Shi <jitao.shi@xxxxxxxxxxxx>
---
drivers/gpu/drm/mediatek/mtk_dsi.c | 29 ++++++++++++++++++++++++-----
1 file changed, 24 insertions(+), 5 deletions(-)
diff --git a/drivers/gpu/drm/mediatek/mtk_dsi.c b/drivers/gpu/drm/mediatek/mtk_dsi.c
index ae403c67cbd9..24f89a1dd421 100644
--- a/drivers/gpu/drm/mediatek/mtk_dsi.c
+++ b/drivers/gpu/drm/mediatek/mtk_dsi.c
@@ -184,6 +184,7 @@ struct mtk_dsi {
struct drm_encoder encoder;
struct drm_bridge bridge;
struct drm_bridge *next_bridge;
+ struct drm_panel *panel;
struct drm_connector *connector;
struct phy *phy;
@@ -619,10 +620,18 @@ static int mtk_dsi_poweron(struct mtk_dsi *dsi)
dsi->data_rate = DIV_ROUND_UP_ULL(dsi->vm.pixelclock * bit_per_pixel,
dsi->lanes);
+ if (dsi->panel) {
+ ret = panel_bridge_prepare_power(dsi->next_bridge)
+ if (ret) {
+ DRM_INFO("can't prepare power the panel\n");
+ goto err_refcount;
+ }
+ }
+
ret = clk_set_rate(dsi->hs_clk, dsi->data_rate);
if (ret < 0) {
dev_err(dev, "Failed to set data rate: %d\n", ret);
- goto err_refcount;
+ goto err_prepare_power;
}
phy_power_on(dsi->phy);
@@ -665,6 +674,11 @@ static int mtk_dsi_poweron(struct mtk_dsi *dsi)
clk_disable_unprepare(dsi->engine_clk);
err_phy_power_off:
phy_power_off(dsi->phy);
+err_prepare_power:
+ if (dsi->panel) {
+ if (panel_bridge_unprepare_power(dsi->next_bridge))
+ dev_err(dev, "Can't unprepare power the panel\n");
+ }
err_refcount:
dsi->refcount--;
return ret;
@@ -698,6 +712,12 @@ static void mtk_dsi_poweroff(struct mtk_dsi *dsi)
clk_disable_unprepare(dsi->digital_clk);
phy_power_off(dsi->phy);
+
+ if (dsi->panel) {
+ ret = panel_bridge_unprepare_power(dsi->next_bridge);
+ if (ret)
+ dev_err(dev, "Can't unprepare power the panel ret:%d\n", ret);
+ }
}
static void mtk_output_dsi_enable(struct mtk_dsi *dsi)
@@ -1001,7 +1021,6 @@ static int mtk_dsi_probe(struct platform_device *pdev)
{
struct mtk_dsi *dsi;
struct device *dev = &pdev->dev;
- struct drm_panel *panel;
struct resource *regs;
int irq_num;
int ret;
@@ -1019,12 +1038,12 @@ static int mtk_dsi_probe(struct platform_device *pdev)
}
ret = drm_of_find_panel_or_bridge(dev->of_node, 0, 0,
- &panel, &dsi->next_bridge);
+ &dsi->panel, &dsi->next_bridge);
if (ret)
goto err_unregister_host;
- if (panel) {
- dsi->next_bridge = devm_drm_panel_bridge_add(dev, panel);
+ if (dsi->panel) {
+ dsi->next_bridge = devm_drm_panel_bridge_add(dev, dsi->panel);
if (IS_ERR(dsi->next_bridge)) {
ret = PTR_ERR(dsi->next_bridge);
goto err_unregister_host;
--
2.25.1