mirror of
https://github.com/hardkernel/linux.git
synced 2026-06-08 03:40:35 +09:00
drm: dw-hdmi: fix RK3328/RK3229 phy abnormal enabling
Under the following conditions, phy will be abnormally enabled. 1. HDMI is enabled in uboot. 2. disabled/bridge_is_on/phy.enabled/mc_clkdis were updated to work when probe. 3. HDMI is disconnected. 4. drm_helper_probe_single_connector_modes update connector->status to disconnected and power off phy by dw_hdmi_update_power. But the polled type of HDMI is DRM_CONNECTOR_POLL_HPD, output_poll_execute will not process this disconnection, and dw_hdmi_bridge_disable is not called, hdmi->disabled is still false. 5. vop will be switch to Tv encoder, and dclk is 27MHz. 6. HDMI is connected. 7. dw_hdmi_update_power is called in dw_hdmi_irq, for hdmi->disabled is false, then phy is powered up with parameter of 27MHz, and bridge_is_on is set to on. 8. VOP switch to HDMI mode, set the new dclk rate. 9. dw_hdmi_bridge_enable is called, but the bridge_is_on is already on, phy will not set again, still maintain the parameters that do not conform to the new dclk rate. This patch introduced an variable initialized to indicate hdmi is initialized before probe, e.g. uboot. When power off hdmi, initialized and disabled is updated. Change-Id: I163967ac02e7f29ab586acbfd25d5a15679470c8 Signed-off-by: Zheng Yang <zhengyang@rock-chips.com>
This commit is contained in:
@@ -261,6 +261,8 @@ struct dw_hdmi {
|
||||
|
||||
void (*write)(struct dw_hdmi *hdmi, u8 val, int offset);
|
||||
u8 (*read)(struct dw_hdmi *hdmi, int offset);
|
||||
|
||||
bool initialized; /* hdmi is enabled before bind */
|
||||
};
|
||||
|
||||
#define HDMI_IH_PHY_STAT0_RX_SENSE \
|
||||
@@ -2396,6 +2398,10 @@ static void dw_hdmi_update_power(struct dw_hdmi *hdmi)
|
||||
}
|
||||
|
||||
if (force == DRM_FORCE_OFF) {
|
||||
if (hdmi->initialized) {
|
||||
hdmi->initialized = false;
|
||||
hdmi->disabled = true;
|
||||
}
|
||||
if (hdmi->bridge_is_on)
|
||||
dw_hdmi_poweroff(hdmi);
|
||||
} else {
|
||||
@@ -3613,6 +3619,7 @@ int dw_hdmi_bind(struct device *dev, struct device *master,
|
||||
prod_id1 & HDMI_PRODUCT_ID1_HDCP ? "with" : "without",
|
||||
hdmi->phy.name);
|
||||
|
||||
hdmi->initialized = false;
|
||||
ret = hdmi_readb(hdmi, HDMI_PHY_STAT0);
|
||||
if ((ret & HDMI_PHY_TX_PHY_LOCK) && (ret & HDMI_PHY_HPD) &&
|
||||
hdmi_readb(hdmi, HDMI_FC_EXCTRLDUR)) {
|
||||
@@ -3620,6 +3627,7 @@ int dw_hdmi_bind(struct device *dev, struct device *master,
|
||||
hdmi->disabled = false;
|
||||
hdmi->bridge_is_on = true;
|
||||
hdmi->phy.enabled = true;
|
||||
hdmi->initialized = true;
|
||||
} else if (ret & HDMI_PHY_TX_PHY_LOCK) {
|
||||
hdmi->phy.ops->disable(hdmi, hdmi->phy.data);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user