video: tegra: dc: split dc.c into smaller files
Jon Mayo [Tue, 26 Jun 2012 20:53:55 +0000 (13:53 -0700)]
Moved mode setting code into mode.c
Move window code info window.c
Moved clock related code into clock.c
Moved LUT and gamma related code into lut.c
Moved csc(color space conversion) into csc.c
Removed unnecessary static function prototypes from header.
Moved many short inline functions to dc_priv.h
Cleaned up copyright headings.
Cleaned up formatting and indent in all files.
Fixed build warnings.

Bug 870907

Change-Id: I6ccc37150191765394f0b5629423eafd4e5e5792
Signed-off-by: Jon Mayo <jmayo@nvidia.com>
Reviewed-on: http://git-master/r/111371
Reviewed-by: Rohan Somvanshi <rsomvanshi@nvidia.com>
Tested-by: Rohan Somvanshi <rsomvanshi@nvidia.com>

32 files changed:
drivers/video/tegra/dc/Makefile
drivers/video/tegra/dc/bandwidth.c
drivers/video/tegra/dc/clock.c [new file with mode: 0644]
drivers/video/tegra/dc/csc.c [new file with mode: 0644]
drivers/video/tegra/dc/dc.c
drivers/video/tegra/dc/dc_config.c
drivers/video/tegra/dc/dc_config.h
drivers/video/tegra/dc/dc_priv.h
drivers/video/tegra/dc/dc_reg.h
drivers/video/tegra/dc/dc_sysfs.c
drivers/video/tegra/dc/dsi.c
drivers/video/tegra/dc/dsi.h
drivers/video/tegra/dc/dsi_regs.h
drivers/video/tegra/dc/edid.c
drivers/video/tegra/dc/ext/control.c
drivers/video/tegra/dc/ext/cursor.c
drivers/video/tegra/dc/ext/dev.c
drivers/video/tegra/dc/ext/events.c
drivers/video/tegra/dc/ext/tegra_dc_ext_priv.h
drivers/video/tegra/dc/ext/util.c
drivers/video/tegra/dc/hdmi.c
drivers/video/tegra/dc/hdmi.h
drivers/video/tegra/dc/hdmi_reg.h
drivers/video/tegra/dc/lut.c [new file with mode: 0644]
drivers/video/tegra/dc/mode.c [new file with mode: 0644]
drivers/video/tegra/dc/nvhdcp.c
drivers/video/tegra/dc/nvhdcp.h
drivers/video/tegra/dc/nvsd.c
drivers/video/tegra/dc/nvsd.h
drivers/video/tegra/dc/rgb.c
drivers/video/tegra/dc/window.c [new file with mode: 0644]
drivers/video/tegra/fb.c

index 13f8989..59104c6 100644 (file)
@@ -1,7 +1,6 @@
 GCOV_PROFILE := y
 EXTRA_CFLAGS += -Idrivers/video/tegra/host
-obj-y += bandwidth.o
-obj-y += dc.o
+obj-y += dc.o bandwidth.o mode.o clock.o lut.o csc.o window.o
 obj-y += rgb.o
 obj-y += hdmi.o
 obj-$(CONFIG_TEGRA_NVHDCP) += nvhdcp.o
index 785ec7c..c7e5072 100644 (file)
@@ -1,7 +1,7 @@
 /*
  * drivers/video/tegra/dc/bandwidth.c
  *
- * Copyright (C) 2010-2012 NVIDIA Corporation
+ * Copyright (c) 2010-2012, NVIDIA CORPORATION, All rights reserved.
  *
  * This software is licensed under the terms of the GNU General Public
  * License version 2, as published by the Free Software Foundation, and
diff --git a/drivers/video/tegra/dc/clock.c b/drivers/video/tegra/dc/clock.c
new file mode 100644 (file)
index 0000000..c785282
--- /dev/null
@@ -0,0 +1,150 @@
+/*
+ * drivers/video/tegra/dc/clock.c
+ *
+ * Copyright (C) 2010 Google, Inc.
+ *
+ * Copyright (c) 2010-2012, NVIDIA CORPORATION, All rights reserved.
+ *
+ * This software is licensed under the terms of the GNU General Public
+ * License version 2, as published by the Free Software Foundation, and
+ * may be copied, distributed, and modified under those terms.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ */
+
+#include <linux/err.h>
+#include <linux/types.h>
+#include <linux/clk.h>
+
+#include <mach/clk.h>
+#include <mach/dc.h>
+
+#include "dc_reg.h"
+#include "dc_priv.h"
+
+unsigned long tegra_dc_pclk_round_rate(struct tegra_dc *dc, int pclk)
+{
+       unsigned long rate;
+       unsigned long div;
+
+       rate = tegra_dc_clk_get_rate(dc);
+
+       div = DIV_ROUND_CLOSEST(rate * 2, pclk);
+
+       if (div < 2)
+               return 0;
+
+       return rate * 2 / div;
+}
+
+static unsigned long tegra_dc_pclk_predict_rate(struct clk *parent, int pclk)
+{
+       unsigned long rate;
+       unsigned long div;
+
+       rate = clk_get_rate(parent);
+
+       div = DIV_ROUND_CLOSEST(rate * 2, pclk);
+
+       if (div < 2)
+               return 0;
+
+       return rate * 2 / div;
+}
+
+void tegra_dc_setup_clk(struct tegra_dc *dc, struct clk *clk)
+{
+       int pclk;
+
+       if (dc->out->type == TEGRA_DC_OUT_RGB) {
+               unsigned long rate;
+               struct clk *parent_clk =
+                       clk_get_sys(NULL, dc->out->parent_clk ? : "pll_p");
+
+               if (dc->out->parent_clk_backup &&
+                   (parent_clk == clk_get_sys(NULL, "pll_p"))) {
+                       rate = tegra_dc_pclk_predict_rate(
+                               parent_clk, dc->mode.pclk);
+                       /* use pll_d as last resort */
+                       if (rate < (dc->mode.pclk / 100 * 99) ||
+                           rate > (dc->mode.pclk / 100 * 109))
+                               parent_clk = clk_get_sys(
+                                       NULL, dc->out->parent_clk_backup);
+               }
+
+               if (clk_get_parent(clk) != parent_clk)
+                       clk_set_parent(clk, parent_clk);
+
+               if (parent_clk != clk_get_sys(NULL, "pll_p")) {
+                       struct clk *base_clk = clk_get_parent(parent_clk);
+
+                       /* Assuming either pll_d or pll_d2 is used */
+                       rate = dc->mode.pclk * 2;
+
+                       if (rate != clk_get_rate(base_clk))
+                               clk_set_rate(base_clk, rate);
+               }
+       }
+
+       if (dc->out->type == TEGRA_DC_OUT_HDMI) {
+               unsigned long rate;
+               struct clk *parent_clk = clk_get_sys(NULL,
+                       dc->out->parent_clk ? : "pll_d_out0");
+               struct clk *base_clk = clk_get_parent(parent_clk);
+
+               /*
+                * Providing dynamic frequency rate setting for T20/T30 HDMI.
+                * The required rate needs to be setup at 4x multiplier,
+                * as out0 is 1/2 of the actual PLL output.
+                */
+
+               rate = dc->mode.pclk * 4;
+               if (rate != clk_get_rate(base_clk))
+                       clk_set_rate(base_clk, rate);
+
+               if (clk_get_parent(clk) != parent_clk)
+                       clk_set_parent(clk, parent_clk);
+       }
+
+       if (dc->out->type == TEGRA_DC_OUT_DSI) {
+               unsigned long rate;
+               struct clk *parent_clk;
+               struct clk *base_clk;
+
+               if (clk == dc->clk) {
+                       parent_clk = clk_get_sys(NULL,
+                                       dc->out->parent_clk ? : "pll_d_out0");
+                       base_clk = clk_get_parent(parent_clk);
+                       tegra_clk_cfg_ex(base_clk,
+                                       TEGRA_CLK_PLLD_DSI_OUT_ENB, 1);
+               } else {
+                       if (dc->pdata->default_out->dsi->dsi_instance) {
+                               parent_clk = clk_get_sys(NULL,
+                                       dc->out->parent_clk ? : "pll_d2_out0");
+                               base_clk = clk_get_parent(parent_clk);
+                               tegra_clk_cfg_ex(base_clk,
+                                               TEGRA_CLK_PLLD_CSI_OUT_ENB, 1);
+                       } else {
+                               parent_clk = clk_get_sys(NULL,
+                                       dc->out->parent_clk ? : "pll_d_out0");
+                               base_clk = clk_get_parent(parent_clk);
+                               tegra_clk_cfg_ex(base_clk,
+                                               TEGRA_CLK_PLLD_DSI_OUT_ENB, 1);
+                       }
+               }
+
+               rate = dc->mode.pclk * dc->shift_clk_div * 2;
+               if (rate != clk_get_rate(base_clk))
+                       clk_set_rate(base_clk, rate);
+
+               if (clk_get_parent(clk) != parent_clk)
+                       clk_set_parent(clk, parent_clk);
+       }
+
+       pclk = tegra_dc_pclk_round_rate(dc, dc->mode.pclk);
+       tegra_dvfs_set_rate(clk, pclk);
+}
diff --git a/drivers/video/tegra/dc/csc.c b/drivers/video/tegra/dc/csc.c
new file mode 100644 (file)
index 0000000..74fa900
--- /dev/null
@@ -0,0 +1,67 @@
+/*
+ * drivers/video/tegra/dc/csc.c
+ *
+ * Copyright (c) 2010-2012, NVIDIA CORPORATION, All rights reserved.
+ *
+ * This software is licensed under the terms of the GNU General Public
+ * License version 2, as published by the Free Software Foundation, and
+ * may be copied, distributed, and modified under those terms.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ */
+
+#include <linux/err.h>
+#include <linux/types.h>
+#include <mach/dc.h>
+
+#include "dc_reg.h"
+#include "dc_priv.h"
+
+void tegra_dc_init_csc_defaults(struct tegra_dc_csc *csc)
+{
+       csc->yof   = 0x00f0;
+       csc->kyrgb = 0x012a;
+       csc->kur   = 0x0000;
+       csc->kvr   = 0x0198;
+       csc->kug   = 0x039b;
+       csc->kvg   = 0x032f;
+       csc->kub   = 0x0204;
+       csc->kvb   = 0x0000;
+}
+
+void tegra_dc_set_csc(struct tegra_dc *dc, struct tegra_dc_csc *csc)
+{
+       tegra_dc_writel(dc, csc->yof,   DC_WIN_CSC_YOF);
+       tegra_dc_writel(dc, csc->kyrgb, DC_WIN_CSC_KYRGB);
+       tegra_dc_writel(dc, csc->kur,   DC_WIN_CSC_KUR);
+       tegra_dc_writel(dc, csc->kvr,   DC_WIN_CSC_KVR);
+       tegra_dc_writel(dc, csc->kug,   DC_WIN_CSC_KUG);
+       tegra_dc_writel(dc, csc->kvg,   DC_WIN_CSC_KVG);
+       tegra_dc_writel(dc, csc->kub,   DC_WIN_CSC_KUB);
+       tegra_dc_writel(dc, csc->kvb,   DC_WIN_CSC_KVB);
+}
+
+int tegra_dc_update_csc(struct tegra_dc *dc, int win_idx)
+{
+       mutex_lock(&dc->lock);
+
+       if (!dc->enabled) {
+               mutex_unlock(&dc->lock);
+               return -EFAULT;
+       }
+
+       tegra_dc_writel(dc, WINDOW_A_SELECT << win_idx,
+                       DC_CMD_DISPLAY_WINDOW_HEADER);
+
+       tegra_dc_set_csc(dc, &dc->windows[win_idx].csc);
+
+       mutex_unlock(&dc->lock);
+
+       return 0;
+}
+EXPORT_SYMBOL(tegra_dc_update_csc);
+
index b79a659..887beb8 100644 (file)
@@ -4,7 +4,7 @@
  * Copyright (C) 2010 Google, Inc.
  * Author: Erik Gilling <konkers@android.com>
  *
- * Copyright (C) 2010-2012 NVIDIA Corporation
+ * Copyright (c) 2010-2012, NVIDIA CORPORATION, All rights reserved.
  *
  * This software is licensed under the terms of the GNU General Public
  * License version 2, as published by the Free Software Foundation, and
 #define DC_COM_PIN_OUTPUT_POLARITY1_INIT_VAL   0x01000000
 #define DC_COM_PIN_OUTPUT_POLARITY3_INIT_VAL   0x0
 
-#ifndef CONFIG_TEGRA_FPGA_PLATFORM
-#define ALL_UF_INT (WIN_A_UF_INT | WIN_B_UF_INT | WIN_C_UF_INT)
-#else
-/* ignore underflows when on simulation and fpga platform */
-#define ALL_UF_INT (0)
-#endif
-
-static int no_vsync;
 static struct fb_videomode tegra_dc_hdmi_fallback_mode = {
        .refresh = 60,
        .xres = 640,
@@ -83,8 +75,6 @@ static struct fb_videomode tegra_dc_hdmi_fallback_mode = {
 
 static void _tegra_dc_controller_disable(struct tegra_dc *dc);
 
-module_param_named(no_vsync, no_vsync, int, S_IRUGO | S_IWUSR);
-
 struct tegra_dc *tegra_dcs[TEGRA_MAX_DC];
 
 DEFINE_MUTEX(tegra_dc_lock);
@@ -112,23 +102,6 @@ static inline void tegra_dc_clk_disable(struct tegra_dc *dc)
        print(data, buff);                                    \
        } while (0)
 
-#define print_mode_info(dc, mode) do {                        \
-       trace_printk("%s:Mode settings: "                              \
-                       "ref_to_sync: H = %d V = %d, "                  \
-                       "sync_width: H = %d V = %d, "                   \
-                       "back_porch: H = %d V = %d, "                   \
-                       "active: H = %d V = %d, "                       \
-                       "front_porch: H = %d V = %d, "                  \
-                       "pclk = %d, stereo mode = %d\n",                \
-                       dc->ndev->name,                                 \
-                       mode.h_ref_to_sync, mode.v_ref_to_sync,         \
-                       mode.h_sync_width, mode.v_sync_width,           \
-                       mode.h_back_porch, mode.v_back_porch,           \
-                       mode.h_active, mode.v_active,                   \
-                       mode.h_front_porch, mode.v_front_porch,         \
-                       mode.pclk, mode.stereo_mode);                   \
-       } while (0)
-
 #define print_underflow_info(dc) do {                 \
        trace_printk("%s:Underflow stats: underflows : %llu, "      \
                        "undeflows_a : %llu, "                          \
@@ -297,7 +270,7 @@ static void _dump_regs(struct tegra_dc *dc, void *data,
        DUMP_REG(DC_COM_PM1_DUTY_CYCLE);
        DUMP_REG(DC_DISP_SD_CONTROL);
 
-       tegra_dc_clk_disable(dc->clk);
+       tegra_dc_clk_disable(dc);
        tegra_dc_io_end(dc);
 }
 
@@ -538,18 +511,6 @@ struct tegra_dc_win *tegra_dc_get_window(struct tegra_dc *dc, unsigned win)
 }
 EXPORT_SYMBOL(tegra_dc_get_window);
 
