fbdev: Merge fbdev topic branches
authorTomi Valkeinen <tomi.valkeinen@ti.com>
Mon, 15 Apr 2013 08:59:20 +0000 (11:59 +0300)
committerTomi Valkeinen <tomi.valkeinen@ti.com>
Mon, 15 Apr 2013 09:00:38 +0000 (12:00 +0300)
Merge branches '3.10/auo-k190x', '3.10/misc', '3.10/videomode' and '3.10/vt8500' into for-next

29 files changed:
Documentation/devicetree/bindings/video/via,vt8500-fb.txt
Documentation/devicetree/bindings/video/wm,wm8505-fb.txt
arch/arm/boot/dts/vt8500-bv07.dts
arch/arm/boot/dts/vt8500.dtsi
arch/arm/boot/dts/wm8505-ref.dts
arch/arm/boot/dts/wm8505.dtsi
arch/arm/boot/dts/wm8650-mid.dts
arch/arm/boot/dts/wm8650.dtsi
arch/arm/boot/dts/wm8850-w70v2.dts
arch/arm/boot/dts/wm8850.dtsi
drivers/gpu/drm/drm_modes.c
drivers/gpu/drm/tilcdc/Kconfig
drivers/gpu/drm/tilcdc/tilcdc_panel.c
drivers/video/Kconfig
drivers/video/Makefile
drivers/video/auo_k1900fb.c
drivers/video/auo_k1901fb.c
drivers/video/auo_k190x.c
drivers/video/fbmon.c
drivers/video/of_display_timing.c
drivers/video/of_videomode.c
drivers/video/videomode.c
drivers/video/vt8500lcdfb.c
drivers/video/wm8505fb.c
drivers/video/wmt_ge_rops.h
include/linux/platform_data/video-vt8500lcdfb.h [deleted file]
include/video/auo_k190xfb.h
include/video/display_timing.h
include/video/videomode.h

index c870b64..2871e21 100644 (file)
@@ -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 */
                        };
                };
        };
+
index 3d325e1..0bcadb2 100644 (file)
@@ -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>;
+                       };
+               };
        };
index 567cf4e..877b33a 100644 (file)
 
 / {
        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>;
                };
        };
 };
index cf31ced..68c8dc6 100644 (file)
                        interrupts = <43>;
                };
 
-               fb@d800e400 {
+               fb: fb@d8050800 {
                        compatible = "via,vt8500-fb";
                        reg = <0xd800e400 0x400>;
                        interrupts = <12>;
-                       display = <&display>;
-                       default-mode = <&mode0>;
                };
 
                ge_rops@d8050400 {
index fd4e248..edd2cec 100644 (file)
 
 / {
        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>;
                };
        };
 };
index e74a1c0..bcf668d 100644 (file)
                        interrupts = <0>;
                };
 
-               fb@d8050800 {
+               fb: fb@d8050800 {
                        compatible = "wm,wm8505-fb";
                        reg = <0xd8050800 0x200>;
-                       display = <&display>;
-                       default-mode = <&mode0>;
                };
 
                ge_rops@d8050400 {
index cefd938..61671a0 100644 (file)
 
 / {
        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>;
                };
        };
 };
+
index db3c0a1..9313407 100644 (file)
                        interrupts = <43>;
                };
 
-               fb@d8050800 {
+               fb: fb@d8050800 {
                        compatible = "wm,wm8505-fb";
                        reg = <0xd8050800 0x200>;
-                       display = <&display>;
-                       default-mode = <&mode0>;
                };
 
                ge_rops@d8050400 {
index fcc660c..32d2253 100644 (file)
 / {
        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 */
                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>;
+               };
+       };
+};
index e8cbfdc..7149cd1 100644 (file)
                        };
                };
 
