static void handle_reset_l(struct tegra_dc_hdmi_data *hdmi)
{
	/* Were we just reset?  If so, shut everything down, then schedule a
	 * check of the plug state in the near future.
	 */
	hdmi_disable_l(hdmi, false);
	hdmi_state_machine_set_state_l(HDMI_STATE_CHECK_PLUG_STATE,
				       CHECK_PLUG_STATE_DELAY_MS);
}
static void handle_check_plug_state_l(struct tegra_dc_hdmi_data *hdmi)
{
	if (tegra_dc_hpd(work_state.hdmi->dc)) {
		/* Looks like there is something plugged in.
		 * Get ready to read the sink's EDID information.
		 */
		work_state.edid_reads = 0;

		hdmi_state_machine_set_state_l(HDMI_STATE_CHECK_EDID,
					       CHECK_EDID_DELAY_MS);
	} else {
		/* nothing plugged in, so we are finished.  Go to the
		 * DONE_DISABLED state and stay there until the next HPD event.
		 * */
		hdmi_disable_l(hdmi, true);
		hdmi_state_machine_set_state_l(HDMI_STATE_DONE_DISABLED, -1);
	}
}
static void handle_check_edid_l(struct tegra_dc_hdmi_data *hdmi)
{
	struct fb_monspecs specs;
#ifdef CONFIG_SWITCH
	int state;
#endif

	memset(&specs, 0, sizeof(specs));
#ifdef CONFIG_FRAMEBUFFER_CONSOLE
	/* Set default videomode on dc before enabling it*/
	tegra_dc_set_default_videomode(hdmi->dc);
#endif

	if (!tegra_dc_hpd(work_state.hdmi->dc)) {
		/* hpd dropped - stop EDID read */
		pr_info("hpd == 0, aborting EDID read\n");
		goto end_disabled;
	}

	if (tegra_edid_get_monspecs(hdmi->edid, &specs)) {
		/* Failed to read EDID.  If we still have retry attempts left,
		 * schedule another attempt.  Otherwise give up and just go to
		 * the disabled state.
		 */
		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);
			goto end_disabled;
		} else {
			hdmi_state_machine_set_state_l(HDMI_STATE_CHECK_EDID,
						       CHECK_EDID_DELAY_MS);
		}

		return;
	}

	if (tegra_edid_get_eld(hdmi->edid, &hdmi->eld) < 0) {
		pr_err("error populating eld\n");
		goto end_disabled;
	}
	hdmi->eld_retrieved = true;

	pr_info("panel size %d by %d\n", specs.max_x, specs.max_y);

	/* monitors like to lie about these but they are still useful for
	 * detecting aspect ratios
	 */
	hdmi->dc->out->h_size = specs.max_x * 1000;
	hdmi->dc->out->v_size = specs.max_y * 1000;

	hdmi->dvi = !(specs.misc & FB_MISC_HDMI);

	/* Need to unpowergate DC if it was powergated. Updating monitorspecs
	 * triggers pan_display which tries updating windows */
	if (hdmi->dc->enabled && !tegra_dc_is_powered(hdmi->dc))
		tegra_dc_unpowergate_locked(hdmi->dc);

	tegra_fb_update_monspecs(hdmi->dc->fb, &specs,
		tegra_dc_hdmi_mode_filter);

#ifdef CONFIG_SWITCH
	state = tegra_edid_audio_supported(hdmi->edid) ? 1 : 0;
	switch_set_state(&hdmi->audio_switch, state);
	pr_info("%s: audio_switch %d\n", __func__, state);
	switch_set_state(&hdmi->hpd_switch, 1);
	pr_info("Display connected, hpd_switch 1\n");
#endif
	hdmi->dc->connected = true;
	tegra_dc_ext_process_hotplug(hdmi->dc->ndev->id);
	hdmi_state_machine_set_state_l(HDMI_STATE_DONE_ENABLED, 0);

	return;

end_disabled:
	hdmi->eld_retrieved = false;
	hdmi_disable_l(hdmi, true);
	hdmi_state_machine_set_state_l(HDMI_STATE_DONE_DISABLED, -1);
}
Example #4
0
static void handle_check_edid_l(struct tegra_dc_hdmi_data *hdmi)
{
	struct fb_monspecs specs;
#ifdef CONFIG_SWITCH
	int state;
#endif

	memset(&specs, 0, sizeof(specs));
#ifdef CONFIG_FRAMEBUFFER_CONSOLE
	/* Set default videomode on dc before enabling it*/
	tegra_dc_set_default_videomode(hdmi->dc);
#endif

	if (!tegra_dc_hpd(work_state.hdmi->dc)) {
		/* hpd dropped - stop EDID read */
		pr_info("hpd == 0, aborting EDID read\n");
		goto end_disabled;
	}

	if (tegra_edid_get_monspecs(hdmi->edid, &specs)) {
		/* Failed to read EDID.  If we still have retry attempts left,
		 * schedule another attempt.  Otherwise give up and just go to
		 * the disabled state.
		 */
		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);
			goto end_disabled;
		} else {
			hdmi_state_machine_set_state_l(HDMI_STATE_CHECK_EDID,
						       CHECK_EDID_DELAY_MS);
		}

		return;
	}

	if (tegra_edid_get_eld(hdmi->edid, &hdmi->eld) < 0) {
		pr_err("error populating eld\n");
		goto end_disabled;
	}
	hdmi->eld_retrieved = true;

	pr_info("panel size %d by %d\n", specs.max_x, specs.max_y);

	/* monitors like to lie about these but they are still useful for
	 * detecting aspect ratios
	 */
	hdmi->dc->out->h_size = specs.max_x * 1000;
	hdmi->dc->out->v_size = specs.max_y * 1000;

	hdmi->dvi = !(specs.misc & FB_MISC_HDMI);

#ifdef CONFIG_ADF_TEGRA
	tegra_adf_process_hotplug_connected(hdmi->dc->adf, &specs);
#endif
#ifdef CONFIG_TEGRA_DC_EXTENSIONS
	tegra_fb_update_monspecs(hdmi->dc->fb, &specs,
		tegra_dc_hdmi_mode_filter);
#endif
#ifdef CONFIG_SWITCH
	state = tegra_edid_audio_supported(hdmi->edid) ? 1 : 0;
	switch_set_state(&hdmi->audio_switch, state);
	pr_info("%s: audio_switch %d\n", __func__, state);
	switch_set_state(&hdmi->hpd_switch, 1);
	pr_info("Display connected, hpd_switch 1\n");
#endif
	hdmi->dc->connected = true;

#ifdef CONFIG_TEGRA_DC_EXTENSIONS
	tegra_dc_ext_process_hotplug(hdmi->dc->ndev->id);
#endif

	if (unlikely(tegra_is_clk_enabled(hdmi->clk))) {
		/* the only time this should happen is on boot, where the
		 * sequence is that hdmi is enabled before EDID is read.
		 * hdmi_enable() doesn't have EDID information yet so can't
		 * setup audio and infoframes, so we have to do so here.
		 */
		pr_info("%s: setting audio and infoframes\n", __func__);
		tegra_dc_io_start(hdmi->dc);
		tegra_dc_hdmi_setup_audio_and_infoframes(hdmi->dc);
		tegra_dc_io_end(hdmi->dc);
	}

	hdmi_state_machine_set_state_l(HDMI_STATE_DONE_ENABLED, -1);

	return;

end_disabled:
	hdmi->eld_retrieved = false;
	hdmi_disable_l(hdmi);
	hdmi_state_machine_set_state_l(HDMI_STATE_DONE_DISABLED, -1);
}