From f80e81610f4e2e3a9051b465a9176ac70f6913f1 Mon Sep 17 00:00:00 2001 From: David Schalig Date: Tue, 25 Oct 2011 19:28:24 +0900 Subject: 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 Tested-by: Varun Colbert Rebase-Id: R7e613b1c8ac469242172bd81db9dfba25176e0c3 --- drivers/video/tegra/dc/dc.c | 80 ++++++++++++++++++++++++++++++++------------- 1 file changed, 58 insertions(+), 22 deletions(-) (limited to 'drivers/video/tegra/dc/dc.c') 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]; -- cgit v1.2.3