Sovle dsi&hdmi refresh probelm at the time of STD

This commit is contained in:
yunxian.zyf
2024-02-22 11:39:03 +08:00
committed by Han Gao
parent 15d53ae438
commit f50a437148
4 changed files with 95 additions and 8 deletions

View File

@@ -34,6 +34,7 @@
#include <drm/drm_print.h>
#include <drm/drm_probe_helper.h>
#include <drm/drm_scdc_helper.h>
#include <linux/suspend.h>
#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))

View File

@@ -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 = &lt8911_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);

View File

@@ -28,7 +28,7 @@
#include <video/mipi_display.h>
#if 1
#if 0
#define DBG_FUNC(format, x...) printk(KERN_ERR "[DSI]%s:" format"\n", __func__, ##x)
#define DBG_PRINT(format, x...) printk(KERN_ERR "[DSI]" format"\n", ##x)
#else
@@ -61,6 +61,8 @@ struct i2c_mipi_dsi {
struct regulator *hsvcc;
struct regulator *vspn3v3;
struct notifier_block pm_notify;
// panel
struct drm_panel panel;
struct panel_data *desc;

View File

@@ -158,7 +158,7 @@ static int dw_hdmi_light_probe(struct platform_device *pdev)
static int dw_hdmi_light_remove(struct platform_device *pdev)
{
component_del(&pdev->dev, &dw_hdmi_light_ops);
component_del(&pdev->dev, &dw_hdmi_light_ops);
return 0;
}
@@ -181,10 +181,10 @@ static int hdmi_runtime_resume(struct device *dev)
#ifdef CONFIG_PM_SLEEP
static int hdmi_resume(struct device *dev)
{
struct light_hdmi *hdmi = dev_get_drvdata(dev);
dev_info(dev,"hdmi resume\n");
dw_hdmi_resume(hdmi->dw_hdmi);
return 0;
struct light_hdmi *hdmi = dev_get_drvdata(dev);
dev_info(dev,"hdmi resume\n");
dw_hdmi_resume(hdmi->dw_hdmi);
return 0;
}
#endif
static const struct dev_pm_ops dw_hdmi_pm_ops = {