summaryrefslogtreecommitdiff
path: root/drivers/video/tegra
diff options
context:
space:
mode:
authorJon Mayo <jmayo@nvidia.com>2012-06-26 13:53:55 -0700
committerRohan Somvanshi <rsomvanshi@nvidia.com>2012-07-02 06:19:09 -0700
commit429d909e14eefa0331b1cd30490bce4d7ff45f33 (patch)
treedc8a78c303c9a58e289ae1adea91f130782cd82e /drivers/video/tegra
parent33b50b0bf4e501a81605c4351ff163d82c87e0d1 (diff)
video: tegra: dc: split dc.c into smaller files
Moved mode setting code into mode.c Move window code info window.c Moved clock related code into clock.c Moved LUT and gamma related code into lut.c Moved csc(color space conversion) into csc.c Removed unnecessary static function prototypes from header. Moved many short inline functions to dc_priv.h Cleaned up copyright headings. Cleaned up formatting and indent in all files. Fixed build warnings. Bug 870907 Change-Id: I6ccc37150191765394f0b5629423eafd4e5e5792 Signed-off-by: Jon Mayo <jmayo@nvidia.com> Reviewed-on: http://git-master/r/111371 Reviewed-by: Rohan Somvanshi <rsomvanshi@nvidia.com> Tested-by: Rohan Somvanshi <rsomvanshi@nvidia.com>
Diffstat (limited to 'drivers/video/tegra')
-rw-r--r--drivers/video/tegra/dc/Makefile3
-rw-r--r--drivers/video/tegra/dc/bandwidth.c2
-rw-r--r--drivers/video/tegra/dc/clock.c150
-rw-r--r--drivers/video/tegra/dc/csc.c67
-rw-r--r--drivers/video/tegra/dc/dc.c1110
-rw-r--r--drivers/video/tegra/dc/dc_config.c3
-rw-r--r--drivers/video/tegra/dc/dc_config.h2
-rw-r--r--drivers/video/tegra/dc/dc_priv.h78
-rw-r--r--drivers/video/tegra/dc/dc_reg.h2
-rw-r--r--drivers/video/tegra/dc/dc_sysfs.c2
-rw-r--r--drivers/video/tegra/dc/dsi.c6
-rw-r--r--drivers/video/tegra/dc/dsi.h28
-rw-r--r--drivers/video/tegra/dc/dsi_regs.h28
-rw-r--r--drivers/video/tegra/dc/edid.c2
-rw-r--r--drivers/video/tegra/dc/ext/control.c9
-rw-r--r--drivers/video/tegra/dc/ext/cursor.c2
-rw-r--r--drivers/video/tegra/dc/ext/dev.c8
-rw-r--r--drivers/video/tegra/dc/ext/events.c2
-rw-r--r--drivers/video/tegra/dc/ext/tegra_dc_ext_priv.h2
-rw-r--r--drivers/video/tegra/dc/ext/util.c2
-rw-r--r--drivers/video/tegra/dc/hdmi.c2
-rw-r--r--drivers/video/tegra/dc/hdmi.h2
-rw-r--r--drivers/video/tegra/dc/hdmi_reg.h2
-rw-r--r--drivers/video/tegra/dc/lut.c130
-rw-r--r--drivers/video/tegra/dc/mode.c318
-rw-r--r--drivers/video/tegra/dc/nvhdcp.c2
-rw-r--r--drivers/video/tegra/dc/nvhdcp.h2
-rw-r--r--drivers/video/tegra/dc/nvsd.c2
-rw-r--r--drivers/video/tegra/dc/nvsd.h2
-rw-r--r--drivers/video/tegra/dc/rgb.c2
-rw-r--r--drivers/video/tegra/dc/window.c466
-rw-r--r--drivers/video/tegra/fb.c2
32 files changed, 1299 insertions, 1141 deletions
diff --git a/drivers/video/tegra/dc/Makefile b/drivers/video/tegra/dc/Makefile
index 13f8989f02fd..59104c681bae 100644
--- a/drivers/video/tegra/dc/Makefile
+++ b/drivers/video/tegra/dc/Makefile
@@ -1,7 +1,6 @@
GCOV_PROFILE := y
EXTRA_CFLAGS += -Idrivers/video/tegra/host
-obj-y += bandwidth.o
-obj-y += dc.o
+obj-y += dc.o bandwidth.o mode.o clock.o lut.o csc.o window.o
obj-y += rgb.o
obj-y += hdmi.o
obj-$(CONFIG_TEGRA_NVHDCP) += nvhdcp.o
diff --git a/drivers/video/tegra/dc/bandwidth.c b/drivers/video/tegra/dc/bandwidth.c
index 785ec7cedfbd..c7e5072286f4 100644
--- a/drivers/video/tegra/dc/bandwidth.c
+++ b/drivers/video/tegra/dc/bandwidth.c
@@ -1,7 +1,7 @@
/*
* drivers/video/tegra/dc/bandwidth.c
*
- * Copyright (C) 2010-2012 NVIDIA Corporation
+ * Copyright (c) 2010-2012, NVIDIA CORPORATION, All rights reserved.
*
* This software is licensed under the terms of the GNU General Public
* License version 2, as published by the Free Software Foundation, and
diff --git a/drivers/video/tegra/dc/clock.c b/drivers/video/tegra/dc/clock.c
new file mode 100644
index 000000000000..c785282693e6
--- /dev/null
+++ b/drivers/video/tegra/dc/clock.c
@@ -0,0 +1,150 @@
+/*
+ * drivers/video/tegra/dc/clock.c
+ *
+ * Copyright (C) 2010 Google, Inc.
+ *
+ * Copyright (c) 2010-2012, NVIDIA CORPORATION, All rights reserved.
+ *
+ * This software is licensed under the terms of the GNU General Public
+ * License version 2, as published by the Free Software Foundation, and
+ * may be copied, distributed, and modified under those terms.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ */
+
+#include <linux/err.h>
+#include <linux/types.h>
+#include <linux/clk.h>
+
+#include <mach/clk.h>
+#include <mach/dc.h>
+
+#include "dc_reg.h"
+#include "dc_priv.h"
+
+unsigned long tegra_dc_pclk_round_rate(struct tegra_dc *dc, int pclk)
+{
+ unsigned long rate;
+ unsigned long div;
+
+ rate = tegra_dc_clk_get_rate(dc);
+
+ div = DIV_ROUND_CLOSEST(rate * 2, pclk);
+
+ if (div < 2)
+ return 0;
+
+ return rate * 2 / div;
+}
+
+static unsigned long tegra_dc_pclk_predict_rate(struct clk *parent, int pclk)
+{
+ unsigned long rate;
+ unsigned long div;
+
+ rate = clk_get_rate(parent);
+
+ div = DIV_ROUND_CLOSEST(rate * 2, pclk);
+
+ if (div < 2)
+ return 0;
+
+ return rate * 2 / div;
+}
+
+void tegra_dc_setup_clk(struct tegra_dc *dc, struct clk *clk)
+{
+ int pclk;
+
+ if (dc->out->type == TEGRA_DC_OUT_RGB) {
+ unsigned long rate;
+ struct clk *parent_clk =
+ clk_get_sys(NULL, dc->out->parent_clk ? : "pll_p");
+
+ if (dc->out->parent_clk_backup &&
+ (parent_clk == clk_get_sys(NULL, "pll_p"))) {
+ rate = tegra_dc_pclk_predict_rate(
+ parent_clk, dc->mode.pclk);
+ /* use pll_d as last resort */
+ if (rate < (dc->mode.pclk / 100 * 99) ||
+ rate > (dc->mode.pclk / 100 * 109))
+ parent_clk = clk_get_sys(
+ NULL, dc->out->parent_clk_backup);
+ }
+
+ if (clk_get_parent(clk) != parent_clk)
+ clk_set_parent(clk, parent_clk);
+
+ if (parent_clk != clk_get_sys(NULL, "pll_p")) {
+ struct clk *base_clk = clk_get_parent(parent_clk);
+
+ /* Assuming either pll_d or pll_d2 is used */
+ rate = dc->mode.pclk * 2;
+
+ if (rate != clk_get_rate(base_clk))
+ clk_set_rate(base_clk, rate);
+ }
+ }
+
+ if (dc->out->type == TEGRA_DC_OUT_HDMI) {
+ unsigned long rate;
+ struct clk *parent_clk = clk_get_sys(NULL,
+ dc->out->parent_clk ? : "pll_d_out0");
+ struct clk *base_clk = clk_get_parent(parent_clk);
+
+ /*
+ * Providing dynamic frequency rate setting for T20/T30 HDMI.
+ * The required rate needs to be setup at 4x multiplier,
+ * as out0 is 1/2 of the actual PLL output.
+ */
+
+ rate = dc->mode.pclk * 4;
+ if (rate != clk_get_rate(base_clk))
+ clk_set_rate(base_clk, rate);
+
+ if (clk_get_parent(clk) != parent_clk)
+ clk_set_parent(clk, parent_clk);
+ }
+
+ if (dc->out->type == TEGRA_DC_OUT_DSI) {
+ unsigned long rate;
+ struct clk *parent_clk;
+ struct clk *base_clk;
+
+ if (clk == dc->clk) {
+ parent_clk = clk_get_sys(NULL,
+ dc->out->parent_clk ? : "pll_d_out0");
+ base_clk = clk_get_parent(parent_clk);
+ tegra_clk_cfg_ex(base_clk,
+ TEGRA_CLK_PLLD_DSI_OUT_ENB, 1);
+ } else {
+ if (dc->pdata->default_out->dsi->dsi_instance) {
+ parent_clk = clk_get_sys(NULL,
+ dc->out->parent_clk ? : "pll_d2_out0");
+ base_clk = clk_get_parent(parent_clk);
+ tegra_clk_cfg_ex(base_clk,
+ TEGRA_CLK_PLLD_CSI_OUT_ENB, 1);
+ } else {
+ parent_clk = clk_get_sys(NULL,
+ dc->out->parent_clk ? : "pll_d_out0");
+ base_clk = clk_get_parent(parent_clk);
+ tegra_clk_cfg_ex(base_clk,
+ TEGRA_CLK_PLLD_DSI_OUT_ENB, 1);
+ }
+ }
+
+ rate = dc->mode.pclk * dc->shift_clk_div * 2;
+ if (rate != clk_get_rate(base_clk))
+ clk_set_rate(base_clk, rate);
+
+ if (clk_get_parent(clk) != parent_clk)
+ clk_set_parent(clk, parent_clk);
+ }
+
+ pclk = tegra_dc_pclk_round_rate(dc, dc->mode.pclk);
+ tegra_dvfs_set_rate(clk, pclk);
+}
diff --git a/drivers/video/tegra/dc/csc.c b/drivers/video/tegra/dc/csc.c
new file mode 100644
index 000000000000..74fa900352a1
--- /dev/null
+++ b/drivers/video/tegra/dc/csc.c
@@ -0,0 +1,67 @@
+/*
+ * drivers/video/tegra/dc/csc.c
+ *
+ * Copyright (c) 2010-2012, NVIDIA CORPORATION, All rights reserved.
+ *
+ * This software is licensed under the terms of the GNU General Public
+ * License version 2, as published by the Free Software Foundation, and
+ * may be copied, distributed, and modified under those terms.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ */
+
+#include <linux/err.h>
+#include <linux/types.h>
+#include <mach/dc.h>
+
+#include "dc_reg.h"
+#include "dc_priv.h"
+
+void tegra_dc_init_csc_defaults(struct tegra_dc_csc *csc)
+{
+ csc->yof = 0x00f0;
+ csc->kyrgb = 0x012a;
+ csc->kur = 0x0000;
+ csc->kvr = 0x0198;
+ csc->kug = 0x039b;
+ csc->kvg = 0x032f;
+ csc->kub = 0x0204;
+ csc->kvb = 0x0000;
+}
+
+void tegra_dc_set_csc(struct tegra_dc *dc, struct tegra_dc_csc *csc)
+{
+ tegra_dc_writel(dc, csc->yof, DC_WIN_CSC_YOF);
+ tegra_dc_writel(dc, csc->kyrgb, DC_WIN_CSC_KYRGB);
+ tegra_dc_writel(dc, csc->kur, DC_WIN_CSC_KUR);
+ tegra_dc_writel(dc, csc->kvr, DC_WIN_CSC_KVR);
+ tegra_dc_writel(dc, csc->kug, DC_WIN_CSC_KUG);
+ tegra_dc_writel(dc, csc->kvg, DC_WIN_CSC_KVG);
+ tegra_dc_writel(dc, csc->kub, DC_WIN_CSC_KUB);
+ tegra_dc_writel(dc, csc->kvb, DC_WIN_CSC_KVB);
+}
+
+int tegra_dc_update_csc(struct tegra_dc *dc, int win_idx)
+{
+ mutex_lock(&dc->lock);
+
+ if (!dc->enabled) {
+ mutex_unlock(&dc->lock);
+ return -EFAULT;
+ }
+
+ tegra_dc_writel(dc, WINDOW_A_SELECT << win_idx,
+ DC_CMD_DISPLAY_WINDOW_HEADER);
+
+ tegra_dc_set_csc(dc, &dc->windows[win_idx].csc);
+
+ mutex_unlock(&dc->lock);
+
+ return 0;
+}
+EXPORT_SYMBOL(tegra_dc_update_csc);
+
diff --git a/drivers/video/tegra/dc/dc.c b/drivers/video/tegra/dc/dc.c
index b79a6595c36f..887beb830a3e 100644
--- a/drivers/video/tegra/dc/dc.c
+++ b/drivers/video/tegra/dc/dc.c
@@ -4,7 +4,7 @@
* Copyright (C) 2010 Google, Inc.
* Author: Erik Gilling <konkers@android.com>
*
- * Copyright (C) 2010-2012 NVIDIA Corporation
+ * Copyright (c) 2010-2012, NVIDIA CORPORATION, All rights reserved.
*
* This software is licensed under the terms of the GNU General Public
* License version 2, as published by the Free Software Foundation, and
@@ -58,14 +58,6 @@
#define DC_COM_PIN_OUTPUT_POLARITY1_INIT_VAL 0x01000000
#define DC_COM_PIN_OUTPUT_POLARITY3_INIT_VAL 0x0
-#ifndef CONFIG_TEGRA_FPGA_PLATFORM
-#define ALL_UF_INT (WIN_A_UF_INT | WIN_B_UF_INT | WIN_C_UF_INT)
-#else
-/* ignore underflows when on simulation and fpga platform */
-#define ALL_UF_INT (0)
-#endif
-
-static int no_vsync;
static struct fb_videomode tegra_dc_hdmi_fallback_mode = {
.refresh = 60,
.xres = 640,
@@ -83,8 +75,6 @@ static struct fb_videomode tegra_dc_hdmi_fallback_mode = {
static void _tegra_dc_controller_disable(struct tegra_dc *dc);
-module_param_named(no_vsync, no_vsync, int, S_IRUGO | S_IWUSR);
-
struct tegra_dc *tegra_dcs[TEGRA_MAX_DC];
DEFINE_MUTEX(tegra_dc_lock);
@@ -112,23 +102,6 @@ static inline void tegra_dc_clk_disable(struct tegra_dc *dc)
print(data, buff); \
} while (0)
-#define print_mode_info(dc, mode) do { \
- trace_printk("%s:Mode settings: " \
- "ref_to_sync: H = %d V = %d, " \
- "sync_width: H = %d V = %d, " \
- "back_porch: H = %d V = %d, " \
- "active: H = %d V = %d, " \
- "front_porch: H = %d V = %d, " \
- "pclk = %d, stereo mode = %d\n", \
- dc->ndev->name, \
- mode.h_ref_to_sync, mode.v_ref_to_sync, \
- mode.h_sync_width, mode.v_sync_width, \
- mode.h_back_porch, mode.v_back_porch, \
- mode.h_active, mode.v_active, \
- mode.h_front_porch, mode.v_front_porch, \
- mode.pclk, mode.stereo_mode); \
- } while (0)
-
#define print_underflow_info(dc) do { \
trace_printk("%s:Underflow stats: underflows : %llu, " \
"undeflows_a : %llu, " \
@@ -297,7 +270,7 @@ static void _dump_regs(struct tegra_dc *dc, void *data,
DUMP_REG(DC_COM_PM1_DUTY_CYCLE);
DUMP_REG(DC_DISP_SD_CONTROL);
- tegra_dc_clk_disable(dc->clk);
+ tegra_dc_clk_disable(dc);
tegra_dc_io_end(dc);
}
@@ -538,18 +511,6 @@ struct tegra_dc_win *tegra_dc_get_window(struct tegra_dc *dc, unsigned win)
}
EXPORT_SYMBOL(tegra_dc_get_window);
-static int get_topmost_window(u32 *depths, unsigned long *wins)
-{
- int idx, best = -1;
-
- for_each_set_bit(idx, wins, DC_N_WINDOWS) {
- if (best == -1 || depths[idx] < depths[best])
- best = idx;
- }
- clear_bit(best, wins);
- return best;
-}
-
bool tegra_dc_get_connected(struct tegra_dc *dc)
{
return dc->connected;
@@ -570,222 +531,6 @@ bool tegra_dc_hpd(struct tegra_dc *dc)
}
EXPORT_SYMBOL(tegra_dc_hpd);
-static u32 blend_topwin(u32 flags)
-{
- if (flags & TEGRA_WIN_FLAG_BLEND_COVERAGE)
- return BLEND(NOKEY, ALPHA, 0xff, 0xff);
- else if (flags & TEGRA_WIN_FLAG_BLEND_PREMULT)
- return BLEND(NOKEY, PREMULT, 0xff, 0xff);
- else
- return BLEND(NOKEY, FIX, 0xff, 0xff);
-}
-
-static u32 blend_2win(int idx, unsigned long behind_mask, u32* flags, int xy)
-{
- int other;
-
- for (other = 0; other < DC_N_WINDOWS; other++) {
- if (other != idx && (xy-- == 0))
- break;
- }
- if (BIT(other) & behind_mask)
- return blend_topwin(flags[idx]);
- else if (flags[other])
- return BLEND(NOKEY, DEPENDANT, 0x00, 0x00);
- else
- return BLEND(NOKEY, FIX, 0x00, 0x00);
-}
-
-static u32 blend_3win(int idx, unsigned long behind_mask, u32* flags)
-{
- unsigned long infront_mask;
- int first;
-
- infront_mask = ~(behind_mask | BIT(idx));
- infront_mask &= (BIT(DC_N_WINDOWS) - 1);
- first = ffs(infront_mask) - 1;
-
- if (!infront_mask)
- return blend_topwin(flags[idx]);
- else if (behind_mask && first != -1 && flags[first])
- return BLEND(NOKEY, DEPENDANT, 0x00, 0x00);
- else
- return BLEND(NOKEY, FIX, 0x0, 0x0);
-}
-
-static void tegra_dc_set_blending(struct tegra_dc *dc, struct tegra_dc_blend *blend)
-{
- unsigned long mask = BIT(DC_N_WINDOWS) - 1;
-
- while (mask) {
- int idx = get_topmost_window(blend->z, &mask);
-
- tegra_dc_writel(dc, WINDOW_A_SELECT << idx,
- DC_CMD_DISPLAY_WINDOW_HEADER);
- tegra_dc_writel(dc, BLEND(NOKEY, FIX, 0xff, 0xff),
- DC_WIN_BLEND_NOKEY);
- tegra_dc_writel(dc, BLEND(NOKEY, FIX, 0xff, 0xff),
- DC_WIN_BLEND_1WIN);
- tegra_dc_writel(dc, blend_2win(idx, mask, blend->flags, 0),
- DC_WIN_BLEND_2WIN_X);
- tegra_dc_writel(dc, blend_2win(idx, mask, blend->flags, 1),
- DC_WIN_BLEND_2WIN_Y);
- tegra_dc_writel(dc, blend_3win(idx, mask, blend->flags),
- DC_WIN_BLEND_3WIN_XY);
- }
-}
-
-static void tegra_dc_init_csc_defaults(struct tegra_dc_csc *csc)
-{
- csc->yof = 0x00f0;
- csc->kyrgb = 0x012a;
- csc->kur = 0x0000;
- csc->kvr = 0x0198;
- csc->kug = 0x039b;
- csc->kvg = 0x032f;
- csc->kub = 0x0204;
- csc->kvb = 0x0000;
-}
-
-static void tegra_dc_set_csc(struct tegra_dc *dc, struct tegra_dc_csc *csc)
-{
- tegra_dc_writel(dc, csc->yof, DC_WIN_CSC_YOF);
- tegra_dc_writel(dc, csc->kyrgb, DC_WIN_CSC_KYRGB);
- tegra_dc_writel(dc, csc->kur, DC_WIN_CSC_KUR);
- tegra_dc_writel(dc, csc->kvr, DC_WIN_CSC_KVR);
- tegra_dc_writel(dc, csc->kug, DC_WIN_CSC_KUG);
- tegra_dc_writel(dc, csc->kvg, DC_WIN_CSC_KVG);
- tegra_dc_writel(dc, csc->kub, DC_WIN_CSC_KUB);
- tegra_dc_writel(dc, csc->kvb, DC_WIN_CSC_KVB);
-}
-
-int tegra_dc_update_csc(struct tegra_dc *dc, int win_idx)
-{
- mutex_lock(&dc->lock);
-
- if (!dc->enabled) {
- mutex_unlock(&dc->lock);
- return -EFAULT;
- }
-
- tegra_dc_writel(dc, WINDOW_A_SELECT << win_idx,
- DC_CMD_DISPLAY_WINDOW_HEADER);
-
- tegra_dc_set_csc(dc, &dc->windows[win_idx].csc);
-
- mutex_unlock(&dc->lock);
-
- return 0;
-}
-EXPORT_SYMBOL(tegra_dc_update_csc);
-
-static void tegra_dc_init_lut_defaults(struct tegra_dc_lut *lut)
-{
- int i;
- for (i = 0; i < 256; i++)
- lut->r[i] = lut->g[i] = lut->b[i] = (u8)i;
-}
-
-static int tegra_dc_loop_lut(struct tegra_dc *dc,
- struct tegra_dc_win *win,
- int(*lambda)(struct tegra_dc *dc, int i, u32 rgb))
-{
- struct tegra_dc_lut *lut = &win->lut;
- struct tegra_dc_lut *global_lut = &dc->fb_lut;
- int i;
- for (i = 0; i < 256; i++) {
-
- u32 r = (u32)lut->r[i];
- u32 g = (u32)lut->g[i];
- u32 b = (u32)lut->b[i];
-
- if (!(win->ppflags & TEGRA_WIN_PPFLAG_CP_FBOVERRIDE)) {
- r = (u32)global_lut->r[r];
- g = (u32)global_lut->g[g];
- b = (u32)global_lut->b[b];
- }
-
- if (!lambda(dc, i, r | (g<<8) | (b<<16)))
- return 0;
- }
- return 1;
-}
-
-static int tegra_dc_lut_isdefaults_lambda(struct tegra_dc *dc, int i, u32 rgb)
-{
- if (rgb != (i | (i<<8) | (i<<16)))
- return 0;
- return 1;
-}
-
-static int tegra_dc_set_lut_setreg_lambda(struct tegra_dc *dc, int i, u32 rgb)
-{
- tegra_dc_writel(dc, rgb, DC_WIN_COLOR_PALETTE(i));
- return 1;
-}
-
-static void tegra_dc_set_lut(struct tegra_dc *dc, struct tegra_dc_win* win)
-{
- unsigned long val = tegra_dc_readl(dc, DC_WIN_WIN_OPTIONS);
-
- tegra_dc_loop_lut(dc, win, tegra_dc_set_lut_setreg_lambda);
-
- if (win->ppflags & TEGRA_WIN_PPFLAG_CP_ENABLE)
- val |= CP_ENABLE;
- else
- val &= ~CP_ENABLE;
-
- tegra_dc_writel(dc, val, DC_WIN_WIN_OPTIONS);
-}
-
-static int tegra_dc_update_winlut(struct tegra_dc *dc, int win_idx, int fbovr)
-{
- struct tegra_dc_win *win = &dc->windows[win_idx];
-
- mutex_lock(&dc->lock);
-
- if (!dc->enabled) {
- mutex_unlock(&dc->lock);
- return -EFAULT;
- }
-
- if (fbovr > 0)
- win->ppflags |= TEGRA_WIN_PPFLAG_CP_FBOVERRIDE;
- else if (fbovr == 0)
- win->ppflags &= ~TEGRA_WIN_PPFLAG_CP_FBOVERRIDE;
-
- if (!tegra_dc_loop_lut(dc, win, tegra_dc_lut_isdefaults_lambda))
- win->ppflags |= TEGRA_WIN_PPFLAG_CP_ENABLE;
- else
- win->ppflags &= ~TEGRA_WIN_PPFLAG_CP_ENABLE;
-
- tegra_dc_writel(dc, WINDOW_A_SELECT << win_idx,
- DC_CMD_DISPLAY_WINDOW_HEADER);
-
- tegra_dc_set_lut(dc, win);
-
- mutex_unlock(&dc->lock);
-
- tegra_dc_update_windows(&win, 1);
-
- return 0;
-}
-
-int tegra_dc_update_lut(struct tegra_dc *dc, int win_idx, int fboveride)
-{
- if (win_idx > -1)
- return tegra_dc_update_winlut(dc, win_idx, fboveride);
-
- for (win_idx = 0; win_idx < DC_N_WINDOWS; win_idx++) {
- int err = tegra_dc_update_winlut(dc, win_idx, fboveride);
- if (err)
- return err;
- }
-
- return 0;
-}
-EXPORT_SYMBOL(tegra_dc_update_lut);
-
static void tegra_dc_set_scaling_filter(struct tegra_dc *dc)
{
unsigned i;
@@ -814,287 +559,10 @@ void tegra_dc_host_resume(struct tegra_dc *dc) {
tegra_dsi_host_resume(dc);
}
-static inline u32 compute_dda_inc(fixed20_12 in, unsigned out_int,
- bool v, unsigned Bpp)
-{
- /*
- * min(round((prescaled_size_in_pixels - 1) * 0x1000 /
- * (post_scaled_size_in_pixels - 1)), MAX)
- * Where the value of MAX is as follows:
- * For V_DDA_INCREMENT: 15.0 (0xF000)
- * For H_DDA_INCREMENT: 4.0 (0x4000) for 4 Bytes/pix formats.
- * 8.0 (0x8000) for 2 Bytes/pix formats.
- */
-
- fixed20_12 out = dfixed_init(out_int);
- u32 dda_inc;
- int max;
-
- if (v) {
- max = 15;
- } else {
- switch (Bpp) {
- default:
- WARN_ON_ONCE(1);
- /* fallthrough */
- case 4:
- max = 4;
- break;
- case 2:
- max = 8;
- break;
- }
- }
-
- out.full = max_t(u32, out.full - dfixed_const(1), dfixed_const(1));
- in.full -= dfixed_const(1);
-
- dda_inc = dfixed_div(in, out);
-
- dda_inc = min_t(u32, dda_inc, dfixed_const(max));
-
- return dda_inc;
-}
-
-static inline u32 compute_initial_dda(fixed20_12 in)
-{
- return dfixed_frac(in);
-}
-
-/* does not support updating windows on multiple dcs in one call */
-int tegra_dc_update_windows(struct tegra_dc_win *windows[], int n)
+static inline void disable_dc_irq(unsigned int irq)
{
- struct tegra_dc *dc;
- unsigned long update_mask = GENERAL_ACT_REQ;
- unsigned long val;
- bool update_blend = false;
- int i;
-
- dc = windows[0]->dc;
-
- if (dc->out->flags & TEGRA_DC_OUT_ONE_SHOT_MODE) {
- /* Acquire one_shot_lock to avoid race condition between
- * cancellation of old delayed work and schedule of new
- * delayed work. */
- mutex_lock(&dc->one_shot_lock);
- cancel_delayed_work_sync(&dc->one_shot_work);
- }
- mutex_lock(&dc->lock);
-
- if (!dc->enabled) {
- mutex_unlock(&dc->lock);
- if (dc->out->flags & TEGRA_DC_OUT_ONE_SHOT_MODE)
- mutex_unlock(&dc->one_shot_lock);
- return -EFAULT;
- }
-
- if (dc->out->flags & TEGRA_DC_OUT_ONE_SHOT_LP_MODE)
- tegra_dc_host_resume(dc);
-
- if (no_vsync)
- tegra_dc_writel(dc, WRITE_MUX_ACTIVE | READ_MUX_ACTIVE, DC_CMD_STATE_ACCESS);
- else
- tegra_dc_writel(dc, WRITE_MUX_ASSEMBLY | READ_MUX_ASSEMBLY, DC_CMD_STATE_ACCESS);
-
- for (i = 0; i < n; i++) {
- struct tegra_dc_win *win = windows[i];
- unsigned h_dda;
- unsigned v_dda;
- fixed20_12 h_offset, v_offset;
- bool invert_h = (win->flags & TEGRA_WIN_FLAG_INVERT_H) != 0;
- bool invert_v = (win->flags & TEGRA_WIN_FLAG_INVERT_V) != 0;
- bool yuv = tegra_dc_is_yuv(win->fmt);
- bool yuvp = tegra_dc_is_yuv_planar(win->fmt);
- unsigned Bpp = tegra_dc_fmt_bpp(win->fmt) / 8;
- /* Bytes per pixel of bandwidth, used for dda_inc calculation */
- unsigned Bpp_bw = Bpp * (yuvp ? 2 : 1);
- const bool filter_h = win_use_h_filter(dc, win);
- const bool filter_v = win_use_v_filter(dc, win);
-
- if (win->z != dc->blend.z[win->idx]) {
- dc->blend.z[win->idx] = win->z;
- update_blend = true;
- }
- if ((win->flags & TEGRA_WIN_BLEND_FLAGS_MASK) !=
- dc->blend.flags[win->idx]) {
- dc->blend.flags[win->idx] =
- win->flags & TEGRA_WIN_BLEND_FLAGS_MASK;
- update_blend = true;
- }
-
- tegra_dc_writel(dc, WINDOW_A_SELECT << win->idx,
- DC_CMD_DISPLAY_WINDOW_HEADER);
-
- if (!no_vsync)
- update_mask |= WIN_A_ACT_REQ << win->idx;
-
- if (!WIN_IS_ENABLED(win)) {
- dc->windows[i].dirty = 1;
- tegra_dc_writel(dc, 0, DC_WIN_WIN_OPTIONS);
- continue;
- }
-
- tegra_dc_writel(dc, win->fmt & 0x1f, DC_WIN_COLOR_DEPTH);
- tegra_dc_writel(dc, win->fmt >> 6, DC_WIN_BYTE_SWAP);
-
- tegra_dc_writel(dc,
- V_POSITION(win->out_y) | H_POSITION(win->out_x),
- DC_WIN_POSITION);
- tegra_dc_writel(dc,
- V_SIZE(win->out_h) | H_SIZE(win->out_w),
- DC_WIN_SIZE);
-
- if (tegra_dc_feature_has_scaling(dc, win->idx)) {
- tegra_dc_writel(dc,
- V_PRESCALED_SIZE(dfixed_trunc(win->h)) |
- H_PRESCALED_SIZE(dfixed_trunc(win->w) * Bpp),
- DC_WIN_PRESCALED_SIZE);
-
- h_dda = compute_dda_inc(win->w, win->out_w, false, Bpp_bw);
- v_dda = compute_dda_inc(win->h, win->out_h, true, Bpp_bw);
- tegra_dc_writel(dc, V_DDA_INC(v_dda) | H_DDA_INC(h_dda),
- DC_WIN_DDA_INCREMENT);
- h_dda = compute_initial_dda(win->x);
- v_dda = compute_initial_dda(win->y);
- tegra_dc_writel(dc, h_dda, DC_WIN_H_INITIAL_DDA);
- tegra_dc_writel(dc, v_dda, DC_WIN_V_INITIAL_DDA);
- }
-
- tegra_dc_writel(dc, 0, DC_WIN_BUF_STRIDE);
- tegra_dc_writel(dc, 0, DC_WIN_UV_BUF_STRIDE);
- tegra_dc_writel(dc,
- (unsigned long)win->phys_addr,
- DC_WINBUF_START_ADDR);
-
- if (!yuvp) {
- tegra_dc_writel(dc, win->stride, DC_WIN_LINE_STRIDE);
- } else {
- tegra_dc_writel(dc,
- (unsigned long)win->phys_addr_u,
- DC_WINBUF_START_ADDR_U);
- tegra_dc_writel(dc,
- (unsigned long)win->phys_addr_v,
- DC_WINBUF_START_ADDR_V);
- tegra_dc_writel(dc,
- LINE_STRIDE(win->stride) |
- UV_LINE_STRIDE(win->stride_uv),
- DC_WIN_LINE_STRIDE);
- }
-
- h_offset = win->x;
- if (invert_h) {
- h_offset.full += win->w.full - dfixed_const(1);
- }
-
- v_offset = win->y;
- if (invert_v) {
- v_offset.full += win->h.full - dfixed_const(1);
- }
-
- tegra_dc_writel(dc, dfixed_trunc(h_offset) * Bpp,
- DC_WINBUF_ADDR_H_OFFSET);
- tegra_dc_writel(dc, dfixed_trunc(v_offset),
- DC_WINBUF_ADDR_V_OFFSET);
-
- if (tegra_dc_feature_has_tiling(dc, win->idx)) {
- if (WIN_IS_TILED(win))
- tegra_dc_writel(dc,
- DC_WIN_BUFFER_ADDR_MODE_TILE |
- DC_WIN_BUFFER_ADDR_MODE_TILE_UV,
- DC_WIN_BUFFER_ADDR_MODE);
- else
- tegra_dc_writel(dc,
- DC_WIN_BUFFER_ADDR_MODE_LINEAR |
- DC_WIN_BUFFER_ADDR_MODE_LINEAR_UV,
- DC_WIN_BUFFER_ADDR_MODE);
- }
-
- val = WIN_ENABLE;
- if (yuv)
- val |= CSC_ENABLE;
- else if (tegra_dc_fmt_bpp(win->fmt) < 24)
- val |= COLOR_EXPAND;
-
- if (win->ppflags & TEGRA_WIN_PPFLAG_CP_ENABLE)
- val |= CP_ENABLE;
-
- if (filter_h)
- val |= H_FILTER_ENABLE;
- if (filter_v)
- val |= V_FILTER_ENABLE;
-
- if (invert_h)
- val |= H_DIRECTION_DECREMENT;
- if (invert_v)
- val |= V_DIRECTION_DECREMENT;
-
- tegra_dc_writel(dc, val, DC_WIN_WIN_OPTIONS);
-
-#ifdef CONFIG_ARCH_TEGRA_3x_SOC
- if (win->global_alpha == 255)
- tegra_dc_writel(dc, 0, DC_WIN_GLOBAL_ALPHA);
- else
- tegra_dc_writel(dc, GLOBAL_ALPHA_ENABLE |
- win->global_alpha, DC_WIN_GLOBAL_ALPHA);
-#endif
-
- win->dirty = no_vsync ? 0 : 1;
-
- dev_dbg(&dc->ndev->dev, "%s():idx=%d z=%d x=%d y=%d w=%d h=%d "
- "out_x=%u out_y=%u out_w=%u out_h=%u "
- "fmt=%d yuvp=%d Bpp=%u filter_h=%d filter_v=%d",
- __func__, win->idx, win->z,
- dfixed_trunc(win->x), dfixed_trunc(win->y),
- dfixed_trunc(win->w), dfixed_trunc(win->h),
- win->out_x, win->out_y, win->out_w, win->out_h,
- win->fmt, yuvp, Bpp, filter_h, filter_v);
- trace_printk("%s:win%u in:%ux%u out:%ux%u fmt=%d\n",
- dc->ndev->name, win->idx, dfixed_trunc(win->w),
- dfixed_trunc(win->h), win->out_w, win->out_h, win->fmt);
- }
-
- if (update_blend) {
- tegra_dc_set_blending(dc, &dc->blend);
- for (i = 0; i < DC_N_WINDOWS; i++) {
- if (!no_vsync)
- dc->windows[i].dirty = 1;
- update_mask |= WIN_A_ACT_REQ << i;
- }
- }
-
- tegra_dc_set_dynamic_emc(windows, n);
-
- tegra_dc_writel(dc, update_mask << 8, DC_CMD_STATE_CONTROL);
-
- tegra_dc_writel(dc, FRAME_END_INT | V_BLANK_INT, DC_CMD_INT_STATUS);
- if (!no_vsync) {
- set_bit(V_BLANK_FLIP, &dc->vblank_ref_count);
- tegra_dc_unmask_interrupt(dc, FRAME_END_INT | V_BLANK_INT | ALL_UF_INT);
- } else {
- clear_bit(V_BLANK_FLIP, &dc->vblank_ref_count);
- tegra_dc_mask_interrupt(dc, FRAME_END_INT | V_BLANK_INT | ALL_UF_INT);
- }
-
- if (dc->out->flags & TEGRA_DC_OUT_ONE_SHOT_MODE)
- schedule_delayed_work(&dc->one_shot_work,
- msecs_to_jiffies(dc->one_shot_delay_ms));
-
- /* update EMC clock if calculated bandwidth has changed */
- tegra_dc_program_bandwidth(dc, false);
-
- if (dc->out->flags & TEGRA_DC_OUT_ONE_SHOT_MODE)
- update_mask |= NC_HOST_TRIG;
-
- tegra_dc_writel(dc, update_mask, DC_CMD_STATE_CONTROL);
- trace_printk("%s:update_mask=%#lx\n", dc->ndev->name, update_mask);
-
- mutex_unlock(&dc->lock);
- if (dc->out->flags & TEGRA_DC_OUT_ONE_SHOT_MODE)
- mutex_unlock(&dc->one_shot_lock);
-
- return 0;
+ disable_irq(irq);
}
-EXPORT_SYMBOL(tegra_dc_update_windows);
u32 tegra_dc_get_syncpt_id(const struct tegra_dc *dc, int i)
{
@@ -1126,502 +594,6 @@ void tegra_dc_incr_syncpt_min(struct tegra_dc *dc, int i, u32 val)
mutex_unlock(&dc->lock);
}
-static bool tegra_dc_windows_are_clean(struct tegra_dc_win *windows[],
- int n)
-{
- int i;
-
- for (i = 0; i < n; i++) {
- if (windows[i]->dirty)
- return false;
- }
-
- return true;
-}
-
-/* does not support syncing windows on multiple dcs in one call */
-int tegra_dc_sync_windows(struct tegra_dc_win *windows[], int n)
-{
- int ret;
- if (n < 1 || n > DC_N_WINDOWS)
- return -EINVAL;
-
- if (!windows[0]->dc->enabled)
- return -EFAULT;
-
-#ifdef CONFIG_TEGRA_SIMULATION_PLATFORM
- /* Don't want to timeout on simulator */
- ret = wait_event_interruptible(windows[0]->dc->wq,
- tegra_dc_windows_are_clean(windows, n));
-#else
- trace_printk("%s:Before wait_event_interruptible_timeout\n",
- windows[0]->dc->ndev->name);
- ret = wait_event_interruptible_timeout(windows[0]->dc->wq,
- tegra_dc_windows_are_clean(windows, n),
- HZ);
- trace_printk("%s:After wait_event_interruptible_timeout\n",
- windows[0]->dc->ndev->name);
-#endif
- return ret;
-}
-EXPORT_SYMBOL(tegra_dc_sync_windows);
-
-static unsigned long tegra_dc_clk_get_rate(struct tegra_dc *dc)
-{
-#ifdef CONFIG_TEGRA_SILICON_PLATFORM
- return clk_get_rate(dc->clk);
-#else
- return 27000000;
-#endif
-}
-
-static unsigned long tegra_dc_pclk_round_rate(struct tegra_dc *dc, int pclk)
-{
- unsigned long rate;
- unsigned long div;
-
- rate = tegra_dc_clk_get_rate(dc);
-
- div = DIV_ROUND_CLOSEST(rate * 2, pclk);
-
- if (div < 2)
- return 0;
-
- return rate * 2 / div;
-}
-
-static unsigned long tegra_dc_pclk_predict_rate(struct clk *parent, int pclk)
-{
- unsigned long rate;
- unsigned long div;
-
- rate = clk_get_rate(parent);
-
- div = DIV_ROUND_CLOSEST(rate * 2, pclk);
-
- if (div < 2)
- return 0;
-
- return rate * 2 / div;
-}
-
-void tegra_dc_setup_clk(struct tegra_dc *dc, struct clk *clk)
-{
- int pclk;
-
- if (dc->out->type == TEGRA_DC_OUT_RGB) {
- unsigned long rate;
- struct clk *parent_clk =
- clk_get_sys(NULL, dc->out->parent_clk ? : "pll_p");
-
- if (dc->out->parent_clk_backup &&
- (parent_clk == clk_get_sys(NULL, "pll_p"))) {
- rate = tegra_dc_pclk_predict_rate(
- parent_clk, dc->mode.pclk);
- /* use pll_d as last resort */
- if (rate < (dc->mode.pclk / 100 * 99) ||
- rate > (dc->mode.pclk / 100 * 109))
- parent_clk = clk_get_sys(
- NULL, dc->out->parent_clk_backup);
- }
-
- if (clk_get_parent(clk) != parent_clk)
- clk_set_parent(clk, parent_clk);
-
- if (parent_clk != clk_get_sys(NULL, "pll_p")) {
- struct clk *base_clk = clk_get_parent(parent_clk);
-
- /* Assuming either pll_d or pll_d2 is used */
- rate = dc->mode.pclk * 2;
-
- if (rate != clk_get_rate(base_clk))
- clk_set_rate(base_clk, rate);
- }
- }
-
- if (dc->out->type == TEGRA_DC_OUT_HDMI) {
- unsigned long rate;
- struct clk *parent_clk =
- clk_get_sys(NULL, dc->out->parent_clk ? : "pll_d_out0");
- struct clk *base_clk = clk_get_parent(parent_clk);
-
- /*
- * Providing dynamic frequency rate setting for T20/T30 HDMI.
- * The required rate needs to be setup at 4x multiplier,
- * as out0 is 1/2 of the actual PLL output.
- */
-
- rate = dc->mode.pclk * 4;
- if (rate != clk_get_rate(base_clk))
- clk_set_rate(base_clk, rate);
-
- if (clk_get_parent(clk) != parent_clk)
- clk_set_parent(clk, parent_clk);
- }
-
- if (dc->out->type == TEGRA_DC_OUT_DSI) {
- unsigned long rate;
- struct clk *parent_clk;
- struct clk *base_clk;
-
- if (clk == dc->clk) {
- parent_clk = clk_get_sys(NULL,
- dc->out->parent_clk ? : "pll_d_out0");
- base_clk = clk_get_parent(parent_clk);
- tegra_clk_cfg_ex(base_clk,
- TEGRA_CLK_PLLD_DSI_OUT_ENB, 1);
- } else {
- if (dc->pdata->default_out->dsi->dsi_instance) {
- parent_clk = clk_get_sys(NULL,
- dc->out->parent_clk ? : "pll_d2_out0");
- base_clk = clk_get_parent(parent_clk);
- tegra_clk_cfg_ex(base_clk,
- TEGRA_CLK_PLLD_CSI_OUT_ENB, 1);
- } else {
- parent_clk = clk_get_sys(NULL,
- dc->out->parent_clk ? : "pll_d_out0");
- base_clk = clk_get_parent(parent_clk);
- tegra_clk_cfg_ex(base_clk,
- TEGRA_CLK_PLLD_DSI_OUT_ENB, 1);
- }
- }
-
- rate = dc->mode.pclk * dc->shift_clk_div * 2;
- if (rate != clk_get_rate(base_clk))
- clk_set_rate(base_clk, rate);
-
- if (clk_get_parent(clk) != parent_clk)
- clk_set_parent(clk, parent_clk);
- }
-
- pclk = tegra_dc_pclk_round_rate(dc, dc->mode.pclk);
- tegra_dvfs_set_rate(clk, pclk);
-}
-
-/* return non-zero if constraint is violated */
-static int calc_h_ref_to_sync(const struct tegra_dc_mode *mode, int *href)
-{
- long a, b;
-
- /* Constraint 5: H_REF_TO_SYNC >= 0 */
- a = 0;
-
- /* Constraint 6: H_FRONT_PORT >= (H_REF_TO_SYNC + 1) */
- b = mode->h_front_porch - 1;
-
- /* Constraint 1: H_REF_TO_SYNC + H_SYNC_WIDTH + H_BACK_PORCH > 11 */
- if (a + mode->h_sync_width + mode->h_back_porch <= 11)
- a = 1 + 11 - mode->h_sync_width - mode->h_back_porch;
- /* check Constraint 1 and 6 */
- if (a > b)
- return 1;
-
- /* Constraint 4: H_SYNC_WIDTH >= 1 */
- if (mode->h_sync_width < 1)
- return 4;
-
- /* Constraint 7: H_DISP_ACTIVE >= 16 */
- if (mode->h_active < 16)
- return 7;
-
- if (href) {
- if (b > a && a % 2)
- *href = a + 1; /* use smallest even value */
- else
- *href = a; /* even or only possible value */
- }
-
- return 0;
-}
-
-static int calc_v_ref_to_sync(const struct tegra_dc_mode *mode, int *vref)
-{
- long a;
- a = 1; /* Constraint 5: V_REF_TO_SYNC >= 1 */
-
- /* Constraint 2: V_REF_TO_SYNC + V_SYNC_WIDTH + V_BACK_PORCH > 1 */
- if (a + mode->v_sync_width + mode->v_back_porch <= 1)
- a = 1 + 1 - mode->v_sync_width - mode->v_back_porch;
-
- /* Constraint 6 */
- if (mode->v_front_porch < a + 1)
- a = mode->v_front_porch - 1;
-
- /* Constraint 4: V_SYNC_WIDTH >= 1 */
- if (mode->v_sync_width < 1)
- return 4;
-
- /* Constraint 7: V_DISP_ACTIVE >= 16 */
- if (mode->v_active < 16)
- return 7;
-
- if (vref)
- *vref = a;
- return 0;
-}
-
-static int calc_ref_to_sync(struct tegra_dc_mode *mode)
-{
- int ret;
- ret = calc_h_ref_to_sync(mode, &mode->h_ref_to_sync);
- if (ret)
- return ret;
- ret = calc_v_ref_to_sync(mode, &mode->v_ref_to_sync);
- if (ret)
- return ret;
-
- return 0;
-}
-
-static bool check_ref_to_sync(struct tegra_dc_mode *mode)
-{
- /* Constraint 1: H_REF_TO_SYNC + H_SYNC_WIDTH + H_BACK_PORCH > 11. */
- if (mode->h_ref_to_sync + mode->h_sync_width + mode->h_back_porch <= 11)
- return false;
-
- /* Constraint 2: V_REF_TO_SYNC + V_SYNC_WIDTH + V_BACK_PORCH > 1. */
- if (mode->v_ref_to_sync + mode->v_sync_width + mode->v_back_porch <= 1)
- return false;
-
- /* Constraint 3: V_FRONT_PORCH + V_SYNC_WIDTH + V_BACK_PORCH > 1
- * (vertical blank). */
- if (mode->v_front_porch + mode->v_sync_width + mode->v_back_porch <= 1)
- return false;
-
- /* Constraint 4: V_SYNC_WIDTH >= 1; H_SYNC_WIDTH >= 1. */
- if (mode->v_sync_width < 1 || mode->h_sync_width < 1)
- return false;
-
- /* Constraint 5: V_REF_TO_SYNC >= 1; H_REF_TO_SYNC >= 0. */
- if (mode->v_ref_to_sync < 1 || mode->h_ref_to_sync < 0)
- return false;
-
- /* Constraint 6: V_FRONT_PORT >= (V_REF_TO_SYNC + 1);
- * H_FRONT_PORT >= (H_REF_TO_SYNC + 1). */
- if (mode->v_front_porch < mode->v_ref_to_sync + 1 ||
- mode->h_front_porch < mode->h_ref_to_sync + 1)
- return false;
-
- /* Constraint 7: H_DISP_ACTIVE >= 16; V_DISP_ACTIVE >= 16. */
- if (mode->h_active < 16 || mode->v_active < 16)
- return false;
-
- return true;
-}
-
-#ifdef DEBUG
-/* return in 1000ths of a Hertz */
-static int calc_refresh(const struct tegra_dc_mode *m)
-{
- long h_total, v_total, refresh;
- h_total = m->h_active + m->h_front_porch + m->h_back_porch +
- m->h_sync_width;
- v_total = m->v_active + m->v_front_porch + m->v_back_porch +
- m->v_sync_width;
- refresh = m->pclk / h_total;
- refresh *= 1000;
- refresh /= v_total;
- return refresh;
-}
-
-static void print_mode(struct tegra_dc *dc,
- const struct tegra_dc_mode *mode, const char *note)
-{
- if (mode) {
- int refresh = calc_refresh(dc, mode);
- dev_info(&dc->ndev->dev, "%s():MODE:%dx%d@%d.%03uHz pclk=%d\n",
- note ? note : "",
- mode->h_active, mode->v_active,
- refresh / 1000, refresh % 1000,
- mode->pclk);
- }
-}
-#else /* !DEBUG */
-static inline void print_mode(struct tegra_dc *dc,
- const struct tegra_dc_mode *mode, const char *note) { }
-#endif /* DEBUG */
-
-static inline void enable_dc_irq(unsigned int irq)
-{
-#ifndef CONFIG_TEGRA_FPGA_PLATFORM
- enable_irq(irq);
-#else
- /* Always disable DC interrupts on FPGA. */
- disable_irq(irq);
-#endif
-}
-
-static inline void disable_dc_irq(unsigned int irq)
-{
- disable_irq(irq);
-}
-
-static inline void tegra_dc_unmask_interrupt(struct tegra_dc *dc, u32 int_val)
-{
- u32 val;
-
- val = tegra_dc_readl(dc, DC_CMD_INT_MASK);
- val |= int_val;
- tegra_dc_writel(dc, val, DC_CMD_INT_MASK);
-}
-
-static inline void tegra_dc_mask_interrupt(struct tegra_dc *dc, u32 int_val)
-{
- u32 val;
-
- val = tegra_dc_readl(dc, DC_CMD_INT_MASK);
- val &= ~int_val;
- tegra_dc_writel(dc, val, DC_CMD_INT_MASK);
-}
-
-static int tegra_dc_program_mode(struct tegra_dc *dc, struct tegra_dc_mode *mode)
-{
- unsigned long val;
- unsigned long rate;
- unsigned long div;
- unsigned long pclk;
-
- print_mode(dc, mode, __func__);
-
- /* use default EMC rate when switching modes */
- dc->new_emc_clk_rate = tegra_dc_get_default_emc_clk_rate(dc);
- tegra_dc_program_bandwidth(dc, true);
-
- tegra_dc_writel(dc, 0x0, DC_DISP_DISP_TIMING_OPTIONS);
- tegra_dc_writel(dc, mode->h_ref_to_sync | (mode->v_ref_to_sync << 16),
- DC_DISP_REF_TO_SYNC);
- tegra_dc_writel(dc, mode->h_sync_width | (mode->v_sync_width << 16),
- DC_DISP_SYNC_WIDTH);
- tegra_dc_writel(dc, mode->h_back_porch | (mode->v_back_porch << 16),
- DC_DISP_BACK_PORCH);
- tegra_dc_writel(dc, mode->h_active | (mode->v_active << 16),
- DC_DISP_DISP_ACTIVE);
- tegra_dc_writel(dc, mode->h_front_porch | (mode->v_front_porch << 16),
- DC_DISP_FRONT_PORCH);
-
- tegra_dc_writel(dc, DE_SELECT_ACTIVE | DE_CONTROL_NORMAL,
- DC_DISP_DATA_ENABLE_OPTIONS);
-
- /* TODO: MIPI/CRT/HDMI clock cals */
-
- val = DISP_DATA_FORMAT_DF1P1C;
-
- if (dc->out->align == TEGRA_DC_ALIGN_MSB)
- val |= DISP_DATA_ALIGNMENT_MSB;
- else
- val |= DISP_DATA_ALIGNMENT_LSB;
-
- if (dc->out->order == TEGRA_DC_ORDER_RED_BLUE)
- val |= DISP_DATA_ORDER_RED_BLUE;
- else
- val |= DISP_DATA_ORDER_BLUE_RED;
-
- tegra_dc_writel(dc, val, DC_DISP_DISP_INTERFACE_CONTROL);
-
- rate = tegra_dc_clk_get_rate(dc);
-
- pclk = tegra_dc_pclk_round_rate(dc, mode->pclk);
- trace_printk("%s:pclk=%ld\n", dc->ndev->name, pclk);
- if (pclk < (mode->pclk / 100 * 99) ||
- pclk > (mode->pclk / 100 * 109)) {
- dev_err(&dc->ndev->dev,
- "can't divide %ld clock to %d -1/+9%% %ld %d %d\n",
- rate, mode->pclk,
- pclk, (mode->pclk / 100 * 99),
- (mode->pclk / 100 * 109));
- return -EINVAL;
- }
-
- div = (rate * 2 / pclk) - 2;
- trace_printk("%s:div=%ld\n", dc->ndev->name, div);
-
- tegra_dc_writel(dc, 0x00010001,
- DC_DISP_SHIFT_CLOCK_OPTIONS);
- tegra_dc_writel(dc, PIXEL_CLK_DIVIDER_PCD1 | SHIFT_CLK_DIVIDER(div),
- DC_DISP_DISP_CLOCK_CONTROL);
-
-#ifdef CONFIG_SWITCH
- switch_set_state(&dc->modeset_switch,
- (mode->h_active << 16) | mode->v_active);
-#endif
-
- tegra_dc_writel(dc, GENERAL_UPDATE, DC_CMD_STATE_CONTROL);
- tegra_dc_writel(dc, GENERAL_ACT_REQ, DC_CMD_STATE_CONTROL);
-
- print_mode_info(dc, dc->mode);
- return 0;
-}
-
-
-int tegra_dc_set_mode(struct tegra_dc *dc, const struct tegra_dc_mode *mode)
-{
- memcpy(&dc->mode, mode, sizeof(dc->mode));
-
- print_mode(dc, mode, __func__);
-
- return 0;
-}
-EXPORT_SYMBOL(tegra_dc_set_mode);
-
-int tegra_dc_set_fb_mode(struct tegra_dc *dc,
- const struct fb_videomode *fbmode, bool stereo_mode)
-{
- struct tegra_dc_mode mode;
-
- if (!fbmode->pixclock)
- return -EINVAL;
-
- mode.pclk = PICOS2KHZ(fbmode->pixclock) * 1000;
- mode.h_sync_width = fbmode->hsync_len;
- mode.v_sync_width = fbmode->vsync_len;
- mode.h_back_porch = fbmode->left_margin;
- mode.v_back_porch = fbmode->upper_margin;
- mode.h_active = fbmode->xres;
- mode.v_active = fbmode->yres;
- mode.h_front_porch = fbmode->right_margin;
- mode.v_front_porch = fbmode->lower_margin;
- mode.stereo_mode = stereo_mode;
- if (dc->out->type == TEGRA_DC_OUT_HDMI) {
- /* HDMI controller requires h_ref=1, v_ref=1 */
- mode.h_ref_to_sync = 1;
- mode.v_ref_to_sync = 1;
- } else {
- calc_ref_to_sync(&mode);
- }
- if (!check_ref_to_sync(&mode)) {
- dev_err(&dc->ndev->dev,
- "Display timing doesn't meet restrictions.\n");
- return -EINVAL;
- }
- dev_info(&dc->ndev->dev, "Using mode %dx%d pclk=%d href=%d vref=%d\n",
- mode.h_active, mode.v_active, mode.pclk,
- mode.h_ref_to_sync, mode.v_ref_to_sync
- );
-
-#ifndef CONFIG_TEGRA_HDMI_74MHZ_LIMIT
- /* Double the pixel clock and update v_active only for frame packed mode */
- if (mode.stereo_mode) {
- mode.pclk *= 2;
- /* total v_active = yres*2 + activespace */
- mode.v_active = fbmode->yres*2 +
- fbmode->vsync_len +
- fbmode->upper_margin +
- fbmode->lower_margin;
- }
-#endif
-
- mode.flags = 0;
-
- if (!(fbmode->sync & FB_SYNC_HOR_HIGH_ACT))
- mode.flags |= TEGRA_DC_MODE_FLAG_NEG_H_SYNC;
-
- if (!(fbmode->sync & FB_SYNC_VERT_HIGH_ACT))
- mode.flags |= TEGRA_DC_MODE_FLAG_NEG_V_SYNC;
-
- return tegra_dc_set_mode(dc, &mode);
-}
-EXPORT_SYMBOL(tegra_dc_set_fb_mode);
-
void
tegra_dc_config_pwm(struct tegra_dc *dc, struct tegra_dc_pwm_params *cfg)
{
@@ -1841,6 +813,28 @@ crc_error:
return crc;
}
+static bool tegra_dc_windows_are_dirty(struct tegra_dc *dc)
+{
+#ifndef CONFIG_TEGRA_SIMULATION_PLATFORM
+ u32 val;
+
+ val = tegra_dc_readl(dc, DC_CMD_STATE_CONTROL);
+ if (val & (WIN_A_ACT_REQ | WIN_B_ACT_REQ | WIN_C_ACT_REQ))
+ return true;
+#endif
+ return false;
+}
+
+static inline void enable_dc_irq(unsigned int irq)
+{
+#ifndef CONFIG_TEGRA_FPGA_PLATFORM
+ enable_irq(irq);
+#else
+ /* Always disable DC interrupts on FPGA. */
+ disable_irq(irq);
+#endif
+}
+
static void tegra_dc_vblank(struct work_struct *work)
{
struct tegra_dc *dc = container_of(work, struct tegra_dc, vblank_work);
@@ -1987,50 +981,6 @@ static void tegra_dc_underflow_handler(struct tegra_dc *dc)
}
#ifndef CONFIG_TEGRA_FPGA_PLATFORM
-static bool tegra_dc_windows_are_dirty(struct tegra_dc *dc)
-{
-#ifndef CONFIG_TEGRA_SIMULATION_PLATFORM
- u32 val;
-
- val = tegra_dc_readl(dc, DC_CMD_STATE_CONTROL);
- if (val & (WIN_A_ACT_REQ | WIN_B_ACT_REQ | WIN_C_ACT_REQ))
- return true;
-#endif
- return false;
-}
-
-static void tegra_dc_trigger_windows(struct tegra_dc *dc)
-{
- u32 val, i;
- u32 completed = 0;
- u32 dirty = 0;
-
- val = tegra_dc_readl(dc, DC_CMD_STATE_CONTROL);
- for (i = 0; i < DC_N_WINDOWS; i++) {
-#ifdef CONFIG_TEGRA_SIMULATION_PLATFORM
- /* FIXME: this is not needed when the simulator
- clears WIN_x_UPDATE bits as in HW */
- dc->windows[i].dirty = 0;
- completed = 1;
-#else
- if (!(val & (WIN_A_ACT_REQ << i))) {
- dc->windows[i].dirty = 0;
- completed = 1;
- } else {
- dirty = 1;
- }
-#endif
- }
-
- if (!dirty) {
- if (!(dc->out->flags & TEGRA_DC_OUT_ONE_SHOT_MODE))
- tegra_dc_mask_interrupt(dc, FRAME_END_INT);
- }
-
- if (completed)
- wake_up(&dc->wq);
-}
-
static void tegra_dc_one_shot_irq(struct tegra_dc *dc, unsigned long status)
{
if (status & V_BLANK_INT) {
@@ -2285,7 +1235,7 @@ static int tegra_dc_init(struct tegra_dc *dc)
nvhost_syncpt_read_ext(dc->ndev, syncpt);
}
- print_mode(dc, &dc->mode, __func__);
+ print_mode_info(dc, dc->mode);
if (dc->mode.pclk)
if (tegra_dc_program_mode(dc, &dc->mode))
@@ -2586,7 +1536,8 @@ static void tegra_dc_reset_worker(struct work_struct *work)
mutex_lock(&shared_lock);
- dev_warn(&dc->ndev->dev, "overlay stuck in underflow state. resetting.\n");
+ dev_warn(&dc->ndev->dev,
+ "overlay stuck in underflow state. resetting.\n");
tegra_dc_ext_disable(dc->ext);
@@ -2698,7 +1649,8 @@ static int tegra_dc_probe(struct nvhost_device *ndev,
goto err_free;
}
- base_res = request_mem_region(res->start, resource_size(res), ndev->name);
+ base_res = request_mem_region(res->start, resource_size(res),
+ ndev->name);
if (!base_res) {
dev_err(&ndev->dev, "request_mem_region failed\n");
ret = -EBUSY;
diff --git a/drivers/video/tegra/dc/dc_config.c b/drivers/video/tegra/dc/dc_config.c
index a40712f5dca1..f238faddab12 100644
--- a/drivers/video/tegra/dc/dc_config.c
+++ b/drivers/video/tegra/dc/dc_config.c
@@ -1,6 +1,7 @@
/*
* drivers/video/tegra/dc/dc_config.c
- * * Copyright (c) 2012, NVIDIA Corporation.
+ *
+ * Copyright (c) 2012, NVIDIA CORPORATION, All rights reserved.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
diff --git a/drivers/video/tegra/dc/dc_config.h b/drivers/video/tegra/dc/dc_config.h
index 4cc924184275..6f5d08ccd82a 100644
--- a/drivers/video/tegra/dc/dc_config.h
+++ b/drivers/video/tegra/dc/dc_config.h
@@ -1,6 +1,6 @@
/*
* drivers/video/tegra/dc/dc_config.c
- * * Copyright (c) 2012, NVIDIA Corporation.
+ * Copyright (c) 2010-2012, NVIDIA CORPORATION, All rights reserved.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
diff --git a/drivers/video/tegra/dc/dc_priv.h b/drivers/video/tegra/dc/dc_priv.h
index 19c8656689d1..fb1243593587 100644
--- a/drivers/video/tegra/dc/dc_priv.h
+++ b/drivers/video/tegra/dc/dc_priv.h
@@ -4,6 +4,8 @@
* Copyright (C) 2010 Google, Inc.
* Author: Erik Gilling <konkers@android.com>
*
+ * Copyright (c) 2010-2012, NVIDIA CORPORATION, All rights reserved.
+ *
* This software is licensed under the terms of the GNU General Public
* License version 2, as published by the Free Software Foundation, and
* may be copied, distributed, and modified under those terms.
@@ -22,6 +24,7 @@
#include <linux/mutex.h>
#include <linux/wait.h>
#include <linux/fb.h>
+#include <linux/clk.h>
#include <linux/completion.h>
#include <linux/switch.h>
#include <linux/nvhost.h>
@@ -31,6 +34,8 @@
#include <mach/tegra_dc_ext.h>
#include <mach/clk.h>
+#include "dc_reg.h"
+
#define WIN_IS_TILED(win) ((win)->flags & TEGRA_WIN_FLAG_TILED)
#define WIN_IS_ENABLED(win) ((win)->flags & TEGRA_WIN_FLAG_ENABLED)
@@ -45,6 +50,13 @@
#define EMC_BW_TO_FREQ(bw) (DDR_BW_TO_FREQ(bw) * 2)
#endif
+#ifndef CONFIG_TEGRA_FPGA_PLATFORM
+#define ALL_UF_INT (WIN_A_UF_INT | WIN_B_UF_INT | WIN_C_UF_INT)
+#else
+/* ignore underflows when on simulation and fpga platform */
+#define ALL_UF_INT (0)
+#endif
+
struct tegra_dc;
struct tegra_dc_blend {
@@ -147,6 +159,23 @@ struct tegra_dc {
struct delayed_work one_shot_work;
};
+#define print_mode_info(dc, mode) do { \
+ trace_printk("%s:Mode settings: " \
+ "ref_to_sync: H = %d V = %d, " \
+ "sync_width: H = %d V = %d, " \
+ "back_porch: H = %d V = %d, " \
+ "active: H = %d V = %d, " \
+ "front_porch: H = %d V = %d, " \
+ "pclk = %d, stereo mode = %d\n", \
+ dc->ndev->name, \
+ mode.h_ref_to_sync, mode.v_ref_to_sync, \
+ mode.h_sync_width, mode.v_sync_width, \
+ mode.h_back_porch, mode.v_back_porch, \
+ mode.h_active, mode.v_active, \
+ mode.h_front_porch, mode.v_front_porch, \
+ mode.pclk, mode.stereo_mode); \
+ } while (0)
+
static inline void tegra_dc_io_start(struct tegra_dc *dc)
{
nvhost_module_busy_ext(nvhost_get_parent(dc->ndev));
@@ -290,11 +319,32 @@ static inline bool tegra_dc_is_yuv_planar(int fmt)
return false;
}
-static inline void tegra_dc_unmask_interrupt(struct tegra_dc *dc, u32 int_val);
-static inline void tegra_dc_mask_interrupt(struct tegra_dc *dc, u32 int_val);
-static bool tegra_dc_windows_are_dirty(struct tegra_dc *dc);
+static inline void tegra_dc_unmask_interrupt(struct tegra_dc *dc, u32 int_val)
+{
+ u32 val;
-void tegra_dc_setup_clk(struct tegra_dc *dc, struct clk *clk);
+ val = tegra_dc_readl(dc, DC_CMD_INT_MASK);
+ val |= int_val;
+ tegra_dc_writel(dc, val, DC_CMD_INT_MASK);
+}
+
+static inline void tegra_dc_mask_interrupt(struct tegra_dc *dc, u32 int_val)
+{
+ u32 val;
+
+ val = tegra_dc_readl(dc, DC_CMD_INT_MASK);
+ val &= ~int_val;
+ tegra_dc_writel(dc, val, DC_CMD_INT_MASK);
+}
+
+static inline unsigned long tegra_dc_clk_get_rate(struct tegra_dc *dc)
+{
+#ifdef CONFIG_TEGRA_SILICON_PLATFORM
+ return clk_get_rate(dc->clk);
+#else
+ return dc->mode.pclk;
+#endif
+}
extern struct tegra_dc_out_ops tegra_dc_rgb_ops;
extern struct tegra_dc_out_ops tegra_dc_hdmi_ops;
@@ -323,4 +373,24 @@ unsigned int tegra_dc_has_multiple_dc(void);
void tegra_dc_clear_bandwidth(struct tegra_dc *dc);
void tegra_dc_program_bandwidth(struct tegra_dc *dc, bool use_new);
int tegra_dc_set_dynamic_emc(struct tegra_dc_win *windows[], int n);
+
+/* defined in mode.c, used in dc.c */
+int tegra_dc_program_mode(struct tegra_dc *dc, struct tegra_dc_mode *mode);
+int tegra_dc_calc_refresh(const struct tegra_dc_mode *m);
+
+/* defined in clock.c, used in dc.c, dsi.c and hdmi.c */
+void tegra_dc_setup_clk(struct tegra_dc *dc, struct clk *clk);
+unsigned long tegra_dc_pclk_round_rate(struct tegra_dc *dc, int pclk);
+
+/* defined in lut.c, used in dc.c */
+void tegra_dc_init_lut_defaults(struct tegra_dc_lut *lut);
+void tegra_dc_set_lut(struct tegra_dc *dc, struct tegra_dc_win *win);
+
+/* defined in csc.c, used in dc.c */
+void tegra_dc_init_csc_defaults(struct tegra_dc_csc *csc);
+void tegra_dc_set_csc(struct tegra_dc *dc, struct tegra_dc_csc *csc);
+
+/* defined in window.c, used in dc.c */
+void tegra_dc_trigger_windows(struct tegra_dc *dc);
+
#endif
diff --git a/drivers/video/tegra/dc/dc_reg.h b/drivers/video/tegra/dc/dc_reg.h
index 0b628fc7a14a..86b1029d3bba 100644
--- a/drivers/video/tegra/dc/dc_reg.h
+++ b/drivers/video/tegra/dc/dc_reg.h
@@ -4,7 +4,7 @@
* Copyright (C) 2010 Google, Inc.
* Author: Erik Gilling <konkers@android.com>
*
- * Copyright (C) 2010-2011 NVIDIA Corporation
+ * Copyright (c) 2010-2012, NVIDIA CORPORATION, All rights reserved.
*
* This software is licensed under the terms of the GNU General Public
* License version 2, as published by the Free Software Foundation, and
diff --git a/drivers/video/tegra/dc/dc_sysfs.c b/drivers/video/tegra/dc/dc_sysfs.c
index 0b259c374360..bf27e963f233 100644
--- a/drivers/video/tegra/dc/dc_sysfs.c
+++ b/drivers/video/tegra/dc/dc_sysfs.c
@@ -1,7 +1,7 @@
/*
* drivers/video/tegra/dc/dc_sysfs.c
*
- * Copyright (c) 2011, NVIDIA Corporation.
+ * Copyright (c) 2011-2012, NVIDIA CORPORATION, All rights reserved.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
diff --git a/drivers/video/tegra/dc/dsi.c b/drivers/video/tegra/dc/dsi.c
index 3c00b3150f47..7ee9375f58f1 100644
--- a/drivers/video/tegra/dc/dsi.c
+++ b/drivers/video/tegra/dc/dsi.c
@@ -1,7 +1,7 @@
/*
* drivers/video/tegra/dc/dsi.c
*
- * Copyright (c) 2011-2012, NVIDIA Corporation.
+ * Copyright (c) 2011-2012, NVIDIA CORPORATION, All rights reserved.
*
* This software is licensed under the terms of the GNU General Public
* License version 2, as published by the Free Software Foundation, and
@@ -40,7 +40,7 @@
#include "dsi_regs.h"
#include "dsi.h"
-#define APB_MISC_GP_MIPI_PAD_CTRL_0 (TEGRA_APB_MISC_BASE + 0x820)
+#define APB_MISC_GP_MIPI_PAD_CTRL_0 (TEGRA_APB_MISC_BASE + 0x820)
#define DSIB_MODE_ENABLE 0x2
#define DSI_USE_SYNC_POINTS 1
@@ -1073,7 +1073,7 @@ static u32 tegra_dsi_sol_delay_burst(struct tegra_dc *dc,
u32 dsi_to_pixel_clk_ratio;
u32 temp;
u32 temp1;
- u32 mipi_clk_adj_kHz;
+ u32 mipi_clk_adj_kHz = 0;
u32 sol_delay;
struct tegra_dc_mode *dc_modes = &dc->mode;
diff --git a/drivers/video/tegra/dc/dsi.h b/drivers/video/tegra/dc/dsi.h
index 18ea9c959e8d..bf54913a1794 100644
--- a/drivers/video/tegra/dc/dsi.h
+++ b/drivers/video/tegra/dc/dsi.h
@@ -1,18 +1,18 @@
/*
- * drivers/video/tegra/dc/dsi.h
- *
- * Copyright (c) 2011, NVIDIA Corporation.
- *
- * This software is licensed under the terms of the GNU General Public
- * License version 2, as published by the Free Software Foundation, and
- * may be copied, distributed, and modified under those terms.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- */
+ * drivers/video/tegra/dc/dsi.h
+ *
+ * Copyright (c) 2011-2012, NVIDIA CORPORATION, All rights reserved.
+ *
+ * This software is licensed under the terms of the GNU General Public
+ * License version 2, as published by the Free Software Foundation, and
+ * may be copied, distributed, and modified under those terms.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ */
#ifndef __DRIVERS_VIDEO_TEGRA_DC_DSI_H__
#define __DRIVERS_VIDEO_TEGRA_DC_DSI_H__
diff --git a/drivers/video/tegra/dc/dsi_regs.h b/drivers/video/tegra/dc/dsi_regs.h
index 203ac32bd92d..71045fcec29e 100644
--- a/drivers/video/tegra/dc/dsi_regs.h
+++ b/drivers/video/tegra/dc/dsi_regs.h
@@ -1,18 +1,18 @@
/*
- * drivers/video/tegra/dc/dsi_regs.h
- *
- * Copyright (c) 2011, NVIDIA Corporation.
- *
- * This software is licensed under the terms of the GNU General Public
- * License version 2, as published by the Free Software Foundation, and
- * may be copied, distributed, and modified under those terms.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- */
+ * drivers/video/tegra/dc/dsi_regs.h
+ *
+ * Copyright (c) 2011-2012, NVIDIA CORPORATION, All rights reserved.
+ *
+ * This software is licensed under the terms of the GNU General Public
+ * License version 2, as published by the Free Software Foundation, and
+ * may be copied, distributed, and modified under those terms.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ */
#ifndef __DRIVERS_VIDEO_TEGRA_DC_DSI_REG_H__
#define __DRIVERS_VIDEO_TEGRA_DC_DSI_REG_H__
diff --git a/drivers/video/tegra/dc/edid.c b/drivers/video/tegra/dc/edid.c
index 8776c5393410..b1de7ab1dfb5 100644
--- a/drivers/video/tegra/dc/edid.c
+++ b/drivers/video/tegra/dc/edid.c
@@ -4,7 +4,7 @@
* Copyright (C) 2010 Google, Inc.
* Author: Erik Gilling <konkers@android.com>
*
- * Copyright (C) 2010-2011 NVIDIA Corporation
+ * Copyright (c) 2010-2012, NVIDIA CORPORATION, All rights reserved.
*
* This software is licensed under the terms of the GNU General Public
* License version 2, as published by the Free Software Foundation, and
diff --git a/drivers/video/tegra/dc/ext/control.c b/drivers/video/tegra/dc/ext/control.c
index 9caf3e11c16c..ed812be2eab5 100644
--- a/drivers/video/tegra/dc/ext/control.c
+++ b/drivers/video/tegra/dc/ext/control.c
@@ -1,7 +1,7 @@
/*
* drivers/video/tegra/dc/ext/control.c
*
- * Copyright (C) 2011, NVIDIA Corporation
+ * Copyright (c) 2011-2012, NVIDIA CORPORATION, All rights reserved.
*
* Author: Robert Morell <rmorell@nvidia.com>
*
@@ -67,7 +67,7 @@ static int get_output_edid(struct tegra_dc_ext_control_output_edid *edid)
struct tegra_dc *dc;
size_t user_size = edid->size;
struct tegra_dc_edid *dc_edid = NULL;
- int ret;
+ int ret = 0;
/* TODO: this should be more dynamic */
if (edid->handle > 2)
@@ -262,10 +262,7 @@ int tegra_dc_ext_control_init(void)
return ret;
control->dev = device_create(tegra_dc_ext_class,
- NULL,
- tegra_dc_ext_devno,
- NULL,
- "tegra_dc_ctrl");
+ NULL, tegra_dc_ext_devno, NULL, "tegra_dc_ctrl");
if (IS_ERR(control->dev)) {
ret = PTR_ERR(control->dev);
cdev_del(&control->cdev);
diff --git a/drivers/video/tegra/dc/ext/cursor.c b/drivers/video/tegra/dc/ext/cursor.c
index d8fa5fd8e6d9..970f38f5ac09 100644
--- a/drivers/video/tegra/dc/ext/cursor.c
+++ b/drivers/video/tegra/dc/ext/cursor.c
@@ -1,7 +1,7 @@
/*
* drivers/video/tegra/dc/ext/cursor.c
*
- * Copyright (C) 2011, NVIDIA Corporation
+ * Copyright (c) 2011-2012, NVIDIA CORPORATION, All rights reserved.
*
* Author: Robert Morell <rmorell@nvidia.com>
*
diff --git a/drivers/video/tegra/dc/ext/dev.c b/drivers/video/tegra/dc/ext/dev.c
index a8de7a7a26e0..f9c76f8f0d0d 100644
--- a/drivers/video/tegra/dc/ext/dev.c
+++ b/drivers/video/tegra/dc/ext/dev.c
@@ -1,7 +1,7 @@
/*
* drivers/video/tegra/dc/dev.c
*
- * Copyright (C) 2011-2012, NVIDIA Corporation
+ * Copyright (c) 2011-2012, NVIDIA CORPORATION, All rights reserved.
*
* Author: Robert Morell <rmorell@nvidia.com>
* Some code based on fbdev extensions written by:
@@ -447,7 +447,7 @@ static int tegra_dc_ext_flip(struct tegra_dc_ext_user *user,
{
struct tegra_dc_ext *ext = user->ext;
struct tegra_dc_ext_flip_data *data;
- int work_index;
+ int work_index = -1;
int i, ret = 0;
#ifdef CONFIG_ANDROID
@@ -559,6 +559,10 @@ static int tegra_dc_ext_flip(struct tegra_dc_ext_user *user,
atomic_inc(&ext->win[work_index].nr_pending_flips);
}
+ if (work_index < 0) {
+ ret = -EINVAL;
+ goto unlock;
+ }
queue_work(ext->win[work_index].flip_wq, &data->work);
unlock_windows_for_flip(user, args);
diff --git a/drivers/video/tegra/dc/ext/events.c b/drivers/video/tegra/dc/ext/events.c
index 150a1501fced..577d056e2436 100644
--- a/drivers/video/tegra/dc/ext/events.c
+++ b/drivers/video/tegra/dc/ext/events.c
@@ -1,7 +1,7 @@
/*
* drivers/video/tegra/dc/ext/events.c
*
- * Copyright (C) 2011, NVIDIA Corporation
+ * Copyright (c) 2011-2012, NVIDIA CORPORATION, All rights reserved.
*
* Author: Robert Morell <rmorell@nvidia.com>
*
diff --git a/drivers/video/tegra/dc/ext/tegra_dc_ext_priv.h b/drivers/video/tegra/dc/ext/tegra_dc_ext_priv.h
index 2a0c5497b7cb..f68c7d5c93c2 100644
--- a/drivers/video/tegra/dc/ext/tegra_dc_ext_priv.h
+++ b/drivers/video/tegra/dc/ext/tegra_dc_ext_priv.h
@@ -1,7 +1,7 @@
/*
* drivers/video/tegra/dc/ext/tegra_dc_ext_priv.h
*
- * Copyright (C) 2011, NVIDIA Corporation
+ * Copyright (c) 2011-2012, NVIDIA CORPORATION, All rights reserved.
*
* Author: Robert Morell <rmorell@nvidia.com>
*
diff --git a/drivers/video/tegra/dc/ext/util.c b/drivers/video/tegra/dc/ext/util.c
index cede642372f3..bd8b3c012c0e 100644
--- a/drivers/video/tegra/dc/ext/util.c
+++ b/drivers/video/tegra/dc/ext/util.c
@@ -1,7 +1,7 @@
/*
* drivers/video/tegra/dc/ext/util.c
*
- * Copyright (C) 2011, NVIDIA Corporation
+ * Copyright (c) 2011-2012, NVIDIA CORPORATION, All rights reserved.
*
* Author: Robert Morell <rmorell@nvidia.com>
*
diff --git a/drivers/video/tegra/dc/hdmi.c b/drivers/video/tegra/dc/hdmi.c
index 3cd8de5085cd..378fd8b9d8b3 100644
--- a/drivers/video/tegra/dc/hdmi.c
+++ b/drivers/video/tegra/dc/hdmi.c
@@ -4,7 +4,7 @@
* Copyright (C) 2010 Google, Inc.
* Author: Erik Gilling <konkers@android.com>
*
- * Copyright (C) 2010-2011 NVIDIA Corporation
+ * Copyright (c) 2010-2012, NVIDIA CORPORATION, All rights reserved.
*
* This software is licensed under the terms of the GNU General Public
* License version 2, as published by the Free Software Foundation, and
diff --git a/drivers/video/tegra/dc/hdmi.h b/drivers/video/tegra/dc/hdmi.h
index 702ab16e87f0..5b4c42a31ffa 100644
--- a/drivers/video/tegra/dc/hdmi.h
+++ b/drivers/video/tegra/dc/hdmi.h
@@ -6,7 +6,7 @@
* Copyright (C) 2010 Google, Inc.
* Author: Erik Gilling <konkers@android.com>
*
- * Copyright (C) 2010-2011 NVIDIA Corporation
+ * Copyright (c) 2010-2012, NVIDIA CORPORATION, All rights reserved.
*
* This software is licensed under the terms of the GNU General Public
* License version 2, as published by the Free Software Foundation, and
diff --git a/drivers/video/tegra/dc/hdmi_reg.h b/drivers/video/tegra/dc/hdmi_reg.h
index 0bdda43199e3..4a5fdcb2aaa6 100644
--- a/drivers/video/tegra/dc/hdmi_reg.h
+++ b/drivers/video/tegra/dc/hdmi_reg.h
@@ -4,6 +4,8 @@
* Copyright (C) 2010 Google, Inc.
* Author: Erik Gilling <konkers@android.com>
*
+ * Copyright (c) 2010-2012, NVIDIA CORPORATION, All rights reserved.
+ *
* This software is licensed under the terms of the GNU General Public
* License version 2, as published by the Free Software Foundation, and
* may be copied, distributed, and modified under those terms.
diff --git a/drivers/video/tegra/dc/lut.c b/drivers/video/tegra/dc/lut.c
new file mode 100644
index 000000000000..7ce8fc6768a0
--- /dev/null
+++ b/drivers/video/tegra/dc/lut.c
@@ -0,0 +1,130 @@
+/*
+ * drivers/video/tegra/dc/lut.c
+ *
+ * Copyright (c) 2010-2012, NVIDIA CORPORATION, All rights reserved.
+ *
+ * This software is licensed under the terms of the GNU General Public
+ * License version 2, as published by the Free Software Foundation, and
+ * may be copied, distributed, and modified under those terms.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ */
+
+#include <linux/err.h>
+#include <linux/types.h>
+#include <mach/dc.h>
+
+#include "dc_reg.h"
+#include "dc_priv.h"
+
+void tegra_dc_init_lut_defaults(struct tegra_dc_lut *lut)
+{
+ int i;
+ for (i = 0; i < 256; i++)
+ lut->r[i] = lut->g[i] = lut->b[i] = (u8)i;
+}
+
+static int tegra_dc_loop_lut(struct tegra_dc *dc,
+ struct tegra_dc_win *win,
+ int(*lambda)(struct tegra_dc *dc, int i, u32 rgb))
+{
+ struct tegra_dc_lut *lut = &win->lut;
+ struct tegra_dc_lut *global_lut = &dc->fb_lut;
+ int i;
+ for (i = 0; i < 256; i++) {
+
+ u32 r = (u32)lut->r[i];
+ u32 g = (u32)lut->g[i];
+ u32 b = (u32)lut->b[i];
+
+ if (!(win->ppflags & TEGRA_WIN_PPFLAG_CP_FBOVERRIDE)) {
+ r = (u32)global_lut->r[r];
+ g = (u32)global_lut->g[g];
+ b = (u32)global_lut->b[b];
+ }
+
+ if (!lambda(dc, i, r | (g<<8) | (b<<16)))
+ return 0;
+ }
+ return 1;
+}
+
+static int tegra_dc_lut_isdefaults_lambda(struct tegra_dc *dc, int i, u32 rgb)
+{
+ if (rgb != (i | (i<<8) | (i<<16)))
+ return 0;
+ return 1;
+}
+
+static int tegra_dc_set_lut_setreg_lambda(struct tegra_dc *dc, int i, u32 rgb)
+{
+ tegra_dc_writel(dc, rgb, DC_WIN_COLOR_PALETTE(i));
+ return 1;
+}
+
+void tegra_dc_set_lut(struct tegra_dc *dc, struct tegra_dc_win *win)
+{
+ unsigned long val = tegra_dc_readl(dc, DC_WIN_WIN_OPTIONS);
+
+ tegra_dc_loop_lut(dc, win, tegra_dc_set_lut_setreg_lambda);
+
+ if (win->ppflags & TEGRA_WIN_PPFLAG_CP_ENABLE)
+ val |= CP_ENABLE;
+ else
+ val &= ~CP_ENABLE;
+
+ tegra_dc_writel(dc, val, DC_WIN_WIN_OPTIONS);
+}
+
+static int tegra_dc_update_winlut(struct tegra_dc *dc, int win_idx, int fbovr)
+{
+ struct tegra_dc_win *win = &dc->windows[win_idx];
+
+ mutex_lock(&dc->lock);
+
+ if (!dc->enabled) {
+ mutex_unlock(&dc->lock);
+ return -EFAULT;
+ }
+
+ if (fbovr > 0)
+ win->ppflags |= TEGRA_WIN_PPFLAG_CP_FBOVERRIDE;
+ else if (fbovr == 0)
+ win->ppflags &= ~TEGRA_WIN_PPFLAG_CP_FBOVERRIDE;
+
+ if (!tegra_dc_loop_lut(dc, win, tegra_dc_lut_isdefaults_lambda))
+ win->ppflags |= TEGRA_WIN_PPFLAG_CP_ENABLE;
+ else
+ win->ppflags &= ~TEGRA_WIN_PPFLAG_CP_ENABLE;
+
+ tegra_dc_writel(dc, WINDOW_A_SELECT << win_idx,
+ DC_CMD_DISPLAY_WINDOW_HEADER);
+
+ tegra_dc_set_lut(dc, win);
+
+ mutex_unlock(&dc->lock);
+
+ tegra_dc_update_windows(&win, 1);
+
+ return 0;
+}
+
+int tegra_dc_update_lut(struct tegra_dc *dc, int win_idx, int fboveride)
+{
+ if (win_idx > -1)
+ return tegra_dc_update_winlut(dc, win_idx, fboveride);
+
+ for (win_idx = 0; win_idx < DC_N_WINDOWS; win_idx++) {
+ int err = tegra_dc_update_winlut(dc, win_idx, fboveride);
+ if (err)
+ return err;
+ }
+
+ return 0;
+}
+EXPORT_SYMBOL(tegra_dc_update_lut);
+
diff --git a/drivers/video/tegra/dc/mode.c b/drivers/video/tegra/dc/mode.c
new file mode 100644
index 000000000000..3359b2a4dafa
--- /dev/null
+++ b/drivers/video/tegra/dc/mode.c
@@ -0,0 +1,318 @@
+/*
+ * drivers/video/tegra/dc/mode.c
+ *
+ * Copyright (C) 2010 Google, Inc.
+ *
+ * Copyright (c) 2010-2012, NVIDIA CORPORATION, All rights reserved.
+ *
+ * This software is licensed under the terms of the GNU General Public
+ * License version 2, as published by the Free Software Foundation, and
+ * may be copied, distributed, and modified under those terms.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ */
+
+#include <linux/err.h>
+#include <linux/types.h>
+#include <linux/clk.h>
+
+#include <mach/clk.h>
+#include <mach/dc.h>
+
+#include "dc_reg.h"
+#include "dc_priv.h"
+
+/* return non-zero if constraint is violated */
+static int calc_h_ref_to_sync(const struct tegra_dc_mode *mode, int *href)
+{
+ long a, b;
+
+ /* Constraint 5: H_REF_TO_SYNC >= 0 */
+ a = 0;
+
+ /* Constraint 6: H_FRONT_PORT >= (H_REF_TO_SYNC + 1) */
+ b = mode->h_front_porch - 1;
+
+ /* Constraint 1: H_REF_TO_SYNC + H_SYNC_WIDTH + H_BACK_PORCH > 11 */
+ if (a + mode->h_sync_width + mode->h_back_porch <= 11)
+ a = 1 + 11 - mode->h_sync_width - mode->h_back_porch;
+ /* check Constraint 1 and 6 */
+ if (a > b)
+ return 1;
+
+ /* Constraint 4: H_SYNC_WIDTH >= 1 */
+ if (mode->h_sync_width < 1)
+ return 4;
+
+ /* Constraint 7: H_DISP_ACTIVE >= 16 */
+ if (mode->h_active < 16)
+ return 7;
+
+ if (href) {
+ if (b > a && a % 2)
+ *href = a + 1; /* use smallest even value */
+ else
+ *href = a; /* even or only possible value */
+ }
+
+ return 0;
+}
+
+static int calc_v_ref_to_sync(const struct tegra_dc_mode *mode, int *vref)
+{
+ long a;
+ a = 1; /* Constraint 5: V_REF_TO_SYNC >= 1 */
+
+ /* Constraint 2: V_REF_TO_SYNC + V_SYNC_WIDTH + V_BACK_PORCH > 1 */
+ if (a + mode->v_sync_width + mode->v_back_porch <= 1)
+ a = 1 + 1 - mode->v_sync_width - mode->v_back_porch;
+
+ /* Constraint 6 */
+ if (mode->v_front_porch < a + 1)
+ a = mode->v_front_porch - 1;
+
+ /* Constraint 4: V_SYNC_WIDTH >= 1 */
+ if (mode->v_sync_width < 1)
+ return 4;
+
+ /* Constraint 7: V_DISP_ACTIVE >= 16 */
+ if (mode->v_active < 16)
+ return 7;
+
+ if (vref)
+ *vref = a;
+ return 0;
+}
+
+static int calc_ref_to_sync(struct tegra_dc_mode *mode)
+{
+ int ret;
+ ret = calc_h_ref_to_sync(mode, &mode->h_ref_to_sync);
+ if (ret)
+ return ret;
+ ret = calc_v_ref_to_sync(mode, &mode->v_ref_to_sync);
+ if (ret)
+ return ret;
+
+ return 0;
+}
+
+static bool check_ref_to_sync(struct tegra_dc_mode *mode)
+{
+ /* Constraint 1: H_REF_TO_SYNC + H_SYNC_WIDTH + H_BACK_PORCH > 11. */
+ if (mode->h_ref_to_sync + mode->h_sync_width + mode->h_back_porch <= 11)
+ return false;
+
+ /* Constraint 2: V_REF_TO_SYNC + V_SYNC_WIDTH + V_BACK_PORCH > 1. */
+ if (mode->v_ref_to_sync + mode->v_sync_width + mode->v_back_porch <= 1)
+ return false;
+
+ /* Constraint 3: V_FRONT_PORCH + V_SYNC_WIDTH + V_BACK_PORCH > 1
+ * (vertical blank). */
+ if (mode->v_front_porch + mode->v_sync_width + mode->v_back_porch <= 1)
+ return false;
+
+ /* Constraint 4: V_SYNC_WIDTH >= 1; H_SYNC_WIDTH >= 1. */
+ if (mode->v_sync_width < 1 || mode->h_sync_width < 1)
+ return false;
+
+ /* Constraint 5: V_REF_TO_SYNC >= 1; H_REF_TO_SYNC >= 0. */
+ if (mode->v_ref_to_sync < 1 || mode->h_ref_to_sync < 0)
+ return false;
+
+ /* Constraint 6: V_FRONT_PORT >= (V_REF_TO_SYNC + 1);
+ * H_FRONT_PORT >= (H_REF_TO_SYNC + 1). */
+ if (mode->v_front_porch < mode->v_ref_to_sync + 1 ||
+ mode->h_front_porch < mode->h_ref_to_sync + 1)
+ return false;
+
+ /* Constraint 7: H_DISP_ACTIVE >= 16; V_DISP_ACTIVE >= 16. */
+ if (mode->h_active < 16 || mode->v_active < 16)
+ return false;
+
+ return true;
+}
+
+/* return in 1000ths of a Hertz */
+int tegra_dc_calc_refresh(const struct tegra_dc_mode *m)
+{
+ long h_total, v_total, refresh;
+ h_total = m->h_active + m->h_front_porch + m->h_back_porch +
+ m->h_sync_width;
+ v_total = m->v_active + m->v_front_porch + m->v_back_porch +
+ m->v_sync_width;
+ refresh = m->pclk / h_total;
+ refresh *= 1000;
+ refresh /= v_total;
+ return refresh;
+}
+
+#ifdef DEBUG
+static void print_mode(struct tegra_dc *dc,
+ const struct tegra_dc_mode *mode, const char *note)
+{
+ if (mode) {
+ int refresh = tegra_dc_calc_refresh(dc, mode);
+ dev_info(&dc->ndev->dev, "%s():MODE:%dx%d@%d.%03uHz pclk=%d\n",
+ note ? note : "",
+ mode->h_active, mode->v_active,
+ refresh / 1000, refresh % 1000,
+ mode->pclk);
+ }
+}
+#else /* !DEBUG */
+static inline void print_mode(struct tegra_dc *dc,
+ const struct tegra_dc_mode *mode, const char *note) { }
+#endif /* DEBUG */
+
+int tegra_dc_program_mode(struct tegra_dc *dc, struct tegra_dc_mode *mode)
+{
+ unsigned long val;
+ unsigned long rate;
+ unsigned long div;
+ unsigned long pclk;
+
+ print_mode(dc, mode, __func__);
+
+ /* use default EMC rate when switching modes */
+ dc->new_emc_clk_rate = tegra_dc_get_default_emc_clk_rate(dc);
+ tegra_dc_program_bandwidth(dc, true);
+
+ tegra_dc_writel(dc, 0x0, DC_DISP_DISP_TIMING_OPTIONS);
+ tegra_dc_writel(dc, mode->h_ref_to_sync | (mode->v_ref_to_sync << 16),
+ DC_DISP_REF_TO_SYNC);
+ tegra_dc_writel(dc, mode->h_sync_width | (mode->v_sync_width << 16),
+ DC_DISP_SYNC_WIDTH);
+ tegra_dc_writel(dc, mode->h_back_porch | (mode->v_back_porch << 16),
+ DC_DISP_BACK_PORCH);
+ tegra_dc_writel(dc, mode->h_active | (mode->v_active << 16),
+ DC_DISP_DISP_ACTIVE);
+ tegra_dc_writel(dc, mode->h_front_porch | (mode->v_front_porch << 16),
+ DC_DISP_FRONT_PORCH);
+
+ tegra_dc_writel(dc, DE_SELECT_ACTIVE | DE_CONTROL_NORMAL,
+ DC_DISP_DATA_ENABLE_OPTIONS);
+
+ /* TODO: MIPI/CRT/HDMI clock cals */
+
+ val = DISP_DATA_FORMAT_DF1P1C;
+
+ if (dc->out->align == TEGRA_DC_ALIGN_MSB)
+ val |= DISP_DATA_ALIGNMENT_MSB;
+ else
+ val |= DISP_DATA_ALIGNMENT_LSB;
+
+ if (dc->out->order == TEGRA_DC_ORDER_RED_BLUE)
+ val |= DISP_DATA_ORDER_RED_BLUE;
+ else
+ val |= DISP_DATA_ORDER_BLUE_RED;
+
+ tegra_dc_writel(dc, val, DC_DISP_DISP_INTERFACE_CONTROL);
+
+ rate = tegra_dc_clk_get_rate(dc);
+
+ pclk = tegra_dc_pclk_round_rate(dc, mode->pclk);
+ trace_printk("%s:pclk=%ld\n", dc->ndev->name, pclk);
+ if (pclk < (mode->pclk / 100 * 99) ||
+ pclk > (mode->pclk / 100 * 109)) {
+ dev_err(&dc->ndev->dev,
+ "can't divide %ld clock to %d -1/+9%% %ld %d %d\n",
+ rate, mode->pclk,
+ pclk, (mode->pclk / 100 * 99),
+ (mode->pclk / 100 * 109));
+ return -EINVAL;
+ }
+
+ div = (rate * 2 / pclk) - 2;
+ trace_printk("%s:div=%ld\n", dc->ndev->name, div);
+
+ tegra_dc_writel(dc, 0x00010001,
+ DC_DISP_SHIFT_CLOCK_OPTIONS);
+ tegra_dc_writel(dc, PIXEL_CLK_DIVIDER_PCD1 | SHIFT_CLK_DIVIDER(div),
+ DC_DISP_DISP_CLOCK_CONTROL);
+
+#ifdef CONFIG_SWITCH
+ switch_set_state(&dc->modeset_switch,
+ (mode->h_active << 16) | mode->v_active);
+#endif
+
+ tegra_dc_writel(dc, GENERAL_UPDATE, DC_CMD_STATE_CONTROL);
+ tegra_dc_writel(dc, GENERAL_ACT_REQ, DC_CMD_STATE_CONTROL);
+
+ print_mode_info(dc, dc->mode);
+ return 0;
+}
+
+int tegra_dc_set_mode(struct tegra_dc *dc, const struct tegra_dc_mode *mode)
+{
+ memcpy(&dc->mode, mode, sizeof(dc->mode));
+
+ print_mode(dc, mode, __func__);
+
+ return 0;
+}
+EXPORT_SYMBOL(tegra_dc_set_mode);
+
+int tegra_dc_set_fb_mode(struct tegra_dc *dc,
+ const struct fb_videomode *fbmode, bool stereo_mode)
+{
+ struct tegra_dc_mode mode;
+
+ if (!fbmode->pixclock)
+ return -EINVAL;
+
+ mode.pclk = PICOS2KHZ(fbmode->pixclock) * 1000;
+ mode.h_sync_width = fbmode->hsync_len;
+ mode.v_sync_width = fbmode->vsync_len;
+ mode.h_back_porch = fbmode->left_margin;
+ mode.v_back_porch = fbmode->upper_margin;
+ mode.h_active = fbmode->xres;
+ mode.v_active = fbmode->yres;
+ mode.h_front_porch = fbmode->right_margin;
+ mode.v_front_porch = fbmode->lower_margin;
+ mode.stereo_mode = stereo_mode;
+ if (dc->out->type == TEGRA_DC_OUT_HDMI) {
+ /* HDMI controller requires h_ref=1, v_ref=1 */
+ mode.h_ref_to_sync = 1;
+ mode.v_ref_to_sync = 1;
+ } else {
+ calc_ref_to_sync(&mode);
+ }
+ if (!check_ref_to_sync(&mode)) {
+ dev_err(&dc->ndev->dev,
+ "Display timing doesn't meet restrictions.\n");
+ return -EINVAL;
+ }
+ dev_info(&dc->ndev->dev, "Using mode %dx%d pclk=%d href=%d vref=%d\n",
+ mode.h_active, mode.v_active, mode.pclk,
+ mode.h_ref_to_sync, mode.v_ref_to_sync
+ );
+
+#ifndef CONFIG_TEGRA_HDMI_74MHZ_LIMIT
+ /* Double the pixel clock and update v_active only for
+ * frame packed mode */
+ if (mode.stereo_mode) {
+ mode.pclk *= 2;
+ /* total v_active = yres*2 + activespace */
+ mode.v_active = fbmode->yres * 2 +
+ fbmode->vsync_len +
+ fbmode->upper_margin +
+ fbmode->lower_margin;
+ }
+#endif
+
+ mode.flags = 0;
+
+ if (!(fbmode->sync & FB_SYNC_HOR_HIGH_ACT))
+ mode.flags |= TEGRA_DC_MODE_FLAG_NEG_H_SYNC;
+
+ if (!(fbmode->sync & FB_SYNC_VERT_HIGH_ACT))
+ mode.flags |= TEGRA_DC_MODE_FLAG_NEG_V_SYNC;
+
+ return tegra_dc_set_mode(dc, &mode);
+}
+EXPORT_SYMBOL(tegra_dc_set_fb_mode);
diff --git a/drivers/video/tegra/dc/nvhdcp.c b/drivers/video/tegra/dc/nvhdcp.c
index 263de07a3da0..3566e2bd33b5 100644
--- a/drivers/video/tegra/dc/nvhdcp.c
+++ b/drivers/video/tegra/dc/nvhdcp.c
@@ -1,7 +1,7 @@
/*
* drivers/video/tegra/dc/nvhdcp.c
*
- * Copyright (c) 2010-2011, NVIDIA Corporation.
+ * Copyright (c) 2010-2012, NVIDIA CORPORATION, All rights reserved.
*
* This software is licensed under the terms of the GNU General Public
* License version 2, as published by the Free Software Foundation, and
diff --git a/drivers/video/tegra/dc/nvhdcp.h b/drivers/video/tegra/dc/nvhdcp.h
index 90ea0be36d19..ce4c7f806745 100644
--- a/drivers/video/tegra/dc/nvhdcp.h
+++ b/drivers/video/tegra/dc/nvhdcp.h
@@ -1,7 +1,7 @@
/*
* drivers/video/tegra/dc/nvhdcp.h
*
- * Copyright (c) 2010-2011, NVIDIA Corporation.
+ * Copyright (c) 2010-2012, NVIDIA CORPORATION, All rights reserved.
*
* This software is licensed under the terms of the GNU General Public
* License version 2, as published by the Free Software Foundation, and
diff --git a/drivers/video/tegra/dc/nvsd.c b/drivers/video/tegra/dc/nvsd.c
index 860dd8dab1fd..e3058b596f69 100644
--- a/drivers/video/tegra/dc/nvsd.c
+++ b/drivers/video/tegra/dc/nvsd.c
@@ -1,7 +1,7 @@
/*
* drivers/video/tegra/dc/nvsd.c
*
- * Copyright (c) 2010-2012, NVIDIA Corporation.
+ * Copyright (c) 2010-2012, NVIDIA CORPORATION, All rights reserved.
*
* This software is licensed under the terms of the GNU General Public
* License version 2, as published by the Free Software Foundation, and
diff --git a/drivers/video/tegra/dc/nvsd.h b/drivers/video/tegra/dc/nvsd.h
index f7fc4a1ead6e..d6f9dc148320 100644
--- a/drivers/video/tegra/dc/nvsd.h
+++ b/drivers/video/tegra/dc/nvsd.h
@@ -1,7 +1,7 @@
/*
* drivers/video/tegra/dc/nvsd.h
*
- * Copyright (c) 2010-2011, NVIDIA Corporation.
+ * Copyright (c) 2010-2012, NVIDIA CORPORATION, All rights reserved.
*
* This software is licensed under the terms of the GNU General Public
* License version 2, as published by the Free Software Foundation, and
diff --git a/drivers/video/tegra/dc/rgb.c b/drivers/video/tegra/dc/rgb.c
index 47d4e69cab2e..b4097d98a9ba 100644
--- a/drivers/video/tegra/dc/rgb.c
+++ b/drivers/video/tegra/dc/rgb.c
@@ -4,6 +4,8 @@
* Copyright (C) 2010 Google, Inc.
* Author: Erik Gilling <konkers@android.com>
*
+ * Copyright (c) 2010-2012, NVIDIA CORPORATION, All rights reserved.
+ *
* This software is licensed under the terms of the GNU General Public
* License version 2, as published by the Free Software Foundation, and
* may be copied, distributed, and modified under those terms.
diff --git a/drivers/video/tegra/dc/window.c b/drivers/video/tegra/dc/window.c
new file mode 100644
index 000000000000..5161dd4f7003
--- /dev/null
+++ b/drivers/video/tegra/dc/window.c
@@ -0,0 +1,466 @@
+/*
+ * drivers/video/tegra/dc/window.c
+ *
+ * Copyright (C) 2010 Google, Inc.
+ *
+ * Copyright (c) 2010-2012, NVIDIA CORPORATION, All rights reserved.
+ *
+ * This software is licensed under the terms of the GNU General Public
+ * License version 2, as published by the Free Software Foundation, and
+ * may be copied, distributed, and modified under those terms.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ */
+#include <linux/err.h>
+#include <linux/types.h>
+#include <mach/dc.h>
+
+#include "dc_reg.h"
+#include "dc_config.h"
+#include "dc_priv.h"
+
+static int no_vsync;
+
+module_param_named(no_vsync, no_vsync, int, S_IRUGO | S_IWUSR);
+
+static bool tegra_dc_windows_are_clean(struct tegra_dc_win *windows[],
+ int n)
+{
+ int i;
+
+ for (i = 0; i < n; i++) {
+ if (windows[i]->dirty)
+ return false;
+ }
+
+ return true;
+}
+
+static int get_topmost_window(u32 *depths, unsigned long *wins)
+{
+ int idx, best = -1;
+
+ for_each_set_bit(idx, wins, DC_N_WINDOWS) {
+ if (best == -1 || depths[idx] < depths[best])
+ best = idx;
+ }
+ clear_bit(best, wins);
+ return best;
+}
+
+static u32 blend_topwin(u32 flags)
+{
+ if (flags & TEGRA_WIN_FLAG_BLEND_COVERAGE)
+ return BLEND(NOKEY, ALPHA, 0xff, 0xff);
+ else if (flags & TEGRA_WIN_FLAG_BLEND_PREMULT)
+ return BLEND(NOKEY, PREMULT, 0xff, 0xff);
+ else
+ return BLEND(NOKEY, FIX, 0xff, 0xff);
+}
+
+static u32 blend_2win(int idx, unsigned long behind_mask, u32* flags, int xy)
+{
+ int other;
+
+ for (other = 0; other < DC_N_WINDOWS; other++) {
+ if (other != idx && (xy-- == 0))
+ break;
+ }
+ if (BIT(other) & behind_mask)
+ return blend_topwin(flags[idx]);
+ else if (flags[other])
+ return BLEND(NOKEY, DEPENDANT, 0x00, 0x00);
+ else
+ return BLEND(NOKEY, FIX, 0x00, 0x00);
+}
+
+static u32 blend_3win(int idx, unsigned long behind_mask, u32* flags)
+{
+ unsigned long infront_mask;
+ int first;
+
+ infront_mask = ~(behind_mask | BIT(idx));
+ infront_mask &= (BIT(DC_N_WINDOWS) - 1);
+ first = ffs(infront_mask) - 1;
+
+ if (!infront_mask)
+ return blend_topwin(flags[idx]);
+ else if (behind_mask && first != -1 && flags[first])
+ return BLEND(NOKEY, DEPENDANT, 0x00, 0x00);
+ else
+ return BLEND(NOKEY, FIX, 0x0, 0x0);
+}
+
+static void tegra_dc_set_blending(struct tegra_dc *dc,
+ struct tegra_dc_blend *blend)
+{
+ unsigned long mask = BIT(DC_N_WINDOWS) - 1;
+
+ while (mask) {
+ int idx = get_topmost_window(blend->z, &mask);
+
+ tegra_dc_writel(dc, WINDOW_A_SELECT << idx,
+ DC_CMD_DISPLAY_WINDOW_HEADER);
+ tegra_dc_writel(dc, BLEND(NOKEY, FIX, 0xff, 0xff),
+ DC_WIN_BLEND_NOKEY);
+ tegra_dc_writel(dc, BLEND(NOKEY, FIX, 0xff, 0xff),
+ DC_WIN_BLEND_1WIN);
+ tegra_dc_writel(dc, blend_2win(idx, mask, blend->flags, 0),
+ DC_WIN_BLEND_2WIN_X);
+ tegra_dc_writel(dc, blend_2win(idx, mask, blend->flags, 1),
+ DC_WIN_BLEND_2WIN_Y);
+ tegra_dc_writel(dc, blend_3win(idx, mask, blend->flags),
+ DC_WIN_BLEND_3WIN_XY);
+ }
+}
+
+/* does not support syncing windows on multiple dcs in one call */
+int tegra_dc_sync_windows(struct tegra_dc_win *windows[], int n)
+{
+ int ret;
+ if (n < 1 || n > DC_N_WINDOWS)
+ return -EINVAL;
+
+ if (!windows[0]->dc->enabled)
+ return -EFAULT;
+
+#ifdef CONFIG_TEGRA_SIMULATION_PLATFORM
+ /* Don't want to timeout on simulator */
+ ret = wait_event_interruptible(windows[0]->dc->wq,
+ tegra_dc_windows_are_clean(windows, n));
+#else
+ trace_printk("%s:Before wait_event_interruptible_timeout\n",
+ windows[0]->dc->ndev->name);
+ ret = wait_event_interruptible_timeout(windows[0]->dc->wq,
+ tegra_dc_windows_are_clean(windows, n),
+ HZ);
+ trace_printk("%s:After wait_event_interruptible_timeout\n",
+ windows[0]->dc->ndev->name);
+#endif
+ return ret;
+}
+EXPORT_SYMBOL(tegra_dc_sync_windows);
+
+static inline u32 compute_dda_inc(fixed20_12 in, unsigned out_int,
+ bool v, unsigned Bpp)
+{
+ /*
+ * min(round((prescaled_size_in_pixels - 1) * 0x1000 /
+ * (post_scaled_size_in_pixels - 1)), MAX)
+ * Where the value of MAX is as follows:
+ * For V_DDA_INCREMENT: 15.0 (0xF000)
+ * For H_DDA_INCREMENT: 4.0 (0x4000) for 4 Bytes/pix formats.
+ * 8.0 (0x8000) for 2 Bytes/pix formats.
+ */
+
+ fixed20_12 out = dfixed_init(out_int);
+ u32 dda_inc;
+ int max;
+
+ if (v) {
+ max = 15;
+ } else {
+ switch (Bpp) {
+ default:
+ WARN_ON_ONCE(1);
+ /* fallthrough */
+ case 4:
+ max = 4;
+ break;
+ case 2:
+ max = 8;
+ break;
+ }
+ }
+
+ out.full = max_t(u32, out.full - dfixed_const(1), dfixed_const(1));
+ in.full -= dfixed_const(1);
+
+ dda_inc = dfixed_div(in, out);
+
+ dda_inc = min_t(u32, dda_inc, dfixed_const(max));
+
+ return dda_inc;
+}
+
+static inline u32 compute_initial_dda(fixed20_12 in)
+{
+ return dfixed_frac(in);
+}
+
+/* does not support updating windows on multiple dcs in one call */
+int tegra_dc_update_windows(struct tegra_dc_win *windows[], int n)
+{
+ struct tegra_dc *dc;
+ unsigned long update_mask = GENERAL_ACT_REQ;
+ unsigned long val;
+ bool update_blend = false;
+ int i;
+
+ dc = windows[0]->dc;
+
+ if (dc->out->flags & TEGRA_DC_OUT_ONE_SHOT_MODE) {
+ /* Acquire one_shot_lock to avoid race condition between
+ * cancellation of old delayed work and schedule of new
+ * delayed work. */
+ mutex_lock(&dc->one_shot_lock);
+ cancel_delayed_work_sync(&dc->one_shot_work);
+ }
+ mutex_lock(&dc->lock);
+
+ if (!dc->enabled) {
+ mutex_unlock(&dc->lock);
+ if (dc->out->flags & TEGRA_DC_OUT_ONE_SHOT_MODE)
+ mutex_unlock(&dc->one_shot_lock);
+ return -EFAULT;
+ }
+
+ if (dc->out->flags & TEGRA_DC_OUT_ONE_SHOT_LP_MODE)
+ tegra_dc_host_resume(dc);
+
+ if (no_vsync)
+ tegra_dc_writel(dc, WRITE_MUX_ACTIVE | READ_MUX_ACTIVE,
+ DC_CMD_STATE_ACCESS);
+ else
+ tegra_dc_writel(dc, WRITE_MUX_ASSEMBLY | READ_MUX_ASSEMBLY,
+ DC_CMD_STATE_ACCESS);
+
+ for (i = 0; i < n; i++) {
+ struct tegra_dc_win *win = windows[i];
+ unsigned h_dda;
+ unsigned v_dda;
+ fixed20_12 h_offset, v_offset;
+ bool invert_h = (win->flags & TEGRA_WIN_FLAG_INVERT_H) != 0;
+ bool invert_v = (win->flags & TEGRA_WIN_FLAG_INVERT_V) != 0;
+ bool yuv = tegra_dc_is_yuv(win->fmt);
+ bool yuvp = tegra_dc_is_yuv_planar(win->fmt);
+ unsigned Bpp = tegra_dc_fmt_bpp(win->fmt) / 8;
+ /* Bytes per pixel of bandwidth, used for dda_inc calculation */
+ unsigned Bpp_bw = Bpp * (yuvp ? 2 : 1);
+ const bool filter_h = win_use_h_filter(dc, win);
+ const bool filter_v = win_use_v_filter(dc, win);
+
+ if (win->z != dc->blend.z[win->idx]) {
+ dc->blend.z[win->idx] = win->z;
+ update_blend = true;
+ }
+ if ((win->flags & TEGRA_WIN_BLEND_FLAGS_MASK) !=
+ dc->blend.flags[win->idx]) {
+ dc->blend.flags[win->idx] =
+ win->flags & TEGRA_WIN_BLEND_FLAGS_MASK;
+ update_blend = true;
+ }
+
+ tegra_dc_writel(dc, WINDOW_A_SELECT << win->idx,
+ DC_CMD_DISPLAY_WINDOW_HEADER);
+
+ if (!no_vsync)
+ update_mask |= WIN_A_ACT_REQ << win->idx;
+
+ if (!WIN_IS_ENABLED(win)) {
+ dc->windows[i].dirty = 1;
+ tegra_dc_writel(dc, 0, DC_WIN_WIN_OPTIONS);
+ continue;
+ }
+
+ tegra_dc_writel(dc, win->fmt & 0x1f, DC_WIN_COLOR_DEPTH);
+ tegra_dc_writel(dc, win->fmt >> 6, DC_WIN_BYTE_SWAP);
+
+ tegra_dc_writel(dc,
+ V_POSITION(win->out_y) | H_POSITION(win->out_x),
+ DC_WIN_POSITION);
+ tegra_dc_writel(dc,
+ V_SIZE(win->out_h) | H_SIZE(win->out_w),
+ DC_WIN_SIZE);
+
+ if (tegra_dc_feature_has_scaling(dc, win->idx)) {
+ tegra_dc_writel(dc,
+ V_PRESCALED_SIZE(dfixed_trunc(win->h)) |
+ H_PRESCALED_SIZE(dfixed_trunc(win->w) * Bpp),
+ DC_WIN_PRESCALED_SIZE);
+
+ h_dda = compute_dda_inc(win->w, win->out_w, false,
+ Bpp_bw);
+ v_dda = compute_dda_inc(win->h, win->out_h, true,
+ Bpp_bw);
+ tegra_dc_writel(dc, V_DDA_INC(v_dda) |
+ H_DDA_INC(h_dda), DC_WIN_DDA_INCREMENT);
+ h_dda = compute_initial_dda(win->x);
+ v_dda = compute_initial_dda(win->y);
+ tegra_dc_writel(dc, h_dda, DC_WIN_H_INITIAL_DDA);
+ tegra_dc_writel(dc, v_dda, DC_WIN_V_INITIAL_DDA);
+ }
+
+ tegra_dc_writel(dc, 0, DC_WIN_BUF_STRIDE);
+ tegra_dc_writel(dc, 0, DC_WIN_UV_BUF_STRIDE);
+ tegra_dc_writel(dc, (unsigned long)win->phys_addr,
+ DC_WINBUF_START_ADDR);
+
+ if (!yuvp) {
+ tegra_dc_writel(dc, win->stride, DC_WIN_LINE_STRIDE);
+ } else {
+ tegra_dc_writel(dc,
+ (unsigned long)win->phys_addr_u,
+ DC_WINBUF_START_ADDR_U);
+ tegra_dc_writel(dc,
+ (unsigned long)win->phys_addr_v,
+ DC_WINBUF_START_ADDR_V);
+ tegra_dc_writel(dc,
+ LINE_STRIDE(win->stride) |
+ UV_LINE_STRIDE(win->stride_uv),
+ DC_WIN_LINE_STRIDE);
+ }
+
+ h_offset = win->x;
+ if (invert_h) {
+ h_offset.full += win->w.full - dfixed_const(1);
+ }
+
+ v_offset = win->y;
+ if (invert_v) {
+ v_offset.full += win->h.full - dfixed_const(1);
+ }
+
+ tegra_dc_writel(dc, dfixed_trunc(h_offset) * Bpp,
+ DC_WINBUF_ADDR_H_OFFSET);
+ tegra_dc_writel(dc, dfixed_trunc(v_offset),
+ DC_WINBUF_ADDR_V_OFFSET);
+
+ if (tegra_dc_feature_has_tiling(dc, win->idx)) {
+ if (WIN_IS_TILED(win))
+ tegra_dc_writel(dc,
+ DC_WIN_BUFFER_ADDR_MODE_TILE |
+ DC_WIN_BUFFER_ADDR_MODE_TILE_UV,
+ DC_WIN_BUFFER_ADDR_MODE);
+ else
+ tegra_dc_writel(dc,
+ DC_WIN_BUFFER_ADDR_MODE_LINEAR |
+ DC_WIN_BUFFER_ADDR_MODE_LINEAR_UV,
+ DC_WIN_BUFFER_ADDR_MODE);
+ }
+
+ val = WIN_ENABLE;
+ if (yuv)
+ val |= CSC_ENABLE;
+ else if (tegra_dc_fmt_bpp(win->fmt) < 24)
+ val |= COLOR_EXPAND;
+
+ if (win->ppflags & TEGRA_WIN_PPFLAG_CP_ENABLE)
+ val |= CP_ENABLE;
+
+ if (filter_h)
+ val |= H_FILTER_ENABLE;
+ if (filter_v)
+ val |= V_FILTER_ENABLE;
+
+ if (invert_h)
+ val |= H_DIRECTION_DECREMENT;
+ if (invert_v)
+ val |= V_DIRECTION_DECREMENT;
+
+ tegra_dc_writel(dc, val, DC_WIN_WIN_OPTIONS);
+
+#ifdef CONFIG_ARCH_TEGRA_3x_SOC
+ if (win->global_alpha == 255)
+ tegra_dc_writel(dc, 0, DC_WIN_GLOBAL_ALPHA);
+ else
+ tegra_dc_writel(dc, GLOBAL_ALPHA_ENABLE |
+ win->global_alpha, DC_WIN_GLOBAL_ALPHA);
+#endif
+
+ win->dirty = no_vsync ? 0 : 1;
+
+ dev_dbg(&dc->ndev->dev, "%s():idx=%d z=%d x=%d y=%d w=%d h=%d "
+ "out_x=%u out_y=%u out_w=%u out_h=%u "
+ "fmt=%d yuvp=%d Bpp=%u filter_h=%d filter_v=%d",
+ __func__, win->idx, win->z,
+ dfixed_trunc(win->x), dfixed_trunc(win->y),
+ dfixed_trunc(win->w), dfixed_trunc(win->h),
+ win->out_x, win->out_y, win->out_w, win->out_h,
+ win->fmt, yuvp, Bpp, filter_h, filter_v);
+ trace_printk("%s:win%u in:%ux%u out:%ux%u fmt=%d\n",
+ dc->ndev->name, win->idx, dfixed_trunc(win->w),
+ dfixed_trunc(win->h), win->out_w, win->out_h, win->fmt);
+ }
+
+ if (update_blend) {
+ tegra_dc_set_blending(dc, &dc->blend);
+ for (i = 0; i < DC_N_WINDOWS; i++) {
+ if (!no_vsync)
+ dc->windows[i].dirty = 1;
+ update_mask |= WIN_A_ACT_REQ << i;
+ }
+ }
+
+ tegra_dc_set_dynamic_emc(windows, n);
+
+ tegra_dc_writel(dc, update_mask << 8, DC_CMD_STATE_CONTROL);
+
+ tegra_dc_writel(dc, FRAME_END_INT | V_BLANK_INT, DC_CMD_INT_STATUS);
+ if (!no_vsync) {
+ set_bit(V_BLANK_FLIP, &dc->vblank_ref_count);
+ tegra_dc_unmask_interrupt(dc,
+ FRAME_END_INT | V_BLANK_INT | ALL_UF_INT);
+ } else {
+ clear_bit(V_BLANK_FLIP, &dc->vblank_ref_count);
+ tegra_dc_mask_interrupt(dc,
+ FRAME_END_INT | V_BLANK_INT | ALL_UF_INT);
+ }
+
+ if (dc->out->flags & TEGRA_DC_OUT_ONE_SHOT_MODE)
+ schedule_delayed_work(&dc->one_shot_work,
+ msecs_to_jiffies(dc->one_shot_delay_ms));
+
+ /* update EMC clock if calculated bandwidth has changed */
+ tegra_dc_program_bandwidth(dc, false);
+
+ if (dc->out->flags & TEGRA_DC_OUT_ONE_SHOT_MODE)
+ update_mask |= NC_HOST_TRIG;
+
+ tegra_dc_writel(dc, update_mask, DC_CMD_STATE_CONTROL);
+ trace_printk("%s:update_mask=%#lx\n", dc->ndev->name, update_mask);
+
+ mutex_unlock(&dc->lock);
+ if (dc->out->flags & TEGRA_DC_OUT_ONE_SHOT_MODE)
+ mutex_unlock(&dc->one_shot_lock);
+
+ return 0;
+}
+EXPORT_SYMBOL(tegra_dc_update_windows);
+
+void tegra_dc_trigger_windows(struct tegra_dc *dc)
+{
+ u32 val, i;
+ u32 completed = 0;
+ u32 dirty = 0;
+
+ val = tegra_dc_readl(dc, DC_CMD_STATE_CONTROL);
+ for (i = 0; i < DC_N_WINDOWS; i++) {
+#ifdef CONFIG_TEGRA_SIMULATION_PLATFORM
+ /* FIXME: this is not needed when the simulator
+ clears WIN_x_UPDATE bits as in HW */
+ dc->windows[i].dirty = 0;
+ completed = 1;
+#else
+ if (!(val & (WIN_A_ACT_REQ << i))) {
+ dc->windows[i].dirty = 0;
+ completed = 1;
+ } else {
+ dirty = 1;
+ }
+#endif
+ }
+
+ if (!dirty) {
+ if (!(dc->out->flags & TEGRA_DC_OUT_ONE_SHOT_MODE))
+ tegra_dc_mask_interrupt(dc, FRAME_END_INT);
+ }
+
+ if (completed)
+ wake_up(&dc->wq);
+}
+
diff --git a/drivers/video/tegra/fb.c b/drivers/video/tegra/fb.c
index 1193a2eb8c52..9c5c06d34938 100644
--- a/drivers/video/tegra/fb.c
+++ b/drivers/video/tegra/fb.c
@@ -6,7 +6,7 @@
* Colin Cross <ccross@android.com>
* Travis Geiselbrecht <travis@palm.com>
*
- * Copyright (C) 2010-2011 NVIDIA Corporation
+ * Copyright (c) 2010-2012, NVIDIA CORPORATION, All rights reserved.
*
* This software is licensed under the terms of the GNU General Public
* License version 2, as published by the Free Software Foundation, and