-static int get_topmost_window(u32 *depths, unsigned long *wins)
-{
-       int idx, best = -1;
-
-       for_each_set_bit(idx, wins, DC_N_WINDOWS) {
-               if (best == -1 || depths[idx] < depths[best])
-                       best = idx;
-       }
-       clear_bit(best, wins);
-       return best;
-}
-
 bool tegra_dc_get_connected(struct tegra_dc *dc)
 {
        return dc->connected;
@@ -570,222 +531,6 @@ bool tegra_dc_hpd(struct tegra_dc *dc)
 }
 EXPORT_SYMBOL(tegra_dc_hpd);
 
-static u32 blend_topwin(u32 flags)
-{
-       if (flags & TEGRA_WIN_FLAG_BLEND_COVERAGE)
-               return BLEND(NOKEY, ALPHA, 0xff, 0xff);
-       else if (flags & TEGRA_WIN_FLAG_BLEND_PREMULT)
-               return BLEND(NOKEY, PREMULT, 0xff, 0xff);
-       else
-               return BLEND(NOKEY, FIX, 0xff, 0xff);
-}
-
-static u32 blend_2win(int idx, unsigned long behind_mask, u32* flags, int xy)
-{
-       int other;
-
-       for (other = 0; other < DC_N_WINDOWS; other++) {
-               if (other != idx && (xy-- == 0))
-                       break;
-       }
-       if (BIT(other) & behind_mask)
-               return blend_topwin(flags[idx]);
-       else if (flags[other])
-               return BLEND(NOKEY, DEPENDANT, 0x00, 0x00);
-       else
-               return BLEND(NOKEY, FIX, 0x00, 0x00);
-}
-
-static u32 blend_3win(int idx, unsigned long behind_mask, u32* flags)
-{
-       unsigned long infront_mask;
-       int first;
-
-       infront_mask = ~(behind_mask | BIT(idx));
-       infront_mask &= (BIT(DC_N_WINDOWS) - 1);
-       first = ffs(infront_mask) - 1;
-
-       if (!infront_mask)
-               return blend_topwin(flags[idx]);
-       else if (behind_mask && first != -1 && flags[first])
-               return BLEND(NOKEY, DEPENDANT, 0x00, 0x00);
-       else
-               return BLEND(NOKEY, FIX, 0x0, 0x0);
-}
-
-static void tegra_dc_set_blending(struct tegra_dc *dc, struct tegra_dc_blend *blend)
-{
-       unsigned long mask = BIT(DC_N_WINDOWS) - 1;
-
-       while (mask) {
-               int idx = get_topmost_window(blend->z, &mask);
-
-               tegra_dc_writel(dc, WINDOW_A_SELECT << idx,
-                               DC_CMD_DISPLAY_WINDOW_HEADER);
-               tegra_dc_writel(dc, BLEND(NOKEY, FIX, 0xff, 0xff),
-                               DC_WIN_BLEND_NOKEY);
-               tegra_dc_writel(dc, BLEND(NOKEY, FIX, 0xff, 0xff),
-                               DC_WIN_BLEND_1WIN);
-               tegra_dc_writel(dc, blend_2win(idx, mask, blend->flags, 0),
-                               DC_WIN_BLEND_2WIN_X);
-               tegra_dc_writel(dc, blend_2win(idx, mask, blend->flags, 1),
-                               DC_WIN_BLEND_2WIN_Y);
-               tegra_dc_writel(dc, blend_3win(idx, mask, blend->flags),
-                               DC_WIN_BLEND_3WIN_XY);
-       }
-}
-
-static void tegra_dc_init_csc_defaults(struct tegra_dc_csc *csc)
-{
-       csc->yof   = 0x00f0;
-       csc->kyrgb = 0x012a;
-       csc->kur   = 0x0000;
-       csc->kvr   = 0x0198;
-       csc->kug   = 0x039b;
-       csc->kvg   = 0x032f;
-       csc->kub   = 0x0204;
-       csc->kvb   = 0x0000;
-}
-
-static void tegra_dc_set_csc(struct tegra_dc *dc, struct tegra_dc_csc *csc)
-{
-       tegra_dc_writel(dc, csc->yof,   DC_WIN_CSC_YOF);
-       tegra_dc_writel(dc, csc->kyrgb, DC_WIN_CSC_KYRGB);
-       tegra_dc_writel(dc, csc->kur,   DC_WIN_CSC_KUR);
-       tegra_dc_writel(dc, csc->kvr,   DC_WIN_CSC_KVR);
-       tegra_dc_writel(dc, csc->kug,   DC_WIN_CSC_KUG);
-       tegra_dc_writel(dc, csc->kvg,   DC_WIN_CSC_KVG);
-       tegra_dc_writel(dc, csc->kub,   DC_WIN_CSC_KUB);
-       tegra_dc_writel(dc, csc->kvb,   DC_WIN_CSC_KVB);
-}
-
-int tegra_dc_update_csc(struct tegra_dc *dc, int win_idx)
-{
-       mutex_lock(&dc->lock);
-
-       if (!dc->enabled) {
-               mutex_unlock(&dc->lock);
-               return -EFAULT;
-       }
-
-       tegra_dc_writel(dc, WINDOW_A_SELECT << win_idx,
-                       DC_CMD_DISPLAY_WINDOW_HEADER);
-
-       tegra_dc_set_csc(dc, &dc->windows[win_idx].csc);
-
-       mutex_unlock(&dc->lock);
-
-       return 0;
-}
-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++)
-               lut->r[i] = lut->g[i] = lut->b[i] = (u8)i;
-}
-
-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))
-{
-       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 int tegra_dc_lut_isdefaults_lambda(struct tegra_dc *dc, int i, u32 rgb)
-{
-       if (rgb != (i | (i<<8) | (i<<16)))
-               return 0;
-       return 1;
-}
-
-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);
-
-       tegra_dc_loop_lut(dc, win, tegra_dc_set_lut_setreg_lambda);
-
-       if (win->ppflags & TEGRA_WIN_PPFLAG_CP_ENABLE)
-               val |= CP_ENABLE;
-       else
-               val &= ~CP_ENABLE;
-
-       tegra_dc_writel(dc, val, DC_WIN_WIN_OPTIONS);
-}
-
-static int tegra_dc_update_winlut(struct tegra_dc *dc, int win_idx, int fbovr)
-{
-       struct tegra_dc_win *win = &dc->windows[win_idx];
-
-       mutex_lock(&dc->lock);
-
-       if (!dc->enabled) {
-               mutex_unlock(&dc->lock);
-               return -EFAULT;
-       }
-
-       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;
-
-       tegra_dc_writel(dc, WINDOW_A_SELECT << win_idx,
-                       DC_CMD_DISPLAY_WINDOW_HEADER);
-
-       tegra_dc_set_lut(dc, win);
-
-       mutex_unlock(&dc->lock);
-
-       tegra_dc_update_windows(&win, 1);
-
-       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)
 {
        unsigned i;
@@ -814,287 +559,10 @@ void tegra_dc_host_resume(struct tegra_dc *dc) {
        tegra_dsi_host_resume(dc);
 }
 
-static inline u32 compute_dda_inc(fixed20_12 in, unsigned out_int,
-                                 bool v, unsigned Bpp)
-{
-       /*
-        * min(round((prescaled_size_in_pixels - 1) * 0x1000 /
-        *           (post_scaled_size_in_pixels - 1)), MAX)
-        * Where the value of MAX is as follows:
-        * For V_DDA_INCREMENT: 15.0 (0xF000)
-        * For H_DDA_INCREMENT:  4.0 (0x4000) for 4 Bytes/pix formats.
-        *                       8.0 (0x8000) for 2 Bytes/pix formats.
-        */
-
-       fixed20_12 out = dfixed_init(out_int);
-       u32 dda_inc;
-       int max;
-
-       if (v) {
-               max = 15;
-       } else {
-               switch (Bpp) {
-               default:
-                       WARN_ON_ONCE(1);
-                       /* fallthrough */
-               case 4:
-                       max = 4;
-                       break;
-               case 2:
-                       max = 8;
-                       break;
-               }
-       }
-
-       out.full = max_t(u32, out.full - dfixed_const(1), dfixed_const(1));
-       in.full -= dfixed_const(1);
-
-       dda_inc = dfixed_div(in, out);
-
-       dda_inc = min_t(u32, dda_inc, dfixed_const(max));
-
-       return dda_inc;
-}
-
-static inline u32 compute_initial_dda(fixed20_12 in)
-{
-       return dfixed_frac(in);
-}
-
-/* does not support updating windows on multiple dcs in one call */
-int tegra_dc_update_windows(struct tegra_dc_win *windows[], int n)
+static inline void disable_dc_irq(unsigned int irq)
 {
-       struct tegra_dc *dc;
-       unsigned long update_mask = GENERAL_ACT_REQ;
-       unsigned long val;
-       bool update_blend = false;
-       int i;
-
-       dc = windows[0]->dc;
-
-       if (dc->out->flags & TEGRA_DC_OUT_ONE_SHOT_MODE) {
-               /* Acquire one_shot_lock to avoid race condition between
-                * cancellation of old delayed work and schedule of new
-                * delayed work. */
-               mutex_lock(&dc->one_shot_lock);
-               cancel_delayed_work_sync(&dc->one_shot_work);
-       }
-       mutex_lock(&dc->lock);
-
-       if (!dc->enabled) {
-               mutex_unlock(&dc->lock);
-               if (dc->out->flags & TEGRA_DC_OUT_ONE_SHOT_MODE)
-                       mutex_unlock(&dc->one_shot_lock);
-               return -EFAULT;
-       }
-
-       if (dc->out->flags & TEGRA_DC_OUT_ONE_SHOT_LP_MODE)
-               tegra_dc_host_resume(dc);
-
-       if (no_vsync)
-               tegra_dc_writel(dc, WRITE_MUX_ACTIVE | READ_MUX_ACTIVE, DC_CMD_STATE_ACCESS);
-       else
-               tegra_dc_writel(dc, WRITE_MUX_ASSEMBLY | READ_MUX_ASSEMBLY, DC_CMD_STATE_ACCESS);
-
-       for (i = 0; i < n; i++) {
-               struct tegra_dc_win *win = windows[i];
-               unsigned h_dda;
-               unsigned v_dda;
-               fixed20_12 h_offset, v_offset;
-               bool invert_h = (win->flags & TEGRA_WIN_FLAG_INVERT_H) != 0;
-               bool invert_v = (win->flags & TEGRA_WIN_FLAG_INVERT_V) != 0;
-               bool yuv = tegra_dc_is_yuv(win->fmt);
-               bool yuvp = tegra_dc_is_yuv_planar(win->fmt);
-               unsigned Bpp = tegra_dc_fmt_bpp(win->fmt) / 8;
-               /* Bytes per pixel of bandwidth, used for dda_inc calculation */
-               unsigned Bpp_bw = Bpp * (yuvp ? 2 : 1);
-               const bool filter_h = win_use_h_filter(dc, win);
-               const bool filter_v = win_use_v_filter(dc, win);
-
-               if (win->z != dc->blend.z[win->idx]) {
-                       dc->blend.z[win->idx] = win->z;
-                       update_blend = true;
-               }
-               if ((win->flags & TEGRA_WIN_BLEND_FLAGS_MASK) !=
-                       dc->blend.flags[win->idx]) {
-                       dc->blend.flags[win->idx] =
-                               win->flags & TEGRA_WIN_BLEND_FLAGS_MASK;
-                       update_blend = true;
-               }
-
-               tegra_dc_writel(dc, WINDOW_A_SELECT << win->idx,
-                               DC_CMD_DISPLAY_WINDOW_HEADER);
-
-               if (!no_vsync)
-                       update_mask |= WIN_A_ACT_REQ << win->idx;
-
-               if (!WIN_IS_ENABLED(win)) {
-                       dc->windows[i].dirty = 1;
-                       tegra_dc_writel(dc, 0, DC_WIN_WIN_OPTIONS);
-                       continue;
-               }
-
-               tegra_dc_writel(dc, win->fmt & 0x1f, DC_WIN_COLOR_DEPTH);
-               tegra_dc_writel(dc, win->fmt >> 6, DC_WIN_BYTE_SWAP);
-
-               tegra_dc_writel(dc,
-                               V_POSITION(win->out_y) | H_POSITION(win->out_x),
-                               DC_WIN_POSITION);
-               tegra_dc_writel(dc,
-                               V_SIZE(win->out_h) | H_SIZE(win->out_w),
-                               DC_WIN_SIZE);
-
-               if (tegra_dc_feature_has_scaling(dc, win->idx)) {
-                       tegra_dc_writel(dc,
-                                       V_PRESCALED_SIZE(dfixed_trunc(win->h)) |
-                                       H_PRESCALED_SIZE(dfixed_trunc(win->w) * Bpp),
-                                       DC_WIN_PRESCALED_SIZE);
-
-                       h_dda = compute_dda_inc(win->w, win->out_w, false, Bpp_bw);
-                       v_dda = compute_dda_inc(win->h, win->out_h, true, Bpp_bw);
-                       tegra_dc_writel(dc, V_DDA_INC(v_dda) | H_DDA_INC(h_dda),
-                                       DC_WIN_DDA_INCREMENT);
-                       h_dda = compute_initial_dda(win->x);
-                       v_dda = compute_initial_dda(win->y);
-                       tegra_dc_writel(dc, h_dda, DC_WIN_H_INITIAL_DDA);
-                       tegra_dc_writel(dc, v_dda, DC_WIN_V_INITIAL_DDA);
-               }
-
-               tegra_dc_writel(dc, 0, DC_WIN_BUF_STRIDE);
-               tegra_dc_writel(dc, 0, DC_WIN_UV_BUF_STRIDE);
-               tegra_dc_writel(dc,
-                               (unsigned long)win->phys_addr,
-                               DC_WINBUF_START_ADDR);
-
-               if (!yuvp) {
-                       tegra_dc_writel(dc, win->stride, DC_WIN_LINE_STRIDE);
-               } else {
-                       tegra_dc_writel(dc,
-                                       (unsigned long)win->phys_addr_u,
-                                       DC_WINBUF_START_ADDR_U);
-                       tegra_dc_writel(dc,
-                                       (unsigned long)win->phys_addr_v,
-                                       DC_WINBUF_START_ADDR_V);
-                       tegra_dc_writel(dc,
-                                       LINE_STRIDE(win->stride) |
-                                       UV_LINE_STRIDE(win->stride_uv),
-                                       DC_WIN_LINE_STRIDE);
-               }
-
-               h_offset = win->x;
-               if (invert_h) {
-                       h_offset.full += win->w.full - dfixed_const(1);
-               }
-
-               v_offset = win->y;
-               if (invert_v) {
-                       v_offset.full += win->h.full - dfixed_const(1);
-               }
-
-               tegra_dc_writel(dc, dfixed_trunc(h_offset) * Bpp,
-                               DC_WINBUF_ADDR_H_OFFSET);
-               tegra_dc_writel(dc, dfixed_trunc(v_offset),
-                               DC_WINBUF_ADDR_V_OFFSET);
-
-               if (tegra_dc_feature_has_tiling(dc, win->idx)) {
-                       if (WIN_IS_TILED(win))
-                               tegra_dc_writel(dc,
-                                               DC_WIN_BUFFER_ADDR_MODE_TILE |
-                                               DC_WIN_BUFFER_ADDR_MODE_TILE_UV,
-                                               DC_WIN_BUFFER_ADDR_MODE);
-                       else
-                               tegra_dc_writel(dc,
-                                               DC_WIN_BUFFER_ADDR_MODE_LINEAR |
-                                               DC_WIN_BUFFER_ADDR_MODE_LINEAR_UV,
-                                               DC_WIN_BUFFER_ADDR_MODE);
-               }
-
-               val = WIN_ENABLE;
-               if (yuv)
-                       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)
-                       val |= V_FILTER_ENABLE;
-
-               if (invert_h)
-                       val |= H_DIRECTION_DECREMENT;
-               if (invert_v)
-                       val |= V_DIRECTION_DECREMENT;
-
-               tegra_dc_writel(dc, val, DC_WIN_WIN_OPTIONS);
-
-#ifdef CONFIG_ARCH_TEGRA_3x_SOC
-               if (win->global_alpha == 255)
-                       tegra_dc_writel(dc, 0, DC_WIN_GLOBAL_ALPHA);
-               else
-                       tegra_dc_writel(dc, GLOBAL_ALPHA_ENABLE |
-                               win->global_alpha, DC_WIN_GLOBAL_ALPHA);
-#endif
-
-               win->dirty = no_vsync ? 0 : 1;
-
-               dev_dbg(&dc->ndev->dev, "%s():idx=%d z=%d x=%d y=%d w=%d h=%d "
-                       "out_x=%u out_y=%u out_w=%u out_h=%u "
-                       "fmt=%d yuvp=%d Bpp=%u filter_h=%d filter_v=%d",
-                       __func__, win->idx, win->z,
-                       dfixed_trunc(win->x), dfixed_trunc(win->y),
-                       dfixed_trunc(win->w), dfixed_trunc(win->h),
-                       win->out_x, win->out_y, win->out_w, win->out_h,
-                       win->fmt, yuvp, Bpp, filter_h, filter_v);
-               trace_printk("%s:win%u in:%ux%u out:%ux%u fmt=%d\n",
-                       dc->ndev->name, win->idx, dfixed_trunc(win->w),
-                       dfixed_trunc(win->h), win->out_w, win->out_h, win->fmt);
-       }
-
-       if (update_blend) {
-               tegra_dc_set_blending(dc, &dc->blend);
-               for (i = 0; i < DC_N_WINDOWS; i++) {
-                       if (!no_vsync)
-                               dc->windows[i].dirty = 1;
-                       update_mask |= WIN_A_ACT_REQ << i;
-               }
-       }
-
-       tegra_dc_set_dynamic_emc(windows, n);
-
-       tegra_dc_writel(dc, update_mask << 8, DC_CMD_STATE_CONTROL);
-
-       tegra_dc_writel(dc, FRAME_END_INT | V_BLANK_INT, DC_CMD_INT_STATUS);
-       if (!no_vsync) {
-               set_bit(V_BLANK_FLIP, &dc->vblank_ref_count);
-               tegra_dc_unmask_interrupt(dc, FRAME_END_INT | V_BLANK_INT | ALL_UF_INT);
-       } else {
-               clear_bit(V_BLANK_FLIP, &dc->vblank_ref_count);
-               tegra_dc_mask_interrupt(dc, FRAME_END_INT | V_BLANK_INT | ALL_UF_INT);
-       }
-
-       if (dc->out->flags & TEGRA_DC_OUT_ONE_SHOT_MODE)
-               schedule_delayed_work(&dc->one_shot_work,
-                               msecs_to_jiffies(dc->one_shot_delay_ms));
-
-       /* update EMC clock if calculated bandwidth has changed */
-       tegra_dc_program_bandwidth(dc, false);
-
-       if (dc->out->flags & TEGRA_DC_OUT_ONE_SHOT_MODE)
-               update_mask |= NC_HOST_TRIG;
-
-       tegra_dc_writel(dc, update_mask, DC_CMD_STATE_CONTROL);
-       trace_printk("%s:update_mask=%#lx\n", dc->ndev->name, update_mask);
-
-       mutex_unlock(&dc->lock);
-       if (dc->out->flags & TEGRA_DC_OUT_ONE_SHOT_MODE)
-               mutex_unlock(&dc->one_shot_lock);
-
-       return 0;
+       disable_irq(irq);
 }
