diff options
author | David Schalig <dschalig@nvidia.com> | 2011-10-25 19:28:24 +0900 |
---|---|---|
committer | Dan Willemsen <dwillemsen@nvidia.com> | 2011-11-30 21:49:35 -0800 |
commit | f80e81610f4e2e3a9051b465a9176ac70f6913f1 (patch) | |
tree | 87e9e17de05b511dc97b6c1c9a0fb3b92ee69732 /drivers/video/tegra/dc/dc.c | |
parent | c48cfa76bc9c61ae99b663519075283bd8e290c1 (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/dc.c')
-rw-r--r-- | drivers/video/tegra/dc/dc.c | 80 |
1 files changed, 58 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]; |