diff options
author | Linus Torvalds <torvalds@linux-foundation.org> | 2016-01-18 22:58:31 +0300 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2016-01-18 22:58:31 +0300 |
commit | d43fb9f3c5dff281dd72bea5cd2e91386fdc33a8 (patch) | |
tree | 4f3f2b00629b2df1ce4f02684689ccaa4b434854 /drivers/video/fbdev | |
parent | 5807fcaa9bf7dd87241df739161c119cf78a6bc4 (diff) | |
parent | 6f6abd360603aff043352db90c28748c8c46560e (diff) | |
download | linux-d43fb9f3c5dff281dd72bea5cd2e91386fdc33a8.tar.xz |
Merge tag 'fbdev-4.5' of git://git.kernel.org/pub/scm/linux/kernel/git/tomba/linux
Pull fbdev updates from Tomi Valkeinen:
"Summary:
- pxafb: device-tree support
- An unsafe kernel parameter 'lockless_register_fb' for debugging
problems happening while inside the console lock
- Small miscellaneous fixes & cleanups
- omapdss: add writeback support functions
- Separation of omapfb and omapdrm (see below)
About the separation of omapfb and omapdrm, see
http://permalink.gmane.org/gmane.comp.video.dri.devel/143151
for longer story. The short version:
omapfb and omapdrm have shared low level drivers (omapdss and panel
drivers), making further development of omapdrm difficult. After
these patches omapfb and omapdrm have their own versions of the
drivers, which are more or less direct copies for now but will diverge
soon.
This also means that omapfb (everything under drivers/video/fbdev/omap2/)
is now in maintenance mode, and all new development will be done for
omapdrm (drivers/gpu/drm/omapdrm/)"
* tag 'fbdev-4.5' of git://git.kernel.org/pub/scm/linux/kernel/git/tomba/linux: (49 commits)
video: fbdev: pxafb: fix out of memory error path
drm/omap: make omapdrm select OMAP2_DSS
drm/omap: move omapdss & displays under omapdrm
omapfb: move vrfb into omapfb
omapfb: take omapfb's private omapdss into use
omapfb/displays: change CONFIG_DISPLAY_* to CONFIG_FB_OMAP2_*
omapfb/dss: change CONFIG_OMAP* to CONFIG_FB_OMAP*
omapdss: remove CONFIG_OMAP2_DSS_VENC from omapdss.h
omapfb: copy omapdss & displays for omapfb
omapfb: allow compilation only if DRM_OMAP is disabled
fbdev: omap2: panel-dpi: simplify gpio setting
fbdev: omap2: panel-dpi: in .disable first disable backlight then display
OMAPDSS: DSS: fix a warning message
video: omapdss: delete unneeded of_node_put
OMAPDSS: DISPC: Remove boolean comparisons
OMAPDSS: DSI: cleanup DSI_IRQ_ERROR_MASK define
OMAPDSS: remove extra out == NULL checks
OMAPDSS: change internal dispc functions to static
OMAPDSS: make a two dss feat funcs internal to omapdss
OMAPDSS: remove extra EXPORT_SYMBOLs
...
Diffstat (limited to 'drivers/video/fbdev')
-rw-r--r-- | drivers/video/fbdev/Kconfig | 17 | ||||
-rw-r--r-- | drivers/video/fbdev/Makefile | 1 | ||||
-rw-r--r-- | drivers/video/fbdev/auo_k190x.c | 11 | ||||
-rw-r--r-- | drivers/video/fbdev/core/Makefile | 2 | ||||
-rw-r--r-- | drivers/video/fbdev/core/fbmem.c | 14 | ||||
-rw-r--r-- | drivers/video/fbdev/geode/display_gx1.c | 2 | ||||
-rw-r--r-- | drivers/video/fbdev/geode/display_gx1.h | 2 | ||||
-rw-r--r-- | drivers/video/fbdev/geode/geodefb.h | 4 | ||||
-rw-r--r-- | drivers/video/fbdev/geode/video_cs5530.c | 2 | ||||
-rw-r--r-- | drivers/video/fbdev/geode/video_cs5530.h | 2 | ||||
-rw-r--r-- | drivers/video/fbdev/i740fb.c | 8 | ||||
-rw-r--r-- | drivers/video/fbdev/omap2/Kconfig | 5 | ||||
-rw-r--r-- | drivers/video/fbdev/omap2/Makefile | 6 | ||||
-rw-r--r-- | drivers/video/fbdev/omap2/displays-new/Makefile | 14 | ||||
-rw-r--r-- | drivers/video/fbdev/omap2/dss/Makefile | 18 | ||||
-rw-r--r-- | drivers/video/fbdev/omap2/omapfb/Kconfig | 14 | ||||
-rw-r--r-- | drivers/video/fbdev/omap2/omapfb/Makefile | 3 | ||||
-rw-r--r-- | drivers/video/fbdev/omap2/omapfb/displays/Kconfig (renamed from drivers/video/fbdev/omap2/displays-new/Kconfig) | 32 | ||||
-rw-r--r-- | drivers/video/fbdev/omap2/omapfb/displays/Makefile | 14 | ||||
-rw-r--r-- | drivers/video/fbdev/omap2/omapfb/displays/connector-analog-tv.c (renamed from drivers/video/fbdev/omap2/displays-new/connector-analog-tv.c) | 0 | ||||
-rw-r--r-- | drivers/video/fbdev/omap2/omapfb/displays/connector-dvi.c (renamed from drivers/video/fbdev/omap2/displays-new/connector-dvi.c) | 0 | ||||
-rw-r--r-- | drivers/video/fbdev/omap2/omapfb/displays/connector-hdmi.c (renamed from drivers/video/fbdev/omap2/displays-new/connector-hdmi.c) | 0 | ||||
-rw-r--r-- | drivers/video/fbdev/omap2/omapfb/displays/encoder-opa362.c (renamed from drivers/video/fbdev/omap2/displays-new/encoder-opa362.c) | 0 | ||||
-rw-r--r-- | drivers/video/fbdev/omap2/omapfb/displays/encoder-tfp410.c (renamed from drivers/video/fbdev/omap2/displays-new/encoder-tfp410.c) | 0 | ||||
-rw-r--r-- | drivers/video/fbdev/omap2/omapfb/displays/encoder-tpd12s015.c (renamed from drivers/video/fbdev/omap2/displays-new/encoder-tpd12s015.c) | 117 | ||||
-rw-r--r-- | drivers/video/fbdev/omap2/omapfb/displays/panel-dpi.c (renamed from drivers/video/fbdev/omap2/displays-new/panel-dpi.c) | 8 | ||||
-rw-r--r-- | drivers/video/fbdev/omap2/omapfb/displays/panel-dsi-cm.c (renamed from drivers/video/fbdev/omap2/displays-new/panel-dsi-cm.c) | 0 | ||||
-rw-r--r-- | drivers/video/fbdev/omap2/omapfb/displays/panel-lgphilips-lb035q02.c (renamed from drivers/video/fbdev/omap2/displays-new/panel-lgphilips-lb035q02.c) | 0 | ||||
-rw-r--r-- | drivers/video/fbdev/omap2/omapfb/displays/panel-nec-nl8048hl11.c (renamed from drivers/video/fbdev/omap2/displays-new/panel-nec-nl8048hl11.c) | 0 | ||||
-rw-r--r-- | drivers/video/fbdev/omap2/omapfb/displays/panel-sharp-ls037v7dw01.c (renamed from drivers/video/fbdev/omap2/displays-new/panel-sharp-ls037v7dw01.c) | 0 | ||||
-rw-r--r-- | drivers/video/fbdev/omap2/omapfb/displays/panel-sony-acx565akm.c (renamed from drivers/video/fbdev/omap2/displays-new/panel-sony-acx565akm.c) | 0 | ||||
-rw-r--r-- | drivers/video/fbdev/omap2/omapfb/displays/panel-tpo-td028ttec1.c (renamed from drivers/video/fbdev/omap2/displays-new/panel-tpo-td028ttec1.c) | 0 | ||||
-rw-r--r-- | drivers/video/fbdev/omap2/omapfb/displays/panel-tpo-td043mtea1.c (renamed from drivers/video/fbdev/omap2/displays-new/panel-tpo-td043mtea1.c) | 0 | ||||
-rw-r--r-- | drivers/video/fbdev/omap2/omapfb/dss/Kconfig (renamed from drivers/video/fbdev/omap2/dss/Kconfig) | 46 | ||||
-rw-r--r-- | drivers/video/fbdev/omap2/omapfb/dss/Makefile | 18 | ||||
-rw-r--r-- | drivers/video/fbdev/omap2/omapfb/dss/apply.c (renamed from drivers/video/fbdev/omap2/dss/apply.c) | 0 | ||||
-rw-r--r-- | drivers/video/fbdev/omap2/omapfb/dss/core.c (renamed from drivers/video/fbdev/omap2/dss/core.c) | 34 | ||||
-rw-r--r-- | drivers/video/fbdev/omap2/omapfb/dss/dispc-compat.c (renamed from drivers/video/fbdev/omap2/dss/dispc-compat.c) | 14 | ||||
-rw-r--r-- | drivers/video/fbdev/omap2/omapfb/dss/dispc-compat.h (renamed from drivers/video/fbdev/omap2/dss/dispc-compat.h) | 0 | ||||
-rw-r--r-- | drivers/video/fbdev/omap2/omapfb/dss/dispc.c (renamed from drivers/video/fbdev/omap2/dss/dispc.c) | 167 | ||||
-rw-r--r-- | drivers/video/fbdev/omap2/omapfb/dss/dispc.h (renamed from drivers/video/fbdev/omap2/dss/dispc.h) | 2 | ||||
-rw-r--r-- | drivers/video/fbdev/omap2/omapfb/dss/dispc_coefs.c (renamed from drivers/video/fbdev/omap2/dss/dispc_coefs.c) | 0 | ||||
-rw-r--r-- | drivers/video/fbdev/omap2/omapfb/dss/display-sysfs.c (renamed from drivers/video/fbdev/omap2/dss/display-sysfs.c) | 2 | ||||
-rw-r--r-- | drivers/video/fbdev/omap2/omapfb/dss/display.c (renamed from drivers/video/fbdev/omap2/dss/display.c) | 0 | ||||
-rw-r--r-- | drivers/video/fbdev/omap2/omapfb/dss/dpi.c (renamed from drivers/video/fbdev/omap2/dss/dpi.c) | 2 | ||||
-rw-r--r-- | drivers/video/fbdev/omap2/omapfb/dss/dsi.c (renamed from drivers/video/fbdev/omap2/dss/dsi.c) | 14 | ||||
-rw-r--r-- | drivers/video/fbdev/omap2/omapfb/dss/dss-of.c (renamed from drivers/video/fbdev/omap2/dss/dss-of.c) | 0 | ||||
-rw-r--r-- | drivers/video/fbdev/omap2/omapfb/dss/dss.c (renamed from drivers/video/fbdev/omap2/dss/dss.c) | 12 | ||||
-rw-r--r-- | drivers/video/fbdev/omap2/omapfb/dss/dss.h (renamed from drivers/video/fbdev/omap2/dss/dss.h) | 18 | ||||
-rw-r--r-- | drivers/video/fbdev/omap2/omapfb/dss/dss_features.c (renamed from drivers/video/fbdev/omap2/dss/dss_features.c) | 11 | ||||
-rw-r--r-- | drivers/video/fbdev/omap2/omapfb/dss/dss_features.h (renamed from drivers/video/fbdev/omap2/dss/dss_features.h) | 5 | ||||
-rw-r--r-- | drivers/video/fbdev/omap2/omapfb/dss/hdmi.h (renamed from drivers/video/fbdev/omap2/dss/hdmi.h) | 0 | ||||
-rw-r--r-- | drivers/video/fbdev/omap2/omapfb/dss/hdmi4.c (renamed from drivers/video/fbdev/omap2/dss/hdmi4.c) | 2 | ||||
-rw-r--r-- | drivers/video/fbdev/omap2/omapfb/dss/hdmi4_core.c (renamed from drivers/video/fbdev/omap2/dss/hdmi4_core.c) | 0 | ||||
-rw-r--r-- | drivers/video/fbdev/omap2/omapfb/dss/hdmi4_core.h (renamed from drivers/video/fbdev/omap2/dss/hdmi4_core.h) | 0 | ||||
-rw-r--r-- | drivers/video/fbdev/omap2/omapfb/dss/hdmi5.c (renamed from drivers/video/fbdev/omap2/dss/hdmi5.c) | 2 | ||||
-rw-r--r-- | drivers/video/fbdev/omap2/omapfb/dss/hdmi5_core.c (renamed from drivers/video/fbdev/omap2/dss/hdmi5_core.c) | 0 | ||||
-rw-r--r-- | drivers/video/fbdev/omap2/omapfb/dss/hdmi5_core.h (renamed from drivers/video/fbdev/omap2/dss/hdmi5_core.h) | 0 | ||||
-rw-r--r-- | drivers/video/fbdev/omap2/omapfb/dss/hdmi_common.c (renamed from drivers/video/fbdev/omap2/dss/hdmi_common.c) | 0 | ||||
-rw-r--r-- | drivers/video/fbdev/omap2/omapfb/dss/hdmi_phy.c (renamed from drivers/video/fbdev/omap2/dss/hdmi_phy.c) | 0 | ||||
-rw-r--r-- | drivers/video/fbdev/omap2/omapfb/dss/hdmi_pll.c (renamed from drivers/video/fbdev/omap2/dss/hdmi_pll.c) | 0 | ||||
-rw-r--r-- | drivers/video/fbdev/omap2/omapfb/dss/hdmi_wp.c (renamed from drivers/video/fbdev/omap2/dss/hdmi_wp.c) | 0 | ||||
-rw-r--r-- | drivers/video/fbdev/omap2/omapfb/dss/manager-sysfs.c (renamed from drivers/video/fbdev/omap2/dss/manager-sysfs.c) | 0 | ||||
-rw-r--r-- | drivers/video/fbdev/omap2/omapfb/dss/manager.c (renamed from drivers/video/fbdev/omap2/dss/manager.c) | 2 | ||||
-rw-r--r-- | drivers/video/fbdev/omap2/omapfb/dss/omapdss-boot-init.c (renamed from drivers/video/fbdev/omap2/dss/omapdss-boot-init.c) | 4 | ||||
-rw-r--r-- | drivers/video/fbdev/omap2/omapfb/dss/output.c (renamed from drivers/video/fbdev/omap2/dss/output.c) | 0 | ||||
-rw-r--r-- | drivers/video/fbdev/omap2/omapfb/dss/overlay-sysfs.c (renamed from drivers/video/fbdev/omap2/dss/overlay-sysfs.c) | 0 | ||||
-rw-r--r-- | drivers/video/fbdev/omap2/omapfb/dss/overlay.c (renamed from drivers/video/fbdev/omap2/dss/overlay.c) | 0 | ||||
-rw-r--r-- | drivers/video/fbdev/omap2/omapfb/dss/pll.c (renamed from drivers/video/fbdev/omap2/dss/pll.c) | 0 | ||||
-rw-r--r-- | drivers/video/fbdev/omap2/omapfb/dss/rfbi.c (renamed from drivers/video/fbdev/omap2/dss/rfbi.c) | 2 | ||||
-rw-r--r-- | drivers/video/fbdev/omap2/omapfb/dss/sdi.c (renamed from drivers/video/fbdev/omap2/dss/sdi.c) | 2 | ||||
-rw-r--r-- | drivers/video/fbdev/omap2/omapfb/dss/venc.c (renamed from drivers/video/fbdev/omap2/dss/venc.c) | 16 | ||||
-rw-r--r-- | drivers/video/fbdev/omap2/omapfb/dss/video-pll.c (renamed from drivers/video/fbdev/omap2/dss/video-pll.c) | 0 | ||||
-rw-r--r-- | drivers/video/fbdev/omap2/omapfb/vrfb.c (renamed from drivers/video/fbdev/omap2/vrfb.c) | 0 | ||||
-rw-r--r-- | drivers/video/fbdev/pxafb.c | 210 | ||||
-rw-r--r-- | drivers/video/fbdev/pxafb.h | 2 | ||||
-rw-r--r-- | drivers/video/fbdev/riva/fbdev.c | 1 | ||||
-rw-r--r-- | drivers/video/fbdev/sh_mobile_hdmi.c | 1489 | ||||
-rw-r--r-- | drivers/video/fbdev/simplefb.c | 120 | ||||
-rw-r--r-- | drivers/video/fbdev/sm712fb.c | 16 |
80 files changed, 664 insertions, 1845 deletions
diff --git a/drivers/video/fbdev/Kconfig b/drivers/video/fbdev/Kconfig index e6d16d65e4e6..8ea45a5cd806 100644 --- a/drivers/video/fbdev/Kconfig +++ b/drivers/video/fbdev/Kconfig @@ -5,6 +5,7 @@ menuconfig FB tristate "Support for frame buffer devices" select FB_CMDLINE + select FB_NOTIFY ---help--- The frame buffer device provides an abstraction for the graphics hardware. It represents the frame buffer of some video hardware and @@ -56,6 +57,9 @@ config FIRMWARE_EDID config FB_CMDLINE bool +config FB_NOTIFY + bool + config FB_DDC tristate depends on FB @@ -1506,6 +1510,7 @@ config FB_SIS select FB_CFB_COPYAREA select FB_CFB_IMAGEBLIT select FB_BOOT_VESA_SUPPORT if FB_SIS = y + select FB_SIS_300 if !FB_SIS_315 help This is the frame buffer device driver for the SiS 300, 315, 330 and 340 series as well as XGI V3XT, V5, V8, Z7 graphics chipsets. @@ -1880,6 +1885,8 @@ config FB_PXA select FB_CFB_FILLRECT select FB_CFB_COPYAREA select FB_CFB_IMAGEBLIT + select VIDEOMODE_HELPERS if OF + select FB_MODE_HELPERS if OF ---help--- Frame buffer driver for the built-in LCD controller in the Intel PXA2x0 processor. @@ -1990,16 +1997,6 @@ config FB_SH_MOBILE_LCDC ---help--- Frame buffer driver for the on-chip SH-Mobile LCD controller. -config FB_SH_MOBILE_HDMI - tristate "SuperH Mobile HDMI controller support" - depends on FB_SH_MOBILE_LCDC - select FB_MODE_HELPERS - select SOUND - select SND - select SND_SOC - ---help--- - Driver for the on-chip SH-Mobile HDMI controller. - config FB_TMIO tristate "Toshiba Mobile IO FrameBuffer support" depends on FB && (MFD_TMIO || COMPILE_TEST) diff --git a/drivers/video/fbdev/Makefile b/drivers/video/fbdev/Makefile index 50ed1b4fc2bf..65fb15075c8f 100644 --- a/drivers/video/fbdev/Makefile +++ b/drivers/video/fbdev/Makefile @@ -118,7 +118,6 @@ obj-$(CONFIG_FB_UDL) += udlfb.o obj-$(CONFIG_FB_SMSCUFX) += smscufx.o obj-$(CONFIG_FB_XILINX) += xilinxfb.o obj-$(CONFIG_SH_MIPI_DSI) += sh_mipi_dsi.o -obj-$(CONFIG_FB_SH_MOBILE_HDMI) += sh_mobile_hdmi.o obj-$(CONFIG_FB_SH_MOBILE_MERAM) += sh_mobile_meram.o obj-$(CONFIG_FB_SH_MOBILE_LCDC) += sh_mobile_lcdcfb.o obj-$(CONFIG_FB_OMAP) += omap/ diff --git a/drivers/video/fbdev/auo_k190x.c b/drivers/video/fbdev/auo_k190x.c index 8d2499d1cafb..9580374667ba 100644 --- a/drivers/video/fbdev/auo_k190x.c +++ b/drivers/video/fbdev/auo_k190x.c @@ -773,9 +773,7 @@ static void auok190x_recover(struct auok190xfb_par *par) /* * Power-management */ - -#ifdef CONFIG_PM -static int auok190x_runtime_suspend(struct device *dev) +static int __maybe_unused auok190x_runtime_suspend(struct device *dev) { struct platform_device *pdev = to_platform_device(dev); struct fb_info *info = platform_get_drvdata(pdev); @@ -822,7 +820,7 @@ finish: return 0; } -static int auok190x_runtime_resume(struct device *dev) +static int __maybe_unused auok190x_runtime_resume(struct device *dev) { struct platform_device *pdev = to_platform_device(dev); struct fb_info *info = platform_get_drvdata(pdev); @@ -856,7 +854,7 @@ static int auok190x_runtime_resume(struct device *dev) return 0; } -static int auok190x_suspend(struct device *dev) +static int __maybe_unused auok190x_suspend(struct device *dev) { struct platform_device *pdev = to_platform_device(dev); struct fb_info *info = platform_get_drvdata(pdev); @@ -896,7 +894,7 @@ static int auok190x_suspend(struct device *dev) return 0; } -static int auok190x_resume(struct device *dev) +static int __maybe_unused auok190x_resume(struct device *dev) { struct platform_device *pdev = to_platform_device(dev); struct fb_info *info = platform_get_drvdata(pdev); @@ -933,7 +931,6 @@ static int auok190x_resume(struct device *dev) return 0; } -#endif const struct dev_pm_ops auok190x_pm = { SET_RUNTIME_PM_OPS(auok190x_runtime_suspend, auok190x_runtime_resume, diff --git a/drivers/video/fbdev/core/Makefile b/drivers/video/fbdev/core/Makefile index 23d86a8b7d7b..9e3ddf225393 100644 --- a/drivers/video/fbdev/core/Makefile +++ b/drivers/video/fbdev/core/Makefile @@ -1,5 +1,5 @@ -obj-y += fb_notify.o obj-$(CONFIG_FB_CMDLINE) += fb_cmdline.o +obj-$(CONFIG_FB_NOTIFY) += fb_notify.o obj-$(CONFIG_FB) += fb.o fb-y := fbmem.o fbmon.o fbcmap.o fbsysfs.o \ modedb.o fbcvt.o diff --git a/drivers/video/fbdev/core/fbmem.c b/drivers/video/fbdev/core/fbmem.c index 0705d8883ede..4e73b6f6b1c0 100644 --- a/drivers/video/fbdev/core/fbmem.c +++ b/drivers/video/fbdev/core/fbmem.c @@ -1608,6 +1608,11 @@ static int do_remove_conflicting_framebuffers(struct apertures_struct *a, return 0; } +static bool lockless_register_fb; +module_param_named_unsafe(lockless_register_fb, lockless_register_fb, bool, 0400); +MODULE_PARM_DESC(lockless_register_fb, + "Lockless framebuffer registration for debugging [default=off]"); + static int do_register_framebuffer(struct fb_info *fb_info) { int i, ret; @@ -1675,15 +1680,18 @@ static int do_register_framebuffer(struct fb_info *fb_info) registered_fb[i] = fb_info; event.info = fb_info; - console_lock(); + if (!lockless_register_fb) + console_lock(); if (!lock_fb_info(fb_info)) { - console_unlock(); + if (!lockless_register_fb) + console_unlock(); return -ENODEV; } fb_notifier_call_chain(FB_EVENT_FB_REGISTERED, &event); unlock_fb_info(fb_info); - console_unlock(); + if (!lockless_register_fb) + console_unlock(); return 0; } diff --git a/drivers/video/fbdev/geode/display_gx1.c b/drivers/video/fbdev/geode/display_gx1.c index 926d53eeb549..b383eb9882bf 100644 --- a/drivers/video/fbdev/geode/display_gx1.c +++ b/drivers/video/fbdev/geode/display_gx1.c @@ -208,7 +208,7 @@ static void gx1_set_hw_palette_reg(struct fb_info *info, unsigned regno, writel(val, par->dc_regs + DC_PAL_DATA); } -struct geode_dc_ops gx1_dc_ops = { +const struct geode_dc_ops gx1_dc_ops = { .set_mode = gx1_set_mode, .set_palette_reg = gx1_set_hw_palette_reg, }; diff --git a/drivers/video/fbdev/geode/display_gx1.h b/drivers/video/fbdev/geode/display_gx1.h index 671c05558c79..e1cc41b343ca 100644 --- a/drivers/video/fbdev/geode/display_gx1.h +++ b/drivers/video/fbdev/geode/display_gx1.h @@ -18,7 +18,7 @@ unsigned gx1_gx_base(void); int gx1_frame_buffer_size(void); -extern struct geode_dc_ops gx1_dc_ops; +extern const struct geode_dc_ops gx1_dc_ops; /* GX1 configuration I/O registers */ diff --git a/drivers/video/fbdev/geode/geodefb.h b/drivers/video/fbdev/geode/geodefb.h index ae04820e0c57..e2e07934868f 100644 --- a/drivers/video/fbdev/geode/geodefb.h +++ b/drivers/video/fbdev/geode/geodefb.h @@ -31,8 +31,8 @@ struct geodefb_par { int panel_y; void __iomem *dc_regs; void __iomem *vid_regs; - struct geode_dc_ops *dc_ops; - struct geode_vid_ops *vid_ops; + const struct geode_dc_ops *dc_ops; + const struct geode_vid_ops *vid_ops; }; #endif /* !__GEODEFB_H__ */ diff --git a/drivers/video/fbdev/geode/video_cs5530.c b/drivers/video/fbdev/geode/video_cs5530.c index 649c3943d431..880613200ecf 100644 --- a/drivers/video/fbdev/geode/video_cs5530.c +++ b/drivers/video/fbdev/geode/video_cs5530.c @@ -186,7 +186,7 @@ static int cs5530_blank_display(struct fb_info *info, int blank_mode) return 0; } -struct geode_vid_ops cs5530_vid_ops = { +const struct geode_vid_ops cs5530_vid_ops = { .set_dclk = cs5530_set_dclk_frequency, .configure_display = cs5530_configure_display, .blank_display = cs5530_blank_display, diff --git a/drivers/video/fbdev/geode/video_cs5530.h b/drivers/video/fbdev/geode/video_cs5530.h index 56cecca7f1ce..c843348bfa20 100644 --- a/drivers/video/fbdev/geode/video_cs5530.h +++ b/drivers/video/fbdev/geode/video_cs5530.h @@ -15,7 +15,7 @@ #ifndef __VIDEO_CS5530_H__ #define __VIDEO_CS5530_H__ -extern struct geode_vid_ops cs5530_vid_ops; +extern const struct geode_vid_ops cs5530_vid_ops; /* CS5530 Video device registers */ diff --git a/drivers/video/fbdev/i740fb.c b/drivers/video/fbdev/i740fb.c index 452e1163ad02..cf5ccd0f2252 100644 --- a/drivers/video/fbdev/i740fb.c +++ b/drivers/video/fbdev/i740fb.c @@ -346,11 +346,10 @@ static void i740_calc_vclk(u32 freq, struct i740fb_par *par) const u32 err_target = freq / (1000 * I740_RFREQ / I740_FFIX); u32 err_best = 512 * I740_FFIX; u32 f_err, f_vco; - int m_best = 0, n_best = 0, p_best = 0, d_best = 0; + int m_best = 0, n_best = 0, p_best = 0; int m, n; p_best = min(15, ilog2(I740_MAX_VCO_FREQ / (freq / I740_RFREQ_FIX))); - d_best = 0; f_vco = (freq * (1 << p_best)) / I740_RFREQ_FIX; freq = freq / I740_RFREQ_FIX; @@ -363,7 +362,7 @@ static void i740_calc_vclk(u32 freq, struct i740fb_par *par) m = 3; { - u32 f_out = (((m * I740_REF_FREQ * (4 << 2 * d_best)) + u32 f_out = (((m * I740_REF_FREQ * 4) / n) + ((1 << p_best) / 2)) / (1 << p_best); f_err = (freq - f_out); @@ -386,8 +385,7 @@ static void i740_calc_vclk(u32 freq, struct i740fb_par *par) par->video_clk2_n = (n_best - 2) & 0xFF; par->video_clk2_mn_msbs = ((((n_best - 2) >> 4) & VCO_N_MSBS) | (((m_best - 2) >> 8) & VCO_M_MSBS)); - par->video_clk2_div_sel = - ((p_best << 4) | (d_best ? 4 : 0) | REF_DIV_1); + par->video_clk2_div_sel = ((p_best << 4) | REF_DIV_1); } static int i740fb_decode_var(const struct fb_var_screeninfo *var, diff --git a/drivers/video/fbdev/omap2/Kconfig b/drivers/video/fbdev/omap2/Kconfig index c22955d2de9a..0921c4de8407 100644 --- a/drivers/video/fbdev/omap2/Kconfig +++ b/drivers/video/fbdev/omap2/Kconfig @@ -1,10 +1,5 @@ -config OMAP2_VRFB - bool - if ARCH_OMAP2PLUS -source "drivers/video/fbdev/omap2/dss/Kconfig" source "drivers/video/fbdev/omap2/omapfb/Kconfig" -source "drivers/video/fbdev/omap2/displays-new/Kconfig" endif diff --git a/drivers/video/fbdev/omap2/Makefile b/drivers/video/fbdev/omap2/Makefile index f8745ec369cc..71ab5ac91106 100644 --- a/drivers/video/fbdev/omap2/Makefile +++ b/drivers/video/fbdev/omap2/Makefile @@ -1,5 +1 @@ -obj-$(CONFIG_OMAP2_VRFB) += vrfb.o - -obj-y += dss/ -obj-y += displays-new/ -obj-$(CONFIG_FB_OMAP2) += omapfb/ +obj-y += omapfb/ diff --git a/drivers/video/fbdev/omap2/displays-new/Makefile b/drivers/video/fbdev/omap2/displays-new/Makefile deleted file mode 100644 index 9aa176bfbf2e..000000000000 --- a/drivers/video/fbdev/omap2/displays-new/Makefile +++ /dev/null @@ -1,14 +0,0 @@ -obj-$(CONFIG_DISPLAY_ENCODER_OPA362) += encoder-opa362.o -obj-$(CONFIG_DISPLAY_ENCODER_TFP410) += encoder-tfp410.o -obj-$(CONFIG_DISPLAY_ENCODER_TPD12S015) += encoder-tpd12s015.o -obj-$(CONFIG_DISPLAY_CONNECTOR_DVI) += connector-dvi.o -obj-$(CONFIG_DISPLAY_CONNECTOR_HDMI) += connector-hdmi.o -obj-$(CONFIG_DISPLAY_CONNECTOR_ANALOG_TV) += connector-analog-tv.o -obj-$(CONFIG_DISPLAY_PANEL_DPI) += panel-dpi.o -obj-$(CONFIG_DISPLAY_PANEL_DSI_CM) += panel-dsi-cm.o -obj-$(CONFIG_DISPLAY_PANEL_SONY_ACX565AKM) += panel-sony-acx565akm.o -obj-$(CONFIG_DISPLAY_PANEL_LGPHILIPS_LB035Q02) += panel-lgphilips-lb035q02.o -obj-$(CONFIG_DISPLAY_PANEL_SHARP_LS037V7DW01) += panel-sharp-ls037v7dw01.o -obj-$(CONFIG_DISPLAY_PANEL_TPO_TD028TTEC1) += panel-tpo-td028ttec1.o -obj-$(CONFIG_DISPLAY_PANEL_TPO_TD043MTEA1) += panel-tpo-td043mtea1.o -obj-$(CONFIG_DISPLAY_PANEL_NEC_NL8048HL11) += panel-nec-nl8048hl11.o diff --git a/drivers/video/fbdev/omap2/dss/Makefile b/drivers/video/fbdev/omap2/dss/Makefile deleted file mode 100644 index b5136d3d4b77..000000000000 --- a/drivers/video/fbdev/omap2/dss/Makefile +++ /dev/null @@ -1,18 +0,0 @@ -obj-$(CONFIG_OMAP2_DSS_INIT) += omapdss-boot-init.o -obj-$(CONFIG_OMAP2_DSS) += omapdss.o -# Core DSS files -omapdss-y := core.o dss.o dss_features.o dispc.o dispc_coefs.o display.o \ - output.o dss-of.o pll.o video-pll.o -# DSS compat layer files -omapdss-y += manager.o manager-sysfs.o overlay.o overlay-sysfs.o apply.o \ - dispc-compat.o display-sysfs.o -omapdss-$(CONFIG_OMAP2_DSS_DPI) += dpi.o -omapdss-$(CONFIG_OMAP2_DSS_RFBI) += rfbi.o -omapdss-$(CONFIG_OMAP2_DSS_VENC) += venc.o -omapdss-$(CONFIG_OMAP2_DSS_SDI) += sdi.o -omapdss-$(CONFIG_OMAP2_DSS_DSI) += dsi.o -omapdss-$(CONFIG_OMAP2_DSS_HDMI_COMMON) += hdmi_common.o hdmi_wp.o hdmi_pll.o \ - hdmi_phy.o -omapdss-$(CONFIG_OMAP4_DSS_HDMI) += hdmi4.o hdmi4_core.o -omapdss-$(CONFIG_OMAP5_DSS_HDMI) += hdmi5.o hdmi5_core.o -ccflags-$(CONFIG_OMAP2_DSS_DEBUG) += -DDEBUG diff --git a/drivers/video/fbdev/omap2/omapfb/Kconfig b/drivers/video/fbdev/omap2/omapfb/Kconfig index 4cb12ce68855..e6226aeed17e 100644 --- a/drivers/video/fbdev/omap2/omapfb/Kconfig +++ b/drivers/video/fbdev/omap2/omapfb/Kconfig @@ -1,7 +1,12 @@ +config OMAP2_VRFB + bool + menuconfig FB_OMAP2 tristate "OMAP2+ frame buffer support" - depends on FB && OMAP2_DSS && !DRM_OMAP + depends on FB + depends on DRM_OMAP = n + select FB_OMAP2_DSS select OMAP2_VRFB if ARCH_OMAP2 || ARCH_OMAP3 select FB_CFB_FILLRECT select FB_CFB_COPYAREA @@ -9,6 +14,8 @@ menuconfig FB_OMAP2 help Frame buffer driver for OMAP2+ based boards. +if FB_OMAP2 + config FB_OMAP2_DEBUG_SUPPORT bool "Debug support for OMAP2+ FB" default y @@ -25,3 +32,8 @@ config FB_OMAP2_NUM_FBS help Select the number of framebuffers created. OMAP2/3 has 3 overlays so normally this would be 3. + +source "drivers/video/fbdev/omap2/omapfb/dss/Kconfig" +source "drivers/video/fbdev/omap2/omapfb/displays/Kconfig" + +endif diff --git a/drivers/video/fbdev/omap2/omapfb/Makefile b/drivers/video/fbdev/omap2/omapfb/Makefile index 51c2e00d9bf8..ad68ecf141af 100644 --- a/drivers/video/fbdev/omap2/omapfb/Makefile +++ b/drivers/video/fbdev/omap2/omapfb/Makefile @@ -1,2 +1,5 @@ +obj-$(CONFIG_OMAP2_VRFB) += vrfb.o +obj-y += dss/ +obj-y += displays/ obj-$(CONFIG_FB_OMAP2) += omapfb.o omapfb-y := omapfb-main.o omapfb-sysfs.o omapfb-ioctl.o diff --git a/drivers/video/fbdev/omap2/displays-new/Kconfig b/drivers/video/fbdev/omap2/omapfb/displays/Kconfig index 574710141a61..08f12039dd02 100644 --- a/drivers/video/fbdev/omap2/displays-new/Kconfig +++ b/drivers/video/fbdev/omap2/omapfb/displays/Kconfig @@ -1,81 +1,81 @@ -menu "OMAP Display Device Drivers (new device model)" - depends on OMAP2_DSS +menu "OMAPFB Panel and Encoder Drivers" + depends on FB_OMAP2_DSS -config DISPLAY_ENCODER_OPA362 +config FB_OMAP2_ENCODER_OPA362 tristate "OPA362 external analog amplifier" help Driver for OPA362 external analog TV amplifier controlled through a GPIO. -config DISPLAY_ENCODER_TFP410 +config FB_OMAP2_ENCODER_TFP410 tristate "TFP410 DPI to DVI Encoder" help Driver for TFP410 DPI to DVI encoder. -config DISPLAY_ENCODER_TPD12S015 +config FB_OMAP2_ENCODER_TPD12S015 tristate "TPD12S015 HDMI ESD protection and level shifter" help Driver for TPD12S015, which offers HDMI ESD protection and level shifting. -config DISPLAY_CONNECTOR_DVI +config FB_OMAP2_CONNECTOR_DVI tristate "DVI Connector" depends on I2C help Driver for a generic DVI connector. -config DISPLAY_CONNECTOR_HDMI +config FB_OMAP2_CONNECTOR_HDMI tristate "HDMI Connector" help Driver for a generic HDMI connector. -config DISPLAY_CONNECTOR_ANALOG_TV +config FB_OMAP2_CONNECTOR_ANALOG_TV tristate "Analog TV Connector" help Driver for a generic analog TV connector. -config DISPLAY_PANEL_DPI +config FB_OMAP2_PANEL_DPI tristate "Generic DPI panel" help Driver for generic DPI panels. -config DISPLAY_PANEL_DSI_CM +config FB_OMAP2_PANEL_DSI_CM tristate "Generic DSI Command Mode Panel" depends on BACKLIGHT_CLASS_DEVICE help Driver for generic DSI command mode panels. -config DISPLAY_PANEL_SONY_ACX565AKM +config FB_OMAP2_PANEL_SONY_ACX565AKM tristate "ACX565AKM Panel" depends on SPI && BACKLIGHT_CLASS_DEVICE help This is the LCD panel used on Nokia N900 -config DISPLAY_PANEL_LGPHILIPS_LB035Q02 +config FB_OMAP2_PANEL_LGPHILIPS_LB035Q02 tristate "LG.Philips LB035Q02 LCD Panel" depends on SPI help LCD Panel used on the Gumstix Overo Palo35 -config DISPLAY_PANEL_SHARP_LS037V7DW01 +config FB_OMAP2_PANEL_SHARP_LS037V7DW01 tristate "Sharp LS037V7DW01 LCD Panel" depends on BACKLIGHT_CLASS_DEVICE help LCD Panel used in TI's SDP3430 and EVM boards -config DISPLAY_PANEL_TPO_TD028TTEC1 +config FB_OMAP2_PANEL_TPO_TD028TTEC1 tristate "TPO TD028TTEC1 LCD Panel" depends on SPI help LCD panel used in Openmoko. -config DISPLAY_PANEL_TPO_TD043MTEA1 +config FB_OMAP2_PANEL_TPO_TD043MTEA1 tristate "TPO TD043MTEA1 LCD Panel" depends on SPI help LCD Panel used in OMAP3 Pandora -config DISPLAY_PANEL_NEC_NL8048HL11 +config FB_OMAP2_PANEL_NEC_NL8048HL11 tristate "NEC NL8048HL11 Panel" depends on SPI depends on BACKLIGHT_CLASS_DEVICE diff --git a/drivers/video/fbdev/omap2/omapfb/displays/Makefile b/drivers/video/fbdev/omap2/omapfb/displays/Makefile new file mode 100644 index 000000000000..4f7459272256 --- /dev/null +++ b/drivers/video/fbdev/omap2/omapfb/displays/Makefile @@ -0,0 +1,14 @@ +obj-$(CONFIG_FB_OMAP2_ENCODER_OPA362) += encoder-opa362.o +obj-$(CONFIG_FB_OMAP2_ENCODER_TFP410) += encoder-tfp410.o +obj-$(CONFIG_FB_OMAP2_ENCODER_TPD12S015) += encoder-tpd12s015.o +obj-$(CONFIG_FB_OMAP2_CONNECTOR_DVI) += connector-dvi.o +obj-$(CONFIG_FB_OMAP2_CONNECTOR_HDMI) += connector-hdmi.o +obj-$(CONFIG_FB_OMAP2_CONNECTOR_ANALOG_TV) += connector-analog-tv.o +obj-$(CONFIG_FB_OMAP2_PANEL_DPI) += panel-dpi.o +obj-$(CONFIG_FB_OMAP2_PANEL_DSI_CM) += panel-dsi-cm.o +obj-$(CONFIG_FB_OMAP2_PANEL_SONY_ACX565AKM) += panel-sony-acx565akm.o +obj-$(CONFIG_FB_OMAP2_PANEL_LGPHILIPS_LB035Q02) += panel-lgphilips-lb035q02.o +obj-$(CONFIG_FB_OMAP2_PANEL_SHARP_LS037V7DW01) += panel-sharp-ls037v7dw01.o +obj-$(CONFIG_FB_OMAP2_PANEL_TPO_TD028TTEC1) += panel-tpo-td028ttec1.o +obj-$(CONFIG_FB_OMAP2_PANEL_TPO_TD043MTEA1) += panel-tpo-td043mtea1.o +obj-$(CONFIG_FB_OMAP2_PANEL_NEC_NL8048HL11) += panel-nec-nl8048hl11.o diff --git a/drivers/video/fbdev/omap2/displays-new/connector-analog-tv.c b/drivers/video/fbdev/omap2/omapfb/displays/connector-analog-tv.c index 8511c648a15c..8511c648a15c 100644 --- a/drivers/video/fbdev/omap2/displays-new/connector-analog-tv.c +++ b/drivers/video/fbdev/omap2/omapfb/displays/connector-analog-tv.c diff --git a/drivers/video/fbdev/omap2/displays-new/connector-dvi.c b/drivers/video/fbdev/omap2/omapfb/displays/connector-dvi.c index d811e6dcaef7..d811e6dcaef7 100644 --- a/drivers/video/fbdev/omap2/displays-new/connector-dvi.c +++ b/drivers/video/fbdev/omap2/omapfb/displays/connector-dvi.c diff --git a/drivers/video/fbdev/omap2/displays-new/connector-hdmi.c b/drivers/video/fbdev/omap2/omapfb/displays/connector-hdmi.c index 6ee4129bc0c0..6ee4129bc0c0 100644 --- a/drivers/video/fbdev/omap2/displays-new/connector-hdmi.c +++ b/drivers/video/fbdev/omap2/omapfb/displays/connector-hdmi.c diff --git a/drivers/video/fbdev/omap2/displays-new/encoder-opa362.c b/drivers/video/fbdev/omap2/omapfb/displays/encoder-opa362.c index 8c246c213e06..8c246c213e06 100644 --- a/drivers/video/fbdev/omap2/displays-new/encoder-opa362.c +++ b/drivers/video/fbdev/omap2/omapfb/displays/encoder-opa362.c diff --git a/drivers/video/fbdev/omap2/displays-new/encoder-tfp410.c b/drivers/video/fbdev/omap2/omapfb/displays/encoder-tfp410.c index d9048b3df495..d9048b3df495 100644 --- a/drivers/video/fbdev/omap2/displays-new/encoder-tfp410.c +++ b/drivers/video/fbdev/omap2/omapfb/displays/encoder-tfp410.c diff --git a/drivers/video/fbdev/omap2/displays-new/encoder-tpd12s015.c b/drivers/video/fbdev/omap2/omapfb/displays/encoder-tpd12s015.c index 990af6baeb0f..677e2545fcbe 100644 --- a/drivers/video/fbdev/omap2/displays-new/encoder-tpd12s015.c +++ b/drivers/video/fbdev/omap2/omapfb/displays/encoder-tpd12s015.c @@ -13,9 +13,8 @@ #include <linux/delay.h> #include <linux/module.h> #include <linux/slab.h> -#include <linux/gpio.h> #include <linux/platform_device.h> -#include <linux/of_gpio.h> +#include <linux/gpio/consumer.h> #include <video/omapdss.h> #include <video/omap-panel-data.h> @@ -24,9 +23,9 @@ struct panel_drv_data { struct omap_dss_device dssdev; struct omap_dss_device *in; - int ct_cp_hpd_gpio; - int ls_oe_gpio; - int hpd_gpio; + struct gpio_desc *ct_cp_hpd_gpio; + struct gpio_desc *ls_oe_gpio; + struct gpio_desc *hpd_gpio; struct omap_video_timings timings; }; @@ -47,9 +46,11 @@ static int tpd_connect(struct omap_dss_device *dssdev, dst->src = dssdev; dssdev->dst = dst; - gpio_set_value_cansleep(ddata->ct_cp_hpd_gpio, 1); - /* DC-DC converter needs at max 300us to get to 90% of 5V */ - udelay(300); + if (ddata->ct_cp_hpd_gpio) { + gpiod_set_value_cansleep(ddata->ct_cp_hpd_gpio, 1); + /* DC-DC converter needs at max 300us to get to 90% of 5V */ + udelay(300); + } return 0; } @@ -65,7 +66,7 @@ static void tpd_disconnect(struct omap_dss_device *dssdev, if (dst != dssdev->dst) return; - gpio_set_value_cansleep(ddata->ct_cp_hpd_gpio, 0); + gpiod_set_value_cansleep(ddata->ct_cp_hpd_gpio, 0); dst->src = NULL; dssdev->dst = NULL; @@ -145,16 +146,14 @@ static int tpd_read_edid(struct omap_dss_device *dssdev, struct omap_dss_device *in = ddata->in; int r; - if (!gpio_get_value_cansleep(ddata->hpd_gpio)) + if (!gpiod_get_value_cansleep(ddata->hpd_gpio)) return -ENODEV; - if (gpio_is_valid(ddata->ls_oe_gpio)) - gpio_set_value_cansleep(ddata->ls_oe_gpio, 1); + gpiod_set_value_cansleep(ddata->ls_oe_gpio, 1); r = in->ops.hdmi->read_edid(in, edid, len); - if (gpio_is_valid(ddata->ls_oe_gpio)) - gpio_set_value_cansleep(ddata->ls_oe_gpio, 0); + gpiod_set_value_cansleep(ddata->ls_oe_gpio, 0); return r; } @@ -163,7 +162,7 @@ static bool tpd_detect(struct omap_dss_device *dssdev) { struct panel_drv_data *ddata = to_panel_data(dssdev); - return gpio_get_value_cansleep(ddata->hpd_gpio); + return gpiod_get_value_cansleep(ddata->hpd_gpio); } static int tpd_set_infoframe(struct omap_dss_device *dssdev, @@ -201,63 +200,11 @@ static const struct omapdss_hdmi_ops tpd_hdmi_ops = { .set_hdmi_mode = tpd_set_hdmi_mode, }; -static int tpd_probe_pdata(struct platform_device *pdev) -{ - struct panel_drv_data *ddata = platform_get_drvdata(pdev); - struct encoder_tpd12s015_platform_data *pdata; - struct omap_dss_device *dssdev, *in; - - pdata = dev_get_platdata(&pdev->dev); - - ddata->ct_cp_hpd_gpio = pdata->ct_cp_hpd_gpio; - ddata->ls_oe_gpio = pdata->ls_oe_gpio; - ddata->hpd_gpio = pdata->hpd_gpio; - - in = omap_dss_find_output(pdata->source); - if (in == NULL) { - dev_err(&pdev->dev, "Failed to find video source\n"); - return -ENODEV; - } - - ddata->in = in; - - dssdev = &ddata->dssdev; - dssdev->name = pdata->name; - - return 0; -} - static int tpd_probe_of(struct platform_device *pdev) { struct panel_drv_data *ddata = platform_get_drvdata(pdev); struct device_node *node = pdev->dev.of_node; struct omap_dss_device *in; - int gpio; - - /* CT CP HPD GPIO */ - gpio = of_get_gpio(node, 0); - if (!gpio_is_valid(gpio)) { - dev_err(&pdev->dev, "failed to parse CT CP HPD gpio\n"); - return gpio; - } - ddata->ct_cp_hpd_gpio = gpio; - - /* LS OE GPIO */ - gpio = of_get_gpio(node, 1); - if (gpio_is_valid(gpio) || gpio == -ENOENT) { - ddata->ls_oe_gpio = gpio; - } else { - dev_err(&pdev->dev, "failed to parse LS OE gpio\n"); - return gpio; - } - - /* HPD GPIO */ - gpio = of_get_gpio(node, 2); - if (!gpio_is_valid(gpio)) { - dev_err(&pdev->dev, "failed to parse HPD gpio\n"); - return gpio; - } - ddata->hpd_gpio = gpio; in = omapdss_of_find_source_for_first_ep(node); if (IS_ERR(in)) { @@ -275,6 +222,7 @@ static int tpd_probe(struct platform_device *pdev) struct omap_dss_device *in, *dssdev; struct panel_drv_data *ddata; int r; + struct gpio_desc *gpio; ddata = devm_kzalloc(&pdev->dev, sizeof(*ddata), GFP_KERNEL); if (!ddata) @@ -282,11 +230,7 @@ static int tpd_probe(struct platform_device *pdev) platform_set_drvdata(pdev, ddata); - if (dev_get_platdata(&pdev->dev)) { - r = tpd_probe_pdata(pdev); - if (r) - return r; - } else if (pdev->dev.of_node) { + if (pdev->dev.of_node) { r = tpd_probe_of(pdev); if (r) return r; @@ -294,23 +238,28 @@ static int tpd_probe(struct platform_device *pdev) return -ENODEV; } - r = devm_gpio_request_one(&pdev->dev, ddata->ct_cp_hpd_gpio, - GPIOF_OUT_INIT_LOW, "hdmi_ct_cp_hpd"); - if (r) + + gpio = devm_gpiod_get_index_optional(&pdev->dev, NULL, 0, + GPIOD_OUT_LOW); + if (IS_ERR(gpio)) goto err_gpio; - if (gpio_is_valid(ddata->ls_oe_gpio)) { - r = devm_gpio_request_one(&pdev->dev, ddata->ls_oe_gpio, - GPIOF_OUT_INIT_LOW, "hdmi_ls_oe"); - if (r) - goto err_gpio; - } + ddata->ct_cp_hpd_gpio = gpio; - r = devm_gpio_request_one(&pdev->dev, ddata->hpd_gpio, - GPIOF_DIR_IN, "hdmi_hpd"); - if (r) + gpio = devm_gpiod_get_index_optional(&pdev->dev, NULL, 1, + GPIOD_OUT_LOW); + if (IS_ERR(gpio)) goto err_gpio; + ddata->ls_oe_gpio = gpio; + + gpio = devm_gpiod_get_index(&pdev->dev, NULL, 2, + GPIOD_IN); + if (IS_ERR(gpio)) + goto err_gpio; + + ddata->hpd_gpio = gpio; + dssdev = &ddata->dssdev; dssdev->ops.hdmi = &tpd_hdmi_ops; dssdev->dev = &pdev->dev; diff --git a/drivers/video/fbdev/omap2/displays-new/panel-dpi.c b/drivers/video/fbdev/omap2/omapfb/displays/panel-dpi.c index f7be3489f744..e780fd4f8b46 100644 --- a/drivers/video/fbdev/omap2/displays-new/panel-dpi.c +++ b/drivers/video/fbdev/omap2/omapfb/displays/panel-dpi.c @@ -83,8 +83,7 @@ static int panel_dpi_enable(struct omap_dss_device *dssdev) if (r) return r; - if (ddata->enable_gpio) - gpiod_set_value_cansleep(ddata->enable_gpio, 1); + gpiod_set_value_cansleep(ddata->enable_gpio, 1); if (gpio_is_valid(ddata->backlight_gpio)) gpio_set_value_cansleep(ddata->backlight_gpio, 1); @@ -102,12 +101,11 @@ static void panel_dpi_disable(struct omap_dss_device *dssdev) if (!omapdss_device_is_enabled(dssdev)) return; - if (ddata->enable_gpio) - gpiod_set_value_cansleep(ddata->enable_gpio, 0); - if (gpio_is_valid(ddata->backlight_gpio)) gpio_set_value_cansleep(ddata->backlight_gpio, 0); + gpiod_set_value_cansleep(ddata->enable_gpio, 0); + in->ops.dpi->disable(in); dssdev->state = OMAP_DSS_DISPLAY_DISABLED; diff --git a/drivers/video/fbdev/omap2/displays-new/panel-dsi-cm.c b/drivers/video/fbdev/omap2/omapfb/displays/panel-dsi-cm.c index 3414c2609320..3414c2609320 100644 --- a/drivers/video/fbdev/omap2/displays-new/panel-dsi-cm.c +++ b/drivers/video/fbdev/omap2/omapfb/displays/panel-dsi-cm.c diff --git a/drivers/video/fbdev/omap2/displays-new/panel-lgphilips-lb035q02.c b/drivers/video/fbdev/omap2/omapfb/displays/panel-lgphilips-lb035q02.c index 18eb60e9c9ec..18eb60e9c9ec 100644 --- a/drivers/video/fbdev/omap2/displays-new/panel-lgphilips-lb035q02.c +++ b/drivers/video/fbdev/omap2/omapfb/displays/panel-lgphilips-lb035q02.c diff --git a/drivers/video/fbdev/omap2/displays-new/panel-nec-nl8048hl11.c b/drivers/video/fbdev/omap2/omapfb/displays/panel-nec-nl8048hl11.c index 8a928c9a2fc9..8a928c9a2fc9 100644 --- a/drivers/video/fbdev/omap2/displays-new/panel-nec-nl8048hl11.c +++ b/drivers/video/fbdev/omap2/omapfb/displays/panel-nec-nl8048hl11.c diff --git a/drivers/video/fbdev/omap2/displays-new/panel-sharp-ls037v7dw01.c b/drivers/video/fbdev/omap2/omapfb/displays/panel-sharp-ls037v7dw01.c index abfd1f6e3327..abfd1f6e3327 100644 --- a/drivers/video/fbdev/omap2/displays-new/panel-sharp-ls037v7dw01.c +++ b/drivers/video/fbdev/omap2/omapfb/displays/panel-sharp-ls037v7dw01.c diff --git a/drivers/video/fbdev/omap2/displays-new/panel-sony-acx565akm.c b/drivers/video/fbdev/omap2/omapfb/displays/panel-sony-acx565akm.c index 31efcca801bd..31efcca801bd 100644 --- a/drivers/video/fbdev/omap2/displays-new/panel-sony-acx565akm.c +++ b/drivers/video/fbdev/omap2/omapfb/displays/panel-sony-acx565akm.c diff --git a/drivers/video/fbdev/omap2/displays-new/panel-tpo-td028ttec1.c b/drivers/video/fbdev/omap2/omapfb/displays/panel-tpo-td028ttec1.c index 4d657f3ab679..4d657f3ab679 100644 --- a/drivers/video/fbdev/omap2/displays-new/panel-tpo-td028ttec1.c +++ b/drivers/video/fbdev/omap2/omapfb/displays/panel-tpo-td028ttec1.c diff --git a/drivers/video/fbdev/omap2/displays-new/panel-tpo-td043mtea1.c b/drivers/video/fbdev/omap2/omapfb/displays/panel-tpo-td043mtea1.c index 68e3b68a2920..68e3b68a2920 100644 --- a/drivers/video/fbdev/omap2/displays-new/panel-tpo-td043mtea1.c +++ b/drivers/video/fbdev/omap2/omapfb/displays/panel-tpo-td043mtea1.c diff --git a/drivers/video/fbdev/omap2/dss/Kconfig b/drivers/video/fbdev/omap2/omapfb/dss/Kconfig index d1fa730c7d54..27d220212870 100644 --- a/drivers/video/fbdev/omap2/dss/Kconfig +++ b/drivers/video/fbdev/omap2/omapfb/dss/Kconfig @@ -1,17 +1,13 @@ -config OMAP2_DSS_INIT +config FB_OMAP2_DSS_INIT bool -menuconfig OMAP2_DSS - tristate "OMAP2+ Display Subsystem support" +config FB_OMAP2_DSS + tristate select VIDEOMODE_HELPERS - select OMAP2_DSS_INIT + select FB_OMAP2_DSS_INIT select HDMI - help - OMAP2+ Display Subsystem support. -if OMAP2_DSS - -config OMAP2_DSS_DEBUG +config FB_OMAP2_DSS_DEBUG bool "Debug support" default n help @@ -19,7 +15,7 @@ config OMAP2_DSS_DEBUG can also be enabled by setting CONFIG_DYNAMIC_DEBUG and then setting appropriate flags in <debugfs>/dynamic_debug/control. -config OMAP2_DSS_DEBUGFS +config FB_OMAP2_DSS_DEBUGFS bool "Debugfs filesystem support" depends on DEBUG_FS default n @@ -28,9 +24,9 @@ config OMAP2_DSS_DEBUGFS querying about clock configuration and register configuration of dss, dispc, dsi, hdmi and rfbi. -config OMAP2_DSS_COLLECT_IRQ_STATS +config FB_OMAP2_DSS_COLLECT_IRQ_STATS bool "Collect DSS IRQ statistics" - depends on OMAP2_DSS_DEBUGFS + depends on FB_OMAP2_DSS_DEBUGFS default n help Collect DSS IRQ statistics, printable via debugfs. @@ -39,13 +35,13 @@ config OMAP2_DSS_COLLECT_IRQ_STATS <debugfs>/omapdss/dispc_irq for DISPC interrupts, and <debugfs>/omapdss/dsi_irq for DSI interrupts. -config OMAP2_DSS_DPI +config FB_OMAP2_DSS_DPI bool "DPI support" default y help DPI Interface. This is the Parallel Display Interface. -config OMAP2_DSS_RFBI +config FB_OMAP2_DSS_RFBI bool "RFBI support" depends on BROKEN default n @@ -58,32 +54,32 @@ config OMAP2_DSS_RFBI See http://www.mipi.org/ for DBI specifications. -config OMAP2_DSS_VENC +config FB_OMAP2_DSS_VENC bool "VENC support" default y help OMAP Video Encoder support for S-Video and composite TV-out. -config OMAP2_DSS_HDMI_COMMON +config FB_OMAP2_DSS_HDMI_COMMON bool -config OMAP4_DSS_HDMI +config FB_OMAP4_DSS_HDMI bool "HDMI support for OMAP4" default y - select OMAP2_DSS_HDMI_COMMON + select FB_OMAP2_DSS_HDMI_COMMON help HDMI support for OMAP4 based SoCs. -config OMAP5_DSS_HDMI +config FB_OMAP5_DSS_HDMI bool "HDMI support for OMAP5" default n - select OMAP2_DSS_HDMI_COMMON + select FB_OMAP2_DSS_HDMI_COMMON help HDMI Interface for OMAP5 and similar cores. This adds the High Definition Multimedia Interface. See http://www.hdmi.org/ for HDMI specification. -config OMAP2_DSS_SDI +config FB_OMAP2_DSS_SDI bool "SDI support" default n help @@ -92,7 +88,7 @@ config OMAP2_DSS_SDI SDI is a high speed one-way display serial bus between the host processor and a display. -config OMAP2_DSS_DSI +config FB_OMAP2_DSS_DSI bool "DSI support" default n help @@ -103,7 +99,7 @@ config OMAP2_DSS_DSI See http://www.mipi.org/ for DSI specifications. -config OMAP2_DSS_MIN_FCK_PER_PCK +config FB_OMAP2_DSS_MIN_FCK_PER_PCK int "Minimum FCK/PCK ratio (for scaling)" range 0 32 default 0 @@ -121,7 +117,7 @@ config OMAP2_DSS_MIN_FCK_PER_PCK Max FCK is 173MHz, so this doesn't work if your PCK is very high. -config OMAP2_DSS_SLEEP_AFTER_VENC_RESET +config FB_OMAP2_DSS_SLEEP_AFTER_VENC_RESET bool "Sleep 20ms after VENC reset" default y help @@ -131,5 +127,3 @@ config OMAP2_DSS_SLEEP_AFTER_VENC_RESET This option enables the sleep, and is enabled by default. You can disable the sleep if it doesn't cause problems on your platform. - -endif diff --git a/drivers/video/fbdev/omap2/omapfb/dss/Makefile b/drivers/video/fbdev/omap2/omapfb/dss/Makefile new file mode 100644 index 000000000000..02308e24f3ef --- /dev/null +++ b/drivers/video/fbdev/omap2/omapfb/dss/Makefile @@ -0,0 +1,18 @@ +obj-$(CONFIG_FB_OMAP2_DSS_INIT) += omapdss-boot-init.o +obj-$(CONFIG_FB_OMAP2_DSS) += omapdss.o +# Core DSS files +omapdss-y := core.o dss.o dss_features.o dispc.o dispc_coefs.o display.o \ + output.o dss-of.o pll.o video-pll.o +# DSS compat layer files +omapdss-y += manager.o manager-sysfs.o overlay.o overlay-sysfs.o apply.o \ + dispc-compat.o display-sysfs.o +omapdss-$(CONFIG_FB_OMAP2_DSS_DPI) += dpi.o +omapdss-$(CONFIG_FB_OMAP2_DSS_RFBI) += rfbi.o +omapdss-$(CONFIG_FB_OMAP2_DSS_VENC) += venc.o +omapdss-$(CONFIG_FB_OMAP2_DSS_SDI) += sdi.o +omapdss-$(CONFIG_FB_OMAP2_DSS_DSI) += dsi.o +omapdss-$(CONFIG_FB_OMAP2_DSS_HDMI_COMMON) += hdmi_common.o hdmi_wp.o hdmi_pll.o \ + hdmi_phy.o +omapdss-$(CONFIG_FB_OMAP4_DSS_HDMI) += hdmi4.o hdmi4_core.o +omapdss-$(CONFIG_FB_OMAP5_DSS_HDMI) += hdmi5.o hdmi5_core.o +ccflags-$(CONFIG_FB_OMAP2_DSS_DEBUG) += -DDEBUG diff --git a/drivers/video/fbdev/omap2/dss/apply.c b/drivers/video/fbdev/omap2/omapfb/dss/apply.c index 663ccc3bf4e5..663ccc3bf4e5 100644 --- a/drivers/video/fbdev/omap2/dss/apply.c +++ b/drivers/video/fbdev/omap2/omapfb/dss/apply.c diff --git a/drivers/video/fbdev/omap2/dss/core.c b/drivers/video/fbdev/omap2/omapfb/dss/core.c index 54eeb507f9b3..5a87179b7312 100644 --- a/drivers/video/fbdev/omap2/dss/core.c +++ b/drivers/video/fbdev/omap2/omapfb/dss/core.c @@ -98,7 +98,7 @@ int dss_set_min_bus_tput(struct device *dev, unsigned long tput) return 0; } -#if defined(CONFIG_OMAP2_DSS_DEBUGFS) +#if defined(CONFIG_FB_OMAP2_DSS_DEBUGFS) static int dss_debug_show(struct seq_file *s, void *unused) { void (*func)(struct seq_file *) = s->private; @@ -150,7 +150,7 @@ int dss_debugfs_create_file(const char *name, void (*write)(struct seq_file *)) return PTR_ERR_OR_ZERO(d); } -#else /* CONFIG_OMAP2_DSS_DEBUGFS */ +#else /* CONFIG_FB_OMAP2_DSS_DEBUGFS */ static inline int dss_initialize_debugfs(void) { return 0; @@ -162,7 +162,7 @@ int dss_debugfs_create_file(const char *name, void (*write)(struct seq_file *)) { return 0; } -#endif /* CONFIG_OMAP2_DSS_DEBUGFS */ +#endif /* CONFIG_FB_OMAP2_DSS_DEBUGFS */ /* PLATFORM DEVICE */ static int omap_dss_pm_notif(struct notifier_block *b, unsigned long v, void *d) @@ -247,49 +247,49 @@ static struct platform_driver omap_dss_driver = { static int (*dss_output_drv_reg_funcs[])(void) __initdata = { dss_init_platform_driver, dispc_init_platform_driver, -#ifdef CONFIG_OMAP2_DSS_DSI +#ifdef CONFIG_FB_OMAP2_DSS_DSI dsi_init_platform_driver, #endif -#ifdef CONFIG_OMAP2_DSS_DPI +#ifdef CONFIG_FB_OMAP2_DSS_DPI dpi_init_platform_driver, #endif -#ifdef CONFIG_OMAP2_DSS_SDI +#ifdef CONFIG_FB_OMAP2_DSS_SDI sdi_init_platform_driver, #endif -#ifdef CONFIG_OMAP2_DSS_RFBI +#ifdef CONFIG_FB_OMAP2_DSS_RFBI rfbi_init_platform_driver, #endif -#ifdef CONFIG_OMAP2_DSS_VENC +#ifdef CONFIG_FB_OMAP2_DSS_VENC venc_init_platform_driver, #endif -#ifdef CONFIG_OMAP4_DSS_HDMI +#ifdef CONFIG_FB_OMAP4_DSS_HDMI hdmi4_init_platform_driver, #endif -#ifdef CONFIG_OMAP5_DSS_HDMI +#ifdef CONFIG_FB_OMAP5_DSS_HDMI hdmi5_init_platform_driver, #endif }; static void (*dss_output_drv_unreg_funcs[])(void) = { -#ifdef CONFIG_OMAP5_DSS_HDMI +#ifdef CONFIG_FB_OMAP5_DSS_HDMI hdmi5_uninit_platform_driver, #endif -#ifdef CONFIG_OMAP4_DSS_HDMI +#ifdef CONFIG_FB_OMAP4_DSS_HDMI hdmi4_uninit_platform_driver, #endif -#ifdef CONFIG_OMAP2_DSS_VENC +#ifdef CONFIG_FB_OMAP2_DSS_VENC venc_uninit_platform_driver, #endif -#ifdef CONFIG_OMAP2_DSS_RFBI +#ifdef CONFIG_FB_OMAP2_DSS_RFBI rfbi_uninit_platform_driver, #endif -#ifdef CONFIG_OMAP2_DSS_SDI +#ifdef CONFIG_FB_OMAP2_DSS_SDI sdi_uninit_platform_driver, #endif -#ifdef CONFIG_OMAP2_DSS_DPI +#ifdef CONFIG_FB_OMAP2_DSS_DPI dpi_uninit_platform_driver, #endif -#ifdef CONFIG_OMAP2_DSS_DSI +#ifdef CONFIG_FB_OMAP2_DSS_DSI dsi_uninit_platform_driver, #endif dispc_uninit_platform_driver, diff --git a/drivers/video/fbdev/omap2/dss/dispc-compat.c b/drivers/video/fbdev/omap2/omapfb/dss/dispc-compat.c index 633c461fbc6e..6607db37a5e4 100644 --- a/drivers/video/fbdev/omap2/dss/dispc-compat.c +++ b/drivers/video/fbdev/omap2/omapfb/dss/dispc-compat.c @@ -60,14 +60,14 @@ static struct { u32 error_irqs; struct work_struct error_work; -#ifdef CONFIG_OMAP2_DSS_COLLECT_IRQ_STATS +#ifdef CONFIG_FB_OMAP2_DSS_COLLECT_IRQ_STATS spinlock_t irq_stats_lock; struct dispc_irq_stats irq_stats; #endif } dispc_compat; -#ifdef CONFIG_OMAP2_DSS_COLLECT_IRQ_STATS +#ifdef CONFIG_FB_OMAP2_DSS_COLLECT_IRQ_STATS static void dispc_dump_irqs(struct seq_file *s) { unsigned long flags; @@ -279,7 +279,7 @@ static irqreturn_t omap_dispc_irq_handler(int irq, void *arg) return IRQ_NONE; } -#ifdef CONFIG_OMAP2_DSS_COLLECT_IRQ_STATS +#ifdef CONFIG_FB_OMAP2_DSS_COLLECT_IRQ_STATS spin_lock(&dispc_compat.irq_stats_lock); dispc_compat.irq_stats.irq_count++; dss_collect_irq_stats(irqstatus, dispc_compat.irq_stats.irqs); @@ -416,7 +416,7 @@ int dss_dispc_initialize_irq(void) { int r; -#ifdef CONFIG_OMAP2_DSS_COLLECT_IRQ_STATS +#ifdef CONFIG_FB_OMAP2_DSS_COLLECT_IRQ_STATS spin_lock_init(&dispc_compat.irq_stats_lock); dispc_compat.irq_stats.last_reset = jiffies; dss_debugfs_create_file("dispc_irq", dispc_dump_irqs); @@ -476,7 +476,7 @@ static void dispc_mgr_disable_lcd_out(enum omap_channel channel) int r; u32 irq; - if (dispc_mgr_is_enabled(channel) == false) + if (!dispc_mgr_is_enabled(channel)) return; /* @@ -524,7 +524,7 @@ static void dispc_mgr_enable_digit_out(void) int r; u32 irq_mask; - if (dispc_mgr_is_enabled(OMAP_DSS_CHANNEL_DIGIT) == true) + if (dispc_mgr_is_enabled(OMAP_DSS_CHANNEL_DIGIT)) return; /* @@ -562,7 +562,7 @@ static void dispc_mgr_disable_digit_out(void) u32 irq_mask; int num_irqs; - if (dispc_mgr_is_enabled(OMAP_DSS_CHANNEL_DIGIT) == false) + if (!dispc_mgr_is_enabled(OMAP_DSS_CHANNEL_DIGIT)) return; /* diff --git a/drivers/video/fbdev/omap2/dss/dispc-compat.h b/drivers/video/fbdev/omap2/omapfb/dss/dispc-compat.h index 14a69b3d4fb0..14a69b3d4fb0 100644 --- a/drivers/video/fbdev/omap2/dss/dispc-compat.h +++ b/drivers/video/fbdev/omap2/omapfb/dss/dispc-compat.h diff --git a/drivers/video/fbdev/omap2/dss/dispc.c b/drivers/video/fbdev/omap2/omapfb/dss/dispc.c index be716c9ffb88..5491e304f4fe 100644 --- a/drivers/video/fbdev/omap2/dss/dispc.c +++ b/drivers/video/fbdev/omap2/omapfb/dss/dispc.c @@ -99,6 +99,11 @@ struct dispc_features { /* PIXEL_INC is not added to the last pixel of a line */ bool last_pixel_inc_missing:1; + + /* POL_FREQ has ALIGN bit */ + bool supports_sync_align:1; + + bool has_writeback:1; }; #define DISPC_MAX_NR_FIFOS 5 @@ -246,6 +251,11 @@ struct color_conv_coef { int full_range; }; +static unsigned long dispc_fclk_rate(void); +static unsigned long dispc_core_clk_rate(void); +static unsigned long dispc_mgr_lclk_rate(enum omap_channel channel); +static unsigned long dispc_mgr_pclk_rate(enum omap_channel channel); + static unsigned long dispc_plane_pclk_rate(enum omap_plane plane); static unsigned long dispc_plane_lclk_rate(enum omap_plane plane); @@ -571,7 +581,7 @@ EXPORT_SYMBOL(dispc_mgr_go_busy); void dispc_mgr_go(enum omap_channel channel) { - WARN_ON(dispc_mgr_is_enabled(channel) == false); + WARN_ON(!dispc_mgr_is_enabled(channel)); WARN_ON(dispc_mgr_go_busy(channel)); DSSDBG("GO %s\n", mgr_desc[channel].name); @@ -707,19 +717,20 @@ static void dispc_setup_color_conv_coef(void) { int i; int num_ovl = dss_feat_get_num_ovls(); - int num_wb = dss_feat_get_num_wbs(); const struct color_conv_coef ctbl_bt601_5_ovl = { + /* YUV -> RGB */ 298, 409, 0, 298, -208, -100, 298, 0, 517, 0, }; const struct color_conv_coef ctbl_bt601_5_wb = { - 66, 112, -38, 129, -94, -74, 25, -18, 112, 0, + /* RGB -> YUV */ + 66, 129, 25, 112, -94, -18, -38, -74, 112, 0, }; for (i = 1; i < num_ovl; i++) dispc_ovl_write_color_conv_coef(i, &ctbl_bt601_5_ovl); - for (; i < num_wb; i++) - dispc_ovl_write_color_conv_coef(i, &ctbl_bt601_5_wb); + if (dispc.feat->has_writeback) + dispc_ovl_write_color_conv_coef(OMAP_DSS_WB, &ctbl_bt601_5_wb); } static void dispc_ovl_set_ba0(enum omap_plane plane, u32 paddr) @@ -970,6 +981,10 @@ void dispc_ovl_set_channel_out(enum omap_plane plane, enum omap_channel channel) return; } break; + case OMAP_DSS_CHANNEL_WB: + chan = 0; + chan2 = 3; + break; default: BUG(); return; @@ -988,7 +1003,6 @@ static enum omap_channel dispc_ovl_get_channel_out(enum omap_plane plane) { int shift; u32 val; - enum omap_channel channel; switch (plane) { case OMAP_DSS_GFX: @@ -1006,23 +1020,23 @@ static enum omap_channel dispc_ovl_get_channel_out(enum omap_plane plane) val = dispc_read_reg(DISPC_OVL_ATTRIBUTES(plane)); - if (dss_has_feature(FEAT_MGR_LCD3)) { - if (FLD_GET(val, 31, 30) == 0) - channel = FLD_GET(val, shift, shift); - else if (FLD_GET(val, 31, 30) == 1) - channel = OMAP_DSS_CHANNEL_LCD2; - else - channel = OMAP_DSS_CHANNEL_LCD3; - } else if (dss_has_feature(FEAT_MGR_LCD2)) { - if (FLD_GET(val, 31, 30) == 0) - channel = FLD_GET(val, shift, shift); - else - channel = OMAP_DSS_CHANNEL_LCD2; - } else { - channel = FLD_GET(val, shift, shift); - } + if (FLD_GET(val, shift, shift) == 1) + return OMAP_DSS_CHANNEL_DIGIT; + + if (!dss_has_feature(FEAT_MGR_LCD2)) + return OMAP_DSS_CHANNEL_LCD; - return channel; + switch (FLD_GET(val, 31, 30)) { + case 0: + default: + return OMAP_DSS_CHANNEL_LCD; + case 1: + return OMAP_DSS_CHANNEL_LCD2; + case 2: + return OMAP_DSS_CHANNEL_LCD3; + case 3: + return OMAP_DSS_CHANNEL_WB; + } } void dispc_wb_set_channel_in(enum dss_writeback_channel channel) @@ -1050,6 +1064,8 @@ static void dispc_configure_burst_sizes(void) /* Configure burst size always to maximum size */ for (i = 0; i < dss_feat_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); } static u32 dispc_ovl_get_burst_size(enum omap_plane plane) @@ -1196,6 +1212,17 @@ static void dispc_init_fifos(void) dispc_ovl_set_fifo_threshold(i, low, high); } + + if (dispc.feat->has_writeback) { + u32 low, high; + const bool use_fifomerge = false; + const bool manual_update = false; + + dispc_ovl_compute_fifo_thresholds(OMAP_DSS_WB, &low, &high, + use_fifomerge, manual_update); + + dispc_ovl_set_fifo_threshold(OMAP_DSS_WB, low, high); + } } static u32 dispc_ovl_get_fifo_size(enum omap_plane plane) @@ -1248,7 +1275,6 @@ void dispc_ovl_set_fifo_threshold(enum omap_plane plane, u32 low, u32 high) plane != OMAP_DSS_WB) dispc_write_reg(DISPC_OVL_PRELOAD(plane), min(high, 0xfffu)); } -EXPORT_SYMBOL(dispc_ovl_set_fifo_threshold); void dispc_enable_fifomerge(bool enable) { @@ -1307,7 +1333,6 @@ void dispc_ovl_compute_fifo_thresholds(enum omap_plane plane, *fifo_high = total_fifo_size - buf_unit; } } -EXPORT_SYMBOL(dispc_ovl_compute_fifo_thresholds); static void dispc_ovl_set_mflag(enum omap_plane plane, bool enable) { @@ -1364,6 +1389,25 @@ static void dispc_init_mflag(void) dispc_ovl_set_mflag_threshold(i, low, high); } + + if (dispc.feat->has_writeback) { + u32 size = dispc_ovl_get_fifo_size(OMAP_DSS_WB); + u32 unit = dss_feat_get_buffer_size_unit(); + u32 low, high; + + dispc_ovl_set_mflag(OMAP_DSS_WB, true); + + /* + * Simulation team suggests below thesholds: + * HT = fifosize * 5 / 8; + * LT = fifosize * 4 / 8; + */ + + low = size * 4 / 8 / unit; + high = size * 5 / 8 / unit; + + dispc_ovl_set_mflag_threshold(OMAP_DSS_WB, low, high); + } } static void dispc_ovl_set_fir(enum omap_plane plane, @@ -2438,7 +2482,7 @@ static int dispc_ovl_calc_scaling(unsigned long pclk, unsigned long lclk, if (width == out_width && height == out_height) return 0; - if (pclk == 0 || mgr_timings->pixelclock == 0) { + if (!mem_to_mem && (pclk == 0 || mgr_timings->pixelclock == 0)) { DSSERR("cannot calculate scaling settings: pclk is zero\n"); return -EINVAL; } @@ -2816,8 +2860,25 @@ int dispc_wb_setup(const struct omap_dss_writeback_info *wi, l = dispc_read_reg(DISPC_OVL_ATTRIBUTES(plane)); l = FLD_MOD(l, truncation, 10, 10); /* TRUNCATIONENABLE */ l = FLD_MOD(l, mem_to_mem, 19, 19); /* WRITEBACKMODE */ + if (mem_to_mem) + l = FLD_MOD(l, 1, 26, 24); /* CAPTUREMODE */ + else + l = FLD_MOD(l, 0, 26, 24); /* CAPTUREMODE */ dispc_write_reg(DISPC_OVL_ATTRIBUTES(plane), l); + if (mem_to_mem) { + /* WBDELAYCOUNT */ + REG_FLD_MOD(DISPC_OVL_ATTRIBUTES2(plane), 0, 7, 0); + } else { + int wbdelay; + + wbdelay = min(mgr_timings->vfp + mgr_timings->vsw + + mgr_timings->vbp, 255); + + /* WBDELAYCOUNT */ + REG_FLD_MOD(DISPC_OVL_ATTRIBUTES2(plane), wbdelay, 7, 0); + } + return r; } @@ -2896,7 +2957,7 @@ static void dispc_mgr_set_lcd_type_tft(enum omap_channel channel) mgr_fld_write(channel, DISPC_MGR_FLD_STNTFT, 1); } -void dispc_set_loadmode(enum omap_dss_load_mode mode) +static void dispc_set_loadmode(enum omap_dss_load_mode mode) { REG_FLD_MOD(DISPC_CONFIG, mode, 2, 1); } @@ -3163,6 +3224,10 @@ static void _dispc_mgr_set_lcd_timings(enum omap_channel channel, int hsw, FLD_VAL(hs, 13, 13) | FLD_VAL(vs, 12, 12); + /* always set ALIGN bit when available */ + if (dispc.feat->supports_sync_align) + l |= (1 << 18); + dispc_write_reg(DISPC_POL_FREQ(channel), l); if (dispc.syscon_pol) { @@ -3220,7 +3285,7 @@ void dispc_mgr_set_timings(enum omap_channel channel, DSSDBG("hsync %luHz, vsync %luHz\n", ht, vt); } else { - if (t.interlace == true) + if (t.interlace) t.y_res /= 2; } @@ -3237,7 +3302,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) == false && + if (!dss_has_feature(FEAT_CORE_CLK_DIV) && channel == OMAP_DSS_CHANNEL_LCD) dispc.core_clk_rate = dispc_fclk_rate() / lck_div; } @@ -3251,7 +3316,7 @@ static void dispc_mgr_get_lcd_divisor(enum omap_channel channel, int *lck_div, *pck_div = FLD_GET(l, 7, 0); } -unsigned long dispc_fclk_rate(void) +static unsigned long dispc_fclk_rate(void) { struct dss_pll *pll; unsigned long r = 0; @@ -3282,7 +3347,7 @@ unsigned long dispc_fclk_rate(void) return r; } -unsigned long dispc_mgr_lclk_rate(enum omap_channel channel) +static unsigned long dispc_mgr_lclk_rate(enum omap_channel channel) { struct dss_pll *pll; int lcd; @@ -3323,7 +3388,7 @@ unsigned long dispc_mgr_lclk_rate(enum omap_channel channel) } } -unsigned long dispc_mgr_pclk_rate(enum omap_channel channel) +static unsigned long dispc_mgr_pclk_rate(enum omap_channel channel) { unsigned long r; @@ -3348,7 +3413,7 @@ void dispc_set_tv_pclk(unsigned long pclk) dispc.tv_pclk_rate = pclk; } -unsigned long dispc_core_clk_rate(void) +static unsigned long dispc_core_clk_rate(void) { return dispc.core_clk_rate; } @@ -3448,6 +3513,7 @@ static void dispc_dump_regs(struct seq_file *s) [OMAP_DSS_VIDEO1] = "VID1", [OMAP_DSS_VIDEO2] = "VID2", [OMAP_DSS_VIDEO3] = "VID3", + [OMAP_DSS_WB] = "WB", }; const char **p_names; @@ -3554,6 +3620,35 @@ static void dispc_dump_regs(struct seq_file *s) DUMPREG(i, DISPC_OVL_ATTRIBUTES2); } + if (dispc.feat->has_writeback) { + i = OMAP_DSS_WB; + DUMPREG(i, DISPC_OVL_BA0); + DUMPREG(i, DISPC_OVL_BA1); + DUMPREG(i, DISPC_OVL_SIZE); + DUMPREG(i, DISPC_OVL_ATTRIBUTES); + DUMPREG(i, DISPC_OVL_FIFO_THRESHOLD); + DUMPREG(i, DISPC_OVL_FIFO_SIZE_STATUS); + DUMPREG(i, DISPC_OVL_ROW_INC); + DUMPREG(i, DISPC_OVL_PIXEL_INC); + + if (dss_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)) { + 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)) + DUMPREG(i, DISPC_OVL_ATTRIBUTES2); + } + #undef DISPC_REG #undef DUMPREG @@ -3626,8 +3721,8 @@ bool dispc_div_calc(unsigned long dispc, unsigned min_fck_per_pck; unsigned long fck; -#ifdef CONFIG_OMAP2_DSS_MIN_FCK_PER_PCK - min_fck_per_pck = CONFIG_OMAP2_DSS_MIN_FCK_PER_PCK; +#ifdef CONFIG_FB_OMAP2_DSS_MIN_FCK_PER_PCK + min_fck_per_pck = CONFIG_FB_OMAP2_DSS_MIN_FCK_PER_PCK; #else min_fck_per_pck = 0; #endif @@ -3854,6 +3949,8 @@ static const struct dispc_features omap44xx_dispc_feats = { .num_fifos = 5, .gfx_fifo_workaround = true, .set_max_preload = true, + .supports_sync_align = true, + .has_writeback = true, }; static const struct dispc_features omap54xx_dispc_feats = { @@ -3875,6 +3972,8 @@ static const struct dispc_features omap54xx_dispc_feats = { .gfx_fifo_workaround = true, .mstandby_workaround = true, .set_max_preload = true, + .supports_sync_align = true, + .has_writeback = true, }; static int dispc_init_features(struct platform_device *pdev) diff --git a/drivers/video/fbdev/omap2/dss/dispc.h b/drivers/video/fbdev/omap2/omapfb/dss/dispc.h index 3043d6e0a5f9..483744223dd1 100644 --- a/drivers/video/fbdev/omap2/dss/dispc.h +++ b/drivers/video/fbdev/omap2/omapfb/dss/dispc.h @@ -908,6 +908,8 @@ static inline u16 DISPC_MFLAG_THRESHOLD_OFFSET(enum omap_plane plane) return 0x0868; case OMAP_DSS_VIDEO3: return 0x086c; + case OMAP_DSS_WB: + return 0x0870; default: BUG(); return 0; diff --git a/drivers/video/fbdev/omap2/dss/dispc_coefs.c b/drivers/video/fbdev/omap2/omapfb/dss/dispc_coefs.c index 038c15b04215..038c15b04215 100644 --- a/drivers/video/fbdev/omap2/dss/dispc_coefs.c +++ b/drivers/video/fbdev/omap2/omapfb/dss/dispc_coefs.c diff --git a/drivers/video/fbdev/omap2/dss/display-sysfs.c b/drivers/video/fbdev/omap2/omapfb/dss/display-sysfs.c index 6ad0991f8259..75b5286029ee 100644 --- a/drivers/video/fbdev/omap2/dss/display-sysfs.c +++ b/drivers/video/fbdev/omap2/omapfb/dss/display-sysfs.c @@ -120,7 +120,7 @@ static ssize_t display_timings_store(struct omap_dss_device *dssdev, return -ENOENT; found = 0; -#ifdef CONFIG_OMAP2_DSS_VENC +#ifdef CONFIG_FB_OMAP2_DSS_VENC if (strncmp("pal", buf, 3) == 0) { t = omap_dss_pal_timings; found = 1; diff --git a/drivers/video/fbdev/omap2/dss/display.c b/drivers/video/fbdev/omap2/omapfb/dss/display.c index ef5b9027985d..ef5b9027985d 100644 --- a/drivers/video/fbdev/omap2/dss/display.c +++ b/drivers/video/fbdev/omap2/omapfb/dss/display.c diff --git a/drivers/video/fbdev/omap2/dss/dpi.c b/drivers/video/fbdev/omap2/omapfb/dss/dpi.c index fb45b6432968..7953e6a52346 100644 --- a/drivers/video/fbdev/omap2/dss/dpi.c +++ b/drivers/video/fbdev/omap2/omapfb/dss/dpi.c @@ -395,7 +395,7 @@ static int dpi_display_enable(struct omap_dss_device *dssdev) goto err_no_reg; } - if (out == NULL || out->manager == NULL) { + if (out->manager == NULL) { DSSERR("failed to enable display: no output/manager\n"); r = -ENODEV; goto err_no_out_mgr; diff --git a/drivers/video/fbdev/omap2/dss/dsi.c b/drivers/video/fbdev/omap2/omapfb/dss/dsi.c index b3606def5b7b..0eec073b3919 100644 --- a/drivers/video/fbdev/omap2/dss/dsi.c +++ b/drivers/video/fbdev/omap2/omapfb/dss/dsi.c @@ -144,7 +144,7 @@ struct dsi_reg { u16 module; u16 idx; }; #define DSI_IRQ_TA_TIMEOUT (1 << 20) #define DSI_IRQ_ERROR_MASK \ (DSI_IRQ_HS_TX_TIMEOUT | DSI_IRQ_LP_RX_TIMEOUT | DSI_IRQ_SYNC_LOST | \ - DSI_IRQ_TA_TIMEOUT | DSI_IRQ_SYNC_LOST) + DSI_IRQ_TA_TIMEOUT) #define DSI_IRQ_CHANNEL_MASK 0xf /* Virtual channel interrupts */ @@ -369,7 +369,7 @@ struct dsi_data { int debug_read; int debug_write; -#ifdef CONFIG_OMAP2_DSS_COLLECT_IRQ_STATS +#ifdef CONFIG_FB_OMAP2_DSS_COLLECT_IRQ_STATS spinlock_t irq_stats_lock; struct dsi_irq_stats irq_stats; #endif @@ -698,7 +698,7 @@ static void print_irq_status_cio(u32 status) #undef PIS } -#ifdef CONFIG_OMAP2_DSS_COLLECT_IRQ_STATS +#ifdef CONFIG_FB_OMAP2_DSS_COLLECT_IRQ_STATS static void dsi_collect_irq_stats(struct platform_device *dsidev, u32 irqstatus, u32 *vcstatus, u32 ciostatus) { @@ -1551,7 +1551,7 @@ void dsi_dump_clocks(struct seq_file *s) } } -#ifdef CONFIG_OMAP2_DSS_COLLECT_IRQ_STATS +#ifdef CONFIG_FB_OMAP2_DSS_COLLECT_IRQ_STATS static void dsi_dump_dsidev_irqs(struct platform_device *dsidev, struct seq_file *s) { @@ -3833,7 +3833,7 @@ static int dsi_enable_video_output(struct omap_dss_device *dssdev, int channel) u16 word_count; int r; - if (out == NULL || out->manager == NULL) { + if (out->manager == NULL) { DSSERR("failed to enable display: no output/manager\n"); return -ENODEV; } @@ -5296,7 +5296,7 @@ static int dsi_bind(struct device *dev, struct device *master, void *data) spin_lock_init(&dsi->errors_lock); dsi->errors = 0; -#ifdef CONFIG_OMAP2_DSS_COLLECT_IRQ_STATS +#ifdef CONFIG_FB_OMAP2_DSS_COLLECT_IRQ_STATS spin_lock_init(&dsi->irq_stats_lock); dsi->irq_stats.last_reset = jiffies; #endif @@ -5468,7 +5468,7 @@ static int dsi_bind(struct device *dev, struct device *master, void *data) else if (dsi->module_id == 1) dss_debugfs_create_file("dsi2_regs", dsi2_dump_regs); -#ifdef CONFIG_OMAP2_DSS_COLLECT_IRQ_STATS +#ifdef CONFIG_FB_OMAP2_DSS_COLLECT_IRQ_STATS if (dsi->module_id == 0) dss_debugfs_create_file("dsi1_irqs", dsi1_dump_irqs); else if (dsi->module_id == 1) diff --git a/drivers/video/fbdev/omap2/dss/dss-of.c b/drivers/video/fbdev/omap2/omapfb/dss/dss-of.c index bf407b6ba15c..bf407b6ba15c 100644 --- a/drivers/video/fbdev/omap2/dss/dss-of.c +++ b/drivers/video/fbdev/omap2/omapfb/dss/dss-of.c diff --git a/drivers/video/fbdev/omap2/dss/dss.c b/drivers/video/fbdev/omap2/omapfb/dss/dss.c index 9200a8668b49..0078c4d1fc31 100644 --- a/drivers/video/fbdev/omap2/dss/dss.c +++ b/drivers/video/fbdev/omap2/omapfb/dss/dss.c @@ -793,12 +793,12 @@ void dss_runtime_put(void) } /* DEBUGFS */ -#if defined(CONFIG_OMAP2_DSS_DEBUGFS) +#if defined(CONFIG_FB_OMAP2_DSS_DEBUGFS) void dss_debug_dump_clocks(struct seq_file *s) { dss_dump_clocks(s); dispc_dump_clocks(s); -#ifdef CONFIG_OMAP2_DSS_DSI +#ifdef CONFIG_FB_OMAP2_DSS_DSI dsi_dump_clocks(s); #endif } @@ -1144,7 +1144,7 @@ static int dss_bind(struct device *dev) dss_select_dispc_clk_source(OMAP_DSS_CLK_SRC_FCK); -#ifdef CONFIG_OMAP2_DSS_VENC +#ifdef CONFIG_FB_OMAP2_DSS_VENC REG_FLD_MOD(DSS_CONTROL, 1, 4, 4); /* venc dac demen */ REG_FLD_MOD(DSS_CONTROL, 1, 3, 3); /* venc clock 4x enable */ REG_FLD_MOD(DSS_CONTROL, 0, 2, 2); /* venc clock mode = normal */ @@ -1264,12 +1264,18 @@ static int dss_runtime_suspend(struct device *dev) { dss_save_context(); dss_set_min_bus_tput(dev, 0); + + pinctrl_pm_select_sleep_state(dev); + return 0; } static int dss_runtime_resume(struct device *dev) { int r; + + pinctrl_pm_select_default_state(dev); + /* * Set an arbitrarily high tput request to ensure OPP100. * What we should really do is to make a request to stay in OPP100, diff --git a/drivers/video/fbdev/omap2/dss/dss.h b/drivers/video/fbdev/omap2/omapfb/dss/dss.h index 2406bcdb831a..b9066afee301 100644 --- a/drivers/video/fbdev/omap2/dss/dss.h +++ b/drivers/video/fbdev/omap2/omapfb/dss/dss.h @@ -278,7 +278,7 @@ void dss_video_pll_uninit(struct dss_pll *pll); struct device_node *dss_of_port_get_parent_device(struct device_node *port); u32 dss_of_port_get_port_number(struct device_node *port); -#if defined(CONFIG_OMAP2_DSS_DEBUGFS) +#if defined(CONFIG_FB_OMAP2_DSS_DEBUGFS) void dss_debug_dump_clocks(struct seq_file *s); #endif @@ -311,7 +311,7 @@ bool dss_div_calc(unsigned long pck, unsigned long fck_min, int sdi_init_platform_driver(void) __init; void sdi_uninit_platform_driver(void); -#ifdef CONFIG_OMAP2_DSS_SDI +#ifdef CONFIG_FB_OMAP2_DSS_SDI int sdi_init_port(struct platform_device *pdev, struct device_node *port); void sdi_uninit_port(struct device_node *port); #else @@ -327,7 +327,7 @@ static inline void sdi_uninit_port(struct device_node *port) /* DSI */ -#ifdef CONFIG_OMAP2_DSS_DSI +#ifdef CONFIG_FB_OMAP2_DSS_DSI struct dentry; struct file_operations; @@ -343,7 +343,8 @@ u8 dsi_get_pixel_size(enum omap_dss_dsi_pixel_format fmt); #else static inline u8 dsi_get_pixel_size(enum omap_dss_dsi_pixel_format fmt) { - WARN("%s: DSI not compiled in, returning pixel_size as 0\n", __func__); + WARN(1, "%s: DSI not compiled in, returning pixel_size as 0\n", + __func__); return 0; } #endif @@ -352,7 +353,7 @@ static inline u8 dsi_get_pixel_size(enum omap_dss_dsi_pixel_format fmt) int dpi_init_platform_driver(void) __init; void dpi_uninit_platform_driver(void); -#ifdef CONFIG_OMAP2_DSS_DPI +#ifdef CONFIG_FB_OMAP2_DSS_DPI int dpi_init_port(struct platform_device *pdev, struct device_node *port); void dpi_uninit_port(struct device_node *port); #else @@ -378,7 +379,6 @@ void dispc_lcd_enable_signal(bool enable); void dispc_pck_free_enable(bool enable); void dispc_enable_fifomerge(bool enable); void dispc_enable_gamma_table(bool enable); -void dispc_set_loadmode(enum omap_dss_load_mode mode); typedef bool (*dispc_div_calc_func)(int lckd, int pckd, unsigned long lck, unsigned long pck, void *data); @@ -388,7 +388,6 @@ bool dispc_div_calc(unsigned long dispc, bool dispc_mgr_timings_ok(enum omap_channel channel, const struct omap_video_timings *timings); -unsigned long dispc_fclk_rate(void); int dispc_calc_clock_rates(unsigned long dispc_fclk_rate, struct dispc_clock_info *cinfo); @@ -398,9 +397,6 @@ void dispc_ovl_compute_fifo_thresholds(enum omap_plane plane, u32 *fifo_low, u32 *fifo_high, bool use_fifomerge, bool manual_update); -unsigned long dispc_mgr_lclk_rate(enum omap_channel channel); -unsigned long dispc_mgr_pclk_rate(enum omap_channel channel); -unsigned long dispc_core_clk_rate(void); void dispc_mgr_set_clock_div(enum omap_channel channel, const struct dispc_clock_info *cinfo); int dispc_mgr_get_clock_div(enum omap_channel channel, @@ -432,7 +428,7 @@ int rfbi_init_platform_driver(void) __init; void rfbi_uninit_platform_driver(void); -#ifdef CONFIG_OMAP2_DSS_COLLECT_IRQ_STATS +#ifdef CONFIG_FB_OMAP2_DSS_COLLECT_IRQ_STATS static inline void dss_collect_irq_stats(u32 irqstatus, unsigned *irq_arr) { int b; diff --git a/drivers/video/fbdev/omap2/dss/dss_features.c b/drivers/video/fbdev/omap2/omapfb/dss/dss_features.c index b0b6dfd657bf..c886a2927f73 100644 --- a/drivers/video/fbdev/omap2/dss/dss_features.c +++ b/drivers/video/fbdev/omap2/omapfb/dss/dss_features.c @@ -46,7 +46,6 @@ struct omap_dss_features { const int num_mgrs; const int num_ovls; - const int num_wbs; const enum omap_display_type *supported_displays; const enum omap_dss_output_id *supported_outputs; const enum omap_color_mode *supported_color_modes; @@ -735,7 +734,6 @@ static const struct omap_dss_features omap4430_es1_0_dss_features = { .num_mgrs = 3, .num_ovls = 4, - .num_wbs = 1, .supported_displays = omap4_dss_supported_displays, .supported_outputs = omap4_dss_supported_outputs, .supported_color_modes = omap4_dss_supported_color_modes, @@ -757,7 +755,6 @@ static const struct omap_dss_features omap4430_es2_0_1_2_dss_features = { .num_mgrs = 3, .num_ovls = 4, - .num_wbs = 1, .supported_displays = omap4_dss_supported_displays, .supported_outputs = omap4_dss_supported_outputs, .supported_color_modes = omap4_dss_supported_color_modes, @@ -779,7 +776,6 @@ static const struct omap_dss_features omap4_dss_features = { .num_mgrs = 3, .num_ovls = 4, - .num_wbs = 1, .supported_displays = omap4_dss_supported_displays, .supported_outputs = omap4_dss_supported_outputs, .supported_color_modes = omap4_dss_supported_color_modes, @@ -825,11 +821,6 @@ int dss_feat_get_num_ovls(void) } EXPORT_SYMBOL(dss_feat_get_num_ovls); -int dss_feat_get_num_wbs(void) -{ - return omap_current_dss_features->num_wbs; -} - unsigned long dss_feat_get_param_min(enum dss_range_param param) { return omap_current_dss_features->dss_params[param].min; @@ -844,13 +835,11 @@ enum omap_display_type dss_feat_get_supported_displays(enum omap_channel channel { return omap_current_dss_features->supported_displays[channel]; } -EXPORT_SYMBOL(dss_feat_get_supported_displays); enum omap_dss_output_id dss_feat_get_supported_outputs(enum omap_channel channel) { return omap_current_dss_features->supported_outputs[channel]; } -EXPORT_SYMBOL(dss_feat_get_supported_outputs); enum omap_color_mode dss_feat_get_supported_color_modes(enum omap_plane plane) { diff --git a/drivers/video/fbdev/omap2/dss/dss_features.h b/drivers/video/fbdev/omap2/omapfb/dss/dss_features.h index 100f7a2d0638..3d67d39f192f 100644 --- a/drivers/video/fbdev/omap2/dss/dss_features.h +++ b/drivers/video/fbdev/omap2/omapfb/dss/dss_features.h @@ -86,7 +86,6 @@ enum dss_range_param { }; /* DSS Feature Functions */ -int dss_feat_get_num_wbs(void); 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 plane); @@ -102,4 +101,8 @@ bool dss_feat_rotation_type_supported(enum omap_dss_rotation_type rot_type); 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); + #endif diff --git a/drivers/video/fbdev/omap2/dss/hdmi.h b/drivers/video/fbdev/omap2/omapfb/dss/hdmi.h index 53616b02b613..53616b02b613 100644 --- a/drivers/video/fbdev/omap2/dss/hdmi.h +++ b/drivers/video/fbdev/omap2/omapfb/dss/hdmi.h diff --git a/drivers/video/fbdev/omap2/dss/hdmi4.c b/drivers/video/fbdev/omap2/omapfb/dss/hdmi4.c index 94c8d5549b4c..7103c659a534 100644 --- a/drivers/video/fbdev/omap2/dss/hdmi4.c +++ b/drivers/video/fbdev/omap2/omapfb/dss/hdmi4.c @@ -343,7 +343,7 @@ static int hdmi_display_enable(struct omap_dss_device *dssdev) mutex_lock(&hdmi.lock); - if (out == NULL || out->manager == NULL) { + if (out->manager == NULL) { DSSERR("failed to enable display: no output/manager\n"); r = -ENODEV; goto err0; diff --git a/drivers/video/fbdev/omap2/dss/hdmi4_core.c b/drivers/video/fbdev/omap2/omapfb/dss/hdmi4_core.c index fa72e735dad2..fa72e735dad2 100644 --- a/drivers/video/fbdev/omap2/dss/hdmi4_core.c +++ b/drivers/video/fbdev/omap2/omapfb/dss/hdmi4_core.c diff --git a/drivers/video/fbdev/omap2/dss/hdmi4_core.h b/drivers/video/fbdev/omap2/omapfb/dss/hdmi4_core.h index a069f96ec6f6..a069f96ec6f6 100644 --- a/drivers/video/fbdev/omap2/dss/hdmi4_core.h +++ b/drivers/video/fbdev/omap2/omapfb/dss/hdmi4_core.h diff --git a/drivers/video/fbdev/omap2/dss/hdmi5.c b/drivers/video/fbdev/omap2/omapfb/dss/hdmi5.c index b59ba7902be1..a955a2c4c061 100644 --- a/drivers/video/fbdev/omap2/dss/hdmi5.c +++ b/drivers/video/fbdev/omap2/omapfb/dss/hdmi5.c @@ -373,7 +373,7 @@ static int hdmi_display_enable(struct omap_dss_device *dssdev) mutex_lock(&hdmi.lock); - if (out == NULL || out->manager == NULL) { + if (out->manager == NULL) { DSSERR("failed to enable display: no output/manager\n"); r = -ENODEV; goto err0; diff --git a/drivers/video/fbdev/omap2/dss/hdmi5_core.c b/drivers/video/fbdev/omap2/omapfb/dss/hdmi5_core.c index 8ea531d2652c..8ea531d2652c 100644 --- a/drivers/video/fbdev/omap2/dss/hdmi5_core.c +++ b/drivers/video/fbdev/omap2/omapfb/dss/hdmi5_core.c diff --git a/drivers/video/fbdev/omap2/dss/hdmi5_core.h b/drivers/video/fbdev/omap2/omapfb/dss/hdmi5_core.h index f2f1022c5516..f2f1022c5516 100644 --- a/drivers/video/fbdev/omap2/dss/hdmi5_core.h +++ b/drivers/video/fbdev/omap2/omapfb/dss/hdmi5_core.h diff --git a/drivers/video/fbdev/omap2/dss/hdmi_common.c b/drivers/video/fbdev/omap2/omapfb/dss/hdmi_common.c index 1b8fcc6c4ba1..1b8fcc6c4ba1 100644 --- a/drivers/video/fbdev/omap2/dss/hdmi_common.c +++ b/drivers/video/fbdev/omap2/omapfb/dss/hdmi_common.c diff --git a/drivers/video/fbdev/omap2/dss/hdmi_phy.c b/drivers/video/fbdev/omap2/omapfb/dss/hdmi_phy.c index 1f5d19c119ce..1f5d19c119ce 100644 --- a/drivers/video/fbdev/omap2/dss/hdmi_phy.c +++ b/drivers/video/fbdev/omap2/omapfb/dss/hdmi_phy.c diff --git a/drivers/video/fbdev/omap2/dss/hdmi_pll.c b/drivers/video/fbdev/omap2/omapfb/dss/hdmi_pll.c index 06e23a7c432c..06e23a7c432c 100644 --- a/drivers/video/fbdev/omap2/dss/hdmi_pll.c +++ b/drivers/video/fbdev/omap2/omapfb/dss/hdmi_pll.c diff --git a/drivers/video/fbdev/omap2/dss/hdmi_wp.c b/drivers/video/fbdev/omap2/omapfb/dss/hdmi_wp.c index 7c544bc56fb5..7c544bc56fb5 100644 --- a/drivers/video/fbdev/omap2/dss/hdmi_wp.c +++ b/drivers/video/fbdev/omap2/omapfb/dss/hdmi_wp.c diff --git a/drivers/video/fbdev/omap2/dss/manager-sysfs.c b/drivers/video/fbdev/omap2/omapfb/dss/manager-sysfs.c index a7414fb12830..a7414fb12830 100644 --- a/drivers/video/fbdev/omap2/dss/manager-sysfs.c +++ b/drivers/video/fbdev/omap2/omapfb/dss/manager-sysfs.c diff --git a/drivers/video/fbdev/omap2/dss/manager.c b/drivers/video/fbdev/omap2/omapfb/dss/manager.c index 1aac9b4191a9..08a67f4f6a20 100644 --- a/drivers/video/fbdev/omap2/dss/manager.c +++ b/drivers/video/fbdev/omap2/omapfb/dss/manager.c @@ -210,7 +210,7 @@ static int dss_mgr_check_lcd_config(struct omap_overlay_manager *mgr, return -EINVAL; /* fifohandcheck should be used only with stallmode */ - if (stallmode == false && fifohandcheck == true) + if (!stallmode && fifohandcheck) return -EINVAL; /* diff --git a/drivers/video/fbdev/omap2/dss/omapdss-boot-init.c b/drivers/video/fbdev/omap2/omapfb/dss/omapdss-boot-init.c index 8b6f6d5fdd68..136d30484d02 100644 --- a/drivers/video/fbdev/omap2/dss/omapdss-boot-init.c +++ b/drivers/video/fbdev/omap2/omapfb/dss/omapdss-boot-init.c @@ -199,10 +199,8 @@ static int __init omapdss_boot_init(void) omapdss_walk_device(dss, true); for_each_available_child_of_node(dss, child) { - if (!of_find_property(child, "compatible", NULL)) { - of_node_put(child); + if (!of_find_property(child, "compatible", NULL)) continue; - } omapdss_walk_device(child, true); } diff --git a/drivers/video/fbdev/omap2/dss/output.c b/drivers/video/fbdev/omap2/omapfb/dss/output.c index 16072159bd24..16072159bd24 100644 --- a/drivers/video/fbdev/omap2/dss/output.c +++ b/drivers/video/fbdev/omap2/omapfb/dss/output.c diff --git a/drivers/video/fbdev/omap2/dss/overlay-sysfs.c b/drivers/video/fbdev/omap2/omapfb/dss/overlay-sysfs.c index 4cc5ddebfb34..4cc5ddebfb34 100644 --- a/drivers/video/fbdev/omap2/dss/overlay-sysfs.c +++ b/drivers/video/fbdev/omap2/omapfb/dss/overlay-sysfs.c diff --git a/drivers/video/fbdev/omap2/dss/overlay.c b/drivers/video/fbdev/omap2/omapfb/dss/overlay.c index 2f7cee985cdd..2f7cee985cdd 100644 --- a/drivers/video/fbdev/omap2/dss/overlay.c +++ b/drivers/video/fbdev/omap2/omapfb/dss/overlay.c diff --git a/drivers/video/fbdev/omap2/dss/pll.c b/drivers/video/fbdev/omap2/omapfb/dss/pll.c index f974ddcd3b6e..f974ddcd3b6e 100644 --- a/drivers/video/fbdev/omap2/dss/pll.c +++ b/drivers/video/fbdev/omap2/omapfb/dss/pll.c diff --git a/drivers/video/fbdev/omap2/dss/rfbi.c b/drivers/video/fbdev/omap2/omapfb/dss/rfbi.c index 1525a494d057..aea6a1d0fb20 100644 --- a/drivers/video/fbdev/omap2/dss/rfbi.c +++ b/drivers/video/fbdev/omap2/omapfb/dss/rfbi.c @@ -880,7 +880,7 @@ static int rfbi_display_enable(struct omap_dss_device *dssdev) struct omap_dss_device *out = &rfbi.output; int r; - if (out == NULL || out->manager == NULL) { + if (out->manager == NULL) { DSSERR("failed to enable display: no output/manager\n"); return -ENODEV; } diff --git a/drivers/video/fbdev/omap2/dss/sdi.c b/drivers/video/fbdev/omap2/omapfb/dss/sdi.c index 5843580a1deb..d747cc6b59e1 100644 --- a/drivers/video/fbdev/omap2/dss/sdi.c +++ b/drivers/video/fbdev/omap2/omapfb/dss/sdi.c @@ -136,7 +136,7 @@ static int sdi_display_enable(struct omap_dss_device *dssdev) unsigned long pck; int r; - if (out == NULL || out->manager == NULL) { + if (out->manager == NULL) { DSSERR("failed to enable display: no output/manager\n"); return -ENODEV; } diff --git a/drivers/video/fbdev/omap2/dss/venc.c b/drivers/video/fbdev/omap2/omapfb/dss/venc.c index d05a54922ba6..26e0ee30adf8 100644 --- a/drivers/video/fbdev/omap2/dss/venc.c +++ b/drivers/video/fbdev/omap2/omapfb/dss/venc.c @@ -275,12 +275,6 @@ const struct omap_video_timings omap_dss_pal_timings = { .vbp = 41, .interlace = true, - - .hsync_level = OMAPDSS_SIG_ACTIVE_LOW, - .vsync_level = OMAPDSS_SIG_ACTIVE_LOW, - .data_pclk_edge = OMAPDSS_DRIVE_SIG_RISING_EDGE, - .de_level = OMAPDSS_SIG_ACTIVE_HIGH, - .sync_pclk_edge = OMAPDSS_DRIVE_SIG_FALLING_EDGE, }; EXPORT_SYMBOL(omap_dss_pal_timings); @@ -296,12 +290,6 @@ const struct omap_video_timings omap_dss_ntsc_timings = { .vbp = 31, .interlace = true, - - .hsync_level = OMAPDSS_SIG_ACTIVE_LOW, - .vsync_level = OMAPDSS_SIG_ACTIVE_LOW, - .data_pclk_edge = OMAPDSS_DRIVE_SIG_RISING_EDGE, - .de_level = OMAPDSS_SIG_ACTIVE_HIGH, - .sync_pclk_edge = OMAPDSS_DRIVE_SIG_FALLING_EDGE, }; EXPORT_SYMBOL(omap_dss_ntsc_timings); @@ -400,7 +388,7 @@ static void venc_reset(void) } } -#ifdef CONFIG_OMAP2_DSS_SLEEP_AFTER_VENC_RESET +#ifdef CONFIG_FB_OMAP2_DSS_SLEEP_AFTER_VENC_RESET /* the magical sleep that makes things work */ /* XXX more info? What bug this circumvents? */ msleep(20); @@ -515,7 +503,7 @@ static int venc_display_enable(struct omap_dss_device *dssdev) mutex_lock(&venc.venc_lock); - if (out == NULL || out->manager == NULL) { + if (out->manager == NULL) { DSSERR("Failed to enable display: no output/manager\n"); r = -ENODEV; goto err0; diff --git a/drivers/video/fbdev/omap2/dss/video-pll.c b/drivers/video/fbdev/omap2/omapfb/dss/video-pll.c index b1ec59e42940..b1ec59e42940 100644 --- a/drivers/video/fbdev/omap2/dss/video-pll.c +++ b/drivers/video/fbdev/omap2/omapfb/dss/video-pll.c diff --git a/drivers/video/fbdev/omap2/vrfb.c b/drivers/video/fbdev/omap2/omapfb/vrfb.c index f346b02eee1d..f346b02eee1d 100644 --- a/drivers/video/fbdev/omap2/vrfb.c +++ b/drivers/video/fbdev/omap2/omapfb/vrfb.c diff --git a/drivers/video/fbdev/pxafb.c b/drivers/video/fbdev/pxafb.c index 94813af97f09..33b2bb315a2a 100644 --- a/drivers/video/fbdev/pxafb.c +++ b/drivers/video/fbdev/pxafb.c @@ -55,6 +55,9 @@ #include <linux/kthread.h> #include <linux/freezer.h> #include <linux/console.h> +#include <linux/of_graph.h> +#include <video/of_display_timing.h> +#include <video/videomode.h> #include <mach/hardware.h> #include <asm/io.h> @@ -457,7 +460,7 @@ static int pxafb_adjust_timing(struct pxafb_info *fbi, static int pxafb_check_var(struct fb_var_screeninfo *var, struct fb_info *info) { struct pxafb_info *fbi = container_of(info, struct pxafb_info, fb); - struct pxafb_mach_info *inf = dev_get_platdata(fbi->dev); + struct pxafb_mach_info *inf = fbi->inf; int err; if (inf->fixed_modes) { @@ -1230,7 +1233,7 @@ static unsigned int __smart_timing(unsigned time_ns, unsigned long lcd_clk) static void setup_smart_timing(struct pxafb_info *fbi, struct fb_var_screeninfo *var) { - struct pxafb_mach_info *inf = dev_get_platdata(fbi->dev); + struct pxafb_mach_info *inf = fbi->inf; struct pxafb_mode_info *mode = &inf->modes[0]; unsigned long lclk = clk_get_rate(fbi->clk); unsigned t1, t2, t3, t4; @@ -1258,14 +1261,13 @@ static void setup_smart_timing(struct pxafb_info *fbi, static int pxafb_smart_thread(void *arg) { struct pxafb_info *fbi = arg; - struct pxafb_mach_info *inf = dev_get_platdata(fbi->dev); + struct pxafb_mach_info *inf = fbi->inf; if (!inf->smart_update) { pr_err("%s: not properly initialized, thread terminated\n", __func__); return -EINVAL; } - inf = dev_get_platdata(fbi->dev); pr_debug("%s(): task starting\n", __func__); @@ -1788,11 +1790,11 @@ decode_mode: fbi->video_mem_size = video_mem_size; } -static struct pxafb_info *pxafb_init_fbinfo(struct device *dev) +static struct pxafb_info *pxafb_init_fbinfo(struct device *dev, + struct pxafb_mach_info *inf) { struct pxafb_info *fbi; void *addr; - struct pxafb_mach_info *inf = dev_get_platdata(dev); /* Alloc the pxafb_info and pseudo_palette in one step */ fbi = kmalloc(sizeof(struct pxafb_info) + sizeof(u32) * 16, GFP_KERNEL); @@ -1801,6 +1803,7 @@ static struct pxafb_info *pxafb_init_fbinfo(struct device *dev) memset(fbi, 0, sizeof(struct pxafb_info)); fbi->dev = dev; + fbi->inf = inf; fbi->clk = clk_get(dev, NULL); if (IS_ERR(fbi->clk)) { @@ -1852,10 +1855,9 @@ static struct pxafb_info *pxafb_init_fbinfo(struct device *dev) } #ifdef CONFIG_FB_PXA_PARAMETERS -static int parse_opt_mode(struct device *dev, const char *this_opt) +static int parse_opt_mode(struct device *dev, const char *this_opt, + struct pxafb_mach_info *inf) { - struct pxafb_mach_info *inf = dev_get_platdata(dev); - const char *name = this_opt+5; unsigned int namelen = strlen(name); int res_specified = 0, bpp_specified = 0; @@ -1911,9 +1913,9 @@ done: return 0; } -static int parse_opt(struct device *dev, char *this_opt) +static int parse_opt(struct device *dev, char *this_opt, + struct pxafb_mach_info *inf) { - struct pxafb_mach_info *inf = dev_get_platdata(dev); struct pxafb_mode_info *mode = &inf->modes[0]; char s[64]; @@ -1922,7 +1924,7 @@ static int parse_opt(struct device *dev, char *this_opt) if (!strncmp(this_opt, "vmem:", 5)) { video_mem_size = memparse(this_opt + 5, NULL); } else if (!strncmp(this_opt, "mode:", 5)) { - return parse_opt_mode(dev, this_opt); + return parse_opt_mode(dev, this_opt, inf); } else if (!strncmp(this_opt, "pixclock:", 9)) { mode->pixclock = simple_strtoul(this_opt+9, NULL, 0); sprintf(s, "pixclock: %ld\n", mode->pixclock); @@ -2011,7 +2013,8 @@ static int parse_opt(struct device *dev, char *this_opt) return 0; } -static int pxafb_parse_options(struct device *dev, char *options) +static int pxafb_parse_options(struct device *dev, char *options, + struct pxafb_mach_info *inf) { char *this_opt; int ret; @@ -2023,7 +2026,7 @@ static int pxafb_parse_options(struct device *dev, char *options) /* could be made table driven or similar?... */ while ((this_opt = strsep(&options, ",")) != NULL) { - ret = parse_opt(dev, this_opt); + ret = parse_opt(dev, this_opt, inf); if (ret) return ret; } @@ -2092,22 +2095,180 @@ static void pxafb_check_options(struct device *dev, struct pxafb_mach_info *inf) #define pxafb_check_options(...) do {} while (0) #endif +#if defined(CONFIG_OF) +static const char * const lcd_types[] = { + "unknown", "mono-stn", "mono-dstn", "color-stn", "color-dstn", + "color-tft", "smart-panel", NULL +}; + +static int of_get_pxafb_display(struct device *dev, struct device_node *disp, + struct pxafb_mach_info *info, u32 bus_width) +{ + struct display_timings *timings; + struct videomode vm; + int i, ret = -EINVAL; + const char *s; + + ret = of_property_read_string(disp, "lcd-type", &s); + if (ret) + s = "color-tft"; + + for (i = 0; lcd_types[i]; i++) + if (!strcmp(s, lcd_types[i])) + break; + if (!i || !lcd_types[i]) { + dev_err(dev, "lcd-type %s is unknown\n", s); + return -EINVAL; + } + info->lcd_conn |= LCD_CONN_TYPE(i); + info->lcd_conn |= LCD_CONN_WIDTH(bus_width); + + timings = of_get_display_timings(disp); + if (!timings) + goto out; + + ret = -ENOMEM; + info->modes = kmalloc_array(timings->num_timings, + sizeof(info->modes[0]), GFP_KERNEL); + if (!info->modes) + goto out; + info->num_modes = timings->num_timings; + + for (i = 0; i < timings->num_timings; i++) { + ret = videomode_from_timings(timings, &vm, i); + if (ret) { + dev_err(dev, "videomode_from_timings %d failed: %d\n", + i, ret); + goto out; + } + if (vm.flags & DISPLAY_FLAGS_PIXDATA_POSEDGE) + info->lcd_conn |= LCD_PCLK_EDGE_RISE; + if (vm.flags & DISPLAY_FLAGS_PIXDATA_NEGEDGE) + info->lcd_conn |= LCD_PCLK_EDGE_FALL; + if (vm.flags & DISPLAY_FLAGS_DE_HIGH) + info->lcd_conn |= LCD_BIAS_ACTIVE_HIGH; + if (vm.flags & DISPLAY_FLAGS_DE_LOW) + info->lcd_conn |= LCD_BIAS_ACTIVE_LOW; + if (vm.flags & DISPLAY_FLAGS_HSYNC_HIGH) + info->modes[i].sync |= FB_SYNC_HOR_HIGH_ACT; + if (vm.flags & DISPLAY_FLAGS_VSYNC_HIGH) + info->modes[i].sync |= FB_SYNC_VERT_HIGH_ACT; + + info->modes[i].pixclock = 1000000000UL / (vm.pixelclock / 1000); + info->modes[i].xres = vm.hactive; + info->modes[i].yres = vm.vactive; + info->modes[i].hsync_len = vm.hsync_len; + info->modes[i].left_margin = vm.hback_porch; + info->modes[i].right_margin = vm.hfront_porch; + info->modes[i].vsync_len = vm.vsync_len; + info->modes[i].upper_margin = vm.vback_porch; + info->modes[i].lower_margin = vm.vfront_porch; + } + ret = 0; + +out: + display_timings_release(timings); + return ret; +} + +static int of_get_pxafb_mode_info(struct device *dev, + struct pxafb_mach_info *info) +{ + struct device_node *display, *np; + u32 bus_width; + int ret, i; + + np = of_graph_get_next_endpoint(dev->of_node, NULL); + if (!np) { + dev_err(dev, "could not find endpoint\n"); + return -EINVAL; + } + ret = of_property_read_u32(np, "bus-width", &bus_width); + if (ret) { + dev_err(dev, "no bus-width specified: %d\n", ret); + return ret; + } + + display = of_graph_get_remote_port_parent(np); + of_node_put(np); + if (!display) { + dev_err(dev, "no display defined\n"); + return -EINVAL; + } + + ret = of_get_pxafb_display(dev, display, info, bus_width); + of_node_put(display); + if (ret) + return ret; + + for (i = 0; i < info->num_modes; i++) + info->modes[i].bpp = bus_width; + + return 0; +} + +static struct pxafb_mach_info *of_pxafb_of_mach_info(struct device *dev) +{ + int ret; + struct pxafb_mach_info *info; + + if (!dev->of_node) + return NULL; + info = devm_kzalloc(dev, sizeof(*info), GFP_KERNEL); + if (!info) + return ERR_PTR(-ENOMEM); + ret = of_get_pxafb_mode_info(dev, info); + if (ret) { + kfree(info->modes); + return ERR_PTR(ret); + } + + /* + * On purpose, neither lccrX registers nor video memory size can be + * specified through device-tree, they are considered more a debug hack + * available through command line. + */ + return info; +} +#else +static struct pxafb_mach_info *of_pxafb_of_mach_info(struct device *dev) +{ + return NULL; +} +#endif + static int pxafb_probe(struct platform_device *dev) { struct pxafb_info *fbi; - struct pxafb_mach_info *inf; + struct pxafb_mach_info *inf, *pdata; struct resource *r; - int irq, ret; + int i, irq, ret; dev_dbg(&dev->dev, "pxafb_probe\n"); - inf = dev_get_platdata(&dev->dev); ret = -ENOMEM; - fbi = NULL; + pdata = dev_get_platdata(&dev->dev); + inf = devm_kmalloc(&dev->dev, sizeof(*inf), GFP_KERNEL); if (!inf) goto failed; - ret = pxafb_parse_options(&dev->dev, g_options); + if (pdata) { + *inf = *pdata; + inf->modes = + devm_kmalloc_array(&dev->dev, pdata->num_modes, + sizeof(inf->modes[0]), GFP_KERNEL); + if (!inf->modes) + goto failed; + for (i = 0; i < inf->num_modes; i++) + inf->modes[i] = pdata->modes[i]; + } + + if (!pdata) + inf = of_pxafb_of_mach_info(&dev->dev); + if (IS_ERR_OR_NULL(inf)) + goto failed; + + ret = pxafb_parse_options(&dev->dev, g_options, inf); if (ret < 0) goto failed; @@ -2125,7 +2286,7 @@ static int pxafb_probe(struct platform_device *dev) goto failed; } - fbi = pxafb_init_fbinfo(&dev->dev); + fbi = pxafb_init_fbinfo(&dev->dev, inf); if (!fbi) { /* only reason for pxafb_init_fbinfo to fail is kmalloc */ dev_err(&dev->dev, "Failed to initialize framebuffer device\n"); @@ -2299,11 +2460,20 @@ static int pxafb_remove(struct platform_device *dev) return 0; } +static const struct of_device_id pxafb_of_dev_id[] = { + { .compatible = "marvell,pxa270-lcdc", }, + { .compatible = "marvell,pxa300-lcdc", }, + { .compatible = "marvell,pxa2xx-lcdc", }, + { /* sentinel */ } +}; +MODULE_DEVICE_TABLE(of, pxafb_of_dev_id); + static struct platform_driver pxafb_driver = { .probe = pxafb_probe, .remove = pxafb_remove, .driver = { .name = "pxa2xx-fb", + .of_match_table = pxafb_of_dev_id, #ifdef CONFIG_PM .pm = &pxafb_pm_ops, #endif diff --git a/drivers/video/fbdev/pxafb.h b/drivers/video/fbdev/pxafb.h index 26ba9fa3f737..5dc414e26fc8 100644 --- a/drivers/video/fbdev/pxafb.h +++ b/drivers/video/fbdev/pxafb.h @@ -167,6 +167,8 @@ struct pxafb_info { void (*lcd_power)(int, struct fb_var_screeninfo *); void (*backlight_power)(int); + + struct pxafb_mach_info *inf; }; #define TO_INF(ptr,member) container_of(ptr,struct pxafb_info,member) diff --git a/drivers/video/fbdev/riva/fbdev.c b/drivers/video/fbdev/riva/fbdev.c index f1ad2747064b..2ef26ad99341 100644 --- a/drivers/video/fbdev/riva/fbdev.c +++ b/drivers/video/fbdev/riva/fbdev.c @@ -1765,6 +1765,7 @@ static int riva_get_EDID_i2c(struct fb_info *info) int i; NVTRACE_ENTER(); + par->riva.LockUnlock(&par->riva, 0); riva_create_i2c_busses(par); for (i = 0; i < 3; i++) { if (!par->chan[i].par) diff --git a/drivers/video/fbdev/sh_mobile_hdmi.c b/drivers/video/fbdev/sh_mobile_hdmi.c deleted file mode 100644 index 7c72a3f02056..000000000000 --- a/drivers/video/fbdev/sh_mobile_hdmi.c +++ /dev/null @@ -1,1489 +0,0 @@ -/* - * SH-Mobile High-Definition Multimedia Interface (HDMI) driver - * for SLISHDMI13T and SLIPHDMIT IP cores - * - * Copyright (C) 2010, Guennadi Liakhovetski <g.liakhovetski@gmx.de> - * - * 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. - */ - -#include <linux/clk.h> -#include <linux/console.h> -#include <linux/delay.h> -#include <linux/err.h> -#include <linux/init.h> -#include <linux/interrupt.h> -#include <linux/io.h> -#include <linux/module.h> -#include <linux/platform_device.h> -#include <linux/pm_runtime.h> -#include <linux/slab.h> -#include <linux/types.h> -#include <linux/workqueue.h> -#include <sound/soc.h> -#include <sound/soc-dapm.h> -#include <sound/initval.h> - -#include <video/sh_mobile_hdmi.h> -#include <video/sh_mobile_lcdc.h> - -#include "sh_mobile_lcdcfb.h" - -/* HDMI Core Control Register (HTOP0) */ -#define HDMI_SYSTEM_CTRL 0x00 /* System control */ -#define HDMI_L_R_DATA_SWAP_CTRL_RPKT 0x01 /* L/R data swap control, - bits 19..16 of 20-bit N for Audio Clock Regeneration packet */ -#define HDMI_20_BIT_N_FOR_AUDIO_RPKT_15_8 0x02 /* bits 15..8 of 20-bit N for Audio Clock Regeneration packet */ -#define HDMI_20_BIT_N_FOR_AUDIO_RPKT_7_0 0x03 /* bits 7..0 of 20-bit N for Audio Clock Regeneration packet */ -#define HDMI_SPDIF_AUDIO_SAMP_FREQ_CTS 0x04 /* SPDIF audio sampling frequency, - bits 19..16 of Internal CTS */ -#define HDMI_INTERNAL_CTS_15_8 0x05 /* bits 15..8 of Internal CTS */ -#define HDMI_INTERNAL_CTS_7_0 0x06 /* bits 7..0 of Internal CTS */ -#define HDMI_EXTERNAL_CTS_19_16 0x07 /* External CTS */ -#define HDMI_EXTERNAL_CTS_15_8 0x08 /* External CTS */ -#define HDMI_EXTERNAL_CTS_7_0 0x09 /* External CTS */ -#define HDMI_AUDIO_SETTING_1 0x0A /* Audio setting.1 */ -#define HDMI_AUDIO_SETTING_2 0x0B /* Audio setting.2 */ -#define HDMI_I2S_AUDIO_SET 0x0C /* I2S audio setting */ -#define HDMI_DSD_AUDIO_SET 0x0D /* DSD audio setting */ -#define HDMI_DEBUG_MONITOR_1 0x0E /* Debug monitor.1 */ -#define HDMI_DEBUG_MONITOR_2 0x0F /* Debug monitor.2 */ -#define HDMI_I2S_INPUT_PIN_SWAP 0x10 /* I2S input pin swap */ -#define HDMI_AUDIO_STATUS_BITS_SETTING_1 0x11 /* Audio status bits setting.1 */ -#define HDMI_AUDIO_STATUS_BITS_SETTING_2 0x12 /* Audio status bits setting.2 */ -#define HDMI_CATEGORY_CODE 0x13 /* Category code */ -#define HDMI_SOURCE_NUM_AUDIO_WORD_LEN 0x14 /* Source number/Audio word length */ -#define HDMI_AUDIO_VIDEO_SETTING_1 0x15 /* Audio/Video setting.1 */ -#define HDMI_VIDEO_SETTING_1 0x16 /* Video setting.1 */ -#define HDMI_DEEP_COLOR_MODES 0x17 /* Deep Color Modes */ - -/* 12 16- and 10-bit Color space conversion parameters: 0x18..0x2f */ -#define HDMI_COLOR_SPACE_CONVERSION_PARAMETERS 0x18 - -#define HDMI_EXTERNAL_VIDEO_PARAM_SETTINGS 0x30 /* External video parameter settings */ -#define HDMI_EXTERNAL_H_TOTAL_7_0 0x31 /* External horizontal total (LSB) */ -#define HDMI_EXTERNAL_H_TOTAL_11_8 0x32 /* External horizontal total (MSB) */ -#define HDMI_EXTERNAL_H_BLANK_7_0 0x33 /* External horizontal blank (LSB) */ -#define HDMI_EXTERNAL_H_BLANK_9_8 0x34 /* External horizontal blank (MSB) */ -#define HDMI_EXTERNAL_H_DELAY_7_0 0x35 /* External horizontal delay (LSB) */ -#define HDMI_EXTERNAL_H_DELAY_9_8 0x36 /* External horizontal delay (MSB) */ -#define HDMI_EXTERNAL_H_DURATION_7_0 0x37 /* External horizontal duration (LSB) */ -#define HDMI_EXTERNAL_H_DURATION_9_8 0x38 /* External horizontal duration (MSB) */ -#define HDMI_EXTERNAL_V_TOTAL_7_0 0x39 /* External vertical total (LSB) */ -#define HDMI_EXTERNAL_V_TOTAL_9_8 0x3A /* External vertical total (MSB) */ -#define HDMI_AUDIO_VIDEO_SETTING_2 0x3B /* Audio/Video setting.2 */ -#define HDMI_EXTERNAL_V_BLANK 0x3D /* External vertical blank */ -#define HDMI_EXTERNAL_V_DELAY 0x3E /* External vertical delay */ -#define HDMI_EXTERNAL_V_DURATION 0x3F /* External vertical duration */ -#define HDMI_CTRL_PKT_MANUAL_SEND_CONTROL 0x40 /* Control packet manual send control */ -#define HDMI_CTRL_PKT_AUTO_SEND 0x41 /* Control packet auto send with VSYNC control */ -#define HDMI_AUTO_CHECKSUM_OPTION 0x42 /* Auto checksum option */ -#define HDMI_VIDEO_SETTING_2 0x45 /* Video setting.2 */ -#define HDMI_OUTPUT_OPTION 0x46 /* Output option */ -#define HDMI_SLIPHDMIT_PARAM_OPTION 0x51 /* SLIPHDMIT parameter option */ -#define HDMI_HSYNC_PMENT_AT_EMB_7_0 0x52 /* HSYNC placement at embedded sync (LSB) */ -#define HDMI_HSYNC_PMENT_AT_EMB_15_8 0x53 /* HSYNC placement at embedded sync (MSB) */ -#define HDMI_VSYNC_PMENT_AT_EMB_7_0 0x54 /* VSYNC placement at embedded sync (LSB) */ -#define HDMI_VSYNC_PMENT_AT_EMB_14_8 0x55 /* VSYNC placement at embedded sync (MSB) */ -#define HDMI_SLIPHDMIT_PARAM_SETTINGS_1 0x56 /* SLIPHDMIT parameter settings.1 */ -#define HDMI_SLIPHDMIT_PARAM_SETTINGS_2 0x57 /* SLIPHDMIT parameter settings.2 */ -#define HDMI_SLIPHDMIT_PARAM_SETTINGS_3 0x58 /* SLIPHDMIT parameter settings.3 */ -#define HDMI_SLIPHDMIT_PARAM_SETTINGS_5 0x59 /* SLIPHDMIT parameter settings.5 */ -#define HDMI_SLIPHDMIT_PARAM_SETTINGS_6 0x5A /* SLIPHDMIT parameter settings.6 */ -#define HDMI_SLIPHDMIT_PARAM_SETTINGS_7 0x5B /* SLIPHDMIT parameter settings.7 */ -#define HDMI_SLIPHDMIT_PARAM_SETTINGS_8 0x5C /* SLIPHDMIT parameter settings.8 */ -#define HDMI_SLIPHDMIT_PARAM_SETTINGS_9 0x5D /* SLIPHDMIT parameter settings.9 */ -#define HDMI_SLIPHDMIT_PARAM_SETTINGS_10 0x5E /* SLIPHDMIT parameter settings.10 */ -#define HDMI_CTRL_PKT_BUF_INDEX 0x5F /* Control packet buffer index */ -#define HDMI_CTRL_PKT_BUF_ACCESS_HB0 0x60 /* Control packet data buffer access window - HB0 */ -#define HDMI_CTRL_PKT_BUF_ACCESS_HB1 0x61 /* Control packet data buffer access window - HB1 */ -#define HDMI_CTRL_PKT_BUF_ACCESS_HB2 0x62 /* Control packet data buffer access window - HB2 */ -#define HDMI_CTRL_PKT_BUF_ACCESS_PB0 0x63 /* Control packet data buffer access window - PB0 */ -#define HDMI_CTRL_PKT_BUF_ACCESS_PB1 0x64 /* Control packet data buffer access window - PB1 */ -#define HDMI_CTRL_PKT_BUF_ACCESS_PB2 0x65 /* Control packet data buffer access window - PB2 */ -#define HDMI_CTRL_PKT_BUF_ACCESS_PB3 0x66 /* Control packet data buffer access window - PB3 */ -#define HDMI_CTRL_PKT_BUF_ACCESS_PB4 0x67 /* Control packet data buffer access window - PB4 */ -#define HDMI_CTRL_PKT_BUF_ACCESS_PB5 0x68 /* Control packet data buffer access window - PB5 */ -#define HDMI_CTRL_PKT_BUF_ACCESS_PB6 0x69 /* Control packet data buffer access window - PB6 */ -#define HDMI_CTRL_PKT_BUF_ACCESS_PB7 0x6A /* Control packet data buffer access window - PB7 */ -#define HDMI_CTRL_PKT_BUF_ACCESS_PB8 0x6B /* Control packet data buffer access window - PB8 */ -#define HDMI_CTRL_PKT_BUF_ACCESS_PB9 0x6C /* Control packet data buffer access window - PB9 */ -#define HDMI_CTRL_PKT_BUF_ACCESS_PB10 0x6D /* Control packet data buffer access window - PB10 */ -#define HDMI_CTRL_PKT_BUF_ACCESS_PB11 0x6E /* Control packet data buffer access window - PB11 */ -#define HDMI_CTRL_PKT_BUF_ACCESS_PB12 0x6F /* Control packet data buffer access window - PB12 */ -#define HDMI_CTRL_PKT_BUF_ACCESS_PB13 0x70 /* Control packet data buffer access window - PB13 */ -#define HDMI_CTRL_PKT_BUF_ACCESS_PB14 0x71 /* Control packet data buffer access window - PB14 */ -#define HDMI_CTRL_PKT_BUF_ACCESS_PB15 0x72 /* Control packet data buffer access window - PB15 */ -#define HDMI_CTRL_PKT_BUF_ACCESS_PB16 0x73 /* Control packet data buffer access window - PB16 */ -#define HDMI_CTRL_PKT_BUF_ACCESS_PB17 0x74 /* Control packet data buffer access window - PB17 */ -#define HDMI_CTRL_PKT_BUF_ACCESS_PB18 0x75 /* Control packet data buffer access window - PB18 */ -#define HDMI_CTRL_PKT_BUF_ACCESS_PB19 0x76 /* Control packet data buffer access window - PB19 */ -#define HDMI_CTRL_PKT_BUF_ACCESS_PB20 0x77 /* Control packet data buffer access window - PB20 */ -#define HDMI_CTRL_PKT_BUF_ACCESS_PB21 0x78 /* Control packet data buffer access window - PB21 */ -#define HDMI_CTRL_PKT_BUF_ACCESS_PB22 0x79 /* Control packet data buffer access window - PB22 */ -#define HDMI_CTRL_PKT_BUF_ACCESS_PB23 0x7A /* Control packet data buffer access window - PB23 */ -#define HDMI_CTRL_PKT_BUF_ACCESS_PB24 0x7B /* Control packet data buffer access window - PB24 */ -#define HDMI_CTRL_PKT_BUF_ACCESS_PB25 0x7C /* Control packet data buffer access window - PB25 */ -#define HDMI_CTRL_PKT_BUF_ACCESS_PB26 0x7D /* Control packet data buffer access window - PB26 */ -#define HDMI_CTRL_PKT_BUF_ACCESS_PB27 0x7E /* Control packet data buffer access window - PB27 */ -#define HDMI_EDID_KSV_FIFO_ACCESS_WINDOW 0x80 /* EDID/KSV FIFO access window */ -#define HDMI_DDC_BUS_ACCESS_FREQ_CTRL_7_0 0x81 /* DDC bus access frequency control (LSB) */ -#define HDMI_DDC_BUS_ACCESS_FREQ_CTRL_15_8 0x82 /* DDC bus access frequency control (MSB) */ -#define HDMI_INTERRUPT_MASK_1 0x92 /* Interrupt mask.1 */ -#define HDMI_INTERRUPT_MASK_2 0x93 /* Interrupt mask.2 */ -#define HDMI_INTERRUPT_STATUS_1 0x94 /* Interrupt status.1 */ -#define HDMI_INTERRUPT_STATUS_2 0x95 /* Interrupt status.2 */ -#define HDMI_INTERRUPT_MASK_3 0x96 /* Interrupt mask.3 */ -#define HDMI_INTERRUPT_MASK_4 0x97 /* Interrupt mask.4 */ -#define HDMI_INTERRUPT_STATUS_3 0x98 /* Interrupt status.3 */ -#define HDMI_INTERRUPT_STATUS_4 0x99 /* Interrupt status.4 */ -#define HDMI_SOFTWARE_HDCP_CONTROL_1 0x9A /* Software HDCP control.1 */ -#define HDMI_FRAME_COUNTER 0x9C /* Frame counter */ -#define HDMI_FRAME_COUNTER_FOR_RI_CHECK 0x9D /* Frame counter for Ri check */ -#define HDMI_HDCP_CONTROL 0xAF /* HDCP control */ -#define HDMI_RI_FRAME_COUNT_REGISTER 0xB2 /* Ri frame count register */ -#define HDMI_DDC_BUS_CONTROL 0xB7 /* DDC bus control */ -#define HDMI_HDCP_STATUS 0xB8 /* HDCP status */ -#define HDMI_SHA0 0xB9 /* sha0 */ -#define HDMI_SHA1 0xBA /* sha1 */ -#define HDMI_SHA2 0xBB /* sha2 */ -#define HDMI_SHA3 0xBC /* sha3 */ -#define HDMI_SHA4 0xBD /* sha4 */ -#define HDMI_BCAPS_READ 0xBE /* BCAPS read / debug */ -#define HDMI_AKSV_BKSV_7_0_MONITOR 0xBF /* AKSV/BKSV[7:0] monitor */ -#define HDMI_AKSV_BKSV_15_8_MONITOR 0xC0 /* AKSV/BKSV[15:8] monitor */ -#define HDMI_AKSV_BKSV_23_16_MONITOR 0xC1 /* AKSV/BKSV[23:16] monitor */ -#define HDMI_AKSV_BKSV_31_24_MONITOR 0xC2 /* AKSV/BKSV[31:24] monitor */ -#define HDMI_AKSV_BKSV_39_32_MONITOR 0xC3 /* AKSV/BKSV[39:32] monitor */ -#define HDMI_EDID_SEGMENT_POINTER 0xC4 /* EDID segment pointer */ -#define HDMI_EDID_WORD_ADDRESS 0xC5 /* EDID word address */ -#define HDMI_EDID_DATA_FIFO_ADDRESS 0xC6 /* EDID data FIFO address */ -#define HDMI_NUM_OF_HDMI_DEVICES 0xC7 /* Number of HDMI devices */ -#define HDMI_HDCP_ERROR_CODE 0xC8 /* HDCP error code */ -#define HDMI_100MS_TIMER_SET 0xC9 /* 100ms timer setting */ -#define HDMI_5SEC_TIMER_SET 0xCA /* 5sec timer setting */ -#define HDMI_RI_READ_COUNT 0xCB /* Ri read count */ -#define HDMI_AN_SEED 0xCC /* An seed */ -#define HDMI_MAX_NUM_OF_RCIVRS_ALLOWED 0xCD /* Maximum number of receivers allowed */ -#define HDMI_HDCP_MEMORY_ACCESS_CONTROL_1 0xCE /* HDCP memory access control.1 */ -#define HDMI_HDCP_MEMORY_ACCESS_CONTROL_2 0xCF /* HDCP memory access control.2 */ -#define HDMI_HDCP_CONTROL_2 0xD0 /* HDCP Control 2 */ -#define HDMI_HDCP_KEY_MEMORY_CONTROL 0xD2 /* HDCP Key Memory Control */ -#define HDMI_COLOR_SPACE_CONV_CONFIG_1 0xD3 /* Color space conversion configuration.1 */ -#define HDMI_VIDEO_SETTING_3 0xD4 /* Video setting.3 */ -#define HDMI_RI_7_0 0xD5 /* Ri[7:0] */ -#define HDMI_RI_15_8 0xD6 /* Ri[15:8] */ -#define HDMI_PJ 0xD7 /* Pj */ -#define HDMI_SHA_RD 0xD8 /* sha_rd */ -#define HDMI_RI_7_0_SAVED 0xD9 /* Ri[7:0] saved */ -#define HDMI_RI_15_8_SAVED 0xDA /* Ri[15:8] saved */ -#define HDMI_PJ_SAVED 0xDB /* Pj saved */ -#define HDMI_NUM_OF_DEVICES 0xDC /* Number of devices */ -#define HDMI_HOT_PLUG_MSENS_STATUS 0xDF /* Hot plug/MSENS status */ -#define HDMI_BCAPS_WRITE 0xE0 /* bcaps */ -#define HDMI_BSTAT_7_0 0xE1 /* bstat[7:0] */ -#define HDMI_BSTAT_15_8 0xE2 /* bstat[15:8] */ -#define HDMI_BKSV_7_0 0xE3 /* bksv[7:0] */ -#define HDMI_BKSV_15_8 0xE4 /* bksv[15:8] */ -#define HDMI_BKSV_23_16 0xE5 /* bksv[23:16] */ -#define HDMI_BKSV_31_24 0xE6 /* bksv[31:24] */ -#define HDMI_BKSV_39_32 0xE7 /* bksv[39:32] */ -#define HDMI_AN_7_0 0xE8 /* An[7:0] */ -#define HDMI_AN_15_8 0xE9 /* An [15:8] */ -#define HDMI_AN_23_16 0xEA /* An [23:16] */ -#define HDMI_AN_31_24 0xEB /* An [31:24] */ -#define HDMI_AN_39_32 0xEC /* An [39:32] */ -#define HDMI_AN_47_40 0xED /* An [47:40] */ -#define HDMI_AN_55_48 0xEE /* An [55:48] */ -#define HDMI_AN_63_56 0xEF /* An [63:56] */ -#define HDMI_PRODUCT_ID 0xF0 /* Product ID */ -#define HDMI_REVISION_ID 0xF1 /* Revision ID */ -#define HDMI_TEST_MODE 0xFE /* Test mode */ - -/* HDMI Control Register (HTOP1) */ -#define HDMI_HTOP1_TEST_MODE 0x0000 /* Test mode */ -#define HDMI_HTOP1_VIDEO_INPUT 0x0008 /* VideoInput */ -#define HDMI_HTOP1_CORE_RSTN 0x000C /* CoreResetn */ -#define HDMI_HTOP1_PLLBW 0x0018 /* PLLBW */ -#define HDMI_HTOP1_CLK_TO_PHY 0x001C /* Clk to Phy */ -#define HDMI_HTOP1_VIDEO_INPUT2 0x0020 /* VideoInput2 */ -#define HDMI_HTOP1_TISEMP0_1 0x0024 /* tisemp0-1 */ -#define HDMI_HTOP1_TISEMP2_C 0x0028 /* tisemp2-c */ -#define HDMI_HTOP1_TISIDRV 0x002C /* tisidrv */ -#define HDMI_HTOP1_TISEN 0x0034 /* tisen */ -#define HDMI_HTOP1_TISDREN 0x0038 /* tisdren */ -#define HDMI_HTOP1_CISRANGE 0x003C /* cisrange */ -#define HDMI_HTOP1_ENABLE_SELECTOR 0x0040 /* Enable Selector */ -#define HDMI_HTOP1_MACRO_RESET 0x0044 /* Macro reset */ -#define HDMI_HTOP1_PLL_CALIBRATION 0x0048 /* PLL calibration */ -#define HDMI_HTOP1_RE_CALIBRATION 0x004C /* Re-calibration */ -#define HDMI_HTOP1_CURRENT 0x0050 /* Current */ -#define HDMI_HTOP1_PLL_LOCK_DETECT 0x0054 /* PLL lock detect */ -#define HDMI_HTOP1_PHY_TEST_MODE 0x0058 /* PHY Test Mode */ -#define HDMI_HTOP1_CLK_SET 0x0080 /* Clock Set */ -#define HDMI_HTOP1_DDC_FAIL_SAFE 0x0084 /* DDC fail safe */ -#define HDMI_HTOP1_PRBS 0x0088 /* PRBS */ -#define HDMI_HTOP1_EDID_AINC_CONTROL 0x008C /* EDID ainc Control */ -#define HDMI_HTOP1_HTOP_DCL_MODE 0x00FC /* Deep Coloer Mode */ -#define HDMI_HTOP1_HTOP_DCL_FRC_COEF0 0x0100 /* Deep Color:FRC COEF0 */ -#define HDMI_HTOP1_HTOP_DCL_FRC_COEF1 0x0104 /* Deep Color:FRC COEF1 */ -#define HDMI_HTOP1_HTOP_DCL_FRC_COEF2 0x0108 /* Deep Color:FRC COEF2 */ -#define HDMI_HTOP1_HTOP_DCL_FRC_COEF3 0x010C /* Deep Color:FRC COEF3 */ -#define HDMI_HTOP1_HTOP_DCL_FRC_COEF0_C 0x0110 /* Deep Color:FRC COEF0C */ -#define HDMI_HTOP1_HTOP_DCL_FRC_COEF1_C 0x0114 /* Deep Color:FRC COEF1C */ -#define HDMI_HTOP1_HTOP_DCL_FRC_COEF2_C 0x0118 /* Deep Color:FRC COEF2C */ -#define HDMI_HTOP1_HTOP_DCL_FRC_COEF3_C 0x011C /* Deep Color:FRC COEF3C */ -#define HDMI_HTOP1_HTOP_DCL_FRC_MODE 0x0120 /* Deep Color:FRC Mode */ -#define HDMI_HTOP1_HTOP_DCL_RECT_START1 0x0124 /* Deep Color:Rect Start1 */ -#define HDMI_HTOP1_HTOP_DCL_RECT_SIZE1 0x0128 /* Deep Color:Rect Size1 */ -#define HDMI_HTOP1_HTOP_DCL_RECT_START2 0x012C /* Deep Color:Rect Start2 */ -#define HDMI_HTOP1_HTOP_DCL_RECT_SIZE2 0x0130 /* Deep Color:Rect Size2 */ -#define HDMI_HTOP1_HTOP_DCL_RECT_START3 0x0134 /* Deep Color:Rect Start3 */ -#define HDMI_HTOP1_HTOP_DCL_RECT_SIZE3 0x0138 /* Deep Color:Rect Size3 */ -#define HDMI_HTOP1_HTOP_DCL_RECT_START4 0x013C /* Deep Color:Rect Start4 */ -#define HDMI_HTOP1_HTOP_DCL_RECT_SIZE4 0x0140 /* Deep Color:Rect Size4 */ -#define HDMI_HTOP1_HTOP_DCL_FIL_PARA_Y1_1 0x0144 /* Deep Color:Fil Para Y1_1 */ -#define HDMI_HTOP1_HTOP_DCL_FIL_PARA_Y1_2 0x0148 /* Deep Color:Fil Para Y1_2 */ -#define HDMI_HTOP1_HTOP_DCL_FIL_PARA_CB1_1 0x014C /* Deep Color:Fil Para CB1_1 */ -#define HDMI_HTOP1_HTOP_DCL_FIL_PARA_CB1_2 0x0150 /* Deep Color:Fil Para CB1_2 */ -#define HDMI_HTOP1_HTOP_DCL_FIL_PARA_CR1_1 0x0154 /* Deep Color:Fil Para CR1_1 */ -#define HDMI_HTOP1_HTOP_DCL_FIL_PARA_CR1_2 0x0158 /* Deep Color:Fil Para CR1_2 */ -#define HDMI_HTOP1_HTOP_DCL_FIL_PARA_Y2_1 0x015C /* Deep Color:Fil Para Y2_1 */ -#define HDMI_HTOP1_HTOP_DCL_FIL_PARA_Y2_2 0x0160 /* Deep Color:Fil Para Y2_2 */ -#define HDMI_HTOP1_HTOP_DCL_FIL_PARA_CB2_1 0x0164 /* Deep Color:Fil Para CB2_1 */ -#define HDMI_HTOP1_HTOP_DCL_FIL_PARA_CB2_2 0x0168 /* Deep Color:Fil Para CB2_2 */ -#define HDMI_HTOP1_HTOP_DCL_FIL_PARA_CR2_1 0x016C /* Deep Color:Fil Para CR2_1 */ -#define HDMI_HTOP1_HTOP_DCL_FIL_PARA_CR2_2 0x0170 /* Deep Color:Fil Para CR2_2 */ -#define HDMI_HTOP1_HTOP_DCL_COR_PARA_Y1 0x0174 /* Deep Color:Cor Para Y1 */ -#define HDMI_HTOP1_HTOP_DCL_COR_PARA_CB1 0x0178 /* Deep Color:Cor Para CB1 */ -#define HDMI_HTOP1_HTOP_DCL_COR_PARA_CR1 0x017C /* Deep Color:Cor Para CR1 */ -#define HDMI_HTOP1_HTOP_DCL_COR_PARA_Y2 0x0180 /* Deep Color:Cor Para Y2 */ -#define HDMI_HTOP1_HTOP_DCL_COR_PARA_CB2 0x0184 /* Deep Color:Cor Para CB2 */ -#define HDMI_HTOP1_HTOP_DCL_COR_PARA_CR2 0x0188 /* Deep Color:Cor Para CR2 */ -#define HDMI_HTOP1_EDID_DATA_READ 0x0200 /* EDID Data Read 128Byte:0x03FC */ - -enum hotplug_state { - HDMI_HOTPLUG_DISCONNECTED, - HDMI_HOTPLUG_CONNECTED, - HDMI_HOTPLUG_EDID_DONE, -}; - -struct sh_hdmi { - struct sh_mobile_lcdc_entity entity; - - void __iomem *base; - void __iomem *htop1; - enum hotplug_state hp_state; /* hot-plug status */ - u8 preprogrammed_vic; /* use a pre-programmed VIC or - the external mode */ - u8 edid_block_addr; - u8 edid_segment_nr; - u8 edid_blocks; - int irq; - struct clk *hdmi_clk; - struct device *dev; - struct delayed_work edid_work; - struct fb_videomode mode; - struct fb_monspecs monspec; - - /* register access functions */ - void (*write)(struct sh_hdmi *hdmi, u8 data, u8 reg); - u8 (*read)(struct sh_hdmi *hdmi, u8 reg); -}; - -#define entity_to_sh_hdmi(e) container_of(e, struct sh_hdmi, entity) - -static void __hdmi_write8(struct sh_hdmi *hdmi, u8 data, u8 reg) -{ - iowrite8(data, hdmi->base + reg); -} - -static u8 __hdmi_read8(struct sh_hdmi *hdmi, u8 reg) -{ - return ioread8(hdmi->base + reg); -} - -static void __hdmi_write32(struct sh_hdmi *hdmi, u8 data, u8 reg) -{ - iowrite32((u32)data, hdmi->base + (reg * 4)); - udelay(100); -} - -static u8 __hdmi_read32(struct sh_hdmi *hdmi, u8 reg) -{ - return (u8)ioread32(hdmi->base + (reg * 4)); -} - -static void hdmi_write(struct sh_hdmi *hdmi, u8 data, u8 reg) -{ - hdmi->write(hdmi, data, reg); -} - -static u8 hdmi_read(struct sh_hdmi *hdmi, u8 reg) -{ - return hdmi->read(hdmi, reg); -} - -static void hdmi_bit_set(struct sh_hdmi *hdmi, u8 mask, u8 data, u8 reg) -{ - u8 val = hdmi_read(hdmi, reg); - - val &= ~mask; - val |= (data & mask); - - hdmi_write(hdmi, val, reg); -} - -static void hdmi_htop1_write(struct sh_hdmi *hdmi, u32 data, u32 reg) -{ - iowrite32(data, hdmi->htop1 + reg); - udelay(100); -} - -static u32 hdmi_htop1_read(struct sh_hdmi *hdmi, u32 reg) -{ - return ioread32(hdmi->htop1 + reg); -} - -/* - * HDMI sound - */ -static unsigned int sh_hdmi_snd_read(struct snd_soc_codec *codec, - unsigned int reg) -{ - struct sh_hdmi *hdmi = snd_soc_codec_get_drvdata(codec); - - return hdmi_read(hdmi, reg); -} - -static int sh_hdmi_snd_write(struct snd_soc_codec *codec, - unsigned int reg, - unsigned int value) -{ - struct sh_hdmi *hdmi = snd_soc_codec_get_drvdata(codec); - - hdmi_write(hdmi, value, reg); - return 0; -} - -static struct snd_soc_dai_driver sh_hdmi_dai = { - .name = "sh_mobile_hdmi-hifi", - .playback = { - .stream_name = "Playback", - .channels_min = 2, - .channels_max = 8, - .rates = SNDRV_PCM_RATE_32000 | SNDRV_PCM_RATE_44100 | - SNDRV_PCM_RATE_48000 | SNDRV_PCM_RATE_88200 | - SNDRV_PCM_RATE_96000 | SNDRV_PCM_RATE_176400 | - SNDRV_PCM_RATE_192000, - .formats = SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S24_LE, - }, -}; - -static int sh_hdmi_snd_probe(struct snd_soc_codec *codec) -{ - dev_info(codec->dev, "SH Mobile HDMI Audio Codec"); - - return 0; -} - -static struct snd_soc_codec_driver soc_codec_dev_sh_hdmi = { - .probe = sh_hdmi_snd_probe, - .read = sh_hdmi_snd_read, - .write = sh_hdmi_snd_write, -}; - -/* - * HDMI video - */ - -/* External video parameter settings */ -static void sh_hdmi_external_video_param(struct sh_hdmi *hdmi) -{ - struct fb_videomode *mode = &hdmi->mode; - u16 htotal, hblank, hdelay, vtotal, vblank, vdelay, voffset; - u8 sync = 0; - - htotal = mode->xres + mode->right_margin + mode->left_margin - + mode->hsync_len; - hdelay = mode->hsync_len + mode->left_margin; - hblank = mode->right_margin + hdelay; - - /* - * Vertical timing looks a bit different in Figure 18, - * but let's try the same first by setting offset = 0 - */ - vtotal = mode->yres + mode->upper_margin + mode->lower_margin - + mode->vsync_len; - vdelay = mode->vsync_len + mode->upper_margin; - vblank = mode->lower_margin + vdelay; - voffset = min(mode->upper_margin / 2, 6U); - - /* - * [3]: VSYNC polarity: Positive - * [2]: HSYNC polarity: Positive - * [1]: Interlace/Progressive: Progressive - * [0]: External video settings enable: used. - */ - if (mode->sync & FB_SYNC_HOR_HIGH_ACT) - sync |= 4; - if (mode->sync & FB_SYNC_VERT_HIGH_ACT) - sync |= 8; - - dev_dbg(hdmi->dev, "H: %u, %u, %u, %u; V: %u, %u, %u, %u; sync 0x%x\n", - htotal, hblank, hdelay, mode->hsync_len, - vtotal, vblank, vdelay, mode->vsync_len, sync); - - hdmi_write(hdmi, sync | (voffset << 4), HDMI_EXTERNAL_VIDEO_PARAM_SETTINGS); - - hdmi_write(hdmi, htotal, HDMI_EXTERNAL_H_TOTAL_7_0); - hdmi_write(hdmi, htotal >> 8, HDMI_EXTERNAL_H_TOTAL_11_8); - - hdmi_write(hdmi, hblank, HDMI_EXTERNAL_H_BLANK_7_0); - hdmi_write(hdmi, hblank >> 8, HDMI_EXTERNAL_H_BLANK_9_8); - - hdmi_write(hdmi, hdelay, HDMI_EXTERNAL_H_DELAY_7_0); - hdmi_write(hdmi, hdelay >> 8, HDMI_EXTERNAL_H_DELAY_9_8); - - hdmi_write(hdmi, mode->hsync_len, HDMI_EXTERNAL_H_DURATION_7_0); - hdmi_write(hdmi, mode->hsync_len >> 8, HDMI_EXTERNAL_H_DURATION_9_8); - - hdmi_write(hdmi, vtotal, HDMI_EXTERNAL_V_TOTAL_7_0); - hdmi_write(hdmi, vtotal >> 8, HDMI_EXTERNAL_V_TOTAL_9_8); - - hdmi_write(hdmi, vblank, HDMI_EXTERNAL_V_BLANK); - - hdmi_write(hdmi, vdelay, HDMI_EXTERNAL_V_DELAY); - - hdmi_write(hdmi, mode->vsync_len, HDMI_EXTERNAL_V_DURATION); - - /* Set bit 0 of HDMI_EXTERNAL_VIDEO_PARAM_SETTINGS here for external mode */ - if (!hdmi->preprogrammed_vic) - hdmi_write(hdmi, sync | 1 | (voffset << 4), - HDMI_EXTERNAL_VIDEO_PARAM_SETTINGS); -} - -/** - * sh_hdmi_video_config() - */ -static void sh_hdmi_video_config(struct sh_hdmi *hdmi) -{ - /* - * [7:4]: Audio sampling frequency: 48kHz - * [3:1]: Input video format: RGB and YCbCr 4:4:4 (Y on Green) - * [0]: Internal/External DE select: internal - */ - hdmi_write(hdmi, 0x20, HDMI_AUDIO_VIDEO_SETTING_1); - - /* - * [7:6]: Video output format: RGB 4:4:4 - * [5:4]: Input video data width: 8 bit - * [3:1]: EAV/SAV location: channel 1 - * [0]: Video input color space: RGB - */ - hdmi_write(hdmi, 0x34, HDMI_VIDEO_SETTING_1); - - /* - * [7:6]: Together with bit [6] of HDMI_AUDIO_VIDEO_SETTING_2, which is - * left at 0 by default, this configures 24bpp and sets the Color Depth - * (CD) field in the General Control Packet - */ - hdmi_write(hdmi, 0x20, HDMI_DEEP_COLOR_MODES); -} - -/** - * sh_hdmi_audio_config() - */ -static void sh_hdmi_audio_config(struct sh_hdmi *hdmi) -{ - u8 data; - struct sh_mobile_hdmi_info *pdata = dev_get_platdata(hdmi->dev); - - /* - * [7:4] L/R data swap control - * [3:0] appropriate N[19:16] - */ - hdmi_write(hdmi, 0x00, HDMI_L_R_DATA_SWAP_CTRL_RPKT); - /* appropriate N[15:8] */ - hdmi_write(hdmi, 0x18, HDMI_20_BIT_N_FOR_AUDIO_RPKT_15_8); - /* appropriate N[7:0] */ - hdmi_write(hdmi, 0x00, HDMI_20_BIT_N_FOR_AUDIO_RPKT_7_0); - - /* [7:4] 48 kHz SPDIF not used */ - hdmi_write(hdmi, 0x20, HDMI_SPDIF_AUDIO_SAMP_FREQ_CTS); - - /* - * [6:5] set required down sampling rate if required - * [4:3] set required audio source - */ - switch (pdata->flags & HDMI_SND_SRC_MASK) { - default: - /* fall through */ - case HDMI_SND_SRC_I2S: - data = 0x0 << 3; - break; - case HDMI_SND_SRC_SPDIF: - data = 0x1 << 3; - break; - case HDMI_SND_SRC_DSD: - data = 0x2 << 3; - break; - case HDMI_SND_SRC_HBR: - data = 0x3 << 3; - break; - } - hdmi_write(hdmi, data, HDMI_AUDIO_SETTING_1); - - /* [3:0] set sending channel number for channel status */ - hdmi_write(hdmi, 0x40, HDMI_AUDIO_SETTING_2); - - /* - * [5:2] set valid I2S source input pin - * [1:0] set input I2S source mode - */ - hdmi_write(hdmi, 0x04, HDMI_I2S_AUDIO_SET); - - /* [7:4] set valid DSD source input pin */ - hdmi_write(hdmi, 0x00, HDMI_DSD_AUDIO_SET); - - /* [7:0] set appropriate I2S input pin swap settings if required */ - hdmi_write(hdmi, 0x00, HDMI_I2S_INPUT_PIN_SWAP); - - /* - * [7] set validity bit for channel status - * [3:0] set original sample frequency for channel status - */ - hdmi_write(hdmi, 0x00, HDMI_AUDIO_STATUS_BITS_SETTING_1); - - /* - * [7] set value for channel status - * [6] set value for channel status - * [5] set copyright bit for channel status - * [4:2] set additional information for channel status - * [1:0] set clock accuracy for channel status - */ - hdmi_write(hdmi, 0x00, HDMI_AUDIO_STATUS_BITS_SETTING_2); - - /* [7:0] set category code for channel status */ - hdmi_write(hdmi, 0x00, HDMI_CATEGORY_CODE); - - /* - * [7:4] set source number for channel status - * [3:0] set word length for channel status - */ - hdmi_write(hdmi, 0x00, HDMI_SOURCE_NUM_AUDIO_WORD_LEN); - - /* [7:4] set sample frequency for channel status */ - hdmi_write(hdmi, 0x20, HDMI_AUDIO_VIDEO_SETTING_1); -} - -/** - * sh_hdmi_phy_config() - configure the HDMI PHY for the used video mode - */ -static void sh_hdmi_phy_config(struct sh_hdmi *hdmi) -{ - if (hdmi->mode.pixclock < 10000) { - /* for 1080p8bit 148MHz */ - hdmi_write(hdmi, 0x1d, HDMI_SLIPHDMIT_PARAM_SETTINGS_1); - hdmi_write(hdmi, 0x00, HDMI_SLIPHDMIT_PARAM_SETTINGS_2); - hdmi_write(hdmi, 0x00, HDMI_SLIPHDMIT_PARAM_SETTINGS_3); - hdmi_write(hdmi, 0x4c, HDMI_SLIPHDMIT_PARAM_SETTINGS_5); - hdmi_write(hdmi, 0x1e, HDMI_SLIPHDMIT_PARAM_SETTINGS_6); - hdmi_write(hdmi, 0x48, HDMI_SLIPHDMIT_PARAM_SETTINGS_7); - hdmi_write(hdmi, 0x0e, HDMI_SLIPHDMIT_PARAM_SETTINGS_8); - hdmi_write(hdmi, 0x25, HDMI_SLIPHDMIT_PARAM_SETTINGS_9); - hdmi_write(hdmi, 0x04, HDMI_SLIPHDMIT_PARAM_SETTINGS_10); - } else if (hdmi->mode.pixclock < 30000) { - /* 720p, 8bit, 74.25MHz. Might need to be adjusted for other formats */ - /* - * [1:0] Speed_A - * [3:2] Speed_B - * [4] PLLA_Bypass - * [6] DRV_TEST_EN - * [7] DRV_TEST_IN - */ - hdmi_write(hdmi, 0x0f, HDMI_SLIPHDMIT_PARAM_SETTINGS_1); - /* PLLB_CONFIG[17], PLLA_CONFIG[17] - not in PHY datasheet */ - hdmi_write(hdmi, 0x00, HDMI_SLIPHDMIT_PARAM_SETTINGS_2); - /* - * [2:0] BGR_I_OFFSET - * [6:4] BGR_V_OFFSET - */ - hdmi_write(hdmi, 0x00, HDMI_SLIPHDMIT_PARAM_SETTINGS_3); - /* PLLA_CONFIG[7:0]: VCO gain, VCO offset, LPF resistance[0] */ - hdmi_write(hdmi, 0x44, HDMI_SLIPHDMIT_PARAM_SETTINGS_5); - /* - * PLLA_CONFIG[15:8]: regulator voltage[0], CP current, - * LPF capacitance, LPF resistance[1] - */ - hdmi_write(hdmi, 0x32, HDMI_SLIPHDMIT_PARAM_SETTINGS_6); - /* PLLB_CONFIG[7:0]: LPF resistance[0], VCO offset, VCO gain */ - hdmi_write(hdmi, 0x4A, HDMI_SLIPHDMIT_PARAM_SETTINGS_7); - /* - * PLLB_CONFIG[15:8]: regulator voltage[0], CP current, - * LPF capacitance, LPF resistance[1] - */ - hdmi_write(hdmi, 0x00, HDMI_SLIPHDMIT_PARAM_SETTINGS_8); - /* DRV_CONFIG, PE_CONFIG */ - hdmi_write(hdmi, 0x25, HDMI_SLIPHDMIT_PARAM_SETTINGS_9); - /* - * [2:0] AMON_SEL (4 == LPF voltage) - * [4] PLLA_CONFIG[16] - * [5] PLLB_CONFIG[16] - */ - hdmi_write(hdmi, 0x04, HDMI_SLIPHDMIT_PARAM_SETTINGS_10); - } else { - /* for 480p8bit 27MHz */ - hdmi_write(hdmi, 0x19, HDMI_SLIPHDMIT_PARAM_SETTINGS_1); - hdmi_write(hdmi, 0x00, HDMI_SLIPHDMIT_PARAM_SETTINGS_2); - hdmi_write(hdmi, 0x00, HDMI_SLIPHDMIT_PARAM_SETTINGS_3); - hdmi_write(hdmi, 0x44, HDMI_SLIPHDMIT_PARAM_SETTINGS_5); - hdmi_write(hdmi, 0x32, HDMI_SLIPHDMIT_PARAM_SETTINGS_6); - hdmi_write(hdmi, 0x48, HDMI_SLIPHDMIT_PARAM_SETTINGS_7); - hdmi_write(hdmi, 0x0F, HDMI_SLIPHDMIT_PARAM_SETTINGS_8); - hdmi_write(hdmi, 0x20, HDMI_SLIPHDMIT_PARAM_SETTINGS_9); - hdmi_write(hdmi, 0x04, HDMI_SLIPHDMIT_PARAM_SETTINGS_10); - } -} - -/** - * sh_hdmi_avi_infoframe_setup() - Auxiliary Video Information InfoFrame CONTROL PACKET - */ -static void sh_hdmi_avi_infoframe_setup(struct sh_hdmi *hdmi) -{ - u8 vic; - - /* AVI InfoFrame */ - hdmi_write(hdmi, 0x06, HDMI_CTRL_PKT_BUF_INDEX); - - /* Packet Type = 0x82 */ - hdmi_write(hdmi, 0x82, HDMI_CTRL_PKT_BUF_ACCESS_HB0); - - /* Version = 0x02 */ - hdmi_write(hdmi, 0x02, HDMI_CTRL_PKT_BUF_ACCESS_HB1); - - /* Length = 13 (0x0D) */ - hdmi_write(hdmi, 0x0D, HDMI_CTRL_PKT_BUF_ACCESS_HB2); - - /* N. A. Checksum */ - hdmi_write(hdmi, 0x00, HDMI_CTRL_PKT_BUF_ACCESS_PB0); - - /* - * Y = RGB - * A0 = No Data - * B = Bar Data not valid - * S = No Data - */ - hdmi_write(hdmi, 0x00, HDMI_CTRL_PKT_BUF_ACCESS_PB1); - - /* - * [7:6] C = Colorimetry: no data - * [5:4] M = 2: 16:9, 1: 4:3 Picture Aspect Ratio - * [3:0] R = 8: Active Frame Aspect Ratio: same as picture aspect ratio - */ - hdmi_write(hdmi, 0x28, HDMI_CTRL_PKT_BUF_ACCESS_PB2); - - /* - * ITC = No Data - * EC = xvYCC601 - * Q = Default (depends on video format) - * SC = No Known non_uniform Scaling - */ - hdmi_write(hdmi, 0x00, HDMI_CTRL_PKT_BUF_ACCESS_PB3); - - /* - * VIC should be ignored if external config is used, so, we could just use 0, - * but play safe and use a valid value in any case just in case - */ - if (hdmi->preprogrammed_vic) - vic = hdmi->preprogrammed_vic; - else - vic = 4; - hdmi_write(hdmi, vic, HDMI_CTRL_PKT_BUF_ACCESS_PB4); - - /* PR = No Repetition */ - hdmi_write(hdmi, 0x00, HDMI_CTRL_PKT_BUF_ACCESS_PB5); - - /* Line Number of End of Top Bar (lower 8 bits) */ - hdmi_write(hdmi, 0x00, HDMI_CTRL_PKT_BUF_ACCESS_PB6); - - /* Line Number of End of Top Bar (upper 8 bits) */ - hdmi_write(hdmi, 0x00, HDMI_CTRL_PKT_BUF_ACCESS_PB7); - - /* Line Number of Start of Bottom Bar (lower 8 bits) */ - hdmi_write(hdmi, 0x00, HDMI_CTRL_PKT_BUF_ACCESS_PB8); - - /* Line Number of Start of Bottom Bar (upper 8 bits) */ - hdmi_write(hdmi, 0x00, HDMI_CTRL_PKT_BUF_ACCESS_PB9); - - /* Pixel Number of End of Left Bar (lower 8 bits) */ - hdmi_write(hdmi, 0x00, HDMI_CTRL_PKT_BUF_ACCESS_PB10); - - /* Pixel Number of End of Left Bar (upper 8 bits) */ - hdmi_write(hdmi, 0x00, HDMI_CTRL_PKT_BUF_ACCESS_PB11); - - /* Pixel Number of Start of Right Bar (lower 8 bits) */ - hdmi_write(hdmi, 0x00, HDMI_CTRL_PKT_BUF_ACCESS_PB12); - - /* Pixel Number of Start of Right Bar (upper 8 bits) */ - hdmi_write(hdmi, 0x00, HDMI_CTRL_PKT_BUF_ACCESS_PB13); -} - -/** - * sh_hdmi_audio_infoframe_setup() - Audio InfoFrame of CONTROL PACKET - */ -static void sh_hdmi_audio_infoframe_setup(struct sh_hdmi *hdmi) -{ - /* Audio InfoFrame */ - hdmi_write(hdmi, 0x08, HDMI_CTRL_PKT_BUF_INDEX); - - /* Packet Type = 0x84 */ - hdmi_write(hdmi, 0x84, HDMI_CTRL_PKT_BUF_ACCESS_HB0); - - /* Version Number = 0x01 */ - hdmi_write(hdmi, 0x01, HDMI_CTRL_PKT_BUF_ACCESS_HB1); - - /* 0 Length = 10 (0x0A) */ - hdmi_write(hdmi, 0x0A, HDMI_CTRL_PKT_BUF_ACCESS_HB2); - - /* n. a. Checksum */ - hdmi_write(hdmi, 0x00, HDMI_CTRL_PKT_BUF_ACCESS_PB0); - - /* Audio Channel Count = Refer to Stream Header */ - hdmi_write(hdmi, 0x00, HDMI_CTRL_PKT_BUF_ACCESS_PB1); - - /* Refer to Stream Header */ - hdmi_write(hdmi, 0x00, HDMI_CTRL_PKT_BUF_ACCESS_PB2); - - /* Format depends on coding type (i.e. CT0...CT3) */ - hdmi_write(hdmi, 0x00, HDMI_CTRL_PKT_BUF_ACCESS_PB3); - - /* Speaker Channel Allocation = Front Right + Front Left */ - hdmi_write(hdmi, 0x00, HDMI_CTRL_PKT_BUF_ACCESS_PB4); - - /* Level Shift Value = 0 dB, Down - mix is permitted or no information */ - hdmi_write(hdmi, 0x00, HDMI_CTRL_PKT_BUF_ACCESS_PB5); - - /* Reserved (0) */ - hdmi_write(hdmi, 0x00, HDMI_CTRL_PKT_BUF_ACCESS_PB6); - hdmi_write(hdmi, 0x00, HDMI_CTRL_PKT_BUF_ACCESS_PB7); - hdmi_write(hdmi, 0x00, HDMI_CTRL_PKT_BUF_ACCESS_PB8); - hdmi_write(hdmi, 0x00, HDMI_CTRL_PKT_BUF_ACCESS_PB9); - hdmi_write(hdmi, 0x00, HDMI_CTRL_PKT_BUF_ACCESS_PB10); -} - -/** - * sh_hdmi_configure() - Initialise HDMI for output - */ -static void sh_hdmi_configure(struct sh_hdmi *hdmi) -{ - /* Configure video format */ - sh_hdmi_video_config(hdmi); - - /* Configure audio format */ - sh_hdmi_audio_config(hdmi); - - /* Configure PHY */ - sh_hdmi_phy_config(hdmi); - - /* Auxiliary Video Information (AVI) InfoFrame */ - sh_hdmi_avi_infoframe_setup(hdmi); - - /* Audio InfoFrame */ - sh_hdmi_audio_infoframe_setup(hdmi); - - /* - * Control packet auto send with VSYNC control: auto send - * General control, Gamut metadata, ISRC, and ACP packets - */ - hdmi_write(hdmi, 0x8E, HDMI_CTRL_PKT_AUTO_SEND); - - /* FIXME */ - msleep(10); - - /* PS mode b->d, reset PLLA and PLLB */ - hdmi_bit_set(hdmi, 0xFC, 0x4C, HDMI_SYSTEM_CTRL); - - udelay(10); - - hdmi_bit_set(hdmi, 0xFC, 0x40, HDMI_SYSTEM_CTRL); -} - -static unsigned long sh_hdmi_rate_error(struct sh_hdmi *hdmi, - const struct fb_videomode *mode, - unsigned long *hdmi_rate, unsigned long *parent_rate) -{ - unsigned long target = PICOS2KHZ(mode->pixclock) * 1000, rate_error; - struct sh_mobile_hdmi_info *pdata = dev_get_platdata(hdmi->dev); - - *hdmi_rate = clk_round_rate(hdmi->hdmi_clk, target); - if ((long)*hdmi_rate < 0) - *hdmi_rate = clk_get_rate(hdmi->hdmi_clk); - - rate_error = (long)*hdmi_rate > 0 ? abs(*hdmi_rate - target) : ULONG_MAX; - if (rate_error && pdata->clk_optimize_parent) - rate_error = pdata->clk_optimize_parent(target, hdmi_rate, parent_rate); - else if (clk_get_parent(hdmi->hdmi_clk)) - *parent_rate = clk_get_rate(clk_get_parent(hdmi->hdmi_clk)); - - dev_dbg(hdmi->dev, "%u-%u-%u-%u x %u-%u-%u-%u\n", - mode->left_margin, mode->xres, - mode->right_margin, mode->hsync_len, - mode->upper_margin, mode->yres, - mode->lower_margin, mode->vsync_len); - - dev_dbg(hdmi->dev, "\t@%lu(+/-%lu)Hz, e=%lu / 1000, r=%uHz, p=%luHz\n", target, - rate_error, rate_error ? 10000 / (10 * target / rate_error) : 0, - mode->refresh, *parent_rate); - - return rate_error; -} - -static int sh_hdmi_read_edid(struct sh_hdmi *hdmi, unsigned long *hdmi_rate, - unsigned long *parent_rate) -{ - struct sh_mobile_lcdc_chan *ch = hdmi->entity.lcdc; - const struct fb_videomode *mode, *found = NULL; - unsigned int f_width = 0, f_height = 0, f_refresh = 0; - unsigned long found_rate_error = ULONG_MAX; /* silly compiler... */ - bool scanning = false, preferred_bad = false; - bool use_edid_mode = false; - u8 edid[128]; - char *forced; - int i; - - /* Read EDID */ - dev_dbg(hdmi->dev, "Read back EDID code:"); - for (i = 0; i < 128; i++) { - edid[i] = (hdmi->htop1) ? - (u8)hdmi_htop1_read(hdmi, HDMI_HTOP1_EDID_DATA_READ + (i * 4)) : - hdmi_read(hdmi, HDMI_EDID_KSV_FIFO_ACCESS_WINDOW); -#ifdef DEBUG - if ((i % 16) == 0) { - printk(KERN_CONT "\n"); - printk(KERN_DEBUG "%02X | %02X", i, edid[i]); - } else { - printk(KERN_CONT " %02X", edid[i]); - } -#endif - } -#ifdef DEBUG - printk(KERN_CONT "\n"); -#endif - - if (!hdmi->edid_blocks) { - fb_edid_to_monspecs(edid, &hdmi->monspec); - hdmi->edid_blocks = edid[126] + 1; - - dev_dbg(hdmi->dev, "%d main modes, %d extension blocks\n", - hdmi->monspec.modedb_len, hdmi->edid_blocks - 1); - } else { - dev_dbg(hdmi->dev, "Extension %u detected, DTD start %u\n", - edid[0], edid[2]); - fb_edid_add_monspecs(edid, &hdmi->monspec); - } - - if (hdmi->edid_blocks > hdmi->edid_segment_nr * 2 + - (hdmi->edid_block_addr >> 7) + 1) { - /* More blocks to read */ - if (hdmi->edid_block_addr) { - hdmi->edid_block_addr = 0; - hdmi->edid_segment_nr++; - } else { - hdmi->edid_block_addr = 0x80; - } - /* Set EDID word address */ - hdmi_write(hdmi, hdmi->edid_block_addr, HDMI_EDID_WORD_ADDRESS); - /* Enable EDID interrupt */ - hdmi_write(hdmi, 0xC6, HDMI_INTERRUPT_MASK_1); - /* Set EDID segment pointer - starts reading EDID */ - hdmi_write(hdmi, hdmi->edid_segment_nr, HDMI_EDID_SEGMENT_POINTER); - return -EAGAIN; - } - - /* All E-EDID blocks ready */ - dev_dbg(hdmi->dev, "%d main and extended modes\n", hdmi->monspec.modedb_len); - - fb_get_options("sh_mobile_lcdc", &forced); - if (forced && *forced) { - /* Only primitive parsing so far */ - i = sscanf(forced, "%ux%u@%u", - &f_width, &f_height, &f_refresh); - if (i < 2) { - f_width = 0; - f_height = 0; - } else { - /* The user wants us to use the EDID data */ - scanning = true; - } - dev_dbg(hdmi->dev, "Forced mode %ux%u@%uHz\n", - f_width, f_height, f_refresh); - } - - /* Walk monitor modes to find the best or the exact match */ - for (i = 0, mode = hdmi->monspec.modedb; - i < hdmi->monspec.modedb_len && scanning; - i++, mode++) { - unsigned long rate_error; - - if (!f_width && !f_height) { - /* - * A parameter string "video=sh_mobile_lcdc:0x0" means - * use the preferred EDID mode. If it is rejected by - * .fb_check_var(), keep looking, until an acceptable - * one is found. - */ - if ((mode->flag & FB_MODE_IS_FIRST) || preferred_bad) - scanning = false; - else - continue; - } else if (f_width != mode->xres || f_height != mode->yres) { - /* No interest in unmatching modes */ - continue; - } - - rate_error = sh_hdmi_rate_error(hdmi, mode, hdmi_rate, parent_rate); - - if (scanning) { - if (f_refresh == mode->refresh || (!f_refresh && !rate_error)) - /* - * Exact match if either the refresh rate - * matches or it hasn't been specified and we've - * found a mode, for which we can configure the - * clock precisely - */ - scanning = false; - else if (found && found_rate_error <= rate_error) - /* - * We otherwise search for the closest matching - * clock rate - either if no refresh rate has - * been specified or we cannot find an exactly - * matching one - */ - continue; - } - - /* Check if supported: sufficient fb memory, supported clock-rate */ - if (ch && ch->notify && - ch->notify(ch, SH_MOBILE_LCDC_EVENT_DISPLAY_MODE, mode, - NULL)) { - scanning = true; - preferred_bad = true; - continue; - } - - found = mode; - found_rate_error = rate_error; - use_edid_mode = true; - } - - /* - * TODO 1: if no default mode is present, postpone running the config - * until after the LCDC channel is initialized. - * TODO 2: consider registering the HDMI platform device from the LCDC - * driver. - */ - if (!found && hdmi->entity.def_mode.xres != 0) { - found = &hdmi->entity.def_mode; - found_rate_error = sh_hdmi_rate_error(hdmi, found, hdmi_rate, - parent_rate); - } - - /* No cookie today */ - if (!found) - return -ENXIO; - - if (found->xres == 640 && found->yres == 480 && found->refresh == 60) - hdmi->preprogrammed_vic = 1; - else if (found->xres == 720 && found->yres == 480 && found->refresh == 60) - hdmi->preprogrammed_vic = 2; - else if (found->xres == 720 && found->yres == 576 && found->refresh == 50) - hdmi->preprogrammed_vic = 17; - else if (found->xres == 1280 && found->yres == 720 && found->refresh == 60) - hdmi->preprogrammed_vic = 4; - else if (found->xres == 1920 && found->yres == 1080 && found->refresh == 24) - hdmi->preprogrammed_vic = 32; - else if (found->xres == 1920 && found->yres == 1080 && found->refresh == 50) - hdmi->preprogrammed_vic = 31; - else if (found->xres == 1920 && found->yres == 1080 && found->refresh == 60) - hdmi->preprogrammed_vic = 16; - else - hdmi->preprogrammed_vic = 0; - - dev_dbg(hdmi->dev, "Using %s %s mode %ux%u@%uHz (%luHz), " - "clock error %luHz\n", use_edid_mode ? "EDID" : "default", - hdmi->preprogrammed_vic ? "VIC" : "external", found->xres, - found->yres, found->refresh, PICOS2KHZ(found->pixclock) * 1000, - found_rate_error); - - hdmi->mode = *found; - sh_hdmi_external_video_param(hdmi); - - return 0; -} - -static irqreturn_t sh_hdmi_hotplug(int irq, void *dev_id) -{ - struct sh_hdmi *hdmi = dev_id; - u8 status1, status2, mask1, mask2; - - /* mode_b and PLLA and PLLB reset */ - hdmi_bit_set(hdmi, 0xFC, 0x2C, HDMI_SYSTEM_CTRL); - - /* How long shall reset be held? */ - udelay(10); - - /* mode_b and PLLA and PLLB reset release */ - hdmi_bit_set(hdmi, 0xFC, 0x20, HDMI_SYSTEM_CTRL); - - status1 = hdmi_read(hdmi, HDMI_INTERRUPT_STATUS_1); - status2 = hdmi_read(hdmi, HDMI_INTERRUPT_STATUS_2); - - mask1 = hdmi_read(hdmi, HDMI_INTERRUPT_MASK_1); - mask2 = hdmi_read(hdmi, HDMI_INTERRUPT_MASK_2); - - /* Correct would be to ack only set bits, but the datasheet requires 0xff */ - hdmi_write(hdmi, 0xFF, HDMI_INTERRUPT_STATUS_1); - hdmi_write(hdmi, 0xFF, HDMI_INTERRUPT_STATUS_2); - - if (printk_ratelimit()) - dev_dbg(hdmi->dev, "IRQ #%d: Status #1: 0x%x & 0x%x, #2: 0x%x & 0x%x\n", - irq, status1, mask1, status2, mask2); - - if (!((status1 & mask1) | (status2 & mask2))) { - return IRQ_NONE; - } else if (status1 & 0xc0) { - u8 msens; - - /* Datasheet specifies 10ms... */ - udelay(500); - - msens = hdmi_read(hdmi, HDMI_HOT_PLUG_MSENS_STATUS); - dev_dbg(hdmi->dev, "MSENS 0x%x\n", msens); - /* Check, if hot plug & MSENS pin status are both high */ - if ((msens & 0xC0) == 0xC0) { - /* Display plug in */ - hdmi->edid_segment_nr = 0; - hdmi->edid_block_addr = 0; - hdmi->edid_blocks = 0; - hdmi->hp_state = HDMI_HOTPLUG_CONNECTED; - - /* Set EDID word address */ - hdmi_write(hdmi, 0x00, HDMI_EDID_WORD_ADDRESS); - /* Enable EDID interrupt */ - hdmi_write(hdmi, 0xC6, HDMI_INTERRUPT_MASK_1); - /* Set EDID segment pointer - starts reading EDID */ - hdmi_write(hdmi, 0x00, HDMI_EDID_SEGMENT_POINTER); - } else if (!(status1 & 0x80)) { - /* Display unplug, beware multiple interrupts */ - if (hdmi->hp_state != HDMI_HOTPLUG_DISCONNECTED) { - hdmi->hp_state = HDMI_HOTPLUG_DISCONNECTED; - schedule_delayed_work(&hdmi->edid_work, 0); - } - /* display_off will switch back to mode_a */ - } - } else if (status1 & 2) { - /* EDID error interrupt: retry */ - /* Set EDID word address */ - hdmi_write(hdmi, hdmi->edid_block_addr, HDMI_EDID_WORD_ADDRESS); - /* Set EDID segment pointer */ - hdmi_write(hdmi, hdmi->edid_segment_nr, HDMI_EDID_SEGMENT_POINTER); - } else if (status1 & 4) { - /* Disable EDID interrupt */ - hdmi_write(hdmi, 0xC0, HDMI_INTERRUPT_MASK_1); - schedule_delayed_work(&hdmi->edid_work, msecs_to_jiffies(10)); - } - - return IRQ_HANDLED; -} - -static int sh_hdmi_display_on(struct sh_mobile_lcdc_entity *entity) -{ - struct sh_hdmi *hdmi = entity_to_sh_hdmi(entity); - - dev_dbg(hdmi->dev, "%s(%p): state %x\n", __func__, hdmi, - hdmi->hp_state); - - /* - * hp_state can be set to - * HDMI_HOTPLUG_DISCONNECTED: on monitor unplug - * HDMI_HOTPLUG_CONNECTED: on monitor plug-in - * HDMI_HOTPLUG_EDID_DONE: on EDID read completion - */ - if (hdmi->hp_state == HDMI_HOTPLUG_EDID_DONE) { - /* PS mode d->e. All functions are active */ - hdmi_bit_set(hdmi, 0xFC, 0x80, HDMI_SYSTEM_CTRL); - dev_dbg(hdmi->dev, "HDMI running\n"); - } - - return hdmi->hp_state == HDMI_HOTPLUG_DISCONNECTED - ? SH_MOBILE_LCDC_DISPLAY_DISCONNECTED - : SH_MOBILE_LCDC_DISPLAY_CONNECTED; -} - -static void sh_hdmi_display_off(struct sh_mobile_lcdc_entity *entity) -{ - struct sh_hdmi *hdmi = entity_to_sh_hdmi(entity); - - dev_dbg(hdmi->dev, "%s(%p)\n", __func__, hdmi); - /* PS mode e->a */ - hdmi_bit_set(hdmi, 0xFC, 0x10, HDMI_SYSTEM_CTRL); -} - -static const struct sh_mobile_lcdc_entity_ops sh_hdmi_ops = { - .display_on = sh_hdmi_display_on, - .display_off = sh_hdmi_display_off, -}; - -/** - * sh_hdmi_clk_configure() - set HDMI clock frequency and enable the clock - * @hdmi: driver context - * @hdmi_rate: HDMI clock frequency in Hz - * @parent_rate: if != 0 - set parent clock rate for optimal precision - * return: configured positive rate if successful - * 0 if couldn't set the rate, but managed to enable the - * clock, negative error, if couldn't enable the clock - */ -static long sh_hdmi_clk_configure(struct sh_hdmi *hdmi, unsigned long hdmi_rate, - unsigned long parent_rate) -{ - int ret; - - if (parent_rate && clk_get_parent(hdmi->hdmi_clk)) { - ret = clk_set_rate(clk_get_parent(hdmi->hdmi_clk), parent_rate); - if (ret < 0) { - dev_warn(hdmi->dev, "Cannot set parent rate %ld: %d\n", parent_rate, ret); - hdmi_rate = clk_round_rate(hdmi->hdmi_clk, hdmi_rate); - } else { - dev_dbg(hdmi->dev, "HDMI set parent frequency %lu\n", parent_rate); - } - } - - ret = clk_set_rate(hdmi->hdmi_clk, hdmi_rate); - if (ret < 0) { - dev_warn(hdmi->dev, "Cannot set rate %ld: %d\n", hdmi_rate, ret); - hdmi_rate = 0; - } else { - dev_dbg(hdmi->dev, "HDMI set frequency %lu\n", hdmi_rate); - } - - return hdmi_rate; -} - -/* Hotplug interrupt occurred, read EDID */ -static void sh_hdmi_edid_work_fn(struct work_struct *work) -{ - struct sh_hdmi *hdmi = container_of(work, struct sh_hdmi, edid_work.work); - struct sh_mobile_lcdc_chan *ch = hdmi->entity.lcdc; - int ret; - - dev_dbg(hdmi->dev, "%s(%p): begin, hotplug status %d\n", __func__, hdmi, - hdmi->hp_state); - - if (hdmi->hp_state == HDMI_HOTPLUG_CONNECTED) { - unsigned long parent_rate = 0, hdmi_rate; - - ret = sh_hdmi_read_edid(hdmi, &hdmi_rate, &parent_rate); - if (ret < 0) - goto out; - - hdmi->hp_state = HDMI_HOTPLUG_EDID_DONE; - - /* Reconfigure the clock */ - ret = sh_hdmi_clk_configure(hdmi, hdmi_rate, parent_rate); - if (ret < 0) - goto out; - - msleep(10); - sh_hdmi_configure(hdmi); - /* Switched to another (d) power-save mode */ - msleep(10); - - if (ch && ch->notify) - ch->notify(ch, SH_MOBILE_LCDC_EVENT_DISPLAY_CONNECT, - &hdmi->mode, &hdmi->monspec); - } else { - hdmi->monspec.modedb_len = 0; - fb_destroy_modedb(hdmi->monspec.modedb); - hdmi->monspec.modedb = NULL; - - if (ch && ch->notify) - ch->notify(ch, SH_MOBILE_LCDC_EVENT_DISPLAY_DISCONNECT, - NULL, NULL); - - ret = 0; - } - -out: - if (ret < 0 && ret != -EAGAIN) - hdmi->hp_state = HDMI_HOTPLUG_DISCONNECTED; - - dev_dbg(hdmi->dev, "%s(%p): end\n", __func__, hdmi); -} - -static void sh_hdmi_htop1_init(struct sh_hdmi *hdmi) -{ - hdmi_htop1_write(hdmi, 0x00000000, HDMI_HTOP1_HTOP_DCL_MODE); - hdmi_htop1_write(hdmi, 0x0000000b, 0x0010); - hdmi_htop1_write(hdmi, 0x00006710, HDMI_HTOP1_HTOP_DCL_FRC_MODE); - hdmi_htop1_write(hdmi, 0x01020406, HDMI_HTOP1_HTOP_DCL_FIL_PARA_Y1_1); - hdmi_htop1_write(hdmi, 0x07080806, HDMI_HTOP1_HTOP_DCL_FIL_PARA_Y1_2); - hdmi_htop1_write(hdmi, 0x01020406, HDMI_HTOP1_HTOP_DCL_FIL_PARA_CB1_1); - hdmi_htop1_write(hdmi, 0x07080806, HDMI_HTOP1_HTOP_DCL_FIL_PARA_CB1_2); - hdmi_htop1_write(hdmi, 0x01020406, HDMI_HTOP1_HTOP_DCL_FIL_PARA_CR1_1); - hdmi_htop1_write(hdmi, 0x07080806, HDMI_HTOP1_HTOP_DCL_FIL_PARA_CR1_2); - hdmi_htop1_write(hdmi, 0x01020406, HDMI_HTOP1_HTOP_DCL_FIL_PARA_Y2_1); - hdmi_htop1_write(hdmi, 0x07080806, HDMI_HTOP1_HTOP_DCL_FIL_PARA_Y2_2); - hdmi_htop1_write(hdmi, 0x01020406, HDMI_HTOP1_HTOP_DCL_FIL_PARA_CB2_1); - hdmi_htop1_write(hdmi, 0x07080806, HDMI_HTOP1_HTOP_DCL_FIL_PARA_CB2_2); - hdmi_htop1_write(hdmi, 0x01020406, HDMI_HTOP1_HTOP_DCL_FIL_PARA_CR2_1); - hdmi_htop1_write(hdmi, 0x07080806, HDMI_HTOP1_HTOP_DCL_FIL_PARA_CR2_2); - hdmi_htop1_write(hdmi, 0x00000000, HDMI_HTOP1_HTOP_DCL_COR_PARA_Y1); - hdmi_htop1_write(hdmi, 0x00000000, HDMI_HTOP1_HTOP_DCL_COR_PARA_CB1); - hdmi_htop1_write(hdmi, 0x00000000, HDMI_HTOP1_HTOP_DCL_COR_PARA_CR1); - hdmi_htop1_write(hdmi, 0x00000000, HDMI_HTOP1_HTOP_DCL_COR_PARA_Y2); - hdmi_htop1_write(hdmi, 0x00000000, HDMI_HTOP1_HTOP_DCL_COR_PARA_CB2); - hdmi_htop1_write(hdmi, 0x00000000, HDMI_HTOP1_HTOP_DCL_COR_PARA_CR2); - hdmi_htop1_write(hdmi, 0x00000008, HDMI_HTOP1_CURRENT); - hdmi_htop1_write(hdmi, 0x00000000, HDMI_HTOP1_TISEMP0_1); - hdmi_htop1_write(hdmi, 0x00000000, HDMI_HTOP1_TISEMP2_C); - hdmi_htop1_write(hdmi, 0x00000000, HDMI_HTOP1_PHY_TEST_MODE); - hdmi_htop1_write(hdmi, 0x00000081, HDMI_HTOP1_TISIDRV); - hdmi_htop1_write(hdmi, 0x00000000, HDMI_HTOP1_PLLBW); - hdmi_htop1_write(hdmi, 0x0000000f, HDMI_HTOP1_TISEN); - hdmi_htop1_write(hdmi, 0x0000000f, HDMI_HTOP1_TISDREN); - hdmi_htop1_write(hdmi, 0x00000003, HDMI_HTOP1_ENABLE_SELECTOR); - hdmi_htop1_write(hdmi, 0x00000001, HDMI_HTOP1_MACRO_RESET); - hdmi_htop1_write(hdmi, 0x00000016, HDMI_HTOP1_CISRANGE); - msleep(100); - hdmi_htop1_write(hdmi, 0x00000001, HDMI_HTOP1_ENABLE_SELECTOR); - msleep(100); - hdmi_htop1_write(hdmi, 0x00000003, HDMI_HTOP1_ENABLE_SELECTOR); - hdmi_htop1_write(hdmi, 0x00000001, HDMI_HTOP1_MACRO_RESET); - hdmi_htop1_write(hdmi, 0x0000000f, HDMI_HTOP1_TISEN); - hdmi_htop1_write(hdmi, 0x0000000f, HDMI_HTOP1_TISDREN); - hdmi_htop1_write(hdmi, 0x00000000, HDMI_HTOP1_VIDEO_INPUT); - hdmi_htop1_write(hdmi, 0x00000000, HDMI_HTOP1_CLK_TO_PHY); - hdmi_htop1_write(hdmi, 0x00000000, HDMI_HTOP1_VIDEO_INPUT2); - hdmi_htop1_write(hdmi, 0x0000000a, HDMI_HTOP1_CLK_SET); -} - -static int __init sh_hdmi_probe(struct platform_device *pdev) -{ - struct sh_mobile_hdmi_info *pdata = dev_get_platdata(&pdev->dev); - struct resource *res = platform_get_resource(pdev, IORESOURCE_MEM, 0); - struct resource *htop1_res; - int irq = platform_get_irq(pdev, 0), ret; - struct sh_hdmi *hdmi; - long rate; - - if (!res || !pdata || irq < 0) - return -ENODEV; - - htop1_res = NULL; - if (pdata->flags & HDMI_HAS_HTOP1) { - htop1_res = platform_get_resource(pdev, IORESOURCE_MEM, 1); - if (!htop1_res) { - dev_err(&pdev->dev, "htop1 needs register base\n"); - return -EINVAL; - } - } - - hdmi = devm_kzalloc(&pdev->dev, sizeof(*hdmi), GFP_KERNEL); - if (!hdmi) { - dev_err(&pdev->dev, "Cannot allocate device data\n"); - return -ENOMEM; - } - - hdmi->dev = &pdev->dev; - hdmi->entity.owner = THIS_MODULE; - hdmi->entity.ops = &sh_hdmi_ops; - hdmi->irq = irq; - - hdmi->hdmi_clk = clk_get(&pdev->dev, "ick"); - if (IS_ERR(hdmi->hdmi_clk)) { - ret = PTR_ERR(hdmi->hdmi_clk); - dev_err(&pdev->dev, "Unable to get clock: %d\n", ret); - return ret; - } - - /* select register access functions */ - if (pdata->flags & HDMI_32BIT_REG) { - hdmi->write = __hdmi_write32; - hdmi->read = __hdmi_read32; - } else { - hdmi->write = __hdmi_write8; - hdmi->read = __hdmi_read8; - } - - /* An arbitrary relaxed pixclock just to get things started: from standard 480p */ - rate = clk_round_rate(hdmi->hdmi_clk, PICOS2KHZ(37037)); - if (rate > 0) - rate = sh_hdmi_clk_configure(hdmi, rate, 0); - - if (rate < 0) { - ret = rate; - goto erate; - } - - ret = clk_prepare_enable(hdmi->hdmi_clk); - if (ret < 0) { - dev_err(hdmi->dev, "Cannot enable clock: %d\n", ret); - goto erate; - } - - dev_dbg(&pdev->dev, "Enabled HDMI clock at %luHz\n", rate); - - if (!request_mem_region(res->start, resource_size(res), dev_name(&pdev->dev))) { - dev_err(&pdev->dev, "HDMI register region already claimed\n"); - ret = -EBUSY; - goto ereqreg; - } - - hdmi->base = ioremap(res->start, resource_size(res)); - if (!hdmi->base) { - dev_err(&pdev->dev, "HDMI register region already claimed\n"); - ret = -ENOMEM; - goto emap; - } - - platform_set_drvdata(pdev, &hdmi->entity); - - INIT_DELAYED_WORK(&hdmi->edid_work, sh_hdmi_edid_work_fn); - - pm_runtime_enable(&pdev->dev); - pm_runtime_get_sync(&pdev->dev); - - /* init interrupt polarity */ - if (pdata->flags & HDMI_OUTPUT_PUSH_PULL) - hdmi_bit_set(hdmi, 0x02, 0x02, HDMI_SYSTEM_CTRL); - - if (pdata->flags & HDMI_OUTPUT_POLARITY_HI) - hdmi_bit_set(hdmi, 0x01, 0x01, HDMI_SYSTEM_CTRL); - - /* enable htop1 register if needed */ - if (htop1_res) { - hdmi->htop1 = ioremap(htop1_res->start, resource_size(htop1_res)); - if (!hdmi->htop1) { - dev_err(&pdev->dev, "control register region already claimed\n"); - ret = -ENOMEM; - goto emap_htop1; - } - sh_hdmi_htop1_init(hdmi); - } - - /* Product and revision IDs are 0 in sh-mobile version */ - dev_info(&pdev->dev, "Detected HDMI controller 0x%x:0x%x\n", - hdmi_read(hdmi, HDMI_PRODUCT_ID), hdmi_read(hdmi, HDMI_REVISION_ID)); - - ret = request_irq(irq, sh_hdmi_hotplug, 0, - dev_name(&pdev->dev), hdmi); - if (ret < 0) { - dev_err(&pdev->dev, "Unable to request irq: %d\n", ret); - goto ereqirq; - } - - ret = snd_soc_register_codec(&pdev->dev, - &soc_codec_dev_sh_hdmi, &sh_hdmi_dai, 1); - if (ret < 0) { - dev_err(&pdev->dev, "codec registration failed\n"); - goto ecodec; - } - - return 0; - -ecodec: - free_irq(irq, hdmi); -ereqirq: - if (hdmi->htop1) - iounmap(hdmi->htop1); -emap_htop1: - pm_runtime_put(&pdev->dev); - pm_runtime_disable(&pdev->dev); - iounmap(hdmi->base); -emap: - release_mem_region(res->start, resource_size(res)); -ereqreg: - clk_disable_unprepare(hdmi->hdmi_clk); -erate: - clk_put(hdmi->hdmi_clk); - - return ret; -} - -static int __exit sh_hdmi_remove(struct platform_device *pdev) -{ - struct sh_hdmi *hdmi = entity_to_sh_hdmi(platform_get_drvdata(pdev)); - struct resource *res = platform_get_resource(pdev, IORESOURCE_MEM, 0); - - snd_soc_unregister_codec(&pdev->dev); - - /* No new work will be scheduled, wait for running ISR */ - free_irq(hdmi->irq, hdmi); - /* Wait for already scheduled work */ - cancel_delayed_work_sync(&hdmi->edid_work); - pm_runtime_put(&pdev->dev); - pm_runtime_disable(&pdev->dev); - clk_disable_unprepare(hdmi->hdmi_clk); - clk_put(hdmi->hdmi_clk); - if (hdmi->htop1) - iounmap(hdmi->htop1); - iounmap(hdmi->base); - release_mem_region(res->start, resource_size(res)); - - return 0; -} - -static int sh_hdmi_suspend(struct device *dev) -{ - struct platform_device *pdev = to_platform_device(dev); - struct sh_hdmi *hdmi = entity_to_sh_hdmi(platform_get_drvdata(pdev)); - - disable_irq(hdmi->irq); - /* Wait for already scheduled work */ - cancel_delayed_work_sync(&hdmi->edid_work); - return 0; -} - -static int sh_hdmi_resume(struct device *dev) -{ - struct platform_device *pdev = to_platform_device(dev); - struct sh_mobile_hdmi_info *pdata = dev_get_platdata(dev); - struct sh_hdmi *hdmi = entity_to_sh_hdmi(platform_get_drvdata(pdev)); - - /* Re-init interrupt polarity */ - if (pdata->flags & HDMI_OUTPUT_PUSH_PULL) - hdmi_bit_set(hdmi, 0x02, 0x02, HDMI_SYSTEM_CTRL); - - if (pdata->flags & HDMI_OUTPUT_POLARITY_HI) - hdmi_bit_set(hdmi, 0x01, 0x01, HDMI_SYSTEM_CTRL); - - /* Re-init htop1 */ - if (hdmi->htop1) - sh_hdmi_htop1_init(hdmi); - - /* Now it's safe to enable interrupts again */ - enable_irq(hdmi->irq); - return 0; -} - -static const struct dev_pm_ops sh_hdmi_pm_ops = { - .suspend = sh_hdmi_suspend, - .resume = sh_hdmi_resume, -}; - -static struct platform_driver sh_hdmi_driver = { - .remove = __exit_p(sh_hdmi_remove), - .driver = { - .name = "sh-mobile-hdmi", - .pm = &sh_hdmi_pm_ops, - }, -}; - -module_platform_driver_probe(sh_hdmi_driver, sh_hdmi_probe); - -MODULE_AUTHOR("Guennadi Liakhovetski <g.liakhovetski@gmx.de>"); -MODULE_DESCRIPTION("SuperH / ARM-shmobile HDMI driver"); -MODULE_LICENSE("GPL v2"); diff --git a/drivers/video/fbdev/simplefb.c b/drivers/video/fbdev/simplefb.c index 52c5c7e63b52..48ccf6db62a2 100644 --- a/drivers/video/fbdev/simplefb.c +++ b/drivers/video/fbdev/simplefb.c @@ -28,7 +28,10 @@ #include <linux/platform_device.h> #include <linux/clk.h> #include <linux/clk-provider.h> +#include <linux/of.h> #include <linux/of_platform.h> +#include <linux/parser.h> +#include <linux/regulator/consumer.h> static struct fb_fix_screeninfo simplefb_fix = { .id = "simple", @@ -174,6 +177,10 @@ struct simplefb_par { int clk_count; struct clk **clks; #endif +#if defined CONFIG_OF && defined CONFIG_REGULATOR + u32 regulator_count; + struct regulator **regulators; +#endif }; #if defined CONFIG_OF && defined CONFIG_COMMON_CLK @@ -269,6 +276,110 @@ static int simplefb_clocks_init(struct simplefb_par *par, static void simplefb_clocks_destroy(struct simplefb_par *par) { } #endif +#if defined CONFIG_OF && defined CONFIG_REGULATOR + +#define SUPPLY_SUFFIX "-supply" + +/* + * Regulator handling code. + * + * Here we handle the num-supplies and vin*-supply properties of our + * "simple-framebuffer" dt node. This is necessary so that we can make sure + * that any regulators needed by the display hardware that the bootloader + * set up for us (and for which it provided a simplefb dt node), stay up, + * for the life of the simplefb driver. + * + * When the driver unloads, we cleanly disable, and then release the + * regulators. + * + * We only complain about errors here, no action is taken as the most likely + * error can only happen due to a mismatch between the bootloader which set + * up simplefb, and the regulator definitions in the device tree. Chances are + * that there are no adverse effects, and if there are, a clean teardown of + * the fb probe will not help us much either. So just complain and carry on, + * and hope that the user actually gets a working fb at the end of things. + */ +static int simplefb_regulators_init(struct simplefb_par *par, + struct platform_device *pdev) +{ + struct device_node *np = pdev->dev.of_node; + struct property *prop; + struct regulator *regulator; + const char *p; + int count = 0, i = 0, ret; + + if (dev_get_platdata(&pdev->dev) || !np) + return 0; + + /* Count the number of regulator supplies */ + for_each_property_of_node(np, prop) { + p = strstr(prop->name, SUPPLY_SUFFIX); + if (p && p != prop->name) + count++; + } + + if (!count) + return 0; + + par->regulators = devm_kcalloc(&pdev->dev, count, + sizeof(struct regulator *), GFP_KERNEL); + if (!par->regulators) + return -ENOMEM; + + /* Get all the regulators */ + for_each_property_of_node(np, prop) { + char name[32]; /* 32 is max size of property name */ + + p = strstr(prop->name, SUPPLY_SUFFIX); + if (!p || p == prop->name) + continue; + + strlcpy(name, prop->name, + strlen(prop->name) - strlen(SUPPLY_SUFFIX) + 1); + regulator = devm_regulator_get_optional(&pdev->dev, name); + if (IS_ERR(regulator)) { + if (PTR_ERR(regulator) == -EPROBE_DEFER) + return -EPROBE_DEFER; + dev_err(&pdev->dev, "regulator %s not found: %ld\n", + name, PTR_ERR(regulator)); + continue; + } + par->regulators[i++] = regulator; + } + par->regulator_count = i; + + /* Enable all the regulators */ + for (i = 0; i < par->regulator_count; i++) { + ret = regulator_enable(par->regulators[i]); + if (ret) { + dev_err(&pdev->dev, + "failed to enable regulator %d: %d\n", + i, ret); + devm_regulator_put(par->regulators[i]); + par->regulators[i] = NULL; + } + } + + return 0; +} + +static void simplefb_regulators_destroy(struct simplefb_par *par) +{ + int i; + + if (!par->regulators) + return; + + for (i = 0; i < par->regulator_count; i++) + if (par->regulators[i]) + regulator_disable(par->regulators[i]); +} +#else +static int simplefb_regulators_init(struct simplefb_par *par, + struct platform_device *pdev) { return 0; } +static void simplefb_regulators_destroy(struct simplefb_par *par) { } +#endif + static int simplefb_probe(struct platform_device *pdev) { int ret; @@ -340,6 +451,10 @@ static int simplefb_probe(struct platform_device *pdev) if (ret < 0) goto error_unmap; + ret = simplefb_regulators_init(par, pdev); + if (ret < 0) + goto error_clocks; + dev_info(&pdev->dev, "framebuffer at 0x%lx, 0x%x bytes, mapped to 0x%p\n", info->fix.smem_start, info->fix.smem_len, info->screen_base); @@ -351,13 +466,15 @@ static int simplefb_probe(struct platform_device *pdev) ret = register_framebuffer(info); if (ret < 0) { dev_err(&pdev->dev, "Unable to register simplefb: %d\n", ret); - goto error_clocks; + goto error_regulators; } dev_info(&pdev->dev, "fb%d: simplefb registered!\n", info->node); return 0; +error_regulators: + simplefb_regulators_destroy(par); error_clocks: simplefb_clocks_destroy(par); error_unmap: @@ -373,6 +490,7 @@ static int simplefb_remove(struct platform_device *pdev) struct simplefb_par *par = info->par; unregister_framebuffer(info); + simplefb_regulators_destroy(par); simplefb_clocks_destroy(par); framebuffer_release(info); diff --git a/drivers/video/fbdev/sm712fb.c b/drivers/video/fbdev/sm712fb.c index 629bfa2d2f51..86ae1d4556fc 100644 --- a/drivers/video/fbdev/sm712fb.c +++ b/drivers/video/fbdev/sm712fb.c @@ -28,9 +28,7 @@ #include <linux/console.h> #include <linux/screen_info.h> -#ifdef CONFIG_PM #include <linux/pm.h> -#endif #include "sm712.h" @@ -1545,8 +1543,7 @@ static void smtcfb_pci_remove(struct pci_dev *pdev) pci_disable_device(pdev); } -#ifdef CONFIG_PM -static int smtcfb_pci_suspend(struct device *device) +static int __maybe_unused smtcfb_pci_suspend(struct device *device) { struct pci_dev *pdev = to_pci_dev(device); struct smtcfb_info *sfb; @@ -1569,7 +1566,7 @@ static int smtcfb_pci_suspend(struct device *device) return 0; } -static int smtcfb_pci_resume(struct device *device) +static int __maybe_unused smtcfb_pci_resume(struct device *device) { struct pci_dev *pdev = to_pci_dev(device); struct smtcfb_info *sfb; @@ -1610,20 +1607,13 @@ static int smtcfb_pci_resume(struct device *device) } static SIMPLE_DEV_PM_OPS(sm7xx_pm_ops, smtcfb_pci_suspend, smtcfb_pci_resume); -#define SM7XX_PM_OPS (&sm7xx_pm_ops) - -#else /* !CONFIG_PM */ - -#define SM7XX_PM_OPS NULL - -#endif /* !CONFIG_PM */ static struct pci_driver smtcfb_driver = { .name = "smtcfb", .id_table = smtcfb_pci_table, .probe = smtcfb_pci_probe, .remove = smtcfb_pci_remove, - .driver.pm = SM7XX_PM_OPS, + .driver.pm = &sm7xx_pm_ops, }; static int __init sm712fb_init(void) |