Commit 8127b39e authored by Linus Torvalds's avatar Linus Torvalds

Merge tag 'fbdev-for-3.10' of git://gitorious.org/linux-omap-dss2/linux

Pull fbdev updates from Tomi Valkeinen:

 - use vm_iomap_memory() in various fb drivers to map the fb memory to
   userspace

 - Cleanups for the videomode and display_timing features

 - Updates to vt8500, wm8505 and auo-k190x fb drivers

* tag 'fbdev-for-3.10' of git://gitorious.org/linux-omap-dss2/linux: (36 commits)
  fbdev: fix check for fb_mmap's mmio availability
  fbdev: improve fb_mmap bounds checks
  fbdev/ps3fb: use vm_iomap_memory()
  fbdev/sgivwfb: use vm_iomap_memory()
  fbdev/vermillion: use vm_iomap_memory()
  fbdev/sa1100fb: use vm_iomap_memory()
  fbdev/fb-puv3: use vm_iomap_memory()
  fbdev/controlfb: use vm_iomap_memory()
  fbdev/omapfb: use vm_iomap_memory()
  video: vt8500: fix Kconfig for videomode
  video/s3c: move platform_data out of arch/arm
  video/exynos: remove unnecessary header inclusions
  drivers/video: fsl-diu-fb: add hardware cursor support
  drivers: video: use module_platform_driver_probe()
  ARM: OMAP: remove "config FB_OMAP_CONSISTENT_DMA_SIZE"
  video: wm8505fb: Convert to devm_ioremap_resource()
  AUO-K190x: Add resolutions for portrait displays
  AUO-K190x: add framebuffer rotation support
  AUO-K190x: add a 16bit truecolor mode
  AUO-K190x: make color handling more flexible
  ...
