diff options
-rw-r--r-- | arch/arm/mach-tegra/include/mach/dc.h | 6 | ||||
-rw-r--r-- | drivers/video/tegra/dc/dc.c | 63 | ||||
-rw-r--r-- | drivers/video/tegra/dc/ext/dev.c | 16 | ||||
-rw-r--r-- | include/video/tegra_dc_ext.h | 11 |
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, |