diff --git a/drivers/gpu/drm/bridge/synopsys/dw-hdmi.c b/drivers/gpu/drm/bridge/synopsys/dw-hdmi.c index 4e1d1104d..47e8aeb11 100644 --- a/drivers/gpu/drm/bridge/synopsys/dw-hdmi.c +++ b/drivers/gpu/drm/bridge/synopsys/dw-hdmi.c @@ -34,6 +34,7 @@ #include #include #include +#include #include "dw-hdmi-audio.h" #include "dw-hdmi-cec.h" @@ -219,8 +220,12 @@ struct dw_hdmi { hdmi_codec_plugged_cb plugged_cb; struct device *codec_dev; enum drm_connector_status last_connector_result; + + struct notifier_block pm_notify; /*Used to receive STD notification*/ }; +static bool g_is_hdmi_std_suspend __nosavedata; + #define HDMI_IH_PHY_STAT0_RX_SENSE \ (HDMI_IH_PHY_STAT0_RX_SENSE0 | HDMI_IH_PHY_STAT0_RX_SENSE1 | \ HDMI_IH_PHY_STAT0_RX_SENSE2 | HDMI_IH_PHY_STAT0_RX_SENSE3) @@ -1431,6 +1436,11 @@ static int dw_hdmi_phy_power_on(struct dw_hdmi *hdmi) unsigned int i; u8 val; + if(g_is_hdmi_std_suspend){ + printk(KERN_INFO "dw_hdmi_phy_power_on under std mod, do not resume\n"); + return 0; + } + if (phy->gen == 1) { dw_hdmi_phy_enable_powerdown(hdmi, false); @@ -3284,6 +3294,27 @@ static void dw_hdmi_init_hw(struct dw_hdmi *hdmi) hdmi->phy.ops->setup_hpd(hdmi, hdmi->phy.data); } +static int hdmi_light_notify(struct notifier_block *notify_block, + unsigned long mode, void *unused) +{ + printk(KERN_INFO"pm_notify: mode (%ld)\n", mode); + + switch (mode) { + case PM_HIBERNATION_PREPARE: + printk(KERN_INFO"hdmi_pm_notify PM_HIBERNATION_PREPARE\n"); + g_is_hdmi_std_suspend = true; + break; + case PM_POST_HIBERNATION: + printk(KERN_INFO"hdmi_pm_notify PM_HIBERNATION_PREPARE\n"); + g_is_hdmi_std_suspend = false; + break; + default: + break; + } + + return NOTIFY_DONE; +} + /* ----------------------------------------------------------------------------- * Probe/remove API, used from platforms based on the DRM bridge API. */ @@ -3551,6 +3582,13 @@ struct dw_hdmi *dw_hdmi_probe(struct platform_device *pdev, drm_bridge_add(&hdmi->bridge); + if (IS_ENABLED(CONFIG_PM)) + hdmi->pm_notify.notifier_call = hdmi_light_notify; + + ret = register_pm_notifier(&hdmi->pm_notify); + if (ret) + printk(KERN_ERR"register_pm_notifier failed: %d\n", ret); + return hdmi; err_res: @@ -3562,6 +3600,8 @@ EXPORT_SYMBOL_GPL(dw_hdmi_probe); void dw_hdmi_remove(struct dw_hdmi *hdmi) { + unregister_pm_notifier(&hdmi->pm_notify); + drm_bridge_remove(&hdmi->bridge); if (hdmi->audio && !IS_ERR(hdmi->audio)) diff --git a/drivers/gpu/drm/panel/panel-lt8911.c b/drivers/gpu/drm/panel/panel-lt8911.c index 524248247..8652671d8 100644 --- a/drivers/gpu/drm/panel/panel-lt8911.c +++ b/drivers/gpu/drm/panel/panel-lt8911.c @@ -11,6 +11,7 @@ #define LT_8911_I2C_ADDR 0x45 static struct i2c_mipi_dsi *g_lt8911_mipi_dsi = NULL; +static bool g_is_std_suspend __nosavedata; static const struct drm_display_mode lt8911_default_mode = { .clock = 152840, @@ -502,6 +503,11 @@ static int panel_prepare(struct drm_panel *panel) DBG_FUNC("lt8911exb enter\n"); + if(g_is_std_suspend){ + DBG_FUNC("lt8911exb prepare under std mode, do not prepare\n"); + return 0; + } + if(md->client == NULL){ DBG_FUNC("lt8911exb i2c client still not ready\n"); return 0; @@ -558,7 +564,12 @@ static int panel_enable(struct drm_panel *panel) int ret = 0; struct i2c_mipi_dsi *md = panel_to_md(panel); - DBG_FUNC("panel_unprepare enter\n"); + DBG_FUNC("panel_enable enter\n"); + + if(g_is_std_suspend){ + DBG_FUNC("lt8911exb enable under std mode, do not enable\n"); + return 0; + } gpio_set_value(md->backlight_pin, 1); @@ -633,7 +644,6 @@ static int backlight_update(struct backlight_device *bd) } md->brightness = brightness; - //i2c_md_write(md, REG_PWM, brightness); return 0; } @@ -643,6 +653,30 @@ static const struct backlight_ops backlight_ops = { .update_status = backlight_update, }; +static int lt8911_pm_notify(struct notifier_block *notify_block, + unsigned long mode, void *unused) +{ + struct i2c_mipi_dsi *ctx = container_of( + notify_block, struct i2c_mipi_dsi, pm_notify); + + DBG_FUNC("pm_notify: mode (%ld)\n", mode); + + switch (mode) { + case PM_HIBERNATION_PREPARE: + DBG_FUNC("pm_notify PM_HIBERNATION_PREPARE\n"); + g_is_std_suspend = true; + break; + case PM_POST_HIBERNATION: + DBG_FUNC("pm_notify PM_HIBERNATION_PREPARE\n"); + g_is_std_suspend = false; + break; + default: + break; + } + + return NOTIFY_DONE; +} + /** static int backlight_init(struct i2c_mipi_dsi *md) { @@ -850,6 +884,8 @@ static int lt8911_dsi_probe(struct mipi_dsi_device *dsi) if(ctx->client == NULL){ return -EPROBE_DEFER; } + + g_is_std_suspend = false; ctx->dsi = dsi; ctx->desc = <8911_panel_data; @@ -876,6 +912,13 @@ static int lt8911_dsi_probe(struct mipi_dsi_device *dsi) //backlight_init(ctx); + if (IS_ENABLED(CONFIG_PM)) + ctx->pm_notify.notifier_call = lt8911_pm_notify; + + ret = register_pm_notifier(&ctx->pm_notify); + if (ret) + DBG_FUNC("register_pm_notifier failed: %d\n", ret); + ret = mipi_dsi_attach(dsi); if (ret < 0) { @@ -889,6 +932,8 @@ static int lt8911_dsi_remove(struct mipi_dsi_device *dsi) { struct i2c_mipi_dsi *ctx = mipi_dsi_get_drvdata(dsi); + unregister_pm_notifier(&ctx->pm_notify); + mipi_dsi_detach(dsi); drm_panel_remove(&ctx->panel); diff --git a/drivers/gpu/drm/panel/panel-lt8911.h b/drivers/gpu/drm/panel/panel-lt8911.h index dd1e5c890..7143dfa55 100644 --- a/drivers/gpu/drm/panel/panel-lt8911.h +++ b/drivers/gpu/drm/panel/panel-lt8911.h @@ -28,7 +28,7 @@ #include