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);
}
示例#2
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);
}