summaryrefslogtreecommitdiff
path: root/drivers/video/tegra/dc
diff options
context:
space:
mode:
authorDavid Schalig <dschalig@nvidia.com>2011-10-25 19:28:24 +0900
committerDan Willemsen <dwillemsen@nvidia.com>2011-11-30 21:49:35 -0800
commitf80e81610f4e2e3a9051b465a9176ac70f6913f1 (patch)
tree87e9e17de05b511dc97b6c1c9a0fb3b92ee69732 /drivers/video/tegra/dc
parentc48cfa76bc9c61ae99b663519075283bd8e290c1 (diff)
video: tegra: dc: support global fbdev gamma table
Add support to set a global gamma correction table via fbdev cmap API. The 3 Tegra DC windows have their own local gamma tables, which can either override or alter the global table. Bug 868060 Change-Id: I0be1c5e4afa8fd8c010b772c7808c883c0848ab4 Reviewed-on: http://git-master/r/60201 Reviewed-by: Varun Colbert <vcolbert@nvidia.com> Tested-by: Varun Colbert <vcolbert@nvidia.com> Rebase-Id: R7e613b1c8ac469242172bd81db9dfba25176e0c3
Diffstat (limited to 'drivers/video/tegra/dc')
-rw-r--r--drivers/video/tegra/dc/dc.c80
-rw-r--r--drivers/video/tegra/dc/dc_priv.h1
2 files changed, 59 insertions, 22 deletions
diff --git a/drivers/video/tegra/dc/dc.c b/drivers/video/tegra/dc/dc.c
index b1c4413..4f8da4e 100644
--- a/drivers/video/tegra/dc/dc.c
+++ b/drivers/video/tegra/dc/dc.c
@@ -672,29 +672,49 @@ static void tegra_dc_init_lut_defaults(struct tegra_dc_lut *lut)
lut->r[i] = lut->g[i] = lut->b[i] = (u8)i;
}
-static int tegra_dc_lut_is_defaults(struct tegra_dc_lut *lut)
+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))
{
- unsigned int i;
- for (i = 0; i < 256; i++)
- if ((lut->r[i] != i) || (lut->g[i] != i) || (lut->b[i] != i))
+ 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 void tegra_dc_set_lut(struct tegra_dc *dc, struct tegra_dc_win* win)
+static int tegra_dc_lut_isdefaults_lambda(struct tegra_dc *dc, int i, u32 rgb)
{
- unsigned int i;
- unsigned long val;
- struct tegra_dc_lut *lut = &win->lut;
+ if (rgb != (i | (i<<8) | (i<<16)))
+ return 0;
+ return 1;
+}
- for (i = 0; i < 256; i++) {
- u32 rgb = ((u32)lut->r[i]) |
- ((u32)lut->g[i]<<8) |
- ((u32)lut->b[i]<<16);
- tegra_dc_writel(dc, rgb, DC_WIN_COLOR_PALETTE(i));
- }
+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);
- 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;
@@ -704,7 +724,7 @@ static void tegra_dc_set_lut(struct tegra_dc *dc, struct tegra_dc_win* win)
tegra_dc_writel(dc, val, DC_WIN_WIN_OPTIONS);
}
-int tegra_dc_update_lut(struct tegra_dc *dc, int win_idx, int fboveride)
+static int tegra_dc_update_winlut(struct tegra_dc *dc, int win_idx, int fbovr)
{
struct tegra_dc_win *win = &dc->windows[win_idx];
@@ -715,16 +735,16 @@ int tegra_dc_update_lut(struct tegra_dc *dc, int win_idx, int fboveride)
return -EFAULT;
}
- if (!tegra_dc_lut_is_defaults(&win->lut))
+ 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;
- if (fboveride)
- win->ppflags |= TEGRA_WIN_PPFLAG_CP_FBOVERRIDE;
- else
- win->ppflags &= ~TEGRA_WIN_PPFLAG_CP_FBOVERRIDE;
-
tegra_dc_writel(dc, WINDOW_A_SELECT << win_idx,
DC_CMD_DISPLAY_WINDOW_HEADER);
@@ -734,6 +754,20 @@ int tegra_dc_update_lut(struct tegra_dc *dc, int win_idx, int fboveride)
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)
@@ -2656,6 +2690,8 @@ static int tegra_dc_probe(struct nvhost_device *ndev)
#endif
INIT_WORK(&dc->vblank_work, tegra_dc_vblank);
+ tegra_dc_init_lut_defaults(&dc->fb_lut);
+
dc->n_windows = DC_N_WINDOWS;
for (i = 0; i < dc->n_windows; i++) {
struct tegra_dc_win *win = &dc->windows[i];
diff --git a/drivers/video/tegra/dc/dc_priv.h b/drivers/video/tegra/dc/dc_priv.h
index 5eaa8be..83f26b8 100644
--- a/drivers/video/tegra/dc/dc_priv.h
+++ b/drivers/video/tegra/dc/dc_priv.h
@@ -132,6 +132,7 @@ struct tegra_dc {
#ifdef CONFIG_DEBUG_FS
struct dentry *debugdir;
#endif
+ struct tegra_dc_lut fb_lut;
};
static inline void tegra_dc_io_start(struct tegra_dc *dc)