summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDavid Schalig <dschalig@nvidia.com>2011-10-13 12:50:14 +0900
committerDan Willemsen <dwillemsen@nvidia.com>2011-11-30 21:49:23 -0800
commitf064889bba674399ee981762a5ed9ef10c667a60 (patch)
treed6dea9eeedfac4e1c10d107e9f58dcb1df87ee58
parent601e1d16240cbe24c6d4fa72c6afacfbde13022e (diff)
video: tegra: dc: ioctl for setting gamma lut
- enable gamma look-up hardware only when needed to save power - add flags field to ioctl TEGRA_DC_EXT_SET_LUT for forward compatibility Bug 868060 Change-Id: I690f8b8856e0b1acd6215907ca8bd78ecaf30b17 Reviewed-on: http://git-master/r/57736 Reviewed-by: David Schalig <dschalig@nvidia.com> Tested-by: David Schalig <dschalig@nvidia.com> Reviewed-by: Jon Mayo <jmayo@nvidia.com> Reviewed-by: Robert Morell <rmorell@nvidia.com> Rebase-Id: Rf6081a9372ba7d6e53a66b9b58a50a62ad409d9a
-rw-r--r--arch/arm/mach-tegra/include/mach/dc.h6
-rw-r--r--drivers/video/tegra/dc/dc.c63
-rw-r--r--drivers/video/tegra/dc/ext/dev.c16
-rw-r--r--include/video/tegra_dc_ext.h11
4 files changed, 71 insertions, 25 deletions
diff --git a/arch/arm/mach-tegra/include/mach/dc.h b/arch/arm/mach-tegra/include/mach/dc.h
index 72d6750d24e7..600df748fc56 100644
--- a/arch/arm/mach-tegra/include/mach/dc.h
+++ b/arch/arm/mach-tegra/include/mach/dc.h
@@ -374,6 +374,7 @@ struct tegra_dc_lut {
struct tegra_dc_win {
u8 idx;
u8 fmt;
+ u8 ppflags; /* see TEGRA_WIN_PPFLAG* */
u32 flags;
void *virt_addr;
@@ -404,6 +405,8 @@ struct tegra_dc_win {
struct tegra_dc_lut lut;
};
+#define TEGRA_WIN_PPFLAG_CP_ENABLE (1 << 0) /* enable RGB color lut */
+#define TEGRA_WIN_PPFLAG_CP_FBOVERRIDE (1 << 1) /* override fbdev color lut */
#define TEGRA_WIN_FLAG_ENABLED (1 << 0)
#define TEGRA_WIN_FLAG_BLEND_PREMULT (1 << 1)
@@ -414,6 +417,7 @@ struct tegra_dc_win {
#define TEGRA_WIN_FLAG_H_FILTER (1 << 6)
#define TEGRA_WIN_FLAG_V_FILTER (1 << 7)
+
#define TEGRA_WIN_BLEND_FLAGS_MASK \
(TEGRA_WIN_FLAG_BLEND_PREMULT | TEGRA_WIN_FLAG_BLEND_COVERAGE)
@@ -510,7 +514,7 @@ void tegra_dc_config_pwm(struct tegra_dc *dc, struct tegra_dc_pwm_params *cfg);
int tegra_dc_update_csc(struct tegra_dc *dc, int win_index);
-int tegra_dc_update_lut(struct tegra_dc *dc, int win_index, int start, int len);
+int tegra_dc_update_lut(struct tegra_dc *dc, int win_index, int fboveride);
/*
* In order to get a dc's current EDID, first call tegra_dc_get_edid() from an
diff --git a/drivers/video/tegra/dc/dc.c b/drivers/video/tegra/dc/dc.c
index 57bdab2b2224..1825d2177ad1 100644
--- a/drivers/video/tegra/dc/dc.c
+++ b/drivers/video/tegra/dc/dc.c
@@ -668,27 +668,46 @@ 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++) {
+ for (i = 0; i < 256; i++)
lut->r[i] = lut->g[i] = lut->b[i] = (u8)i;
- }
}
-static void tegra_dc_set_lut(struct tegra_dc *dc,
- struct tegra_dc_lut *lut,
- int start,
- int len)
+static int tegra_dc_lut_is_defaults(struct tegra_dc_lut *lut)
{
- int i;
- for (i = start, len += start; i < len; i++) {
+ unsigned int i;
+ for (i = 0; i < 256; i++)
+ if ((lut->r[i] != i) || (lut->g[i] != i) || (lut->b[i] != i))
+ return 0;
+ return 1;
+}
+
+static void tegra_dc_set_lut(struct tegra_dc *dc, struct tegra_dc_win* win)
+{
+ unsigned int i;
+ unsigned long val;
+ struct tegra_dc_lut *lut = &win->lut;
+
+ 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));
}
+
+ val = tegra_dc_readl(dc, DC_WIN_WIN_OPTIONS);
+
+ if (win->ppflags & TEGRA_WIN_PPFLAG_CP_ENABLE)
+ val |= CP_ENABLE;
+ else
+ val &= ~CP_ENABLE;
+
+ tegra_dc_writel(dc, val, DC_WIN_WIN_OPTIONS);
}
-int tegra_dc_update_lut(struct tegra_dc *dc, int win_idx, int start, int len)
+int tegra_dc_update_lut(struct tegra_dc *dc, int win_idx, int fboveride)
{
+ struct tegra_dc_win *win = &dc->windows[win_idx];
+
mutex_lock(&dc->lock);
if (!dc->enabled) {
@@ -696,10 +715,20 @@ int tegra_dc_update_lut(struct tegra_dc *dc, int win_idx, int start, int len)
return -EFAULT;
}
+ if (!tegra_dc_lut_is_defaults(&win->lut))
+ 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);
- tegra_dc_set_lut(dc, &dc->windows[win_idx].lut, start, len);
+ tegra_dc_set_lut(dc, win);
mutex_unlock(&dc->lock);
@@ -1117,12 +1146,15 @@ int tegra_dc_update_windows(struct tegra_dc_win *windows[], int n)
DC_WIN_BUFFER_ADDR_MODE_LINEAR_UV,
DC_WIN_BUFFER_ADDR_MODE);
- val = WIN_ENABLE | CP_ENABLE;
+ val = WIN_ENABLE;
if (yuvp)
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)
@@ -2221,12 +2253,13 @@ static void tegra_dc_init(struct tegra_dc *dc)
tegra_dc_set_color_control(dc);
for (i = 0; i < DC_N_WINDOWS; i++) {
+ struct tegra_dc_win *win = &dc->windows[i];
tegra_dc_writel(dc, WINDOW_A_SELECT << i,
DC_CMD_DISPLAY_WINDOW_HEADER);
- tegra_dc_init_csc_defaults(&dc->windows[i].csc);
- tegra_dc_set_csc(dc, &dc->windows[i].csc);
- tegra_dc_init_lut_defaults(&dc->windows[i].lut);
- tegra_dc_set_lut(dc, &dc->windows[i].lut, 0, 256);
+ tegra_dc_init_csc_defaults(&win->csc);
+ tegra_dc_set_csc(dc, &win->csc);
+ tegra_dc_init_lut_defaults(&win->lut);
+ tegra_dc_set_lut(dc, win);
tegra_dc_set_scaling_filter(dc);
}
diff --git a/drivers/video/tegra/dc/ext/dev.c b/drivers/video/tegra/dc/ext/dev.c
index b8993dd350f6..a6290d4701ce 100644
--- a/drivers/video/tegra/dc/ext/dev.c
+++ b/drivers/video/tegra/dc/ext/dev.c
@@ -528,11 +528,16 @@ static int set_lut_channel(u16 *channel_from_user,
int i;
u16 lut16bpp[256];
- if (copy_from_user(lut16bpp, channel_from_user, len<<1))
- return 1;
+ if (channel_from_user) {
+ if (copy_from_user(lut16bpp, channel_from_user, len<<1))
+ return 1;
- for (i=0; i<len; i++)
- channel_to[start+i] = lut16bpp[i]>>8;
+ for (i = 0; i < len; i++)
+ channel_to[start+i] = lut16bpp[i]>>8;
+ } else {
+ for (i = 0; i < len; i++)
+ channel_to[start+i] = start+i;
+ }
return 0;
}
@@ -574,7 +579,8 @@ static int tegra_dc_ext_set_lut(struct tegra_dc_ext_user *user,
return -EFAULT;
}
- tegra_dc_update_lut(dc, index, start, len);
+ tegra_dc_update_lut(dc, index,
+ new_lut->flags & TEGRA_DC_EXT_LUT_FLAGS_FBOVERRIDE);
mutex_unlock(&ext_win->lock);
diff --git a/include/video/tegra_dc_ext.h b/include/video/tegra_dc_ext.h
index 77d4e62d70f6..6c1a4e3e59c6 100644
--- a/include/video/tegra_dc_ext.h
+++ b/include/video/tegra_dc_ext.h
@@ -180,13 +180,16 @@ struct tegra_dc_ext_csc {
*/
struct tegra_dc_ext_lut {
__u32 win_index; /* window index to set lut for */
+ __u32 flags; /* Flag bitmask, see TEGRA_DC_EXT_LUT_FLAGS_* */
__u32 start; /* start index to update lut from */
__u32 len; /* number of valid lut entries */
- __u16* r; /* array of size 16-bit red values */
- __u16* g; /* array of size 16-bit green values */
- __u16* b; /* array of size 16-bit blue values */
+ __u16 *r; /* array of 16-bit red values, 0 to reset */
+ __u16 *g; /* array of 16-bit green values, 0 to reset */
+ __u16 *b; /* array of 16-bit blue values, 0 to reset */
};
+/* tegra_dc_ext_lut.flags - override fb device palette. Default is multiply. */
+#define TEGRA_DC_EXT_LUT_FLAGS_FBOVERRIDE 0x01
#define TEGRA_DC_EXT_FLAGS_ENABLED 1
struct tegra_dc_ext_status {
@@ -229,7 +232,7 @@ struct tegra_dc_ext_status {
_IOR('D', 0x09, __u32)
#define TEGRA_DC_EXT_SET_LUT \
- _IOR('D', 0x0A, struct tegra_dc_ext_lut)
+ _IOW('D', 0x0A, struct tegra_dc_ext_lut)
enum tegra_dc_ext_control_output_type {
TEGRA_DC_EXT_DSI,