-               fb@d8051700 {
+               fb: fb@d8051700 {
                        compatible = "wm,wm8505-fb";
                        reg = <0xd8051700 0x200>;
-                       display = <&display>;
-                       default-mode = <&mode0>;
                };
 
                ge_rops@d8050400 {
index 04fa6f1..f83f071 100644 (file)
@@ -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
index d24d040..e461e99 100644 (file)
@@ -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
index 580b74e..90ee497 100644 (file)
@@ -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);
index 4c1546f..714d32a 100644 (file)
@@ -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"
 
index 9df3873..e414378 100644 (file)
@@ -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
index 1a9ac6e..f5b668e 100644 (file)
 
 static void auok1900_init(struct auok190xfb_par *par)
 {
+       struct device *dev = par->info->device;
        struct auok190x_board *board = par->board;
        u16 init_param = 0;
 
+       pm_runtime_get_sync(dev);
+
        init_param |= AUOK1900_INIT_TEMP_AVERAGE;
        init_param |= AUOK1900_INIT_ROTATE(par->rotation);
        init_param |= AUOK190X_INIT_INVERSE_WHITE;
@@ -74,6 +77,9 @@ static void auok1900_init(struct auok190xfb_par *par)
 
        /* let the controller finish */
        board->wait_for_rdy(par);
+
+       pm_runtime_mark_last_busy(dev);
+       pm_runtime_put_autosuspend(dev);
 }
 
 static void auok1900_update_region(struct auok190xfb_par *par, int mode,
@@ -82,6 +88,7 @@ static void auok1900_update_region(struct auok190xfb_par *par, int mode,
        struct device *dev = par->info->device;
        unsigned char *buf = (unsigned char *)par->info->screen_base;
        int xres = par->info->var.xres;
+       int line_length = par->info->fix.line_length;
        u16 args[4];
 
        pm_runtime_get_sync(dev);
@@ -100,9 +107,9 @@ static void auok1900_update_region(struct auok190xfb_par *par, int mode,
        args[1] = y1 + 1;
        args[2] = xres;
        args[3] = y2 - y1;
-       buf += y1 * xres;
+       buf += y1 * line_length;
        auok190x_send_cmdargs_pixels(par, AUOK1900_CMD_PARTIALDISP, 4, args,
-                                    ((y2 - y1) * xres)/2, (u16 *) buf);
+                                    ((y2 - y1) * line_length)/2, (u16 *) buf);
        auok190x_send_command(par, AUOK190X_CMD_DATA_STOP);
 
        par->update_cnt++;
index d1db165..12b9adc 100644 (file)
 
 static void auok1901_init(struct auok190xfb_par *par)
 {
+       struct device *dev = par->info->device;
        struct auok190x_board *board = par->board;
        u16 init_param = 0;
 
+       pm_runtime_get_sync(dev);
+
        init_param |= AUOK190X_INIT_INVERSE_WHITE;
        init_param |= AUOK190X_INIT_FORMAT0;
        init_param |= AUOK1901_INIT_RESOLUTION(par->resolution);
@@ -113,6 +116,9 @@ static void auok1901_init(struct auok190xfb_par *par)
 
        /* let the controller finish */
        board->wait_for_rdy(par);
+
+       pm_runtime_mark_last_busy(dev);
+       pm_runtime_put_autosuspend(dev);
 }
 
 static void auok1901_update_region(struct auok190xfb_par *par, int mode,
@@ -121,6 +127,7 @@ static void auok1901_update_region(struct auok190xfb_par *par, int mode,
        struct device *dev = par->info->device;
        unsigned char *buf = (unsigned char *)par->info->screen_base;
        int xres = par->info->var.xres;
+       int line_length = par->info->fix.line_length;
        u16 args[5];
 
        pm_runtime_get_sync(dev);
@@ -139,9 +146,9 @@ static void auok1901_update_region(struct auok190xfb_par *par, int mode,
        args[1] = y1 + 1;
        args[2] = xres;
        args[3] = y2 - y1;
-       buf += y1 * xres;
+       buf += y1 * line_length;
        auok190x_send_cmdargs_pixels_nowait(par, AUOK1901_CMD_DMA_START, 4,
-                                           args, ((y2 - y1) * xres)/2,
+                                           args, ((y2 - y1) * line_length)/2,
                                            (u16 *) buf);
        auok190x_send_command_nowait(par, AUOK190X_CMD_DATA_STOP);
 
index 53846cb..b1f19b2 100644 (file)
@@ -40,6 +40,14 @@ static struct panel_info panel_table[] = {
                .w = 1024,
                .h = 768,
        },
+       [AUOK190X_RESOLUTION_600_800] = {
+               .w = 600,
+               .h = 800,
+       },
+       [AUOK190X_RESOLUTION_768_1024] = {
+               .w = 768,
+               .h = 1024,
+       },
 };
 
 /*
@@ -60,8 +68,48 @@ static void auok190x_issue_cmd(struct auok190xfb_par *par, u16 data)
        par->board->set_ctl(par, AUOK190X_I80_DC, 1);
 }
 
-static int auok190x_issue_pixels(struct auok190xfb_par *par, int size,
-                                u16 *data)
+/**
+ * Conversion of 16bit color to 4bit grayscale
+ * does roughly (0.3 * R + 0.6 G + 0.1 B) / 2
+ */
+static inline int rgb565_to_gray4(u16 data, struct fb_var_screeninfo *var)
+{
+       return ((((data & 0xF800) >> var->red.offset) * 77 +
+                ((data & 0x07E0) >> (var->green.offset + 1)) * 151 +
+                ((data & 0x1F) >> var->blue.offset) * 28) >> 8 >> 1);
+}
+
+static int auok190x_issue_pixels_rgb565(struct auok190xfb_par *par, int size,
+                                       u16 *data)
+{
+       struct fb_var_screeninfo *var = &par->info->var;
+       struct device *dev = par->info->device;
+       int i;
+       u16 tmp;
+
+       if (size & 7) {
+               dev_err(dev, "issue_pixels: size %d must be a multiple of 8\n",
+                       size);
+               return -EINVAL;
+       }
+
+       for (i = 0; i < (size >> 2); i++) {
+               par->board->set_ctl(par, AUOK190X_I80_WR, 0);
+
+               tmp  = (rgb565_to_gray4(data[4*i], var) & 0x000F);
+               tmp |= (rgb565_to_gray4(data[4*i+1], var) << 4) & 0x00F0;
+               tmp |= (rgb565_to_gray4(data[4*i+2], var) << 8) & 0x0F00;
+               tmp |= (rgb565_to_gray4(data[4*i+3], var) << 12) & 0xF000;
+
+               par->board->set_hdb(par, tmp);
+               par->board->set_ctl(par, AUOK190X_I80_WR, 1);
+       }
+
+       return 0;
+}
+
+static int auok190x_issue_pixels_gray8(struct auok190xfb_par *par, int size,
+                                      u16 *data)
 {
        struct device *dev = par->info->device;
        int i;
@@ -91,6 +139,23 @@ static int auok190x_issue_pixels(struct auok190xfb_par *par, int size,
        return 0;
 }
 
+static int auok190x_issue_pixels(struct auok190xfb_par *par, int size,
+                                u16 *data)
+{
+       struct fb_info *info = par->info;
+       struct device *dev = par->info->device;
+
+       if (info->var.bits_per_pixel == 8 && info->var.grayscale)
+               auok190x_issue_pixels_gray8(par, size, data);
+       else if (info->var.bits_per_pixel == 16)
+               auok190x_issue_pixels_rgb565(par, size, data);
+       else
+               dev_err(dev, "unsupported color mode (bits: %d, gray: %d)\n",
+                       info->var.bits_per_pixel, info->var.grayscale);
+
+       return 0;
+}
+
 static u16 auok190x_read_data(struct auok190xfb_par *par)
 {
        u16 data;
@@ -224,8 +289,8 @@ static void auok190xfb_dpy_deferred_io(struct fb_info *info,
 {
        struct fb_deferred_io *fbdefio = info->fbdefio;
        struct auok190xfb_par *par = info->par;
+       u16 line_length = info->fix.line_length;
        u16 yres = info->var.yres;
-       u16 xres = info->var.xres;
        u16 y1 = 0, h = 0;
        int prev_index = -1;
        struct page *cur;
@@ -254,7 +319,7 @@ static void auok190xfb_dpy_deferred_io(struct fb_info *info,
        }
 
        /* height increment is fixed per page */
-       h_inc = DIV_ROUND_UP(PAGE_SIZE , xres);
+       h_inc = DIV_ROUND_UP(PAGE_SIZE , line_length);
 
        /* calculate number of pages from pixel height */
        threshold = par->consecutive_threshold / h_inc;
@@ -265,7 +330,7 @@ static void auok190xfb_dpy_deferred_io(struct fb_info *info,
        list_for_each_entry(cur, &fbdefio->pagelist, lru) {
                if (prev_index < 0) {
                        /* just starting so assign first page */
-                       y1 = (cur->index << PAGE_SHIFT) / xres;
+                       y1 = (cur->index << PAGE_SHIFT) / line_length;
                        h = h_inc;
                } else if ((cur->index - prev_index) <= threshold) {
                        /* page is within our threshold for single updates */
@@ -275,7 +340,7 @@ static void auok190xfb_dpy_deferred_io(struct fb_info *info,
                        par->update_partial(par, y1, y1 + h);
 
                        /* start over with our non consecutive page */
-                       y1 = (cur->index << PAGE_SHIFT) / xres;
+                       y1 = (cur->index << PAGE_SHIFT) / line_length;
                        h = h_inc;
                }
                prev_index = cur->index;
@@ -376,27 +441,127 @@ static void auok190xfb_imageblit(struct fb_info *info,
 static int auok190xfb_check_var(struct fb_var_screeninfo *var,
                                   struct fb_info *info)
 {
-       if (info->var.xres != var->xres || info->var.yres != var->yres ||
-           info->var.xres_virtual != var->xres_virtual ||
-           info->var.yres_virtual != var->yres_virtual) {
-               pr_info("%s: Resolution not supported: X%u x Y%u\n",
-                        __func__, var->xres, var->yres);
+       struct device *dev = info->device;
+       struct auok190xfb_par *par = info->par;
+       struct panel_info *panel = &panel_table[par->resolution];
+       int size;
+
+       /*
+        * Color depth
+        */
+
+       if (var->bits_per_pixel == 8 && var->grayscale == 1) {
+               /*
+                * For 8-bit grayscale, R, G, and B offset are equal.
+                */
+               var->red.length = 8;
+               var->red.offset = 0;
+               var->red.msb_right = 0;
+
+               var->green.length = 8;
+               var->green.offset = 0;
+               var->green.msb_right = 0;
+
+               var->blue.length = 8;
+               var->blue.offset = 0;
+               var->blue.msb_right = 0;
+
+               var->transp.length = 0;
+               var->transp.offset = 0;
+               var->transp.msb_right = 0;
+       } else if (var->bits_per_pixel == 16) {
+               var->red.length = 5;
+               var->red.offset = 11;
+               var->red.msb_right = 0;
+
+               var->green.length = 6;
+               var->green.offset = 5;
+               var->green.msb_right = 0;
+
+               var->blue.length = 5;
+               var->blue.offset = 0;
+               var->blue.msb_right = 0;
+
+               var->transp.length = 0;
+               var->transp.offset = 0;
+               var->transp.msb_right = 0;
+       } else {
+               dev_warn(dev, "unsupported color mode (bits: %d, grayscale: %d)\n",
+                       info->var.bits_per_pixel, info->var.grayscale);
                return -EINVAL;
        }
 
+       /*
+        * Dimensions
+        */
+
+       switch (var->rotate) {
+       case FB_ROTATE_UR:
+       case FB_ROTATE_UD:
+               var->xres = panel->w;
+               var->yres = panel->h;
+               break;
+       case FB_ROTATE_CW:
+       case FB_ROTATE_CCW:
+               var->xres = panel->h;
+               var->yres = panel->w;
+               break;
+       default:
+               dev_dbg(dev, "Invalid rotation request\n");
+               return -EINVAL;
+       }
+
+       var->xres_virtual = var->xres;
+       var->yres_virtual = var->yres;
+
        /*
         *  Memory limit
         */
 
-       if ((info->fix.line_length * var->yres_virtual) > info->fix.smem_len) {
-               pr_info("%s: Memory Limit requested yres_virtual = %u\n",
-                        __func__, var->yres_virtual);
+       size = var->xres_virtual * var->yres_virtual * var->bits_per_pixel / 8;
+       if (size > info->fix.smem_len) {
+               dev_err(dev, "Memory limit exceeded, requested %dK\n",
+                       size >> 10);
                return -ENOMEM;
        }
 
        return 0;
 }
 
+static int auok190xfb_set_fix(struct fb_info *info)
+{
+       struct fb_fix_screeninfo *fix = &info->fix;
+       struct fb_var_screeninfo *var = &info->var;
+
+       fix->line_length = var->xres_virtual * var->bits_per_pixel / 8;
+
+       fix->type = FB_TYPE_PACKED_PIXELS;
+       fix->accel = FB_ACCEL_NONE;
+       fix->visual = (var->grayscale) ? FB_VISUAL_STATIC_PSEUDOCOLOR
+                                      : FB_VISUAL_TRUECOLOR;
+       fix->xpanstep = 0;
+       fix->ypanstep = 0;
+       fix->ywrapstep = 0;
+
+       return 0;
+}
+
+static int auok190xfb_set_par(struct fb_info *info)
+{
+       struct auok190xfb_par *par = info->par;
+
+       par->rotation = info->var.rotate;
+       auok190xfb_set_fix(info);
+
+       /* reinit the controller to honor the rotation */
+       par->init(par);
+
+       /* wait for init to complete */
+       par->board->wait_for_rdy(par);
+
+       return 0;
+}
+
 static struct fb_ops auok190xfb_ops = {
        .owner          = THIS_MODULE,
        .fb_read        = fb_sys_read,
@@ -405,6 +570,7 @@ static struct fb_ops auok190xfb_ops = {
        .fb_copyarea    = auok190xfb_copyarea,
        .fb_imageblit   = auok190xfb_imageblit,
        .fb_check_var   = auok190xfb_check_var,
+       .fb_set_par     = auok190xfb_set_par,
 };
 
 /*
@@ -588,10 +754,16 @@ static int auok190x_power(struct auok190xfb_par *par, bool on)
 
 static void auok190x_recover(struct auok190xfb_par *par)
 {
+       struct device *dev = par->info->device;
+
        auok190x_power(par, 0);
        msleep(100);
        auok190x_power(par, 1);
 
+       /* after powercycling the device, it's always active */
+       pm_runtime_set_active(dev);
+       par->standby = 0;
+
        par->init(par);
 
        /* wait for init to complete */
@@ -875,42 +1047,17 @@ int auok190x_common_probe(struct platform_device *pdev,
        /* initialise fix, var, resolution and rotation */
 
        strlcpy(info->fix.id, init->id, 16);
-       info->fix.type = FB_TYPE_PACKED_PIXELS;
-       info->fix.visual = FB_VISUAL_STATIC_PSEUDOCOLOR;
-       info->fix.xpanstep = 0;
-       info->fix.ypanstep = 0;
-       info->fix.ywrapstep = 0;
-       info->fix.accel = FB_ACCEL_NONE;
-
        info->var.bits_per_pixel = 8;
        info->var.grayscale = 1;
-       info->var.red.length = 8;
-       info->var.green.length = 8;
-       info->var.blue.length = 8;
 
        panel = &panel_table[board->resolution];
 
-       /* if 90 degree rotation, switch width and height */
-       if (board->rotation & 1) {
-               info->var.xres = panel->h;
-               info->var.yres = panel->w;
-               info->var.xres_virtual = panel->h;
-               info->var.yres_virtual = panel->w;
-               info->fix.line_length = panel->h;
-       } else {
-               info->var.xres = panel->w;
-               info->var.yres = panel->h;
-               info->var.xres_virtual = panel->w;
-               info->var.yres_virtual = panel->h;
-               info->fix.line_length = panel->w;
-       }
-
        par->resolution = board->resolution;
-       par->rotation = board->rotation;
+       par->rotation = 0;
 
        /* videomemory handling */
 
-       videomemorysize = roundup((panel->w * panel->h), PAGE_SIZE);
+       videomemorysize = roundup((panel->w * panel->h) * 2, PAGE_SIZE);
        videomemory = vmalloc(videomemorysize);
        if (!videomemory) {
                ret = -ENOMEM;
@@ -924,6 +1071,12 @@ int auok190x_common_probe(struct platform_device *pdev,
        info->flags = FBINFO_FLAG_DEFAULT | FBINFO_VIRTFB;
        info->fbops = &auok190xfb_ops;
 
+       ret = auok190xfb_check_var(&info->var, info);
+       if (ret)
+               goto err_defio;
+
+       auok190xfb_set_fix(info);
+
        /* deferred io init */
 
        info->fbdefio = devm_kzalloc(info->device,
index 94ad0f7..e5cc2fd 100644 (file)
@@ -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)
index 13ecd98..56009bc 100644 (file)
@@ -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",
index 5b8066c..111c2d1 100644 (file)
@@ -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;
 
index 21c47a2..df375c9 100644 (file)
 #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);
index aa2579c..9547e18 100644 (file)
  * 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);
index 4dd0580..01f9ace 100644 (file)
  * 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;
 }
 
index 8738075..f73ec63 100644 (file)
@@ -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 (file)
index 7f399c3..0000000
+++ /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 */
index 609efe8..ac329ee 100644 (file)
@@ -22,6 +22,8 @@
  */
 #define AUOK190X_RESOLUTION_800_600            0
 #define AUOK190X_RESOLUTION_1024_768           1
+#define AUOK190X_RESOLUTION_600_800            4
+#define AUOK190X_RESOLUTION_768_1024           5
 
 /*
  * struct used by auok190x. board specific stuff comes from *board
@@ -98,7 +100,6 @@ struct auok190x_board {
        int gpio_nbusy;
 
        int resolution;
-       int rotation;
        int quirks;
        int fps;
 };
index 71e9a38..5d0259b 100644 (file)
 #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,
index a421562..3f1049d 100644 (file)
@@ -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