diff options
Diffstat (limited to 'drivers/video/tegra/dc')
-rw-r--r-- | drivers/video/tegra/dc/dc.c | 80 | ||||
-rw-r--r-- | drivers/video/tegra/dc/dc_priv.h | 1 |
2 files changed, 59 insertions, 22 deletions
diff --git a/drivers/video/tegra/dc/dc.c b/drivers/video/tegra/dc/dc.c index b1c441390ce4..4f8da4e4735e 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 5eaa8be7dafd..83f26b8dd543 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) |