summaryrefslogtreecommitdiffstats
path: root/drivers/video/tegra124/display.c
diff options
context:
space:
mode:
authorSimon Glass <sjg@chromium.org>2015-04-14 21:03:44 -0600
committerTom Warren <twarren@nvidia.com>2015-05-13 09:24:12 -0700
commitdedc44b466ba24bd4f38840a79067d806d37d709 (patch)
treef371ffada3e1b602c30433aff3af0baaead170f9 /drivers/video/tegra124/display.c
parent531eaedc7a397b34979c6d35e5de7b78d2dddfde (diff)
downloadtalos-obmc-uboot-dedc44b466ba24bd4f38840a79067d806d37d709.tar.gz
talos-obmc-uboot-dedc44b466ba24bd4f38840a79067d806d37d709.zip
tegra124: video: Add full link training for eDP
Add full link training as a fallback in case the fast link training fails. Signed-off-by: Simon Glass <sjg@chromium.org> Acked-by: Anatolij Gustschin <agust@denx.de> Signed-off-by: Tom Warren <twarren@nvidia.com>
Diffstat (limited to 'drivers/video/tegra124/display.c')
-rw-r--r--drivers/video/tegra124/display.c114
1 files changed, 114 insertions, 0 deletions
diff --git a/drivers/video/tegra124/display.c b/drivers/video/tegra124/display.c
index 372ad3ea9b..7179dbfe3c 100644
--- a/drivers/video/tegra124/display.c
+++ b/drivers/video/tegra124/display.c
@@ -95,6 +95,120 @@ static int update_display_mode(struct dc_ctlr *disp_ctrl,
return 0;
}
+static u32 tegra_dc_poll_register(void *reg,
+ u32 mask, u32 exp_val, u32 poll_interval_us, u32 timeout_us)
+{
+ u32 temp = timeout_us;
+ u32 reg_val = 0;
+
+ do {
+ udelay(poll_interval_us);
+ reg_val = readl(reg);
+ if (timeout_us > poll_interval_us)
+ timeout_us -= poll_interval_us;
+ else
+ break;
+ } while ((reg_val & mask) != exp_val);
+
+ if ((reg_val & mask) == exp_val)
+ return 0; /* success */
+
+ return temp;
+}
+
+int tegra_dc_sor_general_act(struct dc_ctlr *disp_ctrl)
+{
+ writel(GENERAL_ACT_REQ, &disp_ctrl->cmd.state_ctrl);
+
+ if (tegra_dc_poll_register(&disp_ctrl->cmd.state_ctrl,
+ GENERAL_ACT_REQ, 0, 100,
+ DC_POLL_TIMEOUT_MS * 1000)) {
+ debug("dc timeout waiting for DC to stop\n");
+ return -ETIMEDOUT;
+ }
+
+ return 0;
+}
+
+static struct display_timing min_mode = {
+ .hsync_len = { .typ = 1 },
+ .vsync_len = { .typ = 1 },
+ .hback_porch = { .typ = 20 },
+ .vback_porch = { .typ = 0 },
+ .hactive = { .typ = 16 },
+ .vactive = { .typ = 16 },
+ .hfront_porch = { .typ = 1 },
+ .vfront_porch = { .typ = 2 },
+};
+
+/* Disable windows and set minimum raster timings */
+void tegra_dc_sor_disable_win_short_raster(struct dc_ctlr *disp_ctrl,
+ int *dc_reg_ctx)
+{
+ const int href_to_sync = 0, vref_to_sync = 1;
+ int selected_windows, i;
+
+ selected_windows = readl(&disp_ctrl->cmd.disp_win_header);
+
+ /* Store and clear window options */
+ for (i = 0; i < DC_N_WINDOWS; ++i) {
+ writel(WINDOW_A_SELECT << i, &disp_ctrl->cmd.disp_win_header);
+ dc_reg_ctx[i] = readl(&disp_ctrl->win.win_opt);
+ writel(0, &disp_ctrl->win.win_opt);
+ writel(WIN_A_ACT_REQ << i, &disp_ctrl->cmd.state_ctrl);
+ }
+
+ writel(selected_windows, &disp_ctrl->cmd.disp_win_header);
+
+ /* Store current raster timings and set minimum timings */
+ dc_reg_ctx[i++] = readl(&disp_ctrl->disp.ref_to_sync);
+ writel(href_to_sync | (vref_to_sync << 16),
+ &disp_ctrl->disp.ref_to_sync);
+
+ dc_reg_ctx[i++] = readl(&disp_ctrl->disp.sync_width);
+ writel(min_mode.hsync_len.typ | (min_mode.vsync_len.typ << 16),
+ &disp_ctrl->disp.sync_width);
+
+ dc_reg_ctx[i++] = readl(&disp_ctrl->disp.back_porch);
+ writel(min_mode.hback_porch.typ | (min_mode.vback_porch.typ << 16),
+ &disp_ctrl->disp.back_porch);
+
+ dc_reg_ctx[i++] = readl(&disp_ctrl->disp.front_porch);
+ writel(min_mode.hfront_porch.typ | (min_mode.vfront_porch.typ << 16),
+ &disp_ctrl->disp.front_porch);
+
+ dc_reg_ctx[i++] = readl(&disp_ctrl->disp.disp_active);
+ writel(min_mode.hactive.typ | (min_mode.vactive.typ << 16),
+ &disp_ctrl->disp.disp_active);
+
+ writel(GENERAL_ACT_REQ, &disp_ctrl->cmd.state_ctrl);
+}
+
+/* Restore previous windows status and raster timings */
+void tegra_dc_sor_restore_win_and_raster(struct dc_ctlr *disp_ctrl,
+ int *dc_reg_ctx)
+{
+ int selected_windows, i;
+
+ selected_windows = readl(&disp_ctrl->cmd.disp_win_header);
+
+ for (i = 0; i < DC_N_WINDOWS; ++i) {
+ writel(WINDOW_A_SELECT << i, &disp_ctrl->cmd.disp_win_header);
+ writel(dc_reg_ctx[i], &disp_ctrl->win.win_opt);
+ writel(WIN_A_ACT_REQ << i, &disp_ctrl->cmd.state_ctrl);
+ }
+
+ writel(selected_windows, &disp_ctrl->cmd.disp_win_header);
+
+ writel(dc_reg_ctx[i++], &disp_ctrl->disp.ref_to_sync);
+ writel(dc_reg_ctx[i++], &disp_ctrl->disp.sync_width);
+ writel(dc_reg_ctx[i++], &disp_ctrl->disp.back_porch);
+ writel(dc_reg_ctx[i++], &disp_ctrl->disp.front_porch);
+ writel(dc_reg_ctx[i++], &disp_ctrl->disp.disp_active);
+
+ writel(GENERAL_UPDATE, &disp_ctrl->cmd.state_ctrl);
+}
+
static int tegra_depth_for_bpp(int bpp)
{
switch (bpp) {
OpenPOWER on IntegriCloud