summaryrefslogtreecommitdiff
path: root/drivers/video/tegra/dc/dc_priv.h
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/video/tegra/dc/dc_priv.h')
-rw-r--r--drivers/video/tegra/dc/dc_priv.h419
1 files changed, 419 insertions, 0 deletions
diff --git a/drivers/video/tegra/dc/dc_priv.h b/drivers/video/tegra/dc/dc_priv.h
new file mode 100644
index 000000000000..e91071f70ddc
--- /dev/null
+++ b/drivers/video/tegra/dc/dc_priv.h
@@ -0,0 +1,419 @@
+/*
+ * drivers/video/tegra/dc/dc_priv.h
+ *
+ * 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.
+ *
+ * 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_DC_PRIV_H
+#define __DRIVERS_VIDEO_TEGRA_DC_DC_PRIV_H
+
+#include <linux/io.h>
+#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>
+
+#include <mach/dc.h>
+
+#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 NEED_UPDATE_EMC_ON_EVERY_FRAME (windows_idle_detection_time == 0)
+
+/* DDR: 8 bytes transfer per clock */
+#define DDR_BW_TO_FREQ(bw) ((bw) / 8)
+
+#if defined(CONFIG_TEGRA_EMC_TO_DDR_CLOCK)
+#define EMC_BW_TO_FREQ(bw) (DDR_BW_TO_FREQ(bw) * CONFIG_TEGRA_EMC_TO_DDR_CLOCK)
+#else
+#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 {
+ unsigned z[DC_N_WINDOWS];
+ unsigned flags[DC_N_WINDOWS];
+};
+
+struct tegra_dc_out_ops {
+ /* initialize output. dc clocks are not on at this point */
+ int (*init)(struct tegra_dc *dc);
+ /* destroy output. dc clocks are not on at this point */
+ void (*destroy)(struct tegra_dc *dc);
+ /* detect connected display. can sleep.*/
+ bool (*detect)(struct tegra_dc *dc);
+ /* enable output. dc clocks are on at this point */
+ void (*enable)(struct tegra_dc *dc);
+ /* disable output. dc clocks are on at this point */
+ void (*disable)(struct tegra_dc *dc);
+ /* hold output. keeps dc clocks on. */
+ void (*hold)(struct tegra_dc *dc);
+ /* release output. dc clocks may turn off after this. */
+ void (*release)(struct tegra_dc *dc);
+ /* idle routine of output. dc clocks may turn off after this. */
+ void (*idle)(struct tegra_dc *dc);
+ /* suspend output. dc clocks are on at this point */
+ void (*suspend)(struct tegra_dc *dc);
+ /* resume output. dc clocks are on at this point */
+ void (*resume)(struct tegra_dc *dc);
+ /* mode filter. to provide a list of supported modes*/
+ bool (*mode_filter)(const struct tegra_dc *dc,
+ struct fb_videomode *mode);
+};
+
+struct tegra_dc {
+ struct nvhost_device *ndev;
+ struct tegra_dc_platform_data *pdata;
+
+ struct resource *base_res;
+ void __iomem *base;
+ int irq;
+
+ struct clk *clk;
+ struct clk *emc_clk;
+ int emc_clk_rate;
+ int new_emc_clk_rate;
+ u32 shift_clk_div;
+
+ bool connected;
+ bool enabled;
+ bool suspended;
+
+ struct tegra_dc_out *out;
+ struct tegra_dc_out_ops *out_ops;
+ void *out_data;
+
+ struct tegra_dc_mode mode;
+#ifndef CONFIG_ANDROID
+ s64 frametime_ns;
+#endif /* !CONFIG_ANDROID */
+
+ struct tegra_dc_win windows[DC_N_WINDOWS];
+ struct tegra_dc_blend blend;
+ int n_windows;
+
+ wait_queue_head_t wq;
+#ifndef CONFIG_ANDROID
+ wait_queue_head_t timestamp_wq;
+#endif /* !CONFIG_ANDROID */
+
+ struct mutex lock;
+ struct mutex one_shot_lock;
+
+ struct resource *fb_mem;
+ struct tegra_fb_info *fb;
+
+ struct {
+ u32 id;
+ u32 min;
+ u32 max;
+ } syncpt[DC_N_WINDOWS];
+ u32 vblank_syncpt;
+
+ unsigned long underflow_mask;
+ struct work_struct reset_work;
+
+#ifdef CONFIG_SWITCH
+ struct switch_dev modeset_switch;
+#endif
+
+ struct completion frame_end_complete;
+
+ struct work_struct vblank_work;
+ long vblank_ref_count;
+
+ struct {
+ u64 underflows;
+ u64 underflows_a;
+ u64 underflows_b;
+ u64 underflows_c;
+ } stats;
+
+ struct tegra_dc_ext *ext;
+
+ struct tegra_dc_feature *feature;
+
+#ifdef CONFIG_DEBUG_FS
+ struct dentry *debugdir;
+#endif
+ struct tegra_dc_lut fb_lut;
+ struct delayed_work underflow_work;
+ u32 one_shot_delay_ms;
+ struct delayed_work one_shot_work;
+#ifndef CONFIG_ANDROID
+ s64 frame_end_timestamp;
+#endif /* !CONFIG_ANDROID */
+};
+
+#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));
+}
+
+static inline void tegra_dc_io_end(struct tegra_dc *dc)
+{
+ nvhost_module_idle_ext(nvhost_get_parent(dc->ndev));
+}
+
+static inline unsigned long tegra_dc_readl(struct tegra_dc *dc,
+ unsigned long reg)
+{
+ unsigned long ret;
+
+ BUG_ON(!nvhost_module_powered_ext(nvhost_get_parent(dc->ndev)));
+ if (!tegra_is_clk_enabled(dc->clk))
+ WARN(1, "DC is clock-gated.\n");
+
+ ret = readl(dc->base + reg * 4);
+ trace_printk("readl %p=%#08lx\n", dc->base + reg * 4, ret);
+ return ret;
+}
+
+static inline void tegra_dc_writel(struct tegra_dc *dc, unsigned long val,
+ unsigned long reg)
+{
+ BUG_ON(!nvhost_module_powered_ext(nvhost_get_parent(dc->ndev)));
+ if (!tegra_is_clk_enabled(dc->clk))
+ WARN(1, "DC is clock-gated.\n");
+
+ trace_printk("writel %p=%#08lx\n", dc->base + reg * 4, val);
+ writel(val, dc->base + reg * 4);
+}
+
+static inline void _tegra_dc_write_table(struct tegra_dc *dc, const u32 *table,
+ unsigned len)
+{
+ int i;
+
+ for (i = 0; i < len; i++)
+ tegra_dc_writel(dc, table[i * 2 + 1], table[i * 2]);
+}
+
+#define tegra_dc_write_table(dc, table) \
+ _tegra_dc_write_table(dc, table, ARRAY_SIZE(table) / 2)
+
+static inline void tegra_dc_set_outdata(struct tegra_dc *dc, void *data)
+{
+ dc->out_data = data;
+}
+
+static inline void *tegra_dc_get_outdata(struct tegra_dc *dc)
+{
+ return dc->out_data;
+}
+
+static inline unsigned long tegra_dc_get_default_emc_clk_rate(
+ struct tegra_dc *dc)
+{
+ return dc->pdata->emc_clk_rate ? dc->pdata->emc_clk_rate : ULONG_MAX;
+}
+
+static inline int tegra_dc_fmt_bpp(int fmt)
+{
+ switch (fmt) {
+ case TEGRA_WIN_FMT_P1:
+ return 1;
+
+ case TEGRA_WIN_FMT_P2:
+ return 2;
+
+ case TEGRA_WIN_FMT_P4:
+ return 4;
+
+ case TEGRA_WIN_FMT_P8:
+ return 8;
+
+ case TEGRA_WIN_FMT_B4G4R4A4:
+ case TEGRA_WIN_FMT_B5G5R5A:
+ case TEGRA_WIN_FMT_B5G6R5:
+ case TEGRA_WIN_FMT_AB5G5R5:
+ return 16;
+
+ case TEGRA_WIN_FMT_B8G8R8A8:
+ case TEGRA_WIN_FMT_R8G8B8A8:
+ case TEGRA_WIN_FMT_B6x2G6x2R6x2A8:
+ case TEGRA_WIN_FMT_R6x2G6x2B6x2A8:
+ return 32;
+
+ /* for planar formats, size of the Y plane, 8bit */
+ case TEGRA_WIN_FMT_YCbCr420P:
+ case TEGRA_WIN_FMT_YUV420P:
+ case TEGRA_WIN_FMT_YCbCr422P:
+ case TEGRA_WIN_FMT_YUV422P:
+ case TEGRA_WIN_FMT_YCbCr422R:
+ case TEGRA_WIN_FMT_YUV422R:
+ case TEGRA_WIN_FMT_YCbCr422RA:
+ case TEGRA_WIN_FMT_YUV422RA:
+ return 8;
+
+ /* YUYV packed into 32-bits */
+ case TEGRA_WIN_FMT_YCbCr422:
+ case TEGRA_WIN_FMT_YUV422:
+ return 16;
+ }
+ return 0;
+}
+
+static inline bool tegra_dc_is_yuv(int fmt)
+{
+ switch (fmt) {
+ case TEGRA_WIN_FMT_YUV420P:
+ case TEGRA_WIN_FMT_YCbCr420P:
+ case TEGRA_WIN_FMT_YCbCr422P:
+ case TEGRA_WIN_FMT_YUV422P:
+ case TEGRA_WIN_FMT_YCbCr422:
+ case TEGRA_WIN_FMT_YUV422:
+ case TEGRA_WIN_FMT_YCbCr422R:
+ case TEGRA_WIN_FMT_YUV422R:
+ case TEGRA_WIN_FMT_YCbCr422RA:
+ case TEGRA_WIN_FMT_YUV422RA:
+ return true;
+ }
+ return false;
+}
+
+static inline bool tegra_dc_is_yuv_planar(int fmt)
+{
+ switch (fmt) {
+ case TEGRA_WIN_FMT_YUV420P:
+ case TEGRA_WIN_FMT_YCbCr420P:
+ case TEGRA_WIN_FMT_YCbCr422P:
+ case TEGRA_WIN_FMT_YUV422P:
+ case TEGRA_WIN_FMT_YCbCr422R:
+ case TEGRA_WIN_FMT_YUV422R:
+ case TEGRA_WIN_FMT_YCbCr422RA:
+ case TEGRA_WIN_FMT_YUV422RA:
+ return true;
+ }
+ return false;
+}
+
+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 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;
+extern struct tegra_dc_out_ops tegra_dc_dsi_ops;
+
+/* defined in dc_sysfs.c, used by dc.c */
+void __devexit tegra_dc_remove_sysfs(struct device *dev);
+void tegra_dc_create_sysfs(struct device *dev);
+
+/* defined in dc.c, used by dc_sysfs.c */
+void tegra_dc_stats_enable(struct tegra_dc *dc, bool enable);
+bool tegra_dc_stats_get(struct tegra_dc *dc);
+
+/* defined in dc.c, used by dc_sysfs.c */
+u32 tegra_dc_read_checksum_latched(struct tegra_dc *dc);
+void tegra_dc_enable_crc(struct tegra_dc *dc);
+void tegra_dc_disable_crc(struct tegra_dc *dc);
+
+void tegra_dc_set_out_pin_polars(struct tegra_dc *dc,
+ const struct tegra_dc_out_pin *pins,
+ const unsigned int n_pins);
+/* defined in dc.c, used in bandwidth.c and ext/dev.c */
+unsigned int tegra_dc_has_multiple_dc(void);
+
+/* defined in dc.c, used in dsi.c */
+void tegra_dc_clk_enable(struct tegra_dc *dc);
+void tegra_dc_clk_disable(struct tegra_dc *dc);
+
+/* defined in dc.c, used in nvsd.c and dsi.c */
+void tegra_dc_hold_dc_out(struct tegra_dc *dc);
+void tegra_dc_release_dc_out(struct tegra_dc *dc);
+
+/* defined in bandwidth.c, used in dc.c */
+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