int tegra_fb_update_modelist(struct tegra_dc *dc, int fblistindex);
struct tegra_dc_win *tegra_fb_get_win(struct tegra_fb_info *tegra_fb);
struct tegra_dc_win *tegra_fb_get_blank_win(struct tegra_fb_info *tegra_fb);
+struct fb_videomode *tegra_fb_get_mode(struct tegra_dc *dc);
#else
static inline struct tegra_fb_info *tegra_fb_register(
struct platform_device *ndev, struct tegra_dc *dc,
struct tegra_fb_info *tegra_fb)
{
return NULL;
+
+}
+
+static inline struct fb_videomode *tegra_fb_get_mode(struct tegra_dc *dc)
+{
+ return NULL;
}
#endif
#endif
{
struct tegra_hdmi *hdmi = tegra_dc_get_outdata(dc);
+ _tegra_hdmivrr_activate(hdmi, false);
hdmi->device_shutdown = true;
tegra_nvhdcp_shutdown(hdmi->nvhdcp);
{
struct tegra_hdmi *hdmi = tegra_dc_get_outdata(dc);
+ _tegra_hdmivrr_activate(hdmi, false);
hdmi->enabled = false;
#ifdef CONFIG_SWITCH
switch_set_state(&hdmi->audio_switch, 0);
{
struct tegra_hdmi *hdmi = tegra_dc_get_outdata(dc);
+ _tegra_hdmivrr_activate(hdmi, false);
+
if (dc->out->flags & TEGRA_DC_OUT_HOTPLUG_WAKE_LP0) {
int wake_irq = gpio_to_irq(dc->out->hotplug_gpio);
int ret;
disable_irq_wake(gpio_to_irq(dc->out->hotplug_gpio));
cancel_delayed_work(&hdmi->hpd_worker);
+
+ /* If resume happens with a non-VRR monitor, the HPD
+ worker will correct the mode based on the new EDID */
+ _tegra_hdmivrr_activate(hdmi, true);
+
schedule_delayed_work(&hdmi->hpd_worker,
msecs_to_jiffies(HDMI_HPD_DEBOUNCE_DELAY_MS + HDMI_HPD_DROP_TIMEOUT_MS));
}
if (!vrr)
return;
- if (dc->mode.vmode & FB_VMODE_VRR)
- vrr->enable = enable;
- else
+ if (!(dc->mode.vmode & FB_VMODE_VRR)) {
WARN(enable, "VRR enable request in non-VRR mode\n");
+ return;
+ }
+
+ vrr->enable = enable;
+}
+static void tegra_dc_hdmi_postpoweron(struct tegra_dc *dc)
+{
+ _tegra_hdmivrr_activate(tegra_dc_get_outdata(dc), true);
}
struct tegra_dc_out_ops tegra_dc_hdmi2_0_ops = {
.vrr_enable = tegra_dc_hdmi_vrr_enable,
.vrr_update_monspecs = tegra_hdmivrr_update_monspecs,
.set_hdr = tegra_dc_hdmi_set_hdr,
+ .postpoweron = tegra_dc_hdmi_postpoweron,
};
#endif
#include <mach/dc.h>
+#include <mach/fb.h>
#include "dc_priv.h"
#include "edid.h"
#define HDMIVRR_CHLNG_SRC_MON 0
#define HDMIVRR_CHLNG_SRC_DRV 1
+#define NS_IN_MS (1000 * 1000)
+
static int hdmivrr_i2c_read(struct tegra_hdmi *hdmi, size_t len, void *data)
{
int status;
}
}
+/* Active or deactivate VRR mode on the monitor side */
+void _tegra_hdmivrr_activate(struct tegra_hdmi *hdmi, bool activate)
+{
+ struct tegra_dc *dc = hdmi->dc;
+ struct tegra_vrr *vrr = dc->out->vrr;
+ struct fb_videomode *fbmode = tegra_fb_get_mode(dc);
+ int frametime_ms = (int)div64_s64(dc->frametime_ns, NS_IN_MS);
+
+ if (!vrr || !fbmode || !(dc->mode.vmode & FB_VMODE_VRR))
+ return;
+
+ if (activate) {
+ /*
+ Inform VRR monitor to turn on VRR mode by increase
+ vertical backporch by 2.
+ The monitor needs a few frames of standard timing
+ before activating VRR mode.
+ */
+ msleep(frametime_ms * 20);
+ dc->mode.v_back_porch = fbmode->upper_margin + 2;
+ } else
+ dc->mode.v_back_porch = fbmode->upper_margin;
+
+ _tegra_dc_set_mode(dc, &dc->mode);
+ tegra_dc_update_mode(dc);
+ msleep(frametime_ms * 2);
+}
+
int tegra_hdmivrr_setup(struct tegra_hdmi *hdmi)
{
int status;
struct list_head *head);
int tegra_hdmi_vrr_init(struct tegra_hdmi *hdmi);
void te_authenticate_vrr(u8 *buf_ptr, u32 buflen);
+void _tegra_hdmivrr_activate(struct tegra_hdmi *hdmi, bool activate);
#else
int tegra_hdmivrr_setup(struct tegra_hdmi *hdmi) { return -EPROTONOSUPPORT; }
void tegra_hdmivrr_update_monspecs(struct tegra_dc *dc,
struct list_head *head) { return; }
int tegra_hdmi_vrr_init(struct tegra_hdmi *hdmi) { return -EPROTONOSUPPORT; }
+void _tegra_hdmivrr_activate(struct tegra_hdmi *hdmi, bool activate)
+{ return; }
#endif
#endif
return index;
}
-static int tegra_fb_get_mode(struct tegra_dc *dc)
+static int tegra_fb_get_mode_refresh(struct tegra_dc *dc)
{
if (!dc->fb->info->mode)
return -1;
return dc->fb->info->mode->refresh;
}
+struct fb_videomode *tegra_fb_get_mode(struct tegra_dc *dc)
+{
+ if (dc && dc->fb && dc->fb->info && dc->fb->info->mode)
+ return dc->fb->info->mode;
+ else
+ return NULL;
+}
+
static int tegra_fb_set_mode(struct tegra_dc *dc, int fps)
{
size_t stereo;
struct platform_device *ndev = to_platform_device(device);
struct tegra_dc *dc = platform_get_drvdata(ndev);
- refresh_rate = tegra_fb_get_mode(dc);
+ refresh_rate = tegra_fb_get_mode_refresh(dc);
return snprintf(buf, PAGE_SIZE, "%d\n", refresh_rate);
}