diff options
| author | Linus Torvalds <torvalds@linux-foundation.org> | 2017-09-03 17:02:26 -0700 |
|---|---|---|
| committer | Linus Torvalds <torvalds@linux-foundation.org> | 2017-09-03 17:02:26 -0700 |
| commit | 906dde0f355bd97c080c215811ae7db1137c4af8 (patch) | |
| tree | 1e1b4ba58a59c4027f06d86e7430566ee0dcbb15 /drivers/gpu/drm/omapdrm/dss | |
| parent | 69c0067aa3f40d3e52ab78643aecb17d669d3389 (diff) | |
| parent | 7846b12fe0b5feab5446d892f41b5140c1419109 (diff) | |
| download | talos-op-linux-906dde0f355bd97c080c215811ae7db1137c4af8.tar.gz talos-op-linux-906dde0f355bd97c080c215811ae7db1137c4af8.zip | |
Merge tag 'drm-for-v4.14' of git://people.freedesktop.org/~airlied/linux
Pull drm updates from Dave Airlie:
"This is the main drm pull request for 4.14 merge window.
I'm sending this early, as my continuing journey into fatherhood is
occurring really soon now, I'm going to be mostly useless for the next
couple of weeks, though I may be able to read email, I doubt I'll be
doing much patch applications or git sending. If anything urgent pops
up I've asked Daniel/Jani/Alex/Sean to try and direct stuff towards
you.
Outside drm changes:
Some rcar-du updates that touch the V4L tree, all acks should be in
place. It adds one export to the radix tree code for new i915 use
case. There are some minor AGP cleanups (don't see that too often).
Changes to the vbox driver in staging to avoid breaking compilation.
Summary:
core:
- Atomic helper fixes
- Atomic UAPI fixes
- Add YCBCR 4:2:0 support
- Drop set_busid hook
- Refactor fb_helper locking
- Remove a bunch of internal APIs
- Add a bunch of better default handlers
- Format modifier/blob plane property added
- More internal header refactoring
- Make more internal API names consistent
- Enhanced syncobj APIs (wait/signal/reset/create signalled)
bridge:
- Add Synopsys Designware MIPI DSI host bridge driver
tiny:
- Add Pervasive Displays RePaper displays
- Add support for LEGO MINDSTORMS EV3 LCD
i915:
- Lots of GEN10/CNL support patches
- drm syncobj support
- Skylake+ watermark refactoring
- GVT vGPU 48-bit ppgtt support
- GVT performance improvements
- NOA change ioctl
- CCS (color compression) scanout support
- GPU reset improvements
amdgpu:
- Initial hugepage support
- BO migration logic rework
- Vega10 improvements
- Powerplay fixes
- Stop reprogramming the MC
- Fixes for ACP audio on stoney
- SR-IOV fixes/improvements
- Command submission overhead improvements
amdkfd:
- Non-dGPU upstreaming patches
- Scratch VA ioctl
- Image tiling modes
- Update PM4 headers for new firmware
- Drop all BUG_ONs.
nouveau:
- GP108 modesetting support.
- Disable MSI on big endian.
vmwgfx:
- Add fence fd support.
msm:
- Runtime PM improvements
exynos:
- NV12MT support
- Refactor KMS drivers
imx-drm:
- Lock scanout channel to improve memory bw
- Cleanups
etnaviv:
- GEM object population fixes
tegra:
- Prep work for Tegra186 support
- PRIME mmap support
sunxi:
- HDMI support improvements
- HDMI CEC support
omapdrm:
- HDMI hotplug IRQ support
- Big driver cleanup
- OMAP5 DSI support
rcar-du:
- vblank fixes
- VSP1 updates
arcgpu:
- Minor fixes
stm:
- Add STM32 DSI controller driver
dw_hdmi:
- Add support for Rockchip RK3399
- HDMI CEC support
atmel-hlcdc:
- Add 8-bit color support
vc4:
- Atomic fixes
- New ioctl to attach a label to a buffer object
- HDMI CEC support
- Allow userspace to dictate rendering order on submit ioctl"
* tag 'drm-for-v4.14' of git://people.freedesktop.org/~airlied/linux: (1074 commits)
drm/syncobj: Add a signal ioctl (v3)
drm/syncobj: Add a reset ioctl (v3)
drm/syncobj: Add a syncobj_array_find helper
drm/syncobj: Allow wait for submit and signal behavior (v5)
drm/syncobj: Add a CREATE_SIGNALED flag
drm/syncobj: Add a callback mechanism for replace_fence (v3)
drm/syncobj: add sync obj wait interface. (v8)
i915: Use drm_syncobj_fence_get
drm/syncobj: Add a race-free drm_syncobj_fence_get helper (v2)
drm/syncobj: Rename fence_get to find_fence
drm: kirin: Add mode_valid logic to avoid mode clocks we can't generate
drm/vmwgfx: Bump the version for fence FD support
drm/vmwgfx: Add export fence to file descriptor support
drm/vmwgfx: Add support for imported Fence File Descriptor
drm/vmwgfx: Prepare to support fence fd
drm/vmwgfx: Fix incorrect command header offset at restart
drm/vmwgfx: Support the NOP_ERROR command
drm/vmwgfx: Restart command buffers after errors
drm/vmwgfx: Move irq bottom half processing to threads
drm/vmwgfx: Don't use drm_irq_[un]install
...
Diffstat (limited to 'drivers/gpu/drm/omapdrm/dss')
| -rw-r--r-- | drivers/gpu/drm/omapdrm/dss/Makefile | 2 | ||||
| -rw-r--r-- | drivers/gpu/drm/omapdrm/dss/core.c | 190 | ||||
| -rw-r--r-- | drivers/gpu/drm/omapdrm/dss/dispc.c | 824 | ||||
| -rw-r--r-- | drivers/gpu/drm/omapdrm/dss/dpi.c | 88 | ||||
| -rw-r--r-- | drivers/gpu/drm/omapdrm/dss/dsi.c | 329 | ||||
| -rw-r--r-- | drivers/gpu/drm/omapdrm/dss/dss.c | 406 | ||||
| -rw-r--r-- | drivers/gpu/drm/omapdrm/dss/dss.h | 49 | ||||
| -rw-r--r-- | drivers/gpu/drm/omapdrm/dss/dss_features.c | 905 | ||||
| -rw-r--r-- | drivers/gpu/drm/omapdrm/dss/dss_features.h | 109 | ||||
| -rw-r--r-- | drivers/gpu/drm/omapdrm/dss/hdmi.h | 16 | ||||
| -rw-r--r-- | drivers/gpu/drm/omapdrm/dss/hdmi4.c | 7 | ||||
| -rw-r--r-- | drivers/gpu/drm/omapdrm/dss/hdmi4_core.c | 38 | ||||
| -rw-r--r-- | drivers/gpu/drm/omapdrm/dss/hdmi5.c | 7 | ||||
| -rw-r--r-- | drivers/gpu/drm/omapdrm/dss/hdmi_phy.c | 60 | ||||
| -rw-r--r-- | drivers/gpu/drm/omapdrm/dss/hdmi_pll.c | 24 | ||||
| -rw-r--r-- | drivers/gpu/drm/omapdrm/dss/hdmi_wp.c | 12 | ||||
| -rw-r--r-- | drivers/gpu/drm/omapdrm/dss/omapdss.h | 25 | ||||
| -rw-r--r-- | drivers/gpu/drm/omapdrm/dss/pll.c | 29 | ||||
| -rw-r--r-- | drivers/gpu/drm/omapdrm/dss/venc.c | 86 | ||||
| -rw-r--r-- | drivers/gpu/drm/omapdrm/dss/video-pll.c | 3 |
20 files changed, 1436 insertions, 1773 deletions
diff --git a/drivers/gpu/drm/omapdrm/dss/Makefile b/drivers/gpu/drm/omapdrm/dss/Makefile index 688195e448c5..142ce5a02542 100644 --- a/drivers/gpu/drm/omapdrm/dss/Makefile +++ b/drivers/gpu/drm/omapdrm/dss/Makefile @@ -5,7 +5,7 @@ omapdss-base-y := base.o display.o dss-of.o output.o obj-$(CONFIG_OMAP2_DSS) += omapdss.o # Core DSS files -omapdss-y := core.o dss.o dss_features.o dispc.o dispc_coefs.o \ +omapdss-y := core.o dss.o dispc.o dispc_coefs.o \ pll.o video-pll.o omapdss-$(CONFIG_OMAP2_DSS_DPI) += dpi.o omapdss-$(CONFIG_OMAP2_DSS_VENC) += venc.o diff --git a/drivers/gpu/drm/omapdrm/dss/core.c b/drivers/gpu/drm/omapdrm/dss/core.c index bdce4bfdf6e0..197ddbc1512b 100644 --- a/drivers/gpu/drm/omapdrm/dss/core.c +++ b/drivers/gpu/drm/omapdrm/dss/core.c @@ -24,182 +24,10 @@ #include <linux/kernel.h> #include <linux/module.h> -#include <linux/clk.h> -#include <linux/err.h> #include <linux/platform_device.h> -#include <linux/seq_file.h> -#include <linux/debugfs.h> -#include <linux/io.h> -#include <linux/device.h> -#include <linux/regulator/consumer.h> -#include <linux/suspend.h> -#include <linux/slab.h> #include "omapdss.h" #include "dss.h" -#include "dss_features.h" - -static struct { - struct platform_device *pdev; -} core; - -enum omapdss_version omapdss_get_version(void) -{ - struct omap_dss_board_info *pdata = core.pdev->dev.platform_data; - return pdata->version; -} -EXPORT_SYMBOL(omapdss_get_version); - -int dss_dsi_enable_pads(int dsi_id, unsigned lane_mask) -{ - struct omap_dss_board_info *board_data = core.pdev->dev.platform_data; - - if (!board_data->dsi_enable_pads) - return -ENOENT; - - return board_data->dsi_enable_pads(dsi_id, lane_mask); -} - -void dss_dsi_disable_pads(int dsi_id, unsigned lane_mask) -{ - struct omap_dss_board_info *board_data = core.pdev->dev.platform_data; - - if (!board_data->dsi_disable_pads) - return; - - return board_data->dsi_disable_pads(dsi_id, lane_mask); -} - -int dss_set_min_bus_tput(struct device *dev, unsigned long tput) -{ - struct omap_dss_board_info *pdata = core.pdev->dev.platform_data; - - if (pdata->set_min_bus_tput) - return pdata->set_min_bus_tput(dev, tput); - else - return 0; -} - -#if defined(CONFIG_OMAP2_DSS_DEBUGFS) -static int dss_debug_show(struct seq_file *s, void *unused) -{ - void (*func)(struct seq_file *) = s->private; - func(s); - return 0; -} - -static int dss_debug_open(struct inode *inode, struct file *file) -{ - return single_open(file, dss_debug_show, inode->i_private); -} - -static const struct file_operations dss_debug_fops = { - .open = dss_debug_open, - .read = seq_read, - .llseek = seq_lseek, - .release = single_release, -}; - -static struct dentry *dss_debugfs_dir; - -static int dss_initialize_debugfs(void) -{ - dss_debugfs_dir = debugfs_create_dir("omapdss", NULL); - if (IS_ERR(dss_debugfs_dir)) { - int err = PTR_ERR(dss_debugfs_dir); - dss_debugfs_dir = NULL; - return err; - } - - debugfs_create_file("clk", S_IRUGO, dss_debugfs_dir, - &dss_debug_dump_clocks, &dss_debug_fops); - - return 0; -} - -static void dss_uninitialize_debugfs(void) -{ - if (dss_debugfs_dir) - debugfs_remove_recursive(dss_debugfs_dir); -} - -int dss_debugfs_create_file(const char *name, void (*write)(struct seq_file *)) -{ - struct dentry *d; - - d = debugfs_create_file(name, S_IRUGO, dss_debugfs_dir, - write, &dss_debug_fops); - - return PTR_ERR_OR_ZERO(d); -} -#else /* CONFIG_OMAP2_DSS_DEBUGFS */ -static inline int dss_initialize_debugfs(void) -{ - return 0; -} -static inline void dss_uninitialize_debugfs(void) -{ -} -int dss_debugfs_create_file(const char *name, void (*write)(struct seq_file *)) -{ - return 0; -} -#endif /* CONFIG_OMAP2_DSS_DEBUGFS */ - -/* PLATFORM DEVICE */ - -static void dss_disable_all_devices(void) -{ - struct omap_dss_device *dssdev = NULL; - - for_each_dss_dev(dssdev) { - if (!dssdev->driver) - continue; - - if (dssdev->state == OMAP_DSS_DISPLAY_ACTIVE) - dssdev->driver->disable(dssdev); - } -} - -static int __init omap_dss_probe(struct platform_device *pdev) -{ - int r; - - core.pdev = pdev; - - dss_features_init(omapdss_get_version()); - - r = dss_initialize_debugfs(); - if (r) - goto err_debugfs; - - return 0; - -err_debugfs: - - return r; -} - -static int omap_dss_remove(struct platform_device *pdev) -{ - dss_uninitialize_debugfs(); - - return 0; -} - -static void omap_dss_shutdown(struct platform_device *pdev) -{ - DSSDBG("shutdown\n"); - dss_disable_all_devices(); -} - -static struct platform_driver omap_dss_driver = { - .remove = omap_dss_remove, - .shutdown = omap_dss_shutdown, - .driver = { - .name = "omapdss", - }, -}; /* INIT */ static int (*dss_output_drv_reg_funcs[])(void) __initdata = { @@ -236,21 +64,25 @@ static void (*dss_output_drv_unreg_funcs[])(void) = { dss_uninit_platform_driver, }; +static struct platform_device *omap_drm_device; + static int __init omap_dss_init(void) { int r; int i; - r = platform_driver_probe(&omap_dss_driver, omap_dss_probe); - if (r) - return r; - for (i = 0; i < ARRAY_SIZE(dss_output_drv_reg_funcs); ++i) { r = dss_output_drv_reg_funcs[i](); if (r) goto err_reg; } + omap_drm_device = platform_device_register_simple("omapdrm", 0, NULL, 0); + if (IS_ERR(omap_drm_device)) { + r = PTR_ERR(omap_drm_device); + goto err_reg; + } + return 0; err_reg: @@ -259,8 +91,6 @@ err_reg: ++i) dss_output_drv_unreg_funcs[i](); - platform_driver_unregister(&omap_dss_driver); - return r; } @@ -268,10 +98,10 @@ static void __exit omap_dss_exit(void) { int i; + platform_device_unregister(omap_drm_device); + for (i = 0; i < ARRAY_SIZE(dss_output_drv_unreg_funcs); ++i) dss_output_drv_unreg_funcs[i](); - - platform_driver_unregister(&omap_dss_driver); } module_init(omap_dss_init); diff --git a/drivers/gpu/drm/omapdrm/dss/dispc.c b/drivers/gpu/drm/omapdrm/dss/dispc.c index fd7504b37e3b..0f4fdb221498 100644 --- a/drivers/gpu/drm/omapdrm/dss/dispc.c +++ b/drivers/gpu/drm/omapdrm/dss/dispc.c @@ -39,13 +39,14 @@ #include <linux/mfd/syscon.h> #include <linux/regmap.h> #include <linux/of.h> +#include <linux/of_device.h> #include <linux/component.h> +#include <linux/sys_soc.h> #include <drm/drm_fourcc.h> #include <drm/drm_blend.h> #include "omapdss.h" #include "dss.h" -#include "dss_features.h" #include "dispc.h" /* DISPC */ @@ -63,6 +64,33 @@ enum omap_burst_size { #define REG_FLD_MOD(idx, val, start, end) \ dispc_write_reg(idx, FLD_MOD(dispc_read_reg(idx), val, start, end)) +/* DISPC has feature id */ +enum dispc_feature_id { + FEAT_LCDENABLEPOL, + FEAT_LCDENABLESIGNAL, + FEAT_PCKFREEENABLE, + FEAT_FUNCGATED, + FEAT_MGR_LCD2, + FEAT_MGR_LCD3, + FEAT_LINEBUFFERSPLIT, + FEAT_ROWREPEATENABLE, + FEAT_RESIZECONF, + /* Independent core clk divider */ + FEAT_CORE_CLK_DIV, + FEAT_HANDLE_UV_SEPARATE, + FEAT_ATTR2, + FEAT_CPR, + FEAT_PRELOAD, + FEAT_FIR_COEF_V, + FEAT_ALPHA_FIXED_ZORDER, + FEAT_ALPHA_FREE_ZORDER, + FEAT_FIFO_MERGE, + /* An unknown HW bug causing the normal FIFO thresholds not to work */ + FEAT_OMAP3_DSI_FIFO_BUG, + FEAT_BURST_2D, + FEAT_MFLAG, +}; + struct dispc_features { u8 sw_start; u8 fp_start; @@ -76,6 +104,9 @@ struct dispc_features { u16 mgr_height_max; unsigned long max_lcd_pclk; unsigned long max_tv_pclk; + unsigned int max_downscale; + unsigned int max_line_width; + unsigned int min_pcd; int (*calc_scaling) (unsigned long pclk, unsigned long lclk, const struct videomode *vm, u16 width, u16 height, u16 out_width, u16 out_height, @@ -86,6 +117,16 @@ struct dispc_features { u16 width, u16 height, u16 out_width, u16 out_height, bool mem_to_mem); u8 num_fifos; + const enum dispc_feature_id *features; + unsigned int num_features; + const struct dss_reg_field *reg_fields; + const unsigned int num_reg_fields; + const enum omap_overlay_caps *overlay_caps; + const u32 **supported_color_modes; + unsigned int num_mgrs; + unsigned int num_ovls; + unsigned int buffer_size_unit; + unsigned int burst_size_unit; /* swap GFX & WB fifos */ bool gfx_fifo_workaround:1; @@ -180,6 +221,17 @@ enum mgr_reg_fields { DISPC_MGR_FLD_NUM, }; +/* DISPC register field id */ +enum dispc_feat_reg_field { + FEAT_REG_FIRHINC, + FEAT_REG_FIRVINC, + FEAT_REG_FIFOHIGHTHRESHOLD, + FEAT_REG_FIFOLOWTHRESHOLD, + FEAT_REG_FIFOSIZE, + FEAT_REG_HORIZONTALACCU, + FEAT_REG_VERTICALACCU, +}; + struct dispc_reg_field { u16 reg; u8 high; @@ -343,6 +395,38 @@ static void mgr_fld_write(enum omap_channel channel, spin_unlock_irqrestore(&dispc.control_lock, flags); } +static int dispc_get_num_ovls(void) +{ + return dispc.feat->num_ovls; +} + +static int dispc_get_num_mgrs(void) +{ + return dispc.feat->num_mgrs; +} + +static void dispc_get_reg_field(enum dispc_feat_reg_field id, + u8 *start, u8 *end) +{ + if (id >= dispc.feat->num_reg_fields) + BUG(); + + *start = dispc.feat->reg_fields[id].start; + *end = dispc.feat->reg_fields[id].end; +} + +static bool dispc_has_feature(enum dispc_feature_id id) +{ + unsigned int i; + + for (i = 0; i < dispc.feat->num_features; i++) { + if (dispc.feat->features[i] == id) + return true; + } + + return false; +} + #define SR(reg) \ dispc.ctx[DISPC_##reg / sizeof(u32)] = dispc_read_reg(DISPC_##reg) #define RR(reg) \ @@ -358,19 +442,19 @@ static void dispc_save_context(void) SR(CONTROL); SR(CONFIG); SR(LINE_NUMBER); - if (dss_has_feature(FEAT_ALPHA_FIXED_ZORDER) || - dss_has_feature(FEAT_ALPHA_FREE_ZORDER)) + if (dispc_has_feature(FEAT_ALPHA_FIXED_ZORDER) || + dispc_has_feature(FEAT_ALPHA_FREE_ZORDER)) SR(GLOBAL_ALPHA); - if (dss_has_feature(FEAT_MGR_LCD2)) { + if (dispc_has_feature(FEAT_MGR_LCD2)) { SR(CONTROL2); SR(CONFIG2); } - if (dss_has_feature(FEAT_MGR_LCD3)) { + if (dispc_has_feature(FEAT_MGR_LCD3)) { SR(CONTROL3); SR(CONFIG3); } - for (i = 0; i < dss_feat_get_num_mgrs(); i++) { + for (i = 0; i < dispc_get_num_mgrs(); i++) { SR(DEFAULT_COLOR(i)); SR(TRANS_COLOR(i)); SR(SIZE_MGR(i)); @@ -385,14 +469,14 @@ static void dispc_save_context(void) SR(DATA_CYCLE2(i)); SR(DATA_CYCLE3(i)); - if (dss_has_feature(FEAT_CPR)) { + if (dispc_has_feature(FEAT_CPR)) { SR(CPR_COEF_R(i)); SR(CPR_COEF_G(i)); SR(CPR_COEF_B(i)); } } - for (i = 0; i < dss_feat_get_num_ovls(); i++) { + for (i = 0; i < dispc_get_num_ovls(); i++) { SR(OVL_BA0(i)); SR(OVL_BA1(i)); SR(OVL_POSITION(i)); @@ -401,7 +485,7 @@ static void dispc_save_context(void) SR(OVL_FIFO_THRESHOLD(i)); SR(OVL_ROW_INC(i)); SR(OVL_PIXEL_INC(i)); - if (dss_has_feature(FEAT_PRELOAD)) + if (dispc_has_feature(FEAT_PRELOAD)) SR(OVL_PRELOAD(i)); if (i == OMAP_DSS_GFX) { SR(OVL_WINDOW_SKIP(i)); @@ -422,12 +506,12 @@ static void dispc_save_context(void) for (j = 0; j < 5; j++) SR(OVL_CONV_COEF(i, j)); - if (dss_has_feature(FEAT_FIR_COEF_V)) { + if (dispc_has_feature(FEAT_FIR_COEF_V)) { for (j = 0; j < 8; j++) SR(OVL_FIR_COEF_V(i, j)); } - if (dss_has_feature(FEAT_HANDLE_UV_SEPARATE)) { + if (dispc_has_feature(FEAT_HANDLE_UV_SEPARATE)) { SR(OVL_BA0_UV(i)); SR(OVL_BA1_UV(i)); SR(OVL_FIR2(i)); @@ -443,11 +527,11 @@ static void dispc_save_context(void) for (j = 0; j < 8; j++) SR(OVL_FIR_COEF_V2(i, j)); } - if (dss_has_feature(FEAT_ATTR2)) + if (dispc_has_feature(FEAT_ATTR2)) SR(OVL_ATTRIBUTES2(i)); } - if (dss_has_feature(FEAT_CORE_CLK_DIV)) + if (dispc_has_feature(FEAT_CORE_CLK_DIV)) SR(DIVISOR); dispc.ctx_valid = true; @@ -468,15 +552,15 @@ static void dispc_restore_context(void) /*RR(CONTROL);*/ RR(CONFIG); RR(LINE_NUMBER); - if (dss_has_feature(FEAT_ALPHA_FIXED_ZORDER) || - dss_has_feature(FEAT_ALPHA_FREE_ZORDER)) + if (dispc_has_feature(FEAT_ALPHA_FIXED_ZORDER) || + dispc_has_feature(FEAT_ALPHA_FREE_ZORDER)) RR(GLOBAL_ALPHA); - if (dss_has_feature(FEAT_MGR_LCD2)) + if (dispc_has_feature(FEAT_MGR_LCD2)) RR(CONFIG2); - if (dss_has_feature(FEAT_MGR_LCD3)) + if (dispc_has_feature(FEAT_MGR_LCD3)) RR(CONFIG3); - for (i = 0; i < dss_feat_get_num_mgrs(); i++) { + for (i = 0; i < dispc_get_num_mgrs(); i++) { RR(DEFAULT_COLOR(i)); RR(TRANS_COLOR(i)); RR(SIZE_MGR(i)); @@ -491,14 +575,14 @@ static void dispc_restore_context(void) RR(DATA_CYCLE2(i)); RR(DATA_CYCLE3(i)); - if (dss_has_feature(FEAT_CPR)) { + if (dispc_has_feature(FEAT_CPR)) { RR(CPR_COEF_R(i)); RR(CPR_COEF_G(i)); RR(CPR_COEF_B(i)); } } - for (i = 0; i < dss_feat_get_num_ovls(); i++) { + for (i = 0; i < dispc_get_num_ovls(); i++) { RR(OVL_BA0(i)); RR(OVL_BA1(i)); RR(OVL_POSITION(i)); @@ -507,7 +591,7 @@ static void dispc_restore_context(void) RR(OVL_FIFO_THRESHOLD(i)); RR(OVL_ROW_INC(i)); RR(OVL_PIXEL_INC(i)); - if (dss_has_feature(FEAT_PRELOAD)) + if (dispc_has_feature(FEAT_PRELOAD)) RR(OVL_PRELOAD(i)); if (i == OMAP_DSS_GFX) { RR(OVL_WINDOW_SKIP(i)); @@ -528,12 +612,12 @@ static void dispc_restore_context(void) for (j = 0; j < 5; j++) RR(OVL_CONV_COEF(i, j)); - if (dss_has_feature(FEAT_FIR_COEF_V)) { + if (dispc_has_feature(FEAT_FIR_COEF_V)) { for (j = 0; j < 8; j++) RR(OVL_FIR_COEF_V(i, j)); } - if (dss_has_feature(FEAT_HANDLE_UV_SEPARATE)) { + if (dispc_has_feature(FEAT_HANDLE_UV_SEPARATE)) { RR(OVL_BA0_UV(i)); RR(OVL_BA1_UV(i)); RR(OVL_FIR2(i)); @@ -549,18 +633,18 @@ static void dispc_restore_context(void) for (j = 0; j < 8; j++) RR(OVL_FIR_COEF_V2(i, j)); } - if (dss_has_feature(FEAT_ATTR2)) + if (dispc_has_feature(FEAT_ATTR2)) RR(OVL_ATTRIBUTES2(i)); } - if (dss_has_feature(FEAT_CORE_CLK_DIV)) + if (dispc_has_feature(FEAT_CORE_CLK_DIV)) RR(DIVISOR); /* enable last, because LCD & DIGIT enable are here */ RR(CONTROL); - if (dss_has_feature(FEAT_MGR_LCD2)) + if (dispc_has_feature(FEAT_MGR_LCD2)) RR(CONTROL2); - if (dss_has_feature(FEAT_MGR_LCD3)) + if (dispc_has_feature(FEAT_MGR_LCD3)) RR(CONTROL3); /* clear spurious SYNC_LOST_DIGIT interrupts */ dispc_clear_irqstatus(DISPC_IRQ_SYNC_LOST_DIGIT); @@ -779,7 +863,7 @@ static void dispc_ovl_write_color_conv_coef(enum omap_plane_id plane, static void dispc_setup_color_conv_coef(void) { int i; - int num_ovl = dss_feat_get_num_ovls(); + int num_ovl = dispc_get_num_ovls(); const struct color_conv_coef ctbl_bt601_5_ovl = { /* YUV -> RGB */ 298, 409, 0, 298, -208, -100, 298, 0, 517, 0, @@ -868,10 +952,10 @@ static void dispc_ovl_enable_zorder_planes(void) { int i; - if (!dss_has_feature(FEAT_ALPHA_FREE_ZORDER)) + if (!dispc_has_feature(FEAT_ALPHA_FREE_ZORDER)) return; - for (i = 0; i < dss_feat_get_num_ovls(); i++) + for (i = 0; i < dispc_get_num_ovls(); i++) REG_FLD_MOD(DISPC_OVL_ATTRIBUTES(i), 1, 25, 25); } @@ -994,7 +1078,7 @@ static bool format_is_yuv(u32 fourcc) static void dispc_ovl_configure_burst_type(enum omap_plane_id plane, enum omap_dss_rotation_type rotation_type) { - if (dss_has_feature(FEAT_BURST_2D) == 0) + if (dispc_has_feature(FEAT_BURST_2D) == 0) return; if (rotation_type == OMAP_DSS_ROT_TILER) @@ -1025,7 +1109,7 @@ static void dispc_ovl_set_channel_out(enum omap_plane_id plane, } val = dispc_read_reg(DISPC_OVL_ATTRIBUTES(plane)); - if (dss_has_feature(FEAT_MGR_LCD2)) { + if (dispc_has_feature(FEAT_MGR_LCD2)) { switch (channel) { case OMAP_DSS_CHANNEL_LCD: chan = 0; @@ -1040,7 +1124,7 @@ static void dispc_ovl_set_channel_out(enum omap_plane_id plane, chan2 = 1; break; case OMAP_DSS_CHANNEL_LCD3: - if (dss_has_feature(FEAT_MGR_LCD3)) { + if (dispc_has_feature(FEAT_MGR_LCD3)) { chan = 0; chan2 = 2; } else { @@ -1089,7 +1173,7 @@ static enum omap_channel dispc_ovl_get_channel_out(enum omap_plane_id plane) if (FLD_GET(val, shift, shift) == 1) return OMAP_DSS_CHANNEL_DIGIT; - if (!dss_has_feature(FEAT_MGR_LCD2)) + if (!dispc_has_feature(FEAT_MGR_LCD2)) return OMAP_DSS_CHANNEL_LCD; switch (FLD_GET(val, 31, 30)) { @@ -1128,7 +1212,7 @@ static void dispc_configure_burst_sizes(void) const int burst_size = BURST_SIZE_X8; /* Configure burst size always to maximum size */ - for (i = 0; i < dss_feat_get_num_ovls(); ++i) + for (i = 0; i < dispc_get_num_ovls(); ++i) dispc_ovl_set_burst_size(i, burst_size); if (dispc.feat->has_writeback) dispc_ovl_set_burst_size(OMAP_DSS_WB, burst_size); @@ -1136,19 +1220,28 @@ static void dispc_configure_burst_sizes(void) static u32 dispc_ovl_get_burst_size(enum omap_plane_id plane) { - unsigned unit = dss_feat_get_burst_size_unit(); /* burst multiplier is always x8 (see dispc_configure_burst_sizes()) */ - return unit * 8; + return dispc.feat->burst_size_unit * 8; } -static const u32 *dispc_ovl_get_color_modes(enum omap_plane_id plane) +static bool dispc_ovl_color_mode_supported(enum omap_plane_id plane, u32 fourcc) { - return dss_feat_get_supported_color_modes(plane); + const u32 *modes; + unsigned int i; + + modes = dispc.feat->supported_color_modes[plane]; + + for (i = 0; modes[i]; ++i) { + if (modes[i] == fourcc) + return true; + } + + return false; } -static int dispc_get_num_ovls(void) +static const u32 *dispc_ovl_get_color_modes(enum omap_plane_id plane) { - return dss_feat_get_num_ovls(); + return dispc.feat->supported_color_modes[plane]; } static void dispc_mgr_enable_cpr(enum omap_channel channel, bool enable) @@ -1223,9 +1316,9 @@ static void dispc_init_fifos(void) u32 unit; int i; - unit = dss_feat_get_buffer_size_unit(); + unit = dispc.feat->buffer_size_unit; - dss_feat_get_reg_field(FEAT_REG_FIFOSIZE, &start, &end); + dispc_get_reg_field(FEAT_REG_FIFOSIZE, &start, &end); for (fifo = 0; fifo < dispc.feat->num_fifos; ++fifo) { size = REG_GET(DISPC_OVL_FIFO_SIZE_STATUS(fifo), start, end); @@ -1265,7 +1358,7 @@ static void dispc_init_fifos(void) /* * Setup default fifo thresholds. */ - for (i = 0; i < dss_feat_get_num_ovls(); ++i) { + for (i = 0; i < dispc_get_num_ovls(); ++i) { u32 low, high; const bool use_fifomerge = false; const bool manual_update = false; @@ -1307,7 +1400,7 @@ void dispc_ovl_set_fifo_threshold(enum omap_plane_id plane, u32 low, u8 hi_start, hi_end, lo_start, lo_end; u32 unit; - unit = dss_feat_get_buffer_size_unit(); + unit = dispc.feat->buffer_size_unit; WARN_ON(low % unit != 0); WARN_ON(high % unit != 0); @@ -1315,8 +1408,8 @@ void dispc_ovl_set_fifo_threshold(enum omap_plane_id plane, u32 low, low /= unit; high /= unit; - dss_feat_get_reg_field(FEAT_REG_FIFOHIGHTHRESHOLD, &hi_start, &hi_end); - dss_feat_get_reg_field(FEAT_REG_FIFOLOWTHRESHOLD, &lo_start, &lo_end); + dispc_get_reg_field(FEAT_REG_FIFOHIGHTHRESHOLD, &hi_start, &hi_end); + dispc_get_reg_field(FEAT_REG_FIFOLOWTHRESHOLD, &lo_start, &lo_end); DSSDBG("fifo(%d) threshold (bytes), old %u/%u, new %u/%u\n", plane, @@ -1335,14 +1428,14 @@ void dispc_ovl_set_fifo_threshold(enum omap_plane_id plane, u32 low, * large for the preload field, set the threshold to the maximum value * that can be held by the preload register */ - if (dss_has_feature(FEAT_PRELOAD) && dispc.feat->set_max_preload && + if (dispc_has_feature(FEAT_PRELOAD) && dispc.feat->set_max_preload && plane != OMAP_DSS_WB) dispc_write_reg(DISPC_OVL_PRELOAD(plane), min(high, 0xfffu)); } void dispc_enable_fifomerge(bool enable) { - if (!dss_has_feature(FEAT_FIFO_MERGE)) { + if (!dispc_has_feature(FEAT_FIFO_MERGE)) { WARN_ON(enable); return; } @@ -1360,7 +1453,7 @@ void dispc_ovl_compute_fifo_thresholds(enum omap_plane_id plane, * buffer_units, and the fifo thresholds must be buffer_unit aligned. */ - unsigned buf_unit = dss_feat_get_buffer_size_unit(); + unsigned buf_unit = dispc.feat->buffer_size_unit; unsigned ovl_fifo_size, total_fifo_size, burst_size; int i; @@ -1369,7 +1462,7 @@ void dispc_ovl_compute_fifo_thresholds(enum omap_plane_id plane, if (use_fifomerge) { total_fifo_size = 0; - for (i = 0; i < dss_feat_get_num_ovls(); ++i) + for (i = 0; i < dispc_get_num_ovls(); ++i) total_fifo_size += dispc_ovl_get_fifo_size(i); } else { total_fifo_size = ovl_fifo_size; @@ -1381,7 +1474,7 @@ void dispc_ovl_compute_fifo_thresholds(enum omap_plane_id plane, * combined fifo size */ - if (manual_update && dss_has_feature(FEAT_OMAP3_DSI_FIFO_BUG)) { + if (manual_update && dispc_has_feature(FEAT_OMAP3_DSI_FIFO_BUG)) { *fifo_low = ovl_fifo_size - burst_size * 2; *fifo_high = total_fifo_size - burst_size; } else if (plane == OMAP_DSS_WB) { @@ -1435,9 +1528,9 @@ static void dispc_init_mflag(void) (1 << 0) | /* MFLAG_CTRL = force always on */ (0 << 2)); /* MFLAG_START = disable */ - for (i = 0; i < dss_feat_get_num_ovls(); ++i) { + for (i = 0; i < dispc_get_num_ovls(); ++i) { u32 size = dispc_ovl_get_fifo_size(i); - u32 unit = dss_feat_get_buffer_size_unit(); + u32 unit = dispc.feat->buffer_size_unit; u32 low, high; dispc_ovl_set_mflag(i, true); @@ -1456,7 +1549,7 @@ static void dispc_init_mflag(void) if (dispc.feat->has_writeback) { u32 size = dispc_ovl_get_fifo_size(OMAP_DSS_WB); - u32 unit = dss_feat_get_buffer_size_unit(); + u32 unit = dispc.feat->buffer_size_unit; u32 low, high; dispc_ovl_set_mflag(OMAP_DSS_WB, true); @@ -1483,10 +1576,8 @@ static void dispc_ovl_set_fir(enum omap_plane_id plane, if (color_comp == DISPC_COLOR_COMPONENT_RGB_Y) { u8 hinc_start, hinc_end, vinc_start, vinc_end; - dss_feat_get_reg_field(FEAT_REG_FIRHINC, - &hinc_start, &hinc_end); - dss_feat_get_reg_field(FEAT_REG_FIRVINC, - &vinc_start, &vinc_end); + dispc_get_reg_field(FEAT_REG_FIRHINC, &hinc_start, &hinc_end); + dispc_get_reg_field(FEAT_REG_FIRVINC, &vinc_start, &vinc_end); val = FLD_VAL(vinc, vinc_start, vinc_end) | FLD_VAL(hinc, hinc_start, hinc_end); @@ -1503,8 +1594,8 @@ static void dispc_ovl_set_vid_accu0(enum omap_plane_id plane, int haccu, u32 val; u8 hor_start, hor_end, vert_start, vert_end; - dss_feat_get_reg_field(FEAT_REG_HORIZONTALACCU, &hor_start, &hor_end); - dss_feat_get_reg_field(FEAT_REG_VERTICALACCU, &vert_start, &vert_end); + dispc_get_reg_field(FEAT_REG_HORIZONTALACCU, &hor_start, &hor_end); + dispc_get_reg_field(FEAT_REG_VERTICALACCU, &vert_start, &vert_end); val = FLD_VAL(vaccu, vert_start, vert_end) | FLD_VAL(haccu, hor_start, hor_end); @@ -1518,8 +1609,8 @@ static void dispc_ovl_set_vid_accu1(enum omap_plane_id plane, int haccu, u32 val; u8 hor_start, hor_end, vert_start, vert_end; - dss_feat_get_reg_field(FEAT_REG_HORIZONTALACCU, &hor_start, &hor_end); - dss_feat_get_reg_field(FEAT_REG_VERTICALACCU, &vert_start, &vert_end); + dispc_get_reg_field(FEAT_REG_HORIZONTALACCU, &hor_start, &hor_end); + dispc_get_reg_field(FEAT_REG_VERTICALACCU, &vert_start, &vert_end); val = FLD_VAL(vaccu, vert_start, vert_end) | FLD_VAL(haccu, hor_start, hor_end); @@ -1671,14 +1762,14 @@ static void dispc_ovl_set_scaling_common(enum omap_plane_id plane, l |= five_taps ? (1 << 21) : 0; /* VRESIZECONF and HRESIZECONF */ - if (dss_has_feature(FEAT_RESIZECONF)) { + if (dispc_has_feature(FEAT_RESIZECONF)) { l &= ~(0x3 << 7); l |= (orig_width <= out_width) ? 0 : (1 << 7); l |= (orig_height <= out_height) ? 0 : (1 << 8); } /* LINEBUFFERSPLIT */ - if (dss_has_feature(FEAT_LINEBUFFERSPLIT)) { + if (dispc_has_feature(FEAT_LINEBUFFERSPLIT)) { l &= ~(0x1 << 22); l |= five_taps ? (1 << 22) : 0; } @@ -1713,7 +1804,7 @@ static void dispc_ovl_set_scaling_uv(enum omap_plane_id plane, int scale_y = out_height != orig_height; bool chroma_upscale = plane != OMAP_DSS_WB; - if (!dss_has_feature(FEAT_HANDLE_UV_SEPARATE)) + if (!dispc_has_feature(FEAT_HANDLE_UV_SEPARATE)) return; if (!format_is_yuv(fourcc)) { @@ -1860,11 +1951,11 @@ static void dispc_ovl_set_rotation_attrs(enum omap_plane_id plane, u8 rotation, vidrot = 1; REG_FLD_MOD(DISPC_OVL_ATTRIBUTES(plane), vidrot, 13, 12); - if (dss_has_feature(FEAT_ROWREPEATENABLE)) + if (dispc_has_feature(FEAT_ROWREPEATENABLE)) REG_FLD_MOD(DISPC_OVL_ATTRIBUTES(plane), row_repeat ? 1 : 0, 18, 18); - if (dss_feat_color_mode_supported(plane, DRM_FORMAT_NV12)) { + if (dispc_ovl_color_mode_supported(plane, DRM_FORMAT_NV12)) { bool doublestride = fourcc == DRM_FORMAT_NV12 && rotation_type == OMAP_DSS_ROT_TILER && @@ -2118,8 +2209,7 @@ static int dispc_ovl_calc_scaling_24xx(unsigned long pclk, unsigned long lclk, int error; u16 in_width, in_height; int min_factor = min(*decim_x, *decim_y); - const int maxsinglelinewidth = - dss_feat_get_param_max(FEAT_PARAM_LINEWIDTH); + const int maxsinglelinewidth = dispc.feat->max_line_width; *five_taps = false; @@ -2163,8 +2253,7 @@ static int dispc_ovl_calc_scaling_34xx(unsigned long pclk, unsigned long lclk, { int error; u16 in_width, in_height; - const int maxsinglelinewidth = - dss_feat_get_param_max(FEAT_PARAM_LINEWIDTH); + const int maxsinglelinewidth = dispc.feat->max_line_width; do { in_height = height / *decim_y; @@ -2249,9 +2338,8 @@ static int dispc_ovl_calc_scaling_44xx(unsigned long pclk, unsigned long lclk, u16 in_width, in_width_max; int decim_x_min = *decim_x; u16 in_height = height / *decim_y; - const int maxsinglelinewidth = - dss_feat_get_param_max(FEAT_PARAM_LINEWIDTH); - const int maxdownscale = dss_feat_get_param_max(FEAT_PARAM_DOWNSCALE); + const int maxsinglelinewidth = dispc.feat->max_line_width; + const int maxdownscale = dispc.feat->max_downscale; if (mem_to_mem) { in_width_max = out_width * maxdownscale; @@ -2311,7 +2399,7 @@ static int dispc_ovl_calc_scaling(unsigned long pclk, unsigned long lclk, int *x_predecim, int *y_predecim, u16 pos_x, enum omap_dss_rotation_type rotation_type, bool mem_to_mem) { - const int maxdownscale = dss_feat_get_param_max(FEAT_PARAM_DOWNSCALE); + const int maxdownscale = dispc.feat->max_downscale; const int max_decim_limit = 16; unsigned long core_clk = 0; int decim_x, decim_y, ret; @@ -2332,7 +2420,7 @@ static int dispc_ovl_calc_scaling(unsigned long pclk, unsigned long lclk, } else { *x_predecim = max_decim_limit; *y_predecim = (rotation_type == OMAP_DSS_ROT_TILER && - dss_has_feature(FEAT_BURST_2D)) ? + dispc_has_feature(FEAT_BURST_2D)) ? 2 : max_decim_limit; } @@ -2428,7 +2516,7 @@ static int dispc_ovl_setup_common(enum omap_plane_id plane, out_height); } - if (!dss_feat_color_mode_supported(plane, fourcc)) + if (!dispc_ovl_color_mode_supported(plane, fourcc)) return -EINVAL; r = dispc_ovl_calc_scaling(pclk, lclk, caps, vm, in_width, @@ -2549,7 +2637,7 @@ static int dispc_ovl_setup(enum omap_plane_id plane, enum omap_channel channel) { int r; - enum omap_overlay_caps caps = dss_feat_get_overlay_caps(plane); + enum omap_overlay_caps caps = dispc.feat->overlay_caps[plane]; const bool replication = true; DSSDBG("dispc_ovl_setup %d, pa %pad, pa_uv %pad, sw %d, %d,%d, %dx%d ->" @@ -2647,12 +2735,12 @@ static int dispc_ovl_enable(enum omap_plane_id plane, bool enable) static enum omap_dss_output_id dispc_mgr_get_supported_outputs(enum omap_channel channel) { - return dss_feat_get_supported_outputs(channel); + return dss_get_supported_outputs(channel); } static void dispc_lcd_enable_signal_polarity(bool act_high) { - if (!dss_has_feature(FEAT_LCDENABLEPOL)) + if (!dispc_has_feature(FEAT_LCDENABLEPOL)) return; REG_FLD_MOD(DISPC_CONTROL, act_high ? 1 : 0, 29, 29); @@ -2660,7 +2748,7 @@ static void dispc_lcd_enable_signal_polarity(bool act_high) void dispc_lcd_enable_signal(bool enable) { - if (!dss_has_feature(FEAT_LCDENABLESIGNAL)) + if (!dispc_has_feature(FEAT_LCDENABLESIGNAL)) return; REG_FLD_MOD(DISPC_CONTROL, enable ? 1 : 0, 28, 28); @@ -2668,17 +2756,12 @@ void dispc_lcd_enable_signal(bool enable) void dispc_pck_free_enable(bool enable) { - if (!dss_has_feature(FEAT_PCKFREEENABLE)) + if (!dispc_has_feature(FEAT_PCKFREEENABLE)) return; REG_FLD_MOD(DISPC_CONTROL, enable ? 1 : 0, 27, 27); } -static int dispc_get_num_mgrs(void) -{ - return dss_feat_get_num_mgrs(); -} - static void dispc_mgr_enable_fifohandcheck(enum omap_channel channel, bool enable) { mgr_fld_write(channel, DISPC_MGR_FLD_FIFOHANDCHECK, enable); @@ -2718,7 +2801,7 @@ static void dispc_mgr_enable_trans_key(enum omap_channel ch, bool enable) static void dispc_mgr_enable_alpha_fixed_zorder(enum omap_channel ch, bool enable) { - if (!dss_has_feature(FEAT_ALPHA_FIXED_ZORDER)) + if (!dispc_has_feature(FEAT_ALPHA_FIXED_ZORDER)) return; if (ch == OMAP_DSS_CHANNEL_LCD) @@ -2735,7 +2818,7 @@ static void dispc_mgr_setup(enum omap_channel channel, dispc_mgr_enable_trans_key(channel, info->trans_enabled); dispc_mgr_enable_alpha_fixed_zorder(channel, info->partial_alpha_enabled); - if (dss_has_feature(FEAT_CPR)) { + if (dispc_has_feature(FEAT_CPR)) { dispc_mgr_enable_cpr(channel, info->cpr_enable); dispc_mgr_set_cpr_coef(channel, &info->cpr_coefs); } @@ -3013,7 +3096,7 @@ static void dispc_mgr_set_lcd_divisor(enum omap_channel channel, u16 lck_div, dispc_write_reg(DISPC_DIVISORo(channel), FLD_VAL(lck_div, 23, 16) | FLD_VAL(pck_div, 7, 0)); - if (!dss_has_feature(FEAT_CORE_CLK_DIV) && + if (!dispc_has_feature(FEAT_CORE_CLK_DIV) && channel == OMAP_DSS_CHANNEL_LCD) dispc.core_clk_rate = dispc_fclk_rate() / lck_div; } @@ -3168,7 +3251,7 @@ void dispc_dump_clocks(struct seq_file *s) seq_printf(s, "fck\t\t%-16lu\n", dispc_fclk_rate()); - if (dss_has_feature(FEAT_CORE_CLK_DIV)) { + if (dispc_has_feature(FEAT_CORE_CLK_DIV)) { seq_printf(s, "- DISPC-CORE-CLK -\n"); l = dispc_read_reg(DISPC_DIVISOR); lcd = FLD_GET(l, 23, 16); @@ -3179,9 +3262,9 @@ void dispc_dump_clocks(struct seq_file *s) dispc_dump_clocks_channel(s, OMAP_DSS_CHANNEL_LCD); - if (dss_has_feature(FEAT_MGR_LCD2)) + if (dispc_has_feature(FEAT_MGR_LCD2)) dispc_dump_clocks_channel(s, OMAP_DSS_CHANNEL_LCD2); - if (dss_has_feature(FEAT_MGR_LCD3)) + if (dispc_has_feature(FEAT_MGR_LCD3)) dispc_dump_clocks_channel(s, OMAP_DSS_CHANNEL_LCD3); dispc_runtime_put(); @@ -3221,18 +3304,18 @@ static void dispc_dump_regs(struct seq_file *s) DUMPREG(DISPC_CAPABLE); DUMPREG(DISPC_LINE_STATUS); DUMPREG(DISPC_LINE_NUMBER); - if (dss_has_feature(FEAT_ALPHA_FIXED_ZORDER) || - dss_has_feature(FEAT_ALPHA_FREE_ZORDER)) + if (dispc_has_feature(FEAT_ALPHA_FIXED_ZORDER) || + dispc_has_feature(FEAT_ALPHA_FREE_ZORDER)) DUMPREG(DISPC_GLOBAL_ALPHA); - if (dss_has_feature(FEAT_MGR_LCD2)) { + if (dispc_has_feature(FEAT_MGR_LCD2)) { DUMPREG(DISPC_CONTROL2); DUMPREG(DISPC_CONFIG2); } - if (dss_has_feature(FEAT_MGR_LCD3)) { + if (dispc_has_feature(FEAT_MGR_LCD3)) { DUMPREG(DISPC_CONTROL3); DUMPREG(DISPC_CONFIG3); } - if (dss_has_feature(FEAT_MFLAG)) + if (dispc_has_feature(FEAT_MFLAG)) DUMPREG(DISPC_GLOBAL_MFLAG_ATTRIBUTE); #undef DUMPREG @@ -3245,7 +3328,7 @@ static void dispc_dump_regs(struct seq_file *s) p_names = mgr_names; /* DISPC channel specific registers */ - for (i = 0; i < dss_feat_get_num_mgrs(); i++) { + for (i = 0; i < dispc_get_num_mgrs(); i++) { DUMPREG(i, DISPC_DEFAULT_COLOR); DUMPREG(i, DISPC_TRANS_COLOR); DUMPREG(i, DISPC_SIZE_MGR); @@ -3262,7 +3345,7 @@ static void dispc_dump_regs(struct seq_file *s) DUMPREG(i, DISPC_DATA_CYCLE2); DUMPREG(i, DISPC_DATA_CYCLE3); - if (dss_has_feature(FEAT_CPR)) { + if (dispc_has_feature(FEAT_CPR)) { DUMPREG(i, DISPC_CPR_COEF_R); DUMPREG(i, DISPC_CPR_COEF_G); DUMPREG(i, DISPC_CPR_COEF_B); @@ -3271,7 +3354,7 @@ static void dispc_dump_regs(struct seq_file *s) p_names = ovl_names; - for (i = 0; i < dss_feat_get_num_ovls(); i++) { + for (i = 0; i < dispc_get_num_ovls(); i++) { DUMPREG(i, DISPC_OVL_BA0); DUMPREG(i, DISPC_OVL_BA1); DUMPREG(i, DISPC_OVL_POSITION); @@ -3282,9 +3365,9 @@ static void dispc_dump_regs(struct seq_file *s) DUMPREG(i, DISPC_OVL_ROW_INC); DUMPREG(i, DISPC_OVL_PIXEL_INC); - if (dss_has_feature(FEAT_PRELOAD)) + if (dispc_has_feature(FEAT_PRELOAD)) DUMPREG(i, DISPC_OVL_PRELOAD); - if (dss_has_feature(FEAT_MFLAG)) + if (dispc_has_feature(FEAT_MFLAG)) DUMPREG(i, DISPC_OVL_MFLAG_THRESHOLD); if (i == OMAP_DSS_GFX) { @@ -3297,14 +3380,14 @@ static void dispc_dump_regs(struct seq_file *s) DUMPREG(i, DISPC_OVL_PICTURE_SIZE); DUMPREG(i, DISPC_OVL_ACCU0); DUMPREG(i, DISPC_OVL_ACCU1); - if (dss_has_feature(FEAT_HANDLE_UV_SEPARATE)) { + if (dispc_has_feature(FEAT_HANDLE_UV_SEPARATE)) { DUMPREG(i, DISPC_OVL_BA0_UV); DUMPREG(i, DISPC_OVL_BA1_UV); DUMPREG(i, DISPC_OVL_FIR2); DUMPREG(i, DISPC_OVL_ACCU2_0); DUMPREG(i, DISPC_OVL_ACCU2_1); } - if (dss_has_feature(FEAT_ATTR2)) + if (dispc_has_feature(FEAT_ATTR2)) DUMPREG(i, DISPC_OVL_ATTRIBUTES2); } @@ -3319,21 +3402,21 @@ static void dispc_dump_regs(struct seq_file *s) DUMPREG(i, DISPC_OVL_ROW_INC); DUMPREG(i, DISPC_OVL_PIXEL_INC); - if (dss_has_feature(FEAT_MFLAG)) + if (dispc_has_feature(FEAT_MFLAG)) DUMPREG(i, DISPC_OVL_MFLAG_THRESHOLD); DUMPREG(i, DISPC_OVL_FIR); DUMPREG(i, DISPC_OVL_PICTURE_SIZE); DUMPREG(i, DISPC_OVL_ACCU0); DUMPREG(i, DISPC_OVL_ACCU1); - if (dss_has_feature(FEAT_HANDLE_UV_SEPARATE)) { + if (dispc_has_feature(FEAT_HANDLE_UV_SEPARATE)) { DUMPREG(i, DISPC_OVL_BA0_UV); DUMPREG(i, DISPC_OVL_BA1_UV); DUMPREG(i, DISPC_OVL_FIR2); DUMPREG(i, DISPC_OVL_ACCU2_0); DUMPREG(i, DISPC_OVL_ACCU2_1); } - if (dss_has_feature(FEAT_ATTR2)) + if (dispc_has_feature(FEAT_ATTR2)) DUMPREG(i, DISPC_OVL_ATTRIBUTES2); } @@ -3349,7 +3432,7 @@ static void dispc_dump_regs(struct seq_file *s) /* Video pipeline coefficient registers */ /* start from OMAP_DSS_VIDEO1 */ - for (i = 1; i < dss_feat_get_num_ovls(); i++) { + for (i = 1; i < dispc_get_num_ovls(); i++) { for (j = 0; j < 8; j++) DUMPREG(i, DISPC_OVL_FIR_COEF_H, j); @@ -3359,12 +3442,12 @@ static void dispc_dump_regs(struct seq_file *s) for (j = 0; j < 5; j++) DUMPREG(i, DISPC_OVL_CONV_COEF, j); - if (dss_has_feature(FEAT_FIR_COEF_V)) { + if (dispc_has_feature(FEAT_FIR_COEF_V)) { for (j = 0; j < 8; j++) DUMPREG(i, DISPC_OVL_FIR_COEF_V, j); } - if (dss_has_feature(FEAT_HANDLE_UV_SEPARATE)) { + if (dispc_has_feature(FEAT_HANDLE_UV_SEPARATE)) { for (j = 0; j < 8; j++) DUMPREG(i, DISPC_OVL_FIR_COEF_H2, j); @@ -3397,7 +3480,7 @@ int dispc_calc_clock_rates(unsigned long dispc_fclk_rate, return 0; } -bool dispc_div_calc(unsigned long dispc, +bool dispc_div_calc(unsigned long dispc_freq, unsigned long pck_min, unsigned long pck_max, dispc_div_calc_func func, void *data) { @@ -3415,19 +3498,19 @@ bool dispc_div_calc(unsigned long dispc, min_fck_per_pck = 0; #endif - pckd_hw_min = dss_feat_get_param_min(FEAT_PARAM_DSS_PCD); - pckd_hw_max = dss_feat_get_param_max(FEAT_PARAM_DSS_PCD); + pckd_hw_min = dispc.feat->min_pcd; + pckd_hw_max = 255; - lck_max = dss_feat_get_param_max(FEAT_PARAM_DSS_FCK); + lck_max = dss_get_max_fck_rate(); pck_min = pck_min ? pck_min : 1; pck_max = pck_max ? pck_max : ULONG_MAX; - lckd_start = max(DIV_ROUND_UP(dispc, lck_max), 1ul); - lckd_stop = min(dispc / pck_min, 255ul); + lckd_start = max(DIV_ROUND_UP(dispc_freq, lck_max), 1ul); + lckd_stop = min(dispc_freq / pck_min, 255ul); for (lckd = lckd_start; lckd <= lckd_stop; ++lckd) { - lck = dispc / lckd; + lck = dispc_freq / lckd; pckd_start = max(DIV_ROUND_UP(lck, pck_max), pckd_hw_min); pckd_stop = min(lck / pck_min, pckd_hw_max); @@ -3441,7 +3524,7 @@ bool dispc_div_calc(unsigned long dispc, * also. Thus we need to use the calculated lck. For * OMAP4+ the DISPC fclk is a separate clock. */ - if (dss_has_feature(FEAT_CORE_CLK_DIV)) + if (dispc_has_feature(FEAT_CORE_CLK_DIV)) fck = dispc_core_clk_rate(); else fck = lck; @@ -3556,10 +3639,10 @@ static void dispc_restore_gamma_tables(void) dispc_mgr_write_gamma_table(OMAP_DSS_CHANNEL_DIGIT); - if (dss_has_feature(FEAT_MGR_LCD2)) + if (dispc_has_feature(FEAT_MGR_LCD2)) dispc_mgr_write_gamma_table(OMAP_DSS_CHANNEL_LCD2); - if (dss_has_feature(FEAT_MGR_LCD3)) + if (dispc_has_feature(FEAT_MGR_LCD3)) dispc_mgr_write_gamma_table(OMAP_DSS_CHANNEL_LCD3); } @@ -3627,11 +3710,11 @@ static int dispc_init_gamma_tables(void) u32 *gt; if (channel == OMAP_DSS_CHANNEL_LCD2 && - !dss_has_feature(FEAT_MGR_LCD2)) + !dispc_has_feature(FEAT_MGR_LCD2)) continue; if (channel == OMAP_DSS_CHANNEL_LCD3 && - !dss_has_feature(FEAT_MGR_LCD3)) + !dispc_has_feature(FEAT_MGR_LCD3)) continue; gt = devm_kmalloc_array(&dispc.pdev->dev, gdesc->len, @@ -3651,7 +3734,7 @@ static void _omap_dispc_initial_config(void) u32 l; /* Exclusively enable DISPC_CORE_CLK and set divider to 1 */ - if (dss_has_feature(FEAT_CORE_CLK_DIV)) { + if (dispc_has_feature(FEAT_CORE_CLK_DIV)) { l = dispc_read_reg(DISPC_DIVISOR); /* Use DISPC_DIVISOR.LCD, instead of DISPC_DIVISOR1.LCD */ l = FLD_MOD(l, 1, 0, 0); @@ -3669,7 +3752,7 @@ static void _omap_dispc_initial_config(void) * func-clock auto-gating. For newer versions * (dispc.feat->has_gamma_table) this enables tv-out gamma tables. */ - if (dss_has_feature(FEAT_FUNCGATED) || dispc.feat->has_gamma_table) + if (dispc_has_feature(FEAT_FUNCGATED) || dispc.feat->has_gamma_table) REG_FLD_MOD(DISPC_CONFIG, 1, 9, 9); dispc_setup_color_conv_coef(); @@ -3685,10 +3768,272 @@ static void _omap_dispc_initial_config(void) if (dispc.feat->mstandby_workaround) REG_FLD_MOD(DISPC_MSTANDBY_CTRL, 1, 0, 0); - if (dss_has_feature(FEAT_MFLAG)) + if (dispc_has_feature(FEAT_MFLAG)) dispc_init_mflag(); } +static const enum dispc_feature_id omap2_dispc_features_list[] = { + FEAT_LCDENABLEPOL, + FEAT_LCDENABLESIGNAL, + FEAT_PCKFREEENABLE, + FEAT_FUNCGATED, + FEAT_ROWREPEATENABLE, + FEAT_RESIZECONF, +}; + +static const enum dispc_feature_id omap3_dispc_features_list[] = { + FEAT_LCDENABLEPOL, + FEAT_LCDENABLESIGNAL, + FEAT_PCKFREEENABLE, + FEAT_FUNCGATED, + FEAT_LINEBUFFERSPLIT, + FEAT_ROWREPEATENABLE, + FEAT_RESIZECONF, + FEAT_CPR, + FEAT_PRELOAD, + FEAT_FIR_COEF_V, + FEAT_ALPHA_FIXED_ZORDER, + FEAT_FIFO_MERGE, + FEAT_OMAP3_DSI_FIFO_BUG, +}; + +static const enum dispc_feature_id am43xx_dispc_features_list[] = { + FEAT_LCDENABLEPOL, + FEAT_LCDENABLESIGNAL, + FEAT_PCKFREEENABLE, + FEAT_FUNCGATED, + FEAT_LINEBUFFERSPLIT, + FEAT_ROWREPEATENABLE, + FEAT_RESIZECONF, + FEAT_CPR, + FEAT_PRELOAD, + FEAT_FIR_COEF_V, + FEAT_ALPHA_FIXED_ZORDER, + FEAT_FIFO_MERGE, +}; + +static const enum dispc_feature_id omap4_dispc_features_list[] = { + FEAT_MGR_LCD2, + FEAT_CORE_CLK_DIV, + FEAT_HANDLE_UV_SEPARATE, + FEAT_ATTR2, + FEAT_CPR, + FEAT_PRELOAD, + FEAT_FIR_COEF_V, + FEAT_ALPHA_FREE_ZORDER, + FEAT_FIFO_MERGE, + FEAT_BURST_2D, +}; + +static const enum dispc_feature_id omap5_dispc_features_list[] = { + FEAT_MGR_LCD2, + FEAT_MGR_LCD3, + FEAT_CORE_CLK_DIV, + FEAT_HANDLE_UV_SEPARATE, + FEAT_ATTR2, + FEAT_CPR, + FEAT_PRELOAD, + FEAT_FIR_COEF_V, + FEAT_ALPHA_FREE_ZORDER, + FEAT_FIFO_MERGE, + FEAT_BURST_2D, + FEAT_MFLAG, +}; + +static const struct dss_reg_field omap2_dispc_reg_fields[] = { + [FEAT_REG_FIRHINC] = { 11, 0 }, + [FEAT_REG_FIRVINC] = { 27, 16 }, + [FEAT_REG_FIFOLOWTHRESHOLD] = { 8, 0 }, + [FEAT_REG_FIFOHIGHTHRESHOLD] = { 24, 16 }, + [FEAT_REG_FIFOSIZE] = { 8, 0 }, + [FEAT_REG_HORIZONTALACCU] = { 9, 0 }, + [FEAT_REG_VERTICALACCU] = { 25, 16 }, +}; + +static const struct dss_reg_field omap3_dispc_reg_fields[] = { + [FEAT_REG_FIRHINC] = { 12, 0 }, + [FEAT_REG_FIRVINC] = { 28, 16 }, + [FEAT_REG_FIFOLOWTHRESHOLD] = { 11, 0 }, + [FEAT_REG_FIFOHIGHTHRESHOLD] = { 27, 16 }, + [FEAT_REG_FIFOSIZE] = { 10, 0 }, + [FEAT_REG_HORIZONTALACCU] = { 9, 0 }, + [FEAT_REG_VERTICALACCU] = { 25, 16 }, +}; + +static const struct dss_reg_field omap4_dispc_reg_fields[] = { + [FEAT_REG_FIRHINC] = { 12, 0 }, + [FEAT_REG_FIRVINC] = { 28, 16 }, + [FEAT_REG_FIFOLOWTHRESHOLD] = { 15, 0 }, + [FEAT_REG_FIFOHIGHTHRESHOLD] = { 31, 16 }, + [FEAT_REG_FIFOSIZE] = { 15, 0 }, + [FEAT_REG_HORIZONTALACCU] = { 10, 0 }, + [FEAT_REG_VERTICALACCU] = { 26, 16 }, +}; + +static const enum omap_overlay_caps omap2_dispc_overlay_caps[] = { + /* OMAP_DSS_GFX */ + OMAP_DSS_OVL_CAP_POS | OMAP_DSS_OVL_CAP_REPLICATION, + + /* OMAP_DSS_VIDEO1 */ + OMAP_DSS_OVL_CAP_SCALE | OMAP_DSS_OVL_CAP_POS | + OMAP_DSS_OVL_CAP_REPLICATION, + + /* OMAP_DSS_VIDEO2 */ + OMAP_DSS_OVL_CAP_SCALE | OMAP_DSS_OVL_CAP_POS | + OMAP_DSS_OVL_CAP_REPLICATION, +}; + +static const enum omap_overlay_caps omap3430_dispc_overlay_caps[] = { + /* OMAP_DSS_GFX */ + OMAP_DSS_OVL_CAP_GLOBAL_ALPHA | OMAP_DSS_OVL_CAP_POS | + OMAP_DSS_OVL_CAP_REPLICATION, + + /* OMAP_DSS_VIDEO1 */ + OMAP_DSS_OVL_CAP_SCALE | OMAP_DSS_OVL_CAP_POS | + OMAP_DSS_OVL_CAP_REPLICATION, + + /* OMAP_DSS_VIDEO2 */ + OMAP_DSS_OVL_CAP_SCALE | OMAP_DSS_OVL_CAP_GLOBAL_ALPHA | + OMAP_DSS_OVL_CAP_POS | OMAP_DSS_OVL_CAP_REPLICATION, +}; + +static const enum omap_overlay_caps omap3630_dispc_overlay_caps[] = { + /* OMAP_DSS_GFX */ + OMAP_DSS_OVL_CAP_GLOBAL_ALPHA | OMAP_DSS_OVL_CAP_PRE_MULT_ALPHA | + OMAP_DSS_OVL_CAP_POS | OMAP_DSS_OVL_CAP_REPLICATION, + + /* OMAP_DSS_VIDEO1 */ + OMAP_DSS_OVL_CAP_SCALE | OMAP_DSS_OVL_CAP_POS | + OMAP_DSS_OVL_CAP_REPLICATION, + + /* OMAP_DSS_VIDEO2 */ + OMAP_DSS_OVL_CAP_SCALE | OMAP_DSS_OVL_CAP_GLOBAL_ALPHA | + OMAP_DSS_OVL_CAP_PRE_MULT_ALPHA | OMAP_DSS_OVL_CAP_POS | + OMAP_DSS_OVL_CAP_REPLICATION, +}; + +static const enum omap_overlay_caps omap4_dispc_overlay_caps[] = { + /* OMAP_DSS_GFX */ + OMAP_DSS_OVL_CAP_GLOBAL_ALPHA | OMAP_DSS_OVL_CAP_PRE_MULT_ALPHA | + OMAP_DSS_OVL_CAP_ZORDER | OMAP_DSS_OVL_CAP_POS | + OMAP_DSS_OVL_CAP_REPLICATION, + + /* OMAP_DSS_VIDEO1 */ + OMAP_DSS_OVL_CAP_SCALE | OMAP_DSS_OVL_CAP_GLOBAL_ALPHA | + OMAP_DSS_OVL_CAP_PRE_MULT_ALPHA | OMAP_DSS_OVL_CAP_ZORDER | + OMAP_DSS_OVL_CAP_POS | OMAP_DSS_OVL_CAP_REPLICATION, + + /* OMAP_DSS_VIDEO2 */ + OMAP_DSS_OVL_CAP_SCALE | OMAP_DSS_OVL_CAP_GLOBAL_ALPHA | + OMAP_DSS_OVL_CAP_PRE_MULT_ALPHA | OMAP_DSS_OVL_CAP_ZORDER | + OMAP_DSS_OVL_CAP_POS | OMAP_DSS_OVL_CAP_REPLICATION, + + /* OMAP_DSS_VIDEO3 */ + OMAP_DSS_OVL_CAP_SCALE | OMAP_DSS_OVL_CAP_GLOBAL_ALPHA | + OMAP_DSS_OVL_CAP_PRE_MULT_ALPHA | OMAP_DSS_OVL_CAP_ZORDER | + OMAP_DSS_OVL_CAP_POS | OMAP_DSS_OVL_CAP_REPLICATION, +}; + +#define COLOR_ARRAY(arr...) (const u32[]) { arr, 0 } + +static const u32 *omap2_dispc_supported_color_modes[] = { + + /* OMAP_DSS_GFX */ + COLOR_ARRAY( + DRM_FORMAT_RGBX4444, DRM_FORMAT_RGB565, + DRM_FORMAT_XRGB8888, DRM_FORMAT_RGB888), + + /* OMAP_DSS_VIDEO1 */ + COLOR_ARRAY( + DRM_FORMAT_RGB565, DRM_FORMAT_XRGB8888, + DRM_FORMAT_RGB888, DRM_FORMAT_YUYV, + DRM_FORMAT_UYVY), + + /* OMAP_DSS_VIDEO2 */ + COLOR_ARRAY( + DRM_FORMAT_RGB565, DRM_FORMAT_XRGB8888, + DRM_FORMAT_RGB888, DRM_FORMAT_YUYV, + DRM_FORMAT_UYVY), +}; + +static const u32 *omap3_dispc_supported_color_modes[] = { + /* OMAP_DSS_GFX */ + COLOR_ARRAY( + DRM_FORMAT_RGBX4444, DRM_FORMAT_ARGB4444, + DRM_FORMAT_RGB565, DRM_FORMAT_XRGB8888, + DRM_FORMAT_RGB888, DRM_FORMAT_ARGB8888, + DRM_FORMAT_RGBA8888, DRM_FORMAT_RGBX8888), + + /* OMAP_DSS_VIDEO1 */ + COLOR_ARRAY( + DRM_FORMAT_XRGB8888, DRM_FORMAT_RGB888, + DRM_FORMAT_RGBX4444, DRM_FORMAT_RGB565, + DRM_FORMAT_YUYV, DRM_FORMAT_UYVY), + + /* OMAP_DSS_VIDEO2 */ + COLOR_ARRAY( + DRM_FORMAT_RGBX4444, DRM_FORMAT_ARGB4444, + DRM_FORMAT_RGB565, DRM_FORMAT_XRGB8888, + DRM_FORMAT_RGB888, DRM_FORMAT_YUYV, + DRM_FORMAT_UYVY, DRM_FORMAT_ARGB8888, + DRM_FORMAT_RGBA8888, DRM_FORMAT_RGBX8888), +}; + +static const u32 *omap4_dispc_supported_color_modes[] = { + /* OMAP_DSS_GFX */ + COLOR_ARRAY( + DRM_FORMAT_RGBX4444, DRM_FORMAT_ARGB4444, + DRM_FORMAT_RGB565, DRM_FORMAT_XRGB8888, + DRM_FORMAT_RGB888, DRM_FORMAT_ARGB8888, + DRM_FORMAT_RGBA8888, DRM_FORMAT_RGBX8888, + DRM_FORMAT_ARGB1555, DRM_FORMAT_XRGB4444, + DRM_FORMAT_RGBA4444, DRM_FORMAT_XRGB1555), + + /* OMAP_DSS_VIDEO1 */ + COLOR_ARRAY( + DRM_FORMAT_RGB565, DRM_FORMAT_RGBX4444, + DRM_FORMAT_YUYV, DRM_FORMAT_ARGB1555, + DRM_FORMAT_RGBA8888, DRM_FORMAT_NV12, + DRM_FORMAT_RGBA4444, DRM_FORMAT_XRGB8888, + DRM_FORMAT_RGB888, DRM_FORMAT_UYVY, + DRM_FORMAT_ARGB4444, DRM_FORMAT_XRGB1555, + DRM_FORMAT_ARGB8888, DRM_FORMAT_XRGB4444, + DRM_FORMAT_RGBX8888), + + /* OMAP_DSS_VIDEO2 */ + COLOR_ARRAY( + DRM_FORMAT_RGB565, DRM_FORMAT_RGBX4444, + DRM_FORMAT_YUYV, DRM_FORMAT_ARGB1555, + DRM_FORMAT_RGBA8888, DRM_FORMAT_NV12, + DRM_FORMAT_RGBA4444, DRM_FORMAT_XRGB8888, + DRM_FORMAT_RGB888, DRM_FORMAT_UYVY, + DRM_FORMAT_ARGB4444, DRM_FORMAT_XRGB1555, + DRM_FORMAT_ARGB8888, DRM_FORMAT_XRGB4444, + DRM_FORMAT_RGBX8888), + + /* OMAP_DSS_VIDEO3 */ + COLOR_ARRAY( + DRM_FORMAT_RGB565, DRM_FORMAT_RGBX4444, + DRM_FORMAT_YUYV, DRM_FORMAT_ARGB1555, + DRM_FORMAT_RGBA8888, DRM_FORMAT_NV12, + DRM_FORMAT_RGBA4444, DRM_FORMAT_XRGB8888, + DRM_FORMAT_RGB888, DRM_FORMAT_UYVY, + DRM_FORMAT_ARGB4444, DRM_FORMAT_XRGB1555, + DRM_FORMAT_ARGB8888, DRM_FORMAT_XRGB4444, + DRM_FORMAT_RGBX8888), + + /* OMAP_DSS_WB */ + COLOR_ARRAY( + DRM_FORMAT_RGB565, DRM_FORMAT_RGBX4444, + DRM_FORMAT_YUYV, DRM_FORMAT_ARGB1555, + DRM_FORMAT_RGBA8888, DRM_FORMAT_NV12, + DRM_FORMAT_RGBA4444, DRM_FORMAT_XRGB8888, + DRM_FORMAT_RGB888, DRM_FORMAT_UYVY, + DRM_FORMAT_ARGB4444, DRM_FORMAT_XRGB1555, + DRM_FORMAT_ARGB8888, DRM_FORMAT_XRGB4444, + DRM_FORMAT_RGBX8888), +}; + static const struct dispc_features omap24xx_dispc_feats = { .sw_start = 5, .fp_start = 15, @@ -3701,9 +4046,26 @@ static const struct dispc_features omap24xx_dispc_feats = { .mgr_width_max = 2048, .mgr_height_max = 2048, .max_lcd_pclk = 66500000, + .max_downscale = 2, + /* + * Assume the line width buffer to be 768 pixels as OMAP2 DISPC scaler + * cannot scale an image width larger than 768. + */ + .max_line_width = 768, + .min_pcd = 2, .calc_scaling = dispc_ovl_calc_scaling_24xx, .calc_core_clk = calc_core_clk_24xx, .num_fifos = 3, + .features = omap2_dispc_features_list, + .num_features = ARRAY_SIZE(omap2_dispc_features_list), + .reg_fields = omap2_dispc_reg_fields, + .num_reg_fields = ARRAY_SIZE(omap2_dispc_reg_fields), + .overlay_caps = omap2_dispc_overlay_caps, + .supported_color_modes = omap2_dispc_supported_color_modes, + .num_mgrs = 2, + .num_ovls = 3, + .buffer_size_unit = 1, + .burst_size_unit = 8, .no_framedone_tv = true, .set_max_preload = false, .last_pixel_inc_missing = true, @@ -3722,9 +4084,22 @@ static const struct dispc_features omap34xx_rev1_0_dispc_feats = { .mgr_height_max = 2048, .max_lcd_pclk = 173000000, .max_tv_pclk = 59000000, + .max_downscale = 4, + .max_line_width = 1024, + .min_pcd = 1, .calc_scaling = dispc_ovl_calc_scaling_34xx, .calc_core_clk = calc_core_clk_34xx, .num_fifos = 3, + .features = omap3_dispc_features_list, + .num_features = ARRAY_SIZE(omap3_dispc_features_list), + .reg_fields = omap3_dispc_reg_fields, + .num_reg_fields = ARRAY_SIZE(omap3_dispc_reg_fields), + .overlay_caps = omap3430_dispc_overlay_caps, + .supported_color_modes = omap3_dispc_supported_color_modes, + .num_mgrs = 2, + .num_ovls = 3, + .buffer_size_unit = 1, + .burst_size_unit = 8, .no_framedone_tv = true, .set_max_preload = false, .last_pixel_inc_missing = true, @@ -3743,9 +4118,90 @@ static const struct dispc_features omap34xx_rev3_0_dispc_feats = { .mgr_height_max = 2048, .max_lcd_pclk = 173000000, .max_tv_pclk = 59000000, + .max_downscale = 4, + .max_line_width = 1024, + .min_pcd = 1, + .calc_scaling = dispc_ovl_calc_scaling_34xx, + .calc_core_clk = calc_core_clk_34xx, + .num_fifos = 3, + .features = omap3_dispc_features_list, + .num_features = ARRAY_SIZE(omap3_dispc_features_list), + .reg_fields = omap3_dispc_reg_fields, + .num_reg_fields = ARRAY_SIZE(omap3_dispc_reg_fields), + .overlay_caps = omap3430_dispc_overlay_caps, + .supported_color_modes = omap3_dispc_supported_color_modes, + .num_mgrs = 2, + .num_ovls = 3, + .buffer_size_unit = 1, + .burst_size_unit = 8, + .no_framedone_tv = true, + .set_max_preload = false, + .last_pixel_inc_missing = true, +}; + +static const struct dispc_features omap36xx_dispc_feats = { + .sw_start = 7, + .fp_start = 19, + .bp_start = 31, + .sw_max = 256, + .vp_max = 4095, + .hp_max = 4096, + .mgr_width_start = 10, + .mgr_height_start = 26, + .mgr_width_max = 2048, + .mgr_height_max = 2048, + .max_lcd_pclk = 173000000, + .max_tv_pclk = 59000000, + .max_downscale = 4, + .max_line_width = 1024, + .min_pcd = 1, .calc_scaling = dispc_ovl_calc_scaling_34xx, .calc_core_clk = calc_core_clk_34xx, .num_fifos = 3, + .features = omap3_dispc_features_list, + .num_features = ARRAY_SIZE(omap3_dispc_features_list), + .reg_fields = omap3_dispc_reg_fields, + .num_reg_fields = ARRAY_SIZE(omap3_dispc_reg_fields), + .overlay_caps = omap3630_dispc_overlay_caps, + .supported_color_modes = omap3_dispc_supported_color_modes, + .num_mgrs = 2, + .num_ovls = 3, + .buffer_size_unit = 1, + .burst_size_unit = 8, + .no_framedone_tv = true, + .set_max_preload = false, + .last_pixel_inc_missing = true, +}; + +static const struct dispc_features am43xx_dispc_feats = { + .sw_start = 7, + .fp_start = 19, + .bp_start = 31, + .sw_max = 256, + .vp_max = 4095, + .hp_max = 4096, + .mgr_width_start = 10, + .mgr_height_start = 26, + .mgr_width_max = 2048, + .mgr_height_max = 2048, + .max_lcd_pclk = 173000000, + .max_tv_pclk = 59000000, + .max_downscale = 4, + .max_line_width = 1024, + .min_pcd = 1, + .calc_scaling = dispc_ovl_calc_scaling_34xx, + .calc_core_clk = calc_core_clk_34xx, + .num_fifos = 3, + .features = am43xx_dispc_features_list, + .num_features = ARRAY_SIZE(am43xx_dispc_features_list), + .reg_fields = omap3_dispc_reg_fields, + .num_reg_fields = ARRAY_SIZE(omap3_dispc_reg_fields), + .overlay_caps = omap3430_dispc_overlay_caps, + .supported_color_modes = omap3_dispc_supported_color_modes, + .num_mgrs = 1, + .num_ovls = 3, + .buffer_size_unit = 1, + .burst_size_unit = 8, .no_framedone_tv = true, .set_max_preload = false, .last_pixel_inc_missing = true, @@ -3764,9 +4220,22 @@ static const struct dispc_features omap44xx_dispc_feats = { .mgr_height_max = 2048, .max_lcd_pclk = 170000000, .max_tv_pclk = 185625000, + .max_downscale = 4, + .max_line_width = 2048, + .min_pcd = 1, .calc_scaling = dispc_ovl_calc_scaling_44xx, .calc_core_clk = calc_core_clk_44xx, .num_fifos = 5, + .features = omap4_dispc_features_list, + .num_features = ARRAY_SIZE(omap4_dispc_features_list), + .reg_fields = omap4_dispc_reg_fields, + .num_reg_fields = ARRAY_SIZE(omap4_dispc_reg_fields), + .overlay_caps = omap4_dispc_overlay_caps, + .supported_color_modes = omap4_dispc_supported_color_modes, + .num_mgrs = 3, + .num_ovls = 4, + .buffer_size_unit = 16, + .burst_size_unit = 16, .gfx_fifo_workaround = true, .set_max_preload = true, .supports_sync_align = true, @@ -3790,9 +4259,22 @@ static const struct dispc_features omap54xx_dispc_feats = { .mgr_height_max = 4096, .max_lcd_pclk = 170000000, .max_tv_pclk = 186000000, + .max_downscale = 4, + .max_line_width = 2048, + .min_pcd = 1, .calc_scaling = dispc_ovl_calc_scaling_44xx, .calc_core_clk = calc_core_clk_44xx, .num_fifos = 5, + .features = omap5_dispc_features_list, + .num_features = ARRAY_SIZE(omap5_dispc_features_list), + .reg_fields = omap4_dispc_reg_fields, + .num_reg_fields = ARRAY_SIZE(omap4_dispc_reg_fields), + .overlay_caps = omap4_dispc_overlay_caps, + .supported_color_modes = omap4_dispc_supported_color_modes, + .num_mgrs = 4, + .num_ovls = 4, + .buffer_size_unit = 16, + .burst_size_unit = 16, .gfx_fifo_workaround = true, .mstandby_workaround = true, .set_max_preload = true, @@ -3804,54 +4286,6 @@ static const struct dispc_features omap54xx_dispc_feats = { .has_gamma_i734_bug = true, }; -static int dispc_init_features(struct platform_device *pdev) -{ - const struct dispc_features *src; - struct dispc_features *dst; - - dst = devm_kzalloc(&pdev->dev, sizeof(*dst), GFP_KERNEL); - if (!dst) { - dev_err(&pdev->dev, "Failed to allocate DISPC Features\n"); - return -ENOMEM; - } - - switch (omapdss_get_version()) { - case OMAPDSS_VER_OMAP24xx: - src = &omap24xx_dispc_feats; - break; - - case OMAPDSS_VER_OMAP34xx_ES1: - src = &omap34xx_rev1_0_dispc_feats; - break; - - case OMAPDSS_VER_OMAP34xx_ES3: - case OMAPDSS_VER_OMAP3630: - case OMAPDSS_VER_AM35xx: - case OMAPDSS_VER_AM43xx: - src = &omap34xx_rev3_0_dispc_feats; - break; - - case OMAPDSS_VER_OMAP4430_ES1: - case OMAPDSS_VER_OMAP4430_ES2: - case OMAPDSS_VER_OMAP4: - src = &omap44xx_dispc_feats; - break; - - case OMAPDSS_VER_OMAP5: - case OMAPDSS_VER_DRA7xx: - src = &omap54xx_dispc_feats; - break; - - default: - return -ENODEV; - } - - memcpy(dst, src, sizeof(*dst)); - dispc.feat = dst; - - return 0; -} - static irqreturn_t dispc_irq_handler(int irq, void *arg) { if (!dispc.is_enabled) @@ -4083,9 +4517,28 @@ static const struct dispc_ops dispc_ops = { }; /* DISPC HW IP initialisation */ +static const struct of_device_id dispc_of_match[] = { + { .compatible = "ti,omap2-dispc", .data = &omap24xx_dispc_feats }, + { .compatible = "ti,omap3-dispc", .data = &omap36xx_dispc_feats }, + { .compatible = "ti,omap4-dispc", .data = &omap44xx_dispc_feats }, + { .compatible = "ti,omap5-dispc", .data = &omap54xx_dispc_feats }, + { .compatible = "ti,dra7-dispc", .data = &omap54xx_dispc_feats }, + {}, +}; + +static const struct soc_device_attribute dispc_soc_devices[] = { + { .machine = "OMAP3[45]*", + .revision = "ES[12].?", .data = &omap34xx_rev1_0_dispc_feats }, + { .machine = "OMAP3[45]*", .data = &omap34xx_rev3_0_dispc_feats }, + { .machine = "AM35*", .data = &omap34xx_rev3_0_dispc_feats }, + { .machine = "AM43*", .data = &am43xx_dispc_feats }, + { /* sentinel */ } +}; + static int dispc_bind(struct device *dev, struct device *master, void *data) { struct platform_device *pdev = to_platform_device(dev); + const struct soc_device_attribute *soc; u32 rev; int r = 0; struct resource *dispc_mem; @@ -4095,9 +4548,15 @@ static int dispc_bind(struct device *dev, struct device *master, void *data) spin_lock_init(&dispc.control_lock); - r = dispc_init_features(dispc.pdev); - if (r) - return r; + /* + * The OMAP3-based models can't be told apart using the compatible + * string, use SoC device matching. + */ + soc = soc_device_match(dispc_soc_devices); + if (soc) + dispc.feat = soc->data; + else + dispc.feat = of_match_device(dispc_of_match, &pdev->dev)->data; r = dispc_errata_i734_wa_init(); if (r) @@ -4226,15 +4685,6 @@ static const struct dev_pm_ops dispc_pm_ops = { .runtime_resume = dispc_runtime_resume, }; -static const struct of_device_id dispc_of_match[] = { - { .compatible = "ti,omap2-dispc", }, - { .compatible = "ti,omap3-dispc", }, - { .compatible = "ti,omap4-dispc", }, - { .compatible = "ti,omap5-dispc", }, - { .compatible = "ti,dra7-dispc", }, - {}, -}; - static struct platform_driver omap_dispchw_driver = { .probe = dispc_probe, .remove = dispc_remove, diff --git a/drivers/gpu/drm/omapdrm/dss/dpi.c b/drivers/gpu/drm/omapdrm/dss/dpi.c index 86dbb65a6c28..daf286fc8a40 100644 --- a/drivers/gpu/drm/omapdrm/dss/dpi.c +++ b/drivers/gpu/drm/omapdrm/dss/dpi.c @@ -32,13 +32,14 @@ #include <linux/string.h> #include <linux/of.h> #include <linux/clk.h> +#include <linux/sys_soc.h> #include "omapdss.h" #include "dss.h" -#include "dss_features.h" struct dpi_data { struct platform_device *pdev; + enum dss_model dss_model; struct regulator *vdds_dsi_reg; enum dss_clk_source clk_src; @@ -99,25 +100,21 @@ static enum dss_clk_source dpi_get_clk_src_dra7xx(enum omap_channel channel) return DSS_CLK_SRC_FCK; } -static enum dss_clk_source dpi_get_clk_src(enum omap_channel channel) +static enum dss_clk_source dpi_get_clk_src(struct dpi_data *dpi) { + enum omap_channel channel = dpi->output.dispc_channel; + /* * XXX we can't currently use DSI PLL for DPI with OMAP3, as the DSI PLL * would also be used for DISPC fclk. Meaning, when the DPI output is * disabled, DISPC clock will be disabled, and TV out will stop. */ - switch (omapdss_get_version()) { - case OMAPDSS_VER_OMAP24xx: - case OMAPDSS_VER_OMAP34xx_ES1: - case OMAPDSS_VER_OMAP34xx_ES3: - case OMAPDSS_VER_OMAP3630: - case OMAPDSS_VER_AM35xx: - case OMAPDSS_VER_AM43xx: + switch (dpi->dss_model) { + case DSS_MODEL_OMAP2: + case DSS_MODEL_OMAP3: return DSS_CLK_SRC_FCK; - case OMAPDSS_VER_OMAP4430_ES1: - case OMAPDSS_VER_OMAP4430_ES2: - case OMAPDSS_VER_OMAP4: + case DSS_MODEL_OMAP4: switch (channel) { case OMAP_DSS_CHANNEL_LCD: return DSS_CLK_SRC_PLL1_1; @@ -127,7 +124,7 @@ static enum dss_clk_source dpi_get_clk_src(enum omap_channel channel) return DSS_CLK_SRC_FCK; } - case OMAPDSS_VER_OMAP5: + case DSS_MODEL_OMAP5: switch (channel) { case OMAP_DSS_CHANNEL_LCD: return DSS_CLK_SRC_PLL1_1; @@ -138,7 +135,7 @@ static enum dss_clk_source dpi_get_clk_src(enum omap_channel channel) return DSS_CLK_SRC_FCK; } - case OMAPDSS_VER_DRA7xx: + case DSS_MODEL_DRA7: return dpi_get_clk_src_dra7xx(channel); default: @@ -213,7 +210,7 @@ static bool dpi_calc_pll_cb(int n, int m, unsigned long fint, ctx->pll_cinfo.clkdco = clkdco; return dss_pll_hsdiv_calc_a(ctx->pll, clkdco, - ctx->pck_min, dss_feat_get_param_max(FEAT_PARAM_DSS_FCK), + ctx->pck_min, dss_get_max_fck_rate(), dpi_calc_hsdiv_cb, ctx); } @@ -403,19 +400,13 @@ static int dpi_display_enable(struct omap_dss_device *dssdev) mutex_lock(&dpi->lock); - if (dss_has_feature(FEAT_DPI_USES_VDDS_DSI) && !dpi->vdds_dsi_reg) { - DSSERR("no VDSS_DSI regulator\n"); - r = -ENODEV; - goto err_no_reg; - } - if (!out->dispc_channel_connected) { DSSERR("failed to enable display: no output/manager\n"); r = -ENODEV; goto err_no_out_mgr; } - if (dss_has_feature(FEAT_DPI_USES_VDDS_DSI)) { + if (dpi->vdds_dsi_reg) { r = regulator_enable(dpi->vdds_dsi_reg); if (r) goto err_reg_enable; @@ -459,11 +450,10 @@ err_pll_init: err_src_sel: dispc_runtime_put(); err_get_dispc: - if (dss_has_feature(FEAT_DPI_USES_VDDS_DSI)) + if (dpi->vdds_dsi_reg) regulator_disable(dpi->vdds_dsi_reg); err_reg_enable: err_no_out_mgr: -err_no_reg: mutex_unlock(&dpi->lock); return r; } @@ -484,7 +474,7 @@ static void dpi_display_disable(struct omap_dss_device *dssdev) dispc_runtime_put(); - if (dss_has_feature(FEAT_DPI_USES_VDDS_DSI)) + if (dpi->vdds_dsi_reg) regulator_disable(dpi->vdds_dsi_reg); mutex_unlock(&dpi->lock); @@ -575,11 +565,21 @@ static int dpi_verify_pll(struct dss_pll *pll) return 0; } +static const struct soc_device_attribute dpi_soc_devices[] = { + { .family = "OMAP3[456]*" }, + { .family = "[AD]M37*" }, + { /* sentinel */ } +}; + static int dpi_init_regulator(struct dpi_data *dpi) { struct regulator *vdds_dsi; - if (!dss_has_feature(FEAT_DPI_USES_VDDS_DSI)) + /* + * The DPI uses the DSI VDDS on OMAP34xx, OMAP35xx, OMAP36xx, AM37xx and + * DM37xx only. + */ + if (!soc_device_match(dpi_soc_devices)) return 0; if (dpi->vdds_dsi_reg) @@ -604,7 +604,7 @@ static void dpi_init_pll(struct dpi_data *dpi) if (dpi->pll) return; - dpi->clk_src = dpi_get_clk_src(dpi->output.dispc_channel); + dpi->clk_src = dpi_get_clk_src(dpi); pll = dss_pll_find_by_src(dpi->clk_src); if (!pll) @@ -624,18 +624,14 @@ static void dpi_init_pll(struct dpi_data *dpi) * the channel in some more dynamic manner, or get the channel as a user * parameter. */ -static enum omap_channel dpi_get_channel(int port_num) +static enum omap_channel dpi_get_channel(struct dpi_data *dpi, int port_num) { - switch (omapdss_get_version()) { - case OMAPDSS_VER_OMAP24xx: - case OMAPDSS_VER_OMAP34xx_ES1: - case OMAPDSS_VER_OMAP34xx_ES3: - case OMAPDSS_VER_OMAP3630: - case OMAPDSS_VER_AM35xx: - case OMAPDSS_VER_AM43xx: + switch (dpi->dss_model) { + case DSS_MODEL_OMAP2: + case DSS_MODEL_OMAP3: return OMAP_DSS_CHANNEL_LCD; - case OMAPDSS_VER_DRA7xx: + case DSS_MODEL_DRA7: switch (port_num) { case 2: return OMAP_DSS_CHANNEL_LCD3; @@ -646,12 +642,10 @@ static enum omap_channel dpi_get_channel(int port_num) return OMAP_DSS_CHANNEL_LCD; } - case OMAPDSS_VER_OMAP4430_ES1: - case OMAPDSS_VER_OMAP4430_ES2: - case OMAPDSS_VER_OMAP4: + case DSS_MODEL_OMAP4: return OMAP_DSS_CHANNEL_LCD2; - case OMAPDSS_VER_OMAP5: + case DSS_MODEL_OMAP5: return OMAP_DSS_CHANNEL_LCD3; default: @@ -716,10 +710,8 @@ static const struct omapdss_dpi_ops dpi_ops = { .get_timings = dpi_get_timings, }; -static void dpi_init_output_port(struct platform_device *pdev, - struct device_node *port) +static void dpi_init_output_port(struct dpi_data *dpi, struct device_node *port) { - struct dpi_data *dpi = port->data; struct omap_dss_device *out = &dpi->output; int r; u32 port_num; @@ -741,10 +733,10 @@ static void dpi_init_output_port(struct platform_device *pdev, break; } - out->dev = &pdev->dev; + out->dev = &dpi->pdev->dev; out->id = OMAP_DSS_OUTPUT_DPI; out->output_type = OMAP_DISPLAY_TYPE_DPI; - out->dispc_channel = dpi_get_channel(port_num); + out->dispc_channel = dpi_get_channel(dpi, port_num); out->port_num = port_num; out->ops.dpi = &dpi_ops; out->owner = THIS_MODULE; @@ -760,7 +752,8 @@ static void dpi_uninit_output_port(struct device_node *port) omapdss_unregister_output(out); } -int dpi_init_port(struct platform_device *pdev, struct device_node *port) +int dpi_init_port(struct platform_device *pdev, struct device_node *port, + enum dss_model dss_model) { struct dpi_data *dpi; struct device_node *ep; @@ -786,11 +779,12 @@ int dpi_init_port(struct platform_device *pdev, struct device_node *port) of_node_put(ep); dpi->pdev = pdev; + dpi->dss_model = dss_model; port->data = dpi; mutex_init(&dpi->lock); - dpi_init_output_port(pdev, port); + dpi_init_output_port(dpi, port); dpi->port_initialized = true; diff --git a/drivers/gpu/drm/omapdrm/dss/dsi.c b/drivers/gpu/drm/omapdrm/dss/dsi.c index 835f49004bc3..b56a05730314 100644 --- a/drivers/gpu/drm/omapdrm/dss/dsi.c +++ b/drivers/gpu/drm/omapdrm/dss/dsi.c @@ -20,6 +20,8 @@ #define DSS_SUBSYS_NAME "DSI" #include <linux/kernel.h> +#include <linux/mfd/syscon.h> +#include <linux/regmap.h> #include <linux/io.h> #include <linux/clk.h> #include <linux/device.h> @@ -42,12 +44,12 @@ #include <linux/of_graph.h> #include <linux/of_platform.h> #include <linux/component.h> +#include <linux/sys_soc.h> #include <video/mipi_display.h> #include "omapdss.h" #include "dss.h" -#include "dss_features.h" #define DSI_CATCH_MISSING_TE @@ -228,6 +230,12 @@ static int dsi_vc_send_null(struct omap_dss_device *dssdev, int channel); #define DSI_MAX_NR_ISRS 2 #define DSI_MAX_NR_LANES 5 +enum dsi_model { + DSI_MODEL_OMAP3, + DSI_MODEL_OMAP4, + DSI_MODEL_OMAP5, +}; + enum dsi_lane_function { DSI_LANE_UNUSED = 0, DSI_LANE_CLK, @@ -299,12 +307,36 @@ struct dsi_lp_clock_info { u16 lp_clk_div; }; +struct dsi_module_id_data { + u32 address; + int id; +}; + +enum dsi_quirks { + DSI_QUIRK_PLL_PWR_BUG = (1 << 0), /* DSI-PLL power command 0x3 is not working */ + DSI_QUIRK_DCS_CMD_CONFIG_VC = (1 << 1), + DSI_QUIRK_VC_OCP_WIDTH = (1 << 2), + DSI_QUIRK_REVERSE_TXCLKESC = (1 << 3), + DSI_QUIRK_GNQ = (1 << 4), + DSI_QUIRK_PHY_DCC = (1 << 5), +}; + +struct dsi_of_data { + enum dsi_model model; + const struct dss_pll_hw *pll_hw; + const struct dsi_module_id_data *modules; + unsigned int max_fck_freq; + unsigned int max_pll_lpdiv; + enum dsi_quirks quirks; +}; + struct dsi_data { struct platform_device *pdev; void __iomem *proto_base; void __iomem *phy_base; void __iomem *pll_base; + const struct dsi_of_data *data; int module_id; int irq; @@ -312,6 +344,7 @@ struct dsi_data { bool is_enabled; struct clk *dss_clk; + struct regmap *syscon; struct dispc_clock_info user_dispc_cinfo; struct dss_pll_clock_info user_dsi_cinfo; @@ -397,13 +430,6 @@ struct dsi_packet_sent_handler_data { struct completion *completion; }; -struct dsi_module_id_data { - u32 address; - int id; -}; - -static const struct of_device_id dsi_of_match[]; - #ifdef DSI_PERF_MEASURE static bool dsi_perf; module_param(dsi_perf, bool, 0644); @@ -1186,6 +1212,7 @@ static int dsi_regulator_init(struct platform_device *dsidev) static void _dsi_print_reset_status(struct platform_device *dsidev) { + struct dsi_data *dsi = dsi_get_dsidrv_data(dsidev); u32 l; int b0, b1, b2; @@ -1194,7 +1221,7 @@ static void _dsi_print_reset_status(struct platform_device *dsidev) * I/O. */ l = dsi_read_reg(dsidev, DSI_DSIPHY_CFG5); - if (dss_has_feature(FEAT_DSI_REVERSE_TXCLKESC)) { + if (dsi->data->quirks & DSI_QUIRK_REVERSE_TXCLKESC) { b0 = 28; b1 = 27; b2 = 26; @@ -1297,7 +1324,7 @@ static int dsi_set_lp_clk_divisor(struct platform_device *dsidev) unsigned long dsi_fclk; unsigned lp_clk_div; unsigned long lp_clk; - unsigned lpdiv_max = dss_feat_get_param_max(FEAT_PARAM_DSIPLL_LPDIV); + unsigned lpdiv_max = dsi->data->max_pll_lpdiv; lp_clk_div = dsi->user_lp_cinfo.lp_clk_div; @@ -1349,11 +1376,12 @@ enum dsi_pll_power_state { static int dsi_pll_power(struct platform_device *dsidev, enum dsi_pll_power_state state) { + struct dsi_data *dsi = dsi_get_dsidrv_data(dsidev); int t = 0; /* DSI-PLL power command 0x3 is not working */ - if (dss_has_feature(FEAT_DSI_PLL_PWR_BUG) && - state == DSI_PLL_POWER_ON_DIV) + if ((dsi->data->quirks & DSI_QUIRK_PLL_PWR_BUG) && + state == DSI_PLL_POWER_ON_DIV) state = DSI_PLL_POWER_ON_ALL; /* PLL_PWR_CMD */ @@ -1373,11 +1401,12 @@ static int dsi_pll_power(struct platform_device *dsidev, } -static void dsi_pll_calc_dsi_fck(struct dss_pll_clock_info *cinfo) +static void dsi_pll_calc_dsi_fck(struct dsi_data *dsi, + struct dss_pll_clock_info *cinfo) { unsigned long max_dsi_fck; - max_dsi_fck = dss_feat_get_param_max(FEAT_PARAM_DSI_FCK); + max_dsi_fck = dsi->data->max_fck_freq; cinfo->mX[HSDIV_DSI] = DIV_ROUND_UP(cinfo->clkdco, max_dsi_fck); cinfo->clkout[HSDIV_DSI] = cinfo->clkdco / cinfo->mX[HSDIV_DSI]; @@ -1773,13 +1802,14 @@ static int dsi_cio_power(struct platform_device *dsidev, static unsigned dsi_get_line_buf_size(struct platform_device *dsidev) { + struct dsi_data *dsi = dsi_get_dsidrv_data(dsidev); int val; /* line buffer on OMAP3 is 1024 x 24bits */ /* XXX: for some reason using full buffer size causes * considerable TX slowdown with update sizes that fill the * whole buffer */ - if (!dss_has_feature(FEAT_DSI_GNQ)) + if (!(dsi->data->quirks & DSI_QUIRK_GNQ)) return 1023 * 3; val = REG_GET(dsidev, DSI_GNQ, 14, 12); /* VP1_LINE_BUFFER_SIZE */ @@ -1872,6 +1902,7 @@ static inline unsigned ddr2ns(struct platform_device *dsidev, unsigned ddr) static void dsi_cio_timings(struct platform_device *dsidev) { + struct dsi_data *dsi = dsi_get_dsidrv_data(dsidev); u32 r; u32 ths_prepare, ths_prepare_ths_zero, ths_trail, ths_exit; u32 tlpx_half, tclk_trail, tclk_zero; @@ -1934,7 +1965,7 @@ static void dsi_cio_timings(struct platform_device *dsidev) r = FLD_MOD(r, tclk_trail, 15, 8); r = FLD_MOD(r, tclk_zero, 7, 0); - if (dss_has_feature(FEAT_DSI_PHY_DCC)) { + if (dsi->data->quirks & DSI_QUIRK_PHY_DCC) { r = FLD_MOD(r, 0, 21, 21); /* DCCEN = disable */ r = FLD_MOD(r, 1, 22, 22); /* CLKINP_DIVBY2EN = enable */ r = FLD_MOD(r, 1, 23, 23); /* CLKINP_SEL = enable */ @@ -2006,7 +2037,7 @@ static int dsi_cio_wait_tx_clk_esc_reset(struct platform_device *dsidev) static const u8 offsets_new[] = { 24, 25, 26, 27, 28 }; const u8 *offsets; - if (dss_has_feature(FEAT_DSI_REVERSE_TXCLKESC)) + if (dsi->data->quirks & DSI_QUIRK_REVERSE_TXCLKESC) offsets = offsets_old; else offsets = offsets_new; @@ -2060,6 +2091,83 @@ static unsigned dsi_get_lane_mask(struct platform_device *dsidev) return mask; } +/* OMAP4 CONTROL_DSIPHY */ +#define OMAP4_DSIPHY_SYSCON_OFFSET 0x78 + +#define OMAP4_DSI2_LANEENABLE_SHIFT 29 +#define OMAP4_DSI2_LANEENABLE_MASK (0x7 << 29) +#define OMAP4_DSI1_LANEENABLE_SHIFT 24 +#define OMAP4_DSI1_LANEENABLE_MASK (0x1f << 24) +#define OMAP4_DSI1_PIPD_SHIFT 19 +#define OMAP4_DSI1_PIPD_MASK (0x1f << 19) +#define OMAP4_DSI2_PIPD_SHIFT 14 +#define OMAP4_DSI2_PIPD_MASK (0x1f << 14) + +static int dsi_omap4_mux_pads(struct dsi_data *dsi, unsigned int lanes) +{ + u32 enable_mask, enable_shift; + u32 pipd_mask, pipd_shift; + + if (dsi->module_id == 0) { + enable_mask = OMAP4_DSI1_LANEENABLE_MASK; + enable_shift = OMAP4_DSI1_LANEENABLE_SHIFT; + pipd_mask = OMAP4_DSI1_PIPD_MASK; + pipd_shift = OMAP4_DSI1_PIPD_SHIFT; + } else if (dsi->module_id == 1) { + enable_mask = OMAP4_DSI2_LANEENABLE_MASK; + enable_shift = OMAP4_DSI2_LANEENABLE_SHIFT; + pipd_mask = OMAP4_DSI2_PIPD_MASK; + pipd_shift = OMAP4_DSI2_PIPD_SHIFT; + } else { + return -ENODEV; + } + + return regmap_update_bits(dsi->syscon, OMAP4_DSIPHY_SYSCON_OFFSET, + enable_mask | pipd_mask, + (lanes << enable_shift) | (lanes << pipd_shift)); +} + +/* OMAP5 CONTROL_DSIPHY */ + +#define OMAP5_DSIPHY_SYSCON_OFFSET 0x74 + +#define OMAP5_DSI1_LANEENABLE_SHIFT 24 +#define OMAP5_DSI2_LANEENABLE_SHIFT 19 +#define OMAP5_DSI_LANEENABLE_MASK 0x1f + +static int dsi_omap5_mux_pads(struct dsi_data *dsi, unsigned int lanes) +{ + u32 enable_shift; + + if (dsi->module_id == 0) + enable_shift = OMAP5_DSI1_LANEENABLE_SHIFT; + else if (dsi->module_id == 1) + enable_shift = OMAP5_DSI2_LANEENABLE_SHIFT; + else + return -ENODEV; + + return regmap_update_bits(dsi->syscon, OMAP5_DSIPHY_SYSCON_OFFSET, + OMAP5_DSI_LANEENABLE_MASK << enable_shift, + lanes << enable_shift); +} + +static int dsi_enable_pads(struct dsi_data *dsi, unsigned int lane_mask) +{ + if (dsi->data->model == DSI_MODEL_OMAP4) + return dsi_omap4_mux_pads(dsi, lane_mask); + if (dsi->data->model == DSI_MODEL_OMAP5) + return dsi_omap5_mux_pads(dsi, lane_mask); + return 0; +} + +static void dsi_disable_pads(struct dsi_data *dsi) +{ + if (dsi->data->model == DSI_MODEL_OMAP4) + dsi_omap4_mux_pads(dsi, 0); + else if (dsi->data->model == DSI_MODEL_OMAP5) + dsi_omap5_mux_pads(dsi, 0); +} + static int dsi_cio_init(struct platform_device *dsidev) { struct dsi_data *dsi = dsi_get_dsidrv_data(dsidev); @@ -2068,7 +2176,7 @@ static int dsi_cio_init(struct platform_device *dsidev) DSSDBG("DSI CIO init starts"); - r = dss_dsi_enable_pads(dsi->module_id, dsi_get_lane_mask(dsidev)); + r = dsi_enable_pads(dsi, dsi_get_lane_mask(dsidev)); if (r) return r; @@ -2178,7 +2286,7 @@ err_cio_pwr: dsi_cio_disable_lane_override(dsidev); err_scp_clk_dom: dsi_disable_scp_clk(dsidev); - dss_dsi_disable_pads(dsi->module_id, dsi_get_lane_mask(dsidev)); + dsi_disable_pads(dsi); return r; } @@ -2191,7 +2299,7 @@ static void dsi_cio_uninit(struct platform_device *dsidev) dsi_cio_power(dsidev, DSI_COMPLEXIO_POWER_OFF); dsi_disable_scp_clk(dsidev); - dss_dsi_disable_pads(dsi->module_id, dsi_get_lane_mask(dsidev)); + dsi_disable_pads(dsi); } static void dsi_config_tx_fifo(struct platform_device *dsidev, @@ -2439,7 +2547,7 @@ static void dsi_vc_initial_config(struct platform_device *dsidev, int channel) r = FLD_MOD(r, 1, 7, 7); /* CS_TX_EN */ r = FLD_MOD(r, 1, 8, 8); /* ECC_TX_EN */ r = FLD_MOD(r, 0, 9, 9); /* MODE_SPEED, high speed on/off */ - if (dss_has_feature(FEAT_DSI_VC_OCP_WIDTH)) + if (dsi->data->quirks & DSI_QUIRK_VC_OCP_WIDTH) r = FLD_MOD(r, 3, 11, 10); /* OCP_WIDTH = 32 bit */ r = FLD_MOD(r, 4, 29, 27); /* DMA_RX_REQ_NB = no dma */ @@ -2474,7 +2582,7 @@ static int dsi_vc_config_source(struct platform_device *dsidev, int channel, REG_FLD_MOD(dsidev, DSI_VC_CTRL(channel), source, 1, 1); /* DCS_CMD_ENABLE */ - if (dss_has_feature(FEAT_DSI_DCS_CMD_CONFIG_VC)) { + if (dsi->data->quirks & DSI_QUIRK_DCS_CMD_CONFIG_VC) { bool enable = source == DSI_VC_SOURCE_VP; REG_FLD_MOD(dsidev, DSI_VC_CTRL(channel), enable, 30, 30); } @@ -3607,7 +3715,7 @@ static int dsi_proto_config(struct platform_device *dsidev) r = FLD_MOD(r, 0, 8, 8); /* VP_CLK_POL */ r = FLD_MOD(r, 1, 14, 14); /* TRIGGER_RESET_MODE */ r = FLD_MOD(r, 1, 19, 19); /* EOT_ENABLE */ - if (!dss_has_feature(FEAT_DSI_DCS_CMD_CONFIG_VC)) { + if (!(dsi->data->quirks & DSI_QUIRK_DCS_CMD_CONFIG_VC)) { r = FLD_MOD(r, 1, 24, 24); /* DCS_CMD_ENABLE */ /* DCS_CMD_CODE, 1=start, 0=continue */ r = FLD_MOD(r, 0, 25, 25); @@ -4450,6 +4558,7 @@ static bool dsi_cm_calc_pll_cb(int n, int m, unsigned long fint, unsigned long clkdco, void *data) { struct dsi_clk_calc_ctx *ctx = data; + struct dsi_data *dsi = dsi_get_dsidrv_data(ctx->dsidev); ctx->dsi_cinfo.n = n; ctx->dsi_cinfo.m = m; @@ -4457,7 +4566,7 @@ static bool dsi_cm_calc_pll_cb(int n, int m, unsigned long fint, ctx->dsi_cinfo.clkdco = clkdco; return dss_pll_hsdiv_calc_a(ctx->pll, clkdco, ctx->req_pck_min, - dss_feat_get_param_max(FEAT_PARAM_DSS_FCK), + dsi->data->max_fck_freq, dsi_cm_calc_hsdiv_cb, ctx); } @@ -4749,6 +4858,7 @@ static bool dsi_vm_calc_pll_cb(int n, int m, unsigned long fint, unsigned long clkdco, void *data) { struct dsi_clk_calc_ctx *ctx = data; + struct dsi_data *dsi = dsi_get_dsidrv_data(ctx->dsidev); ctx->dsi_cinfo.n = n; ctx->dsi_cinfo.m = m; @@ -4756,7 +4866,7 @@ static bool dsi_vm_calc_pll_cb(int n, int m, unsigned long fint, ctx->dsi_cinfo.clkdco = clkdco; return dss_pll_hsdiv_calc_a(ctx->pll, clkdco, ctx->req_pck_min, - dss_feat_get_param_max(FEAT_PARAM_DSS_FCK), + dsi->data->max_fck_freq, dsi_vm_calc_hsdiv_cb, ctx); } @@ -4827,7 +4937,7 @@ static int dsi_set_config(struct omap_dss_device *dssdev, goto err; } - dsi_pll_calc_dsi_fck(&ctx.dsi_cinfo); + dsi_pll_calc_dsi_fck(dsi, &ctx.dsi_cinfo); r = dsi_lp_clock_calc(ctx.dsi_cinfo.clkout[HSDIV_DSI], config->lp_clk_min, config->lp_clk_max, &dsi->user_lp_cinfo); @@ -4857,24 +4967,14 @@ err: * the channel in some more dynamic manner, or get the channel as a user * parameter. */ -static enum omap_channel dsi_get_channel(int module_id) +static enum omap_channel dsi_get_channel(struct dsi_data *dsi) { - switch (omapdss_get_version()) { - case OMAPDSS_VER_OMAP24xx: - case OMAPDSS_VER_AM43xx: - DSSWARN("DSI not supported\n"); + switch (dsi->data->model) { + case DSI_MODEL_OMAP3: return OMAP_DSS_CHANNEL_LCD; - case OMAPDSS_VER_OMAP34xx_ES1: - case OMAPDSS_VER_OMAP34xx_ES3: - case OMAPDSS_VER_OMAP3630: - case OMAPDSS_VER_AM35xx: - return OMAP_DSS_CHANNEL_LCD; - - case OMAPDSS_VER_OMAP4430_ES1: - case OMAPDSS_VER_OMAP4430_ES2: - case OMAPDSS_VER_OMAP4: - switch (module_id) { + case DSI_MODEL_OMAP4: + switch (dsi->module_id) { case 0: return OMAP_DSS_CHANNEL_LCD; case 1: @@ -4884,8 +4984,8 @@ static enum omap_channel dsi_get_channel(int module_id) return OMAP_DSS_CHANNEL_LCD; } - case OMAPDSS_VER_OMAP5: - switch (module_id) { + case DSI_MODEL_OMAP5: + switch (dsi->module_id) { case 0: return OMAP_DSS_CHANNEL_LCD; case 1: @@ -5065,7 +5165,7 @@ static void dsi_init_output(struct platform_device *dsidev) out->output_type = OMAP_DISPLAY_TYPE_DSI; out->name = dsi->module_id == 0 ? "dsi.0" : "dsi.1"; - out->dispc_channel = dsi_get_channel(dsi->module_id); + out->dispc_channel = dsi_get_channel(dsi); out->ops.dsi = &dsi_ops; out->owner = THIS_MODULE; @@ -5240,29 +5340,7 @@ static int dsi_init_pll_data(struct platform_device *dsidev) pll->id = dsi->module_id == 0 ? DSS_PLL_DSI1 : DSS_PLL_DSI2; pll->clkin = clk; pll->base = dsi->pll_base; - - switch (omapdss_get_version()) { - case OMAPDSS_VER_OMAP34xx_ES1: - case OMAPDSS_VER_OMAP34xx_ES3: - case OMAPDSS_VER_OMAP3630: - case OMAPDSS_VER_AM35xx: - pll->hw = &dss_omap3_dsi_pll_hw; - break; - - case OMAPDSS_VER_OMAP4430_ES1: - case OMAPDSS_VER_OMAP4430_ES2: - case OMAPDSS_VER_OMAP4: - pll->hw = &dss_omap4_dsi_pll_hw; - break; - - case OMAPDSS_VER_OMAP5: - pll->hw = &dss_omap5_dsi_pll_hw; - break; - - default: - return -ENODEV; - } - + pll->hw = dsi->data->pll_hw; pll->ops = &dsi_pll_ops; r = dss_pll_register(pll); @@ -5273,9 +5351,74 @@ static int dsi_init_pll_data(struct platform_device *dsidev) } /* DSI1 HW IP initialisation */ +static const struct dsi_of_data dsi_of_data_omap34xx = { + .model = DSI_MODEL_OMAP3, + .pll_hw = &dss_omap3_dsi_pll_hw, + .modules = (const struct dsi_module_id_data[]) { + { .address = 0x4804fc00, .id = 0, }, + { }, + }, + .max_fck_freq = 173000000, + .max_pll_lpdiv = (1 << 13) - 1, + .quirks = DSI_QUIRK_REVERSE_TXCLKESC, +}; + +static const struct dsi_of_data dsi_of_data_omap36xx = { + .model = DSI_MODEL_OMAP3, + .pll_hw = &dss_omap3_dsi_pll_hw, + .modules = (const struct dsi_module_id_data[]) { + { .address = 0x4804fc00, .id = 0, }, + { }, + }, + .max_fck_freq = 173000000, + .max_pll_lpdiv = (1 << 13) - 1, + .quirks = DSI_QUIRK_PLL_PWR_BUG, +}; + +static const struct dsi_of_data dsi_of_data_omap4 = { + .model = DSI_MODEL_OMAP4, + .pll_hw = &dss_omap4_dsi_pll_hw, + .modules = (const struct dsi_module_id_data[]) { + { .address = 0x58004000, .id = 0, }, + { .address = 0x58005000, .id = 1, }, + { }, + }, + .max_fck_freq = 170000000, + .max_pll_lpdiv = (1 << 13) - 1, + .quirks = DSI_QUIRK_DCS_CMD_CONFIG_VC | DSI_QUIRK_VC_OCP_WIDTH + | DSI_QUIRK_GNQ, +}; + +static const struct dsi_of_data dsi_of_data_omap5 = { + .model = DSI_MODEL_OMAP5, + .pll_hw = &dss_omap5_dsi_pll_hw, + .modules = (const struct dsi_module_id_data[]) { + { .address = 0x58004000, .id = 0, }, + { .address = 0x58009000, .id = 1, }, + { }, + }, + .max_fck_freq = 209250000, + .max_pll_lpdiv = (1 << 13) - 1, + .quirks = DSI_QUIRK_DCS_CMD_CONFIG_VC | DSI_QUIRK_VC_OCP_WIDTH + | DSI_QUIRK_GNQ | DSI_QUIRK_PHY_DCC, +}; + +static const struct of_device_id dsi_of_match[] = { + { .compatible = "ti,omap3-dsi", .data = &dsi_of_data_omap36xx, }, + { .compatible = "ti,omap4-dsi", .data = &dsi_of_data_omap4, }, + { .compatible = "ti,omap5-dsi", .data = &dsi_of_data_omap5, }, + {}, +}; + +static const struct soc_device_attribute dsi_soc_devices[] = { + { .machine = "OMAP3[45]*", .data = &dsi_of_data_omap34xx }, + { .machine = "AM35*", .data = &dsi_of_data_omap34xx }, + { /* sentinel */ } +}; static int dsi_bind(struct device *dev, struct device *master, void *data) { struct platform_device *dsidev = to_platform_device(dev); + const struct soc_device_attribute *soc; const struct dsi_module_id_data *d; u32 rev; int r, i; @@ -5339,7 +5482,13 @@ static int dsi_bind(struct device *dev, struct device *master, void *data) return r; } - d = of_match_node(dsi_of_match, dsidev->dev.of_node)->data; + soc = soc_device_match(dsi_soc_devices); + if (soc) + dsi->data = soc->data; + else + dsi->data = of_match_node(dsi_of_match, dev->of_node)->data; + + d = dsi->data->modules; while (d->address != 0 && d->address != dsi_mem->start) d++; @@ -5350,6 +5499,24 @@ static int dsi_bind(struct device *dev, struct device *master, void *data) dsi->module_id = d->id; + if (dsi->data->model == DSI_MODEL_OMAP4 || + dsi->data->model == DSI_MODEL_OMAP5) { + struct device_node *np; + + /* + * The OMAP4/5 display DT bindings don't reference the padconf + * syscon. Our only option to retrieve it is to find it by name. + */ + np = of_find_node_by_name(NULL, + dsi->data->model == DSI_MODEL_OMAP4 ? + "omap4_padconf_global" : "omap5_padconf_global"); + if (!np) + return -ENODEV; + + dsi->syscon = syscon_node_to_regmap(np); + of_node_put(np); + } + /* DSI VCs initialization */ for (i = 0; i < ARRAY_SIZE(dsi->vc); i++) { dsi->vc[i].source = DSI_VC_SOURCE_L4; @@ -5375,7 +5542,7 @@ static int dsi_bind(struct device *dev, struct device *master, void *data) /* DSI on OMAP3 doesn't have register DSI_GNQ, set number * of data to 3 by default */ - if (dss_has_feature(FEAT_DSI_GNQ)) + if (dsi->data->quirks & DSI_QUIRK_GNQ) /* NB_DATA_LANES */ dsi->num_lanes_supported = 1 + REG_GET(dsidev, DSI_GNQ, 11, 9); else @@ -5495,30 +5662,6 @@ static const struct dev_pm_ops dsi_pm_ops = { .runtime_resume = dsi_runtime_resume, }; -static const struct dsi_module_id_data dsi_of_data_omap3[] = { - { .address = 0x4804fc00, .id = 0, }, - { }, -}; - -static const struct dsi_module_id_data dsi_of_data_omap4[] = { - { .address = 0x58004000, .id = 0, }, - { .address = 0x58005000, .id = 1, }, - { }, -}; - -static const struct dsi_module_id_data dsi_of_data_omap5[] = { - { .address = 0x58004000, .id = 0, }, - { .address = 0x58009000, .id = 1, }, - { }, -}; - -static const struct of_device_id dsi_of_match[] = { - { .compatible = "ti,omap3-dsi", .data = dsi_of_data_omap3, }, - { .compatible = "ti,omap4-dsi", .data = dsi_of_data_omap4, }, - { .compatible = "ti,omap5-dsi", .data = dsi_of_data_omap5, }, - {}, -}; - static struct platform_driver omap_dsihw_driver = { .probe = dsi_probe, .remove = dsi_remove, diff --git a/drivers/gpu/drm/omapdrm/dss/dss.c b/drivers/gpu/drm/omapdrm/dss/dss.c index 99e22ca972c7..d1755f12236b 100644 --- a/drivers/gpu/drm/omapdrm/dss/dss.c +++ b/drivers/gpu/drm/omapdrm/dss/dss.c @@ -22,6 +22,7 @@ #define DSS_SUBSYS_NAME "DSS" +#include <linux/debugfs.h> #include <linux/kernel.h> #include <linux/module.h> #include <linux/io.h> @@ -38,14 +39,15 @@ #include <linux/mfd/syscon.h> #include <linux/regmap.h> #include <linux/of.h> +#include <linux/of_device.h> #include <linux/of_graph.h> #include <linux/regulator/consumer.h> #include <linux/suspend.h> #include <linux/component.h> +#include <linux/sys_soc.h> #include "omapdss.h" #include "dss.h" -#include "dss_features.h" #define DSS_SZ_REGS SZ_512 @@ -69,15 +71,24 @@ struct dss_reg { #define REG_FLD_MOD(idx, val, start, end) \ dss_write_reg(idx, FLD_MOD(dss_read_reg(idx), val, start, end)) +struct dss_ops { + int (*dpi_select_source)(int port, enum omap_channel channel); + int (*select_lcd_source)(enum omap_channel channel, + enum dss_clk_source clk_src); +}; + struct dss_features { + enum dss_model model; u8 fck_div_max; + unsigned int fck_freq_max; u8 dss_fck_multiplier; const char *parent_clk_name; const enum omap_display_type *ports; int num_ports; - int (*dpi_select_source)(int port, enum omap_channel channel); - int (*select_lcd_source)(enum omap_channel channel, - enum dss_clk_source clk_src); + const enum omap_dss_output_id *outputs; + const struct dss_ops *ops; + struct dss_reg_field dispc_clk_switch; + bool has_lcd_clk_src; }; static struct { @@ -139,8 +150,7 @@ static void dss_save_context(void) SR(CONTROL); - if (dss_feat_get_supported_displays(OMAP_DSS_CHANNEL_LCD) & - OMAP_DISPLAY_TYPE_SDI) { + if (dss.feat->outputs[OMAP_DSS_CHANNEL_LCD] & OMAP_DSS_OUTPUT_SDI) { SR(SDI_CONTROL); SR(PLL_CONTROL); } @@ -159,8 +169,7 @@ static void dss_restore_context(void) RR(CONTROL); - if (dss_feat_get_supported_displays(OMAP_DSS_CHANNEL_LCD) & - OMAP_DISPLAY_TYPE_SDI) { + if (dss.feat->outputs[OMAP_DSS_CHANNEL_LCD] & OMAP_DSS_OUTPUT_SDI) { RR(SDI_CONTROL); RR(PLL_CONTROL); } @@ -390,8 +399,7 @@ static void dss_dump_regs(struct seq_file *s) DUMPREG(DSS_SYSSTATUS); DUMPREG(DSS_CONTROL); - if (dss_feat_get_supported_displays(OMAP_DSS_CHANNEL_LCD) & - OMAP_DISPLAY_TYPE_SDI) { + if (dss.feat->outputs[OMAP_DSS_CHANNEL_LCD] & OMAP_DSS_OUTPUT_SDI) { DUMPREG(DSS_SDI_CONTROL); DUMPREG(DSS_PLL_CONTROL); DUMPREG(DSS_SDI_STATUS); @@ -419,14 +427,12 @@ static int dss_get_channel_index(enum omap_channel channel) static void dss_select_dispc_clk_source(enum dss_clk_source clk_src) { int b; - u8 start, end; /* * We always use PRCM clock as the DISPC func clock, except on DSS3, * where we don't have separate DISPC and LCD clock sources. */ - if (WARN_ON(dss_has_feature(FEAT_LCD_CLK_SRC) && - clk_src != DSS_CLK_SRC_FCK)) + if (WARN_ON(dss.feat->has_lcd_clk_src && clk_src != DSS_CLK_SRC_FCK)) return; switch (clk_src) { @@ -444,9 +450,9 @@ static void dss_select_dispc_clk_source(enum dss_clk_source clk_src) return; } - dss_feat_get_reg_field(FEAT_REG_DISPC_CLK_SWITCH, &start, &end); - - REG_FLD_MOD(DSS_CONTROL, b, start, end); /* DISPC_CLK_SWITCH */ + REG_FLD_MOD(DSS_CONTROL, b, /* DISPC_CLK_SWITCH */ + dss.feat->dispc_clk_switch.start, + dss.feat->dispc_clk_switch.end); dss.dispc_clk_source = clk_src; } @@ -570,13 +576,13 @@ void dss_select_lcd_clk_source(enum omap_channel channel, int idx = dss_get_channel_index(channel); int r; - if (!dss_has_feature(FEAT_LCD_CLK_SRC)) { + if (!dss.feat->has_lcd_clk_src) { dss_select_dispc_clk_source(clk_src); dss.lcd_clk_source[idx] = clk_src; return; } - r = dss.feat->select_lcd_source(channel, clk_src); + r = dss.feat->ops->select_lcd_source(channel, clk_src); if (r) return; @@ -595,7 +601,7 @@ enum dss_clk_source dss_get_dsi_clk_source(int dsi_module) enum dss_clk_source dss_get_lcd_clk_source(enum omap_channel channel) { - if (dss_has_feature(FEAT_LCD_CLK_SRC)) { + if (dss.feat->has_lcd_clk_src) { int idx = dss_get_channel_index(channel); return dss.lcd_clk_source[idx]; } else { @@ -615,7 +621,7 @@ bool dss_div_calc(unsigned long pck, unsigned long fck_min, unsigned long prate; unsigned m; - fck_hw_max = dss_feat_get_param_max(FEAT_PARAM_DSS_FCK); + fck_hw_max = dss.feat->fck_freq_max; if (dss.parent_clk == NULL) { unsigned pckd; @@ -673,6 +679,16 @@ unsigned long dss_get_dispc_clk_rate(void) return dss.dss_clk_rate; } +unsigned long dss_get_max_fck_rate(void) +{ + return dss.feat->fck_freq_max; +} + +enum omap_dss_output_id dss_get_supported_outputs(enum omap_channel channel) +{ + return dss.feat->outputs[channel]; +} + static int dss_setup_default_clock(void) { unsigned long max_dss_fck, prate; @@ -680,7 +696,7 @@ static int dss_setup_default_clock(void) unsigned fck_div; int r; - max_dss_fck = dss_feat_get_param_max(FEAT_PARAM_DSS_FCK); + max_dss_fck = dss.feat->fck_freq_max; if (dss.parent_clk == NULL) { fck = clk_round_rate(dss.dss_clk, max_dss_fck); @@ -721,27 +737,29 @@ void dss_set_dac_pwrdn_bgz(bool enable) void dss_select_hdmi_venc_clk_source(enum dss_hdmi_venc_clk_source_select src) { - enum omap_display_type dp; - dp = dss_feat_get_supported_displays(OMAP_DSS_CHANNEL_DIGIT); + enum omap_dss_output_id outputs; + + outputs = dss.feat->outputs[OMAP_DSS_CHANNEL_DIGIT]; /* Complain about invalid selections */ - WARN_ON((src == DSS_VENC_TV_CLK) && !(dp & OMAP_DISPLAY_TYPE_VENC)); - WARN_ON((src == DSS_HDMI_M_PCLK) && !(dp & OMAP_DISPLAY_TYPE_HDMI)); + WARN_ON((src == DSS_VENC_TV_CLK) && !(outputs & OMAP_DSS_OUTPUT_VENC)); + WARN_ON((src == DSS_HDMI_M_PCLK) && !(outputs & OMAP_DSS_OUTPUT_HDMI)); /* Select only if we have options */ - if ((dp & OMAP_DISPLAY_TYPE_VENC) && (dp & OMAP_DISPLAY_TYPE_HDMI)) + if ((outputs & OMAP_DSS_OUTPUT_VENC) && + (outputs & OMAP_DSS_OUTPUT_HDMI)) REG_FLD_MOD(DSS_CONTROL, src, 15, 15); /* VENC_HDMI_SWITCH */ } enum dss_hdmi_venc_clk_source_select dss_get_hdmi_venc_clk_source(void) { - enum omap_display_type displays; + enum omap_dss_output_id outputs; - displays = dss_feat_get_supported_displays(OMAP_DSS_CHANNEL_DIGIT); - if ((displays & OMAP_DISPLAY_TYPE_HDMI) == 0) + outputs = dss.feat->outputs[OMAP_DSS_CHANNEL_DIGIT]; + if ((outputs & OMAP_DSS_OUTPUT_HDMI) == 0) return DSS_VENC_TV_CLK; - if ((displays & OMAP_DISPLAY_TYPE_VENC) == 0) + if ((outputs & OMAP_DSS_OUTPUT_VENC) == 0) return DSS_HDMI_M_PCLK; return REG_GET(DSS_CONTROL, 15, 15); @@ -823,7 +841,7 @@ static int dss_dpi_select_source_dra7xx(int port, enum omap_channel channel) int dss_dpi_select_source(int port, enum omap_channel channel) { - return dss.feat->dpi_select_source(port, channel); + return dss.feat->ops->dpi_select_source(port, channel); } static int dss_get_clocks(void) @@ -882,7 +900,7 @@ void dss_runtime_put(void) /* DEBUGFS */ #if defined(CONFIG_OMAP2_DSS_DEBUGFS) -void dss_debug_dump_clocks(struct seq_file *s) +static void dss_debug_dump_clocks(struct seq_file *s) { dss_dump_clocks(s); dispc_dump_clocks(s); @@ -890,8 +908,88 @@ void dss_debug_dump_clocks(struct seq_file *s) dsi_dump_clocks(s); #endif } -#endif +static int dss_debug_show(struct seq_file *s, void *unused) +{ + void (*func)(struct seq_file *) = s->private; + + func(s); + return 0; +} + +static int dss_debug_open(struct inode *inode, struct file *file) +{ + return single_open(file, dss_debug_show, inode->i_private); +} + +static const struct file_operations dss_debug_fops = { + .open = dss_debug_open, + .read = seq_read, + .llseek = seq_lseek, + .release = single_release, +}; + +static struct dentry *dss_debugfs_dir; + +static int dss_initialize_debugfs(void) +{ + dss_debugfs_dir = debugfs_create_dir("omapdss", NULL); + if (IS_ERR(dss_debugfs_dir)) { + int err = PTR_ERR(dss_debugfs_dir); + + dss_debugfs_dir = NULL; + return err; + } + + debugfs_create_file("clk", S_IRUGO, dss_debugfs_dir, + &dss_debug_dump_clocks, &dss_debug_fops); + + return 0; +} + +static void dss_uninitialize_debugfs(void) +{ + if (dss_debugfs_dir) + debugfs_remove_recursive(dss_debugfs_dir); +} + +int dss_debugfs_create_file(const char *name, void (*write)(struct seq_file *)) +{ + struct dentry *d; + + d = debugfs_create_file(name, S_IRUGO, dss_debugfs_dir, + write, &dss_debug_fops); + + return PTR_ERR_OR_ZERO(d); +} +#else /* CONFIG_OMAP2_DSS_DEBUGFS */ +static inline int dss_initialize_debugfs(void) +{ + return 0; +} +static inline void dss_uninitialize_debugfs(void) +{ +} +#endif /* CONFIG_OMAP2_DSS_DEBUGFS */ + +static const struct dss_ops dss_ops_omap2_omap3 = { + .dpi_select_source = &dss_dpi_select_source_omap2_omap3, +}; + +static const struct dss_ops dss_ops_omap4 = { + .dpi_select_source = &dss_dpi_select_source_omap4, + .select_lcd_source = &dss_lcd_clk_mux_omap4, +}; + +static const struct dss_ops dss_ops_omap5 = { + .dpi_select_source = &dss_dpi_select_source_omap5, + .select_lcd_source = &dss_lcd_clk_mux_omap5, +}; + +static const struct dss_ops dss_ops_dra7 = { + .dpi_select_source = &dss_dpi_select_source_dra7xx, + .select_lcd_source = &dss_lcd_clk_mux_dra7, +}; static const enum omap_display_type omap2plus_ports[] = { OMAP_DISPLAY_TYPE_DPI, @@ -908,130 +1006,168 @@ static const enum omap_display_type dra7xx_ports[] = { OMAP_DISPLAY_TYPE_DPI, }; +static const enum omap_dss_output_id omap2_dss_supported_outputs[] = { + /* OMAP_DSS_CHANNEL_LCD */ + OMAP_DSS_OUTPUT_DPI | OMAP_DSS_OUTPUT_DBI, + + /* OMAP_DSS_CHANNEL_DIGIT */ + OMAP_DSS_OUTPUT_VENC, +}; + +static const enum omap_dss_output_id omap3430_dss_supported_outputs[] = { + /* OMAP_DSS_CHANNEL_LCD */ + OMAP_DSS_OUTPUT_DPI | OMAP_DSS_OUTPUT_DBI | + OMAP_DSS_OUTPUT_SDI | OMAP_DSS_OUTPUT_DSI1, + + /* OMAP_DSS_CHANNEL_DIGIT */ + OMAP_DSS_OUTPUT_VENC, +}; + +static const enum omap_dss_output_id omap3630_dss_supported_outputs[] = { + /* OMAP_DSS_CHANNEL_LCD */ + OMAP_DSS_OUTPUT_DPI | OMAP_DSS_OUTPUT_DBI | + OMAP_DSS_OUTPUT_DSI1, + + /* OMAP_DSS_CHANNEL_DIGIT */ + OMAP_DSS_OUTPUT_VENC, +}; + +static const enum omap_dss_output_id am43xx_dss_supported_outputs[] = { + /* OMAP_DSS_CHANNEL_LCD */ + OMAP_DSS_OUTPUT_DPI | OMAP_DSS_OUTPUT_DBI, +}; + +static const enum omap_dss_output_id omap4_dss_supported_outputs[] = { + /* OMAP_DSS_CHANNEL_LCD */ + OMAP_DSS_OUTPUT_DBI | OMAP_DSS_OUTPUT_DSI1, + + /* OMAP_DSS_CHANNEL_DIGIT */ + OMAP_DSS_OUTPUT_VENC | OMAP_DSS_OUTPUT_HDMI, + + /* OMAP_DSS_CHANNEL_LCD2 */ + OMAP_DSS_OUTPUT_DPI | OMAP_DSS_OUTPUT_DBI | + OMAP_DSS_OUTPUT_DSI2, +}; + +static const enum omap_dss_output_id omap5_dss_supported_outputs[] = { + /* OMAP_DSS_CHANNEL_LCD */ + OMAP_DSS_OUTPUT_DPI | OMAP_DSS_OUTPUT_DBI | + OMAP_DSS_OUTPUT_DSI1 | OMAP_DSS_OUTPUT_DSI2, + + /* OMAP_DSS_CHANNEL_DIGIT */ + OMAP_DSS_OUTPUT_HDMI, + + /* OMAP_DSS_CHANNEL_LCD2 */ + OMAP_DSS_OUTPUT_DPI | OMAP_DSS_OUTPUT_DBI | + OMAP_DSS_OUTPUT_DSI1, + + /* OMAP_DSS_CHANNEL_LCD3 */ + OMAP_DSS_OUTPUT_DPI | OMAP_DSS_OUTPUT_DBI | + OMAP_DSS_OUTPUT_DSI2, +}; + static const struct dss_features omap24xx_dss_feats = { + .model = DSS_MODEL_OMAP2, /* * fck div max is really 16, but the divider range has gaps. The range * from 1 to 6 has no gaps, so let's use that as a max. */ .fck_div_max = 6, + .fck_freq_max = 133000000, .dss_fck_multiplier = 2, .parent_clk_name = "core_ck", - .dpi_select_source = &dss_dpi_select_source_omap2_omap3, .ports = omap2plus_ports, .num_ports = ARRAY_SIZE(omap2plus_ports), + .outputs = omap2_dss_supported_outputs, + .ops = &dss_ops_omap2_omap3, + .dispc_clk_switch = { 0, 0 }, + .has_lcd_clk_src = false, }; static const struct dss_features omap34xx_dss_feats = { + .model = DSS_MODEL_OMAP3, .fck_div_max = 16, + .fck_freq_max = 173000000, .dss_fck_multiplier = 2, .parent_clk_name = "dpll4_ck", - .dpi_select_source = &dss_dpi_select_source_omap2_omap3, .ports = omap34xx_ports, + .outputs = omap3430_dss_supported_outputs, .num_ports = ARRAY_SIZE(omap34xx_ports), + .ops = &dss_ops_omap2_omap3, + .dispc_clk_switch = { 0, 0 }, + .has_lcd_clk_src = false, }; static const struct dss_features omap3630_dss_feats = { + .model = DSS_MODEL_OMAP3, .fck_div_max = 32, + .fck_freq_max = 173000000, .dss_fck_multiplier = 1, .parent_clk_name = "dpll4_ck", - .dpi_select_source = &dss_dpi_select_source_omap2_omap3, .ports = omap2plus_ports, .num_ports = ARRAY_SIZE(omap2plus_ports), + .outputs = omap3630_dss_supported_outputs, + .ops = &dss_ops_omap2_omap3, + .dispc_clk_switch = { 0, 0 }, + .has_lcd_clk_src = false, }; static const struct dss_features omap44xx_dss_feats = { + .model = DSS_MODEL_OMAP4, .fck_div_max = 32, + .fck_freq_max = 186000000, .dss_fck_multiplier = 1, .parent_clk_name = "dpll_per_x2_ck", - .dpi_select_source = &dss_dpi_select_source_omap4, .ports = omap2plus_ports, .num_ports = ARRAY_SIZE(omap2plus_ports), - .select_lcd_source = &dss_lcd_clk_mux_omap4, + .outputs = omap4_dss_supported_outputs, + .ops = &dss_ops_omap4, + .dispc_clk_switch = { 9, 8 }, + .has_lcd_clk_src = true, }; static const struct dss_features omap54xx_dss_feats = { + .model = DSS_MODEL_OMAP5, .fck_div_max = 64, + .fck_freq_max = 209250000, .dss_fck_multiplier = 1, .parent_clk_name = "dpll_per_x2_ck", - .dpi_select_source = &dss_dpi_select_source_omap5, .ports = omap2plus_ports, .num_ports = ARRAY_SIZE(omap2plus_ports), - .select_lcd_source = &dss_lcd_clk_mux_omap5, + .outputs = omap5_dss_supported_outputs, + .ops = &dss_ops_omap5, + .dispc_clk_switch = { 9, 7 }, + .has_lcd_clk_src = true, }; static const struct dss_features am43xx_dss_feats = { + .model = DSS_MODEL_OMAP3, .fck_div_max = 0, + .fck_freq_max = 200000000, .dss_fck_multiplier = 0, .parent_clk_name = NULL, - .dpi_select_source = &dss_dpi_select_source_omap2_omap3, .ports = omap2plus_ports, .num_ports = ARRAY_SIZE(omap2plus_ports), + .outputs = am43xx_dss_supported_outputs, + .ops = &dss_ops_omap2_omap3, + .dispc_clk_switch = { 0, 0 }, + .has_lcd_clk_src = true, }; static const struct dss_features dra7xx_dss_feats = { + .model = DSS_MODEL_DRA7, .fck_div_max = 64, + .fck_freq_max = 209250000, .dss_fck_multiplier = 1, .parent_clk_name = "dpll_per_x2_ck", - .dpi_select_source = &dss_dpi_select_source_dra7xx, .ports = dra7xx_ports, .num_ports = ARRAY_SIZE(dra7xx_ports), - .select_lcd_source = &dss_lcd_clk_mux_dra7, + .outputs = omap5_dss_supported_outputs, + .ops = &dss_ops_dra7, + .dispc_clk_switch = { 9, 7 }, + .has_lcd_clk_src = true, }; -static int dss_init_features(struct platform_device *pdev) -{ - const struct dss_features *src; - struct dss_features *dst; - - dst = devm_kzalloc(&pdev->dev, sizeof(*dst), GFP_KERNEL); - if (!dst) { - dev_err(&pdev->dev, "Failed to allocate local DSS Features\n"); - return -ENOMEM; - } - - switch (omapdss_get_version()) { - case OMAPDSS_VER_OMAP24xx: - src = &omap24xx_dss_feats; - break; - - case OMAPDSS_VER_OMAP34xx_ES1: - case OMAPDSS_VER_OMAP34xx_ES3: - case OMAPDSS_VER_AM35xx: - src = &omap34xx_dss_feats; - break; - - case OMAPDSS_VER_OMAP3630: - src = &omap3630_dss_feats; - break; - - case OMAPDSS_VER_OMAP4430_ES1: - case OMAPDSS_VER_OMAP4430_ES2: - case OMAPDSS_VER_OMAP4: - src = &omap44xx_dss_feats; - break; - - case OMAPDSS_VER_OMAP5: - src = &omap54xx_dss_feats; - break; - - case OMAPDSS_VER_AM43xx: - src = &am43xx_dss_feats; - break; - - case OMAPDSS_VER_DRA7xx: - src = &dra7xx_dss_feats; - break; - - default: - return -ENODEV; - } - - memcpy(dst, src, sizeof(*dst)); - dss.feat = dst; - - return 0; -} - static int dss_init_ports(struct platform_device *pdev) { struct device_node *parent = pdev->dev.of_node; @@ -1045,7 +1181,7 @@ static int dss_init_ports(struct platform_device *pdev) switch (dss.feat->ports[i]) { case OMAP_DISPLAY_TYPE_DPI: - dpi_init_port(pdev, port); + dpi_init_port(pdev, port, dss.feat->model); break; case OMAP_DISPLAY_TYPE_SDI: sdi_init_port(pdev, port); @@ -1144,6 +1280,23 @@ static int dss_video_pll_probe(struct platform_device *pdev) } /* DSS HW IP initialisation */ +static const struct of_device_id dss_of_match[] = { + { .compatible = "ti,omap2-dss", .data = &omap24xx_dss_feats }, + { .compatible = "ti,omap3-dss", .data = &omap3630_dss_feats }, + { .compatible = "ti,omap4-dss", .data = &omap44xx_dss_feats }, + { .compatible = "ti,omap5-dss", .data = &omap54xx_dss_feats }, + { .compatible = "ti,dra7-dss", .data = &dra7xx_dss_feats }, + {}, +}; +MODULE_DEVICE_TABLE(of, dss_of_match); + +static const struct soc_device_attribute dss_soc_devices[] = { + { .machine = "OMAP3430/3530", .data = &omap34xx_dss_feats }, + { .machine = "AM35??", .data = &omap34xx_dss_feats }, + { .family = "AM43xx", .data = &am43xx_dss_feats }, + { /* sentinel */ } +}; + static int dss_bind(struct device *dev) { struct platform_device *pdev = to_platform_device(dev); @@ -1151,12 +1304,6 @@ static int dss_bind(struct device *dev) u32 rev; int r; - dss.pdev = pdev; - - r = dss_init_features(dss.pdev); - if (r) - return r; - dss_mem = platform_get_resource(dss.pdev, IORESOURCE_MEM, 0); dss.base = devm_ioremap_resource(&pdev->dev, dss_mem); if (IS_ERR(dss.base)) @@ -1288,15 +1435,34 @@ static int dss_add_child_component(struct device *dev, void *data) static int dss_probe(struct platform_device *pdev) { + const struct soc_device_attribute *soc; struct component_match *match = NULL; int r; + dss.pdev = pdev; + + /* + * The various OMAP3-based SoCs can't be told apart using the compatible + * string, use SoC device matching. + */ + soc = soc_device_match(dss_soc_devices); + if (soc) + dss.feat = soc->data; + else + dss.feat = of_match_device(dss_of_match, &pdev->dev)->data; + + r = dss_initialize_debugfs(); + if (r) + return r; + /* add all the child devices as components */ device_for_each_child(&pdev->dev, &match, dss_add_child_component); r = component_master_add_with_match(&pdev->dev, &dss_component_ops, match); - if (r) + if (r) { + dss_uninitialize_debugfs(); return r; + } return 0; } @@ -1304,9 +1470,27 @@ static int dss_probe(struct platform_device *pdev) static int dss_remove(struct platform_device *pdev) { component_master_del(&pdev->dev, &dss_component_ops); + + dss_uninitialize_debugfs(); + return 0; } +static void dss_shutdown(struct platform_device *pdev) +{ + struct omap_dss_device *dssdev = NULL; + + DSSDBG("shutdown\n"); + + for_each_dss_dev(dssdev) { + if (!dssdev->driver) + continue; + + if (dssdev->state == OMAP_DSS_DISPLAY_ACTIVE) + dssdev->driver->disable(dssdev); + } +} + static int dss_runtime_suspend(struct device *dev) { dss_save_context(); @@ -1343,20 +1527,10 @@ static const struct dev_pm_ops dss_pm_ops = { .runtime_resume = dss_runtime_resume, }; -static const struct of_device_id dss_of_match[] = { - { .compatible = "ti,omap2-dss", }, - { .compatible = "ti,omap3-dss", }, - { .compatible = "ti,omap4-dss", }, - { .compatible = "ti,omap5-dss", }, - { .compatible = "ti,dra7-dss", }, - {}, -}; - -MODULE_DEVICE_TABLE(of, dss_of_match); - static struct platform_driver omap_dsshw_driver = { .probe = dss_probe, .remove = dss_remove, + .shutdown = dss_shutdown, .driver = { .name = "omapdss_dss", .pm = &dss_pm_ops, diff --git a/drivers/gpu/drm/omapdrm/dss/dss.h b/drivers/gpu/drm/omapdrm/dss/dss.h index 8dbf35f3ab23..ed465572491e 100644 --- a/drivers/gpu/drm/omapdrm/dss/dss.h +++ b/drivers/gpu/drm/omapdrm/dss/dss.h @@ -27,6 +27,9 @@ #include "omapdss.h" +#define MAX_DSS_LCD_MANAGERS 3 +#define MAX_NUM_DSI 2 + #ifdef pr_fmt #undef pr_fmt #endif @@ -72,6 +75,14 @@ #define FLD_MOD(orig, val, start, end) \ (((orig) & ~FLD_MASK(start, end)) | FLD_VAL(val, start, end)) +enum dss_model { + DSS_MODEL_OMAP2, + DSS_MODEL_OMAP3, + DSS_MODEL_OMAP4, + DSS_MODEL_OMAP5, + DSS_MODEL_DRA7, +}; + enum dss_io_pad_mode { DSS_IO_PAD_MODE_RESET, DSS_IO_PAD_MODE_RFBI, @@ -174,6 +185,9 @@ struct dss_pll_hw { bool has_freqsel; bool has_selfreqdco; bool has_refsel; + + /* DRA7 errata i886: use high N & M to avoid jitter */ + bool errata_i886; }; struct dss_pll { @@ -192,6 +206,11 @@ struct dss_pll { struct dss_pll_clock_info cinfo; }; +/* Defines a generic omap register field */ +struct dss_reg_field { + u8 start, end; +}; + struct dispc_clock_info { /* rates that we get with dividers below */ unsigned long lck; @@ -219,10 +238,11 @@ struct seq_file; struct platform_device; /* core */ -int dss_dsi_enable_pads(int dsi_id, unsigned lane_mask); -void dss_dsi_disable_pads(int dsi_id, unsigned lane_mask); -int dss_set_min_bus_tput(struct device *dev, unsigned long tput); -int dss_debugfs_create_file(const char *name, void (*write)(struct seq_file *)); +static inline int dss_set_min_bus_tput(struct device *dev, unsigned long tput) +{ + /* To be implemented when the OMAP platform will provide this feature */ + return 0; +} static inline bool dss_mgr_is_lcd(enum omap_channel id) { @@ -234,6 +254,16 @@ static inline bool dss_mgr_is_lcd(enum omap_channel id) } /* DSS */ +#if defined(CONFIG_OMAP2_DSS_DEBUGFS) +int dss_debugfs_create_file(const char *name, void (*write)(struct seq_file *)); +#else +static inline int dss_debugfs_create_file(const char *name, + void (*write)(struct seq_file *)) +{ + return 0; +} +#endif /* CONFIG_OMAP2_DSS_DEBUGFS */ + int dss_init_platform_driver(void) __init; void dss_uninit_platform_driver(void); @@ -241,6 +271,8 @@ int dss_runtime_get(void); void dss_runtime_put(void); unsigned long dss_get_dispc_clk_rate(void); +unsigned long dss_get_max_fck_rate(void); +enum omap_dss_output_id dss_get_supported_outputs(enum omap_channel channel); int dss_dpi_select_source(int port, enum omap_channel channel); void dss_select_hdmi_venc_clk_source(enum dss_hdmi_venc_clk_source_select); enum dss_hdmi_venc_clk_source_select dss_get_hdmi_venc_clk_source(void); @@ -252,10 +284,6 @@ struct dss_pll *dss_video_pll_init(struct platform_device *pdev, int id, struct regulator *regulator); void dss_video_pll_uninit(struct dss_pll *pll); -#if defined(CONFIG_OMAP2_DSS_DEBUGFS) -void dss_debug_dump_clocks(struct seq_file *s); -#endif - void dss_ctrl_pll_enable(enum dss_pll_id pll_id, bool enable); void dss_sdi_init(int datapairs); @@ -312,11 +340,12 @@ void dsi_irq_handler(void); /* DPI */ #ifdef CONFIG_OMAP2_DSS_DPI -int dpi_init_port(struct platform_device *pdev, struct device_node *port); +int dpi_init_port(struct platform_device *pdev, struct device_node *port, + enum dss_model dss_model); void dpi_uninit_port(struct device_node *port); #else static inline int dpi_init_port(struct platform_device *pdev, - struct device_node *port) + struct device_node *port, enum dss_model dss_model) { return 0; } diff --git a/drivers/gpu/drm/omapdrm/dss/dss_features.c b/drivers/gpu/drm/omapdrm/dss/dss_features.c deleted file mode 100644 index 0e599710dd95..000000000000 --- a/drivers/gpu/drm/omapdrm/dss/dss_features.c +++ /dev/null @@ -1,905 +0,0 @@ -/* - * linux/drivers/video/omap2/dss/dss_features.c - * - * Copyright (C) 2010 Texas Instruments - * Author: Archit Taneja <archit@ti.com> - * - * This program is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 as published by - * the Free Software Foundation. - * - * 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. - * - * You should have received a copy of the GNU General Public License along with - * this program. If not, see <http://www.gnu.org/licenses/>. - */ - -#include <linux/kernel.h> -#include <linux/module.h> -#include <linux/types.h> -#include <linux/err.h> -#include <linux/slab.h> -#include <drm/drm_fourcc.h> - -#include "omapdss.h" -#include "dss.h" -#include "dss_features.h" - -/* Defines a generic omap register field */ -struct dss_reg_field { - u8 start, end; -}; - -struct dss_param_range { - int min, max; -}; - -struct omap_dss_features { - const struct dss_reg_field *reg_fields; - const int num_reg_fields; - - const enum dss_feat_id *features; - const int num_features; - - const int num_mgrs; - const int num_ovls; - const enum omap_display_type *supported_displays; - const enum omap_dss_output_id *supported_outputs; - const u32 **supported_color_modes; - const enum omap_overlay_caps *overlay_caps; - const struct dss_param_range *dss_params; - - const u32 buffer_size_unit; - const u32 burst_size_unit; -}; - -/* This struct is assigned to one of the below during initialization */ -static const struct omap_dss_features *omap_current_dss_features; - -static const struct dss_reg_field omap2_dss_reg_fields[] = { - [FEAT_REG_FIRHINC] = { 11, 0 }, - [FEAT_REG_FIRVINC] = { 27, 16 }, - [FEAT_REG_FIFOLOWTHRESHOLD] = { 8, 0 }, - [FEAT_REG_FIFOHIGHTHRESHOLD] = { 24, 16 }, - [FEAT_REG_FIFOSIZE] = { 8, 0 }, - [FEAT_REG_HORIZONTALACCU] = { 9, 0 }, - [FEAT_REG_VERTICALACCU] = { 25, 16 }, - [FEAT_REG_DISPC_CLK_SWITCH] = { 0, 0 }, -}; - -static const struct dss_reg_field omap3_dss_reg_fields[] = { - [FEAT_REG_FIRHINC] = { 12, 0 }, - [FEAT_REG_FIRVINC] = { 28, 16 }, - [FEAT_REG_FIFOLOWTHRESHOLD] = { 11, 0 }, - [FEAT_REG_FIFOHIGHTHRESHOLD] = { 27, 16 }, - [FEAT_REG_FIFOSIZE] = { 10, 0 }, - [FEAT_REG_HORIZONTALACCU] = { 9, 0 }, - [FEAT_REG_VERTICALACCU] = { 25, 16 }, - [FEAT_REG_DISPC_CLK_SWITCH] = { 0, 0 }, -}; - -static const struct dss_reg_field am43xx_dss_reg_fields[] = { - [FEAT_REG_FIRHINC] = { 12, 0 }, - [FEAT_REG_FIRVINC] = { 28, 16 }, - [FEAT_REG_FIFOLOWTHRESHOLD] = { 11, 0 }, - [FEAT_REG_FIFOHIGHTHRESHOLD] = { 27, 16 }, - [FEAT_REG_FIFOSIZE] = { 10, 0 }, - [FEAT_REG_HORIZONTALACCU] = { 9, 0 }, - [FEAT_REG_VERTICALACCU] = { 25, 16 }, - [FEAT_REG_DISPC_CLK_SWITCH] = { 0, 0 }, -}; - -static const struct dss_reg_field omap4_dss_reg_fields[] = { - [FEAT_REG_FIRHINC] = { 12, 0 }, - [FEAT_REG_FIRVINC] = { 28, 16 }, - [FEAT_REG_FIFOLOWTHRESHOLD] = { 15, 0 }, - [FEAT_REG_FIFOHIGHTHRESHOLD] = { 31, 16 }, - [FEAT_REG_FIFOSIZE] = { 15, 0 }, - [FEAT_REG_HORIZONTALACCU] = { 10, 0 }, - [FEAT_REG_VERTICALACCU] = { 26, 16 }, - [FEAT_REG_DISPC_CLK_SWITCH] = { 9, 8 }, -}; - -static const struct dss_reg_field omap5_dss_reg_fields[] = { - [FEAT_REG_FIRHINC] = { 12, 0 }, - [FEAT_REG_FIRVINC] = { 28, 16 }, - [FEAT_REG_FIFOLOWTHRESHOLD] = { 15, 0 }, - [FEAT_REG_FIFOHIGHTHRESHOLD] = { 31, 16 }, - [FEAT_REG_FIFOSIZE] = { 15, 0 }, - [FEAT_REG_HORIZONTALACCU] = { 10, 0 }, - [FEAT_REG_VERTICALACCU] = { 26, 16 }, - [FEAT_REG_DISPC_CLK_SWITCH] = { 9, 7 }, -}; - -static const enum omap_display_type omap2_dss_supported_displays[] = { - /* OMAP_DSS_CHANNEL_LCD */ - OMAP_DISPLAY_TYPE_DPI | OMAP_DISPLAY_TYPE_DBI, - - /* OMAP_DSS_CHANNEL_DIGIT */ - OMAP_DISPLAY_TYPE_VENC, -}; - -static const enum omap_display_type omap3430_dss_supported_displays[] = { - /* OMAP_DSS_CHANNEL_LCD */ - OMAP_DISPLAY_TYPE_DPI | OMAP_DISPLAY_TYPE_DBI | - OMAP_DISPLAY_TYPE_SDI | OMAP_DISPLAY_TYPE_DSI, - - /* OMAP_DSS_CHANNEL_DIGIT */ - OMAP_DISPLAY_TYPE_VENC, -}; - -static const enum omap_display_type omap3630_dss_supported_displays[] = { - /* OMAP_DSS_CHANNEL_LCD */ - OMAP_DISPLAY_TYPE_DPI | OMAP_DISPLAY_TYPE_DBI | - OMAP_DISPLAY_TYPE_DSI, - - /* OMAP_DSS_CHANNEL_DIGIT */ - OMAP_DISPLAY_TYPE_VENC, -}; - -static const enum omap_display_type am43xx_dss_supported_displays[] = { - /* OMAP_DSS_CHANNEL_LCD */ - OMAP_DISPLAY_TYPE_DPI | OMAP_DISPLAY_TYPE_DBI, -}; - -static const enum omap_display_type omap4_dss_supported_displays[] = { - /* OMAP_DSS_CHANNEL_LCD */ - OMAP_DISPLAY_TYPE_DBI | OMAP_DISPLAY_TYPE_DSI, - - /* OMAP_DSS_CHANNEL_DIGIT */ - OMAP_DISPLAY_TYPE_VENC | OMAP_DISPLAY_TYPE_HDMI, - - /* OMAP_DSS_CHANNEL_LCD2 */ - OMAP_DISPLAY_TYPE_DPI | OMAP_DISPLAY_TYPE_DBI | - OMAP_DISPLAY_TYPE_DSI, -}; - -static const enum omap_display_type omap5_dss_supported_displays[] = { - /* OMAP_DSS_CHANNEL_LCD */ - OMAP_DISPLAY_TYPE_DPI | OMAP_DISPLAY_TYPE_DBI | - OMAP_DISPLAY_TYPE_DSI, - - /* OMAP_DSS_CHANNEL_DIGIT */ - OMAP_DISPLAY_TYPE_HDMI | OMAP_DISPLAY_TYPE_DPI, - - /* OMAP_DSS_CHANNEL_LCD2 */ - OMAP_DISPLAY_TYPE_DPI | OMAP_DISPLAY_TYPE_DBI | - OMAP_DISPLAY_TYPE_DSI, -}; - -static const enum omap_dss_output_id omap2_dss_supported_outputs[] = { - /* OMAP_DSS_CHANNEL_LCD */ - OMAP_DSS_OUTPUT_DPI | OMAP_DSS_OUTPUT_DBI, - - /* OMAP_DSS_CHANNEL_DIGIT */ - OMAP_DSS_OUTPUT_VENC, -}; - -static const enum omap_dss_output_id omap3430_dss_supported_outputs[] = { - /* OMAP_DSS_CHANNEL_LCD */ - OMAP_DSS_OUTPUT_DPI | OMAP_DSS_OUTPUT_DBI | - OMAP_DSS_OUTPUT_SDI | OMAP_DSS_OUTPUT_DSI1, - - /* OMAP_DSS_CHANNEL_DIGIT */ - OMAP_DSS_OUTPUT_VENC, -}; - -static const enum omap_dss_output_id omap3630_dss_supported_outputs[] = { - /* OMAP_DSS_CHANNEL_LCD */ - OMAP_DSS_OUTPUT_DPI | OMAP_DSS_OUTPUT_DBI | - OMAP_DSS_OUTPUT_DSI1, - - /* OMAP_DSS_CHANNEL_DIGIT */ - OMAP_DSS_OUTPUT_VENC, -}; - -static const enum omap_dss_output_id am43xx_dss_supported_outputs[] = { - /* OMAP_DSS_CHANNEL_LCD */ - OMAP_DSS_OUTPUT_DPI | OMAP_DSS_OUTPUT_DBI, -}; - -static const enum omap_dss_output_id omap4_dss_supported_outputs[] = { - /* OMAP_DSS_CHANNEL_LCD */ - OMAP_DSS_OUTPUT_DBI | OMAP_DSS_OUTPUT_DSI1, - - /* OMAP_DSS_CHANNEL_DIGIT */ - OMAP_DSS_OUTPUT_VENC | OMAP_DSS_OUTPUT_HDMI, - - /* OMAP_DSS_CHANNEL_LCD2 */ - OMAP_DSS_OUTPUT_DPI | OMAP_DSS_OUTPUT_DBI | - OMAP_DSS_OUTPUT_DSI2, -}; - -static const enum omap_dss_output_id omap5_dss_supported_outputs[] = { - /* OMAP_DSS_CHANNEL_LCD */ - OMAP_DSS_OUTPUT_DPI | OMAP_DSS_OUTPUT_DBI | - OMAP_DSS_OUTPUT_DSI1 | OMAP_DSS_OUTPUT_DSI2, - - /* OMAP_DSS_CHANNEL_DIGIT */ - OMAP_DSS_OUTPUT_HDMI, - - /* OMAP_DSS_CHANNEL_LCD2 */ - OMAP_DSS_OUTPUT_DPI | OMAP_DSS_OUTPUT_DBI | - OMAP_DSS_OUTPUT_DSI1, - - /* OMAP_DSS_CHANNEL_LCD3 */ - OMAP_DSS_OUTPUT_DPI | OMAP_DSS_OUTPUT_DBI | - OMAP_DSS_OUTPUT_DSI2, -}; - -#define COLOR_ARRAY(arr...) (const u32[]) { arr, 0 } - -static const u32 *omap2_dss_supported_color_modes[] = { - - /* OMAP_DSS_GFX */ - COLOR_ARRAY( - DRM_FORMAT_RGBX4444, DRM_FORMAT_RGB565, - DRM_FORMAT_XRGB8888, DRM_FORMAT_RGB888), - - /* OMAP_DSS_VIDEO1 */ - COLOR_ARRAY( - DRM_FORMAT_RGB565, DRM_FORMAT_XRGB8888, - DRM_FORMAT_RGB888, DRM_FORMAT_YUYV, - DRM_FORMAT_UYVY), - - /* OMAP_DSS_VIDEO2 */ - COLOR_ARRAY( - DRM_FORMAT_RGB565, DRM_FORMAT_XRGB8888, - DRM_FORMAT_RGB888, DRM_FORMAT_YUYV, - DRM_FORMAT_UYVY), -}; - -static const u32 *omap3_dss_supported_color_modes[] = { - /* OMAP_DSS_GFX */ - COLOR_ARRAY( - DRM_FORMAT_RGBX4444, DRM_FORMAT_ARGB4444, - DRM_FORMAT_RGB565, DRM_FORMAT_XRGB8888, - DRM_FORMAT_RGB888, DRM_FORMAT_ARGB8888, - DRM_FORMAT_RGBA8888, DRM_FORMAT_RGBX8888), - - /* OMAP_DSS_VIDEO1 */ - COLOR_ARRAY( - DRM_FORMAT_XRGB8888, DRM_FORMAT_RGB888, - DRM_FORMAT_RGBX4444, DRM_FORMAT_RGB565, - DRM_FORMAT_YUYV, DRM_FORMAT_UYVY), - - /* OMAP_DSS_VIDEO2 */ - COLOR_ARRAY( - DRM_FORMAT_RGBX4444, DRM_FORMAT_ARGB4444, - DRM_FORMAT_RGB565, DRM_FORMAT_XRGB8888, - DRM_FORMAT_RGB888, DRM_FORMAT_YUYV, - DRM_FORMAT_UYVY, DRM_FORMAT_ARGB8888, - DRM_FORMAT_RGBA8888, DRM_FORMAT_RGBX8888), -}; - -static const u32 *omap4_dss_supported_color_modes[] = { - /* OMAP_DSS_GFX */ - COLOR_ARRAY( - DRM_FORMAT_RGBX4444, DRM_FORMAT_ARGB4444, - DRM_FORMAT_RGB565, DRM_FORMAT_XRGB8888, - DRM_FORMAT_RGB888, DRM_FORMAT_ARGB8888, - DRM_FORMAT_RGBA8888, DRM_FORMAT_RGBX8888, - DRM_FORMAT_ARGB1555, DRM_FORMAT_XRGB4444, - DRM_FORMAT_RGBA4444, DRM_FORMAT_XRGB1555), - - /* OMAP_DSS_VIDEO1 */ - COLOR_ARRAY( - DRM_FORMAT_RGB565, DRM_FORMAT_RGBX4444, - DRM_FORMAT_YUYV, DRM_FORMAT_ARGB1555, - DRM_FORMAT_RGBA8888, DRM_FORMAT_NV12, - DRM_FORMAT_RGBA4444, DRM_FORMAT_XRGB8888, - DRM_FORMAT_RGB888, DRM_FORMAT_UYVY, - DRM_FORMAT_ARGB4444, DRM_FORMAT_XRGB1555, - DRM_FORMAT_ARGB8888, DRM_FORMAT_XRGB4444, - DRM_FORMAT_RGBX8888), - - /* OMAP_DSS_VIDEO2 */ - COLOR_ARRAY( - DRM_FORMAT_RGB565, DRM_FORMAT_RGBX4444, - DRM_FORMAT_YUYV, DRM_FORMAT_ARGB1555, - DRM_FORMAT_RGBA8888, DRM_FORMAT_NV12, - DRM_FORMAT_RGBA4444, DRM_FORMAT_XRGB8888, - DRM_FORMAT_RGB888, DRM_FORMAT_UYVY, - DRM_FORMAT_ARGB4444, DRM_FORMAT_XRGB1555, - DRM_FORMAT_ARGB8888, DRM_FORMAT_XRGB4444, - DRM_FORMAT_RGBX8888), - - /* OMAP_DSS_VIDEO3 */ - COLOR_ARRAY( - DRM_FORMAT_RGB565, DRM_FORMAT_RGBX4444, - DRM_FORMAT_YUYV, DRM_FORMAT_ARGB1555, - DRM_FORMAT_RGBA8888, DRM_FORMAT_NV12, - DRM_FORMAT_RGBA4444, DRM_FORMAT_XRGB8888, - DRM_FORMAT_RGB888, DRM_FORMAT_UYVY, - DRM_FORMAT_ARGB4444, DRM_FORMAT_XRGB1555, - DRM_FORMAT_ARGB8888, DRM_FORMAT_XRGB4444, - DRM_FORMAT_RGBX8888), - - /* OMAP_DSS_WB */ - COLOR_ARRAY( - DRM_FORMAT_RGB565, DRM_FORMAT_RGBX4444, - DRM_FORMAT_YUYV, DRM_FORMAT_ARGB1555, - DRM_FORMAT_RGBA8888, DRM_FORMAT_NV12, - DRM_FORMAT_RGBA4444, DRM_FORMAT_XRGB8888, - DRM_FORMAT_RGB888, DRM_FORMAT_UYVY, - DRM_FORMAT_ARGB4444, DRM_FORMAT_XRGB1555, - DRM_FORMAT_ARGB8888, DRM_FORMAT_XRGB4444, - DRM_FORMAT_RGBX8888), -}; - -static const enum omap_overlay_caps omap2_dss_overlay_caps[] = { - /* OMAP_DSS_GFX */ - OMAP_DSS_OVL_CAP_POS | OMAP_DSS_OVL_CAP_REPLICATION, - - /* OMAP_DSS_VIDEO1 */ - OMAP_DSS_OVL_CAP_SCALE | OMAP_DSS_OVL_CAP_POS | - OMAP_DSS_OVL_CAP_REPLICATION, - - /* OMAP_DSS_VIDEO2 */ - OMAP_DSS_OVL_CAP_SCALE | OMAP_DSS_OVL_CAP_POS | - OMAP_DSS_OVL_CAP_REPLICATION, -}; - -static const enum omap_overlay_caps omap3430_dss_overlay_caps[] = { - /* OMAP_DSS_GFX */ - OMAP_DSS_OVL_CAP_GLOBAL_ALPHA | OMAP_DSS_OVL_CAP_POS | - OMAP_DSS_OVL_CAP_REPLICATION, - - /* OMAP_DSS_VIDEO1 */ - OMAP_DSS_OVL_CAP_SCALE | OMAP_DSS_OVL_CAP_POS | - OMAP_DSS_OVL_CAP_REPLICATION, - - /* OMAP_DSS_VIDEO2 */ - OMAP_DSS_OVL_CAP_SCALE | OMAP_DSS_OVL_CAP_GLOBAL_ALPHA | - OMAP_DSS_OVL_CAP_POS | OMAP_DSS_OVL_CAP_REPLICATION, -}; - -static const enum omap_overlay_caps omap3630_dss_overlay_caps[] = { - /* OMAP_DSS_GFX */ - OMAP_DSS_OVL_CAP_GLOBAL_ALPHA | OMAP_DSS_OVL_CAP_PRE_MULT_ALPHA | - OMAP_DSS_OVL_CAP_POS | OMAP_DSS_OVL_CAP_REPLICATION, - - /* OMAP_DSS_VIDEO1 */ - OMAP_DSS_OVL_CAP_SCALE | OMAP_DSS_OVL_CAP_POS | - OMAP_DSS_OVL_CAP_REPLICATION, - - /* OMAP_DSS_VIDEO2 */ - OMAP_DSS_OVL_CAP_SCALE | OMAP_DSS_OVL_CAP_GLOBAL_ALPHA | - OMAP_DSS_OVL_CAP_PRE_MULT_ALPHA | OMAP_DSS_OVL_CAP_POS | - OMAP_DSS_OVL_CAP_REPLICATION, -}; - -static const enum omap_overlay_caps omap4_dss_overlay_caps[] = { - /* OMAP_DSS_GFX */ - OMAP_DSS_OVL_CAP_GLOBAL_ALPHA | OMAP_DSS_OVL_CAP_PRE_MULT_ALPHA | - OMAP_DSS_OVL_CAP_ZORDER | OMAP_DSS_OVL_CAP_POS | - OMAP_DSS_OVL_CAP_REPLICATION, - - /* OMAP_DSS_VIDEO1 */ - OMAP_DSS_OVL_CAP_SCALE | OMAP_DSS_OVL_CAP_GLOBAL_ALPHA | - OMAP_DSS_OVL_CAP_PRE_MULT_ALPHA | OMAP_DSS_OVL_CAP_ZORDER | - OMAP_DSS_OVL_CAP_POS | OMAP_DSS_OVL_CAP_REPLICATION, - - /* OMAP_DSS_VIDEO2 */ - OMAP_DSS_OVL_CAP_SCALE | OMAP_DSS_OVL_CAP_GLOBAL_ALPHA | - OMAP_DSS_OVL_CAP_PRE_MULT_ALPHA | OMAP_DSS_OVL_CAP_ZORDER | - OMAP_DSS_OVL_CAP_POS | OMAP_DSS_OVL_CAP_REPLICATION, - - /* OMAP_DSS_VIDEO3 */ - OMAP_DSS_OVL_CAP_SCALE | OMAP_DSS_OVL_CAP_GLOBAL_ALPHA | - OMAP_DSS_OVL_CAP_PRE_MULT_ALPHA | OMAP_DSS_OVL_CAP_ZORDER | - OMAP_DSS_OVL_CAP_POS | OMAP_DSS_OVL_CAP_REPLICATION, -}; - -static const struct dss_param_range omap2_dss_param_range[] = { - [FEAT_PARAM_DSS_FCK] = { 0, 133000000 }, - [FEAT_PARAM_DSS_PCD] = { 2, 255 }, - [FEAT_PARAM_DOWNSCALE] = { 1, 2 }, - /* - * Assuming the line width buffer to be 768 pixels as OMAP2 DISPC - * scaler cannot scale a image with width more than 768. - */ - [FEAT_PARAM_LINEWIDTH] = { 1, 768 }, -}; - -static const struct dss_param_range omap3_dss_param_range[] = { - [FEAT_PARAM_DSS_FCK] = { 0, 173000000 }, - [FEAT_PARAM_DSS_PCD] = { 1, 255 }, - [FEAT_PARAM_DSIPLL_LPDIV] = { 1, (1 << 13) - 1}, - [FEAT_PARAM_DSI_FCK] = { 0, 173000000 }, - [FEAT_PARAM_DOWNSCALE] = { 1, 4 }, - [FEAT_PARAM_LINEWIDTH] = { 1, 1024 }, -}; - -static const struct dss_param_range am43xx_dss_param_range[] = { - [FEAT_PARAM_DSS_FCK] = { 0, 200000000 }, - [FEAT_PARAM_DSS_PCD] = { 1, 255 }, - [FEAT_PARAM_DOWNSCALE] = { 1, 4 }, - [FEAT_PARAM_LINEWIDTH] = { 1, 1024 }, -}; - -static const struct dss_param_range omap4_dss_param_range[] = { - [FEAT_PARAM_DSS_FCK] = { 0, 186000000 }, - [FEAT_PARAM_DSS_PCD] = { 1, 255 }, - [FEAT_PARAM_DSIPLL_LPDIV] = { 0, (1 << 13) - 1 }, - [FEAT_PARAM_DSI_FCK] = { 0, 170000000 }, - [FEAT_PARAM_DOWNSCALE] = { 1, 4 }, - [FEAT_PARAM_LINEWIDTH] = { 1, 2048 }, -}; - -static const struct dss_param_range omap5_dss_param_range[] = { - [FEAT_PARAM_DSS_FCK] = { 0, 209250000 }, - [FEAT_PARAM_DSS_PCD] = { 1, 255 }, - [FEAT_PARAM_DSIPLL_LPDIV] = { 0, (1 << 13) - 1 }, - [FEAT_PARAM_DSI_FCK] = { 0, 209250000 }, - [FEAT_PARAM_DOWNSCALE] = { 1, 4 }, - [FEAT_PARAM_LINEWIDTH] = { 1, 2048 }, -}; - -static const enum dss_feat_id omap2_dss_feat_list[] = { - FEAT_LCDENABLEPOL, - FEAT_LCDENABLESIGNAL, - FEAT_PCKFREEENABLE, - FEAT_FUNCGATED, - FEAT_ROWREPEATENABLE, - FEAT_RESIZECONF, -}; - -static const enum dss_feat_id omap3430_dss_feat_list[] = { - FEAT_LCDENABLEPOL, - FEAT_LCDENABLESIGNAL, - FEAT_PCKFREEENABLE, - FEAT_FUNCGATED, - FEAT_LINEBUFFERSPLIT, - FEAT_ROWREPEATENABLE, - FEAT_RESIZECONF, - FEAT_DSI_REVERSE_TXCLKESC, - FEAT_VENC_REQUIRES_TV_DAC_CLK, - FEAT_CPR, - FEAT_PRELOAD, - FEAT_FIR_COEF_V, - FEAT_ALPHA_FIXED_ZORDER, - FEAT_FIFO_MERGE, - FEAT_OMAP3_DSI_FIFO_BUG, - FEAT_DPI_USES_VDDS_DSI, -}; - -static const enum dss_feat_id am35xx_dss_feat_list[] = { - FEAT_LCDENABLEPOL, - FEAT_LCDENABLESIGNAL, - FEAT_PCKFREEENABLE, - FEAT_FUNCGATED, - FEAT_LINEBUFFERSPLIT, - FEAT_ROWREPEATENABLE, - FEAT_RESIZECONF, - FEAT_DSI_REVERSE_TXCLKESC, - FEAT_VENC_REQUIRES_TV_DAC_CLK, - FEAT_CPR, - FEAT_PRELOAD, - FEAT_FIR_COEF_V, - FEAT_ALPHA_FIXED_ZORDER, - FEAT_FIFO_MERGE, - FEAT_OMAP3_DSI_FIFO_BUG, -}; - -static const enum dss_feat_id am43xx_dss_feat_list[] = { - FEAT_LCDENABLEPOL, - FEAT_LCDENABLESIGNAL, - FEAT_PCKFREEENABLE, - FEAT_FUNCGATED, - FEAT_LINEBUFFERSPLIT, - FEAT_ROWREPEATENABLE, - FEAT_RESIZECONF, - FEAT_CPR, - FEAT_PRELOAD, - FEAT_FIR_COEF_V, - FEAT_ALPHA_FIXED_ZORDER, - FEAT_FIFO_MERGE, -}; - -static const enum dss_feat_id omap3630_dss_feat_list[] = { - FEAT_LCDENABLEPOL, - FEAT_LCDENABLESIGNAL, - FEAT_PCKFREEENABLE, - FEAT_FUNCGATED, - FEAT_LINEBUFFERSPLIT, - FEAT_ROWREPEATENABLE, - FEAT_RESIZECONF, - FEAT_DSI_PLL_PWR_BUG, - FEAT_CPR, - FEAT_PRELOAD, - FEAT_FIR_COEF_V, - FEAT_ALPHA_FIXED_ZORDER, - FEAT_FIFO_MERGE, - FEAT_OMAP3_DSI_FIFO_BUG, - FEAT_DPI_USES_VDDS_DSI, -}; - -static const enum dss_feat_id omap4430_es1_0_dss_feat_list[] = { - FEAT_MGR_LCD2, - FEAT_CORE_CLK_DIV, - FEAT_LCD_CLK_SRC, - FEAT_DSI_DCS_CMD_CONFIG_VC, - FEAT_DSI_VC_OCP_WIDTH, - FEAT_DSI_GNQ, - FEAT_HANDLE_UV_SEPARATE, - FEAT_ATTR2, - FEAT_CPR, - FEAT_PRELOAD, - FEAT_FIR_COEF_V, - FEAT_ALPHA_FREE_ZORDER, - FEAT_FIFO_MERGE, - FEAT_BURST_2D, -}; - -static const enum dss_feat_id omap4430_es2_0_1_2_dss_feat_list[] = { - FEAT_MGR_LCD2, - FEAT_CORE_CLK_DIV, - FEAT_LCD_CLK_SRC, - FEAT_DSI_DCS_CMD_CONFIG_VC, - FEAT_DSI_VC_OCP_WIDTH, - FEAT_DSI_GNQ, - FEAT_HDMI_CTS_SWMODE, - FEAT_HANDLE_UV_SEPARATE, - FEAT_ATTR2, - FEAT_CPR, - FEAT_PRELOAD, - FEAT_FIR_COEF_V, - FEAT_ALPHA_FREE_ZORDER, - FEAT_FIFO_MERGE, - FEAT_BURST_2D, -}; - -static const enum dss_feat_id omap4_dss_feat_list[] = { - FEAT_MGR_LCD2, - FEAT_CORE_CLK_DIV, - FEAT_LCD_CLK_SRC, - FEAT_DSI_DCS_CMD_CONFIG_VC, - FEAT_DSI_VC_OCP_WIDTH, - FEAT_DSI_GNQ, - FEAT_HDMI_CTS_SWMODE, - FEAT_HDMI_AUDIO_USE_MCLK, - FEAT_HANDLE_UV_SEPARATE, - FEAT_ATTR2, - FEAT_CPR, - FEAT_PRELOAD, - FEAT_FIR_COEF_V, - FEAT_ALPHA_FREE_ZORDER, - FEAT_FIFO_MERGE, - FEAT_BURST_2D, -}; - -static const enum dss_feat_id omap5_dss_feat_list[] = { - FEAT_MGR_LCD2, - FEAT_MGR_LCD3, - FEAT_CORE_CLK_DIV, - FEAT_LCD_CLK_SRC, - FEAT_DSI_DCS_CMD_CONFIG_VC, - FEAT_DSI_VC_OCP_WIDTH, - FEAT_DSI_GNQ, - FEAT_HDMI_CTS_SWMODE, - FEAT_HDMI_AUDIO_USE_MCLK, - FEAT_HANDLE_UV_SEPARATE, - FEAT_ATTR2, - FEAT_CPR, - FEAT_PRELOAD, - FEAT_FIR_COEF_V, - FEAT_ALPHA_FREE_ZORDER, - FEAT_FIFO_MERGE, - FEAT_BURST_2D, - FEAT_DSI_PHY_DCC, - FEAT_MFLAG, -}; - -/* OMAP2 DSS Features */ -static const struct omap_dss_features omap2_dss_features = { - .reg_fields = omap2_dss_reg_fields, - .num_reg_fields = ARRAY_SIZE(omap2_dss_reg_fields), - - .features = omap2_dss_feat_list, - .num_features = ARRAY_SIZE(omap2_dss_feat_list), - - .num_mgrs = 2, - .num_ovls = 3, - .supported_displays = omap2_dss_supported_displays, - .supported_outputs = omap2_dss_supported_outputs, - .supported_color_modes = omap2_dss_supported_color_modes, - .overlay_caps = omap2_dss_overlay_caps, - .dss_params = omap2_dss_param_range, - .buffer_size_unit = 1, - .burst_size_unit = 8, -}; - -/* OMAP3 DSS Features */ -static const struct omap_dss_features omap3430_dss_features = { - .reg_fields = omap3_dss_reg_fields, - .num_reg_fields = ARRAY_SIZE(omap3_dss_reg_fields), - - .features = omap3430_dss_feat_list, - .num_features = ARRAY_SIZE(omap3430_dss_feat_list), - - .num_mgrs = 2, - .num_ovls = 3, - .supported_displays = omap3430_dss_supported_displays, - .supported_outputs = omap3430_dss_supported_outputs, - .supported_color_modes = omap3_dss_supported_color_modes, - .overlay_caps = omap3430_dss_overlay_caps, - .dss_params = omap3_dss_param_range, - .buffer_size_unit = 1, - .burst_size_unit = 8, -}; - -/* - * AM35xx DSS Features. This is basically OMAP3 DSS Features without the - * vdds_dsi regulator. - */ -static const struct omap_dss_features am35xx_dss_features = { - .reg_fields = omap3_dss_reg_fields, - .num_reg_fields = ARRAY_SIZE(omap3_dss_reg_fields), - - .features = am35xx_dss_feat_list, - .num_features = ARRAY_SIZE(am35xx_dss_feat_list), - - .num_mgrs = 2, - .num_ovls = 3, - .supported_displays = omap3430_dss_supported_displays, - .supported_outputs = omap3430_dss_supported_outputs, - .supported_color_modes = omap3_dss_supported_color_modes, - .overlay_caps = omap3430_dss_overlay_caps, - .dss_params = omap3_dss_param_range, - .buffer_size_unit = 1, - .burst_size_unit = 8, -}; - -static const struct omap_dss_features am43xx_dss_features = { - .reg_fields = am43xx_dss_reg_fields, - .num_reg_fields = ARRAY_SIZE(am43xx_dss_reg_fields), - - .features = am43xx_dss_feat_list, - .num_features = ARRAY_SIZE(am43xx_dss_feat_list), - - .num_mgrs = 1, - .num_ovls = 3, - .supported_displays = am43xx_dss_supported_displays, - .supported_outputs = am43xx_dss_supported_outputs, - .supported_color_modes = omap3_dss_supported_color_modes, - .overlay_caps = omap3430_dss_overlay_caps, - .dss_params = am43xx_dss_param_range, - .buffer_size_unit = 1, - .burst_size_unit = 8, -}; - -static const struct omap_dss_features omap3630_dss_features = { - .reg_fields = omap3_dss_reg_fields, - .num_reg_fields = ARRAY_SIZE(omap3_dss_reg_fields), - - .features = omap3630_dss_feat_list, - .num_features = ARRAY_SIZE(omap3630_dss_feat_list), - - .num_mgrs = 2, - .num_ovls = 3, - .supported_displays = omap3630_dss_supported_displays, - .supported_outputs = omap3630_dss_supported_outputs, - .supported_color_modes = omap3_dss_supported_color_modes, - .overlay_caps = omap3630_dss_overlay_caps, - .dss_params = omap3_dss_param_range, - .buffer_size_unit = 1, - .burst_size_unit = 8, -}; - -/* OMAP4 DSS Features */ -/* For OMAP4430 ES 1.0 revision */ -static const struct omap_dss_features omap4430_es1_0_dss_features = { - .reg_fields = omap4_dss_reg_fields, - .num_reg_fields = ARRAY_SIZE(omap4_dss_reg_fields), - - .features = omap4430_es1_0_dss_feat_list, - .num_features = ARRAY_SIZE(omap4430_es1_0_dss_feat_list), - - .num_mgrs = 3, - .num_ovls = 4, - .supported_displays = omap4_dss_supported_displays, - .supported_outputs = omap4_dss_supported_outputs, - .supported_color_modes = omap4_dss_supported_color_modes, - .overlay_caps = omap4_dss_overlay_caps, - .dss_params = omap4_dss_param_range, - .buffer_size_unit = 16, - .burst_size_unit = 16, -}; - -/* For OMAP4430 ES 2.0, 2.1 and 2.2 revisions */ -static const struct omap_dss_features omap4430_es2_0_1_2_dss_features = { - .reg_fields = omap4_dss_reg_fields, - .num_reg_fields = ARRAY_SIZE(omap4_dss_reg_fields), - - .features = omap4430_es2_0_1_2_dss_feat_list, - .num_features = ARRAY_SIZE(omap4430_es2_0_1_2_dss_feat_list), - - .num_mgrs = 3, - .num_ovls = 4, - .supported_displays = omap4_dss_supported_displays, - .supported_outputs = omap4_dss_supported_outputs, - .supported_color_modes = omap4_dss_supported_color_modes, - .overlay_caps = omap4_dss_overlay_caps, - .dss_params = omap4_dss_param_range, - .buffer_size_unit = 16, - .burst_size_unit = 16, -}; - -/* For all the other OMAP4 versions */ -static const struct omap_dss_features omap4_dss_features = { - .reg_fields = omap4_dss_reg_fields, - .num_reg_fields = ARRAY_SIZE(omap4_dss_reg_fields), - - .features = omap4_dss_feat_list, - .num_features = ARRAY_SIZE(omap4_dss_feat_list), - - .num_mgrs = 3, - .num_ovls = 4, - .supported_displays = omap4_dss_supported_displays, - .supported_outputs = omap4_dss_supported_outputs, - .supported_color_modes = omap4_dss_supported_color_modes, - .overlay_caps = omap4_dss_overlay_caps, - .dss_params = omap4_dss_param_range, - .buffer_size_unit = 16, - .burst_size_unit = 16, -}; - -/* OMAP5 DSS Features */ -static const struct omap_dss_features omap5_dss_features = { - .reg_fields = omap5_dss_reg_fields, - .num_reg_fields = ARRAY_SIZE(omap5_dss_reg_fields), - - .features = omap5_dss_feat_list, - .num_features = ARRAY_SIZE(omap5_dss_feat_list), - - .num_mgrs = 4, - .num_ovls = 4, - .supported_displays = omap5_dss_supported_displays, - .supported_outputs = omap5_dss_supported_outputs, - .supported_color_modes = omap4_dss_supported_color_modes, - .overlay_caps = omap4_dss_overlay_caps, - .dss_params = omap5_dss_param_range, - .buffer_size_unit = 16, - .burst_size_unit = 16, -}; - -/* Functions returning values related to a DSS feature */ -int dss_feat_get_num_mgrs(void) -{ - return omap_current_dss_features->num_mgrs; -} - -int dss_feat_get_num_ovls(void) -{ - return omap_current_dss_features->num_ovls; -} - -unsigned long dss_feat_get_param_min(enum dss_range_param param) -{ - return omap_current_dss_features->dss_params[param].min; -} - -unsigned long dss_feat_get_param_max(enum dss_range_param param) -{ - return omap_current_dss_features->dss_params[param].max; -} - -enum omap_display_type dss_feat_get_supported_displays(enum omap_channel channel) -{ - return omap_current_dss_features->supported_displays[channel]; -} - -enum omap_dss_output_id dss_feat_get_supported_outputs(enum omap_channel channel) -{ - return omap_current_dss_features->supported_outputs[channel]; -} - -const u32 *dss_feat_get_supported_color_modes(enum omap_plane_id plane) -{ - return omap_current_dss_features->supported_color_modes[plane]; -} - -enum omap_overlay_caps dss_feat_get_overlay_caps(enum omap_plane_id plane) -{ - return omap_current_dss_features->overlay_caps[plane]; -} - -bool dss_feat_color_mode_supported(enum omap_plane_id plane, u32 fourcc) -{ - const u32 *modes; - unsigned int i; - - modes = omap_current_dss_features->supported_color_modes[plane]; - - for (i = 0; modes[i]; ++i) { - if (modes[i] == fourcc) - return true; - } - - return false; -} - -u32 dss_feat_get_buffer_size_unit(void) -{ - return omap_current_dss_features->buffer_size_unit; -} - -u32 dss_feat_get_burst_size_unit(void) -{ - return omap_current_dss_features->burst_size_unit; -} - -/* DSS has_feature check */ -bool dss_has_feature(enum dss_feat_id id) -{ - int i; - const enum dss_feat_id *features = omap_current_dss_features->features; - const int num_features = omap_current_dss_features->num_features; - - for (i = 0; i < num_features; i++) { - if (features[i] == id) - return true; - } - - return false; -} - -void dss_feat_get_reg_field(enum dss_feat_reg_field id, u8 *start, u8 *end) -{ - if (id >= omap_current_dss_features->num_reg_fields) - BUG(); - - *start = omap_current_dss_features->reg_fields[id].start; - *end = omap_current_dss_features->reg_fields[id].end; -} - -void dss_features_init(enum omapdss_version version) -{ - switch (version) { - case OMAPDSS_VER_OMAP24xx: - omap_current_dss_features = &omap2_dss_features; - break; - - case OMAPDSS_VER_OMAP34xx_ES1: - case OMAPDSS_VER_OMAP34xx_ES3: - omap_current_dss_features = &omap3430_dss_features; - break; - - case OMAPDSS_VER_OMAP3630: - omap_current_dss_features = &omap3630_dss_features; - break; - - case OMAPDSS_VER_OMAP4430_ES1: - omap_current_dss_features = &omap4430_es1_0_dss_features; - break; - - case OMAPDSS_VER_OMAP4430_ES2: - omap_current_dss_features = &omap4430_es2_0_1_2_dss_features; - break; - - case OMAPDSS_VER_OMAP4: - omap_current_dss_features = &omap4_dss_features; - break; - - case OMAPDSS_VER_OMAP5: - case OMAPDSS_VER_DRA7xx: - omap_current_dss_features = &omap5_dss_features; - break; - - case OMAPDSS_VER_AM35xx: - omap_current_dss_features = &am35xx_dss_features; - break; - - case OMAPDSS_VER_AM43xx: - omap_current_dss_features = &am43xx_dss_features; - break; - - default: - DSSWARN("Unsupported OMAP version"); - break; - } -} diff --git a/drivers/gpu/drm/omapdrm/dss/dss_features.h b/drivers/gpu/drm/omapdrm/dss/dss_features.h deleted file mode 100644 index c36436d27ff5..000000000000 --- a/drivers/gpu/drm/omapdrm/dss/dss_features.h +++ /dev/null @@ -1,109 +0,0 @@ -/* - * linux/drivers/video/omap2/dss/dss_features.h - * - * Copyright (C) 2010 Texas Instruments - * Author: Archit Taneja <archit@ti.com> - * - * This program is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 as published by - * the Free Software Foundation. - * - * 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. - * - * You should have received a copy of the GNU General Public License along with - * this program. If not, see <http://www.gnu.org/licenses/>. - */ - -#ifndef __OMAP2_DSS_FEATURES_H -#define __OMAP2_DSS_FEATURES_H - -#define MAX_DSS_MANAGERS 4 -#define MAX_DSS_OVERLAYS 4 -#define MAX_DSS_LCD_MANAGERS 3 -#define MAX_NUM_DSI 2 - -/* DSS has feature id */ -enum dss_feat_id { - FEAT_LCDENABLEPOL, - FEAT_LCDENABLESIGNAL, - FEAT_PCKFREEENABLE, - FEAT_FUNCGATED, - FEAT_MGR_LCD2, - FEAT_MGR_LCD3, - FEAT_LINEBUFFERSPLIT, - FEAT_ROWREPEATENABLE, - FEAT_RESIZECONF, - /* Independent core clk divider */ - FEAT_CORE_CLK_DIV, - FEAT_LCD_CLK_SRC, - /* DSI-PLL power command 0x3 is not working */ - FEAT_DSI_PLL_PWR_BUG, - FEAT_DSI_DCS_CMD_CONFIG_VC, - FEAT_DSI_VC_OCP_WIDTH, - FEAT_DSI_REVERSE_TXCLKESC, - FEAT_DSI_GNQ, - FEAT_DPI_USES_VDDS_DSI, - FEAT_HDMI_CTS_SWMODE, - FEAT_HDMI_AUDIO_USE_MCLK, - FEAT_HANDLE_UV_SEPARATE, - FEAT_ATTR2, - FEAT_VENC_REQUIRES_TV_DAC_CLK, - FEAT_CPR, - FEAT_PRELOAD, - FEAT_FIR_COEF_V, - FEAT_ALPHA_FIXED_ZORDER, - FEAT_ALPHA_FREE_ZORDER, - FEAT_FIFO_MERGE, - /* An unknown HW bug causing the normal FIFO thresholds not to work */ - FEAT_OMAP3_DSI_FIFO_BUG, - FEAT_BURST_2D, - FEAT_DSI_PHY_DCC, - FEAT_MFLAG, -}; - -/* DSS register field id */ -enum dss_feat_reg_field { - FEAT_REG_FIRHINC, - FEAT_REG_FIRVINC, - FEAT_REG_FIFOHIGHTHRESHOLD, - FEAT_REG_FIFOLOWTHRESHOLD, - FEAT_REG_FIFOSIZE, - FEAT_REG_HORIZONTALACCU, - FEAT_REG_VERTICALACCU, - FEAT_REG_DISPC_CLK_SWITCH, -}; - -enum dss_range_param { - FEAT_PARAM_DSS_FCK, - FEAT_PARAM_DSS_PCD, - FEAT_PARAM_DSIPLL_LPDIV, - FEAT_PARAM_DSI_FCK, - FEAT_PARAM_DOWNSCALE, - FEAT_PARAM_LINEWIDTH, -}; - -/* DSS Feature Functions */ -unsigned long dss_feat_get_param_min(enum dss_range_param param); -unsigned long dss_feat_get_param_max(enum dss_range_param param); -enum omap_overlay_caps dss_feat_get_overlay_caps(enum omap_plane_id plane); -bool dss_feat_color_mode_supported(enum omap_plane_id plane, - u32 fourcc); - -u32 dss_feat_get_buffer_size_unit(void); /* in bytes */ -u32 dss_feat_get_burst_size_unit(void); /* in bytes */ - -bool dss_has_feature(enum dss_feat_id id); -void dss_feat_get_reg_field(enum dss_feat_reg_field id, u8 *start, u8 *end); -void dss_features_init(enum omapdss_version version); - -enum omap_display_type dss_feat_get_supported_displays(enum omap_channel channel); -enum omap_dss_output_id dss_feat_get_supported_outputs(enum omap_channel channel); - -int dss_feat_get_num_mgrs(void); -int dss_feat_get_num_ovls(void); -const u32 *dss_feat_get_supported_color_modes(enum omap_plane_id plane); - -#endif diff --git a/drivers/gpu/drm/omapdrm/dss/hdmi.h b/drivers/gpu/drm/omapdrm/dss/hdmi.h index fb6cccd02374..a820b394af09 100644 --- a/drivers/gpu/drm/omapdrm/dss/hdmi.h +++ b/drivers/gpu/drm/omapdrm/dss/hdmi.h @@ -234,6 +234,7 @@ struct hdmi_core_audio_config { struct hdmi_wp_data { void __iomem *base; phys_addr_t phys_base; + unsigned int version; }; struct hdmi_pll_data { @@ -245,15 +246,24 @@ struct hdmi_pll_data { struct hdmi_wp_data *wp; }; +struct hdmi_phy_features { + bool bist_ctrl; + bool ldo_voltage; + unsigned long max_phy; +}; + struct hdmi_phy_data { void __iomem *base; + const struct hdmi_phy_features *features; u8 lane_function[4]; u8 lane_polarity[4]; }; struct hdmi_core_data { void __iomem *base; + bool cts_swmode; + bool audio_use_mclk; }; static inline void hdmi_write_reg(void __iomem *base_addr, const u32 idx, @@ -303,7 +313,8 @@ void hdmi_wp_video_config_timing(struct hdmi_wp_data *wp, struct videomode *vm); void hdmi_wp_init_vid_fmt_timings(struct hdmi_video_format *video_fmt, struct videomode *vm, struct hdmi_config *param); -int hdmi_wp_init(struct platform_device *pdev, struct hdmi_wp_data *wp); +int hdmi_wp_init(struct platform_device *pdev, struct hdmi_wp_data *wp, + unsigned int version); phys_addr_t hdmi_wp_get_audio_dma_addr(struct hdmi_wp_data *wp); /* HDMI PLL funcs */ @@ -316,7 +327,8 @@ void hdmi_pll_uninit(struct hdmi_pll_data *hpll); int hdmi_phy_configure(struct hdmi_phy_data *phy, unsigned long hfbitclk, unsigned long lfbitclk); void hdmi_phy_dump(struct hdmi_phy_data *phy, struct seq_file *s); -int hdmi_phy_init(struct platform_device *pdev, struct hdmi_phy_data *phy); +int hdmi_phy_init(struct platform_device *pdev, struct hdmi_phy_data *phy, + unsigned int version); int hdmi_phy_parse_lanes(struct hdmi_phy_data *phy, const u32 *lanes); /* HDMI common funcs */ diff --git a/drivers/gpu/drm/omapdrm/dss/hdmi4.c b/drivers/gpu/drm/omapdrm/dss/hdmi4.c index 284b4942b9ac..f169348da377 100644 --- a/drivers/gpu/drm/omapdrm/dss/hdmi4.c +++ b/drivers/gpu/drm/omapdrm/dss/hdmi4.c @@ -40,7 +40,6 @@ #include "omapdss.h" #include "hdmi4_core.h" #include "dss.h" -#include "dss_features.h" #include "hdmi.h" static struct omap_hdmi hdmi; @@ -668,7 +667,7 @@ static int hdmi_audio_register(struct device *dev) { struct omap_hdmi_audio_pdata pdata = { .dev = dev, - .dss_version = omapdss_get_version(), + .version = 4, .audio_dma_addr = hdmi_wp_get_audio_dma_addr(&hdmi.wp), .ops = &hdmi_audio_ops, }; @@ -700,7 +699,7 @@ static int hdmi4_bind(struct device *dev, struct device *master, void *data) if (r) return r; - r = hdmi_wp_init(pdev, &hdmi.wp); + r = hdmi_wp_init(pdev, &hdmi.wp, 4); if (r) return r; @@ -708,7 +707,7 @@ static int hdmi4_bind(struct device *dev, struct device *master, void *data) if (r) return r; - r = hdmi_phy_init(pdev, &hdmi.phy); + r = hdmi_phy_init(pdev, &hdmi.phy, 4); if (r) goto err; diff --git a/drivers/gpu/drm/omapdrm/dss/hdmi4_core.c b/drivers/gpu/drm/omapdrm/dss/hdmi4_core.c index ed6001613405..365cf07daa01 100644 --- a/drivers/gpu/drm/omapdrm/dss/hdmi4_core.c +++ b/drivers/gpu/drm/omapdrm/dss/hdmi4_core.c @@ -31,11 +31,11 @@ #include <linux/platform_device.h> #include <linux/string.h> #include <linux/seq_file.h> +#include <linux/sys_soc.h> #include <sound/asound.h> #include <sound/asoundef.h> #include "hdmi4_core.h" -#include "dss_features.h" #define HDMI_CORE_AV 0x500 @@ -757,10 +757,10 @@ int hdmi4_audio_config(struct hdmi_core_data *core, struct hdmi_wp_data *wp, /* Audio clock regeneration settings */ acore.n = n; acore.cts = cts; - if (dss_has_feature(FEAT_HDMI_CTS_SWMODE)) { + if (core->cts_swmode) { acore.aud_par_busclk = 0; acore.cts_mode = HDMI_AUDIO_CTS_MODE_SW; - acore.use_mclk = dss_has_feature(FEAT_HDMI_AUDIO_USE_MCLK); + acore.use_mclk = core->audio_use_mclk; } else { acore.aud_par_busclk = (((128 * 31) - 1) << 8); acore.cts_mode = HDMI_AUDIO_CTS_MODE_HW; @@ -884,10 +884,42 @@ void hdmi4_audio_stop(struct hdmi_core_data *core, struct hdmi_wp_data *wp) hdmi_wp_audio_core_req_enable(wp, false); } +struct hdmi4_features { + bool cts_swmode; + bool audio_use_mclk; +}; + +static const struct hdmi4_features hdmi4_es1_features = { + .cts_swmode = false, + .audio_use_mclk = false, +}; + +static const struct hdmi4_features hdmi4_es2_features = { + .cts_swmode = true, + .audio_use_mclk = false, +}; + +static const struct hdmi4_features hdmi4_es3_features = { + .cts_swmode = true, + .audio_use_mclk = true, +}; + +static const struct soc_device_attribute hdmi4_soc_devices[] = { + { .family = "OMAP4", .revision = "ES1.?", .data = &hdmi4_es1_features }, + { .family = "OMAP4", .revision = "ES2.?", .data = &hdmi4_es2_features }, + { .family = "OMAP4", .data = &hdmi4_es3_features }, + { /* sentinel */ } +}; + int hdmi4_core_init(struct platform_device *pdev, struct hdmi_core_data *core) { + const struct hdmi4_features *features; struct resource *res; + features = soc_device_match(hdmi4_soc_devices)->data; + core->cts_swmode = features->cts_swmode; + core->audio_use_mclk = features->audio_use_mclk; + res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "core"); core->base = devm_ioremap_resource(&pdev->dev, res); if (IS_ERR(core->base)) diff --git a/drivers/gpu/drm/omapdrm/dss/hdmi5.c b/drivers/gpu/drm/omapdrm/dss/hdmi5.c index 441e1999d86a..b3221ca5bcd8 100644 --- a/drivers/gpu/drm/omapdrm/dss/hdmi5.c +++ b/drivers/gpu/drm/omapdrm/dss/hdmi5.c @@ -45,7 +45,6 @@ #include "omapdss.h" #include "hdmi5_core.h" #include "dss.h" -#include "dss_features.h" static struct omap_hdmi hdmi; @@ -695,7 +694,7 @@ static int hdmi_audio_register(struct device *dev) { struct omap_hdmi_audio_pdata pdata = { .dev = dev, - .dss_version = omapdss_get_version(), + .version = 5, .audio_dma_addr = hdmi_wp_get_audio_dma_addr(&hdmi.wp), .ops = &hdmi_audio_ops, }; @@ -732,7 +731,7 @@ static int hdmi5_bind(struct device *dev, struct device *master, void *data) if (r) return r; - r = hdmi_wp_init(pdev, &hdmi.wp); + r = hdmi_wp_init(pdev, &hdmi.wp, 5); if (r) return r; @@ -740,7 +739,7 @@ static int hdmi5_bind(struct device *dev, struct device *master, void *data) if (r) return r; - r = hdmi_phy_init(pdev, &hdmi.phy); + r = hdmi_phy_init(pdev, &hdmi.phy, 5); if (r) goto err; diff --git a/drivers/gpu/drm/omapdrm/dss/hdmi_phy.c b/drivers/gpu/drm/omapdrm/dss/hdmi_phy.c index fb5e4c724b4b..a156292b1820 100644 --- a/drivers/gpu/drm/omapdrm/dss/hdmi_phy.c +++ b/drivers/gpu/drm/omapdrm/dss/hdmi_phy.c @@ -19,14 +19,6 @@ #include "dss.h" #include "hdmi.h" -struct hdmi_phy_features { - bool bist_ctrl; - bool ldo_voltage; - unsigned long max_phy; -}; - -static const struct hdmi_phy_features *phy_feat; - void hdmi_phy_dump(struct hdmi_phy_data *phy, struct seq_file *s) { #define DUMPPHY(r) seq_printf(s, "%-35s %08x\n", #r,\ @@ -36,7 +28,7 @@ void hdmi_phy_dump(struct hdmi_phy_data *phy, struct seq_file *s) DUMPPHY(HDMI_TXPHY_DIGITAL_CTRL); DUMPPHY(HDMI_TXPHY_POWER_CTRL); DUMPPHY(HDMI_TXPHY_PAD_CFG_CTRL); - if (phy_feat->bist_ctrl) + if (phy->features->bist_ctrl) DUMPPHY(HDMI_TXPHY_BIST_CONTROL); } @@ -146,7 +138,7 @@ int hdmi_phy_configure(struct hdmi_phy_data *phy, unsigned long hfbitclk, * In OMAP5+, the HFBITCLK must be divided by 2 before issuing the * HDMI_PHYPWRCMD_LDOON command. */ - if (phy_feat->bist_ctrl) + if (phy->features->bist_ctrl) REG_FLD_MOD(phy->base, HDMI_TXPHY_BIST_CONTROL, 1, 11, 11); /* @@ -155,7 +147,7 @@ int hdmi_phy_configure(struct hdmi_phy_data *phy, unsigned long hfbitclk, */ if (hfbitclk != lfbitclk) freqout = 0; - else if (hfbitclk / 10 < phy_feat->max_phy) + else if (hfbitclk / 10 < phy->features->max_phy) freqout = 1; else freqout = 2; @@ -170,7 +162,7 @@ int hdmi_phy_configure(struct hdmi_phy_data *phy, unsigned long hfbitclk, hdmi_write_reg(phy->base, HDMI_TXPHY_DIGITAL_CTRL, 0xF0000000); /* Setup max LDO voltage */ - if (phy_feat->ldo_voltage) + if (phy->features->ldo_voltage) REG_FLD_MOD(phy->base, HDMI_TXPHY_POWER_CTRL, 0xB, 3, 0); hdmi_phy_configure_lanes(phy); @@ -190,47 +182,15 @@ static const struct hdmi_phy_features omap54xx_phy_feats = { .max_phy = 186000000, }; -static int hdmi_phy_init_features(struct platform_device *pdev) -{ - struct hdmi_phy_features *dst; - const struct hdmi_phy_features *src; - - dst = devm_kzalloc(&pdev->dev, sizeof(*dst), GFP_KERNEL); - if (!dst) { - dev_err(&pdev->dev, "Failed to allocate HDMI PHY Features\n"); - return -ENOMEM; - } - - switch (omapdss_get_version()) { - case OMAPDSS_VER_OMAP4430_ES1: - case OMAPDSS_VER_OMAP4430_ES2: - case OMAPDSS_VER_OMAP4: - src = &omap44xx_phy_feats; - break; - - case OMAPDSS_VER_OMAP5: - case OMAPDSS_VER_DRA7xx: - src = &omap54xx_phy_feats; - break; - - default: - return -ENODEV; - } - - memcpy(dst, src, sizeof(*dst)); - phy_feat = dst; - - return 0; -} - -int hdmi_phy_init(struct platform_device *pdev, struct hdmi_phy_data *phy) +int hdmi_phy_init(struct platform_device *pdev, struct hdmi_phy_data *phy, + unsigned int version) { - int r; struct resource *res; - r = hdmi_phy_init_features(pdev); - if (r) - return r; + if (version == 4) + phy->features = &omap44xx_phy_feats; + else + phy->features = &omap54xx_phy_feats; res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "phy"); phy->base = devm_ioremap_resource(&pdev->dev, res); diff --git a/drivers/gpu/drm/omapdrm/dss/hdmi_pll.c b/drivers/gpu/drm/omapdrm/dss/hdmi_pll.c index 46239358655a..55bee81f4dd5 100644 --- a/drivers/gpu/drm/omapdrm/dss/hdmi_pll.c +++ b/drivers/gpu/drm/omapdrm/dss/hdmi_pll.c @@ -71,7 +71,7 @@ static void hdmi_pll_disable(struct dss_pll *dsspll) WARN_ON(r < 0 && r != -ENOSYS); } -static const struct dss_pll_ops dsi_pll_ops = { +static const struct dss_pll_ops hdmi_pll_ops = { .enable = hdmi_pll_enable, .disable = hdmi_pll_disable, .set_config = dss_pll_write_config_type_b, @@ -128,7 +128,8 @@ static const struct dss_pll_hw dss_omap5_hdmi_pll_hw = { .has_refsel = true, }; -static int dsi_init_pll_data(struct platform_device *pdev, struct hdmi_pll_data *hpll) +static int hdmi_init_pll_data(struct platform_device *pdev, + struct hdmi_pll_data *hpll) { struct dss_pll *pll = &hpll->pll; struct clk *clk; @@ -145,23 +146,12 @@ static int dsi_init_pll_data(struct platform_device *pdev, struct hdmi_pll_data pll->base = hpll->base; pll->clkin = clk; - switch (omapdss_get_version()) { - case OMAPDSS_VER_OMAP4430_ES1: - case OMAPDSS_VER_OMAP4430_ES2: - case OMAPDSS_VER_OMAP4: + if (hpll->wp->version == 4) pll->hw = &dss_omap4_hdmi_pll_hw; - break; - - case OMAPDSS_VER_OMAP5: - case OMAPDSS_VER_DRA7xx: + else pll->hw = &dss_omap5_hdmi_pll_hw; - break; - - default: - return -ENODEV; - } - pll->ops = &dsi_pll_ops; + pll->ops = &hdmi_pll_ops; r = dss_pll_register(pll); if (r) @@ -184,7 +174,7 @@ int hdmi_pll_init(struct platform_device *pdev, struct hdmi_pll_data *pll, if (IS_ERR(pll->base)) return PTR_ERR(pll->base); - r = dsi_init_pll_data(pdev, pll); + r = hdmi_init_pll_data(pdev, pll); if (r) { DSSERR("failed to init HDMI PLL\n"); return r; diff --git a/drivers/gpu/drm/omapdrm/dss/hdmi_wp.c b/drivers/gpu/drm/omapdrm/dss/hdmi_wp.c index ab129df2e310..88034fbe0e9f 100644 --- a/drivers/gpu/drm/omapdrm/dss/hdmi_wp.c +++ b/drivers/gpu/drm/omapdrm/dss/hdmi_wp.c @@ -178,9 +178,7 @@ void hdmi_wp_video_config_timing(struct hdmi_wp_data *wp, * However, we don't support OMAP5 ES1 at all, so we can just check for * OMAP4 here. */ - if (omapdss_get_version() == OMAPDSS_VER_OMAP4430_ES1 || - omapdss_get_version() == OMAPDSS_VER_OMAP4430_ES2 || - omapdss_get_version() == OMAPDSS_VER_OMAP4) + if (wp->version == 4) hsync_len_offset = 0; timing_h |= FLD_VAL(vm->hback_porch, 31, 20); @@ -235,9 +233,7 @@ void hdmi_wp_audio_config_format(struct hdmi_wp_data *wp, DSSDBG("Enter hdmi_wp_audio_config_format\n"); r = hdmi_read_reg(wp->base, HDMI_WP_AUDIO_CFG); - if (omapdss_get_version() == OMAPDSS_VER_OMAP4430_ES1 || - omapdss_get_version() == OMAPDSS_VER_OMAP4430_ES2 || - omapdss_get_version() == OMAPDSS_VER_OMAP4) { + if (wp->version == 4) { r = FLD_MOD(r, aud_fmt->stereo_channels, 26, 24); r = FLD_MOD(r, aud_fmt->active_chnnls_msk, 23, 16); } @@ -282,7 +278,8 @@ int hdmi_wp_audio_core_req_enable(struct hdmi_wp_data *wp, bool enable) return 0; } -int hdmi_wp_init(struct platform_device *pdev, struct hdmi_wp_data *wp) +int hdmi_wp_init(struct platform_device *pdev, struct hdmi_wp_data *wp, + unsigned int version) { struct resource *res; @@ -292,6 +289,7 @@ int hdmi_wp_init(struct platform_device *pdev, struct hdmi_wp_data *wp) return PTR_ERR(wp->base); wp->phys_base = res->start; + wp->version = version; return 0; } diff --git a/drivers/gpu/drm/omapdrm/dss/omapdss.h b/drivers/gpu/drm/omapdrm/dss/omapdss.h index 85953a0bc7c2..47a331670963 100644 --- a/drivers/gpu/drm/omapdrm/dss/omapdss.h +++ b/drivers/gpu/drm/omapdrm/dss/omapdss.h @@ -25,6 +25,7 @@ #include <video/videomode.h> #include <linux/platform_data/omapdss.h> #include <uapi/drm/drm_mode.h> +#include <drm/drm_crtc.h> #define DISPC_IRQ_FRAMEDONE (1 << 0) #define DISPC_IRQ_VSYNC (1 << 1) @@ -241,13 +242,6 @@ struct omap_dss_dsi_config { enum omap_dss_dsi_trans_mode trans_mode; }; -/* Hardcoded videomodes for tv. Venc only uses these to - * identify the mode, and does not actually use the configs - * itself. However, the configs should be something that - * a normal monitor can also show */ -extern const struct videomode omap_dss_pal_vm; -extern const struct videomode omap_dss_ntsc_vm; - struct omap_dss_cpr_coefs { s16 rr, rg, rb; s16 gr, gg, gb; @@ -403,6 +397,14 @@ struct omapdss_hdmi_ops { int (*read_edid)(struct omap_dss_device *dssdev, u8 *buf, int len); bool (*detect)(struct omap_dss_device *dssdev); + int (*register_hpd_cb)(struct omap_dss_device *dssdev, + void (*cb)(void *cb_data, + enum drm_connector_status status), + void *cb_data); + void (*unregister_hpd_cb)(struct omap_dss_device *dssdev); + void (*enable_hpd)(struct omap_dss_device *dssdev); + void (*disable_hpd)(struct omap_dss_device *dssdev); + int (*set_hdmi_mode)(struct omap_dss_device *dssdev, bool hdmi_mode); int (*set_infoframe)(struct omap_dss_device *dssdev, const struct hdmi_avi_infoframe *avi); @@ -567,12 +569,19 @@ struct omap_dss_driver { int (*read_edid)(struct omap_dss_device *dssdev, u8 *buf, int len); bool (*detect)(struct omap_dss_device *dssdev); + int (*register_hpd_cb)(struct omap_dss_device *dssdev, + void (*cb)(void *cb_data, + enum drm_connector_status status), + void *cb_data); + void (*unregister_hpd_cb)(struct omap_dss_device *dssdev); + void (*enable_hpd)(struct omap_dss_device *dssdev); + void (*disable_hpd)(struct omap_dss_device *dssdev); + int (*set_hdmi_mode)(struct omap_dss_device *dssdev, bool hdmi_mode); int (*set_hdmi_infoframe)(struct omap_dss_device *dssdev, const struct hdmi_avi_infoframe *avi); }; -enum omapdss_version omapdss_get_version(void); bool omapdss_is_initialized(void); int omap_dss_register_driver(struct omap_dss_driver *); diff --git a/drivers/gpu/drm/omapdrm/dss/pll.c b/drivers/gpu/drm/omapdrm/dss/pll.c index 5e221302768b..9d9d9d42009b 100644 --- a/drivers/gpu/drm/omapdrm/dss/pll.c +++ b/drivers/gpu/drm/omapdrm/dss/pll.c @@ -215,8 +215,8 @@ bool dss_pll_calc_a(const struct dss_pll *pll, unsigned long clkin, dss_pll_calc_func func, void *data) { const struct dss_pll_hw *hw = pll->hw; - int n, n_min, n_max; - int m, m_min, m_max; + int n, n_start, n_stop, n_inc; + int m, m_start, m_stop, m_inc; unsigned long fint, clkdco; unsigned long pll_hw_max; unsigned long fint_hw_min, fint_hw_max; @@ -226,22 +226,33 @@ bool dss_pll_calc_a(const struct dss_pll *pll, unsigned long clkin, fint_hw_min = hw->fint_min; fint_hw_max = hw->fint_max; - n_min = max(DIV_ROUND_UP(clkin, fint_hw_max), 1ul); - n_max = min((unsigned)(clkin / fint_hw_min), hw->n_max); + n_start = max(DIV_ROUND_UP(clkin, fint_hw_max), 1ul); + n_stop = min((unsigned)(clkin / fint_hw_min), hw->n_max); + n_inc = 1; + + if (hw->errata_i886) { + swap(n_start, n_stop); + n_inc = -1; + } pll_max = pll_max ? pll_max : ULONG_MAX; - /* Try to find high N & M to avoid jitter (DRA7 errata i886) */ - for (n = n_max; n >= n_min; --n) { + for (n = n_start; n != n_stop; n += n_inc) { fint = clkin / n; - m_min = max(DIV_ROUND_UP(DIV_ROUND_UP(pll_min, fint), 2), + m_start = max(DIV_ROUND_UP(DIV_ROUND_UP(pll_min, fint), 2), 1ul); - m_max = min3((unsigned)(pll_max / fint / 2), + m_stop = min3((unsigned)(pll_max / fint / 2), (unsigned)(pll_hw_max / fint / 2), hw->m_max); + m_inc = 1; + + if (hw->errata_i886) { + swap(m_start, m_stop); + m_inc = -1; + } - for (m = m_max; m >= m_min; --m) { + for (m = m_start; m != m_stop; m += m_inc) { clkdco = 2 * m * fint; if (func(n, m, fint, clkdco, data)) diff --git a/drivers/gpu/drm/omapdrm/dss/venc.c b/drivers/gpu/drm/omapdrm/dss/venc.c index a6bfb3918b8d..d58da6f32693 100644 --- a/drivers/gpu/drm/omapdrm/dss/venc.c +++ b/drivers/gpu/drm/omapdrm/dss/venc.c @@ -37,10 +37,10 @@ #include <linux/of.h> #include <linux/of_graph.h> #include <linux/component.h> +#include <linux/sys_soc.h> #include "omapdss.h" #include "dss.h" -#include "dss_features.h" /* Venc registers */ #define VENC_REV_ID 0x00 @@ -263,7 +263,13 @@ static const struct venc_config venc_config_pal_bdghi = { .fid_ext_start_y__fid_ext_offset_y = 0x01380005, }; -const struct videomode omap_dss_pal_vm = { +enum venc_videomode { + VENC_MODE_UNKNOWN, + VENC_MODE_PAL, + VENC_MODE_NTSC, +}; + +static const struct videomode omap_dss_pal_vm = { .hactive = 720, .vactive = 574, .pixelclock = 13500000, @@ -279,9 +285,8 @@ const struct videomode omap_dss_pal_vm = { DISPLAY_FLAGS_PIXDATA_POSEDGE | DISPLAY_FLAGS_SYNC_NEGEDGE, }; -EXPORT_SYMBOL(omap_dss_pal_vm); -const struct videomode omap_dss_ntsc_vm = { +static const struct videomode omap_dss_ntsc_vm = { .hactive = 720, .vactive = 482, .pixelclock = 13500000, @@ -297,7 +302,24 @@ const struct videomode omap_dss_ntsc_vm = { DISPLAY_FLAGS_PIXDATA_POSEDGE | DISPLAY_FLAGS_SYNC_NEGEDGE, }; -EXPORT_SYMBOL(omap_dss_ntsc_vm); + +static enum venc_videomode venc_get_videomode(const struct videomode *vm) +{ + if (!(vm->flags & DISPLAY_FLAGS_INTERLACED)) + return VENC_MODE_UNKNOWN; + + if (vm->pixelclock == omap_dss_pal_vm.pixelclock && + vm->hactive == omap_dss_pal_vm.hactive && + vm->vactive == omap_dss_pal_vm.vactive) + return VENC_MODE_PAL; + + if (vm->pixelclock == omap_dss_ntsc_vm.pixelclock && + vm->hactive == omap_dss_ntsc_vm.hactive && + vm->vactive == omap_dss_ntsc_vm.vactive) + return VENC_MODE_NTSC; + + return VENC_MODE_UNKNOWN; +} static struct { struct platform_device *pdev; @@ -311,6 +333,7 @@ static struct { struct videomode vm; enum omap_dss_venc_type type; bool invert_polarity; + bool requires_tv_dac_clk; struct omap_dss_device output; } venc; @@ -424,14 +447,14 @@ static void venc_runtime_put(void) static const struct venc_config *venc_timings_to_config(struct videomode *vm) { - if (memcmp(&omap_dss_pal_vm, vm, sizeof(*vm)) == 0) + switch (venc_get_videomode(vm)) { + default: + WARN_ON_ONCE(1); + case VENC_MODE_PAL: return &venc_config_pal_trm; - - if (memcmp(&omap_dss_ntsc_vm, vm, sizeof(*vm)) == 0) + case VENC_MODE_NTSC: return &venc_config_ntsc_trm; - - BUG(); - return NULL; + } } static int venc_power_on(struct omap_dss_device *dssdev) @@ -542,15 +565,28 @@ static void venc_display_disable(struct omap_dss_device *dssdev) static void venc_set_timings(struct omap_dss_device *dssdev, struct videomode *vm) { + struct videomode actual_vm; + DSSDBG("venc_set_timings\n"); mutex_lock(&venc.venc_lock); + switch (venc_get_videomode(vm)) { + default: + WARN_ON_ONCE(1); + case VENC_MODE_PAL: + actual_vm = omap_dss_pal_vm; + break; + case VENC_MODE_NTSC: + actual_vm = omap_dss_ntsc_vm; + break; + } + /* Reset WSS data when the TV standard changes. */ - if (memcmp(&venc.vm, vm, sizeof(*vm))) + if (memcmp(&venc.vm, &actual_vm, sizeof(actual_vm))) venc.wss_data = 0; - venc.vm = *vm; + venc.vm = actual_vm; dispc_set_tv_pclk(13500000); @@ -562,13 +598,13 @@ static int venc_check_timings(struct omap_dss_device *dssdev, { DSSDBG("venc_check_timings\n"); - if (memcmp(&omap_dss_pal_vm, vm, sizeof(*vm)) == 0) - return 0; - - if (memcmp(&omap_dss_ntsc_vm, vm, sizeof(*vm)) == 0) + switch (venc_get_videomode(vm)) { + case VENC_MODE_PAL: + case VENC_MODE_NTSC: return 0; - - return -EINVAL; + default: + return -EINVAL; + } } static void venc_get_timings(struct omap_dss_device *dssdev, @@ -693,7 +729,7 @@ static int venc_get_clocks(struct platform_device *pdev) { struct clk *clk; - if (dss_has_feature(FEAT_VENC_REQUIRES_TV_DAC_CLK)) { + if (venc.requires_tv_dac_clk) { clk = devm_clk_get(&pdev->dev, "tv_dac_clk"); if (IS_ERR(clk)) { DSSERR("can't get tv_dac_clk\n"); @@ -828,6 +864,12 @@ err: } /* VENC HW IP initialisation */ +static const struct soc_device_attribute venc_soc_devices[] = { + { .machine = "OMAP3[45]*" }, + { .machine = "AM35*" }, + { /* sentinel */ } +}; + static int venc_bind(struct device *dev, struct device *master, void *data) { struct platform_device *pdev = to_platform_device(dev); @@ -837,6 +879,10 @@ static int venc_bind(struct device *dev, struct device *master, void *data) venc.pdev = pdev; + /* The OMAP34xx, OMAP35xx and AM35xx VENC require the TV DAC clock. */ + if (soc_device_match(venc_soc_devices)) + venc.requires_tv_dac_clk = true; + mutex_init(&venc.venc_lock); venc.wss_data = 0; diff --git a/drivers/gpu/drm/omapdrm/dss/video-pll.c b/drivers/gpu/drm/omapdrm/dss/video-pll.c index fbd1263a29a4..38a239cc5e04 100644 --- a/drivers/gpu/drm/omapdrm/dss/video-pll.c +++ b/drivers/gpu/drm/omapdrm/dss/video-pll.c @@ -19,7 +19,6 @@ #include "omapdss.h" #include "dss.h" -#include "dss_features.h" struct dss_video_pll { struct dss_pll pll; @@ -131,6 +130,8 @@ static const struct dss_pll_hw dss_dra7_video_pll_hw = { .mX_lsb[3] = 5, .has_refsel = true, + + .errata_i886 = true, }; struct dss_pll *dss_video_pll_init(struct platform_device *pdev, int id, |