parents 96a3e8af 9bf9d47a
......@@ -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 */
};
};
};
......@@ -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>;
};
};
};
......@@ -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 {
&fb {
bits-per-pixel = <16>;
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 */
};
};
};
};
......@@ -98,12 +98,10 @@ uhci@d8007b00 {
interrupts = <43>;
};
fb@d800e400 {
fb: fb@d8050800 {
compatible = "via,vt8500-fb";
reg = <0xd800e400 0x400>;
interrupts = <12>;
display = <&display>;
default-mode = <&mode0>;
};
ge_rops@d8050400 {
......
......@@ -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 {
&fb {
bits-per-pixel = <32>;
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 = <32>; /* non-standard but required */
};
};
};
};
......@@ -128,11 +128,9 @@ uhci@d8007300 {
interrupts = <0>;
};
fb@d8050800 {
fb: fb@d8050800 {
compatible = "wm,wm8505-fb";
reg = <0xd8050800 0x200>;
display = <&display>;
default-mode = <&mode0>;
};
ge_rops@d8050400 {
......
......@@ -11,26 +11,24 @@
/ {
model = "Wondermedia WM8650-MID 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 {
&fb {
bits-per-pixel = <16>;
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 */
};
};
};
};
......@@ -128,11 +128,9 @@ uhci@d8007b00 {
interrupts = <43>;
};
fb@d8050800 {
fb: fb@d8050800 {
compatible = "wm,wm8505-fb";
reg = <0xd8050800 0x200>;
display = <&display>;
default-mode = <&mode0>;
};
ge_rops@d8050400 {
......
......@@ -15,33 +15,29 @@
/ {
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 {
backlight {
compatible = "pwm-backlight";
pwms = <&pwm 0 50000 1>; /* duty inverted */
brightness-levels = <0 40 60 80 100 130 190 255>;
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>;
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 */
};
};
};
backlight {
compatible = "pwm-backlight";
pwms = <&pwm 0 50000 1>; /* duty inverted */
brightness-levels = <0 40 60 80 100 130 190 255>;
default-brightness-level = <5>;
};
};
......@@ -135,11 +135,9 @@ clksdhc: sdhc {
};
};
fb@d8051700 {
fb: fb@d8051700 {
compatible = "wm,wm8505-fb";
reg = <0xd8051700 0x200>;
display = <&display>;
default-mode = <&mode0>;
};
ge_rops@d8050400 {
......
......@@ -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.
......
......@@ -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
......
......@@ -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
......
......@@ -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);
......
......@@ -31,27 +31,9 @@ config VIDEO_OUTPUT_CONTROL
This framework adds support for low-level control of the video
output switch.
config DISPLAY_TIMING
config VIDEOMODE_HELPERS
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 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,37 @@ 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 VIDEOMODE_HELPERS
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 VIDEOMODE_HELPERS
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"
......
......@@ -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
......@@ -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");
......@@ -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>");
......
......@@ -60,9 +60,12 @@
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++;
......
......@@ -101,9 +101,12 @@
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);
......
......@@ -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,7 +68,47 @@ 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,
/**
* 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;
......@@ -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,
......
......@@ -285,36 +285,26 @@ static int controlfb_pan_display(struct fb_var_screeninfo *var,
static int controlfb_mmap(struct fb_info *info,
struct vm_area_struct *vma)
{
unsigned long off, start;
unsigned long mmio_pgoff;
unsigned long start;
u32 len;
off = vma->vm_pgoff << PAGE_SHIFT;
/* frame buffer memory */
start = info->fix.smem_start;
len = PAGE_ALIGN((start & ~PAGE_MASK)+info->fix.smem_len);
if (off >= len) {
/* memory mapped io */
off -= len;
len = info->fix.smem_len;
mmio_pgoff = PAGE_ALIGN((start & ~PAGE_MASK) + len) >> PAGE_SHIFT;
if (vma->vm_pgoff >= mmio_pgoff) {
if (info->var.accel_flags)
return -EINVAL;
vma->vm_pgoff -= mmio_pgoff;
start = info->fix.mmio_start;
len = PAGE_ALIGN((start & ~PAGE_MASK)+info->fix.mmio_len);
len = info->fix.mmio_len;
vma->vm_page_prot = pgprot_noncached(vma->vm_page_prot);
} else {
/* framebuffer */
vma->vm_page_prot = pgprot_cached_wthru(vma->vm_page_prot);
}
start &= PAGE_MASK;
if ((vma->vm_end - vma->vm_start + off) > len)
return -EINVAL;
off += start;
vma->vm_pgoff = off >> PAGE_SHIFT;
if (io_remap_pfn_range(vma, vma->vm_start, off >> PAGE_SHIFT,
vma->vm_end - vma->vm_start, vma->vm_page_prot))
return -EAGAIN;
return 0;
return vm_iomap_memory(vma, start, len);
}
static int controlfb_blank(int blank_mode, struct fb_info *info)
......
......@@ -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"
......
......@@ -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"
......
......@@ -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)
......
......@@ -640,21 +640,9 @@ static int unifb_pan_display(struct fb_var_screeninfo *var,
int unifb_mmap(struct fb_info *info,
struct vm_area_struct *vma)
{
unsigned long size = vma->vm_end - vma->vm_start;
unsigned long offset = vma->vm_pgoff << PAGE_SHIFT;
unsigned long pos = info->fix.smem_start + offset;
if (offset + size > info->fix.smem_len)
return -EINVAL;
vma->vm_page_prot = pgprot_noncached(vma->vm_page_prot);
if (io_remap_pfn_range(vma, vma->vm_start, pos >> PAGE_SHIFT, size,
vma->vm_page_prot))
return -EAGAIN;
/* VM_IO | VM_DONTEXPAND | VM_DONTDUMP are set by remap_pfn_range() */
return 0;
return vm_iomap_memory(vma, info->fix.smem_start, info->fix.smem_len);
}
static struct fb_ops unifb_ops = {
......
......@@ -1398,6 +1398,11 @@ fb_mmap(struct file *file, struct vm_area_struct * vma)
len = info->fix.smem_len;
mmio_pgoff = PAGE_ALIGN((start & ~PAGE_MASK) + len) >> PAGE_SHIFT;
if (vma->vm_pgoff >= mmio_pgoff) {
if (info->var.accel_flags) {
mutex_unlock(&info->mm_lock);
return -EINVAL;
}
vma->vm_pgoff -= mmio_pgoff;
start = info->fix.mmio_start;
len = info->fix.mmio_len;
......
......@@ -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_VSYNC_HIGH)
if (vm->flags & DISPLAY_FLAGS_VSYNC_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)
......
......@@ -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);
......@@ -967,6 +969,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
......@@ -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)
......
......@@ -1016,7 +1016,9 @@ static int gbefb_mmap(struct fb_info *info,
/* check range */
if (vma->vm_pgoff > (~0UL >> PAGE_SHIFT))
return -EINVAL;
if (offset + size > gbe_mem_size)
if (size > gbe_mem_size)
return -EINVAL;
if (offset > gbe_mem_size - size)
return -EINVAL;
/* remap using the fastest write-through mode on architecture */
......
......@@ -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",
......
......@@ -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;
......
......@@ -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
......
......@@ -1101,41 +1101,25 @@ static int omapfb_mmap(struct fb_info *fbi, struct vm_area_struct *vma)
struct omapfb_info *ofbi = FB2OFB(fbi);
struct fb_fix_screeninfo *fix = &fbi->fix;
struct omapfb2_mem_region *rg;
unsigned long off;
unsigned long start;
u32 len;
int r = -EINVAL;
if (vma->vm_end - vma->vm_start == 0)
return 0;
if (vma->vm_pgoff > (~0UL >> PAGE_SHIFT))
return -EINVAL;
off = vma->vm_pgoff << PAGE_SHIFT;
int r;
rg = omapfb_get_mem_region(ofbi->region);
start = omapfb_get_region_paddr(ofbi);
len = fix->smem_len;
if (off >= len)
goto error;
if ((vma->vm_end - vma->vm_start + off) > len)
goto error;
off += start;
DBG("user mmap region start %lx, len %d, off %lx\n", start, len, off);
DBG("user mmap region start %lx, len %d, off %lx\n", start, len,
vma->vm_pgoff << PAGE_SHIFT);
vma->vm_pgoff = off >> PAGE_SHIFT;
/* VM_IO | VM_DONTEXPAND | VM_DONTDUMP are set by remap_pfn_range() */
vma->vm_page_prot = pgprot_writecombine(vma->vm_page_prot);
vma->vm_ops = &mmap_user_ops;
vma->vm_private_data = rg;
if (io_remap_pfn_range(vma, vma->vm_start, off >> PAGE_SHIFT,
vma->vm_end - vma->vm_start,
vma->vm_page_prot)) {
r = -EAGAIN;
r = vm_iomap_memory(vma, start, len);
if (r)
goto error;
}
/* vm_ops.open won't be called for mmap itself. */
atomic_inc(&rg->map_count);
......@@ -1144,7 +1128,7 @@ static int omapfb_mmap(struct fb_info *fbi, struct vm_area_struct *vma)
return 0;
error:
error:
omapfb_put_mem_region(ofbi->region);
return r;
......
......@@ -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");
......
......@@ -705,21 +705,15 @@ static int ps3fb_pan_display(struct fb_var_screeninfo *var,
static int ps3fb_mmap(struct fb_info *info, struct vm_area_struct *vma)
{
unsigned long size, offset;
int r;
size = vma->vm_end - vma->vm_start;
offset = vma->vm_pgoff << PAGE_SHIFT;
if (offset + size > info->fix.smem_len)
return -EINVAL;
offset += info->fix.smem_start;
if (remap_pfn_range(vma, vma->vm_start, offset >> PAGE_SHIFT,
size, vma->vm_page_prot))
return -EAGAIN;
r = vm_iomap_memory(vma, info->fix.smem_start, info->fix.smem_len);
dev_dbg(info->device, "ps3fb: mmap framebuffer P(%lx)->V(%lx)\n",
offset, vma->vm_start);
return 0;
info->fix.smem_start + vma->vm_pgoff << PAGE_SHIFT,
vma->vm_start);
return r;
}
/*
......
......@@ -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
......
......@@ -556,7 +556,7 @@ static int sa1100fb_mmap(struct fb_info *info,
struct vm_area_struct *vma)
{
struct sa1100fb_info *fbi = (struct sa1100fb_info *)info;
unsigned long start, len, off = vma->vm_pgoff << PAGE_SHIFT;
unsigned long off = vma->vm_pgoff << PAGE_SHIFT;
if (off < info->fix.smem_len) {
vma->vm_pgoff += 1; /* skip over the palette */
......@@ -564,19 +564,9 @@ static int sa1100fb_mmap(struct fb_info *info,
fbi->map_dma, fbi->map_size);
}
start = info->fix.mmio_start;
len = PAGE_ALIGN((start & ~PAGE_MASK) + info->fix.mmio_len);
if ((vma->vm_end - vma->vm_start + off) > len)
return -EINVAL;
off += start & PAGE_MASK;
vma->vm_pgoff = off >> PAGE_SHIFT;
vma->vm_flags |= VM_IO;
vma->vm_page_prot = pgprot_noncached(vma->vm_page_prot);
return io_remap_pfn_range(vma, vma->vm_start, off >> PAGE_SHIFT,
vma->vm_end - vma->vm_start,
vma->vm_page_prot);
return vm_iomap_memory(vma, info->fix.mmio_start, info->fix.mmio_len);
}
static struct fb_ops sa1100fb_ops = {
......
......@@ -705,23 +705,17 @@ static int sgivwfb_setcolreg(u_int regno, u_int red, u_int green,
static int sgivwfb_mmap(struct fb_info *info,
struct vm_area_struct *vma)
{
unsigned long size = vma->vm_end - vma->vm_start;
unsigned long offset = vma->vm_pgoff << PAGE_SHIFT;
int r;
if (vma->vm_pgoff > (~0UL >> PAGE_SHIFT))
return -EINVAL;
if (offset + size > sgivwfb_mem_size)
return -EINVAL;
offset += sgivwfb_mem_phys;
pgprot_val(vma->vm_page_prot) =
pgprot_val(vma->vm_page_prot) | _PAGE_PCD;
vma->vm_flags |= VM_IO;
if (remap_pfn_range(vma, vma->vm_start, offset >> PAGE_SHIFT,
size, vma->vm_page_prot))
return -EAGAIN;
r = vm_iomap_memory(vma, sgivwfb_mem_phys, sgivwfb_mem_size);
printk(KERN_DEBUG "sgivwfb: mmap framebuffer P(%lx)->V(%lx)\n",
offset, vma->vm_start);
return 0;
return r;
}
int __init sgivwfb_setup(char *options)
......
......@@ -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");
......
......@@ -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");
......
......@@ -782,7 +782,11 @@ static int ufx_ops_mmap(struct fb_info *info, struct vm_area_struct *vma)
unsigned long offset = vma->vm_pgoff << PAGE_SHIFT;
unsigned long page, pos;
if (offset + size > info->fix.smem_len)
if (vma->vm_pgoff > (~0UL >> PAGE_SHIFT))
return -EINVAL;
if (size > info->fix.smem_len)
return -EINVAL;
if (offset > info->fix.smem_len - size)
return -EINVAL;
pos = (unsigned long)info->fix.smem_start + offset;
......
......@@ -324,7 +324,11 @@ static int dlfb_ops_mmap(struct fb_info *info, struct vm_area_struct *vma)
unsigned long offset = vma->vm_pgoff << PAGE_SHIFT;
unsigned long page, pos;
if (offset + size > info->fix.smem_len)
if (vma->vm_pgoff > (~0UL >> PAGE_SHIFT))
return -EINVAL;
if (size > info->fix.smem_len)
return -EINVAL;
if (offset > info->fix.smem_len - size)
return -EINVAL;
pos = (unsigned long)info->fix.smem_start + offset;
......
......@@ -1003,24 +1003,18 @@ static int vmlfb_setcolreg(u_int regno, u_int red, u_int green, u_int blue,
static int vmlfb_mmap(struct fb_info *info, struct vm_area_struct *vma)
{
struct vml_info *vinfo = container_of(info, struct vml_info, info);
unsigned long size = vma->vm_end - vma->vm_start;
unsigned long offset = vma->vm_pgoff << PAGE_SHIFT;
int ret;
if (vma->vm_pgoff > (~0UL >> PAGE_SHIFT))
return -EINVAL;
if (offset + size > vinfo->vram_contig_size)
return -EINVAL;
ret = vmlfb_vram_offset(vinfo, offset);
if (ret)
return -EINVAL;
offset += vinfo->vram_start;
pgprot_val(vma->vm_page_prot) |= _PAGE_PCD;
pgprot_val(vma->vm_page_prot) &= ~_PAGE_PWT;
if (remap_pfn_range(vma, vma->vm_start, offset >> PAGE_SHIFT,
size, vma->vm_page_prot))
return -EAGAIN;
return 0;
return vm_iomap_memory(vma, vinfo->vram_start,
vinfo->vram_contig_size);
}
static int vmlfb_sync(struct fb_info *info)
......
......@@ -420,9 +420,12 @@ static int vfb_mmap(struct fb_info *info,
unsigned long offset = vma->vm_pgoff << PAGE_SHIFT;
unsigned long page, pos;
if (offset + size > info->fix.smem_len) {
if (vma->vm_pgoff > (~0UL >> PAGE_SHIFT))
return -EINVAL;
if (size > info->fix.smem_len)
return -EINVAL;
if (offset > info->fix.smem_len - size)
return -EINVAL;
}
pos = (unsigned long)info->fix.smem_start + offset;
......
......@@ -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);
......@@ -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);
......
......@@ -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"
......@@ -264,25 +264,21 @@ static int wm8505fb_probe(struct platform_device *pdev)
{
struct wm8505fb_info *fbi;
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;
}
......
#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
/*
* 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 */
#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
......@@ -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;
};
......
......@@ -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,
......
......@@ -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
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment