/* * drivers/video/tegra/dc/dc_priv.h * * Copyright (C) 2010 Google, Inc. * Author: Erik Gilling * * 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 #include #include #include #include #include #include #include "../host/dev.h" #include "../host/nvhost_acm.h" #include "../host/host1x/host1x_syncpt.h" #include #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 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); /* 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; struct tegra_dc_win windows[DC_N_WINDOWS]; struct tegra_dc_blend blend; int n_windows; wait_queue_head_t wq; 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; 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; }; static inline void tegra_dc_io_start(struct tegra_dc *dc) { nvhost_module_busy(nvhost_get_host(dc->ndev)->dev); } static inline void tegra_dc_io_end(struct tegra_dc *dc) { nvhost_module_idle(nvhost_get_host(dc->ndev)->dev); } static inline unsigned long tegra_dc_readl(struct tegra_dc *dc, unsigned long reg) { unsigned long ret; BUG_ON(!nvhost_module_powered(nvhost_get_host(dc->ndev)->dev)); 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(nvhost_get_host(dc->ndev)->dev)); 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; } void tegra_dc_setup_clk(struct tegra_dc *dc, struct clk *clk); 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 */ unsigned int tegra_dc_has_multiple_dc(void); /* 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); int tegra_dc_set_dynamic_emc(struct tegra_dc_win *windows[], int n); #endif