diff options
38 files changed, 516 insertions, 563 deletions
diff --git a/Documentation/devicetree/bindings/video/via,vt8500-fb.txt b/Documentation/devicetree/bindings/video/via,vt8500-fb.txt index c870b6478ec..2871e218a0f 100644 --- a/Documentation/devicetree/bindings/video/via,vt8500-fb.txt +++ b/Documentation/devicetree/bindings/video/via,vt8500-fb.txt @@ -5,58 +5,32 @@ Required properties: - compatible : "via,vt8500-fb" - reg : Should contain 1 register ranges(address and length) - interrupts : framebuffer controller interrupt -- display: a phandle pointing to the display node +- bits-per-pixel : bit depth of framebuffer (16 or 32) -Required nodes: -- display: a display node is required to initialize the lcd panel - This should be in the board dts. -- default-mode: a videomode within the display with timing parameters - as specified below. +Required subnodes: +- display-timings: see display-timing.txt for information Example: - fb@d800e400 { + fb@d8050800 { compatible = "via,vt8500-fb"; reg = <0xd800e400 0x400>; interrupts = <12>; - display = <&display>; - default-mode = <&mode0>; - }; - -VIA VT8500 Display ------------------------------------------------------ -Required properties (as per of_videomode_helper): - - - hactive, vactive: Display resolution - - hfront-porch, hback-porch, hsync-len: Horizontal Display timing parameters - in pixels - vfront-porch, vback-porch, vsync-len: Vertical display timing parameters in - lines - - clock: displayclock in Hz - - bpp: lcd panel bit-depth. - <16> for RGB565, <32> for RGB888 - -Optional properties (as per of_videomode_helper): - - width-mm, height-mm: Display dimensions in mm - - hsync-active-high (bool): Hsync pulse is active high - - vsync-active-high (bool): Vsync pulse is active high - - interlaced (bool): This is an interlaced mode - - doublescan (bool): This is a doublescan mode + bits-per-pixel = <16>; -Example: - display: display@0 { - modes { - mode0: mode@0 { + display-timings { + native-mode = <&timing0>; + timing0: 800x480 { + clock-frequency = <0>; /* unused but required */ hactive = <800>; vactive = <480>; - hback-porch = <88>; hfront-porch = <40>; + hback-porch = <88>; hsync-len = <0>; vback-porch = <32>; vfront-porch = <11>; vsync-len = <1>; - clock = <0>; /* unused but required */ - bpp = <16>; /* non-standard but required */ }; }; }; + diff --git a/Documentation/devicetree/bindings/video/wm,wm8505-fb.txt b/Documentation/devicetree/bindings/video/wm,wm8505-fb.txt index 3d325e1d11e..0bcadb2840a 100644 --- a/Documentation/devicetree/bindings/video/wm,wm8505-fb.txt +++ b/Documentation/devicetree/bindings/video/wm,wm8505-fb.txt @@ -4,20 +4,30 @@ Wondermedia WM8505 Framebuffer Required properties: - compatible : "wm,wm8505-fb" - reg : Should contain 1 register ranges(address and length) -- via,display: a phandle pointing to the display node +- bits-per-pixel : bit depth of framebuffer (16 or 32) -Required nodes: -- display: a display node is required to initialize the lcd panel - This should be in the board dts. See definition in - Documentation/devicetree/bindings/video/via,vt8500-fb.txt -- default-mode: a videomode node as specified in - Documentation/devicetree/bindings/video/via,vt8500-fb.txt +Required subnodes: +- display-timings: see display-timing.txt for information Example: - fb@d8050800 { + fb@d8051700 { compatible = "wm,wm8505-fb"; - reg = <0xd8050800 0x200>; - display = <&display>; - default-mode = <&mode0>; + reg = <0xd8051700 0x200>; + bits-per-pixel = <16>; + + display-timings { + native-mode = <&timing0>; + timing0: 800x480 { + clock-frequency = <0>; /* unused but required */ + hactive = <800>; + vactive = <480>; + hfront-porch = <40>; + hback-porch = <88>; + hsync-len = <0>; + vback-porch = <32>; + vfront-porch = <11>; + vsync-len = <1>; + }; + }; }; diff --git a/arch/arm/boot/dts/vt8500-bv07.dts b/arch/arm/boot/dts/vt8500-bv07.dts index 567cf4e8ab8..877b33afa7e 100644 --- a/arch/arm/boot/dts/vt8500-bv07.dts +++ b/arch/arm/boot/dts/vt8500-bv07.dts @@ -11,26 +11,22 @@ / { model = "Benign BV07 Netbook"; +}; - /* - * Display node is based on Sascha Hauer's patch on dri-devel. - * Added a bpp property to calculate the size of the framebuffer - * until the binding is formalized. - */ - display: display@0 { - modes { - mode0: mode@0 { - hactive = <800>; - vactive = <480>; - hback-porch = <88>; - hfront-porch = <40>; - hsync-len = <0>; - vback-porch = <32>; - vfront-porch = <11>; - vsync-len = <1>; - clock = <0>; /* unused but required */ - bpp = <16>; /* non-standard but required */ - }; +&fb { + bits-per-pixel = <16>; + display-timings { + native-mode = <&timing0>; + timing0: 800x480 { + clock-frequency = <0>; /* unused but required */ + hactive = <800>; + vactive = <480>; + hfront-porch = <40>; + hback-porch = <88>; + hsync-len = <0>; + vback-porch = <32>; + vfront-porch = <11>; + vsync-len = <1>; }; }; }; diff --git a/arch/arm/boot/dts/vt8500.dtsi b/arch/arm/boot/dts/vt8500.dtsi index cf31ced4660..68c8dc64438 100644 --- a/arch/arm/boot/dts/vt8500.dtsi +++ b/arch/arm/boot/dts/vt8500.dtsi @@ -98,12 +98,10 @@ interrupts = <43>; }; - fb@d800e400 { + fb: fb@d8050800 { compatible = "via,vt8500-fb"; reg = <0xd800e400 0x400>; interrupts = <12>; - display = <&display>; - default-mode = <&mode0>; }; ge_rops@d8050400 { diff --git a/arch/arm/boot/dts/wm8505-ref.dts b/arch/arm/boot/dts/wm8505-ref.dts index fd4e248074c..edd2cec3d37 100644 --- a/arch/arm/boot/dts/wm8505-ref.dts +++ b/arch/arm/boot/dts/wm8505-ref.dts @@ -11,26 +11,22 @@ / { model = "Wondermedia WM8505 Netbook"; +}; - /* - * Display node is based on Sascha Hauer's patch on dri-devel. - * Added a bpp property to calculate the size of the framebuffer - * until the binding is formalized. - */ - display: display@0 { - modes { - mode0: mode@0 { - hactive = <800>; - vactive = <480>; - hback-porch = <88>; - hfront-porch = <40>; - hsync-len = <0>; - vback-porch = <32>; - vfront-porch = <11>; - vsync-len = <1>; - clock = <0>; /* unused but required */ - bpp = <32>; /* non-standard but required */ - }; +&fb { + bits-per-pixel = <32>; + display-timings { + native-mode = <&timing0>; + timing0: 800x480 { + clock-frequency = <0>; /* unused but required */ + hactive = <800>; + vactive = <480>; + hfront-porch = <40>; + hback-porch = <88>; + hsync-len = <0>; + vback-porch = <32>; + vfront-porch = <11>; + vsync-len = <1>; }; }; }; diff --git a/arch/arm/boot/dts/wm8505.dtsi b/arch/arm/boot/dts/wm8505.dtsi index e74a1c0fb9a..bcf668d31b2 100644 --- a/arch/arm/boot/dts/wm8505.dtsi +++ b/arch/arm/boot/dts/wm8505.dtsi @@ -128,11 +128,9 @@ interrupts = <0>; }; - fb@d8050800 { + fb: fb@d8050800 { compatible = "wm,wm8505-fb"; reg = <0xd8050800 0x200>; - display = <&display>; - default-mode = <&mode0>; }; ge_rops@d8050400 { diff --git a/arch/arm/boot/dts/wm8650-mid.dts b/arch/arm/boot/dts/wm8650-mid.dts index cefd938f842..61671a0d9ed 100644 --- a/arch/arm/boot/dts/wm8650-mid.dts +++ b/arch/arm/boot/dts/wm8650-mid.dts @@ -11,26 +11,24 @@ / { model = "Wondermedia WM8650-MID Tablet"; +}; + +&fb { + bits-per-pixel = <16>; - /* - * Display node is based on Sascha Hauer's patch on dri-devel. - * Added a bpp property to calculate the size of the framebuffer - * until the binding is formalized. - */ - display: display@0 { - modes { - mode0: mode@0 { - hactive = <800>; - vactive = <480>; - hback-porch = <88>; - hfront-porch = <40>; - hsync-len = <0>; - vback-porch = <32>; - vfront-porch = <11>; - vsync-len = <1>; - clock = <0>; /* unused but required */ - bpp = <16>; /* non-standard but required */ - }; + display-timings { + native-mode = <&timing0>; + timing0: 800x480 { + clock-frequency = <0>; /* unused but required */ + hactive = <800>; + vactive = <480>; + hfront-porch = <40>; + hback-porch = <88>; + hsync-len = <0>; + vback-porch = <32>; + vfront-porch = <11>; + vsync-len = <1>; }; }; }; + diff --git a/arch/arm/boot/dts/wm8650.dtsi b/arch/arm/boot/dts/wm8650.dtsi index db3c0a12e05..9313407bbc3 100644 --- a/arch/arm/boot/dts/wm8650.dtsi +++ b/arch/arm/boot/dts/wm8650.dtsi @@ -128,11 +128,9 @@ interrupts = <43>; }; - fb@d8050800 { + fb: fb@d8050800 { compatible = "wm,wm8505-fb"; reg = <0xd8050800 0x200>; - display = <&display>; - default-mode = <&mode0>; }; ge_rops@d8050400 { diff --git a/arch/arm/boot/dts/wm8850-w70v2.dts b/arch/arm/boot/dts/wm8850-w70v2.dts index fcc660c8954..32d22532cd6 100644 --- a/arch/arm/boot/dts/wm8850-w70v2.dts +++ b/arch/arm/boot/dts/wm8850-w70v2.dts @@ -15,28 +15,6 @@ / { model = "Wondermedia WM8850-W70v2 Tablet"; - /* - * Display node is based on Sascha Hauer's patch on dri-devel. - * Added a bpp property to calculate the size of the framebuffer - * until the binding is formalized. - */ - display: display@0 { - modes { - mode0: mode@0 { - hactive = <800>; - vactive = <480>; - hback-porch = <88>; - hfront-porch = <40>; - hsync-len = <0>; - vback-porch = <32>; - vfront-porch = <11>; - vsync-len = <1>; - clock = <0>; /* unused but required */ - bpp = <16>; /* non-standard but required */ - }; - }; - }; - backlight { compatible = "pwm-backlight"; pwms = <&pwm 0 50000 1>; /* duty inverted */ @@ -45,3 +23,21 @@ default-brightness-level = <5>; }; }; + +&fb { + bits-per-pixel = <16>; + display-timings { + native-mode = <&timing0>; + timing0: 800x480 { + clock-frequency = <0>; /* unused but required */ + hactive = <800>; + vactive = <480>; + hfront-porch = <40>; + hback-porch = <88>; + hsync-len = <0>; + vback-porch = <32>; + vfront-porch = <11>; + vsync-len = <1>; + }; + }; +}; diff --git a/arch/arm/boot/dts/wm8850.dtsi b/arch/arm/boot/dts/wm8850.dtsi index e8cbfdc87bb..7149cd13e3b 100644 --- a/arch/arm/boot/dts/wm8850.dtsi +++ b/arch/arm/boot/dts/wm8850.dtsi @@ -135,11 +135,9 @@ }; }; - fb@d8051700 { + fb: fb@d8051700 { compatible = "wm,wm8505-fb"; reg = <0xd8051700 0x200>; - display = <&display>; - default-mode = <&mode0>; }; ge_rops@d8050400 { diff --git a/arch/arm/plat-samsung/include/plat/fb.h b/arch/arm/plat-samsung/include/plat/fb.h index b885322717a..9ae50727078 100644 --- a/arch/arm/plat-samsung/include/plat/fb.h +++ b/arch/arm/plat-samsung/include/plat/fb.h @@ -15,55 +15,7 @@ #ifndef __PLAT_S3C_FB_H #define __PLAT_S3C_FB_H __FILE__ -/* S3C_FB_MAX_WIN - * Set to the maximum number of windows that any of the supported hardware - * can use. Since the platform data uses this for an array size, having it - * set to the maximum of any version of the hardware can do is safe. - */ -#define S3C_FB_MAX_WIN (5) - -/** - * struct s3c_fb_pd_win - per window setup data - * @xres : The window X size. - * @yres : The window Y size. - * @virtual_x: The virtual X size. - * @virtual_y: The virtual Y size. - */ -struct s3c_fb_pd_win { - unsigned short default_bpp; - unsigned short max_bpp; - unsigned short xres; - unsigned short yres; - unsigned short virtual_x; - unsigned short virtual_y; -}; - -/** - * struct s3c_fb_platdata - S3C driver platform specific information - * @setup_gpio: Setup the external GPIO pins to the right state to transfer - * the data from the display system to the connected display - * device. - * @vidcon0: The base vidcon0 values to control the panel data format. - * @vidcon1: The base vidcon1 values to control the panel data output. - * @vtiming: Video timing when connected to a RGB type panel. - * @win: The setup data for each hardware window, or NULL for unused. - * @display_mode: The LCD output display mode. - * - * The platform data supplies the video driver with all the information - * it requires to work with the display(s) attached to the machine. It - * controls the initial mode, the number of display windows (0 is always - * the base framebuffer) that are initialised etc. - * - */ -struct s3c_fb_platdata { - void (*setup_gpio)(void); - - struct s3c_fb_pd_win *win[S3C_FB_MAX_WIN]; - struct fb_videomode *vtiming; - - u32 vidcon0; - u32 vidcon1; -}; +#include <linux/platform_data/video_s3c.h> /** * s3c_fb_set_platdata() - Setup the FB device with platform data. diff --git a/drivers/gpu/drm/drm_modes.c b/drivers/gpu/drm/drm_modes.c index 04fa6f1808d..f83f0719922 100644 --- a/drivers/gpu/drm/drm_modes.c +++ b/drivers/gpu/drm/drm_modes.c @@ -506,7 +506,7 @@ drm_gtf_mode(struct drm_device *dev, int hdisplay, int vdisplay, int vrefresh, } EXPORT_SYMBOL(drm_gtf_mode); -#if IS_ENABLED(CONFIG_VIDEOMODE) +#ifdef CONFIG_VIDEOMODE_HELPERS int drm_display_mode_from_videomode(const struct videomode *vm, struct drm_display_mode *dmode) { @@ -523,26 +523,25 @@ int drm_display_mode_from_videomode(const struct videomode *vm, dmode->clock = vm->pixelclock / 1000; dmode->flags = 0; - if (vm->dmt_flags & VESA_DMT_HSYNC_HIGH) + if (vm->flags & DISPLAY_FLAGS_HSYNC_HIGH) dmode->flags |= DRM_MODE_FLAG_PHSYNC; - else if (vm->dmt_flags & VESA_DMT_HSYNC_LOW) + else if (vm->flags & DISPLAY_FLAGS_HSYNC_LOW) dmode->flags |= DRM_MODE_FLAG_NHSYNC; - if (vm->dmt_flags & VESA_DMT_VSYNC_HIGH) + if (vm->flags & DISPLAY_FLAGS_VSYNC_HIGH) dmode->flags |= DRM_MODE_FLAG_PVSYNC; - else if (vm->dmt_flags & VESA_DMT_VSYNC_LOW) + else if (vm->flags & DISPLAY_FLAGS_VSYNC_LOW) dmode->flags |= DRM_MODE_FLAG_NVSYNC; - if (vm->data_flags & DISPLAY_FLAGS_INTERLACED) + if (vm->flags & DISPLAY_FLAGS_INTERLACED) dmode->flags |= DRM_MODE_FLAG_INTERLACE; - if (vm->data_flags & DISPLAY_FLAGS_DOUBLESCAN) + if (vm->flags & DISPLAY_FLAGS_DOUBLESCAN) dmode->flags |= DRM_MODE_FLAG_DBLSCAN; drm_mode_set_name(dmode); return 0; } EXPORT_SYMBOL_GPL(drm_display_mode_from_videomode); -#endif -#if IS_ENABLED(CONFIG_OF_VIDEOMODE) +#ifdef CONFIG_OF /** * of_get_drm_display_mode - get a drm_display_mode from devicetree * @np: device_node with the timing specification @@ -572,7 +571,8 @@ int of_get_drm_display_mode(struct device_node *np, return 0; } EXPORT_SYMBOL_GPL(of_get_drm_display_mode); -#endif +#endif /* CONFIG_OF */ +#endif /* CONFIG_VIDEOMODE_HELPERS */ /** * drm_mode_set_name - set the name on a mode diff --git a/drivers/gpu/drm/tilcdc/Kconfig b/drivers/gpu/drm/tilcdc/Kconfig index d24d0401347..e461e997245 100644 --- a/drivers/gpu/drm/tilcdc/Kconfig +++ b/drivers/gpu/drm/tilcdc/Kconfig @@ -4,8 +4,7 @@ config DRM_TILCDC select DRM_KMS_HELPER select DRM_KMS_CMA_HELPER select DRM_GEM_CMA_HELPER - select OF_VIDEOMODE - select OF_DISPLAY_TIMING + select VIDEOMODE_HELPERS select BACKLIGHT_CLASS_DEVICE help Choose this option if you have an TI SoC with LCDC display diff --git a/drivers/gpu/drm/tilcdc/tilcdc_panel.c b/drivers/gpu/drm/tilcdc/tilcdc_panel.c index 580b74e2022..90ee4978637 100644 --- a/drivers/gpu/drm/tilcdc/tilcdc_panel.c +++ b/drivers/gpu/drm/tilcdc/tilcdc_panel.c @@ -173,7 +173,7 @@ static int panel_connector_get_modes(struct drm_connector *connector) struct drm_display_mode *mode = drm_mode_create(dev); struct videomode vm; - if (videomode_from_timing(timings, &vm, i)) + if (videomode_from_timings(timings, &vm, i)) break; drm_display_mode_from_videomode(&vm, mode); diff --git a/drivers/video/Kconfig b/drivers/video/Kconfig index 4c1546f71d5..714d32a279e 100644 --- a/drivers/video/Kconfig +++ b/drivers/video/Kconfig @@ -31,26 +31,8 @@ config VIDEO_OUTPUT_CONTROL This framework adds support for low-level control of the video output switch. -config DISPLAY_TIMING - bool - -config VIDEOMODE - bool - -config OF_DISPLAY_TIMING - bool "Enable device tree display timing support" - depends on OF - select DISPLAY_TIMING - help - helper to parse display timings from the devicetree - -config OF_VIDEOMODE - bool "Enable device tree videomode support" - depends on OF - select VIDEOMODE - select OF_DISPLAY_TIMING - help - helper to get videomodes from the devicetree +config VIDEOMODE_HELPERS + bool config HDMI bool @@ -212,14 +194,6 @@ config FB_SYS_FOPS depends on FB default n -config FB_WMT_GE_ROPS - tristate - depends on FB - default n - ---help--- - Include functions for accelerated rectangle filling and area - copying using WonderMedia Graphics Engine operations. - config FB_DEFERRED_IO bool depends on FB @@ -1797,22 +1771,39 @@ config FB_AU1200 option au1200fb:panel=<name>. config FB_VT8500 - bool "VT8500 LCD Driver" + bool "VIA VT8500 framebuffer support" depends on (FB = y) && ARM && ARCH_VT8500 - select FB_WMT_GE_ROPS + select FB_SYS_FILLRECT if (!FB_WMT_GE_ROPS) + select FB_SYS_COPYAREA if (!FB_WMT_GE_ROPS) select FB_SYS_IMAGEBLIT + select FB_MODE_HELPERS + select OF_DISPLAY_TIMING + select OF_VIDEOMODE help This is the framebuffer driver for VIA VT8500 integrated LCD controller. config FB_WM8505 - bool "WM8505 frame buffer support" + bool "Wondermedia WM8xxx-series frame buffer support" depends on (FB = y) && ARM && ARCH_VT8500 - select FB_WMT_GE_ROPS + select FB_SYS_FILLRECT if (!FB_WMT_GE_ROPS) + select FB_SYS_COPYAREA if (!FB_WMT_GE_ROPS) select FB_SYS_IMAGEBLIT + select FB_MODE_HELPERS + select OF_DISPLAY_TIMING + select OF_VIDEOMODE + help + This is the framebuffer driver for WonderMedia WM8xxx-series + integrated LCD controller. This driver covers the WM8505, WM8650 + and WM8850 SoCs. + +config FB_WMT_GE_ROPS + bool "VT8500/WM8xxx accelerated raster ops support" + depends on (FB = y) && (FB_VT8500 || FB_WM8505) + default n help - This is the framebuffer driver for WonderMedia WM8505/WM8650 - integrated LCD controller. + This adds support for accelerated raster operations on the + VIA VT8500 and Wondermedia 85xx series SoCs. source "drivers/video/geode/Kconfig" diff --git a/drivers/video/Makefile b/drivers/video/Makefile index 9df387334cb..e414378d6a5 100644 --- a/drivers/video/Makefile +++ b/drivers/video/Makefile @@ -171,7 +171,7 @@ obj-$(CONFIG_FB_VIRTUAL) += vfb.o #video output switch sysfs driver obj-$(CONFIG_VIDEO_OUTPUT_CONTROL) += output.o -obj-$(CONFIG_DISPLAY_TIMING) += display_timing.o -obj-$(CONFIG_OF_DISPLAY_TIMING) += of_display_timing.o -obj-$(CONFIG_VIDEOMODE) += videomode.o -obj-$(CONFIG_OF_VIDEOMODE) += of_videomode.o +obj-$(CONFIG_VIDEOMODE_HELPERS) += display_timing.o videomode.o +ifeq ($(CONFIG_OF),y) +obj-$(CONFIG_VIDEOMODE_HELPERS) += of_display_timing.o of_videomode.o +endif diff --git a/drivers/video/amifb.c b/drivers/video/amifb.c index 7fa1bf82372..77cb4ffa1fe 100644 --- a/drivers/video/amifb.c +++ b/drivers/video/amifb.c @@ -3788,19 +3788,7 @@ static struct platform_driver amifb_driver = { }, }; -static int __init amifb_init(void) -{ - return platform_driver_probe(&amifb_driver, amifb_probe); -} - -module_init(amifb_init); - -static void __exit amifb_exit(void) -{ - platform_driver_unregister(&amifb_driver); -} - -module_exit(amifb_exit); +module_platform_driver_probe(amifb_driver, amifb_probe); MODULE_LICENSE("GPL"); MODULE_ALIAS("platform:amiga-video"); diff --git a/drivers/video/atmel_lcdfb.c b/drivers/video/atmel_lcdfb.c index 025428e04c3..98348ec0b3c 100644 --- a/drivers/video/atmel_lcdfb.c +++ b/drivers/video/atmel_lcdfb.c @@ -1158,18 +1158,7 @@ static struct platform_driver atmel_lcdfb_driver = { }, }; -static int __init atmel_lcdfb_init(void) -{ - return platform_driver_probe(&atmel_lcdfb_driver, atmel_lcdfb_probe); -} - -static void __exit atmel_lcdfb_exit(void) -{ - platform_driver_unregister(&atmel_lcdfb_driver); -} - -module_init(atmel_lcdfb_init); -module_exit(atmel_lcdfb_exit); +module_platform_driver_probe(atmel_lcdfb_driver, atmel_lcdfb_probe); MODULE_DESCRIPTION("AT91/AT32 LCD Controller framebuffer driver"); MODULE_AUTHOR("Nicolas Ferre <nicolas.ferre@atmel.com>"); diff --git a/drivers/video/exynos/exynos_mipi_dsi.c b/drivers/video/exynos/exynos_mipi_dsi.c index fac7df6d1ab..3dd43ca2b95 100644 --- a/drivers/video/exynos/exynos_mipi_dsi.c +++ b/drivers/video/exynos/exynos_mipi_dsi.c @@ -35,8 +35,6 @@ #include <video/exynos_mipi_dsim.h> -#include <plat/fb.h> - #include "exynos_mipi_dsi_common.h" #include "exynos_mipi_dsi_lowlevel.h" diff --git a/drivers/video/exynos/exynos_mipi_dsi_common.c b/drivers/video/exynos/exynos_mipi_dsi_common.c index c70cb8926df..520fc9bd887 100644 --- a/drivers/video/exynos/exynos_mipi_dsi_common.c +++ b/drivers/video/exynos/exynos_mipi_dsi_common.c @@ -31,8 +31,6 @@ #include <video/mipi_display.h> #include <video/exynos_mipi_dsim.h> -#include <mach/map.h> - #include "exynos_mipi_dsi_regs.h" #include "exynos_mipi_dsi_lowlevel.h" #include "exynos_mipi_dsi_common.h" diff --git a/drivers/video/exynos/exynos_mipi_dsi_lowlevel.c b/drivers/video/exynos/exynos_mipi_dsi_lowlevel.c index 95cb99a1fe2..15c5abd408d 100644 --- a/drivers/video/exynos/exynos_mipi_dsi_lowlevel.c +++ b/drivers/video/exynos/exynos_mipi_dsi_lowlevel.c @@ -26,8 +26,6 @@ #include <video/exynos_mipi_dsim.h> -#include <mach/map.h> - #include "exynos_mipi_dsi_regs.h" void exynos_mipi_dsi_func_reset(struct mipi_dsim_device *dsim) diff --git a/drivers/video/fbmon.c b/drivers/video/fbmon.c index 94ad0f71383..e5cc2fdb4c8 100644 --- a/drivers/video/fbmon.c +++ b/drivers/video/fbmon.c @@ -1376,7 +1376,7 @@ int fb_get_mode(int flags, u32 val, struct fb_var_screeninfo *var, struct fb_inf return err; } -#if IS_ENABLED(CONFIG_VIDEOMODE) +#ifdef CONFIG_VIDEOMODE_HELPERS int fb_videomode_from_videomode(const struct videomode *vm, struct fb_videomode *fbmode) { @@ -1398,13 +1398,13 @@ int fb_videomode_from_videomode(const struct videomode *vm, fbmode->sync = 0; fbmode->vmode = 0; - if (vm->dmt_flags & VESA_DMT_HSYNC_HIGH) + if (vm->flags & DISPLAY_FLAGS_HSYNC_HIGH) fbmode->sync |= FB_SYNC_HOR_HIGH_ACT; - if (vm->dmt_flags & VESA_DMT_HSYNC_HIGH) + if (vm->flags & DISPLAY_FLAGS_HSYNC_HIGH) fbmode->sync |= FB_SYNC_VERT_HIGH_ACT; - if (vm->data_flags & DISPLAY_FLAGS_INTERLACED) + if (vm->flags & DISPLAY_FLAGS_INTERLACED) fbmode->vmode |= FB_VMODE_INTERLACED; - if (vm->data_flags & DISPLAY_FLAGS_DOUBLESCAN) + if (vm->flags & DISPLAY_FLAGS_DOUBLESCAN) fbmode->vmode |= FB_VMODE_DOUBLE; fbmode->flag = 0; @@ -1424,9 +1424,8 @@ int fb_videomode_from_videomode(const struct videomode *vm, return 0; } EXPORT_SYMBOL_GPL(fb_videomode_from_videomode); -#endif -#if IS_ENABLED(CONFIG_OF_VIDEOMODE) +#ifdef CONFIG_OF static inline void dump_fb_videomode(const struct fb_videomode *m) { pr_debug("fb_videomode = %ux%u@%uHz (%ukHz) %u %u %u %u %u %u %u %u %u\n", @@ -1465,7 +1464,8 @@ int of_get_fb_videomode(struct device_node *np, struct fb_videomode *fb, return 0; } EXPORT_SYMBOL_GPL(of_get_fb_videomode); -#endif +#endif /* CONFIG_OF */ +#endif /* CONFIG_VIDEOMODE_HELPERS */ #else int fb_parse_edid(unsigned char *edid, struct fb_var_screeninfo *var) diff --git a/drivers/video/fsl-diu-fb.c b/drivers/video/fsl-diu-fb.c index 41fbd9453c5..6c278056fc6 100644 --- a/drivers/video/fsl-diu-fb.c +++ b/drivers/video/fsl-diu-fb.c @@ -375,7 +375,10 @@ struct fsl_diu_data { struct diu_ad dummy_ad __aligned(8); struct diu_ad ad[NUM_AOIS] __aligned(8); u8 gamma[256 * 3] __aligned(32); - u8 cursor[MAX_CURS * MAX_CURS * 2] __aligned(32); + /* It's easier to parse the cursor data as little-endian */ + __le16 cursor[MAX_CURS * MAX_CURS] __aligned(32); + /* Blank cursor data -- used to hide the cursor */ + __le16 blank_cursor[MAX_CURS * MAX_CURS] __aligned(32); uint8_t edid_data[EDID_LENGTH]; bool has_edid; } __aligned(32); @@ -824,7 +827,6 @@ static void update_lcdc(struct fb_info *info) /* Program DIU registers */ out_be32(&hw->gamma, DMA_ADDR(data, gamma)); - out_be32(&hw->cursor, DMA_ADDR(data, cursor)); out_be32(&hw->bgnd, 0x007F7F7F); /* Set background to grey */ out_be32(&hw->disp_size, (var->yres << 16) | var->xres); @@ -968,6 +970,156 @@ static u32 fsl_diu_get_pixel_format(unsigned int bits_per_pixel) } /* + * Copies a cursor image from user space to the proper place in driver + * memory so that the hardware can display the cursor image. + * + * Cursor data is represented as a sequence of 'width' bits packed into bytes. + * That is, the first 8 bits are in the first byte, the second 8 bits in the + * second byte, and so on. Therefore, the each row of the cursor is (width + + * 7) / 8 bytes of 'data' + * + * The DIU only supports cursors up to 32x32 (MAX_CURS). We reject cursors + * larger than this, so we already know that 'width' <= 32. Therefore, we can + * simplify our code by using a 32-bit big-endian integer ("line") to read in + * a single line of pixels, and only look at the top 'width' bits of that + * integer. + * + * This could result in an unaligned 32-bit read. For example, if the cursor + * is 24x24, then the first three bytes of 'image' contain the pixel data for + * the top line of the cursor. We do a 32-bit read of 'image', but we look + * only at the top 24 bits. Then we increment 'image' by 3 bytes. The next + * read is unaligned. The only problem is that we might read past the end of + * 'image' by 1-3 bytes, but that should not cause any problems. + */ +static void fsl_diu_load_cursor_image(struct fb_info *info, + const void *image, uint16_t bg, uint16_t fg, + unsigned int width, unsigned int height) +{ + struct mfb_info *mfbi = info->par; + struct fsl_diu_data *data = mfbi->parent; + __le16 *cursor = data->cursor; + __le16 _fg = cpu_to_le16(fg); + __le16 _bg = cpu_to_le16(bg); + unsigned int h, w; + + for (h = 0; h < height; h++) { + uint32_t mask = 1 << 31; + uint32_t line = be32_to_cpup(image); + + for (w = 0; w < width; w++) { + cursor[w] = (line & mask) ? _fg : _bg; + mask >>= 1; + } + + cursor += MAX_CURS; + image += DIV_ROUND_UP(width, 8); + } +} + +/* + * Set a hardware cursor. The image data for the cursor is passed via the + * fb_cursor object. + */ +static int fsl_diu_cursor(struct fb_info *info, struct fb_cursor *cursor) +{ + struct mfb_info *mfbi = info->par; + struct fsl_diu_data *data = mfbi->parent; + struct diu __iomem *hw = data->diu_reg; + + if (cursor->image.width > MAX_CURS || cursor->image.height > MAX_CURS) + return -EINVAL; + + /* The cursor size has changed */ + if (cursor->set & FB_CUR_SETSIZE) { + /* + * The DIU cursor is a fixed size, so when we get this + * message, instead of resizing the cursor, we just clear + * all the image data, in expectation of new data. However, + * in tests this control does not appear to be normally + * called. + */ + memset(data->cursor, 0, sizeof(data->cursor)); + } + + /* The cursor position has changed (cursor->image.dx|dy) */ + if (cursor->set & FB_CUR_SETPOS) { + uint32_t xx, yy; + + yy = (cursor->image.dy - info->var.yoffset) & 0x7ff; + xx = (cursor->image.dx - info->var.xoffset) & 0x7ff; + + out_be32(&hw->curs_pos, yy << 16 | xx); + } + + /* + * FB_CUR_SETIMAGE - the cursor image has changed + * FB_CUR_SETCMAP - the cursor colors has changed + * FB_CUR_SETSHAPE - the cursor bitmask has changed + */ + if (cursor->set & (FB_CUR_SETSHAPE | FB_CUR_SETCMAP | FB_CUR_SETIMAGE)) { + unsigned int image_size = + DIV_ROUND_UP(cursor->image.width, 8) * cursor->image.height; + unsigned int image_words = + DIV_ROUND_UP(image_size, sizeof(uint32_t)); + unsigned int bg_idx = cursor->image.bg_color; + unsigned int fg_idx = cursor->image.fg_color; + uint8_t buffer[image_size]; + uint32_t *image, *source, *mask; + uint16_t fg, bg; + unsigned int i; + + if (info->state != FBINFO_STATE_RUNNING) + return 0; + + /* + * Determine the size of the cursor image data. Normally, + * it's 8x16. + */ + image_size = DIV_ROUND_UP(cursor->image.width, 8) * + cursor->image.height; + + bg = ((info->cmap.red[bg_idx] & 0xf8) << 7) | + ((info->cmap.green[bg_idx] & 0xf8) << 2) | + ((info->cmap.blue[bg_idx] & 0xf8) >> 3) | + 1 << 15; + + fg = ((info->cmap.red[fg_idx] & 0xf8) << 7) | + ((info->cmap.green[fg_idx] & 0xf8) << 2) | + ((info->cmap.blue[fg_idx] & 0xf8) >> 3) | + 1 << 15; + + /* Use 32-bit operations on the data to improve performance */ + image = (uint32_t *)buffer; + source = (uint32_t *)cursor->image.data; + mask = (uint32_t *)cursor->mask; + + if (cursor->rop == ROP_XOR) + for (i = 0; i < image_words; i++) + image[i] = source[i] ^ mask[i]; + else + for (i = 0; i < image_words; i++) + image[i] = source[i] & mask[i]; + + fsl_diu_load_cursor_image(info, image, bg, fg, + cursor->image.width, cursor->image.height); + }; + + /* + * Show or hide the cursor. The cursor data is always stored in the + * 'cursor' memory block, and the actual cursor position is always in + * the DIU's CURS_POS register. To hide the cursor, we redirect the + * CURSOR register to a blank cursor. The show the cursor, we + * redirect the CURSOR register to the real cursor data. + */ + if (cursor->enable) + out_be32(&hw->cursor, DMA_ADDR(data, cursor)); + else + out_be32(&hw->cursor, DMA_ADDR(data, blank_cursor)); + + return 0; +} + +/* * Using the fb_var_screeninfo in fb_info we set the resolution of this * particular framebuffer. This function alters the fb_fix_screeninfo stored * in fb_info. It does not alter var in fb_info since we are using that @@ -1312,6 +1464,7 @@ static struct fb_ops fsl_diu_ops = { .fb_ioctl = fsl_diu_ioctl, .fb_open = fsl_diu_open, .fb_release = fsl_diu_release, + .fb_cursor = fsl_diu_cursor, }; static int install_fb(struct fb_info *info) diff --git a/drivers/video/of_display_timing.c b/drivers/video/of_display_timing.c index 13ecd989701..56009bc02b0 100644 --- a/drivers/video/of_display_timing.c +++ b/drivers/video/of_display_timing.c @@ -79,25 +79,24 @@ static struct display_timing *of_get_display_timing(struct device_node *np) ret |= parse_timing_property(np, "vsync-len", &dt->vsync_len); ret |= parse_timing_property(np, "clock-frequency", &dt->pixelclock); - dt->dmt_flags = 0; - dt->data_flags = 0; + dt->flags = 0; if (!of_property_read_u32(np, "vsync-active", &val)) - dt->dmt_flags |= val ? VESA_DMT_VSYNC_HIGH : - VESA_DMT_VSYNC_LOW; + dt->flags |= val ? DISPLAY_FLAGS_VSYNC_HIGH : + DISPLAY_FLAGS_VSYNC_LOW; if (!of_property_read_u32(np, "hsync-active", &val)) - dt->dmt_flags |= val ? VESA_DMT_HSYNC_HIGH : - VESA_DMT_HSYNC_LOW; + dt->flags |= val ? DISPLAY_FLAGS_HSYNC_HIGH : + DISPLAY_FLAGS_HSYNC_LOW; if (!of_property_read_u32(np, "de-active", &val)) - dt->data_flags |= val ? DISPLAY_FLAGS_DE_HIGH : + dt->flags |= val ? DISPLAY_FLAGS_DE_HIGH : DISPLAY_FLAGS_DE_LOW; if (!of_property_read_u32(np, "pixelclk-active", &val)) - dt->data_flags |= val ? DISPLAY_FLAGS_PIXDATA_POSEDGE : + dt->flags |= val ? DISPLAY_FLAGS_PIXDATA_POSEDGE : DISPLAY_FLAGS_PIXDATA_NEGEDGE; if (of_property_read_bool(np, "interlaced")) - dt->data_flags |= DISPLAY_FLAGS_INTERLACED; + dt->flags |= DISPLAY_FLAGS_INTERLACED; if (of_property_read_bool(np, "doublescan")) - dt->data_flags |= DISPLAY_FLAGS_DOUBLESCAN; + dt->flags |= DISPLAY_FLAGS_DOUBLESCAN; if (ret) { pr_err("%s: error reading timing properties\n", diff --git a/drivers/video/of_videomode.c b/drivers/video/of_videomode.c index 5b8066cd397..111c2d1911d 100644 --- a/drivers/video/of_videomode.c +++ b/drivers/video/of_videomode.c @@ -43,7 +43,7 @@ int of_get_videomode(struct device_node *np, struct videomode *vm, if (index == OF_USE_NATIVE_MODE) index = disp->native_mode; - ret = videomode_from_timing(disp, vm, index); + ret = videomode_from_timings(disp, vm, index); if (ret) return ret; diff --git a/drivers/video/omap/Kconfig b/drivers/video/omap/Kconfig index e512581300f..0bc3a936ce2 100644 --- a/drivers/video/omap/Kconfig +++ b/drivers/video/omap/Kconfig @@ -39,17 +39,6 @@ config FB_OMAP_LCD_MIPID the Mobile Industry Processor Interface DBI-C/DCS specification. (Supported LCDs: Philips LPH8923, Sharp LS041Y3) -config FB_OMAP_CONSISTENT_DMA_SIZE - int "Consistent DMA memory size (MB)" - depends on FB_OMAP - range 1 14 - default 2 - help - Increase the DMA consistent memory size according to your video - memory needs, for example if you want to use multiple planes. - The size must be 2MB aligned. - If unsure say 1. - config FB_OMAP_DMA_TUNE bool "Set DMA SDRAM access priority high" depends on FB_OMAP diff --git a/drivers/video/omap2/vrfb.c b/drivers/video/omap2/vrfb.c index 10560efeb35..5261229c79a 100644 --- a/drivers/video/omap2/vrfb.c +++ b/drivers/video/omap2/vrfb.c @@ -397,18 +397,7 @@ static struct platform_driver vrfb_driver = { .remove = __exit_p(vrfb_remove), }; -static int __init vrfb_init(void) -{ - return platform_driver_probe(&vrfb_driver, &vrfb_probe); -} - -static void __exit vrfb_exit(void) -{ - platform_driver_unregister(&vrfb_driver); -} - -module_init(vrfb_init); -module_exit(vrfb_exit); +module_platform_driver_probe(vrfb_driver, vrfb_probe); MODULE_AUTHOR("Tomi Valkeinen <tomi.valkeinen@ti.com>"); MODULE_DESCRIPTION("OMAP VRFB"); diff --git a/drivers/video/s3c-fb.c b/drivers/video/s3c-fb.c index 968a62571df..2e7991c7ca0 100644 --- a/drivers/video/s3c-fb.c +++ b/drivers/video/s3c-fb.c @@ -24,10 +24,9 @@ #include <linux/uaccess.h> #include <linux/interrupt.h> #include <linux/pm_runtime.h> +#include <linux/platform_data/video_s3c.h> #include <video/samsung_fimd.h> -#include <mach/map.h> -#include <plat/fb.h> /* This driver will export a number of framebuffer interfaces depending * on the configuration passed in via the platform data. Each fb instance diff --git a/drivers/video/sh_mipi_dsi.c b/drivers/video/sh_mipi_dsi.c index 701b461cf8a..6cad53075e9 100644 --- a/drivers/video/sh_mipi_dsi.c +++ b/drivers/video/sh_mipi_dsi.c @@ -581,17 +581,7 @@ static struct platform_driver sh_mipi_driver = { }, }; -static int __init sh_mipi_init(void) -{ - return platform_driver_probe(&sh_mipi_driver, sh_mipi_probe); -} -module_init(sh_mipi_init); - -static void __exit sh_mipi_exit(void) -{ - platform_driver_unregister(&sh_mipi_driver); -} -module_exit(sh_mipi_exit); +module_platform_driver_probe(sh_mipi_driver, sh_mipi_probe); MODULE_AUTHOR("Guennadi Liakhovetski <g.liakhovetski@gmx.de>"); MODULE_DESCRIPTION("SuperH / ARM-shmobile MIPI DSI driver"); diff --git a/drivers/video/sh_mobile_hdmi.c b/drivers/video/sh_mobile_hdmi.c index 930e550e752..bfe4728480f 100644 --- a/drivers/video/sh_mobile_hdmi.c +++ b/drivers/video/sh_mobile_hdmi.c @@ -1445,17 +1445,7 @@ static struct platform_driver sh_hdmi_driver = { }, }; -static int __init sh_hdmi_init(void) -{ - return platform_driver_probe(&sh_hdmi_driver, sh_hdmi_probe); -} -module_init(sh_hdmi_init); - -static void __exit sh_hdmi_exit(void) -{ - platform_driver_unregister(&sh_hdmi_driver); -} -module_exit(sh_hdmi_exit); +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"); diff --git a/drivers/video/videomode.c b/drivers/video/videomode.c index 21c47a202af..df375c96c5d 100644 --- a/drivers/video/videomode.c +++ b/drivers/video/videomode.c @@ -11,7 +11,25 @@ #include <video/display_timing.h> #include <video/videomode.h> -int videomode_from_timing(const struct display_timings *disp, +void videomode_from_timing(const struct display_timing *dt, + struct videomode *vm) +{ + vm->pixelclock = dt->pixelclock.typ; + vm->hactive = dt->hactive.typ; + vm->hfront_porch = dt->hfront_porch.typ; + vm->hback_porch = dt->hback_porch.typ; + vm->hsync_len = dt->hsync_len.typ; + + vm->vactive = dt->vactive.typ; + vm->vfront_porch = dt->vfront_porch.typ; + vm->vback_porch = dt->vback_porch.typ; + vm->vsync_len = dt->vsync_len.typ; + + vm->flags = dt->flags; +} +EXPORT_SYMBOL_GPL(videomode_from_timing); + +int videomode_from_timings(const struct display_timings *disp, struct videomode *vm, unsigned int index) { struct display_timing *dt; @@ -20,20 +38,8 @@ int videomode_from_timing(const struct display_timings *disp, if (!dt) return -EINVAL; - vm->pixelclock = display_timing_get_value(&dt->pixelclock, TE_TYP); - vm->hactive = display_timing_get_value(&dt->hactive, TE_TYP); - vm->hfront_porch = display_timing_get_value(&dt->hfront_porch, TE_TYP); - vm->hback_porch = display_timing_get_value(&dt->hback_porch, TE_TYP); - vm->hsync_len = display_timing_get_value(&dt->hsync_len, TE_TYP); - - vm->vactive = display_timing_get_value(&dt->vactive, TE_TYP); - vm->vfront_porch = display_timing_get_value(&dt->vfront_porch, TE_TYP); - vm->vback_porch = display_timing_get_value(&dt->vback_porch, TE_TYP); - vm->vsync_len = display_timing_get_value(&dt->vsync_len, TE_TYP); - - vm->dmt_flags = dt->dmt_flags; - vm->data_flags = dt->data_flags; + videomode_from_timing(dt, vm); return 0; } -EXPORT_SYMBOL_GPL(videomode_from_timing); +EXPORT_SYMBOL_GPL(videomode_from_timings); diff --git a/drivers/video/vt8500lcdfb.c b/drivers/video/vt8500lcdfb.c index aa2579c2364..9547e1831e0 100644 --- a/drivers/video/vt8500lcdfb.c +++ b/drivers/video/vt8500lcdfb.c @@ -15,22 +15,21 @@ * GNU General Public License for more details. */ -#include <linux/module.h> -#include <linux/kernel.h> -#include <linux/errno.h> -#include <linux/string.h> -#include <linux/mm.h> -#include <linux/slab.h> #include <linux/delay.h> +#include <linux/dma-mapping.h> +#include <linux/errno.h> #include <linux/fb.h> #include <linux/init.h> #include <linux/interrupt.h> #include <linux/io.h> -#include <linux/dma-mapping.h> +#include <linux/kernel.h> +#include <linux/mm.h> +#include <linux/module.h> #include <linux/platform_device.h> +#include <linux/slab.h> +#include <linux/string.h> #include <linux/wait.h> - -#include <linux/platform_data/video-vt8500lcdfb.h> +#include <video/of_display_timing.h> #include "vt8500lcdfb.h" #include "wmt_ge_rops.h" @@ -277,11 +276,11 @@ static int vt8500lcd_probe(struct platform_device *pdev) { struct vt8500lcd_info *fbi; struct resource *res; + struct display_timings *disp_timing; void *addr; int irq, ret; struct fb_videomode of_mode; - struct device_node *np; u32 bpp; dma_addr_t fb_mem_phys; unsigned long fb_mem_len; @@ -346,32 +345,18 @@ static int vt8500lcd_probe(struct platform_device *pdev) goto failed_free_res; } - np = of_parse_phandle(pdev->dev.of_node, "default-mode", 0); - if (!np) { - pr_err("%s: No display description in Device Tree\n", __func__); - ret = -EINVAL; - goto failed_free_res; - } + disp_timing = of_get_display_timings(pdev->dev.of_node); + if (!disp_timing) + return -EINVAL; - /* - * This code is copied from Sascha Hauer's of_videomode helper - * and can be replaced with a call to the helper once mainlined - */ - ret = 0; - ret |= of_property_read_u32(np, "hactive", &of_mode.xres); - ret |= of_property_read_u32(np, "vactive", &of_mode.yres); - ret |= of_property_read_u32(np, "hback-porch", &of_mode.left_margin); - ret |= of_property_read_u32(np, "hfront-porch", &of_mode.right_margin); - ret |= of_property_read_u32(np, "hsync-len", &of_mode.hsync_len); - ret |= of_property_read_u32(np, "vback-porch", &of_mode.upper_margin); - ret |= of_property_read_u32(np, "vfront-porch", &of_mode.lower_margin); - ret |= of_property_read_u32(np, "vsync-len", &of_mode.vsync_len); - ret |= of_property_read_u32(np, "bpp", &bpp); - if (ret) { - pr_err("%s: Unable to read display properties\n", __func__); - goto failed_free_res; - } - of_mode.vmode = FB_VMODE_NONINTERLACED; + ret = of_get_fb_videomode(pdev->dev.of_node, &of_mode, + OF_USE_NATIVE_MODE); + if (ret) + return ret; + + ret = of_property_read_u32(pdev->dev.of_node, "bits-per-pixel", &bpp); + if (ret) + return ret; /* try allocating the framebuffer */ fb_mem_len = of_mode.xres * of_mode.yres * 2 * (bpp / 8); diff --git a/drivers/video/wm8505fb.c b/drivers/video/wm8505fb.c index 4dd0580f96f..01f9ace068e 100644 --- a/drivers/video/wm8505fb.c +++ b/drivers/video/wm8505fb.c @@ -14,25 +14,25 @@ * GNU General Public License for more details. */ -#include <linux/module.h> -#include <linux/kernel.h> -#include <linux/errno.h> -#include <linux/string.h> -#include <linux/mm.h> -#include <linux/slab.h> #include <linux/delay.h> +#include <linux/dma-mapping.h> #include <linux/fb.h> +#include <linux/errno.h> +#include <linux/err.h> #include <linux/init.h> #include <linux/interrupt.h> #include <linux/io.h> -#include <linux/dma-mapping.h> -#include <linux/platform_device.h> -#include <linux/wait.h> +#include <linux/kernel.h> +#include <linux/memblock.h> +#include <linux/mm.h> +#include <linux/module.h> #include <linux/of.h> #include <linux/of_fdt.h> -#include <linux/memblock.h> - -#include <linux/platform_data/video-vt8500lcdfb.h> +#include <linux/platform_device.h> +#include <linux/slab.h> +#include <linux/string.h> +#include <linux/wait.h> +#include <video/of_display_timing.h> #include "wm8505fb_regs.h" #include "wmt_ge_rops.h" @@ -263,26 +263,22 @@ static struct fb_ops wm8505fb_ops = { static int wm8505fb_probe(struct platform_device *pdev) { struct wm8505fb_info *fbi; - struct resource *res; + struct resource *res; + struct display_timings *disp_timing; void *addr; int ret; - struct fb_videomode of_mode; - struct device_node *np; + struct fb_videomode mode; u32 bpp; dma_addr_t fb_mem_phys; unsigned long fb_mem_len; void *fb_mem_virt; - ret = -ENOMEM; - fbi = NULL; - fbi = devm_kzalloc(&pdev->dev, sizeof(struct wm8505fb_info) + sizeof(u32) * 16, GFP_KERNEL); if (!fbi) { dev_err(&pdev->dev, "Failed to initialize framebuffer device\n"); - ret = -ENOMEM; - goto failed; + return -ENOMEM; } strcpy(fbi->fb.fix.id, DRIVER_NAME); @@ -308,54 +304,23 @@ static int wm8505fb_probe(struct platform_device *pdev) fbi->fb.pseudo_palette = addr; res = platform_get_resource(pdev, IORESOURCE_MEM, 0); - if (res == NULL) { - dev_err(&pdev->dev, "no I/O memory resource defined\n"); - ret = -ENODEV; - goto failed_fbi; - } + fbi->regbase = devm_ioremap_resource(&pdev->dev, res); + if (IS_ERR(fbi->regbase)) + return PTR_ERR(fbi->regbase); - res = request_mem_region(res->start, resource_size(res), DRIVER_NAME); - if (res == NULL) { - dev_err(&pdev->dev, "failed to request I/O memory\n"); - ret = -EBUSY; - goto failed_fbi; - } - - fbi->regbase = ioremap(res->start, resource_size(res)); - if (fbi->regbase == NULL) { - dev_err(&pdev->dev, "failed to map I/O memory\n"); - ret = -EBUSY; - goto failed_free_res; - } + disp_timing = of_get_display_timings(pdev->dev.of_node); + if (!disp_timing) + return -EINVAL; - np = of_parse_phandle(pdev->dev.of_node, "default-mode", 0); - if (!np) { - pr_err("%s: No display description in Device Tree\n", __func__); - ret = -EINVAL; - goto failed_free_res; - } + ret = of_get_fb_videomode(pdev->dev.of_node, &mode, OF_USE_NATIVE_MODE); + if (ret) + return ret; - /* - * This code is copied from Sascha Hauer's of_videomode helper - * and can be replaced with a call to the helper once mainlined - */ - ret = 0; - ret |= of_property_read_u32(np, "hactive", &of_mode.xres); - ret |= of_property_read_u32(np, "vactive", &of_mode.yres); - ret |= of_property_read_u32(np, "hback-porch", &of_mode.left_margin); - ret |= of_property_read_u32(np, "hfront-porch", &of_mode.right_margin); - ret |= of_property_read_u32(np, "hsync-len", &of_mode.hsync_len); - ret |= of_property_read_u32(np, "vback-porch", &of_mode.upper_margin); - ret |= of_property_read_u32(np, "vfront-porch", &of_mode.lower_margin); - ret |= of_property_read_u32(np, "vsync-len", &of_mode.vsync_len); - ret |= of_property_read_u32(np, "bpp", &bpp); - if (ret) { - pr_err("%s: Unable to read display properties\n", __func__); - goto failed_free_res; - } + ret = of_property_read_u32(pdev->dev.of_node, "bits-per-pixel", &bpp); + if (ret) + return ret; - of_mode.vmode = FB_VMODE_NONINTERLACED; - fb_videomode_to_var(&fbi->fb.var, &of_mode); + fb_videomode_to_var(&fbi->fb.var, &mode); fbi->fb.var.nonstd = 0; fbi->fb.var.activate = FB_ACTIVATE_NOW; @@ -364,16 +329,16 @@ static int wm8505fb_probe(struct platform_device *pdev) fbi->fb.var.width = -1; /* try allocating the framebuffer */ - fb_mem_len = of_mode.xres * of_mode.yres * 2 * (bpp / 8); - fb_mem_virt = dma_alloc_coherent(&pdev->dev, fb_mem_len, &fb_mem_phys, + fb_mem_len = mode.xres * mode.yres * 2 * (bpp / 8); + fb_mem_virt = dmam_alloc_coherent(&pdev->dev, fb_mem_len, &fb_mem_phys, GFP_KERNEL); if (!fb_mem_virt) { pr_err("%s: Failed to allocate framebuffer\n", __func__); return -ENOMEM; - }; + } - fbi->fb.var.xres_virtual = of_mode.xres; - fbi->fb.var.yres_virtual = of_mode.yres * 2; + fbi->fb.var.xres_virtual = mode.xres; + fbi->fb.var.yres_virtual = mode.yres * 2; fbi->fb.var.bits_per_pixel = bpp; fbi->fb.fix.smem_start = fb_mem_phys; @@ -381,28 +346,29 @@ static int wm8505fb_probe(struct platform_device *pdev) fbi->fb.screen_base = fb_mem_virt; fbi->fb.screen_size = fb_mem_len; + fbi->contrast = 0x10; + ret = wm8505fb_set_par(&fbi->fb); + if (ret) { + dev_err(&pdev->dev, "Failed to set parameters\n"); + return ret; + } + if (fb_alloc_cmap(&fbi->fb.cmap, 256, 0) < 0) { dev_err(&pdev->dev, "Failed to allocate color map\n"); - ret = -ENOMEM; - goto failed_free_io; + return -ENOMEM; } wm8505fb_init_hw(&fbi->fb); - fbi->contrast = 0x80; - ret = wm8505fb_set_par(&fbi->fb); - if (ret) { - dev_err(&pdev->dev, "Failed to set parameters\n"); - goto failed_free_cmap; - } - platform_set_drvdata(pdev, fbi); ret = register_framebuffer(&fbi->fb); if (ret < 0) { dev_err(&pdev->dev, "Failed to register framebuffer device: %d\n", ret); - goto failed_free_cmap; + if (fbi->fb.cmap.len) + fb_dealloc_cmap(&fbi->fb.cmap); + return ret; } ret = device_create_file(&pdev->dev, &dev_attr_contrast); @@ -416,25 +382,11 @@ static int wm8505fb_probe(struct platform_device *pdev) fbi->fb.fix.smem_start + fbi->fb.fix.smem_len - 1); return 0; - -failed_free_cmap: - if (fbi->fb.cmap.len) - fb_dealloc_cmap(&fbi->fb.cmap); -failed_free_io: - iounmap(fbi->regbase); -failed_free_res: - release_mem_region(res->start, resource_size(res)); -failed_fbi: - platform_set_drvdata(pdev, NULL); - kfree(fbi); -failed: - return ret; } static int wm8505fb_remove(struct platform_device *pdev) { struct wm8505fb_info *fbi = platform_get_drvdata(pdev); - struct resource *res; device_remove_file(&pdev->dev, &dev_attr_contrast); @@ -445,13 +397,6 @@ static int wm8505fb_remove(struct platform_device *pdev) if (fbi->fb.cmap.len) fb_dealloc_cmap(&fbi->fb.cmap); - iounmap(fbi->regbase); - - res = platform_get_resource(pdev, IORESOURCE_MEM, 0); - release_mem_region(res->start, resource_size(res)); - - kfree(fbi); - return 0; } diff --git a/drivers/video/wmt_ge_rops.h b/drivers/video/wmt_ge_rops.h index 87380751a44..f73ec6377a4 100644 --- a/drivers/video/wmt_ge_rops.h +++ b/drivers/video/wmt_ge_rops.h @@ -1,5 +1,28 @@ +#ifdef CONFIG_FB_WMT_GE_ROPS + extern void wmt_ge_fillrect(struct fb_info *info, const struct fb_fillrect *rect); extern void wmt_ge_copyarea(struct fb_info *info, const struct fb_copyarea *area); extern int wmt_ge_sync(struct fb_info *info); + +#else + +static inline int wmt_ge_sync(struct fb_info *p) +{ + return 0; +} + +static inline void wmt_ge_fillrect(struct fb_info *p, + const struct fb_fillrect *rect) +{ + sys_fillrect(p, rect); +} + +static inline void wmt_ge_copyarea(struct fb_info *p, + const struct fb_copyarea *area) +{ + sys_copyarea(p, area); +} + +#endif diff --git a/include/linux/platform_data/video-vt8500lcdfb.h b/include/linux/platform_data/video-vt8500lcdfb.h deleted file mode 100644 index 7f399c370fe..00000000000 --- a/include/linux/platform_data/video-vt8500lcdfb.h +++ /dev/null @@ -1,31 +0,0 @@ -/* - * VT8500/WM8505 Frame Buffer platform data definitions - * - * Copyright (C) 2010 Ed Spiridonov <edo.rus@gmail.com> - * - * This software is licensed under the terms of the GNU General Public - * License version 2, as published by the Free Software Foundation, and - * may be copied, distributed, and modified under those terms. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - */ - -#ifndef _VT8500FB_H -#define _VT8500FB_H - -#include <linux/fb.h> - -struct vt8500fb_platform_data { - struct fb_videomode mode; - u32 xres_virtual; - u32 yres_virtual; - u32 bpp; - unsigned long video_mem_phys; - void *video_mem_virt; - unsigned long video_mem_len; -}; - -#endif /* _VT8500FB_H */ diff --git a/include/linux/platform_data/video_s3c.h b/include/linux/platform_data/video_s3c.h new file mode 100644 index 00000000000..48883995f47 --- /dev/null +++ b/include/linux/platform_data/video_s3c.h @@ -0,0 +1,54 @@ +#ifndef __PLATFORM_DATA_VIDEO_S3C +#define __PLATFORM_DATA_VIDEO_S3C + +/* S3C_FB_MAX_WIN + * Set to the maximum number of windows that any of the supported hardware + * can use. Since the platform data uses this for an array size, having it + * set to the maximum of any version of the hardware can do is safe. + */ +#define S3C_FB_MAX_WIN (5) + +/** + * struct s3c_fb_pd_win - per window setup data + * @xres : The window X size. + * @yres : The window Y size. + * @virtual_x: The virtual X size. + * @virtual_y: The virtual Y size. + */ +struct s3c_fb_pd_win { + unsigned short default_bpp; + unsigned short max_bpp; + unsigned short xres; + unsigned short yres; + unsigned short virtual_x; + unsigned short virtual_y; +}; + +/** + * struct s3c_fb_platdata - S3C driver platform specific information + * @setup_gpio: Setup the external GPIO pins to the right state to transfer + * the data from the display system to the connected display + * device. + * @vidcon0: The base vidcon0 values to control the panel data format. + * @vidcon1: The base vidcon1 values to control the panel data output. + * @vtiming: Video timing when connected to a RGB type panel. + * @win: The setup data for each hardware window, or NULL for unused. + * @display_mode: The LCD output display mode. + * + * The platform data supplies the video driver with all the information + * it requires to work with the display(s) attached to the machine. It + * controls the initial mode, the number of display windows (0 is always + * the base framebuffer) that are initialised etc. + * + */ +struct s3c_fb_platdata { + void (*setup_gpio)(void); + + struct s3c_fb_pd_win *win[S3C_FB_MAX_WIN]; + struct fb_videomode *vtiming; + + u32 vidcon0; + u32 vidcon1; +}; + +#endif diff --git a/include/video/display_timing.h b/include/video/display_timing.h index 71e9a383a98..5d0259b08e0 100644 --- a/include/video/display_timing.h +++ b/include/video/display_timing.h @@ -12,19 +12,22 @@ #include <linux/bitops.h> #include <linux/types.h> -/* VESA display monitor timing parameters */ -#define VESA_DMT_HSYNC_LOW BIT(0) -#define VESA_DMT_HSYNC_HIGH BIT(1) -#define VESA_DMT_VSYNC_LOW BIT(2) -#define VESA_DMT_VSYNC_HIGH BIT(3) - -/* display specific flags */ -#define DISPLAY_FLAGS_DE_LOW BIT(0) /* data enable flag */ -#define DISPLAY_FLAGS_DE_HIGH BIT(1) -#define DISPLAY_FLAGS_PIXDATA_POSEDGE BIT(2) /* drive data on pos. edge */ -#define DISPLAY_FLAGS_PIXDATA_NEGEDGE BIT(3) /* drive data on neg. edge */ -#define DISPLAY_FLAGS_INTERLACED BIT(4) -#define DISPLAY_FLAGS_DOUBLESCAN BIT(5) +enum display_flags { + DISPLAY_FLAGS_HSYNC_LOW = BIT(0), + DISPLAY_FLAGS_HSYNC_HIGH = BIT(1), + DISPLAY_FLAGS_VSYNC_LOW = BIT(2), + DISPLAY_FLAGS_VSYNC_HIGH = BIT(3), + + /* data enable flag */ + DISPLAY_FLAGS_DE_LOW = BIT(4), + DISPLAY_FLAGS_DE_HIGH = BIT(5), + /* drive data on pos. edge */ + DISPLAY_FLAGS_PIXDATA_POSEDGE = BIT(6), + /* drive data on neg. edge */ + DISPLAY_FLAGS_PIXDATA_NEGEDGE = BIT(7), + DISPLAY_FLAGS_INTERLACED = BIT(8), + DISPLAY_FLAGS_DOUBLESCAN = BIT(9), +}; /* * A single signal can be specified via a range of minimal and maximal values @@ -36,12 +39,6 @@ struct timing_entry { u32 max; }; -enum timing_entry_index { - TE_MIN = 0, - TE_TYP = 1, - TE_MAX = 2, -}; - /* * Single "mode" entry. This describes one set of signal timings a display can * have in one setting. This struct can later be converted to struct videomode @@ -72,8 +69,7 @@ struct display_timing { struct timing_entry vback_porch; /* ver. back porch */ struct timing_entry vsync_len; /* ver. sync len */ - unsigned int dmt_flags; /* VESA DMT flags */ - unsigned int data_flags; /* video data flags */ + enum display_flags flags; /* display flags */ }; /* @@ -89,25 +85,6 @@ struct display_timings { struct display_timing **timings; }; -/* get value specified by index from struct timing_entry */ -static inline u32 display_timing_get_value(const struct timing_entry *te, - enum timing_entry_index index) -{ - switch (index) { - case TE_MIN: - return te->min; - break; - case TE_TYP: - return te->typ; - break; - case TE_MAX: - return te->max; - break; - default: - return te->typ; - } -} - /* get one entry from struct display_timings */ static inline struct display_timing *display_timings_get(const struct display_timings *disp, diff --git a/include/video/videomode.h b/include/video/videomode.h index a42156234dd..3f1049d870d 100644 --- a/include/video/videomode.h +++ b/include/video/videomode.h @@ -29,20 +29,30 @@ struct videomode { u32 vback_porch; u32 vsync_len; - unsigned int dmt_flags; /* VESA DMT flags */ - unsigned int data_flags; /* video data flags */ + enum display_flags flags; /* display flags */ }; /** * videomode_from_timing - convert display timing to videomode + * @dt: display_timing structure + * @vm: return value + * + * DESCRIPTION: + * This function converts a struct display_timing to a struct videomode. + */ +void videomode_from_timing(const struct display_timing *dt, + struct videomode *vm); + +/** + * videomode_from_timings - convert one display timings entry to videomode * @disp: structure with all possible timing entries * @vm: return value * @index: index into the list of display timings in devicetree * * DESCRIPTION: - * This function converts a struct display_timing to a struct videomode. + * This function converts one struct display_timing entry to a struct videomode. */ -int videomode_from_timing(const struct display_timings *disp, +int videomode_from_timings(const struct display_timings *disp, struct videomode *vm, unsigned int index); #endif |