static void handle_recheck_edid_l(struct tegra_dc_hdmi_data *hdmi) { int match, tgt_state, timeout; tgt_state = HDMI_STATE_RESET; timeout = 0; if (hdmi_recheck_edid(hdmi, &match)) { /* Failed to read EDID. If we still have retry attempts left, * schedule another attempt. Otherwise give up and reset; */ work_state.edid_reads++; if (work_state.edid_reads >= MAX_EDID_READ_ATTEMPTS) { pr_info("Failed to read EDID after %d times. Giving up.\n", work_state.edid_reads); } else { tgt_state = HDMI_STATE_DONE_RECHECK_EDID; timeout = CHECK_EDID_DELAY_MS; } } else { /* Successful read! If the EDID is unchanged, just go back to * the DONE_ENABLED state and do nothing. If something changed, * just reset the whole system. */ if (match) { pr_info("No EDID change after HPD bounce, taking no action.\n"); tgt_state = HDMI_STATE_DONE_ENABLED; if (tegra_is_clk_enabled(hdmi->dc->clk)) { tegra_nvhdcp_set_plug(hdmi->nvhdcp, 0); tegra_nvhdcp_set_plug(hdmi->nvhdcp, 1); } else { pr_info("dc powergated, skipping hdcp reset\n"); } timeout = -1; } else { pr_info("EDID change after HPD bounce, resetting\n"); } } hdmi_state_machine_set_state_l(tgt_state, timeout); }
/************************************************************ * * internal state handlers and dispatch table * ************************************************************/ static void hdmi_disable_l(struct tegra_dc_hdmi_data *hdmi, bool power_gate) { #ifdef CONFIG_SWITCH switch_set_state(&hdmi->audio_switch, 0); pr_info("%s: audio_switch 0\n", __func__); switch_set_state(&hdmi->hpd_switch, 0); pr_info("%s: hpd_switch 0\n", __func__); #endif tegra_nvhdcp_set_plug(hdmi->nvhdcp, 0); if (hdmi->dc->connected) { pr_info("HDMI from connected to disconnected\n"); hdmi->dc->connected = false; tegra_dc_disable(hdmi->dc); tegra_fb_update_monspecs(hdmi->dc->fb, NULL, NULL); tegra_dc_ext_process_hotplug(hdmi->dc->ndev->id); } if (power_gate && tegra_powergate_is_powered(hdmi->dc->powergate_id)) tegra_dc_powergate_locked(hdmi->dc); }
/************************************************************ * * internal state handlers and dispatch table * ************************************************************/ static void hdmi_disable_l(struct tegra_dc_hdmi_data *hdmi) { #ifdef CONFIG_SWITCH switch_set_state(&hdmi->audio_switch, 0); pr_info("%s: audio_switch 0\n", __func__); switch_set_state(&hdmi->hpd_switch, 0); pr_info("%s: hpd_switch 0\n", __func__); #endif tegra_nvhdcp_set_plug(hdmi->nvhdcp, 0); if (hdmi->dc->connected) { pr_info("HDMI from connected to disconnected\n"); hdmi->dc->connected = false; tegra_dc_disable(hdmi->dc); #ifdef CONFIG_ADF_TEGRA tegra_adf_process_hotplug_disconnected(hdmi->dc->adf); #endif #ifdef CONFIG_TEGRA_DC_EXTENSIONS tegra_fb_update_monspecs(hdmi->dc->fb, NULL, NULL); tegra_dc_ext_process_hotplug(hdmi->dc->ndev->id); #endif } }