-EXPORT_SYMBOL(tegra_dc_update_windows);
 
 u32 tegra_dc_get_syncpt_id(const struct tegra_dc *dc, int i)
 {
@@ -1126,502 +594,6 @@ void tegra_dc_incr_syncpt_min(struct tegra_dc *dc, int i, u32 val)
        mutex_unlock(&dc->lock);
 }
 
-static bool tegra_dc_windows_are_clean(struct tegra_dc_win *windows[],
-                                            int n)
-{
-       int i;
-
-       for (i = 0; i < n; i++) {
-               if (windows[i]->dirty)
-                       return false;
-       }
-
-       return true;
-}
-
-/* does not support syncing windows on multiple dcs in one call */
-int tegra_dc_sync_windows(struct tegra_dc_win *windows[], int n)
-{
-       int ret;
-       if (n < 1 || n > DC_N_WINDOWS)
-               return -EINVAL;
-
-       if (!windows[0]->dc->enabled)
-               return -EFAULT;
-
-#ifdef CONFIG_TEGRA_SIMULATION_PLATFORM
-       /* Don't want to timeout on simulator */
-       ret = wait_event_interruptible(windows[0]->dc->wq,
-               tegra_dc_windows_are_clean(windows, n));
-#else
-       trace_printk("%s:Before wait_event_interruptible_timeout\n",
-                       windows[0]->dc->ndev->name);
-       ret = wait_event_interruptible_timeout(windows[0]->dc->wq,
-                                        tegra_dc_windows_are_clean(windows, n),
-                                        HZ);
-       trace_printk("%s:After wait_event_interruptible_timeout\n",
-                       windows[0]->dc->ndev->name);
-#endif
-       return ret;
-}
-EXPORT_SYMBOL(tegra_dc_sync_windows);
-
-static unsigned long tegra_dc_clk_get_rate(struct tegra_dc *dc)
-{
-#ifdef CONFIG_TEGRA_SILICON_PLATFORM
-       return clk_get_rate(dc->clk);
-#else
-       return 27000000;
-#endif
-}
-
-static unsigned long tegra_dc_pclk_round_rate(struct tegra_dc *dc, int pclk)
-{
-       unsigned long rate;
-       unsigned long div;
-
-       rate = tegra_dc_clk_get_rate(dc);
-
-       div = DIV_ROUND_CLOSEST(rate * 2, pclk);
-
-       if (div < 2)
-               return 0;
-
-       return rate * 2 / div;
-}
-
-static unsigned long tegra_dc_pclk_predict_rate(struct clk *parent, int pclk)
-{
-       unsigned long rate;
-       unsigned long div;
-
-       rate = clk_get_rate(parent);
-
-       div = DIV_ROUND_CLOSEST(rate * 2, pclk);
-
-       if (div < 2)
-               return 0;
-
-       return rate * 2 / div;
-}
-
-void tegra_dc_setup_clk(struct tegra_dc *dc, struct clk *clk)
-{
-       int pclk;
-
-       if (dc->out->type == TEGRA_DC_OUT_RGB) {
-               unsigned long rate;
-               struct clk *parent_clk =
-                       clk_get_sys(NULL, dc->out->parent_clk ? : "pll_p");
-
-               if (dc->out->parent_clk_backup &&
-                   (parent_clk == clk_get_sys(NULL, "pll_p"))) {
-                       rate = tegra_dc_pclk_predict_rate(
-                               parent_clk, dc->mode.pclk);
-                       /* use pll_d as last resort */
-                       if (rate < (dc->mode.pclk / 100 * 99) ||
-                           rate > (dc->mode.pclk / 100 * 109))
-                               parent_clk = clk_get_sys(
-                                       NULL, dc->out->parent_clk_backup);
-               }
-
-               if (clk_get_parent(clk) != parent_clk)
-                       clk_set_parent(clk, parent_clk);
-
-               if (parent_clk != clk_get_sys(NULL, "pll_p")) {
-                       struct clk *base_clk = clk_get_parent(parent_clk);
-
-                       /* Assuming either pll_d or pll_d2 is used */
-                       rate = dc->mode.pclk * 2;
-
-                       if (rate != clk_get_rate(base_clk))
-                               clk_set_rate(base_clk, rate);
-               }
-       }
-
-       if (dc->out->type == TEGRA_DC_OUT_HDMI) {
-               unsigned long rate;
-               struct clk *parent_clk =
-                       clk_get_sys(NULL, dc->out->parent_clk ? : "pll_d_out0");
-               struct clk *base_clk = clk_get_parent(parent_clk);
-
-               /*
-                * Providing dynamic frequency rate setting for T20/T30 HDMI.
-                * The required rate needs to be setup at 4x multiplier,
-                * as out0 is 1/2 of the actual PLL output.
-                */
-
-               rate = dc->mode.pclk * 4;
-               if (rate != clk_get_rate(base_clk))
-                       clk_set_rate(base_clk, rate);
-
-               if (clk_get_parent(clk) != parent_clk)
-                       clk_set_parent(clk, parent_clk);
-       }
-
-       if (dc->out->type == TEGRA_DC_OUT_DSI) {
-               unsigned long rate;
-               struct clk *parent_clk;
-               struct clk *base_clk;
-
-               if (clk == dc->clk) {
-                       parent_clk = clk_get_sys(NULL,
-                                       dc->out->parent_clk ? : "pll_d_out0");
-                       base_clk = clk_get_parent(parent_clk);
-                       tegra_clk_cfg_ex(base_clk,
-                                       TEGRA_CLK_PLLD_DSI_OUT_ENB, 1);
-               } else {
-                       if (dc->pdata->default_out->dsi->dsi_instance) {
-                               parent_clk = clk_get_sys(NULL,
-                                       dc->out->parent_clk ? : "pll_d2_out0");
-                               base_clk = clk_get_parent(parent_clk);
-                               tegra_clk_cfg_ex(base_clk,
-                                               TEGRA_CLK_PLLD_CSI_OUT_ENB, 1);
-                       } else {
-                               parent_clk = clk_get_sys(NULL,
-                                       dc->out->parent_clk ? : "pll_d_out0");
-                               base_clk = clk_get_parent(parent_clk);
-                               tegra_clk_cfg_ex(base_clk,
-                                               TEGRA_CLK_PLLD_DSI_OUT_ENB, 1);
-                       }
-               }
-
-               rate = dc->mode.pclk * dc->shift_clk_div * 2;
-               if (rate != clk_get_rate(base_clk))
-                       clk_set_rate(base_clk, rate);
-
-               if (clk_get_parent(clk) != parent_clk)
-                       clk_set_parent(clk, parent_clk);
-       }
-
-       pclk = tegra_dc_pclk_round_rate(dc, dc->mode.pclk);
-       tegra_dvfs_set_rate(clk, pclk);
-}
-
-/* return non-zero if constraint is violated */
-static int calc_h_ref_to_sync(const struct tegra_dc_mode *mode, int *href)
-{
-       long a, b;
-
-       /* Constraint 5: H_REF_TO_SYNC >= 0 */
-       a = 0;
-
-       /* Constraint 6: H_FRONT_PORT >= (H_REF_TO_SYNC + 1) */
-       b = mode->h_front_porch - 1;
-
-       /* Constraint 1: H_REF_TO_SYNC + H_SYNC_WIDTH + H_BACK_PORCH > 11 */
-       if (a + mode->h_sync_width + mode->h_back_porch <= 11)
-               a = 1 + 11 - mode->h_sync_width - mode->h_back_porch;
-       /* check Constraint 1 and 6 */
-       if (a > b)
-               return 1;
-
-       /* Constraint 4: H_SYNC_WIDTH >= 1 */
-       if (mode->h_sync_width < 1)
-               return 4;
-
-       /* Constraint 7: H_DISP_ACTIVE >= 16 */
-       if (mode->h_active < 16)
-               return 7;
-
-       if (href) {
-               if (b > a && a % 2)
-                       *href = a + 1; /* use smallest even value */
-               else
-                       *href = a; /* even or only possible value */
-       }
-
-       return 0;
-}
-
-static int calc_v_ref_to_sync(const struct tegra_dc_mode *mode, int *vref)
-{
-       long a;
-       a = 1; /* Constraint 5: V_REF_TO_SYNC >= 1 */
-
-       /* Constraint 2: V_REF_TO_SYNC + V_SYNC_WIDTH + V_BACK_PORCH > 1 */
-       if (a + mode->v_sync_width + mode->v_back_porch <= 1)
-               a = 1 + 1 - mode->v_sync_width - mode->v_back_porch;
-
-       /* Constraint 6 */
-       if (mode->v_front_porch < a + 1)
-               a = mode->v_front_porch - 1;
-
-       /* Constraint 4: V_SYNC_WIDTH >= 1 */
-       if (mode->v_sync_width < 1)
-               return 4;
-
-       /* Constraint 7: V_DISP_ACTIVE >= 16 */
-       if (mode->v_active < 16)
-               return 7;
-
-       if (vref)
-               *vref = a;
-       return 0;
-}
-
-static int calc_ref_to_sync(struct tegra_dc_mode *mode)
-{
-       int ret;
-       ret = calc_h_ref_to_sync(mode, &mode->h_ref_to_sync);
-       if (ret)
-               return ret;
-       ret = calc_v_ref_to_sync(mode, &mode->v_ref_to_sync);
-       if (ret)
-               return ret;
-
-       return 0;
-}
-
-static bool check_ref_to_sync(struct tegra_dc_mode *mode)
-{
-       /* Constraint 1: H_REF_TO_SYNC + H_SYNC_WIDTH + H_BACK_PORCH > 11. */
-       if (mode->h_ref_to_sync + mode->h_sync_width + mode->h_back_porch <= 11)
-               return false;
-
-       /* Constraint 2: V_REF_TO_SYNC + V_SYNC_WIDTH + V_BACK_PORCH > 1. */
-       if (mode->v_ref_to_sync + mode->v_sync_width + mode->v_back_porch <= 1)
-               return false;
-
-       /* Constraint 3: V_FRONT_PORCH + V_SYNC_WIDTH + V_BACK_PORCH > 1
-        * (vertical blank). */
-       if (mode->v_front_porch + mode->v_sync_width + mode->v_back_porch <= 1)
-               return false;
-
-       /* Constraint 4: V_SYNC_WIDTH >= 1; H_SYNC_WIDTH >= 1. */
-       if (mode->v_sync_width < 1 || mode->h_sync_width < 1)
-               return false;
-
-       /* Constraint 5: V_REF_TO_SYNC >= 1; H_REF_TO_SYNC >= 0. */
-       if (mode->v_ref_to_sync < 1 || mode->h_ref_to_sync < 0)
-               return false;
-
-       /* Constraint 6: V_FRONT_PORT >= (V_REF_TO_SYNC + 1);
-        * H_FRONT_PORT >= (H_REF_TO_SYNC + 1). */
-       if (mode->v_front_porch < mode->v_ref_to_sync + 1 ||
-               mode->h_front_porch < mode->h_ref_to_sync + 1)
-               return false;
-
-       /* Constraint 7: H_DISP_ACTIVE >= 16; V_DISP_ACTIVE >= 16. */
-       if (mode->h_active < 16 || mode->v_active < 16)
-               return false;
-
-       return true;
-}
-
-#ifdef DEBUG
-/* return in 1000ths of a Hertz */
-static int calc_refresh(const struct tegra_dc_mode *m)
-{
-       long h_total, v_total, refresh;
-       h_total = m->h_active + m->h_front_porch + m->h_back_porch +
-               m->h_sync_width;
-       v_total = m->v_active + m->v_front_porch + m->v_back_porch +
-               m->v_sync_width;
-       refresh = m->pclk / h_total;
-       refresh *= 1000;
-       refresh /= v_total;
-       return refresh;
-}
-
-static void print_mode(struct tegra_dc *dc,
-                       const struct tegra_dc_mode *mode, const char *note)
-{
-       if (mode) {
-               int refresh = calc_refresh(dc, mode);
-               dev_info(&dc->ndev->dev, "%s():MODE:%dx%d@%d.%03uHz pclk=%d\n",
-                       note ? note : "",
-                       mode->h_active, mode->v_active,
-                       refresh / 1000, refresh % 1000,
-                       mode->pclk);
-       }
-}
-#else /* !DEBUG */
-static inline void print_mode(struct tegra_dc *dc,
-                       const struct tegra_dc_mode *mode, const char *note) { }
-#endif /* DEBUG */
-
-static inline void enable_dc_irq(unsigned int irq)
-{
-#ifndef CONFIG_TEGRA_FPGA_PLATFORM
-       enable_irq(irq);
-#else
-       /* Always disable DC interrupts on FPGA. */
-       disable_irq(irq);
-#endif
-}
-
-static inline void disable_dc_irq(unsigned int irq)
-{
-       disable_irq(irq);
-}
-
-static inline void tegra_dc_unmask_interrupt(struct tegra_dc *dc, u32 int_val)
-{
-       u32 val;
-
-       val = tegra_dc_readl(dc, DC_CMD_INT_MASK);
-       val |= int_val;
-       tegra_dc_writel(dc, val, DC_CMD_INT_MASK);
-}
-
-static inline void tegra_dc_mask_interrupt(struct tegra_dc *dc, u32 int_val)
-{
-       u32 val;
-
-       val = tegra_dc_readl(dc, DC_CMD_INT_MASK);
-       val &= ~int_val;
-       tegra_dc_writel(dc, val, DC_CMD_INT_MASK);
-}
-
-static int tegra_dc_program_mode(struct tegra_dc *dc, struct tegra_dc_mode *mode)
-{
-       unsigned long val;
-       unsigned long rate;
-       unsigned long div;
-       unsigned long pclk;
-
-       print_mode(dc, mode, __func__);
-
-       /* use default EMC rate when switching modes */
-       dc->new_emc_clk_rate = tegra_dc_get_default_emc_clk_rate(dc);
-       tegra_dc_program_bandwidth(dc, true);
-
-       tegra_dc_writel(dc, 0x0, DC_DISP_DISP_TIMING_OPTIONS);
-       tegra_dc_writel(dc, mode->h_ref_to_sync | (mode->v_ref_to_sync << 16),
-                       DC_DISP_REF_TO_SYNC);
-       tegra_dc_writel(dc, mode->h_sync_width | (mode->v_sync_width << 16),
-                       DC_DISP_SYNC_WIDTH);
-       tegra_dc_writel(dc, mode->h_back_porch | (mode->v_back_porch << 16),
-                       DC_DISP_BACK_PORCH);
-       tegra_dc_writel(dc, mode->h_active | (mode->v_active << 16),
-                       DC_DISP_DISP_ACTIVE);
-       tegra_dc_writel(dc, mode->h_front_porch | (mode->v_front_porch << 16),
-                       DC_DISP_FRONT_PORCH);
-
-       tegra_dc_writel(dc, DE_SELECT_ACTIVE | DE_CONTROL_NORMAL,
-                       DC_DISP_DATA_ENABLE_OPTIONS);
-
-       /* TODO: MIPI/CRT/HDMI clock cals */
-
-       val = DISP_DATA_FORMAT_DF1P1C;
-
-       if (dc->out->align == TEGRA_DC_ALIGN_MSB)
-               val |= DISP_DATA_ALIGNMENT_MSB;
-       else
-               val |= DISP_DATA_ALIGNMENT_LSB;
-
-       if (dc->out->order == TEGRA_DC_ORDER_RED_BLUE)
-               val |= DISP_DATA_ORDER_RED_BLUE;
-       else
-               val |= DISP_DATA_ORDER_BLUE_RED;
-
-       tegra_dc_writel(dc, val, DC_DISP_DISP_INTERFACE_CONTROL);
-
-       rate = tegra_dc_clk_get_rate(dc);
-
-       pclk = tegra_dc_pclk_round_rate(dc, mode->pclk);
-       trace_printk("%s:pclk=%ld\n", dc->ndev->name, pclk);
-       if (pclk < (mode->pclk / 100 * 99) ||
-           pclk > (mode->pclk / 100 * 109)) {
-               dev_err(&dc->ndev->dev,
-                       "can't divide %ld clock to %d -1/+9%% %ld %d %d\n",
-                       rate, mode->pclk,
-                       pclk, (mode->pclk / 100 * 99),
-                       (mode->pclk / 100 * 109));
-               return -EINVAL;
-       }
-
-       div = (rate * 2 / pclk) - 2;
-       trace_printk("%s:div=%ld\n", dc->ndev->name, div);
-
-       tegra_dc_writel(dc, 0x00010001,
-                       DC_DISP_SHIFT_CLOCK_OPTIONS);
-       tegra_dc_writel(dc, PIXEL_CLK_DIVIDER_PCD1 | SHIFT_CLK_DIVIDER(div),
-                       DC_DISP_DISP_CLOCK_CONTROL);
-
-#ifdef CONFIG_SWITCH
-       switch_set_state(&dc->modeset_switch,
-                        (mode->h_active << 16) | mode->v_active);
-#endif
-
-       tegra_dc_writel(dc, GENERAL_UPDATE, DC_CMD_STATE_CONTROL);
-       tegra_dc_writel(dc, GENERAL_ACT_REQ, DC_CMD_STATE_CONTROL);
-
-       print_mode_info(dc, dc->mode);
-       return 0;
-}
-
-
-int tegra_dc_set_mode(struct tegra_dc *dc, const struct tegra_dc_mode *mode)
-{
-       memcpy(&dc->mode, mode, sizeof(dc->mode));
-
-       print_mode(dc, mode, __func__);
-
-       return 0;
-}
-EXPORT_SYMBOL(tegra_dc_set_mode);
-
-int tegra_dc_set_fb_mode(struct tegra_dc *dc,
-               const struct fb_videomode *fbmode, bool stereo_mode)
-{
-       struct tegra_dc_mode mode;
-
-       if (!fbmode->pixclock)
-               return -EINVAL;
-
-       mode.pclk = PICOS2KHZ(fbmode->pixclock) * 1000;
-       mode.h_sync_width = fbmode->hsync_len;
-       mode.v_sync_width = fbmode->vsync_len;
-       mode.h_back_porch = fbmode->left_margin;
-       mode.v_back_porch = fbmode->upper_margin;
-       mode.h_active = fbmode->xres;
-       mode.v_active = fbmode->yres;
-       mode.h_front_porch = fbmode->right_margin;
-       mode.v_front_porch = fbmode->lower_margin;
-       mode.stereo_mode = stereo_mode;
-       if (dc->out->type == TEGRA_DC_OUT_HDMI) {
-               /* HDMI controller requires h_ref=1, v_ref=1 */
-               mode.h_ref_to_sync = 1;
-               mode.v_ref_to_sync = 1;
-       } else {
-               calc_ref_to_sync(&mode);
-       }
-       if (!check_ref_to_sync(&mode)) {
-               dev_err(&dc->ndev->dev,
-                               "Display timing doesn't meet restrictions.\n");
-               return -EINVAL;
-       }
-       dev_info(&dc->ndev->dev, "Using mode %dx%d pclk=%d href=%d vref=%d\n",
-               mode.h_active, mode.v_active, mode.pclk,
-               mode.h_ref_to_sync, mode.v_ref_to_sync
-       );
-
-#ifndef CONFIG_TEGRA_HDMI_74MHZ_LIMIT
-       /* Double the pixel clock and update v_active only for frame packed mode */
-       if (mode.stereo_mode) {
-               mode.pclk *= 2;
-               /* total v_active = yres*2 + activespace */
-               mode.v_active = fbmode->yres*2 +
-                               fbmode->vsync_len +
-                               fbmode->upper_margin +
-                               fbmode->lower_margin;
-       }
-#endif
-
-       mode.flags = 0;
-
-       if (!(fbmode->sync & FB_SYNC_HOR_HIGH_ACT))
-               mode.flags |= TEGRA_DC_MODE_FLAG_NEG_H_SYNC;
-
-       if (!(fbmode->sync & FB_SYNC_VERT_HIGH_ACT))
-               mode.flags |= TEGRA_DC_MODE_FLAG_NEG_V_SYNC;
-
-       return tegra_dc_set_mode(dc, &mode);
-}
-EXPORT_SYMBOL(tegra_dc_set_fb_mode);
-
 void
 tegra_dc_config_pwm(struct tegra_dc *dc, struct tegra_dc_pwm_params *cfg)
 {
@@ -1841,6 +813,28 @@ crc_error:
        return crc;
 }
 
