summaryrefslogtreecommitdiff
path: root/drivers/video/tegra/dc/lut.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/video/tegra/dc/lut.c')
-rw-r--r--drivers/video/tegra/dc/lut.c130
1 files changed, 130 insertions, 0 deletions
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);
+