From 5723ff1f5e032d63df842b58338b75d4477d309d Mon Sep 17 00:00:00 2001 From: Guochun Huang Date: Fri, 13 Oct 2023 07:39:11 +0000 Subject: [PATCH] misc: rk628: hdmitx: disable/enable display when system suspend/resume Change-Id: I7cbd1bfeff186d3333473f3944ae1d15f78ae31d Signed-off-by: Guochun Huang --- drivers/misc/rk628/rk628.c | 5 ++- drivers/misc/rk628/rk628.h | 1 + drivers/misc/rk628/rk628_hdmitx.c | 61 +++++++++++++++++++------------ drivers/misc/rk628/rk628_hdmitx.h | 12 ++++++ 4 files changed, 54 insertions(+), 25 deletions(-) diff --git a/drivers/misc/rk628/rk628.c b/drivers/misc/rk628/rk628.c index 762109eca9f2..dfd261914dd8 100644 --- a/drivers/misc/rk628/rk628.c +++ b/drivers/misc/rk628/rk628.c @@ -401,6 +401,9 @@ static void rk628_display_disable(struct rk628 *rk628) if (rk628_input_is_hdmi(rk628)) rk628_hdmirx_disable(rk628); + if (rk628_output_is_hdmi(rk628)) + rk628_hdmitx_disable(rk628); + rk628->display_enabled = false; } @@ -448,10 +451,8 @@ static void rk628_display_enable(struct rk628 *rk628) if (rk628_output_is_csi(rk628)) rk628_csi_enable(rk628); -#ifdef CONFIG_RK628_MISC_HDMITX if (rk628_output_is_hdmi(rk628)) rk628_hdmitx_enable(rk628); -#endif rk628->display_enabled = true; } diff --git a/drivers/misc/rk628/rk628.h b/drivers/misc/rk628/rk628.h index c76a898b5e7b..98605c0ea526 100644 --- a/drivers/misc/rk628/rk628.h +++ b/drivers/misc/rk628/rk628.h @@ -451,6 +451,7 @@ struct rk628 { struct delayed_work dsi_delay_work; struct rk628_panel_simple *panel; void *hdmirx; + void *hdmitx; bool display_enabled; u32 input_mode; u32 output_mode; diff --git a/drivers/misc/rk628/rk628_hdmitx.c b/drivers/misc/rk628/rk628_hdmitx.c index eaa1c2ea0cec..b58de5f563da 100644 --- a/drivers/misc/rk628/rk628_hdmitx.c +++ b/drivers/misc/rk628/rk628_hdmitx.c @@ -709,13 +709,6 @@ static void rk628_hdmi_bridge_enable(struct drm_bridge *bridge) rk628_hdmi_set_pwr_mode(hdmi, NORMAL); } -static void rk628_hdmi_bridge_disable(struct drm_bridge *bridge) -{ - struct rk628_hdmi *hdmi = bridge_to_hdmi(bridge); - - rk628_hdmi_set_pwr_mode(hdmi, LOWER_PWR); -} - static int rk628_hdmi_bridge_attach(struct drm_bridge *bridge, enum drm_bridge_attach_flags flags) { @@ -760,7 +753,6 @@ static const struct drm_bridge_funcs rk628_hdmi_bridge_funcs = { .mode_set = rk628_hdmi_bridge_mode_set, .mode_fixup = rk628_hdmi_bridge_mode_fixup, .enable = rk628_hdmi_bridge_enable, - .disable = rk628_hdmi_bridge_disable, }; static int @@ -1091,6 +1083,15 @@ static struct i2c_adapter *rk628_hdmi_i2c_adapter(struct rk628_hdmi *hdmi) return adap; } +void rk628_hdmitx_disable(struct rk628 *rk628) +{ + rk628_i2c_update_bits(rk628, HDMI_SYS_CTRL, POWER_MASK, PWR_OFF(1)); + rk628_i2c_write(rk628, HDMI_PHY_DRIVER, 0x00); + rk628_i2c_write(rk628, HDMI_PHY_PRE_EMPHASIS, 0x00); + rk628_i2c_write(rk628, HDMI_PHY_CHG_PWR, 0x00); + rk628_i2c_write(rk628, HDMI_PHY_SYS_CTL, 0x15); +} + int rk628_hdmitx_enable(struct rk628 *rk628) { struct device *dev = rk628->dev; @@ -1098,6 +1099,32 @@ int rk628_hdmitx_enable(struct rk628 *rk628) int irq; int ret; + /* select int io function */ + rk628_i2c_write(rk628, GRF_GPIO0AB_SEL_CON, 0x70007000); + rk628_i2c_write(rk628, GRF_GPIO0AB_SEL_CON, 0x055c055c); + + /* hdmitx vclk pllref select Pin_vclk */ + rk628_i2c_update_bits(rk628, GRF_POST_PROC_CON, + SW_HDMITX_VCLK_PLLREF_SEL_MASK, + SW_HDMITX_VCLK_PLLREF_SEL(1)); + /* set output mode to HDMI */ + rk628_i2c_update_bits(rk628, GRF_SYSTEM_CON0, SW_OUTPUT_MODE_MASK, + SW_OUTPUT_MODE(OUTPUT_MODE_HDMI)); + /* hdmitx int en */ + rk628_i2c_write(rk628, GRF_INTR0_EN, 0x00040004); + + + if (rk628->hdmitx) { + hdmi = rk628->hdmitx; + rk628_hdmi_reset(hdmi); + rk628_hdmi_i2c_init(hdmi); + /* Unmute hotplug interrupt */ + hdmi_modb(hdmi, HDMI_STATUS, MASK_INT_HOTPLUG_MASK, + MASK_INT_HOTPLUG(1)); + + return 0; + } + if (!of_device_is_available(dev->of_node)) return -ENODEV; @@ -1108,24 +1135,13 @@ int rk628_hdmitx_enable(struct rk628 *rk628) hdmi->dev = dev; hdmi->rk628 = rk628; + rk628->hdmitx = hdmi; irq = rk628->client->irq; if (irq < 0) return irq; dev_set_drvdata(dev, hdmi); - /* selete int io function */ - rk628_i2c_write(rk628, GRF_GPIO0AB_SEL_CON, 0x70007000); - rk628_i2c_write(rk628, GRF_GPIO0AB_SEL_CON, 0x055c055c); - - /* hdmitx vclk pllref select Pin_vclk */ - rk628_i2c_update_bits(rk628, GRF_POST_PROC_CON, - SW_HDMITX_VCLK_PLLREF_SEL_MASK, - SW_HDMITX_VCLK_PLLREF_SEL(1)); - /* set output mode to HDMI */ - rk628_i2c_update_bits(rk628, GRF_SYSTEM_CON0, SW_OUTPUT_MODE_MASK, - SW_OUTPUT_MODE(OUTPUT_MODE_HDMI)); - rk628_hdmi_reset(hdmi); hdmi->ddc = rk628_hdmi_i2c_adapter(hdmi); @@ -1142,9 +1158,6 @@ int rk628_hdmitx_enable(struct rk628 *rk628) * and reconfigure the DDC clock. */ hdmi->tmds_rate = 24000 * 1000; - - /* hdmitx int en */ - rk628_i2c_write(rk628, GRF_INTR0_EN, 0x00040004); rk628_hdmi_i2c_init(hdmi); rk628_hdmi_audio_codec_init(hdmi, dev); @@ -1190,6 +1203,8 @@ int rk628_hdmitx_enable(struct rk628 *rk628) return 0; fail: + devm_kfree(dev, hdmi); + rk628->hdmitx = NULL; return ret; } diff --git a/drivers/misc/rk628/rk628_hdmitx.h b/drivers/misc/rk628/rk628_hdmitx.h index 9a1b3b8fa9fa..60baf9e92a16 100644 --- a/drivers/misc/rk628/rk628_hdmitx.h +++ b/drivers/misc/rk628/rk628_hdmitx.h @@ -345,6 +345,18 @@ enum { #define HDMI_MAX_REG HDMITX_REG(0xed) +#ifdef CONFIG_RK628_MISC_HDMITX +void rk628_hdmitx_disable(struct rk628 *rk628); int rk628_hdmitx_enable(struct rk628 *rk628); +#else +static inline void rk628_hdmitx_disable(struct rk628 *rk628) +{ +} + +static inline int rk628_hdmitx_enable(struct rk628 *rk628) +{ + return 0; +} +#endif #endif