+static bool tegra_dc_windows_are_dirty(struct tegra_dc *dc)
+{
+#ifndef CONFIG_TEGRA_SIMULATION_PLATFORM
+       u32 val;
+
+       val = tegra_dc_readl(dc, DC_CMD_STATE_CONTROL);
+       if (val & (WIN_A_ACT_REQ | WIN_B_ACT_REQ | WIN_C_ACT_REQ))
+           return true;
+#endif
+       return false;
+}
+
+static inline void enable_dc_irq(unsigned int irq)
+{
+#ifndef CONFIG_TEGRA_FPGA_PLATFORM
+       enable_irq(irq);
+#else
+       /* Always disable DC interrupts on FPGA. */
+       disable_irq(irq);
+#endif
+}
+
 static void tegra_dc_vblank(struct work_struct *work)
 {
        struct tegra_dc *dc = container_of(work, struct tegra_dc, vblank_work);
@@ -1987,50 +981,6 @@ static void tegra_dc_underflow_handler(struct tegra_dc *dc)
 }
 
 #ifndef CONFIG_TEGRA_FPGA_PLATFORM
-static bool tegra_dc_windows_are_dirty(struct tegra_dc *dc)
-{
-#ifndef CONFIG_TEGRA_SIMULATION_PLATFORM
-       u32 val;
-
-       val = tegra_dc_readl(dc, DC_CMD_STATE_CONTROL);
-       if (val & (WIN_A_ACT_REQ | WIN_B_ACT_REQ | WIN_C_ACT_REQ))
-           return true;
-#endif
-       return false;
-}
-
-static void tegra_dc_trigger_windows(struct tegra_dc *dc)
-{
-       u32 val, i;
-       u32 completed = 0;
-       u32 dirty = 0;
-
-       val = tegra_dc_readl(dc, DC_CMD_STATE_CONTROL);
-       for (i = 0; i < DC_N_WINDOWS; i++) {
-#ifdef CONFIG_TEGRA_SIMULATION_PLATFORM
-               /* FIXME: this is not needed when the simulator
-                  clears WIN_x_UPDATE bits as in HW */
-               dc->windows[i].dirty = 0;
-               completed = 1;
-#else
-               if (!(val & (WIN_A_ACT_REQ << i))) {
-                       dc->windows[i].dirty = 0;
-                       completed = 1;
-               } else {
-                       dirty = 1;
-               }
-#endif
-       }
-
-       if (!dirty) {
-               if (!(dc->out->flags & TEGRA_DC_OUT_ONE_SHOT_MODE))
-                       tegra_dc_mask_interrupt(dc, FRAME_END_INT);
-       }
-
-       if (completed)
-               wake_up(&dc->wq);
-}
-
 static void tegra_dc_one_shot_irq(struct tegra_dc *dc, unsigned long status)
 {
        if (status & V_BLANK_INT) {
@@ -2285,7 +1235,7 @@ static int tegra_dc_init(struct tegra_dc *dc)
                        nvhost_syncpt_read_ext(dc->ndev, syncpt);
        }
 
-       print_mode(dc, &dc->mode, __func__);
+       print_mode_info(dc, dc->mode);
 
        if (dc->mode.pclk)
                if (tegra_dc_program_mode(dc, &dc->mode))
@@ -2586,7 +1536,8 @@ static void tegra_dc_reset_worker(struct work_struct *work)
 
        mutex_lock(&shared_lock);
 
-       dev_warn(&dc->ndev->dev, "overlay stuck in underflow state.  resetting.\n");
+       dev_warn(&dc->ndev->dev,
+               "overlay stuck in underflow state.  resetting.\n");
 
        tegra_dc_ext_disable(dc->ext);
 
@@ -2698,7 +1649,8 @@ static int tegra_dc_probe(struct nvhost_device *ndev,
                goto err_free;
        }
 
-       base_res = request_mem_region(res->start, resource_size(res), ndev->name);
+       base_res = request_mem_region(res->start, resource_size(res),
+               ndev->name);
        if (!base_res) {
                dev_err(&ndev->dev, "request_mem_region failed\n");
                ret = -EBUSY;
index a40712f..f238fad 100644 (file)
@@ -1,6 +1,7 @@
 /*
  * drivers/video/tegra/dc/dc_config.c
- * * Copyright (c) 2012, NVIDIA Corporation.
+ *
+ * Copyright (c) 2012, NVIDIA CORPORATION, All rights reserved.
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License as published by
index 4cc9241..6f5d08c 100644 (file)
@@ -1,6 +1,6 @@
 /*
  * drivers/video/tegra/dc/dc_config.c
- * * Copyright (c) 2012, NVIDIA Corporation.
+ * Copyright (c) 2010-2012, NVIDIA CORPORATION, All rights reserved.
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License as published by
index 19c8656..fb12435 100644 (file)
@@ -4,6 +4,8 @@
  * Copyright (C) 2010 Google, Inc.
  * Author: Erik Gilling <konkers@android.com>
  *
+ * Copyright (c) 2010-2012, NVIDIA CORPORATION, All rights reserved.
+ *
  * This software is licensed under the terms of the GNU General Public
  * License version 2, as published by the Free Software Foundation, and
  * may be copied, distributed, and modified under those terms.
@@ -22,6 +24,7 @@
 #include <linux/mutex.h>
 #include <linux/wait.h>
 #include <linux/fb.h>
+#include <linux/clk.h>
 #include <linux/completion.h>
 #include <linux/switch.h>
 #include <linux/nvhost.h>
@@ -31,6 +34,8 @@
 #include <mach/tegra_dc_ext.h>
 #include <mach/clk.h>
 
+#include "dc_reg.h"
+
 #define WIN_IS_TILED(win)      ((win)->flags & TEGRA_WIN_FLAG_TILED)
 #define WIN_IS_ENABLED(win)    ((win)->flags & TEGRA_WIN_FLAG_ENABLED)
 
 #define EMC_BW_TO_FREQ(bw) (DDR_BW_TO_FREQ(bw) * 2)
 #endif
 
+#ifndef CONFIG_TEGRA_FPGA_PLATFORM
+#define ALL_UF_INT (WIN_A_UF_INT | WIN_B_UF_INT | WIN_C_UF_INT)
+#else
+/* ignore underflows when on simulation and fpga platform */
+#define ALL_UF_INT (0)
+#endif
+
 struct tegra_dc;
 
 struct tegra_dc_blend {
@@ -147,6 +159,23 @@ struct tegra_dc {
        struct delayed_work             one_shot_work;
 };
 
+#define print_mode_info(dc, mode) do {                                 \
+       trace_printk("%s:Mode settings: "                               \
+                       "ref_to_sync: H = %d V = %d, "                  \
+                       "sync_width: H = %d V = %d, "                   \
+                       "back_porch: H = %d V = %d, "                   \
+                       "active: H = %d V = %d, "                       \
+                       "front_porch: H = %d V = %d, "                  \
+                       "pclk = %d, stereo mode = %d\n",                \
+                       dc->ndev->name,                                 \
+                       mode.h_ref_to_sync, mode.v_ref_to_sync,         \
+                       mode.h_sync_width, mode.v_sync_width,           \
+                       mode.h_back_porch, mode.v_back_porch,           \
+                       mode.h_active, mode.v_active,                   \
+                       mode.h_front_porch, mode.v_front_porch,         \
+                       mode.pclk, mode.stereo_mode);                   \
+       } while (0)
+
 static inline void tegra_dc_io_start(struct tegra_dc *dc)
 {
        nvhost_module_busy_ext(nvhost_get_parent(dc->ndev));
@@ -290,11 +319,32 @@ static inline bool tegra_dc_is_yuv_planar(int fmt)
        return false;
 }
 
-static inline void tegra_dc_unmask_interrupt(struct tegra_dc *dc, u32 int_val);
-static inline void tegra_dc_mask_interrupt(struct tegra_dc *dc, u32 int_val);
-static bool tegra_dc_windows_are_dirty(struct tegra_dc *dc);
+static inline void tegra_dc_unmask_interrupt(struct tegra_dc *dc, u32 int_val)
+{
+       u32 val;
 
-void tegra_dc_setup_clk(struct tegra_dc *dc, struct clk *clk);
+       val = tegra_dc_readl(dc, DC_CMD_INT_MASK);
+       val |= int_val;
+       tegra_dc_writel(dc, val, DC_CMD_INT_MASK);
+}
+
+static inline void tegra_dc_mask_interrupt(struct tegra_dc *dc, u32 int_val)
+{
+       u32 val;
+
+       val = tegra_dc_readl(dc, DC_CMD_INT_MASK);
+       val &= ~int_val;
+       tegra_dc_writel(dc, val, DC_CMD_INT_MASK);
+}
+
+static inline unsigned long tegra_dc_clk_get_rate(struct tegra_dc *dc)
+{
+#ifdef CONFIG_TEGRA_SILICON_PLATFORM
+       return clk_get_rate(dc->clk);
+#else
+       return dc->mode.pclk;
+#endif
+}
 
 extern struct tegra_dc_out_ops tegra_dc_rgb_ops;
 extern struct tegra_dc_out_ops tegra_dc_hdmi_ops;
@@ -323,4 +373,24 @@ unsigned int tegra_dc_has_multiple_dc(void);
 void tegra_dc_clear_bandwidth(struct tegra_dc *dc);
 void tegra_dc_program_bandwidth(struct tegra_dc *dc, bool use_new);
 int tegra_dc_set_dynamic_emc(struct tegra_dc_win *windows[], int n);
+
+/* defined in mode.c, used in dc.c */
+int tegra_dc_program_mode(struct tegra_dc *dc, struct tegra_dc_mode *mode);
+int tegra_dc_calc_refresh(const struct tegra_dc_mode *m);
+
+/* defined in clock.c, used in dc.c, dsi.c and hdmi.c */
+void tegra_dc_setup_clk(struct tegra_dc *dc, struct clk *clk);
+unsigned long tegra_dc_pclk_round_rate(struct tegra_dc *dc, int pclk);
+
+/* defined in lut.c, used in dc.c */
+void tegra_dc_init_lut_defaults(struct tegra_dc_lut *lut);
+void tegra_dc_set_lut(struct tegra_dc *dc, struct tegra_dc_win *win);
+
+/* defined in csc.c, used in dc.c */
+void tegra_dc_init_csc_defaults(struct tegra_dc_csc *csc);
+void tegra_dc_set_csc(struct tegra_dc *dc, struct tegra_dc_csc *csc);
+
+/* defined in window.c, used in dc.c */
+void tegra_dc_trigger_windows(struct tegra_dc *dc);
+
 #endif
index 0b628fc..86b1029 100644 (file)
@@ -4,7 +4,7 @@
  * Copyright (C) 2010 Google, Inc.
  * Author: Erik Gilling <konkers@android.com>
  *
- * Copyright (C) 2010-2011 NVIDIA Corporation
+ * Copyright (c) 2010-2012, NVIDIA CORPORATION, All rights reserved.
  *
  * This software is licensed under the terms of the GNU General Public
  * License version 2, as published by the Free Software Foundation, and
index 0b259c3..bf27e96 100644 (file)
@@ -1,7 +1,7 @@
 /*
  * drivers/video/tegra/dc/dc_sysfs.c
  *
- * Copyright (c) 2011, NVIDIA Corporation.
+ * Copyright (c) 2011-2012, NVIDIA CORPORATION, All rights reserved.
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License as published by
index 3c00b31..7ee9375 100644 (file)
@@ -1,7 +1,7 @@
 /*
  * drivers/video/tegra/dc/dsi.c
  *
- * Copyright (c) 2011-2012, NVIDIA Corporation.
+ * Copyright (c) 2011-2012, NVIDIA CORPORATION, All rights reserved.
  *
  * This software is licensed under the terms of the GNU General Public
  * License version 2, as published by the Free Software Foundation, and
@@ -40,7 +40,7 @@
 #include "dsi_regs.h"
 #include "dsi.h"
 
-#define APB_MISC_GP_MIPI_PAD_CTRL_0    (TEGRA_APB_MISC_BASE + 0x820)
+#define APB_MISC_GP_MIPI_PAD_CTRL_0    (TEGRA_APB_MISC_BASE + 0x820)
 #define DSIB_MODE_ENABLE               0x2
 
 #define DSI_USE_SYNC_POINTS            1
@@ -1073,7 +1073,7 @@ static u32 tegra_dsi_sol_delay_burst(struct tegra_dc *dc,
        u32 dsi_to_pixel_clk_ratio;
        u32 temp;
        u32 temp1;
-       u32 mipi_clk_adj_kHz;
+       u32 mipi_clk_adj_kHz = 0;
        u32 sol_delay;
        struct tegra_dc_mode *dc_modes = &dc->mode;
 
index 18ea9c9..bf54913 100644 (file)
@@ -1,18 +1,18 @@
 /*
-  * drivers/video/tegra/dc/dsi.h
-  *
-  * Copyright (c) 2011, NVIDIA Corporation.
-  *
-  * This software is licensed under the terms of the GNU General Public
-  * License version 2, as published by the Free Software Foundation, and
-  * may be copied, distributed, and modified under those terms.
-  *
-  * This program is distributed in the hope that it will be useful,
-  * but WITHOUT ANY WARRANTY; without even the implied warranty of
-  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-  * GNU General Public License for more details.
-  *
-  */
+ * drivers/video/tegra/dc/dsi.h
+ *
+ * Copyright (c) 2011-2012, NVIDIA CORPORATION, All rights reserved.
+ *
+ * This software is licensed under the terms of the GNU General Public
+ * License version 2, as published by the Free Software Foundation, and
+ * may be copied, distributed, and modified under those terms.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ */
 
 #ifndef __DRIVERS_VIDEO_TEGRA_DC_DSI_H__
 #define __DRIVERS_VIDEO_TEGRA_DC_DSI_H__
index 203ac32..71045fc 100644 (file)
@@ -1,18 +1,18 @@
 /*
-  * drivers/video/tegra/dc/dsi_regs.h
-  *
-  * Copyright (c) 2011, NVIDIA Corporation.
-  *
-  * This software is licensed under the terms of the GNU General Public
-  * License version 2, as published by the Free Software Foundation, and
-  * may be copied, distributed, and modified under those terms.
-  *
-  * This program is distributed in the hope that it will be useful,
-  * but WITHOUT ANY WARRANTY; without even the implied warranty of
-  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-  * GNU General Public License for more details.
-  *
-  */
+ * drivers/video/tegra/dc/dsi_regs.h
+ *
+ * Copyright (c) 2011-2012, NVIDIA CORPORATION, All rights reserved.
+ *
+ * This software is licensed under the terms of the GNU General Public
+ * License version 2, as published by the Free Software Foundation, and
+ * may be copied, distributed, and modified under those terms.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ */
 
 #ifndef __DRIVERS_VIDEO_TEGRA_DC_DSI_REG_H__
 #define __DRIVERS_VIDEO_TEGRA_DC_DSI_REG_H__
index 8776c53..b1de7ab 100644 (file)
@@ -4,7 +4,7 @@
  * Copyright (C) 2010 Google, Inc.
  * Author: Erik Gilling <konkers@android.com>
  *
- * Copyright (C) 2010-2011 NVIDIA Corporation
+ * Copyright (c) 2010-2012, NVIDIA CORPORATION, All rights reserved.
  *
  * This software is licensed under the terms of the GNU General Public
  * License version 2, as published by the Free Software Foundation, and
index 9caf3e1..ed812be 100644 (file)
@@ -1,7 +1,7 @@
 /*
  * drivers/video/tegra/dc/ext/control.c
  *
- * Copyright (C) 2011, NVIDIA Corporation
+ * Copyright (c) 2011-2012, NVIDIA CORPORATION, All rights reserved.
  *
  * Author: Robert Morell <rmorell@nvidia.com>
  *
@@ -67,7 +67,7 @@ static int get_output_edid(struct tegra_dc_ext_control_output_edid *edid)
        struct tegra_dc *dc;
        size_t user_size = edid->size;
        struct tegra_dc_edid *dc_edid = NULL;
-       int ret;
+       int ret = 0;
 
        /* TODO: this should be more dynamic */
        if (edid->handle > 2)
@@ -262,10 +262,7 @@ int tegra_dc_ext_control_init(void)
                return ret;
 
        control->dev = device_create(tegra_dc_ext_class,
-                                    NULL,
-                                    tegra_dc_ext_devno,
-                                    NULL,
-                                    "tegra_dc_ctrl");
+            NULL, tegra_dc_ext_devno, NULL, "tegra_dc_ctrl");
        if (IS_ERR(control->dev)) {
                ret = PTR_ERR(control->dev);
                cdev_del(&control->cdev);
index d8fa5fd..970f38f 100644 (file)
@@ -1,7 +1,7 @@
 /*
  * drivers/video/tegra/dc/ext/cursor.c
  *
- * Copyright (C) 2011, NVIDIA Corporation
+ * Copyright (c) 2011-2012, NVIDIA CORPORATION, All rights reserved.
  *
  * Author: Robert Morell <rmorell@nvidia.com>
  *
index a8de7a7..f9c76f8 100644 (file)
@@ -1,7 +1,7 @@
 /*
  * drivers/video/tegra/dc/dev.c
  *
- * Copyright (C) 2011-2012, NVIDIA Corporation
+ * Copyright (c) 2011-2012, NVIDIA CORPORATION, All rights reserved.
  *
  * Author: Robert Morell <rmorell@nvidia.com>
  * Some code based on fbdev extensions written by:
@@ -447,7 +447,7 @@ static int tegra_dc_ext_flip(struct tegra_dc_ext_user *user,
 {
        struct tegra_dc_ext *ext = user->ext;
        struct tegra_dc_ext_flip_data *data;
-       int work_index;
+       int work_index = -1;
        int i, ret = 0;
 
 #ifdef CONFIG_ANDROID
@@ -559,6 +559,10 @@ static int tegra_dc_ext_flip(struct tegra_dc_ext_user *user,
 
                atomic_inc(&ext->win[work_index].nr_pending_flips);
        }
+       if (work_index < 0) {
+               ret = -EINVAL;
+               goto unlock;
+       }
        queue_work(ext->win[work_index].flip_wq, &data->work);
 
        unlock_windows_for_flip(user, args);
index 150a150..577d056 100644 (file)
@@ -1,7 +1,7 @@
 /*
  * drivers/video/tegra/dc/ext/events.c
  *
- * Copyright (C) 2011, NVIDIA Corporation
+ * Copyright (c) 2011-2012, NVIDIA CORPORATION, All rights reserved.
  *
  * Author: Robert Morell <rmorell@nvidia.com>
  *
index 2a0c549..f68c7d5 100644 (file)
@@ -1,7 +1,7 @@
 /*
  * drivers/video/tegra/dc/ext/tegra_dc_ext_priv.h
  *
- * Copyright (C) 2011, NVIDIA Corporation
+ * Copyright (c) 2011-2012, NVIDIA CORPORATION, All rights reserved.
  *
  * Author: Robert Morell <rmorell@nvidia.com>
  *
index cede642..bd8b3c0 100644 (file)
@@ -1,7 +1,7 @@
 /*
  * drivers/video/tegra/dc/ext/util.c
  *
- * Copyright (C) 2011, NVIDIA Corporation
+ * Copyright (c) 2011-2012, NVIDIA CORPORATION, All rights reserved.
  *
  * Author: Robert Morell <rmorell@nvidia.com>
  *
index 3cd8de5..378fd8b 100644 (file)
@@ -4,7 +4,7 @@
  * Copyright (C) 2010 Google, Inc.
  * Author: Erik Gilling <konkers@android.com>
  *
- * Copyright (C) 2010-2011 NVIDIA Corporation
+ * Copyright (c) 2010-2012, NVIDIA CORPORATION, All rights reserved.
  *
  * This software is licensed under the terms of the GNU General Public
  * License version 2, as published by the Free Software Foundation, and
index 702ab16..5b4c42a 100644 (file)
@@ -6,7 +6,7 @@
  * Copyright (C) 2010 Google, Inc.
  * Author: Erik Gilling <konkers@android.com>
  *
- * Copyright (C) 2010-2011 NVIDIA Corporation
+ * Copyright (c) 2010-2012, NVIDIA CORPORATION, All rights reserved.
  *
  * This software is licensed under the terms of the GNU General Public
  * License version 2, as published by the Free Software Foundation, and
index 0bdda43..4a5fdcb 100644 (file)
@@ -4,6 +4,8 @@
  * Copyright (C) 2010 Google, Inc.
  * Author: Erik Gilling <konkers@android.com>
  *
+ * Copyright (c) 2010-2012, NVIDIA CORPORATION, All rights reserved.
+ *
  * This software is licensed under the terms of the GNU General Public
  * License version 2, as published by the Free Software Foundation, and
  * may be copied, distributed, and modified under those terms.
diff --git a/drivers/video/tegra/dc/lut.c b/drivers/video/tegra/dc/lut.c
new file mode 100644 (file)
index 0000000..7ce8fc6
--- /dev/null
@@ -0,0 +1,130 @@
+/*
+ * drivers/video/tegra/dc/lut.c
+ *
+ * Copyright (c) 2010-2012, NVIDIA CORPORATION, All rights reserved.
+ *
+ * This software is licensed under the terms of the GNU General Public
+ * License version 2, as published by the Free Software Foundation, and
+ * may be copied, distributed, and modified under those terms.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ */
+
+#include <linux/err.h>
+#include <linux/types.h>
+#include <mach/dc.h>
+
+#include "dc_reg.h"
+#include "dc_priv.h"
+
+void tegra_dc_init_lut_defaults(struct tegra_dc_lut *lut)
+{
+       int i;
+       for (i = 0; i < 256; i++)
+               lut->r[i] = lut->g[i] = lut->b[i] = (u8)i;
+}
+
+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))
+{
+       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 int tegra_dc_lut_isdefaults_lambda(struct tegra_dc *dc, int i, u32 rgb)
+{
+       if (rgb != (i | (i<<8) | (i<<16)))
+               return 0;
+       return 1;
+}
+
+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;
+}
+
+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);
+
+       tegra_dc_loop_lut(dc, win, tegra_dc_set_lut_setreg_lambda);
+
+       if (win->ppflags & TEGRA_WIN_PPFLAG_CP_ENABLE)
+               val |= CP_ENABLE;
+       else
+               val &= ~CP_ENABLE;
+
+       tegra_dc_writel(dc, val, DC_WIN_WIN_OPTIONS);
+}
+
+static int tegra_dc_update_winlut(struct tegra_dc *dc, int win_idx, int fbovr)
+{
+       struct tegra_dc_win *win = &dc->windows[win_idx];
+
+       mutex_lock(&dc->lock);
+
+       if (!dc->enabled) {
+               mutex_unlock(&dc->lock);
+               return -EFAULT;
+       }
+
+       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;
+
+       tegra_dc_writel(dc, WINDOW_A_SELECT << win_idx,
+                       DC_CMD_DISPLAY_WINDOW_HEADER);
+
+       tegra_dc_set_lut(dc, win);
+
+       mutex_unlock(&dc->lock);
+
+       tegra_dc_update_windows(&win, 1);
+
+       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);
+
diff --git a/drivers/video/tegra/dc/mode.c b/drivers/video/tegra/dc/mode.c
new file mode 100644 (file)
index 0000000..3359b2a
--- /dev/null
@@ -0,0 +1,318 @@
+/*
+ * drivers/video/tegra/dc/mode.c
+ *
+ * Copyright (C) 2010 Google, Inc.
+ *
+ * Copyright (c) 2010-2012, NVIDIA CORPORATION, All rights reserved.
+ *
+ * This software is licensed under the terms of the GNU General Public
+ * License version 2, as published by the Free Software Foundation, and
+ * may be copied, distributed, and modified under those terms.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ */
+
+#include <linux/err.h>
+#include <linux/types.h>
+#include <linux/clk.h>
+
+#include <mach/clk.h>
+#include <mach/dc.h>
+
+#include "dc_reg.h"
+#include "dc_priv.h"
+
+/* return non-zero if constraint is violated */
+static int calc_h_ref_to_sync(const struct tegra_dc_mode *mode, int *href)
+{
+       long a, b;
+
+       /* Constraint 5: H_REF_TO_SYNC >= 0 */
+       a = 0;
+
+       /* Constraint 6: H_FRONT_PORT >= (H_REF_TO_SYNC + 1) */
+       b = mode->h_front_porch - 1;
+
+       /* Constraint 1: H_REF_TO_SYNC + H_SYNC_WIDTH + H_BACK_PORCH > 11 */
+       if (a + mode->h_sync_width + mode->h_back_porch <= 11)
+               a = 1 + 11 - mode->h_sync_width - mode->h_back_porch;
+       /* check Constraint 1 and 6 */
+       if (a > b)
+               return 1;
+
+       /* Constraint 4: H_SYNC_WIDTH >= 1 */
+       if (mode->h_sync_width < 1)
+               return 4;
+
+       /* Constraint 7: H_DISP_ACTIVE >= 16 */
+       if (mode->h_active < 16)
+               return 7;
+
+       if (href) {
+               if (b > a && a % 2)
+                       *href = a + 1; /* use smallest even value */
+               else
+                       *href = a; /* even or only possible value */
+       }
+
+       return 0;
+}
+
+static int calc_v_ref_to_sync(const struct tegra_dc_mode *mode, int *vref)
+{
+       long a;
+       a = 1; /* Constraint 5: V_REF_TO_SYNC >= 1 */
+
+       /* Constraint 2: V_REF_TO_SYNC + V_SYNC_WIDTH + V_BACK_PORCH > 1 */
+       if (a + mode->v_sync_width + mode->v_back_porch <= 1)
+               a = 1 + 1 - mode->v_sync_width - mode->v_back_porch;
+
+       /* Constraint 6 */
+       if (mode->v_front_porch < a + 1)
+               a = mode->v_front_porch - 1;
+
+       /* Constraint 4: V_SYNC_WIDTH >= 1 */
+       if (mode->v_sync_width < 1)
+               return 4;
+
+       /* Constraint 7: V_DISP_ACTIVE >= 16 */
+       if (mode->v_active < 16)
+               return 7;
+
+       if (vref)
+               *vref = a;
+       return 0;
+}
+
+static int calc_ref_to_sync(struct tegra_dc_mode *mode)
+{
+       int ret;
+       ret = calc_h_ref_to_sync(mode, &mode->h_ref_to_sync);
+       if (ret)
+               return ret;
+       ret = calc_v_ref_to_sync(mode, &mode->v_ref_to_sync);
+       if (ret)
+               return ret;
+
+       return 0;
+}
+
+static bool check_ref_to_sync(struct tegra_dc_mode *mode)
+{
+       /* Constraint 1: H_REF_TO_SYNC + H_SYNC_WIDTH + H_BACK_PORCH > 11. */
+       if (mode->h_ref_to_sync + mode->h_sync_width + mode->h_back_porch <= 11)
+               return false;
+
+       /* Constraint 2: V_REF_TO_SYNC + V_SYNC_WIDTH + V_BACK_PORCH > 1. */
+       if (mode->v_ref_to_sync + mode->v_sync_width + mode->v_back_porch <= 1)
+               return false;
+
+       /* Constraint 3: V_FRONT_PORCH + V_SYNC_WIDTH + V_BACK_PORCH > 1
+        * (vertical blank). */
+       if (mode->v_front_porch + mode->v_sync_width + mode->v_back_porch <= 1)
+               return false;
+
+       /* Constraint 4: V_SYNC_WIDTH >= 1; H_SYNC_WIDTH >= 1. */
+       if (mode->v_sync_width < 1 || mode->h_sync_width < 1)
+               return false;
+
+       /* Constraint 5: V_REF_TO_SYNC >= 1; H_REF_TO_SYNC >= 0. */
+       if (mode->v_ref_to_sync < 1 || mode->h_ref_to_sync < 0)
+               return false;
+
+       /* Constraint 6: V_FRONT_PORT >= (V_REF_TO_SYNC + 1);
+        * H_FRONT_PORT >= (H_REF_TO_SYNC + 1). */
+       if (mode->v_front_porch < mode->v_ref_to_sync + 1 ||
+               mode->h_front_porch < mode->h_ref_to_sync + 1)
+               return false;
+
+       /* Constraint 7: H_DISP_ACTIVE >= 16; V_DISP_ACTIVE >= 16. */
+       if (mode->h_active < 16 || mode->v_active < 16)
+               return false;
+
+       return true;
+}
+
+/* return in 1000ths of a Hertz */
+int tegra_dc_calc_refresh(const struct tegra_dc_mode *m)
+{
+       long h_total, v_total, refresh;
+       h_total = m->h_active + m->h_front_porch + m->h_back_porch +
+               m->h_sync_width;
+       v_total = m->v_active + m->v_front_porch + m->v_back_porch +
+               m->v_sync_width;
+       refresh = m->pclk / h_total;
+       refresh *= 1000;
+       refresh /= v_total;
+       return refresh;
+}
+
+#ifdef DEBUG
+static void print_mode(struct tegra_dc *dc,
+                       const struct tegra_dc_mode *mode, const char *note)
+{
+       if (mode) {
+               int refresh = tegra_dc_calc_refresh(dc, mode);
+               dev_info(&dc->ndev->dev, "%s():MODE:%dx%d@%d.%03uHz pclk=%d\n",
+                       note ? note : "",
+                       mode->h_active, mode->v_active,
+                       refresh / 1000, refresh % 1000,
+                       mode->pclk);
+       }
+}
+#else /* !DEBUG */
+static inline void print_mode(struct tegra_dc *dc,
+                       const struct tegra_dc_mode *mode, const char *note) { }
+#endif /* DEBUG */
+
+int tegra_dc_program_mode(struct tegra_dc *dc, struct tegra_dc_mode *mode)
+{
+       unsigned long val;
+       unsigned long rate;
+       unsigned long div;
+       unsigned long pclk;
+
+       print_mode(dc, mode, __func__);
+
+       /* use default EMC rate when switching modes */
+       dc->new_emc_clk_rate = tegra_dc_get_default_emc_clk_rate(dc);
+       tegra_dc_program_bandwidth(dc, true);
+
+       tegra_dc_writel(dc, 0x0, DC_DISP_DISP_TIMING_OPTIONS);
+       tegra_dc_writel(dc, mode->h_ref_to_sync | (mode->v_ref_to_sync << 16),
+                       DC_DISP_REF_TO_SYNC);
+       tegra_dc_writel(dc, mode->h_sync_width | (mode->v_sync_width << 16),
+                       DC_DISP_SYNC_WIDTH);
+       tegra_dc_writel(dc, mode->h_back_porch | (mode->v_back_porch << 16),
+                       DC_DISP_BACK_PORCH);
+       tegra_dc_writel(dc, mode->h_active | (mode->v_active << 16),
+                       DC_DISP_DISP_ACTIVE);
+       tegra_dc_writel(dc, mode->h_front_porch | (mode->v_front_porch << 16),
+                       DC_DISP_FRONT_PORCH);
+
+       tegra_dc_writel(dc, DE_SELECT_ACTIVE | DE_CONTROL_NORMAL,
+                       DC_DISP_DATA_ENABLE_OPTIONS);
+
+       /* TODO: MIPI/CRT/HDMI clock cals */
+
+       val = DISP_DATA_FORMAT_DF1P1C;
+
+       if (dc->out->align == TEGRA_DC_ALIGN_MSB)
+               val |= DISP_DATA_ALIGNMENT_MSB;
+       else
+               val |= DISP_DATA_ALIGNMENT_LSB;
+
+       if (dc->out->order == TEGRA_DC_ORDER_RED_BLUE)
+               val |= DISP_DATA_ORDER_RED_BLUE;
+       else
+               val |= DISP_DATA_ORDER_BLUE_RED;
+
+       tegra_dc_writel(dc, val, DC_DISP_DISP_INTERFACE_CONTROL);
+
+       rate = tegra_dc_clk_get_rate(dc);
+
+       pclk = tegra_dc_pclk_round_rate(dc, mode->pclk);
+       trace_printk("%s:pclk=%ld\n", dc->ndev->name, pclk);
+       if (pclk < (mode->pclk / 100 * 99) ||
+           pclk > (mode->pclk / 100 * 109)) {
+               dev_err(&dc->ndev->dev,
+                       "can't divide %ld clock to %d -1/+9%% %ld %d %d\n",
+                       rate, mode->pclk,
+                       pclk, (mode->pclk / 100 * 99),
+                       (mode->pclk / 100 * 109));
+               return -EINVAL;
+       }
+
+       div = (rate * 2 / pclk) - 2;
+       trace_printk("%s:div=%ld\n", dc->ndev->name, div);
+
+       tegra_dc_writel(dc, 0x00010001,
+                       DC_DISP_SHIFT_CLOCK_OPTIONS);
+       tegra_dc_writel(dc, PIXEL_CLK_DIVIDER_PCD1 | SHIFT_CLK_DIVIDER(div),
+                       DC_DISP_DISP_CLOCK_CONTROL);
+
+#ifdef CONFIG_SWITCH
+       switch_set_state(&dc->modeset_switch,
+                        (mode->h_active << 16) | mode->v_active);
+#endif
+
+       tegra_dc_writel(dc, GENERAL_UPDATE, DC_CMD_STATE_CONTROL);
+       tegra_dc_writel(dc, GENERAL_ACT_REQ, DC_CMD_STATE_CONTROL);
+
+       print_mode_info(dc, dc->mode);
+       return 0;
+}
+
+int tegra_dc_set_mode(struct tegra_dc *dc, const struct tegra_dc_mode *mode)
+{
+       memcpy(&dc->mode, mode, sizeof(dc->mode));
+
+       print_mode(dc, mode, __func__);
+
+       return 0;
+}
+EXPORT_SYMBOL(tegra_dc_set_mode);
+
+int tegra_dc_set_fb_mode(struct tegra_dc *dc,
+               const struct fb_videomode *fbmode, bool stereo_mode)
+{
+       struct tegra_dc_mode mode;
+
+       if (!fbmode->pixclock)
+               return -EINVAL;
+
+       mode.pclk = PICOS2KHZ(fbmode->pixclock) * 1000;
+       mode.h_sync_width = fbmode->hsync_len;
+       mode.v_sync_width = fbmode->vsync_len;
+       mode.h_back_porch = fbmode->left_margin;
+       mode.v_back_porch = fbmode->upper_margin;
+       mode.h_active = fbmode->xres;
+       mode.v_active = fbmode->yres;
+       mode.h_front_porch = fbmode->right_margin;
+       mode.v_front_porch = fbmode->lower_margin;
+       mode.stereo_mode = stereo_mode;
+       if (dc->out->type == TEGRA_DC_OUT_HDMI) {
+               /* HDMI controller requires h_ref=1, v_ref=1 */
+               mode.h_ref_to_sync = 1;
+               mode.v_ref_to_sync = 1;
+       } else {
+               calc_ref_to_sync(&mode);
+       }
+       if (!check_ref_to_sync(&mode)) {
+               dev_err(&dc->ndev->dev,
+                               "Display timing doesn't meet restrictions.\n");
+               return -EINVAL;
+       }
+       dev_info(&dc->ndev->dev, "Using mode %dx%d pclk=%d href=%d vref=%d\n",
+               mode.h_active, mode.v_active, mode.pclk,
+               mode.h_ref_to_sync, mode.v_ref_to_sync
+       );
+
+#ifndef CONFIG_TEGRA_HDMI_74MHZ_LIMIT
+       /* Double the pixel clock and update v_active only for
+        * frame packed mode */
+       if (mode.stereo_mode) {
+               mode.pclk *= 2;
+               /* total v_active = yres*2 + activespace */
+               mode.v_active = fbmode->yres * 2 +
+                               fbmode->vsync_len +
+                               fbmode->upper_margin +
+                               fbmode->lower_margin;
+       }
+#endif
+
+       mode.flags = 0;
+
+       if (!(fbmode->sync & FB_SYNC_HOR_HIGH_ACT))
+               mode.flags |= TEGRA_DC_MODE_FLAG_NEG_H_SYNC;
+
+       if (!(fbmode->sync & FB_SYNC_VERT_HIGH_ACT))
+               mode.flags |= TEGRA_DC_MODE_FLAG_NEG_V_SYNC;
+
+       return tegra_dc_set_mode(dc, &mode);
+}
+EXPORT_SYMBOL(tegra_dc_set_fb_mode);
index 263de07..3566e2b 100644 (file)
@@ -1,7 +1,7 @@
 /*
  * drivers/video/tegra/dc/nvhdcp.c
  *
- * Copyright (c) 2010-2011, NVIDIA Corporation.
+ * Copyright (c) 2010-2012, NVIDIA CORPORATION, All rights reserved.
  *
  * This software is licensed under the terms of the GNU General Public
  * License version 2, as published by the Free Software Foundation, and
index 90ea0be..ce4c7f8 100644 (file)
@@ -1,7 +1,7 @@
 /*
  * drivers/video/tegra/dc/nvhdcp.h
  *
- * Copyright (c) 2010-2011, NVIDIA Corporation.
+ * Copyright (c) 2010-2012, NVIDIA CORPORATION, All rights reserved.
  *
  * This software is licensed under the terms of the GNU General Public
  * License version 2, as published by the Free Software Foundation, and
index 860dd8d..e3058b5 100644 (file)
@@ -1,7 +1,7 @@
 /*
  * drivers/video/tegra/dc/nvsd.c
  *
- * Copyright (c) 2010-2012, NVIDIA Corporation.
+ * Copyright (c) 2010-2012, NVIDIA CORPORATION, All rights reserved.
  *
  * This software is licensed under the terms of the GNU General Public
  * License version 2, as published by the Free Software Foundation, and
index f7fc4a1..d6f9dc1 100644 (file)
@@ -1,7 +1,7 @@
 /*
  * drivers/video/tegra/dc/nvsd.h
  *
- * Copyright (c) 2010-2011, NVIDIA Corporation.
+ * Copyright (c) 2010-2012, NVIDIA CORPORATION, All rights reserved.
  *
  * This software is licensed under the terms of the GNU General Public
  * License version 2, as published by the Free Software Foundation, and
index 47d4e69..b4097d9 100644 (file)
@@ -4,6 +4,8 @@
  * Copyright (C) 2010 Google, Inc.
  * Author: Erik Gilling <konkers@android.com>
  *
+ * Copyright (c) 2010-2012, NVIDIA CORPORATION, All rights reserved.
+ *
  * This software is licensed under the terms of the GNU General Public
  * License version 2, as published by the Free Software Foundation, and
  * may be copied, distributed, and modified under those terms.
diff --git a/drivers/video/tegra/dc/window.c b/drivers/video/tegra/dc/window.c
new file mode 100644 (file)
index 0000000..5161dd4
--- /dev/null
@@ -0,0 +1,466 @@
+/*
+ * drivers/video/tegra/dc/window.c
+ *
+ * Copyright (C) 2010 Google, Inc.
+ *
+ * Copyright (c) 2010-2012, NVIDIA CORPORATION, All rights reserved.
+ *
+ * This software is licensed under the terms of the GNU General Public
+ * License version 2, as published by the Free Software Foundation, and
+ * may be copied, distributed, and modified under those terms.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ */
+#include <linux/err.h>
+#include <linux/types.h>
+#include <mach/dc.h>
+
+#include "dc_reg.h"
+#include "dc_config.h"
+#include "dc_priv.h"
+
+static int no_vsync;
+
+module_param_named(no_vsync, no_vsync, int, S_IRUGO | S_IWUSR);
+
+static bool tegra_dc_windows_are_clean(struct tegra_dc_win *windows[],
+                                            int n)
+{
+       int i;
+
+       for (i = 0; i < n; i++) {
+               if (windows[i]->dirty)
+                       return false;
+       }
+
+       return true;
+}
+
+static int get_topmost_window(u32 *depths, unsigned long *wins)
+{
+       int idx, best = -1;
+
+       for_each_set_bit(idx, wins, DC_N_WINDOWS) {
+               if (best == -1 || depths[idx] < depths[best])
+                       best = idx;
+       }
+       clear_bit(best, wins);
+       return best;
+}
+
+static u32 blend_topwin(u32 flags)
+{
+       if (flags & TEGRA_WIN_FLAG_BLEND_COVERAGE)
+               return BLEND(NOKEY, ALPHA, 0xff, 0xff);
+       else if (flags & TEGRA_WIN_FLAG_BLEND_PREMULT)
+               return BLEND(NOKEY, PREMULT, 0xff, 0xff);
+       else
+               return BLEND(NOKEY, FIX, 0xff, 0xff);
+}
+
+static u32 blend_2win(int idx, unsigned long behind_mask, u32* flags, int xy)
+{
+       int other;
+
+       for (other = 0; other < DC_N_WINDOWS; other++) {
+               if (other != idx && (xy-- == 0))
+                       break;
+       }
+       if (BIT(other) & behind_mask)
+               return blend_topwin(flags[idx]);
+       else if (flags[other])
+               return BLEND(NOKEY, DEPENDANT, 0x00, 0x00);
+       else
+               return BLEND(NOKEY, FIX, 0x00, 0x00);
+}
+
+static u32 blend_3win(int idx, unsigned long behind_mask, u32* flags)
+{
+       unsigned long infront_mask;
+       int first;
+
+       infront_mask = ~(behind_mask | BIT(idx));
+       infront_mask &= (BIT(DC_N_WINDOWS) - 1);
+       first = ffs(infront_mask) - 1;
+
+       if (!infront_mask)
+               return blend_topwin(flags[idx]);
+       else if (behind_mask && first != -1 && flags[first])
+               return BLEND(NOKEY, DEPENDANT, 0x00, 0x00);
+       else
+               return BLEND(NOKEY, FIX, 0x0, 0x0);
+}
+
+static void tegra_dc_set_blending(struct tegra_dc *dc,
+       struct tegra_dc_blend *blend)
+{
+       unsigned long mask = BIT(DC_N_WINDOWS) - 1;
+
+       while (mask) {
+               int idx = get_topmost_window(blend->z, &mask);
+
+               tegra_dc_writel(dc, WINDOW_A_SELECT << idx,
+                               DC_CMD_DISPLAY_WINDOW_HEADER);
+               tegra_dc_writel(dc, BLEND(NOKEY, FIX, 0xff, 0xff),
+                               DC_WIN_BLEND_NOKEY);
+               tegra_dc_writel(dc, BLEND(NOKEY, FIX, 0xff, 0xff),
+                               DC_WIN_BLEND_1WIN);
+               tegra_dc_writel(dc, blend_2win(idx, mask, blend->flags, 0),
+                               DC_WIN_BLEND_2WIN_X);
+               tegra_dc_writel(dc, blend_2win(idx, mask, blend->flags, 1),
+                               DC_WIN_BLEND_2WIN_Y);
+               tegra_dc_writel(dc, blend_3win(idx, mask, blend->flags),
+                               DC_WIN_BLEND_3WIN_XY);
+       }
+}
+
+/* does not support syncing windows on multiple dcs in one call */
+int tegra_dc_sync_windows(struct tegra_dc_win *windows[], int n)
+{
+       int ret;
+       if (n < 1 || n > DC_N_WINDOWS)
+               return -EINVAL;
+
+       if (!windows[0]->dc->enabled)
+               return -EFAULT;
+
+#ifdef CONFIG_TEGRA_SIMULATION_PLATFORM
+       /* Don't want to timeout on simulator */
+       ret = wait_event_interruptible(windows[0]->dc->wq,
+               tegra_dc_windows_are_clean(windows, n));
+#else
+       trace_printk("%s:Before wait_event_interruptible_timeout\n",
+               windows[0]->dc->ndev->name);
+       ret = wait_event_interruptible_timeout(windows[0]->dc->wq,
+               tegra_dc_windows_are_clean(windows, n),
+               HZ);
+       trace_printk("%s:After wait_event_interruptible_timeout\n",
+               windows[0]->dc->ndev->name);
+#endif
+       return ret;
+}
+EXPORT_SYMBOL(tegra_dc_sync_windows);
+
+static inline u32 compute_dda_inc(fixed20_12 in, unsigned out_int,
+                                 bool v, unsigned Bpp)
+{
+       /*
+        * min(round((prescaled_size_in_pixels - 1) * 0x1000 /
+        *           (post_scaled_size_in_pixels - 1)), MAX)
+        * Where the value of MAX is as follows:
+        * For V_DDA_INCREMENT: 15.0 (0xF000)
+        * For H_DDA_INCREMENT:  4.0 (0x4000) for 4 Bytes/pix formats.
+        *                       8.0 (0x8000) for 2 Bytes/pix formats.
+        */
+
+       fixed20_12 out = dfixed_init(out_int);
+       u32 dda_inc;
+       int max;
+
+       if (v) {
+               max = 15;
+       } else {
+               switch (Bpp) {
+               default:
+                       WARN_ON_ONCE(1);
+                       /* fallthrough */
+               case 4:
+                       max = 4;
+                       break;
+               case 2:
+                       max = 8;
+                       break;
+               }
+       }
+
+       out.full = max_t(u32, out.full - dfixed_const(1), dfixed_const(1));
+       in.full -= dfixed_const(1);
+
+       dda_inc = dfixed_div(in, out);
+
+       dda_inc = min_t(u32, dda_inc, dfixed_const(max));
+
+       return dda_inc;
+}
+
+static inline u32 compute_initial_dda(fixed20_12 in)
+{
+       return dfixed_frac(in);
+}
+
+/* does not support updating windows on multiple dcs in one call */
+int tegra_dc_update_windows(struct tegra_dc_win *windows[], int n)
+{
+       struct tegra_dc *dc;
+       unsigned long update_mask = GENERAL_ACT_REQ;
+       unsigned long val;
+       bool update_blend = false;
+       int i;
+
+       dc = windows[0]->dc;
+
+       if (dc->out->flags & TEGRA_DC_OUT_ONE_SHOT_MODE) {
+               /* Acquire one_shot_lock to avoid race condition between
+                * cancellation of old delayed work and schedule of new
+                * delayed work. */
+               mutex_lock(&dc->one_shot_lock);
+               cancel_delayed_work_sync(&dc->one_shot_work);
+       }
+       mutex_lock(&dc->lock);
+
+       if (!dc->enabled) {
+               mutex_unlock(&dc->lock);
+               if (dc->out->flags & TEGRA_DC_OUT_ONE_SHOT_MODE)
+                       mutex_unlock(&dc->one_shot_lock);
+               return -EFAULT;
+       }
+
+       if (dc->out->flags & TEGRA_DC_OUT_ONE_SHOT_LP_MODE)
+               tegra_dc_host_resume(dc);
+
+       if (no_vsync)
+               tegra_dc_writel(dc, WRITE_MUX_ACTIVE | READ_MUX_ACTIVE,
+                       DC_CMD_STATE_ACCESS);
+       else
+               tegra_dc_writel(dc, WRITE_MUX_ASSEMBLY | READ_MUX_ASSEMBLY,
+                       DC_CMD_STATE_ACCESS);
+
+       for (i = 0; i < n; i++) {
+               struct tegra_dc_win *win = windows[i];
+               unsigned h_dda;
+               unsigned v_dda;
+               fixed20_12 h_offset, v_offset;
+               bool invert_h = (win->flags & TEGRA_WIN_FLAG_INVERT_H) != 0;
+               bool invert_v = (win->flags & TEGRA_WIN_FLAG_INVERT_V) != 0;
+               bool yuv = tegra_dc_is_yuv(win->fmt);
+               bool yuvp = tegra_dc_is_yuv_planar(win->fmt);
+               unsigned Bpp = tegra_dc_fmt_bpp(win->fmt) / 8;
+               /* Bytes per pixel of bandwidth, used for dda_inc calculation */
+               unsigned Bpp_bw = Bpp * (yuvp ? 2 : 1);
+               const bool filter_h = win_use_h_filter(dc, win);
+               const bool filter_v = win_use_v_filter(dc, win);
+
+               if (win->z != dc->blend.z[win->idx]) {
+                       dc->blend.z[win->idx] = win->z;
+                       update_blend = true;
+               }
+               if ((win->flags & TEGRA_WIN_BLEND_FLAGS_MASK) !=
+                       dc->blend.flags[win->idx]) {
+                       dc->blend.flags[win->idx] =
+                               win->flags & TEGRA_WIN_BLEND_FLAGS_MASK;
+                       update_blend = true;
+               }
+
+               tegra_dc_writel(dc, WINDOW_A_SELECT << win->idx,
+                               DC_CMD_DISPLAY_WINDOW_HEADER);
+
+               if (!no_vsync)
+                       update_mask |= WIN_A_ACT_REQ << win->idx;
+
+               if (!WIN_IS_ENABLED(win)) {
+                       dc->windows[i].dirty = 1;
+                       tegra_dc_writel(dc, 0, DC_WIN_WIN_OPTIONS);
+                       continue;
+               }
+
+               tegra_dc_writel(dc, win->fmt & 0x1f, DC_WIN_COLOR_DEPTH);
+               tegra_dc_writel(dc, win->fmt >> 6, DC_WIN_BYTE_SWAP);
+
+               tegra_dc_writel(dc,
+                       V_POSITION(win->out_y) | H_POSITION(win->out_x),
+                       DC_WIN_POSITION);
+               tegra_dc_writel(dc,
+                       V_SIZE(win->out_h) | H_SIZE(win->out_w),
+                       DC_WIN_SIZE);
+
+               if (tegra_dc_feature_has_scaling(dc, win->idx)) {
+                       tegra_dc_writel(dc,
+                               V_PRESCALED_SIZE(dfixed_trunc(win->h)) |
+                               H_PRESCALED_SIZE(dfixed_trunc(win->w) * Bpp),
+                               DC_WIN_PRESCALED_SIZE);
+
+                       h_dda = compute_dda_inc(win->w, win->out_w, false,
+                               Bpp_bw);
+                       v_dda = compute_dda_inc(win->h, win->out_h, true,
+                               Bpp_bw);
+                       tegra_dc_writel(dc, V_DDA_INC(v_dda) |
+                               H_DDA_INC(h_dda), DC_WIN_DDA_INCREMENT);
+                       h_dda = compute_initial_dda(win->x);
+                       v_dda = compute_initial_dda(win->y);
+                       tegra_dc_writel(dc, h_dda, DC_WIN_H_INITIAL_DDA);
+                       tegra_dc_writel(dc, v_dda, DC_WIN_V_INITIAL_DDA);
+               }
+
+               tegra_dc_writel(dc, 0, DC_WIN_BUF_STRIDE);
+               tegra_dc_writel(dc, 0, DC_WIN_UV_BUF_STRIDE);
+               tegra_dc_writel(dc, (unsigned long)win->phys_addr,
+                       DC_WINBUF_START_ADDR);
+
+               if (!yuvp) {
+                       tegra_dc_writel(dc, win->stride, DC_WIN_LINE_STRIDE);
+               } else {
+                       tegra_dc_writel(dc,
+                               (unsigned long)win->phys_addr_u,
+                               DC_WINBUF_START_ADDR_U);
+                       tegra_dc_writel(dc,
+                               (unsigned long)win->phys_addr_v,
+                               DC_WINBUF_START_ADDR_V);
+                       tegra_dc_writel(dc,
+                               LINE_STRIDE(win->stride) |
+                               UV_LINE_STRIDE(win->stride_uv),
+                               DC_WIN_LINE_STRIDE);
+               }
+
+               h_offset = win->x;
+               if (invert_h) {
+                       h_offset.full += win->w.full - dfixed_const(1);
+               }
+
+               v_offset = win->y;
+               if (invert_v) {
+                       v_offset.full += win->h.full - dfixed_const(1);
+               }
+
+               tegra_dc_writel(dc, dfixed_trunc(h_offset) * Bpp,
+                               DC_WINBUF_ADDR_H_OFFSET);
+               tegra_dc_writel(dc, dfixed_trunc(v_offset),
+                               DC_WINBUF_ADDR_V_OFFSET);
+
+               if (tegra_dc_feature_has_tiling(dc, win->idx)) {
+                       if (WIN_IS_TILED(win))
+                               tegra_dc_writel(dc,
+                                       DC_WIN_BUFFER_ADDR_MODE_TILE |
+                                       DC_WIN_BUFFER_ADDR_MODE_TILE_UV,
+                                       DC_WIN_BUFFER_ADDR_MODE);
+                       else
+                               tegra_dc_writel(dc,
+                                       DC_WIN_BUFFER_ADDR_MODE_LINEAR |
+                                       DC_WIN_BUFFER_ADDR_MODE_LINEAR_UV,
+                                       DC_WIN_BUFFER_ADDR_MODE);
+               }
+
+               val = WIN_ENABLE;
+               if (yuv)
+                       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)
+                       val |= V_FILTER_ENABLE;
+
+               if (invert_h)
+                       val |= H_DIRECTION_DECREMENT;
+               if (invert_v)
+                       val |= V_DIRECTION_DECREMENT;
+
+               tegra_dc_writel(dc, val, DC_WIN_WIN_OPTIONS);
+
+#ifdef CONFIG_ARCH_TEGRA_3x_SOC
+               if (win->global_alpha == 255)
+                       tegra_dc_writel(dc, 0, DC_WIN_GLOBAL_ALPHA);
+               else
+                       tegra_dc_writel(dc, GLOBAL_ALPHA_ENABLE |
+                               win->global_alpha, DC_WIN_GLOBAL_ALPHA);
+#endif
+
+               win->dirty = no_vsync ? 0 : 1;
+
+               dev_dbg(&dc->ndev->dev, "%s():idx=%d z=%d x=%d y=%d w=%d h=%d "
+                       "out_x=%u out_y=%u out_w=%u out_h=%u "
+                       "fmt=%d yuvp=%d Bpp=%u filter_h=%d filter_v=%d",
+                       __func__, win->idx, win->z,
+                       dfixed_trunc(win->x), dfixed_trunc(win->y),
+                       dfixed_trunc(win->w), dfixed_trunc(win->h),
+                       win->out_x, win->out_y, win->out_w, win->out_h,
+                       win->fmt, yuvp, Bpp, filter_h, filter_v);
+               trace_printk("%s:win%u in:%ux%u out:%ux%u fmt=%d\n",
+                       dc->ndev->name, win->idx, dfixed_trunc(win->w),
+                       dfixed_trunc(win->h), win->out_w, win->out_h, win->fmt);
+       }
+
+       if (update_blend) {
+               tegra_dc_set_blending(dc, &dc->blend);
+               for (i = 0; i < DC_N_WINDOWS; i++) {
+                       if (!no_vsync)
+                               dc->windows[i].dirty = 1;
+                       update_mask |= WIN_A_ACT_REQ << i;
+               }
+       }
+
+       tegra_dc_set_dynamic_emc(windows, n);
+
+       tegra_dc_writel(dc, update_mask << 8, DC_CMD_STATE_CONTROL);
+
+       tegra_dc_writel(dc, FRAME_END_INT | V_BLANK_INT, DC_CMD_INT_STATUS);
+       if (!no_vsync) {
+               set_bit(V_BLANK_FLIP, &dc->vblank_ref_count);
+               tegra_dc_unmask_interrupt(dc,
+                       FRAME_END_INT | V_BLANK_INT | ALL_UF_INT);
+       } else {
+               clear_bit(V_BLANK_FLIP, &dc->vblank_ref_count);
+               tegra_dc_mask_interrupt(dc,
+                       FRAME_END_INT | V_BLANK_INT | ALL_UF_INT);
+       }
+
+       if (dc->out->flags & TEGRA_DC_OUT_ONE_SHOT_MODE)
+               schedule_delayed_work(&dc->one_shot_work,
+                               msecs_to_jiffies(dc->one_shot_delay_ms));
+
+       /* update EMC clock if calculated bandwidth has changed */
+       tegra_dc_program_bandwidth(dc, false);
+
+       if (dc->out->flags & TEGRA_DC_OUT_ONE_SHOT_MODE)
+               update_mask |= NC_HOST_TRIG;
+
+       tegra_dc_writel(dc, update_mask, DC_CMD_STATE_CONTROL);
+       trace_printk("%s:update_mask=%#lx\n", dc->ndev->name, update_mask);
+
+       mutex_unlock(&dc->lock);
+       if (dc->out->flags & TEGRA_DC_OUT_ONE_SHOT_MODE)
+               mutex_unlock(&dc->one_shot_lock);
+
+       return 0;
+}
+EXPORT_SYMBOL(tegra_dc_update_windows);
+
+void tegra_dc_trigger_windows(struct tegra_dc *dc)
+{
+       u32 val, i;
+       u32 completed = 0;
+       u32 dirty = 0;
+
+       val = tegra_dc_readl(dc, DC_CMD_STATE_CONTROL);
+       for (i = 0; i < DC_N_WINDOWS; i++) {
+#ifdef CONFIG_TEGRA_SIMULATION_PLATFORM
+               /* FIXME: this is not needed when the simulator
+                  clears WIN_x_UPDATE bits as in HW */
+               dc->windows[i].dirty = 0;
+               completed = 1;
+#else
+               if (!(val & (WIN_A_ACT_REQ << i))) {
+                       dc->windows[i].dirty = 0;
+                       completed = 1;
+               } else {
+                       dirty = 1;
+               }
+#endif
+       }
+
+       if (!dirty) {
+               if (!(dc->out->flags & TEGRA_DC_OUT_ONE_SHOT_MODE))
+                       tegra_dc_mask_interrupt(dc, FRAME_END_INT);
+       }
+
+       if (completed)
+               wake_up(&dc->wq);
+}
+
index 1193a2e..9c5c06d 100644 (file)
@@ -6,7 +6,7 @@
  *         Colin Cross <ccross@android.com>
  *         Travis Geiselbrecht <travis@palm.com>
  *
- * Copyright (C) 2010-2011 NVIDIA Corporation
+ * Copyright (c) 2010-2012, NVIDIA CORPORATION, All rights reserved.
  *
  * This software is licensed under the terms of the GNU General Public
  * License version 2, as published by the Free Software Foundation, and